From patchwork Sat Jan 22 21:55:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720837 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 AEBE5C433FE for ; Sat, 22 Jan 2022 21:56:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234988AbiAVV4I (ORCPT ); Sat, 22 Jan 2022 16:56:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35696 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234984AbiAVV4H (ORCPT ); Sat, 22 Jan 2022 16:56:07 -0500 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC93FC06173D for ; Sat, 22 Jan 2022 13:56:06 -0800 (PST) Received: by mail-wr1-x434.google.com with SMTP id l25so6470937wrb.13 for ; Sat, 22 Jan 2022 13:56: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=HsHj2KxDWTA9QM6TZSN11NDwemvgrQd3pHbka8fElO8=; b=KcKZ/W6TDraQOypEZBBmPxm6sjzJ1xbo7JK+KH+B9KxPGLGqSgWnRV9AmDGqhJrm/8 0pdv0TFL3rkKuFapz0xeNyWfKXknSYV04c83VYS8sOoC/Nxx8K/SeQwVK4nutZbaGTca iM1CzB83iaimA0Capgk+6pjmF+1PnZ2ycgI/JyDHxUNn++RzNDg5lwROEIc41le5WL1z CI4q3MpuWFHwhfrJbGd+FBAvBEqYUOGR9b1K+yJ6ZL9mBvwWQqLSU5VGPKKy+j3kE09q k66MHDubKoxiFoLWvYVkRDlIaBCrAJ8NC5nvOCcMiMDMqLyvs+DRdnW760RMPWodmmvY g23A== 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=cXE9+T7XDvWYBJOoeVzOUsQg1+N1z1Wyljyrf/ZUBg0DmOWyBFLFfnNXjiww5RTFKl DeIc5GKh+EmifYmfGc6n4eFTy24MUfJkx8i4jKlxcuCQng2Nr/qN/VzPLWzq8jj8XU6O +YN5q6AmkjN3PV9TdSmAiKIV2ktyzLQ1SjsrV+PyzoX7m6tHqBpDQ5n4qKHNOCWhsevM G6FqrgSne1/duNY0yeJSeWfyKJQday7f9EGYNhbq0su5AaJ0UjYjuA7752bQ80603z/V 8NaMnl1Ih3PpKpfrKX45/qim1p74gRzP4nJ4adSfq41Ve89D4s4GfwQI/mLuW5pGRWmR wPbg== X-Gm-Message-State: AOAM5302NbZOsvVicFRkaPTAg0dsCzLA0WngOAWZeOv2F9JQHqqEDe7F 2GnKTQU+x+K2AeSTixGYzKrSX/ocpvg= X-Google-Smtp-Source: ABdhPJzwqYo40cGQlx7seMDj3v0sI9yEXxYAlxvnndeHYVBdCPEzDR0sKj0TgsHmcVfViGx7pZgPVw== X-Received: by 2002:a5d:5046:: with SMTP id h6mr8778056wrt.167.1642888565233; Sat, 22 Jan 2022 13:56:05 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id m64sm3511678wmm.31.2022.01.22.13.56.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:04 -0800 (PST) Message-Id: <4a7cd5542bb2f89b4874e4115542ccee9c4639af.1642888562.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 22 Jan 2022 21:55:51 +0000 Subject: [PATCH 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 , 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 Jan 22 21:55: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: 12720838 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 DA3A6C4332F for ; Sat, 22 Jan 2022 21:56:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235003AbiAVV4M (ORCPT ); Sat, 22 Jan 2022 16:56:12 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35700 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234989AbiAVV4I (ORCPT ); Sat, 22 Jan 2022 16:56:08 -0500 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C90CAC06173B for ; Sat, 22 Jan 2022 13:56:07 -0800 (PST) Received: by mail-wr1-x430.google.com with SMTP id v6so6477793wra.8 for ; Sat, 22 Jan 2022 13:56:07 -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=TUGiTkabHqbZ3JXqPj885ckEpuws8CtmQy/AICerh5snxUhdQKRc5QvobsSb9Y6KkJ iaN9vQq0XESc0L2AGBntdDva9NkW3z9XA+PhWMhjkdC6xbw1eg7vfCyHDB92OKRBoaBg 3N8tcj9wPfdqDHorfEJGipJGiW8B6D4+NZD3yycioMsRoIq8e2ka1PIGwabCwIKu6kJL vn79xsIXxZkySkHwEIZ4luKDVKZgbLpt1C6sq/8bvvAOh+6ulHFN9DW37Ey+npD18rf0 DMPJFeb9cIZuT/uF5vJ1M5K1+WRwWcJT5smiBSqr1xZfJO4Vci3cr9GNqi6wtiF4IohT DoGQ== 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=mWrX2yxPh4xZ/CyVvjzGNBGLfO9PE+deawAyDrOsYdOtGrI4tX7JwG7O4gx4LjyBtS bbSicP/l3XgBGpP4VeM8rL0F9SvF5QRlKwG3KbMC2f5AR5wA0DzSGVxX5LN8RUy/34y9 a3IQJ10JZ3VNxf7x0/Afsrr4mb87jvE4s5YcgtCQtdPqCor1cPPnQX3rslU3p5s+4s4q 1/5M9Zm4OBqMPAzrmwbBernoDEVHkNJgWO+us5Vc6angGgZjpBytwu5jFmuzFiRziSW7 rorU6k1xaHAgNlngFydceHLrvXxtM/3c4yn742rJnQiWS/SqcqHPHCZf9XYWZwU5TCIy vwjQ== X-Gm-Message-State: AOAM530ucTyFXHDV3Z+m4uVUupUDVFad4KCxrdmRNZbeRxRAhBK5mRkm DIpRYhG0oatODQadUH9+jigAPw0anwU= X-Google-Smtp-Source: ABdhPJwxZqXPFCwokaI11TMnnz1ACOrU0WLipqPyJqSUyiGUBsZSMQ2uBYiZ8CtF1u8qaIhzbcBlHg== X-Received: by 2002:adf:f383:: with SMTP id m3mr8542819wro.348.1642888566214; Sat, 22 Jan 2022 13:56:06 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id n8sm9457wmk.18.2022.01.22.13.56.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:05 -0800 (PST) Message-Id: <4780ff6784d426bf0a96859ef9bf9c14e87d5f50.1642888562.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 22 Jan 2022 21:55:52 +0000 Subject: [PATCH 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 , 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 Jan 22 21:55: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: 12720840 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 EC6EAC43219 for ; Sat, 22 Jan 2022 21:56:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235013AbiAVV4N (ORCPT ); Sat, 22 Jan 2022 16:56:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35706 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234996AbiAVV4J (ORCPT ); Sat, 22 Jan 2022 16:56:09 -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 B9E24C06173B for ; Sat, 22 Jan 2022 13:56:08 -0800 (PST) Received: by mail-wm1-x32f.google.com with SMTP id q141-20020a1ca793000000b00347b48dfb53so25215730wme.0 for ; Sat, 22 Jan 2022 13:56:08 -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=TL9IIOJWkeHV3aADLJVy6RlNpZUpHjdBaktqfMu4Usk=; b=qRlBtpbQgqjSHVlP1QXpfZouN4/IrLwq/kjzW2rHZpWw31maWQ/3Hy7eKnz/+41tR7 hDyun9ffxFVnneT3PWztsM/vwGnwI9siHyf7AvurIkoKWC+W1fFs1/C5PxkCpmde3YZm SAp2OKjY9SM8K++OruvyggftLLWUcNF14n0eXltB2xB67OegLZNscuPW3ufsUb5ENPeC 14OpdIGzKlWf98wIJHALoh8FMj6bKvrBvz3UMY8dBSErpGawy79reCYwWsJVmbvgji6e lAlBeLTUptbwV/Mr1tS+7VzFK11QdEs21DGH7FD9KwQIFeOGDkA4btc10OcKR2kSDP1g Kg9w== 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=TL9IIOJWkeHV3aADLJVy6RlNpZUpHjdBaktqfMu4Usk=; b=X81xYuSVL+FueGMVqhxUEHHdSLuh1gC8sZRyosf81CYij9P9ROwHv3dvi8aXAByJeA TIYQqDnl+hmpcptuHZ9k1WVoHO/mnhyR1N1yt9uuk2onxRN5WsZ/bsxoWUBGWNFYCW0E YjnPI18Z/l2m+WsFOxSYe2COZIOJvS8cg2zG80fJ9DCXqSYkNzKpcX4upS1GLyrFJdFE WaJjkTAKakTDD4eHNTX5zpKN4dnNOjqoZmffKr9YbwvFAmOI20CVzD/91C2gW9ptICpX 3YEnixASSIH+B//JjXBptABA7oEGi0K+zM6zqJq2bKYbMGMLl5M3ciGHBPdQtbwQv3bd mI3A== X-Gm-Message-State: AOAM533cRVvS+TIRIWg3EtYN+ONjvz3rcHN0ookt30cCEU+4QbLNWcdQ MRt73TZevogx9ureV/aYlvYrL1D6s4w= X-Google-Smtp-Source: ABdhPJw10IIF4gTyl/zd0uzGGoIDXEwRETdyUYHcjNpPQemZ/wDBjvs0ND26fZFp7yEK3vM0i7gQIw== X-Received: by 2002:a05:600c:3d9b:: with SMTP id bi27mr5855982wmb.36.1642888567017; Sat, 22 Jan 2022 13:56:07 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id p17sm9940544wrf.111.2022.01.22.13.56.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:06 -0800 (PST) Message-Id: <65fdae9ddba7c7065ce27acbf4e80a1a74842aa7.1642888562.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 22 Jan 2022 21:55:53 +0000 Subject: [PATCH 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 , 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 | 67 ++++++++++++++++++++++++++++++++++++++------ git.c | 2 +- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 914ec960b7e..33e47cc1534 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,57 @@ static int trivial_merge(int argc, const char **argv) return 0; } +struct merge_tree_options { + int real; + int trivial; +}; + +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_BOOL(0, "write-tree", &o.real, + N_("do a real merge instead of a trivial merge")), + OPT_BOOL(0, "trivial-merge", &o.trivial, + N_("do a trivial merge only")), + OPT_END() + }; + + /* Check for a request for basic help */ + if (argc == 2 && !strcmp(argv[1], "-h")) + usage_with_options(merge_tree_usage, mt_options); + + /* Parse arguments */ + argc = parse_options(argc, argv, prefix, mt_options, + merge_tree_usage, 0); + if (o.real && o.trivial) + die(_("--write-tree and --trivial-merge are incompatible")); + if (o.real || o.trivial) { + expected_remaining_argc = (o.real ? 2 : 3); + if (argc != expected_remaining_argc) + usage_with_options(merge_tree_usage, mt_options); + } else { + if (argc < 2 || argc > 3) + usage_with_options(merge_tree_usage, mt_options); + o.real = (argc == 2); + } + + /* Do the relevant type of merge */ + if (o.real) + return real_merge(&o, argv[0], argv[1]); + else + return trivial_merge(argv[0], argv[1], argv[2]); } diff --git a/git.c b/git.c index 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 Jan 22 21:55:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720842 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 EF52AC433EF for ; Sat, 22 Jan 2022 21:56:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235015AbiAVV4S (ORCPT ); Sat, 22 Jan 2022 16:56:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35712 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234999AbiAVV4J (ORCPT ); Sat, 22 Jan 2022 16:56:09 -0500 Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 732D6C06173B for ; Sat, 22 Jan 2022 13:56:09 -0800 (PST) Received: by mail-wr1-x433.google.com with SMTP id ba4so6470499wrb.4 for ; Sat, 22 Jan 2022 13:56:09 -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=odFeYR2KbNOxmrzqunzaO4VsyPNeQv/hAkK/HFQjnMY=; b=cQ34xDWUaY7FV4rLm3TksAvmUg0V4aGKDg6j51AAelG/SqqLXyFMOMQeU/2Ym2UcJ6 T3CE3RMCRXNL4bipMb94KMobjto/mOEwe7Chady6U0/nE6fRThGOutSsEF3boTXTmgSE BsCp1jq/Afpwyzc5+/QX/8ghCUyydv6og6LfM8ECnjvmBI16sMn1TpUvkuP4wQMi9Gqw dKp9pPx2N1RqCzJYexPemVj+ycSTodbywi4lDevfbgWvgaJH5laggS8FvbfRu/rGnCI3 lZstiC2l808TypywCZ5zDhet51OjjkeWLNZXtjjPA2JMUrxn2Eolqm+YQ8bXYRjjfUp0 f/Lg== 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=odFeYR2KbNOxmrzqunzaO4VsyPNeQv/hAkK/HFQjnMY=; b=mYyENLCG2HLWfr6rDRPSOhA1M93NOrvtzuv1Lu5tylw3d0LTnT2p4G/NKopp4WwbGH yIE7r97LfenqjvArpPYl4IYcxgzscQ5nAKvnx26g3dv0hm4e04t28sFIT9FM/HeCYUlW wlsMIhRjse2nemvDSP/m6DPegUWQWV8bsQGEiMPcR08N/EOI7p/44DtKgw9WqzQX//UE pc2wvPFpSsNvBZYP4lwL1pEWxhWQUSlGZYoPUkvZkW/cAXA1i+1608Dta9taUeYEWvsd Cpy2BoMESvoFRXd0JVM6q678rE19qmmewEmCe/BRViwn1apsQ5xDf1XfFL7FZX6uBWog M6Qg== X-Gm-Message-State: AOAM533QHlgLMwZ890PKl2xCuvPUxeNkFFlYTLfUW3zqtPoqjC7R7UDk nv0W8w8Mss3DSt+b+3XnpXo4M9I/3H4= X-Google-Smtp-Source: ABdhPJybLZ2mGfvBItmd6ageF7MnCkX6Purr4khAXASUrxHMWZ/7MvtQrfRJ2cvdlvSqlcyIYovvEg== X-Received: by 2002:a5d:6344:: with SMTP id b4mr7243475wrw.607.1642888567848; Sat, 22 Jan 2022 13:56:07 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id z1sm13553967wma.20.2022.01.22.13.56.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:07 -0800 (PST) Message-Id: <05bd17686e1404c81542b6bbf69dcd3decb83c5b.1642888562.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 22 Jan 2022 21:55:54 +0000 Subject: [PATCH 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 , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren This adds the ability to perform real merges rather than just trivial merges (meaning handling three way content merges, recursive ancestor consolidation, renames, proper directory/file conflict handling, and so forth). However, unlike `git merge`, the working tree and index are left alone and no branch is updated. The only output is: - the toplevel resulting tree printed on stdout - exit status of 0 (clean) or 1 (conflicts present) This output is 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. Signed-off-by: Elijah Newren --- Documentation/git-merge-tree.txt | 74 ++++++++++++++++++++++----- builtin/merge-tree.c | 55 +++++++++++++++++++- t/t4301-merge-tree-real.sh | 87 ++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+), 13 deletions(-) create mode 100755 t/t4301-merge-tree-real.sh diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 58731c19422..b900bc1362c 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -3,26 +3,76 @@ 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] 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 full recursive +merge with rename detection. The rest of this manual (other than the +next paragraph) describes the first form in more detail -- including +options, output format, exit status, and usage notes. + +The second form is deprecated; it is kept for backward compatibility +reasons but may be deleted in the future. It will 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. + +USAGE NOTES +----------- + +git-merge-tree was written to be low-level plumbing, similar to +hash-object, mktree, commit-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 + +However, it does not quite fit into the same category of low-level +plumbing commands since the possibility of merge conflicts give it a +much higher chance of the command not succeeding. GIT --- diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 33e47cc1534..0c19639594d 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" @@ -393,7 +396,57 @@ struct merge_tree_options { static int real_merge(struct merge_tree_options *o, const char *branch1, const char *branch2) { - die(_("real merges are not yet implemented")); + struct commit *parent1, *parent2; + struct commit_list *common; + struct commit_list *merge_bases = NULL; + struct commit_list *j; + struct merge_options opt; + struct merge_result result = { 0 }; + + parent1 = get_merge_parent(branch1); + if (!parent1) + help_unknown_ref(branch1, "merge", + _("not something we can merge")); + + parent2 = get_merge_parent(branch2); + if (!parent2) + help_unknown_ref(branch2, "merge", + _("not something we can merge")); + + init_merge_options(&opt, the_repository); + /* + * TODO: Support subtree and other -X options? + if (use_strategies_nr == 1 && + !strcmp(use_strategies[0]->name, "subtree")) + opt.subtree_shift = ""; + for (x = 0; x < xopts_nr; x++) + if (parse_merge_opt(&opt, xopts[x])) + die(_("Unknown strategy option: -X%s"), xopts[x]); + */ + + opt.show_rename_progress = 0; + + opt.branch1 = merge_remote_util(parent1)->name; /* or just branch1? */ + opt.branch2 = merge_remote_util(parent2)->name; /* or just branch2? */ + + /* + * Get the merge bases, in reverse order; see comment above + * merge_incore_recursive in merge-ort.h + */ + common = get_merge_bases(parent1, parent2); + 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); + printf("%s\n", oid_to_hex(&result.tree->object.oid)); + if (result.clean < 0) + die(_("failure to merge")); + else if (!result.clean) + printf(_("Conflicts!\n")); + 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-real.sh b/t/t4301-merge-tree-real.sh new file mode 100755 index 00000000000..e03688515c5 --- /dev/null +++ b/t/t4301-merge-tree-real.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +test_description='git merge-tree --write-tree' + +. ./test-lib.sh + +# This test is ort-specific +test "${GIT_TEST_MERGE_ALGORITHM:-ort}" = ort || { + skip_all="GIT_TEST_MERGE_ALGORITHM != ort" + test_done +} + +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 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 +' + +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 side3 2>expect && + + grep "^usage: git merge-tree" expect +' + +test_done From patchwork Sat Jan 22 21:55:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720841 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 0DA02C433F5 for ; Sat, 22 Jan 2022 21:56:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235052AbiAVV4U (ORCPT ); Sat, 22 Jan 2022 16:56:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35720 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235000AbiAVV4K (ORCPT ); Sat, 22 Jan 2022 16:56: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 4D248C06173B for ; Sat, 22 Jan 2022 13:56:10 -0800 (PST) Received: by mail-wm1-x332.google.com with SMTP id r132-20020a1c448a000000b0034e043aaac7so7693907wma.5 for ; Sat, 22 Jan 2022 13:56:10 -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=tCi4MTvYjABxVi5b+7LScRWbnauYgvfL3kKR3ndeo4s=; b=eVgU92zL62b9D1Q7pOpic/eRHr6SmVjnqS1Z7EeeV+e4KnTYErvBaZ7/ifpufaQ6l8 GJbFlxF8tpbSQc2E0TwSO9cXTuMfTlABy1OF0/u5XUsfdbU5ncBRTFK4U9bxOZQ0yq4+ dBxaTh27Nsft7SvvoVx9qQ2Czftv+HjnM0R6dde0XD+dNtc8fb/tAikyhm4/LMwhOu4f AAVTc3O3CPQS4VYJutuG2iFgZTLC+tTXquImaDJBCxvVQPv7oYEbJUMUDvgW6fBeHHcW 7Eu39wnnfoLutsWdcbhvXoemZkoE4YoPF6U/gkM/N3b5kG4K5vO5ymXxlhrCnp4pxcNS +pog== 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=tCi4MTvYjABxVi5b+7LScRWbnauYgvfL3kKR3ndeo4s=; b=0hcb29DhFIkGky2uMLUpk/7QWw1mG4qFUGD+Z4FHupIgaQY43Lig6EfPOnfAWboRmT buXwILaFzoI0U491lJU9aPeyMPh/MJ0kMsqXxRf/38CAEIfNlst2hN00XUMm5lApc76Z IHKCtKvbu6wtoaR8Cov9yP2kzrhxeqgXsWhL08bu0H8spSDgFm3umMAwhauCLYySoU+7 E5Os9iLFHxCHRaW0Li/phqayu9KuqhIcbz8IGC4HgTaQxXP/unL8EK44ZIsroHVJKTue L7KiagwsfAtMQ/bwa1Q70NpUZbEerIX+EJhPyPI7792OUsf0c9KVM8Kdi+ehiaZmDvFl ujbw== X-Gm-Message-State: AOAM532ho82dSqcN9snkR2W4FQSnwqJVPCUceaG1ovfpuXYrPWR4AuIB EPetLhfdh5jfaTD8rYYX2JEQFDVmc8A= X-Google-Smtp-Source: ABdhPJxtJnPlnBZlJ4ZYu5+6q2E2DdNwzS2MtOX9WUBXLY1NecXVwYr7xMZ3mHXpxnGro9hfgQD8PQ== X-Received: by 2002:a1c:4e1a:: with SMTP id g26mr5649023wmh.146.1642888568754; Sat, 22 Jan 2022 13:56:08 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id b15sm9453216wrs.93.2022.01.22.13.56.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:08 -0800 (PST) Message-Id: <095aa266c2bfdda47ed722fbc5a0d9c94132fbf1.1642888562.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 22 Jan 2022 21:55:55 +0000 Subject: [PATCH 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 , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren No functional changes included in this patch; it's just a preparatory step to allow the printed messages to be handled differently by other callers, such as in `git merge-tree --write-tree`. Signed-off-by: Elijah Newren --- merge-ort.c | 77 ++++++++++++++++++++++++++++------------------------- merge-ort.h | 8 ++++++ 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 9bf15a01db8..f9e35b0f96b 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, @@ -4273,42 +4312,8 @@ void merge_switch_to_result(struct merge_options *opt, trace2_region_leave("merge", "write_auto_merge", opt->repo); } - if (display_update_msgs) { - struct merge_options_internal *opti = result->priv; - struct hashmap_iter iter; - struct strmap_entry *e; - struct string_list olist = STRING_LIST_INIT_NODUP; - int i; - - 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 Jan 22 21:55:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720844 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 2E624C4332F for ; Sat, 22 Jan 2022 21:56:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235062AbiAVV4W (ORCPT ); Sat, 22 Jan 2022 16:56:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35724 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235001AbiAVV4L (ORCPT ); Sat, 22 Jan 2022 16:56:11 -0500 Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1D3C7C06173B for ; Sat, 22 Jan 2022 13:56:11 -0800 (PST) Received: by mail-wm1-x32d.google.com with SMTP id o1-20020a1c4d01000000b0034d95625e1fso17123541wmh.4 for ; Sat, 22 Jan 2022 13:56:11 -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=bDgafxTbt4Tmcf/t0AffhGAhMG7KX/dE6Xhg2Tw+H+c=; b=XpP7B9BJlxh7Vovzhn+T16jLMYVXoo2+Ro//x1Fr9LooVjwRJhoQtgq+em/q6vSQT2 m7MHMh44eKaJUSE3gLQrfe4+cuzheaDwCGzAf4EdDMiRoaAvZE2813XMjgcI1N274QBc Os2tllqVGVkfJmoJXAOBIUeDafU9bOl/8No91dp0RzLduVHvbZ18Y3lA3eDK0L0XlaQr R0ceO8oc95LuAtemccKFAidmUD4o8AVhKLwhwC529YL/mhTyfuVqm4X8lRn+jnjrw0RX lRkNKWXdpdnkensrR7f2JYANXnKwMBIBiaVtDCD4+Y4i67zyMXdzptnFZqxN9NSJsQ0/ reJg== 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=bDgafxTbt4Tmcf/t0AffhGAhMG7KX/dE6Xhg2Tw+H+c=; b=m7BjYuUZyUS3gNZDoFZAVK885km30RLrW1NwyRpUEP+uWI+KE78jkqL/XNQGgUjTVw +BxJs+Yk0iprI9Xys6CykRARoB43WCZheGs/HBF5l7hJpPRSbPuAh+wimRnxvAnbUM+n vDnErb3C07d+Tzc8msr2vLNx+qwkel26TGTWBqdVek5WuxD6k6G7HpV4RxMrYi79ceuy 9VZ6o7bw5Kub/BVLxXSNkqAxYjwty4tORh7JjQnEeoF27NLCWBjwnz0ha4IL53j6wwxb AcZK4BNzd8pcr/XJuGNrDXNf/WC28ycPB4U5zTGy5LtSG/tR72+P5v/aP8MgIvOVpw2N Y4nA== X-Gm-Message-State: AOAM531opPN6vEmXK0MBmRI6QYhbi0fYMzbJowBZSJNwD5EWkfsik0VS 3X4QKFGmSu4jY6jcTHWu+C6G2HMg8Vw= X-Google-Smtp-Source: ABdhPJzeVsBtszwGwSq2TLtY55yCOI6GwAx1jzInd9uvZzkbcj50fM5mHhl+jozxWOKZF5wBEp8z2Q== X-Received: by 2002:a7b:ce08:: with SMTP id m8mr5878327wmc.127.1642888569553; Sat, 22 Jan 2022 13:56:09 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id b12sm10094661wrj.23.2022.01.22.13.56.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:09 -0800 (PST) Message-Id: In-Reply-To: References: Date: Sat, 22 Jan 2022 21:55:56 +0000 Subject: [PATCH 06/12] merge-ort: allow update messages to be written to different file stream Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Christian Couder , Taylor Blau , Johannes Altmanninger , Ramsay Jones , Johannes Schindelin , Christian Couder , =?utf-8?b?UmVuw6k=?= Scharfe , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren This modifies the new display_update_messages() function to allow printing to somewhere other than stdout. Signed-off-by: Elijah Newren --- merge-ort.c | 7 ++++--- merge-ort.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index f9e35b0f96b..b78dde55ad9 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4236,7 +4236,8 @@ static int record_conflicted_index_entries(struct merge_options *opt) } void merge_display_update_messages(struct merge_options *opt, - struct merge_result *result) + struct merge_result *result, + FILE *stream) { struct merge_options_internal *opti = result->priv; struct hashmap_iter iter; @@ -4263,7 +4264,7 @@ void merge_display_update_messages(struct merge_options *opt, for (i = 0; i < olist.nr; ++i) { struct strbuf *sb = olist.items[i].util; - printf("%s", sb->buf); + fprintf(stream, "%s", sb->buf); } string_list_clear(&olist, 0); @@ -4313,7 +4314,7 @@ void merge_switch_to_result(struct merge_options *opt, } if (display_update_msgs) - merge_display_update_messages(opt, result); + merge_display_update_messages(opt, result, stdout); merge_finalize(opt, result); } diff --git a/merge-ort.h b/merge-ort.h index e5aec45b18f..d643b47cb7c 100644 --- a/merge-ort.h +++ b/merge-ort.h @@ -86,7 +86,8 @@ void merge_switch_to_result(struct merge_options *opt, * so only call this when bypassing merge_switch_to_result(). */ void merge_display_update_messages(struct merge_options *opt, - struct merge_result *result); + struct merge_result *result, + FILE *stream); /* Do needed cleanup when not calling merge_switch_to_result() */ void merge_finalize(struct merge_options *opt, From patchwork Sat Jan 22 21:55:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720843 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 3F895C433FE for ; Sat, 22 Jan 2022 21:56:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235089AbiAVV4X (ORCPT ); Sat, 22 Jan 2022 16:56:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35734 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235007AbiAVV4M (ORCPT ); Sat, 22 Jan 2022 16:56:12 -0500 Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 35361C06173D for ; Sat, 22 Jan 2022 13:56:12 -0800 (PST) Received: by mail-wm1-x32d.google.com with SMTP id az27-20020a05600c601b00b0034d2956eb04so25028373wmb.5 for ; Sat, 22 Jan 2022 13:56:12 -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=QB6vdjI5ZUXzQx8gj3AD9+ysUH3Y1x0L49EQ6xQ/MqY=; b=LrcyVMjKhgEg+XRDpzaY76ymPPW92/5UYHgtLamAAIt93a3NwyyZxhOtj6VwipEvIz Hv0XMI+MfhKZGiyEKzI7wlaf4+wDqWa9sLPtMKG94inZv/cLanI5YbeXR5PrV8xpzvlQ qOdsnmmTXXFGLMBSH7Zx+rVVmkcpGd+QUElvxFJwH3fvKzctzshWzvpdFES3Y1uiwXNH DCHoJKxMEee9MccLgTd0aveZj3I0OhjJbyT/wSOsHLKtALji7agDhuxDI59HXmkuuret Kr0E7PgUEA2yRvU4r93nfJ0xiiokTT1sj26m0KAgR6sluJyCGiw+xtASmwquLnlGOFiA V3qw== 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=QB6vdjI5ZUXzQx8gj3AD9+ysUH3Y1x0L49EQ6xQ/MqY=; b=MucT8J0qNp3iulSTR2wiSBn4/RCVq7gBRON7uenwbB23j9SHDm49Mz8rpZBNpKvFqN DTPIPbx8I+5V2Qk/An4Dq/lYTnl5d9iIzGcuS+I+qVWxxXZG5rz3DY657PGIg3M5oMQD 9WtlC430oDfml65iIrHFC6eNmAWTFHf5jlCeaYw50OdA2ltaZ5aZbcH+5tixjj9RiLtb e+U7wAM7sMH5j86qEhSoRXEe7qSmvIuggrG29PG1tgTTHqULd1K/WAh110NlMdOdq51N PE9zbrvXVHh1zZ5OorPmIJgpiz3qMBhRgh+bOsLYeuxodkK4sd/WGNoVXrKm4vryTXZ5 3rng== X-Gm-Message-State: AOAM530TTAwn4xj8neeCUChW7bfVZiWY6OocFJO86+Uh1wEVLxl1PV5P X3TkPa8blVV8iwBPvNgKhkubNSu8J2o= X-Google-Smtp-Source: ABdhPJwFIX23ul+0qTtzaGlIv8IJnRrf8TTjC6OA00BplKrJ3TzcTooTqXXKdVkXX+whSCTwaUfCxA== X-Received: by 2002:a05:600c:1f10:: with SMTP id bd16mr5792353wmb.111.1642888570523; Sat, 22 Jan 2022 13:56:10 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 11sm2126736wmx.5.2022.01.22.13.56.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:09 -0800 (PST) Message-Id: <2f296aeeefbf8340cfb8b7fa4fef5ad49c8b4aa1.1642888562.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 22 Jan 2022 21:55:57 +0000 Subject: [PATCH 07/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 , 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, ("Auto-merging ", "CONFLICT (content): ...", "CONFLICT (file/directory)", etc.) In fact, when non-content conflicts occur (such as file/directory, modify/delete, add/add with differing modes, rename/rename (1to2), etc.), these informational messages are often the only notification since these conflicts are not representable in the contents of the file. Add a --[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 | 24 +++++++++++++---- t/t4301-merge-tree-real.sh | 21 +++++++++++++++ 3 files changed, 78 insertions(+), 12 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index b900bc1362c..fd7a867de60 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] DESCRIPTION @@ -38,17 +38,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. + +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: -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. + * "Auto-merging " + * "CONFLICT (rename/delete): renamed...but deleted in..." + * "Failed to merge submodule ()" + * "Warning: cannot merge binary files: " EXIT STATUS ----------- @@ -72,7 +102,8 @@ be used as a part of a series of steps such as However, it does not quite fit into the same category of low-level plumbing commands since the possibility of merge conflicts give it a -much higher chance of the command not succeeding. +much higher chance of the command not succeeding (and NEWTREE containing +a bunch of stuff other than just a toplevel tree). GIT --- diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 0c19639594d..560640ad911 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -391,6 +391,7 @@ static int trivial_merge(const char *base, struct merge_tree_options { int real; int trivial; + int show_messages; }; static int real_merge(struct merge_tree_options *o, @@ -440,22 +441,30 @@ static int real_merge(struct merge_tree_options *o, commit_list_insert(j->item, &merge_bases); merge_incore_recursive(&opt, merge_bases, parent1, parent2, &result); - printf("%s\n", oid_to_hex(&result.tree->object.oid)); + if (result.clean < 0) die(_("failure to merge")); - else if (!result.clean) - printf(_("Conflicts!\n")); + + if (o->show_messages == -1) + o->show_messages = !result.clean; + + printf("%s\n", oid_to_hex(&result.tree->object.oid)); + if (o->show_messages) { + printf("\n"); + merge_display_update_messages(&opt, &result, stdout); + } 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 }; @@ -464,6 +473,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) N_("do a real merge instead of a trivial merge")), OPT_BOOL(0, "trivial-merge", &o.trivial, N_("do a trivial merge only")), + OPT_BOOL(0, "messages", &o.show_messages, + N_("also show informational/conflict messages")), OPT_END() }; @@ -472,10 +483,13 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) usage_with_options(merge_tree_usage, mt_options); /* Parse arguments */ + original_argc = argc; argc = parse_options(argc, argv, prefix, mt_options, merge_tree_usage, 0); if (o.real && o.trivial) die(_("--write-tree and --trivial-merge are incompatible")); + if (!o.real && original_argc < argc) + die(_("--write-tree must be specified if any other options are")); if (o.real || o.trivial) { expected_remaining_argc = (o.real ? 2 : 3); if (argc != expected_remaining_argc) diff --git a/t/t4301-merge-tree-real.sh b/t/t4301-merge-tree-real.sh index e03688515c5..c34f8e6c1ed 100755 --- a/t/t4301-merge-tree-real.sh +++ b/t/t4301-merge-tree-real.sh @@ -84,4 +84,25 @@ test_expect_success 'Barf on too many arguments' ' grep "^usage: git merge-tree" expect ' +test_expect_success 'test conflict notices and such' ' + test_expect_code 1 git merge-tree --write-tree side1 side2 >out && + sed -e "s/[0-9a-f]\{40,\}/HASH/g" 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 +' + test_done From patchwork Sat Jan 22 21:55:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720846 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 875FEC433F5 for ; Sat, 22 Jan 2022 21:56:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235006AbiAVV40 (ORCPT ); Sat, 22 Jan 2022 16:56:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35740 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235014AbiAVV4N (ORCPT ); Sat, 22 Jan 2022 16:56:13 -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 11DF2C06173B for ; Sat, 22 Jan 2022 13:56:13 -0800 (PST) Received: by mail-wm1-x32e.google.com with SMTP id az27-20020a05600c601b00b0034d2956eb04so25028382wmb.5 for ; Sat, 22 Jan 2022 13:56:13 -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=miSP13fT2WRghhWNZAPyivn3ZVoYRAB2zZZ4g5L4sZA=; b=XP330X3Fl14M8pNhLvuRPVdxbsQPFy1PwxA/Mw1OiwPexCnJprriTHSm5vHeUks4jo MYMnrJ5IVRxqwd/tG1dOqNk3TrhIvAGheoybDQZBAzvs2UwpNqAILT5nm2z9ZocWRoCA C6LnY6DjKEy9+hm/fiLJ4QgK6Z9O8x+RZJDnIjUgx1Ta9TLJUyMlp/UQi0hIzbV2sTM8 k3CtWdZI39ccbHtJ4XACWQ9vndOusCTRrEanc3WJVaeT0bD+6+HeV+b7ionaVtF1phKm IDOSmk5pwX5pY7YWXiEemmyTb8+CEQb5XijEjeCrhILUPMaQpvLp3qd+CWJo4WR1xObg Vpqg== 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=miSP13fT2WRghhWNZAPyivn3ZVoYRAB2zZZ4g5L4sZA=; b=MwS6sWmSPIHrMjZKZ1SaBY1lVnF7U1T5B1FADadpcEGQW9OJbgBEN3xWh0Jsnf49qw 1gzLKadNmlGlf0zuAbE1KeLHZ65etk9PDGnaU/Hbe/p1Zi2JxjcJpc3Llz6LH9DLWyhf am2JNW6JF7Fa5EYj/L06mckaVJwD6x6vq9rU8dqicRq9/uIXFbMT36PITX1z5ueQFstO p0lMhTkXoSDezUy5v9VnIDNXGyh1sLLZL31dgO4twYR7ApWx/S2bLNMYMfECUQUWxWIM AnrdebFtfYHnL8XpD1gRg66l4vvPtffL4/es81v+davCROkwtPGblhXkonGFGH3Lsmdu e7iw== X-Gm-Message-State: AOAM531LNmK0SFaibE6bi95qFQpmavC2Tsp1p92gET5w+uw6jZpdMikC +qhVfKOqJH4yZLkFUCc8Th8pGvGAZAE= X-Google-Smtp-Source: ABdhPJzDYA2E64I98NNsPu0vLMOzQkjfIKBfSaqEUjLFFC6EESKFhm0lIaWcpCSV6YfYTuJd/2LRMQ== X-Received: by 2002:a1c:e914:: with SMTP id q20mr5817632wmc.70.1642888571465; Sat, 22 Jan 2022 13:56:11 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id u14sm9764100wrm.58.2022.01.22.13.56.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:11 -0800 (PST) Message-Id: <35e0ed9271a0229fe2acd2385a7e4171d4dfe077.1642888562.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 22 Jan 2022 21:55:58 +0000 Subject: [PATCH 08/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 , 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` -- conflicted 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 b78dde55ad9..5e7cea6cc8f 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4275,6 +4275,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 d643b47cb7c..e635a294ea8 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; @@ -89,6 +90,26 @@ void merge_display_update_messages(struct merge_options *opt, struct merge_result *result, FILE *stream); +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 Jan 22 21:55:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720849 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 1C6C3C433EF for ; Sat, 22 Jan 2022 21:56:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235099AbiAVV4Y (ORCPT ); Sat, 22 Jan 2022 16:56:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35742 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235016AbiAVV4O (ORCPT ); Sat, 22 Jan 2022 16:56:14 -0500 Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9806C06173D for ; Sat, 22 Jan 2022 13:56:13 -0800 (PST) Received: by mail-wr1-x42f.google.com with SMTP id v13so6470459wrv.10 for ; Sat, 22 Jan 2022 13:56:13 -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=jD5SnTjqP16AUCWi/T/p1cOzzpGdUGc4ygDUm32+4Es=; b=arfWZXPBR+/HThz2dIG59fVVsHtSJRxEfq/NIxM4rzCob3FJsumk9KhFX63TMQA50U el1+bggalErMPXjbfmp78JEK9TPoybiSgYBNdEoyC6putQbufQAFhaRKzQbRuTAMOWYZ WAsJEyg3ODeZuWVoBV6jmFXlMLMC1U8s3+idIZyIMav1MPaCt+pWdFABDHOrxeaXd64f r1RmQdtU1+sRYwz+rrFiChNSqftyogJwXj2OeQDY18AV+qke3KryKeBFq9tR07dwApa9 1Ug9+AGEUx0jdPRntwh6OZZeklM2PRIN9sZupHyo8Ie2bBVTurO0hHr5wwacWQuY065+ Oc1g== 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=jD5SnTjqP16AUCWi/T/p1cOzzpGdUGc4ygDUm32+4Es=; b=CduJgkWRGKIfn+4BBzB55tBqiaKEmMcE7ZArLvgiz0ogSfp3vCt9+uAm4UVG6qBIGy PI2OF411o1Ef/28D4yiRLyppDMAI25Ai2VvJts4OXjzLf9sI1o2q2vqp3rZRWtupCU70 8OWZyNrDjrXPoJRwHQQ97aaUWi5FsrHJ8l/Xma+GfDLfn60M1QJL0ClF9ylM6T1/whbZ +zZe3Xo0wAWf+697bHkVEgjDM1ozV2Iuv85qMQo332lbymCZkZiFptTA0UA9OjpL7wRy mirILwKdv5yo0P2GSH3cN+lLhz6Y1DNobb9rRRLtWoiMZ6yxLE7R6mcaqKiYpg9/C8JP ei2g== X-Gm-Message-State: AOAM5333TbdUkGI2FGdR7zxgw27MB3TkXLTQaCqCeC3JF9Hy7q5fBrHW P2vx7TZwYYHBla3qraLpRindgWr34zc= X-Google-Smtp-Source: ABdhPJxQRY0oTXDLXd/N1z/riQ9yPICVMOGiGyUbqe4r4cMH38rk+FmK0ueDbDjXmVaY3yd7MEENWg== X-Received: by 2002:a5d:58fc:: with SMTP id f28mr8624039wrd.665.1642888572348; Sat, 22 Jan 2022 13:56:12 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id k12sm3240208wrd.110.2022.01.22.13.56.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:11 -0800 (PST) Message-Id: In-Reply-To: References: Date: Sat, 22 Jan 2022 21:55:59 +0000 Subject: [PATCH 09/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 , 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-real.sh | 11 +++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index fd7a867de60..041a4ac2785 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -58,6 +58,7 @@ simply one line: Whereas for a conflicted merge, the output is by default of the form: + These are discussed individually below. @@ -69,6 +70,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 560640ad911..d8eeeb3f306 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; @@ -395,7 +398,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; @@ -449,6 +453,22 @@ static int real_merge(struct merge_tree_options *o, o->show_messages = !result.clean; printf("%s\n", 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, stdout); @@ -502,7 +522,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) /* Do the relevant type of merge */ if (o.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-real.sh b/t/t4301-merge-tree-real.sh index c34f8e6c1ed..43c9950dedb 100755 --- a/t/t4301-merge-tree-real.sh +++ b/t/t4301-merge-tree-real.sh @@ -94,6 +94,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 @@ -105,4 +107,13 @@ test_expect_success 'test conflict notices and such' ' test_cmp expect actual ' +test_expect_success 'Just the conflicted files without the messages' ' + test_expect_code 1 git merge-tree --write-tree --no-messages side1 side2 >out && + sed -e "s/[0-9a-f]\{40,\}/HASH/g" out >actual && + + test_write_lines HASH greeting whatever~side1 >expect && + + test_cmp expect actual +' + test_done From patchwork Sat Jan 22 21:56:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720845 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 5249BC43217 for ; Sat, 22 Jan 2022 21:56:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235107AbiAVV4Z (ORCPT ); Sat, 22 Jan 2022 16:56:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35748 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235018AbiAVV4P (ORCPT ); Sat, 22 Jan 2022 16:56:15 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AE259C061401 for ; Sat, 22 Jan 2022 13:56:14 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id u15so6462392wrt.3 for ; Sat, 22 Jan 2022 13:56:14 -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=7glMBzES/z+oiSwYCi+tcPrJ6YC39GY3cGhTRt9XDzI=; b=j+yCCdSSNSmOTcWFvU70lYCBbJtIejtiLc76uUwYIZzBeFvWnq2MlDVPCNmXahtVqj jAMAMk7wc2pAuggdiuSIGj8+MMU+TEZ2OcAP7op/JcAJv8ODx20jDaEruQlDobjViUEi XbrCzejbnTK5XRnNlRB2NVM7kWu6/BawoEmtXHXE0rQpEStnvCQ5S3dcjXOWWdElRPhn DUF2ke+05F0PzXjS7oR0JhDj1NPIQQZ+b5O9GJfzWrwAzS4Cyoj3+XerwJN/mnIz3jJw 8zZGIZl4gCYyCU5s6VsfGH/zBxEIruWxbI19EZ/VFr3HASkkl1MtQ6rgjw2Claj8oOCG XYeQ== 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=7glMBzES/z+oiSwYCi+tcPrJ6YC39GY3cGhTRt9XDzI=; b=p/inWe04+opKIiZodL55QASudtQAwbOUtYPYqSkXOk/CXtRHNyG0JMQOT1jGm4/XFV zl3l5LmdJVI3RR99kma/18YHSvdFDPEvXDRCrm7DB8CDgz0s6onUGGJXLKzFr7YyaxTs GaxtoeA8zdWHySrAtn2K4KlMQKhY/ZoXwO8eaiS31cmvIuHZq+FV62pmCGufgK2RPUkA UPr4WnXsRHNk+eLBi8Fh/Md+AbihenRc42z4K/V36sTMwreZgTXvf7zsprHK9Bg0FhDW b6OntmlLpxAUH6Xhzd8qeYCkLqPEs3vkqLKF4WzbjP59085wqXRGKEXw1aTkxAsDdP94 f8Zg== X-Gm-Message-State: AOAM531DEyhzChT7wbPH2P+ZU2YB3pcQ4nWlQEuazJ05/tpwR907YQnE psSuq41iHAh6HxpDZ/ZlPF3VxNe5Q/A= X-Google-Smtp-Source: ABdhPJyGuTjpbIRdTGWkaNRl/PAjSKqu/S11F4r4FAjxgGf7kT9ngvbMb4GryIki1ZMVmZWHZIChQg== X-Received: by 2002:a5d:4889:: with SMTP id g9mr8538766wrq.574.1642888573113; Sat, 22 Jan 2022 13:56:13 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id j15sm2700232wmq.26.2022.01.22.13.56.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:12 -0800 (PST) Message-Id: <050add3e4986c457cd467b36eb4fd1f215b7406d.1642888562.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 22 Jan 2022 21:56:00 +0000 Subject: [PATCH 10/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 , 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 an --exclude-oids-and-modes 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 | 30 ++++++++++++++++++++++++------ builtin/merge-tree.c | 11 ++++++++++- t/t4301-merge-tree-real.sh | 26 ++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 041a4ac2785..beb08269a70 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -41,6 +41,11 @@ discuss the first form. OPTIONS ------- +--exclude-oids-and-modes:: + Instead of writing a list of (mode, oid, stage, path) tuples + to output for conflicted files, just provide a list of + filenames with conflicts. + --[no-]messages:: Write any informational messages such as "Auto-merging " or CONFLICT notices to the end of stdout. If unspecified, the @@ -58,7 +63,7 @@ simply one line: Whereas for a conflicted merge, the output is by default of the form: - + These are discussed individually below. @@ -70,18 +75,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 `--exclude-oids-and-modes` 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..." @@ -113,6 +123,14 @@ plumbing commands since the possibility of merge conflicts give it a much higher chance of the command not succeeding (and NEWTREE containing a bunch of stuff other than just a toplevel 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 d8eeeb3f306..7aa7f9fd54a 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -395,6 +395,7 @@ struct merge_tree_options { int real; int trivial; int show_messages; + int exclude_oids_and_modes; }; static int real_merge(struct merge_tree_options *o, @@ -461,7 +462,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->exclude_oids_and_modes) + 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); @@ -495,6 +500,10 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) N_("do a trivial merge only")), OPT_BOOL(0, "messages", &o.show_messages, N_("also show informational/conflict messages")), + OPT_BOOL_F(0, "exclude-oids-and-modes", + &o.exclude_oids_and_modes, + N_("list conflicted files without oids and modes"), + PARSE_OPT_NONEG), OPT_END() }; diff --git a/t/t4301-merge-tree-real.sh b/t/t4301-merge-tree-real.sh index 43c9950dedb..e921115cd2a 100755 --- a/t/t4301-merge-tree-real.sh +++ b/t/t4301-merge-tree-real.sh @@ -46,6 +46,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 && @@ -85,7 +86,7 @@ test_expect_success 'Barf on too many arguments' ' ' 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 --exclude-oids-and-modes side1 side2 >out && sed -e "s/[0-9a-f]\{40,\}/HASH/g" out >actual && # Expected results: @@ -108,7 +109,7 @@ test_expect_success 'test conflict notices and such' ' ' 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 --exclude-oids-and-modes side1 side2 >out && sed -e "s/[0-9a-f]\{40,\}/HASH/g" out >actual && test_write_lines HASH greeting whatever~side1 >expect && @@ -116,4 +117,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 && + sed -e "s/[0-9a-f]\{40,\}/HASH/g" 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 Jan 22 21:56:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720847 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 8C9D4C433EF for ; Sat, 22 Jan 2022 21:56:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235061AbiAVV42 (ORCPT ); Sat, 22 Jan 2022 16:56:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35754 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235023AbiAVV4Q (ORCPT ); Sat, 22 Jan 2022 16:56:16 -0500 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7E839C06173D for ; Sat, 22 Jan 2022 13:56:15 -0800 (PST) Received: by mail-wr1-x430.google.com with SMTP id v6so6478063wra.8 for ; Sat, 22 Jan 2022 13:56:15 -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=F9CLSZjha85LciqxPUUtBN1WTgwQfn25n79BuZOw90Q=; b=LUNIEUpYvhexCHZToLwy/+OxynVnUHKS9nsMILTz/kt2BpQ+9dh4rX3rWLr6nWeVrC XF267EGwOrSYaY0d+pB20sdtucHVFJNj9n3J0bBmXTcDDDYe8wzuo2CcWO+yjdBIf4g8 xv6U9fcXqd4Xv63SB2MFds2vuo0O3ihc9+FT+NPFwsjyHPvbGs80Yb02jTb1FTa92CyM 2NolNsiTAZckBuHgpBQ0/RCT4b9sk3DK3iIQDrc8iEVHFjHIZxVeBQjuPBbYRFzSL704 GS2NVDdLxa4db3a1UIP9PEoOtjVw5nrmfekSutiNUf48hk4dHvPKJOY/3rXL/xp4wlbb vOGQ== 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=F9CLSZjha85LciqxPUUtBN1WTgwQfn25n79BuZOw90Q=; b=PmGpHYUN4wGvetAx+dYuiye8x+r0R+02eVrtmrepsqjnULKXyzNHe8dzKq3jVyJoli yu4MUzBFiKK82HxF6K69H9tYknc/2fNs1NryfOjYeaMXNiZrxfpoc19dYPg0okvNfL+U ImxX+qUExHOHMnR69DsBEaVLXAzUdGvnb6dgLHTw1LjFy/7dlz44FilN89R9U4/fXAgb a2zcyAl7iGty5S6p2Kr1xEQaOcFLouOcgFfLWdFs71jzEGFMehSfQFjPNq7xmBWxGAeL tkt8Ys/ofSn4LhxWj3j8/YX0aZ0486oILQB09mKFfXMq4yoZe72uo44fdnkWjEk36iJ0 MtAA== X-Gm-Message-State: AOAM5339JWwkm+naharAWwHcPigU24vhY7FsXMc5rsXo9a5VA/Qi1uis d4xe1NMBH7yb484fFHXd7MPl4ezh4tI= X-Google-Smtp-Source: ABdhPJzDDJJR9A6zwjyuQHWuyH07gl9f/FrI67cHv8culsEcyKW/TSgZ+sMlSYLwcLjuAuKfvG2kGQ== X-Received: by 2002:adf:e445:: with SMTP id t5mr8719275wrm.537.1642888573962; Sat, 22 Jan 2022 13:56:13 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id l15sm13898191wmh.6.2022.01.22.13.56.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:13 -0800 (PST) Message-Id: In-Reply-To: References: Date: Sat, 22 Jan 2022 21:56:01 +0000 Subject: [PATCH 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 , 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-real.sh | 24 +++++++++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index beb08269a70..df10a5963c7 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -52,6 +52,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 7aa7f9fd54a..98441d5e05b 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -394,6 +394,7 @@ static int trivial_merge(const char *base, struct merge_tree_options { int real; int trivial; + int allow_unrelated_histories; int show_messages; int exclude_oids_and_modes; }; @@ -440,7 +441,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); @@ -504,6 +505,10 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) &o.exclude_oids_and_modes, N_("list conflicted files without oids and modes"), 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-real.sh b/t/t4301-merge-tree-real.sh index e921115cd2a..a0447410655 100755 --- a/t/t4301-merge-tree-real.sh +++ b/t/t4301-merge-tree-real.sh @@ -37,7 +37,13 @@ test_expect_success setup ' >whatever/empty && git add numbers greeting whatever/empty && test_tick && - git commit -m other-modifications + git commit -m other-modifications && + + git switch --orphan unrelated && + >something-else && + git add something-else && + test_tick && + git commit -m first-commit ' test_expect_success 'Content merge and a few conflicts' ' @@ -138,4 +144,20 @@ test_expect_success 'Check conflicted oids and modes without messages' ' test_cmp conflicted-file-info 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 Jan 22 21:56:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12720848 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 9CDBDC433F5 for ; Sat, 22 Jan 2022 21:56:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235067AbiAVV43 (ORCPT ); Sat, 22 Jan 2022 16:56:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35760 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235026AbiAVV4Q (ORCPT ); Sat, 22 Jan 2022 16:56:16 -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 4E343C06173B for ; Sat, 22 Jan 2022 13:56:16 -0800 (PST) Received: by mail-wm1-x335.google.com with SMTP id c66so20393599wma.5 for ; Sat, 22 Jan 2022 13:56:16 -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=TkPdobH4MibBT4N/wYT3RVIO/1rz+5jRHdHl+Ke0pzM=; b=j3ITPR/JoUWnHrSVIUcNb4hCHf3ZzyYX78zm5j3hgeMHTijVKmjCEQbdXXk1rzUmPr /j9KCbGV1G+E3dmM5hZZXdMEhRMBr3d6JT0rgwz3ZxAX/4WDMO8biSi8Z6jjN4GAhyWx T+FYh2OaT5jyu9xjyQGLTjc8vsVc72pIVkRYghmMSUddI9PXIkEYS2coMm103K57dJSf +uDBWu2khG2EnhT22HLrSwDXqA1AunDvTHcVdQk0wmltZzVWAkza0+W+nPilzha1/9My RA3mc4OGjW18V+LzIMNYy9cdu6oVUDrZOuDeUN+BiPI+U2kdW9Z25Hdu60HBg0Ut109O fqVA== 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=TkPdobH4MibBT4N/wYT3RVIO/1rz+5jRHdHl+Ke0pzM=; b=2wpCGyN/a9eKm7BG12W5sbg3X7Cxo2X8l62mXhrU1CpT8DGkmxmjoC8tJRIQBdm/1O ONqolqG7iySZgLfBLbMmw/5Znh3DvCOJ19mAKxuXd+4UJxjvvXBehWJ88Ff2qlQWHfdW g8dY+QXy7JWCCgZUtrX0YIZyijMYwlMpbXDY9u33PTDq/aH9UUKiG+eMla/gOqzSnG6A WhBpzkS3oi2hZSJFFxpMT8Y+4qjHhz+zneUgjEoNqm7UGsvQsJPuW8IdRnT36t0105Uw Yywor0tgdl06lQatZ3Ta3hheTDWtGzxxqEeaZl9lFBiuOgZ+EwLnBI77Sk1bXQIeikkH lT4Q== X-Gm-Message-State: AOAM530lPG8cXBvgJpziXWbt0JCuDrUFMB9k969ViLrySSTqr2Mrg3u6 +TlaE941HcSV9u7JxZC9cb5wg/umIME= X-Google-Smtp-Source: ABdhPJySocQnA387F81PeR15rnABjwEbioZSss8N2XyDhRbEhnKXSHxeoeGgb3BT/HMb2K5o0rh4PQ== X-Received: by 2002:a05:600c:414e:: with SMTP id h14mr3549610wmm.165.1642888574745; Sat, 22 Jan 2022 13:56:14 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 6sm7734976wry.69.2022.01.22.13.56.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jan 2022 13:56:14 -0800 (PST) Message-Id: <4123209cafc953939be66c17e0560749770c5ecc.1642888562.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Sat, 22 Jan 2022 21:56:02 +0000 Subject: [PATCH 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 , 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 df10a5963c7..3c1aa0ffbae 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -136,6 +136,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