Differences between revisions 1 and 16 (spanning 15 versions)
Revision 1 as of 2005-08-26 00:57:48
Size: 916
Editor: waste
Comment:
Revision 16 as of 2011-02-08 18:30:15
Size: 8483
Editor: PaulBoddie
Comment: Added diagrams and headings.
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
== CVS-like working practice ==

In a CVS-like world, you will typically have one central repository; let's call it the "main line". This correspond's to CVS's notion of the "trunk".
= CVS-like Working Practice =

Mercurial allows multiple [[WorkingPractices|working practices]]. In a CVS-like world, you will typically have one central repository; let's call it the "main line". This corresponds to CVS's notion of the "trunk".

{{{#!dot
digraph G {
  trunk [label="main line"];
  subgraph {
    alice [label="Alice's clone"]; bob [label="Bob's clone"]; carlos [label="Carlos' clone"];
    rank=same
  }
  trunk -> alice [label="pull"];
  alice -> trunk [label="push"];
  trunk -> bob [label="pull"];
  bob -> trunk [label="push"];
  trunk -> carlos [label="pull"];
  carlos -> trunk [label="push"];
}
}}}
Line 7: Line 23:
Developers have direct ''ssh'' access to the central repositories on a server, and push their changes directly from their local clones into the appropriate repositories.

Someone may be responsible for "back-porting" changes from a branch to the main line. They do this by pulling changes from the branch and the main line into a local repository, merging appropriately, then pushing back to the main line.
== Workflow ==

Developers have direct SSH access (whether that is through "normal" SSH access with each developer having their own login, or through [[SharedSSH|shared SSH logins]]) to the central repositories on a server, and push their changes directly from their local clones into the appropriate repositories. Thus, the usual CVS practice would be as follows:

{{{
# Check for work done...
cvs update
# Do work, consider changes...
cvs diff
# Commit changes...
cvs commit
}}}

{{{#!dot
digraph G {
  subgraph {
    node [shape="box"]
    rank=same
    start -> committed;
  }
  start -> checkout:w [label="update"];
  checkout:e -> committed [label="commit"];
}
}}}

This doesn't always work out, and so the following workflow is typically required if `cvs commit` complains:

{{{
# Rectify conflicts, then...
cvs update
# Edit conflicts, then commit...
cvs commit
}}}

{{{#!dot
digraph G {
  subgraph {
    node [shape="box"]
    rank=same
    competing [color="red"];
    start -> competing -> committed;
  }
  start -> checkout:w [label="update"];
  competing -> checkout:n [label="update"];
  checkout:e -> committed [label="commit"];
}
}}}

=== The basic workflow in Mercurial ===

The corresponding practice would be as follows with Mercurial:

{{{
# Check for work done (part of the update operation in CVS)...
hg pull
# Start working with the latest changes (part of the update operation in CVS)...
hg update
# Do work, consider changes...
hg diff
# Commit changes (part of the commit operation in CVS)...
hg commit
# Push changes (part of the commit operation in CVS)...
hg push
}}}

{{{#!dot
digraph G {
  subgraph {
    node [shape="box"]
    rank=same
    start1 [label="start"];
    committed1 [label="committed"];
  }
  subgraph {
    node [shape="box"]
    rank=same
    start2 [label="start"];
    committed2 [label="committed"];
  }
  checkout [label="working files"];
  start1 -> committed1;
  start2 -> committed2;
  start1 -> start2 [label="pull"];
  start2 -> checkout:w [label="update"];
  checkout:e -> committed2 [label="commit"];
  committed2 -> committed1 [label="push"];
}
}}}

The single command equivalent of `cvs update` is really...

{{{
hg pull -u
}}}

=== Working independently ===

If you perform the `hg pull` but not the `hg update` you can keep working and ignore other people's work, but you will be able to see what they did.

{{{#!dot
digraph G {
  subgraph {
    node [shape="box"]
    rank=same
    before1 [label="..."];
    start1 [label="start"];
  }
  subgraph {
    node [shape="box"]
    rank=same
    before2 [label="..."];
    sc [shape="none"; label=<
<table border='0' cellspacing='10' cellpadding='10'><tr><td port='start2' border='1' >start</td></tr><tr><td port='committed2' border='1'>committed</td></tr></table>
        >];
  }
  checkout [label="working files"];
  before1 -> start1;
  before2 -> sc:start2;
  before2 -> sc:committed2;
  start1 -> sc:start2 [label="pull"];
  before2 -> checkout:w [label="(previous) update"];
  checkout:e -> sc:committed2 [label="commit"];
}
}}}

Ultimately you are likely to want to combine your own work with theirs, so an [[Update|update]] will need to happen at some stage.

Note that before pushing changes, the developer is free to commit as many [[ChangeSet|changesets]] as they like without being affected by people working elsewhere.

{{{#!dot
digraph G {
  subgraph {
    node [shape="box"]
    rank=same
    start1 [label="start"];
    competing1 [label="competing"; color="red"];
  }
  subgraph {
    node [shape="box"]
    rank=same
    start2 [label="start"];
    committed2 [label="committed"];
    committed3 [label="..."];
  }
  subgraph {
    rank=same
    checkout [label="working files"];
    checkout2 [label="..."];
  }
  start1 -> competing1;
  start2 -> committed2;
  committed2 -> committed3;
  start1 -> start2 [label="pull"];
  start2 -> checkout:w [label="update"];
  checkout:n -> committed2 [label="commit"];
  checkout:e -> checkout2:w;
  checkout2:e -> committed3 [label="commit"];
}
}}}

=== Conflicts and merging in Mercurial ===

When pushing, `hg push` may complain about multiple heads being created which means that the content of the repository has been edited in different ways and has not been reconciled. Multiple heads can exist in the remote repository, but this leaves any work for reconciling the competing changes for later, which may not be desirable.

{{{#!dot
digraph G {
  rankdir=LR
  node [shape="box"]
  start;
  subgraph {
    rank=same
    competing [color="red"];
    committed;
  }
  start -> competing;
  start -> committed;
}
}}}

To reconcile competing changes, the following workflow becomes necessary:

{{{
# Get the remote changes and merge them...
hg pull
hg merge
# Edit any conflicts, then commit...
hg commit
# Push merged changes...
hg push
}}}

{{{#!dot
digraph G {
  subgraph {
    node [shape="box"]
    rank=same
    start1 [label="start"];
    competing1 [label="competing"; color="red"];
    committed1 [label="committed"];
  }
  subgraph {
    node [shape="box"]
    rank=same
    start2 [label="start"];
    cc [shape="none"; label=<
<table border='0' cellspacing='10' cellpadding='10'><tr><td port='competing2' border='1' color='red'>competing</td></tr><tr><td port='committed2' border='1'>committed</td></tr></table>
        >];
    committed3 [label="committed"];
  }
  subgraph {
    rank=same
    checkout [label="working files"];
    checkout2 [label="..."];
  }
  start1 -> competing1 -> committed1;
  start1 -> start2 [label="pull"];
  start2 -> cc:competing2 -> committed3;
  start2 -> cc:committed2 -> committed3;
  start2 -> checkout:w [label="update"];
  checkout:n -> cc:committed2 [label="commit"];
  competing1 -> cc:competing2 [label="pull"];
  checkout:e -> checkout2:w;
  cc:competing2 -> checkout2 [label="update"];
  checkout2:e -> committed3 [label="commit"];
  committed3 -> committed1 [label="push"];
}
}}}

Again, the developer can defer pushing changes until later. The principal advantage of Mercurial here is that the developer need not be confronted with merging others' changes on every commit.

== Branches and merging ==

Someone may be responsible for "backporting" changes from a branch to the main line. They do this by pulling changes from the branch and the main line into a local repository, merging appropriately, then pushing back to the main line.

{{{#!dot
digraph G {
  subgraph {
    trunk [label="main line"];
    branch [label="branch"];
    rank=same
  }
  subgraph {
    carlos [label="Carlos' clone"];
    rank=same
  }
  branch -> carlos [label="pull"];
  trunk -> carlos [label="pull"];
  carlos -> trunk [label="push"];
}
}}}
Line 12: Line 275:

{{{#!dot
digraph G {
  subgraph {
    trunk [label="main line"];
    branch [label="branch"];
    rank=same
  }
  subgraph {
    david [label="David's clone"];
    edward [label="Edward's clone"];
    rank=same
  }
  trunk -> branch [label="clone"];
  branch -> david [label="clone"];
  branch -> david [label="pull"];
  david -> branch [label="push"];
  branch -> edward [label="clone"];
  branch -> edward [label="pull"];
  edward -> branch [label="push"];
}
}}}

== See also ==

 * [[CvsCommands|CVS commands]] and their equivalents in Mercurial
 * [[CvsInfo|Information for CVS users]]

CVS-like Working Practice

Mercurial allows multiple working practices. In a CVS-like world, you will typically have one central repository; let's call it the "main line". This corresponds to CVS's notion of the "trunk".

Repositories tend to be long-lived, and the "authoritative branches" are clones of the central repository.

Workflow

Developers have direct SSH access (whether that is through "normal" SSH access with each developer having their own login, or through shared SSH logins) to the central repositories on a server, and push their changes directly from their local clones into the appropriate repositories. Thus, the usual CVS practice would be as follows:

# Check for work done...
cvs update
# Do work, consider changes...
cvs diff
# Commit changes...
cvs commit

This doesn't always work out, and so the following workflow is typically required if cvs commit complains:

# Rectify conflicts, then...
cvs update
# Edit conflicts, then commit...
cvs commit

The basic workflow in Mercurial

The corresponding practice would be as follows with Mercurial:

# Check for work done (part of the update operation in CVS)...
hg pull
# Start working with the latest changes (part of the update operation in CVS)...
hg update
# Do work, consider changes...
hg diff
# Commit changes (part of the commit operation in CVS)...
hg commit
# Push changes (part of the commit operation in CVS)...
hg push

The single command equivalent of cvs update is really...

hg pull -u

Working independently

If you perform the hg pull but not the hg update you can keep working and ignore other people's work, but you will be able to see what they did.

Ultimately you are likely to want to combine your own work with theirs, so an update will need to happen at some stage.

Note that before pushing changes, the developer is free to commit as many changesets as they like without being affected by people working elsewhere.

Conflicts and merging in Mercurial

When pushing, hg push may complain about multiple heads being created which means that the content of the repository has been edited in different ways and has not been reconciled. Multiple heads can exist in the remote repository, but this leaves any work for reconciling the competing changes for later, which may not be desirable.

To reconcile competing changes, the following workflow becomes necessary:

# Get the remote changes and merge them...
hg pull
hg merge
# Edit any conflicts, then commit...
hg commit
# Push merged changes...
hg push

Again, the developer can defer pushing changes until later. The principal advantage of Mercurial here is that the developer need not be confronted with merging others' changes on every commit.

Branches and merging

Someone may be responsible for "backporting" changes from a branch to the main line. They do this by pulling changes from the branch and the main line into a local repository, merging appropriately, then pushing back to the main line.

When the main line reaches a release point, someone creates a clone on the server at the appropriate revision, and people who need to work on that branch clone it, then start pushing their changes back.

See also

CvsLikePractice (last edited 2012-06-20 16:49:32 by PaulBoddie)