Skip to content

Commit 071dca5

Browse files
derrickstoleedscho
authored andcommitted
commit: add generation to pop_most_recent_commit()
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 <[email protected]>
1 parent efb1826 commit 071dca5

File tree

5 files changed

+16
-6
lines changed

5 files changed

+16
-6
lines changed

commit.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,8 @@ void commit_list_sort_by_date(struct commit_list **list)
583583
}
584584

585585
struct commit *pop_most_recent_commit(struct commit_list **list,
586-
unsigned int mark)
586+
unsigned int mark,
587+
uint32_t min_generation)
587588
{
588589
struct commit *ret = pop_commit(list);
589590
struct commit_list *parents = ret->parents;
@@ -592,7 +593,9 @@ struct commit *pop_most_recent_commit(struct commit_list **list,
592593
struct commit *commit = parents->item;
593594
if (!parse_commit(commit) && !(commit->object.flags & mark)) {
594595
commit->object.flags |= mark;
595-
commit_list_insert_by_date(commit, list);
596+
597+
if (commit->generation >= min_generation)
598+
commit_list_insert_by_date(commit, list);
596599
}
597600
parents = parents->next;
598601
}

commit.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,13 @@ extern const char *skip_blank_lines(const char *msg);
166166

167167
/** Removes the first commit from a list sorted by date, and adds all
168168
* of its parents.
169+
*
170+
* The parents are not added if their generation number is strictly
171+
* lower than min_generation.
169172
**/
170173
struct commit *pop_most_recent_commit(struct commit_list **list,
171-
unsigned int mark);
174+
unsigned int mark,
175+
uint32_t min_generation);
172176

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

fetch-pack.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,8 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args,
521521
while (complete && cutoff <= complete->item->date) {
522522
print_verbose(args, _("Marking %s as complete"),
523523
oid_to_hex(&complete->item->object.oid));
524-
pop_most_recent_commit(&complete, COMPLETE);
524+
pop_most_recent_commit(&complete, COMPLETE,
525+
GENERATION_NUMBER_ZERO);
525526
}
526527
}
527528

sha1-name.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,8 @@ static int get_oid_oneline(const char *prefix, struct object_id *oid,
12171217
struct commit *commit;
12181218
int matches;
12191219

1220-
commit = pop_most_recent_commit(&list, ONELINE_SEEN);
1220+
commit = pop_most_recent_commit(&list, ONELINE_SEEN,
1221+
GENERATION_NUMBER_ZERO);
12211222
if (!parse_object(the_repository, &commit->object.oid))
12221223
continue;
12231224
buf = get_commit_buffer(commit, NULL);

walker.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ static int process_commit(struct walker *walker, struct commit *commit)
8282
return -1;
8383

8484
while (complete && complete->item->date >= commit->date) {
85-
pop_most_recent_commit(&complete, COMPLETE);
85+
pop_most_recent_commit(&complete, COMPLETE,
86+
GENERATION_NUMBER_ZERO);
8687
}
8788

8889
if (commit->object.flags & COMPLETE)

0 commit comments

Comments
 (0)