16 août 2010

Refactoring avec Eclispe, SVN ... et Git

Je me lance dans un gros refactoring de sauvage, pour lequel un module maven doit être splitté en trois, avec des changements de packages en tout genre et j'en passe.

Pour avoir fait ce genre de manip plus d'une fois, celà se traduit généralement par :

  • L'impossibilité de faire l'opération en un seul commit SVN (en tout cas, j'y suis jamais arrivé) : des fichiers déjà modifiés doivent être déplacés ou renommés, et le couple SVN+Eclipse ne gère pas du tout bien la manip
  • L'impossibilité totale d'envisager un merge de modifications apparues en cours de route. Le fichier à changé de place et de nom, SVN ne s'y retrouve pas.
Au final, l'opération se fait sur la pause de midi ou - dans mon cas parce que ça ne me dérange pas - tôt le matin, avec deux ou trois échanges de mail pour alerter tout le monde et bloquer les commits.

Cette fois, je tente la manipulation avec Git. 

Tout d'abord, un git svn clone me fournit un repo Git à l'image du SVN projet.

Ensuite, après un premier essai pas très concluant, j'installe un nightly-build du plugin EGit pour contourner ce bug, qui rend EGit quasiment inexploitable (il veut tout le temps committer les target).

C'est parti pour une séance de "bouge ton code". Mettez à fond "I like to move it" et balancez la sauce...

Je ne vous cache pas que j'ai un peu merdé sur mes premières commandes Git. En gros, pendant la première demi-heure on se demande dans quoi on s'est embarqué, et même avec mon ami Google les commandes restent assez obscures. Pendant cette phase d'appropriation de l'outil, ayez le réflexe de garder sous le coude la refcard Git, ainsi que l'excellent open-livre ProGit :P

Après ces premiers faux pas, les réflexes commencent à venir, et je dois bien avouer que la question devient vite "pourquoi n'ai-je pas essayé plus tôt ?"

Pourquoi Git est-il différent ?
La première différence, liée à  l'aspect décentralisé, est de disposer en local d'un repo très rapide pour committer, brancher, revenir en arrière, etc. Pensez au nombreuses fois où vous avez eu recours à l'historique local d'Eclipse pour rattraper une boulette. Et bien là c'est toute la puissance d'un SCM qui est au bout du clavier. Le switch de branche étant quasi instantané, on en profite (on en abuse même) alors que sous SVN c'était l'horreur.

La seconde différence, c'est que la structure de Git se base sur un unique répertoire .git, et pas une invasion de .svn à tous les niveaux. Ca n'a l'air de rien, mais une conséquence immédiate est que les performances I/O du système (dénaturé par une surcouche MacAffee) s'en trouvent bien meilleures. Lorsqu'on déplace un répertoire entier avec SVN, la première erreur consiste à utiliser l'explorateur. Les fichiers .svn n'étant pas mis à jour il n'y à rien à committer. Après s'être fait avoir 2 ou 3 fois, on apprend à faire un "refactor > move" qui se traduit par une série de Remove + Add au niveau SVN, et au prochain merge c'est l'enfer.

Dernière différence significative : en l'absence de .svn pour marquer chaque répertoire/fichier, Git doit retrouver l'identité de chaque fichier modifié lors d'un commit. Il va comparer les fichiers par rapport à son index, et sera capable d'identifier un déplacement, malgré les déclaration "package" ou d'import qui changent. En gros, le fichier le plus "similaire" dans l'index est celui qui a été déplacé. C'est une solution empirique, mais qui marche bougrement bien. D'ailleurs, tout est empirique dans Git, comme les identifiants de commit qui sont des empruntes SHA1 - mathématiquement parlant il y a un microscopique risque de doublon, mais en attendant ça fonctionne très, très bien ! Résultat, le SCM est très souple et les merges ne sont plus un soucis !

Pourquoi Git fait-il peur ?

  • Git c'est nouveau, c'est geek, donc forcément ça fait un peu peur.
  • Git c'est très "ligne de commande", et quelle ligne ! Même si on s'y fait finalement assez vite, voir quelqu'un travailler avec Git fait penser qu'on est passé du côté obscur.
  • Git est mal intégré dans Windows; msysgit est très correct, mais reste une solution ligne de commande, avec quelques outils graphiques bienvenus. TortoiseGit ne m'a pas convaincu, et j'utilise EGit sous Eclipse en complément de la console GitBash.

L'autre raison qui fait que Git va mettre un peu de temps à rentrer dans les moeurs, c'est son aspect décentralisé : le concept est encore assez neuf, et vient en contradiction avec des années d'habitude centralisatrices.

My 2 cents...

Comment bien aborder Git ? Le couplage avec SVN permet de l'expérimenter localement sans impacter le reste de l'équipe (en dehors des fichiers .gitignore qui vont fleurir dans SVN). Ensuite, il faut considérer votre mode de travail local, votre "workflow", indépendamment de celui de l'équipe qui est formaté par SVN.

Sur le poste de développement, on fait plein de choses en parallèle : on revient en arrière, on teste un truc, on change de tâche. On se retrouve donc à committer quelques fichiers par-ci par là, à commiter un item par petites touches. Autrement dit, on pollue le projet de travaux pas finis, et on est sous-outillé en local pour séparer nos diverses activités. Git est un outil qui vient soutenir ces démarches de manière active, il va structurer et assister notre travail quotidien.

Une fois l'habitude de Git en locale prise, les derniers récalcitrants convertis, le passage du point de centralisation sous Git parait une évidence. Avec lui une autre façon d'envisager le projet peut émerger : comment isoler chaque fonctionnalité et les "merger" au dernier moment ? Comment intégrer les correctifs à la demande ? etc...

Que ce soit Git, ou Mercurial (apparemment plus structurant, je n'ai pas testé) ou un autre candidat, les SCM décentralisés vont bouleverser notre façon de travailler.

10 commentaires:

Emmanuel Lécharny a dit…

Pour les .gitignore dans le repo SVN, il est possible de rajouter ce nom à la propriété svn:ignore (récursivement).

svn propset svn:ignore .gitignore

Ou alors localement dans global-ignores (~/.subversion/config)

Nicolas De Loof a dit…

on peut en effet ignorer les .gitignore, mais dans ce cas tous ceux qui voudront "giter" devront se retaper la manip ! En plus, ces .gitignore peuvent attirer l'attention et "aider" à la promotion de Git ... qui sait.

Par contre, une auto-conversion du sv:ignore en .gitignore serait top :D

Unknown a dit…

Merci, très bon article ça donne vraiment envie de se lancer avec Git

Anonyme a dit…

Alternative au clonage du répo SVN en répo Git qui me semble moins impactante : utiliser un IDE un peu plus prévisible et productif qu'Eclipse, comme IDEA.

Pas de soucis pour des gros refactorings avec le couple SVN+IDEA. Le seul truc à faire gaffe, c'est de ne jamais inclure des fichiers connus de SVN dans des répertoires inconnus de SVN.

Nicolas De Loof a dit…

le soucis des "merge" avec SVN n'est pas lié à Eclipse, tu as exactement les même problèmes pour intégrer des modifs apparues durant ton refactoring. Du point de vue de SVN, tu as supprimé un fichier qui porte une nouvelle modification, donc conflit.

Unknown a dit…

Salut

et en terme d'occupation disque?
Entre le repos Git, celui de maven, les historiques locaux des IDE, les fichiers d'indexations, les VM pour tester sur d'autres OS....
Je ne suis pas sur que l'on va pouvoir continuer à tout loger sur nos disques durs d'ordinateurs portables. En plus les disques SSD ont tendance à être plus petit, ce qui n'arrange pas le tableau.

Nicolas De Loof a dit…

Rien n'oblige à récupérer *tout* l'historique projet dans le repo Git local. Dans ce cas Git est moins consommateur que Subversion car il stocke les "deltas" de manière très compacte dans un format binaire. Git Gui propose d'ailleurs spontanément de compacter ce référentiel.

Maintenant on a rien sans rien. Un IDE confortable, des VM pour tester, ça fait forcément des ressources de bouffées sur la machine...

Mickael BARON a dit…

Article très clair, merci pour les liens sur les ressources GIT.

Tu parles essentiellement dans ton article de la partie locale.

Qu'en est-il de la partie serveur ? de la configuration des droits ? de l'intégration avec un Apache HTTP par exemple, ... as-tu eu le temps de tester ?

Nicolas De Loof a dit…

Je n'ai pas du tout vu la partie serveur, en dehors de GitHub. Il faut déjà pour cela que je convainque mes collègues de passer à Git, alors on en est pas là...
Git est déjà très intéressant en utilisation purement locale, pour une utilisation "complète" il ouvre de nombreuses opportunités pour changer la gestion du workflow projet : développement // des items et sélection lors de la génération d'une livraison, qualification des devs par un "despot" qui pull ou non selon ses critères d'acceptation, etc.

Unknown a dit…

Ca a l'air sympa Git.
Va falloir que tu me montres ça à ton retour de congés ;-)