detached HEAD, 분리된 헤드, git switch | 커밋했는데 브랜치에 안 남으면?
detached HEAD는 지금 커밋이 브랜치에 안 붙은 상태입니다. 커밋을 더 만들기 전에 git switch -c로 이름을 붙이면 그 커밋이 남습니다. 이미 이동했다면 reflog에서 해시를 찾아 브랜치를 엽니다. 갈라진 pull, 푸시 거절과는 다른 줄입니다. Git, 태그, 해시, 한국 1인 개발. 2026년 10월 문서.
detached HEAD는 지금 커밋이 어떤 브랜치에도 안 붙은 상태입니다. git status 첫 줄이 HEAD detached at 이면, 새 커밋을 더 만들기 전에 그 자리에서 브랜치를 하나 여세요.
해시나 태그를 git checkout으로 연 뒤 고친 파일을 커밋하면, main으로 돌아가는 순간 그 커밋이 브랜치 목록에서 사라집니다. 1인으로 핫픽스를 해시 위에서 하면 푸시한 줄 알고 노트북을 덮기 쉽습니다.
커밋이 이미 있으면 git switch -c로 이름을 붙이고, 아직 커밋이 없으면 원래 브랜치로만 돌아가면 됩니다. 갈라진 pull 메시지와는 다른 줄입니다. 근거는 git checkout의 Detached HEAD입니다.
상태 첫 줄이 분리라고 하면
HEAD가 브랜치 이름이 아니라 커밋을 직접 가리키는 상태입니다.
보통 브랜치에 있으면 HEAD는 refs/heads/main 같은 이름을 따라갑니다. 새 커밋을 하면 그 이름이 앞으로 움직입니다. 분리되면 HEAD가 해시만 가리킵니다. 그 위에서 만든 커밋은 브랜치 이름에 연결되지 않습니다.
git status가 HEAD detached at 1a2b3c4 또는 HEAD detached from main이라고 찍습니다. 프롬프트에 (HEAD detached)가 붙는 터미널도 있습니다. 이 한 줄을 보기 전에 커밋을 더 쌓지 마세요.
태그를 열었거나, 릴리스 해시를 그대로 checkout 했거나, git switch --detach를 썼을 때 이 상태가 됩니다. 버그 재현을 위해 옛 커밋을 연 것까지는 괜찮습니다. 그 자리에서 고쳐서 커밋하는 순간부터가 이 글의 장면입니다.
본선 이름 없이 갈라진 선로 위에 커밋을 두면, 다시 본선으로 돌아올 때 그 칸이 목록에서 빠진다
커밋이 이미 있으면 이름부터
그 커밋 위에 브랜치를 만들면 해시가 이름에 붙습니다.
순서가 중요합니다. git switch main을 먼저 하면, 방금 만든 커밋은 어떤 이름도 없이 남습니다. 브랜치를 먼저 만들면 그 이름이 지금 HEAD를 붙잡습니다. 그 다음에 main으로 돌아가 머지하거나, 그 브랜치만 푸시하면 됩니다.
1인 저장소에서 핫픽스를 바로 main에 올리고 싶으면, 브랜치를 만든 뒤 main이 그 커밋의 조상인지 확인하고 fast-forward 머지를 합니다. main이 이미 앞으로 갔으면 머지 커밋이 생기거나, 겹치면 충돌이 납니다. 충돌은 파일을 연 뒤에 고칩니다. 분리된 상태에서 충돌을 풀려고 reset 하지 마세요.
아직 푸시 전이면 원격은 모릅니다. 이름만 붙여도 로컬에는 남습니다. 푸시는 git push -u origin 브랜치이름으로 그 이름을 올립니다. HEAD를 그대로 푸지하면 원격에도 브랜치가 안 생깁니다.
커밋을 브랜치로 고정한 뒤 main에 붙이기
git status
git switch -c rescue/detached-fix
git switch main
git merge --ff-only rescue/detached-fix
# ff가 거절되면 충돌 파일을 보고 merge를 이어간다
# 옛 git은 git checkout -b rescue/detached-fix 가 같은 역할이다
아직 커밋이 없으면 스위치만
커밋을 안 만들었다면 원래 브랜치로 돌아가도 해시가 버려지지 않습니다.
작업 트리의 수정은 브랜치에 안 묻어 있습니다. 겹치는 파일이 없으면 git switch main이 그 수정을 들고 브랜치로 옵니다. 그 다음에 평소처럼 커밋하면 main 위에 쌓입니다.
스위치가 거절하면, 수정 중인 파일을 들어오려는 브랜치가 같이 건드리는 경우입니다. 그때는 커밋하거나 stash 한 뒤에 이동합니다. stash로 치우는 순서는 로컬 변경 덮어쓰기 글과 같습니다. 분리된 HEAD라는 이유만으로 stash가 필수는 아닙니다.
파일을 버리고 깨끗이 돌아가려면 git restore로 그 경로만 되돌린 다음 스위치합니다. 전체 작업 트리를 한 번에 지우는 명령은 이 상태의 첫 수정이 아닙니다.
커밋 없이 원래 브랜치로
git status
git switch main
# 수정이 따라온다. 겹치면 커밋하거나 stash 한 뒤 다시 switch
이미 main으로 돌아왔다면 | git reflog에서 방금 HEAD였던 해시를 찾고, 그 해시에서 git switch -c로 이름을 붙입니다. 도달하지 않는 reflog 기본 보관은 30일입니다.
노트북을 덮기 전에 status 첫 줄이 브랜치 이름인지 확인한다
태그와 해시를 열면 분리된다
브랜치 이름이 아닌 대상은 HEAD를 분리합니다.
git switch --detach v1.2.0과 git checkout 1a2b3c4은 둘 다 그 커밋을 직접 가리킵니다. 릴리스 태그를 읽어 보기만 할 때는 편합니다. 고친 내용을 남기려면 그 자리에서 브랜치를 엽니다. 태그 자체는 움직이지 않으므로, 태그에 커밋이 덮어씌워지지는 않습니다. 대신 새 커밋이 태그 이름 밖에 생깁니다.
git switch -는 직전 위치로 돌아갑니다. 직전이 분리된 해시였으면 다시 분리됩니다. 목적지 이름을 적는 편이 안전합니다. git switch main처럼요.
원격 추적 브랜치를 직접 열어도 분리될 수 있습니다. origin/main은 로컬 브랜치가 아닙니다. 그 위에 커밋하지 말고, 로컬 main을 만들거나 이미 있는 main으로 스위치하세요.
한국 시간으로 밤늦게 옛 배포 지점을 열어 고치고, 본선으로 돌아온 뒤에야 그 커밋이 목록에 없는 걸 알게 됩니다. 이름은 이동하기 전에 붙여야 합니다. 이미 돌아왔다면 기록에서 직전 지점을 찾아 이름을 새로 엽니다. 읽기만 한 표식은 그대로 두고, 고친 내용이 있을 때만 선을 하나 만듭니다. 원격에 올리기 전에 지금 선 곳이 선 이름인지도 한 번 더 봅니다.
합치는 방법을 묻는 문장과, 지금 선 곳이 이름 밖에 있다는 문장은 다음 명령이 다릅니다. 파일 수정이 아직 기록 전이면 원래 선으로 돌아가 거기서 기록하면 됩니다. 수정이 겹쳐 이동이 거절되면 그 파일을 잠시 치운 뒤에 이동합니다. 치운 내용을 되돌리기 전에, 이동이 끝났는지 상태 첫 줄을 다시 읽으세요. 첫 줄이 선 이름이면 그 위에 기록을 남기면 됩니다.
갈라진 pull과는 다른 줄
합치는 방법을 묻는 문장과, 브랜치에 안 붙은 상태는 다음 명령이 다릅니다.
갈라진 브랜치는 로컬 main과 원격 main이 서로 다른 커밋을 가진 채 git pull을 했을 때입니다. 설정으로 ff, rebase, merge 중 하나를 고릅니다. detached HEAD는 pull 설정과 무관하게, 지금 선 곳이 브랜치가 아니라는 상태입니다.
커밋하지 않은 수정 때문에 머지가 멈추는 문장은 overwritten by merge입니다. 작업 트리를 치운 뒤의 이야기이고, HEAD가 분리됐는지는 status 첫 줄로 따로 봅니다.
보이는 문장
의미
먼저
HEAD detached at
브랜치 밖에 서 있음
커밋이 있으면 switch -c
divergent branches
로컬과 원격 이력이 갈라짐
ff, rebase, merge 중 하나
would be overwritten by merge
커밋 안 된 수정이 겹침
stash 또는 restore
이미 브랜치를 버리고 이동했다면 git reflog가 직전 HEAD를 보여 줍니다. git switch -c rescue/detached-fix 해시로 그 칸에 이름을 붙이면 다시 브랜치가 됩니다.