As part our rebase-heavy workflow, I am hoping to use a merge on the master branch. In particular I want to merge only when the topic branch has been rebased onto the most r
git config alias.mff '!mff() { git merge --ff-only "$1" && git reset --hard HEAD@{1} && git merge --no-ff "$1"; }; mff'
and from then on
git mff other-branch
You don't want --ff-only
because you do want to make a merge commit which --ff-only
would inhibit.
The check that you want can be made as a separate check before running the merge command. You could package this into a simple shell function.
E.g.
merge_if_ahead () {
if test "$(git merge-base HEAD "$1")" = "$(git rev-parse HEAD)"; then
git merge --no-ff "$1"
else
echo >&2 "Not up to date; refusing to merge"
return 1
fi
}
I've created an alias that works for my simple tests
git config --global alias.ffmerge '!sh -c "git merge --ff-only $1 && git reset --hard HEAD@{1} && git merge --no-ff $1" -'
It consists of 3 commands, one after each other, that will fail as soon as the first one fails. Explaining each:
git merge --ff-only $1
Will fail if the merge cannot continue as a fast-forward merge. ($1 is the branch name passed in as argument)
git reset --hard HEAD@{1}
If the first command succeeds it means we can do a fast-forward merge but as we want to do a merge commit we'll move back to the state of HEAD just before our (successful) merge. HEAD@{1} is a reflog pointer.
git merge --no-ff $1
Now we'll do the real merge with a merge commit even if the merge can go a head as a fast-forward.
A simple call to git ffmerge
will do the entire thing for us, the only step that can fail is the first and that would leave us in an unchanged working copy as before.
As always with git reset --hard
the working copy should be clean.