Git ou Bazaar ?

Pourquoi je suis passé de Bazaar à Git

Même si je considère que git a beaucoup de points noirs, je pense qu’il reste le meilleur DCVS à ce jour avec lequel travailler. C’est pourquoi je commencerai par parler des qualité de bazaar qui manquent à git. Ensuite seulement je donnerai le seul avantage de git qui suffit à le rendre préférable à Bazaar.

La découverte des DCVS

À savoir avant de débuter l’article. Je suis, comme beaucoup, un ancien utilisateur de subversion. Je trouve subversion très bien, mais j’ai été conquis par les capacités supplémentaires apportées par les systèmes de versions concurrentes décentralisés.

Il y a deux façon de percevoir les systèmes de versions. Soit on voit un système de branches (voir le très bon article sur betterexplained). Soit on peut voir les systèmes de versions comme des moyens d’appliquer des patches. C’est-à-dire que l’on peut soit se concentrer sur les nœuds soit sur les transitions du graphe induit par les différentes versions d’un projet.

Pour git, c’est plutôt ce deuxième point de vue qui a été adopté. C’est un peu normal, étant donné que c’est Linus Torvald qui l’a inventé pour combler les problèmes inhérent aux problèmes de création de code dans le noyau Linux. Et comme historiquement, la communauté Linux se base beaucoup sur les patches, il semblait logique que ce soit ce second point de vue qui soit adopté.

J’ai d’abord été convaincu par Bazaar. Pourquoi ? Les arguments en faveur de bazaar étaient : facilité d’utilisation en particulier, facilité d’adaptation pour tous ceux qui étaient habitués à subversion. Comme c’était mon cas, et que lorsque j’avais essayé de suivre la doc Git à l’époque c’était un peu épique. Puis avec le temps, je me suis dit que je n’allais quand même pas mourir idiot et que j’allais me mettre sérieusement à git histoire de voir si ses défenseurs avaient vraiment raison.

Mon dieu, que ce fut fastidieux. La terminologie est affreuse ! Et ce n’est rien de le dire.

Là où Bazaar est meilleur que git

Par exemple, checkout qui sert certainement à la même chose du point de vue technique, est dans l’usage un terme employé pour faire des actions qui semblent très différentes à un utilisateur λ. Exemple :

git checkout pipo

annule une modification courante du fichier pipo

git checkout pipo

change de la branche courante vers la branche pipo

Et là, comme moi, vous remarquez que la même commande à deux sens complètement différents. Comment ça se passe alors, quand il y a une branche pipo et un fichier pipo alors ? Et bien par défaut, ça change de branche. Pour lever l’ambigüité il faut utiliser la syntaxe

git checkout ./pipo

Oui, bon… Voilà, voilà, voilà….

Ça marche, mais ce n’est pas très convivial. D’autant plus que le mot clé checkout signifiait sous CVS et SVN l’opération pour récupérer un projet distant.

Là où la différence se creuse c’est avec la terminologie Bazaar qui est bien plus naturelle. Car il n’y a pas de commande pour changer de branche, puisqu’il y a une branche par répertoire. Ainsi, pour changer de branche, il suffit de faire cd path/to/branch. Et pour revenir en arrière :

bzr revert pipo

De plus, la plupart des commandes bazaar prennent en paramètre un numéro de révision, par exemple pour revenir 3 versions précédentes il suffit d’écrire :

bzr revert -r -3 pipo

L’équivalent sous git est beaucoup plus cryptique :

bzr checkout HEAD~3 pipo

Encore un fois, Bazaar est bien plus lisible.

Revenir dans le temps pour tout le projet :

avec Bazaar :

bzr revert -r -3 pipo

et avec git ? git checkout ? Bien sûr que non voyons ! Ce serait bien trop simple. Ce que l’on trouve dans les forums c’est :

git reset –hard HEAD~3

Sauf que cette syntaxe est horrible. Elle oublie ‘réellement’ les révisions. Il faut donc l’utiliser avec prudence. Mais en effet, je conseillerai plutôt :

git checkout HEAD~3 – . && git commit -m ‘back in time’

Histoire d’avoir la branche backup sous la main, car sinon, on risque de perdre définitivement la version courante de HEAD. Qui ramène la branche locale à ce point. Mais il reste des erreur s’il y a eu des ajouts de fichier entre temps. Le seul et l’unique vraiment propre de revenir en arrière dans git c’est de lancer la commande suivante :

for i in (seq02); dogitrevert − n −  − no − edithead i; done git commit -m “reverted 3 versions back”

ce qui signifie sur un système UNIX en zsh (ou bash) faire git revert de toutes les dernières versions. Même si quelqu’un d’autre à fait un pull de vos modification intermédiaire il ne sera pas embêté et il sera au courant de ce qu’il s’est passé.

La règle est simple : Ne JAMAIS utiliser la commande git reset avec une version que d’autres personnes auraient pu avoir fetcher.

Voilà, c’est dit. Découvrir ça m’a pris pas mal de temps, avec plein d’essai de tous les cotés. Le plus sûr reste toujours la méthode vue plus haut. Si vous souhaitez automatiser cela, le plus simple est d’ajouter l’alias suivant à votre fichier ~/.gitconfig. Bien sûr l’alias ne fonctionnera que sur les environnement possédant zsh, ce qui est le cas de la plupart des environnements UNIX (Ubuntu, Mac OS X…).

[alias] uncommit = !zsh -c ‘“if ((0)); thennb=(( 0 − 1)); elsenb = 0; fi; i = 0; while((i <  = nb)); dogitrevert − n −  − no − editHEAD i; ((i++)); done; git commit -m "revert to $0 version(s) back"”’

Ce qui fait que git est le meilleur DCVS jusqu’à aujourd’hui

Après avoir énoncé les cotés négatifs (et je les trouve nombreux) de git. Voici les cotés positifs qui a eux seul valent la peine de se coltiner tous les problèmes inhérent à git.

Cheap branching

Vous travaillez toujours dans le même répertoire principal. Par exemple, vous pouvez travailler sur deux corrections de bug. Disons fix1 et fix2 nécessitant la modification respective de file1 et file2. Vous pouvez travailler dans n’importe quel ordre sur vos deux fichiers dans la branche master. Puis, une fois votre travail fini. Aller dans la branche fix1 pour commiter file1. Puis aller dans la branche fix2 pour commiter file2. Et enfin, merger les deux branches dans master.

> vim file1 > vim file2 > git br fix1 > git add file1 > git commit -m ‘fix1’ > git br fix2 > git add file2 > git commit -m ‘fix2’ > git commit master > git merge fix1 > git merge fix2

Et il est vraiment très agréable de ne pas se soucier d’être dans la bonne branche. Vous n’avez à vous occuper que de votre code et seulement ensuite vous occuper du système de version.

Sous Bazaar, il m’est souvent arriver de coder dans la mauvaise branche. Pour récupérer le coup, on doit copier les modifications du fichier dans la bonne branche et faire un revert sur le fichier en question, puis aller dans la bonne branche pour commiter les modifications. Enfin, la plupart du temps, je me trompe de branche et puis tant pis, je merge les deux tout en sachant que c’est sale.

C’est pourquoi je préfère utiliser git. Si Bazaar venait à implémenter ce système de cheap branching, je le replacerai certainement en tête.