Quick Comparison
HEAD는 현재 작업 기준을 나타내는 ref입니다. 일반 상태에서는 local branch를 따라가고, detached 상태에서는 특정 commit을 직접 가리킵니다. detached 상태의 commit은 즉시 없어지지 않지만 보존 ref가 없으면 나중에 찾기 어려워집니다.
| 상태 | HEAD 대상 | 새 commit 후 할 일 |
|---|---|---|
main을 checkout | refs/heads/main | main tip이 이동 |
| commit/tag를 detach | 특정 commit | 실험을 보존할 branch 생성 |
| 과거 상태 test | 특정 commit | test 뒤 original branch 복귀 |
| release hotfix 시작 | tag의 commit | switch -c hotfix/... |
git status
git switch --detach <commit-or-tag>
# 의미 있는 수정이 생겼다면
git switch -c experiment/from-old-state
git push -u origin experiment/from-old-stateref를 따라가는 HEAD
일반 checkout에서 HEAD는 current branch를 가리키고 branch ref가 current commit을 가리킵니다. 새 commit은 branch tip을 이동시키며 HEAD는 계속 branch를 따릅니다. git branch --show-current, git symbolic-ref --short HEAD, git rev-parse HEAD는 각각 branch name, symbolic ref, resolved commit을 확인하는 명령입니다.
commit hash, remote-tracking ref, tag를 직접 checkout하면 HEAD가 branch ref 대신 commit에 붙을 수 있습니다. git status는 detached 상태를 알려 주며, 과거 release를 build/test하거나 bisect하는 동안에는 정상적인 상태입니다. 문제는 상태 자체가 아니라 그 위에서 만든 valuable commit에 이름을 붙이지 않고 떠나는 경우입니다.
commit을 보존하는 범위
detached HEAD에서 만든 commit은 reflog로 잠시 찾을 수 있지만, reflog retention과 garbage collection에 영구 보존을 맡기면 안 됩니다. 작업을 유지할 거면 git switch -c <branch> 또는 tag로 ref를 만들고, 다른 clone에도 필요하면 push합니다. local branch만 만든 것은 local disk 밖 백업이 아닙니다.
tag는 release 기준점을 고정하는 ref이지 feature branch가 아닙니다. tag에서 hotfix를 시작할 때는 branch를 먼저 만들고 그 branch에서 commit합니다. existing branch로 돌아가기 전 uncommitted change가 있으면 switch가 거부되거나 conflict를 만들 수 있으므로 status와 diff를 먼저 확인합니다.
회수 흐름
의미 있는 detached commit을 만들고 다른 branch로 이동했다면 git reflog로 previous HEAD를 찾아 git switch -c recovered <commit>으로 ref를 붙입니다. reflog가 이미 만료됐거나 object가 pruning된 경우 복구를 보장할 수 없으므로, 발견 즉시 branch와 remote push로 보존 범위를 넓힙니다.
detached HEAD는 오류가 아니라 임시 관찰·실험 상태입니다. 위험은 commit에 branch/tag를 붙이지 않고, reflog를 장기 저장소처럼 믿는 데 있습니다.
참고 링크
3 sources