Reputation: 3278
I have a git repository in which I usually work on two branches, a public
branch, and a private
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 git
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 base
above is D
in this scheme. Just running
git diff D'..M
will also give me the results of the merge commit G'
. I'd like to avoid that, and have something robust across any numbers of merges.
Upvotes: 2
Views: 56
Reputation: 2726
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
$ 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>
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 formCreate 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 (exchanged for a better command suggested by @torek)
$ git cherry-pick $(git rev-list --reverse --topo-order --no-merges --first-parent D'..M)
--reverse
is used to reverse the order of commits printed (oldest to newest instead of the other way around)--topo-order
this will avoid problems with commits that have weird or wrong timestamps--no-merges
skip merge commits--first-parent
follow the mainline branch (e.g. the branch the merges were merged into)This approach might fail if commits are based on changes which were merged in
Upvotes: 3