From: Christian Couder <chriscool@tuxfamily.org>
To: git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>,
Johannes Schindelin <Johannes.Schindelin@gmx.de>
Cc: Miklos Vajna <vmiklos@frugalware.org>, Jakub Narebski <jnareb@gmail.com>
Subject: [RFC/PATCH v3] merge-base: teach "git merge-base" to accept more than 2 arguments
Date: Mon, 28 Jul 2008 06:50:23 +0200 [thread overview]
Message-ID: <20080728065023.743930d6.chriscool@tuxfamily.org> (raw)
Before this patch "git merge-base" accepted only 2 arguments, so
only merge bases between 2 references could be computed.
The purpose of this patch is to make "git merge-base" accept more
than 2 arguments, so that the merge bases between the first given
reference and all the other references can be computed.
This is easily implemented because the "get_merge_bases_many"
function in "commit.c" already implements the needed computation.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Documentation/git-merge-base.txt | 27 +++++++++++++++--------
builtin-merge-base.c | 43 ++++++++++++++++++++++++-------------
commit.h | 2 +
3 files changed, 48 insertions(+), 24 deletions(-)
I only changed the code (according to what Dscho asked) not the
documentation in this version as I had not much time and I need
to think more about it.
diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt
index 1a7ecbf..463c230 100644
--- a/Documentation/git-merge-base.txt
+++ b/Documentation/git-merge-base.txt
@@ -8,26 +8,35 @@ git-merge-base - Find as good common ancestors as possible for a merge
SYNOPSIS
--------
-'git merge-base' [--all] <commit> <commit>
+'git merge-base' [--all] <commit> <commit>...
DESCRIPTION
-----------
-'git-merge-base' finds as good a common ancestor as possible between
-the two commits. That is, given two commits A and B, `git merge-base A
-B` will output a commit which is reachable from both A and B through
-the parent relationship.
+'git-merge-base' finds as good common ancestors as possible between
+the first commit and the other commits. The default behavior is to
+output only one as good as possible common ancestor, called a merge
+base.
+
+For example, given two commits A and B, `git merge-base A B` will
+output a commit which is reachable from both A and B through the
+parent relationship.
+
+Given three commits A, B and C, `git merge-base A B C` will output a
+commit which is reachable through the parent relationship from both A
+and B, or from both A and C.
Given a selection of equally good common ancestors it should not be
relied on to decide in any particular way.
-The 'git-merge-base' algorithm is still in flux - use the source...
-
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.
Author
------
diff --git a/builtin-merge-base.c b/builtin-merge-base.c
index 1cb2925..881363f 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 **rev, int rev_nr, int show_all)
{
- struct commit_list *result = get_merge_bases(rev1, rev2, 0);
+ struct commit_list *result;
+
+ result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1, 0);
if (!result)
return 1;
@@ -20,13 +22,21 @@ static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_al
}
static const char merge_base_usage[] =
-"git merge-base [--all] <commit-id> <commit-id>";
+"git merge-base [--all] <commit-id> <commit-id>...";
+
+static struct commit *get_commit_reference(const char *arg)
+{
+ unsigned char revkey[20];
+ if (get_sha1(arg, revkey))
+ die("Not a valid object name %s", arg);
+ return lookup_commit_reference(revkey);
+}
int cmd_merge_base(int argc, const char **argv, const char *prefix)
{
- struct commit *rev1, *rev2;
- unsigned char rev1key[20], rev2key[20];
+ struct commit **rev;
int show_all = 0;
+ int rev_nr = 0;
git_config(git_default_config, NULL);
@@ -38,15 +48,18 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
usage(merge_base_usage);
argc--; argv++;
}
- if (argc != 3)
+ if (argc < 3)
usage(merge_base_usage);
- if (get_sha1(argv[1], rev1key))
- die("Not a valid object name %s", argv[1]);
- if (get_sha1(argv[2], rev2key))
- die("Not a valid object name %s", argv[2]);
- rev1 = lookup_commit_reference(rev1key);
- rev2 = lookup_commit_reference(rev2key);
- if (!rev1 || !rev2)
- return 1;
- return show_merge_base(rev1, rev2, show_all);
+
+ rev = xmalloc((argc - 1) * sizeof(*rev));
+
+ do {
+ struct commit *r = get_commit_reference(argv[1]);
+ if (!r)
+ return 1;
+ rev[rev_nr++] = r;
+ argc--; argv++;
+ } while (argc > 1);
+
+ return show_merge_base(rev, rev_nr, show_all);
}
diff --git a/commit.h b/commit.h
index 77de962..4829a5c 100644
--- a/commit.h
+++ b/commit.h
@@ -121,6 +121,8 @@ int read_graft_file(const char *graft_file);
struct commit_graft *lookup_commit_graft(const unsigned char *sha1);
extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);
+extern struct commit_list *get_merge_bases_many(struct commit *one,
+ int n, struct commit **twos, int cleanup);
extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
extern int register_shallow(const unsigned char *sha1);
--
1.6.0.rc0.43.g00eb.dirty
next reply other threads:[~2008-07-28 4:47 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-28 4:50 Christian Couder [this message]
2008-07-28 5:37 ` [RFC/PATCH v3] merge-base: teach "git merge-base" to accept more than 2 arguments Junio C Hamano
2008-07-29 5:24 ` Christian Couder
2008-07-28 5:46 ` Junio C Hamano
2008-07-28 11:33 ` Johannes Schindelin
2008-07-30 4:52 ` Christian Couder
2008-07-30 13:51 ` Johannes Schindelin
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=20080728065023.743930d6.chriscool@tuxfamily.org \
--to=chriscool@tuxfamily.org \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jnareb@gmail.com \
--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).