Disclaimer: Many readers have noted that this is a straw man argument and git was not designed to use this workflow. I wrote this blog post because I had seen people at two different companies working this way so it's only addressed to people who find themselves working this way accidentally. When you have conflicts in the cherry-picking workflow you can lose track of what has been merged and what has not been merged into particular branches. I've seen teams lose emergency hotfixes and not be aware of it because of this. Cherry-picking has its uses and I don't mean to discourage it when necessary but it shouldn't be something you need to do more frequently than merging.

Cherry-picking Workflow

Changes are made in a maintenance branch off of the release where the bug was found. The commitid from this change is then cherry-picked into the current integration branch.

% git checkout -b maintenance-branch <release tag or commitid> # (if the maintenance branch doesn't yet exist)
% git checkout -t origin/maintenance-branch # (if the branch already exists)
% git commit -am "Made a bug fix" # note the commitid
% git push origin maintenance-branch
% git checkout integration-branch # (e.g. master)
% git cherry-pick <commitid>
# resolve conflicts
% git push origin integration-branch

Problems with the cherry-picking workflow

For example:

Under the cherry-pick workflow, even though a bugfix was cherry-picked into the integration branch and there was a conflict git cherry -v reports that the integration branch is missing this commit from the maintenance branch.

% git cherry -v maintenance-branch integration-branch
+ 33de19776f4446d92b45e1fdfb2d9c37b3a867a7 Made a bug fix

Merge Workflow

Changes are made in a maintenance branch off of the release where the bug was found (same as in the cherry-picking workflow). The maintenance branch is then merged into the current integration branch.

% git checkout -b maintenance-branch <commitid> # (if the branch doesn't yet exist)
% git checkout -t origin/maintenance-branch # (if the branch already exists)
% git commit -am "Made a bug fix"
% git push origin maintenance-branch
% git checkout integration-branch # (e.g. master)
% git merge origin/maintenance
# resolve conflicts
% git push origin integration-branch

Benefits

Confusingly enough one of the most useful tools in the merge workflow to check that the state is correct is named "cherry". It shows the commits that were made in one branch and not the other. It should show no missing changes when following the merge workflow because all the changes from the maintenance should make their way into the integration branch:

% git cherry -v maintenance-branch integration-branch
[nothing]

Draws