13

I would like to run git difftool HEAD~3.. path/to/file and have git open the difftool for each of those three commits so that I can see a side-by-side view of each commit.

How would I go about getting git-difftool to do that?

shytikov
  • 9,155
  • 8
  • 56
  • 103
Dale Forester
  • 18,145
  • 10
  • 27
  • 27

5 Answers5

11

Or you could just run git log -p - it does pretty much the same thing that you want

Antony Hatchkins
  • 31,947
  • 10
  • 111
  • 111
  • Not exactly, I believe. As far as I got, the side-by-side diffs are desirable result. – shytikov Aug 01 '12 at 13:00
  • This is what I usually do to get similar result. My [first](http://stackoverflow.com/a/11726664/237105) answer was devoted to side-by-side comparison exactly. – Antony Hatchkins Aug 01 '12 at 13:21
7

This would accomplish what you describe:

git difftool HEAD~3 HEAD~2 path/to/file
git difftool HEAD~2 HEAD~1 path/to/file
git difftool HEAD~1 HEAD path/to/file

Want to automate this process? Is it always three commits? Do you want a three-way merge?

Update:

If the answers are yes-yes-no, the solution will be:

for i in {3..1}; do
  git difftool HEAD~$i HEAD~$((i-1)) path/to/file
done

Update:

If the answers are yes-no-yes, it is essentially what @ruffin asks here. See my answer there.

Community
  • 1
  • 1
Antony Hatchkins
  • 31,947
  • 10
  • 111
  • 111
1

UPDATE:

Matthieu Moy suggested much better variant:

for rev in $(git rev-list <committish>.. ); do
    git difftool ${rev} ${rev}~1;
    done

The OLD version of the answer:

I would say you do something like:

git rev-list <commitish>.. | wc -l

or

git log --oneline <commitish>.. | wc -l

This will calculate how many revision you have between your <commitish> and HEAD.

Then using this number you can automatically run through the commits to see the diffs

c=`git log --online <commitish>.. | wc -l`

while ! ${c} eq 0 ; do

git difftool HEAD~${c} HEAD~${($c-1)}
c=${c}-1
done
Eugene Sajine
  • 8,104
  • 3
  • 23
  • 28
  • I would make this the answer since it's the first and has the gist of it down but it's a little complicated. I fear others who come around won't 'get' this answer if I mark it. Sorry – Dale Forester Aug 07 '12 at 14:14
  • I'd say it is the last much more than the first. – Antony Hatchkins Aug 08 '12 at 16:59
  • Why count with `wc -l` and then iterate with `HEAD~number` when you can iterate directly on revisions with `for rev in $(git rev-list ...)`? Your version does not work if the history between `commitish` and `HEAD` have merge: `commitish` can be `HEAD~n` with `commitish..HEAD` containing more than `n` commits... – Matthieu Moy May 14 '15 at 08:50
  • @MatthieuMoy - you're correct. By the time I was writing this I probably didn't know of forgot about ability to iterate over rev-list. Correcting the answer. – Eugene Sajine May 14 '15 at 20:03
0
for i in 1 2 3
do
  ((j=${i}-1))
  git difftool HEAD~${i}..HEAD~${j} path/to/file &
done
twalberg
  • 59,951
  • 11
  • 89
  • 84
  • The line `git difftool HEAD~${i}.. path/to/file &` has two errors: (1) standard input is not a tty (2) doesn't show commits, shows diffs between previous states and current state instead. See my answer for fixes. – Antony Hatchkins Jul 30 '12 at 18:00
  • @AntonyHatchkins Corrected for #2, but I'm not sure I see what you're saying for #1 - that works for me, but maybe it's dependent on what you have your `diff.tool` set to (`meld` in my config). – twalberg Jul 30 '12 at 18:38
  • Well, I checked in textmode (`emerge`, `vimdiff`). – Antony Hatchkins Jul 31 '12 at 02:57
0

A slightly different approach:

1) Perform an interactive rebase

git rebase -i <commitish>

2) Mark all your commits for edit

3) For each commit run

git difftool HEAD~1

4) Go to the next commit and repeat step 3

git rebase --continue

The added advantage is that if you see a problem in the review, you have already checked out the commit that you want to fix.

Philip Clarke
  • 727
  • 6
  • 13