Décréer un fichier supprimé dans git

504

Habituellement, pour annuler les modifications apportées à un fichier, vous devez:

git checkout -- <file>

Que faire si la modification que je souhaite supprimer supprime le fichier? La ligne ci-dessus donnerait une erreur:

error: pathspec '<file>' did not match any file(s) known to git.

Quelle commande restaurera ce fichier unique sans annuler d'autres modifications?

point bonus: Et si le changement que je veux supprimer consiste à ajouter un fichier? J'aimerais aussi savoir comment mettre en scène ce changement.

lurscher
la source
1
Ignorer les modifications et annuler la mise en scène sont deux choses différentes, qu'essayez-vous de faire?
Andrew Marshall
1
Il s'agit de deux questions et problèmes différents dans un même article. Cela rend les réponses beaucoup trop confuses et inutiles.
David Sopko

Réponses:

779

En supposant que vous vouliez annuler les effets de git rm <file>ou rm <file>suivis par git add -Aquelque chose de similaire:

# this restores the file status in the index
git reset -- <file>
# then check out a copy from the index
git checkout -- <file>

Pour annuler git add <file>, la première ligne ci-dessus suffit, en supposant que vous ne vous êtes pas encore engagé.

Twalberg
la source
70
C'est --la clé. git reset <file>ne fonctionne pas, c'est ce qui m'a amené ici.
2
Pourquoi est end-of-options-markerrequis uniquement dans le cas de fichiers supprimés?
haridsv
5
@handsv Ce n'est pas strictement requis (vous pouvez le faire alternativement git reset HEAD <file>, ce qui est équivalent), mais git resettraite son premier argument avant end-of-options-markercomme un nom de référence, pas un nom de fichier. Pourrait-il être écrit un peu plus flexiblement? Probablement. Pourquoi pas? Probablement, seuls les développeurs le savent.
twalberg
2
@twalberg git reset filenamefonctionne très bien pour les fichiers non supprimés.
Brian Gordon
1
@AaronMahan - pouvez-vous s'il vous plaît expliquer la différence entre git reset <file>et git reset -- <file>. J'ai du mal à trouver une réponse à cela sur google.
Neeraj B.
56

On répond aux deux questions git status.

Pour supprimer l'ajout d'un nouveau fichier, utilisez git rm --cached filename.ext

# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   test

Pour supprimer la suppression d'un fichier, utilisez git reset HEAD filename.ext

# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   deleted:    test

D'un autre côté, git checkout --ne jamais mettre en scène, il rejette simplement les modifications non mises en scène.

seppo0010
la source
5
Je ne vois pas l'astuce pour un fichier supprimé dans git 1.7.2.5 sur Debian.
tripleee
Agréable à voir git statuscité; montre aux utilisateurs un moyen d'auto-assistance maintenant et la prochaine fois, et au cas où des informations seraient ajoutées ou mises à jour dans les futures versions de git.
Will Cain
C'est faux. "Changements à engager" est ce que vous voyez avant le git reset. Après le git reset, vous voyez "Modifié mais pas mis à jour" ce qui signifie "Modifications non mises en scène" dans la langue maternelle des auteurs git, apparemment. Plus important encore, tout le dogme sur le «statut git vous dit tout ce que vous savez» est un mensonge. (Les gestionnaires qui disent que cela fait perdre du temps aux gens et devraient être licenciés.)
personal_cloud
11

Les réponses à vos deux questions sont liées. Je vais commencer par le second:

Une fois que vous avez mis en scène un fichier (souvent avec git add, bien que d'autres commandes implémentent également implicitement les modifications, comme git rm), vous pouvez annuler ce changement avec git reset -- <file>.

Dans votre cas, vous devez avoir utilisé git rmpour supprimer le fichier, ce qui équivaut à simplement le supprimer avec rm, puis à mettre en scène cette modification. Si vous le décompressez d'abord avec, git reset -- <file>vous pouvez le récupérer avec git checkout -- <file>.

Ben Jackson
la source
7

S'il a été mis en scène et validé, les éléments suivants réinitialiseront le fichier:

git reset COMMIT_HASH file_path
git checkout COMMIT_HASH file_path
git add file_path

Cela fonctionnera pour une suppression qui s'est produite plusieurs fois auparavant.

michaeldever
la source
1
Il est plus efficace degit revert COMMIT_HASH
Flair
2

Depuis git v2.23 , vous avez une autre option:

git restore --staged -- <file>

Kreempuff
la source