0

Suppose I have this history:

...
* c1   
...
* cr: git revert c1
...

Given the commit hash of cr, is there a programmatic way to retrieve the commit hash of c1? It doesn't need to be porcelain, plumbing is fine too.

Cactus
  • 27,075
  • 9
  • 69
  • 149
  • 1
    Normally `git revert` writes you a commit message that says `This reverts commit `. Is that missing or incorrect for some reason? (If so, you're mostly out of luck: you can try reverting the revert and then see if you can find an earlier commit with the same changes, using `git cherry` for instance. On the gripping hand, often you can just revert the revert.) – torek Oct 09 '15 at 03:03
  • I need the original commit so that I can get some metadata from it. I should add to my question that I am looking for a programmatic way. – Cactus Oct 09 '15 at 03:04
  • Do you do a lot of reverts? That might indicate a problem with your development model. – Schwern Oct 09 '15 at 03:29
  • @Schwern: I don't usually do reverts at all. What I'm trying to solve here is more related to detecting messes caused by other developers. – Cactus Oct 09 '15 at 03:31

2 Answers2

3

As noted in comment, this relies on the normal revert log message, but is otherwise easy:

git log -1 --format=%B $revspec | \
    perl -n -e '/^This reverts commit ([0-9a-f]+)/ && print $1 '

(where $revspec is the way you intend to name the revert commit, whether that's a raw SHA-1, or something like master~5, or whatever).

(If the ID is missing from the commit message, you'll get no output. In this case, or if the ID is present but incorrect, you're pretty much SOL.)

Cactus
  • 27,075
  • 9
  • 69
  • 149
torek
  • 448,244
  • 59
  • 642
  • 775
  • 1
    @Cactus Git commits don't store much in the way of metadata, they rely on commit messages, and it's a shame. – Schwern Oct 09 '15 at 03:23
1

Yes. The default revert log message contains the ID of the original. You can parse git log to find it. @torek has already covered this.

What if you didn't use the default revert message? You're SOL. Why? Git doesn't store the revert information anywhere else. And you can't derive the original commit ID.

The commit ID is a cryptographic checksum meaning it contains no information about what it is a checksum of. You can't extract information about the commit from the checksum.

Could you use the diff with the previous commit to regenerate the original commit message? Again, no. First, it's not guaranteed the diff will be the same, for example there could have been a conflict or pieces of the diff can have moved around. More importantly, the commit ID is a checksum of more than just the content including things like the content of the files, the log message, the date, and so on. You'd need to know all that as well to generate the original commit ID.

Your final refuge for undoing things is git reflog, but this won't help you either. It will record the fact that there was a revert, but the message will be the first line of your commit message. It will not contain the original commit ID.


There is a hope, but it's not programmatic. Get the diff of the revert, find a significant line of change, remove the + or -. Now run git log -S'...yourline' to find commits which changed that line.

For example, let's say I have...

commit 2c257ccae4c124e7cff6cfa7ca069250fb33907f (HEAD -> master)
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Thu Oct 8 20:19:26 2015 -0700

    dlfjalkdjflkadj

diff --git a/Build.PL b/Build.PL
index 8c87db4..bed5170 100644
--- a/Build.PL
+++ b/Build.PL
@@ -73,10 +73,6 @@ my $builder = MyBuild->new(
         # so some CPAN shells won't see it.
         "Module::Build"      => '0.36',
     },
-    recommends => {
-        # Significant performance improvements
-        autodie         => '2.26',
-    },

     meta_merge => {
         resources => {

I could then run git log -S'Significant performance improvements' and get:

commit 2c257ccae4c124e7cff6cfa7ca069250fb33907f (HEAD -> master)
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Thu Oct 8 20:19:26 2015 -0700

    dlfjalkdjflkadj

commit ac43bedc8c70fb851c7a594cace18d5fbad135ac
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Wed Dec 31 14:46:05 2014 -0800

    Recommend the latest autodie which has significant performance improvements.

    It's loads much faster and uses much less memory and has significant bug fixes.
    None of this is required by perl5i, so I left the required version at what
    Debian stable is using.

    In the future this can be bumped to a requirement.

    For #284
Community
  • 1
  • 1
Schwern
  • 153,029
  • 25
  • 195
  • 336