比較

git fetch と git pull: 違いと使い分け

更新日: · Skillaria.Top

git fetch はサーバーから新しいコミットをダウンロードし、origin/main のようなリモートブランチの参照を更新しますが、現在のブランチや作業ファイルには触れません。git pull は同じことを行ったうえで、取得した内容を merge または rebase によって現在のブランチへ即座に取り込みます。fetch はいつでも安全に実行でき、pull は変更を取り込む準備ができている場合に便利です。

結論

git fetch はサーバーから新しいコミットをダウンロードし、リモートブランチの参照(origin/main、origin/feature-x など)を更新します。ただし、現在のブランチも作業ディレクトリのファイルも変更しません。git pull は、git fetch を実行したうえで、取得した内容を現在のブランチへ merge(既定)または rebase で即座に取り込みます。

実践的なルールは次のとおりです。fetch はいつ実行しても何も壊しません。pull は現在のブランチを変更し、コンフリクトで止まることもあるため、作業ディレクトリをきれいにしてから、何が起こるかを理解したうえで実行してください。

リモートブランチはどこにあるのか

違いを明確にするため、ローカルリポジトリには2種類のブランチがあることを理解しておきましょう。ローカルブランチ(main、feature-x)は、自分のコミットで進めるものです。リモート追跡ブランチ(origin/main)は、「最後に同期した時点でサーバーがこうだった」ことを示すブックマークです。これを手で動かすことはできず、サーバーとの通信(fetch、pull、push)によってのみ更新されます。

git branch -a
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/main
  remotes/origin/feature-x

git status は、現在のブランチを実際のサーバーではなく、ブックマークの origin/main と比較します。そのため「Your branch is up to date with 'origin/main'」というメッセージは誤解を招くことがあります。長い間 fetch していなければ、Gitは同僚の新しいコミットを知らないだけなのです。

git fetch の動作

$ git fetch
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
Unpacking objects: 100% (4/4), done.
From github.com:team/project
   3f2a1c9..8b7d4e2  main       -> origin/main

最後の行が重要です。origin/main の参照が 3f2a1c9 から 8b7d4e2 に動きました。あなたのローカルの main は変わっていません。そこで、何が届いたのかを落ち着いて確認できます。

git status                       # Your branch is behind 'origin/main' by 2 commits
git log main..origin/main --oneline   # 手元にないコミット
git diff main origin/main        # ファイルでは何が変わるか

fetch の便利なオプション:

  • git fetch --all: すべての remote から取得します(フォークで origin と upstream の両方がある場合に便利です)。
  • git fetch --prune(-p): サーバーに存在しなくなったリモートブランチのローカルの参照を削除します。
  • git fetch origin main: 1つのブランチだけを取得します。
  • git fetch --tags: すべてのタグも取得します。

prune を常に有効にするには、一度だけ次を実行します: git config --global fetch.prune true。

git pull の動作

git pull は2つの手順を続けて行います。まず、現在のブランチの upstream に対して fetch を行い、次に origin/<ブランチ> を自分のブランチへ統合します。文字通り、次の操作と同じです。

git fetch origin
git merge origin/main      # pull --rebase を使う場合は git rebase origin/main

統合の結果は、履歴がどのように分かれているかによって決まります。

  • 自分の新しいコミットがない場合: fast-forward となり、ブランチが単に先へ進みます。
  • 自分にもサーバーにも新しいコミットがある場合: merge ではマージコミットが作られ、rebase では自分のコミットがサーバーのコミットの上に積み直されます。
  • 同じ行が両側で変更された場合: コンフリクトになり、手作業で解決する必要があります。

git fetch と git pull の比較

git fetchgit pull
コミットをダウンロードするはいはい
origin/* を更新するはいはい
現在のブランチを変更するいいえはい
作業ディレクトリのファイルを変更するいいえはい
コンフリクトが起こりうるいいえはい
作業ディレクトリがきれいである必要があるいいえ望ましい
他のブランチへの影響追跡しているすべての参照を更新する現在のブランチにのみ統合する
使う場面何が変わったかを確認する。rebase の前。スクリプト内自分のブランチをすばやくサーバーに追いつかせる

git pull: merge か rebase か

Git 2.27以降では、履歴が分かれているのに設定がない場合、pull は警告を出します。新しいバージョンでは、黙って merge する代わりに「Need to specify how to reconcile divergent branches」というエラーで止まります。Gitは一度だけ戦略を選ぶよう求めます。

git config --global pull.rebase false   # merge(以前の既定の動作)
git config --global pull.rebase true    # rebase
git config --global pull.ff only        # fast-forward のみ。それ以外は拒否

merge は履歴をそのまま保ち、「Merge branch 'main' of github.com:...」というコミットを追加します。ローカルのコミットがある状態で毎日 pull すると、このような技術的なマージコミットが履歴に積み重なります。

rebase は、未送信のコミットを最新のサーバー側のコミットの上に付け直します。履歴は一直線に保たれ、コンフリクトは1コミットずつ解決します。送信していないローカルのコミットには、通常これが最適です。rebase が危険なのは、すでに送信されていて他の人が作業の土台にしているコミットに対して行った場合だけです。

ff only は最も厳格なモードです。自分のコミットがない場合にだけ pull が成功します。履歴が分かれていれば、どうするかを明示的に決める必要があります。経験豊富な開発者の多くは、主要なブランチにこの設定を使っています。

作業ディレクトリに未コミットの変更があり、今すぐ pull したい場合は git pull --rebase --autostash が役立ちます。Gitが変更を退避し、rebase を行い、変更を元に戻してくれます。

典型的な流れ: fetch して確認し、取り込む

「まず fetch」というやり方は、自分のブランチに何が入るかを管理できるので有効です。特に pull request を作る前や、しばらく作業を離れた後に役立ちます。

git fetch
git log --oneline --graph HEAD origin/main   # ブランチがどう分かれているか
git rebase origin/main                       # または git merge origin/main
git push

もう1つのよくあるケースは、フィーチャーブランチを、切り替えずに最新の main で更新することです。

git switch feature-x
git fetch
git rebase origin/main

この場合、pull は適しません。フィーチャーブランチで git pull を実行すると、その upstream(origin/feature-x)の変更を取り込むからです。git pull --rebase origin main と書くこともできますが、fetch を使う方法のほうが分かりやすいです。

サーバーとの同期: ブランチを最新に保つ方法

「git sync」と言うときは、通常「他の人の変更を取り込み、自分の変更を送る」という流れを指します。素の Git には sync というコマンドはありません。IDEやGUIクライアントの Sync ボタンは、内部的に pull を行ったあと push を行います。手動で確実に行うには、次の手順を踏みます。

  1. git statusで、すべてコミットされているか、git stashで退避されていることを確認する。
  2. git pull --rebaseで変更を取り込み、自分のコミットを一番上に付け直す。
  3. コンフリクトがあれば解決する: ファイルを修正し、git add を実行して git rebase --continue を実行する。
  4. テストを実行する。
  5. git push を実行する。

フォークを元のリポジトリと同期するには、次のようにします。

git remote add upstream https://github.com/original/project.git
git fetch upstream
git switch main
git merge --ff-only upstream/main
git push origin main

git pull でよくある問題

Your local changes would be overwritten by merge

pull が、あなたが編集中でまだコミットしていないファイルを変更しようとしています。対処法は、コミットする、git stash で退避してから pull して git stash pop を実行する、または --autostash を使う、のいずれかです。pull のために変更を削除する必要はありません。

pull の後のコンフリクト

Gitは停止し、git status でコンフリクトのあるファイルを表示します。ファイルを開き、<<<<<<< と >>>>>>> のマーカーの間から必要な内容を選び、git add の後、merge の場合は git commit、rebase の場合は git rebase --continue を実行します。やめたい場合は、git merge --abort または git rebase --abort で pull 前の状態に戻せます。

There is no tracking information for the current branch

現在のブランチに upstream が設定されておらず、Gitはどこから取得すればよいか分かりません。明示的に指定してください: git pull origin main。または、一度だけ関連付けを設定します: git branch --set-upstream-to=origin/main。

refusing to merge unrelated histories

ローカルとリモートのリポジトリは、別々に作られています。たとえば、サーバー側でリポジトリ作成時に README を追加した場合などです。両者を統合すべきだと確信しているなら、git pull origin main --allow-unrelated-histories を使います。

失敗した pull を取り消す方法

pull の後の merge が完了していて、結果が望みどおりでない場合は、ブランチを pull 前の状態に戻します: git reset --hard ORIG_HEAD。このコマンドは未コミットの変更を削除するため、先に git status を確認してください。どうしても必要な場合は、git reflog から以前のブランチ位置を見つけられます。

どちらを選ぶか

  • 何が新しいかを、何も変更せずに知りたい: git fetch。
  • 自分のブランチで作業していて、サーバーに追いつくだけ: git pull --rebase(または pull.rebase true を設定した pull)。
  • 自分のコミットがない主要ブランチを更新する: git pull --ff-only。
  • フィーチャーブランチに main を取り込みたい: git fetch の後に git rebase origin/main または git merge origin/main。
  • スクリプトや CI を書く: fetch と明示的なコマンドを使い、pull は使わない。

コミットグラフでの見え方

あなたと同僚が、コミット C から作業を始めたとします。あなたはローカルでコミット D を作り、同僚はコミット E をサーバーに送りました。git fetch の後、あなたのリポジトリは両方の流れを把握します。main は D を、origin/main は E を指し、共通の祖先は C です。

          D   <- main (HEAD)
         /
A---B---C
         \
          E   <- origin/main

ここから先は、統合の方法で結果が変わります。git merge origin/main は、親を D と E に持つマージコミット M を作ります。git rebase origin/main は、D を E の上にコピーして、ハッシュの異なる新しいコミット D' を作るので、履歴は一直線になります。git pull は、これらの手順を間を空けずに自動で実行するだけです。統合の前にグラフを確認できる「間」こそが、fetch を分けて行う大きな価値です。

IDEでの fetch と pull

VS Code、IntelliJ IDEA などのエディタではボタンの名前が異なりますが、裏で実行されるのは同じコマンドです。「Fetch」は git fetch、「Pull」や「Update Project」は、設定で選ばれた戦略(merge または rebase)による pull、「Sync Changes」は pull の後に push を行います。共有ブランチで Sync を押す前には、どの戦略が選ばれているかを確認しておきましょう。そうしないと、思わぬマージコミットが履歴に現れます。多くのIDEは、バックグラウンドで定期的に fetch も行うので、ステータスバーの受信コミット数は通常最新の状態です。

まとめ

git fetch はサーバーに関する知識を更新し、git pull はその知識を現在のブランチに適用します。fetch はいつでも安全ですが、pull はブランチを変更してコンフリクトを生むことがあります。pull の戦略を一度設定し、作業ディレクトリをきれいに保ちましょう。push、pull、fetch の違い、リモートリポジトリと GitHub の扱い方は、Gitコースで実践的に解説しています。

よくある質問

git pull の前に git fetch は必要ですか?

いいえ。pull は最初の手順として自動的に fetch を行います。変更を先に確認してから取り込み方を決めたい場合にだけ、個別の fetch を行います。

git fetch で自分の変更が消えることはありますか?

ありません。fetch が変更するのは origin/main のようなリモート参照だけで、ローカルブランチ、インデックス、作業ディレクトリには触れません。

git pull はすべてのブランチを更新しますか?

いいえ。pull は現在のブランチにだけ変更を取り込みます。fetch によって他のブランチの origin/* 参照は更新されますが、ローカルブランチ自体は動きません。

git fetch はどのくらいの頻度で行うべきですか?

作業を始める前、pull request を作る前、push する前が目安です。多くのIDEはバックグラウンドで fetch を行うため、安全に任せられます。

FETCH_HEAD とは何ですか?

fetch が直前にダウンロードした内容を記録する一時的な参照です。たとえば git fetch origin main の後に git merge FETCH_HEAD を実行できます。

動画でこのテーマを学ぶ

このテーマはコース「Git:初心者から自信を持って使える開発者へ」で実践とともに詳しく解説しています。

コースへ