{"id":1615,"date":"2013-04-02T00:00:00","date_gmt":"2013-04-02T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/beginning-distributed-version-control-with-mercurial\/"},"modified":"2021-05-17T18:36:07","modified_gmt":"2021-05-17T18:36:07","slug":"beginning-distributed-version-control-with-mercurial","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/beginning-distributed-version-control-with-mercurial\/","title":{"rendered":"Beginning Distributed Version Control with Mercurial"},"content":{"rendered":"<div class=\"article-content\">\n<p class=\"start\">If you have only lived in the tranquil world of client-server version source control systems, inhabited by such predictable beasts as <a href=\"http:\/\/subversion.tigris.org\/\">SVN<\/a> and <a href=\"https:\/\/www.visualstudio.com\/tfs\/\">TFS<\/a>, your first encounter with a distributed version control system (DVCS) might prove frustrating and scary. While both client-server and distributed systems share many commands, icons and menus they work quite differently.<\/p>\n<p>This article introduces a few DVCS concepts using <a href=\"https:\/\/www.mercurial-scm.org\/\">Mercurial<\/a>, a popular version control system, as an example.<\/p>\n<h2>The Next Generation<\/h2>\n<p>Many experts consider today&#8217;s distributed version control systems, such as, <a href=\"http:\/\/git-scm.com\/\">GIT<\/a>, Mercurial or <a href=\"http:\/\/veracity-scm.com\/\">Veracity<\/a>, to be the latest generation of version control software. Their architecture goes beyond that of the previous generations&#8217; client-server designs, and it isn&#8217;t surprising that they demand a different mindset to use them effectively.<\/p>\n<div class=\"note\">\n<p class=\"note\"><strong>Risky Business<\/strong> <\/p>\n<p> Labeling a vendor&#8217;s version control product as either distributed or client-server is a risky business. Many of them claim to support both architectures. For example, when Microsoft announced a DVC-Team Foundation Server (TFS) solution did that make TFS a client-server, distributed or a hybrid version control system?<\/p>\n<\/div>\n<h3>Architecture<\/h3>\n<p>Version control exists in order to allow several users to edit the same set of text files with minimum pain. There are many ways to accomplish this. The more traditional Client-server version control solutions use file locking, whereas distributed version control solutions prefer repository change coordination as shown below.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-5da1630d-c1b1-4b9a-ae31-8c613abe7fa5.jpeg\" alt=\"1776-5da1630d-c1b1-4b9a-ae31-8c613abe7fa\" \/><\/p>\n<div class=\"note\">\n<p class=\"note\"><strong>Distributed Means Distributed<\/strong> <\/p>\n<p> Our article presents a relatively modest &#8220;centralized distributed version control&#8221; layout. Distributed Version Control Systems in the Enterprise explores several more complex layouts. Despite the simplicity of our layout it may very well be one of the most common in today&#8217;s enterprise.<\/p>\n<\/div>\n<p>The first Version Control systems used File-locking within a centralized repository. This involves explicitly checking out a file, and then checking it in after you&#8217;ve finished editing it. Such an approach ensures that only one user can change a specific file, but it also means that other users cannot change it until you&#8217;ve checked it in. This has developed into an &#8216;optimistic&#8217; model where the system attempts to merge the contents of any file that has been worked on by two different people at the same time.<\/p>\n<p>Distributed version control systems build on this idea. Users still check files in and out of a repository except that now the repository is local and unshared. This essentially eradicates any file locking issues. It also introduces a new challenge: Instead of checking in a file users now must synchronize their local repository with the central repository, as this graphic shows.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-98479cbf-9ac6-41c0-ade8-51efeec6abb5.jpeg\" alt=\"1776-98479cbf-9ac6-41c0-ade8-51efeec6abb\" \/><\/p>\n<p>It&#8217;d be nice to just lock them both and overwrite the older one. However, not even Client-server Version Control systems do that nowadays. It defeats the reason for team-based version control. To help overcome this synchronization obstacle, distributed version control systems use the concepts of changesets and branches.<\/p>\n<p>DVC tools bundle up all changes, such as files and folders, into a changeset. The <a href=\"https:\/\/www.mercurial-scm.org\/wiki\/ChangeSet\">changeset<\/a> is then forwarded to the appropriate repository branch.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-c3b0870d-8c0d-4fdf-b4a1-7199ca111f3f.jpeg\" alt=\"1776-c3b0870d-8c0d-4fdf-b4a1-7199ca111f3\" \/><\/p>\n<p>To apply the changeset to its branch, you need one other piece of information. Where in the branch does the changeset belong? Distributed version control systems answer this question by remembering the identity of the changeset from which the new one started.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-28bf50ff-25d2-4d0c-86bc-d62e4e0543f6.jpeg\" alt=\"1776-28bf50ff-25d2-4d0c-86bc-d62e4e0543f\" \/><\/p>\n<p>The changeset architecture serves another helpful function. It allows two repositories to efficiently synchronize with each other in most situations by only exchanging some changesets, thereby rather than having to copy an entire repository.<\/p>\n<div class=\"note\">\n<p class=\"note\"><strong>Technically speaking&#8230;<\/strong> <\/p>\n<p> Distributed version control systems manage changesets as a directed acyclic graph. Relating changesets in this fashion allows for adding a new one without altering the repository before the addition.<\/p>\n<\/div>\n<p>Distributed version control does not avoid one substantial pain point of the client-server variant. Files within a changeset that don&#8217;t match the central repository&#8217;s version have to be reconciled. Users still need to merge their files&#8217; changes with the central repository&#8217;s files.<\/p>\n<h3>Changing Mindset<\/h3>\n<p>Distributed repositories are very different to work with than server-managed files.<\/p>\n<p>To begin with, client-server source control tools such as Team Foundation Server (TFS) expect users to execute &#8220;get latest&#8221; when refreshing their local copies of files. Distributed tools, such as Mercurial, expect a &#8220;pull&#8221; command to obtain any changesets from the central server that their local repository does not possess.<\/p>\n<p>To commit changes to a local file, a user must first check it out from the client-server source control repository, and then check it in. Distributed tools involve a two-step process. First, users commit their changes to their local repository which creates a changeset. Second, they &#8220;push&#8221; this new changeset to the central repository.<\/p>\n<p>Distributed version control tools place another, subtler demand on users. Every changeset is bound to a specific antecedent changeset along a specific branch. Therefore, whenever a user initiates a change they must establish that point. In technical parlance, users must set the &#8220;rev&#8221;, &#8220;revision&#8221; or &#8220;tip&#8221; that they&#8217;re working.<\/p>\n<h2>Basic Operations<\/h2>\n<p>Let&#8217;s start our review of basic operations with an existential crisis. Our imaginary software developer cannot get their local committed changes to the Mercurial central repository. We will work through how they discover and address the problem via <a href=\"http:\/\/tortoisehg.bitbucket.org\/manual\/2.0\/workbench.html\">Hg Workbench<\/a>.<\/p>\n<p>The scenario involves two developers, Client 1 and Client 2. Each of these developers sport their own repository, <strong>DemoClient1<\/strong> and <strong>DemoClient2<\/strong> which synchronize with the central repository <strong>DemoServer<\/strong>. Client 1&#8217;s inability to push their latest changes to <strong>DemoServer<\/strong> kicks off the crisis&#8230;<\/p>\n<div class=\"note\">\n<p class=\"note\"><strong>Note:<\/strong> Our basic operations chat begins where a tutorial covered later in this article ends. This backward approach is not accidental. The tutorial covers product and command line details readers may not find too interesting. Our current discussion focuses on basic distributed version control tool activities.<\/p>\n<\/div>\n<h3>Push<\/h3>\n<p>Client 1 completed the process of updating <strong>File1.txt<\/strong> and committed the changes to the local repository <strong>DemoClient1<\/strong>. The tragedy begins with the launching of the Hg Workbench and clicking the push button (<img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-81cb9c29-2e28-4d7d-bd5a-1e846c5dc280.png\" alt=\"1776-81cb9c29-2e28-4d7d-bd5a-1e846c5dc28\" \/>). The central repository&#8217;s harsh, pink highlighted response informs Client 1 that the request cannot be executed and is therefore aborted. It informs the user why; the two repositories, <strong>DemoCleint1<\/strong> and <strong>DemoServer<\/strong>, are not synchronized. The pink window also suggests two fixes.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-4a519704-63f7-46fa-934e-dc812ba0773b.png\" alt=\"1776-4a519704-63f7-46fa-934e-dc812ba0773\" \/><\/p>\n<p>The pink window recommends that Client 1 either &#8220;pull and merge&#8221; or &#8220;push -f to force&#8221; in order the get the gray highlighted Rev 1, &#8220;Client 1 updated Test File 1&#8221; changeset into <strong>DemoServer<\/strong>. Since anyone would be right to regard the notion of forcing change as being scary Client 1 elects the first recommendation.<\/p>\n<p>Before pulling anything, it helps to visualize the likely explanation for the cause of the Version Control system aborting Client 1&#8217;s &#8220;push&#8221;. Using our earlier branch-changeset graphic, you can guess that that another changeset node has jumped into the <strong>DemoServer<\/strong>&#8216;s default branch before Client 1&#8217;s Rev 1 arrived.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-47ef6bf9-3ce8-4243-ba09-e59803f8d0ad.jpeg\" alt=\"1776-47ef6bf9-3ce8-4243-ba09-e59803f8d0a\" \/><\/p>\n<h3>Pull<\/h3>\n<p>Clicking the pull button, <img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-6a6bf99c-1899-4467-b1eb-2590b070f598.png\" alt=\"1776-6a6bf99c-1899-4467-b1eb-2590b070f59\" \/>, updates the Workbench&#8217;s &#8216;Revision Graph Details&#8217; window as shown.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-52265f78-ceed-453f-8e7c-a5e3600c1441.png\" alt=\"1776-52265f78-ceed-453f-8e7c-a5e3600c144\" \/><\/p>\n<p>Our node diagram confirms our suspicions. Client 2 pushed changesets Rev 2 and Rev 3 into the central repository leaving our Rev 1 changeset adrift of it in the antecedent node. Client 1 needs to merge Rev 1 with the latest collection of changesets.<\/p>\n<div class=\"note\">\n<p class=\"note\"><strong>Note:<\/strong> The automatic splitting of the default branch into two branches as depicted by the Revision Graph Details windows confuses some first-time DVCS users. This confusion applies especially to developers reared on a client-server tool where branching had the pariah status of development option of last resort.<\/p>\n<\/div>\n<h3>Merge<\/h3>\n<p>Merging begins with Client 1 switching their context to the latest changeset node. In Mercurial parlance, Client 1 &#8220;updates&#8221; their local version of source-controlled files to those of <strong>DemoServer<\/strong> by right-clicking the blue dot of Rev 3. Workbench reflects Client 1&#8217;s decision by changing the tip or &#8220;Rev&#8221; to the highlighted changeset as shown below.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-a5d93690-dbda-4566-83ce-c10247390766.png\" alt=\"1776-a5d93690-dbda-4566-83ce-c1024739076\" \/><\/p>\n<p>Mercurial&#8217;s merge process begins with Client 1 right-clicking the Rev 1 changeset and executing the &#8220;<em>Merge with local&#8230;&#8221;<\/em> menu item. This kicks off a wizard-like exercise walking Client 1 through a series of steps which includes resolving any file differences. If Client 1 successfully works through these steps, then the Revision Graph Details window as shown below displays a new changeset that captures these implicit merge edits.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-52627369-9b7b-44f2-b1d9-0541e13f827d.png\" alt=\"1776-52627369-9b7b-44f2-b1d9-0541e13f827\" \/><\/p>\n<div class=\"note\">\n<p class=\"note\"><strong>Merging Still Matters<\/strong> <\/p>\n<p> Some enterprises adopt a distributed version control solution in the belief that it simplifies the process of merging different source code branches. The changeset-node architecture along with the state of the art merging algorithms found in most DVC tools surely ease the worst of merge madness. But figuring out what stays and what goes when two files must become one remains a headache.<\/p>\n<\/div>\n<p>With both the local and server repositories synchronized, Client 1 is then ready to &#8220;push&#8221; once more, except this time with two changesets, the original Rev 1 and the merge Rev 4. Assuming Client 2 did not change something since the last &#8220;pull&#8221;, the &#8220;push&#8221; command succeeds as shown below in Client&#8217;s Workbench.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-a780b659-4e88-4590-87ac-32b793f43e3a.png\" alt=\"1776-a780b659-4e88-4590-87ac-32b793f43e3\" \/><\/p>\n<p>Client 1&#8217;s crisis has ended. The central repository, <strong>DemoServer<\/strong>, now includes the Rev 1 changeset which initiated the crisis. Workbench confirms the fact with the green window&#8217;s text along with the &#8220;Phase&#8221; grid column of the two changesets. Before the push, the changesets&#8217; exhibited a &#8220;draft&#8221; phase. Afterwards the phase they became &#8220;public&#8221; and available to any repositories working with <strong>DemoServer<\/strong>.<\/p>\n<h3>Rebase<\/h3>\n<p>Some users find this merge process cumbersome if not graphically unappealing<em>. <\/em>Why bother creating a second merge changeset and a short-lived branch just because another changeset jumped in? Couldn&#8217;t Client 1 simply update the <strong>DemoClient1<\/strong> repository and reapply the Rev 1 changeset? The short answer is yes; the supporting magic goes by the name &#8220;Rebase&#8221;.<\/p>\n<p>The decision to rebase occurs temporally and graphically at the same point as the &#8220;Merge with local&#8230;&#8221; option joined the fray as shown below.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-598812a2-3212-46ee-8bec-4149b2d7a27b.png\" alt=\"1776-598812a2-3212-46ee-8bec-4149b2d7a27\" \/><\/p>\n<p>As with the &#8220;Merge with local&#8230;&#8221; menu, &#8220;Rebase&#8230;&#8221; initiates a wizard-like workflow that helps the user to resolve any file differences. The difference is that, this time, when the wizard finishes, the Workbench displays a cleaner <em>Revision Graph Details<\/em> window.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-4e4d1fa2-1563-4190-af0f-f34213aa8470.png\" alt=\"1776-4e4d1fa2-1563-4190-af0f-f34213aa847\" \/><\/p>\n<p>Our simpler node graph happens after the rebase process tricks the local repository into believing that Client 1&#8217;s original changeset began with the central repository&#8217;s latest changeset, Rev 2. It does so by helping Client 1 to synchronize repositories and then quietly recreate the original changeset with the appropriate antecedent. You&#8217;d be able to confirm the story by carefully comparing the graphs that followed clicking &#8220;<em>Merge with local&#8230;&#8221;<\/em> versus &#8220;<em>Rebase&#8230;&#8221;<\/em> menus. (Hint: Look at the Rev 1 changeset.)<\/p>\n<p>By pushing the rebase changeset to <strong>DemoServer<\/strong>, we leave Client 1 emotionally uncompromised as well as artistically uncluttered: as show below.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-a980cc8f-022d-428f-9685-59946603494f.png\" alt=\"1776-a980cc8f-022d-428f-9685-59946603494\" \/><\/p>\n<div class=\"note\">\n<p class=\"note\"><strong>Merge or Rebase?<\/strong> <\/p>\n<p> Developers often ask whether it is better to merge or rebase. Ignoring artistic biases for linear or bumpy changeset graphs and complex technical minutiae, experience suggests a simple rule. If possible, rebase draft changesets; always merge public. Put another way, once a changeset hits the central server do not rebase &#8211; it&#8217;ll likely confuse other developers.<\/p>\n<\/div>\n<h2>Tutorial Time<\/h2>\n<p>Rather than letting you struggle to learn distributed version control basics with a production repository, I&#8217;ll describe in this section the process of setting up and playing with Mercurial on a Windows computer. Our discussion covers several of the more ubiquitous ideas and line commands.<\/p>\n<h3>Installation<\/h3>\n<p>Readers expecting pain when installing a server product on their computer will be disappointed. Installing and running Mercurial borders on fun. Start the exercise by <a href=\"https:\/\/www.mercurial-scm.org\/downloads\">downloading<\/a> the appropriate OS version.<\/p>\n<div class=\"note\">\n<p class=\"note\"><strong>Note:<\/strong> The discussion that follows used the &#8220;Mercurial 2.5.1 MSI installer &#8211; x86 Windows&#8221; install.<\/p>\n<\/div>\n<p>After downloading the installation executable, <a href=\"http:\/\/www.thewindowsclub.com\/fix-windows-blocked-access-file\">unblock<\/a> and click it. You are unlikely to endanger life by choosing any of the various installation options or defaults. The defaults should be fine for most requirements. Now run Mercurial via the command window.<\/p>\n<h3>Initialization<\/h3>\n<p>Here are the commands used to create a local &#8220;server&#8221; repository and a local &#8220;client&#8221; repository.<\/p>\n<p>Starting from the root, which for this discussion will be C:\\, we will create the required directories and repositories. All of the commands are either DOS, in upper case, or Mercury, in lower case. All Mercury commands begin with the hg prefix. (Why &#8220;hg&#8221;? It&#8217;s the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Periodic_table\">periodical table<\/a> identifier for the Mercury element.)<\/p>\n<pre class=\"listing\">MD HgDemo\r\nhg init c:\\HGDemo\\DemoServer\r\nhg init c:\\HGDemo\\DemoClient1<\/pre>\n<p>The init command creates directories and files for the &#8220;<strong>DemoServer<\/strong>&#8221; and &#8220;<strong>DemoClient1<\/strong>&#8221; repositories. Before going we need to attend to some further minor configuration information.<\/p>\n<p>First, visit the <strong>C:\\HgDemo\\DemoServer\\.hg<\/strong>directory. Once there create the file <strong>hgrc<\/strong> (no extension!) with your text editor and paste in these lines.<\/p>\n<pre class=\"listing\">[web]\r\npush_ssl=False\r\nallow_push=*<\/pre>\n<p>The two settings<strong>, push_ssl<\/strong> and <strong>allow_push<\/strong> enable our <strong>DemoServer<\/strong> repository to behave as a centralized repository.<\/p>\n<div class=\"note\">\n<p class=\"note\"><strong>Warning:<\/strong> The above [web] settings are unsuitable for production, but they are perfect for experimenting locally with Mercurial. For example, push ssl=False allows any user to push and pull changes to <strong>DemoServer<\/strong> without permission.<\/p>\n<\/div>\n<p>Next, visit the <strong>C:\\HgDemo\\DemoClient1\\.hg<\/strong> directory. There, create another hgrc file and paste in the below.<\/p>\n<pre class=\"listing\">[paths]\r\ndefault = http:\/\/localhost:8000\/\r\n[ui]\r\nusername = Client 1 &lt;client1@test.com&gt;\r\n[extensions]\r\nrebase =\r\nmq =<\/pre>\n<p>The first setting, <strong>default,<\/strong> links Client 1&#8217;s repository to <strong>DemoServer<\/strong>. The obvious username property gives <strong>DemoClient1<\/strong> a default user when working other repositories. The last two settings expose <strong>DemoClient1<\/strong> users to the <a href=\"https:\/\/www.mercurial-scm.org\/wiki\/RebaseExtension\">rebase<\/a> functionality as discussed earlier in this article.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-e4f401b7-c0b3-43aa-8d17-6a2621198460.png\" alt=\"1776-e4f401b7-c0b3-43aa-8d17-6a262119846\" \/><\/p>\n<p>With this file structure in place the repository can now be started with this <strong>serve <\/strong>command.<\/p>\n<pre class=\"listing\">CD c:\\HGDemo\\DemoServer\r\nhg serve\r\n<\/pre>\n<p>If we have configured everything properly, then <code>http:\/\/localhost:8000\/<\/code> displays an empty <strong>DemoServer<\/strong> repository. Closing the command window or pressing CONTROL+C within will stop the server.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-f7d472fa-1973-434c-8c7f-c3b26da8fc90.png\" alt=\"1776-f7d472fa-1973-434c-8c7f-c3b26da8fc9\" \/><\/p>\n<p>Now that our initialization efforts are wrapped up, it is time to put the<strong> DemoServer<\/strong> repository to work.<\/p>\n<h3>Working with DemoClient1<\/h3>\n<p>Client 1&#8217;s work begins with a new command window. Inside of it we will add <strong>TestFile1.txt<\/strong>; commit it to the <strong>DemoClient1<\/strong> repository; and push it to the <strong>DemoServer<\/strong> repository.<\/p>\n<pre class=\"listing\">CD C:\\HgDemo\\DemoClient1\\\r\nECHO COMMIT00 &gt; TestFile1.txt\r\nhg add\r\nhg commit -m \"Client 1 added Test File 1\"\r\nhg push<\/pre>\n<p>The hg command, add, notifies the <strong>DemoClient1<\/strong> repository of the new <strong>TestFile1<\/strong> file. <strong>Client1<\/strong> can then commit it to the <strong>DemoClient1<\/strong> via <strong>hg commit<\/strong>. The <strong>-m<\/strong> parameter prefaces the required comment when committing a change. The last hg command, <strong>push<\/strong>, forwards the changeset to the <strong>DemoServer<\/strong> repository.<\/p>\n<h3>Working with DemoClient2<\/h3>\n<p>With a populated central repository, Client 2 joins the fray by copying the <strong>DemoServer<\/strong> repository. Whereas Client 1 manually performed this task by configuring the path to <strong>DemoServer<\/strong>, Client2 takes a quicker and more typical route via the clone command within a new command window.<\/p>\n<pre class=\"listing\">MD C:\\HgDemo\\DemoClient2\\\r\nCD C:\\HgDemo\\DemoClient2\\\r\nhg clone http:\/\/localhost:8000\/<\/pre>\n<p>The hg clone command performs two tasks. First, it automatically populates the <strong>C:\\HgDemo\\DemoClient2\\<\/strong> directory with <strong>TestFile1.txt <\/strong>file. Second, it creates the <strong>C:\\HgDemo\\DemoClient2\\.hg\\hgrc<\/strong> file with the text &#8220;[paths] default = http:\/\/localhost:8000\/&#8221;.<\/p>\n<p>Before performing any work though, Client 2&#8217;s <strong>DemoClient2<\/strong> repository needs a little more configuration information akin to that of <strong>D<\/strong><strong>emoCient1<\/strong>. Open C:\\HgDemo\\DemoClient2\\.hg\\hgrc and add the below after the existing <em>[paths] default = http:\/\/localhost:8000\/<\/em> text.<\/p>\n<pre class=\"listing\">[ui]\r\nusername = Client 2 &lt;client2@test.com&gt;\r\n[extensions]\r\nrebase =\r\nmq =<\/pre>\n<p>With <strong>DemoCient2 <\/strong>configured, Client 2 may now work with their local repository and <strong>DemoServer<\/strong>. The next four commands add the file, <strong>TestFile2.txt<\/strong>, with the text &#8220;Committ01&#8221; and push it to the central repository.<\/p>\n<pre class=\"listing\">ECHO COMMIT01 &gt; TestFile2.txt\r\nhg add\r\nhg commit -m \"Client 2 added Test File 2\"\r\nhg push<\/pre>\n<p>Client 2 is a busy developer and now updates the original <strong>TestFile1.txt <\/strong>with the below.<\/p>\n<pre class=\"listing\">ECHO COMMIT02 &gt; TestFile1.txt\r\nhg commit -m \"Client 2 updated Test File 1\"\r\nhg push<\/pre>\n<h3>Working (again) with DemoClient1<\/h3>\n<p>Client 1 was not slacking while Client 2 hammered away. Client 1 stayed busy editing and committing <strong>TestFile1.txt <\/strong>changes.<\/p>\n<pre class=\"listing\">CD C:\\HgDemo\\DemoClient1\\\r\nECHO COMMIT03 &gt; TestFile1.txt\r\nhg commit -m \" Client 1 updated Test File 1\"\r\n<\/pre>\n<p>Some readers might wonder why the last command did not generate some kind of warning. How can both Client 1 and Client 2 alter and commit changes to <strong>TestFile1.txt<\/strong>? It turns out that Client 1&#8217;s repository does not know about Client 2&#8217;s edits which were committed to both <strong>DemoClient1<\/strong> and <strong>DemoServer<\/strong> repositories. As discussed in the earlier Basic Operations section of this article, Client 1 will need to resolve the different edits.<\/p>\n<p>Readers successfully completing this tutorial and visiting their local <strong>DemoServer<\/strong>&#8216;s web site should see a page similar to that displayed below.<\/p>\n<p class=\"illustration center\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1776-0dc2ebf9-5338-4ca0-bf78-4e33c39a3628.png\" alt=\"1776-0dc2ebf9-5338-4ca0-bf78-4e33c39a362\" \/><\/p>\n<h2>Conclusion<\/h2>\n<p>Our introduction ends with three points. First, we only skimmed the surface of distributed version control systems with Mercurial. Readers wishing to dive further may find <a href=\"https:\/\/www.mercurial-scm.org\/learn\">Learn Mercurial<\/a> worth exploring. Second, many Mercurial users don&#8217;t find all the built-in tools productive. For example, they might catch a lift with PowerShell scripts like <a href=\"http:\/\/poshhg.codeplex.com\/\">Posh-Hg<\/a>. Lastly, personal thanks to my friends at Thomson Reuters. Still amazes me that Barnabas H, Chad A, Rob G and Troy D never stopped providing intelligent answers to my many dumb questions. Thank you.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The move from client-server version ontrol systems (VCS) to distributed version control systems can be bewildering.  Tom uses his experience of moving to Mercurial to explain those aspects of the move that are liable to cause confusion to anyone steeped in the culture of the traditional VCS. Rebase, Push, Pull and Merge explained!&hellip;<\/p>\n","protected":false},"author":200451,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4229,4156,5838,5716,5717,4179,5501],"coauthors":[17935],"class_list":["post-1615","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-net-framework","tag-asp","tag-dvcs","tag-hg","tag-mercurial","tag-source-control","tag-version-control"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1615","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/200451"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1615"}],"version-history":[{"count":6,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1615\/revisions"}],"predecessor-version":[{"id":78586,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1615\/revisions\/78586"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1615"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1615"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1615"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}