Czy częste, skomplikowane konflikty scalania są oznaką problemów?

35

W naszym zespole używamy Git jako naszej kontroli źródła. Mamy kilka obszarów kodu, które są prawie niezależne, ale nakładają się na siebie. Ostatnio dyskutowaliśmy o przepływach pracy i podejściach do korzystania z kontroli źródła. Jedną skargą, która pojawia się, gdy promuję użycie przepływu pracy gałęzi funkcji, jest to, że ludzie często napotykają skomplikowane konflikty scalania, które nieprawidłowo rozwiązują. Przez skomplikowane rozumiem „nie oczywiste, jak rozwiązać”. W związku z tym aktywniej wykorzystywane są inne przepływy pracy, takie jak przepływ pracy oparty na „pull rebase”.

Jako zwolennik podejścia do gałęzi funkcji, tak naprawdę nie otrzymuję skargi. Tak, musisz aktualizować lokalne oddziały funkcji od głównego lub gdziekolwiek, ale to jedyny prawdziwy problem, jaki widzę. Myślę, że jeśli twoje połączenia są zawsze skomplikowane i mogą mieć drugorzędne skutki, to jest to bardziej problem pracy zespołowej niż problem Git.

Czy mam rację, myśląc o tym? Czy skomplikowane konflikty scalania są oznaką czegoś dobrego lub złego?

joshin4colours
źródło
1
Jak długo działają funkcje? Jak dobrze zmodularyzowany jest kod? Czy mógłbyś (na przykład) wybrać Cherry w zatwierdzeniu kodu testowego (zostało to zrobione najpierw i oddzielić od rzeczywistego kodu, prawda?), Aby zobaczyć, jak zmieniła się funkcjonalność?
@MichaelT Baza kodu jest przeznaczona dla naszej bazy automatycznego kodu testowego. Zaraz rozpoczniemy pracę nad nowym dodatkiem do naszego projektu, który prawdopodobnie będzie wymagał nieco równoległego rozwoju. Stąd dyskusja między gałęziami funkcji a innymi.
joshin4colours
7
Czy ludzie rzeczywiście napotykają tego rodzaju problemy, czy tylko obawiają się, że problemy te się pojawią?
Christopher Creutzig
2
Nawiasem mówiąc, NIESAMOWITY samouczek, z którym masz link :)
Vorac,
1
Ponowne utworzenie gałęzi funkcji lub scalenie jej z pniem powoduje podobne scalenia. Rebasing faktycznie powoduje więcej połączeń i dlatego istnieje większe prawdopodobieństwo wystąpienia złych konfliktów. Liczy się to, jak często się to robi.
Jan Hudec,

Odpowiedzi:

23

Problemem jest twój kod. Jeśli twoja baza kodu ma wiele wzajemnych relacji między modułami, to każda zmiana będzie wszędzie miała wąsy, a każdy deweloper będzie współdziałał z kodem innej osoby, będzie to koszmar.

Sądzę, że najpierw zauważysz to na inne sposoby, ale możliwe, że jesteś do tego tak przyzwyczajony, że już go nie widzisz.

Michael Kohne
źródło
9
To była moja pierwsza myśl. Skomplikowane konflikty scalania występują, gdy w tym samym kodzie wprowadzanych jest wiele zmian. Jeśli masz dość młody projekt, jest to powszechne, ale jeśli masz spore podstawy kodu, może to być oznaką „boskich obiektów” lub tego, że niektóre moduły / klasy robią za dużo i trzeba je zrestrukturyzować. Może to również wynikać z nadgorliwych sprawców popełniających dziesiątki drobnych zmian, ale jest to mniej powszechne.
TMN
1
Fakt, że nasza baza kodów jest nieco „młoda” (w wieku około 6 miesięcy, przeszła kilka poważnych refaktorów), może być tego wskaźnikiem.
joshin4colours 16.08.13
10
@ joshin4colours Jeśli refaktoryzujesz, gdy ktoś pisze dużą funkcję, masz kłopoty.
Sean McSomething
17

Jestem przyzwyczajony do przepływu pracy „fetch-rebase-push”. Który jest tak naprawdę pierwszym, najbardziej prymitywnym przepływem pracy opisanym w samouczku Oto zalety:

  • Prawdziwa ciągła integracja
  • Wczesne zarządzanie konfliktami - zaraz po napisaniu i przetestowaniu kodu
  • Szybka odpowiedź - „Hej, Bob, sześcienna interpolacja daje zabawne wyniki, czy mógłbyś na to spojrzeć, kiedy jestem na lunchu?”
  • Nie wymaga łączenia - czyste oś czasu, tak jakby jeden programista napisał wszystko

Teraz dotyczy skomplikowanych konfliktów scalania. Nie rozumiem, jak można doświadczyć zarówno częstych, jak i skomplikowanych połączeń. Powikłanie powstaje w wyniku nieudanej przerwy w zbiorze / zbierania wiśni przez długi czas, pracując nad tą samotną funkcją przez miesiąc.

Osobiście wolałbym radzić sobie z częstymi konfliktami scalania (a właściwie bazowania) niż z rzadkimi, obejmującymi wszystko horrorami scalania.

Vorac
źródło
1
Świetny opis dobrego przepływu pracy w Git, ale to nie do końca odpowiada moje pytanie.
joshin4colours 16.08.13
2
@ joshy to prawda. Tylko środkowy akapit odpowiada na twoje pytanie. Ale tutaj jest bezpośrednia odpowiedź. Jeśli łączenie jest częste i trudne, oznacza to z pewnością problematyczny przepływ pracy / problem z komunikacją / problem z architekturą / podział lub problem z rolami.
Vorac,
7

Fuzje i rebazy powinny powodować dokładnie te same konflikty, dla tych nieodłącznych konfliktów, które człowiek musi rozwiązać (tj. Dwóch programistów zmieniających ten sam wiersz kodu). W przypadku innych konfliktów scalenia wydają się być czystsze, ponieważ nie zmieniasz SHA-1 zatwierdzeń w całym miejscu. Nie jestem pewien, jak udaje ci się doprowadzić do stanu, w którym fuzje powodują więcej konfliktów niż rebaseów, ale z pewnością jest to znak, że przepływ pracy niektórych ludzi jest pomieszany i prawdopodobnie potrzebują więcej szkolenia na temat działania git. Czy usuwają zobowiązania do scalania innych osób, kiedy robią swoje lokalne bazy, czy coś takiego?

Zaletą i wadą metody pull-rebase jest to, że jest bardzo podobna do scentralizowanych przepływów pracy, do których przywykło wiele osób. Nie musisz rozumieć rozgałęziania, aby z niego korzystać.

W każdym razie jest to całkowicie wykonalne, aby wykonać przepływ pracy gałęzi funkcji tylko lokalnie, jeśli nie możesz zmusić innych osób do zalogowania się do niego.

Karl Bielefeldt
źródło
5

Projekt, nad którym pracuję, od czasu do czasu ma tego typu problemy i wydaje się, że wynika on z kilku czynników:

  • Używamy programu Visual Studio, a pliki takie jak Visual Studio .sln to tylko dokumenty XML (które nie reagują dobrze na scalanie tekstów) pełne przewodników (których Git nie rozumie lepiej niż reszta z nas) i mogą być łatwo źle scalone i powodują utratę plików.
  • Niektóre osoby pracują nad podobnymi obszarami kodu, dzięki czemu wprowadzane zmiany mogą znajdować się obok siebie w klasach. Chociaż w tej sytuacji jest to nieuniknione, ten typ konfiguracji będzie bardzo ciężką pracą dla dowolnego systemu kontroli źródła. Nawet jeśli masz świetną komunikację w zespole, czasem ludzie nie zdają sobie sprawy, że napotykają się nawzajem na kod i powstają konflikty.

Interesuje mnie potencjał Semantic Merge, aby pomóc w rozwiązaniu niektórych z tych problemów, ale oczywiście jest to tylko użyteczne, jeśli pracujesz w języku, który można analizować, a ja nie spotkałem się jeszcze z żadnymi znaczącymi wyzwaniami, gdy „ używam go, więc nie mogę ręczyć za jego skuteczność.

glenatron
źródło
4

O ile programiści nie modyfikują historycznych zatwierdzeń (zamiast czystych scaleń), konflikty w gitowym modelu przepływu pracy cech są oznaką ściśle powiązanej bazy kodowej (/ brandnew codebase) lub nakładającego się przypisania funkcji.

sjakubowski
źródło
0

Masz gałąź główną (główną) i wszyscy pracują w swoich gałęziach funkcji.

Praca w gałęziach funkcji może potrwać od kilku godzin do kilku miesięcy.

Co jakiś czas ktoś odwróci scalanie zestawu zmian z powrotem do głównej gałęzi. Kierownik zespołu musi upewnić się, że tylko jedna osoba jednocześnie wykonuje odwrotne scalenie. Po wykonaniu tej czynności musisz przekazać scalanie z gałęzi głównej do gałęzi funkcji. Gdy wszyscy dokonają scalania w przód, innej osobie można zezwolić na odwrócenie scalania do głównej gałęzi. W przeciwnym razie zbyt wiele zmian zostanie scalonych odwrotnie, a podczas scalania do przodu będziesz mieć mnóstwo konfliktów scalania.

Aby wyjaśnić terminologię, przez „scalanie zwrotne” rozumiem łączenie z gałęzi funkcji do gałęzi głównej, a przez „scalanie do przodu” mam na myśli łączenie gałęzi głównej z gałęzią funkcji. Na podstawie tego, czego doświadczyłem wcześniej, prawdopodobnie zobaczysz więcej konfliktów scalania podczas scalania odwrotnego, w przeciwieństwie do scalania do przodu.

CodeART
źródło
1
Połączenie z główną gałęzią nigdy nie może powodować żadnych konfliktów. Zawsze najpierw łączysz główny z funkcyjnym, więc funkcja z głównym jest wtedy wolna od konfliktów.
gnasher729
@ gnasher729 - Myślę , że tak właśnie brzmi ta odpowiedź - sugeruję, że każdy programista łączy się z gałęzi main do ich gałęzi funkcji za każdym razem, gdy ktoś zatwierdza cokolwiek do main, tak aby wszystkie konflikty zostały natychmiast rozwiązane w gałęziach funkcji.
Periata Breatta
Powiedział: „bardziej prawdopodobne jest, że konflikty łączą się z funkcji na mistrza”
gnasher729,
0

Dwie rzeczy, które mogą pomóc: Po pierwsze, unikaj narzędzi, które same wprowadzają zmiany. Dwóch programistów używających różnych ustawień kart to przepis na katastrofę. Po drugie, wprowadź zmiany w różnych lokalizacjach. Problem pojawia się na przykład, gdy trzech programistów dodaje kod na końcu tego samego pliku - znacznie lepiej, jeśli dodają kod w różnych miejscach.

gnasher729
źródło