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

Re: [PATCH 12/17] Documentation: describe split commit-graphs

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
May 9, 2019, 15:48 UTC
Message-ID
<875zqjy6ga.fsf@evledraar.gmail.com>
In-Reply-To
<f27db281-abad-5043-6d71-cbb083b1c877@gmail.com>
On Thu, May 09 2019, Derrick Stolee wrote:

Not a very detailed reply since I've gotta run soon, but figured I'd send something (also given our timezone difference).

Show 59 quoted lines
> On 5/8/2019 4:11 PM, Ævar Arnfjörð Bjarmason wrote:
>>
>> On Wed, May 08 2019, Derrick Stolee wrote:
>>
>>> I'll ignore the improbability of this turn of events (two writes happening
>>> during the span of trying to read two files) and focus on the fact that
>>> we can prevent issues here using the 4th TODO item in my cover letter:
>>
>> FWIW the sort of scenario SZEDER is describing is something I deal with
>> in production a lot. It doesn't require an unfair scheduler, just that
>> you have differently nice(1)'d processes accessing the same repo.
>>
>> So if you have batch "cron" processes their IO scheduling follows their
>> nice(1) scheduling. It's not atypical to e.g. have some background
>> thingy sit for seconds or even minutes on an I/O syscall while the
>> kernel decides everyone else has right of way, since you nice'd that not
>> caring if it finishes in 10 seconds or 10 hours.
>
> Thanks. I learned something today.
>
> I still don't think this is a problem, with the idea below.
>
>>>  4. It would be helpful to add a new optional chunk that contains the
>>>     trailing hash for the lower level of the commit-graph stack. This chunk
>>>     would only be for the commit-graph-N files, and would provide a simple
>>>     way to check that the stack is valid on read, in case we are still
>>>     worried about other processes reading/writing in the wrong order.
>>>
>>> If we have this chunk -- you have convinced me that we need it -- then we
>>> could ignore the "new" commit-graph-2 because its base graph hash does not
>>> match. We can continue without dying because we can always parse the "missing"
>>> commits from the packs.
>
> So, let's set that idea aside. You have other concerns.
>
>> Instead of looping through files N at a time we'd have a discovery step
>> where we'd need to open() all the files, see which ones say "my parent
>> hash hash X", and then create a list of those hashes in order to read a
>> bunch of commit-graph-<HASH> files.
>>
>> Is that a bit painful? Sure, but way less painful than dealing with the
>> caveats I'd mentioned in [1] and SZEDER details here.
>
> I don't see how this step is less painful than the one I am describing.
> You'll need to be a bit more specific to convince me.
>
> I'll try to be specific with a few ideas that have been thrown around,
> so we can compare and contrast (and point out where I am misunderstanding
> what you are trying to say).
>
> Option 0 (this series): commit-graph-N
> --------------------------------------
>
> On read, we look for the 'info/commit-graph' file and acquire a read handle.
> We set that commit_graph struct as our tip commit-graph. Then, for each
> increasing N (until we fail) we acquire a read handle on
> 'info/commit-graphs/commit-graph-N' and check that its base hash matches
> our current tip commit-graph. If the file doesn't exist, or the base
> hash doesn't match, then we stop and continue with our current tip graph.

This "base hash" is something I may have missed. I *thought* we'd happy-go-lucky load e.g. commit-graph-1, commit-graph-2 in that order, and if (e.g. due to fsync/dir entry issues noted earlier) if we got the "wrong" commit-graph-2 we'd be oblivious to that. Is that not the case?

I was trying (and failing) to make the test suite vomit by hacking up the code to load "commit-graph-1" first, then "commit-graph", so maybe I ran into that safeguard, whatever it is. I've just seen how we carry the "num_commits_in_base" forward, not some expected checksum...

> On write, use a 'mv' to swap our .lock file with whatever level we are
> merging, THEN can unlink() the higher layers in decreasing order. (This
> "mv-then-unlink" order is different than what is implemented by this
> series, but is enabled by the chunk containing the base graph hash.)

So one of the things that make me paranoid about this (as noted upthread/earlier) is that at least on POSIX filesystems just because you observe that you create and fsync "foo" and "bar" in that order doesn't mean that a concurrent reader of that directory will get the updates in that order. I.e. file update != dir entry update.

It can be made to work, and core.fsyncObjectFiles is a partial solution, but better to avoid it entirely. Also the failure with core.fsyncObjectFiles is much more graceful, since in that case we don't have a "deadbeef[...]" loose object *yet* but will (presumably) see the *right* thing Real Soon Now since it's content-addressable, whereas with this design we might see the *wrong* thing. So this would be the first area of git (that I know of) where we'd be sensitive to a combination of syncing dir entries and file content in order.

Show 12 quoted lines
> Option 1 (needs format v2): commit-graph -> graph-{hash}.graph
> --------------------------------------------------------------
>
> On read, we load the 'info/commit-graph' file and inspect the byte saying
> how many base files we have. We load their hashes from the base file chunk
> and read 'info/graph-{hash}.graph' for each. If _any_ fail, then we need
> to ignore anything "above" the failure in the chain (and specifically this
> includes the 'commit-graph' file), or consider reloading the commit-graph
> file altogether and hope it works this time. [Note: if an older version
> of Git doesn't understand the incremental file format, it will fail to
> properly understand the graph positions and either fail with an
> "invalid parent position" error, or worse give garbage results.]

Right, except as noted before I'd add (at least per my understanding so far) "s/needs format v2//". I.e. we could stick this data in new v1 backwards-compatible chunks, which also addresses the "older version..." caveat.

I.e. we'd always guarantee that the "commit-graph" file was understandable/valid for older versions (even though eventually their view on it would be "oh, this has no data" (but really it's all in a new chunk they don't grok).

Show 9 quoted lines
> On write, if we are creating a new layer to our chain, we need to _copy_
> the existing commit-graph file to a graph-{hash}.graph file before renaming
> the .lock file. If we are merging layers, then we either (a) clean up the
> dangling chains after moving our commit-graph file, or (b) have something
> like 'gc' clean up the files later. I think using 'gc' for this is not
> a good idea, since I would expect these files to be written and merged
> much more frequently (say, after a 'fetch') than a 'gc' is run. Cleaning
> up the dangling chains leads to our concurrency issues. Further, this
> 'copy the base' no longer keeps our large base file at rest.

So aside from the specifics of implementation both this and the commit-graph-N way of doing it involves juggling a sequence of chunks that "point upwards", which IMO has worse caveats than "point downwards". I.e. we'd need to rewrite "base" files to point "upwards" to new stuff, and there's no (sane) way in option 0 to split commit-graphs across repos, and no way at all in this scenario (if I understand it correctly...).

Show 14 quoted lines
> Option 2: grovel commit-graphs directory for graph-{hash}.graph
> ---------------------------------------------------------------
>
> On read, we load the 'info/commit-graph' file and assume it is never
> an incremental file. Then, scan the 'info/commit-graphs' directory
> for 'graph-{hash}.graph' files and open them _all_ up to construct
> a "graph forest" (each graph has a single parent, given by a chunk
> specifying its base graph hash). If we don't have an instance of a
> graph with a given hash, then ignore any graphs pointing to that hash.
> We now have a decision to make: which leaf of this forest should we
> use as our tip commit-graph? That could be given by the
> commit-graphs/info file. But what happens when we have timing issues
> around scanning the directory and the commit-graphs/info file? Do
> we fall back to modified time?

I think in a worst-case scenario we shrug and just pick whatever chain looks most recent/largest or whatever, but in practice I think it's a non-issue.

Critical for that "it's a non-issue" is the suggestion I had on 17/17 of not doing the incremental write in "fetch", but instead just rely on "gc --auto" *and* to address your "I would expect these files to be written and merged much more frequently" we'd just (and I'm keen to hack this up) teach "gc --auto" such an incremental mode.

This means that within a single repo all updates to the commit-graph will go through the gc.lock, whereas with your current 17/17 we'd potentially have a "commit-graph write" racing a concurrent "gc", with both aiming to update the commit-graph.

Show 30 quoted lines
> On write, if we are not merging, then we just create a new
> graph-{hash}.graph file. If we are merging, but still have a base graph,
> then create a new graph-{hash}.graph file. Finally, if we are merging
> all layers, then we rename our .lock file to 'info/commit-graph'.
> To clean up, we need to grovel the directory to look for graph-{hash}.graph
> files whose base chains no longer match the new, "best" chain and unlink()
> them. This clean-up step can happen at any time.
>
> --[end description of options]--
>
> Did I accurately describe the options we are considering?
>
> Option 1 was the design I was planning, and I think it matches how the
> split-index feature works. Please correct me if I am missing something.
> It _requires_ updating the file format version. But it also has a flaw
> that the other options do not have: the copy of the base file. One
> thing I want to enable is for whatever machinery is handling these
> file writes to run a 'verify' immediately after, and have that be fast
> most of the time. With a model that changes only the "tip" file, we
> can verify only the new files and have confidence that the base file
> did not change. I think options 0 and 2 both improve in this direction.
>
>> With commit-graph-<HASH> all these unlink() race conditions go away,
>> partial reads due to concurrent graph writing becomes a non-issue (we'd
>> just leave the old files, "gc" deals with them later..), no need to
>> carefully fsync() files/dirs etc as we need to carefully juggle N and
>> N+1 files.
>
> Calling this a non-issue is an exaggeration, especially if you are
> claiming we need to be robust to multi-hour gaps between reading files.
We always have a race, but they're very different races.

With "N" files (option #0) we'd have races of the type where within the same few milliseconds of a commit-graph being merged/updated a e.g. concurrent "tag --contains" would either be much slower (couldn't get one of the incremental graphs it expected), or produce the wrong answer (this may be wrong on my part, see my "base hash" comment above).

Whereas if I run something with "ionice -c 3" I could possibly hang for however many hours/days/weeks we wait until another "gc" comes along and unlinks those old files, but if I'm running it like that I'm not expecting it to be fast, so it's OK if the files went away, and it won't ever get the wrong file (since the filenames are hash-addressible).

Show 28 quoted lines
>> It also becomes easy to "chain" graphs across repos e.g. via
>> alternates. Say in the scenario github/gitlab have where they have a
>> "main" repo and other objects on another delta island.
>>
>> In that case the repo would have a local "tip" file with the last link
>> in its chain, some of which would then refer back to <HASHes> in other
>> "parent" alternates.
>>
>> As long as such a setup has a "gc" process that's not overly eager about
>> pruning old stuff and considers that constellation of repos as a whole
>> that should just work. You can freely optimize and rewrite graphs across
>> repos, just be careful about unlinking old stuff.
>>
>> I don't see how it would work with commit-graph-N without a *lot* of
>> painful orchestration (where e.g. you *must* guarantee that the parent
>> repo ends in N, all child repos start at N+1).
>
> You're right that Option 0 does not work in this model where some graph
> information is stored in an alternate _and_ more information is stored
> outside the alternate. My perspective is biased, because I consider the
> alternate to be "almost everything" and the local object store to be
> small. But in a fork network, this is not always the case. I appreciate
> your feedback for this environment, and I've always hoped that someone
> with server experience would come and say "this feature is great, but
> we need X, Y, and Z to make best use of it in our environment. Here's
> a patch that moves us in that direction!" At least you are doing the
> next-best thing: stopping me from making mistakes that would block
> adoption.

I'm happy to write some patches, just want to talk about it first (and if I'm lucky convince you to write them for me :) ).

One example is the git-for-windows commit-graph is 5.6MB, the git.git one is 3.1MB. Should GitHub just stick that all in the one "parent" graph, maybe. But nice to have the flexibility of stacking them.

There's also more disconnected cases, e.g. I have some "staging" boxes where where I have a cronjob running around re-pointing clones of a big monorepo to a shared "alternates" store where I guarantee objects are only ever added, never removed.

It would be nice to have a way to provide a commit-graph there that's "stable" that clients could point to, and they'd just generate the difference.

I.e. now I have a shared .git/objects which contains gigabytes, a crapload of stuff in /home where .git/objects is 10-50MB, and each one has a commit-graph that's around the same 50-100MB size (since it needs to contain the metadata for the full set).

Show 20 quoted lines
> So let's consider how Option 2 would work in this "multi-tip" case.
> Each object directory would have some number of graph files, and one
> 'commit-graphs/info' file pointing to some hash. When we read, we
> try to pick the info file that is "closest" to us.
>
> This does create some complications that I don't think you gave enough
> attention to. These may be solvable, but they are non-trivial:
>
> * When we 'gc' the "core" repo, we need to enumerate all of the
>   "leaf" repos to check their tip commit-graph files and make a
>   decision if we should keep their bases around or delete those tips.
>   Perhaps I'm over-stating the difficulty here, since we need to do
>   something similar to find still-reachable objects, anyway. But if
>   we are doing that reachability calculation, then why are we not
>   just putting all of the commit-graph data in the core repo? Note
>   that we don't get the same value as delta islands because this data
>   isn't being shared across the protocol. The issue with storing all
>   graph data in the core repo is that the core repo doesn't actually
>   have all of the commits, which makes 'verify' on the graph a bit
>   annoying.

Yeah I think similar to "alternates" it would be annoying to have a case where a given repo has metadata on objects it doesn't have, and there's cases (see the "staging" case I mentioned above) where that "parent" repo won't have access to those things.

Show 6 quoted lines
> * If we choose a local tip instead of the "core" tip, then that chain
>   of commit-graphs can be far behind the core repo. In the world where
>   a fork moves only at the speed of a single developer, but the core
>   project moves quickly, then computing a merge base with the core's
>   master branch becomes slow as our local chain doesn't contain most
>   of the commits.

That's a good point and a case where pointing "upwards" or just having commit-graphs in the "base" repo is better, i.e. the "fork" has almost no objects.

But solvable by triggering "gc" on these child projects so their commit-graph keeps being re-pointed to a later version.

And we'd have the reverse problem with a git-for-windows wouldn't we? I.e. the fork is "far ahead".

Show 14 quoted lines
> * We can't take all of the "core" chain _and_ the local chain, because
>   the concept of "graph position" no longer makes sense. The only way
>   I see out of this is to make the graph position two-dimensional:
>   commit -> (index of tip chain, position in that chain). Perhaps this
>   is a valuable thing to do in the future? Or perhaps, we shouldn't
>   have incremental chains spanning object directories and instead
>   introduce "parents-by-ref" where we mark some parents as included
>   by object id instead of by graph position. This would allow the
>   core repo to gc without caring about the external repos. It also
>   wouldn't care about how the graph files are stored (Option 0 would
>   work, as graph chains would not cross object store boundaries) and
>   more closely resembles the independence of the pack-files in each
>   object store. The "parents-by-ref" would require updating the
>   file format version.

The parent repo can "gc" without caring/inspecting "child" repos with the "point downwards" of option #2, as long as it promises to retain its old commit-graph files for some retention period of X, and the "child" repos promise to "gc" (and re-point to new graphs if necessary) at rate that's faster than that.

This makes it easy to e.g. say "we retain old commit-graph files for 2 weeks", and "we re-gc everything in cron weekly".

It would work best if we can also pull this trick on the "base" commit-graph file, which I believe we could do in a backwards-compatible way by making "commit-graph" a symlink to whatever "commit-graph-<HASH>" is the current "base".

Show 9 quoted lines
> --[end discussion of incremental files]--
>
> I'll move forward applying your existing feedback on patches 1-11 and
> submit as a full series to replace ds/commit-graph-format-v2. We can
> work on reviewing that code while we continue to think critically on
> the topic of incremental files.
>
> Thanks,
> -Stolee
Previous: Derrick StoleeNext: Derrick Stolee
Message 22 of 136 in “[RFC] Commit-graph: Write incremental files”
  1. 00/17 [RFC] Commit-graph: Write incremental filesDerrick Stolee via GitGitGadget, May 8, 2019
  2. 01/17 commit-graph: fix the_repository referenceDerrick Stolee via GitGitGadget, May 8, 2019
  3. 02/17 commit-graph: return with errors during writeDerrick Stolee via GitGitGadget, May 8, 2019
  4. 03/17 commit-graph: collapse parameters into flagsDerrick Stolee via GitGitGadget, May 8, 2019
  5. 04/17 commit-graph: remove Future Work sectionDerrick Stolee via GitGitGadget, May 8, 2019
  6. 06/17 commit-graph: extract fill_oids_from_packs()Derrick Stolee via GitGitGadget, May 8, 2019
  7. 08/17 commit-graph: extract fill_oids_from_all_packs()Derrick Stolee via GitGitGadget, May 8, 2019
  8. 10/17 commit-graph: extract copy_oids_to_commits()Derrick Stolee via GitGitGadget, May 8, 2019
  9. 09/17 commit-graph: extract count_distinct_commits()Derrick Stolee via GitGitGadget, May 8, 2019
  10. 07/17 commit-graph: extract fill_oids_from_commit_hex()Derrick Stolee via GitGitGadget, May 8, 2019
  11. 05/17 commit-graph: create write_commit_graph_contextDerrick Stolee via GitGitGadget, May 8, 2019
  12. 14/17 commit-graph: load split commit-graph filesDerrick Stolee via GitGitGadget, May 8, 2019
  13. 11/17 commit-graph: extract write_commit_graph_file()Derrick Stolee via GitGitGadget, May 8, 2019
  14. 13/17 commit-graph: lay groundwork for incremental filesDerrick Stolee via GitGitGadget, May 8, 2019
  15. 12/17 Documentation: describe split commit-graphsDerrick Stolee via GitGitGadget, May 8, 2019
  16. SZEDER GáborMay 8, 2019
  17. Derrick StoleeMay 8, 2019
  18. Ævar Arnfjörð BjarmasonMay 8, 2019
  19. Junio C HamanoMay 9, 2019
  20. Derrick StoleeMay 9, 2019
  21. Derrick StoleeMay 9, 2019
  22. Ævar Arnfjörð BjarmasonMay 9, 2019
  23. Derrick StoleeMay 9, 2019
  24. Ævar Arnfjörð BjarmasonMay 9, 2019
  25. Derrick StoleeMay 10, 2019
  26. 16/17 commit-graph: add --split optionDerrick Stolee via GitGitGadget, May 8, 2019
  27. 15/17 commit-graph: write split commit-graph filesDerrick Stolee via GitGitGadget, May 8, 2019
  28. 17/17 fetch: add fetch.writeCommitGraph config settingDerrick Stolee via GitGitGadget, May 8, 2019
  29. Ævar Arnfjörð BjarmasonMay 9, 2019
  30. Derrick StoleeMay 9, 2019
  31. Ævar Arnfjörð BjarmasonMay 8, 2019
  32. 00/11 [RFC] Commit-graph: Write incremental filesDerrick Stolee via GitGitGadget, May 22, 2019
  33. 01/11 commit-graph: document commit-graph chainsDerrick Stolee via GitGitGadget, May 22, 2019
  34. 02/11 commit-graph: prepare for commit-graph chainsDerrick Stolee via GitGitGadget, May 22, 2019
  35. 03/11 commit-graph: rename commit_compare to oid_compareDerrick Stolee via GitGitGadget, May 22, 2019
  36. 04/11 commit-graph: load commit-graph chainsDerrick Stolee via GitGitGadget, May 22, 2019
  37. 05/11 commit-graph: add base graphs chunkDerrick Stolee via GitGitGadget, May 22, 2019
  38. 06/11 commit-graph: rearrange chunk count logicDerrick Stolee via GitGitGadget, May 22, 2019
  39. 08/11 commit-graph: add --split option to builtinDerrick Stolee via GitGitGadget, May 22, 2019
  40. SZEDER GáborMay 27, 2019
  41. 07/11 commit-graph: write commit-graph chainsDerrick Stolee via GitGitGadget, May 22, 2019
  42. 10/11 commit-graph: allow cross-alternate chainsDerrick Stolee via GitGitGadget, May 22, 2019
  43. 09/11 commit-graph: merge commit-graph chainsDerrick Stolee via GitGitGadget, May 22, 2019
  44. Ævar Arnfjörð BjarmasonMay 23, 2019
  45. Derrick StoleeMay 23, 2019
  46. 11/11 commit-graph: expire commit-graph filesDerrick Stolee via GitGitGadget, May 22, 2019
  47. 00/14 Commit-graph: Write incremental filesDerrick Stolee via GitGitGadget, Jun 3, 2019
  48. 01/14 commit-graph: document commit-graph chainsDerrick Stolee via GitGitGadget, Jun 3, 2019
  49. Junio C HamanoJun 5, 2019
  50. Derrick StoleeJun 5, 2019
  51. Philip OakleyJun 6, 2019
  52. Derrick StoleeJun 6, 2019
  53. Philip OakleyJun 6, 2019
  54. 02/14 commit-graph: prepare for commit-graph chainsDerrick Stolee via GitGitGadget, Jun 3, 2019
  55. 04/14 commit-graph: load commit-graph chainsDerrick Stolee via GitGitGadget, Jun 3, 2019
  56. 03/14 commit-graph: rename commit_compare to oid_compareDerrick Stolee via GitGitGadget, Jun 3, 2019
  57. 08/14 commit-graph: add --split option to builtinDerrick Stolee via GitGitGadget, Jun 3, 2019
  58. 06/14 commit-graph: rearrange chunk count logicDerrick Stolee via GitGitGadget, Jun 3, 2019
  59. 05/14 commit-graph: add base graphs chunkDerrick Stolee via GitGitGadget, Jun 3, 2019
  60. 07/14 commit-graph: write commit-graph chainsDerrick Stolee via GitGitGadget, Jun 3, 2019
  61. 10/14 commit-graph: allow cross-alternate chainsDerrick Stolee via GitGitGadget, Jun 3, 2019
  62. 11/14 commit-graph: expire commit-graph filesDerrick Stolee via GitGitGadget, Jun 3, 2019
  63. 09/14 commit-graph: merge commit-graph chainsDerrick Stolee via GitGitGadget, Jun 3, 2019
  64. 14/14 commit-graph: clean up chains after flattened writeDerrick Stolee via GitGitGadget, Jun 3, 2019
  65. 13/14 commit-graph: verify chains with --shallow modeDerrick Stolee via GitGitGadget, Jun 3, 2019
  66. 12/14 commit-graph: create options for split filesDerrick Stolee via GitGitGadget, Jun 3, 2019
  67. 00/14 Commit-graph: Write incremental filesDerrick Stolee via GitGitGadget, Jun 6, 2019
  68. 02/14 commit-graph: prepare for commit-graph chainsDerrick Stolee via GitGitGadget, Jun 6, 2019
  69. Philip OakleyJun 6, 2019
  70. Junio C HamanoJun 6, 2019
  71. Derrick StoleeJun 7, 2019
  72. 03/14 commit-graph: rename commit_compare to oid_compareDerrick Stolee via GitGitGadget, Jun 6, 2019
  73. 01/14 commit-graph: document commit-graph chainsDerrick Stolee via GitGitGadget, Jun 6, 2019
  74. 06/14 commit-graph: rearrange chunk count logicDerrick Stolee via GitGitGadget, Jun 6, 2019
  75. Junio C HamanoJun 7, 2019
  76. 04/14 commit-graph: load commit-graph chainsDerrick Stolee via GitGitGadget, Jun 6, 2019
  77. Junio C HamanoJun 6, 2019
  78. Derrick StoleeJun 7, 2019
  79. 07/14 commit-graph: write commit-graph chainsDerrick Stolee via GitGitGadget, Jun 6, 2019
  80. 05/14 commit-graph: add base graphs chunkDerrick Stolee via GitGitGadget, Jun 6, 2019
  81. Junio C HamanoJun 7, 2019
  82. 09/14 commit-graph: merge commit-graph chainsDerrick Stolee via GitGitGadget, Jun 6, 2019
  83. 11/14 commit-graph: expire commit-graph filesDerrick Stolee via GitGitGadget, Jun 6, 2019
  84. 10/14 commit-graph: allow cross-alternate chainsDerrick Stolee via GitGitGadget, Jun 6, 2019
  85. Philip OakleyJun 6, 2019
  86. 08/14 commit-graph: add --split option to builtinDerrick Stolee via GitGitGadget, Jun 6, 2019
  87. Junio C HamanoJun 7, 2019
  88. Derrick StoleeJun 11, 2019
  89. Junio C HamanoJun 11, 2019
  90. 12/14 commit-graph: create options for split filesDerrick Stolee via GitGitGadget, Jun 6, 2019
  91. Ramsay JonesJun 6, 2019
  92. 13/14 commit-graph: verify chains with --shallow modeDerrick Stolee via GitGitGadget, Jun 6, 2019
  93. 14/14 commit-graph: clean up chains after flattened writeDerrick Stolee via GitGitGadget, Jun 6, 2019
  94. Junio C HamanoJun 6, 2019
  95. Derrick StoleeJun 7, 2019
  96. 00/16 Commit-graph: Write incremental filesDerrick Stolee via GitGitGadget, Jun 7, 2019
  97. 01/16 commit-graph: document commit-graph chainsDerrick Stolee via GitGitGadget, Jun 7, 2019
  98. 02/16 commit-graph: prepare for commit-graph chainsDerrick Stolee via GitGitGadget, Jun 7, 2019
  99. 07/16 commit-graph: write commit-graph chainsDerrick Stolee via GitGitGadget, Jun 7, 2019
  100. 08/16 commit-graph: add --split option to builtinDerrick Stolee via GitGitGadget, Jun 7, 2019
  101. 05/16 commit-graph: add base graphs chunkDerrick Stolee via GitGitGadget, Jun 7, 2019
  102. 04/16 commit-graph: load commit-graph chainsDerrick Stolee via GitGitGadget, Jun 7, 2019
  103. Junio C HamanoJun 10, 2019
  104. Derrick StoleeJun 10, 2019
  105. 03/16 commit-graph: rename commit_compare to oid_compareDerrick Stolee via GitGitGadget, Jun 7, 2019
  106. 10/16 commit-graph: allow cross-alternate chainsDerrick Stolee via GitGitGadget, Jun 7, 2019
  107. 09/16 commit-graph: merge commit-graph chainsDerrick Stolee via GitGitGadget, Jun 7, 2019
  108. 13/16 commit-graph: verify chains with --shallow modeDerrick Stolee via GitGitGadget, Jun 7, 2019
  109. 15/16 commit-graph: test octopus merges with --splitDerrick Stolee via GitGitGadget, Jun 7, 2019
  110. 16/16 commit-graph: test --split across alternate without --splitDerrick Stolee via GitGitGadget, Jun 7, 2019
  111. 14/16 commit-graph: clean up chains after flattened writeDerrick Stolee via GitGitGadget, Jun 7, 2019
  112. 12/16 commit-graph: create options for split filesDerrick Stolee via GitGitGadget, Jun 7, 2019
  113. 06/16 commit-graph: rearrange chunk count logicDerrick Stolee via GitGitGadget, Jun 7, 2019
  114. 11/16 commit-graph: expire commit-graph filesDerrick Stolee via GitGitGadget, Jun 7, 2019
  115. commit-graph: normalize commit-graph filenamesDerrick Stolee, Jun 17, 2019
  116. Derrick StoleeJun 17, 2019
  117. commit-graph: normalize commit-graph filenamesDerrick Stolee, Jun 17, 2019
  118. 00/18 Commit-graph: Write incremental filesDerrick Stolee via GitGitGadget, Jun 18, 2019
  119. 01/18 commit-graph: document commit-graph chainsDerrick Stolee via GitGitGadget, Jun 18, 2019
  120. 04/18 commit-graph: load commit-graph chainsDerrick Stolee via GitGitGadget, Jun 18, 2019
  121. 05/18 commit-graph: add base graphs chunkDerrick Stolee via GitGitGadget, Jun 18, 2019
  122. 03/18 commit-graph: rename commit_compare to oid_compareDerrick Stolee via GitGitGadget, Jun 18, 2019
  123. 08/18 commit-graph: add --split option to builtinDerrick Stolee via GitGitGadget, Jun 18, 2019
  124. 09/18 commit-graph: merge commit-graph chainsDerrick Stolee via GitGitGadget, Jun 18, 2019
  125. 06/18 commit-graph: rearrange chunk count logicDerrick Stolee via GitGitGadget, Jun 18, 2019
  126. 07/18 commit-graph: write commit-graph chainsDerrick Stolee via GitGitGadget, Jun 18, 2019
  127. 10/18 commit-graph: allow cross-alternate chainsDerrick Stolee via GitGitGadget, Jun 18, 2019
  128. 02/18 commit-graph: prepare for commit-graph chainsDerrick Stolee via GitGitGadget, Jun 18, 2019
  129. 14/18 commit-graph: clean up chains after flattened writeDerrick Stolee via GitGitGadget, Jun 18, 2019
  130. 15/18 commit-graph: test octopus merges with --splitDerrick Stolee via GitGitGadget, Jun 18, 2019
  131. 18/18 commit-graph: test verify across alternatesDerrick Stolee via GitGitGadget, Jun 18, 2019
  132. 11/18 commit-graph: expire commit-graph filesDerrick Stolee via GitGitGadget, Jun 18, 2019
  133. 13/18 commit-graph: verify chains with --shallow modeDerrick Stolee via GitGitGadget, Jun 18, 2019
  134. 12/18 commit-graph: create options for split filesDerrick Stolee via GitGitGadget, Jun 18, 2019
  135. 16/18 commit-graph: test --split across alternate without --splitDerrick Stolee via GitGitGadget, Jun 18, 2019
  136. 17/18 commit-graph: normalize commit-graph filenamesDerrick Stolee via GitGitGadget, Jun 18, 2019

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.