I exec cp -a gitrepo1/ gitrepo2/
in Mac, it seems files and dirs include .git/
are copied into gitrepo2/, how can I restore gitrepo2?
-
By restoring the files from your regular backups, of course! – Cairnarvon May 09 '13 at 04:07
-
Tragedy, no backups, no remote repos! I'm crying. – nfpyfzyf May 09 '13 at 04:08
-
If you had a remote for gitrepo2, you can try setting it and restoring from that? – hd1 May 09 '13 at 04:10
-
First lesson (for future reference): use `git pull` rather than `cp`. – Code-Apprentice May 09 '13 at 05:05
1 Answers
The copy action shouldn't have overwritten the old objects - that's the point of hashed object names; they're unique! Maybe you just had a master branch, and so you've overwritten the .git/refs/heads/master
branch and your .git/HEAD
file. That just means the commits you want are no longer part of a referred-to chain of commits. That means the commits you lost are unreachable. We can find unreachable commits thus:
git fsck --unreachable | grep commits | cut -d' ' -3
That should give you a list of all the commits that aren't in the ancestry (inclusive) of a branch, or tagged commit. You can do various things at this point. For example, you can glue all of these together and send them to gitk to visualize the crazy graph of all of them. If you just have a single master branch, though, things can be pretty easy. We just need to take all of these 'lost' commits, sort them by commit time (author time would be less helpful if commits had been reordered via cherry-pick or rebasing), and look at the commit(s) at the end of the list:
git fsck --unreachable | cut -d' ' -f3 | while read c; do git log -1 --format='%ct %H %s' $c; done | sort
This will be a mix of two repos' worth of commits, but the messages should help. Once you [hopefully] find the old head, get its hash number and (presuming you're on master and want to restore the old master to its rightful place):
git reset --hard <hash>
That should do it! I'm not 100% sure that git fsck --unreachable
really, truly shows all commits (this is worth a scan, even though they're talking about objects, not commits). There's also git fsck --full
, which is supposed to find commits with no parents, but I'm even less trusting of it for finding commits from two separate, original source repos. I think the ideas are sound, though, so if this doesn't find the old head(s), then I'd look first at a better method of tracking down every single commit in the objects folder and any pack file(s).

- 1
- 1

- 5,632
- 2
- 23
- 39