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.
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