Question

Est-il possible d'annuler les modifications provoquées par la commande suivante ?Si c'est le cas, comment?

git reset --hard HEAD~1
Était-ce utile?

La solution

Pat Notz a raison.Vous pouvez récupérer le commit à condition que ce soit dans quelques jours.git ne collecte les ordures qu'après environ un mois, sauf si vous lui dites explicitement de supprimer les blobs les plus récents.

$ git init
Initialized empty Git repository in .git/

$ echo "testing reset" > file1
$ git add file1
$ git commit -m 'added file1'
Created initial commit 1a75c1d: added file1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file1

$ echo "added new file" > file2
$ git add file2
$ git commit -m 'added file2'
Created commit f6e5064: added file2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file2

$ git reset --hard HEAD^
HEAD is now at 1a75c1d... added file1

$ cat file2
cat: file2: No such file or directory

$ git reflog
1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
f6e5064... HEAD@{1}: commit: added file2

$ git reset --hard f6e5064
HEAD is now at f6e5064... added file2

$ cat file2
added new file

Vous pouvez voir dans l'exemple que le fichier2 a été supprimé à la suite de la réinitialisation matérielle, mais a été remis en place lorsque j'ai réinitialisé via le reflog.

Autres conseils

Ce que vous voulez faire est de spécifier le sha1 du commit vers lequel vous souhaitez restaurer.Vous pouvez obtenir le sha1 en examinant le reflog (git reflog) puis en faisant

git reset --hard <sha1 of desired commit>

Mais n'attendez pas trop longtemps...après quelques semaines, git finira par voir ce commit comme non référencé et supprimera tous les blobs.

La réponse est cachée dans la réponse détaillée ci-dessus, vous pouvez simplement faire :

$> git reset --hard HEAD@{1}

(Voir la sortie de git reflog montrer)

Il est possible de le récupérer si Git n'a pas encore récupéré la mémoire.

Obtenez un aperçu des commits en suspens avec fsck:

$ git fsck --lost-found
dangling commit b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf

Récupérez le commit en suspens avec rebase :

$ git rebase b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf

Si vous êtes vraiment chanceux, comme moi, vous pouvez retourner dans votre éditeur de texte et appuyer sur « Annuler ».

Je sais que ce n'est pas vraiment une bonne réponse, mais cela m'a évité une demi-journée de travail, alors j'espère que cela fera la même chose pour quelqu'un d'autre !

Exemple de cas IRL :

$ git fsck --lost-found

Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.
dangling blob 025cab9725ccc00fbd7202da543f556c146cb119
dangling blob 84e9af799c2f5f08fb50874e5be7fb5cb7aa7c1b
dangling blob 85f4d1a289e094012819d9732f017c7805ee85b4
dangling blob 8f654d1cd425da7389d12c17dd2d88d318496d98
dangling blob 9183b84bbd292dcc238ca546dab896e073432933
dangling blob 1448ee51d0ea16f259371b32a557b60f908d15ee
dangling blob 95372cef6148d980ab1d7539ee6fbb44f5e87e22
dangling blob 9b3bf9fb1ee82c6d6d5ec9149e38fe53d4151fbd
dangling blob 2b21002ca449a9e30dbb87e535fbd4e65bac18f7
dangling blob 2fff2f8e4ea6408ac84a8560477aa00583002e66
dangling blob 333e76340b59a944456b4befd0e007c2e23ab37b
dangling blob b87163c8def315d40721e592f15c2192a33816bb
dangling blob c22aafb90358f6bf22577d1ae077ad89d9eea0a7
dangling blob c6ef78dd64c886e9c9895e2fc4556e69e4fbb133
dangling blob 4a71f9ff8262701171d42559a283c751fea6a201
dangling blob 6b762d368f44ddd441e5b8eae6a7b611335b49a2
dangling blob 724d23914b48443b19eada79c3eb1813c3c67fed
dangling blob 749ffc9a412e7584245af5106e78167b9480a27b
dangling commit f6ce1a403399772d4146d306d5763f3f5715cb5a    <- it's this one

$ git show f6ce1a403399772d4146d306d5763f3f5715cb5a

commit f6ce1a403399772d4146d306d5763f3f5715cb5a
Author: Stian Gudmundsen Høiland <stian@Stians-Mac-mini.local>
Date:   Wed Aug 15 08:41:30 2012 +0200

    *MY COMMIT MESSAGE IS DISPLAYED HERE*

diff --git a/Some.file b/Some.file
new file mode 100644
index 0000000..15baeba
--- /dev/null
+++ b/Some.file
*THE WHOLE COMMIT IS DISPLAYED HERE*

$ git rebase f6ce1a403399772d4146d306d5763f3f5715cb5a

First, rewinding head to replay your work on top of it...
Fast-forwarded master to f6ce1a403399772d4146d306d5763f3f5715cb5a.

Pour autant que je sache, --hard supprimera les modifications non validées.Puisque ceux-ci ne sont pas suivis par git.mais vous pouvez annuler le discarded commit.

$ git reflog

listera :

b0d059c HEAD@{0}: reset: moving to HEAD~1
4bac331 HEAD@{1}: commit: added level introduction....
....

4bac331 est le discarded commit.

Maintenant, déplacez simplement la tête vers ce commit : :

$ git reset --hard 4bac331

Dans la plupart des cas, oui.

En fonction de l'état dans lequel se trouvait votre référentiel lorsque vous avez exécuté la commande, les effets de git reset --hard peut aller de trivial à annuler, à fondamentalement impossible.

Ci-dessous, j'ai répertorié une gamme de différents scénarios possibles et la manière dont vous pourriez vous en remettre.

Toutes mes modifications ont été validées, mais maintenant les validations ont disparu !

Cette situation se produit généralement lorsque vous exécutez git reset avec un argument, comme dans git reset --hard HEAD~.Ne vous inquiétez pas, c'est facile à récupérer !

Si tu venais de courir git reset et je n'ai rien fait d'autre depuis, vous pouvez revenir là où vous étiez avec ce one-liner :

git reset --hard @{1}

Cela réinitialise votre branche actuelle, quel que soit son état avant la dernière modification (dans votre cas, la modification la plus récente apportée à la branche serait la réinitialisation matérielle que vous essayez d'annuler).

Si toutefois vous avoir avez apporté d'autres modifications à votre branche depuis la réinitialisation, la ligne ci-dessus ne fonctionnera pas.Au lieu de cela, tu devrais courir git reflog <branchname> pour voir une liste de toutes les modifications récentes apportées à votre branche (y compris les réinitialisations).Cette liste ressemblera à ceci :

7c169bd master@{0}: reset: moving to HEAD~
3ae5027 master@{1}: commit: Changed file2
7c169bd master@{2}: commit: Some change
5eb37ca master@{3}: commit (initial): Initial commit

Recherchez dans cette liste l'opération que vous souhaitez "annuler".Dans l'exemple ci-dessus, il s'agirait de la première ligne, celle qui dit "reset :passer à HEAD~".Copiez ensuite la représentation du commit avant (ci-dessous) cette opération.Dans notre cas, ce serait master@{1} (ou 3ae5027, ils représentent tous les deux le même commit) et exécutez git reset --hard <commit> pour réinitialiser votre branche actuelle à ce commit.

J'ai mis en scène mes modifications avec git add, mais jamais engagé.Maintenant, mes modifications ont disparu !

C'est un peu plus difficile à récupérer.git fait disposez de copies des fichiers que vous avez ajoutés, mais comme ces copies n'ont jamais été liées à une validation particulière, vous ne pouvez pas restaurer les modifications en une seule fois.Au lieu de cela, vous devez localiser les fichiers individuels dans la base de données de git et les restaurer manuellement.Vous pouvez le faire en utilisant git fsck.

Pour plus de détails à ce sujet, voir Annuler git reset --hard avec les fichiers non validés dans la zone de transit.

J'ai apporté des modifications à des fichiers dans mon répertoire de travail avec lesquels je n'ai jamais effectué de préparation. git add, et jamais engagé.Maintenant, mes modifications ont disparu !

Euh oh.Je déteste te dire ça, mais tu n'as probablement pas de chance.git ne stocke pas les modifications que vous n'y ajoutez pas ou ne validez pas, et selon le documentation pour git reset:

--dur

Réinitialise l'index et l'arborescence de travail. Toute modification apportée aux fichiers suivis dans l'arborescence de travail depuis <commit> sont écartés.

Il est possible que tu pourrait Vous pourrez récupérer vos modifications avec une sorte d'utilitaire de récupération de disque ou un service professionnel de récupération de données, mais à ce stade, cela pose probablement plus de problèmes que cela n'en vaut la peine.

Si vous n'avez pas encore récupéré votre dépôt (par ex.en utilisant git repack -d ou git gc, mais notez que le garbage collection peut également s'effectuer automatiquement), alors votre commit est toujours là – il n'est tout simplement plus accessible via HEAD.

Vous pouvez essayer de trouver votre commit en parcourant la sortie de git fsck --lost-found.

Les versions plus récentes de Git ont quelque chose appelé "reflog", qui est un journal de toutes les modifications apportées aux références (par opposition aux modifications apportées au contenu du référentiel).Ainsi, par exemple, chaque fois que vous changez de HEAD (c'est-à-direchaque fois que tu fais un git checkout pour changer de branche) qui sera enregistré.Et bien sûr, votre git reset a également manipulé le HEAD, il a donc également été enregistré.Vous pouvez accéder aux anciens états de vos références de la même manière que vous pouvez accéder aux anciens états de votre référentiel, en utilisant un @ signer au lieu d'un ~, comme git reset HEAD@{1}.

Il m'a fallu un certain temps pour comprendre quelle est la différence entre HEAD@{1} et HEAD~1, alors voici une petite explication :

git init
git commit --allow-empty -mOne
git commit --allow-empty -mTwo
git checkout -b anotherbranch
git commit --allow-empty -mThree
git checkout master # This changes the HEAD, but not the repository contents
git show HEAD~1 # => One
git show HEAD@{1} # => Three
git reflog

Donc, HEAD~1 signifie "aller au commit avant le commit vers lequel HEAD pointe actuellement", tandis que HEAD@{1} signifie "aller au commit pointé par HEAD avant de pointer là où il pointe actuellement".

Cela vous permettra facilement de retrouver votre commit perdu et de le récupérer.

Je sais que c'est un vieux fil...mais comme beaucoup de gens cherchent des moyens d'annuler des choses dans Git, je pense toujours que ce serait peut-être une bonne idée de continuer à donner des conseils ici.

Lorsque vous effectuez un "git add" ou déplacez quoi que ce soit du haut à gauche vers le bas à gauche dans git gui, le contenu du fichier est stocké dans un blob et le contenu du fichier peut être récupéré à partir de ce blob.

Il est donc possible de récupérer un fichier même s'il n'a pas été validé mais il faut qu'il ait été ajouté.

git init  
echo hello >> test.txt  
git add test.txt  

Maintenant, le blob est créé mais il est référencé par l'index, il ne sera donc pas répertorié avec git fsck jusqu'à ce que nous le réinitialisions.Nous réinitialisons donc...

git reset --hard  
git fsck  

vous obtiendrez une goutte pendante ce013625030ba8dba906f756967f9e9ca394464a

git show ce01362  

vous rendra le contenu du fichier "bonjour"

Pour trouver des commits non référencés, j'ai trouvé quelque part une astuce suggérant cela.

gitk --all $(git log -g --pretty=format:%h)  

Je l'ai comme outil dans git gui et c'est très pratique.

Avant de répondre, ajoutons un peu de contexte, expliquant ce que c'est HEAD.

First of all what is HEAD?

HEAD est simplement une référence au commit actuel (le plus récent) sur la branche actuelle.
Il ne peut y en avoir qu'un seul HEAD n'importe quand.(à l'exclusion git worktree)

Le contenu de HEAD est stocké à l'intérieur .git/HEAD et il contient les 40 octets SHA-1 du commit actuel.


detached HEAD

Si vous n'êtes pas sur le dernier commit, ce qui signifie que HEAD pointe vers un commit antérieur dans l'histoire, il s'appelle detached HEAD.

enter image description here

Sur la ligne de commande, cela ressemblera à ceci : SHA-1 au lieu du nom de la branche puisque le HEAD ne pointe pas vers la pointe de la branche actuelle

enter image description here


Quelques options pour récupérer un HEAD détaché :


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Cela permettra d'extraire une nouvelle branche pointant vers le commit souhaité.
Cette commande effectuera une extraction vers un commit donné.
À ce stade, vous pouvez créer une branche et commencer à travailler à partir de ce moment.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Vous pouvez toujours utiliser le reflog aussi.
git reflog affichera tout changement qui a mis à jour le HEAD et vérifier l'entrée de reflog souhaitée définira le HEAD revenons à cet engagement.

Chaque fois que le HEAD est modifié, il y aura une nouvelle entrée dans le reflog

git reflog
git checkout HEAD@{...}

Cela vous ramènera à votre engagement souhaité

enter image description here


git reset HEAD --hard <commit_id>

"Déplacez" votre tête vers le commit souhaité.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • Note:(Depuis Git 2.7)
    vous pouvez également utiliser le git rebase --no-autostash aussi.


git revert <sha-1>

"Annuler" la validation ou la plage de validation donnée.
La commande reset "annulera" toutes les modifications apportées dans le commit donné.
Un nouveau commit avec le patch d'annulation sera validé tandis que le commit d'origine restera également dans l'historique.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Ce schéma illustre quelle commande fait quoi.
Comme vous pouvez le voir là reset && checkout modifier le HEAD.

enter image description here

Je viens de faire une réinitialisation matérielle sur un mauvais projet.Ce qui m'a sauvé la vie, c'est l'histoire locale d'Eclipse.IntelliJ Idea en aurait un également, tout comme votre éditeur, cela vaut la peine de vérifier :

  1. Rubrique d'aide Eclipse sur l'historique local
  2. http://wiki.eclipse.org/FAQ_Where_is_the_workspace_local_history_stored%3F

Création d'un petit script pour faciliter la recherche du commit recherché :

git fsck --lost-found | grep commit | cut -d ' ' -f 3 | xargs -i git show \{\} | egrep '^commit |Date:'

Oui, cela peut être rendu considérablement plus joli avec awk ou quelque chose comme ça, mais c'est simple et j'en avais juste besoin.Cela pourrait faire gagner 30 secondes à quelqu'un d'autre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top