{"thread":{"id":"30431","subject":"how to determine version of binary","startedAt":"2012-05-05T07:12:44Z","lastAt":"2012-05-06T12:43:42Z","messageCount":5,"participants":["Neal Kreitzinger","Jeff King","Sitaram Chamarty"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"190827","messageId":"jo2jtd$m6c$1@dough.gmane.org","threadId":"30431","inReplyTo":null,"subject":"how to determine version of binary","fromName":"Neal Kreitzinger","fromEmail":"nkreitzinger@gmail.com","sentAt":"2012-05-05T07:12:44Z","receivedAt":"2012-05-05T07:12:44Z","isPatch":false,"sender":{"key":"nkreitzinger@gmail.com","avatar":null},"body":"Scenario:  I detect a binary file that is 'dirty'.  I don't know how it \ngot there.  However, I know it came from a git repo.  So I calculate the \nsha1 of the binary.  What is the git command to determine which commit \nthat binary version first appeared in?  And the last commit that binary \nappeared in?\n\nWhy:  we have people ftp'ing binaries around.  I want to see the commit \nmessage and source change of that commit to see what the binary version is.\n\nv/r,\nneal\n"},{"id":"190831","messageId":"20120505092443.GB8172@sigill.intra.peff.net","threadId":"30431","inReplyTo":"jo2jtd$m6c$1@dough.gmane.org","subject":"Re: how to determine version of binary","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2012-05-05T09:24:43Z","receivedAt":"2012-05-05T09:24:43Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, May 05, 2012 at 02:12:44AM -0500, Neal Kreitzinger wrote:\n\n> Scenario:  I detect a binary file that is 'dirty'.  I don't know how\n> it got there.  However, I know it came from a git repo.  So I\n> calculate the sha1 of the binary.  What is the git command to\n> determine which commit that binary version first appeared in?  And\n> the last commit that binary appeared in?\n\nThere is no pre-made git commit. I would look at the output of \"git log --raw\n--no-abbrev\" in a pager and search for the sha1 in question. That will show you\nthe commits that made it come and go. Note that there may be multiple instances\nin which the sha1 comes and goes (e.g., two parallel lines of development which\nboth introduce or modify a sha1, or even linear development with reverting).\n\nYou can script it like this:\n\n  git log --format=%H --no-abbrev --raw |\n  perl -lne '\n    BEGIN { $sha1 = shift }\n    if (/^[0-9a-f]{40}$/) {\n      $commit = $_;\n    }\n    elsif (/^:\\d+ \\d+ ([0-9a-f]{40}) ([0-9a-f]{40}) \\S+\\t(.*)/) {\n      if ($2 eq $sha1) {\n        # sha1 on \"after\" side; content probably came into existence\n        if ($1 eq $sha1) {\n          # unless it was that way before, in which case it was a mode change\n          # or rename. Ignore.\n        }\n        else {\n          print \"$commit: $sha1 appears (as $3)\";\n        }\n      }\n      elsif ($1 eq $sha1) {\n        # sha1 on \"before\" side; content went away\n        print \"$commit: $sha1 went away (from $3)\";\n      }\n    }\n  ' $sha1_of_interest\n\nthough I wouldn't bother to do so unless I was going to do some analysis over\nmany files.\n\n> Why:  we have people ftp'ing binaries around.  I want to see the\n> commit message and source change of that commit to see what the\n> binary version is.\n\nThis won't necessarily show you the version they have; it will only show you\nthe version that introduced that particular version of a file. A more general\nquestion is \"given a set of files, which revision did they come from?\".  For\nthat, you would want to find the set of commits that contain sha1 A, then\nintersect them with the set of commits that contain sha1 B, and so forth. You\ncan do that by scripting around \"rev-list\" and \"ls-tree\", but it's a little\nmore complicated.\n\n-Peff\n"},{"id":"190834","messageId":"20120505114306.GA1498@sita-lt.atc.tcs.com","threadId":"30431","inReplyTo":"jo2jtd$m6c$1@dough.gmane.org","subject":"Re: how to determine version of binary","fromName":"Sitaram Chamarty","fromEmail":"sitaramc@gmail.com","sentAt":"2012-05-05T11:43:06Z","receivedAt":"2012-05-05T11:43:06Z","isPatch":false,"sender":{"key":"sitaramc@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43316?v=4"},"body":"\nOn Sat, May 5, 2012 at 12:42 PM, Neal Kreitzinger <nkreitzinger@gmail.com> wrote:\n> Scenario:  I detect a binary file that is 'dirty'.  I don't know how it got\n> there.  However, I know it came from a git repo.  So I calculate the sha1 of\n> the binary.  What is the git command to determine which commit that binary\n\nmake sure you are using 'git hash-object' to compute the sha,\nnot the system supplied 'sha1sum' or eqvt.\n\n> version first appeared in?  And the last commit that binary appeared in?\n\nUnless it is a frequent need, I would just use git log's --raw\noption to search for the first 7 digits of the SHA you found\nabove.\n\nFor example, a very quick one (which does not count odd\nsituations like the same file appearing multiple times or on\nother branches, for instance) is:\n\n    git log --raw | less +/$SHA\n\nYou'll want a line where the SHA appears as the second SHA, not\nthe first one (in case a later commit changed the file it would\nalso appear as the first sha).  Example, I'm looking for\n\"14136eb\", so I type in\n\n    git log --raw '--format=%n%ncommit: %h subject: %s' | egrep commit\\|14136eb | grep -B 1 14136eb\n\nThe output I get back is:\n\n    commit: 1cf062f subject: ACCESS_CHECK split into ACCESS_1 and ACCESS_2; docs updated\n    :100755 100755 14136eb... 2a57e2d... M\tsrc/gitolite-shell\n    --\n    commit: b391000 subject: POST_GIT triggers get 4 more arguments\n    :100755 100755 20f4e5d... 14136eb... M\tsrc/gitolite-shell\n\nSo the commit that introduced this version of this file is\nb391000 (1cf062f is a later one where this file got changed to\nsomething else).\n"},{"id":"190849","messageId":"4FA552C5.7090000@gmail.com","threadId":"30431","inReplyTo":"20120505092443.GB8172@sigill.intra.peff.net","subject":"Re: how to determine version of binary","fromName":"Neal Kreitzinger","fromEmail":"nkreitzinger@gmail.com","sentAt":"2012-05-05T16:18:13Z","receivedAt":"2012-05-05T16:18:13Z","isPatch":false,"sender":{"key":"nkreitzinger@gmail.com","avatar":null},"body":"On 5/5/2012 4:24 AM, Jeff King wrote:\n> On Sat, May 05, 2012 at 02:12:44AM -0500, Neal Kreitzinger wrote:\n>\n>> Scenario:  I detect a binary file that is 'dirty'.  I don't know how\n>> it got there.  However, I know it came from a git repo.  So I\n>> calculate the sha1 of the binary.  What is the git command to\n>> determine which commit that binary version first appeared in?  And\n>> the last commit that binary appeared in?\n> There is no pre-made git commit. I would look at the output of \"git log --raw\n> --no-abbrev\" in a pager and search for the sha1 in question. That will show you\n> the commits that made it come and go. Note that there may be multiple instances\n> in which the sha1 comes and goes (e.g., two parallel lines of development which\n> both introduce or modify a sha1, or even linear development with reverting).\n>\n> You can script it like this:\n>\n>    git log --format=%H --no-abbrev --raw |\n>    perl -lne '\n>      BEGIN { $sha1 = shift }\n>      if (/^[0-9a-f]{40}$/) {\n>        $commit = $_;\n>      }\n>      elsif (/^:\\d+ \\d+ ([0-9a-f]{40}) ([0-9a-f]{40}) \\S+\\t(.*)/) {\n>        if ($2 eq $sha1) {\n>          # sha1 on \"after\" side; content probably came into existence\n>          if ($1 eq $sha1) {\n>            # unless it was that way before, in which case it was a mode change\n>            # or rename. Ignore.\n>          }\n>          else {\n>            print \"$commit: $sha1 appears (as $3)\";\n>          }\n>        }\n>        elsif ($1 eq $sha1) {\n>          # sha1 on \"before\" side; content went away\n>          print \"$commit: $sha1 went away (from $3)\";\n>        }\n>      }\n>    ' $sha1_of_interest\n>\n> though I wouldn't bother to do so unless I was going to do some analysis over\n> many files.\n>\n>> Why:  we have people ftp'ing binaries around.  I want to see the\n>> commit message and source change of that commit to see what the\n>> binary version is.\n> This won't necessarily show you the version they have; it will only show you\n> the version that introduced that particular version of a file. A more general\n> question is \"given a set of files, which revision did they come from?\".  For\n> that, you would want to find the set of commits that contain sha1 A, then\n> intersect them with the set of commits that contain sha1 B, and so forth. You\n> can do that by scripting around \"rev-list\" and \"ls-tree\", but it's a little\n> more complicated.\n>\nWhat about this recipe:\n\ncalculate sha1 of dirty deliverable (binary, html, etc)\n\ngrep git tree objects for that sha1\n\nsomehow determine which of the tree sha1's is newest.  Not sure how to \ndo that.\n\ngrep commit objects for that tree sha1\n\nnow you have the last commit containing that file so now you know the \nversion of that file.\n\n-neal\n"},{"id":"190905","messageId":"20120506124342.GC26194@sigill.intra.peff.net","threadId":"30431","inReplyTo":"4FA552C5.7090000@gmail.com","subject":"Re: how to determine version of binary","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2012-05-06T12:43:42Z","receivedAt":"2012-05-06T12:43:42Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, May 05, 2012 at 11:18:13AM -0500, Neal Kreitzinger wrote:\n\n> What about this recipe:\n> \n> calculate sha1 of dirty deliverable (binary, html, etc)\n> \n> grep git tree objects for that sha1\n> \n> somehow determine which of the tree sha1's is newest.  Not sure how\n> to do that.\n> \n> grep commit objects for that tree sha1\n>\n> now you have the last commit containing that file so now you know the\n> version of that file.\n\nYour \"not sure\" step would be to walk the revision graph and look for\nthe tree in question. So really you would just walk and grep the trees.\nIf you know the filename (which you do in your instance), then it's not\neven that expensive:\n\n  git rev-list HEAD |\n  while read commit; do\n    if test \"`git rev-parse $commit:path/to/file`\" = $sha1; then\n      echo \"found it in $commit\"\n      break\n    fi\n  done\n\nBut note that that does not tell you the revision of the whole project.\nIt tells you one _possible_ version, because it is one that contains\nthat file.  If you remove the \"break\" there you can get the full set of\ncommits. And then you cross-reference that with the set of commits in\nanother file.  And then another, and so on, until you eventually have\nnarrowed it down to a single commit.\n\nIt's kind of slow, mostly because we have to invoke rev-parse over and\nover. But I don't think there is a way to print the sha1 of some path\nfor each revision via the regular revision walker.\n\nYou could probably do better by finding trees that contain a particular\nsha1, then finding trees that contain that tree, and so forth, until you\nhave a set of commits that contain those trees. And then you could do\nthat backwards walk for all of the files in parallel (i.e., only accept\na tree if it matches all of the deliverables you have).\n\n-Peff\n"}]}