Gode commits: små, bevisste og godt beskrevne
Den interaktive leksjonen trenger JavaScript. Teksten under er hele leksjonen.
Etter leksjonen kan du
- dele blandede endringer i commits med én hensikt hver, også inne i én fil med
git add -panvende - skrive en commitmelding med en kort emnelinje i imperativ og en brødtekst som forklarer hvorfor anvende
- bruke
.gitignorefor å holde byggfiler, logger og hemmeligheter utenfor historikken, og forklare hvor grensen går anvende
Forstå: Én commit, én hensikt
Tenk deg en commit som heter Fix stuff. Den retter en skrivefeil, legger til en ny uke i planen og tar med en loggfil ved et uhell. Om en måned vet ingen hva den var til. Å angre bare én del blir også tungvint.
Her er det samme arbeidet som to små commits, og loggfilen er ikke med i det hele tatt. Hver commit har én hensikt. Da blir de lettere å lese, lettere å angre og lettere å lete i når en feil dukker opp.
Se på meldingene. Emnelinjen er kort, helst under femti tegn, og skrevet i imperativ, som en ordre: Add exam week, ikke Added stuff. Den fullfører setningen «If applied, this commit will». Begrunnelsen skriver du i en brødtekst etter en tom linje.
Men hva om begge endringene ligger i samme fil? Vi spoler tilbake til før commitene. git add -p viser endringene i blokker, kalt hunks, og spør om hver av dem. Her er bare skrivefeilen staget. Den nye uken venter i arbeidsmappen.
Noen filer skal aldri inn i historikken: byggfiler, logger og hemmeligheter som passord. Filen .gitignore lister mønstre, for eksempel *.log. Usporede filer som passer, viser Git ikke lenger, og git add . hopper over dem. Selve .gitignore committer du som en vanlig fil.
Ignore har to grenser. Den påvirker ikke filer Git allerede sporer. Og den er ingen sikkerhetsmekanisme: har et passord først havnet i en commit som er delt, ligger det i historikken. Da må passordet byttes.
Se demo: Del opp en blandet endring
Vi har jobbet en stund i en kursplan. Statusen viser to ting. plan.txt er endret. debug.log er usporet: en logg programmet skrev, som ikke hører hjemme i historikken.
$ git status --short
Diffen har to blokker som starter med to krøllalfa. Hver blokk er en hunk. Den første retter en skrivefeil i uke to. Den andre legger til uke elleve. To ulike hensikter, altså to commits.
$ git diff
git add -p spør hunk for hunk. Vi svarer y, ja, på skrivefeilen og n, nei, på den nye uken. printf skriver bare svarene for oss, så demoen ikke stopper opp. Nå har plan.txt ulikt innhold i staging-området og i arbeidsmappen.
$ printf 'y\nn\n' | git add -p plan.txt
Før vi committer, sjekker vi utkastet. git diff --staged viser bare rettingen av skrivefeilen. Akkurat det skal med.
$ git diff --staged
Emnelinjen er kort, i imperativ, og sier hva commiten gjør. Den andre -m blir brødteksten, som forklarer hvorfor. Uke elleve er fortsatt bare i arbeidsmappen.
$ git commit -m "Fix typo in week 2" -m "The misspelling made the plan hard to search."
Nå loggfilen. Vi lager en .gitignore med mønsteret *.log. Det betyr alle filer som slutter på .log, i alle mapper.
$ echo "*.log" > .gitignore
Hva viser statusen nå, tror du?
$ git status --short
Oppgaver
- Les endringene som ikke er staget.
- Stage bare rettingen av skrivefeilen i
plan.txt, ikke den nye uken. - Commit rettingen av skrivefeilen med en kort emnelinje og en brødtekst som forklarer hvorfor.
- Få Git til å ignorere alle
.log-filer. - Sjekk statusen igjen.
Øv: Overfør: rydd i et oppskriftsprosjekt
Et annet prosjekt: en oppskrift, en lokal fil med hemmeligheter, en byggmappe og en loggfil som ble committet ved en feil. Se på git status først.
Oppgaver
.envinneholder hemmeligheter, ogbuild/lages på nytt av byggverktøyet. Få Git til å slutte å foreslå begge, og commit regelen i en egen commit. Hemmelighetene og byggfilene skal ikke inn i historikken.recipe.txthar to uavhengige endringer: en retting av stavemåten og et nytt serveringstips. Commit bare rettingen. Gi commiten en emnelinje på høyst 50 tegn og en brødtekst som forklarer hvorfor.app.logble committet ved en feil, og Git viser endringer i den hele tiden. Slutt å spore filen og få Git til å ignorere den, men behold den på disken. Lagre dette i en commit.
Sjekk deg selv: Hent det fram igjen
Hvilken emnelinje er best?
- Added password reset link to login page
- Add password reset link to login page
- Add reset link because users could not find it
config.env med et passord ble committet og pushet forrige uke. I dag legger du config.env inn i .gitignore. Hva skjer?
- Git fjerner filen fra historikken
- Ingenting for den filen: Git sporer den fortsatt, og passordet ligger i historikken
- Filen forsvinner fra GitHub ved neste push
I samme fil har du rettet en feil og formatert en funksjon som ikke har noe med feilen å gjøre. Hvordan bør du committe?
- Én commit, siden det er én fil
- To commits: stage feilrettingen med
git add -p, commit, og commit formateringen etterpå - Vent og commit alt samlet på slutten av dagen
Repetisjon fra leksjonen om de tre områdene: du har staget én hunk i plan.txt. Så retter du en ny skrivefeil i samme fil og kjører git commit -m "Fix typo" uten å stage igjen. Hva viser git status --short for plan.txt etterpå?
- Ingenting, fordi commiten tok med hele filen
Mi første kolonne: endringen er staget og venterMi andre kolonne: endret i arbeidsmappen, ikke staget
Vanlige misforståelser
- «En commit er én fil, eller én arbeidsdag.» En commit er én hensikt. Den kan berøre mange filer, eller bare en del av én.
- «
.gitignoreskjuler filer som allerede er committet, og beskytter hemmeligheter.» Ignore gjelder bare usporede filer. En hemmelighet som er pushet, må byttes ut.
Les mer
Hva gjør en commit god?
- Én hensikt. En commit som gjør én ting, er lett å lese i en code review, lett å angre med
git revertog lett å finne igjen når du leter etter commiten som innførte en feil. - Hel. Den motsatte feilen er å dele for mye. En commit som etterlater prosjektet ødelagt, for eksempel en funksjon uten kallet som trengs, gjør historikken vanskeligere å bruke. Hver commit bør helst bygge og bestå testene.
- En fast arbeidsrytme: rediger, les
git diff, stage det som hører sammen, lesgit diff --staged, commit, og kjør testene.
git add . er raskt, men upresist: det tar med alt under mappen, også filer du glemte at fantes. Navngi filene, eller bruk git add -p.
Commitmeldingen
Fix typo in week 2
The misspelling made the plan hard to search for
"staging". No other weeks are affected.
- Emnelinjen er kort, helst høyst 50 tegn, i imperativ og uten punktum. Den fullfører setningen «If applied, this commit will …». Skriv
Add exam week, ikkeAdded stuff. - En tom linje skiller emne og brødtekst. Verktøy som
git log --onelineviser bare emnelinjen. - Brødteksten forklarer hvorfor og eventuelle følger. Hva som ble endret, viser diffen allerede. Bryt linjene rundt 72 tegn.
Med -m to ganger blir første verdi emnelinjen og andre verdi et eget avsnitt:
$ git commit -m "Stop tracking app.log" -m "The log is rewritten on every run and only adds noise to diffs."
$ git log -1
commit b33e60b41b7756c5b4e28b6a7ff2abfc63dbf542
Author: Student <student@example.invalid>
Date: Tue Oct 13 09:10:51 2026 +0200
Stop tracking app.log
The log is rewritten on every run and only adds noise to diffs.
Uten -m åpner git commit editoren som er satt i core.editor. Linjer som starter med #, fjernes. Lagrer du en tom melding, avbrytes commiten. git commit -v viser i tillegg diffen nederst i editoren, så du ser hva du beskriver.
git add -p i detalj
git add -p deler endringene i hunks og spør for hver av dem:
$ git add -p plan.txt
diff --git a/plan.txt b/plan.txt
index f757011..e85757e 100644
--- a/plan.txt
+++ b/plan.txt
@@ -1,6 +1,6 @@
Course plan
Week 1: snapshots
-Week 2: stagign
+Week 2: staging
Week 3: history
Week 4: branches
Week 5: merging
(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?
Bokstavlisten i hakeparentesen varierer litt mellom Git-versjoner. Disse svarene finnes i alle:
| Svar | Betyr |
|---|---|
y / n |
Stage denne hunken / hopp over den |
a / d |
Stage resten av hunkene i filen / hopp over resten |
s |
Del hunken i mindre biter, når det finnes uendrede linjer mellom endringene |
e |
Rediger hunken for hånd |
q |
Avslutt. Det du har svart ja på, er fortsatt staget |
? |
Vis hjelp |
Etterpå viser git status --short filen som MM: én del er staget, resten venter. Kontroller alltid med git diff --staged før du committer. Har du staget en hunk for mye, tar git restore --staged -p den ut igjen, med de samme spørsmålene.
Hva git commit -a tar med
-a stager endringer og slettinger i filer Git allerede sporer, og committer. Nye filer blir ikke med, og du hopper over sjekken av utkastet:
$ echo tmp > notes.txt
$ git commit -am "Add notes"
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
notes.txt
nothing added to commit but untracked files present (use "git add" to track)
.gitignore-mønstre
| Mønster | Treffer |
|---|---|
*.log |
Alle filer som slutter på .log, i alle mapper |
build/ |
Alle mapper som heter build, med alt innhold |
/todo.txt |
Bare todo.txt i rotmappen |
!keep.log |
Unntak: keep.log skal likevel vises |
docs/**/*.pdf |
PDF-filer på alle nivåer under docs |
# tekst |
En kommentar |
Ignorerte filer forsvinner fra git status. --ignored viser dem med !!, og git check-ignore -v forteller hvilken regel som slo til. En regel som starter med !, betyr at filen likevel ikke ignoreres:
$ git status --short --ignored
M plan.txt
?? .gitignore
?? keep.log
!! build/
!! debug.log
$ git check-ignore -v debug.log build/a.js keep.log
.gitignore:2:*.log debug.log
.gitignore:3:build/ build/a.js
.gitignore:4:!keep.log keep.log
Prøver du å stage en ignorert fil, sier Git fra:
$ git add other.log
The following paths are ignored by one of your .gitignore files:
other.log
hint: Use -f if you really want to add them.
.gitignorecommittes og deles med alle. Lokale unntak som bare gjelder deg, skriver du i.git/info/exclude. Filer som editoren eller operativsystemet lager, som.DS_Storeeller.idea/, passer best i en global fil satt medcore.excludesFile.- Git sporer bare filer, ikke tomme mapper. Vil du ha en tom mappe med, legger du en liten fil i den, ofte kalt
.gitkeep.
Når filen allerede er sporet
Ignore gjelder bare usporede filer. Er app.log allerede committet, endrer en ny regel ingenting: Git viser fortsatt endringene i den. Slik slutter du å spore den, uten å slette den fra disken:
$ git rm --cached app.log
rm 'app.log'
$ echo "app.log" >> .gitignore
$ git add .gitignore
$ git commit -m "Stop tracking app.log"
git status --short viser D app.log før commiten: filen fjernes fra snapshotet, men blir liggende hos deg. Når andre tar inn commiten med merge eller pull, sletter Git filen fra arbeidsmappen deres.
Hemmeligheter er et eget problem. Gamle commits inneholder fortsatt filen, og alle som har hentet dem, har en kopi. Et passord eller en nøkkel som har vært pushet, må byttes ut. En ny commit som sletter filen, er ikke nok. Commit heller en mal som
.env.exampleuten ekte verdier.
Les videre
- git commit, avsnittet «Discussion» om meldingsformat
- git add, interaktiv modus
- gitignore, git check-ignore og git rm
Per-Arne's Git Good!