<?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>Sven&#039;s Blog &#187; SVN</title>
	<atom:link href="http://jausoft.com/blog/tag/svn/feed/" rel="self" type="application/rss+xml" />
	<link>http://jausoft.com/blog</link>
	<description></description>
	<lastBuildDate>Thu, 19 Apr 2012 19:26:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>SVN to GIT migration (1)</title>
		<link>http://jausoft.com/blog/2009/07/08/svn-to-git-migration-1/</link>
		<comments>http://jausoft.com/blog/2009/07/08/svn-to-git-migration-1/#comments</comments>
		<pubDate>Thu, 09 Jul 2009 05:30:23 +0000</pubDate>
		<dc:creator>Sven</dc:creator>
				<category><![CDATA[Computer Stuff]]></category>
		<category><![CDATA[JOGL]]></category>
		<category><![CDATA[SCM]]></category>
		<category><![CDATA[GIT]]></category>
		<category><![CDATA[SVN]]></category>

		<guid isPermaLink="false">http://blog.jausoft.com/?p=126</guid>
		<description><![CDATA[Preface Abandoning SVN in our projects (gluegen, jogl and jogl-demos) for the various reasons, http://git.or.cz/gitwiki/GitSvnComparsion, we had to choose a new SCM. Here are some reasons why git wins over mercurial/hg, http://whygitisbetterthanx.com/ http://importantshock.wordpress.com/2008/08/07/git-vs-mercurial/, http://news.ycombinator.com/item?id=577976 especially the branch/merge handling, maturity and wide growing user base favors git. However, it may also be just a matter of [...]]]></description>
			<content:encoded><![CDATA[<h2>Preface</h2>
<p>Abandoning <em>SVN</em> in our projects (gluegen, jogl and jogl-demos) for the various reasons, <a href="http://git.or.cz/gitwiki/GitSvnComparsion">http://git.or.cz/gitwiki/GitSvnComparsion</a>,<br />
we had to choose a new SCM.<span id="more-126"></span></p>
<p>Here are some reasons why <em>git</em> wins over mercurial/hg,</p>
<ul>
<li><a href="http://whygitisbetterthanx.com/">http://whygitisbetterthanx.com/</a></li>
<li><a href="http://importantshock.wordpress.com/2008/08/07/git-vs-mercurial/">http://importantshock.wordpress.com/2008/08/07/git-vs-mercurial/</a>,</li>
<li><a href="http://news.ycombinator.com/item?id=577976">http://news.ycombinator.com/item?id=577976</a></li>
</ul>
<p>especially the branch/merge handling, maturity and wide growing user base favors <em>git</em>.<br />
However, it may also be just a matter of taste ..</p>
<p>Some git resources:</p>
<ul>
<li><a href="http://git.or.cz/gitwiki/GitDocumentation">git wiki</a></li>
<li><a href="http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html">git tutorial</a></li>
<li><a href="http://www.kernel.org/pub/software/scm/git/docs/everyday.html">git everyday</a></li>
<li><a href="http://ktown.kde.org/~zrusin/git/git-cheat-sheet-medium.png">git cheat sheet</a></li>
<li><a href="http://git.or.cz/course/svn.html">git crash course for svn users</a></li>
<li><a href="http://www.kernel.org/pub/software/scm/git/docs/">git documentation</a></li>
<li><a href="http://code.google.com/p/msysgit/">msysgit &#8211; git for MS Windows</a></li>
</ul>
<h2><em>SVN</em> to <em>git</em> Conversion</h2>
<p>The conversion demonstrated here is using the <em>dev.java.net </em>gluegen repository as an example, we have converted the<em> jogl </em>and<em> jogl-demos</em> the same way.</p>
<p>We have used <strong><em>git</em> version 1.6.3.3.</strong></p>
<p><span style="text-decoration: line-through;">Instead of using <em>git-svn</em> directly, we utilize the tool <em>svn-all-fast-export</em>, <a href="http://repo.or.cz/w/svn-all-fast-export.git">http://repo.or.cz/w/svn-all-fast-export.git,<br />
</a>which not only uses a fast local <em>SVN</em> repository, but also migrates all local branches and tags to <em>git</em> branches.<br />
The latter is true, <em>SVN</em> tags converted to git branches, since <em>SVN</em> tags are actually branches.</span></p>
<p><strong><em>Update: </em></strong>It turns out that the tool h<a href="http://repo.or.cz/w/svn-all-fast-export.git">ttp://repo.or.cz/w/svn-all-fast-export.git</a><br />
is not able to find the proper tag and branch points within the original repository,<br />
hence we will use <a href="http://www.kernel.org/pub/software/scm/git/docs/v1.6.3.3/git-svn.html"><em>git-svn</em></a>.</p>
<h3>Directory Layout</h3>
<p>We assume the following layout ..</p>
<pre>/../JOGL
/../JOGL/svn-server-sync
/../JOGL/svn
/../JOGL/git-svn</pre>
<p>All subsequent action start from the root directory <em>JOGL</em>.</p>
<h3><em>SVN</em> Preperation</h3>
<h4>Clone Repository</h4>
<p><strong><em>Update:</em></strong> This task is optional. However it is highly recommended since it dramatically speeds up the <em>SVN</em> checkout process.</p>
<p>First we create a local clone of the <em>SVN</em> repository. This is already tricky, since the <em>svn</em> versions are not backward compatible,<br />
i.e. <em>dev.java.net</em> <em>SVN</em> repository cannot be synchronized with <em>svn</em> version 1.6. The latest compatible version is <em>svn</em> 1.5.2.<br />
Here we used an installed <em>svn</em> version 1.4.4 from a MacOSX machine!</p>
<pre>1: mkdir svn-server-sync
2: cd svn-server-sync
3: svnadmin create gluegen
4: cp gluegen/hooks/pre-revprop-change.tmpl gluegen/hooks/pre-revprop-change
5: vi gluegen/hooks/pre-revprop-change
6: chmod ugo+x gluegen/hooks/pre-revprop-change
7: svnsync --username userid --password pwd init file://`pwd`/gluegen <a class="linkification-ext" title="Linkification: https://gluegen.dev.java.net/svn/gluegen" href="https://gluegen.dev.java.net/svn/gluegen">https://gluegen.dev.java.net/svn/gluegen</a>
8: svnsync sync file://`pwd`/gluegen</pre>
<p>Step [1..3] create the local SVN repository.</p>
<p>Steps [4..6] create the svn critical hook file and makes it writeable, while step 5 edits it as follows:</p>
<pre>diff -Nur gluegen/hooks/pre-revprop-change.tmpl gluegen/hooks/pre-revprop-change
--- gluegen/hooks/pre-revprop-change.tmpl       2009-07-08 09:18:55.000000000 -0700
+++ gluegen/hooks/pre-revprop-change    2009-07-08 09:20:06.000000000 -0700
@@ -60,6 +60,8 @@
 PROPNAME="$4"
 ACTION="$5"

+exit 0
+
 if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi

 echo "Changing revision properties other than svn:log is prohibited" &gt;&amp;2</pre>
<p>Step 7 links the local SVN repository  to it&#8217;s remote master.</p>
<p>Step 8 finally pulls it down to our local copy.</p>
<p>This is done for the <em>jogl</em> and<em> jogl-demos</em> repositories as well.</p>
<h4>Create author mapping file</h4>
<p>Create a <em>svn.authors</em> file, which maps the <em>svn</em> author names to <em>git</em> author names:</p>
<pre>#!/bin/bash
authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)
for author in ${authors}; do
  echo "${author} = ${author} &lt;${author}@dev.java.net&gt;" &gt;&gt; svn.authors ;
done</pre>
<p>Use the above script in all of your original checked-out svn repository directories (<em>gluegen, jogl </em>and<em> jogl-demos</em>) to catch all author names.<br />
Fix the <em>svn.authors</em> file&#8217;s email addresses if appropriate.<br />
Add the mandatory author names:</p>
<pre>(no author) = First Last &lt;<a class="linkification-ext" title="Linkification: mailto:no.author@domain.net" href="mailto:no.author@domain.net">no.author@domain.net</a>&gt;
gfxadmin = gfxadmin &lt;<a class="linkification-ext" title="Linkification: mailto:gfxadmin@domain.net" href="mailto:gfxadmin@domain.net">gfxadmin@domain.net</a>&gt;
root = root &lt;<a class="linkification-ext" title="Linkification: mailto:root@domain.net" href="mailto:root@domain.net">root@domain.net</a>&gt;
httpd = httpd &lt;<a class="linkification-ext" title="Linkification: mailto:httpd@domain.net" href="mailto:httpd@domain.net">httpd@domain.net</a>&gt;</pre>
<h4>Move old local SVN repositories</h4>
<p>We move away the old SVN checkouts ..</p>
<pre>mkdir svn
mv gluegen jogl jogl-demos svn/</pre>
<h3>Converting to git</h3>
<h4>Preperation</h4>
<p><span style="text-decoration: line-through;">Get the tool svn-all-fast-export, <a href="http://repo.or.cz/w/svn-all-fast-export.git">http://repo.or.cz/w/svn-all-fast-export.git</a>, via git clone git://<a title="Linkification: http://repo.or.cz/svn-all-fast-export.git" href="http://repo.or.cz/svn-all-fast-export.git">repo.or.cz/svn-all-fast-export.git</a>, build and install it.</span></p>
<p>Go our parent directory <em>JOGL</em>, where <em>svn-server-sync</em> resides.</p>
<pre>mkdir git-svn
cd git-svn</pre>
<p>Copy the previously created <em>svn.authors</em> file to this directory <em>git-svn</em>.</p>
<p><span style="text-decoration: line-through;">Copy the file <em>merged-branches-tags.rules</em> out of the checked out <em>svn-all-fast-export.git</em><br />
repository, <em>svn-all-fast-export/samples/merged-branches-tags.rules</em>, to this directory <em>git-svn</em>.</span></p>
<h4>Converting</h4>
<pre>cd git-svn</pre>
<p><span style="text-decoration: line-through;">We customize the <em>svn-all-fast-export</em> configuration file, here for gluegen:</span><span style="text-decoration: line-through;"><br />
sed &#8216;s/myproject/gluegen/g&#8217; merged-branches-tags.rules &gt; gluegen-merged-branches-tags.rules</span></p>
<pre>git svn --authors-file=./svn.authors clone -s file://`pwd`/../svn-server-sync/gluegen gluegen 2&gt;&amp;1 | tee gluegen.log</pre>
<p>This task migrates the <em>SVN</em> repository to <em>git</em>, note that all tags of the <em>SVN</em> repository are represented as branches within <em>git</em>,<br />
which we will fix within the next step. Don&#8217;t forget to check the log file, here gluegen.log.</p>
<p>In case somethings goes wrong, ie the task is incompete, e.g. due to a missing author-name mapping,<br />
fix that error (add author-name to svn.authors) and continue:</p>
<pre>cd gluegen
git svn --authors-file=../svn.authors fetch  2&gt;&amp;1 | tee ../gluegen-2.log</pre>
<h4>Pick remote branches &amp; manual tagging</h4>
<pre>cd git-svn/gluegen</pre>
<p>The converted repository has referenced branches to the remote <em>SVN</em> origin,<br />
we have to pick these and make them local.</p>
<p>Also, as mentioned above, <em>SVN</em> tags are actually branches, so we have to converted them to <em>git</em> tags.</p>
<pre>git branch -a
* master
  remotes/1.0b06-maint
  remotes/1.0b06a
  remotes/JOGL_2_SANDBOX
  remotes/tags/1.0b06
  remotes/tags/1.0b06a
  remotes/trunk
git tag -l</pre>
<p>The above shows us a few remote branches and no tags.</p>
<p>We have to distinguish the remote branches from the tags,<br />
which is easy at looking at the <a href="https://gluegen.dev.java.net/source/browse/gluegen/branches/"><em>SVN</em> branches page</a>.  Valid remote branches are <em>1.0b06-maint</em> and the <em>JOGL_2_SANDBOX.</em><br />
The below commands create local branches from the remote ones.<em><br />
</em></p>
<pre>git checkout --track -b 1.0b06-maint remotes/1.0b06-maint
git checkout --track -b JOGL_2_SANDBOX remotes/JOGL_2_SANDBOX</pre>
<p>Last but not least, we have to manually create <em>git </em>tags from the fake <em>SVN</em> tags, which are visible as <em>remotes/tags/*</em> branches.</p>
<pre>1: git checkout --track -b tag_1.0b06 remotes/tags/1.0b06
2: git checkout --track -b tag_1.0b06a remotes/tags/1.0b06a
3: git checkout master
4: git tag 1.0b06 tag_1.0b06
5: git tag 1.0b06a tag_1.0b06a
6: git branch -D tag_1.0b06 tag_1.0b06a
7: git branch -a
  1.0b06-maint
  JOGL_2_SANDBOX
* master
  remotes/1.0b06-maint
  remotes/1.0b06a
  remotes/JOGL_2_SANDBOX
  remotes/tags/1.0b06
  remotes/tags/1.0b06a
  remotes/trunk
8: git tag -l
  1.0b06
  1.0b06a
9: git branch -r -D 1.0b06-maint 1.0b06a JOGL_2_SANDBOX tags/1.0b06 tags/1.0b06a trunk
X: git branch -a
  1.0b06-maint
  JOGL_2_SANDBOX
* master</pre>
<p>Step [1..2] creates local branches with the prefix tag_ from the remote ones.<br />
Step 3 switches back to the master branch<br />
Step [4..5] creates tags from the local branches<br />
Step 6 deletes the local branches, which we just have tagged.<br />
Step 7 shows the branches<br />
Step 8 shows the tags<br />
Step 9 removes the remote branches, which disconnects us from the svn repository<br />
Step X: shows the branches</p>
<p>In case you have many branches, you may use a simple shell script, fed with a file containing the branch names,<br />
without the ref-path (remotes/)</p>
<pre>#! /bin/sh

branchfile=$1
shift

if [ -z "$branchfile" ] ; then
    echo Usage $0 branchfile containing branchnames without ref path
    exit 1
fi

for i in `cat $branchfile` ; do
    git checkout --track -b $i remotes/$i
    git checkout master
    git branch -r -D $i
done</pre>
<p>In case you have many tags, you may use a simple shell script, fed with a file containing the tag names,<br />
without the ref-path (remotes/tags/)</p>
<pre>#! /bin/sh

tagfile=$1
shift

if [ -z "$tagfile" ] ; then
    echo Usage $0 tagfile containing tagnames without ref path
    exit 1
fi

for i in `cat $tagfile` ; do
    git checkout --track -b tag_"$i" remotes/tags/$i
    git tag $i tag_"$i"
    git checkout master
    git branch -D tag_"$i"
    git branch -r -D tags/$i
done</pre>
<h4>Cleanup</h4>
<pre>
<pre>1: cd git-svn/gluegen
2: git gc
3: cd ..
4: git clone --mirror gluegen gluegen.git</pre>
</pre>
<p>Since the conversion left a lot of dirt in the <em>git</em> repository, and we have joggled around with a lot branches,<br />
we want to manually garbage collect (gc) our folder with the Step 2.<br />
Step 4 creates a bare mirror clone of the cleaned up git repository, you may like to use this as a backup.</p>
<p>Pre cleanup: 15MByte, post cleanup 6.6MByte, bare mirror 2.7M.</p>
<h4>Publish <em>git </em>repository to the server</h4>
<pre>cd git-svn/gluegen.git</pre>
<p>Now we push our conversion to the <em>git</em> server&#8217;s repository:</p>
<pre>git push --mirror ssh://<a title="Linkification: http://svengothel@git.kenai.com/gluegen~gluegen-git" href="http://svengothel@git.kenai.com/gluegen~gluegen-git">username@git.kenai.com/gluegen~gluegen-git</a></pre>
<p>The mirror option ensures a 1:1 copy including all branches and tags.</p>
<h2><em>git</em> Usage</h2>
<p>We assume to be in our root directory <em>JOGL</em>.</p>
<p>No more <em>gluegen</em>, <em>jogl</em> or<em> jogl-demos</em> directory exist anymore, since we moved it away to the new subdirectory <em>svn</em>.</p>
<h3>Clone</h3>
<pre>1a: git clone git://<a class="linkification-ext" title="Linkification: http://kenai.com/gluegen~gluegen-git" href="http://kenai.com/gluegen~gluegen-git">kenai.com/gluegen~gluegen-git</a>  gluegen
1b: git clone ssh://<a title="Linkification: http://svengothel@git.kenai.com/gluegen~gluegen-git" href="http://svengothel@git.kenai.com/gluegen~gluegen-git">username@git.kenai.com/gluegen~gluegen-git</a> gluegen
2: cd gluegen
3: git branch -a
4: git remote show origin</pre>
<p>Step <em>1a</em> or <em>1b</em> creates the local <em>gluegen git</em> clone in the directory <em>gluegen</em>,<br />
where <em>1a</em> is the anonymous checkout and <em>1b</em> uses the SSH login shell remote connection,<br />
the latter is recommended for putbacks.</p>
<p>Step 2 cd&#8217;s into it.</p>
<p>Step 3 lists all branches.</p>
<p>Step 4 shows remote tracked branches</p>
<h3>Checkout a remote tracked branch</h3>
<p>In case you like to browse around within some branch, which is not yet local, ie remote,<br />
you have to checkout the remote one to become local, ie the <em>JOGL_2_SANDBOX</em>.</p>
<pre>git remote show origin
git checkout --track -b JOGL_2_SANDBOX origin/JOGL_2_SANDBOX
git checkout JOGL_2_SANDBOX</pre>
<p>Then you can switch between local branches as usual ..</p>
<h3>Switch local branches</h3>
<pre>git checkout JOGL_2_SANDBOX
git checkout master</pre>
<h3>Remove a remote branch on server</h3>
<p>You may have created and published the new branch <em>my_branch</em> derived from <em>master</em>:</p>
<pre>git branch --track my_branch origin/master
git checkout my_branch
.. changes ..
pit push --all</pre>
<p>.. or you were using a remote branch ..</p>
<pre>git checkout --track -b my_branch origin/my_branch
git checkout my_branch
.. changes ..
git push --all</pre>
<p>Now we like to remove the branch <em>my_branch</em>,<br />
and remove it on the server as well.</p>
<pre>1: git branch -D my_branch
2: git push origin :refs/heads/my_branch</pre>
<p>Step 1 removes the branch <em>my_branch</em> in the local repository.<br />
Step 2 removes the branch <em>my_branch</em> on the server repository.</p>
<p>Another user may want to clean up the local repository, ie remove a tracked remote branch:</p>
<pre>1: git branch -r -D origin/my_branch
2: git fetch</pre>
<h3>Last but not least &#8230;</h3>
<p>.. <a href="http://www.kernel.org/pub/software/scm/git/docs/everyday.html#Individual%20Developer%20%28Participant%29">participation and contributions</a>.</p>
<p><em>Git&#8217;s</em> model is <strong>not</strong> really layed out for central SCM,<br />
sure it can be abused as such, as you have seen above.</p>
<p>It&#8217;s real powers are it&#8217;s <strong>distribution qualities</strong>!</p>
<p>Either a contributor has it&#8217;s own repository online via a webserver or ssh access,<br />
or she can send the patch via email.<br />
However it is offered to an integrator within the chain of trust (in a project),<br />
she asks the integrator to pull the branch via the mentioned online or email content.<br />
The integrator then verifies the patch somehow and merges it to her own branch, etc etc.<br />
These are the key features of <em>git</em>,<br />
a very reliable high performance <strong>branching</strong> and <strong>merging</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jausoft.com/blog/2009/07/08/svn-to-git-migration-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

