cherry-pick: use better advice message

"git cherry-pick", upon seeing a conflict, says: 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' as if running "git commit" to conclude the resolution of this single step were the end of the story. This stems from the fact that the command originally was to pick a single commit and not a range of commits, and the message was written back then and has not been adjusted. When picking a range of commits and the command stops with a conflict in the middle of the range, however, after resolving the conflict and (optionally) recording the result with "git commit", the user has to run "git cherry-pick --continue" to have the rest of the range dealt with, "--skip" to drop the current commit, or "--abort" to discard the series. Suggest use of "git cherry-pick --continue/--skip/--abort" so that the message also covers the case where a range of commits are being picked. Similarly, this optimization can be applied to git revert, suggest use of "git revert --continue/--skip/--abort" so that the message also covers the case where a range of commits are being reverted. 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> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: ZheNing Hu <adlternative@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

ZheNing Hu committed Aug 22, 2021 at 13:08 UTC f172556b89822693cae70f87c73fe7b6a96b9855
3 files changed +42 -11
sequencer.c
+16 -4
@@ -403,7 +403,7 @@ static void print_advice(struct repository *r, int show_hint,
403 char *msg = getenv("GIT_CHERRY_PICK_HELP");
404
405 if (msg) {
406 - fprintf(stderr, "%s\n", msg);
406 + advise("%s\n", msg);
407 /*
408 * A conflict has occurred but the porcelain
409 * (typically rebase --interactive) wants to take care
@@ -418,10 +418,22 @@ static void print_advice(struct repository *r, int show_hint,
418 if (opts->no_commit)
419 advise(_("after resolving the conflicts, mark the corrected paths\n"
420 "with 'git add <paths>' or 'git rm <paths>'"));
421 + else if (opts->action == REPLAY_PICK)
422 + advise(_("After resolving the conflicts, mark them with\n"
423 + "\"git add/rm <pathspec>\", then run\n"
424 + "\"git cherry-pick --continue\".\n"
425 + "You can instead skip this commit with \"git cherry-pick --skip\".\n"
426 + "To abort and get back to the state before \"git cherry-pick\",\n"
427 + "run \"git cherry-pick --abort\"."));
428 + else if (opts->action == REPLAY_REVERT)
429 + advise(_("After resolving the conflicts, mark them with\n"
430 + "\"git add/rm <pathspec>\", then run\n"
431 + "\"git revert --continue\".\n"
432 + "You can instead skip this commit with \"git revert --skip\".\n"
433 + "To abort and get back to the state before \"git revert\",\n"
434 + "run \"git revert --abort\"."));
435 else
422 - advise(_("after resolving the conflicts, mark the corrected paths\n"
423 - "with 'git add <paths>' or 'git rm <paths>'\n"
424 - "and commit the result with 'git commit'"));
436 + BUG("unexpected pick action in print_advice()");
437 }
438 }
439
t/t3501-revert-cherry-pick.sh
+16
@@ -158,4 +158,20 @@ test_expect_success 'cherry-pick works with dirty renamed file' '
158 grep -q "^modified$" renamed
159 '
160
161 +test_expect_success 'advice from failed revert' '
162 + test_commit --no-tag "add dream" dream dream &&
163 + dream_oid=$(git rev-parse --short HEAD) &&
164 + cat <<-EOF >expected &&
165 + error: could not revert $dream_oid... add dream
166 + hint: After resolving the conflicts, mark them with
167 + hint: "git add/rm <pathspec>", then run
168 + hint: "git revert --continue".
169 + hint: You can instead skip this commit with "git revert --skip".
170 + hint: To abort and get back to the state before "git revert",
171 + hint: run "git revert --abort".
172 + EOF
173 + test_commit --append --no-tag "double-add dream" dream dream &&
174 + test_must_fail git revert HEAD^ 2>actual &&
175 + test_cmp expected actual
176 +'
177 test_done
t/t3507-cherry-pick-conflict.sh
+10 -7
@@ -47,20 +47,23 @@ test_expect_success 'failed cherry-pick does not advance HEAD' '
47 test "$head" = "$newhead"
48 '
49
50 -test_expect_success 'advice from failed cherry-pick' "
50 +test_expect_success 'advice from failed cherry-pick' '
51 pristine_detach initial &&
52
53 - picked=\$(git rev-parse --short picked) &&
53 + picked=$(git rev-parse --short picked) &&
54 cat <<-EOF >expected &&
55 - error: could not apply \$picked... picked
56 - hint: after resolving the conflicts, mark the corrected paths
57 - hint: with 'git add <paths>' or 'git rm <paths>'
58 - hint: and commit the result with 'git commit'
55 + error: could not apply $picked... picked
56 + hint: After resolving the conflicts, mark them with
57 + hint: "git add/rm <pathspec>", then run
58 + hint: "git cherry-pick --continue".
59 + hint: You can instead skip this commit with "git cherry-pick --skip".
60 + hint: To abort and get back to the state before "git cherry-pick",
61 + hint: run "git cherry-pick --abort".
62 EOF
63 test_must_fail git cherry-pick picked 2>actual &&
64
65 test_cmp expected actual
63 -"
66 +'
67
68 test_expect_success 'advice from failed cherry-pick --no-commit' "
69 pristine_detach initial &&