diff options
-rw-r--r-- | Documentation/git-merge-tree.txt | 47 | ||||
-rw-r--r-- | builtin/merge-tree.c | 21 | ||||
-rwxr-xr-x | t/t4301-merge-tree-write-tree.sh | 37 |
3 files changed, 97 insertions, 8 deletions
diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 2a9c91328d..25b462be14 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -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) [[NEWMERGE]] @@ -37,18 +37,50 @@ linkgit:git-merge[1], including: After the merge completes, a new toplevel tree object is created. 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]] OUTPUT ------ -For either a successful or conflicted merge, the output from -git-merge-tree is simply one line: +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. -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. +[[OIDTLT]] +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. + +[[IM]] +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: + + * "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 ----------- @@ -72,6 +104,9 @@ used as a part of a series of steps such as: NEWCOMMIT=$(git commit-tree $NEWTREE -p $BRANCH1 -p $BRANCH2) git update-ref $BRANCH1 $NEWCOMMIT +Note that when the exit status is non-zero, `NEWTREE` in this sequence +will contain a lot more output than just a tree. + [[DEPMERGE]] DEPRECATED DESCRIPTION ---------------------- diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 2332525d8b..831d9c7758 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -396,6 +396,7 @@ enum mode { struct merge_tree_options { int mode; + int show_messages; }; static int real_merge(struct merge_tree_options *o, @@ -435,18 +436,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); + } 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 }; @@ -456,10 +466,13 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) MODE_REAL), OPT_CMDMODE(0, "trivial-merge", &o.mode, N_("do a trivial merge only"), MODE_TRIVIAL), + OPT_BOOL(0, "messages", &o.show_messages, + N_("also show informational/conflict messages")), OPT_END() }; /* Parse arguments */ + original_argc = argc - 1; /* ignoring argv[0] */ argc = parse_options(argc, argv, prefix, mt_options, merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION); switch (o.mode) { @@ -483,8 +496,12 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) break; case MODE_TRIVIAL: expected_remaining_argc = 3; + /* Removal of `--trivial-merge` is expected */ + original_argc--; break; } + if (o.mode == MODE_TRIVIAL && argc < original_argc) + die(_("--trivial-merge is incompatible with all other options")); if (argc != expected_remaining_argc) usage_with_options(merge_tree_usage, mt_options); diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index 6d321652e2..719d81e717 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -103,4 +103,41 @@ test_expect_success 'Barf on too many arguments' ' grep "^usage: git merge-tree" expect ' +anonymize_hash() { + sed -e "s/[0-9a-f]\{40,\}/HASH/g" "$@" +} + +test_expect_success 'test conflict notices and such' ' + test_expect_code 1 git merge-tree --write-tree side1 side2 >out && + anonymize_hash 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 +' + +for opt in $(git merge-tree --git-completion-helper-all) +do + if test $opt = "--trivial-merge" || test $opt = "--write-tree" + then + continue + fi + + test_expect_success "usage: --trivial-merge is incompatible with $opt" ' + test_expect_code 128 git merge-tree --trivial-merge $opt side1 side2 side3 + ' +done + test_done |