{"thread":{"id":"51670","subject":"[PATCH 0/3] format-patch: teach --infer-cover-subject option","startedAt":"2019-08-19T02:38:35Z","lastAt":"2019-08-20T19:01:30Z","messageCount":9,"participants":["Denton Liu","Eric Sunshine","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"380683","messageId":"cover.1566182184.git.liu.denton@gmail.com","threadId":"51670","inReplyTo":null,"subject":"[PATCH 0/3] format-patch: teach --infer-cover-subject option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T02:37:31Z","receivedAt":"2019-08-19T02:38:35Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, format-patch only puts \"*** SUBJECT HERE ***\" when a cover\nletter is generated. However, it is already smart enough to be able to\npopulate the cover letter with the branch description so there's no\nreason why it cannot populate the subject as well.\n\nTeach format-patch the --infer-cover-subject and corresponding\nformat.inferCoverSubject configuration option which will read the\nsubject from the branch description using the same rules as for a commit\nmessage (that is, it will expect a subject line followed by a blank\nline).\n\nAlso includes some other cleanup along the way.\n\nThis was based on patches 1-3 of an earlier patchset I sent[1].\n\n[1]: https://public-inbox.org/git/cover.1558492582.git.liu.denton@gmail.com/\n\n\nDenton Liu (3):\n  t4014: clean up style\n  Doc: add more detail for git-format-patch\n  format-patch: infer cover letter from branch description\n\n Documentation/config/format.txt    |   5 +\n Documentation/git-format-patch.txt |  35 +-\n builtin/log.c                      |  56 ++-\n t/t4014-format-patch.sh            | 656 ++++++++++++++++-------------\n 4 files changed, 425 insertions(+), 327 deletions(-)\n\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380684","messageId":"7619da962d1fc804392e3552fbd56bf4bc68ac38.1566182184.git.liu.denton@gmail.com","threadId":"51670","inReplyTo":"cover.1566182184.git.liu.denton@gmail.com","subject":"[PATCH 2/3] Doc: add more detail for git-format-patch","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T02:37:37Z","receivedAt":"2019-08-19T02:38:35Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In git-format-patch.txt, we were missing some key user information.\nFirst of all, using the `--to` and `--cc` options don't override\n`format.to` and `format.cc` variables, respectively. They add on to each\nother. Document this.\n\nIn addition, document the special value of `--base=auto`.\n\nNext, while we're at it, surround option arguments with <>.\n\nFinally, document the `format.outputDirectory` config and change\n`format.coverletter` to use camelcase.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-format-patch.txt | 25 ++++++++++++++++---------\n 1 file changed, 16 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex b9b97e63ae..0e2dd59c0f 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -17,9 +17,9 @@ SYNOPSIS\n \t\t   [--signature-file=<file>]\n \t\t   [-n | --numbered | -N | --no-numbered]\n \t\t   [--start-number <n>] [--numbered-files]\n-\t\t   [--in-reply-to=Message-Id] [--suffix=.<sfx>]\n+\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n-\t\t   [--rfc] [--subject-prefix=Subject-Prefix]\n+\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n@@ -159,7 +159,7 @@ Beware that the default for 'git send-email' is to thread emails\n itself.  If you want `git format-patch` to take care of threading, you\n will want to ensure that threading is disabled for `git send-email`.\n \n---in-reply-to=Message-Id::\n+--in-reply-to=<Message-Id>::\n \tMake the first mail (or all the mails with `--no-thread`) appear as a\n \treply to the given Message-Id, which avoids breaking threads to\n \tprovide a new patch series.\n@@ -193,13 +193,17 @@ will want to ensure that threading is disabled for `git send-email`.\n \n --to=<email>::\n \tAdd a `To:` header to the email headers. This is in addition\n-\tto any configured headers, and may be used multiple times.\n+\tto any configured headers, and may be used multiple times. The\n+\temails given will be used along with any emails given by\n+\t`format.to` configurations.\n \tThe negated form `--no-to` discards all `To:` headers added so\n \tfar (from config or command line).\n \n --cc=<email>::\n \tAdd a `Cc:` header to the email headers. This is in addition\n-\tto any configured headers, and may be used multiple times.\n+\tto any configured headers, and may be used multiple times. The\n+\temails given will be used along with any emails given by\n+\t`format.cc` configurations.\n \tThe negated form `--no-cc` discards all `Cc:` headers added so\n \tfar (from config or command line).\n \n@@ -314,7 +318,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n --base=<commit>::\n \tRecord the base tree information to identify the state the\n \tpatch series applies to.  See the BASE TREE INFORMATION section\n-\tbelow for details.\n+\tbelow for details. If <commit> is equal to \"auto\", a base commit\n+\tis automatically chosen.\n \n --root::\n \tTreat the revision argument as a <revision range>, even if it\n@@ -330,8 +335,9 @@ CONFIGURATION\n -------------\n You can specify extra mail header lines to be added to each message,\n defaults for the subject prefix and file suffix, number patches when\n-outputting more than one patch, add \"To\" or \"Cc:\" headers, configure\n-attachments, and sign off patches with configuration variables.\n+outputting more than one patch, add \"To:\" or \"Cc:\" headers, configure\n+attachments, change the patch output directory, and sign off patches\n+with configuration variables.\n \n ------------\n [format]\n@@ -343,7 +349,8 @@ attachments, and sign off patches with configuration variables.\n \tcc = <email>\n \tattach [ = mime-boundary-string ]\n \tsignOff = true\n-\tcoverletter = auto\n+\toutputDirectory = <directory>\n+\tcoverLetter = auto\n ------------\n \n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380685","messageId":"5cc5e354b6d84609f3d1de087b3390488abe5343.1566182184.git.liu.denton@gmail.com","threadId":"51670","inReplyTo":"cover.1566182184.git.liu.denton@gmail.com","subject":"[PATCH 3/3] format-patch: infer cover letter from branch description","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T02:37:39Z","receivedAt":"2019-08-19T02:38:35Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"We used to populate the subject of the cover letter generated by\ngit-format-patch with \"*** SUBJECT HERE ***\". However, if a user submits\nmultiple patchsets, they may want to keep a consistent subject between\nrerolls.\n\nIf git-format-patch is run with `--infer-cover-letter` or\n`format.inferCoverSubject`, infer the subject for the cover letter from\nthe top line(s) of a branch description, similar to how a subject is\nread from a commit message.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/config/format.txt    |  5 +++\n Documentation/git-format-patch.txt | 10 ++++++\n builtin/log.c                      | 56 +++++++++++++++++++-----------\n t/t4014-format-patch.sh            | 33 ++++++++++++++++++\n 4 files changed, 83 insertions(+), 21 deletions(-)\n\ndiff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\nindex 414a5a8a9d..84a40544c5 100644\n--- a/Documentation/config/format.txt\n+++ b/Documentation/config/format.txt\n@@ -36,6 +36,11 @@ format.subjectPrefix::\n \tThe default for format-patch is to output files with the '[PATCH]'\n \tsubject prefix. Use this variable to change that prefix.\n \n+format.inferCoverSubject::\n+\tA boolean that controls whether or not to infer the subject for\n+\tthe cover letter based on the branch's description. See the\n+\t--infer-cover-subject option in linkgit:git-format-patch[1].\n+\n format.signature::\n \tThe default for format-patch is to output a signature containing\n \tthe Git version number. Use this variable to change that default.\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 0e2dd59c0f..757a74cf8a 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -19,6 +19,7 @@ SYNOPSIS\n \t\t   [--start-number <n>] [--numbered-files]\n \t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n+\t\t   [--[no-]infer-cover-subject]\n \t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n@@ -171,6 +172,14 @@ will want to ensure that threading is disabled for `git send-email`.\n \tpatches being generated, and any patch that matches is\n \tignored.\n \n+--[no-]infer-cover-subject::\n+\tInstead of using the default \"*** SUBJECT HERE ***\" subject for\n+\tthe cover letter, infer the subject from the branch's\n+\tdescription.\n++\n+Similar to a commit message, the subject is inferred as the beginning of\n+the description up to and excluding the first blank line.\n+\n --subject-prefix=<Subject-Prefix>::\n \tInstead of the standard '[PATCH]' prefix in the subject\n \tline, instead use '[<Subject-Prefix>]'. This\n@@ -351,6 +360,7 @@ with configuration variables.\n \tsignOff = true\n \toutputDirectory = <directory>\n \tcoverLetter = auto\n+\tinferCoverSubject = true\n ------------\n \n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 44b10b3415..b15754e282 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -774,6 +774,7 @@ static const char *signature = git_version_string;\n static const char *signature_file;\n static int config_cover_letter;\n static const char *config_output_directory;\n+static int infer_cover_subject;\n \n enum {\n \tCOVER_UNSET,\n@@ -887,6 +888,10 @@ static int git_format_config(const char *var, const char *value, void *cb)\n \t\t}\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"format.infercoversubject\")) {\n+\t\tinfer_cover_subject = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n \n \treturn git_log_config(var, value, cb);\n }\n@@ -993,20 +998,6 @@ static void print_signature(FILE *file)\n \tputc('\\n', file);\n }\n \n-static void add_branch_description(struct strbuf *buf, const char *branch_name)\n-{\n-\tstruct strbuf desc = STRBUF_INIT;\n-\tif (!branch_name || !*branch_name)\n-\t\treturn;\n-\tread_branch_desc(&desc, branch_name);\n-\tif (desc.len) {\n-\t\tstrbuf_addch(buf, '\\n');\n-\t\tstrbuf_addbuf(buf, &desc);\n-\t\tstrbuf_addch(buf, '\\n');\n-\t}\n-\tstrbuf_release(&desc);\n-}\n-\n static char *find_branch_name(struct rev_info *rev)\n {\n \tint i, positive = -1;\n@@ -1057,13 +1048,17 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\t\t      struct commit *origin,\n \t\t\t      int nr, struct commit **list,\n \t\t\t      const char *branch_name,\n+\t\t\t      int infer_subject,\n \t\t\t      int quiet)\n {\n \tconst char *committer;\n-\tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n-\tconst char *msg;\n+\tconst char *subject = \"*** SUBJECT HERE ***\";\n+\tconst char *body = \"*** BLURB HERE ***\";\n+\tconst char *description = NULL;\n \tstruct shortlog log;\n \tstruct strbuf sb = STRBUF_INIT;\n+\tstruct strbuf description_sb = STRBUF_INIT;\n+\tstruct strbuf subject_sb = STRBUF_INIT;\n \tint i;\n \tconst char *encoding = \"UTF-8\";\n \tint need_8bit_cte = 0;\n@@ -1091,17 +1086,34 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tif (!branch_name)\n \t\tbranch_name = find_branch_name(rev);\n \n-\tmsg = body;\n+\tif (branch_name && *branch_name)\n+\t\tread_branch_desc(&description_sb, branch_name);\n+\n+\tif (description_sb.len) {\n+\t\tif (infer_subject) {\n+\t\t\tdescription = format_subject(&subject_sb, description_sb.buf, \" \");\n+\t\t\tsubject = subject_sb.buf;\n+\t\t} else {\n+\t\t\tdescription = description_sb.buf;\n+\t\t}\n+\t}\n+\n \tpp.fmt = CMIT_FMT_EMAIL;\n \tpp.date_mode.type = DATE_RFC2822;\n \tpp.rev = rev;\n \tpp.print_email_subject = 1;\n \tpp_user_info(&pp, NULL, &sb, committer, encoding);\n-\tpp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);\n-\tpp_remainder(&pp, &msg, &sb, 0);\n-\tadd_branch_description(&sb, branch_name);\n+\tpp_title_line(&pp, &subject, &sb, encoding, need_8bit_cte);\n+\tpp_remainder(&pp, &body, &sb, 0);\n+\tif (description) {\n+\t\tstrbuf_addch(&sb, '\\n');\n+\t\tstrbuf_addstr(&sb, description);\n+\t\tstrbuf_addch(&sb, '\\n');\n+\t}\n \tfprintf(rev->diffopt.file, \"%s\\n\", sb.buf);\n \n+\tstrbuf_release(&description_sb);\n+\tstrbuf_release(&subject_sb);\n \tstrbuf_release(&sb);\n \n \tshortlog_init(&log);\n@@ -1577,6 +1589,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t{ OPTION_CALLBACK, 0, \"rfc\", &rev, NULL,\n \t\t\t    N_(\"Use [RFC PATCH] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },\n+\t\tOPT_BOOL(0, \"infer-cover-subject\", &infer_cover_subject,\n+\t\t\t    N_(\"infer a cover letter subject from the branch description\")),\n \t\t{ OPTION_CALLBACK, 0, \"subject-prefix\", &rev, N_(\"prefix\"),\n \t\t\t    N_(\"Use [<prefix>] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NONEG, subject_prefix_callback },\n@@ -1916,7 +1930,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tif (thread)\n \t\t\tgen_message_id(&rev, \"cover\");\n \t\tmake_cover_letter(&rev, use_stdout,\n-\t\t\t\t  origin, nr, list, branch_name, quiet);\n+\t\t\t\t  origin, nr, list, branch_name, infer_cover_subject, quiet);\n \t\tprint_bases(&bases, rev.diffopt.file);\n \t\tprint_signature(rev.diffopt.file);\n \t\ttotal++;\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex d6aa41b8c6..a544d0c704 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1558,6 +1558,39 @@ test_expect_success 'format patch ignores color.ui' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'cover letter with config subject' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.inferCoverSubject true &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\tgrep \"^body\" actual\n+'\n+\n+test_expect_success 'cover letter with command-line subject' '\n+\ttest_config branch.rebuild-1.description \"command-line subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --infer-cover-subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] command-line subject$\" actual &&\n+\tgrep \"^body\" actual\n+'\n+\n+test_expect_success 'cover letter with command-line --no-infer-cover-subject overrides config' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.inferCoverSubject true &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --no-infer-cover-subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject\" actual &&\n+\tgrep \"^body\" actual\n+'\n+\n test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380686","messageId":"058f877c342e8ee6683235c32946e5238e7e87f5.1566182184.git.liu.denton@gmail.com","threadId":"51670","inReplyTo":"cover.1566182184.git.liu.denton@gmail.com","subject":"[PATCH 1/3] t4014: clean up style","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T02:37:34Z","receivedAt":"2019-08-19T02:38:35Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In Git's tests, there is typically no space between the redirection\noperator and the filename. Remove these spaces.\n\nSince output is silenced when running without `-v` and debugging\noutput is useful with `-v`, remove redirections to /dev/null.\n\nChange here-docs from `<<\\EOF` to `<<-\\EOF` so that they can be indented\nalong with the rest of the test case.\n\nFinally, refactor to remove Git commands upstream of pipe. This way, if\nan invocation of a Git command fails, the return code won't be lost.\nKeep upstream non-Git commands since we have to assume a base level of\nsanity.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 623 +++++++++++++++++++++-------------------\n 1 file changed, 326 insertions(+), 297 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex ca7debf1d4..d6aa41b8c6 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -34,7 +34,8 @@ test_expect_success setup '\n \tgit commit -m \"Side changes #3 with \\\\n backslash-n in it.\" &&\n \n \tgit checkout master &&\n-\tgit diff-tree -p C2 | git apply --index &&\n+\tgit diff-tree -p C2 >patch &&\n+\tgit apply --index <patch &&\n \ttest_tick &&\n \tgit commit -m \"Master accepts moral equivalent of #2\" &&\n \n@@ -96,7 +97,7 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n \tgit checkout -b merger master &&\n \ttest_tick &&\n \tgit merge --no-ff slave &&\n-\tcnt=$(git format-patch -3 --stdout | grep \"^From \" | wc -l) &&\n+\tcnt=$(git format-patch -3 --stdout >patch && grep \"^From \" patch | wc -l) &&\n \ttest $cnt = 3\n '\n \n@@ -104,21 +105,22 @@ test_expect_success \"format-patch result applies\" '\n \n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n \n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success 'commit did not screw up the log message' '\n \n-\tgit cat-file commit side | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit side >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n \n '\n \n@@ -131,7 +133,8 @@ test_expect_success 'format-patch did not screw up the log message' '\n \n test_expect_success 'replay did not screw up the log message' '\n \n-\tgit cat-file commit rebuild-1 | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit rebuild-1 >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n \n '\n \n@@ -141,8 +144,8 @@ test_expect_success 'extra headers' '\n \" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\n \" &&\n-\tgit format-patch --stdout master..side > patch2 &&\n-\tsed -e \"/^\\$/q\" patch2 > hdrs2 &&\n+\tgit format-patch --stdout master..side >patch2 &&\n+\tsed -e \"/^\\$/q\" patch2 >hdrs2 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs2 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs2\n \n@@ -153,7 +156,7 @@ test_expect_success 'extra headers without newlines' '\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side >patch3 &&\n-\tsed -e \"/^\\$/q\" patch3 > hdrs3 &&\n+\tsed -e \"/^\\$/q\" patch3 >hdrs3 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs3 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs3\n \n@@ -163,8 +166,8 @@ test_expect_success 'extra headers with multiple To:s' '\n \n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"To: S E Cipient <scipient@example.com>\" &&\n-\tgit format-patch --stdout master..side > patch4 &&\n-\tsed -e \"/^\\$/q\" patch4 > hdrs4 &&\n+\tgit format-patch --stdout master..side >patch4 &&\n+\tsed -e \"/^\\$/q\" patch4 >hdrs4 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>,\\$\" hdrs4 &&\n \tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs4\n '\n@@ -172,72 +175,82 @@ test_expect_success 'extra headers with multiple To:s' '\n test_expect_success 'additional command line cc (ascii)' '\n \n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_failure 'additional command line cc (rfc822)' '\n \n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_success 'command line headers' '\n \n \tgit config --unset-all format.headers &&\n-\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch6 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" patch6\n+\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side >patch6 &&\n+\tsed -e \"/^\\$/q\" patch6 >hdrs6 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" hdrs6\n '\n \n test_expect_success 'configuration headers and command line headers' '\n \n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch7 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch7 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch7\n+\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side >patch7 &&\n+\tsed -e \"/^\\$/q\" patch7 >hdrs7 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs7 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs7\n '\n \n test_expect_success 'command line To: header (ascii)' '\n \n \tgit config --unset-all format.headers &&\n-\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc822)' '\n \n-\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc2047)' '\n \n-\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_success 'configuration To: header (ascii)' '\n \n \tgit config format.to \"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc822)' '\n \n \tgit config format.to \"R. E. Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc2047)' '\n \n \tgit config format.to \"R Ä Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs9\n '\n \n # check_patch <patch>: Verify that <patch> looks like a half-sane\n@@ -250,52 +263,52 @@ check_patch () {\n \n test_expect_success 'format.from=false' '\n \n-\tgit -c format.from=false format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n+\tgit -c format.from=false format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n \tcheck_patch patch &&\n-\t! grep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\t! grep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from=true' '\n \n-\tgit -c format.from=true format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\tgit -c format.from=true format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from with address' '\n \n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-from overrides format.from' '\n \n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--from overrides format.from' '\n \n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-to overrides config.to' '\n \n \tgit config --replace-all format.to \\\n \t\t\"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-to --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch10 &&\n-\tcheck_patch patch10 &&\n-\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" patch10\n+\tgit format-patch --no-to --stdout master..side >patch10 &&\n+\tsed -e \"/^\\$/q\" patch10 >hdrs10 &&\n+\tcheck_patch hdrs10 &&\n+\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs10\n '\n \n test_expect_success '--no-to and --to replaces config.to' '\n@@ -303,31 +316,31 @@ test_expect_success '--no-to and --to replaces config.to' '\n \tgit config --replace-all format.to \\\n \t\t\"Someone <someone@out.there>\" &&\n \tgit format-patch --no-to --to=\"Someone Else <else@out.there>\" \\\n-\t\t--stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch11 &&\n-\tcheck_patch patch11 &&\n-\t! grep \"^To: Someone <someone@out.there>\\$\" patch11 &&\n-\tgrep \"^To: Someone Else <else@out.there>\\$\" patch11\n+\t\t--stdout master..side >patch11 &&\n+\tsed -e \"/^\\$/q\" patch11 >hdrs11 &&\n+\tcheck_patch hdrs11 &&\n+\t! grep \"^To: Someone <someone@out.there>\\$\" hdrs11 &&\n+\tgrep \"^To: Someone Else <else@out.there>\\$\" hdrs11\n '\n \n test_expect_success '--no-cc overrides config.cc' '\n \n \tgit config --replace-all format.cc \\\n \t\t\"C E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-cc --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch12 &&\n-\tcheck_patch patch12 &&\n-\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" patch12\n+\tgit format-patch --no-cc --stdout master..side >patch12 &&\n+\tsed -e \"/^\\$/q\" patch12 >hdrs12 &&\n+\tcheck_patch hdrs12 &&\n+\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" hdrs12\n '\n \n test_expect_success '--no-add-header overrides config.headers' '\n \n \tgit config --replace-all format.headers \\\n \t\t\"Header1: B E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-add-header --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch13 &&\n-\tcheck_patch patch13 &&\n-\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" patch13\n+\tgit format-patch --no-add-header --stdout master..side >patch13 &&\n+\tsed -e \"/^\\$/q\" patch13 >hdrs13 &&\n+\tcheck_patch hdrs13 &&\n+\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" hdrs13\n '\n \n test_expect_success 'multiple files' '\n@@ -357,7 +370,7 @@ test_expect_success 'reroll count (-v)' '\n check_threading () {\n \texpect=\"$1\" &&\n \tshift &&\n-\t(git format-patch --stdout \"$@\"; echo $? > status.out) |\n+\t(git format-patch --stdout \"$@\"; echo $? >status.out) |\n \t# Prints everything between the Message-ID and In-Reply-To,\n \t# and replaces all Message-ID-lookalikes by a sequence number\n \tperl -ne '\n@@ -372,12 +385,12 @@ check_threading () {\n \t\t\tprint;\n \t\t}\n \t\tprint \"---\\n\" if /^From /i;\n-\t' > actual &&\n+\t' >actual &&\n \ttest 0 = \"$(cat status.out)\" &&\n \ttest_cmp \"$expect\" actual\n }\n \n-cat >> expect.no-threading <<EOF\n+cat >>expect.no-threading <<EOF\n ---\n ---\n ---\n@@ -388,7 +401,7 @@ test_expect_success 'no threading' '\n \tcheck_threading expect.no-threading master\n '\n \n-cat > expect.thread <<EOF\n+cat >expect.thread <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -405,7 +418,7 @@ test_expect_success 'thread' '\n \tcheck_threading expect.thread --thread master\n '\n \n-cat > expect.in-reply-to <<EOF\n+cat >expect.in-reply-to <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -425,7 +438,7 @@ test_expect_success 'thread in-reply-to' '\n \t\t--thread master\n '\n \n-cat > expect.cover-letter <<EOF\n+cat >expect.cover-letter <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -446,7 +459,7 @@ test_expect_success 'thread cover-letter' '\n \tcheck_threading expect.cover-letter --cover-letter --thread master\n '\n \n-cat > expect.cl-irt <<EOF\n+cat >expect.cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -478,7 +491,7 @@ test_expect_success 'thread explicit shallow' '\n \t\t--in-reply-to=\"<test.message>\" --thread=shallow master\n '\n \n-cat > expect.deep <<EOF\n+cat >expect.deep <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -496,7 +509,7 @@ test_expect_success 'thread deep' '\n \tcheck_threading expect.deep --thread=deep master\n '\n \n-cat > expect.deep-irt <<EOF\n+cat >expect.deep-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -519,7 +532,7 @@ test_expect_success 'thread deep in-reply-to' '\n \t\t--in-reply-to=\"<test.message>\" master\n '\n \n-cat > expect.deep-cl <<EOF\n+cat >expect.deep-cl <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -543,7 +556,7 @@ test_expect_success 'thread deep cover-letter' '\n \tcheck_threading expect.deep-cl --cover-letter --thread=deep master\n '\n \n-cat > expect.deep-cl-irt <<EOF\n+cat >expect.deep-cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -625,7 +638,7 @@ test_expect_success 'cover-letter inherits diff options' '\n \n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n   This is an excessively long subject line for a message due to the\n     habit some projects have of not having a short, one-line subject at\n     the start of the commit message, but rather sticking a whole\n@@ -638,12 +651,12 @@ EOF\n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \n \tgit format-patch --cover-letter -2 &&\n-\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" < 0000-cover-letter.patch > output &&\n+\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" <0000-cover-letter.patch >output &&\n \ttest_cmp expect output\n \n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n index $before..$after 100644\n --- a/file\n +++ b/file\n@@ -665,7 +678,7 @@ test_expect_success 'format-patch respects -U' '\n \n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n \n diff --git a/file b/file\n index $before..$after 100644\n@@ -681,7 +694,7 @@ EOF\n test_expect_success 'format-patch -p suppresses stat' '\n \n \tgit format-patch -p -2 &&\n-\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&\n+\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&\n \ttest_cmp expect output\n \n '\n@@ -736,7 +749,7 @@ test_expect_success 'format-patch from a subdirectory (3)' '\n '\n \n test_expect_success 'format-patch --in-reply-to' '\n-\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" > patch8 &&\n+\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" >patch8 &&\n \tgrep \"^In-Reply-To: <baz@foo.bar>\" patch8 &&\n \tgrep \"^References: <baz@foo.bar>\" patch8\n '\n@@ -827,20 +840,20 @@ test_expect_success 'format-patch with multiple notes refs' '\n \t! grep \"this is note 2\" out\n '\n \n-echo \"fatal: --name-only does not make sense\" > expect.name-only\n-echo \"fatal: --name-status does not make sense\" > expect.name-status\n-echo \"fatal: --check does not make sense\" > expect.check\n+echo \"fatal: --name-only does not make sense\" >expect.name-only\n+echo \"fatal: --name-status does not make sense\" >expect.name-status\n+echo \"fatal: --check does not make sense\" >expect.check\n \n test_expect_success 'options no longer allowed for format-patch' '\n-\ttest_must_fail git format-patch --name-only 2> output &&\n+\ttest_must_fail git format-patch --name-only 2>output &&\n \ttest_i18ncmp expect.name-only output &&\n-\ttest_must_fail git format-patch --name-status 2> output &&\n+\ttest_must_fail git format-patch --name-status 2>output &&\n \ttest_i18ncmp expect.name-status output &&\n-\ttest_must_fail git format-patch --check 2> output &&\n+\ttest_must_fail git format-patch --check 2>output &&\n \ttest_i18ncmp expect.check output'\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n-\tgit format-patch --numstat --stdout master..side > output &&\n+\tgit format-patch --numstat --stdout master..side >output &&\n \ttest 5 = $(grep \"^diff --git a/\" output | wc -l)'\n \n test_expect_success 'format-patch -- <path>' '\n@@ -852,20 +865,22 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n \tgit format-patch --ignore-if-in-upstream HEAD\n '\n \n-git_version=\"$(git --version | sed \"s/.* //\")\"\n+git_version=\"$(git --version >version && sed \"s/.* //\" version)\"\n \n signature() {\n \tprintf \"%s\\n%s\\n\\n\" \"-- \" \"${1:-$git_version}\"\n }\n \n test_expect_success 'format-patch default signature' '\n-\tgit format-patch --stdout -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature >expect &&\n \ttest_cmp expect output\n '\n \n test_expect_success 'format-patch --signature' '\n-\tgit format-patch --stdout --signature=\"my sig\" -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout --signature=\"my sig\" -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature \"my sig\" >expect &&\n \ttest_cmp expect output\n '\n@@ -1256,282 +1271,282 @@ append_signoff()\n \n test_expect_success 'signoff: commit with no body' '\n \tappend_signoff </dev/null >actual &&\n-\tcat <<\\EOF | sed \"s/EOL$//\" >expected &&\n-4:Subject: [PATCH] EOL\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat <<-\\EOF | sed \"s/EOL$//\" >expected &&\n+\t4:Subject: [PATCH] EOL\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: commit with only subject' '\n \techo subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: commit with only subject that does not end with NL' '\n \tprintf subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: no existing signoffs' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tbody\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: no existing signoffs and no trailing NL' '\n \tprintf \"subject\\n\\nbody\" | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: some random signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: misc conforming footer elements' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n-Tested-by: Some One <someone@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-15:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: my@house\n+\t(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n+\tTested-by: Some One <someone@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t15:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: some random signoff-alike' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-Fooled-by-me: my@house\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tbody\n+\tFooled-by-me: my@house\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: not really a signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-I want to mention about Signed-off-by: here.\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:I want to mention about Signed-off-by: here.\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tI want to mention about Signed-off-by: here.\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:I want to mention about Signed-off-by: here.\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: not really a signoff (2)' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-My unfortunate\n-Signed-off-by: example happens to be wrapped here.\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:Signed-off-by: example happens to be wrapped here.\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMy unfortunate\n+\tSigned-off-by: example happens to be wrapped here.\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:Signed-off-by: example happens to be wrapped here.\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: valid S-o-b paragraph in the middle' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Signed-off-by: my@house\n-Signed-off-by: your@house\n+\tSigned-off-by: my@house\n+\tSigned-off-by: your@house\n \n-A lot of houses.\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: my@house\n-10:Signed-off-by: your@house\n-11:\n-13:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tA lot of houses.\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: my@house\n+\t10:Signed-off-by: your@house\n+\t11:\n+\t13:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: the same signoff at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: the same signoff at the end, no trailing NL' '\n \tprintf \"subject\\n\\nSigned-off-by: C O Mitter <committer@example.com>\" |\n \t\tappend_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: the same signoff NOT at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-Signed-off-by: my@house\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-12:Signed-off-by: my@house\n-EOF\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\t12:Signed-off-by: my@house\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: tolerate garbage in conforming footer' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Tested-by: my@house\n-Some Trash\n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-13:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tTested-by: my@house\n+\tSome Trash\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t13:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: respect trailer config' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual &&\n \n \ttest_config trailer.Myfooter.ifexists add &&\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n test_expect_success 'signoff: footer begins with non-signoff without @ sign' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Reviewed-id: Noone\n-Tested-by: my@house\n-Change-id: Ideadbeef\n-Signed-off-by: C O Mitter <committer@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tReviewed-id: Noone\n+\tTested-by: my@house\n+\tChange-id: Ideadbeef\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expected <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expected actual\n '\n \n@@ -1547,42 +1562,42 @@ test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (2)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (3)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter ^master rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (4)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master.. >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (5)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 HEAD >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (6)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter with nothing' '\n@@ -1636,7 +1651,8 @@ test_expect_success 'format-patch format.outputDirectory option' '\n \ttest_config format.outputDirectory patches &&\n \trm -fr patches &&\n \tgit format-patch master..side &&\n-\ttest $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)\n+\tgit rev-list master..side >list &&\n+\ttest_line_count = $(ls patches | wc -l) list\n '\n \n test_expect_success 'format-patch -o overrides format.outputDirectory' '\n@@ -1649,19 +1665,32 @@ test_expect_success 'format-patch -o overrides format.outputDirectory' '\n \n test_expect_success 'format-patch --base' '\n \tgit checkout patchid &&\n-\tgit format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&\n-\tgit format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&\n+\tgit format-patch --stdout --base=HEAD~3 -1 >patch &&\n+\ttail -n 7 patch >actual1 &&\n+\tgit format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&\n+\ttail -n 7 patch >actual2 &&\n \techo >expected &&\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\tsignature >> expected &&\n+\tgit show --patch HEAD~2 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\$1}\" <patch.id.raw >patch.id &&\n+\techo \"prerequisite-patch-id: $(cat patch.id)\" >>expected &&\n+\tgit show --patch HEAD~1 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\$1}\" <patch.id.raw >patch.id &&\n+\techo \"prerequisite-patch-id: $(cat patch.id)\" >>expected &&\n+\tsignature >>expected &&\n \ttest_cmp expected actual1 &&\n \ttest_cmp expected actual2 &&\n \techo >fail &&\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n+\techo \"prerequisite-patch-id: $(\n+\t\tgit show --patch HEAD~2 >patch &&\n+\t\tgit patch-id --unstable <patch >patch.id.raw &&\n+\t\tawk \"{print \\$1}\" <patch.id.raw)\" >>fail &&\n+\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 >patch &&\n+\t\tgit patch-id --unstable <patch >patch.id.raw &&\n+\t\tawk \"{print \\$1}\" <pattch.id.raw)\" >>fail &&\n \tsignature >> fail &&\n \t! test_cmp fail actual1 &&\n \t! test_cmp fail actual2\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380712","messageId":"CAPig+cQE0r5tzTJ5qp1DSgE5L4Zu1W9kuwA0LKbZcVVTO2nK6A@mail.gmail.com","threadId":"51670","inReplyTo":"058f877c342e8ee6683235c32946e5238e7e87f5.1566182184.git.liu.denton@gmail.com","subject":"Re: [PATCH 1/3] t4014: clean up style","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-08-19T16:02:49Z","receivedAt":"2019-08-19T16:03:04Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Aug 18, 2019 at 10:38 PM Denton Liu <liu.denton@gmail.com> wrote:\n> diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\n> @@ -96,7 +97,7 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n>         git merge --no-ff slave &&\n> -       cnt=$(git format-patch -3 --stdout | grep \"^From \" | wc -l) &&\n> +       cnt=$(git format-patch -3 --stdout >patch && grep \"^From \" patch | wc -l) &&\n>         test $cnt = 3\n\nJust below here, you update tests to use test_line_count(). Why not do\nthe same here?\n\n> @@ -104,21 +105,22 @@ test_expect_success \"format-patch result applies\" '\n>\n>         git checkout -b rebuild-0 master &&\n>         git am -3 patch0 &&\n> -       cnt=$(git rev-list master.. | wc -l) &&\n> -       test $cnt = 2\n> +       git rev-list master.. >list &&\n> +       test_line_count = 2 list\n>  '\n> @@ -357,7 +370,7 @@ test_expect_success 'reroll count (-v)' '\n>  check_threading () {\n>         expect=\"$1\" &&\n>         shift &&\n> -       (git format-patch --stdout \"$@\"; echo $? > status.out) |\n> +       (git format-patch --stdout \"$@\"; echo $? >status.out) |\n>         # Prints everything between the Message-ID and In-Reply-To,\n>         # and replaces all Message-ID-lookalikes by a sequence number\n>         perl -ne '\n> @@ -372,12 +385,12 @@ check_threading () {\n>                         print;\n>                 }\n>                 print \"---\\n\" if /^From /i;\n> -       ' > actual &&\n> +       ' >actual &&\n>         test 0 = \"$(cat status.out)\" &&\n>         test_cmp \"$expect\" actual\n>  }\n\nNot a new issue, but this is more difficult to reason about than it\ncould be due to the manual squirreling away of the status code of the\nGit command which is upstream of the pipe. More straightforward would\nbe:\n\n    ...\n    shift &&\n    git format-patch --stdout \"$@\" >patch &&\n    perl -ne '...' <patch >actual &&\n    test_cmp \"$expect\" actual\n\nNo need for capturing or manually checking format-patch's exit code\nsince the &&-chain handles it for you. And, you no longer have a Git\ncommand upstream of a pipe.\n\n> @@ -852,20 +865,22 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n> -git_version=\"$(git --version | sed \"s/.* //\")\"\n> +git_version=\"$(git --version >version && sed \"s/.* //\" version)\"\n\nMeh. The exit code is being ignored anyhow since this is not part of a &&-chain.\n\n> @@ -1649,19 +1665,32 @@ test_expect_success 'format-patch -o overrides format.outputDirectory' '\n>  test_expect_success 'format-patch --base' '\n>         [...]\n>         echo >expected &&\n>         echo \"base-commit: $(git rev-parse HEAD~3)\" >>expected &&\n> -       echo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n> -       echo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n> -       signature >> expected &&\n> +       git show --patch HEAD~2 >patch &&\n> +       git patch-id --stable <patch >patch.id.raw &&\n> +       awk \"{print \\$1}\" <patch.id.raw >patch.id &&\n> +       echo \"prerequisite-patch-id: $(cat patch.id)\" >>expected &&\n> +       git show --patch HEAD~1 >patch &&\n> +       git patch-id --stable <patch >patch.id.raw &&\n> +       awk \"{print \\$1}\" <patch.id.raw >patch.id &&\n> +       echo \"prerequisite-patch-id: $(cat patch.id)\" >>expected &&\n\nNot a big deal, but you could take advantage of the fact that you're\nalready invoking 'awk', thus avoid the 'echo':\n\n    awk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >patch.id &&\n\n> +       signature >>expected &&\n>         test_cmp expected actual1 &&\n>         test_cmp expected actual2 &&\n>         echo >fail &&\n>         echo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n> -       echo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n> -       echo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n> +       echo \"prerequisite-patch-id: $(\n> +               git show --patch HEAD~2 >patch &&\n> +               git patch-id --unstable <patch >patch.id.raw &&\n> +               awk \"{print \\$1}\" <patch.id.raw)\" >>fail &&\n> +       echo \"prerequisite-patch-id: $(git show --patch HEAD~1 >patch &&\n> +               git patch-id --unstable <patch >patch.id.raw &&\n> +               awk \"{print \\$1}\" <pattch.id.raw)\" >>fail &&\n\nHmph, why is this case transformed in a different way than the case\nimmediately above.\n"},{"id":"380715","messageId":"CAPig+cSG6mHCgLRw=QLWkVhK4oVSFkQRCszrBdO6SCGA+M0B3Q@mail.gmail.com","threadId":"51670","inReplyTo":"7619da962d1fc804392e3552fbd56bf4bc68ac38.1566182184.git.liu.denton@gmail.com","subject":"Re: [PATCH 2/3] Doc: add more detail for git-format-patch","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-08-19T17:09:04Z","receivedAt":"2019-08-19T17:09:20Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Aug 18, 2019 at 10:37 PM Denton Liu <liu.denton@gmail.com> wrote:\n> In git-format-patch.txt, we were missing some key user information.\n> First of all, using the `--to` and `--cc` options don't override\n> `format.to` and `format.cc` variables, respectively. They add on to each\n> other. Document this.\n>\n> In addition, document the special value of `--base=auto`.\n>\n> Next, while we're at it, surround option arguments with <>.\n>\n> Finally, document the `format.outputDirectory` config and change\n> `format.coverletter` to use camelcase.\n\nI can't figure out if you typeset \"camelcase\" like that intentionally,\nas opposed to \"camelCase\" or \"camel case\" or \"camel-case\".\n\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\n>  --to=<email>::\n>         Add a `To:` header to the email headers. This is in addition\n> -       to any configured headers, and may be used multiple times.\n> +       to any configured headers, and may be used multiple times. The\n> +       emails given will be used along with any emails given by\n> +       `format.to` configurations.\n\nHmph. This seems redundant. The description already says \"This is in\naddition to...\", so a new sentence saying \"...used along with...\" is\njust parroting what was already stated.\n\n>         The negated form `--no-to` discards all `To:` headers added so\n>         far (from config or command line).\n> @@ -314,7 +318,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n>  --base=<commit>::\n>         Record the base tree information to identify the state the\n>         patch series applies to.  See the BASE TREE INFORMATION section\n> -       below for details.\n> +       below for details. If <commit> is equal to \"auto\", a base commit\n> +       is automatically chosen.\n\n\"is equal to\" is unnecessarily technical-sounding. How about:\n\n    If <commit> is \"auto\", ...\n"},{"id":"380717","messageId":"CAPig+cS1xqO3w9dAmYpHSCJJyquWRhJgYOpasScafabGEYuVWg@mail.gmail.com","threadId":"51670","inReplyTo":"5cc5e354b6d84609f3d1de087b3390488abe5343.1566182184.git.liu.denton@gmail.com","subject":"Re: [PATCH 3/3] format-patch: infer cover letter from branch description","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-08-19T17:29:26Z","receivedAt":"2019-08-19T17:29:40Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Aug 18, 2019 at 10:37 PM Denton Liu <liu.denton@gmail.com> wrote:\n> We used to populate the subject of the cover letter generated by\n> git-format-patch with \"*** SUBJECT HERE ***\". However, if a user submits\n> multiple patchsets, they may want to keep a consistent subject between\n> rerolls.\n>\n> If git-format-patch is run with `--infer-cover-letter` or\n> `format.inferCoverSubject`, infer the subject for the cover letter from\n> the top line(s) of a branch description, similar to how a subject is\n> read from a commit message.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\n> @@ -36,6 +36,11 @@ format.subjectPrefix::\n> +format.inferCoverSubject::\n> +       A boolean that controls whether or not to infer the subject for\n> +       the cover letter based on the branch's description. See the\n> +       --infer-cover-subject option in linkgit:git-format-patch[1].\n\nWhat is the default value?\n"},{"id":"380746","messageId":"20190819231614.GA3444@archbookpro.localdomain","threadId":"51670","inReplyTo":"CAPig+cSG6mHCgLRw=QLWkVhK4oVSFkQRCszrBdO6SCGA+M0B3Q@mail.gmail.com","subject":"Re: [PATCH 2/3] Doc: add more detail for git-format-patch","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T23:16:14Z","receivedAt":"2019-08-19T23:16:18Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Mon, Aug 19, 2019 at 01:09:04PM -0400, Eric Sunshine wrote:\n> On Sun, Aug 18, 2019 at 10:37 PM Denton Liu <liu.denton@gmail.com> wrote:\n> > In git-format-patch.txt, we were missing some key user information.\n> > First of all, using the `--to` and `--cc` options don't override\n> > `format.to` and `format.cc` variables, respectively. They add on to each\n> > other. Document this.\n> >\n> > In addition, document the special value of `--base=auto`.\n> >\n> > Next, while we're at it, surround option arguments with <>.\n> >\n> > Finally, document the `format.outputDirectory` config and change\n> > `format.coverletter` to use camelcase.\n> \n> I can't figure out if you typeset \"camelcase\" like that intentionally,\n> as opposed to \"camelCase\" or \"camel case\" or \"camel-case\".\n\nI thought that was how it's spelled but a quick Google search proves me\nwrong.\n\n> \n> > Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> > ---\n> > diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\n> >  --to=<email>::\n> >         Add a `To:` header to the email headers. This is in addition\n> > -       to any configured headers, and may be used multiple times.\n> > +       to any configured headers, and may be used multiple times. The\n> > +       emails given will be used along with any emails given by\n> > +       `format.to` configurations.\n> \n> Hmph. This seems redundant. The description already says \"This is in\n> addition to...\", so a new sentence saying \"...used along with...\" is\n> just parroting what was already stated.\n> \n> >         The negated form `--no-to` discards all `To:` headers added so\n> >         far (from config or command line).\n> > @@ -314,7 +318,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n> >  --base=<commit>::\n> >         Record the base tree information to identify the state the\n> >         patch series applies to.  See the BASE TREE INFORMATION section\n> > -       below for details.\n> > +       below for details. If <commit> is equal to \"auto\", a base commit\n> > +       is automatically chosen.\n> \n> \"is equal to\" is unnecessarily technical-sounding. How about:\n> \n>     If <commit> is \"auto\", ...\n"},{"id":"380840","messageId":"xmqq1rxfveym.fsf@gitster-ct.c.googlers.com","threadId":"51670","inReplyTo":"7619da962d1fc804392e3552fbd56bf4bc68ac38.1566182184.git.liu.denton@gmail.com","subject":"Re: [PATCH 2/3] Doc: add more detail for git-format-patch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-20T19:01:21Z","receivedAt":"2019-08-20T19:01:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> Next, while we're at it, surround option arguments with <>.\n> ...\n>  \t\t   [--start-number <n>] [--numbered-files]\n> -\t\t   [--in-reply-to=Message-Id] [--suffix=.<sfx>]\n> +\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n>  \t\t   [--ignore-if-in-upstream]\n> -\t\t   [--rfc] [--subject-prefix=Subject-Prefix]\n> +\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n> ...\n> ---in-reply-to=Message-Id::\n> +--in-reply-to=<Message-Id>::\n\nThat is a good change, but if we are making this change while are at\nit, I think we should fix it to read <message id>.  \"Message-Id\" is\na good spelling iff we are talking about the label on the left hand\nside of colon in e-mail header, but in this context, we are talking\nabout the value to be placed on that header.\n\nAll the other multi-word placeholders in the SYNOPSIS section spell\nthe words as normal multiple words separated with whitespace in\nlower case.  You'd also want to fix the spelling of Subject-Prefix\nto <subject prefix> for consistency.\n\nThanks.\n\n"}]}