¿Cómo puedo extraer un solo archivo (o cambios en un archivo) de un alijo de git?

Resuelto Danny asked hace 15 años • 10 respuestas

¿Es posible extraer un solo archivo o una diferencia de un archivo de un alijo de git sin desactivar el conjunto de cambios del alijo?

Danny avatar Jul 10 '09 00:07 Danny
Aceptado

En la página de manual de git stash puedes leer (en la sección "Discusión", justo después de la descripción de "Opciones") que:

Un alijo se representa como una confirmación cuyo árbol registra el estado del directorio de trabajo y su primer padre es la confirmación en HEAD cuando se creó el alijo.

Por lo tanto, puede tratar el alijo (por ejemplo stash@{0}, es el primer alijo/el más alto) como una confirmación de fusión y usar:

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

Explicación: stash@{0}^1significa el primer padre del alijo dado, que, como se indica en la explicación anterior, es la confirmación en la que se guardaron los cambios. Usamos esta forma de "git diff" (con dos confirmaciones) porque stash@{0}/ refs/stashes una confirmación de fusión y tenemos que decirle a git con qué padre queremos comparar. Más críptico:

$ git diff stash@{0}^! -- <filename>

también debería funcionar (consulte la página de manual de git rev-parse para obtener una explicación derev^! la sintaxis, en la sección "Especificar rangos").

Del mismo modo, puedes usar git checkout para retirar un solo archivo del alijo:

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

o para guardarlo con otro nombre de archivo:

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

o

$ git show stash@{0}:./<relative filename> > <newfile>

( tenga en cuenta que aquí <nombre de archivo completo> es la ruta completa de un archivo en relación con el directorio superior de un proyecto (piense: en relación con stash@{0})).


Es posible que necesites protegerte stash@{0}de la expansión del shell, es decir, usar "stash@{0}"o 'stash@{0}'.

Jakub Narębski avatar Jul 09 '2009 18:07 Jakub Narębski

Si usa git stash applyen lugar de git stash pop, aplicará el alijo a su árbol de trabajo pero aún lo conservará.

Una vez hecho esto, puede add/ commitel archivo que desee y luego restablecer los cambios restantes.

Tim Henigan avatar Jul 09 '2009 17:07 Tim Henigan
$ git checkout stash@{0} -- <filename>

Notas:

  1. Asegúrese de poner espacio después de "--" y el parámetro de nombre de archivo

  2. Reemplace cero (0) con su número de alijo específico. Para obtener la lista de alijo, utilice:

    git stash list
    

Basado en la respuesta de Jakub Narębski - Versión más corta

Ram avatar Sep 08 '2017 05:09 Ram

Editar: vea la respuesta de cambunctious , que es básicamente lo que prefiero ahora porque solo usa los cambios en el alijo, en lugar de compararlos con su estado actual. Esto hace que la operación sea aditiva, con muchas menos posibilidades de deshacer el trabajo realizado desde que se creó el alijo.

Para hacerlo de forma interactiva, primero harías

git diff stash^! -- path/to/relevant/file/in/stash.ext perhaps/another/file.ext > my.patch

... luego abra el archivo de parche en un editor de texto, modifíquelo según sea necesario y luego haga

git apply < my.patch

La respuesta de cambunctious evita la interactividad al conectar un comando directamente al otro, lo cual está bien si sabes que quieres todos los cambios del alijo. Puede editarlo stash^!para que sea cualquier rango de confirmación que tenga los cambios acumulativos que desee (pero primero verifique el resultado de la diferencia).

Si falla la aplicación del parche/diff, puede cambiar el último comando al git apply --rejectque realiza todos los cambios que puede y deja .rejarchivos donde hay conflictos que no puede resolver. Luego, los .rejarchivos se pueden aplicar usando wiggle, así:

wiggle --replace path/to/relevant/file/in/stash.ext{,.rej}

Esto resolverá el conflicto o le dará marcadores de conflicto que obtendría de una fusión.

Si tu distribución no lo tiene wiggle, puedes simplemente compilarlo:

cd /usr/local/src/
git clone git://git.neil.brown.name/wiggle
cd wiggle/
git checkout v1.3
make install

Solución anterior: existe una forma sencilla de obtener cambios de cualquier rama, incluidos los alijos:

$ git checkout --patch stash@{0} path/to/file

Puede omitir la especificación del archivo si desea aplicar parches en muchas partes. U omita el parche (pero no la ruta) para obtener todos los cambios en un solo archivo. Reemplácelo 0con el número de alijo de git stash list, si tiene más de uno. Tenga en cuenta que esto es como diffy ofrece aplicar todas las diferencias entre las ramas. Para obtener cambios de una sola confirmación/alijo, eche un vistazo a git cherry-pick --no-commit.

Walf avatar Jun 26 '2017 03:06 Walf

Respuesta corta

Para ver el archivo completo:git show stash@{0}:<filename>

Para ver la diferencia:git diff stash@{0}^1 stash@{0} -- <filename>

Luboš Turek avatar Dec 22 '2015 13:12 Luboš Turek