Git prune
La commande git prune
est un utilitaire de nettoyage interne qui nettoie les objets Git inaccessibles ou « orphelins ». Les objets inaccessibles sont ceux auxquels aucune réf ne peut accéder. Tout commit qui n'est pas accessible via une branche ou un tag est considéré comme inaccessible. La commande git prune
n'est généralement pas exécutée directement. La commande prune est considérée comme une commande garbage collection. Il s'agit d'une commande enfant de la commande git gc.
Présentation de git prune
Afin de comprendre les effets de git prune
, nous devons simuler un scénario dans lequel un commit devient inaccessible. Voici une séquence d'exécutions de ligne de commande qui simulera cette expérience.
~ $ cd git-prune-demo/
~/git-prune-demo $ git init .
Initialized empty Git repository in /Users/kev/Dropbox/git-prune-demo/.git/
~/git-prune-demo $ echo "hello git prune" > hello.txt
~/git-prune-demo $ git add hello.txt
~/git-prune-demo $ git commit -am "added hello.txt"
La séquence de commandes précédente créera un dépôt dans un répertoire nommé git-prune-demo
. Un commit composé d'un nouveau fichier hello.text
est ajouté au dépôt avec le contenu de base de « hello git prune ». Nous allons ensuite modifier hello.txt
et créer un commit à partir de ces modifications.
~/git-prune-demo $ echo "this is second line txt" >> hello.txt
~/git-prune-demo $ cat hello.txt
hello git prune
this is second line txt
~/git-prune-demo $ git commit -am "added another line to hello.txt"
[main 5178bec] added another line to hello.txt
1 file changed, 1 insertion(+)
Ressource connexe
Comment déplacer un dépôt Git complet
DÉCOUVRIR LA SOLUTION
Découvrir Git avec Bitbucket Cloud
Nous avons maintenant un historique de 2 commits dans ce dépôt de démo. Nous pouvons le vérifier en utilisant git log
:
~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 14:49:59 2018 -0700
added another line to hello.txt
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 09:43:41 2018 -0700
added hello.txt
La sortie de git log affiche les 2 commits et les messages de commit correspondants concernant les modifications apportées à hello.txt
.L'étape suivante consiste à rendre l'un des commits inaccessible.Pour ce faire, nous utiliserons la commande git reset. Nous réinitialisons l'état du dépôt sur le premier commit, « added hello.txt ».
~/git-prune-demo $ git reset --hard 994b122045cf4bf0b97139231b4dd52ea2643c7e
HEAD is now at 994b122 added hello.txt
Si maintenant nous utilisons git log
pour examiner l'état du dépôt, nous pouvons voir que nous n'avons qu'un seul commit.
~/git-prune-demo $ git log
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 09:43:41 2018 -0700
added hello.txt
Le dépôt de démo est maintenant dans un état qui contient un commit détaché. Le deuxième commit que nous avons fait avec le message « added another line to hello.txt » n'est plus affiché dans la sortie de git log
, mais il est maintenant détachéOn pourrait croire que nous avons perdu ou supprimé le commit, mais Git est très strict sur le fait de ne pas supprimer l'historique.Nous pouvons confirmer qu'il est toujours disponible, mais qu'il est détaché, en utilisant git checkout
pour y accéder directement :
~/git-prune-demo $ git checkout 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Note: checking out '5178becc2ca965e1728554ce1cb8de2f2c2370b1'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at 5178bec... added another line to hello.txt
~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 14:49:59 2018 -0700
added another line to hello.txt
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 09:43:41 2018 -0700
added hello.txt
Lorsque nous faisons un check-out du commit détaché, Git est assez attentionné pour nous fournir un message détaillé expliquant que nous sommes dans un état détaché. Si nous examinons le journal, nous pouvons voir que le commit « added another line to hello.txt » est maintenant de retour dans la sortie du journal ! Maintenant que nous savons que le dépôt est dans un bon état de simulation avec un commit détaché, nous pouvons nous entraîner à utiliser git prune
. Revenons tout d'abord à la branche main
à l'aide de git checkout
.
~/git-prune-demo $ git checkout main
Warning: you are leaving 1 commit behind, not connected to
any of your branches:
5178bec added another line to hello.txt
If you want to keep it by creating a new branch, this may be a good time
to do so with:
git branch <new-branch-name> 5178bec
Switched to branch 'main'
Lorsque vous revenez à la branche main via git checkout
, Git est à nouveau suffisamment attentionné pour nous faire savoir que nous laissons un commit détaché derrière nous. Il est maintenant temps de nettoyer le commit détaché ! Nous allons exécuter git prune
, mais nous devons tout d'abord nous assurer de lui passer quelques options. Les options --dry-run
et --verbose
permettent d'afficher une sortie indiquant le commit à nettoyer, mais elles ne le nettoient pas.
~/git-prune-demo $ git prune --dry-run --verbose
Cette commande renverra probablement une sortie vide. Une sortie vide implique que la commande prune ne supprimera rien. Pourquoi cela se produirait-il ? Eh bien, le commit n'est probablement pas complètement détaché. Quelque part, Git conserve toujours une référence à ce dernier. C'est un excellent exemple de la raison pour laquelle la commande git prune
ne doit pas être utilisée de manière autonome en dehors de git gc
. Il s'agit également d'un bon exemple qui démontre qu'il est difficile de perdre totalement des données avec Git.
Il est fort probable que Git stocke une référence à notre commit détaché dans le reflog. Nous pouvons enquêter en lançant git reflog. Vous devriez voir une sortie décrivant la séquence des actions que nous avons menées pour arriver à ce résultat. Pour plus d'informations sur git reflog
, consultez la page git reflog. En plus de préserver l'historique dans le reflog, Git dispose de dates d'expiration internes pour déterminer quand il nettoiera les commits détachés. Encore une fois, il s'agit là d'informations d'implémentation que git gc
gère, et la commande git prune
ne devrait pas être utilisée de manière autonome.
Pour terminer notre démo de simulation de git prune
, nous devons effacer le reflog.
~/git-prune-demo $ git reflog expire --expire=now --expire-unreachable=now --all
La commande ci-dessus forcera l'expiration de toutes les entrées du reflog qui sont plus anciennes que maintenant. Il s'agit d'une commande brutale et dangereuse que vous ne devriez jamais avoir à lancer en tant qu'utilisateur occasionnel de Git. Nous exécutons cette commande pour démontrer la réussite de git prune
. Une fois le reflog totalement effacé, nous pouvons maintenant exécuter git prune
.
~/git-prune-demo $ git prune --dry-run --verbose --expire=now
1782293bdfac16b5408420c5cb0c9a22ddbdd985 blob
5178becc2ca965e1728554ce1cb8de2f2c2370b1 commit
a1b3b83440d2aa956ad6482535cbd121510a3280 commit
f91c3433eae245767b9cd5bdb46cd127ed38df26 tree
Cette commande doit afficher une liste de références d'objets Git SHA qui ressemble à la sortie ci-dessus.
Utilisation
La commande git prune
propose une courte liste d'options que nous avons abordées dans la section de présentation.
-n --dry-run
N'exécutez pas la commande prune. Affichez uniquement une sortie indiquant ce qu'elle fera.
-v --verbose
Affichez la sortie de tous les objets et de toutes les actions effectuées avec la commande prune.
--progress
Permet d'afficher la sortie qui indique la progression de la commande prune.
--expire <time>
Permet de forcer l'expiration des objets qui ont dépassé la valeur de
<head>…
La spécification d'un préservera toutes les options de cette réf head.
Discussion
Quelle est la différence entre git prune, git fetch --prune et git remote prune ?
Les commandes git remote prune
et git fetch --prune
font la même chose : supprimer les réfs de branches qui n'existent pas sur le remote. Cela est hautement souhaitable lorsque vous travaillez dans un workflow d'équipe dans lequel les branches distantes sont supprimées après la fusion avec main
. La deuxième commande, git fetch --prune
, se connectera au remote et récupérera le dernier état du remote avant le nettoyage. Il s'agit essentiellement d'une combinaison de commandes :
git fetch --all && git remote prune
La commande générique git prune
est complètement différente. Comme indiqué dans la section de présentation, git prune supprimera les commits détachés localement.
Comment nettoyer les branches obsolètes ?
La commande git fetch --prune
est le meilleur utilitaire pour nettoyer les branches obsolètes. Elle se connectera à un dépôt distant partagé et récupérera toutes les réfs des branches distantes. Elle supprimera ensuite les réfs distantes qui ne sont plus utilisées sur le dépôt distant.
Est-ce que git remote prune origin supprime la branche locale ?
Non, git remote prune origin
supprimera uniquement les réfs des branches distantes qui n'existent plus. Git stocke à la fois les réfs locales et distantes. Un dépôt comportera des collections de réfs local/origin
et remote/origin
. La commande git remote prune origin
ne nettoiera que les réfs présentes dans remote/origin
. Cela permet de laisser en toute sécurité le travail local dans local/origin
.
Résumé de git prune
La commande git prune
est destinée à être invoquée en tant que commande enfant de git gc
. Il est très peu probable que vous ayez un jour besoin d'invoquer git prune
dans le cadre de vos activités quotidiennes d'ingénieur logiciel. D'autres commandes sont nécessaires pour comprendre les effets de git prune
. Les commandes utilisées dans cet article sont git log
, git reflog
et git checkout
.
Partager cet article
Thème suivant
Lectures recommandées
Ajoutez ces ressources à vos favoris pour en savoir plus sur les types d'équipes DevOps, ou pour les mises à jour continues de DevOps chez Atlassian.