Quantcast
Channel: buildengineer.org » git
Viewing all articles
Browse latest Browse all 7

Stupid Git Tricks #3: A few words about merging

$
0
0

Fast-forward merges

There’s a notion that’s actually in all version control systems, but which is more readily apparent in git, namely, the so-called “fast-forward” merge. Charles Duan offers this extremely useful explanation (as part of an excellent git tutorial):

A fast forward merge is a simple optimization for merging. Say your repository looks like this: 
                    +-- (D) -- (E)
                   /            |
    (A) -- (B) -- (C)           |
                   |            |
                current     to-merge
                   |
                  HEAD
and you run git merge to-merge. In this case, all Git needs to do is set current to point to (E). Since (C) is the common ancestor, there are no changes to actually “merge.” Hence, the resulting merged repository looks like:
                    +-- (D) -- (E)
                   /            |
    (A) -- (B) -- (C)           |
                                |
                        to-merge, current
                                     |
                                    HEAD
That is, to-merge and current both point to commit (E), and HEAD still points to current. Note an important difference: no new commit object is created for the merge. Git only shifts the head pointers around.

(emphasis mine)

In other words, the merge doesn’t appear as a merge. This isn’t normally a problem, but when you merge a branch back to master, people often do something like

$ git checkout my_branch
$ git merge master
<-- fix conflicts, etc., if any -->
$ git checkout master
$ git merge my_branch

and that merge back to master (after merging to my_branch) will be a fast-forward merge on master. You can force git to record it as a real merge with the –no-ff flag:

$ git merge --no-ff my_branch

This is useful primarily to have a record that someone actually did a merge at this point, since otherwise that fact is not really recorded in the repo.


Conflicts and “commit -m”

Sometimes when you merge, you have conflicts you have to resolve. This is a fact of life in concurrent development. (It’s also the case that rather than try to implement some tricksy merge algorithm that can solve everything, git will more readily throw its hands up in the metaphorical air and say, “You fix it” than other VCSes.) When you fix the conflicts, git prepares a really handy commit message for you that looks like this:

Merge branch 'master' into testme

* master:
  committed a conflict

Conflicts:
  this-is-a-test
#
# It looks like you may be committing a MERGE.
# If this is not correct, please remove the file
# .git/MERGE_HEAD
# and try again.
#

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch testme

This message records the file(s) that had conflicts. This information can be extremely helpful in the future for finding bad merges. However, if you use git commit -m "some message" this helpful information will be overwritten. So, a helpful hint is, don’t use git commit -m when committing merges.


Viewing all articles
Browse latest Browse all 7

Trending Articles