From patchwork Wed Feb 23 07:46: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: 12756513 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 78416C433EF for ; Wed, 23 Feb 2022 07:47:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238741AbiBWHr0 (ORCPT ); Wed, 23 Feb 2022 02:47:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42994 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229629AbiBWHrY (ORCPT ); Wed, 23 Feb 2022 02:47:24 -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 3CF6A35848 for ; Tue, 22 Feb 2022 23:46:57 -0800 (PST) Received: by mail-wr1-x436.google.com with SMTP id v21so2855486wrv.5 for ; Tue, 22 Feb 2022 23:46: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=HsHj2KxDWTA9QM6TZSN11NDwemvgrQd3pHbka8fElO8=; b=iG1G7llAmaVvRFg9Y4URY29IOAtwSh22rexujPd9nSHj15M+bHgNETBv1UHLnGE/eu +nrFLcYicOOM6s6OgjpoQiBzKP7WlZOvCdP5atOoNg5bAID+0wf0Z7nNTgCgXTsxMuzu UlIVOCBIeYj/+WVGOSW2mGVgFtGL//TQWDjy3VjFoy5e1/xNr/aYKGWVvCzplrF2ZrGa A18c5IO++kMoPgpYjTyQlpo44Mk9ChyBTlE9Ke6jPu1wEvvr1QXEMTrtIMTOfhbKsH+L qfiUvZxbGngKGpxUjqhOZcIDoUpo8cAxgMd3cCHAP7EBOPuLgVHqC/SCOwfwcclZKex4 oPog== 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=ceUlUZJwTUWMzc298J/7Mif6RVRvy0SNNJqmWid6ZHtE7QdetL+cedUXbFJd1kN/Zy 20zAibvqxLTFP2HXhEn07It4rVcB8YeZWtRYOzQjvoRjs1UwFTvIFJvUVdOYdCQiLmqv XJH77yrEU4mnuhsZiutM6GfrXovpyckX5JQU1oti7A/TApX3TJIBk58SvQJmNMymwaoh Q1/c9ytnMa+xOXqbM6Wlv97emxcnVJfOIz+bRURpC5A9m/lN2ybw//GX5UKJ/MCZnz2P LeiWNu1wCkex+WeeKAXCk2E3zI1oIpLkyOnCaQZzQ6z4bBq3EwbWFFjUTuC2IbMXjWM5 rK2w== X-Gm-Message-State: AOAM5339qBxvubpmp3Sqr3OwuP9PIWouL0ES6kXT/EstSSsqDH7VQBCi 2jcaZoTaJniccoCE7CgkH6kd0cpgSEk= X-Google-Smtp-Source: ABdhPJxJm1b0IDJOqeuYqY36/njGmQezUllvOQDd1bGd/+UQA6EQjtZIJp/uXau8irvv0NrB90DpvA== X-Received: by 2002:adf:f1c1:0:b0:1e3:1381:7bd5 with SMTP id z1-20020adff1c1000000b001e313817bd5mr22333833wro.450.1645602415539; Tue, 22 Feb 2022 23:46:55 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id k11sm5431974wrd.103.2022.02.22.23.46.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:46:55 -0800 (PST) Message-Id: <4a7cd5542bb2f89b4874e4115542ccee9c4639af.1645602413.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:42 +0000 Subject: [PATCH v6 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 Wed Feb 23 07:46: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: 12756514 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 1242BC433EF for ; Wed, 23 Feb 2022 07:47:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238746AbiBWHr1 (ORCPT ); Wed, 23 Feb 2022 02:47:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43068 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234726AbiBWHrZ (ORCPT ); Wed, 23 Feb 2022 02:47:25 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2AB9E35849 for ; Tue, 22 Feb 2022 23:46:58 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id x15so3740953wrg.8 for ; Tue, 22 Feb 2022 23:46: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=s/FNUD3Nfv1aJ56di/sqnJE/jJBUPQEIKWoIKlAJYVg=; b=Dk34WnViRnL2EfZYzXgsn2R11NnoVWmUkem+nri68CAo5jMUuwXRVIPQ/jBDYSndbB OybL00yZILI+wWaEYish+a4TyA5dCH+TqE+afCEulFodoJSDZPd+17iJ90dXohKm6K0p VHZZMQipv4kdhCgb+sbpYbfOCF+OUso9rLYCb8uUnuAESIQsMUWBAlNa/cHtU82y5Kpk eibV2O5J+6JMNG+TzJOogF+6+M5+Rh/BSFlOKlcImfb/C0JDzZMZbHVUTS0pcHu3xdG0 A36HavA3QIGvLikcVI+EjAkewnhVEuKB2saRa8ayp6Pce85SMVpieKGPtCDQHEQ2IrPk V2pw== 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=TTXjK+Zur8zfui67EP1uP3jCYNK15MHIvL6CgMYEq4OGzxIBDfeybwidFqQ294zoZj FSjiiiqZBBg0cZhxu6WZmUUbYvyrnxQTm7jyrX/Qyq/60FCYQptRRDtN5GU7hMwjj1t/ F4Dzb9JFXERM796PgB06HgtuyQNXGYl8vS8WwmZH+oyGkuJqaL9YdNc8bR3eZ4B0A5+/ LDLwxBC+0bQxp5XDWHFdfCaNhHkiTw93ivNeCX75vfaARSB1CmLxcYH6uDLGEK5EsJD6 T0IZDX/UiO9Xe5n/LlR47n9jt/AuQi27GRFGOXU77LFyUIFjm+Ik9cVP9hdqtqwp5xOQ MSWA== X-Gm-Message-State: AOAM530Mmjq0zzEjhuXwhtJJPfZZjd6T4uyKhFRwGauhulyP/I5AdUtP gOxxplaSIsPlbzCiFKiOhjSrI7Oe7mw= X-Google-Smtp-Source: ABdhPJw5k9U+0dJnPB7/cFJTTOiBcXia3QMYzyzvysSIkhUZHnNr3a+yHtX1P1oi7xKrgeG6wmpHcQ== X-Received: by 2002:a05:6000:1141:b0:1e4:b28e:461d with SMTP id d1-20020a056000114100b001e4b28e461dmr21290802wrx.320.1645602416653; Tue, 22 Feb 2022 23:46:56 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id f7sm48840273wrz.40.2022.02.22.23.46.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:46:56 -0800 (PST) Message-Id: <4780ff6784d426bf0a96859ef9bf9c14e87d5f50.1645602413.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:43 +0000 Subject: [PATCH v6 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 Wed Feb 23 07:46: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: 12756515 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 B943BC433F5 for ; Wed, 23 Feb 2022 07:47:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238748AbiBWHrc (ORCPT ); Wed, 23 Feb 2022 02:47:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43196 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238743AbiBWHr0 (ORCPT ); Wed, 23 Feb 2022 02:47:26 -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 3B1A835848 for ; Tue, 22 Feb 2022 23:46:59 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id s13so9595702wrb.6 for ; Tue, 22 Feb 2022 23:46: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=lUeMBI0VGqVpVf36mWn+Z0nc/oxflgv+ptH2bmFaszA=; b=bmnClPBCIZxTAddL+o6Nsrox85++kGr+0P+kB3NDR1lIKj2nRWJreoBmw/UNOZQYfD NRF8NljKzlr0/DgErOiZ1+PKEDz1CQla9uaS8aWBCCCJnJZMx9mCI1LziGDjWSNOxYtF hXyYmjQGaRFDbvy4c0PIvLaO8diS892wNbMykXxw2Yuqe52aEOjRO3utYWUod3hBpOQu tfGDIzggIuvXSa/6OZOchFcoojSQgInKvUps0jlvSXpL+4oPD19HpE+rw6RNV51v0b4x PtNC+e1nzpv9FQTGxcW79Lc0nt7SQ+bleYZWdtX7V0XWCz/jusHyEHoY2c8gKXrYbW+g KGeA== 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=aU8EQ1XH6QvzgF5UzW0HKSZB5lYmThjQVBZRCkyd9sdPYkW7JS7Mw7xlVsBt2vr1ja /jdEsXRtF7p57VjbL5/X7pYq7oBnw1FNYl1ubZvBD5QxgH7JNAHQl51Arf1BBCE+kk/l Ks+adffK1qNeLNeDXszW0uwglkw6NnT6T8aG3xe6d4QCTQs4XlE8nPC1vwHL1FCJFxgs e730vlaMiZPK3XS5ioHQA1oKpiz3vQwe3kiwp/qP/x42gsfKwDUEhGCxnG+lqqD8PLR1 GcV7DEYWVsJcX+ACNFAfRWKkRKhl9pRUg3g/jyfNB4b8GR/1a7VjS1pd99rWFycTAPhq cDbA== X-Gm-Message-State: AOAM5325QUGL3UzO1UxEqA0JuuGJuJiC0ha8ifRKrzUN2ZDkOv7u3Ykj a8Ynnhv93G9Wu7TQyAHgXWG6qS7P7YY= X-Google-Smtp-Source: ABdhPJwqsub8qjTmr87L1RMBeP6r4V+pG8ht81yGrxOR9BTWKduQza0huTScHpaLwBLdPIz5upNslA== X-Received: by 2002:a5d:630c:0:b0:1e3:3e4c:c5cc with SMTP id i12-20020a5d630c000000b001e33e4cc5ccmr21735310wru.612.1645602417664; Tue, 22 Feb 2022 23:46:57 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id u15sm67886591wrs.18.2022.02.22.23.46.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:46:57 -0800 (PST) Message-Id: <60253745f5c59ac4c75d46df1f98ee722523f166.1645602413.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:44 +0000 Subject: [PATCH v6 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 Wed Feb 23 07:46: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: 12756517 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 B171CC433FE for ; Wed, 23 Feb 2022 07:47:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238779AbiBWHrf (ORCPT ); Wed, 23 Feb 2022 02:47:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43348 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238747AbiBWHr1 (ORCPT ); Wed, 23 Feb 2022 02:47:27 -0500 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4D37155765 for ; Tue, 22 Feb 2022 23:47:00 -0800 (PST) Received: by mail-wm1-x329.google.com with SMTP id l2-20020a7bc342000000b0037fa585de26so1898546wmj.1 for ; Tue, 22 Feb 2022 23:47: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=Qp5R/2nEDrwidqRUvDGZRkgucr9emIb2r0juqChWThw=; b=RVC/eu9geg5He6Wf7D2MykYAeASkQjef7yGqVvncpF8lCJGTYJXcZd+tSua/6+Ep87 BFCmBLXmK4eEPB9I36gtiFqzfu9Qjzz94NpXxnq2KkJyd7sNHXS2mUBpJpdOXdHSXg9q gMO+aVfAzclnyqYz/6QbWrg6w8EWRQdheSi1hyMwJpVnIyZL93tnga5ouub+N2SJhn2t RK9EePDIy/dfpgDf7ab8QhXmOSaRiRrZ8ZJSI+EL30COxoGdNPUVhrW58GXQ7YYhTKVm hBRzBLJ7kfD9iLBfiU8B/IBRRG0hfobYi/FSr4TAOGdJtFs6doQg257+xF/DF8vp1f7I exOg== 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=Qp5R/2nEDrwidqRUvDGZRkgucr9emIb2r0juqChWThw=; b=hmtd43PFpSPtF8JIEfVlaX+5kmBehLytNOBq0YQ9g+ePsAueGNG2raFL9TehEY2Ia5 NPfjudwl89cOqdEYWY6aFtwNafTKR6yABgWdPt0F3CaW64EzZpMB+o9XAtW6pvDfhEnY dwkrKU6jVN3BPBPEdvtWMCmX8HU6ttu6AuUvvgfafJRtrLVUxOXGv1+WXDKUFNUmRDic jay0yvdcQzsKQ9PkebC+cDrkHemXc/9zUVNa+B2fDzU8bI3vs1TtlOQkxSXnu4PseJMA SvVZOLK4GNKHGc9EV8r+uFdTskeUFzTHu4n9th888hULe9dom+wJ+xjLyZt6kp8dPoGv CvaA== X-Gm-Message-State: AOAM530I1mhjMpU8ffo6nhN7kcbeuUP9O/hTTa4uHCcVpVgPEZ8orQk3 US+sXuqQIJIhongtBmtafZFdK33GKxs= X-Google-Smtp-Source: ABdhPJxWBQjvNuqpujnSnkAhDNtrifvfmkC8wqGa74GRSB62uUUeOuEYlSWB5NLEMb5AcMS7/QXNDQ== X-Received: by 2002:a05:600c:a45:b0:346:5e67:cd54 with SMTP id c5-20020a05600c0a4500b003465e67cd54mr6144466wmq.127.1645602418572; Tue, 22 Feb 2022 23:46:58 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id c17sm4497894wmh.31.2022.02.22.23.46.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:46:58 -0800 (PST) Message-Id: In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:45 +0000 Subject: [PATCH v6 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 | 98 ++++++++++++++++++++++++---- builtin/merge-tree.c | 41 +++++++++++- t/t4301-merge-tree-write-tree.sh | 106 +++++++++++++++++++++++++++++++ 3 files changed, 232 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..2a9c91328de 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -3,26 +3,100 @@ 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) +[[NEWMERGE]] 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. + +This command has a modern `--write-tree` mode and a deprecated +`--trivial-merge` mode. With the exception of the +<> section at the end, the rest of +this documentation describes modern `--write-tree` mode. + +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 performed merge will use the same feature as the "real" +linkgit:git-merge[1], including: + + * 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, a new toplevel tree object is created. See +`OUTPUT` below for details. + +[[OUTPUT]] +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 +----------- + +This command is intended as low-level plumbing, similar to +linkgit:git-hash-object[1], linkgit:git-mktree[1], +linkgit:git-commit-tree[1], linkgit:git-write-tree[1], +linkgit:git-update-ref[1], and linkgit:git-mktag[1]. Thus, it can 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 + +[[DEPMERGE]] +DEPRECATED DESCRIPTION +---------------------- + +Per the <> and unlike the rest of this +documentation, this section describes the deprecated `--trivial-merge` +mode. + +Other than the optional `--trivial-merge`, this mode accepts no +options. + +This mode 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 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 (a trivial merge cannot +handle content merges of individual files, rename detection, proper +directory/file conflict handling, etc.), 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). GIT --- diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 0f9d928e862..2332525d8bd 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,43 @@ 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 *merge_bases = NULL; + 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 + */ + merge_bases = get_merge_bases(parent1, parent2); + if (!merge_bases) + die(_("refusing to merge unrelated histories")); + merge_bases = reverse_commit_list(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..6d321652e21 --- /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' ' + TREE_OID=$(git merge-tree --write-tree side1 side3) && + 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 $TREE_OID >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=$(git rev-parse 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 && + sed -e s/HEAD/side1/ tmp >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 Wed Feb 23 07:46: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: 12756518 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 5380AC4332F for ; Wed, 23 Feb 2022 07:47:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238783AbiBWHrh (ORCPT ); Wed, 23 Feb 2022 02:47:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43432 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234726AbiBWHr2 (ORCPT ); Wed, 23 Feb 2022 02:47:28 -0500 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4A46060CDD for ; Tue, 22 Feb 2022 23:47:01 -0800 (PST) Received: by mail-wr1-x435.google.com with SMTP id q23so3407292wra.2 for ; Tue, 22 Feb 2022 23:47: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=hBf1L3DAgwM6lVnjfgVq6LC6AtXTGHUlM38V8n4wdp8=; b=eeq/Xsne6vv3a4csdBMEWBY+SR9An3H7PeoBcegztBoW+FotPanx9TewqZmNo238Wk RfaJnLlCJSxmJLZK5aqIqqU2RFJCSwKPpYqTfnarNi9fLXmpEbzWMD6Vfp1JQAXkyqAW VfddOFqUxXxon+7dH3UeUqZxcmfHZlOZVWsbjAqpsmQbooUud++OgRbjxU2yvpBp0Rbb JSJdM5lmOd6Nu6Wn1cxKxwxrJK3UQV9cU0sGay3XerHeHo6jNmiPs9FqFy9el04ubsVU 4TmYcSD0Wg8SCzEQSDn7EKvJshl/+i5lQ92Usb6f0a8fAKML4JIoiqoD6rkxOGNl89Cs nQMA== 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=DgNwDtFyqatghvH+XeVg1jYbpvMH7B6aDdTs6FWeYea1osPm3Rv6n59h8Z9+ONLlqF BPTR5NpU0fvPaIMmS4krDGEGg4e8t006m+r/k278DWHDMBH/zS632N1VklsSYzQXUlNC yYeKxfHT10XiKkjEDWFa7XfRLKnEeYUud9VWlXk+ke4iM8cVkSdfbJo7zGtV88HWwRKm Ff/i1H7zZdOhFjBNE3ijZCbfskNKnWBxu5CHbEPt+nhT4LJThA5TqdGMOv7wmJm0jB5y YdR8V701fZVBHU5NlGLji8DfIZ85dFRiH0EKa14l1bhEXbhA23qxN9N77h7bbK0AQrxO sJHw== X-Gm-Message-State: AOAM533tfsamDohpUeIHN8lh7Ik3+vB5GkPUIJsjn9awtKdI/tpwNA1B InMnhXjBtkmAUC5v9Tx3De09QS+CGgg= X-Google-Smtp-Source: ABdhPJyvd8ZUJPsS9zwd5/ukKOCuSk/P7vXxTWB6Ec42SclTas3AkNhWgebu+QI7Pv4LLH7goR1ogg== X-Received: by 2002:a5d:53cb:0:b0:1e7:5e87:9c6c with SMTP id a11-20020a5d53cb000000b001e75e879c6cmr22982233wrw.696.1645602419647; Tue, 22 Feb 2022 23:46:59 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id p8sm49073967wro.106.2022.02.22.23.46.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:46:59 -0800 (PST) Message-Id: <6629af14919a5133c656a0592a18e2adb8925dc4.1645602413.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:46 +0000 Subject: [PATCH v6 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 Wed Feb 23 07:46: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: 12756520 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 67D7EC433FE for ; Wed, 23 Feb 2022 07:47:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238787AbiBWHrl (ORCPT ); Wed, 23 Feb 2022 02:47:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238753AbiBWHrc (ORCPT ); Wed, 23 Feb 2022 02:47:32 -0500 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5157C6662D for ; Tue, 22 Feb 2022 23:47:02 -0800 (PST) Received: by mail-wr1-x429.google.com with SMTP id q23so3407359wra.2 for ; Tue, 22 Feb 2022 23:47: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=WpxAId1kdO/lJ7t476gCpgr/ZvqAUZeQTXQX9mQSlaQ=; b=S9xTDzErfMmppiv3eCkDlipXgj3TOG4Ug+9j4vopWhR2JS96hkaUq827YdtDFVuRgs a9GdctTTVtCWQXBzMTiOecx/4Lmz9W6tXX5Z8WODlPvTOWuIvTixlwsRer+6q6n1XTzs xAjyQcFOClAYbW3KERS0bbJvnkO7ew89ipgBNdcQ+QQsVxRHt5PCuAb5FEl97XiJ0enu Vu4cCX2psYcj0NEbYgzf1hL0M687SNmWe0jt43lff/a3QHpwH//SIRblTS8EWnO9CQKI YhLtAA+WJ+P/sbBAiOeC4s/c+YsiohlM8B88PzqDRTDDJNmGBbhk3clWYhjNm/3ndrel cJ+Q== 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=WpxAId1kdO/lJ7t476gCpgr/ZvqAUZeQTXQX9mQSlaQ=; b=rkm1Ze4xG3sXLQonpGlGr6EqUEAeMevP7zQG5SFOtIDrAYDXsKeFUVakWQf5VvD2G3 3jUzp3pwjmm/Uk82WTmAJlLTtj+dtiz9xTIDqf/QmGYMfaWl97Vydh5hhCio1zIfM6xT qKIklmDN7n1xzlwkK0dSN6NJG6ksKZhstInfyRny5txYRM3roRY5X/Xen1ZIZ7qO4XDr 0lLMtcC/l6FR0B/M6LnLt6DTu8b0/tZNdoYwwjJgupWBGUxYz5Se/0K4/g3uNo1BUjBY 0BSsqazPlQKmbLSG64TJy6wtIJDBUwPltk8UVmUZFIC7LBpZmQpQR4E/OhRAx3wu+6a8 VcTw== X-Gm-Message-State: AOAM5319B+c1yJY3pSJAbVuymNxXDmRnNcWdq5Gpgeh93zxcRsOE1agS wBJMa3H2txOMRoTVl2N8MCEssI8/CmU= X-Google-Smtp-Source: ABdhPJyNI8KQw7C8Kp02KCA73lTuDAVTiIUPnbB56yvFDGIfPD5zRgjwOFr2sKJe7r4zd+jPaI14xQ== X-Received: by 2002:a05:6000:1445:b0:1e8:49ec:5c22 with SMTP id v5-20020a056000144500b001e849ec5c22mr22410328wrx.87.1645602420554; Tue, 22 Feb 2022 23:47:00 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id k3sm18870379wrm.69.2022.02.22.23.46.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:47:00 -0800 (PST) Message-Id: <17b57efb71404a21b05db8284e8dfd2978e6a3dd.1645602413.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:47 +0000 Subject: [PATCH v6 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 | 47 ++++++++++++++++++++++++++++---- builtin/merge-tree.c | 21 ++++++++++++-- t/t4301-merge-tree-write-tree.sh | 37 +++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 8 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 2a9c91328de..25b462be14e 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) [[NEWMERGE]] @@ -37,18 +37,50 @@ linkgit:git-merge[1], including: After the merge completes, a new toplevel tree object is created. See `OUTPUT` below for details. +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]] OUTPUT ------ -For either a successful or conflicted merge, the output from -git-merge-tree is simply one line: +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. +[[OIDTLT]] +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. + +[[IM]] +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 ----------- @@ -72,6 +104,9 @@ 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. + [[DEPMERGE]] DEPRECATED DESCRIPTION ---------------------- diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 2332525d8bd..831d9c77583 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, @@ -435,18 +436,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 }; @@ -456,10 +466,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) { @@ -483,8 +496,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 6d321652e21..719d81e7173 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 Wed Feb 23 07:46: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: 12756519 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 398B0C433F5 for ; Wed, 23 Feb 2022 07:47:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238785AbiBWHrk (ORCPT ); Wed, 23 Feb 2022 02:47:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43862 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238754AbiBWHrc (ORCPT ); Wed, 23 Feb 2022 02:47:32 -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 4DA956A01B for ; Tue, 22 Feb 2022 23:47:03 -0800 (PST) Received: by mail-wm1-x330.google.com with SMTP id y6-20020a7bc186000000b0037bdc5a531eso2099555wmi.0 for ; Tue, 22 Feb 2022 23:47: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=Ap4ZqYlnkgb+ZsEVT3Um4/EicxMnYbd2hGinYTe7EAw=; b=dbHB8geF2tk0PvN/9CzbDsJ6qNFUJlyFIkUiSTJNQyPrpDSUOGSmACuXZ/CTY6GA6D oV8nCk2xWxs8KMxbFRazQPMg/xxQoFc5aagQHci+01ODa+RUgg4hbTShq/bzSckdAkmd 2P7VsRMf0Tjtj4/vgM8/TIiiV8IAJOtYmh2wI3MMFwi7TQhEPHf803T8v8V7URQYWY6O FP0da1UtheWjuVFXCuo4bE5UzmgGOvHyu2Sa188vth/B8AwY54knGnYEJdMHBetB0m58 sgiv0x3LbOxSOBfCSVp8yeMAsyKnnkwkMQc5KGkTsjSD0H5lh5YlvME7D7EMxhU8jiry y4QA== 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=wHHFagFS0IJaiQ1R3HTzgczWlU5YpS4Aq9MYB8f7e9ksI5LcnVDrxbBPjbGcW3Cq6G 3ipRxxYIuUdngKjlxGlOr2A17qv3dxyD/BQz31rm2+FnHbCb1yTIX3/n4vnEh8XLq8/N hO0K4HChAfhVx5zxrWq862UbP1B+bB2WH7q/20pZoUimCD7CbC51SMZotr31ehImJNIT 6/ezAsnPqunUW7lTAnH7hieTqj6zUayNK59fl9Jed2eW5AWwOyLuK/PuIDD+WhGa/Qux UzQ61LkIMv2Cf4J5eDIJinqERMS/V0wtDrHAg7R9eUKsauO0GK5pI4CpRCitYlShMDa0 pycA== X-Gm-Message-State: AOAM5311Q90X2S21EMnND1R7NlosN6hfOU1BWRuknwYiI+5kA8bhX4UK QyJfJUFvPda/H9MssYuflTxMwhsFOEw= X-Google-Smtp-Source: ABdhPJyQbYkKq066U2w3y4wY7bBsbLrpzqTH/bLhLsFnM8UoBETszfSKUVrjInxY2llnb6sdgsKUPg== X-Received: by 2002:a05:600c:3d88:b0:380:f6d9:9461 with SMTP id bi8-20020a05600c3d8800b00380f6d99461mr1010662wmb.137.1645602421617; Tue, 22 Feb 2022 23:47:01 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id c9sm35280326wrn.51.2022.02.22.23.47.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:47:01 -0800 (PST) Message-Id: <4c8f42372dda68230563d5f4d12c3bb2878ae979.1645602413.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:48 +0000 Subject: [PATCH v6 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 Wed Feb 23 07:46: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: 12756521 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 55040C433EF for ; Wed, 23 Feb 2022 07:47:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238789AbiBWHrn (ORCPT ); Wed, 23 Feb 2022 02:47:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43870 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238755AbiBWHrc (ORCPT ); Wed, 23 Feb 2022 02:47:32 -0500 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1200A6A075 for ; Tue, 22 Feb 2022 23:47:04 -0800 (PST) Received: by mail-wm1-x336.google.com with SMTP id d14-20020a05600c34ce00b0037bf4d14dc7so3717873wmq.3 for ; Tue, 22 Feb 2022 23:47: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=XU31w+RDeQVF/hdGuYvGcOqYHJUPM+dwnKV4wxmDH2s=; b=QkSMPnm4mbkeK1clMla4yo+tQcGg5ArPXgjC+1Nb15DMeI0hKxO/2WJOGkr5zlwuAn OADxBQazoMsjpjWhOJYiZJC86mM5073sZ0wBWvfZ0q7/OQCmcuMVLKNKokrB40+T+VZM rt3oD71j8FzMKUSScnz7oyyU9WtGui4bNOV0JndG+F1DrGUaQVnW23uv9k+iFbkDzs0H qhFs4+n/RN477wPlZGoO4ctMk4EBRCfatjEbyuCrfIcfCscMrZraSqZEgznJuiWYqym6 pzX45pqCWXSDhKxeRMV7ROgFOPCQ+63IdbK0QfC1/cflN5AcXLAky6Ucg+pYu0fSJgNP qgag== 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=XU31w+RDeQVF/hdGuYvGcOqYHJUPM+dwnKV4wxmDH2s=; b=cOD4lglHLBKiW4LCcC/N46/7+vZ9igoA0YYqGoLppiY9VX5GH3Oh4u72ttJYZ20ali xxOIB0kigtI7MQFNk8/Vllqr9+qhEpWZeC7LS4ZDoID2wyDiLPbSXMaolX+4VRK6AqAX XVzEoZCuLnUo31EkrVKezYlqUwPZIHovdaCUxHS98HYF0pg4ZuOK41cD3x4TNcSgQAo0 l/e6X3yD8BQKnnPDc+Zy68jqN1QMfT67JENISBlRuw4GGsNEk2yFZH+jT/h9QUvE6NX7 o+ZCkqBgkJ7Z1sW0+fqWaYbmLQqxaQV4CJUaKkVc3oCpFQvEsoScIDuqv+zdOp+/gVfq FD5Q== X-Gm-Message-State: AOAM531sKpHgVCo0KMf+nIVVfTqy4yPmtWzhyR4t/UTL/87QhUdBN3I3 pAJtoMjX83OjULSTomlVgGSyc8jECQY= X-Google-Smtp-Source: ABdhPJw4AIe5IGe5Z0aDYkQFO3sSs9C4pGuKyVFEL4Ss203JtmFR+mWHCBQnsOPwiB+WfWArCYQWag== X-Received: by 2002:a7b:c853:0:b0:380:e16c:19e7 with SMTP id c19-20020a7bc853000000b00380e16c19e7mr4362141wml.172.1645602422452; Tue, 22 Feb 2022 23:47:02 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id t1sm67193031wre.45.2022.02.22.23.47.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:47:02 -0800 (PST) Message-Id: <7b1ee417f3d5a4c1778da289f1b93b28dabe4a4e.1645602413.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:49 +0000 Subject: [PATCH v6 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 | 9 +++++++++ builtin/merge-tree.c | 24 ++++++++++++++++++++++-- t/t4301-merge-tree-write-tree.sh | 11 +++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 25b462be14e..68a51c82618 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -58,6 +58,7 @@ line: Whereas for a conflicted merge, the output is by default of the form: + These are discussed individually below. @@ -70,6 +71,14 @@ 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. +[[CFI]] +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]). + [[IM]] Informational messages ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 831d9c77583..3653526cc0a 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 *merge_bases = NULL; @@ -441,6 +445,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); @@ -508,7 +528,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 719d81e7173..8e6dba44288 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 Wed Feb 23 07:46: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: 12756524 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 EC8ABC433EF for ; Wed, 23 Feb 2022 07:47:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238758AbiBWHsH (ORCPT ); Wed, 23 Feb 2022 02:48:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238762AbiBWHrc (ORCPT ); Wed, 23 Feb 2022 02:47:32 -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 21C0D6AA5B for ; Tue, 22 Feb 2022 23:47:05 -0800 (PST) Received: by mail-wm1-x332.google.com with SMTP id c192so13215962wma.4 for ; Tue, 22 Feb 2022 23:47: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=7SOR/FBx/PG5GwcYfRl7WIzTn+A4mPROJf87y4NZU28=; b=hO3D4fk+VXBYtPmCCg4f3HtJ9Twz03AbSfaLqRBONTCwwMHTrQNiW9OxOJhZNjo1FG 326PR6geA2c3Kd73PwDNJ2l0+YPWwcZF/JcGv4772WSjmUiXD/nd2ST/ut3mRkM/ORqZ 8HMFbVPjRrrbof9I0P4ODz8of70Tnb9Tn0m+NbAR3VSSTB7HyMcpn/wnYVfpWU7Sfp3p ANvnHfHdkfXlBQgQbJfq7NqlSFS5LXa19S/K7aJbg8Qpo+fnqJsb7N3CHBcftvxbFvfN da5PY93ywkjutSs3pK2jjo5VlrkSA6boTJmqOfRmD8s32WbuGMB1vKeuz6g6PKfkMi/J PutQ== 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=7SOR/FBx/PG5GwcYfRl7WIzTn+A4mPROJf87y4NZU28=; b=rg3dbJP2lBLbBSeJmQeBeDfSgFhDQ0/xoQaiJqjSmxre0vAHEeHj+MCta3AsgXHLlt 0Y7Yed+RlgsLoUeo7bs6BYS5g1KdEtbZWw9HNv893CNfNMJNjMJEadxIBrKZwL6qhq+p 1oElUk+7yhm7CKwK1Ghm/cGt0pyAqivuxgOQhEIVP5elkiXLG8ZtgLUbE6Lm8LZ1v9cr AHS4/Y1/hjcQF2XGL3n9jZdAg5jPWNHNRpbJTNuDWBPd6z43K9hZ1j3i1xz1Wbn+jEFh 7+TWW0Gw3DDvU3tum7dPXEovkcDKS9xQGELIKs6iaMuOyXL5A1XE4hIzDI3hXsc3nkqn g4WA== X-Gm-Message-State: AOAM531WDvJpF5dlJYmqRXMDOJ+7STzJUoKn7BpJ4vwecaqRJ6NdWrS0 +LNiL1oVEtHMCkJ9mD9han4m9Kgh5wQ= X-Google-Smtp-Source: ABdhPJwODaiL1+INbPzvYTIDovPYKlxnsjYoLIHt8KAIzNWioU13Hy1tyXU7QDODSY0AIozNLw5KYg== X-Received: by 2002:a1c:e915:0:b0:37b:d847:e127 with SMTP id q21-20020a1ce915000000b0037bd847e127mr6345562wmc.180.1645602423284; Tue, 22 Feb 2022 23:47:03 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id g16-20020a7bc4d0000000b0037bbe255339sm4662299wmk.15.2022.02.22.23.47.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:47:02 -0800 (PST) Message-Id: In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:50 +0000 Subject: [PATCH v6 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 | 34 ++++++++++++++++++++++++++------ builtin/merge-tree.c | 11 ++++++++++- t/t4301-merge-tree-write-tree.sh | 26 ++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 68a51c82618..b89aabdb98e 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -40,6 +40,13 @@ After the merge completes, a new toplevel tree object is created. See 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 @@ -58,7 +65,7 @@ line: Whereas for a conflicted merge, the output is by default of the form: - + These are discussed individually below. @@ -72,19 +79,24 @@ working tree at the end of `git merge`. If there were conflicts, then files within this tree may have embedded conflict markers. [[CFI]] -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. [[IM]] 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..." @@ -116,6 +128,16 @@ 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. +For conflicts, the output includes the same information that you'd get +with linkgit:git-merge[1]: + + * 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 + <>) + [[DEPMERGE]] DEPRECATED DESCRIPTION ---------------------- diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 3653526cc0a..4a79caf081a 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, @@ -453,7 +454,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); @@ -488,6 +493,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 8e6dba44288..0ec5f0d3f7e 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=$(git rev-parse 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 Wed Feb 23 07:46: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: 12756522 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 99CBDC433F5 for ; Wed, 23 Feb 2022 07:47:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238856AbiBWHsC (ORCPT ); Wed, 23 Feb 2022 02:48:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43844 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238764AbiBWHrd (ORCPT ); Wed, 23 Feb 2022 02:47:33 -0500 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0620031920 for ; Tue, 22 Feb 2022 23:47:06 -0800 (PST) Received: by mail-wr1-x431.google.com with SMTP id v21so2855985wrv.5 for ; Tue, 22 Feb 2022 23:47: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=LeY7XdOUECJwKHVlDjMn42GMKPkAu2BcGKlu3wOY/aI=; b=nagSDn4PPLiuQTiTT4pJRG/tD0vyr/wo4jyNakNb95wqKfyOgwaWepIU0p438nqcOc eYzl3pSx7n8sbXt9MxQOhAvMQ5dT/ev1+ex3TM6XvmwHDhE9HREow4+dMKEdA2YyssO0 izNzE+hLzjEC+WNvysIBdGOQ7SAUhhOJ9zEALcVYHk+knQnhkMtWs7DX36TZ59Q77Vo4 9W/SdNEpyRR2m79frb8xWiMQw68zBKn/bP1UEZKplDSZYnj+0LLV26xs+2oeWrDfh6br 7pKExKoAMCgZlD4hB3qmbJ+kcC5nW/IoTxT36Cj04CQEPPweki0rZoiCQdwLjq6AoSNE qGKA== 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=LeY7XdOUECJwKHVlDjMn42GMKPkAu2BcGKlu3wOY/aI=; b=FvcfiE+FsdTdCaTwj51obLgswUclvekGKlKsGN+sw4hbPB1twu4FHa07Fm/pS9AU3/ nX2Fjve6RPxyURJfGB7JR/egTver9vXNivl3r5ESFE4SbTj4J37aPkFtmGgSjjJ3ulo+ +qBaLhAiAqASxT22urYHp+VnvhoR+7dA4c2nFq+aUiszi3Z80W887AORBTBwl1b9/REi gjvGi0IMWKESHyXtVSkwouF/T9PszjnlwTcH2lxqLTIpb6h1iR7rz3sLxxKc7hZQNelr tDnAWK/NhpVG+KJTLBrF5hRRuV6N8pcuE4GJMTzYj0n30EDIn4NL7yOcVthyQY/W9f2g NJfw== X-Gm-Message-State: AOAM532pOO1VILwWQS7N/KJCYs2pQqrart8KtF4bANtYS3lS2tRReZt1 bzNVgjj5nBZBcn/a9KYDMUDnCkqKZSY= X-Google-Smtp-Source: ABdhPJyo0Q//2CsEUJ/+ATz95So/CntaiKflNL/k1CXJrCLpWJIDF8fqN3vdSfNMJjDrV1coRkZ7Rw== X-Received: by 2002:a5d:6343:0:b0:1e6:9825:101e with SMTP id b3-20020a5d6343000000b001e69825101emr22441356wrw.570.1645602424314; Tue, 22 Feb 2022 23:47:04 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id f13sm844154wrf.15.2022.02.22.23.47.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:47:03 -0800 (PST) Message-Id: <22297e6ce75fc232125798e65d0887c5b660900f.1645602413.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:51 +0000 Subject: [PATCH v6 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 b89aabdb98e..75b57f8abab 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -40,6 +40,12 @@ After the merge completes, a new toplevel tree object is created. See 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 <> 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 @@ -76,7 +82,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). [[CFI]] Conflicted file info @@ -89,20 +96,26 @@ 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. [[IM]] 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 4a79caf081a..767892006e3 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -445,7 +445,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; @@ -467,7 +467,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); @@ -493,6 +493,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 0ec5f0d3f7e..22e03f0939c 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 Wed Feb 23 07:46: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: 12756523 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 63BE0C433EF for ; Wed, 23 Feb 2022 07:47:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238826AbiBWHsE (ORCPT ); Wed, 23 Feb 2022 02:48:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44056 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238771AbiBWHre (ORCPT ); Wed, 23 Feb 2022 02:47:34 -0500 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3DA955765 for ; Tue, 22 Feb 2022 23:47:06 -0800 (PST) Received: by mail-wm1-x331.google.com with SMTP id y5so2756268wmi.0 for ; Tue, 22 Feb 2022 23:47: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=mmXje3uuaK8BuJfg02GOpB/9+6GTpkr32zp2fn50u18=; b=T2Z0Zhj61a1Z1nIaheAvue07k2hrl4p3MelcVhhaPwMLtexGCeIFT/LBt3/T7AbwGI UyEk6DuOKLEeGWxF2ZVGncm40tEo3pvxSI4F5u6P8u7AueFxhaqgQeTDW7m1z7FqKWcT FBKOYJgN+83MM5pYsDCN0kzzo6Ye1sToZ1SxznDWy6qvigcanNuXd6uVEOdR7fVn2U4Q 4MLpH+NA0W+yPHTCEbJRkTmD8IKMcksjuZ77lUOaHfLaZKNo0PVlTfuCJwtet3mZSyOA 62pRTJoEoytvrPYq+lcnXiPTVwMRx/lf5hOCSq9VKCW1N0RZkEHs1Q5iDwsHeHZWwEmW oYCQ== 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=mmXje3uuaK8BuJfg02GOpB/9+6GTpkr32zp2fn50u18=; b=Wmm1vnn6KKKPj+UpABScGKvIwVVxi5/I6XMcTzo3xcl5ExAJTTqiCkKUDHBKE11MVI r55WyN9dwOXyjLJYqIrEU/ZDwJyDBumrdE6odXvWBnqDtLaiA0ff9MNCPJdljFmSwnZw CgJsuAxJPfJV9OYJ4wewocavJbHMCLW+mDQfcF2N6eAmtHVFC6x/p0Tn4MuM9Qn7vS/S rxIt8gQiMIy4voa2L4iqUhMohKp/ZdWxUhwU90lBBoIJ1D1ZR6iAYhmg/HPjT0I6lphC euISxwCwgujCZkXBqcI9oEUf4RpAeD0eCCzlZblnoXx+2NYkEsnKnsKImBX9arIqA0ke 2t0g== X-Gm-Message-State: AOAM531ey0JeTQPP3mT8pGROqsV7wtn0AzS0xvOmOGe3vrMUzBpcgLkP NdHLbHsUlJzZlWGmjVOSLFS66iJkUJ8= X-Google-Smtp-Source: ABdhPJxzgn7Cw/ELETK+uKiklgejSJmp2ZphzZ5x2yDJdBv2wropRsReOR1J4spHbGZXZclCtFZDDw== X-Received: by 2002:a05:600c:1547:b0:37b:c6c4:1000 with SMTP id f7-20020a05600c154700b0037bc6c41000mr6462226wmg.111.1645602425187; Tue, 22 Feb 2022 23:47:05 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id n9-20020a05600c294900b00380f8be8ceesm632638wmd.20.2022.02.22.23.47.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:47:04 -0800 (PST) Message-Id: In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:52 +0000 Subject: [PATCH v6 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 75b57f8abab..628324646d3 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -59,6 +59,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]] OUTPUT ------ diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 767892006e3..b4f5c7e0aab 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; }; @@ -434,7 +435,7 @@ static int real_merge(struct merge_tree_options *o, * merge_incore_recursive in merge-ort.h */ merge_bases = get_merge_bases(parent1, parent2); - if (!merge_bases) + if (!merge_bases && !o->allow_unrelated_histories) die(_("refusing to merge unrelated histories")); merge_bases = reverse_commit_list(merge_bases); @@ -499,6 +500,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 22e03f0939c..bd1769c624b 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 Wed Feb 23 07:46: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: 12756525 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 EB71CC433FE for ; Wed, 23 Feb 2022 07:47:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238781AbiBWHsK (ORCPT ); Wed, 23 Feb 2022 02:48:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44196 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238759AbiBWHrf (ORCPT ); Wed, 23 Feb 2022 02:47:35 -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 BD7033584F for ; Tue, 22 Feb 2022 23:47:07 -0800 (PST) Received: by mail-wm1-x332.google.com with SMTP id l2-20020a7bc342000000b0037fa585de26so1898723wmj.1 for ; Tue, 22 Feb 2022 23:47: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=d5LUpEtsylubslKgfGvKWNGyvk65ye3p0n2yZ7hg8ZI=; b=prMEcr9HTwFPJxw1I7i60UcF+IOcOhFDTYhmRT9hQtM7D3/eUYjIGdLKH/VLtinH8C NhHmuRmzYgVwA8O/P2sUD4qv65917a5MubieeroAcayywmWxBfHEcrAletTkT54d4cYM UyXS+LaOxPPaKsOjCCl+27IcqYV7SRbK67pjlaIi+/dnaeiqpIBBZfluT41/kg3xv6kg Zu9y1NQ0D96YkNEZNgMwM2MAVfmR91kWkoS/36kQESPN5jljoNpmcYTIHwR5sbytu+X0 Dg2IS67WvHvVF4MRwxs3FdGeyofjftUgYbHC/lN5does8umbt5kVK3dcFjftFaaeZtXX cSqQ== 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=d5LUpEtsylubslKgfGvKWNGyvk65ye3p0n2yZ7hg8ZI=; b=UxOoZx3u3FQ9M589ke6t8Y8zZD9YnUsFGoiuXStVEYFcWAhiX/PtlxZ7Zr/tPgcIV5 LmyXkZ7HtyDbBfAsiMyut4BEjnRv7sjDj7SAffVwuSpYglOQ38yl+q0l/qKfKGX1mP60 w63VbtIKmyI2dATdvLcjw7xHJkAL3etXswDiz6R+ObwVZsZIoxfCKzr9Bt2DcqqEwtQ2 ircynaUTAqsZjy0+9M1vG87+Mb3icbme26Eo6GGy6iJkYBqkAh1l6URDwbiYChIRSVIK 7xwTLtvxuvv3A9c2f3Bd1J5oVBuf2NgmQ318BUsr7mhakus8WIdkHBeKlwig39ILeBzH arig== X-Gm-Message-State: AOAM532fjQqUQMd6ZUGbV4cccOWQP/DrcGanRo75Jg3hPzQoYSJaLStP IAoppzYj6cCMeoZclX8OGvjhf697OOI= X-Google-Smtp-Source: ABdhPJxE9YhC0HtvWB1oTVO/xzQNhw5sPjP830QIr5ZAnzmnGQYvleNNI9O2i4qqJL0hYgwf2nLQmw== X-Received: by 2002:a1c:7918:0:b0:37b:fab4:9b1 with SMTP id l24-20020a1c7918000000b0037bfab409b1mr6329103wme.40.1645602426186; Tue, 22 Feb 2022 23:47:06 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id b18sm47773753wrx.92.2022.02.22.23.47.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Feb 2022 23:47:05 -0800 (PST) Message-Id: In-Reply-To: References: Date: Wed, 23 Feb 2022 07:46:53 +0000 Subject: [PATCH v6 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 628324646d3..ee8125810e6 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -156,6 +156,52 @@ with linkgit:git-merge[1]: * 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. + [[DEPMERGE]] DEPRECATED DESCRIPTION ----------------------