cherry-pick/revert: add scissors line on merge conflict
Fix a bug where the scissors line is placed after the Conflicts: section, in the case where a merge conflict occurs and commit.cleanup = scissors. Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Denton Liu committed
Apr 17, 2019 at 11:23 UTC
1a2b985fb375e7ce14932bfc59365024af2fb6ab
7 files changed
+122
-14
Documentation/git-cherry-pick.txt
+7
@@ -57,6 +57,13 @@ OPTIONS
57
With this option, 'git cherry-pick' will let you edit the commit
58
message prior to committing.
59
60
+--cleanup=<mode>::
61
+ This option determines how the commit message will be cleaned up before
62
+ being passed on to the commit machinery. See linkgit:git-commit[1] for more
63
+ details. In particular, if the '<mode>' is given a value of `scissors`,
64
+ scissors will be appended to `MERGE_MSG` before being passed on in the case
65
+ of a conflict.
66
+
67
-x::
68
When recording the commit, append a line that says
69
"(cherry picked from commit ...)" to the original commit
Documentation/git-revert.txt
+7
@@ -66,6 +66,13 @@ more details.
66
With this option, 'git revert' will not start the commit
67
message editor.
68
69
+--cleanup=<mode>::
70
+ This option determines how the commit message will be cleaned up before
71
+ being passed on to the commit machinery. See linkgit:git-commit[1] for more
72
+ details. In particular, if the '<mode>' is given a value of `scissors`,
73
+ scissors will be appended to `MERGE_MSG` before being passed on in the case
74
+ of a conflict.
75
+
76
-n::
77
--no-commit::
78
Usually the command automatically creates some commits with
builtin/merge.c
+2
-8
@@ -927,14 +927,8 @@ static int suggest_conflicts(void)
927
* Thus, we will get the cleanup mode which is returned when we _are_
928
* using an editor.
929
*/
930
- if (get_cleanup_mode(cleanup_arg, 1) == COMMIT_MSG_CLEANUP_SCISSORS) {
931
- fputc('\n', fp);
932
- wt_status_add_cut_line(fp);
933
- /* comments out the newline from append_conflicts_hint */
934
- fputc(comment_line_char, fp);
935
- }
936
-
937
- append_conflicts_hint(&the_index, &msgbuf);
930
+ append_conflicts_hint(&the_index, &msgbuf,
931
+ get_cleanup_mode(cleanup_arg, 1));
932
fputs(msgbuf.buf, fp);
933
strbuf_release(&msgbuf);
934
fclose(fp);
builtin/revert.c
+7
@@ -96,11 +96,13 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
96
{
97
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
98
const char *me = action_name(opts);
99
+ const char *cleanup_arg = NULL;
100
int cmd = 0;
101
struct option base_options[] = {
102
OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'),
103
OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'),
104
OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'),
105
+ OPT_CLEANUP(&cleanup_arg),
106
OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")),
107
OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")),
108
OPT_NOOP_NOARG('r', NULL),
@@ -137,6 +139,11 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
139
if (opts->keep_redundant_commits)
140
opts->allow_empty = 1;
141
142
+ if (cleanup_arg) {
143
+ opts->default_msg_cleanup = get_cleanup_mode(cleanup_arg, 1);
144
+ opts->explicit_cleanup = 1;
145
+ }
146
+
147
/* Check for incompatible command line arguments */
148
if (cmd) {
149
char *this_operation;
sequencer.c
+11
-5
@@ -182,7 +182,7 @@ static int git_sequencer_config(const char *k, const char *v, void *cb)
182
opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_ALL;
183
opts->explicit_cleanup = 1;
184
} else if (!strcmp(s, "scissors")) {
185
- opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_SPACE;
185
+ opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_SCISSORS;
186
opts->explicit_cleanup = 1;
187
} else {
188
warning(_("invalid commit message cleanup mode '%s'"),
@@ -554,10 +554,16 @@ static const char *describe_cleanup_mode(int cleanup_mode)
554
}
555
556
void append_conflicts_hint(struct index_state *istate,
557
- struct strbuf *msgbuf)
557
+ struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode)
558
{
559
int i;
560
561
+ if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
562
+ strbuf_addch(msgbuf, '\n');
563
+ wt_status_append_cut_line(msgbuf);
564
+ strbuf_addch(msgbuf, comment_line_char);
565
+ }
566
+
567
strbuf_addch(msgbuf, '\n');
568
strbuf_commented_addf(msgbuf, "Conflicts:\n");
569
for (i = 0; i < istate->cache_nr;) {
@@ -625,7 +631,8 @@ static int do_recursive_merge(struct repository *r,
631
_(action_name(opts)));
632
633
if (!clean)
628
- append_conflicts_hint(r->index, msgbuf);
634
+ append_conflicts_hint(r->index, msgbuf,
635
+ opts->default_msg_cleanup);
636
637
return !clean;
638
}
@@ -944,7 +951,6 @@ static int run_git_commit(struct repository *r,
951
unsigned int flags)
952
{
953
struct child_process cmd = CHILD_PROCESS_INIT;
947
- const char *value;
954
955
if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
956
struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
@@ -1014,7 +1020,7 @@ static int run_git_commit(struct repository *r,
1020
argv_array_push(&cmd.args, "-e");
1021
else if (!(flags & CLEANUP_MSG) &&
1022
!opts->signoff && !opts->record_origin &&
1017
- git_config_get_value("commit.cleanup", &value))
1023
+ !opts->explicit_cleanup)
1024
argv_array_push(&cmd.args, "--cleanup=verbatim");
1025
1026
if ((flags & ALLOW_EMPTY))
sequencer.h
+2
-1
@@ -116,7 +116,8 @@ int rearrange_squash(struct repository *r);
116
*/
117
void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag);
118
119
-void append_conflicts_hint(struct index_state *istate, struct strbuf *msgbuf);
119
+void append_conflicts_hint(struct index_state *istate,
120
+ struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode);
121
enum commit_msg_cleanup_mode get_cleanup_mode(const char *cleanup_arg,
122
int use_editor);
123
t/t3507-cherry-pick-conflict.sh
+86
@@ -189,6 +189,46 @@ test_expect_success 'failed cherry-pick registers participants in index' '
189
test_cmp expected actual
190
'
191
192
+test_expect_success \
193
+ 'cherry-pick conflict, ensure commit.cleanup = scissors places scissors line properly' '
194
+ pristine_detach initial &&
195
+ git config commit.cleanup scissors &&
196
+ cat <<-EOF >expected &&
197
+ picked
198
+
199
+ # ------------------------ >8 ------------------------
200
+ # Do not modify or remove the line above.
201
+ # Everything below it will be ignored.
202
+ #
203
+ # Conflicts:
204
+ # foo
205
+ EOF
206
+
207
+ test_must_fail git cherry-pick picked &&
208
+
209
+ test_i18ncmp expected .git/MERGE_MSG
210
+'
211
+
212
+test_expect_success \
213
+ 'cherry-pick conflict, ensure cleanup=scissors places scissors line properly' '
214
+ pristine_detach initial &&
215
+ git config --unset commit.cleanup &&
216
+ cat <<-EOF >expected &&
217
+ picked
218
+
219
+ # ------------------------ >8 ------------------------
220
+ # Do not modify or remove the line above.
221
+ # Everything below it will be ignored.
222
+ #
223
+ # Conflicts:
224
+ # foo
225
+ EOF
226
+
227
+ test_must_fail git cherry-pick --cleanup=scissors picked &&
228
+
229
+ test_i18ncmp expected .git/MERGE_MSG
230
+'
231
+
232
test_expect_success 'failed cherry-pick describes conflict in work tree' '
233
pristine_detach initial &&
234
cat <<-EOF >expected &&
@@ -335,6 +375,52 @@ test_expect_success 'revert conflict, diff3 -m style' '
375
test_cmp expected actual
376
'
377
378
+test_expect_success \
379
+ 'revert conflict, ensure commit.cleanup = scissors places scissors line properly' '
380
+ pristine_detach initial &&
381
+ git config commit.cleanup scissors &&
382
+ cat >expected <<-EOF &&
383
+ Revert "picked"
384
+
385
+ This reverts commit OBJID.
386
+
387
+ # ------------------------ >8 ------------------------
388
+ # Do not modify or remove the line above.
389
+ # Everything below it will be ignored.
390
+ #
391
+ # Conflicts:
392
+ # foo
393
+ EOF
394
+
395
+ test_must_fail git revert picked &&
396
+
397
+ sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual &&
398
+ test_i18ncmp expected actual
399
+'
400
+
401
+test_expect_success \
402
+ 'revert conflict, ensure cleanup=scissors places scissors line properly' '
403
+ pristine_detach initial &&
404
+ git config --unset commit.cleanup &&
405
+ cat >expected <<-EOF &&
406
+ Revert "picked"
407
+
408
+ This reverts commit OBJID.
409
+
410
+ # ------------------------ >8 ------------------------
411
+ # Do not modify or remove the line above.
412
+ # Everything below it will be ignored.
413
+ #
414
+ # Conflicts:
415
+ # foo
416
+ EOF
417
+
418
+ test_must_fail git revert --cleanup=scissors picked &&
419
+
420
+ sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual &&
421
+ test_i18ncmp expected actual
422
+'
423
+
424
test_expect_success 'failed cherry-pick does not forget -s' '
425
pristine_detach initial &&
426
test_must_fail git cherry-pick -s picked &&