コンテンツにスキップ

fetch と pull の違い

GitHubとのデータのやり取りで必ず使う fetchpull
「なんとなく使っていたけど違いが分からない」という方向けに、図を使いながら丁寧に解説します。


登場人物の整理

Gitでは「ローカル(自分のPC)」と「リモート(GitHub)」の2か所にデータが存在します。

graph LR
    subgraph local ["ローカル(自分のPC)"]
        A["作業ディレクトリ<br/>実際のファイル"]
        B["ステージング<br/>次のコミット候補"]
        C["ローカルリポジトリ<br/>コミット履歴"]
        D["リモート追跡ブランチ<br/>origin/develop など"]
    end
    subgraph remote ["リモート(GitHub)"]
        E["リモートリポジトリ<br/>チームで共有"]
    end

    A -- git add --> B
    B -- git commit --> C
    C -- git push --> E
    E -- git fetch --> D
    D -- "git merge/rebase" --> C
    E -- git pull --> C

リモート追跡ブランチとは

origin/develop のように、「GitHubのdevelopブランチの状態をローカルにキャッシュしたもの」です。
git fetch を実行したときに更新されます。


fetch とは?

git fetch は、GitHubの最新情報をダウンロードするだけで、
手元のファイルや作業ブランチには一切手を加えません。

sequenceDiagram
    participant GitHub as リモート(GitHub)
    participant Cache as リモート追跡ブランチ<br/>origin/develop
    participant Local as ローカルブランチ<br/>develop

    GitHub->>Cache: 最新コミットをダウンロード
    Note over Cache: origin/develop が更新される
    Note over Local: ← 変化なし!

fetch を使う場面

  • 「他の人が何か変更した?」と確認したいとき
  • rebasemerge の前に、まず最新情報だけ取得したいとき
git fetch origin

fetch 後に変更内容を確認できます:

# GitHubのdevelopと自分のブランチの差分を見る
git log HEAD..origin/develop --oneline

pull とは?

git pullgit fetch + git merge を一度にやる操作です。
GitHubの最新を取ってきて、そのまま手元のブランチに反映します。

sequenceDiagram
    participant GitHub as リモート(GitHub)
    participant Cache as リモート追跡ブランチ<br/>origin/develop
    participant Local as ローカルブランチ<br/>develop

    GitHub->>Cache: ① fetch:最新コミットをダウンロード
    Cache->>Local: ② merge:ローカルブランチに反映
    Note over Local: 手元のファイルが更新される!
git pull origin develop

fetch vs pull 比較

git fetch git pull
何をする 情報をダウンロードするだけ ダウンロード+手元に反映
手元のファイル 変わらない 変わる
コンフリクト 起きない 起きる可能性あり
使いどころ 確認してから慎重に反映したいとき 素直に最新を取り込みたいとき

このプロジェクトでの使い方

rebase 運用をしているため、git pull をそのまま使うと
マージコミットが作られてしまいます。以下のルールで使い分けてください。

developを更新するとき(自分のブランチ作業前)

git checkout develop
git pull origin develop

develop は自分が直接作業しないブランチなので pull で問題ありません。


featureブランチ作業中に最新のdevelopを取り込むとき

git fetch origin
git rebase origin/develop

pull ではなく fetchrebase の順で実行します。

sequenceDiagram
    participant GitHub
    participant origin/develop as origin/develop<br/>(リモート追跡)
    participant feature as feature/○○<br/>(自分のブランチ)

    GitHub->>origin/develop: git fetch origin
    Note over origin/develop: 最新の状態になる
    origin/develop->>feature: git rebase origin/develop
    Note over feature: コミットが最新地点に移植される

なぜ pull でなく fetch + rebase なのか

git pull origin develop は内部で merge を使うため、
マージコミットが作られて履歴がY字型になります。
fetch + rebase にすることで、履歴を一直線に保てます。


よく使うパターンまとめ

パターン1:朝イチで最新を取り込む

git checkout develop
git pull origin develop

パターン2:作業中に他の人の変更を確認する(手元は変えない)

git fetch origin

# developに何が追加されたか確認
git log HEAD..origin/develop --oneline

パターン3:featureブランチをdevelopに追いつかせる

git fetch origin
git rebase origin/develop

パターン4:pull でマージコミットを作らずにrebaseする

実は pull にも --rebase オプションがあります。

git pull --rebase origin develop

これは fetch + rebase と同じ動きをします。
ただし明示的に fetchrebase と書いた方が何をしているか分かりやすいため、
このプロジェクトでは fetchrebase を推奨します。


動作イメージ:ビフォーアフター

gitGraph
   commit id: "A"
   commit id: "B"
   branch feature
   checkout feature
   commit id: "C(自分の作業)"
   checkout main
   commit id: "D(他の人の作業)"
   commit id: "E(他の人の作業)"

自分のブランチが古い B から出ている状態。

gitGraph
   commit id: "A"
   commit id: "B"
   commit id: "D"
   commit id: "E"
   commit id: "C-prime(最新地点に移植)"

CE(最新)の後ろに移植され、履歴が一直線に!


まとめ

コマンド 一言まとめ
git fetch origin GitHubを覗き見するだけ。手元は変わらない
git pull origin develop 取ってきてそのまま反映。developブランチの更新に使う
git fetch + git rebase 取ってきて、自分のコミットを最新地点に移植。featureブランチの更新に使う