summary refs log tree commit
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CODE_OF_CONDUCT.md93
-rw-r--r--Documentation/CodingGuidelines4
-rw-r--r--Documentation/Makefile1
-rw-r--r--Documentation/MyFirstContribution.txt53
-rw-r--r--Documentation/MyFirstObjectWalk.txt906
-rw-r--r--Documentation/RelNotes/1.5.0.txt4
-rw-r--r--Documentation/RelNotes/1.6.5.4.txt2
-rw-r--r--Documentation/RelNotes/1.7.0.2.txt2
-rw-r--r--Documentation/RelNotes/1.7.10.4.txt2
-rw-r--r--Documentation/RelNotes/1.7.12.3.txt2
-rw-r--r--Documentation/RelNotes/1.7.5.3.txt2
-rw-r--r--Documentation/RelNotes/1.8.0.txt2
-rw-r--r--Documentation/RelNotes/1.8.4.1.txt2
-rw-r--r--Documentation/RelNotes/2.1.3.txt2
-rw-r--r--Documentation/RelNotes/2.10.0.txt2
-rw-r--r--Documentation/RelNotes/2.10.2.txt2
-rw-r--r--Documentation/RelNotes/2.11.1.txt2
-rw-r--r--Documentation/RelNotes/2.12.0.txt2
-rw-r--r--Documentation/RelNotes/2.13.0.txt2
-rw-r--r--Documentation/RelNotes/2.13.3.txt4
-rw-r--r--Documentation/RelNotes/2.14.0.txt4
-rw-r--r--Documentation/RelNotes/2.16.0.txt2
-rw-r--r--Documentation/RelNotes/2.16.3.txt2
-rw-r--r--Documentation/RelNotes/2.17.0.txt2
-rw-r--r--Documentation/RelNotes/2.18.0.txt2
-rw-r--r--Documentation/RelNotes/2.19.0.txt2
-rw-r--r--Documentation/RelNotes/2.20.0.txt2
-rw-r--r--Documentation/RelNotes/2.24.0.txt69
-rw-r--r--Documentation/RelNotes/2.25.0.txt68
-rw-r--r--Documentation/RelNotes/2.3.3.txt2
-rw-r--r--Documentation/RelNotes/2.3.7.txt2
-rw-r--r--Documentation/RelNotes/2.4.3.txt2
-rw-r--r--Documentation/RelNotes/2.7.0.txt2
-rw-r--r--Documentation/RelNotes/2.8.0.txt2
-rw-r--r--Documentation/RelNotes/2.9.3.txt2
-rw-r--r--Documentation/config.txt2
-rw-r--r--Documentation/config/core.txt10
-rw-r--r--Documentation/config/fetch.txt10
-rw-r--r--Documentation/config/format.txt8
-rw-r--r--Documentation/config/pack.txt4
-rw-r--r--Documentation/config/tag.txt2
-rw-r--r--Documentation/config/trace2.txt6
-rw-r--r--Documentation/fetch-options.txt17
-rw-r--r--Documentation/git-am.txt2
-rw-r--r--Documentation/git-bisect-lk2009.txt2
-rw-r--r--Documentation/git-bisect.txt2
-rw-r--r--Documentation/git-bundle.txt35
-rw-r--r--Documentation/git-check-attr.txt2
-rw-r--r--Documentation/git-check-ignore.txt2
-rw-r--r--Documentation/git-clone.txt8
-rw-r--r--Documentation/git-commit-graph.txt12
-rw-r--r--Documentation/git-cvsserver.txt2
-rw-r--r--Documentation/git-diff.txt2
-rw-r--r--Documentation/git-fast-export.txt19
-rw-r--r--Documentation/git-fast-import.txt23
-rw-r--r--Documentation/git-filter-branch.txt4
-rw-r--r--Documentation/git-format-patch.txt25
-rw-r--r--Documentation/git-multi-pack-index.txt6
-rw-r--r--Documentation/git-notes.txt6
-rw-r--r--Documentation/git-range-diff.txt2
-rw-r--r--Documentation/git-read-tree.txt2
-rw-r--r--Documentation/git-rebase.txt4
-rw-r--r--Documentation/git-rev-parse.txt7
-rw-r--r--Documentation/git-shortlog.txt3
-rw-r--r--Documentation/git-sparse-checkout.txt153
-rw-r--r--Documentation/git-stash.txt5
-rw-r--r--Documentation/git-tag.txt2
-rw-r--r--Documentation/git-update-index.txt8
-rw-r--r--Documentation/git.txt4
-rw-r--r--Documentation/gitattributes.txt8
-rw-r--r--Documentation/gitmodules.txt2
-rw-r--r--Documentation/gitremote-helpers.txt5
-rw-r--r--Documentation/gitrepository-layout.txt10
-rw-r--r--Documentation/gitsubmodules.txt2
-rw-r--r--Documentation/howto/separating-topic-branches.txt2
-rw-r--r--Documentation/manpage-bold-literal.xsl3
-rw-r--r--Documentation/merge-options.txt2
-rw-r--r--Documentation/merge-strategies.txt2
-rw-r--r--Documentation/pretty-formats.txt6
-rw-r--r--Documentation/rev-list-options.txt11
-rw-r--r--Documentation/technical/api-config.txt319
-rw-r--r--Documentation/technical/api-grep.txt8
-rw-r--r--Documentation/technical/api-object-access.txt15
-rw-r--r--Documentation/technical/api-quote.txt10
-rw-r--r--Documentation/technical/api-submodule-config.txt2
-rw-r--r--Documentation/technical/api-trace2.txt45
-rw-r--r--Documentation/technical/api-xdiff-interface.txt7
-rw-r--r--Documentation/technical/commit-graph.txt12
-rw-r--r--Documentation/technical/hash-function-transition.txt4
-rw-r--r--Documentation/technical/index-format.txt4
-rw-r--r--Documentation/technical/pack-protocol.txt2
-rw-r--r--Documentation/technical/partial-clone.txt2
-rw-r--r--Documentation/technical/protocol-v2.txt2
-rw-r--r--Documentation/technical/rerere.txt2
-rw-r--r--Documentation/trace2-target-values.txt4
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--INSTALL6
-rw-r--r--Makefile9
l---------RelNotes2
-rw-r--r--apply.c49
-rw-r--r--attr.c24
-rw-r--r--azure-pipelines.yml164
-rw-r--r--blame.c25
-rw-r--r--builtin.h1
-rw-r--r--builtin/am.c2
-rw-r--r--builtin/blame.c32
-rw-r--r--builtin/bundle.c217
-rw-r--r--builtin/checkout.c14
-rw-r--r--builtin/clone.c38
-rw-r--r--builtin/commit-graph.c71
-rw-r--r--builtin/commit.c22
-rw-r--r--builtin/describe.c21
-rw-r--r--builtin/difftool.c56
-rw-r--r--builtin/fast-export.c82
-rw-r--r--builtin/fetch.c197
-rw-r--r--builtin/fsck.c126
-rw-r--r--builtin/gc.c4
-rw-r--r--builtin/grep.c1
-rw-r--r--builtin/log.c141
-rw-r--r--builtin/merge-recursive.c4
-rw-r--r--builtin/multi-pack-index.c18
-rw-r--r--builtin/notes.c2
-rw-r--r--builtin/pack-objects.c237
-rw-r--r--builtin/push.c6
-rw-r--r--builtin/read-tree.c3
-rw-r--r--builtin/rebase.c7
-rw-r--r--builtin/repack.c9
-rw-r--r--builtin/rev-parse.c11
-rw-r--r--builtin/sparse-checkout.c488
-rw-r--r--builtin/stash.c16
-rw-r--r--builtin/update-index.c6
-rw-r--r--builtin/worktree.c2
-rw-r--r--bundle.c9
-rw-r--r--bundle.h3
-rw-r--r--cache-tree.c85
-rw-r--r--cache-tree.h3
-rw-r--r--cache.h27
-rwxr-xr-xci/install-dependencies.sh6
-rw-r--r--column.c13
-rw-r--r--command-list.txt2
-rw-r--r--commit-graph.c18
-rw-r--r--commit-reach.c1
-rw-r--r--commit.c57
-rw-r--r--commit.h2
-rw-r--r--compat/mingw.c6
-rw-r--r--compat/mingw.h2
-rw-r--r--compat/nedmalloc/malloc.c.h6
-rw-r--r--compat/obstack.h2
-rw-r--r--compat/regex/regcomp.c2
-rw-r--r--compat/regex/regex.h2
-rw-r--r--compat/regex/regex_internal.c2
-rw-r--r--compat/regex/regexec.c4
-rw-r--r--compat/vcbuild/find_vs_env.bat2
-rwxr-xr-xcompat/vcbuild/scripts/clink.pl48
-rw-r--r--compat/win32/path-utils.h5
-rw-r--r--compat/win32/pthread.h2
-rw-r--r--compat/winansi.c2
-rw-r--r--config.c29
-rw-r--r--config.h335
-rw-r--r--config.mak.uname19
-rw-r--r--configure.ac51
-rw-r--r--connected.c3
-rw-r--r--contrib/buildsystems/Generators/Vcxproj.pm3
-rw-r--r--contrib/coccinelle/commit.cocci2
-rw-r--r--contrib/coccinelle/hashmap.cocci16
-rw-r--r--contrib/coccinelle/object_id.cocci32
-rw-r--r--contrib/completion/git-completion.bash9
-rw-r--r--contrib/completion/git-completion.zsh5
-rw-r--r--contrib/diff-highlight/DiffHighlight.pm2
-rwxr-xr-xcontrib/hooks/multimail/git_multimail.py8
-rwxr-xr-xcontrib/hooks/multimail/post-receive.example2
-rwxr-xr-xcontrib/hooks/post-receive-email2
-rwxr-xr-xcontrib/hooks/update-paranoid2
-rw-r--r--contrib/mw-to-git/.perlcriticrc2
-rwxr-xr-xcontrib/mw-to-git/git-remote-mediawiki.perl2
-rw-r--r--contrib/mw-to-git/t/install-wiki/db_install.php2
-rwxr-xr-xcontrib/mw-to-git/t/t9360-mw-to-git-clone.sh2
-rwxr-xr-xcontrib/mw-to-git/t/test-gitmw-lib.sh2
-rwxr-xr-xcontrib/svn-fe/svnrdump_sim.py2
-rw-r--r--convert.c24
-rw-r--r--csum-file.h9
-rw-r--r--daemon.c4
-rw-r--r--diff.c35
-rw-r--r--diffcore-rename.c15
-rw-r--r--dir.c209
-rw-r--r--dir.h36
-rw-r--r--environment.c1
-rw-r--r--ewah/bitmap.c13
-rw-r--r--ewah/ewok.h1
-rw-r--r--fast-import.c92
-rw-r--r--fetch-pack.c109
-rw-r--r--fsck.c386
-rw-r--r--fsck.h39
-rw-r--r--fsmonitor.c31
-rw-r--r--git-compat-util.h40
-rwxr-xr-xgit-cvsimport.perl2
-rw-r--r--git-gui/README.md174
-rwxr-xr-xgit-gui/git-gui.sh15
-rw-r--r--git-gui/lib/diff.tcl33
-rw-r--r--git-gui/po/ja.po9
-rwxr-xr-xgit-legacy-stash.sh5
-rwxr-xr-xgit-send-email.perl2
-rw-r--r--git.c1
-rwxr-xr-xgitweb/gitweb.perl49
-rw-r--r--gitweb/static/js/blame_incremental.js2
-rw-r--r--graph.c646
-rw-r--r--grep.c47
-rw-r--r--grep.h2
-rw-r--r--hashmap.c60
-rw-r--r--hashmap.h178
-rw-r--r--help.c2
-rw-r--r--hex.c10
-rw-r--r--http-push.c8
-rw-r--r--http.c18
-rw-r--r--merge-recursive.c757
-rw-r--r--merge-recursive.h164
-rw-r--r--midx.c71
-rw-r--r--midx.h10
-rw-r--r--name-hash.c61
-rw-r--r--object.h3
-rw-r--r--oidmap.c20
-rw-r--r--oidmap.h6
-rw-r--r--pack-bitmap.c178
-rw-r--r--pack-bitmap.h6
-rw-r--r--pack-objects.c5
-rw-r--r--pack-objects.h19
-rw-r--r--packfile.c32
-rw-r--r--packfile.h3
-rw-r--r--parse-options-cb.c3
-rw-r--r--parse-options.c2
-rw-r--r--patch-ids.c18
-rw-r--r--path.c128
-rw-r--r--perl/Git.pm2
-rw-r--r--po/bg.po4987
-rw-r--r--po/ca.po60
-rw-r--r--po/de.po5044
-rw-r--r--po/es.po5220
-rw-r--r--po/fr.po4994
-rw-r--r--po/git.pot4924
-rw-r--r--po/it.po5034
-rw-r--r--po/sv.po5240
-rw-r--r--po/vi.po5040
-rw-r--r--po/zh_CN.po4978
-rw-r--r--pretty.c9
-rw-r--r--promisor-remote.c3
-rw-r--r--quote.c6
-rw-r--r--range-diff.c10
-rw-r--r--range-diff.h2
-rw-r--r--read-cache.c6
-rw-r--r--ref-filter.c33
-rw-r--r--refs.c25
-rw-r--r--refs/refs-internal.h2
-rw-r--r--remote-curl.c35
-rw-r--r--remote.c21
-rw-r--r--remote.h2
-rw-r--r--repo-settings.c2
-rw-r--r--repository.c4
-rw-r--r--repository.h2
-rw-r--r--rerere.c2
-rw-r--r--revision.c28
-rw-r--r--send-pack.c11
-rw-r--r--sequencer.c100
-rw-r--r--sequencer.h3
-rw-r--r--server-info.c2
-rw-r--r--sha1-lookup.c4
-rw-r--r--sha1dc/sha1.c2
-rw-r--r--sha1dc_git.c2
-rw-r--r--string-list.h2
-rw-r--r--sub-process.c20
-rw-r--r--sub-process.h6
-rw-r--r--submodule-config.c52
-rw-r--r--t/gitweb-lib.sh7
-rw-r--r--t/helper/test-hashmap.c50
-rw-r--r--t/helper/test-lazy-init-name-hash.c12
-rw-r--r--t/helper/test-progress.c2
-rw-r--r--t/helper/test-read-graph.c53
-rw-r--r--t/helper/test-run-command.c153
-rw-r--r--t/helper/test-tool.c1
-rw-r--r--t/helper/test-tool.h1
-rw-r--r--t/lib-rebase.sh28
-rw-r--r--t/oid-info/hash-info9
-rwxr-xr-xt/perf/bisect_regression2
-rwxr-xr-xt/perf/p5303-many-packs.sh1
-rwxr-xr-xt/t0000-basic.sh40
-rwxr-xr-xt/t0014-alias.sh7
-rwxr-xr-xt/t0027-auto-crlf.sh2
-rwxr-xr-xt/t0028-working-tree-encoding.sh45
-rwxr-xr-xt/t0060-path-utils.sh4
-rwxr-xr-xt/t0212-trace2-event.sh19
-rwxr-xr-xt/t0500-progress-display.sh4
-rwxr-xr-xt/t1050-large.sh6
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh293
-rwxr-xr-xt/t1305-config-include.sh2
-rwxr-xr-xt/t1308-config-set.sh8
-rwxr-xr-xt/t1400-update-ref.sh18
-rwxr-xr-xt/t1450-fsck.sh2
-rwxr-xr-xt/t1500-rev-parse.sh15
-rwxr-xr-xt/t1512-rev-parse-disambiguation.sh2
-rwxr-xr-xt/t1600-index.sh4
-rwxr-xr-xt/t2400-worktree-add.sh24
-rwxr-xr-xt/t3030-merge-recursive.sh9
-rwxr-xr-xt/t3060-ls-files-with-tree.sh4
-rwxr-xr-xt/t3206-range-diff.sh40
-rw-r--r--t/t3206/history.export31
-rwxr-xr-xt/t3210-pack-refs.sh2
-rwxr-xr-xt/t3301-notes.sh46
-rwxr-xr-xt/t3404-rebase-interactive.sh596
-rwxr-xr-xt/t3429-rebase-edit-todo.sh2
-rwxr-xr-xt/t3430-rebase-merges.sh2
-rwxr-xr-xt/t3434-rebase-i18n.sh84
-rw-r--r--t/t3434/ISO8859-1.txt3
-rw-r--r--t/t3434/eucJP.txt4
-rwxr-xr-xt/t3900-i18n-commit.sh37
-rwxr-xr-xt/t3903-stash.sh18
-rwxr-xr-xt/t3905-stash-include-untracked.sh4
-rwxr-xr-xt/t3906-stash-submodule.sh42
-rwxr-xr-xt/t4010-diff-pathspec.sh20
-rwxr-xr-xt/t4011-diff-symlink.sh40
-rwxr-xr-xt/t4014-format-patch.sh203
-rwxr-xr-xt/t4015-diff-whitespace.sh89
-rwxr-xr-xt/t4018-diff-funcname.sh1
-rw-r--r--t/t4018/dts-nodes-boolean-prop9
-rw-r--r--t/t4018/dts-nodes-multiline-prop13
-rw-r--r--t/t4018/dts-root2
-rw-r--r--t/t4018/dts-root-comment8
-rw-r--r--t/t4018/elixir-do-not-pick-end5
-rw-r--r--t/t4018/elixir-ex-unit-test6
-rw-r--r--t/t4018/elixir-function5
-rw-r--r--t/t4018/elixir-macro5
-rw-r--r--t/t4018/elixir-module9
-rw-r--r--t/t4018/elixir-module-func8
-rw-r--r--t/t4018/elixir-nested-module9
-rw-r--r--t/t4018/elixir-private-function5
-rw-r--r--t/t4018/elixir-protocol6
-rw-r--r--t/t4018/elixir-protocol-implementation5
-rwxr-xr-xt/t4027-diff-submodule.sh16
-rwxr-xr-xt/t4034-diff-words.sh93
-rwxr-xr-xt/t4038-diff-combined.sh19
-rwxr-xr-xt/t4039-diff-assume-unchanged.sh3
-rwxr-xr-xt/t4041-diff-submodule-option.sh20
-rwxr-xr-xt/t4044-diff-index-unique-abbrev.sh46
-rwxr-xr-xt/t4045-diff-relative.sh2
-rwxr-xr-xt/t4048-diff-combined-binary.sh58
-rwxr-xr-xt/t4057-diff-combined-paths.sh2
-rw-r--r--t/t4100/t-apply-1.patch4
-rw-r--r--t/t4100/t-apply-3.patch2
-rw-r--r--t/t4100/t-apply-5.patch4
-rw-r--r--t/t4100/t-apply-7.patch2
-rwxr-xr-xt/t4108-apply-threeway.sh55
-rwxr-xr-xt/t4202-log.sh2
-rwxr-xr-xt/t4203-mailmap.sh122
-rwxr-xr-xt/t4205-log-pretty-formats.sh2
-rwxr-xr-xt/t4213-log-tabexpand.sh2
-rwxr-xr-xt/t4214-log-graph-octopus.sh353
-rwxr-xr-xt/t4215-log-skewed-merges.sh243
-rwxr-xr-xt/t5318-commit-graph.sh10
-rwxr-xr-xt/t5319-multi-pack-index.sh69
-rwxr-xr-xt/t5324-split-commit-graph.sh2
-rwxr-xr-xt/t5510-fetch.sh16
-rwxr-xr-xt/t5514-fetch-multiple.sh11
-rwxr-xr-xt/t5528-push-default.sh2
-rwxr-xr-xt/t5535-fetch-push-symref.sh2
-rwxr-xr-xt/t5541-http-push-smart.sh40
-rwxr-xr-xt/t5545-push-options.sh2
-rwxr-xr-xt/t5616-partial-clone.sh78
-rwxr-xr-xt/t5702-protocol-v2.sh10
-rwxr-xr-xt/t6006-rev-list-format.sh28
-rwxr-xr-xt/t6016-rev-list-graph-simplify-history.sh30
-rwxr-xr-xt/t6024-recursive-merge.sh130
-rwxr-xr-xt/t6036-recursive-corner-cases.sh12
-rwxr-xr-xt/t6042-merge-rename-corner-cases.sh111
-rwxr-xr-xt/t6043-merge-rename-directories.sh574
-rwxr-xr-xt/t6046-merge-skip-unneeded-updates.sh135
-rwxr-xr-xt/t6047-diff3-conflict-markers.sh202
-rwxr-xr-xt/t6102-rev-list-unexpected-objects.sh2
-rwxr-xr-xt/t6500-gc.sh14
-rwxr-xr-xt/t7004-tag.sh8
-rwxr-xr-xt/t7012-skip-worktree-writing.sh15
-rwxr-xr-xt/t7030-verify-tag.sh14
-rwxr-xr-xt/t7419-submodule-set-branch.sh6
-rwxr-xr-xt/t7508-status.sh2
-rwxr-xr-xt/t7513-interpret-trailers.sh2
-rwxr-xr-xt/t7519-status-fsmonitor.sh21
-rwxr-xr-xt/t7519/fsmonitor-env24
-rwxr-xr-xt/t7519/fsmonitor-watchman13
-rwxr-xr-xt/t9001-send-email.sh2
-rwxr-xr-xt/t9300-fast-import.sh37
-rwxr-xr-xt/t9301-fast-import-notes.sh2
-rwxr-xr-xt/t9350-fast-export.sh68
-rwxr-xr-xt/t9502-gitweb-standalone-parse-output.sh7
-rwxr-xr-xt/t9809-git-p4-client-view.sh2
-rwxr-xr-xt/t9902-completion.sh11
-rw-r--r--t/test-lib-functions.sh6
-rw-r--r--t/test-lib.sh58
-rw-r--r--tag.c21
-rwxr-xr-xtemplates/hooks--fsmonitor-watchman.sample13
-rw-r--r--trace2/tr2_dst.c111
-rw-r--r--trace2/tr2_dst.h1
-rw-r--r--trace2/tr2_sid.c2
-rw-r--r--trace2/tr2_sysenv.c3
-rw-r--r--trace2/tr2_sysenv.h2
-rw-r--r--trace2/tr2_tgt_event.c31
-rw-r--r--trace2/tr2_tgt_normal.c2
-rw-r--r--trace2/tr2_tgt_perf.c19
-rw-r--r--transport-helper.c4
-rw-r--r--transport.c14
-rw-r--r--transport.h3
-rw-r--r--unpack-trees.c114
-rw-r--r--unpack-trees.h3
-rw-r--r--url.c2
-rw-r--r--usage.c20
-rw-r--r--userdiff.c15
-rw-r--r--utf8.c15
-rw-r--r--xdiff-interface.h2
-rw-r--r--xdiff/xdiffi.c99
416 files changed, 34280 insertions, 26049 deletions
diff --git a/.gitignore b/.gitignore
index 89b3b79c1a..aebe7c0908 100644
--- a/.gitignore
+++ b/.gitignore
@@ -158,6 +158,7 @@
 /git-show-branch
 /git-show-index
 /git-show-ref
+/git-sparse-checkout
 /git-stage
 /git-stash
 /git-status
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000..fc4645d5c0
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,93 @@
+# Git Code of Conduct
+
+This code of conduct outlines our expectations for participants within
+the Git community, as well as steps for reporting unacceptable behavior.
+We are committed to providing a welcoming and inspiring community for
+all and expect our code of conduct to be honored. Anyone who violates
+this code of conduct may be banned from the community.
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to make participation in our project and
+our community a harassment-free experience for everyone, regardless of age,
+body size, disability, ethnicity, sex characteristics, gender identity and
+expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+  advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+  address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies within all project spaces, and it also applies
+when an individual is representing the project or its community in public
+spaces. Examples of representing a project or community include using an
+official project e-mail address, posting via an official social media account,
+or acting as an appointed representative at an online or offline event.
+Representation of a project may be further defined and clarified by project
+maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at git@sfconservancy.org. All
+complaints will be reviewed and investigated and will result in a response
+that is deemed necessary and appropriate to the circumstances. The project
+team is obligated to maintain confidentiality with regard to the reporter of
+an incident. Further details of specific enforcement policies may be posted
+separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+The project leadership team can be contacted by email as a whole at
+git@sfconservancy.org, or individually:
+
+  - Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+  - Christian Couder <christian.couder@gmail.com>
+  - Jeff King <peff@peff.net>
+  - Junio C Hamano <gitster@pobox.com>
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see
+https://www.contributor-covenant.org/faq
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index f45db5b727..ed4e443a3c 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -75,7 +75,7 @@ For shell scripts specifically (not exhaustive):
 
  - If you want to find out if a command is available on the user's
    $PATH, you should use 'type <command>', instead of 'which <command>'.
-   The output of 'which' is not machine parseable and its exit code
+   The output of 'which' is not machine parsable and its exit code
    is not reliable across platforms.
 
  - We use POSIX compliant parameter substitutions and avoid bashisms;
@@ -203,7 +203,7 @@ For C programs:
    . since early 2012 with e1327023ea, we have been using an enum
      definition whose last element is followed by a comma.  This, like
      an array initializer that ends with a trailing comma, can be used
-     to reduce the patch noise when adding a new identifer at the end.
+     to reduce the patch noise when adding a new identifier at the end.
 
    . since mid 2017 with cbc0f81d, we have been using designated
      initializers for struct (e.g. "struct t v = { .val = 'a' };").
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 06d85ad958..8fe829cc1b 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -77,6 +77,7 @@ API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technica
 SP_ARTICLES += $(API_DOCS)
 
 TECH_DOCS += MyFirstContribution
+TECH_DOCS += MyFirstObjectWalk
 TECH_DOCS += SubmittingPatches
 TECH_DOCS += technical/hash-function-transition
 TECH_DOCS += technical/http-protocol
diff --git a/Documentation/MyFirstContribution.txt b/Documentation/MyFirstContribution.txt
index 5e9b808f5f..b55837e646 100644
--- a/Documentation/MyFirstContribution.txt
+++ b/Documentation/MyFirstContribution.txt
@@ -38,6 +38,26 @@ $ git clone https://github.com/git/git git
 $ cd git
 ----
 
+[[dependencies]]
+=== Installing Dependencies
+
+To build Git from source, you need to have a handful of dependencies installed
+on your system. For a hint of what's needed, you can take a look at
+`INSTALL`, paying close attention to the section about Git's dependencies on
+external programs and libraries. That document mentions a way to "test-drive"
+our freshly built Git without installing; that's the method we'll be using in
+this tutorial.
+
+Make sure that your environment has everything you need by building your brand
+new clone of Git from the above step:
+
+----
+$ make
+----
+
+NOTE: The Git build is parallelizable. `-j#` is not included above but you can
+use it as you prefer, here and elsewhere.
+
 [[identify-problem]]
 === Identify Problem to Solve
 
@@ -138,9 +158,6 @@ NOTE: When you are developing the Git project, it's preferred that you use the
 `DEVELOPER` flag; if there's some reason it doesn't work for you, you can turn
 it off, but it's a good idea to mention the problem to the mailing list.
 
-NOTE: The Git build is parallelizable. `-j#` is not included above but you can
-use it as you prefer, here and elsewhere.
-
 Great, now your new command builds happily on its own. But nobody invokes it.
 Let's change that.
 
@@ -534,6 +551,28 @@ you want to pass as a parameter something which would usually be interpreted as
 a flag.) `parse_options()` will terminate parsing when it reaches `--` and give
 you the rest of the options afterwards, untouched.
 
+Now that you have a usage hint, you can teach Git how to show it in the general
+command list shown by `git help git` or `git help -a`, which is generated from
+`command-list.txt`. Find the line for 'git-pull' so you can add your 'git-psuh'
+line above it in alphabetical order. Now, we can add some attributes about the
+command which impacts where it shows up in the aforementioned help commands. The
+top of `command-list.txt` shares some information about what each attribute
+means; in those help pages, the commands are sorted according to these
+attributes. `git psuh` is user-facing, or porcelain - so we will mark it as
+"mainporcelain". For "mainporcelain" commands, the comments at the top of
+`command-list.txt` indicate we can also optionally add an attribute from another
+list; since `git psuh` shows some information about the user's workspace but
+doesn't modify anything, let's mark it as "info". Make sure to keep your
+attributes in the same style as the rest of `command-list.txt` using spaces to
+align and delineate them:
+
+----
+git-prune-packed                        plumbingmanipulators
+git-psuh                                mainporcelain                info
+git-pull                                mainporcelain           remote
+git-push                                mainporcelain           remote
+----
+
 Build again. Now, when you run with `-h`, you should see your usage printed and
 your command terminated before anything else interesting happens. Great!
 
@@ -746,6 +785,14 @@ will automatically run your PRs through the CI even without the permission given
 but you will not be able to `/submit` your changes until someone allows you to
 use the tool.
 
+NOTE: You can typically find someone who can `/allow` you on GitGitGadget by
+either examining recent pull requests where someone has been granted `/allow`
+(https://github.com/gitgitgadget/git/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+%22%2Fallow%22[Search:
+is:pr is:open "/allow"]), in which case both the author and the person who
+granted the `/allow` can now `/allow` you, or by inquiring on the
+https://webchat.freenode.net/#git-devel[#git-devel] IRC channel on Freenode
+linking your pull request and asking for someone to `/allow` you.
+
 If the CI fails, you can update your changes with `git rebase -i` and push your
 branch again:
 
diff --git a/Documentation/MyFirstObjectWalk.txt b/Documentation/MyFirstObjectWalk.txt
new file mode 100644
index 0000000000..4d24daeb9f
--- /dev/null
+++ b/Documentation/MyFirstObjectWalk.txt
@@ -0,0 +1,906 @@
+= My First Object Walk
+
+== What's an Object Walk?
+
+The object walk is a key concept in Git - this is the process that underpins
+operations like object transfer and fsck. Beginning from a given commit, the
+list of objects is found by walking parent relationships between commits (commit
+X based on commit W) and containment relationships between objects (tree Y is
+contained within commit X, and blob Z is located within tree Y, giving our
+working tree for commit X something like `y/z.txt`).
+
+A related concept is the revision walk, which is focused on commit objects and
+their parent relationships and does not delve into other object types. The
+revision walk is used for operations like `git log`.
+
+=== Related Reading
+
+- `Documentation/user-manual.txt` under "Hacking Git" contains some coverage of
+  the revision walker in its various incarnations.
+- `Documentation/technical/api-revision-walking.txt`
+- https://eagain.net/articles/git-for-computer-scientists/[Git for Computer Scientists]
+  gives a good overview of the types of objects in Git and what your object
+  walk is really describing.
+
+== Setting Up
+
+Create a new branch from `master`.
+
+----
+git checkout -b revwalk origin/master
+----
+
+We'll put our fiddling into a new command. For fun, let's name it `git walken`.
+Open up a new file `builtin/walken.c` and set up the command handler:
+
+----
+/*
+ * "git walken"
+ *
+ * Part of the "My First Object Walk" tutorial.
+ */
+
+#include "builtin.h"
+
+int cmd_walken(int argc, const char **argv, const char *prefix)
+{
+        trace_printf(_("cmd_walken incoming...\n"));
+        return 0;
+}
+----
+
+NOTE: `trace_printf()` differs from `printf()` in that it can be turned on or
+off at runtime. For the purposes of this tutorial, we will write `walken` as
+though it is intended for use as a "plumbing" command: that is, a command which
+is used primarily in scripts, rather than interactively by humans (a "porcelain"
+command). So we will send our debug output to `trace_printf()` instead. When
+running, enable trace output by setting the environment variable `GIT_TRACE`.
+
+Add usage text and `-h` handling, like all subcommands should consistently do
+(our test suite will notice and complain if you fail to do so).
+
+----
+int cmd_walken(int argc, const char **argv, const char *prefix)
+{
+        const char * const walken_usage[] = {
+                N_("git walken"),
+                NULL,
+        }
+        struct option options[] = {
+                OPT_END()
+        };
+
+        argc = parse_options(argc, argv, prefix, options, walken_usage, 0);
+
+        ...
+}
+----
+
+Also add the relevant line in `builtin.h` near `cmd_whatchanged()`:
+
+----
+int cmd_walken(int argc, const char **argv, const char *prefix);
+----
+
+Include the command in `git.c` in `commands[]` near the entry for `whatchanged`,
+maintaining alphabetical ordering:
+
+----
+{ "walken", cmd_walken, RUN_SETUP },
+----
+
+Add it to the `Makefile` near the line for `builtin/worktree.o`:
+
+----
+BUILTIN_OBJS += builtin/walken.o
+----
+
+Build and test out your command, without forgetting to ensure the `DEVELOPER`
+flag is set, and with `GIT_TRACE` enabled so the debug output can be seen:
+
+----
+$ echo DEVELOPER=1 >>config.mak
+$ make
+$ GIT_TRACE=1 ./bin-wrappers/git walken
+----
+
+NOTE: For a more exhaustive overview of the new command process, take a look at
+`Documentation/MyFirstContribution.txt`.
+
+NOTE: A reference implementation can be found at
+https://github.com/nasamuffin/git/tree/revwalk.
+
+=== `struct rev_cmdline_info`
+
+The definition of `struct rev_cmdline_info` can be found in `revision.h`.
+
+This struct is contained within the `rev_info` struct and is used to reflect
+parameters provided by the user over the CLI.
+
+`nr` represents the number of `rev_cmdline_entry` present in the array.
+
+`alloc` is used by the `ALLOC_GROW` macro. Check
+`Documentation/technical/api-allocation-growing.txt` - this variable is used to
+track the allocated size of the list.
+
+Per entry, we find:
+
+`item` is the object provided upon which to base the object walk. Items in Git
+can be blobs, trees, commits, or tags. (See `Documentation/gittutorial-2.txt`.)
+
+`name` is the object ID (OID) of the object - a hex string you may be familiar
+with from using Git to organize your source in the past. Check the tutorial
+mentioned above towards the top for a discussion of where the OID can come
+from.
+
+`whence` indicates some information about what to do with the parents of the
+specified object. We'll explore this flag more later on; take a look at
+`Documentation/revisions.txt` to get an idea of what could set the `whence`
+value.
+
+`flags` are used to hint the beginning of the revision walk and are the first
+block under the `#include`s in `revision.h`. The most likely ones to be set in
+the `rev_cmdline_info` are `UNINTERESTING` and `BOTTOM`, but these same flags
+can be used during the walk, as well.
+
+=== `struct rev_info`
+
+This one is quite a bit longer, and many fields are only used during the walk
+by `revision.c` - not configuration options. Most of the configurable flags in
+`struct rev_info` have a mirror in `Documentation/rev-list-options.txt`. It's a
+good idea to take some time and read through that document.
+
+== Basic Commit Walk
+
+First, let's see if we can replicate the output of `git log --oneline`. We'll
+refer back to the implementation frequently to discover norms when performing
+an object walk of our own.
+
+To do so, we'll first find all the commits, in order, which preceded the current
+commit. We'll extract the name and subject of the commit from each.
+
+Ideally, we will also be able to find out which ones are currently at the tip of
+various branches.
+
+=== Setting Up
+
+Preparing for your object walk has some distinct stages.
+
+1. Perform default setup for this mode, and others which may be invoked.
+2. Check configuration files for relevant settings.
+3. Set up the `rev_info` struct.
+4. Tweak the initialized `rev_info` to suit the current walk.
+5. Prepare the `rev_info` for the walk.
+6. Iterate over the objects, processing each one.
+
+==== Default Setups
+
+Before examining configuration files which may modify command behavior, set up
+default state for switches or options your command may have. If your command
+utilizes other Git components, ask them to set up their default states as well.
+For instance, `git log` takes advantage of `grep` and `diff` functionality, so
+its `init_log_defaults()` sets its own state (`decoration_style`) and asks
+`grep` and `diff` to initialize themselves by calling each of their
+initialization functions.
+
+For our first example within `git walken`, we don't intend to use any other
+components within Git, and we don't have any configuration to do.  However, we
+may want to add some later, so for now, we can add an empty placeholder. Create
+a new function in `builtin/walken.c`:
+
+----
+static void init_walken_defaults(void)
+{
+        /*
+         * We don't actually need the same components `git log` does; leave this
+         * empty for now.
+         */
+}
+----
+
+Make sure to add a line invoking it inside of `cmd_walken()`.
+
+----
+int cmd_walken(int argc, const char **argv, const char *prefix)
+{
+        init_walken_defaults();
+}
+----
+
+==== Configuring From `.gitconfig`
+
+Next, we should have a look at any relevant configuration settings (i.e.,
+settings readable and settable from `git config`). This is done by providing a
+callback to `git_config()`; within that callback, you can also invoke methods
+from other components you may need that need to intercept these options. Your
+callback will be invoked once per each configuration value which Git knows about
+(global, local, worktree, etc.).
+
+Similarly to the default values, we don't have anything to do here yet
+ourselves; however, we should call `git_default_config()` if we aren't calling
+any other existing config callbacks.
+
+Add a new function to `builtin/walken.c`:
+
+----
+static int git_walken_config(const char *var, const char *value, void *cb)
+{
+        /*
+         * For now, we don't have any custom configuration, so fall back to
+         * the default config.
+         */
+        return git_default_config(var, value, cb);
+}
+----
+
+Make sure to invoke `git_config()` with it in your `cmd_walken()`:
+
+----
+int cmd_walken(int argc, const char **argv, const char *prefix)
+{
+        ...
+
+        git_config(git_walken_config, NULL);
+
+        ...
+}
+----
+
+==== Setting Up `rev_info`
+
+Now that we've gathered external configuration and options, it's time to
+initialize the `rev_info` object which we will use to perform the walk. This is
+typically done by calling `repo_init_revisions()` with the repository you intend
+to target, as well as the `prefix` argument of `cmd_walken` and your `rev_info`
+struct.
+
+Add the `struct rev_info` and the `repo_init_revisions()` call:
+----
+int cmd_walken(int argc, const char **argv, const char *prefix)
+{
+        /* This can go wherever you like in your declarations.*/
+        struct rev_info rev;
+        ...
+
+        /* This should go after the git_config() call. */
+        repo_init_revisions(the_repository, &rev, prefix);
+
+        ...
+}
+----
+
+==== Tweaking `rev_info` For the Walk
+
+We're getting close, but we're still not quite ready to go. Now that `rev` is
+initialized, we can modify it to fit our needs. This is usually done within a
+helper for clarity, so let's add one:
+
+----
+static void final_rev_info_setup(struct rev_info *rev)
+{
+        /*
+         * We want to mimic the appearance of `git log --oneline`, so let's
+         * force oneline format.
+         */
+        get_commit_format("oneline", rev);
+
+        /* Start our object walk at HEAD. */
+        add_head_to_pending(rev);
+}
+----
+
+[NOTE]
+====
+Instead of using the shorthand `add_head_to_pending()`, you could do
+something like this:
+----
+        struct setup_revision_opt opt;
+
+        memset(&opt, 0, sizeof(opt));
+        opt.def = "HEAD";
+        opt.revarg_opt = REVARG_COMMITTISH;
+        setup_revisions(argc, argv, rev, &opt);
+----
+Using a `setup_revision_opt` gives you finer control over your walk's starting
+point.
+====
+
+Then let's invoke `final_rev_info_setup()` after the call to
+`repo_init_revisions()`:
+
+----
+int cmd_walken(int argc, const char **argv, const char *prefix)
+{
+        ...
+
+        final_rev_info_setup(&rev);
+
+        ...
+}
+----
+
+Later, we may wish to add more arguments to `final_rev_info_setup()`. But for
+now, this is all we need.
+
+==== Preparing `rev_info` For the Walk
+
+Now that `rev` is all initialized and configured, we've got one more setup step
+before we get rolling. We can do this in a helper, which will both prepare the
+`rev_info` for the walk, and perform the walk itself. Let's start the helper
+with the call to `prepare_revision_walk()`, which can return an error without
+dying on its own:
+
+----
+static void walken_commit_walk(struct rev_info *rev)
+{
+        if (prepare_revision_walk(rev))
+                die(_("revision walk setup failed"));
+}
+----
+
+NOTE: `die()` prints to `stderr` and exits the program. Since it will print to
+`stderr` it's likely to be seen by a human, so we will localize it.
+
+==== Performing the Walk!
+
+Finally! We are ready to begin the walk itself. Now we can see that `rev_info`
+can also be used as an iterator; we move to the next item in the walk by using
+`get_revision()` repeatedly. Add the listed variable declarations at the top and
+the walk loop below the `prepare_revision_walk()` call within your
+`walken_commit_walk()`:
+
+----
+static void walken_commit_walk(struct rev_info *rev)
+{
+        struct commit *commit;
+        struct strbuf prettybuf = STRBUF_INIT;
+
+        ...
+
+        while ((commit = get_revision(rev))) {
+                if (!commit)
+                        continue;
+
+                strbuf_reset(&prettybuf);
+                pp_commit_easy(CMIT_FMT_ONELINE, commit, &prettybuf);
+                puts(prettybuf.buf);
+        }
+        strbuf_release(&prettybuf);
+}
+----
+
+NOTE: `puts()` prints a `char*` to `stdout`. Since this is the part of the
+command we expect to be machine-parsed, we're sending it directly to stdout.
+
+Give it a shot.
+
+----
+$ make
+$ ./bin-wrappers/git walken
+----
+
+You should see all of the subject lines of all the commits in
+your tree's history, in order, ending with the initial commit, "Initial revision
+of "git", the information manager from hell". Congratulations! You've written
+your first revision walk. You can play with printing some additional fields
+from each commit if you're curious; have a look at the functions available in
+`commit.h`.
+
+=== Adding a Filter
+
+Next, let's try to filter the commits we see based on their author. This is
+equivalent to running `git log --author=<pattern>`. We can add a filter by
+modifying `rev_info.grep_filter`, which is a `struct grep_opt`.
+
+First some setup. Add `init_grep_defaults()` to `init_walken_defaults()` and add
+`grep_config()` to `git_walken_config()`:
+
+----
+static void init_walken_defaults(void)
+{
+        init_grep_defaults(the_repository);
+}
+
+...
+
+static int git_walken_config(const char *var, const char *value, void *cb)
+{
+        grep_config(var, value, cb);
+        return git_default_config(var, value, cb);
+}
+----
+
+Next, we can modify the `grep_filter`. This is done with convenience functions
+found in `grep.h`. For fun, we're filtering to only commits from folks using a
+`gmail.com` email address - a not-very-precise guess at who may be working on
+Git as a hobby. Since we're checking the author, which is a specific line in the
+header, we'll use the `append_header_grep_pattern()` helper. We can use
+the `enum grep_header_field` to indicate which part of the commit header we want
+to search.
+
+In `final_rev_info_setup()`, add your filter line:
+
+----
+static void final_rev_info_setup(int argc, const char **argv,
+                const char *prefix, struct rev_info *rev)
+{
+        ...
+
+        append_header_grep_pattern(&rev->grep_filter, GREP_HEADER_AUTHOR,
+                "gmail");
+        compile_grep_patterns(&rev->grep_filter);
+
+        ...
+}
+----
+
+`append_header_grep_pattern()` adds your new "gmail" pattern to `rev_info`, but
+it won't work unless we compile it with `compile_grep_patterns()`.
+
+NOTE: If you are using `setup_revisions()` (for example, if you are passing a
+`setup_revision_opt` instead of using `add_head_to_pending()`), you don't need
+to call `compile_grep_patterns()` because `setup_revisions()` calls it for you.
+
+NOTE: We could add the same filter via the `append_grep_pattern()` helper if we
+wanted to, but `append_header_grep_pattern()` adds the `enum grep_context` and
+`enum grep_pat_token` for us.
+
+=== Changing the Order
+
+There are a few ways that we can change the order of the commits during a
+revision walk. Firstly, we can use the `enum rev_sort_order` to choose from some
+typical orderings.
+
+`topo_order` is the same as `git log --topo-order`: we avoid showing a parent
+before all of its children have been shown, and we avoid mixing commits which
+are in different lines of history. (`git help log`'s section on `--topo-order`
+has a very nice diagram to illustrate this.)
+
+Let's see what happens when we run with `REV_SORT_BY_COMMIT_DATE` as opposed to
+`REV_SORT_BY_AUTHOR_DATE`. Add the following:
+
+----
+static void final_rev_info_setup(int argc, const char **argv,
+                const char *prefix, struct rev_info *rev)
+{
+        ...
+
+        rev->topo_order = 1;
+        rev->sort_order = REV_SORT_BY_COMMIT_DATE;
+
+        ...
+}
+----
+
+Let's output this into a file so we can easily diff it with the walk sorted by
+author date.
+
+----
+$ make
+$ ./bin-wrappers/git walken > commit-date.txt
+----
+
+Then, let's sort by author date and run it again.
+
+----
+static void final_rev_info_setup(int argc, const char **argv,
+                const char *prefix, struct rev_info *rev)
+{
+        ...
+
+        rev->topo_order = 1;
+        rev->sort_order = REV_SORT_BY_AUTHOR_DATE;
+
+        ...
+}
+----
+
+----
+$ make
+$ ./bin-wrappers/git walken > author-date.txt
+----
+
+Finally, compare the two. This is a little less helpful without object names or
+dates, but hopefully we get the idea.
+
+----
+$ diff -u commit-date.txt author-date.txt
+----
+
+This display indicates that commits can be reordered after they're written, for
+example with `git rebase`.
+
+Let's try one more reordering of commits. `rev_info` exposes a `reverse` flag.
+Set that flag somewhere inside of `final_rev_info_setup()`:
+
+----
+static void final_rev_info_setup(int argc, const char **argv, const char *prefix,
+                struct rev_info *rev)
+{
+        ...
+
+        rev->reverse = 1;
+
+        ...
+}
+----
+
+Run your walk again and note the difference in order. (If you remove the grep
+pattern, you should see the last commit this call gives you as your current
+HEAD.)
+
+== Basic Object Walk
+
+So far we've been walking only commits. But Git has more types of objects than
+that! Let's see if we can walk _all_ objects, and find out some information
+about each one.
+
+We can base our work on an example. `git pack-objects` prepares all kinds of
+objects for packing into a bitmap or packfile. The work we are interested in
+resides in `builtins/pack-objects.c:get_object_list()`; examination of that
+function shows that the all-object walk is being performed by
+`traverse_commit_list()` or `traverse_commit_list_filtered()`. Those two
+functions reside in `list-objects.c`; examining the source shows that, despite
+the name, these functions traverse all kinds of objects. Let's have a look at
+the arguments to `traverse_commit_list_filtered()`, which are a superset of the
+arguments to the unfiltered version.
+
+- `struct list_objects_filter_options *filter_options`: This is a struct which
+  stores a filter-spec as outlined in `Documentation/rev-list-options.txt`.
+- `struct rev_info *revs`: This is the `rev_info` used for the walk.
+- `show_commit_fn show_commit`: A callback which will be used to handle each
+  individual commit object.
+- `show_object_fn show_object`: A callback which will be used to handle each
+  non-commit object (so each blob, tree, or tag).
+- `void *show_data`: A context buffer which is passed in turn to `show_commit`
+  and `show_object`.
+- `struct oidset *omitted`: A linked-list of object IDs which the provided
+  filter caused to be omitted.
+
+It looks like this `traverse_commit_list_filtered()` uses callbacks we provide
+instead of needing us to call it repeatedly ourselves. Cool! Let's add the
+callbacks first.
+
+For the sake of this tutorial, we'll simply keep track of how many of each kind
+of object we find. At file scope in `builtin/walken.c` add the following
+tracking variables:
+
+----
+static int commit_count;
+static int tag_count;
+static int blob_count;
+static int tree_count;
+----
+
+Commits are handled by a different callback than other objects; let's do that
+one first:
+
+----
+static void walken_show_commit(struct commit *cmt, void *buf)
+{
+        commit_count++;
+}
+----
+
+The `cmt` argument is fairly self-explanatory. But it's worth mentioning that
+the `buf` argument is actually the context buffer that we can provide to the
+traversal calls - `show_data`, which we mentioned a moment ago.
+
+Since we have the `struct commit` object, we can look at all the same parts that
+we looked at in our earlier commit-only walk. For the sake of this tutorial,
+though, we'll just increment the commit counter and move on.
+
+The callback for non-commits is a little different, as we'll need to check
+which kind of object we're dealing with:
+
+----
+static void walken_show_object(struct object *obj, const char *str, void *buf)
+{
+        switch (obj->type) {
+        case OBJ_TREE:
+                tree_count++;
+                break;
+        case OBJ_BLOB:
+                blob_count++;
+                break;
+        case OBJ_TAG:
+                tag_count++;
+                break;
+        case OBJ_COMMIT:
+                BUG("unexpected commit object in walken_show_object\n");
+        default:
+                BUG("unexpected object type %s in walken_show_object\n",
+                        type_name(obj->type));
+        }
+}
+----
+
+Again, `obj` is fairly self-explanatory, and we can guess that `buf` is the same
+context pointer that `walken_show_commit()` receives: the `show_data` argument
+to `traverse_commit_list()` and `traverse_commit_list_filtered()`. Finally,
+`str` contains the name of the object, which ends up being something like
+`foo.txt` (blob), `bar/baz` (tree), or `v1.2.3` (tag).
+
+To help assure us that we aren't double-counting commits, we'll include some
+complaining if a commit object is routed through our non-commit callback; we'll
+also complain if we see an invalid object type. Since those two cases should be
+unreachable, and would only change in the event of a semantic change to the Git
+codebase, we complain by using `BUG()` - which is a signal to a developer that
+the change they made caused unintended consequences, and the rest of the
+codebase needs to be updated to understand that change. `BUG()` is not intended
+to be seen by the public, so it is not localized.
+
+Our main object walk implementation is substantially different from our commit
+walk implementation, so let's make a new function to perform the object walk. We
+can perform setup which is applicable to all objects here, too, to keep separate
+from setup which is applicable to commit-only walks.
+
+We'll start by enabling all types of objects in the `struct rev_info`.  We'll
+also turn on `tree_blobs_in_commit_order`, which means that we will walk a
+commit's tree and everything it points to immediately after we find each commit,
+as opposed to waiting for the end and walking through all trees after the commit
+history has been discovered. With the appropriate settings configured, we are
+ready to call `prepare_revision_walk()`.
+
+----
+static void walken_object_walk(struct rev_info *rev)
+{
+        rev->tree_objects = 1;
+        rev->blob_objects = 1;
+        rev->tag_objects = 1;
+        rev->tree_blobs_in_commit_order = 1;
+
+        if (prepare_revision_walk(rev))
+                die(_("revision walk setup failed"));
+
+        commit_count = 0;
+        tag_count = 0;
+        blob_count = 0;
+        tree_count = 0;
+----
+
+Let's start by calling just the unfiltered walk and reporting our counts.
+Complete your implementation of `walken_object_walk()`:
+
+----
+        traverse_commit_list(rev, walken_show_commit, walken_show_object, NULL);
+
+        printf("commits %d\nblobs %d\ntags %d\ntrees %d\n", commit_count,
+                blob_count, tag_count, tree_count);
+}
+----
+
+NOTE: This output is intended to be machine-parsed. Therefore, we are not
+sending it to `trace_printf()`, and we are not localizing it - we need scripts
+to be able to count on the formatting to be exactly the way it is shown here.
+If we were intending this output to be read by humans, we would need to localize
+it with `_()`.
+
+Finally, we'll ask `cmd_walken()` to use the object walk instead. Discussing
+command line options is out of scope for this tutorial, so we'll just hardcode
+a branch we can change at compile time. Where you call `final_rev_info_setup()`
+and `walken_commit_walk()`, instead branch like so:
+
+----
+        if (1) {
+                add_head_to_pending(&rev);
+                walken_object_walk(&rev);
+        } else {
+                final_rev_info_setup(argc, argv, prefix, &rev);
+                walken_commit_walk(&rev);
+        }
+----
+
+NOTE: For simplicity, we've avoided all the filters and sorts we applied in
+`final_rev_info_setup()` and simply added `HEAD` to our pending queue. If you
+want, you can certainly use the filters we added before by moving
+`final_rev_info_setup()` out of the conditional and removing the call to
+`add_head_to_pending()`.
+
+Now we can try to run our command! It should take noticeably longer than the
+commit walk, but an examination of the output will give you an idea why. Your
+output should look similar to this example, but with different counts:
+
+----
+Object walk completed. Found 55733 commits, 100274 blobs, 0 tags, and 104210 trees.
+----
+
+This makes sense. We have more trees than commits because the Git project has
+lots of subdirectories which can change, plus at least one tree per commit. We
+have no tags because we started on a commit (`HEAD`) and while tags can point to
+commits, commits can't point to tags.
+
+NOTE: You will have different counts when you run this yourself! The number of
+objects grows along with the Git project.
+
+=== Adding a Filter
+
+There are a handful of filters that we can apply to the object walk laid out in
+`Documentation/rev-list-options.txt`. These filters are typically useful for
+operations such as creating packfiles or performing a partial clone. They are
+defined in `list-objects-filter-options.h`. For the purposes of this tutorial we
+will use the "tree:1" filter, which causes the walk to omit all trees and blobs
+which are not directly referenced by commits reachable from the commit in
+`pending` when the walk begins. (`pending` is the list of objects which need to
+be traversed during a walk; you can imagine a breadth-first tree traversal to
+help understand. In our case, that means we omit trees and blobs not directly
+referenced by `HEAD` or `HEAD`'s history, because we begin the walk with only
+`HEAD` in the `pending` list.)
+
+First, we'll need to `#include "list-objects-filter-options.h`" and set up the
+`struct list_objects_filter_options` at the top of the function.
+
+----
+static void walken_object_walk(struct rev_info *rev)
+{
+        struct list_objects_filter_options filter_options = {};
+
+        ...
+----
+
+For now, we are not going to track the omitted objects, so we'll replace those
+parameters with `NULL`. For the sake of simplicity, we'll add a simple
+build-time branch to use our filter or not. Replace the line calling
+`traverse_commit_list()` with the following, which will remind us which kind of
+walk we've just performed:
+
+----
+        if (0) {
+                /* Unfiltered: */
+                trace_printf(_("Unfiltered object walk.\n"));
+                traverse_commit_list(rev, walken_show_commit,
+                                walken_show_object, NULL);
+        } else {
+                trace_printf(
+                        _("Filtered object walk with filterspec 'tree:1'.\n"));
+                parse_list_objects_filter(&filter_options, "tree:1");
+
+                traverse_commit_list_filtered(&filter_options, rev,
+                        walken_show_commit, walken_show_object, NULL, NULL);
+        }
+----
+
+`struct list_objects_filter_options` is usually built directly from a command
+line argument, so the module provides an easy way to build one from a string.
+Even though we aren't taking user input right now, we can still build one with
+a hardcoded string using `parse_list_objects_filter()`.
+
+With the filter spec "tree:1", we are expecting to see _only_ the root tree for
+each commit; therefore, the tree object count should be less than or equal to
+the number of commits. (For an example of why that's true: `git commit --revert`
+points to the same tree object as its grandparent.)
+
+=== Counting Omitted Objects
+
+We also have the capability to enumerate all objects which were omitted by a
+filter, like with `git log --filter=<spec> --filter-print-omitted`. Asking
+`traverse_commit_list_filtered()` to populate the `omitted` list means that our
+object walk does not perform any better than an unfiltered object walk; all
+reachable objects are walked in order to populate the list.
+
+First, add the `struct oidset` and related items we will use to iterate it:
+
+----
+static void walken_object_walk(
+        ...
+
+        struct oidset omitted;
+        struct oidset_iter oit;
+        struct object_id *oid = NULL;
+        int omitted_count = 0;
+        oidset_init(&omitted, 0);
+
+        ...
+----
+
+Modify the call to `traverse_commit_list_filtered()` to include your `omitted`
+object:
+
+----
+        ...
+
+                traverse_commit_list_filtered(&filter_options, rev,
+                        walken_show_commit, walken_show_object, NULL, &omitted);
+
+        ...
+----
+
+Then, after your traversal, the `oidset` traversal is pretty straightforward.
+Count all the objects within and modify the print statement:
+
+----
+        /* Count the omitted objects. */
+        oidset_iter_init(&omitted, &oit);
+
+        while ((oid = oidset_iter_next(&oit)))
+                omitted_count++;
+
+        printf("commits %d\nblobs %d\ntags %d\ntrees%d\nomitted %d\n",
+                commit_count, blob_count, tag_count, tree_count, omitted_count);
+----
+
+By running your walk with and without the filter, you should find that the total
+object count in each case is identical. You can also time each invocation of
+the `walken` subcommand, with and without `omitted` being passed in, to confirm
+to yourself the runtime impact of tracking all omitted objects.
+
+=== Changing the Order
+
+Finally, let's demonstrate that you can also reorder walks of all objects, not
+just walks of commits. First, we'll make our handlers chattier - modify
+`walken_show_commit()` and `walken_show_object()` to print the object as they
+go:
+
+----
+static void walken_show_commit(struct commit *cmt, void *buf)
+{
+        trace_printf("commit: %s\n", oid_to_hex(&cmt->object.oid));
+        commit_count++;
+}
+
+static void walken_show_object(struct object *obj, const char *str, void *buf)
+{
+        trace_printf("%s: %s\n", type_name(obj->type), oid_to_hex(&obj->oid));
+
+        ...
+}
+----
+
+NOTE: Since we will be examining this output directly as humans, we'll use
+`trace_printf()` here. Additionally, since this change introduces a significant
+number of printed lines, using `trace_printf()` will allow us to easily silence
+those lines without having to recompile.
+
+(Leave the counter increment logic in place.)
+
+With only that change, run again (but save yourself some scrollback):
+
+----
+$ GIT_TRACE=1 ./bin-wrappers/git walken | head -n 10
+----
+
+Take a look at the top commit with `git show` and the object ID you printed; it
+should be the same as the output of `git show HEAD`.
+
+Next, let's change a setting on our `struct rev_info` within
+`walken_object_walk()`. Find where you're changing the other settings on `rev`,
+such as `rev->tree_objects` and `rev->tree_blobs_in_commit_order`, and add the
+`reverse` setting at the bottom:
+
+----
+        ...
+
+        rev->tree_objects = 1;
+        rev->blob_objects = 1;
+        rev->tag_objects = 1;
+        rev->tree_blobs_in_commit_order = 1;
+        rev->reverse = 1;
+
+        ...
+----
+
+Now, run again, but this time, let's grab the last handful of objects instead
+of the first handful:
+
+----
+$ make
+$ GIT_TRACE=1 ./bin-wrappers git walken | tail -n 10
+----
+
+The last commit object given should have the same OID as the one we saw at the
+top before, and running `git show <oid>` with that OID should give you again
+the same results as `git show HEAD`. Furthermore, if you run and examine the
+first ten lines again (with `head` instead of `tail` like we did before applying
+the `reverse` setting), you should see that now the first commit printed is the
+initial commit, `e83c5163`.
+
+== Wrapping Up
+
+Let's review. In this tutorial, we:
+
+- Built a commit walk from the ground up
+- Enabled a grep filter for that commit walk
+- Changed the sort order of that filtered commit walk
+- Built an object walk (tags, commits, trees, and blobs) from the ground up
+- Learned how to add a filter-spec to an object walk
+- Changed the display order of the filtered object walk
diff --git a/Documentation/RelNotes/1.5.0.txt b/Documentation/RelNotes/1.5.0.txt
index daf4bdb0d7..d6d42f3183 100644
--- a/Documentation/RelNotes/1.5.0.txt
+++ b/Documentation/RelNotes/1.5.0.txt
@@ -251,7 +251,7 @@ Updates in v1.5.0 since v1.4.4 series
    the repository when that happens.
 
 
-* Crufts removal
+* Cruft removal
 
  - We used to say "old commits are retrievable using reflog and
    'master@{yesterday}' syntax as long as you haven't run
@@ -379,7 +379,7 @@ Updates in v1.5.0 since v1.4.4 series
  - The value of i18n.commitencoding in the originating
    repository is recorded in the commit object on the "encoding"
    header, if it is not UTF-8.  git-log and friends notice this,
-   and reencodes the message to the log output encoding when
+   and re-encodes the message to the log output encoding when
    displaying, if they are different.  The log output encoding
    is determined by "git log --encoding=<encoding>",
    i18n.logoutputencoding configuration, or i18n.commitencoding
diff --git a/Documentation/RelNotes/1.6.5.4.txt b/Documentation/RelNotes/1.6.5.4.txt
index d3a2a3e712..344333de66 100644
--- a/Documentation/RelNotes/1.6.5.4.txt
+++ b/Documentation/RelNotes/1.6.5.4.txt
@@ -10,7 +10,7 @@ Fixes since v1.6.5.3
 
  * "git prune-packed" gave progress output even when its standard error is
    not connected to a terminal; this caused cron jobs that run it to
-   produce crufts.
+   produce cruft.
 
  * "git pack-objects --all-progress" is an option to ask progress output
    from write-object phase _if_ progress output were to be produced, and
diff --git a/Documentation/RelNotes/1.7.0.2.txt b/Documentation/RelNotes/1.7.0.2.txt
index fcb46ca6a4..73ed2b5278 100644
--- a/Documentation/RelNotes/1.7.0.2.txt
+++ b/Documentation/RelNotes/1.7.0.2.txt
@@ -34,7 +34,7 @@ Fixes since v1.7.0.1
  * "git status" in 1.7.0 lacked the optimization we used to have in 1.6.X series
    to speed up scanning of large working tree.
 
- * "gitweb" did not diagnose parsing errors properly while reading tis configuration
+ * "gitweb" did not diagnose parsing errors properly while reading its configuration
    file.
 
 And other minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.10.4.txt b/Documentation/RelNotes/1.7.10.4.txt
index 326670df6e..57597f2bf3 100644
--- a/Documentation/RelNotes/1.7.10.4.txt
+++ b/Documentation/RelNotes/1.7.10.4.txt
@@ -7,7 +7,7 @@ Fixes since v1.7.10.3
  * The message file for Swedish translation has been updated a bit.
 
  * A name taken from mailmap was copied into an internal buffer
-   incorrectly and could overun the buffer if it is too long.
+   incorrectly and could overrun the buffer if it is too long.
 
  * A malformed commit object that has a header line chomped in the
    middle could kill git with a NULL pointer dereference.
diff --git a/Documentation/RelNotes/1.7.12.3.txt b/Documentation/RelNotes/1.7.12.3.txt
index ecda427a35..4b822976b8 100644
--- a/Documentation/RelNotes/1.7.12.3.txt
+++ b/Documentation/RelNotes/1.7.12.3.txt
@@ -25,7 +25,7 @@ Fixes since v1.7.12.2
    its Accept-Encoding header.
 
  * "git receive-pack" (the counterpart to "git push") did not give
-   progress output while processing objects it received to the puser
+   progress output while processing objects it received to the user
    when run over the smart-http protocol.
 
  * "git status" honored the ignore=dirty settings in .gitmodules but
diff --git a/Documentation/RelNotes/1.7.5.3.txt b/Documentation/RelNotes/1.7.5.3.txt
index 9c03353af2..1d24edcf2f 100644
--- a/Documentation/RelNotes/1.7.5.3.txt
+++ b/Documentation/RelNotes/1.7.5.3.txt
@@ -22,7 +22,7 @@ Fixes since v1.7.5.2
  * "git log --stdin path" with an input that has additional pathspec
    used to corrupt memory.
 
- * "git send-pack" (hence "git push") over smalt-HTTP protocol could
+ * "git send-pack" (hence "git push") over smart-HTTP protocol could
    deadlock when the client side pack-object died early.
 
  * Compressed tarball gitweb generates used to be made with the timestamp
diff --git a/Documentation/RelNotes/1.8.0.txt b/Documentation/RelNotes/1.8.0.txt
index 43883c14f0..63d6e4afa4 100644
--- a/Documentation/RelNotes/1.8.0.txt
+++ b/Documentation/RelNotes/1.8.0.txt
@@ -233,7 +233,7 @@ to them for details).
    together, misdetected branches.
 
  * "git receive-pack" (the counterpart to "git push") did not give
-   progress output while processing objects it received to the puser
+   progress output while processing objects it received to the user
    when run over the smart-http protocol.
 
  * When you misspell the command name you give to the "exec" action in
diff --git a/Documentation/RelNotes/1.8.4.1.txt b/Documentation/RelNotes/1.8.4.1.txt
index 96090ef599..c257beb114 100644
--- a/Documentation/RelNotes/1.8.4.1.txt
+++ b/Documentation/RelNotes/1.8.4.1.txt
@@ -15,7 +15,7 @@ Fixes since v1.8.4
    in 1.8.4-rc1).
 
  * "git rebase -i" and other scripted commands were feeding a
-   random, data dependant error message to 'echo' and expecting it
+   random, data dependent error message to 'echo' and expecting it
    to come out literally.
 
  * Setting the "submodule.<name>.path" variable to the empty
diff --git a/Documentation/RelNotes/2.1.3.txt b/Documentation/RelNotes/2.1.3.txt
index acc9ebb886..0dfb17c4fc 100644
--- a/Documentation/RelNotes/2.1.3.txt
+++ b/Documentation/RelNotes/2.1.3.txt
@@ -13,7 +13,7 @@ Git v2.1.3 Release Notes
    they are new enough to support the `--output` option.
 
  * "git pack-objects" forgot to disable the codepath to generate
-   object recheability bitmap when it needs to split the resulting
+   object reachability bitmap when it needs to split the resulting
    pack.
 
  * "gitweb" used deprecated CGI::startfrom, which was removed from
diff --git a/Documentation/RelNotes/2.10.0.txt b/Documentation/RelNotes/2.10.0.txt
index f4da28ab66..3792b7d03d 100644
--- a/Documentation/RelNotes/2.10.0.txt
+++ b/Documentation/RelNotes/2.10.0.txt
@@ -478,7 +478,7 @@ notes for details).
  * One part of "git am" had an oddball helper function that called
    stuff from outside "his" as opposed to calling what we have "ours",
    which was not gender-neutral and also inconsistent with the rest of
-   the system where outside stuff is usuall called "theirs" in
+   the system where outside stuff is usually called "theirs" in
    contrast to "ours".
 
  * "git blame file" allowed the lineage of lines in the uncommitted,
diff --git a/Documentation/RelNotes/2.10.2.txt b/Documentation/RelNotes/2.10.2.txt
index c4d4397023..abbd331508 100644
--- a/Documentation/RelNotes/2.10.2.txt
+++ b/Documentation/RelNotes/2.10.2.txt
@@ -86,7 +86,7 @@ Fixes since v2.10.1
    by refusing to check out a branch that is already checked out in
    another worktree.  However, this also prevented checking out a
    branch, which is designated as the primary branch of a bare
-   reopsitory, in a worktree that is connected to the bare
+   repository, in a worktree that is connected to the bare
    repository.  The check has been corrected to allow it.
 
  * "git rebase" immediately after "git clone" failed to find the fork
diff --git a/Documentation/RelNotes/2.11.1.txt b/Documentation/RelNotes/2.11.1.txt
index 9cd14c8197..7d35cf186d 100644
--- a/Documentation/RelNotes/2.11.1.txt
+++ b/Documentation/RelNotes/2.11.1.txt
@@ -104,7 +104,7 @@ Fixes since v2.11
    "git difftool --dir-diff" from a subdirectory never worked. This
    has been fixed.
 
- * "git p4" that tracks multile p4 paths imported a single changelist
+ * "git p4" that tracks multiple p4 paths imported a single changelist
    that touches files in these multiple paths as one commit, followed
    by many empty commits.  This has been fixed.
 
diff --git a/Documentation/RelNotes/2.12.0.txt b/Documentation/RelNotes/2.12.0.txt
index ef8b97da9b..d2f6a83614 100644
--- a/Documentation/RelNotes/2.12.0.txt
+++ b/Documentation/RelNotes/2.12.0.txt
@@ -315,7 +315,7 @@ notes for details).
    "git difftool --dir-diff" from a subdirectory never worked. This
    has been fixed.
 
- * "git p4" that tracks multile p4 paths imported a single changelist
+ * "git p4" that tracks multiple p4 paths imported a single changelist
    that touches files in these multiple paths as one commit, followed
    by many empty commits.  This has been fixed.
 
diff --git a/Documentation/RelNotes/2.13.0.txt b/Documentation/RelNotes/2.13.0.txt
index aa99d4b3ce..2a47b4cb0c 100644
--- a/Documentation/RelNotes/2.13.0.txt
+++ b/Documentation/RelNotes/2.13.0.txt
@@ -177,7 +177,7 @@ UI, Workflows & Features
    been changed to enable "--decorate".
 
  * The output from "git status --short" has been extended to show
-   various kinds of dirtyness in submodules differently; instead of to
+   various kinds of dirtiness in submodules differently; instead of to
    "M" for modified, 'm' and '?' can be shown to signal changes only
    to the working tree of the submodule but not the commit that is
    checked out.
diff --git a/Documentation/RelNotes/2.13.3.txt b/Documentation/RelNotes/2.13.3.txt
index 5d76ad5310..384e4de265 100644
--- a/Documentation/RelNotes/2.13.3.txt
+++ b/Documentation/RelNotes/2.13.3.txt
@@ -25,7 +25,7 @@ Fixes since v2.13.2
  * The code to pick up and execute command alias definition from the
    configuration used to switch to the top of the working tree and
    then come back when the expanded alias was executed, which was
-   unnecessarilyl complex.  Attempt to simplify the logic by using the
+   unnecessarily complex.  Attempt to simplify the logic by using the
    early-config mechanism that does not chdir around.
 
  * "git add -p" were updated in 2.12 timeframe to cope with custom
@@ -35,7 +35,7 @@ Fixes since v2.13.2
  * Fix a recent regression to "git rebase -i" and add tests that would
    have caught it and others.
 
- * An unaligned 32-bit access in pack-bitmap code ahs been corrected.
+ * An unaligned 32-bit access in pack-bitmap code has been corrected.
 
  * Tighten error checks for invalid "git apply" input.
 
diff --git a/Documentation/RelNotes/2.14.0.txt b/Documentation/RelNotes/2.14.0.txt
index 4246c68ff5..2711a2529d 100644
--- a/Documentation/RelNotes/2.14.0.txt
+++ b/Documentation/RelNotes/2.14.0.txt
@@ -141,7 +141,7 @@ Performance, Internal Implementation, Development Support etc.
  * Some platforms have ulong that is smaller than time_t, and our
    historical use of ulong for timestamp would mean they cannot
    represent some timestamp that the platform allows.  Invent a
-   separate and dedicated timestamp_t (so that we can distingiuish
+   separate and dedicated timestamp_t (so that we can distinguish
    timestamps and a vanilla ulongs, which along is already a good
    move), and then declare uintmax_t is the type to be used as the
    timestamp_t.
@@ -442,7 +442,7 @@ notes for details).
  * The code to pick up and execute command alias definition from the
    configuration used to switch to the top of the working tree and
    then come back when the expanded alias was executed, which was
-   unnecessarilyl complex.  Attempt to simplify the logic by using the
+   unnecessarily complex.  Attempt to simplify the logic by using the
    early-config mechanism that does not chdir around.
 
  * Fix configuration codepath to pay proper attention to commondir
diff --git a/Documentation/RelNotes/2.16.0.txt b/Documentation/RelNotes/2.16.0.txt
index 0c81c5915f..b474781ed8 100644
--- a/Documentation/RelNotes/2.16.0.txt
+++ b/Documentation/RelNotes/2.16.0.txt
@@ -407,7 +407,7 @@ Fixes since v2.15
    (merge eef3df5a93 bw/pathspec-match-submodule-boundary later to maint).
 
  * Amending commits in git-gui broke the author name that is non-ascii
-   due to incorrect enconding conversion.
+   due to incorrect encoding conversion.
 
  * Recent update to the submodule configuration code broke "diff-tree"
    by accidentally stopping to read from the index upfront.
diff --git a/Documentation/RelNotes/2.16.3.txt b/Documentation/RelNotes/2.16.3.txt
index 64a0bcb0d2..f0121a8f2d 100644
--- a/Documentation/RelNotes/2.16.3.txt
+++ b/Documentation/RelNotes/2.16.3.txt
@@ -24,7 +24,7 @@ Fixes since v2.16.2
 
  * The http tracing code, often used to debug connection issues,
    learned to redact potentially sensitive information from its output
-   so that it can be more safely sharable.
+   so that it can be more safely shareable.
 
  * Crash fix for a corner case where an error codepath tried to unlock
    what it did not acquire lock on.
diff --git a/Documentation/RelNotes/2.17.0.txt b/Documentation/RelNotes/2.17.0.txt
index c2cf891f71..8b17c26033 100644
--- a/Documentation/RelNotes/2.17.0.txt
+++ b/Documentation/RelNotes/2.17.0.txt
@@ -216,7 +216,7 @@ Fixes since v2.16
 
  * The http tracing code, often used to debug connection issues,
    learned to redact potentially sensitive information from its output
-   so that it can be more safely sharable.
+   so that it can be more safely shareable.
    (merge 8ba18e6fa4 jt/http-redact-cookies later to maint).
 
  * Crash fix for a corner case where an error codepath tried to unlock
diff --git a/Documentation/RelNotes/2.18.0.txt b/Documentation/RelNotes/2.18.0.txt
index 3ea280cf68..6c8a0e97c1 100644
--- a/Documentation/RelNotes/2.18.0.txt
+++ b/Documentation/RelNotes/2.18.0.txt
@@ -179,7 +179,7 @@ Performance, Internal Implementation, Development Support etc.
    (merge 00a3da2a13 nd/remove-ignore-env-field later to maint).
 
  * Code to find the length to uniquely abbreviate object names based
-   on packfile content, which is a relatively recent addtion, has been
+   on packfile content, which is a relatively recent addition, has been
    optimized to use the same fan-out table.
 
  * The mechanism to use parse-options API to automate the command line
diff --git a/Documentation/RelNotes/2.19.0.txt b/Documentation/RelNotes/2.19.0.txt
index a06ccf6e2a..891c79b9cb 100644
--- a/Documentation/RelNotes/2.19.0.txt
+++ b/Documentation/RelNotes/2.19.0.txt
@@ -106,7 +106,7 @@ Performance, Internal Implementation, Development Support etc.
  * The conversion to pass "the_repository" and then "a_repository"
    throughout the object access API continues.
 
- * Continuing with the idea to programatically enumerate various
+ * Continuing with the idea to programmatically enumerate various
    pieces of data required for command line completion, teach the
    codebase to report the list of configuration variables
    subcommands care about to help complete them.
diff --git a/Documentation/RelNotes/2.20.0.txt b/Documentation/RelNotes/2.20.0.txt
index e71fe3dee1..3dd7e6e1fc 100644
--- a/Documentation/RelNotes/2.20.0.txt
+++ b/Documentation/RelNotes/2.20.0.txt
@@ -119,7 +119,7 @@ UI, Workflows & Features
    alias expansion.
 
  * The documentation of "git gc" has been updated to mention that it
-   is no longer limited to "pruning away crufts" but also updates
+   is no longer limited to "pruning away cruft" but also updates
    ancillary files like commit-graph as a part of repository
    optimization.
 
diff --git a/Documentation/RelNotes/2.24.0.txt b/Documentation/RelNotes/2.24.0.txt
index bda29d224a..bde154124c 100644
--- a/Documentation/RelNotes/2.24.0.txt
+++ b/Documentation/RelNotes/2.24.0.txt
@@ -6,10 +6,9 @@ Updates since v2.23
 
 Backward compatibility note
 
- * Although it is not officially deprecated, "filter-branch" is
-   showing its age and alternatives are available.  From this release,
-   we started to discourage its uses and hint people about
-   filter-repo.
+ * "filter-branch" is showing its age and alternatives are available.
+   From this release, we started to discourage its use and hint
+   people about filter-repo.
 
 UI, Workflows & Features
 
@@ -71,6 +70,13 @@ UI, Workflows & Features
  * "git add -i" has been taught to show the total number of hunks and
    the hunks that has been processed so far when showing prompts.
 
+ * "git fetch --jobs=<n>" allowed <n> parallel jobs when fetching
+   submodules, but this did not apply to "git fetch --multiple" that
+   fetches from multiple remote repositories.  It now does.
+
+ * The installation instruction for zsh completion script (in
+   contrib/) has been a bit improved.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -128,6 +134,18 @@ Performance, Internal Implementation, Development Support etc.
 
  * Preparation for SHA-256 upgrade continues.
 
+ * "git log --graph" for an octopus merge is sometimes colored
+   incorrectly, which is demonstrated and documented but not yet
+   fixed.
+
+ * The trace2 output, when sending them to files in a designated
+   directory, can populate the directory with too many files; a
+   mechanism is introduced to set the maximum number of files and
+   discard further logs when the maximum is reached.
+
+ * We have adopted a Code-of-conduct document.
+   (merge 3f9ef874a7 jk/coc later to maint).
+
 
 Fixes since v2.23
 -----------------
@@ -297,6 +315,34 @@ Fixes since v2.23
    to access the worktree correctly, which has been corrected.
    (merge dfd557c978 js/stash-apply-in-secondary-worktree later to maint).
 
+ * The merge-recursive machinery is one of the most complex parts of
+   the system that accumulated cruft over time.  This large series
+   cleans up the implementation quite a bit.
+   (merge b657047719 en/merge-recursive-cleanup later to maint).
+
+ * Pretty-printed command line formatter (used in e.g. reporting the
+   command being run by the tracing API) had a bug that lost an
+   argument that is an empty string, which has been corrected.
+   (merge ce2d7ed2fd gs/sq-quote-buf-pretty later to maint).
+
+ * "git range-diff" failed to handle mode-only change, which has been
+   corrected.
+   (merge 2b6a9b13ca tg/range-diff-output-update later to maint).
+
+ * Dev support update.
+   (merge 4f3c1dc5d6 dl/allow-running-cocci-verbosely later to maint).
+
+ * "git format-patch -o <outdir>" did an equivalent of "mkdir <outdir>"
+   not "mkdir -p <outdir>", which was corrected.
+
+ * "git stash save" lost local changes to submodules, which has been
+   corrected.
+   (merge 556895d0c8 jj/stash-reset-only-toplevel later to maint).
+
+ * The atomic push over smart HTTP transport did not work, which has
+   been corrected.
+   (merge 6f1194246a bc/smart-http-atomic-push later to maint).
+
  * Other code cleanup, docfix, build fix, etc.
    (merge d1387d3895 en/fast-import-merge-doc later to maint).
    (merge 1c24a54ea4 bm/repository-layout-typofix later to maint).
@@ -335,3 +381,18 @@ Fixes since v2.23
    (merge 53d687bf5f ah/cleanups later to maint).
    (merge f537485fa5 rs/test-remove-useless-debugging-cat later to maint).
    (merge 11a3d3aadd dl/rev-list-doc-cleanup later to maint).
+   (merge d928a8388a am/t0028-utf16-tests later to maint).
+   (merge b05b40930e dl/t0000-skip-test-test later to maint).
+   (merge 03d3b1297c js/xdiffi-comment-updates later to maint).
+   (merge 57d8f4b4c7 js/doc-stash-save later to maint).
+   (merge 8c1cfd58e3 ta/t1308-typofix later to maint).
+   (merge fa364ad790 bb/utf8-wcwidth-cleanup later to maint).
+   (merge 68b69211b2 bb/compat-util-comment-fix later to maint).
+   (merge 5cc6a4be11 rs/http-push-simplify later to maint).
+   (merge a81e42d235 rs/column-use-utf8-strnwidth later to maint).
+   (merge 062a309d36 rs/remote-curl-use-argv-array later to maint).
+   (merge 3b3c79f6c9 nr/diff-highlight-indent-fix later to maint).
+   (merge 3444ec2eb2 wb/fsmonitor-bitmap-fix later to maint).
+   (merge 10da030ab7 cb/pcre2-chartables-leakfix later to maint).
+   (merge 60e6569a12 js/mingw-needs-hiding-fix later to maint).
+   (merge 52bd3e4657 rl/gitweb-blame-prev-fix later to maint).
diff --git a/Documentation/RelNotes/2.25.0.txt b/Documentation/RelNotes/2.25.0.txt
new file mode 100644
index 0000000000..b61b69f20b
--- /dev/null
+++ b/Documentation/RelNotes/2.25.0.txt
@@ -0,0 +1,68 @@
+Git 2.25 Release Notes
+======================
+
+Updates since v2.24
+-------------------
+
+Backward compatibility notes
+
+
+UI, Workflows & Features
+
+ * A tutorial on object enumeration has been added.
+
+ * The branch description ("git branch --edit-description") has been
+   used to fill the body of the cover letters by the format-patch
+   command; this has been enhanced so that the subject can also be
+   filled.
+
+ * "git rebase --preserve-merges" has been marked as deprecated; this
+   release stops advertising it in the "git rebase -h" output.
+
+ * The code to generate multi-pack index learned to show (or not to
+   show) progress indicators.
+
+ * "git apply --3way" learned to honor merge.conflictStyle
+   configuration variable, like merges would.
+
+ * The custom format for "git log --format=<format>" learned the l/L
+   placeholder that is similar to e/E that fills in the e-mail
+   address, but only the local part on the left side of '@'.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * Debugging support for lazy cloning has been a bit improved.
+
+ * Move the definition of a set of bitmask constants from 0ctal
+   literal to (1U<<count) notation.
+
+ * Test updates to prepare for SHA-2 transition continues.
+
+
+Fixes since v2.24
+-----------------
+
+ * "rebase -i" ceased to run post-commit hook by mistake in an earlier
+   update, which has been corrected.
+
+ * "git notes copy $original" ought to copy the notes attached to the
+   original object to HEAD, but a mistaken tightening to command line
+   parameter validation made earlier disabled that feature by mistake.
+
+ * When all files from some subdirectory were renamed to the root
+   directory, the directory rename heuristics would fail to detect that
+   as a rename/merge of the subdirectory to the root directory, which has
+   been corrected.
+
+ * Code clean-up and a bugfix in the logic used to tell worktree local
+   and repository global refs apart.
+   (merge f45f88b2e4 sg/dir-trie-fixes later to maint).
+
+ * "git stash save" in a working tree that is sparsely checked out
+   mistakenly removed paths that are outside the area of interest.
+   (merge 4a58c3d7f7 js/update-index-ignore-removal-for-skip-worktree later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+   (merge 80736d7c5e jc/am-show-current-patch-docfix later to maint).
+   (merge 8b656572ca sg/commit-graph-usage-fix later to maint).
diff --git a/Documentation/RelNotes/2.3.3.txt b/Documentation/RelNotes/2.3.3.txt
index 5ef12644c2..850dc68ede 100644
--- a/Documentation/RelNotes/2.3.3.txt
+++ b/Documentation/RelNotes/2.3.3.txt
@@ -12,7 +12,7 @@ Fixes since v2.3.2
  * Description given by "grep -h" for its --exclude-standard option
    was phrased poorly.
 
- * Documentaton for "git remote add" mentioned "--tags" and
+ * Documentation for "git remote add" mentioned "--tags" and
    "--no-tags" and it was not clear that fetch from the remote in
    the future will use the default behaviour when neither is given
    to override it.
diff --git a/Documentation/RelNotes/2.3.7.txt b/Documentation/RelNotes/2.3.7.txt
index fc95812cb3..5769184081 100644
--- a/Documentation/RelNotes/2.3.7.txt
+++ b/Documentation/RelNotes/2.3.7.txt
@@ -4,7 +4,7 @@ Git v2.3.7 Release Notes
 Fixes since v2.3.6
 ------------------
 
- * An earlier update to the parser that disects a URL broke an
+ * An earlier update to the parser that dissects a URL broke an
    address, followed by a colon, followed by an empty string (instead
    of the port number), e.g. ssh://example.com:/path/to/repo.
 
diff --git a/Documentation/RelNotes/2.4.3.txt b/Documentation/RelNotes/2.4.3.txt
index 914d2c1860..422e930aa2 100644
--- a/Documentation/RelNotes/2.4.3.txt
+++ b/Documentation/RelNotes/2.4.3.txt
@@ -66,7 +66,7 @@ Fixes since v2.4.3
  * Some time ago, "git blame" (incorrectly) lost the convert_to_git()
    call when synthesizing a fake "tip" commit that represents the
    state in the working tree, which broke folks who record the history
-   with LF line ending to make their project portabile across
+   with LF line ending to make their project portable across
    platforms while terminating lines in their working tree files with
    CRLF for their platform.
 
diff --git a/Documentation/RelNotes/2.7.0.txt b/Documentation/RelNotes/2.7.0.txt
index 563dadc57e..e3cbf3a73c 100644
--- a/Documentation/RelNotes/2.7.0.txt
+++ b/Documentation/RelNotes/2.7.0.txt
@@ -40,7 +40,7 @@ UI, Workflows & Features
 
  * "git interpret-trailers" can now run outside of a Git repository.
 
- * "git p4" learned to reencode the pathname it uses to communicate
+ * "git p4" learned to re-encode the pathname it uses to communicate
    with the p4 depot with a new option.
 
  * Give progress meter to "git filter-branch".
diff --git a/Documentation/RelNotes/2.8.0.txt b/Documentation/RelNotes/2.8.0.txt
index 5fbe1b86ee..27320b6a9f 100644
--- a/Documentation/RelNotes/2.8.0.txt
+++ b/Documentation/RelNotes/2.8.0.txt
@@ -189,7 +189,7 @@ Performance, Internal Implementation, Development Support etc.
  * Some calls to strcpy(3) triggers a false warning from static
    analyzers that are less intelligent than humans, and reducing the
    number of these false hits helps us notice real issues.  A few
-   calls to strcpy(3) in a couple of protrams that are already safe
+   calls to strcpy(3) in a couple of programs that are already safe
    has been rewritten to avoid false warnings.
 
  * The "name_path" API was an attempt to reduce the need to construct
diff --git a/Documentation/RelNotes/2.9.3.txt b/Documentation/RelNotes/2.9.3.txt
index 695b86f612..305e08062b 100644
--- a/Documentation/RelNotes/2.9.3.txt
+++ b/Documentation/RelNotes/2.9.3.txt
@@ -36,7 +36,7 @@ Fixes since v2.9.2
  * One part of "git am" had an oddball helper function that called
    stuff from outside "his" as opposed to calling what we have "ours",
    which was not gender-neutral and also inconsistent with the rest of
-   the system where outside stuff is usuall called "theirs" in
+   the system where outside stuff is usually called "theirs" in
    contrast to "ours".
 
  * The test framework learned a new helper test_match_signal to
diff --git a/Documentation/config.txt b/Documentation/config.txt
index f50f1b4128..83e7bba872 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -142,7 +142,7 @@ refer to linkgit:gitignore[5] for details. For convenience:
 
 `gitdir/i`::
         This is the same as `gitdir` except that matching is done
-        case-insensitively (e.g. on case-insensitive file sytems)
+        case-insensitively (e.g. on case-insensitive file systems)
 
 `onbranch`::
         The data that follows the keyword `onbranch:` is taken to be a
diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt
index 852d2ba37a..bdbbee58b9 100644
--- a/Documentation/config/core.txt
+++ b/Documentation/config/core.txt
@@ -593,8 +593,14 @@ core.multiPackIndex::
         multi-pack-index design document].
 
 core.sparseCheckout::
-        Enable "sparse checkout" feature. See section "Sparse checkout" in
-        linkgit:git-read-tree[1] for more information.
+        Enable "sparse checkout" feature. See linkgit:git-sparse-checkout[1]
+        for more information.
+
+core.sparseCheckoutCone::
+        Enables the "cone mode" of the sparse checkout feature. When the
+        sparse-checkout file contains a limited set of patterns, then this
+        mode provides significant performance advantages. See
+        linkgit:git-sparse-checkout[1] for more information.
 
 core.abbrev::
         Set the length object names are abbreviated to.  If
diff --git a/Documentation/config/fetch.txt b/Documentation/config/fetch.txt
index e8cb20547c..f11940280f 100644
--- a/Documentation/config/fetch.txt
+++ b/Documentation/config/fetch.txt
@@ -70,6 +70,16 @@ fetch.showForcedUpdates::
         linkgit:git-fetch[1] and linkgit:git-pull[1] commands.
         Defaults to true.
 
+fetch.parallel::
+        Specifies the maximal number of fetch operations to be run in parallel
+        at a time (submodules, or remotes when the `--multiple` option of
+        linkgit:git-fetch[1] is in effect).
++
+A value of 0 will give some reasonable default. If unset, it defaults to 1.
++
+For submodules, this setting can be overridden using the `submodule.fetchJobs`
+config setting.
+
 fetch.writeCommitGraph::
         Set to true to write a commit-graph after every `git fetch` command
         that downloads a pack-file from a remote. Using the `--split` option,
diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt
index cb629fa769..513fcd88d5 100644
--- a/Documentation/config/format.txt
+++ b/Documentation/config/format.txt
@@ -36,6 +36,12 @@ format.subjectPrefix::
         The default for format-patch is to output files with the '[PATCH]'
         subject prefix. Use this variable to change that prefix.
 
+format.coverFromDescription::
+        The default mode for format-patch to determine which parts of
+        the cover letter will be populated using the branch's
+        description. See the `--cover-from-description` option in
+        linkgit:git-format-patch[1].
+
 format.signature::
         The default for format-patch is to output a signature containing
         the Git version number. Use this variable to change that default.
@@ -81,7 +87,7 @@ format.coverLetter::
 
 format.outputDirectory::
         Set a custom directory to store the resulting files instead of the
-        current working directory.
+        current working directory. All directory components will be created.
 
 format.useAutoBase::
         A boolean value which lets you enable the `--base=auto` option of
diff --git a/Documentation/config/pack.txt b/Documentation/config/pack.txt
index 1d66f0c992..58323a351f 100644
--- a/Documentation/config/pack.txt
+++ b/Documentation/config/pack.txt
@@ -27,6 +27,10 @@ Note that changing the compression level will not automatically recompress
 all existing objects. You can force recompression by passing the -F option
 to linkgit:git-repack[1].
 
+pack.allowPackReuse::
+        When true, which is the default, Git will try to reuse parts
+        of existing packfiles when preparing new packfiles.
+
 pack.island::
         An extended regular expression configuring a set of delta
         islands. See "DELTA ISLANDS" in linkgit:git-pack-objects[1]
diff --git a/Documentation/config/tag.txt b/Documentation/config/tag.txt
index ef5adb3f42..6d9110d84c 100644
--- a/Documentation/config/tag.txt
+++ b/Documentation/config/tag.txt
@@ -13,7 +13,7 @@ tag.gpgSign::
         Use of this option when running in an automated script can
         result in a large number of tags being signed. It is therefore
         convenient to use an agent to avoid typing your gpg passphrase
-        several times. Note that this option doesn't affects tag signing
+        several times. Note that this option doesn't affect tag signing
         behavior enabled by "-u <keyid>" or "--local-user=<keyid>" options.
 
 tar.umask::
diff --git a/Documentation/config/trace2.txt b/Documentation/config/trace2.txt
index 2edbfb02fe..4ce0b9a6d1 100644
--- a/Documentation/config/trace2.txt
+++ b/Documentation/config/trace2.txt
@@ -54,3 +54,9 @@ trace2.destinationDebug::
         By default, these errors are suppressed and tracing is
         silently disabled.  May be overridden by the
         `GIT_TRACE2_DST_DEBUG` environment variable.
+
+trace2.maxFiles::
+        Integer.  When writing trace files to a target directory, do not
+        write additional traces if we would exceed this many files. Instead,
+        write a sentinel file that will block further tracing to this
+        directory. Defaults to 0, which disables this check.
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 99df1f3d4e..a2f78624a2 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -92,6 +92,10 @@ ifndef::git-pull[]
         Run `git gc --auto` at the end to perform garbage collection
         if needed. This is enabled by default.
 
+--[no-]write-commit-graph::
+        Write a commit-graph after fetching. This overrides the config
+        setting `fetch.writeCommitGraph`.
+
 -p::
 --prune::
         Before fetching, remove any remote-tracking references that no
@@ -160,10 +164,15 @@ ifndef::git-pull[]
 
 -j::
 --jobs=<n>::
-        Number of parallel children to be used for fetching submodules.
-        Each will fetch from different submodules, such that fetching many
-        submodules will be faster. By default submodules will be fetched
-        one at a time.
+        Number of parallel children to be used for all forms of fetching.
++
+If the `--multiple` option was specified, the different remotes will be fetched
+in parallel. If multiple submodules are fetched, they will be fetched in
+parallel. To control them independently, use the config settings
+`fetch.parallel` and `submodule.fetchJobs` (see linkgit:git-config[1]).
++
+Typically, parallel recursive and multi-remote fetches will be faster. By
+default fetches are performed sequentially, not in parallel.
 
 --no-recurse-submodules::
         Disable recursive fetching of submodules (this has the same effect as
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index fc3b993c33..fc5750b3b8 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -177,7 +177,7 @@ default.   You can use `--no-utf8` to override this.
         untouched.
 
 --show-current-patch::
-        Show the patch being applied when "git am" is stopped because
+        Show the entire e-mail message "git am" has stopped at, because
         of conflicts.
 
 DISCUSSION
diff --git a/Documentation/git-bisect-lk2009.txt b/Documentation/git-bisect-lk2009.txt
index e99925184d..2957bc5e0a 100644
--- a/Documentation/git-bisect-lk2009.txt
+++ b/Documentation/git-bisect-lk2009.txt
@@ -158,7 +158,7 @@ Test suites are very nice. But when they are used alone, they are
 supposed to be used so that all the tests are checked after each
 commit. This means that they are not very efficient, because many
 tests are run for no interesting result, and they suffer from
-combinational explosion.
+combinatorial explosion.
 
 In fact the problem is that big software often has many different
 configuration options and that each test case should pass for each
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index 4b45d837a7..7586c5a843 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -413,7 +413,7 @@ $ cat ~/test.sh
 
 # tweak the working tree by merging the hot-fix branch
 # and then attempt a build
-if        git merge --no-commit hot-fix &&
+if        git merge --no-commit --no-ff hot-fix &&
         make
 then
         # run project specific test and report its status
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index 7d6c9dcd17..ccada80a4a 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -9,8 +9,8 @@ git-bundle - Move objects and refs by archive
 SYNOPSIS
 --------
 [verse]
-'git bundle' create <file> <git-rev-list-args>
-'git bundle' verify <file>
+'git bundle' create [-q | --quiet | --progress | --all-progress] [--all-progress-implied] <file> <git-rev-list-args>
+'git bundle' verify [-q | --quiet] <file>
 'git bundle' list-heads <file> [<refname>...]
 'git bundle' unbundle <file> [<refname>...]
 
@@ -33,9 +33,11 @@ destination repository.
 OPTIONS
 -------
 
-create <file>::
+create [options] <file> <git-rev-list-args>::
         Used to create a bundle named 'file'.  This requires the
         'git-rev-list-args' arguments to define the bundle contents.
+        'options' contains the options specific to the 'git bundle create'
+        subcommand.
 
 verify <file>::
         Used to check that a bundle file is valid and will apply
@@ -75,6 +77,33 @@ unbundle <file>::
         necessarily everything in the pack (in this case, 'git bundle' acts
         like 'git fetch-pack').
 
+--progress::
+        Progress status is reported on the standard error stream
+        by default when it is attached to a terminal, unless -q
+        is specified. This flag forces progress status even if
+        the standard error stream is not directed to a terminal.
+
+--all-progress::
+        When --stdout is specified then progress report is
+        displayed during the object count and compression phases
+        but inhibited during the write-out phase. The reason is
+        that in some cases the output stream is directly linked
+        to another command which may wish to display progress
+        status of its own as it processes incoming pack data.
+        This flag is like --progress except that it forces progress
+        report for the write-out phase as well even if --stdout is
+        used.
+
+--all-progress-implied::
+        This is used to imply --all-progress whenever progress display
+        is activated.  Unlike --all-progress this flag doesn't actually
+        force any progress display by itself.
+
+-q::
+--quiet::
+        This flag makes the command not to report its progress
+        on the standard error stream.
+
 SPECIFYING REFERENCES
 ---------------------
 
diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt
index 3c0578217b..84f41a8e82 100644
--- a/Documentation/git-check-attr.txt
+++ b/Documentation/git-check-attr.txt
@@ -32,7 +32,7 @@ OPTIONS
         instead of from the command-line.
 
 -z::
-        The output format is modified to be machine-parseable.
+        The output format is modified to be machine-parsable.
         If `--stdin` is also given, input paths are separated
         with a NUL character instead of a linefeed character.
 
diff --git a/Documentation/git-check-ignore.txt b/Documentation/git-check-ignore.txt
index 8b42cb3fb2..8b2d49c79e 100644
--- a/Documentation/git-check-ignore.txt
+++ b/Documentation/git-check-ignore.txt
@@ -39,7 +39,7 @@ OPTIONS
         instead of from the command-line.
 
 -z::
-        The output format is modified to be machine-parseable (see
+        The output format is modified to be machine-parsable (see
         below).  If `--stdin` is also given, input paths are separated
         with a NUL character instead of a linefeed character.
 
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 34011c2940..0fe91d2f04 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -15,7 +15,7 @@ SYNOPSIS
           [--dissociate] [--separate-git-dir <git dir>]
           [--depth <depth>] [--[no-]single-branch] [--no-tags]
           [--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules]
-          [--[no-]remote-submodules] [--jobs <n>] [--] <repository>
+          [--[no-]remote-submodules] [--jobs <n>] [--sparse] [--] <repository>
           [<directory>]
 
 DESCRIPTION
@@ -156,6 +156,12 @@ objects from the source repository into a pack in the cloned repository.
         used, neither remote-tracking branches nor the related
         configuration variables are created.
 
+--sparse::
+        Initialize the sparse-checkout file so the working
+        directory starts with only the files in the root
+        of the repository. The sparse-checkout file can be
+        modified to grow the working directory as needed.
+
 --mirror::
         Set up a mirror of the source repository.  This implies `--bare`.
         Compared to `--bare`, `--mirror` not only maps local branches of the
diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.txt
index 8c708a7a16..bcd85c1976 100644
--- a/Documentation/git-commit-graph.txt
+++ b/Documentation/git-commit-graph.txt
@@ -9,7 +9,6 @@ git-commit-graph - Write and verify Git commit-graph files
 SYNOPSIS
 --------
 [verse]
-'git commit-graph read' [--object-dir <dir>]
 'git commit-graph verify' [--object-dir <dir>] [--shallow] [--[no-]progress]
 'git commit-graph write' <options> [--object-dir <dir>] [--[no-]progress]
 
@@ -74,11 +73,6 @@ Finally, if `--expire-time=<datetime>` is not specified, let `datetime`
 be the current time. After writing the split commit-graph, delete all
 unused commit-graph whose modified times are older than `datetime`.
 
-'read'::
-
-Read the commit-graph file and output basic details about it.
-Used for debugging purposes.
-
 'verify'::
 
 Read the commit-graph file and verify its contents against the object
@@ -118,12 +112,6 @@ $ git show-ref -s | git commit-graph write --stdin-commits
 $ git rev-parse HEAD | git commit-graph write --stdin-commits --append
 ------------------------------------------------
 
-* Read basic information from the commit-graph file.
-+
-------------------------------------------------
-$ git commit-graph read
-------------------------------------------------
-
 
 GIT
 ---
diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 79e22b1f3a..1b1c71ad9d 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -294,7 +294,7 @@ In `dbDriver` and `dbUser` you can use the following variables:
         Git directory name
 %g::
         Git directory name, where all characters except for
-        alpha-numeric ones, `.`, and `-` are replaced with
+        alphanumeric ones, `.`, and `-` are replaced with
         `_` (this should make it easier to use the directory
         name in a filename if wanted)
 %m::
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index 72179d993c..37781cf175 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -36,7 +36,7 @@ two blob objects, or changes between two files on disk.
         running the command in a working tree controlled by Git and
         at least one of the paths points outside the working tree,
         or when running the command outside a working tree
-        controlled by Git.
+        controlled by Git. This form implies `--exit-code`.
 
 'git diff' [<options>] --cached [<commit>] [--] [<path>...]::
 
diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt
index 784e934009..e8950de3ba 100644
--- a/Documentation/git-fast-export.txt
+++ b/Documentation/git-fast-export.txt
@@ -75,11 +75,20 @@ produced incorrect results if you gave these options.
         Before processing any input, load the marks specified in
         <file>.  The input file must exist, must be readable, and
         must use the same format as produced by --export-marks.
+
+--mark-tags::
+        In addition to labelling blobs and commits with mark ids, also
+        label tags.  This is useful in conjunction with
+        `--export-marks` and `--import-marks`, and is also useful (and
+        necessary) for exporting of nested tags.  It does not hurt
+        other cases and would be the default, but many fast-import
+        frontends are not prepared to accept tags with mark
+        identifiers.
 +
-Any commits that have already been marked will not be exported again.
-If the backend uses a similar --import-marks file, this allows for
-incremental bidirectional exporting of the repository by keeping the
-marks the same across runs.
+Any commits (or tags) that have already been marked will not be
+exported again.  If the backend uses a similar --import-marks file,
+this allows for incremental bidirectional exporting of the repository
+by keeping the marks the same across runs.
 
 --fake-missing-tagger::
         Some old repositories have tags without a tagger.  The
@@ -133,7 +142,7 @@ marks the same across runs.
         Specify how to handle `encoding` header in commit objects.  When
         asking to 'abort' (which is the default), this program will die
         when encountering such a commit object.  With 'yes', the commit
-        message will be reencoded into UTF-8.  With 'no', the original
+        message will be re-encoded into UTF-8.  With 'no', the original
         encoding will be preserved.
 
 --refspec::
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 0bb276269e..a3f1e0c5e4 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -337,6 +337,13 @@ and control the current import process.  More detailed discussion
         `commit` command.  This command is optional and is not
         needed to perform an import.
 
+`alias`::
+        Record that a mark refers to a given object without first
+        creating any new object.  Using --import-marks and referring
+        to missing marks will cause fast-import to fail, so aliases
+        can provide a way to set otherwise pruned commits to a valid
+        value (e.g. the nearest non-pruned ancestor).
+
 `checkpoint`::
         Forces fast-import to close the current packfile, generate its
         unique SHA-1 checksum and index, and start a new packfile.
@@ -774,6 +781,7 @@ lightweight (non-annotated) tags see the `reset` command below.
 
 ....
         'tag' SP <name> LF
+        mark?
         'from' SP <commit-ish> LF
         original-oid?
         'tagger' (SP <name>)? SP LT <email> GT SP <when> LF
@@ -913,6 +921,21 @@ a data chunk which does not have an LF as its last byte.
 +
 The `LF` after `<delim> LF` is optional (it used to be required).
 
+`alias`
+~~~~~~~
+Record that a mark refers to a given object without first creating any
+new object.
+
+....
+        'alias' LF
+        mark
+        'to' SP <commit-ish> LF
+        LF?
+....
+
+For a detailed description of `<commit-ish>` see above under `from`.
+
+
 `checkpoint`
 ~~~~~~~~~~~~
 Forces fast-import to close the current packfile, start a new one, and to
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 5876598852..3686a67d3e 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -534,7 +534,7 @@ repo-filter' also provides
 https://github.com/newren/git-filter-repo/blob/master/contrib/filter-repo-demos/filter-lamely[filter-lamely],
 a drop-in git-filter-branch replacement (with a few caveats).  While
 filter-lamely suffers from all the same safety issues as
-git-filter-branch, it at least ameloriates the performance issues a
+git-filter-branch, it at least ameliorates the performance issues a
 little.
 
 [[SAFETY]]
@@ -649,7 +649,7 @@ create hoards of confusing empty commits
 commits from before the filtering operation are also pruned instead of
 just pruning commits that became empty due to filtering rules.
 
-* If --prune empty is specified, sometimes empty commits are missed
+* If --prune-empty is specified, sometimes empty commits are missed
 and left around anyway (a somewhat rare bug, but it happens...)
 
 * A minor issue, but users who have a goal to update all names and
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 0ac56f4b70..00bdf9b125 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -19,6 +19,7 @@ SYNOPSIS
                    [--start-number <n>] [--numbered-files]
                    [--in-reply-to=<message id>] [--suffix=.<sfx>]
                    [--ignore-if-in-upstream]
+                   [--cover-from-description=<mode>]
                    [--rfc] [--subject-prefix=<subject prefix>]
                    [(--reroll-count|-v) <n>]
                    [--to=<email>] [--cc=<email>]
@@ -66,7 +67,8 @@ they are created in the current working directory. The default path
 can be set with the `format.outputDirectory` configuration option.
 The `-o` option takes precedence over `format.outputDirectory`.
 To store patches in the current working directory even when
-`format.outputDirectory` points elsewhere, use `-o .`.
+`format.outputDirectory` points elsewhere, use `-o .`. All directory
+components will be created.
 
 By default, the subject of a single patch is "[PATCH] " followed by
 the concatenation of lines from the commit message up to the first blank
@@ -171,6 +173,26 @@ will want to ensure that threading is disabled for `git send-email`.
         patches being generated, and any patch that matches is
         ignored.
 
+--cover-from-description=<mode>::
+        Controls which parts of the cover letter will be automatically
+        populated using the branch's description.
++
+If `<mode>` is `message` or `default`, the cover letter subject will be
+populated with placeholder text. The body of the cover letter will be
+populated with the branch's description. This is the default mode when
+no configuration nor command line option is specified.
++
+If `<mode>` is `subject`, the first paragraph of the branch description will
+populate the cover letter subject. The remainder of the description will
+populate the body of the cover letter.
++
+If `<mode>` is `auto`, if the first paragraph of the branch description
+is greater than 100 bytes, then the mode will be `message`, otherwise
+`subject` will be used.
++
+If `<mode>` is `none`, both the cover letter subject and body will be
+populated with placeholder text.
+
 --subject-prefix=<subject prefix>::
         Instead of the standard '[PATCH]' prefix in the subject
         line, instead use '[<subject prefix>]'. This
@@ -347,6 +369,7 @@ with configuration variables.
         signOff = true
         outputDirectory = <directory>
         coverLetter = auto
+        coverFromDescription = auto
 ------------
 
 
diff --git a/Documentation/git-multi-pack-index.txt b/Documentation/git-multi-pack-index.txt
index 233b2b7862..642d9ac5b7 100644
--- a/Documentation/git-multi-pack-index.txt
+++ b/Documentation/git-multi-pack-index.txt
@@ -9,7 +9,7 @@ git-multi-pack-index - Write and verify multi-pack-indexes
 SYNOPSIS
 --------
 [verse]
-'git multi-pack-index' [--object-dir=<dir>] <subcommand>
+'git multi-pack-index' [--object-dir=<dir>] [--[no-]progress] <subcommand>
 
 DESCRIPTION
 -----------
@@ -23,6 +23,10 @@ OPTIONS
         `<dir>/packs/multi-pack-index` for the current MIDX file, and
         `<dir>/packs` for the pack-files to index.
 
+--[no-]progress::
+        Turn progress on/off explicitly. If neither is specified, progress is
+        shown if standard error is connected to a terminal.
+
 The following subcommands are available:
 
 write::
diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt
index f56a5a9197..ced2e8280e 100644
--- a/Documentation/git-notes.txt
+++ b/Documentation/git-notes.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 [verse]
 'git notes' [list [<object>]]
 'git notes' add [-f] [--allow-empty] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]
-'git notes' copy [-f] ( --stdin | <from-object> <to-object> )
+'git notes' copy [-f] ( --stdin | <from-object> [<to-object>] )
 'git notes' append [--allow-empty] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]
 'git notes' edit [--allow-empty] [<object>]
 'git notes' show [<object>]
@@ -68,8 +68,8 @@ add::
         subcommand).
 
 copy::
-        Copy the notes for the first object onto the second object.
-        Abort if the second object already has notes, or if the first
+        Copy the notes for the first object onto the second object (defaults to
+        HEAD). Abort if the second object already has notes, or if the first
         object has none (use -f to overwrite existing notes to the
         second object). This subcommand is equivalent to:
         `git notes add [-f] -C $(git notes list <from-object>) <to-object>`
diff --git a/Documentation/git-range-diff.txt b/Documentation/git-range-diff.txt
index 8a6ea2c6c5..006feb7ec1 100644
--- a/Documentation/git-range-diff.txt
+++ b/Documentation/git-range-diff.txt
@@ -242,7 +242,7 @@ corresponding.
 
 The overall time needed to compute this algorithm is the time needed to
 compute n+m commit diffs and then n*m diffs of patches, plus the time
-needed to compute the least-cost assigment between n and m diffs. Git
+needed to compute the least-cost assignment between n and m diffs. Git
 uses an implementation of the Jonker-Volgenant algorithm to solve the
 assignment problem, which has cubic runtime complexity. The matching
 found in this case will look like this:
diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt
index d271842608..da33f84f33 100644
--- a/Documentation/git-read-tree.txt
+++ b/Documentation/git-read-tree.txt
@@ -436,7 +436,7 @@ support.
 SEE ALSO
 --------
 linkgit:git-write-tree[1]; linkgit:git-ls-files[1];
-linkgit:gitignore[5]
+linkgit:gitignore[5]; linkgit:git-sparse-checkout[1];
 
 GIT
 ---
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 639a4179d1..0c4f038dd6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -443,8 +443,8 @@ the `rebase-cousins` mode is turned on, such commits are instead rebased
 onto `<upstream>` (or `<onto>`, if specified).
 +
 The `--rebase-merges` mode is similar in spirit to the deprecated
-`--preserve-merges`, but in contrast to that option works well in interactive
-rebases: commits can be reordered, inserted and dropped at will.
+`--preserve-merges` but works with interactive rebases,
+where commits can be reordered, inserted and dropped at will.
 +
 It is currently only possible to recreate the merge commits using the
 `recursive` merge strategy; Different merge strategies can be used only via
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index e72d332b83..9985477efe 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -274,6 +274,13 @@ print a message to stderr and exit with nonzero status.
         Show the path to the shared index file in split index mode, or
         empty if not in split-index mode.
 
+--show-object-format[=(storage|input|output)]::
+        Show the object format (hash algorithm) used for the repository
+        for storage inside the `.git` directory, input, or output. For
+        input, multiple algorithms may be printed, space-separated.
+        If not specified, the default is "storage".
+
+
 Other Options
 ~~~~~~~~~~~~~
 
diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt
index bc80905a8a..a72ea7f7ba 100644
--- a/Documentation/git-shortlog.txt
+++ b/Documentation/git-shortlog.txt
@@ -76,6 +76,9 @@ them.
 Paths may need to be prefixed with `--` to separate them from
 options or the revision range, when confusion arises.
 
+:git-shortlog: 1
+include::rev-list-options.txt[]
+
 MAPPING AUTHORS
 ---------------
 
diff --git a/Documentation/git-sparse-checkout.txt b/Documentation/git-sparse-checkout.txt
new file mode 100644
index 0000000000..3931e4f2ad
--- /dev/null
+++ b/Documentation/git-sparse-checkout.txt
@@ -0,0 +1,153 @@
+git-sparse-checkout(1)
+======================
+
+NAME
+----
+git-sparse-checkout - Initialize and modify the sparse-checkout
+configuration, which reduces the checkout to a set of directories
+given by a list of prefixes.
+
+
+SYNOPSIS
+--------
+[verse]
+'git sparse-checkout <subcommand> [options]'
+
+
+DESCRIPTION
+-----------
+
+Initialize and modify the sparse-checkout configuration, which reduces
+the checkout to a set of directories given by a list of prefixes.
+
+THIS COMMAND IS EXPERIMENTAL. ITS BEHAVIOR, AND THE BEHAVIOR OF OTHER
+COMMANDS IN THE PRESENCE OF SPARSE-CHECKOUTS, WILL LIKELY CHANGE IN
+THE FUTURE.
+
+
+COMMANDS
+--------
+'list'::
+        Provide a list of the contents in the sparse-checkout file.
+
+'init'::
+        Enable the `core.sparseCheckout` setting. If the
+        sparse-checkout file does not exist, then populate it with
+        patterns that match every file in the root directory and
+        no other directories, then will remove all directories tracked
+        by Git. Add patterns to the sparse-checkout file to
+        repopulate the working directory.
++
+To avoid interfering with other worktrees, it first enables the
+`extensions.worktreeConfig` setting and makes sure to set the
+`core.sparseCheckout` setting in the worktree-specific config file.
+
+'set'::
+        Write a set of patterns to the sparse-checkout file, as given as
+        a list of arguments following the 'set' subcommand. Update the
+        working directory to match the new patterns. Enable the
+        core.sparseCheckout config setting if it is not already enabled.
+
+'disable'::
+        Remove the sparse-checkout file, set `core.sparseCheckout` to
+        `false`, and restore the working directory to include all files.
+
+SPARSE CHECKOUT
+---------------
+
+"Sparse checkout" allows populating the working directory sparsely.
+It uses the skip-worktree bit (see linkgit:git-update-index[1]) to tell
+Git whether a file in the working directory is worth looking at. If
+the skip-worktree bit is set, then the file is ignored in the working
+directory. Git will not populate the contents of those files, which
+makes a sparse checkout helpful when working in a repository with many
+files, but only a few are important to the current user.
+
+The `$GIT_DIR/info/sparse-checkout` file is used to define the
+skip-worktree reference bitmap. When Git updates the working
+directory, it updates the skip-worktree bits in the index based
+on this file. The files matching the patterns in the file will
+appear in the working directory, and the rest will not.
+
+To enable the sparse-checkout feature, run `git sparse-checkout init` to
+initialize a simple sparse-checkout file and enable the `core.sparseCheckout`
+config setting. Then, run `git sparse-checkout set` to modify the patterns in
+the sparse-checkout file.
+
+To repopulate the working directory with all files, use the
+`git sparse-checkout disable` command.
+
+## FULL PATTERN SET
+
+By default, the sparse-checkout file uses the same syntax as `.gitignore`
+files.
+
+While `$GIT_DIR/info/sparse-checkout` is usually used to specify what
+files are included, you can also specify what files are _not_ included,
+using negative patterns. For example, to remove the file `unwanted`:
+
+----------------
+/*
+!unwanted
+----------------
+
+
+## CONE PATTERN SET
+
+The full pattern set allows for arbitrary pattern matches and complicated
+inclusion/exclusion rules. These can result in O(N*M) pattern matches when
+updating the index, where N is the number of patterns and M is the number
+of paths in the index. To combat this performance issue, a more restricted
+pattern set is allowed when `core.spareCheckoutCone` is enabled.
+
+The accepted patterns in the cone pattern set are:
+
+1. *Recursive:* All paths inside a directory are included.
+
+2. *Parent:* All files immediately inside a directory are included.
+
+In addition to the above two patterns, we also expect that all files in the
+root directory are included. If a recursive pattern is added, then all
+leading directories are added as parent patterns.
+
+By default, when running `git sparse-checkout init`, the root directory is
+added as a parent pattern. At this point, the sparse-checkout file contains
+the following patterns:
+
+```
+/*
+!/*/
+```
+
+This says "include everything in root, but nothing two levels below root."
+If we then add the folder `A/B/C` as a recursive pattern, the folders `A` and
+`A/B` are added as parent patterns. The resulting sparse-checkout file is
+now
+
+```
+/*
+!/*/
+/A/
+!/A/*/
+/A/B/
+!/A/B/*/
+/A/B/C/
+```
+
+Here, order matters, so the negative patterns are overridden by the positive
+patterns that appear lower in the file.
+
+If `core.sparseCheckoutCone=true`, then Git will parse the sparse-checkout file
+expecting patterns of these types. Git will warn if the patterns do not match.
+If the patterns do match the expected format, then Git will use faster hash-
+based algorithms to compute inclusion in the sparse-checkout.
+
+SEE ALSO
+--------
+
+linkgit:git-read-tree[1]
+linkgit:gitignore[5]
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 8fbe12c66c..53e1a1205d 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -87,8 +87,9 @@ The `--patch` option implies `--keep-index`.  You can use
 save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
 
         This option is deprecated in favour of 'git stash push'.  It
-        differs from "stash push" in that it cannot take pathspecs,
-        and any non-option arguments form the message.
+        differs from "stash push" in that it cannot take pathspecs.
+        Instead, all non-option arguments are concatenated to form the stash
+        message.
 
 list [<options>]::
 
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 2e5599a67f..f6d9791780 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -65,7 +65,7 @@ OPTIONS
 --sign::
         Make a GPG-signed tag, using the default e-mail address's key.
         The default behavior of tag GPG-signing is controlled by `tag.gpgSign`
-        configuration variable if it exists, or disabled oder otherwise.
+        configuration variable if it exists, or disabled otherwise.
         See linkgit:git-config[1].
 
 --no-sign::
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index 1c4d146a41..c7a6271daf 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -16,6 +16,7 @@ SYNOPSIS
              [--chmod=(+|-)x]
              [--[no-]assume-unchanged]
              [--[no-]skip-worktree]
+             [--[no-]ignore-skip-worktree-entries]
              [--[no-]fsmonitor-valid]
              [--ignore-submodules]
              [--[no-]split-index]
@@ -113,6 +114,11 @@ you will need to handle the situation manually.
         set and unset the "skip-worktree" bit for the paths. See
         section "Skip-worktree bit" below for more information.
 
+
+--[no-]ignore-skip-worktree-entries::
+        Do not remove skip-worktree (AKA "index-only") entries even when
+        the `--remove` option was specified.
+
 --[no-]fsmonitor-valid::
         When one of these flags is specified, the object name recorded
         for the paths are not updated. Instead, these options
@@ -426,7 +432,7 @@ specified by the splitIndex.sharedIndexExpire config variable (see
 linkgit:git-config[1]).
 
 To avoid deleting a shared index file that is still used, its
-modification time is updated to the current time everytime a new split
+modification time is updated to the current time every time a new split
 index based on the shared index file is either created or read from.
 
 UNTRACKED CACHE
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 9b82564d1a..1b678e22db 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -271,8 +271,8 @@ In general, the interrogate commands do not touch the files in
 the working tree.
 
 
-Synching repositories
-~~~~~~~~~~~~~~~~~~~~~
+Syncing repositories
+~~~~~~~~~~~~~~~~~~~~
 
 include::cmds-synchingrepositories.txt[]
 
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index c5a528c667..508fe713c4 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -293,10 +293,10 @@ web front ends do not visualize the contents of these files by default.
 
 In these cases you can tell Git the encoding of a file in the working
 directory with the `working-tree-encoding` attribute. If a file with this
-attribute is added to Git, then Git reencodes the content from the
+attribute is added to Git, then Git re-encodes the content from the
 specified encoding to UTF-8. Finally, Git stores the UTF-8 encoded
 content in its internal data structure (called "the index"). On checkout
-the content is reencoded back to the specified encoding.
+the content is re-encoded back to the specified encoding.
 
 Please note that using the `working-tree-encoding` attribute may have a
 number of pitfalls:
@@ -498,7 +498,7 @@ command. This is achieved by using the long-running process protocol
 When Git encounters the first file that needs to be cleaned or smudged,
 it starts the filter and performs the handshake. In the handshake, the
 welcome message sent by Git is "git-filter-client", only version 2 is
-suppported, and the supported capabilities are "clean", "smudge", and
+supported, and the supported capabilities are "clean", "smudge", and
 "delay".
 
 Afterwards Git sends a list of "key=value" pairs terminated with
@@ -812,6 +812,8 @@ patterns are available:
 
 - `dts` suitable for devicetree (DTS) files.
 
+- `elixir` suitable for source code in the Elixir language.
+
 - `fortran` suitable for source code in the Fortran language.
 
 - `fountain` suitable for Fountain documents.
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index f2a65ba0ca..953c3876f0 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -81,7 +81,7 @@ submodule.<name>.ignore::
             Committed differences and modifications to tracked files will show
             up.
 
-        none;; No modifiations to submodules are ignored, all of committed
+        none;; No modifications to submodules are ignored, all of committed
             differences, and modifications to tracked and untracked files are
             shown. This is the default option.
 
diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt
index a5c3c04371..f48a031dc3 100644
--- a/Documentation/gitremote-helpers.txt
+++ b/Documentation/gitremote-helpers.txt
@@ -509,6 +509,11 @@ set by Git if the remote helper has the 'option' capability.
         Indicate that only the objects wanted need to be fetched, not
         their dependents.
 
+'option atomic' {'true'|'false'}::
+        When pushing, request the remote server to update refs in a single atomic
+        transaction.  If successful, all refs will be updated, or none will.  If the
+        remote side does not support this capability, the push will fail.
+
 SEE ALSO
 --------
 linkgit:git-remote[1]
diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt
index d6388f10bb..1a2ef4c150 100644
--- a/Documentation/gitrepository-layout.txt
+++ b/Documentation/gitrepository-layout.txt
@@ -96,9 +96,9 @@ refs::
         directory.  The 'git prune' command knows to preserve
         objects reachable from refs found in this directory and
         its subdirectories.
-        This directory is ignored (except refs/bisect and
-        refs/worktree) if $GIT_COMMON_DIR is set and
-        "$GIT_COMMON_DIR/refs" will be used instead.
+        This directory is ignored (except refs/bisect,
+        refs/rewritten and refs/worktree) if $GIT_COMMON_DIR is
+        set and "$GIT_COMMON_DIR/refs" will be used instead.
 
 refs/heads/`name`::
         records tip-of-the-tree commit objects of branch `name`
@@ -240,8 +240,8 @@ remotes::
 logs::
         Records of changes made to refs are stored in this directory.
         See linkgit:git-update-ref[1] for more information. This
-        directory is ignored if $GIT_COMMON_DIR is set and
-        "$GIT_COMMON_DIR/logs" will be used instead.
+        directory is ignored (except logs/HEAD) if $GIT_COMMON_DIR is
+        set and "$GIT_COMMON_DIR/logs" will be used instead.
 
 logs/refs/heads/`name`::
         Records all changes made to the branch tip named `name`.
diff --git a/Documentation/gitsubmodules.txt b/Documentation/gitsubmodules.txt
index 0a890205b8..c476f891b5 100644
--- a/Documentation/gitsubmodules.txt
+++ b/Documentation/gitsubmodules.txt
@@ -3,7 +3,7 @@ gitsubmodules(7)
 
 NAME
 ----
-gitsubmodules - mounting one repository inside another
+gitsubmodules - Mounting one repository inside another
 
 SYNOPSIS
 --------
diff --git a/Documentation/howto/separating-topic-branches.txt b/Documentation/howto/separating-topic-branches.txt
index bd1027433b..81be0d6115 100644
--- a/Documentation/howto/separating-topic-branches.txt
+++ b/Documentation/howto/separating-topic-branches.txt
@@ -81,7 +81,7 @@ After I am done, I'd try a pretend-merge between "topicA" and
               o---o---o---o---o---o
 
 The last diff better not to show anything other than cleanups
-for crufts.  Then I can finally clean things up:
+for cruft.  Then I can finally clean things up:
 
         $ git branch -D topic
         $ git reset --hard HEAD^ ;# nuke pretend merge
diff --git a/Documentation/manpage-bold-literal.xsl b/Documentation/manpage-bold-literal.xsl
index 608eb5df62..94d6c1b545 100644
--- a/Documentation/manpage-bold-literal.xsl
+++ b/Documentation/manpage-bold-literal.xsl
@@ -1,12 +1,13 @@
 <!-- manpage-bold-literal.xsl:
      special formatting for manpages rendered from asciidoc+docbook -->
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:d="http://docbook.org/ns/docbook"
                 version="1.0">
 
 <!-- render literal text as bold (instead of plain or monospace);
      this makes literal text easier to distinguish in manpages
      viewed on a tty -->
-<xsl:template match="literal">
+<xsl:template match="literal|d:literal">
         <xsl:value-of select="$git.docbook.backslash"/>
         <xsl:text>fB</xsl:text>
         <xsl:apply-templates/>
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index 59b8ff1e51..40dc4f5e8c 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -34,7 +34,7 @@ set to `no` at the beginning of them.
 
 --cleanup=<mode>::
         This option determines how the merge message will be cleaned up before
-        commiting. See linkgit:git-commit[1] for more details. In addition, if
+        committing. See linkgit:git-commit[1] for more details. In addition, if
         the '<mode>' is given a value of `scissors`, scissors will be appended
         to `MERGE_MSG` before being passed on to the commit machinery in the
         case of a merge conflict.
diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt
index aa66cbe41e..2912de706b 100644
--- a/Documentation/merge-strategies.txt
+++ b/Documentation/merge-strategies.txt
@@ -32,7 +32,7 @@ The 'recursive' strategy can take the following options:
 ours;;
         This option forces conflicting hunks to be auto-resolved cleanly by
         favoring 'our' version.  Changes from the other tree that do not
-        conflict with our side are reflected to the merge result.
+        conflict with our side are reflected in the merge result.
         For a binary file, the entire contents are taken from our side.
 +
 This should not be confused with the 'ours' merge strategy, which does not
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index b87e2e83e6..31c6e8d2b8 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -163,6 +163,9 @@ The placeholders are:
 '%ae':: author email
 '%aE':: author email (respecting .mailmap, see linkgit:git-shortlog[1]
         or linkgit:git-blame[1])
+'%al':: author email local-part (the part before the '@' sign)
+'%aL':: author local-part (see '%al') respecting .mailmap, see
+        linkgit:git-shortlog[1] or linkgit:git-blame[1])
 '%ad':: author date (format respects --date= option)
 '%aD':: author date, RFC2822 style
 '%ar':: author date, relative
@@ -175,6 +178,9 @@ The placeholders are:
 '%ce':: committer email
 '%cE':: committer email (respecting .mailmap, see
         linkgit:git-shortlog[1] or linkgit:git-blame[1])
+'%cl':: author email local-part (the part before the '@' sign)
+'%cL':: author local-part (see '%cl') respecting .mailmap, see
+        linkgit:git-shortlog[1] or linkgit:git-blame[1])
 '%cd':: committer date (format respects --date= option)
 '%cD':: committer date, RFC2822 style
 '%cr':: committer date, relative
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 90ff9e2bea..e37df921b5 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -579,6 +579,7 @@ above) if (1) they are referenced by tags, or (2) they change the
 contents of the paths given on the command line.  All other
 commits are marked as TREESAME (subject to be simplified away).
 
+ifndef::git-shortlog[]
 ifdef::git-rev-list[]
 Bisection Helpers
 ~~~~~~~~~~~~~~~~~
@@ -634,8 +635,9 @@ This option can be used along with `--bisect-vars`, in this case,
 after all the sorted commit objects, there will be the same text as if
 `--bisect-vars` had been used alone.
 endif::git-rev-list[]
+endif::git-shortlog[]
 
-
+ifndef::git-shortlog[]
 Commit Ordering
 ~~~~~~~~~~~~~~~
 
@@ -677,7 +679,9 @@ together.
         Output the commits chosen to be shown (see Commit Limiting
         section above) in reverse order. Cannot be combined with
         `--walk-reflogs`.
+endif::git-shortlog[]
 
+ifndef::git-shortlog[]
 Object Traversal
 ~~~~~~~~~~~~~~~~
 
@@ -817,7 +821,9 @@ endif::git-rev-list[]
 
 --do-walk::
         Overrides a previous `--no-walk`.
+endif::git-shortlog[]
 
+ifndef::git-shortlog[]
 Commit Formatting
 ~~~~~~~~~~~~~~~~~
 
@@ -973,7 +979,9 @@ ifdef::git-rev-list[]
         counts and print the count for equivalent commits separated
         by a tab.
 endif::git-rev-list[]
+endif::git-shortlog[]
 
+ifndef::git-shortlog[]
 ifndef::git-rev-list[]
 Diff Formatting
 ~~~~~~~~~~~~~~~
@@ -1016,3 +1024,4 @@ options may be given. See linkgit:git-diff-files[1] for more options.
 -t::
         Show the tree objects in the diff output. This implies `-r`.
 endif::git-rev-list[]
+endif::git-shortlog[]
diff --git a/Documentation/technical/api-config.txt b/Documentation/technical/api-config.txt
deleted file mode 100644
index 7d20716c32..0000000000
--- a/Documentation/technical/api-config.txt
+++ /dev/null
@@ -1,319 +0,0 @@
-config API
-==========
-
-The config API gives callers a way to access Git configuration files
-(and files which have the same syntax). See linkgit:git-config[1] for a
-discussion of the config file syntax.
-
-General Usage
--------------
-
-Config files are parsed linearly, and each variable found is passed to a
-caller-provided callback function. The callback function is responsible
-for any actions to be taken on the config option, and is free to ignore
-some options. It is not uncommon for the configuration to be parsed
-several times during the run of a Git program, with different callbacks
-picking out different variables useful to themselves.
-
-A config callback function takes three parameters:
-
-- the name of the parsed variable. This is in canonical "flat" form: the
-  section, subsection, and variable segments will be separated by dots,
-  and the section and variable segments will be all lowercase. E.g.,
-  `core.ignorecase`, `diff.SomeType.textconv`.
-
-- the value of the found variable, as a string. If the variable had no
-  value specified, the value will be NULL (typically this means it
-  should be interpreted as boolean true).
-
-- a void pointer passed in by the caller of the config API; this can
-  contain callback-specific data
-
-A config callback should return 0 for success, or -1 if the variable
-could not be parsed properly.
-
-Basic Config Querying
----------------------
-
-Most programs will simply want to look up variables in all config files
-that Git knows about, using the normal precedence rules. To do this,
-call `git_config` with a callback function and void data pointer.
-
-`git_config` will read all config sources in order of increasing
-priority. Thus a callback should typically overwrite previously-seen
-entries with new ones (e.g., if both the user-wide `~/.gitconfig` and
-repo-specific `.git/config` contain `color.ui`, the config machinery
-will first feed the user-wide one to the callback, and then the
-repo-specific one; by overwriting, the higher-priority repo-specific
-value is left at the end).
-
-The `config_with_options` function lets the caller examine config
-while adjusting some of the default behavior of `git_config`. It should
-almost never be used by "regular" Git code that is looking up
-configuration variables. It is intended for advanced callers like
-`git-config`, which are intentionally tweaking the normal config-lookup
-process. It takes two extra parameters:
-
-`config_source`::
-If this parameter is non-NULL, it specifies the source to parse for
-configuration, rather than looking in the usual files. See `struct
-git_config_source` in `config.h` for details. Regular `git_config` defaults
-to `NULL`.
-
-`opts`::
-Specify options to adjust the behavior of parsing config files. See `struct
-config_options` in `config.h` for details. As an example: regular `git_config`
-sets `opts.respect_includes` to `1` by default.
-
-Reading Specific Files
-----------------------
-
-To read a specific file in git-config format, use
-`git_config_from_file`. This takes the same callback and data parameters
-as `git_config`.
-
-Querying For Specific Variables
--------------------------------
-
-For programs wanting to query for specific variables in a non-callback
-manner, the config API provides two functions `git_config_get_value`
-and `git_config_get_value_multi`. They both read values from an internal
-cache generated previously from reading the config files.
-
-`int git_config_get_value(const char *key, const char **value)`::
-
-        Finds the highest-priority value for the configuration variable `key`,
-        stores the pointer to it in `value` and returns 0. When the
-        configuration variable `key` is not found, returns 1 without touching
-        `value`. The caller should not free or modify `value`, as it is owned
-        by the cache.
-
-`const struct string_list *git_config_get_value_multi(const char *key)`::
-
-        Finds and returns the value list, sorted in order of increasing priority
-        for the configuration variable `key`. When the configuration variable
-        `key` is not found, returns NULL. The caller should not free or modify
-        the returned pointer, as it is owned by the cache.
-
-`void git_config_clear(void)`::
-
-        Resets and invalidates the config cache.
-
-The config API also provides type specific API functions which do conversion
-as well as retrieval for the queried variable, including:
-
-`int git_config_get_int(const char *key, int *dest)`::
-
-        Finds and parses the value to an integer for the configuration variable
-        `key`. Dies on error; otherwise, stores the value of the parsed integer in
-        `dest` and returns 0. When the configuration variable `key` is not found,
-        returns 1 without touching `dest`.
-
-`int git_config_get_ulong(const char *key, unsigned long *dest)`::
-
-        Similar to `git_config_get_int` but for unsigned longs.
-
-`int git_config_get_bool(const char *key, int *dest)`::
-
-        Finds and parses the value into a boolean value, for the configuration
-        variable `key` respecting keywords like "true" and "false". Integer
-        values are converted into true/false values (when they are non-zero or
-        zero, respectively). Other values cause a die(). If parsing is successful,
-        stores the value of the parsed result in `dest` and returns 0. When the
-        configuration variable `key` is not found, returns 1 without touching
-        `dest`.
-
-`int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)`::
-
-        Similar to `git_config_get_bool`, except that integers are copied as-is,
-        and `is_bool` flag is unset.
-
-`int git_config_get_maybe_bool(const char *key, int *dest)`::
-
-        Similar to `git_config_get_bool`, except that it returns -1 on error
-        rather than dying.
-
-`int git_config_get_string_const(const char *key, const char **dest)`::
-
-        Allocates and copies the retrieved string into the `dest` parameter for
-        the configuration variable `key`; if NULL string is given, prints an
-        error message and returns -1. When the configuration variable `key` is
-        not found, returns 1 without touching `dest`.
-
-`int git_config_get_string(const char *key, char **dest)`::
-
-        Similar to `git_config_get_string_const`, except that retrieved value
-        copied into the `dest` parameter is a mutable string.
-
-`int git_config_get_pathname(const char *key, const char **dest)`::
-
-        Similar to `git_config_get_string`, but expands `~` or `~user` into
-        the user's home directory when found at the beginning of the path.
-
-`git_die_config(const char *key, const char *err, ...)`::
-
-        First prints the error message specified by the caller in `err` and then
-        dies printing the line number and the file name of the highest priority
-        value for the configuration variable `key`.
-
-`void git_die_config_linenr(const char *key, const char *filename, int linenr)`::
-
-        Helper function which formats the die error message according to the
-        parameters entered. Used by `git_die_config()`. It can be used by callers
-        handling `git_config_get_value_multi()` to print the correct error message
-        for the desired value.
-
-See test-config.c for usage examples.
-
-Value Parsing Helpers
----------------------
-
-To aid in parsing string values, the config API provides callbacks with
-a number of helper functions, including:
-
-`git_config_int`::
-Parse the string to an integer, including unit factors. Dies on error;
-otherwise, returns the parsed result.
-
-`git_config_ulong`::
-Identical to `git_config_int`, but for unsigned longs.
-
-`git_config_bool`::
-Parse a string into a boolean value, respecting keywords like "true" and
-"false". Integer values are converted into true/false values (when they
-are non-zero or zero, respectively). Other values cause a die(). If
-parsing is successful, the return value is the result.
-
-`git_config_bool_or_int`::
-Same as `git_config_bool`, except that integers are returned as-is, and
-an `is_bool` flag is unset.
-
-`git_parse_maybe_bool`::
-Same as `git_config_bool`, except that it returns -1 on error rather
-than dying.
-
-`git_config_string`::
-Allocates and copies the value string into the `dest` parameter; if no
-string is given, prints an error message and returns -1.
-
-`git_config_pathname`::
-Similar to `git_config_string`, but expands `~` or `~user` into the
-user's home directory when found at the beginning of the path.
-
-Include Directives
-------------------
-
-By default, the config parser does not respect include directives.
-However, a caller can use the special `git_config_include` wrapper
-callback to support them. To do so, you simply wrap your "real" callback
-function and data pointer in a `struct config_include_data`, and pass
-the wrapper to the regular config-reading functions. For example:
-
--------------------------------------------
-int read_file_with_include(const char *file, config_fn_t fn, void *data)
-{
-        struct config_include_data inc = CONFIG_INCLUDE_INIT;
-        inc.fn = fn;
-        inc.data = data;
-        return git_config_from_file(git_config_include, file, &inc);
-}
--------------------------------------------
-
-`git_config` respects includes automatically. The lower-level
-`git_config_from_file` does not.
-
-Custom Configsets
------------------
-
-A `config_set` can be used to construct an in-memory cache for
-config-like files that the caller specifies (i.e., files like `.gitmodules`,
-`~/.gitconfig` etc.). For example,
-
-----------------------------------------
-struct config_set gm_config;
-git_configset_init(&gm_config);
-int b;
-/* we add config files to the config_set */
-git_configset_add_file(&gm_config, ".gitmodules");
-git_configset_add_file(&gm_config, ".gitmodules_alt");
-
-if (!git_configset_get_bool(gm_config, "submodule.frotz.ignore", &b)) {
-        /* hack hack hack */
-}
-
-/* when we are done with the configset */
-git_configset_clear(&gm_config);
-----------------------------------------
-
-Configset API provides functions for the above mentioned work flow, including:
-
-`void git_configset_init(struct config_set *cs)`::
-
-        Initializes the config_set `cs`.
-
-`int git_configset_add_file(struct config_set *cs, const char *filename)`::
-
-        Parses the file and adds the variable-value pairs to the `config_set`,
-        dies if there is an error in parsing the file. Returns 0 on success, or
-        -1 if the file does not exist or is inaccessible. The user has to decide
-        if he wants to free the incomplete configset or continue using it when
-        the function returns -1.
-
-`int git_configset_get_value(struct config_set *cs, const char *key, const char **value)`::
-
-        Finds the highest-priority value for the configuration variable `key`
-        and config set `cs`, stores the pointer to it in `value` and returns 0.
-        When the configuration variable `key` is not found, returns 1 without
-        touching `value`. The caller should not free or modify `value`, as it
-        is owned by the cache.
-
-`const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key)`::
-
-        Finds and returns the value list, sorted in order of increasing priority
-        for the configuration variable `key` and config set `cs`. When the
-        configuration variable `key` is not found, returns NULL. The caller
-        should not free or modify the returned pointer, as it is owned by the cache.
-
-`void git_configset_clear(struct config_set *cs)`::
-
-        Clears `config_set` structure, removes all saved variable-value pairs.
-
-In addition to above functions, the `config_set` API provides type specific
-functions in the vein of `git_config_get_int` and family but with an extra
-parameter, pointer to struct `config_set`.
-They all behave similarly to the `git_config_get*()` family described in
-"Querying For Specific Variables" above.
-
-Writing Config Files
---------------------
-
-Git gives multiple entry points in the Config API to write config values to
-files namely `git_config_set_in_file` and `git_config_set`, which write to
-a specific config file or to `.git/config` respectively. They both take a
-key/value pair as parameter.
-In the end they both call `git_config_set_multivar_in_file` which takes four
-parameters:
-
-- the name of the file, as a string, to which key/value pairs will be written.
-
-- the name of key, as a string. This is in canonical "flat" form: the section,
-  subsection, and variable segments will be separated by dots, and the section
-  and variable segments will be all lowercase.
-  E.g., `core.ignorecase`, `diff.SomeType.textconv`.
-
-- the value of the variable, as a string. If value is equal to NULL, it will
-  remove the matching key from the config file.
-
-- the value regex, as a string. It will disregard key/value pairs where value
-  does not match.
-
-- a multi_replace value, as an int. If value is equal to zero, nothing or only
-  one matching key/value is replaced, else all matching key/values (regardless
-  how many) are removed, before the new pair is written.
-
-It returns 0 on success.
-
-Also, there are functions `git_config_rename_section` and
-`git_config_rename_section_in_file` with parameters `old_name` and `new_name`
-for renaming or removing sections in the config files. If NULL is passed
-through `new_name` parameter, the section will be removed from the config file.
diff --git a/Documentation/technical/api-grep.txt b/Documentation/technical/api-grep.txt
deleted file mode 100644
index a69cc8964d..0000000000
--- a/Documentation/technical/api-grep.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-grep API
-========
-
-Talk about <grep.h>, things like:
-
-* grep_buffer()
-
-(JC)
diff --git a/Documentation/technical/api-object-access.txt b/Documentation/technical/api-object-access.txt
deleted file mode 100644
index 5b29622d00..0000000000
--- a/Documentation/technical/api-object-access.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-object access API
-=================
-
-Talk about <sha1-file.c> and <object.h> family, things like
-
-* read_sha1_file()
-* read_object_with_reference()
-* has_sha1_file()
-* write_sha1_file()
-* pretend_object_file()
-* lookup_{object,commit,tag,blob,tree}
-* parse_{object,commit,tag,blob,tree}
-* Use of object flags
-
-(JC, Shawn, Daniel, Dscho, Linus)
diff --git a/Documentation/technical/api-quote.txt b/Documentation/technical/api-quote.txt
deleted file mode 100644
index e8a1bce94e..0000000000
--- a/Documentation/technical/api-quote.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-quote API
-=========
-
-Talk about <quote.h>, things like
-
-* sq_quote and unquote
-* c_style quote and unquote
-* quoting for foreign languages
-
-(JC)
diff --git a/Documentation/technical/api-submodule-config.txt b/Documentation/technical/api-submodule-config.txt
index fb06089393..c409559b86 100644
--- a/Documentation/technical/api-submodule-config.txt
+++ b/Documentation/technical/api-submodule-config.txt
@@ -58,7 +58,7 @@ Functions
 
 Whenever a submodule configuration is parsed in `parse_submodule_config_option`
 via e.g. `gitmodules_config()`, it will overwrite the null_sha1 entry.
-So in the normal case, when HEAD:.gitmodules is parsed first and then overlayed
+So in the normal case, when HEAD:.gitmodules is parsed first and then overlaid
 with the repository configuration, the null_sha1 entry contains the local
 configuration of a submodule (e.g. consolidated values from local git
 configuration and the .gitmodules file in the worktree).
diff --git a/Documentation/technical/api-trace2.txt b/Documentation/technical/api-trace2.txt
index 71eb081fed..17490b528c 100644
--- a/Documentation/technical/api-trace2.txt
+++ b/Documentation/technical/api-trace2.txt
@@ -128,7 +128,7 @@ yields
 
 ------------
 $ cat ~/log.event
-{"event":"version","sid":"sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.620713Z","file":"common-main.c","line":38,"evt":"1","exe":"2.20.1.155.g426c96fcdb"}
+{"event":"version","sid":"sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.620713Z","file":"common-main.c","line":38,"evt":"2","exe":"2.20.1.155.g426c96fcdb"}
 {"event":"start","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621027Z","file":"common-main.c","line":39,"t_abs":0.001173,"argv":["git","version"]}
 {"event":"cmd_name","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621122Z","file":"git.c","line":432,"name":"version","hierarchy":"version"}
 {"event":"exit","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621236Z","file":"git.c","line":662,"t_abs":0.001227,"code":0}
@@ -142,10 +142,9 @@ system or global config value to one of the following:
 
 include::../trace2-target-values.txt[]
 
-If the target already exists and is a directory, the traces will be
-written to files (one per process) underneath the given directory. They
-will be named according to the last component of the SID (optionally
-followed by a counter to avoid filename collisions).
+When trace files are written to a target directory, they will be named according
+to the last component of the SID (optionally followed by a counter to avoid
+filename collisions).
 
 == Trace2 API
 
@@ -179,7 +178,7 @@ describe the simplified forms.
 
 == Public API
 
-All Trace2 API functions send a messsage to all of the active
+All Trace2 API functions send a message to all of the active
 Trace2 Targets.  This section describes the set of available
 messages.
 
@@ -378,7 +377,7 @@ of `pthread_create()`.
         and the thread elapsed time.
 +
 This function must be called by the thread-proc before it returns
-(so that the coorect TLS data is used and cleaned up.  It should
+(so that the correct TLS data is used and cleaned up).  It should
 not be called by the caller of `pthread_join()`.
 
 === Region and Data Messages
@@ -407,7 +406,7 @@ The `label` field is an arbitrary label used to describe the activity
 being started, such as "read_recursive" or "do_read_index".
 +
 The `repo` field, if set, will be used to get the "repo-id", so that
-recursive oerations can be attributed to the correct repository.
+recursive operations can be attributed to the correct repository.
 
 `void trace2_region_leave(const char *category, const char *label, const struct repository *repo)`::
 
@@ -422,7 +421,7 @@ This function pops the region nesting stack on the current thread
 and reports the elapsed time of the stack frame.
 +
 The `category`, `label`, and `repo` fields are the same as above.
-The `category` and `label` do not need to match the correpsonding
+The `category` and `label` do not need to match the corresponding
 "region_enter" message, but it makes the data stream easier to
 understand.
 
@@ -605,17 +604,35 @@ only present on the "start" and "atexit" events.
 ==== Event-Specific Key/Value Pairs
 
 `"version"`::
-        This event gives the version of the executable and the EVENT format.
+        This event gives the version of the executable and the EVENT format. It
+        should always be the first event in a trace session. The EVENT format
+        version will be incremented if new event types are added, if existing
+        fields are removed, or if there are significant changes in
+        interpretation of existing events or fields. Smaller changes, such as
+        adding a new field to an existing event, will not require an increment
+        to the EVENT format version.
 +
 ------------
 {
         "event":"version",
         ...
-        "evt":"1",                       # EVENT format version
+        "evt":"2",                       # EVENT format version
         "exe":"2.20.1.155.g426c96fcdb" # git version
 }
 ------------
 
+`"discard"`::
+        This event is written to the git-trace2-discard sentinel file if there
+        are too many files in the target trace directory (see the
+        trace2.maxFiles config option).
++
+------------
+{
+        "event":"discard",
+        ...
+}
+------------
+
 `"start"`::
         This event contains the complete argv received by main().
 +
@@ -799,7 +816,7 @@ with "?".
 Note that the session-id of the child process is not available to
 the current/spawning process, so the child's PID is reported here as
 a hint for post-processing.  (But it is only a hint because the child
-proces may be a shell script which doesn't have a session-id.)
+process may be a shell script which doesn't have a session-id.)
 +
 Note that the `t_rel` field contains the observed run time in seconds
 for the child process (starting before the fork/exec/spawn and
@@ -1159,7 +1176,7 @@ d0 | main                     | atexit       |     |  0.028809 |           |
 +
 Regions may be nested.  This causes messages to be indented in the
 PERF target, for example.
-Elapsed times are relative to the start of the correpsonding nesting
+Elapsed times are relative to the start of the corresponding nesting
 level as expected.  For example, if we add region message to:
 +
 ----------------
@@ -1354,7 +1371,7 @@ d0 | main                     | atexit       |     |  0.030027 |           |
 In this example, the preload region took 0.009122 seconds.  The 7 threads
 took between 0.006069 and 0.008947 seconds to work on their portion of
 the index.  Thread "th01" worked on 508 items at offset 0.  Thread "th02"
-worked on 508 items at offset 2032.  Thread "th04" worked on 508 itemts
+worked on 508 items at offset 2032.  Thread "th04" worked on 508 items
 at offset 508.
 +
 This example also shows that thread names are assigned in a racy manner
diff --git a/Documentation/technical/api-xdiff-interface.txt b/Documentation/technical/api-xdiff-interface.txt
deleted file mode 100644
index 6296ecad1d..0000000000
--- a/Documentation/technical/api-xdiff-interface.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-xdiff interface API
-===================
-
-Talk about our calling convention to xdiff library, including
-xdiff_emit_consume_fn.
-
-(Dscho, JC)
diff --git a/Documentation/technical/commit-graph.txt b/Documentation/technical/commit-graph.txt
index 729fbcb32f..1507117dc2 100644
--- a/Documentation/technical/commit-graph.txt
+++ b/Documentation/technical/commit-graph.txt
@@ -22,11 +22,11 @@ as "commit-graph" either in the .git/objects/info directory or in the info
 directory of an alternate.
 
 The commit-graph file stores the commit graph structure along with some
-extra metadata to speed up graph walks. By listing commit OIDs in lexi-
-cographic order, we can identify an integer position for each commit and
-refer to the parents of a commit using those integer positions. We use
-binary search to find initial commits and then use the integer positions
-for fast lookups during the walk.
+extra metadata to speed up graph walks. By listing commit OIDs in
+lexicographic order, we can identify an integer position for each commit
+and refer to the parents of a commit using those integer positions. We
+use binary search to find initial commits and then use the integer
+positions for fast lookups during the walk.
 
 A consumer may load the following info for a commit from the graph:
 
@@ -85,7 +85,7 @@ have generation number represented by the macro GENERATION_NUMBER_ZERO = 0.
 Since the commit-graph file is closed under reachability, we can guarantee
 the following weaker condition on all commits:
 
-    If A and B are commits with generation numbers N amd M, respectively,
+    If A and B are commits with generation numbers N and M, respectively,
     and N < M, then A cannot reach B.
 
 Note how the strict inequality differs from the inequality when we have
diff --git a/Documentation/technical/hash-function-transition.txt b/Documentation/technical/hash-function-transition.txt
index 2ae8fa470a..8a4596bec1 100644
--- a/Documentation/technical/hash-function-transition.txt
+++ b/Documentation/technical/hash-function-transition.txt
@@ -531,7 +531,7 @@ Until Git protocol gains SHA-256 support, using SHA-256 based storage
 on public-facing Git servers is strongly discouraged. Once Git
 protocol gains SHA-256 support, SHA-256 based servers are likely not
 to support SHA-1 compatibility, to avoid what may be a very expensive
-hash reencode during clone and to encourage peers to modernize.
+hash re-encode during clone and to encourage peers to modernize.
 
 The design described here allows fetches by SHA-1 clients of a
 personal SHA-256 repository because it's not much more difficult than
@@ -602,7 +602,7 @@ git --output-format=sha1 log abac87a^{sha1}..f787cac^{sha256}
 
 Choice of Hash
 --------------
-In early 2005, around the time that Git was written,  Xiaoyun Wang,
+In early 2005, around the time that Git was written, Xiaoyun Wang,
 Yiqun Lisa Yin, and Hongbo Yu announced an attack finding SHA-1
 collisions in 2^69 operations. In August they published details.
 Luckily, no practical demonstrations of a collision in full SHA-1 were
diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt
index 7c4d67aa6a..faa25c5c52 100644
--- a/Documentation/technical/index-format.txt
+++ b/Documentation/technical/index-format.txt
@@ -318,7 +318,7 @@ The remaining data of each directory block is grouped by type:
 == End of Index Entry
 
   The End of Index Entry (EOIE) is used to locate the end of the variable
-  length index entries and the begining of the extensions. Code can take
+  length index entries and the beginning of the extensions. Code can take
   advantage of this to quickly locate the index extensions without having
   to parse through all of the index entries.
 
@@ -351,7 +351,7 @@ The remaining data of each directory block is grouped by type:
 
   - A number of index offset entries each consisting of:
 
-    - 32-bit offset from the begining of the file to the first cache entry
+    - 32-bit offset from the beginning of the file to the first cache entry
         in this block of entries.
 
     - 32-bit count of cache entries in this block
diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt
index c73e72de0e..d5ce4eea8a 100644
--- a/Documentation/technical/pack-protocol.txt
+++ b/Documentation/technical/pack-protocol.txt
@@ -644,7 +644,7 @@ update was successful, or 'ng [refname] [error]' if the update was not.
   command-ok        = PKT-LINE("ok" SP refname)
   command-fail      = PKT-LINE("ng" SP refname SP error-msg)
 
-  error-msg         = 1*(OCTECT) ; where not "ok"
+  error-msg         = 1*(OCTET) ; where not "ok"
 ----
 
 Updates can be unsuccessful for a number of reasons.  The reference can have
diff --git a/Documentation/technical/partial-clone.txt b/Documentation/technical/partial-clone.txt
index 210373e258..a6034d5610 100644
--- a/Documentation/technical/partial-clone.txt
+++ b/Documentation/technical/partial-clone.txt
@@ -32,7 +32,7 @@ if/when needed.
 
 A remote that can later provide the missing objects is called a
 promisor remote, as it promises to send the objects when
-requested. Initialy Git supported only one promisor remote, the origin
+requested. Initially Git supported only one promisor remote, the origin
 remote from which the user cloned and that was configured in the
 "extensions.partialClone" config option. Later support for more than
 one promisor remote has been implemented.
diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt
index 40f91f6b1e..7e3766cafb 100644
--- a/Documentation/technical/protocol-v2.txt
+++ b/Documentation/technical/protocol-v2.txt
@@ -252,7 +252,7 @@ A `fetch` request can take the following arguments:
     ofs-delta
         Indicate that the client understands PACKv2 with delta referring
         to its base by position in pack rather than by an oid.  That is,
-        they can read OBJ_OFS_DELTA (ake type 6) in a packfile.
+        they can read OBJ_OFS_DELTA (aka type 6) in a packfile.
 
 If the 'shallow' feature is advertised the following arguments can be
 included in the clients request as well as the potential addition of the
diff --git a/Documentation/technical/rerere.txt b/Documentation/technical/rerere.txt
index aa22d7ace8..af5f9fc24f 100644
--- a/Documentation/technical/rerere.txt
+++ b/Documentation/technical/rerere.txt
@@ -117,7 +117,7 @@ early A became C or B, a late X became Y or Z".  We can see there are
 4 combinations of ("B or C", "C or B") x ("X or Y", "Y or X").
 
 By sorting, the conflict is given its canonical name, namely, "an
-early part became B or C, a late part becames X or Y", and whenever
+early part became B or C, a late part became X or Y", and whenever
 any of these four patterns appear, and we can get to the same conflict
 and resolution that we saw earlier.
 
diff --git a/Documentation/trace2-target-values.txt b/Documentation/trace2-target-values.txt
index 27d3c64e66..3985b6d3c2 100644
--- a/Documentation/trace2-target-values.txt
+++ b/Documentation/trace2-target-values.txt
@@ -2,7 +2,9 @@
 * `0` or `false` - Disables the target.
 * `1` or `true` - Writes to `STDERR`.
 * `[2-9]` - Writes to the already opened file descriptor.
-* `<absolute-pathname>` - Writes to the file in append mode.
+* `<absolute-pathname>` - Writes to the file in append mode. If the target
+already exists and is a directory, the traces will be written to files (one
+per process) underneath the given directory.
 * `af_unix:[<socket_type>:]<absolute-pathname>` - Write to a
 Unix DomainSocket (on platforms that support them).  Socket
 type can be either `stream` or `dgram`; if omitted Git will
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 98f88a28d3..22e8d83d98 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.23.GIT
+DEF_VER=v2.24.GIT
 
 LF='
 '
diff --git a/INSTALL b/INSTALL
index c39006e8e7..22c364f34f 100644
--- a/INSTALL
+++ b/INSTALL
@@ -109,15 +109,15 @@ Issues of note:
 
  - Git is reasonably self-sufficient, but does depend on a few external
    programs and libraries.  Git can be used without most of them by adding
-   the approriate "NO_<LIBRARY>=YesPlease" to the make command line or
+   the appropriate "NO_<LIBRARY>=YesPlease" to the make command line or
    config.mak file.
 
         - "zlib", the compression library. Git won't build without it.
 
         - "ssh" is used to push and pull over the net.
 
-        - A POSIX-compliant shell is required to run many scripts needed
-          for everyday use (e.g. "bisect", "pull").
+        - A POSIX-compliant shell is required to run some scripts needed
+          for everyday use (e.g. "bisect", "request-pull").
 
         - "Perl" version 5.8 or later is needed to use some of the
           features (e.g. preparing a partial commit using "git add -i/-p",
diff --git a/Makefile b/Makefile
index 03b800da0c..2795ece4c2 100644
--- a/Makefile
+++ b/Makefile
@@ -727,6 +727,7 @@ TEST_BUILTINS_OBJS += test-prio-queue.o
 TEST_BUILTINS_OBJS += test-progress.o
 TEST_BUILTINS_OBJS += test-reach.o
 TEST_BUILTINS_OBJS += test-read-cache.o
+TEST_BUILTINS_OBJS += test-read-graph.o
 TEST_BUILTINS_OBJS += test-read-midx.o
 TEST_BUILTINS_OBJS += test-ref-store.o
 TEST_BUILTINS_OBJS += test-regex.o
@@ -1125,6 +1126,7 @@ BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-index.o
 BUILTIN_OBJS += builtin/show-ref.o
+BUILTIN_OBJS += builtin/sparse-checkout.o
 BUILTIN_OBJS += builtin/stash.o
 BUILTIN_OBJS += builtin/stripspace.o
 BUILTIN_OBJS += builtin/submodule--helper.o
@@ -1885,6 +1887,7 @@ ifndef V
         QUIET_SP       = @echo '   ' SP $<;
         QUIET_HDR      = @echo '   ' HDR $(<:hcc=h);
         QUIET_RC       = @echo '   ' RC $@;
+        QUIET_SPATCH   = @echo '   ' SPATCH $<;
         QUIET_SUBDIR0  = +@subdir=
         QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
                          $(MAKE) $(PRINT_DIR) -C $$subdir
@@ -2813,7 +2816,7 @@ FOUND_C_SOURCES = $(filter %.c,$(shell $(FIND_SOURCE_FILES)))
 COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES))
 
 %.cocci.patch: %.cocci $(COCCI_SOURCES)
-        @echo '    ' SPATCH $<; \
+        $(QUIET_SPATCH) \
         if test $(SPATCH_BATCH_SIZE) = 0; then \
                 limit=; \
         else \
@@ -3042,6 +3045,10 @@ rpm::
         @false
 .PHONY: rpm
 
+ifneq ($(INCLUDE_DLLS_IN_ARTIFACTS),)
+OTHER_PROGRAMS += $(shell echo *.dll t/helper/*.dll)
+endif
+
 artifacts-tar:: $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) \
                 GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \
                 $(MOFILES)
diff --git a/RelNotes b/RelNotes
index fc657e7d2f..091dd024b3 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.24.0.txt \ No newline at end of file
+Documentation/RelNotes/2.25.0.txt \ No newline at end of file
diff --git a/apply.c b/apply.c
index 57a61f2881..d57ac0d052 100644
--- a/apply.c
+++ b/apply.c
@@ -32,7 +32,7 @@ static void git_apply_config(void)
 {
         git_config_get_string_const("apply.whitespace", &apply_default_whitespace);
         git_config_get_string_const("apply.ignorewhitespace", &apply_default_ignorewhitespace);
-        git_config(git_default_config, NULL);
+        git_config(git_xmerge_config, NULL);
 }
 
 static int parse_whitespace_option(struct apply_state *state, const char *option)
@@ -1361,11 +1361,32 @@ int parse_git_diff_header(struct strbuf *root,
                         if (check_header_line(*linenr, patch))
                                 return -1;
                         if (res > 0)
-                                return offset;
+                                goto done;
                         break;
                 }
         }
 
+done:
+        if (!patch->old_name && !patch->new_name) {
+                if (!patch->def_name) {
+                        error(Q_("git diff header lacks filename information when removing "
+                                 "%d leading pathname component (line %d)",
+                                 "git diff header lacks filename information when removing "
+                                 "%d leading pathname components (line %d)",
+                                 parse_hdr_state.p_value),
+                              parse_hdr_state.p_value, *linenr);
+                        return -128;
+                }
+                patch->old_name = xstrdup(patch->def_name);
+                patch->new_name = xstrdup(patch->def_name);
+        }
+        if ((!patch->new_name && !patch->is_delete) ||
+            (!patch->old_name && !patch->is_new)) {
+                error(_("git diff header lacks filename information "
+                        "(line %d)"), *linenr);
+                return -128;
+        }
+        patch->is_toplevel_relative = 1;
         return offset;
 }
 
@@ -1546,26 +1567,6 @@ static int find_header(struct apply_state *state,
                                 return -128;
                         if (git_hdr_len <= len)
                                 continue;
-                        if (!patch->old_name && !patch->new_name) {
-                                if (!patch->def_name) {
-                                        error(Q_("git diff header lacks filename information when removing "
-                                                        "%d leading pathname component (line %d)",
-                                                        "git diff header lacks filename information when removing "
-                                                        "%d leading pathname components (line %d)",
-                                                        state->p_value),
-                                                     state->p_value, state->linenr);
-                                        return -128;
-                                }
-                                patch->old_name = xstrdup(patch->def_name);
-                                patch->new_name = xstrdup(patch->def_name);
-                        }
-                        if ((!patch->new_name && !patch->is_delete) ||
-                            (!patch->old_name && !patch->is_new)) {
-                                error(_("git diff header lacks filename information "
-                                             "(line %d)"), state->linenr);
-                                return -128;
-                        }
-                        patch->is_toplevel_relative = 1;
                         *hdrsize = git_hdr_len;
                         return offset;
                 }
@@ -4182,8 +4183,8 @@ static void show_rename_copy(struct patch *p)
                 old_name = slash_old + 1;
                 new_name = slash_new + 1;
         }
-        /* p->old_name thru old_name is the common prefix, and old_name and new_name
-         * through the end of names are renames
+        /* p->old_name through old_name is the common prefix, and old_name and
+         * new_name through the end of names are renames
          */
         if (old_name != p->old_name)
                 printf(" %s %.*s{%s => %s} (%d%%)\n", renamecopy,
diff --git a/attr.c b/attr.c
index d02d081e28..11f19b541c 100644
--- a/attr.c
+++ b/attr.c
@@ -62,7 +62,7 @@ static struct attr_hashmap g_attr_hashmap;
 
 /* The container for objects stored in "struct attr_hashmap" */
 struct attr_hash_entry {
-        struct hashmap_entry ent; /* must be the first member! */
+        struct hashmap_entry ent;
         const char *key; /* the key; memory should be owned by value */
         size_t keylen; /* length of the key */
         void *value; /* the stored value */
@@ -70,12 +70,14 @@ struct attr_hash_entry {
 
 /* attr_hashmap comparison function */
 static int attr_hash_entry_cmp(const void *unused_cmp_data,
-                               const void *entry,
-                               const void *entry_or_key,
+                               const struct hashmap_entry *eptr,
+                               const struct hashmap_entry *entry_or_key,
                                const void *unused_keydata)
 {
-        const struct attr_hash_entry *a = entry;
-        const struct attr_hash_entry *b = entry_or_key;
+        const struct attr_hash_entry *a, *b;
+
+        a = container_of(eptr, const struct attr_hash_entry, ent);
+        b = container_of(entry_or_key, const struct attr_hash_entry, ent);
         return (a->keylen != b->keylen) || strncmp(a->key, b->key, a->keylen);
 }
 
@@ -98,10 +100,10 @@ static void *attr_hashmap_get(struct attr_hashmap *map,
         if (!map->map.tablesize)
                 attr_hashmap_init(map);
 
-        hashmap_entry_init(&k, memhash(key, keylen));
+        hashmap_entry_init(&k.ent, memhash(key, keylen));
         k.key = key;
         k.keylen = keylen;
-        e = hashmap_get(&map->map, &k, NULL);
+        e = hashmap_get_entry(&map->map, &k, ent, NULL);
 
         return e ? e->value : NULL;
 }
@@ -117,12 +119,12 @@ static void attr_hashmap_add(struct attr_hashmap *map,
                 attr_hashmap_init(map);
 
         e = xmalloc(sizeof(struct attr_hash_entry));
-        hashmap_entry_init(e, memhash(key, keylen));
+        hashmap_entry_init(&e->ent, memhash(key, keylen));
         e->key = key;
         e->keylen = keylen;
         e->value = value;
 
-        hashmap_add(&map->map, e);
+        hashmap_add(&map->map, &e->ent);
 }
 
 struct all_attrs_item {
@@ -161,12 +163,12 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)
         if (size != check->all_attrs_nr) {
                 struct attr_hash_entry *e;
                 struct hashmap_iter iter;
-                hashmap_iter_init(&map->map, &iter);
 
                 REALLOC_ARRAY(check->all_attrs, size);
                 check->all_attrs_nr = size;
 
-                while ((e = hashmap_iter_next(&iter))) {
+                hashmap_for_each_entry(&map->map, &iter, e,
+                                        ent /* member name */) {
                         const struct git_attr *a = e->value;
                         check->all_attrs[a->attr_nr].attr = a;
                 }
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index cb9ab1ef80..af2a5ea484 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,6 +1,5 @@
-resources:
-- repo: self
-  fetchDepth: 1
+variables:
+  Agent.Source.Git.ShallowFetchDepth: 1
 
 jobs:
 - job: windows_build
@@ -131,6 +130,165 @@ jobs:
       PathtoPublish: t/failed-test-artifacts
       ArtifactName: failed-test-artifacts
 
+- job: vs_build
+  displayName: Visual Studio Build
+  condition: succeeded()
+  pool: Hosted VS2017
+  timeoutInMinutes: 240
+  steps:
+  - powershell: |
+      if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") {
+        net use s: \\gitfileshare.file.core.windows.net\test-cache "$GITFILESHAREPWD" /user:AZURE\gitfileshare /persistent:no
+        cmd /c mklink /d "$(Build.SourcesDirectory)\test-cache" S:\
+      }
+    displayName: 'Mount test-cache'
+    env:
+      GITFILESHAREPWD: $(gitfileshare.pwd)
+  - powershell: |
+      $urlbase = "https://dev.azure.com/git-for-windows/git/_apis/build/builds"
+      $id = ((Invoke-WebRequest -UseBasicParsing "${urlbase}?definitions=22&statusFilter=completed&resultFilter=succeeded&`$top=1").content | ConvertFrom-JSON).value[0].id
+      $downloadUrl = ((Invoke-WebRequest -UseBasicParsing "${urlbase}/$id/artifacts").content | ConvertFrom-JSON).value[1].resource.downloadUrl
+      (New-Object Net.WebClient).DownloadFile($downloadUrl,"git-sdk-64-minimal.zip")
+      Expand-Archive git-sdk-64-minimal.zip -DestinationPath . -Force
+      Remove-Item git-sdk-64-minimal.zip
+
+      # Let Git ignore the SDK and the test-cache
+      "/git-sdk-64-minimal/`n/test-cache/`n" | Out-File -NoNewLine -Encoding ascii -Append "$(Build.SourcesDirectory)\.git\info\exclude"
+    displayName: 'Download git-sdk-64-minimal'
+  - powershell: |
+      & git-sdk-64-minimal\usr\bin\bash.exe -lc @"
+        make NDEBUG=1 DEVELOPER=1 vcxproj
+      "@
+      if (!$?) { exit(1) }
+    displayName: Generate Visual Studio Solution
+    env:
+      HOME: $(Build.SourcesDirectory)
+      MSYSTEM: MINGW64
+      DEVELOPER: 1
+      NO_PERL: 1
+      GIT_CONFIG_PARAMETERS: "'user.name=CI' 'user.email=ci@git'"
+  - powershell: |
+      $urlbase = "https://dev.azure.com/git/git/_apis/build/builds"
+      $id = ((Invoke-WebRequest -UseBasicParsing "${urlbase}?definitions=9&statusFilter=completed&resultFilter=succeeded&`$top=1").content | ConvertFrom-JSON).value[0].id
+      $downloadUrl = ((Invoke-WebRequest -UseBasicParsing "${urlbase}/$id/artifacts").content | ConvertFrom-JSON).value[0].resource.downloadUrl
+      (New-Object Net.WebClient).DownloadFile($downloadUrl, "compat.zip")
+      Expand-Archive compat.zip -DestinationPath . -Force
+      Remove-Item compat.zip
+    displayName: 'Download vcpkg artifacts'
+  - task: MSBuild@1
+    inputs:
+      solution: git.sln
+      platform: x64
+      configuration: Release
+      maximumCpuCount: 4
+  - powershell: |
+      & compat\vcbuild\vcpkg_copy_dlls.bat release
+      if (!$?) { exit(1) }
+      & git-sdk-64-minimal\usr\bin\bash.exe -lc @"
+        mkdir -p artifacts &&
+        eval \"`$(make -n artifacts-tar INCLUDE_DLLS_IN_ARTIFACTS=YesPlease ARTIFACTS_DIRECTORY=artifacts | grep ^tar)\"
+      "@
+      if (!$?) { exit(1) }
+    displayName: Bundle artifact tar
+    env:
+      HOME: $(Build.SourcesDirectory)
+      MSYSTEM: MINGW64
+      DEVELOPER: 1
+      NO_PERL: 1
+      MSVC: 1
+      VCPKG_ROOT: $(Build.SourcesDirectory)\compat\vcbuild\vcpkg
+  - powershell: |
+      $tag = (Invoke-WebRequest -UseBasicParsing "https://gitforwindows.org/latest-tag.txt").content
+      $version = (Invoke-WebRequest -UseBasicParsing "https://gitforwindows.org/latest-version.txt").content
+      $url = "https://github.com/git-for-windows/git/releases/download/${tag}/PortableGit-${version}-64-bit.7z.exe"
+      (New-Object Net.WebClient).DownloadFile($url,"PortableGit.exe")
+      & .\PortableGit.exe -y -oartifacts\PortableGit
+      # Wait until it is unpacked
+      while (-not @(Remove-Item -ErrorAction SilentlyContinue PortableGit.exe; $?)) { sleep 1 }
+    displayName: Download & extract portable Git
+  - task: PublishPipelineArtifact@0
+    displayName: 'Publish Pipeline Artifact: MSVC test artifacts'
+    inputs:
+      artifactName: 'vs-artifacts'
+      targetPath: '$(Build.SourcesDirectory)\artifacts'
+  - powershell: |
+      if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") {
+        cmd /c rmdir "$(Build.SourcesDirectory)\test-cache"
+      }
+    displayName: 'Unmount test-cache'
+    condition: true
+    env:
+      GITFILESHAREPWD: $(gitfileshare.pwd)
+
+- job: vs_test
+  displayName: Visual Studio Test
+  dependsOn: vs_build
+  condition: succeeded()
+  pool: Hosted
+  timeoutInMinutes: 240
+  strategy:
+    parallel: 10
+  steps:
+  - powershell: |
+      if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") {
+        net use s: \\gitfileshare.file.core.windows.net\test-cache "$GITFILESHAREPWD" /user:AZURE\gitfileshare /persistent:no
+        cmd /c mklink /d "$(Build.SourcesDirectory)\test-cache" S:\
+      }
+    displayName: 'Mount test-cache'
+    env:
+      GITFILESHAREPWD: $(gitfileshare.pwd)
+  - task: DownloadPipelineArtifact@0
+    displayName: 'Download Pipeline Artifact: VS test artifacts'
+    inputs:
+      artifactName: 'vs-artifacts'
+      targetPath: '$(Build.SourcesDirectory)'
+  - powershell: |
+      & PortableGit\git-cmd.exe --command=usr\bin\bash.exe -lc @"
+        test -f artifacts.tar.gz || {
+          echo No test artifacts found\; skipping >&2
+          exit 0
+        }
+        tar xf artifacts.tar.gz || exit 1
+
+        # Let Git ignore the SDK and the test-cache
+        printf '%s\n' /PortableGit/ /test-cache/ >>.git/info/exclude
+
+        cd t &&
+        PATH=\"`$PWD/helper:`$PATH\" &&
+        test-tool.exe run-command testsuite --jobs=10 -V -x --write-junit-xml \
+                `$(test-tool.exe path-utils slice-tests \
+                        `$SYSTEM_JOBPOSITIONINPHASE `$SYSTEM_TOTALJOBSINPHASE t[0-9]*.sh)
+      "@
+      if (!$?) { exit(1) }
+    displayName: 'Test (parallel)'
+    env:
+      HOME: $(Build.SourcesDirectory)
+      MSYSTEM: MINGW64
+      NO_SVN_TESTS: 1
+      GIT_TEST_SKIP_REBASE_P: 1
+  - powershell: |
+      if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") {
+        cmd /c rmdir "$(Build.SourcesDirectory)\test-cache"
+      }
+    displayName: 'Unmount test-cache'
+    condition: true
+    env:
+      GITFILESHAREPWD: $(gitfileshare.pwd)
+  - task: PublishTestResults@2
+    displayName: 'Publish Test Results **/TEST-*.xml'
+    inputs:
+      mergeTestResults: true
+      testRunTitle: 'vs'
+      platform: Windows
+      publishRunAttachments: false
+    condition: succeededOrFailed()
+  - task: PublishBuildArtifacts@1
+    displayName: 'Publish trash directories of failed tests'
+    condition: failed()
+    inputs:
+      PathtoPublish: t/failed-test-artifacts
+      ArtifactName: failed-vs-test-artifacts
+
 - job: linux_clang
   displayName: linux-clang
   condition: succeeded()
diff --git a/blame.c b/blame.c
index 6596d8de88..29770e5c81 100644
--- a/blame.c
+++ b/blame.c
@@ -417,14 +417,15 @@ static void get_fingerprint(struct fingerprint *result,
                 /* Ignore whitespace pairs */
                 if (hash == 0)
                         continue;
-                hashmap_entry_init(entry, hash);
+                hashmap_entry_init(&entry->entry, hash);
 
-                found_entry = hashmap_get(&result->map, entry, NULL);
+                found_entry = hashmap_get_entry(&result->map, entry,
+                                                /* member name */ entry, NULL);
                 if (found_entry) {
                         found_entry->count += 1;
                 } else {
                         entry->count = 1;
-                        hashmap_add(&result->map, entry);
+                        hashmap_add(&result->map, &entry->entry);
                         ++entry;
                 }
         }
@@ -432,7 +433,7 @@ static void get_fingerprint(struct fingerprint *result,
 
 static void free_fingerprint(struct fingerprint *f)
 {
-        hashmap_free(&f->map, 0);
+        hashmap_free(&f->map);
         free(f->entries);
 }
 
@@ -449,10 +450,10 @@ static int fingerprint_similarity(struct fingerprint *a, struct fingerprint *b)
         struct hashmap_iter iter;
         const struct fingerprint_entry *entry_a, *entry_b;
 
-        hashmap_iter_init(&b->map, &iter);
-
-        while ((entry_b = hashmap_iter_next(&iter))) {
-                if ((entry_a = hashmap_get(&a->map, entry_b, NULL))) {
+        hashmap_for_each_entry(&b->map, &iter, entry_b,
+                                entry /* member name */) {
+                entry_a = hashmap_get_entry(&a->map, entry_b, entry, NULL);
+                if (entry_a) {
                         intersection += entry_a->count < entry_b->count ?
                                         entry_a->count : entry_b->count;
                 }
@@ -470,10 +471,12 @@ static void fingerprint_subtract(struct fingerprint *a, struct fingerprint *b)
 
         hashmap_iter_init(&b->map, &iter);
 
-        while ((entry_b = hashmap_iter_next(&iter))) {
-                if ((entry_a = hashmap_get(&a->map, entry_b, NULL))) {
+        hashmap_for_each_entry(&b->map, &iter, entry_b,
+                                entry /* member name */) {
+                entry_a = hashmap_get_entry(&a->map, entry_b, entry, NULL);
+                if (entry_a) {
                         if (entry_a->count <= entry_b->count)
-                                hashmap_remove(&a->map, entry_b, NULL);
+                                hashmap_remove(&a->map, &entry_b->entry, NULL);
                         else
                                 entry_a->count -= entry_b->count;
                 }
diff --git a/builtin.h b/builtin.h
index 5cf5df69f7..2b25a80cde 100644
--- a/builtin.h
+++ b/builtin.h
@@ -225,6 +225,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix);
 int cmd_show(int argc, const char **argv, const char *prefix);
 int cmd_show_branch(int argc, const char **argv, const char *prefix);
 int cmd_show_index(int argc, const char **argv, const char *prefix);
+int cmd_sparse_checkout(int argc, const char **argv, const char *prefix);
 int cmd_status(int argc, const char **argv, const char *prefix);
 int cmd_stash(int argc, const char **argv, const char *prefix);
 int cmd_stripspace(int argc, const char **argv, const char *prefix);
diff --git a/builtin/am.c b/builtin/am.c
index 761cac39e0..8181c2aef3 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1526,7 +1526,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
         o.branch1 = "HEAD";
         their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
         o.branch2 = their_tree_name;
-        o.detect_directory_renames = 0;
+        o.detect_directory_renames = MERGE_DIRECTORY_RENAMES_NONE;
 
         if (state->quiet)
                 o.verbosity = 0;
diff --git a/builtin/blame.c b/builtin/blame.c
index e946ba6cd9..bf1cecdf3f 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -319,18 +319,18 @@ static const char *format_time(timestamp_t time, const char *tz_str,
         return time_buf.buf;
 }
 
-#define OUTPUT_ANNOTATE_COMPAT        001
-#define OUTPUT_LONG_OBJECT_NAME        002
-#define OUTPUT_RAW_TIMESTAMP        004
-#define OUTPUT_PORCELAIN        010
-#define OUTPUT_SHOW_NAME        020
-#define OUTPUT_SHOW_NUMBER        040
-#define OUTPUT_SHOW_SCORE        0100
-#define OUTPUT_NO_AUTHOR        0200
-#define OUTPUT_SHOW_EMAIL        0400
-#define OUTPUT_LINE_PORCELAIN        01000
-#define OUTPUT_COLOR_LINE        02000
-#define OUTPUT_SHOW_AGE_WITH_COLOR        04000
+#define OUTPUT_ANNOTATE_COMPAT      (1U<<0)
+#define OUTPUT_LONG_OBJECT_NAME     (1U<<1)
+#define OUTPUT_RAW_TIMESTAMP        (1U<<2)
+#define OUTPUT_PORCELAIN            (1U<<3)
+#define OUTPUT_SHOW_NAME            (1U<<4)
+#define OUTPUT_SHOW_NUMBER          (1U<<5)
+#define OUTPUT_SHOW_SCORE           (1U<<6)
+#define OUTPUT_NO_AUTHOR            (1U<<7)
+#define OUTPUT_SHOW_EMAIL           (1U<<8)
+#define OUTPUT_LINE_PORCELAIN       (1U<<9)
+#define OUTPUT_COLOR_LINE           (1U<<10)
+#define OUTPUT_SHOW_AGE_WITH_COLOR  (1U<<11)
 
 static void emit_porcelain_details(struct blame_origin *suspect, int repeat)
 {
@@ -861,14 +861,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
                 OPT_STRING_LIST(0, "ignore-revs-file", &ignore_revs_file_list, N_("file"), N_("Ignore revisions from <file>")),
                 OPT_BIT(0, "color-lines", &output_option, N_("color redundant metadata from previous line differently"), OUTPUT_COLOR_LINE),
                 OPT_BIT(0, "color-by-age", &output_option, N_("color lines by age"), OUTPUT_SHOW_AGE_WITH_COLOR),
-
-                /*
-                 * The following two options are parsed by parse_revision_opt()
-                 * and are only included here to get included in the "-h"
-                 * output:
-                 */
-                { OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental heuristic to improve diffs"), PARSE_OPT_NOARG, NULL, 0, parse_opt_unknown_cb },
-
                 OPT_BIT(0, "minimal", &xdl_opts, N_("Spend extra cycles to find better match"), XDF_NEED_MINIMAL),
                 OPT_STRING('S', NULL, &revs_file, N_("file"), N_("Use revisions from <file> instead of calling git-rev-list")),
                 OPT_STRING(0, "contents", &contents_from, N_("file"), N_("Use <file>'s contents as the final image")),
diff --git a/builtin/bundle.c b/builtin/bundle.c
index 1ea4bfdfc1..f049d27a14 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -1,4 +1,6 @@
 #include "builtin.h"
+#include "argv-array.h"
+#include "parse-options.h"
 #include "cache.h"
 #include "bundle.h"
 
@@ -9,59 +11,184 @@
  * bundle supporting "fetch", "pull", and "ls-remote".
  */
 
-static const char builtin_bundle_usage[] =
-  "git bundle create <file> <git-rev-list args>\n"
-  "   or: git bundle verify <file>\n"
-  "   or: git bundle list-heads <file> [<refname>...]\n"
-  "   or: git bundle unbundle <file> [<refname>...]";
+static const char * const builtin_bundle_usage[] = {
+  N_("git bundle create [<options>] <file> <git-rev-list args>"),
+  N_("git bundle verify [<options>] <file>"),
+  N_("git bundle list-heads <file> [<refname>...]"),
+  N_("git bundle unbundle <file> [<refname>...]"),
+  NULL
+};
 
-int cmd_bundle(int argc, const char **argv, const char *prefix)
-{
+static const char * const builtin_bundle_create_usage[] = {
+  N_("git bundle create [<options>] <file> <git-rev-list args>"),
+  NULL
+};
+
+static const char * const builtin_bundle_verify_usage[] = {
+  N_("git bundle verify [<options>] <file>"),
+  NULL
+};
+
+static const char * const builtin_bundle_list_heads_usage[] = {
+  N_("git bundle list-heads <file> [<refname>...]"),
+  NULL
+};
+
+static const char * const builtin_bundle_unbundle_usage[] = {
+  N_("git bundle unbundle <file> [<refname>...]"),
+  NULL
+};
+
+static int verbose;
+
+static int parse_options_cmd_bundle(int argc,
+                const char **argv,
+                const char* prefix,
+                const char * const usagestr[],
+                const struct option options[],
+                const char **bundle_file) {
+        int newargc;
+        newargc = parse_options(argc, argv, NULL, options, usagestr,
+                             PARSE_OPT_STOP_AT_NON_OPTION);
+        if (argc < 1)
+                usage_with_options(usagestr, options);
+        *bundle_file = prefix_filename(prefix, argv[0]);
+        return newargc;
+}
+
+static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
+        int all_progress_implied = 0;
+        int progress = isatty(STDERR_FILENO);
+        struct argv_array pack_opts;
+
+        struct option options[] = {
+                OPT_SET_INT('q', "quiet", &progress,
+                            N_("do not show progress meter"), 0),
+                OPT_SET_INT(0, "progress", &progress,
+                            N_("show progress meter"), 1),
+                OPT_SET_INT(0, "all-progress", &progress,
+                            N_("show progress meter during object writing phase"), 2),
+                OPT_BOOL(0, "all-progress-implied",
+                         &all_progress_implied,
+                         N_("similar to --all-progress when progress meter is shown")),
+                OPT_END()
+        };
+        const char* bundle_file;
+
+        argc = parse_options_cmd_bundle(argc, argv, prefix,
+                        builtin_bundle_create_usage, options, &bundle_file);
+        /* bundle internals use argv[1] as further parameters */
+
+        argv_array_init(&pack_opts);
+        if (progress == 0)
+                argv_array_push(&pack_opts, "--quiet");
+        else if (progress == 1)
+                argv_array_push(&pack_opts, "--progress");
+        else if (progress == 2)
+                argv_array_push(&pack_opts, "--all-progress");
+        if (progress && all_progress_implied)
+                argv_array_push(&pack_opts, "--all-progress-implied");
+
+        if (!startup_info->have_repository)
+                die(_("Need a repository to create a bundle."));
+        return !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts);
+}
+
+static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
         struct bundle_header header;
-        const char *cmd, *bundle_file;
         int bundle_fd = -1;
+        int quiet = 0;
 
-        if (argc < 3)
-                usage(builtin_bundle_usage);
+        struct option options[] = {
+                OPT_BOOL('q', "quiet", &quiet,
+                            N_("do not show bundle details")),
+                OPT_END()
+        };
+        const char* bundle_file;
 
-        cmd = argv[1];
-        bundle_file = prefix_filename(prefix, argv[2]);
-        argc -= 2;
-        argv += 2;
+        argc = parse_options_cmd_bundle(argc, argv, prefix,
+                        builtin_bundle_verify_usage, options, &bundle_file);
+        /* bundle internals use argv[1] as further parameters */
 
         memset(&header, 0, sizeof(header));
-        if (strcmp(cmd, "create") && (bundle_fd =
-                                read_bundle_header(bundle_file, &header)) < 0)
+        if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
+                return 1;
+        close(bundle_fd);
+        if (verify_bundle(the_repository, &header, !quiet))
                 return 1;
+        fprintf(stderr, _("%s is okay\n"), bundle_file);
+        return 0;
+}
 
-        if (!strcmp(cmd, "verify")) {
-                close(bundle_fd);
-                if (argc != 1) {
-                        usage(builtin_bundle_usage);
-                        return 1;
-                }
-                if (verify_bundle(the_repository, &header, 1))
-                        return 1;
-                fprintf(stderr, _("%s is okay\n"), bundle_file);
-                return 0;
-        }
-        if (!strcmp(cmd, "list-heads")) {
-                close(bundle_fd);
-                return !!list_bundle_refs(&header, argc, argv);
+static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix) {
+        struct bundle_header header;
+        int bundle_fd = -1;
+
+        struct option options[] = {
+                OPT_END()
+        };
+        const char* bundle_file;
+
+        argc = parse_options_cmd_bundle(argc, argv, prefix,
+                        builtin_bundle_list_heads_usage, options, &bundle_file);
+        /* bundle internals use argv[1] as further parameters */
+
+        memset(&header, 0, sizeof(header));
+        if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
+                return 1;
+        close(bundle_fd);
+        return !!list_bundle_refs(&header, argc, argv);
+}
+
+static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix) {
+        struct bundle_header header;
+        int bundle_fd = -1;
+
+        struct option options[] = {
+                OPT_END()
+        };
+        const char* bundle_file;
+
+        argc = parse_options_cmd_bundle(argc, argv, prefix,
+                        builtin_bundle_unbundle_usage, options, &bundle_file);
+        /* bundle internals use argv[1] as further parameters */
+
+        memset(&header, 0, sizeof(header));
+        if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
+                return 1;
+        if (!startup_info->have_repository)
+                die(_("Need a repository to unbundle."));
+        return !!unbundle(the_repository, &header, bundle_fd, 0) ||
+                list_bundle_refs(&header, argc, argv);
+}
+
+int cmd_bundle(int argc, const char **argv, const char *prefix)
+{
+        struct option options[] = {
+                OPT__VERBOSE(&verbose, N_("be verbose; must be placed before a subcommand")),
+                OPT_END()
+        };
+        int result;
+
+        argc = parse_options(argc, argv, prefix, options, builtin_bundle_usage,
+                PARSE_OPT_STOP_AT_NON_OPTION);
+
+        packet_trace_identity("bundle");
+
+        if (argc < 2)
+                usage_with_options(builtin_bundle_usage, options);
+
+        else if (!strcmp(argv[0], "create"))
+                result = cmd_bundle_create(argc, argv, prefix);
+        else if (!strcmp(argv[0], "verify"))
+                result = cmd_bundle_verify(argc, argv, prefix);
+        else if (!strcmp(argv[0], "list-heads"))
+                result = cmd_bundle_list_heads(argc, argv, prefix);
+        else if (!strcmp(argv[0], "unbundle"))
+                result = cmd_bundle_unbundle(argc, argv, prefix);
+        else {
+                error(_("Unknown subcommand: %s"), argv[0]);
+                usage_with_options(builtin_bundle_usage, options);
         }
-        if (!strcmp(cmd, "create")) {
-                if (argc < 2) {
-                        usage(builtin_bundle_usage);
-                        return 1;
-                }
-                if (!startup_info->have_repository)
-                        die(_("Need a repository to create a bundle."));
-                return !!create_bundle(the_repository, bundle_file, argc, argv);
-        } else if (!strcmp(cmd, "unbundle")) {
-                if (!startup_info->have_repository)
-                        die(_("Need a repository to unbundle."));
-                return !!unbundle(the_repository, &header, bundle_fd, 0) ||
-                        list_bundle_refs(&header, argc, argv);
-        } else
-                usage(builtin_bundle_usage);
+        return result ? 1 : 0;
 }
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 1283727761..3634a3dac1 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -709,11 +709,11 @@ static int merge_working_tree(const struct checkout_opts *opts,
                          * give up or do a real merge, depending on
                          * whether the merge flag was used.
                          */
-                        struct tree *result;
                         struct tree *work;
                         struct tree *old_tree;
                         struct merge_options o;
                         struct strbuf sb = STRBUF_INIT;
+                        struct strbuf old_commit_shortname = STRBUF_INIT;
 
                         if (!opts->merge)
                                 return 1;
@@ -754,7 +754,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
                          */
                         init_merge_options(&o, the_repository);
                         o.verbosity = 0;
-                        work = write_tree_from_memory(&o);
+                        work = write_in_core_index_as_tree(the_repository);
 
                         ret = reset_tree(new_tree,
                                          opts, 1,
@@ -762,19 +762,25 @@ static int merge_working_tree(const struct checkout_opts *opts,
                         if (ret)
                                 return ret;
                         o.ancestor = old_branch_info->name;
+                        if (old_branch_info->name == NULL) {
+                                strbuf_add_unique_abbrev(&old_commit_shortname,
+                                                         &old_branch_info->commit->object.oid,
+                                                         DEFAULT_ABBREV);
+                                o.ancestor = old_commit_shortname.buf;
+                        }
                         o.branch1 = new_branch_info->name;
                         o.branch2 = "local";
                         ret = merge_trees(&o,
                                           new_tree,
                                           work,
-                                          old_tree,
-                                          &result);
+                                          old_tree);
                         if (ret < 0)
                                 exit(128);
                         ret = reset_tree(new_tree,
                                          opts, 0,
                                          writeout_error);
                         strbuf_release(&o.obuf);
+                        strbuf_release(&old_commit_shortname);
                         if (ret)
                                 return ret;
                 }
diff --git a/builtin/clone.c b/builtin/clone.c
index c46ee29f0a..cc9cd5d3a9 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -59,6 +59,7 @@ static const char *real_git_dir;
 static char *option_upload_pack = "git-upload-pack";
 static int option_verbosity;
 static int option_progress = -1;
+static int option_sparse_checkout;
 static enum transport_family family;
 static struct string_list option_config = STRING_LIST_INIT_NODUP;
 static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;
@@ -146,6 +147,8 @@ static struct option builtin_clone_options[] = {
         OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
         OPT_BOOL(0, "remote-submodules", &option_remote_submodules,
                     N_("any cloned submodules will use their remote-tracking branch")),
+        OPT_BOOL(0, "sparse", &option_sparse_checkout,
+                    N_("initialize sparse-checkout file to include only files at root")),
         OPT_END()
 };
 
@@ -733,6 +736,27 @@ static void update_head(const struct ref *our, const struct ref *remote,
         }
 }
 
+static int git_sparse_checkout_init(const char *repo)
+{
+        struct argv_array argv = ARGV_ARRAY_INIT;
+        int result = 0;
+        argv_array_pushl(&argv, "-C", repo, "sparse-checkout", "init", NULL);
+
+        /*
+         * We must apply the setting in the current process
+         * for the later checkout to use the sparse-checkout file.
+         */
+        core_apply_sparse_checkout = 1;
+
+        if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
+                error(_("failed to initialize sparse-checkout"));
+                result = 1;
+        }
+
+        argv_array_clear(&argv);
+        return result;
+}
+
 static int checkout(int submodule_progress)
 {
         struct object_id oid;
@@ -899,7 +923,7 @@ static void dissociate_from_references(void)
         free(alternates);
 }
 
-static int dir_exists(const char *path)
+static int path_exists(const char *path)
 {
         struct stat sb;
         return !stat(path, &sb);
@@ -927,8 +951,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
         struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
 
-        fetch_if_missing = 0;
-
         packet_trace_identity("clone");
         argc = parse_options(argc, argv, prefix, builtin_clone_options,
                              builtin_clone_usage, 0);
@@ -981,7 +1003,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                 dir = guess_dir_name(repo_name, is_bundle, option_bare);
         strip_trailing_slashes(dir);
 
-        dest_exists = dir_exists(dir);
+        dest_exists = path_exists(dir);
         if (dest_exists && !is_empty_dir(dir))
                 die(_("destination path '%s' already exists and is not "
                         "an empty directory."), dir);
@@ -992,7 +1014,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                 work_tree = NULL;
         else {
                 work_tree = getenv("GIT_WORK_TREE");
-                if (work_tree && dir_exists(work_tree))
+                if (work_tree && path_exists(work_tree))
                         die(_("working tree '%s' already exists."), work_tree);
         }
 
@@ -1020,7 +1042,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
         }
 
         if (real_git_dir) {
-                if (dir_exists(real_git_dir))
+                if (path_exists(real_git_dir))
                         junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
                 junk_git_dir = real_git_dir;
         } else {
@@ -1106,6 +1128,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
         if (option_required_reference.nr || option_optional_reference.nr)
                 setup_reference();
 
+        if (option_sparse_checkout && git_sparse_checkout_init(repo))
+                return 1;
+
         remote = remote_get(option_origin);
 
         strbuf_addf(&default_refspec, "+%s*:%s*", src_ref_prefix,
@@ -1265,7 +1290,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
         }
 
         junk_mode = JUNK_LEAVE_REPO;
-        fetch_if_missing = 1;
         err = checkout(submodule_progress);
 
         strbuf_release(&reflog_msg);
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index a6c500d8da..e0c6fc4bbf 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -8,8 +8,6 @@
 #include "object-store.h"
 
 static char const * const builtin_commit_graph_usage[] = {
-        N_("git commit-graph [--object-dir <objdir>]"),
-        N_("git commit-graph read [--object-dir <objdir>]"),
         N_("git commit-graph verify [--object-dir <objdir>] [--shallow] [--[no-]progress]"),
         N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] [--[no-]progress] <split options>"),
         NULL
@@ -20,11 +18,6 @@ static const char * const builtin_commit_graph_verify_usage[] = {
         NULL
 };
 
-static const char * const builtin_commit_graph_read_usage[] = {
-        N_("git commit-graph read [--object-dir <objdir>]"),
-        NULL
-};
-
 static const char * const builtin_commit_graph_write_usage[] = {
         N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] [--[no-]progress] <split options>"),
         NULL
@@ -60,6 +53,8 @@ static int graph_verify(int argc, const char **argv)
                 OPT_END(),
         };
 
+        trace2_cmd_mode("verify");
+
         opts.progress = isatty(2);
         argc = parse_options(argc, argv, NULL,
                              builtin_commit_graph_verify_options,
@@ -92,64 +87,6 @@ static int graph_verify(int argc, const char **argv)
         return verify_commit_graph(the_repository, graph, flags);
 }
 
-static int graph_read(int argc, const char **argv)
-{
-        struct commit_graph *graph = NULL;
-        char *graph_name;
-        int open_ok;
-        int fd;
-        struct stat st;
-
-        static struct option builtin_commit_graph_read_options[] = {
-                OPT_STRING(0, "object-dir", &opts.obj_dir,
-                        N_("dir"),
-                        N_("The object directory to store the graph")),
-                OPT_END(),
-        };
-
-        argc = parse_options(argc, argv, NULL,
-                             builtin_commit_graph_read_options,
-                             builtin_commit_graph_read_usage, 0);
-
-        if (!opts.obj_dir)
-                opts.obj_dir = get_object_directory();
-
-        graph_name = get_commit_graph_filename(opts.obj_dir);
-
-        open_ok = open_commit_graph(graph_name, &fd, &st);
-        if (!open_ok)
-                die_errno(_("Could not open commit-graph '%s'"), graph_name);
-
-        graph = load_commit_graph_one_fd_st(fd, &st);
-        if (!graph)
-                return 1;
-
-        FREE_AND_NULL(graph_name);
-
-        printf("header: %08x %d %d %d %d\n",
-                ntohl(*(uint32_t*)graph->data),
-                *(unsigned char*)(graph->data + 4),
-                *(unsigned char*)(graph->data + 5),
-                *(unsigned char*)(graph->data + 6),
-                *(unsigned char*)(graph->data + 7));
-        printf("num_commits: %u\n", graph->num_commits);
-        printf("chunks:");
-
-        if (graph->chunk_oid_fanout)
-                printf(" oid_fanout");
-        if (graph->chunk_oid_lookup)
-                printf(" oid_lookup");
-        if (graph->chunk_commit_data)
-                printf(" commit_metadata");
-        if (graph->chunk_extra_edges)
-                printf(" extra_edges");
-        printf("\n");
-
-        UNLEAK(graph);
-
-        return 0;
-}
-
 extern int read_replace_refs;
 static struct split_commit_graph_opts split_opts;
 
@@ -190,6 +127,8 @@ static int graph_write(int argc, const char **argv)
         split_opts.max_commits = 0;
         split_opts.expire_time = 0;
 
+        trace2_cmd_mode("write");
+
         argc = parse_options(argc, argv, NULL,
                              builtin_commit_graph_write_options,
                              builtin_commit_graph_write_usage, 0);
@@ -263,8 +202,6 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix)
         save_commit_buffer = 0;
 
         if (argc > 0) {
-                if (!strcmp(argv[0], "read"))
-                        return graph_read(argc, argv);
                 if (!strcmp(argv[0], "verify"))
                         return graph_verify(argc, argv);
                 if (!strcmp(argv[0], "write"))
diff --git a/builtin/commit.c b/builtin/commit.c
index e588bc6ad3..294dc574cd 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1463,28 +1463,6 @@ static int git_commit_config(const char *k, const char *v, void *cb)
         return git_status_config(k, v, s);
 }
 
-int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...)
-{
-        struct argv_array hook_env = ARGV_ARRAY_INIT;
-        va_list args;
-        int ret;
-
-        argv_array_pushf(&hook_env, "GIT_INDEX_FILE=%s", index_file);
-
-        /*
-         * Let the hook know that no editor will be launched.
-         */
-        if (!editor_is_used)
-                argv_array_push(&hook_env, "GIT_EDITOR=:");
-
-        va_start(args, name);
-        ret = run_hook_ve(hook_env.argv,name, args);
-        va_end(args);
-        argv_array_clear(&hook_env);
-
-        return ret;
-}
-
 int cmd_commit(int argc, const char **argv, const char *prefix)
 {
         const char *argv_gc_auto[] = {"gc", "--auto", NULL};
diff --git a/builtin/describe.c b/builtin/describe.c
index 90feab1120..b6df81d8d0 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -63,19 +63,22 @@ static const char *prio_names[] = {
 };
 
 static int commit_name_neq(const void *unused_cmp_data,
-                           const void *entry,
-                           const void *entry_or_key,
+                           const struct hashmap_entry *eptr,
+                           const struct hashmap_entry *entry_or_key,
                            const void *peeled)
 {
-        const struct commit_name *cn1 = entry;
-        const struct commit_name *cn2 = entry_or_key;
+        const struct commit_name *cn1, *cn2;
+
+        cn1 = container_of(eptr, const struct commit_name, entry);
+        cn2 = container_of(entry_or_key, const struct commit_name, entry);
 
         return !oideq(&cn1->peeled, peeled ? peeled : &cn2->peeled);
 }
 
 static inline struct commit_name *find_commit_name(const struct object_id *peeled)
 {
-        return hashmap_get_from_hash(&names, oidhash(peeled), peeled);
+        return hashmap_get_entry_from_hash(&names, oidhash(peeled), peeled,
+                                                struct commit_name, entry);
 }
 
 static int replace_name(struct commit_name *e,
@@ -122,8 +125,8 @@ static void add_to_known_names(const char *path,
                 if (!e) {
                         e = xmalloc(sizeof(struct commit_name));
                         oidcpy(&e->peeled, peeled);
-                        hashmap_entry_init(e, oidhash(peeled));
-                        hashmap_add(&names, e);
+                        hashmap_entry_init(&e->entry, oidhash(peeled));
+                        hashmap_add(&names, &e->entry);
                         e->path = NULL;
                 }
                 e->tag = tag;
@@ -329,8 +332,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
                 struct commit_name *n;
 
                 init_commit_names(&commit_names);
-                n = hashmap_iter_first(&names, &iter);
-                for (; n; n = hashmap_iter_next(&iter)) {
+                hashmap_for_each_entry(&names, &iter, n,
+                                        entry /* member name */) {
                         c = lookup_commit_reference_gently(the_repository,
                                                            &n->peeled, 1);
                         if (c)
diff --git a/builtin/difftool.c b/builtin/difftool.c
index 16eb8b70ea..c280e682b2 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -125,12 +125,15 @@ struct working_tree_entry {
 };
 
 static int working_tree_entry_cmp(const void *unused_cmp_data,
-                                  const void *entry,
-                                  const void *entry_or_key,
+                                  const struct hashmap_entry *eptr,
+                                  const struct hashmap_entry *entry_or_key,
                                   const void *unused_keydata)
 {
-        const struct working_tree_entry *a = entry;
-        const struct working_tree_entry *b = entry_or_key;
+        const struct working_tree_entry *a, *b;
+
+        a = container_of(eptr, const struct working_tree_entry, entry);
+        b = container_of(entry_or_key, const struct working_tree_entry, entry);
+
         return strcmp(a->path, b->path);
 }
 
@@ -145,12 +148,14 @@ struct pair_entry {
 };
 
 static int pair_cmp(const void *unused_cmp_data,
-                    const void *entry,
-                    const void *entry_or_key,
+                    const struct hashmap_entry *eptr,
+                    const struct hashmap_entry *entry_or_key,
                     const void *unused_keydata)
 {
-        const struct pair_entry *a = entry;
-        const struct pair_entry *b = entry_or_key;
+        const struct pair_entry *a, *b;
+
+        a = container_of(eptr, const struct pair_entry, entry);
+        b = container_of(entry_or_key, const struct pair_entry, entry);
 
         return strcmp(a->path, b->path);
 }
@@ -161,14 +166,14 @@ static void add_left_or_right(struct hashmap *map, const char *path,
         struct pair_entry *e, *existing;
 
         FLEX_ALLOC_STR(e, path, path);
-        hashmap_entry_init(e, strhash(path));
-        existing = hashmap_get(map, e, NULL);
+        hashmap_entry_init(&e->entry, strhash(path));
+        existing = hashmap_get_entry(map, e, entry, NULL);
         if (existing) {
                 free(e);
                 e = existing;
         } else {
                 e->left[0] = e->right[0] = '\0';
-                hashmap_add(map, e);
+                hashmap_add(map, &e->entry);
         }
         strlcpy(is_right ? e->right : e->left, content, PATH_MAX);
 }
@@ -179,12 +184,14 @@ struct path_entry {
 };
 
 static int path_entry_cmp(const void *unused_cmp_data,
-                          const void *entry,
-                          const void *entry_or_key,
+                          const struct hashmap_entry *eptr,
+                          const struct hashmap_entry *entry_or_key,
                           const void *key)
 {
-        const struct path_entry *a = entry;
-        const struct path_entry *b = entry_or_key;
+        const struct path_entry *a, *b;
+
+        a = container_of(eptr, const struct path_entry, entry);
+        b = container_of(entry_or_key, const struct path_entry, entry);
 
         return strcmp(a->path, key ? key : b->path);
 }
@@ -234,8 +241,8 @@ static void changed_files(struct hashmap *result, const char *index_path,
         while (!strbuf_getline_nul(&buf, fp)) {
                 struct path_entry *entry;
                 FLEX_ALLOC_STR(entry, path, buf.buf);
-                hashmap_entry_init(entry, strhash(buf.buf));
-                hashmap_add(result, entry);
+                hashmap_entry_init(&entry->entry, strhash(buf.buf));
+                hashmap_add(result, &entry->entry);
         }
         fclose(fp);
         if (finish_command(&diff_files))
@@ -461,12 +468,13 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
 
                         /* Avoid duplicate working_tree entries */
                         FLEX_ALLOC_STR(entry, path, dst_path);
-                        hashmap_entry_init(entry, strhash(dst_path));
-                        if (hashmap_get(&working_tree_dups, entry, NULL)) {
+                        hashmap_entry_init(&entry->entry, strhash(dst_path));
+                        if (hashmap_get(&working_tree_dups, &entry->entry,
+                                        NULL)) {
                                 free(entry);
                                 continue;
                         }
-                        hashmap_add(&working_tree_dups, entry);
+                        hashmap_add(&working_tree_dups, &entry->entry);
 
                         if (!use_wt_file(workdir, dst_path, &roid)) {
                                 if (checkout_path(rmode, &roid, dst_path,
@@ -530,8 +538,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
          * temporary file to both the left and right directories to show the
          * change in the recorded SHA1 for the submodule.
          */
-        hashmap_iter_init(&submodules, &iter);
-        while ((entry = hashmap_iter_next(&iter))) {
+        hashmap_for_each_entry(&submodules, &iter, entry,
+                                entry /* member name */) {
                 if (*entry->left) {
                         add_path(&ldir, ldir_len, entry->path);
                         ensure_leading_directories(ldir.buf);
@@ -549,8 +557,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
          * shows only the link itself, not the contents of the link target.
          * This loop replicates that behavior.
          */
-        hashmap_iter_init(&symlinks2, &iter);
-        while ((entry = hashmap_iter_next(&iter))) {
+        hashmap_for_each_entry(&symlinks2, &iter, entry,
+                                entry /* member name */) {
                 if (*entry->left) {
                         add_path(&ldir, ldir_len, entry->path);
                         ensure_leading_directories(ldir.buf);
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index f541f55d33..dbec4df92b 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -40,6 +40,7 @@ static int no_data;
 static int full_tree;
 static int reference_excluded_commits;
 static int show_original_ids;
+static int mark_tags;
 static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
 static struct string_list tag_refs = STRING_LIST_INIT_NODUP;
 static struct refspec refspecs = REFSPEC_INIT_FETCH;
@@ -126,10 +127,15 @@ struct anonymized_entry {
 };
 
 static int anonymized_entry_cmp(const void *unused_cmp_data,
-                                const void *va, const void *vb,
+                                const struct hashmap_entry *eptr,
+                                const struct hashmap_entry *entry_or_key,
                                 const void *unused_keydata)
 {
-        const struct anonymized_entry *a = va, *b = vb;
+        const struct anonymized_entry *a, *b;
+
+        a = container_of(eptr, const struct anonymized_entry, hash);
+        b = container_of(entry_or_key, const struct anonymized_entry, hash);
+
         return a->orig_len != b->orig_len ||
                 memcmp(a->orig, b->orig, a->orig_len);
 }
@@ -148,10 +154,10 @@ static const void *anonymize_mem(struct hashmap *map,
         if (!map->cmpfn)
                 hashmap_init(map, anonymized_entry_cmp, NULL, 0);
 
-        hashmap_entry_init(&key, memhash(orig, *len));
+        hashmap_entry_init(&key.hash, memhash(orig, *len));
         key.orig = orig;
         key.orig_len = *len;
-        ret = hashmap_get(map, &key, NULL);
+        ret = hashmap_get_entry(map, &key, hash, NULL);
 
         if (!ret) {
                 ret = xmalloc(sizeof(*ret));
@@ -160,7 +166,7 @@ static const void *anonymize_mem(struct hashmap *map,
                 ret->orig_len = *len;
                 ret->anon = generate(orig, len);
                 ret->anon_len = *len;
-                hashmap_put(map, ret);
+                hashmap_put(map, &ret->hash);
         }
 
         *len = ret->anon_len;
@@ -842,25 +848,40 @@ static void handle_tag(const char *name, struct tag *tag)
                         free(buf);
                         return;
                 case REWRITE:
-                        if (tagged->type != OBJ_COMMIT) {
-                                die("tag %s tags unexported %s!",
-                                    oid_to_hex(&tag->object.oid),
-                                    type_name(tagged->type));
-                        }
-                        p = rewrite_commit((struct commit *)tagged);
-                        if (!p) {
-                                printf("reset %s\nfrom %s\n\n",
-                                       name, oid_to_hex(&null_oid));
-                                free(buf);
-                                return;
+                        if (tagged->type == OBJ_TAG && !mark_tags) {
+                                die(_("Error: Cannot export nested tags unless --mark-tags is specified."));
+                        } else if (tagged->type == OBJ_COMMIT) {
+                                p = rewrite_commit((struct commit *)tagged);
+                                if (!p) {
+                                        printf("reset %s\nfrom %s\n\n",
+                                               name, oid_to_hex(&null_oid));
+                                        free(buf);
+                                        return;
+                                }
+                                tagged_mark = get_object_mark(&p->object);
+                        } else {
+                                /* tagged->type is either OBJ_BLOB or OBJ_TAG */
+                                tagged_mark = get_object_mark(tagged);
                         }
-                        tagged_mark = get_object_mark(&p->object);
                 }
         }
 
+        if (tagged->type == OBJ_TAG) {
+                printf("reset %s\nfrom %s\n\n",
+                       name, oid_to_hex(&null_oid));
+        }
         if (starts_with(name, "refs/tags/"))
                 name += 10;
-        printf("tag %s\nfrom :%d\n", name, tagged_mark);
+        printf("tag %s\n", name);
+        if (mark_tags) {
+                mark_next_object(&tag->object);
+                printf("mark :%"PRIu32"\n", last_idnum);
+        }
+        if (tagged_mark)
+                printf("from :%d\n", tagged_mark);
+        else
+                printf("from %s\n", oid_to_hex(&tagged->oid));
+
         if (show_original_ids)
                 printf("original-oid %s\n", oid_to_hex(&tag->object.oid));
         printf("%.*s%sdata %d\n%.*s\n",
@@ -1047,11 +1068,16 @@ static void export_marks(char *file)
                 error("Unable to write marks file %s.", file);
 }
 
-static void import_marks(char *input_file)
+static void import_marks(char *input_file, int check_exists)
 {
         char line[512];
-        FILE *f = xfopen(input_file, "r");
+        FILE *f;
+        struct stat sb;
+
+        if (check_exists && stat(input_file, &sb))
+                return;
 
+        f = xfopen(input_file, "r");
         while (fgets(line, sizeof(line), f)) {
                 uint32_t mark;
                 char *line_end, *mark_end;
@@ -1115,7 +1141,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
         struct rev_info revs;
         struct object_array commits = OBJECT_ARRAY_INIT;
         struct commit *commit;
-        char *export_filename = NULL, *import_filename = NULL;
+        char *export_filename = NULL,
+             *import_filename = NULL,
+             *import_filename_if_exists = NULL;
         uint32_t lastimportid;
         struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
         struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP;
@@ -1135,6 +1163,10 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
                              N_("Dump marks to this file")),
                 OPT_STRING(0, "import-marks", &import_filename, N_("file"),
                              N_("Import marks from this file")),
+                OPT_STRING(0, "import-marks-if-exists",
+                             &import_filename_if_exists,
+                             N_("file"),
+                             N_("Import marks from this file if it exists")),
                 OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger,
                          N_("Fake a tagger when tags lack one")),
                 OPT_BOOL(0, "full-tree", &full_tree,
@@ -1149,6 +1181,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
                          &reference_excluded_commits, N_("Reference parents which are not in fast-export stream by object id")),
                 OPT_BOOL(0, "show-original-ids", &show_original_ids,
                             N_("Show original object ids of blobs/commits")),
+                OPT_BOOL(0, "mark-tags", &mark_tags,
+                            N_("Label tags with mark ids")),
 
                 OPT_END()
         };
@@ -1182,8 +1216,12 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
         if (use_done_feature)
                 printf("feature done\n");
 
+        if (import_filename && import_filename_if_exists)
+                die(_("Cannot pass both --import-marks and --import-marks-if-exists"));
         if (import_filename)
-                import_marks(import_filename);
+                import_marks(import_filename, 0);
+        else if (import_filename_if_exists)
+                import_marks(import_filename_if_exists, 1);
         lastimportid = last_idnum;
 
         if (import_filename && revs.prune_data.nr)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 24d382b2fb..46ce7c2710 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -59,7 +59,8 @@ static int verbosity, deepen_relative, set_upstream;
 static int progress = -1;
 static int enable_auto_gc = 1;
 static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
-static int max_children = 1;
+static int max_jobs = -1, submodule_fetch_jobs_config = -1;
+static int fetch_parallel_config = 1;
 static enum transport_family family;
 static const char *depth;
 static const char *deepen_since;
@@ -76,6 +77,7 @@ static struct refspec refmap = REFSPEC_INIT_FETCH;
 static struct list_objects_filter_options filter_options;
 static struct string_list server_options = STRING_LIST_INIT_DUP;
 static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
+static int fetch_write_commit_graph = -1;
 
 static int git_fetch_config(const char *k, const char *v, void *cb)
 {
@@ -101,13 +103,20 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
         }
 
         if (!strcmp(k, "submodule.fetchjobs")) {
-                max_children = parse_submodule_fetchjobs(k, v);
+                submodule_fetch_jobs_config = parse_submodule_fetchjobs(k, v);
                 return 0;
         } else if (!strcmp(k, "fetch.recursesubmodules")) {
                 recurse_submodules = parse_fetch_recurse_submodules_arg(k, v);
                 return 0;
         }
 
+        if (!strcmp(k, "fetch.parallel")) {
+                fetch_parallel_config = git_config_int(k, v);
+                if (fetch_parallel_config < 0)
+                        die(_("fetch.parallel cannot be negative"));
+                return 0;
+        }
+
         return git_default_config(k, v, cb);
 }
 
@@ -141,7 +150,7 @@ static struct option builtin_fetch_options[] = {
                     N_("fetch all tags and associated objects"), TAGS_SET),
         OPT_SET_INT('n', NULL, &tags,
                     N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
-        OPT_INTEGER('j', "jobs", &max_children,
+        OPT_INTEGER('j', "jobs", &max_jobs,
                     N_("number of submodules fetched in parallel")),
         OPT_BOOL('p', "prune", &prune,
                  N_("prune remote-tracking branches no longer on remote")),
@@ -190,6 +199,8 @@ static struct option builtin_fetch_options[] = {
                  N_("run 'gc --auto' after fetching")),
         OPT_BOOL(0, "show-forced-updates", &fetch_show_forced_updates,
                  N_("check for forced-updates on all updated branches")),
+        OPT_BOOL(0, "write-commit-graph", &fetch_write_commit_graph,
+                 N_("write the commit-graph after fetching")),
         OPT_END()
 };
 
@@ -256,20 +267,21 @@ static void create_fetch_oidset(struct ref **head, struct oidset *out)
 }
 
 struct refname_hash_entry {
-        struct hashmap_entry ent; /* must be the first member */
+        struct hashmap_entry ent;
         struct object_id oid;
         int ignore;
         char refname[FLEX_ARRAY];
 };
 
 static int refname_hash_entry_cmp(const void *hashmap_cmp_fn_data,
-                                  const void *e1_,
-                                  const void *e2_,
+                                  const struct hashmap_entry *eptr,
+                                  const struct hashmap_entry *entry_or_key,
                                   const void *keydata)
 {
-        const struct refname_hash_entry *e1 = e1_;
-        const struct refname_hash_entry *e2 = e2_;
+        const struct refname_hash_entry *e1, *e2;
 
+        e1 = container_of(eptr, const struct refname_hash_entry, ent);
+        e2 = container_of(entry_or_key, const struct refname_hash_entry, ent);
         return strcmp(e1->refname, keydata ? keydata : e2->refname);
 }
 
@@ -281,9 +293,9 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
         size_t len = strlen(refname);
 
         FLEX_ALLOC_MEM(ent, refname, refname, len);
-        hashmap_entry_init(ent, strhash(refname));
+        hashmap_entry_init(&ent->ent, strhash(refname));
         oidcpy(&ent->oid, oid);
-        hashmap_add(map, ent);
+        hashmap_add(map, &ent->ent);
         return ent;
 }
 
@@ -372,7 +384,7 @@ static void find_non_local_tags(const struct ref *refs,
                 item = refname_hash_add(&remote_refs, ref->name, &ref->old_oid);
                 string_list_insert(&remote_refs_list, ref->name);
         }
-        hashmap_free(&existing_refs, 1);
+        hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
 
         /*
          * We may have a final lightweight tag that needs to be
@@ -390,8 +402,10 @@ static void find_non_local_tags(const struct ref *refs,
         for_each_string_list_item(remote_ref_item, &remote_refs_list) {
                 const char *refname = remote_ref_item->string;
                 struct ref *rm;
+                unsigned int hash = strhash(refname);
 
-                item = hashmap_get_from_hash(&remote_refs, strhash(refname), refname);
+                item = hashmap_get_entry_from_hash(&remote_refs, hash, refname,
+                                        struct refname_hash_entry, ent);
                 if (!item)
                         BUG("unseen remote ref?");
 
@@ -405,7 +419,7 @@ static void find_non_local_tags(const struct ref *refs,
                 **tail = rm;
                 *tail = &rm->next;
         }
-        hashmap_free(&remote_refs, 1);
+        hashmap_free_entries(&remote_refs, struct refname_hash_entry, ent);
         string_list_clear(&remote_refs_list, 0);
         oidset_clear(&fetch_oids);
 }
@@ -524,17 +538,18 @@ static struct ref *get_ref_map(struct remote *remote,
                 if (rm->peer_ref) {
                         const char *refname = rm->peer_ref->name;
                         struct refname_hash_entry *peer_item;
+                        unsigned int hash = strhash(refname);
 
-                        peer_item = hashmap_get_from_hash(&existing_refs,
-                                                          strhash(refname),
-                                                          refname);
+                        peer_item = hashmap_get_entry_from_hash(&existing_refs,
+                                                hash, refname,
+                                                struct refname_hash_entry, ent);
                         if (peer_item) {
                                 struct object_id *old_oid = &peer_item->oid;
                                 oidcpy(&rm->peer_ref->old_oid, old_oid);
                         }
                 }
         }
-        hashmap_free(&existing_refs, 1);
+        hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
 
         return ref_map;
 }
@@ -1062,7 +1077,8 @@ static int check_exist_and_connected(struct ref *ref_map)
          * we need all direct targets to exist.
          */
         for (r = rm; r; r = r->next) {
-                if (!has_object_file(&r->old_oid))
+                if (!has_object_file_with_flags(&r->old_oid,
+                                                OBJECT_INFO_SKIP_FETCH_OBJECT))
                         return -1;
         }
 
@@ -1073,8 +1089,11 @@ static int check_exist_and_connected(struct ref *ref_map)
 static int fetch_refs(struct transport *transport, struct ref *ref_map)
 {
         int ret = check_exist_and_connected(ref_map);
-        if (ret)
+        if (ret) {
+                trace2_region_enter("fetch", "fetch_refs", the_repository);
                 ret = transport_fetch_refs(transport, ref_map);
+                trace2_region_leave("fetch", "fetch_refs", the_repository);
+        }
         if (!ret)
                 /*
                  * Keep the new pack's ".keep" file around to allow the caller
@@ -1090,11 +1109,14 @@ static int consume_refs(struct transport *transport, struct ref *ref_map)
 {
         int connectivity_checked = transport->smart_options
                 ? transport->smart_options->connectivity_checked : 0;
-        int ret = store_updated_refs(transport->url,
-                                     transport->remote->name,
-                                     connectivity_checked,
-                                     ref_map);
+        int ret;
+        trace2_region_enter("fetch", "consume_refs", the_repository);
+        ret = store_updated_refs(transport->url,
+                                 transport->remote->name,
+                                 connectivity_checked,
+                                 ref_map);
         transport_unlock_pack(transport);
+        trace2_region_leave("fetch", "consume_refs", the_repository);
         return ret;
 }
 
@@ -1339,9 +1361,11 @@ static int do_fetch(struct transport *transport,
                         argv_array_push(&ref_prefixes, "refs/tags/");
         }
 
-        if (must_list_refs)
+        if (must_list_refs) {
+                trace2_region_enter("fetch", "remote_refs", the_repository);
                 remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
-        else
+                trace2_region_leave("fetch", "remote_refs", the_repository);
+        } else
                 remote_refs = NULL;
 
         argv_array_clear(&ref_prefixes);
@@ -1380,7 +1404,7 @@ static int do_fetch(struct transport *transport,
 
                 /*
                  * We're setting the upstream configuration for the
-                 * current branch. The relevent upstream is the
+                 * current branch. The relevant upstream is the
                  * fetched branch that is meant to be merged with the
                  * current one, i.e. the one fetched to FETCH_HEAD.
                  *
@@ -1391,7 +1415,7 @@ static int do_fetch(struct transport *transport,
                 for (rm = ref_map; rm; rm = rm->next) {
                         if (!rm->peer_ref) {
                                 if (source_ref) {
-                                        warning(_("multiple branch detected, incompatible with --set-upstream"));
+                                        warning(_("multiple branches detected, incompatible with --set-upstream"));
                                         goto skip;
                                 } else {
                                         source_ref = rm;
@@ -1513,7 +1537,62 @@ static void add_options_to_argv(struct argv_array *argv)
 
 }
 
-static int fetch_multiple(struct string_list *list)
+/* Fetch multiple remotes in parallel */
+
+struct parallel_fetch_state {
+        const char **argv;
+        struct string_list *remotes;
+        int next, result;
+};
+
+static int fetch_next_remote(struct child_process *cp, struct strbuf *out,
+                             void *cb, void **task_cb)
+{
+        struct parallel_fetch_state *state = cb;
+        char *remote;
+
+        if (state->next < 0 || state->next >= state->remotes->nr)
+                return 0;
+
+        remote = state->remotes->items[state->next++].string;
+        *task_cb = remote;
+
+        argv_array_pushv(&cp->args, state->argv);
+        argv_array_push(&cp->args, remote);
+        cp->git_cmd = 1;
+
+        if (verbosity >= 0)
+                printf(_("Fetching %s\n"), remote);
+
+        return 1;
+}
+
+static int fetch_failed_to_start(struct strbuf *out, void *cb, void *task_cb)
+{
+        struct parallel_fetch_state *state = cb;
+        const char *remote = task_cb;
+
+        state->result = error(_("Could not fetch %s"), remote);
+
+        return 0;
+}
+
+static int fetch_finished(int result, struct strbuf *out,
+                          void *cb, void *task_cb)
+{
+        struct parallel_fetch_state *state = cb;
+        const char *remote = task_cb;
+
+        if (result) {
+                strbuf_addf(out, _("could not fetch '%s' (exit code: %d)\n"),
+                            remote, result);
+                state->result = -1;
+        }
+
+        return 0;
+}
+
+static int fetch_multiple(struct string_list *list, int max_children)
 {
         int i, result = 0;
         struct argv_array argv = ARGV_ARRAY_INIT;
@@ -1524,23 +1603,38 @@ static int fetch_multiple(struct string_list *list)
                         return errcode;
         }
 
-        argv_array_pushl(&argv, "fetch", "--append", "--no-auto-gc", NULL);
+        argv_array_pushl(&argv, "fetch", "--append", "--no-auto-gc",
+                        "--no-write-commit-graph", NULL);
         add_options_to_argv(&argv);
 
-        for (i = 0; i < list->nr; i++) {
-                const char *name = list->items[i].string;
-                argv_array_push(&argv, name);
-                if (verbosity >= 0)
-                        printf(_("Fetching %s\n"), name);
-                if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
-                        error(_("Could not fetch %s"), name);
-                        result = 1;
+        if (max_children != 1 && list->nr != 1) {
+                struct parallel_fetch_state state = { argv.argv, list, 0, 0 };
+
+                argv_array_push(&argv, "--end-of-options");
+                result = run_processes_parallel_tr2(max_children,
+                                                    &fetch_next_remote,
+                                                    &fetch_failed_to_start,
+                                                    &fetch_finished,
+                                                    &state,
+                                                    "fetch", "parallel/fetch");
+
+                if (!result)
+                        result = state.result;
+        } else
+                for (i = 0; i < list->nr; i++) {
+                        const char *name = list->items[i].string;
+                        argv_array_push(&argv, name);
+                        if (verbosity >= 0)
+                                printf(_("Fetching %s\n"), name);
+                        if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
+                                error(_("Could not fetch %s"), name);
+                                result = 1;
+                        }
+                        argv_array_pop(&argv);
                 }
-                argv_array_pop(&argv);
-        }
 
         argv_array_clear(&argv);
-        return result;
+        return !!result;
 }
 
 /*
@@ -1666,14 +1760,13 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 
         packet_trace_identity("fetch");
 
-        fetch_if_missing = 0;
-
         /* Record the command line for the reflog */
         strbuf_addstr(&default_rla, "fetch");
         for (i = 1; i < argc; i++)
                 strbuf_addf(&default_rla, " %s", argv[i]);
 
-        fetch_config_from_gitmodules(&max_children, &recurse_submodules);
+        fetch_config_from_gitmodules(&submodule_fetch_jobs_config,
+                                     &recurse_submodules);
         git_config(git_fetch_config, NULL);
 
         argc = parse_options(argc, argv, prefix,
@@ -1739,15 +1832,27 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                         fetch_one_setup_partial(remote);
                 result = fetch_one(remote, argc, argv, prune_tags_ok);
         } else {
+                int max_children = max_jobs;
+
                 if (filter_options.choice)
                         die(_("--filter can only be used with the remote "
                               "configured in extensions.partialclone"));
+
+                if (max_children < 0)
+                        max_children = fetch_parallel_config;
+
                 /* TODO should this also die if we have a previous partial-clone? */
-                result = fetch_multiple(&list);
+                result = fetch_multiple(&list, max_children);
         }
 
         if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
                 struct argv_array options = ARGV_ARRAY_INIT;
+                int max_children = max_jobs;
+
+                if (max_children < 0)
+                        max_children = submodule_fetch_jobs_config;
+                if (max_children < 0)
+                        max_children = fetch_parallel_config;
 
                 add_options_to_argv(&options);
                 result = fetch_populated_submodules(the_repository,
@@ -1763,7 +1868,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
         string_list_clear(&list, 0);
 
         prepare_repo_settings(the_repository);
-        if (the_repository->settings.fetch_write_commit_graph) {
+        if (fetch_write_commit_graph > 0 ||
+            (fetch_write_commit_graph < 0 &&
+             the_repository->settings.fetch_write_commit_graph)) {
                 int commit_graph_flags = COMMIT_GRAPH_WRITE_SPLIT;
                 struct split_commit_graph_opts split_opts;
                 memset(&split_opts, 0, sizeof(struct split_commit_graph_opts));
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 18403a94fa..8d13794b14 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -50,40 +50,20 @@ static int name_objects;
 #define ERROR_REFS 010
 #define ERROR_COMMIT_GRAPH 020
 
-static const char *describe_object(struct object *obj)
+static const char *describe_object(const struct object_id *oid)
 {
-        static struct strbuf bufs[] = {
-                STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
-        };
-        static int b = 0;
-        struct strbuf *buf;
-        char *name = NULL;
-
-        if (name_objects)
-                name = lookup_decoration(fsck_walk_options.object_names, obj);
-
-        buf = bufs + b;
-        b = (b + 1) % ARRAY_SIZE(bufs);
-        strbuf_reset(buf);
-        strbuf_addstr(buf, oid_to_hex(&obj->oid));
-        if (name)
-                strbuf_addf(buf, " (%s)", name);
-
-        return buf->buf;
+        return fsck_describe_object(&fsck_walk_options, oid);
 }
 
-static const char *printable_type(struct object *obj)
+static const char *printable_type(const struct object_id *oid,
+                                  enum object_type type)
 {
         const char *ret;
 
-        if (obj->type == OBJ_NONE) {
-                enum object_type type = oid_object_info(the_repository,
-                                                        &obj->oid, NULL);
-                if (type > 0)
-                        object_as_type(the_repository, obj, type, 0);
-        }
+        if (type == OBJ_NONE)
+                type = oid_object_info(the_repository, oid, NULL);
 
-        ret = type_name(obj->type);
+        ret = type_name(type);
         if (!ret)
                 ret = _("unknown");
 
@@ -118,26 +98,32 @@ static int objerror(struct object *obj, const char *err)
         errors_found |= ERROR_OBJECT;
         /* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
         fprintf_ln(stderr, _("error in %s %s: %s"),
-                   printable_type(obj), describe_object(obj), err);
+                   printable_type(&obj->oid, obj->type),
+                   describe_object(&obj->oid), err);
         return -1;
 }
 
 static int fsck_error_func(struct fsck_options *o,
-        struct object *obj, int type, const char *message)
+                           const struct object_id *oid,
+                           enum object_type object_type,
+                           int msg_type, const char *message)
 {
-        switch (type) {
+        switch (msg_type) {
         case FSCK_WARN:
                 /* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */
                 fprintf_ln(stderr, _("warning in %s %s: %s"),
-                           printable_type(obj), describe_object(obj), message);
+                           printable_type(oid, object_type),
+                           describe_object(oid), message);
                 return 0;
         case FSCK_ERROR:
                 /* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
                 fprintf_ln(stderr, _("error in %s %s: %s"),
-                           printable_type(obj), describe_object(obj), message);
+                           printable_type(oid, object_type),
+                           describe_object(oid), message);
                 return 1;
         default:
-                BUG("%d (FSCK_IGNORE?) should never trigger this callback", type);
+                BUG("%d (FSCK_IGNORE?) should never trigger this callback",
+                    msg_type);
         }
 }
 
@@ -155,7 +141,8 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
         if (!obj) {
                 /* ... these references to parent->fld are safe here */
                 printf_ln(_("broken link from %7s %s"),
-                          printable_type(parent), describe_object(parent));
+                          printable_type(&parent->oid, parent->type),
+                          describe_object(&parent->oid));
                 printf_ln(_("broken link from %7s %s"),
                           (type == OBJ_ANY ? _("unknown") : type_name(type)),
                           _("unknown"));
@@ -183,10 +170,10 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
                 if (parent && !has_object_file(&obj->oid)) {
                         printf_ln(_("broken link from %7s %s\n"
                                     "              to %7s %s"),
-                                  printable_type(parent),
-                                  describe_object(parent),
-                                  printable_type(obj),
-                                  describe_object(obj));
+                                  printable_type(&parent->oid, parent->type),
+                                  describe_object(&parent->oid),
+                                  printable_type(&obj->oid, obj->type),
+                                  describe_object(&obj->oid));
                         errors_found |= ERROR_REACHABLE;
                 }
                 return 1;
@@ -292,8 +279,9 @@ static void check_reachable_object(struct object *obj)
                         return;
                 if (has_object_pack(&obj->oid))
                         return; /* it is in pack - forget about it */
-                printf_ln(_("missing %s %s"), printable_type(obj),
-                          describe_object(obj));
+                printf_ln(_("missing %s %s"),
+                          printable_type(&obj->oid, obj->type),
+                          describe_object(&obj->oid));
                 errors_found |= ERROR_REACHABLE;
                 return;
         }
@@ -318,8 +306,9 @@ static void check_unreachable_object(struct object *obj)
          * since this is something that is prunable.
          */
         if (show_unreachable) {
-                printf_ln(_("unreachable %s %s"), printable_type(obj),
-                          describe_object(obj));
+                printf_ln(_("unreachable %s %s"),
+                          printable_type(&obj->oid, obj->type),
+                          describe_object(&obj->oid));
                 return;
         }
 
@@ -337,12 +326,13 @@ static void check_unreachable_object(struct object *obj)
          */
         if (!(obj->flags & USED)) {
                 if (show_dangling)
-                        printf_ln(_("dangling %s %s"), printable_type(obj),
-                                  describe_object(obj));
+                        printf_ln(_("dangling %s %s"),
+                                  printable_type(&obj->oid, obj->type),
+                                  describe_object(&obj->oid));
                 if (write_lost_and_found) {
                         char *filename = git_pathdup("lost-found/%s/%s",
                                 obj->type == OBJ_COMMIT ? "commit" : "other",
-                                describe_object(obj));
+                                describe_object(&obj->oid));
                         FILE *f;
 
                         if (safe_create_leading_directories_const(filename)) {
@@ -355,7 +345,7 @@ static void check_unreachable_object(struct object *obj)
                                 if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1))
                                         die_errno(_("could not write '%s'"), filename);
                         } else
-                                fprintf(f, "%s\n", describe_object(obj));
+                                fprintf(f, "%s\n", describe_object(&obj->oid));
                         if (fclose(f))
                                 die_errno(_("could not finish '%s'"),
                                           filename);
@@ -374,7 +364,7 @@ static void check_unreachable_object(struct object *obj)
 static void check_object(struct object *obj)
 {
         if (verbose)
-                fprintf_ln(stderr, _("Checking %s"), describe_object(obj));
+                fprintf_ln(stderr, _("Checking %s"), describe_object(&obj->oid));
 
         if (obj->flags & REACHABLE)
                 check_reachable_object(obj);
@@ -432,7 +422,8 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
 
         if (verbose)
                 fprintf_ln(stderr, _("Checking %s %s"),
-                           printable_type(obj), describe_object(obj));
+                           printable_type(&obj->oid, obj->type),
+                           describe_object(&obj->oid));
 
         if (fsck_walk(obj, NULL, &fsck_obj_options))
                 objerror(obj, _("broken links"));
@@ -445,7 +436,7 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
 
                 if (!commit->parents && show_root)
                         printf_ln(_("root %s"),
-                                  describe_object(&commit->object));
+                                  describe_object(&commit->object.oid));
         }
 
         if (obj->type == OBJ_TAG) {
@@ -453,10 +444,10 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
 
                 if (show_tags && tag->tagged) {
                         printf_ln(_("tagged %s %s (%s) in %s"),
-                                  printable_type(tag->tagged),
-                                  describe_object(tag->tagged),
+                                  printable_type(&tag->tagged->oid, tag->tagged->type),
+                                  describe_object(&tag->tagged->oid),
                                   tag->tag,
-                                  describe_object(&tag->object));
+                                  describe_object(&tag->object.oid));
                 }
         }
 
@@ -499,10 +490,10 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
         if (!is_null_oid(oid)) {
                 obj = lookup_object(the_repository, oid);
                 if (obj && (obj->flags & HAS_OBJ)) {
-                        if (timestamp && name_objects)
-                                add_decoration(fsck_walk_options.object_names,
-                                        obj,
-                                        xstrfmt("%s@{%"PRItime"}", refname, timestamp));
+                        if (timestamp)
+                                fsck_put_object_name(&fsck_walk_options, oid,
+                                                     "%s@{%"PRItime"}",
+                                                     refname, timestamp);
                         obj->flags |= USED;
                         mark_object_reachable(obj);
                 } else if (!is_promisor_object(oid)) {
@@ -566,9 +557,8 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,
         }
         default_refs++;
         obj->flags |= USED;
-        if (name_objects)
-                add_decoration(fsck_walk_options.object_names,
-                        obj, xstrdup(refname));
+        fsck_put_object_name(&fsck_walk_options,
+                             oid, "%s", refname);
         mark_object_reachable(obj);
 
         return 0;
@@ -742,9 +732,7 @@ static int fsck_cache_tree(struct cache_tree *it)
                         return 1;
                 }
                 obj->flags |= USED;
-                if (name_objects)
-                        add_decoration(fsck_walk_options.object_names,
-                                obj, xstrdup(":"));
+                fsck_put_object_name(&fsck_walk_options, &it->oid, ":");
                 mark_object_reachable(obj);
                 if (obj->type != OBJ_TREE)
                         err |= objerror(obj, _("non-tree in cache-tree"));
@@ -830,8 +818,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
         }
 
         if (name_objects)
-                fsck_walk_options.object_names =
-                        xcalloc(1, sizeof(struct decoration));
+                fsck_enable_object_names(&fsck_walk_options);
 
         git_config(fsck_config, NULL);
 
@@ -890,9 +877,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
                         }
 
                         obj->flags |= USED;
-                        if (name_objects)
-                                add_decoration(fsck_walk_options.object_names,
-                                        obj, xstrdup(arg));
+                        fsck_put_object_name(&fsck_walk_options, &oid,
+                                             "%s", arg);
                         mark_object_reachable(obj);
                         continue;
                 }
@@ -928,10 +914,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
                                 continue;
                         obj = &blob->object;
                         obj->flags |= USED;
-                        if (name_objects)
-                                add_decoration(fsck_walk_options.object_names,
-                                        obj,
-                                        xstrfmt(":%s", active_cache[i]->name));
+                        fsck_put_object_name(&fsck_walk_options, &obj->oid,
+                                             ":%s", active_cache[i]->name);
                         mark_object_reachable(obj);
                 }
                 if (active_cache_tree)
diff --git a/builtin/gc.c b/builtin/gc.c
index fadb45489f..3f76bf4aa7 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -458,7 +458,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
 /*
  * Returns 0 if there was no previous error and gc can proceed, 1 if
  * gc should not proceed due to an error in the last run. Prints a
- * message and returns -1 if an error occured while reading gc.log
+ * message and returns -1 if an error occurred while reading gc.log
  */
 static int report_last_gc_error(void)
 {
@@ -601,7 +601,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                 if (detach_auto) {
                         int ret = report_last_gc_error();
                         if (ret < 0)
-                                /* an I/O error occured, already reported */
+                                /* an I/O error occurred, already reported */
                                 exit(128);
                         if (ret == 1)
                                 /* Last gc --auto failed. Skip this one. */
diff --git a/builtin/grep.c b/builtin/grep.c
index 69ac053acc..50ce8d9461 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1147,5 +1147,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                 run_pager(&opt, prefix);
         clear_pathspec(&pathspec);
         free_grep_patterns(&opt);
+        grep_destroy();
         return !hit;
 }
diff --git a/builtin/log.c b/builtin/log.c
index c4b35fdaf9..a26f223ab4 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -37,6 +37,7 @@
 #include "range-diff.h"
 
 #define MAIL_DEFAULT_WRAP 72
+#define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100
 
 /* Set a default date-time format for git log ("log.date" config variable) */
 static const char *default_date_mode = NULL;
@@ -765,23 +766,51 @@ static void add_header(const char *value)
         item->string[len] = '\0';
 }
 
-#define THREAD_SHALLOW 1
-#define THREAD_DEEP 2
-static int thread;
+enum cover_setting {
+        COVER_UNSET,
+        COVER_OFF,
+        COVER_ON,
+        COVER_AUTO
+};
+
+enum thread_level {
+        THREAD_UNSET,
+        THREAD_SHALLOW,
+        THREAD_DEEP
+};
+
+enum cover_from_description {
+        COVER_FROM_NONE,
+        COVER_FROM_MESSAGE,
+        COVER_FROM_SUBJECT,
+        COVER_FROM_AUTO
+};
+
+static enum thread_level thread;
 static int do_signoff;
 static int base_auto;
 static char *from;
 static const char *signature = git_version_string;
 static const char *signature_file;
-static int config_cover_letter;
+static enum cover_setting config_cover_letter;
 static const char *config_output_directory;
+static enum cover_from_description cover_from_description_mode = COVER_FROM_MESSAGE;
 
-enum {
-        COVER_UNSET,
-        COVER_OFF,
-        COVER_ON,
-        COVER_AUTO
-};
+static enum cover_from_description parse_cover_from_description(const char *arg)
+{
+        if (!arg || !strcmp(arg, "default"))
+                return COVER_FROM_MESSAGE;
+        else if (!strcmp(arg, "none"))
+                return COVER_FROM_NONE;
+        else if (!strcmp(arg, "message"))
+                return COVER_FROM_MESSAGE;
+        else if (!strcmp(arg, "subject"))
+                return COVER_FROM_SUBJECT;
+        else if (!strcmp(arg, "auto"))
+                return COVER_FROM_AUTO;
+        else
+                die(_("%s: invalid cover from description mode"), arg);
+}
 
 static int git_format_config(const char *var, const char *value, void *cb)
 {
@@ -836,7 +865,7 @@ static int git_format_config(const char *var, const char *value, void *cb)
                         thread = THREAD_SHALLOW;
                         return 0;
                 }
-                thread = git_config_bool(var, value) && THREAD_SHALLOW;
+                thread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;
                 return 0;
         }
         if (!strcmp(var, "format.signoff")) {
@@ -888,6 +917,10 @@ static int git_format_config(const char *var, const char *value, void *cb)
                 }
                 return 0;
         }
+        if (!strcmp(var, "format.coverfromdescription")) {
+                cover_from_description_mode = parse_cover_from_description(value);
+                return 0;
+        }
 
         return git_log_config(var, value, cb);
 }
@@ -994,20 +1027,6 @@ static void print_signature(FILE *file)
         putc('\n', file);
 }
 
-static void add_branch_description(struct strbuf *buf, const char *branch_name)
-{
-        struct strbuf desc = STRBUF_INIT;
-        if (!branch_name || !*branch_name)
-                return;
-        read_branch_desc(&desc, branch_name);
-        if (desc.len) {
-                strbuf_addch(buf, '\n');
-                strbuf_addbuf(buf, &desc);
-                strbuf_addch(buf, '\n');
-        }
-        strbuf_release(&desc);
-}
-
 static char *find_branch_name(struct rev_info *rev)
 {
         int i, positive = -1;
@@ -1054,6 +1073,44 @@ static void show_diffstat(struct rev_info *rev,
         fprintf(rev->diffopt.file, "\n");
 }
 
+static void prepare_cover_text(struct pretty_print_context *pp,
+                               const char *branch_name,
+                               struct strbuf *sb,
+                               const char *encoding,
+                               int need_8bit_cte)
+{
+        const char *subject = "*** SUBJECT HERE ***";
+        const char *body = "*** BLURB HERE ***";
+        struct strbuf description_sb = STRBUF_INIT;
+        struct strbuf subject_sb = STRBUF_INIT;
+
+        if (cover_from_description_mode == COVER_FROM_NONE)
+                goto do_pp;
+
+        if (branch_name && *branch_name)
+                read_branch_desc(&description_sb, branch_name);
+        if (!description_sb.len)
+                goto do_pp;
+
+        if (cover_from_description_mode == COVER_FROM_SUBJECT ||
+                        cover_from_description_mode == COVER_FROM_AUTO)
+                body = format_subject(&subject_sb, description_sb.buf, " ");
+
+        if (cover_from_description_mode == COVER_FROM_MESSAGE ||
+                        (cover_from_description_mode == COVER_FROM_AUTO &&
+                         subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))
+                body = description_sb.buf;
+        else
+                subject = subject_sb.buf;
+
+do_pp:
+        pp_title_line(pp, &subject, sb, encoding, need_8bit_cte);
+        pp_remainder(pp, &body, sb, 0);
+
+        strbuf_release(&description_sb);
+        strbuf_release(&subject_sb);
+}
+
 static void make_cover_letter(struct rev_info *rev, int use_stdout,
                               struct commit *origin,
                               int nr, struct commit **list,
@@ -1061,8 +1118,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
                               int quiet)
 {
         const char *committer;
-        const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
-        const char *msg;
         struct shortlog log;
         struct strbuf sb = STRBUF_INIT;
         int i;
@@ -1092,15 +1147,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
         if (!branch_name)
                 branch_name = find_branch_name(rev);
 
-        msg = body;
         pp.fmt = CMIT_FMT_EMAIL;
         pp.date_mode.type = DATE_RFC2822;
         pp.rev = rev;
         pp.print_email_subject = 1;
         pp_user_info(&pp, NULL, &sb, committer, encoding);
-        pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
-        pp_remainder(&pp, &msg, &sb, 0);
-        add_branch_description(&sb, branch_name);
+        prepare_cover_text(&pp, branch_name, &sb, encoding, need_8bit_cte);
         fprintf(rev->diffopt.file, "%s\n", sb.buf);
 
         strbuf_release(&sb);
@@ -1249,9 +1301,9 @@ static int output_directory_callback(const struct option *opt, const char *arg,
 
 static int thread_callback(const struct option *opt, const char *arg, int unset)
 {
-        int *thread = (int *)opt->value;
+        enum thread_level *thread = (enum thread_level *)opt->value;
         if (unset)
-                *thread = 0;
+                *thread = THREAD_UNSET;
         else if (!arg || !strcmp(arg, "shallow"))
                 *thread = THREAD_SHALLOW;
         else if (!strcmp(arg, "deep"))
@@ -1542,6 +1594,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
         int use_patch_format = 0;
         int quiet = 0;
         int reroll_count = -1;
+        char *cover_from_description_arg = NULL;
         char *branch_name = NULL;
         char *base_commit = NULL;
         struct base_tree_info bases;
@@ -1578,6 +1631,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                 { OPTION_CALLBACK, 0, "rfc", &rev, NULL,
                             N_("Use [RFC PATCH] instead of [PATCH]"),
                             PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },
+                OPT_STRING(0, "cover-from-description", &cover_from_description_arg,
+                            N_("cover-from-description-mode"),
+                            N_("generate parts of a cover letter based on a branch's description")),
                 { OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"),
                             N_("Use [<prefix>] instead of [PATCH]"),
                             PARSE_OPT_NONEG, subject_prefix_callback },
@@ -1669,6 +1725,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                              PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
                              PARSE_OPT_KEEP_DASHDASH);
 
+        if (cover_from_description_arg)
+                cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
+
         if (0 < reroll_count) {
                 struct strbuf sprefix = STRBUF_INIT;
                 strbuf_addf(&sprefix, "%s v%d",
@@ -1766,10 +1825,26 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                 setup_pager();
 
         if (output_directory) {
+                int saved;
                 if (rev.diffopt.use_color != GIT_COLOR_ALWAYS)
                         rev.diffopt.use_color = GIT_COLOR_NEVER;
                 if (use_stdout)
                         die(_("standard output, or directory, which one?"));
+                /*
+                 * We consider <outdir> as 'outside of gitdir', therefore avoid
+                 * applying adjust_shared_perm in s-c-l-d.
+                 */
+                saved = get_shared_repository();
+                set_shared_repository(0);
+                switch (safe_create_leading_directories_const(output_directory)) {
+                case SCLD_OK:
+                case SCLD_EXISTS:
+                        break;
+                default:
+                        die(_("could not create leading directories "
+                              "of '%s'"), output_directory);
+                }
+                set_shared_repository(saved);
                 if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
                         die_errno(_("could not create directory '%s'"),
                                   output_directory);
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index 5b910e351e..a4bfd8fc51 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -1,3 +1,4 @@
+#include "cache.h"
 #include "builtin.h"
 #include "commit.h"
 #include "tag.h"
@@ -63,6 +64,9 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
         if (argc - i != 3) /* "--" "<head>" "<remote>" */
                 die(_("not handling anything other than two heads merge."));
 
+        if (repo_read_index_unmerged(the_repository))
+                die_resolve_conflict("merge");
+
         o.branch1 = argv[++i];
         o.branch2 = argv[++i];
 
diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c
index b1ea1a6aa1..5bf88cd2a8 100644
--- a/builtin/multi-pack-index.c
+++ b/builtin/multi-pack-index.c
@@ -6,21 +6,25 @@
 #include "trace2.h"
 
 static char const * const builtin_multi_pack_index_usage[] = {
-        N_("git multi-pack-index [--object-dir=<dir>] (write|verify|expire|repack --batch-size=<size>)"),
+        N_("git multi-pack-index [<options>] (write|verify|expire|repack --batch-size=<size>)"),
         NULL
 };
 
 static struct opts_multi_pack_index {
         const char *object_dir;
         unsigned long batch_size;
+        int progress;
 } opts;
 
 int cmd_multi_pack_index(int argc, const char **argv,
                          const char *prefix)
 {
+        unsigned flags = 0;
+
         static struct option builtin_multi_pack_index_options[] = {
                 OPT_FILENAME(0, "object-dir", &opts.object_dir,
                   N_("object directory containing set of packfile and pack-index pairs")),
+                OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")),
                 OPT_MAGNITUDE(0, "batch-size", &opts.batch_size,
                   N_("during repack, collect pack-files of smaller size into a batch that is larger than this size")),
                 OPT_END(),
@@ -28,12 +32,15 @@ int cmd_multi_pack_index(int argc, const char **argv,
 
         git_config(git_default_config, NULL);
 
+        opts.progress = isatty(2);
         argc = parse_options(argc, argv, prefix,
                              builtin_multi_pack_index_options,
                              builtin_multi_pack_index_usage, 0);
 
         if (!opts.object_dir)
                 opts.object_dir = get_object_directory();
+        if (opts.progress)
+                flags |= MIDX_PROGRESS;
 
         if (argc == 0)
                 usage_with_options(builtin_multi_pack_index_usage,
@@ -47,16 +54,17 @@ int cmd_multi_pack_index(int argc, const char **argv,
         trace2_cmd_mode(argv[0]);
 
         if (!strcmp(argv[0], "repack"))
-                return midx_repack(the_repository, opts.object_dir, (size_t)opts.batch_size);
+                return midx_repack(the_repository, opts.object_dir,
+                        (size_t)opts.batch_size, flags);
         if (opts.batch_size)
                 die(_("--batch-size option is only for 'repack' subcommand"));
 
         if (!strcmp(argv[0], "write"))
-                return write_midx_file(opts.object_dir);
+                return write_midx_file(opts.object_dir, flags);
         if (!strcmp(argv[0], "verify"))
-                return verify_midx_file(the_repository, opts.object_dir);
+                return verify_midx_file(the_repository, opts.object_dir, flags);
         if (!strcmp(argv[0], "expire"))
-                return expire_midx_packs(the_repository, opts.object_dir);
+                return expire_midx_packs(the_repository, opts.object_dir, flags);
 
         die(_("unrecognized subcommand: %s"), argv[0]);
 }
diff --git a/builtin/notes.c b/builtin/notes.c
index 02e97f55c5..95456f3165 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -513,7 +513,7 @@ static int copy(int argc, const char **argv, const char *prefix)
                 }
         }
 
-        if (argc < 2) {
+        if (argc < 1) {
                 error(_("too few parameters"));
                 usage_with_options(git_notes_copy_usage, options);
         }
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 5876583220..e231c7f5ca 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -92,10 +92,11 @@ static struct progress *progress_state;
 
 static struct packed_git *reuse_packfile;
 static uint32_t reuse_packfile_objects;
-static off_t reuse_packfile_offset;
+static struct bitmap *reuse_packfile_bitmap;
 
 static int use_bitmap_index_default = 1;
 static int use_bitmap_index = -1;
+static int allow_pack_reuse = 1;
 static enum {
         WRITE_BITMAP_FALSE = 0,
         WRITE_BITMAP_QUIET,
@@ -163,7 +164,7 @@ static void *get_delta(struct object_entry *entry)
         delta_buf = diff_delta(base_buf, base_size,
                                buf, size, &delta_size, 0);
         /*
-         * We succesfully computed this delta once but dropped it for
+         * We successfully computed this delta once but dropped it for
          * memory reasons. Something is very wrong if this time we
          * recompute and create a different delta.
          */
@@ -784,57 +785,177 @@ static struct object_entry **compute_write_order(void)
         return wo;
 }
 
-static off_t write_reused_pack(struct hashfile *f)
+/*
+ * Record the offsets needed in our reused packfile chunks due to
+ * "gaps" where we omitted some objects.
+ */
+static struct reused_chunk {
+        off_t start;
+        off_t offset;
+} *reused_chunks;
+static int reused_chunks_nr;
+static int reused_chunks_alloc;
+
+static void record_reused_object(off_t where, off_t offset)
 {
-        unsigned char buffer[8192];
-        off_t to_write, total;
-        int fd;
+        if (reused_chunks_nr && reused_chunks[reused_chunks_nr-1].offset == offset)
+                return;
 
-        if (!is_pack_valid(reuse_packfile))
-                die(_("packfile is invalid: %s"), reuse_packfile->pack_name);
+        ALLOC_GROW(reused_chunks, reused_chunks_nr + 1,
+                   reused_chunks_alloc);
+        reused_chunks[reused_chunks_nr].start = where;
+        reused_chunks[reused_chunks_nr].offset = offset;
+        reused_chunks_nr++;
+}
 
-        fd = git_open(reuse_packfile->pack_name);
-        if (fd < 0)
-                die_errno(_("unable to open packfile for reuse: %s"),
-                          reuse_packfile->pack_name);
+/*
+ * Binary search to find the chunk that "where" is in. Note
+ * that we're not looking for an exact match, just the first
+ * chunk that contains it (which implicitly ends at the start
+ * of the next chunk.
+ */
+static off_t find_reused_offset(off_t where)
+{
+        int lo = 0, hi = reused_chunks_nr;
+        while (lo < hi) {
+                int mi = lo + ((hi - lo) / 2);
+                if (where == reused_chunks[mi].start)
+                        return reused_chunks[mi].offset;
+                if (where < reused_chunks[mi].start)
+                        hi = mi;
+                else
+                        lo = mi + 1;
+        }
 
-        if (lseek(fd, sizeof(struct pack_header), SEEK_SET) == -1)
-                die_errno(_("unable to seek in reused packfile"));
+        /*
+         * The first chunk starts at zero, so we can't have gone below
+         * there.
+         */
+        assert(lo);
+        return reused_chunks[lo-1].offset;
+}
 
-        if (reuse_packfile_offset < 0)
-                reuse_packfile_offset = reuse_packfile->pack_size - the_hash_algo->rawsz;
+static void write_reused_pack_one(size_t pos, struct hashfile *out,
+                                  struct pack_window **w_curs)
+{
+        off_t offset, next, cur;
+        enum object_type type;
+        unsigned long size;
 
-        total = to_write = reuse_packfile_offset - sizeof(struct pack_header);
+        offset = reuse_packfile->revindex[pos].offset;
+        next = reuse_packfile->revindex[pos + 1].offset;
 
-        while (to_write) {
-                int read_pack = xread(fd, buffer, sizeof(buffer));
+        record_reused_object(offset, offset - hashfile_total(out));
 
-                if (read_pack <= 0)
-                        die_errno(_("unable to read from reused packfile"));
+        cur = offset;
+        type = unpack_object_header(reuse_packfile, w_curs, &cur, &size);
+        assert(type >= 0);
 
-                if (read_pack > to_write)
-                        read_pack = to_write;
+        if (type == OBJ_OFS_DELTA) {
+                off_t base_offset;
+                off_t fixup;
+
+                unsigned char header[MAX_PACK_OBJECT_HEADER];
+                unsigned len;
+
+                base_offset = get_delta_base(reuse_packfile, w_curs, &cur, type, offset);
+                assert(base_offset != 0);
+
+                /* Convert to REF_DELTA if we must... */
+                if (!allow_ofs_delta) {
+                        int base_pos = find_revindex_position(reuse_packfile, base_offset);
+                        const unsigned char *base_sha1 =
+                                nth_packed_object_sha1(reuse_packfile,
+                                                       reuse_packfile->revindex[base_pos].nr);
+
+                        len = encode_in_pack_object_header(header, sizeof(header),
+                                                           OBJ_REF_DELTA, size);
+                        hashwrite(out, header, len);
+                        hashwrite(out, base_sha1, 20);
+                        copy_pack_data(out, reuse_packfile, w_curs, cur, next - cur);
+                        return;
+                }
 
-                hashwrite(f, buffer, read_pack);
-                to_write -= read_pack;
+                /* Otherwise see if we need to rewrite the offset... */
+                fixup = find_reused_offset(offset) -
+                        find_reused_offset(base_offset);
+                if (fixup) {
+                        unsigned char ofs_header[10];
+                        unsigned i, ofs_len;
+                        off_t ofs = offset - base_offset - fixup;
+
+                        len = encode_in_pack_object_header(header, sizeof(header),
+                                                           OBJ_OFS_DELTA, size);
+
+                        i = sizeof(ofs_header) - 1;
+                        ofs_header[i] = ofs & 127;
+                        while (ofs >>= 7)
+                                ofs_header[--i] = 128 | (--ofs & 127);
+
+                        ofs_len = sizeof(ofs_header) - i;
+
+                        hashwrite(out, header, len);
+                        hashwrite(out, ofs_header + sizeof(ofs_header) - ofs_len, ofs_len);
+                        copy_pack_data(out, reuse_packfile, w_curs, cur, next - cur);
+                        return;
+                }
+
+                /* ...otherwise we have no fixup, and can write it verbatim */
+        }
+
+        copy_pack_data(out, reuse_packfile, w_curs, offset, next - offset);
+}
+
+static size_t write_reused_pack_verbatim(struct hashfile *out,
+                                         struct pack_window **w_curs)
+{
+        size_t pos = 0;
+
+        while (pos < reuse_packfile_bitmap->word_alloc &&
+                        reuse_packfile_bitmap->words[pos] == (eword_t)~0)
+                pos++;
+
+        if (pos) {
+                off_t to_write;
+
+                written = (pos * BITS_IN_EWORD);
+                to_write = reuse_packfile->revindex[written].offset
+                        - sizeof(struct pack_header);
+
+                record_reused_object(sizeof(struct pack_header), 0);
+                hashflush(out);
+                copy_pack_data(out, reuse_packfile, w_curs,
+                        sizeof(struct pack_header), to_write);
 
-                /*
-                 * We don't know the actual number of objects written,
-                 * only how many bytes written, how many bytes total, and
-                 * how many objects total. So we can fake it by pretending all
-                 * objects we are writing are the same size. This gives us a
-                 * smooth progress meter, and at the end it matches the true
-                 * answer.
-                 */
-                written = reuse_packfile_objects *
-                                (((double)(total - to_write)) / total);
                 display_progress(progress_state, written);
         }
+        return pos;
+}
+
+static void write_reused_pack(struct hashfile *f)
+{
+        size_t i = 0;
+        uint32_t offset;
+        struct pack_window *w_curs = NULL;
+
+        if (allow_ofs_delta)
+                i = write_reused_pack_verbatim(f, &w_curs);
+
+        for (; i < reuse_packfile_bitmap->word_alloc; ++i) {
+                eword_t word = reuse_packfile_bitmap->words[i];
+                size_t pos = (i * BITS_IN_EWORD);
 
-        close(fd);
-        written = reuse_packfile_objects;
-        display_progress(progress_state, written);
-        return reuse_packfile_offset - sizeof(struct pack_header);
+                for (offset = 0; offset < BITS_IN_EWORD; ++offset) {
+                        if ((word >> offset) == 0)
+                                break;
+
+                        offset += ewah_bit_ctz64(word >> offset);
+                        write_reused_pack_one(pos + offset, f, &w_curs);
+                        display_progress(progress_state, ++written);
+                }
+        }
+
+        unuse_pack(&w_curs);
 }
 
 static const char no_split_warning[] = N_(
@@ -867,11 +988,9 @@ static void write_pack_file(void)
                 offset = write_pack_header(f, nr_remaining);
 
                 if (reuse_packfile) {
-                        off_t packfile_size;
                         assert(pack_to_stdout);
-
-                        packfile_size = write_reused_pack(f);
-                        offset += packfile_size;
+                        write_reused_pack(f);
+                        offset = hashfile_total(f);
                 }
 
                 nr_written = 0;
@@ -1000,6 +1119,10 @@ static int have_duplicate_entry(const struct object_id *oid,
 {
         struct object_entry *entry;
 
+        if (reuse_packfile_bitmap &&
+            bitmap_walk_contains(bitmap_git, reuse_packfile_bitmap, oid))
+                return 1;
+
         entry = packlist_find(&to_pack, oid);
         if (!entry)
                 return 0;
@@ -2552,6 +2675,13 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
         free(p);
 }
 
+static int obj_is_packed(const struct object_id *oid)
+{
+        return packlist_find(&to_pack, oid) ||
+                (reuse_packfile_bitmap &&
+                 bitmap_walk_contains(bitmap_git, reuse_packfile_bitmap, oid));
+}
+
 static void add_tag_chain(const struct object_id *oid)
 {
         struct tag *tag;
@@ -2563,7 +2693,7 @@ static void add_tag_chain(const struct object_id *oid)
          * it was included via bitmaps, we would not have parsed it
          * previously).
          */
-        if (packlist_find(&to_pack, oid))
+        if (obj_is_packed(oid))
                 return;
 
         tag = lookup_tag(the_repository, oid);
@@ -2587,7 +2717,7 @@ static int add_ref_tag(const char *path, const struct object_id *oid, int flag,
 
         if (starts_with(path, "refs/tags/") && /* is a tag? */
             !peel_ref(path, &peeled)    && /* peelable? */
-            packlist_find(&to_pack, &peeled))      /* object packed? */
+            obj_is_packed(&peeled)) /* object packed? */
                 add_tag_chain(oid);
         return 0;
 }
@@ -2655,6 +2785,7 @@ static void prepare_pack(int window, int depth)
 
         if (nr_deltas && n > 1) {
                 unsigned nr_done = 0;
+
                 if (progress)
                         progress_state = start_progress(_("Compressing objects"),
                                                         nr_deltas);
@@ -2699,6 +2830,10 @@ static int git_pack_config(const char *k, const char *v, void *cb)
                 use_bitmap_index_default = git_config_bool(k, v);
                 return 0;
         }
+        if (!strcmp(k, "pack.allowpackreuse")) {
+                allow_pack_reuse = git_config_bool(k, v);
+                return 0;
+        }
         if (!strcmp(k, "pack.threads")) {
                 delta_search_threads = git_config_int(k, v);
                 if (delta_search_threads < 0)
@@ -3030,8 +3165,8 @@ static void loosen_unused_packed_objects(void)
  */
 static int pack_options_allow_reuse(void)
 {
-        return pack_to_stdout &&
-               allow_ofs_delta &&
+        return allow_pack_reuse &&
+               pack_to_stdout &&
                !ignore_packed_keep_on_disk &&
                !ignore_packed_keep_in_core &&
                (!local || !have_non_local_packs) &&
@@ -3048,7 +3183,7 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
                         bitmap_git,
                         &reuse_packfile,
                         &reuse_packfile_objects,
-                        &reuse_packfile_offset)) {
+                        &reuse_packfile_bitmap)) {
                 assert(reuse_packfile_objects);
                 nr_result += reuse_packfile_objects;
                 display_progress(progress_state, nr_result);
@@ -3509,7 +3644,9 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
         if (progress)
                 fprintf_ln(stderr,
                            _("Total %"PRIu32" (delta %"PRIu32"),"
-                             " reused %"PRIu32" (delta %"PRIu32")"),
-                           written, written_delta, reused, reused_delta);
+                             " reused %"PRIu32" (delta %"PRIu32"),"
+                             " pack-reused %"PRIu32),
+                           written, written_delta, reused, reused_delta,
+                           reuse_packfile_objects);
         return 0;
 }
diff --git a/builtin/push.c b/builtin/push.c
index 3742daf7b0..843f5b22a2 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -143,8 +143,8 @@ static int push_url_of_remote(struct remote *remote, const char ***url_p)
         return remote->url_nr;
 }
 
-static NORETURN int die_push_simple(struct branch *branch,
-                                    struct remote *remote)
+static NORETURN void die_push_simple(struct branch *branch,
+                                     struct remote *remote)
 {
         /*
          * There's no point in using shorten_unambiguous_ref here,
@@ -357,8 +357,10 @@ static int push_with_options(struct transport *transport, struct refspec *rs,
 
         if (verbosity > 0)
                 fprintf(stderr, _("Pushing to %s\n"), transport->url);
+        trace2_region_enter("push", "transport_push", the_repository);
         err = transport_push(the_repository, transport,
                              rs, flags, &reject_reasons);
+        trace2_region_leave("push", "transport_push", the_repository);
         if (err != 0) {
                 fprintf(stderr, "%s", push_get_color(PUSH_COLOR_ERROR));
                 error(_("failed to push some refs to '%s'"), transport->url);
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index ca5e655d2f..d7eeaa26ec 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -162,6 +162,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
         opts.head_idx = -1;
         opts.src_index = &the_index;
         opts.dst_index = &the_index;
+        opts.verbose_update = isatty(2);
 
         git_config(git_read_tree_config, NULL);
 
@@ -185,7 +186,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
 
         if (opts.reset || opts.merge || opts.prefix) {
                 if (read_cache_unmerged() && (opts.prefix || opts.merge))
-                        die("You need to resolve your current index first");
+                        die(_("You need to resolve your current index first"));
                 stage = opts.merge = 1;
         }
         resolve_undo_clear();
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 4a20582e72..e755087b0f 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1471,9 +1471,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                         N_("let the user edit the list of commits to rebase"),
                         PARSE_OPT_NOARG | PARSE_OPT_NONEG,
                         parse_opt_interactive },
-                OPT_SET_INT('p', "preserve-merges", &options.type,
-                            N_("(DEPRECATED) try to recreate merges instead of "
-                               "ignoring them"), REBASE_PRESERVE_MERGES),
+                OPT_SET_INT_F('p', "preserve-merges", &options.type,
+                              N_("(DEPRECATED) try to recreate merges instead of "
+                                 "ignoring them"),
+                              REBASE_PRESERVE_MERGES, PARSE_OPT_HIDDEN),
                 OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
                 OPT_BOOL('k', "keep-empty", &options.keep_empty,
                          N_("preserve empty commits during rebase")),
diff --git a/builtin/repack.c b/builtin/repack.c
index 094c2f8ea4..0781763b06 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -233,6 +233,13 @@ static void repack_promisor_objects(const struct pack_objects_args *args,
                 /*
                  * pack-objects creates the .pack and .idx files, but not the
                  * .promisor file. Create the .promisor file, which is empty.
+                 *
+                 * NEEDSWORK: fetch-pack sometimes generates non-empty
+                 * .promisor files containing the ref names and associated
+                 * hashes at the point of generation of the corresponding
+                 * packfile, but this would not preserve their contents. Maybe
+                 * concatenate the contents of all .promisor files instead of
+                 * just creating a new empty file.
                  */
                 promisor_name = mkpathdup("%s-%s.promisor", packtmp,
                                           line.buf);
@@ -562,7 +569,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
         remove_temporary_files();
 
         if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0))
-                write_midx_file(get_object_directory());
+                write_midx_file(get_object_directory(), 0);
 
         string_list_clear(&names, 0);
         string_list_clear(&rollback, 0);
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 308c67e4fc..85ce2095bf 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -919,6 +919,17 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                 show_datestring("--min-age=", arg);
                                 continue;
                         }
+                        if (opt_with_value(arg, "--show-object-format", &arg)) {
+                                const char *val = arg ? arg : "storage";
+
+                                if (strcmp(val, "storage") &&
+                                    strcmp(val, "input") &&
+                                    strcmp(val, "output"))
+                                        die("unknown mode for --show-object-format: %s",
+                                            arg);
+                                puts(the_hash_algo->name);
+                                continue;
+                        }
                         if (show_flag(arg) && verify)
                                 die_no_single_rev(quiet);
                         continue;
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
new file mode 100644
index 0000000000..76f65d8edd
--- /dev/null
+++ b/builtin/sparse-checkout.c
@@ -0,0 +1,488 @@
+#include "builtin.h"
+#include "config.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "pathspec.h"
+#include "repository.h"
+#include "run-command.h"
+#include "strbuf.h"
+#include "string-list.h"
+#include "cache.h"
+#include "cache-tree.h"
+#include "lockfile.h"
+#include "resolve-undo.h"
+#include "unpack-trees.h"
+
+static char const * const builtin_sparse_checkout_usage[] = {
+        N_("git sparse-checkout (init|list|set|disable) <options>"),
+        NULL
+};
+
+static char *get_sparse_checkout_filename(void)
+{
+        return git_pathdup("info/sparse-checkout");
+}
+
+static void write_patterns_to_file(FILE *fp, struct pattern_list *pl)
+{
+        int i;
+
+        for (i = 0; i < pl->nr; i++) {
+                struct path_pattern *p = pl->patterns[i];
+
+                if (p->flags & PATTERN_FLAG_NEGATIVE)
+                        fprintf(fp, "!");
+
+                fprintf(fp, "%s", p->pattern);
+
+                if (p->flags & PATTERN_FLAG_MUSTBEDIR)
+                        fprintf(fp, "/");
+
+                fprintf(fp, "\n");
+        }
+}
+
+static int sparse_checkout_list(int argc, const char **argv)
+{
+        struct pattern_list pl;
+        char *sparse_filename;
+        int res;
+
+        memset(&pl, 0, sizeof(pl));
+
+        sparse_filename = get_sparse_checkout_filename();
+        res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL);
+        free(sparse_filename);
+
+        if (res < 0) {
+                warning(_("this worktree is not sparse (sparse-checkout file may not exist)"));
+                return 0;
+        }
+
+        write_patterns_to_file(stdout, &pl);
+        clear_pattern_list(&pl);
+
+        return 0;
+}
+
+static int update_working_directory(struct pattern_list *pl)
+{
+        int result = 0;
+        struct unpack_trees_options o;
+        struct lock_file lock_file = LOCK_INIT;
+        struct object_id oid;
+        struct tree *tree;
+        struct tree_desc t;
+        struct repository *r = the_repository;
+
+        if (repo_read_index_unmerged(r))
+                die(_("You need to resolve your current index first"));
+
+        if (get_oid("HEAD", &oid))
+                return 0;
+
+        tree = parse_tree_indirect(&oid);
+        parse_tree(tree);
+        init_tree_desc(&t, tree->buffer, tree->size);
+
+        memset(&o, 0, sizeof(o));
+        o.verbose_update = isatty(2);
+        o.merge = 1;
+        o.update = 1;
+        o.fn = oneway_merge;
+        o.head_idx = -1;
+        o.src_index = r->index;
+        o.dst_index = r->index;
+        o.skip_sparse_checkout = 0;
+        o.pl = pl;
+        o.keep_pattern_list = !!pl;
+
+        resolve_undo_clear_index(r->index);
+        setup_work_tree();
+
+        cache_tree_free(&r->index->cache_tree);
+
+        repo_hold_locked_index(r, &lock_file, LOCK_DIE_ON_ERROR);
+
+        core_apply_sparse_checkout = 1;
+        result = unpack_trees(1, &t, &o);
+
+        if (!result) {
+                prime_cache_tree(r, r->index, tree);
+                write_locked_index(r->index, &lock_file, COMMIT_LOCK);
+        } else
+                rollback_lock_file(&lock_file);
+
+        return result;
+}
+
+enum sparse_checkout_mode {
+        MODE_NO_PATTERNS = 0,
+        MODE_ALL_PATTERNS = 1,
+        MODE_CONE_PATTERNS = 2,
+};
+
+static int sc_set_config(enum sparse_checkout_mode mode)
+{
+        struct argv_array argv = ARGV_ARRAY_INIT;
+        struct argv_array cone_argv = ARGV_ARRAY_INIT;
+
+        if (git_config_set_gently("extensions.worktreeConfig", "true")) {
+                error(_("failed to set extensions.worktreeConfig setting"));
+                return 1;
+        }
+
+        argv_array_pushl(&argv, "config", "--worktree", "core.sparseCheckout", NULL);
+
+        if (mode)
+                argv_array_pushl(&argv, "true", NULL);
+        else
+                argv_array_pushl(&argv, "false", NULL);
+
+        if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
+                error(_("failed to enable core.sparseCheckout"));
+                return 1;
+        }
+
+        argv_array_pushl(&cone_argv, "config", "--worktree",
+                         "core.sparseCheckoutCone", NULL);
+
+        if (mode == MODE_CONE_PATTERNS)
+                argv_array_push(&cone_argv, "true");
+        else
+                argv_array_push(&cone_argv, "false");
+
+        if (run_command_v_opt(cone_argv.argv, RUN_GIT_CMD)) {
+                error(_("failed to enable core.sparseCheckoutCone"));
+                return 1;
+        }
+
+        return 0;
+}
+
+static char const * const builtin_sparse_checkout_init_usage[] = {
+        N_("git sparse-checkout init [--cone]"),
+        NULL
+};
+
+static struct sparse_checkout_init_opts {
+        int cone_mode;
+} init_opts;
+
+static int sparse_checkout_init(int argc, const char **argv)
+{
+        struct pattern_list pl;
+        char *sparse_filename;
+        FILE *fp;
+        int res;
+        struct object_id oid;
+        int mode;
+
+        static struct option builtin_sparse_checkout_init_options[] = {
+                OPT_BOOL(0, "cone", &init_opts.cone_mode,
+                         N_("initialize the sparse-checkout in cone mode")),
+                OPT_END(),
+        };
+
+        argc = parse_options(argc, argv, NULL,
+                             builtin_sparse_checkout_init_options,
+                             builtin_sparse_checkout_init_usage, 0);
+
+        if (init_opts.cone_mode) {
+                mode = MODE_CONE_PATTERNS;
+                core_sparse_checkout_cone = 1;
+        } else
+                mode = MODE_ALL_PATTERNS;
+
+        if (sc_set_config(mode))
+                return 1;
+
+        memset(&pl, 0, sizeof(pl));
+
+        sparse_filename = get_sparse_checkout_filename();
+        res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL);
+
+        /* If we already have a sparse-checkout file, use it. */
+        if (res >= 0) {
+                free(sparse_filename);
+                goto reset_dir;
+        }
+
+        /* initial mode: all blobs at root */
+        fp = xfopen(sparse_filename, "w");
+        free(sparse_filename);
+        fprintf(fp, "/*\n!/*/\n");
+        fclose(fp);
+
+        if (get_oid("HEAD", &oid)) {
+                /* assume we are in a fresh repo */
+                return 0;
+        }
+
+reset_dir:
+        core_apply_sparse_checkout = 1;
+        return update_working_directory(NULL);
+}
+
+static void insert_recursive_pattern(struct pattern_list *pl, struct strbuf *path)
+{
+        struct pattern_entry *e = xmalloc(sizeof(*e));
+        e->patternlen = path->len;
+        e->pattern = strbuf_detach(path, NULL);
+        hashmap_entry_init(&e->ent, memhash(e->pattern, e->patternlen));
+
+        hashmap_add(&pl->recursive_hashmap, &e->ent);
+
+        while (e->patternlen) {
+                char *slash = strrchr(e->pattern, '/');
+                char *oldpattern = e->pattern;
+                size_t newlen;
+
+                if (slash == e->pattern)
+                        break;
+
+                newlen = slash - e->pattern;
+                e = xmalloc(sizeof(struct pattern_entry));
+                e->patternlen = newlen;
+                e->pattern = xstrndup(oldpattern, newlen);
+                hashmap_entry_init(&e->ent, memhash(e->pattern, e->patternlen));
+
+                if (!hashmap_get_entry(&pl->parent_hashmap, e, ent, NULL))
+                        hashmap_add(&pl->parent_hashmap, &e->ent);
+        }
+}
+
+static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
+{
+        int i;
+        struct pattern_entry *pe;
+        struct hashmap_iter iter;
+        struct string_list sl = STRING_LIST_INIT_DUP;
+        struct strbuf parent_pattern = STRBUF_INIT;
+
+        hashmap_for_each_entry(&pl->parent_hashmap, &iter, pe, ent) {
+                if (hashmap_get_entry(&pl->recursive_hashmap, pe, ent, NULL))
+                        continue;
+
+                if (!hashmap_contains_parent(&pl->recursive_hashmap,
+                                             pe->pattern,
+                                             &parent_pattern))
+                        string_list_insert(&sl, pe->pattern);
+        }
+
+        string_list_sort(&sl);
+        string_list_remove_duplicates(&sl, 0);
+
+        fprintf(fp, "/*\n!/*/\n");
+
+        for (i = 0; i < sl.nr; i++) {
+                char *pattern = sl.items[i].string;
+
+                if (strlen(pattern))
+                        fprintf(fp, "%s/\n!%s/*/\n", pattern, pattern);
+        }
+
+        string_list_clear(&sl, 0);
+
+        hashmap_for_each_entry(&pl->recursive_hashmap, &iter, pe, ent) {
+                if (!hashmap_contains_parent(&pl->recursive_hashmap,
+                                             pe->pattern,
+                                             &parent_pattern))
+                        string_list_insert(&sl, pe->pattern);
+        }
+
+        strbuf_release(&parent_pattern);
+
+        string_list_sort(&sl);
+        string_list_remove_duplicates(&sl, 0);
+
+        for (i = 0; i < sl.nr; i++) {
+                char *pattern = sl.items[i].string;
+                fprintf(fp, "%s/\n", pattern);
+        }
+}
+
+static int write_patterns_and_update(struct pattern_list *pl)
+{
+        char *sparse_filename;
+        FILE *fp;
+        int fd;
+        struct lock_file lk = LOCK_INIT;
+        int result;
+
+        result = update_working_directory(pl);
+
+        sparse_filename = get_sparse_checkout_filename();
+        fd = hold_lock_file_for_update(&lk, sparse_filename,
+                                      LOCK_DIE_ON_ERROR);
+
+        result = update_working_directory(pl);
+        if (result) {
+                rollback_lock_file(&lk);
+                free(sparse_filename);
+                clear_pattern_list(pl);
+                update_working_directory(NULL);
+                return result;
+        }
+
+        fp = xfdopen(fd, "w");
+
+        if (core_sparse_checkout_cone)
+                write_cone_to_file(fp, pl);
+        else
+                write_patterns_to_file(fp, pl);
+
+        fflush(fp);
+        commit_lock_file(&lk);
+
+        free(sparse_filename);
+        clear_pattern_list(pl);
+
+        return 0;
+}
+
+static void strbuf_to_cone_pattern(struct strbuf *line, struct pattern_list *pl)
+{
+        strbuf_trim(line);
+
+        strbuf_trim_trailing_dir_sep(line);
+
+        if (!line->len)
+                return;
+
+        if (line->buf[0] != '/')
+                strbuf_insert(line, 0, "/", 1);
+
+        insert_recursive_pattern(pl, line);
+}
+
+static char const * const builtin_sparse_checkout_set_usage[] = {
+        N_("git sparse-checkout set [--stdin|<patterns>]"),
+        NULL
+};
+
+static struct sparse_checkout_set_opts {
+        int use_stdin;
+} set_opts;
+
+static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
+{
+        static const char *empty_base = "";
+        int i;
+        struct pattern_list pl;
+        int result;
+        int set_config = 0;
+
+        static struct option builtin_sparse_checkout_set_options[] = {
+                OPT_BOOL(0, "stdin", &set_opts.use_stdin,
+                         N_("read patterns from standard in")),
+                OPT_END(),
+        };
+
+        memset(&pl, 0, sizeof(pl));
+
+        argc = parse_options(argc, argv, prefix,
+                             builtin_sparse_checkout_set_options,
+                             builtin_sparse_checkout_set_usage,
+                             PARSE_OPT_KEEP_UNKNOWN);
+
+        if (core_sparse_checkout_cone) {
+                struct strbuf line = STRBUF_INIT;
+                hashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);
+                hashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);
+                pl.use_cone_patterns = 1;
+
+                if (set_opts.use_stdin) {
+                        while (!strbuf_getline(&line, stdin))
+                                strbuf_to_cone_pattern(&line, &pl);
+                } else {
+                        for (i = 0; i < argc; i++) {
+                                strbuf_setlen(&line, 0);
+                                strbuf_addstr(&line, argv[i]);
+                                strbuf_to_cone_pattern(&line, &pl);
+                        }
+                }
+        } else {
+                if (set_opts.use_stdin) {
+                        struct strbuf line = STRBUF_INIT;
+
+                        while (!strbuf_getline(&line, stdin)) {
+                                size_t len;
+                                char *buf = strbuf_detach(&line, &len);
+                                add_pattern(buf, empty_base, 0, &pl, 0);
+                        }
+                } else {
+                        for (i = 0; i < argc; i++)
+                                add_pattern(argv[i], empty_base, 0, &pl, 0);
+                }
+        }
+
+        if (!core_apply_sparse_checkout) {
+                sc_set_config(MODE_ALL_PATTERNS);
+                core_apply_sparse_checkout = 1;
+                set_config = 1;
+        }
+
+        result = write_patterns_and_update(&pl);
+
+        if (result && set_config)
+                sc_set_config(MODE_NO_PATTERNS);
+
+        clear_pattern_list(&pl);
+        return result;
+}
+
+static int sparse_checkout_disable(int argc, const char **argv)
+{
+        char *sparse_filename;
+        FILE *fp;
+
+        if (sc_set_config(MODE_ALL_PATTERNS))
+                die(_("failed to change config"));
+
+        sparse_filename = get_sparse_checkout_filename();
+        fp = xfopen(sparse_filename, "w");
+        fprintf(fp, "/*\n");
+        fclose(fp);
+
+        core_apply_sparse_checkout = 1;
+        if (update_working_directory(NULL))
+                die(_("error while refreshing working directory"));
+
+        unlink(sparse_filename);
+        free(sparse_filename);
+
+        return sc_set_config(MODE_NO_PATTERNS);
+}
+
+int cmd_sparse_checkout(int argc, const char **argv, const char *prefix)
+{
+        static struct option builtin_sparse_checkout_options[] = {
+                OPT_END(),
+        };
+
+        if (argc == 2 && !strcmp(argv[1], "-h"))
+                usage_with_options(builtin_sparse_checkout_usage,
+                                   builtin_sparse_checkout_options);
+
+        argc = parse_options(argc, argv, prefix,
+                             builtin_sparse_checkout_options,
+                             builtin_sparse_checkout_usage,
+                             PARSE_OPT_STOP_AT_NON_OPTION);
+
+        git_config(git_default_config, NULL);
+
+        if (argc > 0) {
+                if (!strcmp(argv[0], "list"))
+                        return sparse_checkout_list(argc, argv);
+                if (!strcmp(argv[0], "init"))
+                        return sparse_checkout_init(argc, argv);
+                if (!strcmp(argv[0], "set"))
+                        return sparse_checkout_set(argc, argv, prefix);
+                if (!strcmp(argv[0], "disable"))
+                        return sparse_checkout_disable(argc, argv);
+        }
+
+        usage_with_options(builtin_sparse_checkout_usage,
+                           builtin_sparse_checkout_options);
+}
diff --git a/builtin/stash.c b/builtin/stash.c
index 4fc44b35e4..4ad3adf4ba 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -427,6 +427,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
                                 return error(_("could not save index tree"));
 
                         reset_head();
+                        discard_cache();
+                        read_cache();
                 }
         }
 
@@ -481,13 +483,12 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
                 if (ret)
                         return -1;
 
+                /* read back the result of update_index() back from the disk */
                 discard_cache();
+                read_cache();
         }
 
-        if (quiet) {
-                if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
-                        warning("could not refresh index");
-        } else {
+        if (!quiet) {
                 struct child_process cp = CHILD_PROCESS_INIT;
 
                 /*
@@ -1086,8 +1087,9 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
         }
 
         cp_upd_index.git_cmd = 1;
-        argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
-                         "--remove", "--stdin", NULL);
+        argv_array_pushl(&cp_upd_index.args, "update-index",
+                         "--ignore-skip-worktree-entries",
+                         "-z", "--add", "--remove", "--stdin", NULL);
         argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
                          stash_index_path.buf);
 
@@ -1390,7 +1392,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                         struct child_process cp = CHILD_PROCESS_INIT;
                         cp.git_cmd = 1;
                         argv_array_pushl(&cp.args, "reset", "--hard", "-q",
-                                         NULL);
+                                         "--no-recurse-submodules", NULL);
                         if (run_command(&cp)) {
                                 ret = -1;
                                 goto done;
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 49302d98c5..d527b8f106 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -35,6 +35,7 @@ static int verbose;
 static int mark_valid_only;
 static int mark_skip_worktree_only;
 static int mark_fsmonitor_only;
+static int ignore_skip_worktree_entries;
 #define MARK_FLAG 1
 #define UNMARK_FLAG 2
 static struct strbuf mtime_dir = STRBUF_INIT;
@@ -381,7 +382,8 @@ static int process_path(const char *path, struct stat *st, int stat_errno)
                  * so updating it does not make sense.
                  * On the other hand, removing it from index should work
                  */
-                if (allow_remove && remove_file_from_cache(path))
+                if (!ignore_skip_worktree_entries && allow_remove &&
+                    remove_file_from_cache(path))
                         return error("%s: cannot remove from the index", path);
                 return 0;
         }
@@ -1014,6 +1016,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                 {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL,
                         N_("clear skip-worktree bit"),
                         PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
+                OPT_BOOL(0, "ignore-skip-worktree-entries", &ignore_skip_worktree_entries,
+                         N_("do not touch index-only entries")),
                 OPT_SET_INT(0, "info-only", &info_only,
                         N_("add to index only; do not add content to object database"), 1),
                 OPT_SET_INT(0, "force-remove", &force_remove,
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 4de44f579a..d6bc5263f1 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -376,7 +376,7 @@ static int add_worktree(const char *path, const char *refname,
         if (opts->checkout) {
                 cp.argv = NULL;
                 argv_array_clear(&cp.args);
-                argv_array_pushl(&cp.args, "reset", "--hard", NULL);
+                argv_array_pushl(&cp.args, "reset", "--hard", "--no-recurse-submodules", NULL);
                 if (opts->quiet)
                         argv_array_push(&cp.args, "--quiet");
                 cp.env = child_env.argv;
diff --git a/bundle.c b/bundle.c
index a85ed3f7bc..99439e07a1 100644
--- a/bundle.c
+++ b/bundle.c
@@ -249,15 +249,16 @@ out:
 
 
 /* Write the pack data to bundle_fd */
-static int write_pack_data(int bundle_fd, struct rev_info *revs)
+static int write_pack_data(int bundle_fd, struct rev_info *revs, struct argv_array *pack_options)
 {
         struct child_process pack_objects = CHILD_PROCESS_INIT;
         int i;
 
         argv_array_pushl(&pack_objects.args,
-                         "pack-objects", "--all-progress-implied",
+                         "pack-objects",
                          "--stdout", "--thin", "--delta-base-offset",
                          NULL);
+        argv_array_pushv(&pack_objects.args, pack_options->argv);
         pack_objects.in = -1;
         pack_objects.out = bundle_fd;
         pack_objects.git_cmd = 1;
@@ -428,7 +429,7 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
 }
 
 int create_bundle(struct repository *r, const char *path,
-                  int argc, const char **argv)
+                  int argc, const char **argv, struct argv_array *pack_options)
 {
         struct lock_file lock = LOCK_INIT;
         int bundle_fd = -1;
@@ -470,7 +471,7 @@ int create_bundle(struct repository *r, const char *path,
                 goto err;
 
         /* write pack */
-        if (write_pack_data(bundle_fd, &revs))
+        if (write_pack_data(bundle_fd, &revs, pack_options))
                 goto err;
 
         if (!bundle_to_stdout) {
diff --git a/bundle.h b/bundle.h
index 37c37d7f65..ceab0c7475 100644
--- a/bundle.h
+++ b/bundle.h
@@ -1,6 +1,7 @@
 #ifndef BUNDLE_H
 #define BUNDLE_H
 
+#include "argv-array.h"
 #include "cache.h"
 
 struct ref_list {
@@ -19,7 +20,7 @@ struct bundle_header {
 int is_bundle(const char *path, int quiet);
 int read_bundle_header(const char *path, struct bundle_header *header);
 int create_bundle(struct repository *r, const char *path,
-                  int argc, const char **argv);
+                  int argc, const char **argv, struct argv_array *pack_options);
 int verify_bundle(struct repository *r, struct bundle_header *header, int verbose);
 #define BUNDLE_VERBOSE 1
 int unbundle(struct repository *r, struct bundle_header *header,
diff --git a/cache-tree.c b/cache-tree.c
index 62edee45e4..1bd1b23d38 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -609,11 +609,66 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat
         return it;
 }
 
+static int write_index_as_tree_internal(struct object_id *oid,
+                                        struct index_state *index_state,
+                                        int cache_tree_valid,
+                                        int flags,
+                                        const char *prefix)
+{
+        if (flags & WRITE_TREE_IGNORE_CACHE_TREE) {
+                cache_tree_free(&index_state->cache_tree);
+                cache_tree_valid = 0;
+        }
+
+        if (!index_state->cache_tree)
+                index_state->cache_tree = cache_tree();
+
+        if (!cache_tree_valid && cache_tree_update(index_state, flags) < 0)
+                return WRITE_TREE_UNMERGED_INDEX;
+
+        if (prefix) {
+                struct cache_tree *subtree;
+                subtree = cache_tree_find(index_state->cache_tree, prefix);
+                if (!subtree)
+                        return WRITE_TREE_PREFIX_ERROR;
+                oidcpy(oid, &subtree->oid);
+        }
+        else
+                oidcpy(oid, &index_state->cache_tree->oid);
+
+        return 0;
+}
+
+struct tree* write_in_core_index_as_tree(struct repository *repo) {
+        struct object_id o;
+        int was_valid, ret;
+
+        struct index_state *index_state        = repo->index;
+        was_valid = index_state->cache_tree &&
+                    cache_tree_fully_valid(index_state->cache_tree);
+
+        ret = write_index_as_tree_internal(&o, index_state, was_valid, 0, NULL);
+        if (ret == WRITE_TREE_UNMERGED_INDEX) {
+                int i;
+                fprintf(stderr, "BUG: There are unmerged index entries:\n");
+                for (i = 0; i < index_state->cache_nr; i++) {
+                        const struct cache_entry *ce = index_state->cache[i];
+                        if (ce_stage(ce))
+                                fprintf(stderr, "BUG: %d %.*s\n", ce_stage(ce),
+                                        (int)ce_namelen(ce), ce->name);
+                }
+                BUG("unmerged index entries when writing inmemory index");
+        }
+
+        return lookup_tree(repo, &index_state->cache_tree->oid);
+}
+
+
 int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
 {
         int entries, was_valid;
         struct lock_file lock_file = LOCK_INIT;
-        int ret = 0;
+        int ret;
 
         hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);
 
@@ -622,18 +677,14 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
                 ret = WRITE_TREE_UNREADABLE_INDEX;
                 goto out;
         }
-        if (flags & WRITE_TREE_IGNORE_CACHE_TREE)
-                cache_tree_free(&index_state->cache_tree);
 
-        if (!index_state->cache_tree)
-                index_state->cache_tree = cache_tree();
+        was_valid = !(flags & WRITE_TREE_IGNORE_CACHE_TREE) &&
+                    index_state->cache_tree &&
+                    cache_tree_fully_valid(index_state->cache_tree);
 
-        was_valid = cache_tree_fully_valid(index_state->cache_tree);
-        if (!was_valid) {
-                if (cache_tree_update(index_state, flags) < 0) {
-                        ret = WRITE_TREE_UNMERGED_INDEX;
-                        goto out;
-                }
+        ret = write_index_as_tree_internal(oid, index_state, was_valid, flags,
+                                           prefix);
+        if (!ret && !was_valid) {
                 write_locked_index(index_state, &lock_file, COMMIT_LOCK);
                 /* Not being able to write is fine -- we are only interested
                  * in updating the cache-tree part, and if the next caller
@@ -643,18 +694,6 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
                  */
         }
 
-        if (prefix) {
-                struct cache_tree *subtree;
-                subtree = cache_tree_find(index_state->cache_tree, prefix);
-                if (!subtree) {
-                        ret = WRITE_TREE_PREFIX_ERROR;
-                        goto out;
-                }
-                oidcpy(oid, &subtree->oid);
-        }
-        else
-                oidcpy(oid, &index_state->cache_tree->oid);
-
 out:
         rollback_lock_file(&lock_file);
         return ret;
diff --git a/cache-tree.h b/cache-tree.h
index 757bbc48bc..639bfa5340 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -34,7 +34,7 @@ int cache_tree_fully_valid(struct cache_tree *);
 int cache_tree_update(struct index_state *, int);
 void cache_tree_verify(struct repository *, struct index_state *);
 
-/* bitmasks to write_cache_as_tree flags */
+/* bitmasks to write_index_as_tree flags */
 #define WRITE_TREE_MISSING_OK 1
 #define WRITE_TREE_IGNORE_CACHE_TREE 2
 #define WRITE_TREE_DRY_RUN 4
@@ -46,6 +46,7 @@ void cache_tree_verify(struct repository *, struct index_state *);
 #define WRITE_TREE_UNMERGED_INDEX (-2)
 #define WRITE_TREE_PREFIX_ERROR (-3)
 
+struct tree* write_in_core_index_as_tree(struct repository *repo);
 int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
 void prime_cache_tree(struct repository *, struct index_state *, struct tree *);
 
diff --git a/cache.h b/cache.h
index 76f38f7df0..aaeb0cd718 100644
--- a/cache.h
+++ b/cache.h
@@ -304,6 +304,7 @@ static inline unsigned int canon_mode(unsigned int mode)
 
 struct split_index;
 struct untracked_cache;
+struct progress;
 
 struct index_state {
         struct cache_entry **cache;
@@ -326,6 +327,7 @@ struct index_state {
         uint64_t fsmonitor_last_update;
         struct ewah_bitmap *fsmonitor_dirty;
         struct mem_pool *ce_mem_pool;
+        struct progress *progress;
 };
 
 /* Name hashing */
@@ -748,6 +750,19 @@ struct cache_entry *index_file_exists(struct index_state *istate, const char *na
  */
 int index_name_pos(const struct index_state *, const char *name, int namelen);
 
+/*
+ * Some functions return the negative complement of an insert position when a
+ * precise match was not found but a position was found where the entry would
+ * need to be inserted. This helper protects that logic from any integer
+ * underflow.
+ */
+static inline int index_pos_to_insert_pos(uintmax_t pos)
+{
+        if (pos > INT_MAX)
+                die("overflow: -1 - %"PRIuMAX, pos);
+        return -1 - (int)pos;
+}
+
 #define ADD_CACHE_OK_TO_ADD 1                /* Ok to add */
 #define ADD_CACHE_OK_TO_REPLACE 2        /* Ok to replace file/directory */
 #define ADD_CACHE_SKIP_DFCHECK 4        /* Ok to skip DF conflict checks */
@@ -905,12 +920,14 @@ extern char *git_replace_ref_base;
 
 extern int fsync_object_files;
 extern int core_preload_index;
-extern int core_apply_sparse_checkout;
 extern int precomposed_unicode;
 extern int protect_hfs;
 extern int protect_ntfs;
 extern const char *core_fsmonitor;
 
+int core_apply_sparse_checkout;
+int core_sparse_checkout_cone;
+
 /*
  * Include broken refs in all ref iterations, which will
  * generally choke dangerous operations rather than letting
@@ -1438,7 +1455,8 @@ int get_oid_hex(const char *hex, struct object_id *sha1);
 int hex_to_bytes(unsigned char *binary, const char *hex, size_t len);
 
 /*
- * Convert a binary hash to its hex equivalent. The `_r` variant is reentrant,
+ * Convert a binary hash in "unsigned char []" or an object name in
+ * "struct object_id *" to its hex equivalent. The `_r` variant is reentrant,
  * and writes the NUL-terminated output to the buffer `out`, which must be at
  * least `GIT_MAX_HEXSZ + 1` bytes, and returns a pointer to out for
  * convenience.
@@ -1446,13 +1464,12 @@ int hex_to_bytes(unsigned char *binary, const char *hex, size_t len);
  * The non-`_r` variant returns a static buffer, but uses a ring of 4
  * buffers, making it safe to make multiple calls for a single statement, like:
  *
- *   printf("%s -> %s", sha1_to_hex(one), sha1_to_hex(two));
+ *   printf("%s -> %s", hash_to_hex(one), hash_to_hex(two));
+ *   printf("%s -> %s", oid_to_hex(one), oid_to_hex(two));
  */
 char *hash_to_hex_algop_r(char *buffer, const unsigned char *hash, const struct git_hash_algo *);
-char *sha1_to_hex_r(char *out, const unsigned char *sha1);
 char *oid_to_hex_r(char *out, const struct object_id *oid);
 char *hash_to_hex_algop(const unsigned char *hash, const struct git_hash_algo *);        /* static buffer result! */
-char *sha1_to_hex(const unsigned char *sha1);                                                /* same static buffer */
 char *hash_to_hex(const unsigned char *hash);                                                /* same static buffer */
 char *oid_to_hex(const struct object_id *oid);                                                /* same static buffer */
 
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index 85a9d6b15c..4e64a19112 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -40,9 +40,15 @@ osx-clang|osx-gcc)
         test -z "$BREW_INSTALL_PACKAGES" ||
         brew install $BREW_INSTALL_PACKAGES
         brew link --force gettext
+        brew cask install perforce || {
+                # Update the definitions and try again
+                git -C "$(brew --repository)"/Library/Taps/homebrew/homebrew-cask pull &&
+                brew cask install perforce
+        } ||
         brew install caskroom/cask/perforce
         case "$jobname" in
         osx-gcc)
+                brew link gcc ||
                 brew link gcc@8
                 ;;
         esac
diff --git a/column.c b/column.c
index 7a17c14b82..4a38eed322 100644
--- a/column.c
+++ b/column.c
@@ -23,18 +23,7 @@ struct column_data {
 /* return length of 's' in letters, ANSI escapes stripped */
 static int item_length(const char *s)
 {
-        int len, i = 0;
-        struct strbuf str = STRBUF_INIT;
-
-        strbuf_addstr(&str, s);
-        while ((s = strstr(str.buf + i, "\033[")) != NULL) {
-                int len = strspn(s + 2, "0123456789;");
-                i = s - str.buf;
-                strbuf_remove(&str, i, len + 3); /* \033[<len><func char> */
-        }
-        len = utf8_strwidth(str.buf);
-        strbuf_release(&str);
-        return len;
+        return utf8_strnwidth(s, -1, 1);
 }
 
 /*
diff --git a/command-list.txt b/command-list.txt
index a9ac72bef4..2087894655 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -166,6 +166,7 @@ git-show-index                          plumbinginterrogators
 git-show-ref                            plumbinginterrogators
 git-sh-i18n                             purehelpers
 git-sh-setup                            purehelpers
+git-sparse-checkout                     mainporcelain           worktree
 git-stash                               mainporcelain
 git-stage                                                               complete
 git-status                              mainporcelain           info
@@ -203,6 +204,7 @@ gitmodules                              guide
 gitnamespaces                           guide
 gitrepository-layout                    guide
 gitrevisions                            guide
+gitsubmodules                           guide
 gittutorial-2                           guide
 gittutorial                             guide
 gitworkflows                            guide
diff --git a/commit-graph.c b/commit-graph.c
index fc4a43b8d6..e771394aff 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -41,6 +41,9 @@
 #define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * GRAPH_CHUNKLOOKUP_WIDTH \
                         + GRAPH_FANOUT_SIZE + the_hash_algo->rawsz)
 
+/* Remember to update object flag allocation in object.h */
+#define REACHABLE       (1u<<15)
+
 char *get_commit_graph_filename(const char *obj_dir)
 {
         char *filename = xstrfmt("%s/info/commit-graph", obj_dir);
@@ -461,7 +464,7 @@ static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
 /*
  * Return 1 if commit_graph is non-NULL, and 0 otherwise.
  *
- * On the first invocation, this function attemps to load the commit
+ * On the first invocation, this function attempts to load the commit
  * graph if the_repository is configured to have one.
  */
 static int prepare_commit_graph(struct repository *r)
@@ -855,9 +858,6 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
                         die(_("unable to parse commit %s"),
                                 oid_to_hex(&(*list)->object.oid));
                 tree = get_commit_tree_oid(*list);
-                if (!tree)
-                        die(_("unable to get tree for %s"),
-                                oid_to_hex(&(*list)->object.oid));
                 hashwrite(f, tree->hash, hash_len);
 
                 parent = (*list)->parents;
@@ -1030,11 +1030,11 @@ static void add_missing_parents(struct write_commit_graph_context *ctx, struct c
 {
         struct commit_list *parent;
         for (parent = commit->parents; parent; parent = parent->next) {
-                if (!(parent->item->object.flags & UNINTERESTING)) {
+                if (!(parent->item->object.flags & REACHABLE)) {
                         ALLOC_GROW(ctx->oids.list, ctx->oids.nr + 1, ctx->oids.alloc);
                         oidcpy(&ctx->oids.list[ctx->oids.nr], &(parent->item->object.oid));
                         ctx->oids.nr++;
-                        parent->item->object.flags |= UNINTERESTING;
+                        parent->item->object.flags |= REACHABLE;
                 }
         }
 }
@@ -1052,7 +1052,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
                 display_progress(ctx->progress, i + 1);
                 commit = lookup_commit(ctx->r, &ctx->oids.list[i]);
                 if (commit)
-                        commit->object.flags |= UNINTERESTING;
+                        commit->object.flags |= REACHABLE;
         }
         stop_progress(&ctx->progress);
 
@@ -1089,7 +1089,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
                 commit = lookup_commit(ctx->r, &ctx->oids.list[i]);
 
                 if (commit)
-                        commit->object.flags &= ~UNINTERESTING;
+                        commit->object.flags &= ~REACHABLE;
         }
         stop_progress(&ctx->progress);
 }
@@ -1100,7 +1100,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
         struct commit_list *list = NULL;
 
         if (ctx->report_progress)
-                ctx->progress = start_progress(
+                ctx->progress = start_delayed_progress(
                                         _("Computing commit graph generation numbers"),
                                         ctx->commits.nr);
         for (i = 0; i < ctx->commits.nr; i++) {
diff --git a/commit-reach.c b/commit-reach.c
index 3ea174788a..4ca7e706a1 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -10,7 +10,6 @@
 #include "commit-reach.h"
 
 /* Remember to update object flag allocation in object.h */
-#define REACHABLE       (1u<<15)
 #define PARENT1                (1u<<16)
 #define PARENT2                (1u<<17)
 #define STALE                (1u<<18)
diff --git a/commit.c b/commit.c
index 40890ae7ce..434ec030d6 100644
--- a/commit.c
+++ b/commit.c
@@ -19,6 +19,7 @@
 #include "advice.h"
 #include "refs.h"
 #include "commit-reach.h"
+#include "run-command.h"
 
 static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
 
@@ -401,10 +402,22 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
         struct commit_graft *graft;
         const int tree_entry_len = the_hash_algo->hexsz + 5;
         const int parent_entry_len = the_hash_algo->hexsz + 7;
+        struct tree *tree;
 
         if (item->object.parsed)
                 return 0;
-        item->object.parsed = 1;
+
+        if (item->parents) {
+                /*
+                 * Presumably this is leftover from an earlier failed parse;
+                 * clear it out in preparation for us re-parsing (we'll hit the
+                 * same error, but that's good, since it lets our caller know
+                 * the result cannot be trusted.
+                 */
+                free_commit_list(item->parents);
+                item->parents = NULL;
+        }
+
         tail += size;
         if (tail <= bufptr + tree_entry_len + 1 || memcmp(bufptr, "tree ", 5) ||
                         bufptr[tree_entry_len] != '\n')
@@ -412,7 +425,12 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
         if (get_oid_hex(bufptr + 5, &parent) < 0)
                 return error("bad tree pointer in commit %s",
                              oid_to_hex(&item->object.oid));
-        set_commit_tree(item, lookup_tree(r, &parent));
+        tree = lookup_tree(r, &parent);
+        if (!tree)
+                return error("bad tree pointer %s in commit %s",
+                             oid_to_hex(&parent),
+                             oid_to_hex(&item->object.oid));
+        set_commit_tree(item, tree);
         bufptr += tree_entry_len + 1; /* "tree " + "hex sha1" + "\n" */
         pptr = &item->parents;
 
@@ -432,8 +450,11 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
                 if (graft && (graft->nr_parent < 0 || grafts_replace_parents))
                         continue;
                 new_parent = lookup_commit(r, &parent);
-                if (new_parent)
-                        pptr = &commit_list_insert(new_parent, pptr)->next;
+                if (!new_parent)
+                        return error("bad parent %s in commit %s",
+                                     oid_to_hex(&parent),
+                                     oid_to_hex(&item->object.oid));
+                pptr = &commit_list_insert(new_parent, pptr)->next;
         }
         if (graft) {
                 int i;
@@ -442,7 +463,9 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
                         new_parent = lookup_commit(r,
                                                    &graft->parent[i]);
                         if (!new_parent)
-                                continue;
+                                return error("bad graft parent %s in commit %s",
+                                             oid_to_hex(&graft->parent[i]),
+                                             oid_to_hex(&item->object.oid));
                         pptr = &commit_list_insert(new_parent, pptr)->next;
                 }
         }
@@ -451,6 +474,7 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
         if (check_graph)
                 load_commit_graph_info(r, item);
 
+        item->object.parsed = 1;
         return 0;
 }
 
@@ -1581,3 +1605,26 @@ size_t ignore_non_trailer(const char *buf, size_t len)
         }
         return boc ? len - boc : len - cutoff;
 }
+
+int run_commit_hook(int editor_is_used, const char *index_file,
+                    const char *name, ...)
+{
+        struct argv_array hook_env = ARGV_ARRAY_INIT;
+        va_list args;
+        int ret;
+
+        argv_array_pushf(&hook_env, "GIT_INDEX_FILE=%s", index_file);
+
+        /*
+         * Let the hook know that no editor will be launched.
+         */
+        if (!editor_is_used)
+                argv_array_push(&hook_env, "GIT_EDITOR=:");
+
+        va_start(args, name);
+        ret = run_hook_ve(hook_env.argv,name, args);
+        va_end(args);
+        argv_array_clear(&hook_env);
+
+        return ret;
+}
diff --git a/commit.h b/commit.h
index f5295ca7f3..221cdaa34b 100644
--- a/commit.h
+++ b/commit.h
@@ -132,7 +132,7 @@ const void *repo_get_commit_buffer(struct repository *r,
 #endif
 
 /*
- * Tell the commit subsytem that we are done with a particular commit buffer.
+ * Tell the commit subsystem that we are done with a particular commit buffer.
  * The commit and buffer should be the input and return value, respectively,
  * from an earlier call to get_commit_buffer.  The buffer may or may not be
  * freed by this call; callers should not access the memory afterwards.
diff --git a/compat/mingw.c b/compat/mingw.c
index 06566c8c88..2f4654c968 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -363,6 +363,8 @@ static inline int needs_hiding(const char *path)
                         /* ignore trailing slashes */
                         if (*path)
                                 basename = path;
+                        else
+                                break;
                 }
 
         if (hide_dotfiles == HIDE_DOTFILES_TRUE)
@@ -1564,7 +1566,7 @@ static int try_shell_exec(const char *cmd, char *const *argv)
                 while (argv[argc]) argc++;
                 ALLOC_ARRAY(argv2, argc + 1);
                 argv2[0] = (char *)cmd;        /* full path to the script file */
-                memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
+                COPY_ARRAY(&argv2[1], &argv[1], argc);
                 exec_id = trace2_exec(prog, argv2);
                 pid = mingw_spawnv(prog, argv2, 1);
                 if (pid >= 0) {
@@ -1665,6 +1667,8 @@ char *mingw_getenv(const char *name)
         if (!w_key)
                 die("Out of memory, (tried to allocate %u wchar_t's)", len_key);
         xutftowcs(w_key, name, len_key);
+        /* GetEnvironmentVariableW() only sets the last error upon failure */
+        SetLastError(ERROR_SUCCESS);
         len_value = GetEnvironmentVariableW(w_key, w_value, ARRAY_SIZE(w_value));
         if (!len_value && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
                 free(w_key);
diff --git a/compat/mingw.h b/compat/mingw.h
index 9ad204c57c..1a46334399 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -558,7 +558,7 @@ int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
 
 /*
  * A critical section used in the implementation of the spawn
- * functions (mingw_spawnv[p]e()) and waitpid(). Intialised in
+ * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
  * the replacement main() macro below.
  */
 extern CRITICAL_SECTION pinfo_cs;
diff --git a/compat/nedmalloc/malloc.c.h b/compat/nedmalloc/malloc.c.h
index 9134349590..814845d4b3 100644
--- a/compat/nedmalloc/malloc.c.h
+++ b/compat/nedmalloc/malloc.c.h
@@ -1564,7 +1564,7 @@ static FORCEINLINE void* win32direct_mmap(size_t size) {
   return (ptr != 0)? ptr: MFAIL;
 }
 
-/* This function supports releasing coalesed segments */
+/* This function supports releasing coalesced segments */
 static FORCEINLINE int win32munmap(void* ptr, size_t size) {
   MEMORY_BASIC_INFORMATION minfo;
   char* cptr = (char*)ptr;
@@ -1655,7 +1655,7 @@ static FORCEINLINE int win32munmap(void* ptr, size_t size) {
     #define CALL_MREMAP(addr, osz, nsz, mv)     MFAIL
 #endif /* HAVE_MMAP && HAVE_MREMAP */
 
-/* mstate bit set if continguous morecore disabled or failed */
+/* mstate bit set if contiguous morecore disabled or failed */
 #define USE_NONCONTIGUOUS_BIT (4U)
 
 /* segment bit set in create_mspace_with_base */
@@ -2485,7 +2485,7 @@ typedef struct malloc_segment* msegmentptr;
 
   Trim support
     Fields holding the amount of unused topmost memory that should trigger
-    timming, and a counter to force periodic scanning to release unused
+    timing, and a counter to force periodic scanning to release unused
     non-topmost segments.
 
   Locking
diff --git a/compat/obstack.h b/compat/obstack.h
index ae36ed6a66..01e7c81840 100644
--- a/compat/obstack.h
+++ b/compat/obstack.h
@@ -79,7 +79,7 @@ change its address during its lifetime.
 When the chars burst over a chunk boundary, we allocate a larger
 chunk, and then copy the partly formed object from the end of the old
 chunk to the beginning of the new larger chunk.  We then carry on
-accreting characters to the end of the object as we normally would.
+accrediting characters to the end of the object as we normally would.
 
 A special macro is provided to add a single char at a time to a
 growing object.  This allows the use of register variables, which
diff --git a/compat/regex/regcomp.c b/compat/regex/regcomp.c
index c0d838834a..d1bc09e49b 100644
--- a/compat/regex/regcomp.c
+++ b/compat/regex/regcomp.c
@@ -3462,7 +3462,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
         /* This isn't a valid character.  */
         return REG_ECOLLATE;
 
-      /* Build single byte matcing table for this equivalence class.  */
+      /* Build single byte matching table for this equivalence class.  */
       char_buf[1] = (unsigned char) '\0';
       len = weights[idx1 & 0xffffff];
       for (ch = 0; ch < SBC_MAX; ++ch)
diff --git a/compat/regex/regex.h b/compat/regex/regex.h
index 4d81358a83..08a2609663 100644
--- a/compat/regex/regex.h
+++ b/compat/regex/regex.h
@@ -322,7 +322,7 @@ typedef enum
   /* POSIX regcomp return error codes.  (In the order listed in the
      standard.)  */
   REG_BADPAT,                /* Invalid pattern.  */
-  REG_ECOLLATE,                /* Inalid collating element.  */
+  REG_ECOLLATE,                /* Invalid collating element.  */
   REG_ECTYPE,                /* Invalid character class name.  */
   REG_EESCAPE,                /* Trailing backslash.  */
   REG_ESUBREG,                /* Invalid back reference.  */
diff --git a/compat/regex/regex_internal.c b/compat/regex/regex_internal.c
index 59bf151336..ec51cf3446 100644
--- a/compat/regex/regex_internal.c
+++ b/compat/regex/regex_internal.c
@@ -1616,7 +1616,7 @@ free_state (re_dfastate_t *state)
   re_free (state);
 }
 
-/* Create the new state which is independ of contexts.
+/* Create the new state which is independent of contexts.
    Return the new state if succeeded, otherwise return NULL.  */
 
 static re_dfastate_t *
diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c
index 1b5d89fd5e..49358ae475 100644
--- a/compat/regex/regexec.c
+++ b/compat/regex/regexec.c
@@ -2420,7 +2420,7 @@ find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
 /* From the node set CUR_NODES, pick up the nodes whose types are
    OP_OPEN_SUBEXP and which have corresponding back references in the regular
    expression. And register them to use them later for evaluating the
-   correspoding back references.  */
+   corresponding back references.  */
 
 static reg_errcode_t
 internal_function
@@ -3347,7 +3347,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
   dests_node = dests_alloc->dests_node;
   dests_ch = dests_alloc->dests_ch;
 
-  /* Initialize transiton table.  */
+  /* Initialize transition table.  */
   state->word_trtable = state->trtable = NULL;
 
   /* At first, group all nodes belonging to `state' into several
diff --git a/compat/vcbuild/find_vs_env.bat b/compat/vcbuild/find_vs_env.bat
index 40194dd230..b35d264c0e 100644
--- a/compat/vcbuild/find_vs_env.bat
+++ b/compat/vcbuild/find_vs_env.bat
@@ -18,7 +18,7 @@ REM and MAKE, we must blend these two different worlds.  This script
 REM attempts to do that.
 REM ================================================================
 REM This BAT file starts in a plain (non-developer) command prompt,
-REM searches for the "best" commmand prompt setup script, installs
+REM searches for the "best" command prompt setup script, installs
 REM it into the current CMD process, and exports the various MSVC
 REM environment variables for use by MAKE.
 REM
diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl
index c7b021bfac..ec95a3b2d0 100755
--- a/compat/vcbuild/scripts/clink.pl
+++ b/compat/vcbuild/scripts/clink.pl
@@ -68,8 +68,54 @@ while (@ARGV) {
         } elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
                 $arg =~ s/^-L/-LIBPATH:/;
                 push(@lflags, $arg);
-        } elsif ("$arg" =~ /^-R/) {
+        } elsif ("$arg" =~ /^-[Rl]/) {
                 # eat
+        } elsif ("$arg" eq "-Werror") {
+                push(@cflags, "-WX");
+        } elsif ("$arg" eq "-Wall") {
+                # cl.exe understands -Wall, but it is really overzealous
+                push(@cflags, "-W4");
+                # disable the "signed/unsigned mismatch" warnings; our source code violates that
+                push(@cflags, "-wd4018");
+                push(@cflags, "-wd4245");
+                push(@cflags, "-wd4389");
+                # disable the "unreferenced formal parameter" warning; our source code violates that
+                push(@cflags, "-wd4100");
+                # disable the "conditional expression is constant" warning; our source code violates that
+                push(@cflags, "-wd4127");
+                # disable the "const object should be initialized" warning; these warnings affect only objects that are `static`
+                push(@cflags, "-wd4132");
+                # disable the "function/data pointer conversion in expression" warning; our source code violates that
+                push(@cflags, "-wd4152");
+                # disable the "non-constant aggregate initializer" warning; our source code violates that
+                push(@cflags, "-wd4204");
+                # disable the "cannot be initialized using address of automatic variable" warning; our source code violates that
+                push(@cflags, "-wd4221");
+                # disable the "possible loss of data" warnings; our source code violates that
+                push(@cflags, "-wd4244");
+                push(@cflags, "-wd4267");
+                # disable the "array is too small to include a terminating null character" warning; we ab-use strings to initialize OIDs
+                push(@cflags, "-wd4295");
+                # disable the "'<<': result of 32-bit shift implicitly converted to 64 bits" warning; our source code violates that
+                push(@cflags, "-wd4334");
+                # disable the "declaration hides previous local declaration" warning; our source code violates that
+                push(@cflags, "-wd4456");
+                # disable the "declaration hides function parameter" warning; our source code violates that
+                push(@cflags, "-wd4457");
+                # disable the "declaration hides global declaration" warning; our source code violates that
+                push(@cflags, "-wd4459");
+                # disable the "potentially uninitialized local variable '<name>' used" warning; our source code violates that
+                push(@cflags, "-wd4701");
+                # disable the "unreachable code" warning; our source code violates that
+                push(@cflags, "-wd4702");
+                # disable the "potentially uninitialized local pointer variable used" warning; our source code violates that
+                push(@cflags, "-wd4703");
+                # disable the "assignment within conditional expression" warning; our source code violates that
+                push(@cflags, "-wd4706");
+                # disable the "'inet_ntoa': Use inet_ntop() or InetNtop() instead" warning; our source code violates that
+                push(@cflags, "-wd4996");
+        } elsif ("$arg" =~ /^-W[a-z]/) {
+                # let's ignore those
         } else {
                 push(@args, $arg);
         }
diff --git a/compat/win32/path-utils.h b/compat/win32/path-utils.h
index 0f70d43920..8ed062a6b7 100644
--- a/compat/win32/path-utils.h
+++ b/compat/win32/path-utils.h
@@ -1,3 +1,6 @@
+#ifndef WIN32_PATH_UTILS_H
+#define WIN32_PATH_UTILS_H
+
 #define has_dos_drive_prefix(path) \
         (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
 int win32_skip_dos_drive_prefix(char **path);
@@ -18,3 +21,5 @@ static inline char *win32_find_last_dir_sep(const char *path)
 #define find_last_dir_sep win32_find_last_dir_sep
 int win32_offset_1st_component(const char *path);
 #define offset_1st_component win32_offset_1st_component
+
+#endif
diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h
index f1cfe73de9..737983d00b 100644
--- a/compat/win32/pthread.h
+++ b/compat/win32/pthread.h
@@ -51,7 +51,7 @@ typedef struct {
 } pthread_t;
 
 int pthread_create(pthread_t *thread, const void *unused,
-                          void *(*start_routine)(void*), void *arg);
+                   void *(*start_routine)(void*), void *arg);
 
 /*
  * To avoid the need of copying a struct, we use small macro wrapper to pass
diff --git a/compat/winansi.c b/compat/winansi.c
index cacd82c833..54fd701cbf 100644
--- a/compat/winansi.c
+++ b/compat/winansi.c
@@ -546,7 +546,7 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle)
 typedef struct _OBJECT_NAME_INFORMATION
 {
         UNICODE_STRING Name;
-        WCHAR NameBuffer[0];
+        WCHAR NameBuffer[FLEX_ARRAY];
 } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
 
 #define ObjectNameInformation 1
diff --git a/config.c b/config.c
index eef4f4f1bb..d75f88ca0c 100644
--- a/config.c
+++ b/config.c
@@ -1364,6 +1364,11 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
                 return 0;
         }
 
+        if (!strcmp(var, "core.sparsecheckoutcone")) {
+                core_sparse_checkout_cone = git_config_bool(var, value);
+                return 0;
+        }
+
         if (!strcmp(var, "core.precomposeunicode")) {
                 precomposed_unicode = git_config_bool(var, value);
                 return 0;
@@ -1856,9 +1861,9 @@ static struct config_set_element *configset_find_element(struct config_set *cs,
         if (git_config_parse_key(key, &normalized_key, NULL))
                 return NULL;
 
-        hashmap_entry_init(&k, strhash(normalized_key));
+        hashmap_entry_init(&k.ent, strhash(normalized_key));
         k.key = normalized_key;
-        found_entry = hashmap_get(&cs->config_hash, &k, NULL);
+        found_entry = hashmap_get_entry(&cs->config_hash, &k, ent, NULL);
         free(normalized_key);
         return found_entry;
 }
@@ -1877,10 +1882,10 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
          */
         if (!e) {
                 e = xmalloc(sizeof(*e));
-                hashmap_entry_init(e, strhash(key));
+                hashmap_entry_init(&e->ent, strhash(key));
                 e->key = xstrdup(key);
                 string_list_init(&e->value_list, 1);
-                hashmap_add(&cs->config_hash, e);
+                hashmap_add(&cs->config_hash, &e->ent);
         }
         si = string_list_append_nodup(&e->value_list, xstrdup_or_null(value));
 
@@ -1908,12 +1913,14 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
 }
 
 static int config_set_element_cmp(const void *unused_cmp_data,
-                                  const void *entry,
-                                  const void *entry_or_key,
+                                  const struct hashmap_entry *eptr,
+                                  const struct hashmap_entry *entry_or_key,
                                   const void *unused_keydata)
 {
-        const struct config_set_element *e1 = entry;
-        const struct config_set_element *e2 = entry_or_key;
+        const struct config_set_element *e1, *e2;
+
+        e1 = container_of(eptr, const struct config_set_element, ent);
+        e2 = container_of(entry_or_key, const struct config_set_element, ent);
 
         return strcmp(e1->key, e2->key);
 }
@@ -1934,12 +1941,12 @@ void git_configset_clear(struct config_set *cs)
         if (!cs->hash_initialized)
                 return;
 
-        hashmap_iter_init(&cs->config_hash, &iter);
-        while ((entry = hashmap_iter_next(&iter))) {
+        hashmap_for_each_entry(&cs->config_hash, &iter, entry,
+                                ent /* member name */) {
                 free(entry->key);
                 string_list_clear(&entry->value_list, 1);
         }
-        hashmap_free(&cs->config_hash, 1);
+        hashmap_free_entries(&cs->config_hash, struct config_set_element, ent);
         cs->hash_initialized = 0;
         free(cs->list.items);
         cs->list.nr = 0;
diff --git a/config.h b/config.h
index f0ed464004..91fd4c5e96 100644
--- a/config.h
+++ b/config.h
@@ -4,6 +4,22 @@
 #include "hashmap.h"
 #include "string-list.h"
 
+
+/**
+ * The config API gives callers a way to access Git configuration files
+ * (and files which have the same syntax).
+ *
+ * General Usage
+ * -------------
+ *
+ * Config files are parsed linearly, and each variable found is passed to a
+ * caller-provided callback function. The callback function is responsible
+ * for any actions to be taken on the config option, and is free to ignore
+ * some options. It is not uncommon for the configuration to be parsed
+ * several times during the run of a Git program, with different callbacks
+ * picking out different variables useful to themselves.
+ */
+
 struct object_id;
 
 /* git_config_parse_key() returns these negated: */
@@ -71,9 +87,34 @@ struct config_options {
         } error_action;
 };
 
+/**
+ * A config callback function takes three parameters:
+ *
+ * - the name of the parsed variable. This is in canonical "flat" form: the
+ *   section, subsection, and variable segments will be separated by dots,
+ *   and the section and variable segments will be all lowercase. E.g.,
+ *   `core.ignorecase`, `diff.SomeType.textconv`.
+ *
+ * - the value of the found variable, as a string. If the variable had no
+ *   value specified, the value will be NULL (typically this means it
+ *   should be interpreted as boolean true).
+ *
+ * - a void pointer passed in by the caller of the config API; this can
+ *   contain callback-specific data
+ *
+ * A config callback should return 0 for success, or -1 if the variable
+ * could not be parsed properly.
+ */
 typedef int (*config_fn_t)(const char *, const char *, void *);
+
 int git_default_config(const char *, const char *, void *);
+
+/**
+ * Read a specific file in git-config format.
+ * This function takes the same callback and data parameters as `git_config`.
+ */
 int git_config_from_file(config_fn_t fn, const char *, void *);
+
 int git_config_from_file_with_options(config_fn_t fn, const char *,
                                       void *,
                                       const struct config_options *);
@@ -88,34 +129,157 @@ void git_config_push_parameter(const char *text);
 int git_config_from_parameters(config_fn_t fn, void *data);
 void read_early_config(config_fn_t cb, void *data);
 void read_very_early_config(config_fn_t cb, void *data);
+
+/**
+ * Most programs will simply want to look up variables in all config files
+ * that Git knows about, using the normal precedence rules. To do this,
+ * call `git_config` with a callback function and void data pointer.
+ *
+ * `git_config` will read all config sources in order of increasing
+ * priority. Thus a callback should typically overwrite previously-seen
+ * entries with new ones (e.g., if both the user-wide `~/.gitconfig` and
+ * repo-specific `.git/config` contain `color.ui`, the config machinery
+ * will first feed the user-wide one to the callback, and then the
+ * repo-specific one; by overwriting, the higher-priority repo-specific
+ * value is left at the end).
+ */
 void git_config(config_fn_t fn, void *);
+
+/**
+ * Lets the caller examine config while adjusting some of the default
+ * behavior of `git_config`. It should almost never be used by "regular"
+ * Git code that is looking up configuration variables.
+ * It is intended for advanced callers like `git-config`, which are
+ * intentionally tweaking the normal config-lookup process.
+ * It takes two extra parameters:
+ *
+ * - `config_source`
+ * If this parameter is non-NULL, it specifies the source to parse for
+ * configuration, rather than looking in the usual files. See `struct
+ * git_config_source` in `config.h` for details. Regular `git_config` defaults
+ * to `NULL`.
+ *
+ * - `opts`
+ * Specify options to adjust the behavior of parsing config files. See `struct
+ * config_options` in `config.h` for details. As an example: regular `git_config`
+ * sets `opts.respect_includes` to `1` by default.
+ */
 int config_with_options(config_fn_t fn, void *,
                         struct git_config_source *config_source,
                         const struct config_options *opts);
+
+/**
+ * Value Parsing Helpers
+ * ---------------------
+ *
+ * The following helper functions aid in parsing string values
+ */
+
 int git_parse_ssize_t(const char *, ssize_t *);
 int git_parse_ulong(const char *, unsigned long *);
+
+/**
+ * Same as `git_config_bool`, except that it returns -1 on error rather
+ * than dying.
+ */
 int git_parse_maybe_bool(const char *);
+
+/**
+ * Parse the string to an integer, including unit factors. Dies on error;
+ * otherwise, returns the parsed result.
+ */
 int git_config_int(const char *, const char *);
+
 int64_t git_config_int64(const char *, const char *);
+
+/**
+ * Identical to `git_config_int`, but for unsigned longs.
+ */
 unsigned long git_config_ulong(const char *, const char *);
+
 ssize_t git_config_ssize_t(const char *, const char *);
+
+/**
+ * Same as `git_config_bool`, except that integers are returned as-is, and
+ * an `is_bool` flag is unset.
+ */
 int git_config_bool_or_int(const char *, const char *, int *);
+
+/**
+ * Parse a string into a boolean value, respecting keywords like "true" and
+ * "false". Integer values are converted into true/false values (when they
+ * are non-zero or zero, respectively). Other values cause a die(). If
+ * parsing is successful, the return value is the result.
+ */
 int git_config_bool(const char *, const char *);
+
+/**
+ * Allocates and copies the value string into the `dest` parameter; if no
+ * string is given, prints an error message and returns -1.
+ */
 int git_config_string(const char **, const char *, const char *);
+
+/**
+ * Similar to `git_config_string`, but expands `~` or `~user` into the
+ * user's home directory when found at the beginning of the path.
+ */
 int git_config_pathname(const char **, const char *, const char *);
+
 int git_config_expiry_date(timestamp_t *, const char *, const char *);
 int git_config_color(char *, const char *, const char *);
 int git_config_set_in_file_gently(const char *, const char *, const char *);
+
+/**
+ * write config values to a specific config file, takes a key/value pair as
+ * parameter.
+ */
 void git_config_set_in_file(const char *, const char *, const char *);
+
 int git_config_set_gently(const char *, const char *);
+
+/**
+ * write config values to `.git/config`, takes a key/value pair as parameter.
+ */
 void git_config_set(const char *, const char *);
+
 int git_config_parse_key(const char *, char **, int *);
 int git_config_key_is_valid(const char *key);
 int git_config_set_multivar_gently(const char *, const char *, const char *, int);
 void git_config_set_multivar(const char *, const char *, const char *, int);
 int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, int);
+
+/**
+ * takes four parameters:
+ *
+ * - the name of the file, as a string, to which key/value pairs will be written.
+ *
+ * - the name of key, as a string. This is in canonical "flat" form: the section,
+ *   subsection, and variable segments will be separated by dots, and the section
+ *   and variable segments will be all lowercase.
+ *   E.g., `core.ignorecase`, `diff.SomeType.textconv`.
+ *
+ * - the value of the variable, as a string. If value is equal to NULL, it will
+ *   remove the matching key from the config file.
+ *
+ * - the value regex, as a string. It will disregard key/value pairs where value
+ *   does not match.
+ *
+ * - a multi_replace value, as an int. If value is equal to zero, nothing or only
+ *   one matching key/value is replaced, else all matching key/values (regardless
+ *   how many) are removed, before the new pair is written.
+ *
+ * It returns 0 on success.
+ */
 void git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
+
+/**
+ * rename or remove sections in the config file
+ * parameters `old_name` and `new_name`
+ * If NULL is passed through `new_name` parameter,
+ * the section will be removed from the config file.
+ */
 int git_config_rename_section(const char *, const char *);
+
 int git_config_rename_section_in_file(const char *, const char *, const char *);
 int git_config_copy_section(const char *, const char *);
 int git_config_copy_section_in_file(const char *, const char *, const char *);
@@ -142,6 +306,30 @@ enum config_scope current_config_scope(void);
 const char *current_config_origin_type(void);
 const char *current_config_name(void);
 
+/**
+ * Include Directives
+ * ------------------
+ *
+ * By default, the config parser does not respect include directives.
+ * However, a caller can use the special `git_config_include` wrapper
+ * callback to support them. To do so, you simply wrap your "real" callback
+ * function and data pointer in a `struct config_include_data`, and pass
+ * the wrapper to the regular config-reading functions. For example:
+ *
+ * -------------------------------------------
+ * int read_file_with_include(const char *file, config_fn_t fn, void *data)
+ * {
+ * struct config_include_data inc = CONFIG_INCLUDE_INIT;
+ * inc.fn = fn;
+ * inc.data = data;
+ * return git_config_from_file(git_config_include, file, &inc);
+ * }
+ * -------------------------------------------
+ *
+ * `git_config` respects includes automatically. The lower-level
+ * `git_config_from_file` does not.
+ *
+ */
 struct config_include_data {
         int depth;
         config_fn_t fn;
@@ -169,6 +357,33 @@ int parse_config_key(const char *var,
                      const char **subsection, int *subsection_len,
                      const char **key);
 
+/**
+ * Custom Configsets
+ * -----------------
+ *
+ * A `config_set` can be used to construct an in-memory cache for
+ * config-like files that the caller specifies (i.e., files like `.gitmodules`,
+ * `~/.gitconfig` etc.). For example,
+ *
+ * ----------------------------------------
+ * struct config_set gm_config;
+ * git_configset_init(&gm_config);
+ * int b;
+ * //we add config files to the config_set
+ * git_configset_add_file(&gm_config, ".gitmodules");
+ * git_configset_add_file(&gm_config, ".gitmodules_alt");
+ *
+ * if (!git_configset_get_bool(gm_config, "submodule.frotz.ignore", &b)) {
+ * //hack hack hack
+ * }
+ *
+ * when we are done with the configset:
+ * git_configset_clear(&gm_config);
+ * ----------------------------------------
+ *
+ * Configset API provides functions for the above mentioned work flow
+ */
+
 struct config_set_element {
         struct hashmap_entry ent;
         char *key;
@@ -197,16 +412,47 @@ struct config_set {
         struct configset_list list;
 };
 
+/**
+ * Initializes the config_set `cs`.
+ */
 void git_configset_init(struct config_set *cs);
+
+/**
+ * Parses the file and adds the variable-value pairs to the `config_set`,
+ * dies if there is an error in parsing the file. Returns 0 on success, or
+ * -1 if the file does not exist or is inaccessible. The user has to decide
+ * if he wants to free the incomplete configset or continue using it when
+ * the function returns -1.
+ */
 int git_configset_add_file(struct config_set *cs, const char *filename);
+
+/**
+ * Finds and returns the value list, sorted in order of increasing priority
+ * for the configuration variable `key` and config set `cs`. When the
+ * configuration variable `key` is not found, returns NULL. The caller
+ * should not free or modify the returned pointer, as it is owned by the cache.
+ */
 const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
+
+/**
+ * Clears `config_set` structure, removes all saved variable-value pairs.
+ */
 void git_configset_clear(struct config_set *cs);
 
 /*
  * These functions return 1 if not found, and 0 if found, leaving the found
  * value in the 'dest' pointer.
  */
+
+/*
+ * Finds the highest-priority value for the configuration variable `key`
+ * and config set `cs`, stores the pointer to it in `value` and returns 0.
+ * When the configuration variable `key` is not found, returns 1 without
+ * touching `value`. The caller should not free or modify `value`, as it
+ * is owned by the cache.
+ */
 int git_configset_get_value(struct config_set *cs, const char *key, const char **dest);
+
 int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);
 int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
 int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
@@ -240,17 +486,94 @@ int repo_config_get_maybe_bool(struct repository *repo,
 int repo_config_get_pathname(struct repository *repo,
                              const char *key, const char **dest);
 
+/**
+ * Querying For Specific Variables
+ * -------------------------------
+ *
+ * For programs wanting to query for specific variables in a non-callback
+ * manner, the config API provides two functions `git_config_get_value`
+ * and `git_config_get_value_multi`. They both read values from an internal
+ * cache generated previously from reading the config files.
+ */
+
+/**
+ * Finds the highest-priority value for the configuration variable `key`,
+ * stores the pointer to it in `value` and returns 0. When the
+ * configuration variable `key` is not found, returns 1 without touching
+ * `value`. The caller should not free or modify `value`, as it is owned
+ * by the cache.
+ */
 int git_config_get_value(const char *key, const char **value);
+
+/**
+ * Finds and returns the value list, sorted in order of increasing priority
+ * for the configuration variable `key`. When the configuration variable
+ * `key` is not found, returns NULL. The caller should not free or modify
+ * the returned pointer, as it is owned by the cache.
+ */
 const struct string_list *git_config_get_value_multi(const char *key);
+
+/**
+ * Resets and invalidates the config cache.
+ */
 void git_config_clear(void);
+
+/**
+ * Allocates and copies the retrieved string into the `dest` parameter for
+ * the configuration variable `key`; if NULL string is given, prints an
+ * error message and returns -1. When the configuration variable `key` is
+ * not found, returns 1 without touching `dest`.
+ */
 int git_config_get_string_const(const char *key, const char **dest);
+
+/**
+ * Similar to `git_config_get_string_const`, except that retrieved value
+ * copied into the `dest` parameter is a mutable string.
+ */
 int git_config_get_string(const char *key, char **dest);
+
+/**
+ * Finds and parses the value to an integer for the configuration variable
+ * `key`. Dies on error; otherwise, stores the value of the parsed integer in
+ * `dest` and returns 0. When the configuration variable `key` is not found,
+ * returns 1 without touching `dest`.
+ */
 int git_config_get_int(const char *key, int *dest);
+
+/**
+ * Similar to `git_config_get_int` but for unsigned longs.
+ */
 int git_config_get_ulong(const char *key, unsigned long *dest);
+
+/**
+ * Finds and parses the value into a boolean value, for the configuration
+ * variable `key` respecting keywords like "true" and "false". Integer
+ * values are converted into true/false values (when they are non-zero or
+ * zero, respectively). Other values cause a die(). If parsing is successful,
+ * stores the value of the parsed result in `dest` and returns 0. When the
+ * configuration variable `key` is not found, returns 1 without touching
+ * `dest`.
+ */
 int git_config_get_bool(const char *key, int *dest);
+
+/**
+ * Similar to `git_config_get_bool`, except that integers are copied as-is,
+ * and `is_bool` flag is unset.
+ */
 int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
+
+/**
+ * Similar to `git_config_get_bool`, except that it returns -1 on error
+ * rather than dying.
+ */
 int git_config_get_maybe_bool(const char *key, int *dest);
+
+/**
+ * Similar to `git_config_get_string`, but expands `~` or `~user` into
+ * the user's home directory when found at the beginning of the path.
+ */
 int git_config_get_pathname(const char *key, const char **dest);
+
 int git_config_get_index_threads(int *dest);
 int git_config_get_untracked_cache(void);
 int git_config_get_split_index(void);
@@ -270,7 +593,19 @@ struct key_value_info {
         enum config_scope scope;
 };
 
+/**
+ * First prints the error message specified by the caller in `err` and then
+ * dies printing the line number and the file name of the highest priority
+ * value for the configuration variable `key`.
+ */
 NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
+
+/**
+ * Helper function which formats the die error message according to the
+ * parameters entered. Used by `git_die_config()`. It can be used by callers
+ * handling `git_config_get_value_multi()` to print the correct error message
+ * for the desired value.
+ */
 NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);
 
 #define LOOKUP_CONFIG(mapping, var) \
diff --git a/config.mak.uname b/config.mak.uname
index db7f06b95f..cc8efd95b1 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -703,20 +703,24 @@ vcxproj:
         perl contrib/buildsystems/generate -g Vcxproj
         git add -f git.sln {*,*/lib,t/helper/*}/*.vcxproj
 
-        # Generate the LinkOrCopyBuiltins.targets file
+        # Generate the LinkOrCopyBuiltins.targets and LinkOrCopyRemoteHttp.targets file
         (echo '<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">' && \
          echo '  <Target Name="CopyBuiltins_AfterBuild" AfterTargets="AfterBuild">' && \
          for name in $(BUILT_INS);\
          do \
            echo '    <Copy SourceFiles="$$(OutDir)\git.exe" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \
          done && \
+         echo '  </Target>' && \
+         echo '</Project>') >git/LinkOrCopyBuiltins.targets
+        (echo '<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">' && \
+         echo '  <Target Name="CopyBuiltins_AfterBuild" AfterTargets="AfterBuild">' && \
          for name in $(REMOTE_CURL_ALIASES); \
          do \
            echo '    <Copy SourceFiles="$$(OutDir)\'"$(REMOTE_CURL_PRIMARY)"'" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \
          done && \
          echo '  </Target>' && \
-         echo '</Project>') >git/LinkOrCopyBuiltins.targets
-        git add -f git/LinkOrCopyBuiltins.targets
+         echo '</Project>') >git-remote-http/LinkOrCopyRemoteHttp.targets
+        git add -f git/LinkOrCopyBuiltins.targets git-remote-http/LinkOrCopyRemoteHttp.targets
 
         # Add command-list.h
         $(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 command-list.h
@@ -724,11 +728,10 @@ vcxproj:
 
         # Add scripts
         rm -f perl/perl.mak
-        $(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 \
-                $(SCRIPT_LIB) $(SCRIPT_SH_GEN) $(SCRIPT_PERL_GEN)
+        $(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(SCRIPT_LIB) $(SCRIPTS)
         # Strip out the sane tool path, needed only for building
         sed -i '/^git_broken_path_fix ".*/d' git-sh-setup
-        git add -f $(SCRIPT_LIB) $(SCRIPT_SH_GEN) $(SCRIPT_PERL_GEN)
+        git add -f $(SCRIPT_LIB) $(SCRIPTS)
 
         # Add Perl module
         $(MAKE) $(LIB_PERL_GEN)
@@ -758,6 +761,10 @@ vcxproj:
         $(MAKE) -C templates
         git add -f templates/boilerplates.made templates/blt/
 
+        # Add the translated messages
+        make MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(MOFILES)
+        git add -f $(MOFILES)
+
         # Add build options
         $(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 GIT-BUILD-OPTIONS
         git add -f GIT-BUILD-OPTIONS
diff --git a/configure.ac b/configure.ac
index a43b476402..66aedb9288 100644
--- a/configure.ac
+++ b/configure.ac
@@ -85,7 +85,7 @@ AC_DEFUN([GIT_PARSE_WITH],
 
 # GIT_PARSE_WITH_SET_MAKE_VAR(WITHNAME, VAR, HELP_TEXT)
 # -----------------------------------------------------
-# Set VAR to the value specied by --with-WITHNAME.
+# Set VAR to the value specified by --with-WITHNAME.
 # No verification of arguments is performed, but warnings are issued
 # if either 'yes' or 'no' is specified.
 # HELP_TEXT is presented when --help is called.
@@ -844,12 +844,61 @@ AC_MSG_CHECKING([for old iconv()])
 AC_COMPILE_IFELSE([OLDICONVTEST_SRC],
         [AC_MSG_RESULT([no])],
         [AC_MSG_RESULT([yes])
+        AC_DEFINE(HAVE_OLD_ICONV, 1)
         OLD_ICONV=UnfortunatelyYes])
 
 GIT_UNSTASH_FLAGS($ICONVDIR)
 
 GIT_CONF_SUBST([OLD_ICONV])
 
+#
+# Define ICONV_OMITS_BOM if you are on a system which
+# iconv omits bom for utf-{16,32}
+if test -z "$NO_ICONV"; then
+AC_CACHE_CHECK([whether iconv omits bom for utf-16 and utf-32],
+ [ac_cv_iconv_omits_bom],
+[
+old_LIBS="$LIBS"
+if test -n "$NEEDS_LIBICONV"; then
+        LIBS="$LIBS -liconv"
+fi
+
+AC_RUN_IFELSE(
+        [AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
+        #include <iconv.h>
+        #ifdef HAVE_OLD_ICONV
+        typedef const char *iconv_ibp;
+        #else
+        typedef char *iconv_ibp;
+        #endif
+        ],
+        [[
+        int v;
+        iconv_t conv;
+        char in[] = "a"; iconv_ibp pin = in;
+        char out[20] = ""; char *pout = out;
+        size_t isz = sizeof in;
+        size_t osz = sizeof out;
+
+        conv = iconv_open("UTF-16", "UTF-8");
+        iconv(conv, &pin, &isz, &pout, &osz);
+        iconv_close(conv);
+        v = (unsigned char)(out[0]) + (unsigned char)(out[1]);
+        return v != 0xfe + 0xff;
+        ]])],
+        [ac_cv_iconv_omits_bom=no],
+        [ac_cv_iconv_omits_bom=yes])
+
+LIBS="$old_LIBS"
+])
+if test "x$ac_cv_iconv_omits_bom" = xyes; then
+        ICONV_OMITS_BOM=Yes
+else
+        ICONV_OMITS_BOM=
+fi
+GIT_CONF_SUBST([ICONV_OMITS_BOM])
+fi
+
 ## Checks for typedefs, structures, and compiler characteristics.
 AC_MSG_NOTICE([CHECKS for typedefs, structures, and compiler characteristics])
 #
diff --git a/connected.c b/connected.c
index 36c4e5dedb..c337f5f7f4 100644
--- a/connected.c
+++ b/connected.c
@@ -62,7 +62,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
                  * received the objects pointed to by each wanted ref.
                  */
                 do {
-                        if (!repo_has_object_file(the_repository, &oid))
+                        if (!repo_has_object_file_with_flags(the_repository, &oid,
+                                                             OBJECT_INFO_SKIP_FETCH_OBJECT))
                                 return 1;
                 } while (!fn(cb_data, &oid));
                 return 0;
diff --git a/contrib/buildsystems/Generators/Vcxproj.pm b/contrib/buildsystems/Generators/Vcxproj.pm
index 7b1e277eca..5c666f9ac0 100644
--- a/contrib/buildsystems/Generators/Vcxproj.pm
+++ b/contrib/buildsystems/Generators/Vcxproj.pm
@@ -278,6 +278,9 @@ EOM
     if ($target eq 'git') {
       print F "  <Import Project=\"LinkOrCopyBuiltins.targets\" />\n";
     }
+    if ($target eq 'git-remote-http') {
+      print F "  <Import Project=\"LinkOrCopyRemoteHttp.targets\" />\n";
+    }
     print F << "EOM";
 </Project>
 EOM
diff --git a/contrib/coccinelle/commit.cocci b/contrib/coccinelle/commit.cocci
index d03453341e..778e4704f6 100644
--- a/contrib/coccinelle/commit.cocci
+++ b/contrib/coccinelle/commit.cocci
@@ -20,7 +20,7 @@ expression s;
 + set_commit_tree(c, s)
   ...>}
 
-// These excluded functions must access c->maybe_tree direcly.
+// These excluded functions must access c->maybe_tree directly.
 // Note that if c->maybe_tree is written somewhere outside of these
 // functions, then the recommended transformation will be bogus with
 // repo_get_commit_tree() on the LHS.
diff --git a/contrib/coccinelle/hashmap.cocci b/contrib/coccinelle/hashmap.cocci
new file mode 100644
index 0000000000..d69e120ccf
--- /dev/null
+++ b/contrib/coccinelle/hashmap.cocci
@@ -0,0 +1,16 @@
+@ hashmap_entry_init_usage @
+expression E;
+struct hashmap_entry HME;
+@@
+- HME.hash = E;
++ hashmap_entry_init(&HME, E);
+
+@@
+identifier f !~ "^hashmap_entry_init$";
+expression E;
+struct hashmap_entry *HMEP;
+@@
+  f(...) {<...
+- HMEP->hash = E;
++ hashmap_entry_init(HMEP, E);
+  ...>}
diff --git a/contrib/coccinelle/object_id.cocci b/contrib/coccinelle/object_id.cocci
index 3e536a9834..ddf4f22bd7 100644
--- a/contrib/coccinelle/object_id.cocci
+++ b/contrib/coccinelle/object_id.cocci
@@ -13,38 +13,6 @@ struct object_id *OIDPTR;
 @@
 struct object_id OID;
 @@
-- sha1_to_hex(OID.hash)
-+ oid_to_hex(&OID)
-
-@@
-identifier f != oid_to_hex;
-struct object_id *OIDPTR;
-@@
-  f(...) {<...
-- sha1_to_hex(OIDPTR->hash)
-+ oid_to_hex(OIDPTR)
-  ...>}
-
-@@
-expression E;
-struct object_id OID;
-@@
-- sha1_to_hex_r(E, OID.hash)
-+ oid_to_hex_r(E, &OID)
-
-@@
-identifier f != oid_to_hex_r;
-expression E;
-struct object_id *OIDPTR;
-@@
-   f(...) {<...
-- sha1_to_hex_r(E, OIDPTR->hash)
-+ oid_to_hex_r(E, OIDPTR)
-  ...>}
-
-@@
-struct object_id OID;
-@@
 - hashclr(OID.hash)
 + oidclr(&OID)
 
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 00fbe6c03d..67705da641 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -550,7 +550,7 @@ __git_index_files ()
                                                  esc_idx, 1)
                         } else if (esc == "n") {
                                 # Uh-oh, a newline character.
-                                # We cant reliably put a pathname
+                                # We cannot reliably put a pathname
                                 # containing a newline into COMPREPLY,
                                 # and the newline would create a mess.
                                 # Skip this path.
@@ -565,7 +565,7 @@ __git_index_files ()
                         }
                 }
                 # Drop closing double quote, if there is one.
-                # (There isnt any if this is a directory, as it was
+                # (There is not any if this is a directory, as it was
                 # already stripped with the trailing path components.)
                 if (substr(p, length(p), 1) == "\"")
                         out = out substr(p, 1, length(p) - 1)
@@ -2043,6 +2043,10 @@ _git_rebase ()
                 __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
                 return
                 ;;
+        --onto=*)
+                __git_complete_refs --cur="${cur##--onto=}"
+                return
+                ;;
         --*)
                 __gitcomp_builtin rebase "" \
                         "$__git_rebase_interactive_inprogress_options"
@@ -2843,6 +2847,7 @@ _git_svn ()
                         --log-window-size= --no-checkout --quiet
                         --repack-flags --use-log-author --localtime
                         --add-author-from
+                        --recursive
                         --ignore-paths= --include-paths= $remote_opts
                         "
                 local init_opts="
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index 886bf95d1f..eef4eff53d 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -11,8 +11,9 @@
 #
 #  zstyle ':completion:*:*:git:*' script ~/.git-completion.zsh
 #
-# The recommended way to install this script is to copy to '~/.zsh/_git', and
-# then add the following to your ~/.zshrc file:
+# The recommended way to install this script is to make a copy of it in
+# ~/.zsh/ directory as ~/.zsh/git-completion.zsh and then add the following
+# to your ~/.zshrc file:
 #
 #  fpath=(~/.zsh $fpath)
 
diff --git a/contrib/diff-highlight/DiffHighlight.pm b/contrib/diff-highlight/DiffHighlight.pm
index 7440aa1c46..e2589922a6 100644
--- a/contrib/diff-highlight/DiffHighlight.pm
+++ b/contrib/diff-highlight/DiffHighlight.pm
@@ -72,7 +72,7 @@ sub handle_line {
               (?:$COLOR?\|$COLOR?[ ])* # zero or more trailing "|"
                                  [ ]*  # trailing whitespace for merges
             /x) {
-                my $graph_prefix = $&;
+                my $graph_prefix = $&;
 
                 # We must flush before setting graph indent, since the
                 # new commit may be indented differently from what we
diff --git a/contrib/hooks/multimail/git_multimail.py b/contrib/hooks/multimail/git_multimail.py
index 8823399e75..f563be82fc 100755
--- a/contrib/hooks/multimail/git_multimail.py
+++ b/contrib/hooks/multimail/git_multimail.py
@@ -95,7 +95,7 @@ if PYTHON3:
     unicode = str
 
     def write_str(f, msg):
-        # Try outputing with the default encoding. If it fails,
+        # Try outputting with the default encoding. If it fails,
         # try UTF-8.
         try:
             f.buffer.write(msg.encode(sys.getdefaultencoding()))
@@ -2129,7 +2129,7 @@ class SMTPMailer(Mailer):
                 # equivalent to
                 #     self.smtp.ehlo()
                 #     self.smtp.starttls()
-                # with acces to the ssl layer
+                # with access to the ssl layer
                 self.smtp.ehlo()
                 if not self.smtp.has_extn("starttls"):
                     raise smtplib.SMTPException("STARTTLS extension not supported by server")
@@ -2148,7 +2148,7 @@ class SMTPMailer(Mailer):
                         cert_reqs=ssl.CERT_NONE
                         )
                     self.environment.get_logger().error(
-                        '*** Warning, the server certificat is not verified (smtp) ***\n'
+                        '*** Warning, the server certificate is not verified (smtp) ***\n'
                         '***          set the option smtpCACerts                   ***\n'
                         )
                 if not hasattr(self.smtp.sock, "read"):
@@ -3189,7 +3189,7 @@ class ProjectdescEnvironmentMixin(Environment):
         self.COMPUTED_KEYS += ['projectdesc']
 
     def get_projectdesc(self):
-        """Return a one-line descripition of the project."""
+        """Return a one-line description of the project."""
 
         git_dir = get_git_dir()
         try:
diff --git a/contrib/hooks/multimail/post-receive.example b/contrib/hooks/multimail/post-receive.example
index b9bb11834e..0f98c5a23d 100755
--- a/contrib/hooks/multimail/post-receive.example
+++ b/contrib/hooks/multimail/post-receive.example
@@ -56,7 +56,7 @@ config = git_multimail.Config('multimailhook')
 
 # Set some Git configuration variables. Equivalent to passing var=val
 # to "git -c var=val" each time git is called, or to adding the
-# configuration in .git/config (must come before instanciating the
+# configuration in .git/config (must come before instantiating the
 # environment) :
 #git_multimail.Config.add_config_parameters('multimailhook.commitEmailFormat=html')
 #git_multimail.Config.add_config_parameters(('user.name=foo', 'user.email=foo@example.com'))
diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
index 8747b84334..ff565eb3d8 100755
--- a/contrib/hooks/post-receive-email
+++ b/contrib/hooks/post-receive-email
@@ -329,7 +329,7 @@ generate_update_branch_email()
         #
         #  git rev-parse --not --all | grep -v $(git rev-parse $refname)
         #
-        # Get's us to something pretty safe (apart from the small time
+        # Gets us to something pretty safe (apart from the small time
         # between refname being read, and git rev-parse running - for that,
         # I give up)
         #
diff --git a/contrib/hooks/update-paranoid b/contrib/hooks/update-paranoid
index d18b317b2f..0092d67b8a 100755
--- a/contrib/hooks/update-paranoid
+++ b/contrib/hooks/update-paranoid
@@ -49,7 +49,7 @@ opcode.
 Repository sections are matched on the basename of the repository
 (after removing the .git suffix).
 
-The opcode abbrevations are:
+The opcode abbreviations are:
 
   C: create new ref
   D: delete existing ref
diff --git a/contrib/mw-to-git/.perlcriticrc b/contrib/mw-to-git/.perlcriticrc
index 158958d363..b7333267ad 100644
--- a/contrib/mw-to-git/.perlcriticrc
+++ b/contrib/mw-to-git/.perlcriticrc
@@ -14,7 +14,7 @@
 
 # This rule states that each system call should have its return value checked
 # The problem is that it includes the print call. Checking every print call's
-# return value would be harmful to the code readabilty.
+# return value would be harmful to the code readability.
 # This configuration keeps all default function but print.
 [InputOutput::RequireCheckedSyscalls]
 functions = open say close
diff --git a/contrib/mw-to-git/git-remote-mediawiki.perl b/contrib/mw-to-git/git-remote-mediawiki.perl
index af9cbc9d0f..d8ff2e69c4 100755
--- a/contrib/mw-to-git/git-remote-mediawiki.perl
+++ b/contrib/mw-to-git/git-remote-mediawiki.perl
@@ -79,7 +79,7 @@ chomp($export_media);
 $export_media = !($export_media eq 'false');
 
 my $wiki_login = run_git("config --get remote.${remotename}.mwLogin");
-# Note: mwPassword is discourraged. Use the credential system instead.
+# Note: mwPassword is discouraged. Use the credential system instead.
 my $wiki_passwd = run_git("config --get remote.${remotename}.mwPassword");
 my $wiki_domain = run_git("config --get remote.${remotename}.mwDomain");
 chomp($wiki_login);
diff --git a/contrib/mw-to-git/t/install-wiki/db_install.php b/contrib/mw-to-git/t/install-wiki/db_install.php
index 0f3f4e018a..b033849800 100644
--- a/contrib/mw-to-git/t/install-wiki/db_install.php
+++ b/contrib/mw-to-git/t/install-wiki/db_install.php
@@ -24,7 +24,7 @@ $url = 'http://localhost:'.$port.'/wiki/mw-config/index.php';
 $db_dir = urlencode($tmp);
 $tmp_cookie = tempnam($tmp, "COOKIE_");
 /*
- * Fetchs a page with cURL.
+ * Fetches a page with cURL.
  */
 function get($page_name = "") {
         $curl = curl_init();
diff --git a/contrib/mw-to-git/t/t9360-mw-to-git-clone.sh b/contrib/mw-to-git/t/t9360-mw-to-git-clone.sh
index cfbfe7ddf6..9106833578 100755
--- a/contrib/mw-to-git/t/t9360-mw-to-git-clone.sh
+++ b/contrib/mw-to-git/t/t9360-mw-to-git-clone.sh
@@ -143,7 +143,7 @@ test_expect_success 'Git clone works with one specific page cloned ' '
 test_expect_success 'Git clone works with multiple specific page cloned ' '
         wiki_reset &&
         wiki_editpage foo "I will be there" false &&
-        wiki_editpage bar "I will not disapear" false &&
+        wiki_editpage bar "I will not disappear" false &&
         wiki_editpage namnam "I be erased" false &&
         wiki_editpage nyancat "nyan nyan nyan you will not erase me" false &&
         wiki_delete_page namnam &&
diff --git a/contrib/mw-to-git/t/test-gitmw-lib.sh b/contrib/mw-to-git/t/test-gitmw-lib.sh
index 6546294f15..3948a00282 100755
--- a/contrib/mw-to-git/t/test-gitmw-lib.sh
+++ b/contrib/mw-to-git/t/test-gitmw-lib.sh
@@ -279,7 +279,7 @@ start_lighttpd () {
         "$LIGHTTPD_DIR"/lighttpd -f "$WEB"/lighttpd.conf
 
         if test $? -ne 0 ; then
-                echo "Could not execute http deamon lighttpd"
+                echo "Could not execute http daemon lighttpd"
                 exit 1
         fi
 }
diff --git a/contrib/svn-fe/svnrdump_sim.py b/contrib/svn-fe/svnrdump_sim.py
index 50c6a4f89d..8a3cee6175 100755
--- a/contrib/svn-fe/svnrdump_sim.py
+++ b/contrib/svn-fe/svnrdump_sim.py
@@ -54,7 +54,7 @@ if __name__ == "__main__":
         print("usage: %s dump URL -rLOWER:UPPER")
         sys.exit(1)
     if not sys.argv[1] == 'dump':
-        raise NotImplementedError('only "dump" is suppported.')
+        raise NotImplementedError('only "dump" is supported.')
     url = sys.argv[2]
     r = ('0', 'HEAD')
     if len(sys.argv) == 4 and sys.argv[3][0:2] == '-r':
diff --git a/convert.c b/convert.c
index 25ac525d5f..797e0bd0b1 100644
--- a/convert.c
+++ b/convert.c
@@ -270,8 +270,12 @@ static int will_convert_lf_to_crlf(struct text_stat *stats,
 static int validate_encoding(const char *path, const char *enc,
                       const char *data, size_t len, int die_on_error)
 {
+        const char *stripped;
+
         /* We only check for UTF here as UTF?? can be an alias for UTF-?? */
-        if (istarts_with(enc, "UTF")) {
+        if (skip_iprefix(enc, "UTF", &stripped)) {
+