Git
"The stupid content tracker"
Git har många bra features som vi inte använder så flitigt
Avbryt mig med frågor direkt
git-rebase
"Reapply commits on top of another base tip"
Use case 1: uppstädning innan push
Use case 2: flytta en branch (ändra parent)
Use case 3: redigera commits (historik)
Gå igenom användningsområden kortfattat
rebase är kraftful men finns risk att skjuta sig själv i foten.
Gör inte en rebase om det finns en risk att någon gjort en branch från din. Aldrig master osv
Squash merge -> rebase där man squashar alla commits
rebase: städa innan push
rebase: flytta en branch
Enkel feature branch från master
Master har sedan rört på sig
rebase: flytta en branch
När vi gör en rebase flyttar vi vilken commit vi utgick ifrån och skapar nya commits med samma ändring
Notera e' och f' samt att de gamla e och f egentligen finns kvar bara att ingen branch pekar på dem längre.
rebase: flytta en branch
I det enkla fallet vi tittade på nyss så spelar det inte så stor roll
Men ofta ser det ju mer ut så här
Rörig historik
rebase: flytta en branch
När det hade kunnat se ut så här istället
Med det sagt tar vi lite konkret exempel
Exempel: examples/rebase-2
git rebase -i master
För att flytta till helt annan parent använd --onto
rebase: redigera historik
Exempel: examples/rebase-3
Med rebase kan vi redigera commits lite hur som helst
squash för att slå ihop
ta bort
splitta upp en stor commit till flera små
push
Är branchen redan pushad före rebase?
git push -f
(force-push)
Ta bort branch, pusha igen (PR stängs)
Föredra
--force-with-lease
Exempel: examples/rebase-3
Med rebase kan vi redigera commits lite hur som helst
squash för att slå ihop
ta bort
splitta upp en stor commit till flera små
Bitbucket PR
--fixup --autosquash
$ git commit --fixup HEAD # SHA, branch, ref
$ git commit --fixup :/text # sök commitmeddelande efter "text"
$ git rebase --autosquash -i master
Fixup och dess kusin autosquash används när man commitar för att flagga att man vill städa upp något.
Något man märker första gången man gör det är att man inte får frågan om ett commit meddelande och det för för att git själv kommer fylla i det med lite magi
git-bisect
"Use binary search to find the commit that introduced a bug"
$ git bisect start
$ git bisect bad
$ git bisect good v1.2.0
Används när man vill hitta vilken commit (och PR och Jira) som introducerat ett oönskat beteende
Markera commits som good/bad eller old/new
git-bisect
git bisect run <cmd>...
Men vi är ju lata, så vi vill automatisera det lite.
Med run så kan vi köra ett kommando (vanligtvis ett shellscript med ett testfall) och kommer själv märka commits som good/bad baserat på om kommandot lyckas eller ej.
Nu är det inte alltid möjligt att alltid köra det automatiskt:
Byggtekniska saker han hindra det nya testfallet från att kunna köra
Visuella tester är svåra att automatisera
Kan vara ett svårtestat beteende, ex scrollning
Hooks
.git/hooks
man githooks
Hooks i git är script som görs i samband med händelser. Det kan handla om script som städar upp, verifierar data, osv. Det finns både klient- och serverhooks.
Klienthooks inkluderar
pre-commit och pre-push körs precis innan man commitar samt pushar
Serverhooks inkluderar
update körs när någon pushar
Skapa egna kommandon
"git foobar" letar efter "git-foobar" i $PATH
git-foreach-ref
git-find-pr
git-stash
$ git stash # lägger allt uncommited till stacken
$ git stash list # listar innehåll på stacken
$ git stash show # visar senaste innehållet
$ git stash pop # lägger tillbaka från stacken till working copy
$ git stash drop # tar bort från stacken
stash är en stack med ändringar
typiska användningsområden:
flytta kod till annan branch (man stod på fel branch, inte commitat än)
man vill göra en annan operation, ex rebase, som kräver clean working copy
man är inte färdigt med något men måste byta och jobba med något annat tillfälligt
git-rev-list
$ git rev-list origin/master..HEAD
1d574026fbbf84feb67917810c5d8af7a093320d
56624df871c8d87fc916198e4423d716fff87973
1d045be15f4df428c06d9bd9a5b19b9dadb6aae7
b05fde069ab0af86c3d061243daa0b5f4bb32d7f
Hämtar ut lista med commits mellan två referenser, används mest för att scripta och automatisera.
git-reflog
När olyckan är framme
$ git reflog
1d57402 (HEAD -> master) HEAD@{0}: reset: moving to HEAD
1d57402 (HEAD -> master) HEAD@{1}: commit: figures
56624df HEAD@{2}: commit: branch figure test
1d045be HEAD@{3}: commit: outline
b05fde0 HEAD@{4}: rebase -i (finish): returning to refs/heads/master
b05fde0 HEAD@{5}: rebase -i (fixup): presenter view
4021ded HEAD@{6}: rebase -i (start): checkout origin/master
6d50af6 HEAD@{7}: commit: fixup! presenter view
4021ded HEAD@{8}: commit: presenter view
09e5f33 (origin/master) HEAD@{9}: commit: node image
a6d0c5d HEAD@{10}: commit (initial): stub
vad gör man när man gjort fel?
råkat rebase bort en commit? squashat fel saker?
git är garbage collected och tar inte bort något direkt, alla gamla commits osv är kvar.
reflog to the rescue, den talar om alla operationer du senast gjort
git-cherry-pick
$ git cherry-pick 2a33789
ta en commit från en annan branch och kopiera in den i nuvarande branch
Precis som rebase måste man vara lite försiktig, speciellt om man har cherrypicks som ändrar rader fram och tillbaka.
--porcelain
$ git status --porcelain
M figures/merge2.dot
M figures/rebase-merge.dot
A figures/rebase2.dot
?? todo.org
Många kommandon i git stöder porcelain
Ändrar så output är enkelt att hantera i script och är garanterat att vara stabilt, dvs formatet ändrar inte på sig mellan olika releaser