Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【git】git pullのデフォルト動作を追う

git pull

~git pull`リモートリポジトリ上ブランチの状態をローカルブランチに反映させる際、
自分はよく明示的にpullしたいブランチ名を指定しています。

例えばmasterブランチをpullするときは

$ git push origin master

のようにしています。

これはリモートのmasterブランチの状態をローカルブランチに反映させるコマンド
(厳密にはリモートのmasterブランチをfetch+ローカルブランチにmergeしている)ですが
このコマンド、実際には

# git push <ローカルのブランチ名>:<リモートのブランチ名>
$ git push origin master:master

の省略形になります。 ローカルブランチmasterの名称が省略され、リモートブランチorigin masterにマッチする ブランチを探してpullしていたようです。

同様に、引数を指定しないgit pullでも、リモートブランチにマッチする ローカルブランチに変更が反映されます。

# 3つのブランチがある状態
$ git branch
  branch1
  branch2
* master

# masterブランチにだけリモートとローカルで紐付いたブランチがある
$ git pull
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 9 (delta 2), reused 8 (delta 1), pack-reused 0
Unpacking objects: 100% (9/9), done.
From https://github.com/hogehoge/Hoge
   f9db208..5bf5762  master     -> origin/master
 * [new branch]      branch1    -> origin/branch1
 * [new branch]      branch2    -> origin/branch2
Updating f9db208..5bf5762
Fast-forward
 hoge1.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 hoge1.txt

このリモートブランチとローカルブランチは、どのような規則で紐付いているのでしょうか。

リモートブランチとローカルブランチの紐付け

上記の紐付けは、git branch -vvで確認することができます。

$ git branch -vv
  branch1 f9db208 Initial commit
  branch2 f9db208 Initial commit
* master  5bf5762 [origin/master] add hoge1.txt .

上の例では、リモートのmasterブランチがローカルのorigin/masterブランチに紐付いていることを示しています。
あるローカルブランチ上で引数なしgit pullを行った時、fetch&mergeされるのはここに記述されたリモートブランチになるということがわかりました。

一方で、branch1branch2には紐付いているローカルブランチはなく、例えばbranch2上でgit pullすると怒られてしまいます。

# 激おこ
$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> branch2

警告を読んでいくと、どうやらgit branch --set-upstream-to=origin/<branch> branch2branch2に紐づくリモートブランチを設定できるようです。

やってみます。

# ローカルのorigin/branch2をリモートのbranch2に紐付け
$ git branch --set-upstream-to=origin/branch2 branch2 
Branch branch2 set up to track remote branch branch2 from origin.

# git branch -vv の結果が更新されている
$ git branch -vv
  branch1 f9db208 Initial commit
* branch2 cc369d6 [origin/branch2] add hoge3.txt .
  master  5bf5762 [origin/master] add hoge1.txt .

# できた!
$ git pull
Updating f9db208..cc369d6
Fast-forward
 hoge1.txt | 1 +
 hoge2.txt | 1 +
 hoge3.txt | 1 +
 3 files changed, 3 insertions(+)
 create mode 100644 hoge1.txt
 create mode 100644 hoge2.txt
 create mode 100644 hoge3.txt

無事pullできました。

因みに、紐付けられたブランチの組のうち

  • リモートブランチをアップストリームとよび、
  • ローカルブランチをラッキングブランチと呼ぶ

そうです。
先程の--set-upstream-toは、アップストリームに対応するトラッキングブランチを設定するということだったんですね。

デフォルトの--set-upstream-to

先程はorigin/branch2のアップストリームを設定しましたが、普段から引数なしのgit pullを使っている皆さんであれば「あれ?設定した記憶がない。。。」と思うかもしれません。
調べてみたところ、以下のパターンに関してはデフォルトのアップストリームが設定済みの状態になっているそうです。

  • git cloneしたとき
  • リモートのブランチから新しくブランチを作成した場合

このため、普段からリポジトリcloneしている人はあまり気にせずに引数なしでgit pullできるのかもしれません。