git pull 実行時に「error: cannot pull with rebase: You have unstaged changes. Please commit or stash them.」が表示された。原因として正しいものはどれか?
解説
正解は「ワーキングツリーにステージしていない変更が残っている」です。git pull --rebase(またはpull.rebase = trueの設定下でのgit pull)は、リベース処理の前にワーキングツリーがクリーンであることを要求します。編集中のファイルがあると、リベース中にそれらが巻き込まれて壊れる危険があるため、Gitが安全弁として止めてくれている状態です。なぜその答えなのかリモートリポジトリが削除されている — その場合はfatal: Could not read from remote repositoryやrepository not foundといったネットワーク系のエラーになります。エラーメッセージがまったく違います。ローカルブランチがリモートより進んでいる — これはpullしても単に「Already up to date.」と表示されるか、普通にマージ/リベースが走るだけです。ローカルが先行していること自体はエラーになりません。SSHキーの認証失敗 — 認証エラーはPermission denied (publickey)として表示されます。unstaged changesとは無関係です。「git pull rebase できない」「unstaged changes 意味」で検索してこのエラーに辿り着く人は多いですが、要はGitが「手元の作業を先に片付けてからにして」と言っているだけです。背景・仕組みGitのワーキングツリーには3つの状態があります。untracked(Gitが追跡していない新規ファイル)、unstaged(追跡済みだがgit addされていない変更)、staged(git add済みでコミット待ち)です。リベースはコミット履歴を書き換える操作なので、未確定の変更が作業ディレクトリに散らばっていると整合性が取れなくなります。そのためGitはリベース開始前にクリーンな状態を強制します。一方、通常のgit pull(マージ戦略)はunstaged changesがあっても競合しないファイルなら通ることがあります。git pull mergeとrebaseの違いとして、rebaseの方が作業ディレクトリの状態に厳格だと覚えておくとよいでしょう。よくあるミスとエラーこのエラーでありがちなのが「変更した覚えがないのにunstagedと言われる」パターンです。原因の多くは改行コードの自動変換です。# core.autocrlfが有効だと、チェックアウト時にLF→CRLFに変換され # Gitはそれを「変更あり」と認識する git config --global core.autocrlf input # macOS/Linux推奨 git config --global core.autocrlf true # Windows推奨もう一つは、git stashしたつもりが新規ファイル(untracked)が残っているケースです。git stashはデフォルトでuntrackedファイルを含みません。# untrackedファイルもまとめてstashしたい場合 git stash -u実務での活用例作業途中でpullしたいとき — まだコミットしたくない変更がある場合はgit stashで一時退避→git pull→git stash popが定番の流れです。git stash git pull git stash pop # コンフリクトが出たら手動で解消するautostash設定 — 毎回stashするのが面倒なら、以下の設定でrebase時に自動stash→自動popしてくれます。チーム内で設定を揃えておくとトラブルが減ります。git config --global rebase.autoStash trueコミットしてからpull — 中途半端でもいいのでgit commitしてからpullし、後でgit commit --amendやgit rebase -iで整えるという手もあります。stash popでコンフリクトするよりこちらの方が楽な場面もあります。