Dość często jest tak, że piszesz jakiś projekt i po chwili staje się jasne, że jakiś komponent projektu jest faktycznie przydatny jako samodzielny komponent (być może biblioteka). Jeśli miałeś ten pomysł od samego początku, istnieje spora szansa, że większość tego kodu znajduje się w swoim własnym folderze.
Czy istnieje sposób na przekonwertowanie jednego z podkatalogów w projekcie Git na moduł podrzędny?
Idealnie byłoby tak, że cały kod w tym katalogu zostanie usunięty z projektu nadrzędnego, a projekt modułu podrzędnego zostanie dodany w jego miejsce, z całą odpowiednią historią, i tak, że wszystkie zatwierdzenia projektu nadrzędnego wskazują na poprawny moduł podrzędny .
git
git-submodules
naught101
źródło
źródło
Odpowiedzi:
Aby wyodrębnić podkatalog do własnego repozytorium, użyj
filter-branch
na klonie oryginalnego repozytorium:To nic innego jak usunięcie oryginalnego katalogu i dodanie modułu podrzędnego do projektu nadrzędnego.
źródło
git remote rm <name>
po gałęzi filtru, a następnie być może dodać nowego pilota. Ponadto, jeśli są zignorowane pliki,git clean -xd -f
może być przydatny-- --all
można zastąpić nazwą gałęzi, jeśli podmoduł ma być wyodrębniony tylko z tej gałęzi.git clone <your_project> <your_submodule>
pobiera pliki tylko dla your_submodule?git clone source destination
po prostu informuje Git o lokalizacji, w której należy umieścić sklonowane pliki. Właściwa magia filtrowania plików twojego modułu podrzędnego odbywa się następnie wfilter-branch
kroku.filter-branch
jest obecnie przestarzałe . Możesz użyćgit clone --filter
, ale serwer Git musi być skonfigurowany tak, aby zezwalał na filtrowanie, w przeciwnym razie otrzymaszwarning: filtering not recognized by server, ignoring
.Najpierw zmień katalog na folder, który będzie modułem podrzędnym. Następnie:
źródło
Wiem, że to stary wątek, ale odpowiedzi tutaj ograniczają wszelkie powiązane zatwierdzenia w innych gałęziach.
Prosty sposób na sklonowanie i zachowanie tych wszystkich dodatkowych gałęzi i zatwierdzeń:
1 - Upewnij się, że masz ten alias git
2 - Sklonuj pilota, ściągnij wszystkie gałęzie, zmień pilota, przefiltruj katalog, wciśnij
źródło
Można to zrobić, ale nie jest to proste. Jeśli szukać
git filter-branch
,subdirectory
isubmodule
istnieje kilka przyzwoitych write-up na procesie. Zasadniczo pociąga to za sobą utworzenie dwóch klonów twojego projektu, użyciegit filter-branch
do usunięcia wszystkiego oprócz jednego podkatalogu w jednym i usunięcie tylko tego podkatalogu w drugim. Następnie możesz ustawić drugie repozytorium jako podmoduł pierwszego.źródło
Status quo
Załóżmy, że mamy repozytorium o nazwie
repo-old
, która zawiera sub katalogusub
, który chcielibyśmy przekształcić sub modułu z własnym reporepo-sub
.Zamiarem jest ponadto
repo-old
przekształcenie oryginalnego repozytorium w zmodyfikowane repozytorium, wrepo-new
którym wszystkie zatwierdzenia dotykające wcześniej istniejącego podkatalogusub
będą teraz wskazywać na odpowiednie zatwierdzenia naszego wyodrębnionego repozytorium podmodułówrepo-sub
.Zmieńmy się
Można to osiągnąć za pomocą
git filter-branch
dwuetapowego procesu:repo-old
dorepo-sub
(już wspomniana w zaakceptowanej odpowiedzi )repo-old
narepo-new
(z odpowiednim mapowaniem zatwierdzeń)Uwaga : wiem, że to pytanie jest stare i zostało już wspomniane, że
git filter-branch
jest trochę przestarzałe i może być niebezpieczne. Ale z drugiej strony może pomóc innym dzięki osobistym repozytoriom, które można łatwo zweryfikować po konwersji. Więc uważaj ! I daj mi znać, jeśli istnieje inne narzędzie, które robi to samo, ale nie jest przestarzałe i jest bezpieczne w użyciu!Poniżej wyjaśnię, jak zrealizowałem oba kroki na Linuksie z wersją git 2.26.2. Starsze wersje mogą działać w pewnym stopniu, ale należy to przetestować.
Dla uproszczenia ograniczę się do przypadku, gdy w oryginalnym repozytorium jest tylko
master
gałąź iorigin
pilotrepo-old
. Ostrzegam również, że korzystam z tymczasowych tagów git z prefiksem,temp_
które zostaną usunięte w trakcie procesu. Jeśli więc istnieją już tagi o podobnych nazwach, możesz chcieć dostosować przedrostek poniżej. I na koniec, proszę, pamiętaj, że nie testowałem tego szczegółowo i mogą wystąpić narożne przypadki, w których przepis się nie powiedzie. Dlatego przed kontynuowaniem wykonaj kopię zapasową wszystkiego !Następujące fragmenty basha można połączyć w jeden duży skrypt, który następnie powinien zostać wykonany w tym samym folderze, w którym znajduje się repozytorium
repo-org
. Nie zaleca się kopiowania i wklejania wszystkiego bezpośrednio do okna poleceń (mimo że pomyślnie przetestowałem to)!0. Przygotowanie
Zmienne
Skrypt filtru
1. Ekstrakcja podkatalogów
2. Zastąpienie podkatalogu
Uwaga: Jeśli nowo utworzone repozytorium
repo-new
zawiesza się podczas,git submodule update --init
spróbuj ponownie sklonować repozytorium rekurencyjnie raz zamiast tego:źródło
To robi konwersję na miejscu, możesz ją wycofać, jak każdą gałąź filtra (używam
git fetch . +refs/original/*:*
).Mam projekt z
utils
biblioteką, która zaczęła być użyteczna w innych projektach i chciałem podzielić jej historię na podmoduły. Nie pomyślałem, aby najpierw spojrzeć na SO, więc napisałem własną, buduje historię lokalnie, więc jest trochę szybsza, po czym, jeśli chcesz, możesz skonfigurować.gitmodules
plik polecenia pomocnika i tym podobne, i wrzucić historie podmodułów w dowolne miejsce chcesz.Tutaj znajduje się samo polecenie pozbawione elementów, dokument w komentarzach, w następnym, bez ściągania. Uruchom go jako własne polecenie z
subdir
set, tak jak wsubdir=utils git split-submodule
przypadku dzieleniautils
katalogu. Jest to hacking, ponieważ jest jednorazowy, ale przetestowałem go w podkatalogu Documentation w historii Git.źródło