Git 🌙
Chapters â–Ÿ 2nd Edition

7.3 Utilitaires Git - Remisage et nettoyage

Remisage et nettoyage

Souvent, lorsque vous avez travaillé sur une partie de votre projet, les choses sont dans un état instable mais vous voulez changer de branche pour travailler momentanément sur autre chose. Le problÚme est que vous ne voulez pas valider un travail à moitié fait seulement pour pouvoir y revenir plus tard. La réponse à cette problématique est la commande git stash.

Remiser prend l’état en cours de votre rĂ©pertoire de travail, c’est-Ă -dire les fichiers modifiĂ©s et l’index, et l’enregistre dans la pile des modifications non finies que vous pouvez rĂ©-appliquer Ă  n’importe quel moment.

Note
Migrer vers git stash push

Courant fin octobre 2017, il y a eu de longues discussions sur la liste de diffusion Git, pour rendre obsolĂšte la commande git stash save au profit de l’alternative existante git stash push. La raison principale en est que git stash push introduit une option pour remiser des specificateurs de chemin sĂ©lectionnĂ©s, ce que git stash save ne sait pas faire.

git stash save ne va disparaĂźtre immĂ©diatement, donc ne vous inquiĂ©tez pas. NĂ©anmoins il serait prĂ©fĂ©rable de commencer Ă  migrer vers l’alternative push pour bĂ©nĂ©ficier des nouvelles fonctionnalitĂ©s.

Remiser votre travail

Pour dĂ©montrer cette possibilitĂ©, allez dans votre projet et commencez Ă  travailler sur quelques fichiers et indexez l’un de ces changements. Si vous exĂ©cutez git status, vous pouvez voir votre Ă©tat modifié :

$ git status
Modifications qui seront validées :
  (utilisez "git reset HEAD <fichier>..." pour désindexer)

	modifié :   index.html

Modifications qui ne seront pas validées :
  (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé)
  (utilisez "git checkout -- <fichier>..." pour annuler les modifications dans la copie de travail)

	modifié :   lib/simplegit.rb

À ce moment-lĂ , vous voulez changer de branche, mais vous ne voulez pas encore valider ce travail ; vous allez donc remiser vos modifications. Pour crĂ©er une nouvelle remise sur votre pile, exĂ©cutez git stash :

$ git stash
Saved working directory and index state \
  "WIP on master: 049d078 added the index file"
HEAD is now at 049d078 added the index file
(To restore them type "git stash apply")

Votre répertoire de travail est propre :

$ git status
Sur la branche master
rien Ă  valider, la copie de travail est propre

À ce moment, vous pouvez facilement changer de branche et travailler autre part ; vos modifications sont conservĂ©es dans votre pile. Pour voir quelles remises vous avez sauvegardĂ©es, vous pouvez utiliser la commande git stash list :

$ git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051... Revert "added file_size"
stash@{2}: WIP on master: 21d80a5... added number to log

Dans ce cas, deux remises ont Ă©tĂ© crĂ©Ă©es prĂ©cĂ©demment, vous avez donc accĂšs Ă  trois travaux remisĂ©s diffĂ©rents. Vous pouvez rĂ©-appliquer celui que vous venez juste de remiser en utilisant la commande affichĂ©e dans la sortie d’aide de la premiĂšre commande de remise : git stash apply. Si vous voulez appliquer une remise plus ancienne, vous pouvez la spĂ©cifier en la nommant, comme ceci : git stash apply stash@{2}. Si vous ne spĂ©cifiez pas une remise, Git prĂ©sume que vous voulez la remise la plus rĂ©cente et essaye de l’appliquer.

$ git stash apply
Sur la branche master
Modifications qui ne seront pas validées :
  (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé)
  (utilisez "git checkout -- <fichier>..." pour annuler les modifications dans la copie de travail)

     modified:   index.html
     modified:   lib/simplegit.rb

no changes added to commit (use "git add" and/or "git commit -a")

Vous pouvez observer que Git remodifie les fichiers non validĂ©s lorsque vous avez crĂ©Ă© la remise. Dans ce cas, vous aviez un rĂ©pertoire de travail propre lorsque vous avez essayĂ© d’appliquer la remise et vous l’avez fait sur la mĂȘme branche que celle oĂč vous l’aviez crĂ©Ă©e ; mais avoir un rĂ©pertoire de travail propre et l’appliquer sur la mĂȘme branche n’est pas nĂ©cessaire pour rĂ©ussir Ă  appliquer une remise. Vous pouvez trĂšs bien crĂ©er une remise sur une branche, changer de branche et essayer d’appliquer ces modifications. Vous pouvez mĂȘme avoir des fichiers modifiĂ©s et non validĂ©s dans votre rĂ©pertoire de travail quand vous appliquez une remise, Git vous indique les conflits de fusions si quoi que ce soit ne s’applique pas proprement.

Par dĂ©faut, les modifications de vos fichiers sont rĂ©-appliquĂ©es, mais pas les indexations. Pour cela, vous devez exĂ©cuter la commande git stash apply avec l’option --index pour demander Ă  Git d’essayer de rĂ©-appliquer les modifications de votre index. Si vous exĂ©cutez cela Ă  la place de la commande prĂ©cĂ©dente, vous vous retrouvez dans la position d’origine prĂ©cĂ©dent la remise :

$ git stash apply --index
Sur la branche master
Modifications qui seront validées :
  (utilisez "git reset HEAD <fichier>..." pour désindexer)

     modifié :   index.html

Modifications qui ne seront pas validées :
  (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé)
  (utilisez "git checkout -- <fichier>..." pour annuler les modifications dans la copie de travail)

     modified:   lib/simplegit.rb

L’option apply essaye seulement d’appliquer le travail remisĂ©, vous aurez toujours la remise dans votre pile. Pour la supprimer, vous pouvez exĂ©cuter git stash drop avec le nom de la remise Ă  supprimer :

$ git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051... Revert "added file_size"
stash@{2}: WIP on master: 21d80a5... added number to log
$ git stash drop stash@{0}
Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)

Vous pouvez également exécuter git stash pop pour appliquer et supprimer immédiatement la remise de votre pile.

Remisage créatif

Il existe des variantes de remisages qui peuvent s’avĂ©rer utiles. La premiĂšre option assez populaire est l’option --keep-index de la commande stash save. Elle indique Ă  Git de ne pas seulement inclure le contenu indexĂ© dans le remisage en cours de crĂ©ation, mais aussi de le laisser en place dans l’index.

$ git status -s
M  index.html
 M lib/simplegit.rb

$ git stash --keep-index
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file

$ git status -s
M  index.html

Une autre option utile de stash est la possibilitĂ© de remiser les fichiers non suivis aussi bien que les fichiers suivis. Par dĂ©faut, git stash ne sauve que les fichiers qui sont dĂ©jĂ  suivis ou indexĂ©s. Si vous spĂ©cifiez l’option --include-untracked ou -u, Git remisera aussi les fichiers non-suivis du rĂ©pertoire de travail. Cependant, inclure les fichiers non-suivis dans le remisage n’inclura pas les fichiers explicitement ignorĂ©s ; pour ajouter aussi les fichiers ignorĂ©s, utilisez --all (ou juste -a).

$ git status -s
M  index.html
 M lib/simplegit.rb
?? new-file.txt

$ git stash -u
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file

$ git status -s
$

Enfin, si vous ajoutez l’option --patch, Git ne remisera pas tout le contenu modifiĂ©, mais vous invitera Ă  sĂ©lectionner interactivement les modifications que vous souhaitez remiser et celles que vous souhaitez conserver dans la copie de travail.

$ git stash --patch
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 66d332e..8bb5674 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -16,6 +16,10 @@ class SimpleGit
         return `#{git_cmd} 2>&1`.chomp
       end
     end
+
+    def show(treeish = 'master')
+      command("git show #{treeish}")
+    end

 end
 test
Stash this hunk [y,n,q,a,d,/,e,?]? y

Saved working directory and index state WIP on master: 1b65b17 added the index file

Créer une branche depuis une remise

Si vous remisez votre travail, et l’oubliez pendant un temps en continuant sur la branche oĂč vous avez crĂ©Ă© la remise, vous pouvez avoir un problĂšme en rĂ©-appliquant le travail. Si l’application de la remise essaye de modifier un fichier que vous avez modifiĂ© depuis, vous allez obtenir des conflits de fusion et vous devrez essayer de les rĂ©soudre. Si vous voulez un moyen plus facile de tester une nouvelle fois les modifications remisĂ©es, vous pouvez exĂ©cuter git stash branch <nouveau-nom-de-branche> qui crĂ©era une nouvelle branche Ă  votre place, rĂ©cupĂ©rant le commit oĂč vous Ă©tiez lorsque vous avez crĂ©Ă© la remise, rĂ©-appliquera votre travail dedans, et supprimera finalement votre remise si cela a rĂ©ussi :

$ git stash branch testchanges
M	index.html
M	lib/simplegit.rb
Basculement sur la nouvelle branche 'testchanges'
Sur la branche testchanges
Modifications qui seront validées :
  (utilisez "git reset HEAD <fichier>..." pour désindexer)

     modifié :   index.html

Modifications qui ne seront pas validées :
  (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé)
  (utilisez "git checkout -- <fichier>..." pour annuler les modifications dans la copie de travail)

     modified:   lib/simplegit.rb

refs/stash@{0} supprimé (f0dfc4d5dc332d1cee34a634182e168c4efc3359)

C’est un bon raccourci pour rĂ©cupĂ©rer facilement du travail remisĂ© et pouvoir travailler dessus dans une nouvelle branche.

Nettoyer son répertoire de travail

Enfin, vous pouvez souhaiter ne pas remiser certains fichiers de votre rĂ©pertoire de travail, mais simplement vous en dĂ©barrasser. La commande git clean s’en chargera pour vous.

Le besoin le plus commun pourra ĂȘtre d’éliminer les scories gĂ©nĂ©rĂ©es par les fusions ou les outils externes ou d’éliminer les artefacts de compilation pour pouvoir relancer une compilation propre.

Faites nĂ©anmoins trĂšs attention avec cette commande car elle supprime des fichiers non-suivis de votre rĂ©pertoire de travail. Si vous changez d’avis, il est souvent impossible de rĂ©cupĂ©rer aprĂšs coup le contenu de ces fichiers. Une option plus sĂ©curisĂ©e consiste Ă  lancer git stash --all pour tout sauvegarder dans une remise.

En supposant que vous souhaitez rĂ©ellement Ă©liminer les scories et nettoyer votre rĂ©pertoire de travail, vous pouvez lancer git clean. Pour supprimer tous les fichiers non-suivis, vous pouvez lancer git clean -f -d, qui effacera aussi tout sous-rĂ©pertoire vide. L’option -f signifie « force », soit « fais-le rĂ©ellement ».

Si vous souhaitez visualiser ce qui serait fait, vous pouvez lancer la commande avec l’option -n qui signifie « fais-le Ă  blanc et montre-moi ce qui serait supprimé ».

$ git clean -d -n
Supprimerait test.o
Supprimerait tmp/

Par dĂ©faut, la commande git clean ne va supprimer que les fichiers non-suivis qui ne sont pas ignorĂ©s. Tout fichier qui correspond Ă  un motif de votre fichier .gitignore ou tout autre fichier similaire ne sera pas supprimĂ©. Si vous souhaitez supprimer aussi ces fichiers, comme par exemple les fichiers .o gĂ©nĂ©rĂ© par un compilateur pour faire une compilation totale, vous pouvez ajouter l’option -x Ă  la commande de nettoyage.

$ git status -s
 M lib/simplegit.rb
?? build.TMP
?? tmp/

$ git clean -n -d
Supprimerait build.TMP
Supprimerait tmp/

$ git clean -n -d -x
Supprimerait build.TMP
Supprimerait test.o
Supprimerait tmp/

Si vous ne savez pas ce que la commande git clean va effectivement supprimer, lancez-la une premiĂšre fois avec -n par sĂ©curitĂ© avant de transformer le -n en -f et nettoyer dĂ©finitivement. Un autre choix pour s’assurer de ce qui va ĂȘtre effacĂ© consiste Ă  lancer la commande avec l’option -i ou --interactive.

La commande sera lancée en mode interactif.

$ git clean -x -i
Supprimerait les éléments suivants :
  build.TMP  test.o
*** Commandes ***
    1: clean                2: filter by pattern    3: select by numbers    4: ask each             5: quit
    6: help
Et maintenant ?>

De cette maniÚre, vous pouvez détailler chaque fichier individuellement ou spécifier un motif pour la suppression interactive.

Note

Il y a des situations tordues oĂč vous aurez besoin d’ĂȘtre plus impĂ©ratif pour demander Ă  Git de nettoyer votre rĂ©pertoire de travail. S’il vous arrive d’ĂȘtre dans un rĂ©pertoire de travail sous lequel vous avez copiĂ© ou clonĂ© d’autres dĂ©pĂŽts Git (peut-ĂȘtre en tant que sous-modules), mĂȘme git clean -fd refusera de supprimer ces rĂ©pertoires. Dans de tels cas, vous devez ajouter un deuxiĂšme drapeau -f pour insister.

scroll-to-top