lang2
lang2

Reputation: 11966

git cherry-pick from a merge programmatically

We're using a git tool that works similar to GitHub PR system. So stuff gets git merge --no-ffed onto master.

When a release is coming, we cut a release branch. Any further bug fixes gets merged to master first and then cherry-picked to the release branch. I'd like to do this programmatically.

So with:

commit bla
Merge: aaaa bbbb

I'd like to:

  1. figure out what commit hash that merge includes
  2. git cherry-pick that commit hash

How do I find the included commit of a merge? What's the syntax of the Merge: line?

Upvotes: 1

Views: 174

Answers (1)

Jan Krüger
Jan Krüger

Reputation: 18530

If you are sure that you will only ever want to pick one commit, you can just select the second parent of the merge (i.e. the tip of whatever branch you merged in, bbbb in your example), like so: git cherry-pick bla^2 (I used your beautiful name for the merge commit)

If you want to try and pick an entire range of commits, it's a little more complicated, but basically you have to find the point where your merged branch diverged and do a bit of set arithmetic. The former can be done using git merge-base, the latter using the .. syntax (A..B meaning: anything reachable from B but not from A):

git cherry-pick $(git merge-base bla^1 bla^2)..bla^2

This gets a little more complicated, though, if there were additional merges in your merged branch (e.g. you merged master into the bugfix branch before merging it back to master). In a case like that I would recommend against trying to do this automatically, it's just too error-prone.


Edit: you updated your question to ask about the syntax of the Merge line in the log. It's actually quite simple. In terms of data structure, a merge commit differs from normal commits in that it has more than one parent (normal commits only have their immediately preceding "ancestor" as a parent). In normal merges done via git merge and the other high-levels tools, the first parent (aaaa in your example) is the commit that was at the tip of the base branch at the time of the merge, and the second parent (bbbb) is the topmost commit of whatever you merged in - hence my suggesting bla^2 above: 2 refers to the second parent, which is bbbb.

A somewhat unusual case is merge commits with more than two parents, called octopus merges. You get an octopus merge if you pass more than one branch/commit argument to git merge. Few people ever use these and they make fixing conflicts even more tedious and error-prone, I'm really only mentioning them for the sake of completeness.

Upvotes: 2

Related Questions