読者です 読者をやめる 読者になる 読者になる

tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

【git】git stashで変更を一時退避するメモ - error: Your local changes to the following files would be overwritten by checkout:とか言われるとき

はじめに

git stashのメモ。
git stash自体の使い方は、参考になる記事がいっぱいあるので、
使い方の詳細よりはどういうときに使うかのメモ。

あじぇんだ

  1. git stashが必要になる状況をつくって理解する(checkoutのerror
  2. git stashでcheckoutのエラーを回避してみる
  3. git stashの使い方

※ 状況のひとつなだけで他にも必要な状況はあります。

1. git stashが必要になる状況をつくって理解する(checkoutのerror) 

今回の例としてはまず前提としてこれを理解しておくとわかりやすいかとおもいます。

Untrackedなファイル(addがなされていないファイル)は
branchを移動しても引き継がれる

これがどういうことかも流れでやってみます

ブランチ(somebranch)をつくってチェックアウトする

これはまんまですね

$ git branch somebranch
$ git checkout somebranch
somebranchでREADME.mdを編集してからmasterブランチをチェックアウトしてみる

Untrackedなファイル(addがなされていないファイル)なので
masterブランチに切り替えても変更内容が引き継がれます

※ ブランチを確認
$ git branch
  master
* somebranch

※ README.mdを編集する
$ vi README.md
---- vi追記 ----
# git-stash-test
somebranchで修正 ← この行を追加
---------------

※ git statusを見る
$ git status
On branch somebranch
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:   README.md

no changes added to commit (use "git add" and/or "git commit -a")


※ masterブランチに切り替え
$ git checkout master
M   README.md
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

※ README.md見てみる
※ Untrackedなファイルなので変更が引き継がれる
$ vi README.md
---- vi追記 ----
# git-stash-test
somebranchで修正
---------------

※ somebranchにもどっておく
$ git checkout somebranch
somebranchでREADME.mdをgit addしてからmasterブランチをチェックアウトしてみる
※ ブランチを確認
$ git branch
  master
* somebranch

※ git addする
$ git add README.md 

※ git statusを見る
$ git status
On branch somebranch
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README.md


※ masterブランチに切り替え
$ git checkout master
M   README.md
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

※ README.md見てみる
※ Untrackedなファイルなので変更が引き継がれる
$ vi README.md
---- vi追記 ----
# git-stash-test
somebranchで修正
---------------

※ somebranchにもどっておく
$ git checkout somebranch
somebranchでREADME.mdをgit commitしてからmasterブランチをチェックアウトしてみる
※ ブランチを確認
$ git branch
  master
* somebranch

※ git commitする
$ git commit -m 'modify at somebranch'

※ git statusを見る
$ git status
On branch somebranch
nothing to commit, working directory clean

※ masterブランチに切り替え
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

※ README.md見てみる
※ Untrackedなファイルじゃないので変更が引き継がれなくなった
$ vi README.md
---- vi追記 ----
# git-stash-test
---------------

※ somebranchにもどっておく
$ git checkout somebranch
somebranchでREADME.mdをgit commitしてからmasterブランチでREADME.mdを編集してから再度somebranchに切り替える

commit自体は上で行ったので、masterブランチに切り替えてREADME.mdを編集してみます

※ ブランチを確認
$ git branch
  master
* somebranch

※ masterブランチに切り替え
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

※ README.mdを編集してみる
$ vi README.md
---- vi編集 ----
# git-stash-test
masterブランチで編集
----------------

※ somebranchに切り替える
$ git checkout somebranch
error: Your local changes to the following files would be overwritten by checkout:
    README.md
Please, commit your changes or stash them before you can switch branches.
Aborting

ということでエラーになりました。
エラーの内容にもcommit your changes or stashと書いてあるとおり、
stashで回避できそうです。

どういうことか

commitをする前(Untrackedなファイルのまま)だと
master <=> somebranchを切り替えても変更内容が引き継がれました。

somebranchでcommitまでしたのちにmasterに切り替えて編集するとどうなるかを考えてみます。

masterブランチで編集したREADME.mdはUntrackedなファイルなので、
git checkout somebranchした際に変更を引き継ごうとするのですが
somebranchではすでに違う変更がなされているために引き継げず該当のエラーになります。

なので、この場合はエラー内容が下記の通りになっているかとおもいます。

  • masterブランチでcommitしてしまう
    (Untrackedなファイルを引き継がないようにする)
  • stashして一時退避する

2. git stashでcheckoutのエラーを回避してみる

上述の通りこの場合はcommitをすることでも回避できるのですが、
今回はstashについてのメモなのであえてstashで。

※ checkoutしようとしてエラーがでるところから確認
$ git branch
* master
  somebranch

$ git checkout somebranch
error: Your local changes to the following files would be overwritten by checkout:
    README.md
Please, commit your changes or stash them before you can switch branches.
Aborting

※ stashして一時変更を退避する
$ git stash save
Saved working directory and index state WIP on master: b8047df Initial commit
HEAD is now at b8047df Initial commit

※ README.mdの中身を見てみる
※ 変更を退避したのでmasterブランチで行った変更がなくなっている
$ vi README.md
---- vi ----
# git-stash-test
------------

※ checkoutできるようになる
$ git checkout somebranch
Switched to branch 'somebranch'

3. git stashのオプションメモ

作業中のファイルを一旦退避
※ saveは省略可能
$ git stash save
退避した状態を確認
$ git stash list
stash@{0}: WIP on master: b8047df Initial commit
退避した変更内容を確認
$ git stash list -p
stash@{0}: WIP on master: b8047df Initial commit

diff --git a/README.md b/README.md
index 14afcd2..c3f1558 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
 # git-stash-test
-for test repository, about git stash
+masterブランチで編集

上述の流れだと変更してない変更内容もでちゃってますが気にせずにw

退避したファイル名を表示
$ git stash show stash@{0}
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
退避した変更内容を復活
$ git branch
* master
  somebranch

※ stashした後の状態でREADME.mdをみておく
$ vi README.md
---- vi ----
# git-stash-test
------------

※ 退避した変更内容をとりだす
$ git stash pop stash@{0}

※ popしたあとにREADME.mdをみてみる
$ vi README.md
---- vi ----
# git-stash-test
masterブランチで編集
------------

参考

stashについてはこちらが参考になりました。

おわり

stashのコマンドについては調べればいっぱい出てくるし使えるんですが、
どういう状況で必要なの?と聞かれたときに困ったので
その一例メモしてみました。enjoy!