Git でリモートレポジトリとの送受信を理解する上で、「git fetch」の動作仕様を理解することは肝要です。今回、git fetch の具体的な動きをできるだけ分かりやすくまとめました。また、よく使うオプションを紹介します。
git fetch コマンドの概要
リモートブランチの履歴を取得するコマンド「git fetch」
Fetch(取ってくる)の語感からも分かるように、git fetch は、リモートレポジトリから、ブランチ(とタグ)の情報をローカルレポジトリに取得するための Git コマンドです。
例えば、下記はリモートレポジトリ「origin」から、ブランチ「master」のすべてのコミット履歴と、参照(=ブランチ・タグ)を取得するコマンドです。取得した履歴に関連するタグがあれば、同時に取得します。
// origin から master ブランチに関する履歴と参照を取得する
git fetch origin master
Fetchしたリモートブランチ履歴は、「リモート追跡ブランチ」として保存される
git fetch を使って、リモートからブランチとそのコミット履歴を取得する時、リモート側に存在するブランチは「リモート追跡ブランチ」と呼ばれるという特別な種類のブランチとしてローカルに反映されます。
リモート追跡ブランチは、リモート追跡ブランチは、下記のいずれの方法でも参照できますが、最もシンプルな「<リモート名>/<ブランチ名>」という名前を使うことが多いと思います。
// リモート「master」をFetchすれば、該当のリモート追跡ブランチは、下記のいずれかで参照できる
origin/master
remotes/origin/master
refs/remotes/origin/master
なお、実際にレポジトリのディレクトリには「.git/refs/remotes/origin/master」というファイルが見つかりますので、そこに、このブランチの先頭が指し示すコミット識別子が記載されています。
git fetch でブランチ名の引数を省略した場合
ブランチ名を省略すれば、Git デフォルトでは、指定したリモートにあるすべてのブランチを取得します。
// origin にあるのすべてのブランチを取得する
git fetch origin
実際の動作は、.git/config の設定値によるのですが、通常「git remote add <レポジトリ> <URL>」などの実行により、リモートが設定されれば、自動的にconfig に下記の値が書き込まれます。下記は、origin の設定値の例です。多くの場合は、下記と同様の設定値が見つかるはずです。
// 実行
git remote add origin ssh://git@github.com/user-name/repo-name.git
// 作成される.git/config の、リモートに関する設定値
[remote "origin"]
url = ssh://git@github.com/user-name/repo-name.git
fetch = +refs/heads/*:refs/remotes/origin/*
ここに見つかる「fetch」の値は、Git において「refspec(参照仕様)」と呼ばれるフォーマットです。
ここでは、git fetch をブランチ引数なしで、実行した際に利用される設定値で、「リモート側の参照 : ローカルの参照」という、「取得元 → 反映先」という関係性を表しています。冒頭の「+」は、強制的に参照を移動する(--force )を意味します。また、ワイルドカード「*」はすなわち、すべてのリモートブランチを取得することを意味します。
上記の設定値をみれば、「git fetch origin をブランチ引数無しで実行すれば、すべてのリモートブランチに対応するリモート追跡ブランチが強制更新される」ということがわかります。
なお、この参照値はコマンド「git config remote.origin.fetch」で確認できます。
git fetch でブランチ名・レポジトリの引数をどちらも省略した場合
レポジトリ名を省略した実行も可能です。
// 引数なしで git fetch を実行
$ git fetch
このとき自動的に、現在のブランチの上流ブランチから、fetch を行います。
具体的には .git/config に現在のブランチの設定値「branch.<branch _name>.remote」が対応するリモート、「branch.<branch_name>.merge」がそれぞれ、上流レポジトリ、上流ブランチを設定する設定値です。
// .git/config の、ローカルブランチに関する設定値
[branch "master"]
remote = origin
merge = refs/head/origin/master
上流ブランチが設定されていなければ、自動的に、origin にフォールバックします。上流ブランチについては、こちらに詳しく記載しました。ご一読下さい。
もし上流ブランチがまだ設定されていなければ、自動的に「origin」をレポジトリとして fetch が実行されます。
git fetch した履歴を、別名のブランチへ反映することも可能
どのくらい利用するケースがあるかわかりませんが、「:(コロン)」を利用して、リモートとローカルブランチをそれぞれ指定することができます。
// リモートの master を、ローカルの origin/master-tmp に反映する
git fetch origin master:master-tmp
git fetch コマンドの主なオプション
すべてのリモートから fetch する「--all」
設定された、すべてのリモートからすべての履歴を取得します。
ローカルに存在しないブランチを削除する「-p, --prune」
リモートに存在するが、ローカルに存在しないブランチをすべて削除します。
リモートにあるすべてのタグを取得します。
【参考】git fetch と git pull の違い?
「git fetch」は、しばしば「git pull」と混同されます。いずれも何かをリモートから何かを取得する語感があるせいかもしれません。git pull は、リモートから取得したブランチを、任意のローカルブランチにマージするコマンドです。Git は内部的に、下記のコマンドを実行します。
「git pull origin master」により、Git が内部的に実行するコマンド
// 1 ) 任意のブランチ履歴を取得する
git fetch origin master
// 2) 取得したブランチを、対応するブランチにマージ
git merge FETCH_HEAD
git fetch より取得したブランチは、すべて一度 .git/FETCH_HEAD というファイル内に書き込まれます。その直後に実行される「git merge FETCH_HEAD」により、現在の作業ブランチに対して、マージが実行される、というステップです。
git pull のより詳しい仕様は、こちらも記事をぜひご一読下さい。
git fetch に関する参考情報
git fetch は git pull と関連が深いコマンドです。以下、関連記事です。
Git ドキュメントです。