Odłącz (przenieś) podkatalog do oddzielnego repozytorium Git
Mam repozytorium Git , które zawiera wiele podkatalogów. Teraz odkryłem, że jeden z podkatalogów jest niezwiązany z drugim i powinien być odłączony do osobnego repozytorium.
Jak mogę to zrobić, zachowując historię plików w podkatalogu?
Myślę, że mógłbym zrobić klon i usunąć niechciane części każdego klona, ale przypuszczam, że to da mi pełne drzewo podczas sprawdzania starszej wersji itp. To może być akceptowalne, ale wolałbym móc udawać, że oba repozytoria nie mają wspólnej historii.
Żeby było jasne, mam następującą strukturę:
XYZ/
.git/
XY1/
ABC/
XY2/
Ale wolałabym zamiast tego:
XYZ/
.git/
XY1/
XY2/
ABC/
.git/
ABC/
22 answers
Update: ten proces jest tak powszechny, że zespół git znacznie uprościł go za pomocą nowego narzędzia, git subtree
. Zobacz tutaj: odłącz (przenieś) podkatalog do oddzielnego repozytorium Git
Chcesz sklonować swoje repozytorium, a następnie użyć git filter-branch
, aby oznaczyć wszystko poza podkatalogiem, który chcesz w nowym repo, aby został usunięty.
-
Aby sklonować lokalne repozytorium:
git clone /XYZ /ABC
(Uwaga: repozytorium zostanie sklonowane za pomocą twardych linków, ale nie jest to problemem, ponieważ połączone pliki nie będą same w sobie modyfikowane-będą tworzone nowe.)
-
Teraz zachowajmy interesujące gałęzie, które chcemy również przepisać, a następnie usuńmy origin, aby uniknąć popychania i upewnić się, że stare commity nie będą odwoływane przez origin: {]}
cd /ABC for i in branch1 br2 br3; do git branch -t $i origin/$i; done git remote rm origin
Lub dla wszystkich odległych gałęzi:
cd /ABC for i in $(git branch -r | sed "s/.*origin\///"); do git branch -t $i origin/$i; done git remote rm origin
Teraz możesz również usunąć tagi, które nie mają związku z podprojekt; możesz to zrobić również później, ale być może będziesz musiał ponownie przyciąć repo. Nie zrobiłem tego i dostałem
WARNING: Ref 'refs/tags/v0.1' is unchanged
dla wszystkich tagów (ponieważ wszystkie były niezwiązane z podprojektem); dodatkowo, po usunięciu takich tagów więcej miejsca zostanie odzyskane. Najwyraźniejgit filter-branch
powinno być w stanie przepisać inne tagi, ale nie mogłem tego zweryfikować. Jeśli chcesz usunąć wszystkie tagi, użyjgit tag -l | xargs git tag -d
.-
Następnie użyj filter-branch i reset, aby wykluczyć inne pliki, aby można je było przycinać. Let ' s also dodaj
--tag-name-filter cat --prune-empty
, aby usunąć puste commity i przepisać znaczniki (zauważ, że będzie to wymagało usunięcia ich podpisu):
Można też zmienić tylko gałąź nagłówka i zignorować znaczniki i inne gałęzie:git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
-
Następnie usuń Backup reflogs, aby przestrzeń mogła zostać odzyskana (chociaż teraz Operacja jest destrukcyjna)]}
git reset --hard git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d git reflog expire --expire=now --all git gc --aggressive --prune=now
A teraz masz lokalne repozytorium Git podkatalogu ABC z zachowaną historią.
Uwaga: dla większości zastosowań, {[7] } rzeczywiście powinien mieć dodany parametr -- --all
. Tak, to naprawdę --spacja-- all
. To muszą być ostatnie parametry polecenia. Jak odkrył Matli, to utrzymuje gałęzie projektu i tagi zawarte w nowym repo.
Edit: różne sugestie z poniższych komentarzy zostały włączone, aby upewnić się, na przykład, że repozytorium jest rzeczywiście skurczone (co nie było zawsze tak było wcześniej).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-20 22:57:50
The Easy Way™
Okazuje się, że jest to tak powszechna i użyteczna praktyka, że władcy Gita sprawili, że było to naprawdę łatwe, ale musisz mieć nowszą wersję Gita (>= 1.7.11 maj 2012). Zobacz dodatek aby dowiedzieć się jak zainstalować najnowszy git. Poniżej znajduje się przykład z prawdziwego świata w artykule .
-
Przygotuj stare repo
pushd <big-repo> git subtree split -P <name-of-folder> -b <name-of-new-branch> popd
Uwaga:
<name-of-folder>
nie może zawierać znaków początkowych ani końcowych. Na przykład, folder o nazwiesubproject
musi być przekazany jakosubproject
, a nie./subproject/
Uwaga dla użytkowników systemu windows: gdy głębokość folderu wynosi > 1, {[17] } musi mieć separator folderów w stylu *Nix ( / ). Na przykład, folder o nazwie {[22] } musi być przekazany jako
path1/path2/subproject
-
Utwórz nowy repo
mkdir <new-repo> pushd <new-repo> git init git pull </path/to/big-repo> <name-of-new-branch>
-
[[38]}Połącz nowe repo z Github lub gdziekolwiek
git remote add origin <[email protected]:my-user/new-repo.git> git push origin -u master
-
Czyszczenie, w razie potrzeby
popd # get out of <new-repo> pushd <big-repo> git rm -rf <name-of-folder>
Uwaga: To pozostawia wszystkie odniesienia Historyczne w repozytorium.Zobacz dodatek poniżej, jeśli naprawdę obawiasz się, że popełniłeś hasło lub musisz zmniejszyć rozmiar pliku folderu
.git
.
...
Walkthrough
Są to te same kroki jak powyżej , ale wykonując dokładne kroki dla mojego repozytorium zamiast używać <meta-named-things>
.
Oto projekt, który mam do implementacji modułów przeglądarki JavaScript w węzeł:
tree ~/Code/node-browser-compat
node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator
Chcę podzielić pojedynczy folder, btoa
, na osobne repozytorium git
pushd ~/Code/node-browser-compat/
git subtree split -P btoa -b btoa-only
popd
Mam teraz nową gałąź, btoa-only
, która posiada commity tylko dla btoa
i chcę utworzyć nowe repozytorium.
mkdir ~/Code/btoa/
pushd ~/Code/btoa/
git init
git pull ~/Code/node-browser-compat btoa-only
[20]} następnie tworzę nowe repo na Githubie lub bitbucket, lub cokolwiek i dodaję to origin
(btw, "origin" to tylko konwencja , a nie część polecenia - można by to nazwać "remote-server" lub jak tam chcesz)
git remote add origin [email protected]:node-browser-compat/btoa.git
git push origin -u master
Happy dzień!
Uwaga: jeśli utworzyłeś repo z README.md
, .gitignore
i LICENSE
, musisz najpierw pociągnąć:
git pull origin -u master
git push origin -u master
Na koniec chcę usunąć folder z większego repo
git rm -rf btoa
...
Dodatek
Najnowszy git na OS X
Aby pobrać najnowszą wersję git:
brew install git
Aby uzyskać brew dla OS X:
Najnowszy git na Ubuntu
sudo apt-get update
sudo apt-get install git
git --version
If that doesn ' t work (you mieć bardzo starą wersję ubuntu), spróbuj
sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git
Jeśli to nadal nie działa, spróbuj
sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree
Dzięki rui.araujo z komentarzy.
Czyszczenie historii
Domyślnie usunięcie plików z git nie usuwa ich z git, po prostu potwierdza, że już ich nie ma. Jeśli chcesz rzeczywiście usunąć odniesienia historyczne( tzn. masz popełnione hasło), musisz to zrobić: {]}
git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD
Po tym możesz sprawdzić, że Twój plik lub folder w ogóle nie pojawia się w historii Gita
git log -- <name-of-folder> # should show nothing
Jednak nie możesz "wcisnąć" usunięć do Githuba i tym podobnych. Jeśli spróbujesz, dostaniesz błąd i będziesz musiał git pull
, zanim będziesz mógł git push
- a potem wrócisz do wszystkiego w swojej historii.
Więc jeśli chcesz usunąć historię z "origin" - czyli usunąć ją z github, bitbucket, itp - Musisz usunąć repo i ponownie wcisnąć przyciętą kopię repo. Ale czekaj - Jest więcej! - Jeśli naprawdę martwisz się o pozbycie się hasła lub czegoś podobnego, musisz przyciąć kopię zapasową (patrz poniżej).
Making .git
smaller
Wspomniane polecenie delete history wciąż pozostawia po sobie kilka plików kopii zapasowych - ponieważ git jest zbyt miły, pomagając Ci nie zrujnować twojego repo przez przypadek. Ostatecznie usunie osierocone pliki w ciągu dni i miesięcy, ale pozostawia je tam na jakiś czas, jeśli zdasz sobie sprawę że przypadkowo usunąłeś coś, czego nie chciałeś.
Więc jeśli naprawdę chcesz opróżnić kosz aby zmniejszyć rozmiar klonu repo natychmiast musisz zrobić te wszystkie naprawdę dziwne rzeczy:
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now
git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune
To powiedziawszy, polecam nie wykonywać tych kroków, chyba że wiesz, że musisz - na wypadek, gdybyś nie przyciął złego podkatalogu, wiesz? Pliki kopii zapasowych nie powinny być sklonowane po naciśnięciu repo, będą po prostu w Twoim lokalnym przyjąłem.
Kredyt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26
Odpowiedź Paula tworzy nowe repozytorium zawierające / ABC, ale nie usuwa /ABC z / XYZ. Następujące polecenie usunie /ABC z wewnątrz / XYZ:
git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD
Oczywiście najpierw przetestuj go w repozytorium 'clone --no-hardlinks' i wykonaj go poleceniami reset, gc i prune.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:26
Odkryłem, że aby poprawnie usunąć starą historię z nowego repozytorium, musisz wykonać trochę więcej pracy po kroku filter-branch
.
-
Zrób klon i filtr:
git clone --no-hardlinks foo bar; cd bar git filter-branch --subdirectory-filter subdir/you/want
-
Usuń wszystkie odniesienia do starej historii. "origin" śledził Twój klon, a "original" to miejsce, w którym filter-branch zapisuje stare rzeczy: {]}
git remote rm origin git update-ref -d refs/original/refs/heads/master git reflog expire --expire=now --all
-
Nawet teraz twoja historia może utknąć w pliku packfile, którego fsck nie dotknie. Rozedrzyj to na strzępy, tworzenie nowego pliku packfile i usuwanie nieużywanych obiektów:
git repack -ad
Istnieje wyjaśnienie tego w instrukcji dla filter-branch .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-05 18:18:29
Edycja: dodano skrypt Bash.
Odpowiedzi podane tutaj zadziałały tylko częściowo dla mnie; wiele dużych plików pozostało w pamięci podręcznej. Co w końcu zadziałało (po godzinach w #git na freenode):
git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now
W przypadku poprzednich rozwiązań rozmiar repozytorium wynosił około 100 MB. Ten zmniejszył go do 1,7 MB. Może to komuś pomoże:)
Następujący skrypt bash automatyzuje zadanie:
!/bin/bash
if (( $# < 3 ))
then
echo "Usage: $0 </path/to/repo/> <directory/to/extract/> <newName>"
echo
echo "Example: $0 /Projects/42.git first/answer/ firstAnswer"
exit 1
fi
clone=/tmp/${3}Clone
newN=/tmp/${3}
git clone --no-hardlinks file://$1 ${clone}
cd ${clone}
git filter-branch --subdirectory-filter $2 --prune-empty --tag-name-filter cat -- --all
git clone file://${clone} ${newN}
cd ${newN}
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-11 14:00:08
To nie jest już tak skomplikowane, że możesz użyć komendy git filter-branch na klonie twojego repo, aby pobrać podkatalogi, których nie chcesz, a następnie wcisnąć do nowego pilota.
git filter-branch --prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git push <MY_NEW_REMOTE_URL> -f .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 18:43:21
Update : moduł Git-subtree był tak przydatny, że zespół git wciągnął go do core i stworzył git subtree
. Zobacz tutaj: odłącz (przenieś) podkatalog do oddzielnego repozytorium Git
Git-subtree może być przydatne do tego
Http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt (deprecated)
Http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:26
Oto mała modyfikacja CoolAJ86 ' S "the Easy Way™" answer w celu podzielenia wielu podfolderów (powiedzmy sub1
i sub2
) do nowego repozytorium git.
The Easy Way™ (wiele podkatalogów)
-
Przygotuj stare repo
pushd <big-repo> git filter-branch --tree-filter "mkdir <name-of-folder>; mv <sub1> <sub2> <name-of-folder>/" HEAD git subtree split -P <name-of-folder> -b <name-of-new-branch> popd
Uwaga:
<name-of-folder>
nie może zawierać znaków początkowych ani końcowych. Na przykład, folder o nazwie {[7] } musi być przekazany jakosubproject
, a nie./subproject/
Uwaga dla użytkownicy systemu windows: gdy głębokość folderu wynosi > 1, {[6] } musi mieć separator folderów w stylu * Nix ( / ). Na przykład, folder o nazwie {[11] } musi być przekazany jako
path1/path2/subproject
. Ponadto nie używaj komendymv
, leczmove
.Ostatnia uwaga: unikalną i dużą różnicą od odpowiedzi podstawowej jest druga linia skryptu "
git filter-branch...
" -
Utwórz nowy repo
mkdir <new-repo> pushd <new-repo> git init git pull </path/to/big-repo> <name-of-new-branch>
-
Połącz nowe repo z Github lub wherever
git remote add origin <[email protected]:my-user/new-repo.git> git push origin -u master
-
Czyszczenie, W razie potrzeby
popd # get out of <new-repo> pushd <big-repo> git rm -rf <name-of-folder>
Uwaga : pozostawia to wszystkie historyczne odniesienia w repozytorium.Zobacz dodatek w oryginalnej odpowiedzi, jeśli rzeczywiście obawiasz się popełnienia hasła lub musisz zmniejszyć rozmiar pliku folderu
.git
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:37
Oryginalne pytanie chce, aby xyz/ABC/(*files) stał się ABC/ABC / (*files). Po zaimplementowaniu zaakceptowanej odpowiedzi do własnego kodu zauważyłem, że faktycznie zmienia on XYZ/ABC/(*files) na ABC/(*files). Strona podręcznika filter-branch mówi nawet:
Wynik będzie zawierał ten katalog (i tylko ten) jako główny projekt ."
Innymi słowy, Promuje folder najwyższego poziomu " up " o jeden poziom. To ważne rozróżnienie, bo np. w moim historia nazwałem folder najwyższego poziomu. Poprzez promowanie folderów "w górę" o jeden poziom, git traci ciągłość w commicie, w którym dokonałem zmiany nazwy.
Moja odpowiedź na to pytanie to zrobić 2 kopie repozytorium i ręcznie usunąć folder(y), które chcesz zachować w każdym. Strona man wspiera mnie tym:
[...] unikaj używania [tej komendy], jeśli pojedynczy commit wystarczy, aby rozwiązać twój problem
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-17 05:12:06
Aby dodać do odpowiedź Paula , odkryłem, że aby ostatecznie odzyskać przestrzeń, muszę wcisnąć głowę do czystego repozytorium, a to zmniejsza rozmiar .katalog git/objects/pack.
Tzn.
$ mkdir ...ABC.git $ cd ...ABC.git $ git init --bare
Po śliwce gc również zrób:
$ git push ...ABC.git HEAD
Wtedy możesz zrobić
$ git clone ...ABC.git
I wielkość ABC/.git jest zredukowany
Git gc) nie są potrzebne przy czyszczeniu repozytorium, np.:$ git clone --no-hardlinks /XYZ /ABC $ git filter-branch --subdirectory-filter ABC HEAD $ git reset --hard $ git push ...ABC.git HEAD
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:41
Właściwa droga teraz jest następująca:
git filter-branch --prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]
GitHub ma teraz nawet mały artykuł o takich przypadkach.
Ale pamiętaj, aby najpierw sklonować oryginalne repo do oddzielnego katalogu(ponieważ usunęłoby to wszystkie pliki i inne katalogi i prawdopodobnie będziesz musiał z nimi pracować).
Więc twój algorytm powinien być:
- Sklonuj zdalne repo do innego katalogu
- używając
git filter-branch
pozostawia tylko pliki pod jakimś podkatalogiem, wciśnij do new remote - Utwórz commit, aby usunąć ten podkatalog z oryginalnego zdalnego repo
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-12 13:22:04
Wydaje się, że większość(wszystkie?) odpowiedzi tutaj opierają się na jakiejś formie git filter-branch --subdirectory-filter
i jej podobieństwie. Może to działać "najczęściej", jednak w niektórych przypadkach, na przykład w przypadku zmiany nazwy folderu, np.]}
ABC/
/move_this_dir # did some work here, then renamed it to
ABC/
/move_this_dir_renamed
Jeśli wykonasz zwykły styl filtra Gita, aby wyodrębnić "move_me_renamed", stracisz historię zmian pliku, która miała miejsce Od początku, gdy był to move_this_dir (ref ).
Wydaje się więc, że jedynym sposobem, aby naprawdę zachować całą historię zmian (jeśli twój przypadek jest taki jak ten), jest, w istocie, skopiować repozytorium( utworzyć nowy repo, ustawić, że jest źródłem), następnie nuke Wszystko inne I zmienić nazwę podkatalogu do rodzica w następujący sposób:
- Klonuj projekt wielomodułowy lokalnie
- gałęzie-sprawdź co tam jest:
git branch -a
- wykonaj zamówienie dla każdej gałęzi, która zostanie uwzględniona w podziale, aby uzyskać lokalną kopię na swojej stacji roboczej:
git checkout --track origin/branchABC
- zrób kopię w nowym katalogu:
cp -r oldmultimod simple
- idź do nowa kopia projektu:
cd simple
- pozbądź się innych modułów, które nie są potrzebne w tym projekcie:
git rm otherModule1 other2 other3
- teraz pozostaje tylko subdir modułu docelowego
- pozbądź się subdir modułu, aby główny moduł stał się nowym korzeniem projektu
git mv moduleSubdir1/* .
- Usuń subdir relikwii:
rmdir moduleSubdir1
- Sprawdź zmiany w dowolnym momencie:
git status
- Utwórz nowy Git repo i skopiuj jego adres URL, aby skierować ten projekt do it:
git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
- zweryfikuj to dobrze:
git remote -v
- Przesuń zmiany do zdalnego repo:
git push
- idź do zdalnego repo i sprawdź, czy wszystko tam jest
- powtórz dla każdej innej gałęzi:
git checkout branch2
To wynika z dokumentu github "dzielenie podfolderu na nowe repozytorium" kroków 6-11, aby wypchnąć moduł do nowego repozytorium.
To nie pozwoli Ci zaoszczędzić miejsca w Twoim .folder git, ale zachowa on wszystkie Twoje Zmień historię tych plików nawet w trakcie zmiany nazw. A to może nie być tego warte, jeśli nie ma" dużo " utraconej historii itp. Ale przynajmniej masz gwarancję, że nie stracisz starszych commitów!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-31 10:41:55
Miałem dokładnie taki problem, ale wszystkie standardowe rozwiązania bazujące na git filter-branch były bardzo wolne. Jeśli masz małe repozytorium, to może nie być to problem, to było dla mnie. Napisałem kolejny program filtrujący git oparty na libgit2, który w pierwszym kroku tworzy gałęzie dla każdego filtrowania repozytorium podstawowego, a następnie wypycha je do czyszczenia repozytoriów jako następny krok. W moim repozytorium (500MB 100000 commitów) standardowe metody Git filter-branch zajmowały kilka dni. Mój program zajmuje minut, aby zrobić to samo filtrowanie.
Ma bajeczną nazwę git_filter i mieszka tutaj:
Https://github.com/slobobaby/git_filter
Na GitHubie.
Mam nadzieję, że komuś się przyda.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 17:39:13
Jeśli to coś warte, oto jak używać Githuba na komputerze z systemem Windows. Załóżmy, że masz sklonowany repo w C:\dir1
. Struktura katalogów wygląda następująco: C:\dir1\dir2\dir3
. Katalog dir3
jest Tym, który chcę być nowym oddzielnym repo.
Github:
- Utwórz nowe repozytorium:
MyTeam/mynewrepo
Bash Prompt:
$ cd c:/Dir1
$ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
Returned:Ref 'refs/heads/master' was rewritten
(fyi: dir2/dir3 is case wrażliwa.)$ git remote add some_name [email protected]:MyTeam/mynewrepo.git
git remote add origin etc
. nie działał, wrócił "remote origin already exists
"$ git push --progress some_name master
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 01:26:14
Pierwszy, filter-branch
zrobił świetną robotę usuwania commitów, które wprowadzają lub modyfikują kod, ale najwyraźniej merge commity znajdują się pod jego stacją w Gitiverse.
Jest to kwestia kosmetyczna, z którą prawdopodobnie mogę żyć (mówi...cofając się powoli z odwróconymi oczami) .
Po drugie nieliczne commity, które pozostały, są w zasadzie wszystkie zduplikowane! Wydaje mi się, że nabyłem drugą, zbędną oś czasu, która obejmuje całą historię projektu. Ciekawostką (co widać na poniższym zdjęciu) jest to, że moje trzy lokalne oddziały nie są na tej samej osi czasu (czyli, na pewno, dlaczego istnieje i nie jest tylko śmieci zbierane).
Jedyne, co mogę sobie wyobrazić, to to, że jednym z usuniętych commitów był, być może, pojedynczy commit scalający, który filter-branch
faktycznie usunąłem , A To stworzyło równoległą linię czasową, ponieważ każda teraz niezergowana część przyjęła własną kopię commitów. (shrug gdzie jest moja TARDiS?) Jestem prawie pewien, że mogę to naprawić problem, choć naprawdę chciałbym zrozumieć, jak to się stało.
W przypadku szalonego mergefest-O-RAMA, prawdopodobnie zostawię go samego, ponieważ tak mocno zakorzenił się w mojej historii commitów-groźny dla mnie za każdym razem, gdy się zbliżam -, nie wydaje się, aby w rzeczywistości powodował problemy nie kosmetyczne i ponieważ jest całkiem ładny w Tower.app.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:26
Użyj tego polecenia filter, aby usunąć podkatalog, zachowując swoje tagi i gałęzie:
git filter-branch --index-filter \
"git rm -r -f --cached --ignore-unmatch DIR" --prune-empty \
--tag-name-filter cat -- --all
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-26 14:51:21
The Easier Way
- zainstaluj
git splits
. Stworzyłem go jako rozszerzenie git, oparte na rozwiązaniu jkeating. Podziel katalogi na lokalną gałąź
#change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ
#split multiple directories into new branch XYZ git splits -b XYZ XY1 XY2Utwórz gdzieś pusty repo. Założymy, że stworzyliśmy puste repo o nazwie
xyz
na Githubie, które ma path :[email protected]:simpliwp/xyz.git
/ align = "left" /
#add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz [email protected]:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master
Sklonuj nowo utworzony zdalny repo do nowego lokalnego katalog
#change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone [email protected]:simpliwp/xyz.git
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:26
Możesz potrzebować czegoś w rodzaju "git reflog expire -- expire=now --all" przed garbage collectingiem, aby wyczyścić pliki. git filter-branch usuwa tylko odniesienia w historii, ale nie usuwa wpisów reflog, które zawierają dane. Oczywiście najpierw przetestuj to.
Moje użycie dysku drastycznie spadło przy tym, chociaż moje początkowe warunki były nieco inne. Być może --subdirectory-filter neguje tę potrzebę, ale wątpię.
Sprawdź projekt git_split na https://github.com/vangorra/git_split
Zamień katalogi Gita w ich własne repozytoria w ich własnej lokalizacji. Bez podtekstów. Skrypt pobierze istniejący katalog w repozytorium git i zamieni go w niezależne repozytorium. Po drodze skopiuje całą historię zmian w podanym katalogu.
./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo>
src_repo - The source repo to pull from.
src_branch - The branch of the source repo to pull from. (usually master)
relative_dir_path - Relative path of the directory in the source repo to split.
dest_repo - The repo to push to.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-06 02:42:05
Włóż to do gitconfig:
reduce-to-subfolder = !sh -c 'git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter cookbooks/unicorn HEAD && git reset --hard && git for-each-ref refs/original/ | cut -f 2 | xargs -n 1 git update-ref -d && git reflog expire --expire=now --all && git gc --aggressive --prune=now && git remote rm origin'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-29 20:18:09
Jestem pewien, że subtree git jest w porządku i wspaniałe, ale moje podkatalogi kodu zarządzanego git, które chciałem przenieść, były w eclipse. Więc jeśli używasz egit, jest to boleśnie łatwe. Weź projekt, który chcesz przenieść i zespół - > odłącz go, a następnie zespół- > udostępnij go w nowej lokalizacji. Domyślnie będzie próbować użyć starej lokalizacji repo, ale możesz odznaczyć zaznaczenie use-existing i wybrać nowe miejsce, aby je przenieść. Chwała egitowi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-10 16:57:12
Polecam GitHub ' s guide do podziału podfolderów na nowe repozytorium. Kroki są podobne do Paul ' s answer , ale okazało się, że ich instrukcje są łatwiejsze do zrozumienia.
Zmodyfikowałem instrukcje tak, że dotyczą lokalnego repozytorium, a nie hostowanego na Githubie.
Podział podfolderu na nowe repozytorium
Otwórz Git Bash.
Zmień prąd working directory to the location where you want to create your new repozytorium.
Sklonuj repozytorium zawierające podfolder.
git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
- Zmień bieżący katalog roboczy na sklonowane repozytorium.
cd REPOSITORY-NAME
- aby odfiltrować podfolder z pozostałych plików w repozytorium, Uruchom
git filter-branch
, dostarczając te informacje:
FOLDER-NAME
: folder w Twoim projekcie z którego chcesz utworzyć osobne repozytorium.
- Wskazówka: użytkownicy systemu Windows powinni używać
/
do rozdzielania folderów.BRANCH-NAME
: domyślna gałąź dla bieżącego projektu, na przykładmaster
lubgh-pages
.git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME # Filter the specified branch in your directory and remove empty commits Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (89/89) Ref 'refs/heads/BRANCH-NAME' was rewritten
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-31 14:02:49