はじめに
git stash
でファイルを退避させた際の挙動について調べました。
Gitオブジェクトの話が出てきますので、前回の記事もご覧ください。
https://qiita.com/k-yaina60/items/4020a19e4adfab01a895
git stash
とは
gitでファイルを管理していると、編集したファイルをコミットせずに一時的に退避させておきたいということが結構あります。
(別の作業が割り込みで入って、ブランチを切り替える必要がある等)
この時、git stash
を実行すると編集したファイルを退避させることができます。
$ git stash
退避したファイルを戻すにはgit stash pop
を実行します。
$ git stash pop
stashの正体
stashを行うと.git/refs/stash
ファイルが作られます。
このファイルの中身を確認するとGitオブジェクトへのポインタであることがわかります。
$ cat .git/refs/stash
dbbfad1f96c78436c6ef388635fdb579e1bab496
次にこのGitオブジェクトの中身を確認します。
$ git cat-file -p dbbfad1f96c78436c6ef388635fdb579e1bab496
tree 9b2cc9bfc2122829051d130bae10851ab0045ff5
parent 7bc3c78b0bed6a41f110b143e71de4e2de9937a0
parent c7db2bc3cc5c92b19e5fbf83b8bba5819a400c0c
author Test User <test_user@example.com> 1683645430 +0900
committer Test User <test_user@example.com> 1683645430 +0900
WIP on main: 7bc3c78 First commit
stashの正体はcommitオブジェクトです。
そのため編集したファイルはblobオブジェクトとして.git/objects
以下に保存されています。
また、stashするとcommitオブジェクトは2つ作成されます。
例えばブランチの最新コミットAでstashするとコミットB、Cが作成されます。
コミットBでは作業中のindexファイルの状態が保存されます。
つまり、コミットBでステージングされた作業中のファイルが管理されています。
コミットCではステージングしてない作業中のファイルが管理されています。
.git/refs/stash
はコミットCのハッシュ値を指しています。
コミットせず退避させたい時に使うstashですが、実はコミットされていたのです。
ただし、ブランチのハッシュ値は更新されないのでブランチ自体には影響を与えません。
stashが複数ある場合
.git/refs/stash
に最新のstashのハッシュ値しか保存されません。
stashの一覧は.git/logs/refs/stash
に保存されています。
$ cat .git/logs/refs/stash
0000000000000000000000000000000000000000 dbbfad1f96c78436c6ef388635fdb579e1bab496 Test User <test_user@example.com> 1683645430 +0900 WIP on main: First commit
dbbfad1f96c78436c6ef388635fdb579e1bab496 293e3cea4db140399c95ec6e52c489294ab3171b Test User <test_user@example.com> 1683701208 +0900 WIP on main: First commit
まとめ
stashしたファイルはコミットして保存されている。(保存場所は.git/objects
)
参考文献