Desarmar un archivo eliminado en git

504

Por lo general, para descartar cambios en un archivo que haría:

git checkout -- <file>

¿Qué sucede si el cambio que deseo descartar es eliminar el archivo? La línea anterior daría un error:

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

¿Qué comando restaurará ese archivo único sin deshacer otros cambios?

punto extra: Además, ¿qué sucede si el cambio que deseo descartar es agregar un archivo? Quisiera saber cómo eliminar ese cambio también.

acechador
fuente
1
Descartar los cambios y desestabilizar son dos cosas diferentes, ¿qué estás intentando hacer?
Andrew Marshall
1
Estas son dos preguntas y problemas diferentes en una publicación. Esto hace que las respuestas sean demasiado e innecesariamente confusas.
David Sopko el

Respuestas:

779

Suponiendo que desea deshacer los efectos git rm <file>o rm <file>seguidos de git add -Aalgo similar:

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

Para deshacer git add <file>, la primera línea anterior es suficiente, suponiendo que aún no se haya comprometido.

Twalberg
fuente
70
La --es la clave. git reset <file>no funciona, que es lo que me trajo aquí.
2
¿Por qué solo se end-of-options-markerrequiere en el caso del archivo eliminado?
haridsv
55
@handsv No es estrictamente obligatorio (puede hacerlo alternativamente git reset HEAD <file>, lo que es equivalente), pero git resettrata su primer argumento anterior end-of-options-markercomo un nombre de referencia, no un nombre de archivo. ¿Podría escribirse un poco más flexible? Probablemente. ¿Por qué no lo fue? Probablemente solo los desarrolladores lo sepan con certeza.
twalberg
2
@twalberg git reset filenamefunciona bien para archivos no eliminados.
Brian Gordon
1
@AaronMahan: ¿puede explicar la diferencia entre git reset <file>y git reset -- <file>? Me está costando encontrar una respuesta a eso en Google.
Neeraj B.
56

Ambas preguntas se responden en git status.

Para quitar la etapa agregando un nuevo archivo, use git rm --cached filename.ext

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

Para eliminar la eliminación de un archivo, use git reset HEAD filename.ext

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

Por otro lado, git checkout --nunca desarme, solo descarta los cambios no organizados.

seppo0010
fuente
55
No veo la pista para un archivo eliminado en git 1.7.2.5 en Debian.
tripleee
Agradable ver git statuscitado; muestra a los usuarios una forma de autoayuda ahora y la próxima vez, y en caso de que se agregue o actualice información en futuras versiones de git.
Will Cain
Esto está mal. "Cambios para comprometerse" es lo que ve antes del git reset. Después del git reset, verá "Cambiado pero no actualizado", que significa "Cambios no organizados" en el idioma nativo de los autores de git, aparentemente. Más importante aún, todo el dogma sobre "el estado de git te dice todo lo que sabes" es una mentira. (Los gerentes que dicen que están perdiendo el tiempo de las personas y deberían ser despedidos)
Personal_cloud
11

Las respuestas a sus dos preguntas están relacionadas. Comenzaré con el segundo:

Una vez que haya organizado un archivo (a menudo con git add, aunque algunos otros comandos implícitamente también organizan los cambios git rm), puede retroceder ese cambio con git reset -- <file>.

En su caso, debe haber utilizado git rmpara eliminar el archivo, lo que equivale a simplemente eliminarlo rmy luego organizar ese cambio. Si primero lo quitas del escenario, git reset -- <file>puedes recuperarlo con git checkout -- <file>.

Ben Jackson
fuente
7

Si se ha organizado y confirmado, lo siguiente restablecerá el archivo:

git reset COMMIT_HASH file_path
git checkout COMMIT_HASH file_path
git add file_path

Esto funcionará para una eliminación que ocurrió varias confirmaciones anteriores.

michaeldever
fuente
1
Es más eficientegit revert COMMIT_HASH
Flair
2

A partir de git v2.23 , tienes otra opción:

git restore --staged -- <file>

Kreempuff
fuente