修復損毀的git repo

Posted in :

使用 git status 或 git pull 指令,都會顯示錯誤訊:

fatal: bad tree object

或:

fatal: unable to read tree

挑戰使用 git reset –hard 也會失敗。

執行指令:

git fsck --full

顯示詳細的出錯地方:

bad sha1 file: .git/objects/08/a17cc480454ddce
bad sha1 file: .git/objects/0a/b5448f76a304ed7
bad sha1 file: .git/objects/40/1bad05ff57143cab268bae88d1408e
bad sha1 file: .git/objects/4b/b87f2fe96729b5c
bad sha1 file: .git/objects/65/7eae0c1999fa121
bad sha1 file: .git/objects/7c/e8c257894339fb2fc77cee76054aa9
bad sha1 file: .git/objects/87/b6219cffc518346
bad sha1 file: .git/objects/89/77f89bcaf2ee459
bad sha1 file: .git/objects/9e/1e9d0d34dc61fff
bad sha1 file: .git/objects/ac/18db921111520ae
bad sha1 file: .git/objects/b4/4ea3302f22e6950
bad sha1 file: .git/objects/c4/b5fb24a6d920497
bad sha1 file: .git/objects/c4/86a17f9b04637f6
bad sha1 file: .git/objects/cb/8591c50df269669
bad sha1 file: .git/objects/ce/cda4953fdc90eaed632d8bf2f4ee81
bad sha1 file: .git/objects/e9/9bfc0a56df14a3cf257f42896cf0e3
bad sha1 file: .git/objects/f0/63ec472d66cd077
Checking object directories: 100% (256/256), done.
Checking objects: 100% (303/303), done.
error: refs/remotes/origin/master: invalid reflog entry 8977f89bcaf2ee459a348649984f0df89ef15699
error: refs/remotes/origin/master: invalid reflog entry 8977f89bcaf2ee459a348649984f0df89ef15699
error: refs/heads/master: invalid reflog entry 8977f89bcaf2ee459a348649984f0df89ef15699
error: refs/heads/master: invalid reflog entry 8977f89bcaf2ee459a348649984f0df89ef15699
error: HEAD: invalid reflog entry 8977f89bcaf2ee459a348649984f0df89ef15699
error: HEAD: invalid reflog entry 8977f89bcaf2ee459a348649984f0df89ef15699
error: 87b6219cffc518346172f422d1bfa4e8b78ed6fe: invalid sha1 pointer in cache-tree
broken link from    tree 26640b344192f293fac8ebb8d8f3fdccfd189d42
              to    tree 401bad05ff57143cab268bae88d1408e8e76cb3c
broken link from    tree 26640b344192f293fac8ebb8d8f3fdccfd189d42
              to    tree cecda4953fdc90eaed632d8bf2f4ee81508933e8
broken link from    tree 47ba09a9cfaacc42524cf27ad8d9e7908aa0c5d7
              to    tree 08a17cc480454ddce30f0081a2d4badbffd55b9f
broken link from  commit 46bd75ce77f3b65e1c31206600caad57f306ca0a
              to    tree 9e1e9d0d34dc61ffff3fefb38d7e94781cbffb08
broken link from  commit dac0579e0b3bc6ca5a990d659a7cb9ce7655a932
              to    tree 87b6219cffc518346172f422d1bfa4e8b78ed6fe
broken link from  commit dac0579e0b3bc6ca5a990d659a7cb9ce7655a932
              to  commit 8977f89bcaf2ee459a348649984f0df89ef15699
dangling blob 422c38560f4b6f012215f16691347498e4681e0d
missing blob 4bb87f2fe96729b5cc5d4f2caf5c963b8934f02e
missing blob 7ce8c257894339fb2fc77cee76054aa96803679b
dangling tree d13ce7747f9b24259ef8773913bd0f76a87fd2aa
missing tree 08a17cc480454ddce30f0081a2d4badbffd55b9f
missing blob cb8591c50df2696693808909971890b744b25380
missing tree cecda4953fdc90eaed632d8bf2f4ee81508933e8
dangling tree 6ca29d55c0b990e57487ebb0a066c3ac6a992922
missing tree 87b6219cffc518346172f422d1bfa4e8b78ed6fe
missing tree 9e1e9d0d34dc61ffff3fefb38d7e94781cbffb08
dangling blob bf4a20c6380beeb9adf1cf58d424b467580ab004
missing blob c486a17f9b04637f64a9113c4f1ac41de54fb3f6
missing tree 401bad05ff57143cab268bae88d1408e8e76cb3c
dangling tree 46137c7cfcfef7b70f6a01ff17c6271aaad1bc1e
missing commit 8977f89bcaf2ee459a348649984f0df89ef15699
dangling blob a8978263ebd73655bd9197d40935d007b9c6cd9c
missing blob e99bfc0a56df14a3cf257f42896cf0e389686951

建議解法

直接使用 git clone 把遠端 repo 再下載回來,會簡單很多。

複雜解法

mv -v .git .git_old
git init
git remote add origin "${url}"
git fetch
# Note that some repositories use 'master' in place of 'main'. 
git reset origin/master

這一個複雜解法的好處是,可以保留有被異動的檔案們,執行完上面指令,再下 git status 就可以看到被異動的檔案們。

複雜解法的第一次 git push 會失敗,不過系統會提示我們服用下面的指令就OK 了:

git push --set-upstream origin master

資料來源

How can I fix a corrupted Git repository?
https://stackoverflow.com/questions/18678853/how-can-i-fix-a-corrupted-git-repository

As an alternative to Todd’s last option (Full Restores and Re-Initialization), if only the local repository is corrupted, and you know the URL to the remote, you can use this to reset your .git to match the remote (replacing ${url} with the remote URL):

mv -v .git .git_old &&            # Remove old Git files
git init &&                       # Initialise new repository
git remote add origin "${url}" && # Link to old repository
git fetch &&                      # Get old history
# Note that some repositories use 'master' in place of 'main'. Change the following line if your remote uses 'master'.
git reset origin/main --mixed     # Force update to old history.

This leaves your working tree intact, and only affects Git’s bookkeeping.

I also recently made a Bash script for this very purpose (Appendix A), which wraps a bit of safety around this operation.

Note:

  • If your repository has submodules, this process will mess them up somehow, and the only solution I’ve found so far is deleting them and then using git submodule update --init (or recloning the repository, but that seems too drastic).
  • This tries to determine the correct choice between ‘main’ and ‘master’ depending on local configuration settings, however there may be some issues if used on a repository that uses ‘master’, on a machine that has ‘main’ as the default branch.
  • This uses wget to check that the url is reachable before doing anything. This is not necessarily the best operation to determine that a site is reachable, and if you haven’t got wget available, this can likely be replaced with ping -c 1 "${url_base}" (linux), ping -n 1 "${url_base}" (windows), or curl -Is "${url_base}"

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *