Strategia rozgałęziania Git dla długo nieużywanego kodu

15

W naszym zespole, oprócz poszczególnych jednostek pracy (Historie), mamy dłuższe motywy pracy (Epopeje). Liczne historie stają się epickie.

Tradycyjnie mieliśmy gałęzie funkcji dla każdej Opowieści i połączyliśmy je prosto do opanowania, gdy przejdą kontrolę jakości. Chcielibyśmy jednak zacząć powstrzymywać się od wydania ukończonych historii w Eposie, dopóki Epicka nie zostanie uznana za „pełną funkcję”. Wydamy te funkcje do produkcji dopiero po zamknięciu całej Epiki. Co więcej, mamy serwer budowania na noc - chcielibyśmy, aby wszystkie zamknięte Historie (w tym te, które są częścią niekompletnych Eposów) były automatycznie wdrażane na tym serwerze na noc.

Czy są jakieś sugestie, jak zarządzać naszym repozytorium, aby to osiągnąć? Zastanawiałem się nad wprowadzeniem „epickich gałęzi”, w których scalilibyśmy zamknięte historie z pokrewną epicką gałęzią zamiast bezpośrednio w master, ale mam obawy:

  • Martwię się o konflikty scalania, które mogą powstać, jeśli epickie gałęzie będą otwarte przez długi czas
  • Kompilacje nocne wymagałyby połączenia wszystkich epickich gałęzi w gałąź „kompilacji nocnej”. Ponownie mogą pojawić się konflikty scalania i należy to zrobić automatycznie
Sitati
źródło

Odpowiedzi:

23

Prosta sugestia: nie rób tego.

gałęzie git nie są przeznaczone do długotrwałych rozwidleń kodu, jak omówiono tutaj i https://blog.newrelic.com/2012/11/14/long-running-branches-consisted-harmful/ . Oddziały najlepiej traktować jako przejściowe rzeczy używane do organizowania zatwierdzeń przez indywidualnych programistów na poziomie codziennym. Więc jeśli mają nazwę, która odpowiada czemuś kierownikowi projektu (nie wspominając o użytkownikach końcowych) może troszczyć się o to, że robisz coś źle.

Zalecaną praktyką jest ciągła integracja z przełączaniem funkcji lub przełączaniem według gałęzi, aby zapewnić, że:

  • cały kod jest zintegrowany przez cały czas (przynajmniej codziennie, najlepiej częściej)
  • to, co zostanie wdrożone, jest pod wyraźną kontrolą.
soru
źródło
1
Podejrzewałem, że może to być popularna odpowiedź! Moje główne obawy związane z tym to narzut związany z utrzymywaniem zarówno implementacji „na żywo”, jak i „następnej”, a także wymaga, aby programista pracujący nad funkcją wiedział z góry, aby tworzyć zmiany jako nowe funkcje równoległe zamiast aktualizować (/ zastępować) istniejąca funkcjonalność. Chyba wymaga to większej zmiany sposobu myślenia w zespole.
Sitati
Można używać gałęzi do programowania kodu, nigdy nie używaj ich do przechowywania kodu. Jeśli więc nie masz pewności, czy zadanie jest poprawką 30 minut, czy przeróbką na 2 tygodnie, zacznij oddziału. Jak tylko się dowiesz, scal lub przerób abstrakcję / przełącz, a następnie scal.
soru
@ Sitati: Właśnie scaliłem kod, który był w gałęzi funkcji przez ostatnie cztery miesiące. W międzyczasie develprzeszliśmy na CMake z Autotools, wprowadziliśmy Travis CI, zmieniliśmy kod. Ostatecznie łatwiej było zrozumieć nową funkcję i zastosować ją ręcznie develniż próbować scalić. Mieliśmy również nowych studentów studiów magisterskich, którzy opracowali nową funkcję w branży, którą rozgałęzili, kiedy rozpoczęli pracę magisterską. Po roku pchnęli go i nie było żadnego wysiłku, aby go z powrotem połączyć, więc z dnia na dzień coraz trudniej było go scalić.
Martin Ueding
2
Link do posta na blogu ma teraz 5 lat. Nienawidzę przełączania funkcji. Co jest złego w rozgałęzianiu długoterminowym, regularnym łączeniu z powrotem z gałęzią funkcji od głównego i dodawaniu ciągłej integracji do gałęzi długoterminowych funkcji?
Jason Kelley,
CI to nazwa procesu, a nie narzędzie. Jeśli masz więcej niż jedną gałąź funkcji, zwykle nie będą one stale integrowane ze sobą. Co oznacza znalezienie problemów później niż wcześniej.
soru
1

Myślę, że jest to dość powszechny problem i sprowadza się do wyboru, które funkcje mają zostać uwzględnione w wydaniu po ich zakodowaniu, a nie wcześniej.

na przykład.

Mam funkcje A, B i C dla wersji 2 mojego produktu. B i C są powiązane, nie chcę wypuszczać B, chyba że C również jest skończone.

Mam trzech programistów pracujących nad funkcjami jednocześnie.

Mam datę wydania kamienia D

B jest zakończone i połączone, A jest zakończone i połączone. C jest opóźnione ... co mam zrobić ?!

Nie wierzę, że istnieje techniczne rozwiązanie tego problemu. Chcesz wypuścić niesprawdzoną wersję produktu z dołączoną tylko funkcją A. O ile nie scalisz i nie przetestujesz wszystkich możliwych kombinacji funkcji, zawsze będzie to możliwe.

Rozwiązanie jest bardziej ludzkie. Nie znasz daty premiery i musisz ją cofnąć.

Ewan
źródło
1

To trudny problem, z którym boryka się wiele osób. Wolę używać konfiguracji Gitflow jako punktu wyjścia.

Rozwój -> Nowe prace nad
Master -> Gotowe rzeczy wymagające testowania Produkcja -> Rzeczy, które zostały opublikowane do produkcji.

Przy mniejszych (krótszych) funkcjach tworzę gałąź od programowania, pracuję tam, a następnie łączę gałąź z powrotem z programowaniem.

Przy głównych (długoterminowych) funkcjach tworzę gałąź z rozwoju, tworzę mniejsze gałęzie z tej gałęzi, a następnie łączę z powrotem do pierwszej gałęzi. Po zakończeniu głównej funkcji wraca ona do gałęzi programistycznej.

W regularnych odstępach czasu (w zależności od projektu) łączę programowanie z powrotem w master i rozpoczyna się cykl testowania. Jeśli jakieś poprawki pojawią się w trakcie testowania, zostaną wykonane w gałęzi master (gałąź sub, a następnie scalona). Podczas testów można kontynuować rozwój gałęzi master.

W dowolnym momencie master powinien zostać włączony do rozwoju, a rozwój powinien zostać połączony z dowolnym z jego długoterminowych oddziałów.

mistrz powinien zawsze (teoretycznie) być gotowy do produkcji. Rozwój powinien zawsze (teoretycznie) być gotowy do produkcji. Jedyny powód, dla którego istnieje różnica, to zapewnienie solidnego zestawu funkcji do testowania przez testerów.

Gdy jest gotowy, testowane zatwierdzenie w wzorcu jest łączone z produkcją, a wdrażanie w produkcji odbywa się z tej gałęzi. Poprawki, które należy wykonać w nagłych wypadkach, mogą następnie odbywać się w oddziale produkcyjnym bez konieczności łączenia się w trybie głównym (który może zawierać wiele niesprawdzonych zmian).

Moje normalne Drzewo wygląda

 LongTerm -> Development -> Master -> Production    
 LongTerm <- Development      |            |  
     |       Development -> Master         |  
 LongTerm <- Development -> Master         |  
             Development <- Master         |  
                            Master -> Production  

Zasadą ogólną jest, że żadna zmiana nie powinna zająć więcej niż kilka godzin. Jeśli tak, należy wprowadzić mniejsze zmiany. Jeśli jest to ogromna funkcja (jak ponowne pisanie interfejsu użytkownika), to dzieje się to w dłuższej perspektywie, aby normalny rozwój mógł być kontynuowany w tym samym czasie. Oddziały LongTerm są zwykle tylko oddziałami lokalnymi, podczas gdy Programowanie, Master i Produkcja to oddziały zdalne. Wszelkie odgałęzienia są również tylko lokalne. Utrzymuje to repozytorium w czystości dla innych, bez utraty przydatności git na długoterminowym zestawie funkcji.

Chciałbym jednak zauważyć, że istnienie gałęzi długoterminowej jest rzadkością. Zwykle cała moja praca jest w fazie rozwoju. Tylko wtedy, gdy mam funkcję (zestaw), która zajmie tak długo, że muszę być w stanie pracować także nad normalnymi programami, korzystam z gałęzi LongTerm. Jeśli to tylko zestaw zmian, które powinny być razem, po prostu nie łączę się z mistrzem, dopóki wszystko się nie skończy.

Coteyr
źródło
„Przy głównych (długoterminowych) funkcjach tworzę gałąź od rozwoju” - czy nie powinieneś tworzyć nowych gałęzi funkcji (rozwój) z oddziału produkcyjnego? Widząc, że gałąź produkcji jest kodem gotowym do wydania.
robotron
Nie, produkcja jest już wydana, master wyprzedza produkcję, a rozwój wyprzedza master. Nowa funkcja, taka jak dodawanie podatku do sum zamówień, jest bezcelowa, jeśli nie pracujesz nad kodem, który już zawiera zamówienia.
coteyr
Ale jeśli rozgałęzisz się od deweloperów, a później scalisz z powrotem, czy ta gałąź (a w konsekwencji master i produkcja później) nie będą obejmować wszystkich zmian programistycznych dokonanych przez innych, aż do momentu rozgałęzienia? Niektóre z tych zmian mogą nie mieć zatwierdzenia kontroli jakości. Być może mówili o różnych podejściach do zarządzania wydaniami.
robotron
Tak, właśnie o to chodzi. Testy QA na konkretnym SHA w trybie master, ale nie możesz tego zrobić.
coteyr
„Testy jakości na konkretnej SHA w trybie głównym” -> Kontrola jakości testuje każdą nową funkcję jako samodzielną? Pozwól, że poprowadzę Cię przez typowy scenariusz, z którym mierzy się mój zespół: powiedz, że masz 2 długofalowe projekty na tej samej bazie kodu: Projekt A jest poddawany kontroli jakości przez ostatni miesiąc i będzie przeprowadzany kontroli jakości przez kolejny miesiąc. Projekt B był rozwijany przez ostatnie 6 miesięcy i jest teraz gotowy do kontroli jakości. Projekt A jest połączony z głównym i na pewno nie jest gotowy do produkcji z powodu licznych subtelnych błędów reguł biznesowych. Jak radzimy sobie z Projektem B? A i B muszą zostać przetestowane razem, aby sprawdzić interakcje (B nie spowoduje konfliktów podczas łączenia).
robotron