Stash: legg uferdig arbeid til side
Den interaktive leksjonen trenger JavaScript. Teksten under er hele leksjonen.
Etter leksjonen kan du
- legge uferdige endringer til side med
git stash push -mog ta dem tilbake medgit stash popanvende - forklare forskjellen på
git stash popoggit stash apply, og når du trenger-uforstå - velge mellom en stash og en WIP-commit på en egen branch ut fra hvor lenge avbruddet varer og om arbeidet må videre til en annen maskin vurdere
Forstå: Når du blir avbrutt
Du er midt i en endring på branchen feature. README er halvveis skrevet, og du har en ny fil med ideer. Så kommer beskjeden: noe på main må fikses nå, men arbeidet ditt er ikke klart for en commit.
Prøver du å bytte til main nå, kan Git nekte. README ser annerledes ut på main, og byttet ville skrevet over den uferdige teksten din. Git kaster aldri ulagret arbeid uten at du ber om det.
git stash push tar endringene i sporede filer og legger dem på en hylle ved siden av historikken. De sporede filene blir like siste commit igjen. Med -m gir du stashen en melding, så du vet hva den inneholder senere.
Se på grafen: hylla er en egen commit med merkelappen stash@{0}. Den har to foreldre. Den ene er commiten du sto på. Den andre er en liten commit som tar vare på staging-området. Ingen branch flyttet seg.
Se på arbeidsmappen: ideas.txt ble liggende. Usporede filer blir ikke med i en stash, med mindre du legger til -u.
Når du er tilbake, legger git stash pop endringene inn igjen og fjerner oppføringen hvis det gikk uten konflikt. Merkelappen stash@{0} forsvinner, og stash-commitene blir spøkelser. git stash apply legger også endringene inn, men beholder oppføringen til du kjører git stash drop.
En stash er lokal og blir ikke med i en vanlig push. Den har et nummer, ikke et navn, og numrene forskyves: stasher du igjen, blir stash@{0} til stash@{1}. Til en lang pause committer du heller arbeidet som WIP på en egen branch. Den har et navn og kan pushes.
Se demo: Avbrudd, rettelse og tilbake igjen
Vi står på feature med uferdig arbeid. I kortformatet betyr M endret og to spørsmålstegn usporet. README er endret, og ideas.txt er ny.
$ git status --short
Nå prøver vi å bytte til main. Git nekter og sier hvorfor: den lokale endringen i README ville blitt overskrevet. Git foreslår selv å committe eller stashe.
$ git switch main
Vi legger arbeidet til side med en melding. Se på grafen: en stash-commit med merkelappen stash@{0} dukker opp ved siden av feature. README er tilbake til siste commit.
$ git stash push -m "WIP search filters"
git stash list viser hylla. Den nyeste oppføringen ligger øverst som stash null, med branchen og meldingen din. Det er den samme stash@{0} som i grafen.
$ git stash list
Nå prøver vi byttet igjen. Stashen blir hengende ved feature, der den ble laget. Men hvor havner ideas.txt?
$ git switch main
Her gjør vi den hastende rettelsen og committer den. Grafen får en ny commit på main.
$ echo "Contact: team@example.com" >> README.md && git commit -am "Add contact line"
Rettelsen er ute av verden. Vi går tilbake til feature.
$ git switch feature
Til slutt tar vi arbeidet tilbake. pop legger endringene inn igjen og fjerner oppføringen fordi det gikk uten konflikt. Merkelappen stash@{0} forsvinner fra grafen, og README er endret igjen, akkurat der du slapp.
$ git stash pop
Oppgaver
- Legg de uferdige endringene til side med en beskrivende melding.
- Bytt til
main. - Ta det uferdige arbeidet tilbake og fjern oppføringen fra stash-listen.
Øv: Overfør: alt til side, og en bedre plan
Nytt repository på main. README er endret, og todo.txt er en ny fil. Ingen demo denne gangen.
Oppgaver
- Legg bort alt det uferdige arbeidet, også den nye filen
todo.txt, slik at arbeidsmappen blir helt ren. - Ta arbeidet tilbake, men behold oppføringen i stash-listen i tilfelle noe går galt.
- Jobben ble større enn ventet. Lagre arbeidet som en commit på en ny branch
wip-todoi stedet, og fjern den overflødige stash-oppføringen.
Sjekk deg selv: Hent det fram igjen
Du lager den nye filen new.txt, kjører git add new.txt og så git stash push. Blir new.txt lagt bort?
- Nei, nye filer krever
-u - Ja, den er sporet fordi den ligger i staging-området
- Bare den stagede kopien; filen blir liggende i arbeidsmappen
Hva er forskjellen på git stash pop og git stash apply?
popfjerner oppføringen når endringene er lagt inn uten konflikt;applylar den ståpoptar bare tilbake den nyeste stashen;applytar tilbake alleapplyoverskriver arbeidsmappen;popslår endringene sammen
Det er fredag. Featuren er halvferdig, og på mandag skal du jobbe videre med den fra en annen maskin. Hva gjør du?
git stash push -u, og sågit push- En WIP-commit på en egen branch, og så push branchen
- En WIP-commit rett på
main, og sågit push
Repetisjon fra «Angre i filene»: I stedet for å stashe kjører du git restore README.md på en uferdig endring du aldri har staget, committet eller stashet. Kan du få den tilbake etterpå?
- Ja, med
git stash pop - Ja, fra reflogen
- Nei, endringen er borte for godt
Vanlige misforståelser
- «Stash tar med alt.» Uten
-ublir usporede filer liggende i arbeidsmappen. - «Stash er en backup.» Stash finnes bare i ditt lokale repository, blir ikke med i en vanlig
git push, og en droppet stash er vanskelig å finne igjen. - «
git stash popoggit stash applyer det samme.»popfjerner oppføringen når endringene ble lagt inn uten konflikt;applylar den stå.
Les mer
Hva en stash egentlig er
En stash er ingen skjult mappe. git stash push lager vanlige commit-objekter og lar den spesielle referansen refs/stash peke på den nyeste. Denne stash-commiten har to foreldre: commiten du sto på, og en ekstra commit som tar vare på staging-området. Med -u eller -a kommer en tredje forelder med de usporede filene. Derfor tegner den levende grafen stashen som stash@{0}, hengende ut fra commiten du sto på:
$ git stash push -m "WIP search filters"
Saved working directory and index state On feature: WIP search filters
$ git log --oneline --graph stash@{0}
* aa05d36 On feature: WIP search filters
|\
| * 167af41 index on feature: 88dbfe3 Start search feature
|/
* 88dbfe3 Start search feature
* 227577f Initial snapshot
Stash-lista er refloggen til refs/stash. stash@{0} er den nyeste oppføringen, stash@{1} den før, og numrene forskyves hver gang du legger til eller fjerner en oppføring. Les derfor git stash list før du bruker et nummer, og gi hver stash en melding med -m. «WIP on feature» sier deg ingenting om en uke.
Se før du tar den tilbake
| Kommando | Viser |
|---|---|
git stash list |
alle oppføringer, nyeste først |
git stash show |
hvilke filer den nyeste stashen endrer |
git stash show -p stash@{1} |
hele diffen til én bestemt oppføring |
git stash show --include-untracked |
også de usporede filene som ble lagret med -u |
$ git stash show -p
diff --git a/README.md b/README.md
index 5793643..ea67787 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
Welcome
Feature: search
+Search supports filters
Hva blir med
- Vanlig
git stash pushtar endringer i sporede filer, både stagede og ustagede. Usporede filer blir liggende. -u(--include-untracked) tar også nye, usporede filer.-a(--all) tar i tillegg ignorerte filer, som byggeresultater. Det er sjelden det du vil.--keep-indexstasher alt, men lar de stagede endringene ligge, så du kan teste akkurat det du skal committe. Den stagede delen lagres likevel i stashen og kommer tilbake når du kjører pop. Endrer du de samme linjene før det, kan pop gi konflikt.git stash push -- notes.txtstasher bare stiene du nevner.
pop, apply, drop og konflikter
git stash apply merger de lagrede endringene inn i arbeidsmappen og beholder oppføringen. git stash pop gjør det samme og fjerner så oppføringen, men bare hvis alt gikk inn uten konflikt. Begge legger endringer i eksisterende filer tilbake som ustagede, mens nye filer du hadde staget, kommer tilbake staget. Legg til --index for å gjenskape fordelingen mellom staget og ustaget nøyaktig.
Kolliderer stashen med endringer gjort siden, får du konfliktmarkører, status viser UU, og Git beholder oppføringen:
$ git stash pop
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
...
The stash entry is kept in case you need it again.
Løs filen som etter en merge, kjør git add på den, og fjern oppføringen selv med git stash drop når du er sikker på at arbeidet er i trygt forvar.
Når grunnlaget har flyttet seg: stash branch
Har branchen flyttet seg videre så stashen ikke lenger passer, lager git stash branch en ny branch på commiten der stashen ble laget, legger inn stashen der, hvor den garantert passer, og fjerner oppføringen:
$ git stash branch search-filters stash@{1}
Switched to a new branch 'search-filters'
...
Dropped stash@{1} (aa05d36ebb5dca462ca44e0d15313d1e1bff66eb)
Commit arbeidet på den nye branchen, og merge eller rebase den som en hvilken som helst annen branch.
Fjernet ved et uhell?
git stash drop og git stash clear sletter referansen, ikke commitene. drop skriver ut ID-en til commiten den fjernet, og så lenge du har den ID-en, kan du legge den inn igjen med git stash apply dcb6cf2. Uten ID-en leter du etter commits som ingenting lenger peker på:
$ git fsck --unreachable
...
unreachable commit 71170d9e92aa9dc024f199860e70bad17c592d26
unreachable commit dcb6cf266285a1ae2eddd115659790c56acc7039
$ git log --oneline --no-walk 71170d9 dcb6cf2
71170d9 index on main: a69bcbf Initial snapshot
dcb6cf2 On main: two kinds
$ git stash apply dcb6cf2
Commiten med en melding som starter med «On» eller «WIP on», er selve stashen; «index on»-commiten er forelderen med staging-området. Dette virker bare til søppeltømmingen (garbage collection) fjerner objekter ingen peker på, så det er en redningsplanke, ikke en backup.
Stash eller commit?
En stash er lokal. En vanlig git push sender den ikke, den har ikke noe branchnavn, nummeret endrer seg, og den er lett å glemme. Bruk den til avbrudd som varer i minutter. Til alt som varer lenger, lager du en WIP-commit på en egen branch: den har et navn, kan pushes som en kopi og kan ryddes senere med interaktiv rebase. Før git stash clear, les git stash list: clear fjerner alle oppføringene på én gang.
Per-Arne's Git Good!