git selectivo revierte los cambios locales de un archivo

149

En mi repositorio git que está rastreando un repositorio svn, he realizado varias ediciones en un solo archivo.

Ahora quiero revertir esos cambios (como svn revert), pero solo partes del archivo.

Quiero poder ver las diferencias en el archivo, descartar (revertir) los cambios que no quiero y retener los cambios que quiero.

el

git add -i 

El comando parece tener una opción para hacerlo, pero todavía no quiero organizar esto.

Pradeep
fuente

Respuestas:

91

Puedes hacerlo directamente con git checkout -p. Ver la respuesta de Daniel Stutzbach a continuación.


Antigua respuesta (antes checkout -pse introdujo):

Puedes hacerlo así:

git add -i

(seleccione los trozos que desea mantener)

git commit -m "tmp"

Ahora tiene una confirmación con solo los cambios que desea mantener, y el resto no está en escena.

git reset --hard HEAD

En este punto, los cambios no confirmados se han descartado, por lo que tiene un directorio de trabajo limpio, con los cambios que desea mantener confirmados en la parte superior.

git reset --mixed HEAD^

Esto elimina la última confirmación ('tmp'), pero mantiene las modificaciones en su directorio de trabajo, sin etapas.

EDITAR: reemplazado --softpor --mixed, para limpiar el área de preparación.

Paolo Capriotti
fuente
esto confirmará los cambios que quiero conservar, ¿no? No quiero comprometer esos cambios todavía. mm tal vez estoy tomando compromisos demasiado en serio. Tal vez debería relajarme ahora, ya que todo está en un repositorio local. por cierto, ¿qué hace git reset --soft HEAD ^?
Pradeep
"git reset --soft HEAD ^" deshace una confirmación en el sentido de que mantiene el directorio y el índice de trabajo como era, y mueve la confirmación actual de la rama uno.
Jakub Narębski
Gracias Jakub Paolo, ¿por qué se requeriría un restablecimiento parcial a la cabeza - 1 aquí? la confirmación parcial y el restablecimiento completo deberían ser suficientes, ¿no es así para mantener algunos cambios y descartar otros?
Pradeep
1
La respuesta de Daniel a continuación es muy simple y parece la forma correcta de hacerlo.
Umang
309

Creo que puedes hacerlo de la manera más sencilla con:

git checkout -p <optional filename(s)>

Desde la página del manual:

   −p, −−patch
       Interactively select hunks in the difference between the <tree−ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree−ish> was specified, the index).
       This means that you can use git checkout −p to selectively discard
       edits from your current working tree.
Daniel Stutzbach
fuente
1
Además, si no desea hacer esto de forma selectiva, puede usar "git checkout - <file> ..." para descartar los cambios.
db42
¿Se trata de directorios?
bbum
1
Esto parece fallar mucho cuando descarto los cambios ("error: el parche falló <archivo>", "error: el parche <archivo> no se aplica"). Curiosamente, recibiré esos errores cuando use la aopción en modo parche para descartar un archivo completo, pero git checkout -- <file>funciona como se esperaba. Alguien sabe por qué?
chrnola
Tuve ese error varias veces si el archivo ya había sido parcheado, por lo que el parche interactivo no estaba actualizado con los parches aplicados del archivo actual. Sucedió al usar una herramienta de interfaz gráfica de usuario como árbol de origen si descartaba un trozo dos veces accidentalmente. La segunda vez produciría ese error.
phyatt
3

Usted podría funcionar git diffen el archivo, guarde el diff resultante, editarlo para eliminar los cambios que no desea guardar, a continuación, ejecute a través patch -Rde deshacer los diferenciales restantes.

git diff file.txt> patch.tmp
# edit patch.tmp para eliminar los trozos que quieres mantener
parche -R <parche.tmp
Greg Hewgill
fuente
Tenía 2 trozos en mi archivo de parche y eliminé uno. No estoy seguro de cuál es la razón, pero el parche -R sigue siendo rechazado con esto.
Pradeep
2
Menciona en otro comentario que git diffmuestra todo el archivo como modificado. Esto generalmente ocurre cuando ha guardado el archivo usando diferentes finales de línea de lo que era anteriormente. Esto también provocaría el patchrechazo del archivo de revisión. ¿Suena eso como lo que pudo haber sucedido?
Greg Hewgill
tienes razón. los finales de línea se alternan cada vez que uso el comando parche. Estoy en Windows y estoy usando crema / vim. Necesito resolver esto primero, creo.
Pradeep
No pude resolver el problema con el parche en Windows. Aunque estoy seguro de que esto funciona, prefiero usar la receta de Paolo. Por el amor de esos comandos interactivos para trabajar con los diferenciales usando git add -i.
Pradeep
3

Parece que quieres

 git revert --no-commit $REVSISON 

Entonces puedes usar

 git diff --cached

para ver qué cambio se realizará antes de comprometerse (ya que revertir es solo un compromiso en una dirección hacia adelante que replica el inverso de un cambio en el pasado)

Si estuvieras con un repositorio Git puro, podrías, dependiendo de tus objetivos, utilizar rebase interactivo ( git rebase -i) para volver al commit que no te gustó y editar el commit retroactivamente para que los cambios que no te gusten nunca ocurran , pero eso es generalmente solo si SABES que nunca querrás volver a verlo.

Kent Fredric
fuente
Revertí como mencionaste en una revisión anterior (¿es correcto?) Y ahora git diff solo muestra el archivo completo como cambiado. ¿Se supone que muestra las ediciones que hice?
Pradeep
1

Al volver a leer la pregunta, parece que desea revertir los cambios que están en su árbol de trabajo y no los cambios que se han confirmado anteriormente, pero algunas de las otras respuestas hacen que parezca que mi lectura puede ser incorrecta. ¿Puedes aclarar?

Si los cambios están solo en su copia de trabajo, la forma más fácil de hacerlo es organizar los cambios que desea conservar:

git add -i <file>

Luego, descarte los cambios que no desea conservar revisando la versión de índice:

git checkout -- <file>

Luego, desarme los cambios si aún no los desea:

git reset -- <file>

Esta receta solo revierte los cambios seleccionados en el archivo (o los archivos que especifique) y no crea ninguna confirmación temporal que luego deba revertirse.

Si desea aplicar selectivamente solo algunos de los cambios realizados en confirmaciones anteriores, primero puede restablecer un archivo a un estado confirmado anterior:

git reset <commit_before_first_unwanted_change> -- <file>

A continuación, puede seguir la receta anterior git add -i <file>para organizar los cambios que desea conservar, git checkout -- <file>descartar los cambios no deseados y git reset -- <file>'desestabilizar' los cambios.

CB Bailey
fuente
0

Las opciones de línea de comando que se describen en las respuestas aquí son útiles cuando el archivo está en un servidor al que estoy accediendo a través de un terminal ssh. Sin embargo, cuando el archivo está en mi máquina local, prefiero la siguiente manera:

Abra el archivo en el editor de netbeans (que viene con soporte git). Netbeans pone marcas rojas / verdes / azules en los números de línea para indicar dónde se eliminó / agregó / modificó (respectivamente).

Al hacer clic con el botón derecho en cualquiera de estas marcas, tiene la opción de deshacer ese cambio. Además, puede hacer clic derecho en las marcas rojas y azules para ver la versión anterior en una ventana emergente.

Abhishek Anand
fuente