Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Documentation/rev-list-options.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ The following options affect the way the simplification is performed:
times; if so, a commit is included if it is any of the commits
given or if it is an ancestor or descendant of one of them.

`--maximal`::
Restrict the output commits to be those that are not reachable
from any other commits in the revision range.

A more detailed explanation follows.

Suppose you specified `foo` as the _<paths>_. We shall call commits
Expand Down
4 changes: 2 additions & 2 deletions object.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ void object_array_init(struct object_array *array);

/*
* object flag allocation:
* revision.h: 0---------10 15 23------27
* revision.h: 0---------10 15 23--------28
* fetch-pack.c: 01 67
* negotiator/default.c: 2--5
* walker.c: 0-2
Expand All @@ -86,7 +86,7 @@ void object_array_init(struct object_array *array);
* builtin/unpack-objects.c: 2021
* pack-bitmap.h: 2122
*/
#define FLAG_BITS 28
#define FLAG_BITS 29

#define TYPE_BITS 3

Expand Down
9 changes: 7 additions & 2 deletions revision.c
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,8 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
struct commit *p = parent->item;
parent = parent->next;
if (p)
p->object.flags |= UNINTERESTING;
p->object.flags |= UNINTERESTING |
CHILD_VISITED;
if (repo_parse_commit_gently(revs->repo, p, 1) < 0)
continue;
if (p->parents)
Expand Down Expand Up @@ -1204,7 +1205,7 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
if (!*slot)
*slot = *revision_sources_at(revs->sources, commit);
}
p->object.flags |= pass_flags;
p->object.flags |= pass_flags | CHILD_VISITED;
if (!(p->object.flags & SEEN)) {
p->object.flags |= (SEEN | NOT_USER_GIVEN);
if (list)
Expand Down Expand Up @@ -2381,6 +2382,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->first_parent_only = 1;
} else if (!strcmp(arg, "--exclude-first-parent-only")) {
revs->exclude_first_parent_only = 1;
} else if (!strcmp(arg, "--maximal")) {
revs->maximal = 1;
} else if (!strcmp(arg, "--ancestry-path")) {
revs->ancestry_path = 1;
revs->simplify_history = 0;
Expand Down Expand Up @@ -4125,6 +4128,8 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
{
if (commit->object.flags & SHOWN)
return commit_ignore;
if (revs->maximal && (commit->object.flags & CHILD_VISITED))
return commit_ignore;
if (revs->unpacked && has_object_pack(revs->repo, &commit->object.oid))
return commit_ignore;
if (revs->no_kept_objects) {
Expand Down
5 changes: 4 additions & 1 deletion revision.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@
#define NOT_USER_GIVEN (1u<<25)
#define TRACK_LINEAR (1u<<26)
#define ANCESTRY_PATH (1u<<27)
#define ALL_REV_FLAGS (((1u<<11)-1) | NOT_USER_GIVEN | TRACK_LINEAR | PULL_MERGE)
#define CHILD_VISITED (1u<<28)
#define ALL_REV_FLAGS (((1u<<11)-1) | NOT_USER_GIVEN | TRACK_LINEAR \
| PULL_MERGE | CHILD_VISITED)

#define DECORATE_SHORT_REFS 1
#define DECORATE_FULL_REFS 2
Expand Down Expand Up @@ -198,6 +200,7 @@ struct rev_info {
cherry_mark:1,
bisect:1,
ancestry_path:1,
maximal:1,

/* True if --ancestry-path was specified without an
* argument. The bottom revisions are implicitly
Expand Down
75 changes: 75 additions & 0 deletions t/t6600-test-reach.sh
Original file line number Diff line number Diff line change
Expand Up @@ -762,4 +762,79 @@ test_expect_success 'for-each-ref is-base: --sort' '
--sort=refname --sort=-is-base:commit-2-3
'

test_expect_success 'rev-list --maximal (all positive)' '
# Only one maximal.
cat >input <<-\EOF &&
refs/heads/commit-1-1
refs/heads/commit-4-2
refs/heads/commit-4-4
refs/heads/commit-8-4
EOF

cat >expect <<-EOF &&
$(git rev-parse refs/heads/commit-8-4)
EOF
run_all_modes git rev-list --maximal --stdin &&

# All maximal.
cat >input <<-\EOF &&
refs/heads/commit-5-2
refs/heads/commit-4-3
refs/heads/commit-3-4
refs/heads/commit-2-5
EOF

cat >expect <<-EOF &&
$(git rev-parse refs/heads/commit-5-2)
$(git rev-parse refs/heads/commit-4-3)
$(git rev-parse refs/heads/commit-3-4)
$(git rev-parse refs/heads/commit-2-5)
EOF
run_all_modes git rev-list --maximal --stdin &&

# Mix of both.
cat >input <<-\EOF &&
refs/heads/commit-5-2
refs/heads/commit-3-2
refs/heads/commit-2-5
EOF

cat >expect <<-EOF &&
$(git rev-parse refs/heads/commit-5-2)
$(git rev-parse refs/heads/commit-2-5)
EOF
run_all_modes git rev-list --maximal --stdin
'

test_expect_success 'rev-list --maximal (range)' '
cat >input <<-\EOF &&
refs/heads/commit-1-1
refs/heads/commit-2-5
refs/heads/commit-6-4
^refs/heads/commit-4-5
EOF

cat >expect <<-EOF &&
$(git rev-parse refs/heads/commit-6-4)
EOF
run_all_modes git rev-list --maximal --stdin &&

# first-parent changes reachability: the first parent
# reduces the second coordinate to 1 before reducing the
# first coordinate.
cat >input <<-\EOF &&
refs/heads/commit-1-1
refs/heads/commit-2-5
refs/heads/commit-6-4
^refs/heads/commit-4-5
EOF

cat >expect <<-EOF &&
$(git rev-parse refs/heads/commit-6-4)
$(git rev-parse refs/heads/commit-2-5)
EOF
run_all_modes git rev-list --maximal --stdin \
--first-parent --exclude-first-parent-only
'

test_done
Loading