{"thread":{"id":"26261","subject":"[PATCH] Documentation/rev-parse: --verify does not check existence","startedAt":"2011-01-11T18:51:02Z","lastAt":"2011-01-11T21:00:28Z","messageCount":2,"participants":["Thomas Rast","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"159363","messageId":"2441701cf9c9cc09d86f52b093bfa896479daad8.1294771717.git.trast@student.ethz.ch","threadId":"26261","inReplyTo":null,"subject":"[PATCH] Documentation/rev-parse: --verify does not check existence","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2011-01-11T18:51:02Z","receivedAt":"2011-01-11T18:51:02Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Rather counterintuitively,\n\n  $ git rev-parse --verify aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\ndoes *not* fail.  The check is based solely on whether we can come up\nwith something that \"looks like\" a SHA1, not whether the object\nactually exists.  To wit:\n\n  # this cannot be done with update-ref as that *does* check\n  $ echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > .git/refs/heads/nonexistent\n  $ git rev-parse --verify nonexistent\n  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\nNote that the commit message of 79162bb makes clear that this is\nexactly the intended behaviour:\n\n  git-rev-parse: Allow a \"zeroth\" parent of a commit - the commit itself.\n\n  This sounds nonsensical, but it's useful to make sure that the result is\n  a commit.\n[...]\n  Also, since the \"parent\" code will actually parse the commit, this,\n  together with the \"--verify\" flag, will verify not only that the result\n  is a single SHA1, but will also have verified that it's a proper commit\n  that we can see.\n\nDocument this clearly in the description for --verify.\n\nFurthermore the second item in EXAMPLES\n\n  * Print the commit object name from the revision in the $REV shell variable:\n\nseems to imply that rev-parse should actually check that the object\nexists *and* is a commit, when in reality it does neither.  We could\nsuggest the ^0 trick alluded to above, but instead document the more\nverbose (and clear)\n\n  $ git rev-parse --verify \"$REV^{commit}\"\n\nObserve that if you ran\n\n  $ git rev-parse --verify \"nonexistent^{commit}\"\n\nafter the above setup, the failure would come from the ^{} peeling\noperator and not from --verify.\n\nNoticed-by: Zachery Hostens <zacheryph@gmail.com>\nSigned-off-by: Thomas Rast <trast@student.ethz.ch>\n---\n Documentation/git-rev-parse.txt |   23 +++++++++++++++++------\n 1 files changed, 17 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex ff23cb0..779fa87 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -59,8 +59,9 @@ OPTIONS\n \tinstead.\n \n --verify::\n-\tThe parameter given must be usable as a single, valid\n-\tobject name.  Otherwise barf and abort.\n+\tThe parameter must either be formed like an object name, or\n+\tdereference to an object name.  This does 'not' verify that\n+\tthe object actually exists!  See EXAMPLES below.\n \n -q::\n --quiet::\n@@ -292,21 +293,31 @@ EXAMPLES\n $ git rev-parse --verify HEAD\n ------------\n \n-* Print the commit object name from the revision in the $REV shell variable:\n+* Print the object name from the revision in the $REV shell variable:\n +\n ------------\n $ git rev-parse --verify $REV\n ------------\n +\n-This will error out if $REV is empty or not a valid revision.\n+This will error out if $REV does not dereference to a well-formed\n+object name (i.e., SHA1).\n \n-* Same as above:\n+* Same as above, but also verify that the object exists and is a commit:\n++\n+------------\n+$ git rev-parse --verify \"$REV^{commit}\"\n+------------\n++\n+This works because the `{caret}\\{commit\\}` peeling operator will fail\n+unless the object exists and can be peeled into a commit.\n+\n+* Print the object name from $REV, but default to master:\n +\n ------------\n $ git rev-parse --default master --verify $REV\n ------------\n +\n-but if $REV is empty, the commit object name from master will be printed.\n+If $REV is empty, the commit object name from master will be printed.\n \n \n Author\n-- \n1.7.4.rc1.309.g58aa0\n"},{"id":"159382","messageId":"7v39oz40lv.fsf@alter.siamese.dyndns.org","threadId":"26261","inReplyTo":"2441701cf9c9cc09d86f52b093bfa896479daad8.1294771717.git.trast@student.ethz.ch","subject":"Re: [PATCH] Documentation/rev-parse: --verify does not check existence","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-11T21:00:28Z","receivedAt":"2011-01-11T21:00:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n> diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\n> index ff23cb0..779fa87 100644\n> --- a/Documentation/git-rev-parse.txt\n> +++ b/Documentation/git-rev-parse.txt\n> @@ -59,8 +59,9 @@ OPTIONS\n>  \tinstead.\n>  \n>  --verify::\n> -\tThe parameter given must be usable as a single, valid\n> -\tobject name.  Otherwise barf and abort.\n> +\tThe parameter must either be formed like an object name, or\n> +\tdereference to an object name.  This does 'not' verify that\n> +\tthe object actually exists!  See EXAMPLES below.\n\nTo paraphrase what this text says, if you do\n\n\techo >.git/refs/tags/next e17aa8a9dca972ca278dd91a097873101066e963\n\nwhere that hexstring does not name any existing object [*1*], you can\nsuccessfully verify \"tags/next\" (i.e. \"git rev-parse --verify tags/next\"),\nbut not \"tags/next^0\", because \"tags/next^0\" does not \"dereference\" to a\n40-hex string, while \"tags/next\" does.\n\nThat's all good, but as I said, the hexstring is _not_ an object name.  So\n\"dereference to an object name\" is actively a wrong thing to say here.\n\nYou meant \"40-hex string\" with \"formed _like_ an object name\" in the\nabove, and the \"like\" is an attempt to say \"could be usable to name an\nobject, but does not mean that the object has to exist\".\n\nBut \"dereferencing\" a 40-hex string yields itself, so what you wrote can\nbe simplified to something like this, without using a wrong term \"object\nname\":\n\n        Makes sure that the parameter dereferences to a string of 40\n        hexadecimal characters.  Otherwise barf and abort.\n\nBut then, if you read the original carefully, it already says \"must be\nusable as a single valid object name\", and \"be usable as\" does not\nnecessarily mean \"named object must exist\".  So I agree you identified\nsomething that needs to be clarified, but I do not think your rewrite\nclarified things very much.\n\nHow about this?\n\n\tThe parameter given must be usable as a string to name a single\n        object (note that the named object does not have to exist).\n        Otherwise barf and abort.\n\nUnfortunately, this does not clarify if it satisfies the above condition\nto say \"refs/heads/nosuch\" in a repository without \"nosuch\" branch---the\nref expression is usable as a string to name a single object, so it should\nverify Ok, but the reason it doesn't name a single object is not because\nit yields a 40-hex string that no object with that name exists, but\nbecause it doesn't dereference to a 40-hex string to begin with.  So it\nactually should _not_ verify well.\n\nTo fully clarify this, I think the first step we need is to add a better\ndefinition of \"to dereference\" (or whatever word we would end up using to\ncall the act of passing a string through get_sha1()) to the glossary.\nThen we can use the \"string of 40 hexadecimal\" rewrite I gave earlier.\n\n[Footnote]\n\n*1* These days, \"git tag\" and even \"git update-ref\" seems to verify that\nthe given name actually refers to an existing object, so this experiment\nhas to be done by manually futzing with the repository.  Joy of safety ;-)\n"}]}