W git
środowisku, w którym zmodularyzowaliśmy większość projektów, mamy do czynienia z jednym projektem na repozytorium lub wieloma projektami na problem z projektem repozytorium . Rozważmy projekt modułowy:
myProject/
+-- gui
+-- core
+-- api
+-- implA
+-- implB
Dzisiaj mamy jeden projekt na repozytorium . Daje swobodę
release
Poszczególne komponentytag
Poszczególne komponenty
Ale jest to również kłopotliwe dla branch
komponentów, ponieważ często rozgałęzienie api
wymaga równoważnych gałęzi core
i być może innych komponentów.
Biorąc pod uwagę, że chcemy release
poszczególne komponenty, możemy nadal uzyskać podobną elastyczność, wykorzystując wiele projektów na projekt repozytorium .
Jakie są doświadczenia i jak / dlaczego rozwiązałeś te problemy?
java
programming-practices
version-control
git
maven
Johan Sjöberg
źródło
źródło
git-describe
.Odpowiedzi:
Istnieją trzy główne wady
one project per repository
, takie jak opisałeś to powyżej. Są to mniej prawdziwe, jeśli są naprawdę odrębnymi projektami, ale od dźwięków tego zmiany do jednego często wymagają zmian w innym, co może naprawdę wyolbrzymić te problemy:git bisect
stają się znacznie trudniejsze w użyciu, gdy rozbijesz swoje repozytorium na sub-repozytoria. Jest to możliwe, po prostu nie jest tak łatwe, co oznacza, że polowanie na błędy w czasach kryzysu jest o wiele trudniejsze.git log
po prostu, nie wyświetlają tak istotnie historii ze złamanymi strukturami repozytorium. Możesz uzyskać użyteczne dane wyjściowe za pomocą podmodułów lub poddrzewa lub za pomocą innych metod skryptowych, ale to nie to samo, co pisanietig --grep=<caseID>
lubgit log --grep=<caseID>
skanowanie wszystkich zatwierdzeń, na których Ci zależy. Twoja historia staje się trudniejsza do zrozumienia, co czyni ją mniej użyteczną, gdy naprawdę jej potrzebujesz.Ostatecznie jest to kalkulacja kosztów alternatywnych. W jednym z byłych pracodawców nasza podstawowa aplikacja została podzielona na 35 różnych sub-repozytoriów. Do tego użyliśmy skomplikowanego zestawu skryptów do przeszukiwania historii, upewnienia się, że stan (tj. Gałęzie produkcyjne vs. programistyczne) był taki sam we wszystkich i wdrażaliśmy je pojedynczo lub masowo.
To było po prostu za dużo; przynajmniej za dużo dla nas. Narzuty związane z zarządzaniem sprawiły, że nasze funkcje stały się mniej zwinne, znacznie trudniejsze we wdrożeniach, uczyły nauczanie nowych deweloperów zbyt wiele czasu, a na koniec ledwo pamiętaliśmy, dlaczego przede wszystkim rozbiliśmy repozytorium. Pewnego pięknego wiosennego dnia wydałem 10 USD na popołudnie czasu obliczeniowego klastra w EC2. Przetarłem repo z kilkoma tuzinami
git filter-branch
połączeń. Nigdy nie oglądaliśmy się za siebie.źródło
Christopher bardzo dobrze wyliczył wady modelu jednego projektu na repozytorium. Chciałbym omówić niektóre z powodów, dla których warto rozważyć podejście oparte na wielu repozytoriach. W wielu środowiskach, w których pracowałem, podejście oparte na wielu repozytoriach było rozsądnym rozwiązaniem, ale decyzja o tym, ile repozytoriów mieć i gdzie dokonać cięć, nie zawsze była łatwa.
Na moim obecnym stanowisku migrowałem gigantyczne repozytorium CVS z pojedynczym repozytorium i ponad dziesięcioletnią historią do wielu repozytoriów git. Od tej pierwszej decyzji liczba repozytoriów wzrosła (dzięki działaniom innych zespołów), do tego stopnia, że podejrzewam, że mamy więcej niż byłoby optymalne. Niektórzy nowi zatrudnieni sugerowali połączenie repozytoriów, ale ja się temu sprzeciwiałem. Projekt Wayland ma podobne doświadczenie. W rozmowie, którą ostatnio widziałem, mieli w pewnym momencie ponad 200 repozytoriów git, za co przeprosił szef. Patrząc na ich stronę internetową , widzę, że mają teraz 5 lat, co wydaje się rozsądne. Ważne jest, aby pamiętać, że łączenie i dzielenie repozytoriów jest wykonalnym zadaniem i można eksperymentować (z uzasadnieniem).
Kiedy więc chcesz mieć wiele repozytoriów?
Punkty 2 i 3 są znaczące tylko wtedy, gdy punkt 1 jest ważny. Dzieląc nasze repozytoria, znacznie zmniejszyłem opóźnienia naszych współpracowników z zewnątrz, zmniejszyłem zużycie dysku i poprawiłem ruch w sieci.
4 i 5 są bardziej subtelne. Po podzieleniu repozytoriów powiedzmy klienta i serwera, to bardziej kosztowne jest koordynowanie zmian między kodem klienta i serwera. Może to być pozytywne, ponieważ zachęca do oddzielenia interfejsu między nimi.
Nawet pomimo wad projektów obejmujących wiele repozytoriów, w ten sposób wykonuje się wiele poważnych prac - na myśl przychodzą sposoby i ulepszenia. Nie wydaje mi się, aby doszło do konsensusu w sprawie najlepszych praktyk i konieczna jest pewna ocena. Narzędzia do pracy z wieloma repozytoriami (git-poddrzewo, git-submodule i inne) są wciąż rozwijane i eksperymentowane. Radzę eksperymentować i być pragmatycznym.
źródło
Gdy korzystamy z GitHub, faktycznie mamy wiele projektów w jednym repozytorium, ale upewniamy się, że te projekty / moduły są odpowiednio zmodularyzowane (używamy konwencji -api i -core + Maven + sprawdzanie statyczne i uruchomieniowe, a nawet pewnego dnia możemy uruchomić system OSGi) .
Na czym to oszczędza? Nie musimy wydawać wielu żądań ściągania, jeśli zmieniamy coś małego w wielu projektach. Problemy i Wiki są scentralizowane itp.
Nadal traktujemy każdy moduł / projekt jako właściwy niezależny projekt i budujemy i integrujemy je osobno w naszym serwerze CI itp.
źródło
submodules
czy wypuszczasz / tagujesz całe repozytorium?git log -1 -- <project_dir>
). To naprawdę świetne. Ta odpowiedź zasługuje na więcej pochwał.Dla mnie główną różnicą w korzystaniu z jednego lub więcej niż jednego repozytorium są odpowiedzi na następujące pytania:
Na przykład mam małą aplikację (tylko klient), która sprawdza „jakość” repozytorium Subversion. Istnieje podstawowa implementacja, którą można uruchomić z wiersza poleceń i działa dobrze z Javą 6. Ale zacząłem implementować interfejs użytkownika, który używa JavaFX jako części Java 8. Więc podzieliłem 2 i utworzyłem drugie repozytorium (z drugim procesem kompilacji), z innym harmonogramem, ...
Lubię powyższe odpowiedzi (głosowałem za nimi), ale myślę, że to nie jest cała prawdziwa historia. Chciałem więc dodać również argumenty za podzieleniem repozytoriów. Tak więc prawdziwa odpowiedź (kiedy podzielić) może być gdzieś pośrodku ...
źródło
Może być tak, że git-poddrzewo (patrz blog Atlassian , średni blog lub link do jądra ) byłoby dobrym rozwiązaniem. Tak więc każdy projekt najwyższego poziomu używałby zestawu poddrzewa w możliwie różnych wersjach.
źródło
Z twojego przykładu, repozytoria powinny być skonfigurowane pod względem ich współzależności. Obowiązuje tutaj całe rozumowanie dotyczące projektowania MicroServices i Domain Driven Design: w niektórych przypadkach zduplikowany kod jest akceptowalny, praca z interfejsami, nie naruszaj kompatybilności, chyba że naprawdę musisz itp.
Teraz moim zdaniem interfejs powinien być niezależny od backendu. Repozytorium projektu interfejsu użytkownika zwykle powinno zawierać kod interfejsu użytkownika i kontroler klienta. Kontroler klienta połączy się z kontrolerami usług w sposób abstrakcyjny. Będą korzystać z abstrakcji klienta usługi / interfejsu API, która jest wersjonowana oddzielnie od usługi, dzięki czemu usługa może być aktualizowana bez przerywania klienta (ów) (może być kilku różnych klientów).
Tak więc sama usługa powinna być własnym repozytorium. Moim zdaniem usługa ta stanowi jedynie oparcie dla logiki biznesowej opartej na jednym punkcie prawdy. Logika biznesowa powinna więc zazwyczaj być oddzielna od technologii usługowej, która ją hostuje. Z drugiej strony implementacja repozytorium jest zazwyczaj tak ściśle związana z logiką biznesową, że można ją zintegrować z tym samym repozytorium. Ale nawet tam przebieg może się różnić.
Oczywiście proste projekty, które raczej nie zmienią się znacznie pod względem technologicznym lub obsługują wiele stosów, w których cały interfejs użytkownika może być hostowany z tego samego źródła co zaplecza, a usługi zaplecza są zwykle używane tylko przez tego samego klienta, mogą korzystać z większej liczby ściśle zintegrowane repozytoria.
W takim przypadku prawdopodobnie dobrze byłoby mieć pełny pion w jednym repozytorium i skupić się na upewnieniu się, że domeny funkcjonalne są odpowiednio autonomiczne w swoim własnym repozytorium. Dzięki temu nadal masz większość zalet mniejszych repozytoriów, a poza tym niewielki narzut.
źródło