-
1. Kom igång
- 1.1 Om versionshantering
- 1.2 En kort historik om Git
- 1.3 Vad är Git?
- 1.4 Kommandoraden
- 1.5 Installera Git
- 1.6 Första gången med Git
- 1.7 Få hjälp
- 1.8 Sammanfattning
-
2. Grunderna i Git
- 2.1 Att få tag i ett Git‑kodförråd
- 2.2 Spara ändringar i kodförrådet
- 2.3 Visa incheckningshistoriken
- 2.4 Ångra saker
- 2.5 Arbeta med fjärrkodförråd
- 2.6 Att tagga
- 2.7 Git-alias
- 2.8 Sammanfattning
-
3. Git-grenar
- 3.1 Grenar i korthet
- 3.2 Grundläggande gren- och sammanfogningsarbete
- 3.3 Grenhantering
- 3.4 Arbetsflöden med grenar
- 3.5 Fjärrgrenar
- 3.6 Ombasering
- 3.7 Sammanfattning
-
4. Git på servern
- 4.1 Protokollen
- 4.2 Konfigurera Git på en server
- 4.3 Generera din publika SSH-nyckel
- 4.4 Konfigurera servern
- 4.5 Git-demon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Tredjepartsalternativ
- 4.10 Sammanfattning
-
5. Distribuerat Git
-
6. GitHub
-
7. Git-verktyg
- 7.1 Revisionsurval
- 7.2 Interaktiv köläggning
- 7.3 Lägga undan och städa
- 7.4 Signera ditt arbete
- 7.5 Sökning
- 7.6 Skriva om historik
- 7.7 Nollställning förklarad
- 7.8 Avancerad sammanslagning
- 7.9 Rerere
- 7.10 Felsöka med Git
- 7.11 Undermoduler
- 7.12 Bunta
- 7.13 Ersätt
- 7.14 Lagring av inloggningsuppgifter
- 7.15 Sammanfattning
-
8. Anpassa Git
- 8.1 Git‑konfiguration
- 8.2 Git‑attribut
- 8.3 Git‑krokar
- 8.4 Ett exempel på Git‑upprätthållen policy
- 8.5 Sammanfattning
-
9. Git och andra system
- 9.1 Git som klient
- 9.2 Migrera till Git
- 9.3 Sammanfattning
-
10. Git bakom kulisserna
- 10.1 Lågnivådel och användardel
- 10.2 Git-objekt
- 10.3 Git-referenser
- 10.4 Packfiler
- 10.5 Refspecen
- 10.6 Överföringsprotokoll
- 10.7 Underhåll och dataåterställning
- 10.8 Miljövariabler
- 10.9 Sammanfattning
-
A1. Bilaga A: Git i andra miljöer
- A1.1 Grafiska gränssnitt
- A1.2 Git i Visual Studio
- A1.3 Git i Visual Studio Code
- A1.4 Git i IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git i Sublime Text
- A1.6 Git i Bash
- A1.7 Git i Zsh
- A1.8 Git i PowerShell
- A1.9 Sammanfattning
-
A2. Bilaga B: Bädda in Git i dina applikationer
- A2.1 Git på kommandoraden
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Bilaga C: Git-kommandon
- A3.1 Uppstart och konfiguration
- A3.2 Skaffa och skapa projekt
- A3.3 Grundläggande ögonblicksbilder
- A3.4 Grening och sammanslagning
- A3.5 Dela och uppdatera projekt
- A3.6 Inspektion och jämförelse
- A3.7 Felsökning
- A3.8 Patchning
- A3.9 E‑post
- A3.10 Externa system
- A3.11 Administration
- A3.12 Lågnivåkommandon
7.1 Git-verktyg - Revisionsurval
Vid det här laget har du lärt dig de flesta av de dagliga kommandona och arbetsflödena du behöver för att hantera eller förvalta ett Git-kodförråd för versionshantering av källkod. Du har klarat av de grundläggande uppgifterna att spåra och checka in filer, och du har tagit vara på kraften i köytan samt lätta ämnesgrenar och sammanslagningar.
Nu går vi vidare till ett antal mycket kraftfulla saker som Git kan göra och som du kanske inte använder dagligen, men som du ändå kan behöva någon gång.
Revisionsurval
Git låter dig referera till en enskild incheckning, en uppsättning incheckningar eller ett intervall av incheckningar på flera sätt. De är inte alltid självklara, men är bra att känna till.
Enskilda revisioner
Du kan naturligtvis referera till en enskild incheckning med dess fullständiga SHA‑1-hash på 40 tecken, men det finns också mer människovänliga sätt att referera till incheckningar. Detta avsnitt beskriver de olika sätt du kan referera till en incheckning.
Kort SHA‑1
Git är tillräckligt smart för att förstå vilken incheckning du menar om du anger de första tecknen i SHA‑1-hashen, så länge den delvisa hashens längd är minst fyra tecken och entydig; det vill säga, inget annat objekt i objektdatabasen kan ha en hash som börjar med samma prefix.
Till exempel, om du vill undersöka en specifik incheckning där du vet att du lade till viss funktionalitet, kan du först köra kommandot git log för att hitta incheckningen:
$ git log
commit 734713bc047d87bf7eac9674765ae793478c50d3
Author: Scott Chacon <schacon@gmail.com>
Date: Fri Jan 2 18:32:33 2009 -0800
Fix refs handling, add gc auto, update tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 14:58:32 2008 -0800
Add some blame and merge stuff
I det här fallet, säg att du är intresserad av incheckningen vars hash börjar med 1c002dd….
Du kan inspektera den incheckningen med någon av följande varianter av git show (förutsatt att de kortare varianterna är entydiga):
$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
$ git show 1c002dd4b536e7479f
$ git show 1c002d
Git kan räkna ut en kort, unik förkortning för dina SHA‑1-värden.
Om du skickar --abbrev-commit till kommandot git log använder utdata kortare värden men håller dem unika; standard är sju tecken men de blir längre om det behövs för att hålla SHA‑1 entydig:
$ git log --abbrev-commit --pretty=oneline
ca82a6d Change the version number
085bb3b Remove unnecessary test code
a11bef0 Initial commit
I allmänhet räcker åtta till tio tecken mer än väl för att vara unika inom ett projekt. Till exempel hade Linuxkärnan (som är ett ganska stort projekt) i februari 2019 över 875 000 incheckningar och nästan sju miljoner objekt i objektdatabasen, utan att två objekt hade identiska SHA‑1 i de första 12 tecknen.
|
Notera
|
EN KORT ANMÄRKNING OM SHA‑1
Många blir någon gång oroliga för att de, av slump, ska få två olika objekt i sitt kodförråd som hashar till samma SHA‑1-värde. Vad händer då? Om du råkar checka in ett objekt som hashar till samma SHA‑1-värde som ett tidigare annat objekt i ditt kodförråd kommer Git att se att det tidigare objektet redan finns i din Git-databas, anta att det redan skrivits och helt enkelt återanvända det. Om du försöker lägga ut det objektet igen någon gång kommer du alltid få data för det första objektet. Du bör dock känna till hur absurd osannolik den här situationen är.
SHA‑1-summan är 20 byte eller 160 bitar.
Antalet slumpmässigt hashade objekt som krävs för att ge 50 % sannolikhet för en enda kollision är ungefär 280 (formeln för att bestämma kollisionssannolikhet är Här är ett exempel som ger en känsla för vad som skulle krävas för att få en SHA‑1-kollision. Om alla 6,5 miljarder människor på jorden programmerade, och varje sekund producerade kod motsvarande hela Linuxkärnans historik (6,5 miljoner Git-objekt) och skickade in den i ett enda enormt Git-kodförråd, skulle det ta ungefär 2 år innan det kodförrådet innehöll tillräckligt många objekt för att ha 50 % sannolikhet för en enda SHA‑1-kollision. En spontan SHA‑1-kollision är alltså mindre sannolik än att varje medlem i ditt programmeringsteam blir attackerad och dödad av vargar i separata incidenter samma natt. Om du lägger flera tusen dollar i beräkningskraft på det går det att syntetisera två filer med samma hash, vilket visades på https://en.wikipedia.org/wiki/SHA-1 i februari 2017. Git håller på att gå över till SHA256 som standardhashalgoritm, som är mycket mer motståndskraftig mot kollisionsattacker, och har kod på plats för att mildra angreppet (även om den inte helt kan eliminera det). |
Grenreferenser
Ett enkelt sätt att referera till en viss incheckning är om det är incheckningen längst ut på en gren; i så fall kan du helt enkelt använda grennamnet i vilket Git-kommando som helst som förväntar sig en referens till en incheckning.
Om du till exempel vill titta på den senaste incheckningen på en gren är följande kommandon likvärdiga, förutsatt att grenen topic1 pekar på incheckningen ca82a6d…:
$ git show ca82a6dff817ec66f44342007202690a93763949
$ git show topic1
Om du vill se vilken specifik SHA‑1 en gren pekar på, eller om du vill se vad något av exemplen i praktiken leder till i termer av SHA‑1, kan du använda ett Git-rörverktyg som heter rev-parse.
Du kan läsa mer om rörverktyg i Git bakom kulisserna; kort sagt finns rev-parse för lågnivåoperationer och är inte tänkt för dagligt bruk.
Det kan ändå vara hjälpsamt när du behöver se vad som faktiskt händer.
Här kan du köra rev-parse på din gren.
$ git rev-parse topic1
ca82a6dff817ec66f44342007202690a93763949
Referenslogg-kortnamn
En sak Git gör i bakgrunden medan du arbetar är att hålla en "referenslogg" – en logg över var dina HEAD- och grenreferenser har befunnit sig de senaste månaderna.
Du kan se din referenslogg med git reflog:
$ git reflog
734713b HEAD@{0}: commit: Fix refs handling, add gc auto, update tests
d921970 HEAD@{1}: merge phedders/rdocs: Merge made by the 'recursive' strategy.
1c002dd HEAD@{2}: commit: Add some blame and merge stuff
1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
95df984 HEAD@{4}: commit: # This is a combination of two commits.
1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD
Varje gång spetsen på din gren uppdateras av någon anledning sparar Git den informationen åt dig i den här tillfälliga historiken.
Du kan använda referenslogg-datan för att referera till äldre incheckningar också.
Om du till exempel vill se det femte tidigare värdet av HEAD i ditt kodförråd kan du använda referensen @{5} som du ser i referenslogg-utdata:
$ git show HEAD@{5}
Du kan också använda den här syntaxen för att se var en gren befann sig för en viss tid sedan.
Till exempel, för att se var din master-gren var igår kan du skriva:
$ git show master@{yesterday}
Detta visar var spetsen av din master-gren var igår.
Tekniken fungerar bara för data som fortfarande finns i refloggen, så du kan inte använda den för att titta på incheckningar som är äldre än några månader.
För att se referenslogg-information formaterad som git log-utdata kan du köra git log -g:
$ git log -g master
commit 734713bc047d87bf7eac9674765ae793478c50d3
Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
Reflog message: commit: Fix refs handling, add gc auto, update tests
Author: Scott Chacon <schacon@gmail.com>
Date: Fri Jan 2 18:32:33 2009 -0800
Fix refs handling, add gc auto, update tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
Reflog message: merge phedders/rdocs: Merge made by recursive.
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
Det är viktigt att notera att referenslogg-information är strikt lokal – det är en logg enbart över det du har gjort i ditt kodförråd.
Referenserna kommer inte att vara desamma i någon annans kopia av kodförrådet; dessutom har du en tom referenslogg direkt efter att du klonat ett kodförråd, eftersom ingen aktivitet ännu skett i ditt kodförråd.
Om du kör git show HEAD@{2.months.ago} kommer du bara se den matchande incheckningen om du klonade projektet för minst två månader sedan – klonade du det nyligen ser du bara din första lokala incheckning.
|
Tips
|
Se refloggen som Gits motsvarighet till skalhistorik
Om du har UNIX- eller Linuxbakgrund kan du se refloggen som Gits motsvarighet till skalhistorik, vilket betonar att det som finns där bara är relevant för dig och din "arbetsomgång", och inte har något att göra med andra som kan arbeta på samma maskin. |
|
Notera
|
Maska klamrar i PowerShell
När du använder PowerShell är klamrar som
|
Anfadersreferenser
Det andra huvudsättet att ange en incheckning är via dess anfäder.
Om du sätter ^ (cirkumflex) i slutet av en referens tolkar Git det som föräldern till den incheckningen.
Anta att du tittar på historiken i ditt projekt:
$ git log --pretty=format:'%h %s' --graph
* 734713b Fix refs handling, add gc auto, update tests
* d921970 Merge commit 'phedders/rdocs'
|\
| * 35cfb2b Some rdoc changes
* | 1c002dd Add some blame and merge stuff
|/
* 1c36188 Ignore *.gem
* 9b29157 Add open3_detach to gemspec file list
Då kan du se föregående incheckning genom att ange HEAD^, vilket betyder "föräldern till HEAD":
$ git show HEAD^
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
|
Notera
|
Maska cirkumflex på Windows
I Windows
|
Du kan också ange en siffra efter ^ för att identifiera vilken förälder du vill ha; till exempel betyder d921970^2 "den andra föräldern till d921970".
Den här syntaxen är bara användbar för sammanslagningsincheckningar som har mer än en förälder – den första föräldern för en sammanslagningsincheckning kommer från grenen du var på när du sammanfogade (ofta master), medan den andra föräldern kommer från grenen som sammanfogades (till exempel topic):
$ git show d921970^
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 14:58:32 2008 -0800
Add some blame and merge stuff
$ git show d921970^2
commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
Author: Paul Hedderly <paul+git@mjr.org>
Date: Wed Dec 10 22:22:03 2008 +0000
Some rdoc changes
Det andra huvudsättet att ange anfäder är ~ (tilde-tecknet).
Det refererar också till den första föräldern, så HEAD~ och HEAD^ är likvärdiga.
Skillnaden blir tydlig när du anger en siffra.
HEAD~2 betyder "den första föräldern till den första föräldern", eller "farföräldern" – den går uppåt bland första föräldrar det antal gånger du anger.
Till exempel, i historiken ovan skulle HEAD~3 bli:
$ git show HEAD~3
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date: Fri Nov 7 13:47:59 2008 -0500
Ignore *.gem
Det kan också skrivas som HEAD~~~, vilket återigen är den första föräldern till den första föräldern till den första föräldern:
$ git show HEAD~~~
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date: Fri Nov 7 13:47:59 2008 -0500
Ignore *.gem
Du kan också kombinera dessa syntaxer – du kan få den andra föräldern till den föregående referensen (förutsatt att det var en sammanslagningsincheckning) genom att använda HEAD~3^2, och så vidare.
Incheckningsintervall
Nu när du kan ange enskilda incheckningar, låt oss se hur du anger intervall av incheckningar. Det är särskilt användbart när du hanterar grenar – om du har många grenar kan du använda intervallspecifikationer för att besvara frågor som "Vilket arbete finns i den här grenen som jag ännu inte har sammanfogat in i min huvudgren?".
Dubbelpunkt
Den vanligaste intervallspecifikationen är dubbelpunktsyntaxen. Den ber i praktiken Git att lösa ett intervall av incheckningar som kan nås från en incheckning men inte från en annan. Anta till exempel att du har en incheckningshistorik som ser ut som Exempelhistoria för intervallurval.
Säg att du vill se vad som finns i din experiment-gren som ännu inte har sammanfogats i din master-gren.
Du kan be Git visa en logg med just de incheckningarna genom master..experiment — det betyder "alla incheckningar som går att nå från experiment men inte från `master`".
För tydlighetens skull i exemplen används bokstäverna från diagrammet i stället för faktisk loggutdata, i den ordning de skulle visas:
$ git log master..experiment
D
C
Om du i stället vill se motsatsen – alla incheckningar i master som inte finns i experiment – kan du vända på grennamnen.
experiment..master visar dig allt i master som inte är nåbart från experiment:
$ git log experiment..master
F
E
Det här är användbart om du vill hålla experiment-grenen uppdaterad och förhandsgranska vad du ska sammanfoga.
En annan vanlig användning av denna syntax är att se vad du är på väg att skicka till ett fjärrkodförråd:
$ git log origin/master..HEAD
Detta kommando visar alla incheckningar i din nuvarande gren som inte finns i master-grenen i ditt fjärrkodförråd origin.
Om du kör git push och din nuvarande gren spårar origin/master är incheckningarna som listas av git log origin/master..HEAD de som kommer att skickas till servern.
Du kan också lämna bort ena sidan av syntaxen för att låta Git anta HEAD.
Till exempel kan du få samma resultat som i föregående exempel genom att skriva git log origin/master.. – Git ersätter HEAD om ena sidan saknas.
Flera punkter
Dubbelpunktsyntaxen är användbar som förkortning, men du kanske vill ange mer än två grenar för att beskriva din revision, till exempel för att se vilka incheckningar som finns i någon av flera grenar men inte i grenen du står på.
Git låter dig göra detta genom att använda antingen tecknet ^ eller --not före varje referens som du inte vill se nåbara incheckningar från.
Därför är följande tre kommandon likvärdiga:
$ git log refA..refB
$ git log ^refA refB
$ git log refB --not refA
Det fina är att du med denna syntax kan ange mer än två referenser i din fråga, vilket du inte kan göra med dubbelpunktsyntaxen.
Om du till exempel vill se alla incheckningar som kan nås från refA eller refB men inte från refC kan du använda någon av dessa:
$ git log refA refB ^refC
$ git log refA refB --not refC
Detta ger ett mycket kraftfullt revisionsfrågesystem som hjälper dig att förstå vad som finns i dina grenar.
Trippelpunkt
Den sista stora intervallsyntaxen är trippelpunkten, som anger alla incheckningar som kan nås av antingen av två referenser men inte av båda.
Gå tillbaka till exempelhistoriken i Exempelhistoria för intervallurval.
Om du vill se vad som finns i master eller experiment men inte i gemensamma referenser kan du köra:
$ git log master...experiment
F
E
D
C
Återigen får du normal log-utdata men ser bara incheckningsinformationen för de fyra incheckningarna, i den traditionella ordningen efter incheckningsdatum.
Ett vanligt växelval med log i det här fallet är --left-right, som visar vilken sida av intervallet varje incheckning ligger på.
Det gör utdata mer användbar:
$ git log --left-right master...experiment
< F
< E
> D
> C
Med de här verktygen kan du mycket enklare tala om för Git vilken incheckning eller vilka incheckningar du vill inspektera.