¿Cómo deshacer solo ciertos archivos?

387

Me escondí mis cambios. Ahora quiero eliminar solo algunos archivos del alijo. ¿Cómo puedo hacer esto?

Morfeo
fuente
44
Creo que tienes que aplicar todo el alijo, pero luego puedes volver a esconderlo selectivamente.
Richard
44
@AbdouTahiri ¿Qué tiene de malo el alijo?
alex
32
@AbdouTahiri Uhhhh .. git stash es una característica legítima y extremadamente útil. Lo uso a diario. Digamos que un compañero de trabajo necesita que revise algo, pero estoy en medio de un complejo conjunto de cambios. No voy a cometer una pila de código roto solo para poder cambiar de rama. Voy a esconder, cambiar de rama, revisar, volver a cambiar, deshacer. ¿Le gustaría explicar quién o por qué se supone que "git stash" no se recomienda? El hecho de que su historial de alijo git esté confuso y sea difícil de leer no significa que todos los demás lo estén. Un conjunto de alijo git desordenado es solo un mal flujo de trabajo, no un defecto de Git.
dudewad
66
@alex Nada. No hay nada malo con git stash. Sigue usándolo.
dudewad

Respuestas:

462

Como se menciona a continuación , y se detalla en " ¿Cómo extraería un solo archivo (o cambios a un archivo) de un git stash? ", Puede aplicar el uso git checkouto git showrestaurar un archivo específico.

git checkout stash@{0} -- <filename>

Eso sobrescribe filename : asegúrese de no tener modificaciones locales, o tal vez desee fusionar el archivo escondido en su lugar .

(Como se ha comentado por Jaime M. , por cierto cáscara como tcsh donde tiene que escapar los caracteres especiales, la sintaxis sería: git checkout 'stash@{0}' -- <filename>)

o para guardarlo con otro nombre de archivo:

git show stash@{0}:<full filename>  >  <newfile>

(tenga en cuenta que aquí <full filename>está el nombre de ruta completo de un archivo relativo al directorio superior de un proyecto (piense: relativo a stash@{0})).

yucer sugiere en los comentarios :

Si desea seleccionar manualmente qué cambios desea aplicar desde ese archivo:

git difftool stash@{0}..HEAD -- <filename>

Vivek agrega en los comentarios :

Parece que " git checkout stash@{0} -- <filename>" restaura la versión del archivo en el momento en que se realizó el alijo - NO aplica (solo) los cambios escondidos para ese archivo.
Para hacer esto último:

git diff stash@{0}^1 stash@{0} -- <filename> | git apply

(como se ha comentado por peterflynn , puede ser necesario | git apply -p1en algunos casos, la eliminación de uno ( p1) barra inicial de los caminos tradicionales diff)


Como comentó: "unstash" ( git stash pop), entonces:

  • agregue lo que desea mantener al índice ( git add)
  • esconder el resto: git stash --keep-index

El último punto es lo que le permite mantener algunos archivos mientras guarda otros.
Se ilustra en " Cómo guardar solo un archivo de varios archivos que han cambiado ".

VonC
fuente
55
Esto no funciona si no puede git stash popdebido a conflictos de archivos. La respuesta de Balamurugan A me sirvió en ese caso.
Andrey
1
Si desea seleccionar manualmente qué cambios desea aplicar desde ese archivo, puede usar git difftool stash @ {0} .. HEAD - <filename>
yucer
55
Parece que "git checkout stash @ {0} - <nombre de archivo>" restaura la versión del archivo en el momento en que se realizó el alijo - NO aplica (solo) los cambios guardados para ese archivo. Para hacer lo último: "git diff stash @ {0} ^ 1 stash @ {0} - <nombre de archivo> | git apply"
Vivek
1
@JaimeM. Gracias. He incluido tu comentario en la respuesta para mayor visibilidad.
VonC
1
Suponiendo que eso unstashsignifica pop, como me parece que probablemente lo haría en la mayoría de los casos, esto solo responde parcialmente a la pregunta. ¿Cómo se eliminan las piezas aplicadas selectivamente del alijo para evitar conflictos y / o confusión posteriores al hacer estallar los cambios restantes?
DylanYoung
115
git checkout stash@{N} <File(s)/Folder(s) path> 

P.ej. Para restaurar solo el archivo ./test.c y la carpeta ./include desde el último escondite,

git checkout stash@{0} ./test.c ./include
Balamurugan A
fuente
12
¡Esta es la respuesta correcta! ¡El comando de línea única para aplicar solo los cambios escondidos de archivos específicos, funciona de maravilla!
niveles
1
Para aplicar (solo) los cambios guardados para el archivo: "git diff stash @ {N} ^ 1 stash @ {N} - <nombre de archivo> | git apply"
Vivek
Esto también funciona para mí. Simplemente seleccione selectivamente los archivos necesarios para usar desde stash y ya está. Estaba atrapado en esto, había usado una -abandera al crear el alijo.
Rajeev Ranjan
1
@ 4 niveles Creo que "aplicar cambios escondidos" no es lo que sucede, ¿verdad? Creo que "sobrescribir lo que tenga con la copia de alijo" es lo que sucede.
msouth
35

Creo que la respuesta de VonC es probablemente lo que quieres, pero aquí hay una forma de hacer una "aplicación git" selectiva:

git show stash@{0}:MyFile.txt > MyFile.txt
Mike Monkiewicz
fuente
44
Esto puede ser lo que desea en algunos casos, pero tenga en cuenta que este comando sobrescribirá en lugar de fusionarse con cualquier cambio en el directorio de trabajo.
Ruibarbo
Esto funciona para mí, ya que solo quería copiar un archivo que existe solo en el alijo y no me importó checkoutnada.
Tom Russell
1
Para Windows PowerShell: git show stash@`{0`}:Path/To/MyFile.txt |sc Path/To/MyFile.txt- los backticks son necesarios para que PS no interprete los corchetes especialmente, y sces necesario porque el >operador de PS tiene por defecto UTF-16 (en realidad UCS-2), que probablemente no sea lo que desea. La respuesta de @Balamurugan A no sufre estos problemas.
Ian Kemp
19

Primero lista todos los escondites

git stash list

stash@{0}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{1}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{2}: WIP on master: 7e450c81 Merge branch 'Offlineseite'

Luego muestre qué archivos están en el alijo (seleccionemos el alijo 1):

git stash show 1 --name-only

//Hint: you can also write
//git stash show stash@{1} --name-only

 ajax/product.php
 ajax/productPrice.php
 errors/Company/js/offlineMain.phtml
 errors/Company/mage.php
 errors/Company/page.phtml
 js/konfigurator/konfigurator.js

Luego aplique el archivo que desea:

git checkout stash@{1} -- <filename>

o carpeta completa:

git checkout stash@{1} /errors

También funciona sin, --pero se recomienda usarlos. Ver esta publicación

También es convencional reconocer un guión doble como una señal para detener la interpretación de opciones y tratar todos los argumentos siguientes literalmente.

Negro
fuente
1
Eso está más claro con esta edición. +1
VonC
1
Lo intenté de muchas maneras y esta era la que necesitaba. Me enfrenté a un problema que git stash poparrojó un error para los archivos no rastreados. gracias.
Ramin Firooz
10

Si usted git stash pop(sin conflictos) eliminará el alijo después de que se aplique. Pero si lo git stash applyhace, aplicará el parche sin eliminarlo de la lista de alijo. Luego puede revertir los cambios no deseados congit checkout -- files...

Ben Jackson
fuente
2
Para aclarar la parte de conflictos de esta publicación, si usted git stash popy HAY conflictos, deberá solucionarlos manualmente y NO se eliminará el alijo.
Thomas McCabe
6

Una forma más:

git diff stash@{N}^! -- path/to/file1 path/to/file2  | git apply -R
Lacho Tomov
fuente
2
Esta es la única respuesta correcta de la OMI. Usar checkouto showsobrescribirá ciegamente su archivo en lugar de simplemente aplicar cambios. "Una forma más" es quedarse corto.
Cambunctious
1
No obtengo path/to/file2el que desea diferenciar en el mismo archivo en su espacio de trabajo. Dejar el segundo camino funciona bien para mí. - Y recibo un mensaje de error usando la -Ropción ("¿aplicar el parche en reversa", tratando de parchear la versión oculta ?!). Así se ve mi versión de trabajo git diff stash@{N}^! -- path/to/file | git apply -.
ThomasH
"parche fallido"? Intente una fusión de 3 vías. ...| git apply -3 -
John Mee
6

Para usuarios de Windows: las llaves tienen un significado especial en PowerShell. Puede rodear con comillas simples o escapar con una tecla de retroceso. Por ejemplo:

git checkout 'stash@{0}' YourFile

Sin él, puede recibir un error:

Unknown switch 'e'

Janac Meena
fuente
3
Un sobresaliente en PowerShell por el mensaje de usuario menos útil que he visto este mes.
holdenweb