Vincent Fourmond Vincent Fourmond - 1 year ago 53
Git Question

Find files that changed specifically in a branch

I have a git repository in which I usually work on two branches, a

branch, and a
branch, the latter following closely the public branch, but with a few extra additions.

Is there a way to find the changes since a given commit that are specific to the private branch ?

The closest I can think of is to do something on the lines of:

git diff base..public > pub.diff
git diff base..private > private.diff
interdiff pub.diff private.diff

This works, but it's not that robust, and I'm sure it's possible to do that with
in a better way.

This is essentially how the branches look (with many more merges):

...A---B---C---D---E---F---G---H public
\ \ \
A'--I---J---D'--K---L---G'--M private

For instance, let's assume that
above is
in this scheme. Just running

git diff D'..M

will also give me the results of the merge commit
. I'd like to avoid that, and have something robust across any numbers of merges.

Answer Source

Because git diff

is about comparing two endpoints, not ranges

This might not be possible (git diff will not detect were those changes came from).

You could try using

Option A

$ git log -p --no-merges --first-parent D'..M
  • -p gives you a diff (patch) for the commits listed
  • --no-merges will exclude merges from the list
  • --first-parent will only follow the first parent (the one you merged into e.g. private)
  • D'..M as explained in git revisision will

    Include commits that are reachable from <rev2> but exclude those that are reachable from <rev1>

Option B

A different approach would be to follow @torek's suggestion and create a temporary branch, cherry-pick all the commits onto it and then look at the diffs from this branch.

Because AFAIK git cherry-pick is not able to skip commits when specifying commit ranges you would first need to get a list of commits for cherry-picking (Here Option A is useful)

$ git log --no-merges --first-parent D'..M --pretty=format:%H
  • --pretty=format:%H will print all the commit hashes in long form

Create the temporal branch (which needs to have the correct starting point)

$ git checkout -b temp D'

And then cherry-pick those commits manually or try using this command

$ git log --no-merges --first-parent --reverse --pretty=format:%H | git cherry-pick
  • --reverse is used to reverse the order of commits printed (oldest to newest instead of the other way around)

This approach might fail if commits are based on changes which were merged in