<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>experimentalworks &#187; Version Control</title>
	<atom:link href="http://blog.experimentalworks.net/category/vcs/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.experimentalworks.net</link>
	<description></description>
	<lastBuildDate>Fri, 27 Jan 2012 10:07:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Locate your commits or how to use geocommit.</title>
		<link>http://blog.experimentalworks.net/2011/01/locate-your-commits-or-how-to-use-geocommit/</link>
		<comments>http://blog.experimentalworks.net/2011/01/locate-your-commits-or-how-to-use-geocommit/#comments</comments>
		<pubDate>Tue, 04 Jan 2011 14:48:30 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[Entropia]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Version Control]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=478</guid>
		<description><![CDATA[This blog post will show you how to use geocommit in your projects. It shows how to install the Chrome and Firefox extensions to add support for geocommit to github.com and bitbucket.org]]></description>
			<content:encoded><![CDATA[<p>We recently launched <a href="http://geocommit.com">geocommit.com</a>. Geocommit is a service to add geolocation data to your commits. You only need a working WiFi connection. <em>No GPS module is required</em>.</p>
<p>This blogpost gives you an example how to use geocommit and the geocommit.com services. I&#8217;ll show how to use geocommits in your <a href="http://git-scm.org">Git</a> or <a href="http://mercurial.selenic.com">mercurial</a> project. How to make <a href="http://github.com">github</a> and <a href="http://bitbucket.org">bitbucket</a> more beautiful with our Chrome and Firefox extensions and how to get a fancy map of your geocommits.</p>
<h3>What is geocommit</h3>
<p>First of all, geocommit is a text format to attach geolocation data to version control system commits. The geocommit <a href="http://geocommit.com">website</a> has detailed information about the geocommit format.<br />
Second, geocommit is a <em>service</em> to store and analyse your geocommit data. We offer a set of tools and a webservice to make geocommit cool. The Git implementation <em>git geo</em> runs on Mac OS X and Linux. The Mercurial implementation <em>hg-geo</em> runs only under Linux. Mac OS support is under way.</p>
<h3>Git &#038; Geocommit</h3>
<p>To start with geocommit, install <a href="http://github.com/peritus/geocommit">git geo</a>:</p>
<pre>
<b>$ pip install geocommit</b>
</pre>
<p>Go to a project directory and enable geocommit support:</p>
<pre>
$ cd myproject.git
<b>$ git geo setup</b>
geocommit setup
Installing geocommit hook in /home/dsp/awesomeproject/.git/hooks/post-rewrite
Installing geocommit hook in /home/dsp/awesomeproject/.git/hooks/post-merge
Installing geocommit hook in /home/dsp/awesomeproject/.git/hooks/post-commit
</pre>
<p>This will enable geocommit support in your project. If you commit something with git commit, git geo will try to get your current location and add a geocommit. If no WiFi connection is enabled, no geocommit will be created.</p>
<p>Check your geocommits:</p>
<pre>
<b>$ git log --show-notes='geocommit'</b>
commit 5a34e6ebc8cb5c2a394ca26505c1d375095161c4
Merge: 25cf72d 828af6e
Author: David Soria Parra <dsp @php.net>
Date:   Tue Jan 4 14:00:55 2011 +0100

    Merge branch 'master' of https://github.com/jezdez/geocommit

Notes (geocommit):
    geocommit (1.0)
    lat: 48.1211828
    long: 11.4853565
    hacc: 39.0
    src: nmg
</dsp></pre>
<p>Let&#8217;s push our geocommits to github:</p>
<pre>
<b>$ git geo push</b>
</pre>
<p><em>git geo push</em> accepts the same options as git push. It pulls geocommits first, merges them and then pushes geocommits and the given branch to the remote repository.<br />
That&#8217;s everything you need. Easy, isn&#8217;t it? So let&#8217;s see how to enable geocommits on Mercurial and then talk about the Chrome and Firefox extensions.</p>
<hr />
<strong>Deep dive</strong><br />
git geo stores geocommits in git notes. We use the namespace <em>geocommit</em> for that. Git notes have some cool properties. They are metadata and don&#8217;t change the commit hash. Therefore they can be added to a commit at anytime. They are displayed on github and can be deleted without any problem. You also can decide yourself when to push geocommits or not. You can delete already pushed geocommits without breaking the repository or changing any commit sha1. The drawback is that it is hard to deal with git notes from time to time. git notes is a new feature in git and not yet fully supported. We have to write a script to merge git notes as git notes merge is not available before git 1.7.7. </p>
<hr />
<h3>Mercurial &#038; geocommit</h3>
<p>You can add support for geocommits to Mercurial by installing the <a href="http://bitbucket.org/segv/hg-geo">hg-geo</a> extension. Clone the extension and enable it in your hgrc:</p>
<pre>
<b>$ hg clone http://bitbucket.org/segv/hg-geo</b>
$ echo "[extensions]\ngeo=/path/to/hg-geo/geo.py"
$ hg help geo
</pre>
<p>The extension will add an additional line to every commit that you do.</p>
<pre>
<b>$ hg commit</b>
<b>$ hg log -v</b>
changeset:   9:236a0f4c3d2e
tag:         tip
user:        David Soria Parra <dsp @php.net>
date:        Sun Jan 02 03:01:04 2011 +0100
files:       .hgtags
description:
Added tag v1.0.0 for changeset 3079e3ff3083

geocommit(1.0): lat 48.1211306, long 11.4853251, hacc 30.0, src nmg;
</dsp></pre>
<p>Now push your geocommits to <a href="http://bitbucket.org">bitbucket</a>.</p>
<pre>
<b>$ hg push</b>
</pre>
<hr />
<strong>Deep dive</strong><br />
As Mercurial doesn&#8217;t have a way to store metadata, we are adding the geocommit data to the commit message itself. The obvious advantage is that you can use hg-geo with plain Mercurial. You do not need to enable hg-geo on the remote site to push geocommits (like Mercurial bookmarks). The disadvantage is that we modify the commit message and therefore the commit hash. There is no easy way to delete geocommits once they are created.</p>
<hr />
<h3>bitbucket.org and github.com</h3>
<p>We can push geocommits easily now. But how to use them? We can install the Firefox or Chrome extension. This will display a map next to your commit!</p>
<p><strong>Firefox</strong><br />
To install the geocommit extension for Firefox you need Greasemonkey. Greasemonkey is a well know and supported extension that enables user scripts to safely modify the displayed website.</p>
<p>Install Greasemonkey from <a href="https://addons.mozilla.org/de/firefox/addon/748/>addons.mozilla.org and then install the geocommit script from <a href="http://userscripts.org/scripts/show/93129">userscripts.org</a>. You can then browse bitbucket.org or github.com and see a map of your geocommit:</p>
<p><a href="http://blog.experimentalworks.net/wp-content/uploads/2011/01/bb.png"><img src="http://blog.experimentalworks.net/wp-content/uploads/2011/01/bb-300x160.png" alt="bitbucket with geocommit support" title="bitbucket with geocommit support" width="300" height="160" class="alignnone size-medium wp-image-493" /></a></p>
<p><a href="http://blog.experimentalworks.net/wp-content/uploads/2011/01/gh.png"><img src="http://blog.experimentalworks.net/wp-content/uploads/2011/01/gh-300x130.png" alt="github with geocommit support" title="github with geocommit support" width="300" height="130" class="alignnone size-medium wp-image-494" /></a></p>
<p><strong>Chrome</strong><br />
On Chrome install the plugin from<br />
<a href="https://chrome.google.com/extensions/detail/mchakdojblmfdjnhbdopinejdffjjgga">chrome.google.com</a></p>
<h3>Post Hook</h3>
<p>We offer a post hook that you can use with github.com and bitbucket.org. Your commits will be tracked by gecommit.com and we will create a global and a project specific map as well as provide further analytics as soon as possible.</p>
<p><strong>github.com</strong><br />
To install the hook go to th eadmin section of your repository and select <em>Service Hooks</em>.<br />
<a href="http://blog.experimentalworks.net/wp-content/uploads/2011/01/gh-hook1.png"><img src="http://blog.experimentalworks.net/wp-content/uploads/2011/01/gh-hook1-300x113.png" alt="" title="gh-hook1" width="300" height="113" class="alignnone size-medium wp-image-499" /></a></p>
<p>Add <em>http://hook.geocommit.com/api/github</em> as a POST service hook.<br />
<a href="http://blog.experimentalworks.net/wp-content/uploads/2011/01/gh-hook2.png"><img src="http://blog.experimentalworks.net/wp-content/uploads/2011/01/gh-hook2-300x131.png" alt="" title="gh-hook2" width="300" height="131" class="alignnone size-medium wp-image-500" /></a></p>
<p><strong>on bitbucket.org</strong><br />
Go to the admin seciton of your repository and select <em>Services</em><br />
<a href="http://blog.experimentalworks.net/wp-content/uploads/2011/01/bb-hook1.png"><img src="http://blog.experimentalworks.net/wp-content/uploads/2011/01/bb-hook1-300x117.png" alt="" title="bb-hook1" width="300" height="117" class="alignnone size-medium wp-image-502" /></a></p>
<p>Add <em>http://hook.geocommit.com/api/bitbucket</em> as a POST service hook<br />
<a href="http://blog.experimentalworks.net/wp-content/uploads/2011/01/bb-hook21.png"><img src="http://blog.experimentalworks.net/wp-content/uploads/2011/01/bb-hook21-300x140.png" alt="" title="bb-hook2" width="300" height="140" class="alignnone size-medium wp-image-504" /></a></p>
<p>Thats about it. Browse <a href="http://www.geocommit.com/full.html">www.geocommit.com/full.html</a> to checkout your commits on our map.</p>
<p>Questions?!<br />
Enjoy!</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=478&amp;md5=b0683e17a20690f1777df225416c7de9" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2011/01/locate-your-commits-or-how-to-use-geocommit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Review remote changes offline in Mercurial</title>
		<link>http://blog.experimentalworks.net/2010/09/review-remote-changes-offline-in-mercurial/</link>
		<comments>http://blog.experimentalworks.net/2010/09/review-remote-changes-offline-in-mercurial/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 12:01:36 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[review]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=467</guid>
		<description><![CDATA[If you want to review remote changes from Mercurial offline you cannot use hg incoming. For sure there is a nice way to do it. So here is what I do to get changes from a repository to review them later without pulling them into my repo before reviewing. It also has the advantage ...]]></description>
			<content:encoded><![CDATA[<p>If you want to review remote changes from Mercurial offline you cannot use <em>hg incoming</em>. For sure there is a nice way to do it. So here is what I do to get changes from a repository to review them later without pulling them into my repo before reviewing. It also has the advantage that you can review changesets that include a given file. This is not possible with <em>hg incoming</em>.</p>
<p>Read the incoming changes and save them in a bundle file:</p>
<pre>$ hg incoming --bundle incoming.bundle http://selenic.com/hg
</pre>
<p>Now you can disconnect and review them offline.</p>
<pre>$ hg -R incoming.bundle log --no-merges -p -- hgext/bookmarks.py
(log pops up)
</pre>
<p>The <em>-R incoming.bundle</em> option tells Mercurial to use the bundle as an overlay for the current repository. The <em>&#8211;no-merges</em> option tells Mercurial to not display merges (which I usually use for reviewing patches) and the <em>-p</em> option is there to display the applied patches in the output. I use <em>&#8211; hgext/bookmarks.py</em> to display only changesets related to the bookmark extension.</p>
<p>Everything&#8217;s good, let&#8217;s pull it:</p>
<pre>$ hg pull incoming.bundle
pulling from incoming.bundle
searching for changes
adding changesets
adding manifests
adding file changes
added 113 changesets with 281 changes to 204 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
</pre>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=467&amp;md5=baf1c6062c9543325ac9a671d32d9b02" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2010/09/review-remote-changes-offline-in-mercurial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mercurial Bookmarks Revisited &#8211; Part I</title>
		<link>http://blog.experimentalworks.net/2010/06/mercurial-bookmarks-revisited-part-i/</link>
		<comments>http://blog.experimentalworks.net/2010/06/mercurial-bookmarks-revisited-part-i/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 08:53:51 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[bookmarks]]></category>
		<category><![CDATA[dvcs]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=453</guid>
		<description><![CDATA[Bookmarks is an extension to the Mercurial SCM, which adds git-like branches to Mercurial. The extension is distributed together with Mercurial.
Recently the extension has received a major update. Time to look back.

This is a series of blogposts that consists of three parts:
 
 (1) Part   I: History of Bookmarks
 (2) Part  ...]]></description>
			<content:encoded><![CDATA[<p>Bookmarks is an extension to the <a href="http://mercurial-scm.org">Mercurial SCM</a>, which adds git-like branches to Mercurial. The extension is distributed together with Mercurial.<br />
Recently the extension has received a major update. Time to look back.</p>
<p>This is a series of blogposts that consists of three parts:</p>
<p> <strong>(1) Part   I: History of Bookmarks</strong><br />
 (2) Part  II: Daily Bookmarking<br />
 (3) Part III: Pushable Bookmarks</p>
<p><strong>UPDATE</strong> I&#8217;m aware that people wait for Part II. Let me see if I can write about it this weekend&#8230;in the meantime, click the flattr button :)<br />
<span id="more-453"></span><br />
I stumbled over Mercurial in August 2007. Back then I had already<br />
used <a href="http://git-scm.org">Git</a> for 6 months, but wanted<br />
to try out different distributed version control systems (<a href="http://en.wikipedia.org/wiki/Distributed_revision_control">DVCS</a>).<br />
I soon began to like Mercurial&#8217;s approach because of its simple and<br />
intuitive interface and its clean codebase. While playing around<br />
with Mercurial for a few weeks I was content with its concepts.<br />
There was one feature missing<br />
that I really like in Git: <a href="http://www.kernel.org/pub/software/scm/git/docs/git-branch.html">git-like branches</a>.</p>
<p>Unlike in Mercurial or in any other version control system, branches in<br />
Git are simply lightweight markers pointing to a commit. Every ancestor of<br />
the commit is considered part of the branch. Back then, this sounded odd to me. Later I realized it was a really good tool to create small local branches. You can create a small branch<br />
for a feature, merge it into your mainline, and remove the branch<br />
without anyone knowing you ever had a branch called<br />
<em>&#8216;stupid-little-feature</em>&#8216;. To make a long story short: It&#8217;s a good<br />
idea to have a similar concept in Mercurial, but none existed back in 2008.</p>
<p>In June 2008 I started developing Mercurial References providing lightweight branches similar to those available in Git. Although the initial work was appreciated by the community, it was rejected<br />
in favor of a concept more natural to Mercurial. Matt Mackall, the author of<br />
Mercurial proposed Mercurial Bookmarks.</p>
<h3>Bookmarks</h3>
<p>The concept of <a href="http://en.wikipedia.org/wiki/Bookmark">bookmarks</a> is easy:<br />
You can bookmark a commit with a unique name.  So it&#8217;s similar to<br />
a tag, with one exception, a bookmark advanced when you commit.<br />
(Like real bookmarks when you go to the next page).</p>
<p>I wrote an initial version of Mercurial Bookmarks in August, that<br />
was finally accepted in October. This improved git like workflows<br />
in Mercurial but still the implementation was far away from what I<br />
wanted. By adding the notion of a so called &#8220;current bookmark&#8221;, it<br />
got better. Still bookmarks had one major drawback in comparison<br />
to git style branches. They were local only. There was no way to<br />
push or pull bookmarks.</p>
<h3>Pushable bookmarks</h3>
<p>This was the status for the past two years. I tried to make bookmarks<br />
pushable during this time. A proposal by me how extensions in general<br />
can exchange arbitrary information over the wire was rejected in<br />
early 2009 because it was too unrestrictive for the protocol. A new<br />
concept, so called &#8216;pushkey concept&#8217; was developed in 2009.  This<br />
was discussed and accepted during the Mercurial Sprint in Paris,<br />
January 2010.</p>
<p>Matt Mackall, who now gets <a href="http://mercurial.selenic.com/sponsors/">sponsored</a> to work on Mercurial,<br />
worked on the <a href="http://selenic.com/hg/rev/ca4fc993087c">initial implementation</a>of pushkey and<br />
pushable bookmarks. And finally after two years of ongoing complains<br />
by people about local-only bookmarks, Mercurial 1.6 will have<br />
pushable bookmarks and introduces a great new concept to exchange<br />
metadata information between repositories.</p>
<p>The next blogpost will show you how to use bookmarks.</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=453&amp;md5=6168d680a8f2a3c2086cec08e10d8f7c" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2010/06/mercurial-bookmarks-revisited-part-i/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Advanced Git Slides</title>
		<link>http://blog.experimentalworks.net/2010/06/advanced-git-slides/</link>
		<comments>http://blog.experimentalworks.net/2010/06/advanced-git-slides/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 12:43:24 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Version Control]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=442</guid>
		<description><![CDATA[Here are the slide from my Advanced Git talk:

Advanced GitView more presentations from segv.]]></description>
			<content:encoded><![CDATA[<p>Here are the slide from my Advanced Git talk:</p>
<div style="width:425px" id="__ss_4509679"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/segv/advanced-git" title="Advanced Git">Advanced Git</a></strong><object id="__sse4509679" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=advancedgit-100615155156-phpapp01&#038;rel=0&#038;stripped_title=advanced-git" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse4509679" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=advancedgit-100615155156-phpapp01&#038;rel=0&#038;stripped_title=advanced-git" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/segv">segv</a>.</div>
</div>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=442&amp;md5=813c6bb8e7078b5c8e360148b314d9dd" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2010/06/advanced-git-slides/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Talks</title>
		<link>http://blog.experimentalworks.net/2010/02/talks/</link>
		<comments>http://blog.experimentalworks.net/2010/02/talks/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 21:53:29 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Version Control]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=401</guid>
		<description><![CDATA[I really enjoy giving talks. This is particularly because I like to teach people something and because I'm really enthusiastic about the technical things I talk about. Once of these things are obviously decentralized version control system, in particular Git and Mercurial. Finally after two years of submitting talks to various conferences, people and ...]]></description>
			<content:encoded><![CDATA[<p>I really enjoy giving talks. This is particularly because I like to teach people something and because I&#8217;m really enthusiastic about the technical things I talk about. Once of these things are obviously decentralized version control system, in particular <a href="http://git-scm.org">Git</a> and <a href="http://mercurial.selenic.com">Mercurial</a>. Finally after two years of submitting talks to various conferences, people and conferences in the <a href="http://php.net">PHP</a> community start to pick up this topic. Seems that 2010 is the year of <a href="http://en.wikipedia.org/wiki/Distributed_revision_control">DVCS</a>, and I&#8217;m really looking forward to give a talk about the<a href="http://phpconference.nl/schedule/talks#advancedgit"> advanced features of Git</a> at</p>
<ul>
<li><a href="http://phpconference.nl">Dutch PHP Conference 2010</a></li>
<li><a href="http://phpconference.de">Interntational PHP Conference</a></li>
</ul>
<p>The talk will give a very brief overview how Git works, and will then give a more detailed insight in how Git handles commits, files, etc so that people get a very good understanding about the concepts that are needed to fully understand tools like git <a href="http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html">rebase</a>, git <a href="http://ftp.sunet.se/pub/Linux/kernel.org/software/scm/git/docs/git-reflog.html">reflog</a> and git <a href="http://ftp.sunet.se/pub/Linux/kernel.org/software/scm/git/docs/git-svn.html">svn</a>. The aim is to provide them will all necessary information and a few examples to get lost commits back, rebase their branches and design more complex git workflows in the future without needing to search the web or ask a guru.</p>
<p>A second talk will be more focused on beginners and developers coming from <a href="http://subversion.tigris.org/">subversion</a>. This talk will be part of a series of talks the german <a href="http://telekom.de">telekom</a> is organizing. I&#8217;ll also give an extended version of this as an in-house workshop at a Munich based company.</p>
<p>So for me it seems that after five years, DVCS is mature enough to get into companies and that we can expect a bright variety of companies to adopt new tools and workflows. Let&#8217;s see what&#8217;s coming&#8230;</p>
<p><strong>For sure I still offer Git and Mercurial trainings, so feel free to contact me (dsp ~at~ php ~dot~ net)</strong></p>
<p><em>probably shameless self promotion</em></p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=401&amp;md5=522082bbe794026117389f3a80a4adb4" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2010/02/talks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Writing a hg to subversion gate</title>
		<link>http://blog.experimentalworks.net/2009/12/writing-a-hg-to-subversion-gate/</link>
		<comments>http://blog.experimentalworks.net/2009/12/writing-a-hg-to-subversion-gate/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 23:59:04 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[dvcs]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[subversion]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=318</guid>
		<description><![CDATA[Using a decentralized version control system (DVCS) like Mercurial (hg) or Git as a client for Subversion is very common. With the unique features of a DVCS a developer can have both the features of offline development and local branching while still being able to push to a subversion server. This approach is often ...]]></description>
			<content:encoded><![CDATA[<p>Using a decentralized version control system (DVCS) like Mercurial (hg) or Git as a client for Subversion is very common. With the unique features of a DVCS a developer can have both the features of offline development and local branching while still being able to push to a subversion server. This approach is often used in environments in which subversion is the given version control system. While the approach of using this bi-directional push and pull mechanism, provided by git-svn or hgsubversion, works perfectly for one developer, it has limitations working in a team using the usual DVCS push and pull concepts.</p>
<p>The following article will outline the current limitations of bi-directional dvcs to subversion bridges and shows a simple approach to implement a solution for a certain instance of the problem.</p>
<p><span id="more-318"></span><br />
<strong>The bi-directional bridge</strong><br />
The idea of finding a way to interchange commits back and forth between a DVCS and subversion was born early in the development of tools like Git and Mercurial. The basic idea is easy to grasp. To initialize a repository the DVCS requests all changes between revision 0 and the current HEAD from the subversion server and imports every change as a regular changeset into the local repository of the DVCS. In addition it maintains a mapping between the local, DVCS specific, changeset IDs and the revision numbers in the subversion repository. If a developer wants to push his newly created changesets from it&#8217;s local repository back to subversion, the bridge determines the latest pushed changeset and then iterates over the unpushed changes, committing them bit by bit to the subversion server. </p>
<p>Depending on the DVCS you use it will then delete the local changeset and reimport the comitted changesets from the subversion server to ensure that the changeset contains the right date and comitter information as well as the right mapping to the subversion revisionnumber.</p>
<p><em>Example</em><br />
To clarify what we just discussed. Assume that we are using git-svn. We are importing a subversion repository with just one commit using the command (I won&#8217;t get into detail how to use the command):<br />
<code><br />
 $ git svn clone svn://example.com/repo<br />
</code><br />
This command results in a repository which in our example contains the following commit.<br />
<code><br />
commit 7a730e9187becbe1979059cd9752fdea38e3cd9e<br />
Author: david &gt;david @cffdd316-8dd2-4046-8f43-d0df91842a18&lt;<br />
Date:   Thu Jul 12 19:39:51 2007 +0000</p>
<p>    Crescas in mille millia<br />
</code><br />
Let&#8217;s asusme that we create a new commit on top:<br />
<code><br />
commit 129e0e4239ac4d375f2a2132dee042a27f2fd70c<br />
Author: David S. P. &gt;dsp at php.ent&lt;<br />
Date:   Fri Jul 13 12:23:42 2007 +0000</p>
<p>	First Draft<br />
</code><br />
If we push it using <em>git svn dcommit</em>, it&#8217;ll be committed into subversion and<br />
reimported as:<br />
<code><br />
commit 8200f32f61432004b488d063564ac9dae7bf6827<br />
Author: david &gt;david @cffdd316-8dd2-4046-8f43-d0df91842a18&lt;<br />
Date:   Fri Jul 13 12:23:42 2007 +0000</p>
<p>	First Draft<br />
</code></p>
<p><strong>Limitations</strong><br />
Tools like <em>git-svn</em> or <em>hgsubversion</em> are working perfectly fine as long as you use them just as a subversion client. There is a serious limitation in what you can push and pull from and to a subversion server. Particularly, problems arise if you are using the usual DVCS push and pull method to exchange changesets. Why so? If you push and pull from other DVCS repositories you might have to create a merge. Modern DVCS like Git, Mercurial or Bazaar represent history as a directed acyclic graph (DAG). Therefore a merge is a commit which has two (or more) parents, which means that a merge is the resulting connection of two parallel strands of history. Now this is a very comfortable and powerful way to describe history in parallel development. Sadly subversion doesn&#8217;t handles history and hence merges the same way (at least not priort svn 1.5). As a result, it is not possible to represent the Merge from a DVCS in subversion.</p>
<p>Different bi-directional bridges have different approaches to this problems. Git-svn will commit the Merge but not the commits which are part of the seconds strand of history, while hgsubversion will abort if it has to push a merge. The fact that hgsubversion aborts in case of a merge is our actual problem. We want to use Mercurial and therefore need to find a way to push a merge to subversion.</p>
<p><strong>A usecase</strong><br />
You shouldn&#8217;t care much about these limitations. Usually, people are using the bi-directional bridge locally to be able to do offline commits or bisect a bug. In that case, everything will work fine.</p>
<p>But why do I write a complete blog post about a hg to svn bridge if the problem is already solved? The answer is pretty simple.</p>
<ol>
<li>Imagine you are working in a small team. Everybody in the team knows Mercurial and everybody likes to use it. Moreover you are working offline from time to time, and the members of the team sometimes have to exchange unfinished features with other members. In that case you will probably use Mercurial as your version control system. The problem here is the customer. He dictates the VCS and it has to be Subversion. Now subversion at all is not that bad, but in your particular case, it&#8217;s a huge drawback. You have to find a way to mirror your Mercurial repository to the Subversion server.
</li>
<li>A second use case is that you are working on an OpenSource project which uses github or bitbucket to host it&#8217;s repositories. As you are using the OpenSource framework also at work. You have to use Subversion and you want to use svn:externals to integrate your fancy framework into the existing Subversion repository</li>
</ol>
<p>As you see, there is a use case for DVSC to Subversion mirror. As no such tool exists at the moment, we&#8217;ll try to implement a (frankly, very stupid) mirroring mechanism.</p>
<p><strong>The idea and it&#8217;s limitations</strong><br />
We see that we need to mirror a existing Mercurial repository to Subversion.<br />
We also know that we cannot use the existing tools. Our requirements are the following.</p>
<ol>
<li>Mirror a Mercurial repository into a Subversion repository</li>
<li>Track latest synchronized changeset</li>
<li>Handle merges</li>
</ol>
<p>Note that we would have been able to do this with git-svn, while it&#8217;s not possible to do it with hgsubversion.</p>
<p>A few assumptions about the environment where we want to use our mirroring mechanism helps us to simplify the requirements.</p>
<ol>
<li>We do not need to preserve the author information</li>
<li>We have a central Mercurial repository called Gate</li>
<li>No commit will be done into the repository other than our mirroring (and believe me, things get ulgy for you if you try to&#8230;)</li>
<li>We do not need to preserve all commits</li>
</ol>
<p>So what is the end result? We just need to find a way to push all changesets and just ignore all merged changes, but commit the merge itself. This should be sufficient.</p>
<p>In our particular environment everyone has his own repository, but one person integrates all changes into one repository called the Gate. Commits reaching the gate are committed to Subversion.</p>
<p><strong>The implementation</strong><br />
To make a long story short (it&#8217;s getting late). We are using Mercurials log command and it&#8217;s option to obtain a linear history that can be pushed. To get the the history, we use<br />
<code><br />
	hg log --follow-first<br />
</code><br />
This will return the history omitting all merged changesets but including the merges itself. We silently drop the changesets that were merged, but retain the result. As we need to get just the SHA-1, we use the &#8211;template option to get the node. We then iterate over the history, updating our working copy to each changeset in the history, adding all newly created files and deleting all removed files and then comitting the current state of the working directory. So here is our final script<br />
<code></p>
<pre>
#!/bin/sh

lc=0
cont=0
if test -f "LAST_COMMIT"
then
	lc=`cat LAST_COMMIT`
	cont=1
fi

for hash in `hg log --follow-first --template "{node}\n" -r $lc:tip`
	do
		if test $cont -eq 1
		then
			cont=0
			continue
		fi

		echo "update to $hash"
		if ! hg log --template "{desc}\n"  -r $hash > COMMIT_MSG
		then
			echo "Canno get log" >&#038;2
			exit 127;
		fi
		cat COMMIT_MSG

		hg up -C -r $hash
		for file in `hg log --template "{file_adds}\n" -r $hash`
			do
				echo "add $file"
				svn add --parents $file
			done
		for file in `hg log --template "{file_dels}\n" -r $hash`
			do
				echo "del $file"
				svn rm $file
			done
		svn commit -F COMMIT_MSG
		echo $hash > LAST_COMMIT
	done
</pre>
<p></code><br />
It looks scary, and yes it <em>is</em> scary. But for the moment it works. Our simple hg to subversion bridge is finished.</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=318&amp;md5=5699db1240db9791bfbd9c5808d4f26d" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2009/12/writing-a-hg-to-subversion-gate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>hg-scm.org</title>
		<link>http://blog.experimentalworks.net/2009/08/hg-scm-org/</link>
		<comments>http://blog.experimentalworks.net/2009/08/hg-scm-org/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 21:34:08 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[dvcs]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=281</guid>
		<description><![CDATA[For those of you, who didn't notice so far, in the last 6 month we worked on a more userfriendly and accessible page than the current mercurial website. Three weeks ago we launched hg-scm.org which is quite similar to git-scm.org. I hope you enjoy it]]></description>
			<content:encoded><![CDATA[<p>For those of you, who didn&#8217;t notice so far, in the last 6 month we worked on a more userfriendly and accessible page than the current mercurial website. Three weeks ago we launched <a href="http://hg-scm.org">hg-scm.org</a> which is quite similar to <a href="http://git-scm.org">git-scm.org</a>. I hope you enjoy it</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=281&amp;md5=a3a31131e7051326deb1106db2e45072" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2009/08/hg-scm-org/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>git2svn, a little bit of git voodoo.</title>
		<link>http://blog.experimentalworks.net/2009/07/git-voodoo/</link>
		<comments>http://blog.experimentalworks.net/2009/07/git-voodoo/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 15:59:29 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[dvcs]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[voodoo]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=232</guid>
		<description><![CDATA[Interacting between git and subversion is quite common. The git command git-svn can be used to import existing subversion repositories into git and commit synchronize commits between two repositories. While importing a subversion repository into git is common, importing an git repository into subversion is quite unusual. There are various tools to do so, ...]]></description>
			<content:encoded><![CDATA[<p><em>Interacting between <a href="http://git-scm.org">git</a> and <a href="http://subversion.tigris.org/">subversion</a> is quite common. The git command <a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html">git-svn</a> can be used to import existing subversion repositories into git and commit synchronize commits between two repositories. While importing a subversion repository into git is common, importing an git repository into subversion is quite unusual. There are various tools to do so, but most of them require direct access to the svn repository. In fact it is possible to use git-svn to get that job done. Frankly it requires some git voodoo and knowledge of the <a href="http://git.or.cz/gitwiki/GraftPoint">graft-feature</a>. We&#8217;ll do a sample import using grafts, but before we start, we&#8217;ll explain the theory behind the import.</em><br />
<span id="more-232"></span><br />
We assume that we have a remote subversion repository. It is empty and we want to import an existing git repository into that subversion repository.</p>
<p><strong>The idea</strong><br />
Our general idea to import the git repository into subversion is easy. We import the current subversion repository and then push the changes from the our existing git repository on top of that imported subversion repository. We than can use git-svn to commit the changes back to the subversion repository. Even thought this sound simple, it is not. Part of the problem is the fact that subversion usually deals with linear history, while git does not. (1) We have to keep in mind that we need to linearize the git repository while pushing changes to the imported subversion repository. (2) we have to make sure that every commit from the original git repository is pushed to the imported repository as a descendant of the last commit from the subversion repository to avoid conflicts. (3) the imported subversion repository and the existing git repository are not related to each other. As they don&#8217;t have a <a href="http://www.kernel.org/pub/software/scm/git/docs/git-merge-base.html">common ancestor</a> in terms of a common commit (with according sha1s), we are not able to merge both repositories easily. We will use a technique called <em>grafts</em> to create a fake common ancestor, which will make it possible to merge both repositories.</p>
<p><strong>1. Importing the svn repository into git</strong><br />
Our first step is importing the svn repository into git. We are using <em>git-svn</em> for that task.<br />
<code><br />
# git svn clone svn://path/to/repo<br />
</code><br />
We will get a git repository with a branch called <em>master</em>. As we later want to push our git repository on top of the imported svn repository, we need to remember the current id of the repositories head (we&#8217;ll discuss later why we need that).  The command <em><a href="http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html">git rev-parse</a></em> will give us the necessary information.<br />
<code><br />
# git rev-parse HEAD<br />
00f97c72f22b82c6c77ae429986060832c6b6f55<br />
</code></p>
<p><strong>2. Importing the git repository into our imported svn repository</strong><br />
Let&#8217;s start with the voodoo part. We want to merge our imported svn repository and our existing git repository. But git doesn&#8217;t know how to <a href="http://www.kernel.org/pub/software/scm/git/docs/git-merge.html">merge </a>them because both repositories don&#8217;t share a common ancestor. We can solve this problems by creating a fake common ancestor, but to do so we need all commits of both repositories in one repository. Therefore we fetch the content of the git repository into our imported subversion repository. To fetch the existing git repository into our imported svn repository we use the following <em><a href="http://www.kernel.org/pub/software/scm/git/docs/git-fetch.html">git-fetch</a></em> command:<br />
<code><br />
# git fetch /path/to/git/repository master:tomerge<br />
</code><br />
The resulting repository will look that way:<br />
<img src="http://blog.experimentalworks.net/wp-content/uploads/2009/07/graft1.png" alt="Imported" title="Imported" width="500" height="237" class="alignnone size-full wp-image-245" /><br />
Both branches the one from the existing git repository and the svn imported one exist in parallel in the same repository.</p>
<p><strong>3. Tell git what to merge&#8230;</strong><br />
We have two parallel branches. We now create the fake ancestor. This is called a <em>graft</em>. Unfortunately git&#8217;s grafts are not very well documented. Let&#8217;s visualize which commits we want to graft on each other:<br />
<img src="http://blog.experimentalworks.net/wp-content/uploads/2009/07/graft21.png" alt="graft21" title="graft21" width="500" height="215" class="alignnone size-full wp-image-252" /><br />
So we will graft the existing git branch on top of the svn branch. The fake ancestor will be the HEAD of the svn branch and the first commit of the existing git branch. To get the first commit of the existing git branch we use the following command:<br />
<code><br />
# git rev-list --reverse tomerge  | head -n 1<br />
bab39ed371145b83340750101e7ec85167845857<br />
</code><br />
Therefore the commit <em>bab3&#8230;</em> and <em>00f97&#8230;</em> will be our grafts. We create the file <em>.git/info/grafts</em> with the content<br />
<code><br />
bab39ed371145b83340750101e7ec85167845857 00f97c72f22b82c6c77ae429986060832c6b6f55<br />
</code><br />
We use gitk to check if our history seems to be linear. If everything is correct, just switch to the master branch and <em><a href="http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html">rebase</a></em> your tomerge branch. We use rebase here to get a linear history. A merge might make it impossible for git-svn to push to the remote svn repository as imported commits cannot have commits which are not synchronized to the svn yet.<br />
<code><br />
# git checkout master<br />
# git rebase tomerge<br />
# git svn dcommit<br />
</code></p>
<p>Done.</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=232&amp;md5=f9d3756239a6ea93a3163fa7f5c055f1" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2009/07/git-voodoo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Merge vs. Rebase &#8211; A deep dive into the mysteries of revision control</title>
		<link>http://blog.experimentalworks.net/2009/03/merge-vs-rebase-a-deep-dive-into-the-mysteries-of-revision-control/</link>
		<comments>http://blog.experimentalworks.net/2009/03/merge-vs-rebase-a-deep-dive-into-the-mysteries-of-revision-control/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 02:51:51 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[dvcs]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=163</guid>
		<description><![CDATA[I remember the days when I started learning Git about two years ago. I crawled through all the available commands and read the man pages what they are for and I remember when I stumbled over rebase and stuck. After figuring out what it actually does, I start loving it, but didn't understand it's ...]]></description>
			<content:encoded><![CDATA[<p>I remember the days when I started learning <a href="http://git-scm.com">Git</a> about two years ago. I crawled through all the available commands and read the man pages what they are for and I remember when I stumbled over <a href="http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html">rebase</a> and stuck. After figuring out what it actually does, I start loving it, but didn&#8217;t understand it&#8217;s dangerousness until someday I somehow got duplicated commits after pulling from another repository. So let me explain what goes wrong and why merge and rebase are often misunderstood. I&#8217;ll also present a list of golden-rules about their usage. Before we start with explaining both commands, I would like to give you one of the most important rules, in case you don&#8217;t want to read the complete article.</p>
<blockquote style="background-color: #fffad1; font-weight: bold; color: black"><p>
Never rebase branches or trees that you pulled. Only rebase local branches.
</p></blockquote>
<p><span id="more-163"></span><br />
<em>Disclaimer: I never read this article myself</em></p>
<hr />
<strong>Merge</strong><br />
<a href="http://www.kernel.org/pub/software/scm/git/docs/git-merge.html">Merging</a> is one of the most important operations in <a href="http://en.wikipedia.org/wiki/Distributed_revision_control">distributed revision control systems</a>. Basically a merge is a new commit on top of <em>both</em> branches that should be merged. It is like melting two different pipes of steel together. The pipe itself doesn&#8217;t break, it&#8217;s just combined with another pipe. So, the commit itself knows that it is a merge commit. It is important to notice that it is a new commit that gives the revision control system a hint that there was a merge between two branches.</p>
<p>Let&#8217;s visualize this:<br />
Let&#8217;s assume that we have a linear history. In our graphic we see the last tree commits in that history.<br />
<img src="http://blog.experimentalworks.net/wp-content/uploads/2009/03/simple-linear.jpg" alt="simple-linear" title="simple-linear" width="640" height="177" class="alignleft size-full wp-image-165" /></p>
<p>Okay. Now let&#8217;s say there is a bug in the software. For sure, we don&#8217;t do any mistakes, certainly a co-worker did that mistakes. Unfortunatly we are the only one <a href="http://www.titanic-magazin.de/">smart</a> enough to know how to fix that. So we checked out our stable branch and committed our fixes to that branch. Our fix needs <a href="http://en.wikipedia.org/wiki/42">two</a> commits. Let&#8217;s see how this reflects in our <a href="http://en.wikipedia.org/wiki/LSD">visualization</a>:<br />
<img src="http://blog.experimentalworks.net/wp-content/uploads/2009/03/before-merge.jpg" alt="Branch off" title="Branch off" width="640" height="177" class="alignleft size-full wp-image-173" /></p>
<p>The commit <em>433fa</em> and <em>322ac</em> are our commits that fix a certain problem. Now we need to integrate these commits into our current experimental development version. <em>But as we keep our stable branch also public for other employees to push, we push this branch first before we merge it into our experimental branch</em>. Let&#8217;s repeat this. We pushed this branch to a place where other people can pull it. Again, we <a href="http://www.kernel.org/pub/software/scm/git/docs/git-push.html">pushed</a> it. Remember that!</p>
<p>So we have to get that fix into our experimental branch. So we use the merge command. In Git or <a href="http://selenic.com/mercurial">Mercurial </a>this would look like:</p>
<blockquote><p>
$ git checkout stable<br />
..fix fix fix fix..<br />
$ git commit<br />
&#8230;<br />
$ git checkout experimental<br />
$ git merge stable
</p></blockquote>
<blockquote><p>
$ hg branch stable<br />
..fix fix fix..<br />
$ hg commit<br />
&#8230;.<br />
$ hg branch default<br />
$ hg merge stable
</p></blockquote>
<p>So we create our merge commit. This is a <em>new</em> commit that reflects our merge.<br />
<img src="http://blog.experimentalworks.net/wp-content/uploads/2009/03/merge.jpg" alt="merge" title="merge" width="640" height="177" class="alignleft size-full wp-image-176" /><br />
Please note: <em>The actual ID&#8217;s of our commits that include the fixes did not change</em>.</p>
<hr />
<strong>Deep dive</strong><br />
So here is the deep dive into merging. Our revision control system now knows that there was a merge. Therefore if we later start to work on stable again, commit new fixes on top of the old fixes and then do a merge again into the experimental branch, the systems tries to find the common ancestor. This is our merge commit, therefore only commits and changes later than the last merge commit will be used to do the new merge commit. This results in less merge conflicts and in a better tracking when fixes really get back into the experimental branch. Because all these new fancy revision control systems like Git or Mercurial are designed to be fast and to deal with a humongous amount of commits and data, they don&#8217;t compare the actual changes to determine the first common ancestor of two heads. They are using the calculated SHA1 key. So if we merge, the SHA1s don&#8217;t change and we the system has a way to detect that some commits already exist in our tree if we push from other people that pulled from use once.</p>
<hr />
<strong>Rebase</strong><br />
Rebase has a different approach as merging. It is one of the more sophisticated and hard to learn commands. It&#8217;s about cutting off a pipe and weld it on another pipe. In Git it is a build-in command, but as it usually not used very often, it is just an extension in Mercurial. Bascially a rebase is a way to cut of a set of commits from a branch and apply those commits on another branch. This seems to be pretty easy, but usually developers get a lot of problems when using rebase if they are not familar with all the implications of &#8216;cut off&#8217;.</p>
<p>So let&#8217;s get back to our &#8216;stable&#8217; branch which were we commitet our fixes to:<br />
<img src="http://blog.experimentalworks.net/wp-content/uploads/2009/03/before-merge.jpg" alt="Branch off" title="Branch off" width="640" height="177" class="alignleft size-full wp-image-173" /></p>
<p>So we want to rebase this branch on top of our experimental branch. What does rebase do: It cuts off these commits. The commits don&#8217;t have any information about their parents anymore. The system then applies them on top of the new branch, which is in our example the experimental branch. If everything went fine, we get a nice linear <a href="http://www.kernel.org/pub/software/scm/git/docs/git-log.html">history</a>. Our old branch doesn&#8217;t exist anymore but instead we have all the important commits applied on top of our experimental branch. <a href="http://www.buttugly.ca/">As people tend to dislike merge conflicts</a> rebase is the perfect tool to get rid off these commits. Let&#8217;s visualize this:<br />
<img src="http://blog.experimentalworks.net/wp-content/uploads/2009/03/cut-rebase.jpg" alt="cut-rebase" title="cut-rebase" width="640" height="177" class="alignleft size-full wp-image-191" /><br />
We literally cut of these commits and then apply it on top of the new branch:<br />
<img src="http://blog.experimentalworks.net/wp-content/uploads/2009/03/rebase.jpg" alt="rebase" title="rebase" width="640" height="177" class="alignleft size-full wp-image-192" /></p>
<p>But what are the implications? Why does merge even exists if we found such a nice way to handle our history? Ohhhhh. Let&#8217;s way&#8230;take a look at the graphics. <strong>Our commit ID changed!</strong> Why? We have a new parent, we even might have completly new changesets (depending on the changes on the new branch). Our revision control system really thinks of our commits as patches and applies them on top of the new branch.  Therefore our revision control system thinks that our commits are new commits. <em>Recapitulate this</em>. IT THINKS THAT THESE ARE NEW COMMITS. Why? Because they have new IDs. It&#8217;s that simple. The common ancestor of a commit is determined by traversing the list of commit IDs and their parent IDs. As the parents changed, the ID&#8217;s have changed too.</p>
<hr />
<strong>git rebase [--onto branch] <upstream> [branch]</upstream></strong><br />
When you rebase in git, you provide an <i>upstream</i> branch. The upstream branch is the branch to which the commits should be moved. The cut-off point is calculated as the common-ancestor between your current<br />
branch and the provided upstream. You can also provide the branch for that calculation manually as a parameter to git rebase.</p>
<hr />
<strong>Deep dive</strong><br />
E.g. Git literally take this commits as patches by removing the commits from the history, creating patches out of it and applythem on top of the new branch. If you rebase the first time, it will result in more or less the same conflicts as merging, but if your rebase the second time, the revision control system doesn&#8217;t know about that rebase and uses the same common ancestor that was used by the first rebase. Hence if you use rebase frequently between the same branches, Git uses more and more commits to do the actual merge, which is equal to have branches that get more and more diveregent. This usually leads to much more merge conflicts. Think about rebasing as if you pop all those commits from the branch and push it to the new branch (if you speak in the terms of a patch management system like quilt).</p>
<hr />
<p>So if you have pulled your branch to some place and you now pull it back, you will get duplicated commits. Okay you might be smart enough to get around this, but other people that might have pulled from your stable branch might not know what happened, so they have all these duplicated commits, or if you pull from them, you get these commits back. Actually you don&#8217;t even see them until you try to merge them, because their ID is completly different. As a result you get a millions of merge conflicts and have to find a way to get rid of the duplicated commits. But why, and how can you prevent his? And why do these systems include a command that can cause so much pain?</p>
<p>So let&#8217;s see.</p>
<p><strong>Rebase done right</strong><br />
We saw that rebasing results in duplicated commits if we try to rebase branches that we already pushed to some repository, that either we or others pulled from. Let&#8217;s see why there is still a point to use rebase at all. Imagine you want to fix a bug <em>locally</em>. This means, you do not push this branch somewhere. Did you get that point? If you then rebase your local fancy branch on top of your branch that you usally push everything is fine. Let&#8217;s take a look at a good example:</p>
<blockquote><p>
$ git branch pdo-mysql-config-fix<br />
$ git checkout pdo-mysql-config-fix<br />
..hack.hack..<br />
$ git commit<br />
$ git rebase master<br />
$ git checkout master<br />
$ git merge pdo-mysql-config-fix
</p></blockquote>
<p>Got it? We never cut off the pipe. It&#8217;s just like we prepared that pipe on another stream. We realized the main pipe was changed so we weld it of and put it back on top of the main pipe. As all the people just look at our main pipe it looks like we just added a new piece on top of the old pipe. We brought the feature branch in line with master, so the merge will be trivial and git will consider it as a &#8220;fast-forward&#8221; which means there won&#8217;t be a merge commit. We never gonna push the branch that we use to rebase. If we push it, I would get duplicated commits:</p>
<p>So let&#8217;s rehearse the <strong>Golden Rule Of Rebasing</strong>:</p>
<blockquote style="background-color: #fffad1; font-weight: bold; color: black"><p>
Never ever rebase a branch that you pushed, or that you pulled from another person
</p></blockquote>
<p>It&#8217;s that simple. If you would rebase a branch from another person and he would pull back the integrated changes from you, he would get duplicated commits. So never ever do this.</p>
<p>The bad news: Too many developer get rebasing wrong and think that it&#8217;s a fancy way to get a linear history<br />
The good news: Believe me, even well known top-level maintainer didn&#8217;t get what rebasing is about.</p>
<p><em>This article is about rebasing. Rebasing is a way to push commits from a branch on top of another branch. Decentralized revision control systems such as Git or Mercurial implement this feature.</em></p>
<p><strong>UPDATE</strong><br />
A few people at reddit.com pointed out that it might not be a good idea to rebase a dev branch on top of master. If you are doing drastic changes in your dev branch, that&#8217;s right. People might use rebase then to keep their dev branch up to date on top of the master branch and therefore rebase against master. At the end they can merge the dev branch into the master branch (in fact the result is the same here, as it&#8217;s both way a fast forward).</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=163&amp;md5=b984daf91768896b476d2ebbb025abf6" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2009/03/merge-vs-rebase-a-deep-dive-into-the-mysteries-of-revision-control/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>A really unfriendly and not so fair approach to GIT vs. Mercurial</title>
		<link>http://blog.experimentalworks.net/2009/02/a-really-unfriendly-and-not-so-fair-approach-to-git-vs-mercurial/</link>
		<comments>http://blog.experimentalworks.net/2009/02/a-really-unfriendly-and-not-so-fair-approach-to-git-vs-mercurial/#comments</comments>
		<pubDate>Sun, 22 Feb 2009 02:58:13 +0000</pubDate>
		<dc:creator>dsp</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Private]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://blog.experimentalworks.net/?p=156</guid>
		<description><![CDATA[Okay, this is one of the posts I wanted to since about 1 year, but now, nearly 2 years after the first git vs. Mercurial blog post I finally made it to actually write a second time about this topic. A first notice: I won't cover bazaar. I personally hate it with passion and ...]]></description>
			<content:encoded><![CDATA[<p>Okay, this is one of the posts I wanted to since about 1 year, but now, nearly 2 years after the first git vs. Mercurial blog post I finally made it to actually write a second time about this topic. A first notice: I won&#8217;t cover bazaar. I personally hate it with passion and think it is the worst approach to DVCS ever. Nevertheless git and Mercurial fight in the same game with the same weapons (unlike bzr which is just far behind).</p>
<p><strong>WARNING: This is the most subjective, most pointless approach to this topic ever. I didn&#8217;t read it myself a second time, I just published it.</strong></p>
<p>I will start the same way as last time:</p>
<p><strong>git</strong><br />
Git is a decentralized version control system written by Linus Torvalds to replace bitkeeper as the version control system of choice for the kernel because of licensing issues (okay I know this is the short story and it was much more complex and you can write a thousand lines about that, but it&#8217;s enough for most people). Git is designed to be fast. Everthing is optimized in that way. It contains a huge C written core with a lot of bash and perl scripts around it. A few years ago the C written part formed the so called <em>plumbing</em>. Nowadays the git community tries to replace high-level commands written in bash and perl that call the plumbing commands with c-written code to get a more consistent code base.<br />
Let&#8217;s make a long story short:<br />
Git is powerful. Awesome powerful. This is true since git&#8217;s beginning, but back then it lacks a good interface and the git community did a great job in improving the horrible interface git had once. Git is still awesomely fast. Commits, bisecting, everything works like a charm particularly on big projects like the kernel. They can rewrite history, they are doing a great job in helping intergrators to apply patches, reviewing them, and pushing to multiple sources. Everything about git is really unique, their focus on a powerful command set, their branching support and their targeted audience. I want to talk a little bit about that fancy branching support. Frankly, every version control system, even the 3rd generation decentralized ones have a pretty conservative way of doing branching by giving every changeset a name that the changeset belongs to (at least this is true for mercurial, and called named branches there). Git just gives a sh** about that and takes a version control <em>branch</em> the same way as a tree <em>branch</em>. It&#8217;s just an unnamed <em>branch</em> of the DAC. This gives you the awesome possibility to great huge set of local branches, to merge, rebase them without any bigger problem or even just discard them (actually that is one of the biggest problems in mercurials bookmarks implementation). Another just great feature in git is the staging area. You can stage hunks, as a virtual repository that is used to actually commit the &#8216;selected&#8217; changesets. That&#8217;s awesome and I&#8217;m really missing that in most of the version control systems that I use. The idea of a staging area is just a huge win for git. It&#8217;s so incredible powerful. Okay to put it in a nutshell: git is just awesome, but&#8230;.</p>
<p>There is <strong>Mercurial</strong>.<br />
Okay some kind of a warning in advance: I contributed two well known extensions to Mercurial, I hang around in their chatroom and I think that I&#8217;m a well known part of the community. Nevertheless if you talk about Mercurial and compare it with git you have to take care. Mercurial is by far not as powerful as git, and&#8230;that is just the best think about Mercurial. Matt really keeps it simple and clear for everybody. it&#8217;s so incredible easy to understand in the first place. There are no weird commands with a thousand of flags. Okay I try to be fair. Mercurial is much less powerful than git in the first place. Because it tries to keep everything simple. There is no rebase, no cheap branching, no staging area. <strong>But</strong> there are extensions. You can learn Mercurial and know all it&#8217;s commands within 24h. They are really easy to learn, and not powerful, but they can be extended, by a large range of extensions. You can have cheap branching (bookmarks), you can have kind of a staging area (record extension), you can have patch management on top (mq) and much more. With all those extensions, Mercurial is as hard to learn as learning all git commands (which frankly is not necessary at all), but it&#8217;s more of a evolutionary approach. I know a thousand people who say that learning git is as easy. Okay, no problem. I don&#8217;t think so but it doesn&#8217;t matter, but frankly, git is missing 2 big points. Windows and an application integration: If you live in your nice Linux/BSD/foo world you are right. Git is awesome, but come on, I don&#8217;t have a freaky Windows machine, but I <strong>know</strong> that 80% of all people and more than 50% of all programmers use Windows. No they are not these bad, <em>not geeky enough</em> people. They are the real programmers. Those who are not freaks and take programming as a job. They don&#8217;t care (and thats good) about their environment, they just want to get things done and want to earn money. That good. And even that is not quite true for most of them, they do their stuff just faster on Windows than on Linux, therefore it&#8217;s better for them to use Windows. Okay, you might argue, but there is mysysgit and it&#8217;s even part of official git. Oh nice arguement, but frankly, junio doesn&#8217;t provide Windows binary, there is no official site to get them from, and &#8230;.. git daemon still doesn&#8217;t work perfectly nor does git-svn. It just sucks. Big <strong>-1</strong> from me for that one.<br />
The second pint is the worse git internal design. It&#8217;s soooo unix style. It&#8217;s cool for people that love Unix (like I do), who pipe around at least 3 commands, and know that I it starts to get funny if you pipe around 5 commands. But most of the developer want to use a nice integrated version control system. They don&#8217;t like to use fancy command line stuff with a thousand of flags, they want to do click&#038;click (the german expression would be &#8216;klicky-bunti&#8217;). They want to have it integrated in their Eclipse, their NetBeans, Visual Studio, their Windows explorer and so on, and frankly, git does a poor job in that area. I know there is an eclipse plugin (but the mercurial one is stilll a thousand times better), and all this fancy stuff, but what do they do, <em>damn</em>, they have to parse the shell output. This means either git will never ever change their shell output (which would be sad, e.g. I hate the # in git status), or they will break older stuff. Mercurail on the other side is really easy to interface with. Okay you need python but that&#8217;s all. Everything else is just smooth. It&#8217;s easy to handle, it&#8217;s easy to integrate, it just works fine. Git really does a bad job on that. And the git community knows it. That&#8217;s why they start their libgit, and libgit2 project, because they know something like a git library is needed.</p>
<p>Okay it&#8217;s late and I want to finish that without reading it a second time, no frankly, this time I want to be completely unfair, without any objective argument: So here comes my final words, make them:</p>
<p><em>If you like to play with software, if you really like to have the power, go for git, if you use Linux, even better, go for it, there is nothing equal to the power and the fun you can have with Git. You can be a thousand times more productive. But if you, or people in your team are not tech-geeks. If you use Guis and want to use Windows, believe me, you better use Mercurial. I really love both systems (as long as you don&#8217;t use bzr even SVN is fine), but in this use case Mercurial is just better. Think about it.</em></p>
<p><em>shame on myself: song for this post: This is the life by Amy MacDonald</em></p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.experimentalworks.net/?flattrss_redirect&amp;id=156&amp;md5=ad28d9bdc3f4f058ddc4a3b5e535227a" title="Flattr" target="_blank"><img src="http://blog.experimentalworks.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.experimentalworks.net/2009/02/a-really-unfriendly-and-not-so-fair-approach-to-git-vs-mercurial/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

