{"thread":{"id":"37892","subject":"[PATCHv3 0/5] Handling empty notes","startedAt":"2014-11-07T09:19:16Z","lastAt":"2014-11-10T20:18:14Z","messageCount":12,"participants":["Johan Herland","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"251445","messageId":"1415351961-31567-1-git-send-email-johan@herland.net","threadId":"37892","inReplyTo":null,"subject":"[PATCHv3 0/5] Handling empty notes","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-11-07T09:19:16Z","receivedAt":"2014-11-07T09:19:16Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"Changes v1 -> v2:\n - Incorporate Eric's feedback\n - Factor out an initial fix, needed before adding the tests\n\nChanges v2 -> v3:\n - Incorporate Junio's feedback\n - Move tests from t3312 to t3301\n - Refactor the display of empty notes (the part concerning\n   git-log) into a separate follow-up patch (#4)\n - Add a final (optional) patch with some whitespace and other\n   cleanups in t3301. Feel free to drop this if it's too much\n   churn.\n\n\nHave fun! :)\n\n...Johan\n\nJohan Herland (5):\n  builtin/notes: Fix premature failure when trying to add the empty blob\n  t3301: Verify that 'git notes' removes empty notes by default\n  builtin/notes: Add --allow-empty, to allow storing empty notes\n  notes: Empty notes should be shown by 'git log'\n  t3301: Use write_script(), nitpick whitespace\n\n Documentation/git-notes.txt |  12 +-\n builtin/notes.c             |  25 ++--\n notes.c                     |   3 +-\n t/t3301-notes.sh            | 301 +++++++++++++++++++++++++-------------------\n 4 files changed, 197 insertions(+), 144 deletions(-)\n\n-- \n2.0.0.rc4.501.gdaf83ca\n"},{"id":"251450","messageId":"1415351961-31567-2-git-send-email-johan@herland.net","threadId":"37892","inReplyTo":"1415351961-31567-1-git-send-email-johan@herland.net","subject":"[PATCHv3 1/5] builtin/notes: Fix premature failure when trying to add the empty blob","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-11-07T09:19:17Z","receivedAt":"2014-11-07T09:19:17Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"This fixes a small buglet when trying to explicitly add the empty blob\nas a note object using the -c or -C option to git notes add/append.\nInstead of failing with a nonsensical error message indicating that the\nempty blob does not exist, we should rather behave as if an empty notes\nmessage was given (e.g. using -m \"\" or -F /dev/null).\n\nThe next patch contains a test that verifies the fixed behavior.\n\nFound-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n builtin/notes.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 68b6cd8..9ee6816 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -266,7 +266,7 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)\n \n \tif (get_sha1(arg, object))\n \t\tdie(_(\"Failed to resolve '%s' as a valid ref.\"), arg);\n-\tif (!(buf = read_sha1_file(object, &type, &len)) || !len) {\n+\tif (!(buf = read_sha1_file(object, &type, &len))) {\n \t\tfree(buf);\n \t\tdie(_(\"Failed to read object '%s'.\"), arg);\n \t}\n-- \n2.0.0.rc4.501.gdaf83ca\n"},{"id":"251446","messageId":"1415351961-31567-3-git-send-email-johan@herland.net","threadId":"37892","inReplyTo":"1415351961-31567-1-git-send-email-johan@herland.net","subject":"[PATCHv3 2/5] t3301: Verify that 'git notes' removes empty notes by default","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-11-07T09:19:18Z","receivedAt":"2014-11-07T09:19:18Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"Add test cases documenting the current behavior when trying to\nadd/append/edit empty notes. This is in preparation for adding\n--allow-empty; to allow empty notes to be stored.\n\nImproved-by: Eric Sunshine <sunshine@sunshineco.com>\nImproved-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n t/t3301-notes.sh | 27 +++++++++++++++++++++++++++\n 1 file changed, 27 insertions(+)\n\ndiff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\nindex cfd67ff..33f0558 100755\n--- a/t/t3301-notes.sh\n+++ b/t/t3301-notes.sh\n@@ -1239,4 +1239,31 @@ test_expect_success 'git notes get-ref (--ref)' '\n \ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref)\" = \"refs/notes/baz\"\n '\n \n+test_expect_success 'setup testing of empty notes' '\n+\tgit config --unset core.notesRef &&\n+\ttest_commit 16th &&\n+\tempty_blob=$(git hash-object -w /dev/null)\n+'\n+\n+while read cmd\n+do\n+\ttest_expect_success \"'git notes $cmd' removes empty note\" \"\n+\t\ttest_might_fail git notes remove HEAD &&\n+\t\tMSG= git notes $cmd &&\n+\t\ttest_must_fail git notes list HEAD\n+\t\"\n+done <<\\EOF\n+add\n+add -F /dev/null\n+add -m \"\"\n+add -c \"$empty_blob\"\n+add -C \"$empty_blob\"\n+append\n+append -F /dev/null\n+append -m \"\"\n+append -c \"$empty_blob\"\n+append -C \"$empty_blob\"\n+edit\n+EOF\n+\n test_done\n-- \n2.0.0.rc4.501.gdaf83ca\n"},{"id":"251448","messageId":"1415351961-31567-4-git-send-email-johan@herland.net","threadId":"37892","inReplyTo":"1415351961-31567-1-git-send-email-johan@herland.net","subject":"[PATCHv3 3/5] builtin/notes: Add --allow-empty, to allow storing empty notes","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-11-07T09:19:19Z","receivedAt":"2014-11-07T09:19:19Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"Although the \"git notes\" man page advertises that we support binary-safe\nnotes addition (using the -C option), we currently do not support adding\nthe empty note (i.e. using the empty blob to annotate an object). Instead,\nan empty note is always treated as an intent to remove the note\naltogether.\n\nIntroduce the --allow-empty option to the add/append/edit subcommands,\nto explicitly allow an empty note to be stored into the notes tree.\n\nAlso update the documentation, and add test cases for the new option.\n\nReported-by: James H. Fisher <jhf@trifork.com>\nImproved-by: Kyle J. McKay <mackyle@gmail.com>\nImproved-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n Documentation/git-notes.txt | 12 ++++++++----\n builtin/notes.c             | 23 ++++++++++++++---------\n t/t3301-notes.sh            | 10 +++++++++-\n 3 files changed, 31 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt\nindex 310f0a5..851518d 100644\n--- a/Documentation/git-notes.txt\n+++ b/Documentation/git-notes.txt\n@@ -9,10 +9,10 @@ SYNOPSIS\n --------\n [verse]\n 'git notes' [list [<object>]]\n-'git notes' add [-f] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]\n+'git notes' add [-f] [--allow-empty] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]\n 'git notes' copy [-f] ( --stdin | <from-object> <to-object> )\n-'git notes' append [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]\n-'git notes' edit [<object>]\n+'git notes' append [--allow-empty] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]\n+'git notes' edit [--allow-empty] [<object>]\n 'git notes' show [<object>]\n 'git notes' merge [-v | -q] [-s <strategy> ] <notes-ref>\n 'git notes' merge --commit [-v | -q]\n@@ -155,6 +155,10 @@ OPTIONS\n \tLike '-C', but with '-c' the editor is invoked, so that\n \tthe user can further edit the note message.\n \n+--allow-empty::\n+\tAllow an empty note object to be stored. The default behavior is\n+\tto automatically remove empty notes.\n+\n --ref <ref>::\n \tManipulate the notes tree in <ref>.  This overrides\n \t'GIT_NOTES_REF' and the \"core.notesRef\" configuration.  The ref\n@@ -287,7 +291,7 @@ arbitrary files using 'git hash-object':\n ------------\n $ cc *.c\n $ blob=$(git hash-object -w a.out)\n-$ git notes --ref=built add -C \"$blob\" HEAD\n+$ git notes --ref=built add --allow-empty -C \"$blob\" HEAD\n ------------\n \n (You cannot simply use `git notes --ref=built add -F a.out HEAD`\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 9ee6816..038a419 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -22,10 +22,10 @@\n \n static const char * const git_notes_usage[] = {\n \tN_(\"git notes [--ref <notes_ref>] [list [<object>]]\"),\n-\tN_(\"git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]\"),\n+\tN_(\"git notes [--ref <notes_ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]\"),\n \tN_(\"git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>\"),\n-\tN_(\"git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]\"),\n-\tN_(\"git notes [--ref <notes_ref>] edit [<object>]\"),\n+\tN_(\"git notes [--ref <notes_ref>] append [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]\"),\n+\tN_(\"git notes [--ref <notes_ref>] edit [--allow-empty] [<object>]\"),\n \tN_(\"git notes [--ref <notes_ref>] show [<object>]\"),\n \tN_(\"git notes [--ref <notes_ref>] merge [-v | -q] [-s <strategy> ] <notes_ref>\"),\n \tN_(\"git notes merge --commit [-v | -q]\"),\n@@ -150,8 +150,8 @@ static void write_commented_object(int fd, const unsigned char *object)\n }\n \n static void create_note(const unsigned char *object, struct msg_arg *msg,\n-\t\t\tint append_only, const unsigned char *prev,\n-\t\t\tunsigned char *result)\n+\t\t\tint append_only, int allow_empty,\n+\t\t\tconst unsigned char *prev, unsigned char *result)\n {\n \tchar *path = NULL;\n \n@@ -202,7 +202,7 @@ static void create_note(const unsigned char *object, struct msg_arg *msg,\n \t\tfree(prev_buf);\n \t}\n \n-\tif (!msg->buf.len) {\n+\tif (!allow_empty && !msg->buf.len) {\n \t\tfprintf(stderr, _(\"Removing note for object %s\\n\"),\n \t\t\tsha1_to_hex(object));\n \t\thashclr(result);\n@@ -397,7 +397,7 @@ static int append_edit(int argc, const char **argv, const char *prefix);\n \n static int add(int argc, const char **argv, const char *prefix)\n {\n-\tint retval = 0, force = 0;\n+\tint retval = 0, force = 0, allow_empty = 0;\n \tconst char *object_ref;\n \tstruct notes_tree *t;\n \tunsigned char object[20], new_note[20];\n@@ -417,6 +417,8 @@ static int add(int argc, const char **argv, const char *prefix)\n \t\t{ OPTION_CALLBACK, 'C', \"reuse-message\", &msg, N_(\"object\"),\n \t\t\tN_(\"reuse specified note object\"), PARSE_OPT_NONEG,\n \t\t\tparse_reuse_arg},\n+\t\tOPT_BOOL(0, \"allow-empty\", &allow_empty,\n+\t\t\tN_(\"allow storing empty note\")),\n \t\tOPT__FORCE(&force, N_(\"replace existing notes\")),\n \t\tOPT_END()\n \t};\n@@ -460,7 +462,7 @@ static int add(int argc, const char **argv, const char *prefix)\n \t\t\tsha1_to_hex(object));\n \t}\n \n-\tcreate_note(object, &msg, 0, note, new_note);\n+\tcreate_note(object, &msg, 0, allow_empty, note, new_note);\n \n \tif (is_null_sha1(new_note))\n \t\tremove_note(t, object);\n@@ -554,6 +556,7 @@ out:\n \n static int append_edit(int argc, const char **argv, const char *prefix)\n {\n+\tint allow_empty = 0;\n \tconst char *object_ref;\n \tstruct notes_tree *t;\n \tunsigned char object[20], new_note[20];\n@@ -574,6 +577,8 @@ static int append_edit(int argc, const char **argv, const char *prefix)\n \t\t{ OPTION_CALLBACK, 'C', \"reuse-message\", &msg, N_(\"object\"),\n \t\t\tN_(\"reuse specified note object\"), PARSE_OPT_NONEG,\n \t\t\tparse_reuse_arg},\n+\t\tOPT_BOOL(0, \"allow-empty\", &allow_empty,\n+\t\t\tN_(\"allow storing empty note\")),\n \t\tOPT_END()\n \t};\n \tint edit = !strcmp(argv[0], \"edit\");\n@@ -600,7 +605,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)\n \tt = init_notes_check(argv[0]);\n \tnote = get_note(t, object);\n \n-\tcreate_note(object, &msg, !edit, note, new_note);\n+\tcreate_note(object, &msg, !edit, allow_empty, note, new_note);\n \n \tif (is_null_sha1(new_note))\n \t\tremove_note(t, object);\ndiff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\nindex 33f0558..8280a1a 100755\n--- a/t/t3301-notes.sh\n+++ b/t/t3301-notes.sh\n@@ -1242,7 +1242,8 @@ test_expect_success 'git notes get-ref (--ref)' '\n test_expect_success 'setup testing of empty notes' '\n \tgit config --unset core.notesRef &&\n \ttest_commit 16th &&\n-\tempty_blob=$(git hash-object -w /dev/null)\n+\tempty_blob=$(git hash-object -w /dev/null) &&\n+\techo \"$empty_blob\" >expect_empty\n '\n \n while read cmd\n@@ -1252,6 +1253,13 @@ do\n \t\tMSG= git notes $cmd &&\n \t\ttest_must_fail git notes list HEAD\n \t\"\n+\n+\ttest_expect_success \"'git notes $cmd --allow-empty' stores empty note\" \"\n+\t\ttest_might_fail git notes remove HEAD &&\n+\t\tMSG= git notes $cmd --allow-empty &&\n+\t\tgit notes list HEAD >actual &&\n+\t\ttest_cmp expect_empty actual\n+\t\"\n done <<\\EOF\n add\n add -F /dev/null\n-- \n2.0.0.rc4.501.gdaf83ca\n"},{"id":"251449","messageId":"1415351961-31567-5-git-send-email-johan@herland.net","threadId":"37892","inReplyTo":"1415351961-31567-1-git-send-email-johan@herland.net","subject":"[PATCHv3 4/5] notes: Empty notes should be shown by 'git log'","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-11-07T09:19:20Z","receivedAt":"2014-11-07T09:19:20Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"If the user has gone through the trouble of explicitly adding an empty\nnote, then \"git log\" should not silently skip it (as if it didn't exist).\n\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n notes.c          |  3 +--\n t/t3301-notes.sh | 12 ++++++++++++\n 2 files changed, 13 insertions(+), 2 deletions(-)\n\ndiff --git a/notes.c b/notes.c\nindex 5fe691d..62bc6e1 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -1218,8 +1218,7 @@ static void format_note(struct notes_tree *t, const unsigned char *object_sha1,\n \tif (!sha1)\n \t\treturn;\n \n-\tif (!(msg = read_sha1_file(sha1, &type, &msglen)) || !msglen ||\n-\t\t\ttype != OBJ_BLOB) {\n+\tif (!(msg = read_sha1_file(sha1, &type, &msglen)) || type != OBJ_BLOB) {\n \t\tfree(msg);\n \t\treturn;\n \t}\ndiff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\nindex 8280a1a..f5d8193 100755\n--- a/t/t3301-notes.sh\n+++ b/t/t3301-notes.sh\n@@ -1274,4 +1274,16 @@ append -C \"$empty_blob\"\n edit\n EOF\n \n+test_expect_success 'empty notes are displayed by git log' '\n+\ttest_commit 17th &&\n+\tgit log -1 >expect &&\n+\tcat >>expect <<\\EOF &&\n+\n+Notes:\n+EOF\n+\tgit notes add -C \"$empty_blob\" --allow-empty &&\n+\tgit log -1 >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n2.0.0.rc4.501.gdaf83ca\n"},{"id":"251447","messageId":"1415351961-31567-6-git-send-email-johan@herland.net","threadId":"37892","inReplyTo":"1415351961-31567-1-git-send-email-johan@herland.net","subject":"[PATCHv3 5/5] t3301: Use write_script(), nitpick whitespace","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-11-07T09:19:21Z","receivedAt":"2014-11-07T09:19:21Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"Signed-off-by: Johan Herland <johan@herland.net>\n---\n\nDrop this if it's too much churn.\n\n...Johan\n\n t/t3301-notes.sh | 254 +++++++++++++++++++++++++++----------------------------\n 1 file changed, 126 insertions(+), 128 deletions(-)\n\ndiff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\nindex f5d8193..80caee0 100755\n--- a/t/t3301-notes.sh\n+++ b/t/t3301-notes.sh\n@@ -7,13 +7,11 @@ test_description='Test commit notes'\n \n . ./test-lib.sh\n \n-cat > fake_editor.sh << \\EOF\n-#!/bin/sh\n-echo \"$MSG\" > \"$1\"\n-echo \"$MSG\" >& 2\n+write_script fake_editor <<\\EOF\n+echo \"$MSG\" >\"$1\"\n+echo \"$MSG\" >&2\n EOF\n-chmod a+x fake_editor.sh\n-GIT_EDITOR=./fake_editor.sh\n+GIT_EDITOR=./fake_editor\n export GIT_EDITOR\n \n test_expect_success 'cannot annotate non-existing HEAD' '\n@@ -21,11 +19,11 @@ test_expect_success 'cannot annotate non-existing HEAD' '\n '\n \n test_expect_success setup '\n-\t: > a1 &&\n+\t: >a1 &&\n \tgit add a1 &&\n \ttest_tick &&\n \tgit commit -m 1st &&\n-\t: > a2 &&\n+\t: >a2 &&\n \tgit add a2 &&\n \ttest_tick &&\n \tgit commit -m 2nd\n@@ -131,7 +129,7 @@ test_expect_success 'can overwrite existing note with \"git notes add -f\"' '\n \ttest_must_fail git notes show HEAD^\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 268048bfb8a1fb38e703baceb8ab235421bf80c5\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:14:13 2005 -0700\n@@ -144,12 +142,12 @@ EOF\n \n test_expect_success 'show notes' '\n \t! (git cat-file commit HEAD | grep b1) &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect output\n '\n \n test_expect_success 'create multi-line notes (setup)' '\n-\t: > a3 &&\n+\t: >a3 &&\n \tgit add a3 &&\n \ttest_tick &&\n \tgit commit -m 3rd &&\n@@ -158,7 +156,7 @@ c3c3c3c3\n d3d3d3\" git notes add\n '\n \n-cat > expect-multiline << EOF\n+cat >expect-multiline <<EOF\n commit 1584215f1d29c65e99c6c6848626553fdd07fd75\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:15:13 2005 -0700\n@@ -171,23 +169,23 @@ Notes:\n     d3d3d3\n EOF\n \n-printf \"\\n\" >> expect-multiline\n-cat expect >> expect-multiline\n+printf \"\\n\" >>expect-multiline\n+cat expect >>expect-multiline\n \n test_expect_success 'show multi-line notes' '\n-\tgit log -2 > output &&\n+\tgit log -2 >output &&\n \ttest_cmp expect-multiline output\n '\n test_expect_success 'create -F notes (setup)' '\n-\t: > a4 &&\n+\t: >a4 &&\n \tgit add a4 &&\n \ttest_tick &&\n \tgit commit -m 4th &&\n-\techo \"xyzzy\" > note5 &&\n+\techo \"xyzzy\" >note5 &&\n \tgit notes add -F note5\n '\n \n-cat > expect-F << EOF\n+cat >expect-F <<EOF\n commit 15023535574ded8b1a89052b32673f84cf9582b8\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:16:13 2005 -0700\n@@ -198,22 +196,22 @@ Notes:\n     xyzzy\n EOF\n \n-printf \"\\n\" >> expect-F\n-cat expect-multiline >> expect-F\n+printf \"\\n\" >>expect-F\n+cat expect-multiline >>expect-F\n \n test_expect_success 'show -F notes' '\n-\tgit log -3 > output &&\n+\tgit log -3 >output &&\n \ttest_cmp expect-F output\n '\n \n test_expect_success 'Re-adding -F notes without -f fails' '\n-\techo \"zyxxy\" > note5 &&\n+\techo \"zyxxy\" >note5 &&\n \ttest_must_fail git notes add -F note5 &&\n-\tgit log -3 > output &&\n+\tgit log -3 >output &&\n \ttest_cmp expect-F output\n '\n \n-cat >expect << EOF\n+cat >expect <<EOF\n commit 15023535574ded8b1a89052b32673f84cf9582b8\n tree e070e3af51011e47b183c33adf9736736a525709\n parent 1584215f1d29c65e99c6c6848626553fdd07fd75\n@@ -305,7 +303,7 @@ test_expect_success 'git log --no-notes resets ref list' '\n '\n \n test_expect_success 'create -m notes (setup)' '\n-\t: > a5 &&\n+\t: >a5 &&\n \tgit add a5 &&\n \ttest_tick &&\n \tgit commit -m 5th &&\n@@ -315,7 +313,7 @@ baz\"\n '\n \n whitespace=\"    \"\n-cat > expect-m << EOF\n+cat >expect-m <<EOF\n commit bd1753200303d0a0344be813e504253b3d98e74d\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:17:13 2005 -0700\n@@ -330,11 +328,11 @@ $whitespace\n     baz\n EOF\n \n-printf \"\\n\" >> expect-m\n-cat expect-F >> expect-m\n+printf \"\\n\" >>expect-m\n+cat expect-F >>expect-m\n \n test_expect_success 'show -m notes' '\n-\tgit log -4 > output &&\n+\tgit log -4 >output &&\n \ttest_cmp expect-m output\n '\n \n@@ -342,7 +340,7 @@ test_expect_success 'remove note with add -f -F /dev/null (setup)' '\n \tgit notes add -f -F /dev/null\n '\n \n-cat > expect-rm-F << EOF\n+cat >expect-rm-F <<EOF\n commit bd1753200303d0a0344be813e504253b3d98e74d\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:17:13 2005 -0700\n@@ -350,11 +348,11 @@ Date:   Thu Apr 7 15:17:13 2005 -0700\n     5th\n EOF\n \n-printf \"\\n\" >> expect-rm-F\n-cat expect-F >> expect-rm-F\n+printf \"\\n\" >>expect-rm-F\n+cat expect-F >>expect-rm-F\n \n test_expect_success 'verify note removal with -F /dev/null' '\n-\tgit log -4 > output &&\n+\tgit log -4 >output &&\n \ttest_cmp expect-rm-F output &&\n \ttest_must_fail git notes show\n '\n@@ -364,12 +362,12 @@ test_expect_success 'do not create empty note with -m \"\" (setup)' '\n '\n \n test_expect_success 'verify non-creation of note with -m \"\"' '\n-\tgit log -4 > output &&\n+\tgit log -4 >output &&\n \ttest_cmp expect-rm-F output &&\n \ttest_must_fail git notes show\n '\n \n-cat > expect-combine_m_and_F << EOF\n+cat >expect-combine_m_and_F <<EOF\n foo\n \n xyzzy\n@@ -382,10 +380,10 @@ baz\n EOF\n \n test_expect_success 'create note with combination of -m and -F' '\n-\techo \"xyzzy\" > note_a &&\n-\techo \"zyxxy\" > note_b &&\n+\techo \"xyzzy\" >note_a &&\n+\techo \"zyxxy\" >note_b &&\n \tgit notes add -m \"foo\" -F note_a -m \"bar\" -F note_b -m \"baz\" &&\n-\tgit notes show > output &&\n+\tgit notes show >output &&\n \ttest_cmp expect-combine_m_and_F output\n '\n \n@@ -394,7 +392,7 @@ test_expect_success 'remove note with \"git notes remove\" (setup)' '\n \tgit notes remove\n '\n \n-cat > expect-rm-remove << EOF\n+cat >expect-rm-remove <<EOF\n commit bd1753200303d0a0344be813e504253b3d98e74d\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:17:13 2005 -0700\n@@ -408,24 +406,24 @@ Date:   Thu Apr 7 15:16:13 2005 -0700\n     4th\n EOF\n \n-printf \"\\n\" >> expect-rm-remove\n-cat expect-multiline >> expect-rm-remove\n+printf \"\\n\" >>expect-rm-remove\n+cat expect-multiline >>expect-rm-remove\n \n test_expect_success 'verify note removal with \"git notes remove\"' '\n-\tgit log -4 > output &&\n+\tgit log -4 >output &&\n \ttest_cmp expect-rm-remove output &&\n \ttest_must_fail git notes show HEAD^\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd75\n c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5\n EOF\n \n test_expect_success 'removing non-existing note should not create new commit' '\n-\tgit rev-parse --verify refs/notes/commits > before_commit &&\n+\tgit rev-parse --verify refs/notes/commits >before_commit &&\n \ttest_must_fail git notes remove HEAD^ &&\n-\tgit rev-parse --verify refs/notes/commits > after_commit &&\n+\tgit rev-parse --verify refs/notes/commits >after_commit &&\n \ttest_cmp before_commit after_commit\n '\n \n@@ -505,33 +503,33 @@ test_expect_success 'removing with --stdin --ignore-missing' '\n '\n \n test_expect_success 'list notes with \"git notes list\"' '\n-\tgit notes list > output &&\n+\tgit notes list >output &&\n \ttest_cmp expect output\n '\n \n test_expect_success 'list notes with \"git notes\"' '\n-\tgit notes > output &&\n+\tgit notes >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n c18dc024e14f08d18d14eea0d747ff692d66d6a3\n EOF\n \n test_expect_success 'list specific note with \"git notes list <object>\"' '\n-\tgit notes list HEAD^^ > output &&\n+\tgit notes list HEAD^^ >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n EOF\n \n test_expect_success 'listing non-existing notes fails' '\n-\ttest_must_fail git notes list HEAD > output &&\n+\ttest_must_fail git notes list HEAD >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n Initial set of notes\n \n More notes appended with git notes append\n@@ -540,24 +538,24 @@ EOF\n test_expect_success 'append to existing note with \"git notes append\"' '\n \tgit notes add -m \"Initial set of notes\" &&\n \tgit notes append -m \"More notes appended with git notes append\" &&\n-\tgit notes show > output &&\n+\tgit notes show >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect_list << EOF\n+cat >expect_list <<EOF\n c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd75\n c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5\n 4b6ad22357cc8a1296720574b8d2fbc22fab0671 bd1753200303d0a0344be813e504253b3d98e74d\n EOF\n \n test_expect_success '\"git notes list\" does not expand to \"git notes list HEAD\"' '\n-\tgit notes list > output &&\n+\tgit notes list >output &&\n \ttest_cmp expect_list output\n '\n \n test_expect_success 'appending empty string does not change existing note' '\n \tgit notes append -m \"\" &&\n-\tgit notes show > output &&\n+\tgit notes show >output &&\n \ttest_cmp expect output\n '\n \n@@ -567,7 +565,7 @@ test_expect_success 'git notes append == add when there is no existing note' '\n \tgit notes append -m \"Initial set of notes\n \n More notes appended with git notes append\" &&\n-\tgit notes show > output &&\n+\tgit notes show >output &&\n \ttest_cmp expect output\n '\n \n@@ -579,14 +577,14 @@ test_expect_success 'appending empty string to non-existing note does not create\n '\n \n test_expect_success 'create other note on a different notes ref (setup)' '\n-\t: > a6 &&\n+\t: >a6 &&\n \tgit add a6 &&\n \ttest_tick &&\n \tgit commit -m 6th &&\n \tGIT_NOTES_REF=\"refs/notes/other\" git notes add -m \"other note\"\n '\n \n-cat > expect-other << EOF\n+cat >expect-other <<EOF\n commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:18:13 2005 -0700\n@@ -597,7 +595,7 @@ Notes (other):\n     other note\n EOF\n \n-cat > expect-not-other << EOF\n+cat >expect-not-other <<EOF\n commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:18:13 2005 -0700\n@@ -606,27 +604,27 @@ Date:   Thu Apr 7 15:18:13 2005 -0700\n EOF\n \n test_expect_success 'Do not show note on other ref by default' '\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect-not-other output\n '\n \n test_expect_success 'Do show note when ref is given in GIT_NOTES_REF' '\n-\tGIT_NOTES_REF=\"refs/notes/other\" git log -1 > output &&\n+\tGIT_NOTES_REF=\"refs/notes/other\" git log -1 >output &&\n \ttest_cmp expect-other output\n '\n \n test_expect_success 'Do show note when ref is given in core.notesRef config' '\n \tgit config core.notesRef \"refs/notes/other\" &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect-other output\n '\n \n test_expect_success 'Do not show note when core.notesRef is overridden' '\n-\tGIT_NOTES_REF=\"refs/notes/wrong\" git log -1 > output &&\n+\tGIT_NOTES_REF=\"refs/notes/wrong\" git log -1 >output &&\n \ttest_cmp expect-not-other output\n '\n \n-cat > expect-both << EOF\n+cat >expect-both <<EOF\n commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:18:13 2005 -0700\n@@ -655,14 +653,14 @@ test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' '\n \tGIT_NOTES_REF=refs/notes/commits git notes add -m\"order test\" &&\n \tgit config --unset core.notesRef &&\n \tgit config notes.displayRef \"refs/notes/*\" &&\n-\tgit log -2 > output &&\n+\tgit log -2 >output &&\n \ttest_cmp expect-both output\n '\n \n test_expect_success 'core.notesRef is implicitly in notes.displayRef' '\n \tgit config core.notesRef refs/notes/commits &&\n \tgit config notes.displayRef refs/notes/other &&\n-\tgit log -2 > output &&\n+\tgit log -2 >output &&\n \ttest_cmp expect-both output\n '\n \n@@ -670,11 +668,11 @@ test_expect_success 'notes.displayRef can be given more than once' '\n \tgit config --unset core.notesRef &&\n \tgit config notes.displayRef refs/notes/commits &&\n \tgit config --add notes.displayRef refs/notes/other &&\n-\tgit log -2 > output &&\n+\tgit log -2 >output &&\n \ttest_cmp expect-both output\n '\n \n-cat > expect-both-reversed << EOF\n+cat >expect-both-reversed <<EOF\n commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:18:13 2005 -0700\n@@ -692,7 +690,7 @@ test_expect_success 'notes.displayRef respects order' '\n \tgit config core.notesRef refs/notes/other &&\n \tgit config --unset-all notes.displayRef &&\n \tgit config notes.displayRef refs/notes/commits &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect-both-reversed output\n '\n \n@@ -700,11 +698,11 @@ test_expect_success 'GIT_NOTES_DISPLAY_REF works' '\n \tgit config --unset-all core.notesRef &&\n \tgit config --unset-all notes.displayRef &&\n \tGIT_NOTES_DISPLAY_REF=refs/notes/commits:refs/notes/other \\\n-\t\tgit log -2 > output &&\n+\t\tgit log -2 >output &&\n \ttest_cmp expect-both output\n '\n \n-cat > expect-none << EOF\n+cat >expect-none <<EOF\n commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:18:13 2005 -0700\n@@ -720,16 +718,16 @@ EOF\n \n test_expect_success 'GIT_NOTES_DISPLAY_REF overrides config' '\n \tgit config notes.displayRef \"refs/notes/*\" &&\n-\tGIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log -2 > output &&\n+\tGIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log -2 >output &&\n \ttest_cmp expect-none output\n '\n \n test_expect_success '--show-notes=* adds to GIT_NOTES_DISPLAY_REF' '\n-\tGIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log --show-notes=* -2 > output &&\n+\tGIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log --show-notes=* -2 >output &&\n \ttest_cmp expect-both output\n '\n \n-cat > expect-commits << EOF\n+cat >expect-commits <<EOF\n commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:18:13 2005 -0700\n@@ -741,41 +739,41 @@ Notes:\n EOF\n \n test_expect_success '--no-standard-notes' '\n-\tgit log --no-standard-notes --show-notes=commits -1 > output &&\n+\tgit log --no-standard-notes --show-notes=commits -1 >output &&\n \ttest_cmp expect-commits output\n '\n \n test_expect_success '--standard-notes' '\n \tgit log --no-standard-notes --show-notes=commits \\\n-\t\t--standard-notes -2 > output &&\n+\t\t--standard-notes -2 >output &&\n \ttest_cmp expect-both output\n '\n \n test_expect_success '--show-notes=ref accumulates' '\n \tgit log --show-notes=other --show-notes=commits \\\n-\t\t --no-standard-notes -1 > output &&\n+\t\t --no-standard-notes -1 >output &&\n \ttest_cmp expect-both-reversed output\n '\n \n test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '\n \tgit config core.notesRef refs/notes/other &&\n-\techo \"Note on a tree\" > expect &&\n+\techo \"Note on a tree\" >expect &&\n \tgit notes add -m \"Note on a tree\" HEAD: &&\n-\tgit notes show HEAD: > actual &&\n+\tgit notes show HEAD: >actual &&\n \ttest_cmp expect actual &&\n-\techo \"Note on a blob\" > expect &&\n+\techo \"Note on a blob\" >expect &&\n \tfilename=$(git ls-tree --name-only HEAD | head -n1) &&\n \tgit notes add -m \"Note on a blob\" HEAD:$filename &&\n-\tgit notes show HEAD:$filename > actual &&\n+\tgit notes show HEAD:$filename >actual &&\n \ttest_cmp expect actual &&\n-\techo \"Note on a tag\" > expect &&\n+\techo \"Note on a tag\" >expect &&\n \tgit tag -a -m \"This is an annotated tag\" foobar HEAD^ &&\n \tgit notes add -m \"Note on a tag\" foobar &&\n-\tgit notes show foobar > actual &&\n+\tgit notes show foobar >actual &&\n \ttest_cmp expect actual\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 2ede89468182a62d0bde2583c736089bcf7d7e92\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:19:13 2005 -0700\n@@ -787,18 +785,18 @@ Notes (other):\n EOF\n \n test_expect_success 'create note from other note with \"git notes add -C\"' '\n-\t: > a7 &&\n+\t: >a7 &&\n \tgit add a7 &&\n \ttest_tick &&\n \tgit commit -m 7th &&\n \tgit notes add -C $(git notes list HEAD^) &&\n-\tgit log -1 > actual &&\n+\tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n '\n \n test_expect_success 'create note from non-existing note with \"git notes add -C\" fails' '\n-\t: > a8 &&\n+\t: >a8 &&\n \tgit add a8 &&\n \ttest_tick &&\n \tgit commit -m 8th &&\n@@ -814,7 +812,7 @@ test_expect_success 'create note from non-blob with \"git notes add -C\" fails' '\n \ttest_must_fail git notes list HEAD\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 80d796defacd5db327b7a4e50099663902fbdc5c\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:20:13 2005 -0700\n@@ -828,12 +826,12 @@ EOF\n test_expect_success 'create note from blob with \"git notes add -C\" reuses blob id' '\n \tblob=$(echo \"This is a blob object\" | git hash-object -w --stdin) &&\n \tgit notes add -C $blob &&\n-\tgit log -1 > actual &&\n+\tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n \ttest \"$(git notes list HEAD)\" = \"$blob\"\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:21:13 2005 -0700\n@@ -845,17 +843,17 @@ Notes (other):\n EOF\n \n test_expect_success 'create note from other note with \"git notes add -c\"' '\n-\t: > a9 &&\n+\t: >a9 &&\n \tgit add a9 &&\n \ttest_tick &&\n \tgit commit -m 9th &&\n \tMSG=\"yet another note\" git notes add -c $(git notes list HEAD^^) &&\n-\tgit log -1 > actual &&\n+\tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'create note from non-existing note with \"git notes add -c\" fails' '\n-\t: > a10 &&\n+\t: >a10 &&\n \tgit add a10 &&\n \ttest_tick &&\n \tgit commit -m 10th &&\n@@ -863,7 +861,7 @@ test_expect_success 'create note from non-existing note with \"git notes add -c\"\n \ttest_must_fail git notes list HEAD\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:21:13 2005 -0700\n@@ -878,11 +876,11 @@ EOF\n \n test_expect_success 'append to note from other note with \"git notes append -C\"' '\n \tgit notes append -C $(git notes list HEAD^) HEAD^ &&\n-\tgit log -1 HEAD^ > actual &&\n+\tgit log -1 HEAD^ >actual &&\n \ttest_cmp expect actual\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit ffed603236bfa3891c49644257a83598afe8ae5a\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:22:13 2005 -0700\n@@ -895,11 +893,11 @@ EOF\n \n test_expect_success 'create note from other note with \"git notes append -c\"' '\n \tMSG=\"other note\" git notes append -c $(git notes list HEAD^) &&\n-\tgit log -1 > actual &&\n+\tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit ffed603236bfa3891c49644257a83598afe8ae5a\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:22:13 2005 -0700\n@@ -914,11 +912,11 @@ EOF\n \n test_expect_success 'append to note from other note with \"git notes append -c\"' '\n \tMSG=\"yet another note\" git notes append -c $(git notes list HEAD) &&\n-\tgit log -1 > actual &&\n+\tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:23:13 2005 -0700\n@@ -932,24 +930,24 @@ $whitespace\n EOF\n \n test_expect_success 'copy note with \"git notes copy\"' '\n-\t: > a11 &&\n+\t: >a11 &&\n \tgit add a11 &&\n \ttest_tick &&\n \tgit commit -m 11th &&\n \tgit notes copy HEAD^ HEAD &&\n-\tgit log -1 > actual &&\n+\tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n '\n \n test_expect_success 'prevent overwrite with \"git notes copy\"' '\n \ttest_must_fail git notes copy HEAD~2 HEAD &&\n-\tgit log -1 > actual &&\n+\tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:23:13 2005 -0700\n@@ -964,24 +962,24 @@ EOF\n \n test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n \tgit notes copy -f HEAD~2 HEAD &&\n-\tgit log -1 > actual &&\n+\tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\"\n '\n \n test_expect_success 'cannot copy note from object without notes' '\n-\t: > a12 &&\n+\t: >a12 &&\n \tgit add a12 &&\n \ttest_tick &&\n \tgit commit -m 12th &&\n-\t: > a13 &&\n+\t: >a13 &&\n \tgit add a13 &&\n \ttest_tick &&\n \tgit commit -m 13th &&\n \ttest_must_fail git notes copy HEAD^ HEAD\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit e5d4fb5698d564ab8c73551538ecaf2b0c666185\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:25:13 2005 -0700\n@@ -1009,13 +1007,13 @@ test_expect_success 'git notes copy --stdin' '\n \t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \\\n \techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n \tgit notes copy --stdin &&\n-\tgit log -2 > output &&\n+\tgit log -2 >output &&\n \ttest_cmp expect output &&\n \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\" &&\n \ttest \"$(git notes list HEAD^)\" = \"$(git notes list HEAD~3)\"\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:27:13 2005 -0700\n@@ -1035,11 +1033,11 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n \t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \\\n \techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n \tgit notes copy --for-rewrite=foo &&\n-\tgit log -2 > output &&\n+\tgit log -2 >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:27:13 2005 -0700\n@@ -1069,7 +1067,7 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' '\n \t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \\\n \techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n \tgit notes copy --for-rewrite=foo &&\n-\tgit log -2 > output &&\n+\tgit log -2 >output &&\n \ttest_cmp expect output\n '\n \n@@ -1077,11 +1075,11 @@ test_expect_success 'git notes copy --for-rewrite (disabled)' '\n \tgit config notes.rewrite.bar false &&\n \techo $(git rev-parse HEAD~3) $(git rev-parse HEAD) |\n \tgit notes copy --for-rewrite=bar &&\n-\tgit log -2 > output &&\n+\tgit log -2 >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:27:13 2005 -0700\n@@ -1096,7 +1094,7 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n \tgit notes add -f -m\"a fresh note\" HEAD^ &&\n \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n \tgit notes copy --for-rewrite=foo &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect output\n '\n \n@@ -1104,11 +1102,11 @@ test_expect_success 'git notes copy --for-rewrite (ignore)' '\n \tgit config notes.rewriteMode ignore &&\n \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n \tgit notes copy --for-rewrite=foo &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:27:13 2005 -0700\n@@ -1126,11 +1124,11 @@ test_expect_success 'git notes copy --for-rewrite (append)' '\n \tgit config notes.rewriteMode concatenate &&\n \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n \tgit notes copy --for-rewrite=foo &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:27:13 2005 -0700\n@@ -1153,7 +1151,7 @@ test_expect_success 'git notes copy --for-rewrite (append two to one)' '\n \t(echo $(git rev-parse HEAD^) $(git rev-parse HEAD);\n \techo $(git rev-parse HEAD^^) $(git rev-parse HEAD)) |\n \tgit notes copy --for-rewrite=foo &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect output\n '\n \n@@ -1161,11 +1159,11 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' '\n \tgit notes remove HEAD^ &&\n \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n \tgit notes copy --for-rewrite=foo &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:27:13 2005 -0700\n@@ -1180,11 +1178,11 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' '\n \tgit notes add -f -m\"replacement note 1\" HEAD^ &&\n \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n \tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n Author: A U Thor <author@example.com>\n Date:   Thu Apr 7 15:27:13 2005 -0700\n@@ -1202,7 +1200,7 @@ test_expect_success 'GIT_NOTES_REWRITE_REF works' '\n \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits:refs/notes/other \\\n \t\tgit notes copy --for-rewrite=foo &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect output\n '\n \n@@ -1211,7 +1209,7 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' '\n \tgit notes add -f -m\"replacement note 3\" HEAD^ &&\n \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n \tGIT_NOTES_REWRITE_REF= git notes copy --for-rewrite=foo &&\n-\tgit log -1 > output &&\n+\tgit log -1 >output &&\n \ttest_cmp expect output\n '\n \n-- \n2.0.0.rc4.501.gdaf83ca\n"},{"id":"251463","messageId":"xmqq61eqhpgv.fsf@gitster.dls.corp.google.com","threadId":"37892","inReplyTo":"1415351961-31567-3-git-send-email-johan@herland.net","subject":"Re: [PATCHv3 2/5] t3301: Verify that 'git notes' removes empty notes by default","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-11-07T17:48:00Z","receivedAt":"2014-11-07T17:48:00Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> Add test cases documenting the current behavior when trying to\n> add/append/edit empty notes. This is in preparation for adding\n> --allow-empty; to allow empty notes to be stored.\n>\n> Improved-by: Eric Sunshine <sunshine@sunshineco.com>\n> Improved-by: Junio C Hamano <gitster@pobox.com>\n> Signed-off-by: Johan Herland <johan@herland.net>\n> ---\n>  t/t3301-notes.sh | 27 +++++++++++++++++++++++++++\n>  1 file changed, 27 insertions(+)\n>\n> diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\n> index cfd67ff..33f0558 100755\n> --- a/t/t3301-notes.sh\n> +++ b/t/t3301-notes.sh\n> @@ -1239,4 +1239,31 @@ test_expect_success 'git notes get-ref (--ref)' '\n>  \ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref)\" = \"refs/notes/baz\"\n>  '\n>  \n> +test_expect_success 'setup testing of empty notes' '\n> +\tgit config --unset core.notesRef &&\n\nUse \"test_unconfig\" instead?\n\nIf the previous test failed (or a different topic that touches this\nsame script is merged to change what the previous test leaves), this\nconfiguration variable may not be set, and \"config --unset\" may\nfail.\n\n> +\ttest_commit 16th &&\n> +\tempty_blob=$(git hash-object -w /dev/null)\n> +'\n> +\n> +while read cmd\n> +do\n> +\ttest_expect_success \"'git notes $cmd' removes empty note\" \"\n> +\t\ttest_might_fail git notes remove HEAD &&\n> +\t\tMSG= git notes $cmd &&\n> +\t\ttest_must_fail git notes list HEAD\n> +\t\"\n> +done <<\\EOF\n> +add\n> +add -F /dev/null\n> +add -m \"\"\n> +add -c \"$empty_blob\"\n> +add -C \"$empty_blob\"\n> +append\n> +append -F /dev/null\n> +append -m \"\"\n> +append -c \"$empty_blob\"\n> +append -C \"$empty_blob\"\n> +edit\n> +EOF\n> +\n>  test_done\n"},{"id":"251464","messageId":"xmqq1tpehopp.fsf@gitster.dls.corp.google.com","threadId":"37892","inReplyTo":"1415351961-31567-4-git-send-email-johan@herland.net","subject":"Re: [PATCHv3 3/5] builtin/notes: Add --allow-empty, to allow storing empty notes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-11-07T18:04:18Z","receivedAt":"2014-11-07T18:04:18Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> Although the \"git notes\" man page advertises that we support binary-safe\n> notes addition (using the -C option), we currently do not support adding\n> the empty note (i.e. using the empty blob to annotate an object). Instead,\n> an empty note is always treated as an intent to remove the note\n> altogether.\n>\n> Introduce the --allow-empty option to the add/append/edit subcommands,\n> to explicitly allow an empty note to be stored into the notes tree.\n>\n> Also update the documentation, and add test cases for the new option.\n>\n> Reported-by: James H. Fisher <jhf@trifork.com>\n> Improved-by: Kyle J. McKay <mackyle@gmail.com>\n> Improved-by: Junio C Hamano <gitster@pobox.com>\n> Signed-off-by: Johan Herland <johan@herland.net>\n> ---\n\nAssuming that it is a good idea to \"allow\" empty notes, I think\nthere are two issues involved here:\n\n * Traditionally, feeding an empty note is taken as a request to\n   remove an existing note.  Therefore, there is no way to\n   explicitly ask an empty note to be stored for a commit.\n\n * Because feeding an empty note was the way to request removal,\n   even though \"git notes remove\" is there, it is underused.\n\nIn other words, assuming that it is a good idea to allow empty\nnotes, isn't the desired endgame, after compatibility transition\nperiod, that \"git notes add\" will never remove notes?\n\nWith that endgame in mind, shouldn't the internal implementation be\nmoving in a direction where \"create_note()\" will *not* be doing any\nremoval, and its caller (i.e. \"add\") does the switching depending on\nthe \"do we take emptyness as a request to remove\"?  I.e.\n\n         static int add(...)\n         {\n\t\tif (!allow_empty && message_is_empty())\n                \tremove_note();\n\t\telse\n                \tcreate_note();\n\t}\n\n>  static void create_note(const unsigned char *object, struct msg_arg *msg,\n> -\t\t\tint append_only, const unsigned char *prev,\n> -\t\t\tunsigned char *result)\n> +\t\t\tint append_only, int allow_empty,\n> +\t\t\tconst unsigned char *prev, unsigned char *result)\n\nIn other words, I have this suspicion that create_note() that \nremoves is a wrong interface in the first place, and giving it\na new allow_empty parameter to conditionally perform removal is\nmaking it worse.  No?\n"},{"id":"251472","messageId":"xmqqr3xeg7yw.fsf@gitster.dls.corp.google.com","threadId":"37892","inReplyTo":"1415351961-31567-5-git-send-email-johan@herland.net","subject":"Re: [PATCHv3 4/5] notes: Empty notes should be shown by 'git log'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-11-07T18:51:19Z","receivedAt":"2014-11-07T18:51:19Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> If the user has gone through the trouble of explicitly adding an empty\n> note, then \"git log\" should not silently skip it (as if it didn't exist).\n>\n> Signed-off-by: Johan Herland <johan@herland.net>\n> ---\n\nThis makes sense and is in line with the theme of this series.\n\n>  notes.c          |  3 +--\n>  t/t3301-notes.sh | 12 ++++++++++++\n>  2 files changed, 13 insertions(+), 2 deletions(-)\n>\n> diff --git a/notes.c b/notes.c\n> index 5fe691d..62bc6e1 100644\n> --- a/notes.c\n> +++ b/notes.c\n> @@ -1218,8 +1218,7 @@ static void format_note(struct notes_tree *t, const unsigned char *object_sha1,\n>  \tif (!sha1)\n>  \t\treturn;\n>  \n> -\tif (!(msg = read_sha1_file(sha1, &type, &msglen)) || !msglen ||\n> -\t\t\ttype != OBJ_BLOB) {\n> +\tif (!(msg = read_sha1_file(sha1, &type, &msglen)) || type != OBJ_BLOB) {\n>  \t\tfree(msg);\n>  \t\treturn;\n>  \t}\n> diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\n> index 8280a1a..f5d8193 100755\n> --- a/t/t3301-notes.sh\n> +++ b/t/t3301-notes.sh\n> @@ -1274,4 +1274,16 @@ append -C \"$empty_blob\"\n>  edit\n>  EOF\n>  \n> +test_expect_success 'empty notes are displayed by git log' '\n> +\ttest_commit 17th &&\n> +\tgit log -1 >expect &&\n> +\tcat >>expect <<\\EOF &&\n> +\n> +Notes:\n> +EOF\n> +\tgit notes add -C \"$empty_blob\" --allow-empty &&\n> +\tgit log -1 >actual &&\n> +\ttest_cmp expect actual\n> +'\n> +\n>  test_done\n"},{"id":"251473","messageId":"xmqqmw82g7rj.fsf@gitster.dls.corp.google.com","threadId":"37892","inReplyTo":"1415351961-31567-6-git-send-email-johan@herland.net","subject":"Re: [PATCHv3 5/5] t3301: Use write_script(), nitpick whitespace","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-11-07T18:55:44Z","receivedAt":"2014-11-07T18:55:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> Signed-off-by: Johan Herland <johan@herland.net>\n> ---\n>\n> Drop this if it's too much churn.\n\nThis is an overdue clean-up and because nobody else is working in\nthe area, it is good to do so either as a preliminary clean-up or as\na after-the-dust-settles clean-up for this series.\n\nThese whitespace issues are not the only ones in this script that\nneed modernizing, though.  Preparation of \"expect\" outside tests\nmakes this script look quite old fashioned, for example.\n\n> ...Johan\n>\n>  t/t3301-notes.sh | 254 +++++++++++++++++++++++++++----------------------------\n>  1 file changed, 126 insertions(+), 128 deletions(-)\n>\n> diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\n> index f5d8193..80caee0 100755\n> --- a/t/t3301-notes.sh\n> +++ b/t/t3301-notes.sh\n> @@ -7,13 +7,11 @@ test_description='Test commit notes'\n>  \n>  . ./test-lib.sh\n>  \n> -cat > fake_editor.sh << \\EOF\n> -#!/bin/sh\n> -echo \"$MSG\" > \"$1\"\n> -echo \"$MSG\" >& 2\n> +write_script fake_editor <<\\EOF\n> +echo \"$MSG\" >\"$1\"\n> +echo \"$MSG\" >&2\n>  EOF\n> -chmod a+x fake_editor.sh\n> -GIT_EDITOR=./fake_editor.sh\n> +GIT_EDITOR=./fake_editor\n>  export GIT_EDITOR\n>  \n>  test_expect_success 'cannot annotate non-existing HEAD' '\n> @@ -21,11 +19,11 @@ test_expect_success 'cannot annotate non-existing HEAD' '\n>  '\n>  \n>  test_expect_success setup '\n> -\t: > a1 &&\n> +\t: >a1 &&\n>  \tgit add a1 &&\n>  \ttest_tick &&\n>  \tgit commit -m 1st &&\n> -\t: > a2 &&\n> +\t: >a2 &&\n>  \tgit add a2 &&\n>  \ttest_tick &&\n>  \tgit commit -m 2nd\n> @@ -131,7 +129,7 @@ test_expect_success 'can overwrite existing note with \"git notes add -f\"' '\n>  \ttest_must_fail git notes show HEAD^\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 268048bfb8a1fb38e703baceb8ab235421bf80c5\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:14:13 2005 -0700\n> @@ -144,12 +142,12 @@ EOF\n>  \n>  test_expect_success 'show notes' '\n>  \t! (git cat-file commit HEAD | grep b1) &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n>  test_expect_success 'create multi-line notes (setup)' '\n> -\t: > a3 &&\n> +\t: >a3 &&\n>  \tgit add a3 &&\n>  \ttest_tick &&\n>  \tgit commit -m 3rd &&\n> @@ -158,7 +156,7 @@ c3c3c3c3\n>  d3d3d3\" git notes add\n>  '\n>  \n> -cat > expect-multiline << EOF\n> +cat >expect-multiline <<EOF\n>  commit 1584215f1d29c65e99c6c6848626553fdd07fd75\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:15:13 2005 -0700\n> @@ -171,23 +169,23 @@ Notes:\n>      d3d3d3\n>  EOF\n>  \n> -printf \"\\n\" >> expect-multiline\n> -cat expect >> expect-multiline\n> +printf \"\\n\" >>expect-multiline\n> +cat expect >>expect-multiline\n>  \n>  test_expect_success 'show multi-line notes' '\n> -\tgit log -2 > output &&\n> +\tgit log -2 >output &&\n>  \ttest_cmp expect-multiline output\n>  '\n>  test_expect_success 'create -F notes (setup)' '\n> -\t: > a4 &&\n> +\t: >a4 &&\n>  \tgit add a4 &&\n>  \ttest_tick &&\n>  \tgit commit -m 4th &&\n> -\techo \"xyzzy\" > note5 &&\n> +\techo \"xyzzy\" >note5 &&\n>  \tgit notes add -F note5\n>  '\n>  \n> -cat > expect-F << EOF\n> +cat >expect-F <<EOF\n>  commit 15023535574ded8b1a89052b32673f84cf9582b8\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:16:13 2005 -0700\n> @@ -198,22 +196,22 @@ Notes:\n>      xyzzy\n>  EOF\n>  \n> -printf \"\\n\" >> expect-F\n> -cat expect-multiline >> expect-F\n> +printf \"\\n\" >>expect-F\n> +cat expect-multiline >>expect-F\n>  \n>  test_expect_success 'show -F notes' '\n> -\tgit log -3 > output &&\n> +\tgit log -3 >output &&\n>  \ttest_cmp expect-F output\n>  '\n>  \n>  test_expect_success 'Re-adding -F notes without -f fails' '\n> -\techo \"zyxxy\" > note5 &&\n> +\techo \"zyxxy\" >note5 &&\n>  \ttest_must_fail git notes add -F note5 &&\n> -\tgit log -3 > output &&\n> +\tgit log -3 >output &&\n>  \ttest_cmp expect-F output\n>  '\n>  \n> -cat >expect << EOF\n> +cat >expect <<EOF\n>  commit 15023535574ded8b1a89052b32673f84cf9582b8\n>  tree e070e3af51011e47b183c33adf9736736a525709\n>  parent 1584215f1d29c65e99c6c6848626553fdd07fd75\n> @@ -305,7 +303,7 @@ test_expect_success 'git log --no-notes resets ref list' '\n>  '\n>  \n>  test_expect_success 'create -m notes (setup)' '\n> -\t: > a5 &&\n> +\t: >a5 &&\n>  \tgit add a5 &&\n>  \ttest_tick &&\n>  \tgit commit -m 5th &&\n> @@ -315,7 +313,7 @@ baz\"\n>  '\n>  \n>  whitespace=\"    \"\n> -cat > expect-m << EOF\n> +cat >expect-m <<EOF\n>  commit bd1753200303d0a0344be813e504253b3d98e74d\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:17:13 2005 -0700\n> @@ -330,11 +328,11 @@ $whitespace\n>      baz\n>  EOF\n>  \n> -printf \"\\n\" >> expect-m\n> -cat expect-F >> expect-m\n> +printf \"\\n\" >>expect-m\n> +cat expect-F >>expect-m\n>  \n>  test_expect_success 'show -m notes' '\n> -\tgit log -4 > output &&\n> +\tgit log -4 >output &&\n>  \ttest_cmp expect-m output\n>  '\n>  \n> @@ -342,7 +340,7 @@ test_expect_success 'remove note with add -f -F /dev/null (setup)' '\n>  \tgit notes add -f -F /dev/null\n>  '\n>  \n> -cat > expect-rm-F << EOF\n> +cat >expect-rm-F <<EOF\n>  commit bd1753200303d0a0344be813e504253b3d98e74d\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:17:13 2005 -0700\n> @@ -350,11 +348,11 @@ Date:   Thu Apr 7 15:17:13 2005 -0700\n>      5th\n>  EOF\n>  \n> -printf \"\\n\" >> expect-rm-F\n> -cat expect-F >> expect-rm-F\n> +printf \"\\n\" >>expect-rm-F\n> +cat expect-F >>expect-rm-F\n>  \n>  test_expect_success 'verify note removal with -F /dev/null' '\n> -\tgit log -4 > output &&\n> +\tgit log -4 >output &&\n>  \ttest_cmp expect-rm-F output &&\n>  \ttest_must_fail git notes show\n>  '\n> @@ -364,12 +362,12 @@ test_expect_success 'do not create empty note with -m \"\" (setup)' '\n>  '\n>  \n>  test_expect_success 'verify non-creation of note with -m \"\"' '\n> -\tgit log -4 > output &&\n> +\tgit log -4 >output &&\n>  \ttest_cmp expect-rm-F output &&\n>  \ttest_must_fail git notes show\n>  '\n>  \n> -cat > expect-combine_m_and_F << EOF\n> +cat >expect-combine_m_and_F <<EOF\n>  foo\n>  \n>  xyzzy\n> @@ -382,10 +380,10 @@ baz\n>  EOF\n>  \n>  test_expect_success 'create note with combination of -m and -F' '\n> -\techo \"xyzzy\" > note_a &&\n> -\techo \"zyxxy\" > note_b &&\n> +\techo \"xyzzy\" >note_a &&\n> +\techo \"zyxxy\" >note_b &&\n>  \tgit notes add -m \"foo\" -F note_a -m \"bar\" -F note_b -m \"baz\" &&\n> -\tgit notes show > output &&\n> +\tgit notes show >output &&\n>  \ttest_cmp expect-combine_m_and_F output\n>  '\n>  \n> @@ -394,7 +392,7 @@ test_expect_success 'remove note with \"git notes remove\" (setup)' '\n>  \tgit notes remove\n>  '\n>  \n> -cat > expect-rm-remove << EOF\n> +cat >expect-rm-remove <<EOF\n>  commit bd1753200303d0a0344be813e504253b3d98e74d\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:17:13 2005 -0700\n> @@ -408,24 +406,24 @@ Date:   Thu Apr 7 15:16:13 2005 -0700\n>      4th\n>  EOF\n>  \n> -printf \"\\n\" >> expect-rm-remove\n> -cat expect-multiline >> expect-rm-remove\n> +printf \"\\n\" >>expect-rm-remove\n> +cat expect-multiline >>expect-rm-remove\n>  \n>  test_expect_success 'verify note removal with \"git notes remove\"' '\n> -\tgit log -4 > output &&\n> +\tgit log -4 >output &&\n>  \ttest_cmp expect-rm-remove output &&\n>  \ttest_must_fail git notes show HEAD^\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd75\n>  c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5\n>  EOF\n>  \n>  test_expect_success 'removing non-existing note should not create new commit' '\n> -\tgit rev-parse --verify refs/notes/commits > before_commit &&\n> +\tgit rev-parse --verify refs/notes/commits >before_commit &&\n>  \ttest_must_fail git notes remove HEAD^ &&\n> -\tgit rev-parse --verify refs/notes/commits > after_commit &&\n> +\tgit rev-parse --verify refs/notes/commits >after_commit &&\n>  \ttest_cmp before_commit after_commit\n>  '\n>  \n> @@ -505,33 +503,33 @@ test_expect_success 'removing with --stdin --ignore-missing' '\n>  '\n>  \n>  test_expect_success 'list notes with \"git notes list\"' '\n> -\tgit notes list > output &&\n> +\tgit notes list >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n>  test_expect_success 'list notes with \"git notes\"' '\n> -\tgit notes > output &&\n> +\tgit notes >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  c18dc024e14f08d18d14eea0d747ff692d66d6a3\n>  EOF\n>  \n>  test_expect_success 'list specific note with \"git notes list <object>\"' '\n> -\tgit notes list HEAD^^ > output &&\n> +\tgit notes list HEAD^^ >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  EOF\n>  \n>  test_expect_success 'listing non-existing notes fails' '\n> -\ttest_must_fail git notes list HEAD > output &&\n> +\ttest_must_fail git notes list HEAD >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  Initial set of notes\n>  \n>  More notes appended with git notes append\n> @@ -540,24 +538,24 @@ EOF\n>  test_expect_success 'append to existing note with \"git notes append\"' '\n>  \tgit notes add -m \"Initial set of notes\" &&\n>  \tgit notes append -m \"More notes appended with git notes append\" &&\n> -\tgit notes show > output &&\n> +\tgit notes show >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect_list << EOF\n> +cat >expect_list <<EOF\n>  c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd75\n>  c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5\n>  4b6ad22357cc8a1296720574b8d2fbc22fab0671 bd1753200303d0a0344be813e504253b3d98e74d\n>  EOF\n>  \n>  test_expect_success '\"git notes list\" does not expand to \"git notes list HEAD\"' '\n> -\tgit notes list > output &&\n> +\tgit notes list >output &&\n>  \ttest_cmp expect_list output\n>  '\n>  \n>  test_expect_success 'appending empty string does not change existing note' '\n>  \tgit notes append -m \"\" &&\n> -\tgit notes show > output &&\n> +\tgit notes show >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> @@ -567,7 +565,7 @@ test_expect_success 'git notes append == add when there is no existing note' '\n>  \tgit notes append -m \"Initial set of notes\n>  \n>  More notes appended with git notes append\" &&\n> -\tgit notes show > output &&\n> +\tgit notes show >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> @@ -579,14 +577,14 @@ test_expect_success 'appending empty string to non-existing note does not create\n>  '\n>  \n>  test_expect_success 'create other note on a different notes ref (setup)' '\n> -\t: > a6 &&\n> +\t: >a6 &&\n>  \tgit add a6 &&\n>  \ttest_tick &&\n>  \tgit commit -m 6th &&\n>  \tGIT_NOTES_REF=\"refs/notes/other\" git notes add -m \"other note\"\n>  '\n>  \n> -cat > expect-other << EOF\n> +cat >expect-other <<EOF\n>  commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:18:13 2005 -0700\n> @@ -597,7 +595,7 @@ Notes (other):\n>      other note\n>  EOF\n>  \n> -cat > expect-not-other << EOF\n> +cat >expect-not-other <<EOF\n>  commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:18:13 2005 -0700\n> @@ -606,27 +604,27 @@ Date:   Thu Apr 7 15:18:13 2005 -0700\n>  EOF\n>  \n>  test_expect_success 'Do not show note on other ref by default' '\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect-not-other output\n>  '\n>  \n>  test_expect_success 'Do show note when ref is given in GIT_NOTES_REF' '\n> -\tGIT_NOTES_REF=\"refs/notes/other\" git log -1 > output &&\n> +\tGIT_NOTES_REF=\"refs/notes/other\" git log -1 >output &&\n>  \ttest_cmp expect-other output\n>  '\n>  \n>  test_expect_success 'Do show note when ref is given in core.notesRef config' '\n>  \tgit config core.notesRef \"refs/notes/other\" &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect-other output\n>  '\n>  \n>  test_expect_success 'Do not show note when core.notesRef is overridden' '\n> -\tGIT_NOTES_REF=\"refs/notes/wrong\" git log -1 > output &&\n> +\tGIT_NOTES_REF=\"refs/notes/wrong\" git log -1 >output &&\n>  \ttest_cmp expect-not-other output\n>  '\n>  \n> -cat > expect-both << EOF\n> +cat >expect-both <<EOF\n>  commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:18:13 2005 -0700\n> @@ -655,14 +653,14 @@ test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' '\n>  \tGIT_NOTES_REF=refs/notes/commits git notes add -m\"order test\" &&\n>  \tgit config --unset core.notesRef &&\n>  \tgit config notes.displayRef \"refs/notes/*\" &&\n> -\tgit log -2 > output &&\n> +\tgit log -2 >output &&\n>  \ttest_cmp expect-both output\n>  '\n>  \n>  test_expect_success 'core.notesRef is implicitly in notes.displayRef' '\n>  \tgit config core.notesRef refs/notes/commits &&\n>  \tgit config notes.displayRef refs/notes/other &&\n> -\tgit log -2 > output &&\n> +\tgit log -2 >output &&\n>  \ttest_cmp expect-both output\n>  '\n>  \n> @@ -670,11 +668,11 @@ test_expect_success 'notes.displayRef can be given more than once' '\n>  \tgit config --unset core.notesRef &&\n>  \tgit config notes.displayRef refs/notes/commits &&\n>  \tgit config --add notes.displayRef refs/notes/other &&\n> -\tgit log -2 > output &&\n> +\tgit log -2 >output &&\n>  \ttest_cmp expect-both output\n>  '\n>  \n> -cat > expect-both-reversed << EOF\n> +cat >expect-both-reversed <<EOF\n>  commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:18:13 2005 -0700\n> @@ -692,7 +690,7 @@ test_expect_success 'notes.displayRef respects order' '\n>  \tgit config core.notesRef refs/notes/other &&\n>  \tgit config --unset-all notes.displayRef &&\n>  \tgit config notes.displayRef refs/notes/commits &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect-both-reversed output\n>  '\n>  \n> @@ -700,11 +698,11 @@ test_expect_success 'GIT_NOTES_DISPLAY_REF works' '\n>  \tgit config --unset-all core.notesRef &&\n>  \tgit config --unset-all notes.displayRef &&\n>  \tGIT_NOTES_DISPLAY_REF=refs/notes/commits:refs/notes/other \\\n> -\t\tgit log -2 > output &&\n> +\t\tgit log -2 >output &&\n>  \ttest_cmp expect-both output\n>  '\n>  \n> -cat > expect-none << EOF\n> +cat >expect-none <<EOF\n>  commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:18:13 2005 -0700\n> @@ -720,16 +718,16 @@ EOF\n>  \n>  test_expect_success 'GIT_NOTES_DISPLAY_REF overrides config' '\n>  \tgit config notes.displayRef \"refs/notes/*\" &&\n> -\tGIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log -2 > output &&\n> +\tGIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log -2 >output &&\n>  \ttest_cmp expect-none output\n>  '\n>  \n>  test_expect_success '--show-notes=* adds to GIT_NOTES_DISPLAY_REF' '\n> -\tGIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log --show-notes=* -2 > output &&\n> +\tGIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log --show-notes=* -2 >output &&\n>  \ttest_cmp expect-both output\n>  '\n>  \n> -cat > expect-commits << EOF\n> +cat >expect-commits <<EOF\n>  commit 387a89921c73d7ed72cd94d179c1c7048ca47756\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:18:13 2005 -0700\n> @@ -741,41 +739,41 @@ Notes:\n>  EOF\n>  \n>  test_expect_success '--no-standard-notes' '\n> -\tgit log --no-standard-notes --show-notes=commits -1 > output &&\n> +\tgit log --no-standard-notes --show-notes=commits -1 >output &&\n>  \ttest_cmp expect-commits output\n>  '\n>  \n>  test_expect_success '--standard-notes' '\n>  \tgit log --no-standard-notes --show-notes=commits \\\n> -\t\t--standard-notes -2 > output &&\n> +\t\t--standard-notes -2 >output &&\n>  \ttest_cmp expect-both output\n>  '\n>  \n>  test_expect_success '--show-notes=ref accumulates' '\n>  \tgit log --show-notes=other --show-notes=commits \\\n> -\t\t --no-standard-notes -1 > output &&\n> +\t\t --no-standard-notes -1 >output &&\n>  \ttest_cmp expect-both-reversed output\n>  '\n>  \n>  test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '\n>  \tgit config core.notesRef refs/notes/other &&\n> -\techo \"Note on a tree\" > expect &&\n> +\techo \"Note on a tree\" >expect &&\n>  \tgit notes add -m \"Note on a tree\" HEAD: &&\n> -\tgit notes show HEAD: > actual &&\n> +\tgit notes show HEAD: >actual &&\n>  \ttest_cmp expect actual &&\n> -\techo \"Note on a blob\" > expect &&\n> +\techo \"Note on a blob\" >expect &&\n>  \tfilename=$(git ls-tree --name-only HEAD | head -n1) &&\n>  \tgit notes add -m \"Note on a blob\" HEAD:$filename &&\n> -\tgit notes show HEAD:$filename > actual &&\n> +\tgit notes show HEAD:$filename >actual &&\n>  \ttest_cmp expect actual &&\n> -\techo \"Note on a tag\" > expect &&\n> +\techo \"Note on a tag\" >expect &&\n>  \tgit tag -a -m \"This is an annotated tag\" foobar HEAD^ &&\n>  \tgit notes add -m \"Note on a tag\" foobar &&\n> -\tgit notes show foobar > actual &&\n> +\tgit notes show foobar >actual &&\n>  \ttest_cmp expect actual\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 2ede89468182a62d0bde2583c736089bcf7d7e92\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:19:13 2005 -0700\n> @@ -787,18 +785,18 @@ Notes (other):\n>  EOF\n>  \n>  test_expect_success 'create note from other note with \"git notes add -C\"' '\n> -\t: > a7 &&\n> +\t: >a7 &&\n>  \tgit add a7 &&\n>  \ttest_tick &&\n>  \tgit commit -m 7th &&\n>  \tgit notes add -C $(git notes list HEAD^) &&\n> -\tgit log -1 > actual &&\n> +\tgit log -1 >actual &&\n>  \ttest_cmp expect actual &&\n>  \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n>  '\n>  \n>  test_expect_success 'create note from non-existing note with \"git notes add -C\" fails' '\n> -\t: > a8 &&\n> +\t: >a8 &&\n>  \tgit add a8 &&\n>  \ttest_tick &&\n>  \tgit commit -m 8th &&\n> @@ -814,7 +812,7 @@ test_expect_success 'create note from non-blob with \"git notes add -C\" fails' '\n>  \ttest_must_fail git notes list HEAD\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 80d796defacd5db327b7a4e50099663902fbdc5c\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:20:13 2005 -0700\n> @@ -828,12 +826,12 @@ EOF\n>  test_expect_success 'create note from blob with \"git notes add -C\" reuses blob id' '\n>  \tblob=$(echo \"This is a blob object\" | git hash-object -w --stdin) &&\n>  \tgit notes add -C $blob &&\n> -\tgit log -1 > actual &&\n> +\tgit log -1 >actual &&\n>  \ttest_cmp expect actual &&\n>  \ttest \"$(git notes list HEAD)\" = \"$blob\"\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:21:13 2005 -0700\n> @@ -845,17 +843,17 @@ Notes (other):\n>  EOF\n>  \n>  test_expect_success 'create note from other note with \"git notes add -c\"' '\n> -\t: > a9 &&\n> +\t: >a9 &&\n>  \tgit add a9 &&\n>  \ttest_tick &&\n>  \tgit commit -m 9th &&\n>  \tMSG=\"yet another note\" git notes add -c $(git notes list HEAD^^) &&\n> -\tgit log -1 > actual &&\n> +\tgit log -1 >actual &&\n>  \ttest_cmp expect actual\n>  '\n>  \n>  test_expect_success 'create note from non-existing note with \"git notes add -c\" fails' '\n> -\t: > a10 &&\n> +\t: >a10 &&\n>  \tgit add a10 &&\n>  \ttest_tick &&\n>  \tgit commit -m 10th &&\n> @@ -863,7 +861,7 @@ test_expect_success 'create note from non-existing note with \"git notes add -c\"\n>  \ttest_must_fail git notes list HEAD\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:21:13 2005 -0700\n> @@ -878,11 +876,11 @@ EOF\n>  \n>  test_expect_success 'append to note from other note with \"git notes append -C\"' '\n>  \tgit notes append -C $(git notes list HEAD^) HEAD^ &&\n> -\tgit log -1 HEAD^ > actual &&\n> +\tgit log -1 HEAD^ >actual &&\n>  \ttest_cmp expect actual\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit ffed603236bfa3891c49644257a83598afe8ae5a\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:22:13 2005 -0700\n> @@ -895,11 +893,11 @@ EOF\n>  \n>  test_expect_success 'create note from other note with \"git notes append -c\"' '\n>  \tMSG=\"other note\" git notes append -c $(git notes list HEAD^) &&\n> -\tgit log -1 > actual &&\n> +\tgit log -1 >actual &&\n>  \ttest_cmp expect actual\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit ffed603236bfa3891c49644257a83598afe8ae5a\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:22:13 2005 -0700\n> @@ -914,11 +912,11 @@ EOF\n>  \n>  test_expect_success 'append to note from other note with \"git notes append -c\"' '\n>  \tMSG=\"yet another note\" git notes append -c $(git notes list HEAD) &&\n> -\tgit log -1 > actual &&\n> +\tgit log -1 >actual &&\n>  \ttest_cmp expect actual\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:23:13 2005 -0700\n> @@ -932,24 +930,24 @@ $whitespace\n>  EOF\n>  \n>  test_expect_success 'copy note with \"git notes copy\"' '\n> -\t: > a11 &&\n> +\t: >a11 &&\n>  \tgit add a11 &&\n>  \ttest_tick &&\n>  \tgit commit -m 11th &&\n>  \tgit notes copy HEAD^ HEAD &&\n> -\tgit log -1 > actual &&\n> +\tgit log -1 >actual &&\n>  \ttest_cmp expect actual &&\n>  \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n>  '\n>  \n>  test_expect_success 'prevent overwrite with \"git notes copy\"' '\n>  \ttest_must_fail git notes copy HEAD~2 HEAD &&\n> -\tgit log -1 > actual &&\n> +\tgit log -1 >actual &&\n>  \ttest_cmp expect actual &&\n>  \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:23:13 2005 -0700\n> @@ -964,24 +962,24 @@ EOF\n>  \n>  test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n>  \tgit notes copy -f HEAD~2 HEAD &&\n> -\tgit log -1 > actual &&\n> +\tgit log -1 >actual &&\n>  \ttest_cmp expect actual &&\n>  \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\"\n>  '\n>  \n>  test_expect_success 'cannot copy note from object without notes' '\n> -\t: > a12 &&\n> +\t: >a12 &&\n>  \tgit add a12 &&\n>  \ttest_tick &&\n>  \tgit commit -m 12th &&\n> -\t: > a13 &&\n> +\t: >a13 &&\n>  \tgit add a13 &&\n>  \ttest_tick &&\n>  \tgit commit -m 13th &&\n>  \ttest_must_fail git notes copy HEAD^ HEAD\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit e5d4fb5698d564ab8c73551538ecaf2b0c666185\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:25:13 2005 -0700\n> @@ -1009,13 +1007,13 @@ test_expect_success 'git notes copy --stdin' '\n>  \t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \\\n>  \techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n>  \tgit notes copy --stdin &&\n> -\tgit log -2 > output &&\n> +\tgit log -2 >output &&\n>  \ttest_cmp expect output &&\n>  \ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\" &&\n>  \ttest \"$(git notes list HEAD^)\" = \"$(git notes list HEAD~3)\"\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:27:13 2005 -0700\n> @@ -1035,11 +1033,11 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n>  \t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \\\n>  \techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n>  \tgit notes copy --for-rewrite=foo &&\n> -\tgit log -2 > output &&\n> +\tgit log -2 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:27:13 2005 -0700\n> @@ -1069,7 +1067,7 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' '\n>  \t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \\\n>  \techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n>  \tgit notes copy --for-rewrite=foo &&\n> -\tgit log -2 > output &&\n> +\tgit log -2 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> @@ -1077,11 +1075,11 @@ test_expect_success 'git notes copy --for-rewrite (disabled)' '\n>  \tgit config notes.rewrite.bar false &&\n>  \techo $(git rev-parse HEAD~3) $(git rev-parse HEAD) |\n>  \tgit notes copy --for-rewrite=bar &&\n> -\tgit log -2 > output &&\n> +\tgit log -2 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:27:13 2005 -0700\n> @@ -1096,7 +1094,7 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n>  \tgit notes add -f -m\"a fresh note\" HEAD^ &&\n>  \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n>  \tgit notes copy --for-rewrite=foo &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> @@ -1104,11 +1102,11 @@ test_expect_success 'git notes copy --for-rewrite (ignore)' '\n>  \tgit config notes.rewriteMode ignore &&\n>  \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n>  \tgit notes copy --for-rewrite=foo &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:27:13 2005 -0700\n> @@ -1126,11 +1124,11 @@ test_expect_success 'git notes copy --for-rewrite (append)' '\n>  \tgit config notes.rewriteMode concatenate &&\n>  \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n>  \tgit notes copy --for-rewrite=foo &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:27:13 2005 -0700\n> @@ -1153,7 +1151,7 @@ test_expect_success 'git notes copy --for-rewrite (append two to one)' '\n>  \t(echo $(git rev-parse HEAD^) $(git rev-parse HEAD);\n>  \techo $(git rev-parse HEAD^^) $(git rev-parse HEAD)) |\n>  \tgit notes copy --for-rewrite=foo &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> @@ -1161,11 +1159,11 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' '\n>  \tgit notes remove HEAD^ &&\n>  \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n>  \tgit notes copy --for-rewrite=foo &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:27:13 2005 -0700\n> @@ -1180,11 +1178,11 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' '\n>  \tgit notes add -f -m\"replacement note 1\" HEAD^ &&\n>  \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n>  \tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> -cat > expect << EOF\n> +cat >expect <<EOF\n>  commit 37a0d4cba38afef96ba54a3ea567e6dac575700b\n>  Author: A U Thor <author@example.com>\n>  Date:   Thu Apr 7 15:27:13 2005 -0700\n> @@ -1202,7 +1200,7 @@ test_expect_success 'GIT_NOTES_REWRITE_REF works' '\n>  \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n>  \tGIT_NOTES_REWRITE_REF=refs/notes/commits:refs/notes/other \\\n>  \t\tgit notes copy --for-rewrite=foo &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> @@ -1211,7 +1209,7 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' '\n>  \tgit notes add -f -m\"replacement note 3\" HEAD^ &&\n>  \techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n>  \tGIT_NOTES_REWRITE_REF= git notes copy --for-rewrite=foo &&\n> -\tgit log -1 > output &&\n> +\tgit log -1 >output &&\n>  \ttest_cmp expect output\n>  '\n"},{"id":"251605","messageId":"CALKQrgdFDHUc8JzH3XnwvnHdEZOhUN=EmrWXKKDLd+6MG7jMKw@mail.gmail.com","threadId":"37892","inReplyTo":"xmqq1tpehopp.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCHv3 3/5] builtin/notes: Add --allow-empty, to allow storing empty notes","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-11-09T12:31:32Z","receivedAt":"2014-11-09T12:31:32Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Fri, Nov 7, 2014 at 7:04 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Johan Herland <johan@herland.net> writes:\n\n[...]\n\n> Assuming that it is a good idea to \"allow\" empty notes, I think\n> there are two issues involved here:\n>\n>  * Traditionally, feeding an empty note is taken as a request to\n>    remove an existing note.  Therefore, there is no way to\n>    explicitly ask an empty note to be stored for a commit.\n>\n>  * Because feeding an empty note was the way to request removal,\n>    even though \"git notes remove\" is there, it is underused.\n>\n> In other words, assuming that it is a good idea to allow empty\n> notes, isn't the desired endgame, after compatibility transition\n> period, that \"git notes add\" will never remove notes?\n>\n> With that endgame in mind, shouldn't the internal implementation be\n> moving in a direction where \"create_note()\" will *not* be doing any\n> removal, and its caller (i.e. \"add\") does the switching depending on\n> the \"do we take emptyness as a request to remove\"?  I.e.\n>\n>          static int add(...)\n>          {\n>                 if (!allow_empty && message_is_empty())\n>                         remove_note();\n>                 else\n>                         create_note();\n>         }\n>\n>>  static void create_note(const unsigned char *object, struct msg_arg *msg,\n>> -                     int append_only, const unsigned char *prev,\n>> -                     unsigned char *result)\n>> +                     int append_only, int allow_empty,\n>> +                     const unsigned char *prev, unsigned char *result)\n>\n> In other words, I have this suspicion that create_note() that\n> removes is a wrong interface in the first place, and giving it\n> a new allow_empty parameter to conditionally perform removal is\n> making it worse.  No?\n\nI agree, and it's fixed in the re-roll. It turned into a slightly\nlarger rewrite than anticipated, but I'm fairly happy with the result.\n\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"251689","messageId":"xmqqr3xa95dl.fsf@gitster.dls.corp.google.com","threadId":"37892","inReplyTo":"CALKQrgdFDHUc8JzH3XnwvnHdEZOhUN=EmrWXKKDLd+6MG7jMKw@mail.gmail.com","subject":"Re: [PATCHv3 3/5] builtin/notes: Add --allow-empty, to allow storing empty notes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-11-10T20:18:14Z","receivedAt":"2014-11-10T20:18:14Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> On Fri, Nov 7, 2014 at 7:04 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n>> In other words, I have this suspicion that create_note() that\n>> removes is a wrong interface in the first place, and giving it\n>> a new allow_empty parameter to conditionally perform removal is\n>> making it worse.  No?\n>\n> I agree, and it's fixed in the re-roll. It turned into a slightly\n> larger rewrite than anticipated, but I'm fairly happy with the result.\n\n;-)\n"}]}