bos@559: bos@559: bos@559: bos@572: bos@559: A tour of Mercurial: merging work bos@559: bos@584: We've now covered cloning a repository, making changes in a bos@559: repository, and pulling or pushing changes from one repository bos@559: into another. Our next step is merging bos@559: changes from separate repositories. bos@559: bos@559: bos@559: Merging streams of work bos@559: bos@584: Merging is a fundamental part of working with a distributed bos@699: revision control tool. Here are a few cases in which the need bos@699: to merge work arises. bos@559: bos@699: bos@699: Alice and Bob each have a personal copy of a bos@559: repository for a project they're collaborating on. Alice bos@559: fixes a bug in her repository; Bob adds a new feature in bos@559: his. They want the shared repository to contain both the bos@559: bug fix and the new feature. bos@559: bos@699: bos@699: Cynthia frequently works on several different bos@699: tasks for a single project at once, each safely isolated in bos@699: its own repository. Working this way means that she often bos@699: needs to merge one piece of her own work with bos@699: another. bos@699: bos@699: bos@699: bos@699: Because we need to merge often, Mercurial makes bos@699: the process easy. Let's walk through a merge. We'll begin by bos@699: cloning yet another repository (see how often they spring up?) bos@699: and making a change in it. bos@559: bos@567: &interaction.tour.merge.clone; bos@559: bos@584: We should now have two copies of bos@559: hello.c with different contents. The bos@559: histories of the two repositories have also diverged, as bos@592: illustrated in . Here is a copy of our bos@699: file from one repository. bos@699: bos@699: &interaction.tour.merge.cat1; bos@699: bos@700: And here is our slightly different version from the other bos@699: repository. bos@699: bos@699: &interaction.tour.merge.cat2; bos@559: bos@591:
bos@591: Divergent recent histories of the <filename bos@591: class="directory">my-hello</filename> and <filename bos@591: class="directory">my-new-hello</filename> bos@591: repositories bos@559: bos@594: bos@559: XXX add text bos@559: bos@591:
bos@559: bos@584: We already know that pulling changes from our my-hello repository will have no bos@559: effect on the working directory. bos@559: bos@567: &interaction.tour.merge.pull; bos@559: bos@584: However, the hg pull bos@559: command says something about heads. bos@559: bos@559: bos@559: Head changesets bos@559: bos@699: Remember that Mercurial records what the parent bos@699: of each change is. If a change has a parent, we call it a bos@699: child or descendant of the parent. A head is a change that bos@699: has no children. The tip revision is thus a head, because the bos@699: newest revision in a repository doesn't have any children. bos@699: There are times when a repository can contain more than one bos@559: head. bos@559: bos@591:
bos@591: Repository contents after pulling from <filename bos@591: class="directory">my-hello</filename> into <filename bos@591: class="directory">my-new-hello</filename> bos@591: bos@591: bos@594: bos@591: bos@591: XXX add text bos@559: bos@591:
bos@559: bos@592: In , you can bos@559: see the effect of the pull from my-hello into my-new-hello. The history that bos@559: was already present in my-new-hello is untouched, but bos@592: a new revision has been added. By referring to , we can see that the bos@559: changeset ID remains the same in the new bos@559: repository, but the revision number has bos@559: changed. (This, incidentally, is a fine example of why it's bos@559: not safe to use revision numbers when discussing changesets.) bos@559: We can view the heads in a repository using the hg heads command. bos@559: bos@567: &interaction.tour.merge.heads; bos@559:
bos@699: bos@559: bos@559: Performing the merge bos@559: bos@584: What happens if we try to use the normal hg update command to update to the bos@559: new tip? bos@559: bos@567: &interaction.tour.merge.update; bos@559: bos@699: Mercurial is telling us that the hg update command won't do a merge; bos@699: it won't update the working directory when it thinks we might bos@699: want to do a merge, unless we force it to do so. bos@699: (Incidentally, forcing the update with hg update bos@699: -C would revert any uncommitted changes in the bos@699: working directory.) bos@699: bos@700: To start a merge between the two heads, we use the bos@699: hg merge command. bos@559: bos@567: &interaction.tour.merge.merge; bos@559: bos@699: We resolve the contents of hello.c bos@699: bos@699: This updates the working directory so that it bos@699: contains changes from both heads, which bos@699: is reflected in both the output of hg bos@619: parents and the contents of bos@619: hello.c. bos@619: bos@619: &interaction.tour.merge.parents; bos@619: bos@701: bos@619: bos@619: Committing the results of the merge bos@619: bos@619: Whenever we've done a merge, hg bos@619: parents will display two parents until we hg commit the results of the bos@619: merge. bos@619: bos@619: &interaction.tour.merge.commit; bos@619: bos@619: We now have a new tip revision; notice that it has bos@619: both of our former heads as its parents. bos@619: These are the same revisions that were previously displayed by bos@619: hg parents. bos@619: bos@619: &interaction.tour.merge.tip; bos@619: bos@619: In , you can see a bos@619: representation of what happens to the working directory during bos@619: the merge, and how this affects the repository when the commit bos@619: happens. During the merge, the working directory has two bos@619: parent changesets, and these become the parents of the new bos@619: changeset. bos@619: bos@591:
bos@591: Working directory and repository during merge, and bos@591: following commit bos@591: bos@591: bos@594: bos@591: bos@591: XXX add text bos@559: bos@591:
bos@559: bos@676: We sometimes talk about a merge having bos@619: sides: the left side is the first parent bos@670: in the output of hg parents, bos@619: and the right side is the second. If the working directory bos@619: was at e.g. revision 5 before we began a merge, that revision bos@619: will become the left side of the merge. bos@559:
bos@559:
bos@619: bos@559: bos@559: Merging conflicting changes bos@559: bos@584: Most merges are simple affairs, but sometimes you'll find bos@619: yourself merging changes where each side modifies the same portions bos@559: of the same files. Unless both modifications are identical, bos@559: this results in a conflict, where you have bos@559: to decide how to reconcile the different changes into something bos@559: coherent. bos@559: bos@591:
bos@591: Conflicting changes to a document bos@591: bos@594: bos@559: XXX add text bos@591: bos@591:
bos@559: bos@592: illustrates bos@559: an instance of two conflicting changes to a document. We bos@559: started with a single version of the file; then we made some bos@559: changes; while someone else made different changes to the same bos@559: text. Our task in resolving the conflicting changes is to bos@559: decide what the file should look like. bos@559: bos@584: Mercurial doesn't have a built-in facility for handling bos@619: conflicts. Instead, it runs an external program, usually one bos@619: that displays some kind of graphical conflict resolution bos@619: interface. By default, Mercurial tries to find one of several bos@559: different merging tools that are likely to be installed on your bos@559: system. It first tries a few fully automatic merging tools; if bos@559: these don't succeed (because the resolution process requires bos@619: human guidance) or aren't present, it tries a few bos@559: different graphical merging tools. bos@559: bos@699: It's also possible to get Mercurial to run a bos@699: specific program or script, by setting the bos@559: HGMERGE environment variable to the name of your bos@559: preferred program. bos@559: bos@559: bos@559: Using a graphical merge tool bos@559: bos@584: My preferred graphical merge tool is bos@559: kdiff3, which I'll use to describe the bos@559: features that are common to graphical file merging tools. You bos@559: can see a screenshot of kdiff3 in action in bos@592: . The kind of bos@559: merge it is performing is called a three-way bos@559: merge, because there are three different versions bos@559: of the file of interest to us. The tool thus splits the upper bos@559: portion of the window into three panes: bos@559: bos@584: At the left is the base bos@559: version of the file, i.e. the most recent version from bos@559: which the two versions we're trying to merge are bos@559: descended. bos@559: bos@584: In the middle is our version of bos@559: the file, with the contents that we modified. bos@559: bos@584: On the right is their version bos@559: of the file, the one that from the changeset that we're bos@559: trying to merge with. bos@559: bos@584: In the pane below these is the current bos@559: result of the merge. Our task is to bos@559: replace all of the red text, which indicates unresolved bos@559: conflicts, with some sensible merger of the bos@559: ours and theirs versions of the bos@559: file. bos@559: bos@584: All four of these panes are locked bos@559: together; if we scroll vertically or horizontally bos@559: in any of them, the others are updated to display the bos@559: corresponding sections of their respective files. bos@559: bos@591:
bos@591: Using <command>kdiff3</command> to merge versions of a bos@591: file bos@591: bos@591: dongsheng@655: bos@591: bos@591: XXX add text bos@591: bos@559: bos@591:
bos@559: bos@584: For each conflicting portion of the file, we can choose to bos@559: resolve the conflict using some combination of text from the bos@559: base version, ours, or theirs. We can also manually edit the bos@559: merged file at any time, in case we need to make further bos@559: modifications. bos@559: bos@584: There are many file merging tools bos@559: available, too many to cover here. They vary in which bos@559: platforms they are available for, and in their particular bos@559: strengths and weaknesses. Most are tuned for merging files bos@559: containing plain text, while a few are aimed at specialised bos@559: file formats (generally XML). bos@559:
bos@701: bos@559: bos@559: A worked example bos@559: bos@584: In this example, we will reproduce the file modification bos@592: history of bos@559: above. Let's begin by creating a repository with a base bos@559: version of our document. bos@559: bos@567: &interaction.tour-merge-conflict.wife; bos@559: bos@584: We'll clone the repository and make a change to the bos@559: file. bos@559: bos@567: &interaction.tour-merge-conflict.cousin; bos@559: bos@584: And another clone, to simulate someone else making a bos@559: change to the file. (This hints at the idea that it's not all bos@559: that unusual to merge with yourself when you isolate tasks in bos@559: separate repositories, and indeed to find and resolve bos@559: conflicts while doing so.) bos@559: bos@567: &interaction.tour-merge-conflict.son; bos@559: bos@584: Having created two bos@559: different versions of the file, we'll set up an environment bos@559: suitable for running our merge. bos@559: bos@567: &interaction.tour-merge-conflict.pull; bos@559: bos@619: In this example, I'll set bos@559: HGMERGE to tell Mercurial to use the bos@559: non-interactive merge command. This is bos@619: bundled with many Unix-like systems. (If you're following this bos@559: example on your computer, don't bother setting bos@699: HGMERGE. You'll get dropped into a GUI file bos@699: merge tool instead, which is much preferable.) bos@559: bos@567: &interaction.tour-merge-conflict.merge; bos@559: bos@584: Because merge can't resolve the bos@559: conflicting changes, it leaves merge bos@559: markers inside the file that has conflicts, bos@559: indicating which lines have conflicts, and whether they came bos@559: from our version of the file or theirs. bos@559: bos@584: Mercurial can tell from the way merge bos@559: exits that it wasn't able to merge successfully, so it tells bos@559: us what commands we'll need to run if we want to redo the bos@559: merging operation. This could be useful if, for example, we bos@559: were running a graphical merge tool and quit because we were bos@559: confused or realised we had made a mistake. bos@559: bos@584: If automatic or manual merges fail, there's nothing to bos@559: prevent us from fixing up the affected files bos@559: ourselves, and committing the results of our merge: bos@559: bos@567: &interaction.tour-merge-conflict.commit; bos@559: bos@699: bos@699: Where is the <command>hg resolve</command> command? bos@699: bos@700: The hg resolve command was introduced bos@699: in Mercurial 1.1, which was released in December 2008. If bos@699: you are using an older version of Mercurial (run hg bos@699: version to see), this command will not be bos@699: present. If your version of Mercurial is older than 1.1, bos@699: you should strongly consider upgrading to a newer version bos@699: before trying to tackle complicated merges. bos@699: bos@559: bos@559:
bos@701: bos@559: bos@559: Simplifying the pull-merge-commit sequence bos@559: bos@584: The process of merging changes as outlined above is bos@559: straightforward, but requires running three commands in bos@559: sequence. bos@619: hg pull -u bos@579: hg merge bos@579: hg commit -m 'Merged remote changes' bos@584: In the case of the final commit, you also need to enter a bos@559: commit message, which is almost always going to be a piece of bos@559: uninteresting boilerplate text. bos@559: bos@584: It would be nice to reduce the number of steps needed, if bos@559: this were possible. Indeed, Mercurial is distributed with an bos@559: extension called fetch that bos@559: does just this. bos@559: bos@584: Mercurial provides a flexible extension mechanism that lets bos@559: people extend its functionality, while keeping the core of bos@559: Mercurial small and easy to deal with. Some extensions add new bos@559: commands that you can use from the command line, while others bos@559: work behind the scenes, for example adding bos@699: capabilities to Mercurial's built-in server mode. bos@559: bos@619: The fetch bos@619: extension adds a new command called, not surprisingly, hg fetch. This extension acts as a bos@619: combination of hg pull -u, bos@619: hg merge and hg commit. It begins by pulling bos@559: changes from another repository into the current repository. If bos@559: it finds that the changes added a new head to the repository, it bos@699: updates to the new head, begins a merge, then (if the merge bos@699: succeeded) commits the result of the merge with an bos@699: automatically-generated commit message. If no new heads were bos@699: added, it updates the working directory to the new tip bos@699: changeset. bos@619: bos@619: Enabling the fetch extension is easy. Edit the bos@619: .hgrc file in your home bos@619: directory, and either go to the extensions section or create an bos@559: extensions section. Then bos@619: add a line that simply reads bos@619: fetch=. bos@619: bos@579: [extensions] bos@579: fetch = bos@619: bos@619: (Normally, the right-hand side of the bos@619: = would indicate where to find bos@559: the extension, but since the fetch extension is in the standard bos@559: distribution, Mercurial knows where to search for it.) bos@701: bos@701: bos@701: bos@701: Renaming, copying, and merging bos@701: bos@702: During the life of a project, we will often want to change bos@701: the layout of its files and directories. This can be as simple bos@701: as renaming a single file, or as complex as restructuring the bos@701: entire hierarchy of files within the project. bos@701: bos@702: Mercurial supports these kinds of complex changes fluently, bos@701: provided we tell it what we're doing. If we want to rename a bos@701: file, we should use the hg rename bos@702: If you're a Unix user, you'll be glad to know that the bos@701: hg rename command can be abbreviated as bos@701: hg mv. bos@701: command to rename it, so that Mercurial can do the bos@701: right thing later when we merge. bos@701: bos@702: We will cover the use of these commands in more detail in bos@701: . bos@559: bos@559:
bos@559: bos@559: