HEAD, tag들의 커밋 해시값을 저장하는 refs 폴더
앞서 git의 HEAD와 tag에 대해 보았다. 이 값들은 특정 커밋들을 가리키는 포인터들로 특정 커밋의 해시 값을 가리킨다. 이 해시 값들을 저장하는 위치가 바로 refs폴더이다.
따라서 refs 폴더 내부를 보면 다음과 같이 출력된다.
$ ls .git/refs
heads stash tags
refs 폴더 내부에는 heads 폴더와 tags 폴더가 있다. 이 중 heads 폴더 내부에는 브랜치별로 파일이 존재한다. 이 파일들 각각 내부에는 해시값이 저장되어 있다.
$ ls .git/refs/heads
feature-layout feature-view main
실제로 뜯어보면 다음과 같이 나오며 이 값은 main 브랜치의 HEAD 커밋 해시값과 일치한다.
$ vim .git/refs/heads/main
f0cdce562bef70fed30f392a18c82543aa2f126b
tags 폴더에도 tag 별로 파일이 만들어져 있으며, 해당 파일 내부에는 해당 tag들이 포인팅하는 커밋 해시값이 저장된다.
refs 폴더 내부의 stash 파일
눈썰미가 좋은 사람이라면 위에서 refs폴더 내부에 heads, tags 뿐 아니라 stash 또한 있는 것을 발견했을 것이다. 이 stash는 heads와 tags와 다르게 폴더가 아니라 파일이다.
많은 사람들이 stash가 커밋과 다른 방식으로 저장되는 것으로 생각하지만, stash는 실제로는 커밋을 생성해 격리된 브랜치에 저장한다. 따라서 stash를 수행할 때마다 stash에 해당하는 커밋 값이 생성된다.
따라서 stash 파일 내부에는 커밋 해시값이 여러개 있는데 이 값은 바로 stash 됐을 때 커밋을 생성해 파일들을 저장해놓은 것이다. stash는 이전 글에서 확인했듯이 계속 쌓이게 되는데 이 중 가장 마지막 stash된 파일들이 저장된다.
$ vim stash
1dd603dc5523d17d57c13dc444fc3c5aa27b217d
따라서 stash에서 생성된 커밋에 대한 checkout을 수행하면 다음과 같이 detached HEAD를 참조하고 있다는 결과가 나온다. detached HEAD란 특정 브랜치의 HEAD가 아닌 커밋을 참조하고 있는 상태를 뜻한다.
$ git checkout 1dd603dc5523d17d57c13dc444fc3c5aa27b217d
Note: switching to '1dd603dc5523d17d57c13dc444fc3c5aa27b217d'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD의 현재 위치는 1dd603d WIP on main: f0cdce5 merge commit
이 커밋에서의 작업은 깃 내부지만 브랜치에서의 작업이 아니다. 만약 이 stash 파일 커밋에 대한 브랜치를 생성하고 싶다면 git switch -c [branch name] 을 통해 새로운 브랜치를 만들어내야 한다.