¿Revertir o retirar de forma selectiva los cambios en un archivo en Git?

88

¿Existe un comando que le permita deshacer parcialmente los cambios en un archivo (o archivos) en el directorio de trabajo?

Suponga que ha editado mucho un archivo pero se da cuenta de que desea deshacer algunos de los cambios al estado comprometido, pero no los otros cambios.

Estoy imaginando una opción para git checkoutque funcione de manera muy similar git add -p, es decir, revisa el archivo trozo a trozo y pregunta si desea conservarlo o no.

1800 INFORMACIÓN
fuente

Respuestas:

85

Podrías usar

git add -p <path>

para organizar los fragmentos que desea mantener en un archivo en particular, luego

git checkout -- <path>

para descartar los cambios del árbol de trabajo que no deseaba conservar, comprobando la versión provisional del archivo.

Finalmente, puedes usar

git reset -- <path>

para revertir la versión provisional del archivo a la versión confirmada más reciente del archivo para dejar los cambios sin etapas.

CB Bailey
fuente
Para este caso de uso simple, que cualquier otro sistema de control de versiones simplemente llama "revertir", ¿por qué el comando Git es tan oscuro?
Jan Hettich
5
@Jan ¿El comando de otros sistemas de control de versiones revertle permite seleccionar qué cambios dentro de un archivo se revierten? Sinceramente preguntando, ya que solo tengo experiencia con CVS y Git. En Git, git checkout -- path/to/filehay un solo comando que revierte todos los cambios en ese archivo, pero no es el mismo que el anterior.
michiakig
3
También hay git checkout --patchy git reset --patchque funcionan como git add --patchen la última versión de git.
Matt Connolly
2
@Rudie, --generalmente indican el final del análisis de opciones y que cualquier argumento que venga después debe interpretarse literalmente. Esto significa que no tendría que agregar ./antes ningún nombre de archivo que comience con un signo menos, si el nombre del archivo viene después --.
zrajm
cuando utilizo git checkout --patchla diferencia parece estar al revés. Los símbolos menos están AGREGANDO texto a mi copia de trabajo, y los símbolos más están ELIMINANDO líneas de mi copia de trabajo.
Felipe Alvarez
115

Con la versión de git> = 1.7.1 puedo

git checkout -p

No estoy seguro de cuándo se introdujo esta función.

este friki
fuente
11
Vale la pena mencionar que también puede hacer git reset -ppara desescender selectivamente los cambios del índice / área de ensayo. Tampoco sé de mi cabeza en qué versión de Git se introdujo esto.
Esta es la respuesta correcta, por qué no ha sido aceptada.
wukong
1
@wukong porque esta respuesta se publicó 2 años después de la pregunta. En este momento (2009), la respuesta de Charles fue la mejor solución
pomeh
8

git checkout $filerevierte el estado del archivo $fileal último estado comprometido. Creo que puede usar git checkout SHA-1 -- $filepara revertir el archivo a la confirmación identificada por SHA-1.

Koraktor
fuente
1
sí, no es exactamente lo que quiero, ya que quiero mantener algunos de los cambios que hice en el archivo y revertir los demás
1800 INFORMACIÓN
1

¿Cuántas confirmaciones necesitas para volver y seleccionar? Si es solo uno, tal vez tome una rama justo antes, revise el archivo que comprometió y luego use git add -ppara agregarlo como lo quería. Luego puede volver a donde estaba y verificar el archivo de su rama temporal.

es decir:

git checkout -b temp troublesome-commit^
git checkout troublesome-commit -- path/to/file
git add -p path/to/file
git commit -c troublesome-commit
git checkout @{-1}
git checkout temp -- path/to/file
git commit path/to/file
git branch -D temp

Otras alternativas incluyen volver atrás y editar la confirmación con git rebase -i(marcar la confirmación como edit, luego hacer una git reset HEAD^y rehacer la confirmación cuando se vuelve a colocar en el shell).

Si los cambios entre los que necesita seleccionar se distribuyen en una serie de confirmaciones, puede ser mejor extraerlos como parches (o un parche que los cubra todos) y editar manualmente el parche, eliminando los cambios que desea conservar. y alimentar el residuo en git apply --reverse.

arácnido
fuente
En realidad, no quiero revertir nada de lo que está comprometido, quiero deshacer los cambios que están solo en mi copia de trabajo
1800 INFORMACIÓN