You can make use of git log
formatting to get the hashes of previous commits to a file. For example,
git log --pretty=format:'%h' -1 --skip=1 <filename>
will get you the 2nd to last commit to touch a specific file. In fact, if you don't specify a filename, this will get you the 2nd to last commit on the entire repository. To get older hashes, you might set up a git alias that calls a shell function, like this:
[alias]
prior-hash = "!ph() { git log --pretty=format:'%h' -1 --skip=$1 $2; }; ph"
To use it, you'd type something like git prior-hash n <filename>
, where n is the (n+1)th most recent version of the file. So 1 would be the 2nd to last commit to the file, 2 would be the 3rd to last, etc, and 0 would be the most recent commit to touch that file. And again, the filename is optional, if you want to examine the repo as a whole.
I'm sure you could figure out how to build a diff command from there:
[alias]
prior-hash = "!ph() { git log --pretty=format:'%h' -1 --skip=$1 $2; }; ph"
diff-prev-easy = "!dp() { git diff $(git prior-hash $1 $2).. $2; }; dp"
which would be used similar to the prior-hash alias, git diff-prev-easy n <filename>
. This would compare the (n+1)th last revision to the most recent revision of the file. If you wanted to instead compare the (n+1)th last revision to the nth last revision, it's a simple change:
[alias]
prior-hash = "!ph() { git log --pretty=format:'%h' -1 --skip=$1 $2; }; ph"
diff-prev = "!dp() { git diff $(git prior-hash $1 $2)..$(git prior-hash $(($1 - 1)) $2) $2; }; dp"
which, again, is used the same way: git diff-prev n <filename>
One potential problem to watch out for, though, is that git log
lists commits in chronological order, which may not be what you want. Consider this history:
1 - 2 - - - 4 - 5 master
\ /
3 - - develop
Our git diff-prev 1
command would produce the diff between commit 4 and 5, as expected. But git diff-prev 2
would show the diff between commit 3 and 4, which is likely undesirable.