untracked stash name files git git-pull git-stash

stash - git esconder y aplicar



git stash stack overflow (3)

Versión rápida para llevar "TL; DR", para que uno pueda volver más tarde y estudiar más

git stash cuelga un alijo-esta es una forma peculiar de un commit de fusión que no está en ninguna rama-en el commit HEAD actual. Se git stash apply posterior, cuando estás en un commit, probablemente un commit diferente , luego intentas restaurar los cambios que git calcula al mirar el stash-bag colgante y el commit desde el que cuelga.

Cuando hayas terminado con los cambios, debes usar git stash drop para soltar el alijo del commit que fue "escondido". (Y, git stash pop es solo una abreviatura para "aplicar, luego soltar automáticamente". Recomiendo mantener los dos pasos separados, sin embargo, en caso de que no te guste el resultado de "aplicar" y quieras volver a intentarlo más tarde).

La versión larga

git stash es realmente bastante complejo.

Se ha dicho que "git tiene mucho más sentido una vez que entiendes X" , para muchos valores diferentes de "X", que se generaliza a "git tiene mucho más sentido una vez que entiendes git". :-)

En este caso, para comprender realmente el stash , necesita comprender cómo se comprometen, ramas, el área de índice / etapas, el espacio de nombres de referencia de git y fusiona todo el trabajo, porque git stash crea un compromiso de fusión muy peculiar al que hace referencia un nombre fuera de los espacios de nombre habituales -un tipo extraño de combinación que no está "en una rama" en absoluto- y git stash apply utiliza la maquinaria de fusión de git para intentar "volver a aplicar" los cambios guardados cuando se cometió la peculiar fusión hecho, preservando opcionalmente la distinción entre cambios por etapas y cambios por etapas.

Afortunadamente , no es necesario que entiendas todo eso para usar git stash .

Aquí, estás trabajando en alguna rama ( master ) y tienes algunos cambios que aún no están listos, por lo que no quieres comprometerlos en la rama. 1 Mientras tanto, otra persona pone algo bueno, o al menos, espera que sea bueno, en el origin/master en el repositorio remoto, por lo que desea recogerlos.

Digamos que tú y los dos empezaron con commits que terminan en - A - B - C , es decir, C es el compromiso final que tenías en tu repositorio cuando comenzaste a trabajar en Branch master . El nuevo "algo bueno" se compromete, llamaremos D y E

En su caso, está ejecutando git pull y falla con el problema "el directorio de trabajo no está limpio". Entonces, ejecutas git stash . Esto compromete tus cosas para ti, en su especial y extraño estilo stash-y, para que tu directorio de trabajo esté ahora limpio. Ahora puedes git pull .

En términos de dibujo de confirmaciones (un gráfico como el que obtienes con gitk o git log --graph ), ahora tienes algo como esto. El alijo es la pequeña bolsa de iw cuelga de la confirmación que estaba "en", en su rama master , cuando ejecutó git stash . (La razón de los nombres i y w es que estas son las partes "i" ndex / staging-area y "w" ork-tree del stash).

- A - B - C - D - E <-- HEAD=master, origin/master |/ i-w <-- the "stash"

Este dibujo es lo que obtienes si comenzaste a trabajar en master y nunca hiciste ningún commit. El commit más reciente que tuviste fue por lo tanto C Después de hacer el alijo, git pull pudo agregar commits D y E a su branch master local. La bolsa de trabajo escondida sigue colgando C

Si realizó algunos commits propios, los llamaremos Y , para su confirmación, y Z solo para tener dos commits, el resultado de "stash then pull" se ve así:

.-------- origin/master - A - B - C - D - E - M <-- HEAD=master / / Y - Z |/ i-w <-- the "stash"

Esta vez, después de que stash colgara su bolsa de Z , el pull -que es solo fetch luego merge que fusionarse realmente, en lugar de solo un "avance rápido". Entonces hace commit M , la fusión se compromete. La etiqueta de origin/master todavía se refiere a confirmar E , no M Ahora estás en master en commit M , que es una fusión de E y Z Eres "uno por delante" de origin/master .

En cualquier caso, si ahora ejecuta git stash apply , el script stash (es un script de shell que usa una gran cantidad de comandos de "fontanería" de bajo nivel) efectivamente hace esto:

git diff stash^ stash > /tmp/patch git apply /tmp/patch

Esto diffs stash , que nombres w el "árbol de trabajo" parte del escondite-contra el padre correcto 3 . En otras palabras, descubre "lo que ha cambiado" entre la confirmación padre adecuada ( C o Z , según corresponda) y el árbol de trabajo oculto. A continuación, aplica los cambios a la versión actualmente desprotegida, que es E o M , nuevamente según dónde comenzó.

Por cierto, git stash show -p realmente solo ejecuta el mismo comando git diff (sin parte de > /tmp/patch ). Sin -p , ejecuta el diff con --stat . Entonces, si quieres ver en detalle qué se git stash apply , utiliza git stash show -p . (Sin embargo, esto no le mostrará qué puede git stash apply para intentar aplicar desde la parte del índice del alijo, esta es una queja menor que tengo con el script de alijo).

En cualquier caso, una vez que el alijo se aplica limpiamente, puede usar git stash drop para eliminar la referencia al alijo, para que pueda ser recogido. Hasta que lo dejes caer, tiene un nombre ( refs/stash , también conocido como stash@{0} ) por lo que se queda "para siempre" ... excepto por el hecho de que si creas un nuevo alijo, el script de stash "empuja" el el alijo actual en el reflog de ocultación (para que su nombre se convierta en stash@{1} ) y hace que el nuevo escondite use el nombre de refs/stash . La mayoría de las entradas de reflog se mantienen durante 90 días (puede configurar que esto sea diferente) y luego caducan. Los espacios publicitarios no caducan de manera predeterminada, pero si lo configuras de otra manera, un alijo "empujado" puede perderse, así que ten cuidado con depender de "guardar para siempre" si comienzas a configurar git a tu gusto.

Tenga en cuenta que git stash drop "pops" aquí, stash@{2} numerar stash@{2} para stash@{1} y haciendo que stash@{1} convierta en simple stash . Usa la git stash list para ver el stash-stack.

1 No está mal seguir adelante y comprometerlos de todos modos, y luego hacer una posterior git rebase -i para aplastar o corregir más segundo, tercero, cuarto, ..., n-ésimo commit y / o reescribir el compromiso de "punto de control" temporal. Pero eso es independiente de esto.

2 Es un poco más complejo porque puedes usar --index para tratar de mantener los cambios escalonados por etapas, pero de hecho, si miras en el script, verás la secuencia de comandos actual git diff ... | git apply --index git diff ... | git apply --index . ¡Realmente solo aplica una diferencia, en este caso! Finalmente, invoca git merge-recursive directamente, para fusionarse en el árbol de trabajo, permitiendo que los mismos cambios hayan sido introducidos desde otro lugar. Una git apply simple de git apply fallaría si tu parche hace algo que "lo bueno" compromete D y E también lo hace.

3 Esto usa la sintaxis mágica de nombres de padres de git, con un poco de planificación anticipada dentro del script stash . Debido a que el alijo es este funky merge commit, w tiene dos o incluso tres padres, pero el script stash lo configura para que el "primer padre" sea el commit original, C o Z , según corresponda. El stash^2 "segundo padre" stash^2 es el estado del índice en el momento de la confirmación, se muestra como i en el pequeño alijo colgante, y el "tercer padre", si existe, es archivos sin instancia y quizás ignorados , de git stash save -u o git stash save -a .

Tenga en cuenta que asumo, en esta respuesta, que no ha organizado cuidadosamente parte de su árbol de trabajo y que no está usando git stash apply --index para restaurar el índice por etapas. Al no hacer nada de esto, haces que el compromiso sea bastante redundante, por lo que no tenemos que preocuparnos por ello durante el paso de apply . Si está utilizando apply --index o equivalente, y tiene elementos por etapas, puede acceder a muchos más casos de esquina, donde el alijo no se aplicará limpiamente.

Estas mismas advertencias se aplican, con aún más casos de esquina, a los depósitos guardados con -u o -a , que tienen ese tercer compromiso.

Para estos casos extra duros, git stash proporciona una forma de convertir un alijo en una rama completa , pero dejaré todo eso en otra respuesta.

Soy nuevo en git y no tengo muy claro cómo funciona el almacenamiento.

Digamos que estoy trabajando en Branch Master y trato de git pull y recibir el error de que mis cambios locales se sobrescriban y de que se guarden o comprometan. Si no he organizado ninguno de mis cambios y ejecuto git stash , entonces hago un git pull y lo actualizo con éxito, ¿qué sucede cuando git stash apply ?

En general, si alguien más modifica los archivos y ejecuto git pull , ¿qué sucede cuando run git stash apply ? ¿sobrescribe los archivos que se acaban de actualizar, independientemente de si se realizaron o no cuando los escondí? ¿Sobrescribe todos los archivos que acabo de actualizar con git pull , con los archivos que estaban escondidos?


Generalmente los cambios no comprometidos son siempre malos. O bien tus cambios son buenos, luego los comprometes, o son malos que los descartes. Hacer cualquier operación de git mientras tiene cambios no comprometidos tiende a causar problemas y git no podrá ayudarlo, ya que git no sabe nada de lo que no haya cometido.

Habiendo dicho eso, regrese a su pregunta. ;)

Git es generalmente bastante inteligente. Cuando aplica su escondite, intenta combinar sus cambios con los otros cambios. La mayoría de las veces esto solo funciona.

Si los cambios realmente entran en conflicto, porque cambiaste las mismas líneas de una manera diferente, Git te lo dirá, y tendrás que resolver el conflicto tú solo. - Incluso en este caso, Git te ayudará con git mergetool , que lanzará un comando adecuado para mostrarte los conflictos y te permite resolverlos uno por uno.


el comando stash git recuerda de dónde viene el alijo:

git stash list

fuera puesto

stash@{0}: WIP on master.color-rules.0: 35669fb [NEW] another step toward initial cube

Donde puedes ver en que SHA1 fue hecho. Así que, si se equivoca, Git Pull, Git Sshsh se aplica y tiene un conflicto, el alijo no se descarta (solo si se cae o si la aplicación fue exitosa). Así que siempre puedes obtener SHA1 de la lista de git stash y

git checkout 35669fb git stash apply

y está garantizado para trabajar. Recomiendo usar la opción -b y proporcionar un nombre de rama para esa recuperación.

Una vez dicho esto, mi flujo de trabajo favorito es SIEMPRE finalizar la compra en el nuevo nombre "personal" para evitar tales problemas