HEAD는 일반적으로 이름이 붙여진 branch를 참조합니다(예: master).
참조하는 동안, 각 branch는 특정 commit을 참조합니다.
태그가 붙어있는 b commit, mater branch가 체크아웃되어있는 3개의 commit으로 구성된 저장소 예시를 살펴보겠습니다.
이 상태에서 commit이 만들어질 때, branch는 새로운 commit을 참조하게 됩니다. 구체적으로는 git commit이 commit c가 부모인 새로운 commit d를 만들면 master branch는 새로운 commit d를 참조하게 됩니다.
HEAD는 여전히 master branch를 참조해서 간접적으로 현재는 commit d를 참조하고 있습니다.
이러한 특징은 이름이 붙여진 branch의 마지막 commit이 아닌 commit에 체크아웃 할 수 있고, 심지어 이름이 붙여진 branch가 참조하지 않는 새로운 commit을 만들 수 있다는 점에서 때때로 유용합니다. commit b로 체크아웃 했을 때 어떤 상황이 발생하는지 보겠습니다.(체크아웃에는 두 가지 방법이 있습니다)
둘 중 어떤 체크아웃 명령어를 사용했더라도, HEAD는 현재 직접적으로 commit b를 참조하고 있는 것을 볼 수 있습니다. 이러한 상태를 detached HEAD 라고 합니다. 간단히 말해 HEAD는 이름이 있는 branch를 참조하는 것이 아닌(반대로) 특정 commit을 참조하고 있다는 것을 의미합니다. 이 상태에서 commit을 생성하면 어떻게 되는지 살펴보겠습니다.
현재 새로운 commit e가 생성되었고, 오직 HEAD만 이 commit을 참조하고 있습니다. 물론 이 상태에서 다른 commit 추가할 수도 있습니다.
이외에도 모든 일반적인 Git 조작을 수행할 수 있습니다.
하지만, 여기서 master branch로 체크아웃을 하면 어떤일이 발생하는지 살펴보겠습니다.
여기서 주의깊게 봐야하는 부분은 commit f를 참조하는 요소가 없다는 것입니다. 심지어 commit f(그리고 부모 commit e)는 가비지 콜렉션의 프로세스 루틴에 의해 삭제됩니다. 만약 아직 commit f 에서 벗어나지 않은 상태라면, 아래와 같은 명령어로 참조를 생성할 수 있습니다.
$ git checkout -b foo #(1)
$ git branch foo #(2)
$ git tag foo #(3)
(1)은 commit f를 참조하는 새로운 branch foo를 만들어 HEAD가 branch foo를 참조하도록 업데이트합니다. 다시 말해 이 명령어 이후로 더 이상 detached HEAD 상태가 아니게 됩니다.
(2)는 이와 유사하게 commit f를 참조하는 새로운 branch foo를 만들지만 HEAD는 분리된 상태로 둡니다.
(3)은 HEAD는 분리된 상태로 두고 commit f를 참조하는 새로운 tag foo를 만듭니다.
만약 commit f를 이미 벗어난 상태라면, 먼저 해당 commit 객체의 이름을(전형적으로 git reflog를 이용하여) 복구하고 해당 commit에 대한 참조를 생성합니다. 예를 들어, HEAD가 참조하는 마지막 두개의 commit을 보기 위해서, 아래의 명령어를 사용할 수 있습니다.
$ git reflog -2 HEAD # or
$ git log -g -2 HEAD
간단 명료하게 작성된글 잘 읽고 갑니다! 깃 공부중에 새로운 개념을 만나서 이해가 잘 안됐는데 한 번에 이해했습니다. 감사합니다!