@@ -9,7 +9,7 @@ git-merge-tree - Perform merge without touching index or working tree
SYNOPSIS
--------
[verse]
-'git merge-tree' [--write-tree] <branch1> <branch2>
+'git merge-tree' [--write-tree] [<options>] <branch1> <branch2>
'git merge-tree' [--trivial-merge] <base-tree> <branch1> <branch2> (deprecated)
DESCRIPTION
@@ -35,17 +35,47 @@ merge is distinguished from a trivial merge in that it includes:
After the merge completes, it will create a new toplevel tree object.
See `OUTPUT` below for details.
+OPTIONS
+-------
+
+--[no-]messages::
+ Write any informational messages such as "Auto-merging <path>"
+ or CONFLICT notices to the end of stdout. If unspecified, the
+ default is to include these messages if there are merge
+ conflicts, and to omit them otherwise.
+
OUTPUT
------
-For either a successful or conflicted merge, the output from
-git-merge-tree is simply one line:
+By default, for a successful merge, the output from git-merge-tree is
+simply one line:
+
+ <OID of toplevel tree>
+
+Whereas for a conflicted merge, the output is by default of the form:
<OID of toplevel tree>
+ <Informational messages>
+
+These are discussed individually below.
+
+OID of toplevel tree
+~~~~~~~~~~~~~~~~~~~~
+
+This is a tree object that represents what would be checked out in the
+working tree at the end of `git merge`. If there were conflicts, then
+files within this tree may have embedded conflict markers.
+
+Informational messages
+~~~~~~~~~~~~~~~~~~~~~~
+
+This always starts with a blank line to separate it from the previous
+section, and then has free-form messages about the merge, such as:
-The printed tree object corresponds to what would be checked out in
-the working tree at the end of `git merge`, and thus may have files
-with conflict markers in them.
+ * "Auto-merging <file>"
+ * "CONFLICT (rename/delete): <oldfile> renamed...but deleted in..."
+ * "Failed to merge submodule <submodule> (<reason>)"
+ * "Warning: cannot merge binary files: <filename>"
EXIT STATUS
-----------
@@ -69,7 +99,8 @@ be used as a part of a series of steps such as
However, it does not quite fit into the same category of low-level
plumbing commands since the possibility of merge conflicts give it a
-much higher chance of the command not succeeding.
+much higher chance of the command not succeeding (and NEWTREE containing
+a bunch of stuff other than just a toplevel tree).
GIT
---
@@ -390,6 +390,7 @@ static int trivial_merge(const char *base,
struct merge_tree_options {
int mode;
+ int show_messages;
};
static int real_merge(struct merge_tree_options *o,
@@ -432,18 +433,27 @@ static int real_merge(struct merge_tree_options *o,
merge_incore_recursive(&opt, merge_bases, parent1, parent2, &result);
if (result.clean < 0)
die(_("failure to merge"));
+
+ if (o->show_messages == -1)
+ o->show_messages = !result.clean;
+
puts(oid_to_hex(&result.tree->object.oid));
+ if (o->show_messages) {
+ printf("\n");
+ merge_display_update_messages(&opt, &result, stdout);
+ }
merge_finalize(&opt, &result);
return !result.clean; /* result.clean < 0 handled above */
}
int cmd_merge_tree(int argc, const char **argv, const char *prefix)
{
- struct merge_tree_options o = { 0 };
+ struct merge_tree_options o = { .show_messages = -1 };
int expected_remaining_argc;
+ int original_argc;
const char * const merge_tree_usage[] = {
- N_("git merge-tree [--write-tree] <branch1> <branch2>"),
+ N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"),
N_("git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>"),
NULL
};
@@ -453,10 +463,13 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
'w'),
OPT_CMDMODE(0, "trivial-merge", &o.mode,
N_("do a trivial merge only"), 't'),
+ OPT_BOOL(0, "messages", &o.show_messages,
+ N_("also show informational/conflict messages")),
OPT_END()
};
/* Parse arguments */
+ original_argc = argc;
argc = parse_options(argc, argv, prefix, mt_options,
merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION);
if (o.mode) {
@@ -468,6 +481,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
usage_with_options(merge_tree_usage, mt_options);
o.mode = (argc == 2 ? 'w' : 't');
}
+ if (o.mode == 't' && original_argc < argc)
+ die(_("--trivial-merge is incompatible with all other options"));
/* Do the relevant type of merge */
if (o.mode == 'w')
@@ -85,4 +85,25 @@ test_expect_success 'Barf on too many arguments' '
grep "^usage: git merge-tree" expect
'
+test_expect_success 'test conflict notices and such' '
+ test_expect_code 1 git merge-tree --write-tree side1 side2 >out &&
+ sed -e "s/[0-9a-f]\{40,\}/HASH/g" out >actual &&
+
+ # Expected results:
+ # "greeting" should merge with conflicts
+ # "numbers" should merge cleanly
+ # "whatever" has *both* a modify/delete and a file/directory conflict
+ cat <<-EOF >expect &&
+ HASH
+
+ Auto-merging greeting
+ CONFLICT (content): Merge conflict in greeting
+ Auto-merging numbers
+ CONFLICT (file/directory): directory in the way of whatever from side1; moving it to whatever~side1 instead.
+ CONFLICT (modify/delete): whatever~side1 deleted in side2 and modified in side1. Version side1 of whatever~side1 left in tree.
+ EOF
+
+ test_cmp expect actual
+'
+
test_done