Merge Strategies
When the development is complete and ready to be merged into the main line of development, the team should choose which merge strategy is suitable for the merge.
A merge occurs when combining two branches. Git will accept two commit pointers and try to find a common base commit between them. Git can find a common base using different methods called "merge strategies". After choosing the merge strategy, Git will create a new merge commit combining two branches' changes. A merge commit is a simple commit that has two parent commits. If not explicitly specified, git merge will automatically select a merge strategy based on the provided branches. The -s
option can be attached with the name of the desired merge strategy. Both commands git merge and git pull accept the -s
flag.
The following is a listing of merge strategies:
Recursive
$ git merge -s recursive branch_1 branch_2
The "recursive" strategy works with two heads using a 3-way merge algorithm. It is the default merge strategy for pulling or merging branches. The recursive strategy can detect and handle merges that involve renames but currently cannot make use of detected copies;
Resolve
$ git merge -s resolve branch_1 branch_2
The "resolve" strategy works with two heads using a 3-way merge algorithm. It tries to detect criss-cross merge ambiguities and is considered safe and fast.
Octopus
$ git merge -s octopus branch_1 branch_2 branch_3 branch_4 branch_N
The "octopus" strategy is the default when working with more than two heads. It will refuse the merge attempt when the merge has conflicts that need manual resolution. It is usually used for bundling topic branch heads together.
Ours
$ git merge -s ours branch_1 branch_2 branch_3 branch_N
The "ours" strategy resolves multiple branches. It operates on multiple N number of branches. The output resulting tree of the merge result is always that of the current branch head. The "ours" strategy ignores all changes from all other branches. It is meant to be used to combine the history of side branches.
Subtree
$ git merge -s subtree branh_A branch_B
The subtree strategy is the extension version of the recursive strategy. When merging branches A and B, if B corresponds to a subtree of A. B is first modified to reflect the tree structure of A. This modification is also done to the common parent tree that is shared between A and B.
Types of Git Merge Strategies
Explicit merges
The explicit merges are considered the default merge type. It is called explicit due to the creation of a new merge commit that changes the history and points where a merge was performed. The merge commit content is also explicit in that it shows the parents commit of the merge commit. Some developers prefer to avoid the usage of explicit merge because it adds more noise and is not necessary.
Implicit merge via rebase or fast-forward merge
The implicit merges do not create a merge commit. The implicit merge uses a sequence of commits from the specified branch HEAD
and moves them to the top of the target branch. Implicit merges are trigged by rebase events, or fast forward merges.
Squash on merge without explicit merge
Squash is another type of implicit merge. A squash can be performed through an interactive rebase. A squash merge will take the commits from a target branch and squash (combine) them into one commit, which is then added to the HEAD
of the merge base branch. Squash is often used to keep a clean history during a merge. The target branches' commit history becomes a singular squashed branch commit when squashed and merged.
Recursive git merge strategy options
The "recursive" merge strategy discussed above has multiple subsets of additional operation options.
ours
: It will force conflicted parts to be auto-resolved by favoring the "our" version. The changes from the other tree are automatically incorporated if they do not conflict. This option should not be confused with "ours" merge strategy, which does not even look at what other tree contains at all.ours
theirs
: It favors the other merging tree in conflict resolution. It is the opposite of the "ours" strategy. There is no "theirs" merge strategy to confuse this merge option with, unlike the "ours" strategy.theirs
patience
: It will make the "recursive" merge spends more time to avoid mis-merges that occurs due to unimportant matching lines. It is generally used when the branches to be merged have diverged extremely.patience
diff-algorithim=[patience|minimal|histogram|mayers]
: It instructs the "recursive" merge to use another diff algorithm that helps avoid mis-merges on unimportant matching lines.diff-algorithim
ignore-*
: It treats whitespace change as unchanged. By default, whitespace changes mixed with other changes are not ignored.ignore-* ignore-space-change ignore-all-space ignore-space-at-eol ignore-cr-at-eol
renormalize
: It runs a check-out and check-in of all three stages of a file when resolving a three-way merge.renormalize
no-normalize
: It disables the renormalize option. It overrides themerge.renormalize
configuration variable.no-normalize
no-renames
: It ignores renamed files during the merge.no-renames
find-renames=n
: It turns on rename detection. The "n" parameter can be used to pass a threshold for rename similarity. The default "n" value is 100%.find-renames=n
subtree
: It works on the path metadata of the tree to make them match.subtree