blogですかい

株式会社Loco Partnersに勤めるエンジニアうちの一人のブログ。仕事、プライベートで学んだことなどを発信し、その内容がたとえ少数でも誰かの役に立ったらなら、それはとっても嬉しいなって

git rmやgit mvした状態をgit stash saveするのは避けたほうが良いかもしれない

git mvしたものをgit stashで保存・復原という操作をして気になったこと

$ git ls-files
hoge

$ git status
On branch master
nothing to commit, working directory clean

$ git mv hoge fuga
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        renamed:    hoge -> fuga


$ git stash save
Saved working directory and index state WIP on master: f93d032 first commit
HEAD is now at f93d032 first commit

$ git stash pop
Removing hoge
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   fuga

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    hoge

Dropped refs/stash@{0} (96680b45ca302e312299cab38c47802c07642913)

git stash save前とgit stash pop後で状態が変わっている!

$ git rm --cached hoge
rm 'hoge'

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        renamed:    hoge -> fuga

↑ファイルhogeをインデックスから削除すると、git stash save前と同じ状態に戻る。

$ git commit -m 'rename hoge to fuga'
[master 8c198ce] rename hoge to fuga
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename hoge => fuga (100%)

$ git rm fuga
rm 'fuga'

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    fuga

$ git stash save
Saved working directory and index state WIP on master: 8c198ce rename hoge to fuga
HEAD is now at 8c198ce rename hoge to fuga

$ git stash pop
Removing fuga
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    fuga

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (d0cca5c61ae3f9af7b1c9c09eb012081f87ffcf2)

git rmでファイルとインデックスを削除してgit stash save、その後git stash popすると、ファイルは消えているがインデックスは残っている。

$ git reset --hard HEAD
HEAD is now at 8c198ce rename hoge to fuga

$ git rm --cached fuga
rm 'fuga'

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    fuga

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        fuga

$ git stash save
Saved working directory and index state WIP on master: 8c198ce rename hoge to fuga
HEAD is now at 8c198ce rename hoge to fuga

$ git stash pop
Already up-to-date!
On branch master
nothing to commit, working directory clean
Dropped refs/stash@{0} (b39c66764d2bf85fa2b5409e31a9d322b0e72c95)

git rm --cachedでインデックスだけ削除しgit stash save、その後git stash popすると、git rm —cachedする前の状態に戻る。

上記の例ではgit stash saveの直後にgit stash popしているので問題は起こらないが、間に捜査を挟むとpop時に衝突が起こる場合もあると思う。
git rmgit mvした状態をstashで保存しておくということは今までしたことが無かったし、今後もすることがそうそう無いとは思うけれど、滅多にしないことだからこそ、気をつけたい。