I have a branch from the most recent commit to master
. the branch has two commits on it. I'd like to fast-forward merge the first of those commits onto master.
I know I could do a cherry pick, but I don't really want to diverge the master and branch if I can help it.
Current state:
Branch: +--->B--->C
/
Master: --->A
Cherry-pick option:
Branch: +--->B--->C
/
Master: --->A--->B'
Ideal option:
Branch: +--->C
/
Master: --->A--->B
Is this possible?
Note that the commits are all pushed to the remote already; but no-one else currently has access to this particular repo so a push -f
would be OK.
I seem to remember there might be some way to merge onto master while a branch is checked out... if that is true, I could simply check out commit B, then merge in that manner?
More specifically, you might want:
git merge --ff-only <commit-specifier>
which tells Git to do a fast-forward not-really-a-merge of the current branch, whatever that is, to the specified commit. Such an operation:
HEAD
is an ancestor of <commit-specifier>
: if not, fail, if so, continue on to...<commit-specifier>
and read that commit into the index and work-tree (git read-tree
, the "two tree merge" case—note that this too can fail, if you have uncommitted changes, or untracked files that are in the target commit).Now, finding a specific hash that's N commits "ahead of" the current commit in the direction of some target commit can be kind of tricky. Consider, for instance:
...--o--o <-- master
\
\ C--D
\ / \
A--B G--H <-- branch
\ /
E--F
The tip commit of branch
is eight commits ahead of the tip commit of master
—or is it? I think everyone agrees that A
is one commit ahead of master
, and B
is two ahead. But what about C
and E
, and D
and F
? C
is three ahead, but so is E
; and D
and F
are both four ahead. But G
is not five ahead of master
: it seems to be seven ahead of master. Likewise, H
aka branch
seems to be eight ahead of master
.
So if I told you to move three commits ahead, would you pick commit C
, or E
? Would you give me an error, or a choice? Why?
If you constrain things to a linear chain, we can enumerate the commits "between" master
and branch
, excluding master
and including branch
, with:
git rev-list --reverse master..branch
and then the N-th commit in the list is the commit hash to give to git merge --ff-only
. But if there are branch-and-merge chains "between" these two points, the whole question becomes tricky.