Powiedzmy, że mam konfigurację, która wygląda mniej więcej tak
phd/code/
phd/figures/
phd/thesis/
Ze względów historycznych wszystkie one mają swoje własne repozytoria git. Ale chciałbym połączyć je w jeden, aby trochę uprościć. Na przykład teraz mogę wprowadzić dwa zestawy zmian i muszę coś zrobić
cd phd/code
git commit
cd ../figures
git commit
Byłoby (teraz) miło po prostu występować
cd phd
git commit
Wydaje się, że można to zrobić na kilka sposobów za pomocą submodułów lub pobierania z moich repozytoriów, ale jest to trochę bardziej skomplikowane niż szukam. Przynajmniej byłbym szczęśliwy
cd phd
git init
git add [[everything that's already in my other repositories]]
ale to nie wygląda na jedno-liniowe. Czy coś w git
tym może mi pomóc?
Odpowiedzi:
Oto rozwiązanie, które tutaj podałem :
Najpierw wykonaj pełną kopię zapasową katalogu phd: nie chcę ponosić odpowiedzialności za utratę lat ciężkiej pracy! ;-)
Przenieś zawartość
phd/code
dophd/code/code
i napraw historię, aby wyglądała, jakby zawsze tam była (używa komendy git filter-branch ):Sam za treść
phd/figures
iphd/thesis
(wystarczy wymienićcode
zfigures
athesis
).Teraz struktura katalogów powinna wyglądać następująco:
Następnie utwórz repozytorium git w katalogu głównym, przeciągnij do niego wszystko i usuń stare repozytoria:
Wreszcie powinieneś mieć teraz to, czego chciałeś:
Jedną fajną stroną tej procedury jest to, że pozostawi ona nie wersjonowane pliki i katalogi na miejscu.
Mam nadzieję że to pomoże.
Wystarczy jedno słowo ostrzeżenia: jeśli
code
katalog ma jużcode
podkatalog lub plik, rzeczy może pójść bardzo źle (taki sam dlafigures
ithesis
oczywiście). W takim przypadku po prostu zmień nazwę tego katalogu lub pliku przed wykonaniem całej procedury:A po zakończeniu procedury dodaj ten ostatni krok:
Oczywiście, jeśli
code
podkatalog lub plik nie jest wersjonowany, użyjmv
zamiast niegogit mv
i zapomnij o nimgit commit
.źródło
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
a potem zadziałało świetnie!źródło
Być może po prostu (podobnie jak w poprzedniej odpowiedzi, ale przy użyciu prostszych poleceń) dokonanie w każdym z oddzielnych starych repozytoriów zatwierdzenia, które przenosi zawartość do odpowiednio nazwanego podkatalogu, np .:
a następnie łącząc trzy oddzielne repo w jeden nowy, wykonując coś takiego:
Następnie zapiszesz swoje historie, ale przejdzie do jednego repozytorium.
źródło
Możesz wypróbować strategię scalania poddrzewa . Pozwoli ci to połączyć repozytorium B w repozytorium A. Przewaga
git-filter-branch
polega na tym, że nie wymaga przepisania historii repozytorium A (zerwanie sum SHA1).źródło
Rozwiązanie git-filter-branch działa dobrze, ale pamiętaj, że jeśli twoje repozytorium git pochodzi z importu SVN, może się nie powieść z komunikatem:
W takim przypadku należy wykluczyć wstępną wersję z gałęzi filter - tj. Zmienić
HEAD
na końcu na[SHA of 2nd revision]..HEAD
- patrz:http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html
źródło
Rozwiązanie @MiniQuark bardzo mi pomogło, ale niestety nie uwzględnia tagów znajdujących się w repozytoriach źródłowych (przynajmniej w moim przypadku). Poniżej moja poprawa do odpowiedzi @MiniQuark.
Najpierw utwórz katalog, który będzie zawierał złożone repozytorium i połączone repozytorium, utwórz katalog dla każdego scalonego repozytorium.
Wykonaj wyciąg z każdego repozytorium i pobierz wszystkie tagi. (Prezentowanie instrukcji tylko dla
code
podkatalogu)(Jest to poprawka do punktu 2 w odpowiedzi MiniQuark) Przenieś zawartość
new_phd/code
donew_phd/code/code
i dodajcode_
prefiks przed każdym tagiemPo wykonaniu tej czynności będzie dwa razy więcej tagów niż przed wykonaniem odgałęzienia filtru. Stare tagi pozostają w repozytorium i
code_
dodawane są nowe tagi z prefiksem.Usuń stare tagi ręcznie:
Powtórz pkt 2,3,4 dla innych podkatalogów
Teraz mamy strukturę katalogów jak w @MiniQuark w punkcie 3.
Postępuj jak w punkcie 4 anwsera MiniQuark, ale po pociągnięciu i przed usunięciem
.git
reż, pobierz tagi:Kontyntynuj..
To tylko kolejne rozwiązanie. Mam nadzieję, że to komuś pomaga, pomogło mi :)
źródło
git-stitch-repo z odpowiedzi Arystotelesa Pagaltzisa działa tylko w przypadku repozytoriów o prostej, liniowej historii.
Odpowiedź MiniQuark działa dla wszystkich repozytoriów, ale nie obsługuje tagów i gałęzi.
Stworzyłem program, który działa w taki sam sposób, jak opisuje MiniQuark, ale używa jednego zatwierdzenia scalania (z N rodzicami), a także odtwarza wszystkie znaczniki i gałęzie, aby wskazać te zatwierdzenia scalania.
Zobacz repozytorium git-merge-repos, aby dowiedzieć się, jak z niego korzystać.
źródło
Stworzyłem narzędzie, które sprawia, że to zadanie. Zastosowana metoda jest podobna (wewnętrznie tworzą niektóre rzeczy, takie jak --filter-branch), ale jest bardziej przyjazna. Jest GPL 2.0
http://github.com/geppo12/GitCombineRepo
źródło
W rzeczywistości git-stitch-repo obsługuje teraz gałęzie i tagi, w tym tagi z adnotacjami (znalazłem błąd, który zgłosiłem i został naprawiony). Za przydatne uważałem tagi. Ponieważ tagi są dołączane do zatwierdzeń, a niektóre rozwiązania (takie jak podejście Erica Lee) nie radzą sobie z tagami. Próbujesz utworzyć gałąź z zaimportowanego znacznika, a ona cofnie wszelkie połączenia / przeniesienia git i odeśle cię tak, jakby skonsolidowane repozytorium było prawie identyczne z repozytorium, z którego pochodzi znacznik. Istnieją również problemy, jeśli używasz tego samego tagu w wielu repozytoriach, które „scaliłeś / skonsolidowałeś”. Na przykład, jeśli masz repozytorium A reklama B, oba mają tag rel_1.0. Scalasz repozytorium A i repozytorium B w repozytorium AB. Ponieważ znaczniki rel_1.0 dotyczą dwóch różnych zatwierdzeń (jeden dla A i jeden dla B), który tag będzie widoczny w AB? Znacznik z zaimportowanego repozytorium A lub z importowanego repozytorium B, ale nie oba.
git-stitch-repo pomaga rozwiązać ten problem, tworząc tagi rel_1.0-A i rel_1.0-B. Możesz nie być w stanie wyewidencjonować tag rel_1.0 i oczekiwać obu, ale przynajmniej możesz zobaczyć oba i teoretycznie możesz scalić je we wspólny oddział lokalny, a następnie utworzyć tag rel_1.0 w połączonym oddziale (zakładając, że po prostu Scal i nie zmieniaj kodu źródłowego). Lepiej jest pracować z oddziałami, ponieważ można łączyć jak oddziały z każdego repozytorium w oddziały lokalne. (dev-a i dev-b można połączyć w lokalną gałąź programistyczną, którą następnie można zepchnąć do źródła).
źródło
Sekwencja, którą zasugerowałeś
zadziała, ale stracisz swoją historię zmian.
źródło
Aby scalić drugi projekt w ramach głównego projektu:
A) W drugim projekcie
B) W głównym projekcie:
W tej gałęzi dokonaj wszystkich ciężkich transformacji, które musisz zrobić, i dokonaj ich.
C) Następnie z powrotem do mistrza i klasyczne połączenie dwóch gałęzi:
źródło
Wrzucę tu również moje rozwiązanie. Zasadniczo jest to dość proste opakowanie skryptu bash
git filter-branch
. Podobnie jak inne rozwiązania, migruje tylko główne gałęzie i nie migruje tagów. Ale pełne historie zatwierdzeń głównych są migrowane i jest to krótki skrypt bash, więc użytkownicy powinni względnie łatwo przejrzeć lub poprawić.https://github.com/Oakleon/git-join-repos
źródło
Ten skrypt bash działa wokół problemu znaków tabulacji sed (na przykład w systemie MacOS) i problemu brakujących plików.
Jest to kombinacja postów miniquark , marius-butuc i ryan . Pozdrawiam ich!
źródło