Differences between revisions 39 and 40
Revision 39 as of 2009-03-09 13:40:45
Size: 11125
Comment: Error message has probably been updated
Revision 40 as of 2009-05-19 19:31:05
Size: 11150
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
''(This page is part 7 of 9 of the [:Tutorial] series. Previous part is [:TutorialExport], next part is [:TutorialConflict])''

In [:TutorialExport], we learned how to share a change with another person. In this tutorial here, we're going to demonstrate [:Merge:merging] by [:Pull:pulling] from another [:Repository:repository] that has made a diverging change.

First, we must create something to merge. Let's [:Clone:clone] the `my-hello` repository again:
''(This page is part 7 of 9 of the [[Tutorial]] series. Previous part is [[TutorialExport]], next part is [[TutorialConflict]])''

In [[TutorialExport]], we learned how to share a change with another person. In this tutorial here, we're going to demonstrate [[Merge|merging]] by [[Pull|pulling]] from another [[Repository|repository]] that has made a diverging change.

First, we must create something to merge. Let's [[Clone|clone]] the `my-hello` repository again:
Line 35: Line 35:
Let's save and quit the editor, and [:Commit:commit] our change. This time, we save some time by using the `-m` option to the `commit` command, to spare us from being dropped into an editor: Let's save and quit the editor, and [[Commit|commit]] our change. This time, we save some time by using the `-m` option to the `commit` command, to spare us from being dropped into an editor:
Line 56: Line 56:
Mercurial tells us that it has added an additional [:Head:head] to our repository. To see the heads Mercurial tells us that it has added an additional [[Head|head]] to our repository. To see the heads
Line 74: Line 74:
Mercurial ships with a nice [:UsingExtensions:extension] that can show an ASCII graph of the history of a repository: the [:GraphlogExtension]. All you need to do to get it working is to enable it in your `~/.hgrc` file (or `Mercurial.ini` on Windows) by adding the line {{{hgext.graphlog = }}} to the `[extensions]` section like this: Mercurial ships with a nice [[UsingExtensions|extension]] that can show an ASCII graph of the history of a repository: the [[GraphlogExtension]]. All you need to do to get it working is to enable it in your `~/.hgrc` file (or `Mercurial.ini` on Windows) by adding the line {{{hgext.graphlog = }}} to the `[extensions]` section like this:
Line 108: Line 108:
In this graph, you can see that we've just pulled changeset `86794f718fb1` into our repository (which thus is now the [:Tip:tip]). Since both the pulled-in `86794f718fb1` and our own `c3844fde99f0` were committed against the same base `82e55d328c8c` (the [:Parent:parent]), a diverging line of development was created – namely a [:Branch:branch]. Note that in this case that branch is short-lived and handling this forking is easy to resolve with Mercurial.

While looking at the output of `pull`, you may think it looks similar to that from [:TutorialShareChange]. So you might ask: why not just do a simple [:Update:update] now like
In this graph, you can see that we've just pulled changeset `86794f718fb1` into our repository (which thus is now the [[Tip|tip]]). Since both the pulled-in `86794f718fb1` and our own `c3844fde99f0` were committed against the same base `82e55d328c8c` (the [[Parent|parent]]), a diverging line of development was created – namely a [[Branch|branch]]. Note that in this case that branch is short-lived and handling this forking is easy to resolve with Mercurial.

While looking at the output of `pull`, you may think it looks similar to that from [[TutorialShareChange]]. So you might ask: why not just do a simple [[Update|update]] now like
Line 121: Line 121:
But before we do our very first merge let's check to which changeset we are synced to. We can use the `parents` command for this (see [:Parent]): But before we do our very first merge let's check to which changeset we are synced to. We can use the `parents` command for this (see [[Parent]]):
Line 131: Line 131:
This tells us that our [:WorkingDirectory:working directory] content is still synced to changeset `c3844fde99f0` – after all, that is what we just committed. What's important to understand here is, that This tells us that our [[WorkingDirectory|working directory]] content is still synced to changeset `c3844fde99f0` – after all, that is what we just committed. What's important to understand here is, that
Line 146: Line 146:
the change chunks were non-conflicting (a merge with conflicts will be treated in [:TutorialConflict]). If we look at `hello.c` in the working dir now, we find that it contains ''both'' the change from `my-hello-new-output` and the change from `my-hello-desc`. the change chunks were non-conflicting (a merge with conflicts will be treated in [[TutorialConflict]]). If we look at `hello.c` in the working dir now, we find that it contains ''both'' the change from `my-hello-new-output` and the change from `my-hello-desc`.
Line 202: Line 202:
/!\ Note that if you change your mind and you want to undo this merge before comitting anything, just doing a `hg revert -r2 --all` will only revert the state of the files in the working dir to revision 2 and __not change the parents of the working dir back to a single parent__ (see [:Revert]). You should do a "`hg update -C -r.`" instead to undo the merge in this case.

To complete the whole merging procedure, we should not forget to commit these [:LocalModifications:local modifications], as suggested on the last line of the output from the earlier `merge` command:
/!\ Note that if you change your mind and you want to undo this merge before comitting anything, just doing a `hg revert -r2 --all` will only revert the state of the files in the working dir to revision 2 and __not change the parents of the working dir back to a single parent__ (see [[Revert]]). You should do a "`hg update -C -r.`" instead to undo the merge in this case.

To complete the whole merging procedure, we should not forget to commit these [[LocalModifications|local modifications]], as suggested on the last line of the output from the earlier `merge` command:
Line 211: Line 211:
repository as a new [:MergeChangeset:merge changeset] and we can explore it with `glog`: repository as a new [[MergeChangeset|merge changeset]] and we can explore it with `glog`:
Line 269: Line 269:
Let us continue on and learn how to deal with situations where [:Conflict:conflicting] changes have been made in [:TutorialConflict]. Let us continue on and learn how to deal with situations where [[Conflict|conflicting]] changes have been made in [[TutorialConflict]].

Tutorial - Merging changes

(This page is part 7 of 9 of the Tutorial series. Previous part is TutorialExport, next part is TutorialConflict)

In TutorialExport, we learned how to share a change with another person. In this tutorial here, we're going to demonstrate merging by pulling from another repository that has made a diverging change.

First, we must create something to merge. Let's clone the my-hello repository again:

$ cd ..
$ hg clone my-hello my-hello-desc
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved

We are going to give hello.c a description in its comment section.

$ cd my-hello-desc
$ vi hello.c

Let's change the second line from this:

 * hello.c

to this:

 * hello.c - hello, world

Let's save and quit the editor, and commit our change. This time, we save some time by using the -m option to the commit command, to spare us from being dropped into an editor:

$ hg commit -m "Add description of hello.c"

At this point, we have made one change to hello.c in the my-hello-new-output repository, and another change to hello.c in the my-hello-desc repository. How do we merge these two diverging lines of development? Will there be a problem when we want to pull from one into the other?

This works just fine. While still in my-hello-desc, let's pull the changes from my-hello-new-output and see what happens:

$ hg pull ../my-hello-new-output
pulling from ../my-hello-new-output
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)

Mercurial tells us that it has added an additional head to our repository. To see the heads we can use the heads command:

$ hg heads
changeset:   3:86794f718fb1
tag:         tip
parent:      1:82e55d328c8c
user:        mpm@selenic.com
date:        Mon May 05 01:20:46 2008 +0200
summary:     Express great joy at existence of Mercurial

changeset:   2:c3844fde99f0
user:        mpm@selenic.com
date:        Tue May 06 20:10:35 2008 +0200
summary:     Add description of hello.c

Mercurial ships with a nice extension that can show an ASCII graph of the history of a repository: the GraphlogExtension. All you need to do to get it working is to enable it in your ~/.hgrc file (or Mercurial.ini on Windows) by adding the line hgext.graphlog =  to the [extensions] section like this:

[extensions]
hgext.graphlog = 

If you've done that, an additional command glog becomes available (see also hg help glog):

$ hg glog
o  changeset:   3:86794f718fb1
|  tag:         tip
|  parent:      1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Mon May 05 01:20:46 2008 +0200
|  summary:     Express great joy at existence of Mercurial
|
| @  changeset:   2:c3844fde99f0
|/   user:        mpm@selenic.com
|    date:        Tue May 06 20:10:35 2008 +0200
|    summary:     Add description of hello.c
|
o  changeset:   1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Fri Aug 26 01:21:28 2005 -0700
|  summary:     Create a makefile
|
o  changeset:   0:0a04b987be5a
   user:        mpm@selenic.com
   date:        Fri Aug 26 01:20:50 2005 -0700
   summary:     Create a standard "hello, world" program

In this graph, you can see that we've just pulled changeset 86794f718fb1 into our repository (which thus is now the tip). Since both the pulled-in 86794f718fb1 and our own c3844fde99f0 were committed against the same base 82e55d328c8c (the parent), a diverging line of development was created – namely a branch. Note that in this case that branch is short-lived and handling this forking is easy to resolve with Mercurial.

While looking at the output of pull, you may think it looks similar to that from TutorialShareChange. So you might ask: why not just do a simple update now like we did in TutorialShareChange? Let's try that and see what happens:

$ hg update
abort: crosses branches (use 'hg merge' or 'hg update -C')

Something is clearly different here. But as you can see, Mercurial takes care of not doing anything stupid, so if we happen to ever overlook such a "(+1 heads)" notice after a pull, we can be sure that Mercurial will nicely remind us that we probably should do something else here: we should merge.

But before we do our very first merge let's check to which changeset we are synced to. We can use the parents command for this (see Parent):

$ hg parents
changeset:   2:c3844fde99f0
user:        mpm@selenic.com
date:        Tue May 06 20:10:35 2008 +0200
summary:     Add description of hello.c

This tells us that our working directory content is still synced to changeset c3844fde99f0 – after all, that is what we just committed. What's important to understand here is, that the pull we did just pulled that other change into the store of our repository. The pull didn't change anything in our working directory. And take a second look at the output of glog: one changeset is marked with an "@". That's the current parent of the working dir: We are "at" c3844fde99f0.

So, let's finally move on to the merge now. Merging sounds painful, right? It's actually very easy. Let's follow the instructions of the last line of the output of our earlier pull:

$ hg merge
merging hello.c
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

That's all there is to it! Mercurial was able to handle the merge automatically for you, because the change chunks were non-conflicting (a merge with conflicts will be treated in TutorialConflict). If we look at hello.c in the working dir now, we find that it contains both the change from my-hello-new-output and the change from my-hello-desc.

When working with changes made by other people, this is the kind of merge you will end up performing 2nd most of the time. Most often, it's even simpler than that and the files that are changed in the diverged lines of development are disjunct. So, in most merges, there won't even be any files to merge.

We haven't yet committed that merge now. Before we do that, let's see what the parents command is telling us now (we use abbrevation par):

$ hg par
changeset:   2:c3844fde99f0
user:        mpm@selenic.com
date:        Tue May 06 20:10:35 2008 +0200
summary:     Add description of hello.c

changeset:   3:86794f718fb1
tag:         tip
parent:      1:82e55d328c8c
user:        mpm@selenic.com
date:        Mon May 05 01:20:46 2008 +0200
summary:     Express great joy at existence of Mercurial

This now tells us, that the working directory is based on two changesets: it has two parents. Note that these two parents are ordered: the first parent (parent 1) is our earlier changeset c3844fde99f0 in which we added that description to hello.c. That was the then current parent when we issued the merge command. The second parent (parent 2) is changeset 86794f718fb1 which we pulled from the other repository and which actually is the changeset we have merged-in now.

Another glog now shows the @ sign on the two parents:

$ hg glog
@  changeset:   3:86794f718fb1
|  tag:         tip
|  parent:      1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Mon May 05 01:20:46 2008 +0200
|  summary:     Express great joy at existence of Mercurial
|
| @  changeset:   2:c3844fde99f0
|/   user:        mpm@selenic.com
|    date:        Tue May 06 20:10:35 2008 +0200
|    summary:     Add description of hello.c
|
o  changeset:   1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Fri Aug 26 01:21:28 2005 -0700
|  summary:     Create a makefile
|
o  changeset:   0:0a04b987be5a
   user:        mpm@selenic.com
   date:        Fri Aug 26 01:20:50 2005 -0700
   summary:     Create a standard "hello, world" program

/!\ Note that if you change your mind and you want to undo this merge before comitting anything, just doing a hg revert -r2 --all will only revert the state of the files in the working dir to revision 2 and not change the parents of the working dir back to a single parent (see Revert). You should do a "hg update -C -r." instead to undo the merge in this case.

To complete the whole merging procedure, we should not forget to commit these local modifications, as suggested on the last line of the output from the earlier merge command:

$ hg commit -m "Merged changes from my-hello-new-output"

There shouldn't be any output from this command. Now, the merge is recorded in the store of the repository as a new merge changeset and we can explore it with glog:

$ hg glog
@    changeset:   4:d2ecac0134d8
|\   tag:         tip
| |  parent:      2:c3844fde99f0
| |  parent:      3:86794f718fb1
| |  user:        mpm@selenic.com
| |  date:        Tue May 06 23:44:19 2008 +0200
| |  summary:     Merged changes from my-hello-new-output
| |
| o  changeset:   3:86794f718fb1
| |  parent:      1:82e55d328c8c
| |  user:        mpm@selenic.com
| |  date:        Mon May 05 01:20:46 2008 +0200
| |  summary:     Express great joy at existence of Mercurial
| |
o |  changeset:   2:c3844fde99f0
|/   user:        mpm@selenic.com
|    date:        Tue May 06 20:10:35 2008 +0200
|    summary:     Add description of hello.c
|
o  changeset:   1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Fri Aug 26 01:21:28 2005 -0700
|  summary:     Create a makefile
|
o  changeset:   0:0a04b987be5a
   user:        mpm@selenic.com
   date:        Fri Aug 26 01:20:50 2005 -0700
   summary:     Create a standard "hello, world" program

To show the changes of our merging, we can furthermore use the annotate command to show changeset information per file line. Note that revision 2 is our modification to my-hello-desc repository and revision 3 is the changes pulled and merged from my-hello-new-output repository to my-hello-desc repository.

$ hg annotate hello.c
0: /*
2:  * hello.c - hello, world
0:  *
0:  * Placed in the public domain by Bryan O'Sullivan
0:  *
0:  * This program is not covered by patents in the United States or other
0:  * countries.
0:  */
0:
0: #include <stdio.h>
0:
0: int main(int argc, char **argv)
0: {
0:      printf("hello, world!\n");
3:      printf("sure am glad I'm using Mercurial!\n");
0:      return 0;
0: }

Let us continue on and learn how to deal with situations where conflicting changes have been made in TutorialConflict.


CategoryTutorial

TutorialMerge (last edited 2012-11-06 16:18:47 by abuehl)