{"thread":{"id":"32879","subject":"[PATCH] rebase -i: respect core.commentchar","startedAt":"2013-02-11T19:21:15Z","lastAt":"2013-02-12T18:23:16Z","messageCount":13,"participants":["John Keeping","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"209294","messageId":"aa1deab1de2e0f998b9ac0bc8c2d76557429a46b.1360610368.git.john@keeping.me.uk","threadId":"32879","inReplyTo":null,"subject":"[PATCH] rebase -i: respect core.commentchar","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-02-11T19:21:15Z","receivedAt":"2013-02-11T19:21:15Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Commit eff80a9 (Allow custom \"comment char\") introduced a custom comment\ncharacter for commit messages but did not teach git-rebase--interactive\nto use it.\n\nChange git-rebase--interactive to read core.commentchar and use its\nvalue when generating commit messages and for the todo list.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\n git-rebase--interactive.sh    | 85 ++++++++++++++++++++++---------------------\n t/t3404-rebase-interactive.sh | 16 ++++++++\n 2 files changed, 60 insertions(+), 41 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 8ed7fcc..8a37bc1 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -80,6 +80,9 @@ rewritten_pending=\"$state_dir\"/rewritten-pending\n GIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n export GIT_CHERRY_PICK_HELP\n \n+comment_char=$(git config --get core.commentchar 2>/dev/null | cut -c1)\n+: ${comment_char:=#}\n+\n warn () {\n \tprintf '%s\\n' \"$*\" >&2\n }\n@@ -105,8 +108,8 @@ mark_action_done () {\n \tsed -e 1q < \"$todo\" >> \"$done\"\n \tsed -e 1d < \"$todo\" >> \"$todo\".new\n \tmv -f \"$todo\".new \"$todo\"\n-\tnew_count=$(sane_grep -c '^[^#]' < \"$done\")\n-\ttotal=$(($new_count+$(sane_grep -c '^[^#]' < \"$todo\")))\n+\tnew_count=$(sane_grep -c \"^[^${comment_char}]\" < \"$done\")\n+\ttotal=$(($new_count+$(sane_grep -c \"^[^${comment_char}]\" < \"$todo\")))\n \tif test \"$last_count\" != \"$new_count\"\n \tthen\n \t\tlast_count=$new_count\n@@ -116,19 +119,19 @@ mark_action_done () {\n }\n \n append_todo_help () {\n-\tcat >> \"$todo\" << EOF\n-#\n-# Commands:\n-#  p, pick = use commit\n-#  r, reword = use commit, but edit the commit message\n-#  e, edit = use commit, but stop for amending\n-#  s, squash = use commit, but meld into previous commit\n-#  f, fixup = like \"squash\", but discard this commit's log message\n-#  x, exec = run command (the rest of the line) using shell\n-#\n-# These lines can be re-ordered; they are executed from top to bottom.\n-#\n-# If you remove a line here THAT COMMIT WILL BE LOST.\n+\tsed -e \"s/^/$comment_char /\" >>\"$todo\" <<EOF\n+\n+Commands:\n+ p, pick = use commit\n+ r, reword = use commit, but edit the commit message\n+ e, edit = use commit, but stop for amending\n+ s, squash = use commit, but meld into previous commit\n+ f, fixup = like \"squash\", but discard this commit's log message\n+ x, exec = run command (the rest of the line) using shell\n+\n+These lines can be re-ordered; they are executed from top to bottom.\n+\n+If you remove a line here THAT COMMIT WILL BE LOST.\n EOF\n }\n \n@@ -179,7 +182,7 @@ die_abort () {\n }\n \n has_action () {\n-\tsane_grep '^[^#]' \"$1\" >/dev/null\n+\tsane_grep \"^[^${comment_char}]\" \"$1\" >/dev/null\n }\n \n is_empty_commit() {\n@@ -363,10 +366,10 @@ update_squash_messages () {\n \tif test -f \"$squash_msg\"; then\n \t\tmv \"$squash_msg\" \"$squash_msg\".bak || exit\n \t\tcount=$(($(sed -n \\\n-\t\t\t-e \"1s/^# This is a combination of \\(.*\\) commits\\./\\1/p\" \\\n+\t\t\t-e \"1s/^. This is a combination of \\(.*\\) commits\\./\\1/p\" \\\n \t\t\t-e \"q\" < \"$squash_msg\".bak)+1))\n \t\t{\n-\t\t\techo \"# This is a combination of $count commits.\"\n+\t\t\techo \"$comment_char This is a combination of $count commits.\"\n \t\t\tsed -e 1d -e '2,/^./{\n \t\t\t\t/^$/d\n \t\t\t}' <\"$squash_msg\".bak\n@@ -375,8 +378,8 @@ update_squash_messages () {\n \t\tcommit_message HEAD > \"$fixup_msg\" || die \"Cannot write $fixup_msg\"\n \t\tcount=2\n \t\t{\n-\t\t\techo \"# This is a combination of 2 commits.\"\n-\t\t\techo \"# The first commit's message is:\"\n+\t\t\techo \"$comment_char This is a combination of 2 commits.\"\n+\t\t\techo \"$comment_char The first commit's message is:\"\n \t\t\techo\n \t\t\tcat \"$fixup_msg\"\n \t\t} >\"$squash_msg\"\n@@ -385,21 +388,21 @@ update_squash_messages () {\n \tsquash)\n \t\trm -f \"$fixup_msg\"\n \t\techo\n-\t\techo \"# This is the $(nth_string $count) commit message:\"\n+\t\techo \"$comment_char This is the $(nth_string $count) commit message:\"\n \t\techo\n \t\tcommit_message $2\n \t\t;;\n \tfixup)\n \t\techo\n-\t\techo \"# The $(nth_string $count) commit message will be skipped:\"\n+\t\techo \"$comment_char The $(nth_string $count) commit message will be skipped:\"\n \t\techo\n-\t\tcommit_message $2 | sed -e 's/^/#\t/'\n+\t\tcommit_message $2 | sed -e \"s/^/$comment_char\t/\"\n \t\t;;\n \tesac >>\"$squash_msg\"\n }\n \n peek_next_command () {\n-\tsed -n -e \"/^#/d\" -e '/^$/d' -e \"s/ .*//p\" -e \"q\" < \"$todo\"\n+\tsed -n -e \"/^$comment_char/d\" -e '/^$/d' -e \"s/ .*//p\" -e \"q\" < \"$todo\"\n }\n \n # A squash/fixup has failed.  Prepare the long version of the squash\n@@ -464,7 +467,7 @@ do_next () {\n \trm -f \"$msg\" \"$author_script\" \"$amend\" || exit\n \tread -r command sha1 rest < \"$todo\"\n \tcase \"$command\" in\n-\t'#'*|''|noop)\n+\t$comment_char*|''|noop)\n \t\tmark_action_done\n \t\t;;\n \tpick|p)\n@@ -803,15 +806,15 @@ skip)\n \tdo_rest\n \t;;\n edit-todo)\n-\tsed -e '/^#/d' < \"$todo\" > \"$todo\".new\n+\tsed -e \"/^$comment_char/d\" < \"$todo\" > \"$todo\".new\n \tmv -f \"$todo\".new \"$todo\"\n \tappend_todo_help\n-\tcat >> \"$todo\" << EOF\n-#\n-# You are editing the todo file of an ongoing interactive rebase.\n-# To continue rebase after editing, run:\n-#     git rebase --continue\n-#\n+\tsed -e \"s/^/$comment_char /\" >>\"$todo\" <<EOF\n+\n+You are editing the todo file of an ongoing interactive rebase.\n+To continue rebase after editing, run:\n+    git rebase --continue\n+\n EOF\n \n \tgit_sequence_editor \"$todo\" ||\n@@ -881,7 +884,7 @@ do\n \n \tif test -z \"$keep_empty\" && is_empty_commit $shortsha1 && ! is_merge_commit $shortsha1\n \tthen\n-\t\tcomment_out=\"# \"\n+\t\tcomment_out=\"$comment_char \"\n \telse\n \t\tcomment_out=\n \tfi\n@@ -942,20 +945,20 @@ test -s \"$todo\" || echo noop >> \"$todo\"\n test -n \"$autosquash\" && rearrange_squash \"$todo\"\n test -n \"$cmd\" && add_exec_commands \"$todo\"\n \n-cat >> \"$todo\" << EOF\n-\n-# Rebase $shortrevisions onto $shortonto\n+echo >>\"$todo\"\n+sed -e \"s/^/$comment_char /\" >> \"$todo\" << EOF\n+Rebase $shortrevisions onto $shortonto\n EOF\n append_todo_help\n-cat >> \"$todo\" << EOF\n-#\n-# However, if you remove everything, the rebase will be aborted.\n-#\n+sed -e \"s/^/$comment_char /\" >> \"$todo\" << EOF\n+\n+However, if you remove everything, the rebase will be aborted.\n+\n EOF\n \n if test -z \"$keep_empty\"\n then\n-\techo \"# Note that empty commits are commented out\" >>\"$todo\"\n+\techo \"$comment_char Note that empty commits are commented out\" >>\"$todo\"\n fi\n \n \ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 8462be1..1043cdc 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -934,4 +934,20 @@ test_expect_success 'rebase --edit-todo can be used to modify todo' '\n \ttest L = $(git cat-file commit HEAD | sed -ne \\$p)\n '\n \n+test_expect_success 'rebase -i respects core.commentchar' '\n+\tgit reset --hard &&\n+\tgit checkout E^0 &&\n+\tgit config core.commentchar \\; &&\n+\ttest_when_finished \"git config --unset core.commentchar\" &&\n+\tcat >comment-lines.sh <<EOF &&\n+#!$SHELL_PATH\n+sed -e \"2,\\$ s/^/;/\" \"\\$1\" >\"\\$1\".tmp\n+mv \"\\$1\".tmp \"\\$1\"\n+EOF\n+\tchmod a+x comment-lines.sh &&\n+\ttest_set_editor \"$(pwd)/comment-lines.sh\" &&\n+\tgit rebase -i B &&\n+\ttest B = $(git cat-file commit HEAD^ | sed -ne \\$p)\n+'\n+\n test_done\n-- \n1.8.1.2\n"},{"id":"209297","messageId":"7vzjzali6a.fsf@alter.siamese.dyndns.org","threadId":"32879","inReplyTo":"aa1deab1de2e0f998b9ac0bc8c2d76557429a46b.1360610368.git.john@keeping.me.uk","subject":"Re: [PATCH] rebase -i: respect core.commentchar","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-02-11T20:17:01Z","receivedAt":"2013-02-11T20:17:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n> Commit eff80a9 (Allow custom \"comment char\") introduced a custom comment\n> character for commit messages but did not teach git-rebase--interactive\n> to use it.\n>\n> Change git-rebase--interactive to read core.commentchar and use its\n> value when generating commit messages and for the todo list.\n>\n> Signed-off-by: John Keeping <john@keeping.me.uk>\n> ---\n\nIt always is better late than never, but I would have appreciated\nthis was caught while the topic was still in 'next'.  That is the\nwhole point of cooking in-flight topics in 'next'.\n\nYikes....   and thanks.\n\n>  git-rebase--interactive.sh    | 85 ++++++++++++++++++++++---------------------\n>  t/t3404-rebase-interactive.sh | 16 ++++++++\n>  2 files changed, 60 insertions(+), 41 deletions(-)\n>\n> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\n> index 8ed7fcc..8a37bc1 100644\n> --- a/git-rebase--interactive.sh\n> +++ b/git-rebase--interactive.sh\n> @@ -80,6 +80,9 @@ rewritten_pending=\"$state_dir\"/rewritten-pending\n>  GIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n>  export GIT_CHERRY_PICK_HELP\n>  \n> +comment_char=$(git config --get core.commentchar 2>/dev/null | cut -c1)\n> +: ${comment_char:=#}\n\nHmm, somewhat ugly.  I wonder if we can do this without pipe and cut.\n\n> @@ -105,8 +108,8 @@ mark_action_done () {\n>  \tsed -e 1q < \"$todo\" >> \"$done\"\n>  \tsed -e 1d < \"$todo\" >> \"$todo\".new\n>  \tmv -f \"$todo\".new \"$todo\"\n> -\tnew_count=$(sane_grep -c '^[^#]' < \"$done\")\n> -\ttotal=$(($new_count+$(sane_grep -c '^[^#]' < \"$todo\")))\n> +\tnew_count=$(sane_grep -c \"^[^${comment_char}]\" < \"$done\")\n> +\ttotal=$(($new_count+$(sane_grep -c \"^[^${comment_char}]\" < \"$todo\")))\n\nI do not think we would want to worry about comment_char being a\nfunny character that can possibly interfere with regexp.  Can't we\ndo this with \"git stripspace\" piped to \"wc -l\" or something?\n\n> @@ -116,19 +119,19 @@ mark_action_done () {\n>  }\n>  \n>  append_todo_help () {\n> -\tcat >> \"$todo\" << EOF\n> -#\n> -# Commands:\n> -#  p, pick = use commit\n> -#  r, reword = use commit, but edit the commit message\n> -#  e, edit = use commit, but stop for amending\n> -#  s, squash = use commit, but meld into previous commit\n> -#  f, fixup = like \"squash\", but discard this commit's log message\n> -#  x, exec = run command (the rest of the line) using shell\n> -#\n> -# These lines can be re-ordered; they are executed from top to bottom.\n> -#\n> -# If you remove a line here THAT COMMIT WILL BE LOST.\n> +\tsed -e \"s/^/$comment_char /\" >>\"$todo\" <<EOF\n\nWhen $comment_char is slash or backslash this will break.\nPerhaps \"stripspace --comment-lines\" can be used here.\n\n> +\n> +Commands:\n> + p, pick = use commit\n> + r, reword = use commit, but edit the commit message\n> + e, edit = use commit, but stop for amending\n> + s, squash = use commit, but meld into previous commit\n> + f, fixup = like \"squash\", but discard this commit's log message\n> + x, exec = run command (the rest of the line) using shell\n> +\n> +These lines can be re-ordered; they are executed from top to bottom.\n> +\n> +If you remove a line here THAT COMMIT WILL BE LOST.\n>  EOF\n>  }\n>  \n> @@ -179,7 +182,7 @@ die_abort () {\n>  }\n>  \n>  has_action () {\n> -\tsane_grep '^[^#]' \"$1\" >/dev/null\n> +\tsane_grep \"^[^${comment_char}]\" \"$1\" >/dev/null\n\nLikewise.\n\n> @@ -363,10 +366,10 @@ update_squash_messages () {\n>  \tif test -f \"$squash_msg\"; then\n>  \t\tmv \"$squash_msg\" \"$squash_msg\".bak || exit\n>  \t\tcount=$(($(sed -n \\\n> -\t\t\t-e \"1s/^# This is a combination of \\(.*\\) commits\\./\\1/p\" \\\n> +\t\t\t-e \"1s/^. This is a combination of \\(.*\\) commits\\./\\1/p\" \\\n\nThis one is safe.\n\n>  \t\t\t-e \"q\" < \"$squash_msg\".bak)+1))\n>  \t\t{\n> -\t\t\techo \"# This is a combination of $count commits.\"\n> +\t\t\techo \"$comment_char This is a combination of $count commits.\"\n\nBut you need to do \"printf\" to be safe here, I think, for comment_char='\\'.\n\n> @@ -375,8 +378,8 @@ update_squash_messages () {\n>  \t\tcommit_message HEAD > \"$fixup_msg\" || die \"Cannot write $fixup_msg\"\n>  \t\tcount=2\n>  \t\t{\n> -\t\t\techo \"# This is a combination of 2 commits.\"\n> -\t\t\techo \"# The first commit's message is:\"\n> +\t\t\techo \"$comment_char This is a combination of 2 commits.\"\n> +\t\t\techo \"$comment_char The first commit's message is:\"\n\nLikewise.\n\n> @@ -385,21 +388,21 @@ update_squash_messages () {\n>  \tsquash)\n>  \t\trm -f \"$fixup_msg\"\n>  \t\techo\n> -\t\techo \"# This is the $(nth_string $count) commit message:\"\n> +\t\techo \"$comment_char This is the $(nth_string $count) commit message:\"\n\nLikewise.\n\n>  \t\techo\n>  \t\tcommit_message $2\n>  \t\t;;\n>  \tfixup)\n>  \t\techo\n> -\t\techo \"# The $(nth_string $count) commit message will be skipped:\"\n> +\t\techo \"$comment_char The $(nth_string $count) commit message will be skipped:\"\n>  \t\techo\n> -\t\tcommit_message $2 | sed -e 's/^/#\t/'\n> +\t\tcommit_message $2 | sed -e \"s/^/$comment_char\t/\"\n\nLikewise.\n\n>  peek_next_command () {\n> -\tsed -n -e \"/^#/d\" -e '/^$/d' -e \"s/ .*//p\" -e \"q\" < \"$todo\"\n> +\tsed -n -e \"/^$comment_char/d\" -e '/^$/d' -e \"s/ .*//p\" -e \"q\" < \"$todo\"\n>  }\n\nLikewise.\n\n> @@ -464,7 +467,7 @@ do_next () {\n>  \trm -f \"$msg\" \"$author_script\" \"$amend\" || exit\n>  \tread -r command sha1 rest < \"$todo\"\n>  \tcase \"$command\" in\n> -\t'#'*|''|noop)\n> +\t$comment_char*|''|noop)\n\nThis is OK.\n\n> @@ -803,15 +806,15 @@ skip)\n>  \tdo_rest\n>  \t;;\n>  edit-todo)\n> -\tsed -e '/^#/d' < \"$todo\" > \"$todo\".new\n> +\tsed -e \"/^$comment_char/d\" < \"$todo\" > \"$todo\".new\n\nUnsafe.\n\n>  \tmv -f \"$todo\".new \"$todo\"\n>  \tappend_todo_help\n> -\tcat >> \"$todo\" << EOF\n> -#\n> -# You are editing the todo file of an ongoing interactive rebase.\n> -# To continue rebase after editing, run:\n> -#     git rebase --continue\n> -#\n> +\tsed -e \"s/^/$comment_char /\" >>\"$todo\" <<EOF\n\nUnsafe.\n\n> +\n> +You are editing the todo file of an ongoing interactive rebase.\n> +To continue rebase after editing, run:\n> +    git rebase --continue\n> +\n>  EOF\n>  \n>  \tgit_sequence_editor \"$todo\" ||\n> @@ -881,7 +884,7 @@ do\n>  \n>  \tif test -z \"$keep_empty\" && is_empty_commit $shortsha1 && ! is_merge_commit $shortsha1\n>  \tthen\n> -\t\tcomment_out=\"# \"\n> +\t\tcomment_out=\"$comment_char \"\n\nOK.\n\n>  \telse\n>  \t\tcomment_out=\n>  \tfi\n> @@ -942,20 +945,20 @@ test -s \"$todo\" || echo noop >> \"$todo\"\n>  test -n \"$autosquash\" && rearrange_squash \"$todo\"\n>  test -n \"$cmd\" && add_exec_commands \"$todo\"\n>  \n> -cat >> \"$todo\" << EOF\n> -\n> -# Rebase $shortrevisions onto $shortonto\n> +echo >>\"$todo\"\n> +sed -e \"s/^/$comment_char /\" >> \"$todo\" << EOF\n\nUnsafe.\n\n> +Rebase $shortrevisions onto $shortonto\n>  EOF\n>  append_todo_help\n> -cat >> \"$todo\" << EOF\n> -#\n> -# However, if you remove everything, the rebase will be aborted.\n> -#\n> +sed -e \"s/^/$comment_char /\" >> \"$todo\" << EOF\n\nUnsafe.\n\n> +\n> +However, if you remove everything, the rebase will be aborted.\n> +\n>  EOF\n>  \n>  if test -z \"$keep_empty\"\n>  then\n> -\techo \"# Note that empty commits are commented out\" >>\"$todo\"\n> +\techo \"$comment_char Note that empty commits are commented out\" >>\"$todo\"\n>  fi\n>  \n>  \n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index 8462be1..1043cdc 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -934,4 +934,20 @@ test_expect_success 'rebase --edit-todo can be used to modify todo' '\n>  \ttest L = $(git cat-file commit HEAD | sed -ne \\$p)\n>  '\n>  \n> +test_expect_success 'rebase -i respects core.commentchar' '\n> +\tgit reset --hard &&\n> +\tgit checkout E^0 &&\n> +\tgit config core.commentchar \\; &&\n\nTry setting it to '\\' or '/' or '-'; they may catch some more breakages.\n\n> +\ttest_when_finished \"git config --unset core.commentchar\" &&\n> +\tcat >comment-lines.sh <<EOF &&\n> +#!$SHELL_PATH\n> +sed -e \"2,\\$ s/^/;/\" \"\\$1\" >\"\\$1\".tmp\n> +mv \"\\$1\".tmp \"\\$1\"\n> +EOF\n> +\tchmod a+x comment-lines.sh &&\n> +\ttest_set_editor \"$(pwd)/comment-lines.sh\" &&\n> +\tgit rebase -i B &&\n> +\ttest B = $(git cat-file commit HEAD^ | sed -ne \\$p)\n> +'\n> +\n>  test_done\n"},{"id":"209309","messageId":"20130211213900.GE2270@serenity.lan","threadId":"32879","inReplyTo":"7vzjzali6a.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] rebase -i: respect core.commentchar","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-02-11T21:39:00Z","receivedAt":"2013-02-11T21:39:00Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Mon, Feb 11, 2013 at 12:17:01PM -0800, Junio C Hamano wrote:\n> John Keeping <john@keeping.me.uk> writes:\n> > +comment_char=$(git config --get core.commentchar 2>/dev/null | cut -c1)\n> > +: ${comment_char:=#}\n> \n> Hmm, somewhat ugly.  I wonder if we can do this without pipe and cut.\n\nYeah, but I can't see a better way of doing this if we want to mimic the\nbehaviour of the C code in taking only the first character of the\nconfigured value.\n\n> > @@ -105,8 +108,8 @@ mark_action_done () {\n> >  \tsed -e 1q < \"$todo\" >> \"$done\"\n> >  \tsed -e 1d < \"$todo\" >> \"$todo\".new\n> >  \tmv -f \"$todo\".new \"$todo\"\n> > -\tnew_count=$(sane_grep -c '^[^#]' < \"$done\")\n> > -\ttotal=$(($new_count+$(sane_grep -c '^[^#]' < \"$todo\")))\n> > +\tnew_count=$(sane_grep -c \"^[^${comment_char}]\" < \"$done\")\n> > +\ttotal=$(($new_count+$(sane_grep -c \"^[^${comment_char}]\" < \"$todo\")))\n> \n> I do not think we would want to worry about comment_char being a\n> funny character that can possibly interfere with regexp.  Can't we\n> do this with \"git stripspace\" piped to \"wc -l\" or something?\n\nI didn't know about \"git stripspace\", it does make a lot of this\nsignificantly safer.  I'll work up a new version that uses that instead\nof grep and with printf used where necessary.\n\n> > @@ -116,19 +119,19 @@ mark_action_done () {\n> >  }\n> >  \n> >  append_todo_help () {\n> > -\tcat >> \"$todo\" << EOF\n> > -#\n> > -# Commands:\n> > -#  p, pick = use commit\n> > -#  r, reword = use commit, but edit the commit message\n> > -#  e, edit = use commit, but stop for amending\n> > -#  s, squash = use commit, but meld into previous commit\n> > -#  f, fixup = like \"squash\", but discard this commit's log message\n> > -#  x, exec = run command (the rest of the line) using shell\n> > -#\n> > -# These lines can be re-ordered; they are executed from top to bottom.\n> > -#\n> > -# If you remove a line here THAT COMMIT WILL BE LOST.\n> > +\tsed -e \"s/^/$comment_char /\" >>\"$todo\" <<EOF\n> \n> When $comment_char is slash or backslash this will break.\n> Perhaps \"stripspace --comment-lines\" can be used here.\n\nNot in this case - this is adding the comment char in front of each\nline.  Is there a better option than this?\n\n\twhile read -r line\n\tdo\n\t\tprintf '%s %s\\n' \"$comment_char\" \"$line\"\n\tdone >> \"$todo\" <<EOF\n\t...\n\tEOF\n\n> > +\n> > +Commands:\n> > + p, pick = use commit\n> > + r, reword = use commit, but edit the commit message\n> > + e, edit = use commit, but stop for amending\n> > + s, squash = use commit, but meld into previous commit\n> > + f, fixup = like \"squash\", but discard this commit's log message\n> > + x, exec = run command (the rest of the line) using shell\n> > +\n> > +These lines can be re-ordered; they are executed from top to bottom.\n> > +\n> > +If you remove a line here THAT COMMIT WILL BE LOST.\n> >  EOF\n> >  }\n> >  \n> > @@ -179,7 +182,7 @@ die_abort () {\n> >  }\n> >  \n> >  has_action () {\n> > -\tsane_grep '^[^#]' \"$1\" >/dev/null\n> > +\tsane_grep \"^[^${comment_char}]\" \"$1\" >/dev/null\n> \n> Likewise.\n> \n> > @@ -363,10 +366,10 @@ update_squash_messages () {\n> >  \tif test -f \"$squash_msg\"; then\n> >  \t\tmv \"$squash_msg\" \"$squash_msg\".bak || exit\n> >  \t\tcount=$(($(sed -n \\\n> > -\t\t\t-e \"1s/^# This is a combination of \\(.*\\) commits\\./\\1/p\" \\\n> > +\t\t\t-e \"1s/^. This is a combination of \\(.*\\) commits\\./\\1/p\" \\\n> \n> This one is safe.\n> \n> >  \t\t\t-e \"q\" < \"$squash_msg\".bak)+1))\n> >  \t\t{\n> > -\t\t\techo \"# This is a combination of $count commits.\"\n> > +\t\t\techo \"$comment_char This is a combination of $count commits.\"\n> \n> But you need to do \"printf\" to be safe here, I think, for comment_char='\\'.\n> \n> > @@ -375,8 +378,8 @@ update_squash_messages () {\n> >  \t\tcommit_message HEAD > \"$fixup_msg\" || die \"Cannot write $fixup_msg\"\n> >  \t\tcount=2\n> >  \t\t{\n> > -\t\t\techo \"# This is a combination of 2 commits.\"\n> > -\t\t\techo \"# The first commit's message is:\"\n> > +\t\t\techo \"$comment_char This is a combination of 2 commits.\"\n> > +\t\t\techo \"$comment_char The first commit's message is:\"\n> \n> Likewise.\n> \n> > @@ -385,21 +388,21 @@ update_squash_messages () {\n> >  \tsquash)\n> >  \t\trm -f \"$fixup_msg\"\n> >  \t\techo\n> > -\t\techo \"# This is the $(nth_string $count) commit message:\"\n> > +\t\techo \"$comment_char This is the $(nth_string $count) commit message:\"\n> \n> Likewise.\n> \n> >  \t\techo\n> >  \t\tcommit_message $2\n> >  \t\t;;\n> >  \tfixup)\n> >  \t\techo\n> > -\t\techo \"# The $(nth_string $count) commit message will be skipped:\"\n> > +\t\techo \"$comment_char The $(nth_string $count) commit message will be skipped:\"\n> >  \t\techo\n> > -\t\tcommit_message $2 | sed -e 's/^/#\t/'\n> > +\t\tcommit_message $2 | sed -e \"s/^/$comment_char\t/\"\n> \n> Likewise.\n\nAgain this is adding $comment_char in front of each line, so it may need\na loop like above again.\n\n> >  peek_next_command () {\n> > -\tsed -n -e \"/^#/d\" -e '/^$/d' -e \"s/ .*//p\" -e \"q\" < \"$todo\"\n> > +\tsed -n -e \"/^$comment_char/d\" -e '/^$/d' -e \"s/ .*//p\" -e \"q\" < \"$todo\"\n> >  }\n> \n> Likewise.\n> \n> > @@ -464,7 +467,7 @@ do_next () {\n> >  \trm -f \"$msg\" \"$author_script\" \"$amend\" || exit\n> >  \tread -r command sha1 rest < \"$todo\"\n> >  \tcase \"$command\" in\n> > -\t'#'*|''|noop)\n> > +\t$comment_char*|''|noop)\n> \n> This is OK.\n> \n> > @@ -803,15 +806,15 @@ skip)\n> >  \tdo_rest\n> >  \t;;\n> >  edit-todo)\n> > -\tsed -e '/^#/d' < \"$todo\" > \"$todo\".new\n> > +\tsed -e \"/^$comment_char/d\" < \"$todo\" > \"$todo\".new\n> \n> Unsafe.\n> \n> >  \tmv -f \"$todo\".new \"$todo\"\n> >  \tappend_todo_help\n> > -\tcat >> \"$todo\" << EOF\n> > -#\n> > -# You are editing the todo file of an ongoing interactive rebase.\n> > -# To continue rebase after editing, run:\n> > -#     git rebase --continue\n> > -#\n> > +\tsed -e \"s/^/$comment_char /\" >>\"$todo\" <<EOF\n> \n> Unsafe.\n> \n> > +\n> > +You are editing the todo file of an ongoing interactive rebase.\n> > +To continue rebase after editing, run:\n> > +    git rebase --continue\n> > +\n> >  EOF\n> >  \n> >  \tgit_sequence_editor \"$todo\" ||\n> > @@ -881,7 +884,7 @@ do\n> >  \n> >  \tif test -z \"$keep_empty\" && is_empty_commit $shortsha1 && ! is_merge_commit $shortsha1\n> >  \tthen\n> > -\t\tcomment_out=\"# \"\n> > +\t\tcomment_out=\"$comment_char \"\n> \n> OK.\n> \n> >  \telse\n> >  \t\tcomment_out=\n> >  \tfi\n> > @@ -942,20 +945,20 @@ test -s \"$todo\" || echo noop >> \"$todo\"\n> >  test -n \"$autosquash\" && rearrange_squash \"$todo\"\n> >  test -n \"$cmd\" && add_exec_commands \"$todo\"\n> >  \n> > -cat >> \"$todo\" << EOF\n> > -\n> > -# Rebase $shortrevisions onto $shortonto\n> > +echo >>\"$todo\"\n> > +sed -e \"s/^/$comment_char /\" >> \"$todo\" << EOF\n> \n> Unsafe.\n> \n> > +Rebase $shortrevisions onto $shortonto\n> >  EOF\n> >  append_todo_help\n> > -cat >> \"$todo\" << EOF\n> > -#\n> > -# However, if you remove everything, the rebase will be aborted.\n> > -#\n> > +sed -e \"s/^/$comment_char /\" >> \"$todo\" << EOF\n> \n> Unsafe.\n> \n> > +\n> > +However, if you remove everything, the rebase will be aborted.\n> > +\n> >  EOF\n> >  \n> >  if test -z \"$keep_empty\"\n> >  then\n> > -\techo \"# Note that empty commits are commented out\" >>\"$todo\"\n> > +\techo \"$comment_char Note that empty commits are commented out\" >>\"$todo\"\n> >  fi\n> >  \n> >  \n> > diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> > index 8462be1..1043cdc 100755\n> > --- a/t/t3404-rebase-interactive.sh\n> > +++ b/t/t3404-rebase-interactive.sh\n> > @@ -934,4 +934,20 @@ test_expect_success 'rebase --edit-todo can be used to modify todo' '\n> >  \ttest L = $(git cat-file commit HEAD | sed -ne \\$p)\n> >  '\n> >  \n> > +test_expect_success 'rebase -i respects core.commentchar' '\n> > +\tgit reset --hard &&\n> > +\tgit checkout E^0 &&\n> > +\tgit config core.commentchar \\; &&\n> \n> Try setting it to '\\' or '/' or '-'; they may catch some more breakages.\n> \n> > +\ttest_when_finished \"git config --unset core.commentchar\" &&\n> > +\tcat >comment-lines.sh <<EOF &&\n> > +#!$SHELL_PATH\n> > +sed -e \"2,\\$ s/^/;/\" \"\\$1\" >\"\\$1\".tmp\n> > +mv \"\\$1\".tmp \"\\$1\"\n> > +EOF\n> > +\tchmod a+x comment-lines.sh &&\n> > +\ttest_set_editor \"$(pwd)/comment-lines.sh\" &&\n> > +\tgit rebase -i B &&\n> > +\ttest B = $(git cat-file commit HEAD^ | sed -ne \\$p)\n> > +'\n> > +\n> >  test_done\n"},{"id":"209311","messageId":"7va9raldw8.fsf@alter.siamese.dyndns.org","threadId":"32879","inReplyTo":"20130211213900.GE2270@serenity.lan","subject":"Re: [PATCH] rebase -i: respect core.commentchar","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-02-11T21:49:27Z","receivedAt":"2013-02-11T21:49:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n>> I do not think we would want to worry about comment_char being a\n>> funny character that can possibly interfere with regexp.  Can't we\n>> do this with \"git stripspace\" piped to \"wc -l\" or something?\n>\n> I didn't know about \"git stripspace\",...\n>> > -# If you remove a line here THAT COMMIT WILL BE LOST.\n>> > +\tsed -e \"s/^/$comment_char /\" >>\"$todo\" <<EOF\n>> \n>> When $comment_char is slash or backslash this will break.\n>> Perhaps \"stripspace --comment-lines\" can be used here.\n>\n> Not in this case - this is adding the comment char in front of each\n> line.  Is there a better option than this?\n>\n> \twhile read -r line\n> \tdo\n> \t\tprintf '%s %s\\n' \"$comment_char\" \"$line\"\n> \tdone >> \"$todo\" <<EOF\n> \t...\n> \tEOF\n\nPerhaps\n\n\tgit stripspace --comment-lines <<EOF\n        ...\n        EOF\n\nis a better option that that loop.\n"},{"id":"209318","messageId":"20130211230804.GF2270@serenity.lan","threadId":"32879","inReplyTo":"7va9raldw8.fsf@alter.siamese.dyndns.org","subject":"[PATCH v2] rebase -i: respect core.commentchar","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-02-11T23:08:04Z","receivedAt":"2013-02-11T23:08:04Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Commit eff80a9 (Allow custom \"comment char\") introduced a custom comment\ncharacter for commit messages but did not teach git-rebase--interactive\nto use it.\n\nChange git-rebase--interactive to read core.commentchar and use its\nvalue when generating commit messages and for the command list.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n\n---\nChanges since v1:\n- use '\\' as the comment character in tests\n- use \"git stripspace --strip-comments\" where appropriate\n- use \"git stripspace --comment-lines\" where appropriate\n- use printf instead of echo when the string contains $comment_char\n- quote $comment_char in case label\n\nOn Mon, Feb 11, 2013 at 01:49:27PM -0800, Junio C Hamano wrote:\n> ...\n> Perhaps\n> \n> \tgit stripspace --comment-lines <<EOF\n>         ...\n>         EOF\n> \n> is a better option that that loop.\n\nYes.  I was confusing myself with out-of-date documentation.\n\n---\n git-rebase--interactive.sh    | 88 ++++++++++++++++++++++---------------------\n t/t3404-rebase-interactive.sh | 16 ++++++++\n 2 files changed, 62 insertions(+), 42 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 8ed7fcc..b5ce3f2 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -80,6 +80,9 @@ rewritten_pending=\"$state_dir\"/rewritten-pending\n GIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n export GIT_CHERRY_PICK_HELP\n \n+comment_char=$(git config --get core.commentchar 2>/dev/null | cut -c1)\n+: ${comment_char:=#}\n+\n warn () {\n \tprintf '%s\\n' \"$*\" >&2\n }\n@@ -105,8 +108,8 @@ mark_action_done () {\n \tsed -e 1q < \"$todo\" >> \"$done\"\n \tsed -e 1d < \"$todo\" >> \"$todo\".new\n \tmv -f \"$todo\".new \"$todo\"\n-\tnew_count=$(sane_grep -c '^[^#]' < \"$done\")\n-\ttotal=$(($new_count+$(sane_grep -c '^[^#]' < \"$todo\")))\n+\tnew_count=$(git stripspace --strip-comments < \"$done\" | wc -l)\n+\ttotal=$(($new_count+$(git stripspace --strip-comments < \"$todo\" | wc -l)))\n \tif test \"$last_count\" != \"$new_count\"\n \tthen\n \t\tlast_count=$new_count\n@@ -116,19 +119,19 @@ mark_action_done () {\n }\n \n append_todo_help () {\n-\tcat >> \"$todo\" << EOF\n-#\n-# Commands:\n-#  p, pick = use commit\n-#  r, reword = use commit, but edit the commit message\n-#  e, edit = use commit, but stop for amending\n-#  s, squash = use commit, but meld into previous commit\n-#  f, fixup = like \"squash\", but discard this commit's log message\n-#  x, exec = run command (the rest of the line) using shell\n-#\n-# These lines can be re-ordered; they are executed from top to bottom.\n-#\n-# If you remove a line here THAT COMMIT WILL BE LOST.\n+\tgit stripspace --comment-lines >>\"$todo\" <<EOF\n+\n+Commands:\n+ p, pick = use commit\n+ r, reword = use commit, but edit the commit message\n+ e, edit = use commit, but stop for amending\n+ s, squash = use commit, but meld into previous commit\n+ f, fixup = like \"squash\", but discard this commit's log message\n+ x, exec = run command (the rest of the line) using shell\n+\n+These lines can be re-ordered; they are executed from top to bottom.\n+\n+If you remove a line here THAT COMMIT WILL BE LOST.\n EOF\n }\n \n@@ -179,7 +182,9 @@ die_abort () {\n }\n \n has_action () {\n-\tsane_grep '^[^#]' \"$1\" >/dev/null\n+\techo \"space stripped actions:\" >&2\n+\tgit stripspace --strip-comments <\"$1\" >&2\n+\ttest -n \"$(git stripspace --strip-comments <\"$1\")\"\n }\n \n is_empty_commit() {\n@@ -363,10 +368,10 @@ update_squash_messages () {\n \tif test -f \"$squash_msg\"; then\n \t\tmv \"$squash_msg\" \"$squash_msg\".bak || exit\n \t\tcount=$(($(sed -n \\\n-\t\t\t-e \"1s/^# This is a combination of \\(.*\\) commits\\./\\1/p\" \\\n+\t\t\t-e \"1s/^. This is a combination of \\(.*\\) commits\\./\\1/p\" \\\n \t\t\t-e \"q\" < \"$squash_msg\".bak)+1))\n \t\t{\n-\t\t\techo \"# This is a combination of $count commits.\"\n+\t\t\tprintf '%s\\n' \"$comment_char This is a combination of $count commits.\"\n \t\t\tsed -e 1d -e '2,/^./{\n \t\t\t\t/^$/d\n \t\t\t}' <\"$squash_msg\".bak\n@@ -375,8 +380,8 @@ update_squash_messages () {\n \t\tcommit_message HEAD > \"$fixup_msg\" || die \"Cannot write $fixup_msg\"\n \t\tcount=2\n \t\t{\n-\t\t\techo \"# This is a combination of 2 commits.\"\n-\t\t\techo \"# The first commit's message is:\"\n+\t\t\tprintf '%s\\n' \"$comment_char This is a combination of 2 commits.\"\n+\t\t\tprintf '%s\\n' \"$comment_char The first commit's message is:\"\n \t\t\techo\n \t\t\tcat \"$fixup_msg\"\n \t\t} >\"$squash_msg\"\n@@ -385,21 +390,22 @@ update_squash_messages () {\n \tsquash)\n \t\trm -f \"$fixup_msg\"\n \t\techo\n-\t\techo \"# This is the $(nth_string $count) commit message:\"\n+\t\tprintf '%s\\n' \"$comment_char This is the $(nth_string $count) commit message:\"\n \t\techo\n \t\tcommit_message $2\n \t\t;;\n \tfixup)\n \t\techo\n-\t\techo \"# The $(nth_string $count) commit message will be skipped:\"\n+\t\tprintf '%s\\n' \"$comment_char The $(nth_string $count) commit message will be skipped:\"\n \t\techo\n-\t\tcommit_message $2 | sed -e 's/^/#\t/'\n+\t\t# Change the space after the comment character to TAB:\n+\t\tcommit_message $2 | git stripspace --comment-lines | sed -e 's/ /\t/'\n \t\t;;\n \tesac >>\"$squash_msg\"\n }\n \n peek_next_command () {\n-\tsed -n -e \"/^#/d\" -e '/^$/d' -e \"s/ .*//p\" -e \"q\" < \"$todo\"\n+\tgit stripspace --strip-comments <\"$todo\" | sed -n -e 's/ .*//p' -e q\n }\n \n # A squash/fixup has failed.  Prepare the long version of the squash\n@@ -464,7 +470,7 @@ do_next () {\n \trm -f \"$msg\" \"$author_script\" \"$amend\" || exit\n \tread -r command sha1 rest < \"$todo\"\n \tcase \"$command\" in\n-\t'#'*|''|noop)\n+\t\"$comment_char\"*|''|noop)\n \t\tmark_action_done\n \t\t;;\n \tpick|p)\n@@ -803,15 +809,15 @@ skip)\n \tdo_rest\n \t;;\n edit-todo)\n-\tsed -e '/^#/d' < \"$todo\" > \"$todo\".new\n+\tgit stripspace --strip-comments <\"$todo\" >\"$todo\".new\n \tmv -f \"$todo\".new \"$todo\"\n \tappend_todo_help\n-\tcat >> \"$todo\" << EOF\n-#\n-# You are editing the todo file of an ongoing interactive rebase.\n-# To continue rebase after editing, run:\n-#     git rebase --continue\n-#\n+\tgit stripspace --comment-lines >>\"$todo\" <<EOF\n+\n+You are editing the todo file of an ongoing interactive rebase.\n+To continue rebase after editing, run:\n+    git rebase --continue\n+\n EOF\n \n \tgit_sequence_editor \"$todo\" ||\n@@ -881,7 +887,7 @@ do\n \n \tif test -z \"$keep_empty\" && is_empty_commit $shortsha1 && ! is_merge_commit $shortsha1\n \tthen\n-\t\tcomment_out=\"# \"\n+\t\tcomment_out=\"$comment_char \"\n \telse\n \t\tcomment_out=\n \tfi\n@@ -942,20 +948,18 @@ test -s \"$todo\" || echo noop >> \"$todo\"\n test -n \"$autosquash\" && rearrange_squash \"$todo\"\n test -n \"$cmd\" && add_exec_commands \"$todo\"\n \n-cat >> \"$todo\" << EOF\n-\n-# Rebase $shortrevisions onto $shortonto\n-EOF\n+echo >>\"$todo\"\n+printf '%s\\n' \"$comment_char Rebase $shortrevisions onto $shortonto\" >>\"$todo\"\n append_todo_help\n-cat >> \"$todo\" << EOF\n-#\n-# However, if you remove everything, the rebase will be aborted.\n-#\n+git stripspace --comment-lines >>\"$todo\" <<EOF\n+\n+However, if you remove everything, the rebase will be aborted.\n+\n EOF\n \n if test -z \"$keep_empty\"\n then\n-\techo \"# Note that empty commits are commented out\" >>\"$todo\"\n+\tprintf '%s\\n' \"$comment_char Note that empty commits are commented out\" >>\"$todo\"\n fi\n \n \ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 8462be1..16d8160 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -934,4 +934,20 @@ test_expect_success 'rebase --edit-todo can be used to modify todo' '\n \ttest L = $(git cat-file commit HEAD | sed -ne \\$p)\n '\n \n+test_expect_success 'rebase -i respects core.commentchar' '\n+\tgit reset --hard &&\n+\tgit checkout E^0 &&\n+\tgit config core.commentchar \"\\\\\" &&\n+\ttest_when_finished \"git config --unset core.commentchar\" &&\n+\tcat >comment-lines.sh <<EOF &&\n+#!$SHELL_PATH\n+sed -e \"2,\\$ s/^/\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n+mv \"\\$1\".tmp \"\\$1\"\n+EOF\n+\tchmod a+x comment-lines.sh &&\n+\ttest_set_editor \"$(pwd)/comment-lines.sh\" &&\n+\tgit rebase -i B &&\n+\ttest B = $(git cat-file commit HEAD^ | sed -ne \\$p)\n+'\n+\n test_done\n-- \n1.8.1.3.556.gb3310b5.dirty\n"},{"id":"209321","messageId":"7vehgmjsno.fsf@alter.siamese.dyndns.org","threadId":"32879","inReplyTo":"20130211230804.GF2270@serenity.lan","subject":"Re: [PATCH v2] rebase -i: respect core.commentchar","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-02-12T00:13:31Z","receivedAt":"2013-02-12T00:13:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n> @@ -179,7 +182,9 @@ die_abort () {\n>  }\n>  \n>  has_action () {\n> -\tsane_grep '^[^#]' \"$1\" >/dev/null\n> +\techo \"space stripped actions:\" >&2\n> +\tgit stripspace --strip-comments <\"$1\" >&2\n> +\ttest -n \"$(git stripspace --strip-comments <\"$1\")\"\n>  }\n\nI'll remove the debugging remnants while queuing.\n\n>  \tfixup)\n>  \t\techo\n> -\t\techo \"# The $(nth_string $count) commit message will be skipped:\"\n> +\t\tprintf '%s\\n' \"$comment_char The $(nth_string $count) commit message will be skipped:\"\n>  \t\techo\n> -\t\tcommit_message $2 | sed -e 's/^/#\t/'\n> +\t\t# Change the space after the comment character to TAB:\n> +\t\tcommit_message $2 | git stripspace --comment-lines | sed -e 's/ /\t/'\n\nI think this changes the behaviour but in a good way.  It used to\nshow an empty line in the incoming commit message to a hash followed\nby a trailing HT before the end of line, but now it only emits the\ncomment char immediately followed by the end of line.\n\n> @@ -942,20 +948,18 @@ test -s \"$todo\" || echo noop >> \"$todo\"\n>  test -n \"$autosquash\" && rearrange_squash \"$todo\"\n>  test -n \"$cmd\" && add_exec_commands \"$todo\"\n>  \n> -cat >> \"$todo\" << EOF\n> -\n> -# Rebase $shortrevisions onto $shortonto\n> -EOF\n> +echo >>\"$todo\"\n> +printf '%s\\n' \"$comment_char Rebase $shortrevisions onto $shortonto\" >>\"$todo\"\n\nI think you can still do\n\n\tcat >>\"$todo\" <<EOF\n\n\t$comment_char Rebase $shortrevisions onto...\n\tEOF\n\nhere with any funny comment character.  Doing this with two separate\nI/O does not hurt very much, but the resulting code may be easier to\nscan if left as here-text with a single cat.\n\nPlease eyeball what is in 'pu' (I have a separate squashable fixup\non top of your patch) and let me know if I made mistakes.\n\nThanks for working on this.\n"},{"id":"209343","messageId":"20130212095340.GG2270@serenity.lan","threadId":"32879","inReplyTo":"7vehgmjsno.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] rebase -i: respect core.commentchar","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-02-12T09:53:40Z","receivedAt":"2013-02-12T09:53:40Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Mon, Feb 11, 2013 at 04:13:31PM -0800, Junio C Hamano wrote:\n> John Keeping <john@keeping.me.uk> writes:\n> \n> > @@ -179,7 +182,9 @@ die_abort () {\n> >  }\n> >  \n> >  has_action () {\n> > -\tsane_grep '^[^#]' \"$1\" >/dev/null\n> > +\techo \"space stripped actions:\" >&2\n> > +\tgit stripspace --strip-comments <\"$1\" >&2\n> > +\ttest -n \"$(git stripspace --strip-comments <\"$1\")\"\n> >  }\n> \n> I'll remove the debugging remnants while queuing.\n\nThanks.  I don't think I was fully awake when I finished this last\nnight - the following fixup is also needed to avoid relying on the shell\nemitting a literal backslash when a backslash isn't followed by a known\nescape character.\n\n-- >8 --\n\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex cbe36bf..84bd525 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -947,7 +947,7 @@ test_expect_success 'rebase -i respects core.commentchar' '\n \ttest_when_finished \"git config --unset core.commentchar\" &&\n \tcat >comment-lines.sh <<EOF &&\n #!$SHELL_PATH\n-sed -e \"2,\\$ s/^/\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n+sed -e \"2,\\$ s/^/\\\\\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n mv \"\\$1\".tmp \"\\$1\"\n EOF\n \tchmod a+x comment-lines.sh &&\n\n-- >8 --\n\n> > @@ -942,20 +948,18 @@ test -s \"$todo\" || echo noop >> \"$todo\"\n> >  test -n \"$autosquash\" && rearrange_squash \"$todo\"\n> >  test -n \"$cmd\" && add_exec_commands \"$todo\"\n> >  \n> > -cat >> \"$todo\" << EOF\n> > -\n> > -# Rebase $shortrevisions onto $shortonto\n> > -EOF\n> > +echo >>\"$todo\"\n> > +printf '%s\\n' \"$comment_char Rebase $shortrevisions onto $shortonto\" >>\"$todo\"\n> \n> I think you can still do\n> \n> \tcat >>\"$todo\" <<EOF\n> \n> \t$comment_char Rebase $shortrevisions onto...\n> \tEOF\n> \n> here with any funny comment character.  Doing this with two separate\n> I/O does not hurt very much, but the resulting code may be easier to\n> scan if left as here-text with a single cat.\n> \n> Please eyeball what is in 'pu' (I have a separate squashable fixup\n> on top of your patch) and let me know if I made mistakes.\n\nThe fixup commit looks good to me.\n\n\nJohn\n"},{"id":"209378","messageId":"7v4nhhigp5.fsf@alter.siamese.dyndns.org","threadId":"32879","inReplyTo":"20130212095340.GG2270@serenity.lan","subject":"Re: [PATCH v2] rebase -i: respect core.commentchar","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-02-12T17:29:26Z","receivedAt":"2013-02-12T17:29:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n> ... the following fixup is also needed to avoid relying on the shell\n> emitting a literal backslash when a backslash isn't followed by a known\n> escape character.\n>\n> -- >8 --\n>\n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index cbe36bf..84bd525 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -947,7 +947,7 @@ test_expect_success 'rebase -i respects core.commentchar' '\n>  \ttest_when_finished \"git config --unset core.commentchar\" &&\n>  \tcat >comment-lines.sh <<EOF &&\n>  #!$SHELL_PATH\n> -sed -e \"2,\\$ s/^/\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n> +sed -e \"2,\\$ s/^/\\\\\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n>  mv \"\\$1\".tmp \"\\$1\"\n>  EOF\n>  \tchmod a+x comment-lines.sh &&\n\nYeek.  If you used write_script with here-text that does not\ninterpolate,\n\n\twrite_script remove-all-but-the-first.sh <<\\EOF\n\tsed -e '2,$s/^/\\\\/'  <\"$1\" >\"$1.tmp\" &&\n        mv \"$1.tmp\" \"$1\"\n\tEOF\n\nthe above would be much more readable.\n\nI am not sure if I understand what you meant by \"literal backslash\nblah blah\", though.\n"},{"id":"209380","messageId":"20130212175322.GC13501@farnsworth.metanate.com","threadId":"32879","inReplyTo":"7v4nhhigp5.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] rebase -i: respect core.commentchar","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-02-12T17:53:22Z","receivedAt":"2013-02-12T17:53:22Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Tue, Feb 12, 2013 at 09:29:26AM -0800, Junio C Hamano wrote:\n> John Keeping <john@keeping.me.uk> writes:\n> \n> > ... the following fixup is also needed to avoid relying on the shell\n> > emitting a literal backslash when a backslash isn't followed by a known\n> > escape character.\n> >\n> > -- >8 --\n> >\n> > diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> > index cbe36bf..84bd525 100755\n> > --- a/t/t3404-rebase-interactive.sh\n> > +++ b/t/t3404-rebase-interactive.sh\n> > @@ -947,7 +947,7 @@ test_expect_success 'rebase -i respects core.commentchar' '\n> >  \ttest_when_finished \"git config --unset core.commentchar\" &&\n> >  \tcat >comment-lines.sh <<EOF &&\n> >  #!$SHELL_PATH\n> > -sed -e \"2,\\$ s/^/\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n> > +sed -e \"2,\\$ s/^/\\\\\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n> >  mv \"\\$1\".tmp \"\\$1\"\n> >  EOF\n> >  \tchmod a+x comment-lines.sh &&\n> \n> Yeek.  If you used write_script with here-text that does not\n> interpolate,\n> \n> \twrite_script remove-all-but-the-first.sh <<\\EOF\n> \tsed -e '2,$s/^/\\\\/'  <\"$1\" >\"$1.tmp\" &&\n>         mv \"$1.tmp\" \"$1\"\n> \tEOF\n> \n> the above would be much more readable.\n\nYet another thing for me to learn about ;-)\n\nDo you mean to use that outside the test case, so that the single quotes\nwork?  Or do I still need some level of escaping?\n\n> I am not sure if I understand what you meant by \"literal backslash\n> blah blah\", though.\n\nIt turns out that having this in the script works (in bash and dash\nalthough I haven't checked what Posix has to say about it):\n\n    sed -e \"2,$ s/^/\\\\\\/\"\n\nand is equivalent to:\n\n    sed -e '2,$ s/^/\\\\/'\n\nbecause backslashes that aren't recognised as part of an escape sequence\nare not treated specially.\n\n\nJohn\n"},{"id":"209381","messageId":"7vvc9xh0p1.fsf@alter.siamese.dyndns.org","threadId":"32879","inReplyTo":"7v4nhhigp5.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] rebase -i: respect core.commentchar","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-02-12T18:00:26Z","receivedAt":"2013-02-12T18:00:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n>>  \tcat >comment-lines.sh <<EOF &&\n>>  #!$SHELL_PATH\n>> -sed -e \"2,\\$ s/^/\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n>> +sed -e \"2,\\$ s/^/\\\\\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n>>  mv \"\\$1\".tmp \"\\$1\"\n>>  EOF\n>>  \tchmod a+x comment-lines.sh &&\n>\n> Yeek.  If you used write_script with here-text that does not\n> interpolate,\n>\n> \twrite_script remove-all-but-the-first.sh <<\\EOF\n> \tsed -e '2,$s/^/\\\\/'  <\"$1\" >\"$1.tmp\" &&\n>         mv \"$1.tmp\" \"$1\"\n> \tEOF\n>\n> the above would be much more readable.\n\nAs this is already inside a pair of '', we cannot use single quote\naround sed expression without doing the ugly '\\''.\n\nSo it needs to be more like this, and I think it still is more\nreadable.\n\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex cbe36bf..8b3e2cd 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -945,13 +945,11 @@ test_expect_success 'rebase -i respects core.commentchar' '\n \tgit checkout E^0 &&\n \tgit config core.commentchar \"\\\\\" &&\n \ttest_when_finished \"git config --unset core.commentchar\" &&\n-\tcat >comment-lines.sh <<EOF &&\n-#!$SHELL_PATH\n-sed -e \"2,\\$ s/^/\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n-mv \"\\$1\".tmp \"\\$1\"\n-EOF\n-\tchmod a+x comment-lines.sh &&\n-\ttest_set_editor \"$(pwd)/comment-lines.sh\" &&\n+\twrite_script remove-all-but-first.sh <<-\\EOF &&\n+\tsed -e \"2,\\$s/^/\\\\\\\\/\" \"$1\" >\"$1.tmp\" &&\n+\tmv \"$1.tmp\" \"$1\"\n+\tEOF\n+\ttest_set_editor \"$(pwd)/remove-all-but-first.sh\" &&\n \tgit rebase -i B &&\n \ttest B = $(git cat-file commit HEAD^ | sed -ne \\$p)\n '\n"},{"id":"209384","messageId":"20130212180917.GD13501@farnsworth.metanate.com","threadId":"32879","inReplyTo":"7vvc9xh0p1.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] rebase -i: respect core.commentchar","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-02-12T18:09:17Z","receivedAt":"2013-02-12T18:09:17Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Tue, Feb 12, 2013 at 10:00:26AM -0800, Junio C Hamano wrote:\n>\n> So it needs to be more like this, and I think it still is more\n> readable.\n\nAgreed.  Will you squash this in or do you want a re-roll?\n\n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index cbe36bf..8b3e2cd 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -945,13 +945,11 @@ test_expect_success 'rebase -i respects core.commentchar' '\n>  \tgit checkout E^0 &&\n>  \tgit config core.commentchar \"\\\\\" &&\n>  \ttest_when_finished \"git config --unset core.commentchar\" &&\n> -\tcat >comment-lines.sh <<EOF &&\n> -#!$SHELL_PATH\n> -sed -e \"2,\\$ s/^/\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n> -mv \"\\$1\".tmp \"\\$1\"\n> -EOF\n> -\tchmod a+x comment-lines.sh &&\n> -\ttest_set_editor \"$(pwd)/comment-lines.sh\" &&\n> +\twrite_script remove-all-but-first.sh <<-\\EOF &&\n> +\tsed -e \"2,\\$s/^/\\\\\\\\/\" \"$1\" >\"$1.tmp\" &&\n> +\tmv \"$1.tmp\" \"$1\"\n> +\tEOF\n> +\ttest_set_editor \"$(pwd)/remove-all-but-first.sh\" &&\n>  \tgit rebase -i B &&\n>  \ttest B = $(git cat-file commit HEAD^ | sed -ne \\$p)\n>  '\n"},{"id":"209385","messageId":"7vip5xgzp6.fsf@alter.siamese.dyndns.org","threadId":"32879","inReplyTo":"20130212175322.GC13501@farnsworth.metanate.com","subject":"Re: [PATCH v2] rebase -i: respect core.commentchar","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-02-12T18:21:57Z","receivedAt":"2013-02-12T18:21:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n>> I am not sure if I understand what you meant by \"literal backslash\n>> blah blah\", though.\n>\n> It turns out that having this in the script works (in bash and dash\n> although I haven't checked what Posix has to say about it):\n>\n>     sed -e \"2,$ s/^/\\\\\\/\"\n>\n> and is equivalent to:\n>\n>     sed -e '2,$ s/^/\\\\/'\n>\n> because backslashes that aren't recognised as part of an escape sequence\n> are not treated specially.\n\nThat's POSIX.  Inside a dq pair:\n\n        \\\n        The <backslash> shall retain its special meaning as an escape\n        character (see Escape Character (Backslash)) only when followed by\n        one of the following characters when considered special:\n        $   `   \"   \\   <newline>\n\nSo in your example \"\\\\\\/\", the first backslash escapes the second\nbackslash and together they produce a single backslash, the third\nbackslash is followed by a slash that is not special at all, so it\nproduces a second backslash, and the slash stands for itself,\nresulting in \"\\\\/\".\n"},{"id":"209386","messageId":"7vehglgzmz.fsf@alter.siamese.dyndns.org","threadId":"32879","inReplyTo":"20130212180917.GD13501@farnsworth.metanate.com","subject":"Re: [PATCH v2] rebase -i: respect core.commentchar","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-02-12T18:23:16Z","receivedAt":"2013-02-12T18:23:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n> On Tue, Feb 12, 2013 at 10:00:26AM -0800, Junio C Hamano wrote:\n>>\n>> So it needs to be more like this, and I think it still is more\n>> readable.\n>\n> Agreed.  Will you squash this in or do you want a re-roll?\n\nI can squash this and the previous one into your original to a\nsingle commit.  Thanks.\n\n>\n>> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n>> index cbe36bf..8b3e2cd 100755\n>> --- a/t/t3404-rebase-interactive.sh\n>> +++ b/t/t3404-rebase-interactive.sh\n>> @@ -945,13 +945,11 @@ test_expect_success 'rebase -i respects core.commentchar' '\n>>  \tgit checkout E^0 &&\n>>  \tgit config core.commentchar \"\\\\\" &&\n>>  \ttest_when_finished \"git config --unset core.commentchar\" &&\n>> -\tcat >comment-lines.sh <<EOF &&\n>> -#!$SHELL_PATH\n>> -sed -e \"2,\\$ s/^/\\\\\\\\\\\\/\" \"\\$1\" >\"\\$1\".tmp\n>> -mv \"\\$1\".tmp \"\\$1\"\n>> -EOF\n>> -\tchmod a+x comment-lines.sh &&\n>> -\ttest_set_editor \"$(pwd)/comment-lines.sh\" &&\n>> +\twrite_script remove-all-but-first.sh <<-\\EOF &&\n>> +\tsed -e \"2,\\$s/^/\\\\\\\\/\" \"$1\" >\"$1.tmp\" &&\n>> +\tmv \"$1.tmp\" \"$1\"\n>> +\tEOF\n>> +\ttest_set_editor \"$(pwd)/remove-all-but-first.sh\" &&\n>>  \tgit rebase -i B &&\n>>  \ttest B = $(git cat-file commit HEAD^ | sed -ne \\$p)\n>>  '\n"}]}