Skip to content

Commit 3dfbe68

Browse files
committed
Merge branch 'js/merge-edit-option'
* js/merge-edit-option: Teach merge the '[-e|--edit]' option Conflicts: builtin/merge.c
2 parents 9b55aa0 + 66f4b98 commit 3dfbe68

File tree

3 files changed

+99
-39
lines changed

3 files changed

+99
-39
lines changed

Documentation/merge-options.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ With --no-commit perform the merge but pretend the merge
77
failed and do not autocommit, to give the user a chance to
88
inspect and further tweak the merge result before committing.
99

10+
--edit::
11+
-e::
12+
+
13+
Invoke editor before committing successful merge to further
14+
edit the default merge message.
15+
1016
--ff::
1117
--no-ff::
1218
Do not generate a merge commit if the merge resolved as

builtin/merge.c

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ static const char * const builtin_merge_usage[] = {
4646

4747
static int show_diffstat = 1, shortlog_len, squash;
4848
static int option_commit = 1, allow_fast_forward = 1;
49-
static int fast_forward_only;
49+
static int fast_forward_only, option_edit;
5050
static int allow_trivial = 1, have_message;
5151
static struct strbuf merge_msg;
5252
static struct commit_list *remoteheads;
@@ -189,6 +189,8 @@ static struct option builtin_merge_options[] = {
189189
"create a single commit instead of doing a merge"),
190190
OPT_BOOLEAN(0, "commit", &option_commit,
191191
"perform a commit if the merge succeeds (default)"),
192+
OPT_BOOLEAN('e', "edit", &option_edit,
193+
"edit message before committing"),
192194
OPT_BOOLEAN(0, "ff", &allow_fast_forward,
193195
"allow fast-forward (default)"),
194196
OPT_BOOLEAN(0, "ff-only", &fast_forward_only,
@@ -843,30 +845,54 @@ static void add_strategies(const char *string, unsigned attr)
843845

844846
}
845847

846-
static void write_merge_msg(void)
848+
static void write_merge_msg(struct strbuf *msg)
847849
{
848850
int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
849851
if (fd < 0)
850852
die_errno(_("Could not open '%s' for writing"),
851853
git_path("MERGE_MSG"));
852-
if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len)
854+
if (write_in_full(fd, msg->buf, msg->len) != msg->len)
853855
die_errno(_("Could not write to '%s'"), git_path("MERGE_MSG"));
854856
close(fd);
855857
}
856858

857-
static void read_merge_msg(void)
859+
static void read_merge_msg(struct strbuf *msg)
858860
{
859-
strbuf_reset(&merge_msg);
860-
if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0)
861+
strbuf_reset(msg);
862+
if (strbuf_read_file(msg, git_path("MERGE_MSG"), 0) < 0)
861863
die_errno(_("Could not read from '%s'"), git_path("MERGE_MSG"));
862864
}
863865

864-
static void run_prepare_commit_msg(void)
866+
static void write_merge_state(void);
867+
static void abort_commit(const char *err_msg)
865868
{
866-
write_merge_msg();
869+
if (err_msg)
870+
error("%s", err_msg);
871+
fprintf(stderr,
872+
_("Not committing merge; use 'git commit' to complete the merge.\n"));
873+
write_merge_state();
874+
exit(1);
875+
}
876+
877+
static void prepare_to_commit(void)
878+
{
879+
struct strbuf msg = STRBUF_INIT;
880+
strbuf_addbuf(&msg, &merge_msg);
881+
strbuf_addch(&msg, '\n');
882+
write_merge_msg(&msg);
867883
run_hook(get_index_file(), "prepare-commit-msg",
868884
git_path("MERGE_MSG"), "merge", NULL, NULL);
869-
read_merge_msg();
885+
if (option_edit) {
886+
if (launch_editor(git_path("MERGE_MSG"), NULL, NULL))
887+
abort_commit(NULL);
888+
}
889+
read_merge_msg(&msg);
890+
stripspace(&msg, option_edit);
891+
if (!msg.len)
892+
abort_commit(_("Empty commit message."));
893+
strbuf_release(&merge_msg);
894+
strbuf_addbuf(&merge_msg, &msg);
895+
strbuf_release(&msg);
870896
}
871897

872898
static int merge_trivial(struct commit *head)
@@ -880,7 +906,7 @@ static int merge_trivial(struct commit *head)
880906
parent->next = xmalloc(sizeof(*parent->next));
881907
parent->next->item = remoteheads->item;
882908
parent->next->next = NULL;
883-
run_prepare_commit_msg();
909+
prepare_to_commit();
884910
commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
885911
finish(head, result_commit, "In-index merge");
886912
drop_save();
@@ -909,9 +935,9 @@ static int finish_automerge(struct commit *head,
909935
for (j = remoteheads; j; j = j->next)
910936
pptr = &commit_list_insert(j->item, pptr)->next;
911937
}
912-
free_commit_list(remoteheads);
913938
strbuf_addch(&merge_msg, '\n');
914-
run_prepare_commit_msg();
939+
prepare_to_commit();
940+
free_commit_list(remoteheads);
915941
commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
916942
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
917943
finish(head, result_commit, buf.buf);
@@ -1018,6 +1044,36 @@ static int setup_with_upstream(const char ***argv)
10181044
return i;
10191045
}
10201046

1047+
static void write_merge_state(void)
1048+
{
1049+
int fd;
1050+
struct commit_list *j;
1051+
struct strbuf buf = STRBUF_INIT;
1052+
1053+
for (j = remoteheads; j; j = j->next)
1054+
strbuf_addf(&buf, "%s\n",
1055+
sha1_to_hex(j->item->object.sha1));
1056+
fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666);
1057+
if (fd < 0)
1058+
die_errno(_("Could not open '%s' for writing"),
1059+
git_path("MERGE_HEAD"));
1060+
if (write_in_full(fd, buf.buf, buf.len) != buf.len)
1061+
die_errno(_("Could not write to '%s'"), git_path("MERGE_HEAD"));
1062+
close(fd);
1063+
strbuf_addch(&merge_msg, '\n');
1064+
write_merge_msg(&merge_msg);
1065+
fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
1066+
if (fd < 0)
1067+
die_errno(_("Could not open '%s' for writing"),
1068+
git_path("MERGE_MODE"));
1069+
strbuf_reset(&buf);
1070+
if (!allow_fast_forward)
1071+
strbuf_addf(&buf, "no-ff");
1072+
if (write_in_full(fd, buf.buf, buf.len) != buf.len)
1073+
die_errno(_("Could not write to '%s'"), git_path("MERGE_MODE"));
1074+
close(fd);
1075+
}
1076+
10211077
int cmd_merge(int argc, const char **argv, const char *prefix)
10221078
{
10231079
unsigned char result_tree[20];
@@ -1423,33 +1479,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
14231479

14241480
if (squash)
14251481
finish(head_commit, NULL, NULL);
1426-
else {
1427-
int fd;
1428-
struct commit_list *j;
1429-
1430-
for (j = remoteheads; j; j = j->next)
1431-
strbuf_addf(&buf, "%s\n",
1432-
sha1_to_hex(j->item->object.sha1));
1433-
fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666);
1434-
if (fd < 0)
1435-
die_errno(_("Could not open '%s' for writing"),
1436-
git_path("MERGE_HEAD"));
1437-
if (write_in_full(fd, buf.buf, buf.len) != buf.len)
1438-
die_errno(_("Could not write to '%s'"), git_path("MERGE_HEAD"));
1439-
close(fd);
1440-
strbuf_addch(&merge_msg, '\n');
1441-
write_merge_msg();
1442-
fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
1443-
if (fd < 0)
1444-
die_errno(_("Could not open '%s' for writing"),
1445-
git_path("MERGE_MODE"));
1446-
strbuf_reset(&buf);
1447-
if (!allow_fast_forward)
1448-
strbuf_addf(&buf, "no-ff");
1449-
if (write_in_full(fd, buf.buf, buf.len) != buf.len)
1450-
die_errno(_("Could not write to '%s'"), git_path("MERGE_MODE"));
1451-
close(fd);
1452-
}
1482+
else
1483+
write_merge_state();
14531484

14541485
if (merge_was_ok) {
14551486
fprintf(stderr, _("Automatic merge went well; "

t/t7600-merge.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,4 +643,27 @@ test_expect_success 'amending no-ff merge commit' '
643643

644644
test_debug 'git log --graph --decorate --oneline --all'
645645

646+
cat >editor <<\EOF
647+
#!/bin/sh
648+
# Add a new message string that was not in the template
649+
(
650+
echo "Merge work done on the side branch c1"
651+
echo
652+
cat <"$1"
653+
) >"$1.tmp" && mv "$1.tmp" "$1"
654+
# strip comments and blank lines from end of message
655+
sed -e '/^#/d' < "$1" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' > expected
656+
EOF
657+
chmod 755 editor
658+
659+
test_expect_success 'merge --no-ff --edit' '
660+
git reset --hard c0 &&
661+
EDITOR=./editor git merge --no-ff --edit c1 &&
662+
verify_parents $c0 $c1 &&
663+
git cat-file commit HEAD >raw &&
664+
grep "work done on the side branch" raw &&
665+
sed "1,/^$/d" >actual raw &&
666+
test_cmp actual expected
667+
'
668+
646669
test_done

0 commit comments

Comments
 (0)