6

I want to be able to see changes in a branch, since I last reviewed it, but ignoring the changes in master that happened in the meantime.

     F - G       H - I
    /           /
A - B - C - D - E

I have two commit ranges c3af8fc5..7ccc4b49 (represented by B - G) and 4dfdabdd..301a443c (represented by E - I).


Imagine, you're doing code review for your colleague, you checkout his branch on local and your HEAD is now pointing to G. You do the code review and move on to something else.

Some time passes, new commits appeared in master (C, D and E) and your colleague have resolved the comments from your review. He squashed the changes to commits F and G, because he renamed method introduced in F and fixed its usage in G. He also rebased the branch on master, to make sure everything works.

Now you want to make code review again, but you're lazy to do a code review of the whole branch again, so you wanna only see what changed from the last time. You still have the old refs fetched locally. What do you do?

You could do something like git-diff G I, but that would also show you what changed in master which doesn't help you at all.

You could also rebase the old refs on the current master and then diff them. That might help, but there also might be a lot of conflicts, which could make just reviewing the whole branch again easier.


I've tried diffing patches

diff <(git-diff c3af8fc5...7ccc4b49) <(git-diff 4dfdabdd...301a443c)

it helps me to direct my attention somewhere, but it is very crude.

Do you know any nicer, more native way to solve this problem? Thanks.


Edit: I've just discovered interdiff, which makes diffing two diffs much nicer

interdiff <(git-diff -U100 c3af8fc5...7ccc4b49) <(git-diff -U100 4dfdabdd...301a443c)  | colordiff

but still, it lacks the context that git might provide - so... is there anything better?

Filip Procházka
  • 708
  • 6
  • 28
  • Git can only show the diff between two commits. It sounds like you want a diff of a diff, so that’s not something Git can do. – poke Oct 06 '17 at 19:25
  • I know, but git has context of the changes, It could generate that diff of two diffs somehow cleverly. – Filip Procházka Oct 06 '17 at 19:31
  • But what would that even look like? I cannot even think of it visually. – poke Oct 06 '17 at 19:35
  • I have no idea, that's why I've opened this question :) – Filip Procházka Oct 06 '17 at 20:02
  • 2
    Watch out: the syntax `c3af8fc5...7ccc4b49` means, for `git diff`, that it should find the *merge base* of `c3af8fc5` and `7ccc4b49`, and then diff that commit (whatever it is) against `7ccc4b49`. That may not be what you intend. Note that `git diff X..Y` (two dots vs three) means exactly the same thing as `git diff X Y`, and `git diff X...Y` has this special, diff-only meaning. – torek Oct 06 '17 at 20:09
  • I can't make out what you are trying to achieve here. You have only 2 branch refs shown here, `G` and `I`. Are you trying to imply from the diagram that master is currently at `E`? If so, what is the relationship between `F-G` and `H-I` that you are trying to understand? (i.e. why do you say 'before and after rebase' in the title?) – LightCC Oct 07 '17 at 04:13
  • I've tried to provide a better explanation. Does this help? – Filip Procházka Oct 08 '17 at 02:27
  • @FilipProcházka it does help, but why still using `diff` with three dots after torek's explanation? What does `git diff G..I` gives you? (https://stackoverflow.com/a/7256391/6309) – VonC Oct 08 '17 at 04:08
  • I think you're focusing on the wrong part. – Filip Procházka Oct 08 '17 at 09:12
  • Better than interdiff, check out `git range-diff` with Git 2.19 (Q3 2018). See "[Git diff - two disjoint revision ranges](https://stackoverflow.com/a/51956694/6309)", and "[Git diff branch before and after rebase ignoring changes in master](https://stackoverflow.com/a/51956712/6309)". – VonC Aug 21 '18 at 21:08

2 Answers2

9

So the solution is to use the new git range-diff.

Simply run git range-diff c3af8fc5..7ccc4b49 4dfdabdd..301a443c, or even simpler git range-diff 7ccc4b49...301a443c might work unless you've done some really crazy rebase.

For a better explanation, I'm referencing few related topics

Filip Procházka
  • 708
  • 6
  • 28
  • Well done! git rang-diff (with Git 2.19+, Q3 2018) rocks. +1 – VonC Sep 26 '18 at 13:55
  • Just a note: I had to reverse the order of the longer version for the outputs to be the same. git range-diff c3af8fc5..7ccc4b49 4dfdabdd..301a443c became git range-diff 4dfdabdd..301a443c c3af8fc5..7ccc4b49 – Will Bender Mar 10 '20 at 16:16
3

The simplest way may be : visually compare the diffs

Fire up two diff viewers, and compare the two views when you want to see what comes from the rebased revision :

# view the "old" patch :
git difftool -d B G

# view the "new" patch :
git difftool -d H I

You can focus on modified files only :

git diff --name-only B G

will list the names of the modified files between B and G.

You can target only modified files using for example :

# compare G and I,
# looking only at files modified between B and G, or between E and I :
git difftool -d G I -- $(
    git diff --name-only B G; git diff --name-only E I
)

You can also try rebasing B..G on top of E on your local machine, if it doesn't trigger too many conflicts, and then look at the diff :

git checkout G

# as an option, you can make a temporary branch :
git checkout -b wip/G

# rebase on the tip of 'master' :
git rebase E

# look at the diff between "rebased G" and I
git difftool -d wip/G I
LeGEC
  • 29,595
  • 2
  • 37
  • 78