Referencje w Git
Za pomocą komendy git log 1a410e
możesz również przejrzeć całą historię swojego projektu, ale musisz wiedzieć, że 1a410e
jest ostatnią zmianą (commitem) aby zobaczyć wszystkie modyfikacje. Potrzebujesz pliku w którym będziesz mógł zapisywać wartość SHA-1 pod łatwiejszą nazwą, tak abyś mógł jej używać zamiast sumy SHA-1.
W Gitcie nazywane są one "referencjami" lub krócej "refs"; możesz znaleźć pliki zawierające wartość SHA-1 w katalogu .git/refs
. W obecnym projekcie ten katalog nie zawiera żadnych plików, a jego struktura wygląda tak:
$ find .git/refs
.git/refs
.git/refs/heads
.git/refs/tags
$ find .git/refs -type f
$
Aby stworzyć nową referencję, która pomocna będzie przy zapamiętywaniu który commit jest ostatni, możesz wykonać tę prostą komendę:
$ echo "1a410efbd13591db07496601ebc7a059dd55cfe9" > .git/refs/heads/master
Teraz, możesz używać referencji którą właśnie stworzyłeś zamiast sumy SHA-1 w komendach Gita:
$ git log --pretty=oneline master
1a410efbd13591db07496601ebc7a059dd55cfe9 third commit
cac0cab538b970a37ea1e769cbbde608743bc96d second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
Nie musisz bezpośrednio zmieniać plików referencji. Git udostępnia bezpieczniejsze narzędzie do tego, gdy chcesz zaktualizować referencje wywołaj update-ref
:
$ git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9
Praktycznie tym samym są gałęzie w Git: proste wskazanie lub referencja na najnowszą wprowadzoną zmianę. Aby stworzyć gałąź z poprzedniego commita, wykonaj to:
$ git update-ref refs/heads/test cac0ca
Twoja gałąź będzie zawierała tylko zmiany starsze niż podany commit:
$ git log --pretty=oneline test
cac0cab538b970a37ea1e769cbbde608743bc96d second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
W tej chwili, Twoja baza w Git wygląda podobnie do tej z rysunka 9-4.
Figure 9-4. Obiekty w katalogach Git z uwzględnieniem referencji do gałęzi.
Gdy uruchamiasz komendę taką jak git branch (nazwagałęzi)
, Git po prostu uruchamia komendę update-ref
, w celu dodania sumy SHA-1 ostatniego commita w gałęzi na której się obecnie znajdujesz, do referencji którą chcesz stworzyć.
HEAD
Powstaje pytanie, po uruchomieniu git branch (nazwagałęzi)
, skąd Git wie jaka jest suma SHA-1 ostatniego commita? Odpowiedź to plik HEAD. W tym pliku znajduje się symboliczne dowiązanie do gałęzi w której się obecnie znajdujesz. Poprzez symboliczne dowiązanie, mam na myśli to, że inaczej niż w przypadku normalnego dowiązania, nie zawiera ono sumy SHA-1, ale wskaźnik na inną referencję. Jak zobaczysz na zawartość tego pliku, zazwyczaj zobaczysz coś w stylu:
$ cat .git/HEAD
ref: refs/heads/master
Po uruchomieniu git checkout test
, Git zaktualizuje ten plik, aby zawierał:
$ cat .git/HEAD
ref: refs/heads/test
Gdy uruchomisz git commit
, zostanie stworzony obiekt commit, określając rodzica tego obiektu na podstawie wartość SHA-1 na którą wskazuje HEAD.
Możesz również ręcznie zmodyfikować ten plik, ale bezpieczniej będzie użyć komendy symbilic-ref
. Możesz odczytać wartość która jest w HEAD przy jej pomocy:
$ git symbolic-ref HEAD
refs/heads/master
Możesz również ustawić nową wartość HEAD:
$ git symbolic-ref HEAD refs/heads/test
$ cat .git/HEAD
ref: refs/heads/test
Nie możesz jednak wstawić symbolicznego dowiązania które jest poza katalogiem refs:
$ git symbolic-ref HEAD test
fatal: Refusing to point HEAD outside of refs/
Tagi
Poznałeś już trzy główne obiekty Gita, ale istnieje jeszcze czwarty. Obiekt tag, jest bardzo podobny do obiektu commit - zawiera informacje o osobie, dacie, treści komentarza i wskaźnik. Główną różnicą jest to, że obiekt tag wskazuje na commit, a nie na obiekt tree. Jest podobny do referencji gałęzi, ale nigdy się nie zmienia - zawsze wskazuje na ten sam commit, ale z łatwiejszą nazwą.
Jak opisałem w rozdziale 2, istnieją dwa typy tagów: opisanych i lekkich. Możesz stworzyć lekką etykietę poprzez uruchomienie:
$ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d
Właśnie tym jest lekka etykieta - gałęzią która nigdy się nie zmienia. Opisana etykieta jest jednak bardziej skomplikowana. Gdy tworzysz opisaną etykietę, Git stworzy obiekt tag, a następnie zapisze referencję wskazująca na niego, zamiast na obiekt commit. Możesz to zauważyć, po stworzeniu opisanej etykiety (-a
wskazuje że będzie to opisana etykieta):
$ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'test tag'
Stworzona została następująca wartość SHA-1:
$ cat .git/refs/tags/v1.1
9585191f37f7b0fb9444f35a9bf50de191beadc2
Teraz, uruchom komendę cat-file
na tej wartość SHA-1:
$ git cat-file -p 9585191f37f7b0fb9444f35a9bf50de191beadc2
object 1a410efbd13591db07496601ebc7a059dd55cfe9
type commit
tag v1.1
tagger Scott Chacon <[email protected]> Sat May 23 16:48:58 2009 -0700
test tag
Zauważ, że wpis rozpoczynający się od "object" wskazuje na sumą SHA-1 commitu który zatagowałeś. Zauważ również, że nie musi on wskazywać na commit; możesz stworzyć etykietę dla każdego obiektu w Git. Na przykład, w kodzie źródłowym Gita, opiekun projektu zamieścił publiczny klucz GPG, jako obiekt blob i następnie go otagował. Możesz zobaczyć zawartość tego klucz, po wykonaniu
$ git cat-file blob junio-gpg-pub
w kodzie źródłowym Gita. Repozytorium ze źródłami projektu Linux ma również taki tag - pierwszy tag stworzony z początkowego stanu kodu źródłowego.
Zdalne repozytoria
Trzecim typem referencji który poznasz, są referencje zdalne. Jeżeli dodasz zdalne repozytorium i wypchniesz do niego kod, Git przechowa wartość którą ostatnio wypchnąłeś do niego, dla każdej gałęzi w katalogu refs/remotes
. Na przykład, możesz dodać zdalne repozytorium o nazwie origin
i wypchnąć gałąź master
do niego:
$ git remote add origin [email protected]:schacon/simplegit-progit.git
$ git push origin master
Counting objects: 11, done.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (7/7), 716 bytes, done.
Total 7 (delta 2), reused 4 (delta 1)
To [email protected]:schacon/simplegit-progit.git
a11bef0..ca82a6d master -> master
Następnie możesz zobaczyć w którym miejscu była gałąź master
na zdalnym repozytorium origin
w czasie gdy wysyłałeś zmiany, przez sprawdzenie pliku refs/remotes/origin/master
:
$ cat .git/refs/remotes/origin/master
ca82a6dff817ec66f44342007202690a93763949
Zdalne referencje różnią się od gałęzi (referencji w refs/heads
) głównie tym, że nie mogą być pobrane (przez komendę "checkout"). Git zapisuje jest rodzaj zakładek wskazujących na ostatni znany stan w którym te gałęzi były na serwerze.