diff --git a/pl/05-distributed-git/01-chapter5.markdown b/pl/05-distributed-git/01-chapter5.markdown index f7bc47030..54e9f1ac1 100644 --- a/pl/05-distributed-git/01-chapter5.markdown +++ b/pl/05-distributed-git/01-chapter5.markdown @@ -1,9 +1,11 @@ # Rozproszony Git # Teraz, gdy masz już skonfigurowane zdalne repozytorium, które służy do wymiany pracy między programistami w projekcie oraz jesteś zaznajomiony z podstawowymi komendami pozwalającymi na pracę z lokalnym repozytorium Git, zobaczysz jak wykorzystać jego możliwości w rozproszonym trybie pracy, który Git umożliwia. + W tym rozdziale, zobaczysz jak pracować z Gitem w rozproszonym środowisku jako współpracownik lub integrator zmian. Nauczysz się jak udostępniać wprowadzone zmiany oraz jak zrobić to najprościej jak tylko się da dla siebie i opiekuna projektu, oraz jak zarządzać projektem w którym uczestniczy wielu programistów. + ## Rozproszone przepływy pracy ## @@ -22,23 +24,20 @@ Figure 5-1. Scentralizowany przepływ pracy. Oznacza to tyle, że w sytuacji w której dwóch niezależnych programistów korzystających z tego centralnego repozytorium będzie próbowało wgrać swoje zmiany, tylko pierwszemu z nich uda się tego dokonać bezproblemowo. Drugi przed wgraniem, będzie musiał najpierw pobrać i zintegrować zmiany wprowadzone przez pierwszego programistę, a dopiero później ponowić próbę wysłania swoich na serwer. Taki rodzaj współpracy sprawdza się doskonale w Gitcie, tak samo jak funkcjonuje on w Subversion (lub każdym innym CVCS). Jeżeli masz mały zespół, lub dobrze znacie pracę z jednym centralnym repozytorium w firmie lub zespole, możesz bez problemów kontynuować ten rodzaj pracy z Gitem. Po prostu załóż nowe repozytorium, nadaj każdej osobie z zespołu uprawnienia do wgrywania zmian (za pomocą komendy `push`); Git nie pozwoli na nadpisanie pracy jednego programisty przez innego. Jeżeli jeden z programistów sklonuje repozytorium, wprowadzi zmiany i będzie próbował wgrać je do głównego repozytorium, a w międzyczasie inny programista wgra już swoje zmiany, serwer odrzuci jego zmiany. Zostaną poinformowani że próbują wgrać zmiany (tzw. non-fast-forward) i że muszą najpierw pobrać je (fetch) i włączyć do swojego repozytorium (merge). Taki rodzaj współpracy jest atrakcyjny dla dużej ilości osób, ponieważ działa w taki sposób, w jaki przywykli oni pracować. - + + ### Przepływ pracy z osobą integrującą zmiany ### Ponieważ Git powala na posiadanie wielu zdalnych repozytoriów, możliwy jest schamat pracy w którym każdy programista ma uprawnienia do zapisu do swojego własnego repozytorium oraz uprawnienia do odczytu do repozytorium innych osób w zespole. Ten scenariusz często zawiera jedno centralne - "oficjalne" repozytorium projektu. Aby wgrać zmiany do projektu, należy stworzyć publiczną kopię tego repozytorium i wgrać ("push") zmiany do niego. Następnie należy wysłać prośbę do opiekuna aby pobrał zmiany do głównego repozytorium. Może on dodać twoje repozytorium jako zdalne, przetestować twoje zmiany lokalnie, włączyć je do nowej gałęzi i następnie wgrać do repozytorium. Proces ten wygląda następująco (rys. 5-2): - + -1. Opiekun projektu wgrywa zmiany do publiczego repozytorium. +1. Opiekun projektu wgrywa zmiany do publicznego repozytorium. 2. Programiści klonują to repozytorium i wprowadzają zmiany. -3. Programista wgrywa zmiany do swojego publiczego repozytorium. +3. Programista wgrywa zmiany do swojego publicznego repozytorium. 4. Programista wysyła prośbę do opiekuna projektu, aby pobrał zmiany z jego repozytorium. 5. Opiekun dodaje repozytorium programisty jako repozytorium zdalne i pobiera zmiany. 6. Opiekun wgrywa włączone zmiany do głównego repozytorium. @@ -55,19 +54,15 @@ Because Git allows you to have multiple remote repositories, it’s possible to Insert 18333fig0502.png Figure 5-2. Przepływ pracy z osobą integrującą zmiany. -To jest bardzo popularne podejście podczas współpracy przy pomocy stron takich jak GitHub, gdzie bardzo łatwo można stworzyć kopię repozytorium i wgrywać zmiany do niego aby kazdy mógł je zobaczyć. jedną z głównych zalet takiego podejscia jest to, że możesz kontynuować pracę, a opiekun może pobrać twoje zmiany w dowolnym czasie. Programiści nie muszą czekać na opiekuna, aż ten włączy ich zmiany, każdy z nich może pracować oddzielnie. +To jest bardzo popularne podejście podczas współpracy przy pomocy stron takich jak GitHub, gdzie bardzo łatwo można stworzyć kopię repozytorium i wgrywać zmiany do niego aby każdy mógł je zobaczyć. jedną z głównych zalet takiego podejścia jest to, że możesz kontynuować pracę, a opiekun może pobrać twoje zmiany w dowolnym czasie. Programiści nie muszą czekać na opiekuna, aż ten włączy ich zmiany, każdy z nich może pracować oddzielnie. - + ### Przepływ pracy z dyktatorem i porucznikami ### -To jest wartiant przepływu z wieloma repozytoriami. Zazwyczaj jest on używany w bardzo dużych projektach, z setkami programistów; najbardziej znanym przykładem może być jądro Linuksa. Kilkoro opiekunów jest wydelegowanych do obsługi wydzielonych części repozytorium; nazwijmy ich porucznikami. Wszyscy z nich mają jedną, główną osobę integrującą zmiany - znaną jako miłościwy dyktator. Repozytorium dyktatora jest wzorcowym, z którego wszyscy programiści pobierają zmiany. Cały proces działa następująco (rys. 5-3): +To jest wariant przepływu z wieloma repozytoriami. Zazwyczaj jest on używany w bardzo dużych projektach, z setkami programistów; najbardziej znanym przykładem może być jądro Linuksa. Kilkoro opiekunów jest wydelegowanych do obsługi wydzielonych części repozytorium; nazwijmy ich porucznikami. Wszyscy z nich mają jedną, główną osobę integrującą zmiany - znaną jako miłościwy dyktator. Repozytorium dyktatora jest wzorcowym, z którego wszyscy programiści pobierają zmiany. Cały proces działa następująco (rys. 5-3): - + 1. Programiści pracują nad swoimi gałęziami tematycznymi, oraz wykonują "rebase" na gałęzi "master". Gałąź "master" jest tą pobraną od dyktatora. @@ -85,69 +80,49 @@ This is a variant of a multiple-repository workflow. It’s generally used by hu Insert 18333fig0503.png Figure 5-3. Przepływ pracy z miłościwym dyktatorem. -Ten rodzaj współpracy nie jest częsty w użyciu, ale może być użyteczny w bardzo duzych projektach, lub bardzo rozbudowanych strukturach zespołów w których lider zespołu może delegować większość pracy do innych i zbierać duże zestawy zmian przed integracją. +Ten rodzaj współpracy nie jest częsty w użyciu, ale może być użyteczny w bardzo dużych projektach, lub bardzo rozbudowanych strukturach zespołów w których lider zespołu może delegować większość pracy do innych i zbierać duże zestawy zmian przed integracją. - + To są najczęściej stosowane przepływy pracy możliwe przy użyciu rozproszonego systemu takiego jak Git, jednak możesz zauważyć że istnieje w tym względzie duża dowolność, tak abyś mógł dostosować go do używanego przez siebie tryby pracy. Teraz gdy (mam nadzieję) możesz już wybrać sposób pracy który jest dla ciebie odpowiedni, pokaże kilka konkretnych przykładów w jaki sposób osiągnąć odpowiedni podział ról dla każdego z opisanych przepływów. - + ## Wgrywanie zmian do projektu ## Znasz już różne sposoby pracy, oraz powinieneś posiadać solidne podstawy używania Gita. W tej sekcji, nauczysz się kilku najczęstszych sposobów aby uczestniczyć w projekcie. - + -Główną trudnością podczas opisywania tego procesu, jest bardzo duża różnorodność sposobów w jaki jest to realizowane. Ponieważ Git jest bardzo elastycznym narzędziem, ludzie mogą i współpracują ze sobą na różne sposoby, dlatego też trudne jest pokazanie w jaki sposób Ty powinieneś - każdy projekt jest inny. Niektóre ze zmiennych które warto wziąźć pod uwagę to ilość aktywnych współpracowników, wybrany sposób przepływów pracy, uprawnienia, oraz prawdopodobnie sposób współpracy z zewnętrznymi programistami. +Główną trudnością podczas opisywania tego procesu, jest bardzo duża różnorodność sposobów w jaki jest to realizowane. Ponieważ Git jest bardzo elastycznym narzędziem, ludzie mogą i współpracują ze sobą na różne sposoby, dlatego też trudne jest pokazanie w jaki sposób Ty powinieneś - każdy projekt jest inny. Niektóre ze zmiennych które warto wziąć pod uwagę to ilość aktywnych współpracowników, wybrany sposób przepływów pracy, uprawnienia, oraz prawdopodobnie sposób współpracy z zewnętrznymi programistami. - + Pierwszą zmienną jest ilość aktywnych współpracowników. Ilu aktywnych współpracowników/programistów aktywnie wgrywa zmiany do projektu, oraz jak często? Najczęściej będzie to sytuacja, w której uczestniczy dwóch lub trzech programistów, wgrywających kilka razy na dzień zmiany (lub nawet mniej, przy projektach nie rozwijanych aktywnie). Dla bardzo dużych firm lub projektów, ilość programistów może wynieść nawet tysiące, z dziesiątkami lub nawet setkami zmian wgrywanych każdego dnia. Jest to bardzo ważne, ponieważ przy zwiększającej się liczbie programistów, wypływa coraz więcej problemów podczas włączania efektów ich prac. Zmiany które próbujesz wgrać, mogą stać się nieużyteczne, lub niepotrzebne ze względu na zmiany innych osób z zespołu. Tylko w jaki sposób zachować spójność kodu i poprawność wszystkich przygotowanych łatek? - + Następną zmienną jest sposób przepływu pracy w projekcie. Czy jest scentralizowany, w którym każdy programista ma równy dostęp do wgrywania kodu? Czy projekt posiada głównego opiekuna, lub osobę integrującą, która sprawdza wszystkie łatki? Czy wszystkie łatki są wzajemnie zatwierdzane? Czy uczestniczysz w tym procesie? Czy funkcjonuje porucznik, do którego musisz najpierw przekazać swoje zmiany? - + Następnym elementem są uprawnienia do repozytorium. Sposób pracy z repozytorium do którego możesz wgrywać zmiany bezpośrednio, jest zupełnie inny, od tego w którym masz dostęp tylko do odczytu. Jeżeli nie masz uprawnień do zapisu, w jaki sposób w projekcie akceptowane są zmiany? Czy ma on określoną politykę? Jak duże zmiany wgrywasz za jednym razem? Jak często je wgrywasz? - + Odpowiedzi na wszystkie te pytania, mogą wpływać na to w jaki sposób będziesz wgrywał zmiany do repozytorium, oraz jaki rodzaj przepływu pracy jest najlepszy lub nawet dostępny dla Ciebie. Omówię aspekty każdej z nich w serii przypadków użycia, przechodząc od prostych do bardziej złożonych, powinieneś móc skonstruować konkretny przepływ pracy który możesz zastosować w praktyce z tych przykładów. - + ### Wskazówki wgrywania zmian ### Zanim spojrzysz na poszczególne przypadki użycia, najpierw szybka informacja o treści komentarzy do zmian ("commit messages"). Dobre wytyczne do tworzenia commitów, oraz związanych z nią treścią komentarzy pozwala na łatwiejszą pracę z Gitem oraz innymi współpracownikami. Projekt Git dostarcza dokumentację która pokazuje kilka dobrych rad dotyczących tworzenia commit-ów i łat - możesz ją znaleźć w kodzie źródłowym Gita w pliku `Documentation/SubmittingPatches`. - + Po pierwsze, nie chcesz wgrywać żadnych błędów związanych z poprawkami pustych znaków (np. spacji). Git dostarcza łatwy sposób do tego - zanim wgrasz zmiany, uruchom `git diff --check`, komenda ta pokaże możliwe nadmiarowe spacje. Poniżej mamy przykład takiej sytuacji, zamieniłem kolor czerwony na terminalu znakami `X`: - + $ git diff --check lib/simplegit.rb:5: trailing whitespace. @@ -160,23 +135,17 @@ First, you don’t want to submit any whitespace errors. Git provides an easy wa Jeżeli uruchomisz tą komendę przed commit-em, dowiesz się czy zamierzasz wgrać zmiany które mogą zdenerwować innych programistów. - + -Następnie spróbuj w każdym commit-ie zawrzeć logicznie odrebny zestaw zmian. Jeżeli możesz, twórz nie za duże łatki - nie programuj cały weekend poprawiając pięć różnych błędów, aby następnie wszystkie je wypuścić w jednym dużym commit-cie w poniedziałek. Nawet jeżeli nie zatwierdzasz zmian w ciągu weekendu, użyj przechowalni ("stage"), aby w poniedziałek rozdzielić zmiany na przynajmniej jeden commit dla każdego błędu, dodając użyteczny komentarz do każdego commitu. Jeżeli niektóre ze zmian modyfikują ten sam plik, spróbuj użyć komendy `git add --patch`, aby częściowo dodać zmiany do przechowalni (dokładniej opisane to jest w rozdziale 6). Końcowa migawka projektu w gałęzi jest identyczna, nieważne czy zrobisz jeden czy pięć commitów, więc spróbuj ułatwić życie swoim współpraconikom kiedy będą musieli przeglądać twoje zmiany. Takie podejście ułatwia również pobranie lub przywrócenie pojedynczych zestawów zmian w razie potrzeby. Rozdział 6 opisuje kilka ciekawych trików dotyczących nadpisywania historii zmian i interaktywnego dodawania plików do przechowalni - używaj ich do utrzymania czystej i przejrzystej historii. +Następnie spróbuj w każdym commit-ie zawrzeć logicznie odrębny zestaw zmian. Jeżeli możesz, twórz nie za duże łatki - nie programuj cały weekend poprawiając pięć różnych błędów, aby następnie wszystkie je wypuścić w jednym dużym commit-cie w poniedziałek. Nawet jeżeli nie zatwierdzasz zmian w ciągu weekendu, użyj przechowalni ("stage"), aby w poniedziałek rozdzielić zmiany na przynajmniej jeden commit dla każdego błędu, dodając użyteczny komentarz do każdego commitu. Jeżeli niektóre ze zmian modyfikują ten sam plik, spróbuj użyć komendy `git add --patch`, aby częściowo dodać zmiany do przechowalni (dokładniej opisane to jest w rozdziale 6). Końcowa migawka projektu w gałęzi jest identyczna, nieważne czy zrobisz jeden czy pięć commitów, więc spróbuj ułatwić życie swoim współpracownikom kiedy będą musieli przeglądać twoje zmiany. Takie podejście ułatwia również pobranie lub przywrócenie pojedynczych zestawów zmian w razie potrzeby. Rozdział 6 opisuje kilka ciekawych trików dotyczących nadpisywania historii zmian i interaktywnego dodawania plików do przechowalni - używaj ich do utrzymania czystej i przejrzystej historii. - + Ostatnią rzeczą na którą należy zwrócić uwagę są komentarze do zmian. Tworzenie dobrych komentarzy pozwala na łatwiejsze używanie i współpracę za pomocą Gita. Generalną zasadą powinno być to, że treść komentarza rozpoczyna się od pojedynczej linii nie dłuższej niż 50 znaków, która zwięźle opisuje zmianę, następnie powinna znaleźć się pusta linia, a poniżej niej szczegółowy opis zmiany. Projekt Git wymaga bardzo dokładnych wyjaśnień motywujących twoją zmianę w stosunku do poprzedniej implementacji - jest to dobra wskazówka do naśladowania. Dobrym pomysłem jest używania czasu teraźniejszego w trybie rozkazującym. Innymi słowy, używaj komend. Zamiast "Dodałem testy dla" lub "Dodawania testów dla", użyj "Dodaj testy do". -Poniżej znajduje się szablon komentarza przygotowany przez Tima Popea z tpope.net: +Poniżej znajduje się szablon komentarza przygotowany przez Tima Pope z tpope.net: - + Krótki (50 znaków lub mniej) opis zmiany @@ -198,30 +167,23 @@ Here is a template originally written by Tim Pope at tpope.net: Jeżeli wszystkie twoje komentarz do zmian będą wyglądały jak ten, współpraca będzie dużo łatwiejsza dla ciebie i twoich współpracowników. Projekt Git ma poprawnie sformatowane komentarze, uruchom polecenie `git log --no-merges` na tym projekcie, aby zobaczyć jak wygląda ładnie sformatowana i prowadzona historia zmian. - + W poniższych przykładach, i przez większość tej książki, ze względu na zwięzłość nie sformatowałem treści komentarzy tak ładnie; używam opcji `-m` do `git commit`. Rób tak jak mówię, nie tak jak robię. - + ### Małe prywatne zespoły ### Najprostszym przykładem który możesz spotkać, to prywatne repozytorium z jednym lub dwoma innymi współpracownikami. Jako prywatne, mam na myśli repozytorium z zamkniętym kodem źródłowym - nie dostępnym do odczytu dla innych.Ty i inny deweloperzy mają uprawniania do wgrywania ("push") swoich zmian. - -W takim środowisku możesz naśladować sposób pracy znany z Subversion czy innego scenatralizowanego systemu kontroli wersji. Nadal masz wszystkie zalety takie jak commitowanie bez dostępu do centralnego serwera, oraz prostsze tworzenie gałęzi i łączenie zmian, ale przepływ pracy jest bardzo podobny; główną różnicą jest to, że łączenie zmian wykonywane jest po stronie klienta a nie serwera podczas commitu. + + +W takim środowisku możesz naśladować sposób pracy znany z Subversion czy innego scentralizowanego systemu kontroli wersji. Nadal masz wszystkie zalety takie jak commitowanie bez dostępu do centralnego serwera, oraz prostsze tworzenie gałęzi i łączenie zmian, ale przepływ pracy jest bardzo podobny; główną różnicą jest to, że łączenie zmian wykonywane jest po stronie klienta a nie serwera podczas commitu. Zobaczmy jak to może wyglądać, w sytuacji w której dwóch programistów rozpocznie prace z współdzielonym repozytorium. Pierwszy programista, John, klonuje repozytorium, wprowadza zmiany i zatwierdza je lokalnie. (Zamieniłem część informacji znakami `...` aby skrócić przykłady.) - + # Komputer Johna $ git clone john@githost:simplegit.git @@ -261,11 +223,9 @@ John próbuje również wypchnąć swoje zmiany: ! [rejected] master -> master (non-fast forward) error: failed to push some refs to 'john@githost:simplegit.git' -John nie może wypchnąć swoich zmain, ponieważ w międzyczasie Jessica wypchnęła swoje. To jest szczególnie ważne do zrozumienia, jeżeli przywykłeś do Subversion, ponieważ zauważysz że każdy z deweloperów zmianił inne pliki. Chociaż Subversion automatycznie połączy zmiany po stronie serwera jeżeli zmieniane były inne pliki, w Git musisz połączyć zmiany lokalnie. John musi pobrać zmiany Jessici oraz włączyć je do swojego repozytorium zanim będzie wypychał swoje zmiany: +John nie może wypchnąć swoich zmian, ponieważ w międzyczasie Jessica wypchnęła swoje. To jest szczególnie ważne do zrozumienia, jeżeli przywykłeś do Subversion, ponieważ zauważysz że każdy z deweloperów zmieniał inne pliki. Chociaż Subversion automatycznie połączy zmiany po stronie serwera jeżeli zmieniane były inne pliki, w Git musisz połączyć zmiany lokalnie. John musi pobrać zmiany Jessici oraz włączyć je do swojego repozytorium zanim będzie wypychał swoje zmiany: - + $ git fetch origin ... @@ -273,17 +233,15 @@ John isn’t allowed to push because Jessica has pushed in the meantime. This is + 049d078...fbff5bc master -> origin/master W tym momencie lokalne repozytorium Johna wygląda podobnie do tego z rys. 5-4. - + + Insert 18333fig0504.png Figure 5-4. Lokalne repozytorium Johna. John ma już odniesienie do zmian które wypchnęła Jessica, ale musi je lokalnie połączyć ze swoimi zmianami, zanim będzie w stanie wypchnąć je: - + + $ git merge origin/master Merge made by recursive. @@ -291,17 +249,15 @@ John has a reference to the changes Jessica pushed up, but he has to merge them 1 files changed, 1 insertions(+), 0 deletions(-) Łączenie zmian poszło bez problemów - historia zmian u Johna wygląda tak jak na rys. 5-5. - + + Insert 18333fig0505.png Figure 5-5. Repozytorium Johna po połączeniu z origin/master. Teraz, John może przetestować swój kod aby upewnić się że nadal działa poprawnie, oraz następnie wypchnąć swoje zmiany na serwer: - + + $ git push origin master ... @@ -309,28 +265,24 @@ Now, John can test his code to make sure it still works properly, and then he ca fbff5bc..72bbc59 master -> master Ostatecznie, historia zmian u Johna wygląda tak jak na rys. 5-6. - + + Insert 18333fig0506.png -Figure 5-6. Historia zmian Johna po wychnięciu ich na serwer "origin". - +Figure 5-6. Historia zmian Johna po wypchnięciu ich na serwer "origin". + + W tym samym czasie, Jessica pracowała na swojej tematycznej gałęzi. Stworzyła gałąź `issue54` oraz wprowadziła trzy zmiany w niej. Nie pobrała jeszcze zmian Johna, więc jej historia zmian wygląda tak jak na rys. 5-7. - + + Insert 18333fig0507.png Figure 5-7. Początkowa historia zmian u Jessici. Jessica chce zsynchronizować się ze zmianami Johna, więc pobiera ("fetch"): - + + # Jessica's Machine $ git fetch origin @@ -338,21 +290,18 @@ Jessica wants to sync up with John, so she fetches: From jessica@githost:simplegit fbff5bc..72bbc59 master -> origin/master -Ta komenda pobiera zmiany Johna, które wprowadził w miedzyczasie. Historia zmian u Jessici wygląda tak jak na rys. 5-8. - +Ta komenda pobiera zmiany Johna, które wprowadził w międzyczasie. Historia zmian u Jessici wygląda tak jak na rys. 5-8. + + Insert 18333fig0508.png Figure 5-8. Historia zmian u Jessici po pobraniu zmian Johna. - + + Jessica uważa swoje prace w tej gałęzi za zakończone, ale chciałaby wiedzieć jakie zmiany musi włączyć aby mogła wypchnąć swoje. Uruchamia komendę `git log` aby się tego dowiedzieć: - + + $ git log --no-merges origin/master ^issue54 commit 738ee872852dfaa9d6634e0dea7a324040193016 @@ -362,18 +311,16 @@ Jessica thinks her topic branch is ready, but she wants to know what she has to removed invalid default value Teraz Jessica może połączyć zmiany ze swojej gałęzi z gałęzią "master", włączyć zmiany Johna (`origin/master`) do swojej gałęzi `master`, oraz następnie wypchnąć zmiany ponownie na serwer. - + + $ git checkout master Switched to branch "master" Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded. Może ona włączyć `origin/master` lub `issue54` jako pierwszą, obie są nadrzędne więc kolejność nie ma znaczenia. Końcowa wersja plików powinna być identyczna bez względu na kolejność którą wybierze; tylko historia będzie się lekko różniła. Wybiera pierwszą do włączenia gałąź `issue54`: - + + $ git merge issue54 Updating fbff5bc..4af4298 @@ -383,9 +330,8 @@ She can merge either `origin/master` or `issue54` first — they’re both upstr 2 files changed, 6 insertions(+), 1 deletions(-) Nie było problemów; jak widzisz był to proste połączenie tzw. fast-forward. Teraz Jessica może włączyć zmiany Johna (`origin/master`): - + + $ git merge origin/master Auto-merging lib/simplegit.rb @@ -394,20 +340,17 @@ No problems occur; as you can see, it was a simple fast-forward. Now Jessica mer 1 files changed, 1 insertions(+), 1 deletions(-) Wszystko połączyło się bez problemów, więc historia zmian u Jessici wygląda tak jak na rys. 5-9. - + + Insert 18333fig0509.png Figure 5-9. Historia zmian u Jessici po włączeniu zmian Johna. - -Teraz `origin/master` jest dostepny z gałęzi `master` u Jessici, więc powinna bez problemów móc wypchnąć swoje zmiany (zakładając że w międzyczasie John nie wypchnął nic): - + + +Teraz `origin/master` jest dostępny z gałęzi `master` u Jessici, więc powinna bez problemów móc wypchnąć swoje zmiany (zakładając że w międzyczasie John nie wypchnął nic): + + $ git push origin master ... @@ -415,43 +358,36 @@ Now `origin/master` is reachable from Jessica’s `master` branch, so she should 72bbc59..8059c15 master -> master Każdy programista wprowadził zmiany kilkukrotnie, oraz połączył zmiany drugiego bez problemów; zobacz rys. 5-10. - + + Insert 18333fig0510.png -Figure 5-10. Historia zmian u Jessici po wychnięciu zmian na serwer. - +Figure 5-10. Historia zmian u Jessici po wypchnięciu zmian na serwer. + + To jest jeden z najprostszych przepływów pracy. Pracujesz przez chwilę, generalnie na tematycznych gałęziach i włączasz je do gałęzi master kiedy są gotowe. Kiedy chcesz podzielić się swoją pracą, włączasz je do swojej gałęzi master, pobierasz i włączasz zmiany z `origin/master` jeżeli jakieś były, a następnie wypychasz gałąź `master` na serwer. Zazwyczaj sekwencja będzie wyglądała podobnie do tej pokazanej na rys. 5-11. - + + Insert 18333fig0511.png Figure 5-11. Sekwencja zdarzeń dla prostego przepływu zmian między programistami. - + + ### Prywatne zarządzane zespoły ### W tym scenariuszu, zobaczysz jak działa współpraca w większych prywatnych grupach. Nauczysz się jak pracować w środowisku w którym małe grupy współpracują ze sobą nad funkcjonalnościami, a następnie stworzone przez nich zmiany są integrowane przez inną osobą. - -Załóżmy że John i Jessica wspólnie pracują nad jedną funkcjonalnością, a Jessica i Josie nad drugą. W taj sytuacji, organizacja używa przepływu pracy z osobą integrującą zmiany, w której wyniki pracy poszczegółnych grup są integrowane przez wyznaczone osoby, a gałąź `master` może być jedynie przez nie aktualizowana. W tym scenariuszu, cała praca wykonywana jest w osobnych gałęziach zespołów, a następnie zaciągana przez osoby integrujące. - + + +Załóżmy że John i Jessica wspólnie pracują nad jedną funkcjonalnością, a Jessica i Josie nad drugą. W taj sytuacji, organizacja używa przepływu pracy z osobą integrującą zmiany, w której wyniki pracy poszczególnych grup są integrowane przez wyznaczone osoby, a gałąź `master` może być jedynie przez nie aktualizowana. W tym scenariuszu, cała praca wykonywana jest w osobnych gałęziach zespołów, a następnie zaciągana przez osoby integrujące. + + Prześledźmy sposób pracy Jessici w czasie gdy pracuje ona nad obiema funkcjonalnościami, współpracując jednocześnie z dwoma niezależnymi programistami. Zakładając że ma już ona sklonowane repozytorium, rozpoczyna pracę nad funkcjonalnością `featureA`. Tworzy nową gałąź dla niej i wprowadza w niej zmiany: - + + # Jessica's Machine $ git checkout -b featureA @@ -462,9 +398,8 @@ Let’s follow Jessica’s workflow as she works on her two features, collaborat 1 files changed, 1 insertions(+), 1 deletions(-) Teraz musi podzielić się swoją pracę z Johnem, więc wypycha zmiany z gałęzi `featureA` na serwer. Jessica nie ma uprawnień do zapisywania w gałęzi `master` - tylko osoby integrujące mają - musi więc wysłać osobną gałąź aby współpracować z Johnem: - + + $ git push origin featureA ... @@ -472,9 +407,8 @@ At this point, she needs to share her work with John, so she pushes her `feature * [new branch] featureA -> featureA Jessica powiadamia Johna przez wiadomość email, że wysłała swoje zmiany w gałęzi `featureA` i on może je zweryfikować. W czasie gdy czeka na informację zwrotną od Johna, Jessica rozpoczyna pracę nad `featureB` z Josie. Na początku, tworzy nową gałąź przeznaczoną dla nowej funkcjonalności, podając jako gałąź źródłową gałąź `master` na serwerze. - + + # Jessica's Machine $ git fetch origin @@ -482,9 +416,8 @@ Jessica e-mails John to tell him that she’s pushed some work into a branch nam Switched to a new branch "featureB" Następnie, Jessica wprowadza kilka zmian i zapisuje je w gałęzi `featureB`: - + + $ vim lib/simplegit.rb $ git commit -am 'made the ls-tree function recursive' @@ -496,20 +429,17 @@ Now, Jessica makes a couple of commits on the `featureB` branch: 1 files changed, 5 insertions(+), 0 deletions(-) Repozytorium Jessici wygląda tak jak na rys. 5-12. - + + Insert 18333fig0512.png Figure 5-12. Początkowa historia zmian u Jessici. - + + Jest gotowa do wypchnięcia swoich zmian, ale dostaje wiadomość email od Josie, że gałąź z pierwszymi zmianami została już udostępniona na serwerze jako `featureBee`. Jessica najpierw musi połączyć te zmiany ze swoimi, zanim będzie mogła wysłać je na serwer. Może więc pobrać zmiany Jose za pomocą komendy `git fetch`: - + + $ git fetch origin ... @@ -518,9 +448,8 @@ She’s ready to push up her work, but gets an e-mail from Josie that a branch w Jessica może teraz połączyć zmiany ze swoimi za pomocą `git merge`: - + + $ git merge origin/featureBee Auto-merging lib/simplegit.rb @@ -528,10 +457,9 @@ Jessica can now merge this into the work she did with `git merge`: lib/simplegit.rb | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) -Powstał drobny problem - musi wysłać połączone zmiany ze swojej gałęzi `featureB` do `featureBee` na serwerze. Może to zrobić poprzez wskazanie lokalnej i zdalnej gałęzi oddzielonej dwukropkiem (:), jako parametr do komeny `git push`: - +Powstał drobny problem - musi wysłać połączone zmiany ze swojej gałęzi `featureB` do `featureBee` na serwerze. Może to zrobić poprzez wskazanie lokalnej i zdalnej gałęzi oddzielonej dwukropkiem (:), jako parametr do komendy `git push`: + + $ git push origin featureB:featureBee ... @@ -539,14 +467,12 @@ There is a bit of a problem — she needs to push the merged work in her `featur fba9af8..cd685d1 featureB -> featureBee jest to nazywane _refspec_. Zobacz rozdział 9, aby dowiedzieć się więcej o refspecs i rzeczami które można z nimi zrobić. - + + Następnie John wysyła wiadomość do Jessici z informacją że wgrał swoje zmiany do gałęzi `featureA` i prosi ją o ich weryfikację. Uruchamia więc ona `git fetch` aby je pobrać: - + + $ git fetch origin ... @@ -554,9 +480,8 @@ Next, John e-mails Jessica to say he’s pushed some changes to the `featureA` b 3300904..aad881d featureA -> origin/featureA Następnie, może ona zobaczyć co zostało zmienione za pomocą komendy `git log`: - + + $ git log origin/featureA ^featureA commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6 @@ -566,9 +491,8 @@ Then, she can see what has been changed with `git log`: changed log output to 30 from 25 Na końcu, integruje ona zmiany Johna ze swoimi znajdującymi się w gałęzi `featureA`: - + + $ git checkout featureA Switched to branch "featureA" @@ -579,9 +503,8 @@ Finally, she merges John’s work into her own `featureA` branch: 1 files changed, 9 insertions(+), 1 deletions(-) Jessica postanawia jednak wprowadzić jeszcze jakieś zmiany, więc commituje je ponownie i wysyła je z powrotem na serwer: - + + $ git commit -am 'small tweak' [featureA 774b3ed] small tweak @@ -592,49 +515,41 @@ Jessica wants to tweak something, so she commits again and then pushes this back 3300904..774b3ed featureA -> featureA Historia zmian u Jessici wygląda teraz tak jak na rys. 5-13. - + + Insert 18333fig0513.png Figure 5-13. Historia zmian Jessici po wprowadzeniu zmian w gałęzi. - + + Jessica, Josie i John powiadamiają osoby zajmujące się integracją, że gałęzie `featureA` i `featureBee` na serwerze są gotowe do integracji z głównym kodem. Po włączeniu tych gałęzi do głównej, zostaną pobrane zmiany, tworząc historię zmian podobną do tej na rys. 5-14. - + + Insert 18333fig0514.png Figure 5-14. Historia zmian u Jessici po włączeniu jej obu gałęzi. - + + Duża ilość grup przechodzi na Gita ze względu na możliwość jednoczesnej współpracy kilku zespołów, oraz możliwości włączania efektów ich prac w późniejszym terminie. Możliwość tworzenie małych grup współpracujących przy pomocy zdalnych gałęzi bez konieczności angażowania pozostałych członków zespołu jest bardzo dużą zaletą Gita. Sekwencja przepływu pracy którą tutaj zobaczyłeś, jest podobna do tej na rys. 5-15. - + + Insert 18333fig0515.png Figure 5-15. Przebieg zdarzeń w takim przepływie. - + + ### Publiczny mały projekt ### -Uczestniczenie w publicznym projekcie trochę się różni. Ponieważ nie masz uprawnień do bezpośredniego wgrywania zmian w projekcie, musisz przekazać swoje zmiany do opiekunów w inny sposób. Pierwszy przykład opisuje udział w projekcie poprzez rozwidlenie poprzez serwis który to umożliwia. Obie strony repo.or.cz oraz GitHub umozliwiają takie działanie, a wielu opiekunów projektów oczekuje takiego stylu współpracy. Następny rozdział opisuje współpracę w projektach, które preferują otrzymywanie łat poprzez wiadomość e-mail. - +Uczestniczenie w publicznym projekcie trochę się różni. Ponieważ nie masz uprawnień do bezpośredniego wgrywania zmian w projekcie, musisz przekazać swoje zmiany do opiekunów w inny sposób. Pierwszy przykład opisuje udział w projekcie poprzez rozwidlenie poprzez serwis który to umożliwia. Obie strony repo.or.cz oraz GitHub umożliwiają takie działanie, a wielu opiekunów projektów oczekuje takiego stylu współpracy. Następny rozdział opisuje współpracę w projektach, które preferują otrzymywanie łat poprzez wiadomość e-mail. + + Po pierwsze, na początku musisz sklonować główne repozytorium, stworzyć gałąź tematyczną dla zmian które planujesz wprowadzić, oraz zmiany te zrobić. Sekwencja komend wygląda tak: - + + $ git clone (url) $ cd project @@ -645,35 +560,28 @@ First, you’ll probably want to clone the main repository, create a topic branc $ git commit Możesz chcieć użyć `rebase -i`, aby złączyć swoje zmiany do jednego commita, lub przeorganizować je, tak aby łata była łatwiejsza do opiekuna do przeglądu - zobacz rozdział 6, aby dowiedzieć się więcej o tego typu operacjach. - + + Kiedy zmiany w twojej gałęzi zostaną zakończone i jesteś gotowy do przekazania ich do opiekunów projektu, wejdź na stronę projektu i kliknij przycisk "Fork", tworząc w ten sposób swoją własną kopię projektu z uprawnieniami do zapisu. Następnie musisz dodać nowe zdalne repozytorium, w tym przykładzie nazwane `myfork`: - + + $ git remote add myfork (url) Musisz wysłać swoje zmiany do niego. Najprościej będzie wypchnąć lokalną gałąź na której pracujesz do zdalnego repozytorium, zamiast włączać zmiany do gałęzi master i je wysyłać. Warto zrobić tak dlatego, że w sytuacji w której twoje zmiany nie zostaną zaakceptowane, lub zostaną zaakceptowane tylko w części, nie będziesz musiał cofać swojej gałęzi master. Jeżeli opiekun włączy, zmieni bazę lub pobierze część twoich zmian, będziesz mógł je otrzymać zaciągając je z ich repozytorium: - + $ git push myfork featureA Kiedy wgrasz wprowadzone zmiany do swojego rozwidlenia projektu, powinieneś powiadomić o tym opiekuna. Jest to często nazywane `pull request`, i możesz je wygenerować poprzez stronę - GitHub ma przycisk "pull request", który automatycznie generuje wiadomość do opiekuna - lub wykonaj komendę `git request-pull` i wyślij jej wynik do opiekuna projektu samodzielnie. - -Komenda `request-pull` pobiera docelową gałąź do której chcesz wysłać zmiany, oraz adres URL repozytorium Gita z którego chcesz pobrać zmiany, oraz generuje podsumowanie zmian które bedziesz wysyłał. Na przykład, jeżeli Jessica chce wysłać do Johna `pull request`, a wykonała dwe zmiany na swojej gałęzi którą właśnie wypchnęła, powinna uruchomić: + - +Komenda `request-pull` pobiera docelową gałąź do której chcesz wysłać zmiany, oraz adres URL repozytorium Gita z którego chcesz pobrać zmiany, oraz generuje podsumowanie zmian które będziesz wysyłał. Na przykład, jeżeli Jessica chce wysłać do Johna `pull request`, a wykonała dwe zmiany na swojej gałęzi którą właśnie wypchnęła, powinna uruchomić: + + $ git request-pull origin/master myfork The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40: @@ -693,14 +601,12 @@ The `request-pull` command takes the base branch into which you want your topic Wynik tej komendy może być wysłany do opiekuna - mówi on z której wersji została stworzona gałąź, podsumowuje zmiany, oraz pokazuje skąd można je pobrać. - + + W projekcie w którym nie jesteś opiekunem, najprostszym sposobem jest utrzymywanie gałęzi `master` która śledzi `origin/master`, a wprowadzać zmiany w tematycznych gałęziach, które możesz łatwo usunąć jeżeli zostaną odrzucone. Posiadanie oddzielnych gałęzi dla różnych funkcjonalności, ułatwia również tobie zmianę bazy ("rebase") jeżeli główna gałąź zostanie zmieniona i przygotowana łata nie może się poprawnie nałożyć. Na przykład, jeżeli chcesz wysłać drugi zestaw zmian do projektu, nie kontynuuj pracy na gałęzi którą właśnie wypchnąłeś - rozpocznij nową z gałąź `master`: - + + $ git checkout -b featureB origin/master $ (work) @@ -710,45 +616,38 @@ On a project for which you’re not the maintainer, it’s generally easier to h $ git fetch origin Teraz, każdy z zestawów zmian przechowywany jest w formie silosu - podobnego do kolejki z łatami - które możesz nadpisać, zmienić, bez konieczności nachodzenia na siebie, tak jak przedstawiono to na rys. 5-16. - + + Insert 18333fig0516.png Figure 5-16. Początkowa historia ze zmianami featureB. - + + Załóżmy, że opiekun projektu pobrał twoje zmiany i sprawdził twoją pierwszą gałąź, ale niestety nie aplikuje się ona czysto. W takiej sytuacji, możesz spróbować wykonać `rebase` na gałęzi `origin/master`, rozwiązać konflikty i ponownie wysłać zmiany: - + + $ git checkout featureA $ git rebase origin/master $ git push -f myfork featureA To przepisuje twoją historię, która wygląda teraz tak jak na rys. 5-17. - + + Insert 18333fig0517.png Figure 5-17. Historia zmian po pracach na featureA. - + + Z powodu zmiany bazy ("rebase") na gałęzi, musisz użyć przełącznika `-f` do komendy push, tak abyś mógł nadpisać gałąź `featureA` na serwerze, commitem który nie jest jej potomkiem. Alternatywą może być wysłanie tych zmian do nowej gałęzi na serwerze (np. nazwanej `featureAv2`). - + + Spójrzmy na jeszcze jeden scenariusz: opiekun spojrzał na zmiany w twojej drugiej gałęzi i spodobał mu się pomysł, ale chciałby abyś zmienił sposób w jaki je zaimplementowałeś. Wykorzystasz to również do tego, aby przenieść zmiany do obecnej gałęzi `master`. Tworzysz więc nową gałąź bazująć na `origin/master`, złączasz zmiany z gałęzi `featureB` tam, rozwiązujesz ewentualne konflikty, wprowadzasz zmiany w implementacji i następnie wypychasz zmiany do nowej gałęzi: - + + $ git checkout -b featureBv2 origin/master $ git merge --no-commit --squash featureB @@ -758,32 +657,27 @@ Let’s look at one more possible scenario: the maintainer has looked at work in Opcja `--squash` pobiera wszystkie zmiany z gałęzi, oraz łączy je w jedną nie włączoną na gałęzi na której obecnie jesteś. Opcja `--no-commit` mówi Git aby nie zapisywał informacji o commit-cie. Pozwala to na zaimportowanie wszystkich zmian z innej gałęzi oraz wprowadzenie nowych przed ostatecznym zatwierdzeniem ich. - + + Teraz możesz wysłać do opiekuna wiadomość, że wprowadziłeś wszystkie wymagane zmiany, które może znaleźć w gałęzi `featureBv2` (zob. rys. 5-18). - + + Insert 18333fig0518.png Figure 5-18. Historia zmian po zmianach w featureBv2. - + + ### Duży publiczny projekt ### -Duża ilość wiekszych projektów ma ustalone reguły dotyczące akceptowania łat - będziesz musiał sprawdzić konkretne zasady dla każdego z projektów, ponieważ będą się różniły. Jednak sporo większych projektów akceptuje łatki poprzez listy dyskusyjne przeznaczone dla programistów, dlatego też opiszę ten przykład teraz. - +Duża ilość większych projektów ma ustalone reguły dotyczące akceptowania łat - będziesz musiał sprawdzić konkretne zasady dla każdego z projektów, ponieważ będą się różniły. Jednak sporo większych projektów akceptuje łatki poprzez listy dyskusyjne przeznaczone dla programistów, dlatego też opiszę ten przykład teraz. + + Przepływ pracy jest podobny do poprzedniego - tworzysz tematyczne gałęzie dla każdej grupy zmian nad którymi pracujesz. Różnica polega na tym, w jaki sposób wysyłasz je do projektu. Zamiast tworzyć rozwidlenie i wypychać do niego zmiany, tworzysz wiadomość e-email dla każdego zestawu zmian i wysyłasz je na listę dyskusyjną: - + + $ git checkout -b topicA $ (work) @@ -792,18 +686,16 @@ The workflow is similar to the previous use case — you create topic branches f $ git commit Teraz masz dwa commity, które chcesz wysłać na listę dyskusyjną. Uzyj `git format-patch` do wygenerowania plików w formacie mbox, które możesz wysłać na listę - zamieni to każdy commit w osobną wiadomość, z pierwszą linią komentarza ("commit message") jako tematem, jego pozostałą częścią w treści, dołączając jednoczenie zawartość wprowadzanej zmiany. Fajną rzeczą jest to, że aplikowanie łatki przesłanej przez email i wygenerowanej za pomocą `format-patch` zachowuje wszystkie informacje o commit-cie, co zobaczysz w kolejnej sekcji kiedy zaaplikujesz te zmiany: - + + $ git format-patch -M origin/master 0001-add-limit-to-log-function.patch 0002-changed-log-output-to-30-from-25.patch Komenda `format-patch` wypisuje nazwy plików które stworzyła. Opcja `-M` mówi Git, aby brał pod uwagę również zmiany nazw plików. Zawartość plików w efekcie końcowym wygląda tak: - + + $ cat 0001-add-limit-to-log-function.patch From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001 @@ -834,19 +726,16 @@ The `format-patch` command prints out the names of the patch files it creates. T 1.6.2.rc1.20.g8c5b.dirty Możesz oczywiście zmienić te pliki i dodać większą ilość informacji w mailu, których nie chciałeś pokazywać w komentarzu do zmiany. Jeżeli dodasz tekst miedzy linię z `--`, oraz początkiem łaty (linia z `lin/simplegit.rb`), programiści będą mogli to przeczytać; ale podczas nakładania łaty zostanie do pominięte. - + + Aby wysłać to na listę dyskusyjną, możesz albo wkleić zawartość plików w programie e-mail lub użyć programu uruchamianego z linii komend. Wklejanie tekstu często wprowadza problemy z zachowaniem formatowania, szczególnie przy użyciu tych "mądrzejszych" programów pocztowych, które nie zachowują poprawnie znaków nowej linii i spacji. Na szczęście Git udostępnia narzędzie, które pomoże Ci wysłać poprawnie sformatowane łaty poprzez protokół IMAP, może to być łatwiejsze dla Ciebie. Pokażę w jaki sposób wysyłać łaty przy pomocy Gmaila, którego używam; możesz znaleźć bardziej szczegółowe instrukcje dla różnych programów pocztowych na końcu wcześniej wymienonego pliku `Documentation/SubmittingPatches`, który znajduje się w kodzie źródłowym Gita. - + + Najpierw musisz ustawić sekcję imap w swoim pliku `~/.gitconfig`. Możesz ustawić każdą wartość oddzielnie przy pomocy kilku komend `git config`, lub możesz je dodać ręcznie; jednak w efekcie twój plik konfiguracyjny powinien wyglądać podobnie do: - + + [imap] folder = "[Gmail]/Drafts" @@ -857,10 +746,9 @@ First, you need to set up the imap section in your `~/.gitconfig` file. You can sslverify = false Jeżeli twój serwer IMAP nie używa SSL, dwie ostatnie linie prawdopodobnie nie są potrzebne, a wartość host będzie `imap://` zamiast `imaps://`. Po ustawieniu tego, możesz używać komendy `git send-email` aby umieścić łatki w folderze Draft na serwerze IMAP: - + + $ git send-email *.patch 0001-added-limit-to-log-function.patch @@ -871,9 +759,8 @@ When that is set up, you can use `git send-email` to place the patch series in t Message-ID to be used as In-Reply-To for the first email? y Następnie, Git pokaże garść informacji podobnych tych, dla każdej łaty którą wysyłasz: - + + (mbox) Adding cc: Jessica Smith from \line 'From: Jessica Smith ' @@ -891,92 +778,80 @@ Then, Git spits out a bunch of log information looking something like this for e Result: OK Od tego momentu powinieneś móc przejść do folderu Draft, zmienić pole odbiorcy wiadomości na adres listy dyskusyjnej do której wysyłasz łatę, ewentualnie dodać adres osób zainteresowanych tym tematem w kopii i wysłać. - + + ### Podsumowanie ### -Ten rozdział opisywał kilka z najczęściej używanych sposóbów przepływu pracy z różnymi projektami Git które możesz spotkać, oraz wprowadził kilka nowych narzędzi które ułatwiają ten proces. W następnych sekcjach zobaczysz jak pracować z drugiej strony: prowadząc projekt Gita. Nauczysz się jak być miłosiernym dyktatorem oraz osobą integrującą zmiany innych. - +Ten rozdział opisywał kilka z najczęściej używanych sposobów przepływu pracy z różnymi projektami Git które możesz spotkać, oraz wprowadził kilka nowych narzędzi które ułatwiają ten proces. W następnych sekcjach zobaczysz jak pracować z drugiej strony: prowadząc projekt Gita. Nauczysz się jak być miłosiernym dyktatorem oraz osobą integrującą zmiany innych. + + ## Utrzymywanie projektu ## Ponad to co musisz wiedzieć, aby efektywnie uczestniczyć w projekcie, powinieneś również wiedzieć jak go utrzymywać. Składa się na to akceptowanie i nakładanie łat wygenerowanych przez `format-patch` i wysłanych do ciebie, lub łączenie zmian z zewnętrznych repozytoriów które dodałeś w projekcie. Nieważne czy prowadzisz zwykłe repozytorium, lub chcesz pomóc przy weryfikacji i integrowaniu łat, musisz wiedzieć w jaki sposób akceptować zmiany innych w taki sposób, który będzie przejrzysty dla innych i spójny w dłuższym okresie. - + + ### Praca z gałęziami tematycznymi ### Jeżeli zamierzasz włączyć nowe zmiany, dobrym pomysłem jest stworzenie do tego nowej tymczasowej gałęzi, specjalnie przygotowanej do tego, aby przetestować te zmiany. W ten sposób najłatwiej dostosować pojedyncze zmiany, lub zostawić je jeżeli nie działają, do czasu aż będziesz mógł się tym ponownie zająć. Jeżeli stworzysz nową gałąź bazując na głównym motywie wprowadzanych zmian które chcesz przetestować, np. `ruby_client` lub coś podobnego, możesz łatwo zapamiętać czy musiałeś ją zostawić aby później do niej wrócić. Opiekun projektu Git często tworzy oddzielną przestrzeń nazw dla nich - np. `sc/ruby_client`, gdzie `sc` jest skrótem od osoby która udostępniła zmianę. -Jak pamiętasz, możesz stworzyć nową gałąź bazująć na swojej gałęzi master, w taki sposób: - +Jak pamiętasz, możesz stworzyć nową gałąź bazując na swojej gałęzi master, w taki sposób: + + $ git branch sc/ruby_client master Lub, jeżeli chcesz się od razu na nią przełączyć, możesz użyć komendy `checkout -b`: - + + $ git checkout -b sc/ruby_client master Teraz jesteś gotowy do tego, aby dodać do niej udostępnione zmiany i zdecydować czy chcesz je włączyć do jednej ze swoich gałęzi. - + + ### Aplikowanie łat przychodzących e-mailem ### Jeżeli otrzymasz łatę poprzez wiadomość email, którą musisz włączyć do swojego projektu, musisz zaaplikować ją do gałęzi tematycznej w celu przetestowania. Istnieją dwa sposoby aby włączyć takie zmiany: przy użyciu `git apply` lub `git am`. - + + #### Aplikowanie łaty za pomocą komendy apply #### Jeżeli otrzymałeś łatę od kogoś kto wygenerował ją za pomocą komendy `git diff` lub uniksowej `diff`, możesz zaaplikować ją za pomocą komendy `git apply`. Zakładając, że zapisałeś plik w `/tmp/patch-ruby-client.patch`, możesz go nałożyć w taki sposób: - + + $ git apply /tmp/patch-ruby-client.patch -Ta komenda zmodyfikuje pliki znajdujące się w obecnym katalogu. Jest ona prawie identyczna do komendy `patch -p1` w celu nałożenia łaty, ale jest bardziej restrykcyjna pod względem akceptowanych zmian. Obsługuje również dodawanie plików, usuwanie, oraz zmiany nazw jeżeli zostały zapisane w formacie `git diff`, czego komenda `patch` nie zrobi. Wreszcie, `git apply` ma zasadę "zaakceptuj lub odrzuć wszystko", gdzie albo wszystko jest zaakceptowane albo nic, a `patch` może częściowo nałożyć zmiany zostawiając projekt z niespójnym stanem. Komenda `git apply` jest z zasady bardziej restrykcyjna niz `patch`. Nie stworzy za ciebie commita - po uruchomieniu, musisz zatwierdzić wprowadzone zmiany ręcznie. - +Ta komenda zmodyfikuje pliki znajdujące się w obecnym katalogu. Jest ona prawie identyczna do komendy `patch -p1` w celu nałożenia łaty, ale jest bardziej restrykcyjna pod względem akceptowanych zmian. Obsługuje również dodawanie plików, usuwanie, oraz zmiany nazw jeżeli zostały zapisane w formacie `git diff`, czego komenda `patch` nie zrobi. Wreszcie, `git apply` ma zasadę "zaakceptuj lub odrzuć wszystko", gdzie albo wszystko jest zaakceptowane albo nic, a `patch` może częściowo nałożyć zmiany zostawiając projekt z niespójnym stanem. Komenda `git apply` jest z zasady bardziej restrykcyjna niż `patch`. Nie stworzy za ciebie commita - po uruchomieniu, musisz zatwierdzić wprowadzone zmiany ręcznie. + + Możesz również użyć `git apply` aby zobaczyć, czy łata nałoży się czysto zanim ją zaaplikujesz - jeżeli uruchomiesz `git apply --check` z łatą: - + + + $ git apply --check 0001-seeing-if-this-helps-the-gem.patch error: patch failed: ticgit.gemspec:1 error: ticgit.gemspec: patch does not apply -Jeżeli nie zostanie wygenerowany żaden komunikat, to łata nałoży się poprawnie. Ta komenda również konczy działanie z niezerowym statusem w przypadku błędu, możesz więć użyć jej w skryptach jeżeli tylko checesz. - +Jeżeli nie zostanie wygenerowany żaden komunikat, to łata nałoży się poprawnie. Ta komenda również kończy działanie z niezerowym statusem w przypadku błędu, możesz więc użyć jej w skryptach jeżeli tylko chcesz. + + #### Aplikowanie łaty za pomocą am #### Jeżeli otrzymałeś łatę wygenerowaną przez użytkownika używającego Gita, który stworzył go za pomocą `format-patch`, twoja praca będzie prostsza ponieważ łatka zawiera już informacje o autorze oraz komentarz do zmiany. Jeżeli możesz, namawiaj swoich współpracowników aby używali `format-patch` zamiast `diff` do generowania dla Ciebie łat. Powinieneś móc użyć jedynie `git apply` dla takich łat. - + + Aby zaaplikować łatę wygenerowaną przez `format-patch`, użyj `git am`. Technicznie rzecz biorąc, `git am` został stworzony, aby odczytywać plik w formacie mbox, który jest prostym, tekstowym formatem zawierającym jedną lub więcej wiadomości email w jednym pliku. Wygląda on podobnie do: - + + From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001 From: Jessica Smith @@ -986,22 +861,19 @@ To apply a patch generated by `format-patch`, you use `git am`. Technically, `gi Limit log functionality to the first 20 To są pierwsze linie z wyniku komendy format-patch którą zobaczyłeś w poprzedniej sekcji. Jest to również poprawny plik w formacie mbox. Jeżeli ktoś poprawnie przesłał do Ciebie łatkę za pomocą `git send-email`, możesz ją zapisać w formacie mbox, następnie wskazać `git am` ten plik, a git zacznie aplikować wszystkie łatki które znajdzie. Jeżeli używasz klienta pocztowego, który potrafi zapisać kilka wiadomości e-mail w formacie mbox, możesz zapisać serię łatek do pliku i uzyć `git am` aby jest wszystkie nałożyć za jednym zamachem. - + + Również, jeżeli ktoś wgrał łatkę wygenerowaną poprzez `format-patch` do bugtrakera lub podobnego, możesz zapisać lokalnie ten plik i potem przekazać go do `git am` aby zaaplikować go: - + + $ git am 0001-limit-log-function.patch Applying: add limit to log function Możesz zobaczyć, że został czysto nałożony i automatycznie skomitowany. Informacje o autorze zostały pobrane z wiadomości e-mail z nagłówków `From` i `Date`, a treść komentarz została pobrana z tematu i treści (przed łatką) e-maila. Na przykład, jeżeli ta łatka została zaaplikowana z pliku mbox który przed chwilą pokazałem, wygenerowany commit będzie wygląda podobnie do: - + + $ git log --pretty=fuller -1 commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0 @@ -1016,14 +888,12 @@ You can see that it applied cleanly and automatically created the new commit for Linie zaczynające się od `Commit` pokazują osobę która zaaplikowała łatkę oraz czas kiedy to zrobiła. Linie rozpoczynające się od `Author` pokazują osobę która stworzyła łatę wraz z dokładną datę. - -Jednak możliwa jest również sytuacja, w której łatka nie zostanie bez problemów nałożona. Byćmoże twoja gałąź zbyt mocno się zmieniła, w stosunku do gałęzi na której łatka została stworzona, albo zależna jest ona od innej łatki której jeszcze nie nałożyłeś. W takiej sytuacji `git am` zakończy się błędem i zapyta co robić dalej: - + + +Jednak możliwa jest również sytuacja, w której łatka nie zostanie bez problemów nałożona. Być może twoja gałąź zbyt mocno się zmieniła, w stosunku do gałęzi na której łatka została stworzona, albo zależna jest ona od innej łatki której jeszcze nie nałożyłeś. W takiej sytuacji `git am` zakończy się błędem i zapyta co robić dalej: + + $ git am 0001-seeing-if-this-helps-the-gem.patch Applying: seeing if this helps the gem @@ -1034,10 +904,9 @@ But it’s possible that the patch won’t apply cleanly. Perhaps your main bran If you would prefer to skip this patch, instead run "git am --skip". To restore the original branch and stop patching run "git am --abort". -Ta komenda zaznacza pliku z którymi miała problemy, podobnie do konflików występujących podczas komend `merge` lub `rebase`. Rozwiązujesz takie sytuacja również analogicznie - wyedytuj plik w celu rozwiązania konfliktu, dodaj do przechowalni nowe pliki i następnie uruchom `git am --resolved` aby kontynuować działanie do następnej łatki: - +Ta komenda zaznacza pliku z którymi miała problemy, podobnie do konfliktów występujących podczas komend `merge` lub `rebase`. Rozwiązujesz takie sytuacja również analogicznie - wyedytuj plik w celu rozwiązania konfliktu, dodaj do przechowalni nowe pliki i następnie uruchom `git am --resolved` aby kontynuować działanie do następnej łatki: + + $ (fix the file) $ git add ticgit.gemspec @@ -1045,9 +914,8 @@ This command puts conflict markers in any files it has issues with, much like a Applying: seeing if this helps the gem Jeżeli chcesz aby Git spróbował w bardziej inteligentny sposób rozwiązać konflikty, dodaj opcję `-3` do komendy, która daje Gitowi możliwość spróbowania trójstronnego łączenia. Opcja ta nie jest domyślnie włączona, ponieważ nie działa poprawnie w sytuacji gdy w twoim repozytorium nie ma commitu na którym bazuje łata. Jeżeli go masz - jeżeli łatka bazowała na publicznym commit-cie - to dodanie `-3` zazwyczaj pozwala na dużo mądrzejsze zaaplikowanie konfliktującej łatki: - + + $ git am -3 0001-seeing-if-this-helps-the-gem.patch Applying: seeing if this helps the gem @@ -1058,14 +926,12 @@ If you want Git to try a bit more intelligently to resolve the conflict, you can No changes -- Patch already applied. W tej sytuacji, próbowałem zaaplikować łatkę którą już wcześniej włączyłem. Bez podanej opcji `-3` wyglądało to na konflikt. - -Jeżeli włączasz większą liczbę łat z pliku mbox, możesz użyć komendy `am` w trybie interaktywnym, który zatrzymuje się na kazdej łacie którą znajdzie i pyta czy chcesz ją zaaplikować: - + + +Jeżeli włączasz większą liczbę łat z pliku mbox, możesz użyć komendy `am` w trybie interaktywnym, który zatrzymuje się na każdej łacie którą znajdzie i pyta czy chcesz ją zaaplikować: + + $ git am -3 -i mbox Commit Body is: @@ -1075,50 +941,42 @@ If you’re applying a number of patches from an mbox, you can also run the `am` Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all Jest to całkiem dobre jeżeli masz zapisaną większą liczbę łat, ponieważ możesz najpierw zobaczyć łatę jeżeli nie pamiętasz do czego była, lub nie aplikować jej jeżeli już to zrobiłeś. - -Kiedy wszystkie łatki zostaną wgrane i commitniete w twojej gałęzi, możesz zastanowić się w jaki sposób i czy chcesz integrować je do jednej z głównych gałęzi. - + + +Kiedy wszystkie łatki zostaną wgrane i commitnięte w twojej gałęzi, możesz zastanowić się w jaki sposób i czy chcesz integrować je do jednej z głównych gałęzi. + + ### Sprawdzanie zdalnych gałęzi ### Jeżeli zmiana przyszła od użytkownika Gita który ma skonfigurowane własne repozytorium, wgrał do niego już jakąś liczbę zmian i następnie wysłał do Ciebie adres URL repozytorium oraz nazwę zdalnej gałęzi zawierającej zmiany, możesz ją dodać jako zdalną i połączyć zmiany lokalnie. - + + Na przykład, jeżeli Jessica wysyła Ci wiadomość e-mail w której pisze, że ma nową funkcjonalność w gałęzi `ruby-client` w swoim repozytorium, możesz je przetestować dodając zdalne repozytorium i sprawdzając tą gałąź lokalnie: - + + $ git remote add jessica git://github.com/jessica/myproject.git $ git fetch jessica $ git checkout -b rubyclient jessica/ruby-client Jeżeli napisze do Ciebie ponownie z nową gałęzią która zawiera kolejną funkcjonalność, możesz ją pobrać i sprawdzić ponieważ masz już dodane zdalne repozytorium. - + + Jest to bardzo pomocne w sytuacji, w której współpracujesz z jakąś osobą na stałe. Jeżeli ktoś ma tylko pojedyncze łatki które udostępnia raz na jakiś czas, to akceptowanie ich poprzez e-mail może być szybsze, niż zmuszanie wszystkich do tego aby mieli własny serwer, jak również dodawanie i usuwanie zdalnych repozytoriów aby otrzymać jedną lub dwie łatki. Jednakże, skrypty oraz usługi udostępniane mogą uczynić to prostszym - zależy od tego w taki sposób pracujesz, oraz jak pracują Twoi współpracownicy. - + + Kolejną zaletą takiego podejścia jest to, że otrzymujesz również całą historię zmian. Chociaż mogą zdarzyć się uzasadnione problemy ze scalaniem zmian, wiesz na którym etapie historii ich praca bazowała; prawidłowe trójstronne scalenie jest domyślne, nie musisz więc podawać `-3` i mieć nadzieję że łatka została wygenerowana z publicznie dostępnego commitu/zmiany. - + + Jeżeli nie współpracujesz z jakąś osobą na stałe, ale mimo wszystko chcesz pobrać od niej zmiany w ten sposób, możesz podać URL repozytorium do komendy `git pull`. Wykona ona jednokrotne zaciągnięcie zmian i nie zapisze URL repozytorium jako zdalnego: - + + $ git pull git://github.com/onetimeguy/project.git From git://github.com/onetimeguy/project @@ -1128,14 +986,12 @@ If you aren’t working with a person consistently but still want to pull from t ### Ustalenie co zostało wprowadzone ### Teraz posiadać gałąź tematyczną która zawiera otrzymane zmiany. W tym momencie możesz zdecydować co chcesz z nimi zrobić. Ta sekcja przywołuje kilka komend, tak abyś mógł zobaczyć w jaki sposób ich użyć, aby przejrzeć dokładnie co będziesz włączał do głównej gałęzi. - + + Często pomocne jest przejrzenie wszystkich zmian które są w tej gałęzi, ale nie ma ich w gałęzi master. Możesz wyłączyć zmiany z gałęzi master poprzez dodanie opcji `--not` przed jej nazwą. Na przykład, jeżeli twój współpracownik prześle ci dwie łaty, a ty stworzysz nową gałąź `contrib` i włączysz te łatki tam, możesz uruchomić: - + + $ git log contrib --not master commit 5b6235bd297351589efc4d73316f0a68d484f118 @@ -1150,37 +1006,31 @@ It’s often helpful to get a review of all the commits that are in this branch updated the gemspec to hopefully work better -ABy zobaczyć jakie zmiany każdy z commitów wniósł, zapamiętaj że możesz dodać opcję `-p` do `git log`, a otrzymasz również w wyniku różnice w kodzie. - +Aby zobaczyć jakie zmiany każdy z commitów wniósł, zapamiętaj że możesz dodać opcję `-p` do `git log`, a otrzymasz również w wyniku różnice w kodzie. + + Aby zobaczyć różnice tego co się stanie, jeżeli chciałbyś połączyć tą gałąź z inną, będziesz musiał użyć całkiem ciekawych sztuczek aby otrzymać poprawne wyniki. Możesz pomyśleć, aby uruchomić: - + + $ git diff master Ta komenda pokaże ci różnice w kodzie, ale może to być mylące. Jeżeli twoja gałąź `master` zmieniła się od czasu stworzenia gałęzi tematycznej, otrzymasz dziwne wyniki. Tak dzieje się dlatego, ponieważ Git porównuje bezpośrednio ostatnią migawkę z gałęzi tematycznej, z ostatnią migawkę w gałęzi `master`. Na przykład, jeżeli dodasz linię w pliku w gałęzi `master`, bezpośrednie porównanie pokaże, że gałąż tematyczna zamierza usunąć tą linię. - + + Jeżeli `master` jest bezpośrednim przodkiem twojej gałęzi tematycznej, nie stanowi to problemu; jeżeli jednak obie linie się rozjechały, wynik `diff` pokaże dodawane wszystkie zmiany z gałęzi tematycznej, a usuwane wszystkie unikalne z `master`. - + + Wynik którego naprawdę oczekujesz, to ten, pokazujący zmiany będące w gałęzi tematycznej - zmiany które wprowadzisz jeżeli scalisz tą gałąź z master. Możesz to zrobić, poprzez porównanie ostatniego commitu z gałęzi tematycznej, z pierwszym wspólnym przodkiem z gałęzi master. - + + Technicznie rzecz ujmując, możesz to zrobić poprzez wskazanie wspólnego przodka i uruchomienie na nim diff: - + + $ git merge-base contrib master 36c7dba2c95e6bbb78dfa822519ecfec6e1ca649 @@ -1188,127 +1038,108 @@ Technically, you can do that by explicitly figuring out the common ancestor and Jednak to nie jest wygodne rozwiązanie, dlatego Git udostępnia krótszą metodę aby to osiągnąć: składnie z potrójną kropką. W kontekście komendy `diff`, możesz wstawić trzy kropki po nazwie gałęzi z którą chcesz porównać, aby otrzymać różnice z ostatniej zmiany z gałęzi na której się znajdujesz a wspólnym przodkiem tej drugiej. - + + $ git diff master...contrib Ta komenda pokaże zmiany wprowadzone tylko w gałęzi tematycznej, od czasu jej stworzenia. Jest to bardzo użyteczna składnia warta zapamiętania. - + + ### Integrowanie otrzymanych zmian ### Kiedy zakończysz prace nad zmianami w gałęzi tematycznej i będą one gotowe do włączenia do głównej, pozostaje pytanie w jaki sposób to zrobić. Ponadto, jaki rodzaj przepływu pracy chcesz stosować w swoim projekcie? Masz różne możliwości, opiszę więc kilka z nich. - + + #### Przepływ pracy podczas scalania zmian #### Jednym z prostszych przepływów pracy jest scalenie zmian z twoją gałęzią `master`. W tym scenariuszu, posiadasz gałąź `master` która zawiera stabilny kod. Kiedy masz zmiany w jednej z gałęzi tematycznych które wykonałeś, lub ktoś Ci przesłał a Ty je zweryfikowałeś, scalasz je z gałęzią `master`, usuwasz gałąź i kontynuujesz pracę. Jeżeli mielibyśmy repozytorium ze zmianami w dwóch gałęziach `ruby_client` oraz `php_client` (zob. rys. 5-19) i mielibyśmy scalić najpierw `ruby_client`, a w następnej kolejności `php_client`, to twoja historia zmian wyglądała by podobnie do rys. 5-20. - + + Insert 18333fig0519.png Figure 5-19. Historia zmian z kilkoma gałęziami tematycznymi. - + + Insert 18333fig0520.png Figure 5-20. Po scaleniu gałęzi. - + + To jest prawdopodobnie najprostszy schamat pracy, ale jest on również problematyczny jeżeli masz do czynienia z dużymi repozytoriami lub projektami. - + + Jeżeli masz większą ilość deweloperów lub większy projekt, będziesz chciał pewnie używał przynajmniej dwufazowego cyklu scalania. W tym scenariuszu, posiadasz dwie długodystansowe gałęzie `master` oraz `develop`, z których `master` jest aktualizowana tylko z bardzo stabilnymi zmianami, a cały nowy kod jest włączany do gałęzi `develop`. Regularnie wysyłasz ("push") obie te gałęzie do publicznego repozytorium. Za każdym razem gdy masz nową gałąź tematyczną do zintegrowania (rys. 5-21), włączasz ją do `develop` (rys. 5-22); a kiedy tagujesz kolejną wersję, przesuwasz `master` za pomocą fast-forward o punktu w którym jest gałąź `develop`(rys. 5-23). - + + Insert 18333fig0521.png Figure 5-21. Przed scaleniem gałęzi tematycznej. - + + Insert 18333fig0522.png Figure 5-22. Po scaleniu gałęzi tematycznej. - + + Insert 18333fig0523.png Figure 5-23. Po utworzeniu kolejnej wersji. - + + W ten sposób, kiedy ludzie klonują twoje repozytorium, mogą albo pobrać `master` aby zbudować najnowszą stabilną wersję i utrzymywać ją uaktualnioną, lub mogą pobrać `develop` która zawiera mniej stabilne zmiany. Możesz rozbudować tą koncepcję, poprzez dodanie gałęzi służącej do integracji. Wtedy jeżeli kod w znajdujący się w niej jest stabilny i przechodzi wszystkie testy, scalasz ją do gałęzi `develop`; a jeżeli ta okaże się również stabilna, przesuwasz `master` za pomocą fast-forward. - + + #### Large-Merging Workflows #### Projekt Gita ma cztery długodystansowe gałęzie: `master`, `next`, `pu` (proponowane zmiany) dla nowych funkcjonalności, oraz `maint` do wprowadzania zmian wstecznych. Kiedy nowe zmiany są dostarczone przez deweloperów, zbierane są do gałęzi tematycznych w repozytorium opiekuna, w sposób podobny do tego który opisałem (zob. rys. 5-24). W tym momencie, są one weryfikowane i sprawdzane czy mogą być użyte, lub czy nadal wymagają dalszych prac. Jeżeli są gotowe, są włączona do `next`, a ta gałąź jest wypychana dalej, tak aby każdy mógł wypróbować nowe funkcjonalności. - + + Insert 18333fig0524.png -Figure 5-24. Zarządzanie złożoną serią równocesnych zmian w gałęziach tematycznych. - +Figure 5-24. Zarządzanie złożoną serią równoczesnych zmian w gałęziach tematycznych. + + Jeżeli funkcjonalność potrzebuje jeszcze kolejnych zmian, są one włączane do gałęzi `pu`. Kiedy okaże się, że cały kod działa już poprawnie, zmiany są włączane do `master` oraz przebudowywane włącznie ze zmianami z gałęzi `next`, które nie znalazły się jeszcze w `master`. Oznacza to, że `master` praktycznie zawsze przesuwa się do przodu, `next` tylko czasami ma zmienianą bazę poprzez "rebase", a `pu` najczęściej z nich może się przesunąć w innym kierunku (zob. rys. 5-25). - + Insert 18333fig0525.png -Figure 5-25. Włączanie gałęzi tematycznych do gałezi długodystansowych. - +Figure 5-25. Włączanie gałęzi tematycznych do gałęzi długodystansowych. + Z chwilą, gdy gałąź tematycznie zostanie włączona do `master`, jest usuwana z repozytorium. Projekt Gita ma również gałąź `maint`, która jest tworzona z ostatniej wersji, w celu dostarczania zmian w sytuacji gdy trzeba wydać wersję poprawkową. Dlatego kopiując repozytorium Gita masz cztery gałęzie, w których możesz zobaczyć projekt w różnych stadiach rozwoju, w zależności od tego jak stabilny kod chcesz używać, lub nad którym pracować; a opiekun ma ułatwiony przepływ zmian pomagający panować nad nowymi zmianami. - + + #### Zmiana bazy oraz wybiórcze pobieranie zmian #### Część opiekunów woli używać "rebase" lub "cherry-pick" w celu włączania zmian w gałęzi master, zamiast przy użyciu "merge", aby zachować bardziej liniową historię. Kiedy masz zmiany w gałęzi tematycznej i decydujesz się zintegrować je, przenosisz gałąź i uruchamiasz "rebase" aby nałożyć zmiany na górze swojej gałęzi master (lub `develop`, czy innej). Jeżeli to zadziała poprawnie, możesz przesunąć swoją gałąź `master` i otrzymasz praktycznie liniową historię. - -Drugim sposobem na przeniesienie zmian z jednej gałęzi do drugiej jest zrobienie tego za pomocą komendy `cherry-pick`. Komenda ta jest podobna do `rebase`, ale dla pojedynczej zmiany. Pobiera ona zmianę która została wprowadzona i próbóje ją ponownie nałożyć na gałąź na której obecnie pracujesz. Jest to całkiem przydatne, w sytuacji gdy masz większą ilość zmian w gałęzi tematycznej, a chcesz zintegrować tylko jedną z nich, lub jeżeli masz tylko jedną zmianę w gałęzi i wolisz używać cherry-pick zamiast rebase. Dla przykładu, załóżmy że masz projekt który wygląda podobnie do rys. 5-26. - + + +Drugim sposobem na przeniesienie zmian z jednej gałęzi do drugiej jest zrobienie tego za pomocą komendy `cherry-pick`. Komenda ta jest podobna do `rebase`, ale dla pojedynczej zmiany. Pobiera ona zmianę która została wprowadzona i próbuje ją ponownie nałożyć na gałąź na której obecnie pracujesz. Jest to całkiem przydatne, w sytuacji gdy masz większą ilość zmian w gałęzi tematycznej, a chcesz zintegrować tylko jedną z nich, lub jeżeli masz tylko jedną zmianę w gałęzi i wolisz używać cherry-pick zamiast rebase. Dla przykładu, załóżmy że masz projekt który wygląda podobnie do rys. 5-26. + + Insert 18333fig0526.png Figure 5-26. Przykładowa historia przez wybiórczym zaciąganiem zmian. + Jeżeli chcesz pobrać zmianę `e43a6` do swojej gałęzi master, możesz uruchomić: - + + $ git cherry-pick e43a6fd3e94888d76779ad79fb568ed180e5fcdf Finished one cherry-pick. @@ -1316,27 +1147,23 @@ If you want to pull commit `e43a6` into your master branch, you can run 3 files changed, 17 insertions(+), 3 deletions(-) To pobierze tylko zmiany z commita `e43a6`, ale otrzyma nową sumę SHA-1, ze względu na nową datę nałożenia. Teraz Twoja historia wygląda podobnie do rysunku 5-27. - + + Insert 18333fig0527.png Figure 5-27. Historia po wybiórczym zaciągnięciu zmiany z gałęzi tematycznej. - + + Teraz możesz usunąć swoją gałąź tematyczną, oraz zmiany których nie chciałeś pobierać. - + + ### Tagowanie Twoich Wersji ### Kiedy zdecydowałeś, że wydasz nową wersję, najprawdopodobniej będziesz chciał stworzyć taga, tak abyś mógł odtworzyć tą wersję w każdym momencie. Możesz stworzyć nowego taga, tak jak zostało to opisane w rozdziale 2. Jeżeli zdecydujesz się na utworzenie taga jako opiekun, komenda powinna wyglądać podobnie do: - + + $ git tag -s v1.5 -m 'my signed 1.5 tag' You need a passphrase to unlock the secret key for @@ -1344,9 +1171,8 @@ When you’ve decided to cut a release, you’ll probably want to drop a tag so 1024-bit DSA key, ID F721C45A, created 2009-02-09 Jeżeli podpisujesz swoje tagi, możesz mieć problem z dystrybucją swojego publicznego klucza PGP, który został użyty. Można rozwiązać ten problem poprzez dodanie obiektu binarnego (ang. blob) w repozytorium, a następnie stworzenie taga kierującego dokładnie na jego zawartość. Aby to zrobić, musisz wybrać klucz za pomocą komendy `gpg --list-keys`: - + + $ gpg --list-keys /Users/schacon/.gnupg/pubring.gpg @@ -1357,82 +1183,74 @@ If you do sign your tags, you may have the problem of distributing the public PG Następnie, możesz bezpośrednio zaimportować wybrany klucz do Gita, poprzez eksport i przekazanie go do `git hash-object`, który zapisuje nowy obiekt binarny i zwraca jego sumę SHA-1: - + + $ gpg -a --export F721C45A | git hash-object -w --stdin 659ef797d181633c87ec71ac3f9ba29fe5775b92 Teraz, gdy masz zawartość swojego klucza w Gitcie, możesz utworzyć taga wskazującego bezpośrednio na ten klucz, poprzez podanie sumy SHA-1 zwróconej przez `hash-object`: - + + + $ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92 Po uruchomieniu `git push --tags`, etykieta `maintainer-pgp-pub` zostanie udostępniona dla wszystkich. Jeżeli ktoś chciałby zweryfikować etykietę, może bezpośrednio zaimportować twój klucz PGP poprzez pobranie zawartości z gita i import do GPG: - + + $ git show maintainer-pgp-pub | gpg --import Możesz używać tego klucza do weryfikacji wszystkich podpisanych etykiet. Możesz również dodać do komentarza do etykiety dodatkowe informacje, które będą możliwe do odczytania po uruchomieniu `git show ` i pozwolą na prostszą weryfikację. - + + ### Generowanie numeru kompilacji ### + Ponieważ Git nie zwiększa stale numerów, np. 'v123' lub w podobny sposób, jeżeli chcesz mieć łatwiejszą do używania nazwę dla konkretnej zmiany, możesz uruchomić `git describe` na commitcie. Git poda Ci nazwę najbliższej etykiety, wraz z ilością zmian, oraz skróconą sumą SHA-1: - + + $ git describe master v1.6.2-rc1-20-g8c5b85c W ten sposób, możesz udostępnić konkretną wersję lub kompilację pod nazwą łatwiejszą do użycia przez ludzi. W rzeczywistości, jeżeli masz Gita zbudowanego ze źródeł pobranych z jego repozytorium, komenda `git --version` pokaże wynik podobny do powyższego. Jeżeli zamierzasz opisać zmianę którą bezpośrednio zatagowałeś, pokaże ona nazwę taga. - + + Komenda `git describe` faworyzuje etykiety stworzone przy użyciu opcji `-a` lub `-s`, więc etykiety dotyczące konkretnych wersji powinny być tworzone w ten sposób, jezeli używasz `git describe` w celu zapewnienia poprawnych nazw commitów. Możesz również używać tej nazwy do komend "checkout" lub "show", choć polegają one na skróconej wartości SHA-1, mogą więc nie być wiecznie poprawne. Na przykład, projekt jądra Linuksa przeszedł ostatnio z 8 na 10 znaków aby zapewnić unikalność sum SHA-1, więc poprzednie nazwy wygenerowane za pomocą `git describe` zostały unieważnione. - + + ### Przygotowywanie nowej wersji ### + Teraz chcesz stworzyć nową wersję. Jedną z rzeczy które będziesz musiał zrobić, jest przygotowanie spakowanego archiwum z ostatnią zawartością kodu, dla tych, którzy nie używają Gita. Komenda która to umożliwia to `git archive`: - + + $ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz $ ls *.tar.gz v1.6.2-rc1-20-g8c5b85c.tar.gz Jeżeli ktoś otworzy spakowany plik, otrzyma ostatnią wersję kodu w podkatalogu z nazwą projektu. Możesz również stworzyć archiwum zip w podobny sposób, dodając parametr `--format=zip` do `git archive`: - + + $ git archive master --prefix='project/' --format=zip > `git describe master`.zip Masz teraz spakowane pliki projektu w formatach tar i zip, które możesz łatwo wgrać na serwer lub wysłać do ludzi. - + + ### Komenda Shortlog ### Nadszedł czas aby wysłać na listę dyskusyjną - + + $ git shortlog --no-merges master --not v1.0.1 Chris Wanstrath (8): @@ -1450,13 +1268,11 @@ It’s time to e-mail your mailing list of people who want to know what’s happ Regenerated gemspec for version 1.0.2 Możesz pobrać podsumowanie wszystkich zmian począwszy od wersji v1.0.1 pogrupowanych po autorze, które jest gotowe do wysłania na listę. - + + ## Podsumowanie ## Powinieneś się teraz czuć całkiem swobodnie uczestnicząc w projekcie używając Gita, zarówno jako opiekun własnego projektu jak również, integrator zmian dostarczonych przez innych użytkowników. Gratulacje! Właśnie stałeś się skutecznym deweloperem używającym Gita! W kolejnym rozdziale, nauczysz się bardziej zaawansowanych narzędzi oraz rozwiązywania złożonych sytuacji, które uczynią z ciebie prawdziwego mistrza. - + +