Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shorthand to view diff of previous version of file

Tags:

git

diff

I can easily find out what changed for a file since the last commit with git diff HEAD^ -- <filename> but is there an equivalent shorthand to view a diff for a particular file since it was last committed, regardless of how many commits have happened since? Or to go back N commits of that particular file?

Context: I found an error in a file and I want to track down when it snuck in. It's easy enough to get a log report for a particular file with git log -<n> <filename> to show only the commits that included changes to that file. So clearly I can just copy and paste the SHAs from that log report, but what I really want is to be able to do something like git diff ^ -- <filename> or git diff ~2 -- <filename>.

like image 797
Clayton Avatar asked Jan 22 '13 21:01

Clayton


People also ask

Which command is used to explore the previous versions of a project?

git checkout recovers old versions of files.

How do I see previous commits?

To pull up a list of your commits and their associated hashes, you can run the git log command. To checkout a previous commit, you will use the Git checkout command followed by the commit hash you retrieved from your Git log.

What is the command to check diff in git?

The diff can be done with git diff (followed by the filename or nothing if you want to see the diff of all modified files). But if you already did something like git add * , you have to undo with git restore --staged .


2 Answers

$ git log -p <filename>

will show you the log message plus a diff for each commit that touched the named file.

To show only differences to the previous version, ask for just one step in log history:

$ git log -1 -p <filename>
like image 150
Matt McHenry Avatar answered Sep 23 '22 08:09

Matt McHenry


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.

like image 27
Alex W Avatar answered Sep 22 '22 08:09

Alex W