Home Explore Blog CI



git

15th chunk of `Documentation/gitcore-tutorial.adoc`
1d2d21cec4f4983785739723b9aac9587a422c9d15bf4a560000000100000fa5
 HEAD`
. `git pull http://www.kernel.org/pub/scm/git/git.git/ tag v0.99.1`


How does the merge work?
------------------------

We said this tutorial shows what plumbing does to help you cope
with the porcelain that isn't flushing, but we so far did not
talk about how the merge really works.  If you are following
this tutorial the first time, I'd suggest to skip to "Publishing
your work" section and come back here later.

OK, still with me?  To give us an example to look at, let's go
back to the earlier repository with "hello" and "example" file,
and bring ourselves back to the pre-merge state:

------------
$ git show-branch --more=2 master mybranch
! [master] Merge work in mybranch
 * [mybranch] Merge work in mybranch
--
-- [master] Merge work in mybranch
+* [master^2] Some work.
+* [master^] Some fun.
------------

Remember, before running 'git merge', our `master` head was at
"Some fun." commit, while our `mybranch` head was at "Some
work." commit.

------------
$ git switch -C mybranch master^2
$ git switch master
$ git reset --hard master^
------------

After rewinding, the commit structure should look like this:

------------
$ git show-branch
* [master] Some fun.
 ! [mybranch] Some work.
--
*  [master] Some fun.
 + [mybranch] Some work.
*+ [master^] Initial commit
------------

Now we are ready to experiment with the merge by hand.

`git merge` command, when merging two branches, uses 3-way merge
algorithm.  First, it finds the common ancestor between them.
The command it uses is 'git merge-base':

------------
$ mb=$(git merge-base HEAD mybranch)
------------

The command writes the commit object name of the common ancestor
to the standard output, so we captured its output to a variable,
because we will be using it in the next step.  By the way, the common
ancestor commit is the "Initial commit" commit in this case.  You can
tell it by:

------------
$ git name-rev --name-only --tags $mb
my-first-tag
------------

After finding out a common ancestor commit, the second step is
this:

------------
$ git read-tree -m -u $mb HEAD mybranch
------------

This is the same 'git read-tree' command we have already seen,
but it takes three trees, unlike previous examples.  This reads
the contents of each tree into different 'stage' in the index
file (the first tree goes to stage 1, the second to stage 2,
etc.).  After reading three trees into three stages, the paths
that are the same in all three stages are 'collapsed' into stage
0.  Also paths that are the same in two of three stages are
collapsed into stage 0, taking the SHA-1 from either stage 2 or
stage 3, whichever is different from stage 1 (i.e. only one side
changed from the common ancestor).

After 'collapsing' operation, paths that are different in three
trees are left in non-zero stages.  At this point, you can
inspect the index file with this command:

------------
$ git ls-files --stage
100644 7f8b141b65fdcee47321e399a2598a235a032422 0	example
100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1	hello
100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2	hello
100644 cc44c73eb783565da5831b4d820c962954019b69 3	hello
------------

In our example of only two files, we did not have unchanged
files so only 'example' resulted in collapsing.  But in real-life
large projects, when only a small number of files change in one commit,
this 'collapsing' tends to trivially merge most of the paths
fairly quickly, leaving only a handful of real changes in non-zero
stages.

To look at only non-zero stages, use `--unmerged` flag:

------------
$ git ls-files --unmerged
100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1	hello
100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2	hello
100644 cc44c73eb783565da5831b4d820c962954019b69 3	hello
------------

The next step of merging is to merge these three versions of the
file, using 3-way merge.  This is done by giving
'git merge-one-file' command as one of the arguments to
'git merge-index' command:

------------
$ git merge-index git-merge-one-file hello

Title: Git Merge Process
Summary
This section explains the step-by-step process of how Git performs a merge between two branches, using a 3-way merge algorithm, including finding the common ancestor, reading tree contents, collapsing paths, and resolving conflicts using 'git merge-one-file' and 'git merge-index' commands.