π

git: post-commit hook for determining large number of deleted lines in Org-mode

Show Sidebar

Maybe you have faced the very same issue: when large Org mode hierarchies are folded, it might happen that you overwrite or delete large parts of your Org mode file without noticing.

This is not a big deal if you happen to have your Org mode files within a git repository. All changes to my Org mode files even get committed automatically using gitwatch. Everything that happened to your Org mode files can be revoked. However, you have to recognize the deleted lines in order to be able to restore them.

And this is where this small trick can help you: using the post-commit hook below, you get a warning on your daily agenda when you check in a commit that deleted more than a given number of lines.

Implementation

In order to make it work, you have to adopt the script below. Please change the content of OUTFILE to a file which is part of your org-agenda-files. Any warning message generated by the script gets appended to it. With a recurring time-stamp (of the commit), you can not miss the message: it is placed on your daily agenda.

You might also want to adopt the value of THRESHOLD. Its value represents the number of lines that might get deleted within a single file without any warning.

#!/bin/sh
#
# An example hook script that is called after a successful
# commit is made.
#
# To enable this hook, rename this file to "post-commit".

## current/last commit:
CURRENT_HASH=`git rev-parse HEAD`

## the commit before:
PREVIOUS_HASH=`git rev-parse HEAD^1`

## the file where the message(s) are being written to:
OUTFILE="${HOME}/org/errors_orgmode_commits.org"

## number of lines that are OK to be deleted in one single file:
THRESHOLD=250


MESSAGE="** commit ${CURRENT_HASH} deleted more than ${THRESHOLD} lines in a file!"

DETAILS="#+BEGIN_SRC sh :results output
cd ${HOME}/org
echo \"commit ${CURRENT_HASH}\"
git diff --stat \"${PREVIOUS_HASH}\" \"${CURRENT_HASH}\"
#+END_SRC"


## manual test with:
##  git diff --stat `git rev-parse HEAD^1` `git rev-parse HEAD`

git diff --numstat "${PREVIOUS_HASH}" "${CURRENT_HASH}" | \
	cut -f 2 | \
	while read line
	do test "$line" -gt "${THRESHOLD}" && \
	   echo "${MESSAGE}\n<`date '+%Y-%m-%d %H:%M'` +1d>\n\n${DETAILS}\n" >> \
		"${OUTFILE}"; \
	done

#end	  

So when you recognize a warning on your agenda, click on it and optionally do a C-c C-c on the babel snippet which is below the heading. It gives your details on the commit.

After you have resolved the issue, just delete the heading of the resolved error in the error Org mode file manually.

Implementation Using appendorgheading

Using the method described in this article, the post-commit hook looks like this:

 #!/bin/sh
 #
 # An example hook script that is called after a successful
 # commit is made.
 #
 # To enable this hook, rename this file to "post-commit".

 ## current/last commit:
 CURRENT_HASH=$(git rev-parse HEAD)

 ## the commit before:
 PREVIOUS_HASH=$(git rev-parse HEAD^1)

 ## number of lines that are OK to be deleted in one single file:
 THRESHOLD=200

 TMPFILE="$(mktemp)"

 TITLE="commit ${CURRENT_HASH} deleted more than ${THRESHOLD} lines in a file!"
 echo "#+BEGIN_SRC sh
 gitk ${CURRENT_HASH}
 #+END_SRC

 #+BEGIN_EXAMPLE
 `cd ${HOME}/org ; git diff --stat \"${PREVIOUS_HASH}\" \"${CURRENT_HASH}\"`
 #+END_EXAMPLE" > "${TMPFILE}"

 ## manual test with:
 ##  git diff --stat `git rev-parse HEAD^1` `git rev-parse HEAD`

 git diff --numstat "${PREVIOUS_HASH}" "${CURRENT_HASH}" | \
         cut -f 2 | \
         while read line
         do test "$line" -gt "${THRESHOLD}" && \
             /usr/local/bin/appendorgheading --title "${TITLE}" --filecontent "${TMPFILE}"
         done

 rm "${TMPFILE}"
 #end	  

Related articles that link to this one:

Comment via email (persistent) or via Disqus (ephemeral) comments below: