From patchwork Sat Feb 12 20:34:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744426 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 65E3BC433F5 for ; Sat, 12 Feb 2022 20:34:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231584AbiBLUfB (ORCPT ); Sat, 12 Feb 2022 15:35:01 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53394 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231411AbiBLUfA (ORCPT ); Sat, 12 Feb 2022 15:35:00 -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 E2152606E3 for ; Sat, 12 Feb 2022 12:34:56 -0800 (PST) Received: by mail-wm1-x32e.google.com with SMTP id m126-20020a1ca384000000b0037bb8e379feso9267476wme.5 for ; Sat, 12 Feb 2022 12:34:56 -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=N8150CHXpvX+hJss65r04LNIIvsPN7iqWPEmjtAJYYZZLDgI1CWaLwZIwJQAMksMHO EzXcGP22UQmMWzHNkqD1lHga7XPnTO1ywmTfBWBG7Spe0CcGCaPK/MF7QUFSjLS08399 uFlN8JxTjTfGITG1HK67yWNiiViIt+Wo2pF0khCZa4RRjKt6yvJnn9w2kEhlBaWwd0Jl 9wLKx89m0uduBftT3GxC05Nxh+Qbf//mjeJYV24eguYBJSSjkAIPeImPub9IsdIM3PTS kpoDLJRagGwpsGVUYKdAdHFE9Fkv9N4FQbNkekKshkDOK8Gy+wn1XnS+CQoQLJcxWBYp 8djQ== 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=lTOlmCsslKIhLtnJZXYUX2Rg6tGqw5R/XCBonc/7lxlna9rgt9sdchocNWPR4C73vk C3l/1t3TDYqxyXqEjweDswf3L6/iicBvgXp2Xgghur1tE86KbKjWG+WEwijiznhKJ6NR 0QF4kxxZrnnzswvPosr2ADXdh3r4qfR84vYGgbveVmhV7yQdPtEtg6KpQdvFjGOT5mEf 6Be+hAAyax5ngrS7qHC01NSxnjjLwWM52Br3VMoRYjRFrV1ru8+mJ/WqQ9mbMay1QQcB CnPZzJ/hPHruEODj8heWJQW64P35NWuHElcihC7hM8rbfhPA0RbgaSUea1VjqsG0/4Ih sexQ== X-Gm-Message-State: AOAM53133aEGk7Z4spdH7u0bpRd6/5KkAEZ2iPPxmsrVdsbcY91DHoC6 t7OXPgTJmbb4qBt34vdgKX8ucFz73iA= X-Google-Smtp-Source: ABdhPJyBZrvYZR/s2/qRblP7koajMY+cbvOVfK5/um2iwUBEMoafUKqlatYsG4Dr9qHQJw6ACcGTRQ== X-Received: by 2002:a7b:c184:: with SMTP id y4mr5287388wmi.117.1644698095352; Sat, 12 Feb 2022 12:34:55 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a10sm818619wrt.59.2022.02.12.12.34.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:34:54 -0800 (PST) Message-Id: <4a7cd5542bb2f89b4874e4115542ccee9c4639af.1644698093.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:42 +0000 Subject: [PATCH v4 01/12] 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 , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , 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 Sat Feb 12 20:34:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744427 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 5A408C433F5 for ; Sat, 12 Feb 2022 20:35:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231600AbiBLUfD (ORCPT ); Sat, 12 Feb 2022 15:35:03 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53402 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231585AbiBLUfB (ORCPT ); Sat, 12 Feb 2022 15:35:01 -0500 Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ED3B1606E5 for ; Sat, 12 Feb 2022 12:34:57 -0800 (PST) Received: by mail-wm1-x32f.google.com with SMTP id d14-20020a05600c34ce00b0037bf4d14dc7so7763343wmq.3 for ; Sat, 12 Feb 2022 12:34:57 -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=AJy5Hf7MNeXX1+PKGDxKUWgB1mvD/x00HlWELiq3kfRdk444k5PIBhMeDdQ3jzvxLN DZmRTNWSEIKtDoOpWDxxyF7P6Bbh+DnhCQ647VQVrlgu6gKR9z37HpptTyUdymwlSsps ZO3HownZG3RAWWUW0aivwuT6PK7FU2XxDGE/lxoNDWv38dKaLgPI4hF7wcHnRqzurR59 q4eTT+K3JVadhMqzPj5aEEmQsW7jcOcFVCEJp0wltEpmwlpYQ6MIHGYjHN5v1tqBa3jp fgNfPTf2EH3ssdlqkngAo3VTM8rcKv2008lng+BaO3BJK49++mH+bbCTs04nDgRqrQ/z RWsg== 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=M3jEywMTExAbD4Sru/836Qzr7/BZgZWBuHx4de4eVNxjE4czQSbjCEC1H++6neX/eQ xIU6ZEKh2+HxWKdAHIkwA/8y3dd213oU3EiREoHfwAJoKRjaMGM6ZQ/Z2TU2nqbG1WAs FeY8lyfT1ibR+jqt8fQbAwvZ459JagCOaQCipv13us4pc2vO2ZNYUcNbw6JX4vVpKkw4 VvJnW0XslG8cz2ciJckzNaKFxGWNgNsk+1GwAj9/nJQpRlHOoe1/SyaYW3xfX3SAGm92 EVR+GVjCgTr7O2v778ZZcVFZnFxyntk6A9JIAPy9ZXDFAIiHyPySjkADK71n4i93tbsu J5tQ== X-Gm-Message-State: AOAM531KVj4isRnAq7277lFH7TQYsb3jL7GjQKjRwua6UOivj8+M8SAE Mr2AgiJupEMByQOnmTBpxP1LqTTzQmc= X-Google-Smtp-Source: ABdhPJwMsgulaUFKl17jkU/i1Nq/S3ay+2jiJk5TDwzMJB15ZKl1Fua2jk3CA+z8tbuNDWbFnTiU4g== X-Received: by 2002:a05:600c:3641:: with SMTP id y1mr5210607wmq.44.1644698096270; Sat, 12 Feb 2022 12:34:56 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id s7sm8309103wrw.71.2022.02.12.12.34.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:34:55 -0800 (PST) Message-Id: <4780ff6784d426bf0a96859ef9bf9c14e87d5f50.1644698093.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:43 +0000 Subject: [PATCH v4 02/12] 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 , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , 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 Sat Feb 12 20:34:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744428 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 230E4C433F5 for ; Sat, 12 Feb 2022 20:35:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231614AbiBLUfH (ORCPT ); Sat, 12 Feb 2022 15:35:07 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53416 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231592AbiBLUfC (ORCPT ); Sat, 12 Feb 2022 15:35:02 -0500 Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AD580606E3 for ; Sat, 12 Feb 2022 12:34:58 -0800 (PST) Received: by mail-wr1-x436.google.com with SMTP id w11so20666739wra.4 for ; Sat, 12 Feb 2022 12:34:58 -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=lUeMBI0VGqVpVf36mWn+Z0nc/oxflgv+ptH2bmFaszA=; b=ms4MLViO8HtEH3zMUHulje53gE1pKe+MUxOy+x8pfcUkocDclaOSiI6SBOf9IBnQAP QlhESDITnsmODwsCNJEzZLpVv+UYQpa0IkRHwFqXNOu1n00LYKR5aHSULcM/vO/Ehuju UzqAQeVZN36iETuOLCAaEZbOcuibqQ+T9sTKR7mJ5x9XRUPHl8JmVsGEQlb4giE9OEJ8 bve6KWudVtycyjdb+gw4283nK4oJ7wJ5hDVSoGe+DTpuFmwqOqdX/bRP5bOPmX1NnN+X aDTTYsscRUm8NCpPwNyJmo+m3kHBlFqWDdnwzsKb/NDgPFKMyyXHexHYnHAZGJ+zGxjH n3Qg== 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=lUeMBI0VGqVpVf36mWn+Z0nc/oxflgv+ptH2bmFaszA=; b=fUvlih22+t712pNGy7DM2s0eA8GMCNS3NZvTXTBWldXi8lljFy9Gk8yYrnz0KqKBzD 6gEE17dMSM9Jy0FMgE3k2wKzCswtj7LujzrscP92pg8EUlnOA7c3E8ziRXIDDG3lwqH+ 8S8N/KWNU/hNm3H8uHFZ/2EIiVYcafvowQ8eiYIp92FOJZSGGNsEkdlUg1OnVGkU6iSr i8nrWE8i8CkzRcxk/gnyWm6vNp3C3/YsgEepvqqxbhO8sTGT/MY4IktkjwNav2zDgYjx vEnUkoNYKVvOqpVifXHuvYbCtZKHiJ7dx46huqpNkUzOafaOGLF+vlqEA2AnxCTyi+l9 /OFg== X-Gm-Message-State: AOAM533Ac2FdT1vMTBbmhAEmgIvMPNkjgHmsF5Y6/no1zTeLvpccbi5G JO/TuO689MghrCD0GfRvcYGRJkbTf6Y= X-Google-Smtp-Source: ABdhPJzPlSMvFZD9wKiCp/91vUSH9RomZv9YiplmHArJtlDg/Ow7uJp8Ro2P8sAxutaNrRC9Is/naw== X-Received: by 2002:a05:6000:1e1b:: with SMTP id bj27mr5916232wrb.385.1644698097163; Sat, 12 Feb 2022 12:34:57 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id b15sm20132555wri.96.2022.02.12.12.34.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:34:56 -0800 (PST) Message-Id: <60253745f5c59ac4c75d46df1f98ee722523f166.1644698093.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:44 +0000 Subject: [PATCH v4 03/12] 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 , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , 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 `--write-tree` parameter for choosing real merges instead of trivial merges, and accept an optional `--trivial-merge` option to get the traditional behavior. Note that these accept different numbers of arguments, though, so these names need not actually be used. 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 | 84 +++++++++++++++++++++++++++++++++++++++----- git.c | 2 +- 2 files changed, 76 insertions(+), 10 deletions(-) diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 914ec960b7e..0f9d928e862 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,74 @@ static int trivial_merge(int argc, const char **argv) return 0; } +enum mode { + MODE_UNKNOWN, + MODE_TRIVIAL, + MODE_REAL, +}; + +struct merge_tree_options { + int mode; +}; + +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 [--write-tree] "), + N_("git merge-tree [--trivial-merge] "), + NULL + }; + struct option mt_options[] = { + OPT_CMDMODE(0, "write-tree", &o.mode, + N_("do a real merge instead of a trivial merge"), + MODE_REAL), + OPT_CMDMODE(0, "trivial-merge", &o.mode, + N_("do a trivial merge only"), MODE_TRIVIAL), + OPT_END() + }; + + /* Parse arguments */ + argc = parse_options(argc, argv, prefix, mt_options, + merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION); + switch (o.mode) { + default: + BUG("unexpected command mode %d", o.mode); + case MODE_UNKNOWN: + switch (argc) { + default: + usage_with_options(merge_tree_usage, mt_options); + case 2: + o.mode = MODE_REAL; + break; + case 3: + o.mode = MODE_TRIVIAL; + break; + } + expected_remaining_argc = argc; + break; + case MODE_REAL: + expected_remaining_argc = 2; + break; + case MODE_TRIVIAL: + expected_remaining_argc = 3; + break; + } + + if (argc != expected_remaining_argc) + usage_with_options(merge_tree_usage, mt_options); + + /* Do the relevant type of merge */ + if (o.mode == MODE_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 5ff21be21f3..6090a1289db 100644 --- a/git.c +++ b/git.c @@ -558,7 +558,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 Sat Feb 12 20:34:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744430 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 57FFEC433FE for ; Sat, 12 Feb 2022 20:35:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231623AbiBLUfK (ORCPT ); Sat, 12 Feb 2022 15:35:10 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53428 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231585AbiBLUfE (ORCPT ); Sat, 12 Feb 2022 15:35:04 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A9692606E5 for ; Sat, 12 Feb 2022 12:34:59 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id v12so20717990wrv.2 for ; Sat, 12 Feb 2022 12:34:59 -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=BI2XPKuQkY8KatSiVlkfJXv4UIQhhGiLSSJo2kE67sQ=; b=bbm17XjIFCNZzJ7fhRvv0W7ciS2n8yfHZKVXyEl9pIJDnx1OE1OsAZKfR2e+h1LgYU 7Tl2F6HZstRrj8S5ipOAbUzddoJBRC0aWwYH8ljgg3MwHtuXqnDvuXSp6+oPmhC6uIEr XqoRathGsDeUSNJqH/E3xoXF88eRkFWNhoGE7tis0dJLeQd/5AQv39ip1cT7Lmnud3ai kk9fKDdsOCziJG6NwBe4komu5qP4R2T73dxaITenUJQJLNl/c/R1xDm1I1Ht4iwW2xXb s0Bbqee9qwW8NXdDyP/ddMjgz7yS2dUBBM49vx+t/ao59b+13G4QVr5d7if5EMMZHbtt Nq8A== 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=BI2XPKuQkY8KatSiVlkfJXv4UIQhhGiLSSJo2kE67sQ=; b=fX8bPHemtGU5BYrHZrbAypcn3tINOFKso6rap4in366ycRJi4rPOX7VmabiaNRWWhW j2rLbE0vuxtnSdUDW4dLm/B6URNDQkaL44542awQNnwbSywRZseOpJbXt0i4AfKlLrJE fVEppRxSTtieQ81cm1g04Tbn9l/9C050HY8neLaQc/OzInFMmLN47jaRIK4GEPzcLzGC kkIBfZGhaY3bxXKVKvLhMFvlt9k2ReIaq39bAt7eQkYAf+s97dXuo81X39LmAM3vMdGi MEPZyrod1koAgpYVOcnEakcCb6JY7pXP8b0njWe1K3CIEvlLI/vl6q344paJkKDF//hD /rjQ== X-Gm-Message-State: AOAM531uyEUFWRFijkG0lNDM9+m4s/wr9HyUfL3NxFT4Lk/sUAUbAIpT t3BWB7Az0wN9iSdiePcYmAEvaawR3pM= X-Google-Smtp-Source: ABdhPJxfcfIS7J7bWfI6OvnaUfab0Cu8RlBQHoPk3O6QDtGFrzbmf3qzfDQCOzLmnVRDTVHmAGNjzA== X-Received: by 2002:adf:a4c8:: with SMTP id h8mr5828872wrb.169.1644698097979; Sat, 12 Feb 2022 12:34:57 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id i3sm25238365wrq.72.2022.02.12.12.34.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:34:57 -0800 (PST) Message-Id: In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:45 +0000 Subject: [PATCH v4 04/12] merge-tree: implement real merges Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , 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), 1 (conflicts present), anything else (merge could not be performed; unknown if clean or conflicted) This output is meant to be used by some higher level script, perhaps in a sequence of steps like this: NEWTREE=$(git merge-tree --write-tree $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 (meaning that NEWTREE would be a lot more than a tree in the case of conflicts). This also marks the traditional trivial merge of merge-tree as deprecated. The trivial merge not only had limited applicability, the output format was also difficult to work with (and its format undocumented), and will generally be less performant than real merges. Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 79 +++++++++++++++++++---- builtin/merge-tree.c | 44 ++++++++++++- t/t4301-merge-tree-write-tree.sh | 106 +++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+), 13 deletions(-) create mode 100755 t/t4301-merge-tree-write-tree.sh diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 58731c19422..586733ea564 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -3,26 +3,81 @@ 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' +'git merge-tree' [--write-tree] +'git merge-tree' [--trivial-merge] (deprecated) 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. - -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. + +Performs a merge, but does not make any new commits and does not read +from or write to either the working tree or index. + +The first form will merge the two branches, doing a real merge. A real +merge is distinguished from a trivial merge in that it includes: + + * three way content merges of individual files + * rename detection + * proper directory/file conflict handling + * recursive ancestor consolidation (i.e. when there is more than one + merge base, creating a virtual merge base by merging the merge bases) + * etc. + +After the merge completes, the first form will create a new toplevel +tree object. See `OUTPUT` below for details. + +The second form is deprecated; it is kept for backward compatibility +reasons but may be deleted in the future. Other than the optional +`--trivial-merge`, it accepts no options. It can only do a trivial +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. +This form not only has limited applicability, the output format is +also difficult to work with, and it will generally be less performant +than the first form even on successful merges (especially if working +in large repositories). The remainder of this manual will only +discuss the first form. + +OUTPUT +------ + +For either a successful or conflicted merge, the output from +git-merge-tree is simply one line: + + + +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. + +EXIT STATUS +----------- + +For a successful, non-conflicted merge, the exit status is 0. When the +merge has conflicts, the exit status is 1. If the merge is not able to +complete (or start) due to some kind of error, the exit status is +something other than 0 or 1 (and the output is unspecified). + +USAGE NOTES +----------- + +git-merge-tree was written to be low-level plumbing, similar to +hash-object, mktree, commit-tree, write-tree, update-ref, and mktag. +Thus, it could be used as a part of a series of steps such as + + NEWTREE=$(git merge-tree --write-tree $BRANCH1 $BRANCH2) + test $? -eq 0 || die "There were conflicts..." + NEWCOMMIT=$(git commit-tree $NEWTREE -p $BRANCH1 -p $BRANCH2) + git update-ref $BRANCH1 $NEWCOMMIT GIT --- diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 0f9d928e862..af445cb1576 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" @@ -398,7 +401,46 @@ 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-tree", + _("not something we can merge")); + + parent2 = get_merge_parent(branch2); + if (!parent2) + help_unknown_ref(branch2, "merge-tree", + _("not something we can merge")); + + init_merge_options(&opt, the_repository); + + opt.show_rename_progress = 0; + + opt.branch1 = branch1; + opt.branch2 = branch2; + + /* + * Get the merge bases, in reverse order; see comment above + * merge_incore_recursive in merge-ort.h + */ + common = get_merge_bases(parent1, parent2); + if (!common) + die(_("refusing to merge unrelated histories")); + for (j = common; j; j = j->next) + commit_list_insert(j->item, &merge_bases); + + merge_incore_recursive(&opt, merge_bases, parent1, parent2, &result); + if (result.clean < 0) + die(_("failure to merge")); + puts(oid_to_hex(&result.tree->object.oid)); + merge_finalize(&opt, &result); + return !result.clean; /* result.clean < 0 handled above */ } int cmd_merge_tree(int argc, const char **argv, const char *prefix) diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh new file mode 100755 index 00000000000..e4f9421c105 --- /dev/null +++ b/t/t4301-merge-tree-write-tree.sh @@ -0,0 +1,106 @@ +#!/bin/sh + +test_description='git merge-tree --write-tree' + +. ./test-lib.sh + +# This test is ort-specific +if test "${GIT_TEST_MERGE_ALGORITHM}" != "ort" +then + skip_all="GIT_TEST_MERGE_ALGORITHM != ort" + test_done +fi + +test_expect_success setup ' + test_write_lines 1 2 3 4 5 >numbers && + echo hello >greeting && + echo foo >whatever && + git add numbers greeting whatever && + test_tick && + git commit -m initial && + + git branch side1 && + git branch side2 && + git branch side3 && + + git checkout side1 && + test_write_lines 1 2 3 4 5 6 >numbers && + echo hi >greeting && + echo bar >whatever && + git add numbers greeting whatever && + test_tick && + 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 && + test_tick && + git commit -m other-modifications && + + git checkout side3 && + git mv numbers sequence && + test_tick && + git commit -m rename-numbers +' + +test_expect_success 'Clean merge' ' + git merge-tree --write-tree side1 side3 >RESULT && + q_to_tab <<-EOF >expect && + 100644 blob $(git rev-parse side1:greeting)Qgreeting + 100644 blob $(git rev-parse side1:numbers)Qsequence + 100644 blob $(git rev-parse side1:whatever)Qwhatever + EOF + + git ls-tree $(cat RESULT) >actual && + test_cmp expect actual +' + +test_expect_success 'Content merge and a few conflicts' ' + git checkout side1^0 && + test_must_fail git merge side2 && + expected_tree=$(cat .git/AUTO_MERGE) && + + # We will redo the merge, while we are still in a conflicted state! + test_when_finished "git reset --hard" && + + test_expect_code 1 git merge-tree --write-tree side1 side2 >RESULT && + actual_tree=$(head -n 1 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 ${actual_tree}:numbers >actual && + test_cmp expect actual && + + # whatever and whatever~ should have same HASHES + git rev-parse ${expected_tree}:whatever ${expected_tree}:whatever~HEAD >expect && + git rev-parse ${actual_tree}:whatever ${actual_tree}:whatever~side1 >actual && + test_cmp expect actual && + + # greeting should have a merge conflict + git show ${expected_tree}:greeting >tmp && + cat tmp | sed -e s/HEAD/side1/ >expect && + git show ${actual_tree}:greeting >actual && + test_cmp expect actual +' + +test_expect_success 'Barf on misspelled option, with exit code other than 0 or 1' ' + # Mis-spell with single "s" instead of double "s" + test_expect_code 129 git merge-tree --write-tree --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 --write-tree side1 side2 invalid 2>expect && + + grep "^usage: git merge-tree" expect +' + +test_done From patchwork Sat Feb 12 20:34:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744432 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 A7326C433F5 for ; Sat, 12 Feb 2022 20:35:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231656AbiBLUfP (ORCPT ); Sat, 12 Feb 2022 15:35:15 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53434 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231601AbiBLUfE (ORCPT ); Sat, 12 Feb 2022 15:35:04 -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 68874606E6 for ; Sat, 12 Feb 2022 12:35:00 -0800 (PST) Received: by mail-wm1-x335.google.com with SMTP id n8so2558192wms.3 for ; Sat, 12 Feb 2022 12:35:00 -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=hBf1L3DAgwM6lVnjfgVq6LC6AtXTGHUlM38V8n4wdp8=; b=Zt5YSo8T8BEc/GQsguQJwWgiwWOoPkOz9+NK4ImCFDbZGBrg40r6UoFSXZn70hsmVH VJuqikyByFChMMb7GVYkqLkNhptrUMbgsGRJzpRA7lMk+OYtO5o4fcRqnLIVQdPyzBHS B8JGrSP4dzf7ny6jjyrEEAVhp7hHVOysisZiPRdv9RMa7pzxU0MNXySKH80X0Lx1aIL4 Eia4yQJATrBYU/uAGdhkhXqSEhp6/1y5Px/5uXhIp/VDPNfukk0E5pmV7i7J2NkVzAUR ByPrco/GzyoiFuR3/vW3RgDN/AiTKJ+FjZVx3Ms7LA22B2/oNtoLSa+dgZuUY4k4gGOr wwXg== 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=hBf1L3DAgwM6lVnjfgVq6LC6AtXTGHUlM38V8n4wdp8=; b=SIwhgIutcnRpVdq/8L+i4KxrRjHr7fvF05QwK97Gz/WCIMDoUA9Eqa4uJ4rU8aj6CX ymtAmotBhZzQ5FH43zcHXsJlr2o/hRLHOSIEX5u+I97xyHxgCohG7uZ/+cNv7DkL6yC6 WUek6ggAiWUFOosVC3m3Vsxw6UstFbkZIlh3MYbsA2H8A38qKfO0cGqoIKbKk+i1gAKi +9cKaD6fIgfCRVNy4a/w+sJ7oWm6pRgflWFDaCq21oJWXHgGLhxF7nC8NIKeqhbhIlyP nNcXi7ARDp5ocdlhOni5C/nc/pIJMpJyg8VK69tYtKUv7GlNjPkCXYsdWUQQnM9PoU20 VAjA== X-Gm-Message-State: AOAM532k5vmOJ13GTswFOUIL08wxRIBo2ewgQDVbg1kZpPGCyUIANG9J e9fMlsi2vslIaE+7XJF2kgZi8jzIgRI= X-Google-Smtp-Source: ABdhPJysQ8itZZsiypzL5N5v0xFcpKXgQzsc6pVRhyPrFg5gpnP+bgaXltNKLh7RNfVgE0f36u14Ig== X-Received: by 2002:a05:600c:2551:: with SMTP id e17mr5207153wma.128.1644698098735; Sat, 12 Feb 2022 12:34:58 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 11sm27965907wry.68.2022.02.12.12.34.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:34:58 -0800 (PST) Message-Id: <58a5594aeb6e04e21409835e00c721a7417569df.1644698093.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:46 +0000 Subject: [PATCH v4 05/12] 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 , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren This patch includes no new code; it simply moves a bunch of lines into a new function. As such, there are no functional changes. This is just a preparatory step to allow the printed messages to be handled differently by other callers, such as in `git merge-tree --write-tree`. (Patch best viewed with --color-moved --color-moved-ws=allow-indentation-change to see that it is a simple code movement.) Signed-off-by: Elijah Newren --- merge-ort.c | 78 ++++++++++++++++++++++++++++------------------------- merge-ort.h | 8 ++++++ 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 9bf15a01db8..ebaed98d53a 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4235,6 +4235,45 @@ 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; + + if (opt->record_conflict_msgs_as_headers) + BUG("Either display conflict messages or record them as headers, not both"); + + 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, @@ -4272,43 +4311,8 @@ void merge_switch_to_result(struct merge_options *opt, fclose(fp); 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; - - if (opt->record_conflict_msgs_as_headers) - BUG("Either display conflict messages or record them as headers, not both"); - - 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 fe599b87868..e5aec45b18f 100644 --- a/merge-ort.h +++ b/merge-ort.h @@ -80,6 +80,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 Sat Feb 12 20:34:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744431 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 E1976C433EF for ; Sat, 12 Feb 2022 20:35:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231635AbiBLUfL (ORCPT ); Sat, 12 Feb 2022 15:35:11 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53446 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231607AbiBLUfF (ORCPT ); Sat, 12 Feb 2022 15:35:05 -0500 Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 43AC1606E7 for ; Sat, 12 Feb 2022 12:35:01 -0800 (PST) Received: by mail-wm1-x330.google.com with SMTP id m126-20020a1ca384000000b0037bb8e379feso9267603wme.5 for ; Sat, 12 Feb 2022 12:35:01 -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=YC+PILdDKMPHMPRXjtSVNKuqv2zXYvxMiGpRu5YK0sg=; b=MisPVKfgIGZzq7GhSDRzfwFJPhKgJ3NRDXsyOqFD+i5Cd1W7HergCEW7t9nbxHk78G NCEjboZtgXHZB2qYH68QtkKeS8tvUiFkKfDPlWoaTNDZ06g9AxQNclFi9p8PVk2xum81 fD6OkBix4f65qLqrtR4X4xJpwFW77CP8MRfKeyTKR/zYfDjLsIw++d8IKGBW8jDmSGXp e/qAe9aZvON1HcI/NfalK0wvmDfEsFElvpg6ZX2sKEyZlsDTY0J5Lk40lgngKiWgpb7N yHQEau8lIvn6PHn0hEDWWIvzGvF/RFXFyT2VwGi5kcoSRQTRDi4lYkHeOKSqFJFvXIeH BE1g== 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=YC+PILdDKMPHMPRXjtSVNKuqv2zXYvxMiGpRu5YK0sg=; b=PbkqIdXu2gBJJHE3zn478wYmgTRFkAB32PKtUu+Nj4okKghpysPIyXfL23e2V0G38Z +KEnHAnWAbGpy68/BHb8qus44+pqykgVgZ49oXVAqus1VPckcttGLuv5eFRzzWBArx/i R8fi4mGdca+GFrSC207aGr/u5NHu1LyiMo22SR3AyQW/ZVAB8xywfB3O+7FjXTYdWGWS h2hIs5E4xt7V79LH0Z/XWpRQkkoi0M+VQMIwsZHCMBUhbCtBsv6yAwrbGbhITDgmTbvL 1lEotLTLNdW5bVv9oDLBjyJMSF9IkWh+VT8w//1iE9bfHOkb0S60i+INVBIvm6jZ3Dj8 C+2A== X-Gm-Message-State: AOAM5311bUVcX6vZGc1xLDFLAojQJ5jR7TKpQ4UqzNfTGdBokjDpYKJ3 vGBuoo9vWqGRem5AycrYHCPOjqoLiAY= X-Google-Smtp-Source: ABdhPJzI4BToGUlia1p7xVHRUeDJsRFb9l8uMPgd0h/nR5z6yFqIQ1TIddGCfKVlraeZgBNqvhPSQg== X-Received: by 2002:a05:600c:588:: with SMTP id o8mr5094133wmd.103.1644698099695; Sat, 12 Feb 2022 12:34:59 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id h10sm18179723wrt.57.2022.02.12.12.34.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:34:59 -0800 (PST) Message-Id: In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:47 +0000 Subject: [PATCH v4 06/12] merge-tree: support including merge messages in output Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , 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 --write-tree`, 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, such as: * "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 may be the only notification the user gets since these conflicts are not representable in the contents of the file. Add a --[no-]messages option so that callers can request these messages be included at the end of the output. Include such messages by default when there are conflicts, and omit them by default when the merge is clean. Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 45 +++++++++++++++++++++++++++----- builtin/merge-tree.c | 21 +++++++++++++-- t/t4301-merge-tree-write-tree.sh | 37 ++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 8 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 586733ea564..869c38f8223 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] +'git merge-tree' [--write-tree] [] 'git merge-tree' [--trivial-merge] (deprecated) DESCRIPTION @@ -47,17 +47,47 @@ than the first form even on successful merges (especially if working in large repositories). The remainder of this manual will only discuss the first form. +OPTIONS +------- + +--[no-]messages:: + Write any informational messages such as "Auto-merging " + 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: + + + +Whereas for a conflicted merge, the output is by default of the form: + + +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. +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: + + * "Auto-merging " + * "CONFLICT (rename/delete): renamed...but deleted in..." + * "Failed to merge submodule ()" + * "Warning: cannot merge binary files: " EXIT STATUS ----------- @@ -79,6 +109,9 @@ Thus, it could be 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. + GIT --- Part of the linkgit:git[1] suite diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index af445cb1576..d44e8d087b1 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, @@ -438,18 +439,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] "), + N_("git merge-tree [--write-tree] [] "), N_("git merge-tree [--trivial-merge] "), NULL }; @@ -459,10 +469,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) { @@ -486,8 +499,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 e4f9421c105..25adcf36bdf 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 From patchwork Sat Feb 12 20:34:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744433 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 80E4AC433EF for ; Sat, 12 Feb 2022 20:35:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231664AbiBLUfQ (ORCPT ); Sat, 12 Feb 2022 15:35:16 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231610AbiBLUfG (ORCPT ); Sat, 12 Feb 2022 15:35:06 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0B814606E8 for ; Sat, 12 Feb 2022 12:35:02 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id u1so6910243wrg.11 for ; Sat, 12 Feb 2022 12:35:01 -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=Ap4ZqYlnkgb+ZsEVT3Um4/EicxMnYbd2hGinYTe7EAw=; b=HkwDNONTQHTCmGfa92iYdZA6Dd9zV5cyXxSJBhmQSQTO6Ki9ntGvUu10qa3zmoifec skxJZlxMexnzOdcJxOuAPZPlNIeZunSwVH0c5/mkH60YrkteDBJXLzfzC7rtcoh1TWIw HPcujELjUQ/X2QZ++YTHDn8Wa9nMHN+Tbo5303uSjtYf31jKDX1q0TwGklzPoy2Nj9H5 AAem9Om1HR5c7jBDYQDBOVY+sbleljYMLrwCuHGR2mgIJWhJuDFiLyZYrMqLZRliyu1/ uYqdfC9zGCFlkIzgwXPjQr1rnoDyPskrqObq2HUXEgDdI5yRjWZft8q1epr8ttQ9/rX6 7k9g== 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=Ap4ZqYlnkgb+ZsEVT3Um4/EicxMnYbd2hGinYTe7EAw=; b=JK+1+vCRkHnoFT+x2dTYQZNvoMvCWkAxl9iJp3Akd6CC/ypNNWyHrVMwHKTunABXE5 0TwJ8AvVW3OV04zEWHc2LxXEmREd4PIX+2XgChlAdH40ZTj0mgLjf6EkqsqjdDObHAzL Xa4qXQomT1tt+tu5dn0ToldSpABzqiNryWSqfFJ99mSbL1cc9DGi1yut1tjEI2nI4zS6 0bJHwBlSx5kF/py26xMC8fQUF6c4mfCO5GGZirfd/sf2FY9hq8/poX7/nImK2isljtWv kEpjolx5BfgdhvL3tVSjMCfikDocPARd+sKepVAiGPGbDCGdBbmmBoeuZccHvIGFr4fR mvJQ== X-Gm-Message-State: AOAM532q1ECWVv7Iqs6mrcKt1SwVa4agS4dLD4oo+cwsngxrjEwg5BYj OJ+EmGNZy1CFd1Y+KSWrUcSYv3/NF1g= X-Google-Smtp-Source: ABdhPJzGo34LPIGcNFWwTLQmRkv0T3/90GUJx7VQEq3nxGf2Fixg3a+jxL0Euu1O2TfWxZjTERf64Q== X-Received: by 2002:a05:6000:2c8:: with SMTP id o8mr5917811wry.663.1644698100503; Sat, 12 Feb 2022 12:35:00 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id d14sm9507471wri.93.2022.02.12.12.34.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:35:00 -0800 (PST) Message-Id: In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:48 +0000 Subject: [PATCH v4 07/12] merge-ort: provide a merge_get_conflicted_files() helper function Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren After a merge, this function allows the user to extract the same information that would be printed by `ls-files -u`, which means files with their mode, oid, and stage. Signed-off-by: Elijah Newren --- merge-ort.c | 31 +++++++++++++++++++++++++++++++ merge-ort.h | 21 +++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/merge-ort.c b/merge-ort.c index ebaed98d53a..e1b647b0a40 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4274,6 +4274,37 @@ 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) { + const char *path = e->key; + struct conflict_info *ci = e->value; + int i; + + VERIFY_CI(ci); + + for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) { + struct stage_info *si; + + if (!(ci->filemask & (1ul << i))) + continue; + + si = xmalloc(sizeof(*si)); + si->stage = i+1; + si->mode = ci->stages[i].mode; + oidcpy(&si->oid, &ci->stages[i].oid); + string_list_append(conflicted_files, path)->util = si; + } + } + /* string_list_sort() uses a stable sort, so we're good */ + 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 e5aec45b18f..ddcc39d7270 100644 --- a/merge-ort.h +++ b/merge-ort.h @@ -2,6 +2,7 @@ #define MERGE_ORT_H #include "merge-recursive.h" +#include "hash.h" struct commit; struct tree; @@ -88,6 +89,26 @@ void merge_switch_to_result(struct merge_options *opt, void merge_display_update_messages(struct merge_options *opt, struct merge_result *result); +struct stage_info { + struct object_id oid; + int mode; + int stage; +}; + +/* + * Provide a list of path -> {struct stage_info*} mappings for + * all conflicted files. Note that each path could appear up to three + * times in the list, corresponding to 3 different stage entries. In short, + * this basically provides the info that would be printed by `ls-files -u`. + * + * result should have been populated by a call to + * one of the merge_incore_[non]recursive() functions. + * + * conflicted_files should be empty before calling this function. + */ +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); From patchwork Sat Feb 12 20:34:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744434 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 2175AC433EF for ; Sat, 12 Feb 2022 20:35:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231667AbiBLUfQ (ORCPT ); Sat, 12 Feb 2022 15:35:16 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53500 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231625AbiBLUfK (ORCPT ); Sat, 12 Feb 2022 15:35:10 -0500 Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DD433606E9 for ; Sat, 12 Feb 2022 12:35:02 -0800 (PST) Received: by mail-wm1-x334.google.com with SMTP id x3-20020a05600c21c300b0037c01ad715bso5332263wmj.2 for ; Sat, 12 Feb 2022 12:35:02 -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=CzqPmuiPlwT6a7QL+zHW/5Pt51e4bTxme/XtkOQKvGs=; b=FnnOhvQAm/15PmhSUpli638iZI9n8r+nXZKeG8LDlEjRSRokfvIwGRGyZf0BwtL/nN pavaCEvfDKEa32f7JFtJdUlCIsR/mxeylSBKI9HaZSWvvLMdC2wqn66o6R1mutOEYLbs U/AKf8oRVojGrdquU9EoVDxTwo7Z0AphrpOP2Gf0pZV9QWDqDLPOA33cqVPOVMZ4e4jC H4AFxCOFl34s0pyZFIKrrH/eysWb6pfuOkaUhvA4b07Dz6Tj3clADDQMNH3plMpoKyLH aM6xnCJnkd9icgIqQLt4UOJgEtjFSAPv7JX/49BOs0l691lkEHKnW8CKh5bCZ4zMqLON TtuQ== 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=CzqPmuiPlwT6a7QL+zHW/5Pt51e4bTxme/XtkOQKvGs=; b=CH8n0ksK/YEURbQXEoqlx0S9NwGVZprEHH0B7HHLyFVpb4WzEEwFJ60ZZFJH3wBmk7 0P9CvjilIZaY5RoXT3bYVNaWZwW0hSEKP9GumanyKrr/wrdM+rOp7ImcHn5bu5e82DYb lEaHnD4c8nxQhHr8jCK2vBSN8V8bVR78oi+Uc5NaQtUwGbYuCQ8ltpGPp/ia/1gMyiqL mSLBomKfb2KnhREna4llwWI1koGztfHi9Xvb+ihDn0pyx+a3ZKgjB3NiR8LROfGH0YwT ko/Mc3iFupcClzHuo9adrfR01+gqgk6TWK+qd0GdLljiRrzW2mTWRZIaeqooajspCdHy Zlew== X-Gm-Message-State: AOAM533IJIZ8/1S03pyDAtMlzOq0NKZtTd6jR1VRC/a2zWDVqAjQK2VL EVle5iErSpT6aAkZBLoWcL+8HEDhP7U= X-Google-Smtp-Source: ABdhPJyyTm4zQT9N3DUlo+ProclEGXGLhx56Ptjucz1X2ulKP1wg0qF7bRDQDdtRN0MbifbtsGFTuA== X-Received: by 2002:a7b:c381:: with SMTP id s1mr5352219wmj.114.1644698101331; Sat, 12 Feb 2022 12:35:01 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id h18sm8321704wmq.8.2022.02.12.12.35.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:35:00 -0800 (PST) Message-Id: <6058190d1b16a689ac5e4b4c077b594acf13acea.1644698093.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:49 +0000 Subject: [PATCH v4 08/12] merge-tree: provide a list of which files have conflicts Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , 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 --write-tree` will often want to know which files had conflicts. While they could potentially attempt to parse the CONFLICT notices printed, those messages are not meant to be machine readable. Provide a simpler mechanism of just printing the files (in the same format as `git ls-files` with quoting, but restricted to unmerged files) in the output before the free-form messages. Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 8 ++++++++ builtin/merge-tree.c | 24 ++++++++++++++++++++++-- t/t4301-merge-tree-write-tree.sh | 11 +++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 869c38f8223..9f7eb03c6eb 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -67,6 +67,7 @@ simply one line: Whereas for a conflicted merge, the output is by default of the form: + These are discussed individually below. @@ -78,6 +79,13 @@ 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. +Conflicted file list +~~~~~~~~~~~~~~~~~~~~ + +This is a sequence of lines containing a filename on each line, quoted +as explained for the configuration variable `core.quotePath` (see +linkgit:git-config[1]). + Informational messages ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index d44e8d087b1..cb4169d2271 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -11,6 +11,9 @@ #include "blob.h" #include "exec-cmd.h" #include "merge-blobs.h" +#include "quote.h" + +static int line_termination = '\n'; struct merge_list { struct merge_list *next; @@ -400,7 +403,8 @@ struct merge_tree_options { }; static int real_merge(struct merge_tree_options *o, - const char *branch1, const char *branch2) + const char *branch1, const char *branch2, + const char *prefix) { struct commit *parent1, *parent2; struct commit_list *common; @@ -444,6 +448,22 @@ static int real_merge(struct merge_tree_options *o, o->show_messages = !result.clean; puts(oid_to_hex(&result.tree->object.oid)); + if (!result.clean) { + struct string_list conflicted_files = STRING_LIST_INIT_NODUP; + const char *last = NULL; + int i; + + merge_get_conflicted_files(&result, &conflicted_files); + for (i = 0; i < conflicted_files.nr; i++) { + const char *name = conflicted_files.items[i].string; + if (last && !strcmp(last, name)) + continue; + write_name_quoted_relative( + name, prefix, stdout, line_termination); + last = name; + } + string_list_clear(&conflicted_files, 1); + } if (o->show_messages) { printf("\n"); merge_display_update_messages(&opt, &result); @@ -511,7 +531,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) /* Do the relevant type of merge */ if (o.mode == MODE_REAL) - return real_merge(&o, argv[0], argv[1]); + return real_merge(&o, argv[0], argv[1], prefix); else return trivial_merge(argv[0], argv[1], argv[2]); } diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index 25adcf36bdf..0964c1145e6 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -117,6 +117,8 @@ test_expect_success 'test conflict notices and such' ' # "whatever" has *both* a modify/delete and a file/directory conflict cat <<-EOF >expect && HASH + greeting + whatever~side1 Auto-merging greeting CONFLICT (content): Merge conflict in greeting @@ -140,4 +142,13 @@ do ' done +test_expect_success 'Just the conflicted files without the messages' ' + test_expect_code 1 git merge-tree --write-tree --no-messages side1 side2 >out && + anonymize_hash out >actual && + + test_write_lines HASH greeting whatever~side1 >expect && + + test_cmp expect actual +' + test_done From patchwork Sat Feb 12 20:34:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744435 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 57C18C433EF for ; Sat, 12 Feb 2022 20:35:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231695AbiBLUfU (ORCPT ); Sat, 12 Feb 2022 15:35:20 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53502 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231626AbiBLUfK (ORCPT ); Sat, 12 Feb 2022 15:35:10 -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 A61CD606E3 for ; Sat, 12 Feb 2022 12:35:03 -0800 (PST) Received: by mail-wm1-x332.google.com with SMTP id m126-20020a1ca384000000b0037bb8e379feso9267660wme.5 for ; Sat, 12 Feb 2022 12:35:03 -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=ViCfsVymSZrhniztwUknZo7RBG/QJEPkCxLJ9NoEmlI=; b=G8BoKDJrO3lZSrgRCFmBBZACTXhyNaXjqaEL2w4cvJE/v44EfmfwFsAVsaV1JSq53K JO8DvNsD4NDSBttD/cOIXa7XA37VLGV3WdFNokQ4wPVriJLd07zBfRsmr/NVOLoUnOUq gPtYqxmjWpfUNaAS7lsBJnX/UZ+NxpeRIp24boPmt/rosbGzzk3kYgWpLyQM+kpjA8wz Tpd5HTofaVTJ2oZF7C8xEZWIw3bK+Naac/PnXf2hbIYkMUBbz28PBSXR661vAkw0w7gf wehh/zI9NJSZkB0+3/CKF2MZXoHQjd88exDE9Mvt+wBWLXPGrg86MsQt01GzQjYt69Mg y2dQ== 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=ViCfsVymSZrhniztwUknZo7RBG/QJEPkCxLJ9NoEmlI=; b=DXmf+DNPeMlE+CZRnMOqk4F/oX0krxQKC74+Z7SgmgK0f9MbSeJr11ifB3i433ZAUo YnCG2/+oEN2v/+WzpAFLKt3DkpWLSNJnTG5M1sWxV/HG3gy8pdcy+oguSXJ/8CY7sRK3 dPfmbhC9868QcZYG4z2CWN4zTZXKtzHiR7fF9s8nLddfj4huTjfkxSWTfGk4LfIhqCIh B1vLWQz3hMR06ILUBcMhPI+oDurN84ydiS4k+NWw7iZCyZyWqx09BZVxCEKr9k09XEI3 Yg0ALhHKPLb+3b5qpQWEo/Rc5uRiMa5Y29tHScGpUA5Cfynfn+QgC+yCoqIvXRcPIdsd ZrQQ== X-Gm-Message-State: AOAM53276yRGzVx+wJqFNPrfSG47+cR04nvKFTXDqnIpnizGkpmSDtOr XsjbZCdv8jpYa14nK8vuhUGjVTV+X6s= X-Google-Smtp-Source: ABdhPJwWZFbXSYnb5J9yoKWfbVc8XsVecvj32gluRomJvNw2IkgelG7xjmAhSVR23Ev5VK/p42NA0Q== X-Received: by 2002:a05:600c:1c88:: with SMTP id k8mr5440311wms.60.1644698102123; Sat, 12 Feb 2022 12:35:02 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id t18sm7371893wmi.30.2022.02.12.12.35.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:35:01 -0800 (PST) Message-Id: <435f66ea699ff0ff553350bb5c9d6097940794e9.1644698093.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:50 +0000 Subject: [PATCH v4 09/12] merge-tree: provide easy access to `ls-files -u` style info Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Much like `git merge` updates the index with information of the form (mode, oid, stage, name) provide this output for conflicted files for merge-tree as well. Provide a --name-only option for users to exclude the mode, oid, and stage and only get the list of conflicted filenames. Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 32 ++++++++++++++++++++++++++------ builtin/merge-tree.c | 11 ++++++++++- t/t4301-merge-tree-write-tree.sh | 26 ++++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 9f7eb03c6eb..6502ee0669e 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -50,6 +50,13 @@ discuss the first form. OPTIONS ------- +--name-only:: + In the Conflicted file info section, instead of writing a list + of (mode, oid, stage, path) tuples to output for conflicted + files, just provide a list of filenames with conflicts (and + do not list filenames multiple times if they have multiple + conflicting stages). + --[no-]messages:: Write any informational messages such as "Auto-merging " or CONFLICT notices to the end of stdout. If unspecified, the @@ -67,7 +74,7 @@ simply one line: Whereas for a conflicted merge, the output is by default of the form: - + These are discussed individually below. @@ -79,18 +86,23 @@ 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. -Conflicted file list +Conflicted file info ~~~~~~~~~~~~~~~~~~~~ -This is a sequence of lines containing a filename on each line, quoted -as explained for the configuration variable `core.quotePath` (see -linkgit:git-config[1]). +This is a sequence of lines with the format + + + +The filename will be quoted as explained for the configuration +variable `core.quotePath` (see linkgit:git-config[1]). However, if +the `--name-only` option is passed, the mode, object, and stage will +be omitted. 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: +sections, and then has free-form messages about the merge, such as: * "Auto-merging " * "CONFLICT (rename/delete): renamed...but deleted in..." @@ -120,6 +132,14 @@ Thus, it could be used as a part of a series of steps such as Note that when the exit status is non-zero, NEWTREE in this sequence will contain a lot more output than just a tree. +git-merge-tree was written to provide users with the same information +that they'd have access to if using `git merge`: + * what would be written to the working tree (the ) + * the higher order stages that would be written to the index (the + ) + * any messages that would have been printed to stdout (the ) + GIT --- Part of the linkgit:git[1] suite diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index cb4169d2271..1d4d6637b90 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -400,6 +400,7 @@ enum mode { struct merge_tree_options { int mode; int show_messages; + int name_only; }; static int real_merge(struct merge_tree_options *o, @@ -456,7 +457,11 @@ static int real_merge(struct merge_tree_options *o, merge_get_conflicted_files(&result, &conflicted_files); for (i = 0; i < conflicted_files.nr; i++) { const char *name = conflicted_files.items[i].string; - if (last && !strcmp(last, name)) + struct stage_info *c = conflicted_files.items[i].util; + if (!o->name_only) + printf("%06o %s %d\t", + c->mode, oid_to_hex(&c->oid), c->stage); + else if (last && !strcmp(last, name)) continue; write_name_quoted_relative( name, prefix, stdout, line_termination); @@ -491,6 +496,10 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) N_("do a trivial merge only"), MODE_TRIVIAL), OPT_BOOL(0, "messages", &o.show_messages, N_("also show informational/conflict messages")), + OPT_BOOL_F(0, "name-only", + &o.name_only, + N_("list filenames without modes/oids/stages"), + PARSE_OPT_NONEG), OPT_END() }; diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index 0964c1145e6..4ee85439372 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -65,6 +65,7 @@ test_expect_success 'Content merge and a few conflicts' ' expected_tree=$(cat .git/AUTO_MERGE) && # We will redo the merge, while we are still in a conflicted state! + git ls-files -u >conflicted-file-info && test_when_finished "git reset --hard" && test_expect_code 1 git merge-tree --write-tree side1 side2 >RESULT && @@ -108,7 +109,7 @@ anonymize_hash() { } test_expect_success 'test conflict notices and such' ' - test_expect_code 1 git merge-tree --write-tree side1 side2 >out && + test_expect_code 1 git merge-tree --write-tree --name-only side1 side2 >out && anonymize_hash out >actual && # Expected results: @@ -143,7 +144,7 @@ do done test_expect_success 'Just the conflicted files without the messages' ' - test_expect_code 1 git merge-tree --write-tree --no-messages side1 side2 >out && + test_expect_code 1 git merge-tree --write-tree --no-messages --name-only side1 side2 >out && anonymize_hash out >actual && test_write_lines HASH greeting whatever~side1 >expect && @@ -151,4 +152,25 @@ test_expect_success 'Just the conflicted files without the messages' ' test_cmp expect actual ' +test_expect_success 'Check conflicted oids and modes without messages' ' + test_expect_code 1 git merge-tree --write-tree --no-messages side1 side2 >out && + anonymize_hash out >actual && + + # Compare the basic output format + q_to_tab >expect <<-\EOF && + HASH + 100644 HASH 1Qgreeting + 100644 HASH 2Qgreeting + 100644 HASH 3Qgreeting + 100644 HASH 1Qwhatever~side1 + 100644 HASH 2Qwhatever~side1 + EOF + + test_cmp expect actual && + + # Check the actual hashes against the `ls-files -u` output too + tail -n +2 out | sed -e s/side1/HEAD/ >actual && + test_cmp conflicted-file-info actual +' + test_done From patchwork Sat Feb 12 20:34:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744437 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 4A1FAC433EF for ; Sat, 12 Feb 2022 20:35:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231747AbiBLUfZ (ORCPT ); Sat, 12 Feb 2022 15:35:25 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53514 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231640AbiBLUfL (ORCPT ); Sat, 12 Feb 2022 15:35:11 -0500 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7F70E606E4 for ; Sat, 12 Feb 2022 12:35:04 -0800 (PST) Received: by mail-wr1-x42e.google.com with SMTP id u1so6910349wrg.11 for ; Sat, 12 Feb 2022 12:35:04 -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=1VXzmrUXLaqAzreEkcNWjV5iEmmyfWYCQPv/gZp6R9k=; b=Wo1H4b4PsudjEl5ONVh9nMlQdlzFKCik1rtzi8GX9kFMtAyImI4AIdPDNZRl1y99PF o1hNBeT2NaaGv8oM8ot/FtmybKj0UfyQ0SZfx3DeRBQ2yl3jXGPISblibCIlNM5eGQGZ rS0rUpXOcNxgJXRntI5OdTL0tFkwvQ0owVYLW0Nwx2g19rQC5aKVX6INwWrFrrI1XxTb wQl5h8aOSdPkCxGmrjRaT2QkVVkYtG4unOrDJy/F3KZwXIZede7dJu63GdTWY16HbiNp atyRmbHhV/LjrZ29o2IF9FZkXwW4gDCyXe2iDzD6IYS49s9QJec+6BoBBiUMT7Xg7Grc vERQ== 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=1VXzmrUXLaqAzreEkcNWjV5iEmmyfWYCQPv/gZp6R9k=; b=IdcutzxvS+r8gTBRhBvDSw/sy6KAwvKaUABeZRyZ0EIka3w1+zv+ocdghFAyOSw1qM LAjNrsD5vGGFlnofDxJK1BF+3IGbt1RrEzTG3DIqKr4vrwdnkYFqZg8WtW5HGVsH240d NwY9pWPwzcNW4VKEYX9Xhz7xoyNRYvjJxqPH9PF9ILwSTiM+kliknrjhEj8pYHEPli06 UsmTOs3Bymni3M7IP3k/LvQJc4IdwiR1g59tdbsuAF7tYHXASqXlgZFC3swuZK3+3zcM ga9H4wAi/IM01DAl3/IoK6cJtCxOEFHgYWP+U1CuqKQ7lGn0gXyokezy38YEh/SYhKKi TgQw== X-Gm-Message-State: AOAM5300WsGqedpZF3QyMEhfDV/nh9t4PnayXJPuwJD0BiO5MnDuUdSE qTtqHRKdwuTSKbVTAffgS8TYoFcRqYc= X-Google-Smtp-Source: ABdhPJyMWrsgDR0ZkFMhsYqsZd07kHzKidAEVjikQGlw830ANEY0f7l++R9Ms616n6oeeCK/ondFRg== X-Received: by 2002:adf:f5d2:: with SMTP id k18mr6038024wrp.381.1644698102944; Sat, 12 Feb 2022 12:35:02 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id l26sm7052583wmp.31.2022.02.12.12.35.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:35:02 -0800 (PST) Message-Id: <5f253e298b39a9af3f7f9bd473c63ef9ca34b2df.1644698093.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:51 +0000 Subject: [PATCH v4 10/12] merge-tree: allow `ls-files -u` style info to be NUL terminated Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Much as `git ls-files` has a -z option, let's add one to merge-tree so that the conflict-info section can be NUL terminated (and avoid quoting of unusual filenames). Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 21 +++++++++++++---- builtin/merge-tree.c | 6 +++-- t/t4301-merge-tree-write-tree.sh | 40 ++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 6502ee0669e..ada4595b4fc 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -50,6 +50,12 @@ discuss the first form. OPTIONS ------- +-z:: + Do not quote filenames in the section, + and end each filename with a NUL character rather than + newline. Also begin the messages section with a NUL character + instead of a newline. See OUTPUT below for more information. + --name-only:: In the Conflicted file info section, instead of writing a list of (mode, oid, stage, path) tuples to output for conflicted @@ -84,7 +90,8 @@ 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. +files within this tree may have embedded conflict markers. This section +is always followed by a newline (or NUL if `-z` is passed). Conflicted file info ~~~~~~~~~~~~~~~~~~~~ @@ -96,19 +103,25 @@ This is a sequence of lines with the format The filename will be quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). However, if the `--name-only` option is passed, the mode, object, and stage will -be omitted. +be omitted. If `-z` is passed, the "lines" are terminated by a NUL +character instead of a newline character. Informational messages ~~~~~~~~~~~~~~~~~~~~~~ -This always starts with a blank line to separate it from the previous -sections, and then has free-form messages about the merge, such as: +This always starts with a blank line (or NUL if `-z` is passed) to +separate it from the previous sections, and then has free-form +messages about the merge, such as: * "Auto-merging " * "CONFLICT (rename/delete): renamed...but deleted in..." * "Failed to merge submodule ()" * "Warning: cannot merge binary files: " +Note that these free-form messages will never have a NUL character +in or between them, even if -z is passed. It is simply a large block +of text taking up the remainder of the output. + EXIT STATUS ----------- diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 1d4d6637b90..825255667b1 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -448,7 +448,7 @@ static int real_merge(struct merge_tree_options *o, if (o->show_messages == -1) o->show_messages = !result.clean; - puts(oid_to_hex(&result.tree->object.oid)); + printf("%s%c", oid_to_hex(&result.tree->object.oid), line_termination); if (!result.clean) { struct string_list conflicted_files = STRING_LIST_INIT_NODUP; const char *last = NULL; @@ -470,7 +470,7 @@ static int real_merge(struct merge_tree_options *o, string_list_clear(&conflicted_files, 1); } if (o->show_messages) { - printf("\n"); + putchar(line_termination); merge_display_update_messages(&opt, &result); } merge_finalize(&opt, &result); @@ -496,6 +496,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) N_("do a trivial merge only"), MODE_TRIVIAL), OPT_BOOL(0, "messages", &o.show_messages, N_("also show informational/conflict messages")), + OPT_SET_INT('z', NULL, &line_termination, + N_("separate paths with the NUL character"), '\0'), OPT_BOOL_F(0, "name-only", &o.name_only, N_("list filenames without modes/oids/stages"), diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index 4ee85439372..fe476ed1bcc 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -173,4 +173,44 @@ test_expect_success 'Check conflicted oids and modes without messages' ' test_cmp conflicted-file-info actual ' +test_expect_success 'NUL terminated conflicted file "lines"' ' + git checkout -b tweak1 side1 && + test_write_lines zero 1 2 3 4 5 6 >numbers && + git add numbers && + git mv numbers "Αυτά μου φαίνονται κινέζικα" && + git commit -m "Renamed numbers" && + + test_expect_code 1 git merge-tree --write-tree -z tweak1 side2 >out && + anonymize_hash out >actual && + + # Expected results: + # "greeting" should merge with conflicts + # "whatever" has *both* a modify/delete and a file/directory conflict + # "Αυτά μου φαίνονται κινέζικα" should have a conflict + echo HASH | lf_to_nul >expect && + + q_to_tab <<-EOF | lf_to_nul >>expect && + 100644 HASH 1Qgreeting + 100644 HASH 2Qgreeting + 100644 HASH 3Qgreeting + 100644 HASH 1Qwhatever~tweak1 + 100644 HASH 2Qwhatever~tweak1 + 100644 HASH 1QΑυτά μου φαίνονται κινέζικα + 100644 HASH 2QΑυτά μου φαίνονται κινέζικα + 100644 HASH 3QΑυτά μου φαίνονται κινέζικα + + EOF + + cat <<-EOF >>expect && + Auto-merging greeting + CONFLICT (content): Merge conflict in greeting + CONFLICT (file/directory): directory in the way of whatever from tweak1; moving it to whatever~tweak1 instead. + CONFLICT (modify/delete): whatever~tweak1 deleted in side2 and modified in tweak1. Version tweak1 of whatever~tweak1 left in tree. + Auto-merging Αυτά μου φαίνονται κινέζικα + CONFLICT (content): Merge conflict in Αυτά μου φαίνονται κινέζικα + EOF + + test_cmp expect actual +' + test_done From patchwork Sat Feb 12 20:34:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744438 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 78DA2C433EF for ; Sat, 12 Feb 2022 20:35:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231771AbiBLUf2 (ORCPT ); Sat, 12 Feb 2022 15:35:28 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53508 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231633AbiBLUfL (ORCPT ); Sat, 12 Feb 2022 15:35:11 -0500 Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4BADA606E5 for ; Sat, 12 Feb 2022 12:35:05 -0800 (PST) Received: by mail-wm1-x333.google.com with SMTP id y6-20020a7bc186000000b0037bdc5a531eso4214026wmi.0 for ; Sat, 12 Feb 2022 12:35:05 -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=C0DTlc6ft3YAIhbOz3DN1xGI6xoZ/NwSGvkQSaeTJ8U=; b=PLLJRIaMdk0GQwhFRshTPICn27N38JoXhFhdxfOCK45GMStnshD9rotXjnqlrRl3p1 QSwCkmm3LOcRGgkhUNzJDrso8/hzvJCL47/d7+YXzE+7/MmPTXn5a/3IYS0WtgXqAQbK y9wGBiPTe3q2AL8hNUQK0yyfzvpG9uVa3r22W13Gma5eouVWl89V+4QZOiRiqBi96YoZ 4t0zIr1FURm9NUvEx8q9K5PU1hO2iR45VoIUpdGoj8BjHMj00CVLuadjDZ7bI0D8T+mS BkL/n9b0pcFbvvNuxrt5V2Xmcun82eQldXG21kpPRSd9YrS+ZYvWbwu+gKwfDn7G3kP2 Vk1A== 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=C0DTlc6ft3YAIhbOz3DN1xGI6xoZ/NwSGvkQSaeTJ8U=; b=79F3CEsEf1EUfauzLrqIM2ZJVuxby/iEyleFd5EUBsjKLNSV0bNarGRQDP8wMY/LSH xPJWaHRM75XenKDtMPNQpZMFWPiKscOBDWRY/JaaVVl/A+2agFFAfwCYEcx1g05eOtHT h+YI+OqCiZP7MUXiuNos24hjzIN94Hzx1X30DdHFzDMZPCPLNPRB873b9lhSdDO4Rwbl expIO/WQqbv5qVV0jGFZ7MRCXAF9F01mDqrdf406yI0YGWP+YDfcuxb45QzT972pd4Bf 0cWGKng2wH+v0tScN2uvDzJwCg77hnAuoELPgNVyoYMj5lbnz1Gi3iMu3ErRzngzGVd7 9Vaw== X-Gm-Message-State: AOAM532K/Vyhda1ia32OtcV06cleOtK+GaWEOF6EppQGHo7tJtYZiuu/ 850gtWDpzQbQEjXpXQhpgeEZNCOqaTE= X-Google-Smtp-Source: ABdhPJygkGMYMuoqfxPSimotlwy5AqXeju6MB9DQ7OgQJAX+YdABhPwXLAouRmB4iRKDAKHcDb7XUQ== X-Received: by 2002:a7b:ce90:: with SMTP id q16mr5223813wmj.91.1644698103717; Sat, 12 Feb 2022 12:35:03 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id t187sm7245116wma.22.2022.02.12.12.35.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:35:03 -0800 (PST) Message-Id: In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:52 +0000 Subject: [PATCH v4 11/12] merge-tree: add a --allow-unrelated-histories flag Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Folks may want to merge histories that have no common ancestry; provide a flag with the same name as used by `git merge` to allow this. Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 5 +++++ builtin/merge-tree.c | 7 ++++++- t/t4301-merge-tree-write-tree.sh | 24 +++++++++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index ada4595b4fc..3f566477dcb 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -69,6 +69,11 @@ OPTIONS default is to include these messages if there are merge conflicts, and to omit them otherwise. +--allow-unrelated-histories:: + merge-tree will by default error out if the two branches specified + share no common history. This flag can be given to override that + check and make the merge proceed anyway. + OUTPUT ------ diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 825255667b1..911504ad694 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -399,6 +399,7 @@ enum mode { struct merge_tree_options { int mode; + int allow_unrelated_histories; int show_messages; int name_only; }; @@ -436,7 +437,7 @@ static int real_merge(struct merge_tree_options *o, * merge_incore_recursive in merge-ort.h */ common = get_merge_bases(parent1, parent2); - if (!common) + if (!common && !o->allow_unrelated_histories) die(_("refusing to merge unrelated histories")); for (j = common; j; j = j->next) commit_list_insert(j->item, &merge_bases); @@ -502,6 +503,10 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) &o.name_only, N_("list filenames without modes/oids/stages"), PARSE_OPT_NONEG), + OPT_BOOL_F(0, "allow-unrelated-histories", + &o.allow_unrelated_histories, + N_("allow merging unrelated histories"), + PARSE_OPT_NONEG), OPT_END() }; diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index fe476ed1bcc..5cb546083d7 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -44,7 +44,13 @@ test_expect_success setup ' git checkout side3 && git mv numbers sequence && test_tick && - git commit -m rename-numbers + git commit -m rename-numbers && + + git switch --orphan unrelated && + >something-else && + git add something-else && + test_tick && + git commit -m first-commit ' test_expect_success 'Clean merge' ' @@ -213,4 +219,20 @@ test_expect_success 'NUL terminated conflicted file "lines"' ' test_cmp expect actual ' +test_expect_success 'error out by default for unrelated histories' ' + test_expect_code 128 git merge-tree --write-tree side1 unrelated 2>error && + + grep "refusing to merge unrelated histories" error +' + +test_expect_success 'can override merge of unrelated histories' ' + git merge-tree --write-tree --allow-unrelated-histories side1 unrelated >tree && + TREE=$(cat tree) && + + git rev-parse side1:numbers side1:greeting side1:whatever unrelated:something-else >expect && + git rev-parse $TREE:numbers $TREE:greeting $TREE:whatever $TREE:something-else >actual && + + test_cmp expect actual +' + test_done From patchwork Sat Feb 12 20:34:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12744436 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 E73B4C433EF for ; Sat, 12 Feb 2022 20:35:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231726AbiBLUfX (ORCPT ); Sat, 12 Feb 2022 15:35:23 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53510 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231630AbiBLUfL (ORCPT ); Sat, 12 Feb 2022 15:35:11 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2CB8E606E7 for ; Sat, 12 Feb 2022 12:35:06 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id i14so20614317wrc.10 for ; Sat, 12 Feb 2022 12:35:06 -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=EERqRBajAwrz8tYYP1jAGLo3bEid1AOblU7xP683Vq0=; b=SfrPzW/2yXTlOjALvVQj1kUoQPUgJNKIAuBk0olkgbY5OrDHuJeRSHZQsu5twT0rMY ei5CTmvhhKX2/ekYAVbdhuoFpc89BvwkUvNE9hGjwtqX3kmaVuyvXevI13XLOLTSgM5S YPUC5yBM6XBViUUY0F6DBYbmul9sL4g5tT6uUkIs9iQ5vFQJgGjyRZnd6UKZzLCaHxlF eUWlBdHrexlFZyDR9wGinwFnoCzGLBjQovFcfkFrHCOA1js6R6/ak8+5g8gp+kumPFnU V+08qf5QEwbEq558A0sQymx+mqxcQqNwhlvrcwNhUPLi60LKSI9480C2LzvA7Dgx5Qez aqgg== 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=EERqRBajAwrz8tYYP1jAGLo3bEid1AOblU7xP683Vq0=; b=0cEWb22JvNi2pD57jiPU//msq54TrpEy1LouhQIdJrKbsQ6062+sRrXgjvNQ1lI+Xf rQ8MryVXq5KYnBD5Ineaxkq+/BBoFGmCVFy5aLNbx/0RqJpzrfUxmshoCG+fBvzzj7On ArV/LBjeQH+FeM8CMg397fHZeGhzpYk1sPoNATCHGfgpl1hsBylZo2KuSID4K4gxmoQH BZXaiHJH4jMm0v7J4sKT/1UygDEoCUxq6G9nFqX7tbwIshKwIZHiwVHZLzcjz7JCydmh mxqAHiyqC2GBPU36p81oT5P31hEGpr4KLVzx9nxeXeRGK3c74wi4V/DIJlglkQAeCMIJ z8hA== X-Gm-Message-State: AOAM531Mjvi7Diaazb3JF5lF8FjAFEsH8bKpAElFHxhGG1EL0uz5eWbO bKKuW9qmuZMy+81zgbkhh+yZYJ1+ovU= X-Google-Smtp-Source: ABdhPJz54QU6RMxakr0zu6dSHsjpAjxOIIhYheU5IH5XVI9kzdwyiN/XaoTUbULm5pOhg/t3z0FP8g== X-Received: by 2002:a5d:6111:: with SMTP id v17mr5931059wrt.477.1644698104548; Sat, 12 Feb 2022 12:35:04 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id u7sm16608803wrq.112.2022.02.12.12.35.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 12:35:04 -0800 (PST) Message-Id: In-Reply-To: References: Date: Sat, 12 Feb 2022 20:34:53 +0000 Subject: [PATCH v4 12/12] git-merge-tree.txt: add a section on potentional usage mistakes Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Elijah Newren , Johannes Sixt , Josh Steadmon , Emily Shaffer , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 3f566477dcb..4520bbf020a 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -158,6 +158,52 @@ that they'd have access to if using `git merge`: * any messages that would have been printed to stdout (the ) +MISTAKES TO AVOID +----------------- + +Do NOT look through the resulting toplevel tree to try to find which +files conflict; parse the section instead. Not +only would parsing an entire tree be horrendously slow in large +repositories, there are numerous types of conflicts not representable by +conflict markers (modify/delete, mode conflict, binary file changed on +both sides, file/directory conflicts, various rename conflict +permutations, etc.) + +Do NOT interpret an empty list as a clean merge; +check the exit status. A merge can have conflicts without having +individual files conflict (there are a few types of directory rename +conflicts that fall into this category, and others might also be added +in the future). + +Do NOT attempt to guess or make the user guess the conflict types from +the list. The information there is insufficient +to do so. For example: Rename/rename(1to2) conflicts (both sides +renamed the same file differently) will result in three different file +having higher order stages (but each only has one higher order stage), +with no way (short of the section) to determine +which three files are related. File/directory conflicts also result in +a file with exactly one higher order stage. +Possibly-involved-in-directory-rename conflicts (when +"merge.directoryRenames" is unset or set to "conflicts") also result in +a file with exactly one higher order stage. In all cases, the + section has the necessary info, though it is +not designed to be machine parseable. + +Do NOT assume all filenames listed in the +section had conflicts. Messages can be included for files that have no +conflicts, such as "Auto-merging ". + +AVOID taking the OIDS from the and re-merging +them to present the conflicts to the user. This will lose information. +Instead, look up the version of the file found within the and show that instead. In particular, the latter will +have conflict markers annotated with the original branch/commit being +merged and, if renames were involved, the original filename. While you +could include the original branch/commit in the conflict marker +annotations when re-merging, the original filename is not available from +the and thus you would be losing information that +might help the user resolve the conflict. + GIT --- Part of the linkgit:git[1] suite