손상된 Git 저장소 복구: 완벽한 문제 해결 가이드

Git 저장소 손상은 개발을 중단시킬 수 있지만, 복구는 종종 가능합니다. 이 가이드는 필수 백업 절차부터 시작하여 전문가 수준의 단계별 문제 해결 워크플로우를 제공합니다. `git fsck`를 사용하여 손상된 객체를 진단하고, `git reset`을 사용하여 인덱스를 복구하며, `git reflog`를 통해 손실된 커밋을 복구하고, 참조(references)를 수동으로 수정하는 방법을 알아보세요. 사소한 인덱스 오류든 심각한 객체 손실이든, 이 문서는 저장소 무결성을 안전하게 복원하기 위한 실행 가능한 명령어와 모범 사례를 제공합니다.

23 조회수

손상된 Git 저장소 복구: 완벽한 문제 해결 가이드

Git 저장소는 일반적으로 견고하지만, 하드웨어 오류, 갑작스러운 시스템 충돌, 디스크 오류, 또는 중요한 Git 작업(객체 패킹 또는 히스토리 재작성 등) 중 전원 손실과 같은 외부 요인은 데이터 손상을 초래할 수 있습니다. 손상된 저장소는 혼란스러운 오류, 커밋 불능, 또는 누락된 객체 보고서 등으로 나타날 수 있습니다.

이 가이드는 손상 유형을 진단하고, 적절한 복구 기술을 사용하며, 손실된 데이터를 안전하게 복구하는 체계적이고 단계별 접근 방식을 제공합니다. 저장소 손상은 영구적인 데이터 손실로 이어질 수 있으므로, 침습적 복구를 시도하기 전에 항상 안전 백업을 생성하는 모범 사례를 따르십시오.


1. 안전 우선: 손상된 저장소 백업

복구 명령, 특히 .git 디렉토리 내의 파일 시스템 조작을 포함하는 명령을 시작하기 전에, 반드시 전체 백업을 생성해야 합니다. 이는 복구 프로세스가 추가 문제를 일으킬 경우 현재 손상된 상태로 되돌릴 수 있도록 보장합니다.

# 저장소 디렉토리 밖으로 이동
cd ..

# 전체 디렉토리의 압축 백업 생성
tar -czvf myrepo_corrupted_backup.tar.gz myrepo/.git

# 또는, 단순히 .git 폴더 복사
cp -r myrepo/.git myrepo_backup_$(date +%Y%m%d)

2. git fsck로 손상 진단하기

Git 저장소의 무결성을 확인하는 주요 도구는 git fsck(파일 시스템 체크)입니다. 이 명령은 객체 데이터베이스와 참조를 스캔하여 불일치, 누락된 객체 또는 손상된 링크를 찾습니다.

포괄적인 확인을 위해 다음 명령을 실행하십시오:

# 자세한 출력을 포함하여 무결성 검사 실행
git fsck --full --unreachable --strict

git fsck 출력 해석

오류 메시지 의미 심각도 주요 해결책
error: object XXXXX is missing 필요한 블롭, 트리 또는 커밋 객체가 완전히 누락되었습니다. 높음 원격/백업에서 복구.
dangling commit XXXXX 커밋이 존재하지만 어떤 브랜치, 태그 또는 reflog에서도 참조되지 않습니다. 낮음/중간 git reflog를 통한 복구.
dangling blob XXXXX 데이터는 존재하지만 어떤 커밋이나 트리에도 연결되어 있지 않습니다. 낮음 일반적으로 무시하거나 정리할 수 있습니다.
error: HEAD points to an unborn branch .git/HEAD 파일이 손상되었거나 존재하지 않는 브랜치를 가리킵니다. 중간 .git/HEAD 수동 수정 또는 git reset.

3. Git 인덱스 (.git/index) 복구

인덱스 파일은 Git이 작업 디렉토리와 마지막 커밋 사이의 변경 사항을 추적하는 데 사용하는 스테이징 영역 캐시입니다. 인덱스 손상은 시스템 충돌 또는 병합 실패 후 가장 흔한 문제 중 하나입니다.

Git 작업이 인덱스가 유효하지 않거나, 일관성 없거나, 읽을 수 없다는 오류와 함께 실패하면 인덱스를 재구축해야 합니다.

방법 1: Git이 인덱스를 다시 읽도록 강제하기

인덱스 복구를 시도하는 가장 안전한 방법은 하드 리셋을 수행하여 Git이 최신 커밋을 기반으로 인덱스와 작업 디렉토리를 일치시키도록 강제하는 것입니다.

git reset --hard HEAD

방법 2: 인덱스를 수동으로 삭제하고 다시 생성하기

git reset이 실패하면 손상된 인덱스 파일을 삭제할 수 있습니다. Git은 다음번에 git status 또는 git add와 같은 명령이 필요할 때 자동으로 인덱스를 다시 생성합니다.

경고: 인덱스를 삭제하면 스테이징 영역이 비워집니다. 스테이징했던 모든 변경 사항(git add 사용)은 손실됩니다.

# 손상된 인덱스 파일 삭제
rm .git/index

# Git이 작업 디렉토리를 기반으로 인덱스를 재구축하도록 강제
# 현재 수정된 모든 파일을 스테이징합니다
git add -A

# 기능을 확인하기 위해 상태 확인
git status

4. 손상되거나 누락된 객체 처리

손상된 Git 객체(블롭, 트리 또는 커밋)와 관련된 손상은 종종 고치기 가장 어렵습니다. 특히 객체가 실제로 누락된 경우에는 더욱 그렇습니다. 하지만 때로는 손상이 제대로 패키징되지 않은 객체나 복구 가능한 매달린 객체 때문일 수도 있습니다.

4.1. 저장소 다시 패키징하기

Git은 객체를 느슨한 파일로 저장하거나 팩 파일로 통합하여 저장합니다. 때로는 repack 작업을 실행하여 사소한 무결성 문제를 해결하고 성능을 향상시킬 수 있습니다.

# 모든 느슨한 객체를 다시 패키징하고, 무결성을 확인하며, 오래된 팩 파일을 정리
git repack -a -d

# 개선 사항을 확인하기 위해 fsck 다시 실행
git fsck --full

4.2. Reflog를 통해 매달린 커밋 복구

dangling commit은 유효하지만 알려진 참조(브랜치, 태그)로 접근할 수 없는 커밋 객체입니다. 이는 강제 리셋이나 히스토리 재작성 후에 자주 발생합니다. reflog는 로컬 HEAD 및 참조의 히스토리를 추적하며, 종종 복구의 열쇠를 쥐고 있습니다.

  1. Reflog 보기:

bash git reflog
손실을 유발한 작업 앞에 있는 SHA-1 해시를 찾으십시오(예: HEAD@{5}: reset: moving to origin/main).

  1. 커밋 다시 참조하기:

올바른 SHA-1(예: a1b2c3d4)을 식별하면, 해당 SHA-1을 가리키는 새 브랜치를 생성하거나 현재 브랜치를 리셋할 수 있습니다.

```bash
# 예시: 새로운 복구 브랜치 생성
git branch recovered-work a1b2c3d4

# 또는, 현재 브랜치를 매달린 커밋으로 리셋
# (주의하여 사용하세요)
git reset --hard a1b2c3d4
```

4.3. 실제로 누락된 객체 처리

git fsckerror: object XXXXX is missing을 보고하면, 특정 커밋 히스토리에 필요한 데이터가 로컬 객체 데이터베이스(.git/objects)에 더 이상 없다는 의미입니다.

  • 원격 저장소가 존재하는 경우: 유일하고 신뢰할 수 있는 해결책은 원격 저장소에서 누락된 객체를 가져오는 것입니다.

    ```bash
    git fetch origin

    그런 다음 링크를 복구하거나 영향을 받는 브랜치를 리셋 시도

    ```

  • 원격 저장소가 없는 경우 (로컬 손상): 저장소가 전적으로 로컬이고 객체가 누락된 경우, 해당 객체에 의해 참조되는 데이터는 외부 백업이 없는 한 영구적으로 손실됩니다.

5. 손상된 참조 (Refs) 복구

참조(refs)는 .git/refs/ 디렉토리에 있는 파일(예: 브랜치, 태그, 원격 추적 브랜치)로, 가리키는 커밋의 SHA-1 해시를 포함합니다. 이 파일들이 손상되면(예: 0바이트 또는 유효하지 않은 해시를 포함), Git은 브랜치의 상태를 확인할 수 없습니다.

5.1. 위치 파악 및 수동 복구

  1. 손상된 참조 식별: 오류 메시지는 일반적으로 어떤 참조가 손상되었는지 지정합니다(예: error: bad ref for branch 'feature/X').

  2. 참조 디렉토리로 이동:

bash cd .git/refs/heads/ # 또는 .git/refs/remotes/origin/

  1. 파일 검사: 텍스트 편집기나 cat을 사용하여 파일을 확인하십시오. 이 파일은 정확히 40개의 16진수 문자(SHA-1 해시)를 포함해야 합니다.

  2. 복구:

  • 해시를 알고 있는 경우(예: git reflog에서), 올바른 40자 SHA-1을 파일에 수동으로 붙여넣습니다.
  • 참조가 명확히 손상된 경우(예: 0바이트, 가비지 데이터), 파일을 삭제하십시오. 그런 다음 필요한 경우 브랜치/참조를 다시 생성해야 합니다(예: git checkout -b <branch-name> <known-good-commit>).

모범 사례: Reflog 삭제

전체 reflog 데이터베이스가 손상된 것으로 보이면, logs 폴더를 삭제하여 Git이 새로 시작하도록 강제하면 종종 심각한 참조 문제를 해결할 수 있습니다.

rm -rf .git/logs

6. 최종 복구 옵션: 알려진 정상 소스에서 클론하기

저장소 손상이 광범위하거나 필요한 객체가 누락된 경우, 가장 안전하고 신뢰할 수 있는 복구 방법은 현재 로컬 저장소를 버리고 신뢰할 수 있는 소스(일반적으로 GitHub, GitLab 또는 Bitbucket과 같은 원격 서버)에서 다시 클론하는 것입니다.

# 1. 손상된 저장소의 작업 변경 사항 백업
# (예: 커밋되지 않은 파일을 임시 위치로 복사)

# 2. 손상된 저장소 디렉토리 이름 변경 또는 삭제
mv myrepo myrepo_bad

# 3. 새 복사본 클론
git clone <remote_url> myrepo

# 4. 백업된 작업 변경 사항을 새 저장소에 적용

이 방법은 저장소 히스토리의 보장된 깨끗하고 유효한 복사본으로 시작하여 지속적인 손상 위험을 최소화합니다.

요약 및 예방

손상된 Git 저장소를 복구하려면 인덱스, 객체 또는 참조에 대한 특정 복구를 적용하기 전에 git fsck를 사용하여 신중하게 진단해야 합니다. 시작하기 전에 항상 .git 디렉토리를 백업하여 안전을 최우선으로 하십시오. git reflog와 같은 로컬 복구 방법은 히스토리를 복구하는 데 강력하지만, 심각한 손상에 대해서는 원격 저장소에서 클론하는 것이 가장 신뢰할 수 있는 해결책입니다.

핵심 요약:

  1. 먼저 백업. (항상).
  2. git fsck --full로 진단하십시오.
  3. 인덱스 문제는 일반적으로 git reset --hard로 해결됩니다.
  4. 누락된 객체는 일반적으로 원격에서 가져와야 합니다.