Tre områder: arbeidsmappen, staging-området og HEAD
Den interaktive leksjonen trenger JavaScript. Teksten under er hele leksjonen.
Etter leksjonen kan du
- forklare hvor en filversjon ligger, i arbeidsmappen, i staging-området eller i HEAD, og forutsi hvilken versjon som havner i neste commit forstå
- lese
git status --shortog si hva de to kolonnene betyr forstå - velge mellom
git diffoggit diff --stagedfor å se det du faktisk lurer på anvende
Forstå: Tre steder en fil kan ligge
En fil kan finnes i tre versjoner samtidig. Arbeidsmappen er filene du ser og redigerer. Staging-området, også kalt index, er utkastet til neste commit. HEAD peker på siste commit på branchen din, og snapshotet der er den tredje versjonen. Akkurat nå er alle tre like.
Når du redigerer filen, endres bare arbeidsmappen. Staging-området og HEAD har fortsatt den gamle versjonen. Git sier at filen er endret, men ikke staget.
git add kopierer filen slik den er akkurat nå, inn i staging-området. Det er en kopi av innholdet, ikke et merke på filen.
Redigerer du igjen etter git add, får du tre ulike versjoner. Den nye linjen finnes bare i arbeidsmappen. Staging-området husker fortsatt kopien du tok.
En diff sammenligner alltid to versjoner. git diff sammenligner staging-området med arbeidsmappen, altså det du ikke har staget ennå. git diff --staged sammenligner HEAD med staging-området, altså det du har staget.
Se demo: Commiten tar det som er staget
Vi starter med et repository med én commit. Først legger vi til en linje i README. Se at bare kortet i arbeidsmappen endrer seg.
$ echo "Install: npm install" >> README.md
git diff viser forskjellen mellom staging-området og arbeidsmappen. Plusstegnet markerer den nye linjen. Den er ennå ikke staget.
$ git diff
Nå kopierer vi denne versjonen inn i staging-området. Kortet i midten får den nye versjonen.
$ git add README.md
Så redigerer vi videre, slik man ofte gjør. Vi legger til en linje til, etter git add. Nå har filen tre ulike versjoner.
$ echo "Run: npm start" >> README.md
Den korte statusen viser to bokstaver. Første kolonne sammenligner HEAD med staging-området. Andre kolonne sammenligner staging-området med arbeidsmappen. MM betyr altså én endring som er staget, og en nyere som ikke er det.
$ git status --short
git diff --staged viser det som er staget: bare install-linjen.
$ git diff --staged
Nå committer vi. Hva tror du havner i snapshotet?
$ git commit -m "Add install instructions"
Status igjen. Første kolonne er tom: staging-området og HEAD er like. Andre kolonne sier M: npm start-linjen venter fortsatt i arbeidsmappen.
$ git status --short
Oppgaver
- Legg til linjen
Install: npm installnederst iREADME.md. - Vis endringene som ikke er staget ennå.
- Stage
README.md. - Vis statusen i kortformat.
- Commit det som er staget, og bare det.
Øv: Overfør: velg hva som blir med
Et nytt prosjekt der flere filer allerede er endret, og én er delvis staget. Start med å undersøke tilstanden.
Oppgaver
todo.txthar en staget versjon og en enda nyere redigering. Lag en commit som inneholder den nyeste versjonen avtodo.txt, og ingen andre filer.- Både
app.jsognotes.txter endret. Commit bare endringen iapp.js.notes.txtskal fortsatt være endret, men ikke committet.
Sjekk deg selv: Hent det fram igjen
Du har staget README.md, og så redigert den igjen. Du vil se bare den nyeste redigeringen. Hvilken kommando bruker du?
git diffgit diff --stagedgit diff HEAD
git status --short viser MM app.js. Hva betyr det?
- Filen er endret i to commits
- Filen har en endring som er staget, og en nyere som ikke er det
- Filen har en konflikt
Repetisjon fra forrige leksjon: repositoryet sporer app.js, notes.txt og todo.txt. Du endrer og stager app.js. notes.txt har også en endring du ikke har staget. Du committer. Hvilke filer finnes i snapshotet til den nye commiten?
- Bare
app.js, fordi det var den eneste filen som ble endret - Alle tre: den nye versjonen av
app.js, og de to andre slik de var i forrige commit - Alle tre, slik de ser ut i arbeidsmappen akkurat nå
Vanlige misforståelser
- «Commiten tar filen slik den ser ut i editoren.» Den tar versjonen som ligger i staging-området.
- «
git addmerker filen, så senere endringer blir med automatisk.»git addkopierer innholdet slik det er akkurat da. - «
git diffviser alt som skal committes.» Vanliggit diffviser bare det som ennå ikke er staget.
Les mer
De tre områdene, presist
- Arbeidsmappen (working tree) er vanlige filer på disk. Editoren din ser bare denne.
- Staging-området (index) er filen
.git/index. Den er en fullstendig liste over alle sporede filer og innholdet deres, ikke bare en liste over endringer. Rett etter en commit er staging-området lik HEAD. Når folk sier at «ingenting er staget», betyr det at staging-området og HEAD er like. - HEAD peker på branchen du står på, og branchen peker på den siste commiten. Snapshotet i den commiten er sammenligningspunktet for «hva er endret siden sist».
- En fil er sporet når den finnes i staging-området. En ny fil er usporet til første
git add.
git commit lager snapshotet fra staging-området. Arbeidsmappen leses ikke. Derfor må en redigering etter git add stages på nytt for å bli med.
Hvilke to versjoner sammenlignes?
En diff har alltid to endepunkter. Velg kommando etter hvilket spørsmål du stiller:
| Kommando | Sammenligner | Svarer på |
|---|---|---|
git diff |
staging-området → arbeidsmappe | Hva har jeg endret, men ikke staget? |
git diff --staged |
HEAD → staging-området | Hva blir med i neste commit? |
git diff HEAD |
HEAD → arbeidsmappe | Alt som er endret siden siste commit |
--cached betyr det samme som --staged. Usporede filer vises aldri i git diff, så en ny fil du har glemt å stage, finner du bare i git status.
Her har README.md fått én linje som er staget, og én nyere som ikke er det:
$ git diff
diff --git a/README.md b/README.md
index 33684f8..f7ea923 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
Welcome
Install: npm install
+Run: npm start
$ git diff --staged
diff --git a/README.md b/README.md
index ba4c514..33684f8 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
Welcome
+Install: npm install
index 33684f8..f7ea923er ID-ene til de to filversjonene som sammenlignes. Legg merke til at33684f8er «etter» i den ene diffen og «før» i den andre. Det er den stagede versjonen.@@ -1,2 +1,3 @@er overskriften til en hunk, en sammenhengende blokk med endringer: fra linje 1 i den gamle versjonen, 2 linjer, til linje 1 i den nye, 3 linjer.- Linjer med
+er lagt til, linjer med-er fjernet, og linjer med mellomrom er kontekst. - Nyttige valg:
--statgir en oversikt per fil,--name-onlygir bare filnavn, og-- filbegrenser diffen til én fil.
Les git status --short
$ git status --short
MM README.md
AM app.js
D gone.txt
R old.txt -> renamed.txt
?? new.txt
Første kolonne (X) sammenligner HEAD med staging-området. Andre kolonne (Y) sammenligner staging-området med arbeidsmappen. Et mellomrom betyr «ingen forskjell».
| Kode | Betyr |
|---|---|
M |
Endret og staget |
M |
Endret, ikke staget |
MM |
En staget endring og en nyere som ikke er staget |
A |
Ny fil, staget |
AM |
Ny fil staget, så endret igjen |
D |
Sletting staget, for eksempel med git rm |
D |
Slettet fra disk, men slettingen er ikke staget |
R |
Omdøping staget, for eksempel med git mv |
?? |
Usporet |
Den lange git status sier det samme med ord, og foreslår kommandoer. Der ser du git restore --staged <file>, som angrer det du har staget ved å legge HEAD-versjonen tilbake i staging-området, og git restore <file>, som forkaster endringen i arbeidsmappen. Den siste kan ikke angres, fordi endringen aldri var lagret i Git. Leksjonen om å angre går gjennom begge.
Måter å stage på
git add notes.txtstager akkurat de filene du nevner. Det er mest presist.git add .stager alt under mappen du står i: endrede, nye og slettede filer, men ikke filer som er ignorert.git add -Agjør det samme for hele repositoryet.git add -ustager endringer og slettinger i filer Git allerede sporer, men ingen nye filer.git add -plar deg velge bit for bit. Det lærer du i leksjonen om gode commits.git rm notes.txtsletter en fil og stager slettingen.git mv old.txt new.txtomdøper og stager.
Vanen som sparer deg for flest feil: kjør git diff --staged rett før git commit.
Vanlige overraskelser
- «Endringen ble ikke med i commiten.» Du kjørte
git addfør den siste redigeringen.git status --shortviserMpå filen. Stage den på nytt og commit. - «Diffen er tom, men status viser endringer.»
git diffviser ingenting når alt er staget. Brukgit diff --staged. - «Den nye filen vises ikke i diffen.» Den er usporet. Den står under
??i status. - Skrivefeil i filnavnet:
$ git add REDME.md
fatal: pathspec 'REDME.md' did not match any files
Ingenting ble staget. Sjekk navnet med git status, og prøv igjen.
Les videre
- Recording Changes to the Repository i Pro Git-boka
- git add, git status, git diff og git restore
Per-Arne's Git Good!