git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] rev-list --left-right

From
Junio C Hamano <junkio@cox.net>
Date
Oct 23, 2006, 04:47 UTC
Message-ID
<7v7iyrzlhn.fsf@assigned-by-dhcp.cox.net>

The output from "symmetric diff", i.e. A...B, does not distinguish between commits that are reachable from A and the ones that are reachable from B. In this picture, such a symmetric diff includes commits marked with a and b.

         x---b---b  branch B
        / \ /
       /   .
      /   / \
     o---x---a---a  branch A

However, you cannot tell which ones are 'a' and which ones are 'b' from the output. Sometimes this is frustrating. This adds an output option, --left-right, to rev-list.

        rev-list --left-right A...B

would show ones reachable from A prefixed with '<' and the ones reachable from B prefixed with '>'.

When combined with --boundary, boundary commits (the ones marked with 'x' in the above picture) are shown with prefix '-', so you would see list that looks like this:

    git rev-list --left-right --boundary --pretty=oneline A...B
    >bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3rd on b
    >bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 2nd on b
    <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3rd on a
    <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 2nd on a
    -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1st on b
    -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1st on a
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 * This lets you write something like git-cherry with a single
   invocation of rev-list instead of two.  We would need a diff
   format that gives patch-id in addition to this patch to make
   git-cherry more efficient though.
 builtin-rev-list.c |   11 +++++++++++
 commit.c           |   10 +++++-----
 revision.c         |    5 ++++-
 revision.h         |    1 +
 4 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index fb7fc92..4364035 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -45,6 +45,7 @@ static int bisect_list;
 static int show_timestamp;
 static int hdr_termination;
 static const char *header_prefix;
+static int show_left_right;
 
 static void show_commit(struct commit *commit)
 {
@@ -54,6 +55,12 @@ static void show_commit(struct commit *c
 		fputs(header_prefix, stdout);
 	if (commit->object.flags & BOUNDARY)
 		putchar('-');
+	else if (show_left_right) {
+		if (commit->object.flags & SYMMETRIC_LEFT)
+			putchar('<');
+		else
+			putchar('>');
+	}
 	if (revs.abbrev_commit && revs.abbrev)
 		fputs(find_unique_abbrev(commit->object.sha1, revs.abbrev),
 		      stdout);
@@ -240,6 +247,10 @@ int cmd_rev_list(int argc, const char **
 			bisect_list = 1;
 			continue;
 		}
+		if (!strcmp(arg, "--left-right")) {
+			show_left_right = 1;
+			continue;
+		}
 		if (!strcmp(arg, "--stdin")) {
 			if (read_from_stdin++)
 				die("--stdin given twice?");
diff --git a/commit.c b/commit.c
index a6d543e..289ef65 100644
--- a/commit.c
+++ b/commit.c
@@ -868,11 +868,11 @@ void sort_in_topological_order_fn(struct
 
 /* merge-rebase stuff */
 
-/* bits #0..7 in revision.h */
-#define PARENT1		(1u<< 8)
-#define PARENT2		(1u<< 9)
-#define STALE		(1u<<10)
-#define RESULT		(1u<<11)
+/* bits #0..15 in revision.h */
+#define PARENT1		(1u<<16)
+#define PARENT2		(1u<<17)
+#define STALE		(1u<<18)
+#define RESULT		(1u<<19)
 
 static struct commit *interesting(struct commit_list *list)
 {
diff --git a/revision.c b/revision.c
index f1e0caa..26ddf09 100644
--- a/revision.c
+++ b/revision.c
@@ -344,6 +344,7 @@ static void try_to_simplify_commit(struc
 static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)
 {
 	struct commit_list *parent = commit->parents;
+	unsigned left_flag;
 
 	if (commit->object.flags & ADDED)
 		return;
@@ -388,6 +389,7 @@ static void add_parents_to_list(struct r
 	if (revs->no_walk)
 		return;
 
+	left_flag = (commit->object.flags & SYMMETRIC_LEFT);
 	parent = commit->parents;
 	while (parent) {
 		struct commit *p = parent->item;
@@ -395,6 +397,7 @@ static void add_parents_to_list(struct r
 		parent = parent->next;
 
 		parse_commit(p);
+		p->object.flags |= left_flag;
 		if (p->object.flags & SEEN)
 			continue;
 		p->object.flags |= SEEN;
@@ -643,7 +646,7 @@ int handle_revision_arg(const char *arg,
 				add_pending_commit_list(revs, exclude,
 							flags_exclude);
 				free_commit_list(exclude);
-				a->object.flags |= flags;
+				a->object.flags |= flags | SYMMETRIC_LEFT;
 			} else
 				a->object.flags |= flags_exclude;
 			b->object.flags |= flags;
diff --git a/revision.h b/revision.h
index 3adab95..f92a4d4 100644
--- a/revision.h
+++ b/revision.h
@@ -9,6 +9,7 @@ #define TMP_MARK	(1u<<4) /* for isolated
 #define BOUNDARY	(1u<<5)
 #define BOUNDARY_SHOW	(1u<<6)
 #define ADDED		(1u<<7)	/* Parents already parsed and added? */
+#define SYMMETRIC_LEFT	(1u<<8)
 
 struct rev_info;
 struct log_info;
-- 
1.4.3.1.g7ad4
Message 1 of 1 in “rev-list --left-right”
  1. rev-list --left-rightJunio C Hamano, Oct 23, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.