From patchwork Wed Jan 5 17:27:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12704537 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1129FC433F5 for ; Wed, 5 Jan 2022 17:27:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242216AbiAER1o (ORCPT ); Wed, 5 Jan 2022 12:27:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54616 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242203AbiAER1k (ORCPT ); Wed, 5 Jan 2022 12:27:40 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9E47EC061212 for ; Wed, 5 Jan 2022 09:27:39 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id q8so3909206wra.12 for ; Wed, 05 Jan 2022 09:27:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=HsHj2KxDWTA9QM6TZSN11NDwemvgrQd3pHbka8fElO8=; b=n9p/5Y7rn9CDge8DKefAhY1iqgvi43SQLT+02acgKX78gNh8t82fmHIKNDNDwyiN7a wCkwHujQvf7b+/wPLprjflz4NOPecZlXljEJtsbpBpWTUo0vOd7q9LQyMDXgxrvH3i+x VSWVr3QT36Xg99TnQ/D+1TT5Uye601OO1N14gADpRbH8RlwGvLOYzuREUVg26wBiH3JR 5OrevNWBldFpWRa097zdUPmKlstKSxz5OLZUCffdz4E2PeXUqho6HQcT5uefgQe5ik0o x6z85r7zriUS4dnEUBlq+HOmv5ed2z+VQWCKqV+ZNGHFYzZQS70NRMtP8pnw1Jx+iex3 cl2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=HsHj2KxDWTA9QM6TZSN11NDwemvgrQd3pHbka8fElO8=; b=CI+/XqSDyzp1OeWm7Y6GNwb6zs225+La4E4nSmK3b9CfXCgLmPeRP6f0GAlH626po5 QX3n9R279RM8fAy9vCqGk1DFzkAVZamMqt4JU3LqAWe++ZIOeQd9pKulBkVBgtqqK/Q2 033WoUZwC5KlF09uKfWSGyZBtlv3MYSp0IkFKChTULYZzwQjGrYzwIf72vhF6EtSarnU GH6qKhLlN+9OUYKD7hCWrktm8nNZNeRKKlNEAVZsojKzXRji0IgaigRUp8Suv9mXJoF8 5jc2lL/GZlan9zUQsSqokOuVcX0qXjI01YLbSI/5paz6c6bqtecYBxpnD+zmBGnU7e3V zVKw== X-Gm-Message-State: AOAM530rXVn5C88cKFhtARwsnAeDWq3YWiFZofjKM8VSEjPzpqr2ruS9 It8tuY6DbKsgnyIHIIN1qwYspqpm2Gs= X-Google-Smtp-Source: ABdhPJyqdltB4PqVaUM6Ll4rJnB9SEH8NxufyYIXagNJkDKHghYKxclFqGQsL8BPInwMgC5FfuQ9AA== X-Received: by 2002:adf:ecc8:: with SMTP id s8mr49843076wro.184.1641403657324; Wed, 05 Jan 2022 09:27:37 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id h19sm3049391wmm.13.2022.01.05.09.27.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jan 2022 09:27:36 -0800 (PST) Message-Id: In-Reply-To: References: Date: Wed, 05 Jan 2022 17:27:28 +0000 Subject: [PATCH v2 1/8] merge-tree: rename merge_trees() to trivial_merge_trees() Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Elijah Newren , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren merge-recursive.h defined its own merge_trees() function, different than the one found in builtin/merge-tree.c. That was okay in the past, but we want merge-tree to be able to use the merge-ort functions, which will end up including merge-recursive.h. Rename the function found in builtin/merge-tree.c to avoid the conflict. Signed-off-by: Elijah Newren --- builtin/merge-tree.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 5dc94d6f880..06f9eee9f78 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -28,7 +28,7 @@ static void add_merge_entry(struct merge_list *entry) merge_result_end = &entry->next; } -static void merge_trees(struct tree_desc t[3], const char *base); +static void trivial_merge_trees(struct tree_desc t[3], const char *base); static const char *explanation(struct merge_list *entry) { @@ -225,7 +225,7 @@ static void unresolved_directory(const struct traverse_info *info, buf2 = fill_tree_descriptor(r, t + 2, ENTRY_OID(n + 2)); #undef ENTRY_OID - merge_trees(t, newbase); + trivial_merge_trees(t, newbase); free(buf0); free(buf1); @@ -342,7 +342,7 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s return mask; } -static void merge_trees(struct tree_desc t[3], const char *base) +static void trivial_merge_trees(struct tree_desc t[3], const char *base) { struct traverse_info info; @@ -378,7 +378,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) buf1 = get_tree_descriptor(r, t+0, argv[1]); buf2 = get_tree_descriptor(r, t+1, argv[2]); buf3 = get_tree_descriptor(r, t+2, argv[3]); - merge_trees(t, ""); + trivial_merge_trees(t, ""); free(buf1); free(buf2); free(buf3); From patchwork Wed Jan 5 17:27:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12704538 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 30AE2C433FE for ; Wed, 5 Jan 2022 17:27:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242212AbiAER1n (ORCPT ); Wed, 5 Jan 2022 12:27:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54614 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242201AbiAER1k (ORCPT ); Wed, 5 Jan 2022 12:27:40 -0500 Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 872D5C061201 for ; Wed, 5 Jan 2022 09:27:39 -0800 (PST) Received: by mail-wm1-x32e.google.com with SMTP id g191-20020a1c9dc8000000b0032fbf912885so3708566wme.4 for ; Wed, 05 Jan 2022 09:27:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=s/FNUD3Nfv1aJ56di/sqnJE/jJBUPQEIKWoIKlAJYVg=; b=eYhQO4WwXf0uE9Jh00Xwoo98cqFX07KpKEbC8zwt4xVpuUeGCwPXaFJZ0WgkEphWaN Ez3CH+eX5V52Tc1lZXxf8QQdXi+wVs9ijbtajl4y/YeBIBmyaE1GZCfmsqhn7gkDWJS9 PuYWmECezzvt6pZl7fiCR7f3Hb5LlVHc3g53LT+Jjwc1cXFYHLDhM2jqPnRXOuEW+Gsu pm5CsfAXTjpyz87bIk14GrnLndPtctpMdBZSE8jsvmJTTlq4SJdPkQUeGOv9/UC1gwcG HLcl9p71kPKvq4/7s0h+u63c7jaUFlPrI9PA3tJf6P1XMrM+K/RdEp+6bzQSkFW/S939 po1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=s/FNUD3Nfv1aJ56di/sqnJE/jJBUPQEIKWoIKlAJYVg=; b=iLG6x9lhxJOpvDNhao60ZQBLXywCaOT9e+C9FjFZiaIeIfCRVdEnUFr/z5TcwtNWfC fQXfr12PGICS9CZibgZbsjXSDsQpa8gyIgRmSlyf0l8drYDumQnVzuPKYKFRjWFQrw4/ didvo5YNnjxb8tmPFFgrAsmtiQihevzjQV2MS9QLAxrxTUdCLBiYmEj0XGaFIo+T6jgE I//WrUjmW+excVwa0WdJ9U8jATqRjZx2c3Yd5zJTNhPoLftwM74tOESdNByqIYH5ggYK JG1/WUQ5P7VM0f6nNU5d4lx/dxrmj4kAIfO/yPae+RbVW+RI7F098ASO/6Z0OSu0RNKT HnXA== X-Gm-Message-State: AOAM532Zk5+PwYJeSdp+IGVFMay0lmdm40ZEhftX3rCsbk7lOYG78dqE iyF13aMd5V+gIHpI5eL4KOgqtSqk9/Q= X-Google-Smtp-Source: ABdhPJw80r7fAmnuV4tNLRM1Th4yEWTBI24YXkzYn/E3PNZHAItNwWh8StO++9Cr8+EngE1bRIMqWw== X-Received: by 2002:a7b:c3c5:: with SMTP id t5mr3701611wmj.168.1641403657983; Wed, 05 Jan 2022 09:27:37 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id u14sm40802111wrf.39.2022.01.05.09.27.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jan 2022 09:27:37 -0800 (PST) Message-Id: In-Reply-To: References: Date: Wed, 05 Jan 2022 17:27:29 +0000 Subject: [PATCH v2 2/8] merge-tree: move logic for existing merge into new function Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Elijah Newren , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren In preparation for adding a non-trivial merge capability to merge-tree, move the existing merge logic for trivial merges into a new function. Signed-off-by: Elijah Newren --- builtin/merge-tree.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 06f9eee9f78..914ec960b7e 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -366,15 +366,12 @@ static void *get_tree_descriptor(struct repository *r, return buf; } -int cmd_merge_tree(int argc, const char **argv, const char *prefix) +static int trivial_merge(int argc, const char **argv) { struct repository *r = the_repository; struct tree_desc t[3]; void *buf1, *buf2, *buf3; - if (argc != 4) - usage(merge_tree_usage); - buf1 = get_tree_descriptor(r, t+0, argv[1]); buf2 = get_tree_descriptor(r, t+1, argv[2]); buf3 = get_tree_descriptor(r, t+2, argv[3]); @@ -386,3 +383,10 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) show_result(); return 0; } + +int cmd_merge_tree(int argc, const char **argv, const char *prefix) +{ + if (argc != 4) + usage(merge_tree_usage); + return trivial_merge(argc, argv); +} From patchwork Wed Jan 5 17:27:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12704539 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 478BEC433EF for ; Wed, 5 Jan 2022 17:27:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242220AbiAER1p (ORCPT ); Wed, 5 Jan 2022 12:27:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54624 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242204AbiAER1k (ORCPT ); Wed, 5 Jan 2022 12:27:40 -0500 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 34BD3C0611FD for ; Wed, 5 Jan 2022 09:27:40 -0800 (PST) Received: by mail-wr1-x431.google.com with SMTP id r17so84481780wrc.3 for ; Wed, 05 Jan 2022 09:27:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=V8S8SjfTWGNwbuwmn14qUCAsI9OJQyegvG/CX1wq7fI=; b=kB1hYcbjIxJUECAZv/49cByIrysgITvCTzuGXfXEwcudZZlUINgQMmurrAaYI6sHor EzKAKkR5AEe7pY18jU2F4yXHQF5QImOXJd8I+BKFt1ZNkbVdzfPgZliy4eKLAFulssoZ NgOrmXwuWJMApDAWggx4+umVRaqz+JNfqBiBqyU7r4pr5cGDWQMBCpC+1IspUhGU0grI e4U4pvpgUlsO/VRlwsuR221tP42BwAbP/N/M4zEyvyvpjWHZ1fNHITwJ+5q7yGk3xG9R QwEwuE3+uqTbNCYBOclGl9xn3oaFke/ekBQY05FkQ1x4ADEZ1jpO/c4GfvCBkh8ADGcs iSKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=V8S8SjfTWGNwbuwmn14qUCAsI9OJQyegvG/CX1wq7fI=; b=ZWfQwDFWLWg+YSZeD9Ry5h7UJ0f3u2/HcBwemwEu/iMVPBUYAgclZnMZx37faCSKkb yalmeC6+RXw4QEyDUdF/XbTk4uZyG58gFp4swSubVJzedwbpVdKrLVD92MZT/gXAcgmP WTOLYjqi2iBlE5o3tx52KNm9GpQ/hAaHf0ecrIfgwsHO1DIJ391wFybGILgj89EnMNMB tuqadtuw5IllFiorrId1qBveRfHvcBX4Txj6mZf18jtmZvAT5yG8moittphb2Jm1ge/g KOWQ5OA8iK34WEI6LslDWsoA2wFqMcN0j6T7KAM7IKrDXfbU9XCx9+fQwNg6aFkQABM2 Zn7g== X-Gm-Message-State: AOAM530mEfNRgxqSQ3LdTeVqpfd7j+mFiZFBplnJ1bQ5opo13/NDg4BZ p2thFDIlfVauoubqDYcGQkI5GY5sI2s= X-Google-Smtp-Source: ABdhPJwuBaaVW6SMEkCMfqLKvEvYrSHyAKuZhPZhwDd1nCm0J+dCkYRmfQG/0ePoQug/LWeBwAZdWw== X-Received: by 2002:a05:6000:d0:: with SMTP id q16mr1546881wrx.600.1641403658696; Wed, 05 Jan 2022 09:27:38 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a24sm1569325wmj.42.2022.01.05.09.27.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jan 2022 09:27:38 -0800 (PST) Message-Id: In-Reply-To: References: Date: Wed, 05 Jan 2022 17:27:30 +0000 Subject: [PATCH v2 3/8] merge-tree: add option parsing and initial shell for real merge function Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Elijah Newren , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Let merge-tree accept a `--real` parameter for choosing real merges instead of trivial merges. Note that real merges differ from trivial merges in that they handle: - three way content merges - recursive ancestor consolidation - renames - proper directory/file conflict handling - etc. Basically all the stuff you'd expect from `git merge`, just without updating the index and working tree. The initial shell added here does nothing more than die with "real merges are not yet implemented", but that will be fixed in subsequent commits. Signed-off-by: Elijah Newren --- builtin/merge-tree.c | 56 +++++++++++++++++++++++++++++++++++++------- git.c | 2 +- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 914ec960b7e..e1d2832c809 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -3,13 +3,12 @@ #include "tree-walk.h" #include "xdiff-interface.h" #include "object-store.h" +#include "parse-options.h" #include "repository.h" #include "blob.h" #include "exec-cmd.h" #include "merge-blobs.h" -static const char merge_tree_usage[] = "git merge-tree "; - struct merge_list { struct merge_list *next; struct merge_list *link; /* other stages for this object */ @@ -366,15 +365,17 @@ static void *get_tree_descriptor(struct repository *r, return buf; } -static int trivial_merge(int argc, const char **argv) +static int trivial_merge(const char *base, + const char *branch1, + const char *branch2) { struct repository *r = the_repository; struct tree_desc t[3]; void *buf1, *buf2, *buf3; - buf1 = get_tree_descriptor(r, t+0, argv[1]); - buf2 = get_tree_descriptor(r, t+1, argv[2]); - buf3 = get_tree_descriptor(r, t+2, argv[3]); + buf1 = get_tree_descriptor(r, t+0, base); + buf2 = get_tree_descriptor(r, t+1, branch1); + buf3 = get_tree_descriptor(r, t+2, branch2); trivial_merge_trees(t, ""); free(buf1); free(buf2); @@ -384,9 +385,46 @@ static int trivial_merge(int argc, const char **argv) return 0; } +struct merge_tree_options { + int real; +}; + +static int real_merge(struct merge_tree_options *o, + const char *branch1, const char *branch2) +{ + die(_("real merges are not yet implemented")); +} + int cmd_merge_tree(int argc, const char **argv, const char *prefix) { - if (argc != 4) - usage(merge_tree_usage); - return trivial_merge(argc, argv); + struct merge_tree_options o = { 0 }; + int expected_remaining_argc; + + const char * const merge_tree_usage[] = { + N_("git merge-tree --real "), + N_("git merge-tree "), + NULL + }; + struct option mt_options[] = { + OPT_BOOL(0, "real", &o.real, + N_("do a real merge instead of a trivial merge")), + OPT_END() + }; + + /* Check for a request for basic help */ + if (argc == 2 && !strcmp(argv[1], "-h")) + usage_with_options(merge_tree_usage, mt_options); + + /* Parse arguments */ + argc = parse_options(argc, argv, prefix, mt_options, + merge_tree_usage, 0); + expected_remaining_argc = (o.real ? 2 : 3); + if (argc != expected_remaining_argc) + usage_with_options(merge_tree_usage, mt_options); + + /* Do the relevant type of merge */ + if (o.real) + return real_merge(&o, argv[0], argv[1]); + else + return trivial_merge(argv[0], argv[1], argv[2]); } diff --git a/git.c b/git.c index 7edafd8ecff..0124c053878 100644 --- a/git.c +++ b/git.c @@ -561,7 +561,7 @@ static struct cmd_struct commands[] = { { "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, - { "merge-tree", cmd_merge_tree, RUN_SETUP | NO_PARSEOPT }, + { "merge-tree", cmd_merge_tree, RUN_SETUP }, { "mktag", cmd_mktag, RUN_SETUP | NO_PARSEOPT }, { "mktree", cmd_mktree, RUN_SETUP }, { "multi-pack-index", cmd_multi_pack_index, RUN_SETUP }, From patchwork Wed Jan 5 17:27:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12704541 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 85308C433FE for ; Wed, 5 Jan 2022 17:27:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242223AbiAER1p (ORCPT ); Wed, 5 Jan 2022 12:27:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54626 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242206AbiAER1l (ORCPT ); Wed, 5 Jan 2022 12:27:41 -0500 Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0D59FC061245 for ; Wed, 5 Jan 2022 09:27:41 -0800 (PST) Received: by mail-wm1-x332.google.com with SMTP id k66-20020a1ca145000000b00345fa984108so3707325wme.2 for ; Wed, 05 Jan 2022 09:27:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=7GoB9E//7sqZ3qsTLDJp/wclKZXAI4SgsQ5Qaeegepk=; b=QPppUko9E1HRHDI0weHL1Y+YIMXaFEL3kH/Uuc9DOpo5PiXih3mcvp9USNoI0zsstE a9OcLw4gortFE2xrKaqYriVO8pt/BipWYbCyeEQ6vb9zsx+/UjNdyCyYOY/c/Iib4U07 DyIJG6yFSIsuqoTB+2lI/ITWQVevyFCs2M23Xf7eHjc07QWHRVklmFRKUCr62OArZTHF BKECspYPzM9RckfE647y635rbVH5DKy6nukOSIzF33T4CjR4C//Br56gUnKnmbEh0vlU HGCPrJLd3SAq1vKb4o7fya8LwbP19xHDLI5o/8lbyb28hLS4y2gkC1hwwKGgPNKrY3mc l8QQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=7GoB9E//7sqZ3qsTLDJp/wclKZXAI4SgsQ5Qaeegepk=; b=14bIo+ERvcsbFFLMvXA3Xd0OG7Kp8v1I+5325IJ0lKcYA1dCGk/kWdsLFz89MwloP2 WfFtocy9a6MYCmWk50aeHuTKPCIQ+oATpPqELJ70HtK2q6I9xVgIvHV5TeVLUAsinaoV aFGeXm7ifBIC7dM/EQ+bMmrFCVo5z1FHhL01JzFs6aLsh37Aw9ltErvhzfQ3F5dUy3VJ OyX/Z7S1UfZERtu937qkX0gGm/tiRXPAfUmjGW6QnCa288ci7Y7ZniXhDH8iW0GiGnbN cJ7E3EcbdQu6Q7VOljOApef8EpsOGBpHfVUj5iMpCj5jBtC+KWBNncRfCHaxtF6M6783 S8lA== X-Gm-Message-State: AOAM531Kl2ZIR6hX1MRuwPRtjXHEOFobY5Bi7QNg0Xf+YWKOQWd4UMYS F+MDlyRR4HoReRzop854duUP+N+ZpXU= X-Google-Smtp-Source: ABdhPJwpf7gQzMHE2ZWa5TXAp/szNihC/P561a+Mm8vSRn2gR45cUwVGoVFz3F9Sg2qDihd+HOm4xQ== X-Received: by 2002:a7b:c058:: with SMTP id u24mr3716075wmc.90.1641403659362; Wed, 05 Jan 2022 09:27:39 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id x8sm2921905wmj.44.2022.01.05.09.27.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jan 2022 09:27:39 -0800 (PST) Message-Id: <1710ba4a9e432e2a854579c4c929e7f2cfc92211.1641403655.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 05 Jan 2022 17:27:31 +0000 Subject: [PATCH v2 4/8] merge-tree: implement real merges Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Elijah Newren , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren This adds the ability to perform real merges rather than just trivial merges (meaning handling three way content merges, recursive ancestor consolidation, renames, proper directory/file conflict handling, and so forth). However, unlike `git merge`, the working tree and index are left alone and no branch is updated. The only output is: - the toplevel resulting tree printed on stdout - exit status of 0 (clean) or 1 (conflicts present) This output is mean to be used by some higher level script, perhaps in a sequence of steps like this: NEWTREE=$(git merge-tree --real $BRANCH1 $BRANCH2) test $? -eq 0 || die "There were conflicts..." NEWCOMMIT=$(git commit-tree $NEWTREE -p $BRANCH1 -p $BRANCH2) git update-ref $BRANCH1 $NEWCOMMIT Note that higher level scripts may also want to access the conflict/warning messages normally output during a merge, or have quick access to a list of files with conflicts. That is not available in this preliminary implementation, but subsequent commits will add that ability. Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 28 +++++++---- builtin/merge-tree.c | 55 +++++++++++++++++++++- t/t4301-merge-tree-real.sh | 81 ++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 11 deletions(-) create mode 100755 t/t4301-merge-tree-real.sh diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 58731c19422..5823938937f 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -3,26 +3,34 @@ git-merge-tree(1) NAME ---- -git-merge-tree - Show three-way merge without touching index +git-merge-tree - Perform merge without touching index or working tree SYNOPSIS -------- [verse] +'git merge-tree' --real 'git merge-tree' DESCRIPTION ----------- -Reads three tree-ish, and output trivial merge results and -conflicting stages to the standard output. This is similar to -what three-way 'git read-tree -m' does, but instead of storing the -results in the index, the command outputs the entries to the -standard output. +Performs a merge, but does not make any new commits and does not read +from or write to either the working tree or index. -This is meant to be used by higher level scripts to compute -merge results outside of the index, and stuff the results back into the -index. For this reason, the output from the command omits -entries that match the tree. +The first form will merge the two branches, doing a full recursive +merge with rename detection. If the merge is clean, the exit status +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). + +The second form is meant for backward compatibility and will only do a +trival merge. It reads three tree-ish, and outputs trivial merge +results and conflicting stages to the standard output in a semi-diff +format. Since this was designed for higher level scripts to consume +and merge the results back into the index, it omits entries that match +. The result of this second form is is similar to what +three-way 'git read-tree -m' does, but instead of storing the results +in the index, the command outputs the entries to the standard output. GIT --- diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index e1d2832c809..ac50f3d108b 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -2,6 +2,9 @@ #include "builtin.h" #include "tree-walk.h" #include "xdiff-interface.h" +#include "help.h" +#include "commit-reach.h" +#include "merge-ort.h" #include "object-store.h" #include "parse-options.h" #include "repository.h" @@ -392,7 +395,57 @@ struct merge_tree_options { static int real_merge(struct merge_tree_options *o, const char *branch1, const char *branch2) { - die(_("real merges are not yet implemented")); + struct commit *parent1, *parent2; + struct commit_list *common; + struct commit_list *merge_bases = NULL; + struct commit_list *j; + struct merge_options opt; + struct merge_result result = { 0 }; + + parent1 = get_merge_parent(branch1); + if (!parent1) + help_unknown_ref(branch1, "merge", + _("not something we can merge")); + + parent2 = get_merge_parent(branch2); + if (!parent2) + help_unknown_ref(branch2, "merge", + _("not something we can merge")); + + init_merge_options(&opt, the_repository); + /* + * TODO: Support subtree and other -X options? + if (use_strategies_nr == 1 && + !strcmp(use_strategies[0]->name, "subtree")) + opt.subtree_shift = ""; + for (x = 0; x < xopts_nr; x++) + if (parse_merge_opt(&opt, xopts[x])) + die(_("Unknown strategy option: -X%s"), xopts[x]); + */ + + opt.show_rename_progress = 0; + + opt.branch1 = merge_remote_util(parent1)->name; /* or just branch1? */ + opt.branch2 = merge_remote_util(parent2)->name; /* or just branch2? */ + + /* + * Get the merge bases, in reverse order; see comment above + * merge_incore_recursive in merge-ort.h + */ + common = get_merge_bases(parent1, parent2); + for (j = common; j; j = j->next) + commit_list_insert(j->item, &merge_bases); + + /* + * TODO: notify if merging unrelated histories? + if (!common) + fprintf(stderr, _("merging unrelated histories")); + */ + + merge_incore_recursive(&opt, merge_bases, parent1, parent2, &result); + printf("%s\n", oid_to_hex(&result.tree->object.oid)); + merge_switch_to_result(&opt, NULL, &result, 0, 0); + return result.clean ? 0 : 1; } int cmd_merge_tree(int argc, const char **argv, const char *prefix) diff --git a/t/t4301-merge-tree-real.sh b/t/t4301-merge-tree-real.sh new file mode 100755 index 00000000000..f7aa310f8c1 --- /dev/null +++ b/t/t4301-merge-tree-real.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +test_description='git merge-tree --real' + +. ./test-lib.sh + +# This test is ort-specific +GIT_TEST_MERGE_ALGORITHM=ort +export GIT_TEST_MERGE_ALGORITHM + +test_expect_success setup ' + test_write_lines 1 2 3 4 5 >numbers && + echo hello >greeting && + echo foo >whatever && + git add numbers greeting whatever && + git commit -m initial && + + git branch side1 && + git branch side2 && + + git checkout side1 && + test_write_lines 1 2 3 4 5 6 >numbers && + echo hi >greeting && + echo bar >whatever && + git add numbers greeting whatever && + git commit -m modify-stuff && + + git checkout side2 && + test_write_lines 0 1 2 3 4 5 >numbers && + echo yo >greeting && + git rm whatever && + mkdir whatever && + >whatever/empty && + git add numbers greeting whatever/empty && + git commit -m other-modifications +' + +test_expect_success 'Content merge and a few conflicts' ' + git checkout side1^0 && + test_must_fail git merge side2 && + cp .git/AUTO_MERGE EXPECT && + E_TREE=$(cat EXPECT) && + + git reset --hard && + test_must_fail git merge-tree --real side1 side2 >RESULT && + R_TREE=$(cat RESULT) && + + # Due to differences of e.g. "HEAD" vs "side1", the results will not + # exactly match. Dig into individual files. + + # Numbers should have three-way merged cleanly + test_write_lines 0 1 2 3 4 5 6 >expect && + git show ${R_TREE}:numbers >actual && + test_cmp expect actual && + + # whatever and whatever~ should have same HASHES + git rev-parse ${E_TREE}:whatever ${E_TREE}:whatever~HEAD >expect && + git rev-parse ${R_TREE}:whatever ${R_TREE}:whatever~side1 >actual && + test_cmp expect actual && + + # greeting should have a merge conflict + git show ${E_TREE}:greeting >tmp && + cat tmp | sed -e s/HEAD/side1/ >expect && + git show ${R_TREE}:greeting >actual && + test_cmp expect actual +' + +test_expect_success 'Barf on misspelled option' ' + # Mis-spell with single "s" instead of double "s" + test_expect_code 129 git merge-tree --real --mesages FOOBAR side1 side2 2>expect && + + grep "error: unknown option.*mesages" expect +' + +test_expect_success 'Barf on too many arguments' ' + test_expect_code 129 git merge-tree --real side1 side2 side3 2>expect && + + grep "^usage: git merge-tree" expect +' + +test_done From patchwork Wed Jan 5 17:27:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12704540 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E39FEC433F5 for ; Wed, 5 Jan 2022 17:27:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242204AbiAER1q (ORCPT ); Wed, 5 Jan 2022 12:27:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54624 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242207AbiAER1m (ORCPT ); Wed, 5 Jan 2022 12:27:42 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B07F7C061201 for ; Wed, 5 Jan 2022 09:27:41 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id l10so3134899wrh.7 for ; Wed, 05 Jan 2022 09:27:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=DqeyVr+nI1KAiXNxyyhFxkZcB/WDtjcchYITzz1UKpY=; b=l6FfncQjex7bB2ZWtw6DWiPcQb4PP1bjqHl/Ft75+8tLeMmYGSGR+g9el+GAvmGQf1 uuRayV2aasxuLn9KIa+OzCF++lnFDcttPLEA/SrXmj58fdIVIO8b46kn65x2jVOmRuae uRM7+3WQpTHMUe6SWRp3sJzxZZacUgAsAHGQlJgNUBISvWsVDDU8ncIpwB/tlRYL7An9 1tc6YSUCGJmINz7UeaibZSmxOfWP2G5tp+4lImTSDQzNM/IyFo3trmm2OdHWL2+ThsC3 cvP+xEgUMWCwI0Bm5mJTDqG1yW8W/AlvWLo1d9z5WuCcGgPfVO0jn3xcF8fud2uOVUBd IWKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=DqeyVr+nI1KAiXNxyyhFxkZcB/WDtjcchYITzz1UKpY=; b=L7n8fB8eV9rMwUnWSfcXb7MqXJcs6UfyxUiZ1spmVD4G2lWP72wXugpyFqS0pS4nce qsfzqIA1nKMuIQ26oyXqeT04O8esvElt/5llY3Jq42Xsf3/Y4/IJLQ6VnDEJPhMPgWP3 /rP3ZBsZYlPyMtC/BMeAdLWT4EOp0CUarktWpqOoXkSTgPOrShHvCBe046NNhkHhX0+z +PvoK5CRvFNLizKGOaRNI5OngKsd7VpMKf0Zozf3+erMRCG0n1SriXrrjgJj+csFOnBQ uZCmOherzuSnfZRR+GOcRePUnDSw+40HnaZetO/9MNRgyhDUsIBnPGsr4UAb7KmriHp5 f+TQ== X-Gm-Message-State: AOAM530xs6WWSxMuxH9lZZ3fQF5f6eY+81sUcLG3OPuoF4/FjESYdLjI 4bGT728tyNg3AD5pH5fjPIVHzGgHcRw= X-Google-Smtp-Source: ABdhPJxg1Okj2a4FjJhfEgXKlVgAsNx41niBnPAWhocNNoTOqCk4FCBi69JtjUbhLXonswEns8UP3A== X-Received: by 2002:a05:6000:1843:: with SMTP id c3mr48335423wri.316.1641403660176; Wed, 05 Jan 2022 09:27:40 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id z22sm3601294wmp.40.2022.01.05.09.27.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jan 2022 09:27:39 -0800 (PST) Message-Id: In-Reply-To: References: Date: Wed, 05 Jan 2022 17:27:32 +0000 Subject: [PATCH v2 5/8] merge-ort: split out a separate display_update_messages() function Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Elijah Newren , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren No functional changes included in this patch; it's just a preparatory step in anticipation of wanting to handle the printed messages differently in `git merge-tree --real`. Signed-off-by: Elijah Newren --- merge-ort.c | 71 ++++++++++++++++++++++++++++------------------------- merge-ort.h | 8 ++++++ 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 0342f104836..3cdef173cd7 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4197,6 +4197,42 @@ static int record_conflicted_index_entries(struct merge_options *opt) return errs; } +void merge_display_update_messages(struct merge_options *opt, + struct merge_result *result) +{ + struct merge_options_internal *opti = result->priv; + struct hashmap_iter iter; + struct strmap_entry *e; + struct string_list olist = STRING_LIST_INIT_NODUP; + int i; + + trace2_region_enter("merge", "display messages", opt->repo); + + /* Hack to pre-allocate olist to the desired size */ + ALLOC_GROW(olist.items, strmap_get_size(&opti->output), + olist.alloc); + + /* Put every entry from output into olist, then sort */ + strmap_for_each_entry(&opti->output, &iter, e) { + string_list_append(&olist, e->key)->util = e->value; + } + string_list_sort(&olist); + + /* Iterate over the items, printing them */ + for (i = 0; i < olist.nr; ++i) { + struct strbuf *sb = olist.items[i].util; + + printf("%s", sb->buf); + } + string_list_clear(&olist, 0); + + /* Also include needed rename limit adjustment now */ + diff_warn_rename_limit("merge.renamelimit", + opti->renames.needed_limit, 0); + + trace2_region_leave("merge", "display messages", opt->repo); +} + void merge_switch_to_result(struct merge_options *opt, struct tree *head, struct merge_result *result, @@ -4235,39 +4271,8 @@ void merge_switch_to_result(struct merge_options *opt, trace2_region_leave("merge", "write_auto_merge", opt->repo); } - if (display_update_msgs) { - struct merge_options_internal *opti = result->priv; - struct hashmap_iter iter; - struct strmap_entry *e; - struct string_list olist = STRING_LIST_INIT_NODUP; - int i; - - trace2_region_enter("merge", "display messages", opt->repo); - - /* Hack to pre-allocate olist to the desired size */ - ALLOC_GROW(olist.items, strmap_get_size(&opti->output), - olist.alloc); - - /* Put every entry from output into olist, then sort */ - strmap_for_each_entry(&opti->output, &iter, e) { - string_list_append(&olist, e->key)->util = e->value; - } - string_list_sort(&olist); - - /* Iterate over the items, printing them */ - for (i = 0; i < olist.nr; ++i) { - struct strbuf *sb = olist.items[i].util; - - printf("%s", sb->buf); - } - string_list_clear(&olist, 0); - - /* Also include needed rename limit adjustment now */ - diff_warn_rename_limit("merge.renamelimit", - opti->renames.needed_limit, 0); - - trace2_region_leave("merge", "display messages", opt->repo); - } + if (display_update_msgs) + merge_display_update_messages(opt, result); merge_finalize(opt, result); } diff --git a/merge-ort.h b/merge-ort.h index c011864ffeb..1b93555a60b 100644 --- a/merge-ort.h +++ b/merge-ort.h @@ -70,6 +70,14 @@ void merge_switch_to_result(struct merge_options *opt, int update_worktree_and_index, int display_update_msgs); +/* + * Display messages about conflicts and which files were 3-way merged. + * Automatically called by merge_switch_to_result() with stream == stdout, + * so only call this when bypassing merge_switch_to_result(). + */ +void merge_display_update_messages(struct merge_options *opt, + struct merge_result *result); + /* Do needed cleanup when not calling merge_switch_to_result() */ void merge_finalize(struct merge_options *opt, struct merge_result *result); From patchwork Wed Jan 5 17:27:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12704542 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 243D6C433EF for ; Wed, 5 Jan 2022 17:27:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242231AbiAER1u (ORCPT ); Wed, 5 Jan 2022 12:27:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230323AbiAER1m (ORCPT ); Wed, 5 Jan 2022 12:27:42 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6C533C061245 for ; Wed, 5 Jan 2022 09:27:42 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id h23so1579961wrc.1 for ; Wed, 05 Jan 2022 09:27:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=DvALRlYCdTva9ksqtWjdE6MVdFOXX7uWydReXPvBTso=; b=FNzxoIsXrz3GqV+k49hVKHq+djXv5X0qcuF86g3nV4x7VpQrsqPDfd+DfT+fxzAiCF yzWIJKv9Y05KlgL27hyvMDW7tXGVymP3YW0IrzAuF3a0BPd0WKSCR04Ao8rDamohS2J9 SjQ+uiqNn3kCQdo3yL2vL854Ku9s3BnGGbTjbOiTIIRuQDm+G5/078cGUvZZvVmv7FYP 0pWr7vMAa2Qe0Fzhc/PHxLXBAnOFce8lBjGuH7+BGx5pOFKqr0Eprc64pSub9rONJrQY yoXCokVMIKhTRTEP3fJkYXGvFCc/rbGaWDOhFjjIcUUcuLmKMNkhtXZ+g/w4PkR3OPlK v+Vg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=DvALRlYCdTva9ksqtWjdE6MVdFOXX7uWydReXPvBTso=; b=DOTxJj7dZ1jUQoUGASyyXcmFKGaZ7n3qmqV8gK/oVxz0bF3qKv+Dri4/WkbSC1ndqd ww1x98fTQsJkaAggN/SqDFQcGlEFduiYZ5XIpZ/Sz4BkpPZwTLeARNw6XhhIrs/pOiRA iRIW1ffib/XIw2vP4onA9OPWRM9kUsh9i1q5PKvHwu/Hk/hZ/j9fzfgx0Sq1W7HpiwhF AQzvp1f1TX68YpUnFrsgpSRym+QTmTzRaVH7zowOrQR8y6WnMocp+EyDQsfs806E5+pI bFMOmDMAVnbAR5mPQ7TYXZ42OmMKGWNEyUhT+odgN/6QCygqucIYVx0g9lbhaMOyWXxg k//Q== X-Gm-Message-State: AOAM5316WtjHqrBaQWfDO3+TCTUyanoQdBvEC0fmQ4wdjJugQEu6QnF5 Up8boGsFtscWIWj537HkqeLXZEjpxoU= X-Google-Smtp-Source: ABdhPJxTP4dcJM6uoO6GXFjkrs0WprHnj2UJej4qMFUxZu8g4ZrshMEiXYoz0+8FK9SIc7u7E8CVUw== X-Received: by 2002:a05:6000:1807:: with SMTP id m7mr47308498wrh.191.1641403660911; Wed, 05 Jan 2022 09:27:40 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id l10sm3291392wmq.7.2022.01.05.09.27.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jan 2022 09:27:40 -0800 (PST) Message-Id: In-Reply-To: References: Date: Wed, 05 Jan 2022 17:27:33 +0000 Subject: [PATCH v2 6/8] merge-ort: allow update messages to be written to different file stream Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Elijah Newren , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren This modifies the new display_update_messages() function to allow printing to somewhere other than stdout. Signed-off-by: Elijah Newren --- merge-ort.c | 7 ++++--- merge-ort.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 3cdef173cd7..86eebf39166 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4198,7 +4198,8 @@ static int record_conflicted_index_entries(struct merge_options *opt) } void merge_display_update_messages(struct merge_options *opt, - struct merge_result *result) + struct merge_result *result, + FILE *stream) { struct merge_options_internal *opti = result->priv; struct hashmap_iter iter; @@ -4222,7 +4223,7 @@ void merge_display_update_messages(struct merge_options *opt, for (i = 0; i < olist.nr; ++i) { struct strbuf *sb = olist.items[i].util; - printf("%s", sb->buf); + fprintf(stream, "%s", sb->buf); } string_list_clear(&olist, 0); @@ -4272,7 +4273,7 @@ void merge_switch_to_result(struct merge_options *opt, } if (display_update_msgs) - merge_display_update_messages(opt, result); + merge_display_update_messages(opt, result, stdout); merge_finalize(opt, result); } diff --git a/merge-ort.h b/merge-ort.h index 1b93555a60b..55819a57da8 100644 --- a/merge-ort.h +++ b/merge-ort.h @@ -76,7 +76,8 @@ void merge_switch_to_result(struct merge_options *opt, * so only call this when bypassing merge_switch_to_result(). */ void merge_display_update_messages(struct merge_options *opt, - struct merge_result *result); + struct merge_result *result, + FILE *stream); /* Do needed cleanup when not calling merge_switch_to_result() */ void merge_finalize(struct merge_options *opt, From patchwork Wed Jan 5 17:27:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12704543 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DCA15C433F5 for ; Wed, 5 Jan 2022 17:27:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242239AbiAER1x (ORCPT ); Wed, 5 Jan 2022 12:27:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54638 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242214AbiAER1n (ORCPT ); Wed, 5 Jan 2022 12:27:43 -0500 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A8CEC061245 for ; Wed, 5 Jan 2022 09:27:43 -0800 (PST) Received: by mail-wm1-x331.google.com with SMTP id p1-20020a1c7401000000b00345c2d068bdso2342029wmc.3 for ; Wed, 05 Jan 2022 09:27:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=U3xsy67lIPsyRvBAK8igBO4UNzdFYTUMmcc1kQCaIE0=; b=Eb22douKMj6AglSgGHhdeab81qSfO2XuYft9h/dnnxempGBE6fIY+s4Tkw7XQ1UTrv RgqZYtuUI+p6QtugbLwkKoGlzmvB3OzGyWwDEV8U3i6pnJYOQT/HTxDdWQSy2POWeOb/ PidTATKuEQFVt1ok9VV9qMW3L1+jMcgl6G8FbZI7CSwREwd2kVAjnUsSzPDfUECeDFu6 1ILOoRZ58B53l4ixIpJqtzLEydla919MR4xzxIb0EFvila9ATZnVVBJxt7JjFRYMFtTg rF/OKv/1JI2GR+bI15HSH0XPZIxVHeWA2FgL58GMKiPk0MpR+afeCO1Y8Clj54mREQE9 AMaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=U3xsy67lIPsyRvBAK8igBO4UNzdFYTUMmcc1kQCaIE0=; b=A42gsBhUuvjB6mPnd2CHXUl7AjNxVoQUQwzMKLei0oFFdASNx1vt9k1/3ikicpDHfy 2oZ+PicMQeOEBaqbarfH9PLfhHjVRG0XIsKkumMMoKjcYYwojz6YIXQ5nlUAVayt2RSO mXQG8Oc0krnIuS6SovyfJ3k/g5G2Lunl3Evcwh16BTQeBfOyLROln7dty4hXp8ck14jL mJ3weQIduCcTr5NX6R0TOBT+KRB9wkzLz7M8DcDM5WrAQUmZfGbJAPxtR0lj1UlFKlsL 6Q0sfui8+WODPe99PPlrLwoic8TU34Mz5zBRw/p6XL+hDXNbeiBqtHOZ1lVO2vowK/Mg Ny7Q== X-Gm-Message-State: AOAM533MA/OgtWZmlDaamaCS6AYiwHapAChf+xQ7M553vSH2Zwpa9ZID u0m5LH0kTrpjUXRzj8NyhEKcHUd2M78= X-Google-Smtp-Source: ABdhPJwx5i7kY8UYq2mn3mFBycXzXNpXU5TGh05vjYks9Oq024586QQ7X4udz2qRtl1sxFIQ2dxc6Q== X-Received: by 2002:a1c:f706:: with SMTP id v6mr3714290wmh.140.1641403661623; Wed, 05 Jan 2022 09:27:41 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id c18sm3020352wrn.81.2022.01.05.09.27.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jan 2022 09:27:41 -0800 (PST) Message-Id: <4b513a6d696b8e6ff2c1b669059fcd8747bfa10d.1641403655.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 05 Jan 2022 17:27:34 +0000 Subject: [PATCH v2 7/8] merge-tree: support saving merge messages to a separate file Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Elijah Newren , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren When running `git merge-tree --real`, we previously would only return an exit status reflecting the cleanness of a merge, and print out the toplevel tree of the resulting merge. Merges also have informational messages, ("Auto-merging ", "CONFLICT (content): ...", "CONFLICT (file/directory)", etc.) In fact, when non-content conflicts occur (such as file/directory, modify/delete, add/add with differing modes, rename/rename (1to2), etc.), these informational messages are often the only notification since these conflicts are not representable in the contents of the file. Add a --messages option which names a file so that callers can request these messages be recorded somewhere. Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 6 ++++-- builtin/merge-tree.c | 18 ++++++++++++++++-- t/t4301-merge-tree-real.sh | 18 ++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 5823938937f..4d5857b390b 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' --real +'git merge-tree' --real [--messages=] 'git merge-tree' DESCRIPTION @@ -21,7 +21,9 @@ The first form will merge the two branches, doing a full recursive merge with rename detection. If the merge is clean, the exit status 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). +(which may have files including conflict markers). With `--messages`, +it will write any informational messages (such as "Auto-merging +" and conflict notices) 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 diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index ac50f3d108b..46b746b6b7c 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -390,6 +390,7 @@ static int trivial_merge(const char *base, struct merge_tree_options { int real; + char *messages_file; }; static int real_merge(struct merge_tree_options *o, @@ -443,8 +444,15 @@ static int real_merge(struct merge_tree_options *o, */ merge_incore_recursive(&opt, merge_bases, parent1, parent2, &result); + + if (o->messages_file) { + FILE *fp = xfopen(o->messages_file, "w"); + merge_display_update_messages(&opt, &result, fp); + fclose(fp); + } printf("%s\n", oid_to_hex(&result.tree->object.oid)); - merge_switch_to_result(&opt, NULL, &result, 0, 0); + + merge_finalize(&opt, &result); return result.clean ? 0 : 1; } @@ -452,15 +460,18 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) { struct merge_tree_options o = { 0 }; int expected_remaining_argc; + int original_argc; const char * const merge_tree_usage[] = { - N_("git merge-tree --real "), + N_("git merge-tree --real [] "), N_("git merge-tree "), NULL }; struct option mt_options[] = { OPT_BOOL(0, "real", &o.real, 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_END() }; @@ -469,8 +480,11 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) usage_with_options(merge_tree_usage, mt_options); /* Parse arguments */ + original_argc = argc; argc = parse_options(argc, argv, prefix, mt_options, merge_tree_usage, 0); + if (!o.real && original_argc < argc) + die(_("--real must be specified if any other options are")); expected_remaining_argc = (o.real ? 2 : 3); if (argc != expected_remaining_argc) usage_with_options(merge_tree_usage, mt_options); diff --git a/t/t4301-merge-tree-real.sh b/t/t4301-merge-tree-real.sh index f7aa310f8c1..5f3f27f504d 100755 --- a/t/t4301-merge-tree-real.sh +++ b/t/t4301-merge-tree-real.sh @@ -78,4 +78,22 @@ test_expect_success 'Barf on too many arguments' ' grep "^usage: git merge-tree" expect ' +test_expect_success '--messages gives us the conflict notices and such' ' + test_must_fail git merge-tree --real --messages=MSG_FILE side1 side2 && + + # 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 && + 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 MSG_FILE +' + test_done From patchwork Wed Jan 5 17:27:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12704544 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D8A2C433F5 for ; Wed, 5 Jan 2022 17:27:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242247AbiAER14 (ORCPT ); Wed, 5 Jan 2022 12:27:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54646 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242217AbiAER1o (ORCPT ); Wed, 5 Jan 2022 12:27:44 -0500 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 24607C061245 for ; Wed, 5 Jan 2022 09:27:44 -0800 (PST) Received: by mail-wm1-x335.google.com with SMTP id v123so92422wme.2 for ; Wed, 05 Jan 2022 09:27:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=JJXql95jnPmZtiZfmd+4qqg+IOMqUYchmPiA6893R2U=; b=G/51VbYteMMo3JBrV/DCa64deeR53J0OuvlcoS/dXrMlIcSlHNDHrUh1b3rKH8TB6x 83VJm8KS/3fpH92GUiiOVV2mOZ1M3/N4h+2Jky+Iw/vHg7yLCPApx0RQ2+RM0Gok91qd 49BvTdY6fSh2mdGCVyKfNPENQbaYogLXO9R+Z3Pl5a/HR3oLk4YZb8xeSi9eoPPcgww2 OASD/O+hpm9oAw3ObvA19An5R1V0UVpQVzx+gQ8gZmnpZnAksHlyE+OM8tHTTLYbWaw0 qGiCniYPMeI87dmt4rpeSNEUbE7tB1y2leAELudq1jOf+tfyPibpFLLSek56Paz8ChXR 0JNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=JJXql95jnPmZtiZfmd+4qqg+IOMqUYchmPiA6893R2U=; b=T8BZeORuOxBocVFf1fpyUZCb+CbdnmmRnoslytnrILX7S3cclha6PGaHtY+5g1HTLD rLaWcG3Btg6HTTiNPdG5sdgM3wtMR/431ZcEWx67j7UE378DnKee9K9SqrpapRzkUF77 7pauXWR5Sa4TSNb2ypGQYipLQSgz/48kaL3G1shR1o2LBXcirRjO7rHIb76s/lJip0jR W6H1MSPD3fYQmDOffYligy7UKm4xMtr3aHcKKJsLEhxqIhrAKm8+G2z5bi+H8OCMWSob nyO/aRe98Ku8AzpWV9klKysxfuYZatW+EZ28TLo81PVJKBIkTLeTM0R3VxZ1oYSxH7GC 0oag== X-Gm-Message-State: AOAM532NT6bHlOPigQh6KJHDsbhVjx05mWFQ/uPft3ALC044iKEFvYiR pOgG0aDi1N56UuQA0c1+G5YCQKt2fxo= X-Google-Smtp-Source: ABdhPJyhQDmmV4nQILEFrmoX/3n5ghli+L1u/LCPJdwKu44uwz27fVIvon5KWVcDwCjSCeeOpEeKNA== X-Received: by 2002:a05:600c:4f13:: with SMTP id l19mr3781711wmq.152.1641403662516; Wed, 05 Jan 2022 09:27:42 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a24sm3068886wmj.8.2022.01.05.09.27.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jan 2022 09:27:42 -0800 (PST) Message-Id: <01364bb020ee2836016ec0e8eafa2261fb7800ab.1641403655.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 05 Jan 2022 17:27:35 +0000 Subject: [PATCH v2 8/8] merge-tree: provide an easy way to access which files have conflicts Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Elijah Newren , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Callers of `git merge-tree --real` might want an easy way to determine which files conflicted. While they could potentially use the --messages option and parse the resulting messages written to that file, those messages are not meant to be machine readable. Provide a simpler mechanism of having the user specify --unmerged-list=$FILENAME, and then write a NUL-separated list of unmerged filenames to the specified file. Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 6 ++++-- builtin/merge-tree.c | 16 ++++++++++++++++ merge-ort.c | 13 +++++++++++++ merge-ort.h | 3 +++ t/t4301-merge-tree-real.sh | 9 +++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 4d5857b390b..542cea1a1a8 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' --real [--messages=] +'git merge-tree' --real [--messages=] [--conflicted-list=] 'git merge-tree' 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 -" and conflict notices) to the given file. +" 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 diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 46b746b6b7c..4ae34da98b1 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -391,6 +391,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, @@ -450,6 +451,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); @@ -472,6 +486,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() }; diff --git a/merge-ort.c b/merge-ort.c index 86eebf39166..3d6dd1b234c 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -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, diff --git a/merge-ort.h b/merge-ort.h index 55819a57da8..165cef6616f 100644 --- a/merge-ort.h +++ b/merge-ort.h @@ -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); diff --git a/t/t4301-merge-tree-real.sh b/t/t4301-merge-tree-real.sh index 5f3f27f504d..ec7bd8efd06 100755 --- a/t/t4301-merge-tree-real.sh +++ b/t/t4301-merge-tree-real.sh @@ -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