Git の代表的なコマンドである「git pull」の基本的な動作仕様と、オプションの具体的な使用例についてまとめます。
git pull は、通常は「リモートレポジトリでの更新の取り込み」の目的で利用します。しっかりと動作仕様を理解して深いレベルで使いこなしましょう。
目次
git pull の概要
git pull コマンドは、リモートレポジトリの更新内容をローカルに取得し、現在のブランチに取り込むためのコマンドです。
実際には、git pull は git fetch と git merge を連続で実行するショートハンドとして動作します。具体的には、「git fetch」を与えられた引数やオプションで実行した後、そのまま取得したブランチ履歴(= FETCH_HEAD で参照できる)を、現在のブランチにマージする、という動作です。
git pull の動作仕様
git pull の動作について、もう少し詳しく見てみましょう。下記のステップで進みます。
[Step 1] git fetch <repository> <branch>
[Step 2] git merge FETCH_HEAD
Step 1git fetch:指定したリモートブランチの状態を、リモート追跡ブランチに反映する
まず、git fetch の機能は「リモートブランチの履歴を取り込む」です。このとき更新されるのは、あくまで指定したリモートブランチに対応する「リモート追跡ブランチ」です。(git fetch はローカルブランチ、インデックスや作業ツリーに一切の変更を加えません。)
下記は「git fetch origin master」を実行した際のイメージ図ですが、ローカルの master ブランチは影響されず「origin/master」という名前の追跡ブランチのみが更新されています。
また、これと同時に fetch されたコミットオブジェクトへの参照が FETCH_HEAD に書き込まれます。
Step 2git merge FETCH_HEAD: 更新されたリモート追跡ブランチを、現在のブランチにマージする
git pull コマンドの動作において、git fetch の後に実行される「git merge FETCH_HEAD」により、直前に fetch されたリモート追跡ブランチのうち、現在チェックアウトしているブランチの上流ブランチとなるリモートブランチの更新履歴があれば、マージを試みます。
下記は「git merge FETCH_HEAD」の実行イメージです。
origin/master が master よりも(直線的に)進んでいるケースでは、マージ実行時、master は origin/master に「Fast Forward (早送り)マージ」されます。
Fast Forwardマージでは、新しいコミットは作られず、参照のみが移動するのでした。
git merge の動作については、こちらにも詳しくまとめています。
コンフリクトによる git pull の失敗と強制
上記でFast Forward となるケースですが、git merge FETCH_HEAD がコンフリクトにより失敗する時、git pull はエラーとなり、停止されます。この時 git fetch はすでに実行されているので、多くの場合リモート追跡ブランチだけが更新された状態となるはずです。
通常のGit 運用では、このようなコンフリクト時は「もーどうでもいいから、リモートに合わせたい!」という要求が発生することも多いでしょう。
下記のコマンドで履歴を強制します。
// 現在のブランチを強制的に指定したブランチに合わせる
$ git rest origin/master --hard
git pull の強制については、こちらにも詳しくまとめていますので、ぜひご覧ください。
FEATCH_HEADについて
「FETCH_HEAD」は[gitc]git fetch[/gitc] 実行時に更新される、リモートから取得したコミットの参照(ref)です。実際に .git/FETCH_HEAD というファイルに書き込まれます。この参照値は「git pull 実行時に、fetchしたブランチをマージにする際に使われる」のが主な用途になっています。
.git/FETCH_HEAD の中身の例
425b10a branch 'master' of ssh://bitbucket.org/team-name/repo-name
69c5872 branch 'prod' of ssh://bitbucket.org/team-name/repo-name
94b6d0b not-for-merge branch 'feature/a' of ssh://bitbucket.org/team-name/repo-name
※実際はSHA-1はフルの長さで記載されてます(上記は見やすさのため改変)
git pull の使い方
代表的な git pull の使用例を列挙します。わかり易さのために、リモートレポジトリ「origin」に対して、作業中のブランチを「master」と仮定します。
Case A指定したリモートブランチを、現在のブランチに取り込む
上記の概説でも言及した、最も基本的な git pull コマンドです。
リモートレポジトリ「origin」にあるブランチ「master」が他のチームメンバーによって更新され、「ローカルより先に進んでいる」状態において、最新の master ブランチの履歴をローカルの master に取り込みたいと思います。
さて、現在ローカルの master ブランチをチェックアウトしている状態であることを確認してから、下記の git pull コマンドを実行します。
// master をチェックアウト
$ git checkout master
// origin 上の master ブランチを、現在チェックアウトしているブランチ(= master)に取り込む
$ git pull origin master
なお、冒頭での紹介の通り、「git pull origin master」コマンドは下記2つを実行するいことと同義です。
// [1] 指定したリモートブランチの最新状態を、リモート追跡ブランチに反映する
git fetch origin master
// [2] 更新されたリモート追跡ブランチを、現在のローカルブランチにマージする
git merge FETCH_HEAD
Case B引数 (レポジトリ、ブランチ)を省略し「上流ブランチ」を取り込む
これは、実際は Case Aと同じ機能ですが、より短いコマンドで、同じ結果を得る事ができるため、よく利用します。
現在のローカルの master ブランチの「上流ブランチ(upstream branch)」の設定になんらかのリモートのブランチが指定されていれば、git pull のパラメータをすべて省略できます。
// 現在のブランチに、上流ブランチの最新の履歴を取り込む
git pull
通常は、ローカルのブランチには、同じ名前を持つリモートブランチを上流ブランチとして指定した運用となるケースがほとんどだと思います。上記の省略系はそのような場合に、素早くコマンドを実行できて便利です。
「上流ブランチ」についてはこの記事の下の方で補足しました。もしくは「上流ブランチについて」を詳しくまとめていますので、ご覧ください。
git pull コマンドの主要なオプション
下記に幾つかのgit pull のオプションを紹介します。git pull のオプションの多くは、git fetch 向けのオプションですが、裏側の動作としては git fetch が実行されますので、git pull と一緒に使うことができます。
マージせず、リベースする「--rebase」
git fetch 実行後に、通常はマージですが、リベースすることもできます。
// fetch 後、(マージせず)リベース
$ git pull --rebase
早送り(fast-forward)せず、必ずマージコミットを作成「--no-ff」
通常のgit merge コマンド同様、fast-forward(早送り、すなわち参照のみの移動)を行わない時、下記のように「--no-ff」オプションが利用可能です。
// 早送りしない
$ git pull --no-ff origin master
fast-forward可能であっても、かならずマージコミットが新しく作成されます。チームの運用方針によっては、利用するかもしれません。
【補足1】git pull の取り消し操作
誤って、git pull を実行してしまったとき、取り消しを行いたくなるも知れません。Git では、基本的にはコミットされた状態はすべて残っていますので、取り消しはいつも容易です。もっとも基本的な取り消しコマンドとして、「git reset --hard 」があります。
// 現在のブランチを1つ前のコミットに戻す
git reset --hard HEAD^
Git における「取り消し」に関しては、こちらの記事が詳しいですので、ご一読下さい。
【補足2】git pull の失敗。原因とその解決
git pull が失敗する時の原因と解決策です。
原因git merge FETCH_HEADのコンフリクト
もし、ローカルのmasterとリモートのmasterがコンフリクトしていたり、ローカルがリモートより履歴が進んでしまっているとき、git pull コマンドはエラーを出力して中止します。これは、単純に自動の git merge が不可能な場合、コンフリクトの解消を行う必要があるのと一緒の動作です。
もしコミットされていない変更が作業ツリーやインデックスにある場合は、警告が発生し、単純にマージが実行されません。作業ツリーはそのままの状態になります。
解決策git reset --hard による強制上書き
もし、ローカルを強制的にリモートに一致させたければ、現在のブランチの状態を「強制的に」他のブランチの状態に合わせるときの方法として「git reset --hard 」があります。
// 強制的に origin/master と一致させる
git reset --hard origin/master
こちらの記事もぜひご覧ください
【補足3】上流ブランチについて
上記で「上流ブランチ」の概念に触れましたので、おさらいしておきます。
「上流ブランチ」とは?
混乱しやすい Git の用語。「上流ブランチ」とは、あるローカルブランチがどのリモートブランチを追跡しているか?という関係性を示すための言葉です。厳密には、ローカルブランチに対する2つの設定値によって定義されています。
- branch.<ブランチ名>.remote
- branch.<ブランチ名>.merge
試しに .git/conf のファイルを開いてみましょう。すぐに該当項目は見つけられるはずです。下記はmaster ブランチに対する、上流ブランチの設定値です。
Git Document のにも解説がありますが、この説明はあまりわかり易くないかもしれません。念のため:
上流ブランチの設定方法
さて、上流ブランチを設定するには下記の方法があります。
[方法1]リモート追跡ブランチと同名のブランチ名をチェックアウト
すでにgit fetch によりリモート追跡ブランチが作成されている状況では、下記のコマンドで自動的に、上流ブランチとして設定が書き込まれます。
// すでに origin/remote-branch-name が存在する状態で・・
git checkout remote-branch-name
[方法2]Push 時に同時に上流ブランチとして設定
push -時に「-u (--set-upstream)」オプションを付ければ、自動的に push するブランチとpush 先のレポジトリ/ブランチは上流ブランチとして設定されます。
// Push 先を蒸留ブランチとして設定(2つは同義)
git push -u origin master
git push --set-upstream origin master
[方法3]上流ブランチを明示的に設定
もしくは、git branch コマンドを使って明示的に設定することもできます。
// 明示的に上流ブランチを設定(2つは同義)
git branch <local-branch> -u <remote-branch>
git branch <local-branch> --set-upstream-to=<remote-branch>
// ローカルブランチ名を省略すると、自動的に現在のブランチを設定します。
git branch -u <remote-branch>
git branch --set-upstream-to=<remote-branch>
上流ブランチに関しては、こちらにより多くの情報をまとめました。
git pull に関する参考リンク
いかがだったでしょうか?git pull もGit の中で最も使用頻度の高いコマンドの一つだと思います。ぜひマスターして快適な開発を進めましょう。
下記、参考記事です。
- git pullでローカルをリモートで強制上書きする方法、まとめ。
- gitでリモートブランチを削除するコマンド
- git commitしたコミットを取り消す、やり直す、修正する。
- Git 用語集:上流ブランチとは?
下記は、Git公式ドキュメントサイトです。