MENU

ローカル変更がある状態でリモート更新と衝突したときの Git マージ手順

ローカル変更がある状態でリモート更新と衝突したときの Git マージ手順

ローカルで未コミットのファイルを編集している間に、リモート側へ別のコミットが追加されることがあります。その状態で git pull すると、Git はローカルの変更を上書きする危険があるため、pull を止めることがあります。

この場合は、作業中の変更を git stash で一時退避し、リモート変更を取り込んでから、退避した変更を戻すのが扱いやすい手順です。

この記事では、次のような状況を前提に、確認手順と対応手順を整理します。

  • ローカルに未コミット変更がある
  • リモートの origin/main に新しいコミットが積まれている
  • git pull がローカル変更の上書きリスクで中断された
  • ローカル変更は消さずに残したい
目次

結論: stash → fetch/merge → stash pop の順で進める

まず結論です。

未コミット変更がある状態でリモートの更新を取り込みたい場合は、次の順で作業します。

# 実行場所: 対象リポジトリのルートディレクトリ
# 対象: Git 管理下の作業ツリー

git status
git stash
git fetch origin
git merge origin/main
git stash pop
git status

この手順では、ローカルの作業内容を一時的に退避してから、リモートの変更を取り込みます。その後、退避していた作業内容を現在のブランチへ戻します。

ここがポイント: git pull は内部的にはおおむね fetchmerge の組み合わせです。未コミット変更が邪魔になる場合は、先に stash で作業ツリーをきれいにしてから、同じ流れを分解して実行します。

前提条件

ここでは、次の状態を想定します。

  • ブランチ: main
  • リモート: origin/main
  • ローカル: 未コミット変更あり
  • リモート: ローカルより先に進んでいる
  • 目的: ローカル変更を残したまま、リモート変更を取り込む

たとえば git status で、次のような表示が出ている状態です。

Your branch is behind 'origin/main' by 13 commits, and can be fast-forwarded.

Changes not staged for commit:
  modified: src/wp_post_tool/webapp.py
  modified: src/wp_post_tool/web_templates/post_edit.html
  modified: src/wp_post_tool/web_static/app.css

この表示から分かることは2つあります。

  • ローカルブランチは origin/main より 13 コミット遅れている
  • 3つのファイルに未コミット変更がある

このまま git pull すると、Git はリモート変更の取り込みによってローカルの未コミット変更が壊れる可能性を検知し、処理を止めることがあります。

困っていること: pull したいが未コミット変更を消したくない

この場面で避けたいのは、作業中の変更を失うことです。

特に、次のような状況では慎重に進める必要があります。

  • まだコミットできるほど作業がまとまっていない
  • 変更内容を一度確認してからコミットしたい
  • リモートの変更も早めに取り込みたい
  • 同じファイルを別環境や別作業者も触っている可能性がある

git pull が止まるのは不便ですが、Git の挙動としては安全側です。未コミット変更を勝手に上書きせず、ユーザーに判断を促している状態と考えると分かりやすいです。

確認手順

作業前に、現在の状態を確認します。

1. 作業ツリーの状態を見る

# 実行場所: 対象リポジトリのルートディレクトリ

git status

見るポイントは次の通りです。

  • どのブランチにいるか
  • origin/main より遅れているか
  • 未コミット変更があるか
  • 変更ファイルがどれか
  • untracked file があるか

git stash は通常、追跡済みファイルの変更を退避します。新規作成した未追跡ファイルも含めて退避したい場合は、後述する git stash -u を検討します。

2. 退避前に差分を確認する

作業内容を退避する前に、何を変更していたかを確認します。

# 実行場所: 対象リポジトリのルートディレクトリ

git diff

ステージ済みの変更がある場合は、次も確認します。

git diff --cached

この確認を挟むと、stash pop 後にコンフリクトが起きた場合でも、元の意図を追いやすくなります。

対応手順

ここから実際の対応です。

ステップ1: ローカル変更を一時退避する

# 実行場所: 対象リポジトリのルートディレクトリ

git stash

これで、作業中の変更が stash に積まれ、ワーキングツリーはクリーンな状態に戻ります。

退避できたか確認します。

git status
git stash list

git stash liststash@{0} のような項目が表示されれば、退避されています。

未追跡ファイルも退避したい場合は、通常の git stash ではなく次を使います。

git stash -u

ただし、退避対象が増えるため、実行前に git status で含まれるファイルを確認しておくと安全です。

ステップ2: リモートの変更を取得する

# 実行場所: 対象リポジトリのルートディレクトリ

git fetch origin

fetch は、リモートの最新情報を取得します。この時点では、まだ現在のブランチには統合しません。

続けて origin/main を現在のブランチへ統合します。

git merge origin/main

ローカルに独自コミットがなく、単にリモート側だけが進んでいる場合は、fast-forward で進みます。fast-forward では新しいマージコミットを作らず、ローカルのブランチ位置だけが origin/main に追いつきます。

ステップ3: 退避していた変更を戻す

# 実行場所: 対象リポジトリのルートディレクトリ

git stash pop

stash pop は、最新の stash を現在の作業ツリーへ再適用し、成功すれば stash から削除します。

変更箇所がリモート変更と重ならなければ、自動で戻ります。重なる場合は、対象ファイルにコンフリクトマーカーが入ります。

コンフリクトが起きた場合は、次の流れで対応します。

git status
# コンフリクトしたファイルを編集して解消
git add <解消したファイル>
git status

作業内容として保存する段階になったら、通常通りコミットします。

git commit -m "リモート更新取り込み後のローカル変更を反映"

なぜこの方法で解決できるのか

git pull は、リモートの変更取得と現在ブランチへの統合をまとめて実行します。作業ツリーに未コミット変更があると、統合時にその変更が上書きされる可能性があります。

Git はその危険があると判断すると、処理を止めます。

stash を使うと、次のように作業を分けられます。

  • 未コミット変更を一時退避する
  • 作業ツリーをクリーンにする
  • リモート変更を取り込む
  • 退避した変更を戻す
  • 必要ならコンフリクトを解消する

つまり、ローカル変更を保持したまま、リモート変更を先に取り込める状態を作るのがこの手順の目的です。

代替案と使い分け

状況によっては、stash → merge → pop 以外の選択肢もあります。

状況候補向いているケース
未コミット変更があるgit stash作業途中で、まだコミットしたくない場合
ローカル変更がまとまっているgit commit してから merge変更単位として残せる状態になっている場合
ローカルにも独自コミットがあるgit rebase履歴を一直線に保ちたい運用の場合
退避した変更が不要になったgit stash drop戻す必要がないと確認できた場合

rebase は履歴を整理しやすい一方で、共有済みコミットに対して不用意に使うと混乱の原因になります。チーム運用では、ブランチ運用ルールに合わせて選びます。

よく使うコマンド

この場面で使うコマンドをまとめます。

# 作業状態を確認
git status

# 未ステージの差分を確認
git diff

# ステージ済み差分を確認
git diff --cached

# 作業中の変更を退避
git stash

# 未追跡ファイルも含めて退避
git stash -u

# stash の一覧を確認
git stash list

# 最新の stash を戻す
git stash pop

# 最新の stash を削除
git stash drop

# リモート情報を取得
git fetch origin

# origin/main を現在のブランチに統合
git merge origin/main

git stash drop は、退避した変更を破棄します。戻す必要がないと確認してから実行します。

再発防止と次回の確認ポイント

同じ状況は、複数人で同じリポジトリを触る環境ではよく起きます。完全に避けるというより、作業前後の確認を習慣化するのが現実的です。

次回は、作業開始前と pull 前に次を確認します。

  • git status で未コミット変更を確認する
  • git fetch origin でリモートの進み具合を確認する
  • 変更が大きい場合は、先に小さくコミットできないか考える
  • 未追跡ファイルがある場合は、git stash -u が必要か確認する
  • stash pop 後は必ず git status を見る
  • コンフリクトが出たら、マーカーを消してから git add する

特に stash は便利ですが、積みっぱなしにすると後から中身を思い出しにくくなります。退避したら、戻すか、不要なら破棄するところまで確認した方が安全です。

まとめ

ローカルに未コミット変更があり、リモート側にも新しいコミットがある場合は、いきなり git pull で進めようとすると止まることがあります。

基本手順は次の通りです。

  1. git status で状態を確認する
  2. git stash でローカル変更を一時退避する
  3. git fetch origin でリモート情報を取得する
  4. git merge origin/main でリモート変更を取り込む
  5. git stash pop でローカル変更を戻す
  6. コンフリクトがあれば解消する

判断基準はシンプルです。まだコミットしたくない作業中の変更があるなら stash、変更がまとまっているなら先にコミットです。

次に同じエラーが出たときは、まず git status を見て、「未コミット変更」と「リモートとの差分」のどちらが問題になっているかを切り分けるところから始めると、手順を誤りにくくなります。

参照リンク

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

目次