docs/sharing.rst
branchstable
changeset 1261 56cc2eb5995a
parent 1260 e8016d1011b5
child 1262 eff1acc2511c
equal deleted inserted replaced
1260:e8016d1011b5 1261:56cc2eb5995a
     5 ------------------------------
     5 ------------------------------
     6 
     6 
     7 .. contents::
     7 .. contents::
     8 
     8 
     9 Once you have mastered the art of mutable history in a single
     9 Once you have mastered the art of mutable history in a single
    10 repository (see the `user guide`_), you might want to move up to the
    10 repository (see the `user guide`_), you can move up to the next level:
    11 next level: *shared* mutable history. ``evolve`` lets you push and
    11 *shared* mutable history. ``evolve`` lets you push and pull draft
    12 pull draft changesets between repositories along with their
    12 changesets between repositories along with their obsolescence markers.
    13 obsolescence markers. This opens up a number of interesting
    13 This opens up a number of interesting possibilities.
    14 possibilities.
       
    15 
    14 
    16 .. _`user guide`: user-guide.html
    15 .. _`user guide`: user-guide.html
    17 
    16 
    18 The simplest scenario is a single developer working across two
    17 The simplest scenario is a single developer working across two
    19 computers. Say you're working on code that must be tested on a remote
    18 computers. Say you're working on code that must be tested on a remote
    36 than what came before.) The latter, avoiding version control entirely,
    35 than what came before.) The latter, avoiding version control entirely,
    37 means that you're walking a tightrope without a safety net. One
    36 means that you're walking a tightrope without a safety net. One
    38 accidental ``rsync`` in the wrong direction could destroy hours of
    37 accidental ``rsync`` in the wrong direction could destroy hours of
    39 work.
    38 work.
    40 
    39 
    41 Using Mercurial with ``evolve`` to share mutable history solves all of
    40 Using Mercurial with ``evolve`` to share mutable history solves these
    42 these problems. As with single-repository ``evolve``, you can commit
    41 problems. As with single-repository ``evolve``, you can commit
    43 whenever the code is demonstrably better, even if all the tests aren't
    42 whenever the code is demonstrably better, even if all the tests aren't
    44 passing yet—just ``hg amend`` when they are. And you can transfer
    43 passing yet—just ``hg amend`` when they are. And you can transfer
    45 those half-baked changesets between repositories to try things out on
    44 those half-baked changesets between repositories to try things out on
    46 your test server before anything is carved in stone.
    45 your test server before anything is carved in stone.
    47 
    46 
    64 follows.)
    63 follows.)
    65 
    64 
    66 Setting up
    65 Setting up
    67 ==========
    66 ==========
    68 
    67 
    69 We'll work an example with three local repositories, although in the
    68 We'll work through an example with three local repositories, although
    70 real world they'd most likely be on three different computers. First,
    69 in the real world they'd most likely be on three different computers.
    71 the ``public`` repository is where tested, polished changesets live,
    70 First, the ``public`` repository is where tested, polished changesets
    72 and it is where you synchronize changesets with the rest of your team.
    71 live, and it is where you synchronize with the rest of your team. ::
    73 ::
       
    74 
    72 
    75   $ hg init public
    73   $ hg init public
    76 
    74 
    77 We'll need two clones where work gets done::
    75 We'll need two clones where work gets done, ``test-repo`` and
       
    76 ``dev-repo``::
    78 
    77 
    79   $ hg clone public test-repo
    78   $ hg clone public test-repo
    80   updating to branch default
    79   updating to branch default
    81   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
    80   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
    82   $ hg clone test-repo dev-repo
    81   $ hg clone test-repo dev-repo
    87 everything configured just the way you like it. ``test-repo`` is the
    86 everything configured just the way you like it. ``test-repo`` is the
    88 test server in a rack somewhere behind SSH. So for the most part,
    87 test server in a rack somewhere behind SSH. So for the most part,
    89 we'll develop in ``dev-repo``, push to ``test-repo``, test and polish
    88 we'll develop in ``dev-repo``, push to ``test-repo``, test and polish
    90 there, and push to ``public``.
    89 there, and push to ``public``.
    91 
    90 
    92 The key to shared mutable history is to make the target repository,
    91 The key to shared mutable history is to make the target repository, in
    93 ``test-repo`` in this case, non-publishing. And, of course, we have to enable ``evolve`` in both ``test-repo`` and ``dev-repo``.
    92 this case ``test-repo``, non-publishing. And, of course, we have to
       
    93 enable ``evolve`` in both ``test-repo`` and ``dev-repo``.
    94 
    94 
    95 First, edit the configuration for ``test-repo``::
    95 First, edit the configuration for ``test-repo``::
    96 
    96 
    97   $ hg -R test-repo config --edit --local
    97   $ hg -R test-repo config --edit --local
    98 
    98 
   188 obsolete in ``test-repo``, having been replaced by revision 3:60ff
   188 obsolete in ``test-repo``, having been replaced by revision 3:60ff
   189 (revision 2:2a03 is another one of those temporary amend commits that
   189 (revision 2:2a03 is another one of those temporary amend commits that
   190 we saw in the user guide)—but ``dev-repo`` knows nothing of these
   190 we saw in the user guide)—but ``dev-repo`` knows nothing of these
   191 recent developments.
   191 recent developments.
   192 
   192 
   193   [figure SG02: rev 0:0dc9 public, rev 1:f649, 2:2a03 obsolete, rev 3:60ff draft -- but dev-repo same as in SG01]
   193   [figure SG02: test-repo has rev 0:0dc9 public, rev 1:f649, 2:2a03 obsolete, rev 3:60ff draft; dev-repo same as in SG01]
   194 
   194 
   195 Let's resynchronize::
   195 Let's resynchronize::
   196 
   196 
   197   $ cd ../dev-repo
   197   $ cd ../dev-repo
   198   $ hg pull -u
   198   $ hg pull -u
       
   199   [...]
       
   200   added 1 changesets with 1 changes to 1 files (+1 heads)
       
   201   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   199 
   202 
   200 As seen in figure 3, this transfers the new changeset *and* the
   203 As seen in figure 3, this transfers the new changeset *and* the
   201 obsolescence marker for revision 1. However, it does *not* transfer
   204 obsolescence marker for revision 1. However, it does *not* transfer
   202 the temporary amend commit, because it is obsolete. Push and pull
   205 the temporary amend commit, because it is hidden. Push and pull
   203 transfer obsolesence markers between repositories, but they do not
   206 transfer obsolesence markers between repositories, but they do not
   204 normally transfer obsolete changesets.
   207 transfer hidden changesets.
   205 
   208 
   206   [figure SG03: dev-repo grows new rev 2:60ff, marks 1:f649 obsolete]
   209   [figure SG03: dev-repo grows new rev 2:60ff, marks 1:f649 obsolete]
   207 
   210 
   208 Because of this deliberately incomplete synchronization, revision
   211 Because of this deliberately incomplete synchronization, revision
   209 numbers in ``test-repo`` and ``dev-repo`` are no longer consistent. We
   212 numbers in ``test-repo`` and ``dev-repo`` are no longer consistent. We
   240   $ hg push
   243   $ hg push
   241   [...]
   244   [...]
   242   added 1 changesets with 1 changes to 1 files
   245   added 1 changesets with 1 changes to 1 files
   243 
   246 
   244 Note that only one changeset—the final version, after two
   247 Note that only one changeset—the final version, after two
   245 amendments—was actually pushed. Again, Mercurial normally doesn't
   248 amendments—was actually pushed. Again, Mercurial doesn't transfer
   246 transfer obsolete changesets on push and pull. (Specifically, it
   249 hidden changesets on push and pull.
   247 doesn't transfer *hidden* changesets: roughly speaking, obsolete
       
   248 changesets with no non-obsolete descendants. If you're curious, see
       
   249 the `concept guide`_ for the precise definition of hidden.)
       
   250 
   250 
   251 .. _`concept guide`: concepts.html
   251 .. _`concept guide`: concepts.html
   252 
   252 
   253 So the picture in ``public`` is much simpler than in either
   253 So the picture in ``public`` is much simpler than in either
   254 ``dev-repo`` or ``test-repo``. None of our missteps or amendments are
   254 ``dev-repo`` or ``test-repo``. None of our missteps or amendments are
   264 public. Let's avoid that situation for now by pulling from
   264 public. Let's avoid that situation for now by pulling from
   265 ``test-repo`` down to ``dev-repo``::
   265 ``test-repo`` down to ``dev-repo``::
   266 
   266 
   267   $ cd ../dev-repo
   267   $ cd ../dev-repo
   268   $ hg pull -u
   268   $ hg pull -u
   269 
   269   [...]
   270 Sharing with multiple developers
   270   no changes found
   271 --------------------------------
   271 
       
   272 Even though no *changesets* were pulled, Mercurial still pulled
       
   273 obsolescence markers from ``test-repo``.
       
   274 
       
   275 Sharing with multiple developers: code review
       
   276 ---------------------------------------------
       
   277 
       
   278 Now that you know how to share your own mutable history across
       
   279 multiple computers, you might be wondering if it makes sense to share
       
   280 mutable history with others. It does, but you have to be careful, stay
       
   281 alert, and *communicate* with your peers.
       
   282 
       
   283 A good way to start is with code review: Alice commits a draft
       
   284 changeset that Bob can review. Bob sends his comments to Alice, and
       
   285 she amends it until Bob is satisfied. Meanwhile, Bob is also
       
   286 committing draft changesets for Alice to review, amending until she is
       
   287 satisfied. Once a particular changeset passes review, the respective
       
   288 author (Alice or Bob) pushes it to the public repository.
       
   289 
       
   290 Setting up
       
   291 ==========
       
   292 
       
   293 To demonstrate, let's start with the ``public`` repository as we left
       
   294 it in the last example, with two immutable changesets (figure 5
       
   295 above). We'll clone a ``review`` repository from it, and then Alice
       
   296 and Bob will both clone from ``review``. ::
       
   297 
       
   298   $ hg clone public review
       
   299   updating to branch default
       
   300   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
       
   301   $ hg clone review alice
       
   302   updating to branch default
       
   303   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
       
   304   $ hg clone review bob
       
   305   updating to branch default
       
   306   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
       
   307 
       
   308 We need to configure Alice's and Bob's working repositories similar to
       
   309 ``test-repo``, i.e. make them non-publishing and enable ``evolve``.
       
   310 First, edit Alice's configuration with ::
       
   311 
       
   312   $ hg -R alice config --edit --local
       
   313 
       
   314 and add ::
       
   315 
       
   316   [extensions]
       
   317   evolve = /path/to/mutable-history/hgext/evolve.py
       
   318 
       
   319 Then add the same text to Bob's repository configuration::
       
   320 
       
   321   $ hg -R bob config --edit --local
       
   322 
       
   323 Example 3: Alice commits and amends a draft fix
       
   324 ===============================================
       
   325 
       
   326 We'll start by following Alice working on a bug fix. We're going to
       
   327 use bookmarks to make it easier to understand multiple branch heads in
       
   328 the ``review`` repository, so Alice starts off by creating a bookmark
       
   329 and committing her first attempt at a fix::
       
   330 
       
   331   $ hg bookmark bug15
       
   332   $ echo 'fix' > file2
       
   333   $ hg commit -A -u alice -m 'fix bug 15 (v1)'
       
   334   adding file2
       
   335 
       
   336 Note the unorthodox "(v1)" in the commit message. We're just using
       
   337 that to make this tutorial easier to follow; it's not something we'd
       
   338 recommend in real life.
       
   339 
       
   340 Of course Alice wouldn't commit unless her fix worked to her
       
   341 satisfaction, so it must be time to solicit a code review. She does
       
   342 this by pushing to the ``review`` repository::
       
   343 
       
   344   $ hg push -B bug15
       
   345   [...]
       
   346   added 1 changesets with 1 changes to 1 files
       
   347   exporting bookmark bug15
       
   348 
       
   349 (The use of ``-B`` is important to ensure that we only push the
       
   350 bookmarked head, and that the bookmark itself is pushed. See this
       
   351 `guide to bookmarks`_, especially the `Sharing Bookmarks`_ section, if
       
   352 you're not familiar with bookmarks.)
       
   353 
       
   354 .. _`guide to bookmarks`: http://mercurial.aragost.com/kick-start/en/bookmarks/
       
   355 .. _`Sharing Bookmarks`: http://mercurial.aragost.com/kick-start/en/bookmarks/#sharing-bookmarks
       
   356 
       
   357 Some time passes, and Alice receives her code review. (It might be by
       
   358 email, telephone, or carrier pigeon: it doesn't matter, as it's
       
   359 outside the scope of Mercurial.) As a result, Alice revises her fix
       
   360 and submits it for a second review::
       
   361 
       
   362   $ echo 'Fix.' > file2
       
   363   $ hg amend -m 'fix bug 15 (v2)'
       
   364   $ hg push
       
   365   [...]
       
   366   added 1 changesets with 1 changes to 1 files (+1 heads)
       
   367   updating bookmark bug15
       
   368 
       
   369 Figure 6 shows the state of the ``review`` repository at this point.
       
   370 
       
   371   [figure SG06: rev 2:fn1e is alice's obsolete v1, rev 3:cbdf is her v2; both children of rev 1:de61]
       
   372 
       
   373 After a hard morning of bug fixing, Alice stops for lunch. Let's see
       
   374 what Bob has been up to.
       
   375 
       
   376 Example 4: Bob implements and publishes a new feature
       
   377 =====================================================
       
   378 
       
   379 In the meantime, Bob has been working on a new feature. Like Alice,
       
   380 he'll use a bookmark to track his work, and he'll push that bookmark
       
   381 to the ``review`` repository, so that reviewers know which changesets
       
   382 to review. ::
       
   383 
       
   384   $ cd ../bob
       
   385   $ echo 'stuff' > file1
       
   386   $ hg bookmark featureX
       
   387   $ hg commit -u bob -m 'implement feature X (v1)'
       
   388   $ hg push -B featureX
       
   389   [...]
       
   390   added 1 changesets with 1 changes to 1 files (+1 heads)
       
   391   exporting bookmark featureX
       
   392 
       
   393 When Bob receives his code review, he improves his implementation a
       
   394 bit, amends, and submits the resulting changeset for review::
       
   395 
       
   396   $ echo 'do stuff' > file1
       
   397   $ hg amend -m 'implement feature X (v2)'
       
   398   $ hg push
       
   399   [...]
       
   400   added 1 changesets with 1 changes to 1 files (+1 heads)
       
   401   updating bookmark featureX
       
   402 
       
   403 Unfortunately, that still doesn't pass muster. Bob's reviewer insists
       
   404 on proper capitalization and punctuation. ::
       
   405 
       
   406   $ echo 'Do stuff.' > file1
       
   407   $ hg amend -m 'implement feature X (v3)'
       
   408 
       
   409 On the bright side, the second review said, "Go ahead and publish once
       
   410 you fix that." So Bob immediately publishes his third attempt::
       
   411 
       
   412   $ hg push ../public
       
   413   [...]
       
   414   added 1 changesets with 1 changes to 1 files
       
   415 
       
   416 Bob also has to update the ``review`` repository: right now it doesn't
       
   417 have his latest amendment ("v3", revision 6:540b), and it doesn't know
       
   418 that the precursor of that changeset ("v2", revision 5:0eb7) is
       
   419 obsolete. ::
       
   420 
       
   421   $ hg push ../review
       
   422   [...]
       
   423   added 1 changesets with 1 changes to 1 files (+1 heads)
       
   424   updating bookmark featureX
       
   425 
       
   426 Figure 7 shows the result of Bob's work in both ``review`` and
       
   427 ``public``.
       
   428 
       
   429   [figure SG07: review includes alice's draft work on bug 15, as well as Bob's v1, v2, and v3 changes for feature X: v1 and v2 obsolete, v3 public. public contains only the final, public implementation of feature X]
       
   430 
       
   431 Incidentally, it's important that Bob push to ``public`` *before*
       
   432 ``review``. If he pushed to ``review`` first, then revision 6:540b
       
   433 would still be in *draft* phase in ``review``, but it would be
       
   434 *public* in both Bob's local repository and the ``public`` repository.
       
   435 That could lead to confusion at some point, which is easily avoided by
       
   436 pushing first to ``public``.
       
   437 
       
   438 Example 5: Alice integrates and publishes
       
   439 =========================================
       
   440 
       
   441 Finally, Alice gets back from lunch and sees that the carrier pigeon
       
   442 with her second review has arrived (or maybe she just has it in her
       
   443 email inbox). Alice's amended changeset has passed review, so she
       
   444 pushes her fix to ``public``::
       
   445 
       
   446   $ hg push ../public
       
   447   [...]
       
   448   remote has heads on branch 'default' that are not known locally: 540ba8f317e6
       
   449   abort: push creates new remote head cbdfbd5a5db2!
       
   450   (pull and merge or see "hg help push" for details about pushing new heads)
       
   451 
       
   452 Oops! Bob has won the race to push first to ``public``. So Alice needs
       
   453 to integrate with Bob: let's pull his changeset(s) and see what the
       
   454 branch heads are. ::
       
   455 
       
   456   $ hg pull ../public
       
   457   [...]
       
   458   added 1 changesets with 1 changes to 1 files (+1 heads)
       
   459   (run 'hg heads' to see heads, 'hg merge' to merge)
       
   460   $ hg log -G -q -r 'head()' --template '{rev}:{node|short}  ({author})\n'
       
   461   o  5:540ba8f317e6  (bob)
       
   462   |
       
   463   | @  4:cbdfbd5a5db2  (alice)
       
   464   |/
       
   465 
       
   466 Since Alice and Bob are already using advanced technology in the form
       
   467 of shared mutable history, we'll assume they are perfectly comfortable
       
   468 with rebasing changesets. So Alice rebases her changeset on top of
       
   469 Bob's and publishes the result::
       
   470 
       
   471   $ hg rebase -d 5
       
   472   $ hg push ../public
       
   473   [...]
       
   474   added 1 changesets with 1 changes to 1 files
       
   475   $ hg push ../review
       
   476   [...]
       
   477   added 1 changesets with 0 changes to 0 files
       
   478   updating bookmark bug15
       
   479 
       
   480 The result, in both ``review`` and ``public`` repositories, is shown
       
   481 in figure 8.
       
   482 
       
   483   [figure SG08: review shows v1 and v2 of alice's fix, then v1, v2, v3 of bob's feature, finally alice's fix rebased onto bob's. public just shows the final public version of each changeset]
       
   484 
       
   485 
       
   486 ** STOP HERE: WORK IN PROGRESS **
       
   487 
       
   488 
       
   489 Getting into trouble with shared mutable history
       
   490 ------------------------------------------------
   272 
   491 
   273 Mercurial with ``evolve`` is a powerful tool, and using powerful tools
   492 Mercurial with ``evolve`` is a powerful tool, and using powerful tools
   274 can have consequences. (You can cut yourself badly with a sharp knife,
   493 can have consequences. (You can cut yourself badly with a sharp knife,
   275 but every competent chef keeps several around. Ever try to chop onions
   494 but every competent chef keeps several around. Ever try to chop onions
   276 with a spoon?)
   495 with a spoon?)
   280 non-obsolete changeset with obsolete ancestors is unstable.)
   499 non-obsolete changeset with obsolete ancestors is unstable.)
   281 
   500 
   282 Two other types of trouble can crop up: *bumped* and *divergent*
   501 Two other types of trouble can crop up: *bumped* and *divergent*
   283 changesets. Both are more likely with shared mutable history,
   502 changesets. Both are more likely with shared mutable history,
   284 especially mutable history shared by multiple developers.
   503 especially mutable history shared by multiple developers.
   285 
       
   286 Setting up
       
   287 ==========
       
   288 
       
   289 To demonstrate, let's start with the ``public`` repository as we left
       
   290 it in the last example, with two immutable changesets (figure 5
       
   291 above). Two developers, Alice and Bob, start working from this point::
       
   292 
       
   293   $ hg clone public alice
       
   294   updating to branch default
       
   295   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
       
   296   $ hg clone public bob
       
   297   updating to branch default
       
   298   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
       
   299 
       
   300 We need to configure Alice's and Bob's working repositories similar to
       
   301 ``test-repo``, i.e. make them non-publishing and enable ``evolve``::
       
   302 
       
   303   $ cat >> alice/.hg/hgrc <<EOF
       
   304   [phases]
       
   305   publish = false
       
   306   [extensions]
       
   307   evolve = /path/to/mutable-history/hgext/evolve.py
       
   308   EOF
       
   309   $ cp alice/.hg/hgrc bob/.hg/hgrc
       
   310 
   504 
   311 Bumped changesets: only one gets on the plane
   505 Bumped changesets: only one gets on the plane
   312 =============================================
   506 =============================================
   313 
   507 
   314 If two people show up at the airport with tickets for the same seat on
   508 If two people show up at the airport with tickets for the same seat on