チャプター ▾ 第2版

10.5 Git の内部 - Refspec

Refspec

本書を通して、リモートブランチからローカル参照への単純なマッピングを使用してきましたが、これらはより複雑になる可能性があります。前のいくつかのセクションを読んでいて、小さなローカル Git リポジトリを作成し、それにリモートを追加したいとします。

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

上記のコマンドを実行すると、リポジトリの.git/configファイルにセクションが追加され、リモートの名前(origin)、リモートリポジトリのURL、およびフェッチに使用されるrefspecが指定されます。

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

refspec の形式は、まずオプションの+、次に<src>:<dst>が続きます。ここで、<src>はリモート側の参照のパターンで、<dst>はそれらの参照がローカルで追跡される場所です。+は、fast-forward でない場合でも、Git に参照を更新するように指示します。

git remote add originコマンドによって自動的に書き込まれるデフォルトのケースでは、Git はサーバー上のrefs/heads/以下のすべての参照をフェッチし、それらをローカルのrefs/remotes/origin/に書き込みます。したがって、サーバー上にmasterブランチがある場合、そのブランチのログにはローカルで以下のいずれかの方法でアクセスできます。

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

Git はそれぞれをrefs/remotes/origin/masterに展開するため、これらはすべて同等です。

Git に毎回masterブランチのみをプルダウンさせ、リモートサーバー上の他のすべてのブランチはプルダウンさせないようにしたい場合は、フェッチ行をそのブランチのみを参照するように変更できます。

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

これは、そのリモートに対するgit fetchのデフォルトのrefspecにすぎません。一度だけフェッチしたい場合は、コマンドラインで特定のrefspecを指定することもできます。リモートのmasterブランチをローカルのorigin/mymasterにプルするには、次のコマンドを実行します。

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

複数の refspec を指定することもできます。コマンドラインでは、次のようにいくつかのブランチをプルダウンできます。

$ 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

この場合、masterブランチのプルは、fast-forward 参照としてリストされていなかったため拒否されました。refspec の前に+を指定することで、これを上書きできます。

設定ファイルでフェッチ用の複数の refspec を指定することもできます。originリモートから常にmasterexperimentブランチをフェッチしたい場合は、2行を追加します。

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

Git 2.6.0 以降、パターンで部分的なグロブを使用して複数のブランチにマッチさせることができるため、これは機能します。

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

さらに良いのは、名前空間 (またはディレクトリ) を使用して、より構造的に同じことを実現できることです。QA チームが一連のブランチをプッシュし、masterブランチと QA チームのブランチのいずれかを取得したいが、他は何も取得したくない場合、次のような設定セクションを使用できます。

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

QA チームがブランチをプッシュし、開発者がブランチをプッシュし、統合チームがリモートブランチでプッシュと共同作業を行う複雑なワークフロープロセスがある場合、このように簡単に名前空間を設定できます。

Refspec のプッシュ

そのように名前空間付きの参照をフェッチできるのは良いことですが、そもそも QA チームはどのようにしてブランチをqa/名前空間に入れるのでしょうか?これは、refspec を使用してプッシュすることで実現します。

QA チームが自身のmasterブランチをリモートサーバーのqa/masterにプッシュしたい場合、次のコマンドを実行できます。

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

git push originを実行するたびに Git に自動的にそうさせたい場合は、設定ファイルにpushの値を追加できます。

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

繰り返しますが、これによりgit push originは、デフォルトでローカルのmasterブランチをリモートのqa/masterブランチにプッシュします。

refspec を使用して、あるリポジトリからフェッチし、別のリポジトリにプッシュすることはできません。これを行う例については、GitHub の公開リポジトリを最新の状態に保つを参照してください。

参照の削除

refspec を使用して、次のように実行することで、リモートサーバーから参照を削除することもできます。

$ git push origin :topic

refspec は<src>:<dst>なので、<src>部分を省略することで、基本的にリモート上のtopicブランチを何もない状態にする、つまり削除すると言っていることになります。

または、新しい構文 (Git v1.7.0 以降で利用可能) を使用することもできます。

$ git push origin --delete topic
scroll-to-top