¿Cómo deshago 'git add' antes de confirmar?

Resuelto oz10 asked hace 16 años • 38 respuestas

Agregué archivos por error a Git usando el comando:

git add myfile.txt

Todavía no he corrido git commit. ¿Cómo deshago esto para que estos cambios no se incluyan en la confirmación?

oz10 avatar Dec 08 '08 04:12 oz10
Aceptado

Para eliminar un archivo específico

git reset <file>

Eso eliminará el archivo del índice actual (la lista "a punto de confirmarse") sin cambiar nada más.

Para eliminar todos los archivos del conjunto de cambios actual:

git reset

En versiones anteriores de Git, los comandos anteriores son equivalentes a git reset HEAD <file>y git reset HEADrespectivamente, y fallarán si HEADno están definidos (porque aún no has realizado ninguna confirmación en tu repositorio) o son ambiguos (porque creaste una rama llamada HEAD, lo cual es una estupidez). que no deberías hacer). Sin embargo, esto se cambió en Git 1.8.2 , por lo que en las versiones modernas de Git puedes usar los comandos anteriores incluso antes de realizar tu primera confirmación:

"git reset" (sin opciones ni parámetros) solía generar un error cuando no tienes ninguna confirmación en tu historial, pero ahora te proporciona un índice vacío (para coincidir con una confirmación inexistente en la que ni siquiera estás).

Documentación: git reset

genehack avatar Dec 07 '2008 22:12 genehack

Quieres:

git rm --cached <added_file_to_undo>

Razonamiento:

Cuando era nuevo en esto, lo intenté por primera vez.

git reset .

(para deshacer toda mi adición inicial), solo para recibir este (no tan) mensaje útil:

fatal: Failed to resolve 'HEAD' as a valid ref.

Resulta que esto se debe a que la referencia HEAD (¿rama?) no existe hasta después de la primera confirmación. Es decir, te encontrarás con el mismo problema de principiante que yo si tu flujo de trabajo, como el mío, fuera algo como:

  1. cd a mi nuevo directorio de proyectos para probar Git, el nuevo atractivo
  2. git init
  3. git add .
  4. git status

    ... muchos pergaminos de mierda de ...

    => Maldita sea, no quería agregar todo eso.

  5. google "deshacer git add"

    => encontrar desbordamiento de pila - yay

  6. git reset .

    => fatal: No se pudo resolver 'HEAD' como una referencia válida.

Además, resulta que hay un error registrado debido a la inutilidad de esto en la lista de correo.

Y que la solución correcta estaba ahí en la salida de estado de Git (que, sí, pasé por alto como 'basura)

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

Y la solución es, de hecho, utilizar git rm --cached FILE.

Tenga en cuenta las advertencias en otros lugares aquí: git rmelimina su copia de trabajo local del archivo, pero no si usa --cached . Aquí está el resultado de git help rm:

--cached Utilice esta opción para desagregar y eliminar rutas sólo del índice. Se conservarán los archivos del árbol de trabajo, modificados o no.

procedo a usar

git rm --cached .

para quitar todo y empezar de nuevo. Sin embargo, no funcionó, porque si bien add .es recursivo, resulta que rmdebe -rser recursivo. Suspiro.

git rm -r --cached .

Bien, ahora he vuelto al punto de partida. La próxima vez haré -nun ensayo y veré qué se agregará:

git add -n .

Cerré todo a un lugar seguro antes de confiar git help rmen --cachedno destruir nada (y si lo escribí mal).

Rhubarb avatar Mar 25 '2009 16:03 Rhubarb

Si escribes:

git status

Git le dirá qué se prepara, etc., incluidas instrucciones sobre cómo cancelar la preparación:

use "git reset HEAD <file>..." to unstage

Creo que Git hace un buen trabajo al impulsarme a hacer lo correcto en situaciones como esta.

Nota: Las versiones recientes de Git (1.8.4.x) han cambiado este mensaje:

(use "git rm --cached <file>..." to unstage)
Paul Beckingham avatar Dec 07 '2008 23:12 Paul Beckingham

Para aclarar: git addmueve los cambios del directorio de trabajo actual al área de preparación (índice).

Este proceso se llama puesta en escena . Entonces, el comando más natural para preparar los cambios (archivos modificados) es el obvio:

git stage

git addes simplemente un alias más fácil de escribir paragit stage

Lástima que no hay git unstageni git unaddcomandos. El relevante es más difícil de adivinar o recordar, pero es bastante obvio:

git reset HEAD --

Podemos crear fácilmente un alias para esto:

git config --global alias.unadd 'reset HEAD --'
git config --global alias.unstage 'reset HEAD --'

Y por último, tenemos nuevos comandos:

git add file1
git stage file2
git unadd file2
git unstage file1

Personalmente uso alias aún más cortos:

git a # For staging
git u # For unstaging
takeshin avatar Sep 10 '2010 20:09 takeshin

Además de la respuesta aceptada, si el archivo agregado por error era enorme, probablemente notará que, incluso después de eliminarlo del índice con ' git reset', todavía parece ocupar espacio en el .gitdirectorio.

Esto no es nada de qué preocuparse; De hecho, el archivo todavía está en el repositorio, pero sólo como un "objeto suelto". No se copiará a otros repositorios (mediante clonación, inserción) y el espacio eventualmente se recuperará, aunque quizás no muy pronto. Si estás ansioso, puedes ejecutar:

git gc --prune=now

Actualización (lo que sigue es mi intento de aclarar cierta confusión que puede surgir de las respuestas más votadas):

Entonces, ¿cuál es la verdadera ruinagit add ?

git reset HEAD <file>?

o

git rm --cached <file>?

En rigor, y si no me equivoco: ninguna .

git add no se puede deshacer , de forma segura, en general.

Recordemos primero lo que git add <file>realmente hace:

  1. Si no <file>fue rastreado previamente , git add lo agrega al caché , con su contenido actual.

  2. Si ya<file> se realizó un seguimiento , guarda el contenido actual (instantánea, versión) en la memoria caché. En Git, esta acción todavía se llama agregar (no simplemente actualizarla ), porque dos versiones diferentes (instantáneas) de un archivo se consideran dos elementos diferentes: por lo tanto, estamos agregando un nuevo elemento al caché, que eventualmente será agregado. cometido más tarde.git add

En vista de esto, la pregunta es un poco ambigua:

Agregué archivos por error usando el comando...

El escenario del OP parece ser el primero (archivo sin seguimiento), queremos que "deshacer" elimine el archivo (no solo el contenido actual) de los elementos rastreados. Si este es el caso, entonces está bien ejecutarlo git rm --cached <file>.

Y también podríamos correr git reset HEAD <file>. En general, esto es preferible, porque funciona en ambos escenarios: también deshace cuando agregamos incorrectamente una versión de un elemento ya rastreado.

Pero hay dos advertencias.

Primero: hay (como se señala en la respuesta) solo un escenario en el que git reset HEADno funciona, pero git rm --cachedsí: un nuevo repositorio (sin confirmaciones). Pero, en realidad, éste es un caso prácticamente irrelevante.

Segundo: tenga en cuenta que git reset HEAD no se puede recuperar mágicamente el contenido del archivo previamente almacenado en caché, simplemente lo resincroniza desde HEAD. Si nuestro error git addsobrescribió una versión anterior no confirmada, no podremos recuperarla. Por eso, estrictamente hablando, no podemos deshacer [*].

Ejemplo:

$ git init
$ echo "version 1" > file.txt
$ git add file.txt   # First add of file.txt
$ git commit -m 'first commit'
$ echo "version 2" > file.txt
$ git add  file.txt   # Stage (don't commit) "version 2" of file.txt
$ git diff --cached file.txt
-version 1
+version 2
$ echo "version 3" > file.txt
$ git diff  file.txt
-version 2
+version 3
$ git add  file.txt    # Oops we didn't mean this
$ git reset HEAD file.txt  # Undo?
$ git diff --cached file.txt  # No dif, of course. stage == HEAD
$ git diff file.txt   # We have irrevocably lost "version 2"
-version 1
+version 3

Por supuesto, esto no es muy crítico si simplemente seguimos el flujo de trabajo lento habitual de hacer 'git add' solo para agregar nuevos archivos (caso 1) y actualizamos nuevos contenidos mediante el comando commit git commit -a.


* (Editar: lo anterior es prácticamente correcto, pero aún así puede haber algunas formas un poco complicadas o complicadas para recuperar cambios que se realizaron, pero que no se confirmaron y luego se sobrescribieron; consulte los comentarios de Johannes Matokic e iolsmit)

leonbloy avatar May 18 '2011 18:05 leonbloy

Deshacer un archivo que ya se ha agregado es bastante fácil usando Git. Para restablecer archivos myfile.txtque ya se han agregado, use:

git reset HEAD myfile.txt

Explicación:

Después de preparar los archivos no deseados, para deshacerlos, puede hacer git reset. Heades el encabezado de su archivo en el local y el último parámetro es el nombre de su archivo.

He creado los pasos en la imagen a continuación con más detalles para usted, incluidos todos los pasos que pueden ocurrir en estos casos:

git restablecer archivo HEAD

Alireza avatar Jun 28 '2017 10:06 Alireza