git-log --cherry-pick A...B

This is meant to be a saner replacement for "git-cherry".

When used with "A...B", this filters out commits whose patch
text has the same patch-id as a commit on the other side.  It
would probably most useful to use with --left-right.

Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Junio C Hamano 2007-04-09 03:40:38 -07:00
parent 5d23e133d2
commit d7a17cad97
2 changed files with 89 additions and 0 deletions

View File

@ -8,6 +8,7 @@
#include "revision.h" #include "revision.h"
#include "grep.h" #include "grep.h"
#include "reflog-walk.h" #include "reflog-walk.h"
#include "patch-ids.h"
static char *path_name(struct name_path *path, const char *name) static char *path_name(struct name_path *path, const char *name)
{ {
@ -422,6 +423,86 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st
} }
} }
static void cherry_pick_list(struct commit_list *list)
{
struct commit_list *p;
int left_count = 0, right_count = 0;
int left_first;
struct patch_ids ids;
/* First count the commits on the left and on the right */
for (p = list; p; p = p->next) {
struct commit *commit = p->item;
unsigned flags = commit->object.flags;
if (flags & BOUNDARY)
;
else if (flags & SYMMETRIC_LEFT)
left_count++;
else
right_count++;
}
left_first = left_count < right_count;
init_patch_ids(&ids);
/* Compute patch-ids for one side */
for (p = list; p; p = p->next) {
struct commit *commit = p->item;
unsigned flags = commit->object.flags;
if (flags & BOUNDARY)
continue;
/*
* If we have fewer left, left_first is set and we omit
* commits on the right branch in this loop. If we have
* fewer right, we skip the left ones.
*/
if (left_first != !!(flags & SYMMETRIC_LEFT))
continue;
commit->util = add_commit_patch_id(commit, &ids);
}
/* Check the other side */
for (p = list; p; p = p->next) {
struct commit *commit = p->item;
struct patch_id *id;
unsigned flags = commit->object.flags;
if (flags & BOUNDARY)
continue;
/*
* If we have fewer left, left_first is set and we omit
* commits on the left branch in this loop.
*/
if (left_first == !!(flags & SYMMETRIC_LEFT))
continue;
/*
* Have we seen the same patch id?
*/
id = has_commit_patch_id(commit, &ids);
if (!id)
continue;
id->seen = 1;
commit->object.flags |= SHOWN;
}
/* Now check the original side for seen ones */
for (p = list; p; p = p->next) {
struct commit *commit = p->item;
struct patch_id *ent;
ent = commit->util;
if (!ent)
continue;
if (ent->seen)
commit->object.flags |= SHOWN;
commit->util = NULL;
}
free_patch_ids(&ids);
}
static void limit_list(struct rev_info *revs) static void limit_list(struct rev_info *revs)
{ {
struct commit_list *list = revs->commits; struct commit_list *list = revs->commits;
@ -449,6 +530,9 @@ static void limit_list(struct rev_info *revs)
continue; continue;
p = &commit_list_insert(commit, p)->next; p = &commit_list_insert(commit, p)->next;
} }
if (revs->cherry_pick)
cherry_pick_list(newlist);
revs->commits = newlist; revs->commits = newlist;
} }
@ -913,6 +997,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->left_right = 1; revs->left_right = 1;
continue; continue;
} }
if (!strcmp(arg, "--cherry-pick")) {
revs->cherry_pick = 1;
continue;
}
if (!strcmp(arg, "--objects")) { if (!strcmp(arg, "--objects")) {
revs->tag_objects = 1; revs->tag_objects = 1;
revs->tree_objects = 1; revs->tree_objects = 1;

View File

@ -47,6 +47,7 @@ struct rev_info {
left_right:1, left_right:1,
parents:1, parents:1,
reverse:1, reverse:1,
cherry_pick:1,
first_parent_only:1; first_parent_only:1;
/* Diff flags */ /* Diff flags */