Git --fast-version-control
Chapters ▾

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

リモートブランチ

リモートブランチは、リモートリポジトリ上のブランチの状態を指すものです。ネットワーク越しの操作をしたときに自動的に移動します。リモートブランチは、前回リモートリポジトリに接続したときにブランチがどの場所を指していたかを示すブックマークのようなものです。

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

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


図 3-22. git clone により、ローカルの master ブランチのほかに origin の master ブランチを指す origin/master が作られる

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


図 3-23. ローカルで作業している間に誰かがリモートサーバーにプッシュすると、両者の歴史が異なるものとなる

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


図 3-24. git fetch コマンドによるリモートへの参照の更新

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


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

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


図 3-26. teamone の master ブランチの位置をローカルに取得する

プッシュ

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

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

$ git push origin serverfix
Counting objects: 20, done.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (15/15), 1.74 KiB, done.
Total 15 (delta 5), reused 0 (delta 0)
To git@github.com:schacon/simplegit.git
 * [new branch]      serverfix -> serverfix

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

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

$ git fetch origin
remote: Counting objects: 20, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 15 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (15/15), done.
From git@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 が指す先から作業を開始するためのローカルブランチができあがりました。

追跡ブランチ

リモートブランチからローカルブランチにチェックアウトすると、追跡ブランチ (tracking branch) というブランチが自動的に作成されます。追跡ブランチとは、リモートブランチと直接のつながりを持つローカルブランチのことです。追跡ブランチ上で git push を実行すると、Git は自動的にプッシュ先のサーバーとブランチを判断します。また、追跡ブランチ上で git pull を実行すると、リモートの参照先からすべてのデータを取得し、対応するリモートブランチの内容を自動的にマージします。

あるリポジトリをクローンしたら、自動的に master ブランチを作成し、origin/master を追跡するようになります。これが、git pushgit pull が引数なしでもうまく動作する理由です。しかし、必要に応じてそれ以外の追跡ブランチを作成し、origin 以外にあるブランチや master 以外のブランチを追跡させることも可能です。シンプルな方法としては、git checkout -b [branch] [remotename]/[branch] を実行します。Git バージョン 1.6.2 以降では、より簡単に --track を使うことができます。

$ git checkout --track origin/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 を追跡するようになりました。

リモートブランチの削除

リモートブランチでの作業が終わったとしましょう。つまり、あなたや他のメンバーが一通りの作業を終え、それをリモートの master ブランチ (あるいは安定版のコードラインとなるその他のブランチ) にマージし終えたということです。リモートブランチを削除するコマンドは、少しわかりにくい構文ですが git push [remotename] :[branch] となります。サーバーの serverfix ブランチを削除したい場合は次のようになります。

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

ドッカーン。これでブランチはサーバーから消えてしまいました。このページの端を折っておいたほうがいいかもしれませんね。実際にこのコマンドが必要になったときには、おそらくこの構文を忘れてしまっているでしょうから。このコマンドを覚えるコツは、少し前に説明した構文 git push [remotename] [localbranch]:[remotebranch] を思い出すことです。[localbranch] の部分をそのまま残して考えると、これは基本的に「こっちの (何もなし) で、向こうの [remotebranch] を更新しろ」と言っていることになります。