Git stash: "Impossibile applicare a un albero di lavoro sporco, si prega di mettere in scena le modifiche"


133

Sto cercando di applicare le modifiche che ho nascosto in precedenza con git stash pope ottenere il messaggio:

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

Qualche suggerimento su come gestirlo?

Risposte:


196

Quando devo applicare le modifiche nascoste a una copia di lavoro sporca, ad esempio estrarre più di un changeset dalla scorta, utilizzo quanto segue:

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

Fondamentalmente

  1. crea una patch
  2. reindirizza al comando apply
  3. in caso di conflitti dovranno essere risolti tramite l'unione a 3 vie
  4. se apply (o merge) ha avuto successo, lascia cadere l'elemento stash appena applicato ...

Mi chiedo perché non esiste -fun'opzione (force) per la git stash popquale dovrebbe comportarsi esattamente come il one-liner sopra.

Nel frattempo potresti voler aggiungere questo one-liner come alias git:

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

Grazie a @SamHasler per aver sottolineato il -3parametro che consente di risolvere i conflitti direttamente tramite l'unione a 3 vie.


È git stash show -p | git applydiverso da git stash apply?
Factor Mystic,

1
Jo Factor, git stash applynon applicherà le modifiche nascoste se hai una copia di lavoro sporca. Quindi puoi vedere git stash show -p | git applycome si applica una sorta di scorta forzata.
Muhqu,

1
non aiuta Ma aiuta: git resetta HEAD e annulla le modifiche dopo.
Roger Alien,

4
Ottengo "errore: patch non riuscita ... patch non applicabile" per uno dei file. Vorrei che fosse un conflitto di unione.
Aleksandr Dubinsky,

1
Questa soluzione non ha funzionato per me, non è riuscita con error: <file> does not match indexogni file modificato. Tuttavia, un'altra soluzione ha funzionato.
Silvenon,

57

Lo faccio in questo modo:

git add -A
git stash apply

e poi (facoltativamente):

git reset

2
+1! Questo è più semplice delle altre soluzioni che implicano la generazione di patch o modifiche di commit e mantiene le modifiche locali in modo sicuro isolate dalle modifiche degli stash applicati fino a quando non si è sicuri che le modifiche siano state unite correttamente.
Peterflynn,

Ottengo l'errore "... esiste già, nessun checkout ... Impossibile ripristinare i file non tracciati dallo stash"
Aleksandr Dubinsky

2
Ho usato git add -u, che è come -Ase non aggiungesse file non tracciati.
Brad Cupit,

9

Puoi farlo senza dover riporre le modifiche attuali esportando lo stash desiderato come file patch e applicandolo manualmente.

Ad esempio, supponiamo di voler applicare stash @ {0} a un albero sporco:

  1. Esporta stash @ {0} come patch:

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

  2. Applicare manualmente le modifiche:

    git applica Stash0.patch

Se il secondo passaggio fallisce, dovrai modificare il file Stash0.patch per correggere eventuali errori e quindi provare di nuovo ad applicare git.


Questo è pratico e realizzabile nel caso in cui, ho effettuato il refactoring su una directory (rimossa e creata un collegamento simbolico con il suo nome). Git non ha saputo dire quali fossero le mie modifiche alla copia di lavoro.
yclian,

1
Questo ha funzionato alla grande. Non sono stato in grado di applicare una scorta anche se sono abbastanza sicuro che il mio albero di lavoro sia pulito.
Shiki,

Sì, ho dovuto rimuovere le righe su un file binario.
Dorian,

8

Pulisci la tua directory di lavoro con git reset, esegui il commit delle modifiche o, se vuoi riporre le modifiche correnti, prova:

$ git stash save "descrizione delle modifiche correnti"
$ git stash pop stash @ {1}

Questo riporterà le modifiche correnti, quindi aprirà la seconda scorta dallo stack di riserva.


5
Ma questo ragazzo vuole applicare le due scorte!
Elazar Leibovich,

@Elazar Stai leggendo la domanda. L'OP vuole semplicemente applicare una scorta precedente. Se hai ragione a mantenere le modifiche attuali, la soluzione può essere ripetuta: pop, commit, ripeti.
William Pursell,

Penso che li voglia entrambi senza impegno. Ma poi, può impegnarli due volte e schiacciarli in un unico commit.
Elazar Leibovich,

Ottengo l'errore "... esiste già, nessun pagamento ... Impossibile ripristinare i file non tracciati dalla scorta"
Aleksandr Dubinsky

6

La soluzione di Mathias è sicuramente la più vicina a un git stash pop --force (e davvero, dai Git devs, prendiamo già questa opzione!)

Tuttavia, se vuoi fare la stessa cosa usando solo i comandi git, puoi:

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

In altre parole, effettua un commit (che non spingeremo mai) delle tue attuali modifiche. Ora che il tuo spazio di lavoro è pulito, fai scoppiare la scorta. Ora, esegui il commit delle modifiche dello stash come emendamento al tuo precedente commit. Fatto ciò, ora hai entrambi i set di modifiche combinati in un unico commit ("Fixme"); ripristina semplicemente (--soft NOT --hard, quindi nulla è effettivamente perso) il tuo checkout su "uno prima di quel commit", e ora hai entrambi i set di modifiche, completamente senza impegno.

** MODIFICA * *

Ho appena realizzato che in realtà è ancora più facile; puoi saltare completamente il passaggio 3, quindi ...

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

(Esegui il commit delle modifiche correnti, elimina le modifiche nascoste, ripristina il primo commit per ottenere entrambi i set di modifiche combinati in uno stato non confermato.)


4

Nessuna di queste risposte funziona davvero se ti trovi in ​​questa situazione come ho fatto oggi. Indipendentemente da quante ne git reset --hardho fatte, non mi ha portato da nessuna parte. La mia risposta (non ufficiale in alcun modo era):

  1. Scopri l'uso dell'hash dello stash git reflog --all
  2. Unisci l'hash con il ramo che ti interessa

1
Grazie mille Yar. Ero frustrato dal modo in cui Git si era comportato in modo strano sul mio repository locale proprio ora, lo stesso problema che hai descritto.
yclian,

4

Ho anche trovato la soluzione di Mathias Leppich funzionante, quindi ho aggiunto un alias al mio globale .gitconfig

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

Ora posso solo digitare

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

che funziona benissimo per me.

(Il tuo chilometraggio può variare con questo nome alias lungo. Ma mi piace una dose di verbosità quando si tratta di completamento bash.)


3

Puoi applicare uno stash a un albero "sporco" facendo uno git addstage per eventuali modifiche apportate, quindi ripulendo l'albero. Quindi è possibile git stash pope applicare le modifiche nascoste, nessun problema.


2

Hai file che sono stati modificati ma non impegnati. O:

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

oppure, se si desidera salvare le modifiche:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop

1
@MikeCooper - Penso che intendesse solo aggiungere qualsiasi cosa tu voglia aggiungere prima di impegnarti.
sscirrus,

0

Ho avuto lo stesso problema ma git aveva zero file modificati. Ho scoperto che avevo un file index.lock in giro. L'eliminazione ha risolto il problema.


0

Non sono riuscito a far funzionare la maggior parte di questi; per qualche motivo pensa sempre che io abbia delle modifiche locali a un file. Non riesco ad applicare uno stash, le patch non si applicano checkoute reset --hardfalliscono. Ciò che alla fine ha funzionato è stato salvare la scorta come un ramo git stash branch tempbranchnamee quindi fare una normale fusione di rami: git checkout mastere git merge tempbranchname. Da http://git-scm.com/book/en/Git-Tools-Stashing :

Se vuoi un modo più semplice per testare di nuovo le modifiche nascoste, puoi eseguire git stash branch, che crea un nuovo ramo per te, controlla il commit che avevi su quando hai nascosto il tuo lavoro, riapplica il tuo lavoro lì, quindi rilascia il stash se si applica correttamente

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.