Git - podkatalog jako nowe repozytorium

2013-11-29 , Papiewski Łukasz , Software / Oprogramowanie / Narzędzia

Git jest bardzo przydatnym narzędziem do zarządzania wersjami o wiele lepszym niż svn choć brakuje mu bardzo dobrej funkcjonalności typu svn externals, ale to wynika z jego designu, choć nie o tym tutaj.

Jeśli już mamy repozytorium i chcemy całą historię z jednego folderu przenieść do nowego repozytorium git wykonujemy kilka książkowych poleceń. W moim przypadku zachowamy historię ze wszystkich gałęzi nie, tylko z bieżącej jak w większości przykładów w sieci oraz usuniemy skopiowany katalog i wstawimy go jako pod mooduł. Warto zauważyć, że druga część procedury powinna być stosowana na osobistym repozytorium (nie dzielonym np na githubie) gdyż ingerujemy w historię. W przypadku gdy dzielimy z kimś to albo warto poinformować albo po prostu pozostawić historię i usunąć z poziomu klienta i dodać podmoduł. Oto procedura wraz z wymienionymi przypadkami:

Po pierwsze pobieramy repozytorium.

git clone https://papiewski.pl/git/project.git
cd project.git

Następnie dodajemy wszystkie śledzone gałęzie aby były uwzględnione w historii

#dodajemy wszystkie 
git branch -a 
for i in develop feature other ; do git branch -t $i origin/$i; done;
#lub
git branch -la | grep remotes/origin | cut -d '/' -f3 | grep -v HEAD | grep -v master| while read branch; do git branch -t $branch origin/$branch; done;

Usuwamy niepotrzebne referencje

git remote rm origin 
#optional tag removin
git tag -l
git tag -l | xargs git tag -d

Teraz filtrujemy, po tej komendzie w katalogu bieżącym będzie znajdować się tylko wybrany podkatalog

git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter choose/subdirectory -- --all
#opcjonalnie procedura usuwania logów

W tym momencie mamy informacje, które gałęzie nie zawierają żadnej historii z podkatalogu, a które zostały zmodyfikowane. Teraz posiadając wszystko co potrzeba wysyłamy do nowego repozytorium historię tego katalogu. Najpierw trzeba dodać nowe puste repozytorium i skopiować adres adres.

Przykładowo na gitolite - narzędzia, które używam do trzymania prywatnych projektów, pobieram z gitolite-admin, edytuje plik konfiguracyjny następnie wysyłam

Jeśli mamy adres pustego repozytorium (nazwa najlepiej taka jak podkatalogu) dodajemy go i wysyłamy wszystko

git remote add origin 
git push --all

Następnie dodajemy nowe repozytorium do oryginalnego projektu. Możemy usunąć całkowicie historie lub usunąć tylko folder z bieżącej wersji. Prześledźmy pierwszy przypadek w przypadku gdy chcemy zmniejszyć repozytorium i tylko my z niego korzystamy, w innym razie pomijamy ten krok

Aby usunąć z całej historii korzystamy także z filtrowania historii, używamy poniższej komendy. Pobieramy repozytorium całe jeszcze raz i wykonujemy

git filter-branch --tree-filter "rm -rf choosen/subdirectory" --prune-empty HEAD
#opcjonalnie procedura usuwania logów
#wysyłamy, uwaga nadpisujemy historię
git push origin --all --force

Aby usunąć tylko katalog z bieżącej wersji po prostu:

git rm choosen/subdirectory -f
git commit 
git push origin

Czasem przydatne jest usunięcie logów po filtrowaniu, jeśli chcemy zatwierdzić zmiany (bez tego można je cofnąć). Procedura czyszczenie po filtrowaniu wygląda następująco:

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

Ostatnią czynnością jest dodaniu w miejsce katalogu podmodułu tej samej zawartośći

git submodule add <URL> choosen/subdirectory

I to jest wszystko. Pamiętać należy, jeśli gdzieś mamy już to repozytorium np. na innym komputerze/serwerze to pull zwróci nam błąd jeśli usunęliśmy katalog z całej historii (nie problemu z drugim przypadkiem naturalnie) więc dobrze zrobić rebase (o czym napiszę w kolejnej części).

Cytaty

- Simplicity is the ultimate sophistication. - Leonardo da Vinci,
- Popularny człowiek wzbudza zawiść potężnych - Thufir Hawat o Leto Atrydzie (na Kaladanie),
- Szczęście następuje po smutku, a smutek po szczęściu; człowiek jest naprawdę wolny, gdy przestaje rozróżniać między smutkiem a szczęściem, między dobrem a złem - Aforyzmy buddyjskie.