git: add --no-optional-locks option

Some tools like IDEs or fancy editors may periodically run
commands like "git status" in the background to keep track
of the state of the repository. Some of these commands may
refresh the index and write out the result in an
opportunistic way: if they can get the index lock, then they
update the on-disk index with any updates they find. And if
not, then their in-core refresh is lost and just has to be
recomputed by the next caller.

But taking the index lock may conflict with other operations
in the repository. Especially ones that the user is doing
themselves, which _aren't_ opportunistic. In other words,
"git status" knows how to back off when somebody else is
holding the lock, but other commands don't know that status
would be happy to drop the lock if somebody else wanted it.

There are a couple possible solutions:

  1. Have some kind of "pseudo-lock" that allows other
     commands to tell status that they want the lock.

     This is likely to be complicated and error-prone to
     implement (and maybe even impossible with just
     dotlocks to work from, as it requires some
     inter-process communication).

  2. Avoid background runs of commands like "git status"
     that want to do opportunistic updates, preferring
     instead plumbing like diff-files, etc.

     This is awkward for a couple of reasons. One is that
     "status --porcelain" reports a lot more about the
     repository state than is available from individual
     plumbing commands. And two is that we actually _do_
     want to see the refreshed index. We just don't want to
     take a lock or write out the result. Whereas commands
     like diff-files expect us to refresh the index
     separately and write it to disk so that they can depend
     on the result. But that write is exactly what we're
     trying to avoid.

  3. Ask "status" not to lock or write the index.

     This is easy to implement. The big downside is that any
     work done in refreshing the index for such a call is
     lost when the process exits. So a background process
     may end up re-hashing a changed file multiple times
     until the user runs a command that does an index
     refresh themselves.

This patch implements the option 3. The idea (and the test)
is largely stolen from a Git for Windows patch by Johannes
Schindelin, 67e5ce7f63 (status: offer *not* to lock the
index and update it, 2016-08-12). The twist here is that
instead of making this an option to "git status", it becomes
a "git" option and matching environment variable.

The reason there is two-fold:

  1. An environment variable is carried through to
     sub-processes. And whether an invocation is a
     background process or not should apply to the whole
     process tree. So you could do "git --no-optional-locks
     foo", and if "foo" is a script or alias that calls
     "status", you'll still get the effect.

  2. There may be other programs that want the same
     treatment.

     I've punted here on finding more callers to convert,
     since "status" is the obvious one to call as a repeated
     background job. But "git diff"'s opportunistic refresh
     of the index may be a good candidate.

The test is taken from 67e5ce7f63, and it's worth repeating
Johannes's explanation:

  Note that the regression test added in this commit does
  not *really* verify that no index.lock file was written;
  that test is not possible in a portable way. Instead, we
  verify that .git/index is rewritten *only* when `git
  status` is run without `--no-optional-locks`.

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

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-.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.

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