Gitのデフォルト参照 (refs)
概要
GitのオブジェクトやコミットはSHA-1ハッシュ値で管理されている。ただ,毎回SHA-1ハッシュ値を直接指定するのは手間なので,SHA-1ハッシュ値を指す参照 (refs) が用意されている。
Gitではデフォルトで用意されている参照がいくつもある。今までよくわからない状態で使っていたが,最近ようやく理解できたでの,忘れたときのために整理する。
HEAD
HEAD
は最後 (現在) のコミットのSHA-1ハッシュを指す参照 (refs) を保持するシンボリック参照となっている (参考: Git – Gitの参照)。通常の参照と区別するために,シンボリック参照と呼んでいる。
具体的には,.git/HEAD
に値が格納されている。
cat .git/HEAD
ref: refs/heads/master
通常は上記のように,ブランチへの参照が格納されている。ただし,git checkout
で直接コミットに移動した場合,参照ではなくSHA-1ハッシュ値が格納されている。
git checkout HEAD~1
cat .git/HEAD
d7f38fea38edc7e65388e7c90b125c1fe4f801d9
HEAD
を参照することで,最後のコミット (現在のコミット) を把握することができる。
日々のコマンドでよく使うシンボリック参照だ。
FETCH_HEAD
git fetch
またはgit pull
した際にダウンロードしたリモートリポジトリーのブランチごとのSHA-1ハッシュ値を格納している (参考: Git – git-fetch Documentation)。
cat .git/FETCH_HEAD
27ce7d102010ba6d9232027b5b7afac1db1316e8 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/HEAD
ref: refs/heads/master
Git 2.28から設定やオプションでデフォルトのブランチ名を変更可能になっている。
Gitでブランチを切り変えて作業する場合に,必ず参照されるので,よく見かける参照だ。
origin
origin
はデフォルトのリモートリポジトリー名となっている。「Git – リモートでの作業」や「Git – git-clone Documentation」でそのことが説明されている。
より具体的には,git clone
したリモートリポジトリー名のデフォルトがorigin
となっている。以下のコマンドで,現在のorigin
を確認できる。
git remote -v
origin 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件のコメントがあります。