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é logs 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 le stash Git a été utilisé dans le dépôt.

Nous avons discuté de git reflog à un niveau supérieur sur la page Réécriture de 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 avec git reflog, etc.

Utilisation basique

Le cas d'usage Reflog le plus basic appelle :

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éécriture de l'historique pour découvrir un autre exemple d'accès reflog habituel.

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 à git ref est name@{qualifier}. Outre les réfs HEAD, il est également possible de se référer à 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, changez le nom de cette branche en 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}

Exécuté, cet exemple de code affichera la sortie Git diff 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 token 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 qualificatifs 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 qualificatifs temporels peuvent être transmises à d'autres commandes git.

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

Cet exemple comparera la branche master à 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 équivalent à 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 log du <refid> passé.

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. Cette sous-commande est généralement utilisée par Git en interne, pas par les utilisateurs finaux. Le passage d'une option -n ou --dry-run à git reflog expire effectuera un « dry run » qui indiquera 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 transférant 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 rebasage 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 master en exécutant…

git rebase -i origin/master

Durant le rebase, nous marquons les commits à squasher avec la sous-commande de rebase s. Durant le rebase, nous squashons quelques commits dans le commit « quelques changements WIP » 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 squashing n'apparaissent plus. Que faire si nous souhaitons effectuer une opération sur les commits squashés ? Peut-être pour enlever leurs changements 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 « certains changements WIP ». 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 de réinitialisation déplacera HEAD vers le commit où « certains changements WIP » a été ajouté, restaurant essentiellement les autres commits squashés.

Summary

Dans ce tutoriel, nous avons discuté de la commande git reflog. Voici quelques points importants que nous avons couverts !

  • Comment voir le reflog pour des branches spécifiques
  • Comment annuler une commande git rebase avec le reflog
  • Comment spécifier et afficher les entrées de 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