From: Junio C Hamano <gitster@pobox.com>
To: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org, Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: Re: [PATCH] merge-tree: accept 3 trees as arguments
Date: Fri, 26 Jan 2024 08:01:38 -0800 [thread overview]
Message-ID: <xmqqplxoozh9.fsf@gitster.g> (raw)
In-Reply-To: <pull.1647.git.1706277694231.gitgitgadget@gmail.com> (Johannes Schindelin via GitGitGadget's message of "Fri, 26 Jan 2024 14:01:34 +0000")
"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:
> 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.
yes, Yes, YES, YEAHHHHH!
> I was asked to implement this at $dayjob and it seems like a feature
> that might be useful to other users, too.
Yup, I think it is an obvious building block for machinery to
perform any mergy operation to grow history. Many of the time you
may have a commit, but requiring them to be commits when you know
you will not do a virtual ancestor synthesis smells fundamentally
wrong. Thanks for fixing it.
> ---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
> +o specify commits; it is sufficient if they specify trees.
"... do not need to specify commits; trees are enough"?
> 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
OK. The changes here look quite straight-forward.
> diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh
> index 12ac4368736..71f21bb834f 100755
> --- a/t/t4301-merge-tree-write-tree.sh
> +++ b/t/t4301-merge-tree-write-tree.sh
> @@ -945,4 +945,12 @@ 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 >tree &&
> + tree=$(cat tree) &&
> + git merge-tree --merge-base=side1^^{tree} side1^{tree} side3^{tree} >tree2 &&
> + tree2=$(cat tree2) &&
> + test $tree = $tree2
> +'
You do not need $tree and $tree2 variables that would make it harder
to diagnose a failure case when we break merge-tree. You have tree
and tree2 as files, and I think it is sufficient to do
git merge-tree ... >result-from-commits &&
git merge-tree ... >result-from-trees &&
test_cmp result-from-commits result-from-trees
(no, I am not suggesting to rename these tree and tree2 files; I
just needed them to be descriptive in my illustration to show what
is going on to myself).
Thanks.
next prev parent reply other threads:[~2024-01-26 16:01 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 [this message]
2024-01-30 20:05 ` Johannes Schindelin
2024-01-28 20:34 ` [PATCH v2] " Johannes Schindelin via GitGitGadget
2024-01-29 17:49 ` 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=xmqqplxoozh9.fsf@gitster.g \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
--cc=gitgitgadget@gmail.com \
--cc=johannes.schindelin@gmx.de \
/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).