mirror of
https://github.com/git/git.git
synced 2024-05-07 05:46:08 +02:00
Merge branch 'jz/rev-list-exclude-first-parent-only'
"git log" and friends learned an option --exclude-first-parent-only to propagate UNINTERESTING bit down only along the first-parent chain, just like --first-parent option shows commits that lack the UNINTERESTING bit only along the first-parent chain. * jz/rev-list-exclude-first-parent-only: git-rev-list: add --exclude-first-parent-only flag
This commit is contained in:
commit
708cbef33a
|
@ -122,19 +122,27 @@ again. Equivalent forms are `--min-parents=0` (any commit has 0 or more
|
|||
parents) and `--max-parents=-1` (negative numbers denote no upper limit).
|
||||
|
||||
--first-parent::
|
||||
Follow only the first parent commit upon seeing a merge
|
||||
commit. This option can give a better overview when
|
||||
viewing the evolution of a particular topic branch,
|
||||
because merges into a topic branch tend to be only about
|
||||
adjusting to updated upstream from time to time, and
|
||||
this option allows you to ignore the individual commits
|
||||
brought in to your history by such a merge.
|
||||
When finding commits to include, follow only the first
|
||||
parent commit upon seeing a merge commit. This option
|
||||
can give a better overview when viewing the evolution of
|
||||
a particular topic branch, because merges into a topic
|
||||
branch tend to be only about adjusting to updated upstream
|
||||
from time to time, and this option allows you to ignore
|
||||
the individual commits brought in to your history by such
|
||||
a merge.
|
||||
ifdef::git-log[]
|
||||
+
|
||||
This option also changes default diff format for merge commits
|
||||
to `first-parent`, see `--diff-merges=first-parent` for details.
|
||||
endif::git-log[]
|
||||
|
||||
--exclude-first-parent-only::
|
||||
When finding commits to exclude (with a '{caret}'), follow only
|
||||
the first parent commit upon seeing a merge commit.
|
||||
This can be used to find the set of changes in a topic branch
|
||||
from the point where it diverged from the remote branch, given
|
||||
that arbitrary merges can be valid topic branch changes.
|
||||
|
||||
--not::
|
||||
Reverses the meaning of the '{caret}' prefix (or lack thereof)
|
||||
for all following revision specifiers, up to the next `--not`.
|
||||
|
|
2
blame.c
2
blame.c
|
@ -2615,7 +2615,7 @@ void assign_blame(struct blame_scoreboard *sb, int opt)
|
|||
else {
|
||||
commit->object.flags |= UNINTERESTING;
|
||||
if (commit->object.parsed)
|
||||
mark_parents_uninteresting(commit);
|
||||
mark_parents_uninteresting(sb->revs, commit);
|
||||
}
|
||||
/* treat root commit as boundary */
|
||||
if (!commit->parents && !sb->show_root)
|
||||
|
|
30
revision.c
30
revision.c
|
@ -273,7 +273,7 @@ static void commit_stack_clear(struct commit_stack *stack)
|
|||
stack->nr = stack->alloc = 0;
|
||||
}
|
||||
|
||||
static void mark_one_parent_uninteresting(struct commit *commit,
|
||||
static void mark_one_parent_uninteresting(struct rev_info *revs, struct commit *commit,
|
||||
struct commit_stack *pending)
|
||||
{
|
||||
struct commit_list *l;
|
||||
|
@ -290,20 +290,26 @@ static void mark_one_parent_uninteresting(struct commit *commit,
|
|||
* wasn't uninteresting), in which case we need
|
||||
* to mark its parents recursively too..
|
||||
*/
|
||||
for (l = commit->parents; l; l = l->next)
|
||||
for (l = commit->parents; l; l = l->next) {
|
||||
commit_stack_push(pending, l->item);
|
||||
if (revs && revs->exclude_first_parent_only)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mark_parents_uninteresting(struct commit *commit)
|
||||
void mark_parents_uninteresting(struct rev_info *revs, struct commit *commit)
|
||||
{
|
||||
struct commit_stack pending = COMMIT_STACK_INIT;
|
||||
struct commit_list *l;
|
||||
|
||||
for (l = commit->parents; l; l = l->next)
|
||||
mark_one_parent_uninteresting(l->item, &pending);
|
||||
for (l = commit->parents; l; l = l->next) {
|
||||
mark_one_parent_uninteresting(revs, l->item, &pending);
|
||||
if (revs && revs->exclude_first_parent_only)
|
||||
break;
|
||||
}
|
||||
|
||||
while (pending.nr > 0)
|
||||
mark_one_parent_uninteresting(commit_stack_pop(&pending),
|
||||
mark_one_parent_uninteresting(revs, commit_stack_pop(&pending),
|
||||
&pending);
|
||||
|
||||
commit_stack_clear(&pending);
|
||||
|
@ -441,7 +447,7 @@ static struct commit *handle_commit(struct rev_info *revs,
|
|||
if (repo_parse_commit(revs->repo, commit) < 0)
|
||||
die("unable to parse commit %s", name);
|
||||
if (flags & UNINTERESTING) {
|
||||
mark_parents_uninteresting(commit);
|
||||
mark_parents_uninteresting(revs, commit);
|
||||
|
||||
if (!revs->topo_order || !generation_numbers_enabled(the_repository))
|
||||
revs->limited = 1;
|
||||
|
@ -1124,7 +1130,7 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
|
|||
if (repo_parse_commit_gently(revs->repo, p, 1) < 0)
|
||||
continue;
|
||||
if (p->parents)
|
||||
mark_parents_uninteresting(p);
|
||||
mark_parents_uninteresting(revs, p);
|
||||
if (p->object.flags & SEEN)
|
||||
continue;
|
||||
p->object.flags |= (SEEN | NOT_USER_GIVEN);
|
||||
|
@ -1132,6 +1138,8 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
|
|||
commit_list_insert_by_date(p, list);
|
||||
if (queue)
|
||||
prio_queue_put(queue, p);
|
||||
if (revs->exclude_first_parent_only)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1422,7 +1430,7 @@ static int limit_list(struct rev_info *revs)
|
|||
if (process_parents(revs, commit, &original_list, NULL) < 0)
|
||||
return -1;
|
||||
if (obj->flags & UNINTERESTING) {
|
||||
mark_parents_uninteresting(commit);
|
||||
mark_parents_uninteresting(revs, commit);
|
||||
slop = still_interesting(original_list, date, slop, &interesting_cache);
|
||||
if (slop)
|
||||
continue;
|
||||
|
@ -2223,6 +2231,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
|
|||
return argcount;
|
||||
} else if (!strcmp(arg, "--first-parent")) {
|
||||
revs->first_parent_only = 1;
|
||||
} else if (!strcmp(arg, "--exclude-first-parent-only")) {
|
||||
revs->exclude_first_parent_only = 1;
|
||||
} else if (!strcmp(arg, "--ancestry-path")) {
|
||||
revs->ancestry_path = 1;
|
||||
revs->simplify_history = 0;
|
||||
|
@ -3345,7 +3355,7 @@ static void explore_walk_step(struct rev_info *revs)
|
|||
return;
|
||||
|
||||
if (c->object.flags & UNINTERESTING)
|
||||
mark_parents_uninteresting(c);
|
||||
mark_parents_uninteresting(revs, c);
|
||||
|
||||
for (p = c->parents; p; p = p->next)
|
||||
test_flag_and_insert(&info->explore_queue, p->item, TOPO_WALK_EXPLORED);
|
||||
|
|
|
@ -158,6 +158,7 @@ struct rev_info {
|
|||
bisect:1,
|
||||
ancestry_path:1,
|
||||
first_parent_only:1,
|
||||
exclude_first_parent_only:1,
|
||||
line_level_traverse:1,
|
||||
tree_blobs_in_commit_order:1,
|
||||
|
||||
|
@ -402,7 +403,7 @@ const char *get_revision_mark(const struct rev_info *revs,
|
|||
void put_revision_mark(const struct rev_info *revs,
|
||||
const struct commit *commit);
|
||||
|
||||
void mark_parents_uninteresting(struct commit *commit);
|
||||
void mark_parents_uninteresting(struct rev_info *revs, struct commit *commit);
|
||||
void mark_tree_uninteresting(struct repository *r, struct tree *tree);
|
||||
void mark_trees_uninteresting_sparse(struct repository *r, struct oidset *trees);
|
||||
|
||||
|
|
|
@ -603,7 +603,7 @@ static int mark_uninteresting(const char *refname, const struct object_id *oid,
|
|||
if (!commit)
|
||||
return 0;
|
||||
commit->object.flags |= UNINTERESTING;
|
||||
mark_parents_uninteresting(commit);
|
||||
mark_parents_uninteresting(NULL, commit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,13 +16,12 @@ unnote () {
|
|||
}
|
||||
|
||||
#
|
||||
# Create a test repo with interesting commit graph:
|
||||
# Create a test repo with an interesting commit graph:
|
||||
#
|
||||
# A--B----------G--H--I--K--L
|
||||
# \ \ / /
|
||||
# \ \ / /
|
||||
# C------E---F J
|
||||
# \_/
|
||||
# A-----B-----G--H--I--K--L
|
||||
# \ \ / /
|
||||
# \ \ / /
|
||||
# C--D--E--F J
|
||||
#
|
||||
# The commits are laid out from left-to-right starting with
|
||||
# the root commit A and terminating at the tip commit L.
|
||||
|
@ -142,6 +141,13 @@ check_result 'I B A' --author-date-order -- file
|
|||
check_result 'H' --first-parent -- another-file
|
||||
check_result 'H' --first-parent --topo-order -- another-file
|
||||
|
||||
check_result 'L K I H G B A' --first-parent L
|
||||
check_result 'F E D C' --exclude-first-parent-only F ^L
|
||||
check_result '' F ^L
|
||||
check_result 'L K I H G J' L ^F
|
||||
check_result 'L K I H G B J' --exclude-first-parent-only L ^F
|
||||
check_result 'L K I H G B' --exclude-first-parent-only --first-parent L ^F
|
||||
|
||||
check_result 'E C B A' --full-history E -- lost
|
||||
test_expect_success 'full history simplification without parent' '
|
||||
printf "%s\n" E C B A >expect &&
|
||||
|
|
Loading…
Reference in New Issue