56

My Git repository got corrupted after a couple of hard reboots due to power supply issues and now I'm unable to fix it (I was in the middle of staging some files at the last power failure):

$ git status
fatal: failed to read object 3d18855708b0f127d40c13c679559d7679228b69: Invalid argument
$ git fsck
fatal: failed to read object 24377c609184c192f3f3c1733bac7115c1080758: Invalid argument
$ git branch -a
(...works, lists branches...)
$ git checkout someotherbranch
fatal: failed to read object 3d18855708b0f127d40c13c679559d7679228b69: Invalid argument
$ git log
fatal: failed to read object 3d18855708b0f127d40c13c679559d7679228b69: Invalid argument
$ git log someotherbranch
(...works, shows commits...)

So, as you can see, my current branch is pretty screwed up, and I don't seem to be able to fix it. What can I try to repair this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Unknown
  • 5,722
  • 5
  • 43
  • 64
  • 1
    is this server repo? do there exist local clones/repos that you can use for restoration? – prusswan Nov 25 '11 at 16:27
  • 1
    It's my local git repo... I have a clone on another machine which I could use to restore everything (with a few commits lost perhaps), but I'd rather fix this repo if possible... – Unknown Nov 26 '11 at 14:05
  • It is worth mentioning that the working folder contents may still be recoverable. Do `git diff > diff.patch`, then you could use it like this to patch a new clone: `git patch -p1 < diff.patch` – datashaman Jul 03 '15 at 14:50
  • 1
    Power Failures will do that. So will a bad HDD/SSD. – Adam Fowler Nov 24 '15 at 18:52
  • 3
    Nearly all answers assume one can simply re-clone from some uncorruptible remote origin. Here's the problem... What if you **are** the origin, and you're corrupted? Right. So, here: `git-repair` is a program that will run `git fsck` and try pretty hard to fix any problems it encounters. https://git-repair.branchable.com/ It seems quite capable, and though you might end up having to copy (if you can!) objects from a backup (you have a backup, right?), it should save you a lot of time by salvaging whatever it can and leaving you the real work, not lots of automatable tasks. No affiliation, etc. – underscore_d Dec 21 '16 at 01:03

14 Answers14

40

My solution for a similar situation was to replace a hash of the damaged object in .git/refs/heads/my-working-branch with a hash of previous commit (which can be found in .git/logs/HEAD).

Nash Bridges
  • 2,350
  • 14
  • 19
  • 1
    Still leaves repository in broken state, but this allows to recover it. – ony Sep 21 '13 at 03:45
  • 12
    I'm not sure I understand what this is – Andrew Wolfe Nov 10 '15 at 21:42
  • 3
    wow. this works... my `HEAD` had become corrupted to `^@^@^@^@...` or something like that. – kumarharsh Feb 28 '17 at 19:38
  • 2
    You saved me !!! I was working on a new project, hadn't pushed anything to master. GitHub Mac client screwed up, royally. Somehow deleted all my src files and I was left with just a node_modules. Thanks A Ton !!! – ultimate Jul 07 '17 at 00:52
  • 2
    @Nash Bridges you are my hero! For anyone needing a more specific example: When you open up `.git/refs/heads/my-working-branch` go to the very bottom and you should see `0f50.. 017f.. [name] [date] [commitmsg]` where [commitmsg] is your last commit before the calamity. Assuming you were working in a branch named feature/myfeature, paste the `0f50..` hash (the 1st one) into `.git/refs/heads/feature/myfeature`. Problem solved. Rejoice. – Lee Richardson Oct 05 '17 at 01:33
  • In my case, windows 10 blue screened during a commit. `.git/refs/heads/master` was empty. As Lee Richardson explains, I used the 017f... latest commit. Saved it to the `master` file and done. Nothing lost. A million thanks! – Dimitri Mostrey May 22 '23 at 05:54
  • Update: a program called Malwarebytes is possibly the culprit. How? I have no idea. Found the hint here https://stackoverflow.com/a/58395230/2602434 – Dimitri Mostrey May 22 '23 at 06:25
24

This just happened to me. I reclone the repository in a new folder and move my latest changes over manually. Low tech, but it works every time. Hopefully you can remember your last changes.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
nbushnell
  • 1,724
  • 1
  • 14
  • 14
  • 12
    You can simply replace the `.git` folder in the broken repo with the one you recloned. That way you don't need to move your changes manually. Just be aware of branching. You might have to stash and check out the correct branch. – Niel de Wet Jun 01 '16 at 09:37
  • Years later, still a clean way to go. My repo was totally stuffed, so I gzipped out my changed files, replaced the .git folder and pasted them back in. Done. – Timmah Apr 19 '18 at 04:48
16

The most simple solution for me: You should git clone in a new folder, then replace the clean new_folder/.git to the old folder (the broken folder). It has worked well for me!

git clone ...(remote) new_folder
mv old_folder/.git  old_folder/.git_old
cp -R new_folder/.git  old_folder/
SanjiMika
  • 2,664
  • 19
  • 19
13

Try making a backup of the repository and then running git reset --hard HEAD@{1} to go back to the previous HEAD and see if this works. It may be just the current HEAD which is corrupted.

(You should also run fsck on your disk if you haven't already.)

Michael Mior
  • 28,107
  • 9
  • 89
  • 113
  • 1
    $ git reset --hard HEAD@{1} Checking out files: 100% (5724/5724), done. fatal: failed to read object 3d18855708b0f127d40c13c679559d7679228b69: Invalid argument – Unknown Nov 25 '11 at 15:41
  • 1
    No, same thing :( $ git reflog fatal: failed to read object 3d18855708b0f127d40c13c679559d7679228b69: Invalid argument – Unknown Nov 25 '11 at 15:46
  • Maybe the filesystem fsck screwed something up at boot, I see messages about cleaning orphaned inodes.. – Unknown Nov 25 '11 at 15:48
  • You should be able to see the reflog under `.git/logs/HEAD`. If you search for the object in error, you should be able to see how much history may potentially be lost and back up to before the corrupted object. (Note that the file is appended, so the latest `HEAD` will be at the end.) – Michael Mior Nov 25 '11 at 16:30
  • 1
    esto me ayudo a salir del problema. gracias – josue Oct 24 '20 at 03:27
10

For me, I had enabled TRIM in OS X with a non-Apple SSD (which is not recommended) and apparently caused various corruptions on my boot disk. So the corrupted commit was deep in the history.

I don't care too much about repairing my repository, except I have a few local branches that were too experimental to bother pushing to the remote repository, and I'd like to salvage the work in those branches.

Theoretically, since this is a local repository, I feel that Git should be able to recover/repair itself using origin. Why isn't this possible?

At any rate I stumbled across this cool strategy to push a branch to another local Git repository. Unfortunately, cloning the repository into ../repo_copy and then using that as a local remote resulted in the following error:

! git push --force local_remote HEAD
fatal: failed to read object e0a9dffddeeca96dbaa275636f8e8f5d4866e0ed: Invalid argument
error: failed to push some refs to '/Users/steve/Dev/repo_copy'

So I started instead with an empty repository, and then pushing branches to it worked OK. So for any local branch I had whose git log didn't end in:

....
    Fixing cukes
fatal: failed to read object e0a9dffddeeca96dbaa275636f8e8f5d4866e0ed: Invalid argument

I simply would check it out and then do git push --force local_remote HEAD. The last thing I did was:

! cd ~/Dev/repo_copy
! git remote add origin git@github.com:sdhull/my_repo.git  # real remote

Then I went in to git config -e and set up my master branch and was back up and running with nothing lost!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
steve
  • 3,276
  • 27
  • 25
6

Another alternative which worked for me was to reset the Git head and index to its previous state using:

git reset --keep

I also tried the following commands, but they did not work for me, but they might for you:

git reset --mixed
git fsck --full
git gc --auto
git prune --expire now
git reflog --all
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
gaborous
  • 15,832
  • 10
  • 83
  • 102
5

I had the same problem and did the following steps using git-repair

  • cp myrepo myrepo.bak
  • cd myrepo
  • git repair --force (first try it without force)

After this was successful the tree was set back to the last working commit.

Then I did meld myrepo myrepo.bak to apply changes from the working tree of the corrupted repository to the fixed repository.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
student
  • 1,636
  • 3
  • 29
  • 53
  • 2
    Can you specify which version are you using? Its not available in 1.8.3.1 – Ankit Jain Nov 16 '18 at 12:37
  • 1
    I think I was using `git-repair` version `1.20151215-1.1` (from the ubuntu repository) and `git` version `1:2.17.1-1ubuntu0.3` (from ubuntu repository) – student Nov 19 '18 at 19:00
  • 2
    I am getting this error---> git: 'repair' is not a git command. See 'git --help'. – Shamim Feb 03 '20 at 04:58
  • 1
    You need to install git-repair package – Nico Aug 13 '20 at 06:41
  • @Shamim et al: it seems git-repair isn't installed by default (or at least wasn't on the installation I'm on, with `git --version` of `2.20.1`), but it can be installed (installation will vary by platform, for me `sudo apt install git-repair` did the trick -- though `git repair` itself did not actually do the job I was hoping it would, though it did what the documentation said it would). – lindes Dec 12 '21 at 02:31
3

I was able to recover my repository from:

zsh(broken)% git log master
error: object file .git/objects/7f/cab8648a989d9bb3f5246e6be7220395493395 is empty
error: object file .git/objects/7f/cab8648a989d9bb3f5246e6be7220395493395 is empty
fatal: loose object 7fcab8648a989d9bb3f5246e6be7220395493395 (stored in .git/objects/7f/cab8648a989d9bb3f5246e6be7220395493395) is corrupt
zsh(broken)% cat .git/refs/heads/master
7fcab8648a989d9bb3f5246e6be7220395493395
e311726c4eb970f4d4f504ad86248d322855018f da9c14d03e4849394087b61ff6272399937f7cce Nikolay Orliuk <virkony@gmail.com> 1379583764 +0300    commit: plan: timings

By resetting master to prev commit da9c14d03e4849394087b61ff6272399937f7cce as told by @Nash Bridges:

zsh(broken)% echo da9c14d03e4849394087b61ff6272399937f7cce > .git/refs/heads/master
zsh(broken)% git log --oneline -1 master
da9c14d plan: timings
zsh(broken)% git fsck
Checking object directories: 100% (256/256), done.
error: object file .git/objects/0e/ace931fdc851da254e9522596d1517d0ed51c5 is empty
error: object file .git/objects/0e/ace931fdc851da254e9522596d1517d0ed51c5 is empty
fatal: loose object 0eace931fdc851da254e9522596d1517d0ed51c5 (stored in .git/objects/0e/ace931fdc851da254e9522596d1517d0ed51c5) is corrupt

Creating a new empty repository, fetching master from broken:

zsh(broken)% mkdir ../recover && cd ../recover && git init
Initialized empty Git repository in /home/nikolay/talks/y/recover/.git/
zsh(recover)% git fetch ../broken master
remote: Counting objects: 44, done.
remote: Compressing objects: 100% (44/44), done.
remote: Total 44 (delta 20), reused 0 (delta 0)
Unpacking objects: 100% (44/44), done.
From ../broken
 * branch            master     -> FETCH_HEAD
zsh(recover)% git reset --hard FETCH_HEAD
HEAD is now at da9c14d plan: timings
zsh% git fsck
Checking object directories: 100% (256/256), done.

To restore those changes that was on the way to master:

zsh(recover)% rm -rf * && cp -a ../broken/* ./
zsh(recover)% git add -u && git commit -m 'prepare for publishing'
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ony
  • 12,457
  • 1
  • 33
  • 41
3

I followed the instructions found in Recovering from a corrupt Git repository:

$ cd /tmp/
$ git clone good-host:/path/to/good-repo
$ cd /home/user/broken-repo
$ echo /tmp/good-repo/.git/objects/ > .git/objects/info/alternates
$ git repack -a -d
$ rm -rf /tmp/good-repo

It worked for me.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MrJ
  • 1,436
  • 2
  • 15
  • 21
0

Windows gave bluescreen while I was changing branches. Booted back up and all files were corrupted and git did not recognize the repository.

How I fixed it:

  1. I cloned a fresh copy from remote.
  2. Copied over .git/index and .git/HEAD files over to corrupted .git repo.
  3. git finally recognized repo, so I did a hard checkout.
  4. Success

Note: If you had uncommitted changes this method will override them.

Sakox
  • 21
  • 3
0

If it's not possible to repair, sometimes it's useful to retrieve the contents. The following command will print all the contents of uncorrupted objects.

$ git cat-file --batch-check --batch-all-objects 2>&1 | grep blob | grep -v empty | awk '{ print $1; }' -
Talespin_Kit
  • 20,830
  • 29
  • 89
  • 135
0

I had some corrupted files and fixed them with git-repair:

sudo apt install git-repair 
git repair
Jesper
  • 1,007
  • 7
  • 24
0

git-repair (sudo apt install git-repair) and a few additional commands worked for me:

  1. Create a backup copy of your corrupted repository.

  2. Delete broken references:
    find .git/refs -size 0 -delete -print

  3. Repair repository from remote(s):
    git-repair --force

  4. Clean up dangling commits:
    git gc --prune=now

  5. Fetch the latest state from remote:
    git fetch

Optionally switch to master and reset it to origin/master:
git checkout master
git reset --hard origin/master

Verify with git fsck:
git fsck

0

If the objects exist uncorrupted on a remote, you could:

git fetch-pack --thin --keep <remote URL> <object-id(s)>

Get the URL from git remote --verbose.

Note: https:// doesn't work, it will need to be a git:// URL.


Another option:

I created a full clone of the repository in another folder, then imported the blobs from it.

In the original repo (make a backup first) I ran:

git pull
git reset --hard origin/main   # DESTRUCTIVE - reset index to a known good state
git unpack-objects < /path/to/new/clone/.git/objects/pack/<hash>.pack
git fsck --no-dangling

OR Untried:

  • Create a fresh clone of the remote
  • Add the fresh clone as a git alternate
  • Run git fsck again with all the objects present via the alternate
Tom Hale
  • 40,825
  • 36
  • 187
  • 242