Kiedy używać poddrzewa git?

81

Jaki problem git subtreerozwiązuje? Kiedy i dlaczego powinienem używać tej funkcji?

Czytałem, że jest używany do rozdzielania repozytoriów . Ale dlaczego nie miałbym po prostu utworzyć dwóch niezależnych repozytoriów zamiast skleić dwa niepowiązane w jedno?

W tym samouczku GitHub wyjaśniono, jak wykonywać scalenia poddrzewa Git .

W pewnym sensie wiem, jak go używać, ale nie wiem, kiedy (przypadki użycia) i dlaczego i do czego się odnosi git submodule. Używałbym modułów podrzędnych, gdy mam zależność od innego projektu lub biblioteki.

Lernkurve
źródło
1
"separacja repozytoriów"! = "niepowiązane repozytoria" myślą o zależnościach w swoim repozytorium i nie chcesz używać modułów podrzędnych (z jakiegoś powodu może nie podoba ci się to, że nie są przezroczyste i że ścieżki w zatwierdzeniach w podmoduł nie pasuje do Twojej ścieżki w głównym repozytorium git).
cyphar
1
@cyphar: Czy mówisz, że oba submodulei subtreemniej więcej osiągają ten sam cel, którym jest włączanie powiązanych projektów i że jedyną różnicą jest to, że submodulemoże być nieco mniej przejrzysty, a aktualizacja modułów podrzędnych jest operacją dwuetapową, a wadą subtreejest to, że komunikaty dotyczące zmian zostaną pomieszane między dwoma projektami?
Lernkurve
1
Cóż, w niektórych przypadkach nie jest to wada. Na przykład, jeśli chcesz podzielić repozytorium, które ma subtrees, a błąd został wprowadzony w zależności, dokładne zatwierdzenie znajdziesz w tym,subtree który wprowadził błąd. Dzięki modułom podrzędnym przekonasz się tylko, że zatwierdzenie, które submodulespowodowało błąd, i jesteś w pewnym sensie SOL, jeśli chcesz szybko znaleźć, które zatwierdzenie submodulepowoduje błąd w twoim głównym projekcie.
cyphar
1
Oto artykuł porównujący poddrzewo git i podmoduł git z praktycznymi przykładami nering.dev/2016/git-submodules-vs-subtrees
8ctopus

Odpowiedzi:

58

Powinieneś uważać, aby wyraźnie zaznaczyć, o czym mówisz, kiedy używasz terminu `` poddrzewo '' w kontekście, gitponieważ w rzeczywistości istnieją tutaj dwa oddzielne, ale powiązane tematy:

Strategia łączenia git-subtree i git subtree .

TL; DR

Obie koncepcje powiązane z poddrzewem pozwalają efektywnie zarządzać wieloma repozytoriami w jednym. W przeciwieństwie do git-submodule, w którym tylko metadane są przechowywane w repozytorium głównym, w postaci .gitmodules , i musisz osobno zarządzać zewnętrznymi repozytoriami.

Więcej szczegółów

Strategia scalania poddrzewa git jest w zasadzie bardziej ręczną metodą wykorzystującą polecenia, do których się odwołujesz.

git-subtree jest opakowującym skryptem powłoki, który ułatwia bardziej naturalną składnię. W rzeczywistości jest to nadal część contribi nie jest w pełni zintegrowane z git ze zwykłymi stronami podręcznika. Dokumentacja jest przechowywana wzdłuż boku zamiast skryptu.

Oto informacje o użytkowaniu:

NAME
----
git-subtree - Merge subtrees together and split repository into subtrees


SYNOPSIS
--------
[verse]
'git subtree' add   -P <prefix> <commit>
'git subtree' add   -P <prefix> <repository> <ref>
'git subtree' pull  -P <prefix> <repository> <ref>
'git subtree' push  -P <prefix> <repository> <ref>
'git subtree' merge -P <prefix> <commit>
'git subtree' split -P <prefix> [OPTIONS] [<commit>]

Natknąłem się na całkiem niezłą liczbę zasobów na temat poddrzew, ponieważ planowałem napisać własny wpis na blogu. Zaktualizuję ten post, jeśli to zrobię, ale na razie oto kilka istotnych informacji na temat tego pytania:

Wiele z tego, czego szukasz, można znaleźć na tym blogu Atlassian autorstwa Nicoli Paolucciego w odpowiedniej sekcji poniżej:

Po co używać poddrzewa zamiast modułu podrzędnego?

Istnieje kilka powodów, dla których możesz znaleźć subtreelepszy w użyciu:

  • Zarządzanie prostym przepływem pracy jest łatwe.
  • gitObsługiwane są starsze wersje (nawet wcześniej v1.5.2).
  • Kod podprojektu jest dostępny zaraz po clonezakończeniu super projektu.
  • subtreenie wymaga od użytkowników Twojego repozytorium uczenia się niczego nowego, mogą zignorować fakt, że używasz go subtreedo zarządzania zależnościami.
  • subtreenie dodaje nowych plików metadanych, jak submodulesrobi (tj .gitmodule.).
  • Zawartość modułu można modyfikować bez konieczności posiadania oddzielnej kopii repozytorium zależności w innym miejscu.

Moim zdaniem wady są dopuszczalne:

  • Musisz poznać nową strategię łączenia (tj subtree.).
  • Przekazywanie kodu z powrotem upstream dla podprojektów jest nieco bardziej skomplikowane.
  • Odpowiedzialność za niemieszanie kodu super i podprojektu w zatwierdzeniach spoczywa na Tobie.

Z dużą częścią zgodziłbym się również. Poleciłbym zapoznać się z tym artykułem, ponieważ omawia kilka typowych zastosowań.

Być może zauważyłeś, że napisał tutaj również kontynuację, w której wspomina o ważnym szczególe, który został pominięty w tym podejściu ...

git-subtree obecnie nie zawiera pilota!

Ta krótkowzroczność jest prawdopodobnie spowodowana faktem, że ludzie często dodają pilota ręcznie podczas pracy z poddrzewami, ale nie jest to również przechowywane w git. Autor szczegółowo opisuje łatkę, którą napisał, aby dodać te metadane do zatwierdzenia thatgit-subtree już generuje. Dopóki to nie trafi do oficjalnej głównej linii gita, możesz zrobić coś podobnego, modyfikując komunikat o zatwierdzeniu lub przechowując go w innym zatwierdzeniu.

Uważam również, że ten post na blogu jest bardzo pouczający. Autor dodaje trzecią metodę poddrzewa, którą wywołuje git-streedo miksu. Artykuł jest wart przeczytania, ponieważ wykonuje całkiem niezłą robotę porównując te trzy podejścia. Przedstawia swoją osobistą opinię o tym, co lubi, a czego nie, i wyjaśnia, dlaczego stworzył trzecie podejście.

Dodatki

Myśli końcowe

W tym temacie przedstawiono zarówno możliwości git segmentacji, jak i segmentację, która może wystąpić, gdy funkcja po prostu nie trafia w ślad.

Osobiście wzbudziłem wstręt, git-submoduleponieważ uważam to za bardziej zagmatwane, aby współpracownicy mogli to zrozumieć. Wolę również zarządzać WSZYSTKIMI moimi zależnościami w ramach moich projektów, aby zapewnić łatwe do odtworzenia środowisko bez prób zarządzania wieloma repozytoriami. git-submodulejest jednak obecnie znacznie bardziej znany, więc dobrze jest być tego świadomym i w zależności od odbiorców, którzy mogą wpłynąć na twoją decyzję.

Matthew Sanders
źródło
12

Po pierwsze: uważam, że twoje pytanie ma tendencję do uzyskiwania mocno upartych odpowiedzi i może być tutaj uznane za nie na temat. Jednak nie podoba mi się ta polityka SO i chciałbym nieco przesunąć granicę bycia na temat na zewnątrz, więc zamiast tego lubię odpowiadać i mam nadzieję, że inni też.

W samouczku GitHub, na który wskazałeś, znajduje się link do Jak korzystać ze strategii scalania poddrzewa, który daje punkt widzenia na zalety / wady:

Porównanie scalania poddrzewa z modułami podrzędnymi

Zaletą używania funkcji scalania poddrzewa jest to, że wymaga mniejszego obciążenia administracyjnego od użytkowników repozytorium. To działa ze starszymi (przed Git v1.5.2) klientów i masz prawo kod po klonie.

Jeśli jednak używasz modułów podrzędnych , możesz zdecydować, aby nie przenosić obiektów podmodułów . Może to być problem ze scalaniem poddrzewa.

Ponadto, jeśli wprowadzisz zmiany w innym projekcie, łatwiej będzie wprowadzić zmiany, jeśli użyjesz tylko modułów podrzędnych.

Oto mój punkt widzenia oparty na powyższym:

Często pracuję z ludźmi (= committerami), którzy nie są zwykłymi użytkownikami git, niektórzy wciąż (i na zawsze będą) borykać się z kontrolą wersji. Poinformowanie ich o tym, jak używać strategii scalania submodułów jest w zasadzie niemożliwe. Obejmuje koncepcje dodatkowych pilotów, łączenia, rozgałęzień, a następnie mieszania wszystkiego w jeden przepływ pracy. Ciągnięcie z góry i pchanie w górę to proces dwuetapowy. Ponieważ gałęzie są dla nich trudne do zrozumienia, to wszystko jest beznadziejne.

W przypadku modułów podrzędnych jest to dla nich nadal zbyt skomplikowane ( westchnienie ), ale łatwiej to zrozumieć: to tylko repozytorium w ramach repozytorium (znają hierarchię) i możesz normalnie pchać i ciągnąć.

Udostępnianie prostych skryptów opakowujących jest łatwiejsze imho dla przepływu pracy modułu podrzędnego.

W przypadku dużych super-repozytoriów z wieloma repozytoriami podrzędnymi istotną zaletą modułów podrzędnych jest rezygnacja z klonowania danych niektórych repozytoriów. Możemy to ograniczyć na podstawie wymagań pracy i wykorzystania miejsca na dysku.

Kontrola dostępu może być inna. Nie miałem jeszcze tego problemu, ale jeśli różne repozytoria wymagają różnych kontroli dostępu, skutecznie blokując niektórym użytkownikom dostęp do niektórych sub-repozytoriów, zastanawiam się, czy łatwiej to osiągnąć dzięki podejściu submodułowemu.

Osobiście jestem niezdecydowany, czego mam użyć. Więc podzielam Twoje zamieszanie: o]

cfi
źródło
3
Ta odpowiedź jest najbardziej uparty, jaką widziałem, pomimo sprzeczności, ponieważ jest to jedyna odpowiedź i samospełniająca się przepowiednia. Westchnienie zirytowania, zagłada nastawienie innych do zdolności uczenia się, to bardzo arogancka odpowiedź. Twoja opinia na temat polityki prawdopodobnie należy do Meta, gdzie może być pomocna. Sama odpowiedź, poza samolubnym puchem, jest jednak całkiem dobra.
vgoff,
1
@vgoff: Twoja krytyka jest poprawna. Przepraszam za pozorną arogancję - to tylko> 15 lat doświadczenia w pracy z ludźmi, którzy przez ten czas byli szkoleni przez różne osoby w różnych systemach kontroli wersji i nadal kopiują pliki tekstowe do wielu .backup.<timestamp>. Myślę, że na początku wyjaśniłem, że będzie to uparte. Miejmy nadzieję, że inni są w stanie przedstawić bardziej faktyczny wgląd i jestem zaskoczony, że nikt jeszcze tego nie zrobił.
cfi
Nadal nie rozumiem. Czy mówisz, że submodulejest to przestarzały, stary sposób włączania używanych bibliotek i subtreeczy nowy, błyszczący sposób?
Lernkurve
Nie. Dokumenty przynajmniej nie wspominają, że którykolwiek z tych dwóch jest przestarzały. A dla mnie doktorzy mają ostatnie słowo (z wyjątkiem błędów). To tylko dwa różne przepływy pracy, aby osiągnąć podobną rzecz. Obie mają zalety i wady. Dla mnie fakt, że żaden z guru gitu jeszcze nie odpowiedział, jest potwierdzeniem, że dla eksperta różnice są znikome. Najprawdopodobniej użyj strategii scalania poddrzewa, ponieważ jest to strategia, która została zaimplementowana wcześniej i ludzie są zaznajomieni read-tree(i tak czy inaczej rozgałęzianie / scalanie / piloty). submoduleszostał dodany
cfi
5

Prawdziwy przypadek użycia, w którym poddrzewo git było zbawieniem:

Głównym produktem naszej firmy jest wysoki modułowość i rozwijany w kilku projektach w oddzielnych repozytoriach. Wszystkie moduły mają oddzielną mapę drogową. Cały produkt składa się ze wszystkich modułów wersji betonowych.

Równolegle dla każdego klienta dostosowywana jest konkretna wersja całego produktu - oddzielne oddziały dla każdego modułu. Czasami trzeba dostosować kilka projektów jednocześnie ( cross-module customization).

Aby mieć oddzielny cykl życia produktu (konserwacja, gałęzie funkcji) dla niestandardowego produktu, wprowadziliśmy poddrzewo git. Mamy jedno repozytorium git-subtree dla wszystkich niestandardowych modułów. Nasze dostosowywanie to codzienne „wypychanie poddrzewa git” z powrotem do wszystkich oryginalnych repozytoriów do gałęzi dostosowywania.

W ten sposób unikamy zarządzania wieloma repozytoriami i wieloma bankami. git-subtree kilkakrotnie zwiększyło naszą produktywność!

AKTUALIZACJA

Więcej szczegółów na temat rozwiązania, które zostało opublikowane w komentarzach:

Stworzyliśmy zupełnie nowe repozytorium. Następnie dodaliśmy każdy projekt, który miał gałąź klienta do tego nowego repozytorium jako poddrzewo. Mieliśmy zadanie Jenkinsa polegające na regularnym przekazywaniu zmian głównych w oryginalnych repozytoriach do gałęzi klienta. Pracowaliśmy tylko z „repozytorium klienta”, używając typowego przepływu git z gałęziami funkcji i konserwacji.

Nasze repozytorium „klienta” posiadało również skrypty budujące, które również dostosowaliśmy dla tego konkretnego klienta.

Istnieje jednak pułapka przedstawionego rozwiązania.

W miarę jak szliśmy coraz dalej i dalej od głównego rozwoju produktu, możliwa aktualizacja dla tego konkretnego klienta była coraz trudniejsza. W naszym przypadku było to w porządku, ponieważ stan projektu przed poddrzewem był już daleko od głównej ścieżki, więc poddrzewo wprowadza przynajmniej porządek i możliwość wprowadzenia domyślnego przepływu git.

Marek Jagielski
źródło
Marek, mam do czynienia z czymś, co brzmi jak ta sama sytuacja, jestem stosunkowo nowy w gonitwie i grzęznę w możliwościach. Chciałbym dowiedzieć się więcej o Twojej konfiguracji.
goug
Stworzyłem zupełnie nowe repozytorium. Następnie dodałem każdy projekt, który miał gałąź klienta do tego repozytorium jako poddrzewo. Mieliśmy zadanie Jenkinsa polegające na przenoszeniu zmian z oryginalnych repozytoriów do gałęzi klienta. W naszym repozytorium klientów pracowaliśmy normalnie na głównym z gałęziami funkcji, konserwacji.
Marek Jagielski
Pułapka polegała na tym, że szliśmy coraz dalej i dalej od głównego rozwoju produktu. Tak więc ewentualna aktualizacja dla tego konkretnego klienta była coraz trudniejsza. W naszym przypadku było to w porządku, ponieważ stan projektu przed poddrzewem był już daleko od głównej ścieżki, więc poddrzewo wprowadza przynajmniej porządek i możliwość wprowadzenia domyślnego przepływu git.
Marek Jagielski
Jeszcze jedna rzecz, że nasze repozytorium „klienta” miało również budowanie skryptów, które również dostosowywaliśmy dla tego konkretnego klienta.
Marek Jagielski
1
Chciałbym zalecić włączenie dodatkowych informacji z komentarzy do odpowiedzi; zdecydowanie uczynili to lepszą odpowiedzią.
James Skemp
5

Zasadniczo poddrzewo Git jest alternatywą dla podejścia Git-submodule: jest wiele wad, a raczej powiedziałbym, że podczas korzystania z git-submodules trzeba być bardzo ostrożnym. np. jeśli masz „jedno” repozytorium, a wewnątrz „jednego”, dodałeś kolejne repozytorium o nazwie „dwa” za pomocą modułów podrzędnych. Rzeczy, o które musisz zadbać:

  • Kiedy zmieniasz coś w „dwóch”, musisz zatwierdzić i wcisnąć wewnątrz „dwa”, jeśli jesteś w katalogu najwyższego poziomu (tj. W „jednym”), zmiany nie zostaną podświetlone.

  • Gdy nieznany użytkownik próbuje sklonować Twoje „jedno” repozytorium, po sklonowaniu „jednego” użytkownik musi zaktualizować moduły podrzędne, aby uzyskać „dwa” repozytorium

Oto niektóre z punktów i dla lepszego zrozumienia polecam obejrzenie tego filmu: https://www.youtube.com/watch?v=UQvXst5I41I

  • Aby przezwyciężyć takie problemy, wymyślono podejście poddrzewo. Aby uzyskać podstawowe informacje o poddrzewie git, zapoznaj się z tym: https://www.youtube.com/watch?v=t3Qhon7burE

  • Uważam, że podejście do poddrzewa jest bardziej niezawodne i praktyczne w porównaniu do modułów podrzędnych :) (jestem bardzo początkującym w mówieniu tych rzeczy)

Twoje zdrowie!

SH '
źródło
2

Aby dodać do powyższych odpowiedzi, dodatkową wadą korzystania z poddrzewa jest rozmiar repozytorium w porównaniu z modułami podrzędnymi.

Nie mam żadnych rzeczywistych metryk, ale biorąc pod uwagę, że za każdym razem, gdy wysyłany jest moduł, wszędzie tam, gdzie ten moduł jest używany, otrzymuje kopię tej samej zmiany w module nadrzędnym (kiedy jest później aktualizowana w tych repozytoriach).

Więc jeśli baza kodu jest mocno zmodularyzowana, suma się to dość szybko.

Jednak biorąc pod uwagę, że ceny magazynów zawsze spadają, może to nie być istotny czynnik.

Paul Phillips
źródło
Przechowywanie nie jest problemem. Entropia jest problemem ! Na przykład masz 1000 narzędzi o wielkości od 10 do 100 KB, z których każde ma wspólny kod, powiedzmy 35 GB (ponieważ zawiera ogromną liczbę modułów z różnych źródeł). Dzięki modułom podrzędnym przenosisz około 36 GB dla wszystkich, ale prawdopodobnie ponad 1 TB z poddrzewem git! Należy również zauważyć, że podmoduł ma wyraźnie niesprawiedliwą przewagę, jeśli chodzi o git gcdeduplikację ZFS (pakiety obiektów). Stąd AFAICS mniejsze bazy kodów (wielkość repozytorium, a nie liczba repozytoriów) powinny iść z submodułami, większe z monorepo. Nie znalazłem jeszcze żadnego zastosowania dla poddrzewa.
Tino
@tino Git usunie poddrzewa ze wspólnym kodem. Właśnie przeprowadziłem kilka eksperymentów, aby to potwierdzić. W przypadku wyewidencjonowanego kodu musiałbyś uruchomić coś takiego jak ZFS. Ale podmoduły nie są inne.
Matthias