Git
Chapters ▾ 1st Edition

6.7 Narzędzia Gita - Włączanie innych projektów

Włączanie innych projektów

Teraz, gdy znasz już trudności związane z modułami zależnymi, spójrzmy na alternatywny sposób rozwiązania tego problemu. Kiedy Git ma włączyć zmiany, najpierw sprawdza jakie zmiany ma włączyć, a następnie wybiera najlepszą strategię do wykonania tego zadania. Jeżeli łączysz dwie gałęzie, Git użyje strategii rekurencyjnej. Jeżeli łączysz więcej niż dwie gałęzie, Git wybierze strategię ośmiornicy. Te strategie są automatycznie wybierane za Ciebie, ponieważ rekurencyjna strategia może obsłużyć sytuacje łączenia trójstronnego - na przykład, w przypadku więcej niż jednego wspólnego przodka - ale może obsłużyć tylko łączenie dwóch gałęzi. Strategia ośmiornicy może obsłużyć większą ilość gałęzi, ale jest bardziej ostrożna, aby uniknąć trudnych do rozwiązania konfliktów, dlatego jest domyślną strategią w przypadku gdy łączysz więcej niż dwie gałęzie.

Natomiast, są również inne strategie które możesz wybrać. Jedną z nich jest łączenie subtree i możesz go używać z podprojektami. Zobaczysz tutaj jak włączyć do projektu projekt rack opisany w poprzedniej sekcji, ale przy użyciu łączenia subtree.

W zamyśle, łącznie "subtree" jest wtedy, gdy masz dwa projekty w których jeden mapuje się do podkatalogu w drugim i na odwrót. Kiedy użyjesz łączenia "subtree", Git jest na tyle mądry, aby dowiedzieć się, że jeden z nich jest włączany do drugiego i odpowiednio jest złączyć - jest to całkiem ciekawe.

Najpierw dodajesz aplikację Rack do swojego projektu. Dodajesz projekt Rack, jako zdalny i następnie pobierasz go do dedykowanej gałęzi.

$ git remote add rack_remote git@github.com:schacon/rack.git
$ git fetch rack_remote
warning: no common commits
remote: Counting objects: 3184, done.
remote: Compressing objects: 100% (1465/1465), done.
remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done.
Resolving deltas: 100% (1952/1952), done.
From git@github.com:schacon/rack
 * [new branch]      build      -> rack_remote/build
 * [new branch]      master     -> rack_remote/master
 * [new branch]      rack-0.4   -> rack_remote/rack-0.4
 * [new branch]      rack-0.9   -> rack_remote/rack-0.9
$ git checkout -b rack_branch rack_remote/master
Branch rack_branch set up to track remote branch refs/remotes/rack_remote/master.
Switched to a new branch "rack_branch"

Masz teraz zawartość projektu Rack w gałęzi rack_branch, a swój projekt w gałęzi master. Jeżeli pobierzesz najpierw jedną, a potem drugą gałąź, zobaczysz że mają one inną zawartość:

$ ls
AUTHORS        KNOWN-ISSUES   Rakefile      contrib        lib
COPYING        README         bin           example        test
$ git checkout master
Switched to branch "master"
$ ls
README

Chcesz jednak, pobrać projekt Rack do swojej gałęzi master jako podkatalog. Możesz to zrobić, za pomocą komendy Gita git read-tree. Dowiesz się więcej na temat komendy read-tree i jej podobnych w rozdziale 9, ale na teraz wiedz, że odczytuje ona drzewo projektu w jednej gałęzi i włącza je do obecnego katalogu i przechowalni. Ponownie zmieniasz gałąź na master i pobierasz gałąź rack do podkatalogu rack w gałęzi master w projekcie:

$ git read-tree --prefix=rack/ -u rack_branch

Kiedy wykonasz commit, będzie wyglądało że masz wszystkie pliki Rack w podkatalogu - tak jakbyś skopiował je z spakowanego archiwum. To co jest interesujące, to to, że możesz bardzo łatwo włączać zmiany z jednej gałęzi do drugiej. Więc, jeżeli projekt Rack zostanie zaktualizowany, możesz pobrać te zmiany poprzez przełączenie się na gałąź i wydanie komend:

$ git checkout rack_branch
$ git pull

Następnie, możesz włączyć te zmiany do swojej gałęzi master. Możesz użyć git merge -s subtree i ta zadziała poprawnie; ale Git również połączy historię zmian ze sobą, czego prawdopodobnie nie chcesz. Aby pobrać zmiany i samemu wypełnił treść komentarza, użyj opcji --squash oraz --no-commit do opcji -s subtree:

$ git checkout master
$ git merge --squash -s subtree --no-commit rack_branch
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested

Wszystkie zmiany z Twojego projektu Rack są włączone i gotowe do zatwierdzenia lokalnie. Możesz zrobić to również na odwrót - wprowadź zmiany w podkatalogu rack w gałęzi master, a potem włącz je do gałęzi rack_branch, aby wysłać je do opiekunów projektu.

Aby zobaczyć różnicę w zmianach które masz w swoim podkatalogu rack i gałęzi rack_branch - aby zobaczyć czy trzeba je włączyć - nie możesz użyć normalnie komendy diff. Zamiast tego musisz użyć komendy git diff-tree z nazwą gałęzi do której chcesz przywrównać kod:

$ git diff-tree -p rack_branch

Lub, aby porównać zawartość Twojego podkatalogu rack z tym co jak wyglądała gałąź master na serwerze w momencie, gdy ją pobierałeś możesz uruchomić

$ git diff-tree -p rack_remote/master