開発作業をしていて、いくつかファイルを修正後にその開発用のブランチ new-feature で作業しておらず master で作業していたことに気がつきました><。
どうしましょう?
別のフォルダに変更をコピーしておいて、new-feature ブランチを作ってチェックアウト、コピーを被せれば一応解決できそうですけれども。。。
Git で解決する方法を探ってみました。
想定する状況
- new-feature ブランチを作成・チェックアウトしてから行う作業を、master ブランチで行ってしまった。
- まだコミットは 1 度も行っていない。
git checkout を使った方法のポイント
- ただただ、チェックアウトすれば良い。追加したファイルやステージした内容はついてくる。
- 作業内容によってチェックアウト先のファイルが上書きされてしまう場合は、エラーとなってチェックアウトできない。このときに初めて stash の利用を検討すればよい。
$ git checkout master error: Your local changes to the following files would be overwritten by checkout: 1.txt Please, commit your changes or stash them before you can switch branches. Aborting
最初、本投稿は
【Git】コミット前に誤ったブランチで作業していたことに気がついたとき、別のブランチを作って作業フォルダとステージの変更をそのブランチへ移動する方法【git stash】
という問題に対処するために、次から述べる git stash
を使った方法をいきなりやってみていたのでした。役に立つ場面もありますけれども、今回の問題はチェックアウトだけで解決できることに気がつきました。。。
消してしまうのももったいないですし、チェックアウトで対処できなかった場合の解決方法方法として使えますので残しておきますわ♪
git stash を使った方法のポイント
- 作業フォルダ内の、追跡しているファイルのうち変更されたファイルやステージされた変更をスタックに退避できる。
- スタックとは
git stash
で退避されるファイルなどが格納される領域で、永続的に複数格納できる。
あるブランチの変更を隠し、別のブランチに移動して移動先のブランチにそれを書き戻すこともできます。
git コマンド説明
# 追跡しているファイルをスタックに退避 git stash # スタックしている状態のリストを表示 git stash list # 最新のスタックを作業フォルダに適用 git stash apply # 最新のスタックを削除 git stash drop
続いて、git stash
を使ってみましたときのログを掲載いたします。
実践 1. 誤りに気がつく
git status
を見て、誤って master ブランチで作業していたことに気がつきました><。
作業フォルダでファイルを修正したものの、ステージングには追加していない状況ですの。
$ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: bin/SampleExcel.xlsm modified: bin/SampleExcel.xlsm/README.bas no changes added to commit (use "git add" and/or "git commit -a")
実践 2. stash して作業フォルダ状態を一時退避する
$ git stash Saved working directory and index state WIP on master: 3ef4ae7 AAA機能完成のコミット。 HEAD is now at 3ef4ae7 AAA機能完成のコミット。
git status
で作業開始前のコミット状態に戻ったことがわかります。
実際に作業フォルダのファイルを開いてみると、stash 前の状態に戻っていました。
$ git status On branch master nothing to commit, working directory clean
スタック領域に退避されていることも確認できました。
stash 時にコメントをつけなければ、作業開始前のコミットタイトルが設定されるようですの。
stash@{0}: WIP on master: 3ef4ae7 AAA機能完成のコミット。
実践 3. 本来作業を行うべき new-feature ブランチを作り、そこにチェックアウトする
$ git checkout -b new-feature Switched to a new branch 'new-feature'
実践 4. スタックに退避した内容を、new-feature へ適用する
git stash apply
で直近のスタック退避を現在のブランチへ適用します。
apply
ではなく pop
を指定すると、実行後に適用したスタック退避を削除するようです。
$ git stash apply On branch new-feature Changing not staged for commit: (use "git add <file>..." to update what will be committed (use "git checkout -- <file>..." to discard changes in working directory) modified: bin/SampleExcel.xlsm modified: bin/SampleExcel.xlsm/README.bas no changes added to commit (use "git add" and/or "git commit -a")
実行後に git reflog
しましても stash 操作は記録されておりませんでした。git log
でも同様でしたの。
$ git reflog 3ef4ae7 HEAD@{0}: checkout: moving from master to new-feature ... 略 ...
実践 5. 後片付け。スタックを削除する
スタックは明示的に削除しない限り残り続けます。
したがいまして、不要になったスタックは削除いたしましょう。
git stash drop
で直近のスタックを削除します。
$ git stash drop Dropped refs/stash@{0} (fa7b7fc794bff4a1d2411a42d258b8b37f973745)
これで完了です。あとは add したり commit したり push したり merge したり開発を進めればよいですわ♪
補足
git stash
を使わない方法の紹介もございました。
おわりに
チェックアウトしても変更の内容はついてくるということに後で気がつきました。。。こうなりますと stash の使いどきがわからなくなってまいります。。。
複雑なブランチ移動であれば、いったんブランチを作った方が良さそうな気もいたしますし。。。
まだまだ修行が足りていませんの。
以上です。