From 60adf7d73e44126289a98dada60f9c335ffc84b0 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Mon, 21 Feb 2011 17:09:11 +0100 Subject: [PATCH 01/10] revlist.c: introduce --left/right-only for unsymmetric picking The existing "--cherry-pick" does not work with unsymmetric ranges (A..B) for obvious reasons. Introduce "--left-only" and "--right-only" which limit the output to commits on the respective sides of a symmetric range (i.e. only "<" resp. ">" commits as per "--left-right"). This is especially useful for things like git log --cherry-pick --right-only @{u}... which is much more flexible (and descriptive) than git cherry @{u} | sed -ne 's/^+ //p' and potentially more useful than git log --cherry-pick @{u}... Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- revision.c | 24 ++++++++++++++++++++++++ revision.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/revision.c b/revision.c index 7b9eaefae4ed03..0681c7c309a81f 100644 --- a/revision.c +++ b/revision.c @@ -733,6 +733,23 @@ static struct commit_list *collect_bottom_commits(struct commit_list *list) return bottom; } +/* Assumes either left_only or right_only is set */ +static void limit_left_right(struct commit_list *list, struct rev_info *revs) +{ + struct commit_list *p; + + for (p = list; p; p = p->next) { + struct commit *commit = p->item; + + if (revs->right_only) { + if (commit->object.flags & SYMMETRIC_LEFT) + commit->object.flags |= SHOWN; + } else /* revs->left_only is set */ + if (!(commit->object.flags & SYMMETRIC_LEFT)) + commit->object.flags |= SHOWN; + } +} + static int limit_list(struct rev_info *revs) { int slop = SLOP; @@ -788,6 +805,9 @@ static int limit_list(struct rev_info *revs) if (revs->cherry_pick) cherry_pick_list(newlist, revs); + if (revs->left_only || revs->right_only) + limit_left_right(newlist, revs); + if (bottom) { limit_to_ancestry(bottom, newlist); free_commit_list(bottom); @@ -1263,6 +1283,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->boundary = 1; } else if (!strcmp(arg, "--left-right")) { revs->left_right = 1; + } else if (!strcmp(arg, "--left-only")) { + revs->left_only = 1; + } else if (!strcmp(arg, "--right-only")) { + revs->right_only = 1; } else if (!strcmp(arg, "--count")) { revs->count = 1; } else if (!strcmp(arg, "--cherry-pick")) { diff --git a/revision.h b/revision.h index 05659c64acd7fe..d2ffde1ce67a55 100644 --- a/revision.h +++ b/revision.h @@ -59,6 +59,8 @@ struct rev_info { boundary:2, count:1, left_right:1, + left_only:1, + right_only:1, rewrite_parents:1, print_parents:1, show_source:1, From e0b9c34f7eec9d7943bbb8a3134f24e6e4e4ed3e Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Fri, 18 Feb 2011 13:34:19 +0100 Subject: [PATCH 02/10] t6007: Make sure we test --cherry-pick Test 5 wants to test --cherry-pick but limits by pathspec in such a way that there are no commits on the left side of the range. Add a test without "--cherry-pick" which displays this, and add two more commits and another test which tests what we're after. This also shortens the last test. Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- t/t6007-rev-list-cherry-pick-file.sh | 49 +++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh index b565638e92655c..64b72a3e209b16 100755 --- a/t/t6007-rev-list-cherry-pick-file.sh +++ b/t/t6007-rev-list-cherry-pick-file.sh @@ -4,13 +4,14 @@ test_description='test git rev-list --cherry-pick -- file' . ./test-lib.sh -# A---B +# A---B---D # \ # \ -# C +# C---E # # B changes a file foo.c, adding a line of text. C changes foo.c as # well as bar.c, but the change in foo.c was identical to change B. +# D and C change bar in the same way, E differently. test_expect_success setup ' echo Hallo > foo && @@ -25,11 +26,21 @@ test_expect_success setup ' test_tick && git commit -m "C" && git tag C && + echo Dello > bar && + git add bar && + test_tick && + git commit -m "E" && + git tag E && git checkout master && git checkout branch foo && test_tick && git commit -m "B" && - git tag B + git tag B && + echo Cello > bar && + git add bar && + test_tick && + git commit -m "D" && + git tag D ' cat >expect <expect <tags/C +EOF + test_expect_success '--cherry-pick bar does not come up empty' ' - ! test -z "$(git rev-list --left-right --cherry-pick B...C -- bar)" + git rev-list --left-right --cherry-pick B...C -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +test_expect_success 'bar does not come up empty' ' + git rev-list --left-right B...C -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +cat >expect <tags/E +EOF + +test_expect_success '--cherry-pick bar does not come up empty (II)' ' + git rev-list --left-right --cherry-pick D...E -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect ' test_expect_success '--cherry-pick with independent, but identical branches' ' @@ -75,11 +111,8 @@ cat >expect < actual && + git rev-list --count --left-right C...D > actual && test_cmp expect actual ' From 59c8afdf475d2b072fb63383df9f62afd2b3b1ee Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Mon, 21 Feb 2011 17:09:12 +0100 Subject: [PATCH 03/10] rev-list: documentation and test for --left/right-only Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- Documentation/git-rev-list.txt | 2 ++ Documentation/rev-list-options.txt | 13 +++++++++++ t/t6007-rev-list-cherry-pick-file.sh | 32 ++++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index 8e1e32908c31dd..5f47a13d3c6191 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -31,6 +31,8 @@ SYNOPSIS [ \--parents ] [ \--timestamp ] [ \--left-right ] + [ \--left-only ] + [ \--right-only ] [ \--cherry-pick ] [ \--encoding[=] ] [ \--(author|committer|grep)= ] diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 44a2ef1de15bdc..cebba62239ad88 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -319,6 +319,19 @@ from the other branch (for example, "3rd on b" may be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output. +--left-only:: +--right-only:: + + List only commits on the respective side of a symmetric range, + i.e. only those which would be marked `<` resp. `>` by + `--left-right`. ++ +For example, `--cherry-pick --right-only A...B` omits those +commits from `B` which are in `A` or are patch-equivalent to a commit in +`A`. In other words, this lists the `{plus}` commits from `git cherry A B`. +More precisely, `--cherry-pick --right-only --no-merges` gives the exact +list. + -g:: --walk-reflogs:: diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh index 64b72a3e209b16..cd089a913bb93a 100755 --- a/t/t6007-rev-list-cherry-pick-file.sh +++ b/t/t6007-rev-list-cherry-pick-file.sh @@ -4,14 +4,14 @@ test_description='test git rev-list --cherry-pick -- file' . ./test-lib.sh -# A---B---D +# A---B---D---F # \ # \ # C---E # # B changes a file foo.c, adding a line of text. C changes foo.c as # well as bar.c, but the change in foo.c was identical to change B. -# D and C change bar in the same way, E differently. +# D and C change bar in the same way, E and F differently. test_expect_success setup ' echo Hallo > foo && @@ -40,7 +40,12 @@ test_expect_success setup ' git add bar && test_tick && git commit -m "D" && - git tag D + git tag D && + echo Nello > bar && + git add bar && + test_tick && + git commit -m "F" && + git tag F ' cat >expect <expect <tags/E EOF test_expect_success '--cherry-pick bar does not come up empty (II)' ' - git rev-list --left-right --cherry-pick D...E -- bar > actual && + git rev-list --left-right --cherry-pick F...E -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +cat >expect < actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +test_expect_success '--cherry-pick --left-only' ' + git rev-list --cherry-pick --left-only E...F -- bar > actual && git name-rev --stdin --name-only --refs="*tags/*" \ < actual > actual.named && test_cmp actual.named expect From 24852d917104e294726c54803d5c9012997506ca Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 21 Feb 2011 16:58:37 -0800 Subject: [PATCH 04/10] rev-list: --left/right-only are mutually exclusive Signed-off-by: Junio C Hamano --- revision.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/revision.c b/revision.c index 0681c7c309a81f..1fcaeb79024665 100644 --- a/revision.c +++ b/revision.c @@ -1284,8 +1284,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg } else if (!strcmp(arg, "--left-right")) { revs->left_right = 1; } else if (!strcmp(arg, "--left-only")) { + if (revs->right_only) + die("--left-only is incompatible with --right-only"); revs->left_only = 1; } else if (!strcmp(arg, "--right-only")) { + if (revs->left_only) + die("--right-only is incompatible with --left-only"); revs->right_only = 1; } else if (!strcmp(arg, "--count")) { revs->count = 1; From 1df2d656cc442dc057e30b6fb130967e5ae19654 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Mon, 7 Mar 2011 13:31:39 +0100 Subject: [PATCH 05/10] rev-list/log: factor out revision mark generation Currently, we have identical code for generating revision marks ('<', '>', '-') in 5 places. Factor out the code to a single function get_revision_mark() for easier maintenance and extensibility. Note that the check for !!revs in graph.c (which gets removed effectively by this patch) is superfluous. Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- builtin/rev-list.c | 14 ++------------ graph.c | 17 ++--------------- log-tree.c | 28 ++++------------------------ pretty.c | 6 +----- revision.c | 16 ++++++++++++++++ revision.h | 1 + 6 files changed, 26 insertions(+), 56 deletions(-) diff --git a/builtin/rev-list.c b/builtin/rev-list.c index ba27d39f977f28..f458cb7587c7d4 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -64,18 +64,8 @@ static void show_commit(struct commit *commit, void *data) if (info->header_prefix) fputs(info->header_prefix, stdout); - if (!revs->graph) { - if (commit->object.flags & BOUNDARY) - putchar('-'); - else if (commit->object.flags & UNINTERESTING) - putchar('^'); - else if (revs->left_right) { - if (commit->object.flags & SYMMETRIC_LEFT) - putchar('<'); - else - putchar('>'); - } - } + if (!revs->graph) + fputs(get_revision_mark(revs, commit), stdout); if (revs->abbrev_commit && revs->abbrev) fputs(find_unique_abbrev(commit->object.sha1, revs->abbrev), stdout); diff --git a/graph.c b/graph.c index f1a63c2241a30c..ef2e24e85a41dc 100644 --- a/graph.c +++ b/graph.c @@ -798,22 +798,9 @@ static void graph_output_commit_char(struct git_graph *graph, struct strbuf *sb) } /* - * If revs->left_right is set, print '<' for commits that - * come from the left side, and '>' for commits from the right - * side. + * get_revision_mark() handles all other cases without assert() */ - if (graph->revs && graph->revs->left_right) { - if (graph->commit->object.flags & SYMMETRIC_LEFT) - strbuf_addch(sb, '<'); - else - strbuf_addch(sb, '>'); - return; - } - - /* - * Print '*' in all other cases - */ - strbuf_addch(sb, '*'); + strbuf_addstr(sb, get_revision_mark(graph->revs, graph->commit)); } /* diff --git a/log-tree.c b/log-tree.c index b46ed3baef7d9d..12570403110cf5 100644 --- a/log-tree.c +++ b/log-tree.c @@ -380,18 +380,8 @@ void show_log(struct rev_info *opt) if (!opt->verbose_header) { graph_show_commit(opt->graph); - if (!opt->graph) { - if (commit->object.flags & BOUNDARY) - putchar('-'); - else if (commit->object.flags & UNINTERESTING) - putchar('^'); - else if (opt->left_right) { - if (commit->object.flags & SYMMETRIC_LEFT) - putchar('<'); - else - putchar('>'); - } - } + if (!opt->graph) + fputs(get_revision_mark(opt, commit), stdout); fputs(find_unique_abbrev(commit->object.sha1, abbrev_commit), stdout); if (opt->print_parents) show_parents(commit, abbrev_commit); @@ -448,18 +438,8 @@ void show_log(struct rev_info *opt) if (opt->commit_format != CMIT_FMT_ONELINE) fputs("commit ", stdout); - if (!opt->graph) { - if (commit->object.flags & BOUNDARY) - putchar('-'); - else if (commit->object.flags & UNINTERESTING) - putchar('^'); - else if (opt->left_right) { - if (commit->object.flags & SYMMETRIC_LEFT) - putchar('<'); - else - putchar('>'); - } - } + if (!opt->graph) + fputs(get_revision_mark(opt, commit), stdout); fputs(find_unique_abbrev(commit->object.sha1, abbrev_commit), stdout); if (opt->print_parents) diff --git a/pretty.c b/pretty.c index 85499347514ec3..f21a30ccca66e3 100644 --- a/pretty.c +++ b/pretty.c @@ -859,11 +859,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder, c->abbrev_parent_hashes.off; return 1; case 'm': /* left/right/bottom */ - strbuf_addch(sb, (commit->object.flags & BOUNDARY) - ? '-' - : (commit->object.flags & SYMMETRIC_LEFT) - ? '<' - : '>'); + strbuf_addstr(sb, get_revision_mark(NULL, commit)); return 1; case 'd': format_decoration(sb, commit); diff --git a/revision.c b/revision.c index 1fcaeb79024665..0de1608d045d6f 100644 --- a/revision.c +++ b/revision.c @@ -2263,3 +2263,19 @@ struct commit *get_revision(struct rev_info *revs) graph_update(revs->graph, c); return c; } + +char *get_revision_mark(const struct rev_info *revs, const struct commit *commit) +{ + if (commit->object.flags & BOUNDARY) + return "-"; + else if (commit->object.flags & UNINTERESTING) + return "^"; + else if (!revs || revs->left_right) { + if (commit->object.flags & SYMMETRIC_LEFT) + return "<"; + else + return ">"; + } else if (revs->graph) + return "*"; + return ""; +} diff --git a/revision.h b/revision.h index d2ffde1ce67a55..0e4b35e8e54ba9 100644 --- a/revision.h +++ b/revision.h @@ -165,6 +165,7 @@ extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags, extern int prepare_revision_walk(struct rev_info *revs); extern struct commit *get_revision(struct rev_info *revs); +extern char *get_revision_mark(const struct rev_info *revs, const struct commit *commit); extern void mark_parents_uninteresting(struct commit *commit); extern void mark_tree_uninteresting(struct tree *tree); From adbbb31e0d3b4cc7845c6d23d21c00da51025208 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Mon, 7 Mar 2011 13:31:40 +0100 Subject: [PATCH 06/10] revision.c: introduce --cherry-mark for marking those commits which "--cherry-pick" would drop. The marker for those commits is '=' because '-' denotes a boundary commit already, even though 'git cherry' uses it. Nonequivalent commits are denoted '+' unless '--left-right' is used. Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- revision.c | 21 ++++++++++++++++++--- revision.h | 4 +++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/revision.c b/revision.c index 0de1608d045d6f..36022a6f6b95b7 100644 --- a/revision.c +++ b/revision.c @@ -535,6 +535,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs) int left_count = 0, right_count = 0; int left_first; struct patch_ids ids; + unsigned cherry_flag; /* First count the commits on the left and on the right */ for (p = list; p; p = p->next) { @@ -576,6 +577,9 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs) commit->util = add_commit_patch_id(commit, &ids); } + /* either cherry_mark or cherry_pick are true */ + cherry_flag = revs->cherry_mark ? PATCHSAME : SHOWN; + /* Check the other side */ for (p = list; p; p = p->next) { struct commit *commit = p->item; @@ -598,7 +602,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs) if (!id) continue; id->seen = 1; - commit->object.flags |= SHOWN; + commit->object.flags |= cherry_flag; } /* Now check the original side for seen ones */ @@ -610,7 +614,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs) if (!ent) continue; if (ent->seen) - commit->object.flags |= SHOWN; + commit->object.flags |= cherry_flag; commit->util = NULL; } @@ -802,7 +806,7 @@ static int limit_list(struct rev_info *revs) show(revs, newlist); show_early_output = NULL; } - if (revs->cherry_pick) + if (revs->cherry_pick || revs->cherry_mark) cherry_pick_list(newlist, revs); if (revs->left_only || revs->right_only) @@ -1293,7 +1297,14 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->right_only = 1; } else if (!strcmp(arg, "--count")) { revs->count = 1; + } else if (!strcmp(arg, "--cherry-mark")) { + if (revs->cherry_pick) + die("--cherry-mark is incompatible with --cherry-pick"); + revs->cherry_mark = 1; + revs->limited = 1; /* needs limit_list() */ } else if (!strcmp(arg, "--cherry-pick")) { + if (revs->cherry_mark) + die("--cherry-pick is incompatible with --cherry-mark"); revs->cherry_pick = 1; revs->limited = 1; } else if (!strcmp(arg, "--objects")) { @@ -2270,6 +2281,8 @@ char *get_revision_mark(const struct rev_info *revs, const struct commit *commit return "-"; else if (commit->object.flags & UNINTERESTING) return "^"; + else if (commit->object.flags & PATCHSAME) + return "="; else if (!revs || revs->left_right) { if (commit->object.flags & SYMMETRIC_LEFT) return "<"; @@ -2277,5 +2290,7 @@ char *get_revision_mark(const struct rev_info *revs, const struct commit *commit return ">"; } else if (revs->graph) return "*"; + else if (revs->cherry_mark) + return "+"; return ""; } diff --git a/revision.h b/revision.h index 0e4b35e8e54ba9..d38f1355d395d7 100644 --- a/revision.h +++ b/revision.h @@ -14,7 +14,8 @@ #define CHILD_SHOWN (1u<<6) #define ADDED (1u<<7) /* Parents already parsed and added? */ #define SYMMETRIC_LEFT (1u<<8) -#define ALL_REV_FLAGS ((1u<<9)-1) +#define PATCHSAME (1u<<9) +#define ALL_REV_FLAGS ((1u<<10)-1) #define DECORATE_SHORT_REFS 1 #define DECORATE_FULL_REFS 2 @@ -68,6 +69,7 @@ struct rev_info { reverse:1, reverse_output_stage:1, cherry_pick:1, + cherry_mark:1, bisect:1, ancestry_path:1, first_parent_only:1; From cb56e3093a1b25e105df44640e2224c8f6e6b893 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Mon, 7 Mar 2011 13:31:41 +0100 Subject: [PATCH 07/10] rev-list: documentation and test for --cherry-mark Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- Documentation/git-rev-list.txt | 1 + Documentation/rev-list-options.txt | 5 +++++ t/t6007-rev-list-cherry-pick-file.sh | 28 ++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index 5f47a13d3c6191..8a891ca68dc9ab 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -33,6 +33,7 @@ SYNOPSIS [ \--left-right ] [ \--left-only ] [ \--right-only ] + [ \--cherry-mark ] [ \--cherry-pick ] [ \--encoding[=] ] [ \--(author|committer|grep)= ] diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index cebba62239ad88..4755b83d2d4345 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -305,6 +305,11 @@ ifdef::git-rev-list[] to /dev/null as the output does not have to be formatted. endif::git-rev-list[] +--cherry-mark:: + + Like `--cherry-pick` (see below) but mark equivalent commits + with `=` rather than omitting them, and inequivalent ones with `+`. + --cherry-pick:: Omit any commit that introduces the same change as diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh index cd089a913bb93a..37bd25eaaaf5cd 100755 --- a/t/t6007-rev-list-cherry-pick-file.sh +++ b/t/t6007-rev-list-cherry-pick-file.sh @@ -99,6 +99,34 @@ test_expect_success '--cherry-pick bar does not come up empty (II)' ' test_cmp actual.named expect ' +cat >expect < actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +cat >expect <tags/E +=tags/C +EOF + +test_expect_success '--cherry-mark --left-right' ' + git rev-list --cherry-mark --left-right F...E -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + cat >expect < Date: Mon, 7 Mar 2011 13:31:42 +0100 Subject: [PATCH 08/10] log --cherry: a synonym At the porcelain level, because by definition there are many more contributors than integrators, it makes sense to give a handy short-hand for --right-only used with --cherry-mark and --no-merges. Make it so. In other words, this provides "git cherry with rev-list interface". Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- Documentation/rev-list-options.txt | 8 ++++++++ revision.c | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 4755b83d2d4345..95d209c11da4ab 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -337,6 +337,14 @@ commits from `B` which are in `A` or are patch-equivalent to a commit in More precisely, `--cherry-pick --right-only --no-merges` gives the exact list. +--cherry:: + + A synonym for `--right-only --cherry-mark --no-merges`; useful to + limit the output to the commits on our side and mark those that + have been applied to the other side of a forked history with + `git log --cherry upstream...mybranch`, similar to + `git cherry upstream mybranch`. + -g:: --walk-reflogs:: diff --git a/revision.c b/revision.c index 36022a6f6b95b7..51372f650a4ecb 100644 --- a/revision.c +++ b/revision.c @@ -1289,12 +1289,20 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->left_right = 1; } else if (!strcmp(arg, "--left-only")) { if (revs->right_only) - die("--left-only is incompatible with --right-only"); + die("--left-only is incompatible with --right-only" + " or --cherry"); revs->left_only = 1; } else if (!strcmp(arg, "--right-only")) { if (revs->left_only) die("--right-only is incompatible with --left-only"); revs->right_only = 1; + } else if (!strcmp(arg, "--cherry")) { + if (revs->left_only) + die("--cherry is incompatible with --left-only"); + revs->cherry_mark = 1; + revs->right_only = 1; + revs->no_merges = 1; + revs->limited = 1; } else if (!strcmp(arg, "--count")) { revs->count = 1; } else if (!strcmp(arg, "--cherry-mark")) { From fe3b59e595b02ee57314b74a74df915bdd845011 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Mon, 7 Mar 2011 13:31:43 +0100 Subject: [PATCH 09/10] t6007: test rev-list --cherry Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- t/t6007-rev-list-cherry-pick-file.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh index 37bd25eaaaf5cd..cacf3de6c9f318 100755 --- a/t/t6007-rev-list-cherry-pick-file.sh +++ b/t/t6007-rev-list-cherry-pick-file.sh @@ -145,6 +145,18 @@ test_expect_success '--cherry-pick --left-only' ' test_cmp actual.named expect ' +cat >expect < actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + test_expect_success '--cherry-pick with independent, but identical branches' ' git symbolic-ref HEAD refs/heads/independent && rm .git/index && From b1b47554ae889ca76b66349819c9b95a8be5f646 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Thu, 10 Mar 2011 15:45:03 +0100 Subject: [PATCH 10/10] git-log: put space after commit mark Currently, commit marks (left, right, boundary, cherry) are output right before the commit sha1, which makes it difficult to copy sha1s. Sample output for "git log --oneline --cherry": =049c269 t6007: test rev-list --cherry Change this to = 049c269 t6007: test rev-list --cherry which matches exactly the current output of "git log --graph". Leave "git rev-list" output as is (no space) so that they do not break. Adjust "git-svn" which uses "git log --pretty=raw --boundary". Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- git-svn.perl | 2 +- log-tree.c | 4 ++-- revision.c | 9 +++++++++ revision.h | 1 + 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index 177dd259cd53cd..a5857c1ad45b04 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -5734,7 +5734,7 @@ sub cmd_show_log { my (@k, $c, $d, $stat); my $esc_color = qr/(?:\033\[(?:(?:\d+;)*\d*)?m)*/; while (<$log>) { - if (/^${esc_color}commit -?($::sha1_short)/o) { + if (/^${esc_color}commit (- )?($::sha1_short)/o) { my $cmt = $1; if ($c && cmt_showable($c) && $c->{r} != $r_last) { $r_last = $c->{r}; diff --git a/log-tree.c b/log-tree.c index 12570403110cf5..2a1e3a94c910cd 100644 --- a/log-tree.c +++ b/log-tree.c @@ -381,7 +381,7 @@ void show_log(struct rev_info *opt) graph_show_commit(opt->graph); if (!opt->graph) - fputs(get_revision_mark(opt, commit), stdout); + put_revision_mark(opt, commit); fputs(find_unique_abbrev(commit->object.sha1, abbrev_commit), stdout); if (opt->print_parents) show_parents(commit, abbrev_commit); @@ -439,7 +439,7 @@ void show_log(struct rev_info *opt) fputs("commit ", stdout); if (!opt->graph) - fputs(get_revision_mark(opt, commit), stdout); + put_revision_mark(opt, commit); fputs(find_unique_abbrev(commit->object.sha1, abbrev_commit), stdout); if (opt->print_parents) diff --git a/revision.c b/revision.c index 51372f650a4ecb..626f6a23d140d5 100644 --- a/revision.c +++ b/revision.c @@ -2302,3 +2302,12 @@ char *get_revision_mark(const struct rev_info *revs, const struct commit *commit return "+"; return ""; } + +void put_revision_mark(const struct rev_info *revs, const struct commit *commit) +{ + char *mark = get_revision_mark(revs, commit); + if (!strlen(mark)) + return; + fputs(mark, stdout); + putchar(' '); +} diff --git a/revision.h b/revision.h index d38f1355d395d7..1c0abf0f58e355 100644 --- a/revision.h +++ b/revision.h @@ -168,6 +168,7 @@ extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags, extern int prepare_revision_walk(struct rev_info *revs); extern struct commit *get_revision(struct rev_info *revs); extern char *get_revision_mark(const struct rev_info *revs, const struct commit *commit); +extern void put_revision_mark(const struct rev_info *revs, const struct commit *commit); extern void mark_parents_uninteresting(struct commit *commit); extern void mark_tree_uninteresting(struct tree *tree);