W3docs

git reflog

Découvrez la commande git reflog, les références, les sous-commandes, les reflogs temporels et des exemples de récupération de commits.

La commande git reflog est votre filet de sécurité. Elle enregistre chaque modification apportée aux références locales — branches, HEAD et stashes — afin que vous puissiez récupérer des commits qui semblent avoir disparu après un reset, un rebase, un amend ou la suppression d'une branche. Cette page explique ce que le reflog stocke, comment lire sa syntaxe name@{n}, comment filtrer les entrées par temps, les sous-commandes disponibles et un guide complet pour récupérer des commits « perdus ».

Qu'est-ce que le reflog

Une référence (ou « ref ») est un pointeur vers un commit — HEAD, le sommet d'une branche comme main, ou une entrée de stash. De nombreuses opérations Git déplacent ces pointeurs : chaque git commit, checkout, merge, rebase ou reset met à jour l'endroit vers lequel pointe une ref. Le reflog (« journal des références ») enregistre cet historique de déplacements.

C'est important car Git ne supprime presque jamais immédiatement les commits. Lorsqu'une opération comme un hard reset ou un rebase rend un commit inaccessible depuis toute branche ou balise, l'objet commit existe toujours dans votre dépôt et le reflog conserve un pointeur vers lui. Tant que cette entrée de reflog existe, vous pouvez récupérer le commit.

git reflog

Info

Le reflog est strictement local et propre à chaque clone. Il n'est jamais poussé ni récupéré (fetch), donc un clone fraîchement créé possède un reflog vide. Si vous réécrivez l'historique et perdez un commit, vous ne pouvez le récupérer que depuis la machine où le travail a été effectué.

Utilisation de base

La forme la plus simple ne prend aucun argument :

git reflog

C'est un raccourci pour afficher le reflog de HEAD :

git reflog show HEAD

La sortie liste chaque position qu'a occupée HEAD, de la plus récente à la plus ancienne :

a32556a HEAD@{0}: commit: migrating content
ab371fd HEAD@{1}: commit: adding git reflog outline
23a491a HEAD@{2}: checkout: moving from stage to feature/solver
7b119cb HEAD@{3}: checkout: moving from feature/solver to stage
56a183a HEAD@{4}: commit: changing color scheme
7a2aa71 HEAD@{5}: commit: adding more color palettes
a56322b HEAD@{6}: commit: adding color tool package

Lisez chaque ligne en trois parties :

  • a32556a — le hash de commit abrégé vers lequel pointait HEAD.
  • HEAD@{0} — le sélecteur de reflog. @{0} correspond à la position la plus récente, @{1} à celle qui précède, et ainsi de suite, en remontant dans le temps.
  • commit: migrating content — l'action qui a déplacé la ref, accompagnée de son message.

L'étiquette d'action vous indique comment la ref a été déplacée (commit, checkout, merge, rebase -i, reset), ce qui rend le reflog lisible comme un historique étape par étape de ce que vous avez fait localement.

Références du reflog

Par défaut, git reflog affiche le reflog de HEAD, qui suit la branche actuellement extraite. Mais chaque ref conserve son propre reflog, et vous pouvez y accéder avec la syntaxe name@{qualificateur}.

Pour afficher le reflog de toutes les références à la fois :

git reflog show --all

Passez un nom de branche pour inspecter uniquement l'historique de cette branche. Ci-dessous, le reflog de test_branch :

git reflog show test_branch
32a591f test_branch@{0}: commit: add snippets
23bae4a test_branch@{1}: commit (initial): initial commit

Notez la différence : HEAD@{1} signifie « où se trouvait HEAD lors de son dernier déplacement », tandis que test_branch@{1} signifie « où se trouvait test_branch elle-même lors de son dernier déplacement ». Cette distinction est ce qui vous permet de récupérer un sommet de branche qu'un hard reset ou une mise à jour forcée a déplacé.

Vous pouvez également lire le reflog pour le git stash :

git reflog stash
0d44de3 stash@{0}: WIP on git_reflog: a567574 adding Vue.js

Reflogs temporels

Chaque entrée de reflog est accompagnée d'un horodatage. Ceux-ci peuvent être utilisés comme qualificateurs dans la syntaxe des pointeurs de ref Git, vous permettant de filtrer les reflogs Git par temps. Voici quelques exemples de qualificateurs temporels :

  • 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

Vous pouvez combiner les qualificateurs (par ex. 1.week.3.hours.ago) et utiliser des formes plurielles (par ex. 5.hours.ago). Une ref avec qualificateur temporel peut être passée à d'autres commandes Git, pas seulement à git reflog :

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

Ceci affiche un diff entre le master actuel et l'endroit où master pointait il y a une semaine.

Avertissement

Un qualificateur temporel est résolu par rapport au reflog, et non par rapport aux dates de commit. master@{1.week.ago} signifie « le commit que master référençait il y a une semaine sur cette machine », ce qui peut différer du « commit créé il y a une semaine ». Sur un clone fraîchement créé sans historique de reflog, Git revient au sommet actuel et peut avertir que le journal est trop court.

Sous-commandes de git reflog

Git reflog accepte plusieurs arguments qui agissent comme des sous-commandes. Celles-ci sont décrites ci-dessous.

git reflog show

git reflog show est le comportement par défaut et constitue lui-même un alias pour git log -g --abbrev-commit --pretty=oneline. Ces deux commandes sont équivalentes :

git reflog master@{0}
git reflog show master@{0}

git reflog expire

git reflog expire supprime les anciennes entrées de reflog ou celles inaccessibles. Comme supprimer des entrées peut rendre des commits véritablement irrécupérables, vous l'exécutez rarement manuellement — Git l'exécute automatiquement lors de git gc. Par défaut, les entrées accessibles expirent après 90 jours (gc.reflogExpire) et les inaccessibles après 30 jours (gc.reflogExpireUnreachable). Pour forcer une expiration personnalisée :

git reflog expire --expire=1.day.ago --all

git reflog delete

git reflog delete supprime une entrée de reflog spécifique via son sélecteur. Comme expire, cette commande présente un vrai risque de perte de récupérabilité et est rarement nécessaire au quotidien :

git reflog delete HEAD@{1}
Danger

Une fois qu'une entrée de reflog a expiré ou a été supprimée, le commit vers lequel elle pointait devient véritablement inaccessible et sera supprimé lors du prochain passage de git gc. Considérez expire et delete comme des outils de nettoyage, non comme des outils d'annulation.

Récupérer des commits perdus

Les commits ne sont jamais véritablement perdus dans Git, même après des opérations de réécriture d'historique — et le reflog est le moyen de les retrouver. Supposons que git log --pretty=oneline affiche ceci :

2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commit

Supposons maintenant que nous committons de nouveaux changements dans ce dépôt :

# make changes to HEAD
git commit -am "API changes"

Le journal ressemble maintenant à ceci :

37656e19d4e4f1a9b419f57850c8f1974f871b07 API changes
2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commit

Ensuite, nous démarrons un rebase interactif contre master :

git rebase -i origin/master

Pendant le rebase, nous marquons des commits avec l'action s (squash) pour les fusionner dans le commit « API changes » le plus récent. Après cela, la sortie de git log est réduite à :

40d8a1237656e19d4e4f1a9b419f57850c8f1974 API changes
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit

Les commits fusionnés semblent avoir disparu. Mais le reflog enregistre toujours chaque position qu'a occupée HEAD pendant le rebase :

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: API changes

HEAD@{2} correspond à l'état juste avant le début du rebase. Passez ce sélecteur à git reset pour y revenir :

git reset --hard HEAD@{2}

Cela déplace HEAD vers le commit « API changes » d'avant le rebase et restaure tous les commits fusionnés. Utilisez --hard pour également réinitialiser votre arbre de travail à cet état, ou omettez-le (git reset HEAD@{2}) pour déplacer uniquement le pointeur de branche tout en conservant les fichiers actuels.

Quand utiliser git reflog

Utilisez le reflog chaque fois qu'une ref a été déplacée et que vous souhaitez la récupérer :

  • Après un git reset --hard qui a supprimé des commits dont vous aviez besoin.
  • Pour récupérer des commits orphelins suite à un rebase interactif, un amend ou un squash.
  • Pour restaurer une branche supprimée avec git branch -D (trouvez son dernier sommet dans le reflog, puis exécutez git branch <nom> <hash>).
  • Pour retrouver où se trouvait HEAD avant une série déroutante de checkouts ou de merges.

Si le commit est plus récent que la fenêtre d'expiration du reflog (90 jours pour les entrées accessibles par défaut), il est récupérable.

Pages connexes

  • git reset — déplacez les refs vers une entrée de reflog pour annuler des modifications.
  • git rebase — l'opération de réécriture que le reflog permet le plus souvent de corriger.
  • git stash — les stashes ont leur propre reflog sous stash@{n}.
  • git log — la vue d'historique standard ; git log -g lit le reflog.

Pratique

Pratique
Quelles sont les affirmations correctes concernant la commande `git reflog` ?
Quelles sont les affirmations correctes concernant la commande `git reflog` ?
Was this page helpful?