Source

kick-start_fork / src / basic / index.txt

The default branch has multiple heads

Full commit
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
.. -*- rst -*-

.. Mercurial Kick Start: http://mercurial.aragost.com/kick-start/
..
.. Copyright 2010 aragost Trifork
..
.. This software may be used and distributed according to the terms of
.. the GNU General Public License version 2 or any later version.

.. include:: ../common.rst

===============
Basic Mercurial
===============

We will begin with the basics of Mercurial. We believe the best way to
learn is to do things yourself, so we encourage you to follow along
and execute the commands you see "Alice" and "Bob" execute. You can
tell who is executing the command by the color of their terminal:
Alice has a pale peach colored terminal, Bob has a pale turquoise
color, and Carla (introduced later) has a lavender color.

There are also some exercises later that cover the same things that
Alice and Bob did.

.. contents::

Installation & Configuration
============================

Mercurial is available for most platforms, including Windows, Mac OS
X, and GNU/Linux:

Windows:
  Please only install TortoiseHg_, which gives you a complete
  installation with Mercurial and a set of graphical tools for
  examining and manipulating the repository.

  After installation, you will have a right-click menu in Windows
  Explorer that gives you access to the graphical tools. After logging
  out and in again, you will also have a `hg` and a `thg` program
  available in a Command Prompt. You can use the `thk` program to
  start the graphical TortoiseHg tools.

  .. tip::

     While the examples will use a few Unix commands, you can easily
     translate them back to the equivalent commands for the Command
     Prompt::

       ls          -> dir
       cat         -> type
       echo "abc"  -> echo abc

Linux:
  Please install Mercurial_ using your package manager. If you cannot
  find it there, then you can install from source: grab the `latest
  stable release`__, unpack it somewhere and run ``make local``
  inside. Now symlink the `hg` script to a directory in your ``PATH``
  and you are done.

  To install TortoiseHg, you need the PyQt bindings. They are
  available in most distributions. Then follow `these instructions`__.
  That gives you the `thg` program.

  .. __: http://selenic.com/hg/archive/stable.tar.bz2
  .. __: http://bitbucket.org/tortoisehg/thg/wiki/thg

Mac OS X:
  We recommend installing recommend MacHg_ to get a good, fast, and
  native client for Mercurial. MacHg comes bundled with its own
  Mercurial so you won't have to worry about that. If you already use
  TortoiseHg on Windows, then you'll be happy to know that you can now
  `install it on Mac OS X`__ too.

  .. __: https://bitbucket.org/tortoisehg/thg/wiki/developers/MacOSX

.. _Mercurial: http://mercurial.selenic.com/
.. _TortoiseHg: http://tortoisehg.org/
.. _MacHg: http://jasonfharris.com/machg/

We will be using the command line in our examples but will sometime
show the repository state in the TortoiseHg Workbench.

After installing Mercurial, try running `hg version`:


.. shelltest::
   :name: alice

   $ hg version
   Mercurial Distributed SCM (version 2.2)
   (see http://mercurial.selenic.com for more information)

   Copyright (C) 2005-2012 Matt Mackall and others
   This is free software; see the source for copying conditions. There is NO
   warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

It is of course fine if you see a version number greater than 2.2.
Mercurial 1.4 is also okay for our purposes, but we always recommend
upgrading to the newest version available for your platform. You can
verify your installation with:

.. shelltest::
   :name: alice

   $ hg debuginstall ## \
     | sed -e 's|modules .*|modules (/usr/share/pyshared/mercurial)...|' \
           -e 's|templates .*|templates (/usr/lib/python2.7/dist-packages/mercurial)...|'
   Checking encoding (UTF-8)...
   Checking installed modules (/usr/share/pyshared/mercurial)...
   Checking templates (/usr/lib/python2.7/dist-packages/mercurial)...
   Checking commit editor...
   Checking username...
    no username supplied (see "hg help config")
    (specify a username in your configuration file)
   1 problems detected, please check your install!

The username is normally missing immediately after installation. You
set it by putting the name in a configuration file. On Unix-like
systems this is ``$HOME/.hgrc`` and on Windows the file is called
``%HOME%\Mercurial.ini`` (see `hg help config` for all locations or
use `thg userconfig` if you prefer). Create the file with this
content::

   [ui]
   username = Firstname Lastname <example@example.net>

but with your own name. We will use ``Alice <alice@example.net>``
first and her terminals look like the two you saw above. Running `hg
debuginstall` should no longer report any problems.

.. shelltest::
   :name: alice

   $ ##echo "[ui]" >> $HGRCPATH
   $ ##echo "username = Alice <alice@example.net>" >> $HGRCPATH


Basic Commands
==============

We will now make a swift tour through the basic commands. These are
all similar to older systems such as Subversion or even CVS. If you
are using TortoiseHg under Windows, then you might want to also refer
to their `quick start guide`_.

.. _quick start guide: http://tortoisehg.bitbucket.org/manual/1.0/quick.html

Creating a Repository
---------------------

Create a repository with the `hg init` command:

.. shelltest::
   :name: alice

   $ ls
   $ hg init example
   $ ls
   example

The `hg init` command created a new directory which is the new
repository. We could also have made the ``example`` directory
ourselves and issued a blank `hg init` inside that directory to turn
it into a repository.

Entering ``example`` we can look around:

.. shelltest::
   :name: alice

   $ cd example
   $ ls -a
   .
   ..
   .hg

As you can see, the new repository is empty except for a ``.hg``
directory in the repository root. Mercurial stores the history and
some other administrative files inside this directory.

Creating a Changeset
--------------------

Let us create a file and ask Mercurial about the status of the
repository:

.. shelltest::
   :name: alice

   $ echo "Hello World" > hello.txt
   $ hg status
   ? hello.txt

The reply tells us that ``hello.txt`` is unknown to Mercurial, i.e.,
it is not yet tracked. We can add the file:

.. shelltest::
   :name: alice

   $ hg add hello.txt
   $ hg status
   A hello.txt

which changes the status to "A" for "added". The file is not yet
stored in the repository history --- we'll do this by making a commit:

.. shelltest::
   :name: alice

   $ hg commit -m "First version of hello"## -d "2010-03-10 20:10:05"

No output indicates success --- Mercurial wont interrupt you unless
necessary.

Inspecting History
------------------

You can see the newly created changeset with `hg log`:

.. shelltest::
   :name: alice

   $ hg log
   changeset:   0:d312da7770f4
   tag:         tip
   user:        Alice <alice@example.net>
   date:        Wed Mar 10 20:10:05 2010 +0000
   summary:     First version of hello

Success, you have made a commit with Mercurial! Let us modify the file
and ask Mercurial to show us how the files in working copy differ from
the last revision:

.. shelltest::
   :name: alice

   $ echo "Goodbye!" > hello.txt
   $ hg diff## | sed -e 's|\+\+\+ b/hello\.txt.*'\
                         '|+++ b/hello.txt Mon Mar 10 20:10:10 2010 +0000|'
   diff -r d312da7770f4 hello.txt
   --- a/hello.txt Wed Mar 10 20:10:05 2010 +0000
   +++ b/hello.txt Mon Mar 10 20:10:10 2010 +0000
   @@ -1,1 +1,1 @@
   -Hello World
   +Goodbye!

We can change our mind and revert the file back to how it looked
before:

.. shelltest::
   :name: alice

   $ hg revert hello.txt
   $ cat hello.txt
   Hello World

Let us make another change to our file:

.. shelltest::
   :name: alice

   $ echo >> hello.txt
   $ echo "by Alice." >> hello.txt
   $ hg commit -m "Added author." ## -d "2010-03-10 20:15:00"

We can now ask Mercurial to annotate the file, that is, to show when
each line was last modified:

.. shelltest::
   :name: alice

   $ hg annotate hello.txt
   0: Hello World
   1:
   1: by Alice.

Quite right, Mercurial tells us that the first line is from revision
0, and that the two final lines are from revision 1. TortoiseHg offers
a very nice interactive annotate tool, see `thg annotate`.

Annotating files is an invaluable help when fixing bugs: after finding
the bug, you can use `hg annotate` to find out when the offending line
was introduced in your file. Then use `hg log` to retrieve the
associated commit message, which can hopefully explain what the
committer was trying to do when he changed the line:

.. shelltest::
   :name: alice

   $ hg log -r 1
   changeset:   1:2e982bdc137f
   tag:         tip
   user:        Alice <alice@example.net>
   date:        Wed Mar 10 20:15:00 2010 +0000
   summary:     Added author.

The two changesets in our repository are in sequence. This is best
illustrated with the help of the standard `graphlog extension`__. To
keep the core of Mercurial slim, a lot of functionality is delegated
to extensions. Many of the best extensions are shipped with Mercurial
and they are easy to enable. To enable graphlog, Alice simply adds::

  [extensions]
  graphlog =

.. __: http://mercurial.selenic.com/wiki/GraphlogExtension

to her configuration file. She can then run `hg help graphlog` to
learn more about the extension. This extension is particularly simple,
it just gives Alice a new command:

.. shelltest::
   :name: alice

   $ ##echo '[extensions]'                                  >> $HGRCPATH
   $ ##echo 'graphlog ='                                    >> $HGRCPATH
   $ hg glog
   @  changeset:   1:2e982bdc137f
   |  tag:         tip
   |  user:        Alice <alice@example.net>
   |  date:        Wed Mar 10 20:15:00 2010 +0000
   |  summary:     Added author.
   |
   o  changeset:   0:d312da7770f4
      user:        Alice <alice@example.net>
      date:        Wed Mar 10 20:10:05 2010 +0000
      summary:     First version of hello
   $ ## snap-tortoisehg "$DSTDIR/alice-log.png"

This shows how the changeset ``2e982bdc137f`` is a child of
``d312da7770f4``. The same can be seen in `thg log`:

.. image:: alice-log.png
   :align: center

The files in the working copy are always synchronized to a particular
changeset. In `thg log`, this is shown with a circled bullet in the
changeset graph. In the output of `hg glog`, the working directory
parent revision is highlighted with a ``@``-sign.

Time Travel
-----------

You can change the working copy parent revision with the `hg update`
command. This is useful to go back and examine old versions of your
code, for instance if you need to test an old version of your software
with a new operating system. Here Alice will just go back to revision
0 to look at her old file. She first uses the `hg parents` command to
ascertain where she is in the graph:

.. shelltest::
   :name: alice

   $ hg parents
   changeset:   1:2e982bdc137f
   tag:         tip
   user:        Alice <alice@example.net>
   date:        Wed Mar 10 20:15:00 2010 +0000
   summary:     Added author.

and she then makes the jump:

.. shelltest::
   :name: alice

   $ hg update 0
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg parents
   changeset:   0:d312da7770f4
   user:        Alice <alice@example.net>
   date:        Wed Mar 10 20:10:05 2010 +0000
   summary:     First version of hello

Her file is now back at the old version:

.. shelltest::
   :name: alice

   $ cat hello.txt
   Hello World

but the newer version is not forgotten. Mercurial can easily retrieve
it for her:

.. shelltest::
   :name: alice

   $ hg cat -r 1 hello.txt
   Hello World

   by Alice.

The `hg cat` command is useful to quickly see old versions of files
instead of using `hg update` to change the entire working directory to
an old version. Going back to the tip revision is easy, just do `hg
update` without an argument:

.. shelltest::
   :name: alice

   $ hg update
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cat hello.txt
   Hello World

   by Alice.


Exercises
---------

1. Use `hg init` to create a repository called ``kick-start``.

2. Enter ``kick-start`` and create a couple of files. Schedule them
   for addition with `hg add`. You can use `hg revert` to cancel a
   pending addition if you change your mind.

3. Use `hg commit` to commit the files. An editor will be started if
   you do not specify a commit message on the command line.

4. Make a couple of more commits.

5. Use `hg update` to update the working directory to an older
   revision. Notice how the output of `hg parents` changes to match
   and compare this with `hg tip`, which stays fixed then you use `hg
   update`.

6. Try making a commit when the working parent is an old revision. You
   will be told that you have created a new "head" --- a head is a
   changeset without any children. Use `hg heads` to see the
   repository heads and look at the graph in `thg log`.

   Notice how the newly created changeset has the changeset listed
   previously in `hg parents` as its parent changeset. This is an
   invariant in Mercurial: the working copy parent revision becomes
   the parent revision of the next changeset.

7. Multiple heads represent multiple divergent lines of development.
   You will normally merge these lines using `hg merge`. If your
   changes do not overlap, then the merge will be easy. Otherwise you
   will have to resolve the conflicts --- more about this later.

   Notice how `hg parents` print two changesets after you issued `hg
   merge`. Again, this means that the next commit will have two
   parents. You can see the parents in `hg glog` or `thg log` after
   you commit.


Working with Others
===================

Right now Alice's repository is in her home directory. Her co-worker,
Bob, also needs to work on the project. We will show his commands with
a light blue background color.

Making a Clone
--------------

In these examples, we will let Alice and Bob share a local filesystem.
This could very well be a company-wide network filesystem. Changes can
also be shared over SSH and HTTP connections --- people even use emails
or USB sticks to move around changesets. They then typically use a
compressed binary format produced by the `hg bundle` command. This is
not necessary here, instead Bob uses `hg clone` with a relative path
to Alice's repository:

.. shelltest::
   :name: bob

   $ ## echo "[ui]" >> $HGRCPATH
   $ ## echo "username = Bob <bob@example.net>" >> $HGRCPATH
   $ ## echo "[extensions]" >> $HGRCPATH
   $ ## echo "graphlog =" >> $HGRCPATH
   $ hg clone ../alice/example
   destination directory: example
   updating to branch default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved

Bob now has his own fully independent copy of Alice's repository. He
can make such a clone as long as he has read access to Alice's files.
Bob can make his own changesets in his clone, without affecting Alice.
He makes a couple of changes:

.. shelltest::
   :name: bob

   $ cd example
   $ echo "Goodbye!" > goodbye.txt
   $ echo >> goodbye.txt
   $ echo "by Bob." >> goodbye.txt
   $ hg add
   adding goodbye.txt
   $ hg commit -m "My goodbye file." ## -d "2010-03-11 10:00:00"
   $ echo >> hello.txt
   $ echo "not by Bob." >> hello.txt
   $ hg commit -m "Not my file." ## -d "2010-03-11 10:03:00"
   $ ## snap-tortoisehg "$DSTDIR/bob-log.png"

The repository now has four changesets:

.. image:: bob-log.png
   :align: center

Comparing Clones
----------------

The clone knows where it originates from and Bob can ask if there are
any changesets in Alice's clone that he does not already have:

.. shelltest::
   :name: bob

   $ hg incoming
   comparing with /home/alice/example
   searching for changes
   no changes found

He can also ask Mercurial what changeset he has that Alice lacks:

.. shelltest::
   :name: bob

   $ hg outgoing
   comparing with /home/alice/example
   searching for changes
   changeset:   2:659410363fe0
   user:        Bob <bob@example.net>
   date:        Thu Mar 11 10:00:00 2010 +0000
   summary:     My goodbye file.

   changeset:   3:51b2976b01e8
   tag:         tip
   user:        Bob <bob@example.net>
   date:        Thu Mar 11 10:03:00 2010 +0000
   summary:     Not my file.

This hopefully makes sense: Bob created two new changesets in his own
clone, so Alice does not have them yet.

Moving Changesets
-----------------

Bob does not have write access to the files in Alice's home directory,
so he cannot write his changesets to her clone. But he lets her know
that he has made a clone and asks her to retrieve the changesets. She
does this with the `hg pull` command. Before using the command, she
enters the path to Bob's clone in the ``.hg/hgrc`` file. This a
repository-local configuration file. She enters::

  [paths]
  default = /home/bob/example

to make Bob's clone the default target when doing `hg pull` and other
commands that involve a remote repository. She can see what will be
pulled with `hg incoming`:

.. shelltest::
   :name: alice

   $ ## echo "[paths]" > .hg/hgrc
   $ ## echo "default = /home/bob/example" >> .hg/hgrc
   $ hg incoming
   comparing with /home/bob/example
   searching for changes
   changeset:   2:659410363fe0
   user:        Bob <bob@example.net>
   date:        Thu Mar 11 10:00:00 2010 +0000
   summary:     My goodbye file.

   changeset:   3:51b2976b01e8
   tag:         tip
   user:        Bob <bob@example.net>
   date:        Thu Mar 11 10:03:00 2010 +0000
   summary:     Not my file.

Notice how this is symmetric to when Bob executed `hg outgoing` in his
clone. She decides to go ahead and pull Bob's changes:

.. shelltest::
   :name: alice

   $ hg pull
   pulling from /home/bob/example
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files
   (run 'hg update' to get a working copy)
   $ ## snap-tortoisehg "$DSTDIR/alice-pull.png"

The final message is a hint to Alice to her know that her working copy
parent revision has not changed:

.. image:: alice-pull.png
   :align: center

The parent revision is unchanged since Alice may have been working on
a change of her own, and so she might not be interested in updating
right away. In this case she does update:


.. shelltest::
   :name: alice

   $ hg update
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved

You will almost always want to run `hg update` after `hg pull` and for
this reason, there is a shortcut: `hg pull -u` will automatically
update after pulling in new changes.

Divergent Lines of Development
------------------------------

Alice reworks the ``hello.txt`` file a bit:

.. shelltest::
   :name: alice

   $ ## sed -i -e 's|Hello World|Hello, Wonderful World!|' hello.txt
   $ hg diff## | sed -e 's|\+\+\+ b/hello\.txt.*'\
                         '|+++ b/hello.txt Thu Mar 11 11:00:00 2010 +0000|'
   diff -r 51b2976b01e8 hello.txt
   --- a/hello.txt Thu Mar 11 10:03:00 2010 +0000
   +++ b/hello.txt Thu Mar 11 11:00:00 2010 +0000
   @@ -1,4 +1,4 @@
   -Hello World
   +Hello, Wonderful World!

    by Alice.
   $ hg commit -m "Happy, happy!" ## -d "2010-03-11 11:05:00"

At the same time, Bob is working. He creates a new file:

.. shelltest::
   :name: bob

   $ echo "Welcome!" > welcome.txt
   $ hg add
   adding welcome.txt
   $ hg commit -m "Welcome file." ## -d "2010-03-11 11:04:00"

Both Alice and Bob have now made a changeset that is a child of
``51b2976b01e8``, but neither of them knows about this since they have
not yet pulled or pushed the changes anywhere.  Alice decides to pull
from Bob:

.. shelltest::
   :name: alice

   $ hg pull
   pulling from /home/bob/example
   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)
   $ ## snap-tortoisehg "$DSTDIR/alice-heads.png"

What happened? As mentioned above, a "head" changeset is a changeset
without any children. Since Alice and Bob have made *different*
changes based on ``51b2976b01e8``, there are now two changesets in the
repository without any children. These heads are divergent lines of
development, as can be seen in `thg log`:

.. image:: alice-heads.png
   :align: center

The two lines of development should be reconciled, and the `hg merge`
command is the way to do that:

.. shelltest::
   :name: alice

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

There were no conflicts since Alice and Bob edited different files.
After `hg merge`, the working copy has *two* parents --- this is how you
can tell that a merge is in progress if you have left your
computer and forgotten about it. The merge is not yet committed since
you might need to edit the files to make your code compile. Just
because there were no overlapping edits (no conflicts), there might
still be some semantic conflicts which Mercurial cannot detect. It is
therefore a good idea to run the test suite after a merge. In our
case, Alice goes ahead with the commit:

.. shelltest::
   :name: alice

   $ hg commit -m "Merge with Bob." ## -d "2010-03-11 11:10:00"
   $ ## snap-tortoisehg "$DSTDIR/alice-merged.png"

The two heads are now bound together in the changeset graph:

.. image:: alice-merged.png
   :align: center

The merge changeset contains changes from both of its parent
revisions. You should think of a merge changeset as your way of saying
to the world: this is how you should combine changeset ``X`` with
changeset ``Y``. When others pull the merge changeset from your
repository, it will go into the right place in their changeset graph.
They will therefore not have to do the same merge. We can see this if
we let Bob pull from Alice:

.. shelltest::
   :name: bob

   $ hg pull
   pulling from /home/alice/example
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 2 changesets with 1 changes to 1 files
   (run 'hg update' to get a working copy)
   $ ## snap-tortoisehg "$DSTDIR/bob-pull.png"

.. image:: bob-pull.png
   :align: center

Notice how the changesets appear in a different order in Bob's
repository compared to Alice's repository --- the "Happy, happy!"
changeset has switched order with the "Welcome file." changeset.
Changesets always retain their ID, the longer hexadecimal number, but
the revision number can change. The revision number simply depends on
the order in which changesets was added to a repository, and when two
people pull from each other, they will most likely end up with
different revision numbers for the same changesets. You should
therefore *always* refer to a changeset by its ID when talking to
others. But you can still use the revision numbers with commands like
`hg update` that work inside your local repository.

Exercises
---------

#. Create a repository and make a couple of commits inside it.

#. Make two clones of your repository. Notice how the ``.hg/hgrc``
   file records the location of the original repository. The `hg
   paths` command will show you the paths defined.

#. Add another path to ``.hg/hgrc``, such as::

     bob = /home/bob/test

   You will now be able to execute `hg pull bob`, `hg outgoing bob`,
   etc. It is a good idea to add shortcuts for people you collaborate
   with often.

#. Experiment with pulling and pushing changes. Note how the working
   directory is not changed even though history is added to the
   repository. The working copy parent revision is only changed with
   `hg update`.

Mercurial supports disconnected collaboration. This works by
exchanging changesets in what is called *bundles*. A bundle is a
compressed, binary representation of a number of changesets.

#. Create a new changeset in one of your repositories. Use `hg bundle
   --base X out.bundle` to create a bundle in ``out.bundle`` that
   contains all changesets following ``X``. The idea is that you
   record somewhere the last known shared changeset between you and
   the target, and use that as the base.

#. Go to the target repository and use `hg unbundle` to import the
   changesets from the bundle. In this example you will most likely
   have both repositories on your own machine, but in reality the two
   repositories could be on machines that are never online at the same
   time. In that case, bundles offer a way for you to move changesets
   over, say, email.

You can also publish your repository via HTTP:

#. Execute `hg serve` in a repository. You can now access the
   repository in a browser with ``http://localhost:8000``. Try to
   start a server for both Alice's and Bob's repository.

#. Try to pull from a repository published with `hg serve`.

Note `hg serve` is intended for ad-hoc publishing. For permanent
publishing you can for example use Apache with the ``hgweb.cgi``
script supplied with Mercurial.


Summary
=======

You have seen most of the basic commands in Mercurial and you have
seen how the history graph works. The important commands are:

* `hg init`: create a new repository.
* `hg add`: schedule a file for addition.
* `hg diff`: see changes that will be included in the next commit.
* `hg commit`: save your changes in the current repository.
* `hg log`: see all changes in your repository.
* `hg pull`: get all changes from another repository into the current one.
* `hg push`: send all changes from your repository to another one.
* `hg merge`: join different lines of history.

And very importantly:

* `hg help`

..  LocalWords:  aragost Trifork hg TortoiseHg thg PyGTK CVS USB