detached HEAD랑 attached HEAD 상태에 대해 간단하게 알아봅시다.

 


 먼저, 현재 HEAD의 상태를 보겠습니다.

 

 현재 HEAD는 refs/heads/stage를 가리키고 있습니다. 그리고 refs/heads/stage는 606d53.. 커밋을 가리키고 있습니다. 그런데, 여기서 git checkout HEAD~1을 해 보겠습니다. 어떻게 바뀔까요?

 

 

 안내가 뜨면서 detached HEAD state 라는 상태가 되었다는 문구가 뜨게 됩니다. 그리고 아래와 같은 문구도 뜨게 되는데요.

 

 

 현재 retain commit에서 new branch를 생성하고 싶으면, git switch -c BRANCH1 이렇게 생성해라. 라고 되어 있어요. 그리고, 현재 HEAD는 cd8c1c5를 가리키고 있다고 되어 있는데요. 자. 그러면, git checkout HEAD~1을 적용하기 전 상태는 attached HEAD 상태라는 것을 쉽게 알 수 있어요. 왜냐하면, 해당 명령어를 적용한 후에, detached HEAD가 되었기 때문입니다.

 

 

 이제 상태를 봅시다. stage는 stage second를 가리키고 있는데, HEAD는 stage first를 가리키고 있어요.

 

 

보면 stage가 가리키는 commit하고, HEAD가 가리키는 commit하고 다르다는 것을 볼 수 있어요.

 

 


 이 상황을 다시 그림으로 나타내면 아래와 같아요.

 

 

 먼저 git checkout HEAD~1을 하기 전에는 git checkout stage를 했습니다. 그리고 계속 commit을 쌓아나갔습니다. 이 때에는 브랜치 stage를 체크아웃 한 시점에, 이미 branch stage를 참조하고 있었어요. 그래서 attached라고 해요. stage 브랜치가 가리키는 커밋하고, HEAD가 가리키는 것이 같았습니다. 그런데, 제가 HEAD를 이전 커밋으로 돌렸습니다.

 

 

 이 경우, 브랜치를 가리키는 것이 아니라 커밋을 가리키게 됩니다. 사실, 문서에는 name이 refs/heads 에 있는 경우 branch를 참조한다 되어 있어요. 그게 아니라면 commit을 참조한다고 되어 있는데요.

 

 

 제 경우, refs/heads에 master, stage, stage2가 있었습니다. 그래서 git checkout stage를 하면 stage 브랜치가 참조되는데요. 그렇지 않고 git checkout HEAD~1을 입력했다면 있는 브랜치는 아닙니다. 그러면 1개 전으로 돌아간 게 valid한 커밋인지 보는데, 유효한 커밋이였기 때문에, commit을 참조하게 된 것입니다. 이 상태를 detached라고 합니다. 이 상태에서 명령어 git switch -c stage2를 입력하면 어떻게 될까요?

 

 

 새롭게 stage2가 stage first 커밋으로부터 분기되게 됩니다. 그 상태에서 stage2에 커밋을 하나 날리면, 위와 같이 바뀌게 됩니다. 결국 우리는 stage 브랜치의 최신 커밋에서 1개 전 커밋으로부터 분기를 한 셈이 되겠습니다.

 

 


 stage2 브랜치의 최신 커밋에서 분기된 stage3 브랜치는 위와 같습니다. 이 상태에서 HEAD를 1개 전 커밋으로 이동시키면 stage2 브랜치의 HEAD와 가리키는 커밋이 같습니다.

 

 git checkout HEAD~1을 날리면 어떤 상태가 될까요? HEAD가 stage2의 HEAD랑 같은 곳을 가리켜서 attached HEAD가 될 거 같지만, 해당 명령어를 수행한 시점에서 detached가 됩니다. 왜냐하면 HEAD~1이 refs/head에 없는데, 1개 뒤로 돌아가는 커밋이 유효한 것이기 때문입니다.