せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Git】fetchコマンドは引数にトピックブランチを取らない

ずいぶん嵌ったので、備忘録をかねて。
 
fetchコマンドは引数にトピックブランチを取らない!
 

用語の整理

まずは用語の整理から。

トピックブランチ (ローカルにある通常のブランチ)
追跡ブランチ(ローカルにある追跡ブランチ)
リモートブランチ(リモートリポジトリにあるブランチ)

http://d.hatena.ne.jp/hokaccha/20120404/1333507076

現象の整理

リモートブランチのコピーではなく、
以下のようにトピックブランチを作成した場合

git checkout -b hoge

ブランチの状態はこうなる↓

$ git branch -a
* hoge
  master
  sign-in-out
  remotes/heroku/master
  remotes/origin/master

このとき、以下のfetch文はエラーになる。

$ git fetch origin refs/heads/hoge:refs/remotes/origin/master
fatal: Couldn't find remote ref refs/heads/hoge
Unexpected end of command stream

理由:
fetch文の用法は以下の通り

git fetch [<options>] [<repository> [[+]<source>:<destinations>..]]


さきほどのコマンドはsource にrefs/heads/hoge を指定しているが、
source はリモートブランチを指定しないといけない。

さっきのエラーは「リモートにhogeブランチがありませんよ」
という意味。


fetchというのは結局、リモートの状態に
「追跡ブランチ」を追いかけさせるだけなので、
トピックブランチを引数に取ったりすることはない。


リモートもローカルも表記方法が同じだからややこしい!
「refs/heads/*」はこの場合において、ローカルを指すわけではない><

<source>の refs/heads/* はローカルリポジトリの refs/heads/* じゃなくてリモートリポジトリのブランチの指定になってるということ(リモートもローカルと同じようなrefsの構成になっているので表記が同じになる)。

http://d.hatena.ne.jp/hokaccha/20120404/1333507076


 
結局、ローカルブランチ上で作成したトピックブランチは、
追跡情報も同時にコピーされるみたい。
なので、hogeブランチに切り替えたときに
元のローカルブランチの追跡ブランチ(origin/master)との差分を見て
pullコマンドをお勧めしてくれる。

$ git checkout hoge
Switched to branch 'hoge'
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)


うー。
でも追跡ブランチの意味が分かったぞ。