Computer >> 컴퓨터 >  >> 프로그래밍 >> 프로그래밍

Git 분리 HEAD(Detached HEAD) 완벽 이해와 복구 방법

Git을 사용하다 보면 '분리된 HEAD(detached HEAD)' 상태를 한 번쯤 마주치게 됩니다. 이 상태가 무엇인지 미리 알아두면 당황하지 않고 대처할 수 있습니다. 분리된 HEAD에서는 커밋하지 않는 것이 좋지만, 실수로 커밋했다면 어떻게 저장할 수 있는지도 함께 살펴보겠습니다.

HEAD 개념 복습

HEAD가 무엇인지 제대로 이해하려면 Git의 트리 구조에 대해 먼저 짚고 넘어갈 필요가 있습니다.

  1. 작업 디렉터리(Working Directory): 작업 트리라고도 하며, 로컬 디렉터리를 의미합니다. git status 명령어로 현재 작업 디렉터리의 상태를 확인할 수 있습니다.
  2. HEAD: 현재 브랜치의 마지막 커밋 스냅샷을 가리키는 포인터입니다. git checkout으로 브랜치를 전환하면 HEAD도 해당 브랜치의 마지막 커밋으로 이동합니다.
  3. 인덱스(Index): 스테이징 영역이라고도 하며, git add로 커밋할 파일을 추가하면 이 인덱스에 등록됩니다.

연결된 HEAD(Attached HEAD) 이해하기

HEAD는 현재 체크아웃한 브랜치의 최신 커밋을 가리킵니다. git status를 실행하면 On branch master처럼 현재 브랜치를 알려주고, git log를 실행하면 다음과 같은 정보와 함께 커밋 히스토리를 확인할 수 있습니다.

commit 38373004b8f651b58cea64cd629e1e2c18c164a0 (HEAD -> master, origin/master, origin/HEAD)
Author: Felipe <email>
Date:   Wed Sep 29 22:57:59 2020 -0500

이제 git checkout development로 development 브랜치로 전환하면 HEAD는 해당 브랜치의 마지막 커밋으로 이동합니다. 이렇게 평소에는 HEAD가 항상 현재 브랜치의 마지막 커밋에 붙어서 우리를 따라다니게 됩니다.

HEAD가 분리되는 경우

HEAD를 분리하는 방법은 몇 가지가 있습니다.

  • git checkout --detach 명령어 사용
  • 커밋 해시로 체크아웃. 예: 앞서 본 커밋이라면 git checkout 38373004b8f651b58cea64cd629e1e2c18c164a0
  • 브랜치 이름 뒤에 ^0 붙이기. 예: git checkout master^0

일부러 HEAD를 분리하고 싶은 경우는 드뭅니다. 가장 흔한 실수는 브랜치로 체크아웃하려다 브랜치 이름 대신 커밋 해시를 입력하는 것입니다.

그럼 HEAD가 분리되면 어떻게 될까요? 다음과 비슷한 경고 메시지를 보게 될 것입니다.

$ git checkout 38373004b8f651b58cea64cd629e1e2c18c164a0
Note: checking out '38373004b8f651b58cea64cd629e1e2c18c164a0'.

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 performing another checkout.

분리된 HEAD 상태에서 변경 사항을 만든 후 git status를 실행하면 다음과 같이 표시됩니다.

HEAD detached at ac63806
nothing to commit, working tree clean

마치 시간 속에 얼어붙은 것처럼 아무리 작업해도 그 결과가 어디에도 기록되지 않습니다. 왜냐하면 HEAD가 특정 브랜치를 가리키고 있지 않기 때문입니다.

반면 이 상태를 활용하면 저장소를 망칠 걱정 없이 과거의 특정 시점을 자유롭게 탐색할 수 있다는 장점도 있습니다.

HEAD 다시 연결하기

먼저 기억해야 할 점은, 분리된 HEAD 상태에 빠지더라도 기존 브랜치는 전혀 영향을 받지 않는다는 것입니다. HEAD를 다시 연결하는 가장 좋은 방법은 새 브랜치를 만드는 것입니다.

간단히 git checkout -b <branch-name> 명령어로 새 브랜치를 생성하면 됩니다.

그렇다면 HEAD가 분리된 줄 모르고 이미 변경 사항을 만들었다면 어떻게 해야 할까요? 이 경우 임시 브랜치를 만든 후, 커밋하려는 대상 브랜치와 병합하면 됩니다. 예를 들면 다음과 같습니다.

git checkout -b temp-branch
git checkout master
git merge temp-branch

이렇게 하면 임시 브랜치의 변경 사항이 master 브랜치에 반영됩니다.

마무리

오늘은 HEAD를 분리하는 방법과 그 후의 대처법을 알아보았습니다. Git 내부 동작에서 HEAD가 무엇인지 이해하면 분리된 HEAD 같은 특수한 상황도 쉽게 파악할 수 있습니다.

또한 분리된 HEAD 상태가 되더라도 너무 걱정할 필요는 없습니다. 다만 HEAD가 브랜치에 연결되어 있지 않으면 변경 사항과 커밋이 어디에도 반영되지 않으므로, 적절히 HEAD를 다시 연결해 주는 것만 잊지 마세요.