Differences between revisions 31 and 32
Revision 31 as of 2008-09-14 13:25:11
Size: 7874
Editor: abuehl
Comment:
Revision 32 as of 2008-09-14 22:18:23
Size: 9814
Editor: abuehl
Comment: more details about Alice and Bob (i.e. update + working dirs)
Deletions are marked like this. Additions are marked like this.
Line 55: Line 55:
When you [:Commit:commit], the state of the working directory relative to its [:Parent:parents] is recorded as a new [:Revision:revision]: When you [:Commit:commit], the state of the working directory relative to its [:Parent:parents] is recorded as a new [:ChangeSet:changeset] (also called a new "[:Revision:revision]"):
Line 102: Line 102:
   workingdir [label="{{<p1> p1 | <p2> p2} | working directory}"];
Line 109: Line 110:
   label="example history"    rev6 -> workingdir:p1 [dir=back]
label="example repository"
Line 117: Line 119:
== Cloning, Making Changes, Merging, and Pulling ==

Let's start with a user Alice, who has a store that looks like:

{{{#!dot
digraph {
   label="Alice's Repo"
   rankdir = LR
   node [shape=box]
   a->b->c->d [dir=back]
}
}}}

Bob [:Clone:clones] this repo, and ends up with a complete copy of Alice's store (though his working directory is independent!):

{{{#!dot
digraph {
   label="Bob's Repo"
   rankdir = LR
   node [shape=box]
   a->b->c->d [dir=back]
}
}}}

Bob then [:Commit:commits] a couple changes:

{{{#!dot
digraph {
   label="Bob's Repo"
   rankdir = LR
   node [shape=box]
   a->b->c->d->e->f [dir=back]
   e [color=blue]
   f [color=blue]
}
}}}

Alice then makes her own change in parallel:

{{{#!dot
digraph {
   label="Alice's Repo"
   rankdir = LR
   node [shape=box]
   a->b->c->d->g [dir=back]
   g [color=red]
}
}}}

Bob then [:Pull:pulls] Alice's repo to synchronize. This copies all of Alice's changes into Bob's repo:

{{{#!dot
digraph {
   label="Bob's Repo"
   rankdir = LR
   node [shape=box]
   a->b->c->d->e->f [dir=back]
   e [color=blue]
   f [color=blue]
   d->g [dir=back]
   g [color=red;
label="g (tip)"]
}
}}}

Because Alice's '''g''' is the newest head in Bob's repository, it's now the '''tip'''. Bob then does a [:Merge:merge] which combines the last change he was working on ('''f''') with the tip, commits the result, and ends up with:

{{{#!dot
digraph {
   label="Bob's Repo"
   rankdir = LR
   node [shape=box]
   a->b->c->d->e->f [dir=back]
   e [color=blue]
   f [color=blue]
   d->g [dir=back]
   g [color=red]
   f->h [dir=back, weight=3.0]
   g->h [dir=back, weight=3.0]
== Cloning, Making Changes, Merging, Pulling and Updating ==

Let's start with a user Alice, who has a repository that looks like:

{{{#!dot
digraph {
   label="Alice's repo"
   rankdir = LR
   node [shape=box]
   a -> b -> c -> d -> "working dir" [dir=back]
}
}}}

Bob [:Clone:clones] this repo, and ends up with a complete, independent, local copy of Alice's store
and a clean check
out of the tipmost revision d in his working directory:

{{{#!dot
digraph {
   label="Bob's repo"
   rankdir = LR
   node [shape=box]
   a -> b -> c -> d -> "working dir" [dir=back]
}
}}}

Bob can now work independently of Alice. He then [:Commit:commits] two changes e and f:

{{{#!dot
digraph {
   label="Bob's repo"
   rankdir = LR
   node [shape=box]
   a -> b -> c -> d -> e -> f -> "working dir" [dir=back]
   e [color=blue]
   f [color=blue]
}
}}}

Alice then makes her own change g in parallel, which causes her repository store to diverge from Bob's, thus
creating a [:Branch:branch]
:

{{{#!dot
digraph {
   label="Alice's repo"
   rankdir = LR
   node [shape=box]
   a -> b -> c -> d -> g -> "working dir" [dir=back]
   g [color=red]
}
}}}

Bob then [:Pull:pulls] Alice's repo to synchronize. This copies all of Alice's changes into Bob's repository store
(here, it's just a single change g). Note that Bob's working directory is '''not''' changed
by the pull
:

{{{#!dot
digraph {
   label="Bob's repo"
   rankdir = LR
   node [shape=box]
   a -> b -> c -> d -> e -> f -> "working dir" [dir=back]
   e [color=blue]
   f [color=blue]
   d -> g [dir=back]
   g [color=red,
label="g (tip)"]
}
}}}

Because Alice's '''g''' is the newest head in Bob's repository, it's now the '''tip'''.

Bob then does a [:Merge:merge], which combines the last change he was working on (f) with the
tip in his working directory. Now
, his working directory has two parent revisions (f and g):

{{{#!dot
digraph {
   label="Bob's repo"
   rankdir = LR
   node [shape=box]
   a -> b -> c -> d -> e -> f [dir=back]
   e [color=blue]
   f [color=blue]
   d -> g [dir=back]
   g [color=red]
   f -> "working dir" [dir=back, weight=3.0]
   g -> "working dir" [dir=back, weight=3.0]
}
}}}

After examining the result of the merge in his working directory and making sure the merge is
perfect, Bob commits the result and ends up with a new [:MergeChangeset:merge changeset] h in his
store:

{{{#!dot
digraph {
   label="Bob's repo"
   rankdir = LR
   node [shape=box]
   a -> b -> c -> d -> e -> f [dir=back]
   e [color=blue]
   f [color=blue]
   d -> g [dir=back]
   g [color=red]
   f -> h [dir=back, weight=3.0]
   g -> h [dir=back, weight=3.0]
   h -> "working dir" [dir=back]
   h [color=green, label="h (tip)"]
}
}}}

Now if Alice '''pulls''' from Bob, she will get Bob's changes e, f, and h into her store:

{{{#!dot
digraph {
   label="Alice's repo"
   rankdir = LR
   node [shape=box]
   a -> b -> c -> d -> e -> f [dir=back]
   e [color=blue]
   f [color=blue]
   d -> g [dir=back]
   g [color=red]
   f -> h [dir=back, weight=3.0]
   g -> h [dir=back, weight=3.0]
   g -> "working dir" [dir=back]
Line 199: Line 247:
Now if Alice '''pulls''' from Bob, she will get Bob's changes e, f, and h, and they will be fully synchronized:

{{{#!dot
digraph {
   label="Alice's Repo"
   rankdir = LR
   node [shape=box]
   a->b->c->d->e->f [dir=back]
   e [color=blue]
   f [color=blue]
   d->g [dir=back]
   g [color=red]
   f->h [dir=back, weight=3.0]
   g->h [dir=back, weight=3.0]
   h [color=green;label="h (tip)"]
}
}}}
Note that Alice's working directory was not changed by the pull. She has to do an [:Update:update] to synchronize
her working directory to the merge changset h. This changes the parent changeset of her working directory to
changeset h and updates the files in her working directory to revision h.

{{{#!dot
digraph {
   label="Alice's repo"
   rankdir = LR
   node [shape=box]
   a -> b -> c -> d -> e -> f [dir=back]
   e [color=blue]
   f [color=blue]
   d -> g [dir=back]
   g [color=red]
   f -> h [dir=back, weight=3.0]
   g -> h [dir=back, weight=3.0]
   h -> "working dir" [dir=back]
   h [color=green, label="h (tip)"]
}
}}}

Now Alice and Bob are fully synchronized again.

Mercurial's decentralized development model can be confusing to new users. This page attempts to illustrate some of the basic concepts. See the ["Tutorial"] for step-by-step instructions.

(Translations: [:BrazilianPortugueseUnderstandingMercurial:Brazilian Portuguese], [:ChineseUnderstandingMercurial:Chinese], [:FrenchUnderstandingMercurial:French], [:GermanUnderstandingMercurial:German], [:ItalianUnderstandingMercurial:Italian], [:JapaneseUnderstandingMercurial:Japanese], [:KoreanUnderstandingMercurial:Korean], [:RussianUnderstandingMercurial:Russian], [:SpanishUnderstandingMercurial:Spanish] )

TableOfContents

What's in a Repository

Mercurial [:Repository:repositories] contain a [:WorkingDirectory:working directory] coupled with a store:

The store contains the complete history of the project. Unlike traditional [:SCM:SCMs], where there's only one central copy of this history, every working directory is paired with a private copy of the history. This allows development to go on in parallel.

The working directory contains a copy of the project's files at a given point in time (eg rev 2), ready for editing. Because [:Tag:tags] and [:.hgignore:ignored files] are revision-controlled, they are also included.

Committing Changes

When you [:Commit:commit], the state of the working directory relative to its [:Parent:parents] is recorded as a new [:ChangeSet:changeset] (also called a new "[:Revision:revision]"):

Note here that revision 4 is a [:Branch:branch] of revision 2, which was the revision in the working directory. Now revision 4 is the working directory's parent.

Revisions, Changesets, Heads, and Tip

Mercurial groups related changes to multiple files into single atomic [:ChangeSet:changesets], which are revisions of the whole project. These each get a sequential [:RevisionNumber:revision number]. Because Mercurial allows distributed parallel development, these revision numbers may disagree between users. So Mercurial also assigns each revision a global [:ChangeSetID:changeset ID]. Changeset IDs are 40-digit hexadecimal numbers, but they can be abbreviated to any unambiguous prefix, like "e38487".

Branches and [:Merge:merges] in the revision history can occur at any point. Each unmerged branch creates a new [:Head:head] of the revision history. Here, revisions 5 and 6 are heads. Mercurial considers revision 6 to be the [:Tip:tip] of the repository, the head with the highest revision number. Revision 4 is a merge changeset, as it has two parent changesets (revisions 2 and 3).

Cloning, Making Changes, Merging, Pulling and Updating

Let's start with a user Alice, who has a repository that looks like:

Bob [:Clone:clones] this repo, and ends up with a complete, independent, local copy of Alice's store and a clean checkout of the tipmost revision d in his working directory:

Bob can now work independently of Alice. He then [:Commit:commits] two changes e and f:

Alice then makes her own change g in parallel, which causes her repository store to diverge from Bob's, thus creating a [:Branch:branch]:

Bob then [:Pull:pulls] Alice's repo to synchronize. This copies all of Alice's changes into Bob's repository store (here, it's just a single change g). Note that Bob's working directory is not changed by the pull:

Because Alice's g is the newest head in Bob's repository, it's now the tip.

Bob then does a [:Merge:merge], which combines the last change he was working on (f) with the tip in his working directory. Now, his working directory has two parent revisions (f and g):

After examining the result of the merge in his working directory and making sure the merge is perfect, Bob commits the result and ends up with a new [:MergeChangeset:merge changeset] h in his store:

Now if Alice pulls from Bob, she will get Bob's changes e, f, and h into her store:

Note that Alice's working directory was not changed by the pull. She has to do an [:Update:update] to synchronize her working directory to the merge changset h. This changes the parent changeset of her working directory to changeset h and updates the files in her working directory to revision h.

Now Alice and Bob are fully synchronized again.

A Decentralized System

Mercurial is a completely decentralized system, and thus has no internal notion of a central repository. Thus users are free to define their own topologies for sharing changes (see CommunicatingChanges):

What Mercurial can't do

Many SVN/CVS users expect to host related projects together in one repository. This is really not what hg was made for, so you should try a different way of working. This especially means, that you cannot check out only one directory of a repository. If you absolutely need to host multiple projects in a kind of meta-repository though, you could try the ForestExtension.

For a hands-on introduction to using Mercurial, see the ["Tutorial"].

UnderstandingMercurial (last edited 2013-09-02 20:00:50 by WagnerBruna)