Wybór odpowiedniej strategii rozgałęziania dla wydań

11

Zaczynając od nowego zespołu deweloperów przy nowym projekcie, musimy zdefiniować naszą strategię rozgałęzienia dla naszego repozytorium źródłowego ( np. Microsoft Team Foundation Server 2010 ). Natknęliśmy się na trudną dyskusję na temat tego, czy ...

. Posiadaj jedną gałąź wydania, z której wykonujemy kompilacje produkcyjne, a następnie etykietuj, kiedy coś jest faktycznie wydane

LUB

B . Mają nową gałąź wydania dla każdego nowego wydania w produkcji ( np. Wersja 1, 2, 3 itd. )

Opcja A wydaje się dość prosta, ale nie jesteśmy pewni, czy doprowadzi to do problemów na dłuższą metę. Opcja B wydaje się, że po prostu tworzy wiele jednorazowych, długowiecznych gałęzi, które po prostu gromadzą się z czasem.

Czy ktoś ma jakieś doświadczenie, które mogłoby nam pomóc w podjęciu decyzji? W szczególności chcę usłyszeć, gdzie są punkty bólu dla jednego wyboru. Zachęcamy do zapewnienia konkretnych doświadczeń związanych z konsekwencjami TFS i / lub zarządzania wydaniami.

JoeGeeky
źródło

Odpowiedzi:

15

Opcja A. Wystarczy użyć głównej linii i tagowania do wydania

Plusy:

  • Unikasz piekła.
  • Trzymanie się głównej linii zachęca do najlepszych praktyk, takich jak właściwe planowanie wydań, niewprowadzanie dużej ilości PWT, stosowanie rozgałęzienia przez abstrakcję do radzenia sobie z długoterminową pracą poza pasmem oraz korzystanie z otwartego zamkniętego systemu i konfigurowalnych funkcji do zarządzania pracami w toku, które mogą; lub nie; należy wyłączyć teraz lub w przyszłości, aby zwolnić lub uniknąć pełnego wycofania.

Cons:

  • Radzenie sobie z pracami w toku staje się problemem i zwiększa potencjalny obszar ataku powierzchniowego, gdy nadchodzi czas uwolnienia. Jeśli jednak twoi programiści są zdyscyplinowani, nowe funkcje powinny być konfigurowalne i modułowe, a zatem łatwo można je wyłączyć / włączyć, lub nie ma WIP, a w każdym punkcie wydania cała praca jest zakończona lub jeszcze się nie rozpoczęła (tj. Scrum).
  • Wprowadzenie zmian na dużą skalę / poza pasmem wymaga wcześniejszego przemyślenia (np. Rozgałęzienie przez abstrakcję).

Osobiście wolę takie podejście. Pokrycie kodu i testy jednostkowe powinny zidentyfikować kod, który nie jest gotowy do wyjścia, a ludzie nie powinni pracować nad kodem, który nie zostanie wydany podczas bieżącej iteracji. Rozgałęzianie przez abstrakcję lub inne mechanizmy można wykorzystać do radzenia sobie z długoterminowymi zmianami i pracami w toku.

Gdy tego nie zrobisz, zaczniesz zajmować się problemami z scalaniem, przestarzałym kodem, funkcjami, które nigdy nie zostaną wydane itp.

Opcja B. Oddział według wydania

Plusy:

  • Możesz rozpocząć pracę nad kolejną iteracją, podczas gdy bieżąca iteracja zakończy swoją rundę testów akceptacyjnych.
  • Inne rzeczy na pewno.

Cons:

  • Mnóstwo oddziałów.
  • Nadal musisz oznaczyć gałęzie w punktach zwolnienia.
  • Nadal musisz poradzić sobie z WIP i połączyć WIP z gałęzi poprzedniego wydania w gałąź następnego wydania, jeśli nie będzie to możliwe i nadal musisz go wyłączyć lub odciąć z gałęzi wydania i ponownie uruchomić testy akceptacyjne
  • Poprawki muszą być zastosowane do większej liczby gałęzi (zwolnij gałąź + poprawka + nowy tag + scal poprawkę do gałęzi vnext i ewentualnie vnextnext w zależności od tego, gdzie znajduje się poprawka).

Nie jestem wielkim fanem tego rozwiązania ^ _ ^.

Ogólnie polecam po prostu próbować trzymać się głównej linii. Jeśli Twoi programiści mają problem z nie pisaniem WIP, które można łatwo wyciągnąć, gdy zawiedzie cięcie, lub który jest sprawdzany wcześnie w kolejnej wersji, możesz zacząć mówić o oznaczeniu kodu w punkcie, w którym powinien on być kompletny i rozgałęziony. stamtąd, jeśli to konieczne, aby usunąć przeoczone wady i błędy, których nie udało się wykryć w testach jednostkowych programistów.

Idealnie jednak myślę, że chcesz, aby był to proces wyjątku, a nie reguła.

Opcja C. Szalona opcja bonusowa

Jeśli chcesz się spodobać, możesz również rozważyć model rozgałęzienia dla historii użytkownika / funkcji. ( Straszny pomysł w TFS lub dowolnym innym DVCS, a jednocześnie niezwykle trywialny do wdrożenia, jeśli używasz DVCS, takich jak git lub mercurial ).

W przeszłości wdrożyłem poniżej dla poprzedniego zespołu obsługi pracodawców, który pracował ze starszą bazą kodu, której nie można łatwo przenieść na mercurial z svn. Wymagało to dużo niepotrzebnej pracy, aby sprostać wymaganiom biznesowym zawsze zwalnianej linii głównej, a nie tylko lepszej koordynacji wydań. . .

  1. Funkcje zostały opracowane przez deweloperów w ich zespole deweloperów.
  2. Kiedy funkcja jest gotowa do przeglądu, deweloperzy łączą ją w jedno połączenie z gałęzi Dev do gałęzi CR i dołączają do tytułu identyfikator / historię użytkownika. * Wymuszone przez hak przed zatwierdzeniem *
  3. Po przejściu CR używane jest narzędzie administracyjne do promowania funkcji w gałęzi kontroli jakości. (Napisałem małą aplikację terminalową, która wymieniła historie użytkowników obecne na różnych etapach akceptacji i pozwoliła operatorowi promować ją lub obniżać między tymi etapami akceptacji)
  4. QA przeprowadza automatyzację i ręczne testy użyteczności. Jeśli funkcja jest dobra, jest wypychana do gałęzi wydania (główna linia). Jeśli funkcja zostanie odrzucona, zostanie zdegradowana / wycofana z gałęzi kontroli jakości, dopóki deweloperzy nie będą w stanie rozwiązać problemów podniesionych podczas testu i dodać prześlij poprawkę do gałęzi CR.
  5. Jeśli kod został wycofany z gałęzi QA i zastosowana zostanie poprawka, narzędzie terminalowe zastosuje ponownie niezbędne zmiany, aby przywrócić tę funkcję do gałęzi QA z gałęzi CR, aby QA mogła ponownie sprawdzić kod i albo go promować, albo obniżyć to ponownie.
  6. W dowolnym momencie gałąź wydania powinna znajdować się w stabilnym stanie zwalnianym.
  7. Po wydaniu nowe Dev, QA i CR są przestawiane z głównej linii.
Keith przynosi
źródło
@Keith_Brings To naprawdę miłe podsumowanie, dziękuję. Jak już wskazałeś, opcja C nie jest tak naprawdę opcją, ponieważ używam TFS, ale mimo wszystko jest interesująca.
JoeGeeky
Nie rozumiem, jak może działać opcja A. W mojej firmie mamy różne wersje dla różnych klientów. Jeśli nadal pracujemy nad rozwojem funkcji / poprawek w wersji 1.0, a także aktywnie pracujemy nad wersją 2.0, a może nawet 3.0, nie możemy tego wszystkiego zrobić w jednym oddziale. Być może masz luksus korzystania z Opcji A z powodu swojego modelu wydania. Ale to nie jest model wypuszczania dla wszystkich, a dla tych z nas, którzy utknęli w funkcji pełzania funkcji lub wielu równoległych wydań, musimy użyć Opcji B.
void.pointer
6

Dla każdego wydawanego przez nas wydania mamy osobne oddziały (około 4 rocznie). Jest to bardzo wygodne, gdy trzeba wyciągnąć określone wydanie.

Jeśli chcesz zachować kilka starszych wydań, nie sądzę, że to wystarczy. Dzięki określonym gałęziom wersji możesz zastosować poprawki dla każdej gałęzi osobno (lub ich wybrane), nie martwiąc się o żadne inne wersje.

Ułatwia także porównywanie wydań, gdy polujesz, kiedy wprowadzono błąd lub funkcję.

Nie martw się o liczbę oddziałów lub o czas, jaki upłyną bez zmian. Twój system kontroli wersji ma dać ci kontrolę i zapewnić historię rozwoju twojego projektu. Historia ma tendencję, by się nie zmieniać ... I nie martw się, że twoi CVS nie będą w stanie sobie poradzić. Używamy Perforce, ponad 9000 plików w gałęzi programistycznej, do 50 gałęzi programistycznych dla wydań, nad którymi pracujemy, i jak już powiedziano, jeden oddział na wydanie, które publikujemy. Perforce nie oddycha nawet mocniej.

W skrócie: ułatw swoje życie jako programista / opiekun / naprawiacz błędów / łowca problemów i nie martw się o liczbę oddziałów lub liczbę plików. Wszelkie szanujące się cvs sobie poradzą.

Edytować:

W ogóle nie odczuwamy zamieszania w odniesieniu do liczby oddziałów, które posiadamy. Nasz schemat nazewnictwa dla gałęzi wydania i nasze zasady dla gałęzi 1 wydania 1 dla gałęzi programistycznych (lub roboczych) mogą mieć z tym coś wspólnego.

Gałęzie wersji mają nazwę, którą posiadają, tj .: R2011SP1 dla wersji 2011 Service Pack 1. Nasze gałęzie pracy mają mniej inteligentne nazwy: sub01, sub02, sub03 itd. „Sub” pochodzi z faktu, że wszystkie gałęzie pracy są sub-gałęziami oddziału akceptacji. Gałąź akceptacji to ta, w której gromadzone są wszystkie problemy gotowe do wydania.

Nasze zasady dotyczące gałęzi pracy 1 wydanie 1 w połączeniu z faktem, że nasz system śledzenia problemów został dostosowany do pola „oddział”, zapewnia, że ​​zawsze wiemy, jaki problem został opracowany w której gałęzi. Gdy problem jest zintegrowany z gałęzią akceptacji, pole to jest aktualizowane. Oznacza to, że zawsze wiemy, które problemy są gotowe do wydania (po zakończeniu testów akceptacyjnych). Podobnie aktualizujemy to pole, gdy tworzona jest gałąź wydania i w ten sposób zawsze możemy wyśledzić, w której wersji wydano problem.

Marjan Venema
źródło
1
Wierzę, że możesz rozgałęziać się od etykiet w TFS. Więc powinieneś być w porządku, jeśli chodzi o poprawki do bieżących wersji produktów, o ile nie zapomnisz etykiety.
Keith przynosi
@KeithBrings To prawda, właśnie to przetestowałem i rzeczywiście można rozgałęzić się z wytwórni.
JoeGeeky
@MarjanVenema Nie martwię się tak bardzo o obciążenie systemu, jak zamieszanie związane z dużą liczbą gałęzi. Martwię się również trochę, że zmiany dokonane w stosie gałęzi wydania nie zostaną scalone z innymi gałęziami wydania, które powinny je uzyskać, nie wspominając o głównej linii. Czy napotkałeś tego rodzaju problemy?
JoeGeeky,
@JoeGeeky: nie, nie ma zamieszania. Zobacz aktualizację mojej odpowiedzi.
Marjan Venema
2

Chodzi o kontekst: jak często wypuszczasz i co zawiera wydanie.

Oto trochę studium przypadku, które miałem ze swoją starą pracą, używając metody B (nazwaliśmy ją gałąź według celu ).

Aby umieścić historię w kontekście,

  • Wydanie składało się z nowych funkcji naszego oprogramowania: nowych trybów gry, nowych funkcjonalności, nowych opcji konfiguracji.
  • Cykl wydawania był dość długi: naszymi klientami były uniwersytety, które trzymałyby się jednego zestawu funkcji przez zwykle rok.

Główny rozwój został wprowadzony do pnia, dopóki nie osiągnęliśmy stanu pełnej funkcjonalności dla niektórych wydań. W tym momencie utworzylibyśmy gałąź, powiedzmy projectname-styczeń2012, i przeprowadzilibyśmy testy jakości i poprawki błędów w tej właśnie gałęzi. Gdy będziemy gotowi do publicznego wydania, oznaczymy kod w tej gałęzi i wydamy.

Jednak rozwój tej wersji nie zakończył się na tym tagu. Nieuchronnie mieliśmy klientów, którzy znaleźli błędy lub drobne problemy z wydaniem. W takim przypadku wystarczy wrócić do tej gałęzi, załatać kod i utworzyć nową oznaczoną wersję gałęzi stycznia 2012, która zostanie wydana, i scalić poprawki z powrotem do linii głównej.

W naszym przypadku takie podejście było korzystne, ponieważ niektórzy użytkownicy woleli pozostać przy starszych wersjach z ograniczonym zestawem funkcji, lub po prostu dlatego, że koszty wdrożenia w ich infrastrukturze raczej nowej wersji niż poprawki spowodowały pewne problemy.

Pytania, które musisz sobie zadać, to:

  • Jak często wypuszczam?
  • Czy moje wydania będą w 100% kompatybilne wstecz?
  • Czy moi klienci będą w stanie całkowicie zaktualizować system, aby naprawić błędy?

Jeśli często wypuszczasz, być może nie warto mieć gałęzi dla każdego z nich. Jeśli jednak cykl wydawania jest dość długi jak w moim starym przypadku użycia, a to wdrożenie, kompatybilność wsteczna i klienci przywiązujący się do starych wydań mogą stanowić ryzyko, opcja B z pewnością zaoszczędzi ci wiele bólu i ułatwi obsługę. Twoi klienci przy minimalnym koszcie radzenia sobie z bałaganem w oddziale.

Bushibytes
źródło
Podoba mi się, jak określasz tę opcję. W tym przypadku jesteśmy naszymi klientami ( w pewnym sensie ), więc wdrożenie będzie w dużej mierze pod naszą kontrolą. Jesteśmy również sklepem Scrum i oczekujemy dość częstych cykli wydawania ( np. Co 2-4 tygodnie ). Mamy nadzieję, że będziemy obsługiwać uaktualnienia stopniowe, ale kompatybilność wsteczna będzie problemem tylko tak długo, jak długo zajmie to wdrożenie uaktualnień, więc ... może minuty. Z tego dźwięku; z twojego doświadczenia; opcja B może nie być dla mnie najlepszym wyborem. Dzięki za informacje, bardzo interesujące.
JoeGeeky 21.01.12
Ach tak, w tym przypadku opcja B brzmi jak bałagan z niewielkim zwrotem. Chciałem tylko podkreślić, że obie opcje są realne i mają swoje zalety. Zapomniałem wyraźnie wspomnieć: jak sobie radzisz z poprawkami błędów? Czy są one umieszczane wyłącznie w nowych wersjach, czy też w łatkach / łatanych starych wersjach?
Bushibytes
1

Wolę opcję A. Rozwijaj wersje pnia i gałęzi, gdy są stabilne. To znacznie ogranicza pracę nad integracją poprawek zastosowanych do wersji produkcyjnej.

Kontraktowano mnie, aby pomóc zespołowi, który próbował opcji B, wrócić na właściwe tory.

Kilka rzeczy do rozważenia.

  • Migruj poprawki do przodu przez wszystkie aktywne gałęzie kodu. Można tego dokonać poprzez scalenie, łatanie i / lub przebudowę. Należy nimi w pełni zarządzać, aby zapewnić zastosowanie poprawki do wszystkich odpowiednich wydań, a następnie do magistrali.
  • Rozważ gałęzie funkcji, aby umożliwić tworzenie funkcji w oderwaniu od głównego strumienia kodu. Są one zalecane w przypadku zmian eksperymentalnych. Jeśli funkcja nie działa, możesz zrezygnować z gałęzi funkcji.
  • Oznacz i śledź punkty scalania.
  • Rozgałęź swoje wydania, jeśli jest to wymagane. Uważam, że dzieje się tak zwykle, gdy wydanie jest gotowe do wydania kompilacji kandydatów do wydania. W niektórych przypadkach wprowadzenie niekompatybilnych zmian do pnia może wymusić i wczesne rozgałęzienie. Rozważ gałąź funkcji.
BillThor
źródło
0

Przez kilka lat pracowałem nad systemem, który wykorzystuje coś pomiędzy dwoma opisanymi przez ciebie schematami. Kluczem jest to, że stosowany jest wielopoziomowy schemat numeracji. Poziom zewnętrzny jest w zasadzie wersją API i jest zarządzany w gałęziach (z odpowiednimi połączeniami krzyżowymi, gdy coś musi zostać naprawione w wielu gałęziach), a poziom wewnętrzny to dokładnie wykonane wydania, którymi zarządza się za pomocą tagów.

W szczególności, jeśli wiemy, jaką dokładnie wersję ma klient, wiemy dokładnie, z jakiego źródła został zbudowany kod i możemy wykonać dokładną kopię, abyśmy mogli dokładnie zobaczyć, co się dzieje. Jest to bardzo ważne dla wsparcia! Jednak zewnętrzny poziom gałęzi, wersje API, które obecnie wypuszczamy, ewoluują w miarę upływu czasu (główny trzon rozwoju otrzymuje większość nowych funkcji). Ponadto, kiedy robimy nowe główne wydanie API, tworzymy nowy oddział do obsługi tego (z tego, że bagażnik może być zawsze zorientowany na rozwój) i zastanawiamy się, czy powinniśmy wycofać z eksploatacji bieżące najstarsze wsparcie gałąź.

Dlatego polecam coś, co naprawdę jest mieszanką zarówno A, jak i B ; oba mają dobre aspekty, ale żadne z nich nie jest kompletne samo w sobie. Wykorzystaj to, co najlepsze z obu światów.

Donal Fellows
źródło
0

W przeszłości korzystałem z TFS, aby skutecznie wdrożyć opcję (B).

Rozgałęzianie / scalanie jest doskonałym narzędziem, gdy jest wykonywane w małych kawałkach. Trudność nie polega na tym, by gałąź (to głupio było łatwe), ani na przesunięciu tygodnia pracy z powrotem na drzewo (to zwykle też jest łatwe) ... polega na tym, aby system CI za kontrolą źródła automatycznie pracował dla ty.

Ponieważ rozgałęzienie jest dyskusyjne, jeśli system nie buduje i nie uruchamia automatycznie testów dla twojego oddziału.

Dostosowaliśmy domyślny przepływ pracy kompilacji TFS, aby rozpoznawał ścieżki względne zestawów zmian, i ustanowiliśmy konwencję, dzięki której dostosowanie może rozpoznać nową gałąź (w przeciwieństwie do po prostu nowego podfolderu w katalogu głównym programowania). Był płynny, łatwy do rozgałęzienia, łatwy do zabicia oddziału, i otrzymywaliśmy ciągłe informacje zwrotne z naszego systemu dotyczące kompilacji i testów.

Widzę wiele osób deklarujących, jak niemożliwe są te strategie w TFS, i sądzę, że jest to spowodowane brakiem znajomości możliwości silnika kompilacyjnego opartego na XAML. TFS to nie tylko kontrola źródła, to całe rozwiązanie i powinno być używane jako takie.

Craig Brunetti
źródło