<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">
<head>
  <title>the all-thing</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <link rel="stylesheet" href="/static/style.css" type="text/css" />
  <link rel="alternate" type="application/rss+xml" title="the all-thing RSS feed" href="/index.rss" />
  <link rel="alternate" type="text/plain" title="the all-thing in plain text" href="/index.txt" />
  <script type="text/javascript" src="/static/mootools.js"></script>
  <script type="text/javascript" src="http://music.masanjin.net:9292/waxiest.js"></script>
</head>
<body>

<div id="main">
  <div id="header">
    <h1><a  href="/">the all-thing</a></h1>
    
      <p>Showing only posts labeled "git" (<a  href="/label/git.rss">rss</a>). <a  href="/index/">See all posts</a>.</p>
    
  </div>
  <div id="sidebar">
    <h3>Recent comments</h3>

    <ul class="sidebar-list">
    
    <li><b><a  href="/whisper-0.5#58174069c046a78e55f02ef81da81e74">Dominique Julia</a></b>
        <i><a  href="/whisper-0.5">Whisper 0.5 released</a></i>
           one week ago
    </li>
    
    <li><b><a  href="/ruby-ncurses-and-thread-blocking#8fa2a0f392d7c0562d630e4936407c11">William Morgan</a></b>
        <i><a  href="/ruby-ncurses-and-thread-blocking">Ruby, Ncurses and blocked threads</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/git-wtf-bf06ab7-released#533654a7a229569e27a6d0afd716c444">William Morgan</a></b>
        <i><a  href="/git-wtf-bf06ab7-released">git wtf bf06ab7 released</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/git-wtf-bf06ab7-released#b7b7a905477674eb6985b34a964a0dca">Joao Nelas</a></b>
        <i><a  href="/git-wtf-bf06ab7-released">git wtf bf06ab7 released</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/ruby-ncurses-and-thread-blocking#b00001114360ac152f87d4ac2a6e0c5b">Ollivier Robert</a></b>
        <i><a  href="/ruby-ncurses-and-thread-blocking">Ruby, Ncurses and blocked threads</a></i>
           three months ago
    </li>
    
    </ul>

    <h3>Authors</h3>
    <ul class="sidebar-list">
    
      <li><a class="author" href="/by/William+Morgan/">William&nbsp;Morgan</a>&nbsp;(65) </li>
    
    </ul>

    <h3>Tags</h3>
    <ul class="sidebar-list">
    
      <li><a class="label" href="/label/releases/">releases</a>&nbsp;(15) </li>
    
      <li><a class="label" href="/label/whisper/">whisper</a>&nbsp;(13) </li>
    
      <li><a class="label" href="/label/git/">git</a>&nbsp;(9) </li>
    
      <li><a class="label" href="/label/stats/">stats</a>&nbsp;(8) </li>
    
      <li><a class="label" href="/label/trollop/">trollop</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/ruby/">ruby</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/sup/">sup</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/git-wtf/">git-wtf</a>&nbsp;(4) </li>
    
      <li><a class="label" href="/label/vm/">vm</a>&nbsp;(4) </li>
    
      <li><a class="label" href="/label/mathml/">mathml</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/continuations/">continuations</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/ditz/">ditz</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/proglang/">proglang</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/optimization/">optimization</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/benchmarks/">benchmarks</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/rubinius/">rubinius</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/inlining/">inlining</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ubuntu/">ubuntu</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/fibers/">fibers</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ritex/">ritex</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ruby1.9/">ruby1.9</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ncurses/">ncurses</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/javascript/">javascript</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/media/">media</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/vim/">vim</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/classification/">classification</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/massachusetts/">massachusetts</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/greasemonkey/">greasemonkey</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/wine/">wine</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/readme/">readme</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/ancient-greek/">ancient-greek</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/web/">web</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/current+events/">current&nbsp;events</a>&nbsp;(1) </li>
    
    </ul>

    <h3>Other formats</h3>
    <ul class="sidebar-list">
    <li><a href="/index.rss"><img src="/static/rss-badge.png"/></a></li>
    <li><a href="/index.txt">plain text version</a></li>
    </ul>

    <h3 class="waxiest.author.original">Who is this man?</h3>
    <h3 class="waxiest.author.beautiful" style="display:none">I must find out more about this beautiful creature</h3>
    <h3 class="waxiest.author.beautifulbig" style="display:none">I MUST FIND OUT MORE ABOUT THIS BEAUTIFUL CREATURE</h3>
    <h3 class="waxiest.author.originalbig" style="display:none">WHO IS THIS MAN?</h3>

    <script type="text/javascript">
      var w = waxiest();
      w.optimizeHTMLSection("author", ["original", "beautiful", "beautifulbig", "originalbig"]);
    </script>

    <a href="http://masanjin.net" onClick="w.goalReached('greeting')">William Morgan</a>
  </div>
  <div id="content">
    
  <h2><a  href="/git-wtf-bf06ab7-released">git wtf bf06ab7 released</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="7 months ago">July 28, 2009  8:13pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/releases/">releases</a></span> <span class='label'><a  href="/label/git/">git</a></span> <span class='label'><a  href="/label/git-wtf/">git-wtf</a></span> </div>
  
  <p class='first'>I&#8217;ve released git-wtf version bf06ab7. The highlight of this release is
colorized output. <span class="caps">ANSI</span> escape sequences are the future of the web.</p>
<p>Also, the feature / integration branch comparisons is now only displayed when
<code>-r</code> is supplied.</p>
<p>Check out the <a href="http://git-wt-commit.rubyforge.org/#git-wtf">git-wtf home page</a>
for an example of the fancy colorization, or just <a href="http://git-wt-commit.rubyforge.org/git-wtf">download it now</a>.</p>
  <div class="comment-link">
    
    <a  href="/git-wtf-bf06ab7-released#comments">Four comments by <b>William Morgan</b>, <b>Cameron Booth</b>, and one other</a>.
  </div>

  <h2><a  href="/git-wtf-58b87fe9-released">git-wtf 58b87fe9 released</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="10 months ago">May  1, 2009  1:08am</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/git/">git</a></span> <span class='label'><a  href="/label/releases/">releases</a></span> <span class='label'><a  href="/label/git-wtf/">git-wtf</a></span> </div>
  
  <p class='first'>I&#8217;ve released version 58b87fe9 of git-wtf, available here: 
<a href="http://git-wt-commit.rubyforge.org/git-wtf"><a href='http://git-wt-commit.rubyforge.org/git-wtf'>http://git-wt-commit.rubyforge.org/git-wtf</a></a></p>
<p>This version contains a fairly major change: branches on origin are treated as
equal to local branches, and branches that are remote-only are denoted with <code>{
}</code>. So now there are three possible symbols: <code>( )</code> for local-only, <code>{ }</code> for
remote-only, and <code>[ ]</code> for branches that appear on both origin and your local
repo.</p>
<p>The motivation was dealing with the fact that Sup has very many feature
branches going at once, but I work on it on several different computers and
typically only have a subset of them checked out. I didn&#8217;t want anyone to be
left out&#8230;.</p>
<p>I also fixed a few minor things like removing the restriction that version
branches be local branches.</p>
  <div class="comment-link">
    
    <a  href="/git-wtf-58b87fe9-released#comments">No comments</a>.
  </div>

  <h2><a  href="/git-conflict-resolution">Sharing Conflict Resolutions in Git</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="11 months ago">March 22, 2009  5:23pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/git/">git</a></span> <span class='label'><a  href="/label/sup/">sup</a></span> </div>
  
  <p class='first'>Development of <a href="http://sup.rubyforge.org/">Sup</a> is done with Git. Sup follows a
<em>topic branch</em> methodology: features and bugfixes typically start off as
&#8220;topic&#8221; branches from <code>master</code>, and are merged into an &#8220;integration&#8221;/&#8220;version&#8221;
branch <code>next</code> for integration testing. After <em>n</em> cycles of additional bugfix
commits to the topic branch, and re-merges into <code>next</code>, the topic branches are
finally merged down to <code>master</code>, to be included in the next release.</p>
<p>I really like this approach because I think it evinces the real power of Git:
that merges are so foolproof that I can pick and choose, on a
feature-by-feature basis, which bits of code I want at each level of
integration. That&#8217;s crazy cool. And users can stick to <code>master</code> if they want
something stable, and <code>next</code> if they want the latest-and-greatest features.</p>
<p>The biggest problem I&#8217;ve had, though, is that long-lived topic branches often
conflict with each other. This happens both when merging into <code>next</code> and when
merging into <code>master</code>. I don&#8217;t think there&#8217;s a way around it; isolating
features in this way has all the benefits above, but it also means that when
they touch the same bits of code, you&#8217;ll get a conflict.</p>
<p>As a lazy maintainer, the biggest question I&#8217;ve had is: is there a way to push
the burden of conflict resolution to the patch submitter? Is there a way for me
to say: hey, your change conflicts with Bob&#8217;s. Can you resolve the conflict and
send it to me?</p>
<p>One option I&#8217;ve considered is to have contributors to publish not only their
feature branches, but their <code>next</code> branch as well. Assuming they aren&#8217;t mucking
about with their <code>next</code> branch otherwise, if it contains just the merge commit,
I can merge it into mine, and it should be a fast-forward that gets me the
merge commit, conflict resolution and all.</p>
<p>But I don&#8217;t like that idea because, in every other case, I&#8217;m merging in the
feature branches directly. Why should I suddenly start merging in <code>next</code> just
because you have a conflict?</p>
<p>Furthermore, Sup primarily receives email contributions via <code>git format-patch</code>,
and I do the dirty deed of sorting them into branches and merging things
around. Requiring everyone to host a git repo iff they produce a conflicting
patch seems silly. (And <code>git format-patch</code>, unfortunately, produces nothing for
merge commits, even if they have conflict resolution changes. Maybe there&#8217;s a
good reason for this, or maybe not. I&#8217;m not sure.)</p>
<p>After some effort, and some git-talk discussion, I have a solution. And no, it
doesn&#8217;t involve sharing <code>git-rerere</code> caches. (Which it seems that some people
do!)</p>
<p>For the contributor: once you have resolved the conflict, do a <code>git diff
HEAD^</code>. This will output the conflict resolution changes. Email that to the
maintainer along with your patch.</p>
<p>For the maintainer:
<code><pre class="ruby"><span class="global">$ </span><span class="ident">git</span> <span class="ident">checkout</span> <span class="keyword">next</span>
<span class="global">$ </span><span class="ident">git</span> <span class="ident">merge</span> <span class="punct">&lt;</span><span class="ident">offending</span> <span class="ident">branch</span><span class="punct">&gt;</span>
<span class="punct">[...</span> <span class="ident">you</span> <span class="ident">have</span> <span class="ident">a</span> <span class="ident">conflict</span><span class="punct">,</span> <span class="ident">yada</span> <span class="ident">yada</span> <span class="punct">...]</span>
<span class="global">$ </span><span class="ident">git</span> <span class="ident">checkout</span> <span class="keyword">next</span> <span class="punct">.</span>
<span class="global">$ </span><span class="ident">git</span> <span class="ident">apply</span> <span class="punct">--</span><span class="ident">index</span> <span class="punct">&lt;</span><span class="ident">resolution</span> <span class="ident">patch</span> <span class="ident">filename</span><span class="punct">&gt;</span>
<span class="global">$ </span><span class="ident">git</span> <span class="ident">commit</span></pre></code></p>
<p>Running <code>git merge</code> gets you to the point where you have a conflict. Running
<code>git checkout next .</code> sets your working directory to the state it was before
you merged. And <code>git apply</code> applies the resolution changes.</p>
<p>You lose authorship of the conflict resolution, but you can use <code>git commit
--author</code> to set it.</p>
<p>I think the ideal solution would be for <code>git format-patch</code> to produce something
usable in this case. I see some traffic on the Git list that suggests this is
being considered, so hopefully one day this rigmarole will not be necessary.</p>
  <div class="comment-link">
    
    <a  href="/git-conflict-resolution#comments">Four comments by <b>William Morgan</b>, <b>Brendan O'Connor</b>, and one other</a>.
  </div>

  <h2><a  href="/git-wtf-dd706855-released">git-wtf dd706855 released</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="11 months ago">March 16, 2009  1:02pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/git/">git</a></span> <span class='label'><a  href="/label/git-wtf/">git-wtf</a></span> <span class='label'><a  href="/label/releases/">releases</a></span> </div>
  
  <p class='first'>I&#8217;ve released a version dd706855 of git-wtf, available here:
<a href="http://git-wt-commit.rubyforge.org/git-wtf"><a href='http://git-wt-commit.rubyforge.org/git-wtf'>http://git-wt-commit.rubyforge.org/git-wtf</a></a></p>
<p>I&#8217;ve tweaked the output format so that branches that don&#8217;t exist
on the remote server are displayed with <code>()</code>&#8216;s and those that do
with <code>[]</code>&#8217;s, and <code>~</code> is the new symbol for a merge that only occurs
on the local side.</p>
<p>I think this produces a better display; lots more information
per line of ourput.</p>
<p>I&#8217;ve also added a couple random options which you can discover by
reading the source. :)</p>
<p>The big next step I&#8217;d like to take with this thing is to support
multiple remote repos better. Currently it&#8217;s kinda specific to your
origin repo.</p>
  <div class="comment-link">
    
    <a  href="/git-wtf-dd706855-released#comments">No comments</a>.
  </div>

  <h2><a  href="/git-fu">Some git-fu</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="16 months ago">October 28, 2008  7:39pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/git/">git</a></span> </div>
  
  <p class='first'>Some git-fu I&#8217;ve been finding particularly useful recently:</p>
<ol>
	<li>Untangling concurrent changes into multiple commits: <code>git add -p</code> is the
greatest thing since sliced bread. But did you know it features an &#8216;s&#8217;
command which allows you to split a hunk into smaller hunks? Now you can
untangle pretty much anything.</li>
	<li>Splitting a previous commit into multiple commits: I&#8217;ve been finding this one
useful for quite a while. Start with a <code>git rebase -i</code>, mark the commit(s) as
<code>edit</code>, and once you get there, do a <code>git reset HEAD^</code>. All the changes in
that commit will be moved out of the staging area, and you can <code>git add</code>/<code>git
commit</code> to your heart&#8217;s content. Finish with a quick <code>git rebase --continue</code>
to the throat.</li>
	<li>Fixing your email address in previous commits: I often make a new repo and
forget to change my email address. (For historical, and now silly, reasons, I
like to commit to different projects from different addresses, and I often
screw it up.) Here&#8217;s how to do a mass change: <code>git filter-branch --env-filter
"export GIT_AUTHOR_EMAIL=your.new.email.address" commit..HEAD</code>, where
<em>commit</em> is the first commit to be affected. Of course, changing the email
address of a commit changes its id (and the id of all subsequent commits), so
be careful if you&#8217;ve published them. (Also note that using <code>--env-filter=...</code>
won&#8217;t work. No equal sign technology.)</li>
	<li>A <code>git log</code> that includes a list of files modified by each commit: <code>git log
--stat</code>, which also gives you a colorized nice histogram of
additions/deletions for each file. This is a nice middle ground between <code>git
log</code> and <code>git log -p</code>.</li>
	<li>Speaking of <code>git log -p</code>, here&#8217;s how to make it sane in the presence of moves
or renames: <code>git log -p -C -M</code>. Otherwise it doesn&#8217;t check for moves or
copies, and happily gives you the full patch. (These should be on by
default.)</li>
	<li>Comparing two branches: you can use <code>git log --pretty=oneline one..two</code> for
changes in one direction (commits that &#8216;two&#8217; has that &#8216;one&#8217; doesn&#8217;t); and
<code>two..one</code> for the opposite direction. You can also use the triple-dot
operator to merge those two lists into one, but typically I find it useful to
separate the two. Or you can check out
<a href="http://git-wt-commit.rubyforge.org/">git-wtf</a>, which does this for you.</li>
	<li>Preview during commit message: <code>git commit -v</code> will paste the diff into your
editor so you can review it while composing the commit message. (It won&#8217;t be
included in the final message, of course.)</li>
	<li><code>gitk</code>: don&#8217;t use it. You&#8217;ll get obsessive about merge commits, rebasing,
etc., and it just doesn&#8217;t matter in the end. It took me about 4 months to
recover from the bad mindset that <code>gitk</code> put me into.</li>
</ol>
  <div class="comment-link">
    
    <a  href="/git-fu#comments">One comment by <b>Matt Wilson</b></a>.
  </div>

  <h2><a  href="/git-1.6.0-changes">Git 1.6.0 changes</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="18 months ago">August 18, 2008  8:16pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/git/">git</a></span> </div>
  
  <p class='first'>Git 1.6.0 (just released) contains now detects Ruby class, module and method
definitions in diff output. Previously it was just class names. (<a href="http://n2.nabble.com/-PATCH--diff:-add-ruby-funcname-pattern-td661824.html">This
patch</a>.)</p>
<p>Other things I&#8217;m excited about in the new Git:</p>
<ol>
	<li><code>git-clone --mirror</code> is a handy way to set up a bare mirror repository.</li>
	<li><code>git-diff --check</code> now checks for leftover merge conflict markers.</li>
	<li><code>git-stash save</code> now has a &#8212;keep-index option.  This lets you stash away the
local changes and bring the changes staged in the index to your working tree
for examination and testing.</li>
	<li><code>git-stash</code> also has a new <code>branch</code> subcommand to create a new branch out of
stashed changes.</li>
</ol>
  <div class="comment-link">
    
    <a  href="/git-1.6.0-changes#comments">No comments</a>.
  </div>

  <h2><a  href="/old34">ditz git integration plugin, in git</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="20 months ago">June 26, 2008  6:00pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/ditz/">ditz</a></span> <span class='label'><a  href="/label/git/">git</a></span> </div>
  
  <p class='first'>I&#8217;ve fleshed out <a href="http://ditz.rubyforge.org/&#39;s">ditz</a> plugin architecture and just added a plugin that ties it more closely to git. With this plugin enabled, you can tie issues to feature branches and automatically get a list of commits on that branch (until they&#8217;re merged into master, at which point that becomes impossible, thanks to the magic of git).</p>
<p>Here&#8217;s an example: Sup&#8217;s <a href="http://sup.rubyforge.org/ditz/issue-bdd4415a9d4c8fd3602500111bf9268aa7c7c6a4.html">configurable colors</a> issue.</p>
<p>With these changes, Ditz is now firmly in the <span class="caps">MVC</span> camp. The models are created from yaml objects on disk; the views are an <span class="caps">HTML</span> renderer (using <span class="caps">ERB</span>) and a screen renderer (using puts technology), and the controller is the previously-mentioned <a href="http://gitorious.org/projects/ditz/repos/mainline/blobs/master/lib/operator.rb">operator.rb</a>.</p>
<p>If you look at the <a href="http://gitorious.org/projects/ditz/repos/mainline/blobs/master/lib/plugins/git-features.rb">plugin code</a> you see that it need to modify all three of these components. It adds fields to the Issue and Config objects, it adds output to the <span class="caps">HTML</span> and screen views, and it adds commands to the controller. The fact that it can do this in a few lines of code is pretty sweet.</p>
  <div class="comment-link">
    
    <a  href="/old34#comments">Two comments by <b>Jing Xue</b> and <b>William</b></a>.
  </div>

  <h2><a  href="/old35">git-wtf</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="20 months ago">June 25, 2008 10:59pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/git/">git</a></span> <span class='label'><a  href="/label/git-wtf/">git-wtf</a></span> </div>
  
  <p class='first'>I&#8217;ve released a fairly preliminary version of <code>git-wtf</code> to my <a href="http://git-wt-commit.rubyforge.org/">collection of Git tools</a>. This is something I&#8217;ve been working on recently to help wean myself away from excessive <code>gitk</code> usage. From the description:</p>
<blockquote>
<p>If you&#8217;re on a feature     branch, it tells you which version branches it&#8217;s merged into. If you&#8217;re on a version     branch, it tells you which feature branches are merged in and which aren&#8217;t. For every branch,     if it&#8217;s a tracking branch, it tells you which commits need to be pulled and which need to be pushed.</p>
</blockquote>
<p>So basically if you find yourself with a ton of branches (which invariably happens if you use feature branches in Git) or you find that keeping track of branch state is generally hard, and that <code>gitk</code> is confusing as often as it is useful, this is the tool for you.</p>
<p>By default it assumes that any branches named &#8220;master&#8221;, &#8220;next&#8221; or &#8220;edge&#8221; are version branches, and all other branches are feature branches. This is configurable, of course. It also warns, for tracked branches, if both the remote branch and the local branch have new commits, i.e. <code>git pull</code> would create a merge commit and you should rebase instead. If you don&#8217;t care about this type of thing, this might be annoying.</p>
<p>The main thing addition I foresee in the near future is a warning if merging in a feature branch into a version branch would collapse two version branches. Something like: when merging a feature branch into a version branch, warn if the feature branch contains commits reachable from any version branch and not reachable from master.</p>
  <div class="comment-link">
    
    <a  href="/old35#comments">No comments</a>.
  </div>

  <h2><a  href="/old17">The Many Styles of Git</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="20 months ago">June 18, 2008  6:49pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/git/">git</a></span> </div>
  
  <p class='first'>One of Git&#8217;s defining characteristics is its extreme (some say &#8220;ridiculous&#8221;)
flexibility. Even with all the fancy porcelain on top, what you&#8217;re get when you
use Git is basically a general <span class="caps">DAG</span> builder for patches, and the ability to
apply labels to points within.</p>
<p>It&#8217;s interesting to see how this flexibility is put to use in practice. In my
many years (ok, months) of Git usage, across a variety of projects, I&#8217;ve
noticed several distinct styles of Git usage.</p>
<p>The most salient differences between styles are:</p>
<ul>
	<li>How much they care about keeping the development history &#8220;beautiful&#8221;, i.e.
free of unnecessary merges. Git gives you two tools for adding your commit to a
branch: merge and rebase. A rebase will always preserves linearity, a merge has
the potential for introducing non-linearity. Some projects are fanatic about
this. Linus has been known to reject code because there were too many &#8220;test
merges&#8221; (see the <code>git-rerere</code> man page). Other projects don&#8217;t care at all.</li>
	<li>How much they make use of topic branches. Some projects do the majority of
development through them. Some do all development directly onto master,
branching only for long-term divergent development.</li>
	<li>How new commits come into the system: patches to mailing lists, merges from
remote branches performed by the maintainer, or commits directly into the
central repo.</li>
</ul>
<p>Each of these decisions results in a different style
of development. The styles I&#8217;ve encountered in the wild are:</p>
<ul>
	<li>The just-like-<span class="caps">SVN</span> approach. Example project: <a href="http://rubini.us">Rubinius</a>.
Individual contributers have a commit bit, or they don&#8217;t. Everyone works from
local clones. If you have a commit bit, you push directly to origin/master.
Non-committers can post patches to a mailinglist or to <span class="caps">IRC</span>. There are some
published branches, but they&#8217;re for long-running lines of development that are
eventually merged in and discarded. There&#8217;s no real pickiness about merges in
development history; rebasing is encouraged but not required.</li>
	<li>The <a href="http://gitorious.org">Gitorious</a> / <a href="http://github.com">Github</a> approach.
Example project: everything on those systems. Only the maintainer can commit to
the central repository. Anyone can create a remote clone, push commits, and
send a formal merge request through the system to the maintainer. All code
addition (except for the maintainer&#8217;s additions) are done through merges.</li>
	<li>The topic-based approach. Example projects: Git itself, the Linux kernel,
<a href="http://sup.rubyforge.org/">Sup</a>. Patches are submitted to the mailing list. The
maintainer builds topic branches for each feature/bugfix in development and
merges these into different &#8220;version branches&#8221;, which
correspond to different versions of the project such as
stable/experimental/released version distinctions. Sub-maintainers are used
when the project gets large, and their repositories are merged by the
maintainer upon request.</li>
	<li>The remote topic branch approach. This was an experiment I tried with
<a href="http://ditz.rubyforge.org/">Ditz</a>, and is roughly my attempt to do topic-based
Git with Gitorious. In this approach, contributors, instead of submitting
patches to a mailing list, maintain feature branches themselves. When a branch
is updated, a merge request is sent to the maintainer, who
merges the remote branch into a version branch.</li>
</ul>
<p>I&#8217;ve listed the styles in order from least to most overhead. The just-like-<span class="caps">SVN</span>
style requires very little knowledge of Git; at the other end of the spectrum,
the topic-based approaches require a fair amount of branch managment. For
example, care has to be taken that merging a topic branch into a version branch
doesn&#8217;t accidentally merge another version branch in as well. (This type of
complexity spurred me to write tools like <a href="http://git-wt-commit.rubyforge.org/">git
show-merges</a> and the soon-to-be-released
<code>git wtf</code>.)</p>
<p>The advantage of the topic-based approaches, of course, is that it&#8217;s possible
to maintain concurrent versions of the same program at different levels of
stability, and to pick and choose which features go where.</p>
<p>Which style is best for you depends on what you&#8217;re trying to accomplish. Like
all good tools, what you get out of Git depends on what you&#8217;re willing to put
into it, and that&#8217;s a decision you&#8217;ll have to make.</p>
  <div class="comment-link">
    
    <a  href="/old17#comments">No comments</a>.
  </div>




  </div>

  <div id="footer" style="margin: 0px;">
    Served up by <a href="http://masanjin.net/whisper/">Whisper</a>. Yes!
  </div>
</div>
</body>
</html>
