하드 디스크 오류로 인해 손상된 Git 개체를 복구하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/801577

  •  03-07-2019
  •  | 
  •  

문제

하드 디스크 오류로 인해 Git 저장소의 일부 파일이 손상되었습니다.달릴 때 git fsck --full 다음과 같은 결과가 나타납니다.

error: .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack SHA1 checksum mismatch
error: index CRC mismatch for object 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid code lengths set)
error: cannot unpack 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid stored block lengths)
error: failed to read object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa at offset 276988017 from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack
fatal: object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa is corrupted

저장소 백업이 있지만 팩 파일이 포함된 유일한 백업이 이미 손상되었습니다.그래서 다른 백업에서 단일 개체를 검색하는 방법을 찾고 어떻게든 Git에게 올바른 개체만 포함된 새 팩을 생성하도록 지시해야 한다고 생각합니다.

내 저장소를 수정하는 방법에 대한 힌트를 제공해 주시겠습니까?

도움이 되었습니까?

해결책

이전 백업에서는 나쁜 객체가 다른 파일에 포장되었거나 아직 객체가 느슨 할 수 있습니다. 따라서 객체가 복구 될 수 있습니다.

데이터베이스에 몇 가지 나쁜 객체가있는 것 같습니다. 그래서 당신은 그것을 수동으로 할 수 있습니다.

때문에 git hash-object, git mktree 그리고 git commit-tree 팩에서 발견되기 때문에 물체를 쓰지 마십시오.

mv .git/objects/pack/* <somewhere>
for i in <somewhere>/*.pack; do
  git unpack-objects -r < $i
done
rm <somewhere>/*

(팩은 저장소에서 옮겨져 다시 포장을 풀고, 좋은 개체 만 이제 데이터베이스에 있습니다)

넌 할 수있어:

git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee

물체의 유형을 점검하십시오.

유형이 Blob 인 경우 : 이전 백업에서 파일의 내용을 검색합니다 ( git show 또는 git cat-file 또는 git unpack-file; 그러면 당신은 할 수 있습니다 git hash-object -w 현재 저장소에서 객체를 다시 작성하려면

유형이 트리 인 경우 : 사용할 수 있습니다 git ls-tree 이전 백업에서 트리를 복구하려면; 그 다음에 git mktree 현재 저장소에 다시 작성합니다.

유형이 커밋 된 경우 : 동일합니다 git show, git cat-file 그리고 git commit-tree.

물론이 프로세스를 시작하기 전에 원래 작업 사본을 백업 할 것입니다.

또한 살펴보십시오 손상된 Blob 물체를 복구하는 방법.

다른 팁

Banengusk 나를 올바른 길에 올려 놓고 있었다. 자세한 내용은 저장소 손상을 수정하기 위해 취한 단계를 게시하고 싶습니다. 나는 오래된 팩이나 저장소 백업에서 필요한 모든 물체를 찾을만큼 운이 좋았습니다.

# Unpack last non-corrupted pack
$ mv .git/objects/pack .git/objects/pack.old
$ git unpack-objects -r < .git/objects/pack.old/pack-012066c998b2d171913aeb5bf0719fd4655fa7d0.pack
$ git log
fatal: bad object HEAD

$ cat .git/HEAD 
ref: refs/heads/master

$ ls .git/refs/heads/

$ cat .git/packed-refs 
# pack-refs with: peeled 
aa268a069add6d71e162c4e2455c1b690079c8c1 refs/heads/master

$ git fsck --full 
error: HEAD: invalid sha1 pointer aa268a069add6d71e162c4e2455c1b690079c8c1
error: refs/heads/master does not point to a valid object!
missing blob 75405ef0e6f66e48c1ff836786ff110efa33a919
missing blob 27c4611ffbc3c32712a395910a96052a3de67c9b
dangling tree 30473f109d87f4bcde612a2b9a204c3e322cb0dc

# Copy HEAD object from backup of repository
$ cp repobackup/.git/objects/aa/268a069add6d71e162c4e2455c1b690079c8c1 .git/objects/aa
# Now copy all missing objects from backup of repository and run "git fsck --full" afterwards
# Repeat until git fsck --full only reports dangling objects

# Now garbage collect repo
$ git gc
warning: reflog of 'HEAD' references pruned commits
warning: reflog of 'refs/heads/master' references pruned commits
Counting objects: 3992, done.
Delta compression using 2 threads.
fatal: object bf1c4953c0ea4a045bf0975a916b53d247e7ca94 inconsistent object length (6093 vs 415232)
error: failed to run repack

# Check reflogs...
$ git reflog

# ...then clean
$ git reflog expire --expire=0 --all

# Now garbage collect again
$ git gc       
Counting objects: 3992, done.
Delta compression using 2 threads.
Compressing objects: 100% (3970/3970), done.
Writing objects: 100% (3992/3992), done.
Total 3992 (delta 2060), reused 0 (delta 0)
Removing duplicate objects: 100% (256/256), done.
# Done!

처음에는 다음 명령을 시도해 보십시오(필요한 경우 다시 실행하십시오).

$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase

그래도 여전히 문제가 있는 경우 다음을 시도해보세요.

  • 손상된 개체를 모두 제거합니다.

    fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt
    $ rm -v .git/objects/06/91c5...51e5
    
  • 빈 개체를 모두 제거합니다.

    error: object file .git/objects/06/91c5...51e5 is empty
    $ find .git/objects/ -size 0 -exec rm -vf "{}" \;
    
  • 다음 방법으로 "깨진 링크" 메시지를 확인하세요.

    git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
    

    그러면 손상된 blob이 어떤 파일에서 왔는지 알려줍니다!

  • 파일을 복구하려면 정말 운이 좋을 수도 있고 작업 트리에서 이미 체크아웃한 버전일 수도 있습니다.

    git hash-object -w my-magic-file
    

    다시 한 번 누락된 SHA1(4b945..)이 출력되면 이제 모든 작업이 완료된 것입니다!

  • 손상된 일부 이전 버전이라고 가정하면 가장 쉬운 방법은 다음과 같습니다.

    git log --raw --all --full-history -- subdirectory/my-magic-file
    

    그러면 해당 파일에 대한 전체 로그가 표시됩니다(사용한 트리가 최상위 트리가 아닐 수 있으므로 해당 파일이 어느 하위 디렉토리에 있었는지 직접 파악해야 함). 이제 다음을 다시 만들 수 있습니다. 해시 개체가 있는 개체가 다시 누락되었습니다.

  • 누락된 커밋, 트리 또는 blob이 있는 모든 참조 목록을 얻으려면 다음을 수행하세요.

    $ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
    

    git이 손상을 발견하면 해당 참조가 죽기 때문에 일반 Branch -d 또는 tag -d 명령을 사용하여 해당 참조 중 일부를 제거하는 것이 불가능할 수 있습니다.따라서 배관 명령 git update-ref -d $ref를 대신 사용하세요.로컬 브랜치의 경우 이 명령을 사용하면 .git/config에 오래된 브랜치 구성이 남을 수 있습니다.수동으로 삭제할 수 있습니다([branch "$ref"] 섹션 검색).

  • 모든 참조가 정리된 후에도 참조 로그에 깨진 커밋이 여전히 남아 있을 수 있습니다.git reflogexpire --expire=now --all을 사용하여 모든 reflog를 지울 수 있습니다.모든 리플로그를 잃지 않으려면 개별 리플에서 깨진 리플로그를 검색할 수 있습니다.

    $ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
    

    (git rev-list에 -g 옵션이 추가된 것에 주목하세요.) 그런 다음 각 항목에 대해 git reflogexpire --expire=now $ref를 사용하세요.깨진 참조와 참조 로그가 모두 사라지면 git fsck --full을 실행하여 저장소가 깨끗한지 확인하세요.매달려 있는 물체는 괜찮습니다.


아래에서는 현명하게 사용하지 않으면 잠재적으로 git 저장소의 데이터가 손실될 수 있는 고급 명령 사용법을 찾을 수 있으므로 실수로 git에 추가 손상을 입히기 전에 백업을 만드십시오.자신이 무엇을 하고 있는지 알고 있다면 스스로 위험을 감수해 보세요.


가져온 후 업스트림 브랜치 위에 현재 브랜치를 가져오려면 다음을 수행하세요.

$ git pull --rebase

또한 새 브랜치를 체크아웃하고 이전 브랜치를 삭제해 볼 수도 있습니다.

$ git checkout -b new_master origin/master

제거하기 위해 git에서 손상된 개체를 찾으려면 다음 명령을 시도하십시오.

while [ true ]; do f=`git fsck --full 2>&1|awk '{print $3}'|sed -r 's/(^..)(.*)/objects\/\1\/\2/'`; if [ ! -f "$f" ]; then break; fi; echo delete $f; rm -f "$f"; done

OSX의 경우 다음을 사용하세요. sed -E 대신에 sed -r.


다른 아이디어는 팩 파일에서 모든 객체의 압축을 풀어 .git/objects 내의 모든 객체를 재생성하는 것이므로 저장소 내에서 다음 명령을 실행해 보세요.

$ cp -fr .git/objects/pack .git/objects/pack.bak
$ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done
$ rm -frv .git/objects/pack.bak

위의 방법이 도움이 되지 않으면 다른 저장소에서 git 개체를 rsync하거나 복사해 보세요.

$ rsync -varu git_server:/path/to/git/.git local_git_repo/
$ rsync -varu /local/path/to/other-working/git/.git local_git_repo/
$ cp -frv ../other_repo/.git/objects .git/objects

결제를 시도할 때 깨진 분기를 수정하려면 다음과 같이 하세요.

$ git checkout -f master
fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625

이를 제거하고 업스트림에서 다시 결제해 보세요.

$ git branch -D master
$ git checkout -b master github/master

Git으로 인해 분리된 상태가 되면 다음을 확인하세요. master 분리된 브랜치를 병합합니다.


또 다른 아이디어는 기존 마스터를 재귀적으로 리베이스하는 것입니다.

$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master

또한보십시오:

부패한 Blob 물체에서 복구하기위한 단계는 다음과 같습니다.

1) 부패한 얼룩을 식별하십시오

git fsck --full
  error: inflate: data stream error (incorrect data check)
  error: sha1 mismatch 241091723c324aed77b2d35f97a05e856b319efd
  error: 241091723c324aed77b2d35f97a05e856b319efd: object corrupt or missing
  ...

부패한 얼룩입니다 241091723C324AED77B2D35F97A05E856B319EFD

2) 부패한 얼룩을 안전한 곳으로 옮기십시오 (만일 경우)

mv .git/objects/24/1091723c324aed77b2d35f97a05e856b319efd ../24/

3) 부패한 얼룩의 부모를 얻으십시오

git fsck --full
  Checking object directories: 100% (256/256), done.
  Checking objects: 100% (70321/70321), done.
  broken link from    tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
              to    blob 241091723c324aed77b2d35f97a05e856b319efd

부모 해시입니다 0716831E1A6C8D3E6B2B541D21C4748CC0CE7180.

4) 부패한 얼룩에 해당하는 파일 이름을받습니다

git ls-tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
  ...
  100644 blob 241091723c324aed77b2d35f97a05e856b319efd    dump.tar.gz
  ...

백업 또는 업스트림 git 저장소 에서이 특정 파일을 찾으십시오 (제 경우에는 dump.tar.gz). 그런 다음 로컬 저장소 내부의 어딘가에 복사하십시오.

5) GIT 객체 데이터베이스에 이전에 손상된 파일 추가

git hash-object -w dump.tar.gz

6) 축하하십시오!

git gc
  Counting objects: 75197, done.
  Compressing objects: 100% (21805/21805), done.
  Writing objects: 100% (75197/75197), done.
  Total 75197 (delta 52999), reused 69857 (delta 49296)

GIT 체크 아웃은 실제로 개정에서 개별 파일을 선택할 수 있습니다. Commit Hash와 파일 이름을 제공하십시오. 더 자세한 정보 여기.

이것을 안전하게 고치는 가장 쉬운 방법은 최신 비평을받지 않은 백업으로 되돌리고 최신 커밋에서 부패하지 않은 파일을 선택적으로 선택하는 것입니다. 행운을 빕니다!

다음은 백업이 손상되었거나 부분적으로 손상된 백업이 몇 개있을 경우 도움이 될 수있는 두 가지 기능입니다 (손상된 객체를 백업하면 발생할 수 있습니다).

회복하려는 저장소에서 둘 다 실행하십시오.

표준 경고 : 정말로 필사적이고 (손상된) 리포를 백업 한 경우에만 사용하십시오. 이것은 아무것도 해결하지 못할 수도 있지만 적어도 부패 수준을 강조해야합니다.

fsck_rm_corrupted() {
    corrupted='a'
    while [ "$corrupted" ]; do
        corrupted=$(                                  \
        git fsck --full --no-dangling 2>&1 >/dev/null \
            | grep 'stored in'                          \
            | sed -r 's:.*(\.git/.*)\).*:\1:'           \
        )
        echo "$corrupted"
        rm -f "$corrupted"
    done
}

if [ -z "$1" ]  || [ ! -d "$1" ]; then
    echo "'$1' is not a directory. Please provide the directory of the git repo"
    exit 1
fi

pushd "$1" >/dev/null
fsck_rm_corrupted
popd >/dev/null

그리고

unpack_rm_corrupted() {
    corrupted='a'
    while [ "$corrupted" ]; do
        corrupted=$(                                  \
        git unpack-objects -r < "$1" 2>&1 >/dev/null \
            | grep 'stored in'                          \
            | sed -r 's:.*(\.git/.*)\).*:\1:'           \
        )
        echo "$corrupted"
        rm -f "$corrupted"
    done
}

if [ -z "$1" ]  || [ ! -d "$1" ]; then
    echo "'$1' is not a directory. Please provide the directory of the git repo"
    exit 1
fi

for p in $1/objects/pack/pack-*.pack; do
    echo "$p"
    unpack_rm_corrupted "$p"
done

Git Add -A 및 Git Commit과 같은 변경 사항을 다시 추가하기 위해이 문제를 해결했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top