Skip to content

Commit

Permalink
merge: cleanup messages like commit
Browse files Browse the repository at this point in the history
This change allows git-merge messages to be cleaned up with the
commit.cleanup configuration or --cleanup option, just like how
git-commit does it.

We also give git-pull the option of --cleanup so that it can also take
advantage of this change.

Finally, add testing to ensure that messages are properly cleaned up.
Note that some newlines that were added to the commit message were
removed so that if a file were read via -F, it would be copied
faithfully.

Helped-by: Eric Sunshine <[email protected]>
Signed-off-by: Phillip Wood <[email protected]>
Signed-off-by: Denton Liu <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
Denton-L authored and gitster committed Apr 18, 2019
1 parent ca04dc9 commit d540b70
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 13 deletions.
4 changes: 4 additions & 0 deletions Documentation/merge-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ they run `git merge`. To make it easier to adjust such scripts to the
updated behaviour, the environment variable `GIT_MERGE_AUTOEDIT` can be
set to `no` at the beginning of them.

--cleanup=<mode>::
This option determines how the merge message will be cleaned up
before commiting. See linkgit:git-commit[1] for more details.

--ff::
When the merge resolves as a fast-forward, only update the branch
pointer, without creating a merge commit. This is the default
Expand Down
41 changes: 31 additions & 10 deletions builtin/merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "tag.h"
#include "alias.h"
#include "commit-reach.h"
#include "wt-status.h"

#define DEFAULT_TWOHEAD (1<<0)
#define DEFAULT_OCTOPUS (1<<1)
Expand Down Expand Up @@ -98,6 +99,9 @@ enum ff_type {

static enum ff_type fast_forward = FF_ALLOW;

static const char *cleanup_arg;
static enum commit_msg_cleanup_mode cleanup_mode;

static int option_parse_message(const struct option *opt,
const char *arg, int unset)
{
Expand Down Expand Up @@ -249,6 +253,7 @@ static struct option builtin_merge_options[] = {
N_("perform a commit if the merge succeeds (default)")),
OPT_BOOL('e', "edit", &option_edit,
N_("edit message before committing")),
OPT_CLEANUP(&cleanup_arg),
OPT_SET_INT(0, "ff", &fast_forward, N_("allow fast-forward (default)"), FF_ALLOW),
OPT_SET_INT_F(0, "ff-only", &fast_forward,
N_("abort if fast-forward is not possible"),
Expand Down Expand Up @@ -612,6 +617,8 @@ static int git_merge_config(const char *k, const char *v, void *cb)
return git_config_string(&pull_twohead, k, v);
else if (!strcmp(k, "pull.octopus"))
return git_config_string(&pull_octopus, k, v);
else if (!strcmp(k, "commit.cleanup"))
return git_config_string(&cleanup_arg, k, v);
else if (!strcmp(k, "merge.renormalize"))
option_renormalize = git_config_bool(k, v);
else if (!strcmp(k, "merge.ff")) {
Expand Down Expand Up @@ -800,20 +807,33 @@ static void abort_commit(struct commit_list *remoteheads, const char *err_msg)
static const char merge_editor_comment[] =
N_("Please enter a commit message to explain why this merge is necessary,\n"
"especially if it merges an updated upstream into a topic branch.\n"
"\n"
"Lines starting with '%c' will be ignored, and an empty message aborts\n"
"\n");

static const char scissors_editor_comment[] =
N_("An empty message aborts the commit.\n");

static const char no_scissors_editor_comment[] =
N_("Lines starting with '%c' will be ignored, and an empty message aborts\n"
"the commit.\n");

static void write_merge_heads(struct commit_list *);
static void prepare_to_commit(struct commit_list *remoteheads)
{
struct strbuf msg = STRBUF_INIT;
strbuf_addbuf(&msg, &merge_msg);
strbuf_addch(&msg, '\n');
if (squash)
BUG("the control must not reach here under --squash");
if (0 < option_edit)
strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);
if (0 < option_edit) {
strbuf_addch(&msg, '\n');
if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
wt_status_append_cut_line(&msg);
strbuf_commented_addf(&msg, "\n");
}
strbuf_commented_addf(&msg, _(merge_editor_comment));
strbuf_commented_addf(&msg, _(cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS ?
scissors_editor_comment :
no_scissors_editor_comment), comment_line_char);
}
if (signoff)
append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0);
write_merge_heads(remoteheads);
Expand All @@ -832,7 +852,7 @@ static void prepare_to_commit(struct commit_list *remoteheads)
abort_commit(remoteheads, NULL);

read_merge_msg(&msg);
strbuf_stripspace(&msg, 0 < option_edit);
cleanup_message(&msg, cleanup_mode, 0);
if (!msg.len)
abort_commit(remoteheads, _("Empty commit message."));
strbuf_release(&merge_msg);
Expand Down Expand Up @@ -880,7 +900,6 @@ static int finish_automerge(struct commit *head,
parents = remoteheads;
if (!head_subsumed || fast_forward == FF_NO)
commit_list_insert(head, &parents);
strbuf_addch(&merge_msg, '\n');
prepare_to_commit(remoteheads);
if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,
&result_commit, NULL, sign_commit))
Expand Down Expand Up @@ -1301,6 +1320,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
}
resolve_undo_clear();

if (option_edit < 0)
option_edit = default_edit_option();

cleanup_mode = get_cleanup_mode(cleanup_arg, 0 < option_edit);

if (verbosity < 0)
show_diffstat = 0;

Expand Down Expand Up @@ -1386,9 +1410,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
fast_forward = FF_NO;
}

if (option_edit < 0)
option_edit = default_edit_option();

if (!use_strategies) {
if (!remoteheads)
; /* already up-to-date */
Expand Down
12 changes: 12 additions & 0 deletions builtin/pull.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "lockfile.h"
#include "wt-status.h"
#include "commit-reach.h"
#include "sequencer.h"

enum rebase_type {
REBASE_INVALID = -1,
Expand Down Expand Up @@ -101,6 +102,7 @@ static char *opt_signoff;
static char *opt_squash;
static char *opt_commit;
static char *opt_edit;
static char *cleanup_arg;
static char *opt_ff;
static char *opt_verify_signatures;
static int opt_autostash = -1;
Expand Down Expand Up @@ -168,6 +170,7 @@ static struct option pull_options[] = {
OPT_PASSTHRU(0, "edit", &opt_edit, NULL,
N_("edit message before committing"),
PARSE_OPT_NOARG),
OPT_CLEANUP(&cleanup_arg),
OPT_PASSTHRU(0, "ff", &opt_ff, NULL,
N_("allow fast-forward"),
PARSE_OPT_NOARG),
Expand Down Expand Up @@ -644,6 +647,8 @@ static int run_merge(void)
argv_array_push(&args, opt_commit);
if (opt_edit)
argv_array_push(&args, opt_edit);
if (cleanup_arg)
argv_array_pushf(&args, "--cleanup=%s", cleanup_arg);
if (opt_ff)
argv_array_push(&args, opt_ff);
if (opt_verify_signatures)
Expand Down Expand Up @@ -875,6 +880,13 @@ int cmd_pull(int argc, const char **argv, const char *prefix)

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

if (cleanup_arg)
/*
* this only checks the validity of cleanup_arg; we don't need
* a valid value for use_editor
*/
get_cleanup_mode(cleanup_arg, 0);

parse_repo_refspecs(argc, argv, &repo, &refspecs);

if (!opt_ff)
Expand Down
8 changes: 8 additions & 0 deletions t/t5521-pull-options.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ test_expect_success 'git pull -q -v' '
test_must_be_empty out &&
test -s err)
'
test_expect_success 'git pull --cleanup errors early on invalid argument' '
mkdir clonedcleanup &&
(cd clonedcleanup && git init &&
test_must_fail git pull --cleanup invalid "../parent" >out 2>err &&
test_must_be_empty out &&
test -s err)
'


test_expect_success 'git pull --force' '
mkdir clonedoldstyle &&
Expand Down
63 changes: 63 additions & 0 deletions t/t7604-merge-custom-message.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,67 @@ test_expect_success 'merge --log appends to custom message' '
test_cmp exp.log actual
'

mesg_with_comment_and_newlines='
# text
'

test_expect_success 'prepare file with comment line and trailing newlines' '
printf "%s" "$mesg_with_comment_and_newlines" >expect
'

test_expect_success 'cleanup commit messages (verbatim option)' '
git reset --hard c1 &&
git merge --cleanup=verbatim -F expect c2 &&
git cat-file commit HEAD >raw &&
sed -e "1,/^$/d" raw >actual &&
test_cmp expect actual
'

test_expect_success 'cleanup commit messages (whitespace option)' '
git reset --hard c1 &&
test_write_lines "" "# text" "" >text &&
echo "# text" >expect &&
git merge --cleanup=whitespace -F text c2 &&
git cat-file commit HEAD >raw &&
sed -e "1,/^$/d" raw >actual &&
test_cmp expect actual
'

test_expect_success 'cleanup merge messages (scissors option)' '
git reset --hard c1 &&
cat >text <<-\EOF &&
# to be kept
# ------------------------ >8 ------------------------
# to be kept, too
# ------------------------ >8 ------------------------
to be removed
# ------------------------ >8 ------------------------
to be removed, too
EOF
cat >expect <<-\EOF &&
# to be kept
# ------------------------ >8 ------------------------
# to be kept, too
EOF
git merge --cleanup=scissors -e -F text c2 &&
git cat-file commit HEAD >raw &&
sed -e "1,/^$/d" raw >actual &&
test_cmp expect actual
'

test_expect_success 'cleanup commit messages (strip option)' '
git reset --hard c1 &&
test_write_lines "" "# text" "sample" "" >text &&
echo sample >expect &&
git merge --cleanup=strip -F text c2 &&
git cat-file commit HEAD >raw &&
sed -e "1,/^$/d" raw >actual &&
test_cmp expect actual
'

test_done
12 changes: 9 additions & 3 deletions wt-status.c
Original file line number Diff line number Diff line change
Expand Up @@ -1006,13 +1006,19 @@ size_t wt_status_locate_end(const char *s, size_t len)
return len;
}

void wt_status_add_cut_line(FILE *fp)
void wt_status_append_cut_line(struct strbuf *buf)
{
const char *explanation = _("Do not modify or remove the line above.\nEverything below it will be ignored.");

strbuf_commented_addf(buf, "%s", cut_line);
strbuf_add_commented_lines(buf, explanation, strlen(explanation));
}

void wt_status_add_cut_line(FILE *fp)
{
struct strbuf buf = STRBUF_INIT;

fprintf(fp, "%c %s", comment_line_char, cut_line);
strbuf_add_commented_lines(&buf, explanation, strlen(explanation));
wt_status_append_cut_line(&buf);
fputs(buf.buf, fp);
strbuf_release(&buf);
}
Expand Down
1 change: 1 addition & 0 deletions wt-status.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ struct wt_status {
};

size_t wt_status_locate_end(const char *s, size_t len);
void wt_status_append_cut_line(struct strbuf *buf);
void wt_status_add_cut_line(FILE *fp);
void wt_status_prepare(struct repository *r, struct wt_status *s);
void wt_status_print(struct wt_status *s);
Expand Down

0 comments on commit d540b70

Please sign in to comment.