TrotRanking
IT Engineering

Git 하드 리셋 사고 대처법: Reflog를 이용한 고아 커밋 및 손상 레포지토리 완벽 복구 실전기

김민준 · IT 시스템 엔지니어
소프트웨어 개발 프로젝트를 관리하면서 Git만큼 우리에게 강력한 통제권과 두려움을 동시에 안겨주는 형상 관리 시스템도 드물 것입니다. 저 역도 과거 핵심 코어를 개발하던 중 복잡한 병합(Merge) 충돌 과정을 해결하려다가 순간적인 판단 착오로 `git reset --hard HEAD~3` 이라는 치명적인 파괴 명령어를 콘솔에 날린 적이 있습니다. 터미널 창에서 명령어 실행 엔터키가 눌리는 순간, 작업 트리에 마운트되었던 변경 사항과 지난 3번의 주요 커밋들이 제 로컬 파일 시스템에서 흔적도 없이 증발해버렸습니다. 등줄기에 식은땀이 흐르는 순간이었지만, Git의 내부 아키텍처 원리를 침착하게 되짚어본 끝에 저는 수천 줄의 코드를 단 한 글자의 유실도 없이 완벽하게 복원해 낼 수 있었습니다. 초보자들은 코드 파일이 영구적으로 지워졌다고 생각하고 절망에 빠져 새로 코딩을 시작하지만, Git은 실질적으로 가비지 컬렉터(Garbage Collector) 툴이 강제로 내부 시스템을 밀어버리기 전까지는 데이터 스냅샷을 삭제하지 않는 매우 방어적인 구조로 설계되어 있습니다. 이 숨겨진 생명줄과도 같은 보험 시스템이 바로 'Reflog(Reference Log)' 메커니즘입니다. 내부 통제 좌표 기록 시스템, Reflog의 이해 Git은 단순한 소스 파일의 변경 텍스트를 저장하는 것이 아니라 프로젝트 디렉토리 내부 상태의 완벽한 1:1 불변 스냅샷(Snapshot) 객체 단위로 저장소를 굴립니다. 그리고 사용자가 commit을 찍거나 심지어 reset, checkout 시 브랜치를 이동하는 모든 찰나의 '행위' 그 자체를 .git 백그라운드 폴더 내부에 타임라인 로그 형태로 조용히 적어 내려갑니다. 이것이 Reflog의 핵심입니다. 눈에 보이는 브랜치 포인터에서 우리 코드가 사라졌을지언정, 해당 코드가 뭉뚱그려진 해시 블록 덩어리인 객체 상태로 저장소 저 멀리 고립되어 일명 '고아 커밋(Orphan 혹은 Dangling Commit)' 상태로 남아 숨을 쉬고 있는 것입니다. 숨겨진 로그 호출과 헤드 포인터 역산출 명령 프롬프트에서 즉각적으로 `git reflog` 명령어를 타격해 봅니다. 복잡한 난수 문자열 형태의 로그들이 역순으로 와이파이 파도처럼 출력되는 것을 볼 수 정입니다. 로그의 내용을 면밀히 분석하다 보면, 제가 치명적인 하드 리셋 명령을 날리기 바로 직전의 헤드 좌표, 예를 들어 `HEAD@{1}: commit: 로그인 Auth 인증 모듈 로직 추가 완료`라는 내용과 함께 짧게 줄여진 SHA-1 헥스 코드(예: `a1b2c3d`)가 버젓이 기록되어 있는 부분을 발견하게 됩니다. 이 헥스 코드가 바로 허공에 떠도는 제 소중한 레포지토리 객체 좌표계입니다. 이 해시 값을 복사한 뒤, 다시 `git reset --hard a1b2c3d` 혹은 안전하게 별도 브랜치로 격리시키기 위해 `git checkout -b rescue-branch a1b2c3d` 명령어를 입력합니다. 실행 버튼이 떨어지는 찰나의 순간, 작업 트리 내부로 수 시간 동안 정성들여 짰던 코드 파일들이 마치 시간 여행을 마친 것처럼 완벽한 구조의 파일 트리를 그리며 디렉토리 내부로 복원됩니다. fsck를 통한 객체 전수 검사와 로우 레벨 데이터 포렌식 만일 Reflog 기록의 30일 유효 기간마저 지나 만료되어 삭제된 악조건이라면 포기해야 할까요? 그렇지 않습니다. 이때는 Git 내부 시스템을 해부하는 로우 레벨 검증 명령어인 `git fsck --lost-found`를 동원해야 합니다. 이 명령은 브랜치나 태깅 포인터가 연결되지 않고 부유하고 있는 모든 뎅글링 블록 파일 객체(Dangling Blob/Tree/Commit) 단위의 해시들을 모조리 텍스트로 토해냅니다. 토해낸 수많은 SHA-1 해시값들을 하나하나 복사하여 `git show` 명령어 뒤에 붙여 넣어가며 터미널 상에서 Diff 코드를 열람하다 보면 분명 영영 잃어버릴 뻔했던 여러분의 코드 변경 지점을 찾아낼 수 있습니다. 오류로 소스를 날렸을 때의 즉각적인 터미널 통제권과, 이러한 구조적인 객체 보존 스케줄링 메커니즘을 숙지하는 것. 이것이야말로 겉핥기식의 푸시와 풀(Pull) 명령어를 넘어서는 마이너하지만 가장 폭발적으로 유용한 고급 SCM 엔지니어링 생존 기술임을 실무를 통해 뼈저리게 체감하고 있습니다.