You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
readability/test/test-pages/mercurial/expected.html

480 lines
34 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<div id="readability-page-1" class="page">
<div id="evolve-shared-mutable-history">
<p> Once you have mastered the art of mutable history in a single repository (see the <a href="http://fakehost/test/user-guide.html">user guide</a>), you can move up to the next level: <em>shared</em> mutable history. <tt><span>evolve</span></tt> lets you push and pull draft changesets between repositories along with their obsolescence markers. This opens up a number of interesting possibilities. </p>
<p> The simplest scenario is a single developer working across two computers. Say youre working on code that must be tested on a remote test server, probably in a rack somewhere, only accessible by SSH, and running an “enterprise-grade” (out-of-date) OS. But you probably prefer to write code locally: everything is setup the way you like it, and you can use your preferred editor, IDE, merge/diff tools, etc. </p>
<p> Traditionally, your options are limited: either </p>
<blockquote>
<div>
<ul>
<li>(ab)use your source control system by committing half-working code in order to get it onto the remote test server, or </li>
<li>go behind source controls back by using <tt><span>rsync</span></tt> (or similar) to transfer your code back-and-forth until it is ready to commit </li>
</ul>
</div>
</blockquote>
<p> The former is less bad with distributed version control systems like Mercurial, but its still far from ideal. (One important version control “best practice” is that every commit should make things just a little bit better, i.e. you should never commit code that is worse than what came before.) The latter, avoiding version control entirely, means that youre walking a tightrope without a safety net. One accidental <tt><span>rsync</span></tt> in the wrong direction could destroy hours of work. </p>
<p> Using Mercurial with <tt><span>evolve</span></tt> to share mutable history solves these problems. As with single-repository <tt><span>evolve</span></tt>, you can commit whenever the code is demonstrably better, even if all the tests arent passing yet—just <tt><span>hg</span> <span>amend</span></tt> when they are. And you can transfer those half-baked changesets between repositories to try things out on your test server before anything is carved in stone. </p>
<p> A less common scenario is multiple developers sharing mutable history, typically for code review. Well cover this scenario later. First, we will cover single-user sharing. </p>
<div id="sharing-with-a-single-developer">
<h2>
<a href="#id5">Sharing with a single developer</a><a href="#sharing-with-a-single-developer" title="Permalink to this headline"></a>
</h2>
<div id="publishing-and-non-publishing-repositories">
<h3>
<a href="#id6">Publishing and non-publishing repositories</a><a href="#publishing-and-non-publishing-repositories" title="Permalink to this headline"></a>
</h3>
<p> The key to shared mutable history is to keep your changesets in <em>draft</em> phase as you pass them around. Recall that by default, <tt><span>hg</span> <span>push</span></tt> promotes changesets from <em>draft</em> to <em>public</em>, and public changesets are immutable. You can change this behaviour by reconfiguring the <em>remote</em> repository so that it is non-publishing. (Short version: set <tt><span>phases.publish</span></tt> to <tt><span>false</span></tt>. Long version follows.) </p>
</div>
<div id="setting-up">
<h3>
<a href="#id7">Setting up</a><a href="#setting-up" title="Permalink to this headline"></a>
</h3>
<p> Well work through an example with three local repositories, although in the real world theyd most likely be on three different computers. First, the <tt><span>public</span></tt> repository is where tested, polished changesets live, and it is where you synchronize with the rest of your team. </p>
<p> Well need two clones where work gets done, <tt><span>test-repo</span></tt> and <tt><span>dev-repo</span></tt>: </p>
<div>
<pre>$ hg clone public test-repo
updating to branch default
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg clone test-repo dev-repo
updating to branch default
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre>
</div>
<p>
<tt><span>dev-repo</span></tt> is your local machine, with GUI merge tools and IDEs and everything configured just the way you like it. <tt><span>test-repo</span></tt> is the test server in a rack somewhere behind SSH. So for the most part, well develop in <tt><span>dev-repo</span></tt>, push to <tt><span>test-repo</span></tt>, test and polish there, and push to <tt><span>public</span></tt>.
</p>
<p> The key to shared mutable history is to make the target repository, in this case <tt><span>test-repo</span></tt>, non-publishing. And, of course, we have to enable the <tt><span>evolve</span></tt> extension in both <tt><span>test-repo</span></tt> and <tt><span>dev-repo</span></tt>. </p>
<p> First, edit the configuration for <tt><span>test-repo</span></tt>: </p>
<div>
<pre>$ hg -R test-repo config --edit --local
</pre>
</div>
<p> and add </p>
<div>
<pre>[phases]
publish = false
[extensions]
evolve =
</pre>
</div>
<p> Then edit the configuration for <tt><span>dev-repo</span></tt>: </p>
<div>
<pre>$ hg -R dev-repo config --edit --local
</pre>
</div>
<p> and add </p>
<p> Keep in mind that in real life, these repositories would probably be on separate computers, so youd have to login to each one to configure each repository. </p>
<p> To start things off, lets make one public, immutable changeset: </p>
<div>
<pre>$ cd test-repo
$ echo 'my new project' &gt; file1
$ hg add file1
$ hg commit -m 'create new project'
$ hg push
[...]
added 1 changesets with 1 changes to 1 files
</pre>
</div>
<p> and pull that into the development repository: </p>
<div>
<pre>$ cd ../dev-repo
$ hg pull -u
[...]
added 1 changesets with 1 changes to 1 files
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre>
</div>
</div>
<div id="example-2-amend-again-locally">
<h3>
<a href="#id9">Example 2: Amend again, locally</a><a href="#example-2-amend-again-locally" title="Permalink to this headline"></a>
</h3>
<p> This process can repeat. Perhaps you figure out a more elegant fix to the bug, and want to mutate history so nobody ever knows you had a less-than-perfect idea. Well implement it locally in <tt><span>dev-repo</span></tt> and push to <tt><span>test-repo</span></tt>: </p>
<div>
<pre>$ echo 'Fix, fix, and fix.' &gt; file1
$ hg amend
$ hg push
</pre>
</div>
<p> This time around, the temporary amend commit is in <tt><span>dev-repo</span></tt>, and it is not transferred to <tt><span>test-repo</span></tt>—the same as before, just in the opposite direction. Figure 4 shows the two repositories after amending in <tt><span>dev-repo</span></tt> and pushing to <tt><span>test-repo</span></tt>. </p>
<blockquote>
<p> [figure SG04: each repo has one temporary amend commit, but theyre different in each one] </p>
</blockquote>
<p> Lets hop over to <tt><span>test-repo</span></tt> to test the more elegant fix: </p>
<div>
<pre>$ cd ../test-repo
$ hg update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre>
</div>
<p> This time, all the tests pass, so no further amending is required. This bug fix is finished, so we push it to the public repository: </p>
<div>
<pre>$ hg push
[...]
added 1 changesets with 1 changes to 1 files
</pre>
</div>
<p> Note that only one changeset—the final version, after two amendments—was actually pushed. Again, Mercurial doesnt transfer hidden changesets on push and pull. </p>
<p> So the picture in <tt><span>public</span></tt> is much simpler than in either <tt><span>dev-repo</span></tt> or <tt><span>test-repo</span></tt>. Neither of our missteps nor our amendments are publicly visible, just the final, beautifully polished changeset: </p>
<blockquote>
<p> [figure SG05: public repo with rev 0:0dc9, 1:de61, both public] </p>
</blockquote>
<p> There is one important step left to do. Because we pushed from <tt><span>test-repo</span></tt> to <tt><span>public</span></tt>, the pushed changeset is in <em>public</em> phase in those two repositories. But <tt><span>dev-repo</span></tt> has been out-of-the-loop; changeset de61 is still <em>draft</em> there. If were not careful, we might mutate history in <tt><span>dev-repo</span></tt>, obsoleting a changeset that is already public. Lets avoid that situation for now by pushing up to <tt><span>dev-repo</span></tt>: </p>
<div>
<pre>$ hg push ../dev-repo
pushing to ../dev-repo
searching for changes
no changes found
</pre>
</div>
<p> Even though no <em>changesets</em> were pushed, Mercurial still pushed obsolescence markers and phase changes to <tt><span>dev-repo</span></tt>. </p>
<p> A final note: since this fix is now <em>public</em>, it is immutable. Its no longer possible to amend it: </p>
<div>
<pre>$ hg amend -m 'fix bug 37'
abort: cannot amend public changesets
</pre>
</div>
<p> This is, after all, the whole point of Mercurials phases: to prevent rewriting history that has already been published. </p>
</div>
</div>
<div id="sharing-with-multiple-developers-code-review">
<h2>
<a href="#id10">Sharing with multiple developers: code review</a><a href="#sharing-with-multiple-developers-code-review" title="Permalink to this headline"></a>
</h2>
<p> Now that you know how to share your own mutable history across multiple computers, you might be wondering if it makes sense to share mutable history with others. It does, but you have to be careful, stay alert, and <em>communicate</em> with your peers. </p>
<p> Code review is a good use case for sharing mutable history across multiple developers: Alice commits a draft changeset, submits it for review, and amends her changeset until her reviewer is satisfied. Meanwhile, Bob is also committing draft changesets for review, amending until his reviewer is satisfied. Once a particular changeset passes review, the respective author (Alice or Bob) pushes it to the public (publishing) repository. </p>
<p> Incidentally, the reviewers here can be anyone: maybe Bob and Alice review each others work; maybe the same third party reviews both; or maybe they pick different experts to review their work on different parts of a large codebase. Similarly, it doesnt matter if reviews are conducted in person, by email, or by carrier pigeon. Code review is outside of the scope of Mercurial, so all were looking at here is the mechanics of committing, amending, pushing, and pulling. </p>
<div id="id2">
<h3>
<a href="#id11">Setting up</a><a href="#id2" title="Permalink to this headline"></a>
</h3>
<p> To demonstrate, lets start with the <tt><span>public</span></tt> repository as we left it in the last example, with two immutable changesets (figure 5 above). Well clone a <tt><span>review</span></tt> repository from it, and then Alice and Bob will both clone from <tt><span>review</span></tt>. </p>
<div>
<pre>$ hg clone public review
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg clone review alice
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg clone review bob
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre>
</div>
<p> We need to configure Alices and Bobs working repositories to enable <tt><span>evolve</span></tt>. First, edit Alices configuration with </p>
<div>
<pre>$ hg -R alice config --edit --local
</pre>
</div>
<p> and add </p>
<p> Then edit Bobs repository configuration: </p>
<div>
<pre>$ hg -R bob config --edit --local
</pre>
</div>
<p> and add the same text. </p>
</div>
<div id="example-3-alice-commits-and-amends-a-draft-fix">
<h3>
<a href="#id12">Example 3: Alice commits and amends a draft fix</a><a href="#example-3-alice-commits-and-amends-a-draft-fix" title="Permalink to this headline"></a>
</h3>
<p> Well follow Alice working on a bug fix. Were going to use bookmarks to make it easier to understand multiple branch heads in the <tt><span>review</span></tt> repository, so Alice starts off by creating a bookmark and committing her first attempt at a fix: </p>
<div>
<pre>$ hg bookmark bug15
$ echo 'fix' &gt; file2
$ hg commit -A -u alice -m 'fix bug 15 (v1)'
adding file2
</pre>
</div>
<p> Note the unorthodox “(v1)” in the commit message. Were just using that to make this tutorial easier to follow; its not something wed recommend in real life. </p>
<p> Of course Alice wouldnt commit unless her fix worked to her satisfaction, so it must be time to solicit a code review. She does this by pushing to the <tt><span>review</span></tt> repository: </p>
<div>
<pre>$ hg push -B bug15
[...]
added 1 changesets with 1 changes to 1 files
exporting bookmark bug15
</pre>
</div>
<p> (The use of <tt><span>-B</span></tt> is important to ensure that we only push the bookmarked head, and that the bookmark itself is pushed. See this <a href="http://mercurial.aragost.com/kick-start/en/bookmarks/">guide to bookmarks</a>, especially the <a href="http://mercurial.aragost.com/kick-start/en/bookmarks/#sharing-bookmarks">Sharing Bookmarks</a> section, if youre not familiar with bookmarks.) </p>
<p> Some time passes, and Alice receives her code review. As a result, Alice revises her fix and submits it for a second review: </p>
<div>
<pre>$ echo 'Fix.' &gt; file2
$ hg amend -m 'fix bug 15 (v2)'
$ hg push
[...]
added 1 changesets with 1 changes to 1 files (+1 heads)
updating bookmark bug15
</pre>
</div>
<p> Figure 6 shows the state of the <tt><span>review</span></tt> repository at this point. </p>
<blockquote>
<p> [figure SG06: rev 2:fn1e is Alices obsolete v1, rev 3:cbdf is her v2; both children of rev 1:de61] </p>
</blockquote>
<p> After a busy morning of bug fixing, Alice stops for lunch. Lets see what Bob has been up to. </p>
</div>
<div id="example-4-bob-implements-and-publishes-a-new-feature">
<h3>
<a href="#id13">Example 4: Bob implements and publishes a new feature</a><a href="#example-4-bob-implements-and-publishes-a-new-feature" title="Permalink to this headline"></a>
</h3>
<p> Meanwhile, Bob has been working on a new feature. Like Alice, hell use a bookmark to track his work, and hell push that bookmark to the <tt><span>review</span></tt> repository, so that reviewers know which changesets to review. </p>
<div>
<pre>$ cd ../bob
$ echo 'stuff' &gt; file1
$ hg bookmark featureX
$ hg commit -u bob -m 'implement feature X (v1)' # rev 4:1636
$ hg push -B featureX
[...]
added 1 changesets with 1 changes to 1 files (+1 heads)
exporting bookmark featureX
</pre>
</div>
<p> When Bob receives his code review, he improves his implementation a bit, amends, and submits the resulting changeset for review: </p>
<div>
<pre>$ echo 'do stuff' &gt; file1
$ hg amend -m 'implement feature X (v2)' # rev 5:0eb7
$ hg push
[...]
added 1 changesets with 1 changes to 1 files (+1 heads)
updating bookmark featureX
</pre>
</div>
<p> Unfortunately, that still doesnt pass muster. Bobs reviewer insists on proper capitalization and punctuation. </p>
<div>
<pre>$ echo 'Do stuff.' &gt; file1
$ hg amend -m 'implement feature X (v3)' # rev 6:540b
</pre>
</div>
<p> On the bright side, the second review said, “Go ahead and publish once you fix that.” So Bob immediately publishes his third attempt: </p>
<div>
<pre>$ hg push ../public
[...]
added 1 changesets with 1 changes to 1 files
</pre>
</div>
<p> Its not enough just to update <tt><span>public</span></tt>, though! Other people also use the <tt><span>review</span></tt> repository, and right now it doesnt have Bobs latest amendment (“v3”, revision 6:540b), nor does it know that the precursor of that changeset (“v2”, revision 5:0eb7) is obsolete. Thus, Bob pushes to <tt><span>review</span></tt> as well: </p>
<div>
<pre>$ hg push ../review
[...]
added 1 changesets with 1 changes to 1 files (+1 heads)
updating bookmark featureX
</pre>
</div>
<p> Figure 7 shows the result of Bobs work in both <tt><span>review</span></tt> and <tt><span>public</span></tt>. </p>
<blockquote>
<p> [figure SG07: review includes Alices draft work on bug 15, as well as Bobs v1, v2, and v3 changes for feature X: v1 and v2 obsolete, v3 public. public contains only the final, public implementation of feature X] </p>
</blockquote>
<p> Incidentally, its important that Bob push to <tt><span>public</span></tt> <em>before</em> <tt><span>review</span></tt>. If he pushed to <tt><span>review</span></tt> first, then revision 6:540b would still be in <em>draft</em> phase in <tt><span>review</span></tt>, but it would be <em>public</em> in both Bobs local repository and the <tt><span>public</span></tt> repository. That could lead to confusion at some point, which is easily avoided by pushing first to <tt><span>public</span></tt>. </p>
</div>
<div id="example-5-alice-integrates-and-publishes">
<h3>
<a href="#id14">Example 5: Alice integrates and publishes</a><a href="#example-5-alice-integrates-and-publishes" title="Permalink to this headline"></a>
</h3>
<p> Finally, Alice gets back from lunch and sees that the carrier pigeon with her second review has arrived (or maybe its in her email inbox). Alices reviewer approved her amended changeset, so she pushes it to <tt><span>public</span></tt>: </p>
<div>
<pre>$ hg push ../public
[...]
remote has heads on branch 'default' that are not known locally: 540ba8f317e6
abort: push creates new remote head cbdfbd5a5db2!
(pull and merge or see "hg help push" for details about pushing new heads)
</pre>
</div>
<p> Oops! Bob has won the race to push first to <tt><span>public</span></tt>. So Alice needs to integrate with Bob: lets pull his changeset(s) and see what the branch heads are. </p>
<div>
<pre>$ hg pull ../public
[...]
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
$ hg log -G -q -r 'head()' --template '{rev}:{node|short} ({author})\n'
o 5:540ba8f317e6 (bob)
|
| @ 4:cbdfbd5a5db2 (alice)
|/
</pre>
</div>
<p> Well assume Alice and Bob are perfectly comfortable with rebasing changesets. (After all, theyre already using mutable history in the form of <tt><span>amend</span></tt>.) So Alice rebases her changeset on top of Bobs and publishes the result: </p>
<div>
<pre>$ hg rebase -d 5
$ hg push ../public
[...]
added 1 changesets with 1 changes to 1 files
$ hg push ../review
[...]
added 1 changesets with 0 changes to 0 files
updating bookmark bug15
</pre>
</div>
<p> The result, in both <tt><span>review</span></tt> and <tt><span>public</span></tt> repositories, is shown in figure 8. </p>
<blockquote>
<p> [figure SG08: review shows v1 and v2 of Alices fix, then v1, v2, v3 of Bobs feature, finally Alices fix rebased onto Bobs. public just shows the final public version of each changeset] </p>
</blockquote>
</div>
</div>
<div id="getting-into-trouble-with-shared-mutable-history">
<h2>
<a href="#id15">Getting into trouble with shared mutable history</a><a href="#getting-into-trouble-with-shared-mutable-history" title="Permalink to this headline"></a>
</h2>
<p> Mercurial with <tt><span>evolve</span></tt> is a powerful tool, and using powerful tools can have consequences. (You can cut yourself badly with a sharp knife, but every competent chef keeps several around. Ever try to chop onions with a spoon?) </p>
<p> In the user guide, we saw examples of <em>unstbale</em> changesets, which are the most common type of troubled changeset. (Recall that a non-obsolete changeset with obsolete ancestors is an orphan.) </p>
<p> Two other types of troubles can happen: <em>divergent</em> and <em>bumped</em> changesets. Both are more likely with shared mutable history, especially mutable history shared by multiple developers. </p>
<div id="id3">
<h3>
<a href="#id16">Setting up</a><a href="#id3" title="Permalink to this headline"></a>
</h3>
<p> For these examples, were going to use a slightly different workflow: as before, Alice and Bob share a <tt><span>public</span></tt> repository. But this time there is no <tt><span>review</span></tt> repository. Instead, Alice and Bob put on their cowboy hats, throw good practice to the wind, and pull directly from each others working repositories. </p>
<p> So we throw away everything except <tt><span>public</span></tt> and reclone: </p>
<div>
<pre>$ rm -rf review alice bob
$ hg clone public alice
updating to branch default
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg clone public bob
updating to branch default
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre>
</div>
<p> Once again we have to configure their repositories: enable <tt><span>evolve</span></tt> and (since Alice and Bob will be pulling directly from each other) make their repositories non-publishing. Edit Alices configuration: </p>
<div>
<pre>$ hg -R alice config --edit --local
</pre>
</div>
<p> and add </p>
<div>
<pre>[extensions]
rebase =
evolve =
[phases]
publish = false
</pre>
</div>
<p> Then edit Bobs repository configuration: </p>
<div>
<pre>$ hg -R bob config --edit --local
</pre>
</div>
<p> and add the same text. </p>
</div>
<div id="example-6-divergent-changesets">
<h3>
<a href="#id17">Example 6: Divergent changesets</a><a href="#example-6-divergent-changesets" title="Permalink to this headline"></a>
</h3>
<p> When an obsolete changeset has two successors, those successors are <em>divergent</em>. One way to get into such a situation is by failing to communicate with your teammates. Lets see how that might happen. </p>
<p> First, well have Bob commit a bug fix that could still be improved: </p>
<div>
<pre>$ cd bob
$ echo 'pretty good fix' &gt;&gt; file1
$ hg commit -u bob -m 'fix bug 24 (v1)' # rev 4:2fe6
</pre>
</div>
<p> Since Alice and Bob are now in cowboy mode, Alice pulls Bobs draft changeset and amends it herself. </p>
<div>
<pre>$ cd ../alice
$ hg pull -u ../bob
[...]
added 1 changesets with 1 changes to 1 files
$ echo 'better fix (alice)' &gt;&gt; file1
$ hg amend -u alice -m 'fix bug 24 (v2 by alice)'
</pre>
</div>
<p> But Bob has no idea that Alice just did this. (See how important good communication is?) So he implements a better fix of his own: </p>
<div>
<pre>$ cd ../bob
$ echo 'better fix (bob)' &gt;&gt; file1
$ hg amend -u bob -m 'fix bug 24 (v2 by bob)' # rev 6:a360
</pre>
</div>
<p> At this point, the divergence exists, but only in theory: Bobs original changeset, 4:2fe6, is obsolete and has two successors. But those successors are in different repositories, so the trouble is not visible to anyone yet. It will be as soon as Bob pulls from Alices repository (or vice-versa). </p>
<div>
<pre>$ hg pull ../alice
[...]
added 1 changesets with 1 changes to 2 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
2 new divergent changesets
</pre>
</div>
<p> Figure 9 shows the situation in Bobs repository. </p>
<blockquote>
<p> [figure SG09: Bobs repo with 2 heads for the 2 divergent changesets, 6:a360 and 7:e3f9; wc is at 6:a360; both are successors of obsolete 4:2fe6, hence divergence] </p>
</blockquote>
<p> Now we need to get out of trouble. As usual, the answer is to evolve history. </p>
<div>
<pre>$ HGMERGE=internal:other hg evolve
merge:[6] fix bug 24 (v2 by bob)
with: [7] fix bug 24 (v2 by alice)
base: [4] fix bug 24 (v1)
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
</pre>
</div>
<p> Figure 10 shows how Bobs repository looks now. </p>
<blockquote>
<p> [figure SG10: only one visible head, 9:5ad6, successor to hidden 6:a360 and 7:e3f9] </p>
</blockquote>
<p> We carefully dodged a merge conflict by specifying a merge tool (<tt><span>internal:other</span></tt>) that will take Alices changes over Bobs. (You might wonder why Bob wouldnt prefer his own changes by using <tt><span>internal:local</span></tt>. Hes avoiding a <a href="#bug">bug</a> in <tt><span>evolve</span></tt> that occurs when evolving divergent changesets using <tt><span>internal:local</span></tt>.) </p>
<p> # XXX this link does not work .. <span id="bug">bug</span>: <a href="https://bitbucket.org/marmoute/mutable-history/issue/48/">https://bitbucket.org/marmoute/mutable-history/issue/48/</a>
</p>
<p> ** STOP HERE: WORK IN PROGRESS ** </p>
</div>
<div id="phase-divergence-when-a-rewritten-changeset-is-made-public">
<h3>
<a href="#id18">Phase-divergence: when a rewritten changeset is made public</a><a href="#phase-divergence-when-a-rewritten-changeset-is-made-public" title="Permalink to this headline"></a>
</h3>
<p> If Alice and Bob are collaborating on some mutable changesets, its possible to get into a situation where an otherwise worthwhile changeset cannot be pushed to the public repository; it is <em>phase-divergent</em> with another changeset that was made public first. Lets demonstrate one way this could happen. </p>
<p> It starts with Alice committing a bug fix. Right now, we dont yet know if this bug fix is good enough to push to the public repository, but its good enough for Alice to commit. </p>
<div>
<pre>$ cd alice
$ echo 'fix' &gt; file2
$ hg commit -A -m 'fix bug 15'
adding file2
</pre>
</div>
<p> Now Bob has a bad idea: he decides to pull whatever Alice is working on and tweak her bug fix to his taste: </p>
<div>
<pre>$ cd ../bob
$ hg pull -u ../alice
[...]
added 1 changesets with 1 changes to 1 files
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo 'Fix.' &gt; file2
$ hg amend -A -m 'fix bug 15 (amended)'
</pre>
</div>
<p> (Note the lack of communication between Alice and Bob. Failing to communicate with your colleagues is a good way to get into trouble. Nevertheless, <tt><span>evolve</span></tt> can usually sort things out, as we will see.) </p>
<blockquote>
<p> [figure SG06: Bobs repo with one amendment] </p>
</blockquote>
<p> After some testing, Alice realizes her bug fix is just fine as it is: no need for further polishing and amending, this changeset is ready to publish. </p>
<div>
<pre>$ cd ../alice
$ hg push
[...]
added 1 changesets with 1 changes to 1 files
</pre>
</div>
<p> This introduces a contradiction: in Bobs repository, changeset 2:e011 (his copy of Alices fix) is obsolete, since Bob amended it. But in Alices repository (and the <tt><span>public</span></tt> repository), that changeset is public: it is immutable, carved in stone for all eternity. No changeset can be both obsolete and public, so Bob is in for a surprise the next time he pulls from <tt><span>public</span></tt>: </p>
<div>
<pre>$ cd ../bob
$ hg pull -q -u
1 new phase-divergent changesets
</pre>
</div>
<p> Figure 7 shows what just happened to Bobs repository: changeset 2:e011 is now public, so it cant be obsolete. When that changeset was obsolete, it made perfect sense for it to have a successor, namely Bobs amendment of Alices fix (changeset 4:fe88). But its illogical for a public changeset to have a successor, so 4:fe88 is troubled: it has become <em>bumped</em>. </p>
<blockquote>
<p> [figure SG07: 2:e011 now public not obsolete, 4:fe88 now bumped] </p>
</blockquote>
<p> As usual when theres trouble in your repository, the solution is to evolve it: </p>
<p> Figure 8 illustrates Bobs repository after evolving away the bumped changeset. Ignoring the obsolete changesets, Bob now has a nice, clean, simple history. His amendment of Alices bug fix lives on, as changeset 5:227d—albeit with a software-generated commit message. (Bob should probably amend that changeset to improve the commit message.) But the important thing is that his repository no longer has any troubled changesets, thanks to <tt><span>evolve</span></tt>. </p>
<blockquote>
<p> [figure SG08: 5:227d is new, formerly bumped changeset 4:fe88 now hidden] </p>
</blockquote>
</div>
</div>
<div id="conclusion">
<h2>
<a href="#id19">Conclusion</a><a href="#conclusion" title="Permalink to this headline"></a>
</h2>
<p> Mutable history is a powerful tool. Like a sharp knife, an experienced user can do wonderful things with it, much more wonderful than with a dull knife (never mind a rusty spoon). At the same time, an inattentive or careless user can do harm to himself or others. Mercurial with <tt><span>evolve</span></tt> goes to great lengths to limit the harm you can do by trying to handle all possible types of “troubled” changesets. Nevertheless, having a first-aid kit nearby does not mean you should stop being careful with sharp knives. </p>
<p> Mutable history shared across multiple repositories by a single developer is a natural extension of this model. Once you are used to using a single sharp knife on its own, its pretty straightforward to chop onions and mushrooms using the same knife, or to alternate between two chopping boards with different knives. </p>
<p> Mutable history shared by multiple developers is a scary place to go. Imagine a professional kitchen full of expert chefs tossing their favourite knives back and forth, with the occasional axe or chainsaw thrown in to spice things up. If youre confident that you <em>and your colleagues</em> can do it without losing a limb, go for it. But be sure to practice a lot first before you rely on it! </p>
</div>
</div>
</div>