<?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>Chris JeanChris Jean &#187; git</title>
	<atom:link href="http://chrisjean.com/tag/git/feed/" rel="self" type="application/rss+xml" />
	<link>http://chrisjean.com</link>
	<description>Linux, WordPress, programming, anime, and other stuff</description>
	<lastBuildDate>Mon, 16 Jan 2012 15:22:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Great Tutorial on Merging with Git</title>
		<link>http://chrisjean.com/2009/11/12/great-tutorial-on-merging-with-git/</link>
		<comments>http://chrisjean.com/2009/11/12/great-tutorial-on-merging-with-git/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 13:00:36 +0000</pubDate>
		<dc:creator>Chris Jean</dc:creator>
				<category><![CDATA[Tips 'n Tricks]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[Merging]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://gaarai.com/?p=1722</guid>
		<description><![CDATA[One of the functions of Git that I still struggle with is merging. Recently, I found a post that shows a number of very helpful merging examples. If you work with Git and don&#8217;t fully understand merging, I recommend that you check it out. Git merging by example My thanks to Jonathan Rockway on providing [...]]]></description>
			<content:encoded><![CDATA[<!-- filtered -->
<p>One of the functions of Git that I still struggle with is merging. Recently, I found a post that shows a number of very helpful merging examples. If you work with Git and don&#8217;t fully understand merging, I recommend that you check it out.</p>
<p><a href="http://blog.jrock.us/articles/Git%20merging%20by%20example.pod" target="_blank">Git merging by example</a></p>
<p>My thanks to Jonathan Rockway on providing this great guide.</p>
<div class="post-notice">Originally, I wanted to duplicate the content on my site in case the content on the linked to site ceased to exist. Ironically, just days after publishing this, the site has crashed. So, I&#8217;ve recovered the content from the crash and have duplicated it here. The remaining content is from the site I linked to and not my own. If the content stays down for long, I&#8217;ll clean up my duplicate of it.</div>
<p><span id="more-1722"></span><br />
UPDATE (28 Apr 2008): So apparently this article made it to the front page of delicious, reddit, and hacker news. It&#8217;s always the ones I least expect <img src='http://chrisjean.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Anyway, I&#8217;ve updated the branch names to be less confusing, and I&#8217;ve added an explanation of why I say git ci instead of git commit; I have the following section in my .gitconfig file:</p>
<p>[alias]<br />
st = status<br />
di = diff<br />
co = checkout<br />
ci = commit<br />
br = branch<br />
sta = stash</p>
<p>This lets you type git [the left side] and allows git to interpret it as git [the right side]. A very useful feature.</p>
<p>We now bring you the actual article:</p>
<p>I&#8217;ve always liked git&#8217;s merging algorithm, so I thought I&#8217;d show an example where it works exactly like I&#8217;d expect.</p>
<p>Let&#8217;s get started by creating a new git repository and project:</p>
<p>$ mkdir git-test<br />
$ cd git-test<br />
$ git init</p>
<p>Then we&#8217;ll create a file to play with, test.pl:</p>
<p>#!/usr/bin/env perl</p>
<p>print &#8220;Hello, world.\n&#8221;;</p>
<p>__END__</p>
<p>And commit that:</p>
<p>$ git add test.pl<br />
$ git ci -m &#8216;initial import&#8217;<br />
Created initial commit 219c5b3: initial import<br />
1 files changed, 6 insertions(+), 0 deletions(-)<br />
create mode 100644 test.pl</p>
<p>At this point, we want to create a branch so we can refactor this mess without ruining the working code.</p>
<p>$ git co -b refactor<br />
Switched to a new branch &#8220;refactor&#8221;</p>
<p>Now that we&#8217;re on the refactor branch, let&#8217;s sequester the print statement into a subroutine.</p>
<p>#!/usr/bin/env perl</p>
<p>say_hello();</p>
<p>sub say_hello {<br />
print &#8220;Hello, world.\n&#8221;;<br />
}</p>
<p>__END__</p>
<p>And commit:</p>
<p>$ git ci -a -m &#8216;factor print into a subroutine&#8217;;<br />
Created commit 518dec1: factor print into a subroutine<br />
1 files changed, 5 insertions(+), 1 deletions(-)</p>
<p>I have an idea for a new UI feature, so I&#8217;m going to make a branch here, but not switch to it, since I want to add another feature on this refactor branch first.</p>
<p>$ git branch new-ui</p>
<p>While we&#8217;re still on refactor, let&#8217;s get rid of that ugly \n:</p>
<p>#!/usr/bin/env perl<br />
use 5.010;</p>
<p>say_hello();</p>
<p>sub say_hello {<br />
say &#8220;Hello, world.&#8221;;<br />
}</p>
<p>__END__</p>
<p>(Note to the non-perl-users; we added use 5.010 to pull in the new say feature. Unfortunately the program now depends on perl 5.10 instead of perl 5.anything.)</p>
<p>Much cleaner. Commit.</p>
<p>$ git ci -a -m &#8216;use say instead of print&#8217;<br />
Created commit 518dec1: use say instead of print<br />
1 files changed, 2 insertions(+), 1 deletions(-)</p>
<p>OK, with that braindump saved, let&#8217;s go over to the new-ui branch:</p>
<p>$ git co new-ui<br />
Switched to branch &#8220;new-ui&#8221;</p>
<p>Now let&#8217;s add that super cool feature, namely printing &#8220;Hello, world&#8221; three times instead of just once. You think the boss will go for this change before converting all the servers to Perl 5.10, so you add it on this branch that doesn&#8217;t require 5.10.</p>
<p>#!/usr/bin/env perl</p>
<p>say_hello();<br />
say_hello();<br />
say_hello();</p>
<p>sub say_hello {<br />
print &#8220;Hello, world.\n&#8221;;<br />
}</p>
<p>__END__</p>
<p>Let&#8217;s commit that.</p>
<p>$ git ci -a -m &#8216;say hello three times&#8217;<br />
Created commit affad78: say hello three times<br />
1 files changed, 2 insertions(+), 0 deletions(-)</p>
<p>The unfortunate part is that management hasn&#8217;t approved that UI change, and they haven&#8217;t let you upgrade your production server to 5.10 yet. So you switch back to master to work on a task that needs to be done immediately &#8212; adding some documentation.</p>
<p>$ git co master<br />
Switched to branch &#8220;master&#8221;</p>
<p>And then edit the file:</p>
<p>#!/usr/bin/env perl</p>
<p>print &#8220;Hello, world.\n&#8221;;</p>
<p>__END__</p>
<p>=head1 NAME</p>
<p>test.pl &#8211; say hello to the world</p>
<p>=head1 SYNOPSIS</p>
<p>perl test.pl</p>
<p>And commit:</p>
<p>$ git ci -a -m &#8216;add docs&#8217;<br />
Created commit 80d2bba: add docs<br />
1 files changed, 7 insertions(+), 0 deletions(-)</p>
<p>With all that productivity, you feel you&#8217;ve earned a sugary cup of coffee, so you head over to Caribou, buy one, and come back. You check your e-mail and find that the UI team loves your &#8220;say hello 3 times&#8221; change. So, let&#8217;s merge that into master:</p>
<p>$ git pull . new-ui<br />
Auto-merged test.pl<br />
Merge made by recursive.<br />
test.pl |    8 +++++++-<br />
1 files changed, 7 insertions(+), 1 deletions(-)</p>
<p>Your file looks like this now:</p>
<p>#!/usr/bin/env perl</p>
<p>say_hello();<br />
say_hello();<br />
say_hello();</p>
<p>sub say_hello {<br />
print &#8220;Hello, world.\n&#8221;;<br />
}</p>
<p>__END__</p>
<p>=head1 NAME</p>
<p>test.pl &#8211; say hello to the world</p>
<p>=head1 SYNOPSIS</p>
<p>perl test.pl</p>
<p>If you do a git log, you&#8217;ll see that git adds each change you merged in into the history:</p>
<p>commit a6d16af596b2d122f4348ded85ca14a74b6adaae<br />
Merge: 80d2bba&#8230; affad78&#8230;<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:35:16 2008 -0500</p>
<p>Merge branch &#8216;new-ui&#8217;</p>
<p>commit 80d2bba051c525257aa4930b362dbe01d6c280fe<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:34:03 2008 -0500</p>
<p>add docs</p>
<p>commit affad78861d53900199860e60b44fb5c500791f5<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:28:02 2008 -0500</p>
<p>say hello three times</p>
<p>commit 518dec18167d36f6f7813b3affc0e76ad9baf2d9<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:20:52 2008 -0500</p>
<p>factor print into a subroutine</p>
<p>commit 219c5b3a580c0d5d4453e118b7a9c40efb6cd13b<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:15:39 2008 -0500</p>
<p>initial import</p>
<p>Now you&#8217;ve found out that every copy of Perl 5.8 has been destroyed (blame the sunspots), and you&#8217;ll have to upgrade to 5.10. Because of that, you can merge in your 5.10 branch. Lucky break! One thing to lose hair over, though, is that the new-ui branch that you just merged in has some commits in common with the refactor branch you&#8217;re about to merge in. Will git try to apply that change twice? (No.)</p>
<p>Let&#8217;s try it:</p>
<p>$ git pull . refactor<br />
Auto-merged test.pl<br />
Merge made by recursive.<br />
test.pl |    3 ++-<br />
1 files changed, 2 insertions(+), 1 deletions(-)</p>
<p>As expected, it worked perfectly. Here&#8217;s the final file:</p>
<p>#!/usr/bin/env perl<br />
use 5.010;</p>
<p>say_hello();<br />
say_hello();<br />
say_hello();</p>
<p>sub say_hello {<br />
say &#8220;Hello, world.&#8221;;<br />
}</p>
<p>__END__</p>
<p>=head1 NAME</p>
<p>test.pl &#8211; say hello to the world</p>
<p>=head1 SYNOPSIS</p>
<p>perl test.pl</p>
<p>If you look at the log, you&#8217;ll see that git knows exactly what changes were included by the merge:</p>
<p>commit 1d4a7814c29678d8ce69d7e241dcb21c4e5d1b88<br />
Merge: a6d16af&#8230; d35db62&#8230;<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:44:20 2008 -0500</p>
<p>Merge branch &#8216;refactor&#8217;</p>
<p>commit a6d16af596b2d122f4348ded85ca14a74b6adaae<br />
Merge: 80d2bba&#8230; affad78&#8230;<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:35:16 2008 -0500</p>
<p>Merge branch &#8216;new-ui&#8217;</p>
<p>commit 80d2bba051c525257aa4930b362dbe01d6c280fe<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:34:03 2008 -0500</p>
<p>add docs</p>
<p>commit affad78861d53900199860e60b44fb5c500791f5<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:28:02 2008 -0500</p>
<p>say hello three times</p>
<p>commit d35db62f2a628687db8ab2e5759cae35cffb5ab0<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:23:45 2008 -0500</p>
<p>use say instead of print</p>
<p>commit 518dec18167d36f6f7813b3affc0e76ad9baf2d9<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:20:52 2008 -0500</p>
<p>factor print into a subroutine</p>
<p>commit 219c5b3a580c0d5d4453e118b7a9c40efb6cd13b<br />
Author: Jonathan Rockway<br />
Date:   Sun Apr 27 05:15:39 2008 -0500</p>
<p>initial import</p>
<p>Even though you&#8217;ve merged these branches into trunk, you can still work on them:</p>
<p>$ git co new-ui<br />
$ git rebase master</p>
<p>rebase will merge master into the current branch, but it works by deleting your commits, bringing in master&#8217;s commits, and then replaying yours on top. This avoids the useless &#8220;merge branch &#8216;foo&#8217;&#8221; commit, but at the cost of being unable to share your changes with another repository (since the commit ids will change; commit ids are dependant on history, and rebase rewrites history).</p>
<p>The usual use case for rebase is when you&#8217;re working on a feature that takes a few days to write and want to bring in upstream every day. Instead of polluting your feature branch with merges, you can rebase and nobody will ever know that your changes weren&#8217;t originally made against today&#8217;s upstream branch. (If there are conflicts, git will allow you to resolve them for each of your patches, and it will remember how you resolved them in case the same thing comes up when you rebase again tomorrow. See git rerere &#8211;help for details.)</p>
<p>Anyway, after the rebase, our new-ui branch is now up to date with respect to master. If you made some changes here, you could merge them into master without issue.</p>
<p>Let&#8217;s do one more example; we&#8217;ll see how to merge two branches at once. We&#8217;ll switch back to master, and make a doc-refactor branch, since your app really needs more docs.</p>
<p>$ git co master<br />
Switched to branch &#8220;master&#8221;<br />
$ git co -b doc-refactor<br />
Switched to a new branch &#8220;doc-refactor&#8221;</p>
<p>Here, we&#8217;ll add some POD to the end of the file:</p>
<p>__END__</p>
<p>=head1 NAME</p>
<p>test.pl &#8211; say hello to the world</p>
<p>=head1 SYNOPSIS</p>
<p>perl test.pl</p>
<p>=head1 HISTORY</p>
<p>As of version 0.01, C now prints &#8220;Hello, world.&#8221; three<br />
times, for maximum enjoyment.</p>
<p>This isn&#8217;t quite perfect yet, but let&#8217;s commit it.</p>
<p>$ git ci -a -m &#8216;explain the 3x feature&#8217;<br />
Created commit 80920ac: explain the 3x feature<br />
1 files changed, 5 insertions(+), 0 deletions(-)</p>
<p>Meanwhile, a critical bug was just discovered &#8212; a user paused too long while reading the comma in &#8220;Hello, world.&#8221;, so you need to remove it. We&#8217;ll branch off master, since this complicated fix may take a few days of testing to fully implement:</p>
<p>$ git branch comma-bug-fix master<br />
$ git co comma-bug-fix<br />
# fix it<br />
$ git ci -a -m &#8216;fix the comma bug&#8217;<br />
Created commit 053413e: fix the comma bug<br />
1 files changed, 1 insertions(+), 1 deletions(-)</p>
<p>That was easier than expected. Since the bugfix was pretty simple and your docs are done, you&#8217;re ready to share both of those changes with your coworkers by merging them into master:</p>
<p>$ git co master<br />
$ git pull . comma-bug-fix doc-refactor<br />
Trying simple merge with 053413e7fc2935cfe54de74178f493b7965081b3<br />
Trying simple merge with 80920ac16ad72d8714b4e767a09e1f8ce974fe5a<br />
Simple merge did not work, trying automatic merge.<br />
Auto-merging test.pl<br />
Merge made by octopus.<br />
test.pl |    7 ++++++-<br />
1 files changed, 6 insertions(+), 1 deletions(-)</p>
<p>I love the &#8220;Merge made by octopus&#8221; message; I am seriously going to have a t-shirt made that says that. I like it when sea creatures help maintain my code.</p>
<p>Finally, if you don&#8217;t need those branches anymore, you can blow them away:</p>
<p>$ git branch -d refactor new-ui comma-bug-fix doc-refactor<br />
Deleted branch refactor.<br />
Deleted branch new-ui.<br />
Deleted branch comma-bug-fix.<br />
Deleted branch doc-refactor.</p>
<p>Git will only delete branches that are completely merged into the current branch, so you don&#8217;t need to worry about losing data.</p>
<p>In conclusion, git makes non-linear development easy. It&#8217;s smart, so merges Just Work; worrying about branches is not something you need to do anymore. Additionally, if you are the visual type, try running gitk &#8211;all. It will draw an interactive graph of all your merge and branch points, so you can see where your branches are at-a-glance. It&#8217;s awesome.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrisjean.com/2009/11/12/great-tutorial-on-merging-with-git/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recursively Updating Git Submodules</title>
		<link>http://chrisjean.com/2009/09/16/recursively-updating-git-submodules/</link>
		<comments>http://chrisjean.com/2009/09/16/recursively-updating-git-submodules/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 18:30:20 +0000</pubDate>
		<dc:creator>Chris Jean</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Tips 'n Tricks]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[submodules]]></category>

		<guid isPermaLink="false">http://gaarai.com/?p=1528</guid>
		<description><![CDATA[I had fun writing about how I work with Git yesterday. I thought I&#8217;d continue on that thread. I have a solid set of code libraries that I&#8217;ve written that latch into the WordPress themes we produce at iThemes. Each time code is duplicated across different repositories, I break that code out and make it [...]]]></description>
			<content:encoded><![CDATA[<!-- filtered -->
<p>I had fun writing about how I work with Git yesterday. I thought I&#8217;d continue on that thread.</p>
<p>I have a solid set of code libraries that I&#8217;ve written that latch into the WordPress themes we produce at <a href="http://ithemes.com/" target="_blank">iThemes</a>. Each time code is duplicated across different repositories, I break that code out and make it into a separate repository. I then link it back into the project as a submodule. This makes it extremely-easy to keep duplicated code across numerous repositories updated with little or no fuss.</p>
<p>After cloning a repository, simply run <code>git submodule init</code> followed by <code>git submodule update</code> in order to initialize all the submodules and update their container folder with the content of the submodule&#8217;s repository. For a long time, this is exactly what I did when I would clone a theme repository to start working on it. However, this quickly wasn&#8217;t enough.</p>
<p>The problem happened as soon as I added a submodule to a repository that was also a submodule of other repositories. Doing the submodule init and update process wouldn&#8217;t do everything I needed in this case as there would be submodules in some subfolder that haven&#8217;t been set up.</p>
<p>I didn&#8217;t want to get into a habit of always switching to other directories and doing the submodule processes there as well since I 1) knew that I would forget all-too-often, thus wasting my time, and 2) knew that this would not be the last time that a submodule had submodules. Heck, there is even the possibility that I&#8217;ll have a submodule that has a submodule that has a submodule. It was immediately clear that I needed a script to do all this dirty work for me. The rest of this post will be about the script I created.</p>
<p><span id="more-1528"></span></p>
<h3>The Script</h3>
<p>First, I&#8217;ll share the script itself. If you are interested in how it works, continue reading.</p>
<p><a href="/git-submodule-recursive-update" target="_blank">git-submodule-recursive-update</a> (right-click &gt; &#8220;Save Link As&#8230;&#8221; to download)</p>
<p>The script is written in Perl and should work on most systems. I&#8217;ve only tested it on Linux and OS X, so please let me know your results if you try out on Windows.</p>
<pre class="code">#!/usr/bin/perl

use strict;
use Cwd;

init_and_update();

exit;

sub init_and_update
{
    my $start_path = cwd();

    my %paths;
    my $updated;

    do
    {
        my $data = `find . -name '.gitmodules'`;
        chomp($data);

        $data =~ s/\/\.gitmodules//g;

        foreach my $path (split(/\n/, $data))
        {
            $paths{$path} = '' if($paths{$path} eq '');
        }

        $updated = 0;

        foreach my $path (sort keys %paths)
        {
            if($paths{$path} eq '')
            {
                chdir($path);
                `git submodule init 2&gt;&amp;1`;
                `git submodule update 2&gt;&amp;1`;
                `git submodule foreach 'git checkout master' 2&gt;&amp;1`
                chdir($start_path);

                if($ARGV[0] eq '--remove-gitmodules')
                {
                    unlink("$path/.gitmodules");
                }

                $paths{$path} = 1;

                $updated++;
            }
        }
    } while($updated);
}</pre>
<h3>The Description</h3>
<p>The functionality should look very straight-forward to anyone that knows Perl.</p>
<ol>
<li>I store the current directory in the <code>$start_path</code> variable in order to always know where home is.</li>
<li>I start a wrapper loop that keeps running until all the possible submodules are initialized and updated.</li>
<li>Using the find command, I look for all the instances of <code>.gitmodules</code> and store the results in <code>$data</code>. The <code>.gitmodules</code> file exists if a repo has submodules.</li>
<li>I remove all the <code>.gitmodules</code> file references from the <code>$data</code> to leave just the paths.</li>
<li>I split the paths into an array and initialize the <code>%paths</code> hash to have a blank value for new paths (stored in the key). Setting this value to blank will flag the following loop that the submodules in that path have not been set up yet.</li>
<li>I create a tracker variable, <code>$updated</code>, to check if anything happened in the loop.</li>
<li>I then loop through the <code>%paths</code> hash to work on each path. If the path&#8217;s hash value is blank, I process that path.</li>
<li>I <code>cd</code> into the repo path, init and update the submodules, and switch back to the starting folder.</li>
<li>If the script is called with the optional <code>--remove-gitmodules</code> argument, I remove the <code>.gitmodules</code> folder while I&#8217;m focused on that folder. I use this for other automation scripts, so it may or may not be of value to you.</li>
<li>I then set the path&#8217;s hash value to <code>1</code> to flag it as done.</li>
<li>Closing out the loop, I update the <code>$updated</code> variable to show that something was updated in this pass.</li>
<li>Finishing up the <code>do</code> loop towards the top, I have <code>while($updated)</code>. Basically, as long as something was updated in the core update loop, I&#8217;ll run everything again. This means that the loop will keep running until it didn&#8217;t find anything else that needed to be updated. When that point is reached, the main loop ends, and the script is finished.</li>
</ol>
<p>I know that there are a number of things I could have done to make for a much more brief, compact script, but I was going to quick production with solid functionality, not brevity. In addition, there are unnecessary elements such as incrementing the <code>$updated</code> variable rather than just setting it to some value. I thought might want to know how many things were updated at some point, so I left it as a counter.</p>
<p>If you found this script helpful, please leave a comment. The more interest these Git-related posts receive, the more motivated I&#8217;ll be to share other processes, developments I&#8217;ve made to make working Git easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrisjean.com/2009/09/16/recursively-updating-git-submodules/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Updating Multiple Git Repositories Easily Using Bash for Loop</title>
		<link>http://chrisjean.com/2009/09/15/updating-multiple-git-repositories-easily-using-bash-for-loop/</link>
		<comments>http://chrisjean.com/2009/09/15/updating-multiple-git-repositories-easily-using-bash-for-loop/#comments</comments>
		<pubDate>Tue, 15 Sep 2009 16:42:14 +0000</pubDate>
		<dc:creator>Chris Jean</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Tips 'n Tricks]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[Mastering The Command Line]]></category>

		<guid isPermaLink="false">http://gaarai.com/?p=1508</guid>
		<description><![CDATA[All of the WordPress themes that I work on for iThemes are managed as Git repositories. Recently, we moved past the 100 repositories mark. That&#8217;s a lot of repositories to manage, and unfortunately, too many of those repositories contain duplicated information. Later on, I might delve into how we use Git to manage our theme [...]]]></description>
			<content:encoded><![CDATA[<!-- filtered -->
<p>All of the <a href="http://wordpress.org/" target="_blank">WordPress</a> themes that I work on for <a href="http://ithemes.com/" target="_blank">iThemes</a> are managed as Git repositories. Recently, we moved past the 100 repositories mark. That&#8217;s a lot of repositories to manage, and unfortunately, too many of those repositories contain duplicated information.</p>
<p>Later on, I might delve into how we use Git to manage our theme repos. For today, however, I&#8217;d like to focus on how I quickly and easily pushed up changes to more than a dozen repos in a single, albeit long, Bash command.</p>
<p>I had finished making updates to 16 <a href="http://ithemes.com/purchase/flexx-theme-wordpress-blog-themes/" target="_blank">Flexx</a> repos, and I needed to push all of those changes up. Since I had multiple working repos in that folder, I was lucky that each of these repos began with the text &#8220;Flexx&#8221;. Also, since they are all part of the same series and need to keep the same version number, that simplified the tagging as all could be tagged as 2.5.0.</p>
<p>Given this information, I simply ran the following command from the directory that contained all the repository directories:</p>
<div class="code">for i in `ls|grep Flexx`; do echo &#8220;&#8212; Pushing $i&#8221;; cd $i; git commit -am &#8217;2.5.0&#8242; &amp;&amp; git push &amp;&amp; git tag 2.5.0 &amp;&amp; git push &#8211;tags; cd ..; echo &#8220;&#8212; Finished $i&#8221;; done</div>
<p>There&#8217;s a lot going on here, so I&#8217;ll break it up and explain what I&#8217;m doing.</p>
<p><span id="more-1508"></span></p>
<div class="code">for i in `ls|grep Flexx`</div>
<p>This is basically a compound command. Bash&#8217;s <code>for</code> command is being used to step through the results of <code>ls|grep Flexx</code>. Each result will be stored to the variable <code>i</code> which can be referred to with <code>$i</code>.</p>
<p>In other words, I&#8217;m going to loop through each directory that contains the text &#8220;Flexx&#8221; (technically, it isn&#8217;t limited to just directories, but I don&#8217;t have any files containing &#8220;Flexx&#8221;, so I&#8217;m safe). For each iteration of the loop, the variable <code>$i</code> will contain the name of the folder I&#8217;m interested in.</p>
<div class="code">do echo &#8220;&#8212; Pushing $i&#8221;</div>
<p>The most important bit here is <code>do</code>. <code>do</code> simply begins the functional part of the loop and could be followed by any command that I wanted to start the loop with.</p>
<p>The <code>echo</code> command isn&#8217;t technically necessary. I simply have it there so that I can better determine what output belongs to which repository.</p>
<div class="code">cd $i</div>
<p>This is a very important command. It changes the directory to the repository I wish to run commands on.</p>
<div class="code">git commit -am &#8217;2.5.0&#8242; &amp;&amp; git push &amp;&amp; git tag 2.5.0 &amp;&amp; git push &#8211;tags</div>
<p>This is the command that actually does what I want to do in each repo directory. This adds all the modified files, commits them with a message of &#8220;2.5.0&#8243;, pushes the changes to the remote repository, creates a new tag of 2.5.0, and pushes up the new tag.</p>
<p>I have all of these commands chained together with <code>&amp;&amp;</code> so that if one command fails, the other ones won&#8217;t run. This prevents tagging in the event that the repository couldn&#8217;t be committed or pushed.</p>
<div class="code">cd ..</div>
<p>It&#8217;s a small command but necessary. This switches back to the main directory that holds all the repos, thus returning us back to a state that the next loop iteration can work with.</p>
<div class="code">echo &#8220;&#8212; Finished $i&#8221;</div>
<p>As with the other <code>echo</code> command, this simply allows me to keep track of what is going on more easily.</p>
<div class="code">done</div>
<p>The <code>done</code> command finishes out the loop iteration.</p>
<p>I hope that by sharing this you can gain a bit of insight into how I work with repositories while also learning more about how you can do things with Bash.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrisjean.com/2009/09/15/updating-multiple-git-repositories-easily-using-bash-for-loop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Git Submodules: Adding, Using, Removing, Updating</title>
		<link>http://chrisjean.com/2009/04/20/git-submodules-adding-using-removing-and-updating/</link>
		<comments>http://chrisjean.com/2009/04/20/git-submodules-adding-using-removing-and-updating/#comments</comments>
		<pubDate>Mon, 20 Apr 2009 05:00:48 +0000</pubDate>
		<dc:creator>Chris Jean</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Tips 'n Tricks]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[submodules]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://gaarai.com/?p=1423</guid>
		<description><![CDATA[I&#8217;ve spent a little more than a month working with Git now. I can honestly say that while there are many things that I like about Git, there are just as many things that I personally find to be a pain in the butt. Submodules specifically have managed to be a thorn in my side [...]]]></description>
			<content:encoded><![CDATA[<!-- filtered -->
<p>I&#8217;ve spent a little more than a month working with <a href="http://git-scm.com/" target="_blank">Git</a> now. I can honestly say that while there are many things that I like about Git, there are just as many things that I personally find to be a pain in the butt.</p>
<p>Submodules specifically have managed to be a thorn in my side on many occasions. While the concept of submodules is simple, figuring out how to actually work with them can be a chore. I say &#8220;figuring out&#8221; because not everything about working with submodules is well documented. I&#8217;ll cover two of the more difficult things to figure out: removing and updating submodules from your repository.</p>
<p><span id="more-1423"></span></p>
<h3>What are Submodules?</h3>
<p>The concept of submodules is brilliant. It essentially allows you to attach an external repository inside another repository at a specific path. In order to illustrate the value of submodules, it will probably be helpful for me to explain how I am using them.</p>
<p>My profession is working with <a href="http://wordpress.org/" target="_blank">WordPress</a> themes. Basically, I develop feature enhancements to the themes. I develop the code for these enhancements in modules that are completely contained in their own folder. This allows for the code to be easily added to other themes and also simplifies code updates/improvements as the code for specific features is consistent across all the themes that use that specific module.</p>
<p>Each theme that we produce is kept in its own Git repository. In addition, I&#8217;ve created a separate repository for each one of these feature modules. Rather than actually putting the feature module code directly into the theme repositories, I simply add the needed feature module repositories as submodules.</p>
<p>For example, we have a theme called FlexxBold. FlexxBold currently includes a total of seven submodules: billboard, contact-page-plugin, featured-images, feedburner-widget, file-utility, flexx-layout-editor, and tutorials. Since I&#8217;m using submodules, the code can be pulled directly from the relevant submodule repositories rather than requiring me to manually update each individual theme repository.</p>
<p>As I mentioned before, not everything in Git is easy to work with. There are four main functions you will need to understand in order to work with Git submodules. In order, you will need to know how to add, make use of, remove, and update submodules. I&#8217;ll cover each of those uses below.</p>
<h3>Adding Submodules to a Git Repository</h3>
<p>Fortunately, adding a submodule to a git repository is actually quite simple. For example, if I&#8217;m in the repository working directory of a new theme called SampleTheme and need to add the billboard repository to the path lib/billboard, I can do so with the following command:</p>
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git submodule add git@mygithost:billboard lib/billboard</span>
Initialized empty Git repository in ~/git_dev/SampleTheme/lib/billboard/.git/
remote: Counting objects: 1006, done.
remote: Compressing objects: 100% (978/978), done.
remote: Total 1006 (delta 631), reused 0 (delta 0)
Receiving objects: 100% (1006/1006), 408.22 KiB, done.
Resolving deltas: 100% (631/631), done.</pre>
<p>There are three main parts to this command:</p>
<ul>
<li>git submodule add &#8211; This simply tells Git that we are adding a submodule. This syntax will always remain the same.</li>
<li>git@mygithost:billboard &#8211; This is the external repository that is to be added as a submodule. The exact syntax will vary depending on the setup of the Git repository you are connecting to. You need to ensure that you have the ability to clone the given repository.</li>
<li>lib/billboard &#8211; This is the path where the submodule repository will be added to the main repository.</li>
</ul>
<p>Let&#8217;s check to see how the repository is doing.</p>
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git status</span>
# On branch master
# Changes to be committed:
#   (use "git reset HEAD &lt;file&gt;..." to unstage)
#
#       new file:   .gitmodules
#       new file:   lib/billboard
#</pre>
<p>Notice how the supplied path was created and added to the changes to be committed. In addition, a new file called .gitmodules was created. This new file contains the details we supplied about the new submodule. Out of curiosity, let&#8217;s check out the contents of that new file:</p>
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">cat .gitmodules</span>
[submodule "lib/billboard"]
path = lib/billboard
url = git@mygithost:billboard</pre>
<p>Being able to modify this file later will come in handy later.</p>
<p>All that is left to do now is to commit the changes and then push the commit to a remote system if necessary.</p>
<h3>Using Submodules</h3>
<p>Having submodules in a repository is great and all, but if I look in my repository, all I have is an empty folder rather than the actual contents of the submodule&#8217;s repository. In order to fill in the submodule&#8217;s path with the files from the external repository, you must first initialize the submodules and then update them.</p>
<div class="post-notice">
<p>Note: This has changed in newer versions of  Git. Now the submodule&#8217;s repository will be cloned with master checked out. If that repository also has submodules, then your submodule&#8217;s submodules will have to be populated by following the steps below from within your project&#8217;s submodule directory (confusing yet?).</p>
<p>For instance, if you are working in project called <code>phone-app</code>, add a submodule called <code>graphics-lib</code>, and <code>graphics-lib</code> has a submodule called <code>renderer</code>, when you add <code>graphics-lib</code> to <code>phone-app</code>, the <code>phone-app/graphics-lib</code> directory will be populated as a cloned repo but the <code>phone-app/graphics-lib/renderer</code> directory will be empty. To populate <code>phone-app/graphics-lib/renderer</code>, first change directories to <code>phone-app/graphics-lib</code> and follow the instructions below.</p>
</div>
<p>First, we need to initialize the submodule(s). We can do that with the following command:</p>
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git submodule init</span>
Submodule 'lib/billboard' (git@mygithost:billboard) registered for path 'lib/billboard'</pre>
<p>Then we need to run the update in order to pull down the files.</p>
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git submodule update</span>
Initialized empty Git repository in ~/git_dev/SampleTheme/lib/billboard/.git/
remote: Counting objects: 26, done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 26 (delta 5), reused 0 (delta 0)
Receiving objects: 100% (26/26), 17.37 KiB, done.
Resolving deltas: 100% (5/5), done.
Submodule path 'lib/billboard': checked out '1c407cb2315z0847facb57d79d680f88ca004332'</pre>
<p>Looking in the lib/billboard directory now shows a nice listing of the needed files.</p>
<h3>Removing Submodules</h3>
<p>What happens if we need to remove a submodule? Maybe I made a mistake. It could also be that the design of the project has changed, and the submodules need to change with it. No problem, I&#8217;ll simply run &#8220;<strong>git submodule rm [submodule path]</strong>&#8221; and everything will be great, right?</p>
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git submodule rm lib/billboard</span>
error: pathspec 'rm' did not match any file(s) known to git.
Did you forget to 'git add'?
 b8ff8f68eb56938b9b4bf993619218fa848c5848 lib/billboard (1.2.25)</pre>
<p>Unfortunately, this is wrong. Git does not have a built in way to remove submodules. Hopefully this will be resolved in the future, because we now have to do submodule removal manually.</p>
<p>Sticking with the example, we&#8217;ll remove the lib/billboard module from SampleTheme. All the instructions will be run from the working directory of the SampleTheme repository. In order, we need to do the following:</p>
<ol>
<li>Remove the submodule&#8217;s entry in the .gitmodules file.Since lib/billboard is the only submodule in the SampleTheme repository, we can simply remove the file entirely by running &#8220;git rm lib/billboard&#8221;.If lib/billboard isn&#8217;t the only submodule, the .gitmodules file will have to be modified by hand. Open it up in vi, or your favorite text editory, and remove the three lines relevant to the submodule being removed. In this case, these lines will be removed:
<div class="code">[submodule "lib/billboard"]<br />
path = lib/billboard<br />
url = git@mygithost:billboard</div>
</li>
<li>Remove the submodule&#8217;s entry in the .git/config. This step isn&#8217;t strictly necessary, but it does keep your config file tidy and will help prevent problems in the future.The submodule&#8217;s entry in .git/config will only be present if you&#8217;ve run &#8220;git submodule init&#8221; on the repository. If you haven&#8217;t, you can skip this step.In this example, the following lines will be removed:
<div class="code">[submodule "billboard"]<br />
url = git@mygithost:billboard</div>
</li>
<li>Remove the path created for the submodule. This one is easy. Simply run &#8220;<strong>git rm &#8211;cached [plugin path]</strong>&#8220;. In this example, I will run &#8220;<strong>git rm &#8211;cached lib/billboard</strong>&#8220;.As I&#8217;ve seen noted elsewhere, do not put a trailing slash as the command will fail. For example, if I run &#8220;<strong>git rm &#8211;cached lib/billboard/</strong>&#8220;, I get an error: &#8220;<strong>fatal: pathspec &#8216;lib/billboard/&#8217; did not match any files</strong>&#8220;.
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git rm --cached lib/billboard</span>
rm 'lib/billboard'</pre>
</li>
</ol>
<h3>Updating Submodules</h3>
<p>There is an aspect about submodules that some may not realize when first working with Git submodules. When you add the submodule, the most recent commit of the submodule is stored in the main repository&#8217;s index. That means that as the code in the submodule&#8217;s repository updates, the same code will still be pulled on the repositories relying on the submodule.</p>
<p>This makes a lot of sense when you consider how your code will have been tested and verified (or at least should be) against a specific version of the submodule code, but the main repository&#8217;s code may not work well with new submodule updates before the changes are tested.</p>
<p>Unfortunately, like removing submodules, Git does not make it clear how to update a submodule to a later commit. Fortunately though, it&#8217;s not that tough.</p>
<ol>
<li>Initialize the repository&#8217;s submodules by running &#8220;<strong>git submodule init</strong>&#8221; followed by &#8220;<strong>git submodule update</strong>&#8220;.
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git submodule init</span>
Submodule 'lib/billboard' (git@mygithost:billboard) registered for path 'lib/billboard'
<span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git submodule update</span>
Initialized empty Git repository in ~/git_dev/SampleTheme/lib/billboard/.git/
remote: Counting objects: 26, done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 26 (delta 5), reused 0 (delta 0)
Receiving objects: 100% (26/26), 17.37 KiB, done.
Resolving deltas: 100% (5/5), done.
Submodule path 'lib/billboard': checked out '1c407cb2315z0847facb57d79d680f88ca004332'</pre>
</li>
<li>Change into the submodule&#8217;s directory. In this example, &#8220;<strong>cd lib/billboard</strong>&#8220;.
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">cd lib/billboard</span>
<span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme/lib/billboard</span>]$</span> <span style="color:#FFF;"></span></pre>
</li>
<li>The submodule repositories added by &#8220;<strong>git submodule update</strong>&#8221; are &#8220;headless&#8221;. This means that they aren&#8217;t on a current branch.To fix this, we simply need to switch to a branch. In this example, that would be the master branch. We switch with the following command: &#8220;<strong>git checkout master</strong>&#8220;.
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme/lib/billboard</span>]$</span> <span style="color:#FFF;">git status</span>
# Not currently on any branch.
nothing to commit (working directory clean)
<span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme/lib/billboard</span>]$</span> <span style="color:#FFF;">git checkout master</span>
Previous HEAD position was b8ff8f6... re-ordering
Switched to branch 'master'
Your branch is behind 'origin/master' by 8 commits, and can be fast-forwarded.
<span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme/lib/billboard</span>]$</span> <span style="color:#FFF;">git status</span>
# On branch master
# Your branch is behind 'origin/master' by 8 commits, and can be fast-forwarded.
#
nothing to commit (working directory clean)</pre>
</li>
<li>Next, we simply need to update the repository to ensure that we have the latest updates. We can do that with a pull: &#8220;<strong>git pull</strong>&#8220;.
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme/lib/billboard</span>]$</span> <span style="color:#FFF;">git pull</span>
remote: Counting objects: 31, done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 24 (delta 15), reused 0 (delta 0)
Unpacking objects: 100% (24/24), done.
From mygithost:billboard
   b8ff8f6..5cab93f  master     -&gt; origin/master
 * [new tag]         1.2.28     -&gt; 1.2.28
From mygithost:billboard
 * [new tag]         1.2.26     -&gt; 1.2.26
 * [new tag]         1.2.27     -&gt; 1.2.27
Updating c547e0d..5cab93f
Fast-forward
 billboard.php                           |  109 ++++++++++++++-
 classes/view_gettingstarted.php         |  107 ++++++++++++++
 classes/view_gettingstarted_content.php |   38 +++++
 css/admin.css                           |   26 ++++
 history.txt                             |   22 +++-
 js/admin.js                             |   17 +++
 lib/updater/get.php                     |   94 +++++++-----
 lib/updater/history.txt                 |    9 ++
 lib/updater/updater.php                 |  241 ++++++++++++++++++-------------
 9 files changed, 519 insertions(+), 144 deletions(-)
 create mode 100644 classes/view_gettingstarted.php
 create mode 100644 classes/view_gettingstarted_content.php
 create mode 100644 css/admin.css
 create mode 100644 js/admin.js
 create mode 100644 lib/updater/history.txt</pre>
</li>
<li>Now switch back to the root working directory of the repository. In our example, we are two directories in, so we run &#8220;<strong>cd ../..</strong>&#8220;.
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme/lib/billboard</span>]$</span> <span style="color:#FFF;">cd ../..</span>
<span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;"></span></pre>
</li>
<li>Everything is now ready to be commit and pushed back in (if there is a remote repository to push to that is). If you run &#8220;<strong>git status</strong>&#8220;, you&#8217;ll notice that the path to the submodule is listed as modified. This is what you should expect to see. Simply add the path to be commit and do a commit. When you do the commit, the index will update the commit string for the submodule.
<pre class="terminal"><span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git status</span>
# On branch master
# Changed but not updated:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#	modified:   lib/billboard (new commits)
#
no changes added to commit (use "git add" and/or "git commit -a")
<span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git add lib/billboard</span>
<span style="color:#8FED99;">[<span style="color:#BBFF33;">user@office</span> <span style="color:#729FCF;">SampleTheme</span>]$</span> <span style="color:#FFF;">git status</span>
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#	modified:   lib/billboard
#</pre>
</li>
</ol>
<h3>Closing Thoughts</h3>
<p>I&#8217;ve learned a lot in my short time with Git. Expect to see more details about working with Git in the future. I have a series of pitfalls I&#8217;ve discovered that I should organize together and post about. I&#8217;ve also created some really slick scripts to help me automate numerous things when working with the repositories that I&#8217;d like to share.</p>
<p>If there is anything specfic you&#8217;d like to know about Git, please add a comment or <a href="http://chrisjean.com/contact/" target="_blank">contact me</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrisjean.com/2009/04/20/git-submodules-adding-using-removing-and-updating/feed/</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>Goodbye Subversion, Hello Git</title>
		<link>http://chrisjean.com/2009/03/17/goodbye-subversion-hello-git/</link>
		<comments>http://chrisjean.com/2009/03/17/goodbye-subversion-hello-git/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 21:33:29 +0000</pubDate>
		<dc:creator>Chris Jean</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Random Ramblings]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[Gitosis]]></category>
		<category><![CDATA[Subversion]]></category>
		<category><![CDATA[VCS]]></category>

		<guid isPermaLink="false">http://gaarai.com/?p=1376</guid>
		<description><![CDATA[As I mentioned before, I want to switch from using Subversion for project code collaboration and versioning to Git. I&#8217;m switching not because I have some idealogical dread of Subversion or its methods. In fact, I quite like how much easier Subversion has made handling code collaboration. The problem I ran into is that Subversion [...]]]></description>
			<content:encoded><![CDATA[<!-- filtered -->
<p>As <a href="http://chrisjean.com/2009/02/21/git-project-description-file-hasnt-been-set/" target="_blank">I mentioned before</a>, I want to switch from using <a href="http://subversion.tigris.org/" target="_blank">Subversion</a> for project code collaboration and versioning to <a href="http://git-scm.com/" target="_blank">Git</a>.</p>
<p>I&#8217;m switching not because I have some idealogical dread of Subversion or its methods. In fact, I quite like how much easier Subversion has made handling code collaboration. The problem I ran into is that Subversion has become doggedly slow and bloated.</p>
<p>For example, a simple project with a current working size of 2.9MB has a Subversion repository that is a massive 98MB in size. Furthermore, it takes a full four minutes to commit a change, even a simple one-line change to a text file. During this commit process, my server&#8217;s dual quad-core processors are essentially maxed. Why the repository has become so amazingly large and why the commits take so long, I&#8217;ll never know. The maxing out of my server for four minutes per commit is also unacceptable since there are times where minor changes will need to be made to more than a dozen repositories at a time. Multiply the number of commits by 4 minutes a piece, and not only is a terminal on my system tied up for more than an hour, but my server&#8217;s CPU is maxed for just as long.</p>
<p>Beginning last week, I dug into Git and learned what I needed to know. The initial impressions are great; however, Git is not without its problems either. The primary problem with Git is that its syntax is extremely-obscure, IMHO.</p>
<p><span id="more-1376"></span></p>
<p>Subversion was my first <a href="http://en.wikipedia.org/wiki/Version_control_system" target="_blank">version control system</a>, and I only started using it a few months ago. Still, I had no problem setting up remote Subversion repositories, properly setting up read-only and write privilege rules for specific people, getting the repositories to work appropriately, writing automation scripts in Perl that linked into the hooks, and wrapping the whole deal in WordPress to allow for easy management of the repositories and quick access to archives. From my initial playing around with Subversion to having a functional system in use complete with custom code supporting it took maybe two or three work days worth of time.</p>
<p>My progress with Git has been much slower. You might wonder why I&#8217;m bothering with Git and not looking elsewhere then. Frankly, I have found that Git has everything I want (speed, lack of redundant file stores, hooks, etc). It also looks like Git can offer some nice enhancements to how we develop projects as branches can be used without having severe performance penalties. The only true problem I&#8217;ve found with Git so far is the relatively-large learning curve. Fortunately, I&#8217;m just about done with reading, and I&#8217;ve learned all the basics I need to know to implement a system I want.</p>
<p>I started with Git by jumping into the wading pool at <a href="http://github.com/" target="_blank">GitHub</a>. My experience was very good. I highly recommend using GitHub if you have a public project, a private project without specific needs, or just want to try Git out. There are a lot of options at GitHub, and they very nearly had everything I wanted. One of the main limitations at GitHub is the inability for an account to allow other accounts to make repositories for it. For many projects/companies, this won&#8217;t be a problem. For us, it is a critical issue. I want to allow certain people to create new repositories, but I don&#8217;t want to have to give them &#8220;the keys&#8221; to the main account in order to allow them to do this.</p>
<p>So, I&#8217;m sticking with a self-hosted solution for our repositories since I can code up a clean interface that allows anyone with commit access to create whatever repositories they need. I also gain many other customization advantages this way.</p>
<p>Setting up remote repositories, especially private ones with selective access can be a challenge with the tools that come with Git. In fact, they were so much of a challenge that I gave up on them. I ended up using <a href="http://eagain.net/gitweb/?p=gitosis.git;a=summary" target="_blank">Gitosis</a> which supports multiple &#8220;users&#8221; that authenticate using their SSH key and allows for selective repository access for these users.</p>
<p>Since Gitosis doesn&#8217;t appear to have any official site, it&#8217;s use, just like Git itself, is a bit of a difficult thing to grasp. Fortunately, there are some great tutorials on getting starting with Gitosis. I recommend <a href="http://scie.nti.st/2007/11/14/hosting-git-repositories-the-easy-and-secure-way" target="_blank">this Gitosis tutorial</a> as it is the main one that I referred to in order to get everything working.</p>
<p>If this topic looks like it is gaining interest, I&#8217;ll probably do some follow up post with more specifics of how I set everything up, what config tweaks I used, and maybe details about my custom interfaces.</p>
<p>FYI: I converted that 98MB Subversion repository to Git using the git-svn tool. The same repository with all the tags and history preserved weighed in at a mere 6.9MB as a Git repository.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrisjean.com/2009/03/17/goodbye-subversion-hello-git/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>git: &#8220;Project description file hasn&#8217;t been set&#8221;</title>
		<link>http://chrisjean.com/2009/02/21/git-project-description-file-hasnt-been-set/</link>
		<comments>http://chrisjean.com/2009/02/21/git-project-description-file-hasnt-been-set/#comments</comments>
		<pubDate>Sat, 21 Feb 2009 06:00:49 +0000</pubDate>
		<dc:creator>Chris Jean</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Tips 'n Tricks]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://gaarai.com/?p=1163</guid>
		<description><![CDATA[I&#8217;m playing around with git as a possible replacement for Subversion (svn). I&#8217;ll probably blog about my reasons for wanting to switch and also have some tutorials. For now, I wanted to quickly share the fix for a problem I encountered that wasn&#8217;t really handled by the documentation. I set up a bare remote repository [...]]]></description>
			<content:encoded><![CDATA[<!-- filtered -->
<p>I&#8217;m playing around with <a href="http://git-scm.com/" target="_blank">git</a> as a possible replacement for <a href="http://subversion.tigris.org/" target="_blank">Subversion</a> (svn). I&#8217;ll probably blog about my reasons for wanting to switch and also have some tutorials. For now, I wanted to quickly share the fix for a problem I encountered that wasn&#8217;t really handled by the <a href="http://git-scm.com/documentation" target="_blank">documentation</a>.</p>
<p>I set up a bare remote repository to test git out. Everything looked good as I got this going, but then I hit a big snag.</p>
<p>When I tried to push the local repository back to the remote repository, I received the following error:</p>
<p><span id="more-1163"></span></p>
<div class="code">$ git push repository master<br />
Counting objects: 9, done.<br />
Compressing objects: 100% (5/5), done.<br />
Writing objects: 100% (5/5), 531 bytes, done.<br />
Total 5 (delta 3), reused 0 (delta 0)<br />
*** Project description file hasn&#8217;t been set<br />
error: hooks/update exited with error code 1<br />
error: hook declined to update refs/heads/master<br />
To ssh://username@hostname/projectname<br />
! [remote rejected] master -&gt; master (hook declined)<br />
error: failed to push some refs to &#8216;ssh://username@hostname/~/projectname&#8217;</div>
<p>I have to say that this was completely unexpected as I had followed tutorials in the official documentation up to this point. None of the steps said anything about a &#8220;project description file&#8221; nor about new bare repositories requiring additional setup in order to be pushed to.</p>
<p>Fortunately, this problem wasn&#8217;t difficult to fix. There is a file inside the bare repository&#8217;s root called description. I simply modified this file and the next time I pushed the changes, it worked like a charm.</p>
<p>If your bare repository is in ~/projects/test.git, you would do the following:</p>
<ol>
<li>Modify the description file:
<div class="code">vi ~/projects/test.git/description</div>
</li>
<li>Delete the existing text:
<div class="code">Unnamed repository; edit this file to name it for gitweb.</div>
</li>
<li>Put whatever description you want for the repository in the file:
<div class="code">My Really Awesome Project</div>
</li>
<li>As always, save the file and close vi.</li>
</ol>
<p>Now you can push without this nasty error hanging you up.</p>
<p>As a side note, the developers of git have a hosted git solution that is really cool. It&#8217;s called <a href="http://github.com/" target="_blank">github</a>, you should check it out.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrisjean.com/2009/02/21/git-project-description-file-hasnt-been-set/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

