Following Jonathan and Junio's suggestion, I tried to filter promisor objects in get_revision(). Initially I got ride of the for_each_packed_object() loop, but that way promisor trees and blobs are not filtered. I kept the for_each_packed_object() loop, but only mark non-commit objects as UNINTERESTING, that way we ensure all the promisor objects are filtered, and UNINTERESTING bit is not passed down in process_parent() call. But this isn't enough solve the 'reachable objects being gc'ed' problem, as promisor projects is defined as "objects in promisor pack or referenced". git repack only packs objects in promisor pack and non promisor objects. Meaning objects who are promisor objects but not in promisor pack are discarded. So I added a new option to list-objects, '--exclude-promisor-pack-objects'. Which only exclude objects in promisor packs, this way when we run git repack, no reachable objects will be discarded. This seems to fix the problem, but I still don't feel the approach is elegant. Another way to fix this problem I come up with is to pack everything into a promisor packfile, if it is a partial clone repo. This would make pruning unreachable objects impossible, but that is already the case with promisor objects. Packing everything into one packfile will simplify code by a lot. Han Young (4): packfile: split promisor objects oidset into two revision: add exclude-promisor-pack-objects option revision: don't mark commit as UNINTERESTING if --exclude-promisor-objects is set repack: use new exclude promisor pack objects option builtin/pack-objects.c | 8 ++++---- builtin/repack.c | 2 +- list-objects.c | 3 ++- packfile.c | 25 ++++++++++++++++--------- packfile.h | 7 ++++++- revision.c | 17 +++++++++++++++-- revision.h | 3 ++- 7 files changed, 46 insertions(+), 19 deletions(-) -- 2.45.2