章 ▾ 第2版

3.5 Gitブランチ - リモートブランチ

リモートブランチ

リモートリファレンスとは、リモートリポジトリ内のブランチやタグなどを含む参照(ポインタ)のことです。git ls-remote <remote>コマンドを使用するか、git remote show <remote>コマンドでリモートブランチに関する詳細情報を明示的に取得することで、リモートリファレンスの完全なリストを取得できます。しかし、より一般的な方法は、リモートトラッキングブランチを利用することです。

リモートトラッキングブランチは、リモートブランチの状態への参照です。これらは、あなたが動かすことのできないローカルな参照であり、Gitがネットワーク通信を行うたびに、リモートリポジトリの状態を正確に反映するように自動的に移動させます。リモートリポジトリのブランチが最後に接続したときにどこにあったかを思い出させるブックマークだと考えてください。

リモートトラッキングブランチの名前は<remote>/<branch>の形式を取ります。例えば、最後に通信した時点でのoriginリモート上のmasterブランチがどのような状態だったかを確認したい場合は、origin/masterブランチをチェックします。パートナーとある課題に取り組んでいて、彼らがiss53ブランチをプッシュした場合、あなたは自分自身のローカルなiss53ブランチを持っているかもしれませんが、サーバー上のブランチはリモートトラッキングブランチのorigin/iss53によって表されます。

これは少し分かりにくいかもしれませんので、例を見てみましょう。あなたのネットワーク上にgit.ourcompany.comというGitサーバーがあるとします。ここからクローンすると、Gitのcloneコマンドは自動的にそれをoriginと名付け、すべてのデータをダウンロードし、そのmasterブランチがある場所へのポインタを作成し、ローカルでorigin/masterと名付けます。また、Gitはoriginmasterブランチと同じ場所から始まるあなた自身のローカルなmasterブランチを作成するので、そこから作業を開始できます。

注記
「origin」は特別ではない

ブランチ名「master」がGitにおいて特別な意味を持たないのと同様に、「origin」も特別な意味を持ちません。「master」がgit initを実行したときのデフォルトの開始ブランチ名であり、それが広く使われている唯一の理由であるのに対し、「origin」はgit cloneを実行したときのリモートのデフォルト名です。もし代わりにgit clone -o booyahを実行した場合、あなたのデフォルトのリモートブランチはbooyah/masterになります。

Server and local repositories after cloning
図30. クローン後のサーバーとローカルのリポジトリ

ローカルのmasterブランチで作業をしている間に、他の誰かがgit.ourcompany.comにプッシュしてそのmasterブランチを更新した場合、あなたの履歴は異なる形で進んでいきます。また、originサーバーとの連絡を取らない限り、あなたのorigin/masterポインタは移動しません。

Local and remote work can diverge
図31. ローカルとリモートの作業は分岐する可能性がある

特定のリモートと作業を同期するには、git fetch <remote>コマンド(この場合はgit fetch origin)を実行します。このコマンドは、「origin」がどのサーバーであるか(この場合はgit.ourcompany.com)を調べ、まだ持っていないデータをすべてフェッチし、ローカルデータベースを更新して、origin/masterポインタを新しい、より最新の位置に移動させます。

`git fetch` updates your remote-tracking branches
図32. git fetchはリモートトラッキングブランチを更新する

複数のリモートサーバーがある場合や、それらのリモートプロジェクトのリモートブランチがどのように見えるかを示すために、スプリントチームの1つが開発専用に使用する別の社内Gitサーバーがあると仮定しましょう。このサーバーはgit.team1.ourcompany.comにあります。Gitの基本で説明したように、git remote addコマンドを実行して、現在作業しているプロジェクトに新しいリモート参照として追加できます。このリモートをteamoneと名付けます。これがそのURL全体のショートネームになります。

Adding another server as a remote
図33. 別のサーバーをリモートとして追加する

これで、git fetch teamoneを実行して、リモートのteamoneサーバーが持っているまだあなたが持っていないものをすべてフェッチできます。このサーバーは現在、あなたのoriginサーバーが持っているデータの一部しか持っていないため、Gitはデータをフェッチしませんが、teamone/masterというリモートトラッキングブランチを設定し、teamonemasterブランチとして持っているコミットを指すようにします。

Remote-tracking branch for `teamone/master`
図34. 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は自動的にserverfixブランチ名をrefs/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ブランチにプッシュできます。

注記
毎回パスワードを入力しない

HTTPS URLを使用してプッシュする場合、Gitサーバーは認証のためにユーザー名とパスワードを求めます。デフォルトでは、この情報はターミナルでプロンプトとして表示され、サーバーがプッシュを許可するかどうかを判断できるようになります。

プッシュするたびにパスワードを入力したくない場合は、「クレデンシャルキャッシュ」を設定できます。最も簡単な方法は、数分間メモリに保持することであり、これはgit config --global credential.helper cacheを実行することで簡単に設定できます。

利用可能なさまざまなクレデンシャルキャッシュオプションの詳細については、認証情報の保存を参照してください。

次に共同作業者の誰かがサーバーからフェッチすると、リモートブランチorigin/serverfixの下に、サーバーの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はどのサーバーからフェッチし、どのブランチをマージするかを自動的に認識します。

リポジトリをクローンすると、通常は自動的にorigin/masterを追跡するmasterブランチが作成されます。しかし、必要であれば他のトラッキングブランチを設定することもできます。他のリモートのブランチを追跡するものや、masterブランチを追跡しないものなどです。簡単なケースは、先ほど見たgit checkout -b <branch> <remote>/<branch>を実行する例です。これは非常に一般的な操作なので、Gitは--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)唯一のリモート上の名前と完全に一致する場合、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.
注記
アップストリームの短縮形

トラッキングブランチを設定している場合、@{upstream}または@{u}という短縮形を使用してそのアップストリームブランチを参照できます。したがって、masterブランチにいて、それがorigin/masterを追跡している場合、必要に応じてgit merge origin/masterの代わりにgit merge @{u}のように記述できます。

設定されているトラッキングブランチを確認したい場合は、git branch-vvオプションを使用します。これにより、各ブランチが何を追跡しているか、ローカルブランチが先行しているか、遅れているか、またはその両方かを含む詳細情報とともに、ローカルブランチが一覧表示されます。

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] Add forgotten brackets
  master    1ae2a45 [origin/master] Deploy index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] This should do it
  testing   5ea463a Try something new

したがって、ここでiss53ブランチがorigin/iss53を追跡しており、2つのコミットが「ahead」(先行)していることがわかります。これは、まだサーバーにプッシュされていないコミットがローカルに2つあることを意味します。また、masterブランチがorigin/masterを追跡しており、最新の状態であることがわかります。次に、serverfixブランチがteamoneサーバーのserver-fix-goodブランチを追跡しており、3つ「ahead」で1つ「behind」(遅延)していることがわかります。これは、まだマージされていないサーバー上のコミットが1つあり、まだプッシュされていないローカルコミットが3つあることを意味します。最後に、testingブランチがどのリモートブランチも追跡していないことがわかります。

これらの数値は、各サーバーから最後にフェッチしてからのものである点に注意することが重要です。このコマンドはサーバーにアクセスするわけではなく、これらのサーバーからローカルにキャッシュされている情報について教えてくれます。完全に最新の先行・遅延の数値を知りたい場合は、このコマンドを実行する直前にすべてのリモートからフェッチする必要があります。それは次のように実行できます。

$ git fetch --all; git branch -vv

プル

git fetchコマンドは、まだ持っていないサーバー上のすべての変更をフェッチしますが、作業ディレクトリを一切変更しません。単にデータを取得し、自分でマージできるようにするだけです。しかし、git pullというコマンドがあり、これはほとんどの場合、git fetchの直後にgit mergeが続くものです。前のセクションで示したように、明示的に設定したか、cloneまたはcheckoutコマンドによって作成されたトラッキングブランチがある場合、git pullは現在のブランチが追跡しているサーバーとブランチを調べ、そのサーバーからフェッチし、そのリモートブランチをマージしようとします。

リモートブランチの削除

リモートブランチの作業が完了したとします。つまり、あなたと共同作業者が機能の作業を終え、それをリモートのmasterブランチ(または安定したコードラインがある任意のブランチ)にマージしたとします。リモートブランチは、git push--deleteオプションを使用して削除できます。サーバーからserverfixブランチを削除したい場合は、以下を実行します。

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

基本的には、サーバーからポインタを削除するだけです。Gitサーバーは通常、ガベージコレクションが実行されるまでデータをしばらく保持するため、誤って削除された場合でも、多くの場合簡単に回復できます。

scroll-to-top