Przepływ pracy Git to przepis lub zalecenie, jak używać Git do wykonania pracy w spójny i produktywny sposób. Przepływy pracy Git zachęcają użytkowników do efektywnego i konsekwentnego korzystania z Git. Git oferuje dużą elastyczność w sposobie zarządzania zmianami. Biorąc pod uwagę, że Git skupia się na elastyczności, nie ma standardowego procesu, jak współdziałać z Gitem. Podczas pracy z zespołem nad projektem zarządzanym przez Git, ważne jest, aby upewnić się, że wszyscy zgadzają się co do tego, w jaki sposób przepływ zmian będzie stosowany. Aby upewnić się, że zespół jest po tej samej stronie, należy opracować lub wybrać uzgodniony przepływ pracy Git. Istnieje kilka upublicznionych przepływów pracy Git, które mogą być dobrym rozwiązaniem dla Twojego zespołu. Tutaj omówimy niektóre z tych opcji przepływu pracy.
Szeroki wachlarz możliwych przepływów pracy może sprawić, że nie wiadomo, od czego zacząć, wdrażając Git w miejscu pracy. Ta strona stanowi punkt wyjścia do przeglądu najczęściej spotykanych przepływów pracy z Gitem w zespołach programistycznych.
Podczas lektury pamiętaj, że te przepływy pracy zostały zaprojektowane jako wskazówki, a nie konkretne zasady. Chcemy pokazać Ci, co jest możliwe, więc możesz mieszać i łączyć aspekty różnych przepływów pracy, aby dopasować je do swoich indywidualnych potrzeb.
Jaki jest udany przepływ pracy Git?
Podczas oceny przepływu pracy dla Twojego zespołu, najważniejsze jest, abyś wziął pod uwagę kulturę zespołu. Chcesz, aby przepływ pracy zwiększał efektywność zespołu, a nie był ciężarem, który ogranicza produktywność. Niektóre rzeczy, które należy rozważyć podczas oceny przepływu pracy Git to:
- Czy ten przepływ pracy skaluje się wraz z wielkością zespołu?
- Czy łatwo jest cofnąć błędy i pomyłki za pomocą tego przepływu pracy?
- Czy ten przepływ pracy nakłada na zespół jakiekolwiek nowe, niepotrzebne koszty poznawcze?
Scentralizowany przepływ pracy
Scentralizowany przepływ pracy jest świetnym przepływem Gita dla zespołów przechodzących z SVN. Podobnie jak Subversion, scentralizowany przepływ pracy wykorzystuje centralne repozytorium, które służy jako pojedynczy punkt wejścia dla wszystkich zmian w projekcie. Zamiast trunk
, domyślna gałąź rozwojowa nazywa się master
i wszystkie zmiany są przekazywane do tej gałęzi. Ten przepływ pracy nie wymaga żadnych innych gałęzi poza master
.
Przejście na rozproszony system kontroli wersji może wydawać się trudnym zadaniem, ale nie trzeba zmieniać istniejącego przepływu pracy, aby wykorzystać zalety Gita. Twój zespół może rozwijać projekty w dokładnie taki sam sposób, jak przy użyciu Subversion.
Jednakże użycie Git do zasilania przepływu pracy deweloperskiej ma kilka zalet w porównaniu z SVN. Po pierwsze, daje każdemu programiście jego własną, lokalną kopię całego projektu. To odizolowane środowisko pozwala każdemu programiście pracować niezależnie od wszystkich innych zmian w projekcie – może on dodawać commity do swojego lokalnego repozytorium i całkowicie zapomnieć o rozwoju w górę rzeki, dopóki nie będzie to dla niego wygodne.
Po drugie, daje dostęp do solidnego modelu rozgałęziania i łączenia Git. W przeciwieństwie do SVN, gałęzie Git są zaprojektowane jako bezpieczny mechanizm integracji kodu i dzielenia się zmianami pomiędzy repozytoriami. Scentralizowany przepływ pracy jest podobny do innych przepływów pracy, ponieważ wykorzystuje zdalne repozytorium hostowane po stronie serwera, z którego programiści korzystają i z którego korzystają. W porównaniu z innymi przepływami, scentralizowany przepływ pracy nie ma zdefiniowanych wzorców żądań pull czy rozwidlania. Scentralizowany przepływ pracy lepiej nadaje się dla zespołów migrujących z SVN do Git oraz dla zespołów o mniejszym rozmiarze.
Jak to działa
Deweloperzy zaczynają od sklonowania centralnego repozytorium. W swoich lokalnych kopiach projektu edytują pliki i wprowadzają zmiany, tak jak w SVN, ale te nowe commit’y są przechowywane lokalnie – są całkowicie odizolowane od centralnego repozytorium. Pozwala to programistom odroczyć synchronizację do momentu, gdy znajdą się w dogodnym punkcie przerwania pracy.
Aby opublikować zmiany w oficjalnym projekcie, programiści „wypychają” swoją lokalną gałąź master
do centralnego repozytorium. Jest to odpowiednik svn commit
, z tą różnicą, że dodaje wszystkie lokalne commity, które nie są jeszcze w centralnej gałęzi master
.
Inicjalizacja centralnego repozytorium
Po pierwsze, ktoś musi utworzyć centralne repozytorium na serwerze. Jeśli jest to nowy projekt, można zainicjować puste repozytorium. W przeciwnym razie trzeba będzie zaimportować istniejące repozytorium Git lub SVN.
Centralne repozytoria powinny być zawsze gołymi repozytoriami (nie powinny mieć katalogu roboczego), które można utworzyć w następujący sposób:
ssh user@host git init --bare /path/to/repo.git
Pewnie użyj poprawnej nazwy użytkownika SSH dla user
, domenę lub adres IP Twojego serwera dla host
, oraz lokalizację, w której chcesz przechowywać swoje repo dla /path/to/repo.git
. Zauważ, że rozszerzenie .git
jest konwencjonalnie dodawane do nazwy repozytorium, aby wskazać, że jest to gołe repozytorium.
Hostowane centralne repozytoria
Centralne repozytoria są często tworzone za pośrednictwem usług hostingowych Git innych firm, takich jak Bitbucket Cloud lub Bitbucket Server. Proces inicjalizacji gołego repozytorium omówiony powyżej jest obsługiwany za Ciebie przez usługę hostingową. Usługa hostingowa dostarczy następnie adres dla centralnego repozytorium, aby uzyskać do niego dostęp z twojego lokalnego repozytorium.
Klonowanie centralnego repozytorium
Następnie, każdy deweloper tworzy lokalną kopię całego projektu. Odbywa się to za pomocą polecenia git clone
:
git clone ssh://user@host/path/to/repo.git
Kiedy klonujesz repozytorium, Git automatycznie dodaje skrót o nazwie origin
, który wskazuje z powrotem na repozytorium „macierzyste”, zakładając, że będziesz chciał z nim dalej współdziałać.
Wprowadzanie zmian i commit
Po sklonowaniu repozytorium lokalnie, programista może wprowadzać zmiany używając standardowego procesu Git commit: edit, stage, and commit. Jeśli nie jesteś zaznajomiony z obszarem staging, jest to sposób na przygotowanie commitu bez konieczności dołączania każdej zmiany do katalogu roboczego. Pozwala to na tworzenie bardzo precyzyjnych commitów, nawet jeśli dokonałeś wielu lokalnych zmian.
git status # View the state of the repo git add # Stage a file git commit # Commit a file
Pamiętaj, że ponieważ te polecenia tworzą lokalne commity, John może powtarzać ten proces tyle razy, ile chce, nie martwiąc się o to, co dzieje się w centralnym repozytorium. Może to być bardzo przydatne w przypadku dużych funkcjonalności, które muszą być podzielone na prostsze, bardziej atomowe kawałki.
Push new commits do centralnego repozytorium
Od momentu, gdy w lokalnym repozytorium pojawią się nowe zmiany. Te zmiany będą musiały zostać wypchnięte, aby podzielić się nimi z innymi deweloperami w projekcie.
git push origin master
Ta komenda wypchnie nowe popełnione zmiany do centralnego repozytorium. Podczas pchania zmian do centralnego repozytorium, możliwe jest, że aktualizacje od innego dewelopera zostały wcześniej pchnięte, które zawierają kod, który jest sprzeczny z zamierzonymi aktualizacjami push. Git wyświetli komunikat wskazujący na ten konflikt. W tej sytuacji najpierw trzeba będzie wykonać git pull
. Ten scenariusz konfliktu zostanie rozwinięty w następnej sekcji.
Zarządzanie konfliktami
Centralne repozytorium reprezentuje oficjalny projekt, więc jego historia commitów powinna być traktowana jako święta i niezmienna. Jeśli lokalne zobowiązania dewelopera odbiegają od centralnego repozytorium, Git odmówi wypchnięcia jego zmian, ponieważ spowodowałoby to nadpisanie oficjalnych commitów.
Zanim deweloper będzie mógł opublikować swoją funkcję, musi pobrać zaktualizowane centralne commity i ponownie osadzić na nich swoje zmiany. To tak, jakby powiedzieć: „Chcę dodać moje zmiany do tego, co wszyscy inni już zrobili”. W rezultacie otrzymujemy idealnie liniową historię, tak jak w tradycyjnych przepływach pracy SVN.
Jeśli lokalne zmiany bezpośrednio kolidują z commitami upstream, Git wstrzyma proces rebase i da szansę na ręczne rozwiązanie konfliktów. Miłą rzeczą w Gicie jest to, że używa on tych samych poleceń git status
i git add
zarówno do generowania commitów jak i rozwiązywania konfliktów scalania. Ułatwia to nowym programistom zarządzanie ich własnymi scaleniami. Dodatkowo, jeśli wpadną w kłopoty, Git sprawia, że bardzo łatwo jest przerwać cały rebase i spróbować ponownie (lub poszukać pomocy).
Przykład
Patrzmy na ogólny przykład, jak typowy mały zespół mógłby współpracować używając tego przepływu pracy. Zobaczymy jak dwóch programistów, John i Mary, może pracować nad oddzielnymi funkcjami i dzielić się swoimi wkładami poprzez scentralizowane repozytorium.
John pracuje nad swoją funkcją
W swoim lokalnym repozytorium John może rozwijać cechy używając standardowego procesu Git commit: edit, stage, and commit.
Pamiętaj, że ponieważ te polecenia tworzą lokalne polecenia, John może powtarzać ten proces tyle razy ile chce, nie martwiąc się o to co dzieje się w centralnym repozytorium.
Mary pracuje nad swoją cechą
W międzyczasie Mary pracuje nad swoim własnym elementem w swoim lokalnym repozytorium, używając tego samego procesu edit/stage/commit. Podobnie jak John, Mary nie dba o to, co dzieje się w centralnym repozytorium i naprawdę nie obchodzi jej, co John robi w swoim lokalnym repozytorium, ponieważ wszystkie lokalne repozytoria są prywatne.
John publikuje swoją funkcjonalność
Kiedy John skończy swoją funkcjonalność, powinien opublikować swoje lokalne commity w centralnym repozytorium, aby inni członkowie zespołu mieli do nich dostęp. Może to zrobić za pomocą polecenia git push
, w następujący sposób:
git push origin master
Pamiętaj, że origin
to zdalne połączenie z centralnym repozytorium, które Git utworzył, gdy John je sklonował. Argument master
mówi Gitowi, aby spróbował sprawić, by origin
gałąź master
wyglądała jak jego lokalna master
gałąź. Ponieważ centralne repozytorium nie było aktualizowane od czasu sklonowania go przez Johna, nie spowoduje to żadnych konfliktów, a push będzie działał zgodnie z oczekiwaniami.
Mary próbuje opublikować swój feature
Zobaczmy, co się stanie, jeśli Mary spróbuje opublikować swój element po tym, jak John pomyślnie opublikuje swoje zmiany w centralnym repozytorium. Może użyć dokładnie tego samego polecenia push:
git push origin master
Ale ponieważ jej lokalna historia odbiegła od centralnego repozytorium, Git odrzuci żądanie z dość dosadnym komunikatem o błędzie:
error: failed to push some refs to '/path/to/repo.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Merge the remote changes (e.g. 'git pull') hint: before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
To uniemożliwia Mary nadpisanie oficjalnych commitów. Musi ona ściągnąć aktualizacje Johna do swojego repozytorium, zintegrować je ze swoimi lokalnymi zmianami, a następnie spróbować ponownie.
Mary rebases on top of John’s commit(s)
Mary może użyć git pull
aby włączyć zmiany upstream do swojego repozytorium. To polecenie jest podobne do svn update
– ściąga całą historię commitów upstreamu do lokalnego repozytorium Mary i próbuje zintegrować ją z jej lokalnymi commitami:
git pull --rebase origin master
Opcja --rebase
mówi Gitowi, aby przeniósł wszystkie commity Mary do końcówki gałęzi master
po zsynchronizowaniu jej ze zmianami z centralnego repozytorium, jak pokazano poniżej:
Wciąganie nadal działałoby, gdybyś zapomniał o tej opcji, ale skończyłoby się na zbędnym „merge commit” za każdym razem, gdy ktoś potrzebowałby synchronizacji z centralnym repozytorium. Dla tego przepływu pracy, zawsze lepiej jest zrobić rebase zamiast generować merge commit.
Mary rozwiązuje konflikt scalania
Rebasing działa przez przeniesienie każdego lokalnego commitu do zaktualizowanej master
gałęzi po jednym na raz. Oznacza to, że wyłapujesz konflikty scalania na zasadzie commit-by-commit, zamiast rozwiązywać je wszystkie w jednym masywnym merge commit. Dzięki temu twoje zobowiązania są tak skoncentrowane, jak to tylko możliwe, a historia projektu jest czysta. To z kolei sprawia, że o wiele łatwiej jest dowiedzieć się, gdzie zostały wprowadzone błędy i, jeśli to konieczne, cofnąć zmiany z minimalnym wpływem na projekt.
Jeśli Mary i John pracują nad niepowiązanymi funkcjami, jest mało prawdopodobne, że proces zmiany kolejności generuje konflikty. Jeśli jednak tak się stanie, Git wstrzyma rebase na bieżącym zatwierdzeniu i wyświetli następujący komunikat wraz z odpowiednimi instrukcjami:
CONFLICT (content): Merge conflict in
Wspaniałą rzeczą w Gicie jest to, że każdy może rozwiązywać swoje własne konflikty scalania. W naszym przykładzie Mary po prostu uruchomi git status
, aby zobaczyć, gdzie jest problem. Skojarzone pliki pojawią się w sekcji Unmerged paths:
# Unmerged paths: # (use "git reset HEAD ..." to unstage) # (use "git add/rm ..." as appropriate to mark resolution) # # both modified:
astępnie Mary edytuje plik(i) do swoich potrzeb. Gdy będzie zadowolony z rezultatu, może ustawić plik(i) w zwykły sposób i pozwolić, bygit rebase
zrobił resztę:
git add git rebase --continue
I to wszystko. Git przejdzie do następnego commitu i powtórzy proces dla wszystkich innych commitów, które generują konflikty.
Jeśli dotarłeś do tego punktu i zdałeś sobie sprawę, że nie masz pojęcia, co się dzieje, nie panikuj. Po prostu wykonaj następujące polecenie i wrócisz do punktu wyjścia:
git rebase --abort
Mary pomyślnie publikuje swoją funkcję
Po zakończeniu synchronizacji z centralnym repozytorium, Mary będzie mogła pomyślnie opublikować swoje zmiany:
git push origin master
Dokąd zmierzać
Jak widać, możliwe jest odtworzenie tradycyjnego środowiska Subversion przy użyciu tylko kilku poleceń Git. Jest to świetne rozwiązanie dla zespołów przechodzących z SVN, ale nie wykorzystuje ono rozproszonej natury Git.
Scentralizowany przepływ pracy jest świetny dla małych zespołów. Proces rozwiązywania konfliktów opisany powyżej może stanowić wąskie gardło, gdy zespół będzie się powiększał. Jeśli Twój zespół dobrze czuje się w Scentralizowanym Przepływie Pracy, ale chce usprawnić współpracę, zdecydowanie warto poznać zalety Przepływu Pracy z Oddziałem Funkcjonalnym. Poświęcając każdemu elementowi oddzielną gałąź, można zainicjować dogłębną dyskusję na temat nowych dodatków, zanim zostaną one włączone do oficjalnego projektu.
Inne popularne przepływy pracy
Scentralizowany przepływ pracy jest w zasadzie blokiem konstrukcyjnym dla innych przepływów pracy Git. Większość popularnych przepływów pracy Git będzie miała jakieś scentralizowane repo, z którego poszczególni deweloperzy będą pchać i ciągnąć. Poniżej omówimy pokrótce kilka innych popularnych przepływów pracy Git. Te rozszerzone przepływy pracy oferują bardziej wyspecjalizowane wzorce zarządzania gałęziami dla rozwoju funkcjonalności, poprawek i ewentualnego wydania.
Odgałęzianie funkcjonalności
Odgałęzianie funkcjonalności jest logicznym rozszerzeniem scentralizowanego przepływu pracy. Podstawową ideą przepływu pracy opartego na rozgałęzieniach funkcji jest to, że cały rozwój funkcji powinien odbywać się w dedykowanej gałęzi, a nie w gałęzi master
. Taka hermetyzacja ułatwia wielu programistom pracę nad daną funkcjonalnością bez zakłócania głównej bazy kodu. Oznacza to również, że gałąź master
nigdy nie powinna zawierać uszkodzonego kodu, co jest ogromną zaletą dla środowisk ciągłej integracji.
Przepływ pracy Gitflow
Przepływ pracy Gitflow został po raz pierwszy opublikowany w wysoko ocenianym wpisie na blogu Vincenta Driessena z nvie z 2010 roku. Przepływ pracy Gitflow definiuje ścisły model rozgałęziania zaprojektowany wokół wydania projektu. Ten przepływ pracy nie dodaje żadnych nowych koncepcji ani poleceń poza tymi, które są wymagane przez przepływ pracy Feature Branch. Zamiast tego, przypisuje bardzo konkretne role różnym gałęziom oraz definiuje, jak i kiedy powinny one ze sobą współdziałać.
Przepływ pracy dla rozwidlenia
Przepływ pracy dla rozwidlenia różni się zasadniczo od pozostałych przepływów omawianych w tym poradniku. Zamiast używać jednego repozytorium po stronie serwera jako „centralnej” bazy kodu, daje on każdemu deweloperowi własne repozytorium po stronie serwera. Oznacza to, że każdy użytkownik ma nie jedno, ale dwa repozytoria Git: prywatne lokalne i publiczne po stronie serwera.
Wskazówki
Nie ma jednego rozmiaru pasującego do wszystkich przepływów pracy Git. Jak już wcześniej wspomniano, ważne jest, aby opracować taki przepływ pracy Git, który zwiększy produktywność Twojego zespołu. Oprócz kultury zespołu, przepływ pracy powinien również uzupełniać kulturę biznesową. Funkcje Git, takie jak gałęzie i znaczniki, powinny być zgodne z harmonogramem wydań w Twojej firmie. Jeśli Twój zespół korzysta z oprogramowania do zarządzania projektami typu task tracking, możesz chcieć używać gałęzi, które odpowiadają zadaniom w toku. Dodatkowo, niektóre wskazówki do rozważenia przy wyborze przepływu pracy są następujące:
Krótko żyjące gałęzie
Im dłużej gałąź żyje oddzielnie od gałęzi produkcyjnej, tym większe ryzyko konfliktów scalania i problemów z wdrażaniem. Krótko żyjące gałęzie promują czystsze scalenia i wdrożenia.
Zminimalizuj i uprość przywracanie
Ważne jest, aby mieć przepływ pracy, który pomaga proaktywnie zapobiegać scaleniom, które będą musiały być przywracane. Przykładem może być przepływ pracy, który testuje gałąź, zanim pozwoli na połączenie jej z gałęzią master
. Jednakże, wypadki się zdarzają. W związku z tym, korzystne jest posiadanie przepływu pracy, który pozwala na łatwe przywracanie zmian, które nie zakłócają przepływu pracy innych członków zespołu.
Dopasuj do harmonogramu wydań
Przebieg pracy powinien uzupełniać cykl wydawniczy Twojej firmy. Jeśli planujesz wydawać wiele razy dziennie, będziesz chciał utrzymywać swoją gałąź master
stabilną. Jeśli Twój harmonogram wydań jest rzadszy, możesz rozważyć użycie znaczników Git do przypisania gałęzi do wersji.
Podsumowanie
W tym dokumencie omówiliśmy przepływy pracy Git. Przyjrzeliśmy się dogłębnie scentralizowanemu przepływowi pracy z praktycznymi przykładami. Rozszerzając temat scentralizowanego przepływu pracy, omówiliśmy dodatkowe, wyspecjalizowane przepływy pracy. Niektóre kluczowe wnioski z tego dokumentu to:
- Nie ma jednego, uniwersalnego przepływu pracy Git
- Przepływ pracy powinien być prosty i zwiększać produktywność zespołu
- Wymagania biznesowe powinny pomóc w kształtowaniu przepływu pracy Git
Aby przeczytać o kolejnym przepływie pracy Git, sprawdź nasze wyczerpujące omówienie przepływu pracy Feature Branch.
Więcej informacji na temat przepływu pracy Git.