Here is a solution to maintain divergent branches in git. Because it is easy to merge by mistake. I give a script that encapsulate git in order to forbid some merge and warn you some merge should be dangerous.
</div>
<h2id="how-to-protect-against-your-own-dumb">how to protect against your own dumb</h2>
<p>I work on a project in which some of my git branches should remain divergent. And divergences should grow.</p>
<p>I also use some branch to contain what is common between projects.</p>
<p>Say I have some branches:</p>
<p>master: common to all branches
dev: branch devoted to unstable development
client: branch with features for all client but not general enough for master
<p>An arrow from A to B means, you can merge A in B. If there is no arrow from A to B that means it is <em>forbidden</em> to merge A in B. Here is the corresponding rubycode:</p>
<p>Having a <code>:master => [ :dev, :client ]</code> means you can merge <code>master</code> branch into <code>dev</code> and <code>client</code>.</p>
<p>If by mistake I make a <code>git checkout master && git merge clientA</code>, I made a mistake. This is why I made a script which encapsulate the git behaviour to dodge this kind of mistake.</p>
<p>But this script do far more than that. It also merge from top to down. The action <code>allmerges</code> will do:</p>
<div><preclass="twilight">
git co dev <spanclass="Keyword">&&</span> git merge master
git co client <spanclass="Keyword">&&</span> git merge master
git co clientA <spanclass="Keyword">&&</span> git merge client
git co clientB <spanclass="Keyword">&&</span> git merge client
</pre></div>
<p>That means, I can update all branches. The algorithm will not make loop even if there is a cycle in the branch hierarchy.</p>
<p>Here it is:</p>
<divclass="small"><divclass="code"><divclass="file"><ahref="/Scratch/en/blog/2010-03-23-Encapsulate-git/code/eng">➥ eng </a></div><divclass="withfile">
<spanclass="Keyword">if</span> system <spanclass="String"><spanclass="String">%{</span>eng checkout <spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">#{</span>b<spanclass="StringEmbeddedSource">}</span></span><spanclass="String">}</span></span>
<spanclass="Keyword">if</span> get_current_branch <spanclass="Keyword">!=</span> b
puts <spanclass="String"><spanclass="String">"</span>Can't checkout to <spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">#{</span>b<spanclass="StringEmbeddedSource">}</span></span><spanclass="String">"</span></span>
exit <spanclass="Constant">2</span>
<spanclass="Keyword">end</span>
<spanclass="Keyword">if</span> system <spanclass="String"><spanclass="String">%{</span>eng merge <spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">#{</span>branch<spanclass="StringEmbeddedSource">}</span></span><spanclass="String">}</span></span>
system <spanclass="String"><spanclass="String">%{</span>git co <spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">#{</span>current_branch<spanclass="StringEmbeddedSource">}</span></span><spanclass="String">}</span></span>
system <spanclass="String"><spanclass="String">%{</span>git merge <spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">#{</span>src_branch<spanclass="StringEmbeddedSource">}</span></span><spanclass="String">}</span></span>
puts <spanclass="String"><spanclass="String">%{</span>Warning! <spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">#{</span>src_branch<spanclass="StringEmbeddedSource">}</span></span> not mentionned in rb configuration<spanclass="String">}</span></span>
sleep <spanclass="Constant">2</span>
system <spanclass="String"><spanclass="String">%{</span>git merge <spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">#{</span>src_branch<spanclass="StringEmbeddedSource">}</span></span><spanclass="String">}</span></span>
puts <spanclass="String"><spanclass="String">%{</span>Warning! <spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">#{</span>src_branch<spanclass="StringEmbeddedSource">}</span></span> not mentionned in rb configuration<spanclass="String">}</span></span>
<spanclass="Keyword">else</span> system <spanclass="String"><spanclass="String">%{</span>git <spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">#{</span><spanclass="StringVariable">ARGV</span><spanclass="StringEmbeddedSource"><spanclass="StringEmbeddedSource">.</span><spanclass="Entity">join</span></span><spanclass="StringEmbeddedSource">(</span><spanclass="String"><spanclass="String">'</span><spanclass="String">'</span></span><spanclass="StringEmbeddedSource">)</span><spanclass="StringEmbeddedSource">}</span></span><spanclass="String">}</span></span>
<spanclass="Keyword">end</span>
</pre>
</div></div></div>
<p>All you need to do to make it work is simply to copy eng in a directory contained in your PATH.</p>
<p>Of course try to use as few as possible <code>cherry-pick</code> and <code>rebase</code>. This script was intended to work with workflow using <code>pull</code> and <code>merge</code>.</p>