Git Internals

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

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *