git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Christian Couder <chriscool@tuxfamily.org>
Cc: git@vger.kernel.org,
	Johannes Schindelin <Johannes.Schindelin@gmx.de>,
	Miklos Vajna <vmiklos@frugalware.org>
Subject: Re: [RFC/PATCH v2] merge-base: teach "git merge-base" to accept more than 2 arguments
Date: Sat, 26 Jul 2008 21:47:34 -0700	[thread overview]
Message-ID: <7vabg43pcp.fsf@gitster.siamese.dyndns.org> (raw)
In-Reply-To: <20080727053324.b54fe48e.chriscool@tuxfamily.org> (Christian Couder's message of "Sun, 27 Jul 2008 05:33:24 +0200")

Christian Couder <chriscool@tuxfamily.org> writes:

>  OPTIONS
>  -------
>  --all::
> -	Output all common ancestors for the two commits instead of
> -	just one.
> +	Output all merge bases for the commits instead of just one. No
> +	merge bases in the output should be an ancestor of another
> +	merge base in the output. Each common ancestor of the first
> +	commit and any of the other commits passed as arguments,
> +	should be an ancestor of one of the merge bases in the output.

The point of merge_bases_many() is that it allows you to compute a merge
base between a commit and another commit that does not yet exist which is
a merge across all others.

               o---o---o---o---C
              /                 :
             /   o---o---o---B..(M)
            /   /                 :
	---o---*---o---o---o---A..(X)

Suppose you have commits A, B and C, and you would want to come up with an
Octopus merge X across these three commits.  Because our low-level merge
machinery works always on two trees with one common ancestor tree, we
would first create a tree that is a merge between B and C (which is marked
as (M) in the picture), and then merge the tree of (M) and A using common
ancestor between (M) and A.

If we did not have merge_bases_many(), we would actually create (M) as a
real commit, and compute merge base between A and (M), which is marked as
"*" in the picture.  The use of merge_bases_many() allows us to run the
same merge base computation without actually creating commit (M).  Instead
of computing merge-base between A and (M), you can ask for the merge base
between A ("the first commit") and B, C ("the other commits") to obtain
the same answer "*".

Base between A and B is that "*", and you are correct to say that it is an
ancestor of the "*" that is output from the command; base between A and C
is the parent of "*", and again you are correct to say it is ancestor of
the "*" that is output from the command.

But if we output any other commit between "*" and A from the command, it
still satisifies your condition.  "The merge base between A and each of B,
C,... should be an ancestor of what is output".  In order to satisify your
condition, in the extreme case, we could even output A.  Both the merge
base between A and B, and the merge base between A and C, would be an
ancestor of A.

So your description may not be incorrect, but I think it completely misses
the point of what is being computed.

>  Author
>  ------
> diff --git a/builtin-merge-base.c b/builtin-merge-base.c
> index 1cb2925..f2c9756 100644
> --- a/builtin-merge-base.c
> +++ b/builtin-merge-base.c
> @@ -2,9 +2,11 @@
>  #include "cache.h"
>  #include "commit.h"
>  
> -static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_all)
> +static int show_merge_base(struct commit *rev1, int prev2_nr,
> +			   struct commit **prev2, int show_all)
>  {
> -	struct commit_list *result = get_merge_bases(rev1, rev2, 0);
> +	struct commit_list *result = get_merge_bases_many(rev1, prev2_nr,
> +							  prev2, 0);

This is just style, but if you must break lines somewhere, I'd prefer to
have prev2_nr and prev2 on the same line, like this:

	struct commit_list *result = get_merge_bases_many(rev1,
							  prev2_nr, prev2, 0);

because they logically belong to each other.  Further, I think this
84-column single-line statement is perfectly fine as well in this case:

	struct commit_list *result = get_merge_bases_many(rev1, prev2_nr, prev2, 0);

I would probably do this myself in this case, though:

	struct commit_list *result;

	result  = get_merge_bases_many(rev1, prev2_nr, prev2, 0);

  reply	other threads:[~2008-07-27  4:49 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-27  3:33 [RFC/PATCH v2] merge-base: teach "git merge-base" to accept more than 2 arguments Christian Couder
2008-07-27  4:47 ` Junio C Hamano [this message]
2008-07-28  6:10   ` Christian Couder
2008-07-28  6:18     ` Junio C Hamano
2008-07-27 14:38 ` Johannes Schindelin
2008-07-27 15:28   ` Miklos Vajna
2008-07-27 18:11   ` Junio C Hamano
2008-07-27 20:44     ` Johannes Schindelin
2008-07-27 20:47     ` Re* " Junio C Hamano
2008-07-28  5:49   ` Christian Couder
2008-07-27 15:02 ` Jakub Narebski

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=7vabg43pcp.fsf@gitster.siamese.dyndns.org \
    --to=gitster@pobox.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=chriscool@tuxfamily.org \
    --cc=git@vger.kernel.org \
    --cc=vmiklos@frugalware.org \
    /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).