Merge branch 'jc/fmt-merge-msg-suppress-destination' into master

"git merge" learned to selectively omit " into <branch>" at the end
of the title of default merge message with merge.suppressDest
configuration.

* jc/fmt-merge-msg-suppress-destination:
  fmt-merge-msg: allow merge destination to be omitted again
  Revert "fmt-merge-msg: stop treating `master` specially"
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index e7b4e2f..c8755e3 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -16,4 +16,7 @@
 might be useful to you as the presenter walks you through the contribution
 process by example.
 
+Or, you can follow the ["My First Contribution"](https://git-scm.com/docs/MyFirstContribution)
+tutorial for another example of the contribution process.
+
 Your friendly Git community!
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index 227f46a..45465bc 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -489,16 +489,11 @@
 
  - We follow PEP-8 (http://www.python.org/dev/peps/pep-0008/).
 
- - As a minimum, we aim to be compatible with Python 2.6 and 2.7.
+ - As a minimum, we aim to be compatible with Python 2.7.
 
  - Where required libraries do not restrict us to Python 2, we try to
    also be compatible with Python 3.1 and later.
 
- - When you must differentiate between Unicode literals and byte string
-   literals, it is OK to use the 'b' prefix.  Even though the Python
-   documentation for version 2.6 does not mention this prefix, it has
-   been supported since version 2.6.0.
-
 Error Messages
 
  - Do not end error messages with a full stop.
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 15d9d04..ecd0b34 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -93,6 +93,7 @@
 TECH_DOCS += technical/protocol-common
 TECH_DOCS += technical/protocol-v2
 TECH_DOCS += technical/racy-git
+TECH_DOCS += technical/reftable
 TECH_DOCS += technical/send-pack-pipeline
 TECH_DOCS += technical/shallow
 TECH_DOCS += technical/signature-format
diff --git a/Documentation/MyFirstContribution.txt b/Documentation/MyFirstContribution.txt
index 427274d..d85c9b5 100644
--- a/Documentation/MyFirstContribution.txt
+++ b/Documentation/MyFirstContribution.txt
@@ -1179,8 +1179,8 @@
 [[after-approval]]
 === After Review Approval
 
-The Git project has four integration branches: `pu`, `next`, `master`, and
-`maint`. Your change will be placed into `pu` fairly early on by the maintainer
+The Git project has four integration branches: `seen`, `next`, `master`, and
+`maint`. Your change will be placed into `seen` fairly early on by the maintainer
 while it is still in the review process; from there, when it is ready for wider
 testing, it will be merged into `next`. Plenty of early testers use `next` and
 may report issues. Eventually, changes in `next` will make it to `master`,
diff --git a/Documentation/RelNotes/2.28.0.txt b/Documentation/RelNotes/2.28.0.txt
index b1a23e9..6baf781 100644
--- a/Documentation/RelNotes/2.28.0.txt
+++ b/Documentation/RelNotes/2.28.0.txt
@@ -6,9 +6,8 @@
 
 Backward compatibility notes
 
- * "feature.experimental" configuration variable is to let volunteers
-   easily opt into a set of newer features, which use of the v2
-   transport protocol is now a part of.
+ * "fetch.writeCommitGraph" is deemed to be still a bit too risky and
+   is no longer part of the "feature.experimental" set.
 
 
 UI, Workflows & Features
@@ -19,6 +18,33 @@
  * The check in "git fsck" to ensure that the tree objects are sorted
    still had corner cases it missed unsorted entries.
 
+ * The interface to redact sensitive information in the trace output
+   has been simplified.
+
+ * The command line completion (in contrib/) learned to complete
+   options that the "git switch" command takes.
+
+ * "git diff" used to take arguments in random and nonsense range
+   notation, e.g. "git diff A..B C", "git diff A..B C...D", etc.,
+   which has been cleaned up.
+
+ * "git diff-files" has been taught to say paths that are marked as
+   intent-to-add are new files, not modified from an empty blob.
+
+ * "git status" learned to report the status of sparse checkout.
+
+ * "git difftool" has trouble dealing with paths added to the index
+   with the intent-to-add bit.
+
+ * "git fast-export --anonymize" learned to take customized mapping to
+   allow its users to tweak its output more usable for debugging.
+
+ * The command line completion support (in contrib/) used to be
+   prepared to work with "set -u" but recent changes got a bit more
+   sloppy.  This has been corrected.
+
+ * "git gui" now allows opening work trees from the start-up dialog.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -44,6 +70,55 @@
  * Support for GIT_CURL_VERBOSE has been rewritten in terms of
    GIT_TRACE_CURL.
 
+ * Preliminary clean-ups around refs API, plus file format
+   specification documentation for the reftable backend.
+
+ * Workaround breakage in MSVC build, where "curl-config --cflags"
+   gives settings appropriate for GCC build.
+
+ * Code clean-up of "git clean" resulted in a fix of recent
+   performance regression.
+
+ * Code clean-up in the codepath that serves "git fetch" continues.
+
+ * "git merge-base --is-ancestor" is taught to take advantage of the
+   commit graph.
+
+ * Rewrite of parts of the scripted "git submodule" Porcelain command
+   continues; this time it is "git submodule set-branch" subcommand's
+   turn.
+
+ * The "fetch/clone" protocol has been updated to allow the server to
+   instruct the clients to grab pre-packaged packfile(s) in addition
+   to the packed object data coming over the wire.
+
+ * A misdesigned strbuf_write_fd() function has been retired.
+
+ * SHA-256 migration work continues, including CVS/SVN interface.
+
+ * A few fields in "struct commit" that do not have to always be
+   present have been moved to commit slabs.
+
+ * API cleanup for get_worktrees()
+
+ * By renumbering object flag bits, "struct object" managed to lose
+   bloated inter-field padding.
+
+ * The name of the primary branch in existing repositories, and the
+   default name used for the first branch in newly created
+   repositories, is made configurable, so that we can eventually wean
+   ourselves off of the hardcoded 'master'.
+
+ * The effort to avoid using test_must_fail on non-git command continues.
+
+ * In 2.28-rc0, we corrected a bug that some repository extensions are
+   honored by mistake even in a version 0 repositories (these
+   configuration variables in extensions.* namespace were supposed to
+   have special meaning in repositories whose version numbers are 1 or
+   higher), but this was a bit too big a change.  The behaviour in
+   recent versions of Git where certain extensions.* were honored by
+   mistake even in version 0 repositories has been restored.
+
 
 Fixes since v2.27
 -----------------
@@ -78,6 +153,84 @@
    validating the arguments.
    (merge 4d9005ff5d cb/bisect-helper-parser-fix later to maint).
 
+ * Reduce memory usage during "diff --quiet" in a worktree with too
+   many stat-unmatched paths.
+   (merge d2d7fbe129 jk/diff-memuse-optim-with-stat-unmatch later to maint).
+
+ * The reflog entries for "git clone" and "git fetch" did not
+   anonymize the URL they operated on.
+   (merge 46da295a77 js/reflog-anonymize-for-clone-and-fetch later to maint).
+
+ * The behaviour of "sparse-checkout" in the state "git clone
+   --no-checkout" left was changed accidentally in 2.27, which has
+   been corrected.
+
+ * Use of negative pathspec, while collecting paths including
+   untracked ones in the working tree, was broken.
+
+ * The same worktree directory must be registered only once, but
+   "git worktree move" allowed this invariant to be violated, which
+   has been corrected.
+   (merge 810382ed37 es/worktree-duplicate-paths later to maint).
+
+ * The effect of sparse checkout settings on submodules is documented.
+   (merge e7d7c73249 en/sparse-with-submodule-doc later to maint).
+
+ * Code clean-up around "git branch" with a minor bugfix.
+   (merge dc44639904 dl/branch-cleanup later to maint).
+
+ * A branch name used in a test has been clarified to match what is
+   going on.
+   (merge 08dc26061f pb/t4014-unslave later to maint).
+
+ * An in-code comment in "git diff" has been updated.
+   (merge c592fd4c83 dl/diff-usage-comment-update later to maint).
+
+ * The documentation and some tests have been adjusted for the recent
+   renaming of "pu" branch to "seen".
+   (merge 6dca5dbf93 js/pu-to-seen later to maint).
+
+ * The code to push changes over "dumb" HTTP had a bad interaction
+   with the commit reachability code due to incorrect allocation of
+   object flag bits, which has been corrected.
+   (merge 64472d15e9 bc/http-push-flagsfix later to maint).
+
+ * "git send-email --in-reply-to=<msg>" did not use the In-Reply-To:
+   header with the value given from the command line, and let it be
+   overridden by the value on In-Reply-To: header in the messages
+   being sent out (if exists).
+   (merge f9f60d7066 ra/send-email-in-reply-to-from-command-line-wins later to maint).
+
+ * "git log -Lx,y:path --before=date" lost track of where the range
+   should be because it didn't take the changes made by the youngest
+   commits that are omitted from the output into account.
+
+ * When "fetch.writeCommitGraph" configuration is set in a shallow
+   repository and a fetch moves the shallow boundary, we wrote out
+   broken commit-graph files that do not match the reality, which has
+   been corrected.
+
+ * "git checkout" failed to catch an error from fstat() after updating
+   a path in the working tree.
+   (merge 35e6e212fd mt/entry-fstat-fallback-fix later to maint).
+
+ * When an aliased command, whose output is piped to a pager by git,
+   gets killed by a signal, the pager got into a funny state, which
+   has been corrected (again).
+   (merge c0d73a59c9 ta/wait-on-aliased-commands-upon-signal later to maint).
+
+ * The code to produce progress output from "git commit-graph --write"
+   had a few breakages, which have been fixed.
+
  * Other code cleanup, docfix, build fix, etc.
    (merge 2c31a7aa44 jx/pkt-line-doc-count-fix later to maint).
    (merge d63ae31962 cb/t5608-cleanup later to maint).
+   (merge 788db145c7 dl/t-readme-spell-git-correctly later to maint).
+   (merge 45a87a83bb dl/python-2.7-is-the-floor-version later to maint).
+   (merge b75a219904 es/advertise-contribution-doc later to maint).
+   (merge 0c9a4f638a rs/pull-leakfix later to maint).
+   (merge d546fe2874 rs/commit-reach-leakfix later to maint).
+   (merge 087bf5409c mk/pb-pretty-email-without-domain-part-fix later to maint).
+   (merge 5f4ee57ad9 es/worktree-code-cleanup later to maint).
+   (merge 0172f7834a cc/cat-file-usage-update later to maint).
+   (merge 81de0c01cf ma/rebase-doc-typofix later to maint).
diff --git a/Documentation/RelNotes/2.29.0.txt b/Documentation/RelNotes/2.29.0.txt
new file mode 100644
index 0000000..7b189d0
--- /dev/null
+++ b/Documentation/RelNotes/2.29.0.txt
@@ -0,0 +1,73 @@
+Git 2.29 Release Notes
+======================
+
+Updates since v2.28
+-------------------
+
+UI, Workflows & Features
+
+ * "git help log" has been enhanced by sharing more material from the
+   documentation for the underlying "git rev-list" command.
+
+ * "git for-each-ref --format=<>" learned %(contents:size).
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * The changed-path Bloom filter is improved using ideas from an
+   independent implementation.
+
+ * Updates to the changed-paths bloom filter.
+
+ * The test framework has been updated so that most tests will run
+   with predictable (artificial) timestamps.
+
+ * Preliminary clean-up of the refs API in preparation for adding a
+   new refs backend "reftable".
+
+ * Dev support to limit the use of test_must_fail to only git commands.
+
+
+Fixes since v2.28
+-----------------
+
+ * "git clone --separate-git-dir=$elsewhere" used to stomp on the
+   contents of the existing directory $elsewhere, which has been
+   taught to fail when $elsewhere is not an empty directory.
+   (merge dfaa209a79 bw/fail-cloning-into-non-empty later to maint).
+
+
+ * With the base fix to 2.27 regresion, any new extensions in a v0
+   repository would still be silently honored, which is not quite
+   right.  Instead, complain and die loudly.
+   (merge ec91ffca04 jk/reject-newer-extensions-in-v0 later to maint).
+
+ * Fetching from a lazily cloned repository resulted at the server
+   side in attempts to lazy fetch objects that the client side has,
+   many of which will not be available from the third-party anyway.
+   (merge 77aa0941ce jt/avoid-lazy-fetching-upon-have-check later to maint).
+
+ * Fix to an ancient bug caused by an over-eager attempt for
+   optimization.
+   (merge a98f7fb366 rs/add-index-entry-optim-fix later to maint).
+
+ * Pushing a ref whose name contains non-ASCII character with the
+   "--force-with-lease" option did not work over smart HTTP protocol,
+   which has been corrected.
+   (merge cd85b447bf bc/push-cas-cquoted-refname later to maint).
+
+ * "git mv src dst", when src is an unmerged path, errored out
+   correctly but with an incorrect error message to claim that src is
+   not tracked, which has been clarified.
+   (merge 9b906af657 ct/mv-unmerged-path-error later to maint).
+
+ * Fix to a regression introduced during 2.27 cycle.
+   (merge cada7308ad en/fill-directory-exponential later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+   (merge 84544f2ea3 sk/typofixes later to maint).
+   (merge b17f411ab5 ar/help-guides-doc later to maint).
+   (merge 98c6871fad rs/grep-simpler-parse-object-or-die-call later to maint).
+   (merge 861c4ce141 en/typofixes later to maint).
+   (merge 60e47f6773 sg/ci-git-path-fix-with-pyenv later to maint).
+   (merge e2bfa50ac3 jb/doc-packfile-name later to maint).
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 4515cab..291b61e 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -3,8 +3,9 @@
 
 == Guidelines
 
-Here are some guidelines for people who want to contribute their code
-to this software.
+Here are some guidelines for people who want to contribute their code to this
+software. There is also a link:MyFirstContribution.html[step-by-step tutorial]
+available which covers many of these same guidelines.
 
 [[base-branch]]
 === Decide what to base your work on.
@@ -18,7 +19,7 @@
   base your work on the tip of the topic.
 
 * A new feature should be based on `master` in general. If the new
-  feature depends on a topic that is in `pu`, but not in `master`,
+  feature depends on a topic that is in `seen`, but not in `master`,
   base your work on the tip of that topic.
 
 * Corrections and enhancements to a topic not yet in `master` should
@@ -27,7 +28,7 @@
   into the series.
 
 * In the exceptional case that a new feature depends on several topics
-  not in `master`, start working on `next` or `pu` privately and send
+  not in `master`, start working on `next` or `seen` privately and send
   out patches for discussion. Before the final merge, you may have to
   wait until some of the dependent topics graduate to `master`, and
   rebase your work.
@@ -37,7 +38,7 @@
   these parts should be based on their trees.
 
 To find the tip of a topic branch, run `git log --first-parent
-master..pu` and look for the merge commit. The second parent of this
+master..seen` and look for the merge commit. The second parent of this
 commit is the tip of the topic branch.
 
 [[separate-commits]]
@@ -423,7 +424,7 @@
   and cooked further and eventually graduates to `master`.
 
 In any time between the (2)-(3) cycle, the maintainer may pick it up
-from the list and queue it to `pu`, in order to make it easier for
+from the list and queue it to `seen`, in order to make it easier for
 people play with it without having to pick up and apply the patch to
 their trees themselves.
 
@@ -434,7 +435,7 @@
   master. `git pull --rebase` will automatically skip already-applied
   patches, and will let you know. This works only if you rebase on top
   of the branch in which your patch has been merged (i.e. it will not
-  tell you if your patch is merged in pu if you rebase on top of
+  tell you if your patch is merged in `seen` if you rebase on top of
   master).
 
 * Read the Git mailing list, the maintainer regularly posts messages
diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.txt
index 28c3360..c0cbf2b 100644
--- a/Documentation/config/feature.txt
+++ b/Documentation/config/feature.txt
@@ -15,14 +15,6 @@
 * `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
 skipping more commits at a time, reducing the number of round trips.
 +
-* `fetch.writeCommitGraph=true` writes a commit-graph after every `git fetch`
-command that downloads a pack-file from a remote. Using the `--split` option,
-most executions will create a very small commit-graph file on top of the
-existing commit-graph file(s). Occasionally, these files will merge and the
-write may take longer. Having an updated commit-graph file helps performance
-of many Git commands, including `git merge-base`, `git push -f`, and
-`git log --graph`.
-+
 * `protocol.version=2` speeds up fetches from repositories with many refs by
 allowing the client to specify which refs to list before the server lists
 them.
diff --git a/Documentation/config/fetch.txt b/Documentation/config/fetch.txt
index b1a9b14..b203940 100644
--- a/Documentation/config/fetch.txt
+++ b/Documentation/config/fetch.txt
@@ -90,5 +90,4 @@
 	the existing commit-graph file(s). Occasionally, these files will
 	merge and the write may take longer. Having an updated commit-graph
 	file helps performance of many Git commands, including `git merge-base`,
-	`git push -f`, and `git log --graph`. Defaults to false, unless
-	`feature.experimental` is true.
+	`git push -f`, and `git log --graph`. Defaults to false.
diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt
index 46fa8c6..dc77f8c 100644
--- a/Documentation/config/init.txt
+++ b/Documentation/config/init.txt
@@ -1,3 +1,7 @@
 init.templateDir::
 	Specify the directory from which templates will be copied.
 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
+
+init.defaultBranch::
+	Allows overriding the default branch name e.g. when initializing
+	a new repository or when cloning an empty repository.
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 135206f..03c0824 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -12,7 +12,7 @@
 	[-v [--abbrev=<length> | --no-abbrev]]
 	[--column[=<options>] | --no-column] [--sort=<key>]
 	[(--merged | --no-merged) [<commit>]]
-	[--contains [<commit]] [--no-contains [<commit>]]
+	[--contains [<commit>]] [--no-contains [<commit>]]
 	[--points-at <object>] [--format=<format>]
 	[(-r | --remotes) | (-a | --all)]
 	[--list] [<pattern>...]
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index 8eca671..8e192d8 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -10,7 +10,7 @@
 --------
 [verse]
 'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p | <type> | --textconv | --filters ) [--path=<path>] <object>
-'git cat-file' (--batch | --batch-check) [ --textconv | --filters ] [--follow-symlinks]
+'git cat-file' (--batch[=<format>] | --batch-check[=<format>]) [ --textconv | --filters ] [--follow-symlinks]
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 08d6045..c898310 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -259,7 +259,7 @@
 branch. This is useful e.g. to maintain minimal clones of the default
 branch of some repository for search indexing.
 
---recurse-submodules[=<pathspec]::
+--recurse-submodules[=<pathspec>]::
 	After the clone is created, initialize and clone submodules
 	within based on the provided pathspec.  If no pathspec is
 	provided, all submodules are initialized and cloned.
diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.txt
index 8ca1764..17405c7 100644
--- a/Documentation/git-commit-graph.txt
+++ b/Documentation/git-commit-graph.txt
@@ -62,7 +62,10 @@
 With the `--changed-paths` option, compute and write information about the
 paths changed between a commit and its first parent. This operation can
 take a while on large repositories. It provides significant performance gains
-for getting history of a directory or a file with `git log -- <path>`.
+for getting history of a directory or a file with `git log -- <path>`. If
+this option is given, future commit-graph writes will automatically assume
+that this option was intended. Use `--no-changed-paths` to stop storing this
+data.
 +
 With the `--split[=<strategy>]` option, write the commit-graph as a
 chain of multiple commit-graph files stored in
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index 37781cf..727f24d 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -11,15 +11,17 @@
 [verse]
 'git diff' [<options>] [<commit>] [--] [<path>...]
 'git diff' [<options>] --cached [<commit>] [--] [<path>...]
-'git diff' [<options>] <commit> <commit> [--] [<path>...]
+'git diff' [<options>] <commit> [<commit>...] <commit> [--] [<path>...]
+'git diff' [<options>] <commit>...<commit> [--] [<path>...]
 'git diff' [<options>] <blob> <blob>
 'git diff' [<options>] --no-index [--] <path> <path>
 
 DESCRIPTION
 -----------
 Show changes between the working tree and the index or a tree, changes
-between the index and a tree, changes between two trees, changes between
-two blob objects, or changes between two files on disk.
+between the index and a tree, changes between two trees, changes resulting
+from a merge, changes between two blob objects, or changes between two
+files on disk.
 
 'git diff' [<options>] [--] [<path>...]::
 
@@ -61,9 +63,19 @@
 	This is to view the changes between two arbitrary
 	<commit>.
 
+'git diff' [<options>] <commit> <commit>... <commit> [--] [<path>...]::
+
+	This form is to view the results of a merge commit.  The first
+	listed <commit> must be the merge itself; the remaining two or
+	more commits should be its parents.  A convenient way to produce
+	the desired set of revisions is to use the {caret}@ suffix.
+	For instance, if `master` names a merge commit, `git diff master
+	master^@` gives the same combined diff as `git show master`.
+
 'git diff' [<options>] <commit>..<commit> [--] [<path>...]::
 
-	This is synonymous to the previous form.  If <commit> on
+	This is synonymous to the earlier form (without the "..") for
+	viewing the changes between two arbitrary <commit>.  If <commit> on
 	one side is omitted, it will have the same effect as
 	using HEAD instead.
 
@@ -196,7 +208,8 @@
 linkgit:git-log[1],
 linkgit:gitdiffcore[7],
 linkgit:git-format-patch[1],
-linkgit:git-apply[1]
+linkgit:git-apply[1],
+linkgit:git-show[1]
 
 GIT
 ---
diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt
index e8950de..1978dbd 100644
--- a/Documentation/git-fast-export.txt
+++ b/Documentation/git-fast-export.txt
@@ -119,6 +119,11 @@
 	the shape of the history and stored tree.  See the section on
 	`ANONYMIZING` below.
 
+--anonymize-map=<from>[:<to>]::
+	Convert token `<from>` to `<to>` in the anonymized output. If
+	`<to>` is omitted, map `<from>` to itself (i.e., do not
+	anonymize it). See the section on `ANONYMIZING` below.
+
 --reference-excluded-parents::
 	By default, running a command such as `git fast-export
 	master~5..master` will not include the commit master{tilde}5
@@ -238,6 +243,30 @@
 smaller output, and it is usually easy to quickly confirm that there is
 no private data in the stream.
 
+Reproducing some bugs may require referencing particular commits or
+paths, which becomes challenging after refnames and paths have been
+anonymized. You can ask for a particular token to be left as-is or
+mapped to a new value. For example, if you have a bug which reproduces
+with `git rev-list sensitive -- secret.c`, you can run:
+
+---------------------------------------------------
+$ git fast-export --anonymize --all \
+      --anonymize-map=sensitive:foo \
+      --anonymize-map=secret.c:bar.c \
+      >stream
+---------------------------------------------------
+
+After importing the stream, you can then run `git rev-list foo -- bar.c`
+in the anonymized repository.
+
+Note that paths and refnames are split into tokens at slash boundaries.
+The command above would anonymize `subdir/secret.c` as something like
+`path123/bar.c`; you could then search for `bar.c` in the anonymized
+repository to determine the final pathname.
+
+To make referencing the final pathname simpler, you can map each path
+component; so if you also anonymize `subdir` to `publicdir`, then the
+final pathname would be `publicdir/bar.c`.
 
 LIMITATIONS
 -----------
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index 5b1909f..45b6d8e 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -255,14 +255,14 @@
 * Using refspecs explicitly:
 +
 ------------------------------------------------
-$ git fetch origin +pu:pu maint:tmp
+$ git fetch origin +seen:seen maint:tmp
 ------------------------------------------------
 +
-This updates (or creates, as necessary) branches `pu` and `tmp` in
+This updates (or creates, as necessary) branches `seen` and `tmp` in
 the local repository by fetching from the branches (respectively)
-`pu` and `maint` from the remote repository.
+`seen` and `maint` from the remote repository.
 +
-The `pu` branch will be updated even if it does not fast-forward,
+The `seen` branch will be updated even if it does not fast-forward,
 because it is prefixed with a plus sign; `tmp` will not be.
 
 * Peek at a remote's branch, without configuring the remote in your local
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 6dcd39f..2ea71c5 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -232,12 +232,27 @@
 `committer`, and `tagger`) can be suffixed with `name`, `email`,
 and `date` to extract the named component.
 
-The complete message in a commit and tag object is `contents`.
-Its first line is `contents:subject`, where subject is the concatenation
-of all lines of the commit message up to the first blank line.  The next
-line is `contents:body`, where body is all of the lines after the first
-blank line.  The optional GPG signature is `contents:signature`.  The
-first `N` lines of the message is obtained using `contents:lines=N`.
+The message in a commit or a tag object is `contents`, from which
+`contents:<part>` can be used to extract various parts out of:
+
+contents:size::
+	The size in bytes of the commit or tag message.
+
+contents:subject::
+	The first paragraph of the message, which typically is a
+	single line, is taken as the "subject" of the commit or the
+	tag message.
+
+contents:body::
+	The remainder of the commit or the tag message that follows
+	the "subject".
+
+contents:signature::
+	The optional GPG signature of the tag.
+
+contents:lines=N::
+	The first `N` lines of the message.
+
 Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1]
 are obtained as `trailers` (or by using the historical alias
 `contents:trailers`).  Non-trailer lines from the trailer block can be omitted
diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt
index f71db0d..69c0c5c 100644
--- a/Documentation/git-help.txt
+++ b/Documentation/git-help.txt
@@ -8,7 +8,7 @@
 SYNOPSIS
 --------
 [verse]
-'git help' [-a|--all [--[no-]verbose]] [-g|--guide]
+'git help' [-a|--all [--[no-]verbose]] [-g|--guides]
 	   [-i|--info|-m|--man|-w|--web] [COMMAND|GUIDE]
 
 DESCRIPTION
@@ -21,7 +21,7 @@
 If the option `--all` or `-a` is given, all available commands are
 printed on the standard output.
 
-If the option `--guide` or `-g` is given, a list of the useful
+If the option `--guides` or `-g` is given, a list of the useful
 Git guides is also printed on the standard output.
 
 If a command, or a guide, is given, a manual page for that command or
diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.txt
index 666b042..4deb489 100644
--- a/Documentation/git-http-fetch.txt
+++ b/Documentation/git-http-fetch.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin] <commit> <url>
+'git http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin | --packfile=<hash> | <commit>] <url>
 
 DESCRIPTION
 -----------
@@ -40,6 +40,13 @@
 
 		<commit-id>['\t'<filename-as-in--w>]
 
+--packfile=<hash>::
+	Instead of a commit id on the command line (which is not expected in
+	this case), 'git http-fetch' fetches the packfile directly at the given
+	URL and uses index-pack to generate corresponding .idx and .keep files.
+	The hash is used to determine the name of the temporary file and is
+	arbitrary. The output of index-pack is printed to stdout.
+
 --recover::
 	Verify that everything reachable from target is fetched.  Used after
 	an earlier fetch is interrupted.
diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt
index d5b7560..ac74d05 100644
--- a/Documentation/git-index-pack.txt
+++ b/Documentation/git-index-pack.txt
@@ -93,11 +93,19 @@
 --max-input-size=<size>::
 	Die, if the pack is larger than <size>.
 
+--object-format=<hash-algorithm>::
+	Specify the given object format (hash algorithm) for the pack.  The valid
+	values are 'sha1' and (if enabled) 'sha256'.  The default is the algorithm for
+	the current repository (set by `extensions.objectFormat`), or 'sha1' if no
+	value is set or outside a repository.
++
+This option cannot be used with --stdin.
+
 NOTES
 -----
 
-Once the index has been created, the list of object names is sorted
-and the SHA-1 hash of that list is printed to stdout. If --stdin was
+Once the index has been created, the hash that goes into the name of
+the pack/idx file is printed to stdout. If --stdin was
 also used then this is prefixed by either "pack\t", or "keep\t" if a
 new .keep file was successfully created. This is useful to remove a
 .keep file used as a lock to prevent the race with 'git repack'
diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index adc6adf..ddfe265 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -10,7 +10,8 @@
 --------
 [verse]
 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
-	  [--separate-git-dir <git dir>] [--object-format=<format]
+	  [--separate-git-dir <git dir>] [--object-format=<format>]
+	  [-b <branch-name> | --initial-branch=<branch-name>]
 	  [--shared[=<permissions>]] [directory]
 
 
@@ -67,6 +68,12 @@
 +
 If this is reinitialization, the repository will be moved to the specified path.
 
+-b <branch-name::
+--initial-branch=<branch-name>::
+
+Use the specified name for the initial branch in the newly created repository.
+If not specified, fall back to the default name: `master`.
+
 --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
 
 Specify that the Git repository is to be shared amongst several users.  This
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 20e6d21..3fd26d5 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -15,9 +15,12 @@
 -----------
 Shows the commit logs.
 
-The command takes options applicable to the `git rev-list`
+:git-log: 1
+include::rev-list-description.txt[]
+
+The command takes options applicable to the linkgit:git-rev-list[1]
 command to control what is shown and how, and options applicable to
-the `git diff-*` commands to control how the changes
+the linkgit:git-diff[1] command to control how the changes
 each commit introduces are shown.
 
 
diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
index 0a5c8b7..492e573 100644
--- a/Documentation/git-ls-remote.txt
+++ b/Documentation/git-ls-remote.txt
@@ -101,9 +101,9 @@
 7ceca275d047c90c0c7d5afb13ab97efdf51bd6e	refs/tags/v0.99.3
 c5db5456ae3b0873fc659c19fafdde22313cc441	refs/tags/v0.99.2
 0918385dbd9656cab0d1d81ba7453d49bbc16250	refs/tags/junio-gpg-pub
-$ git ls-remote http://www.kernel.org/pub/scm/git/git.git master pu rc
+$ git ls-remote http://www.kernel.org/pub/scm/git/git.git master seen rc
 5fe978a5381f1fbad26a80e682ddd2a401966740	refs/heads/master
-c781a84b5204fb294c9ccc79f8b3baceeb32c061	refs/heads/pu
+c781a84b5204fb294c9ccc79f8b3baceeb32c061	refs/heads/seen
 $ git remote add korg http://www.kernel.org/pub/scm/git/git.git
 $ git ls-remote --tags korg v\*
 d6602ec5194c87b0fc87103ca4d67251c76f233a	refs/tags/v0.99
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 4624cfd..374d248 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -259,7 +259,7 @@
 	unchanged as a result. If a temporary stash entry was created
 	using --autostash, it will be saved to the stash list.
 
---apply:
+--apply::
 	Use applying strategies to rebase (calling `git-am`
 	internally).  This option may become a no-op in the future
 	once the merge backend handles everything the apply one does.
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 025c911..5da6623 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -14,44 +14,8 @@
 DESCRIPTION
 -----------
 
-List commits that are reachable by following the `parent` links from the
-given commit(s), but exclude commits that are reachable from the one(s)
-given with a '{caret}' in front of them.  The output is given in reverse
-chronological order by default.
-
-You can think of this as a set operation.  Commits given on the command
-line form a set of commits that are reachable from any of them, and then
-commits reachable from any of the ones given with '{caret}' in front are
-subtracted from that set.  The remaining commits are what comes out in the
-command's output.  Various other options and paths parameters can be used
-to further limit the result.
-
-Thus, the following command:
-
------------------------------------------------------------------------
-	$ git rev-list foo bar ^baz
------------------------------------------------------------------------
-
-means "list all the commits which are reachable from 'foo' or 'bar', but
-not from 'baz'".
-
-A special notation "'<commit1>'..'<commit2>'" can be used as a
-short-hand for "{caret}'<commit1>' '<commit2>'". For example, either of
-the following may be used interchangeably:
-
------------------------------------------------------------------------
-	$ git rev-list origin..HEAD
-	$ git rev-list HEAD ^origin
------------------------------------------------------------------------
-
-Another special notation is "'<commit1>'...'<commit2>'" which is useful
-for merges.  The resulting set of commits is the symmetric difference
-between the two operands.  The following two commands are equivalent:
-
------------------------------------------------------------------------
-	$ git rev-list A B --not $(git merge-base --all A B)
-	$ git rev-list A...B
------------------------------------------------------------------------
+:git-rev-list: 1
+include::rev-list-description.txt[]
 
 'rev-list' is a very essential Git command, since it
 provides the ability to build and traverse commit ancestry graphs. For
diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt
index 424e4ba..39b1d8e 100644
--- a/Documentation/git-show-index.txt
+++ b/Documentation/git-show-index.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git show-index'
+'git show-index' [--object-format=<hash-algorithm>]
 
 
 DESCRIPTION
@@ -36,6 +36,15 @@
 linkgit:git-verify-pack[1]. However, as this command considers only the
 index file itself, it's both faster and more flexible.
 
+OPTIONS
+-------
+
+--object-format=<hash-algorithm>::
+	Specify the given object format (hash algorithm) for the index file.  The
+	valid values are 'sha1' and (if enabled) 'sha256'.  The default is the
+	algorithm for the current repository (set by `extensions.objectFormat`), or
+	'sha1' if no value is set or outside a repository..
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-sparse-checkout.txt b/Documentation/git-sparse-checkout.txt
index 7c8943a..a0eeaeb 100644
--- a/Documentation/git-sparse-checkout.txt
+++ b/Documentation/git-sparse-checkout.txt
@@ -200,10 +200,32 @@
 SUBMODULES
 ----------
 
-If your repository contains one or more submodules, then those submodules will
-appear based on which you initialized with the `git submodule` command. If
-your sparse-checkout patterns exclude an initialized submodule, then that
-submodule will still appear in your working directory.
+If your repository contains one or more submodules, then submodules
+are populated based on interactions with the `git submodule` command.
+Specifically, `git submodule init -- <path>` will ensure the submodule
+at `<path>` is present, while `git submodule deinit [-f] -- <path>`
+will remove the files for the submodule at `<path>` (including any
+untracked files, uncommitted changes, and unpushed history).  Similar
+to how sparse-checkout removes files from the working tree but still
+leaves entries in the index, deinitialized submodules are removed from
+the working directory but still have an entry in the index.
+
+Since submodules may have unpushed changes or untracked files,
+removing them could result in data loss.  Thus, changing sparse
+inclusion/exclusion rules will not cause an already checked out
+submodule to be removed from the working copy.  Said another way, just
+as `checkout` will not cause submodules to be automatically removed or
+initialized even when switching between branches that remove or add
+submodules, using `sparse-checkout` to reduce or expand the scope of
+"interesting" files will not cause submodules to be automatically
+deinitialized or initialized either.
+
+Further, the above facts mean that there are multiple reasons that
+"tracked" files might not be present in the working copy: sparsity
+pattern application from sparse-checkout, and submodule initialization
+state.  Thus, commands like `git grep` that work on tracked files in
+the working copy may return results that are limited by either or both
+of these restrictions.
 
 
 SEE ALSO
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index c9ed2bf..7e5f995 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -183,7 +183,7 @@
 	Sets the default remote tracking branch for the submodule. The
 	`--branch` option allows the remote branch to be specified. The
 	`--default` option removes the submodule.<name>.branch configuration
-	key, which causes the tracking branch to default to 'master'.
+	key, which causes the tracking branch to default to the remote 'HEAD'.
 
 set-url [--] <path> <newurl>::
 	Sets the URL of the specified submodule to <newurl>. Then, it will
@@ -284,7 +284,7 @@
 	`.gitmodules` for `update --remote`.  A special value of `.` is used to
 	indicate that the name of the branch in the submodule should be the
 	same name as the current branch in the current repository.  If the
-	option is not specified, it defaults to 'master'.
+	option is not specified, it defaults to the remote 'HEAD'.
 
 -f::
 --force::
@@ -322,10 +322,10 @@
 	the superproject's recorded SHA-1 to update the submodule, use the
 	status of the submodule's remote-tracking branch.  The remote used
 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
-	The remote branch used defaults to `master`, but the branch name may
-	be overridden by setting the `submodule.<name>.branch` option in
-	either `.gitmodules` or `.git/config` (with `.git/config` taking
-	precedence).
+	The remote branch used defaults to the remote `HEAD`, but the branch
+	name may be overridden by setting the `submodule.<name>.branch`
+	option in either `.gitmodules` or `.git/config` (with `.git/config`
+	taking precedence).
 +
 This works for any of the supported update procedures (`--checkout`,
 `--rebase`, etc.).  The only change is the source of the target SHA-1.
diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
index 85d92c9..4796c3c 100644
--- a/Documentation/git-worktree.txt
+++ b/Documentation/git-worktree.txt
@@ -126,7 +126,9 @@
 	locked working tree path, specify `--force` twice.
 +
 `move` refuses to move a locked working tree unless `--force` is specified
-twice.
+twice. If the destination is already assigned to some other working tree but is
+missing (for instance, if `<new-path>` was deleted manually), then `--force`
+allows the move to proceed; use --force twice if the destination is locked.
 +
 `remove` refuses to remove an unclean working tree unless `--force` is used.
 To remove a locked working tree, specify `--force` twice.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 40bd32f..3e50065 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -775,11 +775,10 @@
 	See `GIT_TRACE2` for available trace output options and
 	link:technical/api-trace2.html[Trace2 documentation] for full details.
 
-`GIT_REDACT_COOKIES`::
-	This can be set to a comma-separated list of strings. When a curl trace
-	is enabled (see `GIT_TRACE_CURL` above), whenever a "Cookies:" header
-	sent by the client is dumped, values of cookies whose key is in that
-	list (case-sensitive) are redacted.
+`GIT_TRACE_REDACT`::
+	By default, when tracing is activated, Git redacts the values of
+	cookies, the "Authorization:" header, and the "Proxy-Authorization:"
+	header. Set this variable to `0` to prevent this redaction.
 
 `GIT_LITERAL_PATHSPECS`::
 	Setting this variable to `1` will cause Git to treat all
diff --git a/Documentation/giteveryday.txt b/Documentation/giteveryday.txt
index 1bd919f..faba2ef 100644
--- a/Documentation/giteveryday.txt
+++ b/Documentation/giteveryday.txt
@@ -278,13 +278,13 @@
 $ compile/test
 $ git switch -c hold/linus && git am -3 -i -s ./+hold-linus <5>
 $ git switch topic/one && git rebase master <6>
-$ git switch -C pu next <7>
+$ git switch -C seen next <7>
 $ git merge topic/one topic/two && git merge hold/linus <8>
 $ git switch maint
 $ git cherry-pick master~4 <9>
 $ compile/test
 $ git tag -s -m "GIT 0.99.9x" v0.99.9x <10>
-$ git fetch ko && for branch in master maint next pu <11>
+$ git fetch ko && for branch in master maint next seen <11>
     do
 	git show-branch ko/$branch $branch <12>
     done
@@ -294,14 +294,14 @@
 <1> see what you were in the middle of doing, if anything.
 <2> see which branches haven't been merged into `master` yet.
 Likewise for any other integration branches e.g. `maint`, `next`
-and `pu` (potential updates).
+and `seen`.
 <3> read mails, save ones that are applicable, and save others
 that are not quite ready (other mail readers are available).
 <4> apply them, interactively, with your sign-offs.
 <5> create topic branch as needed and apply, again with sign-offs.
 <6> rebase internal topic branch that has not been merged to the
 master or exposed as a part of a stable branch.
-<7> restart `pu` every time from the next.
+<7> restart `seen` every time from the next.
 <8> and bundle topic branches still cooking.
 <9> backport a critical fix.
 <10> create a signed tag.
@@ -323,7 +323,7 @@
 	fetch = refs/heads/*:refs/remotes/ko/*
 	push = refs/heads/master
 	push = refs/heads/next
-	push = +refs/heads/pu
+	push = +refs/heads/seen
 	push = refs/heads/maint
 ------------
 
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 81f2a87..31b601e 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -404,6 +404,35 @@
 `git send-pack` on the other end, so you can simply `echo` messages
 for the user.
 
+reference-transaction
+~~~~~~~~~~~~~~~~~~~~~
+
+This hook is invoked by any Git command that performs reference
+updates. It executes whenever a reference transaction is prepared,
+committed or aborted and may thus get called multiple times.
+
+The hook takes exactly one argument, which is the current state the
+given reference transaction is in:
+
+    - "prepared": All reference updates have been queued to the
+      transaction and references were locked on disk.
+
+    - "committed": The reference transaction was committed and all
+      references now have their respective new value.
+
+    - "aborted": The reference transaction was aborted, no changes
+      were performed and the locks have been released.
+
+For each reference update that was added to the transaction, the hook
+receives on standard input a line of the format:
+
+  <old-value> SP <new-value> SP <ref-name> LF
+
+The exit status of the hook is ignored for any state except for the
+"prepared" state. In the "prepared" state, a non-zero exit status will
+cause the transaction to be aborted. The hook will not be called with
+"aborted" state in that case.
+
 push-to-checkout
 ~~~~~~~~~~~~~~~~
 
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index 67275fd..539b4e1 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -49,9 +49,9 @@
 
 submodule.<name>.branch::
 	A remote branch name for tracking updates in the upstream submodule.
-	If the option is not specified, it defaults to 'master'.  A special
-	value of `.` is used to indicate that the name of the branch in the
-	submodule should be the same name as the current branch in the
+	If the option is not specified, it defaults to the remote 'HEAD'.
+	A special value of `.` is used to indicate that the name of the branch
+	in the submodule should be the same name as the current branch in the
 	current repository.  See the `--remote` documentation in
 	linkgit:git-submodule[1] for details.
 
diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt
index 93baeeb..6f1e269 100644
--- a/Documentation/gitremote-helpers.txt
+++ b/Documentation/gitremote-helpers.txt
@@ -238,6 +238,9 @@
 	`--signed-tags=verbatim` to linkgit:git-fast-export[1].  In the
 	absence of this capability, Git will use `--signed-tags=warn-strip`.
 
+'object-format'::
+	This indicates that the helper is able to interact with the remote
+	side using an explicit hash algorithm extension.
 
 
 COMMANDS
@@ -257,12 +260,14 @@
 'list'::
 	Lists the refs, one per line, in the format "<value> <name>
 	[<attr> ...]". The value may be a hex sha1 hash, "@<dest>" for
-	a symref, or "?" to indicate that the helper could not get the
-	value of the ref. A space-separated list of attributes follows
-	the name; unrecognized attributes are ignored. The list ends
-	with a blank line.
+	a symref, ":<keyword> <value>" for a key-value pair, or
+	"?" to indicate that the helper could not get the value of the
+	ref. A space-separated list of attributes follows the name;
+	unrecognized attributes are ignored. The list ends with a
+	blank line.
 +
 See REF LIST ATTRIBUTES for a list of currently defined attributes.
+See REF LIST KEYWORDS for a list of currently defined keywords.
 +
 Supported if the helper has the "fetch" or "import" capability.
 
@@ -432,6 +437,18 @@
 	This ref is unchanged since the last import or fetch, although
 	the helper cannot necessarily determine what value that produced.
 
+REF LIST KEYWORDS
+-----------------
+
+The 'list' command may produce a list of key-value pairs.
+The following keys are defined.
+
+'object-format'::
+	The refs are using the given hash algorithm.  This keyword is only
+	used if the server and client both support the object-format
+	extension.
+
+
 OPTIONS
 -------
 
@@ -516,6 +533,14 @@
 	transaction.  If successful, all refs will be updated, or none will.  If the
 	remote side does not support this capability, the push will fail.
 
+'option object-format' {'true'|algorithm}::
+	If 'true', indicate that the caller wants hash algorithm information
+	to be passed back from the remote.  This mode is used when fetching
+	refs.
++
+If set to an algorithm, indicate that the caller wants to interact with
+the remote side using that algorithm.
+
 SEE ALSO
 --------
 linkgit:git-remote[1]
diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt
index abc0dc6..47cf97f 100644
--- a/Documentation/gitworkflows.txt
+++ b/Documentation/gitworkflows.txt
@@ -85,15 +85,15 @@
 
 There is a fourth official branch that is used slightly differently:
 
-* 'pu' (proposed updates) is an integration branch for things that are
-  not quite ready for inclusion yet (see "Integration Branches"
-  below).
+* 'seen' (patches seen by the maintainer) is an integration branch for
+  things that are not quite ready for inclusion yet (see "Integration
+  Branches" below).
 
 Each of the four branches is usually a direct descendant of the one
 above it.
 
 Conceptually, the feature enters at an unstable branch (usually 'next'
-or 'pu'), and "graduates" to 'master' for the next release once it is
+or 'seen'), and "graduates" to 'master' for the next release once it is
 considered stable enough.
 
 
@@ -207,7 +207,7 @@
 right after the testing, you can even publish this branch, for example
 to give the testers a chance to work with it, or other developers a
 chance to see if their in-progress work will be compatible.  `git.git`
-has such an official throw-away integration branch called 'pu'.
+has such an official throw-away integration branch called 'seen'.
 
 
 Branch management for a release
@@ -291,8 +291,8 @@
 described in the previous section.
 
 
-Branch management for next and pu after a feature release
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Branch management for next and seen after a feature release
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 After a feature release, the integration branch 'next' may optionally be
 rewound and rebuilt from the tip of 'master' using the surviving
@@ -319,8 +319,8 @@
 If you do this, then you should make a public announcement indicating
 that 'next' was rewound and rebuilt.
 
-The same rewind and rebuild process may be followed for 'pu'. A public
-announcement is not necessary since 'pu' is a throw-away branch, as
+The same rewind and rebuild process may be followed for 'seen'. A public
+announcement is not necessary since 'seen' is a throw-away branch, as
 described above.
 
 
diff --git a/Documentation/howto/maintain-git.txt b/Documentation/howto/maintain-git.txt
index 73be8b4..a67130d 100644
--- a/Documentation/howto/maintain-git.txt
+++ b/Documentation/howto/maintain-git.txt
@@ -66,7 +66,7 @@
    demonstrated to be regression free.  New changes are tested
    in 'next' before merged to 'master'.
 
- - 'pu' branch is used to publish other proposed changes that do
+ - 'seen' branch is used to publish other proposed changes that do
    not yet pass the criteria set for 'next'.
 
  - The tips of 'master' and 'maint' branches will not be rewound to
@@ -76,7 +76,7 @@
    of the cycle.
 
  - Usually 'master' contains all of 'maint' and 'next' contains all
-   of 'master'.  'pu' contains all the topics merged to 'next', but
+   of 'master'.  'seen' contains all the topics merged to 'next', but
    is rebuilt directly on 'master'.
 
  - The tip of 'master' is meant to be more stable than any
@@ -229,12 +229,12 @@
    series?)
 
  - Prepare 'jch' branch, which is used to represent somewhere
-   between 'master' and 'pu' and often is slightly ahead of 'next'.
+   between 'master' and 'seen' and often is slightly ahead of 'next'.
 
-     $ Meta/Reintegrate master..pu >Meta/redo-jch.sh
+     $ Meta/Reintegrate master..seen >Meta/redo-jch.sh
 
    The result is a script that lists topics to be merged in order to
-   rebuild 'pu' as the input to Meta/Reintegrate script.  Remove
+   rebuild 'seen' as the input to Meta/Reintegrate script.  Remove
    later topics that should not be in 'jch' yet.  Add a line that
    consists of '### match next' before the name of the first topic
    in the output that should be in 'jch' but not in 'next' yet.
@@ -291,29 +291,29 @@
    merged to 'master'.  This may lose '### match next' marker;
    add it again to the appropriate place when it happens.
 
- - Rebuild 'pu'.
+ - Rebuild 'seen'.
 
-     $ Meta/Reintegrate master..pu >Meta/redo-pu.sh
+     $ Meta/Reintegrate master..seen >Meta/redo-seen.sh
 
-   Edit the result by adding new topics that are not still in 'pu'
+   Edit the result by adding new topics that are not still in 'seen'
    in the script.  Then
 
-     $ git checkout -B pu jch
-     $ sh Meta/redo-pu.sh
+     $ git checkout -B seen jch
+     $ sh Meta/redo-seen.sh
 
-   When all is well, clean up the redo-pu.sh script with
+   When all is well, clean up the redo-seen.sh script with
 
-     $ sh Meta/redo-pu.sh -u
+     $ sh Meta/redo-seen.sh -u
 
    Double check by running
 
-     $ git branch --no-merged pu
+     $ git branch --no-merged seen
 
    to see there is no unexpected leftover topics.
 
    At this point, build-test the result for semantic conflicts, and
    if there are, prepare an appropriate merge-fix first (see
-   appendix), and rebuild the 'pu' branch from scratch, starting at
+   appendix), and rebuild the 'seen' branch from scratch, starting at
    the tip of 'jch'.
 
  - Update "What's cooking" message to review the updates to
@@ -323,14 +323,14 @@
 
      $ Meta/cook
 
-   This script inspects the history between master..pu, finds tips
+   This script inspects the history between master..seen, finds tips
    of topic branches, compares what it found with the current
    contents in Meta/whats-cooking.txt, and updates that file.
-   Topics not listed in the file but are found in master..pu are
+   Topics not listed in the file but are found in master..seen are
    added to the "New topics" section, topics listed in the file that
-   are no longer found in master..pu are moved to the "Graduated to
+   are no longer found in master..seen are moved to the "Graduated to
    master" section, and topics whose commits changed their states
-   (e.g. used to be only in 'pu', now merged to 'next') are updated
+   (e.g. used to be only in 'seen', now merged to 'next') are updated
    with change markers "<<" and ">>".
 
    Look for lines enclosed in "<<" and ">>"; they hold contents from
@@ -360,7 +360,7 @@
 Some observations to be made.
 
  * Each topic is tested individually, and also together with other
-   topics cooking first in 'pu', then in 'jch' and then in 'next'.
+   topics cooking first in 'seen', then in 'jch' and then in 'next'.
    Until it matures, no part of it is merged to 'master'.
 
  * A topic already in 'next' can get fixes while still in
@@ -411,7 +411,7 @@
 are merged together, the reference to the variable newly added by
 the latter topic will still use the old name in the result.
 
-The Meta/Reintegrate script that is used by redo-jch and redo-pu
+The Meta/Reintegrate script that is used by redo-jch and redo-seen
 scripts implements a crude but usable way to work this issue around.
 When the script merges branch $X, it checks if "refs/merge-fix/$X"
 exists, and if so, the effect of it is squashed into the result of
@@ -431,14 +431,14 @@
 correct semantic conflicts.
 
 After finding that the result of merging branch "ai/topic" to an
-integration branch had such a semantic conflict, say pu~4, check the
+integration branch had such a semantic conflict, say seen~4, check the
 problematic merge out on a detached HEAD, edit the working tree to
 fix the semantic conflict, and make a separate commit to record the
 fix-up:
 
-     $ git checkout pu~4
+     $ git checkout seen~4
      $ git show -s --pretty=%s ;# double check
-     Merge branch 'ai/topic' to pu
+     Merge branch 'ai/topic' to seen
      $ edit
      $ git commit -m 'merge-fix/ai/topic' -a
 
@@ -450,9 +450,9 @@
 Then double check the result by asking Meta/Reintegrate to redo the
 merge:
 
-     $ git checkout pu~5 ;# the parent of the problem merge
+     $ git checkout seen~5 ;# the parent of the problem merge
      $ echo ai/topic | Meta/Reintegrate
-     $ git diff pu~4
+     $ git diff seen~4
 
 This time, because you prepared refs/merge-fix/ai/topic, the
 resulting merge should have been tweaked to include the fix for the
@@ -464,7 +464,7 @@
 to the integration branch changed the underlying assumption ai/topic
 branch made (e.g. ai/topic branch added a site to refer to a
 variable, while the other branch renamed that variable and adjusted
-existing use sites), and if you changed redo-jch (or redo-pu) script
+existing use sites), and if you changed redo-jch (or redo-seen) script
 to merge ai/topic branch before the other branch, then the above
 merge-fix should not be applied while merging ai/topic, but should
 instead be applied while merging the other branch.  You would need
diff --git a/Documentation/howto/rebase-from-internal-branch.txt b/Documentation/howto/rebase-from-internal-branch.txt
index 02cb5f7..f2e10a7 100644
--- a/Documentation/howto/rebase-from-internal-branch.txt
+++ b/Documentation/howto/rebase-from-internal-branch.txt
@@ -4,7 +4,7 @@
 Subject: Re: sending changesets from the middle of a git tree
 Date:	Sun, 14 Aug 2005 18:37:39 -0700
 Abstract: In this article, JC talks about how he rebases the
- public "pu" branch using the core Git tools when he updates
+ public "seen" branch using the core Git tools when he updates
  the "master" branch, and how "rebase" works.  Also discussed
  is how this applies to individual developers who sends patches
  upstream.
@@ -20,8 +20,8 @@
 > where Junio C Hamano <junkio@cox.net> told me that...
 >> Linus Torvalds <torvalds@osdl.org> writes:
 >>
->> > Junio, maybe you want to talk about how you move patches from your "pu"
->> > branch to the real branches.
+>> > Junio, maybe you want to talk about how you move patches from your
+>> > "seen" branch to the real branches.
 >>
 > Actually, wouldn't this be also precisely for what StGIT is intended to?
 --------------------------------------
@@ -33,12 +33,12 @@
 I just have done a simpler one, this time using only the core
 Git tools.
 
-I had a handful of commits that were ahead of master in pu, and I
+I had a handful of commits that were ahead of master in 'seen', and I
 wanted to add some documentation bypassing my usual habit of
-placing new things in pu first.  At the beginning, the commit
+placing new things in 'seen' first.  At the beginning, the commit
 ancestry graph looked like this:
 
-                             *"pu" head
+			     *"seen" head
     master --> #1 --> #2 --> #3
 
 So I started from master, made a bunch of edits, and committed:
@@ -50,7 +50,7 @@
 
 After the commit, the ancestry graph would look like this:
 
-                              *"pu" head
+			      *"seen" head
     master^ --> #1 --> #2 --> #3
           \
             \---> master
@@ -58,31 +58,31 @@
 The old master is now master^ (the first parent of the master).
 The new master commit holds my documentation updates.
 
-Now I have to deal with "pu" branch.
+Now I have to deal with "seen" branch.
 
 This is the kind of situation I used to have all the time when
 Linus was the maintainer and I was a contributor, when you look
-at "master" branch being the "maintainer" branch, and "pu"
+at "master" branch being the "maintainer" branch, and "seen"
 branch being the "contributor" branch.  Your work started at the
 tip of the "maintainer" branch some time ago, you made a lot of
 progress in the meantime, and now the maintainer branch has some
 other commits you do not have yet.  And "git rebase" was written
 with the explicit purpose of helping to maintain branches like
-"pu".  You _could_ merge master to pu and keep going, but if you
+"seen".  You _could_ merge master to 'seen' and keep going, but if you
 eventually want to cherrypick and merge some but not necessarily
 all changes back to the master branch, it often makes later
 operations for _you_ easier if you rebase (i.e. carry forward
-your changes) "pu" rather than merge.  So I ran "git rebase":
+your changes) "seen" rather than merge.  So I ran "git rebase":
 
-    $ git checkout pu
-    $ git rebase master pu
+    $ git checkout seen
+    $ git rebase master seen
 
 What this does is to pick all the commits since the current
-branch (note that I now am on "pu" branch) forked from the
+branch (note that I now am on "seen" branch) forked from the
 master branch, and forward port these changes.
 
     master^ --> #1 --> #2 --> #3
-          \                                  *"pu" head
+	  \                                  *"seen" head
             \---> master --> #1' --> #2' --> #3'
 
 The diff between master^ and #1 is applied to master and
@@ -92,7 +92,7 @@
 
 Old #3 is not recorded in any of the .git/refs/heads/ file
 anymore, so after doing this you will have dangling commit if
-you ran fsck-cache, which is normal.  After testing "pu", you
+you ran fsck-cache, which is normal.  After testing "seen", you
 can run "git prune" to get rid of those original three commits.
 
 While I am talking about "git rebase", I should talk about how
diff --git a/Documentation/howto/revert-branch-rebase.txt b/Documentation/howto/revert-branch-rebase.txt
index 149508e..a3e5595 100644
--- a/Documentation/howto/revert-branch-rebase.txt
+++ b/Documentation/howto/revert-branch-rebase.txt
@@ -15,7 +15,7 @@
 break building Git with GCC 2.95.  While they were well-intentioned
 portability fixes, keeping things working with gcc-2.95 was also
 important.  Here is what I did to revert the change in the 'master'
-branch and to adjust the 'pu' branch, using core Git tools and
+branch and to adjust the 'seen' branch, using core Git tools and
 barebone Porcelain.
 
 First, prepare a throw-away branch in case I screw things up.
@@ -104,11 +104,11 @@
 
 says nothing.
 
-Then we rebase the 'pu' branch as usual.
+Then we rebase the 'seen' branch as usual.
 
 ------------------------------------------------
-$ git checkout pu
-$ git tag pu-anchor pu
+$ git checkout seen
+$ git tag seen-anchor seen
 $ git rebase master
 * Applying: Redo "revert" using three-way merge machinery.
 First trying simple merge strategy to cherry-pick.
@@ -127,11 +127,11 @@
 First trying simple merge strategy to cherry-pick.
 ------------------------------------------------
 
-The temporary tag 'pu-anchor' is me just being careful, in case 'git
+The temporary tag 'seen-anchor' is me just being careful, in case 'git
 rebase' screws up.  After this, I can do these for sanity check:
 
 ------------------------------------------------
-$ git diff pu-anchor..pu ;# make sure we got the master fix.
+$ git diff seen-anchor..seen ;# make sure we got the master fix.
 $ make CC=gcc-2.95 clean test ;# make sure it fixed the breakage.
 $ make clean test ;# make sure it did not cause other breakage.
 ------------------------------------------------
@@ -140,7 +140,7 @@
 or tag anymore, so remove them:
 
 ------------------------------------------------
-$ rm -f .git/refs/tags/pu-anchor
+$ rm -f .git/refs/tags/seen-anchor
 $ git branch -d revert-c99
 ------------------------------------------------
 
@@ -168,18 +168,18 @@
 And the final repository status looks like this:
 
 ------------------------------------------------
-$ git show-branch --more=1 master pu rc
+$ git show-branch --more=1 master seen rc
 ! [master] Revert "Replace zero-length array decls with []."
- ! [pu] git-repack: Add option to repack all objects.
+ ! [seen] git-repack: Add option to repack all objects.
   * [rc] Merge refs/heads/master from .
 ---
- +  [pu] git-repack: Add option to repack all objects.
- +  [pu~1] More documentation updates.
- +  [pu~2] Show commits in topo order and name all commits.
- +  [pu~3] mailinfo and applymbox updates
- +  [pu~4] Document "git cherry-pick" and "git revert"
- +  [pu~5] Remove git-apply-patch-script.
- +  [pu~6] Redo "revert" using three-way merge machinery.
+ +  [seen] git-repack: Add option to repack all objects.
+ +  [seen~1] More documentation updates.
+ +  [seen~2] Show commits in topo order and name all commits.
+ +  [seen~3] mailinfo and applymbox updates
+ +  [seen~4] Document "git cherry-pick" and "git revert"
+ +  [seen~5] Remove git-apply-patch-script.
+ +  [seen~6] Redo "revert" using three-way merge machinery.
   - [rc] Merge refs/heads/master from .
 ++* [master] Revert "Replace zero-length array decls with []."
   - [rc~1] Merge refs/heads/master from .
diff --git a/Documentation/howto/update-hook-example.txt b/Documentation/howto/update-hook-example.txt
index 89821ec..151ee84 100644
--- a/Documentation/howto/update-hook-example.txt
+++ b/Documentation/howto/update-hook-example.txt
@@ -179,7 +179,7 @@
 whom.  The format of each file would look like this:
 
     refs/heads/master   junio
-    +refs/heads/pu      junio
+    +refs/heads/seen    junio
     refs/heads/cogito$  pasky
     refs/heads/bw/.*    linus
     refs/heads/tmp/.*   .*
@@ -187,6 +187,6 @@
 
 With this, Linus can push or create "bw/penguin" or "bw/zebra"
 or "bw/panda" branches, Pasky can do only "cogito", and JC can
-do master and pu branches and make versioned tags.  And anybody
-can do tmp/blah branches. The '+' sign at the pu record means
+do master and "seen" branches and make versioned tags.  And anybody
+can do tmp/blah branches. The '+' sign at the "seen" record means
 that JC can make non-fast-forward pushes on it.
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 547a552..84bbc74 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -196,8 +196,8 @@
 '%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
+'%cl':: committer email local-part (the part before the '@' sign)
+'%cL':: committer 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
diff --git a/Documentation/rev-list-description.txt b/Documentation/rev-list-description.txt
new file mode 100644
index 0000000..a9efa7f
--- /dev/null
+++ b/Documentation/rev-list-description.txt
@@ -0,0 +1,61 @@
+List commits that are reachable by following the `parent` links from the
+given commit(s), but exclude commits that are reachable from the one(s)
+given with a '{caret}' in front of them.  The output is given in reverse
+chronological order by default.
+
+You can think of this as a set operation. Commits reachable from any of
+the commits given on the command line form a set, and then commits reachable
+from any of the ones given with '{caret}' in front are subtracted from that
+set.  The remaining commits are what comes out in the command's output.
+Various other options and paths parameters can be used to further limit the
+result.
+
+Thus, the following command:
+
+ifdef::git-rev-list[]
+-----------------------------------------------------------------------
+$ git rev-list foo bar ^baz
+-----------------------------------------------------------------------
+endif::git-rev-list[]
+ifdef::git-log[]
+-----------------------------------------------------------------------
+$ git log foo bar ^baz
+-----------------------------------------------------------------------
+endif::git-log[]
+
+means "list all the commits which are reachable from 'foo' or 'bar', but
+not from 'baz'".
+
+A special notation "'<commit1>'..'<commit2>'" can be used as a
+short-hand for "^'<commit1>' '<commit2>'". For example, either of
+the following may be used interchangeably:
+
+ifdef::git-rev-list[]
+-----------------------------------------------------------------------
+$ git rev-list origin..HEAD
+$ git rev-list HEAD ^origin
+-----------------------------------------------------------------------
+endif::git-rev-list[]
+ifdef::git-log[]
+-----------------------------------------------------------------------
+$ git log origin..HEAD
+$ git log HEAD ^origin
+-----------------------------------------------------------------------
+endif::git-log[]
+
+Another special notation is "'<commit1>'...'<commit2>'" which is useful
+for merges.  The resulting set of commits is the symmetric difference
+between the two operands.  The following two commands are equivalent:
+
+ifdef::git-rev-list[]
+-----------------------------------------------------------------------
+$ git rev-list A B --not $(git merge-base --all A B)
+$ git rev-list A...B
+-----------------------------------------------------------------------
+endif::git-rev-list[]
+ifdef::git-log[]
+-----------------------------------------------------------------------
+$ git log A B --not $(git merge-base --all A B)
+$ git log A...B
+-----------------------------------------------------------------------
+endif::git-log[]
diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt
index 1ad9506..d9169c0 100644
--- a/Documentation/revisions.txt
+++ b/Documentation/revisions.txt
@@ -254,6 +254,9 @@
 previous section, means the set of commits `reachable` from the given
 commit.
 
+Specifying several revisions means the set of commits reachable from
+any of the given commits.
+
 A commit's reachable set is the commit itself and the commits in
 its ancestry chain.
 
diff --git a/Documentation/technical/commit-graph-format.txt b/Documentation/technical/commit-graph-format.txt
index 1beef17..4405410 100644
--- a/Documentation/technical/commit-graph-format.txt
+++ b/Documentation/technical/commit-graph-format.txt
@@ -32,7 +32,7 @@
 of the body. The header includes certain values, such as number of chunks
 and hash type.
 
-All 4-byte numbers are in network order.
+All multi-byte numbers are in network byte order.
 
 HEADER:
 
diff --git a/Documentation/technical/packfile-uri.txt b/Documentation/technical/packfile-uri.txt
new file mode 100644
index 0000000..318713a
--- /dev/null
+++ b/Documentation/technical/packfile-uri.txt
@@ -0,0 +1,78 @@
+Packfile URIs
+=============
+
+This feature allows servers to serve part of their packfile response as URIs.
+This allows server designs that improve scalability in bandwidth and CPU usage
+(for example, by serving some data through a CDN), and (in the future) provides
+some measure of resumability to clients.
+
+This feature is available only in protocol version 2.
+
+Protocol
+--------
+
+The server advertises the `packfile-uris` capability.
+
+If the client then communicates which protocols (HTTPS, etc.) it supports with
+a `packfile-uris` argument, the server MAY send a `packfile-uris` section
+directly before the `packfile` section (right after `wanted-refs` if it is
+sent) containing URIs of any of the given protocols. The URIs point to
+packfiles that use only features that the client has declared that it supports
+(e.g. ofs-delta and thin-pack). See protocol-v2.txt for the documentation of
+this section.
+
+Clients should then download and index all the given URIs (in addition to
+downloading and indexing the packfile given in the `packfile` section of the
+response) before performing the connectivity check.
+
+Server design
+-------------
+
+The server can be trivially made compatible with the proposed protocol by
+having it advertise `packfile-uris`, tolerating the client sending
+`packfile-uris`, and never sending any `packfile-uris` section. But we should
+include some sort of non-trivial implementation in the Minimum Viable Product,
+at least so that we can test the client.
+
+This is the implementation: a feature, marked experimental, that allows the
+server to be configured by one or more `uploadpack.blobPackfileUri=<sha1>
+<uri>` entries. Whenever the list of objects to be sent is assembled, all such
+blobs are excluded, replaced with URIs. The client will download those URIs,
+expecting them to each point to packfiles containing single blobs.
+
+Client design
+-------------
+
+The client has a config variable `fetch.uriprotocols` that determines which
+protocols the end user is willing to use. By default, this is empty.
+
+When the client downloads the given URIs, it should store them with "keep"
+files, just like it does with the packfile in the `packfile` section. These
+additional "keep" files can only be removed after the refs have been updated -
+just like the "keep" file for the packfile in the `packfile` section.
+
+The division of work (initial fetch + additional URIs) introduces convenient
+points for resumption of an interrupted clone - such resumption can be done
+after the Minimum Viable Product (see "Future work").
+
+Future work
+-----------
+
+The protocol design allows some evolution of the server and client without any
+need for protocol changes, so only a small-scoped design is included here to
+form the MVP. For example, the following can be done:
+
+ * On the server, more sophisticated means of excluding objects (e.g. by
+   specifying a commit to represent that commit and all objects that it
+   references).
+ * On the client, resumption of clone. If a clone is interrupted, information
+   could be recorded in the repository's config and a "clone-resume" command
+   can resume the clone in progress. (Resumption of subsequent fetches is more
+   difficult because that must deal with the user wanting to use the repository
+   even after the fetch was interrupted.)
+
+There are some possible features that will require a change in protocol:
+
+ * Additional HTTP headers (e.g. authentication)
+ * Byte range support
+ * Different file formats referenced by URIs (e.g. raw object)
diff --git a/Documentation/technical/protocol-capabilities.txt b/Documentation/technical/protocol-capabilities.txt
index 2b267c0..36ccd14 100644
--- a/Documentation/technical/protocol-capabilities.txt
+++ b/Documentation/technical/protocol-capabilities.txt
@@ -176,6 +176,21 @@
 purposes, and MUST NOT be used to programmatically assume the presence
 or absence of particular features.
 
+object-format
+-------------
+
+This capability, which takes a hash algorithm as an argument, indicates
+that the server supports the given hash algorithms.  It may be sent
+multiple times; if so, the first one given is the one used in the ref
+advertisement.
+
+When provided by the client, this indicates that it intends to use the
+given hash algorithm to communicate.  The algorithm provided must be one
+that the server supports.
+
+If this capability is not provided, it is assumed that the only
+supported algorithm is SHA-1.
+
 symref
 ------
 
diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt
index 3996d70..e597b74 100644
--- a/Documentation/technical/protocol-v2.txt
+++ b/Documentation/technical/protocol-v2.txt
@@ -325,13 +325,26 @@
 	indicating its sideband (1, 2, or 3), and the server may send "0005\2"
 	(a PKT-LINE of sideband 2 with no payload) as a keepalive packet.
 
+If the 'packfile-uris' feature is advertised, the following argument
+can be included in the client's request as well as the potential
+addition of the 'packfile-uris' section in the server's response as
+explained below.
+
+    packfile-uris <comma-separated list of protocols>
+	Indicates to the server that the client is willing to receive
+	URIs of any of the given protocols in place of objects in the
+	sent packfile. Before performing the connectivity check, the
+	client should download from all given URIs. Currently, the
+	protocols supported are "http" and "https".
+
 The response of `fetch` is broken into a number of sections separated by
 delimiter packets (0001), with each section beginning with its section
-header.
+header. Most sections are sent only when the packfile is sent.
 
-    output = *section
-    section = (acknowledgments | shallow-info | wanted-refs | packfile)
-	      (flush-pkt | delim-pkt)
+    output = acknowledgements flush-pkt |
+	     [acknowledgments delim-pkt] [shallow-info delim-pkt]
+	     [wanted-refs delim-pkt] [packfile-uris delim-pkt]
+	     packfile flush-pkt
 
     acknowledgments = PKT-LINE("acknowledgments" LF)
 		      (nak | *ack)
@@ -349,13 +362,17 @@
 		  *PKT-LINE(wanted-ref LF)
     wanted-ref = obj-id SP refname
 
+    packfile-uris = PKT-LINE("packfile-uris" LF) *packfile-uri
+    packfile-uri = PKT-LINE(40*(HEXDIGIT) SP *%x20-ff LF)
+
     packfile = PKT-LINE("packfile" LF)
 	       *PKT-LINE(%x01-03 *%x00-ff)
 
     acknowledgments section
-	* If the client determines that it is finished with negotiations
-	  by sending a "done" line, the acknowledgments sections MUST be
-	  omitted from the server's response.
+	* If the client determines that it is finished with negotiations by
+	  sending a "done" line (thus requiring the server to send a packfile),
+	  the acknowledgments sections MUST be omitted from the server's
+	  response.
 
 	* Always begins with the section header "acknowledgments"
 
@@ -406,9 +423,6 @@
 	  which the client has not indicated was shallow as a part of
 	  its request.
 
-	* This section is only included if a packfile section is also
-	  included in the response.
-
     wanted-refs section
 	* This section is only included if the client has requested a
 	  ref using a 'want-ref' line and if a packfile section is also
@@ -422,6 +436,20 @@
 	* The server MUST NOT send any refs which were not requested
 	  using 'want-ref' lines.
 
+    packfile-uris section
+	* This section is only included if the client sent
+	  'packfile-uris' and the server has at least one such URI to
+	  send.
+
+	* Always begins with the section header "packfile-uris".
+
+	* For each URI the server sends, it sends a hash of the pack's
+	  contents (as output by git index-pack) followed by the URI.
+
+	* The hashes are 40 hex characters long. When Git upgrades to a new
+	  hash algorithm, this might need to be updated. (It should match
+	  whatever index-pack outputs after "pack\t" or "keep\t".
+
     packfile section
 	* This section is only included if the client has sent 'want'
 	  lines in its request and either requested that no more
@@ -455,3 +483,12 @@
 a request.
 
 The provided options must not contain a NUL or LF character.
+
+ object-format
+~~~~~~~~~~~~~~~
+
+The server can advertise the `object-format` capability with a value `X` (in the
+form `object-format=X`) to notify the client that the server is able to deal
+with objects using hash algorithm X.  If not specified, the server is assumed to
+only handle SHA-1.  If the client would like to use a hash algorithm other than
+SHA-1, it should specify its object-format string.
diff --git a/Documentation/technical/reftable.txt b/Documentation/technical/reftable.txt
new file mode 100644
index 0000000..2951840
--- /dev/null
+++ b/Documentation/technical/reftable.txt
@@ -0,0 +1,1083 @@
+reftable
+--------
+
+Overview
+~~~~~~~~
+
+Problem statement
+^^^^^^^^^^^^^^^^^
+
+Some repositories contain a lot of references (e.g. android at 866k,
+rails at 31k). The existing packed-refs format takes up a lot of space
+(e.g. 62M), and does not scale with additional references. Lookup of a
+single reference requires linearly scanning the file.
+
+Atomic pushes modifying multiple references require copying the entire
+packed-refs file, which can be a considerable amount of data moved
+(e.g. 62M in, 62M out) for even small transactions (2 refs modified).
+
+Repositories with many loose references occupy a large number of disk
+blocks from the local file system, as each reference is its own file
+storing 41 bytes (and another file for the corresponding reflog). This
+negatively affects the number of inodes available when a large number of
+repositories are stored on the same filesystem. Readers can be penalized
+due to the larger number of syscalls required to traverse and read the
+`$GIT_DIR/refs` directory.
+
+
+Objectives
+^^^^^^^^^^
+
+* Near constant time lookup for any single reference, even when the
+repository is cold and not in process or kernel cache.
+* Near constant time verification if an object name is referred to by at least
+one reference (for allow-tip-sha1-in-want).
+* Efficient enumeration of an entire namespace, such as `refs/tags/`.
+* Support atomic push with `O(size_of_update)` operations.
+* Combine reflog storage with ref storage for small transactions.
+* Separate reflog storage for base refs and historical logs.
+
+Description
+^^^^^^^^^^^
+
+A reftable file is a portable binary file format customized for
+reference storage. References are sorted, enabling linear scans, binary
+search lookup, and range scans.
+
+Storage in the file is organized into variable sized blocks. Prefix
+compression is used within a single block to reduce disk space. Block
+size and alignment is tunable by the writer.
+
+Performance
+^^^^^^^^^^^
+
+Space used, packed-refs vs. reftable:
+
+[cols=",>,>,>,>,>",options="header",]
+|===============================================================
+|repository |packed-refs |reftable |% original |avg ref |avg obj
+|android |62.2 M |36.1 M |58.0% |33 bytes |5 bytes
+|rails |1.8 M |1.1 M |57.7% |29 bytes |4 bytes
+|git |78.7 K |48.1 K |61.0% |50 bytes |4 bytes
+|git (heads) |332 b |269 b |81.0% |33 bytes |0 bytes
+|===============================================================
+
+Scan (read 866k refs), by reference name lookup (single ref from 866k
+refs), and by SHA-1 lookup (refs with that SHA-1, from 866k refs):
+
+[cols=",>,>,>,>",options="header",]
+|=========================================================
+|format |cache |scan |by name |by SHA-1
+|packed-refs |cold |402 ms |409,660.1 usec |412,535.8 usec
+|packed-refs |hot | |6,844.6 usec |20,110.1 usec
+|reftable |cold |112 ms |33.9 usec |323.2 usec
+|reftable |hot | |20.2 usec |320.8 usec
+|=========================================================
+
+Space used for 149,932 log entries for 43,061 refs, reflog vs. reftable:
+
+[cols=",>,>",options="header",]
+|================================
+|format |size |avg entry
+|$GIT_DIR/logs |173 M |1209 bytes
+|reftable |5 M |37 bytes
+|================================
+
+Details
+~~~~~~~
+
+Peeling
+^^^^^^^
+
+References stored in a reftable are peeled, a record for an annotated
+(or signed) tag records both the tag object, and the object it refers
+to. This is analogous to storage in the packed-refs format.
+
+Reference name encoding
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Reference names are an uninterpreted sequence of bytes that must pass
+linkgit:git-check-ref-format[1] as a valid reference name.
+
+Key unicity
+^^^^^^^^^^^
+
+Each entry must have a unique key; repeated keys are disallowed.
+
+Network byte order
+^^^^^^^^^^^^^^^^^^
+
+All multi-byte, fixed width fields are in network byte order.
+
+Varint encoding
+^^^^^^^^^^^^^^^
+
+Varint encoding is identical to the ofs-delta encoding method used
+within pack files.
+
+Decoder works such as:
+
+....
+val = buf[ptr] & 0x7f
+while (buf[ptr] & 0x80) {
+  ptr++
+  val = ((val + 1) << 7) | (buf[ptr] & 0x7f)
+}
+....
+
+Ordering
+^^^^^^^^
+
+Blocks are lexicographically ordered by their first reference.
+
+Directory/file conflicts
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The reftable format accepts both `refs/heads/foo` and
+`refs/heads/foo/bar` as distinct references.
+
+This property is useful for retaining log records in reftable, but may
+confuse versions of Git using `$GIT_DIR/refs` directory tree to maintain
+references. Users of reftable may choose to continue to reject `foo` and
+`foo/bar` type conflicts to prevent problems for peers.
+
+File format
+~~~~~~~~~~~
+
+Structure
+^^^^^^^^^
+
+A reftable file has the following high-level structure:
+
+....
+first_block {
+  header
+  first_ref_block
+}
+ref_block*
+ref_index*
+obj_block*
+obj_index*
+log_block*
+log_index*
+footer
+....
+
+A log-only file omits the `ref_block`, `ref_index`, `obj_block` and
+`obj_index` sections, containing only the file header and log block:
+
+....
+first_block {
+  header
+}
+log_block*
+log_index*
+footer
+....
+
+in a log-only file the first log block immediately follows the file
+header, without padding to block alignment.
+
+Block size
+^^^^^^^^^^
+
+The file's block size is arbitrarily determined by the writer, and does
+not have to be a power of 2. The block size must be larger than the
+longest reference name or log entry used in the repository, as
+references cannot span blocks.
+
+Powers of two that are friendly to the virtual memory system or
+filesystem (such as 4k or 8k) are recommended. Larger sizes (64k) can
+yield better compression, with a possible increased cost incurred by
+readers during access.
+
+The largest block size is `16777215` bytes (15.99 MiB).
+
+Block alignment
+^^^^^^^^^^^^^^^
+
+Writers may choose to align blocks at multiples of the block size by
+including `padding` filled with NUL bytes at the end of a block to round
+out to the chosen alignment. When alignment is used, writers must
+specify the alignment with the file header's `block_size` field.
+
+Block alignment is not required by the file format. Unaligned files must
+set `block_size = 0` in the file header, and omit `padding`. Unaligned
+files with more than one ref block must include the link:#Ref-index[ref
+index] to support fast lookup. Readers must be able to read both aligned
+and non-aligned files.
+
+Very small files (e.g. a single ref block) may omit `padding` and the ref
+index to reduce total file size.
+
+Header (version 1)
+^^^^^^^^^^^^^^^^^^
+
+A 24-byte header appears at the beginning of the file:
+
+....
+'REFT'
+uint8( version_number = 1 )
+uint24( block_size )
+uint64( min_update_index )
+uint64( max_update_index )
+....
+
+Aligned files must specify `block_size` to configure readers with the
+expected block alignment. Unaligned files must set `block_size = 0`.
+
+The `min_update_index` and `max_update_index` describe bounds for the
+`update_index` field of all log records in this file. When reftables are
+used in a stack for link:#Update-transactions[transactions], these
+fields can order the files such that the prior file's
+`max_update_index + 1` is the next file's `min_update_index`.
+
+Header (version 2)
+^^^^^^^^^^^^^^^^^^
+
+A 28-byte header appears at the beginning of the file:
+
+....
+'REFT'
+uint8( version_number = 2 )
+uint24( block_size )
+uint64( min_update_index )
+uint64( max_update_index )
+uint32( hash_id )
+....
+
+The header is identical to `version_number=1`, with the 4-byte hash ID
+("sha1" for SHA1 and "s256" for SHA-256) append to the header.
+
+For maximum backward compatibility, it is recommended to use version 1 when
+writing SHA1 reftables.
+
+First ref block
+^^^^^^^^^^^^^^^
+
+The first ref block shares the same block as the file header, and is 24
+bytes smaller than all other blocks in the file. The first block
+immediately begins after the file header, at position 24.
+
+If the first block is a log block (a log-only file), its block header
+begins immediately at position 24.
+
+Ref block format
+^^^^^^^^^^^^^^^^
+
+A ref block is written as:
+
+....
+'r'
+uint24( block_len )
+ref_record+
+uint24( restart_offset )+
+uint16( restart_count )
+
+padding?
+....
+
+Blocks begin with `block_type = 'r'` and a 3-byte `block_len` which
+encodes the number of bytes in the block up to, but not including the
+optional `padding`. This is always less than or equal to the file's
+block size. In the first ref block, `block_len` includes 24 bytes for
+the file header.
+
+The 2-byte `restart_count` stores the number of entries in the
+`restart_offset` list, which must not be empty. Readers can use
+`restart_count` to binary search between restarts before starting a
+linear scan.
+
+Exactly `restart_count` 3-byte `restart_offset` values precedes the
+`restart_count`. Offsets are relative to the start of the block and
+refer to the first byte of any `ref_record` whose name has not been
+prefix compressed. Entries in the `restart_offset` list must be sorted,
+ascending. Readers can start linear scans from any of these records.
+
+A variable number of `ref_record` fill the middle of the block,
+describing reference names and values. The format is described below.
+
+As the first ref block shares the first file block with the file header,
+all `restart_offset` in the first block are relative to the start of the
+file (position 0), and include the file header. This forces the first
+`restart_offset` to be `28`.
+
+ref record
+++++++++++
+
+A `ref_record` describes a single reference, storing both the name and
+its value(s). Records are formatted as:
+
+....
+varint( prefix_length )
+varint( (suffix_length << 3) | value_type )
+suffix
+varint( update_index_delta )
+value?
+....
+
+The `prefix_length` field specifies how many leading bytes of the prior
+reference record's name should be copied to obtain this reference's
+name. This must be 0 for the first reference in any block, and also must
+be 0 for any `ref_record` whose offset is listed in the `restart_offset`
+table at the end of the block.
+
+Recovering a reference name from any `ref_record` is a simple concat:
+
+....
+this_name = prior_name[0..prefix_length] + suffix
+....
+
+The `suffix_length` value provides the number of bytes available in
+`suffix` to copy from `suffix` to complete the reference name.
+
+The `update_index` that last modified the reference can be obtained by
+adding `update_index_delta` to the `min_update_index` from the file
+header: `min_update_index + update_index_delta`.
+
+The `value` follows. Its format is determined by `value_type`, one of
+the following:
+
+* `0x0`: deletion; no value data (see transactions, below)
+* `0x1`: one object name; value of the ref
+* `0x2`: two object names; value of the ref, peeled target
+* `0x3`: symbolic reference: `varint( target_len ) target`
+
+Symbolic references use `0x3`, followed by the complete name of the
+reference target. No compression is applied to the target name.
+
+Types `0x4..0x7` are reserved for future use.
+
+Ref index
+^^^^^^^^^
+
+The ref index stores the name of the last reference from every ref block
+in the file, enabling reduced disk seeks for lookups. Any reference can
+be found by searching the index, identifying the containing block, and
+searching within that block.
+
+The index may be organized into a multi-level index, where the 1st level
+index block points to additional ref index blocks (2nd level), which may
+in turn point to either additional index blocks (e.g. 3rd level) or ref
+blocks (leaf level). Disk reads required to access a ref go up with
+higher index levels. Multi-level indexes may be required to ensure no
+single index block exceeds the file format's max block size of
+`16777215` bytes (15.99 MiB). To achieve constant O(1) disk seeks for
+lookups the index must be a single level, which is permitted to exceed
+the file's configured block size, but not the format's max block size of
+15.99 MiB.
+
+If present, the ref index block(s) appears after the last ref block.
+
+If there are at least 4 ref blocks, a ref index block should be written
+to improve lookup times. Cold reads using the index require 2 disk reads
+(read index, read block), and binary searching < 4 blocks also requires
+<= 2 reads. Omitting the index block from smaller files saves space.
+
+If the file is unaligned and contains more than one ref block, the ref
+index must be written.
+
+Index block format:
+
+....
+'i'
+uint24( block_len )
+index_record+
+uint24( restart_offset )+
+uint16( restart_count )
+
+padding?
+....
+
+The index blocks begin with `block_type = 'i'` and a 3-byte `block_len`
+which encodes the number of bytes in the block, up to but not including
+the optional `padding`.
+
+The `restart_offset` and `restart_count` fields are identical in format,
+meaning and usage as in ref blocks.
+
+To reduce the number of reads required for random access in very large
+files the index block may be larger than other blocks. However, readers
+must hold the entire index in memory to benefit from this, so it's a
+time-space tradeoff in both file size and reader memory.
+
+Increasing the file's block size decreases the index size. Alternatively
+a multi-level index may be used, keeping index blocks within the file's
+block size, but increasing the number of blocks that need to be
+accessed.
+
+index record
+++++++++++++
+
+An index record describes the last entry in another block. Index records
+are written as:
+
+....
+varint( prefix_length )
+varint( (suffix_length << 3) | 0 )
+suffix
+varint( block_position )
+....
+
+Index records use prefix compression exactly like `ref_record`.
+
+Index records store `block_position` after the suffix, specifying the
+absolute position in bytes (from the start of the file) of the block
+that ends with this reference. Readers can seek to `block_position` to
+begin reading the block header.
+
+Readers must examine the block header at `block_position` to determine
+if the next block is another level index block, or the leaf-level ref
+block.
+
+Reading the index
++++++++++++++++++
+
+Readers loading the ref index must first read the footer (below) to
+obtain `ref_index_position`. If not present, the position will be 0. The
+`ref_index_position` is for the 1st level root of the ref index.
+
+Obj block format
+^^^^^^^^^^^^^^^^
+
+Object blocks are optional. Writers may choose to omit object blocks,
+especially if readers will not use the object name to ref mapping.
+
+Object blocks use unique, abbreviated 2-32 object name keys, mapping to
+ref blocks containing references pointing to that object directly, or as
+the peeled value of an annotated tag. Like ref blocks, object blocks use
+the file's standard block size. The abbrevation length is available in
+the footer as `obj_id_len`.
+
+To save space in small files, object blocks may be omitted if the ref
+index is not present, as brute force search will only need to read a few
+ref blocks. When missing, readers should brute force a linear search of
+all references to lookup by object name.
+
+An object block is written as:
+
+....
+'o'
+uint24( block_len )
+obj_record+
+uint24( restart_offset )+
+uint16( restart_count )
+
+padding?
+....
+
+Fields are identical to ref block. Binary search using the restart table
+works the same as in reference blocks.
+
+Because object names are abbreviated by writers to the shortest unique
+abbreviation within the reftable, obj key lengths have a variable length. Their
+length must be at least 2 bytes. Readers must compare only for common prefix
+match within an obj block or obj index.
+
+obj record
+++++++++++
+
+An `obj_record` describes a single object abbreviation, and the blocks
+containing references using that unique abbreviation:
+
+....
+varint( prefix_length )
+varint( (suffix_length << 3) | cnt_3 )
+suffix
+varint( cnt_large )?
+varint( position_delta )*
+....
+
+Like in reference blocks, abbreviations are prefix compressed within an
+obj block. On large reftables with many unique objects, higher block
+sizes (64k), and higher restart interval (128), a `prefix_length` of 2
+or 3 and `suffix_length` of 3 may be common in obj records (unique
+abbreviation of 5-6 raw bytes, 10-12 hex digits).
+
+Each record contains `position_count` number of positions for matching
+ref blocks. For 1-7 positions the count is stored in `cnt_3`. When
+`cnt_3 = 0` the actual count follows in a varint, `cnt_large`.
+
+The use of `cnt_3` bets most objects are pointed to by only a single
+reference, some may be pointed to by a couple of references, and very
+few (if any) are pointed to by more than 7 references.
+
+A special case exists when `cnt_3 = 0` and `cnt_large = 0`: there are no
+`position_delta`, but at least one reference starts with this
+abbreviation. A reader that needs exact reference names must scan all
+references to find which specific references have the desired object.
+Writers should use this format when the `position_delta` list would have
+overflowed the file's block size due to a high number of references
+pointing to the same object.
+
+The first `position_delta` is the position from the start of the file.
+Additional `position_delta` entries are sorted ascending and relative to
+the prior entry, e.g. a reader would perform:
+
+....
+pos = position_delta[0]
+prior = pos
+for (j = 1; j < position_count; j++) {
+  pos = prior + position_delta[j]
+  prior = pos
+}
+....
+
+With a position in hand, a reader must linearly scan the ref block,
+starting from the first `ref_record`, testing each reference's object names
+(for `value_type = 0x1` or `0x2`) for full equality. Faster searching by
+object name within a single ref block is not supported by the reftable format.
+Smaller block sizes reduce the number of candidates this step must
+consider.
+
+Obj index
+^^^^^^^^^
+
+The obj index stores the abbreviation from the last entry for every obj
+block in the file, enabling reduced disk seeks for all lookups. It is
+formatted exactly the same as the ref index, but refers to obj blocks.
+
+The obj index should be present if obj blocks are present, as obj blocks
+should only be written in larger files.
+
+Readers loading the obj index must first read the footer (below) to
+obtain `obj_index_position`. If not present, the position will be 0.
+
+Log block format
+^^^^^^^^^^^^^^^^
+
+Unlike ref and obj blocks, log blocks are always unaligned.
+
+Log blocks are variable in size, and do not match the `block_size`
+specified in the file header or footer. Writers should choose an
+appropriate buffer size to prepare a log block for deflation, such as
+`2 * block_size`.
+
+A log block is written as:
+
+....
+'g'
+uint24( block_len )
+zlib_deflate {
+  log_record+
+  uint24( restart_offset )+
+  uint16( restart_count )
+}
+....
+
+Log blocks look similar to ref blocks, except `block_type = 'g'`.
+
+The 4-byte block header is followed by the deflated block contents using
+zlib deflate. The `block_len` in the header is the inflated size
+(including 4-byte block header), and should be used by readers to
+preallocate the inflation output buffer. A log block's `block_len` may
+exceed the file's block size.
+
+Offsets within the log block (e.g. `restart_offset`) still include the
+4-byte header. Readers may prefer prefixing the inflation output buffer
+with the 4-byte header.
+
+Within the deflate container, a variable number of `log_record` describe
+reference changes. The log record format is described below. See ref
+block format (above) for a description of `restart_offset` and
+`restart_count`.
+
+Because log blocks have no alignment or padding between blocks, readers
+must keep track of the bytes consumed by the inflater to know where the
+next log block begins.
+
+log record
+++++++++++
+
+Log record keys are structured as:
+
+....
+ref_name '\0' reverse_int64( update_index )
+....
+
+where `update_index` is the unique transaction identifier. The
+`update_index` field must be unique within the scope of a `ref_name`.
+See the update transactions section below for further details.
+
+The `reverse_int64` function inverses the value so lexicographical
+ordering the network byte order encoding sorts the more recent records
+with higher `update_index` values first:
+
+....
+reverse_int64(int64 t) {
+  return 0xffffffffffffffff - t;
+}
+....
+
+Log records have a similar starting structure to ref and index records,
+utilizing the same prefix compression scheme applied to the log record
+key described above.
+
+....
+    varint( prefix_length )
+    varint( (suffix_length << 3) | log_type )
+    suffix
+    log_data {
+      old_id
+      new_id
+      varint( name_length    )  name
+      varint( email_length   )  email
+      varint( time_seconds )
+      sint16( tz_offset )
+      varint( message_length )  message
+    }?
+....
+
+Log record entries use `log_type` to indicate what follows:
+
+* `0x0`: deletion; no log data.
+* `0x1`: standard git reflog data using `log_data` above.
+
+The `log_type = 0x0` is mostly useful for `git stash drop`, removing an
+entry from the reflog of `refs/stash` in a transaction file (below),
+without needing to rewrite larger files. Readers reading a stack of
+reflogs must treat this as a deletion.
+
+For `log_type = 0x1`, the `log_data` section follows
+linkgit:git-update-ref[1] logging and includes:
+
+* two object names (old id, new id)
+* varint string of committer's name
+* varint string of committer's email
+* varint time in seconds since epoch (Jan 1, 1970)
+* 2-byte timezone offset in minutes (signed)
+* varint string of message
+
+`tz_offset` is the absolute number of minutes from GMT the committer was
+at the time of the update. For example `GMT-0800` is encoded in reftable
+as `sint16(-480)` and `GMT+0230` is `sint16(150)`.
+
+The committer email does not contain `<` or `>`, it's the value normally
+found between the `<>` in a git commit object header.
+
+The `message_length` may be 0, in which case there was no message
+supplied for the update.
+
+Contrary to traditional reflog (which is a file), renames are encoded as
+a combination of ref deletion and ref creation.  A deletion is a log
+record with a zero new_id, and a creation is a log record with a zero old_id.
+
+Reading the log
++++++++++++++++
+
+Readers accessing the log must first read the footer (below) to
+determine the `log_position`. The first block of the log begins at
+`log_position` bytes since the start of the file. The `log_position` is
+not block aligned.
+
+Importing logs
+++++++++++++++
+
+When importing from `$GIT_DIR/logs` writers should globally order all
+log records roughly by timestamp while preserving file order, and assign
+unique, increasing `update_index` values for each log line. Newer log
+records get higher `update_index` values.
+
+Although an import may write only a single reftable file, the reftable
+file must span many unique `update_index`, as each log line requires its
+own `update_index` to preserve semantics.
+
+Log index
+^^^^^^^^^
+
+The log index stores the log key
+(`refname \0 reverse_int64(update_index)`) for the last log record of
+every log block in the file, supporting bounded-time lookup.
+
+A log index block must be written if 2 or more log blocks are written to
+the file. If present, the log index appears after the last log block.
+There is no padding used to align the log index to block alignment.
+
+Log index format is identical to ref index, except the keys are 9 bytes
+longer to include `'\0'` and the 8-byte `reverse_int64(update_index)`.
+Records use `block_position` to refer to the start of a log block.
+
+Reading the index
++++++++++++++++++
+
+Readers loading the log index must first read the footer (below) to
+obtain `log_index_position`. If not present, the position will be 0.
+
+Footer
+^^^^^^
+
+After the last block of the file, a file footer is written. It begins
+like the file header, but is extended with additional data.
+
+....
+    HEADER
+
+    uint64( ref_index_position )
+    uint64( (obj_position << 5) | obj_id_len )
+    uint64( obj_index_position )
+
+    uint64( log_position )
+    uint64( log_index_position )
+
+    uint32( CRC-32 of above )
+....
+
+If a section is missing (e.g. ref index) the corresponding position
+field (e.g. `ref_index_position`) will be 0.
+
+* `obj_position`: byte position for the first obj block.
+* `obj_id_len`: number of bytes used to abbreviate object names in
+obj blocks.
+* `log_position`: byte position for the first log block.
+* `ref_index_position`: byte position for the start of the ref index.
+* `obj_index_position`: byte position for the start of the obj index.
+* `log_index_position`: byte position for the start of the log index.
+
+The size of the footer is 68 bytes for version 1, and 72 bytes for
+version 2.
+
+Reading the footer
+++++++++++++++++++
+
+Readers must first read the file start to determine the version
+number. Then they seek to `file_length - FOOTER_LENGTH` to access the
+footer. A trusted external source (such as `stat(2)`) is necessary to
+obtain `file_length`. When reading the footer, readers must verify:
+
+* 4-byte magic is correct
+* 1-byte version number is recognized
+* 4-byte CRC-32 matches the other 64 bytes (including magic, and
+version)
+
+Once verified, the other fields of the footer can be accessed.
+
+Empty tables
+++++++++++++
+
+A reftable may be empty. In this case, the file starts with a header
+and is immediately followed by a footer.
+
+Binary search
+^^^^^^^^^^^^^
+
+Binary search within a block is supported by the `restart_offset` fields
+at the end of the block. Readers can binary search through the restart
+table to locate between which two restart points the sought reference or
+key should appear.
+
+Each record identified by a `restart_offset` stores the complete key in
+the `suffix` field of the record, making the compare operation during
+binary search straightforward.
+
+Once a restart point lexicographically before the sought reference has
+been identified, readers can linearly scan through the following record
+entries to locate the sought record, terminating if the current record
+sorts after (and therefore the sought key is not present).
+
+Restart point selection
++++++++++++++++++++++++
+
+Writers determine the restart points at file creation. The process is
+arbitrary, but every 16 or 64 records is recommended. Every 16 may be
+more suitable for smaller block sizes (4k or 8k), every 64 for larger
+block sizes (64k).
+
+More frequent restart points reduces prefix compression and increases
+space consumed by the restart table, both of which increase file size.
+
+Less frequent restart points makes prefix compression more effective,
+decreasing overall file size, with increased penalties for readers
+walking through more records after the binary search step.
+
+A maximum of `65535` restart points per block is supported.
+
+Considerations
+~~~~~~~~~~~~~~
+
+Lightweight refs dominate
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The reftable format assumes the vast majority of references are single
+object names valued with common prefixes, such as Gerrit Code Review's
+`refs/changes/` namespace, GitHub's `refs/pulls/` namespace, or many
+lightweight tags in the `refs/tags/` namespace.
+
+Annotated tags storing the peeled object cost an additional object name per
+reference.
+
+Low overhead
+^^^^^^^^^^^^
+
+A reftable with very few references (e.g. git.git with 5 heads) is 269
+bytes for reftable, vs. 332 bytes for packed-refs. This supports
+reftable scaling down for transaction logs (below).
+
+Block size
+^^^^^^^^^^
+
+For a Gerrit Code Review type repository with many change refs, larger
+block sizes (64 KiB) and less frequent restart points (every 64) yield
+better compression due to more references within the block compressing
+against the prior reference.
+
+Larger block sizes reduce the index size, as the reftable will require
+fewer blocks to store the same number of references.
+
+Minimal disk seeks
+^^^^^^^^^^^^^^^^^^
+
+Assuming the index block has been loaded into memory, binary searching
+for any single reference requires exactly 1 disk seek to load the
+containing block.
+
+Scans and lookups dominate
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Scanning all references and lookup by name (or namespace such as
+`refs/heads/`) are the most common activities performed on repositories.
+Object names are stored directly with references to optimize this use case.
+
+Logs are infrequently read
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Logs are infrequently accessed, but can be large. Deflating log blocks
+saves disk space, with some increased penalty at read time.
+
+Logs are stored in an isolated section from refs, reducing the burden on
+reference readers that want to ignore logs. Further, historical logs can
+be isolated into log-only files.
+
+Logs are read backwards
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Logs are frequently accessed backwards (most recent N records for master
+to answer `master@{4}`), so log records are grouped by reference, and
+sorted descending by update index.
+
+Repository format
+~~~~~~~~~~~~~~~~~
+
+Version 1
+^^^^^^^^^
+
+A repository must set its `$GIT_DIR/config` to configure reftable:
+
+....
+[core]
+    repositoryformatversion = 1
+[extensions]
+    refStorage = reftable
+....
+
+Layout
+^^^^^^
+
+A collection of reftable files are stored in the `$GIT_DIR/reftable/`
+directory:
+
+....
+00000001-00000001.log
+00000002-00000002.ref
+00000003-00000003.ref
+....
+
+where reftable files are named by a unique name such as produced by the
+function `${min_update_index}-${max_update_index}.ref`.
+
+Log-only files use the `.log` extension, while ref-only and mixed ref
+and log files use `.ref`. extension.
+
+The stack ordering file is `$GIT_DIR/reftable/tables.list` and lists the
+current files, one per line, in order, from oldest (base) to newest
+(most recent):
+
+....
+$ cat .git/reftable/tables.list
+00000001-00000001.log
+00000002-00000002.ref
+00000003-00000003.ref
+....
+
+Readers must read `$GIT_DIR/reftable/tables.list` to determine which
+files are relevant right now, and search through the stack in reverse
+order (last reftable is examined first).
+
+Reftable files not listed in `tables.list` may be new (and about to be
+added to the stack by the active writer), or ancient and ready to be
+pruned.
+
+Backward compatibility
+^^^^^^^^^^^^^^^^^^^^^^
+
+Older clients should continue to recognize the directory as a git
+repository so they don't look for an enclosing repository in parent
+directories. To this end, a reftable-enabled repository must contain the
+following dummy files
+
+* `.git/HEAD`, a regular file containing `ref: refs/heads/.invalid`.
+* `.git/refs/`, a directory
+* `.git/refs/heads`, a regular file
+
+Readers
+^^^^^^^
+
+Readers can obtain a consistent snapshot of the reference space by
+following:
+
+1.  Open and read the `tables.list` file.
+2.  Open each of the reftable files that it mentions.
+3.  If any of the files is missing, goto 1.
+4.  Read from the now-open files as long as necessary.
+
+Update transactions
+^^^^^^^^^^^^^^^^^^^
+
+Although reftables are immutable, mutations are supported by writing a
+new reftable and atomically appending it to the stack:
+
+1.  Acquire `tables.list.lock`.
+2.  Read `tables.list` to determine current reftables.
+3.  Select `update_index` to be most recent file's
+`max_update_index + 1`.
+4.  Prepare temp reftable `tmp_XXXXXX`, including log entries.
+5.  Rename `tmp_XXXXXX` to `${update_index}-${update_index}.ref`.
+6.  Copy `tables.list` to `tables.list.lock`, appending file from (5).
+7.  Rename `tables.list.lock` to `tables.list`.
+
+During step 4 the new file's `min_update_index` and `max_update_index`
+are both set to the `update_index` selected by step 3. All log records
+for the transaction use the same `update_index` in their keys. This
+enables later correlation of which references were updated by the same
+transaction.
+
+Because a single `tables.list.lock` file is used to manage locking, the
+repository is single-threaded for writers. Writers may have to busy-spin
+(with backoff) around creating `tables.list.lock`, for up to an
+acceptable wait period, aborting if the repository is too busy to
+mutate. Application servers wrapped around repositories (e.g. Gerrit
+Code Review) can layer their own lock/wait queue to improve fairness to
+writers.
+
+Reference deletions
+^^^^^^^^^^^^^^^^^^^
+
+Deletion of any reference can be explicitly stored by setting the `type`
+to `0x0` and omitting the `value` field of the `ref_record`. This serves
+as a tombstone, overriding any assertions about the existence of the
+reference from earlier files in the stack.
+
+Compaction
+^^^^^^^^^^
+
+A partial stack of reftables can be compacted by merging references
+using a straightforward merge join across reftables, selecting the most
+recent value for output, and omitting deleted references that do not
+appear in remaining, lower reftables.
+
+A compacted reftable should set its `min_update_index` to the smallest
+of the input files' `min_update_index`, and its `max_update_index`
+likewise to the largest input `max_update_index`.
+
+For sake of illustration, assume the stack currently consists of
+reftable files (from oldest to newest): A, B, C, and D. The compactor is
+going to compact B and C, leaving A and D alone.
+
+1.  Obtain lock `tables.list.lock` and read the `tables.list` file.
+2.  Obtain locks `B.lock` and `C.lock`. Ownership of these locks
+prevents other processes from trying to compact these files.
+3.  Release `tables.list.lock`.
+4.  Compact `B` and `C` into a temp file
+`${min_update_index}-${max_update_index}_XXXXXX`.
+5.  Reacquire lock `tables.list.lock`.
+6.  Verify that `B` and `C` are still in the stack, in that order. This
+should always be the case, assuming that other processes are adhering to
+the locking protocol.
+7.  Rename `${min_update_index}-${max_update_index}_XXXXXX` to
+`${min_update_index}-${max_update_index}.ref`.
+8.  Write the new stack to `tables.list.lock`, replacing `B` and `C`
+with the file from (4).
+9.  Rename `tables.list.lock` to `tables.list`.
+10. Delete `B` and `C`, perhaps after a short sleep to avoid forcing
+readers to backtrack.
+
+This strategy permits compactions to proceed independently of updates.
+
+Each reftable (compacted or not) is uniquely identified by its name, so
+open reftables can be cached by their name.
+
+Alternatives considered
+~~~~~~~~~~~~~~~~~~~~~~~
+
+bzip packed-refs
+^^^^^^^^^^^^^^^^
+
+`bzip2` can significantly shrink a large packed-refs file (e.g. 62 MiB
+compresses to 23 MiB, 37%). However the bzip format does not support
+random access to a single reference. Readers must inflate and discard
+while performing a linear scan.
+
+Breaking packed-refs into chunks (individually compressing each chunk)
+would reduce the amount of data a reader must inflate, but still leaves
+the problem of indexing chunks to support readers efficiently locating
+the correct chunk.
+
+Given the compression achieved by reftable's encoding, it does not seem
+necessary to add the complexity of bzip/gzip/zlib.
+
+Michael Haggerty's alternate format
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Michael Haggerty proposed
+link:https://lore.kernel.org/git/CAMy9T_HCnyc1g8XWOOWhe7nN0aEFyyBskV2aOMb_fe%2BwGvEJ7A%40mail.gmail.com/[an
+alternate] format to reftable on the Git mailing list. This format uses
+smaller chunks, without the restart table, and avoids block alignment
+with padding. Reflog entries immediately follow each ref, and are thus
+interleaved between refs.
+
+Performance testing indicates reftable is faster for lookups (51%
+faster, 11.2 usec vs. 5.4 usec), although reftable produces a slightly
+larger file (+ ~3.2%, 28.3M vs 29.2M):
+
+[cols=">,>,>,>",options="header",]
+|=====================================
+|format |size |seek cold |seek hot
+|mh-alt |28.3 M |23.4 usec |11.2 usec
+|reftable |29.2 M |19.9 usec |5.4 usec
+|=====================================
+
+JGit Ketch RefTree
+^^^^^^^^^^^^^^^^^^
+
+https://dev.eclipse.org/mhonarc/lists/jgit-dev/msg03073.html[JGit Ketch]
+proposed
+link:https://lore.kernel.org/git/CAJo%3DhJvnAPNAdDcAAwAvU9C4RVeQdoS3Ev9WTguHx4fD0V_nOg%40mail.gmail.com/[RefTree],
+an encoding of references inside Git tree objects stored as part of the
+repository's object database.
+
+The RefTree format adds additional load on the object database storage
+layer (more loose objects, more objects in packs), and relies heavily on
+the packer's delta compression to save space. Namespaces which are flat
+(e.g. thousands of tags in refs/tags) initially create very large loose
+objects, and so RefTree does not address the problem of copying many
+references to modify a handful.
+
+Flat namespaces are not efficiently searchable in RefTree, as tree
+objects in canonical formatting cannot be binary searched. This fails
+the need to handle a large number of references in a single namespace,
+such as GitHub's `refs/pulls`, or a project with many tags.
+
+LMDB
+^^^^
+
+David Turner proposed
+https://lore.kernel.org/git/1455772670-21142-26-git-send-email-dturner@twopensource.com/[using
+LMDB], as LMDB is lightweight (64k of runtime code) and GPL-compatible
+license.
+
+A downside of LMDB is its reliance on a single C implementation. This
+makes embedding inside JGit (a popular reimplementation of Git)
+difficult, and hoisting onto virtual storage (for JGit DFS) virtually
+impossible.
+
+A common format that can be supported by all major Git implementations
+(git-core, JGit, libgit2) is strongly preferred.
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index 8336529..fd480b8 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -347,7 +347,7 @@
   origin/man
   origin/master
   origin/next
-  origin/pu
+  origin/seen
   origin/todo
 ------------------------------------------------
 
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 06a5333..9db2f4f 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.27.0
+DEF_VER=v2.28.0
 
 LF='
 '
diff --git a/RelNotes b/RelNotes
index a7b4f6d..9143650 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.28.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.29.0.txt
\ No newline at end of file
diff --git a/add-patch.c b/add-patch.c
index f899389..a1d66c1 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -1203,7 +1203,7 @@
 	for (;;) {
 		int res = edit_hunk_manually(s, hunk);
 		if (res == 0) {
-			/* abandonded */
+			/* abandoned */
 			*hunk = backup;
 			return -1;
 		}
diff --git a/alloc.c b/alloc.c
index 1c64c4d..957a0af 100644
--- a/alloc.c
+++ b/alloc.c
@@ -99,23 +99,27 @@
 	return obj;
 }
 
-static unsigned int alloc_commit_index(struct repository *r)
+/*
+ * The returned count is to be used as an index into commit slabs,
+ * that are *NOT* maintained per repository, and that is why a single
+ * global counter is used.
+ */
+static unsigned int alloc_commit_index(void)
 {
-	return r->parsed_objects->commit_count++;
+	static unsigned int parsed_commits_count;
+	return parsed_commits_count++;
 }
 
-void init_commit_node(struct repository *r, struct commit *c)
+void init_commit_node(struct commit *c)
 {
 	c->object.type = OBJ_COMMIT;
-	c->index = alloc_commit_index(r);
-	c->graph_pos = COMMIT_NOT_FROM_GRAPH;
-	c->generation = GENERATION_NUMBER_INFINITY;
+	c->index = alloc_commit_index();
 }
 
 void *alloc_commit_node(struct repository *r)
 {
 	struct commit *c = alloc_node(r->parsed_objects->commit_state, sizeof(struct commit));
-	init_commit_node(r, c);
+	init_commit_node(c);
 	return c;
 }
 
diff --git a/alloc.h b/alloc.h
index ed1071c..371d388 100644
--- a/alloc.h
+++ b/alloc.h
@@ -9,7 +9,7 @@
 
 void *alloc_blob_node(struct repository *r);
 void *alloc_tree_node(struct repository *r);
-void init_commit_node(struct repository *r, struct commit *c);
+void init_commit_node(struct commit *c);
 void *alloc_commit_node(struct repository *r);
 void *alloc_tag_node(struct repository *r);
 void *alloc_object_node(struct repository *r);
diff --git a/blame.c b/blame.c
index da7e288..82fa16d 100644
--- a/blame.c
+++ b/blame.c
@@ -1272,7 +1272,7 @@
 	if (!bd)
 		return 1;
 
-	if (origin->commit->generation == GENERATION_NUMBER_INFINITY)
+	if (commit_graph_generation(origin->commit) == GENERATION_NUMBER_INFINITY)
 		return 1;
 
 	filter = get_bloom_filter(r, origin->commit, 0);
diff --git a/blob.c b/blob.c
index 36f9abd..182718a 100644
--- a/blob.c
+++ b/blob.c
@@ -10,7 +10,7 @@
 	struct object *obj = lookup_object(r, oid);
 	if (!obj)
 		return create_object(r, oid, alloc_blob_node(r));
-	return object_as_type(r, obj, OBJ_BLOB, 0);
+	return object_as_type(obj, OBJ_BLOB, 0);
 }
 
 int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size)
diff --git a/bloom.c b/bloom.c
index 6c76118..1a57322 100644
--- a/bloom.c
+++ b/bloom.c
@@ -33,15 +33,16 @@
 					struct commit *c)
 {
 	uint32_t lex_pos, start_index, end_index;
+	uint32_t graph_pos = commit_graph_position(c);
 
-	while (c->graph_pos < g->num_commits_in_base)
+	while (graph_pos < g->num_commits_in_base)
 		g = g->base_graph;
 
 	/* The commit graph commit 'c' lives in doesn't carry bloom filters. */
 	if (!g->chunk_bloom_indexes)
 		return 0;
 
-	lex_pos = c->graph_pos - g->num_commits_in_base;
+	lex_pos = graph_pos - g->num_commits_in_base;
 
 	end_index = get_be32(g->chunk_bloom_indexes + 4 * lex_pos);
 
@@ -186,24 +187,22 @@
 	struct diff_options diffopt;
 	int max_changes = 512;
 
-	if (bloom_filters.slab_size == 0)
+	if (!bloom_filters.slab_size)
 		return NULL;
 
 	filter = bloom_filter_slab_at(&bloom_filters, c);
 
 	if (!filter->data) {
 		load_commit_graph_info(r, c);
-		if (c->graph_pos != COMMIT_NOT_FROM_GRAPH &&
-			r->objects->commit_graph->chunk_bloom_indexes) {
-			if (load_bloom_filter_from_graph(r->objects->commit_graph, filter, c))
-				return filter;
-			else
-				return NULL;
-		}
+		if (commit_graph_position(c) != COMMIT_NOT_FROM_GRAPH &&
+			r->objects->commit_graph->chunk_bloom_indexes)
+			load_bloom_filter_from_graph(r->objects->commit_graph, filter, c);
 	}
 
-	if (filter->data || !compute_if_not_present)
+	if (filter->data)
 		return filter;
+	if (!compute_if_not_present)
+		return NULL;
 
 	repo_diff_setup(r, &diffopt);
 	diffopt.flags.recursive = 1;
diff --git a/branch.c b/branch.c
index 2d9e767..7095f78 100644
--- a/branch.c
+++ b/branch.c
@@ -370,7 +370,7 @@
 				      const char *logmsg)
 {
 	int ret = 0;
-	struct worktree **worktrees = get_worktrees(0);
+	struct worktree **worktrees = get_worktrees();
 	int i;
 
 	for (i = 0; worktrees[i]; i++) {
diff --git a/bugreport.c b/bugreport.c
index 28f4568..09579e2 100644
--- a/bugreport.c
+++ b/bugreport.c
@@ -180,7 +180,9 @@
 		die(_("couldn't create a new file at '%s'"), report_path.buf);
 	}
 
-	strbuf_write_fd(&buffer, report);
+	if (write_in_full(report, buffer.buf, buffer.len) < 0)
+		die_errno(_("unable to write to %s"), report_path.buf);
+
 	close(report);
 
 	/*
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index ec49962..73f9324 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -13,7 +13,6 @@
 static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
 static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK")
 static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START")
-static GIT_PATH_FUNC(git_path_bisect_head, "BISECT_HEAD")
 static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
 static GIT_PATH_FUNC(git_path_head_name, "head-name")
 static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
@@ -164,7 +163,7 @@
 		strbuf_addstr(&branch, commit);
 	}
 
-	if (!file_exists(git_path_bisect_head())) {
+	if (!ref_exists("BISECT_HEAD")) {
 		struct argv_array argv = ARGV_ARRAY_INIT;
 
 		argv_array_pushl(&argv, "checkout", branch.buf, "--", NULL);
diff --git a/builtin/branch.c b/builtin/branch.c
index accb61b..e82301f 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -468,7 +468,7 @@
 
 static void reject_rebase_or_bisect_branch(const char *target)
 {
-	struct worktree **worktrees = get_worktrees(0);
+	struct worktree **worktrees = get_worktrees();
 	int i;
 
 	for (i = 0; worktrees[i]; i++) {
@@ -693,7 +693,7 @@
 		list = 1;
 
 	if (!!delete + !!rename + !!copy + !!new_upstream + !!show_current +
-	    list + unset_upstream > 1)
+	    list + edit_description + unset_upstream > 1)
 		usage_with_options(builtin_branch_usage, options);
 
 	if (filter.abbrev == -1)
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index ae18e20..5ebf133 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -596,7 +596,7 @@
 
 static const char * const cat_file_usage[] = {
 	N_("git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -p | <type> | --textconv | --filters) [--path=<path>] <object>"),
-	N_("git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv | --filters]"),
+	N_("git cat-file (--batch[=<format>] | --batch-check[=<format>]) [--follow-symlinks] [--textconv | --filters]"),
 	NULL
 };
 
diff --git a/builtin/clean.c b/builtin/clean.c
index 4ca12bc..5a9c29a 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -924,12 +924,6 @@
 			     0);
 
 	memset(&dir, 0, sizeof(dir));
-	if (ignored_only)
-		dir.flags |= DIR_SHOW_IGNORED;
-
-	if (ignored && ignored_only)
-		die(_("-x and -X cannot be used together"));
-
 	if (!interactive && !dry_run && !force) {
 		if (config_set)
 			die(_("clean.requireForce set to true and neither -i, -n, nor -f given; "
@@ -946,6 +940,13 @@
 
 	dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
 
+	if (ignored && ignored_only)
+		die(_("-x and -X cannot be used together"));
+	if (!ignored)
+		setup_standard_excludes(&dir);
+	if (ignored_only)
+		dir.flags |= DIR_SHOW_IGNORED;
+
 	if (argc) {
 		/*
 		 * Remaining args implies pathspecs specified, and we should
@@ -954,15 +955,41 @@
 		remove_directories = 1;
 	}
 
-	if (remove_directories)
-		dir.flags |= DIR_SHOW_IGNORED_TOO | DIR_KEEP_UNTRACKED_CONTENTS;
+	if (remove_directories && !ignored_only) {
+		/*
+		 * We need to know about ignored files too:
+		 *
+		 * If (ignored), then we will delete ignored files as well.
+		 *
+		 * If (!ignored), then even though we not are doing
+		 * anything with ignored files, we need to know about them
+		 * so that we can avoid deleting a directory of untracked
+		 * files that also contains an ignored file within it.
+		 *
+		 * For the (!ignored) case, since we only need to avoid
+		 * deleting ignored files, we can set
+		 * DIR_SHOW_IGNORED_TOO_MODE_MATCHING in order to avoid
+		 * recursing into a directory which is itself ignored.
+		 */
+		dir.flags |= DIR_SHOW_IGNORED_TOO;
+		if (!ignored)
+			dir.flags |= DIR_SHOW_IGNORED_TOO_MODE_MATCHING;
+
+		/*
+		 * Let the fill_directory() machinery know that we aren't
+		 * just recursing to collect the ignored files; we want all
+		 * the untracked ones so that we can delete them.  (Note:
+		 * we could also set DIR_KEEP_UNTRACKED_CONTENTS when
+		 * ignored_only is true, since DIR_KEEP_UNTRACKED_CONTENTS
+		 * only has effect in combination with DIR_SHOW_IGNORED_TOO.  It makes
+		 * the code clearer to exclude it, though.
+		 */
+		dir.flags |= DIR_KEEP_UNTRACKED_CONTENTS;
+	}
 
 	if (read_cache() < 0)
 		die(_("index file corrupt"));
 
-	if (!ignored)
-		setup_standard_excludes(&dir);
-
 	pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option");
 	for (i = 0; i < exclude_list.nr; i++)
 		add_pattern(exclude_list.items[i].string, "", 0, pl, -(i+1));
diff --git a/builtin/clone.c b/builtin/clone.c
index cb48a29..a9f3312 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -945,8 +945,8 @@
 {
 	int is_bundle = 0, is_local;
 	const char *repo_name, *repo, *work_tree, *git_dir;
-	char *path, *dir;
-	int dest_exists;
+	char *path, *dir, *display_repo = NULL;
+	int dest_exists, real_dest_exists = 0;
 	const struct ref *refs, *remote_head;
 	const struct ref *remote_head_points_at;
 	const struct ref *our_head_points_at;
@@ -1000,10 +1000,11 @@
 	path = get_repo_path(repo_name, &is_bundle);
 	if (path)
 		repo = absolute_pathdup(repo_name);
-	else if (!strchr(repo_name, ':'))
-		die(_("repository '%s' does not exist"), repo_name);
-	else
+	else if (strchr(repo_name, ':')) {
 		repo = repo_name;
+		display_repo = transport_anonymize_url(repo);
+	} else
+		die(_("repository '%s' does not exist"), repo_name);
 
 	/* no need to be strict, transport_set_option() will validate it again */
 	if (option_depth && atoi(option_depth) < 1)
@@ -1020,7 +1021,17 @@
 		die(_("destination path '%s' already exists and is not "
 			"an empty directory."), dir);
 
-	strbuf_addf(&reflog_msg, "clone: from %s", repo);
+	if (real_git_dir) {
+		real_dest_exists = path_exists(real_git_dir);
+		if (real_dest_exists && !is_empty_dir(real_git_dir))
+			die(_("repository path '%s' already exists and is not "
+				"an empty directory."), real_git_dir);
+	}
+
+
+	strbuf_addf(&reflog_msg, "clone: from %s",
+		    display_repo ? display_repo : repo);
+	free(display_repo);
 
 	if (option_bare)
 		work_tree = NULL;
@@ -1054,7 +1065,7 @@
 	}
 
 	if (real_git_dir) {
-		if (path_exists(real_git_dir))
+		if (real_dest_exists)
 			junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
 		junk_git_dir = real_git_dir;
 	} else {
@@ -1108,7 +1119,8 @@
 		}
 	}
 
-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
+	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
+		INIT_DB_QUIET);
 
 	if (real_git_dir)
 		git_dir = real_git_dir;
@@ -1217,6 +1229,15 @@
 	refs = transport_get_remote_refs(transport, &ref_prefixes);
 
 	if (refs) {
+		int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
+
+		/*
+		 * Now that we know what algorithm the remote side is using,
+		 * let's set ours to the same thing.
+		 */
+		initialize_repository_version(hash_algo);
+		repo_set_hash_algo(the_repository, hash_algo);
+
 		mapped_refs = wanted_peer_refs(refs, &remote->fetch);
 		/*
 		 * transport_get_remote_refs() may return refs with null sha-1
@@ -1263,9 +1284,13 @@
 		remote_head_points_at = NULL;
 		remote_head = NULL;
 		option_no_checkout = 1;
-		if (!option_bare)
-			install_branch_config(0, "master", option_origin,
-					      "refs/heads/master");
+		if (!option_bare) {
+			const char *branch = git_default_branch_name();
+			char *ref = xstrfmt("refs/heads/%s", branch);
+
+			install_branch_config(0, branch, option_origin, ref);
+			free(ref);
+		}
 	}
 
 	write_refspec_config(src_ref_prefix, our_head_points_at,
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 75455da..523501f 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -154,7 +154,7 @@
 			   NULL, 0);
 	if (!result)
 		return error(_("invalid object: %s"), hash);
-	else if (object_as_type(the_repository, result, OBJ_COMMIT, 1))
+	else if (object_as_type(result, OBJ_COMMIT, 1))
 		oidset_insert(commits, &result->oid);
 
 	display_progress(progress, oidset_size(commits));
@@ -201,6 +201,7 @@
 	};
 
 	opts.progress = isatty(2);
+	opts.enable_changed_paths = -1;
 	split_opts.size_multiple = 2;
 	split_opts.max_commits = 0;
 	split_opts.expire_time = 0;
@@ -221,7 +222,9 @@
 		flags |= COMMIT_GRAPH_WRITE_SPLIT;
 	if (opts.progress)
 		flags |= COMMIT_GRAPH_WRITE_PROGRESS;
-	if (opts.enable_changed_paths ||
+	if (!opts.enable_changed_paths)
+		flags |= COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS;
+	if (opts.enable_changed_paths == 1 ||
 	    git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0))
 		flags |= COMMIT_GRAPH_WRITE_BLOOM_FILTERS;
 
@@ -251,7 +254,7 @@
 			}
 		}
 
-
+		stop_progress(&progress);
 	}
 
 	if (write_commit_graph(odb,
@@ -264,8 +267,6 @@
 cleanup:
 	string_list_clear(&pack_indexes, 0);
 	strbuf_release(&buf);
-	if (progress)
-		stop_progress(&progress);
 	return result;
 }
 
diff --git a/builtin/config.c b/builtin/config.c
index ee4aef6..5e39f61 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -672,7 +672,7 @@
 		given_config_source.file = git_pathdup("config");
 		given_config_source.scope = CONFIG_SCOPE_LOCAL;
 	} else if (use_worktree_config) {
-		struct worktree **worktrees = get_worktrees(0);
+		struct worktree **worktrees = get_worktrees();
 		if (repository_format_worktree_config)
 			given_config_source.file = git_pathdup("config.worktree");
 		else if (worktrees[0] && worktrees[1])
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index 86ae474..1e352dd 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -28,6 +28,13 @@
 	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
 	repo_init_revisions(the_repository, &rev, prefix);
 	rev.abbrev = 0;
+
+	/*
+	 * Consider "intent-to-add" files as new by default, unless
+	 * explicitly specified in the command line or anywhere else.
+	 */
+	rev.diffopt.ita_invisible_in_index = 1;
+
 	precompose_argv(argc, argv);
 
 	argc = setup_revisions(argc, argv, &rev, NULL);
diff --git a/builtin/diff.c b/builtin/diff.c
index 8537b17..cb98811 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -6,6 +6,7 @@
 #define USE_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
 #include "config.h"
+#include "ewah/ewok.h"
 #include "lockfile.h"
 #include "color.h"
 #include "commit.h"
@@ -23,7 +24,13 @@
 #define DIFF_NO_INDEX_IMPLICIT 2
 
 static const char builtin_diff_usage[] =
-"git diff [<options>] [<commit> [<commit>]] [--] [<path>...]";
+"git diff [<options>] [<commit>] [--] [<path>...]\n"
+"   or: git diff [<options>] --cached [<commit>] [--] [<path>...]\n"
+"   or: git diff [<options>] <commit> [<commit>...] <commit> [--] [<path>...]\n"
+"   or: git diff [<options>] <commit>...<commit>] [--] [<path>...]\n"
+"   or: git diff [<options>] <blob> <blob>]\n"
+"   or: git diff [<options>] --no-index [--] <path> <path>]\n"
+COMMON_DIFF_OPTIONS_HELP;
 
 static const char *blob_path(struct object_array_entry *entry)
 {
@@ -254,6 +261,108 @@
 	return run_diff_files(revs, options);
 }
 
+struct symdiff {
+	struct bitmap *skip;
+	int warn;
+	const char *base, *left, *right;
+};
+
+/*
+ * Check for symmetric-difference arguments, and if present, arrange
+ * everything we need to know to handle them correctly.  As a bonus,
+ * weed out all bogus range-based revision specifications, e.g.,
+ * "git diff A..B C..D" or "git diff A..B C" get rejected.
+ *
+ * For an actual symmetric diff, *symdiff is set this way:
+ *
+ *  - its skip is non-NULL and marks *all* rev->pending.objects[i]
+ *    indices that the caller should ignore (extra merge bases, of
+ *    which there might be many, and A in A...B).  Note that the
+ *    chosen merge base and right side are NOT marked.
+ *  - warn is set if there are multiple merge bases.
+ *  - base, left, and right point to the names to use in a
+ *    warning about multiple merge bases.
+ *
+ * If there is no symmetric diff argument, sym->skip is NULL and
+ * sym->warn is cleared.  The remaining fields are not set.
+ */
+static void symdiff_prepare(struct rev_info *rev, struct symdiff *sym)
+{
+	int i, is_symdiff = 0, basecount = 0, othercount = 0;
+	int lpos = -1, rpos = -1, basepos = -1;
+	struct bitmap *map = NULL;
+
+	/*
+	 * Use the whence fields to find merge bases and left and
+	 * right parts of symmetric difference, so that we do not
+	 * depend on the order that revisions are parsed.  If there
+	 * are any revs that aren't from these sources, we have a
+	 * "git diff C A...B" or "git diff A...B C" case.  Or we
+	 * could even get "git diff A...B C...E", for instance.
+	 *
+	 * If we don't have just one merge base, we pick one
+	 * at random.
+	 *
+	 * NB: REV_CMD_LEFT, REV_CMD_RIGHT are also used for A..B,
+	 * so we must check for SYMMETRIC_LEFT too.  The two arrays
+	 * rev->pending.objects and rev->cmdline.rev are parallel.
+	 */
+	for (i = 0; i < rev->cmdline.nr; i++) {
+		struct object *obj = rev->pending.objects[i].item;
+		switch (rev->cmdline.rev[i].whence) {
+		case REV_CMD_MERGE_BASE:
+			if (basepos < 0)
+				basepos = i;
+			basecount++;
+			break;		/* do mark all bases */
+		case REV_CMD_LEFT:
+			if (lpos >= 0)
+				usage(builtin_diff_usage);
+			lpos = i;
+			if (obj->flags & SYMMETRIC_LEFT) {
+				is_symdiff = 1;
+				break;	/* do mark A */
+			}
+			continue;
+		case REV_CMD_RIGHT:
+			if (rpos >= 0)
+				usage(builtin_diff_usage);
+			rpos = i;
+			continue;	/* don't mark B */
+		case REV_CMD_PARENTS_ONLY:
+		case REV_CMD_REF:
+		case REV_CMD_REV:
+			othercount++;
+			continue;
+		}
+		if (map == NULL)
+			map = bitmap_new();
+		bitmap_set(map, i);
+	}
+
+	/*
+	 * Forbid any additional revs for both A...B and A..B.
+	 */
+	if (lpos >= 0 && othercount > 0)
+		usage(builtin_diff_usage);
+
+	if (!is_symdiff) {
+		bitmap_free(map);
+		sym->warn = 0;
+		sym->skip = NULL;
+		return;
+	}
+
+	sym->left = rev->pending.objects[lpos].name;
+	sym->right = rev->pending.objects[rpos].name;
+	if (basecount == 0)
+		die(_("%s...%s: no merge base"), sym->left, sym->right);
+	sym->base = rev->pending.objects[basepos].name;
+	bitmap_unset(map, basepos);	/* unmark the base we want */
+	sym->warn = basecount > 1;
+	sym->skip = map;
+}
+
 int cmd_diff(int argc, const char **argv, const char *prefix)
 {
 	int i;
@@ -263,19 +372,29 @@
 	struct object_array_entry *blob[2];
 	int nongit = 0, no_index = 0;
 	int result = 0;
+	struct symdiff sdiff;
 
 	/*
 	 * We could get N tree-ish in the rev.pending_objects list.
-	 * Also there could be M blobs there, and P pathspecs.
+	 * Also there could be M blobs there, and P pathspecs. --cached may
+	 * also be present.
 	 *
 	 * N=0, M=0:
-	 *	cache vs files (diff-files)
+	 *      cache vs files (diff-files)
+	 *
+	 * N=0, M=0, --cached:
+	 *      HEAD vs cache (diff-index --cached)
+	 *
 	 * N=0, M=2:
 	 *      compare two random blobs.  P must be zero.
+	 *
 	 * N=0, M=1, P=1:
-	 *	compare a blob with a working tree file.
+	 *      compare a blob with a working tree file.
 	 *
 	 * N=1, M=0:
+	 *      tree vs files (diff-index)
+	 *
+	 * N=1, M=0, --cached:
 	 *      tree vs cache (diff-index --cached)
 	 *
 	 * N=2, M=0:
@@ -382,6 +501,7 @@
 		}
 	}
 
+	symdiff_prepare(&rev, &sdiff);
 	for (i = 0; i < rev.pending.nr; i++) {
 		struct object_array_entry *entry = &rev.pending.objects[i];
 		struct object *obj = entry->item;
@@ -396,6 +516,8 @@
 			obj = &get_commit_tree(((struct commit *)obj))->object;
 
 		if (obj->type == OBJ_TREE) {
+			if (sdiff.skip && bitmap_get(sdiff.skip, i))
+				continue;
 			obj->flags |= flags;
 			add_object_array(obj, name, &ent);
 		} else if (obj->type == OBJ_BLOB) {
@@ -437,21 +559,12 @@
 		usage(builtin_diff_usage);
 	else if (ent.nr == 1)
 		result = builtin_diff_index(&rev, argc, argv);
-	else if (ent.nr == 2)
+	else if (ent.nr == 2) {
+		if (sdiff.warn)
+			warning(_("%s...%s: multiple merge bases, using %s"),
+				sdiff.left, sdiff.right, sdiff.base);
 		result = builtin_diff_tree(&rev, argc, argv,
 					   &ent.objects[0], &ent.objects[1]);
-	else if (ent.objects[0].item->flags & UNINTERESTING) {
-		/*
-		 * diff A...B where there is at least one merge base
-		 * between A and B.  We have ent.objects[0] ==
-		 * merge-base, ent.objects[ents-2] == A, and
-		 * ent.objects[ents-1] == B.  Show diff between the
-		 * base and B.  Note that we pick one merge base at
-		 * random if there are more than one.
-		 */
-		result = builtin_diff_tree(&rev, argc, argv,
-					   &ent.objects[0],
-					   &ent.objects[ent.nr-1]);
 	} else
 		result = builtin_diff_combined(&rev, argc, argv,
 					       ent.objects, ent.nr);
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 8586816..9f37895 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -45,6 +45,7 @@
 static struct string_list tag_refs = STRING_LIST_INIT_NODUP;
 static struct refspec refspecs = REFSPEC_INIT_FETCH;
 static int anonymize;
+static struct hashmap anonymized_seeds;
 static struct revision_sources revision_sources;
 
 static int parse_opt_signed_tag_mode(const struct option *opt,
@@ -120,24 +121,33 @@
 
 struct anonymized_entry {
 	struct hashmap_entry hash;
+	const char *anon;
+	const char orig[FLEX_ARRAY];
+};
+
+struct anonymized_entry_key {
+	struct hashmap_entry hash;
 	const char *orig;
 	size_t orig_len;
-	const char *anon;
-	size_t anon_len;
 };
 
 static int anonymized_entry_cmp(const void *unused_cmp_data,
 				const struct hashmap_entry *eptr,
 				const struct hashmap_entry *entry_or_key,
-				const void *unused_keydata)
+				const void *keydata)
 {
 	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);
+	if (keydata) {
+		const struct anonymized_entry_key *key = keydata;
+		int equal = !strncmp(a->orig, key->orig, key->orig_len) &&
+			    !a->orig[key->orig_len];
+		return !equal;
+	}
 
-	return a->orig_len != b->orig_len ||
-		memcmp(a->orig, b->orig, a->orig_len);
+	b = container_of(entry_or_key, const struct anonymized_entry, hash);
+	return strcmp(a->orig, b->orig);
 }
 
 /*
@@ -145,31 +155,39 @@
  * the same anonymized string with another. The actual generation
  * is farmed out to the generate function.
  */
-static const void *anonymize_mem(struct hashmap *map,
-				 void *(*generate)(const void *, size_t *),
-				 const void *orig, size_t *len)
+static const char *anonymize_str(struct hashmap *map,
+				 char *(*generate)(void *),
+				 const char *orig, size_t len,
+				 void *data)
 {
-	struct anonymized_entry key, *ret;
+	struct anonymized_entry_key key;
+	struct anonymized_entry *ret;
 
 	if (!map->cmpfn)
 		hashmap_init(map, anonymized_entry_cmp, NULL, 0);
 
-	hashmap_entry_init(&key.hash, memhash(orig, *len));
+	hashmap_entry_init(&key.hash, memhash(orig, len));
 	key.orig = orig;
-	key.orig_len = *len;
-	ret = hashmap_get_entry(map, &key, hash, NULL);
+	key.orig_len = len;
 
+	/* First check if it's a token the user configured manually... */
+	if (anonymized_seeds.cmpfn)
+		ret = hashmap_get_entry(&anonymized_seeds, &key, hash, &key);
+	else
+		ret = NULL;
+
+	/* ...otherwise check if we've already seen it in this context... */
+	if (!ret)
+		ret = hashmap_get_entry(map, &key, hash, &key);
+
+	/* ...and finally generate a new mapping if necessary */
 	if (!ret) {
-		ret = xmalloc(sizeof(*ret));
+		FLEX_ALLOC_MEM(ret, orig, orig, len);
 		hashmap_entry_init(&ret->hash, key.hash.hash);
-		ret->orig = xstrdup(orig);
-		ret->orig_len = *len;
-		ret->anon = generate(orig, len);
-		ret->anon_len = *len;
+		ret->anon = generate(data);
 		hashmap_put(map, &ret->hash);
 	}
 
-	*len = ret->anon_len;
 	return ret->anon;
 }
 
@@ -181,13 +199,13 @@
  */
 static void anonymize_path(struct strbuf *out, const char *path,
 			   struct hashmap *map,
-			   void *(*generate)(const void *, size_t *))
+			   char *(*generate)(void *))
 {
 	while (*path) {
 		const char *end_of_component = strchrnul(path, '/');
 		size_t len = end_of_component - path;
-		const char *c = anonymize_mem(map, generate, path, &len);
-		strbuf_add(out, c, len);
+		const char *c = anonymize_str(map, generate, path, len, NULL);
+		strbuf_addstr(out, c);
 		path = end_of_component;
 		if (*path)
 			strbuf_addch(out, *path++);
@@ -361,12 +379,12 @@
 		printf("%s", path);
 }
 
-static void *anonymize_path_component(const void *path, size_t *len)
+static char *anonymize_path_component(void *data)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
 	strbuf_addf(&out, "path%d", counter++);
-	return strbuf_detach(&out, len);
+	return strbuf_detach(&out, NULL);
 }
 
 static void print_path(const char *path)
@@ -383,20 +401,23 @@
 	}
 }
 
-static void *generate_fake_oid(const void *old, size_t *len)
+static char *generate_fake_oid(void *data)
 {
 	static uint32_t counter = 1; /* avoid null oid */
 	const unsigned hashsz = the_hash_algo->rawsz;
-	unsigned char *out = xcalloc(hashsz, 1);
+	unsigned char out[GIT_MAX_RAWSZ];
+	char *hex = xmallocz(GIT_MAX_HEXSZ);
+
+	hashclr(out);
 	put_be32(out + hashsz - 4, counter++);
-	return out;
+	return hash_to_hex_algop_r(hex, out, the_hash_algo);
 }
 
-static const struct object_id *anonymize_oid(const struct object_id *oid)
+static const char *anonymize_oid(const char *oid_hex)
 {
 	static struct hashmap objs;
-	size_t len = the_hash_algo->rawsz;
-	return anonymize_mem(&objs, generate_fake_oid, oid, &len);
+	size_t len = strlen(oid_hex);
+	return anonymize_str(&objs, generate_fake_oid, oid_hex, len, NULL);
 }
 
 static void show_filemodify(struct diff_queue_struct *q,
@@ -455,9 +476,9 @@
 			 */
 			if (no_data || S_ISGITLINK(spec->mode))
 				printf("M %06o %s ", spec->mode,
-				       oid_to_hex(anonymize ?
-						  anonymize_oid(&spec->oid) :
-						  &spec->oid));
+				       anonymize ?
+				       anonymize_oid(oid_to_hex(&spec->oid)) :
+				       oid_to_hex(&spec->oid));
 			else {
 				struct object *object = lookup_object(the_repository,
 								      &spec->oid);
@@ -493,12 +514,12 @@
 	return bol;
 }
 
-static void *anonymize_ref_component(const void *old, size_t *len)
+static char *anonymize_ref_component(void *data)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
 	strbuf_addf(&out, "ref%d", counter++);
-	return strbuf_detach(&out, len);
+	return strbuf_detach(&out, NULL);
 }
 
 static const char *anonymize_refname(const char *refname)
@@ -517,13 +538,6 @@
 	static struct strbuf anon = STRBUF_INIT;
 	int i;
 
-	/*
-	 * We also leave "master" as a special case, since it does not reveal
-	 * anything interesting.
-	 */
-	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
-
 	strbuf_reset(&anon);
 	for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
 		if (skip_prefix(refname, prefixes[i], &refname)) {
@@ -546,14 +560,13 @@
 	return xstrfmt("subject %d\n\nbody\n", counter++);
 }
 
-static struct hashmap idents;
-static void *anonymize_ident(const void *old, size_t *len)
+static char *anonymize_ident(void *data)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
 	strbuf_addf(&out, "User %d <user%d@example.com>", counter, counter);
 	counter++;
-	return strbuf_detach(&out, len);
+	return strbuf_detach(&out, NULL);
 }
 
 /*
@@ -563,6 +576,7 @@
  */
 static void anonymize_ident_line(const char **beg, const char **end)
 {
+	static struct hashmap idents;
 	static struct strbuf buffers[] = { STRBUF_INIT, STRBUF_INIT };
 	static unsigned which_buffer;
 
@@ -588,9 +602,9 @@
 		size_t len;
 
 		len = split.mail_end - split.name_begin;
-		ident = anonymize_mem(&idents, anonymize_ident,
-				      split.name_begin, &len);
-		strbuf_add(out, ident, len);
+		ident = anonymize_str(&idents, anonymize_ident,
+				      split.name_begin, len, NULL);
+		strbuf_addstr(out, ident);
 		strbuf_addch(out, ' ');
 		strbuf_add(out, split.date_begin, split.tz_end - split.date_begin);
 	} else {
@@ -712,9 +726,10 @@
 		if (mark)
 			printf(":%d\n", mark);
 		else
-			printf("%s\n", oid_to_hex(anonymize ?
-						  anonymize_oid(&obj->oid) :
-						  &obj->oid));
+			printf("%s\n",
+			       anonymize ?
+			       anonymize_oid(oid_to_hex(&obj->oid)) :
+			       oid_to_hex(&obj->oid));
 		i++;
 	}
 
@@ -729,12 +744,12 @@
 	show_progress();
 }
 
-static void *anonymize_tag(const void *old, size_t *len)
+static char *anonymize_tag(void *data)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
 	strbuf_addf(&out, "tag message %d", counter++);
-	return strbuf_detach(&out, len);
+	return strbuf_detach(&out, NULL);
 }
 
 static void handle_tail(struct object_array *commits, struct rev_info *revs,
@@ -804,8 +819,8 @@
 		name = anonymize_refname(name);
 		if (message) {
 			static struct hashmap tags;
-			message = anonymize_mem(&tags, anonymize_tag,
-						message, &message_size);
+			message = anonymize_str(&tags, anonymize_tag,
+						message, message_size, NULL);
 		}
 	}
 
@@ -1136,6 +1151,37 @@
 	}
 }
 
+static char *anonymize_seed(void *data)
+{
+	return xstrdup(data);
+}
+
+static int parse_opt_anonymize_map(const struct option *opt,
+				   const char *arg, int unset)
+{
+	struct hashmap *map = opt->value;
+	const char *delim, *value;
+	size_t keylen;
+
+	BUG_ON_OPT_NEG(unset);
+
+	delim = strchr(arg, ':');
+	if (delim) {
+		keylen = delim - arg;
+		value = delim + 1;
+	} else {
+		keylen = strlen(arg);
+		value = arg;
+	}
+
+	if (!keylen || !*value)
+		return error(_("--anonymize-map token cannot be empty"));
+
+	anonymize_str(map, anonymize_seed, arg, keylen, (void *)value);
+
+	return 0;
+}
+
 int cmd_fast_export(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
@@ -1177,6 +1223,9 @@
 		OPT_STRING_LIST(0, "refspec", &refspecs_list, N_("refspec"),
 			     N_("Apply refspec to exported refs")),
 		OPT_BOOL(0, "anonymize", &anonymize, N_("anonymize output")),
+		OPT_CALLBACK_F(0, "anonymize-map", &anonymized_seeds, N_("from:to"),
+			       N_("convert <from> to <to> in anonymized output"),
+			       PARSE_OPT_NONEG, parse_opt_anonymize_map),
 		OPT_BOOL(0, "reference-excluded-parents",
 			 &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,
@@ -1204,6 +1253,9 @@
 	if (argc > 1)
 		usage_with_options (fast_export_usage, options);
 
+	if (anonymized_seeds.cmpfn && !anonymize)
+		die(_("--anonymize-map without --anonymize does not make sense"));
+
 	if (refspecs_list.nr) {
 		int i;
 
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 94b0c89..bbb5c96 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -48,8 +48,8 @@
 	struct ref **sought = NULL;
 	int nr_sought = 0, alloc_sought = 0;
 	int fd[2];
-	char *pack_lockfile = NULL;
-	char **pack_lockfile_ptr = NULL;
+	struct string_list pack_lockfiles = STRING_LIST_INIT_DUP;
+	struct string_list *pack_lockfiles_ptr = NULL;
 	struct child_process *conn;
 	struct fetch_pack_args args;
 	struct oid_array shallow = OID_ARRAY_INIT;
@@ -134,7 +134,7 @@
 		}
 		if (!strcmp("--lock-pack", arg)) {
 			args.lock_pack = 1;
-			pack_lockfile_ptr = &pack_lockfile;
+			pack_lockfiles_ptr = &pack_lockfiles;
 			continue;
 		}
 		if (!strcmp("--check-self-contained-and-connected", arg)) {
@@ -235,10 +235,15 @@
 	}
 
 	ref = fetch_pack(&args, fd, ref, sought, nr_sought,
-			 &shallow, pack_lockfile_ptr, version);
-	if (pack_lockfile) {
-		printf("lock %s\n", pack_lockfile);
+			 &shallow, pack_lockfiles_ptr, version);
+	if (pack_lockfiles.nr) {
+		int i;
+
+		printf("lock %s\n", pack_lockfiles.items[0].string);
 		fflush(stdout);
+		for (i = 1; i < pack_lockfiles.nr; i++)
+			warning(_("Lockfile created but not reported: %s"),
+				pack_lockfiles.items[i].string);
 	}
 	if (args.check_self_contained_and_connected &&
 	    args.self_contained_and_connected) {
diff --git a/builtin/fetch.c b/builtin/fetch.c
index b5788c1..82ac4be 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1758,8 +1758,13 @@
 
 	/* 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]);
+	for (i = 1; i < argc; i++) {
+		/* This handles non-URLs gracefully */
+		char *anon = transport_anonymize_url(argv[i]);
+
+		strbuf_addf(&default_rla, " %s", anon);
+		free(anon);
+	}
 
 	fetch_config_from_gitmodules(&submodule_fetch_jobs_config,
 				     &recurse_submodules);
@@ -1790,9 +1795,6 @@
 	if (depth || deepen_since || deepen_not.nr)
 		deepen = 1;
 
-	if (filter_options.choice && !has_promisor_remote())
-		die("--filter can only be used when extensions.partialClone is set");
-
 	if (all) {
 		if (argc == 1)
 			die(_("fetch --all does not take a repository argument"));
diff --git a/builtin/fsck.c b/builtin/fsck.c
index f02cbdb..37aa07d 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -241,7 +241,7 @@
 		enum object_type type = oid_object_info(the_repository,
 							&obj->oid, NULL);
 		if (type > 0)
-			object_as_type(the_repository, obj, type, 0);
+			object_as_type(obj, type, 0);
 	}
 
 	options.walk = mark_used;
@@ -577,7 +577,7 @@
 
 	for_each_rawref(fsck_handle_ref, NULL);
 
-	worktrees = get_worktrees(0);
+	worktrees = get_worktrees();
 	for (p = worktrees; *p; p++) {
 		struct worktree *wt = *p;
 		struct strbuf ref = STRBUF_INIT;
diff --git a/builtin/grep.c b/builtin/grep.c
index a5056f3..5975cf5 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -466,7 +466,7 @@
 		struct strbuf base = STRBUF_INIT;
 
 		obj_read_lock();
-		object = parse_object_or_die(oid, oid_to_hex(oid));
+		object = parse_object_or_die(oid, NULL);
 		obj_read_unlock();
 		data = read_object_with_reference(&subrepo,
 						  &object->oid, tree_type,
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index f176dd2..f865666 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1555,13 +1555,9 @@
 {
 	const uint32_t *idx1, *idx2;
 	uint32_t i;
-	const uint32_t hashwords = the_hash_algo->rawsz / sizeof(uint32_t);
 
 	/* The address of the 4-byte offset table */
-	idx1 = (((const uint32_t *)p->index_data)
-		+ 2 /* 8-byte header */
-		+ 256 /* fan out */
-		+ hashwords * p->num_objects /* object ID table */
+	idx1 = (((const uint32_t *)((const uint8_t *)p->index_data + p->crc_offset))
 		+ p->num_objects /* CRC32 table */
 		);
 
@@ -1671,6 +1667,7 @@
 	unsigned char pack_hash[GIT_MAX_RAWSZ];
 	unsigned foreign_nr = 1;	/* zero is a "good" value, assume bad */
 	int report_end_of_input = 0;
+	int hash_algo = 0;
 
 	/*
 	 * index-pack never needs to fetch missing objects except when
@@ -1764,6 +1761,11 @@
 					die(_("bad %s"), arg);
 			} else if (skip_prefix(arg, "--max-input-size=", &arg)) {
 				max_input_size = strtoumax(arg, NULL, 10);
+			} else if (skip_prefix(arg, "--object-format=", &arg)) {
+				hash_algo = hash_algo_by_name(arg);
+				if (hash_algo == GIT_HASH_UNKNOWN)
+					die(_("unknown hash algorithm '%s'"), arg);
+				repo_set_hash_algo(the_repository, hash_algo);
 			} else
 				usage(index_pack_usage);
 			continue;
@@ -1780,6 +1782,8 @@
 		die(_("--fix-thin cannot be used without --stdin"));
 	if (from_stdin && !startup_info->have_repository)
 		die(_("--stdin requires a git repository"));
+	if (from_stdin && hash_algo)
+		die(_("--object-format cannot be used with --stdin"));
 	if (!index_name && pack_name)
 		index_name = derive_filename(pack_name, "idx", &index_name_buf);
 
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 0b7222e..cee6482 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -203,6 +203,7 @@
 
 static int create_default_files(const char *template_path,
 				const char *original_git_dir,
+				const char *initial_branch,
 				const struct repository_format *fmt)
 {
 	struct stat st1;
@@ -258,15 +259,26 @@
 		die("failed to set up refs db: %s", err.buf);
 
 	/*
-	 * Create the default symlink from ".git/HEAD" to the "master"
-	 * branch, if it does not exist yet.
+	 * Point the HEAD symref to the initial branch with if HEAD does
+	 * not yet exist.
 	 */
 	path = git_path_buf(&buf, "HEAD");
 	reinit = (!access(path, R_OK)
 		  || readlink(path, junk, sizeof(junk)-1) != -1);
 	if (!reinit) {
-		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
+		char *ref;
+
+		if (!initial_branch)
+			initial_branch = git_default_branch_name();
+
+		ref = xstrfmt("refs/heads/%s", initial_branch);
+		if (check_refname_format(ref, 0) < 0)
+			die(_("invalid initial branch name: '%s'"),
+			    initial_branch);
+
+		if (create_symref("HEAD", ref, NULL) < 0)
 			exit(1);
+		free(ref);
 	}
 
 	initialize_repository_version(fmt->hash_algo);
@@ -383,7 +395,8 @@
 }
 
 int init_db(const char *git_dir, const char *real_git_dir,
-	    const char *template_dir, int hash, unsigned int flags)
+	    const char *template_dir, int hash, const char *initial_branch,
+	    unsigned int flags)
 {
 	int reinit;
 	int exist_ok = flags & INIT_DB_EXIST_OK;
@@ -425,7 +438,11 @@
 
 	validate_hash_algorithm(&repo_fmt, hash);
 
-	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
+	reinit = create_default_files(template_dir, original_git_dir,
+				      initial_branch, &repo_fmt);
+	if (reinit && initial_branch)
+		warning(_("re-init: ignored --initial-branch=%s"),
+			initial_branch);
 
 	create_object_directory();
 
@@ -528,6 +545,7 @@
 	const char *template_dir = NULL;
 	unsigned int flags = 0;
 	const char *object_format = NULL;
+	const char *initial_branch = NULL;
 	int hash_algo = GIT_HASH_UNKNOWN;
 	const struct option init_db_options[] = {
 		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
@@ -541,6 +559,8 @@
 		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
 		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
 			   N_("separate git dir from working tree")),
+		OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
+			   N_("override the name of the initial branch")),
 		OPT_STRING(0, "object-format", &object_format, N_("hash"),
 			   N_("specify the hash algorithm to use")),
 		OPT_END()
@@ -652,5 +672,6 @@
 	UNLEAK(work_tree);
 
 	flags |= INIT_DB_EXIST_OK;
-	return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
+	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
+		       initial_branch, flags);
 }
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 6ef5195..3a4dd12 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -118,6 +118,10 @@
 		transport->server_options = &server_options;
 
 	ref = transport_get_remote_refs(transport, &ref_prefixes);
+	if (ref) {
+		int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
+		repo_set_hash_algo(the_repository, hash_algo);
+	}
 	if (transport_disconnect(transport)) {
 		UNLEAK(sorting);
 		return 1;
diff --git a/builtin/mv.c b/builtin/mv.c
index be15ba7..7dac714 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -132,6 +132,7 @@
 	struct stat st;
 	struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
 	struct lock_file lock_file = LOCK_INIT;
+	struct cache_entry *ce;
 
 	git_config(git_default_config, NULL);
 
@@ -220,9 +221,11 @@
 				}
 				argc += last - first;
 			}
-		} else if (cache_name_pos(src, length) < 0)
+		} else if (!(ce = cache_file_exists(src, length, ignore_case))) {
 			bad = _("not under version control");
-		else if (lstat(dst, &st) == 0 &&
+		} else if (ce_stage(ce)) {
+			bad = _("conflicted");
+		} else if (lstat(dst, &st) == 0 &&
 			 (!ignore_case || strcasecmp(src, dst))) {
 			bad = _("destination exists");
 			if (force) {
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index c5b433a..7016b28 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -117,6 +117,8 @@
 
 static struct list_objects_filter_options filter_options;
 
+static struct string_list uri_protocols = STRING_LIST_INIT_NODUP;
+
 enum missing_action {
 	MA_ERROR = 0,      /* fail if any missing objects are encountered */
 	MA_ALLOW_ANY,      /* silently allow ALL missing objects */
@@ -125,6 +127,15 @@
 static enum missing_action arg_missing_action;
 static show_object_fn fn_show_object;
 
+struct configured_exclusion {
+	struct oidmap_entry e;
+	char *pack_hash_hex;
+	char *uri;
+};
+static struct oidmap configured_exclusions;
+
+static struct oidset excluded_by_config;
+
 /*
  * stats
  */
@@ -969,6 +980,25 @@
 	unuse_pack(&w_curs);
 }
 
+static void write_excluded_by_configs(void)
+{
+	struct oidset_iter iter;
+	const struct object_id *oid;
+
+	oidset_iter_init(&excluded_by_config, &iter);
+	while ((oid = oidset_iter_next(&iter))) {
+		struct configured_exclusion *ex =
+			oidmap_get(&configured_exclusions, oid);
+
+		if (!ex)
+			BUG("configured exclusion wasn't configured");
+		write_in_full(1, ex->pack_hash_hex, strlen(ex->pack_hash_hex));
+		write_in_full(1, " ", 1);
+		write_in_full(1, ex->uri, strlen(ex->uri));
+		write_in_full(1, "\n", 1);
+	}
+}
+
 static const char no_split_warning[] = N_(
 "disabling bitmap writing, packs are split due to pack.packSizeLimit"
 );
@@ -1266,6 +1296,25 @@
 		}
 	}
 
+	if (uri_protocols.nr) {
+		struct configured_exclusion *ex =
+			oidmap_get(&configured_exclusions, oid);
+		int i;
+		const char *p;
+
+		if (ex) {
+			for (i = 0; i < uri_protocols.nr; i++) {
+				if (skip_prefix(ex->uri,
+						uri_protocols.items[i].string,
+						&p) &&
+				    *p == ':') {
+					oidset_insert(&excluded_by_config, oid);
+					return 0;
+				}
+			}
+		}
+	}
+
 	return 1;
 }
 
@@ -2864,6 +2913,29 @@
 			    pack_idx_opts.version);
 		return 0;
 	}
+	if (!strcmp(k, "uploadpack.blobpackfileuri")) {
+		struct configured_exclusion *ex = xmalloc(sizeof(*ex));
+		const char *oid_end, *pack_end;
+		/*
+		 * Stores the pack hash. This is not a true object ID, but is
+		 * of the same form.
+		 */
+		struct object_id pack_hash;
+
+		if (parse_oid_hex(v, &ex->e.oid, &oid_end) ||
+		    *oid_end != ' ' ||
+		    parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) ||
+		    *pack_end != ' ')
+			die(_("value of uploadpack.blobpackfileuri must be "
+			      "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v);
+		if (oidmap_get(&configured_exclusions, &ex->e.oid))
+			die(_("object already configured in another "
+			      "uploadpack.blobpackfileuri (got '%s')"), v);
+		ex->pack_hash_hex = xcalloc(1, pack_end - oid_end);
+		memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1);
+		ex->uri = xstrdup(pack_end + 1);
+		oidmap_put(&configured_exclusions, ex);
+	}
 	return git_default_config(k, v, cb);
 }
 
@@ -3462,6 +3534,9 @@
 			 N_("do not pack objects in promisor packfiles")),
 		OPT_BOOL(0, "delta-islands", &use_delta_islands,
 			 N_("respect islands during delta compression")),
+		OPT_STRING_LIST(0, "uri-protocol", &uri_protocols,
+				N_("protocol"),
+				N_("exclude any configured uploadpack.blobpackfileuri with this protocol")),
 		OPT_END(),
 	};
 
@@ -3650,6 +3725,7 @@
 	}
 
 	trace2_region_enter("pack-objects", "write-pack-file", the_repository);
+	write_excluded_by_configs();
 	write_pack_file();
 	trace2_region_leave("pack-objects", "write-pack-file", the_repository);
 
diff --git a/builtin/pull.c b/builtin/pull.c
index 00e5857..8159c5d 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -1025,12 +1025,14 @@
 			commit_list_insert(head, &list);
 			merge_head = lookup_commit_reference(the_repository,
 							     &merge_heads.oid[0]);
-			if (is_descendant_of(merge_head, list)) {
+			if (repo_is_descendant_of(the_repository,
+						  merge_head, list)) {
 				/* we can fast-forward this without invoking rebase */
 				opt_ff = "--ff-only";
 				ran_ff = 1;
 				ret = run_merge();
 			}
+			free_commit_list(list);
 		}
 		if (!ran_ff)
 			ret = run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point);
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index ea3d0f0..d43663b 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -249,6 +249,7 @@
 			strbuf_addf(&cap, " push-cert=%s", push_cert_nonce);
 		if (advertise_push_options)
 			strbuf_addstr(&cap, " push-options");
+		strbuf_addf(&cap, " object-format=%s", the_hash_algo->name);
 		strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized());
 		packet_write_fmt(1, "%s %s%c%s\n",
 			     oid_to_hex(oid), path, 0, cap.buf);
@@ -1624,6 +1625,8 @@
 		linelen = strlen(reader->line);
 		if (linelen < reader->pktlen) {
 			const char *feature_list = reader->line + linelen + 1;
+			const char *hash = NULL;
+			int len = 0;
 			if (parse_feature_request(feature_list, "report-status"))
 				report_status = 1;
 			if (parse_feature_request(feature_list, "side-band-64k"))
@@ -1636,6 +1639,13 @@
 			if (advertise_push_options
 			    && parse_feature_request(feature_list, "push-options"))
 				use_push_options = 1;
+			hash = parse_feature_value(feature_list, "object-format", &len, NULL);
+			if (!hash) {
+				hash = hash_algos[GIT_HASH_SHA1].name;
+				len = strlen(hash);
+			}
+			if (xstrncmpz(the_hash_algo->name, hash, len))
+				die("error: unsupported object format '%s'", hash);
 		}
 
 		if (!strcmp(reader->line, "push-cert")) {
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 52ecf6d..ca1d807 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -615,7 +615,7 @@
 		int i;
 
 		memset(&collected, 0, sizeof(collected));
-		worktrees = get_worktrees(0);
+		worktrees = get_worktrees();
 		for (p = worktrees; *p; p++) {
 			if (!all_worktrees && !(*p)->is_current)
 				continue;
diff --git a/builtin/show-index.c b/builtin/show-index.c
index 0826f6a..8106b03 100644
--- a/builtin/show-index.c
+++ b/builtin/show-index.c
@@ -1,9 +1,12 @@
 #include "builtin.h"
 #include "cache.h"
 #include "pack.h"
+#include "parse-options.h"
 
-static const char show_index_usage[] =
-"git show-index";
+static const char *const show_index_usage[] = {
+	"git show-index [--object-format=<hash-algorithm>]",
+	NULL
+};
 
 int cmd_show_index(int argc, const char **argv, const char *prefix)
 {
@@ -11,10 +14,26 @@
 	unsigned nr;
 	unsigned int version;
 	static unsigned int top_index[256];
-	const unsigned hashsz = the_hash_algo->rawsz;
+	unsigned hashsz;
+	const char *hash_name = NULL;
+	int hash_algo;
+	const struct option show_index_options[] = {
+		OPT_STRING(0, "object-format", &hash_name, N_("hash-algorithm"),
+			   N_("specify the hash algorithm to use")),
+		OPT_END()
+	};
 
-	if (argc != 1)
-		usage(show_index_usage);
+	argc = parse_options(argc, argv, prefix, show_index_options, show_index_usage, 0);
+
+	if (hash_name) {
+		hash_algo = hash_algo_by_name(hash_name);
+		if (hash_algo == GIT_HASH_UNKNOWN)
+			die(_("Unknown hash algorithm"));
+		repo_set_hash_algo(the_repository, hash_algo);
+	}
+
+	hashsz = the_hash_algo->rawsz;
+
 	if (fread(top_index, 2 * 4, 1, stdin) != 1)
 		die("unable to read header");
 	if (top_index[0] == htonl(PACK_IDX_SIGNATURE)) {
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 95d0882..4003f4d 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -99,6 +99,10 @@
 	struct lock_file lock_file = LOCK_INIT;
 	struct repository *r = the_repository;
 
+	/* If no branch has been checked out, there are no updates to make. */
+	if (is_index_unborn(r->index))
+		return UPDATE_SPARSITY_SUCCESS;
+
 	memset(&o, 0, sizeof(o));
 	o.verbose_update = isatty(2);
 	o.update = 1;
@@ -249,6 +253,8 @@
 {
 	const char *config_path;
 
+	if (upgrade_repository_format(1) < 0)
+		die(_("unable to upgrade repository format to enable worktreeConfig"));
 	if (git_config_set_gently("extensions.worktreeConfig", "true")) {
 		error(_("failed to set extensions.worktreeConfig setting"));
 		return 1;
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 46c03d2..a1c7560 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1981,7 +1981,7 @@
 	free(key);
 
 	if (!branch)
-		return "master";
+		return "HEAD";
 
 	if (!strcmp(branch, ".")) {
 		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
@@ -2277,6 +2277,49 @@
 	return 0;
 }
 
+static int module_set_branch(int argc, const char **argv, const char *prefix)
+{
+	int opt_default = 0, ret;
+	const char *opt_branch = NULL;
+	const char *path;
+	char *config_name;
+
+	/*
+	 * We accept the `quiet` option for uniformity across subcommands,
+	 * though there is nothing to make less verbose in this subcommand.
+	 */
+	struct option options[] = {
+		OPT_NOOP_NOARG('q', "quiet"),
+		OPT_BOOL('d', "default", &opt_default,
+			N_("set the default tracking branch to master")),
+		OPT_STRING('b', "branch", &opt_branch, N_("branch"),
+			N_("set the default tracking branch")),
+		OPT_END()
+	};
+	const char *const usage[] = {
+		N_("git submodule--helper set-branch [-q|--quiet] (-d|--default) <path>"),
+		N_("git submodule--helper set-branch [-q|--quiet] (-b|--branch) <branch> <path>"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, options, usage, 0);
+
+	if (!opt_branch && !opt_default)
+		die(_("--branch or --default required"));
+
+	if (opt_branch && opt_default)
+		die(_("--branch and --default are mutually exclusive"));
+
+	if (argc != 1 || !(path = argv[0]))
+		usage_with_options(usage, options);
+
+	config_name = xstrfmt("submodule.%s.branch", path);
+	ret = config_set_in_gitmodules_file_gently(config_name, opt_branch);
+
+	free(config_name);
+	return !!ret;
+}
+
 #define SUPPORT_SUPER_PREFIX (1<<0)
 
 struct cmd_struct {
@@ -2308,6 +2351,7 @@
 	{"check-name", check_name, 0},
 	{"config", module_config, 0},
 	{"set-url", module_set_url, 0},
+	{"set-branch", module_set_branch, 0},
 };
 
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index d99db35..f0cbdef 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -67,7 +67,12 @@
 	rmdir(git_path("worktrees")); /* ignore failed removal */
 }
 
-static int prune_worktree(const char *id, struct strbuf *reason)
+/*
+ * Return true if worktree entry should be pruned, along with the reason for
+ * pruning. Otherwise, return false and the worktree's path, or NULL if it
+ * cannot be determined. Caller is responsible for freeing returned path.
+ */
+static int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath)
 {
 	struct stat st;
 	char *path;
@@ -75,20 +80,21 @@
 	size_t len;
 	ssize_t read_result;
 
+	*wtpath = NULL;
 	if (!is_directory(git_path("worktrees/%s", id))) {
-		strbuf_addf(reason, _("Removing worktrees/%s: not a valid directory"), id);
+		strbuf_addstr(reason, _("not a valid directory"));
 		return 1;
 	}
 	if (file_exists(git_path("worktrees/%s/locked", id)))
 		return 0;
 	if (stat(git_path("worktrees/%s/gitdir", id), &st)) {
-		strbuf_addf(reason, _("Removing worktrees/%s: gitdir file does not exist"), id);
+		strbuf_addstr(reason, _("gitdir file does not exist"));
 		return 1;
 	}
 	fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY);
 	if (fd < 0) {
-		strbuf_addf(reason, _("Removing worktrees/%s: unable to read gitdir file (%s)"),
-			    id, strerror(errno));
+		strbuf_addf(reason, _("unable to read gitdir file (%s)"),
+			    strerror(errno));
 		return 1;
 	}
 	len = xsize_t(st.st_size);
@@ -96,8 +102,8 @@
 
 	read_result = read_in_full(fd, path, len);
 	if (read_result < 0) {
-		strbuf_addf(reason, _("Removing worktrees/%s: unable to read gitdir file (%s)"),
-			    id, strerror(errno));
+		strbuf_addf(reason, _("unable to read gitdir file (%s)"),
+			    strerror(errno));
 		close(fd);
 		free(path);
 		return 1;
@@ -106,53 +112,103 @@
 
 	if (read_result != len) {
 		strbuf_addf(reason,
-			    _("Removing worktrees/%s: short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"),
-			    id, (uintmax_t)len, (uintmax_t)read_result);
+			    _("short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"),
+			    (uintmax_t)len, (uintmax_t)read_result);
 		free(path);
 		return 1;
 	}
 	while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
 		len--;
 	if (!len) {
-		strbuf_addf(reason, _("Removing worktrees/%s: invalid gitdir file"), id);
+		strbuf_addstr(reason, _("invalid gitdir file"));
 		free(path);
 		return 1;
 	}
 	path[len] = '\0';
 	if (!file_exists(path)) {
-		free(path);
 		if (stat(git_path("worktrees/%s/index", id), &st) ||
 		    st.st_mtime <= expire) {
-			strbuf_addf(reason, _("Removing worktrees/%s: gitdir file points to non-existent location"), id);
+			strbuf_addstr(reason, _("gitdir file points to non-existent location"));
+			free(path);
 			return 1;
 		} else {
+			*wtpath = path;
 			return 0;
 		}
 	}
-	free(path);
+	*wtpath = path;
 	return 0;
 }
 
+static void prune_worktree(const char *id, const char *reason)
+{
+	if (show_only || verbose)
+		printf_ln(_("Removing %s/%s: %s"), "worktrees", id, reason);
+	if (!show_only)
+		delete_git_dir(id);
+}
+
+static int prune_cmp(const void *a, const void *b)
+{
+	const struct string_list_item *x = a;
+	const struct string_list_item *y = b;
+	int c;
+
+	if ((c = fspathcmp(x->string, y->string)))
+	    return c;
+	/*
+	 * paths same; prune_dupes() removes all but the first worktree entry
+	 * having the same path, so sort main worktree ('util' is NULL) above
+	 * linked worktrees ('util' not NULL) since main worktree can't be
+	 * removed
+	 */
+	if (!x->util)
+		return -1;
+	if (!y->util)
+		return 1;
+	/* paths same; sort by .git/worktrees/<id> */
+	return strcmp(x->util, y->util);
+}
+
+static void prune_dups(struct string_list *l)
+{
+	int i;
+
+	QSORT(l->items, l->nr, prune_cmp);
+	for (i = 1; i < l->nr; i++) {
+		if (!fspathcmp(l->items[i].string, l->items[i - 1].string))
+			prune_worktree(l->items[i].util, "duplicate entry");
+	}
+}
+
 static void prune_worktrees(void)
 {
 	struct strbuf reason = STRBUF_INIT;
+	struct strbuf main_path = STRBUF_INIT;
+	struct string_list kept = STRING_LIST_INIT_NODUP;
 	DIR *dir = opendir(git_path("worktrees"));
 	struct dirent *d;
 	if (!dir)
 		return;
 	while ((d = readdir(dir)) != NULL) {
+		char *path;
 		if (is_dot_or_dotdot(d->d_name))
 			continue;
 		strbuf_reset(&reason);
-		if (!prune_worktree(d->d_name, &reason))
-			continue;
-		if (show_only || verbose)
-			printf("%s\n", reason.buf);
-		if (show_only)
-			continue;
-		delete_git_dir(d->d_name);
+		if (should_prune_worktree(d->d_name, &reason, &path))
+			prune_worktree(d->d_name, reason.buf);
+		else if (path)
+			string_list_append(&kept, path)->util = xstrdup(d->d_name);
 	}
 	closedir(dir);
+
+	strbuf_add_absolute_path(&main_path, get_git_common_dir());
+	/* massage main worktree absolute path to match 'gitdir' content */
+	strbuf_strip_suffix(&main_path, "/.");
+	string_list_append(&kept, strbuf_detach(&main_path, NULL));
+	prune_dups(&kept);
+	string_list_clear(&kept, 1);
+
 	if (!show_only)
 		delete_worktrees_dir_if_empty();
 	strbuf_release(&reason);
@@ -224,34 +280,33 @@
 	return name;
 }
 
-static void validate_worktree_add(const char *path, const struct add_opts *opts)
+/* check that path is viable location for worktree */
+static void check_candidate_path(const char *path,
+				 int force,
+				 struct worktree **worktrees,
+				 const char *cmd)
 {
-	struct worktree **worktrees;
 	struct worktree *wt;
 	int locked;
 
 	if (file_exists(path) && !is_empty_dir(path))
 		die(_("'%s' already exists"), path);
 
-	worktrees = get_worktrees(0);
 	wt = find_worktree_by_path(worktrees, path);
 	if (!wt)
-		goto done;
+		return;
 
 	locked = !!worktree_lock_reason(wt);
-	if ((!locked && opts->force) || (locked && opts->force > 1)) {
+	if ((!locked && force) || (locked && force > 1)) {
 		if (delete_git_dir(wt->id))
-		    die(_("unable to re-add worktree '%s'"), path);
-		goto done;
+		    die(_("unusable worktree destination '%s'"), path);
+		return;
 	}
 
 	if (locked)
-		die(_("'%s' is a missing but locked worktree;\nuse 'add -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"), path);
+		die(_("'%s' is a missing but locked worktree;\nuse '%s -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"), cmd, path);
 	else
-		die(_("'%s' is a missing but already registered worktree;\nuse 'add -f' to override, or 'prune' or 'remove' to clear"), path);
-
-done:
-	free_worktrees(worktrees);
+		die(_("'%s' is a missing but already registered worktree;\nuse '%s -f' to override, or 'prune' or 'remove' to clear"), cmd, path);
 }
 
 static int add_worktree(const char *path, const char *refname,
@@ -268,8 +323,12 @@
 	struct commit *commit = NULL;
 	int is_branch = 0;
 	struct strbuf sb_name = STRBUF_INIT;
+	struct worktree **worktrees;
 
-	validate_worktree_add(path, opts);
+	worktrees = get_worktrees();
+	check_candidate_path(path, opts->force, worktrees, "add");
+	free_worktrees(worktrees);
+	worktrees = NULL;
 
 	/* is 'refname' a branch or commit? */
 	if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
@@ -638,6 +697,23 @@
 	}
 }
 
+static int pathcmp(const void *a_, const void *b_)
+{
+	const struct worktree *const *a = a_;
+	const struct worktree *const *b = b_;
+	return fspathcmp((*a)->path, (*b)->path);
+}
+
+static void pathsort(struct worktree **wt)
+{
+	int n = 0;
+	struct worktree **p = wt;
+
+	while (*p++)
+		n++;
+	QSORT(wt, n, pathcmp);
+}
+
 static int list(int ac, const char **av, const char *prefix)
 {
 	int porcelain = 0;
@@ -651,9 +727,12 @@
 	if (ac)
 		usage_with_options(worktree_usage, options);
 	else {
-		struct worktree **worktrees = get_worktrees(GWT_SORT_LINKED);
+		struct worktree **worktrees = get_worktrees();
 		int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
 
+		/* sort worktrees by path but keep main worktree at top */
+		pathsort(worktrees + 1);
+
 		if (!porcelain)
 			measure_widths(worktrees, &abbrev, &path_maxlen);
 
@@ -682,7 +761,7 @@
 	if (ac != 1)
 		usage_with_options(worktree_usage, options);
 
-	worktrees = get_worktrees(0);
+	worktrees = get_worktrees();
 	wt = find_worktree(worktrees, prefix, av[0]);
 	if (!wt)
 		die(_("'%s' is not a working tree"), av[0]);
@@ -715,7 +794,7 @@
 	if (ac != 1)
 		usage_with_options(worktree_usage, options);
 
-	worktrees = get_worktrees(0);
+	worktrees = get_worktrees();
 	wt = find_worktree(worktrees, prefix, av[0]);
 	if (!wt)
 		die(_("'%s' is not a working tree"), av[0]);
@@ -789,7 +868,7 @@
 	strbuf_addstr(&dst, path);
 	free(path);
 
-	worktrees = get_worktrees(0);
+	worktrees = get_worktrees();
 	wt = find_worktree(worktrees, prefix, av[0]);
 	if (!wt)
 		die(_("'%s' is not a working tree"), av[0]);
@@ -804,8 +883,7 @@
 		strbuf_trim_trailing_dir_sep(&dst);
 		strbuf_addstr(&dst, sep);
 	}
-	if (file_exists(dst.buf))
-		die(_("target '%s' already exists"), dst.buf);
+	check_candidate_path(dst.buf, force, worktrees, "move");
 
 	validate_no_submodules(wt);
 
@@ -916,7 +994,7 @@
 	if (ac != 1)
 		usage_with_options(worktree_usage, options);
 
-	worktrees = get_worktrees(0);
+	worktrees = get_worktrees();
 	wt = find_worktree(worktrees, prefix, av[0]);
 	if (!wt)
 		die(_("'%s' is not a working tree"), av[0]);
diff --git a/bundle.c b/bundle.c
index 99439e0..2a0d744 100644
--- a/bundle.c
+++ b/bundle.c
@@ -23,6 +23,17 @@
 	list->nr++;
 }
 
+static const struct git_hash_algo *detect_hash_algo(struct strbuf *buf)
+{
+	size_t len = strcspn(buf->buf, " \n");
+	int algo;
+
+	algo = hash_algo_by_length(len / 2);
+	if (algo == GIT_HASH_UNKNOWN)
+		return NULL;
+	return &hash_algos[algo];
+}
+
 static int parse_bundle_header(int fd, struct bundle_header *header,
 			       const char *report_path)
 {
@@ -52,12 +63,21 @@
 		}
 		strbuf_rtrim(&buf);
 
+		if (!header->hash_algo) {
+			header->hash_algo = detect_hash_algo(&buf);
+			if (!header->hash_algo) {
+				error(_("unknown hash algorithm length"));
+				status = -1;
+				break;
+			}
+		}
+
 		/*
 		 * Tip lines have object name, SP, and refname.
 		 * Prerequisites have object name that is optionally
 		 * followed by SP and subject line.
 		 */
-		if (parse_oid_hex(buf.buf, &oid, &p) ||
+		if (parse_oid_hex_algop(buf.buf, &oid, &p, header->hash_algo) ||
 		    (*p && !isspace(*p)) ||
 		    (!is_prereq && !*p)) {
 			if (report_path)
diff --git a/bundle.h b/bundle.h
index ceab0c7..2dc9442 100644
--- a/bundle.h
+++ b/bundle.h
@@ -15,6 +15,7 @@
 struct bundle_header {
 	struct ref_list prerequisites;
 	struct ref_list references;
+	const struct git_hash_algo *hash_algo;
 };
 
 int is_bundle(const char *path, int quiet);
diff --git a/cache.h b/cache.h
index 0f0485e..0290849 100644
--- a/cache.h
+++ b/cache.h
@@ -628,7 +628,7 @@
 
 int init_db(const char *git_dir, const char *real_git_dir,
 	    const char *template_dir, int hash_algo,
-	    unsigned int flags);
+	    const char *initial_branch, unsigned int flags);
 void initialize_repository_version(int hash_algo);
 
 void sanitize_stdfds(void);
@@ -1044,6 +1044,7 @@
 	int hash_algo;
 	char *work_tree;
 	struct string_list unknown_extensions;
+	struct string_list v1_only_extensions;
 };
 
 /*
@@ -1057,6 +1058,7 @@
 	.is_bare = -1, \
 	.hash_algo = GIT_HASH_SHA1, \
 	.unknown_extensions = STRING_LIST_INIT_DUP, \
+	.v1_only_extensions = STRING_LIST_INIT_DUP, \
 }
 
 /*
diff --git a/ci/lib.sh b/ci/lib.sh
index ff24c54..3eefec5 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -184,9 +184,9 @@
 	if [ "$jobname" = linux-gcc ]
 	then
 		export CC=gcc-8
-		MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=$(which python3)"
+		MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python3"
 	else
-		MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=$(which python2)"
+		MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python2"
 	fi
 
 	export GIT_TEST_HTTPD=true
diff --git a/column.c b/column.c
index 4a38eed..a58969b 100644
--- a/column.c
+++ b/column.c
@@ -107,7 +107,7 @@
 		printf("%s%s%s", indent, list->items[i].string, nl);
 }
 
-/* Print a cell to stdout with all necessary leading/traling space */
+/* Print a cell to stdout with all necessary leading/trailing space */
 static int display_cell(struct column_data *data, int initial_width,
 			const char *empty_cell, int x, int y)
 {
diff --git a/command-list.txt b/command-list.txt
index cbb960c..89aa60c 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -136,7 +136,7 @@
 git-pack-refs                           ancillarymanipulators
 git-parse-remote                        synchelpers
 git-patch-id                            purehelpers
-git-prune                               ancillarymanipulators
+git-prune                               ancillarymanipulators   complete
 git-prune-packed                        plumbingmanipulators
 git-pull                                mainporcelain           remote
 git-push                                mainporcelain           remote
diff --git a/commit-graph.c b/commit-graph.c
index 2ff042f..e51c91d 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1,7 +1,5 @@
-#include "cache.h"
-#include "config.h"
-#include "dir.h"
 #include "git-compat-util.h"
+#include "config.h"
 #include "lockfile.h"
 #include "pack.h"
 #include "packfile.h"
@@ -19,6 +17,8 @@
 #include "bloom.h"
 #include "commit-slab.h"
 #include "shallow.h"
+#include "json-writer.h"
+#include "trace2.h"
 
 void git_test_write_commit_graph_or_die(void)
 {
@@ -87,15 +87,69 @@
 	       commit_pos_at(&commit_pos, b);
 }
 
+define_commit_slab(commit_graph_data_slab, struct commit_graph_data);
+static struct commit_graph_data_slab commit_graph_data_slab =
+	COMMIT_SLAB_INIT(1, commit_graph_data_slab);
+
+uint32_t commit_graph_position(const struct commit *c)
+{
+	struct commit_graph_data *data =
+		commit_graph_data_slab_peek(&commit_graph_data_slab, c);
+
+	return data ? data->graph_pos : COMMIT_NOT_FROM_GRAPH;
+}
+
+uint32_t commit_graph_generation(const struct commit *c)
+{
+	struct commit_graph_data *data =
+		commit_graph_data_slab_peek(&commit_graph_data_slab, c);
+
+	if (!data)
+		return GENERATION_NUMBER_INFINITY;
+	else if (data->graph_pos == COMMIT_NOT_FROM_GRAPH)
+		return GENERATION_NUMBER_INFINITY;
+
+	return data->generation;
+}
+
+static struct commit_graph_data *commit_graph_data_at(const struct commit *c)
+{
+	unsigned int i, nth_slab;
+	struct commit_graph_data *data =
+		commit_graph_data_slab_peek(&commit_graph_data_slab, c);
+
+	if (data)
+		return data;
+
+	nth_slab = c->index / commit_graph_data_slab.slab_size;
+	data = commit_graph_data_slab_at(&commit_graph_data_slab, c);
+
+	/*
+	 * commit-slab initializes elements with zero, overwrite this with
+	 * COMMIT_NOT_FROM_GRAPH for graph_pos.
+	 *
+	 * We avoid initializing generation with checking if graph position
+	 * is not COMMIT_NOT_FROM_GRAPH.
+	 */
+	for (i = 0; i < commit_graph_data_slab.slab_size; i++) {
+		commit_graph_data_slab.slab[nth_slab][i].graph_pos =
+			COMMIT_NOT_FROM_GRAPH;
+	}
+
+	return data;
+}
+
 static int commit_gen_cmp(const void *va, const void *vb)
 {
 	const struct commit *a = *(const struct commit **)va;
 	const struct commit *b = *(const struct commit **)vb;
 
+	uint32_t generation_a = commit_graph_generation(a);
+	uint32_t generation_b = commit_graph_generation(b);
 	/* lower generation commits first */
-	if (a->generation < b->generation)
+	if (generation_a < generation_b)
 		return -1;
-	else if (a->generation > b->generation)
+	else if (generation_a > generation_b)
 		return 1;
 
 	/* use date as a heuristic when generations are equal */
@@ -149,7 +203,8 @@
 	}
 
 	prepare_commit_graft(r);
-	if (r->parsed_objects && r->parsed_objects->grafts_nr)
+	if (r->parsed_objects &&
+	    (r->parsed_objects->grafts_nr || r->parsed_objects->substituted_parent))
 		return 0;
 	if (is_repository_shallow(r))
 		return 0;
@@ -230,8 +285,7 @@
 	const unsigned char *data, *chunk_lookup;
 	uint32_t i;
 	struct commit_graph *graph;
-	uint64_t last_chunk_offset;
-	uint32_t last_chunk_id;
+	uint64_t next_chunk_offset;
 	uint32_t graph_signature;
 	unsigned char graph_version, hash_version;
 
@@ -271,24 +325,26 @@
 	graph->data = graph_map;
 	graph->data_len = graph_size;
 
-	last_chunk_id = 0;
-	last_chunk_offset = 8;
+	if (graph_size < GRAPH_HEADER_SIZE +
+			 (graph->num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH +
+			 GRAPH_FANOUT_SIZE + the_hash_algo->rawsz) {
+		error(_("commit-graph file is too small to hold %u chunks"),
+		      graph->num_chunks);
+		free(graph);
+		return NULL;
+	}
+
 	chunk_lookup = data + 8;
+	next_chunk_offset = get_be64(chunk_lookup + 4);
 	for (i = 0; i < graph->num_chunks; i++) {
 		uint32_t chunk_id;
-		uint64_t chunk_offset;
+		uint64_t chunk_offset = next_chunk_offset;
 		int chunk_repeated = 0;
 
-		if (data + graph_size - chunk_lookup <
-		    GRAPH_CHUNKLOOKUP_WIDTH) {
-			error(_("commit-graph chunk lookup table entry missing; file may be incomplete"));
-			goto free_and_return;
-		}
-
 		chunk_id = get_be32(chunk_lookup + 0);
-		chunk_offset = get_be64(chunk_lookup + 4);
 
 		chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH;
+		next_chunk_offset = get_be64(chunk_lookup + 4);
 
 		if (chunk_offset > graph_size - the_hash_algo->rawsz) {
 			error(_("commit-graph improper chunk offset %08x%08x"), (uint32_t)(chunk_offset >> 32),
@@ -307,8 +363,11 @@
 		case GRAPH_CHUNKID_OIDLOOKUP:
 			if (graph->chunk_oid_lookup)
 				chunk_repeated = 1;
-			else
+			else {
 				graph->chunk_oid_lookup = data + chunk_offset;
+				graph->num_commits = (next_chunk_offset - chunk_offset)
+						     / graph->hash_len;
+			}
 			break;
 
 		case GRAPH_CHUNKID_DATA:
@@ -362,15 +421,6 @@
 			error(_("commit-graph chunk id %08x appears multiple times"), chunk_id);
 			goto free_and_return;
 		}
-
-		if (last_chunk_id == GRAPH_CHUNKID_OIDLOOKUP)
-		{
-			graph->num_commits = (chunk_offset - last_chunk_offset)
-					     / graph->hash_len;
-		}
-
-		last_chunk_id = chunk_id;
-		last_chunk_offset = chunk_offset;
 	}
 
 	if (graph->chunk_bloom_indexes && graph->chunk_bloom_data) {
@@ -569,10 +619,6 @@
 		return !!r->objects->commit_graph;
 	r->objects->commit_graph_attempted = 1;
 
-	if (git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD, 0))
-		die("dying as requested by the '%s' variable on commit-graph load!",
-		    GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD);
-
 	prepare_repo_settings(r);
 
 	if (!git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
@@ -670,13 +716,14 @@
 	c = lookup_commit(r, &oid);
 	if (!c)
 		die(_("could not find commit %s"), oid_to_hex(&oid));
-	c->graph_pos = pos;
+	commit_graph_data_at(c)->graph_pos = pos;
 	return &commit_list_insert(c, pptr)->next;
 }
 
 static void fill_commit_graph_info(struct commit *item, struct commit_graph *g, uint32_t pos)
 {
 	const unsigned char *commit_data;
+	struct commit_graph_data *graph_data;
 	uint32_t lex_index;
 
 	while (pos < g->num_commits_in_base)
@@ -684,8 +731,10 @@
 
 	lex_index = pos - g->num_commits_in_base;
 	commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * lex_index;
-	item->graph_pos = pos;
-	item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
+
+	graph_data = commit_graph_data_at(item);
+	graph_data->graph_pos = pos;
+	graph_data->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
 }
 
 static inline void set_commit_tree(struct commit *c, struct tree *t)
@@ -701,6 +750,7 @@
 	uint32_t *parent_data_ptr;
 	uint64_t date_low, date_high;
 	struct commit_list **pptr;
+	struct commit_graph_data *graph_data;
 	const unsigned char *commit_data;
 	uint32_t lex_index;
 
@@ -714,7 +764,8 @@
 	 * Store the "full" position, but then use the
 	 * "local" position for the rest of the calculation.
 	 */
-	item->graph_pos = pos;
+	graph_data = commit_graph_data_at(item);
+	graph_data->graph_pos = pos;
 	lex_index = pos - g->num_commits_in_base;
 
 	commit_data = g->chunk_commit_data + (g->hash_len + 16) * lex_index;
@@ -727,7 +778,7 @@
 	date_low = get_be32(commit_data + g->hash_len + 12);
 	item->date = (timestamp_t)((date_high << 32) | date_low);
 
-	item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
+	graph_data->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
 
 	pptr = &item->parents;
 
@@ -759,8 +810,9 @@
 
 static int find_commit_in_graph(struct commit *item, struct commit_graph *g, uint32_t *pos)
 {
-	if (item->graph_pos != COMMIT_NOT_FROM_GRAPH) {
-		*pos = item->graph_pos;
+	uint32_t graph_pos = commit_graph_position(item);
+	if (graph_pos != COMMIT_NOT_FROM_GRAPH) {
+		*pos = graph_pos;
 		return 1;
 	} else {
 		struct commit_graph *cur_g = g;
@@ -795,6 +847,14 @@
 
 int parse_commit_in_graph(struct repository *r, struct commit *item)
 {
+	static int checked_env = 0;
+
+	if (!checked_env &&
+	    git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE, 0))
+		die("dying as requested by the '%s' variable on commit-graph parse!",
+		    GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE);
+	checked_env = 1;
+
 	if (!prepare_commit_graph(r))
 		return 0;
 	return parse_commit_in_graph_one(r, r->objects->commit_graph, item);
@@ -815,12 +875,13 @@
 {
 	struct object_id oid;
 	const unsigned char *commit_data;
+	uint32_t graph_pos = commit_graph_position(c);
 
-	while (c->graph_pos < g->num_commits_in_base)
+	while (graph_pos < g->num_commits_in_base)
 		g = g->base_graph;
 
 	commit_data = g->chunk_commit_data +
-			GRAPH_DATA_WIDTH * (c->graph_pos - g->num_commits_in_base);
+			GRAPH_DATA_WIDTH * (graph_pos - g->num_commits_in_base);
 
 	hashcpy(oid.hash, commit_data);
 	set_commit_tree(c, lookup_tree(r, &oid));
@@ -834,7 +895,7 @@
 {
 	if (c->maybe_tree)
 		return c->maybe_tree;
-	if (c->graph_pos == COMMIT_NOT_FROM_GRAPH)
+	if (commit_graph_position(c) == COMMIT_NOT_FROM_GRAPH)
 		BUG("get_commit_tree_in_graph_one called from non-commit-graph commit");
 
 	return load_tree_for_commit(r, g, (struct commit *)c);
@@ -886,10 +947,11 @@
 
 	const struct split_commit_graph_opts *split_opts;
 	size_t total_bloom_filter_data_size;
+	const struct bloom_filter_settings *bloom_settings;
 };
 
-static void write_graph_chunk_fanout(struct hashfile *f,
-				     struct write_commit_graph_context *ctx)
+static int write_graph_chunk_fanout(struct hashfile *f,
+				    struct write_commit_graph_context *ctx)
 {
 	int i, count = 0;
 	struct commit **list = ctx->commits.list;
@@ -910,17 +972,21 @@
 
 		hashwrite_be32(f, count);
 	}
+
+	return 0;
 }
 
-static void write_graph_chunk_oids(struct hashfile *f, int hash_len,
-				   struct write_commit_graph_context *ctx)
+static int write_graph_chunk_oids(struct hashfile *f,
+				  struct write_commit_graph_context *ctx)
 {
 	struct commit **list = ctx->commits.list;
 	int count;
 	for (count = 0; count < ctx->commits.nr; count++, list++) {
 		display_progress(ctx->progress, ++ctx->progress_cnt);
-		hashwrite(f, (*list)->object.oid.hash, (int)hash_len);
+		hashwrite(f, (*list)->object.oid.hash, the_hash_algo->rawsz);
 	}
+
+	return 0;
 }
 
 static const unsigned char *commit_to_sha1(size_t index, void *table)
@@ -929,8 +995,8 @@
 	return commits[index]->object.oid.hash;
 }
 
-static void write_graph_chunk_data(struct hashfile *f, int hash_len,
-				   struct write_commit_graph_context *ctx)
+static int write_graph_chunk_data(struct hashfile *f,
+				  struct write_commit_graph_context *ctx)
 {
 	struct commit **list = ctx->commits.list;
 	struct commit **last = ctx->commits.list + ctx->commits.nr;
@@ -947,7 +1013,7 @@
 			die(_("unable to parse commit %s"),
 				oid_to_hex(&(*list)->object.oid));
 		tree = get_commit_tree_oid(*list);
-		hashwrite(f, tree->hash, hash_len);
+		hashwrite(f, tree->hash, the_hash_algo->rawsz);
 
 		parent = (*list)->parents;
 
@@ -1020,17 +1086,19 @@
 		else
 			packedDate[0] = 0;
 
-		packedDate[0] |= htonl((*list)->generation << 2);
+		packedDate[0] |= htonl(commit_graph_data_at(*list)->generation << 2);
 
 		packedDate[1] = htonl((*list)->date);
 		hashwrite(f, packedDate, 8);
 
 		list++;
 	}
+
+	return 0;
 }
 
-static void write_graph_chunk_extra_edges(struct hashfile *f,
-					  struct write_commit_graph_context *ctx)
+static int write_graph_chunk_extra_edges(struct hashfile *f,
+					 struct write_commit_graph_context *ctx)
 {
 	struct commit **list = ctx->commits.list;
 	struct commit **last = ctx->commits.list + ctx->commits.nr;
@@ -1079,59 +1147,67 @@
 
 		list++;
 	}
+
+	return 0;
 }
 
-static void write_graph_chunk_bloom_indexes(struct hashfile *f,
-					    struct write_commit_graph_context *ctx)
+static int write_graph_chunk_bloom_indexes(struct hashfile *f,
+					   struct write_commit_graph_context *ctx)
 {
 	struct commit **list = ctx->commits.list;
 	struct commit **last = ctx->commits.list + ctx->commits.nr;
 	uint32_t cur_pos = 0;
-	struct progress *progress = NULL;
-	int i = 0;
-
-	if (ctx->report_progress)
-		progress = start_delayed_progress(
-			_("Writing changed paths Bloom filters index"),
-			ctx->commits.nr);
 
 	while (list < last) {
 		struct bloom_filter *filter = get_bloom_filter(ctx->r, *list, 0);
-		cur_pos += filter->len;
-		display_progress(progress, ++i);
+		size_t len = filter ? filter->len : 0;
+		cur_pos += len;
+		display_progress(ctx->progress, ++ctx->progress_cnt);
 		hashwrite_be32(f, cur_pos);
 		list++;
 	}
 
-	stop_progress(&progress);
+	return 0;
 }
 
-static void write_graph_chunk_bloom_data(struct hashfile *f,
-					 struct write_commit_graph_context *ctx,
-					 const struct bloom_filter_settings *settings)
+static void trace2_bloom_filter_settings(struct write_commit_graph_context *ctx)
+{
+	struct json_writer jw = JSON_WRITER_INIT;
+
+	jw_object_begin(&jw, 0);
+	jw_object_intmax(&jw, "hash_version", ctx->bloom_settings->hash_version);
+	jw_object_intmax(&jw, "num_hashes", ctx->bloom_settings->num_hashes);
+	jw_object_intmax(&jw, "bits_per_entry", ctx->bloom_settings->bits_per_entry);
+	jw_end(&jw);
+
+	trace2_data_json("bloom", ctx->r, "settings", &jw);
+
+	jw_release(&jw);
+}
+
+static int write_graph_chunk_bloom_data(struct hashfile *f,
+					struct write_commit_graph_context *ctx)
 {
 	struct commit **list = ctx->commits.list;
 	struct commit **last = ctx->commits.list + ctx->commits.nr;
-	struct progress *progress = NULL;
-	int i = 0;
 
-	if (ctx->report_progress)
-		progress = start_delayed_progress(
-			_("Writing changed paths Bloom filters data"),
-			ctx->commits.nr);
+	trace2_bloom_filter_settings(ctx);
 
-	hashwrite_be32(f, settings->hash_version);
-	hashwrite_be32(f, settings->num_hashes);
-	hashwrite_be32(f, settings->bits_per_entry);
+	hashwrite_be32(f, ctx->bloom_settings->hash_version);
+	hashwrite_be32(f, ctx->bloom_settings->num_hashes);
+	hashwrite_be32(f, ctx->bloom_settings->bits_per_entry);
 
 	while (list < last) {
 		struct bloom_filter *filter = get_bloom_filter(ctx->r, *list, 0);
-		display_progress(progress, ++i);
-		hashwrite(f, filter->data, filter->len * sizeof(unsigned char));
+		size_t len = filter ? filter->len : 0;
+
+		display_progress(ctx->progress, ++ctx->progress_cnt);
+		if (len)
+			hashwrite(f, filter->data, len * sizeof(unsigned char));
 		list++;
 	}
 
-	stop_progress(&progress);
+	return 0;
 }
 
 static int oid_compare(const void *_a, const void *_b)
@@ -1219,7 +1295,7 @@
 			continue;
 		if (ctx->split) {
 			if ((!parse_commit(commit) &&
-			     commit->graph_pos == COMMIT_NOT_FROM_GRAPH) ||
+			     commit_graph_position(commit) == COMMIT_NOT_FROM_GRAPH) ||
 			    flags == COMMIT_GRAPH_SPLIT_REPLACE)
 				add_missing_parents(ctx, commit);
 		} else if (!parse_commit_no_graph(commit))
@@ -1251,9 +1327,11 @@
 					_("Computing commit graph generation numbers"),
 					ctx->commits.nr);
 	for (i = 0; i < ctx->commits.nr; i++) {
+		uint32_t generation = commit_graph_data_at(ctx->commits.list[i])->generation;
+
 		display_progress(ctx->progress, i + 1);
-		if (ctx->commits.list[i]->generation != GENERATION_NUMBER_INFINITY &&
-		    ctx->commits.list[i]->generation != GENERATION_NUMBER_ZERO)
+		if (generation != GENERATION_NUMBER_INFINITY &&
+		    generation != GENERATION_NUMBER_ZERO)
 			continue;
 
 		commit_list_insert(ctx->commits.list[i], &list);
@@ -1264,22 +1342,26 @@
 			uint32_t max_generation = 0;
 
 			for (parent = current->parents; parent; parent = parent->next) {
-				if (parent->item->generation == GENERATION_NUMBER_INFINITY ||
-				    parent->item->generation == GENERATION_NUMBER_ZERO) {
+				generation = commit_graph_data_at(parent->item)->generation;
+
+				if (generation == GENERATION_NUMBER_INFINITY ||
+				    generation == GENERATION_NUMBER_ZERO) {
 					all_parents_computed = 0;
 					commit_list_insert(parent->item, &list);
 					break;
-				} else if (parent->item->generation > max_generation) {
-					max_generation = parent->item->generation;
+				} else if (generation > max_generation) {
+					max_generation = generation;
 				}
 			}
 
 			if (all_parents_computed) {
-				current->generation = max_generation + 1;
+				struct commit_graph_data *data = commit_graph_data_at(current);
+
+				data->generation = max_generation + 1;
 				pop_commit(&list);
 
-				if (current->generation > GENERATION_NUMBER_MAX)
-					current->generation = GENERATION_NUMBER_MAX;
+				if (data->generation > GENERATION_NUMBER_MAX)
+					data->generation = GENERATION_NUMBER_MAX;
 			}
 		}
 	}
@@ -1355,12 +1437,13 @@
 			_("Collecting referenced commits"), 0);
 
 	for_each_ref(add_ref_to_set, &data);
+
+	stop_progress(&data.progress);
+
 	result = write_commit_graph(odb, NULL, &commits,
 				    flags, split_opts);
 
 	oidset_clear(&commits);
-	if (data.progress)
-		stop_progress(&data.progress);
 	return result;
 }
 
@@ -1458,7 +1541,7 @@
 			if (ctx->split) {
 				struct commit *c = lookup_commit(ctx->r, &ctx->oids.list[i]);
 
-				if (!c || c->graph_pos != COMMIT_NOT_FROM_GRAPH)
+				if (!c || commit_graph_position(c) != COMMIT_NOT_FROM_GRAPH)
 					continue;
 			}
 
@@ -1492,7 +1575,7 @@
 		ctx->commits.list[ctx->commits.nr] = lookup_commit(ctx->r, &ctx->oids.list[i]);
 
 		if (ctx->split && flags != COMMIT_GRAPH_SPLIT_REPLACE &&
-		    ctx->commits.list[ctx->commits.nr]->graph_pos != COMMIT_NOT_FROM_GRAPH)
+		    commit_graph_position(ctx->commits.list[ctx->commits.nr]) != COMMIT_NOT_FROM_GRAPH)
 			continue;
 
 		if (ctx->split && flags == COMMIT_GRAPH_SPLIT_REPLACE)
@@ -1535,19 +1618,36 @@
 	return 0;
 }
 
+typedef int (*chunk_write_fn)(struct hashfile *f,
+			      struct write_commit_graph_context *ctx);
+
+struct chunk_info {
+	uint32_t id;
+	uint64_t size;
+	chunk_write_fn write_fn;
+};
+
 static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 {
 	uint32_t i;
 	int fd;
 	struct hashfile *f;
 	struct lock_file lk = LOCK_INIT;
-	uint32_t chunk_ids[MAX_NUM_CHUNKS + 1];
-	uint64_t chunk_offsets[MAX_NUM_CHUNKS + 1];
+	struct chunk_info chunks[MAX_NUM_CHUNKS + 1];
 	const unsigned hashsz = the_hash_algo->rawsz;
 	struct strbuf progress_title = STRBUF_INIT;
 	int num_chunks = 3;
+	uint64_t chunk_offset;
 	struct object_id file_hash;
-	const struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
+	struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
+
+	if (!ctx->bloom_settings) {
+		bloom_settings.bits_per_entry = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY",
+							      bloom_settings.bits_per_entry);
+		bloom_settings.num_hashes = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_NUM_HASHES",
+							  bloom_settings.num_hashes);
+		ctx->bloom_settings = &bloom_settings;
+	}
 
 	if (ctx->split) {
 		struct strbuf tmp_file = STRBUF_INIT;
@@ -1593,51 +1693,41 @@
 		f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
 	}
 
-	chunk_ids[0] = GRAPH_CHUNKID_OIDFANOUT;
-	chunk_ids[1] = GRAPH_CHUNKID_OIDLOOKUP;
-	chunk_ids[2] = GRAPH_CHUNKID_DATA;
+	chunks[0].id = GRAPH_CHUNKID_OIDFANOUT;
+	chunks[0].size = GRAPH_FANOUT_SIZE;
+	chunks[0].write_fn = write_graph_chunk_fanout;
+	chunks[1].id = GRAPH_CHUNKID_OIDLOOKUP;
+	chunks[1].size = hashsz * ctx->commits.nr;
+	chunks[1].write_fn = write_graph_chunk_oids;
+	chunks[2].id = GRAPH_CHUNKID_DATA;
+	chunks[2].size = (hashsz + 16) * ctx->commits.nr;
+	chunks[2].write_fn = write_graph_chunk_data;
 	if (ctx->num_extra_edges) {
-		chunk_ids[num_chunks] = GRAPH_CHUNKID_EXTRAEDGES;
+		chunks[num_chunks].id = GRAPH_CHUNKID_EXTRAEDGES;
+		chunks[num_chunks].size = 4 * ctx->num_extra_edges;
+		chunks[num_chunks].write_fn = write_graph_chunk_extra_edges;
 		num_chunks++;
 	}
 	if (ctx->changed_paths) {
-		chunk_ids[num_chunks] = GRAPH_CHUNKID_BLOOMINDEXES;
+		chunks[num_chunks].id = GRAPH_CHUNKID_BLOOMINDEXES;
+		chunks[num_chunks].size = sizeof(uint32_t) * ctx->commits.nr;
+		chunks[num_chunks].write_fn = write_graph_chunk_bloom_indexes;
 		num_chunks++;
-		chunk_ids[num_chunks] = GRAPH_CHUNKID_BLOOMDATA;
+		chunks[num_chunks].id = GRAPH_CHUNKID_BLOOMDATA;
+		chunks[num_chunks].size = sizeof(uint32_t) * 3
+					  + ctx->total_bloom_filter_data_size;
+		chunks[num_chunks].write_fn = write_graph_chunk_bloom_data;
 		num_chunks++;
 	}
 	if (ctx->num_commit_graphs_after > 1) {
-		chunk_ids[num_chunks] = GRAPH_CHUNKID_BASE;
+		chunks[num_chunks].id = GRAPH_CHUNKID_BASE;
+		chunks[num_chunks].size = hashsz * (ctx->num_commit_graphs_after - 1);
+		chunks[num_chunks].write_fn = write_graph_chunk_base;
 		num_chunks++;
 	}
 
-	chunk_ids[num_chunks] = 0;
-
-	chunk_offsets[0] = 8 + (num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH;
-	chunk_offsets[1] = chunk_offsets[0] + GRAPH_FANOUT_SIZE;
-	chunk_offsets[2] = chunk_offsets[1] + hashsz * ctx->commits.nr;
-	chunk_offsets[3] = chunk_offsets[2] + (hashsz + 16) * ctx->commits.nr;
-
-	num_chunks = 3;
-	if (ctx->num_extra_edges) {
-		chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
-						4 * ctx->num_extra_edges;
-		num_chunks++;
-	}
-	if (ctx->changed_paths) {
-		chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
-						sizeof(uint32_t) * ctx->commits.nr;
-		num_chunks++;
-
-		chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
-						sizeof(uint32_t) * 3 + ctx->total_bloom_filter_data_size;
-		num_chunks++;
-	}
-	if (ctx->num_commit_graphs_after > 1) {
-		chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
-						hashsz * (ctx->num_commit_graphs_after - 1);
-		num_chunks++;
-	}
+	chunks[num_chunks].id = 0;
+	chunks[num_chunks].size = 0;
 
 	hashwrite_be32(f, GRAPH_SIGNATURE);
 
@@ -1646,13 +1736,16 @@
 	hashwrite_u8(f, num_chunks);
 	hashwrite_u8(f, ctx->num_commit_graphs_after - 1);
 
+	chunk_offset = 8 + (num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH;
 	for (i = 0; i <= num_chunks; i++) {
 		uint32_t chunk_write[3];
 
-		chunk_write[0] = htonl(chunk_ids[i]);
-		chunk_write[1] = htonl(chunk_offsets[i] >> 32);
-		chunk_write[2] = htonl(chunk_offsets[i] & 0xffffffff);
+		chunk_write[0] = htonl(chunks[i].id);
+		chunk_write[1] = htonl(chunk_offset >> 32);
+		chunk_write[2] = htonl(chunk_offset & 0xffffffff);
 		hashwrite(f, chunk_write, 12);
+
+		chunk_offset += chunks[i].size;
 	}
 
 	if (ctx->report_progress) {
@@ -1665,19 +1758,19 @@
 			progress_title.buf,
 			num_chunks * ctx->commits.nr);
 	}
-	write_graph_chunk_fanout(f, ctx);
-	write_graph_chunk_oids(f, hashsz, ctx);
-	write_graph_chunk_data(f, hashsz, ctx);
-	if (ctx->num_extra_edges)
-		write_graph_chunk_extra_edges(f, ctx);
-	if (ctx->changed_paths) {
-		write_graph_chunk_bloom_indexes(f, ctx);
-		write_graph_chunk_bloom_data(f, ctx, &bloom_settings);
+
+	for (i = 0; i < num_chunks; i++) {
+		uint64_t start_offset = f->total + f->offset;
+
+		if (chunks[i].write_fn(f, ctx))
+			return -1;
+
+		if (f->total + f->offset != start_offset + chunks[i].size)
+			BUG("expected to write %"PRId64" bytes to chunk %"PRIx32", but wrote %"PRId64" instead",
+			    chunks[i].size, chunks[i].id,
+			    f->total + f->offset - start_offset);
 	}
-	if (ctx->num_commit_graphs_after > 1 &&
-	    write_graph_chunk_base(f, ctx)) {
-		return -1;
-	}
+
 	stop_progress(&ctx->progress);
 	strbuf_release(&progress_title);
 
@@ -2011,9 +2104,23 @@
 	ctx->report_progress = flags & COMMIT_GRAPH_WRITE_PROGRESS ? 1 : 0;
 	ctx->split = flags & COMMIT_GRAPH_WRITE_SPLIT ? 1 : 0;
 	ctx->split_opts = split_opts;
-	ctx->changed_paths = flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS ? 1 : 0;
 	ctx->total_bloom_filter_data_size = 0;
 
+	if (flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS)
+		ctx->changed_paths = 1;
+	if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {
+		struct commit_graph *g;
+		prepare_commit_graph_one(ctx->r, ctx->odb);
+
+		g = ctx->r->objects->commit_graph;
+
+		/* We have changed-paths already. Keep them in the next graph */
+		if (g && g->chunk_bloom_data) {
+			ctx->changed_paths = 1;
+			ctx->bloom_settings = g->bloom_filter_settings;
+		}
+	}
+
 	if (ctx->split) {
 		struct commit_graph *g;
 		prepare_commit_graph(ctx->r);
@@ -2241,6 +2348,7 @@
 		struct commit *graph_commit, *odb_commit;
 		struct commit_list *graph_parents, *odb_parents;
 		uint32_t max_generation = 0;
+		uint32_t generation;
 
 		display_progress(progress, i + 1);
 		hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i);
@@ -2279,8 +2387,9 @@
 					     oid_to_hex(&graph_parents->item->object.oid),
 					     oid_to_hex(&odb_parents->item->object.oid));
 
-			if (graph_parents->item->generation > max_generation)
-				max_generation = graph_parents->item->generation;
+			generation = commit_graph_generation(graph_parents->item);
+			if (generation > max_generation)
+				max_generation = generation;
 
 			graph_parents = graph_parents->next;
 			odb_parents = odb_parents->next;
@@ -2290,7 +2399,7 @@
 			graph_report(_("commit-graph parent list for commit %s terminates early"),
 				     oid_to_hex(&cur_oid));
 
-		if (!graph_commit->generation) {
+		if (!commit_graph_generation(graph_commit)) {
 			if (generation_zero == GENERATION_NUMBER_EXISTS)
 				graph_report(_("commit-graph has generation number zero for commit %s, but non-zero elsewhere"),
 					     oid_to_hex(&cur_oid));
@@ -2310,10 +2419,11 @@
 		if (max_generation == GENERATION_NUMBER_MAX)
 			max_generation--;
 
-		if (graph_commit->generation != max_generation + 1)
+		generation = commit_graph_generation(graph_commit);
+		if (generation != max_generation + 1)
 			graph_report(_("commit-graph generation for commit %s is %u != %u"),
 				     oid_to_hex(&cur_oid),
-				     graph_commit->generation,
+				     generation,
 				     max_generation + 1);
 
 		if (graph_commit->date != odb_commit->date)
diff --git a/commit-graph.h b/commit-graph.h
index 3ba0da1..09a9703 100644
--- a/commit-graph.h
+++ b/commit-graph.h
@@ -2,14 +2,11 @@
 #define COMMIT_GRAPH_H
 
 #include "git-compat-util.h"
-#include "repository.h"
-#include "string-list.h"
-#include "cache.h"
 #include "object-store.h"
 #include "oidset.h"
 
 #define GIT_TEST_COMMIT_GRAPH "GIT_TEST_COMMIT_GRAPH"
-#define GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD "GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD"
+#define GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE "GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE"
 #define GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS "GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS"
 
 /*
@@ -23,6 +20,9 @@
 
 struct commit;
 struct bloom_filter_settings;
+struct repository;
+struct raw_object_store;
+struct string_list;
 
 char *get_commit_graph_filename(struct object_directory *odb);
 int open_commit_graph(const char *graph_file, int *fd, struct stat *st);
@@ -92,6 +92,7 @@
 	COMMIT_GRAPH_WRITE_PROGRESS   = (1 << 1),
 	COMMIT_GRAPH_WRITE_SPLIT      = (1 << 2),
 	COMMIT_GRAPH_WRITE_BLOOM_FILTERS = (1 << 3),
+	COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS = (1 << 4),
 };
 
 enum commit_graph_split_flags {
@@ -135,4 +136,14 @@
  */
 void disable_commit_graph(struct repository *r);
 
+struct commit_graph_data {
+	uint32_t graph_pos;
+	uint32_t generation;
+};
+
+/*
+ * Commits should be parsed before accessing generation, graph positions.
+ */
+uint32_t commit_graph_generation(const struct commit *);
+uint32_t commit_graph_position(const struct commit *);
 #endif
diff --git a/commit-reach.c b/commit-reach.c
index 4ca7e70..efd5925 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -58,14 +58,15 @@
 		struct commit *commit = prio_queue_get(&queue);
 		struct commit_list *parents;
 		int flags;
+		uint32_t generation = commit_graph_generation(commit);
 
-		if (min_generation && commit->generation > last_gen)
+		if (min_generation && generation > last_gen)
 			BUG("bad generation skip %8x > %8x at %s",
-			    commit->generation, last_gen,
+			    generation, last_gen,
 			    oid_to_hex(&commit->object.oid));
-		last_gen = commit->generation;
+		last_gen = generation;
 
-		if (commit->generation < min_generation)
+		if (generation < min_generation)
 			break;
 
 		flags = commit->object.flags & (PARENT1 | PARENT2 | STALE);
@@ -176,18 +177,20 @@
 		repo_parse_commit(r, array[i]);
 	for (i = 0; i < cnt; i++) {
 		struct commit_list *common;
-		uint32_t min_generation = array[i]->generation;
+		uint32_t min_generation = commit_graph_generation(array[i]);
 
 		if (redundant[i])
 			continue;
 		for (j = filled = 0; j < cnt; j++) {
+			uint32_t curr_generation;
 			if (i == j || redundant[j])
 				continue;
 			filled_index[filled] = j;
 			work[filled++] = array[j];
 
-			if (array[j]->generation < min_generation)
-				min_generation = array[j]->generation;
+			curr_generation = commit_graph_generation(array[j]);
+			if (curr_generation < min_generation)
+				min_generation = curr_generation;
 		}
 		common = paint_down_to_common(r, array[i], filled,
 					      work, min_generation);
@@ -283,7 +286,9 @@
 /*
  * Is "commit" a descendant of one of the elements on the "with_commit" list?
  */
-int is_descendant_of(struct commit *commit, struct commit_list *with_commit)
+int repo_is_descendant_of(struct repository *r,
+			  struct commit *commit,
+			  struct commit_list *with_commit)
 {
 	if (!with_commit)
 		return 1;
@@ -301,7 +306,7 @@
 
 			other = with_commit->item;
 			with_commit = with_commit->next;
-			if (in_merge_bases(other, commit))
+			if (repo_in_merge_bases_many(r, other, 1, &commit))
 				return 1;
 		}
 		return 0;
@@ -316,23 +321,26 @@
 {
 	struct commit_list *bases;
 	int ret = 0, i;
-	uint32_t min_generation = GENERATION_NUMBER_INFINITY;
+	uint32_t generation, min_generation = GENERATION_NUMBER_INFINITY;
 
 	if (repo_parse_commit(r, commit))
 		return ret;
 	for (i = 0; i < nr_reference; i++) {
 		if (repo_parse_commit(r, reference[i]))
 			return ret;
-		if (reference[i]->generation < min_generation)
-			min_generation = reference[i]->generation;
+
+		generation = commit_graph_generation(reference[i]);
+		if (generation < min_generation)
+			min_generation = generation;
 	}
 
-	if (commit->generation > min_generation)
+	generation = commit_graph_generation(commit);
+	if (generation > min_generation)
 		return ret;
 
 	bases = paint_down_to_common(r, commit,
 				     nr_reference, reference,
-				     commit->generation);
+				     generation);
 	if (commit->object.flags & PARENT2)
 		ret = 1;
 	clear_commit_marks(commit, all_flags);
@@ -348,7 +356,15 @@
 			struct commit *commit,
 			struct commit *reference)
 {
-	return repo_in_merge_bases_many(r, commit, 1, &reference);
+	int res;
+	struct commit_list *list = NULL;
+	struct commit_list **next = &list;
+
+	next = commit_list_append(commit, next);
+	res = repo_is_descendant_of(r, reference, list);
+	free_commit_list(list);
+
+	return res;
 }
 
 struct commit_list *reduce_heads(struct commit_list *heads)
@@ -396,6 +412,7 @@
 	struct object *o;
 	struct commit *old_commit, *new_commit;
 	struct commit_list *old_commit_list = NULL;
+	int ret;
 
 	/*
 	 * Both new_commit and old_commit must be commit-ish and new_commit is descendant of
@@ -417,7 +434,10 @@
 		return 0;
 
 	commit_list_insert(old_commit, &old_commit_list);
-	return is_descendant_of(new_commit, old_commit_list);
+	ret = repo_is_descendant_of(the_repository,
+				    new_commit, old_commit_list);
+	free_commit_list(old_commit_list);
+	return ret;
 }
 
 /*
@@ -467,7 +487,7 @@
 	/* Otherwise, we don't know; prepare to recurse */
 	parse_commit_or_die(candidate);
 
-	if (candidate->generation < cutoff)
+	if (commit_graph_generation(candidate) < cutoff)
 		return CONTAINS_NO;
 
 	return CONTAINS_UNKNOWN;
@@ -490,10 +510,12 @@
 	const struct commit_list *p;
 
 	for (p = want; p; p = p->next) {
+		uint32_t generation;
 		struct commit *c = p->item;
 		load_commit_graph_info(the_repository, c);
-		if (c->generation < cutoff)
-			cutoff = c->generation;
+		generation = commit_graph_generation(c);
+		if (generation < cutoff)
+			cutoff = generation;
 	}
 
 	result = contains_test(candidate, want, cache, cutoff);
@@ -536,7 +558,7 @@
 {
 	if (filter->with_commit_tag_algo)
 		return contains_tag_algo(commit, list, cache) == CONTAINS_YES;
-	return is_descendant_of(commit, list);
+	return repo_is_descendant_of(the_repository, commit, list);
 }
 
 static int compare_commits_by_gen(const void *_a, const void *_b)
@@ -544,9 +566,12 @@
 	const struct commit *a = *(const struct commit * const *)_a;
 	const struct commit *b = *(const struct commit * const *)_b;
 
-	if (a->generation < b->generation)
+	uint32_t generation_a = commit_graph_generation(a);
+	uint32_t generation_b = commit_graph_generation(b);
+
+	if (generation_a < generation_b)
 		return -1;
-	if (a->generation > b->generation)
+	if (generation_a > generation_b)
 		return 1;
 	return 0;
 }
@@ -585,7 +610,7 @@
 
 		list[nr_commits] = (struct commit *)from_one;
 		if (parse_commit(list[nr_commits]) ||
-		    list[nr_commits]->generation < min_generation) {
+		    commit_graph_generation(list[nr_commits]) < min_generation) {
 			result = 0;
 			goto cleanup;
 		}
@@ -621,7 +646,7 @@
 
 					if (parse_commit(parent->item) ||
 					    parent->item->date < min_commit_date ||
-					    parent->item->generation < min_generation)
+					    commit_graph_generation(parent->item) < min_generation)
 						continue;
 
 					commit_list_insert(parent->item, &stack);
@@ -662,11 +687,13 @@
 		add_object_array(&from_iter->item->object, NULL, &from_objs);
 
 		if (!parse_commit(from_iter->item)) {
+			uint32_t generation;
 			if (from_iter->item->date < min_commit_date)
 				min_commit_date = from_iter->item->date;
 
-			if (from_iter->item->generation < min_generation)
-				min_generation = from_iter->item->generation;
+			generation = commit_graph_generation(from_iter->item);
+			if (generation < min_generation)
+				min_generation = generation;
 		}
 
 		from_iter = from_iter->next;
@@ -674,11 +701,13 @@
 
 	while (to_iter) {
 		if (!parse_commit(to_iter->item)) {
+			uint32_t generation;
 			if (to_iter->item->date < min_commit_date)
 				min_commit_date = to_iter->item->date;
 
-			if (to_iter->item->generation < min_generation)
-				min_generation = to_iter->item->generation;
+			generation = commit_graph_generation(to_iter->item);
+			if (generation < min_generation)
+				min_generation = generation;
 		}
 
 		to_iter->item->object.flags |= PARENT2;
@@ -718,11 +747,13 @@
 	struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
 
 	for (item = to; item < to_last; item++) {
+		uint32_t generation;
 		struct commit *c = *item;
 
 		parse_commit(c);
-		if (c->generation < min_generation)
-			min_generation = c->generation;
+		generation = commit_graph_generation(c);
+		if (generation < min_generation)
+			min_generation = generation;
 
 		if (!(c->object.flags & PARENT1)) {
 			c->object.flags |= PARENT1;
@@ -755,7 +786,7 @@
 
 			parse_commit(p);
 
-			if (p->generation < min_generation)
+			if (commit_graph_generation(p) < min_generation)
 				continue;
 
 			if (p->object.flags & PARENT2)
diff --git a/commit-reach.h b/commit-reach.h
index 99a43e8..b49ad71 100644
--- a/commit-reach.h
+++ b/commit-reach.h
@@ -27,7 +27,9 @@
 
 struct commit_list *get_octopus_merge_bases(struct commit_list *in);
 
-int is_descendant_of(struct commit *commit, struct commit_list *with_commit);
+int repo_is_descendant_of(struct repository *r,
+			  struct commit *commit,
+			  struct commit_list *with_commit);
 int repo_in_merge_bases(struct repository *r,
 			struct commit *commit,
 			struct commit *reference);
diff --git a/commit-slab-decl.h b/commit-slab-decl.h
index bfbed15..98de2c9 100644
--- a/commit-slab-decl.h
+++ b/commit-slab-decl.h
@@ -32,6 +32,7 @@
 void init_ ##slabname## _with_stride(struct slabname *s, unsigned stride); \
 void init_ ##slabname(struct slabname *s);				\
 void clear_ ##slabname(struct slabname *s);				\
+void deep_clear_ ##slabname(struct slabname *s, void (*free_fn)(elemtype *ptr)); \
 elemtype *slabname## _at_peek(struct slabname *s, const struct commit *c, int add_if_missing); \
 elemtype *slabname## _at(struct slabname *s, const struct commit *c);	\
 elemtype *slabname## _peek(struct slabname *s, const struct commit *c)
diff --git a/commit-slab-impl.h b/commit-slab-impl.h
index 5c0eb91..557738d 100644
--- a/commit-slab-impl.h
+++ b/commit-slab-impl.h
@@ -38,6 +38,19 @@
 	FREE_AND_NULL(s->slab);						\
 }									\
 									\
+scope void deep_clear_ ##slabname(struct slabname *s, void (*free_fn)(elemtype *)) \
+{									\
+	unsigned int i;							\
+	for (i = 0; i < s->slab_count; i++) {				\
+		unsigned int j;						\
+		if (!s->slab[i])					\
+			continue;					\
+		for (j = 0; j < s->slab_size; j++)			\
+			free_fn(&s->slab[i][j * s->stride]);		\
+	}								\
+	clear_ ##slabname(s);						\
+}									\
+									\
 scope elemtype *slabname## _at_peek(struct slabname *s,			\
 						  const struct commit *c, \
 						  int add_if_missing)   \
diff --git a/commit-slab.h b/commit-slab.h
index 05b3f28..8e72a30 100644
--- a/commit-slab.h
+++ b/commit-slab.h
@@ -47,6 +47,16 @@
  *
  *   Call this function before the slab falls out of scope to avoid
  *   leaking memory.
+ *
+ * - void deep_clear_indegree(struct indegree *, void (*free_fn)(int*))
+ *
+ *   Empties the slab, similar to clear_indegree(), but in addition it
+ *   calls the given 'free_fn' for each slab entry to release any
+ *   additional memory that might be owned by the entry (but not the
+ *   entry itself!).
+ *   Note that 'free_fn' might be called even for entries for which no
+ *   indegree_at() call has been made; in this case 'free_fn' is invoked
+ *   with a pointer to a zero-initialized location.
  */
 
 #define define_commit_slab(slabname, elemtype) \
diff --git a/commit.c b/commit.c
index 87686a7..7128895 100644
--- a/commit.c
+++ b/commit.c
@@ -37,7 +37,7 @@
 
 	if (!obj)
 		return NULL;
-	return object_as_type(r, obj, OBJ_COMMIT, quiet);
+	return object_as_type(obj, OBJ_COMMIT, quiet);
 }
 
 struct commit *lookup_commit_reference(struct repository *r, const struct object_id *oid)
@@ -62,7 +62,7 @@
 	struct object *obj = lookup_object(r, oid);
 	if (!obj)
 		return create_object(r, oid, alloc_commit_node(r));
-	return object_as_type(r, obj, OBJ_COMMIT, 0);
+	return object_as_type(obj, OBJ_COMMIT, 0);
 }
 
 struct commit *lookup_commit_reference_by_name(const char *name)
@@ -339,7 +339,7 @@
 	if (commit->maybe_tree || !commit->object.parsed)
 		return commit->maybe_tree;
 
-	if (commit->graph_pos != COMMIT_NOT_FROM_GRAPH)
+	if (commit_graph_position(commit) != COMMIT_NOT_FROM_GRAPH)
 		return get_commit_tree_in_graph(r, commit);
 
 	return NULL;
@@ -423,6 +423,8 @@
 	pptr = &item->parents;
 
 	graft = lookup_commit_graft(r, &item->object.oid);
+	if (graft)
+		r->parsed_objects->substituted_parent = 1;
 	while (bufptr + parent_entry_len < tail && !memcmp(bufptr, "parent ", 7)) {
 		struct commit *new_parent;
 
@@ -729,11 +731,13 @@
 int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void *unused)
 {
 	const struct commit *a = a_, *b = b_;
+	const uint32_t generation_a = commit_graph_generation(a),
+		       generation_b = commit_graph_generation(b);
 
 	/* newer commits first */
-	if (a->generation < b->generation)
+	if (generation_a < generation_b)
 		return 1;
-	else if (a->generation > b->generation)
+	else if (generation_a > generation_b)
 		return -1;
 
 	/* use date as a heuristic when generations are equal */
diff --git a/commit.h b/commit.h
index 1b2dea5..e901538 100644
--- a/commit.h
+++ b/commit.h
@@ -36,8 +36,6 @@
 	 * or get_commit_tree_oid().
 	 */
 	struct tree *maybe_tree;
-	uint32_t graph_pos;
-	uint32_t generation;
 	unsigned int index;
 };
 
diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl
index d9f71b7..61ad084 100755
--- a/compat/vcbuild/scripts/clink.pl
+++ b/compat/vcbuild/scripts/clink.pl
@@ -23,7 +23,9 @@
 	    # before any "-l*" flags.
 	    $is_debug = 1;
 	}
-	if ("$arg" =~ /^-[DIMGOZ]/) {
+	if ("$arg" =~ /^-I\/mingw(32|64)/) {
+		# eat
+	} elsif ("$arg" =~ /^-[DIMGOZ]/) {
 		push(@cflags, $arg);
 	} elsif ("$arg" eq "-o") {
 		my $file_out = shift @ARGV;
diff --git a/connect.c b/connect.c
index 0df45a1..e0d5b9f 100644
--- a/connect.c
+++ b/connect.c
@@ -18,7 +18,7 @@
 
 static char *server_capabilities_v1;
 static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT;
-static const char *parse_feature_value(const char *, const char *, int *);
+static const char *next_server_feature_value(const char *feature, int *len, int *offset);
 
 static int check_ref(const char *name, unsigned int flags)
 {
@@ -83,6 +83,21 @@
 	return 0;
 }
 
+int server_feature_v2(const char *c, const char **v)
+{
+	int i;
+
+	for (i = 0; i < server_capabilities_v2.argc; i++) {
+		const char *out;
+		if (skip_prefix(server_capabilities_v2.argv[i], c, &out) &&
+		    (*out == '=')) {
+			*v = out + 1;
+			return 1;
+		}
+	}
+	return 0;
+}
+
 int server_supports_feature(const char *c, const char *feature,
 			    int die_on_error)
 {
@@ -181,17 +196,16 @@
 static void annotate_refs_with_symref_info(struct ref *ref)
 {
 	struct string_list symref = STRING_LIST_INIT_DUP;
-	const char *feature_list = server_capabilities_v1;
+	int offset = 0;
 
-	while (feature_list) {
+	while (1) {
 		int len;
 		const char *val;
 
-		val = parse_feature_value(feature_list, "symref", &len);
+		val = next_server_feature_value("symref", &len, &offset);
 		if (!val)
 			break;
 		parse_one_symref_info(&symref, val, len);
-		feature_list = val + 1;
 	}
 	string_list_sort(&symref);
 
@@ -205,21 +219,36 @@
 	string_list_clear(&symref, 0);
 }
 
-static void process_capabilities(const char *line, int *len)
+static void process_capabilities(struct packet_reader *reader, int *linelen)
 {
+	const char *feat_val;
+	int feat_len;
+	const char *line = reader->line;
 	int nul_location = strlen(line);
-	if (nul_location == *len)
+	if (nul_location == *linelen)
 		return;
 	server_capabilities_v1 = xstrdup(line + nul_location + 1);
-	*len = nul_location;
+	*linelen = nul_location;
+
+	feat_val = server_feature_value("object-format", &feat_len);
+	if (feat_val) {
+		char *hash_name = xstrndup(feat_val, feat_len);
+		int hash_algo = hash_algo_by_name(hash_name);
+		if (hash_algo != GIT_HASH_UNKNOWN)
+			reader->hash_algo = &hash_algos[hash_algo];
+		free(hash_name);
+	} else {
+		reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
+	}
 }
 
-static int process_dummy_ref(const char *line)
+static int process_dummy_ref(const struct packet_reader *reader)
 {
+	const char *line = reader->line;
 	struct object_id oid;
 	const char *name;
 
-	if (parse_oid_hex(line, &oid, &name))
+	if (parse_oid_hex_algop(line, &oid, &name, reader->hash_algo))
 		return 0;
 	if (*name != ' ')
 		return 0;
@@ -235,13 +264,15 @@
 			line + strlen(line));
 }
 
-static int process_ref(const char *line, int len, struct ref ***list,
-		       unsigned int flags, struct oid_array *extra_have)
+static int process_ref(const struct packet_reader *reader, int len,
+		       struct ref ***list, unsigned int flags,
+		       struct oid_array *extra_have)
 {
+	const char *line = reader->line;
 	struct object_id old_oid;
 	const char *name;
 
-	if (parse_oid_hex(line, &old_oid, &name))
+	if (parse_oid_hex_algop(line, &old_oid, &name, reader->hash_algo))
 		return 0;
 	if (*name != ' ')
 		return 0;
@@ -261,16 +292,17 @@
 	return 1;
 }
 
-static int process_shallow(const char *line, int len,
+static int process_shallow(const struct packet_reader *reader, int len,
 			   struct oid_array *shallow_points)
 {
+	const char *line = reader->line;
 	const char *arg;
 	struct object_id old_oid;
 
 	if (!skip_prefix(line, "shallow ", &arg))
 		return 0;
 
-	if (get_oid_hex(arg, &old_oid))
+	if (get_oid_hex_algop(arg, &old_oid, reader->hash_algo))
 		die(_("protocol error: expected shallow sha-1, got '%s'"), arg);
 	if (!shallow_points)
 		die(_("repository on the other end cannot be shallow"));
@@ -317,20 +349,20 @@
 
 		switch (state) {
 		case EXPECTING_FIRST_REF:
-			process_capabilities(reader->line, &len);
-			if (process_dummy_ref(reader->line)) {
+			process_capabilities(reader, &len);
+			if (process_dummy_ref(reader)) {
 				state = EXPECTING_SHALLOW;
 				break;
 			}
 			state = EXPECTING_REF;
 			/* fallthrough */
 		case EXPECTING_REF:
-			if (process_ref(reader->line, len, &list, flags, extra_have))
+			if (process_ref(reader, len, &list, flags, extra_have))
 				break;
 			state = EXPECTING_SHALLOW;
 			/* fallthrough */
 		case EXPECTING_SHALLOW:
-			if (process_shallow(reader->line, len, shallow_points))
+			if (process_shallow(reader, len, shallow_points))
 				break;
 			die(_("protocol error: unexpected '%s'"), reader->line);
 		case EXPECTING_DONE:
@@ -344,7 +376,7 @@
 }
 
 /* Returns 1 when a valid ref has been added to `list`, 0 otherwise */
-static int process_ref_v2(const char *line, struct ref ***list)
+static int process_ref_v2(struct packet_reader *reader, struct ref ***list)
 {
 	int ret = 1;
 	int i = 0;
@@ -352,6 +384,7 @@
 	struct ref *ref;
 	struct string_list line_sections = STRING_LIST_INIT_DUP;
 	const char *end;
+	const char *line = reader->line;
 
 	/*
 	 * Ref lines have a number of fields which are space deliminated.  The
@@ -364,7 +397,7 @@
 		goto out;
 	}
 
-	if (parse_oid_hex(line_sections.items[i++].string, &old_oid, &end) ||
+	if (parse_oid_hex_algop(line_sections.items[i++].string, &old_oid, &end, reader->hash_algo) ||
 	    *end) {
 		ret = 0;
 		goto out;
@@ -372,7 +405,7 @@
 
 	ref = alloc_ref(line_sections.items[i++].string);
 
-	oidcpy(&ref->old_oid, &old_oid);
+	memcpy(ref->old_oid.hash, old_oid.hash, reader->hash_algo->rawsz);
 	**list = ref;
 	*list = &ref->next;
 
@@ -385,7 +418,8 @@
 			struct object_id peeled_oid;
 			char *peeled_name;
 			struct ref *peeled;
-			if (parse_oid_hex(arg, &peeled_oid, &end) || *end) {
+			if (parse_oid_hex_algop(arg, &peeled_oid, &end,
+						reader->hash_algo) || *end) {
 				ret = 0;
 				goto out;
 			}
@@ -393,7 +427,8 @@
 			peeled_name = xstrfmt("%s^{}", ref->name);
 			peeled = alloc_ref(peeled_name);
 
-			oidcpy(&peeled->old_oid, &peeled_oid);
+			memcpy(peeled->old_oid.hash, peeled_oid.hash,
+			       reader->hash_algo->rawsz);
 			**list = peeled;
 			*list = &peeled->next;
 
@@ -423,6 +458,7 @@
 			     int stateless_rpc)
 {
 	int i;
+	const char *hash_name;
 	*list = NULL;
 
 	if (server_supports_v2("ls-refs", 1))
@@ -431,6 +467,16 @@
 	if (server_supports_v2("agent", 0))
 		packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized());
 
+	if (server_feature_v2("object-format", &hash_name)) {
+		int hash_algo = hash_algo_by_name(hash_name);
+		if (hash_algo == GIT_HASH_UNKNOWN)
+			die(_("unknown object format '%s' specified by server"), hash_name);
+		reader->hash_algo = &hash_algos[hash_algo];
+		packet_write_fmt(fd_out, "object-format=%s", reader->hash_algo->name);
+	} else {
+		reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
+	}
+
 	if (server_options && server_options->nr &&
 	    server_supports_v2("server-option", 1))
 		for (i = 0; i < server_options->nr; i++)
@@ -450,7 +496,7 @@
 
 	/* Process response from server */
 	while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
-		if (!process_ref_v2(reader->line, &list))
+		if (!process_ref_v2(reader, &list))
 			die(_("invalid ls-refs response: %s"), reader->line);
 	}
 
@@ -463,7 +509,7 @@
 	return list;
 }
 
-static const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp)
+const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset)
 {
 	int len;
 
@@ -471,6 +517,8 @@
 		return NULL;
 
 	len = strlen(feature);
+	if (offset)
+		feature_list += *offset;
 	while (*feature_list) {
 		const char *found = strstr(feature_list, feature);
 		if (!found)
@@ -485,9 +533,14 @@
 			}
 			/* feature with a value (e.g., "agent=git/1.2.3") */
 			else if (*value == '=') {
+				int end;
+
 				value++;
+				end = strcspn(value, " \t\n");
 				if (lenp)
-					*lenp = strcspn(value, " \t\n");
+					*lenp = end;
+				if (offset)
+					*offset = value + end - feature_list;
 				return value;
 			}
 			/*
@@ -500,14 +553,41 @@
 	return NULL;
 }
 
+int server_supports_hash(const char *desired, int *feature_supported)
+{
+	int offset = 0;
+	int len;
+	const char *hash;
+
+	hash = next_server_feature_value("object-format", &len, &offset);
+	if (feature_supported)
+		*feature_supported = !!hash;
+	if (!hash) {
+		hash = hash_algos[GIT_HASH_SHA1].name;
+		len = strlen(hash);
+	}
+	while (hash) {
+		if (!xstrncmpz(desired, hash, len))
+			return 1;
+
+		hash = next_server_feature_value("object-format", &len, &offset);
+	}
+	return 0;
+}
+
 int parse_feature_request(const char *feature_list, const char *feature)
 {
-	return !!parse_feature_value(feature_list, feature, NULL);
+	return !!parse_feature_value(feature_list, feature, NULL, NULL);
+}
+
+static const char *next_server_feature_value(const char *feature, int *len, int *offset)
+{
+	return parse_feature_value(server_capabilities_v1, feature, len, offset);
 }
 
 const char *server_feature_value(const char *feature, int *len)
 {
-	return parse_feature_value(server_capabilities_v1, feature, len);
+	return parse_feature_value(server_capabilities_v1, feature, len, NULL);
 }
 
 int server_supports(const char *feature)
diff --git a/connect.h b/connect.h
index 235bc66..c53586e 100644
--- a/connect.h
+++ b/connect.h
@@ -18,7 +18,10 @@
 struct packet_reader;
 enum protocol_version discover_version(struct packet_reader *reader);
 
+int server_supports_hash(const char *desired, int *feature_supported);
+const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset);
 int server_supports_v2(const char *c, int die_on_error);
+int server_feature_v2(const char *c, const char **v);
 int server_supports_feature(const char *c, const char *feature,
 			    int die_on_error);
 
diff --git a/connected.c b/connected.c
index 3135b71..937b4ba 100644
--- a/connected.c
+++ b/connected.c
@@ -43,10 +43,12 @@
 
 	if (transport && transport->smart_options &&
 	    transport->smart_options->self_contained_and_connected &&
-	    transport->pack_lockfile &&
-	    strip_suffix(transport->pack_lockfile, ".keep", &base_len)) {
+	    transport->pack_lockfiles.nr == 1 &&
+	    strip_suffix(transport->pack_lockfiles.items[0].string,
+			 ".keep", &base_len)) {
 		struct strbuf idx_file = STRBUF_INIT;
-		strbuf_add(&idx_file, transport->pack_lockfile, base_len);
+		strbuf_add(&idx_file, transport->pack_lockfiles.items[0].string,
+			   base_len);
 		strbuf_addstr(&idx_file, ".idx");
 		new_pack = add_packed_git(idx_file.buf, idx_file.len, 1);
 		strbuf_release(&idx_file);
diff --git a/contrib/coccinelle/commit.cocci b/contrib/coccinelle/commit.cocci
index 778e470..af6dd4c 100644
--- a/contrib/coccinelle/commit.cocci
+++ b/contrib/coccinelle/commit.cocci
@@ -32,3 +32,21 @@
 - c->maybe_tree
 + repo_get_commit_tree(specify_the_right_repo_here, c)
   ...>}
+
+@@
+struct commit *c;
+expression E;
+@@
+(
+- c->generation = E;
++ commit_graph_data_at(c)->generation = E;
+|
+- c->graph_pos = E;
++ commit_graph_data_at(c)->graph_pos = E;
+|
+- c->generation
++ commit_graph_generation(c)
+|
+- c->graph_pos
++ commit_graph_position(c)
+)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 4b59004..ee468ea 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -50,7 +50,7 @@
 # variable.
 __git_find_repo_path ()
 {
-	if [ -n "$__git_repo_path" ]; then
+	if [ -n "${__git_repo_path-}" ]; then
 		# we already know where it is
 		return
 	fi
@@ -301,6 +301,19 @@
 	COMPREPLY=($1)
 }
 
+# Similar to __gitcomp_direct, but appends to COMPREPLY instead.
+# Callers must take care of providing only words that match the current word
+# to be completed and adding any prefix and/or suffix (trailing space!), if
+# necessary.
+# 1: List of newline-separated matching completion words, complete with
+#    prefix and suffix.
+__gitcomp_direct_append ()
+{
+	local IFS=$'\n'
+
+	COMPREPLY+=($1)
+}
+
 __gitcompappend ()
 {
 	local x i=${#COMPREPLY[@]}
@@ -391,12 +404,12 @@
 	# spaces must be replaced with underscore for multi-word
 	# commands, e.g. "git remote add" becomes remote_add.
 	local cmd="$1"
-	local incl="$2"
-	local excl="$3"
+	local incl="${2-}"
+	local excl="${3-}"
 
 	local var=__gitcomp_builtin_"${cmd/-/_}"
 	local options
-	eval "options=\$$var"
+	eval "options=\${$var-}"
 
 	if [ -z "$options" ]; then
 		# leading and trailing spaces are significant to make
@@ -611,6 +624,19 @@
 			"refs/heads/$cur_*" "refs/heads/$cur_*/**"
 }
 
+# Lists branches from remote repositories.
+# 1: A prefix to be added to each listed branch (optional).
+# 2: List only branches matching this word (optional; list all branches if
+#    unset or empty).
+# 3: A suffix to be appended to each listed branch (optional).
+__git_remote_heads ()
+{
+	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
+
+	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
+			"refs/remotes/$cur_*" "refs/remotes/$cur_*/**"
+}
+
 # Lists tags from the local repository.
 # Accepts the same positional parameters as __git_heads() above.
 __git_tags ()
@@ -621,6 +647,26 @@
 			"refs/tags/$cur_*" "refs/tags/$cur_*/**"
 }
 
+# List unique branches from refs/remotes used for 'git checkout' and 'git
+# switch' tracking DWIMery.
+# 1: A prefix to be added to each listed branch (optional)
+# 2: List only branches matching this word (optional; list all branches if
+#    unset or empty).
+# 3: A suffix to be appended to each listed branch (optional).
+__git_dwim_remote_heads ()
+{
+	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
+	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
+
+	# employ the heuristic used by git checkout and git switch
+	# Try to find a remote branch that cur_es the completion word
+	# but only output if the branch name is unique
+	__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
+		--sort="refname:strip=3" \
+		"refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \
+	uniq -u
+}
+
 # Lists refs from the local (by default) or from a remote repository.
 # It accepts 0, 1 or 2 arguments:
 # 1: The remote to list refs from (optional; ignored, if set but empty).
@@ -696,13 +742,7 @@
 		__git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \
 			"${refs[@]}"
 		if [ -n "$track" ]; then
-			# employ the heuristic used by git checkout
-			# Try to find a remote branch that matches the completion word
-			# but only output if the branch name is unique
-			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
-				--sort="refname:strip=3" \
-				"refs/remotes/*/$match*" "refs/remotes/*/$match*/**" | \
-			uniq -u
+			__git_dwim_remote_heads "$pfx" "$match" "$sfx"
 		fi
 		return
 	fi
@@ -749,29 +789,51 @@
 # Usage: __git_complete_refs [<option>]...
 # --remote=<remote>: The remote to list refs from, can be the name of a
 #                    configured remote, a path, or a URL.
-# --track: List unique remote branches for 'git checkout's tracking DWIMery.
+# --dwim: List unique remote branches for 'git switch's tracking DWIMery.
 # --pfx=<prefix>: A prefix to be added to each ref.
 # --cur=<word>: The current ref to be completed.  Defaults to the current
 #               word to be completed.
 # --sfx=<suffix>: A suffix to be appended to each ref instead of the default
 #                 space.
+# --mode=<mode>: What set of refs to complete, one of 'refs' (the default) to
+#                complete all refs, 'heads' to complete only branches, or
+#                'remote-heads' to complete only remote branches. Note that
+#                --remote is only compatible with --mode=refs.
 __git_complete_refs ()
 {
-	local remote track pfx cur_="$cur" sfx=" "
+	local remote= dwim= pfx= cur_="$cur" sfx=" " mode="refs"
 
 	while test $# != 0; do
 		case "$1" in
 		--remote=*)	remote="${1##--remote=}" ;;
-		--track)	track="yes" ;;
+		--dwim)		dwim="yes" ;;
+		# --track is an old spelling of --dwim
+		--track)	dwim="yes" ;;
 		--pfx=*)	pfx="${1##--pfx=}" ;;
 		--cur=*)	cur_="${1##--cur=}" ;;
 		--sfx=*)	sfx="${1##--sfx=}" ;;
+		--mode=*)	mode="${1##--mode=}" ;;
 		*)		return 1 ;;
 		esac
 		shift
 	done
 
-	__gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx")"
+	# complete references based on the specified mode
+	case "$mode" in
+		refs)
+			__gitcomp_direct "$(__git_refs "$remote" "" "$pfx" "$cur_" "$sfx")" ;;
+		heads)
+			__gitcomp_direct "$(__git_heads "$pfx" "$cur_" "$sfx")" ;;
+		remote-heads)
+			__gitcomp_direct "$(__git_remote_heads "$pfx" "$cur_" "$sfx")" ;;
+		*)
+			return 1 ;;
+	esac
+
+	# Append DWIM remote branch names if requested
+	if [ "$dwim" = "yes" ]; then
+		__gitcomp_direct_append "$(__git_dwim_remote_heads "$pfx" "$cur_" "$sfx")"
+	fi
 }
 
 # __git_refs2 requires 1 argument (to pass to __git_refs)
@@ -1090,7 +1152,7 @@
 	while [ $c -lt $cword ]; do
 		for word in $wordlist; do
 			if [ "$word" = "${words[c]}" ]; then
-				if [ -n "$show_idx" ]; then
+				if [ -n "${show_idx-}" ]; then
 					echo "$c $word"
 				else
 					echo "$word"
@@ -1102,6 +1164,40 @@
 	done
 }
 
+# Similar to __git_find_on_cmdline, except that it loops backwards and thus
+# prints the *last* word found. Useful for finding which of two options that
+# supersede each other came last, such as "--guess" and "--no-guess".
+#
+# Usage: __git_find_last_on_cmdline [<option>]... "<wordlist>"
+# --show-idx: Optionally show the index of the found word in the $words array.
+__git_find_last_on_cmdline ()
+{
+	local word c=$cword show_idx
+
+	while test $# -gt 1; do
+		case "$1" in
+		--show-idx)	show_idx=y ;;
+		*)		return 1 ;;
+		esac
+		shift
+	done
+	local wordlist="$1"
+
+	while [ $c -gt 1 ]; do
+		((c--))
+		for word in $wordlist; do
+			if [ "$word" = "${words[c]}" ]; then
+				if [ -n "$show_idx" ]; then
+					echo "$c $word"
+				else
+					echo "$word"
+				fi
+				return
+			fi
+		done
+	done
+}
+
 # Echo the value of an option set on the command line or config
 #
 # $1: short option name
@@ -1356,6 +1452,46 @@
 	esac
 }
 
+# Helper function to decide whether or not we should enable DWIM logic for
+# git-switch and git-checkout.
+#
+# To decide between the following rules in priority order
+# 1) the last provided of "--guess" or "--no-guess" explicitly enable or
+#    disable completion of DWIM logic respectively.
+# 2) If the --no-track option is provided, take this as a hint to disable the
+#    DWIM completion logic
+# 3) If GIT_COMPLETION_CHECKOUT_NO_GUESS is set, disable the DWIM completion
+#    logic, as requested by the user.
+# 4) Enable DWIM logic otherwise.
+#
+__git_checkout_default_dwim_mode ()
+{
+	local last_option dwim_opt="--dwim"
+
+	if [ "${GIT_COMPLETION_CHECKOUT_NO_GUESS-}" = "1" ]; then
+		dwim_opt=""
+	fi
+
+	# --no-track disables DWIM, but with lower priority than
+	# --guess/--no-guess
+	if [ -n "$(__git_find_on_cmdline "--no-track")" ]; then
+		dwim_opt=""
+	fi
+
+	# Find the last provided --guess or --no-guess
+	last_option="$(__git_find_last_on_cmdline "--guess --no-guess")"
+	case "$last_option" in
+		--guess)
+			dwim_opt="--dwim"
+			;;
+		--no-guess)
+			dwim_opt=""
+			;;
+	esac
+
+	echo "$dwim_opt"
+}
+
 _git_checkout ()
 {
 	__git_has_doubledash && return
@@ -1368,14 +1504,38 @@
 		__gitcomp_builtin checkout
 		;;
 	*)
-		# check if --track, --no-track, or --no-guess was specified
-		# if so, disable DWIM mode
-		local flags="--track --no-track --no-guess" track_opt="--track"
-		if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] ||
-		   [ -n "$(__git_find_on_cmdline "$flags")" ]; then
-			track_opt=''
+		local dwim_opt="$(__git_checkout_default_dwim_mode)"
+		local prevword prevword="${words[cword-1]}"
+
+		case "$prevword" in
+			-b|-B|--orphan)
+				# Complete local branches (and DWIM branch
+				# remote branch names) for an option argument
+				# specifying a new branch name. This is for
+				# convenience, assuming new branches are
+				# possibly based on pre-existing branch names.
+				__git_complete_refs $dwim_opt --mode="heads"
+				return
+				;;
+			*)
+				;;
+		esac
+
+		# At this point, we've already handled special completion for
+		# the arguments to -b/-B, and --orphan. There are 3 main
+		# things left we can possibly complete:
+		# 1) a start-point for -b/-B, -d/--detach, or --orphan
+		# 2) a remote head, for --track
+		# 3) an arbitrary reference, possibly including DWIM names
+		#
+
+		if [ -n "$(__git_find_on_cmdline "-b -B -d --detach --orphan")" ]; then
+			__git_complete_refs --mode="refs"
+		elif [ -n "$(__git_find_on_cmdline "--track")" ]; then
+			__git_complete_refs --mode="remote-heads"
+		else
+			__git_complete_refs $dwim_opt --mode="refs"
 		fi
-		__git_complete_refs $track_opt
 		;;
 	esac
 }
@@ -2224,29 +2384,43 @@
 		__gitcomp_builtin switch
 		;;
 	*)
-		# check if --track, --no-track, or --no-guess was specified
-		# if so, disable DWIM mode
-		local track_opt="--track" only_local_ref=n
-		if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] ||
-		   [ -n "$(__git_find_on_cmdline "--track --no-track --no-guess")" ]; then
-			track_opt=''
+		local dwim_opt="$(__git_checkout_default_dwim_mode)"
+		local prevword prevword="${words[cword-1]}"
+
+		case "$prevword" in
+			-c|-C|--orphan)
+				# Complete local branches (and DWIM branch
+				# remote branch names) for an option argument
+				# specifying a new branch name. This is for
+				# convenience, assuming new branches are
+				# possibly based on pre-existing branch names.
+				__git_complete_refs $dwim_opt --mode="heads"
+				return
+				;;
+			*)
+				;;
+		esac
+
+		# Unlike in git checkout, git switch --orphan does not take
+		# a start point. Thus we really have nothing to complete after
+		# the branch name.
+		if [ -n "$(__git_find_on_cmdline "--orphan")" ]; then
+			return
 		fi
-		# explicit --guess enables DWIM mode regardless of
-		# $GIT_COMPLETION_CHECKOUT_NO_GUESS
-		if [ -n "$(__git_find_on_cmdline "--guess")" ]; then
-			track_opt='--track'
-		fi
-		if [ -z "$(__git_find_on_cmdline "-d --detach")" ]; then
-			only_local_ref=y
+
+		# At this point, we've already handled special completion for
+		# -c/-C, and --orphan. There are 3 main things left to
+		# complete:
+		# 1) a start-point for -c/-C or -d/--detach
+		# 2) a remote head, for --track
+		# 3) a branch name, possibly including DWIM remote branches
+
+		if [ -n "$(__git_find_on_cmdline "-c -C -d --detach")" ]; then
+			__git_complete_refs --mode="refs"
+		elif [ -n "$(__git_find_on_cmdline "--track")" ]; then
+			__git_complete_refs --mode="remote-heads"
 		else
-			# --guess --detach is invalid combination, no
-			# dwim will be done when --detach is specified
-			track_opt=
-		fi
-		if [ $only_local_ref = y -a -z "$track_opt" ]; then
-			__gitcomp_direct "$(__git_heads "" "$cur" " ")"
-		else
-			__git_complete_refs $track_opt
+			__git_complete_refs $dwim_opt --mode="heads"
 		fi
 		;;
 	esac
@@ -3176,7 +3350,7 @@
 		((c++))
 	done
 
-	if [ -z "$command" ]; then
+	if [ -z "${command-}" ]; then
 		case "$prev" in
 		--git-dir|-C|--work-tree)
 			# these need a path argument, let's fall back to
@@ -3211,7 +3385,7 @@
 			"
 			;;
 		*)
-			if test -n "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
+			if test -n "${GIT_TESTING_PORCELAIN_COMMAND_LIST-}"
 			then
 				__gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
 			else
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 014cd7c..16260ba 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -70,6 +70,15 @@
 # state symbols by setting GIT_PS1_STATESEPARATOR. The default separator
 # is SP.
 #
+# When there is an in-progress operation such as a merge, rebase,
+# revert, cherry-pick, or bisect, the prompt will include information
+# related to the operation, often in the form "|<OPERATION-NAME>".
+#
+# When the repository has a sparse-checkout, a notification of the form
+# "|SPARSE" will be included in the prompt.  This can be shortened to a
+# single '?' character by setting GIT_PS1_COMPRESSSPARSESTATE, or omitted
+# by setting GIT_PS1_OMITSPARSESTATE.
+#
 # By default, __git_ps1 will compare HEAD to your SVN upstream if it can
 # find one, or @{upstream} otherwise.  Once you have set
 # GIT_PS1_SHOWUPSTREAM, you can override it on a per-repository basis by
@@ -421,6 +430,13 @@
 		return $exit
 	fi
 
+	local sparse=""
+	if [ -z "${GIT_PS1_COMPRESSSPARSESTATE}" ] &&
+	   [ -z "${GIT_PS1_OMITSPARSESTATE}" ] &&
+	   [ "$(git config --bool core.sparseCheckout)" = "true" ]; then
+		sparse="|SPARSE"
+	fi
+
 	local r=""
 	local b=""
 	local step=""
@@ -492,6 +508,7 @@
 	local i=""
 	local s=""
 	local u=""
+	local h=""
 	local c=""
 	local p=""
 
@@ -524,6 +541,11 @@
 			u="%${ZSH_VERSION+%}"
 		fi
 
+		if [ -n "${GIT_PS1_COMPRESSSPARSESTATE}" ] &&
+		   [ "$(git config --bool core.sparseCheckout)" = "true" ]; then
+			h="?"
+		fi
+
 		if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
 			__git_ps1_show_upstream
 		fi
@@ -542,8 +564,8 @@
 		b="\${__git_ps1_branch_name}"
 	fi
 
-	local f="$w$i$s$u"
-	local gitstring="$c$b${f:+$z$f}$r$p"
+	local f="$h$w$i$s$u"
+	local gitstring="$c$b${f:+$z$f}${sparse}$r$p"
 
 	if [ $pcmode = yes ]; then
 		if [ "${__git_printf_supports_v-}" != yes ]; then
diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index 57ff4b2..53d7acc 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -196,7 +196,8 @@
 		cd "$subtree_test_count" &&
 		git fetch ./"sub proj" master &&
 		git subtree merge --prefix="sub dir" FETCH_HEAD &&
-		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+		check_equal "$(last_commit_message)" \
+			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
 	)
 '
 
@@ -273,7 +274,8 @@
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir/ FETCH_HEAD &&
-		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+		check_equal "$(last_commit_message)" \
+			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
 	)
 '
 
diff --git a/diff-lib.c b/diff-lib.c
index 61812f4..25fd2de 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -220,8 +220,7 @@
 			} else if (revs->diffopt.ita_invisible_in_index &&
 				   ce_intent_to_add(ce)) {
 				diff_addremove(&revs->diffopt, '+', ce->ce_mode,
-					       the_hash_algo->empty_tree, 0,
-					       ce->name, 0);
+					       &null_oid, 0, ce->name, 0);
 				continue;
 			}
 
diff --git a/diff.c b/diff.c
index 863da89..d24aaa3 100644
--- a/diff.c
+++ b/diff.c
@@ -6763,8 +6763,11 @@
 		return;
 
 	if (options->flags.quick && options->skip_stat_unmatch &&
-	    !diff_filespec_check_stat_unmatch(options->repo, p))
+	    !diff_filespec_check_stat_unmatch(options->repo, p)) {
+		diff_free_filespec_data(p->one);
+		diff_free_filespec_data(p->two);
 		return;
+	}
 
 	options->flags.has_changes = 1;
 }
diff --git a/diff.h b/diff.h
index 9443dc1..e0c0af6 100644
--- a/diff.h
+++ b/diff.h
@@ -431,11 +431,11 @@
 	struct combine_diff_path *p, const struct object_id *oid,
 	const struct object_id **parents_oid, int nparent,
 	struct strbuf *base, struct diff_options *opt);
-int diff_tree_oid(const struct object_id *old_oid,
-		  const struct object_id *new_oid,
-		  const char *base, struct diff_options *opt);
-int diff_root_tree_oid(const struct object_id *new_oid, const char *base,
-		       struct diff_options *opt);
+void diff_tree_oid(const struct object_id *old_oid,
+		   const struct object_id *new_oid,
+		   const char *base, struct diff_options *opt);
+void diff_root_tree_oid(const struct object_id *new_oid, const char *base,
+			struct diff_options *opt);
 
 struct combine_diff_path {
 	struct combine_diff_path *next;
diff --git a/dir.c b/dir.c
index d97e955..fe64be3 100644
--- a/dir.c
+++ b/dir.c
@@ -193,6 +193,10 @@
 	const char *prefix;
 	size_t prefix_len;
 
+	unsigned exclusive_flags = DIR_SHOW_IGNORED | DIR_SHOW_IGNORED_TOO;
+	if ((dir->flags & exclusive_flags) == exclusive_flags)
+		BUG("DIR_SHOW_IGNORED and DIR_SHOW_IGNORED_TOO are exclusive");
+
 	/*
 	 * Calculate common prefix for the pathspec, and
 	 * use that to optimize the directory walk
@@ -364,7 +368,8 @@
 		return MATCHED_FNMATCH;
 
 	/* Perform checks to see if "name" is a leading string of the pathspec */
-	if (flags & DO_MATCH_LEADING_PATHSPEC) {
+	if ( (flags & DO_MATCH_LEADING_PATHSPEC) &&
+	    !(flags & DO_MATCH_EXCLUDE)) {
 		/* name is a literal prefix of the pathspec */
 		int offset = name[namelen-1] == '/' ? 1 : 0;
 		if ((namelen < matchlen) &&
@@ -401,6 +406,10 @@
 }
 
 /*
+ * do_match_pathspec() is meant to ONLY be called by
+ * match_pathspec_with_flags(); calling it directly risks pathspecs
+ * like ':!unwanted_path' being ignored.
+ *
  * Given a name and a list of pathspecs, returns the nature of the
  * closest (i.e. most specific) match of the name to any of the
  * pathspecs.
@@ -486,13 +495,12 @@
 	return retval;
 }
 
-int match_pathspec(const struct index_state *istate,
-		   const struct pathspec *ps,
-		   const char *name, int namelen,
-		   int prefix, char *seen, int is_dir)
+static int match_pathspec_with_flags(const struct index_state *istate,
+				     const struct pathspec *ps,
+				     const char *name, int namelen,
+				     int prefix, char *seen, unsigned flags)
 {
 	int positive, negative;
-	unsigned flags = is_dir ? DO_MATCH_DIRECTORY : 0;
 	positive = do_match_pathspec(istate, ps, name, namelen,
 				     prefix, seen, flags);
 	if (!(ps->magic & PATHSPEC_EXCLUDE) || !positive)
@@ -503,6 +511,16 @@
 	return negative ? 0 : positive;
 }
 
+int match_pathspec(const struct index_state *istate,
+		   const struct pathspec *ps,
+		   const char *name, int namelen,
+		   int prefix, char *seen, int is_dir)
+{
+	unsigned flags = is_dir ? DO_MATCH_DIRECTORY : 0;
+	return match_pathspec_with_flags(istate, ps, name, namelen,
+					 prefix, seen, flags);
+}
+
 /**
  * Check if a submodule is a superset of the pathspec
  */
@@ -511,11 +529,11 @@
 			 const char *submodule_name,
 			 char *seen)
 {
-	int matched = do_match_pathspec(istate, ps, submodule_name,
-					strlen(submodule_name),
-					0, seen,
-					DO_MATCH_DIRECTORY |
-					DO_MATCH_LEADING_PATHSPEC);
+	int matched = match_pathspec_with_flags(istate, ps, submodule_name,
+						strlen(submodule_name),
+						0, seen,
+						DO_MATCH_DIRECTORY |
+						DO_MATCH_LEADING_PATHSPEC);
 	return matched;
 }
 
@@ -1757,9 +1775,11 @@
 	 * for matching patterns.
 	 */
 	if (pathspec && !excluded) {
-		matches_how = do_match_pathspec(istate, pathspec, dirname, len,
-						0 /* prefix */, NULL /* seen */,
-						DO_MATCH_LEADING_PATHSPEC);
+		matches_how = match_pathspec_with_flags(istate, pathspec,
+							dirname, len,
+							0 /* prefix */,
+							NULL /* seen */,
+							DO_MATCH_LEADING_PATHSPEC);
 		if (!matches_how)
 			return path_none;
 	}
@@ -1820,7 +1840,7 @@
 	 * to recurse into untracked/ignored directories if either of the
 	 * following bits is set:
 	 *   - DIR_SHOW_IGNORED_TOO (because then we need to determine if
-	 *                           there are ignored directories below)
+	 *                           there are ignored entries below)
 	 *   - DIR_HIDE_EMPTY_DIRECTORIES (because we have to determine if
 	 *                                 the directory is empty)
 	 */
@@ -1838,10 +1858,11 @@
 		return path_excluded;
 
 	/*
-	 * If we have we don't want to know the all the paths under an
-	 * untracked or ignored directory, we still need to go into the
-	 * directory to determine if it is empty (because an empty directory
-	 * should be path_none instead of path_excluded or path_untracked).
+	 * Even if we don't want to know all the paths under an untracked or
+	 * ignored directory, we may still need to go into the directory to
+	 * determine if it is empty (because with DIR_HIDE_EMPTY_DIRECTORIES,
+	 * an empty directory should be path_none instead of path_excluded or
+	 * path_untracked).
 	 */
 	check_only = ((dir->flags & DIR_HIDE_EMPTY_DIRECTORIES) &&
 		      !(dir->flags & DIR_SHOW_IGNORED_TOO));
@@ -2188,13 +2209,13 @@
 				       baselen, excluded, pathspec);
 	case DT_REG:
 	case DT_LNK:
+		if (pathspec &&
+		    !match_pathspec(istate, pathspec, path->buf, path->len,
+				    0 /* prefix */, NULL /* seen */,
+				    0 /* is_dir */))
+			return path_none;
 		if (excluded)
 			return path_excluded;
-		if (pathspec &&
-		    !do_match_pathspec(istate, pathspec, path->buf, path->len,
-				       0 /* prefix */, NULL /* seen */,
-				       0 /* flags */))
-			return path_none;
 		return path_untracked;
 	}
 }
diff --git a/entry.c b/entry.c
index 00b4903..449bd32 100644
--- a/entry.c
+++ b/entry.c
@@ -113,8 +113,7 @@
 	/* use fstat() only when path == ce->name */
 	if (fstat_is_reliable() &&
 	    state->refresh_cache && !state->base_dir_len) {
-		fstat(fd, st);
-		return 1;
+		return !fstat(fd, st);
 	}
 	return 0;
 }
diff --git a/fetch-pack.c b/fetch-pack.c
index d8bbf45..80fb3bd 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -38,6 +38,7 @@
 static struct shallow_lock shallow_lock;
 static const char *alternate_shallow_file;
 static struct strbuf fsck_msg_types = STRBUF_INIT;
+static struct string_list uri_protocols = STRING_LIST_INIT_DUP;
 
 /* Remember to update object flag allocation in object.h */
 #define COMPLETE	(1U << 0)
@@ -794,7 +795,8 @@
 }
 
 static int get_pack(struct fetch_pack_args *args,
-		    int xd[2], char **pack_lockfile,
+		    int xd[2], struct string_list *pack_lockfiles,
+		    int only_packfile,
 		    struct ref **sought, int nr_sought)
 {
 	struct async demux;
@@ -838,7 +840,7 @@
 	}
 
 	if (do_keep || args->from_promisor) {
-		if (pack_lockfile)
+		if (pack_lockfiles)
 			cmd.out = -1;
 		cmd_name = "index-pack";
 		argv_array_push(&cmd.args, cmd_name);
@@ -855,15 +857,22 @@
 					"--keep=fetch-pack %"PRIuMAX " on %s",
 					(uintmax_t)getpid(), hostname);
 		}
-		if (args->check_self_contained_and_connected)
+		if (only_packfile && args->check_self_contained_and_connected)
 			argv_array_push(&cmd.args, "--check-self-contained-and-connected");
+		else
+			/*
+			 * We cannot perform any connectivity checks because
+			 * not all packs have been downloaded; let the caller
+			 * have this responsibility.
+			 */
+			args->check_self_contained_and_connected = 0;
 		/*
 		 * If we're obtaining the filename of a lockfile, we'll use
 		 * that filename to write a .promisor file with more
 		 * information below. If not, we need index-pack to do it for
 		 * us.
 		 */
-		if (!(do_keep && pack_lockfile) && args->from_promisor)
+		if (!(do_keep && pack_lockfiles) && args->from_promisor)
 			argv_array_push(&cmd.args, "--promisor");
 	}
 	else {
@@ -899,8 +908,9 @@
 	cmd.git_cmd = 1;
 	if (start_command(&cmd))
 		die(_("fetch-pack: unable to fork off %s"), cmd_name);
-	if (do_keep && pack_lockfile) {
-		*pack_lockfile = index_pack_lockfile(cmd.out);
+	if (do_keep && pack_lockfiles) {
+		string_list_append_nodup(pack_lockfiles,
+					 index_pack_lockfile(cmd.out));
 		close(cmd.out);
 	}
 
@@ -922,8 +932,8 @@
 	 * Now that index-pack has succeeded, write the promisor file using the
 	 * obtained .keep filename if necessary
 	 */
-	if (do_keep && pack_lockfile && args->from_promisor)
-		write_promisor_file(*pack_lockfile, sought, nr_sought);
+	if (do_keep && pack_lockfiles && pack_lockfiles->nr && args->from_promisor)
+		write_promisor_file(pack_lockfiles->items[0].string, sought, nr_sought);
 
 	return 0;
 }
@@ -940,7 +950,7 @@
 				 const struct ref *orig_ref,
 				 struct ref **sought, int nr_sought,
 				 struct shallow_info *si,
-				 char **pack_lockfile)
+				 struct string_list *pack_lockfiles)
 {
 	struct repository *r = the_repository;
 	struct ref *ref = copy_ref_list(orig_ref);
@@ -1040,6 +1050,8 @@
 		print_verbose(args, _("Server supports %s"), "deepen-relative");
 	else if (args->deepen_relative)
 		die(_("Server does not support --deepen"));
+	if (!server_supports_hash(the_hash_algo->name, NULL))
+		die(_("Server does not support this repository's object format"));
 
 	if (!args->no_dependents) {
 		mark_complete_and_common_ref(negotiator, args, &ref);
@@ -1067,7 +1079,7 @@
 		alternate_shallow_file = setup_temporary_shallow(si->shallow);
 	else
 		alternate_shallow_file = NULL;
-	if (get_pack(args, fd, pack_lockfile, sought, nr_sought))
+	if (get_pack(args, fd, pack_lockfiles, 1, sought, nr_sought))
 		die(_("git fetch-pack: fetch failed."));
 
  all_done:
@@ -1178,6 +1190,7 @@
 			      int sideband_all, int seen_ack)
 {
 	int ret = 0;
+	const char *hash_name;
 	struct strbuf req_buf = STRBUF_INIT;
 
 	if (server_supports_v2("fetch", 1))
@@ -1192,6 +1205,17 @@
 					 args->server_options->items[i].string);
 	}
 
+	if (server_feature_v2("object-format", &hash_name)) {
+		int hash_algo = hash_algo_by_name(hash_name);
+		if (hash_algo_by_ptr(the_hash_algo) != hash_algo)
+			die(_("mismatched algorithms: client %s; server %s"),
+			    the_hash_algo->name, hash_name);
+		packet_write_fmt(fd_out, "object-format=%s", the_hash_algo->name);
+	} else if (hash_algo_by_ptr(the_hash_algo) != GIT_HASH_SHA1) {
+		die(_("the server does not support algorithm '%s'"),
+		    the_hash_algo->name);
+	}
+
 	packet_buf_delim(&req_buf);
 	if (args->use_thin_pack)
 		packet_buf_write(&req_buf, "thin-pack");
@@ -1221,6 +1245,26 @@
 		warning("filtering not recognized by server, ignoring");
 	}
 
+	if (server_supports_feature("fetch", "packfile-uris", 0)) {
+		int i;
+		struct strbuf to_send = STRBUF_INIT;
+
+		for (i = 0; i < uri_protocols.nr; i++) {
+			const char *s = uri_protocols.items[i].string;
+
+			if (!strcmp(s, "https") || !strcmp(s, "http")) {
+				if (to_send.len)
+					strbuf_addch(&to_send, ',');
+				strbuf_addstr(&to_send, s);
+			}
+		}
+		if (to_send.len) {
+			packet_buf_write(&req_buf, "packfile-uris %s",
+					 to_send.buf);
+			strbuf_release(&to_send);
+		}
+	}
+
 	/* add wants */
 	add_wants(args->no_dependents, wants, &req_buf);
 
@@ -1443,6 +1487,21 @@
 		die(_("error processing wanted refs: %d"), reader->status);
 }
 
+static void receive_packfile_uris(struct packet_reader *reader,
+				  struct string_list *uris)
+{
+	process_section_header(reader, "packfile-uris", 0);
+	while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
+		if (reader->pktlen < the_hash_algo->hexsz ||
+		    reader->line[the_hash_algo->hexsz] != ' ')
+			die("expected '<hash> <uri>', got: %s\n", reader->line);
+
+		string_list_append(uris, reader->line);
+	}
+	if (reader->status != PACKET_READ_DELIM)
+		die("expected DELIM");
+}
+
 enum fetch_state {
 	FETCH_CHECK_LOCAL = 0,
 	FETCH_SEND_REQUEST,
@@ -1464,7 +1523,7 @@
 				    struct ref **sought, int nr_sought,
 				    struct oid_array *shallows,
 				    struct shallow_info *si,
-				    char **pack_lockfile)
+				    struct string_list *pack_lockfiles)
 {
 	struct repository *r = the_repository;
 	struct ref *ref = copy_ref_list(orig_ref);
@@ -1476,6 +1535,8 @@
 	struct fetch_negotiator negotiator_alloc;
 	struct fetch_negotiator *negotiator;
 	int seen_ack = 0;
+	struct string_list packfile_uris = STRING_LIST_INIT_DUP;
+	int i;
 
 	if (args->no_dependents) {
 		negotiator = NULL;
@@ -1569,9 +1630,12 @@
 			if (process_section_header(&reader, "wanted-refs", 1))
 				receive_wanted_refs(&reader, sought, nr_sought);
 
-			/* get the pack */
+			/* get the pack(s) */
+			if (process_section_header(&reader, "packfile-uris", 1))
+				receive_packfile_uris(&reader, &packfile_uris);
 			process_section_header(&reader, "packfile", 0);
-			if (get_pack(args, fd, pack_lockfile, sought, nr_sought))
+			if (get_pack(args, fd, pack_lockfiles,
+				     !packfile_uris.nr, sought, nr_sought))
 				die(_("git fetch-pack: fetch failed."));
 			do_check_stateless_delimiter(args, &reader);
 
@@ -1582,8 +1646,55 @@
 		}
 	}
 
+	for (i = 0; i < packfile_uris.nr; i++) {
+		struct child_process cmd = CHILD_PROCESS_INIT;
+		char packname[GIT_MAX_HEXSZ + 1];
+		const char *uri = packfile_uris.items[i].string +
+			the_hash_algo->hexsz + 1;
+
+		argv_array_push(&cmd.args, "http-fetch");
+		argv_array_pushf(&cmd.args, "--packfile=%.*s",
+				 (int) the_hash_algo->hexsz,
+				 packfile_uris.items[i].string);
+		argv_array_push(&cmd.args, uri);
+		cmd.git_cmd = 1;
+		cmd.no_stdin = 1;
+		cmd.out = -1;
+		if (start_command(&cmd))
+			die("fetch-pack: unable to spawn http-fetch");
+
+		if (read_in_full(cmd.out, packname, 5) < 0 ||
+		    memcmp(packname, "keep\t", 5))
+			die("fetch-pack: expected keep then TAB at start of http-fetch output");
+
+		if (read_in_full(cmd.out, packname,
+				 the_hash_algo->hexsz + 1) < 0 ||
+		    packname[the_hash_algo->hexsz] != '\n')
+			die("fetch-pack: expected hash then LF at end of http-fetch output");
+
+		packname[the_hash_algo->hexsz] = '\0';
+
+		close(cmd.out);
+
+		if (finish_command(&cmd))
+			die("fetch-pack: unable to finish http-fetch");
+
+		if (memcmp(packfile_uris.items[i].string, packname,
+			   the_hash_algo->hexsz))
+			die("fetch-pack: pack downloaded from %s does not match expected hash %.*s",
+			    uri, (int) the_hash_algo->hexsz,
+			    packfile_uris.items[i].string);
+
+		string_list_append_nodup(pack_lockfiles,
+					 xstrfmt("%s/pack/pack-%s.keep",
+						 get_object_directory(),
+						 packname));
+	}
+	string_list_clear(&packfile_uris, 0);
+
 	if (negotiator)
 		negotiator->release(negotiator);
+
 	oidset_clear(&common);
 	return ref;
 }
@@ -1620,6 +1731,14 @@
 	git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta);
 	git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
 	git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
+	if (!uri_protocols.nr) {
+		char *str;
+
+		if (!git_config_get_string("fetch.uriprotocols", &str) && str) {
+			string_list_split(&uri_protocols, str, ',', -1);
+			free(str);
+		}
+	}
 
 	git_config(fetch_pack_config_cb, NULL);
 }
@@ -1772,7 +1891,7 @@
 		       const struct ref *ref,
 		       struct ref **sought, int nr_sought,
 		       struct oid_array *shallow,
-		       char **pack_lockfile,
+		       struct string_list *pack_lockfiles,
 		       enum protocol_version version)
 {
 	struct ref *ref_cpy;
@@ -1807,11 +1926,11 @@
 		memset(&si, 0, sizeof(si));
 		ref_cpy = do_fetch_pack_v2(args, fd, ref, sought, nr_sought,
 					   &shallows_scratch, &si,
-					   pack_lockfile);
+					   pack_lockfiles);
 	} else {
 		prepare_shallow_info(&si, shallow);
 		ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
-					&si, pack_lockfile);
+					&si, pack_lockfiles);
 	}
 	reprepare_packed_git(the_repository);
 
diff --git a/fetch-pack.h b/fetch-pack.h
index 67f6842..85d1e39 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -83,7 +83,7 @@
 		       struct ref **sought,
 		       int nr_sought,
 		       struct oid_array *shallow,
-		       char **pack_lockfile,
+		       struct string_list *pack_lockfiles,
 		       enum protocol_version version);
 
 /*
diff --git a/fsmonitor.c b/fsmonitor.c
index 932bd90..ed796e3 100644
--- a/fsmonitor.c
+++ b/fsmonitor.c
@@ -217,7 +217,7 @@
 				 * Need to use a char * variable because static
 				 * analysis was suggesting to use strbuf_addbuf
 				 * but we don't want to copy the entire strbuf
-				 * only the the chars up to the first NUL
+				 * only the chars up to the first NUL
 				 */
 				buf = query_result.buf;
 				strbuf_addstr(&last_update_token, buf);
diff --git a/fuzz-commit-graph.c b/fuzz-commit-graph.c
index 9fd1c04..4308172 100644
--- a/fuzz-commit-graph.c
+++ b/fuzz-commit-graph.c
@@ -12,7 +12,7 @@
 	initialize_the_repository();
 	g = parse_commit_graph((void *)data, size);
 	repo_clear(the_repository);
-	free(g);
+	free_commit_graph(g);
 
 	return 0;
 }
diff --git a/git-bisect.sh b/git-bisect.sh
index 08a6ed5..f03fbb1 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -41,7 +41,7 @@
 
 bisect_head()
 {
-	if test -f "$GIT_DIR/BISECT_HEAD"
+	if git rev-parse --verify -q BISECT_HEAD > /dev/null
 	then
 		echo BISECT_HEAD
 	else
@@ -153,7 +153,7 @@
 	git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD $TERM_GOOD|| exit
 
 	# Perform all bisection computation, display and checkout
-	git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout)
+	git bisect--helper --next-all $(git rev-parse --verify -q BISECT_HEAD > /dev/null && echo --no-checkout)
 	res=$?
 
 	# Check if we should exit because bisection is finished
diff --git a/git-compat-util.h b/git-compat-util.h
index a73632e..5637114 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -869,6 +869,12 @@
 FILE *fopen_or_warn(const char *path, const char *mode);
 
 /*
+ * Like strncmp, but only return zero if s is NUL-terminated and exactly len
+ * characters long.  If it is not, consider it greater than t.
+ */
+int xstrncmpz(const char *s, const char *t, size_t len);
+
+/*
  * FREE_AND_NULL(ptr) is like free(ptr) followed by ptr = NULL. Note
  * that ptr is used twice, so don't pass e.g. ptr++.
  */
diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl
index fc00d59..6483d79 100755
--- a/git-cvsexportcommit.perl
+++ b/git-cvsexportcommit.perl
@@ -22,6 +22,10 @@
 my $repo = Git->repository();
 $opt_w = $repo->config('cvsexportcommit.cvsdir') unless defined $opt_w;
 
+my $tmpdir = File::Temp->newdir;
+my $hash_algo = $repo->config('extensions.objectformat') || 'sha1';
+my $hexsz = $hash_algo eq 'sha256' ? 64 : 40;
+
 if ($opt_w || $opt_W) {
 	# Remember where GIT_DIR is before changing to CVS checkout
 	unless ($ENV{GIT_DIR}) {
@@ -96,7 +100,7 @@
     }
 
     if ($stage eq 'headers') {
-	if ($line =~ m/^parent (\w{40})$/) { # found a parent
+	if ($line =~ m/^parent ([0-9a-f]{$hexsz})$/) { # found a parent
 	    push @parents, $1;
 	} elsif ($line =~ m/^author (.+) \d+ [-+]\d+$/) {
 	    $author = $1;
@@ -111,7 +115,7 @@
     }
 }
 
-my $noparent = "0000000000000000000000000000000000000000";
+my $noparent = "0" x $hexsz;
 if ($parent) {
     my $found;
     # double check that it's a valid parent
@@ -174,7 +178,7 @@
 print "Checking if patch will apply\n";
 
 my @stat;
-open APPLY, "GIT_DIR= git-apply $context --summary --numstat<.cvsexportcommit.diff|" || die "cannot patch";
+open APPLY, "GIT_INDEX_FILE=$tmpdir/index git-apply $context --summary --numstat<.cvsexportcommit.diff|" || die "cannot patch";
 @stat=<APPLY>;
 close APPLY || die "Cannot patch";
 my (@bfiles,@files,@afiles,@dfiles);
@@ -329,7 +333,7 @@
 if ($opt_W) {
     system("git checkout -q $commit^0") && die "cannot patch";
 } else {
-    `GIT_DIR= git-apply $context --summary --numstat --apply <.cvsexportcommit.diff` || die "cannot patch";
+    `GIT_INDEX_FILE=$tmpdir/index git-apply $context --summary --numstat --apply <.cvsexportcommit.diff` || die "cannot patch";
 }
 
 print "Patch applied successfully. Adding new files and directories to CVS\n";
@@ -407,7 +411,7 @@
 
 if ($opt_W) {
     system("git checkout $go_back_to") && die "cannot move back to $go_back_to";
-    if (!($go_back_to =~ /^[0-9a-fA-F]{40}$/)) {
+    if (!($go_back_to =~ /^[0-9a-fA-F]{$hexsz}$/)) {
 	system("git symbolic-ref HEAD $go_back_to") &&
 	    die "cannot move back to $go_back_to";
     }
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index 1057f38..7bf3c12 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -637,9 +637,9 @@
 	return $pwd;
 }
 
-sub is_sha1 {
+sub is_oid {
 	my $s = shift;
-	return $s =~ /^[a-f0-9]{40}$/;
+	return $s =~ /^[a-f0-9]{40}(?:[a-f0-9]{24})?$/;
 }
 
 sub get_headref ($) {
@@ -810,7 +810,7 @@
 	open(my $fh, '-|', qw(git write-tree))
 		or die "unable to open git write-tree: $!";
 	chomp(my $tree = <$fh>);
-	is_sha1($tree)
+	is_oid($tree)
 		or die "Cannot get tree id ($tree): $!";
 	close($fh)
 		or die "Error running git write-tree: $?\n";
@@ -896,7 +896,7 @@
 
 	print "Committed patch $patchset ($branch $commit_date)\n" if $opt_v;
 	chomp(my $cid = <$commit_read>);
-	is_sha1($cid) or die "Cannot get commit id ($cid): $!\n";
+	is_oid($cid) or die "Cannot get commit id ($cid): $!\n";
 	print "Commit ID $cid\n" if $opt_v;
 	close($commit_read);
 
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index ae10442..f6f3fc1 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -365,7 +365,7 @@
     }
     foreach my $line ( @gitvars )
     {
-        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
+        next unless ( $line =~ /^(gitcvs|extensions)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
         unless ($2) {
             $cfg->{$1}{$3} = $4;
         } else {
@@ -392,6 +392,9 @@
         $log->nofile();
     }
 
+    $state->{rawsz} = ($cfg->{'extensions'}{'objectformat'} || 'sha1') eq 'sha256' ? 32 : 20;
+    $state->{hexsz} = $state->{rawsz} * 2;
+
     return 1;
 }
 
@@ -1581,7 +1584,7 @@
 
             $parenthash = safe_pipe_capture('git', 'show-ref', '-s', $branchRef);
             chomp $parenthash;
-            if ($parenthash !~ /^[0-9a-f]{40}$/)
+            if ($parenthash !~ /^[0-9a-f]{$state->{hexsz}}$/)
             {
                 if ( defined($stickyInfo) && defined($stickyInfo->{tag}) )
                 {
@@ -1708,7 +1711,7 @@
     chomp($commithash);
     $log->info("Commit hash : $commithash");
 
-    unless ( $commithash =~ /[a-zA-Z0-9]{40}/ )
+    unless ( $commithash =~ /[a-zA-Z0-9]{$state->{hexsz}}/ )
     {
         $log->warn("Commit failed (Invalid commit hash)");
         print "error 1 Commit failed (unknown reason)\n";
@@ -2375,7 +2378,7 @@
         print "E ***************\n";
         while ( <ANNOTATE> )
         {
-            if (m/^([a-zA-Z0-9]{40})\t\([^\)]*\)(.*)$/i)
+            if (m/^([a-zA-Z0-9]{$state->{hexsz}})\t\([^\)]*\)(.*)$/i)
             {
                 my $commithash = $1;
                 my $data = $2;
@@ -2852,7 +2855,7 @@
         return;
     }
 
-    die "Need filehash" unless ( defined ( $filehash ) and $filehash =~ /^[a-zA-Z0-9]{40}$/ );
+    die "Need filehash" unless ( defined ( $filehash ) and $filehash =~ /^[a-zA-Z0-9]{$state->{hexsz}}$/ );
 
     my $type = safe_pipe_capture('git', 'cat-file', '-t', $filehash);
     chomp $type;
@@ -3042,7 +3045,7 @@
 
     my $ver = safe_pipe_capture('git', 'show-ref', '-s', "refs/heads/$state->{module}");
     chomp $ver;
-    if ($ver !~ /^[0-9a-f]{40}$/)
+    if ($ver !~ /^[0-9a-f]{$state->{hexsz}}$/)
     {
         $log->warn("Error from git show-ref -s refs/head$state->{module}");
         print "error 1 cannot find the current HEAD of module";
@@ -3281,7 +3284,7 @@
     }
     elsif( $srcType eq "sha1" )
     {
-        unless ( defined ( $name ) and $name =~ /^[a-zA-Z0-9]{40}$/ )
+        unless ( defined ( $name ) and $name =~ /^[a-zA-Z0-9]{$state->{hexsz}}$/ )
         {
             $log->warn("Need filehash");
             die "Need filehash\n";
@@ -3817,7 +3820,7 @@
     chomp $commitsha1;
 
     my $commitinfo = ::safe_pipe_capture('git', 'cat-file', 'commit', $self->{module});
-    unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{40}/ )
+    unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{$state->{hexsz}}/ )
     {
         die("Invalid module '$self->{module}'");
     }
@@ -3957,7 +3960,7 @@
             while ( <FILELIST> )
             {
 		chomp;
-                unless ( /^:\d{6}\s+([0-7]{6})\s+[a-f0-9]{40}\s+([a-f0-9]{40})\s+(\w)$/o )
+                unless ( /^:\d{6}\s+([0-7]{6})\s+[a-f0-9]{$state->{hexsz}}\s+([a-f0-9]{$state->{hexsz}})\s+(\w)$/o )
                 {
                     die("Couldn't process git-diff-tree line : $_");
                 }
@@ -4625,11 +4628,11 @@
             $db_query->execute($filename, $intRev);
             $meta = $db_query->fetchrow_hashref;
         }
-        elsif ( $revision =~ /^2\.1\.1\.2000(\.[1-3][0-9][0-9]){20}$/ )
+        elsif ( $revision =~ /^2\.1\.1\.2000(\.[1-3][0-9][0-9]){$state->{rawsz}}$/ )
         {
             my ($commitHash)=($revision=~/^2\.1\.1\.2000(.*)$/);
             $commitHash=~s/\.([0-9]+)/sprintf("%02x",$1-100)/eg;
-            if($commitHash=~/^[0-9a-f]{40}$/)
+            if($commitHash=~/^[0-9a-f]{$state->{hexsz}}$/)
             {
                 return $self->getMetaFromCommithash($filename,$commitHash);
             }
@@ -4639,7 +4642,7 @@
             $log->warning("failed get $revision with commithash=$commitHash");
             undef $revision;
         }
-        elsif ( $revision =~ /^[0-9a-f]{40}$/ )
+        elsif ( $revision =~ /^[0-9a-f]{$state->{hexsz}}$/ )
         {
             # Try DB first.  This is mostly only useful for req_annotate(),
             # which only calls this for stuff that should already be in
@@ -4658,7 +4661,7 @@
             if(! $meta)
             {
                 my($revCommit)=$self->lookupCommitRef($revision);
-                if($revCommit=~/^[0-9a-f]{40}$/)
+                if($revCommit=~/^[0-9a-f]{$state->{hexsz}}$/)
                 {
                     return $self->getMetaFromCommithash($filename,$revCommit);
                 }
@@ -4672,7 +4675,7 @@
         else
         {
             my($revCommit)=$self->lookupCommitRef($revision);
-            if($revCommit=~/^[0-9a-f]{40}$/)
+            if($revCommit=~/^[0-9a-f]{$state->{hexsz}}$/)
             {
                 return $self->getMetaFromCommithash($filename,$revCommit);
             }
@@ -4767,7 +4770,7 @@
 
     my($fileHash) = ::safe_pipe_capture("git","rev-parse","$revCommit:$filename");
     chomp $fileHash;
-    if(!($fileHash=~/^[0-9a-f]{40}$/))
+    if(!($fileHash=~/^[0-9a-f]{$state->{hexsz}}$/))
     {
         die "Invalid fileHash '$fileHash' looking up"
                     ." '$revCommit:$filename'\n";
@@ -4863,7 +4866,7 @@
     $commitHash = ::safe_pipe_capture("git","rev-parse","--verify","--quiet",
 				      $self->unescapeRefName($ref));
     $commitHash=~s/\s*$//;
-    if(!($commitHash=~/^[0-9a-f]{40}$/))
+    if(!($commitHash=~/^[0-9a-f]{$state->{hexsz}}$/))
     {
         $commitHash=undef;
     }
@@ -4909,7 +4912,7 @@
     my $commithash = shift;
     my $tablename = $self->tablename("commitmsgs");
 
-    die("Need commithash") unless ( defined($commithash) and $commithash =~ /^[a-zA-Z0-9]{40}$/ );
+    die("Need commithash") unless ( defined($commithash) and $commithash =~ /^[a-zA-Z0-9]{$state->{hexsz}}$/ );
 
     my $db_query;
     $db_query = $self->{dbh}->prepare_cached("SELECT value FROM $tablename WHERE key=?",{},1);
diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl
index e54f3e6..af1fee7 100644
--- a/git-gui/lib/choose_repository.tcl
+++ b/git-gui/lib/choose_repository.tcl
@@ -357,31 +357,10 @@
 	if {$outdir_var ne ""} {
 		upvar 1 $outdir_var outdir
 	}
-	if {[file isfile $path]} {
-		set fp [open $path r]
-		gets $fp line
-		close $fp
-		if {[regexp "^gitdir: (.+)$" $line line link_target]} {
-			set path [file join [file dirname $path] $link_target]
-			set path [file normalize $path]
-		}
+	if {[catch {set outdir [git rev-parse --resolve-git-dir $path]}]} {
+		return 0
 	}
-
-	if {[file exists [file join $path HEAD]]
-	 && [file exists [file join $path objects]]
-	 && [file exists [file join $path config]]} {
-		set outdir $path
-		return 1
-	}
-	if {[is_Cygwin]} {
-		if {[file exists [file join $path HEAD]]
-		 && [file exists [file join $path objects.lnk]]
-		 && [file exists [file join $path config.lnk]]} {
-			set outdir $path
-			return 1
-		}
-	}
-	return 0
+	return 1
 }
 
 proc _objdir {path} {
diff --git a/git-send-email.perl b/git-send-email.perl
index dc95656..36c47ba 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1699,10 +1699,14 @@
 				$xfer_encoding = $1 if not defined $xfer_encoding;
 			}
 			elsif (/^In-Reply-To: (.*)/i) {
-				$in_reply_to = $1;
+				if (!$initial_in_reply_to || $thread) {
+					$in_reply_to = $1;
+				}
 			}
 			elsif (/^References: (.*)/i) {
-				$references = $1;
+				if (!$initial_in_reply_to || $thread) {
+					$references = $1;
+				}
 			}
 			elsif (!/^Date:\s/i && /^[-A-Za-z]+:\s+\S/) {
 				push @xh, $_;
diff --git a/git-submodule.sh b/git-submodule.sh
index 39ebdf2..43eb605 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -719,7 +719,7 @@
 # $@ = requested path
 #
 cmd_set_branch() {
-	unset_branch=false
+	default=
 	branch=
 
 	while test $# -ne 0
@@ -729,7 +729,7 @@
 			# we don't do anything with this but we need to accept it
 			;;
 		-d|--default)
-			unset_branch=true
+			default=1
 			;;
 		-b|--branch)
 			case "$2" in '') usage ;; esac
@@ -750,33 +750,7 @@
 		shift
 	done
 
-	if test $# -ne 1
-	then
-		usage
-	fi
-
-	# we can't use `git submodule--helper name` here because internally, it
-	# hashes the path so a trailing slash could lead to an unintentional no match
-	name="$(git submodule--helper list "$1" | cut -f2)"
-	if test -z "$name"
-	then
-		exit 1
-	fi
-
-	test -n "$branch"; has_branch=$?
-	test "$unset_branch" = true; has_unset_branch=$?
-
-	if test $((!$has_branch != !$has_unset_branch)) -eq 0
-	then
-		usage
-	fi
-
-	if test $has_branch -eq 0
-	then
-		git submodule--helper config submodule."$name".branch "$branch"
-	else
-		git submodule--helper config --unset submodule."$name".branch
-	fi
+	git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper set-branch ${GIT_QUIET:+--quiet} ${branch:+--branch "$branch"} ${default:+--default} -- "$@"
 }
 
 #
diff --git a/git-svn.perl b/git-svn.perl
index 4aa208f..58f5a7a 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -5,7 +5,8 @@
 use warnings;
 use strict;
 use vars qw/	$AUTHOR $VERSION
-		$sha1 $sha1_short $_revision $_repository
+		$oid $oid_short $oid_length
+		$_revision $_repository
 		$_q $_authors $_authors_prog %users/;
 $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
 $VERSION = '@@GIT_VERSION@@';
@@ -103,8 +104,9 @@
 	}
 }
 
-$sha1 = qr/[a-f\d]{40}/;
-$sha1_short = qr/[a-f\d]{4,40}/;
+$oid = qr/(?:[a-f\d]{40}(?:[a-f\d]{24})?)/;
+$oid_short = qr/[a-f\d]{4,64}/;
+$oid_length = 40;
 my ($_stdin, $_help, $_edit,
 	$_message, $_file, $_branch_dest,
 	$_template, $_shared,
@@ -498,6 +500,7 @@
 		command_noisy('config', "$pfx.preserve-empty-dirs", 'true');
 		command_noisy('config', "$pfx.placeholder-filename", $$fname);
 	}
+	load_object_format();
 }
 
 sub init_subdir {
@@ -582,7 +585,7 @@
 		print "Reading from stdin...\n";
 		@commits = ();
 		while (<STDIN>) {
-			if (/\b($sha1_short)\b/o) {
+			if (/\b($oid_short)\b/o) {
 				unshift @commits, $1;
 			}
 		}
@@ -1831,7 +1834,7 @@
 	if ($type eq 'commit') {
 		$expected = (grep /^tree /, command(qw/cat-file commit/,
 		                                    $treeish))[0];
-		($expected) = ($expected =~ /^tree ($sha1)$/o);
+		($expected) = ($expected =~ /^tree ($oid)$/o);
 		die "Unable to get tree from $treeish\n" unless $expected;
 	} elsif ($type eq 'tree') {
 		$expected = $treeish;
@@ -1975,9 +1978,15 @@
 			}
 		}
 	}
+	load_object_format();
 	delete @$opts{@config_only} if @config_only;
 }
 
+sub load_object_format {
+	chomp(my $hash = `git config --get extensions.objectformat`);
+	$::oid_length = 64 if $hash eq 'sha256';
+}
+
 sub extract_metadata {
 	my $id = shift or return (undef, undef, undef);
 	my ($url, $rev, $uuid) = ($id =~ /^\s*git-svn-id:\s+(.*)\@(\d+)
@@ -2006,10 +2015,10 @@
 		print $out $sha, "\n";
 
 		while (my $line = <$in>) {
-			if ($first && $line =~ /^[[:xdigit:]]{40}\smissing$/) {
+			if ($first && $line =~ /^$::oid\smissing$/) {
 				last;
 			} elsif ($first &&
-			       $line =~ /^[[:xdigit:]]{40}\scommit\s(\d+)$/) {
+			       $line =~ /^$::oid\scommit\s(\d+)$/) {
 				$first = 0;
 				$size = $1;
 				next;
@@ -2036,7 +2045,7 @@
 	my $hash;
 	my %max;
 	while (<$fh>) {
-		if ( m{^commit ($::sha1)$} ) {
+		if ( m{^commit ($::oid)$} ) {
 			unshift @$refs, $hash if $hash and $refs;
 			$hash = $1;
 			next;
diff --git a/git.c b/git.c
index a2d337e..6cd887b 100644
--- a/git.c
+++ b/git.c
@@ -346,6 +346,8 @@
 			commit_pager_choice();
 
 			child.use_shell = 1;
+			child.clean_on_exit = 1;
+			child.wait_after_clean = 1;
 			child.trace2_child_class = "shell_alias";
 			argv_array_push(&child.args, alias_string + 1);
 			argv_array_pushv(&child.args, (*argv) + 1);
@@ -574,7 +576,7 @@
 	{ "shortlog", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },
 	{ "show", cmd_show, RUN_SETUP },
 	{ "show-branch", cmd_show_branch, RUN_SETUP },
-	{ "show-index", cmd_show_index },
+	{ "show-index", cmd_show_index, RUN_SETUP_GENTLY },
 	{ "show-ref", cmd_show_ref, RUN_SETUP },
 	{ "sparse-checkout", cmd_sparse_checkout, RUN_SETUP | NEED_WORK_TREE },
 	{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
@@ -767,7 +769,7 @@
 			 * OK to return. Otherwise, we just pass along the status code.
 			 */
 			i = run_command_v_opt_tr2(args.argv, RUN_SILENT_EXEC_FAILURE |
-						  RUN_CLEAN_ON_EXIT, "git_alias");
+						  RUN_CLEAN_ON_EXIT | RUN_WAIT_AFTER_CLEAN, "git_alias");
 			if (i >= 0 || errno != ENOENT)
 				exit(i);
 			die("could not execute builtin %s", **argv);
diff --git a/grep.c b/grep.c
index 13232a9..54af9f8 100644
--- a/grep.c
+++ b/grep.c
@@ -1817,7 +1817,7 @@
 		 * We might set up the shared textconv cache data here, which
 		 * is not thread-safe. Also, get_oid_with_context() and
 		 * parse_object() might be internally called. As they are not
-		 * currenty thread-safe and might be racy with object reading,
+		 * currently thread-safe and might be racy with object reading,
 		 * obj_read_lock() must be called.
 		 */
 		grep_attr_lock();
diff --git a/hashmap.h b/hashmap.h
index 79ae9f8..ef220de 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -168,7 +168,7 @@
  * argument `keydata`, respectively. Otherwise, `keydata` is NULL.
  *
  * When it is too expensive to allocate a user entry (either because it is
- * large or varialbe sized, such that it is not on the stack), then the
+ * large or variable sized, such that it is not on the stack), then the
  * relevant data to check for equality should be passed via `keydata`.
  * In this case `key` can be a stripped down version of the user key data
  * or even just a hashmap_entry having the correct hash.
diff --git a/http-fetch.c b/http-fetch.c
index a32ac11..1df376e 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -5,59 +5,24 @@
 #include "walker.h"
 
 static const char http_fetch_usage[] = "git http-fetch "
-"[-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url";
+"[-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin | --packfile=hash | commit-id] url";
 
-int cmd_main(int argc, const char **argv)
+static int fetch_using_walker(const char *raw_url, int get_verbosely,
+			      int get_recover, int commits, char **commit_id,
+			      const char **write_ref, int commits_on_stdin)
 {
-	struct walker *walker;
-	int commits_on_stdin = 0;
-	int commits;
-	const char **write_ref = NULL;
-	char **commit_id;
 	char *url = NULL;
-	int arg = 1;
-	int rc = 0;
-	int get_verbosely = 0;
-	int get_recover = 0;
+	struct walker *walker;
+	int rc;
 
-	while (arg < argc && argv[arg][0] == '-') {
-		if (argv[arg][1] == 't') {
-		} else if (argv[arg][1] == 'c') {
-		} else if (argv[arg][1] == 'a') {
-		} else if (argv[arg][1] == 'v') {
-			get_verbosely = 1;
-		} else if (argv[arg][1] == 'w') {
-			write_ref = &argv[arg + 1];
-			arg++;
-		} else if (argv[arg][1] == 'h') {
-			usage(http_fetch_usage);
-		} else if (!strcmp(argv[arg], "--recover")) {
-			get_recover = 1;
-		} else if (!strcmp(argv[arg], "--stdin")) {
-			commits_on_stdin = 1;
-		}
-		arg++;
-	}
-	if (argc != arg + 2 - commits_on_stdin)
-		usage(http_fetch_usage);
-	if (commits_on_stdin) {
-		commits = walker_targets_stdin(&commit_id, &write_ref);
-	} else {
-		commit_id = (char **) &argv[arg++];
-		commits = 1;
-	}
-
-	if (argv[arg])
-		str_end_url_with_slash(argv[arg], &url);
-
-	setup_git_directory();
-
-	git_config(git_default_config, NULL);
+	str_end_url_with_slash(raw_url, &url);
 
 	http_init(NULL, url, 0);
+
 	walker = get_http_walker(url);
 	walker->get_verbosely = get_verbosely;
 	walker->get_recover = get_recover;
+	walker->get_progress = 0;
 
 	rc = walker_fetch(walker, commits, commit_id, write_ref, url);
 
@@ -73,8 +38,99 @@
 
 	walker_free(walker);
 	http_cleanup();
-
 	free(url);
 
 	return rc;
 }
+
+static void fetch_single_packfile(struct object_id *packfile_hash,
+				  const char *url) {
+	struct http_pack_request *preq;
+	struct slot_results results;
+	int ret;
+
+	http_init(NULL, url, 0);
+
+	preq = new_direct_http_pack_request(packfile_hash->hash, xstrdup(url));
+	if (preq == NULL)
+		die("couldn't create http pack request");
+	preq->slot->results = &results;
+	preq->generate_keep = 1;
+
+	if (start_active_slot(preq->slot)) {
+		run_active_slot(preq->slot);
+		if (results.curl_result != CURLE_OK) {
+			die("Unable to get pack file %s\n%s", preq->url,
+			    curl_errorstr);
+		}
+	} else {
+		die("Unable to start request");
+	}
+
+	if ((ret = finish_http_pack_request(preq)))
+		die("finish_http_pack_request gave result %d", ret);
+
+	release_http_pack_request(preq);
+	http_cleanup();
+}
+
+int cmd_main(int argc, const char **argv)
+{
+	int commits_on_stdin = 0;
+	int commits;
+	const char **write_ref = NULL;
+	char **commit_id;
+	int arg = 1;
+	int get_verbosely = 0;
+	int get_recover = 0;
+	int packfile = 0;
+	struct object_id packfile_hash;
+
+	while (arg < argc && argv[arg][0] == '-') {
+		const char *p;
+
+		if (argv[arg][1] == 't') {
+		} else if (argv[arg][1] == 'c') {
+		} else if (argv[arg][1] == 'a') {
+		} else if (argv[arg][1] == 'v') {
+			get_verbosely = 1;
+		} else if (argv[arg][1] == 'w') {
+			write_ref = &argv[arg + 1];
+			arg++;
+		} else if (argv[arg][1] == 'h') {
+			usage(http_fetch_usage);
+		} else if (!strcmp(argv[arg], "--recover")) {
+			get_recover = 1;
+		} else if (!strcmp(argv[arg], "--stdin")) {
+			commits_on_stdin = 1;
+		} else if (skip_prefix(argv[arg], "--packfile=", &p)) {
+			const char *end;
+
+			packfile = 1;
+			if (parse_oid_hex(p, &packfile_hash, &end) || *end)
+				die(_("argument to --packfile must be a valid hash (got '%s')"), p);
+		}
+		arg++;
+	}
+	if (argc != arg + 2 - (commits_on_stdin || packfile))
+		usage(http_fetch_usage);
+
+	setup_git_directory();
+
+	git_config(git_default_config, NULL);
+
+	if (packfile) {
+		fetch_single_packfile(&packfile_hash, argv[arg]);
+		return 0;
+	}
+
+	if (commits_on_stdin) {
+		commits = walker_targets_stdin(&commit_id, &write_ref);
+	} else {
+		commit_id = (char **) &argv[arg++];
+		commits = 1;
+	}
+	return fetch_using_walker(argv[arg], get_verbosely, get_recover,
+				  commits, commit_id, write_ref,
+				  commits_on_stdin);
+}
diff --git a/http-push.c b/http-push.c
index 822f326..1ff1883 100644
--- a/http-push.c
+++ b/http-push.c
@@ -70,10 +70,10 @@
 #define LOCK_REFRESH 30
 
 /* Remember to update object flag allocation in object.h */
-#define LOCAL    (1u<<16)
-#define REMOTE   (1u<<17)
-#define FETCHING (1u<<18)
-#define PUSHING  (1u<<19)
+#define LOCAL    (1u<<11)
+#define REMOTE   (1u<<12)
+#define FETCHING (1u<<13)
+#define PUSHING  (1u<<14)
 
 /* We allow "recursive" symbolic refs. Only within reason, though */
 #define MAXDEPTH 5
@@ -117,6 +117,7 @@
 
 struct transfer_request {
 	struct object *obj;
+	struct packed_git *target;
 	char *url;
 	char *dest;
 	struct remote_lock *lock;
@@ -314,17 +315,18 @@
 		release_request(request);
 		return;
 	}
+	close_pack_index(target);
+	request->target = target;
 
 	fprintf(stderr,	"Fetching pack %s\n",
 		hash_to_hex(target->hash));
 	fprintf(stderr, " which contains %s\n", oid_to_hex(&request->obj->oid));
 
-	preq = new_http_pack_request(target, repo->url);
+	preq = new_http_pack_request(target->hash, repo->url);
 	if (preq == NULL) {
 		repo->can_update_info_refs = 0;
 		return;
 	}
-	preq->lst = &repo->packs;
 
 	/* Make sure there isn't another open request for this pack */
 	while (check_request) {
@@ -597,6 +599,8 @@
 		}
 		if (fail)
 			repo->can_update_info_refs = 0;
+		else
+			http_install_packfile(request->target, &repo->packs);
 		release_request(request);
 	}
 }
diff --git a/http-walker.c b/http-walker.c
index fe15e32..4fb1235 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -439,6 +439,7 @@
 	target = find_sha1_pack(sha1, repo->packs);
 	if (!target)
 		return -1;
+	close_pack_index(target);
 
 	if (walker->get_verbosely) {
 		fprintf(stderr, "Getting pack %s\n",
@@ -447,10 +448,9 @@
 			hash_to_hex(sha1));
 	}
 
-	preq = new_http_pack_request(target, repo->base);
+	preq = new_http_pack_request(target->hash, repo->base);
 	if (preq == NULL)
 		goto abort;
-	preq->lst = &repo->packs;
 	preq->slot->results = &results;
 
 	if (start_active_slot(preq->slot)) {
@@ -469,6 +469,7 @@
 	release_http_pack_request(preq);
 	if (ret)
 		return ret;
+	http_install_packfile(target, &repo->packs);
 
 	return 0;
 
diff --git a/http.c b/http.c
index 4882c9f..3b12843 100644
--- a/http.c
+++ b/http.c
@@ -18,7 +18,7 @@
 
 static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
 static int trace_curl_data = 1;
-static struct string_list cookies_to_redact = STRING_LIST_INIT_DUP;
+static int trace_curl_redact = 1;
 #if LIBCURL_VERSION_NUM >= 0x070a08
 long int git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
 #else
@@ -642,8 +642,9 @@
 {
 	const char *sensitive_header;
 
-	if (skip_prefix(header->buf, "Authorization:", &sensitive_header) ||
-	    skip_prefix(header->buf, "Proxy-Authorization:", &sensitive_header)) {
+	if (trace_curl_redact &&
+	    (skip_prefix(header->buf, "Authorization:", &sensitive_header) ||
+	     skip_prefix(header->buf, "Proxy-Authorization:", &sensitive_header))) {
 		/* The first token is the type, which is OK to log */
 		while (isspace(*sensitive_header))
 			sensitive_header++;
@@ -652,20 +653,15 @@
 		/* Everything else is opaque and possibly sensitive */
 		strbuf_setlen(header,  sensitive_header - header->buf);
 		strbuf_addstr(header, " <redacted>");
-	} else if (cookies_to_redact.nr &&
+	} else if (trace_curl_redact &&
 		   skip_prefix(header->buf, "Cookie:", &sensitive_header)) {
 		struct strbuf redacted_header = STRBUF_INIT;
-		char *cookie;
+		const char *cookie;
 
 		while (isspace(*sensitive_header))
 			sensitive_header++;
 
-		/*
-		 * The contents of header starting from sensitive_header will
-		 * subsequently be overridden, so it is fine to mutate this
-		 * string (hence the assignment to "char *").
-		 */
-		cookie = (char *) sensitive_header;
+		cookie = sensitive_header;
 
 		while (cookie) {
 			char *equals;
@@ -678,14 +674,8 @@
 				strbuf_addstr(&redacted_header, cookie);
 				continue;
 			}
-			*equals = 0; /* temporarily set to NUL for lookup */
-			if (string_list_lookup(&cookies_to_redact, cookie)) {
-				strbuf_addstr(&redacted_header, cookie);
-				strbuf_addstr(&redacted_header, "=<redacted>");
-			} else {
-				*equals = '=';
-				strbuf_addstr(&redacted_header, cookie);
-			}
+			strbuf_add(&redacted_header, cookie, equals - cookie);
+			strbuf_addstr(&redacted_header, "=<redacted>");
 			if (semicolon) {
 				/*
 				 * There are more cookies. (Or, for some
@@ -1003,11 +993,8 @@
 	setup_curl_trace(result);
 	if (getenv("GIT_TRACE_CURL_NO_DATA"))
 		trace_curl_data = 0;
-	if (getenv("GIT_REDACT_COOKIES")) {
-		string_list_split(&cookies_to_redact,
-				  getenv("GIT_REDACT_COOKIES"), ',', -1);
-		string_list_sort(&cookies_to_redact);
-	}
+	if (!git_env_bool("GIT_TRACE_REDACT", 1))
+		trace_curl_redact = 0;
 
 	curl_easy_setopt(result, CURLOPT_USERAGENT,
 		user_agent ? user_agent : git_user_agent());
@@ -2274,70 +2261,74 @@
 
 int finish_http_pack_request(struct http_pack_request *preq)
 {
-	struct packed_git **lst;
-	struct packed_git *p = preq->target;
-	char *tmp_idx;
-	size_t len;
 	struct child_process ip = CHILD_PROCESS_INIT;
-
-	close_pack_index(p);
+	int tmpfile_fd;
+	int ret = 0;
 
 	fclose(preq->packfile);
 	preq->packfile = NULL;
 
-	lst = preq->lst;
+	tmpfile_fd = xopen(preq->tmpfile.buf, O_RDONLY);
+
+	argv_array_push(&ip.args, "index-pack");
+	argv_array_push(&ip.args, "--stdin");
+	ip.git_cmd = 1;
+	ip.in = tmpfile_fd;
+	if (preq->generate_keep) {
+		argv_array_pushf(&ip.args, "--keep=git %"PRIuMAX,
+				 (uintmax_t)getpid());
+		ip.out = 0;
+	} else {
+		ip.no_stdout = 1;
+	}
+
+	if (run_command(&ip)) {
+		ret = -1;
+		goto cleanup;
+	}
+
+cleanup:
+	close(tmpfile_fd);
+	unlink(preq->tmpfile.buf);
+	return ret;
+}
+
+void http_install_packfile(struct packed_git *p,
+			   struct packed_git **list_to_remove_from)
+{
+	struct packed_git **lst = list_to_remove_from;
+
 	while (*lst != p)
 		lst = &((*lst)->next);
 	*lst = (*lst)->next;
 
-	if (!strip_suffix(preq->tmpfile.buf, ".pack.temp", &len))
-		BUG("pack tmpfile does not end in .pack.temp?");
-	tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile.buf);
-
-	argv_array_push(&ip.args, "index-pack");
-	argv_array_pushl(&ip.args, "-o", tmp_idx, NULL);
-	argv_array_push(&ip.args, preq->tmpfile.buf);
-	ip.git_cmd = 1;
-	ip.no_stdin = 1;
-	ip.no_stdout = 1;
-
-	if (run_command(&ip)) {
-		unlink(preq->tmpfile.buf);
-		unlink(tmp_idx);
-		free(tmp_idx);
-		return -1;
-	}
-
-	unlink(sha1_pack_index_name(p->hash));
-
-	if (finalize_object_file(preq->tmpfile.buf, sha1_pack_name(p->hash))
-	 || finalize_object_file(tmp_idx, sha1_pack_index_name(p->hash))) {
-		free(tmp_idx);
-		return -1;
-	}
-
 	install_packed_git(the_repository, p);
-	free(tmp_idx);
-	return 0;
 }
 
 struct http_pack_request *new_http_pack_request(
-	struct packed_git *target, const char *base_url)
+	const unsigned char *packed_git_hash, const char *base_url) {
+
+	struct strbuf buf = STRBUF_INIT;
+
+	end_url_with_slash(&buf, base_url);
+	strbuf_addf(&buf, "objects/pack/pack-%s.pack",
+		hash_to_hex(packed_git_hash));
+	return new_direct_http_pack_request(packed_git_hash,
+					    strbuf_detach(&buf, NULL));
+}
+
+struct http_pack_request *new_direct_http_pack_request(
+	const unsigned char *packed_git_hash, char *url)
 {
 	off_t prev_posn = 0;
-	struct strbuf buf = STRBUF_INIT;
 	struct http_pack_request *preq;
 
 	preq = xcalloc(1, sizeof(*preq));
 	strbuf_init(&preq->tmpfile, 0);
-	preq->target = target;
 
-	end_url_with_slash(&buf, base_url);
-	strbuf_addf(&buf, "objects/pack/pack-%s.pack",
-		hash_to_hex(target->hash));
-	preq->url = strbuf_detach(&buf, NULL);
+	preq->url = url;
 
-	strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(target->hash));
+	strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(packed_git_hash));
 	preq->packfile = fopen(preq->tmpfile.buf, "a");
 	if (!preq->packfile) {
 		error("Unable to open local file %s for pack",
@@ -2361,7 +2352,7 @@
 		if (http_is_verbose)
 			fprintf(stderr,
 				"Resuming fetch of pack %s at byte %"PRIuMAX"\n",
-				hash_to_hex(target->hash),
+				hash_to_hex(packed_git_hash),
 				(uintmax_t)prev_posn);
 		http_opt_request_remainder(preq->slot->curl, prev_posn);
 	}
diff --git a/http.h b/http.h
index faf8cbb..5de792e 100644
--- a/http.h
+++ b/http.h
@@ -216,18 +216,36 @@
 
 struct http_pack_request {
 	char *url;
-	struct packed_git *target;
-	struct packed_git **lst;
+
+	/*
+	 * If this is true, finish_http_pack_request() will pass "--keep" to
+	 * index-pack, resulting in the creation of a keep file, and will not
+	 * suppress its stdout (that is, the "keep\t<hash>\n" line will be
+	 * printed to stdout).
+	 */
+	unsigned generate_keep : 1;
+
 	FILE *packfile;
 	struct strbuf tmpfile;
 	struct active_request_slot *slot;
 };
 
 struct http_pack_request *new_http_pack_request(
-	struct packed_git *target, const char *base_url);
+	const unsigned char *packed_git_hash, const char *base_url);
+struct http_pack_request *new_direct_http_pack_request(
+	const unsigned char *packed_git_hash, char *url);
 int finish_http_pack_request(struct http_pack_request *preq);
 void release_http_pack_request(struct http_pack_request *preq);
 
+/*
+ * Remove p from the given list, and invoke install_packed_git() on it.
+ *
+ * This is a convenience function for users that have obtained a list of packs
+ * from http_get_info_packs() and have chosen a specific pack to fetch.
+ */
+void http_install_packfile(struct packed_git *p,
+			   struct packed_git **list_to_remove_from);
+
 /* Helpers for fetching object */
 struct http_object_request {
 	char *url;
diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 256bcfb..3553ad7 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -326,7 +326,8 @@
 
 	/* Check if it is already registered */
 	if (!promisor_remote_find(remote)) {
-		git_config_set("core.repositoryformatversion", "1");
+		if (upgrade_repository_format(1) < 0)
+			die(_("unable to upgrade repository format to support partial clone"));
 
 		/* Add promisor config for the remote */
 		cfg_name = xstrfmt("remote.%s.promisor", remote);
diff --git a/object-store.h b/object-store.h
index d1e490f..f439d47 100644
--- a/object-store.h
+++ b/object-store.h
@@ -70,6 +70,7 @@
 	size_t index_size;
 	uint32_t num_objects;
 	uint32_t num_bad_objects;
+	uint32_t crc_offset;
 	unsigned char *bad_object_sha1;
 	int index_version;
 	time_t mtime;
diff --git a/object.c b/object.c
index 794c866..3257518 100644
--- a/object.c
+++ b/object.c
@@ -157,13 +157,13 @@
 	return obj;
 }
 
-void *object_as_type(struct repository *r, struct object *obj, enum object_type type, int quiet)
+void *object_as_type(struct object *obj, enum object_type type, int quiet)
 {
 	if (obj->type == type)
 		return obj;
 	else if (obj->type == OBJ_NONE) {
 		if (type == OBJ_COMMIT)
-			init_commit_node(r, (struct commit *) obj);
+			init_commit_node((struct commit *) obj);
 		else
 			obj->type = type;
 		return obj;
diff --git a/object.h b/object.h
index b22328b..96a2105 100644
--- a/object.h
+++ b/object.h
@@ -15,7 +15,6 @@
 	struct alloc_state *commit_state;
 	struct alloc_state *tag_state;
 	struct alloc_state *object_state;
-	unsigned commit_count;
 
 	/* parent substitutions from .git/info/grafts and .git/shallow */
 	struct commit_graft **grafts;
@@ -26,6 +25,7 @@
 	char *alternate_shallow_file;
 
 	int commit_graft_prepared;
+	int substituted_parent;
 
 	struct buffer_slab *buffer_slab;
 };
@@ -59,7 +59,7 @@
 
 /*
  * object flag allocation:
- * revision.h:               0---------10         15                   25----28
+ * revision.h:               0---------10         15             23------26
  * fetch-pack.c:             01
  * negotiator/default.c:       2--5
  * walker.c:                 0-2
@@ -67,7 +67,7 @@
  * builtin/blame.c:                        12-13
  * bisect.c:                                        16
  * bundle.c:                                        16
- * http-push.c:                                     16-----19
+ * http-push.c:                          11-----14
  * commit-graph.c:                                15
  * commit-reach.c:                                  16-----19
  * sha1-name.c:                                              20
@@ -79,7 +79,7 @@
  * builtin/show-branch.c:    0-------------------------------------------26
  * builtin/unpack-objects.c:                                 2021
  */
-#define FLAG_BITS  29
+#define FLAG_BITS  28
 
 /*
  * The object type is stored in 3 bits.
@@ -121,7 +121,7 @@
 
 void *create_object(struct repository *r, const struct object_id *oid, void *obj);
 
-void *object_as_type(struct repository *r, struct object *obj, enum object_type type, int quiet);
+void *object_as_type(struct object *obj, enum object_type type, int quiet);
 
 /*
  * Returns the object, having parsed it to find out what it is.
diff --git a/pack-write.c b/pack-write.c
index f0017be..685d327 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -38,9 +38,8 @@
 }
 
 /*
- * On entry *sha1 contains the pack content SHA1 hash, on exit it is
- * the SHA1 hash of sorted object names. The objects array passed in
- * will be sorted by SHA1 on exit.
+ * The *sha1 contains the pack content SHA1 hash.
+ * The objects array passed in will be sorted by SHA1 on exit.
  */
 const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects,
 			   int nr_objects, const struct pack_idx_option *opts,
diff --git a/packfile.c b/packfile.c
index f4e7529..6ab5233 100644
--- a/packfile.c
+++ b/packfile.c
@@ -178,6 +178,7 @@
 		     */
 		    (sizeof(off_t) <= 4))
 			return error("pack too large for current definition of off_t in %s", path);
+		p->crc_offset = 8 + 4 * 256 + nr * hashsz;
 	}
 
 	p->index_version = version;
diff --git a/perl/Git/IndexInfo.pm b/perl/Git/IndexInfo.pm
index a43108c..2a7b490 100644
--- a/perl/Git/IndexInfo.pm
+++ b/perl/Git/IndexInfo.pm
@@ -5,13 +5,15 @@
 
 sub new {
 	my ($class) = @_;
+	my $hash_algo = Git::config('extensions.objectformat') || 'sha1';
 	my ($gui, $ctx) = command_input_pipe(qw/update-index -z --index-info/);
-	bless { gui => $gui, ctx => $ctx, nr => 0}, $class;
+	bless { gui => $gui, ctx => $ctx, nr => 0, hash_algo => $hash_algo}, $class;
 }
 
 sub remove {
 	my ($self, $path) = @_;
-	if (print { $self->{gui} } '0 ', 0 x 40, "\t", $path, "\0") {
+	my $length = $self->{hash_algo} eq 'sha256' ? 64 : 40;
+	if (print { $self->{gui} } '0 ', 0 x $length, "\t", $path, "\0") {
 		return ++$self->{nr};
 	}
 	undef;
diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm
index 4b28b87..d1c352f 100644
--- a/perl/Git/SVN.pm
+++ b/perl/Git/SVN.pm
@@ -2,7 +2,7 @@
 use strict;
 use warnings;
 use Fcntl qw/:DEFAULT :seek/;
-use constant rev_map_fmt => 'NH40';
+use constant rev_map_fmt => 'NH*';
 use vars qw/$_no_metadata
             $_repack $_repack_flags $_use_svm_props $_head
             $_use_svnsync_props $no_reuse_existing
@@ -874,7 +874,7 @@
 		command_noisy('read-tree', $treeish) unless -e $self->{index};
 		my $x = command_oneline('write-tree');
 		my ($y) = (command(qw/cat-file commit/, $treeish) =~
-		           /^tree ($::sha1)/mo);
+		           /^tree ($::oid)/mo);
 		return if $y eq $x;
 
 		warn "Index mismatch: $y != $x\nrereading $treeish\n";
@@ -1020,7 +1020,7 @@
 		$tree = $self->tmp_index_do(sub {
 		                            command_oneline('write-tree') });
 	}
-	die "Tree is not a valid sha1: $tree\n" if $tree !~ /^$::sha1$/o;
+	die "Tree is not a valid oid $tree\n" if $tree !~ /^$::oid$/o;
 
 	my @exec = ('git', 'commit-tree', $tree);
 	foreach ($self->get_commit_parents($log_entry)) {
@@ -1048,8 +1048,8 @@
 	close $out_fh or croak $!;
 	waitpid $pid, 0;
 	croak $? if $?;
-	if ($commit !~ /^$::sha1$/o) {
-		die "Failed to commit, invalid sha1: $commit\n";
+	if ($commit !~ /^$::oid$/o) {
+		die "Failed to commit, invalid oid: $commit\n";
 	}
 
 	$self->rev_map_set($log_entry->{revision}, $commit, 1);
@@ -2087,10 +2087,10 @@
 	open my $fh, '<', $path or croak "open: $!";
 	binmode $fh or croak "binmode: $!";
 	while (<$fh>) {
-		length($_) == 41 or croak "inconsistent size in ($_) != 41";
+		length($_) == $::oid_length + 1 or croak "inconsistent size in ($_)";
 		chomp($_);
 		++$r;
-		next if $_ eq ('0' x 40);
+		next if $_ eq ('0' x $::oid_length);
 		$self->rev_map_set($r, $_);
 		print "r$r = $_\n";
 	}
@@ -2150,7 +2150,7 @@
 	my $svn_uuid = $self->rewrite_uuid || $self->ra_uuid;
 	my $c;
 	while (<$log>) {
-		if ( m{^commit ($::sha1)$} ) {
+		if ( m{^commit ($::oid)$} ) {
 			$c = $1;
 			next;
 		}
@@ -2196,9 +2196,9 @@
 # (mainly tags)
 #
 # The format is this:
-#   - 24 bytes for every record,
+#   - 24 or 36 bytes for every record,
 #     * 4 bytes for the integer representing an SVN revision number
-#     * 20 bytes representing the sha1 of a git commit
+#     * 20 or 32 bytes representing the oid of a git commit
 #   - No empty padding records like the old format
 #     (except the last record, which can be overwritten)
 #   - new records are written append-only since SVN revision numbers
@@ -2207,7 +2207,7 @@
 #   - Piping the file to xxd -c24 is a good way of dumping it for
 #     viewing or editing (piped back through xxd -r), should the need
 #     ever arise.
-#   - The last record can be padding revision with an all-zero sha1
+#   - The last record can be padding revision with an all-zero oid
 #     This is used to optimize fetch performance when using multiple
 #     "fetch" directives in .git/config
 #
@@ -2215,38 +2215,39 @@
 
 sub _rev_map_set {
 	my ($fh, $rev, $commit) = @_;
+	my $record_size = ($::oid_length / 2) + 4;
 
 	binmode $fh or croak "binmode: $!";
 	my $size = (stat($fh))[7];
-	($size % 24) == 0 or croak "inconsistent size: $size";
+	($size % $record_size) == 0 or croak "inconsistent size: $size";
 
 	my $wr_offset = 0;
 	if ($size > 0) {
-		sysseek($fh, -24, SEEK_END) or croak "seek: $!";
-		my $read = sysread($fh, my $buf, 24) or croak "read: $!";
-		$read == 24 or croak "read only $read bytes (!= 24)";
+		sysseek($fh, -$record_size, SEEK_END) or croak "seek: $!";
+		my $read = sysread($fh, my $buf, $record_size) or croak "read: $!";
+		$read == $record_size or croak "read only $read bytes (!= $record_size)";
 		my ($last_rev, $last_commit) = unpack(rev_map_fmt, $buf);
-		if ($last_commit eq ('0' x40)) {
-			if ($size >= 48) {
-				sysseek($fh, -48, SEEK_END) or croak "seek: $!";
-				$read = sysread($fh, $buf, 24) or
+		if ($last_commit eq ('0' x $::oid_length)) {
+			if ($size >= ($record_size * 2)) {
+				sysseek($fh, -($record_size * 2), SEEK_END) or croak "seek: $!";
+				$read = sysread($fh, $buf, $record_size) or
 				    croak "read: $!";
-				$read == 24 or
-				    croak "read only $read bytes (!= 24)";
+				$read == $record_size or
+				    croak "read only $read bytes (!= $record_size)";
 				($last_rev, $last_commit) =
 				    unpack(rev_map_fmt, $buf);
-				if ($last_commit eq ('0' x40)) {
+				if ($last_commit eq ('0' x $::oid_length)) {
 					croak "inconsistent .rev_map\n";
 				}
 			}
 			if ($last_rev >= $rev) {
 				croak "last_rev is higher!: $last_rev >= $rev";
 			}
-			$wr_offset = -24;
+			$wr_offset = -$record_size;
 		}
 	}
 	sysseek($fh, $wr_offset, SEEK_END) or croak "seek: $!";
-	syswrite($fh, pack(rev_map_fmt, $rev, $commit), 24) == 24 or
+	syswrite($fh, pack(rev_map_fmt, $rev, $commit), $record_size) == $record_size or
 	  croak "write: $!";
 }
 
@@ -2271,7 +2272,7 @@
 sub rev_map_set {
 	my ($self, $rev, $commit, $update_ref, $uuid) = @_;
 	defined $commit or die "missing arg3\n";
-	length $commit == 40 or die "arg3 must be a full SHA1 hexsum\n";
+	$commit =~ /^$::oid$/ or die "arg3 must be a full hex object ID\n";
 	my $db = $self->map_path($uuid);
 	my $db_lock = "$db.lock";
 	my $sigmask;
@@ -2344,29 +2345,30 @@
 
 sub rev_map_max_norebuild {
 	my ($self, $want_commit) = @_;
+	my $record_size = ($::oid_length / 2) + 4;
 	my $map_path = $self->map_path;
 	stat $map_path or return $want_commit ? (0, undef) : 0;
 	sysopen(my $fh, $map_path, O_RDONLY) or croak "open: $!";
 	binmode $fh or croak "binmode: $!";
 	my $size = (stat($fh))[7];
-	($size % 24) == 0 or croak "inconsistent size: $size";
+	($size % $record_size) == 0 or croak "inconsistent size: $size";
 
 	if ($size == 0) {
 		close $fh or croak "close: $!";
 		return $want_commit ? (0, undef) : 0;
 	}
 
-	sysseek($fh, -24, SEEK_END) or croak "seek: $!";
-	sysread($fh, my $buf, 24) == 24 or croak "read: $!";
+	sysseek($fh, -$record_size, SEEK_END) or croak "seek: $!";
+	sysread($fh, my $buf, $record_size) == $record_size or croak "read: $!";
 	my ($r, $c) = unpack(rev_map_fmt, $buf);
-	if ($want_commit && $c eq ('0' x40)) {
-		if ($size < 48) {
+	if ($want_commit && $c eq ('0' x $::oid_length)) {
+		if ($size < $record_size * 2) {
 			return $want_commit ? (0, undef) : 0;
 		}
-		sysseek($fh, -48, SEEK_END) or croak "seek: $!";
-		sysread($fh, $buf, 24) == 24 or croak "read: $!";
+		sysseek($fh, -($record_size * 2), SEEK_END) or croak "seek: $!";
+		sysread($fh, $buf, $record_size) == $record_size or croak "read: $!";
 		($r, $c) = unpack(rev_map_fmt, $buf);
-		if ($c eq ('0'x40)) {
+		if ($c eq ('0' x $::oid_length)) {
 			croak "Penultimate record is all-zeroes in $map_path";
 		}
 	}
@@ -2387,30 +2389,31 @@
 
 sub _rev_map_get {
 	my ($fh, $rev) = @_;
+	my $record_size = ($::oid_length / 2) + 4;
 
 	binmode $fh or croak "binmode: $!";
 	my $size = (stat($fh))[7];
-	($size % 24) == 0 or croak "inconsistent size: $size";
+	($size % $record_size) == 0 or croak "inconsistent size: $size";
 
 	if ($size == 0) {
 		return undef;
 	}
 
-	my ($l, $u) = (0, $size - 24);
+	my ($l, $u) = (0, $size - $record_size);
 	my ($r, $c, $buf);
 
 	while ($l <= $u) {
-		my $i = int(($l/24 + $u/24) / 2) * 24;
+		my $i = int(($l/$record_size + $u/$record_size) / 2) * $record_size;
 		sysseek($fh, $i, SEEK_SET) or croak "seek: $!";
-		sysread($fh, my $buf, 24) == 24 or croak "read: $!";
+		sysread($fh, my $buf, $record_size) == $record_size or croak "read: $!";
 		my ($r, $c) = unpack(rev_map_fmt, $buf);
 
 		if ($r < $rev) {
-			$l = $i + 24;
+			$l = $i + $record_size;
 		} elsif ($r > $rev) {
-			$u = $i - 24;
+			$u = $i - $record_size;
 		} else { # $r == $rev
-			return $c eq ('0' x 40) ? undef : $c;
+			return $c eq ('0' x $::oid_length) ? undef : $c;
 		}
 	}
 	undef;
diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm
index 0df16ed..c961444 100644
--- a/perl/Git/SVN/Editor.pm
+++ b/perl/Git/SVN/Editor.pm
@@ -63,7 +63,7 @@
 	my @mods;
 	while (defined($_ = get_record($diff_fh, "\0"))) {
 		if ($state eq 'meta' && /^:(\d{6})\s(\d{6})\s
-					($::sha1)\s($::sha1)\s
+					($::oid)\s($::oid)\s
 					([MTCRAD])\d*$/xo) {
 			push @mods, {	mode_a => $1, mode_b => $2,
 					sha1_a => $3, sha1_b => $4,
@@ -400,12 +400,12 @@
 	    ($m->{mode_b} !~ /^120/ && $m->{mode_a} =~ /^120/)) {
 		$self->D({
 			mode_a => $m->{mode_a}, mode_b => '000000',
-			sha1_a => $m->{sha1_a}, sha1_b => '0' x 40,
+			sha1_a => $m->{sha1_a}, sha1_b => '0' x $::oid_length,
 			chg => 'D', file_b => $m->{file_b}
 		}, $deletions);
 		$self->A({
 			mode_a => '000000', mode_b => $m->{mode_b},
-			sha1_a => '0' x 40, sha1_b => $m->{sha1_b},
+			sha1_a => '0' x $::oid_length, sha1_b => $m->{sha1_b},
 			chg => 'A', file_b => $m->{file_b}
 		}, $deletions);
 		return;
@@ -434,7 +434,7 @@
 		$self->change_file_prop($fbat,'svn:special',undef);
 	}
 	my $blob = $m->{"sha1_$which"};
-	return ($fh,) if ($blob =~ /^0{40}$/);
+	return ($fh,) if ($blob =~ /^0+$/);
 	my $size = $::_repository->cat_blob($blob, $fh);
 	croak "Failed to read object $blob" if ($size < 0);
 	$fh->flush == 0 or croak $!;
diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm
index 64e900a..729e533 100644
--- a/perl/Git/SVN/Fetcher.pm
+++ b/perl/Git/SVN/Fetcher.pm
@@ -173,7 +173,7 @@
 
 	# remove entire directories.
 	my ($tree) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
-	                 =~ /\A040000 tree ([a-f\d]{40})\t\Q$gpath\E\0/);
+	                 =~ /\A040000 tree ($::oid)\t\Q$gpath\E\0/);
 	if ($tree) {
 		my ($ls, $ctx) = command_output_pipe(qw/ls-tree
 		                                     -r --name-only -z/,
@@ -203,7 +203,7 @@
 
 	my $gpath = $self->git_path($path);
 	($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
-	                     =~ /\A(\d{6}) blob ([a-f\d]{40})\t\Q$gpath\E\0/);
+	                     =~ /\A(\d{6}) blob ($::oid)\t\Q$gpath\E\0/);
 	unless (defined $mode && defined $blob) {
 		die "$path was not found in commit $self->{c} (r$rev)\n";
 	}
@@ -413,7 +413,7 @@
 
 		$hash = $::_repository->hash_and_insert_object(
 				Git::temp_path($fh));
-		$hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
+		$hash =~ /^$::oid$/ or die "not an object ID: $hash\n";
 
 		Git::temp_release($fb->{base}, 1);
 		Git::temp_release($fh, 1);
diff --git a/perl/Git/SVN/Log.pm b/perl/Git/SVN/Log.pm
index 6641053..3858fcf 100644
--- a/perl/Git/SVN/Log.pm
+++ b/perl/Git/SVN/Log.pm
@@ -285,7 +285,7 @@
 	my (@k, $c, $d, $stat);
 	my $esc_color = qr/(?:\033\[(?:(?:\d+;)*\d*)?m)*/;
 	while (<$log>) {
-		if (/^${esc_color}commit (?:- )?($::sha1_short)/o) {
+		if (/^${esc_color}commit (?:- )?($::oid_short)/o) {
 			my $cmt = $1;
 			if ($c && cmt_showable($c) && $c->{r} != $r_last) {
 				$r_last = $c->{r};
diff --git a/perl/Git/SVN/Ra.pm b/perl/Git/SVN/Ra.pm
index 56ad987..2cfe055 100644
--- a/perl/Git/SVN/Ra.pm
+++ b/perl/Git/SVN/Ra.pm
@@ -486,11 +486,11 @@
 			$reload_ra->() if $ra_invalid;
 		}
 		# pre-fill the .rev_db since it'll eventually get filled in
-		# with '0' x40 if something new gets committed
+		# with '0' x $oid_length if something new gets committed
 		foreach my $gs (@$gsv) {
 			next if $gs->rev_map_max >= $max;
 			next if defined $gs->rev_map_get($max);
-			$gs->rev_map_set($max, 0 x40);
+			$gs->rev_map_set($max, 0 x $::oid_length);
 		}
 		foreach my $g (@$globs) {
 			my $k = "svn-remote.$g->{remote}.$g->{t}-maxRev";
diff --git a/pkt-line.c b/pkt-line.c
index 8f9bc68..844c253 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -490,6 +490,7 @@
 	reader->buffer_size = sizeof(packet_buffer);
 	reader->options = options;
 	reader->me = "git";
+	reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
 }
 
 enum packet_read_status packet_reader_read(struct packet_reader *reader)
diff --git a/pkt-line.h b/pkt-line.h
index 5b373fe..8c90daa 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -177,6 +177,9 @@
 
 	unsigned use_sideband : 1;
 	const char *me;
+
+	/* hash algorithm in use */
+	const struct git_hash_algo *hash_algo;
 };
 
 /*
diff --git a/po/ca.po b/po/ca.po
index 3a0246e..c43c21b 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -51,7 +51,7 @@
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
 "POT-Creation-Date: 2020-05-27 07:23+0800\n"
-"PO-Revision-Date: 2020-05-22 07:51+0200\n"
+"PO-Revision-Date: 2020-05-28 18:14+0200\n"
 "Last-Translator: Jordi Mas <jmas@softcatala.org>\n"
 "Language-Team: Catalan\n"
 "Language: ca\n"
@@ -59,7 +59,7 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.3\n"
+"X-Generator: Poedit 2.3.1\n"
 
 #: add-interactive.c:368
 #, c-format
@@ -222,7 +222,7 @@
 
 #: add-interactive.c:1032
 msgid "choose all items"
-msgstr "escolliu tots els ítems"
+msgstr "trieu tots els ítems"
 
 #: add-interactive.c:1034
 msgid "(empty) finish selecting"
@@ -304,9 +304,9 @@
 msgstr ""
 "y - fes «stage» d'aquest tros\n"
 "n - no facis «stage» d'aquest tros\n"
-"q - surt; no facis «stage» d'aquest tros o de cap altre restant\n"
-"a - fes «stage» d'aquest tros i tota la resta de trossos del fitxer\n"
-"d - no facis «stage» d'aquest tros o de cap altre restant del fitxer\n"
+"q - surt; no facis «stage» d'aquest tros ni de cap altre restant\n"
+"a - fes «stage» d'aquest tros i de tota la resta de trossos del fitxer\n"
+"d - no facis «stage» d'aquest tros ni de cap altre restant del fitxer\n"
 
 #: add-patch.c:55 git-add--interactive.perl:1433
 #, c-format, perl-format
@@ -341,9 +341,9 @@
 msgstr ""
 "y - fes «stash» d'aquest tros\n"
 "n - no facis «stash» d'aquest tros\n"
-"q - surt; no facis «stash» d'aquest tros o de cap altre restant\n"
-"a - fes «stash» d'aquest tros i tota la resta de trossos del fitxer\n"
-"d - no facis «stash» d'aquest tros o de cap altre restant del fitxer\n"
+"q - surt; no facis «stash» d'aquest tros ni de cap altre restant\n"
+"a - fes «stash» d'aquest tros i de tota la resta de trossos del fitxer\n"
+"d - no facis «stash» d'aquest tros ni de cap altre restant del fitxer\n"
 
 #: add-patch.c:78 git-add--interactive.perl:1438
 #, c-format, perl-format
@@ -378,9 +378,9 @@
 msgstr ""
 "y - fes «unstage» d'aquest tros\n"
 "n - no facis «unstage» d'aquest tros\n"
-"q - surt; no facis «unstage» d'aquest tros o de cap altre restant\n"
-"a - fes «unstage» d'aquest tros i tota la resta de trossos del fitxer\n"
-"d - no facis «unstage» d'aquest tros o de cap altre restant del fitxer\n"
+"q - surt; no facis «unstage» d'aquest tros ni de cap altre restant\n"
+"a - fes «unstage» d'aquest tros i de tota la resta de trossos del fitxer\n"
+"d - no facis «unstage» d'aquest tros ni de cap altre restant del fitxer\n"
 
 #: add-patch.c:100 git-add--interactive.perl:1443
 #, c-format, perl-format
@@ -390,7 +390,7 @@
 #: add-patch.c:101 git-add--interactive.perl:1444
 #, c-format, perl-format
 msgid "Apply deletion to index [y,n,q,a,d%s,?]? "
-msgstr "Aplica l'esborrat a l'índex [y,n,q,a,d%s,?]? "
+msgstr "Aplica la supressió a l'índex [y,n,q,a,d%s,?]? "
 
 #: add-patch.c:102 git-add--interactive.perl:1445
 #, c-format, perl-format
@@ -423,19 +423,19 @@
 #: git-add--interactive.perl:1463
 #, c-format, perl-format
 msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? "
-msgstr "Descarta el canvi de mode des de l'arbre de treball [y,n,q,a,d%s,?]? "
+msgstr "Descarta el canvi de mode de l'arbre de treball [y,n,q,a,d%s,?]? "
 
 #: add-patch.c:123 git-add--interactive.perl:1449
 #: git-add--interactive.perl:1464
 #, c-format, perl-format
 msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? "
-msgstr "Descarta l'esborrat des de l'arbre de treball [y,n,q,a,d%s,?]? "
+msgstr "Descarta suprimir de l'arbre de treball [y,n,q,a,d%s,?]? "
 
 #: add-patch.c:124 git-add--interactive.perl:1450
 #: git-add--interactive.perl:1465
 #, c-format, perl-format
 msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? "
-msgstr "Descarta aquest tros des de l'arbre de treball  [y,n,q,a,d%s,?]? "
+msgstr "Descarta aquest tros de l'arbre de treball [y,n,q,a,d%s,?]? "
 
 #: add-patch.c:126 add-patch.c:148 add-patch.c:191
 msgid ""
@@ -454,7 +454,7 @@
 "d - do not discard this hunk or any of the later hunks in the file\n"
 msgstr ""
 "y - descarta aquest tros de l'arbre de treball\n"
-"n - no descartis aquest tros des de l'arbre de treball\n"
+"n - no descartis aquest tros de l'arbre de treball\n"
 "q - surt; no apliquis aquest tros ni cap dels pendents\n"
 "a - descarta aquest tros i tots els trossos posteriors en el fitxer\n"
 "d - no descartis aquest tros ni cap dels trossos posteriors en el fitxer\n"
@@ -463,20 +463,19 @@
 #, c-format, perl-format
 msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
-"Descarta el canvi de mode des de l'índex i l'arbre de treball [y,n,q,a,d"
+"Descarta el canvi de mode de l'índex i de l'arbre de treball [y,n,q,a,d"
 "%s,?]? "
 
 #: add-patch.c:145 add-patch.c:188 git-add--interactive.perl:1454
 #, c-format, perl-format
 msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? "
-msgstr ""
-"Descarta la supressió des de l'índex i l'arbre de treball [y,n,q,a,d%s,?]? "
+msgstr "Descarta suprimir de l'índex i de l'arbre de treball [y,n,q,a,d%s,?]? "
 
 #: add-patch.c:146 add-patch.c:189 git-add--interactive.perl:1455
 #, c-format, perl-format
 msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
-"Descarta aquest tros des de l'índex i l'arbre de treball [y,n,q,a,d%s,?]? "
+"Descarta aquest tros de l'índex i de l'arbre de treball [y,n,q,a,d%s,?]? "
 
 #: add-patch.c:151
 msgid ""
@@ -486,8 +485,8 @@
 "a - discard this hunk and all later hunks in the file\n"
 "d - do not discard this hunk or any of the later hunks in the file\n"
 msgstr ""
-"y - descarta aquest tros de l'arbre de treball\n"
-"n - no descartis aquest tros des de l'arbre de treball\n"
+"y - descarta aquest tros de l'índex i de l'arbre de treball\n"
+"n - no descartis aquest tros de l'índex ni de l'arbre de treball\n"
 "q - surt; no apliquis aquest tros ni cap dels pendents\n"
 "a - descarta aquest tros i tots els trossos posteriors en el fitxer\n"
 "d - no descartis aquest tros ni cap dels trossos posteriors en el fitxer\n"
@@ -496,17 +495,17 @@
 #, c-format, perl-format
 msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
-"Aplica el canvi de mode a l'índex i l'arbre de treball [y,n,q,a,d%s,?]? "
+"Aplica el canvi de mode a l'índex i a l'arbre de treball [y,n,q,a,d%s,?]? "
 
 #: add-patch.c:166 add-patch.c:209 git-add--interactive.perl:1459
 #, c-format, perl-format
 msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Aplica la supressió a l'índex i l'arbre de treball [y,n,q,a,d%s,?]? "
+msgstr "Aplica la supressió a l'índex i a l'arbre de treball [y,n,q,a,d%s,?]? "
 
 #: add-patch.c:167 add-patch.c:210 git-add--interactive.perl:1460
 #, c-format, perl-format
 msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Aplica aquest tros a l'índex i l'arbre de treball [y,n,q,a,d%s,?]? "
+msgstr "Aplica aquest tros a l'índex i a l'arbre de treball [y,n,q,a,d%s,?]? "
 
 #: add-patch.c:172
 msgid ""
@@ -516,8 +515,8 @@
 "a - apply this hunk and all later hunks in the file\n"
 "d - do not apply this hunk or any of the later hunks in the file\n"
 msgstr ""
-"y - aplica aquest tros a l'índex i l'arbre de treball\n"
-"n - no apliquis aquest tros des de l'índex i de l'arbre de treball\n"
+"y - aplica aquest tros a l'índex i a l'arbre de treball\n"
+"n - no apliquis aquest tros a l'índex ni a l'arbre de treball\n"
 "q - surt; no apliquis aquest tros ni cap dels pendents\n"
 "a - aplica aquest tros i tots els trossos posteriors en el fitxer\n"
 "d - no apliquis aquest tros ni cap dels trossos posteriors en el fitxer\n"
@@ -607,9 +606,9 @@
 "Lines starting with %c will be removed.\n"
 msgstr ""
 "---\n"
-"Per suprimir «%c» línies, convertiu-les a ' ' (context).\n"
-"Per suprimir «%c» línies, suprimiu-les.\n"
-"Les línies que comencin per %c seran suprimides.\n"
+"Per a eliminar les línies «%c», convertiu-les en línies ' ' (context).\n"
+"Per a eliminar les línies «%c», suprimiu-les.\n"
+"Les línies que comencin per %c s'eliminaran.\n"
 
 #. TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.
 #: add-patch.c:1071 git-add--interactive.perl:1126
@@ -619,8 +618,7 @@
 "aborted and the hunk is left unchanged.\n"
 msgstr ""
 "Si no s'aplica correctament, tindreu una oportunitat per editar-lo\n"
-"de nou. Si totes les línies del tros se suprimeixen, llavors l'edició "
-"s'avorta\n"
+"de nou. Si s'eliminen totes les línies del tros, llavors l'edició s'avorta\n"
 "i el tros es deixa sense cap canvi.\n"
 
 #: add-patch.c:1104
@@ -629,7 +627,7 @@
 
 #: add-patch.c:1149
 msgid "'git apply --cached' failed"
-msgstr "'git apply --cached' ha fallat"
+msgstr "«git apply --cached» ha fallat"
 
 #. TRANSLATORS: do not translate [y/n]
 #. The program will only accept that input at this point.
@@ -698,7 +696,7 @@
 
 #: add-patch.c:1479 git-add--interactive.perl:1577
 msgid "go to which hunk (<ret> to see more)? "
-msgstr "vés a quin tros (<ret> per veure'n més)? "
+msgstr "vés a quin tros (<ret> per a veure'n més)? "
 
 #: add-patch.c:1480 git-add--interactive.perl:1579
 msgid "go to which hunk? "
@@ -793,7 +791,7 @@
 "as appropriate to mark resolution and make a commit."
 msgstr ""
 "Arregleu-los en l'arbre de treball, i després useu\n"
-"'git add/rm <fitxer>' segons sigui apropiat per a marcar la\n"
+"«git add/rm <fitxer>» segons sigui apropiat per a marcar la\n"
 "resolució i feu una comissió."
 
 #: advice.c:273
@@ -843,7 +841,7 @@
 "Si voleu crear una branca nova per a conservar les comissions que creeu,\n"
 "poder fer-ho (ara o més tard) usant -c amb l'ordre switch. Exemple:\n"
 "\n"
-"  git switch -b <nom-de-branca-nova>\n"
+"  git switch -c <nom-de-branca-nova>\n"
 "\n"
 "O desfer aquesta operació amb:\n"
 "\n"
@@ -1411,7 +1409,7 @@
 
 #: apply.c:4991
 msgid "mark new files with `git add --intent-to-add`"
-msgstr "marca els fitxers nous amb «git add --inten-to-add»"
+msgstr "marca els fitxers nous amb «git add --intent-to-add»"
 
 #: apply.c:4993
 msgid "apply a patch without touching the working tree"
@@ -1584,7 +1582,7 @@
 
 #: archive.c:432
 msgid "current working directory is untracked"
-msgstr "no es segueix el directori de treball actual"
+msgstr "no se segueix el directori de treball actual"
 
 #: archive.c:464
 msgid "fmt"
@@ -1677,7 +1675,7 @@
 #: archive.c:529
 #, c-format
 msgid "Argument not supported for format '%s': -%d"
-msgstr "Paràmetre no admès per al format «%s»: -%d"
+msgstr "Argument no admès per al format «%s»: -%d"
 
 #: attr.c:212
 #, c-format
@@ -1695,7 +1693,7 @@
 "Use '\\!' for literal leading exclamation."
 msgstr ""
 "Els patrons negatius s'ignoren en els atributs de git\n"
-"Useu '\\!' per exclamació capdavantera literal."
+"Useu «\\!» per exclamació capdavantera literal."
 
 #: bisect.c:468
 #, c-format
@@ -1867,7 +1865,7 @@
 "\n"
 "Després de corregir la causa de l'error, podeu\n"
 "intentar corregir la informació de seguiment remot\n"
-"invocant \"git branch --set-upstream-to=%s%s%s\"."
+"invocant «git branch --set-upstream-to=%s%s%s»."
 
 #: branch.c:67
 #, c-format
@@ -2053,7 +2051,7 @@
 
 #: bundle.c:280
 msgid "Could not spawn pack-objects"
-msgstr "No s'ha pogut executar el pack-objects"
+msgstr "No s'ha pogut generar el pack-objects"
 
 #: bundle.c:291
 msgid "pack-objects died"
@@ -2071,7 +2069,7 @@
 #: bundle.c:461 builtin/log.c:208 builtin/log.c:1834 builtin/shortlog.c:306
 #, c-format
 msgid "unrecognized argument: %s"
-msgstr "paràmetre no reconegut: %s"
+msgstr "argument no reconegut: %s"
 
 #: bundle.c:469
 msgid "Refusing to create empty bundle."
@@ -2124,9 +2122,9 @@
 msgstr "desplaçament %08x%08x del gràfic de comissions incorrecte"
 
 #: commit-graph.c:362
-#, fuzzy, c-format
+#, c-format
 msgid "commit-graph chunk id %08x appears multiple times"
-msgstr "id%08x del graf de comissions múltiples vegades"
+msgstr "id %08x del graf de comissions apareix múltiples vegades"
 
 #: commit-graph.c:436
 msgid "commit-graph has no base graphs chunk"
@@ -2140,7 +2138,7 @@
 #, c-format
 msgid "invalid commit-graph chain: line '%s' not a hash"
 msgstr ""
-"la cadena del graf de comissions no és vàlida: la línea «%s» no és un hash"
+"la cadena del graf de comissions no és vàlida: la línia «%s» no és un hash"
 
 #: commit-graph.c:518
 msgid "unable to find all commit-graph files"
@@ -2185,7 +2183,7 @@
 
 #: commit-graph.c:1233
 msgid "Clearing commit marks in commit graph"
-msgstr "S'estan netejant les marques de comissions al graf de comissions"
+msgstr "S'estan esborrant les marques de comissions al graf de comissions"
 
 #: commit-graph.c:1252
 msgid "Computing commit graph generation numbers"
@@ -2374,7 +2372,7 @@
 "commit-graph has non-zero generation number for commit %s, but zero elsewhere"
 msgstr ""
 "El graf de comissions té un nombre de generació diferent de zero per a "
-"commisió %s però té zero en altres llocs"
+"comissió %s però té zero en altres llocs"
 
 #: commit-graph.c:2322
 #, c-format
@@ -2493,7 +2491,7 @@
 #: config.c:414
 #, c-format
 msgid "invalid key (newline): %s"
-msgstr "clau no vàlida (línea nova): %s"
+msgstr "clau no vàlida (línia nova): %s"
 
 #: config.c:450 config.c:462
 #, c-format
@@ -2568,7 +2566,7 @@
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s"
 msgstr ""
-"valor de configuració numèric «%s» erroni' per «%s» en el blob de submòdul "
+"valor de configuració numèric «%s» erroni per «%s» en el blob de submòdul "
 "%s: %s"
 
 #: config.c:1025
@@ -2924,7 +2922,7 @@
 
 #: connected.c:119
 msgid "Could not run 'git rev-list'"
-msgstr "No s'ha pogut executar 'git rev-list'"
+msgstr "No s'ha pogut executar «git rev-list»"
 
 #: connected.c:139
 msgid "failed write to rev-list"
@@ -2937,7 +2935,7 @@
 #: convert.c:194
 #, c-format
 msgid "illegal crlf_action %d"
-msgstr "crlf_action %d  il·legal"
+msgstr "crlf_action %d il·legal"
 
 #: convert.c:207
 #, c-format
@@ -2957,7 +2955,7 @@
 #: convert.c:217
 #, c-format
 msgid "LF would be replaced by CRLF in %s"
-msgstr "LF es reemplaçà per LF en %s"
+msgstr "LF es reemplaçà per CRLF en %s"
 
 #: convert.c:219
 #, c-format
@@ -2994,7 +2992,7 @@
 "The file '%s' is missing a byte order mark (BOM). Please use UTF-%sBE or UTF-"
 "%sLE (depending on the byte order) as working-tree-encoding."
 msgstr ""
-"Falta una marca d'ordre de byte (BOM) al fitxer «%s» . Useu UTF-%sBE o UTF-"
+"Falta una marca d'ordre de byte (BOM) al fitxer «%s». Useu UTF-%sBE o UTF-"
 "%sLE (depenent de l'ordre de byte) com a codificacions d'arbre de treball."
 
 #: convert.c:419 convert.c:490
@@ -3038,7 +3036,7 @@
 
 #: convert.c:851
 msgid "path name too long for external filter"
-msgstr "el nom del camí és massa llarg per al filtre extern"
+msgstr "el nom del camí és massa gran per al filtre extern"
 
 #: convert.c:943
 #, c-format
@@ -3240,7 +3238,7 @@
 #, c-format
 msgid "Unknown value for 'diff.submodule' config variable: '%s'"
 msgstr ""
-"Valor desconegut de la variable de configuració de 'diff.submodule': «%s»"
+"Valor desconegut de la variable de configuració de «diff.submodule»: «%s»"
 
 #: diff.c:465
 #, c-format
@@ -3248,7 +3246,7 @@
 "Found errors in 'diff.dirstat' config variable:\n"
 "%s"
 msgstr ""
-"S'han trobat errors en la variable de configuració 'diff.dirstat':\n"
+"S'han trobat errors en la variable de configuració «diff.dirstat»:\n"
 "%s"
 
 #: diff.c:4238
@@ -3316,12 +3314,12 @@
 #: diff.c:4961
 #, c-format
 msgid "bad --color-moved argument: %s"
-msgstr "paràmetre --color-moved incorrecte: %s"
+msgstr "argument --color-moved incorrecte: %s"
 
 #: diff.c:4980
 #, c-format
 msgid "invalid mode '%s' in --color-moved-ws"
-msgstr "mode «%s» no vàlid en -color-moved-ws"
+msgstr "mode «%s» no vàlid en --color-moved-ws"
 
 #: diff.c:5020
 msgid ""
@@ -3344,7 +3342,7 @@
 #: diff.c:5270
 #, c-format
 msgid "bad --word-diff argument: %s"
-msgstr "paràmetre --word-diff incorrecte: %s"
+msgstr "argument --word-diff incorrecte: %s"
 
 #: diff.c:5293
 msgid "Diff output format options"
@@ -3372,11 +3370,11 @@
 
 #: diff.c:5312
 msgid "synonym for '-p --raw'"
-msgstr "sinònim de per a «-p --raw»"
+msgstr "sinònim de «-p --raw»"
 
 #: diff.c:5316
 msgid "synonym for '-p --stat'"
-msgstr "sinònim de per a «-p --stat»"
+msgstr "sinònim de «-p --stat»"
 
 #: diff.c:5320
 msgid "machine friendly --stat"
@@ -3399,11 +3397,11 @@
 
 #: diff.c:5330
 msgid "synonym for --dirstat=cumulative"
-msgstr "sinònim per -dirstat=cumulative"
+msgstr "sinònim de --dirstat=cumulative"
 
 #: diff.c:5334
 msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "sinònim per --dirstat=files,param1,param2..."
+msgstr "sinònim de --dirstat=files,param1,param2..."
 
 #: diff.c:5338
 msgid "warn if changes introduce conflict markers or whitespace errors"
@@ -3425,7 +3423,7 @@
 
 #: diff.c:5349
 msgid "<width>[,<name-width>[,<count>]]"
-msgstr "<width>[<name-width>[<count>]]"
+msgstr "<amplada>[<amplada-nom>[,<recompte>]]"
 
 #: diff.c:5350
 msgid "generate diffstat"
@@ -3461,7 +3459,7 @@
 
 #: diff.c:5368
 msgid "output a binary diff that can be applied"
-msgstr "diff amb sortida binaria que pot ser aplicada"
+msgstr "diff amb sortida binària que pot ser aplicada"
 
 #: diff.c:5371
 #, fuzzy
@@ -3474,17 +3472,15 @@
 msgstr "mostra un diff amb colors"
 
 #: diff.c:5374
-#, fuzzy
 msgid "<kind>"
 msgstr "<kind>"
 
 #: diff.c:5375
-#, fuzzy
 msgid ""
 "highlight whitespace errors in the 'context', 'old' or 'new' lines in the "
 "diff"
 msgstr ""
-"ressalta els errors d'espai en blanc a les línies «context» «old» o «new» al "
+"ressalta els errors d'espai en blanc a les línies «context», «old» o «new» al "
 "diff"
 
 #: diff.c:5378
@@ -3501,12 +3497,10 @@
 msgstr "<prefix>"
 
 #: diff.c:5382
-#, fuzzy
 msgid "show the given source prefix instead of \"a/\""
 msgstr "mostra el prefix d'origen donat en lloc de «a/»"
 
 #: diff.c:5385
-#, fuzzy
 msgid "show the given destination prefix instead of \"b/\""
 msgstr "mostra el prefix de destinació indicat en lloc de «b/»"
 
@@ -3519,7 +3513,6 @@
 msgstr "no mostris cap prefix d'origen o destí"
 
 #: diff.c:5394
-#, fuzzy
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr ""
 "mostra el context entre trossos de diferència fins al nombre especificat de "
@@ -3585,17 +3578,16 @@
 msgstr "continua llistant l'històric d'un fitxer més enllà dels canvis de nom"
 
 #: diff.c:5439
-#, fuzzy
 msgid ""
 "prevent rename/copy detection if the number of rename/copy targets exceeds "
 "given limit"
 msgstr ""
-"Evita la detecció de canvi de nom/còpia si el nombre d'objectius de canvi de "
-"nom supera el límit indicat"
+"Evita la detecció de canvi de nom/còpia si el nombre d'objectius de canvi de nom/còpia "
+"supera el límit indicat"
 
 #: diff.c:5441
 msgid "Diff algorithm options"
-msgstr "Opcions d'algorisme Diff"
+msgstr "Opcions de l'algorisme Diff"
 
 #: diff.c:5443
 msgid "produce the smallest possible diff"
@@ -3603,7 +3595,7 @@
 
 #: diff.c:5446
 msgid "ignore whitespace when comparing lines"
-msgstr "ignora els espai en blanc en comparar línies"
+msgstr "ignora els espais en blanc en comparar línies"
 
 #: diff.c:5449
 msgid "ignore changes in amount of whitespace"
@@ -3622,10 +3614,9 @@
 msgstr "ignora els canvis en línies que estan en blanc"
 
 #: diff.c:5461
-#, fuzzy
 msgid "heuristic to shift diff hunk boundaries for easy reading"
 msgstr ""
-"heurística per canviar els límits del tros de diferència per a lectura fàcil"
+"heurística per a desplaçar els límits del tros de diferència per a una lectura fàcil"
 
 #: diff.c:5464
 msgid "generate diff using the \"patience diff\" algorithm"
@@ -3641,7 +3632,7 @@
 
 #: diff.c:5471
 msgid "choose a diff algorithm"
-msgstr "escolliu un algorisme pel diff"
+msgstr "trieu un algorisme per al diff"
 
 #: diff.c:5473
 msgid "<text>"
@@ -4070,7 +4061,7 @@
 
 #: fetch-pack.c:1211
 msgid "Server does not support shallow requests"
-msgstr "El servidor no permet peticions superficials"
+msgstr "El servidor no permet sol·licituds superficials"
 
 #: fetch-pack.c:1218
 msgid "Server supports filter"
@@ -4078,7 +4069,7 @@
 
 #: fetch-pack.c:1242
 msgid "unable to write request to remote"
-msgstr "no s'ha pogut escriure la petició al remot"
+msgstr "no s'ha pogut escriure la sol·licitud al remot"
 
 #: fetch-pack.c:1260
 #, c-format
@@ -4102,11 +4093,11 @@
 
 #: fetch-pack.c:1342
 msgid "expected packfile to be sent after 'ready'"
-msgstr "s'espera l'enviament del fitxer de paquet després de «ready»"
+msgstr "s'esperava l'enviament del fitxer de paquet després de «ready»"
 
 #: fetch-pack.c:1344
 msgid "expected no other sections to be sent after no 'ready'"
-msgstr "s'espera que cap altra seccions s'enviï després de no «ready»"
+msgstr "s'esperava que no s'enviés cap altra secció després de no «ready»"
 
 #: fetch-pack.c:1386
 #, c-format
@@ -4209,17 +4200,14 @@
 msgstr "col·laborar (vegeu també: git help workflow)"
 
 #: help.c:31
-#, fuzzy
 msgid "Main Porcelain Commands"
 msgstr "Ordres principals de porcellana"
 
 #: help.c:32
-#, fuzzy
 msgid "Ancillary Commands / Manipulators"
-msgstr "Ordres Auxiliars / Manipuladors"
+msgstr "Ordres auxiliars / manipuladors"
 
 #: help.c:33
-#, fuzzy
 msgid "Ancillary Commands / Interrogators"
 msgstr "Ordres auxiliars / interrogadors"
 
@@ -4477,7 +4465,7 @@
 "may have crashed in this repository earlier:\n"
 "remove the file manually to continue."
 msgstr ""
-"No s'ha pogut crear '%s.lock': %s.\n"
+"No s'ha pogut crear «%s.lock»: %s.\n"
 "\n"
 "Sembla que un altre procés de git s'està executant en aquest\n"
 "dipòsit, per exemple, un editor obert per «git commit». \n"
@@ -4586,8 +4574,7 @@
 #, c-format
 msgid "Failed to merge submodule %s (merge following commits not found)"
 msgstr ""
-"Ha fallat en fusionar el submòdul  %s (no s'ha trobat les comissions "
-"següents)"
+"Ha fallat en fusionar el submòdul %s (no s'ha trobat les comissions següents)"
 
 #: merge-recursive.c:1255
 #, c-format
@@ -4611,7 +4598,7 @@
 msgstr ""
 "Si això és correcte simplement afegiu-ho a l'índex per exemple utilitzant "
 "git update-index --cacheinfo 160000 per cents \"%s\" que acceptaran aquest "
-"suggeriment."
+"suggeriment.\n"
 
 #: merge-recursive.c:1268
 #, c-format
@@ -5050,9 +5037,8 @@
 msgstr "no s'han vist caure els paquets del fitxer"
 
 #: midx.c:925
-#, fuzzy
 msgid "no pack files to index."
-msgstr "Afegint fitxers de paquets a multi-index"
+msgstr "no hi ha fitxers empaquetats a indexar."
 
 #: midx.c:977
 #, fuzzy
@@ -5066,7 +5052,7 @@
 
 #: midx.c:1112
 msgid "Looking for referenced packfiles"
-msgstr "S'estan cercant fitxers de paquets referenciats"
+msgstr "S'estan cercant fitxers empaquetats referenciats"
 
 #: midx.c:1127
 #, fuzzy, c-format
@@ -5124,7 +5110,7 @@
 
 #: midx.c:1433
 msgid "could not start pack-objects"
-msgstr "no s'ha pogut executar el pack-objects"
+msgstr "no s'ha pogut iniciar el pack-objects"
 
 #: midx.c:1452
 msgid "could not finish pack-objects"
@@ -5205,14 +5191,14 @@
 msgstr "no s'ha pogut analitzar l'objecte: %s"
 
 #: object.c:266 object.c:278
-#, fuzzy, c-format
+#, c-format
 msgid "hash mismatch %s"
-msgstr "els resums no coincideixen"
+msgstr "el resum no coincideix %s"
 
 #: pack-bitmap.c:815 pack-bitmap.c:821 builtin/pack-objects.c:2135
-#, fuzzy, c-format
+#, c-format
 msgid "unable to get size of %s"
-msgstr "no s'ha pogut obtenir la mida dels percentatges"
+msgstr "no s'ha pogut obtenir la mida de %s"
 
 #: packfile.c:629
 msgid "offset before end of packfile (broken .idx?)"
@@ -5325,7 +5311,7 @@
 #: parse-options.c:907
 #, c-format
 msgid "   or: %s"
-msgstr " o: %s"
+msgstr "   o: %s"
 
 #: parse-options.c:910
 #, c-format
@@ -5381,7 +5367,7 @@
 #: pathspec.c:327
 #, c-format
 msgid "Invalid pathspec magic '%.*s' in '%s'"
-msgstr "Màgia d'especificació de camí no vàlida '%.*s' en «%s»"
+msgstr "Màgia d'especificació de camí no vàlida «%.*s» en «%s»"
 
 #: pathspec.c:332
 #, c-format
@@ -5728,7 +5714,7 @@
 msgstr "no s'ha pogut desenllaçar: %s"
 
 #: read-cache.c:3179
-#, fuzzy, c-format
+#, c-format
 msgid "cannot fix permission bits on '%s'"
 msgstr "no s'han pogut corregir els bits de permisos en «%s»"
 
@@ -5743,8 +5729,9 @@
 "continue'.\n"
 "Or you can abort the rebase with 'git rebase --abort'.\n"
 msgstr ""
-"Podeu arreglar això amb 'git rebase --edit-todo' i després 'git rebase --"
-"continue'.\n"
+"Podeu arreglar-ho amb «git rebase --edit-todo» i després «git rebase --"
+"continue».\n"
+"O bé, podeu avortar el «rebase» amb «git rebase --abort».\n"
 
 #: rebase-interactive.c:33
 #, c-format
@@ -5776,9 +5763,26 @@
 "\n"
 "These lines can be re-ordered; they are executed from top to bottom.\n"
 msgstr ""
-"Les ordres p select <commit> = fa servir «commit» (commit) «commit» (commit) "
-"«commit» (commit) «commit» (commit) «commit» (commit)"
-
+"\n"
+"Ordres:\n"
+" p, pick <comissió> = usa la comissió\n"
+" r, reword <comissió> = usa la comissió, però edita el missatge de comissió\n"
+" e, edit <comissió> = usa la comissió, però atura't per a esmenar\n"
+" s, squash <comissió> = usa la comissió, però fusiona-la a la comissió prèvia\n"
+" f, fixup <comissió> = com a «squash», però descarta el missatge de registre d'aquesta "
+"comissió\n"
+"x, exec <comissió> = executa l'ordre (la resta de la línia) usant l'intèrpret "
+"d'ordres\n"
+"b, break = atura't aquí (continua fent «rebase» després amb «git rebase --continue»)\n"
+"d, drop <comissió> = elimina la comissió\n"
+"l, label <etiqueta> = etiqueta la HEAD actual amb un nom\n"
+"t, reset <etiqueta> = reinicia HEAD a una etiqueta    \n"
+"m, merge [-C <comissió> | -c <comissió>] <etiqueta> [# <oneline>]\n"
+".       crea una comissió de fusió usant el missatge de la comissió\n"
+".       de fusió original (o línia única, si no hi ha cap comissió de fusió original\n"
+".       especificada). Useu -c <comissió> per a reescriure el missatge de publicació.\n"
+"\n"
+"Es pot canviar l'ordre d'aquestes línies; s'executen de dalt a baix.\n"
 #: rebase-interactive.c:63
 #, c-format
 msgid "Rebase %s onto %s (%d command)"
@@ -5915,37 +5919,37 @@
 #: ref-filter.c:195
 #, c-format
 msgid "unrecognized %%(%s) argument: %s"
-msgstr "paràmetre %%(%s) desconegut: %s"
+msgstr "argument %%(%s) desconegut: %s"
 
 #: ref-filter.c:250
 #, c-format
 msgid "%%(objecttype) does not take arguments"
-msgstr "%%(subject) no accepta paràmetres"
+msgstr "%%(objecttype) no accepta arguments"
 
 #: ref-filter.c:272
 #, c-format
 msgid "unrecognized %%(objectsize) argument: %s"
-msgstr "paràmetre %%(objectsize) no reconegut: %s"
+msgstr "argument %%(objectsize) no reconegut: %s"
 
 #: ref-filter.c:280
 #, c-format
 msgid "%%(deltabase) does not take arguments"
-msgstr "%%(deltabase) no accepta paràmetres"
+msgstr "%%(deltabase) no accepta arguments"
 
 #: ref-filter.c:292
 #, c-format
 msgid "%%(body) does not take arguments"
-msgstr "%%(body) no accepta paràmetres"
+msgstr "%%(body) no accepta arguments"
 
 #: ref-filter.c:301
 #, c-format
 msgid "%%(subject) does not take arguments"
-msgstr "%%(subject) no accepta paràmetres"
+msgstr "%%(subject) no accepta arguments"
 
 #: ref-filter.c:323
 #, c-format
 msgid "unknown %%(trailers) argument: %s"
-msgstr "paràmetre %%(trailers) desconegut: %s"
+msgstr "argument %%(trailers) desconegut: %s"
 
 #: ref-filter.c:352
 #, c-format
@@ -5955,7 +5959,7 @@
 #: ref-filter.c:354
 #, c-format
 msgid "unrecognized %%(contents) argument: %s"
-msgstr "paràmetre %%(contents) no reconegut: %s"
+msgstr "argument %%(contents) no reconegut: %s"
 
 #: ref-filter.c:369
 #, c-format
@@ -5965,7 +5969,7 @@
 #: ref-filter.c:373
 #, c-format
 msgid "unrecognized %%(objectname) argument: %s"
-msgstr "paràmetre %%(objectname) no reconegut: %s"
+msgstr "argument %%(objectname) no reconegut: %s"
 
 #: ref-filter.c:403
 #, c-format
@@ -5985,7 +5989,7 @@
 #: ref-filter.c:431
 #, c-format
 msgid "unrecognized %%(align) argument: %s"
-msgstr "paràmetre %%(align) no reconegut: %s"
+msgstr "argument %%(align) no reconegut: %s"
 
 #: ref-filter.c:439
 #, c-format
@@ -5995,7 +5999,7 @@
 #: ref-filter.c:457
 #, c-format
 msgid "unrecognized %%(if) argument: %s"
-msgstr "paràmetre %%(if) no reconegut: %s"
+msgstr "argument %%(if) no reconegut: %s"
 
 #: ref-filter.c:559
 #, c-format
@@ -6450,7 +6454,7 @@
 #: remote.c:2016
 #, c-format
 msgid "  (use \"%s\" for details)\n"
-msgstr "  (useu  «%s» per detalls)\n"
+msgstr "  (useu «%s» per a detalls)\n"
 
 #: remote.c:2020
 #, c-format
@@ -6461,7 +6465,7 @@
 
 #: remote.c:2026
 msgid "  (use \"git push\" to publish your local commits)\n"
-msgstr "  (useu \"git push\" per a publicar les vostres comissions locals)\n"
+msgstr "  (useu «git push» per a publicar les vostres comissions locals)\n"
 
 #: remote.c:2029
 #, c-format
@@ -6713,7 +6717,7 @@
 #: sequencer.c:316 builtin/rebase.c:743 builtin/rebase.c:1582 builtin/rm.c:385
 #, c-format
 msgid "could not remove '%s'"
-msgstr "no s'ha pogut suprimir «%s»"
+msgstr "no s'ha pogut eliminar «%s»"
 
 #: sequencer.c:326
 msgid "revert"
@@ -6739,7 +6743,7 @@
 "with 'git add <paths>' or 'git rm <paths>'"
 msgstr ""
 "després de resoldre els conflictes, marqueu els camins\n"
-"corregits amb 'git add <camins>' o 'git rm <camins>'"
+"corregits amb «git add <camins>» o «git rm <camins>»"
 
 #: sequencer.c:393
 msgid ""
@@ -6748,8 +6752,8 @@
 "and commit the result with 'git commit'"
 msgstr ""
 "després de resoldre els conflictes, marqueu els camins\n"
-"corregits amb 'git add <camins>' o 'git rm <camins>'\n"
-"i cometeu el resultat amb 'git commit'"
+"corregits amb «git add <camins>» o «git rm <camins>»\n"
+"i cometeu el resultat amb «git commit»"
 
 #: sequencer.c:406 sequencer.c:2921
 #, c-format
@@ -6839,7 +6843,7 @@
 #: sequencer.c:809
 #, c-format
 msgid "unknown variable '%s'"
-msgstr "variable  «%s» desconeguda"
+msgstr "variable «%s» desconeguda"
 
 #: sequencer.c:814
 msgid "missing 'GIT_AUTHOR_NAME'"
@@ -6932,8 +6936,8 @@
 "Comproveu que siguin correctes. Podeu suprimir aquest\n"
 "missatge establint-los explícitament:\n"
 "\n"
-"    git config --global user.name \"El Vostre Nom\"\n"
-"    git config --global user.email tu@example.com\n"
+"    git config --global user.name \"El vostre nom\"\n"
+"    git config --global user.email usuari@example.com\n"
 "\n"
 "Després de fer això, podeu arreglar la identitat usada per a aquesta\n"
 "comissió amb:\n"
@@ -7116,12 +7120,12 @@
 #: sequencer.c:2114
 #, c-format
 msgid "%s does not accept arguments: '%s'"
-msgstr "%s no accepta paràmetres: «%s»"
+msgstr "%s no accepta arguments: «%s»"
 
 #: sequencer.c:2123
 #, c-format
 msgid "missing arguments for %s"
-msgstr "falten els arguments per %s"
+msgstr "falten els arguments per a %s"
 
 #: sequencer.c:2154
 #, c-format
@@ -7515,7 +7519,7 @@
 
 #: sequencer.c:4111
 msgid "could not read 'onto'"
-msgstr "no s'ha pogut llegir 'onto'"
+msgstr "no s'ha pogut llegir «onto»"
 
 #: sequencer.c:4125
 #, c-format
@@ -7624,15 +7628,15 @@
 "Use '--' to separate paths from revisions, like this:\n"
 "'git <command> [<revision>...] -- [<file>...]'"
 msgstr ""
-"paràmetre ambigu «%s»: revisió no coneguda o el camí no és en l'arbre de "
+"argument ambigu «%s»: revisió no coneguda o el camí no és en l'arbre de "
 "treball.\n"
 "Useu «--» per a separar els camins de les revisions:\n"
-"'git <ordre> [<revisió>...] -- [<fitxer>...]'"
+"«git <ordre> [<revisió>...] -- [<fitxer>...]»"
 
 #: setup.c:264
 #, c-format
 msgid "option '%s' must come before non-option arguments"
-msgstr "l'opció «%s» ha de venir abans dels arguments opcionals"
+msgstr "l'opció «%s» ha d'aparèixer abans que els arguments opcionals"
 
 #: setup.c:283
 #, c-format
@@ -7641,9 +7645,9 @@
 "Use '--' to separate paths from revisions, like this:\n"
 "'git <command> [<revision>...] -- [<file>...]'"
 msgstr ""
-"paràmetre ambigu «%s»: ambdós una revisió i un nom de fitxer\n"
-"Useu '--' per a separar els camins de les revisions:\n"
-"'git <ordre> [<revisió>...] -- [<fitxer>...]'"
+"argument ambigu «%s»: ambdós una revisió i un nom de fitxer\n"
+"Useu «--» per a separar els camins de les revisions:\n"
+"«git <ordre> [<revisió>...] -- [<fitxer>...]»"
 
 #: setup.c:419
 msgid "unable to set up work tree using invalid config"
@@ -7672,7 +7676,7 @@
 #: setup.c:598
 #, c-format
 msgid "too large to be a .git file: '%s'"
-msgstr "massa larg per a ser un fitxer .git: «%s»"
+msgstr "massa llarg per a ser un fitxer .git: «%s»"
 
 #: setup.c:600
 #, c-format
@@ -7763,7 +7767,7 @@
 
 #: setup.c:1324
 msgid "setsid failed"
-msgstr "l'«stash» ha fallat"
+msgstr "«setsid» ha fallat"
 
 #: sha1-file.c:470
 #, c-format
@@ -7810,7 +7814,7 @@
 #, c-format
 msgid "reference repository '%s' as a linked checkout is not supported yet."
 msgstr ""
-"Encara no se suporta el dipòsit de referència «%s» com a agafament enllaçat."
+"encara no s'admet el dipòsit de referència «%s» com a agafament enllaçat."
 
 #: sha1-file.c:730
 #, c-format
@@ -8259,13 +8263,13 @@
 msgstr "l'entrada del submòdul «%s» (%s) és a %s, no és una comissió"
 
 #: submodule.c:995
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "Could not run 'git rev-list <commits> --not --remotes -n 1' command in "
 "submodule %s"
 msgstr ""
 "No s'ha pogut executar l'ordre «git rev-list <commits> --not --remotes -n 1» "
-"en els submòdul %s"
+"en el submòdul %s"
 
 #: submodule.c:1118
 #, fuzzy, c-format
@@ -8287,9 +8291,9 @@
 msgstr "No s'ha pogut prémer el submòdul «%s»"
 
 #: submodule.c:1453
-#, fuzzy, c-format
+#, c-format
 msgid "Fetching submodule %s%s\n"
-msgstr "Obtenint submòdul %s%s\n"
+msgstr "S'està obtenint el submòdul %s%s\n"
 
 #: submodule.c:1483
 #, c-format
@@ -8313,12 +8317,12 @@
 #: submodule.c:1679
 #, c-format
 msgid "Could not run 'git status --porcelain=2' in submodule %s"
-msgstr "No s'ha pogut executar «git status --porcelain=2» en els submòdul %s"
+msgstr "No s'ha pogut executar «git status --porcelain=2» en el submòdul %s"
 
 #: submodule.c:1720
 #, c-format
 msgid "'git status --porcelain=2' failed in submodule %s"
-msgstr "«git status --porcelain=2» ha fallat en els submòdul %s"
+msgstr "«git status --porcelain=2» ha fallat en el submòdul %s"
 
 #: submodule.c:1800
 #, c-format
@@ -8328,7 +8332,7 @@
 #: submodule.c:1813
 #, c-format
 msgid "could not run 'git status' in submodule '%s'"
-msgstr "no s'ha pogut executar 'git status' al submòdul «%s»"
+msgstr "no s'ha pogut executar «git status» al submòdul «%s»"
 
 #: submodule.c:1828
 #, fuzzy, c-format
@@ -8358,7 +8362,7 @@
 #: submodule.c:2038
 #, c-format
 msgid "submodule git dir '%s' is inside git dir '%.*s'"
-msgstr "submodule git dir «%s» està dins git dir '%.*s'"
+msgstr "submodule git dir «%s» està dins git dir «%.*s»"
 
 #: submodule.c:2059
 #, c-format
@@ -8417,7 +8421,7 @@
 #: trailer.c:730
 #, c-format
 msgid "empty trailer token in trailer '%.*s'"
-msgstr "testimoni de remolc buit en el remolc '%.*s'"
+msgstr "testimoni de remolc buit en el remolc «%.*s»"
 
 #: trailer.c:750
 #, c-format
@@ -9014,7 +9018,7 @@
 
 #: urlmatch.c:163
 msgid "invalid URL scheme name or missing '://' suffix"
-msgstr "l'esquema d'URL no és vàlid o li manca el sufix '://'"
+msgstr "l'esquema d'URL no és vàlid o li manca el sufix «://»"
 
 #: urlmatch.c:187 urlmatch.c:346 urlmatch.c:405
 #, c-format
@@ -9023,11 +9027,11 @@
 
 #: urlmatch.c:215
 msgid "missing host and scheme is not 'file:'"
-msgstr "manca la màquina i l'esquema no és 'file:'"
+msgstr "manca la màquina i l'esquema no és «file:»"
 
 #: urlmatch.c:232
 msgid "a 'file:' URL may not have a port number"
-msgstr "un URL 'file:' no pot tenir número de port"
+msgstr "un URL «file:» no pot tenir número de port"
 
 #: urlmatch.c:247
 msgid "invalid characters in host name"
@@ -9039,7 +9043,7 @@
 
 #: urlmatch.c:371
 msgid "invalid '..' path segment"
-msgstr "segment de camí '..' no vàlid"
+msgstr "segment de camí «..» no vàlid"
 
 #: walker.c:170
 #, fuzzy
@@ -9107,21 +9111,21 @@
 
 #: wt-status.c:193 wt-status.c:225
 msgid "  (use \"git rm --cached <file>...\" to unstage)"
-msgstr "  (useu \"git rm --cached <fitxer>...\" per a fer «unstage»)"
+msgstr "  (useu «git rm --cached <fitxer>...» per a fer «unstage»)"
 
 #: wt-status.c:197
 msgid "  (use \"git add <file>...\" to mark resolution)"
-msgstr "  (useu \"git add <fitxer>...\" per a senyalar resolució)"
+msgstr "  (useu «git add <fitxer>...» per a senyalar resolució)"
 
 #: wt-status.c:199 wt-status.c:203
 msgid "  (use \"git add/rm <file>...\" as appropriate to mark resolution)"
 msgstr ""
-"  (useu \"git add/rm <fitxer>...\" segons sigui apropiat per a senyalar "
+"  (useu «git add/rm <fitxer>...» segons sigui apropiat per a senyalar "
 "resolució)"
 
 #: wt-status.c:201
 msgid "  (use \"git rm <file>...\" to mark resolution)"
-msgstr "  (useu \"git rm <fitxer>...\" per a senyalar resolució)"
+msgstr "  (useu «git rm <fitxer>...» per a senyalar resolució)"
 
 #: wt-status.c:211 wt-status.c:1072
 msgid "Changes to be committed:"
@@ -9133,11 +9137,11 @@
 
 #: wt-status.c:238
 msgid "  (use \"git add <file>...\" to update what will be committed)"
-msgstr "  (useu \"git add <fitxer>...\" per a actualitzar què es cometrà)"
+msgstr "  (useu «git add <fitxer>...» per a actualitzar què es cometrà)"
 
 #: wt-status.c:240
 msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
-msgstr "  (useu \"git add/rm <fitxer>...\" per a actualitzar què es cometrà)"
+msgstr "  (useu «git add/rm <fitxer>...» per a actualitzar què es cometrà)"
 
 #: wt-status.c:241
 #, fuzzy
@@ -9155,7 +9159,7 @@
 #: wt-status.c:254
 #, c-format
 msgid "  (use \"git %s <file>...\" to include in what will be committed)"
-msgstr "  (useu «git %s <fitxer>...» per a incloure-ho en el que es cometrà)"
+msgstr "  (useu «git %s <fitxer>...» per a incloure-ho en la comissió)"
 
 #: wt-status.c:268
 msgid "both deleted:"
@@ -9249,7 +9253,7 @@
 "Do not modify or remove the line above.\n"
 "Everything below it will be ignored."
 msgstr ""
-"No modifiqueu o suprimiu la línia de dalt.\n"
+"No modifiqueu ni elimineu la línia de dalt.\n"
 "Tot el que hi ha a sota s'ignorarà."
 
 #: wt-status.c:1112
@@ -9268,11 +9272,11 @@
 
 #: wt-status.c:1145
 msgid "  (fix conflicts and run \"git commit\")"
-msgstr "  (arregleu els conflictes i executeu \"git commit\")"
+msgstr "  (arregleu els conflictes i executeu «git commit»)"
 
 #: wt-status.c:1147
 msgid "  (use \"git merge --abort\" to abort the merge)"
-msgstr "  (useu \"git merge --abort\" per a avortar la fusió)"
+msgstr "  (useu «git merge --abort» per a avortar la fusió)"
 
 #: wt-status.c:1151
 msgid "All conflicts fixed but you are still merging."
@@ -9280,7 +9284,7 @@
 
 #: wt-status.c:1154
 msgid "  (use \"git commit\" to conclude merge)"
-msgstr "  (useu \"git commit\" per a concloure la fusió)"
+msgstr "  (useu «git commit» per a concloure la fusió)"
 
 #: wt-status.c:1163
 msgid "You are in the middle of an am session."
@@ -9292,15 +9296,15 @@
 
 #: wt-status.c:1170
 msgid "  (fix conflicts and then run \"git am --continue\")"
-msgstr "  (arregleu els conflictes i després executeu \"git am --continue\")"
+msgstr "  (arregleu els conflictes i després executeu «git am --continue»)"
 
 #: wt-status.c:1172
 msgid "  (use \"git am --skip\" to skip this patch)"
-msgstr "  (useu \"git am --skip\" per a ometre aquest pedaç)"
+msgstr "  (useu «git am --skip» per a ometre aquest pedaç)"
 
 #: wt-status.c:1174
 msgid "  (use \"git am --abort\" to restore the original branch)"
-msgstr "  (useu \"git am --abort\" per a restaurar la branca original)"
+msgstr "  (useu «git am --abort» per a restaurar la branca original)"
 
 #: wt-status.c:1307
 msgid "git-rebase-todo is missing."
@@ -9335,7 +9339,7 @@
 
 #: wt-status.c:1339
 msgid "  (use \"git rebase --edit-todo\" to view and edit)"
-msgstr "  (useu \"git rebase --edit-todo\" per a veure i editar)"
+msgstr "  (useu «git rebase --edit-todo» per a veure i editar)"
 
 #: wt-status.c:1351
 #, c-format
@@ -9378,8 +9382,8 @@
 #: wt-status.c:1392
 msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
 msgstr ""
-"  (Una vegada que el vostre directori de treball sigui net, executeu \"git "
-"rebase --continue\")"
+"  (Una vegada que el vostre directori de treball sigui net, executeu «git "
+"rebase --continue»)"
 
 #: wt-status.c:1396
 #, c-format
@@ -9394,13 +9398,13 @@
 
 #: wt-status.c:1404
 msgid "  (use \"git commit --amend\" to amend the current commit)"
-msgstr "  (useu \"git commit --amend\" per a esmenar la comissió actual)"
+msgstr "  (useu «git commit --amend» per a esmenar la comissió actual)"
 
 #: wt-status.c:1406
 msgid ""
 "  (use \"git rebase --continue\" once you are satisfied with your changes)"
 msgstr ""
-"  (useu \"git rebase --continue\" una vegada que estigueu satisfet amb els "
+"  (useu «git rebase --continue» una vegada que estigueu satisfet amb els "
 "vostres canvis)"
 
 #: wt-status.c:1417
@@ -9417,9 +9421,8 @@
 msgstr "  (arregleu els conflictes i executeu «git cherry-pick --continue»)"
 
 #: wt-status.c:1430
-#, fuzzy
 msgid "  (run \"git cherry-pick --continue\" to continue)"
-msgstr "(executa \"git cherry-pick --continue\" per continuar)"
+msgstr "  (executeu «git cherry-pick --continue» per a continuar)"
 
 #: wt-status.c:1433
 msgid "  (all conflicts fixed: run \"git cherry-pick --continue\")"
@@ -9434,7 +9437,7 @@
 #: wt-status.c:1437
 msgid "  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
 msgstr ""
-"  (useu \"git cherry-pick --abort\" per a cancel·lar l'operació de «cherry "
+"  (useu «git cherry-pick --abort» per a cancel·lar l'operació de «cherry "
 "pick»)"
 
 #: wt-status.c:1447
@@ -9448,27 +9451,24 @@
 
 #: wt-status.c:1456
 msgid "  (fix conflicts and run \"git revert --continue\")"
-msgstr "  (arregleu els conflictes i executeu \"git revert --continue\")"
+msgstr "  (arregleu els conflictes i executeu «git revert --continue»)"
 
 #: wt-status.c:1459
-#, fuzzy
 msgid "  (run \"git revert --continue\" to continue)"
-msgstr "(executa \"git revert --continue\" per continuar)"
+msgstr "  (executeu «git revert --continue» per a continuar)"
 
 #: wt-status.c:1462
 msgid "  (all conflicts fixed: run \"git revert --continue\")"
 msgstr ""
-"  (tots els conflictes estan arreglats: executeu \"git revert --continue\")"
+"  (tots els conflictes estan arreglats: executeu «git revert --continue»)"
 
 #: wt-status.c:1464
-#, fuzzy
 msgid "  (use \"git revert --skip\" to skip this patch)"
-msgstr "(useu \"git revert --skip\" per ometre aquest pedaç)"
+msgstr "  (useu «git revert --skip» per a ometre aquest pedaç)"
 
 #: wt-status.c:1466
 msgid "  (use \"git revert --abort\" to cancel the revert operation)"
-msgstr ""
-"  (useu \"git revert --abort\" per a cancel·lar l'operació de reversió)"
+msgstr "  (useu «git revert --abort» per a cancel·lar l'operació de reversió)"
 
 #: wt-status.c:1476
 #, c-format
@@ -9481,7 +9481,7 @@
 
 #: wt-status.c:1483
 msgid "  (use \"git bisect reset\" to get back to the original branch)"
-msgstr "  (useu \"git bisect reset\" per a tornar a la branca original)"
+msgstr "  (useu «git bisect reset» per a tornar a la branca original)"
 
 #: wt-status.c:1692
 msgid "On branch "
@@ -9523,9 +9523,9 @@
 "new files yourself (see 'git help status')."
 msgstr ""
 "Ha trigat %.2f segons enumerar els fitxers no seguits.\n"
-"'status -uno' pot accelerar-ho, però heu d'anar amb compte de no\n"
+"«status -uno» pot accelerar-ho, però heu d'anar amb compte de no\n"
 "oblidar-vos d'afegir fitxers nous vosaltres mateixos (vegeu\n"
-"'git help status')."
+"«git help status»)."
 
 #: wt-status.c:1755
 #, c-format
@@ -9543,8 +9543,7 @@
 #: wt-status.c:1768
 #, c-format
 msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
-msgstr ""
-"no hi ha canvis afegits a cometre (useu \"git add\" o \"git commit -a\")\n"
+msgstr "no hi ha canvis afegits a cometre (useu «git add» o «git commit -a»)\n"
 
 #: wt-status.c:1771
 #, c-format
@@ -9780,12 +9779,12 @@
 "\n"
 "\tgit submodule add <url> %s\n"
 "\n"
-"Si heu afegit aquest camí per error, podeu suprimir-lo de\n"
+"Si heu afegit aquest camí per error, podeu eliminar-lo de\n"
 "l'índex amb:\n"
 "\n"
 "\tgit rm --cached %s\n"
 "\n"
-"Vegeu \"git help submodule\" per a més informació."
+"Vegeu «git help submodule» per a més informació."
 
 #: builtin/add.c:391
 #, c-format
@@ -9916,20 +9915,19 @@
 #: builtin/am.c:1089
 #, c-format
 msgid "When you have resolved this problem, run \"%s --continue\"."
-msgstr "Quan hàgiu resolt aquest problema, executeu \"%s --continue\"."
+msgstr "Quan hàgiu resolt aquest problema, executeu «%s --continue»."
 
 #: builtin/am.c:1090
 #, c-format
 msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
-msgstr ""
-"Si preferiu ometre aquest pedaç, executeu \"%s --skip\" en lloc d'això."
+msgstr "Si preferiu ometre aquest pedaç, executeu «%s --skip» en lloc d'això."
 
 #: builtin/am.c:1091
 #, c-format
 msgid "To restore the original branch and stop patching, run \"%s --abort\"."
 msgstr ""
-"Per a restaurar la branca original i deixar d'apedaçar, executeu \"%s --abort"
-"\"."
+"Per a restaurar la branca original i deixar d'apedaçar, executeu «%s --"
+"abort»."
 
 #: builtin/am.c:1174
 #, fuzzy
@@ -10035,7 +10033,7 @@
 "If there is nothing left to stage, chances are that something else\n"
 "already introduced the same changes; you might want to skip this patch."
 msgstr ""
-"Cap canvi - heu oblidat d'usar 'git add'?\n"
+"Cap canvi - heu oblidat d'usar «git add»?\n"
 "Si no hi ha res per fer «stage», probablement alguna altra cosa ja ha\n"
 "introduït els mateixos canvis; potser voleu ometre aquest pedaç."
 
@@ -10047,9 +10045,9 @@
 "You might run `git rm` on a file to accept \"deleted by them\" for it."
 msgstr ""
 "Encara teniu camins sense fusionar a l'índex.\n"
-"Heu de fer 'git add' a cada fitxer amb conflictes resolts per marcar-los com "
-"a tal.\n"
-"Podeu executar `git rm` en un fitxer per acceptar \"suprimit per ells\" pel "
+"Heu de fer «git add» a cada fitxer amb conflictes resolts per a marcar-los "
+"com a tal.\n"
+"Podeu executar «git rm» en un fitxer per a acceptar «suprimit per ells» pel "
 "fitxer."
 
 #: builtin/am.c:1928 builtin/am.c:1932 builtin/am.c:1944 builtin/reset.c:347
@@ -10067,7 +10065,7 @@
 "You seem to have moved HEAD since the last 'am' failure.\n"
 "Not rewinding to ORIG_HEAD"
 msgstr ""
-"Sembla que heu mogut HEAD després de l'última fallada de 'am'.\n"
+"Sembla que heu mogut HEAD després de l'última fallada de «am».\n"
 "No s'està rebobinant a ORIG_HEAD"
 
 #: builtin/am.c:2131
@@ -10247,7 +10245,7 @@
 "Use \"git am --abort\" to remove it."
 msgstr ""
 "S'ha trobat un directori %s extraviat.\n"
-"Useu \"git am --abort\" per a eliminar-lo."
+"Useu «git am --abort» per a eliminar-lo."
 
 #: builtin/am.c:2370
 msgid "Resolve operation not in progress, we are not resuming."
@@ -10396,9 +10394,9 @@
 msgstr "Arguments de bisectriu incorrectes"
 
 #: builtin/bisect--helper.c:221
-#, fuzzy, c-format
+#, c-format
 msgid "couldn't get the oid of the rev '%s'"
-msgstr "no s'ha pogut obtenir l'oide de la revista '%s'"
+msgstr "no s'ha pogut obtenir l'oid de la revisió «%s»"
 
 #: builtin/bisect--helper.c:233
 #, fuzzy, c-format
@@ -10426,9 +10424,9 @@
 "You then need to give me at least one %s and %s revision.\n"
 "You can use \"git bisect %s\" and \"git bisect %s\" for that."
 msgstr ""
-"Heu de començar per \"git bisect start\". Després heu de donar-me com a "
-"mínim un per cents i per cents revisió. Podeu utilitzar \"git bisectrius\" i "
-"\"git bisectrius\" per a això."
+"Heu de començar per «git bisect start». \n"
+"Després heu de donar-me com a mínim un per cents i per cents revisió. Podeu "
+"utilitzar «git bisect %s» i «git bisect %s» per a això."
 
 #: builtin/bisect--helper.c:310
 #, c-format
@@ -10462,7 +10460,7 @@
 "invalid argument %s for 'git bisect terms'.\n"
 "Supported options are: --term-good|--term-old and --term-bad|--term-new."
 msgstr ""
-"paràmetre no vàlid %s per a 'git bisect terms'.\n"
+"argument no vàlid %s per a «git bisect terms».\n"
 "Les opcions admeses són: --term-good|--term-old i --term-bad|--term-new."
 
 #: builtin/bisect--helper.c:478
@@ -10483,7 +10481,7 @@
 #, c-format
 msgid "checking out '%s' failed. Try 'git bisect start <valid-branch>'."
 msgstr ""
-"l'agafament de «%s» ha fallat. Proveu «git  bisect start <branca-vàlida>»."
+"l'agafament de «%s» ha fallat. Proveu «git bisect start <branca-vàlida>»."
 
 #: builtin/bisect--helper.c:550
 msgid "won't bisect on cg-seek'ed tree"
@@ -10501,7 +10499,7 @@
 
 #: builtin/bisect--helper.c:633
 msgid "perform 'git bisect next'"
-msgstr "realitza 'git bisect next'"
+msgstr "realitza «git bisect next»"
 
 #: builtin/bisect--helper.c:635
 msgid "write the terms to .git/BISECT_TERMS"
@@ -10556,11 +10554,11 @@
 
 #: builtin/bisect--helper.c:673
 msgid "--write-terms requires two arguments"
-msgstr "--write-terms requereix dos paràmetres"
+msgstr "--write-terms requereix dos arguments"
 
 #: builtin/bisect--helper.c:677
 msgid "--bisect-clean-state requires no arguments"
-msgstr "--bisect-clean-state no accepta paràmetres"
+msgstr "--bisect-clean-state no requereix cap argument"
 
 #: builtin/bisect--helper.c:684
 #, fuzzy
@@ -10834,7 +10832,7 @@
 "If you are sure you want to delete it, run 'git branch -D %s'."
 msgstr ""
 "La branca «%s» no està totalment fusionada.\n"
-"Si esteu segur que la voleu suprimir, executeu 'git branch -D %s'."
+"Si esteu segur que la voleu suprimir, executeu «git branch -D %s»."
 
 #: builtin/branch.c:189
 msgid "Update of config-file failed"
@@ -11135,7 +11133,7 @@
 
 #: builtin/branch.c:790
 msgid "too many arguments for a rename operation"
-msgstr "hi ha massa arguments per a una operació remota"
+msgstr "hi ha massa arguments per a una operació de canvi de nom"
 
 #: builtin/branch.c:795
 msgid "too many arguments to set new upstream"
@@ -11186,8 +11184,8 @@
 "the '--set-upstream' option is no longer supported. Please use '--track' or "
 "'--set-upstream-to' instead."
 msgstr ""
-"L'opció --set-upstream ja no està suportada. Useu en comptes --track o --set-"
-"upstream-to."
+"L'opció --set-upstream ja no s'admet. En lloc seu, useu «--track» o «--set-"
+"upstream-to»."
 
 #: builtin/bundle.c:15 builtin/bundle.c:23
 #, fuzzy
@@ -11944,7 +11942,7 @@
 #: builtin/checkout.c:1697
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
-msgstr "git checkout: --detach no accepta un paràmetre de camí «%s»"
+msgstr "git checkout: --detach no accepta un argument de camí «%s»"
 
 #: builtin/checkout.c:1706
 #, fuzzy
@@ -11990,7 +11988,7 @@
 #: builtin/checkout.c:1757
 #, fuzzy
 msgid "second guess 'git checkout <no-such-branch>' (default)"
-msgstr "segon conjectura 'git checkout <no-such-branch>' (per defecte)"
+msgstr "segon conjectura «git checkout <no-such-branch>» (per defecte)"
 
 #: builtin/checkout.c:1758
 #, fuzzy
@@ -12010,7 +12008,7 @@
 #: builtin/checkout.c:1807
 #, fuzzy
 msgid "second guess 'git switch <no-such-branch>'"
-msgstr "segon conjectura 'git switch <no-such-branch>'"
+msgstr "segon conjectura «git switch <no-such-branch>»"
 
 #: builtin/checkout.c:1809
 #, fuzzy
@@ -12149,9 +12147,9 @@
 "?                   - help for prompt selection"
 msgstr ""
 "clean               - comença a netejar\n"
-"filter by pattern   - exclou ítems de supressió\n"
+"filter by pattern   - exclou ítems de la supressió\n"
 "select by numbers   - selecciona ítems a suprimir per números\n"
-"ask each            - confirma cada supressió (com \"rm -i\")\n"
+"ask each            - confirma cada supressió (com «rm -i»)\n"
 "quit                - deixa de netejar\n"
 "help                - aquesta pantalla\n"
 "?                   - ajuda de selecció de l'avís"
@@ -12478,7 +12476,7 @@
 
 #: builtin/clone.c:971 builtin/receive-pack.c:1972
 msgid "Too many arguments."
-msgstr "Hi ha massa paràmetres."
+msgstr "Hi ha massa arguments."
 
 #: builtin/clone.c:975
 msgid "You must specify a repository to clone."
@@ -12607,7 +12605,7 @@
 
 #: builtin/column.c:51
 msgid "--command must be the first argument"
-msgstr "--command ha de ser el primer paràmetre"
+msgstr "--command ha de ser el primer argument"
 
 #: builtin/commit-graph.c:11 builtin/commit-graph.c:19
 #, fuzzy
@@ -12657,9 +12655,9 @@
 msgstr "No s'ha pogut obrir el graf de comissions «%s»"
 
 #: builtin/commit-graph.c:136
-#, fuzzy, c-format
+#, c-format
 msgid "unrecognized --split argument, %s"
-msgstr "paràmetre --type no reconegut, %s"
+msgstr "argument --split no reconegut, %s"
 
 #: builtin/commit-graph.c:155
 #, fuzzy
@@ -12807,7 +12805,7 @@
 msgstr ""
 "Heu demanat esmenar la comissió més recent, però fer això la\n"
 "deixaria buida. Podeu repetir la vostra ordre amb --allow-empty, o\n"
-"podeu eliminar la comissió per complet amb \"git reset HEAD^\".\n"
+"podeu eliminar la comissió per complet amb «git reset HEAD^».\n"
 
 #: builtin/commit.c:56
 msgid ""
@@ -12817,22 +12815,20 @@
 "    git commit --allow-empty\n"
 "\n"
 msgstr ""
-"El «cherry pick» previ ja està buit, possiblement a causa de resolució de "
-"conflicte.\n"
+"El «cherry pick» previ està ara buit, possiblement a causa de resolució de "
+"conflictes.\n"
 "Si el voleu cometre de totes maneres, useu:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
 
 #: builtin/commit.c:63
-#, fuzzy
 msgid "Otherwise, please use 'git rebase --skip'\n"
-msgstr "Altrament si us plau useu 'git cherry-pick --skip'"
+msgstr "Altrament si us plau useu «git rebase --skip»\n"
 
 #: builtin/commit.c:66
-#, fuzzy
 msgid "Otherwise, please use 'git cherry-pick --skip'\n"
-msgstr "Altrament si us plau useu 'git cherry-pick --skip'"
+msgstr "Altrament si us plau useu «git cherry-pick --skip»\n"
 
 #: builtin/commit.c:69
 #, fuzzy
@@ -12929,7 +12925,7 @@
 #: builtin/commit.c:717 builtin/commit.c:750 builtin/commit.c:1099
 #, c-format
 msgid "could not lookup commit %s"
-msgstr "no s'ha pogut trobar la comissió %s"
+msgstr "no s'ha pogut cercar la comissió %s"
 
 #: builtin/commit.c:729 builtin/shortlog.c:319
 #, c-format
@@ -13047,7 +13043,7 @@
 #: builtin/commit.c:1071
 #, c-format
 msgid "Invalid ignored mode '%s'"
-msgstr "mode ignorat no vàlid «%s»"
+msgstr "Mode ignorat no vàlid «%s»"
 
 #: builtin/commit.c:1089 builtin/commit.c:1333
 #, c-format
@@ -13354,7 +13350,7 @@
 #: builtin/config.c:104 builtin/env--helper.c:23
 #, c-format
 msgid "unrecognized --type argument, %s"
-msgstr "paràmetre --type no reconegut, %s"
+msgstr "argument --type no reconegut, %s"
 
 #: builtin/config.c:116
 msgid "only one type at a time"
@@ -13634,7 +13630,7 @@
 
 #: builtin/config.c:760
 msgid "error processing config file(s)"
-msgstr "s'ha produït un error processant els fitxers de configuració"
+msgstr "s'ha produït un error en processar els fitxers de configuració"
 
 #: builtin/config.c:770
 msgid "editing stdin is not supported"
@@ -13815,11 +13811,11 @@
 
 #: builtin/describe.c:572
 msgid "append <mark> on dirty working tree (default: \"-dirty\")"
-msgstr "annexa <marca> en l'arbre de treball brut (per defecte: \"-dirty\")"
+msgstr "annexa <marca> en l'arbre de treball brut (per defecte: «-dirty»)"
 
 #: builtin/describe.c:575
 msgid "append <mark> on broken working tree (default: \"-broken\")"
-msgstr "annexa <marca> en l'arbre de treball brut (per defecte: \"-broken\")"
+msgstr "annexa <marca> en l'arbre de treball brut (per defecte: «-broken»)"
 
 #: builtin/describe.c:593
 msgid "--long is incompatible with --abbrev=0"
@@ -13888,15 +13884,15 @@
 #: builtin/difftool.c:312
 #, c-format
 msgid "could not read object %s for symlink %s"
-msgstr "No es pot llegir l'objecte %s per l'enllaç simbòlic %s"
+msgstr "no es pot llegir l'objecte %s per l'enllaç simbòlic %s"
 
 #: builtin/difftool.c:413
 msgid ""
 "combined diff formats('-c' and '--cc') are not supported in\n"
 "directory diff mode('-d' and '--dir-diff')."
 msgstr ""
-"els formats de diff combinats ('-c' and '--cc') no són admesos \n"
-"en el mode diff per directoris ('-d' and '--dir-diff')."
+"els formats de diff combinats («-c» i «--cc») no s'admeten\n"
+"en el mode diff per directoris («-d» i «--dir-diff»)."
 
 #: builtin/difftool.c:634
 #, c-format
@@ -13918,7 +13914,7 @@
 
 #: builtin/difftool.c:697
 msgid "use `diff.guitool` instead of `diff.tool`"
-msgstr "utilitza `diff.guitool` en comptes de `diff.tool`"
+msgstr "usa «diff.guitool» en lloc de «diff.tool»"
 
 #: builtin/difftool.c:699
 msgid "perform a full-directory diff"
@@ -13943,14 +13939,14 @@
 #: builtin/difftool.c:710
 msgid "print a list of diff tools that may be used with `--tool`"
 msgstr ""
-"imprimeix una llista de totes les eines diff que podeu usar amb `--tool`"
+"imprimeix una llista de totes les eines diff que podeu usar amb «--tool»"
 
 #: builtin/difftool.c:713
 msgid ""
 "make 'git-difftool' exit when an invoked diff tool returns a non - zero exit "
 "code"
 msgstr ""
-"fes que 'git-difftool' surti quan l'eina de diff invocada torna un codi de "
+"fes que «git-difftool» surti quan l'eina de diff invocada torna un codi de "
 "sortida diferent de zero"
 
 #: builtin/difftool.c:716
@@ -13975,11 +13971,11 @@
 
 #: builtin/difftool.c:750
 msgid "no <tool> given for --tool=<tool>"
-msgstr "no s'ha proporcionat <tool> per --tool=<tool>"
+msgstr "no s'ha proporcionat l'<eina> per a --tool=<eina>"
 
 #: builtin/difftool.c:757
 msgid "no <cmd> given for --extcmd=<cmd>"
-msgstr "no s'ha proporcionat <cmd> per --extcmd=<cmd>"
+msgstr "no s'ha proporcionat l'<ordre> per a --extcmd=<ordre>"
 
 #: builtin/env--helper.c:6
 msgid "git env--helper --type=[bool|ulong] <options> <env-var>"
@@ -14352,7 +14348,7 @@
 " 'git remote prune %s' to remove any old, conflicting branches"
 msgstr ""
 "algunes referències locals no s'han pogut actualitzar;\n"
-" intenteu executar 'git remote prune %s' per a eliminar\n"
+" intenteu executar «git remote prune %s» per a eliminar\n"
 " qualsevol branca antiga o conflictiva"
 
 #: builtin/fetch.c:1128
@@ -14462,7 +14458,7 @@
 
 #: builtin/fetch.c:1798
 msgid "fetch --all does not take a repository argument"
-msgstr "fetch --all no accepta un paràmetre de dipòsit"
+msgstr "fetch --all no accepta un argument de dipòsit"
 
 #: builtin/fetch.c:1800
 msgid "fetch --all does not make sense with refspecs"
@@ -14667,7 +14663,7 @@
 #: builtin/fsck.c:501
 #, c-format
 msgid "%s: invalid reflog entry %s"
-msgstr " %s: entrada de referència no vàlida %s"
+msgstr "%s: entrada de referència no vàlida %s"
 
 #: builtin/fsck.c:515
 #, fuzzy, c-format
@@ -14915,7 +14911,7 @@
 msgid ""
 "There are too many unreachable loose objects; run 'git prune' to remove them."
 msgstr ""
-"Hi ha massa objectes solts inabastables; executeu 'git prune' per a eliminar-"
+"Hi ha massa objectes solts inabastables; executeu «git prune» per a eliminar-"
 "los."
 
 #: builtin/grep.c:30
@@ -14940,7 +14936,7 @@
 #: builtin/pack-objects.c:2855
 #, c-format
 msgid "no threads support, ignoring %s"
-msgstr "no hi ha suport de fils, s'està ignorant %s"
+msgstr "no s'admeten fils, s'ignorarà %s"
 
 #: builtin/grep.c:475 builtin/grep.c:600 builtin/grep.c:640
 #, c-format
@@ -14971,7 +14967,7 @@
 
 #: builtin/grep.c:829
 msgid "ignore files specified via '.gitignore'"
-msgstr "ignora els fitxers especificats mitjançant '.gitignore'"
+msgstr "ignora els fitxers especificats mitjançant «.gitignore»"
 
 #: builtin/grep.c:831
 msgid "recursively search in each submodule"
@@ -15003,7 +14999,7 @@
 
 #: builtin/grep.c:847
 msgid "search in subdirectories (default)"
-msgstr "cerca als subdirectories (per defecte)"
+msgstr "cerca als subdirectoris (per defecte)"
 
 #: builtin/grep.c:849
 msgid "descend at most <depth> levels"
@@ -15163,9 +15159,8 @@
 msgstr "no s'ha pogut resoldre la revisió: %s"
 
 #: builtin/grep.c:1077
-#, fuzzy
 msgid "--untracked not supported with --recurse-submodules"
-msgstr "--untracked no està suportat amb --recurse-submodules"
+msgstr "--untracked no s'admet amb --recurse-submodules"
 
 #: builtin/grep.c:1081
 msgid "invalid option combination, ignoring --threads"
@@ -15173,7 +15168,7 @@
 
 #: builtin/grep.c:1084 builtin/pack-objects.c:3548
 msgid "no threads support, ignoring --threads"
-msgstr "no hi ha suport de fils, s'està ignorant --threads"
+msgstr "no s'admeten fils, s'ignorarà --threads"
 
 #: builtin/grep.c:1087 builtin/index-pack.c:1534 builtin/pack-objects.c:2852
 #, c-format
@@ -15305,7 +15300,7 @@
 "Please consider using 'man.<tool>.cmd' instead."
 msgstr ""
 "«%s»: camí a un visualitzador de manuals no compatible.\n"
-"Considereu usar 'man.<eina>.cmd' en lloc d'això."
+"Considereu usar «man.<eina>.cmd» en lloc d'això."
 
 #: builtin/help.c:319
 #, c-format
@@ -15314,7 +15309,7 @@
 "Please consider using 'man.<tool>.path' instead."
 msgstr ""
 "«%s»: ordre per a un visualitzador de manuals compatible.\n"
-"Considereu usar 'man.<eina>.path' en lloc d'això."
+"Considereu usar «man.<eina>.path» en lloc d'això."
 
 #: builtin/help.c:436
 #, c-format
@@ -15560,7 +15555,7 @@
 #: builtin/index-pack.c:1405
 #, c-format
 msgid "packfile name '%s' does not end with '.pack'"
-msgstr "el nom del fitxer de paquet «%s» no acaba amb '.pack'"
+msgstr "el nom del fitxer de paquet «%s» no acaba amb «.pack»"
 
 #: builtin/index-pack.c:1430
 #, c-format
@@ -16023,7 +16018,7 @@
 
 #: builtin/log.c:1663
 msgid "use <sfx> instead of '.patch'"
-msgstr "usa <sufix> en lloc de '.patch'"
+msgstr "usa <sufix> en lloc de «.patch»"
 
 #: builtin/log.c:1665
 msgid "start numbering patches at <n> instead of 1"
@@ -16281,11 +16276,11 @@
 
 #: builtin/ls-files.c:529
 msgid "use lowercase letters for 'assume unchanged' files"
-msgstr "usa lletres minúscules per als fitxers 'assume unchanged'"
+msgstr "usa lletres minúscules per als fitxers «assume unchanged»"
 
 #: builtin/ls-files.c:531
 msgid "use lowercase letters for 'fsmonitor clean' files"
-msgstr "usa lletres minúscules per als fitxers 'fsmonitor clean'"
+msgstr "usa lletres minúscules per als fitxers «fsmonitor clean»"
 
 #: builtin/ls-files.c:533
 msgid "show cached files in the output (default)"
@@ -16422,7 +16417,7 @@
 
 #: builtin/ls-remote.c:75
 msgid "show underlying ref in addition to the object pointed by it"
-msgstr "mostra la referència subjacent a més de l'objecte que senyali"
+msgstr "mostra la referència subjacent a més de l'objecte que assenyali"
 
 #: builtin/ls-tree.c:30
 msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
@@ -16763,7 +16758,7 @@
 #, c-format
 msgid "Not committing merge; use 'git commit' to complete the merge.\n"
 msgstr ""
-"No s'està cometent la fusió; useu 'git commit' per a completar la fusió.\n"
+"No s'està cometent la fusió; useu «git commit» per a completar la fusió.\n"
 
 #: builtin/merge.c:812
 #, fuzzy
@@ -16839,20 +16834,19 @@
 
 #: builtin/merge.c:1295
 msgid "--abort expects no arguments"
-msgstr "--abort no accepta paràmetres"
+msgstr "--abort no espera cap argument"
 
 #: builtin/merge.c:1299
 msgid "There is no merge to abort (MERGE_HEAD missing)."
 msgstr "No hi ha fusió a avortar (manca MERGE_HEAD)."
 
 #: builtin/merge.c:1317
-#, fuzzy
 msgid "--quit expects no arguments"
 msgstr "--quit no espera cap argument"
 
 #: builtin/merge.c:1330
 msgid "--continue expects no arguments"
-msgstr "--continue no accepta paràmetres"
+msgstr "--continue no espera cap argument"
 
 #: builtin/merge.c:1334
 msgid "There is no merge in progress (MERGE_HEAD missing)."
@@ -17015,12 +17009,11 @@
 
 #: builtin/multi-pack-index.c:50 builtin/prune-packed.c:25
 msgid "too many arguments"
-msgstr "hi ha massa paràmetres"
+msgstr "hi ha massa arguments"
 
 #: builtin/multi-pack-index.c:60
-#, fuzzy
 msgid "--batch-size option is only for 'repack' subcommand"
-msgstr "--batch-size l'opció només és per la subordre 'repack'"
+msgstr "--batch-size l'opció només és per a la subordre «repack»"
 
 #: builtin/multi-pack-index.c:69
 #, fuzzy, c-format
@@ -17294,7 +17287,7 @@
 #: builtin/notes.c:162
 #, c-format
 msgid "failed to finish 'show' for object '%s'"
-msgstr "S'ha produït un error en finalitzar 'show' per a l'objecte «%s»"
+msgstr "S'ha produït un error en finalitzar «show» per a l'objecte «%s»"
 
 #: builtin/notes.c:197
 msgid "please supply the note contents using either -m or -F option"
@@ -17437,7 +17430,7 @@
 "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
 "Please use 'git notes add -f -m/-F/-c/-C' instead.\n"
 msgstr ""
-"Es desaconsellen les opcions -m/-F/-c/-C en favor de la subordre 'edit'.\n"
+"Es desaconsellen les opcions -m/-F/-c/-C en favor de la subordre «edit».\n"
 "Useu «git notes add -f -m/-F/-c/-C» en lloc d'això.\n"
 
 #: builtin/notes.c:698
@@ -17451,7 +17444,7 @@
 #: builtin/notes.c:702
 msgid "failed to remove 'git notes merge' worktree"
 msgstr ""
-"s'ha produït un error en eliminar l'arbre de treball de 'git notes merge'"
+"s'ha produït un error en eliminar l'arbre de treball de «git notes merge»"
 
 #: builtin/notes.c:722
 msgid "failed to read ref NOTES_MERGE_PARTIAL"
@@ -17543,8 +17536,8 @@
 "abort'.\n"
 msgstr ""
 "La fusió de notes automàtica ha fallat. Arregleu els conflictes en %s i "
-"cometeu el resultat amb 'git notes merge --commit', o avorteu la fusió amb "
-"'git notes merge --abort'.\n"
+"cometeu el resultat amb «git notes merge --commit», o avorteu la fusió amb "
+"«git notes merge --abort».\n"
 
 #: builtin/notes.c:897 builtin/tag.c:546
 #, c-format
@@ -17818,7 +17811,7 @@
 
 #: builtin/pack-objects.c:3410
 msgid "read revision arguments from standard input"
-msgstr "llegeix els paràmetres de revisió des de l'entrada estàndard"
+msgstr "llegeix els arguments de revisió des de l'entrada estàndard"
 
 #: builtin/pack-objects.c:3412
 msgid "limit the objects to those that are not yet packed"
@@ -18117,7 +18110,7 @@
 
 #: builtin/pull.c:475 builtin/pull.c:490
 msgid "See git-pull(1) for details."
-msgstr "Vegeu git-pull(1) per detalls."
+msgstr "Vegeu git-pull(1) per a més informació."
 
 #: builtin/pull.c:477 builtin/pull.c:483 builtin/pull.c:492
 #: builtin/rebase.c:1240 git-parse-remote.sh:64
@@ -18232,8 +18225,8 @@
 "To choose either option permanently, see push.default in 'git help config'."
 msgstr ""
 "\n"
-"Per a triar qualsevol opció permanentment, vegeu push.default a 'git help "
-"config'."
+"Per a triar qualsevol opció permanentment, vegeu push.default a «git help "
+"config»."
 
 #: builtin/push.c:171
 #, c-format
@@ -18321,8 +18314,9 @@
 msgstr ""
 "S'han rebutjat les actualitzacions perquè el punt de la vostra branca\n"
 "actual està darrere de la seva branca remota corresponent. Integreu\n"
-"els canvis remots (per exemple, 'git pull ...') abans de pujar de nou.\n"
-"Vegeu la 'Nota sobre avanços ràpids' a 'git push --help' per detalls."
+"els canvis remots (per exemple, «git pull ...») abans de pujar de nou.\n"
+"Vegeu la «Nota sobre avanços ràpids» a «git push --help» per a més "
+"informació."
 
 #: builtin/push.c:283
 msgid ""
@@ -18333,9 +18327,10 @@
 msgstr ""
 "S'han rebutjat les actualitzacions perquè un punt de branca pujada\n"
 "està darrere de la seva branca remota corresponent. Agafeu aquesta\n"
-"branca i integreu els canvis remots (per exemple, 'git pull ...')\n"
+"branca i integreu els canvis remots (per exemple, «git pull ...»)\n"
 "abans de pujar de nou.\n"
-"Vegeu la 'Nota sobre avanços ràpids' a 'git push --help' per detalls."
+"Vegeu la «Nota sobre avanços ràpids» a «git push --help» per a més "
+"informació."
 
 #: builtin/push.c:289
 msgid ""
@@ -18348,9 +18343,10 @@
 "S'han rebutjat les actualitzacions perquè el remot conté canvis\n"
 "que no teniu localment. Això acostuma a ser causat per un altre dipòsit\n"
 "que ha pujat a la mateixa referència. Pot ser que primer vulgueu\n"
-"integrar els canvis remots (per exemple, 'git pull ...') abans de\n"
+"integrar els canvis remots (per exemple, «git pull ...») abans de\n"
 "pujar de nou.\n"
-"Vegeu la 'Nota sobre avanços ràpids' a 'git push --help' per detalls."
+"Vegeu la «Nota sobre avanços ràpids» a «git push --help» per a més "
+"informació."
 
 #: builtin/push.c:296
 msgid "Updates were rejected because the tag already exists in the remote."
@@ -18366,7 +18362,7 @@
 "No podeu actualitzar una referència remota que assenyala un\n"
 "objecte no de comissió, ni actualitzar una referència remota per\n"
 "fer que assenyali un objecte no de comissió, sense usar l'opció\n"
-"'--force'.\n"
+"«--force».\n"
 
 #: builtin/push.c:361
 #, c-format
@@ -18916,8 +18912,8 @@
 "\n"
 msgstr ""
 "%s\n"
-"Especifiqueu sobre què branca voleu fer «rebase».\n"
-"Vegeu git-rebase(1) per detalls.\n"
+"Especifiqueu sobre quina branca voleu fer «rebase».\n"
+"Vegeu git-rebase(1) per a més informació.\n"
 "\n"
 "    git rebase '<branca>'\n"
 "\n"
@@ -18933,7 +18929,7 @@
 "Si voleu establir informació de seguiment per a aquesta branca, podeu fer-ho "
 "amb:\n"
 "\n"
-"    git branch --set-upstream-to=%s/<branch> %s\n"
+"    git branch --set-upstream-to=%s/<branca> %s\n"
 "\n"
 
 #: builtin/rebase.c:1272
@@ -19208,7 +19204,7 @@
 
 #: builtin/rebase.c:1824
 msgid "Could not create new root commit"
-msgstr "no s'ha pogut crear una comissió arrel nova"
+msgstr "No s'ha pogut crear una comissió arrel nova"
 
 #: builtin/rebase.c:1850
 #, fuzzy, c-format
@@ -19275,7 +19271,7 @@
 #: builtin/rebase.c:2001
 #, c-format
 msgid "Changes to %s:\n"
-msgstr "Canvis a  %s:\n"
+msgstr "Canvis a %s:\n"
 
 #: builtin/rebase.c:2004
 #, c-format
@@ -19319,18 +19315,18 @@
 "'receive.denyCurrentBranch' configuration variable to 'refuse'."
 msgstr ""
 "Per defecte, es denega actualitzar la branca actual en un dipòsit no\n"
-"nu, perquè faria l'índex i l'arbre de treball inconsistents amb el\n"
-"que hàgiu pujat, i requeriria 'git reset --hard' per a fer que\n"
-"l'arbre de treball coincideixi amb HEAD.\n"
+"nu, perquè faria l'índex i l'arbre de treball inconsistents amb allò\n"
+"que hàgiu pujat, i requeriria «git reset --hard» per a fer que\n"
+"l'arbre de treball coincidís amb HEAD.\n"
 "\n"
 "Podeu establir la variable de configuració\n"
 "«receive.denyCurrentBranch» a «ignore» o «warn» en el dipòsit remot\n"
-"per a permetre pujar a la seva branca actual; no obstant, no es\n"
-"recomana això a menys que hàgiu decidit actualitzar el seu arbre en\n"
-"alguna altra manera per a coincidir amb el que hàgiu pujat.\n"
+"per a permetre pujar a la seva branca actual; això no obstant, no es\n"
+"recomana a menys que hàgiu decidit actualitzar el seu arbre de treball\n"
+"per a coincidir amb allò que hàgiu pujat d'alguna altra manera.\n"
 "\n"
 "Per a silenciar aquest missatge i mantenir el comportament\n"
-"predeterminat, establiu la variable de configuració\n"
+"per defecte, establiu la variable de configuració\n"
 "«receive.denyCurrentBranch» a «refuse»."
 
 #: builtin/receive-pack.c:863
@@ -19345,7 +19341,7 @@
 "To squelch this message, you can set it to 'refuse'."
 msgstr ""
 "Per defecte, es denega suprimir la branca actual, perquè el\n"
-"'git clone' següent no resultarà en cap fitxer agafat, causant\n"
+"«git clone» següent no resultarà en cap fitxer agafat, causant\n"
 "confusió.\n"
 "\n"
 "Podeu establir la variable de configuració\n"
@@ -19369,20 +19365,21 @@
 "rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] "
 "<refs>..."
 msgstr ""
-"git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--"
+"git reflog expire [--expire=<hora>] [--expire-unreachable=<hora>] [--"
 "rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] "
+"<referències>..."
 
 #: builtin/reflog.c:22
 msgid ""
 "git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] "
 "<refs>..."
 msgstr ""
-"git reflog remove [--rewrite] [--updateref] [---dry-run | -n] [--verbose] "
-"<refs>"
+"git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] "
+"<referències>..."
 
 #: builtin/reflog.c:25
 msgid "git reflog exists <ref>"
-msgstr "git reflog exists <ref>"
+msgstr "git reflog exists <referència>"
 
 #: builtin/reflog.c:568 builtin/reflog.c:573
 #, c-format
@@ -19420,9 +19417,8 @@
 msgstr "format de referència no vàlid: %s"
 
 #: builtin/reflog.c:765
-#, fuzzy
 msgid "git reflog [ show | expire | delete | exists ]"
-msgstr "git reflog [ mostra | expira | suprimeix | existeix ]"
+msgstr "git reflog [ show | expire | delete | exists ]"
 
 #: builtin/remote.c:17
 msgid "git remote [-v | --verbose]"
@@ -19523,7 +19519,7 @@
 #: builtin/remote.c:148
 #, c-format
 msgid "unknown mirror argument: %s"
-msgstr "paràmetre de reflexió desconegut: %s"
+msgstr "argument de «mirror» desconegut: %s"
 
 #: builtin/remote.c:164
 msgid "fetch the remote branches"
@@ -19665,7 +19661,7 @@
 
 #: builtin/remote.c:998
 msgid " stale (use 'git remote prune' to remove)"
-msgstr " estancat (useu 'git remote prune' per a eliminar)"
+msgstr " estancat (useu «git remote prune» per a eliminar)"
 
 #: builtin/remote.c:1000
 msgid " ???"
@@ -19823,11 +19819,11 @@
 
 #: builtin/remote.c:1318
 msgid "set refs/remotes/<name>/HEAD according to remote"
-msgstr "estableix refs/remotes/<name>/HEAD segons el remot"
+msgstr "estableix refs/remotes/<nom>/HEAD segons el remot"
 
 #: builtin/remote.c:1320
 msgid "delete refs/remotes/<name>/HEAD"
-msgstr "suprimeix refs/remotes/<name>/HEAD"
+msgstr "suprimeix refs/remotes/<nom>/HEAD"
 
 #: builtin/remote.c:1335
 msgid "Cannot determine remote HEAD"
@@ -19951,8 +19947,8 @@
 "Incremental repacks are incompatible with bitmap indexes.  Use\n"
 "--no-write-bitmap-index or disable the pack.writebitmaps configuration."
 msgstr ""
-"Els reempaquetaments incrementals són incompatibles amb els índexs de "
-"bitmaps.  Useu\n"
+"Els reempaquetaments incrementals són incompatibles amb els índexs de mapes "
+"de bits.  Useu\n"
 "--no-write-bitmap-index o inhabiliteu el paràmetre de configuració pack."
 "writebitmaps."
 
@@ -20075,7 +20071,7 @@
 msgstr "Res nou per empaquetar."
 
 #: builtin/repack.c:488
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "WARNING: Some packs in use have been renamed by\n"
 "WARNING: prefixing old- to their name, in order to\n"
@@ -20085,11 +20081,13 @@
 "WARNING: original names also failed.\n"
 "WARNING: Please rename them in %s manually:\n"
 msgstr ""
-"AVÍS Alguns paquets en ús s'han reanomenat ALERTA prefixant «old-» al seu "
-"nom per tal d' AVÍS reemplaçar-los per la nova versió del fitxer ALERTA. "
-"Però l'operació ha fallat i l'intent ALERTA de tornar-los a canviar el nom "
-"també ha fallat en el seu ALERTA els noms originals. AVÍS Els reanomeneu "
-"manualment en percentatges"
+"AVÍS: Alguns paquets en ús han canviat de nom\n"
+"AVÍS: prefixant «old-» al seu nom per tal de\n"
+"AVÍS: reemplaçar-los per la nova versió del fitxer.\n"
+"AVÍS: Però l'operació ha fallat i l'intent de\n"
+"AVÍS: tornar-los a canviar als seus noms originals\n"
+"AVÍS: també ha fallat. Canvieu-los de nom en %s\n"
+"AVÍS: manualment:\n"
 
 #: builtin/repack.c:536
 #, c-format
@@ -20479,7 +20477,7 @@
 #: builtin/reset.c:371
 msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
 msgstr ""
-"--mixed amb camins està en desús; useu 'git reset -- <camins>' en lloc "
+"--mixed amb camins està en desús; useu «git reset -- <camins>» en lloc "
 "d'això."
 
 #: builtin/reset.c:373
@@ -20540,15 +20538,15 @@
 
 #: builtin/rev-parse.c:409
 msgid "git rev-parse --parseopt [<options>] -- [<args>...]"
-msgstr "git rev-parse --parseopt [<opcions>] -- [<paràmetres>...]"
+msgstr "git rev-parse --parseopt [<opcions>] -- [<arguments>...]"
 
 #: builtin/rev-parse.c:414
 msgid "keep the `--` passed as an arg"
-msgstr "retén el «--» passat com a paràmetre"
+msgstr "retén el «--» passat com a argument"
 
 #: builtin/rev-parse.c:416
 msgid "stop parsing after the first non-option argument"
-msgstr "deixa d'analitzar després del primer paràmetre no d'opció"
+msgstr "deixa d'analitzar després del primer argument que no sigui d'opció"
 
 #: builtin/rev-parse.c:419
 msgid "output in stuck long form"
@@ -20562,12 +20560,12 @@
 "\n"
 "Run \"git rev-parse --parseopt -h\" for more information on the first usage."
 msgstr ""
-"git rev-parse --parseopt [<opcions>] -- [<paràmetres>...]\n"
-"   or: git rev-parse --sq-quote [<paràmetre>...]\n"
-"   or: git rev-parse [<opcions>] [<paràmetre>...]\n"
+"git rev-parse --parseopt [<opcions>] -- [<arguments>...]\n"
+"   o bé: git rev-parse --sq-quote [<argument>...]\n"
+"   o bé: git rev-parse [<opcions>] [<argument>...]\n"
 "\n"
-"Executeu \"git rev-parse --parseopt -h\" per més informació sobre l'ús "
-"inicial."
+"Executeu «git rev-parse --parseopt -h» per a més informació sobre el primer "
+"ús."
 
 #: builtin/revert.c:24
 msgid "git revert [<options>] <commit-ish>..."
@@ -20736,7 +20734,7 @@
 #: builtin/rm.c:323
 #, c-format
 msgid "not removing '%s' recursively without -r"
-msgstr "no s'ha suprimit «%s» recursivament sense -r"
+msgstr "no s'eliminarà «%s» recursivament sense -r"
 
 #: builtin/rm.c:362
 #, c-format
@@ -20846,7 +20844,7 @@
 
 #: builtin/show-branch.c:649
 msgid "color '*!+-' corresponding to the branch"
-msgstr "colora '*!+-' corresponent a la branca"
+msgstr "colora «*!+-» corresponent a la branca"
 
 #: builtin/show-branch.c:651
 msgid "show <n> more commits after the common ancestor"
@@ -21212,7 +21210,7 @@
 
 #: builtin/stash.c:828
 msgid "\"git stash store\" requires one <commit> argument"
-msgstr "«git stash store» requereix un paràmetre <comissió>"
+msgstr "«git stash store» requereix un argument <comissió>"
 
 #: builtin/stash.c:1046
 msgid "No changes selected"
@@ -21495,7 +21493,7 @@
 "really want to remove it including all of its history)"
 msgstr ""
 "L'arbre de treball de submòdul «%s» conté un directori .git\n"
-"(useu 'rm -rf' si realment voleu eliminar-lo, incloent tota la seva història)"
+"(useu «rm -rf» si realment voleu eliminar-lo, incloent tota la seva història)"
 
 #: builtin/submodule--helper.c:1134
 #, c-format
@@ -21509,7 +21507,7 @@
 #: builtin/submodule--helper.c:1142
 #, c-format
 msgid "Cleared directory '%s'\n"
-msgstr "S'ha netejat el directori «%s»\n"
+msgstr "S'ha esborrat el directori «%s»\n"
 
 #: builtin/submodule--helper.c:1144
 #, c-format
@@ -21529,7 +21527,7 @@
 #: builtin/submodule--helper.c:1200
 msgid "Remove submodule working trees even if they contain local changes"
 msgstr ""
-"Suprimeix els arbres de treball dels submòduls fins i tot si contenen canvis "
+"Elimina els arbres de treball dels submòduls fins i tot si contenen canvis "
 "locals"
 
 #: builtin/submodule--helper.c:1201
@@ -21544,7 +21542,7 @@
 
 #: builtin/submodule--helper.c:1220
 msgid "Use '--all' if you really want to deinitialize all submodules"
-msgstr "Useu '--all' si realment voleu desinicialitzar tots els submòduls"
+msgstr "Useu «--all» si realment voleu desinicialitzar tots els submòduls"
 
 #: builtin/submodule--helper.c:1289
 #, fuzzy
@@ -21647,7 +21645,7 @@
 
 #: builtin/submodule--helper.c:1621
 msgid "Maybe you want to use 'update --init'?"
-msgstr "Potser voleu usar 'update --init'?"
+msgstr "Potser voleu usar «update --init»?"
 
 #: builtin/submodule--helper.c:1651
 #, c-format
@@ -22056,33 +22054,34 @@
 #: builtin/update-index.c:154
 msgid "directory stat info does not change after adding a new file"
 msgstr ""
-"la informació d'stat de directori no canvia després d'afegir un fitxer nou"
+"la informació de stat de directori no canvia després d'afegir un fitxer nou"
 
 #: builtin/update-index.c:167
 msgid "directory stat info does not change after adding a new directory"
 msgstr ""
-"la informació d'stat de directori no canvia després d'afegir un directori nou"
+"la informació de stat de directori no canvia després d'afegir un directori "
+"nou"
 
 #: builtin/update-index.c:180
 msgid "directory stat info changes after updating a file"
 msgstr ""
-"la informació d'stat de directori canvia després d'actualitzar un fitxer"
+"la informació de stat de directori canvia després d'actualitzar un fitxer"
 
 #: builtin/update-index.c:191
 msgid "directory stat info changes after adding a file inside subdirectory"
 msgstr ""
-"la informació d'stat de directori canvia després d'afegir un fitxer dins "
+"la informació de stat de directori canvia després d'afegir un fitxer dins "
 "d'un subdirectori"
 
 #: builtin/update-index.c:202
 msgid "directory stat info does not change after deleting a file"
 msgstr ""
-"la informació d'stat de directori no canvia després de suprimir un fitxer"
+"la informació de stat de directori no canvia després de suprimir un fitxer"
 
 #: builtin/update-index.c:215
 msgid "directory stat info does not change after deleting a directory"
 msgstr ""
-"la informació d'stat de directori no canvia després de suprimir un directori"
+"la informació de stat de directori no canvia després de suprimir un directori"
 
 #: builtin/update-index.c:222
 msgid " OK"
@@ -22135,19 +22134,19 @@
 
 #: builtin/update-index.c:1008
 msgid "mark files as \"not changing\""
-msgstr "marca els fitxers com a \"no canviant\""
+msgstr "marca els fitxers com a «no canviant»"
 
 #: builtin/update-index.c:1011
 msgid "clear assumed-unchanged bit"
-msgstr "neteja el bit assumed-unchanged"
+msgstr "esborra el bit assumed-unchanged"
 
 #: builtin/update-index.c:1014
 msgid "mark files as \"index-only\""
-msgstr "marca els fitxers com a \"només índex\""
+msgstr "marca els fitxers com a «només índex»"
 
 #: builtin/update-index.c:1017
 msgid "clear skip-worktree bit"
-msgstr "neteja el bit skip-worktree"
+msgstr "esborra el bit skip-worktree"
 
 #: builtin/update-index.c:1020
 #, fuzzy
@@ -22233,7 +22232,7 @@
 
 #: builtin/update-index.c:1070
 msgid "clear fsmonitor valid bit"
-msgstr "neteja el bit de validesa del fsmonitor"
+msgstr "esborra el bit de validesa del fsmonitor"
 
 #: builtin/update-index.c:1173
 msgid ""
@@ -22320,7 +22319,7 @@
 
 #: builtin/update-ref.c:490
 msgid "stdin has NUL-terminated arguments"
-msgstr "stdin té paràmetres acabats amb NUL"
+msgstr "stdin té arguments acabats amb NUL"
 
 #: builtin/update-ref.c:491
 msgid "read updates from stdin"
@@ -22389,7 +22388,7 @@
 
 #: builtin/worktree.c:17
 msgid "git worktree add [<options>] <path> [<commit-ish>]"
-msgstr "git worktree add [<opcions>] <camí> [<commit-ish>"
+msgstr "git worktree add [<opcions>] <camí> [<commit-ish>]"
 
 #: builtin/worktree.c:18
 msgid "git worktree list [<options>]"
@@ -22409,7 +22408,7 @@
 
 #: builtin/worktree.c:22
 msgid "git worktree remove [<options>] <worktree>"
-msgstr "git worktree lock [<opcions>] <arbre de treball>"
+msgstr "git worktree remove [<opcions>] <arbre de treball>"
 
 #: builtin/worktree.c:23
 msgid "git worktree unlock <path>"
@@ -22441,8 +22440,8 @@
 "Removing worktrees/%s: short read (expected %<PRIuMAX> bytes, read "
 "%<PRIuMAX>)"
 msgstr ""
-"S'estan suprimint els arbres de treball/%s: lectura curta (s'esperaven "
-"%<PRIuMAX> bytes, llegits %<PRIuMAX>)"
+"S'estan eliminant els arbres de treball/%s: lectura curta (s'esperaven "
+"%<PRIuMAX> bytes, se n'han llegit %<PRIuMAX>)"
 
 #: builtin/worktree.c:117
 #, c-format
@@ -22589,7 +22588,7 @@
 #: builtin/worktree.c:766
 msgid "working trees containing submodules cannot be moved or removed"
 msgstr ""
-"els arbres de treball que contenen submòduls no es poden moure o suprimir"
+"els arbres de treball que contenen submòduls no es poden moure ni eliminar"
 
 #: builtin/worktree.c:774
 msgid "force move even if worktree is dirty or locked"
@@ -22658,7 +22657,7 @@
 #: builtin/worktree.c:906
 msgid "force removal even if worktree is dirty or locked"
 msgstr ""
-"força la supressió encara que l'arbre de treball estigui brut o bloquejat"
+"força l'eliminació encara que l'arbre de treball estigui brut o bloquejat"
 
 #: builtin/worktree.c:929
 #, fuzzy, c-format
@@ -22834,7 +22833,7 @@
 
 #: t/helper/test-reach.c:162
 msgid "too many commits marked reachable"
-msgstr "masses comission marcades com abastable"
+msgstr "hi ha massa comissions marcades com abastables"
 
 #: t/helper/test-serve-v2.c:7
 msgid "test-tool serve-v2 [<options>]"
@@ -22911,12 +22910,12 @@
 msgstr "en expandir l'àlies '%s' '%s'"
 
 #: git.c:371
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "alias '%s' changes environment variables.\n"
 "You can use '!git' in the alias to do this"
 msgstr ""
-"àlies '%s' canvia variables d'entorn. Podeu utilitzar '!git' a l'àlies per "
+"àlies «%s» canvia variables d'entorn. Podeu utilitzar «!git» a l'àlies per a "
 "fer-ho"
 
 #: git.c:378
@@ -22981,7 +22980,7 @@
 
 #: http.c:429
 msgid "Public key pinning not supported with cURL < 7.44.0"
-msgstr "No s'admet l'enganx de clau pública amb cURL < 7.44.0"
+msgstr "No s'admet la fixació de clau pública amb cURL < 7.44.0"
 
 #: http.c:914
 #, fuzzy
@@ -23156,7 +23155,7 @@
 
 #: list-objects-filter-options.h:85
 msgid "args"
-msgstr "args"
+msgstr "arguments"
 
 #: list-objects-filter-options.h:86
 msgid "object filtering"
@@ -23210,7 +23209,7 @@
 #: rerere.h:44
 msgid "update the index with reused conflict resolution if possible"
 msgstr ""
-"actualitza l'índex amb la resolució de conflicte reusada si és possible"
+"actualitza l'índex amb la resolució de conflictes reusada si és possible"
 
 #: wt-status.h:80
 msgid "HEAD detached at "
@@ -23311,7 +23310,7 @@
 
 #: command-list.h:71
 msgid "Remove untracked files from the working tree"
-msgstr "Suprimeix els fitxers no seguits de l'arbre de treball"
+msgstr "Elimina els fitxers no seguits de l'arbre de treball"
 
 #: command-list.h:72
 msgid "Clone a repository into a new directory"
@@ -23561,7 +23560,7 @@
 #: command-list.h:127
 msgid "Run merge conflict resolution tools to resolve merge conflicts"
 msgstr ""
-"Executa eines de resolució de conflictes per a resoldre conflictes de fussió"
+"Executa eines de resolució de conflictes per a resoldre conflictes de fusió"
 
 #: command-list.h:128
 #, fuzzy
@@ -23620,16 +23619,15 @@
 
 #: command-list.h:140
 msgid "Compute unique ID for a patch"
-msgstr "Calcula un identificador única per a cada pedaç"
+msgstr "Calcula un identificador únic per a cada pedaç"
 
 #: command-list.h:141
 msgid "Prune all unreachable objects from the object database"
 msgstr "Poda tots els objectes no accessibles de la base de dades d'objectes"
 
 #: command-list.h:142
-#, fuzzy
 msgid "Remove extra objects that are already in pack files"
-msgstr "Elimina els objectes extres que ja estan en fitxers de paquet"
+msgstr "Elimina els objectes extres que ja estan en fitxers empaquetats"
 
 #: command-list.h:143
 msgid "Fetch from and integrate with another repository or a local branch"
@@ -23652,7 +23650,6 @@
 "Compara dos intervals de comissions (p. ex. dues versions d'una branca)"
 
 #: command-list.h:147
-#, fuzzy
 msgid "Reads tree information into the index"
 msgstr "Llegeix la informació de l'arbre a l'índex"
 
@@ -23666,19 +23663,16 @@
 msgstr "Rep el que s'envia al repositori"
 
 #: command-list.h:150
-#, fuzzy
 msgid "Manage reflog information"
 msgstr "Gestiona la informació del registre de referències"
 
 #: command-list.h:151
-#, fuzzy
 msgid "Manage set of tracked repositories"
-msgstr "Gestiona el conjunt de repositoris seguits"
+msgstr "Gestiona el conjunt de dipòsits seguits"
 
 #: command-list.h:152
-#, fuzzy
 msgid "Pack unpacked objects in a repository"
-msgstr "Empaqueta els objectes desempaquetats en un repositori"
+msgstr "Empaqueta els objectes desempaquetats en un dipòsit"
 
 #: command-list.h:153
 #, fuzzy
@@ -23686,14 +23680,12 @@
 msgstr "Crea una llista suprimeix les referències per substituir els objectes"
 
 #: command-list.h:154
-#, fuzzy
 msgid "Generates a summary of pending changes"
 msgstr "Genera un resum dels canvis pendents"
 
 #: command-list.h:155
-#, fuzzy
 msgid "Reuse recorded resolution of conflicted merges"
-msgstr "Reutilitza la resolució registrada dels fusionats en conflicte"
+msgstr "Reutilitza la resolució registrada dels conflictes de fusió"
 
 #: command-list.h:156
 msgid "Reset current HEAD to the specified state"
@@ -23713,7 +23705,7 @@
 
 #: command-list.h:160
 msgid "Pick out and massage parameters"
-msgstr "Escolliu i personalitzeu els paràmetres"
+msgstr "Trieu i personalitzeu els paràmetres"
 
 #: command-list.h:161
 msgid "Remove files from the working tree and from the index"
@@ -23728,9 +23720,8 @@
 msgstr "Puja objectes sobre el protocol Git a un altre dipòsit"
 
 #: command-list.h:164
-#, fuzzy
 msgid "Restricted login shell for Git-only SSH access"
-msgstr "Intèrpret d'ordres d'entrada restringit per a accés SSH només al Git"
+msgstr "Intèrpret d'ordres d'entrada restringit només per a accés SSH al Git"
 
 #: command-list.h:165
 msgid "Summarize 'git log' output"
@@ -23753,7 +23744,6 @@
 msgstr "Llista les referències en un dipòsit local"
 
 #: command-list.h:170
-#, fuzzy
 msgid "Git's i18n setup code for shell scripts"
 msgstr ""
 "Codi de configuració i18n del Git per als scripts de l'intèrpret d'ordres"
@@ -23773,9 +23763,8 @@
 msgstr "Desa els canvis en un directori de treball brut"
 
 #: command-list.h:174
-#, fuzzy
 msgid "Add file contents to the staging area"
-msgstr "Afegeix el contingut del fitxer a l'àrea de proves"
+msgstr "Afegeix el contingut del fitxer a l'àrea de «staging»"
 
 #: command-list.h:175
 msgid "Show the working tree status"
@@ -23783,7 +23772,7 @@
 
 #: command-list.h:176
 msgid "Remove unnecessary whitespace"
-msgstr "Suprimeix l'espai en blanc innecessari"
+msgstr "Elimina l'espai en blanc innecessari"
 
 #: command-list.h:177
 msgid "Initialize, update or inspect submodules"
@@ -23824,10 +23813,8 @@
 "Actualitza el nom de l'objecte emmagatzema en una referència de forma segura"
 
 #: command-list.h:186
-#, fuzzy
 msgid "Update auxiliary info file to help dumb servers"
-msgstr ""
-"Actualitza el fitxer d'informació auxiliar per ajudar als servidors ximples"
+msgstr "Actualitza el fitxer d'informació auxiliar per a ajudar als servidors ximples"
 
 #: command-list.h:187
 msgid "Send archive back to git-archive"
@@ -23886,7 +23873,6 @@
 msgstr "Git per a usuaris del CVS"
 
 #: command-list.h:201
-#, fuzzy
 msgid "Tweaking diff output"
 msgstr "Ajustament de la sortida de diferències"
 
@@ -23944,7 +23930,7 @@
 
 #: git-bisect.sh:54
 msgid "You need to start by \"git bisect start\""
-msgstr "Cal començar per \"git bisect start\""
+msgstr "Cal començar per «git bisect start»"
 
 #. TRANSLATORS: Make sure to include [Y] and [n] in your
 #. translation. The program will only accept English input
@@ -23971,7 +23957,7 @@
 #: git-bisect.sh:139
 #, sh-format
 msgid "'git bisect $TERM_BAD' can take only one argument."
-msgstr "'git bisect $TERM_BAD' pot acceptar només un paràmetre."
+msgstr "«git bisect $TERM_BAD» pot acceptar només un argument."
 
 #: git-bisect.sh:209
 msgid "No logfile given"
@@ -24002,7 +23988,7 @@
 "exit code $res from '$command' is < 0 or >= 128"
 msgstr ""
 "el pas de bisecció ha fallat:\n"
-"el codi de sortida $res de '$command' és < 0 o >= 128"
+"el codi de sortida $res de «$command» és < 0 o bé >= 128"
 
 #: git-bisect.sh:281
 msgid "bisect run cannot continue any more"
@@ -24015,7 +24001,7 @@
 "'bisect_state $state' exited with error code $res"
 msgstr ""
 "el pas de bisecció ha fallat:\n"
-"'bisect_state $state' ha sortit amb el codi d'error $res"
+"«bisect_state $state» ha sortit amb el codi d'error $res"
 
 #: git-bisect.sh:294
 msgid "bisect run success"
@@ -24088,25 +24074,25 @@
 msgstr "«$sm_path» ja existeix en l'índex i no és submòdul"
 
 #: git-submodule.sh:244
-#, fuzzy, sh-format
+#, sh-format
 msgid "'$sm_path' does not have a commit checked out"
-msgstr "«sm_path» no té una comissió marcada"
+msgstr "«$sm_path» no té una comissió agafada"
 
 #: git-submodule.sh:275
 #, sh-format
 msgid "Adding existing repo at '$sm_path' to the index"
-msgstr "S'està afegint el dipòsit existent a '$sm_path' a l'índex"
+msgstr "S'està afegint el dipòsit existent a «$sm_path» a l'índex"
 
 #: git-submodule.sh:277
 #, sh-format
 msgid "'$sm_path' already exists and is not a valid git repo"
-msgstr "'$sm_path' ja existeix i no és un dipòsit de git vàlid"
+msgstr "«$sm_path» ja existeix i no és un dipòsit de git vàlid"
 
 #: git-submodule.sh:285
 #, sh-format
 msgid "A git directory for '$sm_name' is found locally with remote(s):"
 msgstr ""
-"Es troba un directori de git per a '$sm_name' localment amb els remots:"
+"S'ha trobat un directori de git per a «$sm_name» localment amb els remots:"
 
 #: git-submodule.sh:287
 #, sh-format
@@ -24122,8 +24108,8 @@
 "  $realrepo\n"
 "useu l'opció «--force». Si el directori de git local no és el dipòsit "
 "correcte\n"
-"o no esteu segur de què vol dir això, trieu un altre nom amb l'opció '--"
-"name'."
+"o no esteu segur de què vol dir això, trieu un altre nom amb l'opció «--"
+"name»."
 
 #: git-submodule.sh:293
 #, sh-format
@@ -24164,7 +24150,7 @@
 "'$sm_path'"
 msgstr ""
 "No s'ha pogut trobar la revisió actual de ${remote_name}/${branch} en el "
-"camí de submòdul '$sm_path'"
+"camí de submòdul «$sm_path»"
 
 #: git-submodule.sh:625
 #, sh-format
@@ -24198,7 +24184,7 @@
 #, sh-format
 msgid "Unable to rebase '$sha1' in submodule path '$displaypath'"
 msgstr ""
-"No s'ha pogut fer «rebase» «$sha1»' en el camí de submòdul «$displaypath»"
+"No s'ha pogut fer «rebase» «$sha1» en el camí de submòdul «$displaypath»"
 
 #: git-submodule.sh:644
 #, sh-format
@@ -24261,7 +24247,7 @@
 #: git-parse-remote.sh:89
 #, sh-format
 msgid "See git-${cmd}(1) for details."
-msgstr "Vegeu git-${cmd}(1) per detalls."
+msgstr "Vegeu git-${cmd}(1) per a més informació."
 
 #: git-rebase--preserve-merges.sh:109
 msgid "Applied autostash."
@@ -24280,7 +24266,7 @@
 msgstr ""
 "L'aplicació del «stash» automàtic ha resultat en conflictes.\n"
 "Els vostres canvis estan segurs en el «stash».\n"
-"Podeu executar \"git stash pop\" o \"git stash drop\" en qualsevol moment.\n"
+"Podeu executar «git stash pop» o «git stash drop» en qualsevol moment.\n"
 
 #: git-rebase--preserve-merges.sh:191
 #, sh-format
@@ -24288,7 +24274,6 @@
 msgstr "S'està fent «rebase» ($new_count/$total)"
 
 #: git-rebase--preserve-merges.sh:207
-#, fuzzy
 msgid ""
 "\n"
 "Commands:\n"
@@ -24308,8 +24293,25 @@
 "\n"
 "These lines can be re-ordered; they are executed from top to bottom.\n"
 msgstr ""
-"Les ordres p select <commit> = fa servir «commit» o «commit» o "
-"«commit» (commit) o «commit» (commit)"
+"\n"
+"Ordres:\n"
+" p, pick <comissió> = usa la comissió\n"
+" r, reword <comissió> = usa la comissió, però edita el missatge de comissió\n"
+" e, edit <comissió> = usa la comissió, però atura't per a esmenar\n"
+" s, squash <comissió> = usa la comissió, però fusiona-la a la comissió prèvia\n"
+" f, fixup <comissió> = com a «squash», però descarta el missatge de registre d'aquesta "
+"comissió\n"
+"x, exec <comissió> = executa l'ordre (la resta de la línia) usant l'intèrpret "
+"d'ordres\n"
+"d, drop <comissió> = elimina la comissió\n"
+"l, label <etiqueta> = etiqueta la HEAD actual amb un nom\n"
+"t, reset <etiqueta> = reinicia HEAD a una etiqueta    \n"
+"m, merge [-C <comissió> | -c <comissió>] <etiqueta> [# <oneline>]\n"
+".       crea una comissió de fusió usant el missatge de la comissió\n"
+".       de fusió original (o línia única, si no hi ha cap comissió de fusió original\n"
+".       especificada). Useu -c <comissió> per a reescriure el missatge de publicació.\n"
+"\n"
+"Es pot canviar l'ordre d'aquestes línies; s'executen de dalt a baix.\n"
 
 #: git-rebase--preserve-merges.sh:270
 #, sh-format
@@ -24333,7 +24335,7 @@
 #: git-rebase--preserve-merges.sh:295
 #, sh-format
 msgid "$sha1: not a commit that can be picked"
-msgstr "$sha1: no és una comissió que es pugui escollir"
+msgstr "$sha1: no és una comissió que es pugui triar"
 
 #: git-rebase--preserve-merges.sh:334
 #, sh-format
@@ -24372,7 +24374,7 @@
 #: git-rebase--preserve-merges.sh:458
 #, sh-format
 msgid "Could not pick $sha1"
-msgstr "No s'ha pogut escollir $sha1"
+msgstr "No s'ha pogut triar $sha1"
 
 #: git-rebase--preserve-merges.sh:467
 #, sh-format
@@ -24388,7 +24390,7 @@
 #, sh-format
 msgid "This is a combination of $count commit."
 msgid_plural "This is a combination of $count commits."
-msgstr[0] "Això és una combinació de $count comissió."
+msgstr[0] "Això és una combinació d'$count comissió."
 msgstr[1] "Això és una combinació de $count comissions."
 
 #: git-rebase--preserve-merges.sh:492
@@ -24415,7 +24417,7 @@
 "before\n"
 "you are able to reword the commit."
 msgstr ""
-"No s'ha pogut esmenar la comissió després d'escollir amb èxit $sha1... "
+"No s'ha pogut esmenar la comissió després de triar correctament $sha1... "
 "$rest\n"
 "Això és probablement a causa d'un missatge de comissió buit, o el lligam de\n"
 "precomissió ha fallat. Si el lligam de precomissió ha fallat, pot ser que\n"
@@ -24430,7 +24432,7 @@
 #: git-rebase--preserve-merges.sh:641
 #, sh-format
 msgid "Cannot '$squash_style' without a previous commit"
-msgstr "No es pot '$squash_style' sense una comissió prèvia"
+msgstr "No es pot fer «$squash_style» sense una comissió prèvia"
 
 #: git-rebase--preserve-merges.sh:683
 #, sh-format
@@ -24706,9 +24708,9 @@
 "Lines starting with %s will be removed.\n"
 msgstr ""
 "---\n"
-"Per suprimir «%s» línies, feu-les línies ' ' (context).\n"
-"Per suprimir «%s» línies, suprimiu-les.\n"
-"Les línies que comencin per %s seran suprimides.\n"
+"Per a eliminar les línies «%s», convertiu-les en línies ' ' (context).\n"
+"Per a eliminar les línies «%s», suprimiu-les.\n"
+"Les línies que comencin per %s s'eliminaran.\n"
 
 #: git-add--interactive.perl:1140
 #, perl-format
@@ -24984,7 +24986,7 @@
 #: git-send-email.perl:315
 #, perl-format
 msgid "'%s.final' contains the composed email.\n"
-msgstr "'%s.final' conté el correu redactat.\n"
+msgstr "«%s.final» conté el correu redactat.\n"
 
 #: git-send-email.perl:408
 msgid "--dump-aliases incompatible with other options\n"
@@ -25011,22 +25013,22 @@
 #: git-send-email.perl:528
 #, perl-format
 msgid "Unknown --confirm setting: '%s'\n"
-msgstr "--confirm setting desconegut: «%s»\n"
+msgstr "Paràmetre --confirm desconegut: «%s»\n"
 
 #: git-send-email.perl:556
 #, perl-format
 msgid "warning: sendmail alias with quotes is not supported: %s\n"
-msgstr "avís: el sobrenom de sendmail amb cometes no està suportat: %s\n"
+msgstr "avís: no s'admet l'àlies de sendmail amb cometes: %s\n"
 
 #: git-send-email.perl:558
 #, perl-format
 msgid "warning: `:include:` not supported: %s\n"
-msgstr "avís: `:include:` no està suportat: %s\n"
+msgstr "avís: «:include:» no s'admet: %s\n"
 
 #: git-send-email.perl:560
 #, perl-format
 msgid "warning: `/file` or `|pipe` redirection not supported: %s\n"
-msgstr "avís: les redireccions `/file` or `|pipe no són admeses: %s\n"
+msgstr "avís: les redireccions «/file» ni «|pipe» no s'admeten: %s\n"
 
 #: git-send-email.perl:565
 #, perl-format
@@ -25042,11 +25044,11 @@
 "    * Saying \"./%s\" if you mean a file; or\n"
 "    * Giving --format-patch option if you mean a range.\n"
 msgstr ""
-"El fitxer «%s» existeix però també pot ser un rang de comissions\n"
-"per produir pedaços. Desambigüeu...\n"
+"El fitxer «%s» existeix, però també pot ser un rang de comissions\n"
+"per produir pedaços. Desambigüeu-ho...\n"
 "\n"
-"    * Dient \"./%s\" si volíeu especificar aquest fitxer; o\n"
-"    * Proporcionant l'opció --format-patch si volíeu especificar un rang.\n"
+"    * Dient «./%s» si volíeu especificar un fitxer; o\n"
+"    * Proporcionant l'opció «--format-patch» si volíeu especificar un rang.\n"
 
 #: git-send-email.perl:670
 #, perl-format
@@ -25090,11 +25092,11 @@
 "\n"
 "Clear the body content if you don't wish to send a summary.\n"
 msgstr ""
-"Se suprimiran les línies que comencen amb \"GIT:\".\n"
+"S'eliminaran les línies que comencen amb «GIT:».\n"
 "Considereu incloure un diffstat global o una taula de continguts\n"
-"per cada pedaç que esteu escrivint.\n"
+"per al pedaç que esteu escrivint.\n"
 "\n"
-"Netegeu el contingut del cos si no voleu enviar un resum.\n"
+"Esborreu el contingut del cos si no voleu enviar cap resum.\n"
 
 #: git-send-email.perl:763
 #, perl-format
@@ -25138,8 +25140,8 @@
 msgstr ""
 "S'ha refusat a enviar perquè el pedaç\n"
 "\t%s\n"
-"perquè la plantilla té l'assumpte '*** SUBJECT HERE ***'. Passeu --force si "
-"realment voleu enviar-lo.\n"
+"perquè la plantilla té l'assumpte «*** SUBJECT HERE ***». Passeu --force si "
+"realment voleu enviar-ho.\n"
 
 #: git-send-email.perl:945
 msgid "To whom should the emails be sent (if anyone)?"
@@ -25193,9 +25195,9 @@
 "    Aquest comportament està controlat pel paràmetre de configuració\n"
 "    sendemail.confirm.\n"
 "\n"
-"    Per a informació addicional, executeu 'git send-email --help'.\n"
+"    Per a informació addicional, executeu «git send-email --help».\n"
 "    Per mantenir el comportament actual, però silenciar aquest\n"
-"    missatge, executeu 'git config --global sendemail.confirm auto'.\n"
+"    missatge, executeu «git config --global sendemail.confirm auto».\n"
 "\n"
 
 #. TRANSLATORS: Make sure to include [y] [n] [e] [q] [a] in your
@@ -25298,7 +25300,7 @@
 
 #: git-send-email.perl:1875
 #, perl-format
-msgid "(%s) failed to close pipe to '%s'" 
+msgid "(%s) failed to close pipe to '%s'"
 msgstr "(%s) s'ha produït un error en tancar el conducte «%s»"
 
 #: git-send-email.perl:1905
diff --git a/po/de.po b/po/de.po
index 6356276..656de24 100644
--- a/po/de.po
+++ b/po/de.po
@@ -8,8 +8,8 @@
 msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2020-05-27 07:23+0800\n"
-"PO-Revision-Date: 2020-05-24 15:57+0100\n"
+"POT-Creation-Date: 2020-07-10 09:53+0800\n"
+"PO-Revision-Date: 2020-07-12 13:20+0100\n"
 "Last-Translator: Matthias Rüster <matthias.ruester@gmail.com>\n"
 "Language-Team: Matthias Rüster <matthias.ruester@gmail.com>\n"
 "Language: de\n"
@@ -111,21 +111,21 @@
 msgid "ignoring unmerged: %s"
 msgstr "Ignoriere nicht zusammengeführte Datei: %s"
 
-#: add-interactive.c:929 add-patch.c:1675 git-add--interactive.perl:1366
+#: add-interactive.c:929 add-patch.c:1691 git-add--interactive.perl:1368
 #, c-format
 msgid "Only binary files changed.\n"
 msgstr "Nur Binärdateien geändert.\n"
 
-#: add-interactive.c:931 add-patch.c:1673 git-add--interactive.perl:1368
+#: add-interactive.c:931 add-patch.c:1689 git-add--interactive.perl:1370
 #, c-format
 msgid "No changes.\n"
 msgstr "Keine Änderungen.\n"
 
-#: add-interactive.c:935 git-add--interactive.perl:1376
+#: add-interactive.c:935 git-add--interactive.perl:1378
 msgid "Patch update"
 msgstr "Patch Aktualisierung"
 
-#: add-interactive.c:974 git-add--interactive.perl:1754
+#: add-interactive.c:974 git-add--interactive.perl:1771
 msgid "Review diff"
 msgstr "Diff überprüfen"
 
@@ -193,11 +193,11 @@
 msgid "(empty) select nothing"
 msgstr "(leer) nichts auswählen"
 
-#: add-interactive.c:1083 builtin/clean.c:816 git-add--interactive.perl:1851
+#: add-interactive.c:1083 builtin/clean.c:816 git-add--interactive.perl:1868
 msgid "*** Commands ***"
 msgstr "*** Befehle ***"
 
-#: add-interactive.c:1084 builtin/clean.c:817 git-add--interactive.perl:1848
+#: add-interactive.c:1084 builtin/clean.c:817 git-add--interactive.perl:1865
 msgid "What now"
 msgstr "Was nun"
 
@@ -214,7 +214,7 @@
 #: builtin/merge.c:276 builtin/pull.c:190 builtin/submodule--helper.c:409
 #: builtin/submodule--helper.c:1394 builtin/submodule--helper.c:1397
 #: builtin/submodule--helper.c:1902 builtin/submodule--helper.c:1905
-#: builtin/submodule--helper.c:2148 bugreport.c:129
+#: builtin/submodule--helper.c:2148 bugreport.c:135
 #: git-add--interactive.perl:213
 msgid "path"
 msgstr "Pfad"
@@ -223,27 +223,32 @@
 msgid "could not refresh index"
 msgstr "Index konnte nicht aktualisiert werden"
 
-#: add-interactive.c:1157 builtin/clean.c:781 git-add--interactive.perl:1765
+#: add-interactive.c:1157 builtin/clean.c:781 git-add--interactive.perl:1782
 #, c-format
 msgid "Bye.\n"
 msgstr "Tschüss.\n"
 
-#: add-patch.c:34 git-add--interactive.perl:1428
+#: add-patch.c:34 git-add--interactive.perl:1430
 #, c-format, perl-format
 msgid "Stage mode change [y,n,q,a,d%s,?]? "
 msgstr "Modusänderung der Staging-Area hinzufügen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:35 git-add--interactive.perl:1429
+#: add-patch.c:35 git-add--interactive.perl:1431
 #, c-format, perl-format
 msgid "Stage deletion [y,n,q,a,d%s,?]? "
 msgstr "Löschung der Staging-Area hinzufügen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:36 git-add--interactive.perl:1430
+#: add-patch.c:36 git-add--interactive.perl:1432
+#, c-format, perl-format
+msgid "Stage addition [y,n,q,a,d%s,?]? "
+msgstr "Ergänzung der Staging-Area hinzufügen [y,n,q,a,d%s,?]? "
+
+#: add-patch.c:37 git-add--interactive.perl:1433
 #, c-format, perl-format
 msgid "Stage this hunk [y,n,q,a,d%s,?]? "
 msgstr "Diesen Patch-Block der Staging-Area hinzufügen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:38
+#: add-patch.c:39
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "staging."
@@ -251,7 +256,7 @@
 "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-"
 "Block direkt für die Staging-Area markiert."
 
-#: add-patch.c:41
+#: add-patch.c:42
 msgid ""
 "y - stage this hunk\n"
 "n - do not stage this hunk\n"
@@ -267,22 +272,27 @@
 "d - diesen oder alle weiteren Patch-Blöcke in dieser Datei nicht zum Commit "
 "vormerken\n"
 
-#: add-patch.c:55 git-add--interactive.perl:1433
+#: add-patch.c:56 git-add--interactive.perl:1436
 #, c-format, perl-format
 msgid "Stash mode change [y,n,q,a,d%s,?]? "
 msgstr "Modusänderung stashen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:56 git-add--interactive.perl:1434
+#: add-patch.c:57 git-add--interactive.perl:1437
 #, c-format, perl-format
 msgid "Stash deletion [y,n,q,a,d%s,?]? "
 msgstr "Löschung stashen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:57 git-add--interactive.perl:1435
+#: add-patch.c:58 git-add--interactive.perl:1438
+#, c-format, perl-format
+msgid "Stash addition [y,n,q,a,d%s,?]? "
+msgstr "Ergänzung stashen [y,n,q,a,d%s,?]? "
+
+#: add-patch.c:59 git-add--interactive.perl:1439
 #, c-format, perl-format
 msgid "Stash this hunk [y,n,q,a,d%s,?]? "
 msgstr "Diesen Patch-Block stashen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:59
+#: add-patch.c:61
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "stashing."
@@ -290,7 +300,7 @@
 "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-"
 "Block direkt zum Stashen markiert."
 
-#: add-patch.c:62
+#: add-patch.c:64
 msgid ""
 "y - stash this hunk\n"
 "n - do not stash this hunk\n"
@@ -304,22 +314,27 @@
 "a - diesen und alle weiteren Patch-Blöcke dieser Datei stashen\n"
 "d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht stashen\n"
 
-#: add-patch.c:78 git-add--interactive.perl:1438
+#: add-patch.c:80 git-add--interactive.perl:1442
 #, c-format, perl-format
 msgid "Unstage mode change [y,n,q,a,d%s,?]? "
 msgstr "Modusänderung aus der Staging-Area entfernen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:79 git-add--interactive.perl:1439
+#: add-patch.c:81 git-add--interactive.perl:1443
 #, c-format, perl-format
 msgid "Unstage deletion [y,n,q,a,d%s,?]? "
 msgstr "Löschung aus der Staging-Area entfernen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:80 git-add--interactive.perl:1440
+#: add-patch.c:82 git-add--interactive.perl:1444
+#, c-format, perl-format
+msgid "Unstage addition [y,n,q,a,d%s,?]? "
+msgstr "Ergänzung aus der Staging-Area entfernen [y,n,q,a,d%s,?]? "
+
+#: add-patch.c:83 git-add--interactive.perl:1445
 #, c-format, perl-format
 msgid "Unstage this hunk [y,n,q,a,d%s,?]? "
 msgstr "Diesen Patch-Block aus der Staging-Area entfernen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:82
+#: add-patch.c:85
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "unstaging."
@@ -327,7 +342,7 @@
 "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-"
 "Block direkt zum Entfernen aus der Staging-Area markiert."
 
-#: add-patch.c:85
+#: add-patch.c:88
 msgid ""
 "y - unstage this hunk\n"
 "n - do not unstage this hunk\n"
@@ -344,22 +359,27 @@
 "d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht aus Staging-"
 "Area entfernen\n"
 
-#: add-patch.c:100 git-add--interactive.perl:1443
+#: add-patch.c:103 git-add--interactive.perl:1448
 #, c-format, perl-format
 msgid "Apply mode change to index [y,n,q,a,d%s,?]? "
 msgstr "Modusänderung auf Index anwenden [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:101 git-add--interactive.perl:1444
+#: add-patch.c:104 git-add--interactive.perl:1449
 #, c-format, perl-format
 msgid "Apply deletion to index [y,n,q,a,d%s,?]? "
 msgstr "Löschung auf Index anwenden [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:102 git-add--interactive.perl:1445
+#: add-patch.c:105 git-add--interactive.perl:1450
+#, c-format, perl-format
+msgid "Apply addition to index [y,n,q,a,d%s,?]? "
+msgstr "Ergänzung auf Index anwenden [y,n,q,a,d%s,?]? "
+
+#: add-patch.c:106 git-add--interactive.perl:1451
 #, c-format, perl-format
 msgid "Apply this hunk to index [y,n,q,a,d%s,?]? "
 msgstr "Diesen Patch-Block auf Index anwenden [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:104 add-patch.c:169 add-patch.c:212
+#: add-patch.c:108 add-patch.c:176 add-patch.c:221
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "applying."
@@ -367,7 +387,7 @@
 "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-"
 "Block direkt zum Anwenden markiert."
 
-#: add-patch.c:107
+#: add-patch.c:111
 msgid ""
 "y - apply this hunk to index\n"
 "n - do not apply this hunk to index\n"
@@ -384,25 +404,31 @@
 "d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht auf den Index "
 "anwenden\n"
 
-#: add-patch.c:122 git-add--interactive.perl:1448
-#: git-add--interactive.perl:1463
+#: add-patch.c:126 git-add--interactive.perl:1454
+#: git-add--interactive.perl:1472
 #, c-format, perl-format
 msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? "
 msgstr "Modusänderung im Arbeitsverzeichnis verwerfen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:123 git-add--interactive.perl:1449
-#: git-add--interactive.perl:1464
+#: add-patch.c:127 git-add--interactive.perl:1455
+#: git-add--interactive.perl:1473
 #, c-format, perl-format
 msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? "
 msgstr "Löschung im Arbeitsverzeichnis verwerfen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:124 git-add--interactive.perl:1450
-#: git-add--interactive.perl:1465
+#: add-patch.c:128 git-add--interactive.perl:1456
+#: git-add--interactive.perl:1474
+#, c-format, perl-format
+msgid "Discard addition from worktree [y,n,q,a,d%s,?]? "
+msgstr "Ergänzung im Arbeitsverzeichnis verwerfen [y,n,q,a,d%s,?]? "
+
+#: add-patch.c:129 git-add--interactive.perl:1457
+#: git-add--interactive.perl:1475
 #, c-format, perl-format
 msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? "
 msgstr "Diesen Patch-Block im Arbeitsverzeichnis verwerfen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:126 add-patch.c:148 add-patch.c:191
+#: add-patch.c:131 add-patch.c:154 add-patch.c:199
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "discarding."
@@ -410,7 +436,7 @@
 "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-"
 "Block direkt zum Verwerfen markiert."
 
-#: add-patch.c:129 add-patch.c:194
+#: add-patch.c:134 add-patch.c:202
 msgid ""
 "y - discard this hunk from worktree\n"
 "n - do not discard this hunk from worktree\n"
@@ -427,25 +453,30 @@
 "d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht im "
 "Arbeitsverzeichnis verwerfen\n"
 
-#: add-patch.c:144 add-patch.c:187 git-add--interactive.perl:1453
+#: add-patch.c:149 add-patch.c:194 git-add--interactive.perl:1460
 #, c-format, perl-format
 msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "Modusänderung vom Index und Arbeitsverzeichnis verwerfen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:145 add-patch.c:188 git-add--interactive.perl:1454
+#: add-patch.c:150 add-patch.c:195 git-add--interactive.perl:1461
 #, c-format, perl-format
 msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? "
 msgstr "Löschung vom Index und Arbeitsverzeichnis verwerfen [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:146 add-patch.c:189 git-add--interactive.perl:1455
+#: add-patch.c:151 add-patch.c:196 git-add--interactive.perl:1462
+#,  c-format, perl-format
+msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? "
+msgstr "Ergänzung im Index und Arbeitsverzeichnis verwerfen [y,n,q,a,d%s,?]? "
+
+#: add-patch.c:152 add-patch.c:197 git-add--interactive.perl:1463
 #, c-format, perl-format
 msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "Diesen Patch-Block vom Index und Arbeitsverzeichnis verwerfen [y,n,q,a,d"
 "%s,?]? "
 
-#: add-patch.c:151
+#: add-patch.c:157
 msgid ""
 "y - discard this hunk from index and worktree\n"
 "n - do not discard this hunk from index and worktree\n"
@@ -459,25 +490,30 @@
 "a - diesen und alle weiteren Patch-Blöcke in der Datei verwerfen\n"
 "d - diesen oder alle weiteren Patch-Blöcke in der Datei nicht verwerfen\n"
 
-#: add-patch.c:165 add-patch.c:208 git-add--interactive.perl:1458
+#: add-patch.c:171 add-patch.c:216 git-add--interactive.perl:1466
 #, c-format, perl-format
 msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "Modusänderung auf Index und Arbeitsverzeichnis anwenden [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:166 add-patch.c:209 git-add--interactive.perl:1459
+#: add-patch.c:172 add-patch.c:217 git-add--interactive.perl:1467
 #, c-format, perl-format
 msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? "
 msgstr "Löschung auf Index und Arbeitsverzeichnis anwenden [y,n,q,a,d%s,?]? "
 
-#: add-patch.c:167 add-patch.c:210 git-add--interactive.perl:1460
+#: add-patch.c:173 add-patch.c:218 git-add--interactive.perl:1468
+#, c-format, perl-format
+msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? "
+msgstr "Ergänzung auf Index und Arbeitsverzeichnis anwenden [y,n,q,a,d%s,?]? "
+
+#: add-patch.c:174 add-patch.c:219 git-add--interactive.perl:1469
 #, c-format, perl-format
 msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "Diesen Patch-Block auf Index und Arbeitsverzeichnis anwenden [y,n,q,a,d"
 "%s,?]? "
 
-#: add-patch.c:172
+#: add-patch.c:179
 msgid ""
 "y - apply this hunk to index and worktree\n"
 "n - do not apply this hunk to index and worktree\n"
@@ -492,7 +528,7 @@
 "a - diesen und alle weiteren Patch-Blöcke in der Datei anwenden\n"
 "d - diesen oder alle weiteren Patch-Blöcke in der Datei nicht anwenden\n"
 
-#: add-patch.c:215
+#: add-patch.c:224
 msgid ""
 "y - apply this hunk to worktree\n"
 "n - do not apply this hunk to worktree\n"
@@ -506,34 +542,34 @@
 "a - diesen und alle weiteren Patch-Blöcke in der Datei anwenden\n"
 "d - diesen und alle weiteren Patch-Blöcke in der Datei nicht anwenden\n"
 
-#: add-patch.c:319
+#: add-patch.c:328
 #, c-format
 msgid "could not parse hunk header '%.*s'"
 msgstr "Konnte Block-Header '%.*s' nicht parsen."
 
-#: add-patch.c:338 add-patch.c:342
+#: add-patch.c:347 add-patch.c:351
 #, c-format
 msgid "could not parse colored hunk header '%.*s'"
 msgstr "Konnte farbigen Block-Header '%.*s' nicht parsen."
 
-#: add-patch.c:396
+#: add-patch.c:405
 msgid "could not parse diff"
 msgstr "Konnte Differenz nicht parsen."
 
-#: add-patch.c:415
+#: add-patch.c:424
 msgid "could not parse colored diff"
 msgstr "Konnte farbige Differenz nicht parsen."
 
-#: add-patch.c:429
+#: add-patch.c:438
 #, c-format
 msgid "failed to run '%s'"
 msgstr "'%s' konnte nicht ausgeführt werden"
 
-#: add-patch.c:588
+#: add-patch.c:602
 msgid "mismatched output from interactive.diffFilter"
 msgstr "nicht übereinstimmende Ausgabe von interactive.diffFilter"
 
-#: add-patch.c:589
+#: add-patch.c:603
 msgid ""
 "Your filter must maintain a one-to-one correspondence\n"
 "between its input and output lines."
@@ -541,7 +577,7 @@
 "Der Filter muss eine Eins-zu-Eins-Beziehung\n"
 "zwischen den Ein- und Ausgabe-Zeilen einhalten."
 
-#: add-patch.c:762
+#: add-patch.c:776
 #, c-format
 msgid ""
 "expected context line #%d in\n"
@@ -550,7 +586,7 @@
 "Erwartete Kontextzeile #%d in\n"
 "%.*s"
 
-#: add-patch.c:777
+#: add-patch.c:791
 #, c-format
 msgid ""
 "hunks do not overlap:\n"
@@ -563,13 +599,13 @@
 "\tendet nicht mit:\n"
 "%.*s"
 
-#: add-patch.c:1053 git-add--interactive.perl:1112
+#: add-patch.c:1067 git-add--interactive.perl:1114
 msgid "Manual hunk edit mode -- see bottom for a quick guide.\n"
 msgstr ""
 "Manueller Editiermodus für Patch-Blöcke -- siehe nach unten für eine\n"
 "Kurzanleitung.\n"
 
-#: add-patch.c:1057
+#: add-patch.c:1071
 #, c-format
 msgid ""
 "---\n"
@@ -583,7 +619,7 @@
 "Zeilen, die mit %c beginnen, werden entfernt.\n"
 
 #. TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.
-#: add-patch.c:1071 git-add--interactive.perl:1126
+#: add-patch.c:1085 git-add--interactive.perl:1128
 msgid ""
 "If it does not apply cleanly, you will be given an opportunity to\n"
 "edit again.  If all lines of the hunk are removed, then the edit is\n"
@@ -594,11 +630,11 @@
 "werden,\n"
 "wird die Bearbeitung abgebrochen und der Patch-Block bleibt unverändert.\n"
 
-#: add-patch.c:1104
+#: add-patch.c:1118
 msgid "could not parse hunk header"
 msgstr "Konnte Block-Header nicht parsen."
 
-#: add-patch.c:1149
+#: add-patch.c:1163
 msgid "'git apply --cached' failed"
 msgstr "'git apply --cached' schlug fehl."
 
@@ -614,27 +650,27 @@
 #. Consider translating (saying "no" discards!) as
 #. (saying "n" for "no" discards!) if the translation
 #. of the word "no" does not start with n.
-#: add-patch.c:1218 git-add--interactive.perl:1239
+#: add-patch.c:1232 git-add--interactive.perl:1241
 msgid ""
 "Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
 msgstr ""
 "Ihr bearbeiteter Patch-Block kann nicht angewendet werden.\n"
 "Erneut bearbeiten? (\"n\" verwirft Bearbeitung!) [y/n]?"
 
-#: add-patch.c:1261
+#: add-patch.c:1275
 msgid "The selected hunks do not apply to the index!"
 msgstr ""
 "Die ausgewählten Patch-Blöcke können nicht auf den Index angewendet werden!"
 
-#: add-patch.c:1262 git-add--interactive.perl:1343
+#: add-patch.c:1276 git-add--interactive.perl:1345
 msgid "Apply them to the worktree anyway? "
 msgstr "Trotzdem auf Arbeitsverzeichnis anwenden? "
 
-#: add-patch.c:1269 git-add--interactive.perl:1346
+#: add-patch.c:1283 git-add--interactive.perl:1348
 msgid "Nothing was applied.\n"
 msgstr "Nichts angewendet.\n"
 
-#: add-patch.c:1326
+#: add-patch.c:1340
 msgid ""
 "j - leave this hunk undecided, see next undecided hunk\n"
 "J - leave this hunk undecided, see next hunk\n"
@@ -658,69 +694,69 @@
 "e - aktuellen Patch-Block manuell editieren\n"
 "? - Hilfe anzeigen\n"
 
-#: add-patch.c:1447 add-patch.c:1457
+#: add-patch.c:1463 add-patch.c:1473
 msgid "No previous hunk"
 msgstr "Kein vorheriger Patch-Block"
 
-#: add-patch.c:1452 add-patch.c:1462
+#: add-patch.c:1468 add-patch.c:1478
 msgid "No next hunk"
 msgstr "Kein folgender Patch-Block"
 
-#: add-patch.c:1468
+#: add-patch.c:1484
 msgid "No other hunks to goto"
 msgstr "Keine anderen Patch-Blöcke verbleibend"
 
-#: add-patch.c:1479 git-add--interactive.perl:1577
+#: add-patch.c:1495 git-add--interactive.perl:1594
 msgid "go to which hunk (<ret> to see more)? "
 msgstr "zu welchem Patch-Block springen (<Enter> für mehr Informationen)? "
 
-#: add-patch.c:1480 git-add--interactive.perl:1579
+#: add-patch.c:1496 git-add--interactive.perl:1596
 msgid "go to which hunk? "
 msgstr "zu welchem Patch-Block springen? "
 
-#: add-patch.c:1491
+#: add-patch.c:1507
 #, c-format
 msgid "Invalid number: '%s'"
 msgstr "Ungültige Nummer: '%s'"
 
-#: add-patch.c:1496
+#: add-patch.c:1512
 #, c-format
 msgid "Sorry, only %d hunk available."
 msgid_plural "Sorry, only %d hunks available."
 msgstr[0] "Entschuldigung, nur %d Patch-Block verfügbar."
 msgstr[1] "Entschuldigung, nur %d Patch-Blöcke verfügbar."
 
-#: add-patch.c:1505
+#: add-patch.c:1521
 msgid "No other hunks to search"
 msgstr "Keine anderen Patch-Blöcke zum Durchsuchen"
 
-#: add-patch.c:1511 git-add--interactive.perl:1623
+#: add-patch.c:1527 git-add--interactive.perl:1640
 msgid "search for regex? "
 msgstr "Suche nach regulärem Ausdruck? "
 
-#: add-patch.c:1526
+#: add-patch.c:1542
 #, c-format
 msgid "Malformed search regexp %s: %s"
 msgstr "Fehlerhafter regulärer Ausdruck für Suche %s: %s"
 
-#: add-patch.c:1543
+#: add-patch.c:1559
 msgid "No hunk matches the given pattern"
 msgstr "Kein Patch-Block entspricht dem angegebenen Muster"
 
-#: add-patch.c:1550
+#: add-patch.c:1566
 msgid "Sorry, cannot split this hunk"
 msgstr "Entschuldigung, kann diesen Patch-Block nicht aufteilen"
 
-#: add-patch.c:1554
+#: add-patch.c:1570
 #, c-format
 msgid "Split into %d hunks."
 msgstr "In %d Patch-Block aufgeteilt."
 
-#: add-patch.c:1558
+#: add-patch.c:1574
 msgid "Sorry, cannot edit this hunk"
 msgstr "Entschuldigung, kann diesen Patch-Block nicht bearbeiten"
 
-#: add-patch.c:1609
+#: add-patch.c:1625
 msgid "'git apply' failed"
 msgstr "'git apply' schlug fehl"
 
@@ -1438,7 +1474,7 @@
 
 #: apply.c:5008 builtin/am.c:2238 builtin/interpret-trailers.c:98
 #: builtin/interpret-trailers.c:100 builtin/interpret-trailers.c:102
-#: builtin/pack-objects.c:3458 builtin/rebase.c:1332
+#: builtin/pack-objects.c:3530 builtin/rebase.c:1332
 msgid "action"
 msgstr "Aktion"
 
@@ -1528,7 +1564,7 @@
 msgid "path too long (%d chars, SHA1: %s): %s"
 msgstr "Pfad zu lang (%d Zeichen, SHA1: %s): %s"
 
-#: archive-zip.c:480 builtin/pack-objects.c:232 builtin/pack-objects.c:235
+#: archive-zip.c:480 builtin/pack-objects.c:243 builtin/pack-objects.c:246
 #, c-format
 msgid "deflate error (%d)"
 msgstr "Fehler beim Komprimieren (%d)"
@@ -1598,8 +1634,8 @@
 msgstr "einen Präfix vor jeden Pfadnamen in dem Archiv stellen"
 
 #: archive.c:467 builtin/blame.c:861 builtin/blame.c:865 builtin/blame.c:866
-#: builtin/commit-tree.c:117 builtin/config.c:130 builtin/fast-export.c:1162
-#: builtin/fast-export.c:1164 builtin/fast-export.c:1168 builtin/grep.c:907
+#: builtin/commit-tree.c:117 builtin/config.c:130 builtin/fast-export.c:1208
+#: builtin/fast-export.c:1210 builtin/fast-export.c:1214 builtin/grep.c:907
 #: builtin/hash-object.c:105 builtin/ls-files.c:561 builtin/ls-files.c:564
 #: builtin/notes.c:412 builtin/notes.c:578 builtin/read-tree.c:123
 #: parse-options.h:190
@@ -1828,10 +1864,10 @@
 "endgültigen\n"
 "Commits"
 
-#: blame.c:2821 bundle.c:167 ref-filter.c:2200 remote.c:1924 sequencer.c:2018
+#: blame.c:2821 bundle.c:187 ref-filter.c:2200 remote.c:1924 sequencer.c:2018
 #: sequencer.c:4466 submodule.c:847 builtin/commit.c:1047 builtin/log.c:405
 #: builtin/log.c:1012 builtin/log.c:1541 builtin/log.c:1945 builtin/log.c:2235
-#: builtin/merge.c:415 builtin/pack-objects.c:3276 builtin/pack-objects.c:3291
+#: builtin/merge.c:415 builtin/pack-objects.c:3348 builtin/pack-objects.c:3363
 #: builtin/shortlog.c:192
 msgid "revision walk setup failed"
 msgstr "Einrichtung des Revisionsgangs fehlgeschlagen"
@@ -1995,84 +2031,88 @@
 msgid "HEAD of working tree %s is not updated"
 msgstr "HEAD des Arbeitsverzeichnisses %s ist nicht aktualisiert."
 
-#: bundle.c:36
+#: bundle.c:47
 #, c-format
 msgid "'%s' does not look like a v2 bundle file"
 msgstr "'%s' sieht nicht wie eine v2 Paketdatei aus"
 
-#: bundle.c:64
+#: bundle.c:69
+msgid "unknown hash algorithm length"
+msgstr "unbekannte Länge des Hash-Algorithmus"
+
+#: bundle.c:84
 #, c-format
 msgid "unrecognized header: %s%s (%d)"
 msgstr "nicht erkannter Kopfbereich: %s%s (%d)"
 
-#: bundle.c:90 rerere.c:480 rerere.c:690 sequencer.c:2270 sequencer.c:3034
+#: bundle.c:110 rerere.c:480 rerere.c:690 sequencer.c:2270 sequencer.c:3034
 #: builtin/commit.c:814
 #, c-format
 msgid "could not open '%s'"
 msgstr "Konnte '%s' nicht öffnen"
 
-#: bundle.c:143
+#: bundle.c:163
 msgid "Repository lacks these prerequisite commits:"
 msgstr "Dem Repository fehlen folgende vorausgesetzte Commits:"
 
-#: bundle.c:146
+#: bundle.c:166
 msgid "need a repository to verify a bundle"
 msgstr "Um ein Paket zu überprüfen wird ein Repository benötigt."
 
-#: bundle.c:197
+#: bundle.c:217
 #, c-format
 msgid "The bundle contains this ref:"
 msgid_plural "The bundle contains these %d refs:"
 msgstr[0] "Das Paket enthält diese Referenz:"
 msgstr[1] "Das Paket enthält diese %d Referenzen:"
 
-#: bundle.c:204
+#: bundle.c:224
 msgid "The bundle records a complete history."
 msgstr "Das Paket speichert eine komplette Historie."
 
-#: bundle.c:206
+#: bundle.c:226
 #, c-format
 msgid "The bundle requires this ref:"
 msgid_plural "The bundle requires these %d refs:"
 msgstr[0] "Das Paket benötigt diese Referenz:"
 msgstr[1] "Das Paket benötigt diese %d Referenzen:"
 
-#: bundle.c:273
+#: bundle.c:293
 msgid "unable to dup bundle descriptor"
 msgstr "Konnte dup für Descriptor des Pakets nicht ausführen."
 
-#: bundle.c:280
+#: bundle.c:300
 msgid "Could not spawn pack-objects"
 msgstr "Konnte Paketobjekte nicht erstellen"
 
-#: bundle.c:291
+#: bundle.c:311
 msgid "pack-objects died"
 msgstr "Erstellung der Paketobjekte abgebrochen"
 
-#: bundle.c:333
+#: bundle.c:353
 msgid "rev-list died"
 msgstr "\"rev-list\" abgebrochen"
 
-#: bundle.c:382
+#: bundle.c:402
 #, c-format
 msgid "ref '%s' is excluded by the rev-list options"
 msgstr "Referenz '%s' wird durch \"rev-list\" Optionen ausgeschlossen"
 
-#: bundle.c:461 builtin/log.c:208 builtin/log.c:1834 builtin/shortlog.c:306
+#: bundle.c:481 builtin/log.c:208 builtin/log.c:1834 builtin/shortlog.c:306
 #, c-format
 msgid "unrecognized argument: %s"
 msgstr "nicht erkanntes Argument: %s"
 
-#: bundle.c:469
+#: bundle.c:489
 msgid "Refusing to create empty bundle."
 msgstr "Erstellung eines leeren Pakets zurückgewiesen."
 
-#: bundle.c:479
+#: bundle.c:499
 #, c-format
 msgid "cannot create '%s'"
 msgstr "kann '%s' nicht erstellen"
 
-#: bundle.c:504
+#: bundle.c:524
 msgid "index-pack died"
 msgstr "Erstellung der Paketindexdatei abgebrochen"
 
@@ -2081,258 +2121,250 @@
 msgid "invalid color value: %.*s"
 msgstr "Ungültiger Farbwert: %.*s"
 
-#: commit-graph.c:183
+#: commit-graph.c:238
 msgid "commit-graph file is too small"
 msgstr "Commit-Graph-Datei ist zu klein."
 
-#: commit-graph.c:248
+#: commit-graph.c:303
 #, c-format
 msgid "commit-graph signature %X does not match signature %X"
 msgstr "Commit-Graph-Signatur %X stimmt nicht mit Signatur %X überein."
 
-#: commit-graph.c:255
+#: commit-graph.c:310
 #, c-format
 msgid "commit-graph version %X does not match version %X"
 msgstr "Commit-Graph-Version %X stimmt nicht mit Version %X überein."
 
-#: commit-graph.c:262
+#: commit-graph.c:317
 #, c-format
 msgid "commit-graph hash version %X does not match version %X"
 msgstr "Hash-Version des Commit-Graph %X stimmt nicht mit Version %X überein."
 
-#: commit-graph.c:284
+#: commit-graph.c:339
 msgid "commit-graph chunk lookup table entry missing; file may be incomplete"
 msgstr ""
 "fehlender Tabelleneintrag für Commit-Graph Chunk-Lookup; Datei "
 "möglicherweise unvollständig"
 
-#: commit-graph.c:294
+#: commit-graph.c:349
 #, c-format
 msgid "commit-graph improper chunk offset %08x%08x"
 msgstr "Unzulässiger Commit-Graph Chunk-Offset %08x%08x"
 
-#: commit-graph.c:362
+#: commit-graph.c:417
 #, c-format
 msgid "commit-graph chunk id %08x appears multiple times"
 msgstr "Commit-Graph Chunk-Id %08x kommt mehrfach vor."
 
-#: commit-graph.c:436
+#: commit-graph.c:491
 msgid "commit-graph has no base graphs chunk"
 msgstr "Commit-Graph hat keinen Basis-Graph-Chunk"
 
-#: commit-graph.c:446
+#: commit-graph.c:501
 msgid "commit-graph chain does not match"
 msgstr "Commit-Graph Verkettung stimmt nicht überein."
 
-#: commit-graph.c:494
+#: commit-graph.c:549
 #, c-format
 msgid "invalid commit-graph chain: line '%s' not a hash"
 msgstr "Ungültige Commit-Graph Verkettung: Zeile '%s' ist kein Hash"
 
-#: commit-graph.c:518
+#: commit-graph.c:573
 msgid "unable to find all commit-graph files"
 msgstr "Konnte nicht alle Commit-Graph-Dateien finden."
 
-#: commit-graph.c:651 commit-graph.c:711
+#: commit-graph.c:706 commit-graph.c:770
 msgid "invalid commit position. commit-graph is likely corrupt"
 msgstr "Ungültige Commit-Position. Commit-Graph ist wahrscheinlich beschädigt."
 
-#: commit-graph.c:672
+#: commit-graph.c:727
 #, c-format
 msgid "could not find commit %s"
 msgstr "Konnte Commit %s nicht finden."
 
-#: commit-graph.c:948 builtin/am.c:1292
+#: commit-graph.c:1009 builtin/am.c:1292
 #, c-format
 msgid "unable to parse commit %s"
 msgstr "Konnte Commit '%s' nicht parsen."
 
-#: commit-graph.c:1096
+#: commit-graph.c:1157
 msgid "Writing changed paths Bloom filters index"
 msgstr "Schreibe Index für veränderte Pfade Bloom-Filter"
 
-#: commit-graph.c:1121
+#: commit-graph.c:1182
 msgid "Writing changed paths Bloom filters data"
 msgstr "Schreibe Daten für veränderte Pfade Bloom-Filter"
 
-#: commit-graph.c:1160 builtin/pack-objects.c:2783
+#: commit-graph.c:1221 builtin/pack-objects.c:2832
 #, c-format
 msgid "unable to get type of object %s"
 msgstr "Konnte Art von Objekt '%s' nicht bestimmen."
 
-#: commit-graph.c:1196
+#: commit-graph.c:1257
 msgid "Loading known commits in commit graph"
 msgstr "Lade bekannte Commits in Commit-Graph"
 
-#: commit-graph.c:1213
+#: commit-graph.c:1274
 msgid "Expanding reachable commits in commit graph"
 msgstr "Erweitere erreichbare Commits in Commit-Graph"
 
-#: commit-graph.c:1233
+#: commit-graph.c:1294
 msgid "Clearing commit marks in commit graph"
 msgstr "Lösche Commit-Markierungen in Commit-Graph"
 
-#: commit-graph.c:1252
+#: commit-graph.c:1313
 msgid "Computing commit graph generation numbers"
 msgstr "Commit-Graph Generationsnummern berechnen"
 
-#: commit-graph.c:1300
+#: commit-graph.c:1367
 msgid "Computing commit changed paths Bloom filters"
 msgstr "Berechnung der Bloom-Filter für veränderte Pfade des Commits"
 
-#: commit-graph.c:1359
+#: commit-graph.c:1423
+msgid "Collecting referenced commits"
+msgstr "Sammle referenzierte Commits"
+
+#: commit-graph.c:1447
 #, c-format
 msgid "Finding commits for commit graph in %d pack"
 msgid_plural "Finding commits for commit graph in %d packs"
 msgstr[0] "Suche Commits für Commit-Graph in %d Paket"
 msgstr[1] "Suche Commits für Commit-Graph in %d Paketen"
 
-#: commit-graph.c:1372
+#: commit-graph.c:1460
 #, c-format
 msgid "error adding pack %s"
 msgstr "Fehler beim Hinzufügen von Paket %s."
 
-#: commit-graph.c:1376
+#: commit-graph.c:1464
 #, c-format
 msgid "error opening index for %s"
 msgstr "Fehler beim Öffnen des Index für %s."
 
-#: commit-graph.c:1405
-#, c-format
-msgid "Finding commits for commit graph from %d ref"
-msgid_plural "Finding commits for commit graph from %d refs"
-msgstr[0] "Suche Commits für Commit-Graph in %d Referenz"
-msgstr[1] "Suche Commits für Commit-Graph in %d Referenzen"
-
-#: commit-graph.c:1426
-#, c-format
-msgid "invalid commit object id: %s"
-msgstr "ungültige Commit-Objekt-ID: %s"
-
-#: commit-graph.c:1442
+#: commit-graph.c:1503
 msgid "Finding commits for commit graph among packed objects"
 msgstr "Suche Commits für Commit-Graph in gepackten Objekten"
 
-#: commit-graph.c:1457
+#: commit-graph.c:1518
 msgid "Counting distinct commits in commit graph"
 msgstr "Zähle Commits in Commit-Graph"
 
-#: commit-graph.c:1489
+#: commit-graph.c:1550
 msgid "Finding extra edges in commit graph"
 msgstr "Suche zusätzliche Ränder in Commit-Graph"
 
-#: commit-graph.c:1538
+#: commit-graph.c:1599
 msgid "failed to write correct number of base graph ids"
 msgstr "Fehler beim Schreiben der korrekten Anzahl von Basis-Graph-IDs."
 
-#: commit-graph.c:1572 midx.c:812
+#: commit-graph.c:1633 midx.c:812
 #, c-format
 msgid "unable to create leading directories of %s"
 msgstr "Konnte führende Verzeichnisse von '%s' nicht erstellen."
 
-#: commit-graph.c:1585
+#: commit-graph.c:1646
 msgid "unable to create temporary graph layer"
 msgstr "konnte temporäre Graphen-Schicht nicht erstellen"
 
-#: commit-graph.c:1590
+#: commit-graph.c:1651
 #, c-format
 msgid "unable to adjust shared permissions for '%s'"
 msgstr "konnte geteilte Zugriffsberechtigungen für '%s' nicht ändern"
 
-#: commit-graph.c:1667
+#: commit-graph.c:1728
 #, c-format
 msgid "Writing out commit graph in %d pass"
 msgid_plural "Writing out commit graph in %d passes"
 msgstr[0] "Schreibe Commit-Graph in %d Durchgang"
 msgstr[1] "Schreibe Commit-Graph in %d Durchgängen"
 
-#: commit-graph.c:1712
+#: commit-graph.c:1773
 msgid "unable to open commit-graph chain file"
 msgstr "Konnte Commit-Graph Chain-Datei nicht öffnen."
 
-#: commit-graph.c:1728
+#: commit-graph.c:1789
 msgid "failed to rename base commit-graph file"
 msgstr "Konnte Basis-Commit-Graph-Datei nicht umbenennen."
 
-#: commit-graph.c:1748
+#: commit-graph.c:1809
 msgid "failed to rename temporary commit-graph file"
 msgstr "Konnte temporäre Commit-Graph-Datei nicht umbenennen."
 
-#: commit-graph.c:1874
+#: commit-graph.c:1935
 msgid "Scanning merged commits"
 msgstr "Durchsuche zusammengeführte Commits"
 
-#: commit-graph.c:1885
+#: commit-graph.c:1946
 #, c-format
 msgid "unexpected duplicate commit id %s"
 msgstr "Unerwartete doppelte Commit-ID %s"
 
-#: commit-graph.c:1908
+#: commit-graph.c:1969
 msgid "Merging commit-graph"
 msgstr "Zusammenführen von Commit-Graph"
 
-#: commit-graph.c:2096
+#: commit-graph.c:2156
 #, c-format
 msgid "the commit graph format cannot write %d commits"
 msgstr "Das Commit-Graph Format kann nicht %d Commits schreiben."
 
-#: commit-graph.c:2107
+#: commit-graph.c:2167
 msgid "too many commits to write graph"
 msgstr "Zu viele Commits zum Schreiben des Graphen."
 
-#: commit-graph.c:2200
+#: commit-graph.c:2260
 msgid "the commit-graph file has incorrect checksum and is likely corrupt"
 msgstr ""
 "Die Commit-Graph-Datei hat eine falsche Prüfsumme und ist wahrscheinlich "
 "beschädigt."
 
-#: commit-graph.c:2210
+#: commit-graph.c:2270
 #, c-format
 msgid "commit-graph has incorrect OID order: %s then %s"
 msgstr "Commit-Graph hat fehlerhafte OID-Reihenfolge: %s dann %s"
 
-#: commit-graph.c:2220 commit-graph.c:2235
+#: commit-graph.c:2280 commit-graph.c:2295
 #, c-format
 msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u"
 msgstr "Commit-Graph hat fehlerhaften Fanout-Wert: fanout[%d] = %u != %u"
 
-#: commit-graph.c:2227
+#: commit-graph.c:2287
 #, c-format
 msgid "failed to parse commit %s from commit-graph"
 msgstr "Konnte Commit %s von Commit-Graph nicht parsen."
 
-#: commit-graph.c:2245
+#: commit-graph.c:2305
 msgid "Verifying commits in commit graph"
 msgstr "Commit in Commit-Graph überprüfen"
 
-#: commit-graph.c:2259
+#: commit-graph.c:2320
 #, c-format
 msgid "failed to parse commit %s from object database for commit-graph"
 msgstr ""
 "Fehler beim Parsen des Commits %s von Objekt-Datenbank für Commit-Graph"
 
-#: commit-graph.c:2266
+#: commit-graph.c:2327
 #, c-format
 msgid "root tree OID for commit %s in commit-graph is %s != %s"
 msgstr ""
 "OID des Wurzelverzeichnisses für Commit %s in Commit-Graph ist %s != %s"
 
-#: commit-graph.c:2276
+#: commit-graph.c:2337
 #, c-format
 msgid "commit-graph parent list for commit %s is too long"
 msgstr "Commit-Graph Vorgänger-Liste für Commit %s ist zu lang"
 
-#: commit-graph.c:2285
+#: commit-graph.c:2346
 #, c-format
 msgid "commit-graph parent for %s is %s != %s"
 msgstr "Commit-Graph-Vorgänger für %s ist %s != %s"
 
-#: commit-graph.c:2298
+#: commit-graph.c:2360
 #, c-format
 msgid "commit-graph parent list for commit %s terminates early"
 msgstr "Commit-Graph Vorgänger-Liste für Commit %s endet zu früh"
 
-#: commit-graph.c:2303
+#: commit-graph.c:2365
 #, c-format
 msgid ""
 "commit-graph has generation number zero for commit %s, but non-zero elsewhere"
@@ -2340,7 +2372,7 @@
 "Commit-Graph hat Generationsnummer null für Commit %s, aber sonst ungleich "
 "null"
 
-#: commit-graph.c:2307
+#: commit-graph.c:2369
 #, c-format
 msgid ""
 "commit-graph has non-zero generation number for commit %s, but zero elsewhere"
@@ -2348,12 +2380,12 @@
 "Commit-Graph hat Generationsnummer ungleich null für Commit %s, aber sonst "
 "null"
 
-#: commit-graph.c:2322
+#: commit-graph.c:2385
 #, c-format
 msgid "commit-graph generation for commit %s is %u != %u"
 msgstr "Commit-Graph Erstellung für Commit %s ist %u != %u"
 
-#: commit-graph.c:2328
+#: commit-graph.c:2391
 #, c-format
 msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>"
 msgstr ""
@@ -2391,28 +2423,28 @@
 "Sie können diese Meldung unterdrücken, indem Sie\n"
 "\"git config advice.graftFileDeprecated false\" ausführen."
 
-#: commit.c:1168
+#: commit.c:1172
 #, c-format
 msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
 msgstr ""
 "Commit %s hat eine nicht vertrauenswürdige GPG-Signatur, angeblich von %s."
 
-#: commit.c:1172
+#: commit.c:1176
 #, c-format
 msgid "Commit %s has a bad GPG signature allegedly by %s."
 msgstr "Commit %s hat eine ungültige GPG-Signatur, angeblich von %s."
 
-#: commit.c:1175
+#: commit.c:1179
 #, c-format
 msgid "Commit %s does not have a GPG signature."
 msgstr "Commit %s hat keine GPG-Signatur."
 
-#: commit.c:1178
+#: commit.c:1182
 #, c-format
 msgid "Commit %s has a good GPG signature by %s\n"
 msgstr "Commit %s hat eine gültige GPG-Signatur von %s\n"
 
-#: commit.c:1432
+#: commit.c:1436
 msgid ""
 "Warning: commit message did not conform to UTF-8.\n"
 "You may want to amend it after fixing the message, or set the config\n"
@@ -2614,7 +2646,7 @@
 msgstr ""
 "Muss einer von diesen sein: nothing, matching, simple, upstream, current"
 
-#: config.c:1533 builtin/pack-objects.c:3542
+#: config.c:1533 builtin/pack-objects.c:3617
 #, c-format
 msgid "bad pack compression level %d"
 msgstr "ungültiger Komprimierungsgrad (%d) für Paketierung"
@@ -2770,74 +2802,83 @@
 msgid "server doesn't support '%s'"
 msgstr "Der Server unterstützt kein '%s'."
 
-#: connect.c:103
+#: connect.c:118
 #, c-format
 msgid "server doesn't support feature '%s'"
 msgstr "Der Server unterstützt das Feature '%s' nicht."
 
-#: connect.c:114
+#: connect.c:129
 msgid "expected flush after capabilities"
 msgstr "Erwartete Flush nach Fähigkeiten."
 
-#: connect.c:233
+#: connect.c:263
 #, c-format
 msgid "ignoring capabilities after first line '%s'"
 msgstr "Ignoriere Fähigkeiten nach der ersten Zeile '%s'."
 
-#: connect.c:252
+#: connect.c:284
 msgid "protocol error: unexpected capabilities^{}"
 msgstr "Protokollfehler: unerwartetes capabilities^{}"
 
-#: connect.c:273
+#: connect.c:306
 #, c-format
 msgid "protocol error: expected shallow sha-1, got '%s'"
 msgstr "Protokollfehler: shallow SHA-1 erwartet, '%s' bekommen"
 
-#: connect.c:275
+#: connect.c:308
 msgid "repository on the other end cannot be shallow"
 msgstr ""
 "Repository auf der Gegenseite kann keine unvollständige Historie (shallow) "
 "enthalten"
 
-#: connect.c:313
+#: connect.c:347
 msgid "invalid packet"
-msgstr "Ungültiges Paket."
+msgstr "ungültiges Paket"
 
-#: connect.c:333
+#: connect.c:367
 #, c-format
 msgid "protocol error: unexpected '%s'"
 msgstr "Protokollfehler: unerwartetes '%s'"
 
-#: connect.c:441
+#: connect.c:473
+#, c-format
+msgid "unknown object format '%s' specified by server"
+msgstr "unbekanntes Objekt-Format '%s' vom Server angegeben"
+
+#: connect.c:500
 #, c-format
 msgid "invalid ls-refs response: %s"
-msgstr "Ungültige ls-refs Antwort: %s"
+msgstr "ungültige ls-refs Antwort: %s"
 
-#: connect.c:445
+#: connect.c:504
 msgid "expected flush after ref listing"
-msgstr "Erwartete Flush nach Auflistung der Referenzen."
+msgstr "Flush nach Auflistung der Referenzen erwartet"
 
-#: connect.c:544
+#: connect.c:507
+msgid "expected response end packet after ref listing"
+msgstr "Antwort-Endpaket nach Auflistung der Referenzen erwartet"
+
+#: connect.c:640
 #, c-format
 msgid "protocol '%s' is not supported"
-msgstr "Protokoll '%s' wird nicht unterstützt."
+msgstr "Protokoll '%s' wird nicht unterstützt"
 
-#: connect.c:595
+#: connect.c:691
 msgid "unable to set SO_KEEPALIVE on socket"
-msgstr "Kann SO_KEEPALIVE bei Socket nicht setzen."
+msgstr "kann SO_KEEPALIVE bei Socket nicht setzen"
 
-#: connect.c:635 connect.c:698
+#: connect.c:731 connect.c:794
 #, c-format
 msgid "Looking up %s ... "
 msgstr "Suche nach %s ..."
 
-#: connect.c:639
+#: connect.c:735
 #, c-format
 msgid "unable to look up %s (port %s) (%s)"
 msgstr "Fehler bei Suche nach %s (Port %s) (%s)."
 
 #. TRANSLATORS: this is the end of "Looking up %s ... "
-#: connect.c:643 connect.c:714
+#: connect.c:739 connect.c:810
 #, c-format
 msgid ""
 "done.\n"
@@ -2846,7 +2887,7 @@
 "Fertig.\n"
 "Verbinde nach %s (Port %s) ... "
 
-#: connect.c:665 connect.c:742
+#: connect.c:761 connect.c:838
 #, c-format
 msgid ""
 "unable to connect to %s:\n"
@@ -2856,76 +2897,76 @@
 "%s"
 
 #. TRANSLATORS: this is the end of "Connecting to %s (port %s) ... "
-#: connect.c:671 connect.c:748
+#: connect.c:767 connect.c:844
 msgid "done."
 msgstr "Fertig."
 
-#: connect.c:702
+#: connect.c:798
 #, c-format
 msgid "unable to look up %s (%s)"
 msgstr "Fehler bei der Suche nach %s (%s)"
 
-#: connect.c:708
+#: connect.c:804
 #, c-format
 msgid "unknown port %s"
 msgstr "Unbekannter Port %s"
 
-#: connect.c:845 connect.c:1175
+#: connect.c:941 connect.c:1271
 #, c-format
 msgid "strange hostname '%s' blocked"
 msgstr "Merkwürdigen Hostnamen '%s' blockiert."
 
-#: connect.c:847
+#: connect.c:943
 #, c-format
 msgid "strange port '%s' blocked"
 msgstr "Merkwürdigen Port '%s' blockiert."
 
-#: connect.c:857
+#: connect.c:953
 #, c-format
 msgid "cannot start proxy %s"
 msgstr "Kann Proxy %s nicht starten."
 
-#: connect.c:928
+#: connect.c:1024
 msgid "no path specified; see 'git help pull' for valid url syntax"
 msgstr ""
 "Kein Pfad angegeben; siehe 'git help pull' für eine gültige URL-Syntax."
 
-#: connect.c:1123
+#: connect.c:1219
 msgid "ssh variant 'simple' does not support -4"
 msgstr "SSH-Variante 'simple' unterstützt kein -4."
 
-#: connect.c:1135
+#: connect.c:1231
 msgid "ssh variant 'simple' does not support -6"
 msgstr "SSH-Variante 'simple' unterstützt kein -6."
 
-#: connect.c:1152
+#: connect.c:1248
 msgid "ssh variant 'simple' does not support setting port"
 msgstr "SSH-Variante 'simple' unterstützt nicht das Setzen eines Ports."
 
-#: connect.c:1264
+#: connect.c:1360
 #, c-format
 msgid "strange pathname '%s' blocked"
 msgstr "Merkwürdigen Pfadnamen '%s' blockiert."
 
-#: connect.c:1311
+#: connect.c:1407
 msgid "unable to fork"
 msgstr "Kann Prozess nicht starten."
 
-#: connected.c:107 builtin/fsck.c:209 builtin/prune.c:45
+#: connected.c:109 builtin/fsck.c:209 builtin/prune.c:45
 msgid "Checking connectivity"
 msgstr "Prüfe Konnektivität"
 
-#: connected.c:119
+#: connected.c:121
 msgid "Could not run 'git rev-list'"
 msgstr "Konnte 'git rev-list' nicht ausführen"
 
-#: connected.c:139
+#: connected.c:141
 msgid "failed write to rev-list"
 msgstr "Fehler beim Schreiben nach rev-list"
 
-#: connected.c:146
+#: connected.c:148
 msgid "failed to close rev-list's stdin"
-msgstr "Fehler beim Schließen von rev-list's Standard-Eingabe"
+msgstr "Fehler beim Schließen von rev-lists Standard-Eingabe"
 
 #: convert.c:194
 #, c-format
@@ -3191,18 +3232,18 @@
 "Kein Git-Repository. Nutzen Sie --no-index, um zwei Pfade außerhalb des "
 "Arbeitsverzeichnisses zu vergleichen."
 
-#: diff.c:155
+#: diff.c:156
 #, c-format
 msgid "  Failed to parse dirstat cut-off percentage '%s'\n"
 msgstr ""
 "  Fehler beim Parsen des abgeschnittenen \"dirstat\" Prozentsatzes '%s'\n"
 
-#: diff.c:160
+#: diff.c:161
 #, c-format
 msgid "  Unknown dirstat parameter '%s'\n"
 msgstr "  Unbekannter \"dirstat\" Parameter '%s'\n"
 
-#: diff.c:296
+#: diff.c:297
 msgid ""
 "color moved setting must be one of 'no', 'default', 'blocks', 'zebra', "
 "'dimmed-zebra', 'plain'"
@@ -3210,7 +3251,7 @@
 "\"color moved\"-Einstellung muss eines von diesen sein: 'no', 'default', "
 "'blocks', 'zebra', 'dimmed_zebra', 'plain'"
 
-#: diff.c:324
+#: diff.c:325
 #, c-format
 msgid ""
 "unknown color-moved-ws mode '%s', possible values are 'ignore-space-change', "
@@ -3219,7 +3260,7 @@
 "Unbekannter color-moved-ws Modus '%s', mögliche Werte sind 'ignore-space-"
 "change', 'ignore-space-at-eol', 'ignore-all-space', 'allow-identation-change'"
 
-#: diff.c:332
+#: diff.c:333
 msgid ""
 "color-moved-ws: allow-indentation-change cannot be combined with other "
 "whitespace modes"
@@ -3227,12 +3268,12 @@
 "color-moved-ws: allow-indentation-change kann nicht mit anderen\n"
 "Whitespace-Modi kombiniert werden."
 
-#: diff.c:405
+#: diff.c:410
 #, c-format
 msgid "Unknown value for 'diff.submodule' config variable: '%s'"
 msgstr "Unbekannter Wert in Konfigurationsvariable 'diff.dirstat': '%s'"
 
-#: diff.c:465
+#: diff.c:470
 #, c-format
 msgid ""
 "Found errors in 'diff.dirstat' config variable:\n"
@@ -3241,36 +3282,36 @@
 "Fehler in 'diff.dirstat' Konfigurationsvariable gefunden:\n"
 "%s"
 
-#: diff.c:4238
+#: diff.c:4243
 #, c-format
 msgid "external diff died, stopping at %s"
 msgstr "externes Diff-Programm unerwartet beendet, angehalten bei %s"
 
-#: diff.c:4583
+#: diff.c:4589
 msgid "--name-only, --name-status, --check and -s are mutually exclusive"
 msgstr ""
 "--name-only, --name-status, --check und -s schließen sich gegenseitig aus"
 
-#: diff.c:4586
+#: diff.c:4592
 msgid "-G, -S and --find-object are mutually exclusive"
 msgstr "-G, -S und --find-object schließen sich gegenseitig aus"
 
-#: diff.c:4664
+#: diff.c:4670
 msgid "--follow requires exactly one pathspec"
 msgstr "--follow erfordert genau eine Pfadspezifikation"
 
-#: diff.c:4712
+#: diff.c:4718
 #, c-format
 msgid "invalid --stat value: %s"
 msgstr "Ungültiger --stat Wert: %s"
 
-#: diff.c:4717 diff.c:4722 diff.c:4727 diff.c:4732 diff.c:5245
+#: diff.c:4723 diff.c:4728 diff.c:4733 diff.c:4738 diff.c:5250
 #: parse-options.c:197 parse-options.c:201
 #, c-format
 msgid "%s expects a numerical value"
 msgstr "%s erwartet einen numerischen Wert."
 
-#: diff.c:4749
+#: diff.c:4755
 #, c-format
 msgid ""
 "Failed to parse --dirstat/-X option parameter:\n"
@@ -3279,42 +3320,42 @@
 "Fehler beim Parsen des --dirstat/-X Optionsparameters:\n"
 "%s"
 
-#: diff.c:4834
+#: diff.c:4840
 #, c-format
 msgid "unknown change class '%c' in --diff-filter=%s"
 msgstr "Unbekannte Änderungsklasse '%c' in --diff-filter=%s"
 
-#: diff.c:4858
+#: diff.c:4864
 #, c-format
 msgid "unknown value after ws-error-highlight=%.*s"
 msgstr "Unbekannter Wert nach ws-error-highlight=%.*s"
 
-#: diff.c:4872
+#: diff.c:4878
 #, c-format
 msgid "unable to resolve '%s'"
 msgstr "konnte '%s' nicht auflösen"
 
-#: diff.c:4922 diff.c:4928
+#: diff.c:4928 diff.c:4934
 #, c-format
 msgid "%s expects <n>/<m> form"
 msgstr "%s erwartet die Form <n>/<m>"
 
-#: diff.c:4940
+#: diff.c:4946
 #, c-format
 msgid "%s expects a character, got '%s'"
 msgstr "%s erwartet ein Zeichen, '%s' bekommen"
 
-#: diff.c:4961
+#: diff.c:4967
 #, c-format
 msgid "bad --color-moved argument: %s"
 msgstr "Ungültiges --color-moved Argument: %s"
 
-#: diff.c:4980
+#: diff.c:4986
 #, c-format
 msgid "invalid mode '%s' in --color-moved-ws"
 msgstr "Ungültiger Modus '%s' in --color-moved-ws"
 
-#: diff.c:5020
+#: diff.c:5026
 msgid ""
 "option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
 "\"histogram\""
@@ -3322,152 +3363,152 @@
 "Option diff-algorithm akzeptiert: \"myers\", \"minimal\", \"patience\" and "
 "\"histogram\""
 
-#: diff.c:5056 diff.c:5076
+#: diff.c:5062 diff.c:5082
 #, c-format
 msgid "invalid argument to %s"
 msgstr "Ungültiges Argument für %s"
 
-#: diff.c:5214
+#: diff.c:5219
 #, c-format
 msgid "failed to parse --submodule option parameter: '%s'"
 msgstr "Fehler beim Parsen des --submodule Optionsparameters: '%s'"
 
-#: diff.c:5270
+#: diff.c:5275
 #, c-format
 msgid "bad --word-diff argument: %s"
 msgstr "Ungültiges --word-diff Argument: %s"
 
-#: diff.c:5293
+#: diff.c:5298
 msgid "Diff output format options"
 msgstr "Diff-Optionen zu Ausgabeformaten"
 
-#: diff.c:5295 diff.c:5301
+#: diff.c:5300 diff.c:5306
 msgid "generate patch"
 msgstr "Erzeuge Patch"
 
-#: diff.c:5298 builtin/log.c:177
+#: diff.c:5303 builtin/log.c:177
 msgid "suppress diff output"
 msgstr "Ausgabe der Unterschiede unterdrücken"
 
-#: diff.c:5303 diff.c:5417 diff.c:5424
+#: diff.c:5308 diff.c:5422 diff.c:5429
 msgid "<n>"
 msgstr "<n>"
 
-#: diff.c:5304 diff.c:5307
+#: diff.c:5309 diff.c:5312
 msgid "generate diffs with <n> lines context"
 msgstr "Erstelle Unterschiede mit <n> Zeilen des Kontextes"
 
-#: diff.c:5309
+#: diff.c:5314
 msgid "generate the diff in raw format"
 msgstr "Erstelle Unterschiede im Rohformat"
 
-#: diff.c:5312
+#: diff.c:5317
 msgid "synonym for '-p --raw'"
 msgstr "Synonym für '-p --raw'"
 
-#: diff.c:5316
+#: diff.c:5321
 msgid "synonym for '-p --stat'"
 msgstr "Synonym für '-p --stat'"
 
-#: diff.c:5320
+#: diff.c:5325
 msgid "machine friendly --stat"
 msgstr "maschinenlesbare Ausgabe von --stat"
 
-#: diff.c:5323
+#: diff.c:5328
 msgid "output only the last line of --stat"
 msgstr "nur die letzte Zeile von --stat ausgeben"
 
-#: diff.c:5325 diff.c:5333
+#: diff.c:5330 diff.c:5338
 msgid "<param1,param2>..."
 msgstr "<Parameter1,Parameter2>..."
 
-#: diff.c:5326
+#: diff.c:5331
 msgid ""
 "output the distribution of relative amount of changes for each sub-directory"
 msgstr ""
 "Gebe die Verteilung des relativen Umfangs der Änderungen für jedes "
 "Unterverzeichnis aus"
 
-#: diff.c:5330
+#: diff.c:5335
 msgid "synonym for --dirstat=cumulative"
 msgstr "Synonym für --dirstat=cumulative"
 
-#: diff.c:5334
+#: diff.c:5339
 msgid "synonym for --dirstat=files,param1,param2..."
 msgstr "Synonym für --dirstat=files,Parameter1,Parameter2..."
 
-#: diff.c:5338
+#: diff.c:5343
 msgid "warn if changes introduce conflict markers or whitespace errors"
 msgstr ""
 "Warnen, wenn Änderungen Konfliktmarker oder Whitespace-Fehler einbringen"
 
-#: diff.c:5341
+#: diff.c:5346
 msgid "condensed summary such as creations, renames and mode changes"
 msgstr ""
 "Gekürzte Zusammenfassung, wie z.B. Erstellungen, Umbenennungen und "
 "Änderungen der Datei-Rechte"
 
-#: diff.c:5344
+#: diff.c:5349
 msgid "show only names of changed files"
 msgstr "nur Dateinamen der geänderten Dateien anzeigen"
 
-#: diff.c:5347
+#: diff.c:5352
 msgid "show only names and status of changed files"
 msgstr "nur Dateinamen und Status der geänderten Dateien anzeigen"
 
-#: diff.c:5349
+#: diff.c:5354
 msgid "<width>[,<name-width>[,<count>]]"
 msgstr "<Breite>[,<Namens-Breite>[,<Anzahl>]]"
 
-#: diff.c:5350
+#: diff.c:5355
 msgid "generate diffstat"
 msgstr "Generiere Zusammenfassung der Unterschiede"
 
-#: diff.c:5352 diff.c:5355 diff.c:5358
+#: diff.c:5357 diff.c:5360 diff.c:5363
 msgid "<width>"
 msgstr "<Breite>"
 
-#: diff.c:5353
+#: diff.c:5358
 msgid "generate diffstat with a given width"
 msgstr "Erzeuge Zusammenfassung der Unterschiede mit gegebener Breite"
 
-#: diff.c:5356
+#: diff.c:5361
 msgid "generate diffstat with a given name width"
 msgstr "Erzeuge Zusammenfassung der Unterschiede mit gegebener Namens-Breite"
 
-#: diff.c:5359
+#: diff.c:5364
 msgid "generate diffstat with a given graph width"
 msgstr "Erzeuge Zusammenfassung der Unterschiede mit gegebener Graph-Breite"
 
-#: diff.c:5361
+#: diff.c:5366
 msgid "<count>"
 msgstr "<Anzahl>"
 
-#: diff.c:5362
+#: diff.c:5367
 msgid "generate diffstat with limited lines"
 msgstr "Erzeuge Zusammenfassung der Unterschiede mit begrenzten Zeilen"
 
-#: diff.c:5365
+#: diff.c:5370
 msgid "generate compact summary in diffstat"
 msgstr "Erzeuge kompakte Zusammenstellung in Zusammenfassung der Unterschiede"
 
-#: diff.c:5368
+#: diff.c:5373
 msgid "output a binary diff that can be applied"
 msgstr "Gebe eine binäre Differenz aus, dass angewendet werden kann"
 
-#: diff.c:5371
+#: diff.c:5376
 msgid "show full pre- and post-image object names on the \"index\" lines"
 msgstr "Zeige vollständige Objekt-Namen in den \"index\"-Zeilen"
 
-#: diff.c:5373
+#: diff.c:5378
 msgid "show colored diff"
 msgstr "Zeige farbige Unterschiede"
 
-#: diff.c:5374
+#: diff.c:5379
 msgid "<kind>"
 msgstr "<Art>"
 
-#: diff.c:5375
+#: diff.c:5380
 msgid ""
 "highlight whitespace errors in the 'context', 'old' or 'new' lines in the "
 "diff"
@@ -3475,7 +3516,7 @@
 "Hebe Whitespace-Fehler in den Zeilen 'context', 'old' oder 'new' bei den "
 "Unterschieden hervor"
 
-#: diff.c:5378
+#: diff.c:5383
 msgid ""
 "do not munge pathnames and use NULs as output field terminators in --raw or "
 "--numstat"
@@ -3483,91 +3524,91 @@
 "Verschleiere nicht die Pfadnamen und nutze NUL-Zeichen als Schlusszeichen in "
 "Ausgabefeldern bei --raw oder --numstat"
 
-#: diff.c:5381 diff.c:5384 diff.c:5387 diff.c:5493
+#: diff.c:5386 diff.c:5389 diff.c:5392 diff.c:5498
 msgid "<prefix>"
 msgstr "<Präfix>"
 
-#: diff.c:5382
+#: diff.c:5387
 msgid "show the given source prefix instead of \"a/\""
 msgstr "Zeige den gegebenen Quell-Präfix statt \"a/\""
 
-#: diff.c:5385
+#: diff.c:5390
 msgid "show the given destination prefix instead of \"b/\""
 msgstr "Zeige den gegebenen Ziel-Präfix statt \"b/\""
 
-#: diff.c:5388
+#: diff.c:5393
 msgid "prepend an additional prefix to every line of output"
 msgstr "Stelle einen zusätzlichen Präfix bei jeder Ausgabezeile voran"
 
-#: diff.c:5391
+#: diff.c:5396
 msgid "do not show any source or destination prefix"
 msgstr "Zeige keine Quell- oder Ziel-Präfixe an"
 
-#: diff.c:5394
+#: diff.c:5399
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr ""
 "Zeige Kontext zwischen Unterschied-Blöcken bis zur angegebenen Anzahl von "
 "Zeilen."
 
-#: diff.c:5398 diff.c:5403 diff.c:5408
+#: diff.c:5403 diff.c:5408 diff.c:5413
 msgid "<char>"
 msgstr "<Zeichen>"
 
-#: diff.c:5399
+#: diff.c:5404
 msgid "specify the character to indicate a new line instead of '+'"
 msgstr "Das Zeichen festlegen, das eine neue Zeile kennzeichnet (statt '+')"
 
-#: diff.c:5404
+#: diff.c:5409
 msgid "specify the character to indicate an old line instead of '-'"
 msgstr "Das Zeichen festlegen, das eine alte Zeile kennzeichnet (statt '-')"
 
-#: diff.c:5409
+#: diff.c:5414
 msgid "specify the character to indicate a context instead of ' '"
 msgstr "Das Zeichen festlegen, das den Kontext kennzeichnet (statt ' ')"
 
-#: diff.c:5412
+#: diff.c:5417
 msgid "Diff rename options"
 msgstr "Diff-Optionen zur Umbenennung"
 
-#: diff.c:5413
+#: diff.c:5418
 msgid "<n>[/<m>]"
 msgstr "<n>[/<m>]"
 
-#: diff.c:5414
+#: diff.c:5419
 msgid "break complete rewrite changes into pairs of delete and create"
 msgstr ""
 "Teile komplette Rewrite-Änderungen in Änderungen mit \"löschen\" und "
 "\"erstellen\""
 
-#: diff.c:5418
+#: diff.c:5423
 msgid "detect renames"
 msgstr "Umbenennungen erkennen"
 
-#: diff.c:5422
+#: diff.c:5427
 msgid "omit the preimage for deletes"
 msgstr "Preimage für Löschungen weglassen."
 
-#: diff.c:5425
+#: diff.c:5430
 msgid "detect copies"
 msgstr "Kopien erkennen"
 
-#: diff.c:5429
+#: diff.c:5434
 msgid "use unmodified files as source to find copies"
 msgstr "Nutze ungeänderte Dateien als Quelle zum Finden von Kopien"
 
-#: diff.c:5431
+#: diff.c:5436
 msgid "disable rename detection"
 msgstr "Erkennung von Umbenennungen deaktivieren"
 
-#: diff.c:5434
+#: diff.c:5439
 msgid "use empty blobs as rename source"
 msgstr "Nutze leere Blobs als Quelle von Umbennungen"
 
-#: diff.c:5436
+#: diff.c:5441
 msgid "continue listing the history of a file beyond renames"
 msgstr "Fortführen der Auflistung der Historie einer Datei nach Umbennung"
 
-#: diff.c:5439
+#: diff.c:5444
 msgid ""
 "prevent rename/copy detection if the number of rename/copy targets exceeds "
 "given limit"
@@ -3575,159 +3616,159 @@
 "Verhindere die Erkennung von Umbennungen und Kopien, wenn die Anzahl der "
 "Ziele für Umbennungen und Kopien das gegebene Limit überschreitet"
 
-#: diff.c:5441
+#: diff.c:5446
 msgid "Diff algorithm options"
 msgstr "Diff Algorithmus-Optionen"
 
-#: diff.c:5443
+#: diff.c:5448
 msgid "produce the smallest possible diff"
 msgstr "Erzeuge die kleinstmöglichen Änderungen"
 
-#: diff.c:5446
+#: diff.c:5451
 msgid "ignore whitespace when comparing lines"
 msgstr "Whitespace-Änderungen beim Vergleich von Zeilen ignorieren"
 
-#: diff.c:5449
+#: diff.c:5454
 msgid "ignore changes in amount of whitespace"
 msgstr "Änderungen bei der Anzahl von Whitespace ignorieren"
 
-#: diff.c:5452
+#: diff.c:5457
 msgid "ignore changes in whitespace at EOL"
 msgstr "Whitespace-Änderungen am Zeilenende ignorieren"
 
-#: diff.c:5455
+#: diff.c:5460
 msgid "ignore carrier-return at the end of line"
 msgstr "Ignoriere den Zeilenumbruch am Ende der Zeile"
 
-#: diff.c:5458
+#: diff.c:5463
 msgid "ignore changes whose lines are all blank"
 msgstr "Ignoriere Änderungen in leeren Zeilen"
 
-#: diff.c:5461
+#: diff.c:5466
 msgid "heuristic to shift diff hunk boundaries for easy reading"
 msgstr ""
 "Heuristik, um Grenzen der Änderungsblöcke für bessere Lesbarkeit zu "
 "verschieben"
 
-#: diff.c:5464
+#: diff.c:5469
 msgid "generate diff using the \"patience diff\" algorithm"
 msgstr "Erzeuge Änderungen durch Nutzung des Algorithmus \"Patience Diff\""
 
-#: diff.c:5468
+#: diff.c:5473
 msgid "generate diff using the \"histogram diff\" algorithm"
 msgstr "Erzeuge Änderungen durch Nutzung des Algorithmus \"Histogram Diff\""
 
-#: diff.c:5470
+#: diff.c:5475
 msgid "<algorithm>"
 msgstr "<Algorithmus>"
 
-#: diff.c:5471
+#: diff.c:5476
 msgid "choose a diff algorithm"
 msgstr "Ein Algorithmus für Änderungen wählen"
 
-#: diff.c:5473
+#: diff.c:5478
 msgid "<text>"
 msgstr "<Text>"
 
-#: diff.c:5474
+#: diff.c:5479
 msgid "generate diff using the \"anchored diff\" algorithm"
 msgstr "Erzeuge Änderungen durch Nutzung des Algorithmus \"Anchored Diff\""
 
-#: diff.c:5476 diff.c:5485 diff.c:5488
+#: diff.c:5481 diff.c:5490 diff.c:5493
 msgid "<mode>"
 msgstr "<Modus>"
 
-#: diff.c:5477
+#: diff.c:5482
 msgid "show word diff, using <mode> to delimit changed words"
 msgstr "Zeige Wort-Änderungen, nutze <Modus>, um Wörter abzugrenzen"
 
-#: diff.c:5479 diff.c:5482 diff.c:5527
+#: diff.c:5484 diff.c:5487 diff.c:5532
 msgid "<regex>"
 msgstr "<Regex>"
 
-#: diff.c:5480
+#: diff.c:5485
 msgid "use <regex> to decide what a word is"
 msgstr "Nutze <Regex>, um zu entscheiden, was ein Wort ist"
 
-#: diff.c:5483
+#: diff.c:5488
 msgid "equivalent to --word-diff=color --word-diff-regex=<regex>"
 msgstr "Entsprechend wie --word-diff=color --word-diff-regex=<Regex>"
 
-#: diff.c:5486
+#: diff.c:5491
 msgid "moved lines of code are colored differently"
 msgstr "Verschobene Codezeilen sind andersfarbig"
 
-#: diff.c:5489
+#: diff.c:5494
 msgid "how white spaces are ignored in --color-moved"
 msgstr "Wie Whitespaces in --color-moved ignoriert werden"
 
-#: diff.c:5492
+#: diff.c:5497
 msgid "Other diff options"
 msgstr "Andere Diff-Optionen"
 
-#: diff.c:5494
+#: diff.c:5499
 msgid "when run from subdir, exclude changes outside and show relative paths"
 msgstr ""
 "Wenn vom Unterverzeichnis aufgerufen, schließe Änderungen außerhalb aus und "
 "zeige relative Pfade an"
 
-#: diff.c:5498
+#: diff.c:5503
 msgid "treat all files as text"
 msgstr "alle Dateien als Text behandeln"
 
-#: diff.c:5500
+#: diff.c:5505
 msgid "swap two inputs, reverse the diff"
 msgstr "Vertausche die beiden Eingaben und drehe die Änderungen um"
 
-#: diff.c:5502
+#: diff.c:5507
 msgid "exit with 1 if there were differences, 0 otherwise"
 msgstr ""
 "Beende mit Exit-Status 1, wenn Änderungen vorhanden sind, andernfalls mit 0"
 
-#: diff.c:5504
+#: diff.c:5509
 msgid "disable all output of the program"
 msgstr "Keine Ausgaben vom Programm"
 
-#: diff.c:5506
+#: diff.c:5511
 msgid "allow an external diff helper to be executed"
 msgstr "Erlaube die Ausführung eines externes Programms für Änderungen"
 
-#: diff.c:5508
+#: diff.c:5513
 msgid "run external text conversion filters when comparing binary files"
 msgstr ""
 "Führe externe Text-Konvertierungsfilter aus, wenn binäre Dateien vergleicht "
 "werden"
 
-#: diff.c:5510
+#: diff.c:5515
 msgid "<when>"
 msgstr "<wann>"
 
-#: diff.c:5511
+#: diff.c:5516
 msgid "ignore changes to submodules in the diff generation"
 msgstr ""
 "Änderungen in Submodulen während der Erstellung der Unterschiede ignorieren"
 
-#: diff.c:5514
+#: diff.c:5519
 msgid "<format>"
 msgstr "<Format>"
 
-#: diff.c:5515
+#: diff.c:5520
 msgid "specify how differences in submodules are shown"
 msgstr "Angeben, wie Unterschiede in Submodulen gezeigt werden"
 
-#: diff.c:5519
+#: diff.c:5524
 msgid "hide 'git add -N' entries from the index"
 msgstr "verstecke 'git add -N' Einträge vom Index"
 
-#: diff.c:5522
+#: diff.c:5527
 msgid "treat 'git add -N' entries as real in the index"
 msgstr "Behandle 'git add -N' Einträge im Index als echt"
 
-#: diff.c:5524
+#: diff.c:5529
 msgid "<string>"
 msgstr "<Zeichenkette>"
 
-#: diff.c:5525
+#: diff.c:5530
 msgid ""
 "look for differences that change the number of occurrences of the specified "
 "string"
@@ -3735,7 +3776,7 @@
 "Suche nach Unterschieden, welche die Anzahl des Vorkommens der angegebenen "
 "Zeichenkette verändern"
 
-#: diff.c:5528
+#: diff.c:5533
 msgid ""
 "look for differences that change the number of occurrences of the specified "
 "regex"
@@ -3743,25 +3784,25 @@
 "Suche nach Unterschieden, welche die Anzahl des Vorkommens des angegebenen "
 "regulären Ausdrucks verändern"
 
-#: diff.c:5531
+#: diff.c:5536
 msgid "show all changes in the changeset with -S or -G"
 msgstr "zeige alle Änderungen im Changeset mit -S oder -G"
 
-#: diff.c:5534
+#: diff.c:5539
 msgid "treat <string> in -S as extended POSIX regular expression"
 msgstr ""
 "behandle <Zeichenkette> bei -S als erweiterten POSIX regulären Ausdruck"
 
-#: diff.c:5537
+#: diff.c:5542
 msgid "control the order in which files appear in the output"
 msgstr ""
 "kontrolliere die Reihenfolge, in der die Dateien in der Ausgabe erscheinen"
 
-#: diff.c:5538
+#: diff.c:5543
 msgid "<object-id>"
 msgstr "<Objekt-ID>"
 
-#: diff.c:5539
+#: diff.c:5544
 msgid ""
 "look for differences that change the number of occurrences of the specified "
 "object"
@@ -3769,33 +3810,33 @@
 "Suche nach Unterschieden, welche die Anzahl des Vorkommens des angegebenen "
 "Objektes verändern"
 
-#: diff.c:5541
+#: diff.c:5546
 msgid "[(A|C|D|M|R|T|U|X|B)...[*]]"
 msgstr "[(A|C|D|M|R|T|U|X|B)...[*]]"
 
-#: diff.c:5542
+#: diff.c:5547
 msgid "select files by diff type"
 msgstr "Wähle Dateien anhand der Art der Änderung"
 
-#: diff.c:5544
+#: diff.c:5549
 msgid "<file>"
 msgstr "<Datei>"
 
-#: diff.c:5545
+#: diff.c:5550
 msgid "Output to a specific file"
 msgstr "Ausgabe zu einer bestimmten Datei"
 
-#: diff.c:6200
+#: diff.c:6205
 msgid "inexact rename detection was skipped due to too many files."
 msgstr ""
 "Ungenaue Erkennung für Umbenennungen wurde aufgrund zu vieler Dateien\n"
 "übersprungen."
 
-#: diff.c:6203
+#: diff.c:6208
 msgid "only found copies from modified paths due to too many files."
 msgstr "nur Kopien von geänderten Pfaden, aufgrund zu vieler Dateien, gefunden"
 
-#: diff.c:6206
+#: diff.c:6211
 #, c-format
 msgid ""
 "you may want to set your %s variable to at least %d and retry the command."
@@ -3812,64 +3853,64 @@
 msgid "Performing inexact rename detection"
 msgstr "Führe Erkennung für ungenaue Umbenennung aus"
 
-#: dir.c:555
+#: dir.c:573
 #, c-format
 msgid "pathspec '%s' did not match any file(s) known to git"
 msgstr ""
 "Pfadspezifikation '%s' stimmt mit keinen git-bekannten Dateien überein."
 
-#: dir.c:695 dir.c:724 dir.c:737
+#: dir.c:713 dir.c:742 dir.c:755
 #, c-format
 msgid "unrecognized pattern: '%s'"
 msgstr "Unbekanntes Muster: '%s'"
 
-#: dir.c:754 dir.c:768
+#: dir.c:772 dir.c:786
 #, c-format
 msgid "unrecognized negative pattern: '%s'"
 msgstr "Unbekanntes verneinendes Muster: '%s'"
 
-#: dir.c:786
+#: dir.c:804
 #, c-format
 msgid "your sparse-checkout file may have issues: pattern '%s' is repeated"
 msgstr ""
 "Ihre Datei für den partiellen Checkout hat eventuell Probleme:\n"
 "Muster '%s' wiederholt sich."
 
-#: dir.c:796
+#: dir.c:814
 msgid "disabling cone pattern matching"
 msgstr "Deaktiviere Cone-Muster-Übereinstimmung"
 
-#: dir.c:1173
+#: dir.c:1191
 #, c-format
 msgid "cannot use %s as an exclude file"
 msgstr "Kann %s nicht als exclude-Filter benutzen."
 
-#: dir.c:2275
+#: dir.c:2296
 #, c-format
 msgid "could not open directory '%s'"
 msgstr "Konnte Verzeichnis '%s' nicht öffnen."
 
-#: dir.c:2575
+#: dir.c:2596
 msgid "failed to get kernel name and information"
 msgstr "Fehler beim Sammeln von Namen und Informationen zum Kernel"
 
-#: dir.c:2699
+#: dir.c:2720
 msgid "untracked cache is disabled on this system or location"
 msgstr ""
 "Cache für unversionierte Dateien ist auf diesem System oder\n"
 "für dieses Verzeichnis deaktiviert."
 
-#: dir.c:3481
+#: dir.c:3502
 #, c-format
 msgid "index file corrupt in repo %s"
 msgstr "Index-Datei in Repository %s beschädigt."
 
-#: dir.c:3526 dir.c:3531
+#: dir.c:3547 dir.c:3552
 #, c-format
 msgid "could not create directories for %s"
 msgstr "Konnte Verzeichnisse für '%s' nicht erstellen."
 
-#: dir.c:3560
+#: dir.c:3581
 #, c-format
 msgid "could not migrate git directory from '%s' to '%s'"
 msgstr "Konnte Git-Verzeichnis nicht von '%s' nach '%s' migrieren."
@@ -3879,11 +3920,11 @@
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "Hinweis: Warte auf das Schließen der Datei durch Ihren Editor...%c"
 
-#: entry.c:178
+#: entry.c:177
 msgid "Filtering content"
 msgstr "Filtere Inhalt"
 
-#: entry.c:479
+#: entry.c:478
 #, c-format
 msgid "could not stat file '%s'"
 msgstr "Konnte Datei '%s' nicht lesen."
@@ -3903,227 +3944,245 @@
 msgid "too many args to run %s"
 msgstr "Zu viele Argumente angegeben, um %s auszuführen."
 
-#: fetch-pack.c:151
+#: fetch-pack.c:152
 msgid "git fetch-pack: expected shallow list"
 msgstr "git fetch-pack: erwartete shallow-Liste"
 
-#: fetch-pack.c:154
+#: fetch-pack.c:155
 msgid "git fetch-pack: expected a flush packet after shallow list"
 msgstr "git fetch-pack: erwartete ein Flush-Paket nach der shallow-Liste"
 
-#: fetch-pack.c:165
+#: fetch-pack.c:166
 msgid "git fetch-pack: expected ACK/NAK, got a flush packet"
 msgstr "git fetch-pack: ACK/NAK erwartet, Flush-Paket bekommen"
 
-#: fetch-pack.c:185
+#: fetch-pack.c:186
 #, c-format
 msgid "git fetch-pack: expected ACK/NAK, got '%s'"
 msgstr "git fetch-pack: ACK/NAK erwartet, '%s' bekommen"
 
-#: fetch-pack.c:196
+#: fetch-pack.c:197
 msgid "unable to write to remote"
 msgstr "konnte nicht zum Remote schreiben"
 
-#: fetch-pack.c:258
+#: fetch-pack.c:259
 msgid "--stateless-rpc requires multi_ack_detailed"
 msgstr "--stateless-rpc benötigt multi_ack_detailed"
 
-#: fetch-pack.c:357 fetch-pack.c:1364
+#: fetch-pack.c:358 fetch-pack.c:1408
 #, c-format
 msgid "invalid shallow line: %s"
 msgstr "Ungültige shallow-Zeile: %s"
 
-#: fetch-pack.c:363 fetch-pack.c:1370
+#: fetch-pack.c:364 fetch-pack.c:1414
 #, c-format
 msgid "invalid unshallow line: %s"
 msgstr "Ungültige unshallow-Zeile: %s"
 
-#: fetch-pack.c:365 fetch-pack.c:1372
+#: fetch-pack.c:366 fetch-pack.c:1416
 #, c-format
 msgid "object not found: %s"
 msgstr "Objekt nicht gefunden: %s"
 
-#: fetch-pack.c:368 fetch-pack.c:1375
+#: fetch-pack.c:369 fetch-pack.c:1419
 #, c-format
 msgid "error in object: %s"
 msgstr "Fehler in Objekt: %s"
 
-#: fetch-pack.c:370 fetch-pack.c:1377
+#: fetch-pack.c:371 fetch-pack.c:1421
 #, c-format
 msgid "no shallow found: %s"
 msgstr "Kein shallow-Objekt gefunden: %s"
 
-#: fetch-pack.c:373 fetch-pack.c:1381
+#: fetch-pack.c:374 fetch-pack.c:1425
 #, c-format
 msgid "expected shallow/unshallow, got %s"
 msgstr "shallow/unshallow erwartet, %s bekommen"
 
-#: fetch-pack.c:415
+#: fetch-pack.c:416
 #, c-format
 msgid "got %s %d %s"
 msgstr "%s %d %s bekommen"
 
-#: fetch-pack.c:432
+#: fetch-pack.c:433
 #, c-format
 msgid "invalid commit %s"
 msgstr "Ungültiger Commit %s"
 
-#: fetch-pack.c:463
+#: fetch-pack.c:464
 msgid "giving up"
 msgstr "Gebe auf"
 
-#: fetch-pack.c:476 progress.c:336
+#: fetch-pack.c:477 progress.c:336
 msgid "done"
 msgstr "Fertig"
 
-#: fetch-pack.c:488
+#: fetch-pack.c:489
 #, c-format
 msgid "got %s (%d) %s"
 msgstr "%s (%d) %s bekommen"
 
-#: fetch-pack.c:534
+#: fetch-pack.c:535
 #, c-format
 msgid "Marking %s as complete"
 msgstr "Markiere %s als vollständig"
 
-#: fetch-pack.c:755
+#: fetch-pack.c:756
 #, c-format
 msgid "already have %s (%s)"
 msgstr "habe %s (%s) bereits"
 
-#: fetch-pack.c:819
+#: fetch-pack.c:821
 msgid "fetch-pack: unable to fork off sideband demultiplexer"
 msgstr "fetch-pack: Fehler beim Starten des sideband demultiplexer"
 
-#: fetch-pack.c:827
+#: fetch-pack.c:829
 msgid "protocol error: bad pack header"
 msgstr "Protokollfehler: ungültiger Pack-Header"
 
-#: fetch-pack.c:901
+#: fetch-pack.c:910
 #, c-format
 msgid "fetch-pack: unable to fork off %s"
 msgstr "fetch-pack: konnte %s nicht starten"
 
-#: fetch-pack.c:917
+#: fetch-pack.c:927
 #, c-format
 msgid "%s failed"
 msgstr "%s fehlgeschlagen"
 
-#: fetch-pack.c:919
+#: fetch-pack.c:929
 msgid "error in sideband demultiplexer"