diff mbox series

[v3,GSOC] cherry-pick: use better advice message

Message ID pull.1010.v3.git.1628142482640.gitgitgadget@gmail.com (mailing list archive)
State Superseded
Headers show
Series [v3,GSOC] cherry-pick: use better advice message | expand

Commit Message

ZheNing Hu Aug. 5, 2021, 5:48 a.m. UTC
From: ZheNing Hu <adlternative@gmail.com>

In the past, git cherry-pick would print such advice when
there was a conflict:

hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

But in fact, when we want to cherry-pick multiple commits,
we should not use "git commit" after resolving conflicts, which
will make Git generate some errors. We should recommend users to
use `git cherry-pick --continue`, `git cherry-pick --abort`, just
like git rebase does.

This is the improved advice:

hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit: run "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".

It is worth mentioning that now we use advice() to print the content
of GIT_CHERRY_PICK_HELP in print_advice(), each line of output will
start with "hint: ".

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by Hariom Verma <hariom18599@gmail.com>:
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Hepled-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
---
    [GSOC] cherry-pick: use better advice message
    
    Because git cherry-pick's past advice message is not good enough, it
    often misleads new users of Git, so this patch makes git chery-pick
    advice message better.
    
    v5:
    https://lore.kernel.org/git/pull.1010.git.1627714877.gitgitgadget@gmail.com/
    
    v5-->v6:
    
     1. Deleted the first patch, which could have made git cherry-pick not
        delete CHERRY_PICK_HEAD when using GIT_CHERRY_PICK_HELP, but both
        Junio and Phillip believe that this design does not need to be
        changed.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1010%2Fadlternative%2Fcherry-pick-help-fix-3-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1010/adlternative/cherry-pick-help-fix-3-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/1010

Range-diff vs v2:

 1:  5d2fd55c580 < -:  ----------- [GSOC] cherry-pick: fix bug when used with GIT_CHERRY_PICK_HELP
 2:  5279bca7a79 ! 1:  701645dde17 [GSOC] cherry-pick: use better advice message
     @@ Commit message
          hint: To abort and get back to the state before "git cherry-pick",
          hint: run "git cherry-pick --abort".
      
     +    It is worth mentioning that now we use advice() to print the content
     +    of GIT_CHERRY_PICK_HELP in print_advice(), each line of output will
     +    start with "hint: ".
     +
          Mentored-by: Christian Couder <christian.couder@gmail.com>
          Mentored-by Hariom Verma <hariom18599@gmail.com>:
          Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
     @@ Commit message
          Signed-off-by: ZheNing Hu <adlternative@gmail.com>
      
       ## sequencer.c ##
     -@@ sequencer.c: static void print_advice(struct replay_opts *opts, int show_hint)
     +@@ sequencer.c: static void print_advice(struct repository *r, int show_hint,
     + 	char *msg = getenv("GIT_CHERRY_PICK_HELP");
     + 
       	if (msg) {
     - 		advise("%s\n", msg);
     - 	} else if (show_hint) {
     +-		fprintf(stderr, "%s\n", msg);
     ++		advise("%s\n", msg);
     + 		/*
     + 		 * A conflict has occurred but the porcelain
     + 		 * (typically rebase --interactive) wants to take care
     +@@ sequencer.c: static void print_advice(struct repository *r, int show_hint,
     + 	}
     + 
     + 	if (show_hint) {
      -		if (opts->no_commit)
      +		if (opts->action == REPLAY_PICK) {
      +			advise(_("Resolve all conflicts manually, mark them as resolved with\n"
     @@ sequencer.c: static void print_advice(struct replay_opts *opts, int show_hint)
      +				 "You can instead skip this commit: run \"git cherry-pick --skip\".\n"
      +				 "To abort and get back to the state before \"git cherry-pick\",\n"
      +				 "run \"git cherry-pick --abort\"."));
     -+
      +		} else if (opts->no_commit)
       			advise(_("after resolving the conflicts, mark the corrected paths\n"
       				 "with 'git add <paths>' or 'git rm <paths>'"));


 sequencer.c                     | 11 +++++++++--
 t/t3507-cherry-pick-conflict.sh | 17 ++++++++++++-----
 2 files changed, 21 insertions(+), 7 deletions(-)


base-commit: daab8a564f8bbac55f70f8bf86c070e001a9b006

Comments

Phillip Wood Aug. 11, 2021, 10 a.m. UTC | #1
On 05/08/2021 06:48, ZheNing Hu via GitGitGadget wrote:
> From: ZheNing Hu <adlternative@gmail.com>
> [...]
>   sequencer.c                     | 11 +++++++++--
>   t/t3507-cherry-pick-conflict.sh | 17 ++++++++++++-----
>   2 files changed, 21 insertions(+), 7 deletions(-)
> 
> diff --git a/sequencer.c b/sequencer.c
> index 0bec01cf38e..7fa91b99870 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -403,7 +403,7 @@ static void print_advice(struct repository *r, int show_hint,
>   	char *msg = getenv("GIT_CHERRY_PICK_HELP");
>   
>   	if (msg) {
> -		fprintf(stderr, "%s\n", msg);
> +		advise("%s\n", msg);
>   		/*
>   		 * A conflict has occurred but the porcelain
>   		 * (typically rebase --interactive) wants to take care
> @@ -415,7 +415,14 @@ static void print_advice(struct repository *r, int show_hint,
>   	}
>   
>   	if (show_hint) {
> -		if (opts->no_commit)
> +		if (opts->action == REPLAY_PICK) {

This changes means we give the wrong advice for 'git cherry-pick 
--no-commit'. I think you want to keep the existing clause as the first 
one and insert this before the else. The advice itself looks good. It 
would be nice to improve the advice for 'git revert' in the same way.

> +			advise(_("Resolve all conflicts manually, mark them as resolved with\n"
> +				 "\"git add/rm <conflicted_files>\", then run\n"
> +				 "\"git cherry-pick --continue\".\n"
> +				 "You can instead skip this commit: run \"git cherry-pick --skip\".\n"
> +				 "To abort and get back to the state before \"git cherry-pick\",\n"
> +				 "run \"git cherry-pick --abort\"."));
> +		} else if (opts->no_commit)
>   			advise(_("after resolving the conflicts, mark the corrected paths\n"
>   				 "with 'git add <paths>' or 'git rm <paths>'"));
>   		else
> diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
> index 014001b8f32..d3ed9d7ce0d 100755
> --- a/t/t3507-cherry-pick-conflict.sh
> +++ b/t/t3507-cherry-pick-conflict.sh
> @@ -53,9 +53,12 @@ test_expect_success 'advice from failed cherry-pick' "
>   	picked=\$(git rev-parse --short picked) &&
>   	cat <<-EOF >expected &&

If you quote the here doc end marker then there is no substitution in 
the here doc so writing

	cat <<-\EOF >expected &&

>   	error: could not apply \$picked... picked
> -	hint: after resolving the conflicts, mark the corrected paths
> -	hint: with 'git add <paths>' or 'git rm <paths>'
> -	hint: and commit the result with 'git commit'
> +	hint: Resolve all conflicts manually, mark them as resolved with
> +	hint: \"git add/rm <conflicted_files>\", then run

means you can replace \" with " here

Best Wishes

Phillip

> +	hint: \"git cherry-pick --continue\".
> +	hint: You can instead skip this commit: run \"git cherry-pick --skip\".
> +	hint: To abort and get back to the state before \"git cherry-pick\",
> +	hint: run \"git cherry-pick --abort\".
>   	EOF
>   	test_must_fail git cherry-pick picked 2>actual &&
>   
> @@ -68,8 +71,12 @@ test_expect_success 'advice from failed cherry-pick --no-commit' "
>   	picked=\$(git rev-parse --short picked) &&
>   	cat <<-EOF >expected &&
>   	error: could not apply \$picked... picked
> -	hint: after resolving the conflicts, mark the corrected paths
> -	hint: with 'git add <paths>' or 'git rm <paths>'
> +	hint: Resolve all conflicts manually, mark them as resolved with
> +	hint: \"git add/rm <conflicted_files>\", then run
> +	hint: \"git cherry-pick --continue\".
> +	hint: You can instead skip this commit: run \"git cherry-pick --skip\".
> +	hint: To abort and get back to the state before \"git cherry-pick\",
> +	hint: run \"git cherry-pick --abort\".
>   	EOF
>   	test_must_fail git cherry-pick --no-commit picked 2>actual &&
>   
> 
> base-commit: daab8a564f8bbac55f70f8bf86c070e001a9b006
>
ZheNing Hu Aug. 13, 2021, 8:08 a.m. UTC | #2
Hi,
sorry for the late reply, I am busy processing the patches on the
ref-filter side.

Phillip Wood <phillip.wood123@gmail.com> 于2021年8月11日周三 下午6:00写道:
>
> On 05/08/2021 06:48, ZheNing Hu via GitGitGadget wrote:
> > From: ZheNing Hu <adlternative@gmail.com>
> > [...]
> >   sequencer.c                     | 11 +++++++++--
> >   t/t3507-cherry-pick-conflict.sh | 17 ++++++++++++-----
> >   2 files changed, 21 insertions(+), 7 deletions(-)
> >
> > diff --git a/sequencer.c b/sequencer.c
> > index 0bec01cf38e..7fa91b99870 100644
> > --- a/sequencer.c
> > +++ b/sequencer.c
> > @@ -403,7 +403,7 @@ static void print_advice(struct repository *r, int show_hint,
> >       char *msg = getenv("GIT_CHERRY_PICK_HELP");
> >
> >       if (msg) {
> > -             fprintf(stderr, "%s\n", msg);
> > +             advise("%s\n", msg);
> >               /*
> >                * A conflict has occurred but the porcelain
> >                * (typically rebase --interactive) wants to take care
> > @@ -415,7 +415,14 @@ static void print_advice(struct repository *r, int show_hint,
> >       }
> >
> >       if (show_hint) {
> > -             if (opts->no_commit)
> > +             if (opts->action == REPLAY_PICK) {
>
> This changes means we give the wrong advice for 'git cherry-pick
> --no-commit'. I think you want to keep the existing clause as the first
> one and insert this before the else. The advice itself looks good. It
> would be nice to improve the advice for 'git revert' in the same way.
>

Make sense.

> > +                     advise(_("Resolve all conflicts manually, mark them as resolved with\n"
> > +                              "\"git add/rm <conflicted_files>\", then run\n"
> > +                              "\"git cherry-pick --continue\".\n"
> > +                              "You can instead skip this commit: run \"git cherry-pick --skip\".\n"
> > +                              "To abort and get back to the state before \"git cherry-pick\",\n"
> > +                              "run \"git cherry-pick --abort\"."));
> > +             } else if (opts->no_commit)
> >                       advise(_("after resolving the conflicts, mark the corrected paths\n"
> >                                "with 'git add <paths>' or 'git rm <paths>'"));
> >               else
> > diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
> > index 014001b8f32..d3ed9d7ce0d 100755
> > --- a/t/t3507-cherry-pick-conflict.sh
> > +++ b/t/t3507-cherry-pick-conflict.sh
> > @@ -53,9 +53,12 @@ test_expect_success 'advice from failed cherry-pick' "
> >       picked=\$(git rev-parse --short picked) &&
> >       cat <<-EOF >expected &&
>
> If you quote the here doc end marker then there is no substitution in
> the here doc so writing
>
>         cat <<-\EOF >expected &&
>
> >       error: could not apply \$picked... picked
> > -     hint: after resolving the conflicts, mark the corrected paths
> > -     hint: with 'git add <paths>' or 'git rm <paths>'
> > -     hint: and commit the result with 'git commit'
> > +     hint: Resolve all conflicts manually, mark them as resolved with
> > +     hint: \"git add/rm <conflicted_files>\", then run
>
> means you can replace \" with " here
>

Thanks, I haven't paid attention to this detail before.

> Best Wishes
>
> Phillip
>

Thanks,
--
ZheNing Hu
Junio C Hamano Aug. 13, 2021, 8:14 p.m. UTC | #3
Phillip Wood <phillip.wood123@gmail.com> writes:

>> +++ b/t/t3507-cherry-pick-conflict.sh
>> @@ -53,9 +53,12 @@ test_expect_success 'advice from failed cherry-pick' "
>>   	picked=\$(git rev-parse --short picked) &&
>>   	cat <<-EOF >expected &&
>
> If you quote the here doc end marker then there is no substitution in
> the here doc so writing
>
> 	cat <<-\EOF >expected &&
>
>>   	error: could not apply \$picked... picked
>> -	hint: after resolving the conflicts, mark the corrected paths
>> -	hint: with 'git add <paths>' or 'git rm <paths>'
>> -	hint: and commit the result with 'git commit'
>> +	hint: Resolve all conflicts manually, mark them as resolved with
>> +	hint: \"git add/rm <conflicted_files>\", then run
>
> means you can replace \" with " here

Hmph, actually the double-quote that opens the body of
test_expect_success should be stared at with a very cautious eyes,
as they often do not mean what the author of the patch thought they
do.  I can see that it already fooled your eyes into thinking that
there is no substitution, but $picked needs to be substituted into
its value.  The backslash before it is *not* about guarding it from
substitution inside here-doc; it is to pass literal "$" into the
string, which is the last parameter to test_expect_success, that
gets eval'ed.

The original of this one, for example, would probably have been
better if written like so:

test_expect_success 'advice from failed cherry-pick' '
	pristine_detach initial &&
	SQ='\'' &&

	picked=$(git rev-parse --short picked) &&
	cat <<-EOF >expected &&
	error: could not apply $picked... picked
	hint: after resolving the conflicts, mark the corrected paths
	hint: with ${SQ}git add <paths>${SQ} or ${SQ}git rm <paths>${SQ}
	hint: and commit the result with ${SQ}git commit${SQ}
	EOF
	test_must_fail git cherry-pick picked 2>actual &&

	test_cmp expected actual
'

And because there is no single quote in the updated text, it would
become:

test_expect_success 'advice from failed cherry-pick' '
	pristine_detach initial &&

	picked=$(git rev-parse --short picked) &&
	cat <<-EOF >expected &&
	error: could not apply $picked... picked
	hint: Resolve all conflicts manually, mark them as resolved with
	hint: "git add/rm <conflicted_files>", then run
	EOF
	test_must_fail git cherry-pick picked 2>actual &&

	test_cmp expected actual
'

which makes it far easier to see that $picked needs to be
substituted, and the "git add/rm" are to be enclosed in dq pair.
ZheNing Hu Aug. 14, 2021, 2:07 a.m. UTC | #4
Junio C Hamano <gitster@pobox.com> 于2021年8月14日周六 上午4:14写道:
>
> Phillip Wood <phillip.wood123@gmail.com> writes:
>
> >> +++ b/t/t3507-cherry-pick-conflict.sh
> >> @@ -53,9 +53,12 @@ test_expect_success 'advice from failed cherry-pick' "
> >>      picked=\$(git rev-parse --short picked) &&
> >>      cat <<-EOF >expected &&
> >
> > If you quote the here doc end marker then there is no substitution in
> > the here doc so writing
> >
> >       cat <<-\EOF >expected &&
> >
> >>      error: could not apply \$picked... picked
> >> -    hint: after resolving the conflicts, mark the corrected paths
> >> -    hint: with 'git add <paths>' or 'git rm <paths>'
> >> -    hint: and commit the result with 'git commit'
> >> +    hint: Resolve all conflicts manually, mark them as resolved with
> >> +    hint: \"git add/rm <conflicted_files>\", then run
> >
> > means you can replace \" with " here
>
> Hmph, actually the double-quote that opens the body of
> test_expect_success should be stared at with a very cautious eyes,
> as they often do not mean what the author of the patch thought they
> do.  I can see that it already fooled your eyes into thinking that
> there is no substitution, but $picked needs to be substituted into
> its value.  The backslash before it is *not* about guarding it from
> substitution inside here-doc; it is to pass literal "$" into the
> string, which is the last parameter to test_expect_success, that
> gets eval'ed.
>

Yes, the escaping here comes from double-quote of test_expect_success
instead of here-doc.

> The original of this one, for example, would probably have been
> better if written like so:
>
> test_expect_success 'advice from failed cherry-pick' '
>         pristine_detach initial &&
>         SQ='\'' &&
>
>         picked=$(git rev-parse --short picked) &&
>         cat <<-EOF >expected &&
>         error: could not apply $picked... picked
>         hint: after resolving the conflicts, mark the corrected paths
>         hint: with ${SQ}git add <paths>${SQ} or ${SQ}git rm <paths>${SQ}
>         hint: and commit the result with ${SQ}git commit${SQ}
>         EOF
>         test_must_fail git cherry-pick picked 2>actual &&
>
>         test_cmp expected actual
> '
>

Um? This section is not working for me.

./test-lib.sh: eval: line 917: unexpected EOF while looking for matching `''
./test-lib.sh: eval: line 932: syntax error: unexpected end of file

> And because there is no single quote in the updated text, it would
> become:
>
> test_expect_success 'advice from failed cherry-pick' '
>         pristine_detach initial &&
>
>         picked=$(git rev-parse --short picked) &&
>         cat <<-EOF >expected &&
>         error: could not apply $picked... picked
>         hint: Resolve all conflicts manually, mark them as resolved with
>         hint: "git add/rm <conflicted_files>", then run
>         EOF
>         test_must_fail git cherry-pick picked 2>actual &&
>
>         test_cmp expected actual
> '
>
> which makes it far easier to see that $picked needs to be
> substituted, and the "git add/rm" are to be enclosed in dq pair.

This section is exactly what I want. Using single quotes does make it
look a lot easier.

--
ZheNing Hu
Phillip Wood Aug. 17, 2021, 10:09 a.m. UTC | #5
On 13/08/2021 21:14, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>>> +++ b/t/t3507-cherry-pick-conflict.sh
>>> @@ -53,9 +53,12 @@ test_expect_success 'advice from failed cherry-pick' "
>>>    	picked=\$(git rev-parse --short picked) &&
>>>    	cat <<-EOF >expected &&
>>
>> If you quote the here doc end marker then there is no substitution in
>> the here doc so writing
>>
>> 	cat <<-\EOF >expected &&
>>
>>>    	error: could not apply \$picked... picked
>>> -	hint: after resolving the conflicts, mark the corrected paths
>>> -	hint: with 'git add <paths>' or 'git rm <paths>'
>>> -	hint: and commit the result with 'git commit'
>>> +	hint: Resolve all conflicts manually, mark them as resolved with
>>> +	hint: \"git add/rm <conflicted_files>\", then run
>>
>> means you can replace \" with " here
> 
> Hmph, actually the double-quote that opens the body of
> test_expect_success should be stared at with a very cautious eyes,
> as they often do not mean what the author of the patch thought they
> do.  I can see that it already fooled your eyes into thinking that
> there is no substitution, but $picked needs to be substituted into
> its value.  The backslash before it is *not* about guarding it from
> substitution inside here-doc; it is to pass literal "$" into the
> string, which is the last parameter to test_expect_success, that
> gets eval'ed.

Good point, you're right I had completely missed that, thanks for 
pointing it out

Phillip

> 
> The original of this one, for example, would probably have been
> better if written like so:
> 
> test_expect_success 'advice from failed cherry-pick' '
> 	pristine_detach initial &&
> 	SQ='\'' &&
> 
> 	picked=$(git rev-parse --short picked) &&
> 	cat <<-EOF >expected &&
> 	error: could not apply $picked... picked
> 	hint: after resolving the conflicts, mark the corrected paths
> 	hint: with ${SQ}git add <paths>${SQ} or ${SQ}git rm <paths>${SQ}
> 	hint: and commit the result with ${SQ}git commit${SQ}
> 	EOF
> 	test_must_fail git cherry-pick picked 2>actual &&
> 
> 	test_cmp expected actual
> '
> 
> And because there is no single quote in the updated text, it would
> become:
> 
> test_expect_success 'advice from failed cherry-pick' '
> 	pristine_detach initial &&
> 
> 	picked=$(git rev-parse --short picked) &&
> 	cat <<-EOF >expected &&
> 	error: could not apply $picked... picked
> 	hint: Resolve all conflicts manually, mark them as resolved with
> 	hint: "git add/rm <conflicted_files>", then run
> 	EOF
> 	test_must_fail git cherry-pick picked 2>actual &&
> 
> 	test_cmp expected actual
> '
> 
> which makes it far easier to see that $picked needs to be
> substituted, and the "git add/rm" are to be enclosed in dq pair.
>
diff mbox series

Patch

diff --git a/sequencer.c b/sequencer.c
index 0bec01cf38e..7fa91b99870 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -403,7 +403,7 @@  static void print_advice(struct repository *r, int show_hint,
 	char *msg = getenv("GIT_CHERRY_PICK_HELP");
 
 	if (msg) {
-		fprintf(stderr, "%s\n", msg);
+		advise("%s\n", msg);
 		/*
 		 * A conflict has occurred but the porcelain
 		 * (typically rebase --interactive) wants to take care
@@ -415,7 +415,14 @@  static void print_advice(struct repository *r, int show_hint,
 	}
 
 	if (show_hint) {
-		if (opts->no_commit)
+		if (opts->action == REPLAY_PICK) {
+			advise(_("Resolve all conflicts manually, mark them as resolved with\n"
+				 "\"git add/rm <conflicted_files>\", then run\n"
+				 "\"git cherry-pick --continue\".\n"
+				 "You can instead skip this commit: run \"git cherry-pick --skip\".\n"
+				 "To abort and get back to the state before \"git cherry-pick\",\n"
+				 "run \"git cherry-pick --abort\"."));
+		} else if (opts->no_commit)
 			advise(_("after resolving the conflicts, mark the corrected paths\n"
 				 "with 'git add <paths>' or 'git rm <paths>'"));
 		else
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index 014001b8f32..d3ed9d7ce0d 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -53,9 +53,12 @@  test_expect_success 'advice from failed cherry-pick' "
 	picked=\$(git rev-parse --short picked) &&
 	cat <<-EOF >expected &&
 	error: could not apply \$picked... picked
-	hint: after resolving the conflicts, mark the corrected paths
-	hint: with 'git add <paths>' or 'git rm <paths>'
-	hint: and commit the result with 'git commit'
+	hint: Resolve all conflicts manually, mark them as resolved with
+	hint: \"git add/rm <conflicted_files>\", then run
+	hint: \"git cherry-pick --continue\".
+	hint: You can instead skip this commit: run \"git cherry-pick --skip\".
+	hint: To abort and get back to the state before \"git cherry-pick\",
+	hint: run \"git cherry-pick --abort\".
 	EOF
 	test_must_fail git cherry-pick picked 2>actual &&
 
@@ -68,8 +71,12 @@  test_expect_success 'advice from failed cherry-pick --no-commit' "
 	picked=\$(git rev-parse --short picked) &&
 	cat <<-EOF >expected &&
 	error: could not apply \$picked... picked
-	hint: after resolving the conflicts, mark the corrected paths
-	hint: with 'git add <paths>' or 'git rm <paths>'
+	hint: Resolve all conflicts manually, mark them as resolved with
+	hint: \"git add/rm <conflicted_files>\", then run
+	hint: \"git cherry-pick --continue\".
+	hint: You can instead skip this commit: run \"git cherry-pick --skip\".
+	hint: To abort and get back to the state before \"git cherry-pick\",
+	hint: run \"git cherry-pick --abort\".
 	EOF
 	test_must_fail git cherry-pick --no-commit picked 2>actual &&