はじめに
こんにちは!リンクアンドモチベーションの宮田です!昨日ぶりです。
枠が空いていたのでいただきました🙇♂️
本記事はリンクアンドモチベーション Advent Calendar 2024の3日目を担当しています。🎄
git switch main
error: Your local changes to the following files would be overwritten
by checkout:
Please commit your changes or stash them before you switch branches.
Aborting
このエラーに出会ったのがこの記事を書くきっかけです。
このエラーはなんだ?ということで、調べてみると、
現在のブランチに未コミットの変更がある状態で別のブランチに切り替えようとした際に表示されるエラーで、Gitが「現在の変更が失われる可能性があるので処理を中止した」と警告している状況だとわかりました。
では、この状況で、変更を保持したまま、別のブランチにチェックアウトしたい場合はどうしたらいいのでしょうか。
この記事が、僕と同じエラーに出会った一人でも多くの方のお役に立つことを願っております。
【前提】ブランチ切替時の注意点
変更を保持する方法を知る前に、ブランチ切り替え時に知っておきたいことを確認しておきます。
まずはこの記事を確認すると良さそうです。
今回僕が出会ったのエラーは
「移動先のブランチよりも進んだ変更(コミット済)がある+未コミットの変更がある」状態で、ブランチを移動しようとしたため起こったものでした。
変更があってもエラーが発生せずに移動できる場合もあります。(上の記事にあるもう一つのパターン)
ただここで注意が必要です。
例えば、あるブランチで作業している時に、緊急で別の作業が入ってしまったというとき、作業中のブランチ上にまだコミットしていない変更内容などが含まれている状態でブランチを切り替えると、その変更は切り替えた先のブランチに適用されてしまいます。
コミットしてない変更は移動先のブランチに反映される
だからと言って、作業途中の中途半端な状態でコミットをしてしまうと、コミットログが汚くなってしまいますし、どこまでやったか、作業のログがわかりにくくなってしまいます。
それでは困りますね。
とにかく、エラー発生の有無に関わらず、ブランチを移動するときに現在のブランチの状態を保持し、他のブランチに影響させないようにするための手段が欲しいです!
stash(スタッシュ)
そんな時に使えるのが、変更を一時的に退避させて保管する「stash(スタッシュ)」です。スタッシュは「こっそり隠す」という意味があり、作業内容を一時的にコミットせずに保管する機能です。
以下でstashの使い方を確認していきます。
git stash save "○○" -u
スタッシュを作成したいときはこのコマンドを使用します。
git stash save
の後に続けて、スタッシュの名前を指定します。名前は省略できますが、その代わりに自動でコミットIDやコミットメッセージを使った名前が付加されます。
-u
: これはまだステージングされていない変更も含めてstash
するというオプションです。
git stash save "作業途中" -u
Saved working directory and index state On branchD: 作業途中
この時点で未コミット、未ステージングの変更は全てスタッシュの中に保管されVScodeの画面上からは消えます。
git stash list
作成したスタッシュの一覧化して確認できるコマンドです。
git stash list
stash@{1}: On branchD: 作業途中
stash@{2}: On main: 保存
こんな感じで出てきます。
git stash apply
作成したスタッシュを適用する場合は、このコマンドです。
git stash apply # 直前に作成したスタッシュを適用
git stash apply "stash@{n}" # 指定した番号のスタッシュが適用される
git stash apply
をすると、git stash save
したときの状況を復元することが出来ます。
git stash drop
作成したスタッシュを削除するコマンドです。
一度スタッシュを作成すると適用後も残り続けます。
stash@{0}: On main: Change 20
stash@{1}: On main: Change 19
stash@{2}: On main: Change 18
...
stash@{18}: On main: Change 2
stash@{19}: On main: Change 1
直前のスタッシュを削除したいときは git stash drop
を使います。
git stash drop
git stash list
#直前のスタッシュが削除される
stash@{1}: On main: Change 19
stash@{2}: On main: Change 18
...
stash@{18}: On main: Change 2
stash@{19}: On main: Change 1
指定したいときは、apply
と同様です
git stash drop "stash@{n}" # 指定した番号のスタッシュが削除される
git stash clear
もう全部使いません!一個一個消してたら日が暮れるよの場合は git stash clear
で一括削除できます。
git stash clear
git stash list
# なにも表示されない
使うときには慎重になった方がよさそうですね。
これらのstash
コマンドを使って適切にブランチごとの変更を管理していきたいです。
git pullのエラーでも使える!!
ちなみにこの
git stash
→ git stash apply
実はリモートリポジトリからpull
したいときにも使えます。例えば、自分のローカルでの変更をpush
しようとしたとき、リモートが既に更新されていて、ローカルが遅れた状態になっていると、「一度最新の状態をpull
しなさいという」エラーがでます。
git push
! [rejected] branchc -> branchc (non-fast-forward)
error: failed to push some refs to 'https://github.com/ShoyaMiyata/GitGit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
そこでgit pull
を試みようとすると、つぎは
「今のローカルの変更が上書きされちゃうよ。リモートの変更をマージする前にcommit
するかstash
してね」というエラーが出ます。
git pull
From https://github.com/ShoyaMiyata/GitGit
* [new branch] branchc -> origin/branchc
* [new branch] brancha -> origin/brancha
error: Your local changes to the following files would be overwritten by merge:
ABC.rb
Please commit your changes or stash them before you merge.
Aborting
そこで、スタッシュの登場です。
- ローカルの変更を
stash save
で一時的に避難させておいて、 pull
でリモートの状況と同期させた後にstash apply
で変更を復活させ、リモートよりもローカルの方が進んでいる状況を作り出して、git push
する
という流れができます
おまけ gitignore
stashで変更履歴の保持について理解してきましたが、ここで変更履歴を残さない方法を紹介します。
そんな時には、gitignore
が使えます。変更を無視して、変更履歴に表示する追跡対象から除外してくれる機能です。
実装手順
-
.gitignore
ファイルを作成
-
.gitignore
ファイルをステージングしてコミット -
.gitignore
ファイルに無視させたいファイル名やパスを記述
- 無視させたいファイルを確認
色が薄くなっています。この状態だとlog.txt
に変更を加えても変更履歴が追跡されることはありません。
ちなみに.gitignore
ファイルを作成する前の変更履歴は残ってしまうので、別途対応が必要です。
最後に
Gitのブランチ切り替え時に未コミット変更でエラーが発生する原因と解決策を解説しました。解決法としてgit stashで変更を一時退避し、作業を保護する方法を紹介しました。
内容に不備などありましたら、ご指摘ください。
最後までお読みいただきありがとうございました!
ぜひこちらの記事も併せてご覧になってください