From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Eric Sunshine <sunshine@sunshineco.com>,
Johannes Schindelin <johannes.schindelin@gmx.de>,
Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH v2] merge-tree: accept 3 trees as arguments
Date: Sun, 28 Jan 2024 20:34:22 +0000 [thread overview]
Message-ID: <pull.1647.v2.git.1706474063109.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1647.git.1706277694231.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
When specifying a merge base explicitly, there is actually no good
reason why the inputs need to be commits: that's only needed if the
merge base has to be deduced from the commit graph.
This commit is best viewed with `--color-moved
--color-moved-ws=allow-indentation-change`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
merge-tree: accept 3 trees as arguments
I was asked to implement this at $dayjob and it seems like a feature
that might be useful to other users, too.
Changes since v1:
* Fixed a typo in the manual page, simplified the part after the
semicolon.
* Simplified the test case.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1647%2Fdscho%2Fallow-merge-tree-to-accept-3-trees-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1647/dscho/allow-merge-tree-to-accept-3-trees-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1647
Range-diff vs v1:
1: 29234754c06 ! 1: 233a25e9071 merge-tree: accept 3 trees as arguments
@@ Documentation/git-merge-tree.txt: OPTIONS
currently not supported. This option is incompatible with `--stdin`.
++
+As the merge-base is provided directly, <branch1> and <branch2> do not need
-+o specify commits; it is sufficient if they specify trees.
++to specify commits; trees are enough.
[[OUTPUT]]
OUTPUT
@@ t/t4301-merge-tree-write-tree.sh: test_expect_success 'check the input format wh
'
+test_expect_success '--merge-base with tree OIDs' '
-+ git merge-tree --merge-base=side1^ side1 side3 >tree &&
-+ tree=$(cat tree) &&
-+ git merge-tree --merge-base=side1^^{tree} side1^{tree} side3^{tree} >tree2 &&
-+ tree2=$(cat tree2) &&
-+ test $tree = $tree2
++ git merge-tree --merge-base=side1^ side1 side3 >with-commits &&
++ git merge-tree --merge-base=side1^^{tree} side1^{tree} side3^{tree} >with-trees &&
++ test_cmp with-commits with-trees
+'
+
test_done
Documentation/git-merge-tree.txt | 5 +++-
builtin/merge-tree.c | 42 +++++++++++++++++++-------------
t/t4301-merge-tree-write-tree.sh | 6 +++++
3 files changed, 35 insertions(+), 18 deletions(-)
diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt
index b50acace3bc..dd388fa21d5 100644
--- a/Documentation/git-merge-tree.txt
+++ b/Documentation/git-merge-tree.txt
@@ -64,10 +64,13 @@ OPTIONS
share no common history. This flag can be given to override that
check and make the merge proceed anyway.
---merge-base=<commit>::
+--merge-base=<tree-ish>::
Instead of finding the merge-bases for <branch1> and <branch2>,
specify a merge-base for the merge, and specifying multiple bases is
currently not supported. This option is incompatible with `--stdin`.
++
+As the merge-base is provided directly, <branch1> and <branch2> do not need
+to specify commits; trees are enough.
[[OUTPUT]]
OUTPUT
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 3bdec53fbe5..cbd8e15af6d 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -429,35 +429,43 @@ static int real_merge(struct merge_tree_options *o,
struct merge_options opt;
copy_merge_options(&opt, &o->merge_options);
- 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"));
-
opt.show_rename_progress = 0;
opt.branch1 = branch1;
opt.branch2 = branch2;
if (merge_base) {
- struct commit *base_commit;
struct tree *base_tree, *parent1_tree, *parent2_tree;
- base_commit = lookup_commit_reference_by_name(merge_base);
- if (!base_commit)
- die(_("could not lookup commit '%s'"), merge_base);
+ /*
+ * We actually only need the trees because we already
+ * have a merge base.
+ */
+ struct object_id base_oid, head_oid, merge_oid;
+
+ if (repo_get_oid_treeish(the_repository, merge_base, &base_oid))
+ die(_("could not parse as tree '%s'"), merge_base);
+ base_tree = parse_tree_indirect(&base_oid);
+ if (repo_get_oid_treeish(the_repository, branch1, &head_oid))
+ die(_("could not parse as tree '%s'"), branch1);
+ parent1_tree = parse_tree_indirect(&head_oid);
+ if (repo_get_oid_treeish(the_repository, branch2, &merge_oid))
+ die(_("could not parse as tree '%s'"), branch2);
+ parent2_tree = parse_tree_indirect(&merge_oid);
opt.ancestor = merge_base;
- base_tree = repo_get_commit_tree(the_repository, base_commit);
- parent1_tree = repo_get_commit_tree(the_repository, parent1);
- parent2_tree = repo_get_commit_tree(the_repository, parent2);
merge_incore_nonrecursive(&opt, base_tree, parent1_tree, parent2_tree, &result);
} else {
+ 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"));
+
/*
* Get the merge bases, in reverse order; see comment above
* merge_incore_recursive in merge-ort.h
diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh
index 12ac4368736..c5628c4e613 100755
--- a/t/t4301-merge-tree-write-tree.sh
+++ b/t/t4301-merge-tree-write-tree.sh
@@ -945,4 +945,10 @@ test_expect_success 'check the input format when --stdin is passed' '
test_cmp expect actual
'
+test_expect_success '--merge-base with tree OIDs' '
+ git merge-tree --merge-base=side1^ side1 side3 >with-commits &&
+ git merge-tree --merge-base=side1^^{tree} side1^{tree} side3^{tree} >with-trees &&
+ test_cmp with-commits with-trees
+'
+
test_done
base-commit: e02ecfcc534e2021aae29077a958dd11c3897e4c
--
gitgitgadget
next prev parent reply other threads:[~2024-01-28 20:34 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-26 14:01 [PATCH] merge-tree: accept 3 trees as arguments Johannes Schindelin via GitGitGadget
2024-01-26 14:15 ` Eric Sunshine
2024-01-26 16:01 ` Junio C Hamano
2024-01-30 20:05 ` Johannes Schindelin
2024-01-28 20:34 ` Johannes Schindelin via GitGitGadget [this message]
2024-01-29 17:49 ` [PATCH v2] " Junio C Hamano
2024-01-30 7:04 ` [PATCH] " Elijah Newren
2024-01-30 17:15 ` Junio C Hamano
2024-01-31 16:34 ` Elijah Newren
2024-01-31 18:14 ` Junio C Hamano
2024-01-30 20:04 ` Johannes Schindelin
2024-01-31 16:40 ` Elijah Newren
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.1647.v2.git.1706474063109.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=johannes.schindelin@gmx.de \
--cc=sunshine@sunshineco.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).