Git
Chapters ▾ 1st Edition

.5 Mechanizmy wewnętrzne w Git - Refspec

Refspec

W trakcie czytania tej książki, używałeś prostych mapowań ze zdalnych gałęzi do lokalnych referencji; jednak mogą one być znaczniej bardziej złożone. Załóżmy, że dodajesz zdalne repozytorium w taki sposób:

$ git remote add origin git@github.com:schacon/simplegit-progit.git

Doda to kolejną sekcję w pliku .git/config, określającą nazwę zdalnego repozytorium (origin), adres URL tego repozytorium, oraz refspec do pobierania:

[remote "origin"]
       url = git@github.com:schacon/simplegit-progit.git
       fetch = +refs/heads/*:refs/remotes/origin/*

Refspec składa się z opcjonalnego znaku +, oraz wskazania ścieżki źródłowej i docelowej <src>:<dst>, gdzie <src> wskazuje referencję na zewnętrznym serwerze, a <dst> jest miejscem, w którym te referencje będą zapisywane lokalnie. Znak + wskazuje Gitowi, aby wykonywał aktualizację nawet wtedy, gdy ta referencja nie jest zwykłym przesunięciem (ang. fast-forward).

W zwyczajnym przypadku, jest to zapisywane automatycznie przez komendę git remote add, Git pobiera wszystkie referencje z refs/heads/ na serwerze i zapisuje je do refs/remotes/origin/ lokalnie. Więc, jeżeli istnieje gałąź master na serwerze, możesz uzyskać dostęp do logów tej gałęzi poprzez

$ git log origin/master
$ git log remotes/origin/master
$ git log refs/remotes/origin/master

Wszystkie te komendy są równoważne, ponieważ Git rozwinie je wszystkie do refs/remotes/origin/master.

Jeżeli chciałbyś, aby Git pobierał za każdym razem tylko gałąź master, a nie wszystkie inne gałęzie na zdalnym serwerze, możesz zmienić linię fetch na

fetch = +refs/heads/master:refs/remotes/origin/master

Jest to po prostu domyślna definicja refspec używana przez komendę git fetch podczas pobierania danych ze zdalnego repozytorium. Jeżeli chcesz wykonać coś jednorazowo, możesz podać definicję refspec również z linii komend. Aby pobrać gałąź master z zdalnego serwera, do origin/mymaster możesz uruchomić

$ git fetch origin master:refs/remotes/origin/mymaster

Możesz również ustawić kilka refspec. Z linii komend, możesz pobrać kilka gałęzi za pomocą:

$ git fetch origin master:refs/remotes/origin/mymaster \
   topic:refs/remotes/origin/topic
From git@github.com:schacon/simplegit
 ! [rejected]        master     -> origin/mymaster  (non fast forward)
 * [new branch]      topic      -> origin/topic

W tym wypadku, pobieranie gałęzi master zostało odrzucone, ponieważ nie była to gałąź fast-forward (tzn. nie było możliwe wykonanie prostego przesunięcia w celu włączenia zmian). Możesz to zmienić, poprzez ustawienie znaku + na początku definicji refspec.

Możesz również ustawić wiele definicji refspec w pliku konfiguracyjnym. Jeżeli zawsze chcesz pobierać gałęzie master i experiment, dodaj dwie linie:

[remote "origin"]
       url = git@github.com:schacon/simplegit-progit.git
       fetch = +refs/heads/master:refs/remotes/origin/master
       fetch = +refs/heads/experiment:refs/remotes/origin/experiment

Nie możesz użyć masek na ścieżkach, więc takie ustawienie będzie błędne:

fetch = +refs/heads/qa*:refs/remotes/origin/qa*

Możesz jednak użyć przestrzeni nazw aby osiągnąć podobny efekt. Jeżeli masz zespół QA, który wypycha nowe gałęzie, a Ty chcesz pobrać tylko gałąź master oraz wszystkie gałęzie stworzone przez zespół QA, możesz wpisać w pliku konfiguracyjnym coś takiego:

[remote "origin"]
       url = git@github.com:schacon/simplegit-progit.git
       fetch = +refs/heads/master:refs/remotes/origin/master
       fetch = +refs/heads/qa/*:refs/remotes/origin/qa/*

Jeżeli masz bardziej złożony sposób współpracy, w którym zespół QA wypycha gałęzie, programiści wypychają gałęzie, oraz zespół integrujący również wypycha oraz współpracuje ze zdalnymi gałęziami, możesz stworzyć dla każdego z nich przestrzenie nazw w ten sposób.

Wypychanie Refspecs

Fajnie, że w tym sposobem możesz pobrać referencje z konkretnych referencji, ale w jaki sposób zespół QA ma wstawiać swoje gałęzie do przestrzeni qa/ w pierwszej kolejności? Możesz to osiągnąć, poprzez użycie refspec dla komendy push.

Jeżeli zespół QA chce wypychać swoją gałąź master do qa/master na zdalnym serwerze, mogą oni uruchomić

$ git push origin master:refs/heads/qa/master

Jeżeli zechcą, aby Git robił to automatycznie za każdym razem po uruchomieniu git push origin, mogą dodać definicję push do swojego pliku konfiguracyjnego:

[remote "origin"]
       url = git@github.com:schacon/simplegit-progit.git
       fetch = +refs/heads/*:refs/remotes/origin/*
       push = refs/heads/master:refs/heads/qa/master

I znowu, to spowoduje, że komenda git push origin będzie domyślnie wypychała lokalną gałąź master do zdalnej qa/master.

Usuwanie referencji

Możesz również używać definicji refspec do usuwania referencji ze zdalnego serwera, poprzez uruchomienie komendy podobnej do:

$ git push origin :topic

Ponieważ refspec składa się z <src>:<dst>, przez opuszczenie części <src>, wskazujesz aby stworzyć nową pustą gałąź tematyczną, co ją kasuje.