Mercurial_ The Definitive Guide - Bryan O'Sullivan [60]
$ hg parents
changeset: 1:8928355fee43
branch: foo
user: Bryan O'Sullivan date: Tue May 05 06:44:25 2009 +0000 summary: Second commit $ hg update bar 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg parents changeset: 2:f32855c6764f branch: bar tag: tip user: Bryan O'Sullivan date: Tue May 05 06:44:25 2009 +0000 summary: Third commit If we go back to the foo branch and then run hg update, it will keep us on foo, not move us to the tip of bar. $ hg update foo 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg update 0 files updated, 0 files merged, 0 files removed, 0 files unresolved Committing a new change on the foo branch introduces a new head. $ echo something > somefile $ hg commit -A -m 'New file' adding somefile created new head $ hg heads changeset: 3:2e55e6a73143 branch: foo tag: tip parent: 1:8928355fee43 user: Bryan O'Sullivan date: Tue May 05 06:44:26 2009 +0000 summary: New file changeset: 2:f32855c6764f branch: bar user: Bryan O'Sullivan date: Tue May 05 06:44:25 2009 +0000 summary: Third commit Branch Names and Merging As you’ve probably noticed, merges in Mercurial are not symmetrical. Let’s say our repository has two heads, 17 and 23. If I hg update to 17 and then hg merge with 23, Mercurial records 17 as the first parent of the merge, and 23 as the second. Whereas if I hg update to 23 and then hg merge with 17, it records 23 as the first parent, and 17 as the second. This affects Mercurial’s choice of branch name when you merge. After a merge, Mercurial will retain the branch name of the first parent when you commit the result of the merge. If your first parent’s branch name is foo, and you merge with bar, the branch name will still be foo after you merge. It’s not unusual for a repository to contain multiple heads, each with the same branch name. Let’s say I’m working on the foo branch, and so are you. We commit different changes; I pull your changes; I now have two heads, each claiming to be on the foo branch. The result of a merge will be a single head on the foo branch, as you might hope. But if I’m working on the bar branch, and I merge work from the foo branch, the result will remain on the bar branch. $ hg branch bar $ hg merge foo 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg commit -m 'Merge' $ hg tip changeset: 4:00d606298226 branch: bar tag: tip parent: 2:f32855c6764f parent: 3:2e55e6a73143 user: Bryan O'Sullivan date: Tue May 05 06:44:26 2009 +0000 summary: Merge To give a more concrete example, if I’m working on the bleeding-edge branch, and I want to bring in the latest fixes from the stable branch, Mercurial will choose the “right” (bleeding-edge) branch name when I pull and merge from stable. Branch Naming Is Generally Useful You shouldn’t think of named branches as applicable only to situations where you have multiple long-lived branches cohabiting in a single repository. They’re very useful even in the one-branch-per-repository case. In the simplest case, giving a name to each branch gives you a permanent record of which branch a changeset originated on. This gives you more context when you’re trying to follow the history of a long-lived branchy project. If you’re working with shared repositories, you can set up a pretxnchangegroup hook on each that will block incoming changes that have the “wrong” branch name. This provides a simple, but effective, defense against people accidentally pushing changes from a “bleeding edge” branch to a “stable” branch. Such a hook might look like this inside the shared repo’s /.hgrc. [hooks] pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch Chapter 9. Finding and Fixing Mistakes To err might be human, but to really handle the consequences well takes a top-notch revision control system. In this chapter, we’ll discuss