I have the following scenario:
* ab82147 (HEAD, topic) changes
* 8993636 changes
* 82f4426 changes
* 18be5a3 (master) first
I\'d like to me
Interesting! I don't think there's a built-in way to do this, but you should be able to fudge it using the plumbing:
#!/bin/bash
branch=master
# or take an argument:
# if [ $@ eq 1 ];
# branch="$1";
# fi
# make sure the branch exists
if ! git rev-parse --verify --quiet --heads "$branch" > /dev/null; then
echo "error: branch $branch does not exist"
exit 1
fi
# make sure this could be a fast-forward
if [ "$(git merge-base HEAD $branch)" == "$(git rev-parse $branch)" ]; then
# find the branch name associated with HEAD
currentbranch=$(git symbolic-ref HEAD | sed 's@.*/@@')
# make the commit
newcommit=$(echo "Merge branch '$currentbranch'" | git commit-tree $(git log -n 1 --pretty=%T HEAD) -p $branch -p HEAD)
# move the branch to point to the new commit
git update-ref -m "merge $currentbranch: Merge made by simulated no-ff" "refs/heads/$branch" $newcommit
else
echo "error: merging $currentbranch into $branch would not be a fast-forward"
exit 1
fi
The interesting bit is that newcommit= line; it uses commit-tree to directly create the merge commit. The first argument is the tree to use; that's the tree HEAD, the branch whose contents you want to keep. The commit message is supplied on stdin, and the rest of the arguments name the parents the new commit should have. The commit's SHA1 is printed to stdout, so assuming the commit succeeded, you capture that, then merge that commit (that'll be a fast-forward). If you're obsessive, you could make sure that commit-tree succeeded - but that should be pretty much guaranteed.
Limitations:
--no-ff, git will actually force itself to use the default (recursive) strategy, but to write that in the reflog would be a lie.And yes, I tested this on a toy repo, and it appears to work properly! (Though I didn't try hard to break it.)