Git --fast-version-control
Chapters ▾ 2nd Edition

3.5 Git のブランチ機能 - リモートブランチ

リモートブランチ

リモート参照は、リモートリポジトリにある参照(ポインタ)です。具体的には、ブランチやタグなどを指します。 リモート参照をすべて取得するには、git ls-remote [remote] を実行してみてください。また、git remote show [remote] を実行すれば、リモート参照に加えてその他の情報も取得できます。 とはいえ、リモート参照の用途としてよく知られているのは、やはりリモート追跡ブランチを活用することでしょう。

リモート追跡ブランチは、リモートブランチの状態を保持する参照です。 ローカルに作成される参照ですが、自分で移動することはできません。ネットワーク越しの操作をしたときに自動的に移動します。 リモート追跡ブランチは、前回リモートリポジトリに接続したときにブランチがどの場所を指していたかを示すブックマークのようなものです。

ブランチ名は (remote)/(branch) のようになります。 たとえば、origin サーバーに最後に接続したときの master ブランチの状態を知りたければ origin/master ブランチをチェックします。 誰かほかの人と共同で問題に対応しており、相手が iss53 ブランチにプッシュしたとしましょう。 あなたの手元にはローカルの iss53 ブランチがあります。しかし、サーバー側のブランチは origin/iss53 のコミットを指しています。

……ちょっと混乱してきましたか? では、具体例で考えてみましょう。 ネットワーク上の git.ourcompany.com に Git サーバーがあるとします。 これをクローンすると、Git の clone コマンドがそれに origin という名前をつけ、すべてのデータを引き出し、master ブランチを指すポインタを作成し、そのポインタにローカルで origin/master という名前をつけます。 Git はまた、ローカルに master というブランチも作成します。これは origin の master ブランチと同じ場所を指しており、ここから何らかの作業を始めます。

Note

“origin” は特別なものではない

Git の “master” ブランチがその他のブランチと何ら変わらないものであるのと同様に、 “origin” もその他のサーバーと何ら変わりはありません。 “master” ブランチがよく使われている理由は、ただ単に git init がデフォルトで作るブランチ名がそうだからというだけのことでした。 同様に “origin” も、git clone を実行するときのデフォルトのリモート名です。 たとえば git clone -o booyah などと実行すると、デフォルトのリモートブランチは booyah/master になります。

クローン後のサーバーとローカルのリポジトリ
Figure 3-22. クローン後のサーバーとローカルのリポジトリ

ローカルの master ブランチで何らかの作業をしている間に、誰かが git.ourcompany.com にプッシュして master ブランチを更新したとしましょう。 この時点であなたの歴史とは異なる状態になってしまいます。 また、origin サーバーと再度接続しない限り、origin/master が指す先は移動しません。

ローカルとリモートの作業が枝分かれすることがある
Figure 3-23. ローカルとリモートの作業が枝分かれすることがある

手元での作業を同期させるには、git fetch origin コマンドを実行します。 このコマンドは、まず “origin” が指すサーバー (今回の場合は git.ourcompany.com) を探し、まだ手元にないデータをすべて取得し、ローカルデータベースを更新し、origin/master が指す先を最新の位置に変更します。

`git fetch` によるリモートへの参照の更新
Figure 3-24. git fetch によるリモートへの参照の更新

複数のリモートサーバーがあった場合にリモートのブランチがどのようになるのかを知るために、もうひとつ Git サーバーがあるものと仮定しましょう。 こちらのサーバーは、チームの一部のメンバーが開発目的にのみ使用しています。 このサーバーは git.team1.ourcompany.com にあるものとしましょう。 このサーバーをあなたの作業中のプロジェクトから参照できるようにするには、Git の基本 で紹介した git remote add コマンドを使用します。 このリモートに teamone という名前をつけ、URL ではなく短い名前で参照できるようにします。

別のサーバーをリモートとして追加
Figure 3-25. 別のサーバーをリモートとして追加

git fetch teamone を実行すれば、まだ手元にないデータをリモートの teamone サーバーからすべて取得できるようになりました。 今回、このサーバーが保持してるデータは origin サーバーが保持するデータの一部なので、Gitは何のデータも取得しません。 代わりに、 teamone/master というリモート追跡ブランチが指すコミットを、teamone サーバーの master ブランチが指すコミットと同じにします。

リモート `teamone/master` を追跡するブランチ
Figure 3-26. リモート teamone/master を追跡するブランチ

プッシュ

ブランチの内容をみんなと共有したくなったら、書き込み権限を持つどこかのリモートにそれをプッシュしなければなりません。 ローカルブランチの内容が自動的にリモートと同期されることはありません。 共有したいブランチは、明示的にプッシュする必要があります。 たとえば、共有したくない内容はプライベートなブランチで作業を進め、共有したい内容だけのトピックブランチを作成してそれをプッシュするということもできます。

手元にある serverfix というブランチを他人と共有したい場合は、最初のブランチをプッシュしたときと同様の方法でそれをプッシュします。 つまり git push <remote> <branch> を実行します。

$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
 * [new branch]      serverfix -> serverfix

これは、ちょっとしたショートカットです。 Git はまずブランチ名 serverfixrefs/heads/serverfix:refs/heads/serverfix に展開します。 これは「手元のローカルブランチ serverfix をプッシュして、リモートの serverfix ブランチを更新しろ」という意味です。 refs/heads/ の部分の意味については Gitの内側 で詳しく説明しますが、これは一般的に省略可能です。 git push origin serverfix:serverfix とすることもできます。 これも同じことで、「こっちの serverfix で、リモートの serverfix を更新しろ」という意味になります。 この方式を使えば、ローカルブランチの内容をリモートにある別の名前のブランチにプッシュすることができます。 リモートのブランチ名を serverfix という名前にしたくない場合は、git push origin serverfix:awesomebranch とすればローカルの serverfix ブランチをリモートの awesomebranch という名前のブランチ名でプッシュすることができます。

Note

パスワードを毎回入力したくない

HTTPS URL を使ってプッシュするときに、Git サーバーから、認証用のユーザー名とパスワードを聞かれます。 デフォルトでは、ターミナルからこれらの情報を入力させるようになっており、この情報を使って、プッシュする権限があなたにあるのかを確認します。

プッシュするたびに毎回ユーザー名とパスワードを打ち込みたくない場合は、「認証情報キャッシュ」を使うこともできます。 一番シンプルな方法は、数分間だけメモリに記憶させる方法です。この方法を使いたければ、git config --global credential.helper cache を実行しましょう。

それ以外に使える認証情報キャッシュの方式については、認証情報の保存 を参照ください。

次に誰かがサーバーからフェッチしたときには、その人が取得するサーバー上の serverfix はリモートブランチ origin/serverfix となります。

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
 * [new branch]      serverfix    -> origin/serverfix

注意すべき点は、新しいリモート追跡ブランチを取得したとしても、それが自動的にローカルで編集可能になるわけではないというところです。 言い換えると、この場合に新たに serverfix ブランチができるわけではないということです。 できあがるのは origin/serverfix ポインタだけであり、これは変更することができません。

この作業を現在の作業ブランチにマージするには、git merge origin/serverfix を実行します。 ローカル環境に serverfix ブランチを作ってそこで作業を進めたい場合は、リモート追跡ブランチからそれを作成します。

$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

これで、origin/serverfix が指す先から作業を開始するためのローカルブランチができあがりました。

追跡ブランチ

リモート追跡ブランチからローカルブランチにチェックアウトすると、“追跡ブランチ” というブランチが自動的に作成されます(そしてそれが追跡するブランチを“上流ブランチ”といいます)。 追跡ブランチとは、リモートブランチと直接のつながりを持つローカルブランチのことです。 追跡ブランチ上で git pull を実行すると、Git は自動的に取得元のサーバーとブランチを判断します。

あるリポジトリをクローンしたら、自動的に master ブランチを作成し、origin/master を追跡するようになります。 しかし、必要に応じてそれ以外の追跡ブランチを作成し、origin 以外にあるブランチや master 以外のブランチを追跡させることも可能です。 シンプルな方法としては、git checkout -b [branch] [remotename]/[branch] を実行します。 これはよく使う操作なので、--track という短縮形も用意されています。

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

この短縮形、あまりにもよく使うので、更なる短縮形も用意されています。チェックアウトしたいブランチ名が(a)まだローカルに存在せず、(b)存在するリモートは1つだけ、の場合、Gitは自動的に追跡ブランチを作ってくれるのです。

$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

ローカルブランチをリモートブランチと違う名前にしたい場合は、最初に紹介した方法でローカルブランチに別の名前を指定します。

$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'

これで、ローカルブランチ sf が自動的に origin/serverfix を追跡するようになりました。

既に手元にあるローカルブランチを、リモートブランチの取り込み先に設定したい場合や、 追跡する上流のブランチを変更したい場合は、 git branch のオプション -u あるいは --set-upstream-to を使って明示的に設定することもできます。

$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Note

上流の短縮記法

追跡ブランチを設定すると、その上流のブランチを参照するときに @{upstream}@{u} という短縮記法が使えるようになります。 つまり、仮に今 master ブランチにいて、そのブランチが origin/master を追跡している場合は、 git merge origin/master の代わりに git merge @{u} としてもかまわないということです。

どのブランチを追跡しているのかを知りたい場合は、git branch のオプション -vv が使えます。 これは、ローカルブランチの一覧に加えて、各ブランチが追跡するリモートブランチや、リモートとの差異を表示します。

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] forgot the brackets
  master    1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
  testing   5ea463a trying something new

ここでは、手元の iss53 ブランチが origin/iss53 を追跡していることと、リモートより二つぶん「先行している (ahead)」ことがわかります。 つまり、まだサーバーにプッシュしていないコミットが二つあるということです。 また、master ブランチは origin/master を追跡しており、最新の状態であることもわかります。 同じく、serverfix ブランチは teamone サーバー上の server-fix-good ブランチを追跡しており、三つ先行していると同時に一つ遅れていることがわかります。 つまり、まだローカルにマージしていないコミットがサーバー上に一つあって、まだサーバーにプッシュしていないコミットがローカルに三つあるということです。 そして、testing ブランチは、リモートブランチを追跡していないこともわかります。

これらの数字は、各サーバーから最後にフェッチした時点以降のものであることに注意しましょう。 このコマンドを実行したときに各サーバーに照会しているわけではなく、各サーバーから取得したローカルのキャッシュの状態を見ているだけです。 最新の状態と比べた先行や遅れの数を知りたい場合は、すべてのリモートをフェッチしてからこのコマンドを実行しなければいけません。 たとえば、git fetch --all; git branch -vv のようになります。

プル

git fetch コマンドは、サーバー上の変更のうち、まだ取得していないものをすべて取り込みます。 しかし、ローカルの作業ディレクトリは書き換えません。 データを取得するだけで、その後のマージは自分でしなければいけません。 git pull コマンドは基本的に、git fetch の実行直後に git merge を実行するのと同じ動きになります。 先ほどのセクションのとおりに追跡ブランチを設定した場合、git pull は、 現在のブランチが追跡しているサーバーとブランチを調べ、そのサーバーからフェッチしたうえで、リモートブランチのマージを試みます。

一般的には、シンプルに fetchmerge を明示したほうがよいでしょう。 git pull は、時に予期せぬ動きをすることがあります。

リモートブランチの削除

リモートブランチでの作業が終わったとしましょう。 つまり、あなたや他のメンバーが一通りの作業を終え、それをリモートの master ブランチ (あるいは安定版のコードラインとなるその他のブランチ) にマージし終えたということです。 リモートブランチを削除するには、git push--delete オプションを使います。 サーバーの serverfix ブランチを削除したい場合は次のようになります。

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

基本的に、このコマンドが行うのは、サーバーからポインタを削除することだけです。 Git サーバー上でガベージコレクションが行われるまではデータが残っているので、仮に間違って削除してしまったとしても、たいていの場合は簡単に復元できます。