- Hva er egentlig en commit?
- Hvorfor må en kjøre både git add OG git commit?
- Hva er egentlig en branch?
- Hvordan holder git styr på filer og endringer?
Utgangspunktet her er at en har brukt git før, vet basically hva de mest vanlige git-kommandoene gjør, men skjønner ikke helt hvorfor det fungerer som det gjør, eller hvordan det funker “under the hood”.
rm -rf .git index.js
Det første man må vite er at git er en Directed Acyclic Graph
git init
touch index.js
echo 'console.log("Hei!")' >> index.js
git add -A
git commit -m "Initial commit"
ls -p .git
Som konsept er en commit et innslag i historikken.
Men i realiteten er en commit er egentlig bare ei fil.
git log
tree .git/objects/
Det er ikke en database.
Det er bare masse filer som peker på hverandre.
En commit
-fil under objects
er komprimert med zlib.
Kan bruke pigz -dcz
for å decompress.
Bruk git cat-file -p
for å decompress og print innhold av en object.
Et tree
er på samme måte som en commit
bare en fil under .git/objects
Den kan sees nesten på som ei mappe som peker på andre filer og mapper.
Og ja, så klart er den også en .git/objects
Men kanskje mer korrekt å si, et snapshot av en fil i et gitt øyeblikk.
Selv om en er vant til å tenke på "patches" i git-verden, så er det ingen diffs mellom filer som mellomlagres.
echo "return;" >> index.js
git add index.js
git commit -m "fix: Remember to return"
+--------+ +------+ +------+
| Commit | --> | Tree | --> | Blob |
+--------+ +------+ +------+
+--------+ +------+ +------+
| Commit | --> | Tree | --> | Blob |
+--------+ +------+ +------+
|
V
+--------+ +------+ +------+
| Commit | --> | Tree | --> | Blob |
+--------+ +------+ +------+
Fordi noen mener at git er så skummelt og mystisk at hvis du skal gjøre noe som helst utenom det vanlige må du ta en zip-backup av repoet.
git reset --hard HEAD~1
Eller kanskje ikke? git reflog
to the rescue.
Hvis den fortsatt eksisterer i .git/objects
- hvorfor er den borte fra main
-branchen sin historikk?
Da ser vi i .git/refs
Da ser vi i .git/HEAD
Si at vi skriver noe inn i index.js
:
echo "// unecessary return tbh" >> index.js
Hvordan vet git at filen har endret seg fra før? Sjekker den dato på oppdatering kanskje?
Ligger under .git/index
:
cat .git/index
Bare tull og fjas!
Heldigvis har vi git ls-files
git ls-files -s
Git vet at en fil har endret seg med å sammenligne fil-hash med index
git checkout -b fix-branch
Fordi index-filen deles på tvers av branches.
Filer blir med så lenge det ikke er noen conflicts.
SHA1 av git-object type + file length + NULL-byte + content.
Eller bare kjøre git hash-object
da..
Ja det er veldig kult! Fordi det viser hvordan git sikrer historikken.
git log
echo "Før commit amend:"
git log --oneline
echo "woops!" >> index.js
git add index.js
git commit --amend --no-edit -q
echo "Etter commit amend:"
git log --oneline
Hvorfor oppfører de seg forskjellig?
....oooog snapshot conflict fixen mellom de.
Så begge historier sammenføyes på dato.
Hva skjer da om du resetter merge-commiten?
Bare at en sammenføyer ikke historien
Og hvorfor det kan være OK å lære seg
Uten å zippe folderen! git clone --bare
Kan også ligge på en network share eller lignende for samarbeid!
- push
- pull
- conflicts
- pull requests
- cherry-picking
- diff
- fetch
- tag