Skip to content

Commit f824628

Browse files
committed
merge: use editor by default in interactive sessions
Traditionally, a cleanly resolved merge was committed by "git merge" using the auto-generated merge commit log message without invoking the editor. After 5 years of use in the field, it turns out that people perform too many unjustified merges of the upstream history into their topic branches. These merges are not just useless, but they are often not explained well, and making the end result unreadable when it gets time for merging their history back to their upstream. Earlier we added the "--edit" option to the command, so that people can edit the log message to explain and justify their merge commits. Let's take it one step further and spawn the editor by default when we are in an interactive session (i.e. the standard input and the standard output are pointing at the same tty device). There may be existing scripts that leave the standard input and the standard output of the "git merge" connected to whatever environment the scripts were started, and such invocation might trigger the above "interactive session" heuristics. GIT_MERGE_AUTOEDIT environment variable can be set to "no" at the beginning of such scripts to use the historical behaviour while the script runs. Note that this backward compatibility is meant only for scripts, and we deliberately do *not* support "merge.edit = yes/no/auto" configuration option to allow people to keep the historical behaviour. Suggested-by: Linus Torvalds <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0074d18 commit f824628

File tree

4 files changed

+50
-9
lines changed

4 files changed

+50
-9
lines changed

Documentation/git-merge.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-merge - Join two or more development histories together
99
SYNOPSIS
1010
--------
1111
[verse]
12-
'git merge' [-n] [--stat] [--no-commit] [--squash]
12+
'git merge' [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
1313
[-s <strategy>] [-X <strategy-option>]
1414
[--[no-]rerere-autoupdate] [-m <msg>] [<commit>...]
1515
'git merge' <msg> HEAD <commit>...

Documentation/merge-options.txt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,20 @@ failed and do not autocommit, to give the user a chance to
88
inspect and further tweak the merge result before committing.
99

1010
--edit::
11-
-e::
11+
--no-edit::
12+
Invoke an editor before committing successful mechanical merge to
13+
further edit the auto-generated merge message, so that the user
14+
can explain and justify the merge. The `--no-edit` option can be
15+
used to accept the auto-generated message (this is generally
16+
discouraged). The `--edit` option is still useful if you are
17+
giving a draft message with the `-m` option from the command line
18+
and want to edit it in the editor.
1219
+
13-
Invoke editor before committing successful merge to further
14-
edit the default merge message.
20+
Older scripts may depend on the historical behaviour of not allowing the
21+
user to edit the merge log message. They will see an editor opened when
22+
they run `git merge`. To make it easier to adjust such scripts to the
23+
updated behaviour, the environment variable `GIT_MERGE_AUTOEDIT` can be
24+
set to `no` at the beginning of them.
1525

1626
--ff::
1727
--no-ff::

builtin/merge.c

Lines changed: 34 additions & 4 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, option_edit;
49+
static int fast_forward_only, option_edit = -1;
5050
static int allow_trivial = 1, have_message;
5151
static struct strbuf merge_msg;
5252
static struct commit_list *remoteheads;
@@ -189,7 +189,7 @@ 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,
192+
OPT_BOOL('e', "edit", &option_edit,
193193
"edit message before committing"),
194194
OPT_BOOLEAN(0, "ff", &allow_fast_forward,
195195
"allow fast-forward (default)"),
@@ -877,12 +877,12 @@ static void prepare_to_commit(void)
877877
write_merge_msg(&msg);
878878
run_hook(get_index_file(), "prepare-commit-msg",
879879
git_path("MERGE_MSG"), "merge", NULL, NULL);
880-
if (option_edit) {
880+
if (0 < option_edit) {
881881
if (launch_editor(git_path("MERGE_MSG"), NULL, NULL))
882882
abort_commit(NULL);
883883
}
884884
read_merge_msg(&msg);
885-
stripspace(&msg, option_edit);
885+
stripspace(&msg, 0 < option_edit);
886886
if (!msg.len)
887887
abort_commit(_("Empty commit message."));
888888
strbuf_release(&merge_msg);
@@ -1076,6 +1076,33 @@ static void write_merge_state(void)
10761076
close(fd);
10771077
}
10781078

1079+
static int default_edit_option(void)
1080+
{
1081+
static const char name[] = "GIT_MERGE_AUTOEDIT";
1082+
const char *e = getenv(name);
1083+
struct stat st_stdin, st_stdout;
1084+
1085+
if (have_message)
1086+
/* an explicit -m msg without --[no-]edit */
1087+
return 0;
1088+
1089+
if (e) {
1090+
int v = git_config_maybe_bool(name, e);
1091+
if (v < 0)
1092+
die("Bad value '%s' in environment '%s'", e, name);
1093+
return v;
1094+
}
1095+
1096+
/* Use editor if stdin and stdout are the same and is a tty */
1097+
return (!fstat(0, &st_stdin) &&
1098+
!fstat(1, &st_stdout) &&
1099+
isatty(0) &&
1100+
st_stdin.st_dev == st_stdout.st_dev &&
1101+
st_stdin.st_ino == st_stdout.st_ino &&
1102+
st_stdin.st_mode == st_stdout.st_mode);
1103+
}
1104+
1105+
10791106
int cmd_merge(int argc, const char **argv, const char *prefix)
10801107
{
10811108
unsigned char result_tree[20];
@@ -1261,6 +1288,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
12611288
}
12621289
}
12631290

1291+
if (option_edit < 0)
1292+
option_edit = default_edit_option();
1293+
12641294
if (!use_strategies) {
12651295
if (!remoteheads->next)
12661296
add_strategies(pull_twohead, DEFAULT_TWOHEAD);

t/test-lib.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ GIT_AUTHOR_NAME='A U Thor'
6363
6464
GIT_COMMITTER_NAME='C O Mitter'
6565
GIT_MERGE_VERBOSITY=5
66-
export GIT_MERGE_VERBOSITY
66+
GIT_MERGE_AUTOEDIT=no
67+
export GIT_MERGE_VERBOSITY GIT_MERGE_AUTOEDIT
6768
export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
6869
export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
6970
export EDITOR

0 commit comments

Comments
 (0)