Niezmienne obiekty
Baza danych gita to mapa której kluczem są hashe SHA-1. Jest przechowywana jako katalogi w .git/objects/
, nazwa katalogu to dwa pierwsze znaki hasha (wewnątrz są wszystkie obiekty których hash tak się zaczyna), obiekty to pliki binarne spakowane zlibem z dołączonym nagłówkiem. Nazwa obiektu to pozostałe 38 znaków skrótu.
Blob
Obiekt zawierający zawartość pliku, nie zawiera jego nazwy, ścieżki ani uprawnień. Dlatego dwa pliki o innych nazwach a tej samej zawartości są zapisywane w gicie jako jeden obiekt. Obiekty zapisane są w formacie typObiektu wielkośćObiektu\0 daneBinarne. Hash jest wyliczany z całego obiektu wraz z tym nagłówkiem.
Składnia commit:ścieżkaDoPliku
umożliwia odwołanie się do bloba.
Tree
Drzewo zawiera nagłówek i wpisy o strukturze:
rodzajeWpisów typObiektu hash nazwaPliku
Rodzaje wpisów w drzewie
040000 – drzewo
100644 – normalny
100755 – uprawnienia do wykonywania
120000 – dowiązanie symboliczne
Umożliwia zapisanie informacji o nazwach i typach plików oraz o strukturze katalogów. Git ignoruje puste foldery.
Składania commit^{tree}
umożliwia odwołanie się do drzewa przypisanego do commita
Commit
commit 226tree 6d3a746eeb961ebb0c908653d3f1097b165de352
parent 9eeb2b181261665d6b32d8d3fd242d82d1369454
author Karol Nowak <poczta@karolnowak.net> 1503008723 +0200
committer Karol Nowak <poczta@karolnowak.net> 1503008723 +0200
Commit zawiera nagłówek, wskaźnik do drzewa i rodzica (lub rodziców dla commitu mergującego), autora i commitującego wraz z timestampem. Następnie po pustej linii jest treść commita. Autor i commitujący to różne osoby jeśli zmiany są przesłane w formie diffa (np mailem) do osoby zarządzającej repozytorium która commituje te zmiany (zarówno wysyłanie diffa mailem jak i aplikowanie go ma w gicie oddzielne komendy).
Tag
Utworzony przez git tag -a
(annotated tag) to oddzielny typ obiektu w przeciwieństwie do lekkiego taga który podobnie jak branch jest tylko wskaźnikiem do commita.
tag 156object 4fd5d510efb8184fb76ad7c7064c8a78083f2c4a
type commit
tag nazwaTaga
tagger Karol Nowak <poczta@karolnowak.net> 1503057924 +0200
Treść taga
Tag zawiera nagłówek, wskaźnik do taggowanego obiektu typ taggowanego obiektu, osobę tworzącą taga i treść. Typem może być dowolny obiekt – można otagować taga.
Zmienne obiekty
Branch
Plik w .git/refs/heads/ o zawartości w postaci hasha commita. Commit to najnowszy commit na tym branchu.
HEAD
Wskaźnik na wskaźnik.
We wcześniejszych wersjach gita HEAD to było dowiązanie symboliczne do pliku opisującego brancha. Ze względu na przenośność teraz wykorzystywane są symbolic-ref które są względną ścieżką do brancha (względną do folderu .git ale nie może wskazywać nic poza folderem /refs).
git symbolic-ref HEAD
wyświetli gdzie wskazuje HEAD
git symbolic-ref HEAD refs/heads/test
zaktualizuje wartość HEADa parametrem
Index
Inaczej staging area lub cache. Umożliwia wybór zmian które mają się znaleźć w następnym commicie.
Working directory
Pliki przechowywane w drzewie aktualnego brancha.
Logs
Pliki wykorzystywane przez reflog, zawierają wszystkie zmiany HEADa.
Paczki i delty
Git wyznacza delty (diffy) między wersjami plików. Ale robi to w innych momentach niż SVN.
Garbage collector
Delty są liczone przez garbage collectora który uruchomi się jeśli ilość obiektów przekroczy 7000 lub ilość paczek przekroczy 50, obie wartości są konfigurowalne. GC może być też uruchomiony ręcznie przez git gc
. GC tworzy dwa rodzaje obiektów paczki i indeksy (idx). Paczki to zbiory obiektów, często różnych wersji tego samego pliku (ale nie tylko). Git rozpoznaje, że obiekty to różne wersje tego samego pliku na podstawie nazwy i zawartości. W paczce znajduje się najnowsza wersja pliku oraz delty do odtworzenia starszych wersji. Indeks zawiera przesunięcia do poszczególnych obiektów.
W folderze .git powstaje plik packed-refs który zawiera informację które referencje trafiły do paczki (z .git/refs).
git verify-pack -v paczka
wyświetla listę wszystkich obiektów wewnątrz paczki, jako argument przyjmuje paczkę lub indeks.
Komunikacja z serwerem
Delty są liczone także podczas komunikacji z serwerem (za pomocą git smart protocol).
Upload
Po stronie serwera proces receive-pack przesyła listę wszystkich obiektów które posiada procesowi klienta send-pack. Send-pack sprawdza jakie obiekty są w bazie. Tworzy paczkę zawierającą obiekty których nie ma na serwerze i ją przesyła.
Download
Analogicznie do powyższego, nazwy procesów to fetch-pack i upload-pack.
Inne przydatne komendy
git hash-object plik
zwraca hasha podanego pliku
-w
zapisuje ten obiekt w bazie gita
--stdin
pobiera obiekt jako tekst ze standardowego wejścia zamiast z pliku
git cat-file
bardziej szczegółowe git show
-t
wyświetli typ obiektu
-p
rozpozna typ obiektu i odpowiednio go wyświetli
-s
zwróci wielkość pliku
git ls-tree
jeśli argumentem jest commit i zawiera drzewo to je wyświetla, cat-file
wyświetla commit (ale jeśli argumentem jest drzewo wtedy je wyświetli)
-r
wyświetla drzewa rekurencyjnie
cat plik | zlib-flate -uncompress
pozwala podejrzeć pełną zawartość obiektu (z nagłówkiem)
git fsck
sprawdza integralność bazy danych, wyświetla informację o obiektach na które nic nie wskazuje
git prune
umożliwia usunięcie takich obiektów
-n
pokaże co będzie usunięte
git count-objects
wyświetli informacje o obiektach w bazie
-vH
wyświetli więcej szczegółów i zmieni jednostki
git rev-list
log który pokazuje tylko hashe commitów
Źródła:
„Pro Git” 2nd ed. Scott Chacon, Ben Straub
„Git Internals”Scott Chacon