sequencer: allow disabling conflict advice
PATCH 1/1 sequencer: allow disabling conflict advice
From: Philippe Blain <[email protected]>
Allow disabling the advice shown when a squencer operation results in a merge conflict through a new config 'advice.sequencerConflict'.
Update the tests accordingly. Note that the body of the second test in t3507-cherry-pick-conflict.sh is enclosed in double quotes, so we must escape them in the added line.
---
sequencer: allow disabling conflict advice
CC: Elijah Newren [email protected] CC: Phillip Wood [email protected] CC: Johannes Schindelin [email protected] CC: ZheNing Hu [email protected]
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1682%2Fphil-blain%2Fsequencer-conflict-advice-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1682/phil-blain/sequencer-conflict-advice-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1682
Documentation/config/advice.txt | 3 +++ advice.c | 1 + advice.h | 1 + sequencer.c | 33 ++++++++++++++++++--------------- t/t3501-revert-cherry-pick.sh | 1 + t/t3507-cherry-pick-conflict.sh | 2 ++ 6 files changed, 26 insertions(+), 15 deletions(-)
Documentation/config/advice.txt +3 -0
@@ -104,6 +104,9 @@ advice.*:: rmHints:: In case of failure in the output of linkgit:git-rm[1], show directions on how to proceed from the current state. + sequencerConflict:: + Advice shown when a sequencer operation stops because + of conflicts. sequencerInUse:: Advice shown when a sequencer command is already in progress. skippedCherryPicks::
advice.c +1 -0
@@ -71,6 +71,7 @@ static struct { [ADVICE_RESET_NO_REFRESH_WARNING] = { "resetNoRefresh" }, [ADVICE_RESOLVE_CONFLICT] = { "resolveConflict" }, [ADVICE_RM_HINTS] = { "rmHints" }, + [ADVICE_SEQUENCER_CONFLICT] = { "sequencerConflict" }, [ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse" }, [ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure" }, [ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks" },
advice.h +1 -0
@@ -40,6 +40,7 @@ enum advice_type {ADVICE_RESOLVE_CONFLICT ,ADVICE_RM_HINTS ,ADVICE_SEQUENCER_IN_USE , +ADVICE_SEQUENCER_CONFLICT ,ADVICE_SET_UPSTREAM_FAILURE ,ADVICE_SKIPPED_CHERRY_PICKS , ADVICE_STATUS_AHEAD_BEHIND_WARNING,
sequencer.c +18 -15
@@ -467,7 +467,7 @@ static void print_advice(struct repository *r, int show_hint,char *msg =getenv ("GIT_CHERRY_PICK_HELP" );if (msg) { -advise ("%s\n" , msg); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT ,"%s\n" , msg);/* * A conflict has occurred but the porcelain * (typically rebase --interactive) wants to take care
@@ -480,22 +480,25 @@ static void print_advice(struct repository *r, int show_hint,if (show_hint) {if (opts->no_commit) -advise (_ ("after resolving the conflicts, mark the corrected paths\n" -"with 'git add <paths>' or 'git rm <paths>'" )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("after resolving the conflicts, mark the corrected paths\n" +"with 'git add <paths>' or 'git rm <paths>'" ));else if (opts->action ==REPLAY_PICK ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git cherry-pick --continue\".\n" -"You can instead skip this commit with \"git cherry-pick --skip\".\n" -"To abort and get back to the state before \"git cherry-pick\",\n" -"run \"git cherry-pick --abort\"." )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git cherry-pick --continue\".\n" +"You can instead skip this commit with \"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->action ==REPLAY_REVERT ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git revert --continue\".\n" -"You can instead skip this commit with \"git revert --skip\".\n" -"To abort and get back to the state before \"git revert\",\n" -"run \"git revert --abort\"." )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git revert --continue\".\n" +"You can instead skip this commit with \"git revert --skip\".\n" +"To abort and get back to the state before \"git revert\",\n" +"run \"git revert --abort\"." ));else BUG ("unexpected pick action in print_advice()" ); }
t/t3501-revert-cherry-pick.sh +1 -0
@@ -170,6 +170,7 @@ test_expect_success 'advice from failed revert' ' hint: You can instead skip this commit with "git revert --skip". hint: To abort and get back to the state before "git revert", hint: run "git revert --abort". + hint: Disable this message with "git config advice.sequencerConflict false" EOF test_commit --append --no-tag "double-add dream" dream dream && test_must_fail git revert HEAD^ 2>actual &&
t/t3507-cherry-pick-conflict.sh +2 -0
@@ -60,6 +60,7 @@ test_expect_success 'advice from failed cherry-pick' ' hint: You can instead skip this commit with "git cherry-pick --skip". hint: To abort and get back to the state before "git cherry-pick", hint: run "git cherry-pick --abort". + hint: Disable this message with "git config advice.sequencerConflict false" EOF test_must_fail git cherry-pick picked 2>actual &&
@@ -74,6 +75,7 @@ test_expect_success 'advice from failed cherry-pick --no-commit' " 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: Disable this message with \"git config advice.sequencerConflict false\" EOF test_must_fail git cherry-pick --no-commit picked 2>actual &&
base-commit: 0f9d4d28b7e6021b7e6db192b7bf47bd3a0d0d1d
Signature · 1 line
gitgitgadget
Hi,
Le 2024-03-02 à 11:18, Philippe Blain via GitGitGadget a écrit :
Quoted 10 lines
From: Philippe Blain <[email protected]>
Allow disabling the advice shown when a squencer operation results in a merge conflict through a new config 'advice.sequencerConflict'.
Update the tests accordingly. Note that the body of the second test in
t3507-cherry-pick-conflict.shis enclosed in double quotes, so we must escape them in the added line.Signed-off-by Philippe Blain <[email protected]>
I meant to CC your addresses in https://lore.kernel.org/git/[email protected]/
which I'm responding to, but the CC's did not get through somehow.
Cheers,
Philippe.
sequencer.c static void print_advice(struct repository *r, int show_hint, · line 473
Quoted 6 lines · Philippe Blain via GitGitGadget
sequencer.c +1
-1if (msg) { -advise ("%s\n" , msg); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT ,"%s\n" , msg);/* * A conflict has occurred but the porcelain * (typically rebase --interactive) wants to take care
This hunk is good. The block removes the CHERRY_PICK_HEAD after giving this advice and then returns.
Quoted 30 lines
sequencer.c +10
-14@@ -480,22 +480,25 @@ static void print_advice(struct repository *r, int show_hint,if (show_hint) {if (opts->no_commit) -advise (_ ("after resolving the conflicts, mark the corrected paths\n" -"with 'git add <paths>' or 'git rm <paths>'" )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("after resolving the conflicts, mark the corrected paths\n" +"with 'git add <paths>' or 'git rm <paths>'" ));else if (opts->action ==REPLAY_PICK ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git cherry-pick --continue\".\n" -"You can instead skip this commit with \"git cherry-pick --skip\".\n" -"To abort and get back to the state before \"git cherry-pick\",\n" -"run \"git cherry-pick --abort\"." )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git cherry-pick --continue\".\n" +"You can instead skip this commit with \"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->action ==REPLAY_REVERT ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git revert --continue\".\n" -"You can instead skip this commit with \"git revert --skip\".\n" -"To abort and get back to the state before \"git revert\",\n" -"run \"git revert --abort\"." ));
sequencer.c static void print_advice(struct repository *r, int show_hint, · line 504
Quoted 10 lines
sequencer.c +7
-0+advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git revert --continue\".\n" +"You can instead skip this commit with \"git revert --skip\".\n" +"To abort and get back to the state before \"git revert\",\n" +"run \"git revert --abort\"." )); else BUG("unexpected pick action in print_advice()"); }
This hunk can be improved. If I were doing this patch, I probably would have just done
- if (show_hint) {
+ if (show_hint && advice_enabled(ADVICE_SEQUENCER_CONFLICT)) {
and nothing else, and doing so would keep the block easier to extend and maintain in the future.
Because the block is all about "show_hint", we have code to print advice messages and nothing else in it currently, and more importantly, we will not add anything other than code to print advice messages in it. Because of that, skipping everything when ADVICE_SEQUENCER_CONFLICT is not enabled will not cause problems (unlike the earlier hunk---which will break if we added "&& advice_enabled()" to "if (msg)"). That way, when somebody teaches this code a new kind of opts->action, they do not have to say "advice_if_enabled(ADVICE_SEQUENCER_CONFLICT()"; they can just use "advise()".
t/t3501-revert-cherry-pick.sh
Quoted 4 lines
t/t3501-revert-cherry-pick.sh +0
-0
All changes to the file look good.
Hi Junio,
Le 2024-03-03 à 17:57, Junio C Hamano a écrit :
Quoted 62 lines
sequencer.c static void print_advice(struct repository *r, int show_hint, · line 473
Quoted 6 lines · Philippe Blain via GitGitGadget
sequencer.c +1
-1if (msg) { -advise ("%s\n" , msg); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT ,"%s\n" , msg);/* * A conflict has occurred but the porcelain * (typically rebase --interactive) wants to take care This hunk is good. The block removes the
CHERRY_PICK_HEADafter giving this advice and then returns.Quoted 30 lines
sequencer.c +10
-14@@ -480,22 +480,25 @@ static void print_advice(struct repository *r, int show_hint,if (show_hint) {if (opts->no_commit) -advise (_ ("after resolving the conflicts, mark the corrected paths\n" -"with 'git add <paths>' or 'git rm <paths>'" )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("after resolving the conflicts, mark the corrected paths\n" +"with 'git add <paths>' or 'git rm <paths>'" ));else if (opts->action ==REPLAY_PICK ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git cherry-pick --continue\".\n" -"You can instead skip this commit with \"git cherry-pick --skip\".\n" -"To abort and get back to the state before \"git cherry-pick\",\n" -"run \"git cherry-pick --abort\"." )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git cherry-pick --continue\".\n" +"You can instead skip this commit with \"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->action ==REPLAY_REVERT ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git revert --continue\".\n" -"You can instead skip this commit with \"git revert --skip\".\n" -"To abort and get back to the state before \"git revert\",\n" -"run \"git revert --abort\"." ));sequencer.c static void print_advice(struct repository *r, int show_hint, · line 504
Quoted 10 lines
sequencer.c +7
-0+advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git revert --continue\".\n" +"You can instead skip this commit with \"git revert --skip\".\n" +"To abort and get back to the state before \"git revert\",\n" +"run \"git revert --abort\"." )); else BUG("unexpected pick action in print_advice()"); }This hunk can be improved. If I were doing this patch, I probably would have just done
(quoted diff) +1
-1- if (show_hint) { + if (show_hint && advice_enabled(ADVICE_SEQUENCER_CONFLICT)) {and nothing else, and doing so would keep the block easier to extend and maintain in the future.
Quoted 10 lines
Because the block is all about "
show_hint", we have code to print advice messages and nothing else in it currently, and more importantly, we will not add anything other than code to print advice messages in it. Because of that, skipping everything whenADVICE_SEQUENCER_CONFLICTis not enabled will not cause problems (unlike the earlier hunk---which will break if we added "&&advice_enabled()" to "if (msg)"). That way, when somebody teaches this code a new kind ofopts->action, they do not have to say "advice_if_enabled(ADVICE_SEQUENCER_CONFLICT()"; they can just use "advise()".
That's true and makes the changes simpler, thank you for the suggestion. I'll do that in v2.
Philippe.
Le 2024-03-09 à 12:22, Philippe Blain a écrit :
Quoted 65 lines
Hi Junio,
Le 2024-03-03 à 17:57, Junio C Hamano a écrit :
Quoted 62 lines
sequencer.c static void print_advice(struct repository *r, int show_hint, · line 473
Quoted 6 lines · Philippe Blain via GitGitGadget
sequencer.c +1
-1if (msg) { -advise ("%s\n" , msg); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT ,"%s\n" , msg);/* * A conflict has occurred but the porcelain * (typically rebase --interactive) wants to take care This hunk is good. The block removes the
CHERRY_PICK_HEADafter giving this advice and then returns.Quoted 30 lines
sequencer.c +10
-14@@ -480,22 +480,25 @@ static void print_advice(struct repository *r, int show_hint,if (show_hint) {if (opts->no_commit) -advise (_ ("after resolving the conflicts, mark the corrected paths\n" -"with 'git add <paths>' or 'git rm <paths>'" )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("after resolving the conflicts, mark the corrected paths\n" +"with 'git add <paths>' or 'git rm <paths>'" ));else if (opts->action ==REPLAY_PICK ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git cherry-pick --continue\".\n" -"You can instead skip this commit with \"git cherry-pick --skip\".\n" -"To abort and get back to the state before \"git cherry-pick\",\n" -"run \"git cherry-pick --abort\"." )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git cherry-pick --continue\".\n" +"You can instead skip this commit with \"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->action ==REPLAY_REVERT ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git revert --continue\".\n" -"You can instead skip this commit with \"git revert --skip\".\n" -"To abort and get back to the state before \"git revert\",\n" -"run \"git revert --abort\"." ));sequencer.c static void print_advice(struct repository *r, int show_hint, · line 504
Quoted 10 lines
sequencer.c +7
-0+advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git revert --continue\".\n" +"You can instead skip this commit with \"git revert --skip\".\n" +"To abort and get back to the state before \"git revert\",\n" +"run \"git revert --abort\"." )); else BUG("unexpected pick action in print_advice()"); }This hunk can be improved. If I were doing this patch, I probably would have just done
(quoted diff) +1
-1- if (show_hint) { + if (show_hint && advice_enabled(ADVICE_SEQUENCER_CONFLICT)) {and nothing else, and doing so would keep the block easier to extend and maintain in the future.
Quoted 13 lines
Quoted 10 lines
Because the block is all about "
show_hint", we have code to print advice messages and nothing else in it currently, and more importantly, we will not add anything other than code to print advice messages in it. Because of that, skipping everything whenADVICE_SEQUENCER_CONFLICTis not enabled will not cause problems (unlike the earlier hunk---which will break if we added "&&advice_enabled()" to "if (msg)"). That way, when somebody teaches this code a new kind ofopts->action, they do not have to say "advice_if_enabled(ADVICE_SEQUENCER_CONFLICT()"; they can just use "advise()".That's true and makes the changes simpler, thank you for the suggestion. I'll do that in v2.
Thinking about this more and looking at the code, using 'advice_enabled' in the condition instead of using 'advise_if_enabled' for each message has a side effect:
the text "hint: Disable this message with "git config advice.sequencerConflict false" will not appear, which I find less user friendly...
Philippe.
Quoted 4 lines · Philippe Blain
Thinking about this more and looking at the code, using '
advice_enabled' in the condition instead of using 'advise_if_enabled' for each message has a side effect:
the text "hint: Disable this message with "git config advice.sequencerConflict false" will not appear, which I find less user friendly...
Good eyes.
I agree that you have to do that part yourself at the end of that "if () { ... }" block using turn_off_instructions[] string.
Quoted 11 lines · Junio C Hamano
Quoted 4 lines · Philippe Blain
Thinking about this more and looking at the code, using '
advice_enabled' in the condition instead of using 'advise_if_enabled' for each message has a side effect:
the text "hint: Disable this message with "git config advice.sequencerConflict false" will not appear, which I find less user friendly...Good eyes.
I agree that you have to do that part yourself at the end of that "if () { ... }" block using turn_off_instructions[] string.
Forgot to add "... which is an unnecessary chore" at the end.
Thanks.
Hi Philippe
Quoted 4 lines · Philippe Blain via GitGitGadget
From: Philippe Blain <[email protected]>
Allow disabling the advice shown when a squencer operation results in a merge conflict through a new config 'advice.sequencerConflict'.
We already have "advice.resolveConflict" to suppress conflict advice. Can we extend that to these conflict messages rather than introducing a new category? As far as the user is concerned they are all messages about resolving conflicts - I don't really see why they'd want to suppress the messages from "git merge" separately to "git rebase" (and if they do then why is it ok to suppress the messages from "git merge", "git rebase" and "git cherry-pick" with a single setting). It would also be good to update the "rebase --apply" implementation to respect this advice config to be consistent with "rebase --merge".
Best Wishes
Phillip
Quoted 149 lines
Update the tests accordingly. Note that the body of the second test in
t3507-cherry-pick-conflict.shis enclosed in double quotes, so we must escape them in the added line.Signed-off-by Philippe Blain <[email protected]>---
sequencer: allow disabling conflict adviceCC: Elijah Newren [email protected] CC: Phillip Wood [email protected] CC: Johannes Schindelin [email protected] CC: ZheNing Hu [email protected]
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1682%2Fphil-blain%2Fsequencer-conflict-advice-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1682/phil-blain/sequencer-conflict-advice-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1682Documentation/config/advice.txt | 3 +++ advice.c | 1 + advice.h | 1 + sequencer.c | 33 ++++++++++++++++++--------------- t/t3501-revert-cherry-pick.sh | 1 + t/t3507-cherry-pick-conflict.sh | 2 ++ 6 files changed, 26 insertions(+), 15 deletions(-)Documentation/config/advice.txt +3
-0@@ -104,6 +104,9 @@ advice.*:: rmHints:: In case of failure in the output of linkgit:git-rm[1], show directions on how to proceed from the current state. + sequencerConflict:: + Advice shown when a sequencer operation stops because + of conflicts. sequencerInUse:: Advice shown when a sequencer command is already in progress. skippedCherryPicks::advice.c +1
-0@@ -71,6 +71,7 @@ static struct { [ADVICE_RESET_NO_REFRESH_WARNING] = { "resetNoRefresh" }, [ADVICE_RESOLVE_CONFLICT] = { "resolveConflict" }, [ADVICE_RM_HINTS] = { "rmHints" }, + [ADVICE_SEQUENCER_CONFLICT] = { "sequencerConflict" }, [ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse" }, [ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure" }, [ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks" },advice.h +1
-0@@ -40,6 +40,7 @@ enum advice_type {ADVICE_RESOLVE_CONFLICT ,ADVICE_RM_HINTS ,ADVICE_SEQUENCER_IN_USE , +ADVICE_SEQUENCER_CONFLICT ,ADVICE_SET_UPSTREAM_FAILURE ,ADVICE_SKIPPED_CHERRY_PICKS , ADVICE_STATUS_AHEAD_BEHIND_WARNING,sequencer.c +18
-15@@ -467,7 +467,7 @@ static void print_advice(struct repository *r, int show_hint,char *msg =getenv ("GIT_CHERRY_PICK_HELP" );if (msg) { -advise ("%s\n" , msg); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT ,"%s\n" , msg);/* * A conflict has occurred but the porcelain * (typically rebase --interactive) wants to take care @@ -480,22 +480,25 @@ static void print_advice(struct repository *r, int show_hint,if (show_hint) {if (opts->no_commit) -advise (_ ("after resolving the conflicts, mark the corrected paths\n" -"with 'git add <paths>' or 'git rm <paths>'" )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("after resolving the conflicts, mark the corrected paths\n" +"with 'git add <paths>' or 'git rm <paths>'" ));else if (opts->action ==REPLAY_PICK ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git cherry-pick --continue\".\n" -"You can instead skip this commit with \"git cherry-pick --skip\".\n" -"To abort and get back to the state before \"git cherry-pick\",\n" -"run \"git cherry-pick --abort\"." )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git cherry-pick --continue\".\n" +"You can instead skip this commit with \"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->action ==REPLAY_REVERT ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git revert --continue\".\n" -"You can instead skip this commit with \"git revert --skip\".\n" -"To abort and get back to the state before \"git revert\",\n" -"run \"git revert --abort\"." )); +advise_if_enabled (ADVICE_SEQUENCER_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git revert --continue\".\n" +"You can instead skip this commit with \"git revert --skip\".\n" +"To abort and get back to the state before \"git revert\",\n" +"run \"git revert --abort\"." ));else BUG ("unexpected pick action in print_advice()" ); }t/t3501-revert-cherry-pick.sh +1
-0@@ -170,6 +170,7 @@ test_expect_success 'advice from failed revert' ' hint: You can instead skip this commit with "git revert --skip". hint: To abort and get back to the state before "git revert", hint: run "git revert --abort". + hint: Disable this message with "git config advice.sequencerConflict false" EOF test_commit --append --no-tag "double-add dream" dream dream && test_must_fail git revert HEAD^ 2>actual &&t/t3507-cherry-pick-conflict.sh +2
-0@@ -60,6 +60,7 @@ test_expect_success 'advice from failed cherry-pick' ' hint: You can instead skip this commit with "git cherry-pick --skip". hint: To abort and get back to the state before "git cherry-pick", hint: run "git cherry-pick --abort". + hint: Disable this message with "git config advice.sequencerConflict false" EOF test_must_fail git cherry-pick picked 2>actual &&@@ -74,6 +75,7 @@ test_expect_success 'advice from failed cherry-pick --no-commit' " 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: Disable this message with \"git config advice.sequencerConflict false\" EOF test_must_fail git cherry-pick --no-commit picked 2>actual &&base-commit:
0f9d4d28b7e6021b7e6db192b7bf47bd3a0d0d1d
Quoted 1 line
We already have "advice.resolveConflict" to suppress conflict advice.
Oh looking more closely that is doing something slightly different - it suppresses advice about pre-existing conflicts in the index when starting a merge etc. So we probably do need a new config variable but I think it should have a generic name - not be sequencer specific so we can extend its scope in the future to "git merge", "git am -3", "git stash" etc.
Best Wishes
Phillip
Quoted 4 lines · Phillip Wood
... So we probably do need a new config variable but
I think it should have a generic name - not be sequencer specific so we can extend its scope in the future to "git merge", "git am -3", "git stash" etc.
A very good point. Thanks for your careful thinking.
Hi Phillip and Junio,
Le 2024-03-04 à 12:56, Junio C Hamano a écrit :
Quoted 8 lines
Quoted 4 lines · Phillip Wood
... So we probably do need a new config variable but
I think it should have a generic name - not be sequencer specific so we can extend its scope in the future to "git merge", "git am -3", "git stash" etc.A very good point. Thanks for your careful thinking.
OK, I agree we can make the new advice more generic, but I'm lacking inspiration for the name. Maybe 'advice.mergeConflicted' ?
Or 'advice.resolveConflictedMerge' ? though this is close to the existing 'resolveConflict'...
Maybe just 'advice.mergeConflict' ?
Thanks,
Philippe.
Hi Philippe
Quoted 8 lines · Philippe Blain
Le 2024-03-04 à 12:56, Junio C Hamano a écrit :
Quoted 7 lines
Quoted 4 lines · Phillip Wood
... So we probably do need a new config variable but
I think it should have a generic name - not be sequencer specific so we can extend its scope in the future to "git merge", "git am -3", "git stash" etc.
Quoted 7 lines
Quoted 1 line
A very good point. Thanks for your careful thinking.
OK, I agree we can make the new advice more generic, but I'm lacking inspiration for the name. Maybe 'advice.mergeConflicted' ?
Or 'advice.resolveConflictedMerge' ? though this is close to the existing 'resolveConflict'...
Maybe just 'advice.mergeConflict' ?
'advice.mergeConflict' sounds good to me
Best Wishes
Phillip
Quoted 3 lines · Phillip Wood
Quoted 1 line
Maybe just 'advice.mergeConflict' ?
'advice.mergeConflict' sounds good to me
Yup, looks good to me, too.
Hi Phillip,
Le 2024-03-04 à 05:12, Phillip Wood a écrit :
Quoted 5 lines
Hi Philippe
On 02/03/2024 16:18, Philippe Blain via GitGitGadget wrote:
It would also be good to update the "rebase --apply" implementation to respect this advice config to be consistent with "rebase --merge".
Yes, this is a good idea. This would take care of 'git am' at the same time since both are implemented in builtin/am.c::die_user_resolve.
Thanks,
Philippe.
v2 cover Allow disabling advice shown after merge conflicts
In reply to Philippe Blain via GitGitGadgetThis series introduces a new config 'advice.mergeConflict' and uses it to allow disabling the advice shown when 'git rebase', 'git cherry-pick', 'git revert', 'git rebase --apply' and 'git am' stop because of conflicts.
Changes since v1:
* renamed the new advice to 'advice.mergeConflict' to make it non-sequencer specific
* added 2/2 which uses the advice in builtin/am, which covers 'git rebase --apply' and 'git am'
Note that the code path where 'git rebase --apply' stops because of conflicts is not covered by the tests but I tested it manually using this diff:
t/t5520-pull.sh +1 -1
@@ -374,7 +374,7 @@ test_pull_autostash_fail () echo conflicting >>seq.txt && test_tick && git commit -m "Create conflict" seq.txt && - test_must_fail git pull --rebase . seq 2>err >out && + test_must_fail git -c rebase.backend=apply pull --rebase . seq 2>err >out && test_grep "Resolve all conflicts manually" err '
Philippe Blain (2):
sequencer: allow disabling conflict advice
builtin/am: allow disabling conflict advice
Documentation/config/advice.txt | 2 ++ advice.c | 1 + advice.h | 1 + builtin/am.c | 14 +++++++++----- sequencer.c | 33 ++++++++++++++++++--------------- t/t3501-revert-cherry-pick.sh | 1 + t/t3507-cherry-pick-conflict.sh | 2 ++ t/t4150-am.sh | 8 ++++---- t/t4254-am-corrupt.sh | 2 +- 9 files changed, 39 insertions(+), 25 deletions(-)
base-commit: 0f9d4d28b7e6021b7e6db192b7bf47bd3a0d0d1d
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1682%2Fphil-blain%2Fsequencer-conflict-advice-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1682/phil-blain/sequencer-conflict-advice-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1682
Range-diff vs v1:
1: e929d3381cf ! 1: a2ce6fd24c2 sequencer: allow disabling conflict advice
@@ Commit message
sequencer: allow disabling conflict advice
Allow disabling the advice shown when a squencer operation results in a
- merge conflict through a new config 'advice.sequencerConflict'.
+ merge conflict through a new config 'advice.mergeConflict', which is
+ named generically such that it can be used by other commands eventually.
+
+ Note that we use 'advise_if_enabled' for each message in the second hunk
+ in sequencer.c, instead of using 'if (show_hints &&
+ advice_enabled(...)', because the former instructs the user how to
+ disable the advice, which is more user-friendly.
Update the tests accordingly. Note that the body of the second test in t3507-cherry-pick-conflict.sh is enclosed in double quotes, so we must
@@ Commit message
## Documentation/config/advice.txt ##
@@ Documentation/config/advice.txt: advice.*::
- rmHints::
- In case of failure in the output of linkgit:git-rm[1],
- show directions on how to proceed from the current state.
-+ sequencerConflict::
-+ Advice shown when a sequencer operation stops because
-+ of conflicts.
- sequencerInUse::
- Advice shown when a sequencer command is already in progress.
- skippedCherryPicks::
+ Advice on how to set your identity configuration when
+ your information is guessed from the system username and
+ domain name.
++ mergeConflict::
++ Advice shown when various commands stop because of conflicts.
+ nestedTag::
+ Advice shown if a user attempts to recursively tag a tag object.
+ pushAlreadyExists::
## advice.c ##
@@ advice.c: static struct {
- [ADVICE_RESET_NO_REFRESH_WARNING] = { "resetNoRefresh" },
- [ADVICE_RESOLVE_CONFLICT] = { "resolveConflict" },
- [ADVICE_RM_HINTS] = { "rmHints" },
-+ [ADVICE_SEQUENCER_CONFLICT] = { "sequencerConflict" },
- [ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse" },
- [ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure" },
- [ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks" },
+ [ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated" },
+ [ADVICE_IGNORED_HOOK] = { "ignoredHook" },
+ [ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity" },
++ [ADVICE_MERGE_CONFLICT] = { "mergeConflict" },
+ [ADVICE_NESTED_TAG] = { "nestedTag" },
+ [ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning" },
+ [ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists" },
## advice.h ##
@@ advice.h: enum advice_type {
- ADVICE_RESOLVE_CONFLICT,
- ADVICE_RM_HINTS,
- ADVICE_SEQUENCER_IN_USE,
-+ ADVICE_SEQUENCER_CONFLICT,
- ADVICE_SET_UPSTREAM_FAILURE,
- ADVICE_SKIPPED_CHERRY_PICKS,
- ADVICE_STATUS_AHEAD_BEHIND_WARNING,
+ ADVICE_IGNORED_HOOK,
+ ADVICE_IMPLICIT_IDENTITY,
+ ADVICE_NESTED_TAG,
++ ADVICE_MERGE_CONFLICT,
+ ADVICE_OBJECT_NAME_WARNING,
+ ADVICE_PUSH_ALREADY_EXISTS,
+ ADVICE_PUSH_FETCH_FIRST,
## sequencer.c ##
@@ sequencer.c: static void print_advice(struct repository *r, int show_hint,
@@ sequencer.c: static void print_advice(struct repository *r, int show_hint,
if (msg) {
- advise("%s\n", msg);
-+ advise_if_enabled(ADVICE_SEQUENCER_CONFLICT, "%s\n", msg);
++ advise_if_enabled(ADVICE_MERGE_CONFLICT, "%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 (opts->no_commit)
- advise(_("after resolving the conflicts, mark the corrected paths\n"
- "with 'git add <paths>' or 'git rm <paths>'"));
-+ advise_if_enabled(ADVICE_SEQUENCER_CONFLICT,
++ advise_if_enabled(ADVICE_MERGE_CONFLICT,
+ _("after resolving the conflicts, mark the corrected paths\n"
+ "with 'git add <paths>' or 'git rm <paths>'"));
else if (opts->action == REPLAY_PICK)
@@ sequencer.c: static void print_advice(struct repository *r, int show_hint,
- "You can instead skip this commit with \"git cherry-pick --skip\".\n"
- "To abort and get back to the state before \"git cherry-pick\",\n"
- "run \"git cherry-pick --abort\"."));
-+ advise_if_enabled(ADVICE_SEQUENCER_CONFLICT,
++ advise_if_enabled(ADVICE_MERGE_CONFLICT,
+ _("After resolving the conflicts, mark them with\n"
+ "\"git add/rm <pathspec>\", then run\n"
+ "\"git cherry-pick --continue\".\n"
@@ sequencer.c: static void print_advice(struct repository *r, int show_hint,
- "You can instead skip this commit with \"git revert --skip\".\n"
- "To abort and get back to the state before \"git revert\",\n"
- "run \"git revert --abort\"."));
-+ advise_if_enabled(ADVICE_SEQUENCER_CONFLICT,
++ advise_if_enabled(ADVICE_MERGE_CONFLICT,
+ _("After resolving the conflicts, mark them with\n"
+ "\"git add/rm <pathspec>\", then run\n"
+ "\"git revert --continue\".\n"
@@ t/t3501-revert-cherry-pick.sh: test_expect_success 'advice from failed revert' '
hint: You can instead skip this commit with "git revert --skip".
hint: To abort and get back to the state before "git revert",
hint: run "git revert --abort".
-+ hint: Disable this message with "git config advice.sequencerConflict false"
++ hint: Disable this message with "git config advice.mergeConflict false"
EOF
test_commit --append --no-tag "double-add dream" dream dream && test_must_fail git revert HEAD^ 2>actual &&
@@ t/t3507-cherry-pick-conflict.sh: test_expect_success 'advice from failed cherry-
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
-+ hint: Disable this message with "git config advice.sequencerConflict false"
++ hint: Disable this message with "git config advice.mergeConflict false"
EOF
test_must_fail git cherry-pick picked 2>actual &&
@@ t/t3507-cherry-pick-conflict.sh: test_expect_success 'advice from failed cherry-
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: Disable this message with \"git config advice.sequencerConflict false\"
++ hint: Disable this message with \"git config advice.mergeConflict false\"
EOF
test_must_fail git cherry-pick --no-commit picked 2>actual &&
-: ----------- > 2: 3235542cc6f builtin/am: allow disabling conflict advice
Signature · 1 line
gitgitgadget
PATCH v2 1/2 sequencer: allow disabling conflict advice
From: Philippe Blain <[email protected]>
Allow disabling the advice shown when a squencer operation results in a merge conflict through a new config 'advice.mergeConflict', which is named generically such that it can be used by other commands eventually.
Note that we use 'advise_if_enabled' for each message in the second hunk in sequencer.c, instead of using 'if (show_hints && advice_enabled(...)', because the former instructs the user how to disable the advice, which is more user-friendly.
Update the tests accordingly. Note that the body of the second test in t3507-cherry-pick-conflict.sh is enclosed in double quotes, so we must escape them in the added line.
--- Documentation/config/advice.txt | 2 ++ advice.c | 1 + advice.h | 1 + sequencer.c | 33 ++++++++++++++++++--------------- t/t3501-revert-cherry-pick.sh | 1 + t/t3507-cherry-pick-conflict.sh | 2 ++ 6 files changed, 25 insertions(+), 15 deletions(-)
Documentation/config/advice.txt +2 -0
@@ -56,6 +56,8 @@ advice.*:: Advice on how to set your identity configuration when your information is guessed from the system username and domain name. + mergeConflict:: + Advice shown when various commands stop because of conflicts. nestedTag:: Advice shown if a user attempts to recursively tag a tag object. pushAlreadyExists::
advice.c +1 -0
@@ -57,6 +57,7 @@ static struct { [ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated" }, [ADVICE_IGNORED_HOOK] = { "ignoredHook" }, [ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity" }, + [ADVICE_MERGE_CONFLICT] = { "mergeConflict" }, [ADVICE_NESTED_TAG] = { "nestedTag" }, [ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning" }, [ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists" },
advice.h +1 -0
@@ -26,6 +26,7 @@ enum advice_type {ADVICE_IGNORED_HOOK ,ADVICE_IMPLICIT_IDENTITY ,ADVICE_NESTED_TAG , +ADVICE_MERGE_CONFLICT ,ADVICE_OBJECT_NAME_WARNING ,ADVICE_PUSH_ALREADY_EXISTS , ADVICE_PUSH_FETCH_FIRST,
sequencer.c +18 -15
@@ -467,7 +467,7 @@ static void print_advice(struct repository *r, int show_hint,char *msg =getenv ("GIT_CHERRY_PICK_HELP" );if (msg) { -advise ("%s\n" , msg); +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s\n" , msg);/* * A conflict has occurred but the porcelain * (typically rebase --interactive) wants to take care
@@ -480,22 +480,25 @@ static void print_advice(struct repository *r, int show_hint,if (show_hint) {if (opts->no_commit) -advise (_ ("after resolving the conflicts, mark the corrected paths\n" -"with 'git add <paths>' or 'git rm <paths>'" )); +advise_if_enabled (ADVICE_MERGE_CONFLICT , +_ ("after resolving the conflicts, mark the corrected paths\n" +"with 'git add <paths>' or 'git rm <paths>'" ));else if (opts->action ==REPLAY_PICK ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git cherry-pick --continue\".\n" -"You can instead skip this commit with \"git cherry-pick --skip\".\n" -"To abort and get back to the state before \"git cherry-pick\",\n" -"run \"git cherry-pick --abort\"." )); +advise_if_enabled (ADVICE_MERGE_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git cherry-pick --continue\".\n" +"You can instead skip this commit with \"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->action ==REPLAY_REVERT ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git revert --continue\".\n" -"You can instead skip this commit with \"git revert --skip\".\n" -"To abort and get back to the state before \"git revert\",\n" -"run \"git revert --abort\"." )); +advise_if_enabled (ADVICE_MERGE_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git revert --continue\".\n" +"You can instead skip this commit with \"git revert --skip\".\n" +"To abort and get back to the state before \"git revert\",\n" +"run \"git revert --abort\"." ));else BUG ("unexpected pick action in print_advice()" ); }
t/t3501-revert-cherry-pick.sh +1 -0
@@ -170,6 +170,7 @@ test_expect_success 'advice from failed revert' ' hint: You can instead skip this commit with "git revert --skip". hint: To abort and get back to the state before "git revert", hint: run "git revert --abort". + hint: Disable this message with "git config advice.mergeConflict false" EOF test_commit --append --no-tag "double-add dream" dream dream && test_must_fail git revert HEAD^ 2>actual &&
t/t3507-cherry-pick-conflict.sh +2 -0
@@ -60,6 +60,7 @@ test_expect_success 'advice from failed cherry-pick' ' hint: You can instead skip this commit with "git cherry-pick --skip". hint: To abort and get back to the state before "git cherry-pick", hint: run "git cherry-pick --abort". + hint: Disable this message with "git config advice.mergeConflict false" EOF test_must_fail git cherry-pick picked 2>actual &&
@@ -74,6 +75,7 @@ test_expect_success 'advice from failed cherry-pick --no-commit' " 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: Disable this message with \"git config advice.mergeConflict false\" EOF test_must_fail git cherry-pick --no-commit picked 2>actual &&
Signature · 1 line
gitgitgadget
Hi Philippe
Documentation/config/advice.txt advice.*:: · line 60
Quoted 11 lines · Philippe Blain via GitGitGadget
Documentation/config/advice.txt +2
-0@@ -56,6 +56,8 @@ advice.*:: Advice on how to set your identity configuration when your information is guessed from the system username and domain name. + mergeConflict:: + Advice shown when various commands stop because of conflicts.
Given that topic kh/branch-ref-syntax-advice is in next, maybe this should be changed to “Shown when”?[1]
Quoted 3 lines
Documentation/config/advice.txt +0
-0nestedTag:: Advice shown if a user attempts to recursively tag a tag object. pushAlreadyExists::
Hi Kristoffer,
Le 2024-03-11 à 06:29, Kristoffer Haugsbakk a écrit :
Quoted 18 lines
Hi Philippe
Documentation/config/advice.txt advice.*:: · line 60
Quoted 11 lines · Philippe Blain via GitGitGadget
Documentation/config/advice.txt +2
-0@@ -56,6 +56,8 @@ advice.*:: Advice on how to set your identity configuration when your information is guessed from the system username and domain name. + mergeConflict:: + Advice shown when various commands stop because of conflicts.Given that topic kh/branch-ref-syntax-advice is in
next, maybe this should be changed to “Shown when”?[1]
Quoted 1 line
Thanks for the pointer, I will change that for uniformity in that section of the doc.
Cheers,
Philippe.
PATCH v2 2/2 builtin/am: allow disabling conflict advice
In reply to Philippe Blain via GitGitGadgetFrom: Philippe Blain <[email protected]>
When 'git am' or 'git rebase --apply' encounter a conflict, they show a message instructing the user how to continue the operation. This message can't be disabled.
Use ADVICE_MERGE_CONFLICT introduced in the previous commit to allow disabling it. Update the tests accordingly, as the advice output is now on stderr instead of stdout. In t4150, redirect stdout to 'out' and stderr to 'err', since this is less confusing. In t4254, as we are testing a specific failure mode of 'git am', simply disable the advice.
--- builtin/am.c | 14 +++++++++----- t/t4150-am.sh | 8 ++++---- t/t4254-am-corrupt.sh | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-)
builtin/am.c +9 -5
@@ -1150,19 +1150,23 @@ static const char *msgnum(const struct am_state *state) static void NORETURN die_user_resolve(const struct am_state *state) {if (state->resolvemsg) { -printf_ln ("%s" , state->resolvemsg); +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , state->resolvemsg); }else {const char *cmdline = state->interactive ?"git am -i" :"git am" ; +struct strbuf sb =STRBUF_INIT ; -printf_ln (_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); -printf_ln (_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline); +strbuf_addf (&sb,_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); +strbuf_addf (&sb,_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline);if (advice_enabled (ADVICE_AM_WORK_DIR ) &&is_empty_or_missing_file (am_path (state,"patch" )) && !repo_index_has_changes (the_repository,NULL ,NULL )) -printf_ln (_ ("To record the empty patch as an empty commit, run \"%s --allow-empty\"." ), cmdline); +strbuf_addf (&sb,_ ("To record the empty patch as an empty commit, run \"%s --allow-empty\"." ), cmdline); -printf_ln (_ ("To restore the original branch and stop patching, run \"%s --abort\"." ), cmdline); +strbuf_addf (&sb,_ ("To restore the original branch and stop patching, run \"%s --abort\"." ), cmdline); + +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , sb.buf); +strbuf_release (&sb); }exit (128 );
t/t4150-am.sh +4 -4
@@ -1224,8 +1224,8 @@ test_expect_success 'record as an empty commit when meeting e-mail message that test_expect_success 'skip an empty patch in the middle of an am session' ' git checkout empty-commit^ && - test_must_fail git am empty-commit.patch >err && - grep "Patch is empty." err && + test_must_fail git am empty-commit.patch >out 2>err && + grep "Patch is empty." out && grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err && git am --skip && test_path_is_missing .git/rebase-apply &&
@@ -1236,8 +1236,8 @@ test_expect_success 'skip an empty patch in the middle of an am session' ' test_expect_success 'record an empty patch as an empty commit in the middle of an am session' ' git checkout empty-commit^ && - test_must_fail git am empty-commit.patch >err && - grep "Patch is empty." err && + test_must_fail git am empty-commit.patch >out 2>err && + grep "Patch is empty." out && grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err && git am --allow-empty >output && grep "No changes - recorded it as an empty commit." output &&
t/t4254-am-corrupt.sh +1 -1
@@ -59,7 +59,7 @@ test_expect_success setup ' # Also, it had the unwanted side-effect of deleting f. test_expect_success 'try to apply corrupted patch' ' test_when_finished "git am --abort" && - test_must_fail git -c advice.amWorkDir=false am bad-patch.diff 2>actual && + test_must_fail git -c advice.amWorkDir=false -c advice.mergeConflict=false am bad-patch.diff 2>actual && echo "error: git diff header lacks filename information (line 4)" >expected && test_path_is_file f && test_cmp expected actual
Signature · 1 line
gitgitgadget
Re: [PATCH v2 2/2] builtin/am: allow disabling conflict advice
Hi Philippe
Quoted 8 lines · Philippe Blain via GitGitGadget
builtin/am.c +0
-0@@ -1150,19 +1150,23 @@ static const char *msgnum(const struct am_state *state) static void NORETURN die_user_resolve(const struct am_state *state) {if (state->resolvemsg) {
builtin/am.c static const char *msgnum(const struct am_state *state) · line 1159
Quoted 10 lines
builtin/am.c +4
-3-printf_ln ("%s" , state->resolvemsg); +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , state->resolvemsg); }else {const char *cmdline = state->interactive ?"git am -i" :"git am" ; +struct strbuf sb =STRBUF_INIT ; -printf_ln (_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); -printf_ln (_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline); +strbuf_addf (&sb,_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); +strbuf_addf (&sb,_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline);
I think you need to append "\n" to the message strings here (and below) to match the behavior of printf_ln().
Apart from that both patches look good to me, thanks for re-rolling. It is a bit surprising that we don't need to update any rebase tests. I haven't checked but I guess either we're not testing this advice when rebasing or we're using a grep expression that is vague enough not to be affected.
Best Wishes
Phillip
Quoted 53 lines
builtin/am.c +5
-2if (advice_enabled (ADVICE_AM_WORK_DIR ) &&is_empty_or_missing_file (am_path (state,"patch" )) && !repo_index_has_changes (the_repository,NULL ,NULL )) -printf_ln (_ ("To record the empty patch as an empty commit, run \"%s --allow-empty\"." ), cmdline); +strbuf_addf (&sb,_ ("To record the empty patch as an empty commit, run \"%s --allow-empty\"." ), cmdline); -printf_ln (_ ("To restore the original branch and stop patching, run \"%s --abort\"." ), cmdline); +strbuf_addf (&sb,_ ("To restore the original branch and stop patching, run \"%s --abort\"." ), cmdline); + +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , sb.buf); +strbuf_release (&sb); }message instructing the user how to continue the operation. This messageexit (128 );t/t4150-am.sh +4
-4@@ -1224,8 +1224,8 @@ test_expect_success 'record as an empty commit when meeting e-mail message that test_expect_success 'skip an empty patch in the middle of an am session' ' git checkout empty-commit^ && - test_must_fail git am empty-commit.patch >err && - grep "Patch is empty." err && + test_must_fail git am empty-commit.patch >out 2>err && + grep "Patch is empty." out && grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err && git am --skip && test_path_is_missing .git/rebase-apply &&@@ -1236,8 +1236,8 @@ test_expect_success 'skip an empty patch in the middle of an am session' ' test_expect_success 'record an empty patch as an empty commit in the middle of an am session' ' git checkout empty-commit^ && - test_must_fail git am empty-commit.patch >err && - grep "Patch is empty." err && + test_must_fail git am empty-commit.patch >out 2>err && + grep "Patch is empty." out && grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err && git am --allow-empty >output && grep "No changes - recorded it as an empty commit." output &&t/t4254-am-corrupt.sh +1
-1@@ -59,7 +59,7 @@ test_expect_success setup ' # Also, it had the unwanted side-effect of deleting f. test_expect_success 'try to apply corrupted patch' ' test_when_finished "git am --abort" && - test_must_fail git -c advice.amWorkDir=false am bad-patch.diff 2>actual && + test_must_fail git -c advice.amWorkDir=false -c advice.mergeConflict=false am bad-patch.diff 2>actual && echo "error: git diff header lacks filename information (line 4)" >expected && test_path_is_file f && test_cmp expected actual
Re: [PATCH v2 2/2] builtin/am: allow disabling conflict advice
Quoted 16 lines · [email protected] writes:
Hi Philippe
Quoted 13 lines · Philippe Blain via GitGitGadget
builtin/am.c +2
-1@@ -1150,19 +1150,23 @@ static const char *msgnum(const struct am_state *state) static void NORETURN die_user_resolve(const struct am_state *state) {if (state->resolvemsg) { -printf_ln ("%s" , state->resolvemsg); +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , state->resolvemsg); }else {const char *cmdline = state->interactive ?"git am -i" :"git am" ; +struct strbuf sb =STRBUF_INIT ;
Quoted 8 lines
builtin/am.c static const char *msgnum(const struct am_state *state) · line 1159
Quoted 5 lines
builtin/am.c +2
-1-printf_ln (_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); -printf_ln (_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline); +strbuf_addf (&sb,_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); +strbuf_addf (&sb,_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline);I think you need to append "\n" to the message strings here (and below) to match the behavior of
printf_ln().
Good eyes. You'll get the final "\n" but the line breaks inside the paragraph you give to advise*() functions are your responsibility. Even though advice.c:vadvise() handles multi-line message better (unlike usage.c:vreportf() that is used for error() and die()) by giving a line header for each line of the message, we do not wrap lines at runtime.
Quoted 2 lines
Apart from that both patches look good to me, thanks for re-rolling. It is a bit surprising that we don't need to update any
Thanks, both, and indeed it is a bit surprising.
Quoted 3 lines
rebase tests. I haven't checked but I guess either we're not testing this advice when rebasing or we're using a grep expression that is vague enough not to be affected.
Re: [PATCH v2 2/2] builtin/am: allow disabling conflict advice
Quoted 9 lines · Junio C Hamano
Quoted 2 lines
I think you need to append "\n" to the message strings here (and below) to match the behavior of
printf_ln().Good eyes. You'll get the final "\n" but the line breaks inside the paragraph you give to advise*() functions are your responsibility. Even though advice.c:vadvise() handles multi-line message better (unlike usage.c:vreportf() that is used for
error()anddie()) by giving a line header for each line of the message, we do not wrap lines at runtime.
Perhaps something like this.
The overly long lines are getting a bit annoying but I do not offhand think of a good way to shorten them.
Also, having to assemble the message in a buffer and emit them all once with ("%s" % sb.buf) is a highly annoying pattern. Perhaps given enough examples, somebody will come up with a simpler API to do the same thing, but that is not in the scope of this series.
builtin/am.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
builtin/am.c +3 -4
@@ -1155,14 +1155,13 @@ static void NORETURN die_user_resolve(const struct am_state *state)const char *cmdline = state->interactive ?"git am -i" :"git am" ;struct strbuf sb =STRBUF_INIT ; -strbuf_addf (&sb,_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); -strbuf_addf (&sb,_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline); +strbuf_addf (&sb,_ ("When you have resolved this problem, run \"%s --continue\".\n" ), cmdline); +strbuf_addf (&sb,_ ("If you prefer to skip this patch, run \"%s --skip\" instead.\n" ), cmdline);if (advice_enabled (ADVICE_AM_WORK_DIR ) &&is_empty_or_missing_file (am_path (state,"patch" )) && !repo_index_has_changes (the_repository,NULL ,NULL )) -strbuf_addf (&sb,_ ("To record the empty patch as an empty commit, run \"%s --allow-empty\"." ), cmdline); - +strbuf_addf (&sb,_ ("To record the empty patch as an empty commit, run \"%s --allow-empty\".\n" ), cmdline);strbuf_addf (&sb,_ ("To restore the original branch and stop patching, run \"%s --abort\"." ), cmdline);advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , sb.buf);
Re: [PATCH v2 2/2] builtin/am: allow disabling conflict advice
Hi Phillip and Junio,
Le 2024-03-11 à 13:49, Junio C Hamano a écrit :
Quoted 5 lines
Quoted 3 lines · Junio C Hamano
Quoted 2 lines
I think you need to append "\n" to the message strings here (and below) to match the behavior of
printf_ln().
Quoted 8 lines
Quoted 6 lines
Good eyes. You'll get the final "\n" but the line breaks inside the paragraph you give to advise*() functions are your responsibility. Even though advice.c:vadvise() handles multi-line message better (unlike usage.c:vreportf() that is used for
error()anddie()) by giving a line header for each line of the message, we do not wrap lines at runtime.Perhaps something like this.
Thanks Phillip for noticing, and Junio for the fix. I should have looked at the output, apologies. I made sure that the test passed but since t/t4150-am.sh only checks for the "To record the empty patch as an empty commit" string, it still passed despite the missing newlines.
Just a note if it helps anyone: I cherry-picked Junio's fixes using:
b4 shazam -P _ '<[email protected]>'
Cheers,
Philippe.
Re: [PATCH v2 2/2] builtin/am: allow disabling conflict advice
In reply to Junio C HamanoLe 2024-03-11 à 13:12, Junio C Hamano a écrit :
Quoted 34 lines
Quoted 16 lines · [email protected] writes:
Hi Philippe
Quoted 13 lines · Philippe Blain via GitGitGadget
builtin/am.c +2
-1@@ -1150,19 +1150,23 @@ static const char *msgnum(const struct am_state *state) static void NORETURN die_user_resolve(const struct am_state *state) {if (state->resolvemsg) { -printf_ln ("%s" , state->resolvemsg); +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , state->resolvemsg); }else {const char *cmdline = state->interactive ?"git am -i" :"git am" ; +struct strbuf sb =STRBUF_INIT ;Quoted 8 lines
builtin/am.c static const char *msgnum(const struct am_state *state) · line 1159
Quoted 5 lines
builtin/am.c +2
-1-printf_ln (_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); -printf_ln (_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline); +strbuf_addf (&sb,_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); +strbuf_addf (&sb,_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline);I think you need to append "\n" to the message strings here (and below) to match the behavior of
printf_ln().Good eyes. You'll get the final "\n" but the line breaks inside the paragraph you give to advise*() functions are your responsibility. Even though advice.c:vadvise() handles multi-line message better (unlike usage.c:vreportf() that is used for
error()anddie()) by giving a line header for each line of the message, we do not wrap lines at runtime.
Quoted 8 lines
Quoted 2 lines
Apart from that both patches look good to me, thanks for re-rolling. It is a bit surprising that we don't need to update any
Thanks, both, and indeed it is a bit surprising.
Quoted 3 lines
rebase tests. I haven't checked but I guess either we're not testing this advice when rebasing or we're using a grep expression that is vague enough not to be affected.
We are not testing this advice when rebasing _with the apply backend_. We are testing it with the merge backend (in t5520-pull.sh) but we are only grepping stderr for "Resolve all conflicts manually" so I did not have to change anything. I'll add that to the commit message for completeness.
We were testing the apply backend through the same test before 2ac0d6273f (rebase: change the default backend from "am" to "merge", 2020-02-15).
Thanks,
Philippe.
Re: [PATCH v2 0/2] Allow disabling advice shown after merge conflicts
In reply to Philippe Blain via GitGitGadgetQuoted 3 lines · Philippe Blain via GitGitGadget
Range-diff vs v1:
1:
e929d3381cf! 1:a2ce6fd24c2sequencer: allow disabling conflict advice
[...]
Quoted 8 lines
##
advice.c##
@@advice.c: static struct {
- [ADVICE_RESET_NO_REFRESH_WARNING] = { "resetNoRefresh" },
- [ADVICE_RESOLVE_CONFLICT] = { "resolveConflict" },
- [ADVICE_RM_HINTS] = { "rmHints" },
-+ [ADVICE_SEQUENCER_CONFLICT] = { "sequencerConflict" },
- [ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse" },
- [ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure" },
Quoted 8 lines
- [
ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks" },
+ [ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated" },
+ [ADVICE_IGNORED_HOOK] = { "ignoredHook" },
+ [ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity" },
++ [ADVICE_MERGE_CONFLICT] = { "mergeConflict" },
+ [ADVICE_NESTED_TAG] = { "nestedTag" },
+ [ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning" },
+ [ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists" },
You rename ADVICE_SEQUENCER_CONFLICT to ADVICE_MERGE_CONFLICT and place the new name in the correct position, alphabetically. Nice.
Quoted 8 lines
##
advice.h##
@@advice.h: enumadvice_type{
-ADVICE_RESOLVE_CONFLICT,
-ADVICE_RM_HINTS,
-ADVICE_SEQUENCER_IN_USE,
-+ADVICE_SEQUENCER_CONFLICT,
-ADVICE_SET_UPSTREAM_FAILURE,
-ADVICE_SKIPPED_CHERRY_PICKS,
Quoted 8 lines
-
ADVICE_STATUS_AHEAD_BEHIND_WARNING,
+ADVICE_IGNORED_HOOK,
+ADVICE_IMPLICIT_IDENTITY,
+ADVICE_NESTED_TAG,
++ADVICE_MERGE_CONFLICT,
+ADVICE_OBJECT_NAME_WARNING,
+ADVICE_PUSH_ALREADY_EXISTS,
+ADVICE_PUSH_FETCH_FIRST,
Here, I assume you're trying to place the new name correctly too. However, I see that it's in the wrong place. It initially caught my attention, but then I realize that the list is not sorted. So it's understandable.
Maybe you want to sort the list as a preparatory patch in this series and so we'll avoid this kind of mistakes.
Of course, this does not deserve a reroll. We can do it in a future series when the dust settles.
Re: [PATCH v2 0/2] Allow disabling advice shown after merge conflicts
Hi Rubén,
Le 2024-03-11 à 16:58, Rubén Justo a écrit :
Quoted 25 lines · Philippe Blain via GitGitGadget
Quoted 18 lines
##
advice.h##
@@advice.h: enumadvice_type{
-ADVICE_RESOLVE_CONFLICT,
-ADVICE_RM_HINTS,
-ADVICE_SEQUENCER_IN_USE,
-+ADVICE_SEQUENCER_CONFLICT,
-ADVICE_SET_UPSTREAM_FAILURE,
-ADVICE_SKIPPED_CHERRY_PICKS,
-ADVICE_STATUS_AHEAD_BEHIND_WARNING,
+ADVICE_IGNORED_HOOK,
+ADVICE_IMPLICIT_IDENTITY,
+ADVICE_NESTED_TAG,
++ADVICE_MERGE_CONFLICT,
+ADVICE_OBJECT_NAME_WARNING,
+ADVICE_PUSH_ALREADY_EXISTS,
+ADVICE_PUSH_FETCH_FIRST,Here, I assume you're trying to place the new name correctly too. However, I see that it's in the wrong place. It initially caught my attention, but then I realize that the list is not sorted. So it's understandable.
Quoted 5 lines
Maybe you want to sort the list as a preparatory patch in this series and so we'll avoid this kind of mistakes.
Of course, this does not deserve a reroll. We can do it in a future series when the dust settles.
I fixed this to put it in the correct order.
Thanks,
Philippe.
v3 cover Allow disabling advice shown after merge conflicts
In reply to Philippe Blain via GitGitGadgetThis series introduces a new config 'advice.mergeConflict' and uses it to allow disabling the advice shown when 'git rebase', 'git cherry-pick', 'git revert', 'git rebase --apply' and 'git am' stop because of conflicts.
Thanks everyone for the reviews!
Changes since v2:
* expanded the commit messages to explain why the tests for 'git rebase' do not need to be adjusted
* adjusted the wording of the new 'advice.mergeConflict' in the doc, as suggested by Kristoffer for uniformity with his series which is already merged to 'master' (b09a8839a4 (Merge branch 'kh/branch-ref-syntax-advice', 2024-03-15)).
* checked all new output manually and consequently adjusted the code in 1/2 to avoid a lonely 'hint: ' line.
* adjusted the addition in advice.h in 1/2 to put the new enum alphabetically, as noticed by Rubén.
* added misssing newlines in 2/2 as noticed by Phillip and tweaked by Junio.
* rebased on master (2953d95d40 (The eighth batch, 2024-03-15)), to avoid conflicts in 'Documentation/config/advice.txt' due to Kristoffer's merged series
Changes since v1:
* renamed the new advice to 'advice.mergeConflict' to make it non-sequencer specific
* added 2/2 which uses the advice in builtin/am, which covers 'git rebase --apply' and 'git am'
Note that the code path where 'git rebase --apply' stops because of conflicts is not covered by the tests but I tested it manually using this diff:
t/t5520-pull.sh +1 -1
@@ -374,7 +374,7 @@ test_pull_autostash_fail () echo conflicting >>seq.txt && test_tick && git commit -m "Create conflict" seq.txt && - test_must_fail git pull --rebase . seq 2>err >out && + test_must_fail git -c rebase.backend=apply pull --rebase . seq 2>err >out && test_grep "Resolve all conflicts manually" err '
Philippe Blain (2):
sequencer: allow disabling conflict advice
builtin/am: allow disabling conflict advice
Documentation/config/advice.txt | 2 ++ advice.c | 1 + advice.h | 1 + builtin/am.c | 14 +++++++++----- sequencer.c | 33 ++++++++++++++++++--------------- t/t3501-revert-cherry-pick.sh | 1 + t/t3507-cherry-pick-conflict.sh | 2 ++ t/t4150-am.sh | 8 ++++---- t/t4254-am-corrupt.sh | 2 +- 9 files changed, 39 insertions(+), 25 deletions(-)
base-commit: 2953d95d402b6bff1a59c4712f4d46f1b9ea137f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1682%2Fphil-blain%2Fsequencer-conflict-advice-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1682/phil-blain/sequencer-conflict-advice-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/1682
Range-diff vs v2:
1: a2ce6fd24c2 ! 1: 6005c1e9890 sequencer: allow disabling conflict advice
@@ Commit message
merge conflict through a new config 'advice.mergeConflict', which is named generically such that it can be used by other commands eventually.
+ Remove that final '\n' in the first hunk in sequencer.c to avoid an
+ otherwise empty 'hint: ' line before the line 'hint: Disable this
+ message with "git config advice.mergeConflict false"' which is
+ automatically added by 'advise_if_enabled'.
+
Note that we use 'advise_if_enabled' for each message in the second hunk in sequencer.c, instead of using 'if (show_hints && advice_enabled(...)', because the former instructs the user how to
@@ Commit message
Update the tests accordingly. Note that the body of the second test in t3507-cherry-pick-conflict.sh is enclosed in double quotes, so we must
- escape them in the added line.
+ escape them in the added line. Note that t5520-pull.sh, which checks
+ that we display the advice for 'git rebase' (via 'git pull --rebase')
+ does not have to be updated because it only greps for a specific line in
+ the advice message.
## Documentation/config/advice.txt ##
@@ Documentation/config/advice.txt: advice.*::
- Advice on how to set your identity configuration when
- your information is guessed from the system username and
- domain name.
+ Shown when the user's information is guessed from the
+ system username and domain name, to tell the user how to
+ set their identity configuration.
+ mergeConflict::
-+ Advice shown when various commands stop because of conflicts.
++ Shown when various commands stop because of conflicts.
nestedTag::
- Advice shown if a user attempts to recursively tag a tag object.
+ Shown when a user attempts to recursively tag a tag object.
pushAlreadyExists::
## advice.c ##
@@ advice.c: static struct {
## advice.h ##
@@ advice.h: enum advice_type {
+ ADVICE_GRAFT_FILE_DEPRECATED,
ADVICE_IGNORED_HOOK,
ADVICE_IMPLICIT_IDENTITY,
- ADVICE_NESTED_TAG,
+ ADVICE_MERGE_CONFLICT,
+ ADVICE_NESTED_TAG,
ADVICE_OBJECT_NAME_WARNING,
ADVICE_PUSH_ALREADY_EXISTS,
- ADVICE_PUSH_FETCH_FIRST,
## sequencer.c ##
@@ sequencer.c: static void print_advice(struct repository *r, int show_hint,
@@ sequencer.c: static void print_advice(struct repository *r, int show_hint,
if (msg) {
- advise("%s\n", msg);
-+ advise_if_enabled(ADVICE_MERGE_CONFLICT, "%s\n", msg);
++ advise_if_enabled(ADVICE_MERGE_CONFLICT, "%s", msg);
/*
* A conflict has occurred but the porcelain
* (typically rebase --interactive) wants to take care
2: 3235542cc6f ! 2: 73d07c8b6a7 builtin/am: allow disabling conflict advice
@@ Commit message
on stderr instead of stdout. In t4150, redirect stdout to 'out' and
stderr to 'err', since this is less confusing. In t4254, as we are
testing a specific failure mode of 'git am', simply disable the advice.
+ Note that we are not testing that this advice is shown in 'git rebase'
+ for the apply backend since 2ac0d6273f (rebase: change the default
+ backend from "am" to "merge", 2020-02-15).
+ Helped-by: Phillip Wood <[email protected]>
+ Helped-by: Junio C Hamano <[email protected]>
Signed-off-by: Philippe Blain <[email protected]>
## builtin/am.c ##
@@ builtin/am.c: static const char *msgnum(const struct am_state *state)
- printf_ln(_("When you have resolved this problem, run \"%s --continue\"."), cmdline);
- printf_ln(_("If you prefer to skip this patch, run \"%s --skip\" instead."), cmdline);
-+ strbuf_addf(&sb, _("When you have resolved this problem, run \"%s --continue\"."), cmdline);
-+ strbuf_addf(&sb, _("If you prefer to skip this patch, run \"%s --skip\" instead."), cmdline);
++ strbuf_addf(&sb, _("When you have resolved this problem, run \"%s --continue\".\n"), cmdline);
++ strbuf_addf(&sb, _("If you prefer to skip this patch, run \"%s --skip\" instead.\n"), cmdline);
if (advice_enabled(ADVICE_AM_WORK_DIR) &&
is_empty_or_missing_file(am_path(state, "patch")) &&
!repo_index_has_changes(the_repository, NULL, NULL))
- printf_ln(_("To record the empty patch as an empty commit, run \"%s --allow-empty\"."), cmdline);
-+ strbuf_addf(&sb, _("To record the empty patch as an empty commit, run \"%s --allow-empty\"."), cmdline);
++ strbuf_addf(&sb, _("To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"), cmdline);
- printf_ln(_("To restore the original branch and stop patching, run \"%s --abort\"."), cmdline);
+ strbuf_addf(&sb, _("To restore the original branch and stop patching, run \"%s --abort\"."), cmdline);Signature · 1 line
gitgitgadget
PATCH v3 1/2 sequencer: allow disabling conflict advice
From: Philippe Blain <[email protected]>
Allow disabling the advice shown when a squencer operation results in a merge conflict through a new config 'advice.mergeConflict', which is named generically such that it can be used by other commands eventually.
Remove that final '\n' in the first hunk in sequencer.c to avoid an otherwise empty 'hint: ' line before the line 'hint: Disable this message with "git config advice.mergeConflict false"' which is automatically added by 'advise_if_enabled'.
Note that we use 'advise_if_enabled' for each message in the second hunk in sequencer.c, instead of using 'if (show_hints && advice_enabled(...)', because the former instructs the user how to disable the advice, which is more user-friendly.
Update the tests accordingly. Note that the body of the second test in t3507-cherry-pick-conflict.sh is enclosed in double quotes, so we must escape them in the added line. Note that t5520-pull.sh, which checks that we display the advice for 'git rebase' (via 'git pull --rebase') does not have to be updated because it only greps for a specific line in the advice message.
--- Documentation/config/advice.txt | 2 ++ advice.c | 1 + advice.h | 1 + sequencer.c | 33 ++++++++++++++++++--------------- t/t3501-revert-cherry-pick.sh | 1 + t/t3507-cherry-pick-conflict.sh | 2 ++ 6 files changed, 25 insertions(+), 15 deletions(-)
Documentation/config/advice.txt +2 -0
@@ -56,6 +56,8 @@ advice.*:: Shown when the user's information is guessed from the system username and domain name, to tell the user how to set their identity configuration. + mergeConflict:: + Shown when various commands stop because of conflicts. nestedTag:: Shown when a user attempts to recursively tag a tag object. pushAlreadyExists::
advice.c +1 -0
@@ -57,6 +57,7 @@ static struct { [ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated" }, [ADVICE_IGNORED_HOOK] = { "ignoredHook" }, [ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity" }, + [ADVICE_MERGE_CONFLICT] = { "mergeConflict" }, [ADVICE_NESTED_TAG] = { "nestedTag" }, [ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning" }, [ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists" },
advice.h +1 -0
@@ -25,6 +25,7 @@ enum advice_type {ADVICE_GRAFT_FILE_DEPRECATED ,ADVICE_IGNORED_HOOK ,ADVICE_IMPLICIT_IDENTITY , +ADVICE_MERGE_CONFLICT ,ADVICE_NESTED_TAG ,ADVICE_OBJECT_NAME_WARNING , ADVICE_PUSH_ALREADY_EXISTS,
sequencer.c +18 -15
@@ -467,7 +467,7 @@ static void print_advice(struct repository *r, int show_hint,char *msg =getenv ("GIT_CHERRY_PICK_HELP" );if (msg) { -advise ("%s\n" , msg); +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , msg);/* * A conflict has occurred but the porcelain * (typically rebase --interactive) wants to take care
@@ -480,22 +480,25 @@ static void print_advice(struct repository *r, int show_hint,if (show_hint) {if (opts->no_commit) -advise (_ ("after resolving the conflicts, mark the corrected paths\n" -"with 'git add <paths>' or 'git rm <paths>'" )); +advise_if_enabled (ADVICE_MERGE_CONFLICT , +_ ("after resolving the conflicts, mark the corrected paths\n" +"with 'git add <paths>' or 'git rm <paths>'" ));else if (opts->action ==REPLAY_PICK ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git cherry-pick --continue\".\n" -"You can instead skip this commit with \"git cherry-pick --skip\".\n" -"To abort and get back to the state before \"git cherry-pick\",\n" -"run \"git cherry-pick --abort\"." )); +advise_if_enabled (ADVICE_MERGE_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git cherry-pick --continue\".\n" +"You can instead skip this commit with \"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->action ==REPLAY_REVERT ) -advise (_ ("After resolving the conflicts, mark them with\n" -"\"git add/rm <pathspec>\", then run\n" -"\"git revert --continue\".\n" -"You can instead skip this commit with \"git revert --skip\".\n" -"To abort and get back to the state before \"git revert\",\n" -"run \"git revert --abort\"." )); +advise_if_enabled (ADVICE_MERGE_CONFLICT , +_ ("After resolving the conflicts, mark them with\n" +"\"git add/rm <pathspec>\", then run\n" +"\"git revert --continue\".\n" +"You can instead skip this commit with \"git revert --skip\".\n" +"To abort and get back to the state before \"git revert\",\n" +"run \"git revert --abort\"." ));else BUG ("unexpected pick action in print_advice()" ); }
t/t3501-revert-cherry-pick.sh +1 -0
@@ -170,6 +170,7 @@ test_expect_success 'advice from failed revert' ' hint: You can instead skip this commit with "git revert --skip". hint: To abort and get back to the state before "git revert", hint: run "git revert --abort". + hint: Disable this message with "git config advice.mergeConflict false" EOF test_commit --append --no-tag "double-add dream" dream dream && test_must_fail git revert HEAD^ 2>actual &&
t/t3507-cherry-pick-conflict.sh +2 -0
@@ -60,6 +60,7 @@ test_expect_success 'advice from failed cherry-pick' ' hint: You can instead skip this commit with "git cherry-pick --skip". hint: To abort and get back to the state before "git cherry-pick", hint: run "git cherry-pick --abort". + hint: Disable this message with "git config advice.mergeConflict false" EOF test_must_fail git cherry-pick picked 2>actual &&
@@ -74,6 +75,7 @@ test_expect_success 'advice from failed cherry-pick --no-commit' " 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: Disable this message with \"git config advice.mergeConflict false\" EOF test_must_fail git cherry-pick --no-commit picked 2>actual &&
Signature · 1 line
gitgitgadget
PATCH v3 2/2 builtin/am: allow disabling conflict advice
In reply to Philippe Blain via GitGitGadgetFrom: Philippe Blain <[email protected]>
When 'git am' or 'git rebase --apply' encounter a conflict, they show a message instructing the user how to continue the operation. This message can't be disabled.
Use ADVICE_MERGE_CONFLICT introduced in the previous commit to allow disabling it. Update the tests accordingly, as the advice output is now on stderr instead of stdout. In t4150, redirect stdout to 'out' and stderr to 'err', since this is less confusing. In t4254, as we are testing a specific failure mode of 'git am', simply disable the advice. Note that we are not testing that this advice is shown in 'git rebase' for the apply backend since 2ac0d6273f (rebase: change the default backend from "am" to "merge", 2020-02-15).
--- builtin/am.c | 14 +++++++++----- t/t4150-am.sh | 8 ++++---- t/t4254-am-corrupt.sh | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-)
builtin/am.c +9 -5
@@ -1150,19 +1150,23 @@ static const char *msgnum(const struct am_state *state) static void NORETURN die_user_resolve(const struct am_state *state) {if (state->resolvemsg) { -printf_ln ("%s" , state->resolvemsg); +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , state->resolvemsg); }else {const char *cmdline = state->interactive ?"git am -i" :"git am" ; +struct strbuf sb =STRBUF_INIT ; -printf_ln (_ ("When you have resolved this problem, run \"%s --continue\"." ), cmdline); -printf_ln (_ ("If you prefer to skip this patch, run \"%s --skip\" instead." ), cmdline); +strbuf_addf (&sb,_ ("When you have resolved this problem, run \"%s --continue\".\n" ), cmdline); +strbuf_addf (&sb,_ ("If you prefer to skip this patch, run \"%s --skip\" instead.\n" ), cmdline);if (advice_enabled (ADVICE_AM_WORK_DIR ) &&is_empty_or_missing_file (am_path (state,"patch" )) && !repo_index_has_changes (the_repository,NULL ,NULL )) -printf_ln (_ ("To record the empty patch as an empty commit, run \"%s --allow-empty\"." ), cmdline); +strbuf_addf (&sb,_ ("To record the empty patch as an empty commit, run \"%s --allow-empty\".\n" ), cmdline); -printf_ln (_ ("To restore the original branch and stop patching, run \"%s --abort\"." ), cmdline); +strbuf_addf (&sb,_ ("To restore the original branch and stop patching, run \"%s --abort\"." ), cmdline); + +advise_if_enabled (ADVICE_MERGE_CONFLICT ,"%s" , sb.buf); +strbuf_release (&sb); }exit (128 );
t/t4150-am.sh +4 -4
@@ -1224,8 +1224,8 @@ test_expect_success 'record as an empty commit when meeting e-mail message that test_expect_success 'skip an empty patch in the middle of an am session' ' git checkout empty-commit^ && - test_must_fail git am empty-commit.patch >err && - grep "Patch is empty." err && + test_must_fail git am empty-commit.patch >out 2>err && + grep "Patch is empty." out && grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err && git am --skip && test_path_is_missing .git/rebase-apply &&
@@ -1236,8 +1236,8 @@ test_expect_success 'skip an empty patch in the middle of an am session' ' test_expect_success 'record an empty patch as an empty commit in the middle of an am session' ' git checkout empty-commit^ && - test_must_fail git am empty-commit.patch >err && - grep "Patch is empty." err && + test_must_fail git am empty-commit.patch >out 2>err && + grep "Patch is empty." out && grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err && git am --allow-empty >output && grep "No changes - recorded it as an empty commit." output &&
t/t4254-am-corrupt.sh +1 -1
@@ -59,7 +59,7 @@ test_expect_success setup ' # Also, it had the unwanted side-effect of deleting f. test_expect_success 'try to apply corrupted patch' ' test_when_finished "git am --abort" && - test_must_fail git -c advice.amWorkDir=false am bad-patch.diff 2>actual && + test_must_fail git -c advice.amWorkDir=false -c advice.mergeConflict=false am bad-patch.diff 2>actual && echo "error: git diff header lacks filename information (line 4)" >expected && test_path_is_file f && test_cmp expected actual
Signature · 1 line
gitgitgadget
Re: [PATCH v3 0/2] Allow disabling advice shown after merge conflicts
In reply to Philippe Blain via GitGitGadgetQuoted 8 lines · Philippe Blain via GitGitGadget
This series introduces a new config 'advice.mergeConflict' and uses it to allow disabling the advice shown when 'git rebase', 'git cherry-pick', 'git revert', 'git rebase --apply' and 'git am' stop because of conflicts.
Thanks everyone for the reviews!
Changes since v2:
Quoted 15 lines
* expanded the commit messages to explain why the tests for 'git rebase' do not need to be adjusted
* adjusted the wording of the new 'advice.mergeConflict' in the doc, as suggested by Kristoffer for uniformity with his series which is already merged to 'master' (b09a8839a4(Merge branch 'kh/branch-ref-syntax-advice', 2024-03-15)).
* checked all new output manually and consequently adjusted the code in 1/2 to avoid a lonely 'hint: ' line.
* adjusted the addition inadvice.hin 1/2 to put the new enum alphabetically, as noticed by Rubén.
* added misssing newlines in 2/2 as noticed by Phillip and tweaked by Junio.
* rebased on master (2953d95d40(The eighth batch, 2024-03-15)), to avoid conflicts in 'Documentation/config/advice.txt' due to Kristoffer's merged series
Looking good; will queue. Thanks.
Re: [PATCH v3 0/2] Allow disabling advice shown after merge conflicts
In reply to Philippe Blain via GitGitGadgetHi Philippe
Quoted 25 lines · Philippe Blain via GitGitGadget
Changes since v2:
* expanded the commit messages to explain why the tests for 'git rebase' do not need to be adjusted
* adjusted the wording of the new 'advice.mergeConflict' in the doc, as suggested by Kristoffer for uniformity with his series which is already merged to 'master' (b09a8839a4(Merge branch 'kh/branch-ref-syntax-advice', 2024-03-15)).
* checked all new output manually and consequently adjusted the code in 1/2 to avoid a lonely 'hint: ' line.
* adjusted the addition inadvice.hin 1/2 to put the new enum alphabetically, as noticed by Rubén.
* added misssing newlines in 2/2 as noticed by Phillip and tweaked by Junio.
* rebased on master (2953d95d40(The eighth batch, 2024-03-15)), to avoid
conflicts in 'Documentation/config/advice.txt' due to Kristoffer's merged > series
[...] Note that the code path where 'git rebase --apply' stops because of conflicts is not covered by the tests but I tested it manually using this diff:t/t5520-pull.sh +0
-0
t/t5520-pull.sh test_pull_autostash_fail () · line 379
Quoted 7 lines
t/t5520-pull.sh +1
-1@@ -374,7 +374,7 @@ test_pull_autostash_fail () echo conflicting >>seq.txt && test_tick && git commit -m "Create conflict" seq.txt && - test_must_fail git pull --rebase . seq 2>err >out && + test_must_fail git -c rebase.backend=apply pull --rebase . seq 2>err >out && test_grep "Resolve all conflicts manually" err '
Thanks for being so thorough, this version looks good to me
Best Wishes
Phillip
Quoted 124 lines
Philippe Blain (2):
sequencer: allow disabling conflict advice
builtin/am: allow disabling conflict adviceDocumentation/config/advice.txt | 2 ++ advice.c | 1 + advice.h | 1 + builtin/am.c | 14 +++++++++----- sequencer.c | 33 ++++++++++++++++++--------------- t/t3501-revert-cherry-pick.sh | 1 + t/t3507-cherry-pick-conflict.sh | 2 ++ t/t4150-am.sh | 8 ++++---- t/t4254-am-corrupt.sh | 2 +- 9 files changed, 39 insertions(+), 25 deletions(-)base-commit:
2953d95d402b6bff1a59c4712f4d46f1b9ea137f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1682%2Fphil-blain%2Fsequencer-conflict-advice-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1682/phil-blain/sequencer-conflict-advice-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/1682Range-diff vs v2:
1:
a2ce6fd24c2! 1:6005c1e9890sequencer: allow disabling conflict advice
@@ Commit message
merge conflict through a new config 'advice.mergeConflict', which is named generically such that it can be used by other commands eventually.+ Remove that final '\n' in the first hunk in
sequencer.cto avoid an
+ otherwise empty 'hint: ' line before the line 'hint: Disable this
+ message with "git config advice.mergeConflict false"' which is
+ automatically added by 'advise_if_enabled'.
+
Note that we use 'advise_if_enabled' for each message in the second hunk insequencer.c, instead of using 'if (show_hints&&advice_enabled(...)', because the former instructs the user how to
@@ Commit messageUpdate the tests accordingly. Note that the body of the second test in
t3507-cherry-pick-conflict.shis enclosed in double quotes, so we must
- escape them in the added line.
+ escape them in the added line. Note thatt5520-pull.sh, which checks
+ that we display the advice for 'git rebase' (via 'git pull --rebase')
+ does not have to be updated because it only greps for a specific line in
+ the advice message.Signed-off-by Philippe Blain <[email protected]>##
Documentation/config/advice.txt##
@@Documentation/config/advice.txt: advice.*::
- Advice on how to set your identity configuration when
- your information is guessed from the system username and
- domain name.
+ Shown when the user's information is guessed from the
+ system username and domain name, to tell the user how to
+ set their identity configuration.
+ mergeConflict::
-+ Advice shown when various commands stop because of conflicts.
++ Shown when various commands stop because of conflicts.
nestedTag::
- Advice shown if a user attempts to recursively tag a tag object.
+ Shown when a user attempts to recursively tag a tag object.
pushAlreadyExists::##
advice.c##
@@advice.c: static struct {##
advice.h##
@@advice.h: enumadvice_type{
+ADVICE_GRAFT_FILE_DEPRECATED,
ADVICE_IGNORED_HOOK,
ADVICE_IMPLICIT_IDENTITY,
-ADVICE_NESTED_TAG,
+ADVICE_MERGE_CONFLICT,
+ADVICE_NESTED_TAG,
ADVICE_OBJECT_NAME_WARNING,
ADVICE_PUSH_ALREADY_EXISTS,
-ADVICE_PUSH_FETCH_FIRST,##
sequencer.c##
@@sequencer.c: static void print_advice(struct repository *r, intshow_hint,
@@sequencer.c: static void print_advice(struct repository *r, intshow_hint,if (msg) {
-advise("%s\n", msg);
-+advise_if_enabled(ADVICE_MERGE_CONFLICT, "%s\n", msg);
++advise_if_enabled(ADVICE_MERGE_CONFLICT, "%s", msg);
/*
* A conflict has occurred but the porcelain
* (typically rebase --interactive) wants to take care
2:3235542cc6f! 2:73d07c8b6a7builtin/am: allow disabling conflict advice@@ Commit message on stderr instead of stdout. In t4150, redirect stdout to 'out' and stderr to 'err', since this is less confusing. In t4254, as we are testing a specific failure mode of 'git am', simply disable the advice. + Note that we are not testing that this advice is shown in 'git rebase' + for the apply backend since 2ac0d6273f (rebase: change the default + backend from "am" to "merge", 2020-02-15). + Helped-by: Phillip Wood <[email protected]> + Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Philippe Blain <[email protected]> ## builtin/am.c ## @@ builtin/am.c: static const char *msgnum(const struct am_state *state) - printf_ln(_("When you have resolved this problem, run \"%s --continue\"."), cmdline); - printf_ln(_("If you prefer to skip this patch, run \"%s --skip\" instead."), cmdline); -+ strbuf_addf(&sb, _("When you have resolved this problem, run \"%s --continue\"."), cmdline); -+ strbuf_addf(&sb, _("If you prefer to skip this patch, run \"%s --skip\" instead."), cmdline); ++ strbuf_addf(&sb, _("When you have resolved this problem, run \"%s --continue\".\n"), cmdline); ++ strbuf_addf(&sb, _("If you prefer to skip this patch, run \"%s --skip\" instead.\n"), cmdline); if (advice_enabled(ADVICE_AM_WORK_DIR) && is_empty_or_missing_file(am_path(state, "patch")) && !repo_index_has_changes(the_repository, NULL, NULL)) - printf_ln(_("To record the empty patch as an empty commit, run \"%s --allow-empty\"."), cmdline); -+ strbuf_addf(&sb, _("To record the empty patch as an empty commit, run \"%s --allow-empty\"."), cmdline); ++ strbuf_addf(&sb, _("To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"), cmdline); - printf_ln(_("To restore the original branch and stop patching, run \"%s --abort\"."), cmdline); + strbuf_addf(&sb, _("To restore the original branch and stop patching, run \"%s --abort\"."), cmdline);
Re: [PATCH v3 0/2] Allow disabling advice shown after merge conflicts
Quoted 29 lines · Phillip Wood
Hi Philippe
Quoted 26 lines · Philippe Blain via GitGitGadget
Changes since v2:
* expanded the commit messages to explain why the tests for 'git
rebase' do
not need to be adjusted
* adjusted the wording of the new 'advice.mergeConflict' in the doc, as suggested by Kristoffer for uniformity with his series which is already merged to 'master' (b09a8839a4(Merge branch 'kh/branch-ref-syntax-advice', 2024-03-15)).
* checked all new output manually and consequently adjusted the code in 1/2 to avoid a lonely 'hint: ' line.
* adjusted the addition inadvice.hin 1/2 to put the new enum alphabetically, as noticed by Rubén.
* added misssing newlines in 2/2 as noticed by Phillip and tweaked by Junio.
* rebased on master (2953d95d40(The eighth batch, 2024-03-15)), to avoid
conflicts in 'Documentation/config/advice.txt' due to Kristoffer's merged > series
[...] Note that the code path where 'git rebase --apply' stops because of
conflicts is not covered by the tests but I tested it manually using this diff:t/t5520-pull.sh +0
-0@@ -374,7 +374,7 @@ test_pull_autostash_fail () echo conflicting >>seq.txt &&
Quoted 8 lines
t/t5520-pull.sh test_pull_autostash_fail () · line 379
Quoted 6 lines
t/t5520-pull.sh +1
-1test_tick && git commit -m "Create conflict" seq.txt && - test_must_fail git pull --rebase . seq 2>err >out && + test_must_fail git -c rebase.backend=apply pull --rebase . seq 2>err >out && test_grep "Resolve all conflicts manually" err 'Thanks for being so thorough, this version looks good to me
Yup, these look good. Let's mark the topic for 'next'.
Thanks, both.