Giszmo
Giszmo

Reputation: 2127

How can I produce the git diff omitting changes that are in master?

So I was hinted at there being options to review diffs omitting changes from a specific branch using some cherry picking options but I'm still lost on this and would appreciate an actual command to achieve this.

I want to review revision spans on a feature branch without being distracted by changes that come from merging master.

Suppose Anton does:

git checkout featureX // featureX is a long living branch
[do changes and commits]
git merge master
[do more changes and commits]
git push

Now if Berta does

git checkout featureX
git pull

git tells her

Updating 437b2899c..bffdf1a1f

and when she now does

git difftool --dir-diff 437b2899c..bffdf1a1f

the diff might be cluttered with changes from master. How can she hide changes from master in this diff?

To elaborate ...

Suppose commit X is the merge base (last commit on both master and featureX) and I already reviewed the next 100 commits on featureX up to commit Y at which point the dev did more commits and also merged master into featureX which also had 100 new commits that I already have reviewed. I don't want to re-review those commits from neither branch. git diff X..featureX contains both the 100 commits from master and from featureX that I already reviewed. git diff Y..featureX contains the 100 "old" commits from master. git diff master..featureX contains the 100 "old" commits from featureX. I want a diff with no changes introduced by any of these 200 "old" commits.

Upvotes: 2

Views: 88

Answers (2)

Enrico Campidoglio
Enrico Campidoglio

Reputation: 59923

So I was hinted at there being options to review diffs omitting changes from a specific branch using some cherry picking options

They were probably talking about reviewing the diffs using git-log, since git-diff doesn't have any such options, while git-log does.

In this case, you can use git-log with the double-dot notation and the --ancestry-path option to select the commits you want to review.

From the documentation about the double-dot notation:

This basically asks Git to resolve a range of commits that are reachable from one commit but aren’t reachable from another.

By adding the --ancestry-path option, we're telling Git to only consider the commits that are both descendants of the first commit and ancestors of the second one.

The complete command would then be:

git log --patch --ancestry-path --no-merges Y..featureX

which literally means select the non-merge commits that are both descendants of Y and ancestors of featureX, then generate the patch for each of them.

In your case, it will show you the diffs introduced by the commits that only exist between Y and featureX on the featureX branch.

Upvotes: 0

j6t
j6t

Reputation: 13387

You have this history (time flows left to right):

--X--o--o--o--o--Z--o       <- master
   \              \
    a--b--c--Y--r--s--t     < featureX

You have aready reviewed abc, Y, the os and Z. Now you want to see only the diff generated by rst.

You cannot do this with a git diff command alone. The simplest is possibly to look at the individual diffs of rst:

git log -p Y..featureX ^master

If you really want to see one huge diff, you have to create an auxiliary merge commit that subsumes all commits that you are not interested in:

git checkout --detach Z
git merge Y
# if necessary, resolve conflicts and commit the merge

At this point, all uninteresting commits are in the merge commit:

                 ,-M        <- auxiliary commit
                / /
--X--o--o--o--o+-Z--o       <- master
   \          /   \
    a--b--c--Y--r--s--t     < featureX

Now you can generate the diff that subsumes rst:

git diff ..featureX

Upvotes: 1

Related Questions