Skip to content

Commit

Permalink
commit: add generation to pop_most_recent_commit()
Browse files Browse the repository at this point in the history
The method pop_most_recent_commit() is confusingly named, in that it
pops the most-recent commit, but also adds that commit's parents to
the list. This is used by a few commit walks, especially the one in
ref_newer(). 'git push' uses ref_newer() to check if a force-push is
necessary, and in the case of a force-push being needed, the current
algorithm walks every reachable commit. This is especially severe in
the case of an amended commit: they have the same parent, but we still
walk to the very end of the graph!

Add a 'min_generation' parameter to pop_most_recent_commit() to limit
the commits that are walked to those with generation number at least
'min_generation'. This greatly reduces the number of commits walked by
a force-push.

There may be more work to improve this algorithm in the future, but for
now this is enough for most cases. This direction has the benefit that
it does not affect the non-force-push case at all. Future directions
should consider improving that case as well.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
  • Loading branch information
derrickstolee authored and dscho committed Jun 8, 2019
1 parent 8311f39 commit 3c3c86c
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 6 deletions.
7 changes: 5 additions & 2 deletions commit.c
Expand Up @@ -596,7 +596,8 @@ void commit_list_sort_by_date(struct commit_list **list)
}

struct commit *pop_most_recent_commit(struct commit_list **list,
unsigned int mark)
unsigned int mark,
uint32_t min_generation)
{
struct commit *ret = pop_commit(list);
struct commit_list *parents = ret->parents;
Expand All @@ -605,7 +606,9 @@ struct commit *pop_most_recent_commit(struct commit_list **list,
struct commit *commit = parents->item;
if (!parse_commit(commit) && !(commit->object.flags & mark)) {
commit->object.flags |= mark;
commit_list_insert_by_date(commit, list);

if (commit->generation >= min_generation)
commit_list_insert_by_date(commit, list);
}
parents = parents->next;
}
Expand Down
6 changes: 5 additions & 1 deletion commit.h
Expand Up @@ -200,9 +200,13 @@ const char *skip_blank_lines(const char *msg);

/** Removes the first commit from a list sorted by date, and adds all
* of its parents.
*
* The parents are not added if their generation number is strictly
* lower than min_generation.
**/
struct commit *pop_most_recent_commit(struct commit_list **list,
unsigned int mark);
unsigned int mark,
uint32_t min_generation);

struct commit *pop_commit(struct commit_list **stack);

Expand Down
3 changes: 2 additions & 1 deletion fetch-pack.c
Expand Up @@ -534,7 +534,8 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args,
while (complete && cutoff <= complete->item->date) {
print_verbose(args, _("Marking %s as complete"),
oid_to_hex(&complete->item->object.oid));
pop_most_recent_commit(&complete, COMPLETE);
pop_most_recent_commit(&complete, COMPLETE,
GENERATION_NUMBER_ZERO);
}
}

Expand Down
3 changes: 2 additions & 1 deletion sha1-name.c
Expand Up @@ -1265,7 +1265,8 @@ static int get_oid_oneline(struct repository *r,
struct commit *commit;
int matches;

commit = pop_most_recent_commit(&list, ONELINE_SEEN);
commit = pop_most_recent_commit(&list, ONELINE_SEEN,
GENERATION_NUMBER_ZERO);
if (!parse_object(r, &commit->object.oid))
continue;
buf = get_commit_buffer(commit, NULL);
Expand Down
3 changes: 2 additions & 1 deletion walker.c
Expand Up @@ -82,7 +82,8 @@ static int process_commit(struct walker *walker, struct commit *commit)
return -1;

while (complete && complete->item->date >= commit->date) {
pop_most_recent_commit(&complete, COMPLETE);
pop_most_recent_commit(&complete, COMPLETE,
GENERATION_NUMBER_ZERO);
}

if (commit->object.flags & COMPLETE)
Expand Down

0 comments on commit 3c3c86c

Please sign in to comment.