Robimy projekty, ale ponownie wykorzystujemy dużo kodu między projektami i mamy wiele bibliotek, które zawierają nasz wspólny kod. Wdrażając nowe projekty, znajdujemy więcej sposobów na wyróżnienie wspólnego kodu i umieszczenie go w bibliotekach. Biblioteki zależą od siebie, a projekty zależą od bibliotek. Każdy projekt i wszystkie biblioteki używane w tym projekcie muszą używać tej samej wersji wszystkich bibliotek, do których się odnoszą. Jeśli wydamy oprogramowanie, będziemy musieli naprawiać błędy i być może dodawać nowe funkcje na wiele lat, czasem na dziesięciolecia. Mamy około tuzina bibliotek, zmiany często dotyczą więcej niż dwóch, a kilka zespołów pracuje nad kilkoma projektami równolegle, wprowadzając jednocześnie zmiany we wszystkich tych bibliotekach.
Niedawno przeszliśmy na git i skonfigurowaliśmy repozytoria dla każdej biblioteki i każdego projektu. Używamy skrytki jako wspólnego repozytorium, robimy nowe rzeczy na gałęziach funkcji, a następnie wysyłamy żądania ściągania i scalamy je dopiero po przejrzeniu.
Wiele problemów, z którymi mamy do czynienia w projektach, wymaga zmian w kilku bibliotekach i specyficznym kodzie projektu. Często obejmują one zmiany interfejsów bibliotek, z których niektóre są niezgodne. (Jeśli uważasz, że to brzmi podejrzanie: łączymy się ze sprzętem i ukrywamy konkretny sprzęt za ogólnymi interfejsami. Niemal za każdym razem, gdy integrujemy sprzęt innego dostawcy, spotykamy się z przypadkami, których nasze interfejsy nie przewidywały i dlatego musimy je udoskonalić.) przykład, wyobrazić sobie projekt P1
z wykorzystaniem bibliotek L1
, L2
i L3
. L1
również używa L2
i L3
, i również L2
używa L3
. Wykres zależności wygląda następująco:
<-------L1<--+
P1 <----+ ^ |
<-+ | | |
| +--L2 |
| ^ |
| | |
+-----L3---+
Teraz wyobraź sobie, cechą tego projektu wymaga zmiany P1
i L3
który zmienia interfejs L3
. Teraz dodaj projekty P2
i P3
do miksu, które również odnoszą się do tych bibliotek. Nie możemy sobie pozwolić na przełączenie ich wszystkich na nowy interfejs, przeprowadzenie wszystkich testów i wdrożenie nowego oprogramowania. Więc jaka jest alternatywa?
- zaimplementuj nowy interfejs w
L3
- zgłoś prośbę
L3
i poczekaj na recenzję - scal zmiany
- utwórz nową wersję
L3
- rozpocznij pracę nad funkcją
P1
, odwołując się doL3
nowej wersji, a następnie zaimplementuj funkcję wP1
gałęzi funkcji - zgłoś żądanie ściągnięcia, sprawdź je i połącz
(Właśnie zauważyłem, że zapomniałem przełączyć L1
i L2
do nowej wersji. A ja nawet nie wiem gdzie trzymać to w, bo to muszą być wykonane równolegle P1
...)
Jest to żmudny, podatny na błędy i bardzo długi proces wdrażania tej funkcji, wymaga niezależnych recenzji (co znacznie utrudnia przeglądanie), w ogóle się nie skaluje i prawdopodobnie wyklucza nas z działalności, ponieważ ugrzęznąć w procesie, nigdy nic nie możemy zrobić.
Ale w jaki sposób wykorzystujemy rozgałęzianie i tagowanie, aby stworzyć proces, który pozwala nam wdrażać nowe funkcje w nowych projektach bez nadmiernego obciążenia?
Odpowiedzi:
To coś w rodzaju ujawnienia tego, co oczywiste, ale może warto o tym wspomnieć.
Zwykle repozytorium git jest dostosowywane do lib / projektu, ponieważ zazwyczaj są one niezależne. Aktualizujesz swój projekt i nie przejmujesz się resztą. Inne projekty w zależności od tego po prostu aktualizują swoją bibliotekę, kiedy tylko uznają to za stosowne.
Wydaje się jednak, że Twój przypadek jest wysoce zależny od skorelowanych komponentów, więc jedna cecha zwykle wpływa na wiele z nich. A całość musi być zapakowana jako pakiet. Ponieważ implementacja funkcji / zmiany / błędu często wymaga jednoczesnego dostosowania wielu różnych bibliotek / projektów, być może warto umieścić je wszystkie w tym samym repozytorium.
Są to silne zalety / wady.
Zalety:
Wady:
Od Ciebie zależy, czy cena jest warta korzyści.
EDYTOWAĆ:
Działa to tak:
feature_x
feature_y
ifeature_z
może również zostało dodane. Staje się połączeniem „cross-team”. Dlatego jest to poważna wada.tylko dla przypomnienia: myślę, że w większości przypadków jest to zły pomysł i należy to robić ostrożnie, ponieważ wada scalania jest zwykle wyższa niż ta, którą uzyskujesz dzięki zarządzaniu zależnościami / właściwemu śledzeniu funkcji.
źródło
:-/
Co więcej, nawet ci, którzy są (i którzy nalegali na przejście na git), nie wiedzą, jak dostosować nasz proces rozwoju do git. Westchnienie. Obawiam się, że minie kilka trudnych miesięcy, aż sprawy staną się gładsze. W każdym razie dzięki, twoja jest najbardziej / jedyną pomocną odpowiedzią do tej pory.Rozwiązaniem, którego szukasz, jest narzędzie do zarządzania zależnościami w koordynacji z submodułami git
Narzędzia takie jak:
Możesz użyć tych narzędzi do zdefiniowania zależności projektu.
Możesz wymagać, aby submoduł był co najmniej w wersji > 2.xx lub oznaczał zakres wersji, które są kompatybilne = 2.2. * Lub mniej niż konkretna wersja <2.2.3
Ilekroć wypuszczasz nową wersję jednego z pakietów, możesz oznaczyć go numerem wersji, w ten sposób możesz pobrać tę konkretną wersję kodu do wszystkich innych projektów
źródło
Submoduły
Powinieneś spróbować zdobyć moduły podrzędne , jak sugerowano w jednym komentarzu.
Kiedy projekt
P1
odnosi się do trzech submodułówL1
,L2
iL3
, faktycznie przechowuje odniesienie do poszczególnych zatwierdzeń we wszystkich trzech repozytoriów: są to robocze wersje poszczególnych bibliotek dla tego projektu .Tak więc wiele projektów może współpracować z wieloma podmodułami:
P1
może odnosić się do starej wersji biblioteki,L1
podczas gdy projektP2
korzysta z nowej wersji.Co się stanie, gdy dostarczysz nową wersję
L3
?L3
L2
współpracę zL3
, zatwierdzanie, ...L1
z nowymiL2
, ...P1
współpracuje z nowymi wersjami wszystkich bibliotek:P1
jest lokalna kopia roboczaL1
,L2
iL3
, fetche zmiany jesteś zainteresowany.git add L1 L2 L3
aby zatwierdzić nowe odniesienie do modułówP1
, test, przegląd, żądanie wyciągnięcia, scalenie ...Metodologia
Tak, wymaga niezależnych recenzji, ponieważ zmieniasz:
Czy zostałbyś wykluczony z działalności, ponieważ dostarczasz bzdury? (Właściwie może nie). Jeśli tak, musisz wykonać testy i przejrzeć zmiany.
Dzięki odpowiednim narzędziom git (nawet
gitk
) możesz łatwo zobaczyć, z których wersji bibliotek korzysta każdy projekt, i możesz je aktualizować niezależnie w zależności od potrzeb. Submoduły są idealne do twojej sytuacji i nie spowolnią twojego procesu.Może znajdziesz sposób na zautomatyzowanie części tego procesu, ale większość powyższych kroków wymaga ludzkiego mózgu. Najskuteczniejszym sposobem na skrócenie czasu jest zapewnienie łatwej ewolucji bibliotek i projektów . Jeśli twoja podstawa kodu potrafi z łatwością sprostać nowym wymaganiom, recenzje kodu będą prostsze i nie zajmą ci dużo czasu.
(Edytuj) kolejną rzeczą, która może ci pomóc, jest grupowanie powiązanych recenzji kodów. Zatwierdzasz wszystkie zmiany i czekasz, aż rozpowszechnisz je we wszystkich bibliotekach i projektach, które ich używają, zanim zasygnalizujesz żądania ściągnięcia (lub zanim się nimi zajmiesz). W końcu robisz większą recenzję dla całego łańcucha zależności. Może to pomoże ci zaoszczędzić czas, jeśli każda lokalna zmiana jest niewielka.
źródło
Rozumiem więc, że dla P1 chcesz zmienić interfejs L3, ale chcesz, aby inne P2 i P3, które zależą od interfejsu L3, zmieniły się od razu. Jest to typowy przypadek kompatybilności wstecznej. Jest ładny artykuł na temat zachowania kompatybilności wstecznej
Istnieje kilka sposobów rozwiązania tego problemu:
LUB
źródło
Jeśli dobrze rozwiązuję problem:
Zatem celem jest, abyś mógł wykonać P1 i L1 za jednym razem, a następnie miesiąc później zrobić L2 i L3 za jednym razem.
W świecie Java jest to trywialny i być może domyślny sposób pracy:
Możesz więc mieć kod na dysku lokalnym dla L3, który nie skompilowałby się, gdyby był kompilowany z kopią P1 w innym katalogu na dysku; na szczęście tak nie jest. Java może to zrobić bezpośrednio, ponieważ kompilowanie / łączenie opowieści jest oparte na skompilowanych plikach jar, a nie na kodzie źródłowym.
Nie znam wcześniej powszechnie używanego rozwiązania tego problemu dla świata C / C ++ i wyobrażam sobie, że prawie nie chcesz zmieniać języków. Ale można łatwo zhakować coś razem, tworząc pliki, które zrobiły to samo:
Możesz nawet użyć obsługi C / C ++ w maven , chociaż większość programistów C patrzyłaby na ciebie dziwnie, gdybyś ...
źródło
:)
Istnieje proste rozwiązanie: wycinanie gałęzi wydania w całym repozytorium, łączenie wszystkich poprawek do wszystkich aktywnie wysyłanych wersji (jest to łatwe w jasnym przypadku, powinno być możliwe w git).
Wszystkie alternatywy spowodują z czasem okropny bałagan i rozwój projektu.
źródło