git reflog

Cette page contient une discussion détaillée sur la commande git reflog. Git garde une trace des mises à jour sur la pointe des branches à l'aide d'un mécanisme appelé journaux de référence ou « reflog ». De nombreuses commandes Git acceptent un paramètre pour spécifier une référence ou « réf », qui est un pointeur vers un commit. Quelques exemples communs :

  • git checkout
  • git reset
  • git merge

Les reflogs permettent de suivre le moment où des réfs Git ont été mises à jour dans le dépôt local. Outre les reflogs de pointe de branche, un reflog spécial est conservé pour le stash Git. Les reflogs sont stockés dans des répertoires sous le répertoire .git du dépôt local. Les répertoires git reflog se trouvent ici : .git/logs/refs/heads/., .git/logs/HEAD et .git/logs/refs/stash si la commande git stash a été utilisée dans le dépôt.

Nous avons parlé de git reflog à un niveau supérieur sur la page Réécrire l'historique. Ce document couvrira : les options de configuration étendues de git reflog, les cas d'usage et inconvénients habituels de git reflog, comment annuler des changements grâce à git reflog, et bien plus encore.

Utilisation basique

Voici l'appel le plus basique de la commande reflog :

 git reflog 

Il s'agit essentiellement d'un raccourci équivalent à :

 git reflog show HEAD 

Cela génère le reflog HEAD. Vous devriez voir une sortie similaire à :

 eff544f HEAD@{0}: commit: migrate existing content bf871fd HEAD@{1}: commit: Add Git Reflog outline 9a4491f HEAD@{2}: checkout: moving from master to git_reflog 9a4491f HEAD@{3}: checkout: moving from Git_Config to master 39b159a HEAD@{4}: commit: expand on git context 9b3aa71 HEAD@{5}: commit: more color clarification f34388b HEAD@{6}: commit: expand on color support 9962aed HEAD@{7}: commit: a git editor -> the Git editor 

Consultez la page Réécrire l'historique pour découvrir un autre exemple d'accès reflog courant.

Références reflog

Par défaut, git reflog génère le reflog de la réf HEAD. HEAD est une référence symbolique à la branche active. Les reflogs sont également disponibles pour d'autres réfs. La syntaxe permettant d'accéder à une réf Git est la suivante : name@{qualifier}. Outre les réfs HEAD, il est également possible de faire référence à d'autres branches, tags, branches distantes, ainsi qu'au stash Git.

Vous pouvez obtenir un reflog complet de toutes les réfs en exécutant :

  git reflog show --all 

Pour voir le reflog d'une branche spécifique, transmettez le nom de cette branche à git reflog show.

 git reflog show otherbranch 9a4491f otherbranch@{0}: commit: seperate articles into branch PRs 35aee4a otherbranch{1}: commit (initial): initial commit add git-init and setting-up-a-repo docs 

L'exécution de cet exemple affiche un reflog pour la branche otherbranch. L'exemple suivant suppose que vous avez stashé au préalable certains changements à l'aide de la commande git stash.

 git reflog stash 0d44de3 stash@{0}: WIP on git_reflog: c492574 flesh out intro 

Cela génèrera un reflog pour le stash Git. Les pointeurs de réf renvoyés peuvent être transmis à d'autres commandes Git :

 git diff stash@{0} otherbranch@{0} 

Lorsque vous l'exécutez, cet exemple de code affiche la sortie de diff Git comparant les changements stash@{0} avec le réf otherbranch@{0}.

Reflogs programmés

Chaque entrée de reflog est liée à un horodatage. Ces horodatages peuvent être exploités comme le jeton qualifier de la syntaxe du pointeur de réf Git. Cela permet de filtrer les reflogs Git en fonction de l'heure. Voici quelques exemples de qualificatifs de temps disponibles :

  • 1.minute.ago
  • 1.hour.ago
  • 1.day.ago
  • yesterday
  • 1.week.ago
  • 1.month.ago
  • 1.year.ago
  • 2011-05-17.09:00:00

Les qualificateurs temporels peuvent être combinés (p. ex., 1.day.2.hours.ago). En outre, les formes plurielles sont acceptées (p. ex., 5.minutes.ago).

Les réfs de qualificateurs temporels peuvent être transmises à d'autres commandes Git.

  git diff master@{0} master@{1.day.ago} 

Cet exemple compare la branche principale actuelle à celle d'il y a un jour. Cet exemple est très utile si vous souhaitez connaître les changements survenus durant une certaine période.

Sous-commandes et options de configuration

git reflog accepte quelques arguments d'ajout considérés comme des sous-commandes.

Show - git reflog show

Par défaut, show est implicitement transféré. Par exemple, la commande :

 git reflog master@{0} 

est équivalente à la commande :

 git reflog show master@{0} 

En outre, git reflog show est un alias pour git log -g --abbrev-commit --pretty=oneline. L'exécution de git reflog show affichera le journal du transmis.

Expire - git reflog expire

La sous-commande expire nettoie les entrées du reflog anciennes ou inaccessibles. La sous-commande expire est susceptible d'entraîner des pertes de données. Elle est généralement utilisée par Git en interne, et non par les utilisateurs finaux. La transmission d'une option -n ou --dry-run à git reflog expire effectue un « dry run », qui indique les entrées du reflog à supprimer, sans réellement les supprimer.

Par défaut, le délai d'expiration du reflog est de 90 jours. Une heure d'expiration peut être spécifiée en transmettant un argument de ligne de commande --expire=time à git reflog expire ou en définissant un nom de configuration Git de gc.reflogExpire.

Delete - git reflog delete

Le nom de la sous-commande delete parle de lui-même, et la commande supprime une entrée de reflog transmise. Comme pour expire, delete est susceptible d'entraîner une perte de données et est rarement appelée par les utilisateurs finaux.

Récupération de commits perdus

Git ne perd pas vraiment de contenu, même en effectuant des opérations de réécriture d'historique comme le rebase ou la modification de commit. Pour l'exemple suivant, supposons que nous avons apporté de nouveaux changements à notre dépôt. Notre git log --pretty=oneline ressemble à ceci :

 338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content 1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content c49257493a95185997c87e0bc3a9481715270086 flesh out intro eff544f986d270d7f97c77618314a06f024c7916 migrate existing content bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs 

Nous commitons ensuite ces changements et nous exécutons :

 # Apportez des changements à HEAD git commit -am "some WIP changes" 

Avec l'ajout du nouveau commit. Le journal ressemble à présent à ceci :

 37656e19d4e4f1a9b419f57850c8f1974f871b07 some WIP changes 338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content 1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content c49257493a95185997c87e0bc3a9481715270086 flesh out intro eff544f986d270d7f97c77618314a06f024c7916 migrate existing content bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs 

À ce stade, nous effectuons un rebase interactif sur la branche principale en exécutant…

 git rebase -i origin/master 

Durant le rebase, nous marquons les commits à squasher grâce à la sous-commande de rebase s. Durant le rebase, nous squashons quelques commits dans le commit « some WIP changes » le plus récent.

Étant donné que nous avons squashé les commits, la sortie git log ressemble désormais à ceci :

 40dhsoi37656e19d4e4f1a9b419f57850ch87dah987698hs some WIP changes 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs 

Si nous examinons git log à ce stade, les commits marqués pour le squash n'apparaissent plus. Que faire si nous souhaitons effectuer une opération sur l'un des commits squashés ? Peut-être pour supprimer les changements qu'il a introduits de l'historique ? C'est une occasion d'exploiter le reflog.

 git reflog 37656e1 HEAD@{0}: rebase -i (finish): returning to refs/heads/git_reflog 37656e1 HEAD@{1}: rebase -i (start): checkout origin/master 37656e1 HEAD@{2}: commit: some WIP changes 

Nous voyons qu'il existe des entrées de reflog pour le début et la fin du rebase, et avant celles-ci se trouve notre commit « some WIP changes ». Nous pouvons transmettre la réf de reflog à git reset, puis réinitialiser l'état d'un commit avant le rebase.

 git reset HEAD@{2} 

L'exécution de cette commande reset déplace HEAD vers le commit où « some WIP changes » a été ajouté, restaurant essentiellement les autres commits squashés.

Résumé

Dans ce tutoriel, nous avons parlé de la commande git reflog. Voici quelques points importants abordés :

  • Comment afficher le reflog de branches spécifiques
  • Comment annuler un git rebase à l'aide du reflog
  • Comment spécifier et afficher des entrées du reflog en fonction du temps

Nous avons brièvement expliqué que git reflog pouvait être utilisé avec d'autres commandes Git comme git checkout, git reset et git merge. Découvrez-en plus sur les pages respectives de ces commandes. Pour d'autres discussions sur les réfs et le reflog, découvrez-en plus ici.

Prêt à découvrir Git ?

Essayez ce tutoriel interactif.

Démarrez maintenant