I’m finding that with experience Git mistakes are getting less common and more irritating.

Like a lot of people, I tend to use something like A Successful Git Branching Model. I try to reserve master for releases, which means that every commit should correspond to a tagged release (either features merged in from develop, or a hotfix).

Basically, the network graph should look a bit like this, with every commit on master corresponding to a stable release:

Isn't it pretty

A fast-forward merge occurs when Git detects that the current HEAD is a direct ancestor of the commit you’re merging (i.e: the branches haven’t diverged). In this case, instead of actually merging the branches, Git just moves the old branch pointer around to point at the new commit. Less a merge, more a relabelling.

But your development branch might contain multiple, perhaps partial or unfinished commits (the infamous WIP). We want to make it clear that these commits aren’t stable releases, by letting it be known they occurred on-branch.

To make sure that Git always creates a new merge-commit even when the branches aren’t diverged, add the –no-ff flag:

$ git merge --no-ff