Git par la pratique

Lors de mon arrivée sur divers projets, je me suis souvent heurtée à des gestions de Git différentes les unes des autres. Pourtant, elles étaient toutes plus ou moins intéressantes.

On a dû toutes une fois vivre cela : soit l’organisation du Git est optimisée, soit rien ne va et la puissance du versioning n’est pas utilisée. Dans ce dernier cas, l’envie d’améliorer l’utilisation de Git est confrontée aux retours négatifs des autres développeurs. Les sujets qui contrebalancent cette envie sont souvent importants, comme la gestion de la dette technique ou le manque de test unitaire. Or, la mauvaise utilisation de Git peut augmenter la difficulté de leur traitement de façon exponentielle.

LES TRUCS ET ASTUCES

Il existe quelques astuces dont la mise en place n’est pas chronophage pour les développeurs de toute équipe. Ce changement de pratique qui doit être accepté par tout le monde pour mener à une utilisation optimisée de Git.

La première astuce est la plus simple à mettre en place. Il s’agit de définir une convention de nommage sur les commits. Étant donné qu’ils seront gardés durant toute la vie du projet, il faut les rendre compréhensibles et concis. Je conseille d’utiliser la convention de nommage mis en place par Karma  qui se résume à cette structure : <type>(<scope>): <sujet>. Le scope correspond soit au composant modifié soit, dans certains, cas au numéro de la tâche réalisée. Le sujet est une description succincte de la tâche réalisée. Le type, quant à lui, correspond à ce qui a été réalisé dans le commit :

  • feat : une fonctionnalité pour l’utilisateur ;
  • fix : une rapide correction de bug ;
  • refactor : une modification d’une partie du code pour optimisation ;
  • test : ajout ou modification de test dans l’application ;
  • docs : changement dans la documentation ;
  • style : mise en forme de code, oubli de point-virgule ;
  • chore : modification répétitive de code ;
  • build : changements qui affectent le système de build ou des dépendances externes (npm, make…) ;
  • ci : changements concernant les fichiers et scripts d’intégration ou de configuration (Travis, Ansible, BrowserStack…) ;
  • perf : amélioration des performances.

Les buts de cette convention est de simplifier la navigation dans l’historique Git et de pouvoir en générer facilement un changelog. En effet, les commits ayant tous la même structure, il est plus aisé de retrouver le dernier fix ou le dernier refactor qui aurait pu engendrer des régressions. Cette astuce permet aussi, lors d’un git blame, de comprendre plus rapidement pourquoi la modification a été faite et dans quel but, grâce à la description du sujet traité. Si vous ne connaissez pas la commande git blame elle permet de savoir qui a fait la modification, quand et dans quel commit.

La deuxième astuce, pour récupérer les modifications d’une autre branche, consiste à utiliser la fonction rebase au lieu de la fonction merge. Dans la majorité des cas, les développeurs préfèrent utiliser le merge car la gestion des conflits est faite une seule fois et il y a moins de chance de perdre son code. Le souci lié à cela est que l’on perd le principe d’une branche qui ne contient que notre travail. En effet, en « mergeant » une autre branche, disons develop dans notre branche de travail, on incorpore les commits de develop dans celle-ci, alors que ce n’est pas réellement ce que l’on souhaite. En « rebasant » notre branche sur develop, on accède aux modifications faites sur celle-ci, sans pour autant, les incorporer à notre branche.

De plus, une fois le merge fait dans la branche souhaitée, on perd la linéarité de l’historique de Git. En regardant les deux figures ci-dessus, on se rend compte que l’image de la figure 2 est beaucoup plus lisible que celle de la figure 3. Sur la figure 2, en jetant un coup d’œil à la liste des commits sur l’arbre, on comprend facilement le travail qui a été réalisé. 

A l’inverse, pour comprendre le travail réalisé sur la figure 3, il faut étudier l’arbre  pour trouver quelle branche est « mergée » dans laquelle, pourquoi telle branche a été fusionnée avec celle-ci, etc. Cette étude devient vite une importante perte de temps lors du développement de fonctionnalité.

Lors d’un bug en production, il est beaucoup plus simple de relivrer l’application si on a fait des rebases que si l’on a fait des merges. En effet, comme on peut le voir sur les images précédentes d’arbres Git, la liste des commits sera beaucoup plus simple à analyser. Ainsi, on trouvera assez facilement le commit qui a créé la régression ou le bug. On pourra donc facilement revenir en arrière. Si au contraire on utilise des merges, il faudra démêler l’entremêlement de branches pour savoir quel commit a entraîné la régression.

Les différentes raisons, évoquées précédemment, poussent à utiliser la fonctionnalité de rebase sur Git. Cette dernière permet de garder notre branche de travail dans son périmètre d’utilisation. Elle permet aussi de modifier la base de notre branche. Ainsi, on peut se mettre sur la branche d’un collègue pour récupérer des modifications en cours de développement. La fonctionnalité de rebase peut être utilisée à l’infini et ainsi permettre aux différents développeurs d’un projet de récupérer des modifications sur n’importe quelle branche du dépôt Git.

 

LES COMMANDES INDISPENSABLES

Afin de mettre en place ces différentes astuces, il faut connaître plusieurs commandes Git indispensables. Elles vous permettront de comprendre l’utilisation simplifiée de Git dans votre IDE. Souvent, les développeurs préfèrent optimiser leur utilisation de Git au strict minimum, alors que l’on peut faire tellement plus avec deux ou trois commandes Git supplémentaires. Je pense qu’avec les commandes Git ci-dessous, on peut gérer ses branches et ses commits pour avoir un résultat beaucoup plus satisfaisant, tout en conservant la cohérence de l’arbre.

Voici donc les commandes que j’utilise le plus :

  • git pull origin {branchName} {options}
  • git push origin {branchName} {options}
  • git add {option}
  • git status
  • git commit –m {message} ou git commit –amend
  • git rebase origin/{branchName} –i
  • git log

Les quatre premières commandes sont les plus connues et les plus utilisées sur Git. Je ne m’attarderai pas dessus. La cinquième est une commande aussi très utilisée, seulement ses options sont souvent ignorées. Pour ma part j’utilise beaucoup le git commit –amend. Cette commande Git permet d’ajouter vos dernières modifications au dernier commit ajouté à la branche courante. Attention, une fois cette commande faite, il ne faut surtout pas oublier d’avoir recours à git push -force, sinon vous aurez deux commits sur votre branche au lieu d’un. Je l’utilise régulièrement, en fin de journée, pour mettre à jour mon code sur le dépôt distant du projet. En faisant cela, on évite une situation que j’ai déjà vécue : la perte de tout mon travail si mon ordinateur ne redémarre pas le lendemain.

La commande git rebase origin/{branchName} -i, présentée ci-dessus, ne devrait plus avoir de secret pour vous, à part peut-être l’option interactive. Cette option permet, avant de commencer le rebase, de pouvoir choisir les commits que vous voulez embarquer dans celui-ci. Celle-ci est indispensable lorsque vous changez la racine de votre branche. En réalisant cela, il est possible que vous embarquiez des commits qui ne sont pas les vôtres mais qui ne sont pas présents dans la nouvelle branche. Si l’option est activée, un éditeur (nano, vim, …) identique à celui de la figure 4 s’ouvrira, et vous pourrez alors choisir les commits à prendre en compte. Dans le cas on l’éditeur que vous utilisez ne vous convient pas il est toujours possible de le changer avec git config –global core.editor <emacs/nano/vim…>.

Dans mon utilisation quotidienne, j’active toujours cette option. Elle me permet de savoir exactement quel commit j’embarque dans mon rebase mais aussi de maîtriser de A à Z la réalisation de celui-ci.

La commande git log est pour moi la plus importante et à la fois la plus simple à utiliser. Elle permet de voir l’arbre de notre branche à un instant T, de savoir quel est le dernier commit poussé, s’il est sur le dépôt distant ou local… Grâce à cette commande, je suis en mesure de vérifier si j’ai réussi mon rebase, ou juste avant de le commencer, de vérifier sur quelle branche je suis basée. Elle me permet également lorsque j’arrive sur le poste d’autres développeurs de savoir dans quel état est leur arbre Git.

LE MOT DE LA FIN

En vous apportant ces conseils, je n’affirme pas détenir la vérité absolue. Je suis la première convaincue que je rencontrerai au fil de ma carrière de nouvelles utilisations de Git et que ma vision évoluera. J’ai parcouru un long chemin depuis les premiers projets où je n’appliquais pas moi-même, ou que très peu, les conseils que je vous transmets aujourd’hui. Cette vision a pu être acquise en participant à plusieurs projets avec des leaders techniques différents. Ils avaient chacun des manières de travailler différentes. C’est maintenant à moi de vous transmettre ce que j’ai pu apprendre, et d’essayer d’inciter toujours plus de monde à exploiter au maximum les capacités de Git.

Article paru dans Programmez! n°236 /Développeuses, le code est à vous !