Ever misplaced a stash in git? Like, you accidentally entered "git stash drop" instead of "pop"? Or you did pop, but then went ahead and thoughtlessly did a "git reset --hard"?

If there just went a day's work, you'll be pissed. At yourself mostly, but still. You'll try "git reflog", as always when you've screwed up. However this time, it doesn't help. Things are screwed six ways till Sunday, you're in tears, co-workers laugh at you and your boss threatens to can your sorry ass. But wait, there is help. Unless you've also "git prune"d your repository...

Using "git fsck --unreachable" you can have a list of stuff that's still there, but "unreachable" from the usual tree. You can still say "git show -p $id" to take a look at the unreachable stuff, though. And that's where the magic is. Now, depending on your workflow, there could potentially be a lot output from said command. So let's just throw a bit of Perl at it to run through all the lines one by one:

#!/usr/bin/perl
use warnings;
use strict;
my ($dat, $line, $y);
$y = 0;
open $dat, "git fsck --unreachable |"
    or die "Couldn't run `git-fsck': $!\n";
LINE: while ($line = <$dat>) {
    chomp $line;
    my ($u, $type, $id) = split / +/, $line;
    next LINE unless ($type eq 'commit');
    print "\n Showing `$id'\n\n";
    system(( "git", "show", "--patch", "$id" ));
    print "\n Has this been the commit you were looking for? (y/N) ";
    my $ans = <STDIN>;
    chomp $ans;
    if ($ans eq 'y' || $ans eq 'Y') {
        $y = 1;
        print "\n The chosen commit's id is: `$id'\n\n";
        last LINE;
    }
}
if ($y != 1) {
    print "\n Sorry, I couldn't help you it would seem.\n\n";
}
close $dat;

Throw that into an executable file "git-unreachable" somewhere in your path and you'll be able to call it like a regular git sub-command: "git unreachable"

If this has been helpful to you, flattr me. Oh wait. You can't. Send beer and pizza.

Posted Fri 23 Sep 2011 09:13:05 CEST Tags: