손상된 Git 저장소 복구 방법

발행: (2026년 3월 30일 AM 06:20 GMT+9)
15 분 소요
원문: Dev.to

Source: Dev.to

손상된 Git 저장소 복구하기

Git 저장소가 손상되면 git statusgit log 같은 기본 명령조차 제대로 동작하지 않을 수 있습니다. 이 글에서는 흔히 발생하는 손상 상황을 진단하고, 데이터를 최대한 복구하는 방법을 단계별로 설명합니다.


1️⃣ 증상 확인

다음과 같은 오류 메시지를 보게 된다면 저장소가 손상된 것일 가능성이 높습니다.

  • fatal: bad object <SHA>
  • error: object file ... is empty
  • git fsck 실행 시 “corrupt” 혹은 “missing” 객체가 보고됨

2️⃣ 저장소 무결성 검사

먼저 Git이 제공하는 내장 검사 도구를 사용해 현재 상태를 확인합니다.

git fsck --full

이 명령은 모든 객체와 참조를 검사하고, 손상된 파일이나 누락된 객체를 보고합니다. 출력 결과를 메모해 두면 이후 복구 단계에서 어떤 객체가 문제인지 파악하는 데 도움이 됩니다.


3️⃣ 최근 커밋 복구 (reflog 활용)

Git은 reflog 를 통해 브랜치와 HEAD가 가리킨 최근 위치를 기록합니다. 손상된 HEAD를 복구하려면 다음을 실행해 보세요.

git reflog

출력된 리스트에서 정상적인 커밋 SHA‑1 을 찾은 뒤, 해당 커밋으로 HEAD를 재설정합니다.

git reset --hard <good‑commit‑sha>

4️⃣ 손상된 객체 복구

git fsck 결과에 “missing” 혹은 “corrupt” 객체가 표시된 경우, 가능한 복구 방법은 두 가지입니다.

a. 로컬 백업에서 복원

  • .git/objects/ 디렉터리 안에 해당 SHA‑1 로 시작하는 파일이 있다면, 백업에서 복사해 넣습니다.
  • 파일 권한이 올바른지 확인하고, git fsck 를 다시 실행해 정상 여부를 검증합니다.

b. 원격 저장소에서 재받기

원격에 동일한 커밋이 존재한다면, 손상된 객체를 다시 받아올 수 있습니다.

git fetch --all
git checkout <branch>

필요한 경우, 손상된 브랜치를 삭제하고 새로 체크아웃합니다.

git branch -D <branch>
git checkout -b <branch> origin/<branch>

5️⃣ 저장소 정리 (garbage collection)

복구가 끝났다면, 불필요한 파일과 dangling 객체를 정리해 저장소를 최적화합니다.

git gc --prune=now --aggressive

이 명령은 남아 있는 모든 dangling 객체를 제거하고, pack 파일을 재작성합니다.


6️⃣ 최종 검증

다시 한 번 무결성을 확인합니다.

git fsck --full

에러가 전혀 나오지 않으면 복구가 성공한 것입니다. 이제 정상적으로 커밋, 푸시, 풀 등을 사용할 수 있습니다.


📌 요약

단계핵심 명령목적
1. 증상 확인오류 메시지 파악
2. 무결성 검사git fsck --full손상된 객체 탐색
3. reflog 복구git refloggit reset --hard최근 정상 커밋 복원
4. 객체 복구백업 복원 / git fetch누락/손상된 객체 복구
5. 정리git gc --prune=now --aggressive저장소 최적화
6. 최종 검증git fsck --full복구 완료 확인

🙋‍♂️ 추가 팁

  • 정기적인 백업: .git 디렉터리를 외부 저장소에 주기적으로 복제해 두면 손상 시 복구가 훨씬 쉬워집니다.
  • 작업 전 git status: 작은 이상 징후라도 바로 확인하면 큰 손상을 예방할 수 있습니다.
  • 읽기 전용 미러: 중요한 프로젝트는 읽기 전용 미러 저장소를 유지해 두면, 원본이 손상돼도 바로 복제해 사용할 수 있습니다.

손상된 Git 저장소는 처음엔 겁이 날 수 있지만, 위 단계들을 차근차근 따라가면 대부분의 경우 데이터를 복구하고 정상적인 작업 흐름으로 돌아올 수 있습니다. 문제가 지속된다면, 손상된 레포지토리를 새로 클론하고, 로컬에서만 사용하던 임시 파일이나 패치를 다시 적용하는 방법도 고려해 보세요. Happy coding!

1. 실제로 무엇이 깨졌나요?

Git은 모든 것을 .git/objects/ 안의 객체로 저장합니다:

  • blobs – 파일 내용
  • trees – 디렉터리
  • commits – 스냅샷
  • tags – 레퍼런스

각 객체는 SHA‑1 해시로 이름이 지정되고 zlib으로 압축됩니다.

손상의 일반적인 원인

  • 디스크 오류 또는 전원 손실로 인해 .git/objects/에 대한 쓰기가 중단됨
  • git gc, git repack, 또는 push/pull 중 프로세스가 강제 종료됨
  • 파일 시스템 버그(특히 네트워크/공유 드라이브에서)
  • 파일을 잠그거나 수정하는 과도한 안티바이러스 또는 백업 소프트웨어

Git의 저장소는 content‑addressable이기 때문에 해시와 일치하는 객체는 정상입니다. 손상은 보통 소수의 객체에만 국한됩니다.

Source:

2. 손상 식별

절대 급하게 삭제하지 마세요. 먼저, 정확히 무엇이 손상됐는지 파악합니다.

전체 저장소 무결성 확인

git fsck --full --no-dangling

일반적인 출력 예시:

error: object file .git/objects/a1/b2c3... is empty
error: sha1 mismatch for .git/objects/d4/e5f6...
missing blob a1b2c3d4e5f6...
broken link from tree f7a8b9... to blob a1b2c3...

손상된 SHA‑1 해시를 적어 두세요 – 나중에 필요합니다.

HEAD 확인

cat .git/HEAD          # should show: ref: refs/heads/main
cat .git/refs/heads/main
git cat-file -t $(cat .git/refs/heads/main)   # should output: commit

HEAD 혹은 브랜치 레퍼런스가 손상되었다면, 여기서 문제를 시작하면 됩니다. 그렇지 않다면 문제는 더 깊은 곳(블롭, 트리 등)에 있습니다.

3. Reflog 사용하기 – 최고의 친구

Reflog는 브랜치 포인터가 어디에 있었는지를 기록하고, 객체 데이터베이스와 별도로 저장되기 때문에 대부분의 손상에도 살아남습니다.

# Show recent reflog entries for all refs
git reflog show --all

# If HEAD is broken, read the reflog directly
cat .git/logs/HEAD

마지막으로 정상적인 커밋 해시를 찾아서 그 커밋으로 리셋합니다:

git reset --hard <commit‑hash>

Reflog는 기본적으로 90 일 동안의 히스토리를 보관하므로, 최근에 발생한 손상이라도 복구할 수 있는 유효한 커밋 해시가 거의 항상 존재합니다.

4. 원격에서 누락된 객체 가져오기

원격(GitHub, 자체 호스팅 서버, 동료의 머신)으로 푸시한 적이 있다면 이미 백업이 있습니다.

# 1️⃣ 손상된 객체를 다른 곳으로 이동
mkdir -p .git/objects-broken
# 손상된 객체 a1b2c3... 예시
mv .git/objects/a1/b2c3d4e5f6* .git/objects-broken/

# 2️⃣ 원격에서 누락된 객체를 가져오기
git fetch origin

# 3️⃣ 다시 검증
git fsck --full --no-dangling

Git 객체는 불변이기 때문에 원격에 있는 동일한 커밋은 정확히 같은 SHA‑1과 바이트를 가집니다. 가져오기를 통해 누락된 객체를 복구할 수 있습니다.

5. 손상된 Blob (파일) 재생성

손상된 객체가 blob(파일의 특정 버전)이고 작업 트리 버전이 아직 남아 있다면 다음과 같이 복구할 수 있습니다:

# 손상된 blob이 속한 파일 찾기
git ls-tree -r HEAD | grep <blob‑sha>
# 예시 출력:
# 100644 blob a1b2c3d4e5f6    path/to/file.js

# 현재 파일을 객체 저장소에 다시 해시하기
git hash-object -w path/to/file.js

작업 트리의 파일이 손상된 blob과 일치할 때만 작동합니다. 일치하지 않을 경우 원격 저장소나 백업에서 올바른 버전을 가져오세요.

6. 원격 저장소에서 새로 시작하기 (손상이 심한 경우)

저장소가 심하게 손상되었지만 원격 복사본이 있는 경우:

# Rename the broken repo
mv my-project my-project-broken

# Clone a fresh copy
git clone <remote‑url> my-project

# Copy over any uncommitted work
diff -rq my-project-broken/ my-project/ --exclude='.git'
# (Manually copy any files that differ)

푸시된 내용은 잃지 않으며, 유일한 위험은 커밋되지 않은 로컬 작업이며, diff가 이를 찾아줍니다.

7. 손상된 Packfile 처리

Git은 주기적으로 느슨한 객체들을 .git/objects/pack/에 패킹합니다. 손상된 pack은 수백 개의 객체를 숨길 수 있습니다.

# Try to unpack what you can
git unpack-objects .pack

# Verify the packfile
git verify-pack -v .git/objects/pack/pack-*.idx

git unpack-objects는 손상된 객체에서 실패하지만 정상적인 객체는 복구합니다. 추출이 끝난 후, 원격 저장소에서 fetch하여 누락된 부분을 채웁니다.

Source:

8. 예방 – 손상을 드물게 만들기

  1. 자주 푸시하기 – 모든 원격 저장소는 전체 백업이다. 어수선한 기능 브랜치라도 푸시하고, 나중에 스쿼시하면 된다.

  2. Git 작업을 절대 중단하지 않기git gc, git repack 등은 끝날 때까지 두어라. 실행 중에 강제 종료하는 것이 내가 본 가장 큰 손상 원인이다.

  3. 공유/네트워크 파일 시스템 사용을 피하기 – NFS, CIFS, Dropbox, OneDrive 등은 저장소 손상을 일으키는 경우가 많다. 꼭 사용해야 한다면 git bundle으로 휴대용 백업을 만들라.

  4. 객체 파일에 대해 fsync 활성화 – 전원 손실에 대비한다:

    git config --global core.fsyncObjectFiles true
  5. 중요한 저장소에서 정기적으로 git fsck 실행하여 문제를 조기에 발견한다.

  6. .git 디렉터리(또는 전체 저장소)를 외장 드라이브나 클라우드 스토리지에 정기적으로 백업한다.

TL;DR

  1. git fsck 실행 → 깨진 SHA‑1 확인.
  2. HEAD와 브랜치 레퍼런스를 점검.
  3. reflog를 사용해 정상 커밋을 찾고 git reset --hard 실행.
  4. 원격 저장소가 있다면 손상된 객체를 옮겨두고 git fetch 후 다시 검증.
  5. 복구 가능한 블롭은 다시 해시를 만들거나, 새로 클론한 뒤 커밋되지 않은 작업을 복사.
  6. packfile 문제라면 가능한 파일을 풀어내고 검증한 뒤, 누락된 객체를 fetch.

이 단계들을 따르면 대부분의 “fatal: bad object HEAD” 상황을 완전히 복구할 수 있다. 즐거운 코딩 되세요!

Source:

Git (2.36+) – 더 세분화된 core.fsync

git config core.fsync objects,derived-metadata,reference

주기적인 무결성 검사

  • git fsck을 정기적으로 실행합니다.
  • cron 작업이나 pre‑push 훅에 추가합니다.
  • 손상을 조기에 감지하면 복구 옵션이 더 많아집니다.

Git 설계가 복구에 도움이 되는 이유

  • 내용 주소 지정 객체 저장소이므로 모든 클론이 전체 백업이 됩니다.
  • 각 객체는 자체 검증이 가능합니다.
  • 손상은 보통 국소적이며, 전면적인 재해가 아닙니다.

실제 사례

제가 겪은 최악의 Git 손상은 객체 모델을 이해한 뒤 약 20분 만에 복구했습니다. 처음에는 이걸 몰라서 3시간 동안 당황했었죠. 이 글이 그 3시간을 절약해 주길 바랍니다.

더 깊이 파고들고 싶다면?

  • 공식 Git 책의 Git Internals 장을 읽어보세요.
  • .git/objects/가 어떻게 동작하는지 이해하면 “내 저장소가 손상됐다”는 위기가 15분 안에 해결될 수 있습니다.
0 조회
Back to Blog

관련 글

더 보기 »

버전 관리에 대한 추가 내용

업데이트: 놀랍게도 그리고 기쁘게도 버전 관리에 관한 내 마지막 포스트 https://bramcohen.com/p/manyana 가 Hacker News에 소개되어 많은 조회수를 얻었습니다. 감사합니다.

스페인 법률을 Git repo로

Legalize — España: 스페인 법률을 Git 저장소처럼. 각 법은 Markdown 파일이며, 각 개정은 commit이다. 8,600개가 넘는 법률이 공개 데이터 API에 포함되어 있다.