◀ 3.

Cannot rebase: You have unstaged changes. のエラー対処

▶

Cannot rebaseの開始拒否は、保存対象と作業状態を確認する合図です。stash・commit・延期を選び、破棄や自動復元を一律の解決にしません。

診断、保存、比較、操作の選択、結果確認の順序

この記事の要点
  • Cannot rebase: You have unstaged changes は作業中の変更があるまま rebase しようとしたエラー
  • 対処 ①: 保存範囲を確認してstashに退避。rebase完了後もapply等の結果と競合を確認
  • 対処 ②: 変更を git add + commit してから rebase
  • 破棄操作は初手にしない。index・追跡/未追跡・ignoredを分け、必要な内容を保存する
  • rebase 中の競合解決は git rebase --continue / 中断は git rebase --abort

 

エラーの状況

git rebase を実行したときに、以下のメッセージが出ます:

$ git rebase main
Cannot rebase: You have unstaged changes.
Please commit or stash them.

通常のrebaseは未ステージまたはindexの未コミット変更を検出すると開始を拒否します。--autostashを選んだ場合などは例外で、「未commitがあれば常に不可能」とは限りません。未追跡だけなら開始できる場合もありますが、取込み先が同名pathを使うと衝突します。エラーの文言だけで作業全体の保存状況を判断しません。

状況確認

まず、何が変更されているかを確認:

$ git status
On branch feature/foo
Your branch is up to date with 'origin/feature/foo'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   src/main.py

no changes added to commit

対処方法

方法 1: stash で一時退避(保存範囲を確認)

旧例の訂正・実行前の確認:通常stashは追跡済みの作業ツリーとindexを保存しますが、未追跡は-u、ignoredも含めるなら-aという別の範囲です。-u / -aは保存後に対象ファイルを作業ツリーから除くため、診断コマンドではありません。submoduleや外部ファイルは別に保存します。popは成功するとstash一覧から削除し、競合時は残します。まずapplyで退避を残して差分を確認する案もあり、元のstage状態を再適用するには--indexを検討しますが競合で失敗し得ます。

# 変更を退避
$ git stash
Saved working directory and index state WIP on feature/foo: abc1234 ...

# rebase 実行
$ git rebase main
Successfully rebased and updated refs/heads/feature/foo.

# 退避した変更を復元
$ git stash pop
On branch feature/foo
Changes not staged for commit:
        modified:   src/main.py

注意: stash pop で競合(conflict)が起きる場合があります。その場合は手動で解決:

旧例の訂正・実行前の確認:旧末尾コメントは「競合したpopでは自動削除されない」という場合だけです。成功したpop後にdropすると別のstashを消しかねません。この旧dropは実行しません。競合時はstatusと内容を確認し、編集・必要なpathだけaddして動作を検証します。stash適用の競合だけならrebase --continueでは解決しません。削除を判断する場合もstashのOIDと現在の一覧を照合します。

# 競合発生
$ git stash pop
Auto-merging src/main.py
CONFLICT (content): Merge conflict in src/main.py

# 競合を編集して解決後
$ git add src/main.py
$ git stash drop  # 退避を削除(pop は自動削除されないので明示)

方法 2: 変更をコミットしてから rebase

旧例の訂正・実行前の確認:git add .は意図しない設定や秘密値を含め得るので対象pathとstaged diffを確認します。amendはメッセージだけでなくindexの内容も含めてcommitを置き換えます。reset --soft HEAD~はその時点の最後のcommitを外し、rebaseでWIPが残ったか確認なしに実行できません。共有済みの履歴を安易に編集しません。

# WIP コミットを作っておく
$ git add .
$ git commit -m "WIP: 作業中"

$ git rebase main
# ... rebase 完了 ...

# 後で WIP コミットを修正したい場合
$ git commit --amend  # メッセージ修正
# または
$ git reset --soft HEAD~  # コミットを取り消してステージング状態に

方法 3: 変更を破棄して rebase

注意: 破棄した未保存内容は復元を保証できません。「全変更を消す」は各コマンドの作用を正しく表しません。次の旧コードは実行推奨ではなく、まとめて実行しないでください。

旧例の訂正・実行前の確認:checkout .は現在位置以下の追跡pathをindexから戻すため、stage済みの変更は残り得ます。clean -fdは未追跡のファイル / directoryが対象で、通常ignoredは除外、-xはignoredも、-Xはignoredだけです。まずclean -n -dと必要なpath指定で予定だけ確認します。reset --hard HEADはindexと追跡内容をHEADへ合わせ、書込みの邪魔になる未追跡 / ignoredを失う場合もあります。未追跡を必ず全削除する操作でも完全バックアップでもありません。実clean / hard resetは本検証では実行しません。

# 変更を完全に破棄
$ git checkout .       # トラッキング済みファイルの変更を破棄
$ git clean -fd        # 未追跡ファイルを削除
# または
$ git reset --hard HEAD  # 全変更を破棄してコミット状態に戻す

$ git rebase main

rebase 中に競合が発生したら

rebase 実行中に競合が起きると以下のメッセージ:

CONFLICT (content): Merge conflict in src/main.py
error: could not apply abc1234... commit message
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".

競合の解決手順

  1. 競合ファイルを編集: <<<<<<< / ======= / >>>>>>> マーカーで挟まれた部分を修正
  2. 解決済みをマーク: git add 解決したファイル
  3. rebase 継続: git rebase --continue
  4. すべてのコミットを処理し終わるまで 1-3 を繰り返す

rebase を中断したい

旧例の訂正・実行前の確認:開始拒否と進行中のrebaseを区別します。--abortは進行中のrebaseを中止し開始時のbranch / HEADへ戻す操作で、途中で作った未保存ファイルまで完全に戻す保証ではありません。必要な追加作業を保全してから判断します。--quitはHEAD / index / worktreeを戻さず管理状態を終了し、autostashはstash一覧へ保存する別操作です。

$ git rebase --abort
# rebase 前の状態に戻る

関連エラー

  • Cannot pull with rebase: You have unstaged changes — git pull --rebase で同じエラー、同じ対処
  • Your local changes to the following files would be overwritten by merge — checkout / merge / pull 時の同種エラー
  • Cannot checkout: You have unstaged changes — 切替拒否の表現は版やツールで異なる。未commitがあっても衝突しない変更は持ち越せる場合がある

予防策

  • こまめにコミット: WIP コミットでもよいので作業中の変更を残す
  • 作業前に状態確認: git status を習慣化
  • pull の前に commit / stash: 作業中に他の人の変更を取り込む前に整理
  • 自動stashは個別に判断: 旧案内のgit config --global rebase.autoStash trueは全repoへ影響する永続変更なので、診断のために実行しません。必要なら保存を確認した1回のrebaseで--autostashを選ぶ方法がありますが、最後の再適用で競合し得ます。未追跡 / ignored / submoduleの作業まで退避済みとは扱いません。取込完了と再適用完了を別々に確認します

関連記事

保存する対象と再開条件を決める

最初にstatus、未stage差分、stage差分、未追跡、ignoredを別に確認します。ignoredの環境設定や秘密値を「Gitに入っていないから不要」と判断しません。branchで保持できるのはcommitへの参照であり、未commit内容の保存にはなりません。stashも同じディスク上のGitオブジェクトなので外部バックアップの代用ではなく、dropや期限 / gc後の回収は保証できません。

変更を履歴へ残せるなら選択したpathでcommit、履歴へ入れたくなければ範囲を確認したstashや別の保存先、取込み自体を延期するという選択肢があります。秘密値をWIP commitしてしまうより、適切なアクセス制限のある別保存先を選びます。stash -uでもignoredやsubmoduleの作業は別扱いで、pathspec指定や--keep-indexでは変更が残る場合もあります。退避後にstatusで開始条件を確かめます。

読取中心の確認例

Bashでrepoのトップから実行します。diff / ignored名等は秘密情報を含み得るので共有前に伏せます。cleanは-n付きの予定表示だけで実削除しません。

#!/usr/bin/env bash
set -eu
export GIT_OPTIONAL_LOCKS=0
if [ "$#" -ne 0 ] || [ ! -e .git ]; then
    printf '%s\n' 'Run at a worktree root without arguments.' >&2
    exit 2
fi
git status --short --branch --untracked-files=all
git diff --no-ext-diff --no-textconv --
git diff --cached --no-ext-diff --no-textconv --
git ls-files --others --exclude-standard
git ls-files --others --ignored --exclude-standard
git stash list
git clean -n -d
# Inspect only: no stash push/pop/drop, discard, or permanent config change.

stashの再適用を確認する順番

  1. stash listとstash show -p --include-untrackedで保存内容と識別子を確認する。古いGitでは対応オプションをgit help stashで確認する。
  2. rebaseの競合中ならstatusで対象を確認し、編集とadd後に--continue、取りやめるなら--abortを個別に選ぶ。--skipは現在のpatchを除外するので単なるエラー回避に使わない。
  3. rebase完了後にstash apply等を行い、戻った差分・index・未追跡と必要な実行テストを確認する。--indexでも無競合の保証はない。
  4. 競合したpopを繰り返さず、残ったstashと現在の変更を保全して解決する。成功したpopの後に無条件dropしない。

--autostashを使う場合もこの確認は省略できません。rebase自体が成功しても自動stashの再適用が競合することがあります。出力とstatus / stash一覧で処理段階を確認し、再適用競合を理由にもう一度rebaseやabortを機械的に実行しません。

公式資料と検証範囲

2026年10月26日確認:pushのlease / dry-run、init --shared、receive.denyNonFastForwards、stashの保存 / pop / apply、rebaseの中断 / autostash、checkoutのindex参照、resetの範囲、cleanの予定表示、reflogのローカル記録。旧コードは比較資料として保持し、誤コメントは直前で訂正しています。追加例と合成履歴は隔離したローカルrepoで検証し、強制更新はdry-runのみで全ref不変を検査します。実サービスの保護 / hook / 権限、本番復旧、実clean / hard reset、全submodule構成を検証するものではありません。

子ページ

子ページはありません

同階層のページ
  1. fatal: remote origin already exists.
  2. fatal: '~' does not appear to be a git repository
  3. Cannot rebase: You have unstaged changes. Please commit or stash them.
  4. remote: error: denying non-fast-forward refs/heads/master (you should pull first)
  5. error: pathspec ... did not match any file(s) known to git.
  6. The following untracked working tree files would be overwritten by checkout
  7. fatal: Not a valid object name: 'master'.
  8. Unlink of file 'ファイル名' failed. Should I try again? (y/n)
  9. Another git process seems to be running in this repository
  10. error: Your local changes to the following files would be overwritten by checkout:

最近更新/作成されたページ