git fetchは「リモートの最新情報を手元に取ってくるだけ」、git pullは「fetchしたうえで、いまのブランチに取り込むところまで行う」コマンドです。fetchで動くのはリモート追跡ブランチ(origin/main)だけで、作業中のファイルも手元の main も変わりません。pullは、その後ろに merge または rebase が続きます。

この記事では、ローカルにbareリポジトリと2つのクローンを作り、Git 2.43.0で実際に実行した出力を載せています。fetch・pull(merge)・pull --rebase・pull --ff-only のそれぞれで origin/main と main の位置がどう動くかを git log --graph --all と図で比べ、「divergent branches」のhint全文、pull.rebase / pull.ff の設定ごとの挙動表、コンフリクトしたときの戻し方、fetch --prune、autostashまでまとめました。なお、git-scm.comの公式ドキュメントで確認した時点の最新版はGit 2.56.0(2026年9月28日リリース)で、この記事で使うオプションと設定名は最新版のドキュメントにも同じ名前で載っています。

git fetchとpullの早見表

何が変わるかの比較

コマンド origin/main(リモート追跡ブランチ) 手元の main 作業ツリーのファイル 一言でいうと
git fetch 進む そのまま そのまま 取ってくるだけ
git pull(merge) 進む 進む(必要ならマージコミットができる) 更新される fetch + merge
git pull --rebase 進む 進む(手元のコミットを付け替える) 更新される fetch + rebase
git pull --ff-only 進む 一直線に進められるときだけ進む 進んだときだけ更新 fetch + 早送りだけ

やりたいこと別のコマンド

やりたいこと コマンド
リモートの最新情報を取ってくる git fetch(git fetch origin と同じ)
すべてのリモートから取ってくる git fetch --all
リモートで消えたブランチを手元からも消す git fetch --prune(-p)
取り込む前に、増えたコミットを見る git log --oneline main..origin/main
取り込む前に、変更内容を見る git diff main origin/main
何コミット進んで・遅れているか数える git rev-list --left-right --count main...origin/main
fetchした内容を取り込む(マージ) git merge origin/main または git pull --no-rebase
手元のコミットを最新の上に付け替える git pull --rebase
一直線に進められるときだけ取り込む git pull --ff-only
作業中の変更を自動で退避して取り込む git pull --rebase --autostash
コンフリクトしたpullを取りやめる(merge) git merge --abort
コンフリクトしたpullを取りやめる(rebase) git rebase --abort
終わったpullを取り消す git reset --hard ORIG_HEAD
pullの既定をrebaseにする git config --global pull.rebase true
pullの既定を早送りだけにする git config --global pull.ff only

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「git fetchとpullの違い|図解とpull --rebaseの使い分け」

fetchとpullの違いを図で見る

登場する3つの場所

fetchとpullの違いは、「リモートのmain」「origin/main」「手元のmain」の3つを分けて考えるとすっきりします。

名前 ある場所 役割 動かすコマンド
リモートの main サーバー(origin) チーム全員の共有先 誰かの git push
origin/main 自分のPCの中 「最後に通信したときのリモートのmain」の写し git fetch(pullの前半)
main 自分のPCの中 自分が作業するブランチ git commit・git merge・git rebase(pullの後半)

origin/main は名前に origin/ と付いていますが、手元にあるブランチです。通信しない限り動かないので、「リモートの最新」ではなく「最後にfetchした時点のリモート」を指しています。これをリモート追跡ブランチと呼びます。

flowchart LR
    subgraph R["サーバー origin"]
        RM["リモートの main"]
    end
    subgraph L["自分のPC"]
        OM["origin/main<br>リモート追跡ブランチ"]
        M["main<br>ローカルブランチ"]
        W["作業ツリー<br>ファイル"]
    end
    RM -- "git fetch" --> OM
    OM -- "git merge または git rebase" --> M
    M --> W
    RM == "git pull = fetch と 取り込み" ==> M

fetchの前後

リモートにコミットCが増えた状態で git fetch すると、origin/main だけがCへ進みます。

flowchart LR
    subgraph before["fetch 前"]
        A1["A"] --> B1["B"]
        B1 -.- T1["main と origin/main"]
    end
    subgraph after["fetch 後"]
        A2["A"] --> B2["B"] --> C2["C"]
        B2 -.- T2["main"]
        C2 -.- T3["origin/main"]
    end
    before --> after

pullの前後(一直線に進められる場合)

手元に独自のコミットがなければ、pullは main のラベルをCまで動かすだけです。これをfast-forward(早送り)と呼びます。

flowchart LR
    subgraph before["pull 前"]
        A1["A"] --> B1["B"]
        B1 -.- T1["main と origin/main"]
    end
    subgraph after["pull 後"]
        A2["A"] --> B2["B"] --> C2["C"]
        C2 -.- T2["main と origin/main"]
    end
    before --> after

検証用のリポジトリを作る(コピペ用)

以降の実行結果は、次の構成で取りました。bareリポジトリ(作業ツリーを持たない共有用リポジトリ)をサーバーの代わりにして、aliceとbobの2人分のクローンを作ります。ネットワークなしで試せるので、手元で同じ動きを確かめられます。

git --version   # git version 2.43.0

mkdir fetch-pull-lab && cd fetch-pull-lab
git init --bare remote.git

# alice: 最初のコミットを作って push
git clone remote.git alice
cd alice
git config user.name alice && git config user.email alice@example.com
echo "# memo" > README.md && git add . && git commit -m "A: README を追加"
echo "line1" > app.txt   && git add . && git commit -m "B: app.txt を追加"
git push -u origin main
cd ..

# bob: この時点でクローン
git clone remote.git bob
cd bob
git config user.name bob && git config user.email bob@example.com
cd ..

# alice: コミット C を push(bob はまだ知らない)
cd alice
echo "line2" >> app.txt && git add . && git commit -m "C: app.txt に2行目"
git push
cd ..

実行結果に出てくるリモートのパスは、/srv/git/memo に短く書き換えています。コミットのハッシュは実行時のものです。

git fetchで起きること

fetchの前:手元はリモートの変化を知らない

bobのリポジトリで状態を見ます。aliceがCをpushしたあとですが、通信していないので「最新です」と表示されます。

cd bob
git status -sb
git log --oneline --graph --all
## main...origin/main
* bb0aa38 B: app.txt を追加
* c13e720 A: README を追加

fetchを実行する

git fetch
From /srv/git/memo
   bb0aa38..2af525d  main       -> origin/main

main -> origin/main は「リモートのmainの内容を、手元の origin/main に反映した」という意味です。手元の main を動かしたという表示ではありません。

git status
git log --oneline --graph --all
cat app.txt
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

nothing to commit, working tree clean
* 2af525d C: app.txt に2行目
* bb0aa38 B: app.txt を追加
* c13e720 A: README を追加
line1

コミットCは手元に届いていますが、app.txt は1行のままです。fetchはファイルを書き換えないので、作業の途中でも安心して実行できます。

取り込む前に差分を確認する

fetchとpullを分ける一番の利点は、取り込む前に中身を確かめられることです。

# リモートにあって手元にないコミット
git log --oneline main..origin/main

# 手元にあってリモートにないコミット(今回はなし)
git log --oneline origin/main..main

# 変更されたファイルと行数
git diff --stat main origin/main

# 変更内容そのもの
git diff main origin/main

# 手元だけ / リモートだけ のコミット数
git rev-list --left-right --count main...origin/main

実行結果:

2af525d C: app.txt に2行目
 app.txt | 1 +
 1 file changed, 1 insertion(+)
diff --git a/app.txt b/app.txt
index a29bdeb..c0d0fb4 100644
--- a/app.txt
+++ b/app.txt
@@ -1 +1,2 @@
 line1
+line2
0   1
コマンド わかること
git log main..origin/main 取り込むと増えるコミット
git log origin/main..main まだpushしていない自分のコミット
git diff main origin/main 取り込むと変わる内容
git rev-list --left-right --count main...origin/main 左が「手元だけ」、右が「リモートだけ」のコミット数
git status -sb [ahead 1, behind 1] の形で進み・遅れを1行表示

main..origin/main の .. は「左から届かず、右から届くコミット」という意味です。git logの範囲指定は既存記事「git logオプション一覧|見やすくするformat指定子とalias設定例」で、git diffの読み方は「git diffの使い方」の記事で詳しく扱っています。

pullで取り込む(fast-forward)

確認できたら取り込みます。fetch済みなので git merge origin/main でも同じ結果になります。

git pull
git log --oneline --graph --all
Updating bb0aa38..2af525d
Fast-forward
 app.txt | 1 +
 1 file changed, 1 insertion(+)
* 2af525d C: app.txt に2行目
* bb0aa38 B: app.txt を追加
* c13e720 A: README を追加

分岐したときのpull:4通りの結果を比べる

ここからが本題です。手元にもリモートにも新しいコミットがある「分岐した状態」では、pullのしかたでコミットグラフの形が変わります。

分岐した状態を作る

# alice: D を push
cd alice
echo "docs" > docs.txt && git add . && git commit -m "D: docs.txt を追加(alice)"
git push
cd ..

# bob: pull せずに X をコミット
cd bob
echo "bob memo" > bob.txt && git add . && git commit -m "X: bob.txt を追加(bob)"
flowchart LR
    A["A"] --> B["B"] --> C["C"]
    C --> D["D(alice)"]
    C --> X["X(bob)"]
    D -.- OM["リモートの main"]
    X -.- M["bob の main"]

1. 何も指定しないgit pull(divergent branchesのhint)

git pull

実行結果(Git 2.43.0。hintの全文):

From /srv/git/memo
   2af525d..fececeb  main       -> origin/main
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint: 
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint: 
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fatal: Need to specify how to reconcile divergent branches.

終了コードは128でした。「ブランチが分岐しているので、どう合流させるかを決めてください」という案内です。メッセージの意味は次のとおりです。

hintの行 意味
git config pull.rebase false # merge 分岐したらマージコミットを作って合流する
git config pull.rebase true # rebase 分岐したら手元のコミットを最新の上に付け替える
git config pull.ff only # fast-forward only 一直線に進められるときだけ取り込み、分岐していたら止まる
--rebase, --no-rebase, or --ff-only 設定せず、その回だけコマンドのオプションで指定してもよい

このとき、状態はこうなっています。

git log --oneline --graph --all
git status -sb
* b1793e0 X: bob.txt を追加(bob)
| * fececeb D: docs.txt を追加(alice)
|/  
* 2af525d C: app.txt に2行目
* bb0aa38 B: app.txt を追加
* c13e720 A: README を追加
## main...origin/main [ahead 1, behind 1]

pullは止まりましたが、前半のfetchは終わっているので origin/main はDまで進んでいます。手元の main とファイルは変わっていません。あとは合流のしかたを選ぶだけです。

2. git pull --no-rebase(merge)

git pull --no-rebase
git log --oneline --graph --all
Merge made by the 'ort' strategy.
 docs.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 docs.txt
*   90e2151 Merge branch 'main' of /srv/git/memo
|\  
| * fececeb D: docs.txt を追加(alice)
* | b1793e0 X: bob.txt を追加(bob)
|/  
* 2af525d C: app.txt に2行目
* bb0aa38 B: app.txt を追加
* c13e720 A: README を追加

XとDを親に持つマージコミット(90e2151)ができ、履歴が枝分かれして合流する形になります。Xのハッシュ(b1793e0)は変わりません。

3. git pull --rebase

git pull --rebase
git log --oneline --graph --all
Successfully rebased and updated refs/heads/main.
* ff00600 X: bob.txt を追加(bob)
* fececeb D: docs.txt を追加(alice)
* 2af525d C: app.txt に2行目
* bb0aa38 B: app.txt を追加
* c13e720 A: README を追加

履歴は一直線になり、XはDの次に付け替えられました。その代わり、Xのハッシュが b1793e0 から ff00600 に変わっています。内容は同じでも、親が変わると別のコミットとして作り直されるためです。

4. git pull --ff-only

git pull --ff-only
hint: Diverging branches can't be fast-forwarded, you need to either:
hint: 
hint:   git merge --no-ff
hint: 
hint: or:
hint: 
hint:   git rebase
hint: 
hint: Disable this message with "git config advice.diverging false"
fatal: Not possible to fast-forward, aborting.

分岐しているときは何も取り込まずに止まります(終了コード128、グラフは「1」のときと同じ)。「知らないうちにマージコミットができる」ことがないので、状況を見てから merge か rebase を自分で選びたい人に向いています。

4通りの結果を並べる

flowchart TB
    subgraph S1["pull --no-rebase(merge)"]
        direction LR
        c1["C"] --> d1["D"] --> m1["M マージコミット"]
        c1 --> x1["X"] --> m1
    end
    subgraph S2["pull --rebase"]
        direction LR
        c2["C"] --> d2["D"] --> x2["X' 作り直し"]
    end
    subgraph S3["pull --ff-only または 指定なし"]
        direction LR
        c3["C"] --> d3["D origin/main"]
        c3 --> x3["X main のまま"]
    end
方法 分岐時の結果 マージコミット 手元のコミットのハッシュ 終了コード
git pull(設定なし) 止まる(hintを表示) できない 変わらない 128
git pull --no-rebase マージして合流 できる 変わらない 0
git pull --rebase 一直線に付け替え できない 変わる 0
git pull --ff-only 止まる できない 変わらない 128

pull.rebaseとpull.ffの設定ごとの挙動

毎回オプションを付ける代わりに、設定で既定の動きを決められます。同じリポジトリのコピーに設定を1つずつ入れて git pull を実行した結果です(Git 2.43.0)。

設定 早送りできる状態(遅れているだけ) 分岐した状態
設定なし Fast-forward 止まる(Need to specify how to reconcile divergent branches.)
pull.rebase false Fast-forward マージコミットを作る
pull.rebase true Fast-forward rebaseして一直線
pull.rebase merges (今回は未実行) rebaseして一直線(手元のマージコミットは保ったまま付け替える指定)
pull.ff only Fast-forward 止まる(Not possible to fast-forward, aborting.)
pull.ff false 早送りできてもマージコミットを作る マージコミットを作る
pull.ff true (今回は未実行) マージコミットを作る
pull.rebase true + pull.ff only (今回は未実行) 止まる(Not possible to fast-forward, aborting.)
pull.rebase false + pull.ff only (今回は未実行) 止まる(同上)

pull.ff false を入れた状態で、早送りできるpullをした結果は次のとおりです。手元に独自のコミットがなくてもマージコミットができました。

Merge made by the 'ort' strategy.
 docs.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 docs.txt
*   5f359ec Merge branch 'main' of /srv/git/memo
|\  
| * fececeb D: docs.txt を追加(alice)
|/  
* 2af525d C: app.txt に2行目

どの設定を選ぶか

方針 設定 向いているチーム・人
履歴を一直線に保つ git config --global pull.rebase true 自分の未pushコミットを最新の上に積み直す運用。pushしていないコミットだけが作り直されるので扱いやすい
合流の記録を残す git config --global pull.rebase false マージコミットで「いつ取り込んだか」を残したい運用
自分で毎回選ぶ git config --global pull.ff only 分岐したら止まってほしい。状況を見てから git rebase origin/main か git merge origin/main を実行する

設定はリポジトリ単位(--global なし)でも入れられます。ブランチごとに変えたいときは branch.<名前>.rebase もあります。一時的に設定と違う動きをさせたいときは、--rebase・--no-rebase・--ff-only をコマンドに付ければその回だけ上書きできます。

mergeとrebaseそのものの違い(履歴の形、共有済みブランチで気をつけること)は、既存記事「git mergeとrebaseの違い|使い分けとコンフリクト解消」で詳しく扱っています。ここでは「pullの後半がどちらになるか」だけ押さえれば十分です。

pullでコンフリクトしたときの戻し方

aliceとbobが app.txt の同じ行を変更した状態を作り、pullしてみます。コンフリクトの直し方ではなく、「いったんpull前に戻す」方法に絞って紹介します(マーカーの読み方と解消の手順は、既存記事「Gitのコンフリクトの解消方法|マーカーの読み方から防ぎ方まで」をご覧ください)。

mergeでコンフリクトした場合:git merge --abort

git pull --no-rebase
From /srv/git/memo
   ff00600..6b25572  main       -> origin/main
Auto-merging app.txt
CONFLICT (content): Merge conflict in app.txt
Automatic merge failed; fix conflicts and then commit the result.

git status には取りやめる方法も表示されます。

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)
git merge --abort
git status -sb
git log --oneline --graph --all -4
cat app.txt
## main...origin/main [ahead 1, behind 1]
* e5557af Y: 1行目を変更(bob)
| * 6b25572 E: 1行目を変更(alice)
|/  
* ff00600 X: bob.txt を追加(bob)
* fececeb D: docs.txt を追加(alice)
line1 (bob)
line2

ファイルはpull前の内容に戻り、origin/main は進んだままです。fetchの結果は残るので、落ち着いて差分を見直せます。

rebaseでコンフリクトした場合:git rebase --abort

git pull --rebase
CONFLICT (content): Merge conflict in app.txt
error: could not apply e5557af... Y: 1行目を変更(bob)
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply e5557af... Y: 1行目を変更(bob)
git rebase --abort
git status -sb
## main...origin/main [ahead 1, behind 1]
pullのしかた コンフリクト中に取りやめる 解消して続ける
merge(--no-rebase) git merge --abort ファイルを直して git add → git commit
rebase(--rebase) git rebase --abort ファイルを直して git add → git rebase --continue

どちらの途中なのか迷ったら git status を実行します。実行すべきコマンドがかっこ書きで表示されます。

終わったpullを取り消す:ORIG_HEAD

コンフリクトなしで終わったpullを「やはり取り込む前に戻したい」ときは、Gitが直前の位置を覚えている ORIG_HEAD を使います。

git reflog -3
git reset --hard ORIG_HEAD
git log --oneline --graph --all -4
90e2151 HEAD@{0}: pull --no-rebase: Merge made by the 'ort' strategy.
b1793e0 HEAD@{1}: commit: X: bob.txt を追加(bob)
2af525d HEAD@{2}: pull: Fast-forward
HEAD is now at b1793e0 X: bob.txt を追加(bob)
* b1793e0 X: bob.txt を追加(bob)
| * fececeb D: docs.txt を追加(alice)
|/  
* 2af525d C: app.txt に2行目
* bb0aa38 B: app.txt を追加

git reset --hard はコミットしていない変更も消すので、作業中の変更があるときは先にコミットかstashをしてから実行します。reflogを使った復元は、既存記事「git reset --hardを取り消す方法|reflogで復元する手順」にまとめています。

作業中の変更があるときのpullとautostash

コミットしていない変更が残っている状態でpullしたときの動きを、3つのパターンで確かめました。

パターン1:別のファイルを編集中(mergeのpull)

編集中の bob.txt と、取り込まれる docs.txt が別のファイルなら、そのままpullできます。

Updating 6b25572..2e35c09
Fast-forward
 docs.txt | 1 +
 1 file changed, 1 insertion(+)

pullのあとも M bob.txt と表示され、編集中の変更は残っていました。

パターン2:同じファイルを編集中

取り込まれる docs.txt を自分も編集していると、pullは上書きを避けて止まります。

error: Your local changes to the following files would be overwritten by merge:
    docs.txt
Please commit your changes or stash them before you merge.
Aborting
Updating 6b25572..2e35c09

パターン3:pull --rebaseは変更があるだけで止まる

rebaseは作業ツリーがきれいな状態を前提にするので、別のファイルの編集でも止まります。

git pull --rebase
error: cannot pull with rebase: You have unstaged changes.
error: Please commit or stash them.

--autostashで自動的に退避・復元する

--autostash を付けると、pullの前に変更を自動でstashし、終わったら戻してくれます。

git pull --rebase --autostash
git status -sb
Updating 6b25572..2e35c09
Created autostash: 67e893e
Fast-forward
 docs.txt | 1 +
 1 file changed, 1 insertion(+)
Applied autostash.
## main...origin/main
 M bob.txt

Created autostash で退避し、Applied autostash. で戻しています。毎回付けるのが手間なら、git config --global rebase.autoStash true を設定しておくと、rebaseのpullで自動的に働きます(mergeのpull向けには merge.autoStash があります)。

同じファイルを編集していた「パターン2」で --autostash を使うと、戻すときにコンフリクトになることがあります。実際の出力は次のとおりです。

Updating 6b25572..2e35c09
Created autostash: 6a8de49
Fast-forward
 docs.txt | 1 +
 1 file changed, 1 insertion(+)
Applying autostash resulted in conflicts.
Your changes are safe in the stash.
You can run "git stash pop" or "git stash drop" at any time.

pull自体は終わっていて、退避した変更はstashに残っています。ファイルのコンフリクトを直したあと、stashが不要なら git stash drop で片づけます。stashの操作は、既存記事「git stashの使い方|全コマンド実行結果つきで退避と復元を解説」を参照してください。

fetch --pruneで消えたリモートブランチを整理する

リモートでブランチが削除されても、手元の origin/ブランチ名 は自動では消えません。aliceが feature/login をpushしてから削除した状態で確かめます。

git fetch
git branch -r
  origin/HEAD -> origin/main
  origin/feature/login
  origin/main

リモートにはもう存在しないのに、origin/feature/login が残っています。--prune を付けると整理されます。先に --dry-run を付けると、何が消えるかだけを確認できます。

git fetch --prune --dry-run
git fetch --prune
git branch -r
From /srv/git/memo
 - [deleted]         (none)     -> origin/feature/login
  origin/HEAD -> origin/main
  origin/main
やりたいこと コマンド
その回だけ整理する git fetch --prune(git fetch -p)
消える対象だけ確認する git fetch --prune --dry-run
fetchのたびに自動で整理する git config --global fetch.prune true
pullのときに整理する git pull --prune

--prune が消すのはリモート追跡ブランチ(origin/...)だけです。手元で作ったローカルブランチは残るので、不要になったら git branch -d ブランチ名 で別に削除します。

originとは何か・fetchの書き方いろいろ

originは、クローン元のリモートリポジトリに自動で付く名前(あだ名)です。URLの代わりに使えます。

git remote -v
git branch -vv
origin  /srv/git/memo.git (fetch)
origin  /srv/git/memo.git (push)
* main 2af525d [origin/main] C: app.txt に2行目

[origin/main] は、手元の main が origin/main を追跡している(上流ブランチに設定している)という表示です。git pull や git status の「ahead / behind」は、この対応をもとに動きます。

書き方 動き
git fetch 現在のブランチの上流があるリモート(ふつうはorigin)から、全ブランチ分を取得
git fetch origin originから全ブランチ分を取得
git fetch origin main originのmainだけ取得(origin/main も更新される)
git fetch --all 登録してある全リモートから取得
git fetch --tags タグもすべて取得
git pull origin main originのmainを取得して、いまのブランチに取り込む

上流ブランチが設定されていないブランチで git pull すると、次の案内が出ます。

There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> topic

案内のとおり git branch --set-upstream-to=origin/main で対応づけるか、git pull origin main のように取得元を明示すれば進められます。

fetchとpullの使い分け

場面 おすすめ 理由
朝いちばんに最新へ追いつく(手元に未pushコミットなし) git pull 早送りで終わるので手数が少ない
作業の途中で、リモートの動きだけ知りたい git fetch ファイルが変わらないので作業を中断せずに済む
取り込む前に、他の人の変更を読みたい git fetch → git log / git diff → git merge または git rebase 内容を確かめてから取り込める
手元に未pushコミットがあり、履歴を一直線にしたい git pull --rebase マージコミットを作らずに追いつける
取り込みの記録をマージコミットで残したい git pull --no-rebase 合流した時点が履歴に残る
分岐していたら止まってほしい git pull --ff-only 自分で方法を選ぶきっかけになる
レビュー用に他の人のブランチを見るだけ git fetch → git switch --detach origin/ブランチ名 手元のブランチを増やさずに確認できる
pushが ! [rejected] main -> main (fetch first) で止まった git pull --rebase → git push リモートの新しいコミットを取り込んでから送り直す

迷ったら「まずfetch、見てから取り込む」が、どの状況でも通用する進め方です。fetchは何度実行しても手元の作業に影響しません。

つまずきやすい点と対処

表示・状況 原因 対処
fatal: Need to specify how to reconcile divergent branches. 分岐していて、合流方法が未設定 --rebase / --no-rebase を付ける。または pull.rebase を設定する
fatal: Not possible to fast-forward, aborting. --ff-only(または pull.ff only)で分岐していた git rebase origin/main か git merge origin/main を選んで実行する
error: cannot pull with rebase: You have unstaged changes. 未コミットの変更がある コミットかstashをする。または --autostash を付ける
Your local changes ... would be overwritten by merge 取り込まれるファイルを自分も編集中 コミットかstashをしてからpullする
There is no tracking information for the current branch. 上流ブランチが未設定 git branch --set-upstream-to=origin/<branch>
fetchしたのにファイルが変わらない fetchは origin/main を進めるだけ git merge origin/main か git pull で取り込む
git status は最新と言うのに、リモートには新しいコミットがある 最後のfetchから時間がたっている git fetch してからもう一度 git status
削除済みのリモートブランチが git branch -r に残る 追跡ブランチは自動では消えない git fetch --prune
pullのたびにマージコミットが増える 分岐した状態でmergeのpullをしている git pull --rebase に切り替える(チームの方針に合わせる)

よくある質問

Q. git pullは、git fetchとgit mergeを続けて実行するのと同じですか? A. 既定の動きはそのとおりです。git pull は git fetch のあと、上流ブランチ(origin/main など)を現在のブランチに取り込みます。取り込み方は設定とオプションで変わり、--rebase なら git rebase origin/main、--no-rebase なら git merge origin/main に相当します。この記事の実行結果でも、fetch済みの状態で git pull を実行すると Fast-forward と表示され、mergeと同じ結果になりました。

Q. git pull --rebaseを使うと、他の人のコミットも書き換わりますか? A. 書き換わりません。作り直されるのは「手元にあって、まだリモートにない自分のコミット」だけです。この記事の例でも、aliceのコミットD(fececeb)はそのままで、bobのコミットXだけが b1793e0 から ff00600 に変わりました。

Q. fetchしただけの内容は、どうやって見ればよいですか? A. origin/main を指定して見ます。増えたコミットは git log --oneline main..origin/main、内容は git diff main origin/main、ファイルの中身は git show origin/main:app.txt で確認できます。ブランチを切り替えずに確認できるので、作業中のファイルには影響しません。

Q. 「divergent branches」のhintが出ないようにするには? A. git config --global pull.rebase true(rebaseで合流)、git config --global pull.rebase false(mergeで合流)、git config --global pull.ff only(早送りだけ)のいずれかを設定します。前の2つは分岐したときに自動で合流し、pull.ff only は別のメッセージ(Not possible to fast-forward)で止まります。チームで方針がある場合はそれに合わせましょう。

まとめ

  • fetchは origin/main だけを進め、手元の main とファイルは変えない。作業の途中でもいつでも実行できる
  • pullは fetch + 取り込み。後半が merge になるか rebase になるかは、オプションと pull.rebase / pull.ff で決まる
  • 分岐したときの結果は3通り。--no-rebase はマージコミット、--rebase は一直線(手元のコミットのハッシュが変わる)、--ff-only は止まる
  • 「divergent branches」は合流方法を決めてほしいという案内。hintにある3つの設定から選ぶ
  • 取り込む前の確認は git log main..origin/main と git diff main origin/main
  • コンフリクトしたら git status。mergeなら git merge --abort、rebaseなら git rebase --abort でpull前に戻せる
  • fetch --prune で消えたリモートブランチを整理、--autostash で作業中の変更を自動で退避できる

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「git fetchとpullの違い|図解とpull --rebaseの使い分け」

株式会社RJCでは、git fetchとpullの使い分けのようなGitの基本を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?