Git fork

merge-tree: add a new --quiet flag

Git Forges may be interested in whether two branches can be merged while
not being interested in what the resulting merge tree is nor which files
conflicted. For such cases, add a new --quiet flag which
will make use of the new mergeability_only flag added to merge-ort in
the previous commit. This option allows the merge machinery to, in the
outer layer of the merge:
* exit early when a conflict is detected
* avoid writing (most) merged blobs/trees to the object store

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Elijah Newren and committed by
Junio C Hamano
29d7bf19 c6d5ca10

+62
+6
Documentation/git-merge-tree.adoc
··· 65 default is to include these messages if there are merge 66 conflicts, and to omit them otherwise. 67 68 --allow-unrelated-histories:: 69 merge-tree will by default error out if the two branches specified 70 share no common history. This flag can be given to override that
··· 65 default is to include these messages if there are merge 66 conflicts, and to omit them otherwise. 67 68 + --quiet:: 69 + Disable all output from the program. Useful when you are only 70 + interested in the exit status. Allows merge-tree to exit 71 + early when it finds a conflict, and allows it to avoid writing 72 + most objects created by merges. 73 + 74 --allow-unrelated-histories:: 75 merge-tree will by default error out if the two branches specified 76 share no common history. This flag can be given to override that
+18
builtin/merge-tree.c
··· 490 if (result.clean < 0) 491 die(_("failure to merge")); 492 493 if (show_messages == -1) 494 show_messages = !result.clean; 495 ··· 522 } 523 if (o->use_stdin) 524 putchar(line_termination); 525 merge_finalize(&opt, &result); 526 clear_merge_options(&opt); 527 return !result.clean; /* result.clean < 0 handled above */ ··· 538 int original_argc; 539 const char *merge_base = NULL; 540 int ret; 541 542 const char * const merge_tree_usage[] = { 543 N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"), ··· 552 N_("do a trivial merge only"), MODE_TRIVIAL), 553 OPT_BOOL(0, "messages", &o.show_messages, 554 N_("also show informational/conflict messages")), 555 OPT_SET_INT('z', NULL, &line_termination, 556 N_("separate paths with the NUL character"), '\0'), 557 OPT_BOOL_F(0, "name-only", ··· 582 original_argc = argc - 1; /* ignoring argv[0] */ 583 argc = parse_options(argc, argv, prefix, mt_options, 584 merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION); 585 586 if (xopts.nr && o.mode == MODE_TRIVIAL) 587 die(_("--trivial-merge is incompatible with all other options"));
··· 490 if (result.clean < 0) 491 die(_("failure to merge")); 492 493 + if (o->merge_options.mergeability_only) 494 + goto cleanup; 495 + 496 if (show_messages == -1) 497 show_messages = !result.clean; 498 ··· 525 } 526 if (o->use_stdin) 527 putchar(line_termination); 528 + 529 + cleanup: 530 merge_finalize(&opt, &result); 531 clear_merge_options(&opt); 532 return !result.clean; /* result.clean < 0 handled above */ ··· 543 int original_argc; 544 const char *merge_base = NULL; 545 int ret; 546 + int quiet = 0; 547 548 const char * const merge_tree_usage[] = { 549 N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"), ··· 558 N_("do a trivial merge only"), MODE_TRIVIAL), 559 OPT_BOOL(0, "messages", &o.show_messages, 560 N_("also show informational/conflict messages")), 561 + OPT_BOOL_F(0, "quiet", 562 + &quiet, 563 + N_("suppress all output; only exit status wanted"), 564 + PARSE_OPT_NONEG), 565 OPT_SET_INT('z', NULL, &line_termination, 566 N_("separate paths with the NUL character"), '\0'), 567 OPT_BOOL_F(0, "name-only", ··· 592 original_argc = argc - 1; /* ignoring argv[0] */ 593 argc = parse_options(argc, argv, prefix, mt_options, 594 merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION); 595 + 596 + if (quiet && o.show_messages == -1) 597 + o.show_messages = 0; 598 + o.merge_options.mergeability_only = quiet; 599 + die_for_incompatible_opt2(quiet, "--quiet", o.show_messages, "--messages"); 600 + die_for_incompatible_opt2(quiet, "--quiet", o.name_only, "--name-only"); 601 + die_for_incompatible_opt2(quiet, "--quiet", o.use_stdin, "--stdin"); 602 + die_for_incompatible_opt2(quiet, "--quiet", !line_termination, "-z"); 603 604 if (xopts.nr && o.mode == MODE_TRIVIAL) 605 die(_("--trivial-merge is incompatible with all other options"));
+38
t/t4301-merge-tree-write-tree.sh
··· 54 git commit -m first-commit 55 ' 56 57 test_expect_success 'Clean merge' ' 58 TREE_OID=$(git merge-tree --write-tree side1 side3) && 59 q_to_tab <<-EOF >expect && ··· 70 test_expect_success 'Failed merge without rename detection' ' 71 test_must_fail git -c diff.renames=false merge-tree --write-tree side1 side3 >out && 72 grep "CONFLICT (modify/delete): numbers deleted" out 73 ' 74 75 test_expect_success 'Content merge and a few conflicts' '
··· 54 git commit -m first-commit 55 ' 56 57 + test_expect_success '--quiet on clean merge' ' 58 + # Get rid of loose objects to start with 59 + git gc && 60 + echo "0 objects, 0 kilobytes" >expect && 61 + git count-objects >actual && 62 + test_cmp expect actual && 63 + 64 + # Ensure merge is successful (exit code of 0) 65 + git merge-tree --write-tree --quiet side1 side3 >output && 66 + 67 + # Ensure there is no output 68 + test_must_be_empty output && 69 + 70 + # Ensure no loose objects written (all new objects written would have 71 + # been in "outer layer" of the merge) 72 + git count-objects >actual && 73 + test_cmp expect actual 74 + ' 75 + 76 test_expect_success 'Clean merge' ' 77 TREE_OID=$(git merge-tree --write-tree side1 side3) && 78 q_to_tab <<-EOF >expect && ··· 89 test_expect_success 'Failed merge without rename detection' ' 90 test_must_fail git -c diff.renames=false merge-tree --write-tree side1 side3 >out && 91 grep "CONFLICT (modify/delete): numbers deleted" out 92 + ' 93 + 94 + test_expect_success '--quiet on conflicted merge' ' 95 + # Get rid of loose objects to start with 96 + git gc && 97 + echo "0 objects, 0 kilobytes" >expect && 98 + git count-objects >actual && 99 + test_cmp expect actual && 100 + 101 + # Ensure merge has conflict 102 + test_expect_code 1 git merge-tree --write-tree --quiet side1 side2 >output && 103 + 104 + # Ensure there is no output 105 + test_must_be_empty output && 106 + 107 + # Ensure no loose objects written (all new objects written would have 108 + # been in "outer layer" of the merge) 109 + git count-objects >actual && 110 + test_cmp expect actual 111 ' 112 113 test_expect_success 'Content merge and a few conflicts' '