GitHub Flow
Problemy z git-flow
Podróżuję wszędzie ucząc ludzi Gita i prawie na każdych zajęciach i warsztatach, które ostatnio robiłem, pytano mnie co myślę o git-flow. Zawsze odpowiadam, że uważam, że jest świetny – wziął system (Git), który ma milion możliwych przepływów pracy i udokumentował dobrze przetestowany, elastyczny przepływ pracy, który działa dla wielu programistów w dość prosty sposób. Stało się to czymś w rodzaju standardu, dzięki czemu programiści mogą przenosić się między projektami lub firmami i być zaznajomieni z tym standardowym przepływem pracy.
Jednakże ma to swoje problemy. Słyszałem wiele opinii od ludzi, którym nie podoba się to, że nowe gałęzie funkcji są uruchamiane z develop
zamiast master
, lub sposób w jaki obsługuje hotfixy, ale są one dość drobne.
Jednym z większych problemów dla mnie jest to, że jest to bardziej skomplikowane niż myślę, że większość deweloperów i zespołów rozwojowych faktycznie wymaga. Jest to na tyle skomplikowane, że opracowano duży skrypt pomocniczy, który pomaga wymusić przepływ. Chociaż jest to fajne, problem polega na tym, że nie można tego wymusić w GUI Gita, tylko w wierszu poleceń, więc jedynymi ludźmi, którzy muszą nauczyć się skomplikowanego przepływu pracy naprawdę dobrze, ponieważ muszą wykonać wszystkie kroki ręcznie, są ci sami ludzie, którzy nie czują się komfortowo z systemem na tyle, aby używać go z wiersza poleceń. To może być ogromny problem.
Oba te problemy mogą być łatwo rozwiązane po prostu przez posiadanie znacznie bardziej uproszczonego procesu. W GitHubie nie używamy git-flow. Używamy, i zawsze używaliśmy, znacznie prostszego przepływu pracy Git.
Jego prostota daje mu wiele zalet. Jedną z nich jest to, że jest łatwy do zrozumienia dla ludzi, co oznacza, że mogą go szybko przyswoić i rzadko, jeśli w ogóle, psują go lub muszą cofać kroki, które zrobili źle. Inną jest to, że nie potrzebujemy skryptu, który pomoże nam go wymusić lub podążać za nim, więc używanie GUI nie stanowi problemu.
GitHub Flow
Dlaczego więc nie używamy git-flow na GitHubie? Cóż, głównym problemem jest to, że wdrażamy cały czas. Proces git-flow jest zaprojektowany w dużej mierze wokół „wydania”. Tak naprawdę nie mamy „wydań”, ponieważ wdrażamy do produkcji każdego dnia – często kilka razy dziennie. Możemy to zrobić poprzez naszego robota na czacie, który jest tym samym miejscem, w którym wyświetlane są nasze wyniki CI. Staramy się uczynić proces testowania i wysyłania tak prostym, jak to tylko możliwe, aby każdy pracownik czuł się komfortowo robiąc to.
Wdrażanie tak regularne ma wiele zalet. Jeśli wdrażasz co kilka godzin, jest prawie niemożliwe, aby wprowadzić dużą liczbę dużych błędów. Małe problemy mogą być wprowadzone, ale wtedy mogą być naprawione i ponownie wdrożone bardzo szybko. Normalnie musiałbyś zrobić „hotfix” lub coś poza normalnym procesem, ale to jest po prostu część naszego normalnego procesu – nie ma różnicy w przepływie GitHub między hotfixem a bardzo małą funkcjonalnością.
Inną zaletą wdrażania przez cały czas jest możliwość szybkiego rozwiązywania problemów wszelkiego rodzaju. Możemy reagować na problemy związane z bezpieczeństwem, na które zwracamy uwagę lub wdrażać małe, ale interesujące żądania funkcji niewiarygodnie szybko, a jednocześnie możemy używać dokładnie tego samego procesu do zajmowania się tymi zmianami, co do obsługi normalnego lub nawet dużego rozwoju funkcji. To wszystko jest tym samym procesem i jest bardzo proste.
Jak to robimy
Więc, czym jest GitHub Flow?
- Anything in the
master
branch is deployable - Aby pracować nad czymś nowym, utwórz opisowo nazwaną gałąź poza
master
(np:new-oauth2-scopes
) - Commituj do tej gałęzi lokalnie i regularnie popychaj swoją pracę do tak samo nazwanej gałęzi na serwerze
- Gdy potrzebujesz informacji zwrotnej lub pomocy, lub uważasz, że gałąź jest gotowa do scalenia, otwórz pull request
- Po tym, jak ktoś inny przejrzy i podpisze się pod cechą, możesz scalić ją w master
- Gdy zostanie scalona i pchnięta do 'master’, możesz i powinieneś wdrożyć ją natychmiast
To jest cały przepływ. Jest to bardzo proste, bardzo skuteczne i działa dla dość dużych zespołów – GitHub to 35 pracowników teraz, może 15-20 z nich pracuje nad tym samym projektem (github.com) w tym samym czasie. Myślę, że większość zespołów programistycznych – grup, które pracują nad tym samym logicznym kodem w tym samym czasie, co mogłoby powodować konflikty – jest mniej więcej tej wielkości lub mniejsza. Szczególnie te, które są na tyle postępowe, że robią szybkie i spójne wdrożenia.
Więc, spójrzmy na każdy z tych kroków po kolei.
#1 – wszystko w gałęzi master jest możliwe do wdrożenia
To jest w zasadzie jedyna twarda zasada systemu. Jest tylko jedna gałąź, która ma jakieś konkretne i spójne znaczenie i nazwaliśmy ją master
. Dla nas oznacza to, że został on wdrożony lub w najgorszym wypadku zostanie wdrożony w ciągu kilku godzin. Niesamowicie rzadko zdarza się, że gałąź jest zwijana (gałąź jest cofana do starszego commitu, aby odwrócić pracę) – jeśli wystąpi jakiś problem, polecenia zostaną odwrócone lub wprowadzone zostaną nowe polecenia, które naprawią problem, ale sama gałąź prawie nigdy nie jest zwijana.
Gałąź master
jest stabilna i zawsze, zawsze bezpiecznie jest wdrażać z niej lub tworzyć nowe gałęzie na jej podstawie. Jeśli popchniesz do master coś, co nie jest przetestowane lub psuje build, łamiesz umowę społeczną zespołu deweloperów i zazwyczaj czujesz się z tym bardzo źle. Każda gałąź, którą popychamy, ma uruchomione testy i zgłoszone na czacie, więc jeśli nie uruchomiłeś ich lokalnie, możesz po prostu popchnąć do gałęzi tematycznej (nawet gałęzi z jednym commitem) na serwerze i poczekać, aż Jenkins powie ci, czy przeszła wszystko.
Mógłbyś mieć gałąź deployed
, która jest aktualizowana tylko wtedy, gdy wdrażasz, ale nie robimy tego. Po prostu wystawiamy aktualnie wdrożony SHA poprzez samą webaplikację i curl
go, jeśli potrzebujemy porównania.
#2 – twórz opisowe gałęzie poza master
Gdy chcesz rozpocząć pracę nad czymkolwiek, tworzysz opisowo nazwaną gałąź poza stabilną master
gałęzią. Niektóre przykłady w bazie kodu GitHuba to user-content-cache-key
, submodules-init-task
lub redis2-transition
. Ma to kilka zalet – jedną z nich jest to, że podczas pobierania możesz zobaczyć tematy, nad którymi pracowali wszyscy inni. Inną jest to, że jeśli porzucisz gałąź na jakiś czas i wrócisz do niej później, dość łatwo przypomnisz sobie, co to było.
Jest to miłe, ponieważ kiedy wejdziemy na stronę z listą gałęzi na GitHubie, możemy łatwo zobaczyć, nad jakimi gałęziami ostatnio pracowano i ile mniej więcej jest w nich pracy.
To prawie jak lista nadchodzących funkcji z aktualnym statusem. Ta strona jest świetna, jeśli jej nie używasz – pokazuje tylko te gałęzie, nad którymi trwają prace w stosunku do aktualnie wybranej gałęzi i sortuje je tak, że te, nad którymi ostatnio pracowano, są na górze. Jeśli jestem naprawdę ciekawy, mogę kliknąć przycisk „Porównaj”, aby zobaczyć, jaka jest rzeczywista ujednolicona lista diff i commit, która jest unikalna dla tej gałęzi.
Więc, od tego momentu mamy 44 gałęzie w naszym repozytorium z niezmergowaną pracą w nich, ale widzę również, że tylko około 9 lub 10 z nich zostało popchniętych w ciągu ostatniego tygodnia.
#3 – pchaj do nazwanych gałęzi stale
Kolejną dużą różnicą w stosunku do git-flow jest to, że pchamy do nazwanych gałęzi na serwerze stale. Ponieważ jedyną rzeczą, o którą naprawdę musimy się martwić, jest master
z punktu widzenia wdrażania, pchanie na serwer nie wprowadza nikogo w błąd ani nie miesza rzeczy – wszystko, co nie jest master
, jest po prostu czymś, nad czym się pracuje.
Upewnia to również, że nasza praca jest zawsze zarchiwizowana w przypadku utraty laptopa lub awarii dysku twardego. Co ważniejsze, dzięki temu wszyscy są w ciągłej komunikacji. Proste 'git fetch’ w zasadzie da ci listę TODO tego, nad czym każdy obecnie pracuje.
$ git fetchremote: Counting objects: 3032, done.remote: Compressing objects: 100% (947/947), done.remote: Total 2672 (delta 1993), reused 2328 (delta 1689)Receiving objects: 100% (2672/2672), 16.45 MiB | 1.04 MiB/s, done.Resolving deltas: 100% (1993/1993), completed with 213 local objects.From github.com:github/github * charlock-linguist -> origin/charlock-linguist * enterprise-non-config -> origin/enterprise-non-config * fi-signup -> origin/fi-signup 2647a42..4d6d2c2 git-http-server -> origin/git-http-server * knyle-style-commits -> origin/knyle-style-commits 157d2b0..d33e00d master -> origin/master * menu-behavior-act-i -> origin/menu-behavior-act-i ea1c5e2..dfd315a no-inline-js-config -> origin/no-inline-js-config * svg-tests -> origin/svg-tests 87bb870..9da23f3 view-modes -> origin/view-modes * wild-renaming -> origin/wild-renaming
Pozwala również każdemu zobaczyć, patrząc na stronę GitHub Branch List, nad czym wszyscy inni pracują, więc mogą je sprawdzić i zobaczyć, czy chcą w czymś pomóc.
#4 – otwórz pull request w każdej chwili
GitHub ma niesamowity system przeglądu kodu zwany Pull Requests, o którym obawiam się, że nie wie wystarczająco dużo ludzi. Wiele osób używa go do pracy open source – rozwidla projekt, aktualizuje projekt, wysyła pull request do opiekuna. Jednakże, może on być również z łatwością używany jako wewnętrzny system przeglądu kodu, co właśnie robimy.
Właściwie, używamy go bardziej jako widok konwersacji w gałęzi niż pull request. Możesz wysyłać pull requesty z jednej gałęzi do drugiej w pojedynczym projekcie (publicznym lub prywatnym) w GitHubie, więc możesz ich użyć, aby powiedzieć „Potrzebuję pomocy lub recenzji tego” oprócz „Proszę scalić to w”.
Tutaj możesz zobaczyć Josha cc’ing Briana do recenzji i Briana przychodzącego z kilkoma poradami na temat jednej z linii kodu. Dalej widzimy Josha potwierdzającego obawy Briana i przesuwającego więcej kodu w celu ich rozwiania.
W końcu widać, że wciąż jesteśmy w fazie próbnej – to nie jest jeszcze gałąź gotowa do wdrożenia, używamy Pull Requests do przejrzenia kodu na długo przed tym, jak faktycznie chcemy go scalić z master
w celu wdrożenia.
Jeśli utknąłeś w rozwoju swojej funkcji lub gałęzi i potrzebujesz pomocy lub porady, lub jeśli jesteś programistą i potrzebujesz projektanta do przejrzenia swojej pracy (lub vice versa), lub nawet jeśli masz mało kodu lub nie masz go wcale, ale kilka kompilacji zrzutów ekranu lub ogólnych pomysłów, otwierasz pull request. Możesz cytować ludzi w systemie GitHub poprzez dodanie @username, więc jeśli chcesz uzyskać recenzję lub informację zwrotną od konkretnych osób, po prostu cytujesz ich w wiadomości PR (tak jak widziałeś Josha powyżej).
To jest fajne, ponieważ funkcja Pull Request pozwala Ci komentować poszczególne linie w ujednoliconym diff, pojedyncze commity lub samo pull request i wyciąga wszystko inline do pojedynczego widoku konwersacji.Pozwala również na kontynuowanie pushowania do gałęzi, więc jeśli ktoś skomentuje, że zapomniałeś coś zrobić lub jest błąd w kodzie, możesz go naprawić i popchnąć do gałęzi, GitHub pokaże nowe commity w widoku konwersacji i możesz kontynuować iterację na gałęzi w ten sposób.
Jeśli gałąź była otwarta zbyt długo i czujesz, że wymyka się z synchronizacji z gałęzią master, możesz scalić master do swojej gałęzi tematycznej i kontynuować. Możesz łatwo sprawdzić w dyskusji pull request lub na liście commitów, kiedy gałąź została ostatnio uaktualniona z 'master’.
Gdy wszystko jest naprawdę i naprawdę zrobione w gałęzi i czujesz, że jest gotowa do wdrożenia, możesz przejść do następnego kroku.
#5 – scalaj tylko po przejrzeniu pull request
Nie wykonujemy po prostu pracy bezpośrednio na master
lub pracujemy nad gałęzią tematyczną i scalamy ją, gdy uważamy, że jest skończona – staramy się uzyskać zgodę kogoś innego w firmie. Zazwyczaj jest to +1 lub emoji lub komentarz „„, ale staramy się, aby ktoś inny na to spojrzał.
Gdy to uzyskamy, a gałąź przejdzie CI, możemy połączyć ją z masterem w celu wdrożenia, co automatycznie zamknie Pull Request, gdy go popchniemy.
#6 – wdrożyć natychmiast po przeglądzie
W końcu, twoja praca została wykonana i scalona do gałęzi master
. Oznacza to, że nawet jeśli nie wdrożysz jej teraz, ludzie będą bazować na nowej pracy, a następne wdrożenie, które prawdopodobnie nastąpi za kilka godzin, wypchnie ją na zewnątrz. Tak więc, ponieważ naprawdę nie chcesz, aby ktoś inny pchnął coś, co napisałeś, a co zepsuje rzeczy, ludzie mają tendencję do upewniania się, że to naprawdę jest stabilne, kiedy jest scalane, a ludzie mają również tendencję do popychania własnych zmian.
Nasz bot ogniska, hubot, może wykonywać wdrożenia dla każdego z pracowników, więc proste:
hubot depoy github to production
wprowadzi kod i zero-downtime ponownie uruchomi wszystkie niezbędne procesy. Możesz zobaczyć, jak powszechne jest to na GitHub:
Możesz zobaczyć 6 różnych osób (w tym faceta od wsparcia i projektanta) wdrażających około 24 razy w ciągu jednego dnia.
Zrobiłem to dla oddziałów z jednym commitem zawierającym zmianę jednej linii. Proces jest prosty, nieskomplikowany, skalowalny i potężny. Możesz to zrobić z gałęziami funkcji z 50 commitami na nich, które zajęły 2 tygodnie, lub 1 commit, który zajął 10 minut. Jest to tak prosty i bezproblemowy proces, że nie jesteś zirytowany, że musisz to zrobić nawet dla 1 commitu, co oznacza, że ludzie rzadko próbują pominąć lub ominąć proces, chyba że zmiana jest tak mała lub nieistotna, że po prostu nie ma znaczenia.
Jest to niesamowicie prosty i potężny proces. Myślę, że większość ludzi zgodzi się, że GitHub ma bardzo stabilną platformę, że problemy są rozwiązywane szybko, jeśli w ogóle się pojawią, i że nowe funkcje są wprowadzane w szybkim tempie. Nie ma kompromisu z jakością lub stabilnością, abyśmy mogli uzyskać więcej szybkości lub prostoty lub mniej procesu.
Wnioski
Git sam w sobie jest dość skomplikowany do zrozumienia, czyniąc przepływ pracy, którego używasz z nim bardziej złożonym niż to konieczne, jest po prostu dodaniem więcej mentalnego narzutu do dnia każdego. Zawsze zalecałbym używanie najprostszego możliwego systemu, który będzie działał dla twojego zespołu i robienie tego tak długo, aż przestanie działać, a następnie dodawanie złożoności tylko wtedy, gdy jest to absolutnie konieczne.
Dla zespołów, które muszą robić formalne wydania w dłuższym odstępie czasu (kilka tygodni do kilku miesięcy pomiędzy wydaniami), i być w stanie robić hot-fixy i gałęzie konserwacyjne oraz inne rzeczy, które wynikają z tak rzadkich wysyłek, git-flow ma sens i bardzo zalecałbym jego użycie.
Dla zespołów, które stworzyły kulturę wysyłania, które pchają do produkcji każdego dnia, które ciągle testują i wdrażają, zalecałbym wybranie czegoś prostszego, jak GitHub Flow.
Leave a Reply