Git diff on topic branch, excluding merge commits

2019-02-08 17:32发布

问题:

Let's say I have the following situation:

    B---D---F---G topic
   /       /
--A---C---E master

For code review purposes, I would like to pull out a diff from commit A to commit G, but not including commits E and C which happened on the master branch, and also not including commit F which is a merge commit.

In other words, I would like to generate a diff that contains changes from F to G and aggregate those changes with changes from A to D.

In other-other words, I want the review diff to contain only my changes from the topic branch, not including a bunch of code from master that happened in the meantime.

Is this possible? If git cannot handle such "diff aggregations", I would be very thankful if someone can provide some pointers as to how some external command can do that (so that I can try writing a bash script which would do the trick).

回答1:

If you don't care what's in the "context" part of the diffs, then git diff master..topic will give you what you want. Any changes introduced in C and E are considered part of the "base" of the diff, so the changes from master will be there in the context, but only the actual changes made in your topic branch will be marked with + or - as changes. That's usually what people want for code reviews.

If instead you want to act like the merge never happened, you will have to rebase it out:

git rebase --onto A master


回答2:

The answer from Karl is misleading:

git diff never works on proper ranges (i.e. multiple commits), only between two commits!

The range syntax has special meaning for git diff.

git diff E..G is always equal to git diff E G (and
git diff E...G is equal to git diff E G in this case, because E is the merge-base between the two).

git diff master...topic is what you want in this and in the general case: it shows you all changes of the topic branch, comparing it to the last merge-base (i.e. contrasting it to master when it was merged the last time, ignoring all later changes in master which are not in your topic branch anyway).

Note: unfortunately (by coincidence?) the effect of x..y in git log, etc. is best represented by x...y in git diff and vice versa!



回答3:

What about:

  1. git checkout topic

  2. git checkout -b temp

  3. git revert F

  4. git diff A

Afterwards you can happily remove the temp branch.