Squashons avec GIT

Dans ce premier article consacré aux astuces GIT, je vais vous parler d’une technique permettant de regrouper un ensemble de commits en un seul.

Contexte

Après avoir reçu quelques commentaires sur mon code suite à une Pull Request sur le github du PropelBundle, j’ai du effectuer des modifications, faire un commit de ses dernières et re-pusher le tout. La Pull Request a donc été mise à jour et ces nouveaux commits se sont ajoutés au premier.

Seulement, par souci de visibilité, tant sur la Pull Request que sur l’historique final, on m’a demandé de squasher mes commits.

Sur le moment je me suis dis WTF!!!
Après une petite recherche sur notre ami Google, j’ai compris ce qu’on me demandait. Il s’agissait de regrouper les commits en un seul.

Voilà donc comment faire pour regrouper plusieurs commit en un seul.

/!\Attention à éviter le plus possible si les commits à regrouper ont été récupéré par d’autres utilisateurs./!\

Le point de départ de cette technique est l’utilisation de git rebase. Cette commande permet de modifier l’historique du repository.

Lister les commits

Dans un premier temps, il faut déterminer les commits à regrouper.

Pour cela rien de plus simple, un simple git log et vous comptez le nombre de commit que vous voulez regrouper.

Regrouper les commits

Maintenant que le nombre de commit à regrouper a été défini, nous pouvons nous mettre au travail.

Lancez cette commande en remplaçant nb_commit par votre nombre de commit:

git rebase -i HEAD~nb_commit

Pour l’exemple, disons que nous voulons regrouper les 4 premiers commits:

$ git rebase -i HEAD~4

pick 01d1124 commit text1
pick 6340aaa commit text2
pick ebfd367 commit text3
pick 30e0ccb commit text4

# Rebase 60709da..30e0ccb onto 60709da
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

Cette commande dit à GIT que l’on veut reconstruire l’historique en utilisant les 4 derniers commits.
L’éditeur de texte, qui est ouvert suite à la commande, nous montre la liste des 4 premiers commits ainsi que plusieurs petites explications sur le fonctionnement de tout ça. Comme vous pouvez le voir sur la description, la commande squash permet de fusionner(meld) le commit dans le précédent. Il s’agit de la commande qui nous intéresse.

Et oui vous avez donc bien compris que c’est cette me commande que nous allons utiliser.

Nous allons remplacer les « pick » par des « squash » devant les commits que nous souhaitons regrouper :

pick 01d1124 commit text1
squash 6340aaa commit text2
squash ebfd367 commit text3
squash 30e0ccb commit text4

Nous disons donc à GIT de fusionner tous les commits dans le premier. Une fois que la modification des lignes est faite, il suffit de sauvegarder et de fermer l’éditeur. Un autre éditeur de texte va alors s’ouvrir pour vous permettre de modifier le message du commit nouvellement crée:

# This is a combination of 4 commits.
# The first commit's message is:
commit text1

# This is the 2nd commit message:

commit text2

# This is the 3rd commit message:

commit text3

# This is the 4th commit message:

commit text4

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Explicit paths specified without -i nor -o; assuming --only paths...
# Not currently on any branch.
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#	new file:   file1
#	modified:   file2
#	modified:   file3
#	modified:   file3
#

Cette fois, il suffit de choisir le message du commit nouvellement crée, pour moi c’est commenter les commits que j’ai regroupé pour n’avoir que le message du premier commit mais chacun fait comme il l’entend. Lorsque le message du commit correspond à ce que vous désirez, sauvegardez et quittez l’éditeur pour que GIT crée le nouveau commit en lieu et place des 4 commits.
Un message du style « Successfully rebased and updated refs/heads/master. » devrait vous signifier la réussite du procédé.

Maintenant si vous faites git log, vous ne devriez plus voir qu’un seul commit à la place de 4.

Si vous avez des conflits à un moment, il suffit juste de résoudre, d’add les fichiers et de faire un git rebase –continue.

Lorsque j’ai effectué cette manipulation, GIT m’indiquait, à juste titre, que mon repository local divergeait du repository distant. J’avais effectivement pushé des commits mais comme personne ne les avait récupérés, c’était bon.
Pour reconstruire l’historique du repository distant, j’ai donc forcé le push en faisant git push -f.

Le mot de la fin

Cette méthode peut bien sûr avoir d’autres utilités. Dans mon cas, j’ai du l’utiliser pour n’avoir qu’un seul commit à la fin du développement.

N’hésitez pas à donner votre avis sur ce sujet.

 

Serv-Tech

 

One thought on “Squashons avec GIT

Laisser un commentaire