Git stash: "No se puede aplicar a un árbol de trabajo sucio, por favor realice sus cambios"

133

Estoy tratando de aplicar los cambios con los que me escondí anteriormente git stash popy recibo el mensaje:

Cannot apply to a dirty working tree, please stage your changes

¿Alguna sugerencia sobre cómo lidiar con eso?

avernet
fuente

Respuestas:

196

Cuando tengo que aplicar cambios escondidos a una copia de trabajo sucia, por ejemplo, extraer más de un conjunto de cambios del alijo, utilizo lo siguiente:

$ git stash show -p | git apply -3 && git stash drop

Básicamente

  1. crea un parche
  2. tuberías que al comando aplicar
  3. Si hay conflictos, deberán resolverse mediante una combinación de 3 vías.
  4. si aplicar (o fusionar) tuvo éxito, suelta el elemento de alijo recién aplicado ...

Me pregunto por qué no hay una -fopción (forzada) para la git stash popcual debería comportarse exactamente como la línea anterior.

Mientras tanto, es posible que desee agregar esta línea como un alias git:

$ git config --global --replace-all alias.unstash \
   '!git stash show -p | git apply -3 && git stash drop'
$ git unstash

Gracias a @SamHasler por señalar el -3parámetro que permite resolver conflictos directamente a través de la fusión de 3 vías.

revs muhqu
fuente
Es git stash show -p | git applydiferente de git stash apply?
Factor Mystic
1
Jo Factor, git stash applyno aplicará los cambios escondidos si tiene una copia de trabajo sucia. Entonces puedes ver git stash show -p | git applycomo se aplica algún tipo de escondite forzado.
muhqu
1
no ayuda Pero ayuda: git reset HEAD y desestima los cambios después de eso.
Roger Alien
44
Me sale "error: parche falló ... el parche no se aplica" para uno de los archivos. Desearía que hubiera un conflicto de fusión.
Aleksandr Dubinsky
1
Esta solución no funcionó para mí, falló con error: <file> does not match indexcada archivo modificado. Sin embargo, otra solución funcionó.
silvenon
57

Lo hago de esta manera:

git add -A
git stash apply

y luego (opcionalmente):

git reset
Sergii Mostovyi
fuente
2
+1! Esto es más simple que las otras soluciones que implican generar parches o enmendar confirmaciones, y mantiene sus cambios locales aislados de forma segura de los cambios de alijo aplicados hasta que esté seguro de que los cambios se fusionaron correctamente.
peterflynn
Recibo el error "... ya existe, no hay pago ... No se pudieron restaurar los archivos no rastreados del alijo"
Aleksandr Dubinsky
2
Solía git add -u, que es como, -Aexcepto que no agrega archivos sin seguimiento.
Brad Cupit el
9

Puede hacerlo sin tener que guardar sus cambios actuales exportando el alijo que desea como un archivo de parche y aplicándolo manualmente.

Por ejemplo, supongamos que desea aplicar stash @ {0} a un árbol sucio:

  1. Exportar alijo @ {0} como parche:

    git stash show -p stash @ {0}> Stash0.patch

  2. Aplicar manualmente los cambios:

    git apply Stash0.patch

Si el segundo paso falla, tendrá que editar el archivo Stash0.patch para corregir cualquier error y luego intentar git apply nuevamente.

Ishan
fuente
Esto es práctico y viable para el caso de que realicé una refactorización en un directorio (lo eliminé y creé un enlace simbólico con su nombre). Git no podía decir cuáles fueron mis cambios en la copia de trabajo.
yclian
1
Esto funcionó muy bien. No pude aplicar un alijo a pesar de que estoy bastante seguro de que mi árbol de trabajo está limpio.
Shiki
Sí, tuve que eliminar líneas sobre un archivo binario.
Dorian
8

Limpie su directorio de trabajo con git reset, confirme los cambios o, si desea guardar los cambios actuales, intente:

$ git stash save "descripción de los cambios actuales"
$ git stash pop stash @ {1}

Esto esconderá los cambios actuales y luego sacará el segundo alijo de la pila de alijo.

William Pursell
fuente
55
¡Pero este tipo quiere que se apliquen los dos escondites!
Elazar Leibovich
@Elazar Estás leyendo la pregunta. El OP simplemente quiere aplicar un alijo anterior. Si tiene razón en que los cambios actuales deben mantenerse, la solución puede repetirse: pop, commit, repeat.
William Pursell el
Creo que los quiere a ambos sin compromiso. Pero, de nuevo, puede cometerlos dos veces y aplastarlos en un solo compromiso.
Elazar Leibovich
Recibo el error "... ya existe, no se puede pagar ... No se pudieron restaurar los archivos no rastreados del alijo"
Aleksandr Dubinsky
6

La solución de Mathias es definitivamente la más cercana a un git stash pop --force (y realmente, vamos desarrolladores de Git, ¡obtengamos esta opción ya!)

Sin embargo, si desea hacer lo mismo utilizando solo comandos git, puede:

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git commit -a --amend
  4. git reset HEAD ~

En otras palabras, haga una confirmación (que nunca empujaremos) de sus cambios actuales. Ahora que su espacio de trabajo está limpio, saque su alijo. Ahora, confirme los cambios de alijo como una enmienda a su confirmación anterior. Una vez hecho esto, ahora tiene ambos conjuntos de cambios combinados en una sola confirmación ("Fixme"); simplemente restablezca (--soft NO --duro para que no se pierda nada) su pago a "uno antes de esa confirmación", y ahora tiene ambos conjuntos de cambios, completamente no comprometidos.

** EDITAR * *

Me acabo de dar cuenta de que en realidad es aún más fácil; puedes omitir por completo el paso 3, así que ...

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git reset HEAD ~

(Confirme los cambios actuales, elimine los cambios escondidos, restablezca ese primer compromiso para obtener ambos conjuntos de cambios combinados en un estado no confirmado).

maquina
fuente
4

Ninguna de estas respuestas realmente funciona si te encuentras en esta situación como lo hice hoy. Independientemente de cuántos git reset --hardhice, no me llevó a ninguna parte. Mi respuesta (no oficial de ninguna manera fue):

  1. Averigua el uso de hash del alijo git reflog --all
  2. Combina ese hash con la rama que te interesa
Dan Rosenstark
fuente
1
Muchas gracias Yar. Estaba frustrado por cómo Git se comportó extrañamente en mi repositorio local en este momento, el mismo problema que describiste.
yclian
4

También encontré que la solución de Mathias Leppich funcionaba muy bien, así que agregué un alias a mi .gitconfig global

[alias]
        apply-stash-to-dirty-working-tree = !git stash show -p | git apply && git stash drop

Ahora solo puedo escribir

git apply-stash-to-dirty-working-tree

que funciona muy bien para mi

(Su millaje puede variar en este largo nombre de alias. Pero me gusta una dosis de verbosidad cuando se trata de completar bash).

estera
fuente
3

Puede aplicar un alijo a un árbol "sucio" haciendo una git addetapa para cualquier cambio que haya realizado, limpiando así el árbol. Entonces puedes git stash popy aplicar los cambios escondidos, no hay problema.

Chris Vandevelde
fuente
2

Tiene archivos que han sido modificados pero no confirmados. Ya sea:

git reset --hard HEAD (to bring everything back to HEAD)

o, si desea guardar sus cambios:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop
brool
fuente
1
@ MikeCooper: creo que solo quiso decir lo que quieras agregar antes de comprometerte.
sscirrus
0

Tuve el mismo problema pero git tenía cero archivos modificados. Resulta que tenía un archivo index.lock que estaba por ahí. Eliminarlo resolvió el problema.

en caja
fuente
0

No pude conseguir que la mayoría de estos funcionen; Por alguna razón, siempre piensa que tengo cambios locales en un archivo. No puedo aplicar un alijo, los parches no se aplicarán checkouty reset --hardfallarán. Lo que finalmente funcionó fue guardar el alijo como una rama con git stash branch tempbranchname, y luego hacer una fusión de rama normal: git checkout mastery git merge tempbranchname. De http://git-scm.com/book/en/Git-Tools-Stashing :

Si desea una forma más fácil de probar los cambios guardados nuevamente, puede ejecutar git stash branch, que crea una nueva rama para usted, verifica el compromiso en el que estaba cuando escondió su trabajo, vuelve a aplicar su trabajo allí y luego deja caer el esconderse si se aplica con éxito

rwilson04
fuente