diff --git a/path-walk.c b/path-walk.c index aaa2cce7471941..dd1acb29d92b45 100644 --- a/path-walk.c +++ b/path-walk.c @@ -278,9 +278,11 @@ int walk_objects_by_path(struct path_walk_info *info) struct object_array_entry *pending = info->revs->pending.objects + i; struct object *obj = pending->item; - if (obj->type == OBJ_COMMIT) + if (obj->type == OBJ_COMMIT || obj->flags & SEEN) continue; + obj->flags |= SEEN; + while (obj->type == OBJ_TAG) { struct tag *tag = lookup_tag(info->revs->repo, &obj->oid); @@ -341,8 +343,12 @@ int walk_objects_by_path(struct path_walk_info *info) t = lookup_tree(info->revs->repo, oid); if (t) { - oidset_insert(&root_tree_set, oid); - oid_array_append(&root_tree_list->oids, oid); + if (t->object.flags & SEEN) + continue; + t->object.flags |= SEEN; + + if (!oidset_insert(&root_tree_set, oid)) + oid_array_append(&root_tree_list->oids, oid); } else { warning("could not find tree %s", oid_to_hex(oid)); } diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh index 26498cab24890d..943adc6c8f132f 100755 --- a/t/t6601-path-walk.sh +++ b/t/t6601-path-walk.sh @@ -276,4 +276,26 @@ test_expect_success 'topic, not base, boundary with pruning' ' test_cmp expect.sorted out.sorted ' +test_expect_success 'trees are reported exactly once' ' + test_when_finished "rm -rf unique-trees" && + test_create_repo unique-trees && + ( + cd unique-trees && + mkdir initial && + test_commit initial/file && + + git switch -c move-to-top && + git mv initial/file.t ./ && + test_tick && + git commit -m moved && + + git update-ref refs/heads/other HEAD + ) && + + test-tool -C unique-trees path-walk -- --all >out && + tree=$(git -C unique-trees rev-parse HEAD:) && + grep "$tree" out >out-filtered && + test_line_count = 1 out-filtered +' + test_done