threads / discuss / 60056

[Question] git rev-parse verify for non-existent object

Subject: [Question] git rev-parse verify for non-existent object

## tl;dr

5 messages between Aug 2, 2023 and Aug 3, 2023.

replies: 4people: 3as markdown or json

ZheNing Hu· Aug 2, 2023, 07:50 UTC · lore

In my case, I often need to use "git rev-parse --verify" to verify if a revision exists in the repository, and this usually works:

git rev-parse --verify HEAD afa5ff0f56bc60d1c9abe839726e7fb2105a9ca3

git rev-parse --verify afa5ff0f56bc60d1c9abe839726e7fb2105a9ca3 afa5ff0f56bc60d1c9abe839726e7fb2105a9ca3

git rev-parse --verify aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa fatal: Needed a single revision

However, when I started checking for a non-existent OID that happened
to be exactly 40 characters long, something unexpected happened.
 "git rev-parse --verify" did not produce any error messages.
I consider this to be a BUG.

git rev-parse --verify aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

I understand that using "git cat-file --batch-check="%(objectname)" may be a potential solution, but I currently do not want to do it because it would require significant changes and I am unsure if the behavior would be consistent.

The simplest solution for me would be to fix "git rev-parse --verify". What do you all think?

-- ZheNing Hu

Christian Couder· Aug 2, 2023, 10:24 UTC · re: ZheNing Hu · lore

Re: [Question] git rev-parse verify for non-existent object

On Wed, Aug 2, 2023 at 9:50 AM ZheNing Hu <adlternative@gmail.com> wrote:
Show 20 quoted lines
>
> In my case, I often need to use "git rev-parse --verify" to verify
> if a revision exists in the repository, and this usually works:
>
> git rev-parse --verify HEAD
> afa5ff0f56bc60d1c9abe839726e7fb2105a9ca3
>
> git rev-parse --verify afa5ff0f56bc60d1c9abe839726e7fb2105a9ca3
> afa5ff0f56bc60d1c9abe839726e7fb2105a9ca3
>
> git rev-parse --verify aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> fatal: Needed a single revision
>
> However, when I started checking for a non-existent OID that happened
> to be exactly 40 characters long, something unexpected happened.
>  "git rev-parse --verify" did not produce any error messages.
> I consider this to be a BUG.
>
> git rev-parse --verify aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
The doc says:
"
      --verify
          Verify that exactly one parameter is provided, and that it
can be turned into a raw 20-byte SHA-1 that can be used to access the
object database. If so, emit it to the standard output;
          otherwise, error out.
          If you want to make sure that the output actually names an
object in your object database and/or can be used as a specific type
of object you require, you can add the ^{type} peeling
          operator to the parameter. For example, git rev-parse
"$VAR^{commit}" will make sure $VAR names an existing object that is a
commit-ish (i.e. a commit, or an annotated tag that points
          at a commit). To make sure that $VAR names an existing
object of any type, git rev-parse "$VAR^{object}" can be used.
"

So "--verify <argument>" only checks that the <argument> provided to it can be turned into a raw 20-byte SHA-1 (or perhaps a raw 32-byte SHA256 in case the repo is using SHA256). "^{object}" should be added at the end of the <argument> if you want to verify that the raw 20-byte SHA-1 (or the raw 32-byte SHA256) also corresponds to an actual object in the repo.

$ git rev-parse --verify aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^{object} fatal: Needed a single revision

Hope this helps.
ZheNing Hu· Aug 2, 2023, 13:03 UTC · re: Christian Couder · lore

Re: [Question] git rev-parse verify for non-existent object

Christian Couder <christian.couder@gmail.com> 于2023年8月2日周三 18:25写道:
Show 32 quoted lines
>
> On Wed, Aug 2, 2023 at 9:50 AM ZheNing Hu <adlternative@gmail.com> wrote:
> >
> > In my case, I often need to use "git rev-parse --verify" to verify
> > if a revision exists in the repository, and this usually works:
> >
> > git rev-parse --verify HEAD
> > afa5ff0f56bc60d1c9abe839726e7fb2105a9ca3
> >
> > git rev-parse --verify afa5ff0f56bc60d1c9abe839726e7fb2105a9ca3
> > afa5ff0f56bc60d1c9abe839726e7fb2105a9ca3
> >
> > git rev-parse --verify aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> > fatal: Needed a single revision
> >
> > However, when I started checking for a non-existent OID that happened
> > to be exactly 40 characters long, something unexpected happened.
> >  "git rev-parse --verify" did not produce any error messages.
> > I consider this to be a BUG.
> >
> > git rev-parse --verify aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
>
> The doc says:
>
> "
>       --verify
>           Verify that exactly one parameter is provided, and that it
> can be turned into a raw 20-byte SHA-1 that can be used to access the
> object database. If so, emit it to the standard output;
>           otherwise, error out.
>
So why doesn't "git rev-list --verify" check if 20-byte SHA-1 can
 "access the object database"?
Show 21 quoted lines
>           If you want to make sure that the output actually names an
> object in your object database and/or can be used as a specific type
> of object you require, you can add the ^{type} peeling
>           operator to the parameter. For example, git rev-parse
> "$VAR^{commit}" will make sure $VAR names an existing object that is a
> commit-ish (i.e. a commit, or an annotated tag that points
>           at a commit). To make sure that $VAR names an existing
> object of any type, git rev-parse "$VAR^{object}" can be used.
> "
>
> So "--verify <argument>" only checks that the <argument> provided to
> it can be turned into a raw 20-byte SHA-1 (or perhaps a raw 32-byte
> SHA256 in case the repo is using SHA256). "^{object}" should be added
> at the end of the <argument> if you want to verify that the raw
> 20-byte SHA-1 (or the raw 32-byte SHA256) also corresponds to an
> actual object in the repo.
>
> $ git rev-parse --verify aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^{object}
> fatal: Needed a single revision
>
> Hope this helps.
Thank you, your method is effective for me.
Junio C Hamano· Aug 2, 2023, 16:32 UTC · re: ZheNing Hu · lore

Re: [Question] git rev-parse verify for non-existent object

ZheNing Hu <adlternative@gmail.com> writes:
Show 9 quoted lines
>>       --verify
>>           Verify that exactly one parameter is provided, and that it
>> can be turned into a raw 20-byte SHA-1 that can be used to access the
>> object database. If so, emit it to the standard output;
>>           otherwise, error out.
>>
>
> So why doesn't "git rev-list --verify" check if 20-byte SHA-1 can
>  "access the object database"?
Hysterical Raisins.

"rev-parse" can do many things, and one of them is about expanding strings (like "9e4df4da", "jt/path-filter-fix", "seen~7^2", and "9e4df4da0786797b1d51ed8fd3dfc18970772a91") given from the command line into hexadecimal strings of the full length (they are often called "revision"). "--verify" tells the command that on the command line there must be ONE and only one "revision", give the full length hexadecimal string for it. The command fails if the command line argument cannot be turned into a hexadecimal string of the full length.

Now, among the ones given as examples in the above, "9e4df4da", needs to look at the object database to turn it into a hexadecimal string of the full length, because it is likely to be an abbrevation (although it could be a branch name, too). "jt/path-filter-fix" and "seen~7^2" needs to look at the refs and probably into the object database (to see what the 7th generation grandparent is and what the second parent of that commit is) before they can be turned into hexadecimal strings of the full length.

But "9e4df4da0786797b1d51ed8fd3dfc18970772a91" is already a full hexadecimal, so it is given back as a "revision" without checking if there is such an object in the object database.

Checking if it can be turned into the form that can be used to query the object database, and checking the object database using it to find out if such an object exists, are two distinct steps low-level tool authors, who would want to use the plumbing tools, may need. The current option set allows the separation (and ^{object} suffix lets you do the both at the same time, too).

ZheNing Hu· Aug 3, 2023, 06:16 UTC · re: Junio C Hamano · lore

Re: [Question] git rev-parse verify for non-existent object

Junio C Hamano <gitster@pobox.com> 于2023年8月3日周四 00:32写道:
Show 38 quoted lines
>
> ZheNing Hu <adlternative@gmail.com> writes:
>
> >>       --verify
> >>           Verify that exactly one parameter is provided, and that it
> >> can be turned into a raw 20-byte SHA-1 that can be used to access the
> >> object database. If so, emit it to the standard output;
> >>           otherwise, error out.
> >>
> >
> > So why doesn't "git rev-list --verify" check if 20-byte SHA-1 can
> >  "access the object database"?
>
> Hysterical Raisins.
>
> "rev-parse" can do many things, and one of them is about expanding
> strings (like "9e4df4da", "jt/path-filter-fix", "seen~7^2", and
> "9e4df4da0786797b1d51ed8fd3dfc18970772a91") given from the command
> line into hexadecimal strings of the full length (they are often
> called "revision").  "--verify" tells the command that on the
> command line there must be ONE and only one "revision", give the
> full length hexadecimal string for it.  The command fails if the
> command line argument cannot be turned into a hexadecimal string of
> the full length.
>
> Now, among the ones given as examples in the above, "9e4df4da",
> needs to look at the object database to turn it into a hexadecimal
> string of the full length, because it is likely to be an abbrevation
> (although it could be a branch name, too).  "jt/path-filter-fix" and
> "seen~7^2" needs to look at the refs and probably into the object
> database (to see what the 7th generation grandparent is and what the
> second parent of that commit is) before they can be turned into
> hexadecimal strings of the full length.
>
> But "9e4df4da0786797b1d51ed8fd3dfc18970772a91" is already a full
> hexadecimal, so it is given back as a "revision" without checking if
> there is such an object in the object database.
>

Well, so the "git rev-parse --verify" command simply converts the revision into a 20-byte SHA-1 without actually performing any real "verification", which can be quite misleading.

Show 7 quoted lines
> Checking if it can be turned into the form that can be used to query
> the object database, and checking the object database using it to
> find out if such an object exists, are two distinct steps low-level
> tool authors, who would want to use the plumbing tools, may need.
> The current option set allows the separation (and ^{object} suffix
> lets you do the both at the same time, too).
>
Thanks for the answer.

← back to recent threads