<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>object.io</title>
	
	<link>http://object.io/site</link>
	<description>All code has costs. Only some code has value.</description>
	<lastBuildDate>Tue, 20 Dec 2011 20:44:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/objectio" /><feedburner:info uri="objectio" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>56.15</geo:lat><geo:long>10.22</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-sa/3.0/</creativeCommons:license><feedburner:emailServiceId>objectio</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Getting to know Ruby debugger</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/WhCLu5qn2rM/</link>
		<comments>http://object.io/site/2011/getting-to-know-ruby-debugger/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 13:07:09 +0000</pubDate>
		<dc:creator>Cameron Dykes</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[debugger]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://object.io/site/?p=460</guid>
		<description><![CDATA[This is a guest-post by Cameron Dykes, about getting started with the ruby debugger. A key step to debugging any program is replicating the environment to ensure you can consistently produce the bug. In my early Ruby days, to inspect (&#8230;)</p><p><a href="http://object.io/site/2011/getting-to-know-ruby-debugger/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><em>This is a guest-post by <a href="https://github.com/yellow5">Cameron Dykes</a>, about getting started with the ruby debugger.</em></p>
<p>A key step to debugging any program is replicating the environment to ensure you can consistently produce the bug. In my early <a href="http://ruby-lang.org">Ruby</a> days, to inspect the environment, I used a primitive method: placing <code>puts</code> lines in my code to print values to the console (let&#8217;s call them &#8220;inspection puts&#8221;). It may have looked something like this:</p>
<div id="gist-1290190" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">class</span> <span class="nc">Buggy</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="c1"># assuming perform_operation and special_options exist...</span></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">buggy_method</span><span class="p">(</span><span class="n">param</span><span class="o">=</span><span class="kp">nil</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="p">{})</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\n\n\n</span><span class="s2">DEBUG&quot;</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">puts</span> <span class="s2">&quot;param: </span><span class="si">#{</span><span class="n">param</span><span class="si">}</span><span class="s2">&quot;</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">puts</span> <span class="s2">&quot;options: </span><span class="si">#{</span><span class="n">options</span><span class="si">}</span><span class="s2">&quot;</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@instance_var</span> <span class="o">=</span> <span class="n">perform_operation</span><span class="p">(</span><span class="n">special_options</span><span class="p">(</span><span class="n">param</span><span class="p">,</span> <span class="n">options</span><span class="p">))</span></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC9'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1290190/db97518c5293dcc397a7d8a53be7b6e9ee18cd80/debug-example1.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1290190#file_debug_example1.rb" style="float:right;margin-right:10px;color:#666">debug-example1.rb</a>
            <a href="https://gist.github.com/1290190">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h3>The case for ruby-debug</h3>
<p>This method very easily gives me the information I need, but it has some downsides:</p>
<ol>
<li>To inspect the return value of <code>special_options</code> I have to add another inspection puts.</li>
<li>Every addition of a new <code>puts</code> requires that I restart the application to inspect the results.</li>
<li>To inspect how <code>special_options</code> and <code>perform_operation</code> are handling the data, I have to add inspection puts inside of them.</li>
<li>I must remember to remove all of the inspection puts before I push the code.</li>
</ol>
<p>If only there was a better way to do this.</p>
<p><a href="https://rubygems.org/gems/ruby-debug19">ruby-debug</a> to the rescue! By putting a breakpoint in our code, we have the ability to inspect environment state, check the return value of any methods, and step through our code one line at a time. This is much more versatile than inspection puts because the full environment is available to us. The &#8220;I wonder what the value of this is&#8221; problem is gone since we can inspect whatever we want. The step functionality the debugger gives us is useful as well, allowing us to step inside of a called method while maintaining the interactive environment.</p>
<h3>Setting up ruby-debug</h3>
<p>To get set up with the debugger, we&#8217;ll need to install the gem:</p>
<div id="gist-1290190" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c"># Using MRI-1.9.2</span></div><div class='line' id='LC2'>gem install ruby-debug19</div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="c"># Using MRI-1.8.7 or Ruby Enterprise Edition</span></div><div class='line' id='LC5'>gem install ruby-debug</div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1290190/e0498a60ce18dd99d25fc0afecf7c8b840f6c7ed/debugger-installation.sh" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1290190#file_debugger_installation.sh" style="float:right;margin-right:10px;color:#666">debugger-installation.sh</a>
            <a href="https://gist.github.com/1290190">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h3>ruby-debug in action</h3>
<p>Let&#8217;s update the example from above using a debugger breakpoint instead of inspection puts:</p>
<div id="gist-1290190" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">class</span> <span class="nc">Buggy</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="c1"># assuming perform_operation and special_options exist...</span></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">buggy_method</span><span class="p">(</span><span class="n">param</span><span class="o">=</span><span class="kp">nil</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="p">{})</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">require</span> <span class="s1">&#39;ruby-debug&#39;</span><span class="p">;</span> <span class="n">debugger</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@instance_var</span> <span class="o">=</span> <span class="n">perform_operation</span><span class="p">(</span><span class="n">special_options</span><span class="p">(</span><span class="n">param</span><span class="p">,</span> <span class="n">options</span><span class="p">))</span></div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC7'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1290190/c744e48b1e52d36460addf3c9d2cd594a38733ad/debug-example2.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1290190#file_debug_example2.rb" style="float:right;margin-right:10px;color:#666">debug-example2.rb</a>
            <a href="https://gist.github.com/1290190">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>The next time the method is called, the debugger will stop and give us an interactive shell. We can inspect the values of each variable with the <code>eval</code> command:</p>
<pre><code>eval param
eval options
</code></pre>
<p>We can also see what the return value is of the invoked methods:</p>
<pre><code>eval special_options(param, options)
eval perform_operation(special_options(param, options))
</code></pre>
<p>We can even use the step command to enter inside of <code>special_options</code> and <code>perform_operation</code> to see what they do.</p>
<p>Here are the various debugger commands that I most commonly use:</p>
<ul>
<li><code>list, l</code> &#8211; show the code for the current breakpoint</li>
<li><code>eval, e</code> &#8211; evaluate expression and print the value</li>
<li><code>step, s</code> &#8211; next line of code, moving within methods</li>
<li><code>continue, c</code> &#8211; continue in the program until the program ends or reaches another breakpoint</li>
<li><code>quit, q</code> &#8211; abort the program</li>
</ul>
<p>Many more commands are available, which can be seen by entering <code>help</code> in the debugger.</p>
<h3>Better debugging ftw!</h3>
<p>With the <a href="https://rubygems.org/gems/ruby-debug19">ruby-debug</a> gem, we have a better tool for diving in to our code than inspection puts. Using a debugger breakpoint, we can interactively step through our code with less cleanup.</p>
<p>Happy debugging!</p>
<h3>Debugging references</h3>
<ul>
<li><a href="http://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-ruby-debug">Debugging with ruby-debug in the Debugging Rails Applications guide</a></li>
<li><a href="https://rubygems.org/gems/ruby-debug19">ruby-debug19 gem</a></li>
<li><a href="https://gist.github.com/1290190">Example code from this post</a></li>
</ul>
<h3>Who am I?</h3>
<ul>
<li><a href="http://twitter.com/yellow5">@yellow5</a></li>
<li><a href="http://github.com/yellow5">Github</a></li>
</ul>
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/ruby-stacktrace-at-will/' title='Identify what your Ruby process is doing'>Identify what your Ruby process is doing</a></li>
<li><a href='http://object.io/site/2011/idiomatic-rspec-state/' title='Idiomatic shared state in RSpec'>Idiomatic shared state in RSpec</a></li>
<li><a href='http://object.io/site/2011/rails-data-import/' title='Quick data import and linking in Rails'>Quick data import and linking in Rails</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/WhCLu5qn2rM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/getting-to-know-ruby-debugger/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/getting-to-know-ruby-debugger/</feedburner:origLink></item>
		<item>
		<title>Deploy a private Github repository with whiskey_disk</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/UFe21zbDESM/</link>
		<comments>http://object.io/site/2011/whiskey_disk-private-github/#comments</comments>
		<pubDate>Sun, 04 Sep 2011 00:00:04 +0000</pubDate>
		<dc:creator>Laust Rud Jacobsen</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[whiskey_disk]]></category>

		<guid isPermaLink="false">http://object.io/site/?p=420</guid>
		<description><![CDATA[whiskey_disk makes it very easy to quickly deploy a new version of your site to one or more servers. It&#8217;s very efficient, as files are copied directly from your git repository to the server. This means you can very quickly (&#8230;)</p><p><a href="http://object.io/site/2011/whiskey_disk-private-github/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/flogic/whiskey_disk">whiskey_disk</a> makes it very easy to quickly deploy a new version of your site to one or more servers. It&#8217;s very efficient, as files are copied directly from your git repository to the server. This means you can very quickly make large deployments even when you are on a slow internet connection. You do need a secure way for your server to access the git repository while the deploy is going on, read on to see how this is easily done.</p>
<p>For this example, I&#8217;m going to deploy a small static site from a private <a href="https://github.com">Github</a> repository to a server via ssh using whiskey_disk.  There are a few steps in getting this all setup, but once you have the ssh infrastructure playing nicely, a complete deployment of a small static site takes on the order of 2-5 seconds. Stay with me, and I&#8217;ll show how all the pieces fit together.</p>
<p>To begin with, I&#8217;ll assume you have a site or application already pushed to a private Github reposity that you now want to do a deploy of. You also have ssh access to the server you are deploying to for this to work. For this example, I&#8217;m deploying the <code>master</code> branch of the following private git repository:</p>
<blockquote>
<pre><code>git@github.com:rud/whiskey_disk-demo.git
</code></pre>
</blockquote>
<h2>Adding the configuration file</h2>
<p>Make sure you have your appropriate code pushed to Github, then we&#8217;ll add the whiskey_disk config file <code>config/deploy.yml</code> to the project:</p>
<blockquote>
<pre><code>demo:
  domain: "deploy_user@example.com"
  deploy_to: "/home/deploy_user/domains/useful_site.com"
  repository: "git@github.com:rud/whiskey_disk-demo.git"
</code></pre>
</blockquote>
<p>This is a simple YAML file (indentation matters), you will need to adjust the domain and paths as appropriate. I use the name <code>demo</code> for the environment, other common examples would be <code>staging</code>, <code>production</code>, etc. A lot more options are available, see the official <a href="https://github.com/flogic/whiskey_disk#readme">whiskey_disk readme</a>, but this all we need to get started.</p>
<h2>Running whiskey_disk setup</h2>
<p>whiskey_disk has two commands: a <code>setup</code> command, for doing the initial repository clone, and the <code>deploy</code> command used for all subsequent deploys.</p>
<p>With the <code>config/deploy.yml</code> file in place inside the project, we&#8217;re going to just try and run the <code>setup</code> command from the local computer, seeing what happens. For now, this errors out:</p>
<blockquote>
<pre><code>$ wd setup -t demo
Initialized empty Git repository in /home/deploy_user/domains/useful_site.com/.git/
Host key verification failed.
fatal: The remote end hung up unexpectedly
fetch-pack from 'git@github.com:rud/whiskey_disk-demo.git' failed.
error: pathspec 'origin/master' did not match any file(s) known to git.
Did you forget to 'git add'?
</code></pre>
</blockquote>
<p>Okay, we&#8217;re not quite ready to do deployments just yet.</p>
<h3>Resolving all ssh issues</h3>
<p>Github hangs up on us &#8211; what&#8217;s happening? Testing from my local machine as described in <a href="http://help.github.com/ssh-issues/">the github ssh guide</a>:</p>
<blockquote>
<pre><code>$ ssh -T git@github.com
Hi rud! You've successfully authenticated, but GitHub does not provide shell access.
</code></pre>
</blockquote>
<p>That&#8217;s the kind of success we&#8217;re looking for on the server as well. Ssh to the server as the deploy user, and try the same command there:</p>
<blockquote>
<pre><code>$ ssh -T git@github.com
The authenticity of host 'github.com (207.97.227.239)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,207.97.227.239' (RSA) to the list of known hosts.
Permission denied (publickey).
</code></pre>
</blockquote>
<p>Try the command again, now that the host key is trusted:</p>
<blockquote>
<pre><code>$ ssh -T git@github.com
Permission denied (publickey).
</code></pre>
</blockquote>
<p>Notice how we get a new error later in the connection process, a <code>Permission denied (publickey)</code> instead of <code>Host key verification failed</code>.</p>
<p>For the sake of completeness, this is what this situation looks like from whiskey_disk:</p>
<blockquote>
<pre><code>$ wd setup -t demo
Initialized empty Git repository in /home/deploy_user/domains/useful_site.com/.git/
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
fetch-pack from 'git@github.com:rud/whiskey_disk-demo.git' failed.
error: pathspec 'origin/master' did not match any file(s) known to git.
</code></pre>
</blockquote>
<h3>ssh-agent to the rescue</h3>
<p>The root cause for this difference is Github knows my public key and has access to the corresponding private key, but this key is not available to my server, so it cannot authenticate against Github. The solution is fortunately simple. Do this on your local machine:</p>
<blockquote>
<pre><code>$ ssh-add
</code></pre>
</blockquote>
<p>This prompts you for the password for your private key, then keeps the private key unlocked in memory for automated access. <strong>You need to do this after each time you restart</strong> before you can do new deployments, as the unlocked key is only stored in memory. We also need to enable ssh-agent support for the connection to the server &#8211; as ssh-agent gives a server the possibility to use our private key without further prompting, you need to trust the administrator of servers you deploy to. With that caveat out of the way, open your <code>~/.ssh/config</code> file, and add a config block like this:</p>
<blockquote>
<pre><code>Host example.com
    ForwardAgent yes  # This enables ssh-agent functionality, making whiskey_disk happy
</code></pre>
</blockquote>
<p>Adjust the hostname to taste, obviously. You can also add port-number here, if your admin moved ssh access from the default port. While you have that file open, also check out these extremely handy <a href="http://blogs.perl.org/users/smylers/2011/08/ssh-productivity-tips.html">ssh productivity tips</a> for a lot of extra ssh goodness.</p>
<p>Close the previous connection to your server, open a new one (so ssh-agent can do its magic), then re-run the test:</p>
<blockquote>
<pre><code>$ ssh -T git@github.com
Hi rud! You've successfully authenticated, but GitHub does not provide shell access.
</code></pre>
</blockquote>
<p>We have ssh-win!</p>
<h2>Deploying</h2>
<p>Time to re-try the deployment <code>setup</code> from the local machine:</p>
<blockquote>
<pre><code>$ wd setup -t demo
Results:
deploy_user@example.com =&gt; succeeded.
Total: 1 deployment, 1 success, 0 failures.
</code></pre>
</blockquote>
<p>This means the repository was successfully cloned into place. We only have to do this once, from now on deployments are just a matter of:</p>
<blockquote>
<pre><code>$ wd deploy -t demo
Results:
deploy_user@example.com =&gt; succeeded.
Total: 1 deployment, 1 success, 0 failures.
</code></pre>
</blockquote>
<p>I&#8217;m seeing a total time taken for a deployment in the area of 2-5 seconds. Remember to push to Github before running your deployment, as it is from Github your server is pulling versions.</p>
<p>This method for deployment is extremely awesome, and the amount of awesome grows with the size of your deployments, as server-server connections are most likely a lot faster than your own internet connection.</p>
<h2>Next steps</h2>
<p>There is a lot more to whiskey_disk that I&#8217;ve shown here. In particular I&#8217;d like to highlight the &#8220;Configuration Repository&#8221; section of the <a href="https://github.com/flogic/whiskey_disk#readme">official whiskey_disk readme</a>. Editing per-application configuration files on individual servers is effectively a thing of the past.</p>
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/enter-git-flow/' title='Modernize Your Git Workflow'>Modernize Your Git Workflow</a></li>
<li><a href='http://object.io/site/2011/sneakernet-git/' title='The sneakernet in git'>The sneakernet in git</a></li>
<li><a href='http://object.io/site/2011/meet-chop/' title='chop – efficiently dispense with current git branch'>chop – efficiently dispense with current git branch</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/UFe21zbDESM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/whiskey_disk-private-github/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/whiskey_disk-private-github/</feedburner:origLink></item>
		<item>
		<title>Modernize Your Git Workflow</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/Dy1qVYKkFRk/</link>
		<comments>http://object.io/site/2011/enter-git-flow/#comments</comments>
		<pubDate>Mon, 09 May 2011 10:00:39 +0000</pubDate>
		<dc:creator>Laust Rud Jacobsen</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Workflow]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[git flow]]></category>
		<category><![CDATA[homebrew]]></category>

		<guid isPermaLink="false">http://object.io/site/?p=382</guid>
		<description><![CDATA[Years ago I read Streamed Lines: Branching Patterns for Parallel Software Development, and many of the thoughts have stayed me. Think of it as a catalogue of Design Patterns for version control workflows. There are so many ways to efficiently (&#8230;)</p><p><a href="http://object.io/site/2011/enter-git-flow/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Years ago I read <a href="http://www.cmcrossroads.com/bradapp/acme/branching/">Streamed Lines: Branching Patterns for Parallel Software Development</a>, and many of the thoughts have stayed me. Think of it as a catalogue of <a href="http://en.wikipedia.org/wiki/Design_pattern_(computer_science)">Design Patterns</a> for version control workflows. There are so many ways to efficiently use branches to both collaborate and isolate work. Lively discussions can be had on how to best organize a repository, and having a great overview of the options makes for more informed discussions.</p>
<p>I have previously described how I&#8217;ve been using small <a title="Simple git workflow with hack and ship" href="http://object.io/site/2010/hack-and-ship/">hack &amp;&amp; ship</a> commands to simplify and streamline my personal git workflow. Recently I&#8217;ve switched to using the <a href="http://nvie.com/posts/a-successful-git-branching-model/">Git Flow</a> setup as my branching and release workflow.</p>
<h3>Setting up git-flow</h3>
<p>Installing the <a href="https://github.com/nvie/gitflow">git-flow</a> toolset on OS X is trivial using the <a href="http://mxcl.github.com/homebrew/">homebrew</a> installer:</p>
<blockquote>
<pre>brew install git-flow</pre>
</blockquote>
<p>The <a href="https://github.com/nvie/gitflow">git-flow project</a> also has instructions for installation on Linux and Windows.</p>
<p>Installing git-flow adds a few helpful commands to the git environment for creating and managing branches for features and releases. A fresh git repository is born with a <code>master</code> branch. In the default git-flow setup, this is where the current <strong>production</strong> release lives. Furthermore, a branch called <code>develop</code> is created, this is where development takes place. Note that git-flow is just a series of shortcuts to having a development branch and a production branch with sensible ways of shuttling changes back and forth. After installing the git-flow package, configure your local repository for git-flow use with:</p>
<blockquote>
<pre>git flow init</pre>
</blockquote>
<p>You can most likely accept the defaults by pressing enter at each question &#8211; this also makes it easier for others to initialize git-flow in their working copy, as all are using the same defaults. The only change from running the <code>init</code> command is two <code>[gitflow]</code> sections in your <code>.git/config</code> file looking like this:</p>
<blockquote>
<pre>
[gitflow "branch"]
	master = master
	develop = develop
[gitflow "prefix"]
	feature = feature/
	release = release/
	hotfix = hotfix/
	support = support/
	versiontag =
</pre>
</blockquote>
<p>It&#8217;s no more magic than that. Consult the built-in help with: </p>
<blockquote>
<pre>git flow</pre>
</blockquote>
<p>If you&#8217;ve got the <code>bash-completion</code> package installed, you can use tab-completion for git-flow commands and arguments. Highly recommended.</p>
<h3>Working on a feature</h3>
<p>Start work on a feature &#8211; say feature 77 from your issue-tracker:</p>
<blockquote>
<pre>git flow feature start 77-speedup-yak-shaving</pre>
</blockquote>
<p>This creates a new regular local git branch called <code>feature/77-speedup-yak-shaving</code> based on the current <code>develop</code> and places you on it.  Want to share your work in progress with others? Use:</p>
<blockquote>
<pre>git flow feature publish 77-speedup-yak-shaving</pre>
</blockquote>
<p>This pushes the branch, and sets up your local branch to track the remote branch in one easy step. The regular <code>git push</code> and <code>git pull --rebase</code> work as you would expect here. <span class="highlighted">There is nothing special about branches created by git-flow, they are just conveniently named and managed.</span></p>
<p>All done with a feature? Rebase your feature on the current <code>develop</code> branch, then merge it in:</p>
<blockquote>
<pre>git flow feature rebase
git flow feature finish 77-speedup-yak-shaving
</pre>
</blockquote>
<p>With these two steps, you end up on <code>develop</code> with your feature merged in. Run your test-suite, and push to a central repository as appropriate.</p>
<h3>Releasing to production version and hotfixes</h3>
<p>Production releases are handled quite nicely in git-flow:</p>
<blockquote>
<pre>git flow release start 2011_year_of_the_yak</pre>
</blockquote>
<p>This creates a new branch called <code>release/2011_year_of_the_yak</code>, based on the current <code>develop</code> branch. Here you can fix any HISTORY or VERSION file, commit, and the finish up the release with:</p>
<blockquote>
<pre>git flow release finish 2011_year_of_the_yak</pre>
</blockquote>
<p>By finishing the release, you now get a tag called <code>2011_year_of_the_yak</code>, and the temporary release-branch is removed. You end up back at the <code>master</code> branch.</p>
<p>A hotfix is simply a feature branch which is based on the latest production release, and which is automatically merged to both <code>develop</code> and <code>master</code>. Extremely handy. </p>
<h3>Rebase considered harmful?</h3>
<p>Some developers prefer to only ever merge, but I&#8217;m a big fan of <a href="http://darwinweb.net/articles/the-case-for-git-rebase">rebasing local work before publishing</a>. I&#8217;ll leave you with this:</p>
<blockquote><p>If you treat rebasing as a way to clean up and work with commits before you push them, and if you only rebase commits that have never been available publicly, then you’ll be fine. If you rebase commits that have already been pushed publicly, and people may have based work on those commits, then you may be in for some frustrating trouble.</p></blockquote>
<p style="text-align: right;">From <a href="http://progit.org/book/ch3-6.html">Pro Git</a>, chapter 3</p>
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/whiskey_disk-private-github/' title='Deploy a private Github repository with whiskey_disk'>Deploy a private Github repository with whiskey_disk</a></li>
<li><a href='http://object.io/site/2011/sneakernet-git/' title='The sneakernet in git'>The sneakernet in git</a></li>
<li><a href='http://object.io/site/2011/meet-chop/' title='chop – efficiently dispense with current git branch'>chop – efficiently dispense with current git branch</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/Dy1qVYKkFRk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/enter-git-flow/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/enter-git-flow/</feedburner:origLink></item>
		<item>
		<title>The sneakernet in git</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/jVSOlds3rG8/</link>
		<comments>http://object.io/site/2011/sneakernet-git/#comments</comments>
		<pubDate>Sun, 27 Feb 2011 18:51:21 +0000</pubDate>
		<dc:creator>Laust Rud Jacobsen</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Workflow]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://object.io/site/?p=334</guid>
		<description><![CDATA[There are many ways to backup a git repository and shuttle sets of changes around. If you just want an offline copy for safe-keeping, this method is very simple and convenient: $ git bundle create blog-dump.bundle master This creates a (&#8230;)</p><p><a href="http://object.io/site/2011/sneakernet-git/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>There are many ways to backup a git repository and shuttle sets of changes around. If you just want an offline copy for safe-keeping, this method is very simple and convenient:</p>
<blockquote><p><code>$ git bundle create blog-dump.bundle master</code></p></blockquote>
<p>This creates a file <code>blog-dump.bundle</code> with the full history for <code>master</code>, including all parent commits. You now have a single file, which can effectively be mailed, downloaded via SCP or FTP, or simply moved to <a href="http://db.tt/cHU9N1d">Dropbox</a> (affiliate link) for safe keeping, or otherwise shared with others. Single files are easy to archive and backup.</p>
<h3>Thawing a bundle</h3>
<p>When you want to restore from such a bundle backup, you simply clone from it. The steps include creating a new repository, and then pulling from the bundle, like you would a remote repository:</p>
<blockquote><p><code>$ git init<br />
$ git pull blog-dump.bundle master</code></p></blockquote>
<p>Your repository now holds all commits that were stored in the bundle. For more usage-scenarios see the official <a href="http://www.kernel.org/pub/software/scm/git/docs/git-bundle.html">git bundle help</a> or just type:</p>
<blockquote><p><code>$ git bundle --help</code></p></blockquote>
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/meet-chop/' title='chop – efficiently dispense with current git branch'>chop – efficiently dispense with current git branch</a></li>
<li><a href='http://object.io/site/2011/local-review-with-git/' title='Easy local code-review with git'>Easy local code-review with git</a></li>
<li><a href='http://object.io/site/2010/hack-and-ship/' title='Simple git workflow with hack and ship'>Simple git workflow with hack and ship</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/jVSOlds3rG8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/sneakernet-git/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/sneakernet-git/</feedburner:origLink></item>
		<item>
		<title>Idiomatic shared state in RSpec</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/qrvWbncSJNk/</link>
		<comments>http://object.io/site/2011/idiomatic-rspec-state/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 19:01:47 +0000</pubDate>
		<dc:creator>Laust Rud Jacobsen</dc:creator>
				<category><![CDATA[Behavior Driven Development]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[rspec]]></category>

		<guid isPermaLink="false">http://object.io/site/?p=251</guid>
		<description><![CDATA[RSpec is an extremely convenient tool for structuring and writing specs, and I use it on all my ruby-projects. One set of built-in helpers I&#8217;d like to cheer on a bit are let and let!, as they can greatly simplify (&#8230;)</p><p><a href="http://object.io/site/2011/idiomatic-rspec-state/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>RSpec is an extremely convenient tool for structuring and writing specs, and I use it on all my ruby-projects. </p>
<p>One set of built-in helpers I&#8217;d like to cheer on a bit are <code>let</code> and <code>let!</code>, as they can greatly simplify setting up state for multiple examples. They exist to provide a simple and convenient way to create and share state between examples. When not using these methods, specs with a bit of shared state typically look like this:</p>
<div id="gist-832250" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="n">context</span> <span class="s2">&quot;with a bit of state&quot;</span> <span class="k">do</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="n">before</span> <span class="ss">:each</span> <span class="k">do</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@user</span> <span class="o">=</span> <span class="no">User</span><span class="o">.</span><span class="n">create!</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="c1"># The following specs assume the user has already been created</span></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="n">it</span> <span class="s2">&quot;should be the latest user&quot;</span> <span class="k">do</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">User</span><span class="o">.</span><span class="n">last</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="vi">@user</span></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'>&nbsp;&nbsp;<span class="c1"># .. more examples reusing the @user</span></div><div class='line' id='LC12'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/832250/860f18cdf6bdcfc57aa23d1246bbf21c9d0f1e8f/old_style.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/832250#file_old_style.rb" style="float:right;margin-right:10px;color:#666">old_style.rb</a>
            <a href="https://gist.github.com/832250">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>This is easy to get started with, and when there are only a few variables in the <code>before</code> block, things are fine. But if you have a typo in an example where you intended to use the <code>@user</code> instance variable in an example, but you accidentally typed <code>@usr</code>, you just get a <code>nil</code> value, instead of a helpful error message regarding an unknown indentifier. This minor problem can be avoided by using <code>let</code> instead, as you get an unknown indentifier error instead of a <code>nil</code> value. Another issue is that all variables in the <code>before</code> block are evaluated, whether or not they are actually used in the examples.</p>
<p>The excellent <a href="http://relishapp.com/rspec/rspec-core/v/2-5/dir/helper-methods/let-and-let">official RSpec 2</a> documentation has the following to say on <code>let</code>, before showing clear examples of use:</p>
<blockquote>
<h3><code>let</code> and <code>let!</code></h3>
<p>Use <code>let</code> to define a memoized helper method. The value will be cached across multiple calls in the same example but not across examples.</p>
<p>Note that <code>let</code> is lazy-evaluated: it is not evaluated until the first time the method it defines is invoked. You can use <code>let!</code> to force the method&#8217;s invocation before each example.
</p></blockquote>
<p>The fact that results are both memoized and lazy-evaluated means no extra effort is expended if the value is not used in a given example. Performance win!</p>
<h3>Use <code>let</code> or <code>let!</code>?</h3>
<p>Please use the correct helper method &#8211; I&#8217;ve seen examples like this:<br />
<div id="gist-832250" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="n">context</span> <span class="s2">&quot;with a bit of state&quot;</span> <span class="k">do</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="n">let</span><span class="p">(</span><span class="ss">:user</span><span class="p">)</span> <span class="p">{</span> <span class="no">User</span><span class="o">.</span><span class="n">create!</span> <span class="p">}</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="n">before</span> <span class="ss">:each</span> <span class="k">do</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">user</span></div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="c1"># The following specs assume the user has already been created</span></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="n">it</span> <span class="s2">&quot;should be the latest user&quot;</span> <span class="k">do</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">User</span><span class="o">.</span><span class="n">last</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="n">user</span></div><div class='line' id='LC11'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'>&nbsp;&nbsp;<span class="c1"># .. more examples reusing the user</span></div><div class='line' id='LC14'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/832250/8ae6a2bcba06c29b889b6bb945c8f279b7d0a493/verbose_spec.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/832250#file_verbose_spec.rb" style="float:right;margin-right:10px;color:#666">verbose_spec.rb</a>
            <a href="https://gist.github.com/832250">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>The exact same thing can be expressed directly and become more readable, just by adding a <code>!</code>:<br />
<div id="gist-832250" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="n">context</span> <span class="s2">&quot;with a bit of state&quot;</span> <span class="k">do</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="n">let!</span><span class="p">(</span><span class="ss">:user</span><span class="p">)</span> <span class="p">{</span> <span class="no">User</span><span class="o">.</span><span class="n">create!</span> <span class="p">}</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="n">it</span> <span class="s2">&quot;should be the latest user&quot;</span> <span class="k">do</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">User</span><span class="o">.</span><span class="n">last</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="n">user</span></div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="c1"># .. more examples reusing the user</span></div><div class='line' id='LC9'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/832250/de1060ead6a5f4de4dd79a4b9bbc8558936ee821/concise_spec.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/832250#file_concise_spec.rb" style="float:right;margin-right:10px;color:#666">concise_spec.rb</a>
            <a href="https://gist.github.com/832250">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>The <code>let</code> and <code>let!</code> helpers are available in from versions <code>rspec 1.3.1</code>, and <code>rspec-core 2.0.0</code> onwards. In a nutshell, this means they are available for use in Rails 2 and Rails 3 projects. Take them for a spin if you haven&#8217;t already, and tell me how it goes.</p>
<p>I recommend having a quick look at the <a href="http://relishapp.com/rspec/rspec-core/v/2-5">RSpec 2.5</a> documentation now, as you&#8217;ll probably discover one or more neat new solutions to recurring issues when writing specs.<br />
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/getting-to-know-ruby-debugger/' title='Getting to know Ruby debugger'>Getting to know Ruby debugger</a></li>
<li><a href='http://object.io/site/2011/ruby-stacktrace-at-will/' title='Identify what your Ruby process is doing'>Identify what your Ruby process is doing</a></li>
<li><a href='http://object.io/site/2011/rails-data-import/' title='Quick data import and linking in Rails'>Quick data import and linking in Rails</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/qrvWbncSJNk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/idiomatic-rspec-state/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/idiomatic-rspec-state/</feedburner:origLink></item>
		<item>
		<title>Identify what your Ruby process is doing</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/v6zywOGGh9g/</link>
		<comments>http://object.io/site/2011/ruby-stacktrace-at-will/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 07:43:19 +0000</pubDate>
		<dc:creator>Laust Rud Jacobsen</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[optimize]]></category>
		<category><![CDATA[stacktrace]]></category>

		<guid isPermaLink="false">http://object.io/site/?p=219</guid>
		<description><![CDATA[Quick diagnostics of production issues become a lot easier with a direct way to inspect the running process. Ever wondered exactly what the program is doing right now, without adding a lot of slow logging? With this gem in place, (&#8230;)</p><p><a href="http://object.io/site/2011/ruby-stacktrace-at-will/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Quick diagnostics of production issues become a lot easier with a direct way to inspect the running process. Ever wondered exactly what the program is doing right now, without adding a lot of slow logging? With this gem in place, you can get full stacktraces for all threads in the system, while the process keeps running, in production. This means you can do this a few of these dumps, and then look for recurring patterns to identify the currently largest bottlenecks. It&#8217;s much easier to fix a problem when you know exactly where to look. </p>
<p><strong>Soon you&#8217;ll be back on the road to awesome.</strong></p>
<p>Simply install and load the <code><a href="https://github.com/ph7/xray">xray</a></code> gem, then add this to your Gemfile (or similar):</p>
<blockquote><p><code>gem "xray", :require => "xray/thread_dump_signal_handler"</code></p></blockquote>
<p>Next, you need to start the ruby-process, and find the PID (process identifier):</p>
<blockquote><p><code>$ ps ax | grep ruby</code></p></blockquote>
<p>You can now invoke:</p>
<blockquote><p><code>$ kill -3 1234</code></p></blockquote>
<p>where <code>1234</code> is the PID of the ruby process. <strong>Note this does not terminate the process</strong>. Instead, you immediately see a full stacktrace for <strong>current thread</strong> written to standard out of the process. If you&#8217;re using the <a href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a> runtime, you will get a stacktrace for <strong>all threads</strong>, a big win. If you are running the process interactively, you see the output directly in the terminal. For service-processes in production, you will need to check the appropriate logfile.</p>
<h2>Thread dumps for Phusion Passenger with RVM</h2>
<p>You can see all running <a href="http://www.modrails.com/">Phusion Passenger</a> instances, including their individual PIDs with this:</p>
<blockquote><p><code>$ rvmsudo passenger-status</code></p></blockquote>
<p>Then move in for the <code>kill -3</code>, and have a look at standard out for Passenger. By default on OS X 10.6, this ends up in the file <code>/private/var/log/apache2/error_log</code>, so have a look there. Notice the use of <code>rvmsudo</code> instead of regular <code>sudo</code> &#8211; this is because I&#8217;m using <a href="http://rvm.beginrescueend.com/">RVM</a> to manage my ruby-versions. </p>
<p>I hope you found this useful &#8211; what is your stacktrace-aided war-story?<br />
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/idiomatic-rspec-state/' title='Idiomatic shared state in RSpec'>Idiomatic shared state in RSpec</a></li>
<li><a href='http://object.io/site/2011/rails-data-import/' title='Quick data import and linking in Rails'>Quick data import and linking in Rails</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/v6zywOGGh9g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/ruby-stacktrace-at-will/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/ruby-stacktrace-at-will/</feedburner:origLink></item>
		<item>
		<title>Ack! Effortlessly search your codebase</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/jvr6vOo2uPU/</link>
		<comments>http://object.io/site/2011/ack-code-search/#comments</comments>
		<pubDate>Mon, 24 Jan 2011 21:13:47 +0000</pubDate>
		<dc:creator>Laust Rud Jacobsen</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Workflow]]></category>
		<category><![CDATA[ack]]></category>
		<category><![CDATA[data]]></category>

		<guid isPermaLink="false">http://object.io/site/?p=193</guid>
		<description><![CDATA[My favorite commandline tool for efficiently searching a codebase is Ack. It shows file:line and highlights the matches in the output. When refactoring a solution it is a trusty companion to quickly find all uses of a method, for instance. (&#8230;)</p><p><a href="http://object.io/site/2011/ack-code-search/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>My favorite commandline tool for efficiently searching a codebase is <a href="http://betterthangrep.com/">Ack</a>. It shows file:line and highlights the matches in the output. When refactoring a solution it is a trusty companion to quickly find all uses of a method, for instance.</p>
<p style="text-align: center;"><a href="http://object.io/site/wp-content/uploads/2011/01/ack-quick-demo.png"><img class="size-full wp-image-199 aligncenter" title="ack quick demo" src="http://object.io/site/wp-content/uploads/2011/01/ack-quick-demo.png" alt="" width="619" height="140" /></a></p>
<p>It is easy to install with DarwinPorts:</p>
<blockquote><p><code>sudo port install p5-app-ack</code></p></blockquote>
<p>This puts the <code>ack</code> command in your <code>PATH</code> and you&#8217;re ready to go.</p>
<h3>Basic usage of Ack</h3>
<p>A recurring task is to find all uses of a method or class in a project. As this is simply a substring search, you invoke Ack with:</p>
<blockquote><p><code>ack inconvenience_late_payers</code></p></blockquote>
<p>and ack quickly starts outputting all the places where this is used. If you add a <code>-i</code>, the search becomes case-insensitive. Use <code>ack --help</code> to see all the many available options.</p>
<h3>A bit of configuration goes a long way</h3>
<p>Ack is fast because it skips uninteresting files. It is meant for searching for text, and skips version control folders, logfiles, images, and a lot of other <strong>stuff</strong> you are not interested in when searching through your source-code. However, the backside is you need to configure things once to have support for all your various kinds of source-code.</p>
<p>Adding this small bit of config means <code>.haml</code>, <code>.sass</code>, and Cucumber <code>.feature</code> files are also included when searching.</p>
<p><code>~/.arkrc:</code></p>
<blockquote><p><code>--type-set=haml=.haml<br />
--type-set=sass=.sass<br />
--type-set=cucumber=.feature<br />
</code></p></blockquote>
<p>With this in place, you are ready to rock HAML/SSS + Cucumber projects.</p>
<p>Know any extra must-have options or shortcuts I have left out?</p>
<p><strong>Update:</strong> added link to official <a href="http://betterthangrep.com/">Ack homepage</a>.<br />
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/meet-chop/' title='chop – efficiently dispense with current git branch'>chop – efficiently dispense with current git branch</a></li>
<li><a href='http://object.io/site/2011/local-review-with-git/' title='Easy local code-review with git'>Easy local code-review with git</a></li>
<li><a href='http://object.io/site/2010/hack-and-ship/' title='Simple git workflow with hack and ship'>Simple git workflow with hack and ship</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/jvr6vOo2uPU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/ack-code-search/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/ack-code-search/</feedburner:origLink></item>
		<item>
		<title>chop – efficiently dispense with current git branch</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/pG2HtTY0BOA/</link>
		<comments>http://object.io/site/2011/meet-chop/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 10:55:16 +0000</pubDate>
		<dc:creator>Laust Rud Jacobsen</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Workflow]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://object.io.s115060.gridserver.com/site/?p=28</guid>
		<description><![CDATA[My git workflow includes the commands for easy tracking of a shared master branch, and conveniently delivering commits. Feature branches are cheap and fast in git, and I am often spawning new branches to try stuff out or work on (&#8230;)</p><p><a href="http://object.io/site/2011/meet-chop/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>My git workflow includes the <a href="http://object.io/site/2010/hack-and-ship/">hack and ship</a> commands for easy tracking of a shared <code>master</code> branch, and conveniently delivering commits. Feature branches are cheap and fast in git, and I am often spawning new branches to try stuff out or work on unrelated things.</p>
<p>Now, meet <code>chop</code> &#8211; for chopping down the current working branch after it has been shipped and is no longer needed. The script changes the current branch to <code>master</code>, and then deletes the branch you was previously on. If you give a branch-name as an argument that will be the new current branch. </p>
<div id="gist-406262" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c">#!/bin/sh -x</span></div><div class='line' id='LC2'><span class="nb">set</span> -o errexit</div><div class='line' id='LC3'><span class="nv">CURRENT_BRANCH</span><span class="o">=</span><span class="k">$(</span>git branch | grep <span class="s1">&#39;\*&#39;</span><span class="k">)</span></div><div class='line' id='LC4'>git checkout <span class="k">${</span><span class="nv">1</span><span class="k">:-</span><span class="s2">&quot;master&quot;</span><span class="k">}</span> <span class="o">||</span> <span class="nb">exit </span>1</div><div class='line' id='LC5'>git branch -d <span class="k">${</span><span class="nv">CURRENT_BRANCH</span><span class="p">:</span><span class="nv">2</span><span class="k">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/406262/67d2e83a145c6ab538e1c83aef13d30c63e0bb12/chop.sh" style="float:right;">view raw</a>
            <a href="https://gist.github.com/406262#file_chop.sh" style="float:right;margin-right:10px;color:#666">chop.sh</a>
            <a href="https://gist.github.com/406262">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>I use this small script is multiple times every day, and I really like the name of it. There is not a whole lot of functionlity, but as this is an often repeated action, it makes sense to automate it.</p>
<p>Enjoy!<br />
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/local-review-with-git/' title='Easy local code-review with git'>Easy local code-review with git</a></li>
<li><a href='http://object.io/site/2010/hack-and-ship/' title='Simple git workflow with hack and ship'>Simple git workflow with hack and ship</a></li>
<li><a href='http://object.io/site/2011/ack-code-search/' title='Ack! Effortlessly search your codebase'>Ack! Effortlessly search your codebase</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/pG2HtTY0BOA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/meet-chop/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/meet-chop/</feedburner:origLink></item>
		<item>
		<title>Quick data import and linking in Rails</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/uHt8fvTRvCg/</link>
		<comments>http://object.io/site/2011/rails-data-import/#comments</comments>
		<pubDate>Mon, 17 Jan 2011 10:35:34 +0000</pubDate>
		<dc:creator>Laust Rud Jacobsen</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[exceptions]]></category>
		<category><![CDATA[import]]></category>

		<guid isPermaLink="false">http://object.io/site/?p=116</guid>
		<description><![CDATA[Some web-applications have to ingest an enormous amount of new data on a regular basis. Import scripts easily become an ever-growing procedural mess, annoying to maintain. In this post I show a bit of code which can be used to (&#8230;)</p><p><a href="http://object.io/site/2011/rails-data-import/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Some web-applications have to ingest an enormous amount of new data on a regular basis. Import scripts easily become an ever-growing procedural mess, annoying to maintain. In this post I show a bit of code which can be used to simplify and unify such import scripts.</p>
<p>Assume you have a pipeline of post-import steps to run. This can be organized in numerous ways. Simplest is to just have a bunch of methods called one after the other once you have the data loaded:</p>
<ul>
<li><code>link_frobnitz</code></li>
<li><code>spin_really_fast_around_z_axis</code></li>
<li><code>reticulate_splines</code></li>
<li><code>deploy_hamsters</code></li>
</ul>
<p>Now, assume once in a while one of the steps fail for an unexpected reason. You know, it&#8217;s rare data from external sources is as clean as we&#8217;d like. So you need to fix a few things and retry the import. However, as datasizes grow and with that the running time of the import, it can be a huge waste redoing all the work because of a misplaced comma made the final <code>deploy_hamsters</code> step fail.</p>
<p>Exceptions are the obvious way to report fatal data-errors, and implicit or explicit transactions to ensure consistency of the import. But how can this easily be combined for a resume-friendly import mechanism?</p>
<p>Enter the bulk importer step runner with trivial progress reporting:<br />
<div id="gist-782643" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">def</span> <span class="nf">import_updaters</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="n">all_steps</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">step_name</span><span class="o">|</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">run_import_step</span><span class="p">(</span><span class="n">step_name</span><span class="p">)</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC5'><span class="k">end</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="kp">private</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'><span class="k">def</span> <span class="nf">run_import_step</span> <span class="n">step_name</span></div><div class='line' id='LC10'>&nbsp;&nbsp;<span class="nb">puts</span> <span class="s2">&quot;Running </span><span class="si">#{</span><span class="n">step_name</span><span class="si">}</span><span class="s2">&quot;</span></div><div class='line' id='LC11'><br/></div><div class='line' id='LC12'>&nbsp;&nbsp;<span class="no">ImportModel</span><span class="o">.</span><span class="n">transaction</span> <span class="k">do</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">self</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">step_name</span><span class="p">)</span></div><div class='line' id='LC14'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'><span class="k">rescue</span> <span class="o">=&gt;</span> <span class="n">e</span></div><div class='line' id='LC17'>&nbsp;&nbsp;<span class="no">STDERR</span><span class="o">.</span><span class="n">print</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">Import error:  </span><span class="si">#{</span><span class="n">e</span><span class="o">.</span><span class="n">inspect</span><span class="si">}</span><span class="se">\n</span><span class="si">#{</span><span class="n">e</span><span class="o">.</span><span class="n">backtrace</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span></div><div class='line' id='LC18'>&nbsp;&nbsp;<span class="no">STDERR</span><span class="o">.</span><span class="n">print</span> <span class="s2">&quot;Please resume at step </span><span class="si">#{</span><span class="n">step_name</span><span class="si">}</span><span class="s2">&quot;</span></div><div class='line' id='LC19'>&nbsp;&nbsp;<span class="nb">exit</span> <span class="mi">1</span></div><div class='line' id='LC20'><span class="k">end</span></div><div class='line' id='LC21'><br/></div><div class='line' id='LC22'><span class="kp">protected</span></div><div class='line' id='LC23'><br/></div><div class='line' id='LC24'><span class="k">def</span> <span class="nf">all_steps</span></div><div class='line' id='LC25'>&nbsp;&nbsp;<span class="o">[</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="ss">:link_frobnitz</span><span class="p">,</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="ss">:spin_really_fast_around_z_axis</span><span class="p">,</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="ss">:reticulate_splines</span><span class="p">,</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="ss">:deploy_hamsters</span></div><div class='line' id='LC30'>&nbsp;&nbsp;<span class="o">]</span></div><div class='line' id='LC31'><span class="k">end</span></div><div class='line' id='LC32'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/782643/5b41fe9504357ddb64e3e6137a33b676bf0c49a7/importer.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/782643#file_importer.rb" style="float:right;margin-right:10px;color:#666">importer.rb</a>
            <a href="https://gist.github.com/782643">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>Notice you obviously have to change the model-name (<code>ImportModel</code> above) and provide the actual implementation for these individual steps. <code>all_steps</code> returns the list of methods to run, <code>run_import_step</code> runs a single step with error-handling, and <code>import_updaters</code> runs all the relevant updaters.</p>
<h3>Easy performance statistics</h3>
<p>As a bit of bonus-functionality, the following can be used for reporting import progress with timing-statistics after each step completes:<br />
<div id="gist-782643" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">def</span> <span class="nf">report_progress</span> <span class="n">message</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="no">STDERR</span><span class="o">.</span><span class="n">print</span> <span class="n">message</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="k">if</span> <span class="nb">block_given?</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">time</span> <span class="o">=</span> <span class="no">Benchmark</span><span class="o">.</span><span class="n">measure</span> <span class="p">{</span> <span class="k">yield</span> <span class="p">}</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">formatted_time</span> <span class="o">=</span> <span class="s2">&quot;%.2fs&quot;</span> <span class="o">%</span> <span class="n">time</span><span class="o">.</span><span class="n">real</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot; - </span><span class="si">#{</span><span class="n">formatted_time</span><span class="si">}</span><span class="s2">&quot;</span></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="k">else</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span></div><div class='line' id='LC11'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC12'><span class="k">end</span></div><div class='line' id='LC13'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/782643/5d76f60644b4645a82ba05882ee7aa16128e8f23/progress.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/782643#file_progress.rb" style="float:right;margin-right:10px;color:#666">progress.rb</a>
            <a href="https://gist.github.com/782643">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>Usage is simple &#8211; just call <code>report_progress</code> with a comment to print and a block of code, like this:</p>
<div id="gist-782643" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">def</span> <span class="nf">run_import_step</span> <span class="n">step_name</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="n">report_progress</span> <span class="s2">&quot;Running </span><span class="si">#{</span><span class="n">step_name</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">do</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">ImportModel</span><span class="o">.</span><span class="n">transaction</span> <span class="k">do</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">self</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">step_name</span><span class="p">)</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="sr">//</span><span class="o">.</span><span class="n">.</span><span class="o">.</span></div><div class='line' id='LC8'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/782643/938027586aba97fac79bd6e519b794ad56ff6320/import-with-progress.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/782643#file_import_with_progress.rb" style="float:right;margin-right:10px;color:#666">import-with-progress.rb</a>
            <a href="https://gist.github.com/782643">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>What do you use to make data-imports easier to manage?</p>
<p><!--62bd9683f49e4d8cbcfa1069a71c8658--><br />
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/idiomatic-rspec-state/' title='Idiomatic shared state in RSpec'>Idiomatic shared state in RSpec</a></li>
<li><a href='http://object.io/site/2011/ruby-stacktrace-at-will/' title='Identify what your Ruby process is doing'>Identify what your Ruby process is doing</a></li>
<li><a href='http://object.io/site/2011/ack-code-search/' title='Ack! Effortlessly search your codebase'>Ack! Effortlessly search your codebase</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/uHt8fvTRvCg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/rails-data-import/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/rails-data-import/</feedburner:origLink></item>
		<item>
		<title>Easy local code-review with git</title>
		<link>http://feedproxy.google.com/~r/objectio/~3/ehIm4WpoY-U/</link>
		<comments>http://object.io/site/2011/local-review-with-git/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 09:45:51 +0000</pubDate>
		<dc:creator>Laust Rud Jacobsen</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Workflow]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[review]]></category>

		<guid isPermaLink="false">http://object.io.s115060.gridserver.com/site/?p=54</guid>
		<description><![CDATA[When multiple developers contribute to a project, keeping on top of the constant flow changes can be a challenge. The following is a simple local workflow to stay on top of a tracked git repository where multiple developers share code.]]></description>
			<content:encoded><![CDATA[<p>When multiple developers contribute to a project, keeping on top of the constant flow changes can be a challenge. The following simple review workflow assumes a shared git-repository with a fairly <a href="http://object.io/site/2010/hack-and-ship/">linear commit-history</a>, that is, not having too many merge-commits. </p>
<p>So, assuming a fairly linear history of commits from multiple developers, how do you easily keep track of what you have already read through and reviewed? Easy, use a local branch as a bookmark. This tiny script makes it trivial to add or update such a branch:</p>
<div id="gist-175421" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c">#!/bin/sh</span></div><div class='line' id='LC2'><span class="nv">NEW_BASE</span><span class="o">=</span><span class="k">${</span><span class="nv">1</span><span class="p">?</span><span class="s2">&quot;Usage: $0 &lt;treeish&gt;&quot;</span><span class="k">}</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'>git branch --force reviewed <span class="nv">$NEW_BASE</span> <span class="o">||</span> <span class="nb">exit </span>1</div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'><span class="nb">echo </span>Marked as reviewed: <span class="sb">`</span>git rev-parse --short reviewed<span class="sb">`</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/175421/42ac5f7c12d1aec95884430b3afa0a61b7d13f26/reviewed.sh" style="float:right;">view raw</a>
            <a href="https://gist.github.com/175421#file_reviewed.sh" style="float:right;margin-right:10px;color:#666">reviewed.sh</a>
            <a href="https://gist.github.com/175421">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Save this as a new file called <code>reviewed.sh</code> in your <code>PATH</code>.</p>
<p>Usage is extremely simple:</p>
<blockquote><p><code>reviewed.sh 369b5cc<br />
reviewed.sh master<br />
reviewed.sh v1.0.7<br />
reviewed.sh HEAD~5<br />
</code></p></blockquote>
<p>Running one of these commands will mark the given <a href="http://book.git-scm.com/4_git_treeishes.html">treeish</a> as reviewed, and when you look at your commit-history in a visual tool such as <code>git gui</code>, or <code><a href="http://gitx.frim.nl/">gitx</a></code>, the <code>reviewed</code> branch visually indicates how far you have gotten. Note how both commit-IDs, branch names, tags, and relative commit-IDs can be used as argument.</p>
<p>You can also utilize this review bookmark from the commandline. The following shows you all commits added to master since your last review:</p>
<blockquote><p><code>git log reviewed..master --reverse</code></p></blockquote>
<p>You can add a <code>--patch</code> to that command to see the full diff for each change. Adding <code>--format=oneline</code> just shows you the commit-IDs and first line of the commit-message.</p>
<p>Once you&#8217;ve read all the latest commits on master, simply do a</p>
<blockquote><p><code>reviewed.sh master</code></p></blockquote>
<p>and you&#8217;re done.</p>
<h3>Why not use a tag?</h3>
<p>I find it convenient to be able to do a push of all tags to the central repository with</p>
<blockquote><p><code>git push --tags</code></p></blockquote>
<p>and this would share such a private review-tag. As this is my private reminder of how far in the commit-history I have reviewed, sharing it is just confusing to other developers.</p>
<p><strong>Notice:</strong> Any commits which are added only to the <code>reviewed</code> branch are unreferenced when you mark a new treeish as reviewed. Just something to keep in mind.</p>
<p>How do you keep track of the flow of changes?</p>
<h3 class='related_post_title'>Possibly related posts</h3>
<ul class='related_post'>
<li><a href='http://object.io/site/2011/meet-chop/' title='chop – efficiently dispense with current git branch'>chop – efficiently dispense with current git branch</a></li>
<li><a href='http://object.io/site/2010/hack-and-ship/' title='Simple git workflow with hack and ship'>Simple git workflow with hack and ship</a></li>
<li><a href='http://object.io/site/2011/ack-code-search/' title='Ack! Effortlessly search your codebase'>Ack! Effortlessly search your codebase</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/objectio/~4/ehIm4WpoY-U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://object.io/site/2011/local-review-with-git/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://object.io/site/2011/local-review-with-git/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 1.873 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-04-24 07:05:03 --><!-- Compression = gzip -->

