Organiser son historique avec Git rebase

Git effectue des commits atomiques : il applique des lots de modifications sur un contenu souvent réparti sur plusieurs fichiers, au lieu de gérer des fichiers proprement dits. Il nous invite à raisonner par lots de tâches sur un contenu et non par fichier.

Ce fonctionnement peut sembler peu intuitif si l’on a l’habitude de travailler fichier par fichier et non tâche par tâche. Mais une fois que l’on a adapté ses habitudes de travail à ce workflow, on s’aperçoit :

  • que l’on dispose d’un historique beaucoup plus facilement exploitable,
  • qu’il est beaucoup plus facile de gérer des versions concurrentes d’un même contenu dans des branches de développement parallèles.

Imaginons que vous ayez identifié deux types de modifications majeurs à apporter à votre contenu :

  • les synopsis d’un programme en ligne de commande,
  • les corrections grammaticales du texte.

Si votre contenu est réparti dans un ensemble de fichiers modulaires, vous pourriez décider d’apporter en même temps les deux types de modifications dans chaque fichier un à un. Pour répartir le travail sur un groupe de rédacteurs techniques, il vous suffit d’allouer à chacun un lot de fichiers.

Ce workflow n’est pas le plus adapté à Git. Si vous utilisez ce système de gestion de versions, il est préférable de diviser le travail en deux lots de tâches, que l’on appelera synopsis et texte, appliqués concurremment sur tous les fichiers.

Les contraintes de production vous obligeront souvent à scinder ces deux lots de tâches en sous-lots, que vous serez obligé de faire alterner.

Vous committez chaque sous-lot à chaque fois qu’il est achevé. Votre historique de commit ressemble alors au schéma suivant :

_images/git-rebase-commits.png

Historique Git

Lorsque vous placerez vos commits sur le dépôt central, certains commits représenteront une étape intermédiaire de l’une des tâches. Votre historique et vos branches seront donc plus difficiles à exploiter. D’autant plus que les tâches inachevées alternent. Pour en récupérer une seule, il faudra donc choisir soigneusement les commits via la commande git cherry-pick.

Heureusement, Git vous permet de réorganiser facilement vos commits avant de les partager. Lancez la commande git rebase -i HEAD~5 pour réorganiser les commits, de la version en cours aux cinq précédentes, par exemple.

Attention

La commande rebase est potentiellement destructive ; veillez à sauvegarder votre espace de travail, répertoire .git compris, avant de l’exécuter, sous risque de perdre des données ; vous pouvez également créer une branche de sauvegarde provisoire.

Vous pouvez alors réécrire l’histoire pour proposer à vos collaborateurs un commit pour chaque tâche réalisée en son entier, comme sur le schéma suivant :

_images/git-rebase-commits-2.png

Historique Git

Les commits ont tout d’abord été regroupés par type sur la flèche du temps de Git, puis fusionnés.

Note

Si vous avez effectué simultanément les deux tâches sur un ou plusieurs fichiers, pas de panique : grâce à la commande git add -p vous pouvez répartir vos modifications imbriquées sur les commits idoines. Lorsque vous lancez git status, vous vous apercevez alors que vos fichiers sont à la fois prêts et non prêts à être commités : il y a deux états des fichiers, chaque état représentant un stade partiel de votre travail et la somme des deux représentant la totalité des modifications que vous avez apportées.

Évidemment, vous n’avez plus accès aux commits intermédiaires, mais c’est ce que vous souhaitiez : chaque commit unique représente un état cohérent de votre contenu.

Ce workflow facilite également le travail d’équipe : vous pouvez confier ces tâches à deux membres différents de votre équipe, chacun travaillant dans son espace local. Les modifications du premier sont ensuite fusionnées avec celles du second dans son espace local via des patches. Enfin, les commits sont refactorisés avant de les placer sur le dépôt central.

Important

Moins vous réorganiserez vos commits (surtout chronologiquement), plus le risque de devoir corriger manuellement des conflits sera faible. Autrement dit, git rebase ne doit pas être une excuse pour ne pas planifier rationnellement son travail.