git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Missing Promisor Objects in Partial Repo Design Doc

From
Calvin Wan <calvinwan@google.com>
Date
Oct 8, 2024, 21:35 UTC
Message-ID
<CAFySSZCyoaKCGycYgJjCJGJ2mV1yfg+gVFb7RytGKmkjupkNkQ@mail.gmail.com>
In-Reply-To
<xmqqo743qkn9.fsf@gitster.g>
On Tue, Oct 1, 2024 at 7:54 PM Junio C Hamano <gitster@pobox.com> wrote:
Show 6 quoted lines
>
> True.  Will it become even worse, if a protocol extension Christian
> proposes starts suggesting a repository that is not lazy to add a
> promisor remote?  In such a set-up, perhaps all history leading to
> C2b down to the root are local, but C3 may have come from a promisor
> remote (hence in a promisor pack).
Yes if we and consequently Git considers this state to be problematic.
Show 18 quoted lines
> > Bad State Solutions
> > ===================
> >
> > Fetch negotiation
> > -----------------
> > Implemented at
> > https://lore.kernel.org/git/20240919234741.1317946-1-calvinwan@google.com/
> >
> > During fetch negotiation, if a commit is not in a promisor pack and
> > therefore local, do not declare it as "have" so they can be fetched into
> > a promisor pack.
> >
> > Cost:
> > - Creation of set of promisor pack objects (by iterating through every
> >   .idx of promisor packs)
>
> What is "promisor PACK objects"?  Is it different from the "promisor
> objects" (i.e. what I called the useless definition above)?

Objects that are in promisor packs, specifically the ones that have the flag, packed_git::pack_promisor, set. However, since this design doc was sent out, it turns out the creation of a set of promisor pack objects in a large repository (such as Android or Chrome) is very expensive, so this design is infeasible in my opinion.

Show 20 quoted lines
>
> > - Refetch number of local commits
> >
> > Pros: Implementation is simple, client doesn’t have to repack, prevents
> > state from ever occurring in the repository.
> >
> > Cons: Network cost of refetching could be high if many local commits
> > need to be refetched.
>
> What if we get into the same state by creating local C4, which gets
> to outside and on top of which C5 is built, which is now sitting at
> the tip of the remote history and we fetch from them?  In order to
> include C4 in the "promisor pack", we refrain from saying C4 is a
> "have" for us and refetch.  Would C2 be fetched again?
>
> I do not think C2 would be, because we made it an object in a
> promisor pack when we "fixed" the history for C3.
>
> So the cost will not grow proportionally to the depth of the
> history, which makes it OK from my point of view.

Correct, the cost of refetching is only a one time cost, but unfortunately creation of a set of promisor pack objects isn't.

Show 23 quoted lines
>
> > Garbage Collection repack
> > -------------------------
> > Not yet implemented.
> >
> > Same concept at “fetch repack”, but happens during garbage collection
> > instead. The traversal is more expensive since we no longer have access
> > to what was recently fetched so we have to traverse through all promisor
> > packs to collect tips of “bad” history.
>
> In other words, with the status quo, "git gc" that attempts to
> repack "objects in promisor packs" and "other objects that did not
> get repacked in the step that repack objects in promisor packs"
> separately, it implements the latter in a buggy way and discards
> some objects.  And fixing that bug by doing the right thing is
> expensive.
>
> Stepping back a bit, why is the loss of C2a/C2b/C2 a problem after
> "git gc"?  Wouldn't these "missing" objects be lazily fetchable, now
> C3 is known to the remote and the remote promises everything
> reachable from what they offer are (re)fetchable from them?  IOW, is
> this a correctness issue, or only performance issue (of having to
> re-fetch what we once locally had)?

My first thought is that from both the user and developer perspective, we don't expect our reachable objects to be gc'ed. So all of the "bad state" solutions work to ensure that that isn't the case in some way or form. However, if it turns out that all of these solutions are much more expensive and disruptive to the user than accepting that local objects can be gc'ed and JIT refetching, then the latter seems much more palatable. It is inevitable that we take some performance hit to fix this problem and we may just have to accept this as one of the costs of having partial clones to begin with.

Show 10 quoted lines
>
> > Cons: Packing local objects into promisor packs means that it is no
> > longer possible to detect if an object is missing due to repository
> > corruption or because we need to fetch it from a promisor remote.
>
> Is this true?  Can we tell, when trying to access C2a/C2b/C2 after
> the current version of "git gc" removes them from the local object
> store, that they are missing due to repository corruption?  After
> all, C3 can reach them so wouldn't it be possible for us to fetch
> them from the promisor remote?

I should be more clear that "detecting if an object is missing due to repository corruption" refers to fsck currently not having the functionality to do that. We are "accidentally" discovering the corruption when we try to access the missing object, but we can still fetch them from the promisor remote afterwards.

Show 8 quoted lines
> After a lazy clone that omits a lot of objects acquires many objects
> over time by fetching missing objects on demand, wouldn't we want to
> have an option to "slim" the local repository by discarding some of
> these objects (the ones that are least frequently used), relying on
> the promise by the promisor remote that even if we did so, they can
> be fetched again?  Can we treat loss of C2a/C2b/C2 as if such a
> feature prematurely kicked in?  Or are we failing to refetch them
> for some reason?

Yes if such a feature existed, then it would be feasible and a possible solution for this issue (I'm leaning quite towards this now after testing out some of the other designs).

Previous: Han YoungNext: Han Young
Message 35 of 65 in “revision: fix reachable objects being gc'ed in no blob clone repo”
  1. 0/1 revision: fix reachable objects being gc'ed in no blob clone repoHan Young, Aug 2, 2024
  2. 1/1 revision: don't set parents as uninteresting if exclude promisor objectsHan Young, Aug 2, 2024
  3. Junio C HamanoAug 2, 2024
  4. 韩仰Aug 12, 2024
  5. Junio C HamanoAug 12, 2024
  6. 韩仰Aug 22, 2024
  7. Jonathan TanAug 13, 2024
  8. Jonathan TanAug 13, 2024
  9. Junio C HamanoAug 14, 2024
  10. Jonathan TanAug 14, 2024
  11. 0/4 revision: fix reachable objects being gc'ed in no blob clone repoHan Young, Aug 23, 2024
  12. 1/4 packfile: split promisor objects oidset into twoHan Young, Aug 23, 2024
  13. 2/4 revision: add exclude-promisor-pack-objects optionHan Young, Aug 23, 2024
  14. 3/4 revision: don't mark commit as UNINTERESTING if --exclude-promisor-objects is setHan Young, Aug 23, 2024
  15. 4/4 repack: use new exclude promisor pack objects optionHan Young, Aug 23, 2024
  16. 0/2 revision: fix reachable commits being gc'ed in partial repoCalvin Wan, Sep 19, 2024
  17. 1/2 packfile: split promisor objects oidset into twoCalvin Wan, Sep 19, 2024
  18. Junio C HamanoSep 22, 2024
  19. 2/2 fetch-pack.c: do not declare local commits as "have" in partial reposCalvin Wan, Sep 19, 2024
  20. Junio C HamanoSep 22, 2024
  21. Junio C HamanoSep 22, 2024
  22. 韩仰Sep 23, 2024
  23. Junio C HamanoSep 23, 2024
  24. Calvin WanOct 2, 2024
  25. 0/2 repack: pack everything into promisor packfile in partial reposHan Young, Sep 25, 2024
  26. 1/2 repack: pack everything into packfileHan Young, Sep 25, 2024
  27. 2/2 t0410: adapt tests to repack changesHan Young, Sep 25, 2024
  28. Phillip WoodSep 25, 2024
  29. Junio C HamanoSep 25, 2024
  30. Junio C HamanoSep 25, 2024
  31. Missing Promisor Objects in Partial Repo Design DocCalvin Wan, Oct 1, 2024
  32. Junio C HamanoOct 1, 2024
  33. Junio C HamanoOct 2, 2024
  34. Han YoungOct 2, 2024
  35. Calvin WanOct 8, 2024
  36. Han YoungOct 9, 2024
  37. Jonathan TanOct 9, 2024
  38. Jonathan TanOct 12, 2024
  39. Han YoungOct 12, 2024
  40. Jonathan TanOct 14, 2024
  41. Jonathan TanOct 9, 2024
  42. 0/3 repack: pack everything into promisor packfile in partial reposHan Young, Oct 8, 2024
  43. 1/3 repack: pack everything into packfileHan Young, Oct 8, 2024
  44. Calvin WanOct 8, 2024
  45. 2/3 t0410: adapt tests to repack changesHan Young, Oct 8, 2024
  46. 3/3 partial-clone: update docHan Young, Oct 8, 2024
  47. Junio C HamanoOct 8, 2024
  48. Junio C HamanoOct 8, 2024
  49. Han YoungOct 9, 2024
  50. 0/3 repack: pack everything into promisor packfile in partial reposHan Young, Oct 11, 2024
  51. 1/3 repack: pack everything into packfileHan Young, Oct 11, 2024
  52. 2/3 repack: adapt tests to repack changesHan Young, Oct 11, 2024
  53. 3/3 partial-clone: update docHan Young, Oct 11, 2024
  54. Junio C HamanoOct 11, 2024
  55. Junio C HamanoOct 11, 2024
  56. 0/3 repack: pack everything into promisor packfile in partial reposHan Young, Oct 14, 2024
  57. 1/3 repack: pack everything into packfileHan Young, Oct 14, 2024
  58. 2/3 t0410: adapt tests to repack changesHan Young, Oct 14, 2024
  59. 3/3 partial-clone: update docHan Young, Oct 14, 2024
  60. 0/3 Repack on fetchJonathan Tan, Oct 21, 2024
  61. 1/3 move variableJonathan Tan, Oct 21, 2024
  62. 2/3 pack-objectsJonathan Tan, Oct 21, 2024
  63. 3/3 record local links and call pack-objectsJonathan Tan, Oct 21, 2024
  64. Han YoungOct 23, 2024
  65. Jonathan TanOct 23, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.