Skip to content

Commit b877cb4

Browse files
committed
Merge branch 'dl/merge-cleanup-scissors-fix'
The list of conflicted paths shown in the editor while concluding a conflicted merge was shown above the scissors line when the clean-up mode is set to "scissors", even though it was commented out just like the list of updated paths and other information to help the user explain the merge better. * dl/merge-cleanup-scissors-fix: cherry-pick/revert: add scissors line on merge conflict sequencer.c: save and restore cleanup mode merge: add scissors line on merge conflict merge: cleanup messages like commit parse-options.h: extract common --cleanup option commit: extract cleanup_mode functions to sequencer t7502: clean up style t7604: clean up style t3507: clean up style t7600: clean up style
2 parents f757794 + 1a2b985 commit b877cb4

18 files changed

+484
-132
lines changed

Documentation/git-cherry-pick.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ OPTIONS
5757
With this option, 'git cherry-pick' will let you edit the commit
5858
message prior to committing.
5959

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+
6067
-x::
6168
When recording the commit, append a line that says
6269
"(cherry picked from commit ...)" to the original commit

Documentation/git-revert.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ more details.
6666
With this option, 'git revert' will not start the commit
6767
message editor.
6868

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+
6976
-n::
7077
--no-commit::
7178
Usually the command automatically creates some commits with

Documentation/merge-options.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ they run `git merge`. To make it easier to adjust such scripts to the
3232
updated behaviour, the environment variable `GIT_MERGE_AUTOEDIT` can be
3333
set to `no` at the beginning of them.
3434

35+
--cleanup=<mode>::
36+
This option determines how the merge message will be cleaned up before
37+
commiting. See linkgit:git-commit[1] for more details. In addition, if
38+
the '<mode>' is given a value of `scissors`, scissors will be appended
39+
to `MERGE_MSG` before being passed on to the commit machinery in the
40+
case of a merge conflict.
41+
3542
--ff::
3643
When the merge resolves as a fast-forward, only update the branch
3744
pointer, without creating a merge commit. This is the default

builtin/commit.c

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
668668
const char *hook_arg2 = NULL;
669669
int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE);
670670
int old_display_comment_prefix;
671+
int merge_contains_scissors = 0;
671672

672673
/* This checks and barfs if author is badly specified */
673674
determine_author_info(author_ident);
@@ -728,6 +729,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
728729
strbuf_addbuf(&sb, &message);
729730
hook_arg1 = "message";
730731
} else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
732+
size_t merge_msg_start;
733+
731734
/*
732735
* prepend SQUASH_MSG here if it exists and a
733736
* "merge --squash" was originally performed
@@ -738,8 +741,16 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
738741
hook_arg1 = "squash";
739742
} else
740743
hook_arg1 = "merge";
744+
745+
merge_msg_start = sb.len;
741746
if (strbuf_read_file(&sb, git_path_merge_msg(the_repository), 0) < 0)
742747
die_errno(_("could not read MERGE_MSG"));
748+
749+
if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
750+
wt_status_locate_end(sb.buf + merge_msg_start,
751+
sb.len - merge_msg_start) <
752+
sb.len - merge_msg_start)
753+
merge_contains_scissors = 1;
743754
} else if (!stat(git_path_squash_msg(the_repository), &statbuf)) {
744755
if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0)
745756
die_errno(_("could not read SQUASH_MSG"));
@@ -807,7 +818,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
807818
struct ident_split ci, ai;
808819

809820
if (whence != FROM_COMMIT) {
810-
if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS)
821+
if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
822+
!merge_contains_scissors)
811823
wt_status_add_cut_line(s->fp);
812824
status_printf_ln(s, GIT_COLOR_NORMAL,
813825
whence == FROM_MERGE
@@ -832,10 +844,10 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
832844
_("Please enter the commit message for your changes."
833845
" Lines starting\nwith '%c' will be ignored, and an empty"
834846
" message aborts the commit.\n"), comment_line_char);
835-
else if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
836-
whence == FROM_COMMIT)
837-
wt_status_add_cut_line(s->fp);
838-
else /* COMMIT_MSG_CLEANUP_SPACE, that is. */
847+
else if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
848+
if (whence == FROM_COMMIT && !merge_contains_scissors)
849+
wt_status_add_cut_line(s->fp);
850+
} else /* COMMIT_MSG_CLEANUP_SPACE, that is. */
839851
status_printf(s, GIT_COLOR_NORMAL,
840852
_("Please enter the commit message for your changes."
841853
" Lines starting\n"
@@ -1172,24 +1184,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
11721184
die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
11731185
if (argc == 0 && (also || (only && !amend && !allow_empty)))
11741186
die(_("No paths with --include/--only does not make sense."));
1175-
if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
1176-
cleanup_mode = use_editor ? COMMIT_MSG_CLEANUP_ALL :
1177-
COMMIT_MSG_CLEANUP_SPACE;
1178-
else if (!strcmp(cleanup_arg, "verbatim"))
1179-
cleanup_mode = COMMIT_MSG_CLEANUP_NONE;
1180-
else if (!strcmp(cleanup_arg, "whitespace"))
1181-
cleanup_mode = COMMIT_MSG_CLEANUP_SPACE;
1182-
else if (!strcmp(cleanup_arg, "strip"))
1183-
cleanup_mode = COMMIT_MSG_CLEANUP_ALL;
1184-
else if (!strcmp(cleanup_arg, "scissors"))
1185-
cleanup_mode = use_editor ? COMMIT_MSG_CLEANUP_SCISSORS :
1186-
COMMIT_MSG_CLEANUP_SPACE;
1187-
/*
1188-
* Please update _git_commit() in git-completion.bash when you
1189-
* add new options.
1190-
*/
1191-
else
1192-
die(_("Invalid cleanup mode %s"), cleanup_arg);
1187+
cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
11931188

11941189
handle_untracked_files_arg(s);
11951190

@@ -1491,7 +1486,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
14911486
OPT_BOOL('s', "signoff", &signoff, N_("add Signed-off-by:")),
14921487
OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
14931488
OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
1494-
OPT_STRING(0, "cleanup", &cleanup_arg, N_("default"), N_("how to strip spaces and #comments from message")),
1489+
OPT_CLEANUP(&cleanup_arg),
14951490
OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")),
14961491
{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
14971492
N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
@@ -1627,11 +1622,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
16271622
die(_("could not read commit message: %s"), strerror(saved_errno));
16281623
}
16291624

1630-
if (verbose || /* Truncate the message just before the diff, if any. */
1631-
cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS)
1632-
strbuf_setlen(&sb, wt_status_locate_end(sb.buf, sb.len));
1633-
if (cleanup_mode != COMMIT_MSG_CLEANUP_NONE)
1634-
strbuf_stripspace(&sb, cleanup_mode == COMMIT_MSG_CLEANUP_ALL);
1625+
cleanup_message(&sb, cleanup_mode, verbose);
16351626

16361627
if (message_is_empty(&sb, cleanup_mode) && !allow_empty_message) {
16371628
rollback_index_files();

builtin/merge.c

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "tag.h"
3939
#include "alias.h"
4040
#include "commit-reach.h"
41+
#include "wt-status.h"
4142

4243
#define DEFAULT_TWOHEAD (1<<0)
4344
#define DEFAULT_OCTOPUS (1<<1)
@@ -98,6 +99,9 @@ enum ff_type {
9899

99100
static enum ff_type fast_forward = FF_ALLOW;
100101

102+
static const char *cleanup_arg;
103+
static enum commit_msg_cleanup_mode cleanup_mode;
104+
101105
static int option_parse_message(const struct option *opt,
102106
const char *arg, int unset)
103107
{
@@ -249,6 +253,7 @@ static struct option builtin_merge_options[] = {
249253
N_("perform a commit if the merge succeeds (default)")),
250254
OPT_BOOL('e', "edit", &option_edit,
251255
N_("edit message before committing")),
256+
OPT_CLEANUP(&cleanup_arg),
252257
OPT_SET_INT(0, "ff", &fast_forward, N_("allow fast-forward (default)"), FF_ALLOW),
253258
OPT_SET_INT_F(0, "ff-only", &fast_forward,
254259
N_("abort if fast-forward is not possible"),
@@ -612,6 +617,8 @@ static int git_merge_config(const char *k, const char *v, void *cb)
612617
return git_config_string(&pull_twohead, k, v);
613618
else if (!strcmp(k, "pull.octopus"))
614619
return git_config_string(&pull_octopus, k, v);
620+
else if (!strcmp(k, "commit.cleanup"))
621+
return git_config_string(&cleanup_arg, k, v);
615622
else if (!strcmp(k, "merge.renormalize"))
616623
option_renormalize = git_config_bool(k, v);
617624
else if (!strcmp(k, "merge.ff")) {
@@ -800,20 +807,33 @@ static void abort_commit(struct commit_list *remoteheads, const char *err_msg)
800807
static const char merge_editor_comment[] =
801808
N_("Please enter a commit message to explain why this merge is necessary,\n"
802809
"especially if it merges an updated upstream into a topic branch.\n"
803-
"\n"
804-
"Lines starting with '%c' will be ignored, and an empty message aborts\n"
810+
"\n");
811+
812+
static const char scissors_editor_comment[] =
813+
N_("An empty message aborts the commit.\n");
814+
815+
static const char no_scissors_editor_comment[] =
816+
N_("Lines starting with '%c' will be ignored, and an empty message aborts\n"
805817
"the commit.\n");
806818

807819
static void write_merge_heads(struct commit_list *);
808820
static void prepare_to_commit(struct commit_list *remoteheads)
809821
{
810822
struct strbuf msg = STRBUF_INIT;
811823
strbuf_addbuf(&msg, &merge_msg);
812-
strbuf_addch(&msg, '\n');
813824
if (squash)
814825
BUG("the control must not reach here under --squash");
815-
if (0 < option_edit)
816-
strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);
826+
if (0 < option_edit) {
827+
strbuf_addch(&msg, '\n');
828+
if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
829+
wt_status_append_cut_line(&msg);
830+
strbuf_commented_addf(&msg, "\n");
831+
}
832+
strbuf_commented_addf(&msg, _(merge_editor_comment));
833+
strbuf_commented_addf(&msg, _(cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS ?
834+
scissors_editor_comment :
835+
no_scissors_editor_comment), comment_line_char);
836+
}
817837
if (signoff)
818838
append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0);
819839
write_merge_heads(remoteheads);
@@ -832,7 +852,7 @@ static void prepare_to_commit(struct commit_list *remoteheads)
832852
abort_commit(remoteheads, NULL);
833853

834854
read_merge_msg(&msg);
835-
strbuf_stripspace(&msg, 0 < option_edit);
855+
cleanup_message(&msg, cleanup_mode, 0);
836856
if (!msg.len)
837857
abort_commit(remoteheads, _("Empty commit message."));
838858
strbuf_release(&merge_msg);
@@ -880,7 +900,6 @@ static int finish_automerge(struct commit *head,
880900
parents = remoteheads;
881901
if (!head_subsumed || fast_forward == FF_NO)
882902
commit_list_insert(head, &parents);
883-
strbuf_addch(&merge_msg, '\n');
884903
prepare_to_commit(remoteheads);
885904
if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,
886905
&result_commit, NULL, sign_commit))
@@ -901,7 +920,15 @@ static int suggest_conflicts(void)
901920
filename = git_path_merge_msg(the_repository);
902921
fp = xfopen(filename, "a");
903922

904-
append_conflicts_hint(&the_index, &msgbuf);
923+
/*
924+
* We can't use cleanup_mode because if we're not using the editor,
925+
* get_cleanup_mode will return COMMIT_MSG_CLEANUP_SPACE instead, even
926+
* though the message is meant to be processed later by git-commit.
927+
* Thus, we will get the cleanup mode which is returned when we _are_
928+
* using an editor.
929+
*/
930+
append_conflicts_hint(&the_index, &msgbuf,
931+
get_cleanup_mode(cleanup_arg, 1));
905932
fputs(msgbuf.buf, fp);
906933
strbuf_release(&msgbuf);
907934
fclose(fp);
@@ -1301,6 +1328,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
13011328
}
13021329
resolve_undo_clear();
13031330

1331+
if (option_edit < 0)
1332+
option_edit = default_edit_option();
1333+
1334+
cleanup_mode = get_cleanup_mode(cleanup_arg, 0 < option_edit);
1335+
13041336
if (verbosity < 0)
13051337
show_diffstat = 0;
13061338

@@ -1386,9 +1418,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
13861418
fast_forward = FF_NO;
13871419
}
13881420

1389-
if (option_edit < 0)
1390-
option_edit = default_edit_option();
1391-
13921421
if (!use_strategies) {
13931422
if (!remoteheads)
13941423
; /* already up-to-date */

builtin/pull.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "lockfile.h"
2525
#include "wt-status.h"
2626
#include "commit-reach.h"
27+
#include "sequencer.h"
2728

2829
enum rebase_type {
2930
REBASE_INVALID = -1,
@@ -101,6 +102,7 @@ static char *opt_signoff;
101102
static char *opt_squash;
102103
static char *opt_commit;
103104
static char *opt_edit;
105+
static char *cleanup_arg;
104106
static char *opt_ff;
105107
static char *opt_verify_signatures;
106108
static int opt_autostash = -1;
@@ -168,6 +170,7 @@ static struct option pull_options[] = {
168170
OPT_PASSTHRU(0, "edit", &opt_edit, NULL,
169171
N_("edit message before committing"),
170172
PARSE_OPT_NOARG),
173+
OPT_CLEANUP(&cleanup_arg),
171174
OPT_PASSTHRU(0, "ff", &opt_ff, NULL,
172175
N_("allow fast-forward"),
173176
PARSE_OPT_NOARG),
@@ -645,6 +648,8 @@ static int run_merge(void)
645648
argv_array_push(&args, opt_commit);
646649
if (opt_edit)
647650
argv_array_push(&args, opt_edit);
651+
if (cleanup_arg)
652+
argv_array_pushf(&args, "--cleanup=%s", cleanup_arg);
648653
if (opt_ff)
649654
argv_array_push(&args, opt_ff);
650655
if (opt_verify_signatures)
@@ -876,6 +881,13 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
876881

877882
argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
878883

884+
if (cleanup_arg)
885+
/*
886+
* this only checks the validity of cleanup_arg; we don't need
887+
* a valid value for use_editor
888+
*/
889+
get_cleanup_mode(cleanup_arg, 0);
890+
879891
parse_repo_refspecs(argc, argv, &repo, &refspecs);
880892

881893
if (!opt_ff)

builtin/revert.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,13 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
9696
{
9797
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
9898
const char *me = action_name(opts);
99+
const char *cleanup_arg = NULL;
99100
int cmd = 0;
100101
struct option base_options[] = {
101102
OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'),
102103
OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'),
103104
OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'),
105+
OPT_CLEANUP(&cleanup_arg),
104106
OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")),
105107
OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")),
106108
OPT_NOOP_NOARG('r', NULL),
@@ -137,6 +139,11 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
137139
if (opts->keep_redundant_commits)
138140
opts->allow_empty = 1;
139141

142+
if (cleanup_arg) {
143+
opts->default_msg_cleanup = get_cleanup_mode(cleanup_arg, 1);
144+
opts->explicit_cleanup = 1;
145+
}
146+
140147
/* Check for incompatible command line arguments */
141148
if (cmd) {
142149
char *this_operation;

builtin/tag.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
408408
OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
409409
OPT_BOOL('e', "edit", &edit_flag, N_("force edit of tag message")),
410410
OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
411-
OPT_STRING(0, "cleanup", &cleanup_arg, N_("mode"),
412-
N_("how to strip spaces and #comments from message")),
411+
OPT_CLEANUP(&cleanup_arg),
413412
OPT_STRING('u', "local-user", &keyid, N_("key-id"),
414413
N_("use another key to sign the tag")),
415414
OPT__FORCE(&force, N_("replace the tag if exists"), 0),

parse-options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,5 +316,6 @@ int parse_opt_passthru_argv(const struct option *, const char *, int);
316316
#define OPT_NO_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("no-contains", v, h, PARSE_OPT_NONEG)
317317
#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG)
318318
#define OPT_WITHOUT(v, h) _OPT_CONTAINS_OR_WITH("without", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG)
319+
#define OPT_CLEANUP(v) OPT_STRING(0, "cleanup", v, N_("mode"), N_("how to strip spaces and #comments from message"))
319320

320321
#endif

0 commit comments

Comments
 (0)