Thursday, 27 December 2018

GIT: Merging

Git allows you to combine the changes which were created on two different branches. One way to achieve this is merging, which is described in this chapter. You can merge based on branches, tags or commits. Other ways are using rebase or cherry-pick.
This part explains how to merge changes between two different branches under the assumption that no merging conflicts happen. .

35.1. Fast-forward merge

If the commits which are merged are direct successors of the HEAD pointer of the current branch, Git performs a so-called fast forward merge. This fast forward merge only moves the HEAD pointer of the current branch to the tip of the branch which is being merged.
This process is depicted in the following diagram. The first picture assumes that master is checked out and that you want to merge the changes of the branch labeled "branch 1" into your "master" branch. Each commit points to its predecessor (parent).
Fast forward merge starting
After the fast-forward merge the HEAD points to the master branch pointing to "Commit 3". The "branch 1" branch points to the same commit.
Fast forward merge result

35.2. Merge commit

If commits are merged which are not direct predecessors of the current branch, Git performs a so-called three-way-merge between the latest commits of the two branches, based on the most recent common predecessor of both.
Original state before the merge commit
As a result a so-called merge commit is created on the current branch. It combines the respective changes from the two branches being merged. This commit points to both of its predecessors.
Merge commit
If multiple common predecessors exist, Git uses recursion to create a virtual common predecessor. For this Git creates a merged tree of the common ancestors and uses that as the reference for the 3-way merge. This is called the recursive merge strategy and is the default merge strategy.

35.3. Merge strategies - Octopus, Subtree, Ours

If a fast-forward merge is not possible, Git uses a merge strategy. The default strategy called recursive merge strategy.
The Git command line tooling also supports the octopus merge strategy for merges of multiple references. With this operation it can merge multiple branches at once.
The subtree option is useful when you want to merge in another project into a sub-directory of your current project. It is rarely used and you should prefer the usage of Git submodules. 
The ours strategy merges a branch without looking at the changes introduced in this branch. This keeps the history of the merged branch but ignores the changes introduced in this branch.
You can use the ours merge strategy to document that you have integrated a branch and decided to ignore all changes from this branch.

35.4. Using the git merge command

The git merge command performs a merge. You can merge changes from one branch to the current active one via the following command.
# syntax: git merge <branch-name>
# merges into your currently checked out branch
git merge testing

35.5. Specifying merge strategies

The -s parameter allows you to specify other merge strategies. This is demonstrated with the following command.
For example, you can specify the ours strategy in which the result of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. This is demonstrated with the following command.
# merge branch "obsolete" ignoring all
# changes in the branch
git merge -s ours obsolete
Be careful if you use the ours merge strategy, it ignores everything from the branch which is merged.
The usage of the octopus merge strategy is triggered if you specify more than one reference to merge.
# merge the branch1 and the branch2 using
# changes in the branch
git merge branch1 branch2`

35.6. Specifying parameters for the default merge strategy

The recursive merge strategy (default) allows you to specify flags with the -X parameter. For example you can specify here the ours option. This option forces conflicting changes to be auto-resolved by favoring the local version. Changes from the other branch that do not conflict with our local version are reflected to the merge result. For a binary file, the entire contents are taken from the local version.
The ours option for the recursive merge strategy should not be confused with the ours merge strategy.
A similar option to ours is the theirs option. This option prefers the version from the branch which is merged.
Both options are demonstrated in the following example code.
# merge changes preferring our version
git merge -s recursive -X ours [branch_to_merge]

# merge changes preferring the version from
# the branch to merge
git merge -s recursive -X theirs [branch_to_merge]
Another useful option is the ignore-space-change parameter which ignores whitespace changes.
35.7. Enforcing the creation of a merge commit
If you prefer to have merge commits even for situations in which Git could perform a fast-forward merge you can use the git merge --no-ff command.
The --no-ff parameter can make sense if you want to record in the history at which time you merged from a maintenance branch to the master branch.
When pulling from a remote repository, prefer doing a rebase to a merge. This will help to keep the history easier to read. A merge commit can be helpful to document that functionality was developed in parallel.


0 comments:

Post a Comment