{"thread":{"id":"56062","subject":"[PATCH] rev-list: add option for --pretty without header","startedAt":"2021-07-06T22:45:26Z","lastAt":"2021-07-13T00:16:12Z","messageCount":9,"participants":["brian m. carlson","Christian Couder","Junio C Hamano","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"429375","messageId":"20210706224321.14371-1-sandals@crustytoothpaste.net","threadId":"56062","inReplyTo":null,"subject":"[PATCH] rev-list: add option for --pretty without header","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2021-07-06T22:43:21Z","receivedAt":"2021-07-06T22:45:26Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"In general, we encourage users to use plumbing commands, like git\nrev-list, over porcelain commands, like git log, when scripting.\nHowever, git rev-list has one glaring problem that prevents it from\nbeing used in certain cases: when --pretty is used, it always prints out\na line containing \"commit\" and the object ID.  This makes it unsuitable\nfor many scripting needs, and forces users to use git log instead.\n\nWhile we can't change this behavior for backwards compatibility, we can\nadd an option to suppress this behavior, so let's do so, and call it\n\"--no-commit-header\".  Additionally, add the corresponding positive\noption to switch it back on.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\nThis has come up a lot on the list and I'm sure most of the regulars\nhave run into it before.  It came up at $DAYJOB and I said I intended to\nsend a patch, so here it is.\n\nI chose --no-commit-header because --header is already taken.  Of\ncourse, suggestions for better names are welcome, since we all know my\nnaming skills are terrible.\n\n Documentation/rev-list-options.txt |  7 +++++++\n builtin/rev-list.c                 | 17 ++++++++++++++---\n revision.h                         |  3 ++-\n t/t6006-rev-list-format.sh         | 23 ++++++++++++++++++++++-\n 4 files changed, 45 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex 5bf2a85f69..84b03a4cde 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -1064,6 +1064,13 @@ ifdef::git-rev-list[]\n --header::\n \tPrint the contents of the commit in raw-format; each record is\n \tseparated with a NUL character.\n+\n+--no-commit-header::\n+\tSuppress the header line containing \"commit\" and the object ID printed before\n+\tthe specified format.\n+\n+--commit-header::\n+\tOverrides a previous `--no-commit-header`.\n endif::git-rev-list[]\n \n --parents::\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex 7677b1af5a..f571cc9598 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -132,7 +132,7 @@ static void show_commit(struct commit *commit, void *data)\n \tif (revs->abbrev_commit && revs->abbrev)\n \t\tfputs(find_unique_abbrev(&commit->object.oid, revs->abbrev),\n \t\t      stdout);\n-\telse\n+\telse if (revs->include_header)\n \t\tfputs(oid_to_hex(&commit->object.oid), stdout);\n \tif (revs->print_parents) {\n \t\tstruct commit_list *parents = commit->parents;\n@@ -153,7 +153,7 @@ static void show_commit(struct commit *commit, void *data)\n \tshow_decorations(revs, commit);\n \tif (revs->commit_format == CMIT_FMT_ONELINE)\n \t\tputchar(' ');\n-\telse\n+\telse if (revs->include_header)\n \t\tputchar('\\n');\n \n \tif (revs->verbose_header) {\n@@ -512,6 +512,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \trepo_init_revisions(the_repository, &revs, prefix);\n \trevs.abbrev = DEFAULT_ABBREV;\n \trevs.commit_format = CMIT_FMT_UNSPECIFIED;\n+\trevs.include_header = 1;\n \n \t/*\n \t * Scan the argument list before invoking setup_revisions(), so that we\n@@ -627,6 +628,16 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \t\t\tcontinue;\n \t\t}\n \n+\t\tif (!strcmp(arg, (\"--commit-header\"))) {\n+\t\t\trevs.include_header = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(arg, (\"--no-commit-header\"))) {\n+\t\t\trevs.include_header = 0;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tif (!strcmp(arg, \"--disk-usage\")) {\n \t\t\tshow_disk_usage = 1;\n \t\t\tinfo.flags |= REV_LIST_QUIET;\n@@ -639,7 +650,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \tif (revs.commit_format != CMIT_FMT_UNSPECIFIED) {\n \t\t/* The command line has a --pretty  */\n \t\tinfo.hdr_termination = '\\n';\n-\t\tif (revs.commit_format == CMIT_FMT_ONELINE)\n+\t\tif (revs.commit_format == CMIT_FMT_ONELINE || !revs.include_header)\n \t\t\tinfo.header_prefix = \"\";\n \t\telse\n \t\t\tinfo.header_prefix = \"commit \";\ndiff --git a/revision.h b/revision.h\nindex 17698cb51a..7464434f60 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -215,7 +215,8 @@ struct rev_info {\n \t\t\tmissing_newline:1,\n \t\t\tdate_mode_explicit:1,\n \t\t\tpreserve_subject:1,\n-\t\t\tencode_email_headers:1;\n+\t\t\tencode_email_headers:1,\n+\t\t\tinclude_header:1;\n \tunsigned int\tdisable_stdin:1;\n \t/* --show-linear-break */\n \tunsigned int\ttrack_linear:1,\ndiff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh\nindex 35a2f62392..e68bf9f21c 100755\n--- a/t/t6006-rev-list-format.sh\n+++ b/t/t6006-rev-list-format.sh\n@@ -54,9 +54,15 @@ test_expect_success 'setup' '\n \n # usage: test_format name format_string [failure] <expected_output\n test_format () {\n+\tlocal header_arg=\n+\tif test \"$1\" = \"--no-commit-header\"\n+\tthen\n+\t\theader_arg=\"--no-commit-header\"\n+\t\tshift\n+\tfi\n \tcat >expect.$1\n \ttest_expect_${3:-success} \"format $1\" \"\n-\t\tgit rev-list --pretty=format:'$2' main >output.$1 &&\n+\t\tgit rev-list $header_arg --pretty=format:'$2' main >output.$1 &&\n \t\ttest_cmp expect.$1 output.$1\n \t\"\n }\n@@ -93,6 +99,14 @@ $head1\n $head1_short\n EOF\n \n+test_format --no-commit-header hash-no-header %H%n%h <<EOF\n+$head2\n+$head2_short\n+$head1\n+$head1_short\n+EOF\n+\n+\n test_format tree %T%n%t <<EOF\n commit $head2\n $tree2\n@@ -181,6 +195,13 @@ $added\n \n EOF\n \n+test_format --no-commit-header raw-body-no-header %B <<EOF\n+$changed\n+\n+$added\n+\n+EOF\n+\n test_expect_success 'basic colors' '\n \tcat >expect <<-EOF &&\n \tcommit $head2\n"},{"id":"429527","messageId":"CAP8UFD0t0=us1MWHTtEvVhNhWB1P6Q5gp-6v5XVGLBVeZ5RYKg@mail.gmail.com","threadId":"56062","inReplyTo":"20210706224321.14371-1-sandals@crustytoothpaste.net","subject":"Re: [PATCH] rev-list: add option for --pretty without header","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2021-07-09T08:01:46Z","receivedAt":"2021-07-09T08:02:02Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Wed, Jul 7, 2021 at 12:47 AM brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n>\n> In general, we encourage users to use plumbing commands, like git\n> rev-list, over porcelain commands, like git log, when scripting.\n> However, git rev-list has one glaring problem that prevents it from\n> being used in certain cases: when --pretty is used, it always prints out\n> a line containing \"commit\" and the object ID.\n\nYou say always, but it looks like it doesn't do it when\n--pretty=oneline is used.\n\nBy the way this makes me think that the doc could be improved, because\nit describes the format this way:\n\n      •   online\n\n              <hash> <title line>\n\n      •   short\n\n              commit <hash>\n              Author: <author>\n\n              <title line>\n\n      •   reference\n\n              <abbrev hash> (<title line>, <short author date>)\n\n      •   email\n\n              From <hash> <date>\n              From: <author>\n              Date: <author date>\n              Subject: [PATCH] <title line>\n\n              <full commit message>\n\nwhile when --pretty=reference or --pretty=email is used the 'commit\n<hash>' line is still printed despite not being shown in the doc.\n\n> This makes it unsuitable\n> for many scripting needs, and forces users to use git log instead.\n\nI agree that it's annoying when using --pretty=format:'...'\n\n> While we can't change this behavior for backwards compatibility, we can\n> add an option to suppress this behavior, so let's do so, and call it\n> \"--no-commit-header\".  Additionally, add the corresponding positive\n> option to switch it back on.\n\nIt's not clear if this new option will remove the 'commit <hash>' line\nwhen a builtin format like --pretty=short, --pretty=medium,\n--pretty=reference or --pretty=email is used.\n\n> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> ---\n> This has come up a lot on the list and I'm sure most of the regulars\n> have run into it before.\n\nYeah, I did run into it before. Thanks for doing something about it!\n\n> It came up at $DAYJOB and I said I intended to\n> send a patch, so here it is.\n>\n> I chose --no-commit-header because --header is already taken.\n\nYeah, that looks like the most obvious option name.\n\n>  --header::\n>         Print the contents of the commit in raw-format; each record is\n>         separated with a NUL character.\n> +\n> +--no-commit-header::\n> +       Suppress the header line containing \"commit\" and the object ID printed before\n> +       the specified format.\n\nThis might want to tell what happens with builtin formats.\n\n> +--commit-header::\n> +       Overrides a previous `--no-commit-header`.\n>  endif::git-rev-list[]\n>\n>  --parents::\n\n[...]\n\n> diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh\n> index 35a2f62392..e68bf9f21c 100755\n> --- a/t/t6006-rev-list-format.sh\n> +++ b/t/t6006-rev-list-format.sh\n> @@ -54,9 +54,15 @@ test_expect_success 'setup' '\n>\n>  # usage: test_format name format_string [failure] <expected_output\n>  test_format () {\n> +       local header_arg=\n> +       if test \"$1\" = \"--no-commit-header\"\n> +       then\n> +               header_arg=\"--no-commit-header\"\n> +               shift\n> +       fi\n>         cat >expect.$1\n>         test_expect_${3:-success} \"format $1\" \"\n> -               git rev-list --pretty=format:'$2' main >output.$1 &&\n> +               git rev-list $header_arg --pretty=format:'$2' main >output.$1 &&\n>                 test_cmp expect.$1 output.$1\n>         \"\n>  }\n\nIt looks like the tests only check what happens in case\n--pretty=format:'...' is used, but I wonder what the code does if a\nbuiltin format is used.\n"},{"id":"429557","messageId":"xmqq8s2f8pbf.fsf@gitster.g","threadId":"56062","inReplyTo":"CAP8UFD0t0=us1MWHTtEvVhNhWB1P6Q5gp-6v5XVGLBVeZ5RYKg@mail.gmail.com","subject":"Re: [PATCH] rev-list: add option for --pretty without header","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-07-09T15:44:20Z","receivedAt":"2021-07-09T15:44:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Christian Couder <christian.couder@gmail.com> writes:\n\n> On Wed, Jul 7, 2021 at 12:47 AM brian m. carlson\n> <sandals@crustytoothpaste.net> wrote:\n>>\n>> In general, we encourage users to use plumbing commands, like git\n>> rev-list, over porcelain commands, like git log, when scripting.\n>> However, git rev-list has one glaring problem that prevents it from\n>> being used in certain cases: when --pretty is used, it always prints out\n>> a line containing \"commit\" and the object ID.\n>\n> You say always, but it looks like it doesn't do it when\n> --pretty=oneline is used.\n\nI've understood that he meant \"when --pretty=format is used\",\nthough, as it is the only format whose intent was to allow\ngeneration of output stream that does not have to be preprocessed\nwith \"grep -v '^[0-9a-f]{40}'\" etc.\n\n> It looks like the tests only check what happens in case\n> --pretty=format:'...' is used, but I wonder what the code does if a\n> builtin format is used.\n\nGood point.\n\nI also think the handling of --abbrev-commit may need to be\nrethought with this change.  See here:\n\n    diff --git a/builtin/rev-list.c b/builtin/rev-list.c\n    index 7677b1af5a..f571cc9598 100644\n    --- a/builtin/rev-list.c\n    +++ b/builtin/rev-list.c\n    @@ -132,7 +132,7 @@ static void show_commit(struct commit *commit, void *data)\n            if (revs->abbrev_commit && revs->abbrev)\n                    fputs(find_unique_abbrev(&commit->object.oid, revs->abbrev),\n                          stdout);\n    -\telse\n    +\telse if (revs->include_header)\n                    fputs(oid_to_hex(&commit->object.oid), stdout);\n            if (revs->print_parents) {\n                    struct commit_list *parents = commit->parents;\n\nThe original says that if --abbrev-commit is set and --abbrev is set\nto non-zero, we'd show unique abbreviation and if not, specifically,\neven when --abbrev-commit is set but --abbrev is set to 0, we didn't\ndo the find_unique_abbrev() of full hexdigits but left the output to\nthe else clause.  This was because the original code KNOWS that the\nelse clause unconditionally emits the full commit object name.\n\nThat assumption, which made the original code's handling of\n\"--abbrev-commit --abbrev=0\" correct, no longer holds with the\nupdated code.  What happens is with --no-commit-header, if we give\n\"--abbrev-commit --abbrev=4\", we still see the unique abbreviation\nthat is not shorter than 4 hexdigits (i.e. \"--no-commit-header\" is\nignored), but if we say \"--abbrev-commit --abbrev=0\", we do not see\nany commit header.\n\nMy hunch is that this \"if / else\", which determines if the commit\nheader should give shortened or full length, should be skipped when\nthe .include_header is false.\n"},{"id":"429708","messageId":"YOskQhWjD6Kg8t33@camp.crustytoothpaste.net","threadId":"56062","inReplyTo":"xmqq8s2f8pbf.fsf@gitster.g","subject":"Re: [PATCH] rev-list: add option for --pretty without header","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2021-07-11T17:02:58Z","receivedAt":"2021-07-11T17:03:03Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2021-07-09 at 15:44:20, Junio C Hamano wrote:\n> Christian Couder <christian.couder@gmail.com> writes:\n> \n> > On Wed, Jul 7, 2021 at 12:47 AM brian m. carlson\n> > <sandals@crustytoothpaste.net> wrote:\n> >>\n> >> In general, we encourage users to use plumbing commands, like git\n> >> rev-list, over porcelain commands, like git log, when scripting.\n> >> However, git rev-list has one glaring problem that prevents it from\n> >> being used in certain cases: when --pretty is used, it always prints out\n> >> a line containing \"commit\" and the object ID.\n> >\n> > You say always, but it looks like it doesn't do it when\n> > --pretty=oneline is used.\n> \n> I've understood that he meant \"when --pretty=format is used\",\n> though, as it is the only format whose intent was to allow\n> generation of output stream that does not have to be preprocessed\n> with \"grep -v '^[0-9a-f]{40}'\" etc.\n\nYes, that's the case.  I'll rephrase the commit message to reflect\nthat's what I meant.\n\n> > It looks like the tests only check what happens in case\n> > --pretty=format:'...' is used, but I wonder what the code does if a\n> > builtin format is used.\n> \n> Good point.\n\nI'll add some more tests.\n\n> I also think the handling of --abbrev-commit may need to be\n> rethought with this change.  See here:\n> \n>     diff --git a/builtin/rev-list.c b/builtin/rev-list.c\n>     index 7677b1af5a..f571cc9598 100644\n>     --- a/builtin/rev-list.c\n>     +++ b/builtin/rev-list.c\n>     @@ -132,7 +132,7 @@ static void show_commit(struct commit *commit, void *data)\n>             if (revs->abbrev_commit && revs->abbrev)\n>                     fputs(find_unique_abbrev(&commit->object.oid, revs->abbrev),\n>                           stdout);\n>     -\telse\n>     +\telse if (revs->include_header)\n>                     fputs(oid_to_hex(&commit->object.oid), stdout);\n>             if (revs->print_parents) {\n>                     struct commit_list *parents = commit->parents;\n> \n> The original says that if --abbrev-commit is set and --abbrev is set\n> to non-zero, we'd show unique abbreviation and if not, specifically,\n> even when --abbrev-commit is set but --abbrev is set to 0, we didn't\n> do the find_unique_abbrev() of full hexdigits but left the output to\n> the else clause.  This was because the original code KNOWS that the\n> else clause unconditionally emits the full commit object name.\n> \n> That assumption, which made the original code's handling of\n> \"--abbrev-commit --abbrev=0\" correct, no longer holds with the\n> updated code.  What happens is with --no-commit-header, if we give\n> \"--abbrev-commit --abbrev=4\", we still see the unique abbreviation\n> that is not shorter than 4 hexdigits (i.e. \"--no-commit-header\" is\n> ignored), but if we say \"--abbrev-commit --abbrev=0\", we do not see\n> any commit header.\n> \n> My hunch is that this \"if / else\", which determines if the commit\n> header should give shortened or full length, should be skipped when\n> the .include_header is false.\n\nI'll take a look at this for a v2.\n-- \nbrian m. carlson (he/him or they/them)\nToronto, Ontario, CA\n"},{"id":"429713","messageId":"20210711215510.191626-1-sandals@crustytoothpaste.net","threadId":"56062","inReplyTo":"20210706224321.14371-1-sandals@crustytoothpaste.net","subject":"[PATCH v2] rev-list: add option for --pretty=format without header","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2021-07-11T21:55:10Z","receivedAt":"2021-07-11T21:55:23Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"In general, we encourage users to use plumbing commands, like git\nrev-list, over porcelain commands, like git log, when scripting.\nHowever, git rev-list has one glaring problem that prevents it from\nbeing used in certain cases: when --pretty is used with a custom format,\nit always prints out a line containing \"commit\" and the object ID.  This\nmakes it unsuitable for many scripting needs, and forces users to use\ngit log instead.\n\nWhile we can't change this behavior for backwards compatibility, we can\nadd an option to suppress this behavior, so let's do so, and call it\n\"--no-commit-header\".  Additionally, add the corresponding positive\noption to switch it back on.\n\nNote that this option doesn't affect the built-in formats, only custom\nformats.  This is exactly the same behavior as users already have from\ngit log and is what most users will be used to.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\nChanges from v1:\n* Ensure this applies only to custom formats.\n* Fix the issue with --abbrev-commit mentioned by Junio.\n* Add tests for additional cases, including built-in formats.\n* Update documentation to reflect this data.\n\n Documentation/rev-list-options.txt |  8 +++\n builtin/rev-list.c                 | 33 ++++++++----\n revision.h                         |  3 +-\n t/t6006-rev-list-format.sh         | 80 +++++++++++++++++++++++++++++-\n 4 files changed, 112 insertions(+), 12 deletions(-)\n\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex 5bf2a85f69..23388f36c3 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -1064,6 +1064,14 @@ ifdef::git-rev-list[]\n --header::\n \tPrint the contents of the commit in raw-format; each record is\n \tseparated with a NUL character.\n+\n+--no-commit-header::\n+\tSuppress the header line containing \"commit\" and the object ID printed before\n+\tthe specified format.  This has no effect on the built-in formats; only custom\n+\tformats are affected.\n+\n+--commit-header::\n+\tOverrides a previous `--no-commit-header`.\n endif::git-rev-list[]\n \n --parents::\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex 7677b1af5a..36cb909eba 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -127,13 +127,15 @@ static void show_commit(struct commit *commit, void *data)\n \tif (info->header_prefix)\n \t\tfputs(info->header_prefix, stdout);\n \n-\tif (!revs->graph)\n-\t\tfputs(get_revision_mark(revs, commit), stdout);\n-\tif (revs->abbrev_commit && revs->abbrev)\n-\t\tfputs(find_unique_abbrev(&commit->object.oid, revs->abbrev),\n-\t\t      stdout);\n-\telse\n-\t\tfputs(oid_to_hex(&commit->object.oid), stdout);\n+\tif (revs->include_header) {\n+\t\tif (!revs->graph)\n+\t\t\tfputs(get_revision_mark(revs, commit), stdout);\n+\t\tif (revs->abbrev_commit && revs->abbrev)\n+\t\t\tfputs(find_unique_abbrev(&commit->object.oid, revs->abbrev),\n+\t\t\t      stdout);\n+\t\telse\n+\t\t\tfputs(oid_to_hex(&commit->object.oid), stdout);\n+\t}\n \tif (revs->print_parents) {\n \t\tstruct commit_list *parents = commit->parents;\n \t\twhile (parents) {\n@@ -153,7 +155,7 @@ static void show_commit(struct commit *commit, void *data)\n \tshow_decorations(revs, commit);\n \tif (revs->commit_format == CMIT_FMT_ONELINE)\n \t\tputchar(' ');\n-\telse\n+\telse if (revs->include_header)\n \t\tputchar('\\n');\n \n \tif (revs->verbose_header) {\n@@ -512,6 +514,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \trepo_init_revisions(the_repository, &revs, prefix);\n \trevs.abbrev = DEFAULT_ABBREV;\n \trevs.commit_format = CMIT_FMT_UNSPECIFIED;\n+\trevs.include_header = 1;\n \n \t/*\n \t * Scan the argument list before invoking setup_revisions(), so that we\n@@ -627,6 +630,16 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \t\t\tcontinue;\n \t\t}\n \n+\t\tif (!strcmp(arg, (\"--commit-header\"))) {\n+\t\t\trevs.include_header = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(arg, (\"--no-commit-header\"))) {\n+\t\t\trevs.include_header = 0;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tif (!strcmp(arg, \"--disk-usage\")) {\n \t\t\tshow_disk_usage = 1;\n \t\t\tinfo.flags |= REV_LIST_QUIET;\n@@ -636,10 +649,12 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \t\tusage(rev_list_usage);\n \n \t}\n+\tif (revs.commit_format != CMIT_FMT_USERFORMAT)\n+\t\trevs.include_header = 1;\n \tif (revs.commit_format != CMIT_FMT_UNSPECIFIED) {\n \t\t/* The command line has a --pretty  */\n \t\tinfo.hdr_termination = '\\n';\n-\t\tif (revs.commit_format == CMIT_FMT_ONELINE)\n+\t\tif (revs.commit_format == CMIT_FMT_ONELINE || !revs.include_header)\n \t\t\tinfo.header_prefix = \"\";\n \t\telse\n \t\t\tinfo.header_prefix = \"commit \";\ndiff --git a/revision.h b/revision.h\nindex 17698cb51a..7464434f60 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -215,7 +215,8 @@ struct rev_info {\n \t\t\tmissing_newline:1,\n \t\t\tdate_mode_explicit:1,\n \t\t\tpreserve_subject:1,\n-\t\t\tencode_email_headers:1;\n+\t\t\tencode_email_headers:1,\n+\t\t\tinclude_header:1;\n \tunsigned int\tdisable_stdin:1;\n \t/* --show-linear-break */\n \tunsigned int\ttrack_linear:1,\ndiff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh\nindex 35a2f62392..41d0ca00b1 100755\n--- a/t/t6006-rev-list-format.sh\n+++ b/t/t6006-rev-list-format.sh\n@@ -41,22 +41,59 @@ test_expect_success 'setup' '\n \techo \"$added_iso88591\" | git commit -F - &&\n \thead1=$(git rev-parse --verify HEAD) &&\n \thead1_short=$(git rev-parse --verify --short $head1) &&\n+\thead1_short4=$(git rev-parse --verify --short=4 $head1) &&\n \ttree1=$(git rev-parse --verify HEAD:) &&\n \ttree1_short=$(git rev-parse --verify --short $tree1) &&\n \techo \"$changed\" > foo &&\n \techo \"$changed_iso88591\" | git commit -a -F - &&\n \thead2=$(git rev-parse --verify HEAD) &&\n \thead2_short=$(git rev-parse --verify --short $head2) &&\n+\thead2_short4=$(git rev-parse --verify --short=4 $head2) &&\n \ttree2=$(git rev-parse --verify HEAD:) &&\n \ttree2_short=$(git rev-parse --verify --short $tree2) &&\n \tgit config --unset i18n.commitEncoding\n '\n \n-# usage: test_format name format_string [failure] <expected_output\n+# usage: test_format [argument...] name format_string [failure] <expected_output\n test_format () {\n+\tlocal args=\n+\twhile true\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--*)\n+\t\t\targs=\"$args $1\"\n+\t\t\tshift;;\n+\t\t*)\n+\t\t\tbreak;;\n+\t\tesac\n+\tdone\n \tcat >expect.$1\n \ttest_expect_${3:-success} \"format $1\" \"\n-\t\tgit rev-list --pretty=format:'$2' main >output.$1 &&\n+\t\tgit rev-list $args --pretty=format:'$2' main >output.$1 &&\n+\t\ttest_cmp expect.$1 output.$1\n+\t\"\n+}\n+\n+# usage: test_pretty [argument...] name format_name [failure] <expected_output\n+test_pretty () {\n+\tlocal args=\n+\twhile true\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--*)\n+\t\t\targs=\"$args $1\"\n+\t\t\tshift;;\n+\t\t*)\n+\t\t\tbreak;;\n+\t\tesac\n+\tdone\n+\tcat >expect.$1\n+\ttest_expect_${3:-success} \"pretty $1 (without --no-commit-header)\" \"\n+\t\tgit rev-list $args --pretty='$2' main >output.$1 &&\n+\t\ttest_cmp expect.$1 output.$1\n+\t\"\n+\ttest_expect_${3:-success} \"pretty $1 (with --no-commit-header)\" \"\n+\t\tgit rev-list $args --no-commit-header --pretty='$2' main >output.$1 &&\n \t\ttest_cmp expect.$1 output.$1\n \t\"\n }\n@@ -93,6 +130,20 @@ $head1\n $head1_short\n EOF\n \n+test_format --no-commit-header hash-no-header %H%n%h <<EOF\n+$head2\n+$head2_short\n+$head1\n+$head1_short\n+EOF\n+\n+test_format --abbrev-commit --abbrev=0 --no-commit-header hash-no-header-abbrev %H%n%h <<EOF\n+$head2\n+$head2_short4\n+$head1\n+$head1_short4\n+EOF\n+\n test_format tree %T%n%t <<EOF\n commit $head2\n $tree2\n@@ -181,6 +232,31 @@ $added\n \n EOF\n \n+test_format --no-commit-header raw-body-no-header %B <<EOF\n+$changed\n+\n+$added\n+\n+EOF\n+\n+test_pretty oneline oneline <<EOF\n+$head2 $changed\n+$head1 $added\n+EOF\n+\n+test_pretty short short <<EOF\n+commit $head2\n+Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\n+\n+    $changed\n+\n+commit $head1\n+Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\n+\n+    $added\n+\n+EOF\n+\n test_expect_success 'basic colors' '\n \tcat >expect <<-EOF &&\n \tcommit $head2\n"},{"id":"429718","messageId":"CAP8UFD2BVba_vsXaTPkXgYDGg28xApoyDrrT2fdTddvM1_3CiA@mail.gmail.com","threadId":"56062","inReplyTo":"20210711215510.191626-1-sandals@crustytoothpaste.net","subject":"Re: [PATCH v2] rev-list: add option for --pretty=format without header","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2021-07-12T07:30:33Z","receivedAt":"2021-07-12T07:42:25Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Sun, Jul 11, 2021 at 11:55 PM brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n>\n> In general, we encourage users to use plumbing commands, like git\n> rev-list, over porcelain commands, like git log, when scripting.\n> However, git rev-list has one glaring problem that prevents it from\n> being used in certain cases: when --pretty is used with a custom format,\n> it always prints out a line containing \"commit\" and the object ID.  This\n> makes it unsuitable for many scripting needs, and forces users to use\n> git log instead.\n>\n> While we can't change this behavior for backwards compatibility, we can\n> add an option to suppress this behavior, so let's do so, and call it\n> \"--no-commit-header\".  Additionally, add the corresponding positive\n> option to switch it back on.\n>\n> Note that this option doesn't affect the built-in formats, only custom\n> formats.  This is exactly the same behavior as users already have from\n> git log and is what most users will be used to.\n>\n> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> ---\n> Changes from v1:\n> * Ensure this applies only to custom formats.\n> * Fix the issue with --abbrev-commit mentioned by Junio.\n> * Add tests for additional cases, including built-in formats.\n> * Update documentation to reflect this data.\n\nThanks! This version mostly looks good to me!\n\n> diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh\n> index 35a2f62392..41d0ca00b1 100755\n> --- a/t/t6006-rev-list-format.sh\n> +++ b/t/t6006-rev-list-format.sh\n> @@ -41,22 +41,59 @@ test_expect_success 'setup' '\n>         echo \"$added_iso88591\" | git commit -F - &&\n>         head1=$(git rev-parse --verify HEAD) &&\n>         head1_short=$(git rev-parse --verify --short $head1) &&\n> +       head1_short4=$(git rev-parse --verify --short=4 $head1) &&\n>         tree1=$(git rev-parse --verify HEAD:) &&\n>         tree1_short=$(git rev-parse --verify --short $tree1) &&\n>         echo \"$changed\" > foo &&\n>         echo \"$changed_iso88591\" | git commit -a -F - &&\n>         head2=$(git rev-parse --verify HEAD) &&\n>         head2_short=$(git rev-parse --verify --short $head2) &&\n> +       head2_short4=$(git rev-parse --verify --short=4 $head2) &&\n>         tree2=$(git rev-parse --verify HEAD:) &&\n>         tree2_short=$(git rev-parse --verify --short $tree2) &&\n>         git config --unset i18n.commitEncoding\n>  '\n>\n> -# usage: test_format name format_string [failure] <expected_output\n> +# usage: test_format [argument...] name format_string [failure] <expected_output\n\nUsually we use \"option\" instead of \"argument\" for the flags starting\nwith \"-\" or \"--\" before the required parameter. For example:\n\n$ git rev-list -h\nusage: git rev-list [OPTION] <commit-id>... [ -- paths... ]\n...\n\n(Yeah, I agree that [OPTION] is not very consistent with what other\ncommands show, which is usually \"[<options>]\".)\n\n>  test_format () {\n> +       local args=\n\nHere...\n\n> +       while true\n> +       do\n> +               case \"$1\" in\n> +               --*)\n> +                       args=\"$args $1\"\n\n...here...\n\n> +                       shift;;\n> +               *)\n> +                       break;;\n> +               esac\n> +       done\n>         cat >expect.$1\n>         test_expect_${3:-success} \"format $1\" \"\n> -               git rev-list --pretty=format:'$2' main >output.$1 &&\n> +               git rev-list $args --pretty=format:'$2' main >output.$1 &&\n\n...and here \"opts\" might be better than \"args\".\n\n> +               test_cmp expect.$1 output.$1\n> +       \"\n> +}\n> +\n> +# usage: test_pretty [argument...] name format_name [failure] <expected_output\n\nHere...\n\n> +test_pretty () {\n> +       local args=\n\n...and in this function too.\n\n> +       while true\n> +       do\n> +               case \"$1\" in\n> +               --*)\n> +                       args=\"$args $1\"\n> +                       shift;;\n> +               *)\n> +                       break;;\n> +               esac\n> +       done\n> +       cat >expect.$1\n> +       test_expect_${3:-success} \"pretty $1 (without --no-commit-header)\" \"\n> +               git rev-list $args --pretty='$2' main >output.$1 &&\n> +               test_cmp expect.$1 output.$1\n> +       \"\n> +       test_expect_${3:-success} \"pretty $1 (with --no-commit-header)\" \"\n> +               git rev-list $args --no-commit-header --pretty='$2' main >output.$1 &&\n>                 test_cmp expect.$1 output.$1\n>         \"\n>  }\n\n[...]\n\n> +test_pretty oneline oneline <<EOF\n> +$head2 $changed\n> +$head1 $added\n> +EOF\n> +\n> +test_pretty short short <<EOF\n\ntest_pretty() accepts options like --no-commit-header, but it's only\nused without any option. So I wonder if you forgot to add a few tests\nwith some options.\n\n> +commit $head2\n> +Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\n> +\n> +    $changed\n> +\n> +commit $head1\n> +Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\n> +\n> +    $added\n> +\n> +EOF\n> +\n>  test_expect_success 'basic colors' '\n>         cat >expect <<-EOF &&\n>         commit $head2\n"},{"id":"429807","messageId":"YOyGYs+uDr7tYxON@coredump.intra.peff.net","threadId":"56062","inReplyTo":"20210711215510.191626-1-sandals@crustytoothpaste.net","subject":"Re: [PATCH v2] rev-list: add option for --pretty=format without header","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-07-12T18:13:54Z","receivedAt":"2021-07-12T18:13:57Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Jul 11, 2021 at 09:55:10PM +0000, brian m. carlson wrote:\n\n> In general, we encourage users to use plumbing commands, like git\n> rev-list, over porcelain commands, like git log, when scripting.\n> However, git rev-list has one glaring problem that prevents it from\n> being used in certain cases: when --pretty is used with a custom format,\n> it always prints out a line containing \"commit\" and the object ID.  This\n> makes it unsuitable for many scripting needs, and forces users to use\n> git log instead.\n> \n> While we can't change this behavior for backwards compatibility, we can\n> add an option to suppress this behavior, so let's do so, and call it\n> \"--no-commit-header\".  Additionally, add the corresponding positive\n> option to switch it back on.\n> \n> Note that this option doesn't affect the built-in formats, only custom\n> formats.  This is exactly the same behavior as users already have from\n> git log and is what most users will be used to.\n\nThanks for working on this. It has bugged me for at least a decade. :)\n\nI do wish this had been made the default when we introduced\n--pretty=format, but I agree we can't just change it now. This could be\nsomething to keep in mind for future deprecation (or a large breaking\nversion). People would have to start saying --commit-header now to\nfuture-proof themselves if they really want the current behavior. I'm OK\nto leave any plans / warnings like that for future work.\n\nThe patch looks correct to me. I did have one small nit:\n\n> diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\n> index 5bf2a85f69..23388f36c3 100644\n> --- a/Documentation/rev-list-options.txt\n> +++ b/Documentation/rev-list-options.txt\n> @@ -1064,6 +1064,14 @@ ifdef::git-rev-list[]\n>  --header::\n>  \tPrint the contents of the commit in raw-format; each record is\n>  \tseparated with a NUL character.\n> +\n> +--no-commit-header::\n> +\tSuppress the header line containing \"commit\" and the object ID printed before\n> +\tthe specified format.  This has no effect on the built-in formats; only custom\n> +\tformats are affected.\n\nIt wasn't immediately obvious to me what \"custom formats\" meant here. I\ndon't think we use that term elsewhere, nor do we seem to have a\nsuccinct phrase for the concept. Maybe something like:\n\n  only custom formats (i.e., `--pretty=format:`) are affected.\n\nhelps without making it too clunky?\n\n-Peff\n"},{"id":"429855","messageId":"YOzZ9Zzv+NJu7Wo8@camp.crustytoothpaste.net","threadId":"56062","inReplyTo":"CAP8UFD2BVba_vsXaTPkXgYDGg28xApoyDrrT2fdTddvM1_3CiA@mail.gmail.com","subject":"Re: [PATCH v2] rev-list: add option for --pretty=format without header","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2021-07-13T00:10:29Z","receivedAt":"2021-07-13T00:10:37Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2021-07-12 at 07:30:33, Christian Couder wrote:\n> Usually we use \"option\" instead of \"argument\" for the flags starting\n> with \"-\" or \"--\" before the required parameter. For example:\n> \n> $ git rev-list -h\n> usage: git rev-list [OPTION] <commit-id>... [ -- paths... ]\n> ...\n> \n> (Yeah, I agree that [OPTION] is not very consistent with what other\n> commands show, which is usually \"[<options>]\".)\n\nI can do that rename.\n\n> test_pretty() accepts options like --no-commit-header, but it's only\n> used without any option. So I wonder if you forgot to add a few tests\n> with some options.\n\nI originally intended to add some, but decided to remove them because\nthe --abbrev tests fit better elsewhere.  I'll remove the options.\n-- \nbrian m. carlson (he/him or they/them)\nToronto, Ontario, CA\n"},{"id":"429857","messageId":"YOzbKDlBkLniOwjB@camp.crustytoothpaste.net","threadId":"56062","inReplyTo":"YOyGYs+uDr7tYxON@coredump.intra.peff.net","subject":"Re: [PATCH v2] rev-list: add option for --pretty=format without header","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2021-07-13T00:15:36Z","receivedAt":"2021-07-13T00:16:12Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2021-07-12 at 18:13:54, Jeff King wrote:\n> Thanks for working on this. It has bugged me for at least a decade. :)\n\nI figured this would be something you'd like to see fixed.  I'm just\nsurprised that I'm the first to send a patch.\n\n> It wasn't immediately obvious to me what \"custom formats\" meant here. I\n> don't think we use that term elsewhere, nor do we seem to have a\n> succinct phrase for the concept. Maybe something like:\n> \n>   only custom formats (i.e., `--pretty=format:`) are affected.\n> \n> helps without making it too clunky?\n\nI can add that.\n-- \nbrian m. carlson (he/him or they/them)\nToronto, Ontario, CA\n"}]}