Co to jest trunk based development? Przewodnik dla solo deva
Summary
Co to jest trunk based development? To model pracy, w którym zespół scala małe zmiany do jednej wspólnej gałęzi co najmniej raz dziennie, a niedokończoną pracę chowa za flagami funkcji. Trunk zostaje gotowy do wydania przy każdym commicie. Dla solo deva i małych zespołów oznacza to mniej konfliktów, szybszy feedback z CI i prostsze review. Warunek: testy, którym ufasz, i szybki sposób na cofnięcie zmian.
Co to jest trunk based development? To model pracy z gałęziami, w którym wszyscy scalają małe zmiany do jednej wspólnej gałęzi, zwykle nazywanej main albo trunk, co najmniej raz dziennie. Gałęzie, jeśli w ogóle je tworzysz, żyją godziny, a nie tygodnie. Niedokończona praca trafia do kodu schowana za flagą, więc trunk zostaje gotowy do wydania przy każdym commicie. To cała idea i jest mniej egzotyczna, niż sugeruje nazwa.
Oto scena, która to dobrze pokazuje. Otwierasz side project, który zostawiłeś trzy tygodnie temu. Gałąź z funkcją jest 41 commitów za main, dwa pliki mają konflikty, a to, co budowałeś, nie pasuje już do reszty kodu. Trunk based development to nawyk, który nie dopuszcza do takiej sceny.
Co tak naprawdę oznacza trunk based development?
Serwis trunkbaseddevelopment.com opisuje to jako model kontroli wersji, w którym programiści pracują na jednej wspólnej gałęzi i unikają innych gałęzi żyjących długo. Bezpośrednie commity do trunk są w porządku w bardzo małych zespołach. Pull requesty też, o ile gałęzie są krótkotrwałe i powstają z pracy jednej osoby.
Za większość tego modelu odpowiadają trzy zasady.
Scalaj do trunk przynajmniej raz na 24 godziny.
Pilnuj, żeby trunk był zielony: zepsuty build na main to priorytet dla wszystkich.
Ukrywaj niedokończoną pracę za flagami funkcji zamiast trzymać ją w osobnej gałęzi.
Zauważ, czego tu brakuje. Nie ma gałęzi develop, nie ma długiej gałęzi wydaniowej dla każdej funkcji, nie ma fazy integracji na końcu, kiedy wszyscy odkrywają, że ich kod do siebie nie pasuje. Przy starszych modelach ból się kumuluje i spada na raz.

Dlaczego to lepsze niż długo żyjące gałęzie w małych zespołach?
Długo żyjąca gałąź to pożyczka. Każdego dnia oddala się trochę od main, a odsetki płacisz konfliktami przy scalaniu, nieaktualnymi założeniami i review, których nikt nie domknie, bo diff dotyka 60 plików.
Strona DORA o trunk-based development wiąże te praktyki z lepszą szybkością dostarczania, stabilnością i dostępnością, na podstawie badań State of DevOps. Według niej warto mieć trzy lub mniej aktywnych gałęzi w repozytorium, scalać do trunk przynajmniej raz dziennie i unikać zamrożeń kodu oraz faz integracji. To konkretne, mierzalne cele, a w tej branży rzadko się je spotyka.
Dla solo dewelopera albo zespołu z trzech osób argument jest jeszcze prostszy. Małe scalenia łatwo przejrzeć, łatwo cofnąć i łatwo zrozumieć pół roku później, gdy o 22 czytasz git blame i zastanawiasz się, co myślał sobie wtedy ty.
Trzy powody, żeby to zrobić, i jeden, żeby tego nie robić. Powody: mniejsze diffy, szybszy feedback z CI i main, który możesz wdrożyć w piątek bez nerwów. Powód przeciw: jeśli testy są cienkie, codzienne scalanie tylko szybciej rozprzestrzenia błędy. Do tego wrócimy niżej.
Krótkotrwałe gałęzie czy commit prosto do main?
Oba warianty to trunk based development. Różnica polega na tym, ile bezpieczeństwa chcesz mieć, zanim kod trafi do wspólnej historii.
Commit bezpośrednio do main działa, gdy pracujesz sam albo w parze, lokalny build trwa poniżej minuty i ufasz swoim testom. To najszybsza pętla, jaka istnieje. Większość solo builderów już tak robi, nawet nie nazywając tego w ten sposób.
Krótkotrwałe gałęzie z pull requestem mają sens, gdy dołącza druga albo trzecia osoba, albo gdy chcesz, żeby CI odpaliło się na czystym checkoucie przed scaleniem. Cała dyscyplina siedzi w słowie krótkotrwałe. Gałąź, która przetrwa do następnego dnia, już dryfuje w stronę modelu, z którego chcesz uciec.
Praktyczna rutyna, która się sprawdza:
Zaciągnij main i utwórz gałąź o nazwie, która mówi, czym jest zmiana.
Zrób najmniejszą zmianę, która przesuwa sprawę do przodu, i uruchom pełny build lokalnie.
Otwórz PR, pozwól CI przejść i scal tego samego dnia.
Usuń gałąź. Nie pozwól, żeby się nawarstwiały.
Jeśli zmiany nie da się zrobić w jeden dzień, odpowiedzią nie jest dłuższa gałąź. Odpowiedzią jest pocięcie zmiany na cieńsze plasterki.
W praktyce najtrudniej zauważyć, że gałąź jest za długa, zanim zacznie boleć. Dobry sygnał to moment, w którym zaczynasz wątpić, czy twoja zmiana w ogóle pasuje do obecnego kodu. Wtedy scalenie jest już nerwowe, a nie rutynowe. Zapytaj się wcześniej, co w tej zmianie da się wydzielić jako osobny, bezpieczny krok: zmiana nazwy, dodany test, wydzielona funkcja albo nowy element schowany za flagą. Każdy taki krok możesz scalić dziś, a reszta zmiany poczeka w kolejce, zamiast gnić na osobnej gałęzi.
Jak wysłać niedokończoną pracę, nie psując main?
To pytanie zatrzymuje większość ludzi. Jeśli scalasz codziennie, będziesz scalać kod funkcji, które jeszcze nie istnieją. Radzą sobie z tym dwie techniki.
Pierwsza to flaga funkcji. Nowa ścieżka kodu jest scalona, ale wyłączona, więc użytkownicy jej nie widzą. Flaga może być równie prosta jak zmienna środowiskowa typu boolean:
const showNewCheckout = process.env.FEATURE_NEW_CHECKOUT === "true";
export function Checkout() {
return showNewCheckout ? <NewCheckout /> : <OldCheckout />;
}Na side project to wystarczy. Gdy potrzebujesz kierowania ruchu, stopniowych wdrożeń albo wyłącznika awaryjnego bez ponownego deployu, zarządzana usługa zaczyna się opłacać.
Druga technika to branch by abstraction, do większych zmian, na przykład wymiany klienta bazy danych albo dostawcy płatności. Stawiasz interfejs przed starą implementacją, budujesz nową za tym samym interfejsem, przenosisz wywołania fragment po fragmencie, a potem usuwasz starą. Każdy krok to małe scalenie do trunk i nic nie leży w długiej gałęzi.

Jedna uczciwa uwaga o flagach: to dług. Flaga, która siedzi w kodzie przez rok, jest gałęzią w przebraniu. Przypisz każdej flagi właściciela i datę usunięcia, a gdy funkcja jest w pełni wdrożona, skasuj ją.
Czego potrzebuje twoje CI, zanim spróbujesz?
Trunk based development bez siatki bezpieczeństwa to po prostu szybkie psucie rzeczy. Zanim zobowiążesz się do codziennego scalania, potrzebujesz trzech rzeczy.
Build uruchamiany przy każdym pushu, który kończy się w minutach, a nie w pół godziny.
Testy, które padają, gdy coś realnego się zepsuje. Liczby pokrycia mają mniejsze znaczenie niż to, czy zła zmiana zostanie złapana.
Szybki sposób na wycofanie: revert commita albo wyłączenie flagi.
Analiza statyczna to tania dodatkowa warstwa. Wyłapuje klasę problemów, takich jak oczywiste błędy, podejrzane wzorce bezpieczeństwa i zduplikowany kod, zanim człowiek przeczyta diff.
Jeśli jesteś jedynym recenzentem, narzędzia wskazujące ryzykowne miejsca pomagają jeszcze bardziej, bo nikt inny nie powie ci, że plik, który ciągle edytujesz, zamienia się w bałagan.
Nie zakładaj, że pierwszego dnia potrzebujesz ciężkiego pipeline'u. Jeden plik workflow, który instaluje zależności, lintuje, testuje i wdraża main, to dobry start. Działa, nie jest optymalny i warto to zrobić mimo to: to pierwsza wersja, która działa, a zaostrzysz ją później.
Gałęzie wydaniowe, hotfixy i rzeczy, które wciąż wymagają uwagi
Trunk based development nie zabrania gałęzi wydaniowych. Niektóre zespoły wycinają gałąź z trunk tuż przed wydaniem, utwardzają ją, wypuszczają i usuwają. Inne wydają prosto z trunk i naprawiają do przodu, gdy pojawi się błąd. Dla aplikacji webowej wdrażanej kilka razy w tygodniu naprawianie do przodu jest niemal zawsze prostsze.
Aplikacje mobilne i wszystko, co przechodzi powolną weryfikację w sklepie, to inna historia. Tam można trzymać krótkotrwałą gałąź wydaniową dla każdej wersji, żeby łatać to, co już jest u użytkowników. Nawet wtedy zasada zostaje: poprawki lądują najpierw na trunk, a potem są przenoszone cherry-pickiem, nigdy odwrotnie.
Hotfixy działają tak samo. Napraw na trunk, wdróż, gotowe. Osobna gałąź hotfix, która nigdy nie wraca do main, to sposób, w jaki zespoły dostają dwie rozjeżdżające się historie.

Jak wygląda realistyczny pierwszy tydzień?
Pierwszego dnia sprawdź, jak dziś wygląda rozgałęzianie w twoim repo. Wypisz otwarte gałęzie i zanotuj wiek każdej. Wszystko starsze niż kilka dni to kandydat do scalenia albo usunięcia. Samo to często pokazuje, gdzie leży tarcie.
Drugiego dnia dodaj mechanizm flag. Nawet zmienna środowiskowa wystarczy. Wybierz jedną funkcję w toku, schowaj jej punkt wejścia za flagą i scal to, co masz.
Dni trzeci do piątego to zmiana nawyku. Tnij każde zadanie na kawałki, które mogą wylądować w ciągu dnia, i scalaj każdy kawałek, gdy CI przejdzie. Spodziewaj się, że pierwsze kawałki będą wydawać się za małe. Nie są. Commit, który dodaje uśpioną kolumnę w bazie albo nieużywaną funkcję, to w pełni dobra jednostka postępu, bo jest bezpieczna, przejrzana i już zintegrowana.
Pod koniec tygodnia będziesz wiedzieć dwie rzeczy: czy twoje testy są wystarczająco wiarygodne i które części kodu opierają się małym zmianom. Obie są przydatne, a żadna nie wychodzi na jaw, gdy pracujesz na długich gałęziach.
Nie potrzebujesz dashboardu, żeby to ocenić. Patrz, jak długo żyją twoje gałęzie, jak często main jest czerwony i ile czasu zajmuje zmiana od pierwszego commita do produkcji. Jeśli wiek gałęzi maleje, a wdrożenia stają się nudne, nawyk się opłaca.
Jeśli chcesz liczb o wpływie na użytkowników tego, co wysyłasz za flagami, narzędzie do eksperymentów może powiązać rollout z realnymi metrykami zamiast z przeczuciem.
Dla zespołu jednoosobowego zwykły zeszyt też wystarczy. Zapisuj co tydzień czas od scalenia do wdrożenia przez miesiąc. Trend powie ci więcej niż jakakolwiek pojedyncza liczba.
Przejść na to czy poczekać?
Przejdź, jeśli pracujesz sam, w parze albo w małym zespole z testami, którym ufasz tylko połowicznie, i CI, które da się poprawić. Koszt próby to tydzień lekko niewygodnych, małych commitów. Koszt długich gałęzi płacisz konfliktami i wolnymi review, a rośnie on z każdym współpracownikiem.
Poczekaj, jeśli nie masz żadnych automatycznych testów i nie masz jak cofnąć zmian. Najpierw to napraw, bo codzienne scalanie do nieprzetestowanego trunk tylko przesuwa ból w inne miejsce.
To nie jest idealna metoda. Jest wykonalna. Wybierz następną małą zmianę w swoim obecnym projekcie, scal ją dziś i zobacz, jak to wygląda. Jaki jest najmniejszy kawałek twojej obecnej funkcji, który mógłbyś wysłać jeszcze dziś wieczorem?