Gitのデフォルト参照 (refs)
概要
GitのオブジェクトやコミットはSHA-1ハッシュ値で管理されている。ただ,毎回SHA-1ハッシュ値を直接指定するのは手間なので,SHA-1ハッシュ値を指す参照 (refs) が用意されている。
Gitではデフォルトで用意されている参照がいくつもある。今までよくわからない状態で使っていたが,最近ようやく理解できたでの,忘れたときのために整理する。
HEAD
HEADは最後 (現在) のコミットのSHA-1ハッシュを指す参照 (refs) を保持するシンボリック参照となっている (参考: Git – Gitの参照)。通常の参照と区別するために,シンボリック参照と呼んでいる。
具体的には,.git/HEADに値が格納されている。
cat .git/HEADref: refs/heads/master
通常は上記のように,ブランチへの参照が格納されている。ただし,git checkoutで直接コミットに移動した場合,参照ではなくSHA-1ハッシュ値が格納されている。
git checkout HEAD~1
cat .git/HEADd7f38fea38edc7e65388e7c90b125c1fe4f801d9
HEADを参照することで,最後のコミット (現在のコミット) を把握することができる。
日々のコマンドでよく使うシンボリック参照だ。
FETCH_HEAD
git fetchまたはgit pullした際にダウンロードしたリモートリポジトリーのブランチごとのSHA-1ハッシュ値を格納している (参考: Git – git-fetch Documentation)。
cat .git/FETCH_HEAD27ce7d102010ba6d9232027b5b7afac1db1316e8 branch 'master' of https://github.com/senooken/example 50bf24172bb962ef31f02abcbdce95662213210b not-for-merge branch 'gh-pages' of https://github.com/senooken/example
これにより,どこまでリモートリポジトリーをダウンロードしたかがわかるようになっている。
git fetchコマンドを実行した際のメッセージで見かけるくらいで,自分でコマンドで使うことはあまりない。
master
masterはGitのデフォルトのブランチ名を指す参照だ (参考: Git – git-init Documentation)。
具体的には,git initを実行してGItリポジトリーが作成すると,HEADがmasterブランチを指している。
git init
cat .git/HEADref: refs/heads/master
Git 2.28から設定やオプションでデフォルトのブランチ名を変更可能になっている。
Gitでブランチを切り変えて作業する場合に,必ず参照されるので,よく見かける参照だ。
origin
originはデフォルトのリモートリポジトリー名となっている。「Git – リモートでの作業」や「Git – git-clone Documentation」でそのことが説明されている。
より具体的には,git cloneしたリモートリポジトリー名のデフォルトがoriginとなっている。以下のコマンドで,現在のoriginを確認できる。
git remote -vorigin git@github.com:senooken/dotfile.git (fetch) origin git@github.com:senooken/dotfile.git (push)
リモートリポジトリー名も参照の一種である。リモートリポジトリー名のおかげで,URL使わずに済んでいる。
リモートリポジトリー名は以下のコマンドで変更できる。
git remote rename <old> <new>
リモートリポジトリーやそのブランチを参照する際に頻繁に使用する。HEADと同じかそれ以上に使用する参照となっている。
例えば,リモートリポジトリーのmasterブランチはorigin/masterで参照する。
ブランチ名だけの場合,ローカルのブランチを指すため,リモートのブランチを参照する際は常にリモートリポジトリー名が必要となる。
refs
参照 (refs) はGitにおけるSHA-1ハッシュ値を示す別名である (参考: Git – Gitの参照)。.git/refsディレクトリーの中身が実体となっている。
find .git/refs.git/refs/ .git/refs/tags .git/refs/remotes .git/refs/remotes/origin .git/refs/remotes/origin/master .git/refs/heads .git/refs/heads/master
refs/直下のディレクトリで用途が以下の通りに分けられている。
| 参照 | 説明 |
|---|---|
refs/tags | ローカルのタグへの参照を格納。 |
refs/heads | ローカルのブランチへの参照を格納。 |
refs/remotes | リモートリポジトリーへの参照 (ブランチ,タグ) を格納 |
.git/以降のrefsからを参照として使用でき,前半部分はGitが展開するため省略可能となっている。
例えば,以下のコマンドはどれも同じ意味となる。
git log refs/heads/master
git log heads/master
git log master念のため繰り返すが,ブランチ名だけを指定した場合,ローカルのブランチを指すので,リモートリポジトリー名を指定する場合はリモートリポジトリー名 (origin) などが必須となる。
refspec
refspecはリモートリポジトリーとローカルリポジトリーの対応関係の書式となっている (参考: Git – Refspec)。
具体的には,.git/config内で以下のように指定され,fetch/pullとpushで使用する。.git/config上ではそれぞれfetch, pushの別々の設定項目として設定する。
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/*:refs/remotes/origin/*
# fetch = +refs/heads/master:refs/remotes/origin/master
# push = :2行目のfetchの行の右辺がrefspecsとなっている。git cloneした場合のデフォルト値が2行目となっており,git clone --depth 1などでブランチを限定した場合が3行目となっている。
refspecは+<src>:<dst>という書式になっている。先頭の+はfast-forward以外の場合も取り込むことを意味する。
それ以外は,fetchとpushで若干意味が異なる。コマンドごとに以下の通りとなる。
| コマンド | <src> | <dst> |
|---|---|---|
fetch/pull | リモートリポジトリーの参照 | ローカルリポジトリーの参照 |
push | ローカルリポジトリーの参照 | リモートリポジトリーの参照 |
データの移動方向に合わせて,<src>と<dst>が指すものが反対になる。
詳細は以下のマニュアルを参照する。
<src>と<dst>には*のワイルドカードを使用できる。ただし,ファイル名の一部だけ (例: +refs/heads/qa*:refs/remotes/orign/qa*) を指定することはできず,ブランチ全体を指定することしかできない。
.git/configを直接編集する他,以下のコマンドでも変更・追加できる。
git config remote.origin.fetch refs/heads/master:refs/remotes/origin/master
git config --add remote.origin.fetch refs/heads/master:refs/remotes/origin/masterただ,基本的には自分で編集する必要はない。変更するとしたら,git clone --depth 1でクローンした後に,他のブランチもfetch/pullしたい場合に編集する場合がありえる。
その他,コマンドライン上ではリモートリポジトリーのブランチを削除する場合や,push先を変更する場合に使用する。
git push origin :topic # delete topic remote branch
git push origin master:gh-pages # push master to remote gh-pages
コマンド上で使う場合はGitが自動で解釈してくれるため,refsから書かなくても指定を一部省略できるようだ。
例えば,git push origin :topicは<src>の部分が省略されている。pushの場合は<src>=ローカルリポジトリーの参照を<dst>=リモートリポジトリの参照に送信するという意味になる。従って,この場合""=<dst>という意味となり,リモートリポジトリーのブランチ (<dst>) の参照を空にする,つまり削除するという意味になる。
その他,「GitHub Pages用gh-pagesブランチとmasterブランチの自動同期」に記した通り,GitHubでのWeb上での公開するために,masterブランチの内容をgh-pagesブランチにpushしたい場合に,ローカルブランチのpush先を指定する場合に使用する。
こちらのスライド (5分で分かるgitのrefspec) も参考になった。
結論
Gitでデフォルトで用意されている参照に付いて整理した。
なんだかんだでGitの存在を知って使い始めてから数年は経つ。しかし,このデフォルトの参照の意味が理解できておらず,なんだかとっつきにくいものだと抵抗を感じていた。
Gitの公式文書を読み込んで意味が理解でき,すっきりした。時間はかかったが整理してよかった。


“Gitのデフォルト参照 (refs)” に対して1件のコメントがあります。