Eliminar archivos de Git commit

1613

Estoy usando Git y he comprometido algunos archivos usando

git commit -a

Más tarde, descubrí que se había agregado un archivo por error al commit.

¿Cómo puedo eliminar un archivo de la última confirmación?

Paleta
fuente
2
Este enlace es perfecto para su pregunta: stackoverflow.com/questions/307828/…
b3h3m0th
@CharlesB: sí, este es mi último compromiso
Lolly
8
¿Has empujado el commit al servidor?
Paritosh Singh
44
Simplemente lo hago usando:git reset filepath
felipekm

Respuestas:

3090

Creo que otras respuestas aquí son incorrectas, porque esta es una cuestión de mover los archivos confirmados por error de nuevo al área de preparación de la confirmación anterior, sin cancelar los cambios realizados en ellos. Esto se puede hacer como sugirió Paritosh Singh:

git reset --soft HEAD^ 

o

git reset --soft HEAD~1

Luego restablezca los archivos no deseados para dejarlos fuera de la confirmación:

git reset HEAD path/to/unwanted_file

Ahora confirme nuevamente, incluso puede reutilizar el mismo mensaje de confirmación:

git commit -c ORIG_HEAD  
juzzlin
fuente
86
Gracias por esto. Vale la pena agregar que si ya ha presionado su compromiso anterior (incorrecto) y ahora intenta git pushcorregir su repositorio, se quejará Updates were rejected because the tip of your current branch is behind its remote counterpart.. Si está seguro de que desea empujarlos (p. Ej., Es su tenedor), puede usar la -fopción para forzar el empuje, p git push origin master -f. Ej . (No le hagas esto a un repositorio aguas arriba del que otros están buscando)
andy magoon
57
git reset --soft HEAD^es mi operación de deshacer más común
funroll
2
@PabloFernandez, en primer lugar, la respuesta aceptada podría haber sido lo que estaba buscando el OP (Además, se publicó meses antes). En segundo lugar, las respuestas aceptadas siempre están en la parte superior, independientemente de la cantidad de votos.
MITjanitor
44
@PabloFernandez en la parte superior de todas las respuestas son tres pestañas que le permiten controlar el orden de las respuestas: activo , más antiguo y votos . Mi conjetura es suya está ajustado a más antiguo . Cámbielo a votos aunque la respuesta aceptada seguirá estando en la parte superior, esta respuesta será la segunda.
ahsteele
15
Sabía mucho de esto, git resetpero quería una manera de afectar el compromiso existente "en su lugar". Acabo de enterarme git commit -C. Entonces, para mí, lo que quiero es su receta exacta con un paso más, el "nuevo compromiso de nuevo" enunciado como git commit -C [hash of original HEAD commit from first step].
metamatt
323

ATENCION ! Si solo desea eliminar un archivo de su confirmación anterior y mantenerlo en el disco , lea la respuesta de juzzlin justo arriba.

Si esta es su última confirmación y desea eliminar completamente el archivo de su repositorio local y remoto , puede:

  1. eliminar el archivo git rm <file>
  2. comprometerse con la bandera de modificación: git commit --amend

La bandera de modificación le dice a git que se comprometa nuevamente, pero "fusionar" (no en el sentido de fusionar dos ramas) esta confirmación con la última confirmación.

Como se indicó en los comentarios, ¡usar git rmaquí es como usar el rmcomando mismo!

CharlesB
fuente
120
también puede usar git rm --cachedpara mantener los archivos en el disco
Arkadiy Kukarkin
14
Advertencia para aquellos que naveguen por esta respuesta: asegúrese de que desea ELIMINAR el archivo (como en ido ido ido!), No solo eliminarlo de la lista de Compromiso.
Scott Biggs
8
Para añadir a lo que otros dicen (y para que sea más fácil de recordar para no hacer esto a menos que realmente quiere): El rmen el gitcomando está haciendo lo rmmismo hace!
yo'
@CharlesB ¿Puedes agregar la nota del comentario de Arkadiy Kukarkin a tu respuesta para darle más visibilidad?
mopo922
2
Tenga en cuenta que los archivos aún se pueden restaurar, en caso de que haya cambiado de opinión, el commit antes git commit --amendtodavía está allí y se puede encontrar, por ejemplo, con git reflog. Por lo tanto, no es tan malo como sugieren los otros comentarios.
Steohan
165

Las respuestas existentes están hablando de eliminar los archivos no deseados de la última confirmación.

Si desea eliminar archivos no deseados de una vieja comprometerse (incluso de difusión) y no desea crear una nueva cometer, que es innecesaria, debido a la acción:

1)

Encuentre el commit al que desea que se ajuste el archivo.

git checkout <commit_id> <path_to_file>

puede hacerlo varias veces si desea eliminar muchos archivos.

2)

git commit -am "remove unwanted files"

3)

Encuentre el commit_id del commit en el que se agregaron los archivos por error , digamos "35c23c2" aquí

git rebase 35c23c2~1 -i  // notice: "~1" is necessary

Este comando abre el editor de acuerdo con su configuración. El predeterminado es vim.

Mueva la última confirmación, que debería ser "eliminar archivos no deseados", a la siguiente línea de la confirmación incorrecta ("35c23c2" en nuestro caso) y configure el comando como fixup:

pick 35c23c2 the first commit
fixup 0d78b28 remove unwanted files

Deberías ser bueno después de guardar el archivo.

Para terminar :

git push -f

Si desafortunadamente tiene conflictos, debe resolverlos manualmente.

Brian
fuente
2
¡Hacer esto con nano es fabuloso! Ctrl + K, Ctrl + U, poner una 'f', Ctrl + X, poner 'y', ¡y listo!
sequielo
66
Si realmente desea eliminar los archivos del repositorio (no el sistema de archivos), en lugar de simplemente revertirlos a una versión anterior, en lugar del paso 1, hágalo git rm --cached <file(s)>.
waldyrious
2
Espera, ¿puedes mover commits alrededor del archivo de rebase interactivo a voluntad?
Dan Rosenstark
2
Puede totalmente, pero puede (o no) tener conflictos.
Brian
66
Este proceso podría facilitarse un poco si se agrega --fixup=35c23c2al git commitcomando. Esto configurará la confirmación automáticamente como una reparación de la confirmación requerida y, por lo tanto, no necesitará especificarla en el rebase. Además, si agrega --autosquashal git rebasecomando, git moverá automáticamente su confirmación a la ubicación correcta, por lo que no necesita hacer nada en el rebase interactivo: solo guarde el resultado (lo que significa que ni siquiera necesita -imarcar, aunque me gusta usarlo de todos modos para asegurarme de que todo se vea como esperaba).
Guss
144

Como indica la respuesta aceptada, puede hacerlo restableciendo todo el commit. Pero este es un enfoque bastante pesado.
Una forma más limpia de hacer esto sería mantener la confirmación y simplemente eliminar los archivos modificados.

git reset HEAD^ -- path/to/file
git commit --amend --no-edit

El git resettomará el archivo como lo fue en la confirmación anterior, y la etapa en el índice. El archivo en el directorio de trabajo está intacto.
El git commitentonces comprometerse y aplastar el índice en la corriente cometió.

Básicamente, esto toma la versión del archivo que estaba en la confirmación anterior y la agrega a la confirmación actual. Esto no produce ningún cambio neto, por lo que el archivo se elimina efectivamente de la confirmación.

Patricio
fuente
55
Esta es una respuesta mucho mejor para eliminar solo un archivo, sin revisar todo el commit.
nimish
Esto es exactamente lo mismo que esta respuesta: D stackoverflow.com/a/27340569/1623984
ThatsAMorais
@ThatsAMorais de hecho :-). Me pregunto si esta pregunta se fusionó con otra, y es por eso que no la vi. O tal vez solo estoy ciego. En cualquier caso, creo que me inclino a dejarlo ya que según los votos parece ser más popular (tal vez la gente prefiere la respuesta corta y directa).
Patrick
¡Por supuesto déjalo! :) Claramente teníamos la idea correcta, y el propósito es ayudar. Creo que la fusión es una buena teoría.
ThatsAMorais
¿Cómo haces esto si ya empujaste a una rama en github? Traté de presionar después de hacer esta corrección y recibí el mensaje "Las actualizaciones fueron rechazadas porque la punta de su rama actual está detrás de la pista: su contraparte remota".
Ollie Williams
41

Si no ha presionado los cambios en el servidor, puede usar

git reset --soft HEAD~1

Restablecerá todos los cambios y volverá a una confirmación

Si ha presionado sus cambios, siga los pasos que respondió @CharlesB

Paritosh Singh
fuente
2
-1 git reset elimina los cambios ocurridos en el archivo del área de preparación, aquí el cambio se ha confirmado
CharlesB
OK, pero mantendré mi voto negativo ya que no es lo que quiere el OP :) lo siento
CharlesB
está bien para mí, pero por qué el oponente no quiere esto. ¿Cuál es el problema?
Paritosh Singh
no es un gran problema, pero porque el OP quiere eliminar el archivo no deseado de la última confirmación, y simplemente se restablece al estado antes de confirmar. aun así tienes que rehacer el commit.
CharlesB
3
@Aris usa <git diff --cached> para ver los cambios
Paritosh Singh
37

¡Eliminar el archivo usando rm lo eliminará!

Siempre está agregando a un commit en git en lugar de eliminar, por lo que en este caso devuelva el archivo al estado en el que estaba antes del primer commit (esto puede ser una acción de eliminación 'rm' si el archivo es nuevo) y luego vuelva a confirmar y el archivo se irá.

Para devolver el archivo a algún estado anterior:

    git checkout <commit_id> <path_to_file>

o para devolverlo al estado en el HEAD remoto:

    git checkout origin/master <path_to_file>

luego corrija la confirmación y debería encontrar que el archivo ha desaparecido de la lista (¡y no se ha eliminado de su disco!)

Bob Flannigon
fuente
36
git checkout HEAD~ path/to/file
git commit --amend
Denis Shchepetov
fuente
1
Esta es la mejor manera de modificar la última confirmación, la que no se ha enviado. Esto restablecerá los cambios en un archivo, eliminando efectivamente ese archivo de la última confirmación.
Alex Bravo
Esto también cambió el archivo. ¿Cómo preservar los cambios locales en el archivo?
theonlygusti
29

Lo siguiente desestabilizará solo el archivo que deseaba, que es lo que solicitó el OP.

git reset HEAD^ /path/to/file

Verás algo como lo siguiente ...

Cambios a realizar: (use "git reset HEAD ..." para quitar el escenario)

modificado: / ruta / a / archivo

Cambios no organizados para commit: (use "git add ..." para actualizar lo que se confirmará) (use "git checkout - ..." para descartar cambios en el directorio de trabajo)

modificado: / ruta / a / archivo

  • "Cambios a confirmar" es la versión anterior del archivo antes de la confirmación. Esto se verá como una eliminación si el archivo nunca existió. Si confirma este cambio, habrá una revisión que revierte el cambio al archivo en su rama.
  • "Cambios no organizados para la confirmación" es el cambio que confirmó y el estado actual del archivo

En este punto, puede hacer lo que quiera con el archivo, como restablecer a una versión diferente.

Cuando estés listo para comprometerte:

git commit --amend -a

o (si tiene otros cambios en curso que todavía no desea confirmar)

git commit add /path/to/file
git commit --amend
ThatsAMorais
fuente
3
La respuesta de juzzlin es excelente, pero es excesivo desestabilizar todo el commit cuando solo deseas desarmar uno. Desinstalar todo el commit puede causar problemas si actualmente tiene cambios no escalonados en los archivos en ese commit que no desea perder.
ThatsAMorais
27

Te explicaré con el ejemplo.
Deje A, B, C ser 3 confirmaciones sucesivas. La confirmación B contiene un archivo que no debería haberse confirmado.

git log  # take A commit_id
git rebase -i "A_commit_ID" # do an interactive rebase
change commit to 'e' in rebase vim # means commit will be edited
git rm unwanted_file
git rebase --continue
git push --force-with-lease <branchName>    
Moaz Rashad
fuente
Si el archivo en particular no está en el último o anterior commit, esta es la forma más elegante. Incluso diría que es la forma más elegante en general. Me gusta el rebase interactivo.
bvgheluwe
Para un solo compromiso, cambie noopa edit [A_commit_ID]oe [A_commit_ID]
TamusJRoyce
23

Simplemente puedes intentarlo.

git reset --soft HEAD~1

y crea una nueva confirmación.

Sin embargo, hay un software impresionante "gitkraken". lo que facilita trabajar con git.

HamzaMushtaq
fuente
1
Y solo para tener en cuenta: después de esto, debería hacer git commit --amendque la eliminación del archivo se actualice en su última confirmación; y luego, puedes comprobar que efectivamente se ha eliminado congit log -1 --stat
sdbbs
13
git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "removed unwanted file from git"

te dejará el archivo local todavía. Si tampoco desea el archivo localmente, puede saltarse la opción --cached.

Si todo el trabajo está en su sucursal local, debe mantener el archivo en una confirmación posterior, y como tener un historial limpio, creo que una forma más simple de hacerlo podría ser:

git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit --squash <commit_id>
git add <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "brand new file!"
git rebase --interactive <commit_id>^

y luego puede finalizar el rebase con facilidad sin tener que recordar comandos más complejos o confirmar mensajes o escribir tanto.

Bryan Buckley
fuente
Esto funciona para mi. Supongo que si desea volver a agregar los archivos a la mezcla, solo use git add -A o git add. y están de vuelta
Alexander Mills
11

Usar git GUI puede simplificar la eliminación de un archivo de la confirmación anterior.

Suponiendo que esta no es una rama compartida y no le importa reescribir el historial , ejecute:

git gui citool --amend

Puede desmarcar el archivo que se confirmó por error y luego hacer clic en "Confirmar".

ingrese la descripción de la imagen aquí

El archivo se elimina de la confirmación, pero se mantendrá en el disco . Entonces, si desmarcó el archivo después de agregarlo por error, se mostrará en su lista de archivos no rastreados (y si desmarcó el archivo después de modificarlo erróneamente, se mostrará en sus cambios no organizados para la lista de confirmación).

JDiMatteo
fuente
2
En Ubuntu, puede instalar git gui consudo apt-get install git-gui
JDiMatteo
¡Gracias! Estaba atrapado con un problema (¿error?) En el que se agregaba una carpeta que contenía un repositorio .git y todos los comandos de eliminación normales no funcionaban. Esto sin embargo ayudó. Siendo unas pocas confirmaciones, primero utilicé git rebase -i HEAD~4y luego ejecuté su comando para abrir el editor. Otra nota: "Unstaging" se puede encontrar en el menú "Commit".
Johny Skovdal
La solución más fácil de todas. Más simple de recordar. Y mucho menos propenso a errores que usar git reset --soft HEAD^(recordando el argumento --soft), seguido de git commit -c ORIG_HEAD(en lugar de --amend, que arruina todo).
Brent Faust
9

Si desea preservar su confirmación (tal vez ya pasó algún tiempo escribiendo un mensaje de confirmación detallado y no desea perderlo), y solo desea eliminar el archivo de la confirmación, pero no del repositorio por completo:

git checkout origin/<remote-branch> <filename>
git commit --amend
mattexx
fuente
6

Realice una secuencia de los siguientes comandos:

//to remove the last commit, but preserve changes  
git reset --soft HEAD~1

//to remove unneded file from the staging area  
git reset HEAD `<your file>` 

//finally make a new commit  
git commit -m 'Your message'
Sergey Onishchenko
fuente
Intenté seguir estos pasos, y veo este error de error: no pude colocar algunas referencias a 'git ...' Para evitar que pierdas el historial, se rechazaron las actualizaciones que no son de avance rápido. Combina los cambios remotos (p. Ej. 'git pull') antes de presionar nuevamente. Consulte la sección 'Nota sobre avance rápido' de 'git push --help' para más detalles. (después de git pull tengo los mismos cambios)
Dezigo
Significa que el estado de su repositorio remoto ha cambiado mientras realizaba su trabajo local. Y después de 'git pull', sus cambios locales deberían fusionarse con los remotos, eso es todo. Por supuesto, sus cambios deben permanecer.
Sergey Onishchenko
En otras palabras, si obtiene ese error @Dezigo, agregue el indicador -f para forzar la actualización.
jungledev
5

Solo quería complementar la respuesta principal ya que tenía que ejecutar un comando adicional:

git reset --soft HEAD^
git checkout origin/master <filepath>

¡Salud!

andrepo
fuente
Bienvenidos. Esta respuesta sería mejor si explicaras lo que realmente hacen los comandos.
Mark Chorley,
3

Algo que funcionó para mí, pero aún creo que debería haber una mejor solución:

$ git revert <commit_id>
$ git reset HEAD~1 --hard

Simplemente deje el cambio que desea descartar en el otro commit, vea otros

$ git commit --amend // or stash and rebase to <commit_id> to amend changes
saiyancoder
fuente
3

git reset --soft HEAD^revierte su confirmación, y cuando escribe git status, le dice qué hacer:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
cardamomo
fuente
2

En realidad, creo que una forma más rápida y fácil es usar el modo interactivo git rebase.

git rebase -i head~1  

(o cabeza ~ 4, hasta dónde quieres llegar)

y luego, en lugar de 'elegir', use 'editar'. No me di cuenta de lo poderosa que es 'editar'.

https://www.youtube.com/watch?v=2dQosJaLN18

Espero que lo encuentren útil.

Mate
fuente
el video dura 10 minutos y no es tan útil
MolbOrg
2

Tuve el mismo problema cuando tengo cambios en una sucursal local donde quería revertir solo un archivo. Lo que funcionó para mí fue ...

( Feature / target_branch a continuación es donde tengo todos mis cambios, incluidos los que quería deshacer para un archivo específico)

( origin / feature / target_branch es la rama remota a la que quiero enviar mis cambios)

( característica / puesta en escena es mi rama de puesta en escena temporal en la que presionaré desde todos mis cambios deseados, excluyendo el cambio en ese archivo)

  1. Crear una sucursal local desde mi origen / función / target_branch - lo llamé función / organización

  2. Fusioné mi función de sucursal local de trabajo / target_branch con la función / sucursal provisional

  3. Se desprotegió la función / puesta en escena y luego se reinició git --soft ORIG_HEAD (Ahora todos los cambios de la función / puesta en escena se organizarán pero no se confirmarán).

  4. Desinstaló el archivo que he verificado previamente con cambios innecesarios

  5. Cambió la rama ascendente para la característica / puesta en escena a origen / característica / target_branch

  6. Cometí el resto de los cambios organizados y empujé río arriba a mi origen / función / objetivo_branco remoto

usuario1201303
fuente
1

Si ya no necesita ese archivo, puede hacer

git rm file
git commit --amend
git push origin branch
tven
fuente
1

Si está utilizando GitHub y aún no ha empujado la confirmación, GitHub Desktop resuelve este problema fácilmente:

  1. Elija Repositorio -> Deshacer la confirmación más reciente
  2. Anule la selección del archivo que agregó por error. Su mensaje de confirmación anterior ya estará en el cuadro de diálogo.
  3. ¡Presione el botón Confirmar!
Ron
fuente
1

Si desea eliminar archivos de confirmaciones anteriores, use filtros

git filter-branch --prune-empty --index-filter 'git rm --ignore-unmatch --cached "file_to_be_removed.dmg"'

Si ves este error:

No se puede crear una nueva copia de seguridad. Ya existe una copia de seguridad anterior en refs / original / Force sobrescribiendo la copia de seguridad con -f

Simplemente elimine las copias de seguridad de las referencias en su repositorio local

$ rm -rf .git/refs/original/refs
wilo087
fuente
1

si aún no empujas tus cambios a git

git reset --soft HEAD~1

Restablecerá todos los cambios y volverá a una confirmación

Si esta es la última confirmación que realizó y desea eliminar el archivo del repositorio local y remoto, intente esto:

git rm <file>
 git commit --amend

o mejor :

restablecer primero

git reset --soft HEAD~1

restablecer el archivo no deseado

git reset HEAD path/to/unwanted_file

comprometerse de nuevo

git commit -c ORIG_HEAD  
TanvirChowdhury
fuente
es lo mismo que el anterior pero incluso realmente ayudó a verificar
Reshma
0

Esto funcionó para mí para eliminar el archivo del repositorio de bit bucket que empujé el archivo a la ramificación inicialmente.

git checkout origin/develop <path-to-file>
git add <path-to-file>
git commit -m "Message"
git push
swathi
fuente
0

Copié los archivos actuales en una carpeta diferente, luego me deshago de todos los cambios no acelerados:

git reset --hard @{u}

Luego copia las cosas de nuevo. Comprometerse, empujar.

Miranda
fuente
0

Simplemente puede usar este comando:

git restore --staged <file>
suulisina
fuente
0
Here is the step to remove files from Git Commit.

>git reset --soft HEAD^1(either commitid ) -- now files moved to the staging area.
>git rm --cached filename(it will removed the file from staging area)
>git commit -m 'meaningfull message'(Now commit the required files)
Sheo Dayal Singh
fuente
-1

Ninguna de las respuestas en este momento es razonable. Parece que hay suficiente demanda para que se proponga una solución real: https://github.com/git/git/blob/master/Documentation/SubmittingPatches

git --uncommit <nombre de archivo>

sería bueno. Entiendo que no queremos modificar el historial, pero si soy local y accidentalmente agregué un archivo local de "pirateo" y quiero eliminarlo del commit, esto sería muy útil.

Bob9630
fuente