|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>HgInit: Setting up for a Team</title>
<script src="c/jquery-1.4.1.js"></script>
<script src="c/basic.js"></script>
<link href="c/styles.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-225715-20");
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
} catch(err) {}</script>
</head>
<body>
<div id="kilnFlyOut">
<div class="flyoutscreenshot">
<img class="screenshot" src="i/dag.png" />
</div>
<div class="flyouttext">
<strong>Kiln gives you:</strong>
<ul>
<li class="first"><a class="selected thumbnail" data-src="i/dag.png" href="convert.html">Mercurial-based<br/>version control</a></li>
<li><a class="thumbnail" data-src="i/setup.png" href="convert.html">Straightforward<br/>setup</a></li>
<li class="last"><a class="thumbnail" data-src="i/review.png" href="convert.html">Seamless<br/>code review</a></li>
</ul>
<a class="convert" href="convert.html" target="_blank" onClick="javascript: pageTracker._trackPageview('/outbound/flyout/freetrial.shop.fogcreek.com');"><img src="i/getstarted.gif" width="114" height="24" border="0" /></a>
</div>
<div class="flyoutteaser"><nobr><strong>Try Kiln free!</strong> Easy Mercurial hosting and more.</nobr></div>
</div>
<div class="toptop" align="left">
<ul>
<li align="center"><a href="http://www.joelonsoftware.com/" onClick="javascript: pageTracker._trackPageview('/outbound/toptop/joelonsoftware.com');">Joel on Software</a></li>
<li align="center"><a href="http://mercurial.selenic.com/" onClick="javascript: pageTracker._trackPageview('/outbound/toptop/mercurial.selenic.com');">Mercurial</a></li>
<li align="center"><a href="index.html">Home</a></li>
</ul>
</div>
<div id="dropshadow"></div>
<div id="topnav">
<div class="tInterior">
<a href="index.html">
<img src="i/logo.png" border="0" alt="HgInit Home" />
</a>
One of the benefits of using Mercurial is working with a team on the same code. Mercurial lets you each work independently, and merges your changes together.</div>
</div>
<div class="main">
<h1>Setting up for a Team</h1>
<div class="content">
<p>The most common way to collaborate with Mercurial is to set up a central repository, in addition to the private repositories that we each have on our own computers. We can use the central repository sort of like a swap meet, where we get together to trade the changes we’ve been making.</p>
<div><img src="i/02-repo.png" /></div>
<div class="cheatcontent" style="margin-top:0px">
<div class="cheattop">
<div class="command">hg serve</div>
</div>
<p class="cheattext">runs a web server to make the current repository accessible over the Internet </p>
<img src="i/cheatbot.png" width="241" height="41" />
</div>
<p>The quick-and-dirty way to make a central repository is to use Mercurial’s built in web server—all you have to do is make a repository with <strong>hg init</strong> and then serve it on the web with <strong>hg serve</strong>. By default it will be served on port 8000.</p>
<div class="codesnippet">
<div class="codetop"> </div>
<pre>
C:\> <strong>mkdir CentralRepo</strong>
C:\> <strong>cd CentralRepo</strong>
C:\CentralRepo> <strong>hg init</strong>
C:\CentralRepo> <strong>hg serve</strong>
</pre>
<div class="codebottom"> </div>
</div>
<p>Since this computer is named <strong>joel.example.com</strong> I can just go to <strong>http://joel.example.com:8000/</strong> with a web browser and see that the server is up and running, even though the repository there is completely empty.</p>
<div><img src="i/02-web.png" /></div>
<div class="cheatcontent" style="margin-top:0px">
<div class="cheattop">
<div class="command">hg clone</div>
</div>
<p class="cheattext">make a complete copy of an entire repository </p>
<img src="i/cheatbot.png" width="241" height="41" />
</div>
<p>With the central web server running, I can <em>clone</em> this repository <em>from</em> the server <em>onto</em> my own computer for my own use. This repository is empty right now, so I’ll just get another empty repository when I clone it.</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel> <strong>hg clone http://joel.example.com:8000/ recipes</strong>
no changes found
updating to branch default
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
C:\Users\joel> <strong>cd recipes</strong>
C:\Users\joel\recipes> <strong>dir</strong>
Volume in drive C has no label.
Volume Serial Number is 84BD-9C2C
Directory of C:\Users\joel\recipes
02/08/2010 02:46 PM <DIR> .
02/08/2010 02:46 PM <DIR> ..
02/08/2010 02:46 PM <DIR> .hg
0 File(s) 0 bytes
3 Dir(s) 41,852,125,184 bytes free
</pre>
<div class="codebottom"> </div>
</div>
<p>Now I’ll create a file called <strong>guac</strong> with my famous guacamole recipe.</p>
<div class="edit1">
<div class="edittopbefore" >
guac </div>
<div class="editcontent">
* 2 ripe avocados<br>
* 1/2 red onion, minced (about 1/2 cup)<br>
* 1-2 serrano chiles, stems and seeds removed, minced<br>
* 2 tablespoons cilantro leaves, finely chopped<br>
* 1 tablespoon of fresh lime or lemon juice<br>
* 1/2 teaspoon coarse salt<br>
* A dash of freshly grated black pepper<br>
* 1/2 ripe tomato, seeds and pulp removed, chopped<br><br>
Crunch all ingredients together.<br>
Serve with tortilla chips.<br>
</div>
<img src="i/edit-bot.gif" width="387" height="76" />
</div>
<div style="clear: both;"> </div>
<p>I’ll add this file, and commit it as the first official version:</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg add</strong>
adding guac
C:\Users\joel\recipes> <strong>hg commit</strong>
</pre>
<div class="codebottom"> </div>
</div>
<p>I’ll provide a commit comment:</p>
<img src="i/02-commit0.png">
<p>I’m just going to quickly edit this file and make one small change, so
that we have a little bit of history in the repository.</p>
<div class="edit1">
<div class="edittopbefore">
guac </div>
<div class="editcontent">
…<br>
* A dash of freshly grated black pepper<br>
* 1/2 ripe tomato, seeds and pulp removed, chopped<br><br>
Crunch all ingredients together.<br>
Serve with tortilla chips.<br>
</div>
<img src="i/edit-bot.gif" width="387" height="76" />
</div>
<div class="edit2">
<img src="i/arrow2.gif" width="83" height="97" class="editArrow" />
<div class="edittopafter">
guac
</div>
<div class="editcontent">
…<br>
* A dash of freshly grated black pepper<br>
* 1/2 ripe tomato, seeds and pulp removed, chopped<br><br>
<strong>Smoosh</strong> all ingredients together.<br>
Serve with tortilla chips.<br>
</div>
<img src="i/edit-bot.gif" width="387" height="76" />
</div>
<div style="clear: both;"> </div>
<p>And now to commit that change:</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg status</strong>
M guac
C:\Users\joel\recipes> <strong>hg diff guac</strong>
diff -r c1fb7e7fbe50 guac
--- a/guac Mon Feb 08 14:50:08 2010 -0500
+++ b/guac Mon Feb 08 14:51:08 2010 -0500
@@ -7,5 +7,5 @@
* A dash of freshly grated black pepper
* 1/2 ripe tomato, seeds and pulp removed, chopped
-Crunch all ingredients together.
+Smoosh all ingredients together.
Serve with tortilla chips.
C:\Users\joel\recipes> <strong>hg com -m "Change crunch to smoosh"</strong>
C:\Users\joel\recipes> <strong>hg log</strong>
changeset: 1:a52881ed530d
tag: tip
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:51:18 2010 -0500
summary: Change crunch to smoosh
changeset: 0:c1fb7e7fbe50
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:50:08 2010 -0500
summary: Initial version of guacamole recipe
</pre>
<div class="codebottom"> </div>
</div>
<p>Notice that when I committed that time, I used the <strong>-m</strong> argument, which I haven’t done before. That’s just a way to provide the commit message on the command line, without using an editor.</p>
<p>OK, where are we? So far, I’ve got a central repository, and my clone of it. I’ve made two changes and committed them, but those changes are only in my clone—they’re not in the central repository yet. So the world looks like this:</p>
<div><img src="i/02-repo-2.png" /></div>
<div class="cheatcontent" style="margin-top:0px">
<div class="cheattop">
<div class="command">hg push</div>
</div>
<p class="cheattext"> push new changes from this repository into another </p>
<img src="i/cheatbot.png" width="241" height="41" />
</div>
<p>Now I’m going to use the <strong>hg push</strong> command, which will push my changes from my repository into the central repository:</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg push</strong>
pushing to http://joel.example.com:8000/
searching for changes
ssl required
</pre>
<div class="codebottom"> </div>
</div>
<p>Oh great. It figures that wouldn’t work. I neglected to think about the security implications of just running a random web server and allowing anybody in the world to push their stupid changes into it. Bear with me for a moment; I’m going to configure that server to allow anybody in the world to do anything they want to it. This can be done by editing the file .hg\hgrc on the server:</p>
<div class="edit1">
<div class="edittopbefore">
.hg\hgrc </div>
<div class="editcontent">
[web]<br />
push_ssl=False<br />
allow_push=*<br />
</div>
<img src="i/edit-bot.gif" width="387" height="76" />
</div>
<div style="clear: both;"> </div>
<p>Needless to say, this is rather unsafe, but if you’re on a nice protected LAN at work and there’s a good firewall and you trust everybody on your LAN, this is reasonably OK. Otherwise, you’ll want to read the advanced chapters on security.</p>
<p>OK, time to fire up the server again:</p>
<div class="codesnippet">
<div class="codetop"> </div>
<pre>
C:\CentralRepo> <strong>hg serve</strong>
</pre>
<div class="codebottom"> </div>
</div>
<p>And now I should be able to push into it:</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg push</strong>
pushing to http://joel.example.com:8000/
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
</pre>
<div class="codebottom"> </div>
</div>
<p>Yay! Now the world looks like this:</p>
<img src="i/02-repo-3.png" />
<p>I know what you’re thinking. You’re thinking, “Gosh, Joel, that’s strange. Why do these repositories contain <em>changes</em> as opposed to <em>files</em>? Where’s that <strong>guac</strong> file?”</p>
<p>Yeah, it’s weird. But that’s the way distributed version control works. Repositories just contain big stacks of changes. Imagine that a change is like one of those clear transparency sheets. When you have a bunch of transparency sheets, you stack them on each other in order, with the latest change on the top, and look down from above, and—tada!—you’re looking at the current version of the file. As you peel away transparencies from the top of the pile, you see older and older versions.</p>
<p>We can use our web browser to peek into the central repository now:</p>
<img src="i/02-web-2.png" />
<p>Exactly what you would expect.</p>
<p>Now I want Rose to help me work on the recipe. Rose is on the test team. Everyone agrees that she reminds them of those middle-aged ladies you see in Vegas, sitting there slack-jawed for hours, shoveling quarter after quarter into the slot machines, only she’s testing software. You can throw her a new version of your code and she’ll test it on 23 different Linux distros, one after the other, expressionless, unmoving, pausing only to tell you that there’s a dot missing on one of the lower-case I’s in the Turkish version on Ubuntu Linux. Rose is a great tester but I swear sometimes she acts like a zombie.</p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose> <strong>hg clone http://joel.example.com:8000/ recipes</strong>
requesting all changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre>
<div class="codebottom"> </div>
</div>
<p>Rose used the <strong>hg clone</strong> command to get her own, complete copy of the repository. <strong>hg clone</strong> takes two arguments: the URL of the repository and the name of the directory where you want it cloned. She made her own <strong>recipes</strong> folder.</p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose> <strong>cd recipes</strong>
C:\Users\rose\recipes> <strong>dir</strong>
Volume in drive C has no label.
Volume Serial Number is 84BD-9C2C
Directory of C:\Users\rose\recipes
02/08/2010 03:23 PM <DIR> .
02/08/2010 03:23 PM <DIR> ..
02/08/2010 03:23 PM <DIR> .hg
02/08/2010 03:23 PM 394 guac
1 File(s) 394 bytes
3 Dir(s) 41,871,872,000 bytes free
C:\Users\rose\recipes> <strong>hg log</strong>
changeset: 1:a52881ed530d
tag: tip
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:51:18 2010 -0500
summary: Change crunch to smoosh
changeset: 0:c1fb7e7fbe50
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:50:08 2010 -0500
summary: Initial version of guacamole recipe
</pre>
<div class="codebottom"> </div>
</div>
<p>Notice that when she types <strong>hg log</strong> she sees the whole history. She has actually downloaded the entire repository, with its complete history of everything that happened.</p>
<p>Rose is going to make a change, and check it in:</p>
<div class="edit1">
<div class="edittopbefore">
guac </div>
<div class="editcontent">
* 2 ripe avocados<br>
* 1/2 red onion, minced (about 1/2 cup)<br>
* 1-2 serrano chiles, stems and seeds removed, minced<br>
* 2 tablespoons cilantro leaves, finely chopped<br>
* 1 tablespoon of fresh lime or lemon juice<br>
…
</div>
<img src="i/edit-bot.gif" width="387" height="76" />
</div>
<div class="edit2">
<img src="i/arrow2.gif" width="83" height="97" class="editArrow" />
<div class="edittopafter">
guac
</div>
<div class="editcontent">
* 2 ripe avocados<br>
* 1/2 red onion, minced (about 1/2 cup)<br>
* 1-2 <strong>habanero</strong> chiles, stems and seeds removed, minced<br>
* 2 tablespoons cilantro leaves, finely chopped<br>
* 1 tablespoon of fresh lime or lemon juice<br>
…<br>
</div>
<img src="i/edit-bot.gif" width="387" height="76" />
</div>
<div style="clear: both;"> </div>
<p>Now she commits it. Notice that she can do this even if the server is not running: the commit entirely happens on her machine.</p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose\recipes> <strong>hg diff</strong>
diff -r a52881ed530d guac
--- a/guac Mon Feb 08 14:51:18 2010 -0500
+++ b/guac Mon Feb 08 15:28:57 2010 -0500
@@ -1,6 +1,6 @@
* 2 ripe avocados
* 1/2 red onion, minced (about 1/2 cup)
-* 1-2 serrano chiles, stems and seeds removed, minced
+* 1-2 habanero chiles, stems and seeds removed, minced
* 2 tablespoons cilantro leaves, finely chopped
* 1 tablespoon of fresh lime or lemon juice
* 1/2 teaspoon coarse salt
C:\Users\rose\recipes> <strong>hg com -m "spicier kind of chile"</strong>
C:\Users\rose\recipes> <strong>hg log</strong>
changeset: 2:689026657682
tag: tip
user: Rose Hillman <rose@example.com>
date: Mon Feb 08 15:29:09 2010 -0500
summary: spicier kind of chile
changeset: 1:a52881ed530d
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:51:18 2010 -0500
summary: Change crunch to smoosh
changeset: 0:c1fb7e7fbe50
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:50:08 2010 -0500
summary: Initial version of guacamole recipe
</pre>
<div class="codebottom"> </div>
</div>
<p>While Rose was making her change, I can make a change at the same time.</p>
<div class="edit1">
<div class="edittopbefore">
guac </div>
<div class="editcontent">
…<br>
* 1/2 ripe tomato, seeds and pulp removed, chopped<br><br>
Smoosh all ingredients together.<br>
Serve with tortilla chips.<br>
</div>
<img src="i/edit-bot.gif" width="387" height="76" />
</div>
<div class="edit2">
<img src="i/arrow2.gif" width="83" height="97" class="editArrow" />
<div class="edittopafter">
guac
</div>
<div class="editcontent">
…<br>
* 1/2 ripe tomato, seeds and pulp removed, chopped<br><br>
Smoosh all ingredients together.<br>
Serve with <strong>potato</strong> chips.
</div>
<img src="i/edit-bot.gif" width="387" height="76" />
</div>
<div style="clear: both;"> </div>
<p>After I check that in, you’ll see that my log shows something different as changeset #2 than Rose’s log.</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg com -m "potato chips. No one can eat just one."</strong>
C:\Users\joel\recipes> <strong>hg log</strong>
changeset: 2:4ecdb2401ab4
tag: tip
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 15:32:01 2010 -0500
summary: potato chips. No one can eat just one.
changeset: 1:a52881ed530d
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:51:18 2010 -0500
summary: Change crunch to smoosh
changeset: 0:c1fb7e7fbe50
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:50:08 2010 -0500
summary: Initial version of guacamole recipe
</pre>
<div class="codebottom"> </div>
</div>
<p>Our histories are starting to diverge.</p>
<img src="i/02-repo-4.png" />
<p>Don’t worry… in a minute we’ll see how to bring these diverging changes back together into one delicious habanero-based potato chip dip.</p>
<div class="cheatcontent" style="margin-top:-15px">
<div class="cheattop">
<div class="command">hg outgoing</div>
</div>
<p class="cheattext">list changes in current repository waiting to be pushed </p>
<img src="i/cheatbot.png" width="241" height="41" />
</div>
<p>Rose can continue to work, disconnected, making as many changes as she wants, and either committing them, or reverting them, in her own repository. At some point, though, she’s going to want to share all the changes she’s been committing with the outside world. She can type <strong>hg outgoing</strong> which will show a list of changes that are waiting to be sent up to the central repository. These are the changes that <strong>hg push</strong> would send, if she were to <strong>hg push</strong>.</p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose\recipes> <strong>hg outgoing</strong>
comparing with http://joel.example.com:8000/
searching for changes
changeset: 2:689026657682
tag: tip
user: Rose Hillman <rose@example.com>
date: Mon Feb 08 15:29:09 2010 -0500
summary: spicier kind of chile
</pre>
<div class="codebottom"> </div>
</div>
<p>Think of <strong>hg outgoing</strong> like this: it simply lists any changes in the current repository that aren’t in the central repository.</p>
<p>OK, so Rose pushes her changes.</p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose\recipes> <strong>hg push</strong>
pushing to http://joel.example.com:8000/
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
</pre>
<div class="codebottom"> </div>
</div>
<p>And the world looks like this:</p>
<img src="i/02-repo-5.png" />
<p>When I get back from my fourth latte break of the day, I’m ready to push my potato-chip change, too.</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg outgoing</strong>
comparing with http://joel.example.com:8000/
searching for changes
changeset: 2:4ecdb2401ab4
tag: tip
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 15:32:01 2010 -0500
summary: potato chips. No one can eat just one.
C:\Users\joel\recipes> <strong>hg push</strong>
pushing to http://joel.example.com:8000/
searching for changes
abort: push creates new remote heads!
(did you forget to merge? use push -f to force)
</pre>
<div class="codebottom"> </div>
</div>
<p>Ahhh!! Failure! By the way… that message you see there? The one that says <strong>use push -f to force?</strong> That’s <em>terrible</em> advice. Never, ever, EVER use <strong>push -f</strong> to force. You will regret it. Trust me for now.</p>
<p>The reason Rose’s push succeeded while mine failed is because potato chips do not go well with guacamole. Just kidding! I wanted to see if you were awake, there.</p>
<p>The push failed because we both made changes, and so they need to be merged somehow, and Mercurial knows it.</p>
<p>The first thing I’m going to do is get all those changes that are in the central repository that I don’t have yet, so I can merge them.</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg incoming</strong>
comparing with http://joel.example.com:8000/
searching for changes
changeset: 3:689026657682
tag: tip
parent: 1:a52881ed530d
user: Rose Hillman <rose@example.com>
date: Mon Feb 08 15:29:09 2010 -0500
summary: spicier kind of chile
C:\Users\joel\recipes> <strong>hg pull</strong>
pulling from http://joel.example.com:8000/
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)
</pre>
<div class="codebottom"> </div>
</div>
<p>There’s some gibberish there about +1 heads. That’s because my repository, which used to just have three changes neatly stacked, is now a two-headed monster, with two different changes stacked precariously on top like this:</p>
<div class="i">
<img src="i/02-repo-6.png" />
</div>
<p>I’ve got both versions in my repository now… I’ve got my version:</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>type guac</strong>
* 2 ripe avocados
* 1/2 red onion, minced (about 1/2 cup)
* 1-2 serrano chiles, stems and seeds removed, minced
* 2 tablespoons cilantro leaves, finely chopped
* 1 tablespoon of fresh lime or lemon juice
* 1/2 teaspoon coarse salt
* A dash of freshly grated black pepper
* 1/2 ripe tomato, seeds and pulp removed, chopped
Smoosh all ingredients together.
Serve with potato chips.
</pre>
<div class="codebottom"> </div>
</div>
<p>And I’ve got Rose’s version:</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg cat -r 3 guac</strong>
* 2 ripe avocados
* 1/2 red onion, minced (about 1/2 cup)
* 1-2 habanero chiles, stems and seeds removed, minced
* 2 tablespoons cilantro leaves, finely chopped
* 1 tablespoon of fresh lime or lemon juice
* 1/2 teaspoon coarse salt
* A dash of freshly grated black pepper
* 1/2 ripe tomato, seeds and pulp removed, chopped
Smoosh all ingredients together.
Serve with tortilla chips.
</pre>
<div class="codebottom"> </div>
</div>
<p>And it’s up to me to merge them. Luckily, this is easy.</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg merge</strong>
merging guac
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
C:\Users\joel\recipes> <strong>type guac</strong>
* 2 ripe avocados
* 1/2 red onion, minced (about 1/2 cup)
* 1-2 habanero chiles, stems and seeds removed, minced
* 2 tablespoons cilantro leaves, finely chopped
* 1 tablespoon of fresh lime or lemon juice
* 1/2 teaspoon coarse salt
* A dash of freshly grated black pepper
* 1/2 ripe tomato, seeds and pulp removed, chopped
Smoosh all ingredients together.
Serve with potato chips.
</pre>
<div class="codebottom"> </div>
</div>
<p>Look! The <strong>hg merge</strong> command took my two heads and combined them together. In this case, since we both edited different parts of the file, there was no conflict at all and the merge went off without a hitch.</p>
<div class="cheatcontent" style="margin-top:-65px">
<div class="cheattop">
<div class="command">hg merge</div>
</div>
<p class="cheattext">merge two heads </p>
<img src="i/cheatbot.png" width="241" height="41" />
</div>
<p>I still have to commit. This is important. If the merge failed, I could always revert and try again. Since the merge was successful, I’m going to commit it. Then I’ll be able to push my changes to the central repository.</p>
<div class="codesnippetjoel">
<div class="codetop"> </div>
<pre class="joel">
C:\Users\joel\recipes> <strong>hg commit -m "merge"</strong>
C:\Users\joel\recipes> <strong>hg log</strong>
changeset: 4:0849ca96c304
tag: tip
parent: 2:4ecdb2401ab4
parent: 3:689026657682
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 16:07:23 2010 -0500
summary: merge
changeset: 3:689026657682
parent: 1:a52881ed530d
user: Rose Hillman <rose@example.com>
date: Mon Feb 08 15:29:09 2010 -0500
summary: spicier kind of chile
changeset: 2:4ecdb2401ab4
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 15:32:01 2010 -0500
summary: potato chips. No one can eat just one.
changeset: 1:a52881ed530d
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:51:18 2010 -0500
summary: Change crunch to smoosh
changeset: 0:c1fb7e7fbe50
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:50:08 2010 -0500
summary: Initial version of guacamole recipe
C:\Users\joel\recipes> <strong>hg out</strong>
comparing with http://joel.example.com:8000/
searching for changes
changeset: 2:4ecdb2401ab4
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 15:32:01 2010 -0500
summary: potato chips. No one can eat just one.
changeset: 4:0849ca96c304
tag: tip
parent: 2:4ecdb2401ab4
parent: 3:689026657682
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 16:07:23 2010 -0500
summary: merge
C:\Users\joel\recipes> <strong>hg push</strong>
pushing to http://joel.example.com:8000/
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
</pre>
<div class="codebottom"> </div>
</div>
<p>And now the central repository has the same thing as I do:</p>
<img src="i/02-repo-7.png" />
<p>OK, I have Rose’s changes, and my changes, but Rose doesn’t have my changes yet.</p>
<p>One thing I forgot to tell you about Rose. She’s a doctor. Yep. A medical doctor. Isn’t that weird? She was a hotshot pediatrician at Mt. Sinai, probably earning five times as much as this crappy joint pays its testers. Nobody really knows why she left the field of medicine. The other testers think something tragic happened. She had a family, once, too; there’s a picture of a cute ten year old on her desk, but now she lives alone, and we don’t want to pry.</p>
<p>Rose needs to
pull the latest, incoming stuff from the repository to get it.</p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose\recipes> <strong>hg pull</strong>
pulling from http://joel.example.com:8000/
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
(run 'hg update' to get a working copy)
</pre>
<div class="codebottom"> </div>
</div>
<p>Got it. Now, you may find this a bit odd, but even though Rose pulled those new changes into her repository, <em>they’re not in her working directory yet.</em></p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose\recipes> <strong>type guac</strong>
* 2 ripe avocados
* 1/2 red onion, minced (about 1/2 cup)
* 1-2 habanero chiles, stems and seeds removed, minced
* 2 tablespoons cilantro leaves, finely chopped
* 1 tablespoon of fresh lime or lemon juice
* 1/2 teaspoon coarse salt
* A dash of freshly grated black pepper
* 1/2 ripe tomato, seeds and pulp removed, chopped
Smoosh all ingredients together.
Serve with tortilla chips.
</pre>
<div class="codebottom"> </div>
</div>
<p>See that? She’s still working with Tortilla chips. Tortilla chips!</p>
<p>She <em>does</em> have my new changes somewhere in her repository…</p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose\recipes> <strong>hg log</strong>
changeset: 4:0849ca96c304
tag: tip
parent: 3:4ecdb2401ab4
parent: 2:689026657682
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 16:07:23 2010 -0500
summary: merge
changeset: 3:4ecdb2401ab4
parent: 1:a52881ed530d
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 15:32:01 2010 -0500
summary: potato chips. No one can eat just one.
changeset: 2:689026657682
user: Rose Hillman <rose@example.com>
date: Mon Feb 08 15:29:09 2010 -0500
summary: spicier kind of chile
changeset: 1:a52881ed530d
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:51:18 2010 -0500
summary: Change crunch to smoosh
changeset: 0:c1fb7e7fbe50
user: Joel Spolsky <joel@joelonsoftware.com>
date: Mon Feb 08 14:50:08 2010 -0500
summary: Initial version of guacamole recipe
</pre>
<div class="codebottom"> </div>
</div>
<div class="cheatcontent" style="margin-top:0px">
<div class="cheattop">
<div class="command">hg parent</div>
</div>
<p class="cheattext">show the changeset that’s in the working directory </p>
<img src="i/cheatbot.png" width="241" height="41" />
</div>
<p>They’re just not in her working directory. That’s because she’s still working off of changeset #2. You can see this with the “parent” command:</p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose\recipes> <strong>hg parent</strong>
changeset: 2:689026657682
user: Rose Hillman <rose@example.com>
date: Mon Feb 08 15:29:09 2010 -0500
summary: spicier kind of chile
</pre>
<div class="codebottom"> </div>
</div>
<p>Mercurial is being nice to us. It’s always safe to pull; all it does is get us the latest changes that other people have been making. We can switch to working with them later, at our own convenience.<p>
<p>Remember that the <strong>hg up</strong> command with no arguments will change the working directory to the <em>tip</em> (the absolute TOP changeset), in this case number 4:</p>
<div class="codesnippetrose">
<div class="codetop"> </div>
<pre class="rose">
C:\Users\rose\recipes> <strong>hg up</strong>
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
C:\Users\rose\recipes> <strong>type guac</strong>
* 2 ripe avocados
* 1/2 red onion, minced (about 1/2 cup)
* 1-2 habanero chiles, stems and seeds removed, minced
* 2 tablespoons cilantro leaves, finely chopped
* 1 tablespoon of fresh lime or lemon juice
* 1/2 teaspoon coarse salt
* A dash of freshly grated black pepper
* 1/2 ripe tomato, seeds and pulp removed, chopped
Smoosh all ingredients together.
Serve with potato chips.
</pre>
<div class="codebottom"> </div>
</div>
<p>And now, she’s looking at the latest version with everybody’s changes.</p>
<p>When you’re working on a team, your workflow is going to look a lot like this:</p>
<ol>
<li>If you haven’t done so in a while, get the latest version that everyone else is
working off of:</li>
<ul>
<li>hg pull</li>
<li>hg up</li>
</ul>
<li>Make some changes</li>
<li>Commit them (locally)</li>
<li>Repeat steps 2-3 until you’ve got some nice code that you’re willing to inflict on everyone else</li>
<li>When you’re ready to share:</li>
<ul>
<li>hg pull to get everyone else’s changes (if there are any)</li>
<li>hg merge to merge them into yours</li>
<li>test! to make sure the merge didn’t screw anything up</li>
<li>hg commit (the merge)</li>
<li>hg push</li>
</ul>
</ol>
<h2>Test yourself</h2>
<p>Here are the things you should know how to do after reading this tutorial:</p>
<ol>
<li>Set up a central repository and let team members clone off of it</li>
<li>Push changes into the central repository</li>
<li>Pull changes from the central repository</li>
<li>Merge changes from different contributors</li>
</li>
</ol>
<div class="footer">
<div class="footernav" id="home" align="center"><a href="index.html"><span class="angleQuote">«</span> Home</a></div>
<div class="footernav" id="comingup">Next, we talk about how to fix <span style="text-decoration: line-through;">misstakes</span> mistakes. </div>
<div class="footernav" id="next" align="center"><a href="03.html">Next <span class="angleQuote">»</span></a></div>
</div>
<div class="pagebottom">
<div class="bottomimg">
<a href="http://www.kilnhg.com" target="_blank" id="logoLink" title="KilnHg.com" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/klinhg.com');"> </a>
<div class="bottomtext">This tutorial was brought to you by the fine folks at Fog Creek Software, makers of Kiln, a version control system powered by Mercurial</div>
<div class="bottomtext"><strong>Kiln gives you:</strong><br />
• A complete version control system based on <a href="http://mercurial.selenic.com/" target="_blank" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/mercurial.selenic.com');">Mercurial</a><br />
• <a href="http://fogcreek.com/kiln/learnmore.html#hist_BranchAndMerge" target="_blank" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/branchandmerge.kilnhg.com');">Branching and merging</a> that really works<br />
• <a href="http://fogcreek.com/kiln/learnmore.html#hist_Tools" target="_blank" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/tools.kilnhg.com');">Straightforward setup</a> on your server, or simple secure hosting on ours<br />
• Seamlessly integrated <a href="http://fogcreek.com/kiln/learnmore.html#hist_StartReviewsEffortlessly" target="_blank" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/startreviews.kilnhg.com');">code review</a><br />
</div>
<div class="bottomtext getStarted">
<a href="convert.html" target="_blank" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/freetrial.shop.fogcreek.com');"><img src="i/getstarted.gif" width="114" height="24" border="0" /></a>
</div>
</div>
<div class="about">
<p>
<strong>Any questions?</strong>
</p>
<p>
If you have any questions about the material in this tutorial,
no matter how newbie, ask them at <a href="http://kiln.stackexchange.com/" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/kiln.stackexchange.com');">the
Kiln Knowledge Exchange.</a>
</p>
<p>
<strong>About the author.</strong>
</p>
<p>
Joel Spolsky is the founder of <a href="http://fogcreek.com" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/fogcreek.com');">Fog Creek Software</a>, a New York company that proves that you can treat programmers well and still be profitable. Programmers get private offices, free lunch, and work 40 hours a week. Customers only pay for software if they’re delighted. Fog Creek makes <a href="http://www.fogbugz.com" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/fogbugz.com');">FogBugz</a>, <a href="http://www.kilnhg.com/" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/text.kilnhg.com');">Kiln</a>, and <a href="https://www.copilot.com/" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/copilot.com');">Fog Creek Copilot</a>. Joel's blog <a href="http://www.joelonsoftware.com/" onClick="javascript: pageTracker._trackPageview('/outbound/bottom/joelonsoftware.com');">Joel on Software</a> is read by programmers everywhere.
</p>
</div>
<!-- close bottom div -->
</div>
<!-- close "content" column -->
</div>
<!-- close "main" div -->
</div>
<!-- bottom grey bar -->
<div class="botbot" align="left">
</div>
<!-- Google Website Optimizer Tracking Script -->
<script type="text/javascript">
if(typeof(_gat)!='object')document.write('<sc'+'ript src="http'+
(document.location.protocol=='https:'?'s://ssl':'://www')+
'.google-analytics.com/ga.js"></sc'+'ript>')</script>
<script type="text/javascript">
try {
var gwoTracker=_gat._getTracker("UA-225715-15");
gwoTracker._trackPageview("/2687020024/test");
}catch(err){}</script>
<!-- End of Google Website Optimizer Tracking Script -->
</body>
</html>
|
Loading...