Voici une solution pour conserver des branches divergentes avec <code>git</code>.
Parce qu’il est facile de <em>merger</em> par erreur, je propose un script qui encapsule le comportement de <code>git</code> pour interdire certains <em>merges</em> dangereux. Mais qui permet aussi de faire des merges en cascades de la racines vers les autres branches.
</span></p>
<h2id="se-prmunir-contre-les-erreurs">Se prémunir contre les erreurs</h2>
<p>Je travaille sur un projet dans lequel certaines de mes branches <code>git</code> doivent rester divergentes. Et les divergences devraient aller en s’accentuant.</p>
<p>J’utilise aussi certaines branches qui contiennent la partie commune de ces projets.</p>
<p>Disons que j’ai les branches :</p>
<p>master: commune à toutes les branches
dev: branche instable pour le développement
client: Branche commune à plusieurs clients
clientA: le projet spécialisé pour le client A
clientB: le projet spécialisé pour le client B</p>
<p>Voilà comment je souhaiterai que ça fonctionne</p>
<p>Une flèche de A vers B signifie que l’on peut merger A dans B. S’il n’y a pas de flèche de A vers B cela signifie qu’il est <em>interdit</em> de merger A dans B. Voici le code ruby correspondant :</p>
<p><code>:master => [ :dev, :client ]</code> signifie que l’on peut merger la branche <code>master</code> dans la branche <code>dev</code> et la branche <code>client</code>.</p>
<p>Je fait une erreur si je tape <code>git checkout master && git merge clientA</code>.
C’est pour éviter ça que j’ai fait un script pour encapsuler le comportement de <code>git</code>.</p>
<p>Mais ce script fait bien plus que ça. Il fait des merges en cascade de la racine vers les feuilles avec l’acion <code>allmerges</code>.</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>Je peux ainsi mettre à jour toutes les branches. L’algorithme ne boucle pas même s’il y a des cycles dans la structure des branches.<br/>
Le voici :</p>
<divclass="small"><divclass="code"><divclass="file"><ahref="/Scratch/fr/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>
f 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>Pour que ça fonctionne il vous suffit de copier <code>eng</code> dans un répertoire présent dans votre <code>PATH</code>.</p>
<p>Bien entendu, il faut essayer de faire aussi peu que possible des <code>cherry-pick</code> et des <code>rebase</code>. Ce script a pour but de s’intégrer avec les workflow basé sur les <code>pull</code> et <code>merge</code>.</p>
<ahref="/Scratch/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/"><spanclass="nicer">«</span> Quand se passer des expressions régulières ?</a>