Come recuperare le modifiche non impegnate nascoste


696

Ho avuto alcune modifiche non confermate nel mio ramo di sviluppo e le ho messe da parte usando git stash, ma c'erano alcune modifiche che erano molto importanti tra quelle nascoste. C'è un modo per recuperare quei cambiamenti?

Inoltre, da allora ho apportato alcune modifiche ai file di codice nascosti.

C'è qualche possibilità che io possa recuperare le modifiche nascoste in un nuovo ramo, se possibile?


7
hai provato a usare 'stash pop'?
robert,

No. In realtà sono nuovo a git. Dato che non sono pienamente consapevole di tutti i comandi, non ho provato nient'altro! Non voglio perdere quei cambiamenti.
Aswathy P Krishnan,

33
Se non vuoi perdere le modifiche nascoste, prova a usare 'git stash applicare'. Questo applicherà le modifiche nascoste al ramo corrente, mantenendo comunque la scorta. Se tutto va bene, dopo aver applicato lo stash, puoi rilasciare lo stash, usando 'git stash drop'
robert

2
@robert Grazie per la risposta semplice rispetto alla risposta accettata orribilmente complicata (per un principiante).
Saheel Godhane

Risposte:


1189

La risposta semplice alla domanda semplice è git stash apply

Dai un'occhiata al ramo in cui desideri apportare le modifiche e quindi git stash apply. Quindi utilizzare git diffper vedere il risultato.

Dopo aver fatto tutto con le modifiche apportate, la applyguarda bene e sei sicuro che non è necessario la scorta qualsiasi altro ancora, quindi utilizzare git stash dropper sbarazzarsi di esso.

Suggerisco sempre di utilizzare git stash applypiuttosto che git stash pop. La differenza è che applylascia lo stash in giro per riprovare facilmente apply, o per guardare, ecc. Se popè in grado di estrarre lo stash, lo farà immediatamente anche drop, e se improvvisamente ti rendi conto che volevi estrarlo da qualche parte altro (in un ramo diverso), o con --index, o alcuni di questi, non è così facile. Se sì apply, puoi scegliere quando farlo drop.

È tutto piuttosto secondario in un modo o nell'altro, e per un principiante, dovrebbe essere più o meno lo stesso. (E puoi saltare tutto il resto!)


E se stai facendo cose più avanzate o più complicate?

Ci sono almeno tre o quattro diversi "modi di usare git stash", per così dire. Quanto sopra è per "way 1", il "modo semplice":

  1. Hai iniziato con un ramo pulito, stavi lavorando su alcuni cambiamenti e poi hai capito che li stavi facendo nel ramo sbagliato. Vuoi solo prendere le modifiche che hai ora e "spostarle" in un altro ramo.

    Questo è il caso semplice, descritto sopra. Corri git stash save(o semplicemente git stash, stessa cosa). Controlla l'altro ramo e utilizzare git stash apply. Questo fa sì che git si fonda con le tue modifiche precedenti, usando il meccanismo di unione piuttosto potente di git. Ispeziona attentamente i risultati (con git diff) per vedere se ti piacciono e, se lo fai, usa git stash dropper eliminare la scorta. Hai finito!

  2. Hai iniziato alcune modifiche e le hai nascoste. Quindi sei passato a un altro ramo e hai iniziato altre modifiche, dimenticando che avevi quelle nascoste.

    Ora vuoi mantenere o persino spostare queste modifiche e applicare anche la tua scorta.

    È possibile infatti di git stash savenuovo, in quanto git stasheffettua una "pila" di modifiche. Se lo fai hai due blocchi, uno appena chiamato, stashma puoi anche scrivere, stash@{0}e uno scritto stash@{1}. Usa git stash list(in qualsiasi momento) per vederli tutti. Il più recente è sempre il numero più basso. Quando lo fai git stash drop, lascia cadere il più recente e quello che era stash@{1}in cima alla pila. Se ne avessi ancora di più, quello che era stash@{2}diventa stash@{1}, e così via.

    Puoi applye poi anche dropuna scorta specifica: git stash apply stash@{2}e così via. Rilasciare uno stash specifico, rinumera solo quelli di numero più alto. Ancora una volta, anche quello senza un numero lo è stash@{0}.

    Se accumuli un sacco di oggetti, può diventare piuttosto confuso (era lo stash che volevo stash@{7}o era stash@{4}? Aspetta, ne ho appena spinto un altro, ora sono 8 e 5?). Personalmente preferisco trasferire queste modifiche in un nuovo ramo, perché i rami hanno nomi e cleanup-attempt-in-Decembersignificano molto di più per me stash@{12}. (Il git stashcomando accetta un messaggio di salvataggio opzionale, e quelli possono aiutare, ma in qualche modo, tutte le mie scorte finiscono col nome WIP on branch.)

  3. (Extra-avanzato) Prima di eseguire hai usato git stash save -p, o usato con attenzione git adde / o git rm-ed bit specifici del tuo codice git stash save. Avevi una versione nell'area dell'indice / di gestione temporanea nascosta e un'altra (diversa) nella struttura di lavoro. Vuoi preservare tutto questo. Quindi ora usi git stash apply --index, e questo a volte fallisce con:

    Conflicts in index.  Try without --index.
    
  4. Stai usando git stash save --keep-indexper testare "cosa sarà commesso". Questo va oltre lo scopo di questa risposta; vedi invece questa altra risposta StackOverflow .

Per casi complicati, ti consiglio di iniziare prima in una directory di lavoro "pulita", eseguendo tutte le modifiche che hai ora (su un nuovo ramo, se lo desideri). In questo modo il "da qualche parte" che li stai applicando, non ha nient'altro in esso e proverai solo le modifiche nascoste:

git status               # see if there's anything you need to commit
                         # uh oh, there is - let's put it on a new temp branch
git checkout -b temp     # create new temp branch to save stuff
git add ...              # add (and/or remove) stuff as needed
git commit               # save first set of changes

Ora sei su un punto di partenza "pulito". O forse va più così:

git status               # see if there's anything you need to commit
                         # status says "nothing to commit"
git checkout -b temp     # optional: create new branch for "apply"
git stash apply          # apply stashed changes; see below about --index

La cosa principale da ricordare è che lo "stash" è un commit, è solo un commit leggermente "divertente / strano" che non è "su un ramo". L' applyoperazione guarda cosa è cambiato il commit e cerca di ripeterlo ovunque tu sia ora. Lo stash sarà ancora lì ( applytienilo in giro), quindi puoi guardarlo di più, o decidere che questo era il posto sbagliato applye riprovare diversamente, o qualunque altra cosa.


Ogni volta che hai una scorta, puoi usare git stash show -pper vedere una versione semplificata di ciò che è nella scorta. (Questa versione semplificata esamina solo le modifiche dell '"albero di lavoro finale", non le modifiche all'indice salvate che vengono --indexripristinate separatamente.) Il comando git stash apply, senza --index, tenta ora di apportare le stesse modifiche nella directory di lavoro ora.

Questo è vero anche se hai già alcune modifiche. Il applycomando è felice di applicare uno stash a una directory di lavoro modificata (o almeno, per provare ad applicarlo). Ad esempio, puoi farlo:

git stash apply stash      # apply top of stash stack
git stash apply stash@{1}  # and mix in next stash stack entry too

Puoi scegliere l'ordine "applica" qui, selezionando gli stash particolari da applicare in una sequenza particolare. Nota, tuttavia, che ogni volta che stai praticamente facendo una "unione git", e come la documentazione di unione avverte:

L'esecuzione di git merge con modifiche non banali e non banali è scoraggiata: per quanto possibile, potrebbe lasciarti in uno stato di cui è difficile uscire in caso di conflitto.

Se inizi con una directory pulita e stai solo facendo diverse git applyoperazioni, è facile tornare indietro: usa git reset --hardper tornare allo stato pulito e cambiare le tue applyoperazioni. (Ecco perché consiglio di iniziare prima in una directory di lavoro pulita, per questi casi complicati.)


E il caso peggiore possibile?

Diciamo che stai facendo un sacco di roba Git avanzata e hai fatto una scorta, e vuoi farlo git stash apply --index, ma non è più possibile applicare la scorta salvata --index, perché il ramo è divergente troppo dal momento in cui l'hai salvata.

Questo è ciò che git stash branchserve.

Se tu:

  1. controllare l' esatto impegnarsi eravate quando avete fatto l'originale stash, poi
  2. creare un nuovo ramo e infine
  3. git stash apply --index

il tentativo di ricreare le modifiche sicuramente sarà funzionerà. Questo è ciò che fa. (E quindi rilascia lo stash da quando è stato applicato con successo.)git stash branch newbranch


Alcune parole finali su --index(che diamine è?)

Quello che --indexfa è semplice da spiegare, ma un po 'complicato internamente:

  • Quando hai delle modifiche, devi git add(o "metterle in scena") prima di commiting.
  • Pertanto, quando hai eseguito git stash, potresti aver modificato entrambi i file fooe zorg, ma messo in scena solo uno di questi.
  • Quindi, quando chiedi di recuperare la scorta, potrebbe essere bello se sono git addle addcose edite e non git add quelle non aggiunte. Cioè, se addEd foo, ma non zorgindietro prima di te la stash, potrebbe essere bello avere quella stessa configurazione. Ciò che è stato messo in scena, dovrebbe essere nuovamente messo in scena; ciò che è stato modificato ma non messo in scena, dovrebbe essere nuovamente modificato ma non messo in scena.

La --indexbandiera per applycercare di sistemare le cose in questo modo. Se l'albero di lavoro è pulito, di solito funziona. Se il tuo albero di lavoro ha già roba modificata add, puoi vedere come potrebbero esserci dei problemi qui. Se si lascia fuori --index, ilapply operazione non tenta di preservare l'intera configurazione graduale / non scenica. Invece, invoca semplicemente il meccanismo di unione di git, usando il commit dell'albero di lavoro nella "borsa stash" . Se non ti interessa conservare la messa in scena / non messa in scena, tralasciare --indexrende molto più facile git stash applyfare le sue cose.


2
Non capisco il tuo commento. Intendi dire: hai corso git stash pop? O vuoi dire: hai modificato alcuni file, ma non hai ancora eseguito di git stashnuovo? O vuoi dire qualcos'altro interamente?
Torek,

1
Sì. Nota, nella mia (lunga) modifica, ti consiglio di impegnare quello che hai ora prima di fare applyuna scorta. Non devi fare questo, ma rende le cose molto più semplici per voi a guardare. È possibile utilizzare rebase -iper comprimere più commit o selezionare in modo particolare modifiche o qualsiasi altra cosa in un secondo momento.
Torek,

1
Sì: git stash apply --index(ricorda i due trattini). Se si lascia fuori --index, nessun grosso problema; l'unico punto di --indexè mantenere la configurazione graduale / non scenica. (Probabilmente non hai avuto nessuna configurazione speciale in primo luogo.) Quindi git statusecc. E aggiungi / commetti come desiderato ecc. Quando (e solo quando) hai finito con lo stash, usa git stash dropper scartarlo.
Torek,

1
Finché mantenete (non dropo pop) lo stash, avrete sempre il codice originale stash al sicuro su un commit, perché uno stash è un commit! Se vuoi recuperarlo esattamente, ma su un ramo, usa git stash branch(vedi quella sezione sopra, o il libro Pro Git nella risposta di Shunya ). È quindi possibile git checkoutquel ramo o git cherry-pickil commit fuori da quel ramo, ecc.
torek

2
@ChuckWolber: le convenzioni di denominazione di Git lasciano molto a desiderare (quanti significati diversi possiamo assegnare alle parole "remoto", "tracciamento" e "ramo" ?!). Vale la pena notare che è possibile applicare uno stash a qualcosa di non correlato allo stash originale.
Torek,

57
git stash pop

rimetterà tutto a posto

come suggerito nei commenti, è possibile utilizzare git stash branch newbranchper applicare lo stash a un nuovo ramo, che è lo stesso dell'esecuzione:

git checkout -b newbranch
git stash pop

Grazie per l'aiuto. Posso ottenere queste modifiche in una nuova filiale? In questo momento sono sul ramo di sviluppo
Aswathy P Krishnan,

3
git stash branch newbranch, creerà un nuovo ramo con le modifiche nascoste.
robert,

3
@robert: lo git stash branch newbranchfarà davvero; ma tieni presente che crea il nuovo ramo con il suo genitore impostato sul commit che era HEADal momento in cui è stashstato fatto. In altre parole, è per quando torni dopo una lunga sessione di hacking o altro, fissa il disordine e decidi "Avrei dovuto metterlo su un ramo, piuttosto che nasconderlo" :-)
torek

Ho modificato la mia domanda. Vorrei ottenere tali modifiche in una nuova filiale, se possibile.
Aswathy P Krishnan,

1
A volte vuoi solo la risposta TLDR :)
sachinruk,

24

Per semplificare, hai due opzioni per riapplicare la tua scorta:

  1. git stash pop - Ripristina lo stato salvato, ma elimina lo stash dall'archivio temporaneo.
  2. git stash apply - Ripristina lo stato salvato e lascia l'elenco degli stash per un possibile riutilizzo successivo.

In questo articolo puoi leggere più dettagliatamente gli stash git .


19

Per controllare il contenuto dello stash: -

git stash list

applica un particolare numero di stash dall'elenco di stash: -

git stash applica stash @ {2}

o per applicare solo la prima scorta: -

git stash pop

Nota: git stash pop rimuoverà lo stash dall'elenco degli stash mentre git stash si applica. Quindi usali di conseguenza.


2

Su Mac ha funzionato per me:

git stash list (vedi tutti i tuoi stash)

git stash list

git stash si applica (solo il numero desiderato dall'elenco di stash)

come questo:

git stash apply 1

0

puoi riporre le modifiche senza commit usando "git stash", quindi fare il checkout in un nuovo ramo usando "git checkout -b", quindi applicare i commit nascosti "git stash applicare"

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.