Revertir cambios a un archivo en una confirmación

126

Quiero revertir los cambios realizados por un commit particular a un archivo dado solamente.

¿Puedo usar el comando git revert para eso?

¿Alguna otra forma simple de hacerlo?

Lakshman Prasad
fuente
Extraño ... ¿por qué el cambio después de todos esos años?
VonC

Respuestas:

222

La forma más limpia que he visto de hacer esto se describe aquí.

git show some_commit_sha1 -- some_file.c | git apply -R

Similar a la respuesta de VonC pero usando git showy git apply.

mgalgs
fuente
10
Bien hecho. La solución de script es demasiado para esto. ¿Por qué no puede haber solo git revert sha-1 filename?
Mark Edington
16
Esto funciona en mi Mac, pero en Windows (bajo Cygwin) me da:fatal: unrecognized input
Kedar Mhaswade
1
@MerhawiFissehaye: Creo que git checkout solo revertirá los cambios nuevamente para volver al estado que estaba comprometido. Di 'git add filename; git commit --amend 'para eliminar el archivo de commit.
ViFI
3
Solo un consejo, casi siempre tengo que agregar la -3bandera para que git solicite la fusión tripartita cuando falla el parche, ya que generalmente estoy corrigiendo un cambio un poco en el tiempo.
angularsen
2
Quizás sea obvio para la mayoría, pero asegúrese de some_file.cincluir la ruta al archivo si hay uno; de lo contrario, no parcheará nada en silencio :)
Warpling el
35

Suponiendo que está bien cambiar el historial de confirmación, aquí hay un flujo de trabajo para revertir los cambios en un solo archivo en una confirmación anterior:

Por ejemplo, desea revertir los cambios en 1 archivo ( badfile.txt) en commit aaa222:

aaa333 Good commit
aaa222 Problem commit containing badfile.txt
aaa111 Base commit

Rebase en la confirmación de la base, corrija la confirmación del problema y continúe.

1) Iniciar rebase interactivo:

git rebase -i aaa111

2) Marque la confirmación del problema para editar en el editor cambiando picka e(para editar):

e aaa222
pick aaa333

3) Revertir los cambios en el archivo incorrecto:

git show -- badfile.txt | git apply -R

4) Agregue los cambios y modifique la confirmación:

git add badfile.txt
git commit --amend

5) Termina el rebase:

git rebase --continue
tee
fuente
Solo quiero señalar que esto supone que puede editar el historial de git. Algunas respuestas anteriores crean una nueva confirmación que revierte el cambio particular sin editar el historial, que no siempre es posible / permitido.
angularsen
Fantástico. Esto era exactamente lo que estaba buscando. Ya tenía esta idea, pero me confundí al hacer el rebase interactivo que los archivos al hacerlo editno se mostraban como modificados. Pero git show -- badfile.txt | git apply -Rdieron la respuesta que necesitaba <3
mraxus
si entiendo este git apply -R elimina el commit en ese archivo y lo restablece al estado original modificado.
DaImTo
19

git revert es para todo el contenido del archivo dentro de un commit.

Para un solo archivo, puede escribirlo :

#!/bin/bash

function output_help {
    echo "usage: git-revert-single-file <sha1> <file>"
}

sha1=$1
file=$2

if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi

(De las utilidades git-shell-scripts de smtlaissezfaire )


Nota:

aquí se describe otra forma si aún no ha confirmado su modificación actual.

git checkout -- filename

git checkout tiene algunas opciones para un archivo, modificando el archivo desde HEAD, sobrescribiendo su cambio.


Dropped.on.Caprica menciona en los comentarios :

Puede agregar un alias a git para que pueda hacer git revert-file <hash> <file-loc>y revertir ese archivo específico.
Ver esta esencia .

[alias]
  revert-file = !sh /home/some-user/git-file-revert.sh
VonC
fuente
Solo para agregar a la discusión aquí, puede agregar un alias a git para que pueda hacer git revert-file <hash> <file-loc>y revertir ese archivo específico. Levanté esta respuesta (aunque tuve que hacer un par de ediciones para que funcione correctamente). Puede encontrar una copia de mi .gitconfigscript editado aquí: gist.github.com/droppedoncaprica/5b67ec0021371a0ad438
AlbertEngelB
@ Dropped.on.Caprica buen punto. Lo he incluido en la respuesta para mayor visibilidad.
VonC
12

Simplemente usaría la --no-commitopción git-reverty luego eliminaría los archivos que no desea revertir del índice antes de finalmente confirmarlo. Aquí hay un ejemplo que muestra cómo revertir fácilmente solo los cambios a foo.c en la segunda confirmación más reciente:

$ git revert --no-commit HEAD~1
$ git reset HEAD
$ git add foo.c
$ git commit -m "Reverting recent change to foo.c"
$ git reset --hard HEAD

El primero git-reset"desestabiliza" todos los archivos, para que luego podamos volver a agregar solo el archivo que queremos revertir. La final git-reset --hardelimina los reversos de archivos restantes que no queremos conservar.

Dan Molding
fuente
9

Mucho más simple:

git reset HEAD^ path/to/file/to/revert

luego

git commit --amend   

y entonces

git push -f

el archivo se ha ido y confirmar hash, mensaje, etc. es lo mismo.

Para descanso
fuente
Para completar, ¿necesitas un git checkout -- path/to/file/to/revertpaso? Además, no es cierto que el hash sea el mismo después, ¿verdad? La última oración podría ser mejor como algo así como: "El resultado es que la última confirmación se reemplaza por una nueva que solo difiere en que no contiene los cambios en el archivo revertido".
Kevin
@ Kevin probablemente tengas razón. Tendré que volver a verificar esa última línea, pero mirando hacia atrás desde hace un par de años, me sorprendería si el hash de confirmación no cambia.
Forrest
6
git reset HEAD^ path/to/file/to/revert/in/commit

El comando anterior sacará el archivo de la confirmación, pero se reflejará en git status.

git checkout path/to/file/to/revert/in/commit

El comando anterior revertirá los cambios (como resultado, obtendrá el mismo archivo que HEAD).

git commit

(Pase --amendpara enmendar el compromiso).

git push

Con esto, el archivo que ya está en el commit se elimina y se revierte.

Los pasos anteriores se deben seguir desde la rama donde se realiza la confirmación.

Bharath TS
fuente
5

Puedes seguir este procedimiento:

  1. git revert -n <*commit*>( -nrevierte todos los cambios pero no los confirma)
  2. git add <*filename*> (nombre de los archivos que desea revertir y confirmar)
  3. git commit -m 'reverted message' (agregue un mensaje para revertir)
  4. después de confirmar descarte los otros cambios de archivos para que los archivos permanezcan actualizados con los cambios que confirmó antes de la reversión
Imran Sahil
fuente
1

Si desea restablecer los cambios en un archivo desde su última confirmación, esto es lo que generalmente uso. Creo que esta es la solución más simple.

Tenga en cuenta que el archivo se agregará al área de preparación.

git checkout <prev_commit_hash> -- <path_to_your_file>

Espero eso ayude :)

Gabeeka
fuente