Skip to content

Commit 0ff919e

Browse files
pks-tgitster
authored andcommitted
object-name: fix reversed ordering with ":/<text>" revisions
Recently it was reported [1] that "look for the youngest commit reachable from any ref with log message that match the given pattern" syntax (i.e. ':/<text>') started to return results in reverse recency order. This regression was introduced in Git v2.47.0 and is caused by a memory leak fix done in 57fb139 (object-name: fix leaking commit list items, 2024-08-01). The intent of the identified commit is to stop modifying the commit list provided by the caller such that the caller can properly free all commit list items, including those that the called function might potentially remove from the list. This was done by creating a copy of the passed-in commit list and modifying this copy instead of the caller-provided list. We already knew to create such a copy beforehand with the `backup` list, which was used to clear the `ONELINE_SEEN` commit mark after we were done. So the refactoring simply renamed that list to `copy` and started to operate on that list instead. There is a gotcha though: the backup list, and thus now also the copied list, is always being prepended to, so the resulting list is in reverse order! The end result is that we pop commits from the wrong end of the commit list, returning commits in reverse recency order. Fix the bug by appending to the list instead. [1]: <CAKOEJdcPYn3O01p29rVa+xv=Qr504FQyKJeSB-Moze04ViCGGg@mail.gmail.com> Reported-by: Aarni Koskela <[email protected]> Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f30bfaf commit 0ff919e

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

object-name.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1393,7 +1393,7 @@ static int get_oid_oneline(struct repository *r,
13931393
const char *prefix, struct object_id *oid,
13941394
const struct commit_list *list)
13951395
{
1396-
struct commit_list *copy = NULL;
1396+
struct commit_list *copy = NULL, **copy_tail = &copy;
13971397
const struct commit_list *l;
13981398
int found = 0;
13991399
int negative = 0;
@@ -1415,7 +1415,7 @@ static int get_oid_oneline(struct repository *r,
14151415

14161416
for (l = list; l; l = l->next) {
14171417
l->item->object.flags |= ONELINE_SEEN;
1418-
commit_list_insert(l->item, &copy);
1418+
copy_tail = &commit_list_insert(l->item, copy_tail)->next;
14191419
}
14201420
while (copy) {
14211421
const char *p, *buf;

t/t1500-rev-parse.sh

+15
Original file line numberDiff line numberDiff line change
@@ -310,4 +310,19 @@ test_expect_success '--short= truncates to the actual hash length' '
310310
test_cmp expect actual
311311
'
312312

313+
test_expect_success ':/ and HEAD^{/} favor more recent matching commits' '
314+
test_when_finished "rm -rf repo" &&
315+
git init repo &&
316+
(
317+
cd repo &&
318+
test_commit common-old &&
319+
test_commit --no-tag common-new &&
320+
git rev-parse HEAD >expect &&
321+
git rev-parse :/common >actual &&
322+
test_cmp expect actual &&
323+
git rev-parse HEAD^{/common} >actual &&
324+
test_cmp expect actual
325+
)
326+
'
327+
313328
test_done

0 commit comments

Comments
 (0)