upload-pack: disable commit graph more gently for shallow traversal

When the client has asked for certain shallow options like
"deepen-since", we do a custom rev-list walk that pretends to be
shallow. Before doing so, we have to disable the commit-graph, since it
is not compatible with the shallow view of the repository. That's
handled by 829a321569 (commit-graph: close_commit_graph before shallow
walk, 2018-08-20). That commit literally closes and frees our
repo->objects->commit_graph struct.

That creates an interesting problem for commits that have _already_ been
parsed using the commit graph. Their commit->object.parsed flag is set,
their commit->graph_pos is set, but their commit->maybe_tree may still
be NULL. When somebody later calls repo_get_commit_tree(), we see that
we haven't loaded the tree oid yet and try to get it from the commit
graph. But since it has been freed, we segfault!

So the root of the issue is a data dependency between the commit's
lazy-load of the tree oid and the fact that the commit graph can go
away mid-process. How can we resolve it?

There are a couple of general approaches:

  1. The obvious answer is to avoid loading the tree from the graph when
     we see that it's NULL. But then what do we return for the tree oid?
     If we return NULL, our caller in do_traverse() will rightly
     complain that we have no tree. We'd have to fallback to loading the
     actual commit object and re-parsing it. That requires teaching
     parse_commit_buffer() to understand re-parsing (i.e., not starting
     from a clean slate and not leaking any allocated bits like parent
     list pointers).

  2. When we close the commit graph, walk through the set of in-memory
     objects and clear any graph_pos pointers. But this means we also
     have to "unparse" any such commits so that we know they still need
     to open the commit object to fill in their trees. So it's no less
     complicated than (1), and is more expensive (since we clear objects
     we might not later need).

  3. Stop freeing the commit-graph struct. Continue to let it be used
     for lazy-loads of tree oids, but let upload-pack specify that it
     shouldn't be used for further commit parsing.

  4. Push the whole shallow rev-list out to its own sub-process, with
     the commit-graph disabled from the start, giving it a clean memory
     space to work from.

I've chosen (3) here. Options (1) and (2) would work, but are
non-trivial to implement. Option (4) is more expensive, and I'm not sure
how complicated it is (shelling out for the actual rev-list part is
easy, but we do then parse the resulting commits internally, and I'm not
clear which parts need to be handling shallow-ness).

The new test in t5500 triggers this segfault, but see the comments there
for how horribly intimate it has to be with how both upload-pack and
commit graphs work.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 files changed
tree: 9de02f0dea7a699bb7e6e16301ec71a84e507f4b
  1. .github/
  2. block-sha1/
  3. builtin/
  4. ci/
  5. compat/
  6. contrib/
  7. Documentation/
  8. ewah/
  9. git-gui/
  10. gitk-git/
  11. gitweb/
  12. mergetools/
  13. negotiator/
  14. perl/
  15. po/
  16. ppc/
  17. refs/
  18. sha1dc/
  19. sha256/
  20. t/
  21. templates/
  22. trace2/
  23. vcs-svn/
  24. xdiff/
  25. .clang-format
  26. .editorconfig
  27. .gitattributes
  28. .gitignore
  29. .gitmodules
  30. .mailmap
  31. .travis.yml
  32. .tsan-suppressions
  33. abspath.c
  34. aclocal.m4
  35. advice.c
  36. advice.h
  37. alias.c
  38. alias.h
  39. alloc.c
  40. alloc.h
  41. apply.c
  42. apply.h
  43. archive-tar.c
  44. archive-zip.c
  45. archive.c
  46. archive.h
  47. argv-array.c
  48. argv-array.h
  49. attr.c
  50. attr.h
  51. azure-pipelines.yml
  52. banned.h
  53. base85.c
  54. bisect.c
  55. bisect.h
  56. blame.c
  57. blame.h
  58. blob.c
  59. blob.h
  60. branch.c
  61. branch.h
  62. builtin.h
  63. bulk-checkin.c
  64. bulk-checkin.h
  65. bundle.c
  66. bundle.h
  67. cache-tree.c
  68. cache-tree.h
  69. cache.h
  70. chdir-notify.c
  71. chdir-notify.h
  72. check-builtins.sh
  73. check_bindir
  74. checkout.c
  75. checkout.h
  76. color.c
  77. color.h
  78. column.c
  79. column.h
  80. combine-diff.c
  81. command-list.txt
  82. commit-graph.c
  83. commit-graph.h
  84. commit-reach.c
  85. commit-reach.h
  86. commit-slab-decl.h
  87. commit-slab-impl.h
  88. commit-slab.h
  89. commit.c
  90. commit.h
  91. common-main.c
  92. config.c
  93. config.h
  94. config.mak.dev
  95. config.mak.in
  96. config.mak.uname
  97. configure.ac
  98. connect.c
  99. connect.h
  100. connected.c
  101. connected.h
  102. convert.c
  103. convert.h
  104. copy.c
  105. COPYING
  106. credential-cache--daemon.c
  107. credential-cache.c
  108. credential-store.c
  109. credential.c
  110. credential.h
  111. csum-file.c
  112. csum-file.h
  113. ctype.c
  114. daemon.c
  115. date.c
  116. decorate.c
  117. decorate.h
  118. delta-islands.c
  119. delta-islands.h
  120. delta.h
  121. detect-compiler
  122. diff-delta.c
  123. diff-lib.c
  124. diff-no-index.c
  125. diff.c
  126. diff.h
  127. diffcore-break.c
  128. diffcore-delta.c
  129. diffcore-order.c
  130. diffcore-pickaxe.c
  131. diffcore-rename.c
  132. diffcore.h
  133. dir-iterator.c
  134. dir-iterator.h
  135. dir.c
  136. dir.h
  137. editor.c
  138. entry.c
  139. environment.c
  140. exec-cmd.c
  141. exec-cmd.h
  142. fast-import.c
  143. fetch-negotiator.c
  144. fetch-negotiator.h
  145. fetch-object.c
  146. fetch-object.h
  147. fetch-pack.c
  148. fetch-pack.h
  149. fmt-merge-msg.h
  150. fsck.c
  151. fsck.h
  152. fsmonitor.c
  153. fsmonitor.h
  154. fuzz-commit-graph.c
  155. fuzz-pack-headers.c
  156. fuzz-pack-idx.c
  157. generate-cmdlist.sh
  158. gettext.c
  159. gettext.h
  160. git-add--interactive.perl
  161. git-archimport.perl
  162. git-bisect.sh
  163. git-compat-util.h
  164. git-cvsexportcommit.perl
  165. git-cvsimport.perl
  166. git-cvsserver.perl
  167. git-difftool--helper.sh
  168. git-filter-branch.sh
  169. git-instaweb.sh
  170. git-legacy-stash.sh
  171. git-merge-octopus.sh
  172. git-merge-one-file.sh
  173. git-merge-resolve.sh
  174. git-mergetool--lib.sh
  175. git-mergetool.sh
  176. git-p4.py
  177. git-parse-remote.sh
  178. git-quiltimport.sh
  179. git-rebase--preserve-merges.sh
  180. git-request-pull.sh
  181. git-send-email.perl
  182. git-sh-i18n.sh
  183. git-sh-setup.sh
  184. git-submodule.sh
  185. git-svn.perl
  186. GIT-VERSION-GEN
  187. git-web--browse.sh
  188. git.c
  189. git.rc
  190. gpg-interface.c
  191. gpg-interface.h
  192. graph.c
  193. graph.h
  194. grep.c
  195. grep.h
  196. hash.h
  197. hashmap.c
  198. hashmap.h
  199. help.c
  200. help.h
  201. hex.c
  202. http-backend.c
  203. http-fetch.c
  204. http-push.c
  205. http-walker.c
  206. http.c
  207. http.h
  208. ident.c
  209. imap-send.c
  210. INSTALL
  211. interdiff.c
  212. interdiff.h
  213. iterator.h
  214. json-writer.c
  215. json-writer.h
  216. khash.h
  217. kwset.c
  218. kwset.h
  219. levenshtein.c
  220. levenshtein.h
  221. LGPL-2.1
  222. line-log.c
  223. line-log.h
  224. line-range.c
  225. line-range.h
  226. linear-assignment.c
  227. linear-assignment.h
  228. list-objects-filter-options.c
  229. list-objects-filter-options.h
  230. list-objects-filter.c
  231. list-objects-filter.h
  232. list-objects.c
  233. list-objects.h
  234. list.h
  235. ll-merge.c
  236. ll-merge.h
  237. lockfile.c
  238. lockfile.h
  239. log-tree.c
  240. log-tree.h
  241. ls-refs.c
  242. ls-refs.h
  243. mailinfo.c
  244. mailinfo.h
  245. mailmap.c
  246. mailmap.h
  247. Makefile
  248. match-trees.c
  249. mem-pool.c
  250. mem-pool.h
  251. merge-blobs.c
  252. merge-blobs.h
  253. merge-recursive.c
  254. merge-recursive.h
  255. merge.c
  256. mergesort.c
  257. mergesort.h
  258. midx.c
  259. midx.h
  260. name-hash.c
  261. notes-cache.c
  262. notes-cache.h
  263. notes-merge.c
  264. notes-merge.h
  265. notes-utils.c
  266. notes-utils.h
  267. notes.c
  268. notes.h
  269. object-store.h
  270. object.c
  271. object.h
  272. oidmap.c
  273. oidmap.h
  274. oidset.c
  275. oidset.h
  276. pack-bitmap-write.c
  277. pack-bitmap.c
  278. pack-bitmap.h
  279. pack-check.c
  280. pack-objects.c
  281. pack-objects.h
  282. pack-revindex.c
  283. pack-revindex.h
  284. pack-write.c
  285. pack.h
  286. packfile.c
  287. packfile.h
  288. pager.c
  289. parse-options-cb.c
  290. parse-options.c
  291. parse-options.h
  292. patch-delta.c
  293. patch-ids.c
  294. patch-ids.h
  295. path.c
  296. path.h
  297. pathspec.c
  298. pathspec.h
  299. pkt-line.c
  300. pkt-line.h
  301. preload-index.c
  302. pretty.c
  303. pretty.h
  304. prio-queue.c
  305. prio-queue.h
  306. progress.c
  307. progress.h
  308. prompt.c
  309. prompt.h
  310. protocol.c
  311. protocol.h
  312. quote.c
  313. quote.h
  314. range-diff.c
  315. range-diff.h
  316. reachable.c
  317. reachable.h
  318. read-cache.c
  319. README.md
  320. rebase-interactive.c
  321. rebase-interactive.h
  322. ref-filter.c
  323. ref-filter.h
  324. reflog-walk.c
  325. reflog-walk.h
  326. refs.c
  327. refs.h
  328. refspec.c
  329. refspec.h
  330. remote-curl.c
  331. remote-testsvn.c
  332. remote.c
  333. remote.h
  334. replace-object.c
  335. replace-object.h
  336. repo-settings.c
  337. repository.c
  338. repository.h
  339. rerere.c
  340. rerere.h
  341. resolve-undo.c
  342. resolve-undo.h
  343. revision.c
  344. revision.h
  345. run-command.c
  346. run-command.h
  347. send-pack.c
  348. send-pack.h
  349. sequencer.c
  350. sequencer.h
  351. serve.c
  352. serve.h
  353. server-info.c
  354. setup.c
  355. sh-i18n--envsubst.c
  356. sha1-array.c
  357. sha1-array.h
  358. sha1-file.c
  359. sha1-lookup.c
  360. sha1-lookup.h
  361. sha1-name.c
  362. sha1dc_git.c
  363. sha1dc_git.h
  364. shallow.c
  365. shell.c
  366. shortlog.h
  367. sideband.c
  368. sideband.h
  369. sigchain.c
  370. sigchain.h
  371. split-index.c
  372. split-index.h
  373. strbuf.c
  374. strbuf.h
  375. streaming.c
  376. streaming.h
  377. string-list.c
  378. string-list.h
  379. sub-process.c
  380. sub-process.h
  381. submodule-config.c
  382. submodule-config.h
  383. submodule.c
  384. submodule.h
  385. symlinks.c
  386. tag.c
  387. tag.h
  388. tar.h
  389. tempfile.c
  390. tempfile.h
  391. thread-utils.c
  392. thread-utils.h
  393. tmp-objdir.c
  394. tmp-objdir.h
  395. trace.c
  396. trace.h
  397. trace2.c
  398. trace2.h
  399. trailer.c
  400. trailer.h
  401. transport-helper.c
  402. transport-internal.h
  403. transport.c
  404. transport.h
  405. tree-diff.c
  406. tree-walk.c
  407. tree-walk.h
  408. tree.c
  409. tree.h
  410. unicode-width.h
  411. unimplemented.sh
  412. unix-socket.c
  413. unix-socket.h
  414. unpack-trees.c
  415. unpack-trees.h
  416. upload-pack.c
  417. upload-pack.h
  418. url.c
  419. url.h
  420. urlmatch.c
  421. urlmatch.h
  422. usage.c
  423. userdiff.c
  424. userdiff.h
  425. utf8.c
  426. utf8.h
  427. varint.c
  428. varint.h
  429. version.c
  430. version.h
  431. versioncmp.c
  432. walker.c
  433. walker.h
  434. wildmatch.c
  435. wildmatch.h
  436. worktree.c
  437. worktree.h
  438. wrap-for-bin.sh
  439. wrapper.c
  440. write-or-die.c
  441. ws.c
  442. wt-status.c
  443. wt-status.h
  444. xdiff-interface.c
  445. xdiff-interface.h
  446. zlib.c
README.md

Build Status

Git - fast, scalable, distributed revision control system

Git is a fast, scalable, distributed revision control system with an unusually rich command set that provides both high-level operations and full access to internals.

Git is an Open Source project covered by the GNU General Public License version 2 (some parts of it are under different licenses, compatible with the GPLv2). It was originally written by Linus Torvalds with help of a group of hackers around the net.

Please read the file INSTALL for installation instructions.

Many Git online resources are accessible from https://git-scm.com/ including full documentation and Git related tools.

See Documentation/gittutorial.txt to get started, then see Documentation/giteveryday.txt for a useful minimum set of commands, and Documentation/git-<commandname>.txt for documentation of each command. If git has been correctly installed, then the tutorial can also be read with man gittutorial or git help tutorial, and the documentation of each command with man git-<commandname> or git help <commandname>.

CVS users may also want to read Documentation/gitcvs-migration.txt (man gitcvs-migration or git help cvs-migration if git is installed).

The user discussion and development of Git take place on the Git mailing list -- everyone is welcome to post bug reports, feature requests, comments and patches to git@vger.kernel.org (read Documentation/SubmittingPatches for instructions on patch submission). To subscribe to the list, send an email with just “subscribe git” in the body to majordomo@vger.kernel.org. The mailing list archives are available at https://public-inbox.org/git/, http://marc.info/?l=git and other archival sites.

Issues which are security relevant should be disclosed privately to the Git Security mailing list git-security@googlegroups.com.

The maintainer frequently sends the “What's cooking” reports that list the current status of various development topics to the mailing list. The discussion following them give a good reference for project status, development direction and remaining tasks.

The name “git” was given by Linus Torvalds when he wrote the very first version. He described the tool as “the stupid content tracker” and the name as (depending on your mood):

  • random three-letter combination that is pronounceable, and not actually used by any common UNIX command. The fact that it is a mispronunciation of “get” may or may not be relevant.
  • stupid. contemptible and despicable. simple. Take your pick from the dictionary of slang.
  • “global information tracker”: you're in a good mood, and it actually works for you. Angels sing, and a light suddenly fills the room.
  • “goddamn idiotic truckload of sh*t”: when it breaks