Agregué por error archivos a Git usando el comando:
git add myfile.txt
Aún no he corrido git commit
. ¿Hay alguna manera de deshacer esto, por lo que estos archivos no se incluirán en la confirmación?
fuente
Agregué por error archivos a Git usando el comando:
git add myfile.txt
Aún no he corrido git commit
. ¿Hay alguna manera de deshacer esto, por lo que estos archivos no se incluirán en la confirmación?
Puede deshacer git add
antes de comprometerse con
git reset <file>
que lo eliminará del índice actual (la lista "a punto de confirmarse") sin cambiar nada más.
Puedes usar
git reset
sin ningún nombre de archivo para desestabilizar todos los cambios debidos. Esto puede ser útil cuando hay demasiados archivos para enumerar uno por uno en un período de tiempo razonable.
En versiones anteriores de Git, los comandos anteriores son equivalentes git reset HEAD <file>
y git reset HEAD
respectivamente, y fallarán si no HEAD
está definido (porque aún no ha realizado ninguna confirmación en su repositorio) o ambiguo (porque creó 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 puede usar los comandos anteriores incluso antes de realizar su primera confirmación:
"git reset" (sin opciones ni parámetros) se usa para generar un error cuando no tiene ningún commit en su historial, pero ahora le da un índice vacío (para que coincida con el commit inexistente que ni siquiera tiene).
git add
sobrescribió una versión previa no confirmada, no podemos recuperarla. Traté de aclarar esto en mi respuesta a continuación.
git reset HEAD *.ext
¿Dónde ext
están los archivos de la extensión dada que desea agregar? Para mí fue *.bmp
&*.zip
git rm --cached
), significa que se está preparando para realizar una confirmación que elimine ese archivo. git reset HEAD <filename>
por otro lado, copiará el archivo de HEAD al índice, para que la próxima confirmación no muestre ningún cambio realizado en ese archivo.
git reset -p
igual git add -p
. ¡Esto es asombroso!
git add
que desea recuperar ( 61/3AF3...
- > ID del objeto 613AF3...
), entonces git cat-file -p <object-id>
(podría valer la pena recuperar varias horas de trabajo pero también una lección para comprometerse más a menudo ...)
Usted quiere:
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 obtener 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 así como:
git init
git add .
git status
... muchos rollos de basura por ...
=> Maldición, no quería agregar todo eso.
google "deshacer git add"
=> buscar desbordamiento de pila - yay
git reset .
=> fatal: no se pudo resolver 'HEAD' como una referencia válida.
Resulta que hay un error registrado en contra de la inutilidad de esto en la lista de correo.
Y que la solución correcta estaba allí en la salida de estado de Git (que, sí, lo pasé por alto como 'basura')
... # Changes to be committed: # (use "git rm --cached <file>..." to unstage) ...
Y la solución de hecho es usar git rm --cached FILE
.
Tenga en cuenta las advertencias en otro lugar aquí: git rm
elimina su copia de trabajo local del archivo, pero no si usa --cached . Aquí está el resultado de git help rm
:
--cached Use esta opción para quitar etapas y eliminar rutas solo del índice. Se dejarán los archivos del árbol de trabajo, ya sea modificado o no.
Procedo a usar
git rm --cached .
para eliminar todo y comenzar de nuevo. Sin embargo, no funcionó, porque si bien add .
es recursivo, resulta que rm
debe -r
repetirse. Suspiro.
git rm -r --cached .
Bien, ahora estoy de vuelta a donde empecé. La próxima vez voy a usar -n
para hacer una carrera en seco y ver qué se agregará:
git add -n .
Comprimí todo en un lugar seguro antes de confiar git help rm
en que --cached
no destruiría nada (y qué pasa si lo escribí mal).
rm -rf .git
, git init
porque no confiaba git rm --cached
en mantener mi copia de trabajo. Dice un poco sobre cómo git sigue siendo demasiado complejo en algunos lugares. git unstage
debería ser un comando estándar estándar, no me importa si puedo agregarlo como un alias.
git reset HEAD <File>...
git add
comando agregó nuevos archivos, pero no cambia los archivos existentes.
Si escribe:
git status
Git le dirá lo que está organizado, etc., incluidas las instrucciones sobre cómo quitar el escenario:
use "git reset HEAD <file>..." to unstage
Me parece que Git hace un buen trabajo al empujarme 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)
add
archivo ed ya estaba siendo rastreado ( add
solo se guardó una nueva versión en el caché; aquí mostrará su mensaje). En otros lugares, si el archivo no se use "git rm --cached <file>..." to unstage
git reset HEAD <file>
uno es el único que funcionará en caso de que desee eliminar la eliminación de un archivo
git reset HEAD
que desestabilice
Para aclarar: git add
mueve 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 organizar los cambios (archivos modificados) es el obvio:
git stage
git add
es solo un alias más fácil de escribir para git stage
Lástima que no hay git unstage
ni git unadd
comandos. 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 finalmente, 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
git stage
es el alias de git add
, que es el comando histórico, tanto en Git como en otros SCM. Se ha agregado en diciembre de 2008 con commit 11920d28da en el "repositorio de git de Git", si puedo decirlo.
Además de la respuesta aceptada, si su 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.git
directorio.
Esto no es nada de qué preocuparse; el archivo todavía está en el repositorio, pero solo como un "objeto suelto". No se copiará a otros repositorios (a través de clonar, empujar), y el espacio se recuperará eventualmente, aunque tal vez no muy pronto. Si está ansioso, puede correr:
git gc --prune=now
Actualizar (lo que sigue es mi intento de aclarar alguna confusión que pueda surgir de las respuestas más votadas):
Entonces, ¿cuál es el verdadero deshacer degit add
?
git reset HEAD <file>
?
o
git rm --cached <file>
?
Estrictamente hablando, y si no me equivoco: ninguno .
git add
no se puede deshacer forma segura, en general.
Recordemos primero lo que git add <file>
realmente hace:
Si <file>
se no rastreado previamente , git add
lo agrega a la caché , con su contenido actual.
Si <file>
fue ya rastreado , git add
guarda el contenido actual (instantánea, versión) a la caché. En Git, esta acción todavía se llama agregar , (no solo actualizarla ), porque dos versiones diferentes (instantáneas) de un archivo se consideran dos elementos diferentes: por lo tanto, de hecho, estamos agregando un nuevo elemento a la memoria caché, para ser eventualmente comprometido después.
A la luz de esto, la pregunta es ligeramente ambigua:
Agregué por error archivos usando el comando ...
El escenario del OP parece ser el primero (archivo no rastreado), queremos que el "deshacer" elimine el archivo (no solo el contenido actual) de los elementos rastreados. Si este es el caso, entonces está bien ejecutar 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 erróneamente 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 HEAD
no funciona, perogit rm --cached
funciona: un nuevo repositorio (sin confirmaciones). Pero, realmente, este es un caso prácticamente irrelevante.
Segundo: tenga en cuenta que git reset HEAD
no puede recuperar mágicamente el contenido del archivo previamente almacenado en caché, solo lo vuelve a sincronizar desde HEAD. Si nuestra equivocadagit add
guía sobrescribió una versión previa no confirmada, no podemos 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 solo seguimos el flujo de trabajo perezoso habitual de hacer 'git add' solo para agregar nuevos archivos (caso 1), y actualizamos nuevos contenidos a través del git commit -a
comando commit .
* (Editar: lo anterior es prácticamente correcto, pero aún puede haber algunas formas un poco hackeadas / complicadas para recuperar los cambios que se organizaron, pero no se cometieron y luego se sobrescribieron; vea los comentarios de Johannes Matokic e iolsmit)
git cat-file
podría usarse para recuperar su contenido.
git add
es a través de git fsck --unreachable
una lista de todos los obj inalcanzables, que luego puede inspeccionar git show SHA-1_ID
o git fsck --lost-found
> Escribir objetos colgantes en .git/lost-found/commit/
o .git/lost-found/other/
, según el tipo. Ver tambiéngit fsck --help
Deshacer un archivo que ya se ha agregado es bastante fácil con Git. Para restablecer myfile.txt
, que ya se han agregado, use:
git reset HEAD myfile.txt
Explicación:
Después de organizar los archivos no deseados, puede deshacerlos git reset
.Head
es la cabecera 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 rm --cached . -r
"des-agregará" todo lo que haya agregado de su directorio actual de forma recursiva
git reset HEAD <file>
diríafatal: Failed to resolve 'HEAD' as a valid ref.
correr
git gui
y elimine todos los archivos manualmente o seleccionándolos y haciendo clic en el botón Unstage from commit .
git-gui
..." :)
Git tiene comandos para cada acción imaginable, pero necesita un amplio conocimiento para hacer las cosas bien y por eso es contraintuitivo en el mejor de los casos ...
Lo que hiciste antes:
git add .
, o git add <file>
.Lo que quieras:
Elimine el archivo del índice, pero manténgalo versionado y deje cambios sin confirmar en la copia de trabajo:
git reset head <file>
Restablezca el archivo al último estado desde HEAD, deshaciendo los cambios y eliminándolos del índice:
# Think `svn revert <file>` IIRC.
git reset HEAD <file>
git checkout <file>
# If you have a `<branch>` named like `<file>`, use:
git checkout -- <file>
Esto es necesario ya git reset --hard HEAD
que no funcionará con archivos individuales.
Eliminar <file>
del índice y el control de versiones, manteniendo el archivo sin versión con cambios en la copia de trabajo:
git rm --cached <file>
Eliminar <file>
de la copia de trabajo y versionar completamente:
git rm <file>
reset head
deshace sus cambios actuales, pero git todavía está monitoreando el archivo. rm --cached
elimina el archivo del control de versiones, por lo que git ya no lo comprueba en busca de cambios (y también elimina los cambios actuales eventualmente indexados, indicados a git por el anterior add
), pero el archivo modificado se guardará en su copia de trabajo, es decir, en su carpeta de archivos en el disco duro.
git reset HEAD <file>
temporal: el comando se aplicará solo a la próxima confirmación, pero git rm --cached <file>
se desestabilizará hasta que se agregue nuevamente git add <file>
. Además, git rm --cached <file>
significa que si empuja esa rama al control remoto, cualquiera que tire de la rama obtendrá el archivo REALMENTE eliminado de su carpeta.
La pregunta no está claramente planteada. La razón es que git add
tiene dos significados:
git rm --cached file
.git reset HEAD file
.En caso de duda, use
git reset HEAD file
Porque hace lo esperado en ambos casos.
Advertencia: si lo hace git rm --cached file
en un archivo que fue modificado (un archivo que existía antes en el repositorio), ¡entonces el archivo se eliminará git commit
! Todavía existirá en su sistema de archivos, pero si alguien más retira su confirmación, el archivo se eliminará de su árbol de trabajo.
git status
le dirá si el archivo era nuevo o modificado :
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: my_new_file.txt
modified: my_modified_file.txt
git rm --cached somefile
. Espero que esta respuesta suba por la página a una posición destacada donde pueda proteger a los novatos de ser engañados por todas las afirmaciones falsas.
Si está en su confirmación inicial y no puede usar git reset
, simplemente declare "bancarrota Git" y elimine la .git
carpeta y comience de nuevo
git add -A && git rm --cached EXCLUDEFILE && git commit -m 'awesome commit'
(Esto también funciona cuando no hay confirmaciones anteriores, Failed to resolve 'HEAD'
problema re )
Según muchas de las otras respuestas, puede usar git reset
PERO:
Encontré esta gran publicación que realmente agrega el comando Git (bueno, un alias) para git unadd
: ver git unadd para más detalles o ...
Simplemente,
git config --global alias.unadd "reset HEAD"
Ahora usted puede
git unadd foo.txt bar.txt
Úselo git add -i
para eliminar archivos recién agregados de su próxima confirmación. Ejemplo:
Agregar el archivo que no quería:
$ git add foo
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: foo
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
# [...]#
Entrando en el complemento interactivo para deshacer su complemento (los comandos escritos aquí en git son "r" (revertir), "1" (la primera entrada en la lista muestra revertir), 'return' para salir del modo revertir y "q" (dejar):
$ git add -i
staged unstaged path
1: +1/-0 nothing foo
*** Commands ***
1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
What now> r
staged unstaged path
1: +1/-0 nothing [f]oo
Revert>> 1
staged unstaged path
* 1: +1/-0 nothing [f]oo
Revert>>
note: foo is untracked now.
reverted one path
*** Commands ***
1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
What now> q
Bye.
$
¡Eso es! Aquí está su prueba, que muestra que "foo" está de vuelta en la lista sin seguimiento:
$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
# [...]
# foo
nothing added to commit but untracked files present (use "git add" to track)
$
git remove
o git rm
puede usarse para esto, con la --cached
bandera. Tratar:
git help rm
git rm --cached ...
eliminará archivos de un repositorio de git. Todavía existirán en su computadora, pero esto es MUY diferente de los cambios no escalonados en un archivo. Para cualquiera que se encuentre con esto, no es una respuesta válida a la pregunta.
Aquí hay una manera de evitar este molesto problema cuando comienza un nuevo proyecto:
git init
.Git hace que sea realmente difícil hacerlo git reset
si no tienes ninguna confirmación. Si crea una pequeña confirmación inicial solo por el hecho de tener una, después de eso puede hacerlo git add -A
y git reset
tantas veces como desee para hacer todo bien.
Otra ventaja de este método es que si luego se encuentra con problemas de final de línea y necesita actualizar todos sus archivos, es fácil:
autocrlf
valor ... Esto no funcionará en todos los proyectos, dependiendo de la configuración.
git reset somefile
y git reset
ambos trabajan antes de hacer el primer commit, ahora. Este ha sido el caso desde varios lanzamientos de Git.
Tal vez Git ha evolucionado desde que publicaste tu pregunta.
$> git --version
git version 1.6.2.1
Ahora puedes probar:
git reset HEAD .
Esto debería ser lo que estás buscando.
Tenga en cuenta que si no puede especificar una revisión, debe incluir un separador. Ejemplo de mi consola:
git reset <path_to_file>
fatal: ambiguous argument '<path_to_file>': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
git reset -- <path_to_file>
Unstaged changes after reset:
M <path_to_file>
(Git versión 1.7.5.4)
git reset <path>
y funciona bien sin un separador. También estoy usando git 1.9.0. ¿Quizás no funciona en versiones anteriores?
Para eliminar archivos nuevos del área de preparación (y solo en el caso de un archivo nuevo), como se sugirió anteriormente:
git rm --cached FILE
Use rm --cached solo para nuevos archivos agregados accidentalmente.
--cached
es una parte realmente importante.
Para restablecer cada archivo en una carpeta particular (y sus subcarpetas), puede usar el siguiente comando:
git reset *
git status
para ver cualquier cosa restante y restablecerlo manualmente, es decir git reset file
.
Use el *
comando para manejar múltiples archivos a la vez:
git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*
etc.
.*
o.*.prj
Simplemente git reset
escríbalo volverá atrás y es como si nunca hubiera escrito git add .
desde su última confirmación. Asegúrese de haberse comprometido antes.
Supongamos que creo un nuevo archivo newFile.txt
:
Supongamos que agrego el archivo accidentalmente git add newFile.txt
:
Ahora quiero deshacer este complemento, antes de confirmar git reset newFile.txt
:
Para un archivo específico:
- git reset my_file.txt
- git checkout my_file.txt
Para todos los archivos agregados:
- git reset
- Git Checkout.
Nota: el pago cambia el código en los archivos y pasa al último estado actualizado (comprometido). restablecer no cambia los códigos; solo restablece el encabezado.
git reset <file>
y git checkout <file>
.
Este comando eliminará sus cambios:
git reset HEAD filename.txt
También puedes usar
git add -p
para agregar partes de archivos.
También hay modo interactivo:
git add -i
Elija la opción 3 para eliminar archivos. En mi caso, a menudo quiero agregar más de un archivo, y con el modo interactivo puede usar números como este para agregar archivos. Esto tomará todo menos 4: 1, 2, 3 y 5
Para elegir una secuencia, simplemente escriba 1-5 para tomar todo del 1 al 5.
Para deshacer git add
, use:
git reset filename
git reset filename.txt
Eliminará un archivo llamado filename.txt del índice actual, el área "a punto de confirmarse", sin cambiar nada más.
git add myfile.txt
# Esto agregará su archivo a la lista de compromisos
Muy opuesto a este comando es,
git reset HEAD myfile.txt # This will undo it.
entonces, estarás en el estado anterior. Se especificará nuevamente en la lista sin seguimiento (estado anterior).
Se restablecerá la cabeza con ese archivo especificado. entonces, si su cabeza no tiene los medios, simplemente lo restablecerá.
En Sourcetree puede hacerlo fácilmente a través de la GUI. Puede verificar qué comando usa Sourcetree para quitar el escenario de un archivo.
Creé un nuevo archivo y lo agregué a Git. Luego lo desestimé usando la GUI de Sourcetree. Este es el resultado:
Desinstalar archivos [12/08/15 10:43] git -c diff.mnemonicprefix = false -c core.quotepath = false -c credential.helper = sourcetree reset -q - ruta / a / archivo / nombre de archivo.java
Sourcetree utiliza reset
para desestabilizar nuevos archivos.
git reset filename.txt
Eliminará un archivo llamado filename.txt del índice actual, el área "a punto de confirmarse", sin cambiar nada más.
HEAD
ohead
ahora pueden usar@
en su lugarHEAD
. Vea esta respuesta (última sección) para saber por qué puede hacer eso.git checkout
no elimina los cambios por etapas del índice de confirmación. Solo revierte los cambios no organizados en la última revisión comprometida, que por cierto tampoco es lo que quiero, quiero esos cambios, solo los quiero en una confirmación posterior.