@@ -9,7 +9,7 @@ git-merge-tree - Perform merge without touching index or working tree
SYNOPSIS
--------
[verse]
-'git merge-tree' --real [--messages=<file>] <branch1> <branch2>
+'git merge-tree' --real [--messages=<file>] [--conflicted-list=<file>] <branch1> <branch2>
'git merge-tree' <base-tree> <branch1> <branch2>
DESCRIPTION
@@ -23,7 +23,9 @@ will be `0`, and if the merge has conflicts, the exit status will be
`1`. The output will consist solely of the resulting toplevel tree
(which may have files including conflict markers). With `--messages`,
it will write any informational messages (such as "Auto-merging
-<path>" and conflict notices) to the given file.
+<path>" and conflict notices) to the given file. With
+`--conflicted-list`, it will write a list of unmerged files, one per
+line, to the given file.
The second form is meant for backward compatibility and will only do a
trival merge. It reads three tree-ish, and outputs trivial merge
@@ -390,6 +390,7 @@ static int trivial_merge(const char *base,
struct merge_tree_options {
int real;
char *messages_file;
+ char *conflicted_file;
};
static int real_merge(struct merge_tree_options *o,
@@ -449,6 +450,19 @@ static int real_merge(struct merge_tree_options *o,
merge_display_update_messages(&opt, &result, fp);
fclose(fp);
}
+ if (o->conflicted_file) {
+ struct string_list conflicted_files = STRING_LIST_INIT_NODUP;
+ FILE *fp = xfopen(o->conflicted_file, "w");
+ int i;
+
+ merge_get_conflicted_files(&result, &conflicted_files);
+ for (i = 0; i < conflicted_files.nr; i++) {
+ fprintf(fp, "%s", conflicted_files.items[i].string);
+ fputc('\0', fp);
+ }
+ fclose(fp);
+ string_list_clear(&conflicted_files, 0);
+ }
printf("%s\n", oid_to_hex(&result.tree->object.oid));
merge_finalize(&opt, &result);
@@ -471,6 +485,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
N_("do a real merge instead of a trivial merge")),
OPT_STRING(0, "messages", &o.messages_file, N_("file"),
N_("filename to write informational/conflict messages to")),
+ OPT_STRING(0, "conflicted-list", &o.conflicted_file, N_("file"),
+ N_("filename to write list of unmerged files")),
OPT_END()
};
@@ -4234,6 +4234,19 @@ void merge_display_update_messages(struct merge_options *opt,
trace2_region_leave("merge", "display messages", opt->repo);
}
+void merge_get_conflicted_files(struct merge_result *result,
+ struct string_list *conflicted_files)
+{
+ struct hashmap_iter iter;
+ struct strmap_entry *e;
+ struct merge_options_internal *opti = result->priv;
+
+ strmap_for_each_entry(&opti->conflicted, &iter, e) {
+ string_list_append(conflicted_files, e->key);
+ }
+ string_list_sort(conflicted_files);
+}
+
void merge_switch_to_result(struct merge_options *opt,
struct tree *head,
struct merge_result *result,
@@ -79,6 +79,9 @@ void merge_display_update_messages(struct merge_options *opt,
struct merge_result *result,
FILE *stream);
+void merge_get_conflicted_files(struct merge_result *result,
+ struct string_list *conflicted_files);
+
/* Do needed cleanup when not calling merge_switch_to_result() */
void merge_finalize(struct merge_options *opt,
struct merge_result *result);
@@ -96,4 +96,13 @@ test_expect_success '--messages gives us the conflict notices and such' '
test_cmp expect MSG_FILE
'
+test_expect_success '--messages gives us the conflict notices and such' '
+ test_must_fail git merge-tree --real --conflicted-list=UNMERGED side1 side2 &&
+
+ cat UNMERGED | tr "\0" "\n" >actual &&
+ test_write_lines greeting whatever~side1 >expect &&
+
+ test_cmp expect actual
+'
+
test_done