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

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

From
Derrick Stolee <stolee@gmail.com>
Date
May 10, 2019, 12:44 UTC
Message-ID
<6d9c0911-6f36-3fb7-2be9-2be9bc68fc69@gmail.com>
In-Reply-To
<874l63xpwx.fsf@evledraar.gmail.com>
On 5/9/2019 5:45 PM, Ævar Arnfjörð Bjarmason wrote:
Show 24 quoted lines
> 
> On Thu, May 09 2019, Derrick Stolee wrote:
> 
>> How far apart can these concurrency issues happen in the file system?
>> One benefit to Option 0 is that there is only one file _write_ that matters.
>> The other options require at least two writes.
> 
> You need to write() and then fsync()/close() to be guaranteed that the
> data was written to the file.
> 
> As an aside I see that the current commit-graph uses CSUM_FSYNC (but
> without CSUM_CLOSE, probably doesn't matter), I thought it
> didn't. Maybe we should remove that unless core.fsyncObjectFiles=true
> (or have another "looser" fsync config).
> 
> So writing is cheap, but it's asking the OS to sync to disk that
> generally hurts. As noted in the discussions when core.fsyncObjectFiles
> was introduced some FSs are really stupid about it, so it's better to
> avoid these caveats if you can.
> 
> As noted in the fsync(2) manpage on Linux (ditto POSIX) an fsync to a
> *file* doesn't guarantee that the directory entry is updated. So we'd
> also need to opendir() the containing directory and fsync that FD as we
> juggle these renames/replaces.

I think any plan should not rely on directory scanning for this reason. Starting from a known file (info/commit-graphs/head?) and then navigating directly to files would avoid these issues, right?

Show 14 quoted lines
>> That would prevent breaking old clients, but they would also not have any
>> commit-graph data to use. Option 0 and Option 2 can leave a valid v1
>> commit-graph file with the majority of the commit data. This is only a
>> performance issue for a narrow case, so maybe that's worth ignoring.
> 
> Indeed. As noted in the thread about the v1->v2 format if we just append
> new chunks we have leeway like that, i.e. it's completely OK if we
> choose to from the POV of old clients write no data to them so they're
> not helped by the optimization, that's a more graceful way than them
> dying on a format change.
> 
> And yes, we could stick the proposed commit-graphs/info "index" in a
> chunk there. I've got a preference for a \n-delimited list similar to
> objects/info/packs, but that's mostly for aesthetic reasons.

I think a \n-delimited list would be better because using the commit-graph format with zero commits creates at least a kilobyte of data for a zero-valued fanout table. If we relax the format to say "the head file has zero commits, so the fanout, commit oids, and commit data chunks should not exist" then we would be fine, and get versioning "for free". But the file serves a different purpose.

Show 12 quoted lines
>>> 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).
>>
>> How do we recover from this situation? Have no commit-graph at all? Or
>> do we try again?
> 
> I think just no commit-graph at all is fine. If it lazily took you N
> hours from reading the "commit-graphs/info" to getting around to looking
> at now-disappeared files it sucks to be you.

Sounds good. We can revisit if this actually starts hurting any real scenarios.

Show 17 quoted lines
>>> And we'd have the reverse problem with a git-for-windows wouldn't we?
>>> I.e. the fork is "far ahead".
>>
>> This is the quintessential example for why we can't have a single chain
>> of commit-graphs long-term. It deviates from most fork networks enough
>> that we can't say "just take the base repo's commit-graph" but typical
>> fork networks can't say "just take my local commit-graph chain". The
>> two-dimensional graph position would be valuable to help both shapes.
> 
> Indeed. I just thought about e.g. a [branch|tag] --contains for the
> current repo, but for things like "how ahead of gitster/pu is my GFW
> topic?" one graph for the network is needed.
> 
> If we can help it it would be useful to not unduly box the user in and
> offer them flexibility to choose. I.e. some (e.g. my staging server
> use-case) might want base+local repo and never need 2x local repos
> v.s. each other, whereas github/gitlab might need one giant graph etc.
I made a note to follow up with the two-dimensional graph position [1].
[1] https://github.com/microsoft/git/issues/138
Show 39 quoted lines
>>> 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".
>>
>> Here, I think, is the most crucial point of why Option 2 may be worth the
>> added complexity over Option 0. Option 0 _requires_ that the files be
>> replaced immediately on a new write, while Option 2 provides a way to
>> leave old files around and be cleaned up later.
>>
>> But how should we actually perform this cleanup? I would imagine a
>> 'git commit-graph gc' subcommand that cleans up old files. A 'git gc'
>> run would perform the same logic, but we need a way to do this outside
>> of 'gc'. It needs to use the modified time as an indicator, since we
>> could run 'git commit-graph write' twice an hour before our two-week
>> cleanup job and need to keep our hour-old stale file. Perhaps the
>> 'git commit-graph gc' subcommand could take a '--window' parameter that
>> can be 0, while 'git gc' uses a config setting.
>>
>> The decision can then be: "is this file not in our graph chain and
>> older than <window> from now?"
>>
>> But also, I expect the stale commit-graph files will pile up quickly.
>> We rebuild the commit-graph file roughly every hour. I would write
>> our maintenance to call these subcommands in order with no delay:
>>
>>     "write" -> "verify --shallow" -> "gc --window=0"
>>
>> (Here, "verify --shallow" would only verify the tip of the
>> commit-graph chain.)
> 
> I think a sane default would be to just unlink() the old ones as soon as
> we're done writing the new ones & writing the commit-graphs/info file
> saying "here's your current ones".
> 
> I.e. as noted in what I said about fsync above it's not that we need to
> keep the old ones around, but avoiding the tight dance with N & N+1
> updates, and being friendlier to stuff like lookupcache=positive.
> 
> Users with more advanced use-cases (e.g. cross-repo graphs) could then
> always increase such an expiry.
Noted. Thanks.
Show 11 quoted lines
>>> 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".
>>
>> Could we do this, anyway? Use 'commit-graphs/info' to point to the tip
>> and let the symlink 'commit-graph' point to the base. Then, old clients
>> would load a full commit-graph and new clients would get the full chain.
> 
> How's the Windows support for symlinks? We don't symlink anything in
> .git/objects/ ourselves now (but see[1]).

Maybe this won't work in all scenarios, but it could be left as a future enhancement if anyone cares. The "support two versions" scenario is rare enough to avoid building something specifically for it, but often enough to not _break_ it.

Show 21 quoted lines
> On *nix just manually symlinking it works fine (you need to go out of
> your way not to support it, which we didn't).
> 
> So something like this would be desirable:
> 
>     $ tree -a .git/objects/info/
>     .git/objects/info/
>     ├── commit-graph -> commit-graphs/commit-graph-2492e0ef38643d4cb6369f76443e6a814d616258
>     ├── commit-graphs
>     │   ├── commit-graph-2492e0ef38643d4cb6369f76443e6a814d616258
>     │   ├── commit-graph-988881adc9fc3655077dc2d4d757d480b5ea0e11
>     │   └── info
>     └── packs
>     $ cat .git/objects/info/commit-graphs/info
>     2492e0ef38643d4cb6369f76443e6a814d616258
>     988881adc9fc3655077dc2d4d757d480b5ea0e11
> 
> I.e. create new ones as needed, and when done say what sequence they
> should be read in in the "info" file, and symlink "commit-graph" to
> whatever the latest "base" is as a courtesy to old clients (or not, or
> eventually don't bother).
OK. Glad that the idea would work.

Thanks, -Stolee

Previous: Ævar Arnfjörð BjarmasonNext: Derrick Stolee via GitGitGadget
Message 25 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.