131

My git repository has somehow gone wonky - I loaded up msysgit this morning and instead of the branch name being shown after the current directory, it says "((ref: re...))", 'git status' reports everything as a new file, 'git log' and 'git reflog' tell me "fatal: bad default revision 'HEAD'", and so on.

Doing 'git reflog --all' or 'gitk --all' shows me the rest of the repository is intact, but it looks like the branch I was working on has just disappeared, which explains why HEAD doesn't seem to exist/point to anything.

I know git keeps hold of all sorts of globs of information, and I'm assuming my commits have just been orphaned somehow, so is there some command that will show me those commits so I can reset HEAD to them?

EDIT: Oh dear. I discovered 'git fsck', and 'git fsck --full' reports "fatal: object 03ca4... is corrupted". What the devil can I do about that?

EDIT: Oh dear oh dear. I checked out another branch, then tried to re-create the original branch with the same name using 'git checkout -b lostbranchname', and git says "error: unable to resolve reference refs/heads/lostbranchname: No error, fatal: Failed to lock ref for update: No error". 'No error' must be a particularly nasty error. So it looks like it's still hanging around, but unable to be used and unable to be killed.

EDIT: Super duper oh dear. I've done a bunch of unpacking and repacking and replacing of things as suggested here: How to recover Git objects damaged by hard disk failure?, but now I'm getting another hash reported as corrupt, for something as innocuous as 'git status'. I think the entire thing is hosed. Git's lovely and all, but I shouldn't have to deal with this kind of thing.

Community
  • 1
  • 1
Ben Hymers
  • 25,586
  • 16
  • 59
  • 84
  • Concerning `git checkout -b lostbranchname` - if you only care about the name of the branch (not the contents of it), you can manually delete(or rename) `.git/refs/heads/lostbranchname` - that will hopefully do the trick. – Antony Hatchkins Jan 19 '10 at 11:35
  • chkdsk reports everything as ok. I've removed the dangling branch in .git/refs/heads/ since it was causing problems but now other commands are complaining about other objects being corrupt, so I think it's not as simple as one object being corrupt now. – Ben Hymers Jan 19 '10 at 11:44
  • 1
    And you haven't an upstream where you push this git folder to? – lprsd Jan 19 '10 at 12:48
  • 1
    Sadly not, it's actually kind of a surrogate repository for an inferior source control system, I'm just using it locally to get all git's features and niceties without the hassle of the other system. But at least the other system doesn't randomly corrupt itself. Still, that means all I've lost is my changes since I last checked in to the other system, which I've recovered already. Time to start a fresh repository! – Ben Hymers Jan 19 '10 at 13:07
  • 8
    I'd hesitate to say that git made you "deal with this kind of thing" or that it corrupted itself. Nothing besides a backup can be completely stable against data loss. – Cascabel Jan 19 '10 at 19:02
  • 1
    I know really, I'm just (naturally) a bit miffed that I've lost my pretty history. It's not git's fault, any other system would behave the same given file system errors. – Ben Hymers Jan 20 '10 at 14:46
  • I think many other systems would behave *worse* -- in particular, if they didn't report an error to you when there was one, and you happily go along with data corruption that you don't know you have. Condolences on your loss, though. :( (Though, hopefully you're over it by now, and I hope I'm not digging up an old wound. ;) (but I stumbled on this when looking for something else.) – lindes Feb 16 '11 at 22:30
  • @BenHymers sounds like the "inferior" source control system is significantly better at what its supposed to do - look after your source code. A SCM that doesn't do this is about as good as Visual SourceSafe (which, BTW, doesn't) – gbjbaanb Aug 08 '13 at 19:48

5 Answers5

172

Rather than leave this open I think I'll give an answer to my own question. Using git reflog --all is a good way to browse orphaned commits - and using the SHA1 hashes from that you can reconstruct history.

In my case though, the repository was corrupted so this didn't help; git fsck can help you find and sometimes fix errors in the repository itself.

Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
Ben Hymers
  • 25,586
  • 16
  • 59
  • 84
  • 5
    Thanks. This is the only place I found this information when trying to pull an orphaned pull request on github. Solved my problem. – SystemParadox Apr 27 '12 at 15:49
  • 6
    in case anyone would want all in gitk: `[alias] orphank = !gitk --all --date-order ``git reflog | cut -c1-7``&` (edit: imagine those double backticks where single ones - escaping does not seem to work here) – mbx Jun 19 '15 at 07:58
  • 1
    Awesome tip @mbx! Very useful to be able to see the links between orphaned commits graphically! – Ben Hymers Jun 20 '15 at 11:48
  • @BenHymers Would be cool, if we could get dotted lines for "rebase/squash"-like commit relations too. I haven't yet found a way to do thatt. – mbx Jun 20 '15 at 12:40
  • I didn't know about reflog when I wrote the answer above. It is such a useful tool! – Jamey Hicks Jun 29 '16 at 00:19
38

I typically find the git reflog output to be confusing. It's much easier for me to understand a commit graph from git log --graph --reflog. Overriding the log format to show only commit summaries also can make the graph easier to follow:

$ git config --global alias.graph \
    "log --graph --all --format='%h %s%n        (%an, %ar)%d' --abbrev-commit"

$ git graph --reflog

* f06abeb Add feature
|         (Sue Dakota, 4 days ago) (HEAD -> master)
* f126291 Fix the build
|         (Oski M. Wizard, 5 days ago) (origin/master, master)
* 3c4fb9c Move fast, break things
|         (Alyssa P. Hacker, 5 days ago)
| * e3124bf fixup! More work for feature
| |         (Sue Dakota, 4 days ago)
| | * 6a7a52e Lost commit
| |/          (Sue Dakota, 4 days ago)
| * 69d9438 More work for feature
| |         (Sue Dakota, 2 weeks ago)
| * 8f69aba Initial work for feature
|/          (Sue Dakota, 3 weeks ago)
* d824fa9 Fix warnings from the linter
|         (Theo Rhys Tudent, 4 weeks ago)
* 9f782b8 Fix test flakes
|         (Tess Driven, 5 weeks ago)

From that it's clear that e3124bf and 6a7a52e are unreferenced orphans, and there's context from their ancestor commits.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • 2
    Saved me hours of lost work just now! accidentally deleted a local branch that had unpushed commits on it, `git reflog --all` doesn't show them, with `git log --graph --reflog` they were very visible... – Adam.Er8 Aug 09 '20 at 14:47
  • Thanks for `git alias`, how have I never seen that anywhere else?! Seems like you have to [use `git config` to set them](https://www.atlassian.com/git/tutorials/git-alias) though. – Jivan Pal Oct 13 '20 at 18:42
  • @JivanPal Oops! Fixed. – jamesdlin Oct 13 '20 at 19:46
  • 1
    I use an alias for the following, for even more attractive output, and inline dates for more compact output: `git log --graph --all --pretty=format:"%Cred%h%Creset - %Cgreen(%cr)%Creset %s%C(yellow)%d%Creset" --abbrev-commit --date=relative` – amcgregor Dec 19 '20 at 22:41
23

With git 2.9.x/2.10 (Q3 2016), you won't have to use git reflog --all anymore, git reflog will be enough.

See commit 71abeb7 (03 Jun 2016) by SZEDER Gábor (szeder).
(Merged by Junio C Hamano -- gitster -- in commit 7949837, 06 Jul 2016)

reflog: continue walking the reflog past root commits

If a repository contains more than one root commit, then its HEAD reflog may contain multiple "creation events", i.e. entries whose "from" value is the null sha1.
Listing such a reflog currently stops prematurely at the first such entry, even when the reflog still contains older entries.
This can scare users into thinking that their reflog got truncated after 'git checkout --orphan'.

Continue walking the reflog past such creation events based on the preceeding reflog entry's "new" value.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
5

One good feature of git is that it detects corruption. However, it does not include error correction to protect from corruption.

I hope that you have pushed the contents of this repository to another machine or that you have backups to recover the corrupted parts.

I do not have any experience with git on windows but have never seen this sort of behavior with git on Linux or OS X.

Jamey Hicks
  • 2,340
  • 1
  • 14
  • 20
1

If you wish to see only your orphaned commits, you can use the following commands (using a *nix shell):

# Save the output to a file since it might take a minute.
git fsck --unreachable > unreachable.txt
# Note unreachable.txt now includes all unreachable blobs, trees, and commits.
cat unreachable.txt | grep commit
TTT
  • 22,611
  • 8
  • 63
  • 69
  • if you only want the commits you can also do this: `git fsck --unreachable |grep commit > unreachable.txt` – JoSSte Nov 14 '22 at 18:38
  • @JoSSte Agreed! It's been a while, but I think the reason I didn't elect to write the answer that way is because the `fsck` portion is the slower part compared to the grep, so if you do wish to look at the blobs or trees later you still have them. That being said, that's not the way I worded the answer so maybe I just didn't think of it. Thanks either way. ;) – TTT Jan 25 '23 at 19:23