On Wed, Feb 2, 2022 at 1:22 PM Junio C Hamano <gitster@xxxxxxxxx> wrote: > > "Elijah Newren via GitGitGadget" <gitgitgadget@xxxxxxxxx> writes: > > > @@ -392,7 +395,46 @@ struct merge_tree_options { > > static int real_merge(struct merge_tree_options *o, > > const char *branch1, const char *branch2) > > { > > - die(_("real merges are not yet implemented")); > > + struct commit *parent1, *parent2; > > + struct commit_list *common; > > + struct commit_list *merge_bases = NULL; > > + struct commit_list *j; > > + struct merge_options opt; > > + struct merge_result result = { 0 }; > > + > > + parent1 = get_merge_parent(branch1); > > + if (!parent1) > > + help_unknown_ref(branch1, "merge-tree", > > + _("not something we can merge")); > > + > > + parent2 = get_merge_parent(branch2); > > + if (!parent2) > > + help_unknown_ref(branch2, "merge-tree", > > + _("not something we can merge")); > > + > > + init_merge_options(&opt, the_repository); > > + > > + opt.show_rename_progress = 0; > > + > > + opt.branch1 = branch1; > > + opt.branch2 = branch2; > > + > > + /* > > + * Get the merge bases, in reverse order; see comment above > > + * merge_incore_recursive in merge-ort.h > > + */ > > + common = get_merge_bases(parent1, parent2); > > + if (!common) > > + die(_("refusing to merge unrelated histories")); > > It appears to me that "merge-tree" in this mode, with the above > code, cannot be used as a workhorse to implement server-side > cherry-pick (or revert), which needs to allow the user to specify an > arbitrary "common ancestor", instead of computing on its own. > > To replay the change made by commit A on top of commit X (i.e. > "cherry-pick A on X"), we have to be able to say "compute the > three-way merge between A and X, pretending as if A^ were their > common ancestor". The story is the same for revert---we compute > three-way merge between A^ and X, pretending as if A were their > common ancestor. > > The above interface into this function, sadly, does not seem to > allow such a request, unless I am missing something. > > And if I am correct, it is a shame---after all, the point of the > merge-trees command is to take three trees and run a three-way > merge, and not being able to merge three "trees" and require > "commits" makes this mode much less useful than its potential. Yes, you are reading right. I think the cherry-pick/rebase replacement actually deserves a separate command from what merges should use; replaying a sequence of commits just has a number of UI differences and abilities that I think pull it in a different direction. I didn't want to wait and submit everything all at once (this series is long enough), and I figured that providing the in-core equivalent to `git merge` was a simpler first step worth submitting first before later providing the in-core equivalents to `git rebase/git cherry-pick`. (Also, I'm a bit wary of providing a command meant to just do a single three-way merge with a defined merge-base, because that seems to be a path towards returning to a scripted rebase. Having a way to do only a single such special merge is fine but we should avoid encouraging people to go down that route.)