Zacząłem projekt kilka miesięcy temu i zapisałem wszystko w głównym katalogu. W moim głównym katalogu "Project" jest kilka podkatalogów zawierających różne rzeczy: Project / paper zawiera dokument napisany w LaTeX Project / sourcecode / RailsApp zawiera moją aplikację railsową.
"Projekt" jest oznaczony GIT i było wiele zatwierdzeń zarówno w katalogu "paper", jak i "RailsApp". Teraz, ponieważ chciałbym użyć cruisecontrol.rb dla mojej „RailsApp”, zastanawiam się, czy istnieje sposób na utworzenie podmodułu z „RailsApp” bez utraty historii.
git
git-submodules
Cœur
źródło
źródło
Odpowiedzi:
W dzisiejszych czasach istnieje znacznie łatwiejszy sposób na zrobienie tego niż ręcznie za pomocą git filter-branch: git subtree
Instalacja
UWAGA
git-subtree
jest teraz częściągit
(jeśli zainstalujesz Contrib) od 1.7.11, więc możesz już mieć ją zainstalowaną. Możesz sprawdzić, wykonującgit subtree
.Aby zainstalować poddrzewo git ze źródła (dla starszych wersji git):
Lub jeśli chcesz strony podręcznika i wszystko
Stosowanie
Podziel większy na mniejsze kawałki:
Aby uzyskać szczegółową dokumentację (strona podręcznika), przeczytaj
git-subtree.txt
.źródło
git rm -rf ./foo
usuwafoo
zHEAD
ale nie filtrujemy-project
jest cała historia. Następniegit submodule add [email protected]:my-user/new-project.git foo
tworzy tylkofoo
podmoduł zaczynający się odHEAD
. Pod tym względem skryptyfilter-branch
są lepsze, ponieważ pozwalają osiągnąć „rób tak, jakby subdir był od samego początku podmodułem”Checkout git filter-branch .
Examples
Sekcja mężczyzny stronie pokazuje jak wyodrębnić podkatalogu do niego własnego projektu przy zachowaniu wszystkich jego historii i odrzucając historię innych plików / katalogów (tylko to, czego szukają).źródło
Jednym ze sposobów jest odwrotność - usuń wszystko oprócz pliku, który chcesz zachować.
Zasadniczo utwórz kopię repozytorium, a następnie użyj,
git filter-branch
aby usunąć wszystko oprócz plików / folderów, które chcesz zachować.Na przykład mam projekt, z którego chcę wyodrębnić plik
tvnamer.py
do nowego repozytorium:Wykorzystuje
git filter-branch --tree-filter
to przejście przez każde zatwierdzenie, uruchomienie polecenia i ponowne zatwierdzenie wynikowej zawartości katalogów. Jest to niezwykle destrukcyjne (więc powinieneś to robić tylko na kopii swojego repozytorium!) I może zająć trochę czasu (około 1 minuty na repozytorium z 300 zatwierdzeniami i około 20 plikami)Powyższe polecenie po prostu uruchamia następujący skrypt powłoki dla każdej wersji, którą musiałbyś oczywiście zmodyfikować (aby wykluczyć twój podkatalog zamiast
tvnamer.py
):Największym oczywistym problemem jest to, że pozostawia wszystkie komunikaty o zmianach, nawet jeśli nie są one związane z pozostałym plikiem. Skrypt git-remove-empty-commits rozwiązuje ten problem.
Musisz użyć
-f
argumentu force runfilter-branch
ponownie z czymkolwiek wrefs/original/
(co w zasadzie jest kopią zapasową)Oczywiście to nigdy nie będzie idealne, na przykład jeśli twoje komunikaty o zmianach wspominają o innych plikach, ale jest to tak blisko, jak pozwala na to prąd git (o ile wiem).
Ponownie, uruchamiaj to tylko na kopii swojego repozytorium! - ale podsumowując, aby usunąć wszystkie pliki oprócz „thisismyfilename.txt”:
źródło
git filter-branch
ma (obecnie?) wbudowaną opcję usuwania pustych zatwierdzeń, a mianowicie--prune-empty
. Lepszym przewodnikiemgit filter-branch
po odpowiedziach na to pytanie są: stackoverflow.com/questions/359424/ ...Zarówno CoolAJ86 i apenwarr odpowiedzi są bardzo podobne. Chodziłem tam iz powrotem między nimi, próbując zrozumieć fragmenty, których brakowało w jednym z nich. Poniżej znajduje się ich połączenie.
Najpierw przejdź do Git Bash do katalogu głównego repozytorium git, które chcesz podzielić. W moim przykładzie to jest
~/Documents/OriginalRepo (master)
Poniżej znajduje się kopia powyższego z nazwami, które można dostosować, zastąpionymi i używającymi zamiast tego protokołu https. Katalog główny to teraz
~/Documents/_Shawn/UnityProjects/SoProject (master)
źródło
Jeśli chcesz przenieść jakiś podzbiór plików do nowego repozytorium, ale zachować historię, w zasadzie skończysz z zupełnie nową historią. Sposób, w jaki to działałoby, jest zasadniczo następujący:
Zautomatyzowanie tego powinno być dość proste, jeśli nie masz nic przeciwko napisaniu małego, ale włochatego skryptu. Proste, tak, ale także bolesne. Ludzie robili w przeszłości przepisywanie historii w Git, możesz to wyszukać.
Alternatywnie: sklonuj repozytorium i usuń papier w klonie, usuń aplikację z oryginału. Zajmie to minutę, na pewno zadziała i możesz wrócić do ważniejszych rzeczy niż próba oczyszczenia historii gita. I nie martw się o miejsce na dysku zajmowane przez nadmiarowe kopie historii.
źródło