Tutorial Gita
Jacek Bzdak
1
Spis tre´sci
2
4
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
. . . . . . . . . . . . . . . .
4
5
. . . . . . . . . . . . . . . . . . . . . . . . . . .
5
. . . . . . . . . . . . . . . . . . .
6
. . . . . . . . . . . . . . . . . . . . . . . . . .
7
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
. . . . . . . . . . . . . . . . . . . . . . . .
7
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
Scenariusz: praca z branchachami
. . . . . . . . . . . . .
8
. . . . . . . . . . . . . . . . . . . . . .
8
Scenariusz: Wycofanie nieskomitowanych zmian
.
9
Scenariusz: Wycofanie skomitowanych zmian 1
. .
9
Scenariusz: Wycofanie skomitowanych zmian 2
. .
9
O gorliwo´sci gita i git-stash
. . . . . . . . . . . . . . . .
9
2.3 Praca z wieloma repozytoriami
. . . . . . . . . . . . . . . .
11
. . . . . . . . . . . . . . . . . . . . .
11
. . . . . . . . . . . . . . . . . . .
11
. . . . . . . . . . . . . . . . . . . . . . .
12
Pobieranie danych z repozytorium
. . . . . . . . . . . . . .
12
Wysyłanie danych do repozytoriów
. . . . . . . . . . . . .
12
Scenariusz: praca ze zdalnym repozyrorium
. . . . . . . .
12
Scenariusz: upublicznienie repozytorium po ssh
. . . . .
13
Scenariusz: pobranie zawarto´sci repozytorium
. . . . . .
13
2.4 Zaawansowana praca z branchami
. . . . . . . . . . . . .
13
. . . . . . . . . . . . . . . . . . . . . . . .
13
. . . . . . . . . . . . . . . . . . . . .
14
O nieumieszczanu plików IDE w repozytorium
. . . . . .
15
. . . . . . . . . . . . . . . . . . . . . .
15
2.5 Zaawansowane u ˙zycia gita
. . . . . . . . . . . . . . . . . .
15
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
. . . . . . . . . . . . . . . . . . . . . . .
16
. . . . . . . . . . . . . . . . . . . . . . . . . . .
16
2
Spis tre´sci
3
. . . . . . . . . . . . . . . . . . . . . . . .
17
. . . . . . . . . . . . . . . . . . . .
17
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
. . . . . . . . . . . . . . . . . . . .
18
. . . . . . . . . . . . . . . . . . . . . . . .
18
. . . . . . . . . . . . . . . . . . . . .
18
. . . . . . . . . . . . . . . . . . . . . . . .
18
. . .
18
Rozdział 1
Instalacja gita
1.1
Linux
Prosta piłka — nale ˙zy u ˙zy´c swojego managera pakietów.
Dla ubuntu/debiana nale ˙zy wpisa´c:
sudo apt-get install git-core
Dodatkowo mo ˙zna zainstalowa´c przydatne narz ˛edzia
program do mergeowania Na przykład meld, kdiff3. Te obsługiwane
przez gita natywnie s ˛
a wypisane w manie dla git-config w opisie
klucza merge.tool.
edytor tekstu do edycji messagey commiów. Ja nie lubie vi u ˙zywam
nano.
1.2
Windows
Tu ju ˙z trzeba cudowa´c. Oficjalny port gita dla windows jest w cygwinie.
. . A jaki cygwin jest wiadomo ;)
Tak czy inaczej mamy takie opcje:
Cygwin
MSGit Natywna implementacja. Pono´c szybsza ni´z cygwinowa. Nie wiem,
nie bawiłem si ˛e. Mo ˙zna j ˛
a pora´c ze strony
http://code.google.com/p/msysgit/
Nie wiem nie bawiłem si ˛e.
Instalacja dla Cygwina
Najpierw trzeba ´sci ˛
agn ˛
a´c instalator cygwina, nast ˛epnie nale ˙zy ´sci ˛
a-
gn ˛
a´c pakiety dla gita i openssh (je´sli potrzebne jest wsparcie gita wspar-
cia dla ssh).
Je´sli potrzebujesz korzysta´c z ssh-agent, trzeba jeszcze w pliku
$CYGWIN_FOLDER$\bin\cygwin.bat
zamieni´c ostatni ˛
a lini ˛e na ssh-agent
bash --login -i
.
4
Rozdział 2
Praca z GITem
Filozofia
1
gita
2
jest zasadniczo ró ˙zna od filozofii klasycznych systemow
wersjonowania. Repozytorium gita to po prostu dowolny katalog w któ-
rym znajduje si ˛e podkatalog o nazwie .git zawieraj ˛
acy dane wersjo-
nowania. Repozytorium po stronie serwera niczym nie ró ˙zni si ˛e od re-
pozytorium kilenta — albo inaczej — w gicie nie istniej ˛
a w ogóle poj ˛ecia
serwera i kilenta, repozytoria s ˛
a równoprawne.
Zawarto´s´c katalogu repozytorium (poza katalogiem .git) to tak
zwana kopia robocza
3
.
2.1
Słownik gita
Wówczas Budda rzekł: <<Bracia istniej ˛
a tylko
działania oraz ich skutki, ale nie istnieje osoba,
która działa (...) Nie istnieje ˙zadne indywiduum,
jest tylko umownma nazwa nadana zbiorowi
elementów>>
Nizeznany
Krótkie wyja´snienie poj ˛e´c gita
repozytorium Struktura danych zawieraj ˛
aca histori ˛e projektu (zawar-
to´s´c katalogu .git).
kopia robocza Bierz ˛
aca wersja projektu na której pracuje programi-
sta.
nazwa Nazwa obiektu Gita to 20 cyfrowy skrót SHA-1 danego obiektu.
obiekt Co´s co jest w repozytorium gita. S ˛
a nastepuj ˛
ace rodzaje obiek-
tów gita: blob
4
, drzewa, komity, tagi.
1
„Filozofia to legalne dragi” — m ˛
adro´s´c ludowa
2
I innych tzw. rozproszonych systenów wersjonowania
3
(z ang.)
working copy
4
z ang. binary large object
5
ROZDZIAŁ 2. PRACA Z GITEM
6
blob Reprezentuje plik. Najgłupszy obieky gita. Jego nazwa jest cał-
kowicie determiniowana przez jego zawarto´s´c, czyli dwa pliki o
ró ˙znych nazwach i poło ˙zeniach maj ˛
a jedn ˛
a i dziel ˛
a tego samego
bloba.
drzewo Reprezentuje katalog. Zawiera odniesienia do innych drzew i
do blobów. Bloby reprezentuj ˛
a pliki w danym katalogu, drzewa
— podkatalogi. Drzewo przechowuje te ˙z nazwy (nie chodzi mi tu
o nazwy gita, ale o filenames) plików i katalogów które zawiera.
Nazwa drzewa zale ˙zy tylko od jego zawarto´sci.
commit Czyli stan projektu w danej chwili czasu. Zawiera odniesienie
do drzewa które reprezentuje główny katalog projektu w chwili
komitowania i komitu rodzica. Zawiera te ˙z komentarz, osob ˛e kom-
tuj ˛
ac ˛
a i autora zmian
5
. Komit nie posiadaj ˛
acy rodzica, to tak
zwany root commit który reprezentuje inicjaln ˛
a wersj ˛e projektu.
Commit, który reprezentuje ł ˛
aczenie branchy, mo ˙ze mie´c wi ˛ecej
ni ˙z jednego rodzica.
tag Czyli zrozumiała dla człowieka nazwa jakiego´s obiektu. Zawiera
informacje o osobie które ów obiekt otagowała i komentarz. Mo ˙ze
zawiera´c cyfrowy podpis danego tagu.
index Plik b ˛ed ˛
acy po´srednikiem mi ˛edzy kopi ˛
a robocz ˛
a a repozytorium.
Podczas komitowania skomitowana nie b ˛edzie cała zawarto´s´c ko-
pii roboczej, a tylko zawarto´s´c indexu.
HEAD wska´znik na bierz ˛
acego brancha
2.2
Proste zastosowania gita
Czyli jak stosowa´c gita na lokalnym komputerze.
Tworzenie repozytorium
By utworzy´c repozytorium w bierz ˛
acym katalogu nale ˙zy wykona´c po-
lecenie:
git-init
Dodawanie plików do indexu
Podczas komitowania do repozytorium trafiaj ˛
a tylko pliki znajduj ˛
ace
si ˛e w indeksie. By doda´c plik do indeksu nale ˙zy wykona´c polecenie:
git-add lista_plików
Poniewa ˙z git-add przyjmuje list ˛e plików mo ˙zna przy nim u ˙zywa´c
znaków wieloznacznych np:
git-add *tex
5
W Gicie który powtał na potrzeby j ˛
adra linuxa mog ˛
a to by´c dwie ró ˙zne osoby —
jedna osoba poprawia bł ˛
ad, kto inny ma prawo do komitowania do repozytorium j ˛
adra.
ROZDZIAŁ 2. PRACA Z GITEM
7
Mo ˙zna równie ˙z dodawa´c drzewa katalogów, na przykład polecenie:
git-add .
Doda cały bierz ˛
acy katalog.
Komitowanie
By skomitowa´c dodane pliki nale ˙zy wykona´c nast ˛epuj ˛
ace polecenie:
git-commit [-a] [-m tre´
s´
c wiadomo´
sci]
Wyja´snienie parametrów:
-a
Bez tego parametru git skomituje tylko pliki które s ˛
a w indeksie –
czyli te o zmianach w których został poinformowany poleceniem
git-add
. Z tym parametrem git automatycznie doda wszystkie
zmodyfikowane lub usuniete pliki o które ju ˙z s ˛
a w indeksie, lecz
zignoruje wszystkie nowe pliki.
-m
Komentarz komitu. Jest obowi ˛
azkowy, je´sli nie jest on podany git
otworzy w konsoli okno edytora w którym mo ˙zna go napisa´c. O
tym jak wybra´c odpalany przez gita edytor w
na stronie
Branche
By stworzy´c brancha nale ˙zy wkona´c polecenie:
git-branch nazwa_brancha punkt_w_historii
nazwa_brancha Pownna by´c zrozumiała dla człowieka, nie mo ˙ze za-
wiera´c spacji. Domy´slnie git pracuje w branchu master.
punkt_w_historii Czyli do czego ma si ˛e dany branch odnosi´c. Je´sli
tego parametru nie podamy branch utworzy si ˛e wskazuj ˛
ac na
bierz ˛
ace poło ˙zenie.
Uwaga! git-branch tylko tworzy brancha - nie zaczynamy w nim pra-
cowa´c.
Checkoutowanie
Polecenie git-checkout przenosi do kopii roboczej jaki´s punkt w hi-
storii.
git-checkout punkt_w_historii
Merge
Czyli ł ˛
aczenie branchy. Do ł ˛
aczenia branchy słu ˙zy polecenie:
git-merge nazwa_brancha
Polecenie to przenosi zmiany z brancha nazwa_brancha do bierz ˛
a-
cego brancha.
ROZDZIAŁ 2. PRACA Z GITEM
8
Scenariusz: praca z branchachami
Załó ˙zmy ˙ze zaczynamy w branchu master, który ma zawiera´c gotowy,
przetestowany kod. Chcemy dokona´c jakiej´s zmiany w kodzie, ale nie
chcemy by byla ona w tym branchu, puki jej nie przetestujemy. Mo ˙zna
oczywi´scie zmian nie umieszcza´c w repozytorium póki nie b ˛ed ˛
a one
gotowe, ale przecie ˙z po to jest repozytorium, ˙zeby w nim trzmya´c kod.
Tworzymy wi ˛ec brancha work w którym b ˛ed ˛
a zmiany, wprowadzamy
w nim zmiany, testujemy je, a nastepnie merd ˙zujemy do rbancha master.
Musimy wi ˛ec wykona´c nastepuj ˛
ace polecenia.
Najpierw tworzymy brancha work.
git-branch work
Mo ˙zemy sprawdzi´c czy rzeczywi´scie go utworzyli´smy wywołuj ˛
ac ko-
mend ˛e git-branch bez argumentów która po prostu wy´swietla wszyst-
kie branche.
$ git-branch
* master
work
Gwiazdk ˛
a zaznaczono bierz ˛
acy branch.
Teraz przechodzimy do brancha work.
git-checkout work
Dokonujemy zmian i komitujemy je.
git-commit -a
Po skomitowaniu zmian checkoutujemy brancha master. Musimy
to zrobi´c gdy ˙z git-merge działa w ten sposób ˙ze do bierz ˛
acego brancha
mergeuje inny branch.
git-checkout master
Wykonujemy mergea
git-merge work
Teraz mo ˙zemy albo przenie´s´c si ˛e do brancha work i dalej pracowa´c
albo np skasowa´c brancha work.
Wycofywanie zmian
Do usuni ˛ecia nieskomitowanych zmian słu ˙zy polecenie:
git-reset --tryb commit
Tryby s ˛
a trzy:
soft Nie resetuje indexu, ani kopii roboczej. Zmienia tylko wska´znik
heada.
mixed Resetuje indeks, nie dotyka kopii roboczej. Po wywołaniu tego
polecenia ˙zaden z plików nie b ˛edzie oznaczony jako gotowy do
skomitowania.
ROZDZIAŁ 2. PRACA Z GITEM
9
hard Resetuje indeks i kopi ˛e robocz ˛
a.
Parametr commit to commit na który b ˛edzie wskazywa´c HEAD po wy-
wołaniu tego polecenia, je´sli nie podamy tego paramtetru HEAD nie
b ˛edzie zmieniony.
Scenariusz: Wycofanie nieskomitowanych zmian
Załó ˙zmy ˙ze robi ˛e refractoring kodu, przy czym decyduje ˙ze jaka´s zmiana
jednak jest nietrafiona. ˙Zeby wycowa´c wszystkie zmiany musz ˛e napi-
sa´c:
git-reset --hard
Scenariusz: Wycofanie skomitowanych zmian 1
Podobnie jak ostatnio, z tym ˙ze zmiany zostały skomitowane. Ci ˛
agle
mog ˛e je wycofa´c poleceniem git-reset, jednak jest to potencjalnie do´s´c
gro´zne. Najpierw jednak polecenie:
git-reset --hard HEAD^
HEAD^
— znaczy rodzic HEAD. Wi ˛ecej o nazwach gita w sekcji
na stronie
Niebezpiecze ´
nstwo jest takie ˙ze je´sli gdy któ´s ów commit wychec-
koutuje i b ˛edzie nad nim dalej pracowa´c zaczniecie mie´c niespójn ˛
a hi-
stori ˛e, a wtedy git zgłupieje, ziemia si ˛e otworzy i wyjdzie z niej szatan
;).
Scenariusz: Wycofanie skomitowanych zmian 2
Do wycofania opublikowanego commitu słu ˙zy polecenie git-revert.
Wykonuje ono commit cofaj ˛
acy zmiany.
Ró ˙znica mi ˛edzy git-reset a git-revert jest taka ˙ze je´sli u ˙zyjesz
pierwszego to w historii nie pozostanie ´sladu po złym commicie.
O gorliwo´sci gita i git-stash
Git nigdy nie nadpisze zmian nieznajduj ˛
acych si ˛e w repozytorium —
czyli nigdy nie wykona nieodwracalnych zmian. Co´s takiego mo ˙ze si ˛e
zdarzy´c w kilku przypadkach. Przykładowo mamy w kopii roboczej plik
baz.txt, który jest poza repozytorium (nie był dodany), a w branchu B
(czyli automatycznie w repozytorium) jest plik o tej samej nazwie z inn ˛
a
zawarto´sci ˛
a.
Mo ˙zna to zobaczy´c na własne oczy:
jb@lucy:~/foo$ git-init
Initialized empty Git repository in /home/jb/foo/.git/
jb@lucy:~/foo$ echo "xxx" > foo.txt
jb@lucy:~/foo$ git-add foo.txt
jb@lucy:~/foo$ git-commit
Created initial commit c073b2e: sa
1 files changed, 1 insertions(+), 0 deletions(-)
ROZDZIAŁ 2. PRACA Z GITEM
10
create mode 100644 foo.txt
jb@lucy:~/foo$ git-branch work
jb@lucy:~/foo$ git-checkout work
Switched to branch "work"
jb@lucy:~/foo$ echo "zzz" > baz.txt
jb@lucy:~/foo$ git-add baz.txt
jb@lucy:~/foo$ git-commit
Created commit 44e60cc: baz
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 baz.txt
jb@lucy:~/foo$ git-checkout master
Switched to branch "master"
jb@lucy:~/foo$ echo "yyy" > baz.txt
jb@lucy:~/foo$ git-checkout work
error: Untracked working tree file ’baz.txt’ would be
overwritten by merge.
jb@lucy:~/foo$ git-merge work
Updating c073b2e..44e60cc
error: Untracked working tree file ’baz.txt’ would be
overwritten by merge.
By problem rozwi ˛
aza´c nale ˙zy plik baz.txt doda´c do repozytorium:
jb@lucy:~/foo$ git-add baz.txt
jb@lucy:~/foo$ git-commit
Created commit df1cf44: foo
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 baz.txt
jb@lucy:~/foo$ git-checkout work
Switched to branch "work"
jb@lucy:~/foo$ git-checkout master
Switched to branch "master"
jb@lucy:~/foo$ git-merge work
Auto-merged baz.txt
CONFLICT (add/add): Merge conflict in baz.txt
Automatic merge failed; fix conflicts and then commit
the result.
jb@lucy:~/foo$ git-mergetool
Merging the files: baz.txt
jb@lucy:~/foo$ git-commit
Created commit 5fa91f9: Merge branch ’work’
Analogicznie Git si ˛e zachowa je´sli spróbujemy wykona´c mergea/com-
mita przy nieskomitowanych zmianach w kopii roboczej.
jb@lucy:~/foo$ git-checkout work
Switched to branch "work"
jb@lucy:~/foo$ echo "jjj" > foo.txt
jb@lucy:~/foo$ git-commit -a
Created commit b04a588: das
1 files changed, 1 insertions(+), 1 deletions(-)
jb@lucy:~/foo$ git-checkout master
ROZDZIAŁ 2. PRACA Z GITEM
11
Switched to branch "master"
jb@lucy:~/foo$ echo "ppp" > foo.txt
jb@lucy:~/foo$ git-merge work
foo.txt: needs update
error: Entry ’foo.txt’ not uptodate. Cannot merge.
fatal: merging of trees
62c4cf4f82d52932a4d2148efa7e80f1807ac6aa and
9923cc607172ca543cb5115f0ce25178a033651a failed
Merge with strategy recursive failed.
Na pierwszy rzut oka jest to upierdliwe, lecz z drugiej strony: chroni
przed nieodwracalnym usuni ˛eciem zmian.
2.3
Praca z wieloma repozytoriami
Repozytoria nazwane
Git posiada mechanizmrepozytoriów nazwanych, które cho´c to konieczne
do pracy ze zdalnymi repozytoriami bardzo j ˛
a ułatwia.
By utworzy´c nada´c jakiemu´s zdalnemu repozytroum nazw ˛e nale ˙zy
wykona´c polecenie:
git-remote add nazwa url
nazwa to nazwa zdalnego repozytorium. Nie mo ˙ze zawiera´c spacji.
url to url do danego repozytrorium. Przykł ˛
adowo mo ˙ze by´c to Urlem
mo ˙ze by´c na przykład: ssh://skimbleshanks.ath.cx/var/git/diesIrae
6
,
urlem mo ˙ze te ˙z by´c ´scie ˙zka lokalnego systemu plików.
Kopiowanie repozytoriów
S ˛
a dwie metody na kopiowanie repozytoriów.
Pierwsz ˛
a jest Pierwsz ˛
a jest polecenie git-clone. Pozwala ono sko-
piowa´c zawarto´s´c całego repozytorium.
git-clone url
Po wykonaniu tego polecenia z podanym urlem git zrobi nast ˛epu-
j ˛
ace rzeczy:
1. utworzy w bierz ˛
acym katalogu katalog diesIrae
2. zainicjalizuje w nim repozytorium
6
Skimbleshanks is a cat character in T. S. Eliot’s book of poetry Old Possum’s Book
of Practical Cats and in Andrew Lloyd Webber’s musical Cats:
Saying ‘Skimble where is Skimble has he gone to hunt the thimble?
We must find him or the train can’t start.’
All the guards and all the porters and the stationmaster’s daughters
They are searching high and low,
Saying ‘Skimble where is Skimble for unless he’s very nimble
Then the Night Mail just can’t go.’
´
Zródło:
ROZDZIAŁ 2. PRACA Z GITEM
12
3. ´sci ˛
agnie zawarto´s´c z zadanego repozytorium
4. W repozytorium na tym komputerze utworzy odniesienie o nazwie
origin
wskazuj ˛
ace na danego urla.
Nagie repozytoria
S ˛
a to repozytoria nie maj ˛
ace kopii roboczej. Maj ˛
a bardzo ograniczon ˛
a
funkcjonalno´s´c — nie mo ˙zna na nich wykonywa´c wielu operacji (w
zasadzie wszystkich poza komitowaniem kodu i pobieraniem zmian).
Nadaj ˛
a si ˛e natomiast całkiem nie´zle rpeopzytoria w serwerze. Twozy
si ˛e je poleceniem:
git-init --bare
Pobieranie danych z repozytorium
By pobra´c zawarto´sc repozytorium nale ˙zy wykona´c polecenie:
git-fetch nazwa_repozytorium
Spowoduje to pobranie wszystkich branchy z danego repozytorium i
zapisanie ich jako branchy o nazwach: nazwa_repozytorium/nazwa_brancha
Przykładowo, w repozytorium skimbleshanks znajduje si ˛e branch
master wi ˛ec po wykonaniu polecenia:
git-fetch skimbleshanks
powstanie branch o nazwie skimbleshanks/master.
Wysyłanie danych do repozytoriów
By wysła´c zmienione pliki do repozytorium nale ˙zy wykona´c:
git-push nazwa_repozytorium wysylany_branch
Polecenie git-push zadziała poprawnie tylko je´sli merge zmian do
brancha na zdalnym repozytrium b ˛edzie typu fast forward, czyli nikt
inny w mi ˛edzyczasie nie zmieni zalnego brancha. Je´sli tak nie b ˛edzie
git-push zwróci bł ˛
ad.
Scenariusz: praca ze zdalnym repozyrorium
Zakładam ˙ze pracuje na repozytorium skimbleshanks, w branchu
unstable
.
Rano ´sci ˛
agam ewentualne zmiany z repozytorium:
git-fetch skimbleshanks unstable
Podczas całego dnia wykonuje zmiany w kodzie. Chc ˛e teraz moje
zmiany wysła´c do zdalnego repozytorium.
Polecenie git-push zadziała poprawnie tylko je´sli merge zmian do
brancha na zdalnym repozytrium b ˛edzie typu fast forward (dokłanie o
typach merd ˙zy w
na nast ˛epnej stronie), czyli nasz branch b ˛edzie
zawierał w swojej hisorii HEADa zdalnego brancha. B ˛edzie tak je´sli
ROZDZIAŁ 2. PRACA Z GITEM
13
albo nikt nie komitował w mi ˛edzyczasie do zdalnego brancha, albo my
w naszym repozytorium zmergeowali´smy nowe zdalne zmiany.
Załó ˙zmy ˙ze w mi ˛edzyczasie kto´s skomitował co´s do tego repozyto-
rium. Musimy zatem nowe zmiany pobra´c raz jeszcze:
git-fetch skimbleshanks unstable
Teraz owe zmiany mergeujemy:
git-merge skimbleshanks/unstable
git-mergetool
Po mergeowaniu mo ˙zna ju ˙z wysła´c zmiany:
git-push skimbleshanks unstable
Scenariusz: upublicznienie repozytorium po ssh
Powiedzmy ˙ze mam repozytorium na moim lokalnym komputerze, re-
pozytorium zawiera program nad którym mój kolega Adam chce pra-
cowa´c. Mo ˙ze on bezpo´srednio pobiera´c zmiany z mojego repozytorium
(o ma dost ˛ep), ale mo ˙zemy te ˙z ustawi´c repozytorium na zdalnym ser-
werze i obaj do niego komiowa´c, rozwi ˛
azanie to jest lepsze o tyle o ile
lepiej si ˛e skaluje.
Powiedzmy ˙ze serwer nazywa si ˛e skimbleshanks.
Najpierw na zdalnym komputerze tworze nagie repozytorium (ma to
sens poniewa ˙z nikt nie b ˛edzie na tym repozytorium pracowa´c bezpo-
´srednio).
jb@skimbleshanks$ git-init --bare
Nast ˛epnie, u siebie, tworze repozytorium nazwane:
jb@lucy$ git-remote add skimbleshanks
ssh://skimbleshanks.ath.cx/var/git/diesIrae
Potem przesyłam do repozytorium na skimbleshanks zawarto´s´c mo-
jego repozytorium. Wykonuje u siebie polecenie:
jb@lucy$ git-push --all skimbleshanks
Scenariusz: pobranie zawarto´sci repozytorium
Teraz Adam chce pobra´c zawarto´s´c tego repozytorium. Wykonuje wi ˛ec
polecenie:
git clone ssh://skimbleshanks.ath.cx/var/git/diesIrae
2.4
Zaawansowana praca z branchami
Rodzaje mergeów
S ˛
a trzy roadzaje mergeów:
ROZDZIAŁ 2. PRACA Z GITEM
14
Rysunek 2.1: Ilustracja mergea already up to date.
Rysunek 2.2: Ilustracja fast forward merge
Rysunek 2.3: Ilustracja mergea
already up to date Je´sli próbujemy zmergeowa´c commita który ju ˙z
jest cz ˛e´sci ˛
a historii HEADa. W tym wypadku merge nie wykonuje
˙zadnej czynno´sci.
fast_forward Odwrotnie: HEAD jest cz ˛e´sci ˛
a historii mergeowanego com-
mita. W tym przypadku nie jest tworzony komit mergeuj ˛
acy (bo i
nie ma ˙zadnych nowych zmian w repozytorium), po prostu HEAD
jest updejtowany tak ˙ze wskazuje na komit merd ˙zowany.
prawdziwy_merge Nie zachodzi ˙zadna z powy ˙zszych alternatyw. Trzeba
mergeowa´c r ˛ecznie i (opcjonalnie) rozwi ˛
azywa´c konflikty.
Obrazki powinny rozja´sni´c sytuacj ˛e, opisane merd ˙ze s ˛
a na obrazkach.
Kropki reprezentuj ˛
a komity. Je´ste´smy w pukcie zaznaczonym ˙zółt ˛
a
kropk ˛
a i mergeujemy kropk ˛e niebiesk ˛
a.
Metody mergeowania
Je´sli w merd ˙zu b ˛ed ˛
a konflikty (ten sam plik wyedytowany w obu gał ˛e-
ziach) to stan ˛
a si ˛e nast ˛epuj ˛
ace rzeczy:
• Git przejdzie w specjalny stan który zabrania wykonywa´c komity
puki merge nie b ˛edzie wykonany
• Do plików z konfliktami zosan ˛
a wyplute conflict markery, które
wygl ˛
adaj ˛
a mniej wi ˛ecej tak:
ROZDZIAŁ 2. PRACA Z GITEM
15
<<<<<<< HEAD:file.txt
Hello world
=======
Goodbye
>>>>>>>
77976da35a11db4580b80ae27e8d65caf5208086:file.txt
Teraz pora na git-mergetool jest to narz ˛edzie pozwalaj ˛
ace na roz-
s ˛
adzenie konfliktów.
O nieumieszczanu plików IDE w repozytorium
Taka krótka sprawa. Nieumieszczanie plików generowanych przez IDE
w repozytorium jest dobrym pomysłem w ogóle. Jednak przy u ˙zywaniu
GITa umieszczanie tych plików ma dodatkowe wady szczególnie je´sli
u ˙zywamy branchy.
Przy mergeowaniu branchów cz ˛esto w tych plikach b ˛ed ˛
a konflikty,
co wi ˛ecej podczas rozwi ˛
azywania takiego mergea mo ˙ze si ˛e okaza´c ˙ze
przestanie działa´c. Git wypluje do plików konfiguracyjnych markery
konfliktów, przez co IDE mo ˙ze ich nie umie´c odczyta´c! Brrr.
No i je´sli si ˛e oka ˙ze ˙ze dodamy plik IDE w trakcie pisania projektu
mo ˙ze si ˛e okaza´c ˙ze merge nie wychodz ˛
a w ogóle — mamy tak ˛
a sytuacj ˛e:
w branchu work dodajemy do repozytorium jaki´s plik IDE, który przy
okazji jest modyfikowany przez owo IDE, i od tej pory merd ˙z brancha
master
i work b ˛edzie wypluwa´c bł ˛
ad (patrz.
jb@lucy:~/foo$ git-merge work
foo.txt: needs update
error: Entry ’.classpath’ not uptodate. Cannot merge.
Kasowanie branchy
Branche mo ˙zna te ˙z kasowa´c.
git-brach -d nazwa_brancha
Polecenie to ze switchem -d ma wbudowane zabezpieczenie — wy-
kona si ˛e tylko je´sli ten branch nazwa_brancha jest ju ˙z wmergeowany
w HEADa.
Je´sli chcemy skasowa´c bracha bez tego sprawdzenia, bo na przy-
kład zawiera on kod którego nie chcemy mergeowa´c nale ˙zy u ˙zy´c para-
metru -D:
git-brach -D nazwa_brancha
2.5
Zaawansowane u ˙zycia gita
Gitignore
Nie wszystko powinno by´c w repozytorium. Je´sli jednak mamy grupy
plików których w repozytorium nie chcemy polecenie git-add z argu-
mentem . zaczyna by´c bezu ˙zyteczne.
ROZDZIAŁ 2. PRACA Z GITEM
16
Mo ˙zemy zatem nakaza´c Gitowi ignorowanie pewnych wzorców nazw
plików. Zainteresowanych odsyłam do
man gitignore
Znaki ko ´
nca linii
Znaki ko ´
nca linii s ˛
a zmor ˛
a je´sli nad programem w jednym repozyto-
rium pracuj ˛
a u ˙zytkownicy *nixów i windowsów.
Git jednak jest w stanie sobie z tym poradzic (z pewnymi ale). Je´sli
ustawimy w konfiguracji klucz core.autoclf na warto´s´c true to git
przy zapisywaniu b ˛edzie podmieniał sekwencj ˛e CRLF na samo LF, a
przy odczycie na odwrót. Warto od razu ustawi´c opcj ˛e core.safeclf,
która pilnuje ˙ze konwertowane s ˛
a tylko pliki dla których konwersja
jest odwracalna.
Zasadniczym problemem z tym mechanizmem jest to ˙ze git mo ˙ze
tak potraktowa´c pliki binarne (generalnie stara si ˛e je wykrywa´c i nawet
mu to wychodzi — jednak mo ˙zliwo´s´c jest ˙ze si ˛e pomyli). Git w obiek-
tach blob nie pamieta nazw plików (wszak jeden blob mo ˙ze mie´c kilka
nazw w ró ˙znych momentach historii), wi ˛ec wykrywanie binarno´sci pli-
ków musi działa´c maj ˛
ac tylko jego zawarto´s´c. Opcja core.safeclf
pilnuje ˙ze nawet je´sli plik jest jest przez gita uszkadzany zmiana jest
odwracalna (potem s ˛
a jakie´s mechanizmy oznaczania plików jako pli-
ków binarnych)
7
.
git-config
Narz ˛edzie pozwalaj ˛
ace konfigurowa´c gita.
Konfiguracja edytora
W
na stronie
dowiedzieli´smy si ˛e ˙ze
je´sli poleceniu git-commit nie poda´c komentarza do komita git odpali
edytor. Poniewa ˙z ka ˙zdy ma swój ulubiony edytor mo ˙zna skonfigurowa´c
polecenie ów edytor wł ˛
acz ˛
acy. Słu ˙zy do tego klucz w konfiguracji o
nazwie: core.editor. Na przykład:
git-config --global core.editor emacs
.
Opcje konfiguracji s ˛
a dobrze udokumentowane w manie
man git-config
Znaki ko ´
nca linii
Do zarz ˛
adzania traktowaniem znaków ko ´
nca
linii słu ˙z ˛
a klucze: core.autoclf i core.safeclf. Patrz akapit
7
Dla mnie cała ten wywód to wy ˙zsza magia i jest on mało interesujacy — w moich
repzoytoriach nie ma plików binarnych (poza wyj ˛
atkami w stylu: wrappery .exe ktore
odpalaj ˛
a moje programy javy, które to wyj ˛
atki i tak da si ˛e łatwo odtworzy´c). Zale ˙zno-
´sciami zajmuje si ˛e maven i ich nie ma w repozytorium.
ROZDZIAŁ 2. PRACA Z GITEM
17
Punkt w historii
Historia gita sklada si ˛e z grafu komitów, historia brancha to linia co-
mitów. Ka ˙zdy punkt historii jest dost ˛epny po nazwie komitu. Nazwy
gita s ˛
a raczej niepor ˛eczne — wszak to 20 cyfrowe hasze SHA-1. Za-
miast całeho SHA-1 mo ˙zna poda´c jego pocz ˛
atek — o ile pocz ˛
atek jest
unikalny w repozytorium. Tak wi ˛ec zamigit-resetast
git-checkout 980e3ccdaac54a0d4de358f3fe5d718027d96aae
Mo ˙zna napisa´c:
git-checkout 980e3cc
Jest te ˙z kilka innych mo ˙zliwo´sci:
nazwa barancha Punktem w historii jest te ˙z nazwa brancha — wska-
zuje on na naj´swie ˙zszy commit w branchu.
nazwa tagu Tag to de facto commit.
HEAD Czyli naj´swie ˙zszy comit w aktualnym branchu.
Rodzice Mo ˙zna odnie´s´c si ˛e te ˙z do rodziców danego commita. HEAD^ to
rodzic HEADa. Mo ˙zna te ˙z zapyta´c o dalszych rodziców horzystaj ˛
ac
z HEAD@{n}, gdzie n to poszukiwane pokolenie.
Urle które obsługuje git
Git obsługuje ró ˙zne i ró ˙zniaste rodzaje urli:
lokalne pliki Podajemy po prostu absolutn ˛
a ´scie ˙zk ˛e do danego kata-
logu.
git-clone /var/git/diesIrae
ssh Przykłady były
http Cho´c ustawienie repozytorium HTTP gita nie jest bardzo łatwe
8
,
to mo ˙zna łatwo pobiera´c repozytorium gita za pomoc ˛
a tego pro-
tokołu.
http://foo/git/diesIrae
Wszystkie mo ˙zliwo´sci urla s ˛
a opisane w manie dla git-clone.
8
Nie jest te ˙z jako´s trudne ;) po prostu si ˛e na tym nie znam totalnie.
ROZDZIAŁ 2. PRACA Z GITEM
18
Stashing
Hardlinki a git-clone
Czytanie historii
Przepisywanie historii
git-rebase
Scenariusz: Wyci ˛
agni ˛ece podmodułu z kodu.
Mam projekt który stanowi gui dla takiego sprz ˛etu spektrometrycz-
nego. Kawałkiem projektu jest biblioteka, i teraz ow ˛
a bibliotek ˛e chc ˛e
z projektu wyci ˛
a´c i przenie´s´c do własnego repozytorium, tak by za-
chwoa´c cał ˛
a histori ˛e owej biblioteki.
W zasadzie git ma standardowe narz ˛edzia do zarz ˛
adzanai podmo-
dułami, ale ja jestem na to troszk ˛e za głupi.
Znalazłem wi ˛ec projekt git-subtree, który robi dokładnie to, nie jest
to cz ˛e´s´c standardowego gita, ale działa.
Najpierw trzeba to sobie ´sci ˛
agn ˛
a´c i umie´sci´c gdzie´s w pathu. ´
Scia-
gamy z
http://github.com/apenwarr/git-subtree
. Interesuje nas plik
git-subtree.sh
.
Zakładamy ˙ze biblioteka jest w podkatalogu o nazwie libdir.
git-subtree --prefix libdir -b lib-export
Utworzy to nam brancha o nazwie lib-export zawieraj ˛
acego wszyst-
kie commity dotykaj ˛
ace katalogu libdir.
Teraz tworzymy repozytroium i wykonujemy:
git-push url_repozytorium lib-export