Merge branch 'gc/doc-cocci-updates'

Update documentation regarding Coccinelle patches.

* gc/doc-cocci-updates:
  cocci: codify authoring and reviewing practices
  cocci: add headings to and reword README
diff --git a/.mailmap b/.mailmap
index 95aaa1c..733e047 100644
--- a/.mailmap
+++ b/.mailmap
@@ -65,6 +65,7 @@
 Deskin Miller <deskinm@umich.edu>
 Đoàn Trần Công Danh <congdanhqx@gmail.com> Doan Tran Cong Danh
 Dirk Süsserott <newsletter@dirk.my1.cc>
+Emily Shaffer <nasamuffin@google.com> <emilyshaffer@google.com>
 Eric Blake <eblake@redhat.com> <ebb9@byu.net>
 Eric Hanchrow <eric.hanchrow@gmail.com> <offby1@blarg.net>
 Eric S. Raymond <esr@thyrsus.com>
diff --git a/Documentation/.gitignore b/Documentation/.gitignore
index 1c3771e..a48448d 100644
--- a/Documentation/.gitignore
+++ b/Documentation/.gitignore
@@ -10,7 +10,6 @@
 doc.dep
 cmds-*.txt
 mergetools-*.txt
-manpage-base-url.xsl
 SubmittingPatches.txt
 tmp-doc-diff/
 GIT-ASCIIDOCFLAGS
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index 9d5c278..003393e 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -442,8 +442,12 @@
    detail.
 
  - The first #include in C files, except in platform specific compat/
-   implementations, must be either "git-compat-util.h", "cache.h" or
-   "builtin.h".  You do not have to include more than one of these.
+   implementations and sha1dc/, must be either "git-compat-util.h" or
+   one of the approved headers that includes it first for you.  (The
+   approved headers currently include "cache.h", "builtin.h",
+   "t/helper/test-tool.h", "xdiff/xinclude.h", or
+   "reftable/system.h").  You do not have to include more than one of
+   these.
 
  - A C file must directly include the header files that declare the
    functions and the types it uses, except for the functions and types
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 9c67c3a..b629176 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -144,14 +144,16 @@
 man7dir = $(mandir)/man7
 # DESTDIR =
 
+GIT_DATE := $(shell git show --quiet --pretty='%as')
+
 ASCIIDOC = asciidoc
 ASCIIDOC_EXTRA =
 ASCIIDOC_HTML = xhtml11
 ASCIIDOC_DOCBOOK = docbook
 ASCIIDOC_CONF = -f asciidoc.conf
 ASCIIDOC_COMMON = $(ASCIIDOC) $(ASCIIDOC_EXTRA) $(ASCIIDOC_CONF) \
-		-amanversion=$(GIT_VERSION) \
-		-amanmanual='Git Manual' -amansource='Git'
+		-amanmanual='Git Manual' -amansource='Git $(GIT_VERSION)' \
+		-arevdate='$(GIT_DATE)'
 ASCIIDOC_DEPS = asciidoc.conf GIT-ASCIIDOCFLAGS
 TXT_TO_HTML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_HTML)
 TXT_TO_XML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_DOCBOOK)
@@ -189,15 +191,7 @@
 ifndef MAN_BASE_URL
 MAN_BASE_URL = file://$(htmldir)/
 endif
-XMLTO_EXTRA += -m manpage-base-url.xsl
-
-# If your target system uses GNU groff, it may try to render
-# apostrophes as a "pretty" apostrophe using unicode.  This breaks
-# cut&paste, so you should set GNU_ROFF to force them to be ASCII
-# apostrophes.  Unfortunately does not work with non-GNU roff.
-ifdef GNU_ROFF
-XMLTO_EXTRA += -m manpage-quote-apos.xsl
-endif
+XMLTO_EXTRA += --stringparam man.base.url.for.relative.links='$(MAN_BASE_URL)'
 
 ifdef USE_ASCIIDOCTOR
 ASCIIDOC = asciidoctor
@@ -339,7 +333,6 @@
 	$(RM) technical/*.html technical/api-index.txt
 	$(RM) SubmittingPatches.txt
 	$(RM) $(cmds_txt) $(mergetools_txt) *.made
-	$(RM) manpage-base-url.xsl
 	$(RM) GIT-ASCIIDOCFLAGS
 
 $(MAN_HTML): %.html : %.txt $(ASCIIDOC_DEPS)
@@ -348,11 +341,7 @@
 $(OBSOLETE_HTML): %.html : %.txto $(ASCIIDOC_DEPS)
 	$(QUIET_ASCIIDOC)$(TXT_TO_HTML) -o $@ $<
 
-manpage-base-url.xsl: manpage-base-url.xsl.in
-	$(QUIET_GEN)sed "s|@@MAN_BASE_URL@@|$(MAN_BASE_URL)|" $< > $@
-
-
-manpage-prereqs := manpage-base-url.xsl $(wildcard manpage*.xsl)
+manpage-prereqs := $(wildcard manpage*.xsl)
 manpage-cmd = $(QUIET_XMLTO)$(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
 
 %.1 : %.xml $(manpage-prereqs)
diff --git a/Documentation/MyFirstContribution.txt b/Documentation/MyFirstContribution.txt
index ccfd0cb..56130e4 100644
--- a/Documentation/MyFirstContribution.txt
+++ b/Documentation/MyFirstContribution.txt
@@ -1164,28 +1164,28 @@
 directory, alongside the v1 patches. Using a single directory makes it easy to
 refer to the old v1 patches while proofreading the v2 patches, but you will need
 to be careful to send out only the v2 patches. We will use a pattern like
-"psuh/v2-*.patch" (not "psuh/*.patch", which would match v1 and v2 patches).
+`psuh/v2-*.patch` (not `psuh/*.patch`, which would match v1 and v2 patches).
 
 Edit your cover letter again. Now is a good time to mention what's different
 between your last version and now, if it's something significant. You do not
 need the exact same body in your second cover letter; focus on explaining to
 reviewers the changes you've made that may not be as visible.
 
-You will also need to go and find the Message-Id of your previous cover letter.
+You will also need to go and find the Message-ID of your previous cover letter.
 You can either note it when you send the first series, from the output of `git
 send-email`, or you can look it up on the
 https://lore.kernel.org/git[mailing list]. Find your cover letter in the
-archives, click on it, then click "permalink" or "raw" to reveal the Message-Id
+archives, click on it, then click "permalink" or "raw" to reveal the Message-ID
 header. It should match:
 
 ----
-Message-Id: <foo.12345.author@example.com>
+Message-ID: <foo.12345.author@example.com>
 ----
 
-Your Message-Id is `<foo.12345.author@example.com>`. This example will be used
-below as well; make sure to replace it with the correct Message-Id for your
-**previous cover letter** - that is, if you're sending v2, use the Message-Id
-from v1; if you're sending v3, use the Message-Id from v2.
+Your Message-ID is `<foo.12345.author@example.com>`. This example will be used
+below as well; make sure to replace it with the correct Message-ID for your
+**previous cover letter** - that is, if you're sending v2, use the Message-ID
+from v1; if you're sending v3, use the Message-ID from v2.
 
 While you're looking at the email, you should also note who is CC'd, as it's
 common practice in the mailing list to keep all CCs on a thread. You can add
diff --git a/Documentation/RelNotes/2.30.9.txt b/Documentation/RelNotes/2.30.9.txt
new file mode 100644
index 0000000..708d626
--- /dev/null
+++ b/Documentation/RelNotes/2.30.9.txt
@@ -0,0 +1,43 @@
+Git v2.30.9 Release Notes
+=========================
+
+This release addresses the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007.
+
+
+Fixes since v2.30.8
+-------------------
+
+ * CVE-2023-25652:
+
+   By feeding specially crafted input to `git apply --reject`, a
+   path outside the working tree can be overwritten with partially
+   controlled contents (corresponding to the rejected hunk(s) from
+   the given patch).
+
+ * CVE-2023-25815:
+
+   When Git is compiled with runtime prefix support and runs without
+   translated messages, it still used the gettext machinery to
+   display messages, which subsequently potentially looked for
+   translated messages in unexpected places. This allowed for
+   malicious placement of crafted messages.
+
+ * CVE-2023-29007:
+
+   When renaming or deleting a section from a configuration file,
+   certain malicious configuration values may be misinterpreted as
+   the beginning of a new configuration section, leading to arbitrary
+   configuration injection.
+
+Credit for finding CVE-2023-25652 goes to Ry0taK, and the fix was
+developed by Taylor Blau, Junio C Hamano and Johannes Schindelin,
+with the help of Linus Torvalds.
+
+Credit for finding CVE-2023-25815 goes to Maxime Escourbiac and
+Yassine BENGANA of Michelin, and the fix was developed by Johannes
+Schindelin.
+
+Credit for finding CVE-2023-29007 goes to André Baptista and Vítor Pinho
+of Ethiack, and the fix was developed by Taylor Blau, and Johannes
+Schindelin, with help from Jeff King, and Patrick Steinhardt.
diff --git a/Documentation/RelNotes/2.31.8.txt b/Documentation/RelNotes/2.31.8.txt
new file mode 100644
index 0000000..0aa3080
--- /dev/null
+++ b/Documentation/RelNotes/2.31.8.txt
@@ -0,0 +1,6 @@
+Git v2.31.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9 to address the
+security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007;
+see the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.32.7.txt b/Documentation/RelNotes/2.32.7.txt
new file mode 100644
index 0000000..7bb3538
--- /dev/null
+++ b/Documentation/RelNotes/2.32.7.txt
@@ -0,0 +1,7 @@
+Git v2.32.7 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9 and v2.31.8 to
+address the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
diff --git a/Documentation/RelNotes/2.33.8.txt b/Documentation/RelNotes/2.33.8.txt
new file mode 100644
index 0000000..d8cf4c7
--- /dev/null
+++ b/Documentation/RelNotes/2.33.8.txt
@@ -0,0 +1,7 @@
+Git v2.33.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8 and
+v2.32.7 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
diff --git a/Documentation/RelNotes/2.34.8.txt b/Documentation/RelNotes/2.34.8.txt
new file mode 100644
index 0000000..2b5bd7d
--- /dev/null
+++ b/Documentation/RelNotes/2.34.8.txt
@@ -0,0 +1,7 @@
+Git v2.34.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7 and v2.33.8 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
diff --git a/Documentation/RelNotes/2.35.8.txt b/Documentation/RelNotes/2.35.8.txt
new file mode 100644
index 0000000..3c9c094
--- /dev/null
+++ b/Documentation/RelNotes/2.35.8.txt
@@ -0,0 +1,7 @@
+Git v2.35.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8 and v2.34.8 to address the security issues
+CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007; see the release
+notes for these versions for details.
diff --git a/Documentation/RelNotes/2.36.6.txt b/Documentation/RelNotes/2.36.6.txt
new file mode 100644
index 0000000..e1edebc
--- /dev/null
+++ b/Documentation/RelNotes/2.36.6.txt
@@ -0,0 +1,7 @@
+Git v2.36.6 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8 and v2.35.8 to address the security issues
+CVE-2023-25652, CVS-2023-25815, and CVE-2023-29007; see the release
+notes for these versions for details.
diff --git a/Documentation/RelNotes/2.37.7.txt b/Documentation/RelNotes/2.37.7.txt
new file mode 100644
index 0000000..4b8165f
--- /dev/null
+++ b/Documentation/RelNotes/2.37.7.txt
@@ -0,0 +1,7 @@
+Git v2.37.7 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8 and v2.36.6 to address the
+security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007;
+see the release notes for these versions for details.
diff --git a/Documentation/RelNotes/2.38.5.txt b/Documentation/RelNotes/2.38.5.txt
new file mode 100644
index 0000000..2d1f3b1
--- /dev/null
+++ b/Documentation/RelNotes/2.38.5.txt
@@ -0,0 +1,8 @@
+Git v2.38.5 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6 and v2.37.7 to address
+the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
diff --git a/Documentation/RelNotes/2.39.3.txt b/Documentation/RelNotes/2.39.3.txt
index dddff53..66351b6 100644
--- a/Documentation/RelNotes/2.39.3.txt
+++ b/Documentation/RelNotes/2.39.3.txt
@@ -1,9 +1,15 @@
 Git v2.39.3 Release Notes
 =========================
 
-This release is primarily to merge fixes accumulated on the 'master'
-front to prepare for 2.40 release that are still relevant to 2.39.x
-maintenance track.
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6, v2.37.7 and v2.38.5 to
+address the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
+
+This release also merges fixes that have accumulated on the 'master'
+front to prepare for the 2.40 release that are still relevant to
+2.39.x maintenance track.
 
 Fixes since v2.39.2
 -------------------
diff --git a/Documentation/RelNotes/2.40.1.txt b/Documentation/RelNotes/2.40.1.txt
new file mode 100644
index 0000000..e72f6b1
--- /dev/null
+++ b/Documentation/RelNotes/2.40.1.txt
@@ -0,0 +1,8 @@
+Git v2.40.1 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6, v2.37.7, v2.38.5
+and v2.39.3 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
diff --git a/Documentation/RelNotes/2.41.0.txt b/Documentation/RelNotes/2.41.0.txt
new file mode 100644
index 0000000..8a9e170
--- /dev/null
+++ b/Documentation/RelNotes/2.41.0.txt
@@ -0,0 +1,399 @@
+Git v2.41 Release Notes
+=======================
+
+UI, Workflows & Features
+
+ * Allow information carried on the WWW-Authenticate header to be
+   passed to the credential helpers.
+
+ * A new "fetch.hideRefs" option can be used to exclude specified refs
+   from "rev-list --objects --stdin --not --all" traversal for
+   checking object connectivity, most useful when there are many
+   unrelated histories in a single repository.
+
+ * "git push" has been taught to allow deletion of refs with one-level
+   names to help repairing a repository who acquired such a ref by
+   mistake.  In general, we don't encourage use of such a ref, and
+   creation or update to such a ref is rejected as before.
+
+ * Allow "git bisect reset" to check out the original branch when the
+   branch is already checked out in a different worktree linked to the
+   same repository.
+
+ * A few subcommands have been taught to stop users from working on a
+   branch that is being used in another worktree linked to the same
+   repository.
+
+ * "git format-patch" learned to write a log-message only output file
+   for empty commits.
+
+ * "git format-patch" honors the src/dst prefixes set to nonstandard
+   values with configuration variables like "diff.noprefix", causing
+   receiving end of the patch that expects the standard -p1 format to
+   break.  "format-patch" has been taught to ignore end-user configuration
+   and always use the standard prefixes.
+
+   This is a backward compatibility breaking change.
+
+ * Lift the limitation that colored prompts can only be used with
+   PROMPT_COMMAND mode.
+
+ * "git blame --contents=<file> <rev> -- <path>" used to be forbidden,
+   but now it finds the origins of lines starting at <file> contents
+   through the history that leads to <rev>.
+
+ * "git pack-redundant" gave a warning when run, as the command has
+   outlived its usefulness long ago and is nominated for future
+   removal.  Now we escalate to give an error.
+
+ * "git clone" from an empty repository learned to propagate the
+   choice of the hash algorithm from the source repository to the
+   newly created repository over any one of the v0/v1/v2 protocol.
+
+ * "git mergetool" and "git difftool" learns a new configuration
+   guiDefault to optionally favor configured guitool over non-gui-tool
+   automatically when $DISPLAY is set.
+
+ * "git branch -d origin/master" would say "no such branch", but it is
+   likely a missed "-r" if refs/remotes/origin/master exists.  The
+   command has been taught to give such a hint in its error message.
+
+ * Clean-up of the code path that deals with merge strategy option
+   handling in "git rebase".
+
+ * "git clone --local" stops copying from an original repository that
+   has symbolic links inside its $GIT_DIR; an error message when that
+   happens has been updated.
+
+ * The "--format=..." option of "git for-each-ref", "git branch", and
+   "git tag" commands learn "--omit-empty" to hide refs whose
+   formatting results in an empty string from the output.
+
+ * The sendemail-validate validate hook learned to pass the total
+   number of input files and where in the sequence each invocation is
+   via environment variables.
+
+ * When "gc" needs to retain unreachable objects, packing them into
+   cruft packs (instead of exploding them into loose object files) has
+   been offered as a more efficient option for some time.  Now the use
+   of cruft packs has been made the default and no longer considered
+   an experimental feature.
+
+ * The output given by "git blame" that attributes a line to contents
+   taken from the file specified by the "--contents" option shows it
+   differently from a line attributed to the working tree file.
+
+ * "git send-email" learned to give the e-mail headers to the validate
+   hook by passing an extra argument from the command line.
+
+ * The credential subsystem learns to help OAuth framework.
+
+ * The titles of manual pages used to be chomped at an unreasonably
+   short limit, which has been removed.
+
+ * Error messages given when working on an unborn branch that is
+   checked out in another worktree have been improved.
+
+ * The documentation was misleading about the interaction between
+   GIT_DEFAULT_HASH and "git clone", which has been clarified to
+   stress that the variable is to be ignored by the command.
+
+ * "git send-email" learned "--header-cmd=<cmd>" that can inject
+   arbitrary e-mail header lines to the outgoing messages.
+
+ * "git fsck" learned to detect bit-flip breakages in the reachability
+   bitmap files.
+
+ * The "--stdin" option of "git name-rev" has been replaced with
+   the "--annotate-stdin" option more than a year ago.  We stop
+   advertising it in the "git name-rev -h" output.
+
+ * "git push --all" gained an alias "git push --branches".
+
+ * "git fetch" learned the "--porcelain" option that emits what it did
+   in a machine-parseable format.
+
+ * "git --attr-source=<tree> cmd $args" is a new way to have any
+   command to read attributes not from the working tree but from the
+   given tree object.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * Code clean-up to clarify directory traversal API.
+
+ * Code clean-up to clarify the rule that "git-compat-util.h" must be
+   the first to be included.
+
+ * More work towards -Wunused.
+
+ * Instead of forcing each command to choose to honor GPG related
+   configuration variables, make the subsystem lazily initialize
+   itself.
+
+ * Remove workaround for ancient versions of DocBook to make it work
+   correctly with groff, which has not been necessary since docbook
+   1.76 from 2010.
+
+ * Code clean-up to include and/or uninclude parse-options.h file as
+   needed.
+
+ * The code path that reports what "git fetch" did to each ref has
+   been cleaned up.
+
+ * Assorted config API updates.
+
+ * A few configuration variables to tell the cURL library that
+   different types of ssl-cert and ssl-key are in use have been added.
+
+ * Split key function and data structure definitions out of cache.h to
+   new header files and adjust the users.
+
+ * "git fetch --all" does not have to download and handle the same
+   bundleURI over and over, which has been corrected.
+
+ * "git sparse-checkout" command learns a debugging aid for the sparse
+   rule definitions.
+
+ * "git write-tree" learns to work better with sparse-index.
+
+ * The on-disk reverse index that allows mapping from the pack offset
+   to the object name for the object stored at the offset has been
+   enabled by default.
+
+ * "git fsck" learned to validate the on-disk pack reverse index files.
+
+ * strtok() and strtok_r() are banned in this codebase.
+
+ * The detect-compilers script to help auto-tweaking the build system
+   had trouble working with compilers whose version number has extra
+   suffixes.  The script has been taught that certain suffixes (like
+   "-win32" in "gcc 10-win32") can be safely stripped as they share
+   the same features and bugs with the version without the suffix.
+
+ * ctype tests have been taught to test EOF, too.
+
+ * The implementation of credential helpers used fgets() over fixed
+   size buffers to read protocol messages, causing the remainder of
+   the folded long line to trigger unexpected behaviour, which has
+   been corrected.
+
+ * The implementation of the default "negotiator", used to find common
+   ancestor over the network for object tranfer, used to be recursive;
+   it was updated to be iterative to conserve stackspace usage.
+
+ * Our custom callout formatter is no longer used in the documentation
+   formatting toolchain, as the upstream default ones give better
+   output these days.
+
+ * The tracing mechanism learned to notice and report when
+   auto-discovered bare repositories are being used, as allowing so
+   without explicitly stating the user intends to do so (with setting
+   GIT_DIR for example) can be used with social engineering as an
+   attack vector.
+
+ * "git diff-files" learned not to expand sparse-index unless needed.
+
+
+Fixes since v2.40
+-----------------
+
+ * "git fsck" learned to check the index files in other worktrees,
+   just like "git gc" honors them as anchoring points.
+   (merge 8d3e7eac52 jk/fsck-indices-in-worktrees later to maint).
+
+ * Fix a segfaulting loop.  The function and its caller may need
+   further clean-up.
+   (merge c5773dc078 ew/commit-reach-clean-up-flags-fix later to maint).
+
+ * "git restore" supports options like "--ours" that are only
+   meaningful during a conflicted merge, but these options are only
+   meaningful when updating the working tree files.  These options are
+   marked to be incompatible when both "--staged" and "--worktree" are
+   in effect.
+   (merge ee8a88826a ak/restore-both-incompatible-with-conflicts later to maint).
+
+ * Simplify UI to control progress meter given by "git bundle" command.
+   (merge 8b95521edb jk/bundle-progress later to maint).
+
+ * "git bundle" learned that "-" is a common way to say that the input
+   comes from the standard input and/or the output goes to the
+   standard output.  It used to work only for output and only from the
+   root level of the working tree.
+   (merge 0bbe10313e jk/bundle-use-dash-for-stdfiles later to maint).
+
+ * Once we start running, we assumed that the list of alternate object
+   databases would never change.  Hook into the machinery used to
+   update the list of packfiles during runtime to update this list as
+   well.
+   (merge e2d003dbed ds/reprepare-alternates-when-repreparing-packfiles later to maint).
+
+ * The code to parse "git rebase -X<opt>" was not prepared to see an
+   unparsable option string, which has been corrected.
+   (merge 15a4cc912e ab/fix-strategy-opts-parsing later to maint).
+
+ * "git add -p" while the index is unmerged sometimes failed to parse
+   the diff output it internally produces and died, which has been
+   corrected.
+   (merge 28d1122f9c jk/add-p-unmerged-fix later to maint).
+
+ * Fix for a "ls-files --format="%(path)" that produced nonsense
+   output, which was a bug in 2.38.
+   (merge cfb62dd006 aj/ls-files-format-fix later to maint).
+
+ * "git receive-pack" that responds to "git push" requests failed to
+   clean a stale lockfile when killed in the middle, which has been
+   corrected.
+   (merge c55c30669c ps/receive-pack-unlock-before-die later to maint).
+
+ * "git rev-parse --quiet foo@{u}", or anything that asks @{u} to be
+   parsed with GET_OID_QUIETLY option, did not quietly fail, which has
+   been corrected.
+   (merge dfbfdc521d fc/oid-quietly-parse-upstream later to maint).
+
+ * Transports that do not support protocol v2 did not correctly fall
+   back to protocol v0 under certain conditions, which has been
+   corrected.
+   (merge eaa0fd6584 jk/fix-proto-downgrade-to-v0 later to maint).
+
+ * time(2) on glib 2.31+, especially on Linux, goes out of sync with
+   higher resolution timers used for gettimeofday(2) and by the
+   filesystem.  Replace all calls to it with a git_time() wrapper and
+   (merge 370ddcbc89 pe/time-use-gettimeofday later to maint).
+
+ * Code clean-up to use designated initializers in parse-options API.
+   (merge 353e6d4554 sg/parse-options-h-initializers later to maint).
+
+ * A recent-ish change to allow unicode character classes to be used
+   with "grep -P" triggered a JIT bug in older pcre2 libraries.
+   The problematic change in Git built with these older libraries has
+   been disabled to work around the bug.
+   (merge 14b9a04479 mk/workaround-pcre-jit-ucp-bug later to maint).
+
+ * The wildmatch library code unlearns exponential behaviour it
+   acquired some time ago since it was borrowed from rsync.
+   (merge 3dc0b7f0dc pw/wildmatch-fixes later to maint).
+
+ * The index files can become corrupt under certain conditions when
+   the split-index feature is in use, especially together with
+   fsmonitor, which have been corrected.
+   (merge 061dd722dc js/split-index-fixes later to maint).
+
+ * Document what the pathname-looking strings in "rev-list --object"
+   output are for and what they mean.
+   (merge 15364d2a3c jk/document-rev-list-object-name later to maint).
+
+ * Fix unnecessary truncation of generation numbers used in-core.
+   (merge d3af1c193d ps/ahead-behind-truncation-fix later to maint).
+
+ * Code clean-up around the use of the_repository.
+   (merge 4a93b899c1 ab/remove-implicit-use-of-the-repository later to maint).
+
+ * Consistently spell "Message-ID" as such, not "Message-Id".
+   (merge ba4324c4e1 jc/spell-id-in-both-caps-in-message-id later to maint).
+
+ * Correct use of an uninitialized structure member.
+   (merge dc12ee77ab jx/cap-object-info-uninitialized-fix later to maint).
+
+ * Tests had a few places where we ignored PERL_PATH and blindly used
+   /usr/bin/perl, which have been corrected.
+   (merge c1917156a0 jk/use-perl-path-consistently later to maint).
+
+ * Documentation mark-up fix.
+   (merge 78b6369e67 la/mfc-markup-fix later to maint).
+
+ * Doc toolchain update to remove old workaround for AsciiDoc.
+   (merge 8806120de6 fc/remove-header-workarounds-for-asciidoc later to maint).
+
+ * The userdiff regexp patterns for various filetypes that are built
+   into the system have been updated to avoid triggering regexp errors
+   from UTF-8 aware regex engines.
+   (merge be39144954 rs/userdiff-multibyte-regex later to maint).
+
+ * The approxidate() API has been simplified by losing an extra
+   function that did the same thing as another one.
+   (merge 8a7f0b666f rs/remove-approxidate-relative later to maint).
+
+ * Code clean-up to replace a hardcoded constant with a CPP macro.
+   (merge c870de6502 rs/get-tar-commit-id-use-defined-const later to maint).
+
+ * Doc build simplification.
+   (merge 9a09ed3229 fc/doc-stop-using-manversion later to maint).
+
+ * "git archive" run from a subdirectory mishandled attributes and
+   paths outside the current directory.
+   (merge 92b1dd1b9e rs/archive-from-subdirectory-fixes later to maint).
+
+ * The code to parse capability list for v0 on-wire protocol fell into
+   an infinite loop when a capability appears multiple times, which
+   has been corrected.
+
+ * Geometric repacking ("git repack --geometric=<n>") in a repository
+   that borrows from an alternate object database had various corner
+   case bugs, which have been corrected.
+   (merge d85cd18777 ps/fix-geom-repack-with-alternates later to maint).
+
+ * The "%GT" placeholder for the "--format" option of "git log" and
+   friends caused BUG() to trigger on a commit signed with an unknown
+   key, which has been corrected.
+   (merge 7891e46585 jk/gpg-trust-level-fix later to maint).
+
+ * The completion script used to use bare "read" without the "-r"
+   option to read the contents of various state files, which risked
+   getting confused with backslashes in them.  This has been
+   corrected.
+   (merge 197152098a ek/completion-use-read-r-to-read-literally later to maint).
+
+ * A small API fix to the ort merge strategy backend.
+   (merge 000c4ceca7 en/ort-finalize-after-0-merges-fix later to maint).
+
+ * The commit object parser has been taught to be a bit more lenient
+   to parse timestamps on the author/committer line with a malformed
+   author/committer ident.
+   (merge 90ef0f14eb jk/parse-commit-with-malformed-ident later to maint).
+
+ * Retitle a test script with an overly narrow name.
+   (merge 8bb19c14fb ob/t3501-retitle later to maint).
+
+ * Doc update to clarify how text and eol attributes interact to
+   specify the end-of-line conversion.
+   (merge 6696077ace ah/doc-attributes-text later to maint).
+
+ * Gitk updates from GfW project.
+   (merge 99e70f3077 js/gitk-fixes-from-gfw later to maint).
+
+ * "git diff --dirstat" leaked memory, which has been plugged.
+   (merge 83973981eb jc/dirstat-plug-leaks later to maint).
+
+ * "git merge-tree" reads the basic configuration, which can be used
+    by git forges to disable replace-refs feature.
+   (merge b6551feadf ds/merge-tree-use-config later to maint).
+
+ * A few bugs in the sequencer machinery that results in miscounting
+   the steps have been corrected.
+   (merge 170eea9750 js/rebase-count-fixes later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+   (merge f7111175df as/doc-markup-fix later to maint).
+   (merge 90ff7c9898 fc/test-aggregation-clean-up later to maint).
+   (merge 9b0c7f308a jc/am-doc-refer-to-format-patch later to maint).
+   (merge b10cbdac4c bb/unicode-width-table-15 later to maint).
+   (merge 3457b50e8c ab/retire-scripted-add-p later to maint).
+   (merge d52fcf493b ds/p2000-fix-grep-sparse later to maint).
+   (merge ec063d2591 ss/hashmap-typofix later to maint).
+   (merge 1aaed69d11 rs/archive-mtime later to maint).
+   (merge 2da2cc9b28 ob/rollback-after-commit-lock-failure later to maint).
+   (merge 54dbd0933b ob/sequencer-save-head-simplify later to maint).
+   (merge a93cbe8d78 ar/test-cleanup-unused-file-creation later to maint).
+   (merge cc48ddd937 jk/chainlint-fixes later to maint).
+   (merge 4833b08426 ow/ref-format-remove-unused-member later to maint).
+   (merge d0ea2ca1cf dw/doc-submittingpatches-grammofix later to maint).
+   (merge fd72637423 ar/t2024-checkout-output-fix later to maint).
+   (merge d45cbe3fe0 ob/sequencer-i18n-fix later to maint).
+   (merge b734fe49fd ob/messages-capitalize-exception later to maint).
+   (merge ad353d7e77 ma/gittutorial-fixes later to maint).
+   (merge a5855fd8d4 ar/test-cleanup-unused-file-creation-part2 later to maint).
+   (merge 0c5308af30 sd/doc-gitignore-and-rm-cached later to maint).
+   (merge cbb83daeaf kh/doc-interpret-trailers-updates later to maint).
+   (merge 3d77fbb664 ar/config-count-tests-updates later to maint).
+   (merge b7cf25c8f4 jc/t9800-fix-use-of-show-s-raw later to maint).
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 927f732..b218e27 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -543,7 +543,7 @@
 [[mua]]
 == MUA specific hints
 
-Some of patches I receive or pick up from the list share common
+Some of the patches I receive or pick up from the list share common
 patterns of breakage.  Please make sure your MUA is set up
 properly not to corrupt whitespaces.
 
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index 3e4c139..60f76f4 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -51,25 +51,6 @@
 endif::doctype-manpage[]
 endif::backend-docbook[]
 
-ifdef::doctype-manpage[]
-ifdef::backend-docbook[]
-[header]
-template::[header-declarations]
-<refentry>
-<refmeta>
-<refentrytitle>{mantitle}</refentrytitle>
-<manvolnum>{manvolnum}</manvolnum>
-<refmiscinfo class="source">{mansource}</refmiscinfo>
-<refmiscinfo class="version">{manversion}</refmiscinfo>
-<refmiscinfo class="manual">{manmanual}</refmiscinfo>
-</refmeta>
-<refnamediv>
-  <refname>{manname}</refname>
-  <refpurpose>{manpurpose}</refpurpose>
-</refnamediv>
-endif::backend-docbook[]
-endif::doctype-manpage[]
-
 ifdef::backend-xhtml11[]
 [attributes]
 git-relative-html-prefix=
diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt
index 9a66353..552dcc6 100644
--- a/Documentation/blame-options.txt
+++ b/Documentation/blame-options.txt
@@ -64,11 +64,9 @@
 	manual page.
 
 --contents <file>::
-	When <rev> is not specified, the command annotates the
-	changes starting backwards from the working tree copy.
-	This flag makes the command pretend as if the working
-	tree copy has the contents of the named file (specify
-	`-` to make the command read from the standard input).
+	Annotate using the contents from the named file, starting from <rev>
+	if it is specified, and HEAD otherwise. You may specify '-' to make
+	the command read from the standard input for the file contents.
 
 --date <format>::
 	Specifies the format used to output dates. If --date is not
diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt
index a00d010..c96b5b2 100644
--- a/Documentation/config/advice.txt
+++ b/Documentation/config/advice.txt
@@ -136,4 +136,6 @@
 		Advice shown when either linkgit:git-add[1] or linkgit:git-rm[1]
 		is asked to update index entries outside the current sparse
 		checkout.
+	diverging::
+		Advice shown when a fast-forward is not possible.
 --
diff --git a/Documentation/config/difftool.txt b/Documentation/config/difftool.txt
index a3f8211..447c40d 100644
--- a/Documentation/config/difftool.txt
+++ b/Documentation/config/difftool.txt
@@ -34,3 +34,10 @@
 
 difftool.prompt::
 	Prompt before each invocation of the diff tool.
+
+difftool.guiDefault::
+	Set `true` to use the `diff.guitool` by default (equivalent to specifying
+	the `--gui` argument), or `auto` to select `diff.guitool` or `diff.tool`
+	depending on the presence of a `DISPLAY` environment variable value. The
+	default is `false`, where the `--gui` argument must be provided
+	explicitly for the `diff.guitool` to be used.
diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.txt
index e52bc6b..17b4d39 100644
--- a/Documentation/config/feature.txt
+++ b/Documentation/config/feature.txt
@@ -14,9 +14,6 @@
 +
 * `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
 skipping more commits at a time, reducing the number of round trips.
-+
-* `gc.cruftPacks=true` reduces disk space used by unreachable objects during
-garbage collection, preventing loose object explosions.
 
 feature.manyFiles::
 	Enable config options that optimize for repos with many files in the
diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt
index 73678d8..8cf6f00 100644
--- a/Documentation/config/format.txt
+++ b/Documentation/config/format.txt
@@ -144,3 +144,10 @@
 format.mboxrd::
 	A boolean value which enables the robust "mboxrd" format when
 	`--stdout` is in use to escape "^>+From " lines.
+
+format.noprefix::
+	If set, do not show any source or destination prefix in patches.
+	This is equivalent to the `diff.noprefix` option used by `git
+	diff` (but which is not respected by `format-patch`). Note that
+	by setting this, the receiver of any patches you generate will
+	have to apply them using the `-p0` option.
diff --git a/Documentation/config/gc.txt b/Documentation/config/gc.txt
index 38fea07..7f95c86 100644
--- a/Documentation/config/gc.txt
+++ b/Documentation/config/gc.txt
@@ -43,11 +43,11 @@
 	if the system supports it. Default is true.
 
 gc.bigPackThreshold::
-	If non-zero, all packs larger than this limit are kept when
-	`git gc` is run. This is very similar to `--keep-largest-pack`
-	except that all packs that meet the threshold are kept, not
-	just the largest pack. Defaults to zero. Common unit suffixes of
-	'k', 'm', or 'g' are supported.
+	If non-zero, all non-cruft packs larger than this limit are kept
+	when `git gc` is run. This is very similar to
+	`--keep-largest-pack` except that all non-cruft packs that meet
+	the threshold are kept, not just the largest pack. Defaults to
+	zero. Common unit suffixes of 'k', 'm', or 'g' are supported.
 +
 Note that if the number of kept packs is more than gc.autoPackLimit,
 this configuration variable is ignored, all packs except the base pack
@@ -84,7 +84,7 @@
 gc.cruftPacks::
 	Store unreachable objects in a cruft pack (see
 	linkgit:git-repack[1]) instead of as loose objects. The default
-	is `false`.
+	is `true`.
 
 gc.pruneExpire::
 	When 'git gc' is run, it will call 'prune --expire 2.weeks.ago'
diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt
index afeeccf..51a7078 100644
--- a/Documentation/config/http.txt
+++ b/Documentation/config/http.txt
@@ -246,8 +246,9 @@
 pushes.
 
 http.lowSpeedLimit, http.lowSpeedTime::
-	If the HTTP transfer speed is less than 'http.lowSpeedLimit'
-	for longer than 'http.lowSpeedTime' seconds, the transfer is aborted.
+	If the HTTP transfer speed, in bytes per second, is less than
+	'http.lowSpeedLimit' for longer than 'http.lowSpeedTime' seconds,
+	the transfer is aborted.
 	Can be overridden by the `GIT_HTTP_LOW_SPEED_LIMIT` and
 	`GIT_HTTP_LOW_SPEED_TIME` environment variables.
 
diff --git a/Documentation/config/mergetool.txt b/Documentation/config/mergetool.txt
index e779a12..56a7eee 100644
--- a/Documentation/config/mergetool.txt
+++ b/Documentation/config/mergetool.txt
@@ -85,3 +85,10 @@
 
 mergetool.prompt::
 	Prompt before each invocation of the merge resolution program.
+
+mergetool.guiDefault::
+	Set `true` to use the `merge.guitool` by default (equivalent to
+	specifying the `--gui` argument), or `auto` to select `merge.guitool`
+	or `merge.tool` depending on the presence of a `DISPLAY` environment
+	variable value. The default is `false`, where the `--gui` argument
+	must be provided explicitly for the `merge.guitool` to be used.
diff --git a/Documentation/config/pack.txt b/Documentation/config/pack.txt
index 53093d9..d4c7c9d 100644
--- a/Documentation/config/pack.txt
+++ b/Documentation/config/pack.txt
@@ -171,9 +171,15 @@
 	beneficial in repositories that have relatively large bitmap
 	indexes. Defaults to false.
 
+pack.readReverseIndex::
+	When true, git will read any .rev file(s) that may be available
+	(see: linkgit:gitformat-pack[5]). When false, the reverse index
+	will be generated from scratch and stored in memory. Defaults to
+	true.
+
 pack.writeReverseIndex::
 	When true, git will write a corresponding .rev file (see:
 	linkgit:gitformat-pack[5])
 	for each new packfile that it writes in all places except for
 	linkgit:git-fast-import[1] and in the bulk checkin mechanism.
-	Defaults to false.
+	Defaults to true.
diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt
index f19bd0e..afaf6da 100644
--- a/Documentation/config/rebase.txt
+++ b/Documentation/config/rebase.txt
@@ -67,3 +67,13 @@
 
 rebase.forkPoint::
 	If set to false set `--no-fork-point` option by default.
+
+rebase.rebaseMerges::
+	Whether and how to set the `--rebase-merges` option by default. Can
+	be `rebase-cousins`, `no-rebase-cousins`, or a boolean. Setting to
+	true or to `no-rebase-cousins` is equivalent to
+	`--rebase-merges=no-rebase-cousins`, setting to `rebase-cousins` is
+	equivalent to `--rebase-merges=rebase-cousins`, and setting to false is
+	equivalent to `--no-rebase-merges`. Passing `--rebase-merges` on the
+	command line, with or without an argument, overrides any
+	`rebase.rebaseMerges` configuration.
diff --git a/Documentation/config/sendemail.txt b/Documentation/config/sendemail.txt
index 51da708..92a9ebe 100644
--- a/Documentation/config/sendemail.txt
+++ b/Documentation/config/sendemail.txt
@@ -61,6 +61,7 @@
 sendemail.chainReplyTo::
 sendemail.envelopeSender::
 sendemail.from::
+sendemail.headerCmd::
 sendemail.signedoffbycc::
 sendemail.smtpPass::
 sendemail.suppresscc::
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 7d73e97..9f33f88 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -35,8 +35,11 @@
 
 -s::
 --no-patch::
-	Suppress diff output. Useful for commands like `git show` that
-	show the patch by default, or to cancel the effect of `--patch`.
+	Suppress all output from the diff machinery.  Useful for
+	commands like `git show` that show the patch by default to
+	squelch their output, or to cancel the effect of options like
+	`--patch`, `--stat` earlier on the command line in an alias.
+
 endif::git-format-patch[]
 
 ifdef::git-log[]
@@ -852,6 +855,11 @@
 --no-prefix::
 	Do not show any source or destination prefix.
 
+--default-prefix::
+	Use the default source and destination prefixes ("a/" and "b/").
+	This is usually the default already, but may be used to override
+	config such as `diff.noprefix`.
+
 --line-prefix=<prefix>::
 	Prepend an additional prefix to every line of output.
 
diff --git a/Documentation/doc-diff b/Documentation/doc-diff
index 1694300..fb09e0a 100755
--- a/Documentation/doc-diff
+++ b/Documentation/doc-diff
@@ -153,7 +153,7 @@
 		make -j$parallel -C "$tmp/worktree" \
 			$makemanflags \
 			GIT_VERSION=omitted \
-			SOURCE_DATE_EPOCH=0 \
+			GIT_DATE=1970-01-01 \
 			DESTDIR="$tmp/installed/$dname+" \
 			install-man &&
 		mv "$tmp/installed/$dname+" "$tmp/installed/$dname"
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 622bd84..41fc7ca 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -78,6 +78,13 @@
 --dry-run::
 	Show what would be done, without making any changes.
 
+--porcelain::
+	Print the output to standard output in an easy-to-parse format for
+	scripts. See section OUTPUT in linkgit:git-fetch[1] for details.
++
+This is incompatible with `--recurse-submodules=[yes|on-demand]` and takes
+precedence over the `fetch.output` config option.
+
 ifndef::git-pull[]
 --[no-]write-fetch-head::
 	Write the list of remote refs fetched in the `FETCH_HEAD`
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 0c1dfb3..900be19 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -24,7 +24,9 @@
 -----------
 Splits mail messages in a mailbox into commit log message,
 authorship information and patches, and applies them to the
-current branch.
+current branch. You could think of it as a reverse operation
+of linkgit:git-format-patch[1] run on a branch with a straight
+history without merges.
 
 OPTIONS
 -------
@@ -273,7 +275,8 @@
 
 SEE ALSO
 --------
-linkgit:git-apply[1].
+linkgit:git-apply[1],
+linkgit:git-format-patch[1].
 
 GIT
 ---
diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt
index 4400a17..f69a871 100644
--- a/Documentation/git-blame.txt
+++ b/Documentation/git-blame.txt
@@ -12,7 +12,7 @@
 	    [-L <range>] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
 	    [--ignore-rev <rev>] [--ignore-revs-file <file>]
 	    [--color-lines] [--color-by-age] [--progress] [--abbrev=<n>]
-	    [<rev> | --contents <file> | --reverse <rev>..<rev>] [--] <file>
+	    [ --contents <file> ] [<rev> | --reverse <rev>..<rev>] [--] <file>
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index d382ac6..d207da9 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -156,6 +156,10 @@
 --ignore-case::
 	Sorting and filtering branches are case insensitive.
 
+--omit-empty::
+	Do not print a newline after formatted refs where the format expands
+	to the empty string.
+
 --column[=<options>]::
 --no-column::
 	Display branch listing in columns. See configuration variable
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index 18a022b..3ab42a1 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git bundle' create [-q | --quiet | --progress | --all-progress] [--all-progress-implied]
+'git bundle' create [-q | --quiet | --progress]
 		    [--version=<version>] <file> <git-rev-list-args>
 'git bundle' verify [-q | --quiet] <file>
 'git bundle' list-heads <file> [<refname>...]
@@ -66,7 +66,7 @@
 	Used to create a bundle named 'file'.  This requires the
 	'<git-rev-list-args>' arguments to define the bundle contents.
 	'options' contains the options specific to the 'git bundle create'
-	subcommand.
+	subcommand. If 'file' is `-`, the bundle is written to stdout.
 
 verify <file>::
 	Used to check that a bundle file is valid and will apply
@@ -77,12 +77,13 @@
 	Finally, information about additional capabilities, such as "object
 	filter", is printed. See "Capabilities" in linkgit:gitformat-bundle[5]
 	for more information. The exit code is zero for success, but will
-	be nonzero if the bundle file is invalid.
+	be nonzero if the bundle file is invalid. If 'file' is `-`, the
+	bundle is read from stdin.
 
 list-heads <file>::
 	Lists the references defined in the bundle.  If followed by a
 	list of references, only references matching those given are
-	printed out.
+	printed out. If 'file' is `-`, the bundle is read from stdin.
 
 unbundle <file>::
 	Passes the objects in the bundle to 'git index-pack'
@@ -90,6 +91,7 @@
 	defined references. If a list of references is given, only
 	references matching those in the list are printed. This command is
 	really plumbing, intended to be called only by 'git fetch'.
+	If 'file' is `-`, the bundle is read from stdin.
 
 <git-rev-list-args>::
 	A list of arguments, acceptable to 'git rev-parse' and
@@ -115,22 +117,6 @@
 	is specified. This flag forces progress status even if
 	the standard error stream is not directed to a terminal.
 
---all-progress::
-	When --stdout is specified then progress report is
-	displayed during the object count and compression phases
-	but inhibited during the write-out phase. The reason is
-	that in some cases the output stream is directly linked
-	to another command which may wish to display progress
-	status of its own as it processes incoming pack data.
-	This flag is like --progress except that it forces progress
-	report for the write-out phase as well even if --stdout is
-	used.
-
---all-progress-implied::
-	This is used to imply --all-progress whenever progress display
-	is activated.  Unlike --all-progress this flag doesn't actually
-	force any progress display by itself.
-
 --version=<version>::
 	Specify the bundle version.  Version 2 is the older format and can only be
 	used with SHA-1 repositories; the newer version 3 contains capabilities that
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 6bb32ab..4af0904 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -483,14 +483,11 @@
 $ git branch foo                                 <2>
 $ git tag foo                                    <3>
 ------------
-
 <1> creates a new branch `foo`, which refers to commit `f`, and then
     updates `HEAD` to refer to branch `foo`. In other words, we'll no longer
     be in detached `HEAD` state after this command.
-
 <2> similarly creates a new branch `foo`, which refers to commit `f`,
     but leaves `HEAD` detached.
-
 <3> creates a new tag `foo`, which refers to commit `f`,
     leaving `HEAD` detached.
 
@@ -519,84 +516,89 @@
 EXAMPLES
 --------
 
-. The following sequence checks out the `master` branch, reverts
-  the `Makefile` to two revisions back, deletes `hello.c` by
-  mistake, and gets it back from the index.
-+
+=== 1. Paths
+
+The following sequence checks out the `master` branch, reverts
+the `Makefile` to two revisions back, deletes `hello.c` by
+mistake, and gets it back from the index.
+
 ------------
 $ git checkout master             <1>
 $ git checkout master~2 Makefile  <2>
 $ rm -f hello.c
 $ git checkout hello.c            <3>
 ------------
-+
 <1> switch branch
 <2> take a file out of another commit
 <3> restore `hello.c` from the index
-+
+
 If you want to check out _all_ C source files out of the index,
 you can say
-+
+
 ------------
 $ git checkout -- '*.c'
 ------------
-+
+
 Note the quotes around `*.c`.  The file `hello.c` will also be
 checked out, even though it is no longer in the working tree,
 because the file globbing is used to match entries in the index
 (not in the working tree by the shell).
-+
+
 If you have an unfortunate branch that is named `hello.c`, this
 step would be confused as an instruction to switch to that branch.
 You should instead write:
-+
+
 ------------
 $ git checkout -- hello.c
 ------------
 
-. After working in the wrong branch, switching to the correct
-  branch would be done using:
-+
+=== 2. Merge
+
+After working in the wrong branch, switching to the correct
+branch would be done using:
+
 ------------
 $ git checkout mytopic
 ------------
-+
+
 However, your "wrong" branch and correct `mytopic` branch may
 differ in files that you have modified locally, in which case
 the above checkout would fail like this:
-+
+
 ------------
 $ git checkout mytopic
 error: You have local changes to 'frotz'; not switching branches.
 ------------
-+
+
 You can give the `-m` flag to the command, which would try a
 three-way merge:
-+
+
 ------------
 $ git checkout -m mytopic
 Auto-merging frotz
 ------------
-+
+
 After this three-way merge, the local modifications are _not_
 registered in your index file, so `git diff` would show you what
 changes you made since the tip of the new branch.
 
-. When a merge conflict happens during switching branches with
-  the `-m` option, you would see something like this:
-+
+=== 3. Merge conflict
+
+When a merge conflict happens during switching branches with
+the `-m` option, you would see something like this:
+
 ------------
 $ git checkout -m mytopic
 Auto-merging frotz
 ERROR: Merge conflict in frotz
 fatal: merge program failed
 ------------
-+
+
 At this point, `git diff` shows the changes cleanly merged as in
 the previous example, as well as the changes in the conflicted
 files.  Edit and resolve the conflict and mark it resolved with
 `git add` as usual:
-+
+
 ------------
 $ edit frotz
 $ git add frotz
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index d6434d2..c37c4a3 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -58,6 +58,11 @@
 override the default when `/path/to/repo` is given, using the regular
 Git transport instead.
 +
+If the repository's `$GIT_DIR/objects` has symbolic links or is a
+symbolic link, the clone will fail. This is a security measure to
+prevent the unintentional copying of files by dereferencing the symbolic
+links.
++
 *NOTE*: this operation can race with concurrent modification to the
 source repository, similar to running `cp -r src dst` while modifying
 `src`.
diff --git a/Documentation/git-credential.txt b/Documentation/git-credential.txt
index 29d184a..0e6d9e8 100644
--- a/Documentation/git-credential.txt
+++ b/Documentation/git-credential.txt
@@ -113,7 +113,13 @@
 The key may contain any bytes except `=`, newline, or NUL. The value may
 contain any bytes except newline or NUL.
 
-In both cases, all bytes are treated as-is (i.e., there is no quoting,
+Attributes with keys that end with C-style array brackets `[]` can have
+multiple values. Each instance of a multi-valued attribute forms an
+ordered list of values - the order of the repeated attributes defines
+the order of the values. An empty multi-valued attribute (`key[]=\n`)
+acts to clear any previous entries and reset the list.
+
+In all cases, all bytes are treated as-is (i.e., there is no quoting,
 and one cannot transmit a value with newline or NUL in it). The list of
 attributes is terminated by a blank line or end-of-file.
 
@@ -150,6 +156,12 @@
 	When reading credentials from helpers, `git credential fill` ignores expired
 	passwords. Represented as Unix time UTC, seconds since 1970.
 
+`oauth_refresh_token`::
+
+	An OAuth refresh token may accompany a password that is an OAuth access
+	token. Helpers must treat this attribute as confidential like the password
+	attribute. Git itself has no special behaviour for this attribute.
+
 `url`::
 
 	When this special attribute is read by `git credential`, the
@@ -166,6 +178,17 @@
 Components which are missing from the URL (e.g., there is no
 username in the example above) will be left unset.
 
+`wwwauth[]`::
+
+	When an HTTP response is received by Git that includes one or more
+	'WWW-Authenticate' authentication headers, these will be passed by Git
+	to credential helpers.
++
+Each 'WWW-Authenticate' header value is passed as a multi-valued
+attribute 'wwwauth[]', where the order of the attributes is the same as
+they appear in the HTTP response. This attribute is 'one-way' from Git
+to pass additional information to credential helpers.
+
 Unrecognised attributes are silently discarded.
 
 GIT
diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt
index 9d14c3c..ac0ac6f 100644
--- a/Documentation/git-difftool.txt
+++ b/Documentation/git-difftool.txt
@@ -97,10 +97,12 @@
 --[no-]gui::
 	When 'git-difftool' is invoked with the `-g` or `--gui` option
 	the default diff tool will be read from the configured
-	`diff.guitool` variable instead of `diff.tool`. The `--no-gui`
-	option can be used to override this setting. If `diff.guitool`
-	is not set, we will fallback in the order of `merge.guitool`,
-	`diff.tool`, `merge.tool` until a tool is found.
+	`diff.guitool` variable instead of `diff.tool`. This may be
+	selected automatically using the configuration variable
+	`difftool.guiDefault`. The `--no-gui` option can be used to
+	override these settings. If `diff.guitool` is not set, we will
+	fallback in the order of `merge.guitool`, `diff.tool`,
+	`merge.tool` until a tool is found.
 
 --[no-]trust-exit-code::
 	'git-difftool' invokes a diff tool individually on each file.
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index fba66f1..f123139 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -204,6 +204,15 @@
  <flag> <summary> <from> -> <to> [<reason>]
 -------------------------------
 
+When using `--porcelain`, the output format is intended to be
+machine-parseable. In contrast to the human-readable output formats it
+thus prints to standard output instead of standard error. Each line is
+of the form:
+
+-------------------------------
+<flag> <old-object-id> <new-object-id> <local-reference>
+-------------------------------
+
 The status of up-to-date refs is shown only if the --verbose option is
 used.
 
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 6da899c..1e215d4 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -9,7 +9,8 @@
 --------
 [verse]
 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
-		   [(--sort=<key>)...] [--format=<format>] [<pattern>...]
+		   [(--sort=<key>)...] [--format=<format>]
+		   [ --stdin | <pattern>... ]
 		   [--points-at=<object>]
 		   [--merged[=<object>]] [--no-merged[=<object>]]
 		   [--contains[=<object>]] [--no-contains[=<object>]]
@@ -32,6 +33,10 @@
 	literally, in the latter case matching completely or from the
 	beginning up to a slash.
 
+--stdin::
+	If `--stdin` is supplied, then the list of patterns is read from
+	standard input instead of from the argument list.
+
 --count=<count>::
 	By default the command shows all refs that match
 	`<pattern>`.  This option makes it stop after showing
@@ -93,6 +98,10 @@
 --ignore-case::
 	Sorting and filtering refs are case insensitive.
 
+--omit-empty::
+	Do not print a newline after formatted refs where the format expands
+	to the empty string.
+
 FIELD NAMES
 -----------
 
@@ -217,6 +226,11 @@
 	out, if it is checked out in any linked worktree. Empty string
 	otherwise.
 
+ahead-behind:<committish>::
+	Two integers, separated by a space, demonstrating the number of
+	commits ahead and behind, respectively, when comparing the output
+	ref to the `<committish>` specified in the format.
+
 In addition to the above, for commit and tag objects, the header
 field names (`tree`, `parent`, `object`, `type`, and `tag`) can
 be used to specify the value in the header field.
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index dfcc7da..b1c13fb 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -99,7 +99,7 @@
 
 If given `--thread`, `git-format-patch` will generate `In-Reply-To` and
 `References` headers to make the second and subsequent patch mails appear
-as replies to the first mail; this also generates a `Message-Id` header to
+as replies to the first mail; this also generates a `Message-ID` header to
 reference.
 
 OPTIONS
@@ -163,7 +163,7 @@
 --no-thread::
 	Controls addition of `In-Reply-To` and `References` headers to
 	make the second and subsequent mails appear as replies to the
-	first.  Also controls generation of the `Message-Id` header to
+	first.  Also controls generation of the `Message-ID` header to
 	reference.
 +
 The optional <style> argument can be either `shallow` or `deep`.
@@ -173,8 +173,7 @@
 threading makes every mail a reply to the previous one.
 +
 The default is `--no-thread`, unless the `format.thread` configuration
-is set.  If `--thread` is specified without a style, it defaults to the
-style specified by `format.thread` if any, or else `shallow`.
+is set.  `--thread` without an argument is equivalent to `--thread=shallow`.
 +
 Beware that the default for 'git send-email' is to thread emails
 itself.  If you want `git format-patch` to take care of threading, you
diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index a65c9aa..90806fd 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -54,9 +54,10 @@
 be performed as well.
 
 
---cruft::
+--[no-]cruft::
 	When expiring unreachable objects, pack them separately into a
-	cruft pack instead of storing them as loose objects.
+	cruft pack instead of storing them as loose objects. `--cruft`
+	is on by default.
 
 --prune=<date>::
 	Prune loose objects older than date (default is 2 weeks ago,
@@ -77,9 +78,10 @@
 	instance running on this repository.
 
 --keep-largest-pack::
-	All packs except the largest pack and those marked with a
-	`.keep` files are consolidated into a single pack. When this
-	option is used, `gc.bigPackThreshold` is ignored.
+	All packs except the largest non-cruft pack, any packs marked
+	with a `.keep` file, and any cruft pack(s) are consolidated into
+	a single pack. When this option is used, `gc.bigPackThreshold`
+	is ignored.
 
 AGGRESSIVE
 ----------
diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt
index 22ff3a6..4b97f81 100644
--- a/Documentation/git-interpret-trailers.txt
+++ b/Documentation/git-interpret-trailers.txt
@@ -280,7 +280,7 @@
 subject
 
 message
-$ cat msg.txt | git interpret-trailers --trailer 'sign: Alice <alice@example.com>' --trailer 'sign: Bob <bob@example.com>'
+$ git interpret-trailers --trailer 'sign: Alice <alice@example.com>' --trailer 'sign: Bob <bob@example.com>' <msg.txt
 subject
 
 message
@@ -322,17 +322,30 @@
   'Signed-off-by: ' already, and show how it works:
 +
 ------------
+$ cat msg1.txt
+subject
+
+message
 $ git config trailer.sign.key "Signed-off-by: "
 $ git config trailer.sign.ifmissing add
 $ git config trailer.sign.ifexists doNothing
-$ git config trailer.sign.command 'echo "$(git config user.name) <$(git config user.email)>"'
-$ git interpret-trailers <<EOF
-> EOF
+$ git config trailer.sign.cmd 'echo "$(git config user.name) <$(git config user.email)>"'
+$ git interpret-trailers --trailer sign <msg1.txt
+subject
+
+message
 
 Signed-off-by: Bob <bob@example.com>
-$ git interpret-trailers <<EOF
-> Signed-off-by: Alice <alice@example.com>
-> EOF
+$ cat msg2.txt
+subject
+
+message
+
+Signed-off-by: Alice <alice@example.com>
+$ git interpret-trailers --trailer sign <msg2.txt
+subject
+
+message
 
 Signed-off-by: Alice <alice@example.com>
 ------------
@@ -357,15 +370,14 @@
 $ cat ~/bin/glog-find-author
 #!/bin/sh
 test -n "$1" && git log --author="$1" --pretty="%an <%ae>" -1 || true
+$ cat msg.txt
+subject
+
+message
 $ git config trailer.help.key "Helped-by: "
 $ git config trailer.help.ifExists "addIfDifferentNeighbor"
 $ git config trailer.help.cmd "~/bin/glog-find-author"
-$ git interpret-trailers --trailer="help:Junio" --trailer="help:Couder" <<EOF
-> subject
->
-> message
->
-> EOF
+$ git interpret-trailers --trailer="help:Junio" --trailer="help:Couder" <msg.txt
 subject
 
 message
@@ -382,15 +394,14 @@
 $ cat ~/bin/glog-grep
 #!/bin/sh
 test -n "$1" && git log --grep "$1" --pretty=reference -1 || true
+$ cat msg.txt
+subject
+
+message
 $ git config trailer.ref.key "Reference-to: "
 $ git config trailer.ref.ifExists "replace"
 $ git config trailer.ref.cmd "~/bin/glog-grep"
-$ git interpret-trailers --trailer="ref:Add copyright notices." <<EOF
-> subject
->
-> message
->
-> EOF
+$ git interpret-trailers --trailer="ref:Add copyright notices." <msg.txt
 subject
 
 message
@@ -402,17 +413,20 @@
   commit that is related, and show how it works:
 +
 ------------
+$ cat msg.txt
+subject
+
+message
+
+see: HEAD~2
+$ cat ~/bin/glog-ref
+#!/bin/sh
+git log -1 --oneline --format="%h (%s)" --abbrev-commit --abbrev=14
 $ git config trailer.see.key "See-also: "
 $ git config trailer.see.ifExists "replace"
 $ git config trailer.see.ifMissing "doNothing"
-$ git config trailer.see.command "git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 \$ARG"
-$ git interpret-trailers <<EOF
-> subject
-> 
-> message
-> 
-> see: HEAD~2
-> EOF
+$ git config trailer.see.cmd "glog-ref"
+$ git interpret-trailers --trailer=see <msg.txt
 subject
 
 message
@@ -427,22 +441,21 @@
   to add a 'git-version' trailer:
 +
 ------------
-$ sed -e 's/ Z$/ /' >commit_template.txt <<EOF
-> ***subject***
-> 
-> ***message***
-> 
-> Fixes: Z
-> Cc: Z
-> Reviewed-by: Z
-> Signed-off-by: Z
-> EOF
+$ cat temp.txt
+***subject***
+
+***message***
+
+Fixes: Z
+Cc: Z
+Reviewed-by: Z
+Signed-off-by: Z
+$ sed -e 's/ Z$/ /' temp.txt > commit_template.txt
 $ git config commit.template commit_template.txt
-$ cat >.git/hooks/commit-msg <<EOF
-> #!/bin/sh
-> git interpret-trailers --trim-empty --trailer "git-version: \$(git describe)" "\$1" > "\$1.new"
-> mv "\$1.new" "\$1"
-> EOF
+$ cat .git/hooks/commit-msg
+#!/bin/sh
+git interpret-trailers --trim-empty --trailer "git-version: \$(git describe)" "\$1" > "\$1.new"
+mv "\$1.new" "\$1"
 $ chmod +x .git/hooks/commit-msg
 ------------
 
diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt
index 88ee942..ffc4fbf 100644
--- a/Documentation/git-merge-tree.txt
+++ b/Documentation/git-merge-tree.txt
@@ -108,7 +108,7 @@
 
      0: merge had conflicts
      1: merge was clean
-     &lt;0: something prevented the merge from running (e.g. access to repository
+     <0: something prevented the merge from running (e.g. access to repository
 	 objects denied by filesystem)
 
 [[OIDTLT]]
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index c44e205..07535f6 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -85,12 +85,13 @@
 	the default merge tool will be read from the configured
 	`merge.guitool` variable instead of `merge.tool`. If
 	`merge.guitool` is not set, we will fallback to the tool
-	configured under `merge.tool`.
+	configured under `merge.tool`. This may be autoselected using
+	the configuration variable `mergetool.guiDefault`.
 
 --no-gui::
-	This overrides a previous `-g` or `--gui` setting and reads the
-	default merge tool will be read from the configured `merge.tool`
-	variable.
+	This overrides a previous `-g` or `--gui` setting or
+	`mergetool.guiDefault` configuration and reads the default merge
+	tool from the configured `merge.tool` variable.
 
 -O<orderfile>::
 	Process files in the order specified in the
diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index ec8a27c..5c56c87 100644
--- a/Documentation/git-name-rev.txt
+++ b/Documentation/git-name-rev.txt
@@ -10,7 +10,7 @@
 --------
 [verse]
 'git name-rev' [--tags] [--refs=<pattern>]
-	       ( --all | --stdin | <commit-ish>... )
+	       ( --all | --annotate-stdin | <commit-ish>... )
 
 DESCRIPTION
 -----------
@@ -46,7 +46,8 @@
 	Transform stdin by substituting all the 40-character SHA-1
 	hexes (say $hex) with "$hex ($rev_name)".  When used with
 	--name-only, substitute with "$rev_name", omitting $hex
-	altogether.
+	altogether. This option was called `--stdin` in older versions
+	of Git.
 +
 For example:
 +
@@ -70,10 +71,6 @@
 while its tree object is 70d105cc79e63b81cfdcb08a15297c23e60b07ad
 -----------
 
---stdin::
-	This option is deprecated in favor of 'git name-rev --annotate-stdin'.
-	They are functionally equivalent.
-
 --name-only::
 	Instead of printing both the SHA-1 and the name, print only
 	the name.  If given with --tags the usual tag prefix of
@@ -107,7 +104,7 @@
 Another nice thing you can do is:
 
 ------------
-% git log | git name-rev --stdin
+% git log | git name-rev --annotate-stdin
 ------------
 
 GIT
diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt
index 99ef138..13c3eb5 100644
--- a/Documentation/git-pack-redundant.txt
+++ b/Documentation/git-pack-redundant.txt
@@ -11,6 +11,20 @@
 [verse]
 'git pack-redundant' [--verbose] [--alt-odb] (--all | <pack-filename>...)
 
+WARNING
+-------
+`git pack-redundant` has been deprecated and is scheduled for removal in
+a future version of Git. Because it can only remove entire duplicate
+packs and not individual duplicate objects, it is generally not a useful
+tool for reducing repository size. You are better off using `git gc` to
+do so, which will put objects into a new pack, removing duplicates.
+
+Running `pack-redundant` without the `--i-still-use-this` flag will fail
+in this release. If you believe you have a use case for which
+`pack-redundant` is better suited and oppose this removal, please
+contact the Git mailing list at git@vger.kernel.org. More information
+about the list is available at https://git-scm.com/community.
+
 DESCRIPTION
 -----------
 This program computes which packs in your repository
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 5bb1d5a..297927d 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
+'git push' [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
 	   [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
 	   [-u | --set-upstream] [-o <string> | --push-option=<string>]
 	   [--[no-]signed|--signed=(true|false|if-asked)]
@@ -147,6 +147,7 @@
 `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
 
 --all::
+--branches::
 	Push all branches (i.e. refs under `refs/heads/`); cannot be
 	used with other <refspec>.
 
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 9a295bc..e7b39ad 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -529,20 +529,25 @@
 
 -r::
 --rebase-merges[=(rebase-cousins|no-rebase-cousins)]::
+--no-rebase-merges::
 	By default, a rebase will simply drop merge commits from the todo
 	list, and put the rebased commits into a single, linear branch.
 	With `--rebase-merges`, the rebase will instead try to preserve
 	the branching structure within the commits that are to be rebased,
 	by recreating the merge commits. Any resolved merge conflicts or
 	manual amendments in these merge commits will have to be
-	resolved/re-applied manually.
+	resolved/re-applied manually. `--no-rebase-merges` can be used to
+	countermand both the `rebase.rebaseMerges` config option and a previous
+	`--rebase-merges`.
 +
-By default, or when `no-rebase-cousins` was specified, commits which do not
-have `<upstream>` as direct ancestor will keep their original branch point,
-i.e. commits that would be excluded by linkgit:git-log[1]'s
-`--ancestry-path` option will keep their original ancestry by default. If
-the `rebase-cousins` mode is turned on, such commits are instead rebased
-onto `<upstream>` (or `<onto>`, if specified).
+When rebasing merges, there are two modes: `rebase-cousins` and
+`no-rebase-cousins`. If the mode is not specified, it defaults to
+`no-rebase-cousins`. In `no-rebase-cousins` mode, commits which do not have
+`<upstream>` as direct ancestor will keep their original branch point, i.e.
+commits that would be excluded by linkgit:git-log[1]'s `--ancestry-path`
+option will keep their original ancestry by default. In `rebase-cousins` mode,
+such commits are instead rebased onto `<upstream>` (or `<onto>`, if
+specified).
 +
 It is currently only possible to recreate the merge commits using the
 `ort` merge strategy; different merge strategies can be used only via
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index bcd8069..f26a759 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -197,10 +197,11 @@
 or `--all`. If a trailing '/{asterisk}' is intended, it must be given
 explicitly.
 
---exclude-hidden=[receive|uploadpack]::
-	Do not include refs that would be hidden by `git-receive-pack` or
-	`git-upload-pack` by consulting the appropriate `receive.hideRefs` or
-	`uploadpack.hideRefs` configuration along with `transfer.hideRefs` (see
+--exclude-hidden=[fetch|receive|uploadpack]::
+	Do not include refs that would be hidden by `git-fetch`,
+	`git-receive-pack` or `git-upload-pack` by consulting the appropriate
+	`fetch.hideRefs`, `receive.hideRefs` or `uploadpack.hideRefs`
+	configuration along with `transfer.hideRefs` (see
 	linkgit:git-config[1]). This option affects the next pseudo-ref option
 	`--all` or `--glob` and is cleared after processing them.
 
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 765b2df..492a823 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -93,7 +93,7 @@
 
 --in-reply-to=<identifier>::
 	Make the first mail (or all the mails with `--no-thread`) appear as a
-	reply to the given Message-Id, which avoids breaking threads to
+	reply to the given Message-ID, which avoids breaking threads to
 	provide a new patch series.
 	The second and subsequent emails will be sent as replies according to
 	the `--[no-]chain-reply-to` setting.
@@ -320,6 +320,17 @@
 	Output of this command must be single email address per line.
 	Default is the value of `sendemail.ccCmd` configuration value.
 
+--header-cmd=<command>::
+	Specify a command that is executed once per outgoing message
+	and output RFC 2822 style header lines to be inserted into
+	them. When the `sendemail.headerCmd` configuration variable is
+	set, its value is always used. When --header-cmd is provided
+	at the command line, its value takes precedence over the
+	`sendemail.headerCmd` configuration variable.
+
+--no-header-cmd::
+	Disable any header command in use.
+
 --[no-]chain-reply-to::
 	If this is set, each email will be sent as a reply to the previous
 	email sent.  If disabled with "--no-chain-reply-to", all emails after
@@ -484,14 +495,10 @@
 	smtpServerPort = 587
 ----
 
-If you have multi-factor authentication set up on your Gmail account, you will
-need to generate an app-specific password for use with 'git send-email'. Visit
+If you have multi-factor authentication set up on your Gmail account, you can
+generate an app-specific password for use with 'git send-email'. Visit
 https://security.google.com/settings/security/apppasswords to create it.
 
-If you do not have multi-factor authentication set up on your Gmail account,
-you will need to allow less secure app access. Visit
-https://myaccount.google.com/lesssecureapps to enable it.
-
 Once your commits are ready to be sent to the mailing list, run the
 following commands:
 
diff --git a/Documentation/git-sparse-checkout.txt b/Documentation/git-sparse-checkout.txt
index 68392d2..53dc17a 100644
--- a/Documentation/git-sparse-checkout.txt
+++ b/Documentation/git-sparse-checkout.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git sparse-checkout' (init | list | set | add | reapply | disable) [<options>]
+'git sparse-checkout' (init | list | set | add | reapply | disable | check-rules) [<options>]
 
 
 DESCRIPTION
@@ -135,6 +135,29 @@
 the disable command, so the easy restore of calling a plain `init`
 decreased in utility.
 
+'check-rules'::
+	Check whether sparsity rules match one or more paths.
++
+By default `check-rules` reads a list of paths from stdin and outputs only
+the ones that match the current sparsity rules. The input is expected to consist
+of one path per line, matching the output of `git ls-tree --name-only` including
+that pathnames that begin with a double quote (") are interpreted as C-style
+quoted strings.
++
+When called with the `--rules-file <file>` flag the input files are matched
+against the sparse checkout rules found in `<file>` instead of the current ones.
+The rules in the files are expected to be in the same form as accepted by `git
+sparse-checkout set --stdin` (in particular, they must be newline-delimited).
++
+By default, the rules passed to the `--rules-file` option are interpreted as
+cone mode directories. To pass non-cone mode patterns with `--rules-file`,
+combine the option with the `--no-cone` option.
++
+When called with the `-z` flag, the format of the paths input on stdin as well
+as the output paths are \0 terminated and not quoted. Note that this does not
+apply to the format of the rules passed with the `--rules-file` option.
+
+
 EXAMPLES
 --------
 `git sparse-checkout set MY/DIR1 SUB/DIR2`::
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index fdc72b5..d42efb3 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -131,6 +131,10 @@
 --ignore-case::
 	Sorting and filtering tags are case insensitive.
 
+--omit-empty::
+	Do not print a newline after formatted refs where the format expands
+	to the empty string.
+
 --column[=<options>]::
 --no-column::
 	Display tag listing in columns. See configuration variable
@@ -377,6 +381,16 @@
 
 include::date-formats.txt[]
 
+FILES
+-----
+
+`$GIT_DIR/TAG_EDITMSG`::
+	This file contains the message of an in-progress annotated
+	tag. If `git tag` exits due to an error before creating an
+	annotated tag then the tag message that has been provided by the
+	user in an editor session will be available in this file, but
+	may be overwritten by the next invocation of `git tag`.
+
 NOTES
 -----
 
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 74973d3..f0cafa2 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -212,6 +212,11 @@
 	nohelpers (exclude helper commands), alias and config
 	(retrieve command list from config variable completion.commands)
 
+--attr-source=<tree-ish>::
+	Read gitattributes from <tree-ish> instead of the worktree. See
+	linkgit:gitattributes[5]. This is equivalent to setting the
+	`GIT_ATTR_SOURCE` environment variable.
+
 GIT COMMANDS
 ------------
 
@@ -546,9 +551,9 @@
 
 `GIT_DEFAULT_HASH`::
 	If this variable is set, the default hash algorithm for new
-	repositories will be set to this value. This value is currently
-	ignored when cloning; the setting of the remote repository
-	is used instead. The default is "sha1". THIS VARIABLE IS
+	repositories will be set to this value. This value is
+	ignored when cloning and the setting of the remote repository
+	is always used. The default is "sha1". THIS VARIABLE IS
 	EXPERIMENTAL! See `--object-format` in linkgit:git-init[1].
 
 Git Commits
@@ -686,6 +691,9 @@
 	tells Git not to verify the SSL certificate when fetching or
 	pushing over HTTPS.
 
+`GIT_ATTR_SOURCE`::
+	Sets the treeish that gitattributes will be read from.
+
 `GIT_ASKPASS`::
 	If this environment variable is set, then Git commands which need to
 	acquire passwords or passphrases (e.g. for HTTP or IMAP authentication)
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 39bfbca..02a3ec8 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -120,20 +120,19 @@
 `text`
 ^^^^^^
 
-This attribute enables and controls end-of-line normalization.  When a
-text file is normalized, its line endings are converted to LF in the
-repository.  To control what line ending style is used in the working
-directory, use the `eol` attribute for a single file and the
-`core.eol` configuration variable for all text files.
-Note that setting `core.autocrlf` to `true` or `input` overrides
-`core.eol` (see the definitions of those options in
-linkgit:git-config[1]).
+This attribute marks the path as a text file, which enables end-of-line
+conversion: When a matching file is added to the index, the file's line
+endings are normalized to LF in the index.  Conversely, when the file is
+copied from the index to the working directory, its line endings may be
+converted from LF to CRLF depending on the `eol` attribute, the Git
+config, and the platform (see explanation of `eol` below).
 
 Set::
 
 	Setting the `text` attribute on a path enables end-of-line
-	normalization and marks the path as a text file.  End-of-line
-	conversion takes place without guessing the content type.
+	conversion on checkin and checkout as described above.  Line endings
+	are normalized to LF in the index every time the file is checked in,
+	even if the file was previously added to Git with CRLF line endings.
 
 Unset::
 
@@ -142,10 +141,11 @@
 
 Set to string value "auto"::
 
-	When `text` is set to "auto", the path is marked for automatic
-	end-of-line conversion.  If Git decides that the content is
-	text, its line endings are converted to LF on checkin.
-	When the file has been committed with CRLF, no conversion is done.
+	When `text` is set to "auto", Git decides by itself whether the file
+	is text or binary.  If it is text and the file was not already in
+	Git with CRLF endings, line endings are converted on checkin and
+	checkout as described above.  Otherwise, no conversion is done on
+	checkin or checkout.
 
 Unspecified::
 
@@ -159,26 +159,29 @@
 `eol`
 ^^^^^
 
-This attribute sets a specific line-ending style to be used in the
-working directory.  This attribute has effect only if the `text`
-attribute is set or unspecified, or if it is set to `auto`, the file is
-detected as text, and it is stored with LF endings in the index.  Note
-that setting this attribute on paths which are in the index with CRLF
-line endings may make the paths to be considered dirty unless
-`text=auto` is set. Adding the path to the index again will normalize
-the line endings in the index.
+This attribute marks a path to use a specific line-ending style in the
+working tree when it is checked out.  It has effect only if `text` or
+`text=auto` is set (see above), but specifying `eol` automatically sets
+`text` if `text` was left unspecified.
 
 Set to string value "crlf"::
 
-	This setting forces Git to normalize line endings for this
-	file on checkin and convert them to CRLF when the file is
-	checked out.
+	This setting converts the file's line endings in the working
+	directory to CRLF when the file is checked out.
 
 Set to string value "lf"::
 
-	This setting forces Git to normalize line endings to LF on
-	checkin and prevents conversion to CRLF when the file is
-	checked out.
+	This setting uses the same line endings in the working directory as
+	in the index when the file is checked out.
+
+Unspecified::
+
+	If the `eol` attribute is unspecified for a file, its line endings
+	in the working directory are determined by the `core.autocrlf` or
+	`core.eol` configuration variable (see the definitions of those
+	options in linkgit:git-config[1]).  If `text` is set but neither of
+	those variables is, the default is `eol=crlf` on Windows and
+	`eol=lf` on all other platforms.
 
 Backwards compatibility with `crlf` attribute
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Documentation/gitformat-pack.txt b/Documentation/gitformat-pack.txt
index e06af02..0c1be2d 100644
--- a/Documentation/gitformat-pack.txt
+++ b/Documentation/gitformat-pack.txt
@@ -611,8 +611,8 @@
 
 If you are GC-ing repositories in a mixed version environment, consider omitting
 the `--cruft` option when using linkgit:git-repack[1] and linkgit:git-gc[1], and
-leaving the `gc.cruftPacks` configuration unset until all writers understand
-cruft packs.
+setting the `gc.cruftPacks` configuration to "false" until all writers
+understand cruft packs.
 
 === Alternatives
 
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 6290860..86f8047 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -595,10 +595,51 @@
 sendemail-validate
 ~~~~~~~~~~~~~~~~~~
 
-This hook is invoked by linkgit:git-send-email[1].  It takes a single parameter,
-the name of the file that holds the e-mail to be sent.  Exiting with a
-non-zero status causes `git send-email` to abort before sending any
-e-mails.
+This hook is invoked by linkgit:git-send-email[1].
+
+It takes these command line arguments. They are,
+1. the name of the file which holds the contents of the email to be sent.
+2. The name of the file which holds the SMTP headers of the email.
+
+The SMTP headers are passed in the exact same way as they are passed to the
+user's Mail Transport Agent (MTA). In effect, the email given to the user's
+MTA, is the contents of $2 followed by the contents of $1.
+
+An example of a few common headers is shown below. Take notice of the
+capitalization and multi-line tab structure.
+
+  From: Example <from@example.com>
+  To: to@example.com
+  Cc: cc@example.com,
+	  A <author@example.com>,
+	  One <one@example.com>,
+	  two@example.com
+  Subject: PATCH-STRING
+
+Exiting with a non-zero status causes `git send-email` to abort
+before sending any e-mails.
+
+The following environment variables are set when executing the hook.
+
+`GIT_SENDEMAIL_FILE_COUNTER`::
+	A 1-based counter incremented by one for every file holding an e-mail
+	to be sent (excluding any FIFOs). This counter does not follow the
+	patch series counter scheme. It will always start at 1 and will end at
+	GIT_SENDEMAIL_FILE_TOTAL.
+
+`GIT_SENDEMAIL_FILE_TOTAL`::
+	The total number of files that will be sent (excluding any FIFOs). This
+	counter does not follow the patch series counter scheme. It will always
+	be equal to the number of files being sent, whether there is a cover
+	letter or not.
+
+These variables may for instance be used to validate patch series.
+
+The sample `sendemail-validate` hook that comes with Git checks that all sent
+patches (excluding the cover letter) can be applied on top of the upstream
+repository default branch without conflicts. Some placeholders are left for
+additional validation steps to be performed after all patches of a given series
+have been applied.
 
 fsmonitor-watchman
 ~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index f2738b1..4c17f23 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -146,7 +146,9 @@
 not tracked by Git remain untracked.
 
 To stop tracking a file that is currently tracked, use
-'git rm --cached'.
+'git rm --cached' to remove the file from the index. The filename
+can then be added to the `.gitignore` file to stop the file from
+being reintroduced in later commits.
 
 Git does not follow symbolic links when accessing a `.gitignore` file in
 the working tree. This keeps behavior consistent when the file is
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index 0e0b863..c7cadd8 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -49,7 +49,7 @@
 Importing a new project
 -----------------------
 
-Assume you have a tarball project.tar.gz with your initial work.  You
+Assume you have a tarball `project.tar.gz` with your initial work.  You
 can place it under Git revision control as follows.
 
 ------------------------------------------------
@@ -65,10 +65,10 @@
 ------------------------------------------------
 
 You've now initialized the working directory--you may notice a new
-directory created, named ".git".
+directory created, named `.git`.
 
 Next, tell Git to take a snapshot of the contents of all files under the
-current directory (note the '.'), with 'git add':
+current directory (note the `.`), with `git add`:
 
 ------------------------------------------------
 $ git add .
@@ -76,7 +76,7 @@
 
 This snapshot is now stored in a temporary staging area which Git calls
 the "index".  You can permanently store the contents of the index in the
-repository with 'git commit':
+repository with `git commit`:
 
 ------------------------------------------------
 $ git commit
@@ -95,21 +95,20 @@
 ------------------------------------------------
 
 You are now ready to commit.  You can see what is about to be committed
-using 'git diff' with the --cached option:
+using `git diff` with the `--cached` option:
 
 ------------------------------------------------
 $ git diff --cached
 ------------------------------------------------
 
-(Without --cached, 'git diff' will show you any changes that
+(Without `--cached`, `git diff` will show you any changes that
 you've made but not yet added to the index.)  You can also get a brief
-summary of the situation with 'git status':
+summary of the situation with `git status`:
 
 ------------------------------------------------
 $ git status
 On branch master
 Changes to be committed:
-Your branch is up to date with 'origin/master'.
   (use "git restore --staged <file>..." to unstage)
 
 	modified:   file1
@@ -128,7 +127,7 @@
 This will again prompt you for a message describing the change, and then
 record a new version of the project.
 
-Alternatively, instead of running 'git add' beforehand, you can use
+Alternatively, instead of running `git add` beforehand, you can use
 
 ------------------------------------------------
 $ git commit -a
@@ -151,7 +150,7 @@
 
 Many revision control systems provide an `add` command that tells the
 system to start tracking changes to a new file.  Git's `add` command
-does something simpler and more powerful: 'git add' is used both for new
+does something simpler and more powerful: `git add` is used both for new
 and newly modified files, and in both cases it takes a snapshot of the
 given files and stages that content in the index, ready for inclusion in
 the next commit.
@@ -182,7 +181,7 @@
 -----------------
 
 A single Git repository can maintain multiple branches of
-development.  To create a new branch named "experimental", use
+development.  To create a new branch named `experimental`, use
 
 ------------------------------------------------
 $ git branch experimental
@@ -201,8 +200,8 @@
 * master
 ------------------------------------------------
 
-The "experimental" branch is the one you just created, and the
-"master" branch is a default branch that was created for you
+The `experimental` branch is the one you just created, and the
+`master` branch is a default branch that was created for you
 automatically.  The asterisk marks the branch you are currently on;
 type
 
@@ -210,8 +209,8 @@
 $ git switch experimental
 ------------------------------------------------
 
-to switch to the experimental branch.  Now edit a file, commit the
-change, and switch back to the master branch:
+to switch to the `experimental` branch.  Now edit a file, commit the
+change, and switch back to the `master` branch:
 
 ------------------------------------------------
 (edit file)
@@ -220,9 +219,9 @@
 ------------------------------------------------
 
 Check that the change you made is no longer visible, since it was
-made on the experimental branch and you're back on the master branch.
+made on the `experimental` branch and you're back on the `master` branch.
 
-You can make a different change on the master branch:
+You can make a different change on the `master` branch:
 
 ------------------------------------------------
 (edit file)
@@ -230,7 +229,7 @@
 ------------------------------------------------
 
 at this point the two branches have diverged, with different changes
-made in each.  To merge the changes made in experimental into master, run
+made in each.  To merge the changes made in `experimental` into `master`, run
 
 ------------------------------------------------
 $ git merge experimental
@@ -258,16 +257,16 @@
 
 will show a nice graphical representation of the resulting history.
 
-At this point you could delete the experimental branch with
+At this point you could delete the `experimental` branch with
 
 ------------------------------------------------
 $ git branch -d experimental
 ------------------------------------------------
 
-This command ensures that the changes in the experimental branch are
+This command ensures that the changes in the `experimental` branch are
 already in the current branch.
 
-If you develop on a branch crazy-idea, then regret it, you can always
+If you develop on a branch `crazy-idea`, then regret it, you can always
 delete the branch with
 
 -------------------------------------
@@ -281,7 +280,7 @@
 ---------------------------
 
 Suppose that Alice has started a new project with a Git repository in
-/home/alice/project, and that Bob, who has a home directory on the
+`/home/alice/project`, and that Bob, who has a home directory on the
 same machine, wants to contribute.
 
 Bob begins with:
@@ -290,7 +289,7 @@
 bob$ git clone /home/alice/project myrepo
 ------------------------------------------------
 
-This creates a new directory "myrepo" containing a clone of Alice's
+This creates a new directory `myrepo` containing a clone of Alice's
 repository.  The clone is on an equal footing with the original
 project, possessing its own copy of the original project's history.
 
@@ -303,31 +302,31 @@
 ------------------------------------------------
 
 When he's ready, he tells Alice to pull changes from the repository
-at /home/bob/myrepo.  She does this with:
+at `/home/bob/myrepo`.  She does this with:
 
 ------------------------------------------------
 alice$ cd /home/alice/project
 alice$ git pull /home/bob/myrepo master
 ------------------------------------------------
 
-This merges the changes from Bob's "master" branch into Alice's
+This merges the changes from Bob's `master` branch into Alice's
 current branch.  If Alice has made her own changes in the meantime,
 then she may need to manually fix any conflicts.
 
-The "pull" command thus performs two operations: it fetches changes
+The `pull` command thus performs two operations: it fetches changes
 from a remote branch, then merges them into the current branch.
 
 Note that in general, Alice would want her local changes committed before
-initiating this "pull".  If Bob's work conflicts with what Alice did since
+initiating this `pull`.  If Bob's work conflicts with what Alice did since
 their histories forked, Alice will use her working tree and the index to
 resolve conflicts, and existing local changes will interfere with the
 conflict resolution process (Git will still perform the fetch but will
 refuse to merge -- Alice will have to get rid of her local changes in
 some way and pull again when this happens).
 
-Alice can peek at what Bob did without merging first, using the "fetch"
+Alice can peek at what Bob did without merging first, using the `fetch`
 command; this allows Alice to inspect what Bob did, using a special
-symbol "FETCH_HEAD", in order to determine if he has anything worth
+symbol `FETCH_HEAD`, in order to determine if he has anything worth
 pulling, like this:
 
 ------------------------------------------------
@@ -336,10 +335,10 @@
 ------------------------------------------------
 
 This operation is safe even if Alice has uncommitted local changes.
-The range notation "HEAD..FETCH_HEAD" means "show everything that is reachable
-from the FETCH_HEAD but exclude anything that is reachable from HEAD".
-Alice already knows everything that leads to her current state (HEAD),
-and reviews what Bob has in his state (FETCH_HEAD) that she has not
+The range notation `HEAD..FETCH_HEAD` means "show everything that is reachable
+from the `FETCH_HEAD` but exclude anything that is reachable from `HEAD`".
+Alice already knows everything that leads to her current state (`HEAD`),
+and reviews what Bob has in his state (`FETCH_HEAD`) that she has not
 seen with this command.
 
 If Alice wants to visualize what Bob did since their histories forked
@@ -349,7 +348,7 @@
 $ gitk HEAD..FETCH_HEAD
 ------------------------------------------------
 
-This uses the same two-dot range notation we saw earlier with 'git log'.
+This uses the same two-dot range notation we saw earlier with `git log`.
 
 Alice may want to view what both of them did since they forked.
 She can use three-dot form instead of the two-dot form:
@@ -361,13 +360,13 @@
 This means "show everything that is reachable from either one, but
 exclude anything that is reachable from both of them".
 
-Please note that these range notation can be used with both gitk
-and "git log".
+Please note that these range notation can be used with both `gitk`
+and `git log`.
 
 After inspecting what Bob did, if there is nothing urgent, Alice may
 decide to continue working without pulling from Bob.  If Bob's history
 does have something Alice would immediately need, Alice may choose to
-stash her work-in-progress first, do a "pull", and then finally unstash
+stash her work-in-progress first, do a `pull`, and then finally unstash
 her work-in-progress on top of the resulting history.
 
 When you are working in a small closely knit group, it is not
@@ -379,8 +378,8 @@
 alice$ git remote add bob /home/bob/myrepo
 ------------------------------------------------
 
-With this, Alice can perform the first part of the "pull" operation
-alone using the 'git fetch' command without merging them with her own
+With this, Alice can perform the first part of the `pull` operation
+alone using the `git fetch` command without merging them with her own
 branch, using:
 
 -------------------------------------
@@ -388,7 +387,7 @@
 -------------------------------------
 
 Unlike the longhand form, when Alice fetches from Bob using a
-remote repository shorthand set up with 'git remote', what was
+remote repository shorthand set up with `git remote`, what was
 fetched is stored in a remote-tracking branch, in this case
 `bob/master`.  So after this:
 
@@ -397,10 +396,10 @@
 -------------------------------------
 
 shows a list of all the changes that Bob made since he branched from
-Alice's master branch.
+Alice's `master` branch.
 
 After examining those changes, Alice
-could merge the changes into her master branch:
+could merge the changes into her `master` branch:
 
 -------------------------------------
 alice$ git merge bob/master
@@ -432,12 +431,12 @@
 /home/alice/project
 -------------------------------------
 
-(The complete configuration created by 'git clone' is visible using
+(The complete configuration created by `git clone` is visible using
 `git config -l`, and the linkgit:git-config[1] man page
 explains the meaning of each option.)
 
-Git also keeps a pristine copy of Alice's master branch under the
-name "origin/master":
+Git also keeps a pristine copy of Alice's `master` branch under the
+name `origin/master`:
 
 -------------------------------------
 bob$ git branch -r
@@ -462,8 +461,8 @@
 -----------------
 
 Git history is represented as a series of interrelated commits.  We
-have already seen that the 'git log' command can list those commits.
-Note that first line of each git log entry also gives a name for the
+have already seen that the `git log` command can list those commits.
+Note that first line of each `git log` entry also gives a name for the
 commit:
 
 -------------------------------------
@@ -475,7 +474,7 @@
     merge-base: Clarify the comments on post processing.
 -------------------------------------
 
-We can give this name to 'git show' to see the details about this
+We can give this name to `git show` to see the details about this
 commit.
 
 -------------------------------------
@@ -514,7 +513,7 @@
 $ git tag v2.5 1b2e1d63ff
 -------------------------------------
 
-you can refer to 1b2e1d63ff by the name "v2.5".  If you intend to
+you can refer to `1b2e1d63ff` by the name `v2.5`.  If you intend to
 share this name with other people (for example, to identify a release
 version), you should create a "tag" object, and perhaps sign it; see
 linkgit:git-tag[1] for details.
@@ -533,22 +532,22 @@
 Be careful with that last command: in addition to losing any changes
 in the working directory, it will also remove all later commits from
 this branch.  If this branch is the only branch containing those
-commits, they will be lost.  Also, don't use 'git reset' on a
+commits, they will be lost.  Also, don't use `git reset` on a
 publicly-visible branch that other developers pull from, as it will
 force needless merges on other developers to clean up the history.
-If you need to undo changes that you have pushed, use 'git revert'
+If you need to undo changes that you have pushed, use `git revert`
 instead.
 
-The 'git grep' command can search for strings in any version of your
+The `git grep` command can search for strings in any version of your
 project, so
 
 -------------------------------------
 $ git grep "hello" v2.5
 -------------------------------------
 
-searches for all occurrences of "hello" in v2.5.
+searches for all occurrences of "hello" in `v2.5`.
 
-If you leave out the commit name, 'git grep' will search any of the
+If you leave out the commit name, `git grep` will search any of the
 files it manages in your current directory.  So
 
 -------------------------------------
@@ -558,7 +557,7 @@
 is a quick way to search just the files that are tracked by Git.
 
 Many Git commands also take sets of commits, which can be specified
-in a number of ways.  Here are some examples with 'git log':
+in a number of ways.  Here are some examples with `git log`:
 
 -------------------------------------
 $ git log v2.5..v2.6            # commits between v2.5 and v2.6
@@ -568,16 +567,16 @@
 				# Makefile
 -------------------------------------
 
-You can also give 'git log' a "range" of commits where the first is not
+You can also give `git log` a "range" of commits where the first is not
 necessarily an ancestor of the second; for example, if the tips of
-the branches "stable" and "master" diverged from a common
+the branches `stable` and `master` diverged from a common
 commit some time ago, then
 
 -------------------------------------
 $ git log stable..master
 -------------------------------------
 
-will list commits made in the master branch but not in the
+will list commits made in the `master` branch but not in the
 stable branch, while
 
 -------------------------------------
@@ -585,15 +584,15 @@
 -------------------------------------
 
 will show the list of commits made on the stable branch but not
-the master branch.
+the `master` branch.
 
-The 'git log' command has a weakness: it must present commits in a
+The `git log` command has a weakness: it must present commits in a
 list.  When the history has lines of development that diverged and
-then merged back together, the order in which 'git log' presents
+then merged back together, the order in which `git log` presents
 those commits is meaningless.
 
 Most projects with multiple contributors (such as the Linux kernel,
-or Git itself) have frequent merges, and 'gitk' does a better job of
+or Git itself) have frequent merges, and `gitk` does a better job of
 visualizing their history.  For example,
 
 -------------------------------------
@@ -601,7 +600,7 @@
 -------------------------------------
 
 allows you to browse any commits from the last 2 weeks of commits
-that modified files under the "drivers" directory.  (Note: you can
+that modified files under the `drivers` directory.  (Note: you can
 adjust gitk's fonts by holding down the control key while pressing
 "-" or "+".)
 
@@ -613,7 +612,7 @@
 $ git diff v2.5:Makefile HEAD:Makefile.in
 -------------------------------------
 
-You can also use 'git show' to see any such file:
+You can also use `git show` to see any such file:
 
 -------------------------------------
 $ git show v2.5:Makefile
@@ -649,7 +648,7 @@
 
   * linkgit:git-bisect[1]: When there is a regression in your
     project, one way to track down the bug is by searching through
-    the history to find the exact commit that's to blame.  Git bisect
+    the history to find the exact commit that's to blame.  `git bisect`
     can help you perform a binary search for that commit.  It is
     smart enough to perform a close-to-optimal search even in the
     case of complex non-linear history with lots of merged branches.
diff --git a/Documentation/manpage-base-url.xsl.in b/Documentation/manpage-base-url.xsl.in
deleted file mode 100644
index e800904..0000000
--- a/Documentation/manpage-base-url.xsl.in
+++ /dev/null
@@ -1,10 +0,0 @@
-<!-- manpage-base-url.xsl:
-     special settings for manpages rendered from newer docbook -->
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-		version="1.0">
-
-<!-- set a base URL for relative links -->
-<xsl:param name="man.base.url.for.relative.links"
-	>@@MAN_BASE_URL@@</xsl:param>
-
-</xsl:stylesheet>
diff --git a/Documentation/manpage-normal.xsl b/Documentation/manpage-normal.xsl
index a9c7ec6..beb5ff8 100644
--- a/Documentation/manpage-normal.xsl
+++ b/Documentation/manpage-normal.xsl
@@ -8,19 +8,7 @@
 <xsl:param name="man.output.quietly" select="1"/>
 <xsl:param name="refentry.meta.get.quietly" select="1"/>
 
-<!-- convert asciidoc callouts to man page format -->
-<xsl:template match="co">
-	<xsl:value-of select="concat('\fB(',substring-after(@id,'-'),')\fR')"/>
-</xsl:template>
-<xsl:template match="calloutlist">
-	<xsl:text>.sp&#10;</xsl:text>
-	<xsl:apply-templates/>
-	<xsl:text>&#10;</xsl:text>
-</xsl:template>
-<xsl:template match="callout">
-	<xsl:value-of select="concat('\fB',substring-after(@arearefs,'-'),'. \fR')"/>
-	<xsl:apply-templates/>
-	<xsl:text>.br&#10;</xsl:text>
-</xsl:template>
+<!-- unset maximum length of title -->
+<xsl:param name="man.th.title.max.length"/>
 
 </xsl:stylesheet>
diff --git a/Documentation/manpage-quote-apos.xsl b/Documentation/manpage-quote-apos.xsl
deleted file mode 100644
index aeb8839..0000000
--- a/Documentation/manpage-quote-apos.xsl
+++ /dev/null
@@ -1,16 +0,0 @@
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-		version="1.0">
-
-<!-- work around newer groff/man setups using a prettier apostrophe
-     that unfortunately does not quote anything when cut&pasting
-     examples to the shell -->
-<xsl:template name="escape.apostrophe">
-  <xsl:param name="content"/>
-  <xsl:call-template name="string.subst">
-    <xsl:with-param name="string" select="$content"/>
-    <xsl:with-param name="target">'</xsl:with-param>
-    <xsl:with-param name="replacement">\(aq</xsl:with-param>
-  </xsl:call-template>
-</xsl:template>
-
-</xsl:stylesheet>
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 0d90d5b..3000888 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -195,10 +195,11 @@
 or `--all`. If a trailing '/{asterisk}' is intended, it must be given
 explicitly.
 
---exclude-hidden=[receive|uploadpack]::
-	Do not include refs that would be hidden by `git-receive-pack` or
-	`git-upload-pack` by consulting the appropriate `receive.hideRefs` or
-	`uploadpack.hideRefs` configuration along with `transfer.hideRefs` (see
+--exclude-hidden=[fetch|receive|uploadpack]::
+	Do not include refs that would be hidden by `git-fetch`,
+	`git-receive-pack` or `git-upload-pack` by consulting the appropriate
+	`fetch.hideRefs`, `receive.hideRefs` or `uploadpack.hideRefs`
+	configuration along with `transfer.hideRefs` (see
 	linkgit:git-config[1]). This option affects the next pseudo-ref option
 	`--all` or `--glob` and is cleared after processing them.
 
@@ -889,7 +890,7 @@
 	Print the object IDs of any object referenced by the listed
 	commits.  `--objects foo ^bar` thus means ``send me
 	all object IDs which I need to download if I have the commit
-	object _bar_ but not _foo_''.
+	object _bar_ but not _foo_''. See also `--object-names` below.
 
 --in-commit-order::
 	Print tree and blob ids in order of the commits. The tree
@@ -919,7 +920,12 @@
 
 --object-names::
 	Only useful with `--objects`; print the names of the object IDs
-	that are found. This is the default behavior.
+	that are found. This is the default behavior. Note that the
+	"name" of each object is ambiguous, and mostly intended as a
+	hint for packing objects. In particular: no distinction is made between
+	the names of tags, trees, and blobs; path names may be modified
+	to remove newlines; and if an object would appear multiple times
+	with different names, only one name is shown.
 
 --no-object-names::
 	Only useful with `--objects`; does not print the names of the object
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index a87f0ad..b37f72a 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.40.0
+DEF_VER=v2.41.0
 
 LF='
 '
diff --git a/Makefile b/Makefile
index 50ee51f..e440728 100644
--- a/Makefile
+++ b/Makefile
@@ -207,10 +207,6 @@
 # Define NO_ST_BLOCKS_IN_STRUCT_STAT if your platform does not have st_blocks
 # field that counts the on-disk footprint in 512-byte blocks.
 #
-# Define GNU_ROFF if your target system uses GNU groff.  This forces
-# apostrophes to be ASCII so that cut&pasting examples to the shell
-# will work.
-#
 # Define USE_ASCIIDOCTOR to use Asciidoctor instead of AsciiDoc to build the
 # documentation.
 #
@@ -1036,6 +1032,7 @@
 LIB_OBJS += fsmonitor-ipc.o
 LIB_OBJS += fsmonitor-settings.o
 LIB_OBJS += gettext.o
+LIB_OBJS += git-zlib.o
 LIB_OBJS += gpg-interface.o
 LIB_OBJS += graph.o
 LIB_OBJS += grep.o
@@ -1196,7 +1193,6 @@
 LIB_OBJS += ws.o
 LIB_OBJS += wt-status.o
 LIB_OBJS += xdiff-interface.o
-LIB_OBJS += zlib.o
 
 BUILTIN_OBJS += builtin/add.o
 BUILTIN_OBJS += builtin/am.o
diff --git a/RelNotes b/RelNotes
index 47807bf..4da73c9 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.40.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.41.0.txt
\ No newline at end of file
diff --git a/abspath.c b/abspath.c
index 39e06b5..d032f5d 100644
--- a/abspath.c
+++ b/abspath.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "strbuf.h"
 
 /*
  * Do not use this for inspecting *tracked* content.  When path is a
@@ -280,3 +282,10 @@ char *prefix_filename(const char *pfx, const char *arg)
 #endif
 	return strbuf_detach(&path, NULL);
 }
+
+char *prefix_filename_except_for_dash(const char *pfx, const char *arg)
+{
+	if (!strcmp(arg, "-"))
+		return xstrdup(arg);
+	return prefix_filename(pfx, arg);
+}
diff --git a/abspath.h b/abspath.h
new file mode 100644
index 0000000..7cd3de5
--- /dev/null
+++ b/abspath.h
@@ -0,0 +1,33 @@
+#ifndef ABSPATH_H
+#define ABSPATH_H
+
+int is_directory(const char *);
+char *strbuf_realpath(struct strbuf *resolved, const char *path,
+		      int die_on_error);
+char *strbuf_realpath_forgiving(struct strbuf *resolved, const char *path,
+				int die_on_error);
+char *real_pathdup(const char *path, int die_on_error);
+const char *absolute_path(const char *path);
+char *absolute_pathdup(const char *path);
+
+/*
+ * Concatenate "prefix" (if len is non-zero) and "path", with no
+ * connecting characters (so "prefix" should end with a "/").
+ * Unlike prefix_path, this should be used if the named file does
+ * not have to interact with index entry; i.e. name of a random file
+ * on the filesystem.
+ *
+ * The return value is always a newly allocated string (even if the
+ * prefix was empty).
+ */
+char *prefix_filename(const char *prefix, const char *path);
+
+/* Likewise, but path=="-" always yields "-" */
+char *prefix_filename_except_for_dash(const char *prefix, const char *path);
+
+static inline int is_absolute_path(const char *path)
+{
+	return is_dir_sep(path[0]) || has_dos_drive_prefix(path);
+}
+
+#endif /* ABSPATH_H */
diff --git a/add-interactive.c b/add-interactive.c
index 00a0f6f..de877ca 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -3,6 +3,8 @@
 #include "color.h"
 #include "config.h"
 #include "diffcore.h"
+#include "gettext.h"
+#include "hex.h"
 #include "revision.h"
 #include "refs.h"
 #include "string-list.h"
@@ -10,6 +12,7 @@
 #include "dir.h"
 #include "run-command.h"
 #include "prompt.h"
+#include "tree.h"
 
 static void init_color(struct repository *r, struct add_i_state *s,
 		       const char *section_and_slot, char *dst,
@@ -551,7 +554,7 @@ static int get_modified_files(struct repository *r,
 		opt.def = is_initial ?
 			empty_tree_oid_hex() : oid_to_hex(&head_oid);
 
-		init_revisions(&rev, NULL);
+		repo_init_revisions(r, &rev, NULL);
 		setup_revisions(0, NULL, &rev, &opt);
 
 		rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
diff --git a/add-patch.c b/add-patch.c
index a86a92e..8d770d2 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -1,5 +1,11 @@
 #include "cache.h"
 #include "add-interactive.h"
+#include "advice.h"
+#include "alloc.h"
+#include "editor.h"
+#include "environment.h"
+#include "gettext.h"
+#include "object-name.h"
 #include "strbuf.h"
 #include "run-command.h"
 #include "strvec.h"
@@ -414,7 +420,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
 		strvec_push(&args,
 			    /* could be on an unborn branch */
 			    !strcmp("HEAD", s->revision) &&
-			    get_oid("HEAD", &oid) ?
+			    repo_get_oid(the_repository, "HEAD", &oid) ?
 			    empty_tree_oid_hex() : s->revision);
 	}
 	color_arg_index = args.nr;
@@ -483,7 +489,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
 		if (!eol)
 			eol = pend;
 
-		if (starts_with(p, "diff ")) {
+		if (starts_with(p, "diff ") ||
+		    starts_with(p, "* Unmerged path ")) {
 			complete_file(marker, hunk);
 			ALLOC_GROW_BY(s->file_diff, s->file_diff_nr, 1,
 				   file_diff_alloc);
diff --git a/advice.c b/advice.c
index fd18968..d623243 100644
--- a/advice.c
+++ b/advice.c
@@ -1,6 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
 #include "config.h"
 #include "color.h"
+#include "gettext.h"
 #include "help.h"
 #include "string-list.h"
 
@@ -44,6 +46,7 @@ static struct {
 	[ADVICE_COMMIT_BEFORE_MERGE]			= { "commitBeforeMerge", 1 },
 	[ADVICE_DETACHED_HEAD]				= { "detachedHead", 1 },
 	[ADVICE_SUGGEST_DETACHING_HEAD]			= { "suggestDetachingHead", 1 },
+	[ADVICE_DIVERGING]				= { "diverging", 1 },
 	[ADVICE_FETCH_SHOW_FORCED_UPDATES]		= { "fetchShowForcedUpdates", 1 },
 	[ADVICE_GRAFT_FILE_DEPRECATED]			= { "graftFileDeprecated", 1 },
 	[ADVICE_IGNORED_HOOK]				= { "ignoredHook", 1 },
@@ -217,6 +220,14 @@ void NORETURN die_conclude_merge(void)
 
 void NORETURN die_ff_impossible(void)
 {
+	advise_if_enabled(ADVICE_DIVERGING,
+		_("Diverging branches can't be fast-forwarded, you need to either:\n"
+		"\n"
+		"\tgit merge --no-ff\n"
+		"\n"
+		"or:\n"
+		"\n"
+		"\tgit rebase\n"));
 	die(_("Not possible to fast-forward, aborting."));
 }
 
diff --git a/advice.h b/advice.h
index 07e0f76..0f58416 100644
--- a/advice.h
+++ b/advice.h
@@ -1,8 +1,6 @@
 #ifndef ADVICE_H
 #define ADVICE_H
 
-#include "git-compat-util.h"
-
 struct string_list;
 
 /*
@@ -21,6 +19,7 @@ struct string_list;
 	ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME,
 	ADVICE_COMMIT_BEFORE_MERGE,
 	ADVICE_DETACHED_HEAD,
+	ADVICE_DIVERGING,
 	ADVICE_SUGGEST_DETACHING_HEAD,
 	ADVICE_FETCH_SHOW_FORCED_UPDATES,
 	ADVICE_GRAFT_FILE_DEPRECATED,
diff --git a/alias.c b/alias.c
index 00abde0..54a1a23 100644
--- a/alias.c
+++ b/alias.c
@@ -1,6 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "alias.h"
+#include "alloc.h"
 #include "config.h"
+#include "gettext.h"
+#include "strbuf.h"
 #include "string-list.h"
 
 struct config_alias_data {
@@ -44,6 +47,23 @@ void list_aliases(struct string_list *list)
 	read_early_config(config_alias_cb, &data);
 }
 
+void quote_cmdline(struct strbuf *buf, const char **argv)
+{
+	for (const char **argp = argv; *argp; argp++) {
+		if (argp != argv)
+			strbuf_addch(buf, ' ');
+		strbuf_addch(buf, '"');
+		for (const char *p = *argp; *p; p++) {
+			const char c = *p;
+
+			if (c == '"' || c =='\\')
+				strbuf_addch(buf, '\\');
+			strbuf_addch(buf, c);
+		}
+		strbuf_addch(buf, '"');
+	}
+}
+
 #define SPLIT_CMDLINE_BAD_ENDING 1
 #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2
 #define SPLIT_CMDLINE_ARGC_OVERFLOW 3
diff --git a/alias.h b/alias.h
index aef4843..43db736 100644
--- a/alias.h
+++ b/alias.h
@@ -1,9 +1,12 @@
 #ifndef ALIAS_H
 #define ALIAS_H
 
+struct strbuf;
 struct string_list;
 
 char *alias_lookup(const char *alias);
+/* Quote argv so buf can be parsed by split_cmdline() */
+void quote_cmdline(struct strbuf *buf, const char **argv);
 int split_cmdline(char *cmdline, const char ***argv);
 /* Takes a negative value returned by split_cmdline */
 const char *split_cmdline_strerror(int cmdline_errno);
diff --git a/alloc.c b/alloc.c
index 27f697e..377e80f 100644
--- a/alloc.c
+++ b/alloc.c
@@ -8,11 +8,12 @@
  * up with maximal alignment because it doesn't know what the object alignment
  * for the new allocation is.
  */
-#include "cache.h"
+#include "git-compat-util.h"
 #include "object.h"
 #include "blob.h"
 #include "tree.h"
 #include "commit.h"
+#include "repository.h"
 #include "tag.h"
 #include "alloc.h"
 
diff --git a/alloc.h b/alloc.h
index 3f4a0ad..4312db4 100644
--- a/alloc.h
+++ b/alloc.h
@@ -17,4 +17,79 @@ void *alloc_object_node(struct repository *r);
 struct alloc_state *allocate_alloc_state(void);
 void clear_alloc_state(struct alloc_state *s);
 
+#define alloc_nr(x) (((x)+16)*3/2)
+
+/**
+ * Dynamically growing an array using realloc() is error prone and boring.
+ *
+ * Define your array with:
+ *
+ * - a pointer (`item`) that points at the array, initialized to `NULL`
+ *   (although please name the variable based on its contents, not on its
+ *   type);
+ *
+ * - an integer variable (`alloc`) that keeps track of how big the current
+ *   allocation is, initialized to `0`;
+ *
+ * - another integer variable (`nr`) to keep track of how many elements the
+ *   array currently has, initialized to `0`.
+ *
+ * Then before adding `n`th element to the item, call `ALLOC_GROW(item, n,
+ * alloc)`.  This ensures that the array can hold at least `n` elements by
+ * calling `realloc(3)` and adjusting `alloc` variable.
+ *
+ * ------------
+ * sometype *item;
+ * size_t nr;
+ * size_t alloc
+ *
+ * for (i = 0; i < nr; i++)
+ * 	if (we like item[i] already)
+ * 		return;
+ *
+ * // we did not like any existing one, so add one
+ * ALLOC_GROW(item, nr + 1, alloc);
+ * item[nr++] = value you like;
+ * ------------
+ *
+ * You are responsible for updating the `nr` variable.
+ *
+ * If you need to specify the number of elements to allocate explicitly
+ * then use the macro `REALLOC_ARRAY(item, alloc)` instead of `ALLOC_GROW`.
+ *
+ * Consider using ALLOC_GROW_BY instead of ALLOC_GROW as it has some
+ * added niceties.
+ *
+ * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'.
+ */
+#define ALLOC_GROW(x, nr, alloc) \
+	do { \
+		if ((nr) > alloc) { \
+			if (alloc_nr(alloc) < (nr)) \
+				alloc = (nr); \
+			else \
+				alloc = alloc_nr(alloc); \
+			REALLOC_ARRAY(x, alloc); \
+		} \
+	} while (0)
+
+/*
+ * Similar to ALLOC_GROW but handles updating of the nr value and
+ * zeroing the bytes of the newly-grown array elements.
+ *
+ * DO NOT USE any expression with side-effect for any of the
+ * arguments.
+ */
+#define ALLOC_GROW_BY(x, nr, increase, alloc) \
+	do { \
+		if (increase) { \
+			size_t new_nr = nr + (increase); \
+			if (new_nr < nr) \
+				BUG("negative growth in ALLOC_GROW_BY"); \
+			ALLOC_GROW(x, new_nr, alloc); \
+			memset((x) + nr, 0, sizeof(*(x)) * (increase)); \
+			nr = new_nr; \
+		} \
+	} while (0)
+
 #endif
diff --git a/apply.c b/apply.c
index 5cc5479..6212ab3 100644
--- a/apply.c
+++ b/apply.c
@@ -8,20 +8,32 @@
  */
 
 #include "cache.h"
+#include "abspath.h"
+#include "alloc.h"
+#include "base85.h"
 #include "config.h"
 #include "object-store.h"
 #include "blob.h"
 #include "delta.h"
 #include "diff.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "xdiff-interface.h"
 #include "ll-merge.h"
 #include "lockfile.h"
+#include "object-name.h"
+#include "object-file.h"
 #include "parse-options.h"
 #include "quote.h"
 #include "rerere.h"
 #include "apply.h"
 #include "entry.h"
+#include "setup.h"
+#include "symlinks.h"
+#include "ws.h"
+#include "wrapper.h"
 
 struct gitdiff_data {
 	struct strbuf *root;
@@ -3201,7 +3213,8 @@ static int apply_binary(struct apply_state *state,
 		unsigned long size;
 		char *result;
 
-		result = read_object_file(&oid, &type, &size);
+		result = repo_read_object_file(the_repository, &oid, &type,
+					       &size);
 		if (!result)
 			return error(_("the necessary postimage %s for "
 				       "'%s' cannot be read"),
@@ -3264,7 +3277,8 @@ static int read_blob_object(struct strbuf *buf, const struct object_id *oid, uns
 		unsigned long sz;
 		char *result;
 
-		result = read_object_file(oid, &type, &sz);
+		result = repo_read_object_file(the_repository, oid, &type,
+					       &sz);
 		if (!result)
 			return -1;
 		/* XXX read_sha1_file NUL-terminates */
@@ -3492,7 +3506,8 @@ static int resolve_to(struct image *image, const struct object_id *result_id)
 
 	clear_image(image);
 
-	image->buf = read_object_file(result_id, &type, &size);
+	image->buf = repo_read_object_file(the_repository, result_id, &type,
+					   &size);
 	if (!image->buf || type != OBJ_BLOB)
 		die("unable to read blob object %s", oid_to_hex(result_id));
 	image->len = size;
@@ -3610,7 +3625,7 @@ static int try_threeway(struct apply_state *state,
 	/* Preimage the patch was prepared for */
 	if (patch->is_new)
 		write_object_file("", 0, OBJ_BLOB, &pre_oid);
-	else if (get_oid(patch->old_oid_prefix, &pre_oid) ||
+	else if (repo_get_oid(the_repository, patch->old_oid_prefix, &pre_oid) ||
 		 read_blob_object(&buf, &pre_oid, patch->old_mode))
 		return error(_("repository lacks the necessary blob to perform 3-way merge."));
 
@@ -4127,7 +4142,7 @@ static int build_fake_ancestor(struct apply_state *state, struct patch *list)
 			else
 				return error(_("sha1 information is lacking or "
 					       "useless for submodule %s"), name);
-		} else if (!get_oid_blob(patch->old_oid_prefix, &oid)) {
+		} else if (!repo_get_oid_blob(the_repository, patch->old_oid_prefix, &oid)) {
 			; /* ok */
 		} else if (!patch->lines_added && !patch->lines_deleted) {
 			/* mode-only change: update the current */
@@ -4576,7 +4591,7 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
 	FILE *rej;
 	char namebuf[PATH_MAX];
 	struct fragment *frag;
-	int cnt = 0;
+	int fd, cnt = 0;
 	struct strbuf sb = STRBUF_INIT;
 
 	for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) {
@@ -4616,7 +4631,17 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
 	memcpy(namebuf, patch->new_name, cnt);
 	memcpy(namebuf + cnt, ".rej", 5);
 
-	rej = fopen(namebuf, "w");
+	fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
+	if (fd < 0) {
+		if (errno != EEXIST)
+			return error_errno(_("cannot open %s"), namebuf);
+		if (unlink(namebuf))
+			return error_errno(_("cannot unlink '%s'"), namebuf);
+		fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
+		if (fd < 0)
+			return error_errno(_("cannot open %s"), namebuf);
+	}
+	rej = fdopen(fd, "w");
 	if (!rej)
 		return error_errno(_("cannot open %s"), namebuf);
 
diff --git a/apply.h b/apply.h
index b9f18ce..7cd38b1 100644
--- a/apply.h
+++ b/apply.h
@@ -1,7 +1,7 @@
 #ifndef APPLY_H
 #define APPLY_H
 
-#include "hash.h"
+#include "hash-ll.h"
 #include "lockfile.h"
 #include "string-list.h"
 #include "strmap.h"
diff --git a/archive-tar.c b/archive-tar.c
index f8fad294..4cd81d8 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -1,13 +1,18 @@
 /*
  * Copyright (c) 2005, 2006 Rene Scharfe
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
+#include "gettext.h"
+#include "git-zlib.h"
+#include "hex.h"
 #include "tar.h"
 #include "archive.h"
 #include "object-store.h"
 #include "streaming.h"
 #include "run-command.h"
+#include "write-or-die.h"
 
 #define RECORDSIZE	(512)
 #define BLOCKSIZE	(RECORDSIZE * 20)
diff --git a/archive-zip.c b/archive-zip.c
index 0456f1e..d0d065a 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -1,13 +1,17 @@
 /*
  * Copyright (c) 2006 Rene Scharfe
  */
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "archive.h"
+#include "gettext.h"
+#include "git-zlib.h"
+#include "hex.h"
 #include "streaming.h"
 #include "utf8.h"
 #include "object-store.h"
 #include "userdiff.h"
+#include "write-or-die.h"
 #include "xdiff-interface.h"
 #include "date.h"
 
diff --git a/archive.c b/archive.c
index 9aeaf2b..2ea9cbe 100644
--- a/archive.c
+++ b/archive.c
@@ -1,8 +1,17 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
+#include "convert.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "pretty.h"
+#include "setup.h"
 #include "refs.h"
 #include "object-store.h"
 #include "commit.h"
+#include "tree.h"
 #include "tree-walk.h"
 #include "attr.h"
 #include "archive.h"
@@ -59,7 +68,8 @@ static void format_subst(const struct commit *commit,
 		strbuf_add(&fmt, b + 8, c - b - 8);
 
 		strbuf_add(buf, src, b - src);
-		format_commit_message(commit, fmt.buf, buf, ctx);
+		repo_format_commit_message(the_repository, commit, fmt.buf,
+					   buf, ctx);
 		len -= c + 1 - src;
 		src  = c + 1;
 	}
@@ -84,7 +94,7 @@ static void *object_file_to_archive(const struct archiver_args *args,
 			       (args->tree ? &args->tree->object.oid : NULL), oid);
 
 	path += args->baselen;
-	buffer = read_object_file(oid, type, sizep);
+	buffer = repo_read_object_file(the_repository, oid, type, sizep);
 	if (buffer && S_ISREG(mode)) {
 		struct strbuf buf = STRBUF_INIT;
 		size_t size = 0;
@@ -120,7 +130,7 @@ static const struct attr_check *get_archive_attrs(struct index_state *istate,
 	static struct attr_check *check;
 	if (!check)
 		check = attr_check_initl("export-ignore", "export-subst", NULL);
-	git_check_attr(istate, NULL, path, check);
+	git_check_attr(istate, path, check);
 	return check;
 }
 
@@ -166,6 +176,29 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
 		args->convert = check_attr_export_subst(check);
 	}
 
+	if (args->prefix) {
+		static struct strbuf new_path = STRBUF_INIT;
+		static struct strbuf buf = STRBUF_INIT;
+		const char *rel;
+
+		rel = relative_path(path_without_prefix, args->prefix, &buf);
+
+		/*
+		 * We don't add an entry for the current working
+		 * directory when we are at the root; skip it also when
+		 * we're in a subdirectory or submodule.  Skip entries
+		 * higher up as well.
+		 */
+		if (!strcmp(rel, "./") || starts_with(rel, "../"))
+			return S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0;
+
+		/* rel can refer to path, so don't edit it in place */
+		strbuf_reset(&new_path);
+		strbuf_add(&new_path, args->base, args->baselen);
+		strbuf_addstr(&new_path, rel);
+		strbuf_swap(&path, &new_path);
+	}
+
 	if (args->verbose)
 		fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
 
@@ -401,6 +434,27 @@ static int reject_entry(const struct object_id *oid UNUSED,
 	return ret;
 }
 
+static int reject_outside(const struct object_id *oid UNUSED,
+			  struct strbuf *base, const char *filename,
+			  unsigned mode, void *context)
+{
+	struct archiver_args *args = context;
+	struct strbuf buf = STRBUF_INIT;
+	struct strbuf path = STRBUF_INIT;
+	int ret = 0;
+
+	if (S_ISDIR(mode))
+		return READ_TREE_RECURSIVE;
+
+	strbuf_addbuf(&path, base);
+	strbuf_addstr(&path, filename);
+	if (starts_with(relative_path(path.buf, args->prefix, &buf), "../"))
+		ret = -1;
+	strbuf_release(&buf);
+	strbuf_release(&path);
+	return ret;
+}
+
 static int path_exists(struct archiver_args *args, const char *path)
 {
 	const char *paths[] = { path, NULL };
@@ -408,8 +462,13 @@ static int path_exists(struct archiver_args *args, const char *path)
 	int ret;
 
 	ctx.args = args;
-	parse_pathspec(&ctx.pathspec, 0, 0, "", paths);
+	parse_pathspec(&ctx.pathspec, 0, PATHSPEC_PREFER_CWD,
+		       args->prefix, paths);
 	ctx.pathspec.recursive = 1;
+	if (args->prefix && read_tree(args->repo, args->tree, &ctx.pathspec,
+				      reject_outside, args))
+		die(_("pathspec '%s' matches files outside the "
+		      "current directory"), path);
 	ret = read_tree(args->repo, args->tree,
 			&ctx.pathspec,
 			reject_entry, &ctx);
@@ -425,9 +484,8 @@ static void parse_pathspec_arg(const char **pathspec,
 	 * Also if pathspec patterns are dependent, we're in big
 	 * trouble as we test each one separately
 	 */
-	parse_pathspec(&ar_args->pathspec, 0,
-		       PATHSPEC_PREFER_FULL,
-		       "", pathspec);
+	parse_pathspec(&ar_args->pathspec, 0, PATHSPEC_PREFER_CWD,
+		       ar_args->prefix, pathspec);
 	ar_args->pathspec.recursive = 1;
 	if (pathspec) {
 		while (*pathspec) {
@@ -439,8 +497,7 @@ static void parse_pathspec_arg(const char **pathspec,
 }
 
 static void parse_treeish_arg(const char **argv,
-		struct archiver_args *ar_args, const char *prefix,
-		int remote)
+			      struct archiver_args *ar_args, int remote)
 {
 	const char *name = argv[0];
 	const struct object_id *commit_oid;
@@ -455,13 +512,14 @@ static void parse_treeish_arg(const char **argv,
 		const char *colon = strchrnul(name, ':');
 		int refnamelen = colon - name;
 
-		if (!dwim_ref(name, refnamelen, &oid, &ref, 0))
+		if (!repo_dwim_ref(the_repository, name, refnamelen, &oid, &ref, 0))
 			die(_("no such ref: %.*s"), refnamelen, name);
 	} else {
-		dwim_ref(name, strlen(name), &oid, &ref, 0);
+		repo_dwim_ref(the_repository, name, strlen(name), &oid, &ref,
+			      0);
 	}
 
-	if (get_oid(name, &oid))
+	if (repo_get_oid(the_repository, name, &oid))
 		die(_("not a valid object name: %s"), name);
 
 	commit = lookup_commit_reference_gently(ar_args->repo, &oid, 1);
@@ -479,20 +537,6 @@ static void parse_treeish_arg(const char **argv,
 	if (!tree)
 		die(_("not a tree object: %s"), oid_to_hex(&oid));
 
-	if (prefix) {
-		struct object_id tree_oid;
-		unsigned short mode;
-		int err;
-
-		err = get_tree_entry(ar_args->repo,
-				     &tree->object.oid,
-				     prefix, &tree_oid,
-				     &mode);
-		if (err || !S_ISDIR(mode))
-			die(_("current working directory is untracked"));
-
-		tree = parse_tree_indirect(&tree_oid);
-	}
 	ar_args->refname = ref;
 	ar_args->tree = tree;
 	ar_args->commit_oid = commit_oid;
@@ -710,7 +754,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 		setup_git_directory();
 	}
 
-	parse_treeish_arg(argv, &args, prefix, remote);
+	parse_treeish_arg(argv, &args, remote);
 	parse_pathspec_arg(argv + 1, &args);
 
 	rc = ar->write_archive(ar, &args);
diff --git a/archive.h b/archive.h
index 7178e2a..3a4bdfb 100644
--- a/archive.h
+++ b/archive.h
@@ -1,8 +1,9 @@
 #ifndef ARCHIVE_H
 #define ARCHIVE_H
 
-#include "cache.h"
+#include "object-name.h"
 #include "pathspec.h"
+#include "string-list.h"
 
 struct repository;
 struct pretty_print_context;
diff --git a/attr.c b/attr.c
index 1053dfc..d45d340 100644
--- a/attr.c
+++ b/attr.c
@@ -7,15 +7,21 @@
  */
 
 #include "cache.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
 #include "exec-cmd.h"
 #include "attr.h"
 #include "dir.h"
+#include "gettext.h"
 #include "utf8.h"
 #include "quote.h"
 #include "revision.h"
 #include "object-store.h"
+#include "setup.h"
 #include "thread-utils.h"
+#include "tree-walk.h"
+#include "object-name.h"
 
 const char git_attr__true[] = "(builtin)true";
 const char git_attr__false[] = "\0(builtin)false";
@@ -1165,11 +1171,42 @@ static void collect_some_attrs(struct index_state *istate,
 	fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem);
 }
 
+static const char *default_attr_source_tree_object_name;
+
+void set_git_attr_source(const char *tree_object_name)
+{
+	default_attr_source_tree_object_name = xstrdup(tree_object_name);
+}
+
+static void compute_default_attr_source(struct object_id *attr_source)
+{
+	if (!default_attr_source_tree_object_name)
+		default_attr_source_tree_object_name = getenv(GIT_ATTR_SOURCE_ENVIRONMENT);
+
+	if (!default_attr_source_tree_object_name || !is_null_oid(attr_source))
+		return;
+
+	if (repo_get_oid_treeish(the_repository, default_attr_source_tree_object_name, attr_source))
+		die(_("bad --attr-source or GIT_ATTR_SOURCE"));
+}
+
+static struct object_id *default_attr_source(void)
+{
+	static struct object_id attr_source;
+
+	if (is_null_oid(&attr_source))
+		compute_default_attr_source(&attr_source);
+	if (is_null_oid(&attr_source))
+		return NULL;
+	return &attr_source;
+}
+
 void git_check_attr(struct index_state *istate,
-		    const struct object_id *tree_oid, const char *path,
+		    const char *path,
 		    struct attr_check *check)
 {
 	int i;
+	const struct object_id *tree_oid = default_attr_source();
 
 	collect_some_attrs(istate, tree_oid, path, check);
 
@@ -1182,10 +1219,11 @@ void git_check_attr(struct index_state *istate,
 	}
 }
 
-void git_all_attrs(struct index_state *istate, const struct object_id *tree_oid,
+void git_all_attrs(struct index_state *istate,
 		   const char *path, struct attr_check *check)
 {
 	int i;
+	const struct object_id *tree_oid = default_attr_source();
 
 	attr_check_reset(check);
 	collect_some_attrs(istate, tree_oid, path, check);
diff --git a/attr.h b/attr.h
index 9884ea2..676bd17 100644
--- a/attr.h
+++ b/attr.h
@@ -45,7 +45,7 @@
  * const char *path;
  *
  * setup_check();
- * git_check_attr(&the_index, tree_oid, path, check);
+ * git_check_attr(&the_index, path, check);
  * ------------
  *
  * - Act on `.value` member of the result, left in `check->items[]`:
@@ -120,7 +120,6 @@
 #define ATTR_MAX_FILE_SIZE (100 * 1024 * 1024)
 
 struct index_state;
-struct object_id;
 
 /**
  * An attribute is an opaque object that is identified by its name. Pass the
@@ -136,6 +135,12 @@ struct all_attrs_item;
 struct attr_stack;
 
 /*
+ * The textual object name for the tree-ish used by git_check_attr()
+ * to read attributes from (instead of from the working tree).
+ */
+void set_git_attr_source(const char *);
+
+/*
  * Given a string, return the gitattribute object that
  * corresponds to it.
  */
@@ -203,14 +208,14 @@ void attr_check_free(struct attr_check *check);
 const char *git_attr_name(const struct git_attr *);
 
 void git_check_attr(struct index_state *istate,
-		    const struct object_id *tree_oid, const char *path,
+		    const char *path,
 		    struct attr_check *check);
 
 /*
  * Retrieve all attributes that apply to the specified path.
  * check holds the attributes and their values.
  */
-void git_all_attrs(struct index_state *istate, const struct object_id *tree_oid,
+void git_all_attrs(struct index_state *istate,
 		   const char *path, struct attr_check *check);
 
 enum git_attr_direction {
diff --git a/banned.h b/banned.h
index 6ccf46b..44e76bd 100644
--- a/banned.h
+++ b/banned.h
@@ -18,6 +18,10 @@
 #define strncpy(x,y,n) BANNED(strncpy)
 #undef strncat
 #define strncat(x,y,n) BANNED(strncat)
+#undef strtok
+#define strtok(x,y) BANNED(strtok)
+#undef strtok_r
+#define strtok_r(x,y,z) BANNED(strtok_r)
 
 #undef sprintf
 #undef vsprintf
diff --git a/base85.c b/base85.c
index 5ca601e..bbacdca 100644
--- a/base85.c
+++ b/base85.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "base85.h"
 
 #undef DEBUG_85
 
diff --git a/base85.h b/base85.h
new file mode 100644
index 0000000..c835086
--- /dev/null
+++ b/base85.h
@@ -0,0 +1,7 @@
+#ifndef BASE85_H
+#define BASE85_H
+
+int decode_85(char *dst, const char *line, int linelen);
+void encode_85(char *buf, const unsigned char *data, int bytes);
+
+#endif /* BASE85_H */
diff --git a/bisect.c b/bisect.c
index ef5ee5a..8d5f8e5 100644
--- a/bisect.c
+++ b/bisect.c
@@ -1,7 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "commit.h"
 #include "diff.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "revision.h"
 #include "refs.h"
 #include "list-objects.h"
@@ -14,6 +17,7 @@
 #include "strvec.h"
 #include "commit-slab.h"
 #include "commit-reach.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "dir.h"
 
@@ -148,8 +152,9 @@ static void show_list(const char *debug, int counted, int nr,
 		unsigned commit_flags = commit->object.flags;
 		enum object_type type;
 		unsigned long size;
-		char *buf = read_object_file(&commit->object.oid, &type,
-					     &size);
+		char *buf = repo_read_object_file(the_repository,
+						  &commit->object.oid, &type,
+						  &size);
 		const char *subject_start;
 		int subject_len;
 
@@ -751,7 +756,8 @@ enum bisect_error bisect_checkout(const struct object_id *bisect_rev,
 	}
 
 	commit = lookup_commit_reference(the_repository, bisect_rev);
-	format_commit_message(commit, "[%H] %s%n", &commit_msg, &pp);
+	repo_format_commit_message(the_repository, commit, "[%H] %s%n",
+				   &commit_msg, &pp);
 	fputs(commit_msg.buf, stdout);
 	strbuf_release(&commit_msg);
 
@@ -846,7 +852,8 @@ static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int
 	enum bisect_error res = BISECT_OK;
 	struct commit_list *result;
 
-	result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1);
+	result = repo_get_merge_bases_many(the_repository, rev[0], rev_nr - 1,
+					   rev + 1);
 
 	for (; result; result = result->next) {
 		const struct object_id *mb = &result->item->object.oid;
diff --git a/blame.c b/blame.c
index 8bfeaa1..b830654 100644
--- a/blame.c
+++ b/blame.c
@@ -3,9 +3,14 @@
 #include "object-store.h"
 #include "cache-tree.h"
 #include "mergesort.h"
+#include "convert.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "gettext.h"
+#include "hex.h"
+#include "setup.h"
 #include "tag.h"
+#include "trace2.h"
 #include "blame.h"
 #include "alloc.h"
 #include "commit-slab.h"
@@ -176,12 +181,12 @@ static void set_commit_buffer_from_strbuf(struct repository *r,
 static struct commit *fake_working_tree_commit(struct repository *r,
 					       struct diff_options *opt,
 					       const char *path,
-					       const char *contents_from)
+					       const char *contents_from,
+					       struct object_id *oid)
 {
 	struct commit *commit;
 	struct blame_origin *origin;
 	struct commit_list **parent_tail, *parent;
-	struct object_id head_oid;
 	struct strbuf buf = STRBUF_INIT;
 	const char *ident;
 	time_t now;
@@ -197,17 +202,18 @@ static struct commit *fake_working_tree_commit(struct repository *r,
 	commit->date = now;
 	parent_tail = &commit->parents;
 
-	if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
-		die("no such ref: HEAD");
-
-	parent_tail = append_parent(r, parent_tail, &head_oid);
+	parent_tail = append_parent(r, parent_tail, oid);
 	append_merge_parents(r, parent_tail);
 	verify_working_tree_path(r, commit, path);
 
 	origin = make_origin(commit, path);
 
-	ident = fmt_ident("Not Committed Yet", "not.committed.yet",
-			WANT_BLANK_IDENT, NULL, 0);
+	if (contents_from)
+		ident = fmt_ident("External file (--contents)", "external.file",
+				  WANT_BLANK_IDENT, NULL, 0);
+	else
+		ident = fmt_ident("Not Committed Yet", "not.committed.yet",
+				  WANT_BLANK_IDENT, NULL, 0);
 	strbuf_addstr(&msg, "tree 0000000000000000000000000000000000000000\n");
 	for (parent = commit->parents; parent; parent = parent->next)
 		strbuf_addf(&msg, "parent %s\n",
@@ -1028,8 +1034,9 @@ static void fill_origin_blob(struct diff_options *opt,
 				    &o->blob_oid, 1, &file->ptr, &file_size))
 			;
 		else
-			file->ptr = read_object_file(&o->blob_oid, &type,
-						     &file_size);
+			file->ptr = repo_read_object_file(the_repository,
+							  &o->blob_oid, &type,
+							  &file_size);
 		file->size = file_size;
 
 		if (!file->ptr)
@@ -2429,7 +2436,7 @@ static void pass_blame(struct blame_scoreboard *sb, struct blame_origin *origin,
 
 			if (sg_origin[i])
 				continue;
-			if (parse_commit(p))
+			if (repo_parse_commit(the_repository, p))
 				continue;
 			porigin = find(sb->repo, p, origin, sb->bloom_data);
 			if (!porigin)
@@ -2592,7 +2599,7 @@ void assign_blame(struct blame_scoreboard *sb, int opt)
 		 * so hold onto it in the meantime.
 		 */
 		blame_origin_incref(suspect);
-		parse_commit(commit);
+		repo_parse_commit(the_repository, commit);
 		if (sb->reverse ||
 		    (!(commit->object.flags & UNINTERESTING) &&
 		     !(revs->max_age != -1 && commit->date < revs->max_age)))
@@ -2771,22 +2778,37 @@ void setup_scoreboard(struct blame_scoreboard *sb,
 		sb->commits.compare = compare_commits_by_reverse_commit_date;
 	}
 
-	if (sb->final && sb->contents_from)
-		die(_("cannot use --contents with final commit object name"));
-
 	if (sb->reverse && sb->revs->first_parent_only)
 		sb->revs->children.name = NULL;
 
-	if (!sb->final) {
+	if (sb->contents_from || !sb->final) {
+		struct object_id head_oid, *parent_oid;
+
 		/*
-		 * "--not A B -- path" without anything positive;
-		 * do not default to HEAD, but use the working tree
-		 * or "--contents".
+		 * Build a fake commit at the top of the history, when
+		 * (1) "git blame [^A] --path", i.e. with no positive end
+		 *     of the history range, in which case we build such
+		 *     a fake commit on top of the HEAD to blame in-tree
+		 *     modifications.
+		 * (2) "git blame --contents=file [A] -- path", with or
+		 *     without positive end of the history range but with
+		 *     --contents, in which case we pretend that there is
+		 *     a fake commit on top of the positive end (defaulting to
+		 *     HEAD) that has the given contents in the path.
 		 */
+		if (sb->final) {
+			parent_oid = &sb->final->object.oid;
+		} else {
+			if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
+				die("no such ref: HEAD");
+			parent_oid = &head_oid;
+		}
+
 		setup_work_tree();
 		sb->final = fake_working_tree_commit(sb->repo,
 						     &sb->revs->diffopt,
-						     sb->path, sb->contents_from);
+						     sb->path, sb->contents_from,
+						     parent_oid);
 		add_pending_object(sb->revs, &(sb->final->object), ":");
 	}
 
@@ -2838,8 +2860,10 @@ void setup_scoreboard(struct blame_scoreboard *sb,
 				    &sb->final_buf_size))
 			;
 		else
-			sb->final_buf = read_object_file(&o->blob_oid, &type,
-							 &sb->final_buf_size);
+			sb->final_buf = repo_read_object_file(the_repository,
+							      &o->blob_oid,
+							      &type,
+							      &sb->final_buf_size);
 
 		if (!sb->final_buf)
 			die(_("cannot read blob %s for path %s"),
diff --git a/blame.h b/blame.h
index 38bde53..b60d1d8 100644
--- a/blame.h
+++ b/blame.h
@@ -1,7 +1,6 @@
 #ifndef BLAME_H
 #define BLAME_H
 
-#include "cache.h"
 #include "commit.h"
 #include "xdiff-interface.h"
 #include "revision.h"
diff --git a/blob.c b/blob.c
index 8f83523..888e28a 100644
--- a/blob.c
+++ b/blob.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "blob.h"
 #include "repository.h"
 #include "alloc.h"
diff --git a/bloom.c b/bloom.c
index d073052..aef6b5f 100644
--- a/bloom.c
+++ b/bloom.c
@@ -6,6 +6,7 @@
 #include "hashmap.h"
 #include "commit-graph.h"
 #include "commit.h"
+#include "commit-slab.h"
 
 define_commit_slab(bloom_filter_slab, struct bloom_filter);
 
diff --git a/branch.c b/branch.c
index e5614b5..ba3914a 100644
--- a/branch.c
+++ b/branch.c
@@ -1,10 +1,15 @@
 #include "git-compat-util.h"
-#include "cache.h"
+#include "advice.h"
 #include "config.h"
 #include "branch.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "refs.h"
 #include "refspec.h"
 #include "remote.h"
+#include "repository.h"
 #include "sequencer.h"
 #include "commit.h"
 #include "worktree.h"
@@ -531,7 +536,7 @@ static void dwim_branch_start(struct repository *r, const char *start_name,
 		explicit_tracking = 1;
 
 	real_ref = NULL;
-	if (get_oid_mb(start_name, &oid)) {
+	if (repo_get_oid_mb(r, start_name, &oid)) {
 		if (explicit_tracking) {
 			int code = die_message(_(upstream_missing), start_name);
 			advise_if_enabled(ADVICE_SET_UPSTREAM_FAILURE,
@@ -541,7 +546,8 @@ static void dwim_branch_start(struct repository *r, const char *start_name,
 		die(_("not a valid object name: '%s'"), start_name);
 	}
 
-	switch (dwim_ref(start_name, strlen(start_name), &oid, &real_ref, 0)) {
+	switch (repo_dwim_ref(r, start_name, strlen(start_name), &oid,
+			      &real_ref, 0)) {
 	case 0:
 		/* Not branching from any existing branch */
 		if (explicit_tracking)
@@ -772,7 +778,7 @@ void create_branches_recursively(struct repository *r, const char *name,
 			    name);
 	}
 
-	create_branch(the_repository, name, start_commitish, force, 0, reflog, quiet,
+	create_branch(r, name, start_commitish, force, 0, reflog, quiet,
 		      BRANCH_TRACK_NEVER, dry_run);
 	if (dry_run)
 		return;
@@ -820,40 +826,17 @@ void remove_branch_state(struct repository *r, int verbose)
 void die_if_checked_out(const char *branch, int ignore_current_worktree)
 {
 	struct worktree **worktrees = get_worktrees();
-	const struct worktree *wt;
 
-	wt = find_shared_symref(worktrees, "HEAD", branch);
-	if (wt && (!ignore_current_worktree || !wt->is_current)) {
-		skip_prefix(branch, "refs/heads/", &branch);
-		die(_("'%s' is already checked out at '%s'"), branch, wt->path);
+	for (int i = 0; worktrees[i]; i++) {
+		if (worktrees[i]->is_current && ignore_current_worktree)
+			continue;
+
+		if (is_shared_symref(worktrees[i], "HEAD", branch)) {
+			skip_prefix(branch, "refs/heads/", &branch);
+			die(_("'%s' is already checked out at '%s'"),
+				branch, worktrees[i]->path);
+		}
 	}
 
 	free_worktrees(worktrees);
 }
-
-int replace_each_worktree_head_symref(const char *oldref, const char *newref,
-				      const char *logmsg)
-{
-	int ret = 0;
-	struct worktree **worktrees = get_worktrees();
-	int i;
-
-	for (i = 0; worktrees[i]; i++) {
-		struct ref_store *refs;
-
-		if (worktrees[i]->is_detached)
-			continue;
-		if (!worktrees[i]->head_ref)
-			continue;
-		if (strcmp(oldref, worktrees[i]->head_ref))
-			continue;
-
-		refs = get_worktree_ref_store(worktrees[i]);
-		if (refs_create_symref(refs, "HEAD", newref, logmsg))
-			ret = error(_("HEAD of working tree %s is not updated"),
-				    worktrees[i]->path);
-	}
-
-	free_worktrees(worktrees);
-	return ret;
-}
diff --git a/branch.h b/branch.h
index ef56103..30c01ae 100644
--- a/branch.h
+++ b/branch.h
@@ -155,12 +155,4 @@ int read_branch_desc(struct strbuf *, const char *branch_name);
  */
 void die_if_checked_out(const char *branch, int ignore_current_worktree);
 
-/*
- * Update all per-worktree HEADs pointing at the old ref to point the new ref.
- * This will be used when renaming a branch. Returns 0 if successful, non-zero
- * otherwise.
- */
-int replace_each_worktree_head_symref(const char *oldref, const char *newref,
-				      const char *logmsg);
-
 #endif
diff --git a/builtin.h b/builtin.h
index 46cc789..cb0db67 100644
--- a/builtin.h
+++ b/builtin.h
@@ -107,6 +107,16 @@ void setup_auto_pager(const char *cmd, int def);
 
 int is_builtin(const char *s);
 
+/*
+ * Builtins which do not use RUN_SETUP should never see
+ * a prefix that is not empty; use this to protect downstream
+ * code which is not prepared to call prefix_filename(), etc.
+ */
+#define BUG_ON_NON_EMPTY_PREFIX(prefix) do { \
+	if ((prefix)) \
+		BUG("unexpected prefix in builtin: %s", (prefix)); \
+} while (0)
+
 int cmd_add(int argc, const char **argv, const char *prefix);
 int cmd_am(int argc, const char **argv, const char *prefix);
 int cmd_annotate(int argc, const char **argv, const char *prefix);
diff --git a/builtin/add.c b/builtin/add.c
index 61dd386..76cc026 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -5,10 +5,13 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
+#include "advice.h"
 #include "config.h"
 #include "builtin.h"
 #include "lockfile.h"
+#include "editor.h"
 #include "dir.h"
+#include "gettext.h"
 #include "pathspec.h"
 #include "exec-cmd.h"
 #include "cache-tree.h"
diff --git a/builtin/am.c b/builtin/am.c
index e0848dd..5c83f2e 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -5,9 +5,15 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
+#include "abspath.h"
+#include "advice.h"
 #include "config.h"
 #include "builtin.h"
+#include "editor.h"
+#include "environment.h"
 #include "exec-cmd.h"
+#include "gettext.h"
+#include "hex.h"
 #include "parse-options.h"
 #include "dir.h"
 #include "run-command.h"
@@ -22,6 +28,7 @@
 #include "diffcore.h"
 #include "unpack-trees.h"
 #include "branch.h"
+#include "object-name.h"
 #include "sequencer.h"
 #include "revision.h"
 #include "merge-recursive.h"
@@ -33,8 +40,10 @@
 #include "apply.h"
 #include "string-list.h"
 #include "packfile.h"
+#include "pager.h"
 #include "repository.h"
 #include "pretty.h"
+#include "wrapper.h"
 
 /**
  * Returns the length of the first line of msg.
@@ -1066,7 +1075,7 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
 	else
 		write_state_text(state, "applying", "");
 
-	if (!get_oid("HEAD", &curr_head)) {
+	if (!repo_get_oid(the_repository, "HEAD", &curr_head)) {
 		write_state_text(state, "abort-safety", oid_to_hex(&curr_head));
 		if (!state->rebasing)
 			update_ref("am", "ORIG_HEAD", &curr_head, NULL, 0,
@@ -1109,7 +1118,7 @@ static void am_next(struct am_state *state)
 	unlink(am_path(state, "original-commit"));
 	delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
 
-	if (!get_oid("HEAD", &head))
+	if (!repo_get_oid(the_repository, "HEAD", &head))
 		write_state_text(state, "abort-safety", oid_to_hex(&head));
 	else
 		write_state_text(state, "abort-safety", "");
@@ -1329,7 +1338,8 @@ static void get_commit_info(struct am_state *state, struct commit *commit)
 	size_t ident_len;
 	struct ident_split id;
 
-	buffer = logmsg_reencode(commit, NULL, get_commit_output_encoding());
+	buffer = repo_logmsg_reencode(the_repository, commit, NULL,
+				      get_commit_output_encoding());
 
 	ident_line = find_commit_header(buffer, "author", &ident_len);
 	if (!ident_line)
@@ -1361,7 +1371,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit)
 		die(_("unable to parse commit %s"), oid_to_hex(&commit->object.oid));
 	state->msg = xstrdup(msg + 2);
 	state->msg_len = strlen(state->msg);
-	unuse_commit_buffer(commit, buffer);
+	repo_unuse_commit_buffer(the_repository, commit, buffer);
 }
 
 /**
@@ -1402,9 +1412,9 @@ static void write_index_patch(const struct am_state *state)
 	struct rev_info rev_info;
 	FILE *fp;
 
-	if (!get_oid("HEAD", &head)) {
+	if (!repo_get_oid(the_repository, "HEAD", &head)) {
 		struct commit *commit = lookup_commit_or_die(&head, "HEAD");
-		tree = get_commit_tree(commit);
+		tree = repo_get_commit_tree(the_repository, commit);
 	} else
 		tree = lookup_tree(the_repository,
 				   the_repository->hash_algo->empty_tree);
@@ -1556,7 +1566,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
 	struct commit *result;
 	char *their_tree_name;
 
-	if (get_oid("HEAD", &our_tree) < 0)
+	if (repo_get_oid(the_repository, "HEAD", &our_tree) < 0)
 		oidcpy(&our_tree, the_hash_algo->empty_tree);
 
 	if (build_fake_ancestor(state, index_path))
@@ -1646,7 +1656,7 @@ static void do_commit(const struct am_state *state)
 	if (write_index_as_tree(&tree, &the_index, get_index_file(), 0, NULL))
 		die(_("git write-tree failed to write a tree"));
 
-	if (!get_oid_commit("HEAD", &parent)) {
+	if (!repo_get_oid_commit(the_repository, "HEAD", &parent)) {
 		old_oid = &parent;
 		commit_list_insert(lookup_commit(the_repository, &parent),
 				   &parents);
@@ -2088,7 +2098,7 @@ static void am_skip(struct am_state *state)
 
 	am_rerere_clear();
 
-	if (get_oid("HEAD", &head))
+	if (repo_get_oid(the_repository, "HEAD", &head))
 		oidcpy(&head, the_hash_algo->empty_tree);
 
 	if (clean_index(&head, &head))
@@ -2130,7 +2140,7 @@ static int safe_to_abort(const struct am_state *state)
 		oidclr(&abort_safety);
 	strbuf_release(&sb);
 
-	if (get_oid("HEAD", &head))
+	if (repo_get_oid(the_repository, "HEAD", &head))
 		oidclr(&head);
 
 	if (oideq(&head, &abort_safety))
@@ -2163,7 +2173,7 @@ static void am_abort(struct am_state *state)
 	if (!has_curr_head)
 		oidcpy(&curr_head, the_hash_algo->empty_tree);
 
-	has_orig_head = !get_oid("ORIG_HEAD", &orig_head);
+	has_orig_head = !repo_get_oid(the_repository, "ORIG_HEAD", &orig_head);
 	if (!has_orig_head)
 		oidcpy(&orig_head, the_hash_algo->empty_tree);
 
@@ -2300,17 +2310,6 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 	return 0;
 }
 
-static int git_am_config(const char *k, const char *v, void *cb UNUSED)
-{
-	int status;
-
-	status = git_gpg_config(k, v, NULL);
-	if (status)
-		return status;
-
-	return git_default_config(k, v, NULL);
-}
-
 int cmd_am(int argc, const char **argv, const char *prefix)
 {
 	struct am_state state;
@@ -2434,7 +2433,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(usage, options);
 
-	git_config(git_am_config, NULL);
+	git_config(git_default_config, NULL);
 
 	am_state_init(&state);
 
diff --git a/builtin/apply.c b/builtin/apply.c
index 555219d..e3ff02a 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -1,6 +1,8 @@
 #include "cache.h"
 #include "builtin.h"
+#include "gettext.h"
 #include "parse-options.h"
+#include "repository.h"
 #include "apply.h"
 
 static const char * const apply_usage[] = {
diff --git a/builtin/archive.c b/builtin/archive.c
index f094390..b0eaa3c 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -5,9 +5,11 @@
 #include "cache.h"
 #include "builtin.h"
 #include "archive.h"
+#include "gettext.h"
 #include "transport.h"
 #include "parse-options.h"
 #include "pkt-line.h"
+#include "repository.h"
 #include "sideband.h"
 
 static void create_output_file(const char *output_file)
@@ -81,7 +83,7 @@ static int run_remote_archiver(int argc, const char **argv,
 int cmd_archive(int argc, const char **argv, const char *prefix)
 {
 	const char *exec = "git-upload-archive";
-	const char *output = NULL;
+	char *output = NULL;
 	const char *remote = NULL;
 	struct option local_opts[] = {
 		OPT_FILENAME('o', "output", &output,
@@ -106,5 +108,6 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
 
 	setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
 
+	UNLEAK(output);
 	return write_archive(argc, argv, prefix, the_repository, output, 0);
 }
diff --git a/builtin/bisect.c b/builtin/bisect.c
index 7301740..4812450 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -1,14 +1,21 @@
 #include "builtin.h"
 #include "cache.h"
+#include "copy.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "bisect.h"
 #include "refs.h"
 #include "dir.h"
 #include "strvec.h"
 #include "run-command.h"
+#include "oid-array.h"
 #include "prompt.h"
 #include "quote.h"
 #include "revision.h"
+#include "wrapper.h"
 
 static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS")
 static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
@@ -235,7 +242,7 @@ static int bisect_reset(const char *commit)
 	} else {
 		struct object_id oid;
 
-		if (get_oid_commit(commit, &oid))
+		if (repo_get_oid_commit(the_repository, commit, &oid))
 			return error(_("'%s' is not a valid commit"), commit);
 		strbuf_addstr(&branch, commit);
 	}
@@ -244,7 +251,8 @@ static int bisect_reset(const char *commit)
 		struct child_process cmd = CHILD_PROCESS_INIT;
 
 		cmd.git_cmd = 1;
-		strvec_pushl(&cmd.args, "checkout", branch.buf, "--", NULL);
+		strvec_pushl(&cmd.args, "checkout", "--ignore-other-worktrees",
+				branch.buf, "--", NULL);
 		if (run_command(&cmd)) {
 			error(_("could not check out original"
 				" HEAD '%s'. Try 'git bisect"
@@ -265,7 +273,8 @@ static void log_commit(FILE *fp, char *fmt, const char *state,
 	struct strbuf commit_msg = STRBUF_INIT;
 	char *label = xstrfmt(fmt, state);
 
-	format_commit_message(commit, "%s", &commit_msg, &pp);
+	repo_format_commit_message(the_repository, commit, "%s", &commit_msg,
+				   &pp);
 
 	fprintf(fp, "# %s: [%s] %s\n", label, oid_to_hex(&commit->object.oid),
 		commit_msg.buf);
@@ -292,7 +301,7 @@ static int bisect_write(const char *state, const char *rev,
 		goto finish;
 	}
 
-	if (get_oid(rev, &oid)) {
+	if (repo_get_oid(the_repository, rev, &oid)) {
 		res = error(_("couldn't get the oid of the rev '%s'"), rev);
 		goto finish;
 	}
@@ -567,7 +576,7 @@ static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
 	 * sets up a revision walk.
 	 */
 	reset_revision_walk();
-	init_revisions(revs, NULL);
+	repo_init_revisions(the_repository, revs, NULL);
 	setup_revisions(0, NULL, revs, NULL);
 	for_each_glob_ref_in(add_bisect_ref, bad, "refs/bisect/", &cb);
 	cb.object_flags = UNINTERESTING;
@@ -603,8 +612,8 @@ static int bisect_skipped_commits(struct bisect_terms *terms)
 
 	while ((commit = get_revision(&revs)) != NULL) {
 		strbuf_reset(&commit_name);
-		format_commit_message(commit, "%s",
-				      &commit_name, &pp);
+		repo_format_commit_message(the_repository, commit, "%s",
+					   &commit_name, &pp);
 		fprintf(fp, "# possible first %s commit: [%s] %s\n",
 			terms->term_bad, oid_to_hex(&commit->object.oid),
 			commit_name.buf);
@@ -633,7 +642,8 @@ static int bisect_successful(struct bisect_terms *terms)
 
 	read_ref(bad_ref, &oid);
 	commit = lookup_commit_reference_by_name(bad_ref);
-	format_commit_message(commit, "%s", &commit_name, &pp);
+	repo_format_commit_message(the_repository, commit, "%s", &commit_name,
+				   &pp);
 
 	res = append_to_file(git_path_bisect_log(), "# first %s commit: [%s] %s\n",
 			    terms->term_bad, oid_to_hex(&commit->object.oid),
@@ -775,7 +785,7 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
 	 */
 	head = resolve_ref_unsafe("HEAD", 0, &head_oid, &flags);
 	if (!head)
-		if (get_oid("HEAD", &head_oid))
+		if (repo_get_oid(the_repository, "HEAD", &head_oid))
 			return error(_("bad HEAD - I need a HEAD"));
 
 	/*
@@ -801,11 +811,11 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
 		}
 	} else {
 		/* Get the rev from where we start. */
-		if (!get_oid(head, &head_oid) &&
+		if (!repo_get_oid(the_repository, head, &head_oid) &&
 		    !starts_with(head, "refs/heads/")) {
 			strbuf_reset(&start_head);
 			strbuf_addstr(&start_head, oid_to_hex(&head_oid));
-		} else if (!get_oid(head, &head_oid) &&
+		} else if (!repo_get_oid(the_repository, head, &head_oid) &&
 			   skip_prefix(head, "refs/heads/", &head)) {
 			strbuf_addstr(&start_head, head);
 		} else {
@@ -828,7 +838,7 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
 		write_file(git_path_bisect_first_parent(), "\n");
 
 	if (no_checkout) {
-		if (get_oid(start_head.buf, &oid) < 0) {
+		if (repo_get_oid(the_repository, start_head.buf, &oid) < 0) {
 			res = error(_("invalid ref: '%s'"), start_head.buf);
 			goto finish;
 		}
@@ -933,11 +943,12 @@ static enum bisect_error bisect_state(struct bisect_terms *terms, int argc,
 
 	if (argc == 0) {
 		const char *head = "BISECT_HEAD";
-		enum get_oid_result res_head = get_oid(head, &oid);
+		enum get_oid_result res_head = repo_get_oid(the_repository,
+							    head, &oid);
 
 		if (res_head == MISSING_OBJECT) {
 			head = "HEAD";
-			res_head = get_oid(head, &oid);
+			res_head = repo_get_oid(the_repository, head, &oid);
 		}
 
 		if (res_head)
@@ -953,7 +964,7 @@ static enum bisect_error bisect_state(struct bisect_terms *terms, int argc,
 	for (; argc; argc--, argv++) {
 		struct commit *commit;
 
-		if (get_oid(*argv, &oid)){
+		if (repo_get_oid(the_repository, *argv, &oid)){
 			error(_("Bad rev input: %s"), *argv);
 			oid_array_clear(&revs);
 			return BISECT_FAILED;
@@ -1092,7 +1103,7 @@ static enum bisect_error bisect_skip(struct bisect_terms *terms, int argc,
 			struct rev_info revs;
 			struct commit *commit;
 
-			init_revisions(&revs, NULL);
+			repo_init_revisions(the_repository, &revs, NULL);
 			setup_revisions(2, argv + i - 1, &revs, NULL);
 
 			if (prepare_revision_walk(&revs))
diff --git a/builtin/blame.c b/builtin/blame.c
index 71f925e..2df6039 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -5,10 +5,14 @@
  * See COPYING for licensing conditions
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
 #include "color.h"
 #include "builtin.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "commit.h"
 #include "diff.h"
@@ -24,10 +28,14 @@
 #include "line-log.h"
 #include "dir.h"
 #include "progress.h"
+#include "object-name.h"
 #include "object-store.h"
+#include "pager.h"
 #include "blame.h"
 #include "refs.h"
+#include "setup.h"
 #include "tag.h"
+#include "write-or-die.h"
 
 static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>");
 static char annotate_usage[] = N_("git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>");
@@ -199,13 +207,13 @@ static void get_commit_info(struct commit *commit,
 	const char *message;
 
 	encoding = get_log_output_encoding();
-	message = logmsg_reencode(commit, NULL, encoding);
+	message = repo_logmsg_reencode(the_repository, commit, NULL, encoding);
 	get_ac_line(message, "\nauthor ",
 		    &ret->author, &ret->author_mail,
 		    &ret->author_time, &ret->author_tz);
 
 	if (!detailed) {
-		unuse_commit_buffer(commit, message);
+		repo_unuse_commit_buffer(the_repository, commit, message);
 		return;
 	}
 
@@ -219,7 +227,7 @@ static void get_commit_info(struct commit *commit,
 	else
 		strbuf_addf(&ret->summary, "(%s)", oid_to_hex(&commit->object.oid));
 
-	unuse_commit_buffer(commit, message);
+	repo_unuse_commit_buffer(the_repository, commit, message);
 }
 
 /*
@@ -601,8 +609,9 @@ static int read_ancestry(const char *graft_file)
 
 static int update_auto_abbrev(int auto_abbrev, struct blame_origin *suspect)
 {
-	const char *uniq = find_unique_abbrev(&suspect->commit->object.oid,
-					      auto_abbrev);
+	const char *uniq = repo_find_unique_abbrev(the_repository,
+						   &suspect->commit->object.oid,
+						   auto_abbrev);
 	int len = strlen(uniq);
 	if (auto_abbrev < len)
 		return len;
@@ -802,7 +811,7 @@ static int is_a_rev(const char *name)
 {
 	struct object_id oid;
 
-	if (get_oid(name, &oid))
+	if (repo_get_oid(the_repository, name, &oid))
 		return 0;
 	return OBJ_NONE < oid_object_info(the_repository, &oid, NULL);
 }
@@ -845,7 +854,7 @@ static void build_ignorelist(struct blame_scoreboard *sb,
 						    peel_to_commit_oid, sb);
 	}
 	for_each_string_list_item(i, ignore_rev_list) {
-		if (get_oid_committish(i->string, &oid) ||
+		if (repo_get_oid_committish(the_repository, i->string, &oid) ||
 		    peel_to_commit_oid(&oid, sb))
 			die(_("cannot find revision %s to ignore"), i->string);
 		oidset_insert(&sb->ignore_list, &oid);
diff --git a/builtin/branch.c b/builtin/branch.c
index f63fd45..e6c2655 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -8,9 +8,13 @@
 #include "cache.h"
 #include "config.h"
 #include "color.h"
+#include "editor.h"
+#include "environment.h"
 #include "refs.h"
 #include "commit.h"
 #include "builtin.h"
+#include "gettext.h"
+#include "object-name.h"
 #include "remote.h"
 #include "parse-options.h"
 #include "branch.h"
@@ -24,6 +28,7 @@
 #include "worktree.h"
 #include "help.h"
 #include "commit-reach.h"
+#include "wrapper.h"
 
 static const char * const builtin_branch_usage[] = {
 	N_("git branch [<options>] [-r | -a] [--merged] [--no-merged]"),
@@ -41,6 +46,7 @@ static const char *head;
 static struct object_id head_oid;
 static int recurse_submodules = 0;
 static int submodule_propagate_branches = 0;
+static int omit_empty = 0;
 
 static int branch_use_color = -1;
 static char branch_colors[][COLOR_MAXLEN] = {
@@ -150,17 +156,18 @@ static int branch_merged(int kind, const char *name,
 	if (!reference_rev)
 		reference_rev = head_rev;
 
-	merged = reference_rev ? in_merge_bases(rev, reference_rev) : 0;
+	merged = reference_rev ? repo_in_merge_bases(the_repository, rev,
+						     reference_rev) : 0;
 
 	/*
 	 * After the safety valve is fully redefined to "check with
 	 * upstream, if any, otherwise with HEAD", we should just
-	 * return the result of the in_merge_bases() above without
+	 * return the result of the repo_in_merge_bases() above without
 	 * any of the following code, but during the transition period,
 	 * a gentle reminder is in order.
 	 */
 	if ((head_rev != reference_rev) &&
-	    (head_rev ? in_merge_bases(rev, head_rev) : 0) != merged) {
+	    (head_rev ? repo_in_merge_bases(the_repository, rev, head_rev) : 0) != merged) {
 		if (merged)
 			warning(_("deleting branch '%s' that has been merged to\n"
 				"         '%s', but not yet merged to HEAD."),
@@ -216,10 +223,11 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 	struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
 	struct string_list_item *item;
 	int branch_name_pos;
+	const char *fmt_remotes = "refs/remotes/%s";
 
 	switch (kinds) {
 	case FILTER_REFS_REMOTES:
-		fmt = "refs/remotes/%s";
+		fmt = fmt_remotes;
 		/* For subsequent UI messages */
 		remote_branch = 1;
 		allowed_interpret = INTERPRET_BRANCH_REMOTE;
@@ -263,9 +271,25 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 					| RESOLVE_REF_ALLOW_BAD_NAME,
 					&oid, &flags);
 		if (!target) {
-			error(remote_branch
-			      ? _("remote-tracking branch '%s' not found.")
-			      : _("branch '%s' not found."), bname.buf);
+			if (remote_branch) {
+				error(_("remote-tracking branch '%s' not found."), bname.buf);
+			} else {
+				char *virtual_name = mkpathdup(fmt_remotes, bname.buf);
+				char *virtual_target = resolve_refdup(virtual_name,
+							RESOLVE_REF_READING
+							| RESOLVE_REF_NO_RECURSE
+							| RESOLVE_REF_ALLOW_BAD_NAME,
+							&oid, &flags);
+				FREE_AND_NULL(virtual_name);
+
+				if (virtual_target)
+					error(_("branch '%s' not found.\n"
+						"Did you forget --remote?"),
+						bname.buf);
+				else
+					error(_("branch '%s' not found."), bname.buf);
+				FREE_AND_NULL(virtual_target);
+			}
 			ret = 1;
 			continue;
 		}
@@ -280,7 +304,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 		item = string_list_append(&refs_to_delete, name);
 		item->util = xstrdup((flags & REF_ISBROKEN) ? "broken"
 				    : (flags & REF_ISSYMREF) ? target
-				    : find_unique_abbrev(&oid, DEFAULT_ABBREV));
+				    : repo_find_unique_abbrev(the_repository, &oid, DEFAULT_ABBREV));
 
 	next:
 		free(target);
@@ -448,6 +472,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
 	if (verify_ref_format(format))
 		die(_("unable to parse format string"));
 
+	filter_ahead_behind(the_repository, format, &array);
 	ref_array_sort(sorting, &array);
 
 	for (i = 0; i < array.nr; i++) {
@@ -461,7 +486,8 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
 			string_list_append(output, out.buf);
 		} else {
 			fwrite(out.buf, 1, out.len, stdout);
-			putchar('\n');
+			if (out.len || !omit_empty)
+				putchar('\n');
 		}
 	}
 
@@ -486,9 +512,9 @@ static void print_current_branch_name(void)
 		die(_("HEAD (%s) points outside of refs/heads/"), refname);
 }
 
-static void reject_rebase_or_bisect_branch(const char *target)
+static void reject_rebase_or_bisect_branch(struct worktree **worktrees,
+					   const char *target)
 {
-	struct worktree **worktrees = get_worktrees();
 	int i;
 
 	for (i = 0; worktrees[i]; i++) {
@@ -505,17 +531,50 @@ static void reject_rebase_or_bisect_branch(const char *target)
 			die(_("Branch %s is being bisected at %s"),
 			    target, wt->path);
 	}
-
-	free_worktrees(worktrees);
 }
 
+/*
+ * Update all per-worktree HEADs pointing at the old ref to point the new ref.
+ * This will be used when renaming a branch. Returns 0 if successful, non-zero
+ * otherwise.
+ */
+static int replace_each_worktree_head_symref(struct worktree **worktrees,
+					     const char *oldref, const char *newref,
+					     const char *logmsg)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; worktrees[i]; i++) {
+		struct ref_store *refs;
+
+		if (worktrees[i]->is_detached)
+			continue;
+		if (!worktrees[i]->head_ref)
+			continue;
+		if (strcmp(oldref, worktrees[i]->head_ref))
+			continue;
+
+		refs = get_worktree_ref_store(worktrees[i]);
+		if (refs_create_symref(refs, "HEAD", newref, logmsg))
+			ret = error(_("HEAD of working tree %s is not updated"),
+				    worktrees[i]->path);
+	}
+
+	return ret;
+}
+
+#define IS_HEAD 1
+#define IS_ORPHAN 2
+
 static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
 {
 	struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
 	struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
 	const char *interpreted_oldname = NULL;
 	const char *interpreted_newname = NULL;
-	int recovery = 0;
+	int recovery = 0, oldref_usage = 0;
+	struct worktree **worktrees = get_worktrees();
 
 	if (strbuf_check_branch_ref(&oldref, oldname)) {
 		/*
@@ -528,8 +587,19 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 			die(_("Invalid branch name: '%s'"), oldname);
 	}
 
-	if ((copy || strcmp(head, oldname)) && !ref_exists(oldref.buf)) {
-		if (copy && !strcmp(head, oldname))
+	for (int i = 0; worktrees[i]; i++) {
+		struct worktree *wt = worktrees[i];
+
+		if (wt->head_ref && !strcmp(oldref.buf, wt->head_ref)) {
+			oldref_usage |= IS_HEAD;
+			if (is_null_oid(&wt->head_oid))
+				oldref_usage |= IS_ORPHAN;
+			break;
+		}
+	}
+
+	if ((copy || !(oldref_usage & IS_HEAD)) && !ref_exists(oldref.buf)) {
+		if (oldref_usage & IS_HEAD)
 			die(_("No commit on branch '%s' yet."), oldname);
 		else
 			die(_("No branch named '%s'."), oldname);
@@ -544,7 +614,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 	else
 		validate_new_branchname(newname, &newref, force);
 
-	reject_rebase_or_bisect_branch(oldref.buf);
+	reject_rebase_or_bisect_branch(worktrees, oldref.buf);
 
 	if (!skip_prefix(oldref.buf, "refs/heads/", &interpreted_oldname) ||
 	    !skip_prefix(newref.buf, "refs/heads/", &interpreted_newname)) {
@@ -558,8 +628,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 		strbuf_addf(&logmsg, "Branch: renamed %s to %s",
 			    oldref.buf, newref.buf);
 
-	if (!copy &&
-	    (!head || strcmp(oldname, head) || !is_null_oid(&head_oid)) &&
+	if (!copy && !(oldref_usage & IS_ORPHAN) &&
 	    rename_ref(oldref.buf, newref.buf, logmsg.buf))
 		die(_("Branch rename failed"));
 	if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
@@ -574,8 +643,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 				interpreted_oldname);
 	}
 
-	if (!copy &&
-	    replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
+	if (!copy && (oldref_usage & IS_HEAD) &&
+	    replace_each_worktree_head_symref(worktrees, oldref.buf, newref.buf,
+					      logmsg.buf))
 		die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
 
 	strbuf_release(&logmsg);
@@ -590,6 +660,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 	strbuf_release(&newref);
 	strbuf_release(&oldsection);
 	strbuf_release(&newsection);
+	free_worktrees(worktrees);
 }
 
 static GIT_PATH_FUNC(edit_description, "EDIT_DESCRIPTION")
@@ -670,6 +741,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
 		OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
 		OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2),
+		OPT_BOOL(0, "omit-empty",  &omit_empty,
+			N_("do not output a newline after empty formatted refs")),
 		OPT_BIT('c', "copy", &copy, N_("copy a branch and its reflog"), 1),
 		OPT_BIT('C', NULL, &copy, N_("copy a branch, even if target exists"), 2),
 		OPT_BOOL('l', "list", &list, N_("list branch names")),
@@ -806,7 +879,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 
 		strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
 		if (!ref_exists(branch_ref.buf))
-			error((!argc || !strcmp(head, branch_name))
+			error((!argc || branch_checked_out(branch_ref.buf))
 			      ? _("No commit on branch '%s' yet.")
 			      : _("No branch named '%s'."),
 			      branch_name);
@@ -851,7 +924,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		}
 
 		if (!ref_exists(branch->refname)) {
-			if (!argc || !strcmp(head, branch->name))
+			if (!argc || branch_checked_out(branch->refname))
 				die(_("No commit on branch '%s' yet."), branch->name);
 			die(_("branch '%s' does not exist"), branch->name);
 		}
diff --git a/builtin/bugreport.c b/builtin/bugreport.c
index 5bc254b..daf6c23 100644
--- a/builtin/bugreport.c
+++ b/builtin/bugreport.c
@@ -1,4 +1,7 @@
 #include "builtin.h"
+#include "abspath.h"
+#include "editor.h"
+#include "gettext.h"
 #include "parse-options.h"
 #include "strbuf.h"
 #include "help.h"
@@ -6,7 +9,9 @@
 #include "hook.h"
 #include "hook-list.h"
 #include "diagnose.h"
-
+#include "object-file.h"
+#include "setup.h"
+#include "wrapper.h"
 
 static void get_system_info(struct strbuf *sys_info)
 {
diff --git a/builtin/bundle.c b/builtin/bundle.c
index acceef6..4411338 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -1,6 +1,11 @@
 #include "builtin.h"
+#include "abspath.h"
+#include "gettext.h"
+#include "setup.h"
 #include "strvec.h"
 #include "parse-options.h"
+#include "pkt-line.h"
+#include "repository.h"
 #include "cache.h"
 #include "bundle.h"
 
@@ -12,7 +17,7 @@
  */
 
 #define BUILTIN_BUNDLE_CREATE_USAGE \
-	N_("git bundle create [-q | --quiet | --progress | --all-progress] [--all-progress-implied]\n" \
+	N_("git bundle create [-q | --quiet | --progress]\n" \
 	   "                  [--version=<version>] <file> <git-rev-list-args>")
 #define BUILTIN_BUNDLE_VERIFY_USAGE \
 	N_("git bundle verify [-q | --quiet] <file>")
@@ -59,12 +64,12 @@ static int parse_options_cmd_bundle(int argc,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 	if (!argc)
 		usage_msg_opt(_("need a <file> argument"), usagestr, options);
-	*bundle_file = prefix_filename(prefix, argv[0]);
+	*bundle_file = prefix_filename_except_for_dash(prefix, argv[0]);
 	return argc;
 }
 
 static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
-	int all_progress_implied = 0;
+	int all_progress_implied = 1;
 	int progress = isatty(STDERR_FILENO);
 	struct strvec pack_opts;
 	int version = -1;
@@ -74,11 +79,12 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
 			    N_("do not show progress meter"), 0),
 		OPT_SET_INT(0, "progress", &progress,
 			    N_("show progress meter"), 1),
-		OPT_SET_INT(0, "all-progress", &progress,
-			    N_("show progress meter during object writing phase"), 2),
-		OPT_BOOL(0, "all-progress-implied",
-			 &all_progress_implied,
-			 N_("similar to --all-progress when progress meter is shown")),
+		OPT_SET_INT_F(0, "all-progress", &progress,
+			      N_("historical; same as --progress"), 2,
+			      PARSE_OPT_HIDDEN),
+		OPT_HIDDEN_BOOL(0, "all-progress-implied",
+				&all_progress_implied,
+				N_("historical; does nothing")),
 		OPT_INTEGER(0, "version", &version,
 			    N_("specify bundle format version")),
 		OPT_END()
@@ -107,6 +113,23 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
 	return ret;
 }
 
+/*
+ * Similar to read_bundle_header(), but handle "-" as stdin.
+ */
+static int open_bundle(const char *path, struct bundle_header *header,
+		       const char **name)
+{
+	if (!strcmp(path, "-")) {
+		if (name)
+			*name = "<stdin>";
+		return read_bundle_header_fd(0, header, "<stdin>");
+	}
+
+	if (name)
+		*name = path;
+	return read_bundle_header(path, header);
+}
+
 static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
 	struct bundle_header header = BUNDLE_HEADER_INIT;
 	int bundle_fd = -1;
@@ -118,12 +141,13 @@ static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
 		OPT_END()
 	};
 	char *bundle_file;
+	const char *name;
 
 	argc = parse_options_cmd_bundle(argc, argv, prefix,
 			builtin_bundle_verify_usage, options, &bundle_file);
 	/* bundle internals use argv[1] as further parameters */
 
-	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
+	if ((bundle_fd = open_bundle(bundle_file, &header, &name)) < 0) {
 		ret = 1;
 		goto cleanup;
 	}
@@ -134,7 +158,7 @@ static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
 		goto cleanup;
 	}
 
-	fprintf(stderr, _("%s is okay\n"), bundle_file);
+	fprintf(stderr, _("%s is okay\n"), name);
 	ret = 0;
 cleanup:
 	free(bundle_file);
@@ -155,7 +179,7 @@ static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix
 			builtin_bundle_list_heads_usage, options, &bundle_file);
 	/* bundle internals use argv[1] as further parameters */
 
-	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
+	if ((bundle_fd = open_bundle(bundle_file, &header, NULL)) < 0) {
 		ret = 1;
 		goto cleanup;
 	}
@@ -185,7 +209,7 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix)
 			builtin_bundle_unbundle_usage, options, &bundle_file);
 	/* bundle internals use argv[1] as further parameters */
 
-	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
+	if ((bundle_fd = open_bundle(bundle_file, &header, NULL)) < 0) {
 		ret = 1;
 		goto cleanup;
 	}
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index cc17635..0bafc14 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -5,18 +5,28 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
+#include "alloc.h"
 #include "config.h"
+#include "convert.h"
 #include "builtin.h"
 #include "diff.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "ident.h"
 #include "parse-options.h"
 #include "userdiff.h"
 #include "streaming.h"
 #include "tree-walk.h"
 #include "oid-array.h"
 #include "packfile.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
+#include "replace-object.h"
 #include "promisor-remote.h"
 #include "mailmap.h"
+#include "write-or-die.h"
 
 enum batch_mode {
 	BATCH_MODE_CONTENTS,
@@ -60,7 +70,7 @@ static int filter_object(const char *path, unsigned mode,
 {
 	enum object_type type;
 
-	*buf = read_object_file(oid, &type, size);
+	*buf = repo_read_object_file(the_repository, oid, &type, size);
 	if (!*buf)
 		return error(_("cannot read object %s '%s'"),
 			     oid_to_hex(oid), path);
@@ -152,7 +162,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 		goto cleanup;
 
 	case 'e':
-		return !has_object_file(&oid);
+		return !repo_has_object_file(the_repository, &oid);
 
 	case 'w':
 
@@ -187,7 +197,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 			ret = stream_blob(&oid);
 			goto cleanup;
 		}
-		buf = read_object_file(&oid, &type, &size);
+		buf = repo_read_object_file(the_repository, &oid, &type,
+					    &size);
 		if (!buf)
 			die("Cannot read object %s", obj_name);
 
@@ -207,8 +218,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 		if (exp_type_id == OBJ_BLOB) {
 			struct object_id blob_oid;
 			if (oid_object_info(the_repository, &oid, NULL) == OBJ_TAG) {
-				char *buffer = read_object_file(&oid, &type,
-								&size);
+				char *buffer = repo_read_object_file(the_repository,
+								     &oid,
+								     &type,
+								     &size);
 				const char *target;
 				if (!skip_prefix(buffer, "object ", &target) ||
 				    get_oid_hex(target, &blob_oid))
@@ -383,9 +396,10 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
 				if (!textconv_object(the_repository,
 						     data->rest, 0100644, oid,
 						     1, &contents, &size))
-					contents = read_object_file(oid,
-								    &type,
-								    &size);
+					contents = repo_read_object_file(the_repository,
+									 oid,
+									 &type,
+									 &size);
 				if (!contents)
 					die("could not convert '%s' %s",
 					    oid_to_hex(oid), data->rest);
@@ -402,7 +416,8 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
 		unsigned long size;
 		void *contents;
 
-		contents = read_object_file(oid, &type, &size);
+		contents = repo_read_object_file(the_repository, oid, &type,
+						 &size);
 
 		if (use_mailmap) {
 			size_t s = size;
@@ -559,7 +574,7 @@ static int batch_object_cb(const struct object_id *oid, void *vdata)
 }
 
 static int collect_loose_object(const struct object_id *oid,
-				const char *path,
+				const char *path UNUSED,
 				void *data)
 {
 	oid_array_append(data, oid);
@@ -567,8 +582,8 @@ static int collect_loose_object(const struct object_id *oid,
 }
 
 static int collect_packed_object(const struct object_id *oid,
-				 struct packed_git *pack,
-				 uint32_t pos,
+				 struct packed_git *pack UNUSED,
+				 uint32_t pos UNUSED,
 				 void *data)
 {
 	oid_array_append(data, oid);
@@ -591,7 +606,7 @@ static int batch_unordered_object(const struct object_id *oid,
 }
 
 static int batch_unordered_loose(const struct object_id *oid,
-				 const char *path,
+				 const char *path UNUSED,
 				 void *data)
 {
 	return batch_unordered_object(oid, NULL, 0, data);
@@ -787,7 +802,7 @@ static int batch_objects(struct batch_options *opt)
 		if (!memcmp(&data.info, &empty, sizeof(empty)))
 			data.skip_object_info = 1;
 
-		if (has_promisor_remote())
+		if (repo_has_promisor_remote(the_repository))
 			warning("This repository uses promisor remotes. Some objects may not be loaded.");
 
 		read_replace_refs = 0;
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index d7a40e6..e27b86d 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -3,8 +3,14 @@
 #include "cache.h"
 #include "config.h"
 #include "attr.h"
+#include "environment.h"
+#include "gettext.h"
+#include "object-name.h"
 #include "quote.h"
+#include "repository.h"
+#include "setup.h"
 #include "parse-options.h"
+#include "write-or-die.h"
 
 static int all_attrs;
 static int cached_attrs;
@@ -58,7 +64,7 @@ static void output_attr(struct attr_check *check, const char *file)
 }
 
 static void check_attr(const char *prefix, struct attr_check *check,
-		       const struct object_id *tree_oid, int collect_all,
+		       int collect_all,
 		       const char *file)
 
 {
@@ -66,9 +72,9 @@ static void check_attr(const char *prefix, struct attr_check *check,
 		prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
 
 	if (collect_all) {
-		git_all_attrs(&the_index, tree_oid, full_path, check);
+		git_all_attrs(&the_index, full_path, check);
 	} else {
-		git_check_attr(&the_index, tree_oid, full_path, check);
+		git_check_attr(&the_index, full_path, check);
 	}
 	output_attr(check, file);
 
@@ -76,7 +82,7 @@ static void check_attr(const char *prefix, struct attr_check *check,
 }
 
 static void check_attr_stdin_paths(const char *prefix, struct attr_check *check,
-				   const struct object_id *tree_oid, int collect_all)
+				   int collect_all)
 {
 	struct strbuf buf = STRBUF_INIT;
 	struct strbuf unquoted = STRBUF_INIT;
@@ -90,7 +96,7 @@ static void check_attr_stdin_paths(const char *prefix, struct attr_check *check,
 				die("line is badly quoted");
 			strbuf_swap(&buf, &unquoted);
 		}
-		check_attr(prefix, check, tree_oid, collect_all, buf.buf);
+		check_attr(prefix, check, collect_all, buf.buf);
 		maybe_flush_or_die(stdout, "attribute to stdout");
 	}
 	strbuf_release(&buf);
@@ -106,7 +112,6 @@ static NORETURN void error_with_usage(const char *msg)
 int cmd_check_attr(int argc, const char **argv, const char *prefix)
 {
 	struct attr_check *check;
-	struct object_id *tree_oid = NULL;
 	struct object_id initialized_oid;
 	int cnt, i, doubledash, filei;
 
@@ -182,14 +187,14 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
 	if (source) {
 		if (repo_get_oid_tree(the_repository, source, &initialized_oid))
 			die("%s: not a valid tree-ish source", source);
-		tree_oid = &initialized_oid;
+		set_git_attr_source(source);
 	}
 
 	if (stdin_paths)
-		check_attr_stdin_paths(prefix, check, tree_oid, all_attrs);
+		check_attr_stdin_paths(prefix, check, all_attrs);
 	else {
 		for (i = filei; i < argc; i++)
-			check_attr(prefix, check, tree_oid, all_attrs, argv[i]);
+			check_attr(prefix, check, all_attrs, argv[i]);
 		maybe_flush_or_die(stdout, "attribute to stdout");
 	}
 
diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c
index ab77606..e4b7878 100644
--- a/builtin/check-ignore.c
+++ b/builtin/check-ignore.c
@@ -3,10 +3,13 @@
 #include "cache.h"
 #include "config.h"
 #include "dir.h"
+#include "gettext.h"
 #include "quote.h"
 #include "pathspec.h"
 #include "parse-options.h"
+#include "repository.h"
 #include "submodule.h"
+#include "write-or-die.h"
 
 static int quiet, verbose, stdin_paths, show_non_matching, no_index;
 static const char * const check_ignore_usage[] = {
diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c
index 7dc47e4..002d294 100644
--- a/builtin/check-mailmap.c
+++ b/builtin/check-mailmap.c
@@ -1,8 +1,11 @@
 #include "builtin.h"
 #include "config.h"
+#include "gettext.h"
+#include "ident.h"
 #include "mailmap.h"
 #include "parse-options.h"
 #include "string-list.h"
+#include "write-or-die.h"
 
 static int use_stdin;
 static const char * const check_mailmap_usage[] = {
diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c
index fd0e5f8..57f0505 100644
--- a/builtin/check-ref-format.c
+++ b/builtin/check-ref-format.c
@@ -5,6 +5,7 @@
 #include "cache.h"
 #include "refs.h"
 #include "builtin.h"
+#include "setup.h"
 #include "strbuf.h"
 
 static const char builtin_check_ref_format_usage[] =
@@ -60,6 +61,8 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
 	char *to_free = NULL;
 	int ret = 1;
 
+	BUG_ON_NON_EMPTY_PREFIX(prefix);
+
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage(builtin_check_ref_format_usage);
 
diff --git a/builtin/checkout--worker.c b/builtin/checkout--worker.c
index ede7dc3..2120dd1 100644
--- a/builtin/checkout--worker.c
+++ b/builtin/checkout--worker.c
@@ -1,6 +1,8 @@
 #include "builtin.h"
+#include "alloc.h"
 #include "config.h"
 #include "entry.h"
+#include "gettext.h"
 #include "parallel-checkout.h"
 #include "parse-options.h"
 #include "pkt-line.h"
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index cf6fba9..9375a05 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -8,12 +8,15 @@
 #include "builtin.h"
 #include "config.h"
 #include "dir.h"
+#include "gettext.h"
 #include "lockfile.h"
 #include "quote.h"
+#include "repository.h"
 #include "cache-tree.h"
 #include "parse-options.h"
 #include "entry.h"
 #include "parallel-checkout.h"
+#include "setup.h"
 
 #define CHECKOUT_ALL 4
 static int nul_term_line;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index a5155cf..715eeb5 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -9,10 +9,15 @@
 #include "config.h"
 #include "diff.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "hook.h"
 #include "ll-merge.h"
 #include "lockfile.h"
+#include "mem-pool.h"
 #include "merge-recursive.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "parse-options.h"
 #include "refs.h"
@@ -20,8 +25,11 @@
 #include "resolve-undo.h"
 #include "revision.h"
 #include "run-command.h"
+#include "setup.h"
 #include "submodule.h"
 #include "submodule-config.h"
+#include "symlinks.h"
+#include "trace2.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "unpack-trees.h"
@@ -75,7 +83,7 @@ struct checkout_opts {
 	const char *ignore_unmerged_opt;
 	int ignore_unmerged;
 	int pathspec_file_nul;
-	const char *pathspec_from_file;
+	char *pathspec_from_file;
 
 	const char *new_branch;
 	const char *new_branch_force;
@@ -432,8 +440,8 @@ static int checkout_worktree(const struct checkout_opts *opts,
 					      "Updated %d paths from %s",
 					      nr_checkouts),
 				   nr_checkouts,
-				   find_unique_abbrev(&opts->source_tree->object.oid,
-						      DEFAULT_ABBREV));
+				   repo_find_unique_abbrev(the_repository, &opts->source_tree->object.oid,
+							   DEFAULT_ABBREV));
 		else if (!nr_unmerged || nr_checkouts)
 			fprintf_ln(stderr, Q_("Updated %d path from the index",
 					      "Updated %d paths from the index",
@@ -489,15 +497,28 @@ static int checkout_paths(const struct checkout_opts *opts,
 		die(_("'%s' must be used when '%s' is not specified"),
 		    "--worktree", "--source");
 
-	if (opts->checkout_index && !opts->checkout_worktree &&
-	    opts->writeout_stage)
-		die(_("'%s' or '%s' cannot be used with %s"),
-		    "--ours", "--theirs", "--staged");
+	/*
+	 * Reject --staged option to the restore command when combined with
+	 * merge-related options. Use the accept_ref flag to distinguish it
+	 * from the checkout command, which does not accept --staged anyway.
+	 *
+	 * `restore --ours|--theirs --worktree --staged` could mean resolving
+	 * conflicted paths to one side in both the worktree and the index,
+	 * but does not currently.
+	 *
+	 * `restore --merge|--conflict=<style>` already recreates conflicts
+	 * in both the worktree and the index, so adding --staged would be
+	 * meaningless.
+	 */
+	if (!opts->accept_ref && opts->checkout_index) {
+		if (opts->writeout_stage)
+			die(_("'%s' or '%s' cannot be used with %s"),
+			    "--ours", "--theirs", "--staged");
 
-	if (opts->checkout_index && !opts->checkout_worktree &&
-	    opts->merge)
-		die(_("'%s' or '%s' cannot be used with %s"),
-		    "--merge", "--conflict", "--staged");
+		if (opts->merge)
+			die(_("'%s' or '%s' cannot be used with %s"),
+			    "--merge", "--conflict", "--staged");
+	}
 
 	if (opts->patch_mode) {
 		enum add_p_mode patch_mode;
@@ -640,14 +661,16 @@ static void describe_detached_head(const char *msg, struct commit *commit)
 {
 	struct strbuf sb = STRBUF_INIT;
 
-	if (!parse_commit(commit))
+	if (!repo_parse_commit(the_repository, commit))
 		pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);
 	if (print_sha1_ellipsis()) {
 		fprintf(stderr, "%s %s... %s\n", msg,
-			find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV), sb.buf);
+			repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV),
+			sb.buf);
 	} else {
 		fprintf(stderr, "%s %s %s\n", msg,
-			find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV), sb.buf);
+			repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV),
+			sb.buf);
 	}
 	strbuf_release(&sb);
 }
@@ -701,7 +724,8 @@ static void setup_branch_path(struct branch_info *branch)
 	 * If this is a ref, resolve it; otherwise, look up the OID for our
 	 * expression.  Failure here is okay.
 	 */
-	if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname, 0))
+	if (!repo_dwim_ref(the_repository, branch->name, strlen(branch->name),
+			   &branch->oid, &branch->refname, 0))
 		repo_get_oid_committish(the_repository, branch->name, &branch->oid);
 
 	strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL);
@@ -753,7 +777,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
 			BUG("'switch --orphan' should never accept a commit as starting point");
 		new_tree = parse_tree_indirect(the_hash_algo->empty_tree);
 	} else
-		new_tree = get_commit_tree(new_branch_info->commit);
+		new_tree = repo_get_commit_tree(the_repository,
+						new_branch_info->commit);
 	if (opts->discard_changes) {
 		ret = reset_tree(new_tree, opts, 1, writeout_error, new_branch_info);
 		if (ret)
@@ -815,7 +840,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
 			 */
 			if (!old_branch_info->commit)
 				return 1;
-			old_tree = get_commit_tree(old_branch_info->commit);
+			old_tree = repo_get_commit_tree(the_repository,
+							old_branch_info->commit);
 
 			if (repo_index_has_changes(the_repository, old_tree, &sb))
 				die(_("cannot continue with staged changes in "
@@ -1004,7 +1030,7 @@ static void describe_one_orphan(struct strbuf *sb, struct commit *commit)
 	strbuf_addstr(sb, "  ");
 	strbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV);
 	strbuf_addch(sb, ' ');
-	if (!parse_commit(commit))
+	if (!repo_parse_commit(the_repository, commit))
 		pp_commit_easy(CMIT_FMT_ONELINE, commit, sb);
 	strbuf_addch(sb, '\n');
 }
@@ -1060,7 +1086,7 @@ static void suggest_reattach(struct commit *commit, struct rev_info *revs)
 			" git branch <new-branch-name> %s\n\n",
 			/* Give ngettext() the count */
 			lost),
-			find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
+			repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));
 }
 
 /*
@@ -1204,7 +1230,8 @@ static void setup_new_branch_info_and_source_tree(
 		*source_tree = parse_tree_indirect(rev);
 	} else {
 		parse_commit_or_die(new_branch_info->commit);
-		*source_tree = get_commit_tree(new_branch_info->commit);
+		*source_tree = repo_get_commit_tree(the_repository,
+						    new_branch_info->commit);
 	}
 }
 
@@ -1322,7 +1349,7 @@ static int parse_branchname_arg(int argc, const char **argv,
 	if (!strcmp(arg, "-"))
 		arg = "@{-1}";
 
-	if (get_oid_mb(arg, rev)) {
+	if (repo_get_oid_mb(the_repository, arg, rev)) {
 		/*
 		 * Either case (3) or (4), with <something> not being
 		 * a commit, or an attempt to use case (1) with an
@@ -1419,7 +1446,8 @@ static void die_expecting_a_branch(const struct branch_info *branch_info)
 	char *to_free;
 	int code;
 
-	if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free, 0) == 1) {
+	if (repo_dwim_ref(the_repository, branch_info->name,
+			  strlen(branch_info->name), &oid, &to_free, 0) == 1) {
 		const char *ref = to_free;
 
 		if (skip_prefix(ref, "refs/tags/", &ref))
@@ -1748,7 +1776,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 	} else if (!opts->accept_ref && opts->from_treeish) {
 		struct object_id rev;
 
-		if (get_oid_mb(opts->from_treeish, &rev))
+		if (repo_get_oid_mb(the_repository, opts->from_treeish, &rev))
 			die(_("could not resolve %s"), opts->from_treeish);
 
 		setup_new_branch_info_and_source_tree(new_branch_info,
@@ -1876,6 +1904,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 			    options, checkout_usage, &new_branch_info);
 	branch_info_release(&new_branch_info);
 	clear_pathspec(&opts.pathspec);
+	free(opts.pathspec_from_file);
 	FREE_AND_NULL(options);
 	return ret;
 }
diff --git a/builtin/clean.c b/builtin/clean.c
index 10aaa8c..78852d2 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -8,10 +8,14 @@
 
 #define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
+#include "abspath.h"
 #include "cache.h"
 #include "config.h"
 #include "dir.h"
+#include "gettext.h"
 #include "parse-options.h"
+#include "repository.h"
+#include "setup.h"
 #include "string-list.h"
 #include "quote.h"
 #include "column.h"
diff --git a/builtin/clone.c b/builtin/clone.c
index 65b5b7d..15f9912 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -10,12 +10,19 @@
 
 #define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
+#include "abspath.h"
+#include "advice.h"
 #include "config.h"
+#include "copy.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "parse-options.h"
 #include "fetch-pack.h"
 #include "refs.h"
 #include "refspec.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "tree.h"
 #include "tree-walk.h"
@@ -29,12 +36,15 @@
 #include "branch.h"
 #include "remote.h"
 #include "run-command.h"
+#include "setup.h"
 #include "connected.h"
 #include "packfile.h"
+#include "pkt-line.h"
 #include "list-objects-filter-options.h"
 #include "hook.h"
 #include "bundle.h"
 #include "bundle-uri.h"
+#include "wrapper.h"
 
 /*
  * Overall FIXMEs:
@@ -326,8 +336,18 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
 
 	iter = dir_iterator_begin(src->buf, DIR_ITERATOR_PEDANTIC);
 
-	if (!iter)
+	if (!iter) {
+		if (errno == ENOTDIR) {
+			int saved_errno = errno;
+			struct stat st;
+
+			if (!lstat(src->buf, &st) && S_ISLNK(st.st_mode))
+				die(_("'%s' is a symlink, refusing to clone with --local"),
+				    src->buf);
+			errno = saved_errno;
+		}
 		die_errno(_("failed to start iterator over '%s'"), src->buf);
+	}
 
 	strbuf_addch(src, '/');
 	src_len = src->len;
@@ -547,9 +567,9 @@ static void write_followtags(const struct ref *refs, const char *msg)
 			continue;
 		if (ends_with(ref->name, "^{}"))
 			continue;
-		if (!has_object_file_with_flags(&ref->old_oid,
-						OBJECT_INFO_QUICK |
-						OBJECT_INFO_SKIP_FETCH_OBJECT))
+		if (!repo_has_object_file_with_flags(the_repository, &ref->old_oid,
+						     OBJECT_INFO_QUICK |
+						     OBJECT_INFO_SKIP_FETCH_OBJECT))
 			continue;
 		update_ref(msg, ref->name, &ref->old_oid, NULL, 0,
 			   UPDATE_REFS_DIE_ON_ERR);
@@ -909,6 +929,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	int err = 0, complete_refs_before_fetch = 1;
 	int submodule_progress;
 	int filter_submodules = 0;
+	int hash_algo;
 
 	struct transport_ls_refs_options transport_ls_refs_options =
 		TRANSPORT_LS_REFS_OPTIONS_INIT;
@@ -1297,15 +1318,15 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	if (mapped_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, 1);
-		repo_set_hash_algo(the_repository, hash_algo);
+	hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
+	initialize_repository_version(hash_algo, 1);
+	repo_set_hash_algo(the_repository, hash_algo);
+
+	if (mapped_refs) {
 		/*
 		 * transport_get_remote_refs() may return refs with null sha-1
 		 * in mapped_refs (see struct transport->get_refs_list
diff --git a/builtin/column.c b/builtin/column.c
index 158fdf5..de623a1 100644
--- a/builtin/column.c
+++ b/builtin/column.c
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
 #include "strbuf.h"
 #include "parse-options.h"
 #include "string-list.h"
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 93704f9..a3d00fa 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -1,13 +1,18 @@
 #include "builtin.h"
 #include "config.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "parse-options.h"
 #include "repository.h"
 #include "commit-graph.h"
 #include "object-store.h"
 #include "progress.h"
+#include "replace-object.h"
 #include "tag.h"
+#include "trace2.h"
 
 #define BUILTIN_COMMIT_GRAPH_VERIFY_USAGE \
 	N_("git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]")
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index cc8d584..d1d251c 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -5,6 +5,9 @@
  */
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "repository.h"
 #include "commit.h"
@@ -37,14 +40,6 @@ static void new_parent(struct commit *parent, struct commit_list **parents_p)
 	commit_list_insert(parent, parents_p);
 }
 
-static int commit_tree_config(const char *var, const char *value, void *cb)
-{
-	int status = git_gpg_config(var, value, NULL);
-	if (status)
-		return status;
-	return git_default_config(var, value, cb);
-}
-
 static int parse_parent_arg_callback(const struct option *opt,
 		const char *arg, int unset)
 {
@@ -53,7 +48,7 @@ static int parse_parent_arg_callback(const struct option *opt,
 
 	BUG_ON_OPT_NEG_NOARG(unset, arg);
 
-	if (get_oid_commit(arg, &oid))
+	if (repo_get_oid_commit(the_repository, arg, &oid))
 		die(_("not a valid object name %s"), arg);
 
 	assert_oid_type(&oid, OBJ_COMMIT);
@@ -121,7 +116,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
-	git_config(commit_tree_config, NULL);
+	git_config(git_default_config, NULL);
 
 	if (argc < 2 || !strcmp(argv[1], "-h"))
 		usage_with_options(commit_tree_usage, options);
@@ -131,7 +126,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		die(_("must give exactly one tree"));
 
-	if (get_oid_tree(argv[0], &tree_oid))
+	if (repo_get_oid_tree(the_repository, argv[0], &tree_oid))
 		die(_("not a valid object name %s"), argv[0]);
 
 	if (!buffer.len) {
diff --git a/builtin/commit.c b/builtin/commit.c
index 985a044..e67c4be 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -7,15 +7,19 @@
 
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
+#include "advice.h"
 #include "config.h"
 #include "lockfile.h"
 #include "cache-tree.h"
 #include "color.h"
 #include "dir.h"
+#include "editor.h"
+#include "environment.h"
 #include "builtin.h"
 #include "diff.h"
 #include "diffcore.h"
 #include "commit.h"
+#include "gettext.h"
 #include "revision.h"
 #include "wt-status.h"
 #include "run-command.h"
@@ -24,6 +28,7 @@
 #include "log-tree.h"
 #include "strbuf.h"
 #include "utf8.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "string-list.h"
 #include "rerere.h"
@@ -557,7 +562,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
 	s->index_file = index_file;
 	s->fp = fp;
 	s->nowarn = nowarn;
-	s->is_initial = get_oid(s->reference, &oid) ? 1 : 0;
+	s->is_initial = repo_get_oid(the_repository, s->reference, &oid) ? 1 : 0;
 	if (!s->is_initial)
 		oidcpy(&s->oid_commit, &oid);
 	s->status_format = status_format;
@@ -712,15 +717,15 @@ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
 {
 	const char *buffer, *subject, *fmt;
 
-	buffer = get_commit_buffer(commit, NULL);
+	buffer = repo_get_commit_buffer(the_repository, commit, NULL);
 	find_commit_subject(buffer, &subject);
 	/*
 	 * If we amend the 'amend!' commit then we don't want to
 	 * duplicate the subject line.
 	 */
 	fmt = starts_with(subject, "amend!") ? "%b" : "%B";
-	format_commit_message(commit, fmt, sb, ctx);
-	unuse_commit_buffer(commit, buffer);
+	repo_format_commit_message(the_repository, commit, fmt, sb, ctx);
+	repo_unuse_commit_buffer(the_repository, commit, buffer);
 }
 
 static int prepare_to_commit(const char *index_file, const char *prefix,
@@ -760,8 +765,9 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 			if (!c)
 				die(_("could not lookup commit %s"), squash_message);
 			ctx.output_encoding = get_commit_output_encoding();
-			format_commit_message(c, "squash! %s\n\n", &sb,
-					      &ctx);
+			repo_format_commit_message(the_repository, c,
+						   "squash! %s\n\n", &sb,
+						   &ctx);
 		}
 	}
 
@@ -795,7 +801,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 			die(_("could not lookup commit %s"), fixup_commit);
 		ctx.output_encoding = get_commit_output_encoding();
 		fmt = xstrfmt("%s! %%s\n\n", fixup_prefix);
-		format_commit_message(commit, fmt, &sb, &ctx);
+		repo_format_commit_message(the_repository, commit, fmt, &sb,
+					   &ctx);
 		free(fmt);
 		hook_arg1 = "message";
 
@@ -1000,7 +1007,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		if (amend)
 			parent = "HEAD^1";
 
-		if (get_oid(parent, &oid)) {
+		if (repo_get_oid(the_repository, parent, &oid)) {
 			int i, ita_nr = 0;
 
 			/* TODO: audit for interaction with sparse-index. */
@@ -1135,7 +1142,8 @@ static const char *find_author_by_nickname(const char *name)
 		struct pretty_print_context ctx = {0};
 		ctx.date_mode.type = DATE_NORMAL;
 		strbuf_release(&buf);
-		format_commit_message(commit, "%aN <%aE>", &buf, &ctx);
+		repo_format_commit_message(the_repository, commit,
+					   "%aN <%aE>", &buf, &ctx);
 		release_revisions(&revs);
 		return strbuf_detach(&buf, NULL);
 	}
@@ -1183,7 +1191,7 @@ static const char *read_commit_message(const char *name)
 	if (!commit)
 		die(_("could not lookup commit %s"), name);
 	out_enc = get_commit_output_encoding();
-	return logmsg_reencode(commit, NULL, out_enc);
+	return repo_logmsg_reencode(the_repository, commit, NULL, out_enc);
 }
 
 /*
@@ -1567,7 +1575,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 	else
 		fd = -1;
 
-	s.is_initial = get_oid(s.reference, &oid) ? 1 : 0;
+	s.is_initial = repo_get_oid(the_repository, s.reference, &oid) ? 1 : 0;
 	if (!s.is_initial)
 		oidcpy(&s.oid_commit, &oid);
 
@@ -1600,7 +1608,6 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 static int git_commit_config(const char *k, const char *v, void *cb)
 {
 	struct wt_status *s = cb;
-	int status;
 
 	if (!strcmp(k, "commit.template"))
 		return git_config_pathname(&template_file, k, v);
@@ -1620,9 +1627,6 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 		return 0;
 	}
 
-	status = git_gpg_config(k, v, NULL);
-	if (status)
-		return status;
 	return git_status_config(k, v, s);
 }
 
@@ -1714,11 +1718,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 	status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
 	s.colopts = 0;
 
-	if (get_oid("HEAD", &oid))
+	if (repo_get_oid(the_repository, "HEAD", &oid))
 		current_head = NULL;
 	else {
 		current_head = lookup_commit_or_die(&oid, "HEAD");
-		if (parse_commit(current_head))
+		if (repo_parse_commit(the_repository, current_head))
 			die(_("could not parse HEAD commit"));
 	}
 	verbose = -1; /* unspecified */
diff --git a/builtin/config.c b/builtin/config.c
index 060cf9f..ff2fe8e 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -1,11 +1,19 @@
 #include "builtin.h"
-#include "cache.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
 #include "color.h"
+#include "editor.h"
+#include "environment.h"
+#include "gettext.h"
+#include "ident.h"
 #include "parse-options.h"
 #include "urlmatch.h"
+#include "path.h"
 #include "quote.h"
+#include "setup.h"
 #include "worktree.h"
+#include "wrapper.h"
 
 static const char *const builtin_config_usage[] = {
 	N_("git config [<options>]"),
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 07b9419..f3d8f1b 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -7,6 +7,8 @@
 #include "cache.h"
 #include "config.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
 #include "repository.h"
 #include "builtin.h"
 #include "parse-options.h"
@@ -57,7 +59,8 @@ static void loose_garbage(const char *path)
 		report_garbage(PACKDIR_FILE_GARBAGE, path);
 }
 
-static int count_loose(const struct object_id *oid, const char *path, void *data)
+static int count_loose(const struct object_id *oid, const char *path,
+		       void *data UNUSED)
 {
 	struct stat st;
 
@@ -72,7 +75,8 @@ static int count_loose(const struct object_id *oid, const char *path, void *data
 	return 0;
 }
 
-static int count_cruft(const char *basename, const char *path, void *data)
+static int count_cruft(const char *basename UNUSED, const char *path,
+		       void *data UNUSED)
 {
 	loose_garbage(path);
 	return 0;
diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c
index 338058b..756c5f0 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -1,4 +1,8 @@
 #include "builtin.h"
+#include "abspath.h"
+#include "alloc.h"
+#include "gettext.h"
+#include "object-file.h"
 #include "parse-options.h"
 
 #ifndef NO_UNIX_SOCKETS
@@ -130,6 +134,9 @@ static void serve_one_client(FILE *in, FILE *out)
 			if (e->item.password_expiry_utc != TIME_MAX)
 				fprintf(out, "password_expiry_utc=%"PRItime"\n",
 					e->item.password_expiry_utc);
+			if (e->item.oauth_refresh_token)
+				fprintf(out, "oauth_refresh_token=%s\n",
+					e->item.oauth_refresh_token);
 		}
 	}
 	else if (!strcmp(action.buf, "exit")) {
diff --git a/builtin/credential-cache.c b/builtin/credential-cache.c
index 78c02ad..0ffacfd 100644
--- a/builtin/credential-cache.c
+++ b/builtin/credential-cache.c
@@ -1,5 +1,9 @@
 #include "builtin.h"
+#include "gettext.h"
 #include "parse-options.h"
+#include "path.h"
+#include "wrapper.h"
+#include "write-or-die.h"
 
 #ifndef NO_UNIX_SOCKETS
 
diff --git a/builtin/credential-store.c b/builtin/credential-store.c
index 62a4f3c..30c6ccf 100644
--- a/builtin/credential-store.c
+++ b/builtin/credential-store.c
@@ -1,9 +1,12 @@
 #include "builtin.h"
 #include "config.h"
+#include "gettext.h"
 #include "lockfile.h"
 #include "credential.h"
+#include "path.h"
 #include "string-list.h"
 #include "parse-options.h"
+#include "write-or-die.h"
 
 static struct lock_file credential_lock;
 
diff --git a/builtin/credential.c b/builtin/credential.c
index d7b304f..7010752 100644
--- a/builtin/credential.c
+++ b/builtin/credential.c
@@ -6,7 +6,7 @@
 static const char usage_msg[] =
 	"git credential (fill|approve|reject)";
 
-int cmd_credential(int argc, const char **argv, const char *prefix)
+int cmd_credential(int argc, const char **argv, const char *prefix UNUSED)
 {
 	const char *op;
 	struct credential c = CREDENTIAL_INIT;
diff --git a/builtin/describe.c b/builtin/describe.c
index eea1e33..55b4baa 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -1,6 +1,9 @@
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "commit.h"
 #include "tag.h"
@@ -8,10 +11,12 @@
 #include "refs.h"
 #include "builtin.h"
 #include "exec-cmd.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "revision.h"
 #include "diff.h"
 #include "hashmap.h"
+#include "setup.h"
 #include "strvec.h"
 #include "run-command.h"
 #include "object-store.h"
@@ -261,7 +266,7 @@ static unsigned long finish_depth_computation(
 			best->depth++;
 		while (parents) {
 			struct commit *p = parents->item;
-			parse_commit(p);
+			repo_parse_commit(the_repository, p);
 			if (!(p->object.flags & SEEN))
 				commit_list_insert_by_date(p, list);
 			p->object.flags |= c->object.flags;
@@ -298,7 +303,8 @@ static void append_name(struct commit_name *n, struct strbuf *dst)
 
 static void append_suffix(int depth, const struct object_id *oid, struct strbuf *dst)
 {
-	strbuf_addf(dst, "-%d-g%s", depth, find_unique_abbrev(oid, abbrev));
+	strbuf_addf(dst, "-%d-g%s", depth,
+		    repo_find_unique_abbrev(the_repository, oid, abbrev));
 }
 
 static void describe_commit(struct object_id *oid, struct strbuf *dst)
@@ -403,7 +409,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 		}
 		while (parents) {
 			struct commit *p = parents->item;
-			parse_commit(p);
+			repo_parse_commit(the_repository, p);
 			if (!(p->object.flags & SEEN))
 				commit_list_insert_by_date(p, &list);
 			p->object.flags |= c->object.flags;
@@ -531,7 +537,7 @@ static void describe(const char *arg, int last_one)
 	if (debug)
 		fprintf(stderr, _("describe %s\n"), arg);
 
-	if (get_oid(arg, &oid))
+	if (repo_get_oid(the_repository, arg, &oid))
 		die(_("Not a valid object name %s"), arg);
 	cmit = lookup_commit_reference_gently(the_repository, &oid, 1);
 
@@ -653,6 +659,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 			int fd, result;
 
 			setup_work_tree();
+			prepare_repo_settings(the_repository);
+			the_repository->settings.command_requires_full_index = 0;
 			repo_read_index(the_repository);
 			refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED,
 				      NULL, NULL, NULL);
diff --git a/builtin/diagnose.c b/builtin/diagnose.c
index d52015c..4f22eb2 100644
--- a/builtin/diagnose.c
+++ b/builtin/diagnose.c
@@ -1,4 +1,7 @@
 #include "builtin.h"
+#include "abspath.h"
+#include "gettext.h"
+#include "object-file.h"
 #include "parse-options.h"
 #include "diagnose.h"
 
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index dc991f7..360464e 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -27,6 +27,10 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
 		usage(diff_files_usage);
 
 	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
+
+	prepare_repo_settings(the_repository);
+	the_repository->settings.command_requires_full_index = 0;
+
 	repo_init_revisions(the_repository, &rev, prefix);
 	rev.abbrev = 0;
 
diff --git a/builtin/diff-index.c b/builtin/diff-index.c
index 35dc9b2..b9a19bb 100644
--- a/builtin/diff-index.c
+++ b/builtin/diff-index.c
@@ -5,6 +5,7 @@
 #include "commit.h"
 #include "revision.h"
 #include "builtin.h"
+#include "setup.h"
 #include "submodule.h"
 
 static const char diff_cache_usage[] =
diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index 25b853b..0b02c62 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -3,10 +3,13 @@
 #include "config.h"
 #include "diff.h"
 #include "commit.h"
+#include "gettext.h"
+#include "hex.h"
 #include "log-tree.h"
 #include "builtin.h"
 #include "submodule.h"
 #include "repository.h"
+#include "tree.h"
 
 static struct rev_info log_tree_opt;
 
diff --git a/builtin/diff.c b/builtin/diff.c
index 26f1e53..7b64659 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -11,6 +11,7 @@
 #include "color.h"
 #include "commit.h"
 #include "blob.h"
+#include "gettext.h"
 #include "tag.h"
 #include "diff.h"
 #include "diff-merges.h"
@@ -18,8 +19,10 @@
 #include "revision.h"
 #include "log-tree.h"
 #include "builtin.h"
+#include "setup.h"
 #include "submodule.h"
 #include "oid-array.h"
+#include "tree.h"
 
 #define DIFF_NO_INDEX_EXPLICIT 1
 #define DIFF_NO_INDEX_IMPLICIT 2
@@ -74,7 +77,7 @@ static void stuff_change(struct diff_options *opt,
 }
 
 static int builtin_diff_b_f(struct rev_info *revs,
-			    int argc, const char **argv,
+			    int argc, const char **argv UNUSED,
 			    struct object_array_entry **blob)
 {
 	/* Blob vs file in the working tree*/
@@ -109,7 +112,7 @@ static int builtin_diff_b_f(struct rev_info *revs,
 }
 
 static int builtin_diff_blobs(struct rev_info *revs,
-			      int argc, const char **argv,
+			      int argc, const char **argv UNUSED,
 			      struct object_array_entry **blob)
 {
 	const unsigned mode = canon_mode(S_IFREG | 0644);
@@ -209,7 +212,7 @@ static int builtin_diff_tree(struct rev_info *revs,
 }
 
 static int builtin_diff_combined(struct rev_info *revs,
-				 int argc, const char **argv,
+				 int argc, const char **argv UNUSED,
 				 struct object_array_entry *ent,
 				 int ents, int first_non_parent)
 {
@@ -548,7 +551,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
 		if (!obj)
 			die(_("invalid object '%s' given."), name);
 		if (obj->type == OBJ_COMMIT)
-			obj = &get_commit_tree(((struct commit *)obj))->object;
+			obj = &repo_get_commit_tree(the_repository,
+						    ((struct commit *)obj))->object;
 
 		if (obj->type == OBJ_TREE) {
 			if (sdiff.skip && bitmap_get(sdiff.skip, i))
diff --git a/builtin/difftool.c b/builtin/difftool.c
index dbbfb19..0049342 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -13,17 +13,25 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
+#include "abspath.h"
 #include "config.h"
+#include "copy.h"
 #include "builtin.h"
 #include "run-command.h"
+#include "environment.h"
 #include "exec-cmd.h"
+#include "gettext.h"
+#include "hex.h"
 #include "parse-options.h"
 #include "strvec.h"
 #include "strbuf.h"
 #include "lockfile.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "dir.h"
 #include "entry.h"
+#include "setup.h"
+#include "wrapper.h"
 
 static int trust_exit_code;
 
@@ -295,7 +303,8 @@ static char *get_symlink(const struct object_id *oid, const char *path)
 	} else {
 		enum object_type type;
 		unsigned long size;
-		data = read_object_file(oid, &type, &size);
+		data = repo_read_object_file(the_repository, oid, &type,
+					     &size);
 		if (!data)
 			die(_("could not read object %s for symlink %s"),
 				oid_to_hex(oid), path);
@@ -684,7 +693,7 @@ static int run_file_diff(int prompt, const char *prefix,
 
 int cmd_difftool(int argc, const char **argv, const char *prefix)
 {
-	int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
+	int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0,
 	    tool_help = 0, no_index = 0;
 	static char *difftool_cmd = NULL, *extcmd = NULL;
 	struct option builtin_difftool_options[] = {
@@ -734,13 +743,21 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 	} else if (dir_diff)
 		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
 
-	die_for_incompatible_opt3(use_gui_tool, "--gui",
+	die_for_incompatible_opt3(use_gui_tool == 1, "--gui",
 				  !!difftool_cmd, "--tool",
 				  !!extcmd, "--extcmd");
 
-	if (use_gui_tool)
+	/*
+	 * Explicitly specified GUI option is forwarded to git-mergetool--lib.sh;
+	 * empty or unset means "use the difftool.guiDefault config or default to
+	 * false".
+	 */
+	if (use_gui_tool == 1)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
-	else if (difftool_cmd) {
+	else if (use_gui_tool == 0)
+		setenv("GIT_MERGETOOL_GUI", "false", 1);
+
+	if (difftool_cmd) {
 		if (*difftool_cmd)
 			setenv("GIT_DIFF_TOOL", difftool_cmd, 1);
 		else
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 39a890f..9a95f6a 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -6,8 +6,11 @@
 #include "builtin.h"
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
 #include "refspec.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "commit.h"
 #include "object.h"
@@ -109,7 +112,7 @@ static struct decoration idnums;
 static uint32_t last_idnum;
 struct anonymized_entry {
 	struct hashmap_entry hash;
-	const char *anon;
+	char *anon;
 	const char orig[FLEX_ARRAY];
 };
 
@@ -138,43 +141,56 @@ static int anonymized_entry_cmp(const void *cmp_data UNUSED,
 	return strcmp(a->orig, b->orig);
 }
 
+static struct anonymized_entry *add_anonymized_entry(struct hashmap *map,
+						     unsigned hash,
+						     const char *orig, size_t len,
+						     char *anon)
+{
+	struct anonymized_entry *ret, *old;
+
+	if (!map->cmpfn)
+		hashmap_init(map, anonymized_entry_cmp, NULL, 0);
+
+	FLEX_ALLOC_MEM(ret, orig, orig, len);
+	hashmap_entry_init(&ret->hash, hash);
+	ret->anon = anon;
+	old = hashmap_put_entry(map, ret, hash);
+
+	if (old) {
+		free(old->anon);
+		free(old);
+	}
+
+	return ret;
+}
+
 /*
  * Basically keep a cache of X->Y so that we can repeatedly replace
  * the same anonymized string with another. The actual generation
  * is farmed out to the generate function.
  */
 static const char *anonymize_str(struct hashmap *map,
-				 char *(*generate)(void *),
-				 const char *orig, size_t len,
-				 void *data)
+				 char *(*generate)(void),
+				 const char *orig, size_t len)
 {
 	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));
 	key.orig = orig;
 	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;
+	ret = hashmap_get_entry(&anonymized_seeds, &key, hash, &key);
 
 	/* ...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) {
-		FLEX_ALLOC_MEM(ret, orig, orig, len);
-		hashmap_entry_init(&ret->hash, key.hash.hash);
-		ret->anon = generate(data);
-		hashmap_put(map, &ret->hash);
-	}
+	if (!ret)
+		ret = add_anonymized_entry(map, key.hash.hash,
+					   orig, len, generate());
 
 	return ret->anon;
 }
@@ -187,12 +203,12 @@ static const char *anonymize_str(struct hashmap *map,
  */
 static void anonymize_path(struct strbuf *out, const char *path,
 			   struct hashmap *map,
-			   char *(*generate)(void *))
+			   char *(*generate)(void))
 {
 	while (*path) {
 		const char *end_of_component = strchrnul(path, '/');
 		size_t len = end_of_component - path;
-		const char *c = anonymize_str(map, generate, path, len, NULL);
+		const char *c = anonymize_str(map, generate, path, len);
 		strbuf_addstr(out, c);
 		path = end_of_component;
 		if (*path)
@@ -296,7 +312,7 @@ static void export_blob(const struct object_id *oid)
 		object = (struct object *)lookup_blob(the_repository, oid);
 		eaten = 0;
 	} else {
-		buf = read_object_file(oid, &type, &size);
+		buf = repo_read_object_file(the_repository, oid, &type, &size);
 		if (!buf)
 			die("could not read blob %s", oid_to_hex(oid));
 		if (check_object_signature(the_repository, oid, buf, size,
@@ -367,7 +383,7 @@ static void print_path_1(const char *path)
 		printf("%s", path);
 }
 
-static char *anonymize_path_component(void *data)
+static char *anonymize_path_component(void)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
@@ -389,7 +405,7 @@ static void print_path(const char *path)
 	}
 }
 
-static char *generate_fake_oid(void *data)
+static char *generate_fake_oid(void)
 {
 	static uint32_t counter = 1; /* avoid null oid */
 	const unsigned hashsz = the_hash_algo->rawsz;
@@ -405,7 +421,7 @@ static const char *anonymize_oid(const char *oid_hex)
 {
 	static struct hashmap objs;
 	size_t len = strlen(oid_hex);
-	return anonymize_str(&objs, generate_fake_oid, oid_hex, len, NULL);
+	return anonymize_str(&objs, generate_fake_oid, oid_hex, len);
 }
 
 static void show_filemodify(struct diff_queue_struct *q,
@@ -502,7 +518,7 @@ static const char *find_encoding(const char *begin, const char *end)
 	return bol;
 }
 
-static char *anonymize_ref_component(void *data)
+static char *anonymize_ref_component(void)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
@@ -542,13 +558,13 @@ static const char *anonymize_refname(const char *refname)
  * We do not even bother to cache commit messages, as they are unlikely
  * to be repeated verbatim, and it is not that interesting when they are.
  */
-static char *anonymize_commit_message(const char *old)
+static char *anonymize_commit_message(void)
 {
 	static int counter;
 	return xstrfmt("subject %d\n\nbody\n", counter++);
 }
 
-static char *anonymize_ident(void *data)
+static char *anonymize_ident(void)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
@@ -591,7 +607,7 @@ static void anonymize_ident_line(const char **beg, const char **end)
 
 		len = split.mail_end - split.name_begin;
 		ident = anonymize_str(&idents, anonymize_ident,
-				      split.name_begin, len, NULL);
+				      split.name_begin, len);
 		strbuf_addstr(out, ident);
 		strbuf_addch(out, ' ');
 		strbuf_add(out, split.date_begin, split.tz_end - split.date_begin);
@@ -618,7 +634,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
 	rev->diffopt.output_format = DIFF_FORMAT_CALLBACK;
 
 	parse_commit_or_die(commit);
-	commit_buffer = get_commit_buffer(commit, NULL);
+	commit_buffer = repo_get_commit_buffer(the_repository, commit, NULL);
 	author = strstr(commit_buffer, "\nauthor ");
 	if (!author)
 		die("could not find author in commit %s",
@@ -669,7 +685,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
 
 	mark_next_object(&commit->object);
 	if (anonymize) {
-		reencoded = anonymize_commit_message(message);
+		reencoded = anonymize_commit_message();
 	} else if (encoding) {
 		switch(reencode_mode) {
 		case REENCODE_YES:
@@ -699,7 +715,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
 			  ? strlen(message) : 0),
 	       reencoded ? reencoded : message ? message : "");
 	free(reencoded);
-	unuse_commit_buffer(commit, commit_buffer);
+	repo_unuse_commit_buffer(the_repository, commit, commit_buffer);
 
 	for (i = 0, p = commit->parents; p; p = p->next) {
 		struct object *obj = &p->item->object;
@@ -732,7 +748,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
 	show_progress();
 }
 
-static char *anonymize_tag(void *data)
+static char *anonymize_tag(void)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
@@ -766,7 +782,8 @@ static void handle_tag(const char *name, struct tag *tag)
 		return;
 	}
 
-	buf = read_object_file(&tag->object.oid, &type, &size);
+	buf = repo_read_object_file(the_repository, &tag->object.oid, &type,
+				    &size);
 	if (!buf)
 		die("could not read tag %s", oid_to_hex(&tag->object.oid));
 	message = memmem(buf, size, "\n\n", 2);
@@ -794,7 +811,7 @@ static void handle_tag(const char *name, struct tag *tag)
 		if (message) {
 			static struct hashmap tags;
 			message = anonymize_str(&tags, anonymize_tag,
-						message, message_size, NULL);
+						message, message_size);
 			message_size = strlen(message);
 		}
 	}
@@ -917,7 +934,8 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
 		if (e->flags & UNINTERESTING)
 			continue;
 
-		if (dwim_ref(e->name, strlen(e->name), &oid, &full_name, 0) != 1)
+		if (repo_dwim_ref(the_repository, e->name, strlen(e->name),
+				  &oid, &full_name, 0) != 1)
 			continue;
 
 		if (refspecs.nr) {
@@ -1125,11 +1143,6 @@ static void handle_deletes(void)
 	}
 }
 
-static char *anonymize_seed(void *data)
-{
-	return xstrdup(data);
-}
-
 static int parse_opt_anonymize_map(const struct option *opt,
 				   const char *arg, int unset)
 {
@@ -1151,7 +1164,8 @@ static int parse_opt_anonymize_map(const struct option *opt,
 	if (!keylen || !*value)
 		return error(_("--anonymize-map token cannot be empty"));
 
-	anonymize_str(map, anonymize_seed, arg, keylen, (void *)value);
+	add_anonymized_entry(map, memhash(arg, keylen), arg, keylen,
+			     xstrdup(value));
 
 	return 0;
 }
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 7134683..bbd9b2b 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -1,5 +1,9 @@
 #include "builtin.h"
+#include "abspath.h"
 #include "cache.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "config.h"
 #include "lockfile.h"
@@ -15,11 +19,14 @@
 #include "dir.h"
 #include "run-command.h"
 #include "packfile.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "mem-pool.h"
 #include "commit-reach.h"
 #include "khash.h"
 #include "date.h"
+#include "wrapper.h"
 
 #define PACK_ID_BITS 16
 #define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
@@ -175,6 +182,7 @@ static FILE *pack_edges;
 static unsigned int show_stats = 1;
 static int global_argc;
 static const char **global_argv;
+static const char *global_prefix;
 
 /* Memory pools */
 static struct mem_pool fi_mem_pool = {
@@ -436,7 +444,7 @@ static void set_checkpoint_signal(void)
 
 #else
 
-static void checkpoint_signal(int signo)
+static void checkpoint_signal(int signo UNUSED)
 {
 	checkpoint_requested = 1;
 }
@@ -1265,7 +1273,7 @@ static void load_tree(struct tree_entry *root)
 			die("Can't load tree %s", oid_to_hex(oid));
 	} else {
 		enum object_type type;
-		buf = read_object_file(oid, &type, &size);
+		buf = repo_read_object_file(the_repository, oid, &type, &size);
 		if (!buf || type != OBJ_TREE)
 			die("Can't load tree %s", oid_to_hex(oid));
 	}
@@ -1625,7 +1633,7 @@ static int update_branch(struct branch *b)
 		if (!old_cmit || !new_cmit)
 			return error("Branch %s is missing commits.", b->name);
 
-		if (!in_merge_bases(old_cmit, new_cmit)) {
+		if (!repo_in_merge_bases(the_repository, old_cmit, new_cmit)) {
 			warning("Not updating %s"
 				" (new tip %s does not contain %s)",
 				b->name, oid_to_hex(&b->oid),
@@ -2486,7 +2494,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
 		if (commit_oe->type != OBJ_COMMIT)
 			die("Mark :%" PRIuMAX " not a commit", commit_mark);
 		oidcpy(&commit_oid, &commit_oe->idx.oid);
-	} else if (!get_oid(p, &commit_oid)) {
+	} else if (!repo_get_oid(the_repository, p, &commit_oid)) {
 		unsigned long size;
 		char *buf = read_object_with_reference(the_repository,
 						       &commit_oid,
@@ -2599,7 +2607,7 @@ static int parse_objectish(struct branch *b, const char *objectish)
 			} else
 				parse_from_existing(b);
 		}
-	} else if (!get_oid(objectish, &b->oid)) {
+	} else if (!repo_get_oid(the_repository, objectish, &b->oid)) {
 		parse_from_existing(b);
 		if (is_null_oid(&b->oid))
 			b->delete = 1;
@@ -2654,7 +2662,7 @@ static struct hash_list *parse_merge(unsigned int *count)
 			if (oe->type != OBJ_COMMIT)
 				die("Mark :%" PRIuMAX " not a commit", idnum);
 			oidcpy(&n->oid, &oe->idx.oid);
-		} else if (!get_oid(from, &n->oid)) {
+		} else if (!repo_get_oid(the_repository, from, &n->oid)) {
 			unsigned long size;
 			char *buf = read_object_with_reference(the_repository,
 							       &n->oid,
@@ -2827,7 +2835,7 @@ static void parse_new_tag(const char *arg)
 		oe = find_mark(marks, from_mark);
 		type = oe->type;
 		oidcpy(&oid, &oe->idx.oid);
-	} else if (!get_oid(from, &oid)) {
+	} else if (!repo_get_oid(the_repository, from, &oid)) {
 		struct object_entry *oe = find_object(&oid);
 		if (!oe) {
 			type = oid_object_info(the_repository, &oid, NULL);
@@ -2936,7 +2944,7 @@ static void cat_blob(struct object_entry *oe, struct object_id *oid)
 	char *buf;
 
 	if (!oe || oe->pack_id == MAX_PACK_ID) {
-		buf = read_object_file(oid, &type, &size);
+		buf = repo_read_object_file(the_repository, oid, &type, &size);
 	} else {
 		type = oe->type;
 		buf = gfi_unpack_entry(oe, &size);
@@ -3044,7 +3052,8 @@ static struct object_entry *dereference(struct object_entry *oe,
 		buf = gfi_unpack_entry(oe, &size);
 	} else {
 		enum object_type unused;
-		buf = read_object_file(oid, &unused, &size);
+		buf = repo_read_object_file(the_repository, oid, &unused,
+					    &size);
 	}
 	if (!buf)
 		die("Can't load object %s", oid_to_hex(oid));
@@ -3245,7 +3254,7 @@ static void parse_alias(void)
 static char* make_fast_import_path(const char *path)
 {
 	if (!relative_marks_paths || is_absolute_path(path))
-		return xstrdup(path);
+		return prefix_filename(global_prefix, path);
 	return git_pathdup("info/fast-import/%s", path);
 }
 
@@ -3316,9 +3325,11 @@ static void option_cat_blob_fd(const char *fd)
 
 static void option_export_pack_edges(const char *edges)
 {
+	char *fn = prefix_filename(global_prefix, edges);
 	if (pack_edges)
 		fclose(pack_edges);
-	pack_edges = xfopen(edges, "a");
+	pack_edges = xfopen(fn, "a");
+	free(fn);
 }
 
 static void option_rewrite_submodules(const char *arg, struct string_list *list)
@@ -3333,11 +3344,13 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list)
 	f++;
 	CALLOC_ARRAY(ms, 1);
 
+	f = prefix_filename(global_prefix, f);
 	fp = fopen(f, "r");
 	if (!fp)
 		die_errno("cannot read '%s'", f);
 	read_mark_file(&ms, fp, insert_oid_entry);
 	fclose(fp);
+	free(f);
 
 	string_list_insert(list, s)->util = ms;
 }
@@ -3551,6 +3564,7 @@ int cmd_fast_import(int argc, const char **argv, const char *prefix)
 
 	global_argc = argc;
 	global_argv = argv;
+	global_prefix = prefix;
 
 	rc_free = mem_pool_alloc(&fi_mem_pool, cmd_save * sizeof(*rc_free));
 	for (i = 0; i < (cmd_save - 1); i++)
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index afe6793..3ba0fe5 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -1,4 +1,8 @@
 #include "builtin.h"
+#include "alloc.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-file.h"
 #include "pkt-line.h"
 #include "fetch-pack.h"
 #include "remote.h"
@@ -40,7 +44,7 @@ static void add_sought_entry(struct ref ***sought, int *nr, int *alloc,
 	(*sought)[*nr - 1] = ref;
 }
 
-int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
+int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED)
 {
 	int i, ret;
 	struct ref *ref = NULL;
@@ -211,8 +215,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 		int flags = args.verbose ? CONNECT_VERBOSE : 0;
 		if (args.diag_url)
 			flags |= CONNECT_DIAG_URL;
-		conn = git_connect(fd, dest, args.uploadpack,
-				   flags);
+		conn = git_connect(fd, dest, "git-upload-pack",
+				   args.uploadpack, flags);
 		if (!conn)
 			return args.diag_url ? 0 : 1;
 	}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index a09606b..849a9be 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -2,12 +2,18 @@
  * "git fetch"
  */
 #include "cache.h"
+#include "advice.h"
 #include "config.h"
+#include "gettext.h"
+#include "environment.h"
+#include "hex.h"
 #include "repository.h"
 #include "refs.h"
 #include "refspec.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "oidset.h"
+#include "oid-array.h"
 #include "commit.h"
 #include "builtin.h"
 #include "string-list.h"
@@ -22,12 +28,16 @@
 #include "strvec.h"
 #include "utf8.h"
 #include "packfile.h"
+#include "pager.h"
+#include "pkt-line.h"
 #include "list-objects-filter-options.h"
 #include "commit-reach.h"
 #include "branch.h"
 #include "promisor-remote.h"
 #include "commit-graph.h"
 #include "shallow.h"
+#include "trace.h"
+#include "trace2.h"
 #include "worktree.h"
 #include "bundle-uri.h"
 
@@ -47,6 +57,23 @@ enum {
 	TAGS_SET = 2
 };
 
+enum display_format {
+	DISPLAY_FORMAT_UNKNOWN = 0,
+	DISPLAY_FORMAT_FULL,
+	DISPLAY_FORMAT_COMPACT,
+	DISPLAY_FORMAT_PORCELAIN,
+};
+
+struct display_state {
+	struct strbuf buf;
+
+	int refcol_width;
+	enum display_format format;
+
+	char *url;
+	int url_len, shown_url;
+};
+
 static int fetch_prune_config = -1; /* unspecified */
 static int fetch_show_forced_updates = 1;
 static uint64_t forced_updates_ms = 0;
@@ -58,13 +85,12 @@ static int fetch_prune_tags_config = -1; /* unspecified */
 static int prune_tags = -1; /* unspecified */
 #define PRUNE_TAGS_BY_DEFAULT 0 /* do we prune tags by default? */
 
-static int all, append, dry_run, force, keep, multiple, update_head_ok;
+static int append, dry_run, force, keep, update_head_ok;
 static int write_fetch_head = 1;
 static int verbosity, deepen_relative, set_upstream, refetch;
 static int progress = -1;
-static int enable_auto_gc = 1;
-static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
-static int max_jobs = -1, submodule_fetch_jobs_config = -1;
+static int tags = TAGS_DEFAULT, update_shallow, deepen;
+static int submodule_fetch_jobs_config = -1;
 static int fetch_parallel_config = 1;
 static int atomic_fetch;
 static enum transport_family family;
@@ -75,21 +101,20 @@ static struct string_list deepen_not = STRING_LIST_INIT_NODUP;
 static struct strbuf default_rla = STRBUF_INIT;
 static struct transport *gtransport;
 static struct transport *gsecondary;
-static const char *submodule_prefix = "";
 static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
-static int recurse_submodules_cli = RECURSE_SUBMODULES_DEFAULT;
-static int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND;
-static int shown_url = 0;
 static struct refspec refmap = REFSPEC_INIT_FETCH;
 static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT;
 static struct string_list server_options = STRING_LIST_INIT_DUP;
 static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
-static int fetch_write_commit_graph = -1;
-static int stdin_refspecs = 0;
-static int negotiate_only;
+
+struct fetch_config {
+	enum display_format display_format;
+};
 
 static int git_fetch_config(const char *k, const char *v, void *cb)
 {
+	struct fetch_config *fetch_config = cb;
+
 	if (!strcmp(k, "fetch.prune")) {
 		fetch_prune_config = git_config_bool(k, v);
 		return 0;
@@ -128,6 +153,18 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
 		return 0;
 	}
 
+	if (!strcmp(k, "fetch.output")) {
+		if (!v)
+			return config_error_nonbool(k);
+		else if (!strcasecmp(v, "full"))
+			fetch_config->display_format = DISPLAY_FORMAT_FULL;
+		else if (!strcasecmp(v, "compact"))
+			fetch_config->display_format = DISPLAY_FORMAT_COMPACT;
+		else
+			die(_("invalid value for '%s': '%s'"),
+			    "fetch.output", v);
+	}
+
 	return git_default_config(k, v, cb);
 }
 
@@ -144,92 +181,6 @@ static int parse_refmap_arg(const struct option *opt, const char *arg, int unset
 	return 0;
 }
 
-static struct option builtin_fetch_options[] = {
-	OPT__VERBOSITY(&verbosity),
-	OPT_BOOL(0, "all", &all,
-		 N_("fetch from all remotes")),
-	OPT_BOOL(0, "set-upstream", &set_upstream,
-		 N_("set upstream for git pull/fetch")),
-	OPT_BOOL('a', "append", &append,
-		 N_("append to .git/FETCH_HEAD instead of overwriting")),
-	OPT_BOOL(0, "atomic", &atomic_fetch,
-		 N_("use atomic transaction to update references")),
-	OPT_STRING(0, "upload-pack", &upload_pack, N_("path"),
-		   N_("path to upload pack on remote end")),
-	OPT__FORCE(&force, N_("force overwrite of local reference"), 0),
-	OPT_BOOL('m', "multiple", &multiple,
-		 N_("fetch from multiple remotes")),
-	OPT_SET_INT('t', "tags", &tags,
-		    N_("fetch all tags and associated objects"), TAGS_SET),
-	OPT_SET_INT('n', NULL, &tags,
-		    N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
-	OPT_INTEGER('j', "jobs", &max_jobs,
-		    N_("number of submodules fetched in parallel")),
-	OPT_BOOL(0, "prefetch", &prefetch,
-		 N_("modify the refspec to place all refs within refs/prefetch/")),
-	OPT_BOOL('p', "prune", &prune,
-		 N_("prune remote-tracking branches no longer on remote")),
-	OPT_BOOL('P', "prune-tags", &prune_tags,
-		 N_("prune local tags no longer on remote and clobber changed tags")),
-	OPT_CALLBACK_F(0, "recurse-submodules", &recurse_submodules_cli, N_("on-demand"),
-		    N_("control recursive fetching of submodules"),
-		    PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
-	OPT_BOOL(0, "dry-run", &dry_run,
-		 N_("dry run")),
-	OPT_BOOL(0, "write-fetch-head", &write_fetch_head,
-		 N_("write fetched references to the FETCH_HEAD file")),
-	OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")),
-	OPT_BOOL('u', "update-head-ok", &update_head_ok,
-		    N_("allow updating of HEAD ref")),
-	OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
-	OPT_STRING(0, "depth", &depth, N_("depth"),
-		   N_("deepen history of shallow clone")),
-	OPT_STRING(0, "shallow-since", &deepen_since, N_("time"),
-		   N_("deepen history of shallow repository based on time")),
-	OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"),
-			N_("deepen history of shallow clone, excluding rev")),
-	OPT_INTEGER(0, "deepen", &deepen_relative,
-		    N_("deepen history of shallow clone")),
-	OPT_SET_INT_F(0, "unshallow", &unshallow,
-		      N_("convert to a complete repository"),
-		      1, PARSE_OPT_NONEG),
-	OPT_SET_INT_F(0, "refetch", &refetch,
-		      N_("re-fetch without negotiating common commits"),
-		      1, PARSE_OPT_NONEG),
-	{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
-		   N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
-	OPT_CALLBACK_F(0, "recurse-submodules-default",
-		   &recurse_submodules_default, N_("on-demand"),
-		   N_("default for recursive fetching of submodules "
-		      "(lower priority than config files)"),
-		   PARSE_OPT_HIDDEN, option_fetch_parse_recurse_submodules),
-	OPT_BOOL(0, "update-shallow", &update_shallow,
-		 N_("accept refs that update .git/shallow")),
-	OPT_CALLBACK_F(0, "refmap", NULL, N_("refmap"),
-		       N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg),
-	OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
-	OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
-			TRANSPORT_FAMILY_IPV4),
-	OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
-			TRANSPORT_FAMILY_IPV6),
-	OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"),
-			N_("report that we have only objects reachable from this object")),
-	OPT_BOOL(0, "negotiate-only", &negotiate_only,
-		 N_("do not fetch a packfile; instead, print ancestors of negotiation tips")),
-	OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
-	OPT_BOOL(0, "auto-maintenance", &enable_auto_gc,
-		 N_("run 'maintenance --auto' after fetching")),
-	OPT_BOOL(0, "auto-gc", &enable_auto_gc,
-		 N_("run 'maintenance --auto' after fetching")),
-	OPT_BOOL(0, "show-forced-updates", &fetch_show_forced_updates,
-		 N_("check for forced-updates on all updated branches")),
-	OPT_BOOL(0, "write-commit-graph", &fetch_write_commit_graph,
-		 N_("write the commit-graph after fetching")),
-	OPT_BOOL(0, "stdin", &stdin_refspecs,
-		 N_("accept refspecs from stdin")),
-	OPT_END()
-};
-
 static void unlock_pack(unsigned int flags)
 {
 	if (gtransport)
@@ -407,9 +358,9 @@ static void find_non_local_tags(const struct ref *refs,
 		 */
 		if (ends_with(ref->name, "^{}")) {
 			if (item &&
-			    !has_object_file_with_flags(&ref->old_oid, quick_flags) &&
+			    !repo_has_object_file_with_flags(the_repository, &ref->old_oid, quick_flags) &&
 			    !oidset_contains(&fetch_oids, &ref->old_oid) &&
-			    !has_object_file_with_flags(&item->oid, quick_flags) &&
+			    !repo_has_object_file_with_flags(the_repository, &item->oid, quick_flags) &&
 			    !oidset_contains(&fetch_oids, &item->oid))
 				clear_item(item);
 			item = NULL;
@@ -423,7 +374,7 @@ static void find_non_local_tags(const struct ref *refs,
 		 * fetch.
 		 */
 		if (item &&
-		    !has_object_file_with_flags(&item->oid, quick_flags) &&
+		    !repo_has_object_file_with_flags(the_repository, &item->oid, quick_flags) &&
 		    !oidset_contains(&fetch_oids, &item->oid))
 			clear_item(item);
 
@@ -444,7 +395,7 @@ static void find_non_local_tags(const struct ref *refs,
 	 * checked to see if it needs fetching.
 	 */
 	if (item &&
-	    !has_object_file_with_flags(&item->oid, quick_flags) &&
+	    !repo_has_object_file_with_flags(the_repository, &item->oid, quick_flags) &&
 	    !oidset_contains(&fetch_oids, &item->oid))
 		clear_item(item);
 
@@ -741,76 +692,97 @@ static int s_update_ref(const char *action,
 	return ret;
 }
 
-static int refcol_width = 10;
-static int compact_format;
-
-static void adjust_refcol_width(const struct ref *ref)
+static int refcol_width(const struct ref *ref_map, int compact_format)
 {
-	int max, rlen, llen, len;
+	const struct ref *ref;
+	int max, width = 10;
 
-	/* uptodate lines are only shown on high verbosity level */
-	if (verbosity <= 0 && oideq(&ref->peer_ref->old_oid, &ref->old_oid))
-		return;
-
-	max    = term_columns();
-	rlen   = utf8_strwidth(prettify_refname(ref->name));
-
-	llen   = utf8_strwidth(prettify_refname(ref->peer_ref->name));
-
-	/*
-	 * rough estimation to see if the output line is too long and
-	 * should not be counted (we can't do precise calculation
-	 * anyway because we don't know if the error explanation part
-	 * will be printed in update_local_ref)
-	 */
-	if (compact_format) {
-		llen = 0;
+	max = term_columns();
+	if (compact_format)
 		max = max * 2 / 3;
-	}
-	len = 21 /* flag and summary */ + rlen + 4 /* -> */ + llen;
-	if (len >= max)
-		return;
 
-	/*
-	 * Not precise calculation for compact mode because '*' can
-	 * appear on the left hand side of '->' and shrink the column
-	 * back.
-	 */
-	if (refcol_width < rlen)
-		refcol_width = rlen;
+	for (ref = ref_map; ref; ref = ref->next) {
+		int rlen, llen = 0, len;
+
+		if (ref->status == REF_STATUS_REJECT_SHALLOW ||
+		    !ref->peer_ref ||
+		    !strcmp(ref->name, "HEAD"))
+			continue;
+
+		/* uptodate lines are only shown on high verbosity level */
+		if (verbosity <= 0 && oideq(&ref->peer_ref->old_oid, &ref->old_oid))
+			continue;
+
+		rlen = utf8_strwidth(prettify_refname(ref->name));
+		if (!compact_format)
+			llen = utf8_strwidth(prettify_refname(ref->peer_ref->name));
+
+		/*
+		 * rough estimation to see if the output line is too long and
+		 * should not be counted (we can't do precise calculation
+		 * anyway because we don't know if the error explanation part
+		 * will be printed in update_local_ref)
+		 */
+		len = 21 /* flag and summary */ + rlen + 4 /* -> */ + llen;
+		if (len >= max)
+			continue;
+
+		if (width < rlen)
+			width = rlen;
+	}
+
+	return width;
 }
 
-static void prepare_format_display(struct ref *ref_map)
+static void display_state_init(struct display_state *display_state, struct ref *ref_map,
+			       const char *raw_url, enum display_format format)
 {
-	struct ref *rm;
-	const char *format = "full";
+	int i;
+
+	memset(display_state, 0, sizeof(*display_state));
+	strbuf_init(&display_state->buf, 0);
+	display_state->format = format;
+
+	if (raw_url)
+		display_state->url = transport_anonymize_url(raw_url);
+	else
+		display_state->url = xstrdup("foreign");
+
+	display_state->url_len = strlen(display_state->url);
+	for (i = display_state->url_len - 1; display_state->url[i] == '/' && 0 <= i; i--)
+		;
+	display_state->url_len = i + 1;
+	if (4 < i && !strncmp(".git", display_state->url + i - 3, 4))
+		display_state->url_len = i - 3;
 
 	if (verbosity < 0)
 		return;
 
-	git_config_get_string_tmp("fetch.output", &format);
-	if (!strcasecmp(format, "full"))
-		compact_format = 0;
-	else if (!strcasecmp(format, "compact"))
-		compact_format = 1;
-	else
-		die(_("invalid value for '%s': '%s'"),
-		    "fetch.output", format);
-
-	for (rm = ref_map; rm; rm = rm->next) {
-		if (rm->status == REF_STATUS_REJECT_SHALLOW ||
-		    !rm->peer_ref ||
-		    !strcmp(rm->name, "HEAD"))
-			continue;
-
-		adjust_refcol_width(rm);
+	switch (display_state->format) {
+	case DISPLAY_FORMAT_FULL:
+	case DISPLAY_FORMAT_COMPACT:
+		display_state->refcol_width = refcol_width(ref_map,
+							   display_state->format == DISPLAY_FORMAT_COMPACT);
+		break;
+	case DISPLAY_FORMAT_PORCELAIN:
+		/* We don't need to precompute anything here. */
+		break;
+	default:
+		BUG("unexpected display format %d", display_state->format);
 	}
 }
 
-static void print_remote_to_local(struct strbuf *display,
+static void display_state_release(struct display_state *display_state)
+{
+	strbuf_release(&display_state->buf);
+	free(display_state->url);
+}
+
+static void print_remote_to_local(struct display_state *display_state,
 				  const char *remote, const char *local)
 {
-	strbuf_addf(display, "%-*s -> %s", refcol_width, remote, local);
+	strbuf_addf(&display_state->buf, "%-*s -> %s",
+		    display_state->refcol_width, remote, local);
 }
 
 static int find_and_replace(struct strbuf *haystack,
@@ -840,14 +812,14 @@ static int find_and_replace(struct strbuf *haystack,
 	return 1;
 }
 
-static void print_compact(struct strbuf *display,
+static void print_compact(struct display_state *display_state,
 			  const char *remote, const char *local)
 {
 	struct strbuf r = STRBUF_INIT;
 	struct strbuf l = STRBUF_INIT;
 
 	if (!strcmp(remote, local)) {
-		strbuf_addf(display, "%-*s -> *", refcol_width, remote);
+		strbuf_addf(&display_state->buf, "%-*s -> *", display_state->refcol_width, remote);
 		return;
 	}
 
@@ -856,40 +828,73 @@ static void print_compact(struct strbuf *display,
 
 	if (!find_and_replace(&r, local, "*"))
 		find_and_replace(&l, remote, "*");
-	print_remote_to_local(display, r.buf, l.buf);
+	print_remote_to_local(display_state, r.buf, l.buf);
 
 	strbuf_release(&r);
 	strbuf_release(&l);
 }
 
-static void format_display(struct strbuf *display, char code,
-			   const char *summary, const char *error,
-			   const char *remote, const char *local,
-			   int summary_width)
+static void display_ref_update(struct display_state *display_state, char code,
+			       const char *summary, const char *error,
+			       const char *remote, const char *local,
+			       const struct object_id *old_oid,
+			       const struct object_id *new_oid,
+			       int summary_width)
 {
-	int width;
+	FILE *f = stderr;
 
 	if (verbosity < 0)
 		return;
 
-	width = (summary_width + strlen(summary) - gettext_width(summary));
+	strbuf_reset(&display_state->buf);
 
-	strbuf_addf(display, "%c %-*s ", code, width, summary);
-	if (!compact_format)
-		print_remote_to_local(display, remote, local);
-	else
-		print_compact(display, remote, local);
-	if (error)
-		strbuf_addf(display, "  (%s)", error);
+	switch (display_state->format) {
+	case DISPLAY_FORMAT_FULL:
+	case DISPLAY_FORMAT_COMPACT: {
+		int width;
+
+		if (!display_state->shown_url) {
+			strbuf_addf(&display_state->buf, _("From %.*s\n"),
+				    display_state->url_len, display_state->url);
+			display_state->shown_url = 1;
+		}
+
+		width = (summary_width + strlen(summary) - gettext_width(summary));
+		remote = prettify_refname(remote);
+		local = prettify_refname(local);
+
+		strbuf_addf(&display_state->buf, " %c %-*s ", code, width, summary);
+
+		if (display_state->format != DISPLAY_FORMAT_COMPACT)
+			print_remote_to_local(display_state, remote, local);
+		else
+			print_compact(display_state, remote, local);
+
+		if (error)
+			strbuf_addf(&display_state->buf, "  (%s)", error);
+
+		break;
+	}
+	case DISPLAY_FORMAT_PORCELAIN:
+		strbuf_addf(&display_state->buf, "%c %s %s %s", code,
+			    oid_to_hex(old_oid), oid_to_hex(new_oid), local);
+		f = stdout;
+		break;
+	default:
+		BUG("unexpected display format %d", display_state->format);
+	};
+	strbuf_addch(&display_state->buf, '\n');
+
+	fputs(display_state->buf.buf, f);
 }
 
 static int update_local_ref(struct ref *ref,
 			    struct ref_transaction *transaction,
-			    const char *remote, const struct ref *remote_ref,
-			    struct strbuf *display, int summary_width)
+			    struct display_state *display_state,
+			    const struct ref *remote_ref,
+			    int summary_width)
 {
 	struct commit *current = NULL, *updated;
-	const char *pretty_ref = prettify_refname(ref->name);
 	int fast_forward = 0;
 
 	if (!repo_has_object_file(the_repository, &ref->new_oid))
@@ -897,8 +902,9 @@ static int update_local_ref(struct ref *ref,
 
 	if (oideq(&ref->old_oid, &ref->new_oid)) {
 		if (verbosity > 0)
-			format_display(display, '=', _("[up to date]"), NULL,
-				       remote, pretty_ref, summary_width);
+			display_ref_update(display_state, '=', _("[up to date]"), NULL,
+					   remote_ref->name, ref->name,
+					   &ref->old_oid, &ref->new_oid, summary_width);
 		return 0;
 	}
 
@@ -909,9 +915,10 @@ static int update_local_ref(struct ref *ref,
 		 * If this is the head, and it's not okay to update
 		 * the head, and the old value of the head isn't empty...
 		 */
-		format_display(display, '!', _("[rejected]"),
-			       _("can't fetch into checked-out branch"),
-			       remote, pretty_ref, summary_width);
+		display_ref_update(display_state, '!', _("[rejected]"),
+				   _("can't fetch into checked-out branch"),
+				   remote_ref->name, ref->name,
+				   &ref->old_oid, &ref->new_oid, summary_width);
 		return 1;
 	}
 
@@ -920,13 +927,16 @@ static int update_local_ref(struct ref *ref,
 		if (force || ref->force) {
 			int r;
 			r = s_update_ref("updating tag", ref, transaction, 0);
-			format_display(display, r ? '!' : 't', _("[tag update]"),
-				       r ? _("unable to update local ref") : NULL,
-				       remote, pretty_ref, summary_width);
+			display_ref_update(display_state, r ? '!' : 't', _("[tag update]"),
+					   r ? _("unable to update local ref") : NULL,
+					   remote_ref->name, ref->name,
+					   &ref->old_oid, &ref->new_oid, summary_width);
 			return r;
 		} else {
-			format_display(display, '!', _("[rejected]"), _("would clobber existing tag"),
-				       remote, pretty_ref, summary_width);
+			display_ref_update(display_state, '!', _("[rejected]"),
+					   _("would clobber existing tag"),
+					   remote_ref->name, ref->name,
+					   &ref->old_oid, &ref->new_oid, summary_width);
 			return 1;
 		}
 	}
@@ -957,15 +967,17 @@ static int update_local_ref(struct ref *ref,
 		}
 
 		r = s_update_ref(msg, ref, transaction, 0);
-		format_display(display, r ? '!' : '*', what,
-			       r ? _("unable to update local ref") : NULL,
-			       remote, pretty_ref, summary_width);
+		display_ref_update(display_state, r ? '!' : '*', what,
+				   r ? _("unable to update local ref") : NULL,
+				   remote_ref->name, ref->name,
+				   &ref->old_oid, &ref->new_oid, summary_width);
 		return r;
 	}
 
 	if (fetch_show_forced_updates) {
 		uint64_t t_before = getnanotime();
-		fast_forward = in_merge_bases(current, updated);
+		fast_forward = repo_in_merge_bases(the_repository, current,
+						   updated);
 		forced_updates_ms += (getnanotime() - t_before) / 1000000;
 	} else {
 		fast_forward = 1;
@@ -979,9 +991,10 @@ static int update_local_ref(struct ref *ref,
 		strbuf_addstr(&quickref, "..");
 		strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
 		r = s_update_ref("fast-forward", ref, transaction, 1);
-		format_display(display, r ? '!' : ' ', quickref.buf,
-			       r ? _("unable to update local ref") : NULL,
-			       remote, pretty_ref, summary_width);
+		display_ref_update(display_state, r ? '!' : ' ', quickref.buf,
+				   r ? _("unable to update local ref") : NULL,
+				   remote_ref->name, ref->name,
+				   &ref->old_oid, &ref->new_oid, summary_width);
 		strbuf_release(&quickref);
 		return r;
 	} else if (force || ref->force) {
@@ -991,14 +1004,16 @@ static int update_local_ref(struct ref *ref,
 		strbuf_addstr(&quickref, "...");
 		strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
 		r = s_update_ref("forced-update", ref, transaction, 1);
-		format_display(display, r ? '!' : '+', quickref.buf,
-			       r ? _("unable to update local ref") : _("forced update"),
-			       remote, pretty_ref, summary_width);
+		display_ref_update(display_state, r ? '!' : '+', quickref.buf,
+				   r ? _("unable to update local ref") : _("forced update"),
+				   remote_ref->name, ref->name,
+				   &ref->old_oid, &ref->new_oid, summary_width);
 		strbuf_release(&quickref);
 		return r;
 	} else {
-		format_display(display, '!', _("[rejected]"), _("non-fast-forward"),
-			       remote, pretty_ref, summary_width);
+		display_ref_update(display_state, '!', _("[rejected]"), _("non-fast-forward"),
+				   remote_ref->name, ref->name,
+				   &ref->old_oid, &ref->new_oid, summary_width);
 		return 1;
 	}
 }
@@ -1108,39 +1123,34 @@ N_("it took %.2f seconds to check forced updates; you can use\n"
    "'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates false'\n"
    "to avoid this check\n");
 
-static int store_updated_refs(const char *raw_url, const char *remote_name,
+static int store_updated_refs(struct display_state *display_state,
+			      const char *remote_name,
 			      int connectivity_checked,
 			      struct ref_transaction *transaction, struct ref *ref_map,
 			      struct fetch_head *fetch_head)
 {
-	int url_len, i, rc = 0;
+	int rc = 0;
 	struct strbuf note = STRBUF_INIT;
 	const char *what, *kind;
 	struct ref *rm;
-	char *url;
 	int want_status;
 	int summary_width = 0;
 
 	if (verbosity >= 0)
 		summary_width = transport_summary_width(ref_map);
 
-	if (raw_url)
-		url = transport_anonymize_url(raw_url);
-	else
-		url = xstrdup("foreign");
-
 	if (!connectivity_checked) {
 		struct check_connected_options opt = CHECK_CONNECTED_INIT;
 
+		opt.exclude_hidden_refs_section = "fetch";
 		rm = ref_map;
 		if (check_connected(iterate_ref_map, &rm, &opt)) {
-			rc = error(_("%s did not send all necessary objects\n"), url);
+			rc = error(_("%s did not send all necessary objects\n"),
+				   display_state->url);
 			goto abort;
 		}
 	}
 
-	prepare_format_display(ref_map);
-
 	/*
 	 * We do a pass for each fetch_head_status type in their enum order, so
 	 * merged entries are written before not-for-merge. That lets readers
@@ -1208,25 +1218,17 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
 			if (!strcmp(rm->name, "HEAD")) {
 				kind = "";
 				what = "";
-			}
-			else if (skip_prefix(rm->name, "refs/heads/", &what))
+			} else if (skip_prefix(rm->name, "refs/heads/", &what)) {
 				kind = "branch";
-			else if (skip_prefix(rm->name, "refs/tags/", &what))
+			} else if (skip_prefix(rm->name, "refs/tags/", &what)) {
 				kind = "tag";
-			else if (skip_prefix(rm->name, "refs/remotes/", &what))
+			} else if (skip_prefix(rm->name, "refs/remotes/", &what)) {
 				kind = "remote-tracking branch";
-			else {
+			} else {
 				kind = "";
 				what = rm->name;
 			}
 
-			url_len = strlen(url);
-			for (i = url_len - 1; url[i] == '/' && 0 <= i; i--)
-				;
-			url_len = i + 1;
-			if (4 < i && !strncmp(".git", url + i - 3, 4))
-				url_len = i - 3;
-
 			strbuf_reset(&note);
 			if (*what) {
 				if (*kind)
@@ -1236,12 +1238,12 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
 
 			append_fetch_head(fetch_head, &rm->old_oid,
 					  rm->fetch_head_status,
-					  note.buf, url, url_len);
+					  note.buf, display_state->url,
+					  display_state->url_len);
 
-			strbuf_reset(&note);
 			if (ref) {
-				rc |= update_local_ref(ref, transaction, what,
-						       rm, &note, summary_width);
+				rc |= update_local_ref(ref, transaction, display_state,
+						       rm, summary_width);
 				free(ref);
 			} else if (write_fetch_head || dry_run) {
 				/*
@@ -1249,18 +1251,12 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
 				 * would be written to FETCH_HEAD, if --dry-run
 				 * is set).
 				 */
-				format_display(&note, '*',
-					       *kind ? kind : "branch", NULL,
-					       *what ? what : "HEAD",
-					       "FETCH_HEAD", summary_width);
-			}
-			if (note.len) {
-				if (!shown_url) {
-					fprintf(stderr, _("From %.*s\n"),
-							url_len, url);
-					shown_url = 1;
-				}
-				fprintf(stderr, " %s\n", note.buf);
+				display_ref_update(display_state, '*',
+						   *kind ? kind : "branch", NULL,
+						   rm->name,
+						   "FETCH_HEAD",
+						   &rm->new_oid, &rm->old_oid,
+						   summary_width);
 			}
 		}
 	}
@@ -1281,7 +1277,6 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
 
  abort:
 	strbuf_release(&note);
-	free(url);
 	return rc;
 }
 
@@ -1319,16 +1314,18 @@ static int check_exist_and_connected(struct ref *ref_map)
 	 * we need all direct targets to exist.
 	 */
 	for (r = rm; r; r = r->next) {
-		if (!has_object_file_with_flags(&r->old_oid,
-						OBJECT_INFO_SKIP_FETCH_OBJECT))
+		if (!repo_has_object_file_with_flags(the_repository, &r->old_oid,
+						     OBJECT_INFO_SKIP_FETCH_OBJECT))
 			return -1;
 	}
 
 	opt.quiet = 1;
+	opt.exclude_hidden_refs_section = "fetch";
 	return check_connected(iterate_ref_map, &rm, &opt);
 }
 
-static int fetch_and_consume_refs(struct transport *transport,
+static int fetch_and_consume_refs(struct display_state *display_state,
+				  struct transport *transport,
 				  struct ref_transaction *transaction,
 				  struct ref *ref_map,
 				  struct fetch_head *fetch_head)
@@ -1352,7 +1349,7 @@ static int fetch_and_consume_refs(struct transport *transport,
 	}
 
 	trace2_region_enter("fetch", "consume_refs", the_repository);
-	ret = store_updated_refs(transport->url, transport->remote->name,
+	ret = store_updated_refs(display_state, transport->remote->name,
 				 connectivity_checked, transaction, ref_map,
 				 fetch_head);
 	trace2_region_leave("fetch", "consume_refs", the_repository);
@@ -1362,32 +1359,18 @@ static int fetch_and_consume_refs(struct transport *transport,
 	return ret;
 }
 
-static int prune_refs(struct refspec *rs,
+static int prune_refs(struct display_state *display_state,
+		      struct refspec *rs,
 		      struct ref_transaction *transaction,
-		      struct ref *ref_map,
-		      const char *raw_url)
+		      struct ref *ref_map)
 {
-	int url_len, i, result = 0;
+	int result = 0;
 	struct ref *ref, *stale_refs = get_stale_heads(rs, ref_map);
 	struct strbuf err = STRBUF_INIT;
-	char *url;
 	const char *dangling_msg = dry_run
 		? _("   (%s will become dangling)")
 		: _("   (%s has become dangling)");
 
-	if (raw_url)
-		url = transport_anonymize_url(raw_url);
-	else
-		url = xstrdup("foreign");
-
-	url_len = strlen(url);
-	for (i = url_len - 1; url[i] == '/' && 0 <= i; i--)
-		;
-
-	url_len = i + 1;
-	if (4 < i && !strncmp(".git", url + i - 3, 4))
-		url_len = i - 3;
-
 	if (!dry_run) {
 		if (transaction) {
 			for (ref = stale_refs; ref; ref = ref->next) {
@@ -1411,23 +1394,16 @@ static int prune_refs(struct refspec *rs,
 		int summary_width = transport_summary_width(stale_refs);
 
 		for (ref = stale_refs; ref; ref = ref->next) {
-			struct strbuf sb = STRBUF_INIT;
-			if (!shown_url) {
-				fprintf(stderr, _("From %.*s\n"), url_len, url);
-				shown_url = 1;
-			}
-			format_display(&sb, '-', _("[deleted]"), NULL,
-				       _("(none)"), prettify_refname(ref->name),
-				       summary_width);
-			fprintf(stderr, " %s\n",sb.buf);
-			strbuf_release(&sb);
+			display_ref_update(display_state, '-', _("[deleted]"), NULL,
+					   _("(none)"), ref->name,
+					   &ref->new_oid, &ref->old_oid,
+					   summary_width);
 			warn_dangling_symref(stderr, dangling_msg, ref->name);
 		}
 	}
 
 cleanup:
 	strbuf_release(&err);
-	free(url);
 	free_refs(stale_refs);
 	return result;
 }
@@ -1487,7 +1463,7 @@ static void add_negotiation_tips(struct git_transport_options *smart_options)
 		int old_nr;
 		if (!has_glob_specials(s)) {
 			struct object_id oid;
-			if (get_oid(s, &oid))
+			if (repo_get_oid(the_repository, s, &oid))
 				die(_("%s is not a valid object"), s);
 			if (!has_object(the_repository, &oid, 0))
 				die(_("the object %s does not exist"), s);
@@ -1542,7 +1518,8 @@ static struct transport *prepare_transport(struct remote *remote, int deepen)
 	return transport;
 }
 
-static int backfill_tags(struct transport *transport,
+static int backfill_tags(struct display_state *display_state,
+			 struct transport *transport,
 			 struct ref_transaction *transaction,
 			 struct ref *ref_map,
 			 struct fetch_head *fetch_head)
@@ -1566,7 +1543,7 @@ static int backfill_tags(struct transport *transport,
 	transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
 	transport_set_option(transport, TRANS_OPT_DEPTH, "0");
 	transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
-	retcode = fetch_and_consume_refs(transport, transaction, ref_map, fetch_head);
+	retcode = fetch_and_consume_refs(display_state, transport, transaction, ref_map, fetch_head);
 
 	if (gsecondary) {
 		transport_disconnect(gsecondary);
@@ -1577,10 +1554,12 @@ static int backfill_tags(struct transport *transport,
 }
 
 static int do_fetch(struct transport *transport,
-		    struct refspec *rs)
+		    struct refspec *rs,
+		    enum display_format display_format)
 {
 	struct ref_transaction *transaction = NULL;
 	struct ref *ref_map = NULL;
+	struct display_state display_state = { 0 };
 	int autotags = (transport->remote->fetch_tags == 1);
 	int retcode = 0;
 	const struct ref *remote_refs;
@@ -1662,6 +1641,8 @@ static int do_fetch(struct transport *transport,
 	if (retcode)
 		goto cleanup;
 
+	display_state_init(&display_state, ref_map, transport->url, display_format);
+
 	if (atomic_fetch) {
 		transaction = ref_transaction_begin(&err);
 		if (!transaction) {
@@ -1679,17 +1660,16 @@ static int do_fetch(struct transport *transport,
 		 * don't care whether --tags was specified.
 		 */
 		if (rs->nr) {
-			retcode = prune_refs(rs, transaction, ref_map, transport->url);
+			retcode = prune_refs(&display_state, rs, transaction, ref_map);
 		} else {
-			retcode = prune_refs(&transport->remote->fetch,
-					     transaction, ref_map,
-					     transport->url);
+			retcode = prune_refs(&display_state, &transport->remote->fetch,
+					     transaction, ref_map);
 		}
 		if (retcode != 0)
 			retcode = 1;
 	}
 
-	if (fetch_and_consume_refs(transport, transaction, ref_map, &fetch_head)) {
+	if (fetch_and_consume_refs(&display_state, transport, transaction, ref_map, &fetch_head)) {
 		retcode = 1;
 		goto cleanup;
 	}
@@ -1711,7 +1691,7 @@ static int do_fetch(struct transport *transport,
 			 * when `--atomic` is passed: in that case we'll abort
 			 * the transaction and don't commit anything.
 			 */
-			if (backfill_tags(transport, transaction, tags_ref_map,
+			if (backfill_tags(&display_state, transport, transaction, tags_ref_map,
 					  &fetch_head))
 				retcode = 1;
 		}
@@ -1794,6 +1774,7 @@ static int do_fetch(struct transport *transport,
 		error("%s", err.buf);
 	}
 
+	display_state_release(&display_state);
 	close_fetch_head(&fetch_head);
 	strbuf_release(&err);
 	free_refs(ref_map);
@@ -1848,7 +1829,8 @@ static int add_remote_or_group(const char *name, struct string_list *list)
 	return 1;
 }
 
-static void add_options_to_argv(struct strvec *argv)
+static void add_options_to_argv(struct strvec *argv,
+				enum display_format format)
 {
 	if (dry_run)
 		strvec_push(argv, "--dry-run");
@@ -1864,6 +1846,8 @@ static void add_options_to_argv(struct strvec *argv)
 		strvec_push(argv, "--keep");
 	if (recurse_submodules == RECURSE_SUBMODULES_ON)
 		strvec_push(argv, "--recurse-submodules");
+	else if (recurse_submodules == RECURSE_SUBMODULES_OFF)
+		strvec_push(argv, "--no-recurse-submodules");
 	else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
 		strvec_push(argv, "--recurse-submodules=on-demand");
 	if (tags == TAGS_SET)
@@ -1880,6 +1864,10 @@ static void add_options_to_argv(struct strvec *argv)
 		strvec_push(argv, "--ipv4");
 	else if (family == TRANSPORT_FAMILY_IPV6)
 		strvec_push(argv, "--ipv6");
+	if (!write_fetch_head)
+		strvec_push(argv, "--no-write-fetch-head");
+	if (format == DISPLAY_FORMAT_PORCELAIN)
+		strvec_pushf(argv, "--porcelain");
 }
 
 /* Fetch multiple remotes in parallel */
@@ -1888,9 +1876,11 @@ struct parallel_fetch_state {
 	const char **argv;
 	struct string_list *remotes;
 	int next, result;
+	enum display_format format;
 };
 
-static int fetch_next_remote(struct child_process *cp, struct strbuf *out,
+static int fetch_next_remote(struct child_process *cp,
+			     struct strbuf *out UNUSED,
 			     void *cb, void **task_cb)
 {
 	struct parallel_fetch_state *state = cb;
@@ -1906,13 +1896,14 @@ static int fetch_next_remote(struct child_process *cp, struct strbuf *out,
 	strvec_push(&cp->args, remote);
 	cp->git_cmd = 1;
 
-	if (verbosity >= 0)
+	if (verbosity >= 0 && state->format != DISPLAY_FORMAT_PORCELAIN)
 		printf(_("Fetching %s\n"), remote);
 
 	return 1;
 }
 
-static int fetch_failed_to_start(struct strbuf *out, void *cb, void *task_cb)
+static int fetch_failed_to_start(struct strbuf *out UNUSED,
+				 void *cb, void *task_cb)
 {
 	struct parallel_fetch_state *state = cb;
 	const char *remote = task_cb;
@@ -1937,7 +1928,8 @@ static int fetch_finished(int result, struct strbuf *out,
 	return 0;
 }
 
-static int fetch_multiple(struct string_list *list, int max_children)
+static int fetch_multiple(struct string_list *list, int max_children,
+			  enum display_format format)
 {
 	int i, result = 0;
 	struct strvec argv = STRVEC_INIT;
@@ -1948,12 +1940,17 @@ static int fetch_multiple(struct string_list *list, int max_children)
 			return errcode;
 	}
 
-	strvec_pushl(&argv, "fetch", "--append", "--no-auto-gc",
+	/*
+	 * Cancel out the fetch.bundleURI config when running subprocesses,
+	 * to avoid fetching from the same bundle list multiple times.
+	 */
+	strvec_pushl(&argv, "-c", "fetch.bundleURI=",
+		     "fetch", "--append", "--no-auto-gc",
 		     "--no-write-commit-graph", NULL);
-	add_options_to_argv(&argv);
+	add_options_to_argv(&argv, format);
 
 	if (max_children != 1 && list->nr != 1) {
-		struct parallel_fetch_state state = { argv.v, list, 0, 0 };
+		struct parallel_fetch_state state = { argv.v, list, 0, 0, format };
 		const struct run_process_parallel_opts opts = {
 			.tr2_category = "fetch",
 			.tr2_label = "parallel/fetch",
@@ -1977,7 +1974,7 @@ static int fetch_multiple(struct string_list *list, int max_children)
 
 			strvec_pushv(&cmd.args, argv.v);
 			strvec_push(&cmd.args, name);
-			if (verbosity >= 0)
+			if (verbosity >= 0 && format != DISPLAY_FORMAT_PORCELAIN)
 				printf(_("Fetching %s\n"), name);
 			cmd.git_cmd = 1;
 			if (run_command(&cmd)) {
@@ -2007,7 +2004,7 @@ static inline void fetch_one_setup_partial(struct remote *remote)
 	 * If no prior partial clone/fetch and the current fetch DID NOT
 	 * request a partial-fetch, do a normal fetch.
 	 */
-	if (!has_promisor_remote() && !filter_options.choice)
+	if (!repo_has_promisor_remote(the_repository) && !filter_options.choice)
 		return;
 
 	/*
@@ -2032,7 +2029,8 @@ static inline void fetch_one_setup_partial(struct remote *remote)
 }
 
 static int fetch_one(struct remote *remote, int argc, const char **argv,
-		     int prune_tags_ok, int use_stdin_refspecs)
+		     int prune_tags_ok, int use_stdin_refspecs,
+		     enum display_format display_format)
 {
 	struct refspec rs = REFSPEC_INIT_FETCH;
 	int i;
@@ -2099,7 +2097,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv,
 	sigchain_push_common(unlock_pack_on_signal);
 	atexit(unlock_pack_atexit);
 	sigchain_push(SIGPIPE, SIG_IGN);
-	exit_code = do_fetch(gtransport, &rs);
+	exit_code = do_fetch(gtransport, &rs, display_format);
 	sigchain_pop(SIGPIPE);
 	refspec_clear(&rs);
 	transport_disconnect(gtransport);
@@ -2109,12 +2107,113 @@ static int fetch_one(struct remote *remote, int argc, const char **argv,
 
 int cmd_fetch(int argc, const char **argv, const char *prefix)
 {
-	int i;
+	struct fetch_config config = {
+		.display_format = DISPLAY_FORMAT_FULL,
+	};
+	const char *submodule_prefix = "";
 	const char *bundle_uri;
 	struct string_list list = STRING_LIST_INIT_DUP;
 	struct remote *remote = NULL;
+	int all = 0, multiple = 0;
 	int result = 0;
 	int prune_tags_ok = 1;
+	int enable_auto_gc = 1;
+	int unshallow = 0;
+	int max_jobs = -1;
+	int recurse_submodules_cli = RECURSE_SUBMODULES_DEFAULT;
+	int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND;
+	int fetch_write_commit_graph = -1;
+	int stdin_refspecs = 0;
+	int negotiate_only = 0;
+	int porcelain = 0;
+	int i;
+
+	struct option builtin_fetch_options[] = {
+		OPT__VERBOSITY(&verbosity),
+		OPT_BOOL(0, "all", &all,
+			 N_("fetch from all remotes")),
+		OPT_BOOL(0, "set-upstream", &set_upstream,
+			 N_("set upstream for git pull/fetch")),
+		OPT_BOOL('a', "append", &append,
+			 N_("append to .git/FETCH_HEAD instead of overwriting")),
+		OPT_BOOL(0, "atomic", &atomic_fetch,
+			 N_("use atomic transaction to update references")),
+		OPT_STRING(0, "upload-pack", &upload_pack, N_("path"),
+			   N_("path to upload pack on remote end")),
+		OPT__FORCE(&force, N_("force overwrite of local reference"), 0),
+		OPT_BOOL('m', "multiple", &multiple,
+			 N_("fetch from multiple remotes")),
+		OPT_SET_INT('t', "tags", &tags,
+			    N_("fetch all tags and associated objects"), TAGS_SET),
+		OPT_SET_INT('n', NULL, &tags,
+			    N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
+		OPT_INTEGER('j', "jobs", &max_jobs,
+			    N_("number of submodules fetched in parallel")),
+		OPT_BOOL(0, "prefetch", &prefetch,
+			 N_("modify the refspec to place all refs within refs/prefetch/")),
+		OPT_BOOL('p', "prune", &prune,
+			 N_("prune remote-tracking branches no longer on remote")),
+		OPT_BOOL('P', "prune-tags", &prune_tags,
+			 N_("prune local tags no longer on remote and clobber changed tags")),
+		OPT_CALLBACK_F(0, "recurse-submodules", &recurse_submodules_cli, N_("on-demand"),
+			    N_("control recursive fetching of submodules"),
+			    PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
+		OPT_BOOL(0, "dry-run", &dry_run,
+			 N_("dry run")),
+		OPT_BOOL(0, "porcelain", &porcelain, N_("machine-readable output")),
+		OPT_BOOL(0, "write-fetch-head", &write_fetch_head,
+			 N_("write fetched references to the FETCH_HEAD file")),
+		OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")),
+		OPT_BOOL('u', "update-head-ok", &update_head_ok,
+			    N_("allow updating of HEAD ref")),
+		OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
+		OPT_STRING(0, "depth", &depth, N_("depth"),
+			   N_("deepen history of shallow clone")),
+		OPT_STRING(0, "shallow-since", &deepen_since, N_("time"),
+			   N_("deepen history of shallow repository based on time")),
+		OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"),
+				N_("deepen history of shallow clone, excluding rev")),
+		OPT_INTEGER(0, "deepen", &deepen_relative,
+			    N_("deepen history of shallow clone")),
+		OPT_SET_INT_F(0, "unshallow", &unshallow,
+			      N_("convert to a complete repository"),
+			      1, PARSE_OPT_NONEG),
+		OPT_SET_INT_F(0, "refetch", &refetch,
+			      N_("re-fetch without negotiating common commits"),
+			      1, PARSE_OPT_NONEG),
+		{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
+			   N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
+		OPT_CALLBACK_F(0, "recurse-submodules-default",
+			   &recurse_submodules_default, N_("on-demand"),
+			   N_("default for recursive fetching of submodules "
+			      "(lower priority than config files)"),
+			   PARSE_OPT_HIDDEN, option_fetch_parse_recurse_submodules),
+		OPT_BOOL(0, "update-shallow", &update_shallow,
+			 N_("accept refs that update .git/shallow")),
+		OPT_CALLBACK_F(0, "refmap", NULL, N_("refmap"),
+			       N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg),
+		OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
+		OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
+				TRANSPORT_FAMILY_IPV4),
+		OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
+				TRANSPORT_FAMILY_IPV6),
+		OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"),
+				N_("report that we have only objects reachable from this object")),
+		OPT_BOOL(0, "negotiate-only", &negotiate_only,
+			 N_("do not fetch a packfile; instead, print ancestors of negotiation tips")),
+		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
+		OPT_BOOL(0, "auto-maintenance", &enable_auto_gc,
+			 N_("run 'maintenance --auto' after fetching")),
+		OPT_BOOL(0, "auto-gc", &enable_auto_gc,
+			 N_("run 'maintenance --auto' after fetching")),
+		OPT_BOOL(0, "show-forced-updates", &fetch_show_forced_updates,
+			 N_("check for forced-updates on all updated branches")),
+		OPT_BOOL(0, "write-commit-graph", &fetch_write_commit_graph,
+			 N_("write the commit-graph after fetching")),
+		OPT_BOOL(0, "stdin", &stdin_refspecs,
+			 N_("accept refspecs from stdin")),
+		OPT_END()
+	};
 
 	packet_trace_identity("fetch");
 
@@ -2128,7 +2227,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		free(anon);
 	}
 
-	git_config(git_fetch_config, NULL);
+	git_config(git_fetch_config, &config);
 	if (the_repository->gitdir) {
 		prepare_repo_settings(the_repository);
 		the_repository->settings.command_requires_full_index = 0;
@@ -2167,6 +2266,26 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		fetch_config_from_gitmodules(sfjc, rs);
 	}
 
+
+	if (porcelain) {
+		switch (recurse_submodules_cli) {
+		case RECURSE_SUBMODULES_OFF:
+		case RECURSE_SUBMODULES_DEFAULT:
+			/*
+			 * Reference updates in submodules would be ambiguous
+			 * in porcelain mode, so we reject this combination.
+			 */
+			recurse_submodules = RECURSE_SUBMODULES_OFF;
+			break;
+
+		default:
+			die(_("options '%s' and '%s' cannot be used together"),
+			    "--porcelain", "--recurse-submodules");
+		}
+
+		config.display_format = DISPLAY_FORMAT_PORCELAIN;
+	}
+
 	if (negotiate_only && !negotiation_tip.nr)
 		die(_("--negotiate-only needs one or more --negotiation-tip=*"));
 
@@ -2263,9 +2382,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 			printf("%s\n", oid_to_hex(oid));
 		oidset_clear(&acked_commits);
 	} else if (remote) {
-		if (filter_options.choice || has_promisor_remote())
+		if (filter_options.choice || repo_has_promisor_remote(the_repository))
 			fetch_one_setup_partial(remote);
-		result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs);
+		result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs,
+				   config.display_format);
 	} else {
 		int max_children = max_jobs;
 
@@ -2285,10 +2405,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 			max_children = fetch_parallel_config;
 
 		/* TODO should this also die if we have a previous partial-clone? */
-		result = fetch_multiple(&list, max_children);
+		result = fetch_multiple(&list, max_children, config.display_format);
 	}
 
-
 	/*
 	 * This is only needed after fetch_one(), which does not fetch
 	 * submodules by itself.
@@ -2307,7 +2426,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		if (max_children < 0)
 			max_children = fetch_parallel_config;
 
-		add_options_to_argv(&options);
+		add_options_to_argv(&options, config.display_format);
 		result = fetch_submodules(the_repository,
 					  &options,
 					  submodule_prefix,
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 8d8fd39..cc81241 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -1,7 +1,9 @@
 #include "builtin.h"
 #include "config.h"
 #include "fmt-merge-msg.h"
+#include "gettext.h"
 #include "parse-options.h"
+#include "wrapper.h"
 
 static const char * const fmt_merge_msg_usage[] = {
 	N_("git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]"),
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 6f62f40..695fc8f 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -1,10 +1,13 @@
 #include "builtin.h"
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
 #include "refs.h"
 #include "object.h"
 #include "parse-options.h"
 #include "ref-filter.h"
+#include "strvec.h"
+#include "commit-reach.h"
 
 static char const * const for_each_ref_usage[] = {
 	N_("git for-each-ref [<options>] [<pattern>]"),
@@ -19,12 +22,14 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 	int i;
 	struct ref_sorting *sorting;
 	struct string_list sorting_options = STRING_LIST_INIT_DUP;
-	int maxcount = 0, icase = 0;
+	int maxcount = 0, icase = 0, omit_empty = 0;
 	struct ref_array array;
 	struct ref_filter filter;
 	struct ref_format format = REF_FORMAT_INIT;
 	struct strbuf output = STRBUF_INIT;
 	struct strbuf err = STRBUF_INIT;
+	int from_stdin = 0;
+	struct strvec vec = STRVEC_INIT;
 
 	struct option opts[] = {
 		OPT_BIT('s', "shell", &format.quote_style,
@@ -35,6 +40,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 			N_("quote placeholders suitably for python"), QUOTE_PYTHON),
 		OPT_BIT(0 , "tcl",  &format.quote_style,
 			N_("quote placeholders suitably for Tcl"), QUOTE_TCL),
+		OPT_BOOL(0, "omit-empty",  &omit_empty,
+			N_("do not output a newline after empty formatted refs")),
 
 		OPT_GROUP(""),
 		OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
@@ -49,6 +56,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 		OPT_CONTAINS(&filter.with_commit, N_("print only refs which contain the commit")),
 		OPT_NO_CONTAINS(&filter.no_commit, N_("print only refs which don't contain the commit")),
 		OPT_BOOL(0, "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
+		OPT_BOOL(0, "stdin", &from_stdin, N_("read reference patterns from stdin")),
 		OPT_END(),
 	};
 
@@ -75,9 +83,27 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 	ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);
 	filter.ignore_case = icase;
 
-	filter.name_patterns = argv;
+	if (from_stdin) {
+		struct strbuf line = STRBUF_INIT;
+
+		if (argv[0])
+			die(_("unknown arguments supplied with --stdin"));
+
+		while (strbuf_getline(&line, stdin) != EOF)
+			strvec_push(&vec, line.buf);
+
+		strbuf_release(&line);
+
+		/* vec.v is NULL-terminated, just like 'argv'. */
+		filter.name_patterns = vec.v;
+	} else {
+		filter.name_patterns = argv;
+	}
+
 	filter.match_as_path = 1;
 	filter_refs(&array, &filter, FILTER_REFS_ALL);
+	filter_ahead_behind(the_repository, &format, &array);
+
 	ref_array_sort(sorting, &array);
 
 	if (!maxcount || array.nr < maxcount)
@@ -88,7 +114,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 		if (format_ref_array_item(array.items[i], &format, &output, &err))
 			die("%s", err.buf);
 		fwrite(output.buf, 1, output.len, stdout);
-		putchar('\n');
+		if (output.len || !omit_empty)
+			putchar('\n');
 	}
 
 	strbuf_release(&err);
@@ -97,5 +124,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 	free_commit_list(filter.with_commit);
 	free_commit_list(filter.no_commit);
 	ref_sorting_release(sorting);
+	strvec_clear(&vec);
 	return 0;
 }
diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c
index 6aeac37..37daf7b 100644
--- a/builtin/for-each-repo.c
+++ b/builtin/for-each-repo.c
@@ -1,7 +1,10 @@
 #include "cache.h"
 #include "config.h"
 #include "builtin.h"
+#include "gettext.h"
 #include "parse-options.h"
+#include "path.h"
+#include "repository.h"
 #include "run-command.h"
 #include "string-list.h"
 
@@ -32,6 +35,7 @@ int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
 	static const char *config_key = NULL;
 	int i, result = 0;
 	const struct string_list *values;
+	int err;
 
 	const struct option options[] = {
 		OPT_STRING(0, "config", &config_key, N_("config"),
@@ -45,14 +49,11 @@ int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
 	if (!config_key)
 		die(_("missing --config=<config>"));
 
-	values = repo_config_get_value_multi(the_repository,
-					     config_key);
-
-	/*
-	 * Do nothing on an empty list, which is equivalent to the case
-	 * where the config variable does not exist at all.
-	 */
-	if (!values)
+	err = repo_config_get_string_multi(the_repository, config_key, &values);
+	if (err < 0)
+		usage_msg_optf(_("got bad config --config=%s"),
+			       for_each_repo_usage, options, config_key);
+	else if (err)
 		return 0;
 
 	for (i = 0; !result && i < values->nr; i++)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index d207bd9..dcc165b 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -1,6 +1,7 @@
-#define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
 #include "cache.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "config.h"
 #include "commit.h"
@@ -18,10 +19,15 @@
 #include "streaming.h"
 #include "decorate.h"
 #include "packfile.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
+#include "replace-object.h"
 #include "resolve-undo.h"
 #include "run-command.h"
 #include "worktree.h"
+#include "pack-revindex.h"
+#include "pack-bitmap.h"
 
 #define REACHABLE 0x0001
 #define SEEN      0x0002
@@ -51,6 +57,8 @@ static int name_objects;
 #define ERROR_REFS 010
 #define ERROR_COMMIT_GRAPH 020
 #define ERROR_MULTI_PACK_INDEX 040
+#define ERROR_PACK_REV_INDEX 0100
+#define ERROR_BITMAP 0200
 
 static const char *describe_object(const struct object_id *oid)
 {
@@ -233,17 +241,17 @@ static void mark_unreachable_referents(const struct object_id *oid)
 }
 
 static int mark_loose_unreachable_referents(const struct object_id *oid,
-					    const char *path,
-					    void *data)
+					    const char *path UNUSED,
+					    void *data UNUSED)
 {
 	mark_unreachable_referents(oid);
 	return 0;
 }
 
 static int mark_packed_unreachable_referents(const struct object_id *oid,
-					     struct packed_git *pack,
-					     uint32_t pos,
-					     void *data)
+					     struct packed_git *pack UNUSED,
+					     uint32_t pos UNUSED,
+					     void *data UNUSED)
 {
 	mark_unreachable_referents(oid);
 	return 0;
@@ -661,14 +669,15 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)
 	return 0; /* keep checking other objects, even if we saw an error */
 }
 
-static int fsck_cruft(const char *basename, const char *path, void *data)
+static int fsck_cruft(const char *basename, const char *path,
+		      void *data UNUSED)
 {
 	if (!starts_with(basename, "tmp_obj_"))
 		fprintf_ln(stderr, _("bad sha1 file: %s"), path);
 	return 0;
 }
 
-static int fsck_subdir(unsigned int nr, const char *path, void *data)
+static int fsck_subdir(unsigned int nr, const char *path UNUSED, void *data)
 {
 	struct for_each_loose_cb *cb_data = data;
 	struct progress *progress = cb_data->progress;
@@ -732,19 +741,19 @@ static int fsck_head_link(const char *head_ref_name,
 	return 0;
 }
 
-static int fsck_cache_tree(struct cache_tree *it)
+static int fsck_cache_tree(struct cache_tree *it, const char *index_path)
 {
 	int i;
 	int err = 0;
 
 	if (verbose)
-		fprintf_ln(stderr, _("Checking cache tree"));
+		fprintf_ln(stderr, _("Checking cache tree of %s"), index_path);
 
 	if (0 <= it->entry_count) {
 		struct object *obj = parse_object(the_repository, &it->oid);
 		if (!obj) {
-			error(_("%s: invalid sha1 pointer in cache-tree"),
-			      oid_to_hex(&it->oid));
+			error(_("%s: invalid sha1 pointer in cache-tree of %s"),
+			      oid_to_hex(&it->oid), index_path);
 			errors_found |= ERROR_REFS;
 			return 1;
 		}
@@ -755,11 +764,12 @@ static int fsck_cache_tree(struct cache_tree *it)
 			err |= objerror(obj, _("non-tree in cache-tree"));
 	}
 	for (i = 0; i < it->subtree_nr; i++)
-		err |= fsck_cache_tree(it->down[i]->cache_tree);
+		err |= fsck_cache_tree(it->down[i]->cache_tree, index_path);
 	return err;
 }
 
-static int fsck_resolve_undo(struct index_state *istate)
+static int fsck_resolve_undo(struct index_state *istate,
+			     const char *index_path)
 {
 	struct string_list_item *item;
 	struct string_list *resolve_undo = istate->resolve_undo;
@@ -782,8 +792,9 @@ static int fsck_resolve_undo(struct index_state *istate)
 
 			obj = parse_object(the_repository, &ru->oid[i]);
 			if (!obj) {
-				error(_("%s: invalid sha1 pointer in resolve-undo"),
-				      oid_to_hex(&ru->oid[i]));
+				error(_("%s: invalid sha1 pointer in resolve-undo of %s"),
+				      oid_to_hex(&ru->oid[i]),
+				      index_path);
 				errors_found |= ERROR_REFS;
 				continue;
 			}
@@ -796,6 +807,38 @@ static int fsck_resolve_undo(struct index_state *istate)
 	return 0;
 }
 
+static void fsck_index(struct index_state *istate, const char *index_path,
+		       int is_main_index)
+{
+	unsigned int i;
+
+	/* TODO: audit for interaction with sparse-index. */
+	ensure_full_index(istate);
+	for (i = 0; i < istate->cache_nr; i++) {
+		unsigned int mode;
+		struct blob *blob;
+		struct object *obj;
+
+		mode = istate->cache[i]->ce_mode;
+		if (S_ISGITLINK(mode))
+			continue;
+		blob = lookup_blob(the_repository,
+				   &istate->cache[i]->oid);
+		if (!blob)
+			continue;
+		obj = &blob->object;
+		obj->flags |= USED;
+		fsck_put_object_name(&fsck_walk_options, &obj->oid,
+				     "%s:%s",
+				     is_main_index ? "" : index_path,
+				     istate->cache[i]->name);
+		mark_object_reachable(obj);
+	}
+	if (istate->cache_tree)
+		fsck_cache_tree(istate->cache_tree, index_path);
+	fsck_resolve_undo(istate, index_path);
+}
+
 static void mark_object_for_connectivity(const struct object_id *oid)
 {
 	struct object *obj = lookup_unknown_object(the_repository, oid);
@@ -803,22 +846,54 @@ static void mark_object_for_connectivity(const struct object_id *oid)
 }
 
 static int mark_loose_for_connectivity(const struct object_id *oid,
-				       const char *path,
-				       void *data)
+				       const char *path UNUSED,
+				       void *data UNUSED)
 {
 	mark_object_for_connectivity(oid);
 	return 0;
 }
 
 static int mark_packed_for_connectivity(const struct object_id *oid,
-					struct packed_git *pack,
-					uint32_t pos,
-					void *data)
+					struct packed_git *pack UNUSED,
+					uint32_t pos UNUSED,
+					void *data UNUSED)
 {
 	mark_object_for_connectivity(oid);
 	return 0;
 }
 
+static int check_pack_rev_indexes(struct repository *r, int show_progress)
+{
+	struct progress *progress = NULL;
+	uint32_t pack_count = 0;
+	int res = 0;
+
+	if (show_progress) {
+		for (struct packed_git *p = get_all_packs(r); p; p = p->next)
+			pack_count++;
+		progress = start_delayed_progress("Verifying reverse pack-indexes", pack_count);
+		pack_count = 0;
+	}
+
+	for (struct packed_git *p = get_all_packs(r); p; p = p->next) {
+		int load_error = load_pack_revindex_from_disk(p);
+
+		if (load_error < 0) {
+			error(_("unable to load rev-index for pack '%s'"), p->pack_name);
+			res = ERROR_PACK_REV_INDEX;
+		} else if (!load_error &&
+			   !load_pack_revindex(r, p) &&
+			   verify_pack_revindex(p)) {
+			error(_("invalid rev-index for pack '%s'"), p->pack_name);
+			res = ERROR_PACK_REV_INDEX;
+		}
+		display_progress(progress, ++pack_count);
+	}
+	stop_progress(&progress);
+
+	return res;
+}
+
 static char const * const fsck_usage[] = {
 	N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
 	   "         [--[no-]full] [--strict] [--verbose] [--lost-found]\n"
@@ -923,7 +998,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 	for (i = 0; i < argc; i++) {
 		const char *arg = argv[i];
 		struct object_id oid;
-		if (!get_oid(arg, &oid)) {
+		if (!repo_get_oid(the_repository, arg, &oid)) {
 			struct object *obj = lookup_object(the_repository,
 							   &oid);
 
@@ -956,34 +1031,36 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 	}
 
 	if (keep_cache_objects) {
+		struct worktree **worktrees, **p;
+
 		verify_index_checksum = 1;
 		verify_ce_order = 1;
-		repo_read_index(the_repository);
-		/* TODO: audit for interaction with sparse-index. */
-		ensure_full_index(&the_index);
-		for (i = 0; i < the_index.cache_nr; i++) {
-			unsigned int mode;
-			struct blob *blob;
-			struct object *obj;
 
-			mode = the_index.cache[i]->ce_mode;
-			if (S_ISGITLINK(mode))
-				continue;
-			blob = lookup_blob(the_repository,
-					   &the_index.cache[i]->oid);
-			if (!blob)
-				continue;
-			obj = &blob->object;
-			obj->flags |= USED;
-			fsck_put_object_name(&fsck_walk_options, &obj->oid,
-					     ":%s", the_index.cache[i]->name);
-			mark_object_reachable(obj);
+		worktrees = get_worktrees();
+		for (p = worktrees; *p; p++) {
+			struct worktree *wt = *p;
+			struct index_state istate =
+				INDEX_STATE_INIT(the_repository);
+			char *path;
+
+			/*
+			 * Make a copy since the buffer is reusable
+			 * and may get overwritten by other calls
+			 * while we're examining the index.
+			 */
+			path = xstrdup(worktree_git_path(wt, "index"));
+			read_index_from(&istate, path, get_worktree_git_dir(wt));
+			fsck_index(&istate, path, wt->is_current);
+			discard_index(&istate);
+			free(path);
 		}
-		if (the_index.cache_tree)
-			fsck_cache_tree(the_index.cache_tree);
-		fsck_resolve_undo(&the_index);
+		free_worktrees(worktrees);
 	}
 
+	errors_found |= check_pack_rev_indexes(the_repository, show_progress);
+	if (verify_bitmap_files(the_repository))
+		errors_found |= ERROR_BITMAP;
+
 	check_connectivity();
 
 	if (the_repository->settings.core_commit_graph) {
diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c
index 0feef8c..f6dd9a7 100644
--- a/builtin/fsmonitor--daemon.c
+++ b/builtin/fsmonitor--daemon.c
@@ -1,5 +1,9 @@
 #include "builtin.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
 #include "parse-options.h"
 #include "fsmonitor.h"
 #include "fsmonitor-ipc.h"
@@ -10,6 +14,7 @@
 #include "simple-ipc.h"
 #include "khash.h"
 #include "pkt-line.h"
+#include "trace2.h"
 
 static const char * const builtin_fsmonitor__daemon_usage[] = {
 	N_("git fsmonitor--daemon start [<options>]"),
@@ -1574,7 +1579,7 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
 }
 
 #else
-int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
+int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix UNUSED)
 {
 	struct option options[] = {
 		OPT_END()
diff --git a/builtin/gc.c b/builtin/gc.c
index 02455fd..f394218 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -11,6 +11,10 @@
  */
 
 #include "builtin.h"
+#include "abspath.h"
+#include "date.h"
+#include "environment.h"
+#include "hex.h"
 #include "repository.h"
 #include "config.h"
 #include "tempfile.h"
@@ -22,6 +26,7 @@
 #include "commit.h"
 #include "commit-graph.h"
 #include "packfile.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "pack.h"
 #include "pack-objects.h"
@@ -31,7 +36,11 @@
 #include "refs.h"
 #include "remote.h"
 #include "exec-cmd.h"
+#include "gettext.h"
 #include "hook.h"
+#include "setup.h"
+#include "trace2.h"
+#include "wrapper.h"
 
 #define FAILED_RUN "failed to run %s"
 
@@ -42,7 +51,7 @@ static const char * const builtin_gc_usage[] = {
 
 static int pack_refs = 1;
 static int prune_reflogs = 1;
-static int cruft_packs = -1;
+static int cruft_packs = 1;
 static int aggressive_depth = 50;
 static int aggressive_window = 250;
 static int gc_auto_threshold = 6700;
@@ -213,7 +222,7 @@ static struct packed_git *find_base_packs(struct string_list *packs,
 	struct packed_git *p, *base = NULL;
 
 	for (p = get_all_packs(the_repository); p; p = p->next) {
-		if (!p->pack_local)
+		if (!p->pack_local || p->is_cruft)
 			continue;
 		if (limit) {
 			if (p->pack_size >= limit)
@@ -284,7 +293,7 @@ static uint64_t total_ram(void)
 
 static uint64_t estimate_repack_memory(struct packed_git *pack)
 {
-	unsigned long nr_objects = approximate_object_count();
+	unsigned long nr_objects = repo_approximate_object_count(the_repository);
 	size_t os_cache, heap;
 
 	if (!pack || !nr_objects)
@@ -602,10 +611,6 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 	if (prune_expire && parse_expiry_date(prune_expire, &dummy))
 		die(_("failed to parse prune expiry value %s"), prune_expire);
 
-	prepare_repo_settings(the_repository);
-	if (cruft_packs < 0)
-		cruft_packs = the_repository->settings.gc_cruft_packs;
-
 	if (aggressive) {
 		strvec_push(&repack, "-f");
 		if (aggressive_depth > 0)
@@ -699,7 +704,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 			strvec_push(&prune, prune_expire);
 			if (quiet)
 				strvec_push(&prune, "--no-progress");
-			if (has_promisor_remote())
+			if (repo_has_promisor_remote(the_repository))
 				strvec_push(&prune,
 					    "--exclude-promisor-objects");
 			prune_cmd.git_cmd = 1;
@@ -820,7 +825,7 @@ static int dfs_on_ref(const char *refname UNUSED,
 	commit = lookup_commit(the_repository, oid);
 	if (!commit)
 		return 0;
-	if (parse_commit(commit) ||
+	if (repo_parse_commit(the_repository, commit) ||
 	    commit_graph_position(commit) != COMMIT_NOT_FROM_GRAPH)
 		return 0;
 
@@ -837,7 +842,7 @@ static int dfs_on_ref(const char *refname UNUSED,
 		commit = pop_commit(&stack);
 
 		for (parent = commit->parents; parent; parent = parent->next) {
-			if (parse_commit(parent->item) ||
+			if (repo_parse_commit(the_repository, parent->item) ||
 			    commit_graph_position(parent->item) != COMMIT_NOT_FROM_GRAPH ||
 			    parent->item->object.flags & SEEN)
 				continue;
@@ -976,9 +981,9 @@ struct write_loose_object_data {
 
 static int loose_object_auto_limit = 100;
 
-static int loose_object_count(const struct object_id *oid,
-			       const char *path,
-			       void *data)
+static int loose_object_count(const struct object_id *oid UNUSED,
+			      const char *path UNUSED,
+			      void *data)
 {
 	int *count = (int*)data;
 	if (++(*count) >= loose_object_auto_limit)
@@ -1003,15 +1008,15 @@ static int loose_object_auto_condition(void)
 					     NULL, NULL, &count);
 }
 
-static int bail_on_loose(const struct object_id *oid,
-			 const char *path,
-			 void *data)
+static int bail_on_loose(const struct object_id *oid UNUSED,
+			 const char *path UNUSED,
+			 void *data UNUSED)
 {
 	return 1;
 }
 
 static int write_loose_object_to_stdin(const struct object_id *oid,
-				       const char *path,
+				       const char *path UNUSED,
 				       void *data)
 {
 	struct write_loose_object_data *d = (struct write_loose_object_data *)data;
@@ -1493,7 +1498,6 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)
 	};
 	int found = 0;
 	const char *key = "maintenance.repo";
-	char *config_value;
 	char *maintpath = get_maintpath();
 	struct string_list_item *item;
 	const struct string_list *list;
@@ -1508,13 +1512,10 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)
 	git_config_set("maintenance.auto", "false");
 
 	/* Set maintenance strategy, if unset */
-	if (!git_config_get_string("maintenance.strategy", &config_value))
-		free(config_value);
-	else
+	if (git_config_get("maintenance.strategy"))
 		git_config_set("maintenance.strategy", "incremental");
 
-	list = git_config_get_value_multi(key);
-	if (list) {
+	if (!git_config_get_string_multi(key, &list)) {
 		for_each_string_list_item(item, list) {
 			if (!strcmp(maintpath, item->string)) {
 				found = 1;
@@ -1580,11 +1581,10 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi
 	if (config_file) {
 		git_configset_init(&cs);
 		git_configset_add_file(&cs, config_file);
-		list = git_configset_get_value_multi(&cs, key);
-	} else {
-		list = git_config_get_value_multi(key);
 	}
-	if (list) {
+	if (!(config_file
+	      ? git_configset_get_string_multi(&cs, key, &list)
+	      : git_config_get_string_multi(key, &list))) {
 		for_each_string_list_item(item, list) {
 			if (!strcmp(maintpath, item->string)) {
 				found = 1;
@@ -1686,11 +1686,11 @@ static int get_schedule_cmd(const char **cmd, int *is_available)
 	if (is_available)
 		*is_available = 0;
 
-	string_list_split_in_place(&list, testing, ',', -1);
+	string_list_split_in_place(&list, testing, ",", -1);
 	for_each_string_list_item(item, &list) {
 		struct string_list pair = STRING_LIST_INIT_NODUP;
 
-		if (string_list_split_in_place(&pair, item->string, ':', 2) != 2)
+		if (string_list_split_in_place(&pair, item->string, ":", 2) != 2)
 			continue;
 
 		if (!strcmp(*cmd, pair.items[0].string)) {
diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c
index 491af92..564cfca 100644
--- a/builtin/get-tar-commit-id.c
+++ b/builtin/get-tar-commit-id.c
@@ -6,6 +6,7 @@
 #include "tar.h"
 #include "builtin.h"
 #include "quote.h"
+#include "wrapper.h"
 
 static const char builtin_get_tar_commit_id_usage[] =
 "git get-tar-commit-id";
@@ -14,7 +15,7 @@ static const char builtin_get_tar_commit_id_usage[] =
 #define RECORDSIZE	(512)
 #define HEADERSIZE (2 * RECORDSIZE)
 
-int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
+int cmd_get_tar_commit_id(int argc, const char **argv UNUSED, const char *prefix)
 {
 	char buffer[HEADERSIZE];
 	struct ustar_header *header = (struct ustar_header *)buffer;
@@ -24,6 +25,8 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
 	long len;
 	char *end;
 
+	BUG_ON_NON_EMPTY_PREFIX(prefix);
+
 	if (argc != 1)
 		usage(builtin_get_tar_commit_id_usage);
 
@@ -32,7 +35,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
 		die_errno("git get-tar-commit-id: read error");
 	if (n != HEADERSIZE)
 		die_errno("git get-tar-commit-id: EOF before reading tar header");
-	if (header->typeflag[0] != 'g')
+	if (header->typeflag[0] != TYPEFLAG_GLOBAL_HEADER)
 		return 1;
 
 	len = strtol(content, &end, 10);
diff --git a/builtin/grep.c b/builtin/grep.c
index f7821c5..b86c754 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -4,6 +4,9 @@
  * Copyright (c) 2006 Junio C Hamano
  */
 #include "cache.h"
+#include "alloc.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "config.h"
 #include "blob.h"
@@ -20,10 +23,15 @@
 #include "quote.h"
 #include "dir.h"
 #include "pathspec.h"
+#include "setup.h"
 #include "submodule.h"
 #include "submodule-config.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "packfile.h"
+#include "pager.h"
+#include "write-or-die.h"
 
 static const char *grep_prefix;
 
@@ -560,7 +568,8 @@ static int grep_cache(struct grep_opt *opt,
 			void *data;
 			unsigned long size;
 
-			data = read_object_file(&ce->oid, &type, &size);
+			data = repo_read_object_file(the_repository, &ce->oid,
+						     &type, &size);
 			init_tree_desc(&tree, data, size);
 
 			hit |= grep_tree(opt, pathspec, &tree, &name, 0, 0);
@@ -650,7 +659,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 			void *data;
 			unsigned long size;
 
-			data = read_object_file(&entry.oid, &type, &size);
+			data = repo_read_object_file(the_repository,
+						     &entry.oid, &type, &size);
 			if (!data)
 				die(_("unable to read tree (%s)"),
 				    oid_to_hex(&entry.oid));
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 44db83f..a380121 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -5,12 +5,18 @@
  * Copyright (C) Junio C Hamano, 2005
  */
 #include "builtin.h"
+#include "abspath.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "blob.h"
 #include "quote.h"
 #include "parse-options.h"
 #include "exec-cmd.h"
+#include "setup.h"
+#include "write-or-die.h"
 
 /*
  * This is to create corrupt objects for debugging and as such it
diff --git a/builtin/help.c b/builtin/help.c
index 53f2812..d3cf4af 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -5,11 +5,15 @@
 #include "config.h"
 #include "builtin.h"
 #include "exec-cmd.h"
+#include "gettext.h"
+#include "pager.h"
 #include "parse-options.h"
+#include "path.h"
 #include "run-command.h"
 #include "config-list.h"
 #include "help.h"
 #include "alias.h"
+#include "setup.h"
 
 #ifndef DEFAULT_HELP_FORMAT
 #define DEFAULT_HELP_FORMAT "man"
diff --git a/builtin/hook.c b/builtin/hook.c
index f95b796..8805179 100644
--- a/builtin/hook.c
+++ b/builtin/hook.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "builtin.h"
 #include "config.h"
+#include "gettext.h"
 #include "hook.h"
 #include "parse-options.h"
 #include "strbuf.h"
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 6648f2d..bb67e16 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1,6 +1,10 @@
 #include "builtin.h"
+#include "alloc.h"
 #include "config.h"
 #include "delta.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "pack.h"
 #include "csum-file.h"
 #include "blob.h"
@@ -13,8 +17,14 @@
 #include "streaming.h"
 #include "thread-utils.h"
 #include "packfile.h"
+#include "pack-revindex.h"
+#include "object-file.h"
 #include "object-store.h"
+#include "oid-array.h"
+#include "replace-object.h"
 #include "promisor-remote.h"
+#include "setup.h"
+#include "wrapper.h"
 
 static const char index_pack_usage[] =
 "git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
@@ -801,7 +811,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
 	if (startup_info->have_repository) {
 		read_lock();
 		collision_test_needed =
-			has_object_file_with_flags(oid, OBJECT_INFO_QUICK);
+			repo_has_object_file_with_flags(the_repository, oid,
+							OBJECT_INFO_QUICK);
 		read_unlock();
 	}
 
@@ -821,7 +832,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
 			die(_("cannot read existing object info %s"), oid_to_hex(oid));
 		if (has_type != type || has_size != size)
 			die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid));
-		has_data = read_object_file(oid, &has_type, &has_size);
+		has_data = repo_read_object_file(the_repository, oid,
+						 &has_type, &has_size);
 		read_unlock();
 		if (!data)
 			data = new_data = get_data_from_pack(obj_entry);
@@ -1388,7 +1400,7 @@ static void fix_unresolved_deltas(struct hashfile *f)
 		sorted_by_pos[i] = &ref_deltas[i];
 	QSORT(sorted_by_pos, nr_ref_deltas, delta_pos_compare);
 
-	if (has_promisor_remote()) {
+	if (repo_has_promisor_remote(the_repository)) {
 		/*
 		 * Prefetch the delta bases.
 		 */
@@ -1414,7 +1426,8 @@ static void fix_unresolved_deltas(struct hashfile *f)
 
 		if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
 			continue;
-		data = read_object_file(&d->oid, &type, &size);
+		data = repo_read_object_file(the_repository, &d->oid, &type,
+					     &size);
 		if (!data)
 			continue;
 
@@ -1743,12 +1756,13 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	fsck_options.walk = mark_link;
 
 	reset_pack_idx_option(&opts);
+	opts.flags |= WRITE_REV;
 	git_config(git_index_pack_config, &opts);
 	if (prefix && chdir(prefix))
 		die(_("Cannot come back to cwd"));
 
-	if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0))
-		rev_index = 1;
+	if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0))
+		rev_index = 0;
 	else
 		rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV));
 
diff --git a/builtin/init-db.c b/builtin/init-db.c
index dcaaf10..aef4036 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -4,12 +4,20 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "abspath.h"
 #include "config.h"
+#include "copy.h"
+#include "environment.h"
+#include "gettext.h"
 #include "refs.h"
 #include "builtin.h"
 #include "exec-cmd.h"
+#include "object-file.h"
 #include "parse-options.h"
+#include "path.h"
+#include "setup.h"
 #include "worktree.h"
+#include "wrapper.h"
 
 #ifndef DEFAULT_GIT_TEMPLATE_DIR
 #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index e58627c..107ac28 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -7,6 +7,7 @@
 
 #include "cache.h"
 #include "builtin.h"
+#include "gettext.h"
 #include "parse-options.h"
 #include "string-list.h"
 #include "trailer.h"
diff --git a/builtin/log.c b/builtin/log.c
index a70fba1..676de10 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -4,10 +4,18 @@
  * (C) Copyright 2006 Linus Torvalds
  *		 2006 Junio Hamano
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
+#include "pager.h"
 #include "color.h"
 #include "commit.h"
 #include "diff.h"
@@ -15,6 +23,7 @@
 #include "revision.h"
 #include "log-tree.h"
 #include "builtin.h"
+#include "oid-array.h"
 #include "tag.h"
 #include "reflog-walk.h"
 #include "patch-ids.h"
@@ -35,6 +44,8 @@
 #include "commit-reach.h"
 #include "range-diff.h"
 #include "tmp-objdir.h"
+#include "tree.h"
+#include "write-or-die.h"
 
 #define MAIL_DEFAULT_WRAP 72
 #define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100
@@ -56,6 +67,7 @@ static int stdout_mboxrd;
 static const char *fmt_patch_subject_prefix = "PATCH";
 static int fmt_patch_name_max = FORMAT_PATCH_NAME_MAX_DEFAULT;
 static const char *fmt_pretty;
+static int format_no_prefix;
 
 static const char * const builtin_log_usage[] = {
 	N_("git log [<options>] [<revision-range>] [[--] <path>...]"),
@@ -182,10 +194,10 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f
 	int i;
 	char *value = NULL;
 	struct string_list *include = decoration_filter->include_ref_pattern;
-	const struct string_list *config_exclude =
-			git_config_get_value_multi("log.excludeDecoration");
+	const struct string_list *config_exclude;
 
-	if (config_exclude) {
+	if (!git_config_get_string_multi("log.excludeDecoration",
+					 &config_exclude)) {
 		struct string_list_item *item;
 		for_each_string_list_item(item, config_exclude)
 			string_list_append(decoration_filter->exclude_ref_config_pattern,
@@ -436,7 +448,7 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list)
 	setitimer(ITIMER_REAL, &early_output_timer, NULL);
 }
 
-static void early_output(int signal)
+static void early_output(int signal UNUSED)
 {
 	show_early_output = log_show_early;
 }
@@ -601,8 +613,6 @@ static int git_log_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
-	if (git_gpg_config(var, value, cb) < 0)
-		return -1;
 	return git_diff_ui_config(var, value, cb);
 }
 
@@ -675,7 +685,7 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
 {
 	unsigned long size;
 	enum object_type type;
-	char *buf = read_object_file(oid, &type, &size);
+	char *buf = repo_read_object_file(the_repository, oid, &type, &size);
 	int offset = 0;
 
 	if (!buf)
@@ -1084,6 +1094,19 @@ static int git_format_config(const char *var, const char *value, void *cb)
 		stdout_mboxrd = git_config_bool(var, value);
 		return 0;
 	}
+	if (!strcmp(var, "format.noprefix")) {
+		format_no_prefix = 1;
+		return 0;
+	}
+
+	/*
+	 * ignore some porcelain config which would otherwise be parsed by
+	 * git_diff_ui_config(), via git_log_config(); we can't just avoid
+	 * diff_ui_config completely, because we do care about some ui options
+	 * like color.
+	 */
+	if (!strcmp(var, "diff.noprefix"))
+		return 0;
 
 	return git_log_config(var, value, cb);
 }
@@ -1204,7 +1227,8 @@ static char *find_branch_name(struct rev_info *rev)
 		return NULL;
 	ref = rev->cmdline.rev[positive].name;
 	tip_oid = &rev->cmdline.rev[positive].item->oid;
-	if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref, 0) &&
+	if (repo_dwim_ref(the_repository, ref, strlen(ref), &branch_oid,
+			  &full_ref, 0) &&
 	    skip_prefix(full_ref, "refs/heads/", &v) &&
 	    oideq(tip_oid, &branch_oid))
 		branch = xstrdup(v);
@@ -1314,10 +1338,11 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
 	log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte, 0);
 
 	for (i = 0; !need_8bit_cte && i < nr; i++) {
-		const char *buf = get_commit_buffer(list[i], NULL);
+		const char *buf = repo_get_commit_buffer(the_repository,
+							 list[i], NULL);
 		if (has_non_ascii(buf))
 			need_8bit_cte = 1;
-		unuse_commit_buffer(list[i], buf);
+		repo_unuse_commit_buffer(the_repository, list[i], buf);
 	}
 
 	if (!branch_name)
@@ -1370,7 +1395,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
 			.other_arg = &other_arg
 		};
 
-		diff_setup(&opts);
+		repo_diff_setup(the_repository, &opts);
 		opts.file = rev->diffopt.file;
 		opts.use_color = rev->diffopt.use_color;
 		diff_setup_done(&opts);
@@ -1642,14 +1667,16 @@ static struct commit *get_base_commit(const char *base_commit,
 			struct commit *commit;
 			struct object_id oid;
 
-			if (get_oid(upstream, &oid)) {
+			if (repo_get_oid(the_repository, upstream, &oid)) {
 				if (die_on_failure)
 					die(_("failed to resolve '%s' as a valid ref"), upstream);
 				else
 					return NULL;
 			}
 			commit = lookup_commit_or_die(&oid, "upstream base");
-			base_list = get_merge_bases_many(commit, total, list);
+			base_list = repo_get_merge_bases_many(the_repository,
+							      commit, total,
+							      list);
 			/* There should be one and only one merge base. */
 			if (!base_list || base_list->next) {
 				if (die_on_failure) {
@@ -1683,7 +1710,9 @@ static struct commit *get_base_commit(const char *base_commit,
 	while (rev_nr > 1) {
 		for (i = 0; i < rev_nr / 2; i++) {
 			struct commit_list *merge_base;
-			merge_base = get_merge_bases(rev[2 * i], rev[2 * i + 1]);
+			merge_base = repo_get_merge_bases(the_repository,
+							  rev[2 * i],
+							  rev[2 * i + 1]);
 			if (!merge_base || merge_base->next) {
 				if (die_on_failure) {
 					die(_("failed to find exact merge base"));
@@ -1701,7 +1730,7 @@ static struct commit *get_base_commit(const char *base_commit,
 		rev_nr = DIV_ROUND_UP(rev_nr, 2);
 	}
 
-	if (!in_merge_bases(base, rev[0])) {
+	if (!repo_in_merge_bases(the_repository, base, rev[0])) {
 		if (die_on_failure) {
 			die(_("base commit should be the ancestor of revision list"));
 		} else {
@@ -1993,6 +2022,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	s_r_opt.def = "HEAD";
 	s_r_opt.revarg_opt = REVARG_COMMITTISH;
 
+	if (format_no_prefix)
+		diff_set_noprefix(&rev.diffopt);
+
 	if (default_attach) {
 		rev.mime_boundary = default_attach;
 		rev.no_inline = 1;
@@ -2097,6 +2129,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 
 	/* Always generate a patch */
 	rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
+	rev.always_show_header = 1;
 
 	rev.zero_commit = zero_commit;
 	rev.patch_name_max = fmt_patch_name_max;
@@ -2396,7 +2429,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
 {
 	struct object_id oid;
-	if (get_oid(arg, &oid) == 0) {
+	if (repo_get_oid(the_repository, arg, &oid) == 0) {
 		struct commit *commit = lookup_commit_reference(the_repository,
 								&oid);
 		if (commit) {
@@ -2418,12 +2451,12 @@ static void print_commit(char sign, struct commit *commit, int verbose,
 {
 	if (!verbose) {
 		fprintf(file, "%c %s\n", sign,
-		       find_unique_abbrev(&commit->object.oid, abbrev));
+		       repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev));
 	} else {
 		struct strbuf buf = STRBUF_INIT;
 		pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
 		fprintf(file, "%c %s %s\n", sign,
-		       find_unique_abbrev(&commit->object.oid, abbrev),
+		       repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev),
 		       buf.buf);
 		strbuf_release(&buf);
 	}
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index a03b559..625f48f 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -8,9 +8,12 @@
 #include "cache.h"
 #include "repository.h"
 #include "config.h"
+#include "convert.h"
 #include "quote.h"
 #include "dir.h"
 #include "builtin.h"
+#include "gettext.h"
+#include "object-name.h"
 #include "strbuf.h"
 #include "tree.h"
 #include "cache-tree.h"
@@ -19,6 +22,7 @@
 #include "string-list.h"
 #include "pathspec.h"
 #include "run-command.h"
+#include "setup.h"
 #include "submodule.h"
 #include "submodule-config.h"
 
@@ -89,12 +93,15 @@ static void write_name(const char *name)
 
 static void write_name_to_buf(struct strbuf *sb, const char *name)
 {
-	const char *rel = relative_path(name, prefix_len ? prefix : NULL, sb);
+	struct strbuf buf = STRBUF_INIT;
+	const char *rel = relative_path(name, prefix_len ? prefix : NULL, &buf);
 
 	if (line_terminator)
 		quote_c_style(rel, sb, NULL, 0);
 	else
 		strbuf_addstr(sb, rel);
+
+	strbuf_release(&buf);
 }
 
 static const char *get_tag(const struct cache_entry *ce, const char *tag)
@@ -360,7 +367,7 @@ static void show_ru_info(struct index_state *istate)
 			if (!ui->mode[i])
 				continue;
 			printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
-			       find_unique_abbrev(&ui->oid[i], abbrev),
+			       repo_find_unique_abbrev(the_repository, &ui->oid[i], abbrev),
 			       i + 1);
 			write_name(path);
 		}
@@ -575,7 +582,7 @@ void overlay_tree_on_index(struct index_state *istate,
 	read_tree_fn_t fn = NULL;
 	int err;
 
-	if (get_oid(tree_name, &oid))
+	if (repo_get_oid(the_repository, tree_name, &oid))
 		die("tree-ish %s not found.", tree_name);
 	tree = parse_tree_indirect(&oid);
 	if (!tree)
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 6516177..cb6cb77 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -1,9 +1,13 @@
 #include "builtin.h"
 #include "cache.h"
+#include "gettext.h"
+#include "hex.h"
 #include "transport.h"
+#include "pkt-line.h"
 #include "ref-filter.h"
 #include "remote.h"
 #include "refs.h"
+#include "parse-options.h"
 
 static const char * const ls_remote_usage[] = {
 	N_("git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 8cc8c99..077977a 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -5,6 +5,9 @@
  */
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "blob.h"
 #include "tree.h"
@@ -228,7 +231,7 @@ static int show_tree_default(const struct object_id *oid, struct strbuf *base,
 		return early;
 
 	printf("%06o %s %s\t", mode, type_name(object_type(mode)),
-	       find_unique_abbrev(oid, options->abbrev));
+	       repo_find_unique_abbrev(the_repository, oid, options->abbrev));
 	show_tree_common_default_long(options, base, pathname, base->len);
 	return recurse;
 }
@@ -259,7 +262,8 @@ static int show_tree_long(const struct object_id *oid, struct strbuf *base,
 	}
 
 	printf("%06o %s %s %7s\t", mode, type_name(type),
-	       find_unique_abbrev(oid, options->abbrev), size_text);
+	       repo_find_unique_abbrev(the_repository, oid, options->abbrev),
+	       size_text);
 	show_tree_common_default_long(options, base, pathname, base->len);
 	return recurse;
 }
@@ -310,7 +314,7 @@ static int show_tree_object(const struct object_id *oid, struct strbuf *base,
 	if (early >= 0)
 		return early;
 
-	str = find_unique_abbrev(oid, options->abbrev);
+	str = repo_find_unique_abbrev(the_repository, oid, options->abbrev);
 	if (options->null_termination) {
 		fputs(str, stdout);
 		fputc('\0', stdout);
@@ -433,7 +437,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 			ls_tree_usage, ls_tree_options);
 	if (argc < 1)
 		usage_with_options(ls_tree_usage, ls_tree_options);
-	if (get_oid(argv[0], &oid))
+	if (repo_get_oid(the_repository, argv[0], &oid))
 		die("Not a valid object name %s", argv[0]);
 
 	/*
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index 01d16ef..a032a1c 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -3,7 +3,10 @@
  * email to figure out authorship and subject
  */
 #include "cache.h"
+#include "abspath.h"
 #include "builtin.h"
+#include "environment.h"
+#include "gettext.h"
 #include "utf8.h"
 #include "strbuf.h"
 #include "mailinfo.h"
diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c
index 73509f6..0b6193a 100644
--- a/builtin/mailsplit.c
+++ b/builtin/mailsplit.c
@@ -6,6 +6,7 @@
  */
 #include "cache.h"
 #include "builtin.h"
+#include "gettext.h"
 #include "string-list.h"
 #include "strbuf.h"
 
@@ -277,6 +278,8 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
 	const char **argp;
 	static const char *stdin_only[] = { "-", NULL };
 
+	BUG_ON_NON_EMPTY_PREFIX(prefix);
+
 	for (argp = argv+1; *argp; argp++) {
 		const char *arg = *argp;
 
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 6f3941f..854019a 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -2,9 +2,12 @@
 #include "cache.h"
 #include "config.h"
 #include "commit.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
 #include "diff.h"
 #include "revision.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "repository.h"
 #include "commit-reach.h"
@@ -13,7 +16,8 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
 {
 	struct commit_list *result, *r;
 
-	result = get_merge_bases_many_dirty(rev[0], rev_nr - 1, rev + 1);
+	result = repo_get_merge_bases_many_dirty(the_repository, rev[0],
+						 rev_nr - 1, rev + 1);
 
 	if (!result)
 		return 1;
@@ -42,7 +46,7 @@ static struct commit *get_commit_reference(const char *arg)
 	struct object_id revkey;
 	struct commit *r;
 
-	if (get_oid(arg, &revkey))
+	if (repo_get_oid(the_repository, arg, &revkey))
 		die("Not a valid object name %s", arg);
 	r = lookup_commit_reference(the_repository, &revkey);
 	if (!r)
@@ -105,7 +109,7 @@ static int handle_is_ancestor(int argc, const char **argv)
 		die("--is-ancestor takes exactly two commits");
 	one = get_commit_reference(argv[0]);
 	two = get_commit_reference(argv[1]);
-	if (in_merge_bases(one, two))
+	if (repo_in_merge_bases(the_repository, one, two))
 		return 0;
 	else
 		return 1;
@@ -118,7 +122,7 @@ static int handle_fork_point(int argc, const char **argv)
 	const char *commitname;
 
 	commitname = (argc == 2) ? argv[1] : "HEAD";
-	if (get_oid(commitname, &oid))
+	if (repo_get_oid(the_repository, commitname, &oid))
 		die("Not a valid object name: '%s'", commitname);
 
 	derived = lookup_commit_reference(the_repository, &oid);
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index c923bbf..781818d 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -1,6 +1,9 @@
 #include "builtin.h"
+#include "abspath.h"
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
+#include "setup.h"
 #include "xdiff/xdiff.h"
 #include "xdiff-interface.h"
 #include "parse-options.h"
diff --git a/builtin/merge-index.c b/builtin/merge-index.c
index 452f833..ab16e70 100644
--- a/builtin/merge-index.c
+++ b/builtin/merge-index.c
@@ -1,5 +1,7 @@
 #define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
+#include "hex.h"
+#include "repository.h"
 #include "run-command.h"
 
 static const char *pgm;
@@ -70,7 +72,7 @@ static void merge_all(void)
 	}
 }
 
-int cmd_merge_index(int argc, const char **argv, const char *prefix)
+int cmd_merge_index(int argc, const char **argv, const char *prefix UNUSED)
 {
 	int i, force_file = 0;
 
diff --git a/builtin/merge-ours.c b/builtin/merge-ours.c
index 284eb48..c2e5193 100644
--- a/builtin/merge-ours.c
+++ b/builtin/merge-ours.c
@@ -14,7 +14,7 @@
 static const char builtin_merge_ours_usage[] =
 	"git merge-ours <base>... -- HEAD <remote>...";
 
-int cmd_merge_ours(int argc, const char **argv, const char *prefix)
+int cmd_merge_ours(int argc, const char **argv, const char *prefix UNUSED)
 {
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage(builtin_merge_ours_usage);
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index b9acbf5..b9e9803 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -1,8 +1,13 @@
 #include "cache.h"
 #include "builtin.h"
+#include "advice.h"
 #include "commit.h"
+#include "gettext.h"
+#include "hash.h"
 #include "tag.h"
 #include "merge-recursive.h"
+#include "object-name.h"
+#include "repository.h"
 #include "xdiff-interface.h"
 
 static const char builtin_merge_recursive_usage[] =
@@ -20,7 +25,7 @@ static char *better_branch_name(const char *branch)
 	return xstrdup(name ? name : branch);
 }
 
-int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
+int cmd_merge_recursive(int argc, const char **argv, const char *prefix UNUSED)
 {
 	const struct object_id *bases[21];
 	unsigned bases_count = 0;
@@ -49,7 +54,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
 		}
 		if (bases_count < ARRAY_SIZE(bases)-1) {
 			struct object_id *oid = xmalloc(sizeof(struct object_id));
-			if (get_oid(argv[i], oid))
+			if (repo_get_oid(the_repository, argv[i], oid))
 				die(_("could not parse object '%s'"), argv[i]);
 			bases[bases_count++] = oid;
 		}
@@ -70,9 +75,9 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
 	o.branch1 = argv[++i];
 	o.branch2 = argv[++i];
 
-	if (get_oid(o.branch1, &h1))
+	if (repo_get_oid(the_repository, o.branch1, &h1))
 		die(_("could not resolve ref '%s'"), o.branch1);
-	if (get_oid(o.branch2, &h2))
+	if (repo_get_oid(the_repository, o.branch2, &h2))
 		die(_("could not resolve ref '%s'"), o.branch2);
 
 	o.branch1 = better1 = better_branch_name(o.branch1);
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 828dc81..b8f8a8b 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -3,9 +3,12 @@
 #include "tree-walk.h"
 #include "xdiff-interface.h"
 #include "help.h"
+#include "gettext.h"
+#include "hex.h"
 #include "commit.h"
 #include "commit-reach.h"
 #include "merge-ort.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "parse-options.h"
 #include "repository.h"
@@ -13,6 +16,8 @@
 #include "exec-cmd.h"
 #include "merge-blobs.h"
 #include "quote.h"
+#include "tree.h"
+#include "config.h"
 
 static int line_termination = '\n';
 
@@ -69,7 +74,9 @@ static void *result(struct merge_list *entry, unsigned long *size)
 	const char *path = entry->path;
 
 	if (!entry->stage)
-		return read_object_file(&entry->blob->object.oid, &type, size);
+		return repo_read_object_file(the_repository,
+					     &entry->blob->object.oid, &type,
+					     size);
 	base = NULL;
 	if (entry->stage == 1) {
 		base = entry->blob;
@@ -92,8 +99,9 @@ static void *origin(struct merge_list *entry, unsigned long *size)
 	enum object_type type;
 	while (entry) {
 		if (entry->stage == 2)
-			return read_object_file(&entry->blob->object.oid,
-						&type, size);
+			return repo_read_object_file(the_repository,
+						     &entry->blob->object.oid,
+						     &type, size);
 		entry = entry->link;
 	}
 	return NULL;
@@ -443,16 +451,17 @@ static int real_merge(struct merge_tree_options *o,
 			die(_("could not lookup commit %s"), merge_base);
 
 		opt.ancestor = merge_base;
-		base_tree = get_commit_tree(base_commit);
-		parent1_tree = get_commit_tree(parent1);
-		parent2_tree = get_commit_tree(parent2);
+		base_tree = repo_get_commit_tree(the_repository, base_commit);
+		parent1_tree = repo_get_commit_tree(the_repository, parent1);
+		parent2_tree = repo_get_commit_tree(the_repository, parent2);
 		merge_incore_nonrecursive(&opt, base_tree, parent1_tree, parent2_tree, &result);
 	} else {
 		/*
 		 * Get the merge bases, in reverse order; see comment above
 		 * merge_incore_recursive in merge-ort.h
 		 */
-		merge_bases = get_merge_bases(parent1, parent2);
+		merge_bases = repo_get_merge_bases(the_repository, parent1,
+						   parent2);
 		if (!merge_bases && !o->allow_unrelated_histories)
 			die(_("refusing to merge unrelated histories"));
 		merge_bases = reverse_commit_list(merge_bases);
@@ -620,6 +629,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
 	if (argc != expected_remaining_argc)
 		usage_with_options(merge_tree_usage, mt_options);
 
+	git_config(git_default_config, NULL);
+
 	/* Do the relevant type of merge */
 	if (o.mode == MODE_REAL)
 		return real_merge(&o, merge_base, argv[0], argv[1], prefix);
diff --git a/builtin/merge.c b/builtin/merge.c
index 0a3c10a..8da3e46 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -8,7 +8,15 @@
 
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
+#include "abspath.h"
+#include "advice.h"
+#include "alloc.h"
 #include "config.h"
+#include "editor.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "builtin.h"
 #include "lockfile.h"
@@ -44,6 +52,7 @@
 #include "commit-reach.h"
 #include "wt-status.h"
 #include "commit-graph.h"
+#include "wrapper.h"
 
 #define DEFAULT_TWOHEAD (1<<0)
 #define DEFAULT_OCTOPUS (1<<1)
@@ -337,7 +346,7 @@ static int save_state(struct object_id *stash)
 	else if (!len)		/* no changes */
 		goto out;
 	strbuf_setlen(&buffer, buffer.len-1);
-	if (get_oid(buffer.buf, stash))
+	if (repo_get_oid(the_repository, buffer.buf, stash))
 		die(_("not a valid object: %s"), buffer.buf);
 	rc = 0;
 out:
@@ -517,7 +526,8 @@ static void merge_name(const char *remote, struct strbuf *msg)
 	if (!remote_head)
 		die(_("'%s' does not point to a commit"), remote);
 
-	if (dwim_ref(remote, strlen(remote), &branch_head, &found_ref, 0) > 0) {
+	if (repo_dwim_ref(the_repository, remote, strlen(remote), &branch_head,
+			  &found_ref, 0) > 0) {
 		if (starts_with(found_ref, "refs/heads/")) {
 			strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
 				    oid_to_hex(&branch_head), remote);
@@ -661,9 +671,6 @@ static int git_merge_config(const char *k, const char *v, void *cb)
 	status = fmt_merge_msg_config(k, v, cb);
 	if (status)
 		return status;
-	status = git_gpg_config(k, v, NULL);
-	if (status)
-		return status;
 	return git_diff_ui_config(k, v, cb);
 }
 
@@ -1531,7 +1538,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	if (!remoteheads)
 		; /* already up-to-date */
 	else if (!remoteheads->next)
-		common = get_merge_bases(head_commit, remoteheads->item);
+		common = repo_get_merge_bases(the_repository, head_commit,
+					      remoteheads->item);
 	else {
 		struct commit_list *list = remoteheads;
 		commit_list_insert(head_commit, &list);
@@ -1567,10 +1575,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 
 		if (verbosity >= 0) {
 			printf(_("Updating %s..%s\n"),
-			       find_unique_abbrev(&head_commit->object.oid,
-						  DEFAULT_ABBREV),
-			       find_unique_abbrev(&remoteheads->item->object.oid,
-						  DEFAULT_ABBREV));
+			       repo_find_unique_abbrev(the_repository, &head_commit->object.oid,
+						       DEFAULT_ABBREV),
+			       repo_find_unique_abbrev(the_repository, &remoteheads->item->object.oid,
+						       DEFAULT_ABBREV));
 		}
 		commit = remoteheads->item;
 		if (!commit) {
@@ -1610,7 +1618,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			 * Must first ensure that index matches HEAD before
 			 * attempting a trivial merge.
 			 */
-			struct tree *head_tree = get_commit_tree(head_commit);
+			struct tree *head_tree = repo_get_commit_tree(the_repository,
+								      head_commit);
 			struct strbuf sb = STRBUF_INIT;
 
 			if (repo_index_has_changes(the_repository, head_tree,
@@ -1649,7 +1658,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			 * merge_bases again, otherwise "git merge HEAD^
 			 * HEAD^^" would be missed.
 			 */
-			common_one = get_merge_bases(head_commit, j->item);
+			common_one = repo_get_merge_bases(the_repository,
+							  head_commit,
+							  j->item);
 			if (!oideq(&common_one->item->object.oid, &j->item->object.oid)) {
 				up_to_date = 0;
 				break;
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 5d22909..44fa56e 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -1,7 +1,10 @@
 #include "builtin.h"
+#include "gettext.h"
+#include "hex.h"
 #include "parse-options.h"
 #include "tag.h"
 #include "replace-object.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "fsck.h"
 #include "config.h"
@@ -51,7 +54,8 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 	void *buffer;
 	const struct object_id *repl;
 
-	buffer = read_object_file(tagged_oid, &type, &size);
+	buffer = repo_read_object_file(the_repository, tagged_oid, &type,
+				       &size);
 	if (!buffer)
 		die(_("could not read tagged object '%s'"),
 		    oid_to_hex(tagged_oid));
@@ -80,7 +84,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	int tagged_type;
 	struct object_id result;
 
-	argc = parse_options(argc, argv, NULL,
+	argc = parse_options(argc, argv, prefix,
 			     builtin_mktag_options,
 			     builtin_mktag_usage, 0);
 
diff --git a/builtin/mktree.c b/builtin/mktree.c
index 06d8140..09a7bd5 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -4,6 +4,9 @@
  * Copyright (c) Junio C Hamano, 2006, 2009
  */
 #include "builtin.h"
+#include "alloc.h"
+#include "gettext.h"
+#include "hex.h"
 #include "quote.h"
 #include "tree.h"
 #include "parse-options.h"
diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c
index 9a18a82..1b5083f 100644
--- a/builtin/multi-pack-index.c
+++ b/builtin/multi-pack-index.c
@@ -1,6 +1,9 @@
 #include "builtin.h"
+#include "abspath.h"
 #include "cache.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
 #include "parse-options.h"
 #include "midx.h"
 #include "trace2.h"
diff --git a/builtin/mv.c b/builtin/mv.c
index edd7b93..665bd27 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -5,13 +5,21 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
+#include "abspath.h"
+#include "advice.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "object-file.h"
 #include "pathspec.h"
 #include "lockfile.h"
 #include "dir.h"
 #include "cache-tree.h"
 #include "string-list.h"
 #include "parse-options.h"
+#include "repository.h"
+#include "setup.h"
 #include "submodule.h"
 #include "entry.h"
 
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 97959bf..4d15a23 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -1,10 +1,15 @@
 #include "builtin.h"
-#include "cache.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "config.h"
 #include "commit.h"
 #include "tag.h"
 #include "refs.h"
+#include "object-name.h"
+#include "pager.h"
 #include "parse-options.h"
 #include "prio-queue.h"
 #include "hash-lookup.h"
@@ -181,7 +186,7 @@ static void name_rev(struct commit *start_commit,
 	size_t parents_to_queue_nr, parents_to_queue_alloc = 0;
 	struct rev_name *start_name;
 
-	parse_commit(start_commit);
+	repo_parse_commit(the_repository, start_commit);
 	if (commit_is_before_cutoff(start_commit))
 		return;
 
@@ -211,7 +216,7 @@ static void name_rev(struct commit *start_commit,
 			struct rev_name *parent_name;
 			int generation, distance;
 
-			parse_commit(parent);
+			repo_parse_commit(the_repository, parent);
 			if (commit_is_before_cutoff(parent))
 				continue;
 
@@ -493,7 +498,8 @@ static void show_name(const struct object *obj,
 	else if (allow_undefined)
 		printf("undefined\n");
 	else if (always)
-		printf("%s\n", find_unique_abbrev(oid, DEFAULT_ABBREV));
+		printf("%s\n",
+		       repo_find_unique_abbrev(the_repository, oid, DEFAULT_ABBREV));
 	else
 		die("cannot describe '%s'", oid_to_hex(oid));
 	strbuf_release(&buf);
@@ -527,7 +533,7 @@ static void name_rev_line(char *p, struct name_ref_data *data)
 			counter = 0;
 
 			*(p+1) = 0;
-			if (!get_oid(p - (hexsz - 1), &oid)) {
+			if (!repo_get_oid(the_repository, p - (hexsz - 1), &oid)) {
 				struct object *o =
 					lookup_object(the_repository, &oid);
 				if (o)
@@ -567,7 +573,11 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 				   N_("ignore refs matching <pattern>")),
 		OPT_GROUP(""),
 		OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
-		OPT_BOOL(0, "stdin", &transform_stdin, N_("deprecated: use --annotate-stdin instead")),
+		OPT_BOOL_F(0,
+			   "stdin",
+			   &transform_stdin,
+			   N_("deprecated: use --annotate-stdin instead"),
+			   PARSE_OPT_HIDDEN),
 		OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")),
 		OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
 		OPT_BOOL(0, "always",     &always,
@@ -604,7 +614,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 		struct object *object;
 		struct commit *commit;
 
-		if (get_oid(*argv, &oid)) {
+		if (repo_get_oid(the_repository, *argv, &oid)) {
 			fprintf(stderr, "Could not get sha1 for %s. Skipping.\n",
 					*argv);
 			continue;
diff --git a/builtin/notes.c b/builtin/notes.c
index 80d9dfd..d578835 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -10,7 +10,11 @@
 #include "cache.h"
 #include "config.h"
 #include "builtin.h"
+#include "editor.h"
+#include "gettext.h"
+#include "hex.h"
 #include "notes.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "repository.h"
 #include "blob.h"
@@ -23,6 +27,7 @@
 #include "notes-merge.h"
 #include "notes-utils.h"
 #include "worktree.h"
+#include "write-or-die.h"
 
 static const char * const git_notes_usage[] = {
 	N_("git notes [--ref <notes-ref>] [list [<object>]]"),
@@ -113,8 +118,9 @@ static void free_note_data(struct note_data *d)
 }
 
 static int list_each_note(const struct object_id *object_oid,
-		const struct object_id *note_oid, char *note_path,
-		void *cb_data)
+			  const struct object_id *note_oid,
+			  char *note_path UNUSED,
+			  void *cb_data UNUSED)
 {
 	printf("%s %s\n", oid_to_hex(note_oid), oid_to_hex(object_oid));
 	return 0;
@@ -124,7 +130,7 @@ static void copy_obj_to_fd(int fd, const struct object_id *oid)
 {
 	unsigned long size;
 	enum object_type type;
-	char *buf = read_object_file(oid, &type, &size);
+	char *buf = repo_read_object_file(the_repository, oid, &type, &size);
 	if (buf) {
 		if (size)
 			write_or_die(fd, buf, size);
@@ -257,9 +263,9 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)
 	if (d->buf.len)
 		strbuf_addch(&d->buf, '\n');
 
-	if (get_oid(arg, &object))
+	if (repo_get_oid(the_repository, arg, &object))
 		die(_("failed to resolve '%s' as a valid ref."), arg);
-	if (!(buf = read_object_file(&object, &type, &len)))
+	if (!(buf = repo_read_object_file(the_repository, &object, &type, &len)))
 		die(_("failed to read object '%s'."), arg);
 	if (type != OBJ_BLOB) {
 		free(buf);
@@ -307,9 +313,9 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
 			die(_("malformed input line: '%s'."), buf.buf);
 		strbuf_rtrim(split[0]);
 		strbuf_rtrim(split[1]);
-		if (get_oid(split[0]->buf, &from_obj))
+		if (repo_get_oid(the_repository, split[0]->buf, &from_obj))
 			die(_("failed to resolve '%s' as a valid ref."), split[0]->buf);
-		if (get_oid(split[1]->buf, &to_obj))
+		if (repo_get_oid(the_repository, split[1]->buf, &to_obj))
 			die(_("failed to resolve '%s' as a valid ref."), split[1]->buf);
 
 		if (rewrite_cmd)
@@ -377,7 +383,7 @@ static int list(int argc, const char **argv, const char *prefix)
 
 	t = init_notes_check("list", 0);
 	if (argc) {
-		if (get_oid(argv[0], &object))
+		if (repo_get_oid(the_repository, argv[0], &object))
 			die(_("failed to resolve '%s' as a valid ref."), argv[0]);
 		note = get_note(t, &object);
 		if (note) {
@@ -432,7 +438,7 @@ static int add(int argc, const char **argv, const char *prefix)
 
 	object_ref = argc > 1 ? argv[1] : "HEAD";
 
-	if (get_oid(object_ref, &object))
+	if (repo_get_oid(the_repository, object_ref, &object))
 		die(_("failed to resolve '%s' as a valid ref."), object_ref);
 
 	t = init_notes_check("add", NOTES_INIT_WRITABLE);
@@ -520,12 +526,12 @@ static int copy(int argc, const char **argv, const char *prefix)
 		usage_with_options(git_notes_copy_usage, options);
 	}
 
-	if (get_oid(argv[0], &from_obj))
+	if (repo_get_oid(the_repository, argv[0], &from_obj))
 		die(_("failed to resolve '%s' as a valid ref."), argv[0]);
 
 	object_ref = 1 < argc ? argv[1] : "HEAD";
 
-	if (get_oid(object_ref, &object))
+	if (repo_get_oid(the_repository, object_ref, &object))
 		die(_("failed to resolve '%s' as a valid ref."), object_ref);
 
 	t = init_notes_check("copy", NOTES_INIT_WRITABLE);
@@ -604,7 +610,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)
 
 	object_ref = 1 < argc ? argv[1] : "HEAD";
 
-	if (get_oid(object_ref, &object))
+	if (repo_get_oid(the_repository, object_ref, &object))
 		die(_("failed to resolve '%s' as a valid ref."), object_ref);
 
 	t = init_notes_check(argv[0], NOTES_INIT_WRITABLE);
@@ -616,7 +622,8 @@ static int append_edit(int argc, const char **argv, const char *prefix)
 		/* Append buf to previous note contents */
 		unsigned long size;
 		enum object_type type;
-		char *prev_buf = read_object_file(note, &type, &size);
+		char *prev_buf = repo_read_object_file(the_repository, note,
+						       &type, &size);
 
 		strbuf_grow(&d.buf, size + 1);
 		if (d.buf.len && prev_buf && size)
@@ -666,7 +673,7 @@ static int show(int argc, const char **argv, const char *prefix)
 
 	object_ref = argc ? argv[0] : "HEAD";
 
-	if (get_oid(object_ref, &object))
+	if (repo_get_oid(the_repository, object_ref, &object))
 		die(_("failed to resolve '%s' as a valid ref."), object_ref);
 
 	t = init_notes_check("show", 0);
@@ -716,11 +723,11 @@ static int merge_commit(struct notes_merge_options *o)
 	 * and target notes ref from .git/NOTES_MERGE_REF.
 	 */
 
-	if (get_oid("NOTES_MERGE_PARTIAL", &oid))
+	if (repo_get_oid(the_repository, "NOTES_MERGE_PARTIAL", &oid))
 		die(_("failed to read ref NOTES_MERGE_PARTIAL"));
 	else if (!(partial = lookup_commit_reference(the_repository, &oid)))
 		die(_("could not find commit from NOTES_MERGE_PARTIAL."));
-	else if (parse_commit(partial))
+	else if (repo_parse_commit(the_repository, partial))
 		die(_("could not parse commit from NOTES_MERGE_PARTIAL."));
 
 	if (partial->parents)
@@ -741,7 +748,8 @@ static int merge_commit(struct notes_merge_options *o)
 
 	/* Reuse existing commit message in reflog message */
 	memset(&pretty_ctx, 0, sizeof(pretty_ctx));
-	format_commit_message(partial, "%s", &msg, &pretty_ctx);
+	repo_format_commit_message(the_repository, partial, "%s", &msg,
+				   &pretty_ctx);
 	strbuf_trim(&msg);
 	strbuf_insertstr(&msg, 0, "notes: ");
 	update_ref(msg.buf, o->local_ref, &oid,
@@ -895,7 +903,7 @@ static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag
 {
 	int status;
 	struct object_id oid;
-	if (get_oid(name, &oid))
+	if (repo_get_oid(the_repository, name, &oid))
 		return error(_("Failed to resolve '%s' as a valid ref."), name);
 	status = remove_note(t, oid.hash);
 	if (status)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 74a167a..9cfc880 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1,5 +1,8 @@
 #include "builtin.h"
-#include "cache.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "config.h"
 #include "attr.h"
@@ -30,13 +33,17 @@
 #include "strvec.h"
 #include "list.h"
 #include "packfile.h"
+#include "object-file.h"
 #include "object-store.h"
+#include "replace-object.h"
 #include "dir.h"
 #include "midx.h"
 #include "trace2.h"
 #include "shallow.h"
 #include "promisor-remote.h"
 #include "pack-mtimes.h"
+#include "parse-options.h"
+#include "wrapper.h"
 
 /*
  * Objects we are going to pack are collected in the `to_pack` structure.
@@ -288,11 +295,13 @@ static void *get_delta(struct object_entry *entry)
 	void *buf, *base_buf, *delta_buf;
 	enum object_type type;
 
-	buf = read_object_file(&entry->idx.oid, &type, &size);
+	buf = repo_read_object_file(the_repository, &entry->idx.oid, &type,
+				    &size);
 	if (!buf)
 		die(_("unable to read %s"), oid_to_hex(&entry->idx.oid));
-	base_buf = read_object_file(&DELTA(entry)->idx.oid, &type,
-				    &base_size);
+	base_buf = repo_read_object_file(the_repository,
+					 &DELTA(entry)->idx.oid, &type,
+					 &base_size);
 	if (!base_buf)
 		die("unable to read %s",
 		    oid_to_hex(&DELTA(entry)->idx.oid));
@@ -454,7 +463,9 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent
 				       &size, NULL)) != NULL)
 			buf = NULL;
 		else {
-			buf = read_object_file(&entry->idx.oid, &type, &size);
+			buf = repo_read_object_file(the_repository,
+						    &entry->idx.oid, &type,
+						    &size);
 			if (!buf)
 				die(_("unable to read %s"),
 				    oid_to_hex(&entry->idx.oid));
@@ -1320,7 +1331,7 @@ static int no_try_delta(const char *path)
 
 	if (!check)
 		check = attr_check_initl("delta", NULL);
-	git_check_attr(the_repository->index, NULL, path, check);
+	git_check_attr(the_repository->index, path, check);
 	if (ATTR_FALSE(check->items[0].value))
 		return 1;
 	return 0;
@@ -1590,7 +1601,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type,
 
 static int add_object_entry_from_bitmap(const struct object_id *oid,
 					enum object_type type,
-					int flags, uint32_t name_hash,
+					int flags UNUSED, uint32_t name_hash,
 					struct packed_git *pack, off_t offset)
 {
 	display_progress(progress_state, ++nr_seen);
@@ -1665,7 +1676,7 @@ static struct pbase_tree_cache *pbase_tree_get(const struct object_id *oid)
 	/* Did not find one.  Either we got a bogus request or
 	 * we need to read and perhaps cache.
 	 */
-	data = read_object_file(oid, &type, &size);
+	data = repo_read_object_file(the_repository, oid, &type, &size);
 	if (!data)
 		return NULL;
 	if (type != OBJ_TREE) {
@@ -2074,7 +2085,7 @@ static void check_object(struct object_entry *entry, uint32_t object_index)
 
 	if (oid_object_info_extended(the_repository, &entry->idx.oid, &oi,
 				     OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_LOOKUP_REPLACE) < 0) {
-		if (has_promisor_remote()) {
+		if (repo_has_promisor_remote(the_repository)) {
 			prefetch_to_pack(object_index);
 			if (oid_object_info_extended(the_repository, &entry->idx.oid, &oi,
 						     OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_LOOKUP_REPLACE) < 0)
@@ -2525,7 +2536,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 	/* Load data if not already done */
 	if (!trg->data) {
 		packing_data_lock(&to_pack);
-		trg->data = read_object_file(&trg_entry->idx.oid, &type, &sz);
+		trg->data = repo_read_object_file(the_repository,
+						  &trg_entry->idx.oid, &type,
+						  &sz);
 		packing_data_unlock(&to_pack);
 		if (!trg->data)
 			die(_("object %s cannot be read"),
@@ -2538,7 +2551,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 	}
 	if (!src->data) {
 		packing_data_lock(&to_pack);
-		src->data = read_object_file(&src_entry->idx.oid, &type, &sz);
+		src->data = repo_read_object_file(the_repository,
+						  &src_entry->idx.oid, &type,
+						  &sz);
 		packing_data_unlock(&to_pack);
 		if (!src->data) {
 			if (src_entry->preferred_base) {
@@ -3260,13 +3275,14 @@ static int add_object_entry_from_pack(const struct object_id *oid,
 	return 0;
 }
 
-static void show_commit_pack_hint(struct commit *commit, void *_data)
+static void show_commit_pack_hint(struct commit *commit UNUSED,
+				  void *data UNUSED)
 {
 	/* nothing to do; commits don't have a namehash */
 }
 
 static void show_object_pack_hint(struct object *object, const char *name,
-				  void *_data)
+				  void *data UNUSED)
 {
 	struct object_entry *oe = packlist_find(&to_pack, &object->oid);
 	if (!oe)
@@ -3344,16 +3360,16 @@ static void read_packs_list_from_stdin(void)
 	}
 
 	string_list_sort(&include_packs);
+	string_list_remove_duplicates(&include_packs, 0);
 	string_list_sort(&exclude_packs);
+	string_list_remove_duplicates(&exclude_packs, 0);
 
 	for (p = get_all_packs(the_repository); p; p = p->next) {
 		const char *pack_name = pack_basename(p);
 
-		item = string_list_lookup(&include_packs, pack_name);
-		if (!item)
-			item = string_list_lookup(&exclude_packs, pack_name);
-
-		if (item)
+		if ((item = string_list_lookup(&include_packs, pack_name)))
+			item->util = p;
+		if ((item = string_list_lookup(&exclude_packs, pack_name)))
 			item->util = p;
 	}
 
@@ -3464,7 +3480,7 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type
 	return;
 }
 
-static void show_cruft_object(struct object *obj, const char *name, void *data)
+static void show_cruft_object(struct object *obj, const char *name, void *data UNUSED)
 {
 	/*
 	 * if we did not record it earlier, it's at least as old as our
@@ -3484,7 +3500,7 @@ static void show_cruft_commit(struct commit *commit, void *data)
 	show_cruft_object((struct object*)commit, NULL, data);
 }
 
-static int cruft_include_check_obj(struct object *obj, void *data)
+static int cruft_include_check_obj(struct object *obj, void *data UNUSED)
 {
 	return !has_object_kept_pack(&obj->oid, IN_CORE_KEEP_PACKS);
 }
@@ -3663,7 +3679,7 @@ static void read_object_list_from_stdin(void)
 	}
 }
 
-static void show_commit(struct commit *commit, void *data)
+static void show_commit(struct commit *commit, void *data UNUSED)
 {
 	add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0);
 
@@ -3674,7 +3690,8 @@ static void show_commit(struct commit *commit, void *data)
 		propagate_island_marks(commit);
 }
 
-static void show_object(struct object *obj, const char *name, void *data)
+static void show_object(struct object *obj, const char *name,
+			void *data UNUSED)
 {
 	add_preferred_base_object(name);
 	add_object_entry(&obj->oid, obj->type, name, 0);
@@ -3761,7 +3778,7 @@ static void show_edge(struct commit *commit)
 static int add_object_in_unpacked_pack(const struct object_id *oid,
 				       struct packed_git *pack,
 				       uint32_t pos,
-				       void *_data)
+				       void *data UNUSED)
 {
 	if (cruft) {
 		off_t offset;
@@ -3795,7 +3812,7 @@ static void add_objects_in_unpacked_packs(void)
 }
 
 static int add_loose_object(const struct object_id *oid, const char *path,
-			    void *data)
+			    void *data UNUSED)
 {
 	enum object_type type = oid_object_info(the_repository, oid, NULL);
 
@@ -3946,13 +3963,13 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
 }
 
 static void record_recent_object(struct object *obj,
-				 const char *name,
-				 void *data)
+				 const char *name UNUSED,
+				 void *data UNUSED)
 {
 	oid_array_append(&recent_objects, &obj->oid);
 }
 
-static void record_recent_commit(struct commit *commit, void *data)
+static void record_recent_commit(struct commit *commit, void *data UNUSED)
 {
 	oid_array_append(&recent_objects, &commit->object.oid);
 }
@@ -4277,9 +4294,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 	}
 
 	reset_pack_idx_option(&pack_idx_opts);
+	pack_idx_opts.flags |= WRITE_REV;
 	git_config(git_pack_config, NULL);
-	if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0))
-		pack_idx_opts.flags |= WRITE_REV;
+	if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0))
+		pack_idx_opts.flags &= ~WRITE_REV;
 
 	progress = isatty(2);
 	argc = parse_options(argc, argv, prefix, pack_objects_options,
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index ecd49ca..43e9d12 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -7,6 +7,8 @@
 */
 
 #include "builtin.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "packfile.h"
 #include "object-store.h"
@@ -557,7 +559,7 @@ static void load_all(void)
 	}
 }
 
-int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
+int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED)
 {
 	int i;
 	int i_still_use_this = 0;
@@ -603,6 +605,7 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
 			"option, '--i-still-use-this', on the command line\n"
 			"and let us know you still use it by sending an e-mail\n"
 			"to <git@vger.kernel.org>.  Thanks.\n"), stderr);
+		die(_("refusing to run without --i-still-use-this"));
 	}
 
 	if (load_all_packs)
diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index 27c2ca0..9833815 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "config.h"
+#include "gettext.h"
 #include "parse-options.h"
 #include "refs.h"
 #include "repository.h"
diff --git a/builtin/patch-id.c b/builtin/patch-id.c
index f840fbf..9d5585d 100644
--- a/builtin/patch-id.c
+++ b/builtin/patch-id.c
@@ -2,6 +2,8 @@
 #include "builtin.h"
 #include "config.h"
 #include "diff.h"
+#include "gettext.h"
+#include "hex.h"
 #include "parse-options.h"
 
 static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index da3273a..ca3578e 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "gettext.h"
 #include "parse-options.h"
 #include "prune-packed.h"
 
diff --git a/builtin/prune.c b/builtin/prune.c
index 2719220..5dc9b20 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -1,12 +1,18 @@
 #include "cache.h"
 #include "commit.h"
 #include "diff.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "revision.h"
 #include "builtin.h"
 #include "reachable.h"
 #include "parse-options.h"
 #include "progress.h"
 #include "prune-packed.h"
+#include "replace-object.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "shallow.h"
 
@@ -98,7 +104,8 @@ static int prune_object(const struct object_id *oid, const char *fullpath,
 	return 0;
 }
 
-static int prune_cruft(const char *basename, const char *path, void *data)
+static int prune_cruft(const char *basename, const char *path,
+		       void *data UNUSED)
 {
 	if (starts_with(basename, "tmp_obj_"))
 		prune_tmp_file(path);
@@ -107,7 +114,8 @@ static int prune_cruft(const char *basename, const char *path, void *data)
 	return 0;
 }
 
-static int prune_subdir(unsigned int nr, const char *path, void *data)
+static int prune_subdir(unsigned int nr UNUSED, const char *path,
+			void *data UNUSED)
 {
 	if (!show_only)
 		rmdir(path);
@@ -168,7 +176,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
 		struct object_id oid;
 		const char *name = *argv++;
 
-		if (!get_oid(name, &oid)) {
+		if (!repo_get_oid(the_repository, name, &oid)) {
 			struct object *object = parse_object_or_die(&oid,
 								    name);
 			add_pending_object(&revs, object, "");
diff --git a/builtin/pull.c b/builtin/pull.c
index 1ab4de0..0c7bac9 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -7,8 +7,12 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
+#include "advice.h"
 #include "config.h"
 #include "builtin.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "exec-cmd.h"
 #include "run-command.h"
@@ -359,8 +363,6 @@ static enum rebase_type config_get_rebase(int *rebase_unspecified)
  */
 static int git_pull_config(const char *var, const char *value, void *cb)
 {
-	int status;
-
 	if (!strcmp(var, "rebase.autostash")) {
 		config_autostash = git_config_bool(var, value);
 		return 0;
@@ -372,10 +374,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)
 		check_trust_level = 0;
 	}
 
-	status = git_gpg_config(var, value, cb);
-	if (status)
-		return status;
-
 	return git_default_config(var, value, cb);
 }
 
@@ -1036,7 +1034,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
 	if (file_exists(git_path_merge_head(the_repository)))
 		die_conclude_merge();
 
-	if (get_oid("HEAD", &orig_head))
+	if (repo_get_oid(the_repository, "HEAD", &orig_head))
 		oidclr(&orig_head);
 
 	if (opt_rebase) {
@@ -1049,7 +1047,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
 		if (!opt_autostash)
 			require_clean_work_tree(the_repository,
 				N_("pull with rebase"),
-				_("please commit or stash them."), 1, 0);
+				_("Please commit or stash them."), 1, 0);
 
 		if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs))
 			oidclr(&rebase_fork_point);
@@ -1061,7 +1059,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
 	if (opt_dry_run)
 		return 0;
 
-	if (get_oid("HEAD", &curr_head))
+	if (repo_get_oid(the_repository, "HEAD", &curr_head))
 		oidclr(&curr_head);
 
 	if (!is_null_oid(&orig_head) && !is_null_oid(&curr_head) &&
diff --git a/builtin/push.c b/builtin/push.c
index 8f7d326..dbdf609 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -2,8 +2,11 @@
  * "git push"
  */
 #include "cache.h"
+#include "advice.h"
 #include "branch.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
 #include "refs.h"
 #include "refspec.h"
 #include "run-command.h"
@@ -11,9 +14,12 @@
 #include "remote.h"
 #include "transport.h"
 #include "parse-options.h"
+#include "pkt-line.h"
+#include "repository.h"
 #include "submodule.h"
 #include "submodule-config.h"
 #include "send-pack.h"
+#include "trace2.h"
 #include "color.h"
 
 static const char * const push_usage[] = {
@@ -508,11 +514,6 @@ static int git_push_config(const char *k, const char *v, void *cb)
 {
 	const char *slot_name;
 	int *flags = cb;
-	int status;
-
-	status = git_gpg_config(k, v, NULL);
-	if (status)
-		return status;
 
 	if (!strcmp(k, "push.followtags")) {
 		if (git_config_bool(k, v))
@@ -594,11 +595,12 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 	struct option options[] = {
 		OPT__VERBOSITY(&verbosity),
 		OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
-		OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
+		OPT_BIT( 0 , "all", &flags, N_("push all branches"), TRANSPORT_PUSH_ALL),
+		OPT_ALIAS( 0 , "branches", "all"),
 		OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
 			    (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
 		OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")),
-		OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
+		OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --branches or --mirror)")),
 		OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
 		OPT_BIT( 0,  "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
 		OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
@@ -641,7 +643,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 	set_push_cert_flags(&flags, push_cert);
 
 	if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
-		die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--mirror/--tags");
+		die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--branches/--mirror/--tags");
 	if (deleterefs && argc < 2)
 		die(_("--delete doesn't make sense without any refs"));
 
diff --git a/builtin/range-diff.c b/builtin/range-diff.c
index aecfae1..04339a9 100644
--- a/builtin/range-diff.c
+++ b/builtin/range-diff.c
@@ -1,5 +1,7 @@
 #include "cache.h"
 #include "builtin.h"
+#include "gettext.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "range-diff.h"
 #include "config.h"
@@ -65,20 +67,20 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix)
 
 	if (dash_dash == 3 ||
 	    (dash_dash < 0 && argc > 2 &&
-	     !get_oid_committish(argv[0], &oid) &&
-	     !get_oid_committish(argv[1], &oid) &&
-	     !get_oid_committish(argv[2], &oid))) {
+	     !repo_get_oid_committish(the_repository, argv[0], &oid) &&
+	     !repo_get_oid_committish(the_repository, argv[1], &oid) &&
+	     !repo_get_oid_committish(the_repository, argv[2], &oid))) {
 		if (dash_dash < 0)
 			; /* already validated arguments */
-		else if (get_oid_committish(argv[0], &oid))
+		else if (repo_get_oid_committish(the_repository, argv[0], &oid))
 			usage_msg_optf(_("not a revision: '%s'"),
 				       builtin_range_diff_usage, options,
 				       argv[0]);
-		else if (get_oid_committish(argv[1], &oid))
+		else if (repo_get_oid_committish(the_repository, argv[1], &oid))
 			usage_msg_optf(_("not a revision: '%s'"),
 				       builtin_range_diff_usage, options,
 				       argv[1]);
-		else if (get_oid_committish(argv[2], &oid))
+		else if (repo_get_oid_committish(the_repository, argv[2], &oid))
 			usage_msg_optf(_("not a revision: '%s'"),
 				       builtin_range_diff_usage, options,
 				       argv[2]);
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 3ce7541..440f19b 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -7,8 +7,11 @@
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "object.h"
+#include "object-name.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "cache-tree.h"
@@ -16,7 +19,9 @@
 #include "dir.h"
 #include "builtin.h"
 #include "parse-options.h"
+#include "repository.h"
 #include "resolve-undo.h"
+#include "setup.h"
 #include "submodule.h"
 #include "submodule-config.h"
 
@@ -87,9 +92,9 @@ static int debug_merge(const struct cache_entry * const *stages,
 {
 	int i;
 
-	printf("* %d-way merge\n", o->merge_size);
+	printf("* %d-way merge\n", o->internal.merge_size);
 	debug_stage("index", stages[0], o);
-	for (i = 1; i <= o->merge_size; i++) {
+	for (i = 1; i <= o->internal.merge_size; i++) {
 		char buf[24];
 		xsnprintf(buf, sizeof(buf), "ent#%d", i);
 		debug_stage(buf, stages[i], o);
@@ -144,7 +149,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
 		OPT__DRY_RUN(&opts.dry_run, N_("don't update the index or the work tree")),
 		OPT_BOOL(0, "no-sparse-checkout", &opts.skip_sparse_checkout,
 			 N_("skip applying sparse checkout filter")),
-		OPT_BOOL(0, "debug-unpack", &opts.debug_unpack,
+		OPT_BOOL(0, "debug-unpack", &opts.internal.debug_unpack,
 			 N_("debug unpack-trees")),
 		OPT_CALLBACK_F(0, "recurse-submodules", NULL,
 			    "checkout", "control recursive updating of submodules",
@@ -198,7 +203,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
 	for (i = 0; i < argc; i++) {
 		const char *arg = argv[i];
 
-		if (get_oid(arg, &oid))
+		if (repo_get_oid(the_repository, arg, &oid))
 			die("Not a valid object name %s", arg);
 		if (list_tree(&oid) < 0)
 			die("failed to unpack tree object %s", arg);
@@ -247,7 +252,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
 			opts.head_idx = 1;
 	}
 
-	if (opts.debug_unpack)
+	if (opts.internal.debug_unpack)
 		opts.fn = debug_merge;
 
 	/* If we're going to prime_cache_tree later, skip cache tree update */
@@ -263,7 +268,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
 	if (unpack_trees(nr_trees, t, &opts))
 		return 128;
 
-	if (opts.debug_unpack || opts.dry_run)
+	if (opts.internal.debug_unpack || opts.dry_run)
 		return 0; /* do not write the index out */
 
 	/*
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 6635f10..ace1d5e 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -6,6 +6,10 @@
 
 #define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
+#include "abspath.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "run-command.h"
 #include "exec-cmd.h"
 #include "strvec.h"
@@ -17,6 +21,8 @@
 #include "cache-tree.h"
 #include "unpack-trees.h"
 #include "lockfile.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "commit.h"
 #include "diff.h"
@@ -28,7 +34,9 @@
 #include "sequencer.h"
 #include "rebase-interactive.h"
 #include "reset.h"
+#include "trace2.h"
 #include "hook.h"
+#include "wrapper.h"
 
 static char const * const builtin_rebase_usage[] = {
 	N_("git rebase [-i] [options] [--exec <cmd>] "
@@ -116,13 +124,15 @@ struct rebase_options {
 	struct string_list exec;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
-	char *strategy, *strategy_opts;
+	char *strategy;
+	struct string_list strategy_opts;
 	struct strbuf git_format_patch_opt;
 	int reschedule_failed_exec;
 	int reapply_cherry_picks;
 	int fork_point;
 	int update_refs;
 	int config_autosquash;
+	int config_rebase_merges;
 	int config_update_refs;
 };
 
@@ -140,8 +150,11 @@ struct rebase_options {
 		.allow_empty_message = 1,               \
 		.autosquash = -1,                       \
 		.config_autosquash = -1,                \
+		.rebase_merges = -1,                    \
+		.config_rebase_merges = -1,             \
 		.update_refs = -1,                      \
 		.config_update_refs = -1,               \
+		.strategy_opts = STRING_LIST_INIT_NODUP,\
 	}
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
@@ -175,8 +188,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 		replay.default_strategy = NULL;
 	}
 
-	if (opts->strategy_opts)
-		parse_strategy_opts(&replay, opts->strategy_opts);
+	for (size_t i = 0; i < opts->strategy_opts.nr; i++)
+		strvec_push(&replay.xopts, opts->strategy_opts.items[i].string);
 
 	if (opts->squash_onto) {
 		oidcpy(&replay.squash_onto, opts->squash_onto);
@@ -218,13 +231,15 @@ static int get_revision_ranges(struct commit *upstream, struct commit *onto,
 	*revisions = xstrfmt("%s...%s", oid_to_hex(&base_rev->object.oid),
 			     oid_to_hex(orig_head));
 
-	shorthead = find_unique_abbrev(orig_head, DEFAULT_ABBREV);
+	shorthead = repo_find_unique_abbrev(the_repository, orig_head,
+					    DEFAULT_ABBREV);
 
 	if (upstream) {
 		const char *shortrev;
 
-		shortrev = find_unique_abbrev(&base_rev->object.oid,
-					      DEFAULT_ABBREV);
+		shortrev = repo_find_unique_abbrev(the_repository,
+						   &base_rev->object.oid,
+						   DEFAULT_ABBREV);
 
 		*shortrevisions = xstrfmt("%s..%s", shortrev, shorthead);
 	} else
@@ -482,24 +497,6 @@ static int read_basic_state(struct rebase_options *opts)
 		opts->gpg_sign_opt = xstrdup(buf.buf);
 	}
 
-	if (file_exists(state_dir_path("strategy", opts))) {
-		strbuf_reset(&buf);
-		if (!read_oneliner(&buf, state_dir_path("strategy", opts),
-				   READ_ONELINER_WARN_MISSING))
-			return -1;
-		free(opts->strategy);
-		opts->strategy = xstrdup(buf.buf);
-	}
-
-	if (file_exists(state_dir_path("strategy_opts", opts))) {
-		strbuf_reset(&buf);
-		if (!read_oneliner(&buf, state_dir_path("strategy_opts", opts),
-				   READ_ONELINER_WARN_MISSING))
-			return -1;
-		free(opts->strategy_opts);
-		opts->strategy_opts = xstrdup(buf.buf);
-	}
-
 	strbuf_release(&buf);
 
 	return 0;
@@ -517,12 +514,6 @@ static int rebase_write_basic_state(struct rebase_options *opts)
 		write_file(state_dir_path("quiet", opts), "%s", "");
 	if (opts->flags & REBASE_VERBOSE)
 		write_file(state_dir_path("verbose", opts), "%s", "");
-	if (opts->strategy)
-		write_file(state_dir_path("strategy", opts), "%s",
-			   opts->strategy);
-	if (opts->strategy_opts)
-		write_file(state_dir_path("strategy_opts", opts), "%s",
-			   opts->strategy_opts);
 	if (opts->allow_rerere_autoupdate > 0)
 		write_file(state_dir_path("allow_rerere_autoupdate", opts),
 			   "-%s-rerere-autoupdate",
@@ -660,7 +651,7 @@ static int run_am(struct rebase_options *opts)
 	format_patch.git_cmd = 1;
 	strvec_pushl(&format_patch.args, "format-patch", "-k", "--stdout",
 		     "--full-index", "--cherry-pick", "--right-only",
-		     "--src-prefix=a/", "--dst-prefix=b/", "--no-renames",
+		     "--default-prefix", "--no-renames",
 		     "--no-cover-letter", "--pretty=mboxrd", "--topo-order",
 		     "--no-base", NULL);
 	if (opts->git_format_patch_opt.len)
@@ -771,6 +762,16 @@ static int run_specific_rebase(struct rebase_options *opts)
 	return status ? -1 : 0;
 }
 
+static void parse_rebase_merges_value(struct rebase_options *options, const char *value)
+{
+	if (!strcmp("no-rebase-cousins", value))
+		options->rebase_cousins = 0;
+	else if (!strcmp("rebase-cousins", value))
+		options->rebase_cousins = 1;
+	else
+		die(_("Unknown rebase-merges mode: %s"), value);
+}
+
 static int rebase_config(const char *var, const char *value, void *data)
 {
 	struct rebase_options *opts = data;
@@ -800,6 +801,17 @@ static int rebase_config(const char *var, const char *value, void *data)
 		return 0;
 	}
 
+	if (!strcmp(var, "rebase.rebasemerges")) {
+		opts->config_rebase_merges = git_parse_maybe_bool(value);
+		if (opts->config_rebase_merges < 0) {
+			opts->config_rebase_merges = 1;
+			parse_rebase_merges_value(opts, value);
+		} else {
+			opts->rebase_cousins = 0;
+		}
+		return 0;
+	}
+
 	if (!strcmp(var, "rebase.updaterefs")) {
 		opts->config_update_refs = git_config_bool(var, value);
 		return 0;
@@ -851,7 +863,7 @@ static int checkout_up_to_date(struct rebase_options *options)
 static int is_linear_history(struct commit *from, struct commit *to)
 {
 	while (to && to != from) {
-		parse_commit(to);
+		repo_parse_commit(the_repository, to);
 		if (!to->parents)
 			return 1;
 		if (to->parents->next)
@@ -880,7 +892,7 @@ static int can_fast_forward(struct commit *onto, struct commit *upstream,
 	if (!upstream)
 		goto done;
 
-	merge_bases = get_merge_bases(upstream, head);
+	merge_bases = repo_get_merge_bases(the_repository, upstream, head);
 	if (!merge_bases || merge_bases->next)
 		goto done;
 
@@ -899,7 +911,8 @@ static void fill_branch_base(struct rebase_options *options,
 {
 	struct commit_list *merge_bases = NULL;
 
-	merge_bases = get_merge_bases(options->onto, options->orig_head);
+	merge_bases = repo_get_merge_bases(the_repository, options->onto,
+					   options->orig_head);
 	if (!merge_bases || merge_bases->next)
 		oidcpy(branch_base, null_oid());
 	else
@@ -980,6 +993,28 @@ static int parse_opt_empty(const struct option *opt, const char *arg, int unset)
 	return 0;
 }
 
+static int parse_opt_rebase_merges(const struct option *opt, const char *arg, int unset)
+{
+	struct rebase_options *options = opt->value;
+
+	options->rebase_merges = !unset;
+	options->rebase_cousins = 0;
+
+	if (arg) {
+		if (!*arg) {
+			warning(_("--rebase-merges with an empty string "
+				  "argument is deprecated and will stop "
+				  "working in a future version of Git. Use "
+				  "--rebase-merges without an argument "
+				  "instead, which does the same thing."));
+			return 0;
+		}
+		parse_rebase_merges_value(options, arg);
+	}
+
+	return 0;
+}
+
 static void NORETURN error_on_missing_default_upstream(void)
 {
 	struct branch *current_branch = branch_get(NULL);
@@ -1035,8 +1070,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	struct object_id branch_base;
 	int ignore_whitespace = 0;
 	const char *gpg_sign = NULL;
-	const char *rebase_merges = NULL;
-	struct string_list strategy_options = STRING_LIST_INIT_NODUP;
 	struct object_id squash_onto;
 	char *squash_onto_name = NULL;
 	char *keep_base_onto_name = NULL;
@@ -1137,15 +1170,14 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			   &options.allow_empty_message,
 			   N_("allow rebasing commits with empty messages"),
 			   PARSE_OPT_HIDDEN),
-		{OPTION_STRING, 'r', "rebase-merges", &rebase_merges,
-			N_("mode"),
+		OPT_CALLBACK_F('r', "rebase-merges", &options, N_("mode"),
 			N_("try to rebase merges instead of skipping them"),
-			PARSE_OPT_OPTARG, NULL, (intptr_t)""},
+			PARSE_OPT_OPTARG, parse_opt_rebase_merges),
 		OPT_BOOL(0, "fork-point", &options.fork_point,
 			 N_("use 'merge-base --fork-point' to refine upstream")),
 		OPT_STRING('s', "strategy", &options.strategy,
 			   N_("strategy"), N_("use the given merge strategy")),
-		OPT_STRING_LIST('X', "strategy-option", &strategy_options,
+		OPT_STRING_LIST('X', "strategy-option", &options.strategy_opts,
 				N_("option"),
 				N_("pass the argument through to the merge "
 				   "strategy")),
@@ -1261,7 +1293,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		int fd;
 
 		/* Sanity check */
-		if (get_oid("HEAD", &head))
+		if (repo_get_oid(the_repository, "HEAD", &head))
 			die(_("Cannot read HEAD"));
 
 		fd = repo_hold_locked_index(the_repository, &lock_file, 0);
@@ -1436,17 +1468,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	if (options.exec.nr)
 		imply_merge(&options, "--exec");
 
-	if (rebase_merges) {
-		if (!*rebase_merges)
-			; /* default mode; do nothing */
-		else if (!strcmp("rebase-cousins", rebase_merges))
-			options.rebase_cousins = 1;
-		else if (strcmp("no-rebase-cousins", rebase_merges))
-			die(_("Unknown mode: %s"), rebase_merges);
-		options.rebase_merges = 1;
-		imply_merge(&options, "--rebase-merges");
-	}
-
 	if (options.type == REBASE_APPLY) {
 		if (ignore_whitespace)
 			strvec_push(&options.git_am_opts,
@@ -1459,23 +1480,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	} else {
 		/* REBASE_MERGE */
 		if (ignore_whitespace) {
-			string_list_append(&strategy_options,
+			string_list_append(&options.strategy_opts,
 					   "ignore-space-change");
 		}
 	}
 
-	if (strategy_options.nr) {
-		int i;
-
-		if (!options.strategy)
-			options.strategy = "ort";
-
-		strbuf_reset(&buf);
-		for (i = 0; i < strategy_options.nr; i++)
-			strbuf_addf(&buf, " --%s",
-				    strategy_options.items[i].string);
-		options.strategy_opts = xstrdup(buf.buf);
-	}
+	if (options.strategy_opts.nr && !options.strategy)
+		options.strategy = "ort";
 
 	if (options.strategy) {
 		options.strategy = xstrdup(options.strategy);
@@ -1513,7 +1524,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 				die(_("apply options and merge options "
 					  "cannot be used together"));
 			else if (options.autosquash == -1 && options.config_autosquash == 1)
-				die(_("apply options are incompatible with rebase.autosquash.  Consider adding --no-autosquash"));
+				die(_("apply options are incompatible with rebase.autoSquash.  Consider adding --no-autosquash"));
+			else if (options.rebase_merges == -1 && options.config_rebase_merges == 1)
+				die(_("apply options are incompatible with rebase.rebaseMerges.  Consider adding --no-rebase-merges"));
 			else if (options.update_refs == -1 && options.config_update_refs == 1)
 				die(_("apply options are incompatible with rebase.updateRefs.  Consider adding --no-update-refs"));
 			else
@@ -1526,6 +1539,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	options.update_refs = (options.update_refs >= 0) ? options.update_refs :
 			     ((options.config_update_refs >= 0) ? options.config_update_refs : 0);
 
+	if (options.rebase_merges == 1)
+		imply_merge(&options, "--rebase-merges");
+	options.rebase_merges = (options.rebase_merges >= 0) ? options.rebase_merges :
+				((options.config_rebase_merges >= 0) ? options.config_rebase_merges : 0);
+
 	if (options.autosquash == 1)
 		imply_merge(&options, "--autosquash");
 	options.autosquash = (options.autosquash >= 0) ? options.autosquash :
@@ -1680,7 +1698,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	} else if (!options.onto_name)
 		options.onto_name = options.upstream_name;
 	if (strstr(options.onto_name, "...")) {
-		if (get_oid_mb(options.onto_name, &branch_base) < 0) {
+		if (repo_get_oid_mb(the_repository, options.onto_name, &branch_base) < 0) {
 			if (keep_base)
 				die(_("'%s': need exactly one merge base with branch"),
 				    options.upstream_name);
@@ -1783,7 +1801,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		}
 
 		/* We want color (if set), but no pager */
-		diff_setup(&opts);
+		repo_diff_setup(the_repository, &opts);
 		opts.stat_width = -1; /* use full terminal width */
 		opts.stat_graph_width = -1; /* respect statGraphWidth config */
 		opts.output_format |=
@@ -1850,10 +1868,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	free(options.gpg_sign_opt);
 	string_list_clear(&options.exec, 0);
 	free(options.strategy);
-	free(options.strategy_opts);
+	string_list_clear(&options.strategy_opts, 0);
 	strbuf_release(&options.git_format_patch_opt);
 	free(squash_onto_name);
 	free(keep_base_onto_name);
-	string_list_clear(&strategy_options, 0);
 	return !!ret;
 }
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index cd5c7a2..1a31a58 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1,6 +1,10 @@
 #include "builtin.h"
+#include "abspath.h"
 #include "repository.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "pack.h"
 #include "refs.h"
@@ -25,11 +29,17 @@
 #include "tmp-objdir.h"
 #include "oidset.h"
 #include "packfile.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "protocol.h"
 #include "commit-reach.h"
+#include "server-info.h"
+#include "trace.h"
+#include "trace2.h"
 #include "worktree.h"
 #include "shallow.h"
+#include "parse-options.h"
+#include "wrapper.h"
 
 static const char * const receive_pack_usage[] = {
 	N_("git receive-pack <git-dir>"),
@@ -136,10 +146,6 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
 	if (status)
 		return status;
 
-	status = git_gpg_config(var, value, NULL);
-	if (status)
-		return status;
-
 	if (strcmp(var, "receive.denydeletes") == 0) {
 		deny_deletes = git_config_bool(var, value);
 		return 0;
@@ -1347,7 +1353,7 @@ static int head_has_history(void)
 {
 	struct object_id oid;
 
-	return !get_oid("HEAD", &oid);
+	return !repo_get_oid(the_repository, "HEAD", &oid);
 }
 
 static const char *push_to_deploy(unsigned char *sha1,
@@ -1463,8 +1469,10 @@ static const char *update(struct command *cmd, struct shallow_info *si)
 		find_shared_symref(worktrees, "HEAD", name);
 
 	/* only refs/... are allowed */
-	if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) {
-		rp_error("refusing to create funny ref '%s' remotely", name);
+	if (!starts_with(name, "refs/") ||
+	    check_refname_format(name + 5, is_null_oid(new_oid) ?
+				 REFNAME_ALLOW_ONELEVEL : 0)) {
+		rp_error("refusing to update funny ref '%s' remotely", name);
 		ret = "funny refname";
 		goto out;
 	}
@@ -1494,7 +1502,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
 		}
 	}
 
-	if (!is_null_oid(new_oid) && !has_object_file(new_oid)) {
+	if (!is_null_oid(new_oid) && !repo_has_object_file(the_repository, new_oid)) {
 		error("unpack should have generated %s, "
 		      "but I can't find it!", oid_to_hex(new_oid));
 		ret = "bad pack";
@@ -1548,7 +1556,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
 		}
 		old_commit = (struct commit *)old_object;
 		new_commit = (struct commit *)new_object;
-		if (!in_merge_bases(old_commit, new_commit)) {
+		if (!repo_in_merge_bases(the_repository, old_commit, new_commit)) {
 			rp_error("denying non-fast-forward %s"
 				 " (you should pull first)", name);
 			ret = "non-fast-forward";
@@ -1681,11 +1689,11 @@ static void check_aliased_update_internal(struct command *cmd,
 	rp_error("refusing inconsistent update between symref '%s' (%s..%s) and"
 		 " its target '%s' (%s..%s)",
 		 cmd->ref_name,
-		 find_unique_abbrev(&cmd->old_oid, DEFAULT_ABBREV),
-		 find_unique_abbrev(&cmd->new_oid, DEFAULT_ABBREV),
+		 repo_find_unique_abbrev(the_repository, &cmd->old_oid, DEFAULT_ABBREV),
+		 repo_find_unique_abbrev(the_repository, &cmd->new_oid, DEFAULT_ABBREV),
 		 dst_cmd->ref_name,
-		 find_unique_abbrev(&dst_cmd->old_oid, DEFAULT_ABBREV),
-		 find_unique_abbrev(&dst_cmd->new_oid, DEFAULT_ABBREV));
+		 repo_find_unique_abbrev(the_repository, &dst_cmd->old_oid, DEFAULT_ABBREV),
+		 repo_find_unique_abbrev(the_repository, &dst_cmd->new_oid, DEFAULT_ABBREV));
 
 	cmd->error_string = dst_cmd->error_string =
 		"inconsistent aliased update";
@@ -2089,7 +2097,7 @@ static struct command *read_head_info(struct packet_reader *reader,
 			const char *feature_list = reader->line + linelen + 1;
 			const char *hash = NULL;
 			const char *client_sid;
-			int len = 0;
+			size_t len = 0;
 			if (parse_feature_request(feature_list, "report-status"))
 				report_status = 1;
 			if (parse_feature_request(feature_list, "report-status-v2"))
@@ -2184,7 +2192,7 @@ static const char *parse_pack_header(struct pack_header *hdr)
 	}
 }
 
-static const char *pack_lockfile;
+static struct tempfile *pack_lockfile;
 
 static void push_header_arg(struct strvec *args, struct pack_header *hdr)
 {
@@ -2251,6 +2259,7 @@ static const char *unpack(int err_fd, struct shallow_info *si)
 			return "unpack-objects abnormal exit";
 	} else {
 		char hostname[HOST_NAME_MAX + 1];
+		char *lockfile;
 
 		strvec_pushl(&child.args, "index-pack", "--stdin", NULL);
 		push_header_arg(&child.args, &hdr);
@@ -2280,8 +2289,14 @@ static const char *unpack(int err_fd, struct shallow_info *si)
 		status = start_command(&child);
 		if (status)
 			return "index-pack fork failed";
-		pack_lockfile = index_pack_lockfile(child.out, NULL);
+
+		lockfile = index_pack_lockfile(child.out, NULL);
+		if (lockfile) {
+			pack_lockfile = register_tempfile(lockfile);
+			free(lockfile);
+		}
 		close(child.out);
+
 		status = finish_command(&child);
 		if (status)
 			return "index-pack abnormal exit";
@@ -2568,8 +2583,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 		use_keepalive = KEEPALIVE_ALWAYS;
 		execute_commands(commands, unpack_status, &si,
 				 &push_options);
-		if (pack_lockfile)
-			unlink_or_warn(pack_lockfile);
+		delete_tempfile(&pack_lockfile);
 		sigchain_push(SIGPIPE, SIG_IGN);
 		if (report_status_v2)
 			report_v2(commands, unpack_status);
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 270681d..a1fa0c8 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -1,9 +1,11 @@
 #include "builtin.h"
 #include "config.h"
+#include "gettext.h"
 #include "revision.h"
 #include "reachable.h"
 #include "worktree.h"
 #include "reflog.h"
+#include "parse-options.h"
 
 #define BUILTIN_REFLOG_SHOW_USAGE \
 	N_("git reflog [show] [<log-options>] [<ref>]")
diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c
index ee338bf..282782e 100644
--- a/builtin/remote-ext.c
+++ b/builtin/remote-ext.c
@@ -197,6 +197,8 @@ static int command_loop(const char *child)
 
 int cmd_remote_ext(int argc, const char **argv, const char *prefix)
 {
+	BUG_ON_NON_EMPTY_PREFIX(prefix);
+
 	if (argc != 3)
 		usage(usage_msg);
 
diff --git a/builtin/remote-fd.c b/builtin/remote-fd.c
index b2a3980..9020fab 100644
--- a/builtin/remote-fd.c
+++ b/builtin/remote-fd.c
@@ -59,6 +59,8 @@ int cmd_remote_fd(int argc, const char **argv, const char *prefix)
 	int output_fd = -1;
 	char *end;
 
+	BUG_ON_NON_EMPTY_PREFIX(prefix);
+
 	if (argc != 3)
 		usage(usage_msg);
 
diff --git a/builtin/remote.c b/builtin/remote.c
index 729f6f3..1e0b137 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "config.h"
+#include "gettext.h"
 #include "parse-options.h"
 #include "transport.h"
 #include "remote.h"
@@ -443,7 +444,7 @@ static int get_push_ref_states(const struct ref *remote_refs,
 			info->status = PUSH_STATUS_UPTODATE;
 		else if (is_null_oid(&ref->old_oid))
 			info->status = PUSH_STATUS_CREATE;
-		else if (has_object_file(&ref->old_oid) &&
+		else if (repo_has_object_file(the_repository, &ref->old_oid) &&
 			 ref_newer(&ref->new_oid, &ref->old_oid))
 			info->status = PUSH_STATUS_FASTFORWARD;
 		else
diff --git a/builtin/repack.c b/builtin/repack.c
index f649379..0541c3c 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -1,9 +1,13 @@
 #include "builtin.h"
-#include "cache.h"
+#include "alloc.h"
 #include "config.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "parse-options.h"
 #include "run-command.h"
+#include "server-info.h"
 #include "sigchain.h"
 #include "strbuf.h"
 #include "string-list.h"
@@ -182,8 +186,9 @@ static void prepare_pack_objects(struct child_process *cmd,
  * Write oid to the given struct child_process's stdin, starting it first if
  * necessary.
  */
-static int write_oid(const struct object_id *oid, struct packed_git *pack,
-		     uint32_t pos, void *data)
+static int write_oid(const struct object_id *oid,
+		     struct packed_git *pack UNUSED,
+		     uint32_t pos UNUSED, void *data)
 {
 	struct child_process *cmd = data;
 
@@ -321,7 +326,8 @@ static int geometry_cmp(const void *va, const void *vb)
 }
 
 static void init_pack_geometry(struct pack_geometry **geometry_p,
-			       struct string_list *existing_kept_packs)
+			       struct string_list *existing_kept_packs,
+			       const struct pack_objects_args *args)
 {
 	struct packed_git *p;
 	struct pack_geometry *geometry;
@@ -331,6 +337,14 @@ static void init_pack_geometry(struct pack_geometry **geometry_p,
 	geometry = *geometry_p;
 
 	for (p = get_all_packs(the_repository); p; p = p->next) {
+		if (args->local && !p->pack_local)
+			/*
+			 * When asked to only repack local packfiles we skip
+			 * over any packfiles that are borrowed from alternate
+			 * object directories.
+			 */
+			continue;
+
 		if (!pack_kept_objects) {
 			/*
 			 * Any pack that has its pack_keep bit set will appear
@@ -444,8 +458,10 @@ static void split_pack_geometry(struct pack_geometry *geometry, int factor)
 	geometry->split = split;
 }
 
-static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry)
+static struct packed_git *get_preferred_pack(struct pack_geometry *geometry)
 {
+	uint32_t i;
+
 	if (!geometry) {
 		/*
 		 * No geometry means either an all-into-one repack (in which
@@ -460,7 +476,21 @@ static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry
 	}
 	if (geometry->split == geometry->pack_nr)
 		return NULL;
-	return geometry->pack[geometry->pack_nr - 1];
+
+	/*
+	 * The preferred pack is the largest pack above the split line. In
+	 * other words, it is the largest pack that does not get rolled up in
+	 * the geometric repack.
+	 */
+	for (i = geometry->pack_nr; i > geometry->split; i--)
+		/*
+		 * A pack that is not local would never be included in a
+		 * multi-pack index. We thus skip over any non-local packs.
+		 */
+		if (geometry->pack[i - 1]->pack_local)
+			return geometry->pack[i - 1];
+
+	return NULL;
 }
 
 static void clear_pack_geometry(struct pack_geometry *geometry)
@@ -554,6 +584,17 @@ static void midx_included_packs(struct string_list *include,
 		for (i = geometry->split; i < geometry->pack_nr; i++) {
 			struct packed_git *p = geometry->pack[i];
 
+			/*
+			 * The multi-pack index never refers to packfiles part
+			 * of an alternate object database, so we skip these.
+			 * While git-multi-pack-index(1) would silently ignore
+			 * them anyway, this allows us to skip executing the
+			 * command completely when we have only non-local
+			 * packfiles.
+			 */
+			if (!p->pack_local)
+				continue;
+
 			strbuf_addstr(&buf, pack_basename(p));
 			strbuf_strip_suffix(&buf, ".pack");
 			strbuf_addstr(&buf, ".idx");
@@ -587,7 +628,7 @@ static int write_midx_included_packs(struct string_list *include,
 {
 	struct child_process cmd = CHILD_PROCESS_INIT;
 	struct string_list_item *item;
-	struct packed_git *largest = get_largest_active_pack(geometry);
+	struct packed_git *preferred = get_preferred_pack(geometry);
 	FILE *in;
 	int ret;
 
@@ -608,9 +649,9 @@ static int write_midx_included_packs(struct string_list *include,
 	if (write_bitmaps)
 		strvec_push(&cmd.args, "--bitmap");
 
-	if (largest)
+	if (preferred)
 		strvec_pushf(&cmd.args, "--preferred-pack=%s",
-			     pack_basename(largest));
+			     pack_basename(preferred));
 
 	if (refs_snapshot)
 		strvec_pushf(&cmd.args, "--refs-snapshot=%s", refs_snapshot);
@@ -770,7 +811,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 				N_("same as -a, pack unreachable cruft objects separately"),
 				   PACK_CRUFT),
 		OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"),
-				N_("with -C, expire objects older than this")),
+				N_("with --cruft, expire objects older than this")),
 		OPT_BOOL('d', NULL, &delete_redundant,
 				N_("remove redundant packs, and run git-prune-packed")),
 		OPT_BOOL('f', NULL, &po_args.no_reuse_delta,
@@ -849,6 +890,18 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) && !write_midx)
 		die(_(incremental_bitmap_conflict_error));
 
+	if (write_bitmaps && po_args.local && has_alt_odb(the_repository)) {
+		/*
+		 * When asked to do a local repack, but we have
+		 * packfiles that are inherited from an alternate, then
+		 * we cannot guarantee that the multi-pack-index would
+		 * have full coverage of all objects. We thus disable
+		 * writing bitmaps in that case.
+		 */
+		warning(_("disabling bitmap writing, as some objects are not being packed"));
+		write_bitmaps = 0;
+	}
+
 	if (write_midx && write_bitmaps) {
 		struct strbuf path = STRBUF_INIT;
 
@@ -871,7 +924,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	if (geometric_factor) {
 		if (pack_everything)
 			die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a");
-		init_pack_geometry(&geometry, &existing_kept_packs);
+		init_pack_geometry(&geometry, &existing_kept_packs, &po_args);
 		split_pack_geometry(geometry, geometric_factor);
 	}
 
@@ -901,7 +954,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		strvec_push(&cmd.args, "--reflog");
 		strvec_push(&cmd.args, "--indexed-objects");
 	}
-	if (has_promisor_remote())
+	if (repo_has_promisor_remote(the_repository))
 		strvec_push(&cmd.args, "--exclude-promisor-objects");
 	if (!write_midx) {
 		if (write_bitmaps > 0)
diff --git a/builtin/replace.c b/builtin/replace.c
index a29e911..981f189 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -11,10 +11,17 @@
 #include "cache.h"
 #include "config.h"
 #include "builtin.h"
+#include "editor.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
 #include "parse-options.h"
 #include "run-command.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
+#include "replace-object.h"
 #include "repository.h"
 #include "tag.h"
 
@@ -54,7 +61,7 @@ static int show_reference(struct repository *r, const char *refname,
 			struct object_id object;
 			enum object_type obj_type, repl_type;
 
-			if (get_oid(refname, &object))
+			if (repo_get_oid(r, refname, &object))
 				return error(_("failed to resolve '%s' as a valid ref"), refname);
 
 			obj_type = oid_object_info(r, &object, NULL);
@@ -112,7 +119,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
 	base_len = ref.len;
 
 	for (p = argv; *p; p++) {
-		if (get_oid(*p, &oid)) {
+		if (repo_get_oid(the_repository, *p, &oid)) {
 			error("failed to resolve '%s' as a valid ref", *p);
 			had_error = 1;
 			continue;
@@ -206,10 +213,10 @@ static int replace_object(const char *object_ref, const char *replace_ref, int f
 {
 	struct object_id object, repl;
 
-	if (get_oid(object_ref, &object))
+	if (repo_get_oid(the_repository, object_ref, &object))
 		return error(_("failed to resolve '%s' as a valid ref"),
 			     object_ref);
-	if (get_oid(replace_ref, &repl))
+	if (repo_get_oid(the_repository, replace_ref, &repl))
 		return error(_("failed to resolve '%s' as a valid ref"),
 			     replace_ref);
 
@@ -320,7 +327,7 @@ static int edit_and_replace(const char *object_ref, int force, int raw)
 	struct object_id old_oid, new_oid, prev;
 	struct strbuf ref = STRBUF_INIT;
 
-	if (get_oid(object_ref, &old_oid) < 0)
+	if (repo_get_oid(the_repository, object_ref, &old_oid) < 0)
 		return error(_("not a valid object name: '%s'"), object_ref);
 
 	type = oid_object_info(the_repository, &old_oid, NULL);
@@ -375,7 +382,7 @@ static int replace_parents(struct strbuf *buf, int argc, const char **argv)
 		struct object_id oid;
 		struct commit *commit;
 
-		if (get_oid(argv[i], &oid) < 0) {
+		if (repo_get_oid(the_repository, argv[i], &oid) < 0) {
 			strbuf_release(&new_parents);
 			return error(_("not a valid object name: '%s'"),
 				     argv[i]);
@@ -422,7 +429,7 @@ static int check_one_mergetag(struct commit *commit,
 	/* iterate over new parents */
 	for (i = 1; i < mergetag_data->argc; i++) {
 		struct object_id oid;
-		if (get_oid(mergetag_data->argv[i], &oid) < 0)
+		if (repo_get_oid(the_repository, mergetag_data->argv[i], &oid) < 0)
 			return error(_("not a valid object name: '%s'"),
 				     mergetag_data->argv[i]);
 		if (oideq(get_tagged_oid(tag), &oid))
@@ -452,15 +459,15 @@ static int create_graft(int argc, const char **argv, int force, int gentle)
 	const char *buffer;
 	unsigned long size;
 
-	if (get_oid(old_ref, &old_oid) < 0)
+	if (repo_get_oid(the_repository, old_ref, &old_oid) < 0)
 		return error(_("not a valid object name: '%s'"), old_ref);
 	commit = lookup_commit_reference(the_repository, &old_oid);
 	if (!commit)
 		return error(_("could not parse %s"), old_ref);
 
-	buffer = get_commit_buffer(commit, &size);
+	buffer = repo_get_commit_buffer(the_repository, commit, &size);
 	strbuf_add(&buf, buffer, size);
-	unuse_commit_buffer(commit, buffer);
+	repo_unuse_commit_buffer(the_repository, commit, buffer);
 
 	if (replace_parents(&buf, argc - 1, &argv[1]) < 0) {
 		strbuf_release(&buf);
diff --git a/builtin/rerere.c b/builtin/rerere.c
index 94ffb8c..d4bd527 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -2,9 +2,12 @@
 #include "cache.h"
 #include "config.h"
 #include "dir.h"
+#include "gettext.h"
 #include "parse-options.h"
+#include "repository.h"
 #include "string-list.h"
 #include "rerere.h"
+#include "wrapper.h"
 #include "xdiff/xdiff.h"
 #include "xdiff-interface.h"
 #include "pathspec.h"
diff --git a/builtin/reset.c b/builtin/reset.c
index 0697fa8..f99f32d 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -9,7 +9,11 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
+#include "advice.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "tag.h"
 #include "object.h"
@@ -20,11 +24,15 @@
 #include "diffcore.h"
 #include "tree.h"
 #include "branch.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "unpack-trees.h"
 #include "cache-tree.h"
+#include "setup.h"
 #include "submodule.h"
 #include "submodule-config.h"
+#include "trace.h"
+#include "trace2.h"
 #include "dir.h"
 #include "add-interactive.h"
 
@@ -89,7 +97,7 @@ static int reset_index(const char *ref, const struct object_id *oid, int reset_t
 
 	if (reset_type == KEEP) {
 		struct object_id head_oid;
-		if (get_oid("HEAD", &head_oid))
+		if (repo_get_oid(the_repository, "HEAD", &head_oid))
 			return error(_("You do not have a valid HEAD."));
 		if (!fill_tree_descriptor(the_repository, desc + nr, &head_oid))
 			return error(_("Failed to find tree of HEAD."));
@@ -124,7 +132,7 @@ static void print_new_head_line(struct commit *commit)
 	struct strbuf buf = STRBUF_INIT;
 
 	printf(_("HEAD is now at %s"),
-		find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
+		repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));
 
 	pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
 	if (buf.len > 0)
@@ -260,8 +268,8 @@ static void parse_args(struct pathspec *pathspec,
 		 * has to be unambiguous. If there is a single argument, it
 		 * can not be a tree
 		 */
-		else if ((!argv[1] && !get_oid_committish(argv[0], &unused)) ||
-			 (argv[1] && !get_oid_treeish(argv[0], &unused))) {
+		else if ((!argv[1] && !repo_get_oid_committish(the_repository, argv[0], &unused)) ||
+			 (argv[1] && !repo_get_oid_treeish(the_repository, argv[0], &unused))) {
 			/*
 			 * Ok, argv[0] looks like a commit/tree; it should not
 			 * be a filename.
@@ -288,9 +296,9 @@ static int reset_refs(const char *rev, const struct object_id *oid)
 	struct object_id *orig = NULL, oid_orig,
 		*old_orig = NULL, oid_old_orig;
 
-	if (!get_oid("ORIG_HEAD", &oid_old_orig))
+	if (!repo_get_oid(the_repository, "ORIG_HEAD", &oid_old_orig))
 		old_orig = &oid_old_orig;
-	if (!get_oid("HEAD", &oid_orig)) {
+	if (!repo_get_oid(the_repository, "HEAD", &oid_orig)) {
 		orig = &oid_orig;
 		set_reflog_message(&msg, "updating ORIG_HEAD", NULL);
 		update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0,
@@ -317,7 +325,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 	int reset_type = NONE, update_ref_status = 0, quiet = 0;
 	int no_refresh = 0;
 	int patch_mode = 0, pathspec_file_nul = 0, unborn;
-	const char *rev, *pathspec_from_file = NULL;
+	const char *rev;
+	char *pathspec_from_file = NULL;
 	struct object_id oid;
 	struct pathspec pathspec;
 	int intent_to_add = 0;
@@ -365,13 +374,14 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
-	unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
+	unborn = !strcmp(rev, "HEAD") && repo_get_oid(the_repository, "HEAD",
+						      &oid);
 	if (unborn) {
 		/* reset on unborn branch: treat as reset to empty tree */
 		oidcpy(&oid, the_hash_algo->empty_tree);
 	} else if (!pathspec.nr && !patch_mode) {
 		struct commit *commit;
-		if (get_oid_committish(rev, &oid))
+		if (repo_get_oid_committish(the_repository, rev, &oid))
 			die(_("Failed to resolve '%s' as a valid revision."), rev);
 		commit = lookup_commit_reference(the_repository, &oid);
 		if (!commit)
@@ -379,7 +389,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		oidcpy(&oid, &commit->object.oid);
 	} else {
 		struct tree *tree;
-		if (get_oid_treeish(rev, &oid))
+		if (repo_get_oid_treeish(the_repository, rev, &oid))
 			die(_("Failed to resolve '%s' as a valid tree."), rev);
 		tree = parse_tree_indirect(&oid);
 		if (!tree)
@@ -464,7 +474,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			char *ref = NULL;
 			int err;
 
-			dwim_ref(rev, strlen(rev), &dummy, &ref, 0);
+			repo_dwim_ref(the_repository, rev, strlen(rev),
+				      &dummy, &ref, 0);
 			if (ref && !starts_with(ref, "refs/"))
 				FREE_AND_NULL(ref);
 
@@ -495,5 +506,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 cleanup:
 	clear_pathspec(&pathspec);
+	free(pathspec_from_file);
 	return update_ref_status;
 }
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index d42db0b..6dc8be4 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -2,11 +2,16 @@
 #include "config.h"
 #include "commit.h"
 #include "diff.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "revision.h"
 #include "list-objects.h"
 #include "list-objects-filter.h"
 #include "list-objects-filter-options.h"
 #include "object.h"
+#include "object-name.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "pack.h"
 #include "pack-bitmap.h"
@@ -38,7 +43,7 @@ static const char rev_list_usage[] =
 "    --tags\n"
 "    --remotes\n"
 "    --stdin\n"
-"    --exclude-hidden=[receive|uploadpack]\n"
+"    --exclude-hidden=[fetch|receive|uploadpack]\n"
 "    --quiet\n"
 "  ordering output:\n"
 "    --topo-order\n"
@@ -134,7 +139,7 @@ static void show_commit(struct commit *commit, void *data)
 		if (!revs->graph)
 			fputs(get_revision_mark(revs, commit), stdout);
 		if (revs->abbrev_commit && revs->abbrev)
-			fputs(find_unique_abbrev(&commit->object.oid, revs->abbrev),
+			fputs(repo_find_unique_abbrev(the_repository, &commit->object.oid, revs->abbrev),
 			      stdout);
 		else
 			fputs(oid_to_hex(&commit->object.oid), stdout);
@@ -257,7 +262,8 @@ static inline void finish_object__ma(struct object *obj)
 	}
 }
 
-static int finish_object(struct object *obj, const char *name, void *cb_data)
+static int finish_object(struct object *obj, const char *name UNUSED,
+			 void *cb_data)
 {
 	struct rev_list_info *info = cb_data;
 	if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) {
@@ -362,11 +368,11 @@ static int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
 
 static int show_object_fast(
 	const struct object_id *oid,
-	enum object_type type,
-	int exclude,
-	uint32_t name_hash,
-	struct packed_git *found_pack,
-	off_t found_offset)
+	enum object_type type UNUSED,
+	int exclude UNUSED,
+	uint32_t name_hash UNUSED,
+	struct packed_git *found_pack UNUSED,
+	off_t found_offset UNUSED)
 {
 	fprintf(stdout, "%s\n", oid_to_hex(oid));
 	return 1;
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index e67999e..852e49e 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -5,14 +5,21 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
 #include "commit.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
 #include "quote.h"
 #include "builtin.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "diff.h"
 #include "revision.h"
+#include "setup.h"
 #include "split-index.h"
 #include "submodule.h"
 #include "commit-reach.h"
@@ -136,7 +143,9 @@ static void show_rev(int type, const struct object_id *oid, const char *name)
 			struct object_id discard;
 			char *full;
 
-			switch (dwim_ref(name, strlen(name), &discard, &full, 0)) {
+			switch (repo_dwim_ref(the_repository, name,
+					      strlen(name), &discard, &full,
+					      0)) {
 			case 0:
 				/*
 				 * Not found -- not a ref.  We could
@@ -162,7 +171,8 @@ static void show_rev(int type, const struct object_id *oid, const char *name)
 		}
 	}
 	else if (abbrev)
-		show_with_type(type, find_unique_abbrev(oid, abbrev));
+		show_with_type(type,
+			       repo_find_unique_abbrev(the_repository, oid, abbrev));
 	else
 		show_with_type(type, oid_to_hex(oid));
 }
@@ -187,7 +197,7 @@ static int show_default(void)
 		struct object_id oid;
 
 		def = NULL;
-		if (!get_oid(s, &oid)) {
+		if (!repo_get_oid(the_repository, s, &oid)) {
 			show_rev(NORMAL, &oid, s);
 			return 1;
 		}
@@ -279,7 +289,7 @@ static int try_difference(const char *arg)
 		return 0;
 	}
 
-	if (!get_oid_committish(start, &start_oid) && !get_oid_committish(end, &end_oid)) {
+	if (!repo_get_oid_committish(the_repository, start, &start_oid) && !repo_get_oid_committish(the_repository, end, &end_oid)) {
 		show_rev(NORMAL, &end_oid, end);
 		show_rev(symmetric ? NORMAL : REVERSED, &start_oid, start);
 		if (symmetric) {
@@ -291,7 +301,7 @@ static int try_difference(const char *arg)
 				*dotdot = '.';
 				return 0;
 			}
-			exclude = get_merge_bases(a, b);
+			exclude = repo_get_merge_bases(the_repository, a, b);
 			while (exclude) {
 				struct commit *commit = pop_commit(&exclude);
 				show_rev(REVERSED, &commit->object.oid, NULL);
@@ -337,7 +347,7 @@ static int try_parent_shorthands(const char *arg)
 		return 0;
 
 	*dotdot = 0;
-	if (get_oid_committish(arg, &oid) ||
+	if (repo_get_oid_committish(the_repository, arg, &oid) ||
 	    !(commit = lookup_commit_reference(the_repository, &oid))) {
 		*dotdot = '^';
 		return 0;
@@ -868,7 +878,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 				continue;
 			}
 			if (skip_prefix(arg, "--disambiguate=", &arg)) {
-				for_each_abbrev(arg, show_abbrev, NULL);
+				repo_for_each_abbrev(the_repository, arg,
+						     show_abbrev, NULL);
 				continue;
 			}
 			if (!strcmp(arg, "--bisect")) {
diff --git a/builtin/revert.c b/builtin/revert.c
index 77d2035..0240ec8 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -1,8 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
 #include "builtin.h"
 #include "parse-options.h"
 #include "diff.h"
+#include "gettext.h"
 #include "revision.h"
 #include "rerere.h"
 #include "dir.h"
@@ -43,20 +45,6 @@ static const char * const *revert_or_cherry_pick_usage(struct replay_opts *opts)
 	return opts->action == REPLAY_REVERT ? revert_usage : cherry_pick_usage;
 }
 
-static int option_parse_x(const struct option *opt,
-			  const char *arg, int unset)
-{
-	struct replay_opts **opts_ptr = opt->value;
-	struct replay_opts *opts = *opts_ptr;
-
-	if (unset)
-		return 0;
-
-	ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
-	opts->xopts[opts->xopts_nr++] = xstrdup(arg);
-	return 0;
-}
-
 static int option_parse_m(const struct option *opt,
 			  const char *arg, int unset)
 {
@@ -93,7 +81,8 @@ static void verify_opt_compatible(const char *me, const char *base_opt, ...)
 		die(_("%s: %s cannot be used with %s"), me, this_opt, base_opt);
 }
 
-static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
+static int run_sequencer(int argc, const char **argv, const char *prefix,
+			 struct replay_opts *opts)
 {
 	const char * const * usage_str = revert_or_cherry_pick_usage(opts);
 	const char *me = action_name(opts);
@@ -113,8 +102,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
 			     N_("select mainline parent"), option_parse_m),
 		OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
 		OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")),
-		OPT_CALLBACK('X', "strategy-option", &opts, N_("option"),
-			N_("option for merge strategy"), option_parse_x),
+		OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"),
+			N_("option for merge strategy")),
 		{ OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"),
 		  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 		OPT_END()
@@ -140,7 +129,7 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
 		options = parse_options_concat(options, cp_extra);
 	}
 
-	argc = parse_options(argc, argv, NULL, options, usage_str,
+	argc = parse_options(argc, argv, prefix, options, usage_str,
 			PARSE_OPT_KEEP_ARGV0 |
 			PARSE_OPT_KEEP_UNKNOWN_OPT);
 
@@ -175,7 +164,7 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
 				"--signoff", opts->signoff,
 				"--mainline", opts->mainline,
 				"--strategy", opts->strategy ? 1 : 0,
-				"--strategy-option", opts->xopts ? 1 : 0,
+				"--strategy-option", opts->xopts.nr ? 1 : 0,
 				"-x", opts->record_origin,
 				"--ff", opts->allow_ff,
 				"--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE,
@@ -245,7 +234,7 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
 
 	opts.action = REPLAY_REVERT;
 	sequencer_init_config(&opts);
-	res = run_sequencer(argc, argv, &opts);
+	res = run_sequencer(argc, argv, prefix, &opts);
 	if (res < 0)
 		die(_("revert failed"));
 	replay_opts_release(&opts);
@@ -259,7 +248,7 @@ int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
 
 	opts.action = REPLAY_PICK;
 	sequencer_init_config(&opts);
-	res = run_sequencer(argc, argv, &opts);
+	res = run_sequencer(argc, argv, prefix, &opts);
 	if (res < 0)
 		die(_("cherry-pick failed"));
 	replay_opts_release(&opts);
diff --git a/builtin/rm.c b/builtin/rm.c
index 8844f90..b4589c8 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -5,14 +5,20 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
+#include "alloc.h"
 #include "advice.h"
 #include "config.h"
 #include "lockfile.h"
 #include "dir.h"
 #include "cache-tree.h"
+#include "gettext.h"
+#include "hash.h"
 #include "tree-walk.h"
+#include "object-name.h"
 #include "parse-options.h"
+#include "repository.h"
 #include "string-list.h"
+#include "setup.h"
 #include "submodule.h"
 #include "pathspec.h"
 
@@ -370,7 +376,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 	 */
 	if (!force) {
 		struct object_id oid;
-		if (get_oid("HEAD", &oid))
+		if (repo_get_oid(the_repository, "HEAD", &oid))
 			oidclr(&oid);
 		if (check_local_mod(&oid, index_only))
 			exit(1);
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 4c5d125..4784143 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "config.h"
 #include "commit.h"
+#include "hex.h"
 #include "refs.h"
 #include "pkt-line.h"
 #include "sideband.h"
@@ -15,6 +16,8 @@
 #include "gpg-interface.h"
 #include "gettext.h"
 #include "protocol.h"
+#include "parse-options.h"
+#include "write-or-die.h"
 
 static const char * const send_pack_usage[] = {
 	N_("git send-pack [--mirror] [--dry-run] [--force]\n"
@@ -130,8 +133,6 @@ static void print_helper_status(struct ref *ref)
 
 static int send_pack_config(const char *k, const char *v, void *cb)
 {
-	git_gpg_config(k, v, NULL);
-
 	if (!strcmp(k, "push.gpgsign")) {
 		const char *value;
 		if (!git_config_get_value("push.gpgsign", &value)) {
@@ -275,7 +276,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 		fd[0] = 0;
 		fd[1] = 1;
 	} else {
-		conn = git_connect(fd, dest, receivepack,
+		conn = git_connect(fd, dest, "git-receive-pack", receivepack,
 			args.verbose ? CONNECT_VERBOSE : 0);
 	}
 
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 27a8716..46f4e08 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -3,10 +3,13 @@
 #include "config.h"
 #include "commit.h"
 #include "diff.h"
+#include "environment.h"
+#include "gettext.h"
 #include "string-list.h"
 #include "revision.h"
 #include "utf8.h"
 #include "mailmap.h"
+#include "setup.h"
 #include "shortlog.h"
 #include "parse-options.h"
 #include "trailer.h"
@@ -176,10 +179,11 @@ static void insert_records_from_trailers(struct shortlog *log,
 		return;
 
 	/*
-	 * Using format_commit_message("%B") would be simpler here, but
+	 * Using repo_format_commit_message("%B") would be simpler here, but
 	 * this saves us copying the message.
 	 */
-	commit_buffer = logmsg_reencode(commit, NULL, ctx->output_encoding);
+	commit_buffer = repo_logmsg_reencode(the_repository, commit, NULL,
+					     ctx->output_encoding);
 	body = strstr(commit_buffer, "\n\n");
 	if (!body)
 		return;
@@ -202,7 +206,7 @@ static void insert_records_from_trailers(struct shortlog *log,
 	trailer_iterator_release(&iter);
 
 	strbuf_release(&ident);
-	unuse_commit_buffer(commit, commit_buffer);
+	repo_unuse_commit_buffer(the_repository, commit, commit_buffer);
 }
 
 static int shortlog_needs_dedup(const struct shortlog *log)
@@ -222,7 +226,8 @@ static void insert_records_from_format(struct shortlog *log,
 	for_each_string_list_item(item, &log->format) {
 		strbuf_reset(&buf);
 
-		format_commit_message(commit, item->string, &buf, ctx);
+		repo_format_commit_message(the_repository, commit,
+					   item->string, &buf, ctx);
 
 		if (!shortlog_needs_dedup(log) || strset_add(dups, buf.buf))
 			insert_one_record(log, buf.buf, oneline);
@@ -248,7 +253,8 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
 		if (log->user_format)
 			pretty_print_commit(&ctx, commit, &oneline);
 		else
-			format_commit_message(commit, "%s", &oneline, &ctx);
+			repo_format_commit_message(the_repository, commit,
+						   "%s", &oneline, &ctx);
 	}
 	oneline_str = oneline.len ? oneline.buf : "<none>";
 
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 358ac3e..7ef4a64 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -1,11 +1,17 @@
 #include "cache.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hash.h"
+#include "hex.h"
 #include "pretty.h"
 #include "refs.h"
 #include "builtin.h"
 #include "color.h"
 #include "strvec.h"
+#include "object-name.h"
 #include "parse-options.h"
+#include "repository.h"
 #include "dir.h"
 #include "commit-slab.h"
 #include "date.h"
@@ -240,7 +246,7 @@ static void join_revs(struct commit_list **list_p,
 			parents = parents->next;
 			if ((this_flag & flags) == flags)
 				continue;
-			parse_commit(p);
+			repo_parse_commit(the_repository, p);
 			if (mark_seen(p, seen_p) && !still_interesting)
 				extra--;
 			p->object.flags |= flags;
@@ -312,8 +318,8 @@ static void show_one_commit(struct commit *commit, int no_name)
 		}
 		else
 			printf("[%s] ",
-			       find_unique_abbrev(&commit->object.oid,
-						  DEFAULT_ABBREV));
+			       repo_find_unique_abbrev(the_repository, &commit->object.oid,
+						       DEFAULT_ABBREV));
 	}
 	puts(pretty_str);
 	strbuf_release(&pretty);
@@ -414,7 +420,7 @@ static int append_head_ref(const char *refname, const struct object_id *oid,
 	/* If both heads/foo and tags/foo exists, get_sha1 would
 	 * get confused.
 	 */
-	if (get_oid(refname + ofs, &tmp) || !oideq(&tmp, oid))
+	if (repo_get_oid(the_repository, refname + ofs, &tmp) || !oideq(&tmp, oid))
 		ofs = 5;
 	return append_ref(refname + ofs, oid, 0);
 }
@@ -429,7 +435,7 @@ static int append_remote_ref(const char *refname, const struct object_id *oid,
 	/* If both heads/foo and tags/foo exists, get_sha1 would
 	 * get confused.
 	 */
-	if (get_oid(refname + ofs, &tmp) || !oideq(&tmp, oid))
+	if (repo_get_oid(the_repository, refname + ofs, &tmp) || !oideq(&tmp, oid))
 		ofs = 5;
 	return append_ref(refname + ofs, oid, 0);
 }
@@ -533,7 +539,7 @@ static int show_independent(struct commit **rev,
 static void append_one_rev(const char *av)
 {
 	struct object_id revkey;
-	if (!get_oid(av, &revkey)) {
+	if (!repo_get_oid(the_repository, av, &revkey)) {
 		append_ref(av, &revkey, 0);
 		return;
 	}
@@ -746,7 +752,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 			die(Q_("only %d entry can be shown at one time.",
 			       "only %d entries can be shown at one time.",
 			       MAX_REVS), MAX_REVS);
-		if (!dwim_ref(*av, strlen(*av), &oid, &ref, 0))
+		if (!repo_dwim_ref(the_repository, *av, strlen(*av), &oid,
+				   &ref, 0))
 			die(_("no such ref %s"), *av);
 
 		/* Has the base been specified? */
@@ -836,13 +843,13 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 			die(Q_("cannot handle more than %d rev.",
 			       "cannot handle more than %d revs.",
 			       MAX_REVS), MAX_REVS);
-		if (get_oid(ref_name[num_rev], &revkey))
+		if (repo_get_oid(the_repository, ref_name[num_rev], &revkey))
 			die(_("'%s' is not a valid ref."), ref_name[num_rev]);
 		commit = lookup_commit_reference(the_repository, &revkey);
 		if (!commit)
 			die(_("cannot find commit %s (%s)"),
 			    ref_name[num_rev], oid_to_hex(&revkey));
-		parse_commit(commit);
+		repo_parse_commit(the_repository, commit);
 		mark_seen(commit, &seen);
 
 		/* rev#0 uses bit REV_SHIFT, rev#1 uses bit REV_SHIFT+1,
diff --git a/builtin/show-index.c b/builtin/show-index.c
index 0e0b9fb..d839e55 100644
--- a/builtin/show-index.c
+++ b/builtin/show-index.c
@@ -1,7 +1,11 @@
 #include "builtin.h"
 #include "cache.h"
+#include "gettext.h"
+#include "hash.h"
+#include "hex.h"
 #include "pack.h"
 #include "parse-options.h"
+#include "repository.h"
 
 static const char *const show_index_usage[] = {
 	"git show-index [--object-format=<hash-algorithm>]",
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 3af6a53..a2243b4 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -1,7 +1,10 @@
 #include "builtin.h"
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "object.h"
 #include "tag.h"
@@ -26,14 +29,14 @@ static void show_one(const char *refname, const struct object_id *oid)
 	const char *hex;
 	struct object_id peeled;
 
-	if (!has_object_file(oid))
+	if (!repo_has_object_file(the_repository, oid))
 		die("git show-ref: bad ref %s (%s)", refname,
 		    oid_to_hex(oid));
 
 	if (quiet)
 		return;
 
-	hex = find_unique_abbrev(oid, abbrev);
+	hex = repo_find_unique_abbrev(the_repository, oid, abbrev);
 	if (hash_only)
 		printf("%s\n", hex);
 	else
@@ -43,7 +46,7 @@ static void show_one(const char *refname, const struct object_id *oid)
 		return;
 
 	if (!peel_iterated_oid(oid, &peeled)) {
-		hex = find_unique_abbrev(&peeled, abbrev);
+		hex = repo_find_unique_abbrev(the_repository, &peeled, abbrev);
 		printf("%s %s^{}\n", hex, refname);
 	}
 }
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index c373815..40d420f 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -2,6 +2,10 @@
 #include "cache.h"
 #include "config.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "pathspec.h"
 #include "repository.h"
@@ -14,13 +18,14 @@
 #include "unpack-trees.h"
 #include "wt-status.h"
 #include "quote.h"
+#include "setup.h"
 #include "sparse-index.h"
 #include "worktree.h"
 
 static const char *empty_base = "";
 
 static char const * const builtin_sparse_checkout_usage[] = {
-	N_("git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"),
+	N_("git sparse-checkout (init | list | set | add | reapply | disable | check-rules) [<options>]"),
 	NULL
 };
 
@@ -57,6 +62,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix)
 	char *sparse_filename;
 	int res;
 
+	setup_work_tree();
 	if (!core_apply_sparse_checkout)
 		die(_("this worktree is not sparse"));
 
@@ -217,16 +223,14 @@ static int update_working_directory(struct pattern_list *pl)
 	o.head_idx = -1;
 	o.src_index = r->index;
 	o.dst_index = r->index;
-	index_state_init(&o.result, r);
 	o.skip_sparse_checkout = 0;
-	o.pl = pl;
 
 	setup_work_tree();
 
 	repo_hold_locked_index(r, &lock_file, LOCK_DIE_ON_ERROR);
 
 	setup_unpack_trees_porcelain(&o, "sparse-checkout");
-	result = update_sparsity(&o);
+	result = update_sparsity(&o, pl);
 	clear_unpack_trees_porcelain(&o);
 
 	if (result == UPDATE_SPARSITY_WARNINGS)
@@ -383,13 +387,7 @@ static int set_config(enum sparse_checkout_mode mode)
 	return 0;
 }
 
-static int update_modes(int *cone_mode, int *sparse_index)
-{
-	int mode, record_mode;
-
-	/* Determine if we need to record the mode; ensure sparse checkout on */
-	record_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;
-
+static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {
 	/* If not specified, use previous definition of cone mode */
 	if (*cone_mode == -1 && core_apply_sparse_checkout)
 		*cone_mode = core_sparse_checkout_cone;
@@ -397,12 +395,21 @@ static int update_modes(int *cone_mode, int *sparse_index)
 	/* Set cone/non-cone mode appropriately */
 	core_apply_sparse_checkout = 1;
 	if (*cone_mode == 1 || *cone_mode == -1) {
-		mode = MODE_CONE_PATTERNS;
 		core_sparse_checkout_cone = 1;
-	} else {
-		mode = MODE_ALL_PATTERNS;
-		core_sparse_checkout_cone = 0;
+		return MODE_CONE_PATTERNS;
 	}
+	core_sparse_checkout_cone = 0;
+	return MODE_ALL_PATTERNS;
+}
+
+static int update_modes(int *cone_mode, int *sparse_index)
+{
+	int mode, record_mode;
+
+	/* Determine if we need to record the mode; ensure sparse checkout on */
+	record_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;
+
+	mode = update_cone_mode(cone_mode);
 	if (record_mode && set_config(mode))
 		return 1;
 
@@ -448,6 +455,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix)
 		OPT_END(),
 	};
 
+	setup_work_tree();
 	repo_read_index(the_repository);
 
 	init_opts.cone_mode = -1;
@@ -471,7 +479,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix)
 		return update_working_directory(NULL);
 	}
 
-	if (get_oid("HEAD", &oid)) {
+	if (repo_get_oid(the_repository, "HEAD", &oid)) {
 		FILE *fp;
 
 		/* assume we are in a fresh repo, but update the sparse-checkout file */
@@ -545,7 +553,7 @@ static void strbuf_to_cone_pattern(struct strbuf *line, struct pattern_list *pl)
 
 static void add_patterns_from_input(struct pattern_list *pl,
 				    int argc, const char **argv,
-				    int use_stdin)
+				    FILE *file)
 {
 	int i;
 	if (core_sparse_checkout_cone) {
@@ -555,9 +563,9 @@ static void add_patterns_from_input(struct pattern_list *pl,
 		hashmap_init(&pl->parent_hashmap, pl_hashmap_cmp, NULL, 0);
 		pl->use_cone_patterns = 1;
 
-		if (use_stdin) {
+		if (file) {
 			struct strbuf unquoted = STRBUF_INIT;
-			while (!strbuf_getline(&line, stdin)) {
+			while (!strbuf_getline(&line, file)) {
 				if (line.buf[0] == '"') {
 					strbuf_reset(&unquoted);
 					if (unquote_c_style(&unquoted, line.buf, NULL))
@@ -579,10 +587,10 @@ static void add_patterns_from_input(struct pattern_list *pl,
 			}
 		}
 	} else {
-		if (use_stdin) {
+		if (file) {
 			struct strbuf line = STRBUF_INIT;
 
-			while (!strbuf_getline(&line, stdin)) {
+			while (!strbuf_getline(&line, file)) {
 				size_t len;
 				char *buf = strbuf_detach(&line, &len);
 				add_pattern(buf, empty_base, 0, pl, 0);
@@ -609,7 +617,8 @@ static void add_patterns_cone_mode(int argc, const char **argv,
 	struct pattern_list existing;
 	char *sparse_filename = get_sparse_checkout_filename();
 
-	add_patterns_from_input(pl, argc, argv, use_stdin);
+	add_patterns_from_input(pl, argc, argv,
+				use_stdin ? stdin : NULL);
 
 	memset(&existing, 0, sizeof(existing));
 	existing.use_cone_patterns = core_sparse_checkout_cone;
@@ -646,7 +655,7 @@ static void add_patterns_literal(int argc, const char **argv,
 					   pl, NULL, 0))
 		die(_("unable to load existing sparse-checkout patterns"));
 	free(sparse_filename);
-	add_patterns_from_input(pl, argc, argv, use_stdin);
+	add_patterns_from_input(pl, argc, argv, use_stdin ? stdin : NULL);
 }
 
 static int modify_pattern_list(int argc, const char **argv, int use_stdin,
@@ -665,7 +674,8 @@ static int modify_pattern_list(int argc, const char **argv, int use_stdin,
 		break;
 
 	case REPLACE:
-		add_patterns_from_input(pl, argc, argv, use_stdin);
+		add_patterns_from_input(pl, argc, argv,
+					use_stdin ? stdin : NULL);
 		break;
 	}
 
@@ -760,6 +770,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix)
 		OPT_END(),
 	};
 
+	setup_work_tree();
 	if (!core_apply_sparse_checkout)
 		die(_("no sparse-checkout to add to"));
 
@@ -806,6 +817,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
 		OPT_END(),
 	};
 
+	setup_work_tree();
 	repo_read_index(the_repository);
 
 	set_opts.cone_mode = -1;
@@ -855,6 +867,7 @@ static int sparse_checkout_reapply(int argc, const char **argv,
 		OPT_END(),
 	};
 
+	setup_work_tree();
 	if (!core_apply_sparse_checkout)
 		die(_("must be in a sparse-checkout to reapply sparsity patterns"));
 
@@ -898,6 +911,7 @@ static int sparse_checkout_disable(int argc, const char **argv,
 	 * forcibly return to a dense checkout regardless of initial state.
 	 */
 
+	setup_work_tree();
 	argc = parse_options(argc, argv, prefix,
 			     builtin_sparse_checkout_disable_options,
 			     builtin_sparse_checkout_disable_usage, 0);
@@ -923,6 +937,91 @@ static int sparse_checkout_disable(int argc, const char **argv,
 	return set_config(MODE_NO_PATTERNS);
 }
 
+static char const * const builtin_sparse_checkout_check_rules_usage[] = {
+	N_("git sparse-checkout check-rules [-z] [--skip-checks]"
+	   "[--[no-]cone] [--rules-file <file>]"),
+	NULL
+};
+
+static struct sparse_checkout_check_rules_opts {
+	int cone_mode;
+	int null_termination;
+	char *rules_file;
+} check_rules_opts;
+
+static int check_rules(struct pattern_list *pl, int null_terminated) {
+	struct strbuf line = STRBUF_INIT;
+	struct strbuf unquoted = STRBUF_INIT;
+	char *path;
+	int line_terminator = null_terminated ? 0 : '\n';
+	strbuf_getline_fn getline_fn = null_terminated ? strbuf_getline_nul
+		: strbuf_getline;
+	the_repository->index->sparse_checkout_patterns = pl;
+	while (!getline_fn(&line, stdin)) {
+		path = line.buf;
+		if (!null_terminated && line.buf[0] == '"') {
+			strbuf_reset(&unquoted);
+			if (unquote_c_style(&unquoted, line.buf, NULL))
+				die(_("unable to unquote C-style string '%s'"),
+					line.buf);
+
+			path = unquoted.buf;
+		}
+
+		if (path_in_sparse_checkout(path, the_repository->index))
+			write_name_quoted(path, stdout, line_terminator);
+	}
+	strbuf_release(&line);
+	strbuf_release(&unquoted);
+
+	return 0;
+}
+
+static int sparse_checkout_check_rules(int argc, const char **argv, const char *prefix)
+{
+	static struct option builtin_sparse_checkout_check_rules_options[] = {
+		OPT_BOOL('z', NULL, &check_rules_opts.null_termination,
+			 N_("terminate input and output files by a NUL character")),
+		OPT_BOOL(0, "cone", &check_rules_opts.cone_mode,
+			 N_("when used with --rules-file interpret patterns as cone mode patterns")),
+		OPT_FILENAME(0, "rules-file", &check_rules_opts.rules_file,
+			 N_("use patterns in <file> instead of the current ones.")),
+		OPT_END(),
+	};
+
+	FILE *fp;
+	int ret;
+	struct pattern_list pl = {0};
+	char *sparse_filename;
+	check_rules_opts.cone_mode = -1;
+
+	argc = parse_options(argc, argv, prefix,
+			     builtin_sparse_checkout_check_rules_options,
+			     builtin_sparse_checkout_check_rules_usage,
+			     PARSE_OPT_KEEP_UNKNOWN_OPT);
+
+	if (check_rules_opts.rules_file && check_rules_opts.cone_mode < 0)
+		check_rules_opts.cone_mode = 1;
+
+	update_cone_mode(&check_rules_opts.cone_mode);
+	pl.use_cone_patterns = core_sparse_checkout_cone;
+	if (check_rules_opts.rules_file) {
+		fp = xfopen(check_rules_opts.rules_file, "r");
+		add_patterns_from_input(&pl, argc, argv, fp);
+		fclose(fp);
+	} else {
+		sparse_filename = get_sparse_checkout_filename();
+		if (add_patterns_from_file_to_list(sparse_filename, "", 0, &pl,
+						   NULL, 0))
+			die(_("unable to load existing sparse-checkout patterns"));
+		free(sparse_filename);
+	}
+
+	ret = check_rules(&pl, check_rules_opts.null_termination);
+	clear_pattern_list(&pl);
+	return ret;
+}
+
 int cmd_sparse_checkout(int argc, const char **argv, const char *prefix)
 {
 	parse_opt_subcommand_fn *fn = NULL;
@@ -933,6 +1032,7 @@ int cmd_sparse_checkout(int argc, const char **argv, const char *prefix)
 		OPT_SUBCOMMAND("add", &fn, sparse_checkout_add),
 		OPT_SUBCOMMAND("reapply", &fn, sparse_checkout_reapply),
 		OPT_SUBCOMMAND("disable", &fn, sparse_checkout_disable),
+		OPT_SUBCOMMAND("check-rules", &fn, sparse_checkout_check_rules),
 		OPT_END(),
 	};
 
diff --git a/builtin/stash.c b/builtin/stash.c
index 3a4f9fd..a7e17ff 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1,6 +1,11 @@
 #define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
+#include "abspath.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "refs.h"
 #include "lockfile.h"
@@ -14,6 +19,7 @@
 #include "entry.h"
 #include "rerere.h"
 #include "revision.h"
+#include "setup.h"
 #include "log-tree.h"
 #include "diffcore.h"
 #include "exec-cmd.h"
@@ -201,7 +207,7 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
 
 	revision = info->revision.buf;
 
-	if (get_oid(revision, &info->w_commit))
+	if (repo_get_oid(the_repository, revision, &info->w_commit))
 		return error(_("%s is not a valid reference"), revision);
 
 	assert_stash_like(info, revision);
@@ -211,7 +217,8 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
 	end_of_rev = strchrnul(revision, '@');
 	strbuf_add(&symbolic, revision, end_of_rev - revision);
 
-	ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref, 0);
+	ret = repo_dwim_ref(the_repository, symbolic.buf, symbolic.len,
+			    &dummy, &expanded_ref, 0);
 	strbuf_release(&symbolic);
 	switch (ret) {
 	case 0: /* Not found, but valid ref */
@@ -231,7 +238,7 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
 static int do_clear_stash(void)
 {
 	struct object_id obj;
-	if (get_oid(ref_stash, &obj))
+	if (repo_get_oid(the_repository, ref_stash, &obj))
 		return 0;
 
 	return delete_ref(NULL, ref_stash, &obj, 0);
@@ -427,7 +434,7 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
 	 * to the index before a merge was run) and the current index
 	 * (reflecting the changes brought in by the merge).
 	 */
-	diff_setup(&diff_opts);
+	repo_diff_setup(the_repository, &diff_opts);
 	diff_opts.flags.recursive = 1;
 	diff_opts.detect_rename = 0;
 	diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
@@ -600,7 +607,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
 		ret = error(_("could not write index"));
 
 	if (ret) {
-		rerere(0);
+		repo_rerere(the_repository, 0);
 
 		if (index)
 			fprintf_ln(stderr, _("Index was not unstashed."));
@@ -900,7 +907,7 @@ static int show_stash(int argc, const char **argv, const char *prefix)
 
 	init_diff_ui_defaults();
 	git_config(git_diff_ui_config, NULL);
-	init_revisions(&rev, prefix);
+	repo_init_revisions(the_repository, &rev, prefix);
 
 	argc = parse_options(argc, argv, prefix, options, git_stash_show_usage,
 			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT |
@@ -1083,13 +1090,13 @@ static int check_changes_tracked_files(const struct pathspec *ps)
 	int ret = 0;
 
 	/* No initial commit. */
-	if (get_oid("HEAD", &dummy))
+	if (repo_get_oid(the_repository, "HEAD", &dummy))
 		return -1;
 
 	if (repo_read_index(the_repository) < 0)
 		return -1;
 
-	init_revisions(&rev, NULL);
+	repo_init_revisions(the_repository, &rev, NULL);
 	copy_pathspec(&rev.prune_data, ps);
 
 	rev.diffopt.flags.quick = 1;
@@ -1276,7 +1283,7 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
 	struct strbuf diff_output = STRBUF_INIT;
 	struct index_state istate = INDEX_STATE_INIT(the_repository);
 
-	init_revisions(&rev, NULL);
+	repo_init_revisions(the_repository, &rev, NULL);
 	copy_pathspec(&rev.prune_data, ps);
 
 	set_alternate_index_output(stash_index_path.buf);
@@ -1355,7 +1362,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
 		goto done;
 	}
 
-	if (get_oid("HEAD", &info->b_commit)) {
+	if (repo_get_oid(the_repository, "HEAD", &info->b_commit)) {
 		if (!quiet)
 			fprintf_ln(stderr, _("You do not have "
 					     "the initial commit yet"));
@@ -1373,8 +1380,9 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
 	branch_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
 	if (flags & REF_ISSYMREF)
 		skip_prefix(branch_ref, "refs/heads/", &branch_name);
-	head_short_sha1 = find_unique_abbrev(&head_commit->object.oid,
-					     DEFAULT_ABBREV);
+	head_short_sha1 = repo_find_unique_abbrev(the_repository,
+						  &head_commit->object.oid,
+						  DEFAULT_ABBREV);
 	strbuf_addf(&msg, "%s: %s ", branch_name, head_short_sha1);
 	pp_commit_easy(CMIT_FMT_ONELINE, head_commit, &msg);
 
@@ -1465,7 +1473,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
 	return ret;
 }
 
-static int create_stash(int argc, const char **argv, const char *prefix)
+static int create_stash(int argc, const char **argv, const char *prefix UNUSED)
 {
 	int ret;
 	struct strbuf stash_msg_buf = STRBUF_INIT;
diff --git a/builtin/stripspace.c b/builtin/stripspace.c
index 1e34cf2..9451eb6 100644
--- a/builtin/stripspace.c
+++ b/builtin/stripspace.c
@@ -1,8 +1,11 @@
 #include "builtin.h"
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
 #include "parse-options.h"
+#include "setup.h"
 #include "strbuf.h"
+#include "write-or-die.h"
 
 static void comment_lines(struct strbuf *buf)
 {
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 4c173d8..6bf8d66 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1,5 +1,10 @@
 #define USE_THE_INDEX_VARIABLE
 #include "builtin.h"
+#include "abspath.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "cache.h"
 #include "config.h"
@@ -7,6 +12,7 @@
 #include "quote.h"
 #include "pathspec.h"
 #include "dir.h"
+#include "setup.h"
 #include "submodule.h"
 #include "submodule-config.h"
 #include "string-list.h"
@@ -18,6 +24,8 @@
 #include "revision.h"
 #include "diffcore.h"
 #include "diff.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "advice.h"
 #include "branch.h"
@@ -557,7 +565,7 @@ static int module_init(int argc, const char **argv, const char *prefix)
 	 * If there are no path args and submodule.active is set then,
 	 * by default, only initialize 'active' modules.
 	 */
-	if (!argc && git_config_get_value_multi("submodule.active"))
+	if (!argc && !git_config_get("submodule.active"))
 		module_list_active(&list);
 
 	info.prefix = prefix;
@@ -1108,7 +1116,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
 		strvec_pushv(&diff_args, info->argv);
 
 	git_config(git_diff_basic_config, NULL);
-	init_revisions(&rev, info->prefix);
+	repo_init_revisions(the_repository, &rev, info->prefix);
 	rev.abbrev = 0;
 	precompose_argv_prefix(diff_args.nr, diff_args.v, NULL);
 	setup_revisions(diff_args.nr, diff_args.v, &rev, &opt);
@@ -1174,7 +1182,7 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 	if (!summary_limit)
 		return 0;
 
-	if (!get_oid(argc ? argv[0] : "HEAD", &head_oid)) {
+	if (!repo_get_oid(the_repository, argc ? argv[0] : "HEAD", &head_oid)) {
 		if (argc) {
 			argv++;
 			argc--;
@@ -1187,7 +1195,7 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 			argc--;
 		}
 	} else {
-		if (get_oid("HEAD", &head_oid))
+		if (repo_get_oid(the_repository, "HEAD", &head_oid))
 			die(_("could not fetch a revision for HEAD"));
 	}
 
@@ -2132,9 +2140,9 @@ static int update_clone_get_next_task(struct child_process *child,
 	return 0;
 }
 
-static int update_clone_start_failure(struct strbuf *err,
+static int update_clone_start_failure(struct strbuf *err UNUSED,
 				      void *suc_cb,
-				      void *idx_task_cb)
+				      void *idx_task_cb UNUSED)
 {
 	struct submodule_update_clone *suc = suc_cb;
 
@@ -2743,7 +2751,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
 		 * If there are no path args and submodule.active is set then,
 		 * by default, only initialize 'active' modules.
 		 */
-		if (!argc && git_config_get_value_multi("submodule.active"))
+		if (!argc && !git_config_get("submodule.active"))
 			module_list_active(&list);
 
 		info.prefix = opt.prefix;
@@ -2764,7 +2772,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
 	return ret;
 }
 
-static int push_check(int argc, const char **argv, const char *prefix)
+static int push_check(int argc, const char **argv, const char *prefix UNUSED)
 {
 	struct remote *remote;
 	const char *superproject_head;
@@ -3140,7 +3148,6 @@ static int config_submodule_in_gitmodules(const char *name, const char *var, con
 static void configure_added_submodule(struct add_data *add_data)
 {
 	char *key;
-	const char *val;
 	struct child_process add_submod = CHILD_PROCESS_INIT;
 	struct child_process add_gitmodules = CHILD_PROCESS_INIT;
 
@@ -3185,7 +3192,7 @@ static void configure_added_submodule(struct add_data *add_data)
 	 * is_submodule_active(), since that function needs to find
 	 * out the value of "submodule.active" again anyway.
 	 */
-	if (!git_config_get_string_tmp("submodule.active", &val)) {
+	if (!git_config_get("submodule.active")) {
 		/*
 		 * If the submodule being added isn't already covered by the
 		 * current configured pathspec, set the submodule's active flag
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index e00768a..10198a7 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "config.h"
 #include "cache.h"
+#include "gettext.h"
 #include "refs.h"
 #include "parse-options.h"
 
diff --git a/builtin/tag.c b/builtin/tag.c
index d428c45..49b64c7 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -7,9 +7,15 @@
  */
 
 #include "cache.h"
+#include "advice.h"
 #include "config.h"
 #include "builtin.h"
+#include "editor.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "tag.h"
 #include "run-command.h"
@@ -21,6 +27,7 @@
 #include "column.h"
 #include "ref-filter.h"
 #include "date.h"
+#include "write-or-die.h"
 
 static const char * const git_tag_usage[] = {
 	N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n"
@@ -37,6 +44,7 @@ static const char * const git_tag_usage[] = {
 static unsigned int colopts;
 static int force_sign_annotate;
 static int config_sign_tag = -1; /* unspecified */
+static int omit_empty = 0;
 
 static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
 		     struct ref_format *format)
@@ -66,6 +74,7 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
 		die(_("unable to parse format string"));
 	filter->with_commit_tag_algo = 1;
 	filter_refs(&array, filter, FILTER_REFS_TAGS);
+	filter_ahead_behind(the_repository, format, &array);
 	ref_array_sort(sorting, &array);
 
 	for (i = 0; i < array.nr; i++) {
@@ -74,7 +83,8 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
 		if (format_ref_array_item(array.items[i], format, &output, &err))
 			die("%s", err.buf);
 		fwrite(output.buf, 1, output.len, stdout);
-		putchar('\n');
+		if (output.len || !omit_empty)
+			putchar('\n');
 	}
 
 	strbuf_release(&err);
@@ -137,7 +147,7 @@ static int delete_tags(const char **argv)
 		if (!ref_exists(name))
 			printf(_("Deleted tag '%s' (was %s)\n"),
 				item->string + 10,
-				find_unique_abbrev(oid, DEFAULT_ABBREV));
+				repo_find_unique_abbrev(the_repository, oid, DEFAULT_ABBREV));
 
 		free(oid);
 	}
@@ -180,8 +190,6 @@ static const char tag_template_nocleanup[] =
 
 static int git_tag_config(const char *var, const char *value, void *cb)
 {
-	int status;
-
 	if (!strcmp(var, "tag.gpgsign")) {
 		config_sign_tag = git_config_bool(var, value);
 		return 0;
@@ -194,9 +202,6 @@ static int git_tag_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
-	status = git_gpg_config(var, value, cb);
-	if (status)
-		return status;
 	if (!strcmp(var, "tag.forcesignannotated")) {
 		force_sign_annotate = git_config_bool(var, value);
 		return 0;
@@ -215,7 +220,7 @@ static void write_tag_body(int fd, const struct object_id *oid)
 	struct strbuf payload = STRBUF_INIT;
 	struct strbuf signature = STRBUF_INIT;
 
-	orig = buf = read_object_file(oid, &type, &size);
+	orig = buf = repo_read_object_file(the_repository, oid, &type, &size);
 	if (!buf)
 		return;
 	if (parse_signature(buf, size, &payload, &signature)) {
@@ -266,11 +271,10 @@ static const char message_advice_nested_tag[] =
 static void create_tag(const struct object_id *object, const char *object_ref,
 		       const char *tag,
 		       struct strbuf *buf, struct create_tag_options *opt,
-		       struct object_id *prev, struct object_id *result)
+		       struct object_id *prev, struct object_id *result, char *path)
 {
 	enum object_type type;
 	struct strbuf header = STRBUF_INIT;
-	char *path = NULL;
 
 	type = oid_object_info(the_repository, object, NULL);
 	if (type <= OBJ_NONE)
@@ -294,7 +298,6 @@ static void create_tag(const struct object_id *object, const char *object_ref,
 		int fd;
 
 		/* write the template message before editing: */
-		path = git_pathdup("TAG_EDITMSG");
 		fd = xopen(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
 
 		if (opt->message_given) {
@@ -336,10 +339,6 @@ static void create_tag(const struct object_id *object, const char *object_ref,
 				path);
 		exit(128);
 	}
-	if (path) {
-		unlink_or_warn(path);
-		free(path);
-	}
 }
 
 static void create_reflog_msg(const struct object_id *oid, struct strbuf *sb)
@@ -366,7 +365,7 @@ static void create_reflog_msg(const struct object_id *oid, struct strbuf *sb)
 		strbuf_addstr(sb, "object of unknown type");
 		break;
 	case OBJ_COMMIT:
-		if ((buf = read_object_file(oid, &type, &size))) {
+		if ((buf = repo_read_object_file(the_repository, oid, &type, &size))) {
 			subject_len = find_commit_subject(buf, &subject_start);
 			strbuf_insert(sb, sb->len, subject_start, subject_len);
 		} else {
@@ -433,7 +432,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	int create_reflog = 0;
 	int annotate = 0, force = 0;
 	int cmdmode = 0, create_tag_object = 0;
-	const char *msgfile = NULL, *keyid = NULL;
+	char *msgfile = NULL;
+	const char *keyid = NULL;
 	struct msg_arg msg = { .buf = STRBUF_INIT };
 	struct ref_transaction *transaction;
 	struct strbuf err = STRBUF_INIT;
@@ -473,6 +473,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_WITHOUT(&filter.no_commit, N_("print only tags that don't contain the commit")),
 		OPT_MERGED(&filter, N_("print only tags that are merged")),
 		OPT_NO_MERGED(&filter, N_("print only tags that are not merged")),
+		OPT_BOOL(0, "omit-empty",  &omit_empty,
+			N_("do not output a newline after empty formatted refs")),
 		OPT_REF_SORT(&sorting_options),
 		{
 			OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"),
@@ -487,6 +489,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	};
 	int ret = 0;
 	const char *only_in_list = NULL;
+	char *path = NULL;
 
 	setup_ref_filter_porcelain_msg();
 
@@ -593,7 +596,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	if (argc > 2)
 		die(_("too many arguments"));
 
-	if (get_oid(object_ref, &object))
+	if (repo_get_oid(the_repository, object_ref, &object))
 		die(_("Failed to resolve '%s' as a valid ref."), object_ref);
 
 	if (strbuf_check_tag_ref(&ref, tag))
@@ -621,7 +624,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	if (create_tag_object) {
 		if (force_sign_annotate && !annotate)
 			opt.sign = 1;
-		create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object);
+		path = git_pathdup("TAG_EDITMSG");
+		create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object,
+			   path);
 	}
 
 	transaction = ref_transaction_begin(&err);
@@ -629,12 +634,21 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	    ref_transaction_update(transaction, ref.buf, &object, &prev,
 				   create_reflog ? REF_FORCE_CREATE_REFLOG : 0,
 				   reflog_msg.buf, &err) ||
-	    ref_transaction_commit(transaction, &err))
+	    ref_transaction_commit(transaction, &err)) {
+		if (path)
+			fprintf(stderr,
+				_("The tag message has been left in %s\n"),
+				path);
 		die("%s", err.buf);
+	}
+	if (path) {
+		unlink_or_warn(path);
+		free(path);
+	}
 	ref_transaction_free(transaction);
 	if (force && !is_null_oid(&prev) && !oideq(&prev, &object))
 		printf(_("Updated tag '%s' (was %s)\n"), tag,
-		       find_unique_abbrev(&prev, DEFAULT_ABBREV));
+		       repo_find_unique_abbrev(the_repository, &prev, DEFAULT_ABBREV));
 
 cleanup:
 	ref_sorting_release(sorting);
@@ -643,5 +657,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	strbuf_release(&reflog_msg);
 	strbuf_release(&msg.buf);
 	strbuf_release(&err);
+	free(msgfile);
 	return ret;
 }
diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c
index 88de32b..b35a4b9 100644
--- a/builtin/unpack-file.c
+++ b/builtin/unpack-file.c
@@ -1,6 +1,9 @@
 #include "builtin.h"
 #include "config.h"
+#include "hex.h"
+#include "object-name.h"
 #include "object-store.h"
+#include "wrapper.h"
 
 static char *create_temp_file(struct object_id *oid)
 {
@@ -10,7 +13,7 @@ static char *create_temp_file(struct object_id *oid)
 	unsigned long size;
 	int fd;
 
-	buf = read_object_file(oid, &type, &size);
+	buf = repo_read_object_file(the_repository, oid, &type, &size);
 	if (!buf || type != OBJ_BLOB)
 		die("unable to read blob object %s", oid_to_hex(oid));
 
@@ -23,13 +26,13 @@ static char *create_temp_file(struct object_id *oid)
 	return path;
 }
 
-int cmd_unpack_file(int argc, const char **argv, const char *prefix)
+int cmd_unpack_file(int argc, const char **argv, const char *prefix UNUSED)
 {
 	struct object_id oid;
 
 	if (argc != 2 || !strcmp(argv[1], "-h"))
 		usage("git unpack-file <blob>");
-	if (get_oid(argv[1], &oid))
+	if (repo_get_oid(the_repository, argv[1], &oid))
 		die("Not a valid object name %s", argv[1]);
 
 	git_config(git_default_config, NULL);
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 43789b8..2c52c3a 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -2,12 +2,17 @@
 #include "cache.h"
 #include "bulk-checkin.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "git-zlib.h"
+#include "hex.h"
 #include "object-store.h"
 #include "object.h"
 #include "delta.h"
 #include "pack.h"
 #include "blob.h"
 #include "commit.h"
+#include "replace-object.h"
 #include "tag.h"
 #include "tree.h"
 #include "tree-walk.h"
@@ -442,7 +447,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
 		delta_data = get_data(delta_size);
 		if (!delta_data)
 			return;
-		if (has_object_file(&base_oid))
+		if (repo_has_object_file(the_repository, &base_oid))
 			; /* Ok we have this one */
 		else if (resolve_against_held(nr, &base_oid,
 					      delta_data, delta_size))
@@ -508,7 +513,8 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
 	if (resolve_against_held(nr, &base_oid, delta_data, delta_size))
 		return;
 
-	base = read_object_file(&base_oid, &type, &base_size);
+	base = repo_read_object_file(the_repository, &base_oid, &type,
+				     &base_size);
 	if (!base) {
 		error("failed to read delta-pack base object %s",
 		      oid_to_hex(&base_oid));
@@ -598,7 +604,7 @@ static void unpack_all(void)
 		die("unresolved deltas left after unpacking");
 }
 
-int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
+int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED)
 {
 	int i;
 	struct object_id oid;
diff --git a/builtin/update-index.c b/builtin/update-index.c
index bf38885..5fab9ad 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -7,18 +7,27 @@
 #include "cache.h"
 #include "bulk-checkin.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hash.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "quote.h"
 #include "cache-tree.h"
 #include "tree-walk.h"
 #include "builtin.h"
+#include "object-file.h"
 #include "refs.h"
 #include "resolve-undo.h"
 #include "parse-options.h"
 #include "pathspec.h"
 #include "dir.h"
+#include "repository.h"
+#include "setup.h"
 #include "split-index.h"
+#include "symlinks.h"
 #include "fsmonitor.h"
+#include "write-or-die.h"
 
 /*
  * Default to not allowing changes to the list of files. The
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index a84e7b4..0c59b1c 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -1,9 +1,13 @@
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
+#include "hash.h"
 #include "refs.h"
 #include "builtin.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "quote.h"
+#include "repository.h"
 #include "strvec.h"
 
 static const char * const git_update_ref_usage[] = {
@@ -116,7 +120,7 @@ static int parse_next_oid(const char **next, const char *end,
 		(*next)++;
 		*next = parse_arg(*next, &arg);
 		if (arg.len) {
-			if (get_oid(arg.buf, oid))
+			if (repo_get_oid(the_repository, arg.buf, oid))
 				goto invalid;
 		} else {
 			/* Without -z, an empty value means all zeros: */
@@ -134,7 +138,7 @@ static int parse_next_oid(const char **next, const char *end,
 		*next += arg.len;
 
 		if (arg.len) {
-			if (get_oid(arg.buf, oid))
+			if (repo_get_oid(the_repository, arg.buf, oid))
 				goto invalid;
 		} else if (flags & PARSE_SHA1_ALLOW_EMPTY) {
 			/* With -z, treat an empty value as all zeros: */
@@ -549,7 +553,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 		refname = argv[0];
 		value = argv[1];
 		oldval = argv[2];
-		if (get_oid(value, &oid))
+		if (repo_get_oid(the_repository, value, &oid))
 			die("%s: not a valid SHA1", value);
 	}
 
@@ -560,7 +564,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 			 * must not already exist:
 			 */
 			oidclr(&oldoid);
-		else if (get_oid(oldval, &oldoid))
+		else if (repo_get_oid(the_repository, oldval, &oldoid))
 			die("%s: not a valid old SHA1", oldval);
 	}
 
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index d2239c9..19dce3c 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -1,7 +1,9 @@
 #include "cache.h"
 #include "config.h"
 #include "builtin.h"
+#include "gettext.h"
 #include "parse-options.h"
+#include "server-info.h"
 
 static const char * const update_server_info_usage[] = {
 	"git update-server-info [-f | --force]",
diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c
index 945ee2b..44ad400 100644
--- a/builtin/upload-archive.c
+++ b/builtin/upload-archive.c
@@ -6,6 +6,7 @@
 #include "archive.h"
 #include "pkt-line.h"
 #include "sideband.h"
+#include "repository.h"
 #include "run-command.h"
 #include "strvec.h"
 
@@ -79,6 +80,8 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
 {
 	struct child_process writer = CHILD_PROCESS_INIT;
 
+	BUG_ON_NON_EMPTY_PREFIX(prefix);
+
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage(upload_archive_usage);
 
diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c
index 25b69da..beb9dd0 100644
--- a/builtin/upload-pack.c
+++ b/builtin/upload-pack.c
@@ -1,9 +1,11 @@
 #include "cache.h"
 #include "builtin.h"
 #include "exec-cmd.h"
+#include "gettext.h"
 #include "pkt-line.h"
 #include "parse-options.h"
 #include "protocol.h"
+#include "replace-object.h"
 #include "upload-pack.h"
 #include "serve.h"
 
diff --git a/builtin/var.c b/builtin/var.c
index a80c1df..2149998 100644
--- a/builtin/var.c
+++ b/builtin/var.c
@@ -5,6 +5,9 @@
  */
 #include "builtin.h"
 #include "config.h"
+#include "editor.h"
+#include "ident.h"
+#include "pager.h"
 #include "refs.h"
 
 static const char var_usage[] = "git var (-l | <variable>)";
@@ -77,7 +80,7 @@ static int show_config(const char *var, const char *value, void *cb)
 	return git_default_config(var, value, cb);
 }
 
-int cmd_var(int argc, const char **argv, const char *prefix)
+int cmd_var(int argc, const char **argv, const char *prefix UNUSED)
 {
 	const struct git_var *git_var;
 	const char *val;
diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c
index 3ebad32..5d99b82 100644
--- a/builtin/verify-commit.c
+++ b/builtin/verify-commit.c
@@ -8,6 +8,8 @@
 #include "cache.h"
 #include "config.h"
 #include "builtin.h"
+#include "gettext.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "repository.h"
 #include "commit.h"
@@ -39,7 +41,7 @@ static int verify_commit(const char *name, unsigned flags)
 	struct object_id oid;
 	struct object *obj;
 
-	if (get_oid(name, &oid))
+	if (repo_get_oid(the_repository, name, &oid))
 		return error("commit '%s' not found.", name);
 
 	obj = parse_object(the_repository, &oid);
@@ -52,14 +54,6 @@ static int verify_commit(const char *name, unsigned flags)
 	return run_gpg_verify((struct commit *)obj, flags);
 }
 
-static int git_verify_commit_config(const char *var, const char *value, void *cb)
-{
-	int status = git_gpg_config(var, value, cb);
-	if (status)
-		return status;
-	return git_default_config(var, value, cb);
-}
-
 int cmd_verify_commit(int argc, const char **argv, const char *prefix)
 {
 	int i = 1, verbose = 0, had_error = 0;
@@ -70,7 +64,7 @@ int cmd_verify_commit(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
-	git_config(git_verify_commit_config, NULL);
+	git_config(git_default_config, NULL);
 
 	argc = parse_options(argc, argv, prefix, verify_commit_options,
 			     verify_commit_usage, PARSE_OPT_KEEP_ARGV0);
diff --git a/builtin/verify-pack.c b/builtin/verify-pack.c
index 27d6f75..190fd69 100644
--- a/builtin/verify-pack.c
+++ b/builtin/verify-pack.c
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "cache.h"
 #include "config.h"
+#include "gettext.h"
 #include "run-command.h"
 #include "parse-options.h"
 
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index 2175669..c6019a0 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -8,8 +8,10 @@
 #include "cache.h"
 #include "config.h"
 #include "builtin.h"
+#include "gettext.h"
 #include "tag.h"
 #include "run-command.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "gpg-interface.h"
 #include "ref-filter.h"
@@ -19,14 +21,6 @@ static const char * const verify_tag_usage[] = {
 		NULL
 };
 
-static int git_verify_tag_config(const char *var, const char *value, void *cb)
-{
-	int status = git_gpg_config(var, value, cb);
-	if (status)
-		return status;
-	return git_default_config(var, value, cb);
-}
-
 int cmd_verify_tag(int argc, const char **argv, const char *prefix)
 {
 	int i = 1, verbose = 0, had_error = 0;
@@ -39,7 +33,7 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
-	git_config(git_verify_tag_config, NULL);
+	git_config(git_default_config, NULL);
 
 	argc = parse_options(argc, argv, prefix, verify_tag_options,
 			     verify_tag_usage, PARSE_OPT_KEEP_ARGV0);
@@ -60,7 +54,7 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
 		struct object_id oid;
 		const char *name = argv[i++];
 
-		if (get_oid(name, &oid)) {
+		if (repo_get_oid(the_repository, name, &oid)) {
 			had_error = !!error("tag '%s' not found.", name);
 			continue;
 		}
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 254283a..f318046 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -1,18 +1,27 @@
 #include "cache.h"
+#include "abspath.h"
 #include "checkout.h"
 #include "config.h"
+#include "copy.h"
 #include "builtin.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "strvec.h"
 #include "branch.h"
 #include "refs.h"
+#include "repository.h"
 #include "run-command.h"
 #include "hook.h"
 #include "sigchain.h"
 #include "submodule.h"
 #include "utf8.h"
 #include "worktree.h"
+#include "wrapper.h"
 #include "quote.h"
 
 #define BUILTIN_WORKTREE_ADD_USAGE \
@@ -319,7 +328,6 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir)
 
 	if (file_exists(from_file)) {
 		struct config_set cs = { { 0 } };
-		const char *core_worktree;
 		int bare;
 
 		if (safe_create_leading_directories(to_file) ||
@@ -338,7 +346,7 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir)
 				to_file, "core.bare", NULL, "true", 0))
 			error(_("failed to unset '%s' in '%s'"),
 				"core.bare", to_file);
-		if (!git_configset_get_value(&cs, "core.worktree", &core_worktree) &&
+		if (!git_configset_get(&cs, "core.worktree") &&
 			git_config_set_in_file_gently(to_file,
 							"core.worktree", NULL))
 			error(_("failed to unset '%s' in '%s'"),
@@ -552,7 +560,7 @@ static void print_preparing_worktree_line(int detach,
 		else
 			fprintf_ln(stderr, _("Preparing worktree (resetting branch '%s'; was at %s)"),
 				  new_branch,
-				  find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
+				  repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));
 	} else if (new_branch) {
 		fprintf_ln(stderr, _("Preparing worktree (new branch '%s')"), new_branch);
 	} else {
@@ -566,7 +574,7 @@ static void print_preparing_worktree_line(int detach,
 			if (!commit)
 				die(_("invalid reference: %s"), branch);
 			fprintf_ln(stderr, _("Preparing worktree (detached HEAD %s)"),
-				  find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
+				  repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));
 		}
 		strbuf_release(&s);
 	}
@@ -756,7 +764,7 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
 		strbuf_addstr(&sb, "(bare)");
 	else {
 		strbuf_addf(&sb, "%-*s ", abbrev_len,
-				find_unique_abbrev(&wt->head_oid, DEFAULT_ABBREV));
+				repo_find_unique_abbrev(the_repository, &wt->head_oid, DEFAULT_ABBREV));
 		if (wt->is_detached)
 			strbuf_addstr(&sb, "(detached HEAD)");
 		else if (wt->head_ref) {
@@ -793,7 +801,7 @@ static void measure_widths(struct worktree **wt, int *abbrev, int *maxlen)
 
 		if (path_len > *maxlen)
 			*maxlen = path_len;
-		sha1_len = strlen(find_unique_abbrev(&wt[i]->head_oid, *abbrev));
+		sha1_len = strlen(repo_find_unique_abbrev(the_repository, &wt[i]->head_oid, *abbrev));
 		if (sha1_len > *abbrev)
 			*abbrev = sha1_len;
 	}
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index 0780103..84b8331 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -7,9 +7,13 @@
 #include "builtin.h"
 #include "cache.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "tree.h"
 #include "cache-tree.h"
 #include "parse-options.h"
+#include "repository.h"
 
 static const char * const write_tree_usage[] = {
 	N_("git write-tree [--missing-ok] [--prefix=<prefix>/]"),
@@ -38,6 +42,9 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)
 	argc = parse_options(argc, argv, cmd_prefix, write_tree_options,
 			     write_tree_usage, 0);
 
+	prepare_repo_settings(the_repository);
+	the_repository->settings.command_requires_full_index = 0;
+
 	ret = write_index_as_tree(&oid, &the_index, get_index_file(), flags,
 				  tree_prefix);
 	switch (ret) {
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 855b68e..d843279 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -1,8 +1,12 @@
 /*
  * Copyright (c) 2011, Google Inc.
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "bulk-checkin.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "repository.h"
 #include "csum-file.h"
@@ -11,7 +15,9 @@
 #include "string-list.h"
 #include "tmp-objdir.h"
 #include "packfile.h"
+#include "object-file.h"
 #include "object-store.h"
+#include "wrapper.h"
 
 static int odb_transaction_nesting;
 
@@ -124,7 +130,7 @@ static int already_written(struct bulk_checkin_packfile *state, struct object_id
 	int i;
 
 	/* The object may already exist in the repository */
-	if (has_object_file(oid))
+	if (repo_has_object_file(the_repository, oid))
 		return 1;
 
 	/* Might want to keep the list sorted */
diff --git a/bulk-checkin.h b/bulk-checkin.h
index 8281b9c..48fe9a6 100644
--- a/bulk-checkin.h
+++ b/bulk-checkin.h
@@ -4,7 +4,7 @@
 #ifndef BULK_CHECKIN_H
 #define BULK_CHECKIN_H
 
-#include "cache.h"
+#include "object.h"
 
 void prepare_loose_object_bulk_checkin(void);
 void fsync_loose_object_bulk_checkin(int fd, const char *filename);
diff --git a/bundle-uri.c b/bundle-uri.c
index 8a3c39c..2a2db1a 100644
--- a/bundle-uri.c
+++ b/bundle-uri.c
@@ -1,6 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "bundle-uri.h"
 #include "bundle.h"
+#include "copy.h"
+#include "environment.h"
+#include "gettext.h"
 #include "object-store.h"
 #include "refs.h"
 #include "run-command.h"
@@ -792,6 +795,15 @@ int fetch_bundle_uri(struct repository *r, const char *uri,
 
 	init_bundle_list(&list);
 
+	/*
+	 * Do not fetch an empty bundle URI. An empty bundle URI
+	 * could signal that a configured bundle URI has been disabled.
+	 */
+	if (!*uri) {
+		result = 0;
+		goto cleanup;
+	}
+
 	/* If a bundle is added to this global list, then it is required. */
 	list.mode = BUNDLE_MODE_ALL;
 
@@ -884,7 +896,7 @@ int bundle_uri_command(struct repository *r,
 	 * Read all "bundle.*" config lines to the client as key=value
 	 * packet lines.
 	 */
-	git_config(config_to_packet_line, &writer);
+	repo_config(r, config_to_packet_line, &writer);
 
 	packet_writer_flush(&writer);
 
diff --git a/bundle.c b/bundle.c
index 6ab6cd7..a550536 100644
--- a/bundle.c
+++ b/bundle.c
@@ -1,6 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "lockfile.h"
 #include "bundle.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "object-store.h"
 #include "repository.h"
 #include "object.h"
@@ -13,6 +16,7 @@
 #include "strvec.h"
 #include "list-objects-filter-options.h"
 #include "connected.h"
+#include "write-or-die.h"
 
 static const char v2_bundle_signature[] = "# v2 git bundle\n";
 static const char v3_bundle_signature[] = "# v3 git bundle\n";
@@ -293,7 +297,7 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
 	if (revs->max_age == -1 && revs->min_age == -1)
 		goto out;
 
-	buf = read_object_file(&tag->oid, &type, &size);
+	buf = repo_read_object_file(the_repository, &tag->oid, &type, &size);
 	if (!buf)
 		goto out;
 	line = memmem(buf, size, "\ntagger ", 8);
@@ -382,7 +386,8 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
 
 		if (e->item->flags & UNINTERESTING)
 			continue;
-		if (dwim_ref(e->name, strlen(e->name), &oid, &ref, 0) != 1)
+		if (repo_dwim_ref(the_repository, e->name, strlen(e->name),
+				  &oid, &ref, 0) != 1)
 			goto skip_write_ref;
 		if (read_ref_full(e->name, RESOLVE_REF_READING, &oid, &flag))
 			flag = 0;
diff --git a/bundle.h b/bundle.h
index 9f2bd73..021adbd 100644
--- a/bundle.h
+++ b/bundle.h
@@ -2,7 +2,6 @@
 #define BUNDLE_H
 
 #include "strvec.h"
-#include "cache.h"
 #include "string-list.h"
 #include "list-objects-filter-options.h"
 
diff --git a/cache-tree.c b/cache-tree.c
index 88c2c04..ebfe649 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -1,13 +1,19 @@
 #include "cache.h"
+#include "alloc.h"
+#include "environment.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "cache-tree.h"
 #include "bulk-checkin.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "replace-object.h"
 #include "promisor-remote.h"
 #include "sparse-index.h"
+#include "trace.h"
+#include "trace2.h"
 
 #ifndef DEBUG_CACHE_TREE
 #define DEBUG_CACHE_TREE 0
@@ -229,7 +235,7 @@ int cache_tree_fully_valid(struct cache_tree *it)
 	int i;
 	if (!it)
 		return 0;
-	if (it->entry_count < 0 || !has_object_file(&it->oid))
+	if (it->entry_count < 0 || !repo_has_object_file(the_repository, &it->oid))
 		return 0;
 	for (i = 0; i < it->subtree_nr; i++) {
 		if (!cache_tree_fully_valid(it->down[i]->cache_tree))
@@ -240,7 +246,7 @@ int cache_tree_fully_valid(struct cache_tree *it)
 
 static int must_check_existence(const struct cache_entry *ce)
 {
-	return !(has_promisor_remote() && ce_skip_worktree(ce));
+	return !(repo_has_promisor_remote(the_repository) && ce_skip_worktree(ce));
 }
 
 static int update_one(struct cache_tree *it,
@@ -280,7 +286,7 @@ static int update_one(struct cache_tree *it,
 		}
 	}
 
-	if (0 <= it->entry_count && has_object_file(&it->oid))
+	if (0 <= it->entry_count && repo_has_object_file(the_repository, &it->oid))
 		return it->entry_count;
 
 	/*
@@ -386,7 +392,7 @@ static int update_one(struct cache_tree *it,
 		ce_missing_ok = mode == S_IFGITLINK || missing_ok ||
 			!must_check_existence(ce);
 		if (is_null_oid(oid) ||
-		    (!ce_missing_ok && !has_object_file(oid))) {
+		    (!ce_missing_ok && !repo_has_object_file(the_repository, oid))) {
 			strbuf_release(&buffer);
 			if (expected_missing)
 				return -1;
@@ -434,7 +440,7 @@ static int update_one(struct cache_tree *it,
 		struct object_id oid;
 		hash_object_file(the_hash_algo, buffer.buf, buffer.len,
 				 OBJ_TREE, &oid);
-		if (has_object_file_with_flags(&oid, OBJECT_INFO_SKIP_FETCH_OBJECT))
+		if (repo_has_object_file_with_flags(the_repository, &oid, OBJECT_INFO_SKIP_FETCH_OBJECT))
 			oidcpy(&it->oid, &oid);
 		else
 			to_invalidate = 1;
@@ -470,7 +476,7 @@ int cache_tree_update(struct index_state *istate, int flags)
 	if (!istate->cache_tree)
 		istate->cache_tree = cache_tree();
 
-	if (!(flags & WRITE_TREE_MISSING_OK) && has_promisor_remote())
+	if (!(flags & WRITE_TREE_MISSING_OK) && repo_has_promisor_remote(the_repository))
 		prefetch_cache_entries(istate, must_check_existence);
 
 	trace_performance_enter();
@@ -814,14 +820,14 @@ void prime_cache_tree(struct repository *r,
 {
 	struct strbuf tree_path = STRBUF_INIT;
 
-	trace2_region_enter("cache-tree", "prime_cache_tree", the_repository);
+	trace2_region_enter("cache-tree", "prime_cache_tree", r);
 	cache_tree_free(&istate->cache_tree);
 	istate->cache_tree = cache_tree();
 
 	prime_cache_tree_rec(r, istate->cache_tree, tree, &tree_path);
 	strbuf_release(&tree_path);
 	istate->cache_changed |= CACHE_TREE_CHANGED;
-	trace2_region_leave("cache-tree", "prime_cache_tree", the_repository);
+	trace2_region_leave("cache-tree", "prime_cache_tree", r);
 }
 
 /*
diff --git a/cache-tree.h b/cache-tree.h
index bd97caa..faae88b 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -1,7 +1,6 @@
 #ifndef CACHE_TREE_H
 #define CACHE_TREE_H
 
-#include "cache.h"
 #include "tree.h"
 #include "tree-walk.h"
 
diff --git a/cache.h b/cache.h
index 1278990..bdedb87 100644
--- a/cache.h
+++ b/cache.h
@@ -4,105 +4,9 @@
 #include "git-compat-util.h"
 #include "strbuf.h"
 #include "hashmap.h"
-#include "list.h"
-#include "advice.h"
-#include "gettext.h"
-#include "convert.h"
-#include "trace.h"
-#include "trace2.h"
-#include "string-list.h"
-#include "pack-revindex.h"
-#include "hash.h"
-#include "path.h"
-#include "oid-array.h"
-#include "repository.h"
-#include "mem-pool.h"
-
-typedef struct git_zstream {
-	z_stream z;
-	unsigned long avail_in;
-	unsigned long avail_out;
-	unsigned long total_in;
-	unsigned long total_out;
-	unsigned char *next_in;
-	unsigned char *next_out;
-} git_zstream;
-
-void git_inflate_init(git_zstream *);
-void git_inflate_init_gzip_only(git_zstream *);
-void git_inflate_end(git_zstream *);
-int git_inflate(git_zstream *, int flush);
-
-void git_deflate_init(git_zstream *, int level);
-void git_deflate_init_gzip(git_zstream *, int level);
-void git_deflate_init_raw(git_zstream *, int level);
-void git_deflate_end(git_zstream *);
-int git_deflate_abort(git_zstream *);
-int git_deflate_end_gently(git_zstream *);
-int git_deflate(git_zstream *, int flush);
-unsigned long git_deflate_bound(git_zstream *, unsigned long);
-
-#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
-#define DTYPE(de)	((de)->d_type)
-#else
-#undef DT_UNKNOWN
-#undef DT_DIR
-#undef DT_REG
-#undef DT_LNK
-#define DT_UNKNOWN	0
-#define DT_DIR		1
-#define DT_REG		2
-#define DT_LNK		3
-#define DTYPE(de)	DT_UNKNOWN
-#endif
-
-/* unknown mode (impossible combination S_IFIFO|S_IFCHR) */
-#define S_IFINVALID     0030000
-
-/*
- * A "directory link" is a link to another git directory.
- *
- * The value 0160000 is not normally a valid mode, and
- * also just happens to be S_IFDIR + S_IFLNK
- */
-#define S_IFGITLINK	0160000
-#define S_ISGITLINK(m)	(((m) & S_IFMT) == S_IFGITLINK)
-
-/*
- * Some mode bits are also used internally for computations.
- *
- * They *must* not overlap with any valid modes, and they *must* not be emitted
- * to outside world - i.e. appear on disk or network. In other words, it's just
- * temporary fields, which we internally use, but they have to stay in-house.
- *
- * ( such approach is valid, as standard S_IF* fits into 16 bits, and in Git
- *   codebase mode is `unsigned int` which is assumed to be at least 32 bits )
- */
-
-/* used internally in tree-diff */
-#define S_DIFFTREE_IFXMIN_NEQ	0x80000000
-
-
-/*
- * Intensive research over the course of many years has shown that
- * port 9418 is totally unused by anything else. Or
- *
- *	Your search - "port 9418" - did not match any documents.
- *
- * as www.google.com puts it.
- *
- * This port has been properly assigned for git use by IANA:
- * git (Assigned-9418) [I06-050728-0001].
- *
- *	git  9418/tcp   git pack transfer service
- *	git  9418/udp   git pack transfer service
- *
- * with Linus Torvalds <torvalds@osdl.org> as the point of
- * contact. September 2005.
- *
- * See http://www.iana.org/assignments/port-numbers
- */
-#define DEFAULT_GIT_PORT 9418
+#include "pathspec.h"
+#include "object.h"
+#include "statinfo.h"
 
 /*
  * Basic data structures for the directory cache
@@ -118,26 +22,6 @@ struct cache_header {
 #define INDEX_FORMAT_LB 2
 #define INDEX_FORMAT_UB 4
 
-/*
- * The "cache_time" is just the low 32 bits of the
- * time. It doesn't matter if it overflows - we only
- * check it for equality in the 32 bits we save.
- */
-struct cache_time {
-	uint32_t sec;
-	uint32_t nsec;
-};
-
-struct stat_data {
-	struct cache_time sd_ctime;
-	struct cache_time sd_mtime;
-	unsigned int sd_dev;
-	unsigned int sd_ino;
-	unsigned int sd_uid;
-	unsigned int sd_gid;
-	unsigned int sd_size;
-};
-
 struct cache_entry {
 	struct hashmap_entry ent;
 	struct stat_data ce_stat_data;
@@ -203,11 +87,8 @@ struct cache_entry {
 #error "CE_EXTENDED_FLAGS out of range"
 #endif
 
-#define S_ISSPARSEDIR(m) ((m) == S_IFDIR)
-
 /* Forward structure decls */
 struct pathspec;
-struct child_process;
 struct tree;
 
 /*
@@ -245,17 +126,6 @@ static inline unsigned create_ce_flags(unsigned stage)
 #define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
 #define ce_intent_to_add(ce) ((ce)->ce_flags & CE_INTENT_TO_ADD)
 
-#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
-static inline unsigned int create_ce_mode(unsigned int mode)
-{
-	if (S_ISLNK(mode))
-		return S_IFLNK;
-	if (S_ISSPARSEDIR(mode))
-		return S_IFDIR;
-	if (S_ISDIR(mode) || S_ISGITLINK(mode))
-		return S_IFGITLINK;
-	return S_IFREG | ce_permissions(mode);
-}
 static inline unsigned int ce_mode_from_stat(const struct cache_entry *ce,
 					     unsigned int mode)
 {
@@ -282,15 +152,14 @@ static inline int ce_to_dtype(const struct cache_entry *ce)
 	else
 		return DT_UNKNOWN;
 }
-static inline unsigned int canon_mode(unsigned int mode)
+
+static inline int ce_path_match(struct index_state *istate,
+				const struct cache_entry *ce,
+				const struct pathspec *pathspec,
+				char *seen)
 {
-	if (S_ISREG(mode))
-		return S_IFREG | ce_permissions(mode);
-	if (S_ISLNK(mode))
-		return S_IFLNK;
-	if (S_ISDIR(mode))
-		return S_IFDIR;
-	return S_IFGITLINK;
+	return match_pathspec(istate, pathspec, ce->name, ce_namelen(ce), 0, seen,
+			      S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode));
 }
 
 #define cache_entry_size(len) (offsetof(struct cache_entry,name) + (len) + 1)
@@ -443,7 +312,7 @@ void validate_cache_entries(const struct index_state *istate);
 /*
  * Bulk prefetch all missing cache entries that are not GITLINKs and that match
  * the given predicate. This function should only be called if
- * has_promisor_remote() returns true.
+ * repo_has_promisor_remote() returns true.
  */
 typedef int (*must_prefetch_predicate)(const struct cache_entry *);
 void prefetch_cache_entries(const struct index_state *istate,
@@ -453,198 +322,6 @@ void prefetch_cache_entries(const struct index_state *istate,
 extern struct index_state the_index;
 #endif
 
-#define TYPE_BITS 3
-
-/*
- * Values in this enum (except those outside the 3 bit range) are part
- * of pack file format. See gitformat-pack(5) for more information.
- */
-enum object_type {
-	OBJ_BAD = -1,
-	OBJ_NONE = 0,
-	OBJ_COMMIT = 1,
-	OBJ_TREE = 2,
-	OBJ_BLOB = 3,
-	OBJ_TAG = 4,
-	/* 5 for future expansion */
-	OBJ_OFS_DELTA = 6,
-	OBJ_REF_DELTA = 7,
-	OBJ_ANY,
-	OBJ_MAX
-};
-
-static inline enum object_type object_type(unsigned int mode)
-{
-	return S_ISDIR(mode) ? OBJ_TREE :
-		S_ISGITLINK(mode) ? OBJ_COMMIT :
-		OBJ_BLOB;
-}
-
-/* Double-check local_repo_env below if you add to this list. */
-#define GIT_DIR_ENVIRONMENT "GIT_DIR"
-#define GIT_COMMON_DIR_ENVIRONMENT "GIT_COMMON_DIR"
-#define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
-#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
-#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
-#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
-#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
-#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
-#define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE"
-#define GIT_SHALLOW_FILE_ENVIRONMENT "GIT_SHALLOW_FILE"
-#define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIR"
-#define CONFIG_ENVIRONMENT "GIT_CONFIG"
-#define CONFIG_DATA_ENVIRONMENT "GIT_CONFIG_PARAMETERS"
-#define CONFIG_COUNT_ENVIRONMENT "GIT_CONFIG_COUNT"
-#define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
-#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
-#define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
-#define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
-#define GITATTRIBUTES_FILE ".gitattributes"
-#define INFOATTRIBUTES_FILE "info/attributes"
-#define ATTRIBUTE_MACRO_PREFIX "[attr]"
-#define GITMODULES_FILE ".gitmodules"
-#define GITMODULES_INDEX ":.gitmodules"
-#define GITMODULES_HEAD "HEAD:.gitmodules"
-#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
-#define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
-#define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
-#define GIT_NOTES_REWRITE_REF_ENVIRONMENT "GIT_NOTES_REWRITE_REF"
-#define GIT_NOTES_REWRITE_MODE_ENVIRONMENT "GIT_NOTES_REWRITE_MODE"
-#define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS"
-#define GIT_GLOB_PATHSPECS_ENVIRONMENT "GIT_GLOB_PATHSPECS"
-#define GIT_NOGLOB_PATHSPECS_ENVIRONMENT "GIT_NOGLOB_PATHSPECS"
-#define GIT_ICASE_PATHSPECS_ENVIRONMENT "GIT_ICASE_PATHSPECS"
-#define GIT_QUARANTINE_ENVIRONMENT "GIT_QUARANTINE_PATH"
-#define GIT_OPTIONAL_LOCKS_ENVIRONMENT "GIT_OPTIONAL_LOCKS"
-#define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT "GIT_TEXTDOMAINDIR"
-
-/*
- * Environment variable used in handshaking the wire protocol.
- * Contains a colon ':' separated list of keys with optional values
- * 'key[=value]'.  Presence of unknown keys and values must be
- * ignored.
- */
-#define GIT_PROTOCOL_ENVIRONMENT "GIT_PROTOCOL"
-/* HTTP header used to handshake the wire protocol */
-#define GIT_PROTOCOL_HEADER "Git-Protocol"
-
-/*
- * This environment variable is expected to contain a boolean indicating
- * whether we should or should not treat:
- *
- *   GIT_DIR=foo.git git ...
- *
- * as if GIT_WORK_TREE=. was given. It's not expected that users will make use
- * of this, but we use it internally to communicate to sub-processes that we
- * are in a bare repo. If not set, defaults to true.
- */
-#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
-
-/*
- * Repository-local GIT_* environment variables; these will be cleared
- * when git spawns a sub-process that runs inside another repository.
- * The array is NULL-terminated, which makes it easy to pass in the "env"
- * parameter of a run-command invocation, or to do a simple walk.
- */
-extern const char * const local_repo_env[];
-
-void setup_git_env(const char *git_dir);
-
-/*
- * Returns true iff we have a configured git repository (either via
- * setup_git_directory, or in the environment via $GIT_DIR).
- */
-int have_git_dir(void);
-
-extern int is_bare_repository_cfg;
-int is_bare_repository(void);
-int is_inside_git_dir(void);
-extern char *git_work_tree_cfg;
-int is_inside_work_tree(void);
-const char *get_git_dir(void);
-const char *get_git_common_dir(void);
-const char *get_object_directory(void);
-char *get_index_file(void);
-char *get_graft_file(struct repository *r);
-void set_git_dir(const char *path, int make_realpath);
-int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
-int get_common_dir(struct strbuf *sb, const char *gitdir);
-const char *get_git_namespace(void);
-const char *strip_namespace(const char *namespaced_ref);
-const char *get_git_work_tree(void);
-
-/*
- * Return true if the given path is a git directory; note that this _just_
- * looks at the directory itself. If you want to know whether "foo/.git"
- * is a repository, you must feed that path, not just "foo".
- */
-int is_git_directory(const char *path);
-
-/*
- * Return 1 if the given path is the root of a git repository or
- * submodule, else 0. Will not return 1 for bare repositories with the
- * exception of creating a bare repository in "foo/.git" and calling
- * is_git_repository("foo").
- *
- * If we run into read errors, we err on the side of saying "yes, it is",
- * as we usually consider sub-repos precious, and would prefer to err on the
- * side of not disrupting or deleting them.
- */
-int is_nonbare_repository_dir(struct strbuf *path);
-
-#define READ_GITFILE_ERR_STAT_FAILED 1
-#define READ_GITFILE_ERR_NOT_A_FILE 2
-#define READ_GITFILE_ERR_OPEN_FAILED 3
-#define READ_GITFILE_ERR_READ_FAILED 4
-#define READ_GITFILE_ERR_INVALID_FORMAT 5
-#define READ_GITFILE_ERR_NO_PATH 6
-#define READ_GITFILE_ERR_NOT_A_REPO 7
-#define READ_GITFILE_ERR_TOO_LARGE 8
-void read_gitfile_error_die(int error_code, const char *path, const char *dir);
-const char *read_gitfile_gently(const char *path, int *return_error_code);
-#define read_gitfile(path) read_gitfile_gently((path), NULL)
-const char *resolve_gitdir_gently(const char *suspect, int *return_error_code);
-#define resolve_gitdir(path) resolve_gitdir_gently((path), NULL)
-
-void set_git_work_tree(const char *tree);
-
-#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
-
-void setup_work_tree(void);
-/*
- * Find the commondir and gitdir of the repository that contains the current
- * working directory, without changing the working directory or other global
- * state. The result is appended to commondir and gitdir.  If the discovered
- * gitdir does not correspond to a worktree, then 'commondir' and 'gitdir' will
- * both have the same result appended to the buffer.  The return value is
- * either 0 upon success and non-zero if no repository was found.
- */
-int discover_git_directory(struct strbuf *commondir,
-			   struct strbuf *gitdir);
-const char *setup_git_directory_gently(int *);
-const char *setup_git_directory(void);
-char *prefix_path(const char *prefix, int len, const char *path);
-char *prefix_path_gently(const char *prefix, int len, int *remaining, const char *path);
-
-/*
- * Concatenate "prefix" (if len is non-zero) and "path", with no
- * connecting characters (so "prefix" should end with a "/").
- * Unlike prefix_path, this should be used if the named file does
- * not have to interact with index entry; i.e. name of a random file
- * on the filesystem.
- *
- * The return value is always a newly allocated string (even if the
- * prefix was empty).
- */
-char *prefix_filename(const char *prefix, const char *path);
-
-int check_filename(const char *prefix, const char *name);
-void verify_filename(const char *prefix,
-		     const char *name,
-		     int diagnose_misspelt_rev);
-void verify_non_filename(const char *prefix, const char *name);
-int path_inside_repo(const char *prefix, const char *path);
-
 #define INIT_DB_QUIET 0x0001
 #define INIT_DB_EXIST_OK 0x0002
 
@@ -653,84 +330,6 @@ int init_db(const char *git_dir, const char *real_git_dir,
 	    const char *initial_branch, unsigned int flags);
 void initialize_repository_version(int hash_algo, int reinit);
 
-void sanitize_stdfds(void);
-int daemonize(void);
-
-#define alloc_nr(x) (((x)+16)*3/2)
-
-/**
- * Dynamically growing an array using realloc() is error prone and boring.
- *
- * Define your array with:
- *
- * - a pointer (`item`) that points at the array, initialized to `NULL`
- *   (although please name the variable based on its contents, not on its
- *   type);
- *
- * - an integer variable (`alloc`) that keeps track of how big the current
- *   allocation is, initialized to `0`;
- *
- * - another integer variable (`nr`) to keep track of how many elements the
- *   array currently has, initialized to `0`.
- *
- * Then before adding `n`th element to the item, call `ALLOC_GROW(item, n,
- * alloc)`.  This ensures that the array can hold at least `n` elements by
- * calling `realloc(3)` and adjusting `alloc` variable.
- *
- * ------------
- * sometype *item;
- * size_t nr;
- * size_t alloc
- *
- * for (i = 0; i < nr; i++)
- * 	if (we like item[i] already)
- * 		return;
- *
- * // we did not like any existing one, so add one
- * ALLOC_GROW(item, nr + 1, alloc);
- * item[nr++] = value you like;
- * ------------
- *
- * You are responsible for updating the `nr` variable.
- *
- * If you need to specify the number of elements to allocate explicitly
- * then use the macro `REALLOC_ARRAY(item, alloc)` instead of `ALLOC_GROW`.
- *
- * Consider using ALLOC_GROW_BY instead of ALLOC_GROW as it has some
- * added niceties.
- *
- * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'.
- */
-#define ALLOC_GROW(x, nr, alloc) \
-	do { \
-		if ((nr) > alloc) { \
-			if (alloc_nr(alloc) < (nr)) \
-				alloc = (nr); \
-			else \
-				alloc = alloc_nr(alloc); \
-			REALLOC_ARRAY(x, alloc); \
-		} \
-	} while (0)
-
-/*
- * Similar to ALLOC_GROW but handles updating of the nr value and
- * zeroing the bytes of the newly-grown array elements.
- *
- * DO NOT USE any expression with side-effect for any of the
- * arguments.
- */
-#define ALLOC_GROW_BY(x, nr, increase, alloc) \
-	do { \
-		if (increase) { \
-			size_t new_nr = nr + (increase); \
-			if (new_nr < nr) \
-				BUG("negative growth in ALLOC_GROW_BY"); \
-			ALLOC_GROW(x, new_nr, alloc); \
-			memset((x) + nr, 0, sizeof(*(x)) * (increase)); \
-			nr = new_nr; \
-		} \
-	} while (0)
-
 /* Initialize and use the cache information */
 struct lock_file;
 void preload_index(struct index_state *index,
@@ -897,13 +496,6 @@ int has_racy_timestamp(struct index_state *istate);
 int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
 int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
 
-#define HASH_WRITE_OBJECT 1
-#define HASH_FORMAT_CHECK 2
-#define HASH_RENORMALIZE  4
-#define HASH_SILENT 8
-int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
-int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
-
 /*
  * Record to sd the data from st that we use to check whether a file
  * might have changed.
@@ -955,238 +547,6 @@ void set_alternate_index_output(const char *);
 extern int verify_index_checksum;
 extern int verify_ce_order;
 
-/* Environment bits from configuration mechanism */
-extern int trust_executable_bit;
-extern int trust_ctime;
-extern int check_stat;
-extern int quote_path_fully;
-extern int has_symlinks;
-extern int minimum_abbrev, default_abbrev;
-extern int ignore_case;
-extern int assume_unchanged;
-extern int prefer_symlink_refs;
-extern int warn_ambiguous_refs;
-extern int warn_on_object_refname_ambiguity;
-extern char *apply_default_whitespace;
-extern char *apply_default_ignorewhitespace;
-extern const char *git_attributes_file;
-extern const char *git_hooks_path;
-extern int zlib_compression_level;
-extern int pack_compression_level;
-extern size_t packed_git_window_size;
-extern size_t packed_git_limit;
-extern size_t delta_base_cache_limit;
-extern unsigned long big_file_threshold;
-extern unsigned long pack_size_limit_cfg;
-
-/*
- * Accessors for the core.sharedrepository config which lazy-load the value
- * from the config (if not already set). The "reset" function can be
- * used to unset "set" or cached value, meaning that the value will be loaded
- * fresh from the config file on the next call to get_shared_repository().
- */
-void set_shared_repository(int value);
-int get_shared_repository(void);
-void reset_shared_repository(void);
-
-/*
- * Do replace refs need to be checked this run?  This variable is
- * initialized to true unless --no-replace-object is used or
- * $GIT_NO_REPLACE_OBJECTS is set, but is set to false by some
- * commands that do not want replace references to be active.
- */
-extern int read_replace_refs;
-
-/*
- * These values are used to help identify parts of a repository to fsync.
- * FSYNC_COMPONENT_NONE identifies data that will not be a persistent part of the
- * repository and so shouldn't be fsynced.
- */
-enum fsync_component {
-	FSYNC_COMPONENT_NONE,
-	FSYNC_COMPONENT_LOOSE_OBJECT		= 1 << 0,
-	FSYNC_COMPONENT_PACK			= 1 << 1,
-	FSYNC_COMPONENT_PACK_METADATA		= 1 << 2,
-	FSYNC_COMPONENT_COMMIT_GRAPH		= 1 << 3,
-	FSYNC_COMPONENT_INDEX			= 1 << 4,
-	FSYNC_COMPONENT_REFERENCE		= 1 << 5,
-};
-
-#define FSYNC_COMPONENTS_OBJECTS (FSYNC_COMPONENT_LOOSE_OBJECT | \
-				  FSYNC_COMPONENT_PACK)
-
-#define FSYNC_COMPONENTS_DERIVED_METADATA (FSYNC_COMPONENT_PACK_METADATA | \
-					   FSYNC_COMPONENT_COMMIT_GRAPH)
-
-#define FSYNC_COMPONENTS_DEFAULT ((FSYNC_COMPONENTS_OBJECTS | \
-				   FSYNC_COMPONENTS_DERIVED_METADATA) & \
-				  ~FSYNC_COMPONENT_LOOSE_OBJECT)
-
-#define FSYNC_COMPONENTS_COMMITTED (FSYNC_COMPONENTS_OBJECTS | \
-				    FSYNC_COMPONENT_REFERENCE)
-
-#define FSYNC_COMPONENTS_ADDED (FSYNC_COMPONENTS_COMMITTED | \
-				FSYNC_COMPONENT_INDEX)
-
-#define FSYNC_COMPONENTS_ALL (FSYNC_COMPONENT_LOOSE_OBJECT | \
-			      FSYNC_COMPONENT_PACK | \
-			      FSYNC_COMPONENT_PACK_METADATA | \
-			      FSYNC_COMPONENT_COMMIT_GRAPH | \
-			      FSYNC_COMPONENT_INDEX | \
-			      FSYNC_COMPONENT_REFERENCE)
-
-#ifndef FSYNC_COMPONENTS_PLATFORM_DEFAULT
-#define FSYNC_COMPONENTS_PLATFORM_DEFAULT FSYNC_COMPONENTS_DEFAULT
-#endif
-
-/*
- * A bitmask indicating which components of the repo should be fsynced.
- */
-extern enum fsync_component fsync_components;
-extern int fsync_object_files;
-extern int use_fsync;
-
-enum fsync_method {
-	FSYNC_METHOD_FSYNC,
-	FSYNC_METHOD_WRITEOUT_ONLY,
-	FSYNC_METHOD_BATCH,
-};
-
-extern enum fsync_method fsync_method;
-extern int core_preload_index;
-extern int precomposed_unicode;
-extern int protect_hfs;
-extern int protect_ntfs;
-
-extern int core_apply_sparse_checkout;
-extern int core_sparse_checkout_cone;
-extern int sparse_expect_files_outside_of_patterns;
-
-/*
- * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).
- */
-int use_optional_locks(void);
-
-/*
- * The character that begins a commented line in user-editable file
- * that is subject to stripspace.
- */
-extern char comment_line_char;
-extern int auto_comment_line_char;
-
-enum log_refs_config {
-	LOG_REFS_UNSET = -1,
-	LOG_REFS_NONE = 0,
-	LOG_REFS_NORMAL,
-	LOG_REFS_ALWAYS
-};
-extern enum log_refs_config log_all_ref_updates;
-
-enum rebase_setup_type {
-	AUTOREBASE_NEVER = 0,
-	AUTOREBASE_LOCAL,
-	AUTOREBASE_REMOTE,
-	AUTOREBASE_ALWAYS
-};
-
-enum push_default_type {
-	PUSH_DEFAULT_NOTHING = 0,
-	PUSH_DEFAULT_MATCHING,
-	PUSH_DEFAULT_SIMPLE,
-	PUSH_DEFAULT_UPSTREAM,
-	PUSH_DEFAULT_CURRENT,
-	PUSH_DEFAULT_UNSPECIFIED
-};
-
-extern enum rebase_setup_type autorebase;
-extern enum push_default_type push_default;
-
-enum object_creation_mode {
-	OBJECT_CREATION_USES_HARDLINKS = 0,
-	OBJECT_CREATION_USES_RENAMES = 1
-};
-
-extern enum object_creation_mode object_creation_mode;
-
-extern char *notes_ref_name;
-
-extern int grafts_replace_parents;
-
-/*
- * GIT_REPO_VERSION is the version we write by default. The
- * _READ variant is the highest number we know how to
- * handle.
- */
-#define GIT_REPO_VERSION 0
-#define GIT_REPO_VERSION_READ 1
-extern int repository_format_precious_objects;
-extern int repository_format_worktree_config;
-
-/*
- * You _have_ to initialize a `struct repository_format` using
- * `= REPOSITORY_FORMAT_INIT` before calling `read_repository_format()`.
- */
-struct repository_format {
-	int version;
-	int precious_objects;
-	char *partial_clone; /* value of extensions.partialclone */
-	int worktree_config;
-	int is_bare;
-	int hash_algo;
-	int sparse_index;
-	char *work_tree;
-	struct string_list unknown_extensions;
-	struct string_list v1_only_extensions;
-};
-
-/*
- * Always use this to initialize a `struct repository_format`
- * to a well-defined, default state before calling
- * `read_repository()`.
- */
-#define REPOSITORY_FORMAT_INIT \
-{ \
-	.version = -1, \
-	.is_bare = -1, \
-	.hash_algo = GIT_HASH_SHA1, \
-	.unknown_extensions = STRING_LIST_INIT_DUP, \
-	.v1_only_extensions = STRING_LIST_INIT_DUP, \
-}
-
-/*
- * Read the repository format characteristics from the config file "path" into
- * "format" struct. Returns the numeric version. On error, or if no version is
- * found in the configuration, -1 is returned, format->version is set to -1,
- * and all other fields in the struct are set to the default configuration
- * (REPOSITORY_FORMAT_INIT). Always initialize the struct using
- * REPOSITORY_FORMAT_INIT before calling this function.
- */
-int read_repository_format(struct repository_format *format, const char *path);
-
-/*
- * Free the memory held onto by `format`, but not the struct itself.
- * (No need to use this after `read_repository_format()` fails.)
- */
-void clear_repository_format(struct repository_format *format);
-
-/*
- * Verify that the repository described by repository_format is something we
- * can read. If it is, return 0. Otherwise, return -1, and "err" will describe
- * any errors encountered.
- */
-int verify_repository_format(const struct repository_format *format,
-			     struct strbuf *err);
-
-/*
- * Check the repository format version in the path found in get_git_dir(),
- * and die if it is a version we don't understand. Generally one would
- * set_git_dir() before calling this, and use it only for "are we in a valid
- * repo?".
- *
- * If successful and fmt is not NULL, fill fmt with data.
- */
-void check_repository_format(struct repository_format *fmt);
-
 #define MTIME_CHANGED	0x0001
 #define CTIME_CHANGED	0x0002
 #define OWNER_CHANGED	0x0004
@@ -1195,644 +555,7 @@ void check_repository_format(struct repository_format *fmt);
 #define DATA_CHANGED    0x0020
 #define TYPE_CHANGED    0x0040
 
-/*
- * Return an abbreviated sha1 unique within this repository's object database.
- * The result will be at least `len` characters long, and will be NUL
- * terminated.
- *
- * The non-`_r` version returns a static buffer which remains valid until 4
- * more calls to find_unique_abbrev are made.
- *
- * The `_r` variant writes to a buffer supplied by the caller, which must be at
- * least `GIT_MAX_HEXSZ + 1` bytes. The return value is the number of bytes
- * written (excluding the NUL terminator).
- *
- * Note that while this version avoids the static buffer, it is not fully
- * reentrant, as it calls into other non-reentrant git code.
- */
-const char *repo_find_unique_abbrev(struct repository *r, const struct object_id *oid, int len);
-#define find_unique_abbrev(oid, len) repo_find_unique_abbrev(the_repository, oid, len)
-int repo_find_unique_abbrev_r(struct repository *r, char *hex, const struct object_id *oid, int len);
-#define find_unique_abbrev_r(hex, oid, len) repo_find_unique_abbrev_r(the_repository, hex, oid, len)
-
-/* set default permissions by passing mode arguments to open(2) */
-int git_mkstemps_mode(char *pattern, int suffix_len, int mode);
-int git_mkstemp_mode(char *pattern, int mode);
-
-/*
- * NOTE NOTE NOTE!!
- *
- * PERM_UMASK, OLD_PERM_GROUP and OLD_PERM_EVERYBODY enumerations must
- * not be changed. Old repositories have core.sharedrepository written in
- * numeric format, and therefore these values are preserved for compatibility
- * reasons.
- */
-enum sharedrepo {
-	PERM_UMASK          = 0,
-	OLD_PERM_GROUP      = 1,
-	OLD_PERM_EVERYBODY  = 2,
-	PERM_GROUP          = 0660,
-	PERM_EVERYBODY      = 0664
-};
-int git_config_perm(const char *var, const char *value);
-int adjust_shared_perm(const char *path);
-
-/*
- * Create the directory containing the named path, using care to be
- * somewhat safe against races. Return one of the scld_error values to
- * indicate success/failure. On error, set errno to describe the
- * problem.
- *
- * SCLD_VANISHED indicates that one of the ancestor directories of the
- * path existed at one point during the function call and then
- * suddenly vanished, probably because another process pruned the
- * directory while we were working.  To be robust against this kind of
- * race, callers might want to try invoking the function again when it
- * returns SCLD_VANISHED.
- *
- * safe_create_leading_directories() temporarily changes path while it
- * is working but restores it before returning.
- * safe_create_leading_directories_const() doesn't modify path, even
- * temporarily. Both these variants adjust the permissions of the
- * created directories to honor core.sharedRepository, so they are best
- * suited for files inside the git dir. For working tree files, use
- * safe_create_leading_directories_no_share() instead, as it ignores
- * the core.sharedRepository setting.
- */
-enum scld_error {
-	SCLD_OK = 0,
-	SCLD_FAILED = -1,
-	SCLD_PERMS = -2,
-	SCLD_EXISTS = -3,
-	SCLD_VANISHED = -4
-};
-enum scld_error safe_create_leading_directories(char *path);
-enum scld_error safe_create_leading_directories_const(const char *path);
-enum scld_error safe_create_leading_directories_no_share(char *path);
-
-int mkdir_in_gitdir(const char *path);
-char *interpolate_path(const char *path, int real_home);
-/* NEEDSWORK: remove this synonym once in-flight topics have migrated */
-#define expand_user_path interpolate_path
-const char *enter_repo(const char *path, int strict);
-static inline int is_absolute_path(const char *path)
-{
-	return is_dir_sep(path[0]) || has_dos_drive_prefix(path);
-}
-int is_directory(const char *);
-char *strbuf_realpath(struct strbuf *resolved, const char *path,
-		      int die_on_error);
-char *strbuf_realpath_forgiving(struct strbuf *resolved, const char *path,
-				int die_on_error);
-char *real_pathdup(const char *path, int die_on_error);
-const char *absolute_path(const char *path);
-char *absolute_pathdup(const char *path);
-const char *remove_leading_path(const char *in, const char *prefix);
-const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
-int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);
-int normalize_path_copy(char *dst, const char *src);
-int longest_ancestor_length(const char *path, struct string_list *prefixes);
-char *strip_path_suffix(const char *path, const char *suffix);
-int daemon_avoid_alias(const char *path);
-
-/*
- * These functions match their is_hfs_dotgit() counterparts; see utf8.h for
- * details.
- */
-int is_ntfs_dotgit(const char *name);
-int is_ntfs_dotgitmodules(const char *name);
-int is_ntfs_dotgitignore(const char *name);
-int is_ntfs_dotgitattributes(const char *name);
-int is_ntfs_dotmailmap(const char *name);
-
-/*
- * Returns true iff "str" could be confused as a command-line option when
- * passed to a sub-program like "ssh". Note that this has nothing to do with
- * shell-quoting, which should be handled separately; we're assuming here that
- * the string makes it verbatim to the sub-program.
- */
-int looks_like_command_line_option(const char *str);
-
-/**
- * Return a newly allocated string with the evaluation of
- * "$XDG_CONFIG_HOME/$subdir/$filename" if $XDG_CONFIG_HOME is non-empty, otherwise
- * "$HOME/.config/$subdir/$filename". Return NULL upon error.
- */
-char *xdg_config_home_for(const char *subdir, const char *filename);
-
-/**
- * Return a newly allocated string with the evaluation of
- * "$XDG_CONFIG_HOME/git/$filename" if $XDG_CONFIG_HOME is non-empty, otherwise
- * "$HOME/.config/git/$filename". Return NULL upon error.
- */
-char *xdg_config_home(const char *filename);
-
-/**
- * Return a newly allocated string with the evaluation of
- * "$XDG_CACHE_HOME/git/$filename" if $XDG_CACHE_HOME is non-empty, otherwise
- * "$HOME/.cache/git/$filename". Return NULL upon error.
- */
-char *xdg_cache_home(const char *filename);
-
-int git_open_cloexec(const char *name, int flags);
-#define git_open(name) git_open_cloexec(name, O_RDONLY)
-
-/**
- * unpack_loose_header() initializes the data stream needed to unpack
- * a loose object header.
- *
- * Returns:
- *
- * - ULHR_OK on success
- * - ULHR_BAD on error
- * - ULHR_TOO_LONG if the header was too long
- *
- * It will only parse up to MAX_HEADER_LEN bytes unless an optional
- * "hdrbuf" argument is non-NULL. This is intended for use with
- * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
- * reporting. The full header will be extracted to "hdrbuf" for use
- * with parse_loose_header(), ULHR_TOO_LONG will still be returned
- * from this function to indicate that the header was too long.
- */
-enum unpack_loose_header_result {
-	ULHR_OK,
-	ULHR_BAD,
-	ULHR_TOO_LONG,
-};
-enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
-						    unsigned char *map,
-						    unsigned long mapsize,
-						    void *buffer,
-						    unsigned long bufsiz,
-						    struct strbuf *hdrbuf);
-
-/**
- * parse_loose_header() parses the starting "<type> <len>\0" of an
- * object. If it doesn't follow that format -1 is returned. To check
- * the validity of the <type> populate the "typep" in the "struct
- * object_info". It will be OBJ_BAD if the object type is unknown. The
- * parsed <len> can be retrieved via "oi->sizep", and from there
- * passed to unpack_loose_rest().
- */
-struct object_info;
-int parse_loose_header(const char *hdr, struct object_info *oi);
-
-/**
- * With in-core object data in "buf", rehash it to make sure the
- * object name actually matches "oid" to detect object corruption.
- *
- * A negative value indicates an error, usually that the OID is not
- * what we expected, but it might also indicate another error.
- */
-int check_object_signature(struct repository *r, const struct object_id *oid,
-			   void *map, unsigned long size,
-			   enum object_type type);
-
-/**
- * A streaming version of check_object_signature().
- * Try reading the object named with "oid" using
- * the streaming interface and rehash it to do the same.
- */
-int stream_object_signature(struct repository *r, const struct object_id *oid);
-
-int finalize_object_file(const char *tmpfile, const char *filename);
-
-/* Helper to check and "touch" a file */
-int check_and_freshen_file(const char *fn, int freshen);
-
-extern const signed char hexval_table[256];
-static inline unsigned int hexval(unsigned char c)
-{
-	return hexval_table[c];
-}
-
-/*
- * Convert two consecutive hexadecimal digits into a char.  Return a
- * negative value on error.  Don't run over the end of short strings.
- */
-static inline int hex2chr(const char *s)
-{
-	unsigned int val = hexval(s[0]);
-	return (val & ~0xf) ? val : (val << 4) | hexval(s[1]);
-}
-
-/* Convert to/from hex/sha1 representation */
-#define MINIMUM_ABBREV minimum_abbrev
-#define DEFAULT_ABBREV default_abbrev
-
-/* used when the code does not know or care what the default abbrev is */
-#define FALLBACK_DEFAULT_ABBREV 7
-
-struct object_context {
-	unsigned short mode;
-	/*
-	 * symlink_path is only used by get_tree_entry_follow_symlinks,
-	 * and only for symlinks that point outside the repository.
-	 */
-	struct strbuf symlink_path;
-	/*
-	 * If GET_OID_RECORD_PATH is set, this will record path (if any)
-	 * found when resolving the name. The caller is responsible for
-	 * releasing the memory.
-	 */
-	char *path;
-};
-
-#define GET_OID_QUIETLY           01
-#define GET_OID_COMMIT            02
-#define GET_OID_COMMITTISH        04
-#define GET_OID_TREE             010
-#define GET_OID_TREEISH          020
-#define GET_OID_BLOB             040
-#define GET_OID_FOLLOW_SYMLINKS 0100
-#define GET_OID_RECORD_PATH     0200
-#define GET_OID_ONLY_TO_DIE    04000
-#define GET_OID_REQUIRE_PATH  010000
-
-#define GET_OID_DISAMBIGUATORS \
-	(GET_OID_COMMIT | GET_OID_COMMITTISH | \
-	GET_OID_TREE | GET_OID_TREEISH | \
-	GET_OID_BLOB)
-
-enum get_oid_result {
-	FOUND = 0,
-	MISSING_OBJECT = -1, /* The requested object is missing */
-	SHORT_NAME_AMBIGUOUS = -2,
-	/* The following only apply when symlinks are followed */
-	DANGLING_SYMLINK = -4, /*
-				* The initial symlink is there, but
-				* (transitively) points to a missing
-				* in-tree file
-				*/
-	SYMLINK_LOOP = -5,
-	NOT_DIR = -6, /*
-		       * Somewhere along the symlink chain, a path is
-		       * requested which contains a file as a
-		       * non-final element.
-		       */
-};
-
-int repo_get_oid(struct repository *r, const char *str, struct object_id *oid);
-__attribute__((format (printf, 2, 3)))
-int get_oidf(struct object_id *oid, const char *fmt, ...);
-int repo_get_oid_commit(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_committish(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_tree(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_treeish(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_blob(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_mb(struct repository *r, const char *str, struct object_id *oid);
-void maybe_die_on_misspelt_object_name(struct repository *repo,
-				       const char *name,
-				       const char *prefix);
-enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
-					 unsigned flags, struct object_id *oid,
-					 struct object_context *oc);
-
-#define get_oid(str, oid)		repo_get_oid(the_repository, str, oid)
-#define get_oid_commit(str, oid)	repo_get_oid_commit(the_repository, str, oid)
-#define get_oid_committish(str, oid)	repo_get_oid_committish(the_repository, str, oid)
-#define get_oid_tree(str, oid)		repo_get_oid_tree(the_repository, str, oid)
-#define get_oid_treeish(str, oid)	repo_get_oid_treeish(the_repository, str, oid)
-#define get_oid_blob(str, oid)		repo_get_oid_blob(the_repository, str, oid)
-#define get_oid_mb(str, oid) 		repo_get_oid_mb(the_repository, str, oid)
-
-typedef int each_abbrev_fn(const struct object_id *oid, void *);
-int repo_for_each_abbrev(struct repository *r, const char *prefix, each_abbrev_fn, void *);
-#define for_each_abbrev(prefix, fn, data) repo_for_each_abbrev(the_repository, prefix, fn, data)
-
-int set_disambiguate_hint_config(const char *var, const char *value);
-
-/*
- * Try to read a SHA1 in hexadecimal format from the 40 characters
- * starting at hex.  Write the 20-byte result to sha1 in binary form.
- * Return 0 on success.  Reading stops if a NUL is encountered in the
- * input, so it is safe to pass this function an arbitrary
- * null-terminated string.
- */
-int get_sha1_hex(const char *hex, unsigned char *sha1);
-int get_oid_hex(const char *hex, struct object_id *sha1);
-
-/* Like get_oid_hex, but for an arbitrary hash algorithm. */
-int get_oid_hex_algop(const char *hex, struct object_id *oid, const struct git_hash_algo *algop);
-
-/*
- * Read `len` pairs of hexadecimal digits from `hex` and write the
- * values to `binary` as `len` bytes. Return 0 on success, or -1 if
- * the input does not consist of hex digits).
- */
-int hex_to_bytes(unsigned char *binary, const char *hex, size_t len);
-
-/*
- * Convert a binary hash in "unsigned char []" or an object name in
- * "struct object_id *" to its hex equivalent. The `_r` variant is reentrant,
- * and writes the NUL-terminated output to the buffer `out`, which must be at
- * least `GIT_MAX_HEXSZ + 1` bytes, and returns a pointer to out for
- * convenience.
- *
- * The non-`_r` variant returns a static buffer, but uses a ring of 4
- * buffers, making it safe to make multiple calls for a single statement, like:
- *
- *   printf("%s -> %s", hash_to_hex(one), hash_to_hex(two));
- *   printf("%s -> %s", oid_to_hex(one), oid_to_hex(two));
- */
-char *hash_to_hex_algop_r(char *buffer, const unsigned char *hash, const struct git_hash_algo *);
-char *oid_to_hex_r(char *out, const struct object_id *oid);
-char *hash_to_hex_algop(const unsigned char *hash, const struct git_hash_algo *);	/* static buffer result! */
-char *hash_to_hex(const unsigned char *hash);						/* same static buffer */
-char *oid_to_hex(const struct object_id *oid);						/* same static buffer */
-
-/*
- * Parse a 40-character hexadecimal object ID starting from hex, updating the
- * pointer specified by end when parsing stops.  The resulting object ID is
- * stored in oid.  Returns 0 on success.  Parsing will stop on the first NUL or
- * other invalid character.  end is only updated on success; otherwise, it is
- * unmodified.
- */
-int parse_oid_hex(const char *hex, struct object_id *oid, const char **end);
-
-/* Like parse_oid_hex, but for an arbitrary hash algorithm. */
-int parse_oid_hex_algop(const char *hex, struct object_id *oid, const char **end,
-			const struct git_hash_algo *algo);
-
-
-/*
- * These functions work like get_oid_hex and parse_oid_hex, but they will parse
- * a hex value for any algorithm. The algorithm is detected based on the length
- * and the algorithm in use is returned. If this is not a hex object ID in any
- * algorithm, returns GIT_HASH_UNKNOWN.
- */
-int get_oid_hex_any(const char *hex, struct object_id *oid);
-int parse_oid_hex_any(const char *hex, struct object_id *oid, const char **end);
-
-/*
- * This reads short-hand syntax that not only evaluates to a commit
- * object name, but also can act as if the end user spelled the name
- * of the branch from the command line.
- *
- * - "@{-N}" finds the name of the Nth previous branch we were on, and
- *   places the name of the branch in the given buf and returns the
- *   number of characters parsed if successful.
- *
- * - "<branch>@{upstream}" finds the name of the other ref that
- *   <branch> is configured to merge with (missing <branch> defaults
- *   to the current branch), and places the name of the branch in the
- *   given buf and returns the number of characters parsed if
- *   successful.
- *
- * If the input is not of the accepted format, it returns a negative
- * number to signal an error.
- *
- * If the input was ok but there are not N branch switches in the
- * reflog, it returns 0.
- */
-#define INTERPRET_BRANCH_LOCAL (1<<0)
-#define INTERPRET_BRANCH_REMOTE (1<<1)
-#define INTERPRET_BRANCH_HEAD (1<<2)
-struct interpret_branch_name_options {
-	/*
-	 * If "allowed" is non-zero, it is a treated as a bitfield of allowable
-	 * expansions: local branches ("refs/heads/"), remote branches
-	 * ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
-	 * allowed, even ones to refs outside of those namespaces.
-	 */
-	unsigned allowed;
-
-	/*
-	 * If ^{upstream} or ^{push} (or equivalent) is requested, and the
-	 * branch in question does not have such a reference, return -1 instead
-	 * of die()-ing.
-	 */
-	unsigned nonfatal_dangling_mark : 1;
-};
-int repo_interpret_branch_name(struct repository *r,
-			       const char *str, int len,
-			       struct strbuf *buf,
-			       const struct interpret_branch_name_options *options);
-#define interpret_branch_name(str, len, buf, options) \
-	repo_interpret_branch_name(the_repository, str, len, buf, options)
-
-int validate_headref(const char *ref);
-
-int base_name_compare(const char *name1, size_t len1, int mode1,
-		      const char *name2, size_t len2, int mode2);
-int df_name_compare(const char *name1, size_t len1, int mode1,
-		    const char *name2, size_t len2, int mode2);
-int name_compare(const char *name1, size_t len1, const char *name2, size_t len2);
-int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2);
-
-void *read_object_with_reference(struct repository *r,
-				 const struct object_id *oid,
-				 enum object_type required_type,
-				 unsigned long *size,
-				 struct object_id *oid_ret);
-
-struct object *repo_peel_to_type(struct repository *r,
-				 const char *name, int namelen,
-				 struct object *o, enum object_type);
-#define peel_to_type(name, namelen, obj, type) \
-	repo_peel_to_type(the_repository, name, namelen, obj, type)
-
-#define IDENT_STRICT	       1
-#define IDENT_NO_DATE	       2
-#define IDENT_NO_NAME	       4
-
-enum want_ident {
-	WANT_BLANK_IDENT,
-	WANT_AUTHOR_IDENT,
-	WANT_COMMITTER_IDENT
-};
-
-const char *git_author_info(int);
-const char *git_committer_info(int);
-const char *fmt_ident(const char *name, const char *email,
-		      enum want_ident whose_ident,
-		      const char *date_str, int);
-const char *fmt_name(enum want_ident);
-const char *ident_default_name(void);
-const char *ident_default_email(void);
-const char *git_editor(void);
-const char *git_sequence_editor(void);
-const char *git_pager(int stdout_is_tty);
-int is_terminal_dumb(void);
-int git_ident_config(const char *, const char *, void *);
-/*
- * Prepare an ident to fall back on if the user didn't configure it.
- */
-void prepare_fallback_ident(const char *name, const char *email);
-void reset_ident_date(void);
-
-struct ident_split {
-	const char *name_begin;
-	const char *name_end;
-	const char *mail_begin;
-	const char *mail_end;
-	const char *date_begin;
-	const char *date_end;
-	const char *tz_begin;
-	const char *tz_end;
-};
-/*
- * Signals an success with 0, but time part of the result may be NULL
- * if the input lacks timestamp and zone
- */
-int split_ident_line(struct ident_split *, const char *, int);
-
-/*
- * Given a commit or tag object buffer and the commit or tag headers, replaces
- * the idents in the headers with their canonical versions using the mailmap mechanism.
- */
-void apply_mailmap_to_header(struct strbuf *, const char **, struct string_list *);
-
-/*
- * Compare split idents for equality or strict ordering. Note that we
- * compare only the ident part of the line, ignoring any timestamp.
- *
- * Because there are two fields, we must choose one as the primary key; we
- * currently arbitrarily pick the email.
- */
-int ident_cmp(const struct ident_split *, const struct ident_split *);
-
-struct cache_def {
-	struct strbuf path;
-	int flags;
-	int track_flags;
-	int prefix_len_stat_func;
-};
-#define CACHE_DEF_INIT { \
-	.path = STRBUF_INIT, \
-}
-static inline void cache_def_clear(struct cache_def *cache)
-{
-	strbuf_release(&cache->path);
-}
-
-int has_symlink_leading_path(const char *name, int len);
-int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
-int check_leading_path(const char *name, int len, int warn_on_lstat_err);
-int has_dirs_only_path(const char *name, int len, int prefix_len);
-void invalidate_lstat_cache(void);
-void schedule_dir_for_removal(const char *name, int len);
-void remove_scheduled_dirs(void);
-
-struct pack_window {
-	struct pack_window *next;
-	unsigned char *base;
-	off_t offset;
-	size_t len;
-	unsigned int last_used;
-	unsigned int inuse_cnt;
-};
-
-struct pack_entry {
-	off_t offset;
-	struct packed_git *p;
-};
-
-/*
- * Create a temporary file rooted in the object database directory, or
- * die on failure. The filename is taken from "pattern", which should have the
- * usual "XXXXXX" trailer, and the resulting filename is written into the
- * "template" buffer. Returns the open descriptor.
- */
-int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);
-
-/*
- * Create a pack .keep file named "name" (which should generally be the output
- * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on
- * error.
- */
-int odb_pack_keep(const char *name);
-
-/*
- * Set this to 0 to prevent oid_object_info_extended() from fetching missing
- * blobs. This has a difference only if extensions.partialClone is set.
- *
- * Its default value is 1.
- */
-extern int fetch_if_missing;
-
-/* Dumb servers support */
-int update_server_info(int);
-
-const char *get_log_output_encoding(void);
-const char *get_commit_output_encoding(void);
-
-int committer_ident_sufficiently_given(void);
-int author_ident_sufficiently_given(void);
-
-extern const char *git_commit_encoding;
-extern const char *git_log_output_encoding;
-extern const char *git_mailmap_file;
-extern const char *git_mailmap_blob;
-
-/* IO helper functions */
-void maybe_flush_or_die(FILE *, const char *);
-__attribute__((format (printf, 2, 3)))
-void fprintf_or_die(FILE *, const char *fmt, ...);
-void fwrite_or_die(FILE *f, const void *buf, size_t count);
-void fflush_or_die(FILE *f);
-
-#define COPY_READ_ERROR (-2)
-#define COPY_WRITE_ERROR (-3)
-int copy_fd(int ifd, int ofd);
-int copy_file(const char *dst, const char *src, int mode);
-int copy_file_with_time(const char *dst, const char *src, int mode);
-
-void write_or_die(int fd, const void *buf, size_t count);
-void fsync_or_die(int fd, const char *);
-int fsync_component(enum fsync_component component, int fd);
-void fsync_component_or_die(enum fsync_component component, int fd, const char *msg);
-
-static inline int batch_fsync_enabled(enum fsync_component component)
-{
-	return (fsync_components & component) && (fsync_method == FSYNC_METHOD_BATCH);
-}
-
-ssize_t read_in_full(int fd, void *buf, size_t count);
-ssize_t write_in_full(int fd, const void *buf, size_t count);
-ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
-
-static inline ssize_t write_str_in_full(int fd, const char *str)
-{
-	return write_in_full(fd, str, strlen(str));
-}
-
-/**
- * Open (and truncate) the file at path, write the contents of buf to it,
- * and close it. Dies if any errors are encountered.
- */
-void write_file_buf(const char *path, const char *buf, size_t len);
-
-/**
- * Like write_file_buf(), but format the contents into a buffer first.
- * Additionally, write_file() will append a newline if one is not already
- * present, making it convenient to write text files:
- *
- *   write_file(path, "counter: %d", ctr);
- */
-__attribute__((format (printf, 2, 3)))
-void write_file(const char *path, const char *fmt, ...);
-
-/* pager.c */
-void setup_pager(void);
-int pager_in_use(void);
-extern int pager_use_color;
-int term_columns(void);
-void term_clear_line(void);
-int decimal_width(uintmax_t);
-int check_pager_config(const char *cmd);
-void prepare_pager_args(struct child_process *, const char *pager);
-
-extern const char *editor_program;
-extern const char *askpass_program;
-extern const char *excludes_file;
-
-/* base85 */
-int decode_85(char *dst, const char *line, int linelen);
-void encode_85(char *buf, const unsigned char *data, int bytes);
-
-/* pkt-line.c */
-void packet_trace_identity(const char *prog);
+int cmp_cache_name_compare(const void *a_, const void *b_);
 
 /* add */
 /*
@@ -1844,49 +567,10 @@ int add_files_to_cache(const char *prefix, const struct pathspec *pathspec, int
 /* diff.c */
 extern int diff_auto_refresh_index;
 
-/* match-trees.c */
-void shift_tree(struct repository *, const struct object_id *, const struct object_id *, struct object_id *, int);
-void shift_tree_by(struct repository *, const struct object_id *, const struct object_id *, struct object_id *, const char *);
-
-/*
- * whitespace rules.
- * used by both diff and apply
- * last two digits are tab width
- */
-#define WS_BLANK_AT_EOL         0100
-#define WS_SPACE_BEFORE_TAB     0200
-#define WS_INDENT_WITH_NON_TAB  0400
-#define WS_CR_AT_EOL           01000
-#define WS_BLANK_AT_EOF        02000
-#define WS_TAB_IN_INDENT       04000
-#define WS_TRAILING_SPACE      (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
-#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
-#define WS_TAB_WIDTH_MASK        077
-/* All WS_* -- when extended, adapt diff.c emit_symbol */
-#define WS_RULE_MASK           07777
-extern unsigned whitespace_rule_cfg;
-unsigned whitespace_rule(struct index_state *, const char *);
-unsigned parse_whitespace_rule(const char *);
-unsigned ws_check(const char *line, int len, unsigned ws_rule);
-void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
-char *whitespace_error_string(unsigned ws);
-void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
-int ws_blank_line(const char *line, int len);
-#define ws_tab_width(rule)     ((rule) & WS_TAB_WIDTH_MASK)
-
 /* ls-files */
 void overlay_tree_on_index(struct index_state *istate,
 			   const char *tree_name, const char *prefix);
 
-/* setup.c */
-struct startup_info {
-	int have_repository;
-	const char *prefix;
-	const char *original_cwd;
-};
-extern struct startup_info *startup_info;
-extern const char *tmp_original_cwd;
-
 /* merge.c */
 struct commit_list;
 int try_merge_command(struct repository *r,
@@ -1928,23 +612,4 @@ int stat_validity_check(struct stat_validity *sv, const char *path);
  */
 void stat_validity_update(struct stat_validity *sv, int fd);
 
-int versioncmp(const char *s1, const char *s2);
-
-/*
- * Create a directory and (if share is nonzero) adjust its permissions
- * according to the shared_repository setting. Only use this for
- * directories under $GIT_DIR.  Don't use it for working tree
- * directories.
- */
-void safe_create_dir(const char *dir, int share);
-
-/*
- * Should we print an ellipsis after an abbreviated SHA-1 value
- * when doing diff-raw output or indicating a detached HEAD?
- */
-int print_sha1_ellipsis(void);
-
-/* Return 1 if the file is empty or does not exists, 0 otherwise. */
-int is_empty_or_missing_file(const char *filename);
-
 #endif /* CACHE_H */
diff --git a/cbtree.c b/cbtree.c
index 336e46d..c1cc30a 100644
--- a/cbtree.c
+++ b/cbtree.c
@@ -4,6 +4,7 @@
  * Based on Adam Langley's adaptation of Dan Bernstein's public domain code
  * git clone https://github.com/agl/critbit.git
  */
+#include "git-compat-util.h"
 #include "cbtree.h"
 
 static struct cb_node *cb_node_of(const void *p)
diff --git a/cbtree.h b/cbtree.h
index 0be14fb..43193ab 100644
--- a/cbtree.h
+++ b/cbtree.h
@@ -14,8 +14,6 @@
 #ifndef CBTREE_H
 #define CBTREE_H
 
-#include "git-compat-util.h"
-
 struct cb_node;
 struct cb_node {
 	struct cb_node *child[2];
diff --git a/chdir-notify.c b/chdir-notify.c
index 5f7f2c2..0d7bc04 100644
--- a/chdir-notify.c
+++ b/chdir-notify.c
@@ -1,7 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
 #include "chdir-notify.h"
 #include "list.h"
+#include "path.h"
 #include "strbuf.h"
+#include "trace.h"
 
 struct chdir_notify_entry {
 	const char *name;
diff --git a/checkout.c b/checkout.c
index 2e39dae..4256e71 100644
--- a/checkout.c
+++ b/checkout.c
@@ -1,8 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "object-name.h"
 #include "remote.h"
 #include "refspec.h"
+#include "repository.h"
 #include "checkout.h"
 #include "config.h"
+#include "strbuf.h"
 
 struct tracking_name_data {
 	/* const */ char *src_ref;
@@ -23,7 +26,7 @@ static int check_tracking_name(struct remote *remote, void *cb_data)
 	memset(&query, 0, sizeof(struct refspec_item));
 	query.src = cb->src_ref;
 	if (remote_find_tracking(remote, &query) ||
-	    get_oid(query.dst, cb->dst_oid)) {
+	    repo_get_oid(the_repository, query.dst, cb->dst_oid)) {
 		free(query.dst);
 		return 0;
 	}
diff --git a/checkout.h b/checkout.h
index 1152133..3c514a5 100644
--- a/checkout.h
+++ b/checkout.h
@@ -1,7 +1,7 @@
 #ifndef CHECKOUT_H
 #define CHECKOUT_H
 
-#include "cache.h"
+#include "hash-ll.h"
 
 /*
  * Check if the branch name uniquely matches a branch name on a remote
diff --git a/chunk-format.c b/chunk-format.c
index 0275b74..e7d613c 100644
--- a/chunk-format.c
+++ b/chunk-format.c
@@ -1,6 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "chunk-format.h"
 #include "csum-file.h"
+#include "gettext.h"
+#include "hash.h"
+#include "trace2.h"
 
 /*
  * When writing a chunk-based file format, collect the chunks in
diff --git a/chunk-format.h b/chunk-format.h
index 7885aa0..c7794e8 100644
--- a/chunk-format.h
+++ b/chunk-format.h
@@ -1,8 +1,7 @@
 #ifndef CHUNK_FORMAT_H
 #define CHUNK_FORMAT_H
 
-#include "git-compat-util.h"
-#include "hash.h"
+#include "hash-ll.h"
 
 struct hashfile;
 struct chunkfile;
diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh
index b098e10..a18b13a 100755
--- a/ci/run-build-and-tests.sh
+++ b/ci/run-build-and-tests.sh
@@ -27,7 +27,7 @@
 	export GIT_TEST_MULTI_PACK_INDEX=1
 	export GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=1
 	export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
-	export GIT_TEST_WRITE_REV_INDEX=1
+	export GIT_TEST_NO_WRITE_REV_INDEX=1
 	export GIT_TEST_CHECKOUT_WORKERS=2
 	;;
 linux-clang)
diff --git a/color.c b/color.c
index f05d8a8..83abb11 100644
--- a/color.c
+++ b/color.c
@@ -1,6 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "color.h"
+#include "editor.h"
+#include "gettext.h"
+#include "hex.h"
+#include "pager.h"
+#include "strbuf.h"
 
 static int git_use_color_default = GIT_COLOR_AUTO;
 int color_stdout_is_tty = -1;
diff --git a/column.c b/column.c
index fbf8863..ff2f0ab 100644
--- a/column.c
+++ b/column.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "column.h"
 #include "string-list.h"
+#include "pager.h"
 #include "parse-options.h"
 #include "run-command.h"
 #include "utf8.h"
diff --git a/combine-diff.c b/combine-diff.c
index 1a39b5d..1e3cd7f 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1,17 +1,23 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "object-store.h"
 #include "commit.h"
+#include "convert.h"
 #include "blob.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "environment.h"
+#include "hex.h"
+#include "object-name.h"
 #include "quote.h"
 #include "xdiff-interface.h"
 #include "xdiff/xmacros.h"
 #include "log-tree.h"
 #include "refs.h"
+#include "tree.h"
 #include "userdiff.h"
 #include "oid-array.h"
 #include "revision.h"
+#include "wrapper.h"
 
 static int compare_paths(const struct combine_diff_path *one,
 			  const struct diff_filespec *two)
@@ -332,7 +338,7 @@ static char *grab_blob(struct repository *r,
 		*size = fill_textconv(r, textconv, df, &blob);
 		free_filespec(df);
 	} else {
-		blob = read_object_file(oid, &type, size);
+		blob = repo_read_object_file(r, oid, &type, size);
 		if (type != OBJ_BLOB)
 			die("object '%s' is not a blob!", oid_to_hex(oid));
 	}
@@ -948,11 +954,11 @@ static void show_combined_header(struct combine_diff_path *elem,
 			 "", elem->path, line_prefix, c_meta, c_reset);
 	printf("%s%sindex ", line_prefix, c_meta);
 	for (i = 0; i < num_parent; i++) {
-		abb = find_unique_abbrev(&elem->parent[i].oid,
-					 abbrev);
+		abb = repo_find_unique_abbrev(the_repository,
+					      &elem->parent[i].oid, abbrev);
 		printf("%s%s", i ? "," : "", abb);
 	}
-	abb = find_unique_abbrev(&elem->oid, abbrev);
+	abb = repo_find_unique_abbrev(the_repository, &elem->oid, abbrev);
 	printf("..%s%s\n", abb, c_reset);
 
 	if (mode_differs) {
diff --git a/commit-graph.c b/commit-graph.c
index c11b59f..843bdb4 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1,5 +1,7 @@
 #include "git-compat-util.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "pack.h"
 #include "packfile.h"
@@ -9,7 +11,9 @@
 #include "revision.h"
 #include "hash-lookup.h"
 #include "commit-graph.h"
+#include "object-file.h"
 #include "object-store.h"
+#include "oid-array.h"
 #include "alloc.h"
 #include "hashmap.h"
 #include "replace-object.h"
@@ -19,7 +23,9 @@
 #include "shallow.h"
 #include "json-writer.h"
 #include "trace2.h"
+#include "tree.h"
 #include "chunk-format.h"
+#include "wrapper.h"
 
 void git_test_write_commit_graph_or_die(void)
 {
@@ -116,12 +122,10 @@ timestamp_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;
+	if (data && data->generation)
+		return data->generation;
 
-	return data->generation;
+	return GENERATION_NUMBER_INFINITY;
 }
 
 static struct commit_graph_data *commit_graph_data_at(const struct commit *c)
@@ -1446,24 +1450,52 @@ static void close_reachable(struct write_commit_graph_context *ctx)
 	stop_progress(&ctx->progress);
 }
 
-static void compute_topological_levels(struct write_commit_graph_context *ctx)
+struct compute_generation_info {
+	struct repository *r;
+	struct packed_commit_list *commits;
+	struct progress *progress;
+	int progress_cnt;
+
+	timestamp_t (*get_generation)(struct commit *c, void *data);
+	void (*set_generation)(struct commit *c, timestamp_t gen, void *data);
+	void *data;
+};
+
+static timestamp_t compute_generation_from_max(struct commit *c,
+					       timestamp_t max_gen,
+					       int generation_version)
+{
+	switch (generation_version) {
+	case 1: /* topological levels */
+		if (max_gen > GENERATION_NUMBER_V1_MAX - 1)
+			max_gen = GENERATION_NUMBER_V1_MAX - 1;
+		return max_gen + 1;
+
+	case 2: /* corrected commit date */
+		if (c->date && c->date > max_gen)
+			max_gen = c->date - 1;
+		return max_gen + 1;
+
+	default:
+		BUG("attempting unimplemented version");
+	}
+}
+
+static void compute_reachable_generation_numbers(
+			struct compute_generation_info *info,
+			int generation_version)
 {
 	int i;
 	struct commit_list *list = NULL;
 
-	if (ctx->report_progress)
-		ctx->progress = start_delayed_progress(
-					_("Computing commit graph topological levels"),
-					ctx->commits.nr);
-	for (i = 0; i < ctx->commits.nr; i++) {
-		struct commit *c = ctx->commits.list[i];
-		uint32_t level;
+	for (i = 0; i < info->commits->nr; i++) {
+		struct commit *c = info->commits->list[i];
+		timestamp_t gen;
+		repo_parse_commit(info->r, c);
+		gen = info->get_generation(c, info->data);
+		display_progress(info->progress, info->progress_cnt + 1);
 
-		repo_parse_commit(ctx->r, c);
-		level = *topo_level_slab_at(ctx->topo_levels, c);
-
-		display_progress(ctx->progress, i + 1);
-		if (level != GENERATION_NUMBER_ZERO)
+		if (gen != GENERATION_NUMBER_ZERO && gen != GENERATION_NUMBER_INFINITY)
 			continue;
 
 		commit_list_insert(c, &list);
@@ -1471,41 +1503,91 @@ static void compute_topological_levels(struct write_commit_graph_context *ctx)
 			struct commit *current = list->item;
 			struct commit_list *parent;
 			int all_parents_computed = 1;
-			uint32_t max_level = 0;
+			uint32_t max_gen = 0;
 
 			for (parent = current->parents; parent; parent = parent->next) {
-				repo_parse_commit(ctx->r, parent->item);
-				level = *topo_level_slab_at(ctx->topo_levels, parent->item);
+				repo_parse_commit(info->r, parent->item);
+				gen = info->get_generation(parent->item, info->data);
 
-				if (level == GENERATION_NUMBER_ZERO) {
+				if (gen == GENERATION_NUMBER_ZERO) {
 					all_parents_computed = 0;
 					commit_list_insert(parent->item, &list);
 					break;
 				}
 
-				if (level > max_level)
-					max_level = level;
+				if (gen > max_gen)
+					max_gen = gen;
 			}
 
 			if (all_parents_computed) {
 				pop_commit(&list);
-
-				if (max_level > GENERATION_NUMBER_V1_MAX - 1)
-					max_level = GENERATION_NUMBER_V1_MAX - 1;
-				*topo_level_slab_at(ctx->topo_levels, current) = max_level + 1;
+				gen = compute_generation_from_max(
+						current, max_gen,
+						generation_version);
+				info->set_generation(current, gen, info->data);
 			}
 		}
 	}
+}
+
+static timestamp_t get_topo_level(struct commit *c, void *data)
+{
+	struct write_commit_graph_context *ctx = data;
+	return *topo_level_slab_at(ctx->topo_levels, c);
+}
+
+static void set_topo_level(struct commit *c, timestamp_t t, void *data)
+{
+	struct write_commit_graph_context *ctx = data;
+	*topo_level_slab_at(ctx->topo_levels, c) = (uint32_t)t;
+}
+
+static void compute_topological_levels(struct write_commit_graph_context *ctx)
+{
+	struct compute_generation_info info = {
+		.r = ctx->r,
+		.commits = &ctx->commits,
+		.get_generation = get_topo_level,
+		.set_generation = set_topo_level,
+		.data = ctx,
+	};
+
+	if (ctx->report_progress)
+		info.progress = ctx->progress
+			      = start_delayed_progress(
+					_("Computing commit graph topological levels"),
+					ctx->commits.nr);
+
+	compute_reachable_generation_numbers(&info, 1);
+
 	stop_progress(&ctx->progress);
 }
 
+static timestamp_t get_generation_from_graph_data(struct commit *c, void *data)
+{
+	return commit_graph_data_at(c)->generation;
+}
+
+static void set_generation_v2(struct commit *c, timestamp_t t, void *data)
+{
+	struct commit_graph_data *g = commit_graph_data_at(c);
+	g->generation = t;
+}
+
 static void compute_generation_numbers(struct write_commit_graph_context *ctx)
 {
 	int i;
-	struct commit_list *list = NULL;
+	struct compute_generation_info info = {
+		.r = ctx->r,
+		.commits = &ctx->commits,
+		.get_generation = get_generation_from_graph_data,
+		.set_generation = set_generation_v2,
+		.data = ctx,
+	};
 
 	if (ctx->report_progress)
-		ctx->progress = start_delayed_progress(
+		info.progress = ctx->progress
+			      = start_delayed_progress(
 					_("Computing commit graph generation numbers"),
 					ctx->commits.nr);
 
@@ -1517,47 +1599,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
 		}
 	}
 
-	for (i = 0; i < ctx->commits.nr; i++) {
-		struct commit *c = ctx->commits.list[i];
-		timestamp_t corrected_commit_date;
-
-		repo_parse_commit(ctx->r, c);
-		corrected_commit_date = commit_graph_data_at(c)->generation;
-
-		display_progress(ctx->progress, i + 1);
-		if (corrected_commit_date != GENERATION_NUMBER_ZERO)
-			continue;
-
-		commit_list_insert(c, &list);
-		while (list) {
-			struct commit *current = list->item;
-			struct commit_list *parent;
-			int all_parents_computed = 1;
-			timestamp_t max_corrected_commit_date = 0;
-
-			for (parent = current->parents; parent; parent = parent->next) {
-				repo_parse_commit(ctx->r, parent->item);
-				corrected_commit_date = commit_graph_data_at(parent->item)->generation;
-
-				if (corrected_commit_date == GENERATION_NUMBER_ZERO) {
-					all_parents_computed = 0;
-					commit_list_insert(parent->item, &list);
-					break;
-				}
-
-				if (corrected_commit_date > max_corrected_commit_date)
-					max_corrected_commit_date = corrected_commit_date;
-			}
-
-			if (all_parents_computed) {
-				pop_commit(&list);
-
-				if (current->date && current->date > max_corrected_commit_date)
-					max_corrected_commit_date = current->date - 1;
-				commit_graph_data_at(current)->generation = max_corrected_commit_date + 1;
-			}
-		}
-	}
+	compute_reachable_generation_numbers(&info, 2);
 
 	for (i = 0; i < ctx->commits.nr; i++) {
 		struct commit *c = ctx->commits.list[i];
@@ -1568,6 +1610,35 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
 	stop_progress(&ctx->progress);
 }
 
+static void set_generation_in_graph_data(struct commit *c, timestamp_t t,
+					 void *data)
+{
+	commit_graph_data_at(c)->generation = t;
+}
+
+/*
+ * After this method, all commits reachable from those in the given
+ * list will have non-zero, non-infinite generation numbers.
+ */
+void ensure_generations_valid(struct repository *r,
+			      struct commit **commits, size_t nr)
+{
+	int generation_version = get_configured_generation_version(r);
+	struct packed_commit_list list = {
+		.list = commits,
+		.alloc = nr,
+		.nr = nr,
+	};
+	struct compute_generation_info info = {
+		.r = r,
+		.commits = &list,
+		.get_generation = get_generation_from_graph_data,
+		.set_generation = set_generation_in_graph_data,
+	};
+
+	compute_reachable_generation_numbers(&info, generation_version);
+}
+
 static void trace2_bloom_filter_write_statistics(struct write_commit_graph_context *ctx)
 {
 	trace2_data_intmax("commit-graph", ctx->r, "filter-computed",
@@ -2360,7 +2431,7 @@ int write_commit_graph(struct object_directory *odb,
 			replace = ctx->opts->split_flags & COMMIT_GRAPH_SPLIT_REPLACE;
 	}
 
-	ctx->approx_nr_objects = approximate_object_count();
+	ctx->approx_nr_objects = repo_approximate_object_count(the_repository);
 
 	if (ctx->append && ctx->r->objects->commit_graph) {
 		struct commit_graph *g = ctx->r->objects->commit_graph;
@@ -2549,7 +2620,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags)
 
 		graph_commit = lookup_commit(r, &cur_oid);
 		odb_commit = (struct commit *)create_object(r, &cur_oid, alloc_commit_node(r));
-		if (parse_commit_internal(odb_commit, 0, 0)) {
+		if (repo_parse_commit_internal(r, odb_commit, 0, 0)) {
 			graph_report(_("failed to parse commit %s from object database for commit-graph"),
 				     oid_to_hex(&cur_oid));
 			continue;
diff --git a/commit-graph.h b/commit-graph.h
index 37faee6..83aaa1d 100644
--- a/commit-graph.h
+++ b/commit-graph.h
@@ -1,7 +1,6 @@
 #ifndef COMMIT_GRAPH_H
 #define COMMIT_GRAPH_H
 
-#include "git-compat-util.h"
 #include "object-store.h"
 #include "oidset.h"
 
@@ -190,4 +189,12 @@ struct commit_graph_data {
  */
 timestamp_t commit_graph_generation(const struct commit *);
 uint32_t commit_graph_position(const struct commit *);
+
+/*
+ * After this method, all commits reachable from those in the given
+ * list will have non-zero, non-infinite generation numbers.
+ */
+void ensure_generations_valid(struct repository *r,
+			      struct commit **commits, size_t nr);
+
 #endif
diff --git a/commit-reach.c b/commit-reach.c
index 2e33c59..70bde8a 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -1,13 +1,16 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "commit.h"
 #include "commit-graph.h"
 #include "decorate.h"
+#include "hex.h"
 #include "prio-queue.h"
 #include "tree.h"
 #include "ref-filter.h"
 #include "revision.h"
 #include "tag.h"
 #include "commit-reach.h"
+#include "ewah/ewok.h"
 
 /* Remember to update object flag allocation in object.h */
 #define PARENT1		(1u<<16)
@@ -162,7 +165,8 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in)
 
 		for (j = ret; j; j = j->next) {
 			struct commit_list *bases;
-			bases = get_merge_bases(i->item, j->item);
+			bases = repo_get_merge_bases(the_repository, i->item,
+						     j->item);
 			if (!new_commits)
 				new_commits = bases;
 			else
@@ -447,7 +451,7 @@ int repo_is_descendant_of(struct repository *r,
 	if (!with_commit)
 		return 1;
 
-	if (generation_numbers_enabled(the_repository)) {
+	if (generation_numbers_enabled(r)) {
 		struct commit_list *from_list = NULL;
 		int result;
 		commit_list_insert(commit, &from_list);
@@ -584,7 +588,7 @@ int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid)
 		return 0;
 	new_commit = (struct commit *) o;
 
-	if (parse_commit(new_commit) < 0)
+	if (repo_parse_commit(the_repository, new_commit) < 0)
 		return 0;
 
 	commit_list_insert(old_commit, &old_commit_list);
@@ -748,7 +752,7 @@ int can_all_from_reach_with_flag(struct object_array *from,
 		}
 
 		list[nr_commits] = (struct commit *)from_one;
-		if (parse_commit(list[nr_commits]) ||
+		if (repo_parse_commit(the_repository, list[nr_commits]) ||
 		    commit_graph_generation(list[nr_commits]) < min_generation) {
 			result = 0;
 			goto cleanup;
@@ -783,7 +787,7 @@ int can_all_from_reach_with_flag(struct object_array *from,
 				if (!(parent->item->object.flags & assign_flag)) {
 					parent->item->object.flags |= assign_flag;
 
-					if (parse_commit(parent->item) ||
+					if (repo_parse_commit(the_repository, parent->item) ||
 					    parent->item->date < min_commit_date ||
 					    commit_graph_generation(parent->item) < min_generation)
 						continue;
@@ -807,8 +811,12 @@ int can_all_from_reach_with_flag(struct object_array *from,
 	clear_commit_marks_many(nr_commits, list, RESULT | assign_flag);
 	free(list);
 
-	for (i = 0; i < from->nr; i++)
-		from->objects[i].item->flags &= ~assign_flag;
+	for (i = 0; i < from->nr; i++) {
+		struct object *from_one = from->objects[i].item;
+
+		if (from_one)
+			from_one->flags &= ~assign_flag;
+	}
 
 	return result;
 }
@@ -825,7 +833,7 @@ int can_all_from_reach(struct commit_list *from, struct commit_list *to,
 	while (from_iter) {
 		add_object_array(&from_iter->item->object, NULL, &from_objs);
 
-		if (!parse_commit(from_iter->item)) {
+		if (!repo_parse_commit(the_repository, from_iter->item)) {
 			timestamp_t generation;
 			if (from_iter->item->date < min_commit_date)
 				min_commit_date = from_iter->item->date;
@@ -839,7 +847,7 @@ int can_all_from_reach(struct commit_list *from, struct commit_list *to,
 	}
 
 	while (to_iter) {
-		if (!parse_commit(to_iter->item)) {
+		if (!repo_parse_commit(the_repository, to_iter->item)) {
 			timestamp_t generation;
 			if (to_iter->item->date < min_commit_date)
 				min_commit_date = to_iter->item->date;
@@ -889,7 +897,7 @@ struct commit_list *get_reachable_subset(struct commit **from, int nr_from,
 		timestamp_t generation;
 		struct commit *c = *item;
 
-		parse_commit(c);
+		repo_parse_commit(the_repository, c);
 		generation = commit_graph_generation(c);
 		if (generation < min_generation)
 			min_generation = generation;
@@ -904,7 +912,7 @@ struct commit_list *get_reachable_subset(struct commit **from, int nr_from,
 		struct commit *c = *item;
 		if (!(c->object.flags & PARENT2)) {
 			c->object.flags |= PARENT2;
-			parse_commit(c);
+			repo_parse_commit(the_repository, c);
 
 			prio_queue_put(&queue, *item);
 		}
@@ -923,7 +931,7 @@ struct commit_list *get_reachable_subset(struct commit **from, int nr_from,
 		for (parents = current->parents; parents; parents = parents->next) {
 			struct commit *p = parents->item;
 
-			parse_commit(p);
+			repo_parse_commit(the_repository, p);
 
 			if (commit_graph_generation(p) < min_generation)
 				continue;
@@ -941,3 +949,218 @@ struct commit_list *get_reachable_subset(struct commit **from, int nr_from,
 
 	return found_commits;
 }
+
+define_commit_slab(bit_arrays, struct bitmap *);
+static struct bit_arrays bit_arrays;
+
+static void insert_no_dup(struct prio_queue *queue, struct commit *c)
+{
+	if (c->object.flags & PARENT2)
+		return;
+	prio_queue_put(queue, c);
+	c->object.flags |= PARENT2;
+}
+
+static struct bitmap *get_bit_array(struct commit *c, int width)
+{
+	struct bitmap **bitmap = bit_arrays_at(&bit_arrays, c);
+	if (!*bitmap)
+		*bitmap = bitmap_word_alloc(width);
+	return *bitmap;
+}
+
+static void free_bit_array(struct commit *c)
+{
+	struct bitmap **bitmap = bit_arrays_at(&bit_arrays, c);
+	if (!*bitmap)
+		return;
+	bitmap_free(*bitmap);
+	*bitmap = NULL;
+}
+
+void ahead_behind(struct repository *r,
+		  struct commit **commits, size_t commits_nr,
+		  struct ahead_behind_count *counts, size_t counts_nr)
+{
+	struct prio_queue queue = { .compare = compare_commits_by_gen_then_commit_date };
+	size_t width = DIV_ROUND_UP(commits_nr, BITS_IN_EWORD);
+
+	if (!commits_nr || !counts_nr)
+		return;
+
+	for (size_t i = 0; i < counts_nr; i++) {
+		counts[i].ahead = 0;
+		counts[i].behind = 0;
+	}
+
+	ensure_generations_valid(r, commits, commits_nr);
+
+	init_bit_arrays(&bit_arrays);
+
+	for (size_t i = 0; i < commits_nr; i++) {
+		struct commit *c = commits[i];
+		struct bitmap *bitmap = get_bit_array(c, width);
+
+		bitmap_set(bitmap, i);
+		insert_no_dup(&queue, c);
+	}
+
+	while (queue_has_nonstale(&queue)) {
+		struct commit *c = prio_queue_get(&queue);
+		struct commit_list *p;
+		struct bitmap *bitmap_c = get_bit_array(c, width);
+
+		for (size_t i = 0; i < counts_nr; i++) {
+			int reach_from_tip = !!bitmap_get(bitmap_c, counts[i].tip_index);
+			int reach_from_base = !!bitmap_get(bitmap_c, counts[i].base_index);
+
+			if (reach_from_tip ^ reach_from_base) {
+				if (reach_from_base)
+					counts[i].behind++;
+				else
+					counts[i].ahead++;
+			}
+		}
+
+		for (p = c->parents; p; p = p->next) {
+			struct bitmap *bitmap_p;
+
+			repo_parse_commit(r, p->item);
+
+			bitmap_p = get_bit_array(p->item, width);
+			bitmap_or(bitmap_p, bitmap_c);
+
+			/*
+			 * If this parent is reachable from every starting
+			 * commit, then none of its ancestors can contribute
+			 * to the ahead/behind count. Mark it as STALE, so
+			 * we can stop the walk when every commit in the
+			 * queue is STALE.
+			 */
+			if (bitmap_popcount(bitmap_p) == commits_nr)
+				p->item->object.flags |= STALE;
+
+			insert_no_dup(&queue, p->item);
+		}
+
+		free_bit_array(c);
+	}
+
+	/* STALE is used here, PARENT2 is used by insert_no_dup(). */
+	repo_clear_commit_marks(r, PARENT2 | STALE);
+	clear_bit_arrays(&bit_arrays);
+	clear_prio_queue(&queue);
+}
+
+struct commit_and_index {
+	struct commit *commit;
+	unsigned int index;
+	timestamp_t generation;
+};
+
+static int compare_commit_and_index_by_generation(const void *va, const void *vb)
+{
+	const struct commit_and_index *a = (const struct commit_and_index *)va;
+	const struct commit_and_index *b = (const struct commit_and_index *)vb;
+
+	if (a->generation > b->generation)
+		return 1;
+	if (a->generation < b->generation)
+		return -1;
+	return 0;
+}
+
+void tips_reachable_from_bases(struct repository *r,
+			       struct commit_list *bases,
+			       struct commit **tips, size_t tips_nr,
+			       int mark)
+{
+	struct commit_and_index *commits;
+	size_t min_generation_index = 0;
+	timestamp_t min_generation;
+	struct commit_list *stack = NULL;
+
+	if (!bases || !tips || !tips_nr)
+		return;
+
+	/*
+	 * Do a depth-first search starting at 'bases' to search for the
+	 * tips. Stop at the lowest (un-found) generation number. When
+	 * finding the lowest commit, increase the minimum generation
+	 * number to the next lowest (un-found) generation number.
+	 */
+
+	CALLOC_ARRAY(commits, tips_nr);
+
+	for (size_t i = 0; i < tips_nr; i++) {
+		commits[i].commit = tips[i];
+		commits[i].index = i;
+		commits[i].generation = commit_graph_generation(tips[i]);
+	}
+
+	/* Sort with generation number ascending. */
+	QSORT(commits, tips_nr, compare_commit_and_index_by_generation);
+	min_generation = commits[0].generation;
+
+	while (bases) {
+		repo_parse_commit(r, bases->item);
+		commit_list_insert(bases->item, &stack);
+		bases = bases->next;
+	}
+
+	while (stack) {
+		int explored_all_parents = 1;
+		struct commit_list *p;
+		struct commit *c = stack->item;
+		timestamp_t c_gen = commit_graph_generation(c);
+
+		/* Does it match any of our tips? */
+		for (size_t j = min_generation_index; j < tips_nr; j++) {
+			if (c_gen < commits[j].generation)
+				break;
+
+			if (commits[j].commit == c) {
+				tips[commits[j].index]->object.flags |= mark;
+
+				if (j == min_generation_index) {
+					unsigned int k = j + 1;
+					while (k < tips_nr &&
+					       (tips[commits[k].index]->object.flags & mark))
+						k++;
+
+					/* Terminate early if all found. */
+					if (k >= tips_nr)
+						goto done;
+
+					min_generation_index = k;
+					min_generation = commits[k].generation;
+				}
+			}
+		}
+
+		for (p = c->parents; p; p = p->next) {
+			repo_parse_commit(r, p->item);
+
+			/* Have we already explored this parent? */
+			if (p->item->object.flags & SEEN)
+				continue;
+
+			/* Is it below the current minimum generation? */
+			if (commit_graph_generation(p->item) < min_generation)
+				continue;
+
+			/* Ok, we will explore from here on. */
+			p->item->object.flags |= SEEN;
+			explored_all_parents = 0;
+			commit_list_insert(p->item, &stack);
+			break;
+		}
+
+		if (explored_all_parents)
+			pop_commit(&stack);
+	}
+
+done:
+	free(commits);
+	repo_clear_commit_marks(r, SEEN);
+}
diff --git a/commit-reach.h b/commit-reach.h
index 148b56f..35c4da4 100644
--- a/commit-reach.h
+++ b/commit-reach.h
@@ -19,11 +19,6 @@ struct commit_list *repo_get_merge_bases_many(struct repository *r,
 struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
 						    struct commit *one, int n,
 						    struct commit **twos);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define get_merge_bases(r1, r2)           repo_get_merge_bases(the_repository, r1, r2)
-#define get_merge_bases_many(one, n, two) repo_get_merge_bases_many(the_repository, one, n, two)
-#define get_merge_bases_many_dirty(one, n, twos) repo_get_merge_bases_many_dirty(the_repository, one, n, twos)
-#endif
 
 struct commit_list *get_octopus_merge_bases(struct commit_list *in);
 
@@ -36,10 +31,6 @@ int repo_in_merge_bases(struct repository *r,
 int repo_in_merge_bases_many(struct repository *r,
 			     struct commit *commit,
 			     int nr_reference, struct commit **reference);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define in_merge_bases(c1, c2) repo_in_merge_bases(the_repository, c1, c2)
-#define in_merge_bases_many(c1, n, cs) repo_in_merge_bases_many(the_repository, c1, n, cs)
-#endif
 
 /*
  * Takes a list of commits and returns a new list where those
@@ -104,4 +95,44 @@ struct commit_list *get_reachable_subset(struct commit **from, int nr_from,
 					 struct commit **to, int nr_to,
 					 unsigned int reachable_flag);
 
+struct ahead_behind_count {
+	/**
+	 * As input, the *_index members indicate which positions in
+	 * the 'tips' array correspond to the tip and base of this
+	 * comparison.
+	 */
+	size_t tip_index;
+	size_t base_index;
+
+	/**
+	 * These values store the computed counts for each side of the
+	 * symmetric difference:
+	 *
+	 * 'ahead' stores the number of commits reachable from the tip
+	 * and not reachable from the base.
+	 *
+	 * 'behind' stores the number of commits reachable from the base
+	 * and not reachable from the tip.
+	 */
+	unsigned int ahead;
+	unsigned int behind;
+};
+
+/*
+ * Given an array of commits and an array of ahead_behind_count pairs,
+ * compute the ahead/behind counts for each pair.
+ */
+void ahead_behind(struct repository *r,
+		  struct commit **commits, size_t commits_nr,
+		  struct ahead_behind_count *counts, size_t counts_nr);
+
+/*
+ * For all tip commits, add 'mark' to their flags if and only if they
+ * are reachable from one of the commits in 'bases'.
+ */
+void tips_reachable_from_bases(struct repository *r,
+			       struct commit_list *bases,
+			       struct commit **tips, size_t tips_nr,
+			       int mark);
+
 #endif
diff --git a/commit-slab-impl.h b/commit-slab-impl.h
index 557738d..4a414ee 100644
--- a/commit-slab-impl.h
+++ b/commit-slab-impl.h
@@ -1,8 +1,6 @@
 #ifndef COMMIT_SLAB_IMPL_H
 #define COMMIT_SLAB_IMPL_H
 
-#include "git-compat-util.h"
-
 #define implement_static_commit_slab(slabname, elemtype) \
 	implement_commit_slab(slabname, elemtype, MAYBE_UNUSED static)
 
diff --git a/commit.c b/commit.c
index e433c33..0fb9316 100644
--- a/commit.c
+++ b/commit.c
@@ -1,8 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "tag.h"
 #include "commit.h"
 #include "commit-graph.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "pkt-line.h"
 #include "utf8.h"
@@ -20,7 +24,9 @@
 #include "refs.h"
 #include "commit-reach.h"
 #include "run-command.h"
+#include "setup.h"
 #include "shallow.h"
+#include "tree.h"
 #include "hook.h"
 
 static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
@@ -80,10 +86,10 @@ struct commit *lookup_commit_reference_by_name(const char *name)
 	struct object_id oid;
 	struct commit *commit;
 
-	if (get_oid_committish(name, &oid))
+	if (repo_get_oid_committish(the_repository, name, &oid))
 		return NULL;
 	commit = lookup_commit_reference(the_repository, &oid);
-	if (parse_commit(commit))
+	if (repo_parse_commit(the_repository, commit))
 		return NULL;
 	return commit;
 }
@@ -91,6 +97,7 @@ struct commit *lookup_commit_reference_by_name(const char *name)
 static timestamp_t parse_commit_date(const char *buf, const char *tail)
 {
 	const char *dateptr;
+	const char *eol;
 
 	if (buf + 6 >= tail)
 		return 0;
@@ -102,16 +109,56 @@ static timestamp_t parse_commit_date(const char *buf, const char *tail)
 		return 0;
 	if (memcmp(buf, "committer", 9))
 		return 0;
-	while (buf < tail && *buf++ != '>')
-		/* nada */;
-	if (buf >= tail)
+
+	/*
+	 * Jump to end-of-line so that we can walk backwards to find the
+	 * end-of-email ">". This is more forgiving of malformed cases
+	 * because unexpected characters tend to be in the name and email
+	 * fields.
+	 */
+	eol = memchr(buf, '\n', tail - buf);
+	if (!eol)
 		return 0;
-	dateptr = buf;
-	while (buf < tail && *buf++ != '\n')
-		/* nada */;
-	if (buf >= tail)
+	dateptr = eol;
+	while (dateptr > buf && dateptr[-1] != '>')
+		dateptr--;
+	if (dateptr == buf)
 		return 0;
-	/* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */
+
+	/*
+	 * Trim leading whitespace, but make sure we have at least one
+	 * non-whitespace character, as parse_timestamp() will otherwise walk
+	 * right past the newline we found in "eol" when skipping whitespace
+	 * itself.
+	 *
+	 * In theory it would be sufficient to allow any character not matched
+	 * by isspace(), but there's a catch: our isspace() does not
+	 * necessarily match the behavior of parse_timestamp(), as the latter
+	 * is implemented by system routines which match more exotic control
+	 * codes, or even locale-dependent sequences.
+	 *
+	 * Since we expect the timestamp to be a number, we can check for that.
+	 * Anything else (e.g., a non-numeric token like "foo") would just
+	 * cause parse_timestamp() to return 0 anyway.
+	 */
+	while (dateptr < eol && isspace(*dateptr))
+		dateptr++;
+	if (!isdigit(*dateptr) && *dateptr != '-')
+		return 0;
+
+	/*
+	 * We know there is at least one digit (or dash), so we'll begin
+	 * parsing there and stop at worst case at eol.
+	 *
+	 * Note that we may feed parse_timestamp() extra characters here if the
+	 * commit is malformed, and it will parse as far as it can. For
+	 * example, "123foo456" would return "123". That might be questionable
+	 * (versus returning "0"), but it would help in a hypothetical case
+	 * like "123456+0100", where the whitespace from the timezone is
+	 * missing. Since such syntactic errors may be baked into history and
+	 * hard to correct now, let's err on trying to make our best guess
+	 * here, rather than insist on perfect syntax.
+	 */
 	return parse_timestamp(dateptr, NULL, 10);
 }
 
@@ -382,7 +429,7 @@ struct tree *repo_get_commit_tree(struct repository *r,
 
 struct object_id *get_commit_tree_oid(const struct commit *commit)
 {
-	struct tree *tree = get_commit_tree(commit);
+	struct tree *tree = repo_get_commit_tree(the_repository, commit);
 	return tree ? &tree->object.oid : NULL;
 }
 
@@ -555,7 +602,7 @@ int repo_parse_commit_gently(struct repository *r,
 
 void parse_commit_or_die(struct commit *item)
 {
-	if (parse_commit(item))
+	if (repo_parse_commit(the_repository, item))
 		die("unable to parse commit %s",
 		    item ? oid_to_hex(&item->object.oid) : "(null)");
 }
@@ -688,7 +735,7 @@ struct commit *pop_most_recent_commit(struct commit_list **list,
 
 	while (parents) {
 		struct commit *commit = parents->item;
-		if (!parse_commit(commit) && !(commit->object.flags & mark)) {
+		if (!repo_parse_commit(the_repository, commit) && !(commit->object.flags & mark)) {
 			commit->object.flags |= mark;
 			commit_list_insert_by_date(commit, list);
 		}
@@ -762,7 +809,8 @@ define_commit_slab(author_date_slab, timestamp_t);
 void record_author_date(struct author_date_slab *author_date,
 			struct commit *commit)
 {
-	const char *buffer = get_commit_buffer(commit, NULL);
+	const char *buffer = repo_get_commit_buffer(the_repository, commit,
+						    NULL);
 	struct ident_split ident;
 	const char *ident_line;
 	size_t ident_len;
@@ -782,7 +830,7 @@ void record_author_date(struct author_date_slab *author_date,
 	*(author_date_slab_at(author_date, commit)) = date;
 
 fail_exit:
-	unuse_commit_buffer(commit, buffer);
+	repo_unuse_commit_buffer(the_repository, commit, buffer);
 }
 
 int compare_commits_by_author_date(const void *a_, const void *b_,
@@ -801,7 +849,8 @@ int compare_commits_by_author_date(const void *a_, const void *b_,
 	return 0;
 }
 
-int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void *unused)
+int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_,
+					    void *unused UNUSED)
 {
 	const struct commit *a = a_, *b = b_;
 	const timestamp_t generation_a = commit_graph_generation(a),
@@ -821,7 +870,8 @@ int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void
 	return 0;
 }
 
-int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused)
+int compare_commits_by_commit_date(const void *a_, const void *b_,
+				   void *unused UNUSED)
 {
 	const struct commit *a = a_, *b = b_;
 	/* newer commits with larger date first */
@@ -963,7 +1013,7 @@ static void add_one_commit(struct object_id *oid, struct rev_collect *revs)
 	commit = lookup_commit(the_repository, oid);
 	if (!commit ||
 	    (commit->object.flags & TMP_MARK) ||
-	    parse_commit(commit))
+	    repo_parse_commit(the_repository, commit))
 		return;
 
 	ALLOC_GROW(revs->commit, revs->nr + 1, revs->alloc);
@@ -995,7 +1045,8 @@ struct commit *get_fork_point(const char *refname, struct commit *commit)
 	struct commit *ret = NULL;
 	char *full_refname;
 
-	switch (dwim_ref(refname, strlen(refname), &oid, &full_refname, 0)) {
+	switch (repo_dwim_ref(the_repository, refname, strlen(refname), &oid,
+			      &full_refname, 0)) {
 	case 0:
 		die("No such ref: '%s'", refname);
 	case 1:
@@ -1014,7 +1065,8 @@ struct commit *get_fork_point(const char *refname, struct commit *commit)
 	for (i = 0; i < revs.nr; i++)
 		revs.commit[i]->object.flags &= ~TMP_MARK;
 
-	bases = get_merge_bases_many(commit, revs.nr, revs.commit);
+	bases = repo_get_merge_bases_many(the_repository, commit, revs.nr,
+					  revs.commit);
 
 	/*
 	 * There should be one and only one merge base, when we found
@@ -1095,10 +1147,11 @@ int parse_signed_commit(const struct commit *commit,
 			const struct git_hash_algo *algop)
 {
 	unsigned long size;
-	const char *buffer = get_commit_buffer(commit, &size);
+	const char *buffer = repo_get_commit_buffer(the_repository, commit,
+						    &size);
 	int ret = parse_buffer_signed_by_header(buffer, size, payload, signature, algop);
 
-	unuse_commit_buffer(commit, buffer);
+	repo_unuse_commit_buffer(the_repository, commit, buffer);
 	return ret;
 }
 
@@ -1209,7 +1262,8 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header
 	desc = merge_remote_util(parent);
 	if (!desc || !desc->obj)
 		return;
-	buf = read_object_file(&desc->obj->oid, &type, &size);
+	buf = repo_read_object_file(the_repository, &desc->obj->oid, &type,
+				    &size);
 	if (!buf || type != OBJ_TAG)
 		goto free_return;
 	if (!parse_signature(buf, size, &payload, &signature))
@@ -1271,7 +1325,8 @@ void verify_merge_signature(struct commit *commit, int verbosity,
 
 	ret = check_commit_signature(commit, &signature_check);
 
-	find_unique_abbrev_r(hex, &commit->object.oid, DEFAULT_ABBREV);
+	repo_find_unique_abbrev_r(the_repository, hex, &commit->object.oid,
+				  DEFAULT_ABBREV);
 	switch (signature_check.result) {
 	case 'G':
 		if (ret || (check_trust && signature_check.trust_level < TRUST_MARGINAL))
@@ -1316,9 +1371,10 @@ struct commit_extra_header *read_commit_extra_headers(struct commit *commit,
 {
 	struct commit_extra_header *extra = NULL;
 	unsigned long size;
-	const char *buffer = get_commit_buffer(commit, &size);
+	const char *buffer = repo_get_commit_buffer(the_repository, commit,
+						    &size);
 	extra = read_commit_extra_header_lines(buffer, size, exclude);
-	unuse_commit_buffer(commit, buffer);
+	repo_unuse_commit_buffer(the_repository, commit, buffer);
 	return extra;
 }
 
@@ -1632,10 +1688,11 @@ struct commit *get_merge_parent(const char *name)
 	struct object *obj;
 	struct commit *commit;
 	struct object_id oid;
-	if (get_oid(name, &oid))
+	if (repo_get_oid(the_repository, name, &oid))
 		return NULL;
 	obj = parse_object(the_repository, &oid);
-	commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
+	commit = (struct commit *)repo_peel_to_type(the_repository, name, 0,
+						    obj, OBJ_COMMIT);
 	if (commit && !merge_remote_util(commit))
 		set_merge_remote_desc(commit, name, obj);
 	return commit;
diff --git a/commit.h b/commit.h
index cc2c5da..2892883 100644
--- a/commit.h
+++ b/commit.h
@@ -2,13 +2,10 @@
 #define COMMIT_H
 
 #include "object.h"
-#include "tree.h"
-#include "strbuf.h"
-#include "decorate.h"
-#include "gpg-interface.h"
-#include "string-list.h"
-#include "pretty.h"
-#include "commit-slab.h"
+
+struct signature_check;
+struct strbuf;
+struct tree;
 
 #define COMMIT_NOT_FROM_GRAPH 0xFFFFFFFF
 #define GENERATION_NUMBER_INFINITY ((1ULL << 63) - 1)
@@ -109,11 +106,6 @@ static inline int repo_parse_commit_no_graph(struct repository *r,
 	return repo_parse_commit_internal(r, commit, 0, 0);
 }
 
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define parse_commit_internal(item, quiet, use) repo_parse_commit_internal(the_repository, item, quiet, use)
-#define parse_commit(item) repo_parse_commit(the_repository, item)
-#endif
-
 void parse_commit_or_die(struct commit *item);
 
 struct buffer_slab;
@@ -135,27 +127,21 @@ const void *get_cached_commit_buffer(struct repository *, const struct commit *,
 /*
  * Get the commit's object contents, either from cache or by reading the object
  * from disk. The resulting memory should not be modified, and must be given
- * to unuse_commit_buffer when the caller is done.
+ * to repo_unuse_commit_buffer when the caller is done.
  */
 const void *repo_get_commit_buffer(struct repository *r,
 				   const struct commit *,
 				   unsigned long *size);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define get_commit_buffer(c, s) repo_get_commit_buffer(the_repository, c, s)
-#endif
 
 /*
  * Tell the commit subsystem that we are done with a particular commit buffer.
  * The commit and buffer should be the input and return value, respectively,
- * from an earlier call to get_commit_buffer.  The buffer may or may not be
+ * from an earlier call to repo_get_commit_buffer.  The buffer may or may not be
  * freed by this call; callers should not access the memory afterwards.
  */
 void repo_unuse_commit_buffer(struct repository *r,
 			      const struct commit *,
 			      const void *buffer);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define unuse_commit_buffer(c, b) repo_unuse_commit_buffer(the_repository, c, b)
-#endif
 
 /*
  * Free any cached object buffer associated with the commit.
@@ -163,7 +149,6 @@ void repo_unuse_commit_buffer(struct repository *r,
 void free_commit_buffer(struct parsed_object_pool *pool, struct commit *);
 
 struct tree *repo_get_commit_tree(struct repository *, const struct commit *);
-#define get_commit_tree(c) repo_get_commit_tree(the_repository, c)
 struct object_id *get_commit_tree_oid(const struct commit *);
 
 /*
@@ -205,17 +190,10 @@ void free_commit_list(struct commit_list *list);
 
 struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
 
-int has_non_ascii(const char *text);
-const char *logmsg_reencode(const struct commit *commit,
-			    char **commit_encoding,
-			    const char *output_encoding);
 const char *repo_logmsg_reencode(struct repository *r,
 				 const struct commit *commit,
 				 char **commit_encoding,
 				 const char *output_encoding);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define logmsg_reencode(c, enc, out) repo_logmsg_reencode(the_repository, c, enc, out)
-#endif
 
 const char *skip_blank_lines(const char *msg);
 
diff --git a/common-main.c b/common-main.c
index 0a22861..033778b 100644
--- a/common-main.c
+++ b/common-main.c
@@ -1,6 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "exec-cmd.h"
+#include "gettext.h"
 #include "attr.h"
+#include "repository.h"
+#include "setup.h"
+#include "strbuf.h"
+#include "trace2.h"
 
 /*
  * Many parts of Git have subprograms communicate via pipe, expect the
diff --git a/compat/disk.h b/compat/disk.h
index 50a32e3..6c979c2 100644
--- a/compat/disk.h
+++ b/compat/disk.h
@@ -2,6 +2,8 @@
 #define COMPAT_DISK_H
 
 #include "git-compat-util.h"
+#include "abspath.h"
+#include "gettext.h"
 
 static int get_disk_info(struct strbuf *out)
 {
diff --git a/compat/fsmonitor/fsm-health-darwin.c b/compat/fsmonitor/fsm-health-darwin.c
index b9f709e..4c291f8 100644
--- a/compat/fsmonitor/fsm-health-darwin.c
+++ b/compat/fsmonitor/fsm-health-darwin.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "fsmonitor.h"
 #include "fsm-health.h"
diff --git a/compat/fsmonitor/fsm-health-win32.c b/compat/fsmonitor/fsm-health-win32.c
index 2ea08c1..fe11bdd 100644
--- a/compat/fsmonitor/fsm-health-win32.c
+++ b/compat/fsmonitor/fsm-health-win32.c
@@ -3,6 +3,7 @@
 #include "fsmonitor.h"
 #include "fsm-health.h"
 #include "fsmonitor--daemon.h"
+#include "gettext.h"
 
 /*
  * Every minute wake up and test our health.
diff --git a/compat/fsmonitor/fsm-ipc-darwin.c b/compat/fsmonitor/fsm-ipc-darwin.c
index d67b0ee..793073a 100644
--- a/compat/fsmonitor/fsm-ipc-darwin.c
+++ b/compat/fsmonitor/fsm-ipc-darwin.c
@@ -1,5 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
+#include "repository.h"
 #include "strbuf.h"
 #include "fsmonitor.h"
 #include "fsmonitor-ipc.h"
diff --git a/compat/fsmonitor/fsm-ipc-win32.c b/compat/fsmonitor/fsm-ipc-win32.c
index e08c505..8928fa9 100644
--- a/compat/fsmonitor/fsm-ipc-win32.c
+++ b/compat/fsmonitor/fsm-ipc-win32.c
@@ -1,5 +1,7 @@
+#include "git-compat-util.h"
 #include "config.h"
 #include "fsmonitor-ipc.h"
+#include "path.h"
 
 const char *fsmonitor_ipc__get_path(struct repository *r) {
 	static char *ret;
diff --git a/compat/fsmonitor/fsm-listen-darwin.c b/compat/fsmonitor/fsm-listen-darwin.c
index 97a55a6..23e24b4 100644
--- a/compat/fsmonitor/fsm-listen-darwin.c
+++ b/compat/fsmonitor/fsm-listen-darwin.c
@@ -23,11 +23,13 @@
 #endif
 #endif
 
-#include "cache.h"
+#include "git-compat-util.h"
 #include "fsmonitor.h"
 #include "fsm-listen.h"
 #include "fsmonitor--daemon.h"
 #include "fsmonitor-path-utils.h"
+#include "gettext.h"
+#include "string-list.h"
 
 struct fsm_listen_data
 {
diff --git a/compat/fsmonitor/fsm-listen-win32.c b/compat/fsmonitor/fsm-listen-win32.c
index 03df8d9..677b1bb 100644
--- a/compat/fsmonitor/fsm-listen-win32.c
+++ b/compat/fsmonitor/fsm-listen-win32.c
@@ -3,6 +3,8 @@
 #include "fsmonitor.h"
 #include "fsm-listen.h"
 #include "fsmonitor--daemon.h"
+#include "gettext.h"
+#include "trace2.h"
 
 /*
  * The documentation of ReadDirectoryChangesW() states that the maximum
diff --git a/compat/fsmonitor/fsm-path-utils-darwin.c b/compat/fsmonitor/fsm-path-utils-darwin.c
index ce5a8fe..45eb4a9 100644
--- a/compat/fsmonitor/fsm-path-utils-darwin.c
+++ b/compat/fsmonitor/fsm-path-utils-darwin.c
@@ -1,5 +1,6 @@
 #include "fsmonitor.h"
 #include "fsmonitor-path-utils.h"
+#include "gettext.h"
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
diff --git a/compat/fsmonitor/fsm-path-utils-win32.c b/compat/fsmonitor/fsm-path-utils-win32.c
index 0d95bbb..4024baa 100644
--- a/compat/fsmonitor/fsm-path-utils-win32.c
+++ b/compat/fsmonitor/fsm-path-utils-win32.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "fsmonitor.h"
 #include "fsmonitor-path-utils.h"
+#include "gettext.h"
 
 /*
  * Check remote working directory protocol.
diff --git a/compat/fsmonitor/fsm-settings-darwin.c b/compat/fsmonitor/fsm-settings-darwin.c
index 6abbc7a..58b623f 100644
--- a/compat/fsmonitor/fsm-settings-darwin.c
+++ b/compat/fsmonitor/fsm-settings-darwin.c
@@ -1,3 +1,4 @@
+#include "git-compat-util.h"
 #include "config.h"
 #include "fsmonitor.h"
 #include "fsmonitor-ipc.h"
diff --git a/compat/linux/procinfo.c b/compat/linux/procinfo.c
index bc2f938..4bb2d66 100644
--- a/compat/linux/procinfo.c
+++ b/compat/linux/procinfo.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 
 #include "strbuf.h"
 #include "strvec.h"
diff --git a/compat/mingw.c b/compat/mingw.c
index e433740..d06cdc6 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -7,9 +7,16 @@
 #include "../strbuf.h"
 #include "../run-command.h"
 #include "../cache.h"
+#include "../abspath.h"
+#include "../alloc.h"
 #include "win32/lazyload.h"
 #include "../config.h"
+#include "../environment.h"
+#include "../trace2.h"
+#include "../symlinks.h"
+#include "../wrapper.h"
 #include "dir.h"
+#include "gettext.h"
 #define SECURITY_WIN32
 #include <sspi.h>
 
diff --git a/compat/pread.c b/compat/pread.c
index 978cac4..484e6d4 100644
--- a/compat/pread.c
+++ b/compat/pread.c
@@ -1,4 +1,5 @@
 #include "../git-compat-util.h"
+#include "../wrapper.h"
 
 ssize_t git_pread(int fd, void *buf, size_t count, off_t offset)
 {
diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index cce1d57..a4d1137 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -7,6 +7,9 @@
 
 #include "cache.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "path.h"
 #include "utf8.h"
 #include "precompose_utf8.h"
 
diff --git a/compat/simple-ipc/ipc-shared.c b/compat/simple-ipc/ipc-shared.c
index 1b9d359..e5e1dda 100644
--- a/compat/simple-ipc/ipc-shared.c
+++ b/compat/simple-ipc/ipc-shared.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "simple-ipc.h"
 #include "strbuf.h"
 #include "pkt-line.h"
diff --git a/compat/simple-ipc/ipc-unix-socket.c b/compat/simple-ipc/ipc-unix-socket.c
index 28a7928..b2f4f22 100644
--- a/compat/simple-ipc/ipc-unix-socket.c
+++ b/compat/simple-ipc/ipc-unix-socket.c
@@ -1,8 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
 #include "simple-ipc.h"
 #include "strbuf.h"
 #include "pkt-line.h"
 #include "thread-utils.h"
+#include "trace2.h"
 #include "unix-socket.h"
 #include "unix-stream-server.h"
 
diff --git a/compat/simple-ipc/ipc-win32.c b/compat/simple-ipc/ipc-win32.c
index 20ea7b6..6adce3c 100644
--- a/compat/simple-ipc/ipc-win32.c
+++ b/compat/simple-ipc/ipc-win32.c
@@ -1,8 +1,12 @@
 #include "cache.h"
+#include "abspath.h"
+#include "gettext.h"
 #include "simple-ipc.h"
 #include "strbuf.h"
 #include "pkt-line.h"
 #include "thread-utils.h"
+#include "trace.h"
+#include "trace2.h"
 #include "accctrl.h"
 #include "aclapi.h"
 
diff --git a/compat/terminal.c b/compat/terminal.c
index ea490a7..d87e321 100644
--- a/compat/terminal.c
+++ b/compat/terminal.c
@@ -1,10 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "compat/terminal.h"
+#include "gettext.h"
 #include "sigchain.h"
 #include "strbuf.h"
 #include "run-command.h"
 #include "string-list.h"
 #include "hashmap.h"
+#include "wrapper.h"
 
 #if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE)
 
diff --git a/compat/win32/trace2_win32_process_info.c b/compat/win32/trace2_win32_process_info.c
index a53fd92..a4e3376 100644
--- a/compat/win32/trace2_win32_process_info.c
+++ b/compat/win32/trace2_win32_process_info.c
@@ -1,5 +1,7 @@
 #include "../../cache.h"
 #include "../../json-writer.h"
+#include "../../repository.h"
+#include "../../trace2.h"
 #include "lazyload.h"
 #include <Psapi.h>
 #include <tlHelp32.h>
diff --git a/config.c b/config.c
index 00090a3..b79baf8 100644
--- a/config.c
+++ b/config.c
@@ -5,24 +5,39 @@
  * Copyright (C) Johannes Schindelin, 2005
  *
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "advice.h"
+#include "alloc.h"
 #include "date.h"
 #include "branch.h"
 #include "config.h"
+#include "convert.h"
 #include "environment.h"
+#include "gettext.h"
+#include "ident.h"
 #include "repository.h"
 #include "lockfile.h"
+#include "mailmap.h"
 #include "exec-cmd.h"
 #include "strbuf.h"
 #include "quote.h"
 #include "hashmap.h"
 #include "string-list.h"
+#include "object-name.h"
 #include "object-store.h"
+#include "pager.h"
 #include "utf8.h"
 #include "dir.h"
 #include "color.h"
+#include "replace-object.h"
 #include "refs.h"
+#include "setup.h"
+#include "trace2.h"
 #include "worktree.h"
+#include "ws.h"
+#include "wrapper.h"
+#include "write-or-die.h"
 
 struct config_source {
 	struct config_source *prev;
@@ -49,34 +64,79 @@ struct config_source {
 	int (*do_ungetc)(int c, struct config_source *conf);
 	long (*do_ftell)(struct config_source *c);
 };
+#define CONFIG_SOURCE_INIT { 0 }
 
+struct config_reader {
+	/*
+	 * These members record the "current" config source, which can be
+	 * accessed by parsing callbacks.
+	 *
+	 * The "source" variable will be non-NULL only when we are actually
+	 * parsing a real config source (file, blob, cmdline, etc).
+	 *
+	 * The "config_kvi" variable will be non-NULL only when we are feeding
+	 * cached config from a configset into a callback.
+	 *
+	 * They cannot be non-NULL at the same time. If they are both NULL, then
+	 * we aren't parsing anything (and depending on the function looking at
+	 * the variables, it's either a bug for it to be called in the first
+	 * place, or it's a function which can be reused for non-config
+	 * purposes, and should fall back to some sane behavior).
+	 */
+	struct config_source *source;
+	struct key_value_info *config_kvi;
+	/*
+	 * The "scope" of the current config source being parsed (repo, global,
+	 * etc). Like "source", this is only set when parsing a config source.
+	 * It's not part of "source" because it transcends a single file (i.e.,
+	 * a file included from .git/config is still in "repo" scope).
+	 *
+	 * When iterating through a configset, the equivalent value is
+	 * "config_kvi.scope" (see above).
+	 */
+	enum config_scope parsing_scope;
+};
 /*
- * These variables record the "current" config source, which
- * can be accessed by parsing callbacks.
- *
- * The "cf" variable will be non-NULL only when we are actually parsing a real
- * config source (file, blob, cmdline, etc).
- *
- * The "current_config_kvi" variable will be non-NULL only when we are feeding
- * cached config from a configset into a callback.
- *
- * They should generally never be non-NULL at the same time. If they are both
- * NULL, then we aren't parsing anything (and depending on the function looking
- * at the variables, it's either a bug for it to be called in the first place,
- * or it's a function which can be reused for non-config purposes, and should
- * fall back to some sane behavior).
+ * Where possible, prefer to accept "struct config_reader" as an arg than to use
+ * "the_reader". "the_reader" should only be used if that is infeasible, e.g. in
+ * a public function.
  */
-static struct config_source *cf;
-static struct key_value_info *current_config_kvi;
+static struct config_reader the_reader;
 
-/*
- * Similar to the variables above, this gives access to the "scope" of the
- * current value (repo, global, etc). For cached values, it can be found via
- * the current_config_kvi as above. During parsing, the current value can be
- * found in this variable. It's not part of "cf" because it transcends a single
- * file (i.e., a file included from .git/config is still in "repo" scope).
- */
-static enum config_scope current_parsing_scope;
+static inline void config_reader_push_source(struct config_reader *reader,
+					     struct config_source *top)
+{
+	if (reader->config_kvi)
+		BUG("source should not be set while iterating a config set");
+	top->prev = reader->source;
+	reader->source = top;
+}
+
+static inline struct config_source *config_reader_pop_source(struct config_reader *reader)
+{
+	struct config_source *ret;
+	if (!reader->source)
+		BUG("tried to pop config source, but we weren't reading config");
+	ret = reader->source;
+	reader->source = reader->source->prev;
+	return ret;
+}
+
+static inline void config_reader_set_kvi(struct config_reader *reader,
+					 struct key_value_info *kvi)
+{
+	if (kvi && (reader->source || reader->parsing_scope))
+		BUG("kvi should not be set while parsing a config source");
+	reader->config_kvi = kvi;
+}
+
+static inline void config_reader_set_scope(struct config_reader *reader,
+					   enum config_scope scope)
+{
+	if (scope && reader->config_kvi)
+		BUG("scope should only be set when iterating through a config source");
+	reader->parsing_scope = scope;
+}
 
 static int pack_compression_seen;
 static int zlib_compression_seen;
@@ -139,6 +199,7 @@ struct config_include_data {
 	void *data;
 	const struct config_options *opts;
 	struct git_config_source *config_source;
+	struct config_reader *config_reader;
 
 	/*
 	 * All remote URLs discovered when reading all config files.
@@ -156,7 +217,8 @@ static const char include_depth_advice[] = N_(
 "from\n"
 "	%s\n"
 "This might be due to circular includes.");
-static int handle_path_include(const char *path, struct config_include_data *inc)
+static int handle_path_include(struct config_source *cs, const char *path,
+			       struct config_include_data *inc)
 {
 	int ret = 0;
 	struct strbuf buf = STRBUF_INIT;
@@ -177,14 +239,14 @@ static int handle_path_include(const char *path, struct config_include_data *inc
 	if (!is_absolute_path(path)) {
 		char *slash;
 
-		if (!cf || !cf->path) {
+		if (!cs || !cs->path) {
 			ret = error(_("relative config includes must come from files"));
 			goto cleanup;
 		}
 
-		slash = find_last_dir_sep(cf->path);
+		slash = find_last_dir_sep(cs->path);
 		if (slash)
-			strbuf_add(&buf, cf->path, slash - cf->path + 1);
+			strbuf_add(&buf, cs->path, slash - cs->path + 1);
 		strbuf_addstr(&buf, path);
 		path = buf.buf;
 	}
@@ -192,8 +254,8 @@ static int handle_path_include(const char *path, struct config_include_data *inc
 	if (!access_or_die(path, R_OK, 0)) {
 		if (++inc->depth > MAX_INCLUDE_DEPTH)
 			die(_(include_depth_advice), MAX_INCLUDE_DEPTH, path,
-			    !cf ? "<unknown>" :
-			    cf->name ? cf->name :
+			    !cs ? "<unknown>" :
+			    cs->name ? cs->name :
 			    "the command line");
 		ret = git_config_from_file(git_config_include, path, inc);
 		inc->depth--;
@@ -210,7 +272,8 @@ static void add_trailing_starstar_for_dir(struct strbuf *pat)
 		strbuf_addstr(pat, "**");
 }
 
-static int prepare_include_condition_pattern(struct strbuf *pat)
+static int prepare_include_condition_pattern(struct config_source *cs,
+					     struct strbuf *pat)
 {
 	struct strbuf path = STRBUF_INIT;
 	char *expanded;
@@ -226,11 +289,11 @@ static int prepare_include_condition_pattern(struct strbuf *pat)
 	if (pat->buf[0] == '.' && is_dir_sep(pat->buf[1])) {
 		const char *slash;
 
-		if (!cf || !cf->path)
+		if (!cs || !cs->path)
 			return error(_("relative config include "
 				       "conditionals must come from files"));
 
-		strbuf_realpath(&path, cf->path, 1);
+		strbuf_realpath(&path, cs->path, 1);
 		slash = find_last_dir_sep(path.buf);
 		if (!slash)
 			BUG("how is this possible?");
@@ -245,7 +308,8 @@ static int prepare_include_condition_pattern(struct strbuf *pat)
 	return prefix;
 }
 
-static int include_by_gitdir(const struct config_options *opts,
+static int include_by_gitdir(struct config_source *cs,
+			     const struct config_options *opts,
 			     const char *cond, size_t cond_len, int icase)
 {
 	struct strbuf text = STRBUF_INIT;
@@ -261,7 +325,7 @@ static int include_by_gitdir(const struct config_options *opts,
 
 	strbuf_realpath(&text, git_dir, 1);
 	strbuf_add(&pattern, cond, cond_len);
-	prefix = prepare_include_condition_pattern(&pattern);
+	prefix = prepare_include_condition_pattern(cs, &pattern);
 
 again:
 	if (prefix < 0)
@@ -342,24 +406,18 @@ static void populate_remote_urls(struct config_include_data *inc)
 {
 	struct config_options opts;
 
-	struct config_source *store_cf = cf;
-	struct key_value_info *store_kvi = current_config_kvi;
-	enum config_scope store_scope = current_parsing_scope;
+	enum config_scope store_scope = inc->config_reader->parsing_scope;
 
 	opts = *inc->opts;
 	opts.unconditional_remote_url = 1;
 
-	cf = NULL;
-	current_config_kvi = NULL;
-	current_parsing_scope = 0;
+	config_reader_set_scope(inc->config_reader, 0);
 
 	inc->remote_urls = xmalloc(sizeof(*inc->remote_urls));
 	string_list_init_dup(inc->remote_urls);
 	config_with_options(add_remote_url, inc->remote_urls, inc->config_source, &opts);
 
-	cf = store_cf;
-	current_config_kvi = store_kvi;
-	current_parsing_scope = store_scope;
+	config_reader_set_scope(inc->config_reader, store_scope);
 }
 
 static int forbid_remote_url(const char *var, const char *value UNUSED,
@@ -406,15 +464,16 @@ static int include_by_remote_url(struct config_include_data *inc,
 					     inc->remote_urls);
 }
 
-static int include_condition_is_true(struct config_include_data *inc,
+static int include_condition_is_true(struct config_source *cs,
+				     struct config_include_data *inc,
 				     const char *cond, size_t cond_len)
 {
 	const struct config_options *opts = inc->opts;
 
 	if (skip_prefix_mem(cond, cond_len, "gitdir:", &cond, &cond_len))
-		return include_by_gitdir(opts, cond, cond_len, 0);
+		return include_by_gitdir(cs, opts, cond, cond_len, 0);
 	else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len))
-		return include_by_gitdir(opts, cond, cond_len, 1);
+		return include_by_gitdir(cs, opts, cond, cond_len, 1);
 	else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len))
 		return include_by_branch(cond, cond_len);
 	else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
@@ -428,6 +487,7 @@ static int include_condition_is_true(struct config_include_data *inc,
 static int git_config_include(const char *var, const char *value, void *data)
 {
 	struct config_include_data *inc = data;
+	struct config_source *cs = inc->config_reader->source;
 	const char *cond, *key;
 	size_t cond_len;
 	int ret;
@@ -441,16 +501,16 @@ static int git_config_include(const char *var, const char *value, void *data)
 		return ret;
 
 	if (!strcmp(var, "include.path"))
-		ret = handle_path_include(value, inc);
+		ret = handle_path_include(cs, value, inc);
 
 	if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) &&
-	    cond && include_condition_is_true(inc, cond, cond_len) &&
+	    cond && include_condition_is_true(cs, inc, cond, cond_len) &&
 	    !strcmp(key, "path")) {
 		config_fn_t old_fn = inc->fn;
 
 		if (inc->opts->unconditional_remote_url)
 			inc->fn = forbid_remote_url;
-		ret = handle_path_include(value, inc);
+		ret = handle_path_include(cs, value, inc);
 		inc->fn = old_fn;
 	}
 
@@ -710,12 +770,10 @@ int git_config_from_parameters(config_fn_t fn, void *data)
 	struct strvec to_free = STRVEC_INIT;
 	int ret = 0;
 	char *envw = NULL;
-	struct config_source source;
+	struct config_source source = CONFIG_SOURCE_INIT;
 
-	memset(&source, 0, sizeof(source));
-	source.prev = cf;
 	source.origin_type = CONFIG_ORIGIN_CMDLINE;
-	cf = &source;
+	config_reader_push_source(&the_reader, &source);
 
 	env = getenv(CONFIG_COUNT_ENVIRONMENT);
 	if (env) {
@@ -773,25 +831,25 @@ int git_config_from_parameters(config_fn_t fn, void *data)
 	strbuf_release(&envvar);
 	strvec_clear(&to_free);
 	free(envw);
-	cf = source.prev;
+	config_reader_pop_source(&the_reader);
 	return ret;
 }
 
-static int get_next_char(void)
+static int get_next_char(struct config_source *cs)
 {
-	int c = cf->do_fgetc(cf);
+	int c = cs->do_fgetc(cs);
 
 	if (c == '\r') {
 		/* DOS like systems */
-		c = cf->do_fgetc(cf);
+		c = cs->do_fgetc(cs);
 		if (c != '\n') {
 			if (c != EOF)
-				cf->do_ungetc(c, cf);
+				cs->do_ungetc(c, cs);
 			c = '\r';
 		}
 	}
 
-	if (c != EOF && ++cf->total_len > INT_MAX) {
+	if (c != EOF && ++cs->total_len > INT_MAX) {
 		/*
 		 * This is an absurdly long config file; refuse to parse
 		 * further in order to protect downstream code from integer
@@ -799,38 +857,38 @@ static int get_next_char(void)
 		 * but we can mark EOF and put trash in the return value,
 		 * which will trigger a parse error.
 		 */
-		cf->eof = 1;
+		cs->eof = 1;
 		return 0;
 	}
 
 	if (c == '\n')
-		cf->linenr++;
+		cs->linenr++;
 	if (c == EOF) {
-		cf->eof = 1;
-		cf->linenr++;
+		cs->eof = 1;
+		cs->linenr++;
 		c = '\n';
 	}
 	return c;
 }
 
-static char *parse_value(void)
+static char *parse_value(struct config_source *cs)
 {
 	int quote = 0, comment = 0, space = 0;
 
-	strbuf_reset(&cf->value);
+	strbuf_reset(&cs->value);
 	for (;;) {
-		int c = get_next_char();
+		int c = get_next_char(cs);
 		if (c == '\n') {
 			if (quote) {
-				cf->linenr--;
+				cs->linenr--;
 				return NULL;
 			}
-			return cf->value.buf;
+			return cs->value.buf;
 		}
 		if (comment)
 			continue;
 		if (isspace(c) && !quote) {
-			if (cf->value.len)
+			if (cs->value.len)
 				space++;
 			continue;
 		}
@@ -841,9 +899,9 @@ static char *parse_value(void)
 			}
 		}
 		for (; space; space--)
-			strbuf_addch(&cf->value, ' ');
+			strbuf_addch(&cs->value, ' ');
 		if (c == '\\') {
-			c = get_next_char();
+			c = get_next_char(cs);
 			switch (c) {
 			case '\n':
 				continue;
@@ -863,18 +921,19 @@ static char *parse_value(void)
 			default:
 				return NULL;
 			}
-			strbuf_addch(&cf->value, c);
+			strbuf_addch(&cs->value, c);
 			continue;
 		}
 		if (c == '"') {
 			quote = 1-quote;
 			continue;
 		}
-		strbuf_addch(&cf->value, c);
+		strbuf_addch(&cs->value, c);
 	}
 }
 
-static int get_value(config_fn_t fn, void *data, struct strbuf *name)
+static int get_value(struct config_source *cs, config_fn_t fn, void *data,
+		     struct strbuf *name)
 {
 	int c;
 	char *value;
@@ -882,8 +941,8 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name)
 
 	/* Get the full name */
 	for (;;) {
-		c = get_next_char();
-		if (cf->eof)
+		c = get_next_char(cs);
+		if (cs->eof)
 			break;
 		if (!iskeychar(c))
 			break;
@@ -891,13 +950,13 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name)
 	}
 
 	while (c == ' ' || c == '\t')
-		c = get_next_char();
+		c = get_next_char(cs);
 
 	value = NULL;
 	if (c != '\n') {
 		if (c != '=')
 			return -1;
-		value = parse_value();
+		value = parse_value(cs);
 		if (!value)
 			return -1;
 	}
@@ -906,20 +965,21 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name)
 	 * the line we just parsed during the call to fn to get
 	 * accurate line number in error messages.
 	 */
-	cf->linenr--;
+	cs->linenr--;
 	ret = fn(name->buf, value, data);
 	if (ret >= 0)
-		cf->linenr++;
+		cs->linenr++;
 	return ret;
 }
 
-static int get_extended_base_var(struct strbuf *name, int c)
+static int get_extended_base_var(struct config_source *cs, struct strbuf *name,
+				 int c)
 {
-	cf->subsection_case_sensitive = 0;
+	cs->subsection_case_sensitive = 0;
 	do {
 		if (c == '\n')
 			goto error_incomplete_line;
-		c = get_next_char();
+		c = get_next_char(cs);
 	} while (isspace(c));
 
 	/* We require the format to be '[base "extension"]' */
@@ -928,13 +988,13 @@ static int get_extended_base_var(struct strbuf *name, int c)
 	strbuf_addch(name, '.');
 
 	for (;;) {
-		int c = get_next_char();
+		int c = get_next_char(cs);
 		if (c == '\n')
 			goto error_incomplete_line;
 		if (c == '"')
 			break;
 		if (c == '\\') {
-			c = get_next_char();
+			c = get_next_char(cs);
 			if (c == '\n')
 				goto error_incomplete_line;
 		}
@@ -942,25 +1002,25 @@ static int get_extended_base_var(struct strbuf *name, int c)
 	}
 
 	/* Final ']' */
-	if (get_next_char() != ']')
+	if (get_next_char(cs) != ']')
 		return -1;
 	return 0;
 error_incomplete_line:
-	cf->linenr--;
+	cs->linenr--;
 	return -1;
 }
 
-static int get_base_var(struct strbuf *name)
+static int get_base_var(struct config_source *cs, struct strbuf *name)
 {
-	cf->subsection_case_sensitive = 1;
+	cs->subsection_case_sensitive = 1;
 	for (;;) {
-		int c = get_next_char();
-		if (cf->eof)
+		int c = get_next_char(cs);
+		if (cs->eof)
 			return -1;
 		if (c == ']')
 			return 0;
 		if (isspace(c))
-			return get_extended_base_var(name, c);
+			return get_extended_base_var(cs, name, c);
 		if (!iskeychar(c) && c != '.')
 			return -1;
 		strbuf_addch(name, tolower(c));
@@ -973,7 +1033,8 @@ struct parse_event_data {
 	const struct config_options *opts;
 };
 
-static int do_event(enum config_event_t type, struct parse_event_data *data)
+static int do_event(struct config_source *cs, enum config_event_t type,
+		    struct parse_event_data *data)
 {
 	size_t offset;
 
@@ -984,7 +1045,7 @@ static int do_event(enum config_event_t type, struct parse_event_data *data)
 	    data->previous_type == type)
 		return 0;
 
-	offset = cf->do_ftell(cf);
+	offset = cs->do_ftell(cs);
 	/*
 	 * At EOF, the parser always "inserts" an extra '\n', therefore
 	 * the end offset of the event is the current file position, otherwise
@@ -1004,12 +1065,12 @@ static int do_event(enum config_event_t type, struct parse_event_data *data)
 	return 0;
 }
 
-static int git_parse_source(config_fn_t fn, void *data,
-			    const struct config_options *opts)
+static int git_parse_source(struct config_source *cs, config_fn_t fn,
+			    void *data, const struct config_options *opts)
 {
 	int comment = 0;
 	size_t baselen = 0;
-	struct strbuf *var = &cf->var;
+	struct strbuf *var = &cs->var;
 	int error_return = 0;
 	char *error_msg = NULL;
 
@@ -1024,7 +1085,7 @@ static int git_parse_source(config_fn_t fn, void *data,
 	for (;;) {
 		int c;
 
-		c = get_next_char();
+		c = get_next_char(cs);
 		if (bomptr && *bomptr) {
 			/* We are at the file beginning; skip UTF8-encoded BOM
 			 * if present. Sane editors won't put this in on their
@@ -1041,12 +1102,12 @@ static int git_parse_source(config_fn_t fn, void *data,
 			}
 		}
 		if (c == '\n') {
-			if (cf->eof) {
-				if (do_event(CONFIG_EVENT_EOF, &event_data) < 0)
+			if (cs->eof) {
+				if (do_event(cs, CONFIG_EVENT_EOF, &event_data) < 0)
 					return -1;
 				return 0;
 			}
-			if (do_event(CONFIG_EVENT_WHITESPACE, &event_data) < 0)
+			if (do_event(cs, CONFIG_EVENT_WHITESPACE, &event_data) < 0)
 				return -1;
 			comment = 0;
 			continue;
@@ -1054,23 +1115,23 @@ static int git_parse_source(config_fn_t fn, void *data,
 		if (comment)
 			continue;
 		if (isspace(c)) {
-			if (do_event(CONFIG_EVENT_WHITESPACE, &event_data) < 0)
+			if (do_event(cs, CONFIG_EVENT_WHITESPACE, &event_data) < 0)
 					return -1;
 			continue;
 		}
 		if (c == '#' || c == ';') {
-			if (do_event(CONFIG_EVENT_COMMENT, &event_data) < 0)
+			if (do_event(cs, CONFIG_EVENT_COMMENT, &event_data) < 0)
 					return -1;
 			comment = 1;
 			continue;
 		}
 		if (c == '[') {
-			if (do_event(CONFIG_EVENT_SECTION, &event_data) < 0)
+			if (do_event(cs, CONFIG_EVENT_SECTION, &event_data) < 0)
 					return -1;
 
 			/* Reset prior to determining a new stem */
 			strbuf_reset(var);
-			if (get_base_var(var) < 0 || var->len < 1)
+			if (get_base_var(cs, var) < 0 || var->len < 1)
 				break;
 			strbuf_addch(var, '.');
 			baselen = var->len;
@@ -1079,7 +1140,7 @@ static int git_parse_source(config_fn_t fn, void *data,
 		if (!isalpha(c))
 			break;
 
-		if (do_event(CONFIG_EVENT_ENTRY, &event_data) < 0)
+		if (do_event(cs, CONFIG_EVENT_ENTRY, &event_data) < 0)
 			return -1;
 
 		/*
@@ -1089,42 +1150,42 @@ static int git_parse_source(config_fn_t fn, void *data,
 		 */
 		strbuf_setlen(var, baselen);
 		strbuf_addch(var, tolower(c));
-		if (get_value(fn, data, var) < 0)
+		if (get_value(cs, fn, data, var) < 0)
 			break;
 	}
 
-	if (do_event(CONFIG_EVENT_ERROR, &event_data) < 0)
+	if (do_event(cs, CONFIG_EVENT_ERROR, &event_data) < 0)
 		return -1;
 
-	switch (cf->origin_type) {
+	switch (cs->origin_type) {
 	case CONFIG_ORIGIN_BLOB:
 		error_msg = xstrfmt(_("bad config line %d in blob %s"),
-				      cf->linenr, cf->name);
+				      cs->linenr, cs->name);
 		break;
 	case CONFIG_ORIGIN_FILE:
 		error_msg = xstrfmt(_("bad config line %d in file %s"),
-				      cf->linenr, cf->name);
+				      cs->linenr, cs->name);
 		break;
 	case CONFIG_ORIGIN_STDIN:
 		error_msg = xstrfmt(_("bad config line %d in standard input"),
-				      cf->linenr);
+				      cs->linenr);
 		break;
 	case CONFIG_ORIGIN_SUBMODULE_BLOB:
 		error_msg = xstrfmt(_("bad config line %d in submodule-blob %s"),
-				       cf->linenr, cf->name);
+				       cs->linenr, cs->name);
 		break;
 	case CONFIG_ORIGIN_CMDLINE:
 		error_msg = xstrfmt(_("bad config line %d in command line %s"),
-				       cf->linenr, cf->name);
+				       cs->linenr, cs->name);
 		break;
 	default:
 		error_msg = xstrfmt(_("bad config line %d in %s"),
-				      cf->linenr, cf->name);
+				      cs->linenr, cs->name);
 	}
 
 	switch (opts && opts->error_action ?
 		opts->error_action :
-		cf->default_error_action) {
+		cs->default_error_action) {
 	case CONFIG_ERROR_DIE:
 		die("%s", error_msg);
 		break;
@@ -1265,38 +1326,48 @@ int git_parse_ssize_t(const char *value, ssize_t *ret)
 	return 1;
 }
 
+static int reader_config_name(struct config_reader *reader, const char **out);
+static int reader_origin_type(struct config_reader *reader,
+			      enum config_origin_type *type);
 NORETURN
-static void die_bad_number(const char *name, const char *value)
+static void die_bad_number(struct config_reader *reader, const char *name,
+			   const char *value)
 {
 	const char *error_type = (errno == ERANGE) ?
 		N_("out of range") : N_("invalid unit");
 	const char *bad_numeric = N_("bad numeric config value '%s' for '%s': %s");
+	const char *config_name = NULL;
+	enum config_origin_type config_origin = CONFIG_ORIGIN_UNKNOWN;
 
 	if (!value)
 		value = "";
 
-	if (!(cf && cf->name))
+	/* Ignoring the return value is okay since we handle missing values. */
+	reader_config_name(reader, &config_name);
+	reader_origin_type(reader, &config_origin);
+
+	if (!config_name)
 		die(_(bad_numeric), value, name, _(error_type));
 
-	switch (cf->origin_type) {
+	switch (config_origin) {
 	case CONFIG_ORIGIN_BLOB:
 		die(_("bad numeric config value '%s' for '%s' in blob %s: %s"),
-		    value, name, cf->name, _(error_type));
+		    value, name, config_name, _(error_type));
 	case CONFIG_ORIGIN_FILE:
 		die(_("bad numeric config value '%s' for '%s' in file %s: %s"),
-		    value, name, cf->name, _(error_type));
+		    value, name, config_name, _(error_type));
 	case CONFIG_ORIGIN_STDIN:
 		die(_("bad numeric config value '%s' for '%s' in standard input: %s"),
 		    value, name, _(error_type));
 	case CONFIG_ORIGIN_SUBMODULE_BLOB:
 		die(_("bad numeric config value '%s' for '%s' in submodule-blob %s: %s"),
-		    value, name, cf->name, _(error_type));
+		    value, name, config_name, _(error_type));
 	case CONFIG_ORIGIN_CMDLINE:
 		die(_("bad numeric config value '%s' for '%s' in command line %s: %s"),
-		    value, name, cf->name, _(error_type));
+		    value, name, config_name, _(error_type));
 	default:
 		die(_("bad numeric config value '%s' for '%s' in %s: %s"),
-		    value, name, cf->name, _(error_type));
+		    value, name, config_name, _(error_type));
 	}
 }
 
@@ -1304,7 +1375,7 @@ int git_config_int(const char *name, const char *value)
 {
 	int ret;
 	if (!git_parse_int(value, &ret))
-		die_bad_number(name, value);
+		die_bad_number(&the_reader, name, value);
 	return ret;
 }
 
@@ -1312,7 +1383,7 @@ int64_t git_config_int64(const char *name, const char *value)
 {
 	int64_t ret;
 	if (!git_parse_int64(value, &ret))
-		die_bad_number(name, value);
+		die_bad_number(&the_reader, name, value);
 	return ret;
 }
 
@@ -1320,7 +1391,7 @@ unsigned long git_config_ulong(const char *name, const char *value)
 {
 	unsigned long ret;
 	if (!git_parse_ulong(value, &ret))
-		die_bad_number(name, value);
+		die_bad_number(&the_reader, name, value);
 	return ret;
 }
 
@@ -1328,7 +1399,7 @@ ssize_t git_config_ssize_t(const char *name, const char *value)
 {
 	ssize_t ret;
 	if (!git_parse_ssize_t(value, &ret))
-		die_bad_number(name, value);
+		die_bad_number(&the_reader, name, value);
 	return ret;
 }
 
@@ -1683,7 +1754,7 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
 			comment_line_char = value[0];
 			auto_comment_line_char = 0;
 		} else
-			return error(_("core.commentChar should only be one character"));
+			return error(_("core.commentChar should only be one ASCII character"));
 		return 0;
 	}
 
@@ -1934,36 +2005,37 @@ int git_default_config(const char *var, const char *value, void *cb)
  * fgetc, ungetc, ftell of top need to be initialized before calling
  * this function.
  */
-static int do_config_from(struct config_source *top, config_fn_t fn, void *data,
+static int do_config_from(struct config_reader *reader,
+			  struct config_source *top, config_fn_t fn, void *data,
 			  const struct config_options *opts)
 {
 	int ret;
 
 	/* push config-file parsing state stack */
-	top->prev = cf;
 	top->linenr = 1;
 	top->eof = 0;
 	top->total_len = 0;
 	strbuf_init(&top->value, 1024);
 	strbuf_init(&top->var, 1024);
-	cf = top;
+	config_reader_push_source(reader, top);
 
-	ret = git_parse_source(fn, data, opts);
+	ret = git_parse_source(top, fn, data, opts);
 
 	/* pop config-file parsing state stack */
 	strbuf_release(&top->value);
 	strbuf_release(&top->var);
-	cf = top->prev;
+	config_reader_pop_source(reader);
 
 	return ret;
 }
 
-static int do_config_from_file(config_fn_t fn,
-		const enum config_origin_type origin_type,
-		const char *name, const char *path, FILE *f,
-		void *data, const struct config_options *opts)
+static int do_config_from_file(struct config_reader *reader,
+			       config_fn_t fn,
+			       const enum config_origin_type origin_type,
+			       const char *name, const char *path, FILE *f,
+			       void *data, const struct config_options *opts)
 {
-	struct config_source top;
+	struct config_source top = CONFIG_SOURCE_INIT;
 	int ret;
 
 	top.u.file = f;
@@ -1976,15 +2048,15 @@ static int do_config_from_file(config_fn_t fn,
 	top.do_ftell = config_file_ftell;
 
 	flockfile(f);
-	ret = do_config_from(&top, fn, data, opts);
+	ret = do_config_from(reader, &top, fn, data, opts);
 	funlockfile(f);
 	return ret;
 }
 
 static int git_config_from_stdin(config_fn_t fn, void *data)
 {
-	return do_config_from_file(fn, CONFIG_ORIGIN_STDIN, "", NULL, stdin,
-				   data, NULL);
+	return do_config_from_file(&the_reader, fn, CONFIG_ORIGIN_STDIN, "",
+				   NULL, stdin, data, NULL);
 }
 
 int git_config_from_file_with_options(config_fn_t fn, const char *filename,
@@ -1998,8 +2070,8 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename,
 		BUG("filename cannot be NULL");
 	f = fopen_or_warn(filename, "r");
 	if (f) {
-		ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename,
-					  filename, f, data, opts);
+		ret = do_config_from_file(&the_reader, fn, CONFIG_ORIGIN_FILE,
+					  filename, filename, f, data, opts);
 		fclose(f);
 	}
 	return ret;
@@ -2015,7 +2087,7 @@ int git_config_from_mem(config_fn_t fn,
 			const char *name, const char *buf, size_t len,
 			void *data, const struct config_options *opts)
 {
-	struct config_source top;
+	struct config_source top = CONFIG_SOURCE_INIT;
 
 	top.u.buf.buf = buf;
 	top.u.buf.len = len;
@@ -2028,7 +2100,7 @@ int git_config_from_mem(config_fn_t fn,
 	top.do_ungetc = config_buf_ungetc;
 	top.do_ftell = config_buf_ftell;
 
-	return do_config_from(&top, fn, data, opts);
+	return do_config_from(&the_reader, &top, fn, data, opts);
 }
 
 int git_config_from_blob_oid(config_fn_t fn,
@@ -2119,7 +2191,8 @@ int git_config_system(void)
 	return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
 }
 
-static int do_git_config_sequence(const struct config_options *opts,
+static int do_git_config_sequence(struct config_reader *reader,
+				  const struct config_options *opts,
 				  config_fn_t fn, void *data)
 {
 	int ret = 0;
@@ -2127,7 +2200,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	char *xdg_config = NULL;
 	char *user_config = NULL;
 	char *repo_config;
-	enum config_scope prev_parsing_scope = current_parsing_scope;
+	enum config_scope prev_parsing_scope = reader->parsing_scope;
 
 	if (opts->commondir)
 		repo_config = mkpathdup("%s/config", opts->commondir);
@@ -2136,13 +2209,13 @@ static int do_git_config_sequence(const struct config_options *opts,
 	else
 		repo_config = NULL;
 
-	current_parsing_scope = CONFIG_SCOPE_SYSTEM;
+	config_reader_set_scope(reader, CONFIG_SCOPE_SYSTEM);
 	if (git_config_system() && system_config &&
 	    !access_or_die(system_config, R_OK,
 			   opts->system_gently ? ACCESS_EACCES_OK : 0))
 		ret += git_config_from_file(fn, system_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_GLOBAL;
+	config_reader_set_scope(reader, CONFIG_SCOPE_GLOBAL);
 	git_global_config(&user_config, &xdg_config);
 
 	if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK))
@@ -2151,12 +2224,12 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
 		ret += git_config_from_file(fn, user_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_LOCAL;
+	config_reader_set_scope(reader, CONFIG_SCOPE_LOCAL);
 	if (!opts->ignore_repo && repo_config &&
 	    !access_or_die(repo_config, R_OK, 0))
 		ret += git_config_from_file(fn, repo_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
+	config_reader_set_scope(reader, CONFIG_SCOPE_WORKTREE);
 	if (!opts->ignore_worktree && repository_format_worktree_config) {
 		char *path = git_pathdup("config.worktree");
 		if (!access_or_die(path, R_OK, 0))
@@ -2164,11 +2237,11 @@ static int do_git_config_sequence(const struct config_options *opts,
 		free(path);
 	}
 
-	current_parsing_scope = CONFIG_SCOPE_COMMAND;
+	config_reader_set_scope(reader, CONFIG_SCOPE_COMMAND);
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
-	current_parsing_scope = prev_parsing_scope;
+	config_reader_set_scope(reader, prev_parsing_scope);
 	free(system_config);
 	free(xdg_config);
 	free(user_config);
@@ -2181,6 +2254,7 @@ int config_with_options(config_fn_t fn, void *data,
 			const struct config_options *opts)
 {
 	struct config_include_data inc = CONFIG_INCLUDE_INIT;
+	enum config_scope prev_scope = the_reader.parsing_scope;
 	int ret;
 
 	if (opts->respect_includes) {
@@ -2188,12 +2262,13 @@ int config_with_options(config_fn_t fn, void *data,
 		inc.data = data;
 		inc.opts = opts;
 		inc.config_source = config_source;
+		inc.config_reader = &the_reader;
 		fn = git_config_include;
 		data = &inc;
 	}
 
 	if (config_source)
-		current_parsing_scope = config_source->scope;
+		config_reader_set_scope(&the_reader, config_source->scope);
 
 	/*
 	 * If we have a specific filename, use it. Otherwise, follow the
@@ -2209,36 +2284,38 @@ int config_with_options(config_fn_t fn, void *data,
 		ret = git_config_from_blob_ref(fn, repo, config_source->blob,
 						data);
 	} else {
-		ret = do_git_config_sequence(opts, fn, data);
+		ret = do_git_config_sequence(&the_reader, opts, fn, data);
 	}
 
 	if (inc.remote_urls) {
 		string_list_clear(inc.remote_urls, 0);
 		FREE_AND_NULL(inc.remote_urls);
 	}
+	config_reader_set_scope(&the_reader, prev_scope);
 	return ret;
 }
 
-static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
+static void configset_iter(struct config_reader *reader, struct config_set *set,
+			   config_fn_t fn, void *data)
 {
 	int i, value_index;
 	struct string_list *values;
 	struct config_set_element *entry;
-	struct configset_list *list = &cs->list;
+	struct configset_list *list = &set->list;
 
 	for (i = 0; i < list->nr; i++) {
 		entry = list->items[i].e;
 		value_index = list->items[i].value_index;
 		values = &entry->value_list;
 
-		current_config_kvi = values->items[value_index].util;
+		config_reader_set_kvi(reader, values->items[value_index].util);
 
 		if (fn(entry->key, values->items[value_index].string, data) < 0)
 			git_die_config_linenr(entry->key,
-					      current_config_kvi->filename,
-					      current_config_kvi->linenr);
+					      reader->config_kvi->filename,
+					      reader->config_kvi->linenr);
 
-		current_config_kvi = NULL;
+		config_reader_set_kvi(reader, NULL);
 	}
 }
 
@@ -2289,33 +2366,44 @@ void read_very_early_config(config_fn_t cb, void *data)
 	config_with_options(cb, data, NULL, &opts);
 }
 
-static struct config_set_element *configset_find_element(struct config_set *cs, const char *key)
+RESULT_MUST_BE_USED
+static int configset_find_element(struct config_set *set, const char *key,
+				  struct config_set_element **dest)
 {
 	struct config_set_element k;
 	struct config_set_element *found_entry;
 	char *normalized_key;
+	int ret;
+
 	/*
 	 * `key` may come from the user, so normalize it before using it
 	 * for querying entries from the hashmap.
 	 */
-	if (git_config_parse_key(key, &normalized_key, NULL))
-		return NULL;
+	ret = git_config_parse_key(key, &normalized_key, NULL);
+	if (ret)
+		return ret;
 
 	hashmap_entry_init(&k.ent, strhash(normalized_key));
 	k.key = normalized_key;
-	found_entry = hashmap_get_entry(&cs->config_hash, &k, ent, NULL);
+	found_entry = hashmap_get_entry(&set->config_hash, &k, ent, NULL);
 	free(normalized_key);
-	return found_entry;
+	*dest = found_entry;
+	return 0;
 }
 
-static int configset_add_value(struct config_set *cs, const char *key, const char *value)
+static int configset_add_value(struct config_reader *reader,
+			       struct config_set *set, const char *key,
+			       const char *value)
 {
 	struct config_set_element *e;
 	struct string_list_item *si;
 	struct configset_list_item *l_item;
 	struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
+	int ret;
 
-	e = configset_find_element(cs, key);
+	ret = configset_find_element(set, key, &e);
+	if (ret)
+		return ret;
 	/*
 	 * Since the keys are being fed by git_config*() callback mechanism, they
 	 * are already normalized. So simply add them without any further munging.
@@ -2325,28 +2413,28 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
 		hashmap_entry_init(&e->ent, strhash(key));
 		e->key = xstrdup(key);
 		string_list_init_dup(&e->value_list);
-		hashmap_add(&cs->config_hash, &e->ent);
+		hashmap_add(&set->config_hash, &e->ent);
 	}
 	si = string_list_append_nodup(&e->value_list, xstrdup_or_null(value));
 
-	ALLOC_GROW(cs->list.items, cs->list.nr + 1, cs->list.alloc);
-	l_item = &cs->list.items[cs->list.nr++];
+	ALLOC_GROW(set->list.items, set->list.nr + 1, set->list.alloc);
+	l_item = &set->list.items[set->list.nr++];
 	l_item->e = e;
 	l_item->value_index = e->value_list.nr - 1;
 
-	if (!cf)
+	if (!reader->source)
 		BUG("configset_add_value has no source");
-	if (cf->name) {
-		kv_info->filename = strintern(cf->name);
-		kv_info->linenr = cf->linenr;
-		kv_info->origin_type = cf->origin_type;
+	if (reader->source->name) {
+		kv_info->filename = strintern(reader->source->name);
+		kv_info->linenr = reader->source->linenr;
+		kv_info->origin_type = reader->source->origin_type;
 	} else {
 		/* for values read from `git_config_from_parameters()` */
 		kv_info->filename = NULL;
 		kv_info->linenr = -1;
 		kv_info->origin_type = CONFIG_ORIGIN_CMDLINE;
 	}
-	kv_info->scope = current_parsing_scope;
+	kv_info->scope = reader->parsing_scope;
 	si->util = kv_info;
 
 	return 0;
@@ -2365,84 +2453,134 @@ static int config_set_element_cmp(const void *cmp_data UNUSED,
 	return strcmp(e1->key, e2->key);
 }
 
-void git_configset_init(struct config_set *cs)
+void git_configset_init(struct config_set *set)
 {
-	hashmap_init(&cs->config_hash, config_set_element_cmp, NULL, 0);
-	cs->hash_initialized = 1;
-	cs->list.nr = 0;
-	cs->list.alloc = 0;
-	cs->list.items = NULL;
+	hashmap_init(&set->config_hash, config_set_element_cmp, NULL, 0);
+	set->hash_initialized = 1;
+	set->list.nr = 0;
+	set->list.alloc = 0;
+	set->list.items = NULL;
 }
 
-void git_configset_clear(struct config_set *cs)
+void git_configset_clear(struct config_set *set)
 {
 	struct config_set_element *entry;
 	struct hashmap_iter iter;
-	if (!cs->hash_initialized)
+	if (!set->hash_initialized)
 		return;
 
-	hashmap_for_each_entry(&cs->config_hash, &iter, entry,
+	hashmap_for_each_entry(&set->config_hash, &iter, entry,
 				ent /* member name */) {
 		free(entry->key);
 		string_list_clear(&entry->value_list, 1);
 	}
-	hashmap_clear_and_free(&cs->config_hash, struct config_set_element, ent);
-	cs->hash_initialized = 0;
-	free(cs->list.items);
-	cs->list.nr = 0;
-	cs->list.alloc = 0;
-	cs->list.items = NULL;
+	hashmap_clear_and_free(&set->config_hash, struct config_set_element, ent);
+	set->hash_initialized = 0;
+	free(set->list.items);
+	set->list.nr = 0;
+	set->list.alloc = 0;
+	set->list.items = NULL;
 }
 
+struct configset_add_data {
+	struct config_set *config_set;
+	struct config_reader *config_reader;
+};
+#define CONFIGSET_ADD_INIT { 0 }
+
 static int config_set_callback(const char *key, const char *value, void *cb)
 {
-	struct config_set *cs = cb;
-	configset_add_value(cs, key, value);
+	struct configset_add_data *data = cb;
+	configset_add_value(data->config_reader, data->config_set, key, value);
 	return 0;
 }
 
-int git_configset_add_file(struct config_set *cs, const char *filename)
+int git_configset_add_file(struct config_set *set, const char *filename)
 {
-	return git_config_from_file(config_set_callback, filename, cs);
+	struct configset_add_data data = CONFIGSET_ADD_INIT;
+	data.config_reader = &the_reader;
+	data.config_set = set;
+	return git_config_from_file(config_set_callback, filename, &data);
 }
 
-int git_configset_get_value(struct config_set *cs, const char *key, const char **value)
+int git_configset_get_value(struct config_set *set, const char *key, const char **value)
 {
 	const struct string_list *values = NULL;
+	int ret;
+
 	/*
 	 * Follows "last one wins" semantic, i.e., if there are multiple matches for the
 	 * queried key in the files of the configset, the value returned will be the last
 	 * value in the value list for that key.
 	 */
-	values = git_configset_get_value_multi(cs, key);
+	if ((ret = git_configset_get_value_multi(set, key, &values)))
+		return ret;
 
-	if (!values)
-		return 1;
 	assert(values->nr > 0);
 	*value = values->items[values->nr - 1].string;
 	return 0;
 }
 
-const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key)
+int git_configset_get_value_multi(struct config_set *set, const char *key,
+				  const struct string_list **dest)
 {
-	struct config_set_element *e = configset_find_element(cs, key);
-	return e ? &e->value_list : NULL;
+	struct config_set_element *e;
+	int ret;
+
+	if ((ret = configset_find_element(set, key, &e)))
+		return ret;
+	else if (!e)
+		return 1;
+	*dest = &e->value_list;
+
+	return 0;
 }
 
-int git_configset_get_string(struct config_set *cs, const char *key, char **dest)
+static int check_multi_string(struct string_list_item *item, void *util)
+{
+	return item->string ? 0 : config_error_nonbool(util);
+}
+
+int git_configset_get_string_multi(struct config_set *cs, const char *key,
+				   const struct string_list **dest)
+{
+	int ret;
+
+	if ((ret = git_configset_get_value_multi(cs, key, dest)))
+		return ret;
+	if ((ret = for_each_string_list((struct string_list *)*dest,
+					check_multi_string, (void *)key)))
+		return ret;
+
+	return 0;
+}
+
+int git_configset_get(struct config_set *set, const char *key)
+{
+	struct config_set_element *e;
+	int ret;
+
+	if ((ret = configset_find_element(set, key, &e)))
+		return ret;
+	else if (!e)
+		return 1;
+	return 0;
+}
+
+int git_configset_get_string(struct config_set *set, const char *key, char **dest)
 {
 	const char *value;
-	if (!git_configset_get_value(cs, key, &value))
+	if (!git_configset_get_value(set, key, &value))
 		return git_config_string((const char **)dest, key, value);
 	else
 		return 1;
 }
 
-static int git_configset_get_string_tmp(struct config_set *cs, const char *key,
+static int git_configset_get_string_tmp(struct config_set *set, const char *key,
 					const char **dest)
 {
 	const char *value;
-	if (!git_configset_get_value(cs, key, &value)) {
+	if (!git_configset_get_value(set, key, &value)) {
 		if (!value)
 			return config_error_nonbool(key);
 		*dest = value;
@@ -2452,51 +2590,51 @@ static int git_configset_get_string_tmp(struct config_set *cs, const char *key,
 	}
 }
 
-int git_configset_get_int(struct config_set *cs, const char *key, int *dest)
+int git_configset_get_int(struct config_set *set, const char *key, int *dest)
 {
 	const char *value;
-	if (!git_configset_get_value(cs, key, &value)) {
+	if (!git_configset_get_value(set, key, &value)) {
 		*dest = git_config_int(key, value);
 		return 0;
 	} else
 		return 1;
 }
 
-int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest)
+int git_configset_get_ulong(struct config_set *set, const char *key, unsigned long *dest)
 {
 	const char *value;
-	if (!git_configset_get_value(cs, key, &value)) {
+	if (!git_configset_get_value(set, key, &value)) {
 		*dest = git_config_ulong(key, value);
 		return 0;
 	} else
 		return 1;
 }
 
-int git_configset_get_bool(struct config_set *cs, const char *key, int *dest)
+int git_configset_get_bool(struct config_set *set, const char *key, int *dest)
 {
 	const char *value;
-	if (!git_configset_get_value(cs, key, &value)) {
+	if (!git_configset_get_value(set, key, &value)) {
 		*dest = git_config_bool(key, value);
 		return 0;
 	} else
 		return 1;
 }
 
-int git_configset_get_bool_or_int(struct config_set *cs, const char *key,
+int git_configset_get_bool_or_int(struct config_set *set, const char *key,
 				int *is_bool, int *dest)
 {
 	const char *value;
-	if (!git_configset_get_value(cs, key, &value)) {
+	if (!git_configset_get_value(set, key, &value)) {
 		*dest = git_config_bool_or_int(key, value, is_bool);
 		return 0;
 	} else
 		return 1;
 }
 
-int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest)
+int git_configset_get_maybe_bool(struct config_set *set, const char *key, int *dest)
 {
 	const char *value;
-	if (!git_configset_get_value(cs, key, &value)) {
+	if (!git_configset_get_value(set, key, &value)) {
 		*dest = git_parse_maybe_bool(value);
 		if (*dest == -1)
 			return -1;
@@ -2505,10 +2643,10 @@ int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *de
 		return 1;
 }
 
-int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest)
+int git_configset_get_pathname(struct config_set *set, const char *key, const char **dest)
 {
 	const char *value;
-	if (!git_configset_get_value(cs, key, &value))
+	if (!git_configset_get_value(set, key, &value))
 		return git_config_pathname(dest, key, value);
 	else
 		return 1;
@@ -2518,6 +2656,7 @@ int git_configset_get_pathname(struct config_set *cs, const char *key, const cha
 static void repo_read_config(struct repository *repo)
 {
 	struct config_options opts = { 0 };
+	struct configset_add_data data = CONFIGSET_ADD_INIT;
 
 	opts.respect_includes = 1;
 	opts.commondir = repo->commondir;
@@ -2529,8 +2668,10 @@ static void repo_read_config(struct repository *repo)
 		git_configset_clear(repo->config);
 
 	git_configset_init(repo->config);
+	data.config_set = repo->config;
+	data.config_reader = &the_reader;
 
-	if (config_with_options(config_set_callback, repo->config, NULL, &opts) < 0)
+	if (config_with_options(config_set_callback, &data, NULL, &opts) < 0)
 		/*
 		 * config_with_options() normally returns only
 		 * zero, as most errors are fatal, and
@@ -2562,7 +2703,13 @@ static void repo_config_clear(struct repository *repo)
 void repo_config(struct repository *repo, config_fn_t fn, void *data)
 {
 	git_config_check_init(repo);
-	configset_iter(repo->config, fn, data);
+	configset_iter(&the_reader, repo->config, fn, data);
+}
+
+int repo_config_get(struct repository *repo, const char *key)
+{
+	git_config_check_init(repo);
+	return git_configset_get(repo->config, key);
 }
 
 int repo_config_get_value(struct repository *repo,
@@ -2572,11 +2719,18 @@ int repo_config_get_value(struct repository *repo,
 	return git_configset_get_value(repo->config, key, value);
 }
 
-const struct string_list *repo_config_get_value_multi(struct repository *repo,
-						      const char *key)
+int repo_config_get_value_multi(struct repository *repo, const char *key,
+				const struct string_list **dest)
 {
 	git_config_check_init(repo);
-	return git_configset_get_value_multi(repo->config, key);
+	return git_configset_get_value_multi(repo->config, key, dest);
+}
+
+int repo_config_get_string_multi(struct repository *repo, const char *key,
+				 const struct string_list **dest)
+{
+	git_config_check_init(repo);
+	return git_configset_get_string_multi(repo->config, key, dest);
 }
 
 int repo_config_get_string(struct repository *repo,
@@ -2656,16 +2810,19 @@ static void read_protected_config(void)
 		.ignore_worktree = 1,
 		.system_gently = 1,
 	};
+	struct configset_add_data data = CONFIGSET_ADD_INIT;
+
 	git_configset_init(&protected_config);
-	config_with_options(config_set_callback, &protected_config,
-			    NULL, &opts);
+	data.config_set = &protected_config;
+	data.config_reader = &the_reader;
+	config_with_options(config_set_callback, &data, NULL, &opts);
 }
 
 void git_protected_config(config_fn_t fn, void *data)
 {
 	if (!protected_config.hash_initialized)
 		read_protected_config();
-	configset_iter(&protected_config, fn, data);
+	configset_iter(&the_reader, &protected_config, fn, data);
 }
 
 /* Functions used historically to read configuration from 'the_repository' */
@@ -2679,14 +2836,25 @@ void git_config_clear(void)
 	repo_config_clear(the_repository);
 }
 
+int git_config_get(const char *key)
+{
+	return repo_config_get(the_repository, key);
+}
+
 int git_config_get_value(const char *key, const char **value)
 {
 	return repo_config_get_value(the_repository, key, value);
 }
 
-const struct string_list *git_config_get_value_multi(const char *key)
+int git_config_get_value_multi(const char *key, const struct string_list **dest)
 {
-	return repo_config_get_value_multi(the_repository, key);
+	return repo_config_get_value_multi(the_repository, key, dest);
+}
+
+int git_config_get_string_multi(const char *key,
+				const struct string_list **dest)
+{
+	return repo_config_get_string_multi(the_repository, key, dest);
 }
 
 int git_config_get_string(const char *key, char **dest)
@@ -2833,7 +3001,8 @@ void git_die_config(const char *key, const char *err, ...)
 		error_fn(err, params);
 		va_end(params);
 	}
-	values = git_config_get_value_multi(key);
+	if (git_config_get_value_multi(key, &values))
+		BUG("for key '%s' we must have a value to report on", key);
 	kv_info = values->items[values->nr - 1].util;
 	git_die_config_linenr(key, kv_info->filename, kv_info->linenr);
 }
@@ -2843,6 +3012,7 @@ void git_die_config(const char *key, const char *err, ...)
  */
 
 struct config_store_data {
+	struct config_reader *config_reader;
 	size_t baselen;
 	char *key;
 	int do_not_match;
@@ -2857,6 +3027,7 @@ struct config_store_data {
 	unsigned int parsed_nr, parsed_alloc, *seen, seen_nr, seen_alloc;
 	unsigned int key_seen:1, section_seen:1, is_keys_section:1;
 };
+#define CONFIG_STORE_INIT { 0 }
 
 static void config_store_data_clear(struct config_store_data *store)
 {
@@ -2891,6 +3062,7 @@ static int store_aux_event(enum config_event_t type,
 			   size_t begin, size_t end, void *data)
 {
 	struct config_store_data *store = data;
+	struct config_source *cs = store->config_reader->source;
 
 	ALLOC_GROW(store->parsed, store->parsed_nr + 1, store->parsed_alloc);
 	store->parsed[store->parsed_nr].begin = begin;
@@ -2900,10 +3072,10 @@ static int store_aux_event(enum config_event_t type,
 	if (type == CONFIG_EVENT_SECTION) {
 		int (*cmpfn)(const char *, const char *, size_t);
 
-		if (cf->var.len < 2 || cf->var.buf[cf->var.len - 1] != '.')
-			return error(_("invalid section name '%s'"), cf->var.buf);
+		if (cs->var.len < 2 || cs->var.buf[cs->var.len - 1] != '.')
+			return error(_("invalid section name '%s'"), cs->var.buf);
 
-		if (cf->subsection_case_sensitive)
+		if (cs->subsection_case_sensitive)
 			cmpfn = strncasecmp;
 		else
 			cmpfn = strncmp;
@@ -2911,8 +3083,8 @@ static int store_aux_event(enum config_event_t type,
 		/* Is this the section we were looking for? */
 		store->is_keys_section =
 			store->parsed[store->parsed_nr].is_keys_section =
-			cf->var.len - 1 == store->baselen &&
-			!cmpfn(cf->var.buf, store->key, store->baselen);
+			cs->var.len - 1 == store->baselen &&
+			!cmpfn(cs->var.buf, store->key, store->baselen);
 		if (store->is_keys_section) {
 			store->section_seen = 1;
 			ALLOC_GROW(store->seen, store->seen_nr + 1,
@@ -3208,9 +3380,9 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
 	char *filename_buf = NULL;
 	char *contents = NULL;
 	size_t contents_sz;
-	struct config_store_data store;
+	struct config_store_data store = CONFIG_STORE_INIT;
 
-	memset(&store, 0, sizeof(store));
+	store.config_reader = &the_reader;
 
 	/* parse-key returns negative; flip the sign to feed exit(3) */
 	ret = 0 - git_config_parse_key(key, &store.key, &store.baselen);
@@ -3487,9 +3659,10 @@ void git_config_set_multivar(const char *key, const char *value,
 					flags);
 }
 
-static int section_name_match (const char *buf, const char *name)
+static size_t section_name_match (const char *buf, const char *name)
 {
-	int i = 0, j = 0, dot = 0;
+	size_t i = 0, j = 0;
+	int dot = 0;
 	if (buf[i] != '[')
 		return 0;
 	for (i = 1; buf[i] && buf[i] != ']'; i++) {
@@ -3542,6 +3715,8 @@ static int section_name_is_ok(const char *name)
 	return 1;
 }
 
+#define GIT_CONFIG_MAX_LINE_LEN (512 * 1024)
+
 /* if new_name == NULL, the section is removed instead */
 static int git_config_copy_or_rename_section_in_file(const char *config_filename,
 				      const char *old_name,
@@ -3551,11 +3726,12 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
 	char *filename_buf = NULL;
 	struct lock_file lock = LOCK_INIT;
 	int out_fd;
-	char buf[1024];
+	struct strbuf buf = STRBUF_INIT;
 	FILE *config_file = NULL;
 	struct stat st;
 	struct strbuf copystr = STRBUF_INIT;
 	struct config_store_data store;
+	uint32_t line_nr = 0;
 
 	memset(&store, 0, sizeof(store));
 
@@ -3592,16 +3768,25 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
 		goto out;
 	}
 
-	while (fgets(buf, sizeof(buf), config_file)) {
-		unsigned i;
-		int length;
+	while (!strbuf_getwholeline(&buf, config_file, '\n')) {
+		size_t i, length;
 		int is_section = 0;
-		char *output = buf;
-		for (i = 0; buf[i] && isspace(buf[i]); i++)
+		char *output = buf.buf;
+
+		line_nr++;
+
+		if (buf.len >= GIT_CONFIG_MAX_LINE_LEN) {
+			ret = error(_("refusing to work with overly long line "
+				      "in '%s' on line %"PRIuMAX),
+				    config_filename, (uintmax_t)line_nr);
+			goto out;
+		}
+
+		for (i = 0; buf.buf[i] && isspace(buf.buf[i]); i++)
 			; /* do nothing */
-		if (buf[i] == '[') {
+		if (buf.buf[i] == '[') {
 			/* it's a section */
-			int offset;
+			size_t offset;
 			is_section = 1;
 
 			/*
@@ -3618,7 +3803,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
 				strbuf_reset(&copystr);
 			}
 
-			offset = section_name_match(&buf[i], old_name);
+			offset = section_name_match(&buf.buf[i], old_name);
 			if (offset > 0) {
 				ret++;
 				if (!new_name) {
@@ -3693,6 +3878,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
 out_no_rollback:
 	free(filename_buf);
 	config_store_data_clear(&store);
+	strbuf_release(&buf);
 	return ret;
 }
 
@@ -3766,14 +3952,23 @@ int parse_config_key(const char *var,
 	return 0;
 }
 
+static int reader_origin_type(struct config_reader *reader,
+			      enum config_origin_type *type)
+{
+	if (the_reader.config_kvi)
+		*type = reader->config_kvi->origin_type;
+	else if(the_reader.source)
+		*type = reader->source->origin_type;
+	else
+		return 1;
+	return 0;
+}
+
 const char *current_config_origin_type(void)
 {
-	int type;
-	if (current_config_kvi)
-		type = current_config_kvi->origin_type;
-	else if(cf)
-		type = cf->origin_type;
-	else
+	enum config_origin_type type = CONFIG_ORIGIN_UNKNOWN;
+
+	if (reader_origin_type(&the_reader, &type))
 		BUG("current_config_origin_type called outside config callback");
 
 	switch (type) {
@@ -3812,32 +4007,39 @@ const char *config_scope_name(enum config_scope scope)
 	}
 }
 
+static int reader_config_name(struct config_reader *reader, const char **out)
+{
+	if (the_reader.config_kvi)
+		*out = reader->config_kvi->filename;
+	else if (the_reader.source)
+		*out = reader->source->name;
+	else
+		return 1;
+	return 0;
+}
+
 const char *current_config_name(void)
 {
 	const char *name;
-	if (current_config_kvi)
-		name = current_config_kvi->filename;
-	else if (cf)
-		name = cf->name;
-	else
+	if (reader_config_name(&the_reader, &name))
 		BUG("current_config_name called outside config callback");
 	return name ? name : "";
 }
 
 enum config_scope current_config_scope(void)
 {
-	if (current_config_kvi)
-		return current_config_kvi->scope;
+	if (the_reader.config_kvi)
+		return the_reader.config_kvi->scope;
 	else
-		return current_parsing_scope;
+		return the_reader.parsing_scope;
 }
 
 int current_config_line(void)
 {
-	if (current_config_kvi)
-		return current_config_kvi->linenr;
+	if (the_reader.config_kvi)
+		return the_reader.config_kvi->linenr;
 	else
-		return cf->linenr;
+		return the_reader.source->linenr;
 }
 
 int lookup_config(const char **mapping, int nr_mapping, const char *var)
diff --git a/config.h b/config.h
index 7606246..247b572 100644
--- a/config.h
+++ b/config.h
@@ -56,6 +56,7 @@ struct git_config_source {
 };
 
 enum config_origin_type {
+	CONFIG_ORIGIN_UNKNOWN = 0,
 	CONFIG_ORIGIN_BLOB,
 	CONFIG_ORIGIN_FILE,
 	CONFIG_ORIGIN_STDIN,
@@ -450,10 +451,31 @@ int git_configset_add_file(struct config_set *cs, const char *filename);
 /**
  * Finds and returns the value list, sorted in order of increasing priority
  * for the configuration variable `key` and config set `cs`. When the
- * configuration variable `key` is not found, returns NULL. The caller
- * should not free or modify the returned pointer, as it is owned by the cache.
+ * configuration variable `key` is not found, returns 1 without touching
+ * `value`.
+ *
+ * The key will be parsed for validity with git_config_parse_key(), on
+ * error a negative value will be returned.
+ *
+ * The caller should not free or modify the returned pointer, as it is
+ * owned by the cache.
  */
-const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
+RESULT_MUST_BE_USED
+int git_configset_get_value_multi(struct config_set *cs, const char *key,
+				  const struct string_list **dest);
+
+/**
+ * A validation wrapper for git_configset_get_value_multi() which does
+ * for it what git_configset_get_string() does for
+ * git_configset_get_value().
+ *
+ * The configuration syntax allows for "[section] key", which will
+ * give us a NULL entry in the "struct string_list", as opposed to
+ * "[section] key =" which is the empty string. Most users of the API
+ * are not prepared to handle NULL in a "struct string_list".
+ */
+int git_configset_get_string_multi(struct config_set *cs, const char *key,
+				   const struct string_list **dest);
 
 /**
  * Clears `config_set` structure, removes all saved variable-value pairs.
@@ -465,6 +487,13 @@ void git_configset_clear(struct config_set *cs);
  * value in the 'dest' pointer.
  */
 
+/**
+ * git_configset_get() returns negative values on error, see
+ * repo_config_get() below.
+ */
+RESULT_MUST_BE_USED
+int git_configset_get(struct config_set *cs, const char *key);
+
 /*
  * Finds the highest-priority value for the configuration variable `key`
  * and config set `cs`, stores the pointer to it in `value` and returns 0.
@@ -485,10 +514,22 @@ int git_configset_get_pathname(struct config_set *cs, const char *key, const cha
 /* Functions for reading a repository's config */
 struct repository;
 void repo_config(struct repository *repo, config_fn_t fn, void *data);
+
+/**
+ * Run only the discover part of the repo_config_get_*() functions
+ * below, in addition to 1 if not found, returns negative values on
+ * error (e.g. if the key itself is invalid).
+ */
+RESULT_MUST_BE_USED
+int repo_config_get(struct repository *repo, const char *key);
 int repo_config_get_value(struct repository *repo,
 			  const char *key, const char **value);
-const struct string_list *repo_config_get_value_multi(struct repository *repo,
-						      const char *key);
+RESULT_MUST_BE_USED
+int repo_config_get_value_multi(struct repository *repo, const char *key,
+				const struct string_list **dest);
+RESULT_MUST_BE_USED
+int repo_config_get_string_multi(struct repository *repo, const char *key,
+				 const struct string_list **dest);
 int repo_config_get_string(struct repository *repo,
 			   const char *key, char **dest);
 int repo_config_get_string_tmp(struct repository *repo,
@@ -521,8 +562,15 @@ void git_protected_config(config_fn_t fn, void *data);
  * manner, the config API provides two functions `git_config_get_value`
  * and `git_config_get_value_multi`. They both read values from an internal
  * cache generated previously from reading the config files.
+ *
+ * For those git_config_get*() functions that aren't documented,
+ * consult the corresponding repo_config_get*() function's
+ * documentation.
  */
 
+RESULT_MUST_BE_USED
+int git_config_get(const char *key);
+
 /**
  * Finds the highest-priority value for the configuration variable `key`,
  * stores the pointer to it in `value` and returns 0. When the
@@ -535,10 +583,17 @@ int git_config_get_value(const char *key, const char **value);
 /**
  * Finds and returns the value list, sorted in order of increasing priority
  * for the configuration variable `key`. When the configuration variable
- * `key` is not found, returns NULL. The caller should not free or modify
- * the returned pointer, as it is owned by the cache.
+ * `key` is not found, returns 1 without touching `value`.
+ *
+ * The caller should not free or modify the returned pointer, as it is
+ * owned by the cache.
  */
-const struct string_list *git_config_get_value_multi(const char *key);
+RESULT_MUST_BE_USED
+int git_config_get_value_multi(const char *key,
+			       const struct string_list **dest);
+RESULT_MUST_BE_USED
+int git_config_get_string_multi(const char *key,
+				const struct string_list **dest);
 
 /**
  * Resets and invalidates the config cache.
diff --git a/connect.c b/connect.c
index 63e5964..3a01862 100644
--- a/connect.c
+++ b/connect.c
@@ -1,6 +1,8 @@
 #include "git-compat-util.h"
-#include "cache.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "pkt-line.h"
 #include "quote.h"
 #include "refs.h"
@@ -11,6 +13,7 @@
 #include "string-list.h"
 #include "oid-array.h"
 #include "transport.h"
+#include "trace2.h"
 #include "strbuf.h"
 #include "version.h"
 #include "protocol.h"
@@ -19,7 +22,7 @@
 
 static char *server_capabilities_v1;
 static struct strvec server_capabilities_v2 = STRVEC_INIT;
-static const char *next_server_feature_value(const char *feature, int *len, int *offset);
+static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset);
 
 static int check_ref(const char *name, unsigned int flags)
 {
@@ -30,7 +33,8 @@ static int check_ref(const char *name, unsigned int flags)
 		return 0;
 
 	/* REF_NORMAL means that we don't want the magic fake tag refs */
-	if ((flags & REF_NORMAL) && check_refname_format(name, 0))
+	if ((flags & REF_NORMAL) && check_refname_format(name,
+							 REFNAME_ALLOW_ONELEVEL))
 		return 0;
 
 	/* REF_HEADS means that we want regular branch heads */
@@ -201,10 +205,10 @@ static void parse_one_symref_info(struct string_list *symref, const char *val, i
 static void annotate_refs_with_symref_info(struct ref *ref)
 {
 	struct string_list symref = STRING_LIST_INIT_DUP;
-	int offset = 0;
+	size_t offset = 0;
 
 	while (1) {
-		int len;
+		size_t len;
 		const char *val;
 
 		val = next_server_feature_value("symref", &len, &offset);
@@ -227,7 +231,7 @@ static void annotate_refs_with_symref_info(struct ref *ref)
 static void process_capabilities(struct packet_reader *reader, int *linelen)
 {
 	const char *feat_val;
-	int feat_len;
+	size_t feat_len;
 	const char *line = reader->line;
 	int nul_location = strlen(line);
 	if (nul_location == *linelen)
@@ -259,7 +263,8 @@ static int process_dummy_ref(const struct packet_reader *reader)
 		return 0;
 	name++;
 
-	return oideq(null_oid(), &oid) && !strcmp(name, "capabilities^{}");
+	return oideq(reader->hash_algo->null_oid, &oid) &&
+		!strcmp(name, "capabilities^{}");
 }
 
 static void check_no_capabilities(const char *line, int len)
@@ -591,9 +596,10 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
 	return list;
 }
 
-const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset)
+const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset)
 {
-	int len;
+	const char *orig_start = feature_list;
+	size_t len;
 
 	if (!feature_list)
 		return NULL;
@@ -612,19 +618,19 @@ const char *parse_feature_value(const char *feature_list, const char *feature, i
 				if (lenp)
 					*lenp = 0;
 				if (offset)
-					*offset = found + len - feature_list;
+					*offset = found + len - orig_start;
 				return value;
 			}
 			/* feature with a value (e.g., "agent=git/1.2.3") */
 			else if (*value == '=') {
-				int end;
+				size_t end;
 
 				value++;
 				end = strcspn(value, " \t\n");
 				if (lenp)
 					*lenp = end;
 				if (offset)
-					*offset = value + end - feature_list;
+					*offset = value + end - orig_start;
 				return value;
 			}
 			/*
@@ -639,8 +645,8 @@ const char *parse_feature_value(const char *feature_list, const char *feature, i
 
 int server_supports_hash(const char *desired, int *feature_supported)
 {
-	int offset = 0;
-	int len;
+	size_t offset = 0;
+	size_t len;
 	const char *hash;
 
 	hash = next_server_feature_value("object-format", &len, &offset);
@@ -664,12 +670,12 @@ int parse_feature_request(const char *feature_list, const char *feature)
 	return !!parse_feature_value(feature_list, feature, NULL, NULL);
 }
 
-static const char *next_server_feature_value(const char *feature, int *len, int *offset)
+static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset)
 {
 	return parse_feature_value(server_capabilities_v1, feature, len, offset);
 }
 
-const char *server_feature_value(const char *feature, int *len)
+const char *server_feature_value(const char *feature, size_t *len)
 {
 	return parse_feature_value(server_capabilities_v1, feature, len, NULL);
 }
@@ -1406,6 +1412,7 @@ static void fill_ssh_args(struct child_process *conn, const char *ssh_host,
  * the connection failed).
  */
 struct child_process *git_connect(int fd[2], const char *url,
+				  const char *name,
 				  const char *prog, int flags)
 {
 	char *hostandport, *path;
@@ -1415,10 +1422,11 @@ struct child_process *git_connect(int fd[2], const char *url,
 
 	/*
 	 * NEEDSWORK: If we are trying to use protocol v2 and we are planning
-	 * to perform a push, then fallback to v0 since the client doesn't know
-	 * how to push yet using v2.
+	 * to perform any operation that doesn't involve upload-pack (i.e., a
+	 * fetch, ls-remote, etc), then fallback to v0 since we don't know how
+	 * to do anything else (like push or remote archive) via v2.
 	 */
-	if (version == protocol_v2 && !strcmp("git-receive-pack", prog))
+	if (version == protocol_v2 && strcmp("git-upload-pack", name))
 		version = protocol_v0;
 
 	/* Without this we cannot rely on waitpid() to tell
diff --git a/connect.h b/connect.h
index b26f7de..1645126 100644
--- a/connect.h
+++ b/connect.h
@@ -7,19 +7,19 @@
 #define CONNECT_DIAG_URL      (1u << 1)
 #define CONNECT_IPV4          (1u << 2)
 #define CONNECT_IPV6          (1u << 3)
-struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
+struct child_process *git_connect(int fd[2], const char *url, const char *name, const char *prog, int flags);
 int finish_connect(struct child_process *conn);
 int git_connection_is_socket(struct child_process *conn);
 int server_supports(const char *feature);
 int parse_feature_request(const char *features, const char *feature);
-const char *server_feature_value(const char *feature, int *len_ret);
+const char *server_feature_value(const char *feature, size_t *len_ret);
 int url_is_local_not_ssh(const char *url);
 
 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);
+const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset);
 int server_supports_v2(const char *c);
 void ensure_server_supports_v2(const char *c);
 int server_feature_v2(const char *c, const char **v);
diff --git a/connected.c b/connected.c
index b90fd61..d672521 100644
--- a/connected.c
+++ b/connected.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
+#include "hex.h"
 #include "object-store.h"
 #include "run-command.h"
 #include "sigchain.h"
@@ -54,7 +56,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 		strbuf_release(&idx_file);
 	}
 
-	if (has_promisor_remote()) {
+	if (repo_has_promisor_remote(the_repository)) {
 		/*
 		 * For partial clones, we don't want to have to do a regular
 		 * connectivity check because we have to enumerate and exclude
@@ -97,7 +99,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 	strvec_push(&rev_list.args,"rev-list");
 	strvec_push(&rev_list.args, "--objects");
 	strvec_push(&rev_list.args, "--stdin");
-	if (has_promisor_remote())
+	if (repo_has_promisor_remote(the_repository))
 		strvec_push(&rev_list.args, "--exclude-promisor-objects");
 	if (!opt->is_deepening_fetch) {
 		strvec_push(&rev_list.args, "--not");
diff --git a/contrib/coccinelle/tests/unused.c b/contrib/coccinelle/tests/unused.c
deleted file mode 100644
index 8294d73..0000000
--- a/contrib/coccinelle/tests/unused.c
+++ /dev/null
@@ -1,82 +0,0 @@
-void test_strbuf(void)
-{
-	struct strbuf sb1 = STRBUF_INIT;
-	struct strbuf sb2 = STRBUF_INIT;
-	struct strbuf sb3 = STRBUF_INIT;
-	struct strbuf sb4 = STRBUF_INIT;
-	struct strbuf sb5;
-	struct strbuf sb6 = { 0 };
-	struct strbuf sb7 = STRBUF_INIT;
-	struct strbuf sb8 = STRBUF_INIT;
-	struct strbuf *sp1;
-	struct strbuf *sp2;
-	struct strbuf *sp3;
-	struct strbuf *sp4 = xmalloc(sizeof(struct strbuf));
-	struct strbuf *sp5 = xmalloc(sizeof(struct strbuf));
-	struct strbuf *sp6 = xmalloc(sizeof(struct strbuf));
-	struct strbuf *sp7;
-
-	strbuf_init(&sb5, 0);
-	strbuf_init(sp1, 0);
-	strbuf_init(sp2, 0);
-	strbuf_init(sp3, 0);
-	strbuf_init(sp4, 0);
-	strbuf_init(sp5, 0);
-	strbuf_init(sp6, 0);
-	strbuf_init(sp7, 0);
-	sp7 = xmalloc(sizeof(struct strbuf));
-
-	use_before(&sb3);
-	use_as_str("%s", sb7.buf);
-	use_as_str("%s", sp1->buf);
-	use_as_str("%s", sp6->buf);
-	pass_pp(&sp3);
-
-	strbuf_release(&sb1);
-	strbuf_reset(&sb2);
-	strbuf_release(&sb3);
-	strbuf_release(&sb4);
-	strbuf_release(&sb5);
-	strbuf_release(&sb6);
-	strbuf_release(&sb7);
-	strbuf_release(sp1);
-	strbuf_release(sp2);
-	strbuf_release(sp3);
-	strbuf_release(sp4);
-	strbuf_release(sp5);
-	strbuf_release(sp6);
-	strbuf_release(sp7);
-
-	use_after(&sb4);
-
-	if (when_strict())
-		return;
-	strbuf_release(&sb8);
-}
-
-void test_other(void)
-{
-	struct string_list l = STRING_LIST_INIT_DUP;
-	struct strbuf sb = STRBUF_INIT;
-
-	string_list_clear(&l, 0);
-	string_list_clear(&sb, 0);
-}
-
-void test_worktrees(void)
-{
-	struct worktree **w1 = get_worktrees();
-	struct worktree **w2 = get_worktrees();
-	struct worktree **w3;
-	struct worktree **w4;
-
-	w3 = get_worktrees();
-	w4 = get_worktrees();
-
-	use_it(w4);
-
-	free_worktrees(w1);
-	free_worktrees(w2);
-	free_worktrees(w3);
-	free_worktrees(w4);
-}
diff --git a/contrib/coccinelle/tests/unused.res b/contrib/coccinelle/tests/unused.res
deleted file mode 100644
index 6d3e745..0000000
--- a/contrib/coccinelle/tests/unused.res
+++ /dev/null
@@ -1,45 +0,0 @@
-void test_strbuf(void)
-{
-	struct strbuf sb3 = STRBUF_INIT;
-	struct strbuf sb4 = STRBUF_INIT;
-	struct strbuf sb7 = STRBUF_INIT;
-	struct strbuf *sp1;
-	struct strbuf *sp3;
-	struct strbuf *sp6 = xmalloc(sizeof(struct strbuf));
-	strbuf_init(sp1, 0);
-	strbuf_init(sp3, 0);
-	strbuf_init(sp6, 0);
-
-	use_before(&sb3);
-	use_as_str("%s", sb7.buf);
-	use_as_str("%s", sp1->buf);
-	use_as_str("%s", sp6->buf);
-	pass_pp(&sp3);
-
-	strbuf_release(&sb3);
-	strbuf_release(&sb4);
-	strbuf_release(&sb7);
-	strbuf_release(sp1);
-	strbuf_release(sp3);
-	strbuf_release(sp6);
-
-	use_after(&sb4);
-
-	if (when_strict())
-		return;
-}
-
-void test_other(void)
-{
-}
-
-void test_worktrees(void)
-{
-	struct worktree **w4;
-
-	w4 = get_worktrees();
-
-	use_it(w4);
-
-	free_worktrees(w4);
-}
diff --git a/contrib/coccinelle/the_repository.cocci b/contrib/coccinelle/the_repository.cocci
new file mode 100644
index 0000000..765ad68
--- /dev/null
+++ b/contrib/coccinelle/the_repository.cocci
@@ -0,0 +1,123 @@
+// Fully migrated "the_repository" additions
+@@
+@@
+(
+// cache.h
+- get_oid
++ repo_get_oid
+|
+- get_oid_commit
++ repo_get_oid_commit
+|
+- get_oid_committish
++ repo_get_oid_committish
+|
+- get_oid_tree
++ repo_get_oid_tree
+|
+- get_oid_treeish
++ repo_get_oid_treeish
+|
+- get_oid_blob
++ repo_get_oid_blob
+|
+- get_oid_mb
++ repo_get_oid_mb
+|
+- find_unique_abbrev
++ repo_find_unique_abbrev
+|
+- find_unique_abbrev_r
++ repo_find_unique_abbrev_r
+|
+- for_each_abbrev
++ repo_for_each_abbrev
+|
+- interpret_branch_name
++ repo_interpret_branch_name
+|
+- peel_to_type
++ repo_peel_to_type
+// commit-reach.h
+|
+- get_merge_bases
++ repo_get_merge_bases
+|
+- get_merge_bases_many
++ repo_get_merge_bases_many
+|
+- get_merge_bases_many_dirty
++ repo_get_merge_bases_many_dirty
+|
+- in_merge_bases
++ repo_in_merge_bases
+|
+- in_merge_bases_many
++ repo_in_merge_bases_many
+// commit.h
+|
+- parse_commit_internal
++ repo_parse_commit_internal
+|
+- parse_commit
++ repo_parse_commit
+|
+- get_commit_buffer
++ repo_get_commit_buffer
+|
+- unuse_commit_buffer
++ repo_unuse_commit_buffer
+|
+- logmsg_reencode
++ repo_logmsg_reencode
+|
+- get_commit_tree
++ repo_get_commit_tree
+// diff.h
+|
+- diff_setup
++ repo_diff_setup
+// object-store.h
+|
+- read_object_file
++ repo_read_object_file
+|
+- has_object_file
++ repo_has_object_file
+|
+- has_object_file_with_flags
++ repo_has_object_file_with_flags
+// pretty.h
+|
+- format_commit_message
++ repo_format_commit_message
+// packfile.h
+|
+- approximate_object_count
++ repo_approximate_object_count
+// promisor-remote.h
+|
+- promisor_remote_reinit
++ repo_promisor_remote_reinit
+|
+- promisor_remote_find
++ repo_promisor_remote_find
+|
+- has_promisor_remote
++ repo_has_promisor_remote
+// refs.h
+|
+- dwim_ref
++ repo_dwim_ref
+// rerere.h
+|
+- rerere
++ repo_rerere
+// revision.h
+|
+- init_revisions
++ repo_init_revisions
+)
+  (
++ the_repository,
+  ...)
diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci
deleted file mode 100644
index 747d382..0000000
--- a/contrib/coccinelle/the_repository.pending.cocci
+++ /dev/null
@@ -1,128 +0,0 @@
-// This file is used for the ongoing refactoring of
-// bringing the index or repository struct in all of
-// our code base.
-
-@@
-expression E;
-expression F;
-expression G;
-@@
-- read_object_file(
-+ repo_read_object_file(the_repository,
-  E, F, G)
-
-@@
-expression E;
-@@
-- has_object_file(
-+ repo_has_object_file(the_repository,
-  E)
-
-@@
-expression E;
-@@
-- has_object_file_with_flags(
-+ repo_has_object_file_with_flags(the_repository,
-  E)
-
-@@
-expression E;
-expression F;
-expression G;
-@@
-- parse_commit_internal(
-+ repo_parse_commit_internal(the_repository,
-  E, F, G)
-
-@@
-expression E;
-expression F;
-@@
-- parse_commit_gently(
-+ repo_parse_commit_gently(the_repository,
-  E, F)
-
-@@
-expression E;
-@@
-- parse_commit(
-+ repo_parse_commit(the_repository,
-  E)
-
-@@
-expression E;
-expression F;
-@@
-- get_merge_bases(
-+ repo_get_merge_bases(the_repository,
-  E, F);
-
-@@
-expression E;
-expression F;
-expression G;
-@@
-- get_merge_bases_many(
-+ repo_get_merge_bases_many(the_repository,
-  E, F, G);
-
-@@
-expression E;
-expression F;
-expression G;
-@@
-- get_merge_bases_many_dirty(
-+ repo_get_merge_bases_many_dirty(the_repository,
-  E, F, G);
-
-@@
-expression E;
-expression F;
-@@
-- in_merge_bases(
-+ repo_in_merge_bases(the_repository,
-  E, F);
-
-@@
-expression E;
-expression F;
-expression G;
-@@
-- in_merge_bases_many(
-+ repo_in_merge_bases_many(the_repository,
-  E, F, G);
-
-@@
-expression E;
-expression F;
-@@
-- get_commit_buffer(
-+ repo_get_commit_buffer(the_repository,
-  E, F);
-
-@@
-expression E;
-expression F;
-@@
-- unuse_commit_buffer(
-+ repo_unuse_commit_buffer(the_repository,
-  E, F);
-
-@@
-expression E;
-expression F;
-expression G;
-@@
-- logmsg_reencode(
-+ repo_logmsg_reencode(the_repository,
-  E, F, G);
-
-@@
-expression E;
-expression F;
-expression G;
-expression H;
-@@
-- format_commit_message(
-+ repo_format_commit_message(the_repository,
-  E, F, G, H);
diff --git a/contrib/coccinelle/unused.cocci b/contrib/coccinelle/unused.cocci
deleted file mode 100644
index d84046f..0000000
--- a/contrib/coccinelle/unused.cocci
+++ /dev/null
@@ -1,43 +0,0 @@
-// This rule finds sequences of "unused" declerations and uses of a
-// variable, where "unused" is defined to include only calling the
-// equivalent of alloc, init & free functions on the variable.
-@@
-type T;
-identifier I;
-// STRBUF_INIT, but also e.g. STRING_LIST_INIT_DUP (so no anchoring)
-constant INIT_MACRO =~ "_INIT";
-identifier MALLOC1 =~ "^x?[mc]alloc$";
-identifier INIT_ASSIGN1 =~ "^get_worktrees$";
-identifier INIT_CALL1 =~ "^[a-z_]*_init$";
-identifier REL1 =~ "^[a-z_]*_(release|reset|clear|free)$";
-identifier REL2 =~ "^(release|clear|free)_[a-z_]*$";
-@@
-
-(
-- T I;
-|
-- T I = { 0 };
-|
-- T I = INIT_MACRO;
-|
-- T I = MALLOC1(...);
-|
-- T I = INIT_ASSIGN1(...);
-)
-
-<... when != \( I \| &I \)
-(
-- \( INIT_CALL1 \)( \( I \| &I \), ...);
-|
-- I = \( INIT_ASSIGN1 \)(...);
-|
-- I = MALLOC1(...);
-)
-...>
-
-(
-- \( REL1 \| REL2 \)( \( I \| &I \), ...);
-|
-- \( REL1 \| REL2 \)( \( &I \| I \) );
-)
-  ... when != \( I \| &I \)
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 57972c2..2c03005 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -100,9 +100,7 @@
 #
 # If you would like a colored hint about the current dirty state, set
 # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
-# the colored output of "git status -sb" and are available only when
-# using __git_ps1 for PROMPT_COMMAND or precmd in Bash,
-# but always available in Zsh.
+# the colored output of "git status -sb".
 #
 # If you would like __git_ps1 to do nothing in the case when the current
 # directory is set up to be ignored by git, then set
@@ -259,12 +257,12 @@
 		local c_lblue='%F{blue}'
 		local c_clear='%f'
 	else
-		# Using \[ and \] around colors is necessary to prevent
+		# Using \001 and \002 around colors is necessary to prevent
 		# issues with command line editing/browsing/completion!
-		local c_red='\[\e[31m\]'
-		local c_green='\[\e[32m\]'
-		local c_lblue='\[\e[1;34m\]'
-		local c_clear='\[\e[0m\]'
+		local c_red=$'\001\e[31m\002'
+		local c_green=$'\001\e[32m\002'
+		local c_lblue=$'\001\e[1;34m\002'
+		local c_clear=$'\001\e[0m\002'
 	fi
 	local bad_color=$c_red
 	local ok_color=$c_green
@@ -300,7 +298,7 @@
 # variable, in that order.
 __git_eread ()
 {
-	test -r "$1" && IFS=$'\r\n' read "$2" <"$1"
+	test -r "$1" && IFS=$'\r\n' read -r "$2" <"$1"
 }
 
 # see if a cherry-pick or revert is in progress, if the user has committed a
@@ -574,11 +572,8 @@
 		b="\${__git_ps1_branch_name}"
 	fi
 
-	# NO color option unless in PROMPT_COMMAND mode or it's Zsh
 	if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
-		if [ $pcmode = yes ] || [ -n "${ZSH_VERSION-}" ]; then
-			__git_ps1_colorize_gitstring
-		fi
+		__git_ps1_colorize_gitstring
 	fi
 
 	local f="$h$w$i$s$u$p"
diff --git a/contrib/credential/gnome-keyring/.gitignore b/contrib/credential/gnome-keyring/.gitignore
deleted file mode 100644
index 88d8fcd..0000000
--- a/contrib/credential/gnome-keyring/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-git-credential-gnome-keyring
diff --git a/contrib/credential/gnome-keyring/Makefile b/contrib/credential/gnome-keyring/Makefile
deleted file mode 100644
index 22c19df..0000000
--- a/contrib/credential/gnome-keyring/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-MAIN:=git-credential-gnome-keyring
-all:: $(MAIN)
-
-CC = gcc
-RM = rm -f
-CFLAGS = -g -O2 -Wall
-PKG_CONFIG = pkg-config
-
--include ../../../config.mak.autogen
--include ../../../config.mak
-
-INCS:=$(shell $(PKG_CONFIG) --cflags gnome-keyring-1 glib-2.0)
-LIBS:=$(shell $(PKG_CONFIG) --libs gnome-keyring-1 glib-2.0)
-
-SRCS:=$(MAIN).c
-OBJS:=$(SRCS:.c=.o)
-
-%.o: %.c
-	$(CC) $(CFLAGS) $(CPPFLAGS) $(INCS) -o $@ -c $<
-
-$(MAIN): $(OBJS)
-	$(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
-
-clean:
-	@$(RM) $(MAIN) $(OBJS)
diff --git a/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c b/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c
deleted file mode 100644
index 5927e27..0000000
--- a/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (C) 2011 John Szakmeister <john@szakmeister.net>
- *               2012 Philipp A. Hartmann <pah@qo.cx>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Credits:
- * - GNOME Keyring API handling originally written by John Szakmeister
- * - ported to credential helper API by Philipp A. Hartmann
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <gnome-keyring.h>
-
-#ifdef GNOME_KEYRING_DEFAULT
-
-   /* Modern gnome-keyring */
-
-#include <gnome-keyring-memory.h>
-
-#else
-
-   /*
-    * Support ancient gnome-keyring, circ. RHEL 5.X.
-    * GNOME_KEYRING_DEFAULT seems to have been introduced with Gnome 2.22,
-    * and the other features roughly around Gnome 2.20, 6 months before.
-    * Ubuntu 8.04 used Gnome 2.22 (I think).  Not sure any distro used 2.20.
-    * So the existence/non-existence of GNOME_KEYRING_DEFAULT seems like
-    * a decent thing to use as an indicator.
-    */
-
-#define GNOME_KEYRING_DEFAULT NULL
-
-/*
- * ancient gnome-keyring returns DENIED when an entry is not found.
- * Setting NO_MATCH to DENIED will prevent us from reporting DENIED
- * errors during get and erase operations, but we will still report
- * DENIED errors during a store.
- */
-#define GNOME_KEYRING_RESULT_NO_MATCH GNOME_KEYRING_RESULT_DENIED
-
-#define gnome_keyring_memory_alloc g_malloc
-#define gnome_keyring_memory_free gnome_keyring_free_password
-#define gnome_keyring_memory_strdup g_strdup
-
-static const char *gnome_keyring_result_to_message(GnomeKeyringResult result)
-{
-	switch (result) {
-	case GNOME_KEYRING_RESULT_OK:
-		return "OK";
-	case GNOME_KEYRING_RESULT_DENIED:
-		return "Denied";
-	case GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON:
-		return "No Keyring Daemon";
-	case GNOME_KEYRING_RESULT_ALREADY_UNLOCKED:
-		return "Already UnLocked";
-	case GNOME_KEYRING_RESULT_NO_SUCH_KEYRING:
-		return "No Such Keyring";
-	case GNOME_KEYRING_RESULT_BAD_ARGUMENTS:
-		return "Bad Arguments";
-	case GNOME_KEYRING_RESULT_IO_ERROR:
-		return "IO Error";
-	case GNOME_KEYRING_RESULT_CANCELLED:
-		return "Cancelled";
-	case GNOME_KEYRING_RESULT_ALREADY_EXISTS:
-		return "Already Exists";
-	default:
-		return "Unknown Error";
-	}
-}
-
-/*
- * Support really ancient gnome-keyring, circ. RHEL 4.X.
- * Just a guess for the Glib version.  Glib 2.8 was roughly Gnome 2.12 ?
- * Which was released with gnome-keyring 0.4.3 ??
- */
-#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 8
-
-static void gnome_keyring_done_cb(GnomeKeyringResult result, gpointer user_data)
-{
-	gpointer *data = (gpointer *)user_data;
-	int *done = (int *)data[0];
-	GnomeKeyringResult *r = (GnomeKeyringResult *)data[1];
-
-	*r = result;
-	*done = 1;
-}
-
-static void wait_for_request_completion(int *done)
-{
-	GMainContext *mc = g_main_context_default();
-	while (!*done)
-		g_main_context_iteration(mc, TRUE);
-}
-
-static GnomeKeyringResult gnome_keyring_item_delete_sync(const char *keyring, guint32 id)
-{
-	int done = 0;
-	GnomeKeyringResult result;
-	gpointer data[] = { &done, &result };
-
-	gnome_keyring_item_delete(keyring, id, gnome_keyring_done_cb, data,
-		NULL);
-
-	wait_for_request_completion(&done);
-
-	return result;
-}
-
-#endif
-#endif
-
-/*
- * This credential struct and API is simplified from git's credential.{h,c}
- */
-struct credential {
-	char *protocol;
-	char *host;
-	unsigned short port;
-	char *path;
-	char *username;
-	char *password;
-};
-
-#define CREDENTIAL_INIT { 0 }
-
-typedef int (*credential_op_cb)(struct credential *);
-
-struct credential_operation {
-	char *name;
-	credential_op_cb op;
-};
-
-#define CREDENTIAL_OP_END { NULL, NULL }
-
-/* ----------------- GNOME Keyring functions ----------------- */
-
-/* create a special keyring option string, if path is given */
-static char *keyring_object(struct credential *c)
-{
-	if (!c->path)
-		return NULL;
-
-	if (c->port)
-		return g_strdup_printf("%s:%hd/%s", c->host, c->port, c->path);
-
-	return g_strdup_printf("%s/%s", c->host, c->path);
-}
-
-static int keyring_get(struct credential *c)
-{
-	char *object = NULL;
-	GList *entries;
-	GnomeKeyringNetworkPasswordData *password_data;
-	GnomeKeyringResult result;
-
-	if (!c->protocol || !(c->host || c->path))
-		return EXIT_FAILURE;
-
-	object = keyring_object(c);
-
-	result = gnome_keyring_find_network_password_sync(
-				c->username,
-				NULL /* domain */,
-				c->host,
-				object,
-				c->protocol,
-				NULL /* authtype */,
-				c->port,
-				&entries);
-
-	g_free(object);
-
-	if (result == GNOME_KEYRING_RESULT_NO_MATCH)
-		return EXIT_SUCCESS;
-
-	if (result == GNOME_KEYRING_RESULT_CANCELLED)
-		return EXIT_SUCCESS;
-
-	if (result != GNOME_KEYRING_RESULT_OK) {
-		g_critical("%s", gnome_keyring_result_to_message(result));
-		return EXIT_FAILURE;
-	}
-
-	/* pick the first one from the list */
-	password_data = (GnomeKeyringNetworkPasswordData *)entries->data;
-
-	gnome_keyring_memory_free(c->password);
-	c->password = gnome_keyring_memory_strdup(password_data->password);
-
-	if (!c->username)
-		c->username = g_strdup(password_data->user);
-
-	gnome_keyring_network_password_list_free(entries);
-
-	return EXIT_SUCCESS;
-}
-
-
-static int keyring_store(struct credential *c)
-{
-	guint32 item_id;
-	char *object = NULL;
-	GnomeKeyringResult result;
-
-	/*
-	 * Sanity check that what we are storing is actually sensible.
-	 * In particular, we can't make a URL without a protocol field.
-	 * Without either a host or pathname (depending on the scheme),
-	 * we have no primary key. And without a username and password,
-	 * we are not actually storing a credential.
-	 */
-	if (!c->protocol || !(c->host || c->path) ||
-	    !c->username || !c->password)
-		return EXIT_FAILURE;
-
-	object = keyring_object(c);
-
-	result = gnome_keyring_set_network_password_sync(
-				GNOME_KEYRING_DEFAULT,
-				c->username,
-				NULL /* domain */,
-				c->host,
-				object,
-				c->protocol,
-				NULL /* authtype */,
-				c->port,
-				c->password,
-				&item_id);
-
-	g_free(object);
-
-	if (result != GNOME_KEYRING_RESULT_OK &&
-	    result != GNOME_KEYRING_RESULT_CANCELLED) {
-		g_critical("%s", gnome_keyring_result_to_message(result));
-		return EXIT_FAILURE;
-	}
-
-	return EXIT_SUCCESS;
-}
-
-static int keyring_erase(struct credential *c)
-{
-	char *object = NULL;
-	GList *entries;
-	GnomeKeyringNetworkPasswordData *password_data;
-	GnomeKeyringResult result;
-
-	/*
-	 * Sanity check that we actually have something to match
-	 * against. The input we get is a restrictive pattern,
-	 * so technically a blank credential means "erase everything".
-	 * But it is too easy to accidentally send this, since it is equivalent
-	 * to empty input. So explicitly disallow it, and require that the
-	 * pattern have some actual content to match.
-	 */
-	if (!c->protocol && !c->host && !c->path && !c->username)
-		return EXIT_FAILURE;
-
-	object = keyring_object(c);
-
-	result = gnome_keyring_find_network_password_sync(
-				c->username,
-				NULL /* domain */,
-				c->host,
-				object,
-				c->protocol,
-				NULL /* authtype */,
-				c->port,
-				&entries);
-
-	g_free(object);
-
-	if (result == GNOME_KEYRING_RESULT_NO_MATCH)
-		return EXIT_SUCCESS;
-
-	if (result == GNOME_KEYRING_RESULT_CANCELLED)
-		return EXIT_SUCCESS;
-
-	if (result != GNOME_KEYRING_RESULT_OK) {
-		g_critical("%s", gnome_keyring_result_to_message(result));
-		return EXIT_FAILURE;
-	}
-
-	/* pick the first one from the list (delete all matches?) */
-	password_data = (GnomeKeyringNetworkPasswordData *)entries->data;
-
-	result = gnome_keyring_item_delete_sync(
-		password_data->keyring, password_data->item_id);
-
-	gnome_keyring_network_password_list_free(entries);
-
-	if (result != GNOME_KEYRING_RESULT_OK) {
-		g_critical("%s", gnome_keyring_result_to_message(result));
-		return EXIT_FAILURE;
-	}
-
-	return EXIT_SUCCESS;
-}
-
-/*
- * Table with helper operation callbacks, used by generic
- * credential helper main function.
- */
-static struct credential_operation const credential_helper_ops[] = {
-	{ "get",   keyring_get },
-	{ "store", keyring_store },
-	{ "erase", keyring_erase },
-	CREDENTIAL_OP_END
-};
-
-/* ------------------ credential functions ------------------ */
-
-static void credential_init(struct credential *c)
-{
-	memset(c, 0, sizeof(*c));
-}
-
-static void credential_clear(struct credential *c)
-{
-	g_free(c->protocol);
-	g_free(c->host);
-	g_free(c->path);
-	g_free(c->username);
-	gnome_keyring_memory_free(c->password);
-
-	credential_init(c);
-}
-
-static int credential_read(struct credential *c)
-{
-	char *buf;
-	size_t line_len;
-	char *key;
-	char *value;
-
-	key = buf = gnome_keyring_memory_alloc(1024);
-
-	while (fgets(buf, 1024, stdin)) {
-		line_len = strlen(buf);
-
-		if (line_len && buf[line_len-1] == '\n')
-			buf[--line_len] = '\0';
-
-		if (!line_len)
-			break;
-
-		value = strchr(buf, '=');
-		if (!value) {
-			g_warning("invalid credential line: %s", key);
-			gnome_keyring_memory_free(buf);
-			return -1;
-		}
-		*value++ = '\0';
-
-		if (!strcmp(key, "protocol")) {
-			g_free(c->protocol);
-			c->protocol = g_strdup(value);
-		} else if (!strcmp(key, "host")) {
-			g_free(c->host);
-			c->host = g_strdup(value);
-			value = strrchr(c->host, ':');
-			if (value) {
-				*value++ = '\0';
-				c->port = atoi(value);
-			}
-		} else if (!strcmp(key, "path")) {
-			g_free(c->path);
-			c->path = g_strdup(value);
-		} else if (!strcmp(key, "username")) {
-			g_free(c->username);
-			c->username = g_strdup(value);
-		} else if (!strcmp(key, "password")) {
-			gnome_keyring_memory_free(c->password);
-			c->password = gnome_keyring_memory_strdup(value);
-			while (*value)
-				*value++ = '\0';
-		}
-		/*
-		 * Ignore other lines; we don't know what they mean, but
-		 * this future-proofs us when later versions of git do
-		 * learn new lines, and the helpers are updated to match.
-		 */
-	}
-
-	gnome_keyring_memory_free(buf);
-
-	return 0;
-}
-
-static void credential_write_item(FILE *fp, const char *key, const char *value)
-{
-	if (!value)
-		return;
-	fprintf(fp, "%s=%s\n", key, value);
-}
-
-static void credential_write(const struct credential *c)
-{
-	/* only write username/password, if set */
-	credential_write_item(stdout, "username", c->username);
-	credential_write_item(stdout, "password", c->password);
-}
-
-static void usage(const char *name)
-{
-	struct credential_operation const *try_op = credential_helper_ops;
-	const char *basename = strrchr(name, '/');
-
-	basename = (basename) ? basename + 1 : name;
-	fprintf(stderr, "usage: %s <", basename);
-	while (try_op->name) {
-		fprintf(stderr, "%s", (try_op++)->name);
-		if (try_op->name)
-			fprintf(stderr, "%s", "|");
-	}
-	fprintf(stderr, "%s", ">\n");
-}
-
-int main(int argc, char *argv[])
-{
-	int ret = EXIT_SUCCESS;
-
-	struct credential_operation const *try_op = credential_helper_ops;
-	struct credential cred = CREDENTIAL_INIT;
-
-	if (!argv[1]) {
-		usage(argv[0]);
-		exit(EXIT_FAILURE);
-	}
-
-	g_set_application_name("Git Credential Helper");
-
-	/* lookup operation callback */
-	while (try_op->name && strcmp(argv[1], try_op->name))
-		try_op++;
-
-	/* unsupported operation given -- ignore silently */
-	if (!try_op->name || !try_op->op)
-		goto out;
-
-	ret = credential_read(&cred);
-	if (ret)
-		goto out;
-
-	/* perform credential operation */
-	ret = (*try_op->op)(&cred);
-
-	credential_write(&cred);
-
-out:
-	credential_clear(&cred);
-	return ret;
-}
diff --git a/contrib/credential/libsecret/.gitignore b/contrib/credential/libsecret/.gitignore
new file mode 100644
index 0000000..4fa2235
--- /dev/null
+++ b/contrib/credential/libsecret/.gitignore
@@ -0,0 +1 @@
+git-credential-libsecret
diff --git a/contrib/credential/libsecret/git-credential-libsecret.c b/contrib/credential/libsecret/git-credential-libsecret.c
index 2c5d76d..ef681f2 100644
--- a/contrib/credential/libsecret/git-credential-libsecret.c
+++ b/contrib/credential/libsecret/git-credential-libsecret.c
@@ -244,17 +244,16 @@ static void credential_clear(struct credential *c)
 
 static int credential_read(struct credential *c)
 {
-	char *buf;
-	size_t line_len;
+	char *buf = NULL;
+	size_t alloc;
+	ssize_t line_len;
 	char *key;
 	char *value;
 
-	key = buf = g_malloc(1024);
+	while ((line_len = getline(&buf, &alloc, stdin)) > 0) {
+		key = buf;
 
-	while (fgets(buf, 1024, stdin)) {
-		line_len = strlen(buf);
-
-		if (line_len && buf[line_len-1] == '\n')
+		if (buf[line_len-1] == '\n')
 			buf[--line_len] = '\0';
 
 		if (!line_len)
@@ -298,7 +297,7 @@ static int credential_read(struct credential *c)
 		 */
 	}
 
-	g_free(buf);
+	free(buf);
 
 	return 0;
 }
diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
index e29cc28..5f2e5f1 100644
--- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
+++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
@@ -113,14 +113,16 @@ static void add_internet_password(void)
 
 static void read_credential(void)
 {
-	char buf[1024];
+	char *buf = NULL;
+	size_t alloc;
+	ssize_t line_len;
 
-	while (fgets(buf, sizeof(buf), stdin)) {
+	while ((line_len = getline(&buf, &alloc, stdin)) > 0) {
 		char *v;
 
 		if (!strcmp(buf, "\n"))
 			break;
-		buf[strlen(buf)-1] = '\0';
+		buf[line_len-1] = '\0';
 
 		v = strchr(buf, '=');
 		if (!v)
@@ -165,6 +167,8 @@ static void read_credential(void)
 		 * learn new lines, and the helpers are updated to match.
 		 */
 	}
+
+	free(buf);
 }
 
 int main(int argc, const char **argv)
diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c
index ead6e26..96f1061 100644
--- a/contrib/credential/wincred/git-credential-wincred.c
+++ b/contrib/credential/wincred/git-credential-wincred.c
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include <io.h>
 #include <fcntl.h>
+#include <wincred.h>
 
 /* common helpers */
 
@@ -33,65 +34,8 @@ static void *xmalloc(size_t size)
 	return ret;
 }
 
-/* MinGW doesn't have wincred.h, so we need to define stuff */
-
-typedef struct _CREDENTIAL_ATTRIBUTEW {
-	LPWSTR Keyword;
-	DWORD  Flags;
-	DWORD  ValueSize;
-	LPBYTE Value;
-} CREDENTIAL_ATTRIBUTEW, *PCREDENTIAL_ATTRIBUTEW;
-
-typedef struct _CREDENTIALW {
-	DWORD                  Flags;
-	DWORD                  Type;
-	LPWSTR                 TargetName;
-	LPWSTR                 Comment;
-	FILETIME               LastWritten;
-	DWORD                  CredentialBlobSize;
-	LPBYTE                 CredentialBlob;
-	DWORD                  Persist;
-	DWORD                  AttributeCount;
-	PCREDENTIAL_ATTRIBUTEW Attributes;
-	LPWSTR                 TargetAlias;
-	LPWSTR                 UserName;
-} CREDENTIALW, *PCREDENTIALW;
-
-#define CRED_TYPE_GENERIC 1
-#define CRED_PERSIST_LOCAL_MACHINE 2
-#define CRED_MAX_ATTRIBUTES 64
-
-typedef BOOL (WINAPI *CredWriteWT)(PCREDENTIALW, DWORD);
-typedef BOOL (WINAPI *CredEnumerateWT)(LPCWSTR, DWORD, DWORD *,
-    PCREDENTIALW **);
-typedef VOID (WINAPI *CredFreeT)(PVOID);
-typedef BOOL (WINAPI *CredDeleteWT)(LPCWSTR, DWORD, DWORD);
-
-static HMODULE advapi;
-static CredWriteWT CredWriteW;
-static CredEnumerateWT CredEnumerateW;
-static CredFreeT CredFree;
-static CredDeleteWT CredDeleteW;
-
-static void load_cred_funcs(void)
-{
-	/* load DLLs */
-	advapi = LoadLibraryExA("advapi32.dll", NULL,
-				LOAD_LIBRARY_SEARCH_SYSTEM32);
-	if (!advapi)
-		die("failed to load advapi32.dll");
-
-	/* get function pointers */
-	CredWriteW = (CredWriteWT)GetProcAddress(advapi, "CredWriteW");
-	CredEnumerateW = (CredEnumerateWT)GetProcAddress(advapi,
-	    "CredEnumerateW");
-	CredFree = (CredFreeT)GetProcAddress(advapi, "CredFree");
-	CredDeleteW = (CredDeleteWT)GetProcAddress(advapi, "CredDeleteW");
-	if (!CredWriteW || !CredEnumerateW || !CredFree || !CredDeleteW)
-		die("failed to load functions");
-}
-
-static WCHAR *wusername, *password, *protocol, *host, *path, target[1024];
+static WCHAR *wusername, *password, *protocol, *host, *path, target[1024],
+	*password_expiry_utc;
 
 static void write_item(const char *what, LPCWSTR wbuf, int wlen)
 {
@@ -183,6 +127,7 @@ static void get_credential(void)
 	CREDENTIALW **creds;
 	DWORD num_creds;
 	int i;
+	CREDENTIAL_ATTRIBUTEW *attr;
 
 	if (!CredEnumerateW(L"git:*", 0, &num_creds, &creds))
 		return;
@@ -195,6 +140,14 @@ static void get_credential(void)
 			write_item("password",
 				(LPCWSTR)creds[i]->CredentialBlob,
 				creds[i]->CredentialBlobSize / sizeof(WCHAR));
+			for (int j = 0; j < creds[i]->AttributeCount; j++) {
+				attr = creds[i]->Attributes + j;
+				if (!wcscmp(attr->Keyword, L"git_password_expiry_utc")) {
+					write_item("password_expiry_utc", (LPCWSTR)attr->Value,
+					attr->ValueSize / sizeof(WCHAR));
+					break;
+				}
+			}
 			break;
 		}
 
@@ -204,6 +157,7 @@ static void get_credential(void)
 static void store_credential(void)
 {
 	CREDENTIALW cred;
+	CREDENTIAL_ATTRIBUTEW expiry_attr;
 
 	if (!wusername || !password)
 		return;
@@ -217,6 +171,14 @@ static void store_credential(void)
 	cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
 	cred.AttributeCount = 0;
 	cred.Attributes = NULL;
+	if (password_expiry_utc != NULL) {
+		expiry_attr.Keyword = L"git_password_expiry_utc";
+		expiry_attr.Value = (LPVOID)password_expiry_utc;
+		expiry_attr.ValueSize = (wcslen(password_expiry_utc)) * sizeof(WCHAR);
+		expiry_attr.Flags = 0;
+		cred.Attributes = &expiry_attr;
+		cred.AttributeCount = 1;
+	}
 	cred.TargetAlias = NULL;
 	cred.UserName = wusername;
 
@@ -249,16 +211,27 @@ static WCHAR *utf8_to_utf16_dup(const char *str)
 	return wstr;
 }
 
+#define KB (1024)
+
 static void read_credential(void)
 {
-	char buf[1024];
+	size_t alloc = 100 * KB;
+	char *buf = calloc(alloc, sizeof(*buf));
 
-	while (fgets(buf, sizeof(buf), stdin)) {
+	while (fgets(buf, alloc, stdin)) {
 		char *v;
-		int len = strlen(buf);
+		size_t len = strlen(buf);
+		int ends_in_newline = 0;
 		/* strip trailing CR / LF */
-		while (len && strchr("\r\n", buf[len - 1]))
+		if (len && buf[len - 1] == '\n') {
 			buf[--len] = 0;
+			ends_in_newline = 1;
+		}
+		if (len && buf[len - 1] == '\r')
+			buf[--len] = 0;
+
+		if (!ends_in_newline)
+			die("bad input: %s", buf);
 
 		if (!*buf)
 			break;
@@ -278,12 +251,16 @@ static void read_credential(void)
 			wusername = utf8_to_utf16_dup(v);
 		} else if (!strcmp(buf, "password"))
 			password = utf8_to_utf16_dup(v);
+		else if (!strcmp(buf, "password_expiry_utc"))
+			password_expiry_utc = utf8_to_utf16_dup(v);
 		/*
 		 * Ignore other lines; we don't know what they mean, but
 		 * this future-proofs us when later versions of git do
 		 * learn new lines, and the helpers are updated to match.
 		 */
 	}
+
+	free(buf);
 }
 
 int main(int argc, char *argv[])
@@ -292,7 +269,7 @@ int main(int argc, char *argv[])
 	    "usage: git credential-wincred <get|store|erase>\n";
 
 	if (!argv[1])
-		die(usage);
+		die("%s", usage);
 
 	/* git use binary pipes to avoid CRLF-issues */
 	_setmode(_fileno(stdin), _O_BINARY);
@@ -300,8 +277,6 @@ int main(int argc, char *argv[])
 
 	read_credential();
 
-	load_cred_funcs();
-
 	if (!protocol || !(host || path))
 		return 0;
 
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 10c9c87..7db4c45 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -34,8 +34,8 @@
 git subtree push  --prefix=<prefix> <repository> <refspec>
 --
 h,help        show the help
-q             quiet
-d             show debug messages
+q,quiet       quiet
+d,debug       show debug messages
 P,prefix=     the name of the subdir to split out
  options for 'split' (also: 'push')
 annotate=     add a prefix to commit message of new commits
diff --git a/contrib/subtree/t/Makefile b/contrib/subtree/t/Makefile
index 4655e09..093399c 100644
--- a/contrib/subtree/t/Makefile
+++ b/contrib/subtree/t/Makefile
@@ -74,9 +74,7 @@
 	$(MAKE) clean
 
 aggregate-results:
-	for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \
-		echo "$$f"; \
-	done | '$(SHELL_PATH_SQ)' ../../../t/aggregate-results.sh
+	@'$(SHELL_PATH_SQ)' ../../../t/aggregate-results.sh '$(TEST_RESULTS_DIRECTORY_SQ)'
 
 valgrind:
 	$(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind"
diff --git a/convert.c b/convert.c
index a54d169..9ee79fe 100644
--- a/convert.c
+++ b/convert.c
@@ -1,5 +1,10 @@
 #include "cache.h"
+#include "advice.h"
 #include "config.h"
+#include "convert.h"
+#include "copy.h"
+#include "gettext.h"
+#include "hex.h"
 #include "object-store.h"
 #include "attr.h"
 #include "run-command.h"
@@ -7,8 +12,10 @@
 #include "sigchain.h"
 #include "pkt-line.h"
 #include "sub-process.h"
+#include "trace.h"
 #include "utf8.h"
 #include "ll-merge.h"
+#include "wrapper.h"
 
 /*
  * convert.c - convert a file when checking it out and checking it in.
@@ -1308,7 +1315,7 @@ void convert_attrs(struct index_state *istate,
 		git_config(read_convert_config, NULL);
 	}
 
-	git_check_attr(istate, NULL, path, check);
+	git_check_attr(istate, path, check);
 	ccheck = check->items;
 	ca->crlf_action = git_path_check_crlf(ccheck + 4);
 	if (ca->crlf_action == CRLF_UNDEFINED)
diff --git a/convert.h b/convert.h
index 0a6e408..d925589 100644
--- a/convert.h
+++ b/convert.h
@@ -4,7 +4,7 @@
 #ifndef CONVERT_H
 #define CONVERT_H
 
-#include "hash.h"
+#include "hash-ll.h"
 #include "string-list.h"
 
 struct index_state;
diff --git a/copy.c b/copy.c
index 4de6a11..882c79c 100644
--- a/copy.c
+++ b/copy.c
@@ -1,4 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "copy.h"
+#include "path.h"
+#include "wrapper.h"
 
 int copy_fd(int ifd, int ofd)
 {
diff --git a/copy.h b/copy.h
new file mode 100644
index 0000000..2af77cb
--- /dev/null
+++ b/copy.h
@@ -0,0 +1,10 @@
+#ifndef COPY_H
+#define COPY_H
+
+#define COPY_READ_ERROR (-2)
+#define COPY_WRITE_ERROR (-3)
+int copy_fd(int ifd, int ofd);
+int copy_file(const char *dst, const char *src, int mode);
+int copy_file_with_time(const char *dst, const char *src, int mode);
+
+#endif /* COPY_H */
diff --git a/credential.c b/credential.c
index f320113..023b59d 100644
--- a/credential.c
+++ b/credential.c
@@ -1,11 +1,14 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
 #include "config.h"
 #include "credential.h"
+#include "gettext.h"
 #include "string-list.h"
 #include "run-command.h"
 #include "url.h"
 #include "prompt.h"
 #include "sigchain.h"
+#include "strbuf.h"
 #include "urlmatch.h"
 #include "git-compat-util.h"
 
@@ -22,7 +25,9 @@ void credential_clear(struct credential *c)
 	free(c->path);
 	free(c->username);
 	free(c->password);
+	free(c->oauth_refresh_token);
 	string_list_clear(&c->helpers, 0);
+	strvec_clear(&c->wwwauth_headers);
 
 	credential_init(c);
 }
@@ -235,11 +240,16 @@ int credential_read(struct credential *c, FILE *fp)
 		} else if (!strcmp(key, "path")) {
 			free(c->path);
 			c->path = xstrdup(value);
+		} else if (!strcmp(key, "wwwauth[]")) {
+			strvec_push(&c->wwwauth_headers, value);
 		} else if (!strcmp(key, "password_expiry_utc")) {
 			errno = 0;
 			c->password_expiry_utc = parse_timestamp(value, NULL, 10);
 			if (c->password_expiry_utc == 0 || errno == ERANGE)
 				c->password_expiry_utc = TIME_MAX;
+		} else if (!strcmp(key, "oauth_refresh_token")) {
+			free(c->oauth_refresh_token);
+			c->oauth_refresh_token = xstrdup(value);
 		} else if (!strcmp(key, "url")) {
 			credential_from_url(c, value);
 		} else if (!strcmp(key, "quit")) {
@@ -275,11 +285,14 @@ void credential_write(const struct credential *c, FILE *fp)
 	credential_write_item(fp, "path", c->path, 0);
 	credential_write_item(fp, "username", c->username, 0);
 	credential_write_item(fp, "password", c->password, 0);
+	credential_write_item(fp, "oauth_refresh_token", c->oauth_refresh_token, 0);
 	if (c->password_expiry_utc != TIME_MAX) {
 		char *s = xstrfmt("%"PRItime, c->password_expiry_utc);
 		credential_write_item(fp, "password_expiry_utc", s, 0);
 		free(s);
 	}
+	for (size_t i = 0; i < c->wwwauth_headers.nr; i++)
+		credential_write_item(fp, "wwwauth[]", c->wwwauth_headers.v[i], 0);
 }
 
 static int run_credential_helper(struct credential *c,
@@ -398,6 +411,7 @@ void credential_reject(struct credential *c)
 
 	FREE_AND_NULL(c->username);
 	FREE_AND_NULL(c->password);
+	FREE_AND_NULL(c->oauth_refresh_token);
 	c->password_expiry_utc = TIME_MAX;
 	c->approved = 0;
 }
diff --git a/credential.h b/credential.h
index 935b28a..b8e2936 100644
--- a/credential.h
+++ b/credential.h
@@ -2,6 +2,7 @@
 #define CREDENTIAL_H
 
 #include "string-list.h"
+#include "strvec.h"
 
 /**
  * The credentials API provides an abstracted way of gathering username and
@@ -115,6 +116,20 @@ struct credential {
 	 */
 	struct string_list helpers;
 
+	/**
+	 * A `strvec` of WWW-Authenticate header values. Each string
+	 * is the value of a WWW-Authenticate header in an HTTP response,
+	 * in the order they were received in the response.
+	 */
+	struct strvec wwwauth_headers;
+
+	/**
+	 * Internal use only. Keeps track of if we previously matched against a
+	 * WWW-Authenticate header line in order to re-fold future continuation
+	 * lines into one value.
+	 */
+	unsigned header_is_last_match:1;
+
 	unsigned approved:1,
 		 configured:1,
 		 quit:1,
@@ -126,12 +141,14 @@ struct credential {
 	char *protocol;
 	char *host;
 	char *path;
+	char *oauth_refresh_token;
 	timestamp_t password_expiry_utc;
 };
 
 #define CREDENTIAL_INIT { \
 	.helpers = STRING_LIST_INIT_DUP, \
 	.password_expiry_utc = TIME_MAX, \
+	.wwwauth_headers = STRVEC_INIT, \
 }
 
 /* Initialize a credential structure, setting all fields to empty. */
diff --git a/csum-file.c b/csum-file.c
index cce13c0..daf9b06 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -7,9 +7,11 @@
  * files. Useful when you write a file that you want to be
  * able to verify hasn't been messed with afterwards.
  */
-#include "cache.h"
+#include "git-compat-util.h"
 #include "progress.h"
 #include "csum-file.h"
+#include "hash.h"
+#include "wrapper.h"
 
 static void verify_buffer_or_die(struct hashfile *f,
 				 const void *buf,
diff --git a/csum-file.h b/csum-file.h
index 793a59d..bc5bec2 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -1,8 +1,8 @@
 #ifndef CSUM_FILE_H
 #define CSUM_FILE_H
 
-#include "cache.h"
-#include "hash.h"
+#include "hash-ll.h"
+#include "write-or-die.h"
 
 struct progress;
 
diff --git a/daemon.c b/daemon.c
index 0ae7d12..7139cc2 100644
--- a/daemon.c
+++ b/daemon.c
@@ -1,9 +1,16 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "path.h"
 #include "pkt-line.h"
+#include "protocol.h"
 #include "run-command.h"
+#include "setup.h"
 #include "strbuf.h"
 #include "string-list.h"
+#include "wrapper.h"
 
 #ifdef NO_INITGROUPS
 #define initgroups(x, y) (0) /* nothing */
@@ -928,7 +935,7 @@ static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 		add_child(&cld, addr, addrlen);
 }
 
-static void child_handler(int signo)
+static void child_handler(int signo UNUSED)
 {
 	/*
 	 * Otherwise empty handler because systemcalls will get interrupted
diff --git a/date.c b/date.c
index 6f45eeb..619ada5 100644
--- a/date.c
+++ b/date.c
@@ -4,8 +4,11 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
 #include "date.h"
+#include "gettext.h"
+#include "pager.h"
+#include "strbuf.h"
 
 /*
  * This is like mktime, but without normalization of tm_wday and tm_yday.
@@ -1365,20 +1368,6 @@ static timestamp_t approxidate_str(const char *date,
 	return (timestamp_t)update_tm(&tm, &now, 0);
 }
 
-timestamp_t approxidate_relative(const char *date)
-{
-	struct timeval tv;
-	timestamp_t timestamp;
-	int offset;
-	int errors = 0;
-
-	if (!parse_date_basic(date, &timestamp, &offset))
-		return timestamp;
-
-	get_time(&tv);
-	return approxidate_str(date, (const struct timeval *) &tv, &errors);
-}
-
 timestamp_t approxidate_careful(const char *date, int *error_ret)
 {
 	struct timeval tv;
diff --git a/date.h b/date.h
index 5d4eaba..6136212 100644
--- a/date.h
+++ b/date.h
@@ -68,7 +68,6 @@ int parse_expiry_date(const char *date, timestamp_t *timestamp);
 void datestamp(struct strbuf *out);
 #define approxidate(s) approxidate_careful((s), NULL)
 timestamp_t approxidate_careful(const char *, int *);
-timestamp_t approxidate_relative(const char *date);
 int date_overflows(timestamp_t date);
 time_t tm_to_time_t(const struct tm *tm);
 #endif
diff --git a/decorate.c b/decorate.c
index 2036d15..71e79da 100644
--- a/decorate.c
+++ b/decorate.c
@@ -2,7 +2,8 @@
  * decorate.c - decorate a git object with some arbitrary
  * data.
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "hashmap.h"
 #include "object.h"
 #include "decorate.h"
 
diff --git a/delta-islands.c b/delta-islands.c
index afdec0a..c824a5f 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -1,8 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "attr.h"
 #include "object.h"
 #include "blob.h"
 #include "commit.h"
+#include "gettext.h"
+#include "hex.h"
 #include "tag.h"
 #include "tree.h"
 #include "delta.h"
@@ -506,8 +509,9 @@ void propagate_island_marks(struct commit *commit)
 		struct commit_list *p;
 		struct island_bitmap *root_marks = kh_value(island_marks, pos);
 
-		parse_commit(commit);
-		set_island_marks(&get_commit_tree(commit)->object, root_marks);
+		repo_parse_commit(the_repository, commit);
+		set_island_marks(&repo_get_commit_tree(the_repository, commit)->object,
+				 root_marks);
 		for (p = commit->parents; p; p = p->next)
 			set_island_marks(&p->item->object, root_marks);
 	}
diff --git a/detect-compiler b/detect-compiler
index 50087f5..a87650b 100755
--- a/detect-compiler
+++ b/detect-compiler
@@ -17,7 +17,15 @@
 }
 
 get_version() {
-	get_version_line | sed 's/^.* version \([0-9][^ ]*\).*/\1/'
+	# A string that begins with a digit up to the next SP
+	ver=$(get_version_line | sed 's/^.* version \([0-9][^ ]*\).*/\1/')
+
+	# There are known -variant suffixes that do not affect the
+	# meaning of the main version number.  Strip them.
+	ver=${ver%-win32}
+	ver=${ver%-posix}
+
+	echo "$ver"
 }
 
 print_flags() {
diff --git a/diagnose.c b/diagnose.c
index 8f26569..c8c7ebc 100644
--- a/diagnose.c
+++ b/diagnose.c
@@ -1,12 +1,16 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "diagnose.h"
 #include "compat/disk.h"
 #include "archive.h"
 #include "dir.h"
 #include "help.h"
+#include "gettext.h"
+#include "hex.h"
 #include "strvec.h"
 #include "object-store.h"
 #include "packfile.h"
+#include "parse-options.h"
+#include "write-or-die.h"
 
 struct archive_dir {
 	const char *path;
@@ -43,7 +47,8 @@ int option_parse_diagnose(const struct option *opt, const char *arg, int unset)
 	return error(_("invalid --%s value '%s'"), opt->long_name, arg);
 }
 
-static void dir_file_stats_objects(const char *full_path, size_t full_path_len,
+static void dir_file_stats_objects(const char *full_path,
+				   size_t full_path_len UNUSED,
 				   const char *file_name, void *data)
 {
 	struct strbuf *buf = data;
diff --git a/diagnose.h b/diagnose.h
index 7a4951a..f525219 100644
--- a/diagnose.h
+++ b/diagnose.h
@@ -2,7 +2,8 @@
 #define DIAGNOSE_H
 
 #include "strbuf.h"
-#include "parse-options.h"
+
+struct option;
 
 enum diagnose_mode {
 	DIAGNOSE_NONE,
diff --git a/diff-lib.c b/diff-lib.c
index dec040c..60e979d 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -6,11 +6,16 @@
 #include "commit.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "revision.h"
 #include "cache-tree.h"
 #include "unpack-trees.h"
 #include "refs.h"
 #include "submodule.h"
+#include "symlinks.h"
+#include "trace.h"
 #include "dir.h"
 #include "fsmonitor.h"
 #include "commit-reach.h"
@@ -581,7 +586,7 @@ void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb)
 	if (revs->pending.nr == 1) {
 		struct object_id oid;
 
-		if (get_oid("HEAD", &oid))
+		if (repo_get_oid(the_repository, "HEAD", &oid))
 			die(_("unable to get HEAD"));
 
 		mb_child[1] = lookup_commit_reference(the_repository, &oid);
diff --git a/diff-merges.c b/diff-merges.c
index 85cbefa..ec97616 100644
--- a/diff-merges.c
+++ b/diff-merges.c
@@ -1,5 +1,7 @@
+#include "git-compat-util.h"
 #include "diff-merges.h"
 
+#include "gettext.h"
 #include "revision.h"
 
 typedef void (*diff_merges_setup_func_t)(struct rev_info *);
diff --git a/diff-no-index.c b/diff-no-index.c
index 05fafd0..4296940 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -4,16 +4,17 @@
  * Copyright (c) 2008 by Junio C Hamano
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
 #include "color.h"
 #include "commit.h"
 #include "blob.h"
 #include "tag.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "gettext.h"
 #include "revision.h"
 #include "log-tree.h"
-#include "builtin.h"
 #include "parse-options.h"
 #include "string-list.h"
 #include "dir.h"
diff --git a/diff.c b/diff.c
index 469e18a..1cdac6e 100644
--- a/diff.c
+++ b/diff.c
@@ -2,12 +2,19 @@
  * Copyright (C) 2005 Junio C Hamano
  */
 #include "cache.h"
+#include "abspath.h"
+#include "alloc.h"
+#include "base85.h"
 #include "config.h"
+#include "convert.h"
+#include "environment.h"
+#include "gettext.h"
 #include "tempfile.h"
 #include "quote.h"
 #include "diff.h"
 #include "diffcore.h"
 #include "delta.h"
+#include "hex.h"
 #include "xdiff-interface.h"
 #include "color.h"
 #include "attr.h"
@@ -23,12 +30,19 @@
 #include "string-list.h"
 #include "strvec.h"
 #include "graph.h"
+#include "oid-array.h"
 #include "packfile.h"
+#include "pager.h"
 #include "parse-options.h"
 #include "help.h"
 #include "promisor-remote.h"
 #include "dir.h"
+#include "object-file.h"
+#include "object-name.h"
+#include "setup.h"
 #include "strmap.h"
+#include "ws.h"
+#include "wrapper.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
@@ -127,7 +141,7 @@ static int parse_dirstat_params(struct diff_options *options, const char *params
 	int i;
 
 	if (*params_copy)
-		string_list_split_in_place(&params, params_copy, ',', -1);
+		string_list_split_in_place(&params, params_copy, ",", -1);
 	for (i = 0; i < params.nr; i++) {
 		const char *p = params.items[i].string;
 		if (!strcmp(p, "changes")) {
@@ -2993,6 +3007,24 @@ static int dirstat_compare(const void *_a, const void *_b)
 	return strcmp(a->name, b->name);
 }
 
+static void conclude_dirstat(struct diff_options *options,
+			     struct dirstat_dir *dir,
+			     unsigned long changed)
+{
+	struct dirstat_file *to_free = dir->files;
+
+	if (!changed) {
+		/* This can happen even with many files, if everything was renames */
+		;
+	} else {
+		/* Show all directories with more than x% of the changes */
+		QSORT(dir->files, dir->nr, dirstat_compare);
+		gather_dirstat(options, dir, changed, "", 0);
+	}
+
+	free(to_free);
+}
+
 static void show_dirstat(struct diff_options *options)
 {
 	int i;
@@ -3082,13 +3114,7 @@ static void show_dirstat(struct diff_options *options)
 		dir.nr++;
 	}
 
-	/* This can happen even with many files, if everything was renames */
-	if (!changed)
-		return;
-
-	/* Show all directories with more than x% of the changes */
-	QSORT(dir.files, dir.nr, dirstat_compare);
-	gather_dirstat(options, &dir, changed, "", 0);
+	conclude_dirstat(options, &dir, changed);
 }
 
 static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *options)
@@ -3126,13 +3152,7 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o
 		dir.nr++;
 	}
 
-	/* This can happen even with many files, if everything was renames */
-	if (!changed)
-		return;
-
-	/* Show all directories with more than x% of the changes */
-	QSORT(dir.files, dir.nr, dirstat_compare);
-	gather_dirstat(options, &dir, changed, "", 0);
+	conclude_dirstat(options, &dir, changed);
 }
 
 static void free_diffstat_file(struct diffstat_file *f)
@@ -3374,6 +3394,17 @@ void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const
 		options->b_prefix = b;
 }
 
+void diff_set_noprefix(struct diff_options *options)
+{
+	options->a_prefix = options->b_prefix = "";
+}
+
+void diff_set_default_prefix(struct diff_options *options)
+{
+	options->a_prefix = "a/";
+	options->b_prefix = "b/";
+}
+
 struct userdiff_driver *get_textconv(struct repository *r,
 				     struct diff_filespec *one)
 {
@@ -4351,7 +4382,7 @@ static int similarity_index(struct diff_filepair *p)
 static const char *diff_abbrev_oid(const struct object_id *oid, int abbrev)
 {
 	if (startup_info->have_repository)
-		return find_unique_abbrev(oid, abbrev);
+		return repo_find_unique_abbrev(the_repository, oid, abbrev);
 	else {
 		char *hex = oid_to_hex(oid);
 		if (abbrev < 0)
@@ -4674,10 +4705,9 @@ void repo_diff_setup(struct repository *r, struct diff_options *options)
 		options->flags.ignore_untracked_in_submodules = 1;
 
 	if (diff_no_prefix) {
-		options->a_prefix = options->b_prefix = "";
+		diff_set_noprefix(options);
 	} else if (!diff_mnemonic_prefix) {
-		options->a_prefix = "a/";
-		options->b_prefix = "b/";
+		diff_set_default_prefix(options);
 	}
 
 	options->color_moved = diff_color_moved_default;
@@ -4906,6 +4936,7 @@ static int diff_opt_stat(const struct option *opt, const char *value, int unset)
 	} else
 		BUG("%s should not get here", opt->long_name);
 
+	options->output_format &= ~DIFF_FORMAT_NO_OUTPUT;
 	options->output_format |= DIFF_FORMAT_DIFFSTAT;
 	options->stat_name_width = name_width;
 	options->stat_graph_width = graph_width;
@@ -4925,6 +4956,7 @@ static int parse_dirstat_opt(struct diff_options *options, const char *params)
 	 * The caller knows a dirstat-related option is given from the command
 	 * line; allow it to say "return this_function();"
 	 */
+	options->output_format &= ~DIFF_FORMAT_NO_OUTPUT;
 	options->output_format |= DIFF_FORMAT_DIRSTAT;
 	return 1;
 }
@@ -4988,7 +5020,7 @@ static int diff_opt_find_object(const struct option *option,
 	struct object_id oid;
 
 	BUG_ON_OPT_NEG(unset);
-	if (get_oid(arg, &oid))
+	if (repo_get_oid(the_repository, arg, &oid))
 		return error(_("unable to resolve '%s'"), arg);
 
 	if (!opt->objfind)
@@ -5124,6 +5156,7 @@ static int diff_opt_compact_summary(const struct option *opt,
 		options->flags.stat_with_summary = 0;
 	} else {
 		options->flags.stat_with_summary = 1;
+		options->output_format &= ~DIFF_FORMAT_NO_OUTPUT;
 		options->output_format |= DIFF_FORMAT_DIFFSTAT;
 	}
 	return 0;
@@ -5261,8 +5294,18 @@ static int diff_opt_no_prefix(const struct option *opt,
 
 	BUG_ON_OPT_NEG(unset);
 	BUG_ON_OPT_ARG(optarg);
-	options->a_prefix = "";
-	options->b_prefix = "";
+	diff_set_noprefix(options);
+	return 0;
+}
+
+static int diff_opt_default_prefix(const struct option *opt,
+				   const char *optarg, int unset)
+{
+	struct diff_options *options = opt->value;
+
+	BUG_ON_OPT_NEG(unset);
+	BUG_ON_OPT_ARG(optarg);
+	diff_set_default_prefix(options);
 	return 0;
 }
 
@@ -5459,9 +5502,8 @@ struct option *add_diff_options(const struct option *opts,
 		OPT_BITOP('p', "patch", &options->output_format,
 			  N_("generate patch"),
 			  DIFF_FORMAT_PATCH, DIFF_FORMAT_NO_OUTPUT),
-		OPT_BIT_F('s', "no-patch", &options->output_format,
-			  N_("suppress diff output"),
-			  DIFF_FORMAT_NO_OUTPUT, PARSE_OPT_NONEG),
+		OPT_SET_INT('s', "no-patch", &options->output_format,
+			    N_("suppress diff output"), DIFF_FORMAT_NO_OUTPUT),
 		OPT_BITOP('u', NULL, &options->output_format,
 			  N_("generate patch"),
 			  DIFF_FORMAT_PATCH, DIFF_FORMAT_NO_OUTPUT),
@@ -5470,9 +5512,9 @@ struct option *add_diff_options(const struct option *opts,
 			       PARSE_OPT_NONEG | PARSE_OPT_OPTARG, diff_opt_unified),
 		OPT_BOOL('W', "function-context", &options->flags.funccontext,
 			 N_("generate diffs with <n> lines context")),
-		OPT_BIT_F(0, "raw", &options->output_format,
+		OPT_BITOP(0, "raw", &options->output_format,
 			  N_("generate the diff in raw format"),
-			  DIFF_FORMAT_RAW, PARSE_OPT_NONEG),
+			  DIFF_FORMAT_RAW, DIFF_FORMAT_NO_OUTPUT),
 		OPT_BITOP(0, "patch-with-raw", &options->output_format,
 			  N_("synonym for '-p --raw'"),
 			  DIFF_FORMAT_PATCH | DIFF_FORMAT_RAW,
@@ -5481,12 +5523,12 @@ struct option *add_diff_options(const struct option *opts,
 			  N_("synonym for '-p --stat'"),
 			  DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT,
 			  DIFF_FORMAT_NO_OUTPUT),
-		OPT_BIT_F(0, "numstat", &options->output_format,
+		OPT_BITOP(0, "numstat", &options->output_format,
 			  N_("machine friendly --stat"),
-			  DIFF_FORMAT_NUMSTAT, PARSE_OPT_NONEG),
-		OPT_BIT_F(0, "shortstat", &options->output_format,
+			  DIFF_FORMAT_NUMSTAT, DIFF_FORMAT_NO_OUTPUT),
+		OPT_BITOP(0, "shortstat", &options->output_format,
 			  N_("output only the last line of --stat"),
-			  DIFF_FORMAT_SHORTSTAT, PARSE_OPT_NONEG),
+			  DIFF_FORMAT_SHORTSTAT, DIFF_FORMAT_NO_OUTPUT),
 		OPT_CALLBACK_F('X', "dirstat", options, N_("<param1,param2>..."),
 			       N_("output the distribution of relative amount of changes for each sub-directory"),
 			       PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
@@ -5502,9 +5544,9 @@ struct option *add_diff_options(const struct option *opts,
 		OPT_BIT_F(0, "check", &options->output_format,
 			  N_("warn if changes introduce conflict markers or whitespace errors"),
 			  DIFF_FORMAT_CHECKDIFF, PARSE_OPT_NONEG),
-		OPT_BIT_F(0, "summary", &options->output_format,
+		OPT_BITOP(0, "summary", &options->output_format,
 			  N_("condensed summary such as creations, renames and mode changes"),
-			  DIFF_FORMAT_SUMMARY, PARSE_OPT_NONEG),
+			  DIFF_FORMAT_SUMMARY, DIFF_FORMAT_NO_OUTPUT),
 		OPT_BIT_F(0, "name-only", &options->output_format,
 			  N_("show only names of changed files"),
 			  DIFF_FORMAT_NAME, PARSE_OPT_NONEG),
@@ -5555,6 +5597,9 @@ struct option *add_diff_options(const struct option *opts,
 		OPT_CALLBACK_F(0, "no-prefix", options, NULL,
 			       N_("do not show any source or destination prefix"),
 			       PARSE_OPT_NONEG | PARSE_OPT_NOARG, diff_opt_no_prefix),
+		OPT_CALLBACK_F(0, "default-prefix", options, NULL,
+			       N_("use default prefixes a/ and b/"),
+			       PARSE_OPT_NONEG | PARSE_OPT_NOARG, diff_opt_default_prefix),
 		OPT_INTEGER_F(0, "inter-hunk-context", &options->interhunkcontext,
 			      N_("show context between diff hunks up to the specified number of lines"),
 			      PARSE_OPT_NONEG),
@@ -6860,7 +6905,7 @@ void diffcore_std(struct diff_options *options)
 	 * If no prefetching occurs, diffcore_rename() will prefetch if it
 	 * decides that it needs inexact rename detection.
 	 */
-	if (options->repo == the_repository && has_promisor_remote() &&
+	if (options->repo == the_repository && repo_has_promisor_remote(the_repository) &&
 	    (options->output_format & output_formats_to_prefetch ||
 	     options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
 		diff_queued_diff_prefetch(options->repo);
diff --git a/diff.h b/diff.h
index 8d770b1..3a7a9e8 100644
--- a/diff.h
+++ b/diff.h
@@ -4,10 +4,9 @@
 #ifndef DIFF_H
 #define DIFF_H
 
-#include "tree-walk.h"
 #include "pathspec.h"
-#include "object.h"
 #include "oidset.h"
+#include "strbuf.h"
 
 /**
  * The diff API is for programs that compare two sets of files (e.g. two trees,
@@ -71,7 +70,6 @@ struct oid_array;
 struct option;
 struct repository;
 struct rev_info;
-struct strbuf;
 struct userdiff_driver;
 
 typedef int (*pathchange_fn_t)(struct diff_options *options,
@@ -497,6 +495,8 @@ void diff_tree_combined(const struct object_id *oid, const struct oid_array *par
 void diff_tree_combined_merge(const struct commit *commit, struct rev_info *rev);
 
 void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b);
+void diff_set_noprefix(struct diff_options *options);
+void diff_set_default_prefix(struct diff_options *options);
 
 int diff_can_quit_early(struct diff_options *);
 
@@ -535,9 +535,6 @@ int git_diff_basic_config(const char *var, const char *value, void *cb);
 int git_diff_heuristic_config(const char *var, const char *value, void *cb);
 void init_diff_ui_defaults(void);
 int git_diff_ui_config(const char *var, const char *value, void *cb);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define diff_setup(diffopts) repo_diff_setup(the_repository, diffopts)
-#endif
 void repo_diff_setup(struct repository *, struct diff_options *);
 struct option *add_diff_options(const struct option *, struct diff_options *);
 int diff_opt_parse(struct diff_options *, const char **, int, const char *);
@@ -617,7 +614,7 @@ void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc);
 #define DIFF_STATUS_FILTER_BROKEN	'B'
 
 /*
- * This is different from find_unique_abbrev() in that
+ * This is different from repo_find_unique_abbrev() in that
  * it stuffs the result with dots for alignment.
  */
 const char *diff_aligned_abbrev(const struct object_id *sha1, int);
diff --git a/diffcore-break.c b/diffcore-break.c
index 0d4a149..5462420 100644
--- a/diffcore-break.c
+++ b/diffcore-break.c
@@ -65,7 +65,7 @@ static int should_break(struct repository *r,
 	    oideq(&src->oid, &dst->oid))
 		return 0; /* they are the same */
 
-	if (r == the_repository && has_promisor_remote()) {
+	if (r == the_repository && repo_has_promisor_remote(the_repository)) {
 		options.missing_object_cb = diff_queued_diff_prefetch;
 		options.missing_object_data = r;
 	}
diff --git a/diffcore-delta.c b/diffcore-delta.c
index 18d8f76..c30b56e 100644
--- a/diffcore-delta.c
+++ b/diffcore-delta.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "diff.h"
 #include "diffcore.h"
 
diff --git a/diffcore-order.c b/diffcore-order.c
index 19e7331..57ccab2 100644
--- a/diffcore-order.c
+++ b/diffcore-order.c
@@ -1,7 +1,8 @@
 /*
  * Copyright (C) 2005 Junio C Hamano
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
 #include "diff.h"
 #include "diffcore.h"
 
diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
index 03fcbcb..13c98a7 100644
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c
@@ -2,12 +2,12 @@
  * Copyright (C) 2005 Junio C Hamano
  * Copyright (C) 2010 Google Inc.
  */
-#include "cache.h"
+#include "git-compat-util.h"
 #include "diff.h"
 #include "diffcore.h"
 #include "xdiff-interface.h"
 #include "kwset.h"
-#include "commit.h"
+#include "pretty.h"
 #include "quote.h"
 
 typedef int (*pickaxe_fn)(mmfile_t *one, mmfile_t *two,
diff --git a/diffcore-rename.c b/diffcore-rename.c
index c0422d9..8e2e7a3 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -2,14 +2,19 @@
  *
  * Copyright (C) 2005 Junio C Hamano
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "diff.h"
 #include "diffcore.h"
 #include "object-store.h"
 #include "hashmap.h"
+#include "mem-pool.h"
+#include "oid-array.h"
 #include "progress.h"
 #include "promisor-remote.h"
+#include "string-list.h"
 #include "strmap.h"
+#include "trace2.h"
 
 /* Table of rename/copy destinations */
 
@@ -981,7 +986,7 @@ static int find_basename_matches(struct diff_options *options,
 			strintmap_set(&dests, base, i);
 	}
 
-	if (options->repo == the_repository && has_promisor_remote()) {
+	if (options->repo == the_repository && repo_has_promisor_remote(the_repository)) {
 		dpf_options.missing_object_cb = basename_prefetch;
 		dpf_options.missing_object_data = &prefetch_options;
 	}
@@ -1567,7 +1572,7 @@ void diffcore_rename_extended(struct diff_options *options,
 
 	/* Finish setting up dpf_options */
 	prefetch_options.skip_unmodified = skip_unmodified;
-	if (options->repo == the_repository && has_promisor_remote()) {
+	if (options->repo == the_repository && repo_has_promisor_remote(the_repository)) {
 		dpf_options.missing_object_cb = inexact_prefetch;
 		dpf_options.missing_object_data = &prefetch_options;
 	}
diff --git a/diffcore-rotate.c b/diffcore-rotate.c
index 445f060..533986c 100644
--- a/diffcore-rotate.c
+++ b/diffcore-rotate.c
@@ -2,7 +2,8 @@
  * Copyright (C) 2021, Google LLC.
  * Based on diffcore-order.c, which is Copyright (C) 2005, Junio C Hamano
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
 #include "diff.h"
 #include "diffcore.h"
 
diff --git a/diffcore.h b/diffcore.h
index 9b588a1..5ffe4ec 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -4,9 +4,11 @@
 #ifndef DIFFCORE_H
 #define DIFFCORE_H
 
-#include "cache.h"
+#include "hash-ll.h"
 
 struct diff_options;
+struct mem_pool;
+struct oid_array;
 struct repository;
 struct strintmap;
 struct strmap;
diff --git a/dir-iterator.c b/dir-iterator.c
index cedd304..fb7c47f 100644
--- a/dir-iterator.c
+++ b/dir-iterator.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "dir.h"
 #include "iterator.h"
 #include "dir-iterator.h"
diff --git a/dir.c b/dir.c
index 4e99f0c..a7469df 100644
--- a/dir.c
+++ b/dir.c
@@ -5,9 +5,15 @@
  * Copyright (C) Linus Torvalds, 2005-2006
  *		 Junio Hamano, 2005-2006
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
+#include "convert.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "attr.h"
 #include "refs.h"
@@ -17,7 +23,12 @@
 #include "varint.h"
 #include "ewah/ewok.h"
 #include "fsmonitor.h"
+#include "setup.h"
 #include "submodule-config.h"
+#include "symlinks.h"
+#include "trace2.h"
+#include "tree.h"
+#include "wrapper.h"
 
 /*
  * Tells read_directory_recursive how a file or directory should be treated.
@@ -267,7 +278,7 @@ static int do_read_blob(const struct object_id *oid, struct oid_stat *oid_stat,
 	*size_out = 0;
 	*data_out = NULL;
 
-	data = read_object_file(oid, &type, &sz);
+	data = repo_read_object_file(the_repository, oid, &type, &sz);
 	if (!data || type != OBJ_BLOB) {
 		free(data);
 		return -1;
@@ -1190,7 +1201,7 @@ struct pattern_list *add_pattern_list(struct dir_struct *dir,
 	struct pattern_list *pl;
 	struct exclude_list_group *group;
 
-	group = &dir->exclude_list_group[group_type];
+	group = &dir->internal.exclude_list_group[group_type];
 	ALLOC_GROW(group->pl, group->nr + 1, group->alloc);
 	pl = &group->pl[group->nr++];
 	memset(pl, 0, sizeof(*pl));
@@ -1211,7 +1222,7 @@ static void add_patterns_from_file_1(struct dir_struct *dir, const char *fname,
 	 * differently when dir->untracked is non-NULL.
 	 */
 	if (!dir->untracked)
-		dir->unmanaged_exclude_files++;
+		dir->internal.unmanaged_exclude_files++;
 	pl = add_pattern_list(dir, EXC_FILE, fname);
 	if (add_patterns(fname, "", 0, pl, NULL, 0, oid_stat) < 0)
 		die(_("cannot use %s as an exclude file"), fname);
@@ -1219,7 +1230,7 @@ static void add_patterns_from_file_1(struct dir_struct *dir, const char *fname,
 
 void add_patterns_from_file(struct dir_struct *dir, const char *fname)
 {
-	dir->unmanaged_exclude_files++; /* see validate_untracked_cache() */
+	dir->internal.unmanaged_exclude_files++; /* see validate_untracked_cache() */
 	add_patterns_from_file_1(dir, fname, NULL);
 }
 
@@ -1519,7 +1530,7 @@ static struct path_pattern *last_matching_pattern_from_lists(
 	struct exclude_list_group *group;
 	struct path_pattern *pattern;
 	for (i = EXC_CMDL; i <= EXC_FILE; i++) {
-		group = &dir->exclude_list_group[i];
+		group = &dir->internal.exclude_list_group[i];
 		for (j = group->nr - 1; j >= 0; j--) {
 			pattern = last_matching_pattern_from_list(
 				pathname, pathlen, basename, dtype_p,
@@ -1545,20 +1556,20 @@ static void prep_exclude(struct dir_struct *dir,
 	struct untracked_cache_dir *untracked;
 	int current;
 
-	group = &dir->exclude_list_group[EXC_DIRS];
+	group = &dir->internal.exclude_list_group[EXC_DIRS];
 
 	/*
 	 * Pop the exclude lists from the EXCL_DIRS exclude_list_group
 	 * which originate from directories not in the prefix of the
 	 * path being checked.
 	 */
-	while ((stk = dir->exclude_stack) != NULL) {
+	while ((stk = dir->internal.exclude_stack) != NULL) {
 		if (stk->baselen <= baselen &&
-		    !strncmp(dir->basebuf.buf, base, stk->baselen))
+		    !strncmp(dir->internal.basebuf.buf, base, stk->baselen))
 			break;
-		pl = &group->pl[dir->exclude_stack->exclude_ix];
-		dir->exclude_stack = stk->prev;
-		dir->pattern = NULL;
+		pl = &group->pl[dir->internal.exclude_stack->exclude_ix];
+		dir->internal.exclude_stack = stk->prev;
+		dir->internal.pattern = NULL;
 		free((char *)pl->src); /* see strbuf_detach() below */
 		clear_pattern_list(pl);
 		free(stk);
@@ -1566,7 +1577,7 @@ static void prep_exclude(struct dir_struct *dir,
 	}
 
 	/* Skip traversing into sub directories if the parent is excluded */
-	if (dir->pattern)
+	if (dir->internal.pattern)
 		return;
 
 	/*
@@ -1574,12 +1585,12 @@ static void prep_exclude(struct dir_struct *dir,
 	 * memset(dir, 0, sizeof(*dir)) before use. Changing all of
 	 * them seems lots of work for little benefit.
 	 */
-	if (!dir->basebuf.buf)
-		strbuf_init(&dir->basebuf, PATH_MAX);
+	if (!dir->internal.basebuf.buf)
+		strbuf_init(&dir->internal.basebuf, PATH_MAX);
 
 	/* Read from the parent directories and push them down. */
 	current = stk ? stk->baselen : -1;
-	strbuf_setlen(&dir->basebuf, current < 0 ? 0 : current);
+	strbuf_setlen(&dir->internal.basebuf, current < 0 ? 0 : current);
 	if (dir->untracked)
 		untracked = stk ? stk->ucd : dir->untracked->root;
 	else
@@ -1599,32 +1610,33 @@ static void prep_exclude(struct dir_struct *dir,
 				die("oops in prep_exclude");
 			cp++;
 			untracked =
-				lookup_untracked(dir->untracked, untracked,
+				lookup_untracked(dir->untracked,
+						 untracked,
 						 base + current,
 						 cp - base - current);
 		}
-		stk->prev = dir->exclude_stack;
+		stk->prev = dir->internal.exclude_stack;
 		stk->baselen = cp - base;
 		stk->exclude_ix = group->nr;
 		stk->ucd = untracked;
 		pl = add_pattern_list(dir, EXC_DIRS, NULL);
-		strbuf_add(&dir->basebuf, base + current, stk->baselen - current);
-		assert(stk->baselen == dir->basebuf.len);
+		strbuf_add(&dir->internal.basebuf, base + current, stk->baselen - current);
+		assert(stk->baselen == dir->internal.basebuf.len);
 
 		/* Abort if the directory is excluded */
 		if (stk->baselen) {
 			int dt = DT_DIR;
-			dir->basebuf.buf[stk->baselen - 1] = 0;
-			dir->pattern = last_matching_pattern_from_lists(dir,
+			dir->internal.basebuf.buf[stk->baselen - 1] = 0;
+			dir->internal.pattern = last_matching_pattern_from_lists(dir,
 									istate,
-				dir->basebuf.buf, stk->baselen - 1,
-				dir->basebuf.buf + current, &dt);
-			dir->basebuf.buf[stk->baselen - 1] = '/';
-			if (dir->pattern &&
-			    dir->pattern->flags & PATTERN_FLAG_NEGATIVE)
-				dir->pattern = NULL;
-			if (dir->pattern) {
-				dir->exclude_stack = stk;
+				dir->internal.basebuf.buf, stk->baselen - 1,
+				dir->internal.basebuf.buf + current, &dt);
+			dir->internal.basebuf.buf[stk->baselen - 1] = '/';
+			if (dir->internal.pattern &&
+			    dir->internal.pattern->flags & PATTERN_FLAG_NEGATIVE)
+				dir->internal.pattern = NULL;
+			if (dir->internal.pattern) {
+				dir->internal.exclude_stack = stk;
 				return;
 			}
 		}
@@ -1647,15 +1659,15 @@ static void prep_exclude(struct dir_struct *dir,
 		      */
 		     !is_null_oid(&untracked->exclude_oid))) {
 			/*
-			 * dir->basebuf gets reused by the traversal, but we
-			 * need fname to remain unchanged to ensure the src
-			 * member of each struct path_pattern correctly
+			 * dir->internal.basebuf gets reused by the traversal,
+			 * but we need fname to remain unchanged to ensure the
+			 * src member of each struct path_pattern correctly
 			 * back-references its source file.  Other invocations
 			 * of add_pattern_list provide stable strings, so we
 			 * strbuf_detach() and free() here in the caller.
 			 */
 			struct strbuf sb = STRBUF_INIT;
-			strbuf_addbuf(&sb, &dir->basebuf);
+			strbuf_addbuf(&sb, &dir->internal.basebuf);
 			strbuf_addstr(&sb, dir->exclude_per_dir);
 			pl->src = strbuf_detach(&sb, NULL);
 			add_patterns(pl->src, pl->src, stk->baselen, pl, istate,
@@ -1681,10 +1693,10 @@ static void prep_exclude(struct dir_struct *dir,
 			invalidate_gitignore(dir->untracked, untracked);
 			oidcpy(&untracked->exclude_oid, &oid_stat.oid);
 		}
-		dir->exclude_stack = stk;
+		dir->internal.exclude_stack = stk;
 		current = stk->baselen;
 	}
-	strbuf_setlen(&dir->basebuf, baselen);
+	strbuf_setlen(&dir->internal.basebuf, baselen);
 }
 
 /*
@@ -1704,8 +1716,8 @@ struct path_pattern *last_matching_pattern(struct dir_struct *dir,
 
 	prep_exclude(dir, istate, pathname, basename-pathname);
 
-	if (dir->pattern)
-		return dir->pattern;
+	if (dir->internal.pattern)
+		return dir->internal.pattern;
 
 	return last_matching_pattern_from_lists(dir, istate, pathname, pathlen,
 			basename, dtype_p);
@@ -1742,7 +1754,7 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir,
 	if (index_file_exists(istate, pathname, len, ignore_case))
 		return NULL;
 
-	ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
+	ALLOC_GROW(dir->entries, dir->nr+1, dir->internal.alloc);
 	return dir->entries[dir->nr++] = dir_entry_new(pathname, len);
 }
 
@@ -1753,7 +1765,7 @@ struct dir_entry *dir_add_ignored(struct dir_struct *dir,
 	if (!index_name_is_other(istate, pathname, len))
 		return NULL;
 
-	ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc);
+	ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->internal.ignored_alloc);
 	return dir->ignored[dir->ignored_nr++] = dir_entry_new(pathname, len);
 }
 
@@ -2569,7 +2581,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
 
 	if (open_cached_dir(&cdir, dir, untracked, istate, &path, check_only))
 		goto out;
-	dir->visited_directories++;
+	dir->internal.visited_directories++;
 
 	if (untracked)
 		untracked->check_only = !!check_only;
@@ -2578,7 +2590,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
 		/* check how the file or directory should be treated */
 		state = treat_path(dir, untracked, &cdir, istate, &path,
 				   baselen, pathspec);
-		dir->visited_paths++;
+		dir->internal.visited_paths++;
 
 		if (state > dir_state)
 			dir_state = state;
@@ -2586,7 +2598,8 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
 		/* recurse into subdir if instructed by treat_path */
 		if (state == path_recurse) {
 			struct untracked_cache_dir *ud;
-			ud = lookup_untracked(dir->untracked, untracked,
+			ud = lookup_untracked(dir->untracked,
+					      untracked,
 					      path.buf + baselen,
 					      path.len - baselen);
 			subdir_state =
@@ -2846,7 +2859,7 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
 	 * condition also catches running setup_standard_excludes()
 	 * before setting dir->untracked!
 	 */
-	if (dir->unmanaged_exclude_files)
+	if (dir->internal.unmanaged_exclude_files)
 		return NULL;
 
 	/*
@@ -2875,7 +2888,7 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
 	 * EXC_CMDL is not considered in the cache. If people set it,
 	 * skip the cache.
 	 */
-	if (dir->exclude_list_group[EXC_CMDL].nr)
+	if (dir->internal.exclude_list_group[EXC_CMDL].nr)
 		return NULL;
 
 	if (!ident_in_untracked(dir->untracked)) {
@@ -2935,15 +2948,15 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
 
 	/* Validate $GIT_DIR/info/exclude and core.excludesfile */
 	root = dir->untracked->root;
-	if (!oideq(&dir->ss_info_exclude.oid,
+	if (!oideq(&dir->internal.ss_info_exclude.oid,
 		   &dir->untracked->ss_info_exclude.oid)) {
 		invalidate_gitignore(dir->untracked, root);
-		dir->untracked->ss_info_exclude = dir->ss_info_exclude;
+		dir->untracked->ss_info_exclude = dir->internal.ss_info_exclude;
 	}
-	if (!oideq(&dir->ss_excludes_file.oid,
+	if (!oideq(&dir->internal.ss_excludes_file.oid,
 		   &dir->untracked->ss_excludes_file.oid)) {
 		invalidate_gitignore(dir->untracked, root);
-		dir->untracked->ss_excludes_file = dir->ss_excludes_file;
+		dir->untracked->ss_excludes_file = dir->internal.ss_excludes_file;
 	}
 
 	/* Make sure this directory is not dropped out at saving phase */
@@ -2969,9 +2982,9 @@ static void emit_traversal_statistics(struct dir_struct *dir,
 	}
 
 	trace2_data_intmax("read_directory", repo,
-			   "directories-visited", dir->visited_directories);
+			   "directories-visited", dir->internal.visited_directories);
 	trace2_data_intmax("read_directory", repo,
-			   "paths-visited", dir->visited_paths);
+			   "paths-visited", dir->internal.visited_paths);
 
 	if (!dir->untracked)
 		return;
@@ -2993,8 +3006,8 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
 	struct untracked_cache_dir *untracked;
 
 	trace2_region_enter("dir", "read_directory", istate->repo);
-	dir->visited_paths = 0;
-	dir->visited_directories = 0;
+	dir->internal.visited_paths = 0;
+	dir->internal.visited_directories = 0;
 
 	if (has_symlink_leading_path(path, len)) {
 		trace2_region_leave("dir", "read_directory", istate->repo);
@@ -3342,14 +3355,14 @@ void setup_standard_excludes(struct dir_struct *dir)
 		excludes_file = xdg_config_home("ignore");
 	if (excludes_file && !access_or_warn(excludes_file, R_OK, 0))
 		add_patterns_from_file_1(dir, excludes_file,
-					 dir->untracked ? &dir->ss_excludes_file : NULL);
+					 dir->untracked ? &dir->internal.ss_excludes_file : NULL);
 
 	/* per repository user preference */
 	if (startup_info->have_repository) {
 		const char *path = git_path_info_exclude();
 		if (!access_or_warn(path, R_OK, 0))
 			add_patterns_from_file_1(dir, path,
-						 dir->untracked ? &dir->ss_info_exclude : NULL);
+						 dir->untracked ? &dir->internal.ss_info_exclude : NULL);
 	}
 }
 
@@ -3405,7 +3418,7 @@ void dir_clear(struct dir_struct *dir)
 	struct dir_struct new = DIR_INIT;
 
 	for (i = EXC_CMDL; i <= EXC_FILE; i++) {
-		group = &dir->exclude_list_group[i];
+		group = &dir->internal.exclude_list_group[i];
 		for (j = 0; j < group->nr; j++) {
 			pl = &group->pl[j];
 			if (i == EXC_DIRS)
@@ -3422,13 +3435,13 @@ void dir_clear(struct dir_struct *dir)
 	free(dir->ignored);
 	free(dir->entries);
 
-	stk = dir->exclude_stack;
+	stk = dir->internal.exclude_stack;
 	while (stk) {
 		struct exclude_stack *prev = stk->prev;
 		free(stk);
 		stk = prev;
 	}
-	strbuf_release(&dir->basebuf);
+	strbuf_release(&dir->internal.basebuf);
 
 	memcpy(dir, &new, sizeof(*dir));
 }
diff --git a/dir.h b/dir.h
index 8acfc04..79b85a0 100644
--- a/dir.h
+++ b/dir.h
@@ -1,8 +1,9 @@
 #ifndef DIR_H
 #define DIR_H
 
-#include "cache.h"
 #include "hashmap.h"
+#include "pathspec.h"
+#include "statinfo.h"
 #include "strbuf.h"
 
 /**
@@ -212,17 +213,6 @@ struct untracked_cache {
  */
 struct dir_struct {
 
-	/* The number of members in `entries[]` array. */
-	int nr;
-
-	/* Internal use; keeps track of allocation of `entries[]` array.*/
-	int alloc;
-
-	/* The number of members in `ignored[]` array. */
-	int ignored_nr;
-
-	int ignored_alloc;
-
 	/* bit-field of options */
 	enum {
 
@@ -287,60 +277,81 @@ struct dir_struct {
 		DIR_SKIP_NESTED_GIT = 1<<9
 	} flags;
 
+	/* The number of members in `entries[]` array. */
+	int nr; /* output only */
+
+	/* The number of members in `ignored[]` array. */
+	int ignored_nr; /* output only */
+
 	/* An array of `struct dir_entry`, each element of which describes a path. */
-	struct dir_entry **entries;
+	struct dir_entry **entries; /* output only */
 
 	/**
 	 * used for ignored paths with the `DIR_SHOW_IGNORED_TOO` and
 	 * `DIR_COLLECT_IGNORED` flags.
 	 */
-	struct dir_entry **ignored;
+	struct dir_entry **ignored; /* output only */
+
+	/* Enable/update untracked file cache if set */
+	struct untracked_cache *untracked;
 
 	/**
-	 * The name of the file to be read in each directory for excluded files
-	 * (typically `.gitignore`).
+	 * Deprecated: ls-files is the only allowed caller; all other callers
+	 * should leave this as NULL; it pre-dated the
+	 * setup_standard_excludes() mechanism that replaces this.
+	 *
+	 * This field tracks the name of the file to be read in each directory
+	 * for excluded files (typically `.gitignore`).
 	 */
 	const char *exclude_per_dir;
 
-	/*
-	 * We maintain three groups of exclude pattern lists:
-	 *
-	 * EXC_CMDL lists patterns explicitly given on the command line.
-	 * EXC_DIRS lists patterns obtained from per-directory ignore files.
-	 * EXC_FILE lists patterns from fallback ignore files, e.g.
-	 *   - .git/info/exclude
-	 *   - core.excludesfile
-	 *
-	 * Each group contains multiple exclude lists, a single list
-	 * per source.
-	 */
+	struct dir_struct_internal {
+		/* Keeps track of allocation of `entries[]` array.*/
+		int alloc;
+
+		/* Keeps track of allocation of `ignored[]` array. */
+		int ignored_alloc;
+
+		/*
+		 * We maintain three groups of exclude pattern lists:
+		 *
+		 * EXC_CMDL lists patterns explicitly given on the command line.
+		 * EXC_DIRS lists patterns obtained from per-directory ignore
+		 *          files.
+		 * EXC_FILE lists patterns from fallback ignore files, e.g.
+		 *   - .git/info/exclude
+		 *   - core.excludesfile
+		 *
+		 * Each group contains multiple exclude lists, a single list
+		 * per source.
+		 */
 #define EXC_CMDL 0
 #define EXC_DIRS 1
 #define EXC_FILE 2
-	struct exclude_list_group exclude_list_group[3];
+		struct exclude_list_group exclude_list_group[3];
 
-	/*
-	 * Temporary variables which are used during loading of the
-	 * per-directory exclude lists.
-	 *
-	 * exclude_stack points to the top of the exclude_stack, and
-	 * basebuf contains the full path to the current
-	 * (sub)directory in the traversal. Exclude points to the
-	 * matching exclude struct if the directory is excluded.
-	 */
-	struct exclude_stack *exclude_stack;
-	struct path_pattern *pattern;
-	struct strbuf basebuf;
+		/*
+		 * Temporary variables which are used during loading of the
+		 * per-directory exclude lists.
+		 *
+		 * exclude_stack points to the top of the exclude_stack, and
+		 * basebuf contains the full path to the current
+		 * (sub)directory in the traversal. Exclude points to the
+		 * matching exclude struct if the directory is excluded.
+		 */
+		struct exclude_stack *exclude_stack;
+		struct path_pattern *pattern;
+		struct strbuf basebuf;
 
-	/* Enable untracked file cache if set */
-	struct untracked_cache *untracked;
-	struct oid_stat ss_info_exclude;
-	struct oid_stat ss_excludes_file;
-	unsigned unmanaged_exclude_files;
+		/* Additional metadata related to 'untracked' */
+		struct oid_stat ss_info_exclude;
+		struct oid_stat ss_excludes_file;
+		unsigned unmanaged_exclude_files;
 
-	/* Stats about the traversal */
-	unsigned visited_paths;
-	unsigned visited_directories;
+		/* Stats about the traversal */
+		unsigned visited_paths;
+		unsigned visited_directories;
+	} internal;
 };
 
 #define DIR_INIT { 0 }
@@ -363,10 +374,6 @@ int count_slashes(const char *s);
 int simple_length(const char *match);
 int no_wildcard(const char *string);
 char *common_prefix(const struct pathspec *pathspec);
-int match_pathspec(struct index_state *istate,
-		   const struct pathspec *pathspec,
-		   const char *name, int namelen,
-		   int prefix, char *seen, int is_dir);
 int report_path_error(const char *ps_matched, const struct pathspec *pathspec);
 int within_depth(const char *name, int namelen, int depth, int max_depth);
 
@@ -533,15 +540,6 @@ int submodule_path_match(struct index_state *istate,
 			 const char *submodule_name,
 			 char *seen);
 
-static inline int ce_path_match(struct index_state *istate,
-				const struct cache_entry *ce,
-				const struct pathspec *pathspec,
-				char *seen)
-{
-	return match_pathspec(istate, pathspec, ce->name, ce_namelen(ce), 0, seen,
-			      S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode));
-}
-
 static inline int dir_path_match(struct index_state *istate,
 				 const struct dir_entry *ent,
 				 const struct pathspec *pathspec,
@@ -642,4 +640,19 @@ static inline int starts_with_dot_dot_slash_native(const char *const path)
 
 	return path_match_flags(path, what | PATH_MATCH_NATIVE);
 }
+
+#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
+#define DTYPE(de)	((de)->d_type)
+#else
+#undef DT_UNKNOWN
+#undef DT_DIR
+#undef DT_REG
+#undef DT_LNK
+#define DT_UNKNOWN	0
+#define DT_DIR		1
+#define DT_REG		2
+#define DT_LNK		3
+#define DTYPE(de)	DT_UNKNOWN
+#endif
+
 #endif
diff --git a/editor.c b/editor.c
index 008c04f..38c5dbb 100644
--- a/editor.c
+++ b/editor.c
@@ -1,9 +1,17 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "advice.h"
 #include "config.h"
+#include "editor.h"
+#include "environment.h"
+#include "gettext.h"
+#include "pager.h"
+#include "path.h"
 #include "strbuf.h"
 #include "strvec.h"
 #include "run-command.h"
 #include "sigchain.h"
+#include "wrapper.h"
 
 #ifndef DEFAULT_EDITOR
 #define DEFAULT_EDITOR "vi"
@@ -126,3 +134,31 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer,
 {
 	return launch_specified_editor(git_sequence_editor(), path, buffer, env);
 }
+
+int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
+			      const char *const *env)
+{
+	char *path2 = NULL;
+	int fd, res = 0;
+
+	if (!is_absolute_path(path))
+		path = path2 = xstrdup(git_path("%s", path));
+
+	fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+	if (fd < 0)
+		res = error_errno(_("could not open '%s' for writing"), path);
+	else if (write_in_full(fd, buffer->buf, buffer->len) < 0) {
+		res = error_errno(_("could not write to '%s'"), path);
+		close(fd);
+	} else if (close(fd) < 0)
+		res = error_errno(_("could not close '%s'"), path);
+	else {
+		strbuf_reset(buffer);
+		if (launch_editor(path, buffer, env) < 0)
+			res = error_errno(_("could not edit '%s'"), path);
+		unlink(path);
+	}
+
+	free(path2);
+	return res;
+}
diff --git a/editor.h b/editor.h
new file mode 100644
index 0000000..8016bb5
--- /dev/null
+++ b/editor.h
@@ -0,0 +1,34 @@
+#ifndef EDITOR_H
+#define EDITOR_H
+
+struct strbuf;
+
+const char *git_editor(void);
+const char *git_sequence_editor(void);
+int is_terminal_dumb(void);
+
+/**
+ * Launch the user preferred editor to edit a file and fill the buffer
+ * with the file's contents upon the user completing their editing. The
+ * third argument can be used to set the environment which the editor is
+ * run in. If the buffer is NULL the editor is launched as usual but the
+ * file's contents are not read into the buffer upon completion.
+ */
+int launch_editor(const char *path, struct strbuf *buffer,
+		  const char *const *env);
+
+int launch_sequence_editor(const char *path, struct strbuf *buffer,
+			   const char *const *env);
+
+/*
+ * In contrast to `launch_editor()`, this function writes out the contents
+ * of the specified file first, then clears the `buffer`, then launches
+ * the editor and reads back in the file contents into the `buffer`.
+ * Finally, it deletes the temporary file.
+ *
+ * If `path` is relative, it refers to a file in the `.git` directory.
+ */
+int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
+			      const char *const *env);
+
+#endif
diff --git a/entry.c b/entry.c
index 971ab26..91a540b 100644
--- a/entry.c
+++ b/entry.c
@@ -2,12 +2,17 @@
 #include "blob.h"
 #include "object-store.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "streaming.h"
 #include "submodule.h"
+#include "symlinks.h"
 #include "progress.h"
 #include "fsmonitor.h"
 #include "entry.h"
 #include "parallel-checkout.h"
+#include "wrapper.h"
 
 static void create_directories(const char *path, int path_len,
 			       const struct checkout *state)
@@ -86,7 +91,8 @@ void *read_blob_entry(const struct cache_entry *ce, size_t *size)
 {
 	enum object_type type;
 	unsigned long ul;
-	void *blob_data = read_object_file(&ce->oid, &type, &ul);
+	void *blob_data = repo_read_object_file(the_repository, &ce->oid,
+						&type, &ul);
 
 	*size = ul;
 	if (blob_data) {
diff --git a/entry.h b/entry.h
index 2d4fbb8..7329f91 100644
--- a/entry.h
+++ b/entry.h
@@ -1,9 +1,11 @@
 #ifndef ENTRY_H
 #define ENTRY_H
 
-#include "cache.h"
 #include "convert.h"
 
+struct cache_entry;
+struct index_state;
+
 struct checkout {
 	struct index_state *istate;
 	const char *base_dir;
diff --git a/environment.c b/environment.c
index 1ee3686..28d18ea 100644
--- a/environment.c
+++ b/environment.c
@@ -7,19 +7,28 @@
  * even if you might want to know where the git directory etc
  * are.
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
 #include "branch.h"
+#include "convert.h"
 #include "environment.h"
+#include "gettext.h"
 #include "repository.h"
 #include "config.h"
 #include "refs.h"
 #include "fmt-merge-msg.h"
 #include "commit.h"
 #include "strvec.h"
+#include "object-file.h"
 #include "object-store.h"
+#include "replace-object.h"
 #include "tmp-objdir.h"
 #include "chdir-notify.h"
+#include "setup.h"
 #include "shallow.h"
+#include "trace.h"
+#include "wrapper.h"
+#include "write-or-die.h"
 
 int trust_executable_bit = 1;
 int trust_ctime = 1;
@@ -50,7 +59,6 @@ size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
 size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
 size_t delta_base_cache_limit = 96 * 1024 * 1024;
 unsigned long big_file_threshold = 512 * 1024 * 1024;
-int pager_use_color = 1;
 const char *editor_program;
 const char *askpass_program;
 const char *excludes_file;
@@ -59,7 +67,6 @@ int read_replace_refs = 1;
 enum eol core_eol = EOL_UNSET;
 int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
 char *check_roundtrip_encoding = "SHIFT-JIS";
-unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
 enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
 enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
diff --git a/environment.h b/environment.h
index d438b5c..30cb7e0 100644
--- a/environment.h
+++ b/environment.h
@@ -3,10 +3,231 @@
 
 #include "strvec.h"
 
+struct repository;
+
+/*
+ * The character that begins a commented line in user-editable file
+ * that is subject to stripspace.
+ */
+extern char comment_line_char;
+extern int auto_comment_line_char;
+
 /*
  * Wrapper of getenv() that returns a strdup value. This value is kept
  * in argv to be freed later.
  */
 const char *getenv_safe(struct strvec *argv, const char *name);
 
+/* Double-check local_repo_env below if you add to this list. */
+#define GIT_DIR_ENVIRONMENT "GIT_DIR"
+#define GIT_COMMON_DIR_ENVIRONMENT "GIT_COMMON_DIR"
+#define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
+#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
+#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
+#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
+#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
+#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
+#define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE"
+#define GIT_SHALLOW_FILE_ENVIRONMENT "GIT_SHALLOW_FILE"
+#define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIR"
+#define CONFIG_ENVIRONMENT "GIT_CONFIG"
+#define CONFIG_DATA_ENVIRONMENT "GIT_CONFIG_PARAMETERS"
+#define CONFIG_COUNT_ENVIRONMENT "GIT_CONFIG_COUNT"
+#define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
+#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
+#define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
+#define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
+#define GITATTRIBUTES_FILE ".gitattributes"
+#define INFOATTRIBUTES_FILE "info/attributes"
+#define ATTRIBUTE_MACRO_PREFIX "[attr]"
+#define GITMODULES_FILE ".gitmodules"
+#define GITMODULES_INDEX ":.gitmodules"
+#define GITMODULES_HEAD "HEAD:.gitmodules"
+#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
+#define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
+#define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
+#define GIT_NOTES_REWRITE_REF_ENVIRONMENT "GIT_NOTES_REWRITE_REF"
+#define GIT_NOTES_REWRITE_MODE_ENVIRONMENT "GIT_NOTES_REWRITE_MODE"
+#define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS"
+#define GIT_GLOB_PATHSPECS_ENVIRONMENT "GIT_GLOB_PATHSPECS"
+#define GIT_NOGLOB_PATHSPECS_ENVIRONMENT "GIT_NOGLOB_PATHSPECS"
+#define GIT_ICASE_PATHSPECS_ENVIRONMENT "GIT_ICASE_PATHSPECS"
+#define GIT_QUARANTINE_ENVIRONMENT "GIT_QUARANTINE_PATH"
+#define GIT_OPTIONAL_LOCKS_ENVIRONMENT "GIT_OPTIONAL_LOCKS"
+#define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT "GIT_TEXTDOMAINDIR"
+#define GIT_ATTR_SOURCE_ENVIRONMENT "GIT_ATTR_SOURCE"
+
+/*
+ * Environment variable used in handshaking the wire protocol.
+ * Contains a colon ':' separated list of keys with optional values
+ * 'key[=value]'.  Presence of unknown keys and values must be
+ * ignored.
+ */
+#define GIT_PROTOCOL_ENVIRONMENT "GIT_PROTOCOL"
+/* HTTP header used to handshake the wire protocol */
+#define GIT_PROTOCOL_HEADER "Git-Protocol"
+
+/*
+ * This environment variable is expected to contain a boolean indicating
+ * whether we should or should not treat:
+ *
+ *   GIT_DIR=foo.git git ...
+ *
+ * as if GIT_WORK_TREE=. was given. It's not expected that users will make use
+ * of this, but we use it internally to communicate to sub-processes that we
+ * are in a bare repo. If not set, defaults to true.
+ */
+#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
+
+/*
+ * Repository-local GIT_* environment variables; these will be cleared
+ * when git spawns a sub-process that runs inside another repository.
+ * The array is NULL-terminated, which makes it easy to pass in the "env"
+ * parameter of a run-command invocation, or to do a simple walk.
+ */
+extern const char * const local_repo_env[];
+
+void setup_git_env(const char *git_dir);
+
+/*
+ * Returns true iff we have a configured git repository (either via
+ * setup_git_directory, or in the environment via $GIT_DIR).
+ */
+int have_git_dir(void);
+
+extern int is_bare_repository_cfg;
+int is_bare_repository(void);
+extern char *git_work_tree_cfg;
+const char *get_git_dir(void);
+const char *get_git_common_dir(void);
+const char *get_object_directory(void);
+char *get_index_file(void);
+char *get_graft_file(struct repository *r);
+void set_git_dir(const char *path, int make_realpath);
+const char *get_git_namespace(void);
+const char *strip_namespace(const char *namespaced_ref);
+const char *get_git_work_tree(void);
+void set_git_work_tree(const char *tree);
+
+#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
+
+/* Environment bits from configuration mechanism */
+extern int trust_executable_bit;
+extern int trust_ctime;
+extern int check_stat;
+extern int has_symlinks;
+extern int minimum_abbrev, default_abbrev;
+extern int ignore_case;
+extern int assume_unchanged;
+extern int prefer_symlink_refs;
+extern int warn_ambiguous_refs;
+extern int warn_on_object_refname_ambiguity;
+extern char *apply_default_whitespace;
+extern char *apply_default_ignorewhitespace;
+extern const char *git_attributes_file;
+extern const char *git_hooks_path;
+extern int zlib_compression_level;
+extern int pack_compression_level;
+extern size_t packed_git_window_size;
+extern size_t packed_git_limit;
+extern size_t delta_base_cache_limit;
+extern unsigned long big_file_threshold;
+extern unsigned long pack_size_limit_cfg;
+
+/*
+ * Accessors for the core.sharedrepository config which lazy-load the value
+ * from the config (if not already set). The "reset" function can be
+ * used to unset "set" or cached value, meaning that the value will be loaded
+ * fresh from the config file on the next call to get_shared_repository().
+ */
+void set_shared_repository(int value);
+int get_shared_repository(void);
+void reset_shared_repository(void);
+
+extern int core_preload_index;
+extern int precomposed_unicode;
+extern int protect_hfs;
+extern int protect_ntfs;
+
+extern int core_apply_sparse_checkout;
+extern int core_sparse_checkout_cone;
+extern int sparse_expect_files_outside_of_patterns;
+
+/*
+ * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).
+ */
+int use_optional_locks(void);
+
+enum log_refs_config {
+	LOG_REFS_UNSET = -1,
+	LOG_REFS_NONE = 0,
+	LOG_REFS_NORMAL,
+	LOG_REFS_ALWAYS
+};
+extern enum log_refs_config log_all_ref_updates;
+
+enum rebase_setup_type {
+	AUTOREBASE_NEVER = 0,
+	AUTOREBASE_LOCAL,
+	AUTOREBASE_REMOTE,
+	AUTOREBASE_ALWAYS
+};
+
+enum push_default_type {
+	PUSH_DEFAULT_NOTHING = 0,
+	PUSH_DEFAULT_MATCHING,
+	PUSH_DEFAULT_SIMPLE,
+	PUSH_DEFAULT_UPSTREAM,
+	PUSH_DEFAULT_CURRENT,
+	PUSH_DEFAULT_UNSPECIFIED
+};
+
+extern enum rebase_setup_type autorebase;
+extern enum push_default_type push_default;
+
+enum object_creation_mode {
+	OBJECT_CREATION_USES_HARDLINKS = 0,
+	OBJECT_CREATION_USES_RENAMES = 1
+};
+
+extern enum object_creation_mode object_creation_mode;
+
+extern char *notes_ref_name;
+
+extern int grafts_replace_parents;
+
+extern int repository_format_precious_objects;
+extern int repository_format_worktree_config;
+
+/*
+ * Create a temporary file rooted in the object database directory, or
+ * die on failure. The filename is taken from "pattern", which should have the
+ * usual "XXXXXX" trailer, and the resulting filename is written into the
+ * "template" buffer. Returns the open descriptor.
+ */
+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);
+
+/*
+ * Create a pack .keep file named "name" (which should generally be the output
+ * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on
+ * error.
+ */
+int odb_pack_keep(const char *name);
+
+const char *get_log_output_encoding(void);
+const char *get_commit_output_encoding(void);
+
+extern const char *git_commit_encoding;
+extern const char *git_log_output_encoding;
+
+extern const char *editor_program;
+extern const char *askpass_program;
+extern const char *excludes_file;
+
+/*
+ * Should we print an ellipsis after an abbreviated SHA-1 value
+ * when doing diff-raw output or indicating a detached HEAD?
+ */
+int print_sha1_ellipsis(void);
+
 #endif
diff --git a/ewah/bitmap.c b/ewah/bitmap.c
index ac61864..12d6aa3 100644
--- a/ewah/bitmap.c
+++ b/ewah/bitmap.c
@@ -16,7 +16,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "ewok.h"
 
 #define EWAH_MASK(x) ((eword_t)1 << (x % BITS_IN_EWORD))
diff --git a/ewah/ewah_bitmap.c b/ewah/ewah_bitmap.c
index 6fe48d3..c6d4ffc 100644
--- a/ewah/ewah_bitmap.c
+++ b/ewah/ewah_bitmap.c
@@ -17,9 +17,9 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "git-compat-util.h"
+#include "alloc.h"
 #include "ewok.h"
 #include "ewok_rlw.h"
-#include "cache.h"
 
 static inline size_t min_size(size_t a, size_t b)
 {
diff --git a/exec-cmd.c b/exec-cmd.c
index 0232bbc..1e34e48 100644
--- a/exec-cmd.c
+++ b/exec-cmd.c
@@ -1,7 +1,13 @@
 #include "cache.h"
+#include "abspath.h"
+#include "environment.h"
 #include "exec-cmd.h"
+#include "gettext.h"
+#include "path.h"
 #include "quote.h"
 #include "strvec.h"
+#include "trace.h"
+#include "trace2.h"
 
 #if defined(RUNTIME_PREFIX)
 
diff --git a/fetch-pack.c b/fetch-pack.c
index 04016d1..0f71054 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1,6 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "repository.h"
 #include "config.h"
+#include "date.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "refs.h"
 #include "pkt-line.h"
@@ -13,6 +18,7 @@
 #include "remote.h"
 #include "run-command.h"
 #include "connect.h"
+#include "trace2.h"
 #include "transport.h"
 #include "version.h"
 #include "oid-array.h"
@@ -27,6 +33,7 @@
 #include "commit-graph.h"
 #include "sigchain.h"
 #include "mergesort.h"
+#include "wrapper.h"
 
 static int transfer_unpack_limit = -1;
 static int fetch_unpack_limit = -1;
@@ -722,7 +729,7 @@ static void filter_refs(struct fetch_pack_args *args,
 	*refs = newlist;
 }
 
-static void mark_alternate_complete(struct fetch_negotiator *unused,
+static void mark_alternate_complete(struct fetch_negotiator *negotiator UNUSED,
 				    struct object *obj)
 {
 	mark_complete(&obj->oid);
@@ -762,9 +769,9 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
 		if (!commit) {
 			struct object *o;
 
-			if (!has_object_file_with_flags(&ref->old_oid,
-						OBJECT_INFO_QUICK |
-						OBJECT_INFO_SKIP_FETCH_OBJECT))
+			if (!repo_has_object_file_with_flags(the_repository, &ref->old_oid,
+							     OBJECT_INFO_QUICK |
+							     OBJECT_INFO_SKIP_FETCH_OBJECT))
 				continue;
 			o = parse_object(the_repository, &ref->old_oid);
 			if (!o || o->type != OBJ_COMMIT)
@@ -1094,7 +1101,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 	struct ref *ref = copy_ref_list(orig_ref);
 	struct object_id oid;
 	const char *agent_feature;
-	int agent_len;
+	size_t agent_len;
 	struct fetch_negotiator negotiator_alloc;
 	struct fetch_negotiator *negotiator;
 
@@ -1112,7 +1119,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 		agent_supported = 1;
 		if (agent_len)
 			print_verbose(args, _("Server version is %.*s"),
-				      agent_len, agent_feature);
+				      (int)agent_len, agent_feature);
 	}
 
 	if (!server_supports("session-id"))
@@ -1963,7 +1970,7 @@ static void update_shallow(struct fetch_pack_args *args,
 		struct oid_array extra = OID_ARRAY_INIT;
 		struct object_id *oid = si->shallow->oid;
 		for (i = 0; i < si->shallow->nr; i++)
-			if (has_object_file(&oid[i]))
+			if (repo_has_object_file(the_repository, &oid[i]))
 				oid_array_append(&extra, &oid[i]);
 		if (extra.nr) {
 			setup_alternate_shallow(&shallow_lock,
diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
index f48f44f..5af0d47 100644
--- a/fmt-merge-msg.c
+++ b/fmt-merge-msg.c
@@ -1,8 +1,13 @@
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
 #include "refs.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "diff.h"
 #include "diff-merges.h"
+#include "hex.h"
 #include "revision.h"
 #include "tag.h"
 #include "string-list.h"
@@ -17,8 +22,6 @@ static struct string_list suppress_dest_patterns = STRING_LIST_INIT_DUP;
 
 int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 {
-	int status = 0;
-
 	if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) {
 		int is_bool;
 		merge_log_config = git_config_bool_or_int(key, value, &is_bool);
@@ -37,9 +40,6 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 			string_list_append(&suppress_dest_patterns, value);
 		suppress_dest_pattern_seen = 1;
 	} else {
-		status = git_gpg_config(key, value, NULL);
-		if (status)
-			return status;
 		return git_default_config(key, value, cb);
 	}
 	return 0;
@@ -271,9 +271,10 @@ static void record_person_from_buf(int which, struct string_list *people,
 static void record_person(int which, struct string_list *people,
 			  struct commit *commit)
 {
-	const char *buffer = get_commit_buffer(commit, NULL);
+	const char *buffer = repo_get_commit_buffer(the_repository, commit,
+						    NULL);
 	record_person_from_buf(which, people, buffer);
-	unuse_commit_buffer(commit, buffer);
+	repo_unuse_commit_buffer(the_repository, commit, buffer);
 }
 
 static int cmp_string_list_util_as_integral(const void *a_, const void *b_)
@@ -384,7 +385,8 @@ static void shortlog(const char *name,
 		if (subjects.nr > limit)
 			continue;
 
-		format_commit_message(commit, "%s", &sb, &ctx);
+		repo_format_commit_message(the_repository, commit, "%s", &sb,
+					   &ctx);
 		strbuf_ltrim(&sb);
 
 		if (!sb.len)
@@ -519,7 +521,8 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
 		struct object_id *oid = origins.items[i].util;
 		enum object_type type;
 		unsigned long size;
-		char *buf = read_object_file(oid, &type, &size);
+		char *buf = repo_read_object_file(the_repository, oid, &type,
+						  &size);
 		char *origbuf = buf;
 		unsigned long len = size;
 		struct signature_check sigc = { NULL };
@@ -605,7 +608,9 @@ static void find_merge_parents(struct merge_parents *result,
 		 * util field yet.
 		 */
 		obj = parse_object(the_repository, &oid);
-		parent = (struct commit *)peel_to_type(NULL, 0, obj, OBJ_COMMIT);
+		parent = (struct commit *)repo_peel_to_type(the_repository,
+							    NULL, 0, obj,
+							    OBJ_COMMIT);
 		if (!parent)
 			continue;
 		commit_list_insert(parent, &parents);
diff --git a/fsck.c b/fsck.c
index 2b18717..3261ef9 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1,4 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
+#include "date.h"
+#include "hex.h"
 #include "object-store.h"
 #include "repository.h"
 #include "object.h"
@@ -353,7 +356,7 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio
 	int result;
 	const char *name;
 
-	if (parse_commit(commit))
+	if (repo_parse_commit(the_repository, commit))
 		return -1;
 
 	name = fsck_get_object_name(options, &commit->object.oid);
@@ -361,7 +364,7 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio
 		fsck_put_object_name(options, get_commit_tree_oid(commit),
 				     "%s:", name);
 
-	result = options->walk((struct object *)get_commit_tree(commit),
+	result = options->walk((struct object *) repo_get_commit_tree(the_repository, commit),
 			       OBJ_TREE, data, options);
 	if (result < 0)
 		return result;
@@ -1332,7 +1335,7 @@ static int fsck_blobs(struct oidset *blobs_found, struct oidset *blobs_done,
 		if (oidset_contains(blobs_done, oid))
 			continue;
 
-		buf = read_object_file(oid, &type, &size);
+		buf = repo_read_object_file(the_repository, oid, &type, &size);
 		if (!buf) {
 			if (is_promisor_object(oid))
 				continue;
diff --git a/fsck.h b/fsck.h
index 6683308..e17730e 100644
--- a/fsck.h
+++ b/fsck.h
@@ -1,6 +1,7 @@
 #ifndef GIT_FSCK_H
 #define GIT_FSCK_H
 
+#include "object.h"
 #include "oidset.h"
 
 enum fsck_msg_type {
diff --git a/fsmonitor--daemon.h b/fsmonitor--daemon.h
index e24838f..70d776c 100644
--- a/fsmonitor--daemon.h
+++ b/fsmonitor--daemon.h
@@ -3,7 +3,6 @@
 
 #ifdef HAVE_FSMONITOR_DAEMON_BACKEND
 
-#include "cache.h"
 #include "dir.h"
 #include "run-command.h"
 #include "simple-ipc.h"
diff --git a/fsmonitor-ipc.c b/fsmonitor-ipc.c
index 19d772f..6a6a897 100644
--- a/fsmonitor-ipc.c
+++ b/fsmonitor-ipc.c
@@ -1,7 +1,9 @@
 #include "cache.h"
 #include "fsmonitor.h"
+#include "gettext.h"
 #include "simple-ipc.h"
 #include "fsmonitor-ipc.h"
+#include "repository.h"
 #include "run-command.h"
 #include "strbuf.h"
 #include "trace2.h"
diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c
index 899bfe9..b62acf4 100644
--- a/fsmonitor-settings.c
+++ b/fsmonitor-settings.c
@@ -1,5 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "gettext.h"
 #include "repository.h"
 #include "fsmonitor-ipc.h"
 #include "fsmonitor-settings.h"
diff --git a/fsmonitor.c b/fsmonitor.c
index a5b9e75..28c083d 100644
--- a/fsmonitor.c
+++ b/fsmonitor.c
@@ -1,11 +1,13 @@
 #include "cache.h"
 #include "config.h"
 #include "dir.h"
+#include "environment.h"
 #include "ewah/ewok.h"
 #include "fsmonitor.h"
 #include "fsmonitor-ipc.h"
 #include "run-command.h"
 #include "strbuf.h"
+#include "trace2.h"
 
 #define INDEX_EXTENSION_VERSION1	(1)
 #define INDEX_EXTENSION_VERSION2	(2)
diff --git a/fsmonitor.h b/fsmonitor.h
index edf7ce5..c67e0eb 100644
--- a/fsmonitor.h
+++ b/fsmonitor.h
@@ -4,6 +4,7 @@
 #include "cache.h"
 #include "dir.h"
 #include "fsmonitor-settings.h"
+#include "trace.h"
 
 extern struct trace_key trace_fsmonitor;
 
@@ -86,7 +87,7 @@ static inline void mark_fsmonitor_valid(struct index_state *istate, struct cache
 	    !(ce->ce_flags & CE_FSMONITOR_VALID)) {
 		if (S_ISGITLINK(ce->ce_mode))
 			return;
-		istate->cache_changed = 1;
+		istate->cache_changed |= FSMONITOR_CHANGED;
 		ce->ce_flags |= CE_FSMONITOR_VALID;
 		trace_printf_key(&trace_fsmonitor, "mark_fsmonitor_clean '%s'", ce->name);
 	}
diff --git a/gettext.c b/gettext.c
index f139008..f27e944 100644
--- a/gettext.c
+++ b/gettext.c
@@ -2,7 +2,9 @@
  * Copyright (c) 2010 Ævar Arnfjörð Bjarmason
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "environment.h"
 #include "exec-cmd.h"
 #include "gettext.h"
 #include "strbuf.h"
@@ -100,6 +102,8 @@ static void init_gettext_charset(const char *domain)
 		setlocale(LC_CTYPE, "C");
 }
 
+int git_gettext_enabled = 0;
+
 void git_setup_gettext(void)
 {
 	const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);
@@ -119,6 +123,8 @@ void git_setup_gettext(void)
 	init_gettext_charset("git");
 	textdomain("git");
 
+	git_gettext_enabled = 1;
+
 	free(p);
 }
 
diff --git a/gettext.h b/gettext.h
index d209911..484cafa 100644
--- a/gettext.h
+++ b/gettext.h
@@ -29,9 +29,11 @@
 #define FORMAT_PRESERVING(n) __attribute__((format_arg(n)))
 
 #ifndef NO_GETTEXT
+extern int git_gettext_enabled;
 void git_setup_gettext(void);
 int gettext_width(const char *s);
 #else
+#define git_gettext_enabled (0)
 static inline void git_setup_gettext(void)
 {
 }
@@ -45,12 +47,16 @@ static inline FORMAT_PRESERVING(1) const char *_(const char *msgid)
 {
 	if (!*msgid)
 		return "";
+	if (!git_gettext_enabled)
+		return msgid;
 	return gettext(msgid);
 }
 
 static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2)
 const char *Q_(const char *msgid, const char *plu, unsigned long n)
 {
+	if (!git_gettext_enabled)
+		return n == 1 ? msgid : plu;
 	return ngettext(msgid, plu, n);
 }
 
diff --git a/git-compat-util.h b/git-compat-util.h
index 4f0028c..5b2b99c 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -339,6 +339,25 @@ static inline const char *precompose_string_if_needed(const char *in)
 int compat_mkdir_wo_trailing_slash(const char*, mode_t);
 #endif
 
+#ifdef time
+#undef time
+#endif
+static inline time_t git_time(time_t *tloc)
+{
+	struct timeval tv;
+
+	/*
+	 * Avoid time(NULL), which can disagree with gettimeofday(2)
+	 * and filesystem timestamps.
+	 */
+	gettimeofday(&tv, NULL);
+
+	if (tloc)
+		*tloc = tv.tv_sec;
+	return tv.tv_sec;
+}
+#define time git_time
+
 #ifdef NO_STRUCT_ITIMERVAL
 struct itimerval {
 	struct timeval it_interval;
@@ -859,12 +878,6 @@ int git_lstat(const char *, struct stat *);
 #define pread git_pread
 ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
 #endif
-/*
- * Forward decl that will remind us if its twin in cache.h changes.
- * This function is used in compat/pread.c.  But we can't include
- * cache.h there.
- */
-ssize_t read_in_full(int fd, void *buf, size_t count);
 
 #ifdef NO_SETENV
 #define setenv gitsetenv
@@ -1225,6 +1238,7 @@ extern const unsigned char tolower_trans_tbl[256];
 #undef isxdigit
 
 extern const unsigned char sane_ctype[256];
+extern const signed char hexval_table[256];
 #define GIT_SPACE 0x01
 #define GIT_DIGIT 0x02
 #define GIT_ALPHA 0x04
@@ -1287,6 +1301,25 @@ static inline int skip_iprefix(const char *str, const char *prefix,
 	return 0;
 }
 
+/*
+ * Like skip_prefix_mem, but compare case-insensitively. Note that the
+ * comparison is done via tolower(), so it is strictly ASCII (no multi-byte
+ * characters or locale-specific conversions).
+ */
+static inline int skip_iprefix_mem(const char *buf, size_t len,
+				   const char *prefix,
+				   const char **out, size_t *outlen)
+{
+	do {
+		if (!*prefix) {
+			*out = buf;
+			*outlen = len;
+			return 1;
+		}
+	} while (len-- > 0 && tolower(*buf++) == tolower(*prefix++));
+	return 0;
+}
+
 static inline int strtoul_ui(char const *s, int base, unsigned int *result)
 {
 	unsigned long ul;
diff --git a/git-difftool--helper.sh b/git-difftool--helper.sh
index 992124c..e4e820e 100755
--- a/git-difftool--helper.sh
+++ b/git-difftool--helper.sh
@@ -75,6 +75,11 @@
 		merge_tool="$GIT_DIFF_TOOL"
 	else
 		merge_tool="$(get_merge_tool)"
+		subshell_exit_status=$?
+		if test $subshell_exit_status -gt 1
+		then
+			exit $subshell_exit_status
+		fi
 	fi
 fi
 
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index 9f99201..1ff2617 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -97,7 +97,42 @@
 	test "$TOOL_MODE" = merge
 }
 
+get_gui_default () {
+	if diff_mode
+	then
+		GUI_DEFAULT_KEY="difftool.guiDefault"
+	else
+		GUI_DEFAULT_KEY="mergetool.guiDefault"
+	fi
+	GUI_DEFAULT_CONFIG_LCASE=$(git config --default false --get "$GUI_DEFAULT_KEY" | tr 'A-Z' 'a-z')
+	if test "$GUI_DEFAULT_CONFIG_LCASE" = "auto"
+	then
+		if test -n "$DISPLAY"
+		then
+			GUI_DEFAULT=true
+		else
+			GUI_DEFAULT=false
+		fi
+	else
+		GUI_DEFAULT=$(git config --default false --bool --get "$GUI_DEFAULT_KEY")
+		subshell_exit_status=$?
+		if test $subshell_exit_status -ne 0
+		then
+			exit $subshell_exit_status
+		fi
+	fi
+	echo $GUI_DEFAULT
+}
+
 gui_mode () {
+	if test -z "$GIT_MERGETOOL_GUI"
+	then
+		GIT_MERGETOOL_GUI=$(get_gui_default)
+		if test $? -ne 0
+		then
+			exit 2
+		fi
+	fi
 	test "$GIT_MERGETOOL_GUI" = true
 }
 
@@ -467,6 +502,11 @@
 	is_guessed=false
 	# Check if a merge tool has been configured
 	merge_tool=$(get_configured_merge_tool)
+	subshell_exit_status=$?
+	if test $subshell_exit_status -gt "1"
+	then
+		exit $subshell_exit_status
+	fi
 	# Try to guess an appropriate merge tool if no tool has been set.
 	if test -z "$merge_tool"
 	then
diff --git a/git-mergetool.sh b/git-mergetool.sh
index f751d9c..8a92289 100755
--- a/git-mergetool.sh
+++ b/git-mergetool.sh
@@ -451,7 +451,7 @@
 
 main () {
 	prompt=$(git config --bool mergetool.prompt)
-	GIT_MERGETOOL_GUI=false
+	GIT_MERGETOOL_GUI=
 	guessed_merge_tool=false
 	orderfile=
 
@@ -511,9 +511,14 @@
 
 	if test -z "$merge_tool"
 	then
-		if ! merge_tool=$(get_merge_tool)
+		merge_tool=$(get_merge_tool)
+		subshell_exit_status=$?
+		if test $subshell_exit_status = 1
 		then
 			guessed_merge_tool=true
+		elif test $subshell_exit_status -gt 1
+		then
+			exit $subshell_exit_status
 		fi
 	fi
 	merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)"
diff --git a/git-send-email.perl b/git-send-email.perl
index 07f2a0c..affbb88 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -87,8 +87,10 @@
 
   Automating:
     --identity              <str>  * Use the sendemail.<id> options.
-    --to-cmd                <str>  * Email To: via `<str> \$patch_path`
-    --cc-cmd                <str>  * Email Cc: via `<str> \$patch_path`
+    --to-cmd                <str>  * Email To: via `<str> \$patch_path`.
+    --cc-cmd                <str>  * Email Cc: via `<str> \$patch_path`.
+    --header-cmd            <str>  * Add headers via `<str> \$patch_path`.
+    --no-header-cmd                * Disable any header command in use.
     --suppress-cc           <str>  * author, self, sob, cc, cccmd, body, bodycc, misc-by, all.
     --[no-]cc-cover                * Email Cc: addresses in the cover letter.
     --[no-]to-cover                * Email To: addresses in the cover letter.
@@ -202,7 +204,7 @@
 	$author,$sender,$smtp_authpass,$annotate,$compose,$time);
 # Things we either get from config, *or* are overridden on the
 # command-line.
-my ($no_cc, $no_to, $no_bcc, $no_identity);
+my ($no_cc, $no_to, $no_bcc, $no_identity, $no_header_cmd);
 my (@config_to, @getopt_to);
 my (@config_cc, @getopt_cc);
 my (@config_bcc, @getopt_bcc);
@@ -269,7 +271,7 @@
 # Variables with corresponding config settings
 my ($suppress_from, $signed_off_by_cc);
 my ($cover_cc, $cover_to);
-my ($to_cmd, $cc_cmd);
+my ($to_cmd, $cc_cmd, $header_cmd);
 my ($smtp_server, $smtp_server_port, @smtp_server_options);
 my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
 my ($batch_size, $relogin_delay);
@@ -318,6 +320,7 @@
     "tocmd" => \$to_cmd,
     "cc" => \@config_cc,
     "cccmd" => \$cc_cmd,
+    "headercmd" => \$header_cmd,
     "aliasfiletype" => \$aliasfiletype,
     "bcc" => \@config_bcc,
     "suppresscc" => \@suppress_cc,
@@ -519,6 +522,8 @@
 		    "compose" => \$compose,
 		    "quiet" => \$quiet,
 		    "cc-cmd=s" => \$cc_cmd,
+		    "header-cmd=s" => \$header_cmd,
+		    "no-header-cmd" => \$no_header_cmd,
 		    "suppress-from!" => \$suppress_from,
 		    "no-suppress-from" => sub {$suppress_from = 0},
 		    "suppress-cc=s" => \@suppress_cc,
@@ -792,16 +797,46 @@
 				    @rev_list_opts);
 }
 
-@files = handle_backup_files(@files);
+if (defined $sender) {
+	$sender =~ s/^\s+|\s+$//g;
+	($sender) = expand_aliases($sender);
+} else {
+	$sender = $repoauthor->() || $repocommitter->() || '';
+}
+
+# $sender could be an already sanitized address
+# (e.g. sendemail.from could be manually sanitized by user).
+# But it's a no-op to run sanitize_address on an already sanitized address.
+$sender = sanitize_address($sender);
+
+$time = time - scalar $#files;
 
 if ($validate) {
+	# FIFOs can only be read once, exclude them from validation.
+	my @real_files = ();
 	foreach my $f (@files) {
 		unless (-p $f) {
-			validate_patch($f, $target_xfer_encoding);
+			push(@real_files, $f);
 		}
 	}
+
+	# Run the loop once again to avoid gaps in the counter due to FIFO
+	# arguments provided by the user.
+	my $num = 1;
+	my $num_files = scalar @real_files;
+	$ENV{GIT_SENDEMAIL_FILE_TOTAL} = "$num_files";
+	foreach my $r (@real_files) {
+		$ENV{GIT_SENDEMAIL_FILE_COUNTER} = "$num";
+		pre_process_file($r, 1);
+		validate_patch($r, $target_xfer_encoding);
+		$num += 1;
+	}
+	delete $ENV{GIT_SENDEMAIL_FILE_COUNTER};
+	delete $ENV{GIT_SENDEMAIL_FILE_TOTAL};
 }
 
+@files = handle_backup_files(@files);
+
 if (@files) {
 	unless ($quiet) {
 		print $_,"\n" for (@files);
@@ -1050,18 +1085,6 @@
 	}
 }
 
-if (defined $sender) {
-	$sender =~ s/^\s+|\s+$//g;
-	($sender) = expand_aliases($sender);
-} else {
-	$sender = $repoauthor->() || $repocommitter->() || '';
-}
-
-# $sender could be an already sanitized address
-# (e.g. sendemail.from could be manually sanitized by user).
-# But it's a no-op to run sanitize_address on an already sanitized address.
-$sender = sanitize_address($sender);
-
 my $to_whom = __("To whom should the emails be sent (if anyone)?");
 my $prompting = 0;
 if (!@initial_to && !defined $to_cmd) {
@@ -1221,10 +1244,6 @@
 	#print "new message id = $message_id\n"; # Was useful for debugging
 }
 
-
-
-$time = time - scalar $#files;
-
 sub unquote_rfc2047 {
 	local ($_) = @_;
 	my $charset;
@@ -1502,16 +1521,7 @@
 	return File::Spec::Functions::file_name_is_absolute($path);
 }
 
-# Prepares the email, then asks the user what to do.
-#
-# If the user chooses to send the email, it's sent and 1 is returned.
-# If the user chooses not to send the email, 0 is returned.
-# If the user decides they want to make further edits, -1 is returned and the
-# caller is expected to call send_message again after the edits are performed.
-#
-# If an error occurs sending the email, this just dies.
-
-sub send_message {
+sub gen_header {
 	my @recipients = unique_email_list(@to);
 	@cc = (grep { my $cc = extract_valid_address_or_die($_);
 		      not grep { $cc eq $_ || $_ =~ /<\Q${cc}\E>$/ } @recipients
@@ -1537,7 +1547,7 @@
 To: $to${ccline}
 Subject: $subject
 Date: $date
-Message-Id: $message_id
+Message-ID: $message_id
 ";
 	if ($use_xmailer) {
 		$header .= "X-Mailer: git-send-email $gitversion\n";
@@ -1553,6 +1563,22 @@
 	if (@xh) {
 		$header .= join("\n", @xh) . "\n";
 	}
+	my $recipients_ref = \@recipients;
+	return ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header);
+}
+
+# Prepares the email, then asks the user what to do.
+#
+# If the user chooses to send the email, it's sent and 1 is returned.
+# If the user chooses not to send the email, 0 is returned.
+# If the user decides they want to make further edits, -1 is returned and the
+# caller is expected to call send_message again after the edits are performed.
+#
+# If an error occurs sending the email, this just dies.
+
+sub send_message {
+	my ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();
+	my @recipients = @$recipients_ref;
 
 	my @sendmail_parameters = ('-i', @recipients);
 	my $raw_from = $sender;
@@ -1742,11 +1768,8 @@
 $references = $initial_in_reply_to || '';
 $message_num = 0;
 
-# Prepares the email, prompts the user, sends it out
-# Returns 0 if an edit was done and the function should be called again, or 1
-# otherwise.
-sub process_file {
-	my ($t) = @_;
+sub pre_process_file {
+	my ($t, $quiet) = @_;
 
 	open my $fh, "<", $t or die sprintf(__("can't open file %s"), $t);
 
@@ -1765,16 +1788,17 @@
 	$subject = $initial_subject;
 	$message = "";
 	$message_num++;
-	# First unfold multiline header fields
+	undef $message_id;
+	# Retrieve and unfold header fields.
+	my @header_lines = ();
 	while(<$fh>) {
 		last if /^\s*$/;
-		if (/^\s+\S/ and @header) {
-			chomp($header[$#header]);
-			s/^\s+/ /;
-			$header[$#header] .= $_;
-	    } else {
-			push(@header, $_);
-		}
+		push(@header_lines, $_);
+	}
+	@header = unfold_headers(@header_lines);
+	# Add computed headers, if applicable.
+	unless ($no_header_cmd || ! $header_cmd) {
+		push @header, invoke_header_cmd($header_cmd, $t);
 	}
 	# Now parse the header
 	foreach(@header) {
@@ -1832,7 +1856,7 @@
 				$has_mime_version = 1;
 				push @xh, $_;
 			}
-			elsif (/^Message-Id: (.*)/i) {
+			elsif (/^Message-ID: (.*)/i) {
 				$message_id = $1;
 			}
 			elsif (/^Content-Transfer-Encoding: (.*)/i) {
@@ -1900,9 +1924,9 @@
 	}
 	close $fh;
 
-	push @to, recipients_cmd("to-cmd", "to", $to_cmd, $t)
+	push @to, recipients_cmd("to-cmd", "to", $to_cmd, $t, $quiet)
 		if defined $to_cmd;
-	push @cc, recipients_cmd("cc-cmd", "cc", $cc_cmd, $t)
+	push @cc, recipients_cmd("cc-cmd", "cc", $cc_cmd, $t, $quiet)
 		if defined $cc_cmd && !$suppress_cc{'cccmd'};
 
 	if ($broken_encoding{$t} && !$has_content_type) {
@@ -1961,6 +1985,15 @@
 			@initial_to = @to;
 		}
 	}
+}
+
+# Prepares the email, prompts the user, and sends it out
+# Returns 0 if an edit was done and the function should be called again, or 1
+# on the email being successfully sent out.
+sub process_file {
+	my ($t) = @_;
+
+        pre_process_file($t, $quiet);
 
 	my $message_was_sent = send_message();
 	if ($message_was_sent == -1) {
@@ -2006,15 +2039,64 @@
 	}
 }
 
+# Execute a command and return its output lines as an array.  Blank
+# lines which do not appear at the end of the output are reported as
+# errors.
+sub execute_cmd {
+	my ($prefix, $cmd, $file) = @_;
+	my @lines = ();
+	my $seen_blank_line = 0;
+	open my $fh, "-|", "$cmd \Q$file\E"
+		or die sprintf(__("(%s) Could not execute '%s'"), $prefix, $cmd);
+	while (my $line = <$fh>) {
+		die sprintf(__("(%s) Malformed output from '%s'"), $prefix, $cmd)
+		    if $seen_blank_line;
+		if ($line =~ /^$/) {
+			$seen_blank_line = $line =~ /^$/;
+			next;
+		}
+		push @lines, $line;
+	}
+	close $fh
+	    or die sprintf(__("(%s) failed to close pipe to '%s'"), $prefix, $cmd);
+	return @lines;
+}
+
+# Process headers lines, unfolding multiline headers as defined by RFC
+# 2822.
+sub unfold_headers {
+	my @headers;
+	foreach(@_) {
+		last if /^\s*$/;
+		if (/^\s+\S/ and @headers) {
+			chomp($headers[$#headers]);
+			s/^\s+/ /;
+			$headers[$#headers] .= $_;
+		} else {
+			push(@headers, $_);
+		}
+	}
+	return @headers;
+}
+
+# Invoke the provided CMD with FILE as an argument, which should
+# output RFC 2822 email headers. Fold multiline headers and return the
+# headers as an array.
+sub invoke_header_cmd {
+	my ($cmd, $file) = @_;
+	my @lines = execute_cmd("header-cmd", $header_cmd, $file);
+	return unfold_headers(@lines);
+}
+
 # Execute a command (e.g. $to_cmd) to get a list of email addresses
 # and return a results array
 sub recipients_cmd {
-	my ($prefix, $what, $cmd, $file) = @_;
-
+	my ($prefix, $what, $cmd, $file, $quiet) = @_;
+	my @lines = ();
 	my @addresses = ();
-	open my $fh, "-|", "$cmd \Q$file\E"
-	    or die sprintf(__("(%s) Could not execute '%s'"), $prefix, $cmd);
-	while (my $address = <$fh>) {
+
+	@lines = execute_cmd($prefix, $cmd, $file);
+	for my $address (@lines) {
 		$address =~ s/^\s*//g;
 		$address =~ s/\s*$//g;
 		$address = sanitize_address($address);
@@ -2023,8 +2105,6 @@
 		printf(__("(%s) Adding %s: %s from: '%s'\n"),
 		       $prefix, $what, $address, $cmd) unless $quiet;
 		}
-	close $fh
-	    or die sprintf(__("(%s) failed to close pipe to '%s'"), $prefix, $cmd);
 	return @addresses;
 }
 
@@ -2095,10 +2175,21 @@
 			chdir($repo->wc_path() or $repo->repo_path())
 				or die("chdir: $!");
 			local $ENV{"GIT_DIR"} = $repo->repo_path();
+
+			my ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();
+
+			require File::Temp;
+			my ($header_filehandle, $header_filename) = File::Temp::tempfile(
+                            TEMPLATE => ".gitsendemail.header.XXXXXX",
+                            DIR => $repo->repo_path(),
+                            UNLINK => 1,
+                        );
+			print $header_filehandle $header;
+
 			my @cmd = ("git", "hook", "run", "--ignore-missing",
 				    $hook_name, "--");
-			my @cmd_msg = (@cmd, "<patch>");
-			my @cmd_run = (@cmd, $target);
+			my @cmd_msg = (@cmd, "<patch>", "<header>");
+			my @cmd_run = (@cmd, $target, $header_filename);
 			$hook_error = system_or_msg(\@cmd_run, undef, "@cmd_msg");
 			chdir($cwd_save) or die("chdir: $!");
 		}
diff --git a/zlib.c b/git-zlib.c
similarity index 98%
rename from zlib.c
rename to git-zlib.c
index d594cba..d43bbeb 100644
--- a/zlib.c
+++ b/git-zlib.c
@@ -2,7 +2,8 @@
  * zlib wrappers to make sure we don't silently miss errors
  * at init time.
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "git-zlib.h"
 
 static const char *zerr_to_string(int status)
 {
diff --git a/git-zlib.h b/git-zlib.h
new file mode 100644
index 0000000..d8a670a
--- /dev/null
+++ b/git-zlib.h
@@ -0,0 +1,28 @@
+#ifndef GIT_ZLIB_H
+#define GIT_ZLIB_H
+
+typedef struct git_zstream {
+	z_stream z;
+	unsigned long avail_in;
+	unsigned long avail_out;
+	unsigned long total_in;
+	unsigned long total_out;
+	unsigned char *next_in;
+	unsigned char *next_out;
+} git_zstream;
+
+void git_inflate_init(git_zstream *);
+void git_inflate_init_gzip_only(git_zstream *);
+void git_inflate_end(git_zstream *);
+int git_inflate(git_zstream *, int flush);
+
+void git_deflate_init(git_zstream *, int level);
+void git_deflate_init_gzip(git_zstream *, int level);
+void git_deflate_init_raw(git_zstream *, int level);
+void git_deflate_end(git_zstream *);
+int git_deflate_abort(git_zstream *);
+int git_deflate_end_gently(git_zstream *);
+int git_deflate(git_zstream *, int flush);
+unsigned long git_deflate_bound(git_zstream *, unsigned long);
+
+#endif /* GIT_ZLIB_H */
diff --git a/git.c b/git.c
index 6171fd6..2f42da2 100644
--- a/git.c
+++ b/git.c
@@ -1,10 +1,18 @@
 #include "builtin.h"
 #include "config.h"
+#include "environment.h"
 #include "exec-cmd.h"
+#include "gettext.h"
 #include "help.h"
+#include "pager.h"
 #include "run-command.h"
 #include "alias.h"
+#include "replace-object.h"
+#include "setup.h"
+#include "attr.h"
 #include "shallow.h"
+#include "trace.h"
+#include "trace2.h"
 
 #define RUN_SETUP		(1<<0)
 #define RUN_SETUP_GENTLY	(1<<1)
@@ -307,6 +315,21 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 			} else {
 				exit(list_cmds(cmd));
 			}
+		} else if (!strcmp(cmd, "--attr-source")) {
+			if (*argc < 2) {
+				fprintf(stderr, _("no attribute source given for --attr-source\n" ));
+				usage(git_usage_string);
+			}
+			setenv(GIT_ATTR_SOURCE_ENVIRONMENT, (*argv)[1], 1);
+			if (envchanged)
+				*envchanged = 1;
+			(*argv)++;
+			(*argc)--;
+		} else if (skip_prefix(cmd, "--attr-source=", &cmd)) {
+			set_git_attr_source(cmd);
+			setenv(GIT_ATTR_SOURCE_ENVIRONMENT, cmd, 1);
+			if (envchanged)
+				*envchanged = 1;
 		} else {
 			fprintf(stderr, _("unknown option: %s\n"), cmd);
 			usage(git_usage_string);
@@ -583,7 +606,7 @@ static struct cmd_struct commands[] = {
 	{ "show-branch", cmd_show_branch, RUN_SETUP },
 	{ "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 },
+	{ "sparse-checkout", cmd_sparse_checkout, RUN_SETUP },
 	{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
 	{ "stash", cmd_stash, RUN_SETUP | NEED_WORK_TREE },
 	{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 0ae7d68..df3ba2e 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -353,6 +353,16 @@
     return $ret
 }
 
+# Escapes a list of filter paths to be passed to git log via stdin. Note that
+# paths must not be quoted.
+proc escape_filter_paths {paths} {
+	set escaped [list]
+	foreach path $paths {
+		lappend escaped [string map {\\ \\\\ "\ " "\\\ "} $path]
+	}
+	return $escaped
+}
+
 # Start off a git log process and arrange to read its output
 proc start_rev_list {view} {
     global startmsecs commitidx viewcomplete curview
@@ -405,14 +415,17 @@
         if {$revs eq {}} {
             return 0
         }
-        set args [concat $vflags($view) $revs]
+        set args $vflags($view)
     } else {
+        set revs {}
         set args $vorigargs($view)
     }
 
     if {[catch {
         set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
-                        --parents --boundary $args "--" $files] r]
+                        --parents --boundary $args --stdin \
+                        "<<[join [concat $revs "--" \
+                                [escape_filter_paths $files]] "\\n"]"] r]
     } err]} {
         error_popup "[mc "Error executing git log:"] $err"
         return 0
@@ -554,13 +567,20 @@
             set revs $newrevs
             set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
         }
-        set args [concat $vflags($view) $revs --not $oldpos]
+        set args $vflags($view)
+        foreach r $oldpos {
+                lappend revs "^$r"
+        }
     } else {
+        set revs {}
         set args $vorigargs($view)
     }
     if {[catch {
         set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
-                        --parents --boundary $args "--" $vfilelimit($view)] r]
+                        --parents --boundary $args --stdin \
+                        "<<[join [concat $revs "--" \
+                                [escape_filter_paths \
+                                        $vfilelimit($view)]] "\\n"]"] r]
     } err]} {
         error_popup "[mc "Error executing git log:"] $err"
         return
@@ -10231,10 +10251,16 @@
             foreach id $seeds {
                 lappend ids "^$id"
             }
+            lappend ids "--"
         }
     }
     if {$ids ne {}} {
-        set fd [open [concat $cmd $ids] r]
+        if {$ids eq "--all"} {
+            set cmd [concat $cmd "--all"]
+        } else {
+            set cmd [concat $cmd --stdin "<<[join $ids "\\n"]"]
+        }
+        set fd [open $cmd r]
         fconfigure $fd -blocking 0
         incr allcommits
         nowbusy allcommits
diff --git a/gpg-interface.c b/gpg-interface.c
index 5cd66d3..19a3471 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -1,13 +1,30 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "commit.h"
 #include "config.h"
+#include "date.h"
+#include "gettext.h"
 #include "run-command.h"
 #include "strbuf.h"
 #include "dir.h"
+#include "ident.h"
 #include "gpg-interface.h"
+#include "path.h"
 #include "sigchain.h"
 #include "tempfile.h"
 #include "alias.h"
+#include "wrapper.h"
+
+static int git_gpg_config(const char *, const char *, void *);
+
+static void gpg_interface_lazy_init(void)
+{
+	static int done;
+
+	if (done)
+		return;
+	done = 1;
+	git_config(git_gpg_config, NULL);
+}
 
 static char *configured_signing_key;
 static const char *ssh_default_key_command, *ssh_allowed_signers, *ssh_revocation_file;
@@ -632,8 +649,10 @@ int check_signature(struct signature_check *sigc,
 	struct gpg_format *fmt;
 	int status;
 
+	gpg_interface_lazy_init();
+
 	sigc->result = 'N';
-	sigc->trust_level = -1;
+	sigc->trust_level = TRUST_UNDEFINED;
 
 	fmt = get_format_by_sig(signature);
 	if (!fmt)
@@ -695,11 +714,13 @@ int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct
 
 void set_signing_key(const char *key)
 {
+	gpg_interface_lazy_init();
+
 	free(configured_signing_key);
 	configured_signing_key = xstrdup(key);
 }
 
-int git_gpg_config(const char *var, const char *value, void *cb UNUSED)
+static int git_gpg_config(const char *var, const char *value, void *cb UNUSED)
 {
 	struct gpg_format *fmt = NULL;
 	char *fmtname = NULL;
@@ -888,6 +909,8 @@ static const char *get_ssh_key_id(void) {
 /* Returns a textual but unique representation of the signing key */
 const char *get_signing_key_id(void)
 {
+	gpg_interface_lazy_init();
+
 	if (use_format->get_key_id) {
 		return use_format->get_key_id();
 	}
@@ -898,6 +921,8 @@ const char *get_signing_key_id(void)
 
 const char *get_signing_key(void)
 {
+	gpg_interface_lazy_init();
+
 	if (configured_signing_key)
 		return configured_signing_key;
 	if (use_format->get_default_key) {
@@ -923,6 +948,8 @@ const char *gpg_trust_level_to_str(enum signature_trust_level level)
 
 int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key)
 {
+	gpg_interface_lazy_init();
+
 	return use_format->sign_buffer(buffer, signature, signing_key);
 }
 
@@ -1025,7 +1052,7 @@ static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
 		ssh_signing_key_file = strbuf_detach(&key_file->filename, NULL);
 	} else {
 		/* We assume a file */
-		ssh_signing_key_file = expand_user_path(signing_key, 1);
+		ssh_signing_key_file = interpolate_path(signing_key, 1);
 	}
 
 	buffer_file = mks_tempfile_t(".git_signing_buffer_tmpXXXXXX");
diff --git a/gpg-interface.h b/gpg-interface.h
index 8a9ef41..143cdc1 100644
--- a/gpg-interface.h
+++ b/gpg-interface.h
@@ -79,7 +79,6 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
  */
 const char *gpg_trust_level_to_str(enum signature_trust_level level);
 
-int git_gpg_config(const char *, const char *, void *);
 void set_signing_key(const char *);
 const char *get_signing_key(void);
 
diff --git a/graph.c b/graph.c
index 568b6e7..2a9dc43 100644
--- a/graph.c
+++ b/graph.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
 #include "config.h"
 #include "commit.h"
 #include "color.h"
diff --git a/grep.c b/grep.c
index cee44a7..f00986c 100644
--- a/grep.c
+++ b/grep.c
@@ -1,7 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "gettext.h"
 #include "grep.h"
+#include "hex.h"
 #include "object-store.h"
+#include "pretty.h"
 #include "userdiff.h"
 #include "xdiff-interface.h"
 #include "diff.h"
@@ -9,6 +12,7 @@
 #include "commit.h"
 #include "quote.h"
 #include "help.h"
+#include "wrapper.h"
 
 static int grep_source_load(struct grep_source *gs);
 static int grep_source_is_binary(struct grep_source *gs,
@@ -320,6 +324,15 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
 	if (!opt->ignore_locale && is_utf8_locale() && !literal)
 		options |= (PCRE2_UTF | PCRE2_UCP | PCRE2_MATCH_INVALID_UTF);
 
+#ifndef GIT_PCRE2_VERSION_10_35_OR_HIGHER
+	/*
+	 * Work around a JIT bug related to invalid Unicode character handling
+	 * fixed in 10.35:
+	 * https://github.com/PCRE2Project/pcre2/commit/c21bd977547d
+	 */
+	options &= ~PCRE2_UCP;
+#endif
+
 #ifndef GIT_PCRE2_VERSION_10_36_OR_HIGHER
 	/* Work around https://bugs.exim.org/show_bug.cgi?id=2642 fixed in 10.36 */
 	if (PCRE2_MATCH_INVALID_UTF && options & (PCRE2_UTF | PCRE2_CASELESS))
diff --git a/grep.h b/grep.h
index 6075f99..c59592e 100644
--- a/grep.h
+++ b/grep.h
@@ -7,6 +7,9 @@
 #if (PCRE2_MAJOR >= 10 && PCRE2_MINOR >= 36) || PCRE2_MAJOR >= 11
 #define GIT_PCRE2_VERSION_10_36_OR_HIGHER
 #endif
+#if (PCRE2_MAJOR >= 10 && PCRE2_MINOR >= 35) || PCRE2_MAJOR >= 11
+#define GIT_PCRE2_VERSION_10_35_OR_HIGHER
+#endif
 #if (PCRE2_MAJOR >= 10 && PCRE2_MINOR >= 34) || PCRE2_MAJOR >= 11
 #define GIT_PCRE2_VERSION_10_34_OR_HIGHER
 #endif
diff --git a/hash-ll.h b/hash-ll.h
new file mode 100644
index 0000000..8050925
--- /dev/null
+++ b/hash-ll.h
@@ -0,0 +1,276 @@
+#ifndef HASH_LL_H
+#define HASH_LL_H
+
+#if defined(SHA1_APPLE)
+#include <CommonCrypto/CommonDigest.h>
+#elif defined(SHA1_OPENSSL)
+#include <openssl/sha.h>
+#elif defined(SHA1_DC)
+#include "sha1dc_git.h"
+#else /* SHA1_BLK */
+#include "block-sha1/sha1.h"
+#endif
+
+#if defined(SHA256_NETTLE)
+#include "sha256/nettle.h"
+#elif defined(SHA256_GCRYPT)
+#define SHA256_NEEDS_CLONE_HELPER
+#include "sha256/gcrypt.h"
+#elif defined(SHA256_OPENSSL)
+#include <openssl/sha.h>
+#else
+#include "sha256/block/sha256.h"
+#endif
+
+#ifndef platform_SHA_CTX
+/*
+ * platform's underlying implementation of SHA-1; could be OpenSSL,
+ * blk_SHA, Apple CommonCrypto, etc...  Note that the relevant
+ * SHA-1 header may have already defined platform_SHA_CTX for our
+ * own implementations like block-sha1, so we list
+ * the default for OpenSSL compatible SHA-1 implementations here.
+ */
+#define platform_SHA_CTX	SHA_CTX
+#define platform_SHA1_Init	SHA1_Init
+#define platform_SHA1_Update	SHA1_Update
+#define platform_SHA1_Final    	SHA1_Final
+#endif
+
+#define git_SHA_CTX		platform_SHA_CTX
+#define git_SHA1_Init		platform_SHA1_Init
+#define git_SHA1_Update		platform_SHA1_Update
+#define git_SHA1_Final		platform_SHA1_Final
+
+#ifndef platform_SHA256_CTX
+#define platform_SHA256_CTX	SHA256_CTX
+#define platform_SHA256_Init	SHA256_Init
+#define platform_SHA256_Update	SHA256_Update
+#define platform_SHA256_Final	SHA256_Final
+#endif
+
+#define git_SHA256_CTX		platform_SHA256_CTX
+#define git_SHA256_Init		platform_SHA256_Init
+#define git_SHA256_Update	platform_SHA256_Update
+#define git_SHA256_Final	platform_SHA256_Final
+
+#ifdef platform_SHA256_Clone
+#define git_SHA256_Clone	platform_SHA256_Clone
+#endif
+
+#ifdef SHA1_MAX_BLOCK_SIZE
+#include "compat/sha1-chunked.h"
+#undef git_SHA1_Update
+#define git_SHA1_Update		git_SHA1_Update_Chunked
+#endif
+
+static inline void git_SHA1_Clone(git_SHA_CTX *dst, const git_SHA_CTX *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+#ifndef SHA256_NEEDS_CLONE_HELPER
+static inline void git_SHA256_Clone(git_SHA256_CTX *dst, const git_SHA256_CTX *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+#endif
+
+/*
+ * Note that these constants are suitable for indexing the hash_algos array and
+ * comparing against each other, but are otherwise arbitrary, so they should not
+ * be exposed to the user or serialized to disk.  To know whether a
+ * git_hash_algo struct points to some usable hash function, test the format_id
+ * field for being non-zero.  Use the name field for user-visible situations and
+ * the format_id field for fixed-length fields on disk.
+ */
+/* An unknown hash function. */
+#define GIT_HASH_UNKNOWN 0
+/* SHA-1 */
+#define GIT_HASH_SHA1 1
+/* SHA-256  */
+#define GIT_HASH_SHA256 2
+/* Number of algorithms supported (including unknown). */
+#define GIT_HASH_NALGOS (GIT_HASH_SHA256 + 1)
+
+/* "sha1", big-endian */
+#define GIT_SHA1_FORMAT_ID 0x73686131
+
+/* The length in bytes and in hex digits of an object name (SHA-1 value). */
+#define GIT_SHA1_RAWSZ 20
+#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
+/* The block size of SHA-1. */
+#define GIT_SHA1_BLKSZ 64
+
+/* "s256", big-endian */
+#define GIT_SHA256_FORMAT_ID 0x73323536
+
+/* The length in bytes and in hex digits of an object name (SHA-256 value). */
+#define GIT_SHA256_RAWSZ 32
+#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ)
+/* The block size of SHA-256. */
+#define GIT_SHA256_BLKSZ 64
+
+/* The length in byte and in hex digits of the largest possible hash value. */
+#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ
+#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ
+/* The largest possible block size for any supported hash. */
+#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ
+
+struct object_id {
+	unsigned char hash[GIT_MAX_RAWSZ];
+	int algo;	/* XXX requires 4-byte alignment */
+};
+
+#define GET_OID_QUIETLY           01
+#define GET_OID_COMMIT            02
+#define GET_OID_COMMITTISH        04
+#define GET_OID_TREE             010
+#define GET_OID_TREEISH          020
+#define GET_OID_BLOB             040
+#define GET_OID_FOLLOW_SYMLINKS 0100
+#define GET_OID_RECORD_PATH     0200
+#define GET_OID_ONLY_TO_DIE    04000
+#define GET_OID_REQUIRE_PATH  010000
+
+#define GET_OID_DISAMBIGUATORS \
+	(GET_OID_COMMIT | GET_OID_COMMITTISH | \
+	GET_OID_TREE | GET_OID_TREEISH | \
+	GET_OID_BLOB)
+
+enum get_oid_result {
+	FOUND = 0,
+	MISSING_OBJECT = -1, /* The requested object is missing */
+	SHORT_NAME_AMBIGUOUS = -2,
+	/* The following only apply when symlinks are followed */
+	DANGLING_SYMLINK = -4, /*
+				* The initial symlink is there, but
+				* (transitively) points to a missing
+				* in-tree file
+				*/
+	SYMLINK_LOOP = -5,
+	NOT_DIR = -6, /*
+		       * Somewhere along the symlink chain, a path is
+		       * requested which contains a file as a
+		       * non-final element.
+		       */
+};
+
+/* A suitably aligned type for stack allocations of hash contexts. */
+union git_hash_ctx {
+	git_SHA_CTX sha1;
+	git_SHA256_CTX sha256;
+};
+typedef union git_hash_ctx git_hash_ctx;
+
+typedef void (*git_hash_init_fn)(git_hash_ctx *ctx);
+typedef void (*git_hash_clone_fn)(git_hash_ctx *dst, const git_hash_ctx *src);
+typedef void (*git_hash_update_fn)(git_hash_ctx *ctx, const void *in, size_t len);
+typedef void (*git_hash_final_fn)(unsigned char *hash, git_hash_ctx *ctx);
+typedef void (*git_hash_final_oid_fn)(struct object_id *oid, git_hash_ctx *ctx);
+
+struct git_hash_algo {
+	/*
+	 * The name of the algorithm, as appears in the config file and in
+	 * messages.
+	 */
+	const char *name;
+
+	/* A four-byte version identifier, used in pack indices. */
+	uint32_t format_id;
+
+	/* The length of the hash in binary. */
+	size_t rawsz;
+
+	/* The length of the hash in hex characters. */
+	size_t hexsz;
+
+	/* The block size of the hash. */
+	size_t blksz;
+
+	/* The hash initialization function. */
+	git_hash_init_fn init_fn;
+
+	/* The hash context cloning function. */
+	git_hash_clone_fn clone_fn;
+
+	/* The hash update function. */
+	git_hash_update_fn update_fn;
+
+	/* The hash finalization function. */
+	git_hash_final_fn final_fn;
+
+	/* The hash finalization function for object IDs. */
+	git_hash_final_oid_fn final_oid_fn;
+
+	/* The OID of the empty tree. */
+	const struct object_id *empty_tree;
+
+	/* The OID of the empty blob. */
+	const struct object_id *empty_blob;
+
+	/* The all-zeros OID. */
+	const struct object_id *null_oid;
+};
+extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];
+
+/*
+ * Return a GIT_HASH_* constant based on the name.  Returns GIT_HASH_UNKNOWN if
+ * the name doesn't match a known algorithm.
+ */
+int hash_algo_by_name(const char *name);
+/* Identical, except based on the format ID. */
+int hash_algo_by_id(uint32_t format_id);
+/* Identical, except based on the length. */
+int hash_algo_by_length(int len);
+/* Identical, except for a pointer to struct git_hash_algo. */
+static inline int hash_algo_by_ptr(const struct git_hash_algo *p)
+{
+	return p - hash_algos;
+}
+
+const struct object_id *null_oid(void);
+
+static inline int hashcmp_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
+{
+	/*
+	 * Teach the compiler that there are only two possibilities of hash size
+	 * here, so that it can optimize for this case as much as possible.
+	 */
+	if (algop->rawsz == GIT_MAX_RAWSZ)
+		return memcmp(sha1, sha2, GIT_MAX_RAWSZ);
+	return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
+}
+
+static inline int hasheq_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
+{
+	/*
+	 * We write this here instead of deferring to hashcmp so that the
+	 * compiler can properly inline it and avoid calling memcmp.
+	 */
+	if (algop->rawsz == GIT_MAX_RAWSZ)
+		return !memcmp(sha1, sha2, GIT_MAX_RAWSZ);
+	return !memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
+}
+
+static inline void oidcpy(struct object_id *dst, const struct object_id *src)
+{
+	memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ);
+	dst->algo = src->algo;
+}
+
+static inline struct object_id *oiddup(const struct object_id *src)
+{
+	struct object_id *dst = xmalloc(sizeof(struct object_id));
+	oidcpy(dst, src);
+	return dst;
+}
+
+static inline void oid_set_algo(struct object_id *oid, const struct git_hash_algo *algop)
+{
+	oid->algo = hash_algo_by_ptr(algop);
+}
+
+const char *empty_tree_oid_hex(void);
+const char *empty_blob_oid_hex(void);
+
+#endif
diff --git a/hash-lookup.c b/hash-lookup.c
index b98ed5e..bb54dfd 100644
--- a/hash-lookup.c
+++ b/hash-lookup.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "hash.h"
 #include "hash-lookup.h"
 
 static uint32_t take2(const struct object_id *oid, size_t ofs)
diff --git a/hash.h b/hash.h
index 36b6416..615ae06 100644
--- a/hash.h
+++ b/hash.h
@@ -1,217 +1,11 @@
 #ifndef HASH_H
 #define HASH_H
 
-#include "git-compat-util.h"
+#include "hash-ll.h"
 #include "repository.h"
 
-#if defined(SHA1_APPLE)
-#include <CommonCrypto/CommonDigest.h>
-#elif defined(SHA1_OPENSSL)
-#include <openssl/sha.h>
-#elif defined(SHA1_DC)
-#include "sha1dc_git.h"
-#else /* SHA1_BLK */
-#include "block-sha1/sha1.h"
-#endif
-
-#if defined(SHA256_NETTLE)
-#include "sha256/nettle.h"
-#elif defined(SHA256_GCRYPT)
-#define SHA256_NEEDS_CLONE_HELPER
-#include "sha256/gcrypt.h"
-#elif defined(SHA256_OPENSSL)
-#include <openssl/sha.h>
-#else
-#include "sha256/block/sha256.h"
-#endif
-
-#ifndef platform_SHA_CTX
-/*
- * platform's underlying implementation of SHA-1; could be OpenSSL,
- * blk_SHA, Apple CommonCrypto, etc...  Note that the relevant
- * SHA-1 header may have already defined platform_SHA_CTX for our
- * own implementations like block-sha1, so we list
- * the default for OpenSSL compatible SHA-1 implementations here.
- */
-#define platform_SHA_CTX	SHA_CTX
-#define platform_SHA1_Init	SHA1_Init
-#define platform_SHA1_Update	SHA1_Update
-#define platform_SHA1_Final    	SHA1_Final
-#endif
-
-#define git_SHA_CTX		platform_SHA_CTX
-#define git_SHA1_Init		platform_SHA1_Init
-#define git_SHA1_Update		platform_SHA1_Update
-#define git_SHA1_Final		platform_SHA1_Final
-
-#ifndef platform_SHA256_CTX
-#define platform_SHA256_CTX	SHA256_CTX
-#define platform_SHA256_Init	SHA256_Init
-#define platform_SHA256_Update	SHA256_Update
-#define platform_SHA256_Final	SHA256_Final
-#endif
-
-#define git_SHA256_CTX		platform_SHA256_CTX
-#define git_SHA256_Init		platform_SHA256_Init
-#define git_SHA256_Update	platform_SHA256_Update
-#define git_SHA256_Final	platform_SHA256_Final
-
-#ifdef platform_SHA256_Clone
-#define git_SHA256_Clone	platform_SHA256_Clone
-#endif
-
-#ifdef SHA1_MAX_BLOCK_SIZE
-#include "compat/sha1-chunked.h"
-#undef git_SHA1_Update
-#define git_SHA1_Update		git_SHA1_Update_Chunked
-#endif
-
-static inline void git_SHA1_Clone(git_SHA_CTX *dst, const git_SHA_CTX *src)
-{
-	memcpy(dst, src, sizeof(*dst));
-}
-
-#ifndef SHA256_NEEDS_CLONE_HELPER
-static inline void git_SHA256_Clone(git_SHA256_CTX *dst, const git_SHA256_CTX *src)
-{
-	memcpy(dst, src, sizeof(*dst));
-}
-#endif
-
-/*
- * Note that these constants are suitable for indexing the hash_algos array and
- * comparing against each other, but are otherwise arbitrary, so they should not
- * be exposed to the user or serialized to disk.  To know whether a
- * git_hash_algo struct points to some usable hash function, test the format_id
- * field for being non-zero.  Use the name field for user-visible situations and
- * the format_id field for fixed-length fields on disk.
- */
-/* An unknown hash function. */
-#define GIT_HASH_UNKNOWN 0
-/* SHA-1 */
-#define GIT_HASH_SHA1 1
-/* SHA-256  */
-#define GIT_HASH_SHA256 2
-/* Number of algorithms supported (including unknown). */
-#define GIT_HASH_NALGOS (GIT_HASH_SHA256 + 1)
-
-/* "sha1", big-endian */
-#define GIT_SHA1_FORMAT_ID 0x73686131
-
-/* The length in bytes and in hex digits of an object name (SHA-1 value). */
-#define GIT_SHA1_RAWSZ 20
-#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
-/* The block size of SHA-1. */
-#define GIT_SHA1_BLKSZ 64
-
-/* "s256", big-endian */
-#define GIT_SHA256_FORMAT_ID 0x73323536
-
-/* The length in bytes and in hex digits of an object name (SHA-256 value). */
-#define GIT_SHA256_RAWSZ 32
-#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ)
-/* The block size of SHA-256. */
-#define GIT_SHA256_BLKSZ 64
-
-/* The length in byte and in hex digits of the largest possible hash value. */
-#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ
-#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ
-/* The largest possible block size for any supported hash. */
-#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ
-
-struct object_id {
-	unsigned char hash[GIT_MAX_RAWSZ];
-	int algo;	/* XXX requires 4-byte alignment */
-};
-
-/* A suitably aligned type for stack allocations of hash contexts. */
-union git_hash_ctx {
-	git_SHA_CTX sha1;
-	git_SHA256_CTX sha256;
-};
-typedef union git_hash_ctx git_hash_ctx;
-
-typedef void (*git_hash_init_fn)(git_hash_ctx *ctx);
-typedef void (*git_hash_clone_fn)(git_hash_ctx *dst, const git_hash_ctx *src);
-typedef void (*git_hash_update_fn)(git_hash_ctx *ctx, const void *in, size_t len);
-typedef void (*git_hash_final_fn)(unsigned char *hash, git_hash_ctx *ctx);
-typedef void (*git_hash_final_oid_fn)(struct object_id *oid, git_hash_ctx *ctx);
-
-struct git_hash_algo {
-	/*
-	 * The name of the algorithm, as appears in the config file and in
-	 * messages.
-	 */
-	const char *name;
-
-	/* A four-byte version identifier, used in pack indices. */
-	uint32_t format_id;
-
-	/* The length of the hash in binary. */
-	size_t rawsz;
-
-	/* The length of the hash in hex characters. */
-	size_t hexsz;
-
-	/* The block size of the hash. */
-	size_t blksz;
-
-	/* The hash initialization function. */
-	git_hash_init_fn init_fn;
-
-	/* The hash context cloning function. */
-	git_hash_clone_fn clone_fn;
-
-	/* The hash update function. */
-	git_hash_update_fn update_fn;
-
-	/* The hash finalization function. */
-	git_hash_final_fn final_fn;
-
-	/* The hash finalization function for object IDs. */
-	git_hash_final_oid_fn final_oid_fn;
-
-	/* The OID of the empty tree. */
-	const struct object_id *empty_tree;
-
-	/* The OID of the empty blob. */
-	const struct object_id *empty_blob;
-
-	/* The all-zeros OID. */
-	const struct object_id *null_oid;
-};
-extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];
-
-/*
- * Return a GIT_HASH_* constant based on the name.  Returns GIT_HASH_UNKNOWN if
- * the name doesn't match a known algorithm.
- */
-int hash_algo_by_name(const char *name);
-/* Identical, except based on the format ID. */
-int hash_algo_by_id(uint32_t format_id);
-/* Identical, except based on the length. */
-int hash_algo_by_length(int len);
-/* Identical, except for a pointer to struct git_hash_algo. */
-static inline int hash_algo_by_ptr(const struct git_hash_algo *p)
-{
-	return p - hash_algos;
-}
-
 #define the_hash_algo the_repository->hash_algo
 
-const struct object_id *null_oid(void);
-
-static inline int hashcmp_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
-{
-	/*
-	 * Teach the compiler that there are only two possibilities of hash size
-	 * here, so that it can optimize for this case as much as possible.
-	 */
-	if (algop->rawsz == GIT_MAX_RAWSZ)
-		return memcmp(sha1, sha2, GIT_MAX_RAWSZ);
-	return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
-}
-
 static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
 {
 	return hashcmp_algop(sha1, sha2, the_hash_algo);
@@ -227,17 +21,6 @@ static inline int oidcmp(const struct object_id *oid1, const struct object_id *o
 	return hashcmp_algop(oid1->hash, oid2->hash, algop);
 }
 
-static inline int hasheq_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
-{
-	/*
-	 * We write this here instead of deferring to hashcmp so that the
-	 * compiler can properly inline it and avoid calling memcmp.
-	 */
-	if (algop->rawsz == GIT_MAX_RAWSZ)
-		return !memcmp(sha1, sha2, GIT_MAX_RAWSZ);
-	return !memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
-}
-
 static inline int hasheq(const unsigned char *sha1, const unsigned char *sha2)
 {
 	return hasheq_algop(sha1, sha2, the_hash_algo);
@@ -263,12 +46,6 @@ static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src)
 	memcpy(sha_dst, sha_src, the_hash_algo->rawsz);
 }
 
-static inline void oidcpy(struct object_id *dst, const struct object_id *src)
-{
-	memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ);
-	dst->algo = src->algo;
-}
-
 /* Like oidcpy() but zero-pads the unused bytes in dst's hash array. */
 static inline void oidcpy_with_padding(struct object_id *dst,
 				       const struct object_id *src)
@@ -285,13 +62,6 @@ static inline void oidcpy_with_padding(struct object_id *dst,
 	dst->algo = src->algo;
 }
 
-static inline struct object_id *oiddup(const struct object_id *src)
-{
-	struct object_id *dst = xmalloc(sizeof(struct object_id));
-	oidcpy(dst, src);
-	return dst;
-}
-
 static inline void hashclr(unsigned char *hash)
 {
 	memset(hash, 0, the_hash_algo->rawsz);
@@ -329,12 +99,4 @@ static inline int is_empty_tree_oid(const struct object_id *oid)
 	return oideq(oid, the_hash_algo->empty_tree);
 }
 
-static inline void oid_set_algo(struct object_id *oid, const struct git_hash_algo *algop)
-{
-	oid->algo = hash_algo_by_ptr(algop);
-}
-
-const char *empty_tree_oid_hex(void);
-const char *empty_blob_oid_hex(void);
-
 #endif
diff --git a/hashmap.c b/hashmap.c
index cf5fea8..ee45ef0 100644
--- a/hashmap.c
+++ b/hashmap.c
@@ -1,7 +1,7 @@
 /*
  * Generic implementation of hash-based key value mappings.
  */
-#include "cache.h"
+#include "git-compat-util.h"
 #include "hashmap.h"
 
 #define FNV32_BASE ((unsigned int) 0x811c9dc5)
diff --git a/hashmap.h b/hashmap.h
index 7251687..2695f3d 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -1,7 +1,7 @@
 #ifndef HASHMAP_H
 #define HASHMAP_H
 
-#include "hash.h"
+#include "hash-ll.h"
 
 /*
  * Generic implementation of hash-based key-value mappings.
@@ -270,7 +270,7 @@ void hashmap_clear_(struct hashmap *map, ssize_t offset);
 #define hashmap_clear(map) hashmap_clear_(map, -1)
 
 /*
- * Similar to hashmap_clear(), except that the table is no deallocated; it
+ * Similar to hashmap_clear(), except that the table is not deallocated; it
  * is merely zeroed out but left the same size as before.  If the hashmap
  * will be reused, this avoids the overhead of deallocating and
  * reallocating map->table.  As with hashmap_clear(), you may need to free
diff --git a/help.c b/help.c
index 812af4c..5d7637d 100644
--- a/help.c
+++ b/help.c
@@ -1,9 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
 #include "builtin.h"
 #include "exec-cmd.h"
 #include "run-command.h"
 #include "levenshtein.h"
+#include "gettext.h"
 #include "help.h"
 #include "command-list.h"
 #include "string-list.h"
@@ -540,7 +542,8 @@ static struct cmdnames aliases;
 #define AUTOCORRECT_NEVER (-2)
 #define AUTOCORRECT_IMMEDIATELY (-1)
 
-static int git_unknown_cmd_config(const char *var, const char *value, void *cb)
+static int git_unknown_cmd_config(const char *var, const char *value,
+				  void *cb UNUSED)
 {
 	const char *p;
 
diff --git a/hex.c b/hex.c
index 4f64d34..7bb440e 100644
--- a/hex.c
+++ b/hex.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "hash.h"
+#include "hex.h"
 
 const signed char hexval_table[256] = {
 	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 00-07 */
diff --git a/hex.h b/hex.h
new file mode 100644
index 0000000..7df4b3c
--- /dev/null
+++ b/hex.h
@@ -0,0 +1,84 @@
+#ifndef HEX_H
+#define HEX_H
+
+#include "hash-ll.h"
+
+extern const signed char hexval_table[256];
+static inline unsigned int hexval(unsigned char c)
+{
+	return hexval_table[c];
+}
+
+/*
+ * Convert two consecutive hexadecimal digits into a char.  Return a
+ * negative value on error.  Don't run over the end of short strings.
+ */
+static inline int hex2chr(const char *s)
+{
+	unsigned int val = hexval(s[0]);
+	return (val & ~0xf) ? val : (val << 4) | hexval(s[1]);
+}
+
+/*
+ * Try to read a SHA1 in hexadecimal format from the 40 characters
+ * starting at hex.  Write the 20-byte result to sha1 in binary form.
+ * Return 0 on success.  Reading stops if a NUL is encountered in the
+ * input, so it is safe to pass this function an arbitrary
+ * null-terminated string.
+ */
+int get_sha1_hex(const char *hex, unsigned char *sha1);
+int get_oid_hex(const char *hex, struct object_id *sha1);
+
+/* Like get_oid_hex, but for an arbitrary hash algorithm. */
+int get_oid_hex_algop(const char *hex, struct object_id *oid, const struct git_hash_algo *algop);
+
+/*
+ * Read `len` pairs of hexadecimal digits from `hex` and write the
+ * values to `binary` as `len` bytes. Return 0 on success, or -1 if
+ * the input does not consist of hex digits).
+ */
+int hex_to_bytes(unsigned char *binary, const char *hex, size_t len);
+
+/*
+ * Convert a binary hash in "unsigned char []" or an object name in
+ * "struct object_id *" to its hex equivalent. The `_r` variant is reentrant,
+ * and writes the NUL-terminated output to the buffer `out`, which must be at
+ * least `GIT_MAX_HEXSZ + 1` bytes, and returns a pointer to out for
+ * convenience.
+ *
+ * The non-`_r` variant returns a static buffer, but uses a ring of 4
+ * buffers, making it safe to make multiple calls for a single statement, like:
+ *
+ *   printf("%s -> %s", hash_to_hex(one), hash_to_hex(two));
+ *   printf("%s -> %s", oid_to_hex(one), oid_to_hex(two));
+ */
+char *hash_to_hex_algop_r(char *buffer, const unsigned char *hash, const struct git_hash_algo *);
+char *oid_to_hex_r(char *out, const struct object_id *oid);
+char *hash_to_hex_algop(const unsigned char *hash, const struct git_hash_algo *);	/* static buffer result! */
+char *hash_to_hex(const unsigned char *hash);						/* same static buffer */
+char *oid_to_hex(const struct object_id *oid);						/* same static buffer */
+
+/*
+ * Parse a 40-character hexadecimal object ID starting from hex, updating the
+ * pointer specified by end when parsing stops.  The resulting object ID is
+ * stored in oid.  Returns 0 on success.  Parsing will stop on the first NUL or
+ * other invalid character.  end is only updated on success; otherwise, it is
+ * unmodified.
+ */
+int parse_oid_hex(const char *hex, struct object_id *oid, const char **end);
+
+/* Like parse_oid_hex, but for an arbitrary hash algorithm. */
+int parse_oid_hex_algop(const char *hex, struct object_id *oid, const char **end,
+			const struct git_hash_algo *algo);
+
+
+/*
+ * These functions work like get_oid_hex and parse_oid_hex, but they will parse
+ * a hex value for any algorithm. The algorithm is detected based on the length
+ * and the algorithm in use is returned. If this is not a hex object ID in any
+ * algorithm, returns GIT_HASH_UNKNOWN.
+ */
+int get_oid_hex_any(const char *hex, struct object_id *oid);
+int parse_oid_hex_any(const char *hex, struct object_id *oid, const char **end);
+
+#endif
diff --git a/hook.c b/hook.c
index 1a84831..3ca5e60 100644
--- a/hook.c
+++ b/hook.c
@@ -1,7 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
+#include "gettext.h"
 #include "hook.h"
+#include "path.h"
 #include "run-command.h"
 #include "config.h"
+#include "strbuf.h"
 
 const char *find_hook(const char *name)
 {
@@ -43,9 +47,9 @@ int hook_exists(const char *name)
 }
 
 static int pick_next_hook(struct child_process *cp,
-			  struct strbuf *out,
+			  struct strbuf *out UNUSED,
 			  void *pp_cb,
-			  void **pp_task_cb)
+			  void **pp_task_cb UNUSED)
 {
 	struct hook_cb_data *hook_cb = pp_cb;
 	const char *hook_path = hook_cb->hook_path;
@@ -77,9 +81,9 @@ static int pick_next_hook(struct child_process *cp,
 	return 1;
 }
 
-static int notify_start_failure(struct strbuf *out,
+static int notify_start_failure(struct strbuf *out UNUSED,
 				void *pp_cb,
-				void *pp_task_cp)
+				void *pp_task_cp UNUSED)
 {
 	struct hook_cb_data *hook_cb = pp_cb;
 
@@ -89,9 +93,9 @@ static int notify_start_failure(struct strbuf *out,
 }
 
 static int notify_hook_finished(int result,
-				struct strbuf *out,
+				struct strbuf *out UNUSED,
 				void *pp_cb,
-				void *pp_task_cb)
+				void *pp_task_cb UNUSED)
 {
 	struct hook_cb_data *hook_cb = pp_cb;
 	struct run_hooks_opt *opt = hook_cb->options;
diff --git a/http-backend.c b/http-backend.c
index 8ab58e5..ac146d8 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -1,5 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "git-zlib.h"
+#include "hex.h"
 #include "repository.h"
 #include "refs.h"
 #include "pkt-line.h"
@@ -14,6 +18,8 @@
 #include "object-store.h"
 #include "protocol.h"
 #include "date.h"
+#include "wrapper.h"
+#include "write-or-die.h"
 
 static const char content_type[] = "Content-Type";
 static const char content_length[] = "Content-Length";
@@ -524,7 +530,7 @@ static int show_text_ref(const char *name, const struct object_id *oid,
 	return 0;
 }
 
-static void get_info_refs(struct strbuf *hdr, char *arg)
+static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
 {
 	const char *service_name = get_parameter("service");
 	struct strbuf buf = STRBUF_INIT;
@@ -578,7 +584,7 @@ static int show_head_ref(const char *refname, const struct object_id *oid,
 	return 0;
 }
 
-static void get_head(struct strbuf *hdr, char *arg)
+static void get_head(struct strbuf *hdr, char *arg UNUSED)
 {
 	struct strbuf buf = STRBUF_INIT;
 
@@ -588,7 +594,7 @@ static void get_head(struct strbuf *hdr, char *arg)
 	strbuf_release(&buf);
 }
 
-static void get_info_packs(struct strbuf *hdr, char *arg)
+static void get_info_packs(struct strbuf *hdr, char *arg UNUSED)
 {
 	size_t objdirlen = strlen(get_object_directory());
 	struct strbuf buf = STRBUF_INIT;
@@ -736,7 +742,7 @@ static int bad_request(struct strbuf *hdr, const struct service_cmd *c)
 	return 0;
 }
 
-int cmd_main(int argc, const char **argv)
+int cmd_main(int argc UNUSED, const char **argv UNUSED)
 {
 	char *method = getenv("REQUEST_METHOD");
 	const char *proto_header;
diff --git a/http-fetch.c b/http-fetch.c
index 258fec2..fffda59 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -1,8 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "exec-cmd.h"
+#include "gettext.h"
+#include "hex.h"
 #include "http.h"
 #include "walker.h"
+#include "setup.h"
 #include "strvec.h"
 #include "urlmatch.h"
 #include "trace2.h"
diff --git a/http-push.c b/http-push.c
index 7f71316..29cf9db 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "environment.h"
+#include "hex.h"
 #include "repository.h"
 #include "commit.h"
 #include "tag.h"
@@ -10,8 +12,11 @@
 #include "exec-cmd.h"
 #include "remote.h"
 #include "list-objects.h"
+#include "setup.h"
 #include "sigchain.h"
 #include "strvec.h"
+#include "tree.h"
+#include "tree-walk.h"
 #include "packfile.h"
 #include "object-store.h"
 #include "commit-reach.h"
@@ -362,7 +367,8 @@ static void start_put(struct transfer_request *request)
 	ssize_t size;
 	git_zstream stream;
 
-	unpacked = read_object_file(&request->obj->oid, &type, &len);
+	unpacked = repo_read_object_file(the_repository, &request->obj->oid,
+					 &type, &len);
 	hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
 
 	/* Set it up */
@@ -601,7 +607,7 @@ static void finish_request(struct transfer_request *request)
 }
 
 static int is_running_queue;
-static int fill_active_slot(void *unused)
+static int fill_active_slot(void *data UNUSED)
 {
 	struct transfer_request *request;
 
@@ -1331,7 +1337,8 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock)
 	int count = 0;
 
 	while ((commit = get_revision(revs)) != NULL) {
-		p = process_tree(get_commit_tree(commit), p);
+		p = process_tree(repo_get_commit_tree(the_repository, commit),
+				 p);
 		commit->object.flags |= LOCAL;
 		if (!(commit->object.flags & UNINTERESTING))
 			count += add_send_request(&commit->object, lock);
@@ -1426,7 +1433,7 @@ static void one_remote_ref(const char *refname)
 	 * Fetch a copy of the object if it doesn't exist locally - it
 	 * may be required for updating server info later.
 	 */
-	if (repo->can_update_info_refs && !has_object_file(&ref->old_oid)) {
+	if (repo->can_update_info_refs && !repo_has_object_file(the_repository, &ref->old_oid)) {
 		obj = lookup_unknown_object(the_repository, &ref->old_oid);
 		fprintf(stderr,	"  fetch %s for %s\n",
 			oid_to_hex(&ref->old_oid), refname);
@@ -1570,7 +1577,7 @@ static int verify_merge_base(struct object_id *head_oid, struct ref *remote)
 	struct commit *branch = lookup_commit_or_die(&remote->old_oid,
 						     remote->name);
 
-	return in_merge_bases(branch, head);
+	return repo_in_merge_bases(the_repository, branch, head);
 }
 
 static int delete_remote_branch(const char *pattern, int force)
@@ -1627,14 +1634,14 @@ static int delete_remote_branch(const char *pattern, int force)
 			return error("Remote HEAD symrefs too deep");
 		if (is_null_oid(&head_oid))
 			return error("Unable to resolve remote HEAD");
-		if (!has_object_file(&head_oid))
+		if (!repo_has_object_file(the_repository, &head_oid))
 			return error("Remote HEAD resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", oid_to_hex(&head_oid));
 
 		/* Remote branch must resolve to a known object */
 		if (is_null_oid(&remote_ref->old_oid))
 			return error("Unable to resolve remote branch %s",
 				     remote_ref->name);
-		if (!has_object_file(&remote_ref->old_oid))
+		if (!repo_has_object_file(the_repository, &remote_ref->old_oid))
 			return error("Remote branch %s resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", remote_ref->name, oid_to_hex(&remote_ref->old_oid));
 
 		/* Remote branch must be an ancestor of remote HEAD */
@@ -1854,7 +1861,7 @@ int cmd_main(int argc, const char **argv)
 		if (!force_all &&
 		    !is_null_oid(&ref->old_oid) &&
 		    !ref->force) {
-			if (!has_object_file(&ref->old_oid) ||
+			if (!repo_has_object_file(the_repository, &ref->old_oid) ||
 			    !ref_newer(&ref->peer_ref->new_oid,
 				       &ref->old_oid)) {
 				/*
diff --git a/http-walker.c b/http-walker.c
index b8f0f98..bba306b 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "repository.h"
 #include "commit.h"
+#include "hex.h"
 #include "walker.h"
 #include "http.h"
 #include "list.h"
@@ -52,8 +53,7 @@ static void fetch_alternates(struct walker *walker, const char *base);
 
 static void process_object_response(void *callback_data);
 
-static void start_object_request(struct walker *walker,
-				 struct object_request *obj_req)
+static void start_object_request(struct object_request *obj_req)
 {
 	struct active_request_slot *slot;
 	struct http_object_request *req;
@@ -110,7 +110,7 @@ static void process_object_response(void *callback_data)
 			obj_req->repo =
 				obj_req->repo->next;
 			release_http_object_request(obj_req->req);
-			start_object_request(walker, obj_req);
+			start_object_request(obj_req);
 			return;
 		}
 	}
@@ -127,7 +127,7 @@ static void release_object_request(struct object_request *obj_req)
 	free(obj_req);
 }
 
-static int fill_active_slot(struct walker *walker)
+static int fill_active_slot(void *data UNUSED)
 {
 	struct object_request *obj_req;
 	struct list_head *pos, *tmp, *head = &object_queue_head;
@@ -135,10 +135,10 @@ static int fill_active_slot(struct walker *walker)
 	list_for_each_safe(pos, tmp, head) {
 		obj_req = list_entry(pos, struct object_request, node);
 		if (obj_req->state == WAITING) {
-			if (has_object_file(&obj_req->oid))
+			if (repo_has_object_file(the_repository, &obj_req->oid))
 				obj_req->state = COMPLETE;
 			else {
-				start_object_request(walker, obj_req);
+				start_object_request(obj_req);
 				return 1;
 			}
 		}
@@ -492,7 +492,7 @@ static int fetch_object(struct walker *walker, unsigned char *hash)
 	if (!obj_req)
 		return error("Couldn't find request for %s in the queue", hex);
 
-	if (has_object_file(&obj_req->oid)) {
+	if (repo_has_object_file(the_repository, &obj_req->oid)) {
 		if (obj_req->req)
 			abort_http_object_request(obj_req->req);
 		abort_object_request(obj_req);
@@ -613,7 +613,7 @@ struct walker *get_http_walker(const char *url)
 	walker->cleanup = cleanup;
 	walker->data = data;
 
-	add_fill_function(walker, (int (*)(void *)) fill_active_slot);
+	add_fill_function(NULL, fill_active_slot);
 
 	return walker;
 }
diff --git a/http.c b/http.c
index c4b6dde..bb58bb3 100644
--- a/http.c
+++ b/http.c
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "git-curl-compat.h"
+#include "hex.h"
 #include "http.h"
 #include "config.h"
 #include "pack.h"
@@ -11,10 +12,12 @@
 #include "version.h"
 #include "pkt-line.h"
 #include "gettext.h"
+#include "trace.h"
 #include "transport.h"
 #include "packfile.h"
 #include "protocol.h"
 #include "string-list.h"
+#include "object-file.h"
 #include "object-store.h"
 
 static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
@@ -39,6 +42,7 @@ static int curl_ssl_verify = -1;
 static int curl_ssl_try;
 static const char *curl_http_version = NULL;
 static const char *ssl_cert;
+static const char *ssl_cert_type;
 static const char *ssl_cipherlist;
 static const char *ssl_version;
 static struct {
@@ -58,6 +62,7 @@ static struct {
 #endif
 };
 static const char *ssl_key;
+static const char *ssl_key_type;
 static const char *ssl_capath;
 static const char *curl_no_proxy;
 #ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY
@@ -181,6 +186,115 @@ size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
 	return nmemb;
 }
 
+/*
+ * A folded header continuation line starts with any number of spaces or
+ * horizontal tab characters (SP or HTAB) as per RFC 7230 section 3.2.
+ * It is not a continuation line if the line starts with any other character.
+ */
+static inline int is_hdr_continuation(const char *ptr, const size_t size)
+{
+	return size && (*ptr == ' ' || *ptr == '\t');
+}
+
+static size_t fwrite_wwwauth(char *ptr, size_t eltsize, size_t nmemb, void *p)
+{
+	size_t size = eltsize * nmemb;
+	struct strvec *values = &http_auth.wwwauth_headers;
+	struct strbuf buf = STRBUF_INIT;
+	const char *val;
+	size_t val_len;
+
+	/*
+	 * Header lines may not come NULL-terminated from libcurl so we must
+	 * limit all scans to the maximum length of the header line, or leverage
+	 * strbufs for all operations.
+	 *
+	 * In addition, it is possible that header values can be split over
+	 * multiple lines as per RFC 7230. 'Line folding' has been deprecated
+	 * but older servers may still emit them. A continuation header field
+	 * value is identified as starting with a space or horizontal tab.
+	 *
+	 * The formal definition of a header field as given in RFC 7230 is:
+	 *
+	 * header-field   = field-name ":" OWS field-value OWS
+	 *
+	 * field-name     = token
+	 * field-value    = *( field-content / obs-fold )
+	 * field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
+	 * field-vchar    = VCHAR / obs-text
+	 *
+	 * obs-fold       = CRLF 1*( SP / HTAB )
+	 *                ; obsolete line folding
+	 *                ; see Section 3.2.4
+	 */
+
+	/* Start of a new WWW-Authenticate header */
+	if (skip_iprefix_mem(ptr, size, "www-authenticate:", &val, &val_len)) {
+		strbuf_add(&buf, val, val_len);
+
+		/*
+		 * Strip the CRLF that should be present at the end of each
+		 * field as well as any trailing or leading whitespace from the
+		 * value.
+		 */
+		strbuf_trim(&buf);
+
+		strvec_push(values, buf.buf);
+		http_auth.header_is_last_match = 1;
+		goto exit;
+	}
+
+	/*
+	 * This line could be a continuation of the previously matched header
+	 * field. If this is the case then we should append this value to the
+	 * end of the previously consumed value.
+	 */
+	if (http_auth.header_is_last_match && is_hdr_continuation(ptr, size)) {
+		/*
+		 * Trim the CRLF and any leading or trailing from this line.
+		 */
+		strbuf_add(&buf, ptr, size);
+		strbuf_trim(&buf);
+
+		/*
+		 * At this point we should always have at least one existing
+		 * value, even if it is empty. Do not bother appending the new
+		 * value if this continuation header is itself empty.
+		 */
+		if (!values->nr) {
+			BUG("should have at least one existing header value");
+		} else if (buf.len) {
+			char *prev = xstrdup(values->v[values->nr - 1]);
+
+			/* Join two non-empty values with a single space. */
+			const char *const sp = *prev ? " " : "";
+
+			strvec_pop(values);
+			strvec_pushf(values, "%s%s%s", prev, sp, buf.buf);
+			free(prev);
+		}
+
+		goto exit;
+	}
+
+	/* Not a continuation of a previously matched auth header line. */
+	http_auth.header_is_last_match = 0;
+
+	/*
+	 * If this is a HTTP status line and not a header field, this signals
+	 * a different HTTP response. libcurl writes all the output of all
+	 * response headers of all responses, including redirects.
+	 * We only care about the last HTTP request response's headers so clear
+	 * the existing array.
+	 */
+	if (skip_iprefix_mem(ptr, size, "http/", &val, &val_len))
+		strvec_clear(values);
+
+exit:
+	strbuf_release(&buf);
+	return size;
+}
+
 size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf)
 {
 	return nmemb;
@@ -264,8 +378,12 @@ static int http_options(const char *var, const char *value, void *cb)
 		return git_config_string(&ssl_version, var, value);
 	if (!strcmp("http.sslcert", var))
 		return git_config_pathname(&ssl_cert, var, value);
+	if (!strcmp("http.sslcerttype", var))
+		return git_config_string(&ssl_cert_type, var, value);
 	if (!strcmp("http.sslkey", var))
 		return git_config_pathname(&ssl_key, var, value);
+	if (!strcmp("http.sslkeytype", var))
+		return git_config_string(&ssl_key_type, var, value);
 	if (!strcmp("http.sslcapath", var))
 		return git_config_pathname(&ssl_capath, var, value);
 	if (!strcmp("http.sslcainfo", var))
@@ -904,10 +1022,14 @@ static CURL *get_curl_handle(void)
 
 	if (ssl_cert)
 		curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
+	if (ssl_cert_type)
+		curl_easy_setopt(result, CURLOPT_SSLCERTTYPE, ssl_cert_type);
 	if (has_cert_password())
 		curl_easy_setopt(result, CURLOPT_KEYPASSWD, cert_auth.password);
 	if (ssl_key)
 		curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
+	if (ssl_key_type)
+		curl_easy_setopt(result, CURLOPT_SSLKEYTYPE, ssl_key_type);
 	if (ssl_capath)
 		curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
 #ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY
@@ -1142,7 +1264,9 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
 		curl_ssl_verify = 0;
 
 	set_from_env(&ssl_cert, "GIT_SSL_CERT");
+	set_from_env(&ssl_cert_type, "GIT_SSL_CERT_TYPE");
 	set_from_env(&ssl_key, "GIT_SSL_KEY");
+	set_from_env(&ssl_key_type, "GIT_SSL_KEY_TYPE");
 	set_from_env(&ssl_capath, "GIT_SSL_CAPATH");
 	set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO");
 
@@ -1895,6 +2019,8 @@ static int http_request(const char *url,
 					 fwrite_buffer);
 	}
 
+	curl_easy_setopt(slot->curl, CURLOPT_HEADERFUNCTION, fwrite_wwwauth);
+
 	accept_language = http_get_accept_language_header();
 
 	if (accept_language)
diff --git a/http.h b/http.h
index 77c0427..3a409bc 100644
--- a/http.h
+++ b/http.h
@@ -1,7 +1,9 @@
 #ifndef HTTP_H
 #define HTTP_H
 
-#include "cache.h"
+struct packed_git;
+
+#include "git-zlib.h"
 
 #include <curl/curl.h>
 #include <curl/easy.h>
diff --git a/ident.c b/ident.c
index 6de76f9..8fad92d 100644
--- a/ident.c
+++ b/ident.c
@@ -5,10 +5,13 @@
  *
  * Copyright (C) 2005 Linus Torvalds
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "ident.h"
 #include "config.h"
 #include "date.h"
+#include "gettext.h"
 #include "mailmap.h"
+#include "strbuf.h"
 
 static struct strbuf git_default_name = STRBUF_INIT;
 static struct strbuf git_default_email = STRBUF_INIT;
diff --git a/ident.h b/ident.h
new file mode 100644
index 0000000..96a6489
--- /dev/null
+++ b/ident.h
@@ -0,0 +1,67 @@
+#ifndef IDENT_H
+#define IDENT_H
+
+#include "string-list.h"
+
+struct ident_split {
+	const char *name_begin;
+	const char *name_end;
+	const char *mail_begin;
+	const char *mail_end;
+	const char *date_begin;
+	const char *date_end;
+	const char *tz_begin;
+	const char *tz_end;
+};
+
+#define IDENT_STRICT	       1
+#define IDENT_NO_DATE	       2
+#define IDENT_NO_NAME	       4
+
+enum want_ident {
+	WANT_BLANK_IDENT,
+	WANT_AUTHOR_IDENT,
+	WANT_COMMITTER_IDENT
+};
+
+const char *ident_default_name(void);
+const char *ident_default_email(void);
+/*
+ * Prepare an ident to fall back on if the user didn't configure it.
+ */
+void prepare_fallback_ident(const char *name, const char *email);
+void reset_ident_date(void);
+/*
+ * Signals an success with 0, but time part of the result may be NULL
+ * if the input lacks timestamp and zone
+ */
+int split_ident_line(struct ident_split *, const char *, int);
+
+/*
+ * Given a commit or tag object buffer and the commit or tag headers, replaces
+ * the idents in the headers with their canonical versions using the mailmap mechanism.
+ */
+void apply_mailmap_to_header(struct strbuf *, const char **, struct string_list *);
+
+/*
+ * Compare split idents for equality or strict ordering. Note that we
+ * compare only the ident part of the line, ignoring any timestamp.
+ *
+ * Because there are two fields, we must choose one as the primary key; we
+ * currently arbitrarily pick the email.
+ */
+int ident_cmp(const struct ident_split *, const struct ident_split *);
+
+const char *git_author_info(int);
+const char *git_committer_info(int);
+const char *fmt_ident(const char *name, const char *email,
+		      enum want_ident whose_ident,
+		      const char *date_str, int);
+const char *fmt_name(enum want_ident);
+
+int committer_ident_sufficiently_given(void);
+int author_ident_sufficiently_given(void);
+
+int git_ident_config(const char *, const char *, void *);
+
+#endif
diff --git a/imap-send.c b/imap-send.c
index a50af56..7f54261 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -21,12 +21,16 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "credential.h"
 #include "exec-cmd.h"
+#include "gettext.h"
 #include "run-command.h"
 #include "parse-options.h"
+#include "setup.h"
+#include "strbuf.h"
+#include "wrapper.h"
 #if defined(NO_OPENSSL) && !defined(HAVE_OPENSSL_CSPRNG)
 typedef void *SSL;
 #endif
diff --git a/json-writer.c b/json-writer.c
index f1cfd8f..005c820 100644
--- a/json-writer.c
+++ b/json-writer.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "json-writer.h"
 
 void jw_init(struct json_writer *jw)
diff --git a/khash.h b/khash.h
index cb79bf8..56241e6 100644
--- a/khash.h
+++ b/khash.h
@@ -26,8 +26,8 @@
 #ifndef __AC_KHASH_H
 #define __AC_KHASH_H
 
-#include "cache.h"
 #include "hashmap.h"
+#include "hash.h"
 
 #define AC_VERSION_KHASH_H "0.2.8"
 
diff --git a/kwset.c b/kwset.c
index 08aadf0..4b14d4f 100644
--- a/kwset.c
+++ b/kwset.c
@@ -32,7 +32,7 @@
    String Matching:  An Aid to Bibliographic Search," CACM June 1975,
    Vol. 18, No. 6, which describes the failure function used below. */
 
-#include "cache.h"
+#include "git-compat-util.h"
 
 #include "kwset.h"
 #include "compat/obstack.h"
diff --git a/levenshtein.c b/levenshtein.c
index d263269..fd8026f 100644
--- a/levenshtein.c
+++ b/levenshtein.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "levenshtein.h"
 
 /*
diff --git a/line-log.c b/line-log.c
index a7f3e7f..6a7ac31 100644
--- a/line-log.c
+++ b/line-log.c
@@ -1,6 +1,7 @@
 #include "git-compat-util.h"
+#include "alloc.h"
 #include "line-range.h"
-#include "cache.h"
+#include "hex.h"
 #include "tag.h"
 #include "blob.h"
 #include "tree.h"
@@ -14,8 +15,10 @@
 #include "graph.h"
 #include "userdiff.h"
 #include "line-log.h"
+#include "setup.h"
 #include "strvec.h"
 #include "bloom.h"
+#include "tree-walk.h"
 
 static void range_set_grow(struct range_set *rs, size_t extra)
 {
@@ -1281,7 +1284,8 @@ int line_log_process_ranges_arbitrary_commit(struct rev_info *rev, struct commit
 	return changed;
 }
 
-static enum rewrite_result line_log_rewrite_one(struct rev_info *rev, struct commit **pp)
+static enum rewrite_result line_log_rewrite_one(struct rev_info *rev UNUSED,
+						struct commit **pp)
 {
 	for (;;) {
 		struct commit *p = *pp;
diff --git a/line-log.h b/line-log.h
index 82ae8d9..adff361 100644
--- a/line-log.h
+++ b/line-log.h
@@ -5,6 +5,7 @@
 
 struct rev_info;
 struct commit;
+struct string_list;
 
 /* A range [start,end].  Lines are numbered starting at 0, and the
  * ranges include start but exclude end. */
diff --git a/linear-assignment.c b/linear-assignment.c
index ecffc09..5416cbc 100644
--- a/linear-assignment.c
+++ b/linear-assignment.c
@@ -3,7 +3,7 @@
  * algorithm for dense and sparse linear assignment problems</i>. Computing,
  * 38(4), 325-340.
  */
-#include "cache.h"
+#include "git-compat-util.h"
 #include "linear-assignment.h"
 
 #define COST(column, row) cost[(column) + column_count * (row)]
diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index ee01bcd..2a3b788 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -1,6 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "commit.h"
 #include "config.h"
+#include "gettext.h"
 #include "revision.h"
 #include "strvec.h"
 #include "list-objects.h"
@@ -9,6 +11,7 @@
 #include "promisor-remote.h"
 #include "trace.h"
 #include "url.h"
+#include "parse-options.h"
 
 static int parse_combine_filter(
 	struct list_objects_filter_options *filter_options,
@@ -341,7 +344,7 @@ void partial_clone_register(
 	char *filter_name;
 
 	/* Check if it is already registered */
-	if ((promisor_remote = promisor_remote_find(remote))) {
+	if ((promisor_remote = repo_promisor_remote_find(the_repository, remote))) {
 		if (promisor_remote->partial_clone_filter)
 			/*
 			 * Remote is already registered and a filter is already
@@ -369,14 +372,15 @@ void partial_clone_register(
 	free(filter_name);
 
 	/* Make sure the config info are reset */
-	promisor_remote_reinit();
+	repo_promisor_remote_reinit(the_repository);
 }
 
 void partial_clone_get_default_filter_spec(
 	struct list_objects_filter_options *filter_options,
 	const char *remote)
 {
-	struct promisor_remote *promisor = promisor_remote_find(remote);
+	struct promisor_remote *promisor = repo_promisor_remote_find(the_repository,
+								     remote);
 	struct strbuf errbuf = STRBUF_INIT;
 
 	/*
diff --git a/list-objects-filter-options.h b/list-objects-filter-options.h
index 1fe393f..f620612 100644
--- a/list-objects-filter-options.h
+++ b/list-objects-filter-options.h
@@ -1,9 +1,12 @@
 #ifndef LIST_OBJECTS_FILTER_OPTIONS_H
 #define LIST_OBJECTS_FILTER_OPTIONS_H
 
-#include "cache.h"
-#include "parse-options.h"
+#include "gettext.h"
+#include "object.h"
 #include "string-list.h"
+#include "strbuf.h"
+
+struct option;
 
 /*
  * The list of defined filters for list-objects.
diff --git a/list-objects-filter.c b/list-objects-filter.c
index 7ed21cb..5d270ce 100644
--- a/list-objects-filter.c
+++ b/list-objects-filter.c
@@ -1,5 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "dir.h"
+#include "gettext.h"
+#include "hex.h"
 #include "tag.h"
 #include "commit.h"
 #include "tree.h"
@@ -12,6 +15,7 @@
 #include "list-objects-filter-options.h"
 #include "oidmap.h"
 #include "oidset.h"
+#include "object-name.h"
 #include "object-store.h"
 
 /* Remember to update object flag allocation in object.h */
diff --git a/list-objects.c b/list-objects.c
index 7528fe1..eecca72 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -1,6 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "tag.h"
 #include "commit.h"
+#include "gettext.h"
+#include "hex.h"
 #include "tree.h"
 #include "blob.h"
 #include "diff.h"
@@ -64,7 +66,7 @@ static void process_blob(struct traversal_context *ctx,
 	 * of missing objects.
 	 */
 	if (ctx->revs->exclude_promisor_objects &&
-	    !has_object_file(&obj->oid) &&
+	    !repo_has_object_file(the_repository, &obj->oid) &&
 	    is_promisor_object(&obj->oid))
 		return;
 
@@ -227,7 +229,8 @@ static void mark_edge_parents_uninteresting(struct commit *commit,
 		struct commit *parent = parents->item;
 		if (!(parent->object.flags & UNINTERESTING))
 			continue;
-		mark_tree_uninteresting(revs->repo, get_commit_tree(parent));
+		mark_tree_uninteresting(revs->repo,
+					repo_get_commit_tree(the_repository, parent));
 		if (revs->edge_hint && !(parent->object.flags & SHOWN)) {
 			parent->object.flags |= SHOWN;
 			show_edge(parent);
@@ -244,7 +247,8 @@ static void add_edge_parents(struct commit *commit,
 
 	for (parents = commit->parents; parents; parents = parents->next) {
 		struct commit *parent = parents->item;
-		struct tree *tree = get_commit_tree(parent);
+		struct tree *tree = repo_get_commit_tree(the_repository,
+							 parent);
 
 		if (!tree)
 			continue;
@@ -275,7 +279,8 @@ void mark_edges_uninteresting(struct rev_info *revs,
 
 		for (list = revs->commits; list; list = list->next) {
 			struct commit *commit = list->item;
-			struct tree *tree = get_commit_tree(commit);
+			struct tree *tree = repo_get_commit_tree(the_repository,
+								 commit);
 
 			if (commit->object.flags & UNINTERESTING)
 				tree->object.flags |= UNINTERESTING;
@@ -291,7 +296,7 @@ void mark_edges_uninteresting(struct rev_info *revs,
 			struct commit *commit = list->item;
 			if (commit->object.flags & UNINTERESTING) {
 				mark_tree_uninteresting(revs->repo,
-							get_commit_tree(commit));
+							repo_get_commit_tree(the_repository, commit));
 				if (revs->edge_hint_aggressive && !(commit->object.flags & SHOWN)) {
 					commit->object.flags |= SHOWN;
 					show_edge(commit);
@@ -309,7 +314,7 @@ void mark_edges_uninteresting(struct rev_info *revs,
 			if (obj->type != OBJ_COMMIT || !(obj->flags & UNINTERESTING))
 				continue;
 			mark_tree_uninteresting(revs->repo,
-						get_commit_tree(commit));
+						repo_get_commit_tree(the_repository, commit));
 			if (!(obj->flags & SHOWN)) {
 				obj->flags |= SHOWN;
 				show_edge(commit);
@@ -376,8 +381,9 @@ static void do_traverse(struct traversal_context *ctx)
 		 */
 		if (!ctx->revs->tree_objects)
 			; /* do not bother loading tree */
-		else if (get_commit_tree(commit)) {
-			struct tree *tree = get_commit_tree(commit);
+		else if (repo_get_commit_tree(the_repository, commit)) {
+			struct tree *tree = repo_get_commit_tree(the_repository,
+								 commit);
 			tree->object.flags |= NOT_USER_GIVEN;
 			add_pending_tree(ctx->revs, tree);
 		} else if (commit->object.parsed) {
diff --git a/ll-merge.c b/ll-merge.c
index 130d265..07ec16e 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -4,13 +4,16 @@
  * Copyright (c) 2007 Junio C Hamano
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "convert.h"
 #include "attr.h"
 #include "xdiff-interface.h"
 #include "run-command.h"
 #include "ll-merge.h"
 #include "quote.h"
+#include "strbuf.h"
+#include "wrapper.h"
 
 struct ll_merge_driver;
 
@@ -391,7 +394,7 @@ enum ll_merge_result ll_merge(mmbuffer_t *result_buf,
 		normalize_file(theirs, path, istate);
 	}
 
-	git_check_attr(istate, NULL, path, check);
+	git_check_attr(istate, path, check);
 	ll_driver_name = check->items[0].value;
 	if (check->items[1].value) {
 		marker_size = atoi(check->items[1].value);
@@ -419,7 +422,7 @@ int ll_merge_marker_size(struct index_state *istate, const char *path)
 
 	if (!check)
 		check = attr_check_initl("conflict-marker-size", NULL);
-	git_check_attr(istate, NULL, path, check);
+	git_check_attr(istate, path, check);
 	if (check->items[0].value) {
 		marker_size = atoi(check->items[0].value);
 		if (marker_size <= 0)
diff --git a/lockfile.c b/lockfile.c
index cc9a4b8..1d5ed01 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -2,7 +2,9 @@
  * Copyright (c) 2005, Junio C Hamano
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "gettext.h"
 #include "lockfile.h"
 
 /*
diff --git a/log-tree.c b/log-tree.c
index 1dd5fcb..f4b22a6 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -1,7 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "commit-reach.h"
 #include "config.h"
 #include "diff.h"
+#include "environment.h"
+#include "hex.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "repository.h"
 #include "tmp-objdir.h"
@@ -12,6 +15,7 @@
 #include "merge-ort.h"
 #include "reflog-walk.h"
 #include "refs.h"
+#include "replace-object.h"
 #include "string-list.h"
 #include "color.h"
 #include "gpg-interface.h"
@@ -20,6 +24,8 @@
 #include "help.h"
 #include "range-diff.h"
 #include "strmap.h"
+#include "tree.h"
+#include "write-or-die.h"
 
 static struct decoration name_decoration = { "object names" };
 static int decoration_loaded;
@@ -196,7 +202,8 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,
 	return 0;
 }
 
-static int add_graft_decoration(const struct commit_graft *graft, void *cb_data)
+static int add_graft_decoration(const struct commit_graft *graft,
+				void *cb_data UNUSED)
 {
 	struct commit *commit = lookup_commit(the_repository, &graft->oid);
 	if (!commit)
@@ -233,7 +240,8 @@ static void show_parents(struct commit *commit, int abbrev, FILE *file)
 	struct commit_list *p;
 	for (p = commit->parents; p ; p = p->next) {
 		struct commit *parent = p->item;
-		fprintf(file, " %s", find_unique_abbrev(&parent->object.oid, abbrev));
+		fprintf(file, " %s",
+			repo_find_unique_abbrev(the_repository, &parent->object.oid, abbrev));
 	}
 }
 
@@ -241,7 +249,8 @@ static void show_children(struct rev_info *opt, struct commit *commit, int abbre
 {
 	struct commit_list *p = lookup_decoration(&opt->children, &commit->object);
 	for ( ; p; p = p->next) {
-		fprintf(opt->diffopt.file, " %s", find_unique_abbrev(&p->item->object.oid, abbrev));
+		fprintf(opt->diffopt.file, " %s",
+			repo_find_unique_abbrev(the_repository, &p->item->object.oid, abbrev));
 	}
 }
 
@@ -405,7 +414,8 @@ void fmt_output_commit(struct strbuf *filename,
 	struct pretty_print_context ctx = {0};
 	struct strbuf subject = STRBUF_INIT;
 
-	format_commit_message(commit, "%f", &subject, &ctx);
+	repo_format_commit_message(the_repository, commit, "%f", &subject,
+				   &ctx);
 	fmt_output_subject(filename, subject.buf, info);
 	strbuf_release(&subject);
 }
@@ -440,7 +450,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
 	fprintf(opt->diffopt.file, "From %s Mon Sep 17 00:00:00 2001\n", name);
 	graph_show_oneline(opt->graph);
 	if (opt->message_id) {
-		fprintf(opt->diffopt.file, "Message-Id: <%s>\n", opt->message_id);
+		fprintf(opt->diffopt.file, "Message-ID: <%s>\n", opt->message_id);
 		graph_show_oneline(opt->graph);
 	}
 	if (opt->ref_message_ids && opt->ref_message_ids->nr > 0) {
@@ -644,7 +654,8 @@ void show_log(struct rev_info *opt)
 
 		if (!opt->graph)
 			put_revision_mark(opt, commit);
-		fputs(find_unique_abbrev(&commit->object.oid, abbrev_commit), opt->diffopt.file);
+		fputs(repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev_commit),
+		      opt->diffopt.file);
 		if (opt->print_parents)
 			show_parents(commit, abbrev_commit, opt->diffopt.file);
 		if (opt->children.name)
@@ -706,8 +717,8 @@ void show_log(struct rev_info *opt)
 
 		if (!opt->graph)
 			put_revision_mark(opt, commit);
-		fputs(find_unique_abbrev(&commit->object.oid,
-					 abbrev_commit),
+		fputs(repo_find_unique_abbrev(the_repository, &commit->object.oid,
+					      abbrev_commit),
 		      opt->diffopt.file);
 		if (opt->print_parents)
 			show_parents(commit, abbrev_commit, opt->diffopt.file);
@@ -715,7 +726,7 @@ void show_log(struct rev_info *opt)
 			show_children(opt, commit, abbrev_commit);
 		if (parent)
 			fprintf(opt->diffopt.file, " (from %s)",
-			       find_unique_abbrev(&parent->object.oid, abbrev_commit));
+			       repo_find_unique_abbrev(the_repository, &parent->object.oid, abbrev_commit));
 		fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), opt->diffopt.file);
 		show_decorations(opt, commit);
 		if (opt->commit_format == CMIT_FMT_ONELINE) {
@@ -846,7 +857,7 @@ void show_log(struct rev_info *opt)
 		 * Pass minimum required diff-options to range-diff; others
 		 * can be added later if deemed desirable.
 		 */
-		diff_setup(&opts);
+		repo_diff_setup(the_repository, &opts);
 		opts.file = opt->diffopt.file;
 		opts.use_color = opt->diffopt.use_color;
 		diff_setup_done(&opts);
@@ -982,15 +993,17 @@ static int do_remerge_diff(struct rev_info *opt,
 	o.msg_header_prefix = "remerge";
 
 	ctx.abbrev = DEFAULT_ABBREV;
-	format_commit_message(parent1, "%h (%s)", &parent1_desc, &ctx);
-	format_commit_message(parent2, "%h (%s)", &parent2_desc, &ctx);
+	repo_format_commit_message(the_repository, parent1, "%h (%s)",
+				   &parent1_desc, &ctx);
+	repo_format_commit_message(the_repository, parent2, "%h (%s)",
+				   &parent2_desc, &ctx);
 	o.branch1 = parent1_desc.buf;
 	o.branch2 = parent2_desc.buf;
 
 	/* Parse the relevant commits and get the merge bases */
 	parse_commit_or_die(parent1);
 	parse_commit_or_die(parent2);
-	bases = get_merge_bases(parent1, parent2);
+	bases = repo_get_merge_bases(the_repository, parent1, parent2);
 
 	/* Re-merge the parents */
 	merge_incore_recursive(&o, bases, parent1, parent2, &res);
diff --git a/ls-refs.c b/ls-refs.c
index 697d4be..f385938 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -1,4 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hash.h"
+#include "hex.h"
 #include "repository.h"
 #include "refs.h"
 #include "remote.h"
@@ -8,38 +12,32 @@
 #include "config.h"
 #include "string-list.h"
 
-static int config_read;
-static int advertise_unborn;
-static int allow_unborn;
-
-static void ensure_config_read(void)
+static enum {
+	UNBORN_IGNORE = 0,
+	UNBORN_ALLOW,
+	UNBORN_ADVERTISE /* implies ALLOW */
+} unborn_config(struct repository *r)
 {
 	const char *str = NULL;
 
-	if (config_read)
-		return;
-
-	if (repo_config_get_string_tmp(the_repository, "lsrefs.unborn", &str)) {
+	if (repo_config_get_string_tmp(r, "lsrefs.unborn", &str)) {
 		/*
 		 * If there is no such config, advertise and allow it by
 		 * default.
 		 */
-		advertise_unborn = 1;
-		allow_unborn = 1;
+		return UNBORN_ADVERTISE;
 	} else {
 		if (!strcmp(str, "advertise")) {
-			advertise_unborn = 1;
-			allow_unborn = 1;
+			return UNBORN_ADVERTISE;
 		} else if (!strcmp(str, "allow")) {
-			allow_unborn = 1;
+			return UNBORN_ALLOW;
 		} else if (!strcmp(str, "ignore")) {
-			/* do nothing */
+			return UNBORN_IGNORE;
 		} else {
 			die(_("invalid value for '%s': '%s'"),
 			    "lsrefs.unborn", str);
 		}
 	}
-	config_read = 1;
 }
 
 /*
@@ -159,7 +157,6 @@ int ls_refs(struct repository *r, struct packet_reader *request)
 	strbuf_init(&data.buf, 0);
 	string_list_init_dup(&data.hidden_refs);
 
-	ensure_config_read();
 	git_config(ls_refs_config, &data);
 
 	while (packet_reader_read(request) == PACKET_READ_NORMAL) {
@@ -175,7 +172,7 @@ int ls_refs(struct repository *r, struct packet_reader *request)
 				strvec_push(&data.prefixes, out);
 		}
 		else if (!strcmp("unborn", arg))
-			data.unborn = allow_unborn;
+			data.unborn = !!unborn_config(r);
 		else
 			die(_("unexpected line: '%s'"), arg);
 	}
@@ -206,11 +203,8 @@ int ls_refs(struct repository *r, struct packet_reader *request)
 
 int ls_refs_advertise(struct repository *r, struct strbuf *value)
 {
-	if (value) {
-		ensure_config_read();
-		if (advertise_unborn)
-			strbuf_addstr(value, "unborn");
-	}
+	if (value && unborn_config(r) == UNBORN_ADVERTISE)
+		strbuf_addstr(value, "unborn");
 
 	return 1;
 }
diff --git a/mailinfo.c b/mailinfo.c
index 833d286..2aeb20e 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -1,5 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
 #include "utf8.h"
 #include "strbuf.h"
 #include "mailinfo.h"
@@ -597,7 +599,7 @@ static int check_header(struct mailinfo *mi,
 		ret = 1;
 		goto check_header_out;
 	}
-	if (parse_header(line, "Message-Id", mi, &sb)) {
+	if (parse_header(line, "Message-ID", mi, &sb)) {
 		if (mi->add_message_id)
 			mi->message_id = strbuf_detach(&sb, NULL);
 		ret = 1;
@@ -829,7 +831,7 @@ static int handle_commit_msg(struct mailinfo *mi, struct strbuf *line)
 	if (patchbreak(line)) {
 		if (mi->message_id)
 			strbuf_addf(&mi->log_message,
-				    "Message-Id: %s\n", mi->message_id);
+				    "Message-ID: %s\n", mi->message_id);
 		return 1;
 	}
 
diff --git a/mailmap.c b/mailmap.c
index da2589b..5dc5223 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -1,17 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "environment.h"
 #include "string-list.h"
 #include "mailmap.h"
+#include "object-name.h"
 #include "object-store.h"
-
-#define DEBUG_MAILMAP 0
-#if DEBUG_MAILMAP
-#define debug_mm(...) fprintf(stderr, __VA_ARGS__)
-#define debug_str(X) ((X) ? (X) : "(none)")
-#else
-__attribute__((format (printf, 1, 2)))
-static inline void debug_mm(const char *format, ...) {}
-static inline const char *debug_str(const char *s) { return s; }
-#endif
+#include "setup.h"
 
 const char *git_mailmap_file;
 const char *git_mailmap_blob;
@@ -30,23 +23,17 @@ struct mailmap_entry {
 	struct string_list namemap;
 };
 
-static void free_mailmap_info(void *p, const char *s)
+static void free_mailmap_info(void *p, const char *s UNUSED)
 {
 	struct mailmap_info *mi = (struct mailmap_info *)p;
-	debug_mm("mailmap: -- complex: '%s' -> '%s' <%s>\n",
-		 s, debug_str(mi->name), debug_str(mi->email));
 	free(mi->name);
 	free(mi->email);
 	free(mi);
 }
 
-static void free_mailmap_entry(void *p, const char *s)
+static void free_mailmap_entry(void *p, const char *s UNUSED)
 {
 	struct mailmap_entry *me = (struct mailmap_entry *)p;
-	debug_mm("mailmap: removing entries for <%s>, with %"PRIuMAX" sub-entries\n",
-		 s, (uintmax_t)me->namemap.nr);
-	debug_mm("mailmap: - simple: '%s' <%s>\n",
-		 debug_str(me->name), debug_str(me->email));
 
 	free(me->name);
 	free(me->email);
@@ -93,8 +80,6 @@ static void add_mapping(struct string_list *map,
 	}
 
 	if (!old_name) {
-		debug_mm("mailmap: adding (simple) entry for '%s'\n", old_email);
-
 		/* Replace current name and new email for simple entry */
 		if (new_name) {
 			free(me->name);
@@ -106,15 +91,10 @@ static void add_mapping(struct string_list *map,
 		}
 	} else {
 		struct mailmap_info *mi = xcalloc(1, sizeof(struct mailmap_info));
-		debug_mm("mailmap: adding (complex) entry for '%s'\n", old_email);
 		mi->name = xstrdup_or_null(new_name);
 		mi->email = xstrdup_or_null(new_email);
 		string_list_insert(&me->namemap, old_name)->util = mi;
 	}
-
-	debug_mm("mailmap:  '%s' <%s> -> '%s' <%s>\n",
-		 debug_str(old_name), old_email,
-		 debug_str(new_name), debug_str(new_email));
 }
 
 static char *parse_name_and_email(char *buffer, char **name,
@@ -213,10 +193,10 @@ static int read_mailmap_blob(struct string_list *map, const char *name)
 
 	if (!name)
 		return 0;
-	if (get_oid(name, &oid) < 0)
+	if (repo_get_oid(the_repository, name, &oid) < 0)
 		return 0;
 
-	buf = read_object_file(&oid, &type, &size);
+	buf = repo_read_object_file(the_repository, &oid, &type, &size);
 	if (!buf)
 		return error("unable to read mailmap object at %s", name);
 	if (type != OBJ_BLOB)
@@ -250,11 +230,8 @@ int read_mailmap(struct string_list *map)
 
 void clear_mailmap(struct string_list *map)
 {
-	debug_mm("mailmap: clearing %"PRIuMAX" entries...\n",
-		 (uintmax_t)map->nr);
 	map->strdup_strings = 1;
 	string_list_clear_func(map, free_mailmap_entry);
-	debug_mm("mailmap: cleared\n");
 }
 
 /*
@@ -315,10 +292,6 @@ int map_user(struct string_list *map,
 	struct string_list_item *item;
 	struct mailmap_entry *me;
 
-	debug_mm("map_user: map '%.*s' <%.*s>\n",
-		 (int)*namelen, debug_str(*name),
-		 (int)*emaillen, debug_str(*email));
-
 	item = lookup_prefix(map, *email, *emaillen);
 	if (item) {
 		me = (struct mailmap_entry *)item->util;
@@ -336,10 +309,8 @@ int map_user(struct string_list *map,
 	}
 	if (item) {
 		struct mailmap_info *mi = (struct mailmap_info *)item->util;
-		if (mi->name == NULL && mi->email == NULL) {
-			debug_mm("map_user:  -- (no simple mapping)\n");
+		if (mi->name == NULL && mi->email == NULL)
 			return 0;
-		}
 		if (mi->email) {
 				*email = mi->email;
 				*emaillen = strlen(*email);
@@ -348,11 +319,7 @@ int map_user(struct string_list *map,
 				*name = mi->name;
 				*namelen = strlen(*name);
 		}
-		debug_mm("map_user:  to '%.*s' <%.*s>\n",
-			 (int)*namelen, debug_str(*name),
-			 (int)*emaillen, debug_str(*email));
 		return 1;
 	}
-	debug_mm("map_user:  --\n");
 	return 0;
 }
diff --git a/mailmap.h b/mailmap.h
index 7e99fcc..0f8fd2c 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -3,6 +3,9 @@
 
 struct string_list;
 
+extern const char *git_mailmap_file;
+extern const char *git_mailmap_blob;
+
 int read_mailmap(struct string_list *map);
 void clear_mailmap(struct string_list *map);
 
diff --git a/match-trees.c b/match-trees.c
index 49398e5..6bc8eb7 100644
--- a/match-trees.c
+++ b/match-trees.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "hex.h"
+#include "match-trees.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "object-store.h"
@@ -55,7 +57,7 @@ static void *fill_tree_desc_strict(struct tree_desc *desc,
 	enum object_type type;
 	unsigned long size;
 
-	buffer = read_object_file(hash, &type, &size);
+	buffer = repo_read_object_file(the_repository, hash, &type, &size);
 	if (!buffer)
 		die("unable to read tree (%s)", oid_to_hex(hash));
 	if (type != OBJ_TREE)
@@ -188,7 +190,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,
 	if (*subpath)
 		subpath++;
 
-	buf = read_object_file(oid1, &type, &sz);
+	buf = repo_read_object_file(the_repository, oid1, &type, &sz);
 	if (!buf)
 		die("cannot read tree %s", oid_to_hex(oid1));
 	init_tree_desc(&desc, buf, sz);
diff --git a/match-trees.h b/match-trees.h
new file mode 100644
index 0000000..e3877ac
--- /dev/null
+++ b/match-trees.h
@@ -0,0 +1,10 @@
+#ifndef MATCH_TREES_H
+#define MATCH_TREES_H
+
+struct object_id;
+struct repository;
+
+void shift_tree(struct repository *, const struct object_id *, const struct object_id *, struct object_id *, int);
+void shift_tree_by(struct repository *, const struct object_id *, const struct object_id *, struct object_id *, const char *);
+
+#endif /* MATCH_TREES_H */
diff --git a/mem-pool.c b/mem-pool.c
index 599d8e8..c34846d 100644
--- a/mem-pool.c
+++ b/mem-pool.c
@@ -2,7 +2,7 @@
  * Memory Pool implementation logic.
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
 #include "mem-pool.h"
 
 #define BLOCK_GROWTH_SIZE (1024 * 1024 - sizeof(struct mp_block))
diff --git a/merge-blobs.c b/merge-blobs.c
index 8138090..5632ff6 100644
--- a/merge-blobs.c
+++ b/merge-blobs.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "run-command.h"
 #include "xdiff-interface.h"
 #include "ll-merge.h"
@@ -12,7 +12,8 @@ static int fill_mmfile_blob(mmfile_t *f, struct blob *obj)
 	unsigned long size;
 	enum object_type type;
 
-	buf = read_object_file(&obj->object.oid, &type, &size);
+	buf = repo_read_object_file(the_repository, &obj->object.oid, &type,
+				    &size);
 	if (!buf)
 		return -1;
 	if (type != OBJ_BLOB) {
@@ -78,7 +79,8 @@ void *merge_blobs(struct index_state *istate, const char *path,
 			return NULL;
 		if (!our)
 			our = their;
-		return read_object_file(&our->object.oid, &type, size);
+		return repo_read_object_file(the_repository, &our->object.oid,
+					     &type, size);
 	}
 
 	if (fill_mmfile_blob(&f1, our) < 0)
diff --git a/merge-ort-wrappers.c b/merge-ort-wrappers.c
index 748924a..a550753 100644
--- a/merge-ort-wrappers.c
+++ b/merge-ort-wrappers.c
@@ -1,6 +1,9 @@
 #include "cache.h"
+#include "gettext.h"
+#include "hash.h"
 #include "merge-ort.h"
 #include "merge-ort-wrappers.h"
+#include "tree.h"
 
 #include "commit.h"
 
diff --git a/merge-ort.c b/merge-ort.c
index d1611ca..a50b095 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -26,14 +26,22 @@
 #include "diff.h"
 #include "diffcore.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "entry.h"
 #include "ll-merge.h"
+#include "match-trees.h"
+#include "mem-pool.h"
+#include "object-name.h"
 #include "object-store.h"
+#include "oid-array.h"
 #include "promisor-remote.h"
 #include "revision.h"
 #include "strmap.h"
 #include "submodule-config.h"
 #include "submodule.h"
+#include "trace2.h"
 #include "tree.h"
 #include "unpack-trees.h"
 #include "xdiff-interface.h"
@@ -3505,7 +3513,7 @@ static int read_oid_strbuf(struct merge_options *opt,
 	void *buf;
 	enum object_type type;
 	unsigned long size;
-	buf = read_object_file(oid, &type, &size);
+	buf = repo_read_object_file(the_repository, oid, &type, &size);
 	if (!buf)
 		return err(opt, _("cannot read object %s"), oid_to_hex(oid));
 	if (type != OBJ_BLOB) {
@@ -4216,7 +4224,7 @@ static void prefetch_for_content_merges(struct merge_options *opt,
 	struct string_list_item *e;
 	struct oid_array to_fetch = OID_ARRAY_INIT;
 
-	if (opt->repo != the_repository || !has_promisor_remote())
+	if (opt->repo != the_repository || !repo_has_promisor_remote(the_repository))
 		return;
 
 	for (e = &plist->items[plist->nr-1]; e >= plist->items; --e) {
@@ -4715,14 +4723,14 @@ void merge_switch_to_result(struct merge_options *opt,
 void merge_finalize(struct merge_options *opt,
 		    struct merge_result *result)
 {
-	struct merge_options_internal *opti = result->priv;
-
 	if (opt->renormalize)
 		git_attr_set_direction(GIT_ATTR_CHECKIN);
 	assert(opt->priv == NULL);
 
-	clear_or_reinit_internal_opts(opti, 0);
-	FREE_AND_NULL(opti);
+	if (result->priv) {
+		clear_or_reinit_internal_opts(result->priv, 0);
+		FREE_AND_NULL(result->priv);
+	}
 }
 
 /*** Function Grouping: helper functions for merge_incore_*() ***/
@@ -5017,7 +5025,7 @@ static void merge_ort_internal(struct merge_options *opt,
 	struct strbuf merge_base_abbrev = STRBUF_INIT;
 
 	if (!merge_bases) {
-		merge_bases = get_merge_bases(h1, h2);
+		merge_bases = repo_get_merge_bases(the_repository, h1, h2);
 		/* See merge-ort.h:merge_incore_recursive() declaration NOTE */
 		merge_bases = reverse_commit_list(merge_bases);
 	}
diff --git a/merge-ort.h b/merge-ort.h
index a994c9a..ce56ec1 100644
--- a/merge-ort.h
+++ b/merge-ort.h
@@ -2,7 +2,7 @@
 #define MERGE_ORT_H
 
 #include "merge-recursive.h"
-#include "hash.h"
+#include "hash-ll.h"
 
 struct commit;
 struct tree;
diff --git a/merge-recursive.c b/merge-recursive.c
index ae469f8..8e87b63 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -10,7 +10,6 @@
 #include "alloc.h"
 #include "attr.h"
 #include "blob.h"
-#include "builtin.h"
 #include "cache-tree.h"
 #include "commit.h"
 #include "commit-reach.h"
@@ -18,17 +17,25 @@
 #include "diff.h"
 #include "diffcore.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "ll-merge.h"
 #include "lockfile.h"
+#include "match-trees.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "repository.h"
 #include "revision.h"
 #include "string-list.h"
 #include "submodule-config.h"
 #include "submodule.h"
+#include "symlinks.h"
 #include "tag.h"
 #include "tree-walk.h"
 #include "unpack-trees.h"
+#include "wrapper.h"
 #include "xdiff-interface.h"
 
 struct merge_options_internal {
@@ -951,7 +958,8 @@ static int update_file_flags(struct merge_options *opt,
 			goto update_index;
 		}
 
-		buf = read_object_file(&contents->oid, &type, &size);
+		buf = repo_read_object_file(the_repository, &contents->oid,
+					    &type, &size);
 		if (!buf) {
 			ret = err(opt, _("cannot read object %s '%s'"),
 				  oid_to_hex(&contents->oid), path);
@@ -3021,7 +3029,7 @@ static int read_oid_strbuf(struct merge_options *opt,
 	void *buf;
 	enum object_type type;
 	unsigned long size;
-	buf = read_object_file(oid, &type, &size);
+	buf = repo_read_object_file(the_repository, oid, &type, &size);
 	if (!buf)
 		return err(opt, _("cannot read object %s"), oid_to_hex(oid));
 	if (type != OBJ_BLOB) {
@@ -3592,7 +3600,7 @@ static int merge_recursive_internal(struct merge_options *opt,
 	}
 
 	if (!merge_bases) {
-		merge_bases = get_merge_bases(h1, h2);
+		merge_bases = repo_get_merge_bases(the_repository, h1, h2);
 		merge_bases = reverse_commit_list(merge_bases);
 	}
 
@@ -3797,7 +3805,7 @@ static struct commit *get_ref(struct repository *repo,
 		return make_virtual_commit(repo, (struct tree*)object, name);
 	if (object->type != OBJ_COMMIT)
 		return NULL;
-	if (parse_commit((struct commit *)object))
+	if (repo_parse_commit(repo, (struct commit *)object))
 		return NULL;
 	return (struct commit *)object;
 }
diff --git a/merge.c b/merge.c
index 445b4f1..10aaec3 100644
--- a/merge.c
+++ b/merge.c
@@ -1,10 +1,13 @@
 #include "cache.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "commit.h"
 #include "run-command.h"
 #include "resolve-undo.h"
+#include "tree.h"
 #include "tree-walk.h"
 #include "unpack-trees.h"
 #include "dir.h"
diff --git a/midx.c b/midx.c
index 7cfad04..b500174 100644
--- a/midx.c
+++ b/midx.c
@@ -1,9 +1,14 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
 #include "csum-file.h"
 #include "dir.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "packfile.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "hash-lookup.h"
 #include "midx.h"
@@ -1326,17 +1331,17 @@ static int write_midx_internal(const char *object_dir,
 	}
 
 	if (preferred_pack_name) {
-		int found = 0;
+		ctx.preferred_pack_idx = -1;
+
 		for (i = 0; i < ctx.nr; i++) {
 			if (!cmp_idx_or_pack_name(preferred_pack_name,
 						  ctx.info[i].pack_name)) {
 				ctx.preferred_pack_idx = i;
-				found = 1;
 				break;
 			}
 		}
 
-		if (!found)
+		if (ctx.preferred_pack_idx == -1)
 			warning(_("unknown preferred pack: '%s'"),
 				preferred_pack_name);
 	} else if (ctx.nr &&
@@ -1607,7 +1612,7 @@ struct clear_midx_data {
 	const char *ext;
 };
 
-static void clear_midx_file_ext(const char *full_path, size_t full_path_len,
+static void clear_midx_file_ext(const char *full_path, size_t full_path_len UNUSED,
 				const char *file_name, void *_data)
 {
 	struct clear_midx_data *data = _data;
diff --git a/name-hash.c b/name-hash.c
index cd009c7..fb13716 100644
--- a/name-hash.c
+++ b/name-hash.c
@@ -6,7 +6,10 @@
  * Copyright (C) 2008 Linus Torvalds
  */
 #include "cache.h"
+#include "environment.h"
+#include "gettext.h"
 #include "thread-utils.h"
+#include "trace.h"
 #include "trace2.h"
 #include "sparse-index.h"
 
diff --git a/negotiator/default.c b/negotiator/default.c
index b7e79fe..9a5b696 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -1,9 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "default.h"
 #include "../commit.h"
 #include "../fetch-negotiator.h"
 #include "../prio-queue.h"
 #include "../refs.h"
+#include "../repository.h"
 #include "../tag.h"
 
 /* Remember to update object flag allocation in object.h */
@@ -25,7 +26,7 @@ static void rev_list_push(struct negotiation_state *ns,
 	if (!(commit->object.flags & mark)) {
 		commit->object.flags |= mark;
 
-		if (parse_commit(commit))
+		if (repo_parse_commit(the_repository, commit))
 			return;
 
 		prio_queue_put(&ns->rev_list, commit);
@@ -55,30 +56,49 @@ static int clear_marks(const char *refname, const struct object_id *oid,
 static void mark_common(struct negotiation_state *ns, struct commit *commit,
 		int ancestors_only, int dont_parse)
 {
-	if (commit != NULL && !(commit->object.flags & COMMON)) {
-		struct object *o = (struct object *)commit;
+	struct prio_queue queue = { NULL };
 
-		if (!ancestors_only)
-			o->flags |= COMMON;
+	if (!commit || (commit->object.flags & COMMON))
+		return;
+
+	prio_queue_put(&queue, commit);
+	if (!ancestors_only) {
+		commit->object.flags |= COMMON;
+
+		if ((commit->object.flags & SEEN) && !(commit->object.flags & POPPED))
+			ns->non_common_revs--;
+	}
+	while ((commit = prio_queue_get(&queue))) {
+		struct object *o = (struct object *)commit;
 
 		if (!(o->flags & SEEN))
 			rev_list_push(ns, commit, SEEN);
 		else {
 			struct commit_list *parents;
 
-			if (!ancestors_only && !(o->flags & POPPED))
-				ns->non_common_revs--;
 			if (!o->parsed && !dont_parse)
-				if (parse_commit(commit))
-					return;
+				if (repo_parse_commit(the_repository, commit))
+					continue;
 
 			for (parents = commit->parents;
 					parents;
-					parents = parents->next)
-				mark_common(ns, parents->item, 0,
-					    dont_parse);
+					parents = parents->next) {
+				struct commit *p = parents->item;
+
+				if (p->object.flags & COMMON)
+					continue;
+
+				p->object.flags |= COMMON;
+
+				if ((p->object.flags & SEEN) && !(p->object.flags & POPPED))
+					ns->non_common_revs--;
+
+				prio_queue_put(&queue, parents->item);
+			}
 		}
 	}
+
+	clear_prio_queue(&queue);
 }
 
 /*
@@ -96,7 +116,7 @@ static const struct object_id *get_rev(struct negotiation_state *ns)
 			return NULL;
 
 		commit = prio_queue_get(&ns->rev_list);
-		parse_commit(commit);
+		repo_parse_commit(the_repository, commit);
 		parents = commit->parents;
 
 		commit->object.flags |= POPPED;
diff --git a/negotiator/noop.c b/negotiator/noop.c
index 60569b8..7b72937 100644
--- a/negotiator/noop.c
+++ b/negotiator/noop.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "noop.h"
 #include "../commit.h"
 #include "../fetch-negotiator.h"
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index 0f5ac48..5b91520 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -1,9 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "skipping.h"
 #include "../commit.h"
 #include "../fetch-negotiator.h"
+#include "../hex.h"
 #include "../prio-queue.h"
 #include "../refs.h"
+#include "../repository.h"
 #include "../tag.h"
 
 /* Remember to update object flag allocation in object.h */
@@ -50,7 +52,7 @@ struct data {
 	int non_common_revs;
 };
 
-static int compare(const void *a_, const void *b_, void *unused)
+static int compare(const void *a_, const void *b_, void *data UNUSED)
 {
 	const struct entry *a = a_;
 	const struct entry *b = b_;
@@ -84,29 +86,37 @@ static int clear_marks(const char *refname, const struct object_id *oid,
 }
 
 /*
- * Mark this SEEN commit and all its SEEN ancestors as COMMON.
+ * Mark this SEEN commit and all its parsed SEEN ancestors as COMMON.
  */
 static void mark_common(struct data *data, struct commit *seen_commit)
 {
 	struct prio_queue queue = { NULL };
 	struct commit *c;
 
+	if (seen_commit->object.flags & COMMON)
+		return;
+
 	prio_queue_put(&queue, seen_commit);
+	seen_commit->object.flags |= COMMON;
 	while ((c = prio_queue_get(&queue))) {
 		struct commit_list *p;
-		if (c->object.flags & COMMON)
-			return;
-		c->object.flags |= COMMON;
+
 		if (!(c->object.flags & POPPED))
 			data->non_common_revs--;
 
 		if (!c->object.parsed)
-			return;
+			continue;
 		for (p = c->parents; p; p = p->next) {
-			if (p->item->object.flags & SEEN)
-				prio_queue_put(&queue, p->item);
+			if (!(p->item->object.flags & SEEN) ||
+			    (p->item->object.flags & COMMON))
+				continue;
+
+			p->item->object.flags |= COMMON;
+			prio_queue_put(&queue, p->item);
 		}
 	}
+
+	clear_prio_queue(&queue);
 }
 
 /*
@@ -183,7 +193,7 @@ static const struct object_id *get_rev(struct data *data)
 		if (!(commit->object.flags & COMMON) && !entry->ttl)
 			to_send = commit;
 
-		parse_commit(commit);
+		repo_parse_commit(the_repository, commit);
 		for (p = commit->parents; p; p = p->next)
 			parent_pushed |= push_parent(data, entry, p->item);
 
diff --git a/notes-cache.c b/notes-cache.c
index 9dfd251..14288ca 100644
--- a/notes-cache.c
+++ b/notes-cache.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "notes-cache.h"
 #include "object-store.h"
+#include "pretty.h"
 #include "repository.h"
 #include "commit.h"
 #include "refs.h"
@@ -23,7 +24,8 @@ static int notes_cache_match_validity(struct repository *r,
 		return 0;
 
 	memset(&pretty_ctx, 0, sizeof(pretty_ctx));
-	format_commit_message(commit, "%s", &msg, &pretty_ctx);
+	repo_format_commit_message(r, commit, "%s", &msg,
+				   &pretty_ctx);
 	strbuf_trim(&msg);
 
 	ret = !strcmp(msg.buf, validity);
@@ -81,7 +83,7 @@ char *notes_cache_get(struct notes_cache *c, struct object_id *key_oid,
 	value_oid = get_note(&c->tree, key_oid);
 	if (!value_oid)
 		return NULL;
-	value = read_object_file(value_oid, &type, &size);
+	value = repo_read_object_file(the_repository, value_oid, &type, &size);
 
 	*outsize = size;
 	return value;
diff --git a/notes-merge.c b/notes-merge.c
index b4cc594..233e49e 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -1,18 +1,25 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
 #include "commit.h"
+#include "gettext.h"
 #include "refs.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "repository.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "hex.h"
 #include "xdiff-interface.h"
 #include "ll-merge.h"
 #include "dir.h"
 #include "notes.h"
 #include "notes-merge.h"
 #include "strbuf.h"
+#include "trace.h"
 #include "notes-utils.h"
 #include "commit-reach.h"
+#include "wrapper.h"
 
 struct notes_merge_pair {
 	struct object_id obj, base, local, remote;
@@ -326,7 +333,7 @@ static void write_note_to_worktree(const struct object_id *obj,
 {
 	enum object_type type;
 	unsigned long size;
-	void *buf = read_object_file(note, &type, &size);
+	void *buf = repo_read_object_file(the_repository, note, &type, &size);
 
 	if (!buf)
 		die("cannot read note %s for object %s",
@@ -566,7 +573,7 @@ int notes_merge(struct notes_merge_options *o,
 	trace_printf("\tlocal commit: %.7s\n", oid_to_hex(&local_oid));
 
 	/* Dereference o->remote_ref into remote_oid */
-	if (get_oid(o->remote_ref, &remote_oid)) {
+	if (repo_get_oid(the_repository, o->remote_ref, &remote_oid)) {
 		/*
 		 * Failed to get remote_oid. If o->remote_ref looks like an
 		 * unborn ref, perform the merge using an empty notes tree.
@@ -600,7 +607,7 @@ int notes_merge(struct notes_merge_options *o,
 	assert(local && remote);
 
 	/* Find merge bases */
-	bases = get_merge_bases(local, remote);
+	bases = repo_get_merge_bases(the_repository, local, remote);
 	if (!bases) {
 		base_oid = null_oid();
 		base_tree_oid = the_hash_algo->empty_tree;
@@ -678,7 +685,8 @@ int notes_merge_commit(struct notes_merge_options *o,
 	DIR *dir;
 	struct dirent *e;
 	struct strbuf path = STRBUF_INIT;
-	const char *buffer = get_commit_buffer(partial_commit, NULL);
+	const char *buffer = repo_get_commit_buffer(the_repository,
+						    partial_commit, NULL);
 	const char *msg = strstr(buffer, "\n\n");
 	int baselen;
 
@@ -725,7 +733,7 @@ int notes_merge_commit(struct notes_merge_options *o,
 
 	create_notes_commit(o->repo, partial_tree, partial_commit->parents, msg,
 			    strlen(msg), result_oid);
-	unuse_commit_buffer(partial_commit, buffer);
+	repo_unuse_commit_buffer(the_repository, partial_commit, buffer);
 	if (o->verbosity >= 4)
 		printf("Finalized notes merge commit: %s\n",
 			oid_to_hex(result_oid));
diff --git a/notes-utils.c b/notes-utils.c
index d7d18e3..4a793eb 100644
--- a/notes-utils.c
+++ b/notes-utils.c
@@ -1,9 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "commit.h"
+#include "environment.h"
+#include "gettext.h"
 #include "refs.h"
 #include "notes-utils.h"
 #include "repository.h"
+#include "strbuf.h"
 
 void create_notes_commit(struct repository *r,
 			 struct notes_tree *t,
@@ -23,7 +26,7 @@ void create_notes_commit(struct repository *r,
 		struct object_id parent_oid;
 		if (!read_ref(t->ref, &parent_oid)) {
 			struct commit *parent = lookup_commit(r, &parent_oid);
-			if (parse_commit(parent))
+			if (repo_parse_commit(r, parent))
 				die("Failed to find/parse commit %s", t->ref);
 			commit_list_insert(parent, &parents);
 		}
diff --git a/notes.c b/notes.c
index f2805d5..f51a2d3 100644
--- a/notes.c
+++ b/notes.c
@@ -1,6 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "environment.h"
+#include "hex.h"
 #include "notes.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "blob.h"
 #include "tree.h"
@@ -752,7 +755,7 @@ static int write_each_non_note_until(const char *note_path,
 	return 0;
 }
 
-static int write_each_note(const struct object_id *object_oid,
+static int write_each_note(const struct object_id *object_oid UNUSED,
 		const struct object_id *note_oid, char *note_path,
 		void *cb_data)
 {
@@ -780,13 +783,14 @@ struct note_delete_list {
 };
 
 static int prune_notes_helper(const struct object_id *object_oid,
-		const struct object_id *note_oid, char *note_path,
-		void *cb_data)
+			      const struct object_id *note_oid UNUSED,
+			      char *note_path UNUSED,
+			      void *cb_data)
 {
 	struct note_delete_list **l = (struct note_delete_list **) cb_data;
 	struct note_delete_list *n;
 
-	if (has_object_file(object_oid))
+	if (repo_has_object_file(the_repository, object_oid))
 		return 0; /* nothing to do for this note */
 
 	/* failed to find object => prune this note */
@@ -807,13 +811,15 @@ int combine_notes_concatenate(struct object_id *cur_oid,
 
 	/* read in both note blob objects */
 	if (!is_null_oid(new_oid))
-		new_msg = read_object_file(new_oid, &new_type, &new_len);
+		new_msg = repo_read_object_file(the_repository, new_oid,
+						&new_type, &new_len);
 	if (!new_msg || !new_len || new_type != OBJ_BLOB) {
 		free(new_msg);
 		return 0;
 	}
 	if (!is_null_oid(cur_oid))
-		cur_msg = read_object_file(cur_oid, &cur_type, &cur_len);
+		cur_msg = repo_read_object_file(the_repository, cur_oid,
+						&cur_type, &cur_len);
 	if (!cur_msg || !cur_len || cur_type != OBJ_BLOB) {
 		free(cur_msg);
 		free(new_msg);
@@ -848,8 +854,8 @@ int combine_notes_overwrite(struct object_id *cur_oid,
 	return 0;
 }
 
-int combine_notes_ignore(struct object_id *cur_oid,
-			 const struct object_id *new_oid)
+int combine_notes_ignore(struct object_id *cur_oid UNUSED,
+			 const struct object_id *new_oid UNUSED)
 {
 	return 0;
 }
@@ -869,7 +875,7 @@ static int string_list_add_note_lines(struct string_list *list,
 		return 0;
 
 	/* read_sha1_file NUL-terminates */
-	data = read_object_file(oid, &t, &len);
+	data = repo_read_object_file(the_repository, oid, &t, &len);
 	if (t != OBJ_BLOB || !data || !len) {
 		free(data);
 		return t != OBJ_BLOB || !data;
@@ -944,7 +950,7 @@ void string_list_add_refs_by_glob(struct string_list *list, const char *glob)
 		for_each_glob_ref(string_list_add_one_ref, glob, list);
 	} else {
 		struct object_id oid;
-		if (get_oid(glob, &oid))
+		if (repo_get_oid(the_repository, glob, &oid))
 			warning("notes ref %s is invalid", glob);
 		if (!unsorted_string_list_has_string(list, glob))
 			string_list_append(list, glob);
@@ -958,7 +964,7 @@ void string_list_add_refs_from_colon_sep(struct string_list *list,
 	char *globs_copy = xstrdup(globs);
 	int i;
 
-	string_list_split_in_place(&split, globs_copy, ':', -1);
+	string_list_split_in_place(&split, globs_copy, ":", -1);
 	string_list_remove_empty_items(&split, 0);
 
 	for (i = 0; i < split.nr; i++)
@@ -1014,14 +1020,14 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
 	t->root = (struct int_node *) xcalloc(1, sizeof(struct int_node));
 	t->first_non_note = NULL;
 	t->prev_non_note = NULL;
-	t->ref = xstrdup_or_null(notes_ref);
+	t->ref = xstrdup(notes_ref);
 	t->update_ref = (flags & NOTES_INIT_WRITABLE) ? t->ref : NULL;
 	t->combine_notes = combine_notes;
 	t->initialized = 1;
 	t->dirty = 0;
 
-	if (flags & NOTES_INIT_EMPTY || !notes_ref ||
-	    get_oid_treeish(notes_ref, &object_oid))
+	if (flags & NOTES_INIT_EMPTY ||
+	    repo_get_oid_treeish(the_repository, notes_ref, &object_oid))
 		return;
 	if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, &object_oid))
 		die("Cannot use notes ref %s", notes_ref);
@@ -1264,7 +1270,7 @@ static void format_note(struct notes_tree *t, const struct object_id *object_oid
 	if (!oid)
 		return;
 
-	if (!(msg = read_object_file(oid, &type, &msglen)) || type != OBJ_BLOB) {
+	if (!(msg = repo_read_object_file(the_repository, oid, &type, &msglen)) || type != OBJ_BLOB) {
 		free(msg);
 		return;
 	}
@@ -1348,7 +1354,7 @@ void expand_loose_notes_ref(struct strbuf *sb)
 {
 	struct object_id object;
 
-	if (get_oid(sb->buf, &object)) {
+	if (repo_get_oid(the_repository, sb->buf, &object)) {
 		/* fallback to expand_notes_ref */
 		expand_notes_ref(sb);
 	}
diff --git a/object-file.c b/object-file.c
index 939865c..7c1af5c 100644
--- a/object-file.c
+++ b/object-file.c
@@ -6,8 +6,14 @@
  * This handles basic git object files - packing, unpacking,
  * creation etc.
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
+#include "convert.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "string-list.h"
 #include "lockfile.h"
 #include "delta.h"
@@ -30,10 +36,14 @@
 #include "mergesort.h"
 #include "quote.h"
 #include "packfile.h"
+#include "object-file.h"
 #include "object-store.h"
+#include "oidtree.h"
 #include "promisor-remote.h"
+#include "setup.h"
 #include "submodule.h"
 #include "fsck.h"
+#include "wrapper.h"
 
 /* The maximum size for an object header. */
 #define MAX_HEADER_LEN 32
@@ -267,7 +277,7 @@ int hash_algo_by_length(int len)
 
 /*
  * This is meant to hold a *small* number of objects that you would
- * want read_object_file() to be able to return, but yet you do not want
+ * want repo_read_object_file() to be able to return, but yet you do not want
  * to write them into the object store (e.g. a browse-only
  * application).
  */
@@ -944,6 +954,12 @@ void prepare_alt_odb(struct repository *r)
 	r->objects->loaded_alternates = 1;
 }
 
+int has_alt_odb(struct repository *r)
+{
+	prepare_alt_odb(r);
+	return !!r->objects->odb->next;
+}
+
 /* Returns 1 if we have successfully freshened the file, 0 otherwise. */
 static int freshen_file(const char *fn)
 {
@@ -1678,7 +1694,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type,
 	struct cached_object *co;
 
 	hash_object_file(the_hash_algo, buf, len, type, oid);
-	if (has_object_file_with_flags(oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) ||
+	if (repo_has_object_file_with_flags(the_repository, oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) ||
 	    find_cached_object(oid))
 		return 0;
 	ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc);
@@ -2644,7 +2660,8 @@ int for_each_loose_object(each_loose_object_fn cb, void *data,
 	return 0;
 }
 
-static int append_loose_object(const struct object_id *oid, const char *path,
+static int append_loose_object(const struct object_id *oid,
+			       const char *path UNUSED,
 			       void *data)
 {
 	oidtree_insert(data, oid);
diff --git a/object-file.h b/object-file.h
new file mode 100644
index 0000000..d641461
--- /dev/null
+++ b/object-file.h
@@ -0,0 +1,131 @@
+#ifndef OBJECT_FILE_H
+#define OBJECT_FILE_H
+
+#include "git-zlib.h"
+#include "object.h"
+
+struct index_state;
+
+/*
+ * Set this to 0 to prevent oid_object_info_extended() from fetching missing
+ * blobs. This has a difference only if extensions.partialClone is set.
+ *
+ * Its default value is 1.
+ */
+extern int fetch_if_missing;
+
+#define HASH_WRITE_OBJECT 1
+#define HASH_FORMAT_CHECK 2
+#define HASH_RENORMALIZE  4
+#define HASH_SILENT 8
+int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
+int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
+
+/*
+ * Create the directory containing the named path, using care to be
+ * somewhat safe against races. Return one of the scld_error values to
+ * indicate success/failure. On error, set errno to describe the
+ * problem.
+ *
+ * SCLD_VANISHED indicates that one of the ancestor directories of the
+ * path existed at one point during the function call and then
+ * suddenly vanished, probably because another process pruned the
+ * directory while we were working.  To be robust against this kind of
+ * race, callers might want to try invoking the function again when it
+ * returns SCLD_VANISHED.
+ *
+ * safe_create_leading_directories() temporarily changes path while it
+ * is working but restores it before returning.
+ * safe_create_leading_directories_const() doesn't modify path, even
+ * temporarily. Both these variants adjust the permissions of the
+ * created directories to honor core.sharedRepository, so they are best
+ * suited for files inside the git dir. For working tree files, use
+ * safe_create_leading_directories_no_share() instead, as it ignores
+ * the core.sharedRepository setting.
+ */
+enum scld_error {
+	SCLD_OK = 0,
+	SCLD_FAILED = -1,
+	SCLD_PERMS = -2,
+	SCLD_EXISTS = -3,
+	SCLD_VANISHED = -4
+};
+enum scld_error safe_create_leading_directories(char *path);
+enum scld_error safe_create_leading_directories_const(const char *path);
+enum scld_error safe_create_leading_directories_no_share(char *path);
+
+int mkdir_in_gitdir(const char *path);
+
+int git_open_cloexec(const char *name, int flags);
+#define git_open(name) git_open_cloexec(name, O_RDONLY)
+
+/**
+ * unpack_loose_header() initializes the data stream needed to unpack
+ * a loose object header.
+ *
+ * Returns:
+ *
+ * - ULHR_OK on success
+ * - ULHR_BAD on error
+ * - ULHR_TOO_LONG if the header was too long
+ *
+ * It will only parse up to MAX_HEADER_LEN bytes unless an optional
+ * "hdrbuf" argument is non-NULL. This is intended for use with
+ * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
+ * reporting. The full header will be extracted to "hdrbuf" for use
+ * with parse_loose_header(), ULHR_TOO_LONG will still be returned
+ * from this function to indicate that the header was too long.
+ */
+enum unpack_loose_header_result {
+	ULHR_OK,
+	ULHR_BAD,
+	ULHR_TOO_LONG,
+};
+enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
+						    unsigned char *map,
+						    unsigned long mapsize,
+						    void *buffer,
+						    unsigned long bufsiz,
+						    struct strbuf *hdrbuf);
+
+/**
+ * parse_loose_header() parses the starting "<type> <len>\0" of an
+ * object. If it doesn't follow that format -1 is returned. To check
+ * the validity of the <type> populate the "typep" in the "struct
+ * object_info". It will be OBJ_BAD if the object type is unknown. The
+ * parsed <len> can be retrieved via "oi->sizep", and from there
+ * passed to unpack_loose_rest().
+ */
+struct object_info;
+int parse_loose_header(const char *hdr, struct object_info *oi);
+
+/**
+ * With in-core object data in "buf", rehash it to make sure the
+ * object name actually matches "oid" to detect object corruption.
+ *
+ * A negative value indicates an error, usually that the OID is not
+ * what we expected, but it might also indicate another error.
+ */
+int check_object_signature(struct repository *r, const struct object_id *oid,
+			   void *map, unsigned long size,
+			   enum object_type type);
+
+/**
+ * A streaming version of check_object_signature().
+ * Try reading the object named with "oid" using
+ * the streaming interface and rehash it to do the same.
+ */
+int stream_object_signature(struct repository *r, const struct object_id *oid);
+
+int finalize_object_file(const char *tmpfile, const char *filename);
+
+/* Helper to check and "touch" a file */
+int check_and_freshen_file(const char *fn, int freshen);
+
+void *read_object_with_reference(struct repository *r,
+				 const struct object_id *oid,
+				 enum object_type required_type,
+				 unsigned long *size,
+				 struct object_id *oid_ret);
+
+#endif /* OBJECT_FILE_H */
diff --git a/object-name.c b/object-name.c
index 2dd1a0f..6fc3fa5 100644
--- a/object-name.c
+++ b/object-name.c
@@ -1,5 +1,10 @@
 #include "cache.h"
+#include "object-name.h"
+#include "advice.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "tag.h"
 #include "commit.h"
 #include "tree.h"
@@ -9,9 +14,12 @@
 #include "remote.h"
 #include "dir.h"
 #include "oid-array.h"
+#include "oidtree.h"
 #include "packfile.h"
+#include "pretty.h"
 #include "object-store.h"
 #include "repository.h"
+#include "setup.h"
 #include "submodule.h"
 #include "midx.h"
 #include "commit-reach.h"
@@ -223,7 +231,7 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,
 
 static int disambiguate_commit_only(struct repository *r,
 				    const struct object_id *oid,
-				    void *cb_data_unused)
+				    void *cb_data UNUSED)
 {
 	int kind = oid_object_info(r, oid, NULL);
 	return kind == OBJ_COMMIT;
@@ -231,7 +239,7 @@ static int disambiguate_commit_only(struct repository *r,
 
 static int disambiguate_committish_only(struct repository *r,
 					const struct object_id *oid,
-					void *cb_data_unused)
+					void *cb_data UNUSED)
 {
 	struct object *obj;
 	int kind;
@@ -251,7 +259,7 @@ static int disambiguate_committish_only(struct repository *r,
 
 static int disambiguate_tree_only(struct repository *r,
 				  const struct object_id *oid,
-				  void *cb_data_unused)
+				  void *cb_data UNUSED)
 {
 	int kind = oid_object_info(r, oid, NULL);
 	return kind == OBJ_TREE;
@@ -259,7 +267,7 @@ static int disambiguate_tree_only(struct repository *r,
 
 static int disambiguate_treeish_only(struct repository *r,
 				     const struct object_id *oid,
-				     void *cb_data_unused)
+				     void *cb_data UNUSED)
 {
 	struct object *obj;
 	int kind;
@@ -279,7 +287,7 @@ static int disambiguate_treeish_only(struct repository *r,
 
 static int disambiguate_blob_only(struct repository *r,
 				  const struct object_id *oid,
-				  void *cb_data_unused)
+				  void *cb_data UNUSED)
 {
 	int kind = oid_object_info(r, oid, NULL);
 	return kind == OBJ_BLOB;
@@ -394,8 +402,10 @@ static int show_ambiguous_object(const struct object_id *oid, void *data)
 		if (commit) {
 			struct pretty_print_context pp = {0};
 			pp.date_mode.type = DATE_SHORT;
-			format_commit_message(commit, "%ad", &date, &pp);
-			format_commit_message(commit, "%s", &msg, &pp);
+			repo_format_commit_message(the_repository, commit,
+						   "%ad", &date, &pp);
+			repo_format_commit_message(the_repository, commit,
+						   "%s", &msg, &pp);
 		}
 
 		/*
@@ -473,7 +483,7 @@ static int collect_ambiguous(const struct object_id *oid, void *data)
 	return 0;
 }
 
-static int repo_collect_ambiguous(struct repository *r,
+static int repo_collect_ambiguous(struct repository *r UNUSED,
 				  const struct object_id *oid,
 				  void *data)
 {
@@ -665,7 +675,7 @@ static int extend_abbrev_len(const struct object_id *oid, void *cb_data)
 	return 0;
 }
 
-static int repo_extend_abbrev_len(struct repository *r,
+static int repo_extend_abbrev_len(struct repository *r UNUSED,
 				  const struct object_id *oid,
 				  void *cb_data)
 {
@@ -898,6 +908,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
 	char *real_ref = NULL;
 	int refs_found = 0;
 	int at, reflog_len, nth_prior = 0;
+	int fatal = !(flags & GET_OID_QUIETLY);
 
 	if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
 		if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {
@@ -952,11 +963,11 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
 
 	if (!len && reflog_len)
 		/* allow "@{...}" to mean the current branch reflog */
-		refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref, 0);
+		refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref, !fatal);
 	else if (reflog_len)
 		refs_found = repo_dwim_log(r, str, len, oid, &real_ref);
 	else
-		refs_found = repo_dwim_ref(r, str, len, oid, &real_ref, 0);
+		refs_found = repo_dwim_ref(r, str, len, oid, &real_ref, !fatal);
 
 	if (!refs_found)
 		return -1;
@@ -1036,7 +1047,7 @@ static enum get_oid_result get_parent(struct repository *r,
 	if (ret)
 		return ret;
 	commit = lookup_commit_reference(r, &oid);
-	if (parse_commit(commit))
+	if (repo_parse_commit(r, commit))
 		return MISSING_OBJECT;
 	if (!idx) {
 		oidcpy(result, &commit->object.oid);
@@ -1070,7 +1081,7 @@ static enum get_oid_result get_nth_ancestor(struct repository *r,
 		return MISSING_OBJECT;
 
 	while (generation--) {
-		if (parse_commit(commit) || !commit->parents)
+		if (repo_parse_commit(r, commit) || !commit->parents)
 			return MISSING_OBJECT;
 		commit = commit->parents->item;
 	}
@@ -1361,10 +1372,10 @@ static int get_oid_oneline(struct repository *r,
 		commit = pop_most_recent_commit(&list, ONELINE_SEEN);
 		if (!parse_object(r, &commit->object.oid))
 			continue;
-		buf = get_commit_buffer(commit, NULL);
+		buf = repo_get_commit_buffer(r, commit, NULL);
 		p = strstr(buf, "\n\n");
 		matches = negative ^ (p && !regexec(&regex, p + 2, 0, NULL, 0));
-		unuse_commit_buffer(commit, buf);
+		repo_unuse_commit_buffer(r, commit, buf);
 
 		if (matches) {
 			oidcpy(oid, &commit->object.oid);
@@ -1666,7 +1677,8 @@ void strbuf_branchname(struct strbuf *sb, const char *name, unsigned allowed)
 	struct interpret_branch_name_options options = {
 		.allowed = allowed
 	};
-	int used = interpret_branch_name(name, len, sb, &options);
+	int used = repo_interpret_branch_name(the_repository, name, len, sb,
+					      &options);
 
 	if (used < 0)
 		used = 0;
@@ -1719,7 +1731,7 @@ int get_oidf(struct object_id *oid, const char *fmt, ...)
 	strbuf_vaddf(&sb, fmt, ap);
 	va_end(ap);
 
-	ret = get_oid(sb.buf, oid);
+	ret = repo_get_oid(the_repository, sb.buf, oid);
 	strbuf_release(&sb);
 
 	return ret;
diff --git a/object-name.h b/object-name.h
new file mode 100644
index 0000000..1d63698
--- /dev/null
+++ b/object-name.h
@@ -0,0 +1,121 @@
+#ifndef OBJECT_NAME_H
+#define OBJECT_NAME_H
+
+#include "object.h"
+#include "strbuf.h"
+
+struct object_id;
+struct repository;
+
+struct object_context {
+	unsigned short mode;
+	/*
+	 * symlink_path is only used by get_tree_entry_follow_symlinks,
+	 * and only for symlinks that point outside the repository.
+	 */
+	struct strbuf symlink_path;
+	/*
+	 * If GET_OID_RECORD_PATH is set, this will record path (if any)
+	 * found when resolving the name. The caller is responsible for
+	 * releasing the memory.
+	 */
+	char *path;
+};
+
+/*
+ * Return an abbreviated sha1 unique within this repository's object database.
+ * The result will be at least `len` characters long, and will be NUL
+ * terminated.
+ *
+ * The non-`_r` version returns a static buffer which remains valid until 4
+ * more calls to repo_find_unique_abbrev are made.
+ *
+ * The `_r` variant writes to a buffer supplied by the caller, which must be at
+ * least `GIT_MAX_HEXSZ + 1` bytes. The return value is the number of bytes
+ * written (excluding the NUL terminator).
+ *
+ * Note that while this version avoids the static buffer, it is not fully
+ * reentrant, as it calls into other non-reentrant git code.
+ */
+const char *repo_find_unique_abbrev(struct repository *r, const struct object_id *oid, int len);
+int repo_find_unique_abbrev_r(struct repository *r, char *hex, const struct object_id *oid, int len);
+
+int repo_get_oid(struct repository *r, const char *str, struct object_id *oid);
+__attribute__((format (printf, 2, 3)))
+int get_oidf(struct object_id *oid, const char *fmt, ...);
+int repo_get_oid_commit(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_committish(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_tree(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_treeish(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_blob(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_mb(struct repository *r, const char *str, struct object_id *oid);
+void maybe_die_on_misspelt_object_name(struct repository *repo,
+				       const char *name,
+				       const char *prefix);
+enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
+					 unsigned flags, struct object_id *oid,
+					 struct object_context *oc);
+
+
+typedef int each_abbrev_fn(const struct object_id *oid, void *);
+int repo_for_each_abbrev(struct repository *r, const char *prefix, each_abbrev_fn, void *);
+
+int set_disambiguate_hint_config(const char *var, const char *value);
+
+/*
+ * This reads short-hand syntax that not only evaluates to a commit
+ * object name, but also can act as if the end user spelled the name
+ * of the branch from the command line.
+ *
+ * - "@{-N}" finds the name of the Nth previous branch we were on, and
+ *   places the name of the branch in the given buf and returns the
+ *   number of characters parsed if successful.
+ *
+ * - "<branch>@{upstream}" finds the name of the other ref that
+ *   <branch> is configured to merge with (missing <branch> defaults
+ *   to the current branch), and places the name of the branch in the
+ *   given buf and returns the number of characters parsed if
+ *   successful.
+ *
+ * If the input is not of the accepted format, it returns a negative
+ * number to signal an error.
+ *
+ * If the input was ok but there are not N branch switches in the
+ * reflog, it returns 0.
+ */
+#define INTERPRET_BRANCH_LOCAL (1<<0)
+#define INTERPRET_BRANCH_REMOTE (1<<1)
+#define INTERPRET_BRANCH_HEAD (1<<2)
+struct interpret_branch_name_options {
+	/*
+	 * If "allowed" is non-zero, it is a treated as a bitfield of allowable
+	 * expansions: local branches ("refs/heads/"), remote branches
+	 * ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
+	 * allowed, even ones to refs outside of those namespaces.
+	 */
+	unsigned allowed;
+
+	/*
+	 * If ^{upstream} or ^{push} (or equivalent) is requested, and the
+	 * branch in question does not have such a reference, return -1 instead
+	 * of die()-ing.
+	 */
+	unsigned nonfatal_dangling_mark : 1;
+};
+int repo_interpret_branch_name(struct repository *r,
+			       const char *str, int len,
+			       struct strbuf *buf,
+			       const struct interpret_branch_name_options *options);
+
+struct object *repo_peel_to_type(struct repository *r,
+				 const char *name, int namelen,
+				 struct object *o, enum object_type);
+
+/* Convert to/from hex/sha1 representation */
+#define MINIMUM_ABBREV minimum_abbrev
+#define DEFAULT_ABBREV default_abbrev
+
+/* used when the code does not know or care what the default abbrev is */
+#define FALLBACK_DEFAULT_ABBREV 7
+
+#endif /* OBJECT_NAME_H */
diff --git a/object-store.h b/object-store.h
index 1a713d8..12415e5 100644
--- a/object-store.h
+++ b/object-store.h
@@ -1,17 +1,17 @@
 #ifndef OBJECT_STORE_H
 #define OBJECT_STORE_H
 
-#include "cache.h"
-#include "oidmap.h"
+#include "object.h"
 #include "list.h"
-#include "oid-array.h"
-#include "strbuf.h"
 #include "thread-utils.h"
 #include "khash.h"
 #include "dir.h"
-#include "oidtree.h"
 #include "oidset.h"
 
+struct oidmap;
+struct oidtree;
+struct strbuf;
+
 struct object_directory {
 	struct object_directory *next;
 
@@ -56,6 +56,7 @@ KHASH_INIT(odb_path_map, const char * /* key: odb_path */,
 	struct object_directory *, 1, fspathhash, fspatheq)
 
 void prepare_alt_odb(struct repository *r);
+int has_alt_odb(struct repository *r);
 char *compute_alternate_path(const char *path, struct strbuf *err);
 struct object_directory *find_odb(struct repository *r, const char *obj_dir);
 typedef int alt_odb_fn(struct object_directory *, void *);
@@ -216,7 +217,7 @@ struct raw_object_store {
 	/*
 	 * A fast, rough count of the number of objects in the repository.
 	 * These two fields are not meant for direct access. Use
-	 * approximate_object_count() instead.
+	 * repo_approximate_object_count() instead.
 	 */
 	unsigned long approximate_object_count;
 	unsigned approximate_object_count_valid : 1;
@@ -245,9 +246,6 @@ void *repo_read_object_file(struct repository *r,
 			    const struct object_id *oid,
 			    enum object_type *type,
 			    unsigned long *size);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define read_object_file(oid, type, size) repo_read_object_file(the_repository, oid, type, size)
-#endif
 
 /* Read and unpack an object file into memory, write memory to an object file */
 int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);
@@ -284,103 +282,6 @@ int pretend_object_file(void *, unsigned long, enum object_type,
 
 int force_object_loose(const struct object_id *oid, time_t mtime);
 
-/*
- * Open the loose object at path, check its hash, and return the contents,
- * use the "oi" argument to assert things about the object, or e.g. populate its
- * type, and size. If the object is a blob, then "contents" may return NULL,
- * to allow streaming of large blobs.
- *
- * Returns 0 on success, negative on error (details may be written to stderr).
- */
-int read_loose_object(const char *path,
-		      const struct object_id *expected_oid,
-		      struct object_id *real_oid,
-		      void **contents,
-		      struct object_info *oi);
-
-/* Retry packed storage after checking packed and loose storage */
-#define HAS_OBJECT_RECHECK_PACKED 1
-
-/*
- * Returns 1 if the object exists. This function will not lazily fetch objects
- * in a partial clone.
- */
-int has_object(struct repository *r, const struct object_id *oid,
-	       unsigned flags);
-
-/*
- * These macros and functions are deprecated. If checking existence for an
- * object that is likely to be missing and/or whose absence is relatively
- * inconsequential (or is consequential but the caller is prepared to handle
- * it), use has_object(), which has better defaults (no lazy fetch in a partial
- * clone and no rechecking of packed storage). In the unlikely event that a
- * caller needs to assert existence of an object that it fully expects to
- * exist, and wants to trigger a lazy fetch in a partial clone, use
- * oid_object_info_extended() with a NULL struct object_info.
- *
- * These functions can be removed once all callers have migrated to
- * has_object() and/or oid_object_info_extended().
- */
-int repo_has_object_file(struct repository *r, const struct object_id *oid);
-int repo_has_object_file_with_flags(struct repository *r,
-				    const struct object_id *oid, int flags);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define has_object_file(oid) repo_has_object_file(the_repository, oid)
-#define has_object_file_with_flags(oid, flags) repo_has_object_file_with_flags(the_repository, oid, flags)
-#endif
-
-/*
- * Return true iff an alternate object database has a loose object
- * with the specified name.  This function does not respect replace
- * references.
- */
-int has_loose_object_nonlocal(const struct object_id *);
-
-int has_loose_object(const struct object_id *);
-
-/**
- * format_object_header() is a thin wrapper around s xsnprintf() that
- * writes the initial "<type> <obj-len>" part of the loose object
- * header. It returns the size that snprintf() returns + 1.
- */
-int format_object_header(char *str, size_t size, enum object_type type,
-			 size_t objsize);
-
-void assert_oid_type(const struct object_id *oid, enum object_type expect);
-
-/*
- * Enabling the object read lock allows multiple threads to safely call the
- * following functions in parallel: repo_read_object_file(), read_object_file(),
- * read_object_with_reference(), oid_object_info() and oid_object_info_extended().
- *
- * obj_read_lock() and obj_read_unlock() may also be used to protect other
- * section which cannot execute in parallel with object reading. Since the used
- * lock is a recursive mutex, these sections can even contain calls to object
- * reading functions. However, beware that in these cases zlib inflation won't
- * be performed in parallel, losing performance.
- *
- * TODO: oid_object_info_extended()'s call stack has a recursive behavior. If
- * any of its callees end up calling it, this recursive call won't benefit from
- * parallel inflation.
- */
-void enable_obj_read_lock(void);
-void disable_obj_read_lock(void);
-
-extern int obj_read_use_lock;
-extern pthread_mutex_t obj_read_mutex;
-
-static inline void obj_read_lock(void)
-{
-	if(obj_read_use_lock)
-		pthread_mutex_lock(&obj_read_mutex);
-}
-
-static inline void obj_read_unlock(void)
-{
-	if(obj_read_use_lock)
-		pthread_mutex_unlock(&obj_read_mutex);
-}
-
 struct object_info {
 	/* Request */
 	enum object_type *typep;
@@ -445,6 +346,99 @@ int oid_object_info_extended(struct repository *r,
 			     struct object_info *, unsigned flags);
 
 /*
+ * Open the loose object at path, check its hash, and return the contents,
+ * use the "oi" argument to assert things about the object, or e.g. populate its
+ * type, and size. If the object is a blob, then "contents" may return NULL,
+ * to allow streaming of large blobs.
+ *
+ * Returns 0 on success, negative on error (details may be written to stderr).
+ */
+int read_loose_object(const char *path,
+		      const struct object_id *expected_oid,
+		      struct object_id *real_oid,
+		      void **contents,
+		      struct object_info *oi);
+
+/* Retry packed storage after checking packed and loose storage */
+#define HAS_OBJECT_RECHECK_PACKED 1
+
+/*
+ * Returns 1 if the object exists. This function will not lazily fetch objects
+ * in a partial clone.
+ */
+int has_object(struct repository *r, const struct object_id *oid,
+	       unsigned flags);
+
+/*
+ * These macros and functions are deprecated. If checking existence for an
+ * object that is likely to be missing and/or whose absence is relatively
+ * inconsequential (or is consequential but the caller is prepared to handle
+ * it), use has_object(), which has better defaults (no lazy fetch in a partial
+ * clone and no rechecking of packed storage). In the unlikely event that a
+ * caller needs to assert existence of an object that it fully expects to
+ * exist, and wants to trigger a lazy fetch in a partial clone, use
+ * oid_object_info_extended() with a NULL struct object_info.
+ *
+ * These functions can be removed once all callers have migrated to
+ * has_object() and/or oid_object_info_extended().
+ */
+int repo_has_object_file(struct repository *r, const struct object_id *oid);
+int repo_has_object_file_with_flags(struct repository *r,
+				    const struct object_id *oid, int flags);
+
+/*
+ * Return true iff an alternate object database has a loose object
+ * with the specified name.  This function does not respect replace
+ * references.
+ */
+int has_loose_object_nonlocal(const struct object_id *);
+
+int has_loose_object(const struct object_id *);
+
+/**
+ * format_object_header() is a thin wrapper around s xsnprintf() that
+ * writes the initial "<type> <obj-len>" part of the loose object
+ * header. It returns the size that snprintf() returns + 1.
+ */
+int format_object_header(char *str, size_t size, enum object_type type,
+			 size_t objsize);
+
+void assert_oid_type(const struct object_id *oid, enum object_type expect);
+
+/*
+ * Enabling the object read lock allows multiple threads to safely call the
+ * following functions in parallel: repo_read_object_file(),
+ * read_object_with_reference(), oid_object_info() and oid_object_info_extended().
+ *
+ * obj_read_lock() and obj_read_unlock() may also be used to protect other
+ * section which cannot execute in parallel with object reading. Since the used
+ * lock is a recursive mutex, these sections can even contain calls to object
+ * reading functions. However, beware that in these cases zlib inflation won't
+ * be performed in parallel, losing performance.
+ *
+ * TODO: oid_object_info_extended()'s call stack has a recursive behavior. If
+ * any of its callees end up calling it, this recursive call won't benefit from
+ * parallel inflation.
+ */
+void enable_obj_read_lock(void);
+void disable_obj_read_lock(void);
+
+extern int obj_read_use_lock;
+extern pthread_mutex_t obj_read_mutex;
+
+static inline void obj_read_lock(void)
+{
+	if(obj_read_use_lock)
+		pthread_mutex_lock(&obj_read_mutex);
+}
+
+static inline void obj_read_unlock(void)
+{
+	if(obj_read_use_lock)
+		pthread_mutex_unlock(&obj_read_mutex);
+}
+
+/*
  * Iterate over the files in the loose-object parts of the object
  * directory "path", triggering the following callbacks:
  *
diff --git a/object.c b/object.c
index 344087d..6d4ef15 100644
--- a/object.c
+++ b/object.c
@@ -1,6 +1,9 @@
 #include "cache.h"
+#include "gettext.h"
+#include "hex.h"
 #include "object.h"
 #include "replace-object.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "blob.h"
 #include "tree.h"
diff --git a/object.h b/object.h
index 31ebe11..5871615 100644
--- a/object.h
+++ b/object.h
@@ -1,9 +1,10 @@
 #ifndef OBJECT_H
 #define OBJECT_H
 
-#include "cache.h"
+#include "hash-ll.h"
 
 struct buffer_slab;
+struct repository;
 
 struct parsed_object_pool {
 	struct object **obj_hash;
@@ -81,6 +82,70 @@ struct object_array {
  */
 #define FLAG_BITS  28
 
+#define TYPE_BITS 3
+
+/*
+ * Values in this enum (except those outside the 3 bit range) are part
+ * of pack file format. See gitformat-pack(5) for more information.
+ */
+enum object_type {
+	OBJ_BAD = -1,
+	OBJ_NONE = 0,
+	OBJ_COMMIT = 1,
+	OBJ_TREE = 2,
+	OBJ_BLOB = 3,
+	OBJ_TAG = 4,
+	/* 5 for future expansion */
+	OBJ_OFS_DELTA = 6,
+	OBJ_REF_DELTA = 7,
+	OBJ_ANY,
+	OBJ_MAX
+};
+
+/* unknown mode (impossible combination S_IFIFO|S_IFCHR) */
+#define S_IFINVALID     0030000
+
+/*
+ * A "directory link" is a link to another git directory.
+ *
+ * The value 0160000 is not normally a valid mode, and
+ * also just happens to be S_IFDIR + S_IFLNK
+ */
+#define S_IFGITLINK	0160000
+#define S_ISGITLINK(m)	(((m) & S_IFMT) == S_IFGITLINK)
+
+#define S_ISSPARSEDIR(m) ((m) == S_IFDIR)
+
+static inline enum object_type object_type(unsigned int mode)
+{
+	return S_ISDIR(mode) ? OBJ_TREE :
+		S_ISGITLINK(mode) ? OBJ_COMMIT :
+		OBJ_BLOB;
+}
+
+#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
+static inline unsigned int create_ce_mode(unsigned int mode)
+{
+	if (S_ISLNK(mode))
+		return S_IFLNK;
+	if (S_ISSPARSEDIR(mode))
+		return S_IFDIR;
+	if (S_ISDIR(mode) || S_ISGITLINK(mode))
+		return S_IFGITLINK;
+	return S_IFREG | ce_permissions(mode);
+}
+
+static inline unsigned int canon_mode(unsigned int mode)
+{
+	if (S_ISREG(mode))
+		return S_IFREG | ce_permissions(mode);
+	if (S_ISLNK(mode))
+		return S_IFLNK;
+	if (S_ISDIR(mode))
+		return S_IFDIR;
+	return S_IFGITLINK;
+}
+
 /*
  * The object type is stored in 3 bits.
  */
diff --git a/oid-array.c b/oid-array.c
index 73ba76e..e8228c7 100644
--- a/oid-array.c
+++ b/oid-array.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "oid-array.h"
 #include "hash-lookup.h"
 
diff --git a/oidmap.c b/oidmap.c
index 49965fe..8b1bc4d 100644
--- a/oidmap.c
+++ b/oidmap.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "hash.h"
 #include "oidmap.h"
 
 static int oidmap_neq(const void *hashmap_cmp_fn_data UNUSED,
diff --git a/oidmap.h b/oidmap.h
index c66a83a..c164292 100644
--- a/oidmap.h
+++ b/oidmap.h
@@ -1,7 +1,6 @@
 #ifndef OIDMAP_H
 #define OIDMAP_H
 
-#include "cache.h"
 #include "hashmap.h"
 
 /*
diff --git a/oidset.c b/oidset.c
index b36a2ba..d1e5376 100644
--- a/oidset.c
+++ b/oidset.c
@@ -1,5 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "oidset.h"
+#include "hex.h"
+#include "strbuf.h"
 
 void oidset_init(struct oidset *set, size_t initial_size)
 {
diff --git a/oidtree.c b/oidtree.c
index 0d39389..7d57b7b 100644
--- a/oidtree.c
+++ b/oidtree.c
@@ -2,6 +2,7 @@
  * A wrapper around cbtree which stores oids
  * May be used to replace oid-array for prefix (abbreviation) matches
  */
+#include "git-compat-util.h"
 #include "oidtree.h"
 #include "alloc.h"
 #include "hash.h"
diff --git a/oidtree.h b/oidtree.h
index 77898f5..55c8351 100644
--- a/oidtree.h
+++ b/oidtree.h
@@ -2,7 +2,7 @@
 #define OIDTREE_H
 
 #include "cbtree.h"
-#include "hash.h"
+#include "hash-ll.h"
 #include "mem-pool.h"
 
 struct oidtree {
diff --git a/oss-fuzz/fuzz-commit-graph.c b/oss-fuzz/fuzz-commit-graph.c
index 914026f..2992079 100644
--- a/oss-fuzz/fuzz-commit-graph.c
+++ b/oss-fuzz/fuzz-commit-graph.c
@@ -1,3 +1,4 @@
+#include "git-compat-util.h"
 #include "commit-graph.h"
 #include "repository.h"
 
diff --git a/oss-fuzz/fuzz-pack-headers.c b/oss-fuzz/fuzz-pack-headers.c
index 99da1d0..150c0f5 100644
--- a/oss-fuzz/fuzz-pack-headers.c
+++ b/oss-fuzz/fuzz-pack-headers.c
@@ -1,3 +1,4 @@
+#include "git-compat-util.h"
 #include "packfile.h"
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
diff --git a/oss-fuzz/fuzz-pack-idx.c b/oss-fuzz/fuzz-pack-idx.c
index 0c3d777..609a343 100644
--- a/oss-fuzz/fuzz-pack-idx.c
+++ b/oss-fuzz/fuzz-pack-idx.c
@@ -1,3 +1,4 @@
+#include "git-compat-util.h"
 #include "object-store.h"
 #include "packfile.h"
 
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index cfa67a5..cdffe2c 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -1,4 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "object-store.h"
 #include "commit.h"
 #include "tag.h"
@@ -13,6 +17,9 @@
 #include "pack-objects.h"
 #include "commit-reach.h"
 #include "prio-queue.h"
+#include "trace2.h"
+#include "tree.h"
+#include "tree-walk.h"
 
 struct bitmapped_commit {
 	struct commit *commit;
@@ -425,7 +432,8 @@ static int fill_bitmap_commit(struct bb_commit *ent,
 		if (!found)
 			return -1;
 		bitmap_set(ent->bitmap, pos);
-		prio_queue_put(tree_queue, get_commit_tree(c));
+		prio_queue_put(tree_queue,
+			       repo_get_commit_tree(the_repository, c));
 
 		for (p = c->parents; p; p = p->next) {
 			pos = find_object_pos(&p->item->object.oid, &found);
diff --git a/pack-bitmap.c b/pack-bitmap.c
index d2a42ab..999f962 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -1,5 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "commit.h"
+#include "gettext.h"
+#include "hex.h"
 #include "strbuf.h"
 #include "tag.h"
 #include "diff.h"
@@ -12,6 +15,8 @@
 #include "pack-objects.h"
 #include "packfile.h"
 #include "repository.h"
+#include "trace2.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "list-objects-filter-options.h"
 #include "midx.h"
@@ -376,7 +381,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
 		goto cleanup;
 	}
 
-	if (load_midx_revindex(bitmap_git->midx) < 0) {
+	if (load_midx_revindex(bitmap_git->midx)) {
 		warning(_("multi-pack bitmap is missing required reverse index"));
 		goto cleanup;
 	}
@@ -460,7 +465,7 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git
 	return 0;
 }
 
-static int load_reverse_index(struct bitmap_index *bitmap_git)
+static int load_reverse_index(struct repository *r, struct bitmap_index *bitmap_git)
 {
 	if (bitmap_is_midx(bitmap_git)) {
 		uint32_t i;
@@ -474,23 +479,23 @@ static int load_reverse_index(struct bitmap_index *bitmap_git)
 		 * since we will need to make use of them in pack-objects.
 		 */
 		for (i = 0; i < bitmap_git->midx->num_packs; i++) {
-			ret = load_pack_revindex(bitmap_git->midx->packs[i]);
+			ret = load_pack_revindex(r, bitmap_git->midx->packs[i]);
 			if (ret)
 				return ret;
 		}
 		return 0;
 	}
-	return load_pack_revindex(bitmap_git->pack);
+	return load_pack_revindex(r, bitmap_git->pack);
 }
 
-static int load_bitmap(struct bitmap_index *bitmap_git)
+static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git)
 {
 	assert(bitmap_git->map);
 
 	bitmap_git->bitmaps = kh_init_oid_map();
 	bitmap_git->ext_index.positions = kh_init_oid_pos();
 
-	if (load_reverse_index(bitmap_git))
+	if (load_reverse_index(r, bitmap_git))
 		goto failed;
 
 	if (!(bitmap_git->commits = read_bitmap_1(bitmap_git)) ||
@@ -577,7 +582,7 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r)
 {
 	struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
 
-	if (!open_bitmap(r, bitmap_git) && !load_bitmap(bitmap_git))
+	if (!open_bitmap(r, bitmap_git) && !load_bitmap(r, bitmap_git))
 		return bitmap_git;
 
 	free_bitmap_index(bitmap_git);
@@ -586,9 +591,10 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r)
 
 struct bitmap_index *prepare_midx_bitmap_git(struct multi_pack_index *midx)
 {
+	struct repository *r = the_repository;
 	struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
 
-	if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(bitmap_git))
+	if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(r, bitmap_git))
 		return bitmap_git;
 
 	free_bitmap_index(bitmap_git);
@@ -951,7 +957,8 @@ static void show_object(struct object *object, const char *name, void *data_)
 	bitmap_set(data->base, bitmap_pos);
 }
 
-static void show_commit(struct commit *commit, void *data)
+static void show_commit(struct commit *commit UNUSED,
+			void *data UNUSED)
 {
 }
 
@@ -1588,7 +1595,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
 	 * from disk. this is the point of no return; after this the rev_list
 	 * becomes invalidated and we must perform the revwalk through bitmaps
 	 */
-	if (load_bitmap(bitmap_git) < 0)
+	if (load_bitmap(revs->repo, bitmap_git) < 0)
 		goto cleanup;
 
 	object_array_clear(&revs->pending);
@@ -1738,6 +1745,7 @@ int reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
 				       uint32_t *entries,
 				       struct bitmap **reuse_out)
 {
+	struct repository *r = the_repository;
 	struct packed_git *pack;
 	struct bitmap *result = bitmap_git->result;
 	struct bitmap *reuse;
@@ -1748,7 +1756,7 @@ int reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
 
 	assert(result);
 
-	load_reverse_index(bitmap_git);
+	load_reverse_index(r, bitmap_git);
 
 	if (bitmap_is_midx(bitmap_git))
 		pack = bitmap_git->midx->packs[midx_preferred_pack(bitmap_git)];
@@ -1940,7 +1948,8 @@ static void test_bitmap_type(struct bitmap_test_data *tdata,
 		    type_name(bitmap_type));
 }
 
-static void test_show_object(struct object *object, const char *name,
+static void test_show_object(struct object *object,
+			     const char *name UNUSED,
 			     void *data)
 {
 	struct bitmap_test_data *tdata = data;
@@ -2127,12 +2136,13 @@ int rebuild_bitmap(const uint32_t *reposition,
 uint32_t *create_bitmap_mapping(struct bitmap_index *bitmap_git,
 				struct packing_data *mapping)
 {
+	struct repository *r = the_repository;
 	uint32_t i, num_objects;
 	uint32_t *reposition;
 
 	if (!bitmap_is_midx(bitmap_git))
-		load_reverse_index(bitmap_git);
-	else if (load_midx_revindex(bitmap_git->midx) < 0)
+		load_reverse_index(r, bitmap_git);
+	else if (load_midx_revindex(bitmap_git->midx))
 		BUG("rebuild_existing_bitmaps: missing required rev-cache "
 		    "extension");
 
@@ -2314,7 +2324,11 @@ int bitmap_is_midx(struct bitmap_index *bitmap_git)
 
 const struct string_list *bitmap_preferred_tips(struct repository *r)
 {
-	return repo_config_get_value_multi(r, "pack.preferbitmaptips");
+	const struct string_list *dest;
+
+	if (!repo_config_get_string_multi(r, "pack.preferbitmaptips", &dest))
+		return dest;
+	return NULL;
 }
 
 int bitmap_is_preferred_refname(struct repository *r, const char *refname)
@@ -2332,3 +2346,48 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)
 
 	return 0;
 }
+
+static int verify_bitmap_file(const char *name)
+{
+	struct stat st;
+	unsigned char *data;
+	int fd = git_open(name);
+	int res = 0;
+
+	/* It is OK to not have the file. */
+	if (fd < 0 || fstat(fd, &st)) {
+		if (fd >= 0)
+			close(fd);
+		return 0;
+	}
+
+	data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	close(fd);
+	if (!hashfile_checksum_valid(data, st.st_size))
+		res = error(_("bitmap file '%s' has invalid checksum"),
+			    name);
+
+	munmap(data, st.st_size);
+	return res;
+}
+
+int verify_bitmap_files(struct repository *r)
+{
+	int res = 0;
+
+	for (struct multi_pack_index *m = get_multi_pack_index(r);
+	     m; m = m->next) {
+		char *midx_bitmap_name = midx_bitmap_filename(m);
+		res |= verify_bitmap_file(midx_bitmap_name);
+		free(midx_bitmap_name);
+	}
+
+	for (struct packed_git *p = get_all_packs(r);
+	     p; p = p->next) {
+		char *pack_bitmap_name = pack_bitmap_filename(p);
+		res |= verify_bitmap_file(pack_bitmap_name);
+		free(pack_bitmap_name);
+	}
+
+	return res;
+}
diff --git a/pack-bitmap.h b/pack-bitmap.h
index f0180b5..84591f0 100644
--- a/pack-bitmap.h
+++ b/pack-bitmap.h
@@ -111,4 +111,6 @@ int bitmap_is_midx(struct bitmap_index *bitmap_git);
 const struct string_list *bitmap_preferred_tips(struct repository *r);
 int bitmap_is_preferred_refname(struct repository *r, const char *refname);
 
+int verify_bitmap_files(struct repository *r);
+
 #endif
diff --git a/pack-check.c b/pack-check.c
index bfb593b..049f2f0 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -1,9 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "environment.h"
+#include "hex.h"
 #include "repository.h"
 #include "pack.h"
 #include "pack-revindex.h"
 #include "progress.h"
 #include "packfile.h"
+#include "object-file.h"
 #include "object-store.h"
 
 struct idx_entry {
diff --git a/pack-mtimes.c b/pack-mtimes.c
index 0f9785f..020a37f 100644
--- a/pack-mtimes.c
+++ b/pack-mtimes.c
@@ -1,5 +1,7 @@
 #include "git-compat-util.h"
+#include "gettext.h"
 #include "pack-mtimes.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "packfile.h"
 
diff --git a/pack-mtimes.h b/pack-mtimes.h
index cc957b3..107327c 100644
--- a/pack-mtimes.h
+++ b/pack-mtimes.h
@@ -1,8 +1,6 @@
 #ifndef PACK_MTIMES_H
 #define PACK_MTIMES_H
 
-#include "git-compat-util.h"
-
 #define MTIMES_SIGNATURE 0x4d544d45 /* "MTME" */
 #define MTIMES_VERSION 1
 
diff --git a/pack-objects.c b/pack-objects.c
index 272e8d4..ccab09f 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "object.h"
 #include "pack.h"
 #include "pack-objects.h"
diff --git a/pack-revindex.c b/pack-revindex.c
index 08dc160..1f51b71 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -1,9 +1,13 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
 #include "pack-revindex.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "packfile.h"
+#include "trace2.h"
 #include "config.h"
 #include "midx.h"
+#include "csum-file.h"
 
 struct revindex_entry {
 	off_t offset;
@@ -204,10 +208,14 @@ static int load_revindex_from_disk(char *revindex_name,
 	size_t revindex_size;
 	struct revindex_header *hdr;
 
+	if (git_env_bool(GIT_TEST_REV_INDEX_DIE_ON_DISK, 0))
+		die("dying as requested by '%s'", GIT_TEST_REV_INDEX_DIE_ON_DISK);
+
 	fd = git_open(revindex_name);
 
 	if (fd < 0) {
-		ret = -1;
+		/* "No file" means return 1. */
+		ret = 1;
 		goto cleanup;
 	}
 	if (fstat(fd, &st)) {
@@ -259,7 +267,7 @@ static int load_revindex_from_disk(char *revindex_name,
 	return ret;
 }
 
-static int load_pack_revindex_from_disk(struct packed_git *p)
+int load_pack_revindex_from_disk(struct packed_git *p)
 {
 	char *revindex_name;
 	int ret;
@@ -282,18 +290,58 @@ static int load_pack_revindex_from_disk(struct packed_git *p)
 	return ret;
 }
 
-int load_pack_revindex(struct packed_git *p)
+int load_pack_revindex(struct repository *r, struct packed_git *p)
 {
 	if (p->revindex || p->revindex_data)
 		return 0;
 
-	if (!load_pack_revindex_from_disk(p))
+	prepare_repo_settings(r);
+
+	if (r->settings.pack_read_reverse_index &&
+	    !load_pack_revindex_from_disk(p))
 		return 0;
 	else if (!create_pack_revindex_in_memory(p))
 		return 0;
 	return -1;
 }
 
+/*
+ * verify_pack_revindex verifies that the on-disk rev-index for the given
+ * pack-file is the same that would be created if written from scratch.
+ *
+ * A negative number is returned on error.
+ */
+int verify_pack_revindex(struct packed_git *p)
+{
+	int res = 0;
+
+	/* Do not bother checking if not initialized. */
+	if (!p->revindex_map || !p->revindex_data)
+		return res;
+
+	if (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) {
+		error(_("invalid checksum"));
+		res = -1;
+	}
+
+	/* This may fail due to a broken .idx. */
+	if (create_pack_revindex_in_memory(p))
+		return res;
+
+	for (size_t i = 0; i < p->num_objects; i++) {
+		uint32_t nr = p->revindex[i].nr;
+		uint32_t rev_val = get_be32(p->revindex_data + i);
+
+		if (nr != rev_val) {
+			error(_("invalid rev-index position at %"PRIu64": %"PRIu32" != %"PRIu32""),
+			      (uint64_t)i, nr, rev_val);
+			res = -1;
+		}
+	}
+
+	return res;
+}
+
 int load_midx_revindex(struct multi_pack_index *m)
 {
 	struct strbuf revindex_name = STRBUF_INIT;
@@ -355,7 +403,7 @@ int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos)
 {
 	unsigned lo, hi;
 
-	if (load_pack_revindex(p) < 0)
+	if (load_pack_revindex(the_repository, p) < 0)
 		return -1;
 
 	lo = 0;
diff --git a/pack-revindex.h b/pack-revindex.h
index 4974e75..6dd47ef 100644
--- a/pack-revindex.h
+++ b/pack-revindex.h
@@ -34,11 +34,13 @@
 #define RIDX_SIGNATURE 0x52494458 /* "RIDX" */
 #define RIDX_VERSION 1
 
-#define GIT_TEST_WRITE_REV_INDEX "GIT_TEST_WRITE_REV_INDEX"
+#define GIT_TEST_NO_WRITE_REV_INDEX "GIT_TEST_NO_WRITE_REV_INDEX"
 #define GIT_TEST_REV_INDEX_DIE_IN_MEMORY "GIT_TEST_REV_INDEX_DIE_IN_MEMORY"
+#define GIT_TEST_REV_INDEX_DIE_ON_DISK "GIT_TEST_REV_INDEX_DIE_ON_DISK"
 
 struct packed_git;
 struct multi_pack_index;
+struct repository;
 
 /*
  * load_pack_revindex populates the revindex's internal data-structures for the
@@ -47,7 +49,23 @@ struct multi_pack_index;
  * If a '.rev' file is present it is mmap'd, and pointers are assigned into it
  * (instead of using the in-memory variant).
  */
-int load_pack_revindex(struct packed_git *p);
+int load_pack_revindex(struct repository *r, struct packed_git *p);
+
+/*
+ * Specifically load a pack revindex from disk.
+ *
+ * Returns 0 on success, 1 on "no .rev file", and -1 when there is an
+ * error parsing the .rev file.
+ */
+int load_pack_revindex_from_disk(struct packed_git *p);
+
+/*
+ * verify_pack_revindex verifies that the on-disk rev-index for the given
+ * pack-file is the same that would be created if written from scratch.
+ *
+ * A negative number is returned on error.
+ */
+int verify_pack_revindex(struct packed_git *p);
 
 /*
  * load_midx_revindex loads the '.rev' file corresponding to the given
diff --git a/pack-write.c b/pack-write.c
index 3363729..3b3ce89 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -1,4 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "pack.h"
 #include "csum-file.h"
 #include "remote.h"
@@ -6,6 +9,8 @@
 #include "pack-mtimes.h"
 #include "oidmap.h"
 #include "pack-objects.h"
+#include "pack-revindex.h"
+#include "wrapper.h"
 
 void reset_pack_idx_option(struct pack_idx_option *opts)
 {
@@ -309,13 +314,13 @@ static void write_mtimes_trailer(struct hashfile *f, const unsigned char *hash)
 	hashwrite(f, hash, the_hash_algo->rawsz);
 }
 
-static const char *write_mtimes_file(struct packing_data *to_pack,
-				     struct pack_idx_entry **objects,
-				     uint32_t nr_objects,
-				     const unsigned char *hash)
+static char *write_mtimes_file(struct packing_data *to_pack,
+			       struct pack_idx_entry **objects,
+			       uint32_t nr_objects,
+			       const unsigned char *hash)
 {
 	struct strbuf tmp_file = STRBUF_INIT;
-	const char *mtimes_name;
+	char *mtimes_name;
 	struct hashfile *f;
 	int fd;
 
@@ -541,7 +546,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
 			 char **idx_tmp_name)
 {
 	const char *rev_tmp_name = NULL;
-	const char *mtimes_tmp_name = NULL;
+	char *mtimes_tmp_name = NULL;
 
 	if (adjust_shared_perm(pack_tmp_name))
 		die_errno("unable to make temporary pack file readable");
@@ -565,6 +570,9 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
 		rename_tmp_packfile(name_buffer, rev_tmp_name, "rev");
 	if (mtimes_tmp_name)
 		rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes");
+
+	free((char *)rev_tmp_name);
+	free(mtimes_tmp_name);
 }
 
 void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought)
diff --git a/pack.h b/pack.h
index 01d3859..3ab9e3f 100644
--- a/pack.h
+++ b/pack.h
@@ -4,6 +4,8 @@
 #include "object.h"
 #include "csum-file.h"
 
+struct packed_git;
+struct pack_window;
 struct repository;
 
 /*
diff --git a/packfile.c b/packfile.c
index 79e21ab..fd083c8 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1,4 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "list.h"
 #include "pack.h"
 #include "repository.h"
@@ -11,12 +15,16 @@
 #include "commit.h"
 #include "object.h"
 #include "tag.h"
+#include "trace.h"
 #include "tree-walk.h"
 #include "tree.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "midx.h"
 #include "commit-graph.h"
+#include "pack-revindex.h"
 #include "promisor-remote.h"
+#include "wrapper.h"
 
 char *odb_pack_name(struct strbuf *buf,
 		    const unsigned char *hash,
@@ -1008,6 +1016,16 @@ void reprepare_packed_git(struct repository *r)
 	struct object_directory *odb;
 
 	obj_read_lock();
+
+	/*
+	 * Reprepare alt odbs, in case the alternates file was modified
+	 * during the course of this process. This only _adds_ odbs to
+	 * the linked list, so existing odbs will continue to exist for
+	 * the lifetime of the process.
+	 */
+	r->objects->loaded_alternates = 0;
+	prepare_alt_odb(r);
+
 	for (odb = r->objects->odb; odb; odb = odb->next)
 		odb_clear_loose_cache(odb);
 
@@ -2136,7 +2154,7 @@ int for_each_object_in_pack(struct packed_git *p,
 	int r = 0;
 
 	if (flags & FOR_EACH_OBJECT_PACK_ORDER) {
-		if (load_pack_revindex(p))
+		if (load_pack_revindex(the_repository, p))
 			return -1;
 	}
 
@@ -2204,8 +2222,8 @@ int for_each_packed_object(each_packed_object_fn cb, void *data,
 }
 
 static int add_promisor_object(const struct object_id *oid,
-			       struct packed_git *pack,
-			       uint32_t pos,
+			       struct packed_git *pack UNUSED,
+			       uint32_t pos UNUSED,
 			       void *set_)
 {
 	struct oidset *set = set_;
@@ -2263,7 +2281,7 @@ int is_promisor_object(const struct object_id *oid)
 	static int promisor_objects_prepared;
 
 	if (!promisor_objects_prepared) {
-		if (has_promisor_remote()) {
+		if (repo_has_promisor_remote(the_repository)) {
 			for_each_packed_object(add_promisor_object,
 					       &promisor_objects,
 					       FOR_EACH_OBJECT_PROMISOR_ONLY |
diff --git a/packfile.h b/packfile.h
index a3f6723..c369230 100644
--- a/packfile.h
+++ b/packfile.h
@@ -1,13 +1,27 @@
 #ifndef PACKFILE_H
 #define PACKFILE_H
 
-#include "cache.h"
+#include "object.h"
 #include "oidset.h"
 
 /* in object-store.h */
 struct packed_git;
 struct object_info;
 
+struct pack_window {
+	struct pack_window *next;
+	unsigned char *base;
+	off_t offset;
+	size_t len;
+	unsigned int last_used;
+	unsigned int inuse_cnt;
+};
+
+struct pack_entry {
+	off_t offset;
+	struct packed_git *p;
+};
+
 /*
  * Generate the filename to be used for a pack file with checksum "sha1" and
  * extension "ext". The result is written into the strbuf "buf", overwriting
@@ -65,7 +79,6 @@ struct packed_git *get_all_packs(struct repository *r);
  * for speed.
  */
 unsigned long repo_approximate_object_count(struct repository *r);
-#define approximate_object_count() repo_approximate_object_count(the_repository)
 
 struct packed_git *find_sha1_pack(const unsigned char *sha1,
 				  struct packed_git *packs);
diff --git a/pager.c b/pager.c
index b66bbff..63055d0 100644
--- a/pager.c
+++ b/pager.c
@@ -1,9 +1,13 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "editor.h"
+#include "pager.h"
 #include "run-command.h"
 #include "sigchain.h"
 #include "alias.h"
 
+int pager_use_color = 1;
+
 #ifndef DEFAULT_PAGER
 #define DEFAULT_PAGER "less"
 #endif
diff --git a/pager.h b/pager.h
new file mode 100644
index 0000000..b774330
--- /dev/null
+++ b/pager.h
@@ -0,0 +1,17 @@
+#ifndef PAGER_H
+#define PAGER_H
+
+struct child_process;
+
+const char *git_pager(int stdout_is_tty);
+void setup_pager(void);
+int pager_in_use(void);
+int term_columns(void);
+void term_clear_line(void);
+int decimal_width(uintmax_t);
+int check_pager_config(const char *cmd);
+void prepare_pager_args(struct child_process *, const char *pager);
+
+extern int pager_use_color;
+
+#endif /* PAGER_H */
diff --git a/parallel-checkout.c b/parallel-checkout.c
index 4f6819f..69d569f 100644
--- a/parallel-checkout.c
+++ b/parallel-checkout.c
@@ -1,14 +1,20 @@
 #include "cache.h"
+#include "alloc.h"
 #include "config.h"
 #include "entry.h"
+#include "gettext.h"
+#include "hash.h"
+#include "hex.h"
 #include "parallel-checkout.h"
 #include "pkt-line.h"
 #include "progress.h"
 #include "run-command.h"
 #include "sigchain.h"
 #include "streaming.h"
+#include "symlinks.h"
 #include "thread-utils.h"
 #include "trace2.h"
+#include "wrapper.h"
 
 struct pc_worker {
 	struct child_process cp;
diff --git a/parse-options-cb.c b/parse-options-cb.c
index d346dbe..a24521d 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -1,9 +1,12 @@
 #include "git-compat-util.h"
 #include "parse-options.h"
 #include "branch.h"
-#include "cache.h"
 #include "commit.h"
 #include "color.h"
+#include "date.h"
+#include "environment.h"
+#include "gettext.h"
+#include "object-name.h"
 #include "string-list.h"
 #include "strvec.h"
 #include "oid-array.h"
@@ -91,7 +94,7 @@ int parse_opt_commits(const struct option *opt, const char *arg, int unset)
 
 	if (!arg)
 		return -1;
-	if (get_oid(arg, &oid))
+	if (repo_get_oid(the_repository, arg, &oid))
 		return error("malformed object name %s", arg);
 	commit = lookup_commit_reference(the_repository, &oid);
 	if (!commit)
@@ -110,7 +113,7 @@ int parse_opt_commit(const struct option *opt, const char *arg, int unset)
 
 	if (!arg)
 		return -1;
-	if (get_oid(arg, &oid))
+	if (repo_get_oid(the_repository, arg, &oid))
 		return error("malformed object name %s", arg);
 	commit = lookup_commit_reference(the_repository, &oid);
 	if (!commit)
@@ -129,7 +132,7 @@ int parse_opt_object_name(const struct option *opt, const char *arg, int unset)
 	}
 	if (!arg)
 		return -1;
-	if (get_oid(arg, &oid))
+	if (repo_get_oid(the_repository, arg, &oid))
 		return error(_("malformed object name '%s'"), arg);
 	oid_array_append(opt->value, &oid);
 	return 0;
@@ -146,7 +149,7 @@ int parse_opt_object_id(const struct option *opt, const char *arg, int unset)
 	}
 	if (!arg)
 		return -1;
-	if (get_oid(arg, &oid))
+	if (repo_get_oid(the_repository, arg, &oid))
 		return error(_("malformed object name '%s'"), arg);
 	*target = oid;
 	return 0;
@@ -208,24 +211,25 @@ int parse_opt_string_list(const struct option *opt, const char *arg, int unset)
 	return 0;
 }
 
-int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset)
+int parse_opt_strvec(const struct option *opt, const char *arg, int unset)
 {
+	struct strvec *v = opt->value;
+
+	if (unset) {
+		strvec_clear(v);
+		return 0;
+	}
+
+	if (!arg)
+		return -1;
+
+	strvec_push(v, arg);
 	return 0;
 }
 
-/**
- * Report that the option is unknown, so that other code can handle
- * it. This can be used as a callback together with
- * OPTION_LOWLEVEL_CALLBACK to allow an option to be documented in the
- * "-h" output even if it's not being handled directly by
- * parse_options().
- */
-enum parse_opt_result parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx,
-					   const struct option *opt,
-					   const char *arg, int unset)
+int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset)
 {
-	BUG_ON_OPT_ARG(arg);
-	return PARSE_OPT_UNKNOWN;
+	return 0;
 }
 
 /**
diff --git a/parse-options.c b/parse-options.c
index fd47432..f8a155e 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -1,9 +1,11 @@
 #include "git-compat-util.h"
 #include "parse-options.h"
-#include "cache.h"
+#include "abspath.h"
 #include "config.h"
 #include "commit.h"
 #include "color.h"
+#include "gettext.h"
+#include "strbuf.h"
 #include "utf8.h"
 
 static int disallow_abbreviated_options;
@@ -59,12 +61,12 @@ static enum parse_opt_result get_arg(struct parse_opt_ctx_t *p,
 	return 0;
 }
 
-static void fix_filename(const char *prefix, const char **file)
+static void fix_filename(const char *prefix, char **file)
 {
-	if (!file || !*file || !prefix || is_absolute_path(*file)
-	    || !strcmp("-", *file))
-		return;
-	*file = prefix_filename(prefix, *file);
+	if (!file || !*file)
+		; /* leave as NULL */
+	else
+		*file = prefix_filename_except_for_dash(prefix, *file);
 }
 
 static enum parse_opt_result opt_command_mode_error(
@@ -177,7 +179,7 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
 			err = get_arg(p, opt, flags, (const char **)opt->value);
 
 		if (!err)
-			fix_filename(p->prefix, (const char **)opt->value);
+			fix_filename(p->prefix, (char **)opt->value);
 		return err;
 
 	case OPTION_CALLBACK:
diff --git a/parse-options.h b/parse-options.h
index 50d852f..8e48efe 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -1,6 +1,8 @@
 #ifndef PARSE_OPTIONS_H
 #define PARSE_OPTIONS_H
 
+#include "gettext.h"
+
 /**
  * Refer to Documentation/technical/api-parse-options.txt for the API doc.
  */
@@ -158,71 +160,211 @@ struct option {
 	parse_opt_subcommand_fn *subcommand_fn;
 };
 
-#define OPT_BIT_F(s, l, v, h, b, f) { OPTION_BIT, (s), (l), (v), NULL, (h), \
-				      PARSE_OPT_NOARG|(f), NULL, (b) }
-#define OPT_COUNTUP_F(s, l, v, h, f) { OPTION_COUNTUP, (s), (l), (v), NULL, \
-				       (h), PARSE_OPT_NOARG|(f) }
-#define OPT_SET_INT_F(s, l, v, h, i, f) { OPTION_SET_INT, (s), (l), (v), NULL, \
-					  (h), PARSE_OPT_NOARG | (f), NULL, (i) }
+#define OPT_BIT_F(s, l, v, h, b, f) { \
+	.type = OPTION_BIT, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.help = (h), \
+	.flags = PARSE_OPT_NOARG|(f), \
+	.callback = NULL, \
+	.defval = (b), \
+}
+#define OPT_COUNTUP_F(s, l, v, h, f) { \
+	.type = OPTION_COUNTUP, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.help = (h), \
+	.flags = PARSE_OPT_NOARG|(f), \
+}
+#define OPT_SET_INT_F(s, l, v, h, i, f) { \
+	.type = OPTION_SET_INT, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.help = (h), \
+	.flags = PARSE_OPT_NOARG | (f), \
+	.defval = (i), \
+}
 #define OPT_BOOL_F(s, l, v, h, f)   OPT_SET_INT_F(s, l, v, h, 1, f)
-#define OPT_CALLBACK_F(s, l, v, a, h, f, cb)			\
-	{ OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), (cb) }
-#define OPT_STRING_F(s, l, v, a, h, f)   { OPTION_STRING,  (s), (l), (v), (a), (h), (f) }
-#define OPT_INTEGER_F(s, l, v, h, f)     { OPTION_INTEGER, (s), (l), (v), N_("n"), (h), (f) }
+#define OPT_CALLBACK_F(s, l, v, a, h, f, cb) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = (a), \
+	.help = (h), \
+	.flags = (f), \
+	.callback = (cb), \
+}
+#define OPT_STRING_F(s, l, v, a, h, f) { \
+	.type = OPTION_STRING, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = (a), \
+	.help = (h), \
+	.flags = (f), \
+}
+#define OPT_INTEGER_F(s, l, v, h, f) { \
+	.type = OPTION_INTEGER, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = N_("n"), \
+	.help = (h), \
+	.flags = (f), \
+}
 
-#define OPT_END()                   { OPTION_END }
-#define OPT_GROUP(h)                { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
+#define OPT_END() { \
+	.type = OPTION_END, \
+}
+#define OPT_GROUP(h) { \
+	.type = OPTION_GROUP, \
+	.help = (h), \
+}
 #define OPT_BIT(s, l, v, h, b)      OPT_BIT_F(s, l, v, h, b, 0)
-#define OPT_BITOP(s, l, v, h, set, clear) { OPTION_BITOP, (s), (l), (v), NULL, (h), \
-					    PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, \
-					    (set), NULL, (clear) }
-#define OPT_NEGBIT(s, l, v, h, b)   { OPTION_NEGBIT, (s), (l), (v), NULL, \
-				      (h), PARSE_OPT_NOARG, NULL, (b) }
+#define OPT_BITOP(s, l, v, h, set, clear) { \
+	.type = OPTION_BITOP, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.help = (h), \
+	.flags = PARSE_OPT_NOARG|PARSE_OPT_NONEG, \
+	.defval = (set), \
+	.extra = (clear), \
+}
+#define OPT_NEGBIT(s, l, v, h, b) { \
+	.type = OPTION_NEGBIT, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.help = (h), \
+	.flags = PARSE_OPT_NOARG, \
+	.defval = (b), \
+}
 #define OPT_COUNTUP(s, l, v, h)     OPT_COUNTUP_F(s, l, v, h, 0)
 #define OPT_SET_INT(s, l, v, h, i)  OPT_SET_INT_F(s, l, v, h, i, 0)
 #define OPT_BOOL(s, l, v, h)        OPT_BOOL_F(s, l, v, h, 0)
-#define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \
-				      (h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
-#define OPT_CMDMODE_F(s, l, v, h, i, f)  { OPTION_SET_INT, (s), (l), (v), NULL, \
-				      (h), PARSE_OPT_CMDMODE|PARSE_OPT_NOARG|PARSE_OPT_NONEG | (f), NULL, (i) }
+#define OPT_HIDDEN_BOOL(s, l, v, h) { \
+	.type = OPTION_SET_INT, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.help = (h), \
+	.flags = PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, \
+	.defval = 1, \
+}
+#define OPT_CMDMODE_F(s, l, v, h, i, f) { \
+	.type = OPTION_SET_INT, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.help = (h), \
+	.flags = PARSE_OPT_CMDMODE|PARSE_OPT_NOARG|PARSE_OPT_NONEG | (f), \
+	.defval = (i), \
+}
 #define OPT_CMDMODE(s, l, v, h, i)  OPT_CMDMODE_F(s, l, v, h, i, 0)
 
 #define OPT_INTEGER(s, l, v, h)     OPT_INTEGER_F(s, l, v, h, 0)
-#define OPT_MAGNITUDE(s, l, v, h)   { OPTION_MAGNITUDE, (s), (l), (v), \
-				      N_("n"), (h), PARSE_OPT_NONEG }
+#define OPT_MAGNITUDE(s, l, v, h) { \
+	.type = OPTION_MAGNITUDE, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = N_("n"), \
+	.help = (h), \
+	.flags = PARSE_OPT_NONEG, \
+}
 #define OPT_STRING(s, l, v, a, h)   OPT_STRING_F(s, l, v, a, h, 0)
-#define OPT_STRING_LIST(s, l, v, a, h) \
-				    { OPTION_CALLBACK, (s), (l), (v), (a), \
-				      (h), 0, &parse_opt_string_list }
-#define OPT_UYN(s, l, v, h)         { OPTION_CALLBACK, (s), (l), (v), NULL, \
-				      (h), PARSE_OPT_NOARG, &parse_opt_tertiary }
-#define OPT_EXPIRY_DATE(s, l, v, h) \
-	{ OPTION_CALLBACK, (s), (l), (v), N_("expiry-date"),(h), 0,	\
-	  parse_opt_expiry_date_cb }
-#define OPT_CALLBACK(s, l, v, a, h, f) OPT_CALLBACK_F(s, l, v, a, h, 0, f)
-#define OPT_NUMBER_CALLBACK(v, h, f) \
-	{ OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
-	  PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
-#define OPT_FILENAME(s, l, v, h)    { OPTION_FILENAME, (s), (l), (v), \
-				       N_("file"), (h) }
-#define OPT_COLOR_FLAG(s, l, v, h) \
-	{ OPTION_CALLBACK, (s), (l), (v), N_("when"), (h), PARSE_OPT_OPTARG, \
-		parse_opt_color_flag_cb, (intptr_t)"always" }
+#define OPT_STRING_LIST(s, l, v, a, h) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = (a), \
+	.help = (h), \
+	.callback = &parse_opt_string_list, \
+}
+#define OPT_STRVEC(s, l, v, a, h) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = (a), \
+	.help = (h), \
+	.callback = &parse_opt_strvec, \
+}
+#define OPT_UYN(s, l, v, h) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.help = (h), \
+	.flags = PARSE_OPT_NOARG, \
+	.callback = &parse_opt_tertiary, \
+}
+#define OPT_EXPIRY_DATE(s, l, v, h) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = N_("expiry-date"), \
+	.help = (h), \
+	.callback = parse_opt_expiry_date_cb, \
+}
+#define OPT_CALLBACK(s, l, v, a, h, cb) OPT_CALLBACK_F(s, l, v, a, h, 0, cb)
+#define OPT_NUMBER_CALLBACK(v, h, cb) { \
+	.type = OPTION_NUMBER, \
+	.value = (v), \
+	.help = (h), \
+	.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, \
+	.callback = (cb), \
+}
+#define OPT_FILENAME(s, l, v, h) { \
+	.type = OPTION_FILENAME, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = N_("file"), \
+	.help = (h), \
+}
+#define OPT_COLOR_FLAG(s, l, v, h) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = N_("when"), \
+	.help = (h), \
+	.flags = PARSE_OPT_OPTARG, \
+	.callback = parse_opt_color_flag_cb, \
+	.defval = (intptr_t)"always", \
+}
 
-#define OPT_NOOP_NOARG(s, l) \
-	{ OPTION_CALLBACK, (s), (l), NULL, NULL, \
-	  N_("no-op (backward compatibility)"),		\
-	  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, parse_opt_noop_cb }
+#define OPT_NOOP_NOARG(s, l) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.help = N_("no-op (backward compatibility)"), \
+	.flags = PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, \
+	.callback = parse_opt_noop_cb, \
+}
 
-#define OPT_ALIAS(s, l, source_long_name) \
-	{ OPTION_ALIAS, (s), (l), (source_long_name) }
+#define OPT_ALIAS(s, l, source_long_name) { \
+	.type = OPTION_ALIAS, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (source_long_name), \
+}
 
 #define OPT_SUBCOMMAND_F(l, v, fn, f) { \
 	.type = OPTION_SUBCOMMAND, \
 	.long_name = (l), \
 	.value = (v), \
 	.flags = (f), \
-	.subcommand_fn = (fn) }
+	.subcommand_fn = (fn), \
+}
 #define OPT_SUBCOMMAND(l, v, fn)    OPT_SUBCOMMAND_F((l), (v), (fn), 0)
 
 /*
@@ -347,10 +489,8 @@ int parse_opt_commits(const struct option *, const char *, int);
 int parse_opt_commit(const struct option *, const char *, int);
 int parse_opt_tertiary(const struct option *, const char *, int);
 int parse_opt_string_list(const struct option *, const char *, int);
+int parse_opt_strvec(const struct option *, const char *, int);
 int parse_opt_noop_cb(const struct option *, const char *, int);
-enum parse_opt_result parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx,
-					   const struct option *,
-					   const char *, int);
 int parse_opt_passthru(const struct option *, const char *, int);
 int parse_opt_passthru_argv(const struct option *, const char *, int);
 /* value is enum branch_track* */
@@ -358,34 +498,80 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);
 
 #define OPT__VERBOSE(var, h)  OPT_COUNTUP('v', "verbose", (var), (h))
 #define OPT__QUIET(var, h)    OPT_COUNTUP('q', "quiet",   (var), (h))
-#define OPT__VERBOSITY(var) \
-	{ OPTION_CALLBACK, 'v', "verbose", (var), NULL, N_("be more verbose"), \
-	  PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }, \
-	{ OPTION_CALLBACK, 'q', "quiet", (var), NULL, N_("be more quiet"), \
-	  PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }
+#define OPT__VERBOSITY(var) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = 'v', \
+	.long_name = "verbose", \
+	.value = (var), \
+	.help = N_("be more verbose"), \
+	.flags = PARSE_OPT_NOARG, \
+	.callback = &parse_opt_verbosity_cb, \
+}, { \
+	.type = OPTION_CALLBACK, \
+	.short_name = 'q', \
+	.long_name = "quiet", \
+	.value = (var), \
+	.help = N_("be more quiet"), \
+	.flags = PARSE_OPT_NOARG, \
+	.callback = &parse_opt_verbosity_cb, \
+}
 #define OPT__DRY_RUN(var, h)  OPT_BOOL('n', "dry-run", (var), (h))
 #define OPT__FORCE(var, h, f) OPT_COUNTUP_F('f', "force",   (var), (h), (f))
-#define OPT__ABBREV(var)  \
-	{ OPTION_CALLBACK, 0, "abbrev", (var), N_("n"),	\
-	  N_("use <n> digits to display object names"),	\
-	  PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
+#define OPT__ABBREV(var) { \
+	.type = OPTION_CALLBACK, \
+	.long_name = "abbrev", \
+	.value = (var), \
+	.argh = N_("n"), \
+	.help = N_("use <n> digits to display object names"), \
+	.flags = PARSE_OPT_OPTARG, \
+	.callback = &parse_opt_abbrev_cb, \
+}
 #define OPT__SUPER_PREFIX(var) \
 	OPT_STRING_F(0, "super-prefix", (var), N_("prefix"), \
 		N_("prefixed path to initial superproject"), PARSE_OPT_HIDDEN)
 
 #define OPT__COLOR(var, h) \
 	OPT_COLOR_FLAG(0, "color", (var), (h))
-#define OPT_COLUMN(s, l, v, h) \
-	{ OPTION_CALLBACK, (s), (l), (v), N_("style"), (h), PARSE_OPT_OPTARG, parseopt_column_callback }
-#define OPT_PASSTHRU(s, l, v, a, h, f) \
-	{ OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), parse_opt_passthru }
-#define OPT_PASSTHRU_ARGV(s, l, v, a, h, f) \
-	{ OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), parse_opt_passthru_argv }
-#define _OPT_CONTAINS_OR_WITH(name, variable, help, flag) \
-	{ OPTION_CALLBACK, 0, name, (variable), N_("commit"), (help), \
-	  PARSE_OPT_LASTARG_DEFAULT | flag, \
-	  parse_opt_commits, (intptr_t) "HEAD" \
-	}
+#define OPT_COLUMN(s, l, v, h) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = N_("style"), \
+	.help = (h), \
+	.flags = PARSE_OPT_OPTARG, \
+	.callback = parseopt_column_callback, \
+}
+#define OPT_PASSTHRU(s, l, v, a, h, f) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = (a), \
+	.help = (h), \
+	.flags = (f), \
+	.callback = parse_opt_passthru, \
+}
+#define OPT_PASSTHRU_ARGV(s, l, v, a, h, f) { \
+	.type = OPTION_CALLBACK, \
+	.short_name = (s), \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = (a), \
+	.help = (h), \
+	.flags = (f), \
+	.callback = parse_opt_passthru_argv, \
+}
+#define _OPT_CONTAINS_OR_WITH(l, v, h, f) { \
+	.type = OPTION_CALLBACK, \
+	.long_name = (l), \
+	.value = (v), \
+	.argh = N_("commit"), \
+	.help = (h), \
+	.flags = PARSE_OPT_LASTARG_DEFAULT | (f), \
+	.callback = parse_opt_commits, \
+	.defval = (intptr_t) "HEAD", \
+}
 #define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, PARSE_OPT_NONEG)
 #define OPT_NO_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("no-contains", v, h, PARSE_OPT_NONEG)
 #define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG)
diff --git a/patch-ids.c b/patch-ids.c
index 3153446..19af7be 100644
--- a/patch-ids.c
+++ b/patch-ids.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "diff.h"
 #include "commit.h"
 #include "hash-lookup.h"
+#include "hex.h"
 #include "patch-ids.h"
 
 static int patch_id_defined(struct commit *commit)
diff --git a/path.c b/path.c
index 492e17a..7c1cd81 100644
--- a/path.c
+++ b/path.c
@@ -1,18 +1,24 @@
 /*
  * Utilities for paths and pathnames
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "strbuf.h"
 #include "string-list.h"
 #include "dir.h"
 #include "worktree.h"
+#include "setup.h"
 #include "submodule-config.h"
 #include "path.h"
 #include "packfile.h"
 #include "object-store.h"
 #include "lockfile.h"
 #include "exec-cmd.h"
+#include "wrapper.h"
 
 static int get_st_mode_bits(const char *path, int *mode)
 {
@@ -347,7 +353,8 @@ static void init_common_trie(void)
  * Helper function for update_common_dir: returns 1 if the dir
  * prefix is common.
  */
-static int check_common(const char *unmatched, void *value, void *baton)
+static int check_common(const char *unmatched, void *value,
+			void *baton UNUSED)
 {
 	struct common_dir *dir = value;
 
diff --git a/path.h b/path.h
index 0a59c85..60e83a4 100644
--- a/path.h
+++ b/path.h
@@ -3,6 +3,7 @@
 
 struct repository;
 struct strbuf;
+struct string_list;
 
 /*
  * The result to all functions which return statically allocated memory may be
@@ -179,7 +180,66 @@ const char *git_path_auto_merge(struct repository *r);
 const char *git_path_fetch_head(struct repository *r);
 const char *git_path_shallow(struct repository *r);
 
-
 int ends_with_path_components(const char *path, const char *components);
+int validate_headref(const char *ref);
+
+int adjust_shared_perm(const char *path);
+
+char *interpolate_path(const char *path, int real_home);
+const char *enter_repo(const char *path, int strict);
+const char *remove_leading_path(const char *in, const char *prefix);
+const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
+int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);
+int normalize_path_copy(char *dst, const char *src);
+int longest_ancestor_length(const char *path, struct string_list *prefixes);
+char *strip_path_suffix(const char *path, const char *suffix);
+int daemon_avoid_alias(const char *path);
+
+/*
+ * These functions match their is_hfs_dotgit() counterparts; see utf8.h for
+ * details.
+ */
+int is_ntfs_dotgit(const char *name);
+int is_ntfs_dotgitmodules(const char *name);
+int is_ntfs_dotgitignore(const char *name);
+int is_ntfs_dotgitattributes(const char *name);
+int is_ntfs_dotmailmap(const char *name);
+
+/*
+ * Returns true iff "str" could be confused as a command-line option when
+ * passed to a sub-program like "ssh". Note that this has nothing to do with
+ * shell-quoting, which should be handled separately; we're assuming here that
+ * the string makes it verbatim to the sub-program.
+ */
+int looks_like_command_line_option(const char *str);
+
+/**
+ * Return a newly allocated string with the evaluation of
+ * "$XDG_CONFIG_HOME/$subdir/$filename" if $XDG_CONFIG_HOME is non-empty, otherwise
+ * "$HOME/.config/$subdir/$filename". Return NULL upon error.
+ */
+char *xdg_config_home_for(const char *subdir, const char *filename);
+
+/**
+ * Return a newly allocated string with the evaluation of
+ * "$XDG_CONFIG_HOME/git/$filename" if $XDG_CONFIG_HOME is non-empty, otherwise
+ * "$HOME/.config/git/$filename". Return NULL upon error.
+ */
+char *xdg_config_home(const char *filename);
+
+/**
+ * Return a newly allocated string with the evaluation of
+ * "$XDG_CACHE_HOME/git/$filename" if $XDG_CACHE_HOME is non-empty, otherwise
+ * "$HOME/.cache/git/$filename". Return NULL upon error.
+ */
+char *xdg_cache_home(const char *filename);
+
+/*
+ * Create a directory and (if share is nonzero) adjust its permissions
+ * according to the shared_repository setting. Only use this for
+ * directories under $GIT_DIR.  Don't use it for working tree
+ * directories.
+ */
+void safe_create_dir(const char *dir, int share);
 
 #endif /* PATH_H */
diff --git a/pathspec.c b/pathspec.c
index ab70fcb..6966b26 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -1,9 +1,15 @@
 #include "cache.h"
+#include "abspath.h"
 #include "config.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
 #include "pathspec.h"
 #include "attr.h"
+#include "repository.h"
+#include "setup.h"
 #include "strvec.h"
+#include "symlinks.h"
 #include "quote.h"
 
 /*
@@ -730,7 +736,7 @@ int match_pathspec_attrs(struct index_state *istate,
 	if (name[namelen])
 		name = to_free = xmemdupz(name, namelen);
 
-	git_check_attr(istate, NULL, name, item->attr_check);
+	git_check_attr(istate, name, item->attr_check);
 
 	free(to_free);
 
diff --git a/pathspec.h b/pathspec.h
index 41f6adf..a5b38e0 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -171,6 +171,11 @@ int match_pathspec_attrs(struct index_state *istate,
 			 const char *name, int namelen,
 			 const struct pathspec_item *item);
 
+int match_pathspec(struct index_state *istate,
+		   const struct pathspec *pathspec,
+		   const char *name, int namelen,
+		   int prefix, char *seen, int is_dir);
+
 /*
  * Determine whether a pathspec will match only entire index entries (non-sparse
  * files and/or entire sparse directories). If the pathspec has the potential to
diff --git a/pkt-line.c b/pkt-line.c
index ce4e73b..62b4208 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -1,6 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "copy.h"
 #include "pkt-line.h"
+#include "gettext.h"
+#include "hex.h"
 #include "run-command.h"
+#include "trace.h"
+#include "wrapper.h"
+#include "write-or-die.h"
 
 char packet_buffer[LARGE_PACKET_MAX];
 static const char *packet_trace_prefix = "git";
diff --git a/pkt-line.h b/pkt-line.h
index 79c538b..7c23a4b 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -1,7 +1,6 @@
 #ifndef PKTLINE_H
 #define PKTLINE_H
 
-#include "git-compat-util.h"
 #include "strbuf.h"
 #include "sideband.h"
 
@@ -247,4 +246,6 @@ void packet_writer_error(struct packet_writer *writer, const char *fmt, ...);
 void packet_writer_delim(struct packet_writer *writer);
 void packet_writer_flush(struct packet_writer *writer);
 
+void packet_trace_identity(const char *prog);
+
 #endif
diff --git a/po/TEAMS b/po/TEAMS
index 5a63397..87df7c6 100644
--- a/po/TEAMS
+++ b/po/TEAMS
@@ -51,7 +51,7 @@
 Leader:		Arusekk <arek_koz@o2.pl>
 
 Language:	pt_PT (Portuguese - Portugal)
-Repository:	https://codeberg.org/git-pt/Git-PO-pt_PT/
+Repository:	https://gitlab.com/alexandre1985/git-pt/
 Leader:		Daniel Santos <dacs.git@brilhante.top>
 
 Language:	ru (Russian)
@@ -67,16 +67,22 @@
 Repository:	https://github.com/bitigchi/git-po/
 Leader:		Emir SARI <bitigchi@me.com>
 
+Language:	uk (Ukrainian)
+Repository:	https://github.com/arkid15r/git-ukrainian-l10n/
+Leader:		Arkadii Yakovets <ark@cho.red>
+Members:	Kateryna Golovanova <kate@kgthreads.com>
+
 Language:	vi (Vietnamese)
 Repository:	https://github.com/vnwildman/git/
 Leader:		Trần Ngọc Quân <vnwildman AT gmail.com>
 Members:	Nguyễn Thái Ngọc Duy <pclouds AT gmail.com>
 
 Language:	zh_CN (Simplified Chinese)
-Repository:	https://github.com/fangyi-zhou/git-po/
-Leader:		Fangyi Zhou <me AT fangyi.io>
+Repository:	https://github.com/dyrone/git/
+Leader:		Teng Long <dyroneteng AT gmail.com>
 Members:	Ray Chen <oldsharp AT gmail.com>
 		依云 <lilydjwg AT gmail.com>
+		Fangyi Zhou <me AT fangyi.io>
 		Jiang Xin <worldhello.net AT gmail.com>
 
 Language:	zh_TW (Traditional Chinese)
diff --git a/po/bg.po b/po/bg.po
index daec132..61214c4 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -199,7 +199,8 @@
 # gitattributes file файл с атрибути на git
 # advertised обявен за наличен
 # superproject свръхпроект
-#
+# rev-index обратен индекс (reverse index)
+# dererging branches раздалечили се клони
 # ------------------------
 # „$var“ - може да не сработва за shell има gettext и eval_gettext - проверка - намират се лесно по „$
 # ------------------------
@@ -216,10 +217,10 @@
 # for i in `sort -u FILES`; do cnt=`grep $i FILES | wc -l`; echo $cnt $i ;done | sort -n
 msgid ""
 msgstr ""
-"Project-Id-Version: git 2.40\n"
+"Project-Id-Version: git 2.41\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-03-01 01:20+0000\n"
-"PO-Revision-Date: 2023-03-02 08:54+0200\n"
+"POT-Creation-Date: 2023-05-19 19:48+0200\n"
+"PO-Revision-Date: 2023-05-19 20:57+0300\n"
 "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
 "Language-Team: Bulgarian <dict@fsa-bg.org>\n"
 "Language: bg\n"
@@ -890,6 +891,23 @@
 msgid "Exiting because of unfinished merge."
 msgstr "Изход от програмата заради незавършено сливане."
 
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"Раздалечили се клони не може да се превъртят.  Ползвайте:\n"
+"\n"
+"  git merge --no-ff\n"
+"\n"
+"или:\n"
+"\n"
+"  git rebase\n"
+
 msgid "Not possible to fast-forward, aborting."
 msgstr "Не може да се извърши превъртане, преустановяване на действието."
 
@@ -1354,6 +1372,10 @@
 msgstr "„%s“ не може да бъде отворен"
 
 #, c-format
+msgid "cannot unlink '%s'"
+msgstr "„%s“ не може да се изтрие"
+
+#, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "%d-то парче бе успешно приложено."
 
@@ -1547,6 +1569,10 @@
 msgstr "файлът „%s“ не може да бъде прочетен"
 
 #, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr "пътят „%s“ съвпада с файлове извън текущата директория"
+
+#, c-format
 msgid "pathspec '%s' did not match any files"
 msgstr "пътят „%s“ не съвпада с никой файл"
 
@@ -1562,9 +1588,6 @@
 msgid "not a tree object: %s"
 msgstr "не е обект-дърво: %s"
 
-msgid "current working directory is untracked"
-msgstr "текущата работна директория не е следена"
-
 #, c-format
 msgid "File not found: %s"
 msgstr "Файлът „%s“ липсва"
@@ -1691,6 +1714,11 @@
 msgid "ignoring overly large gitattributes blob '%s'"
 msgstr "прескачане на прекалено големия обект-BLOB за атрибути на git: „%s“"
 
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr ""
+"неправилна стойност за опцията „--attr-source“ или променливата "
+"„GIT_ATTR_SOURCE“"
+
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
 msgstr "Неправилно цитирано съдържание във файла „%s“: %s"
@@ -1796,9 +1824,6 @@
 msgid "--contents and --reverse do not blend well."
 msgstr "опциите „--contents“ и „--reverse“ са несъвместими"
 
-msgid "cannot use --contents with final commit object name"
-msgstr "опцията „--contents“ е несъвместима с име на обект от крайно подаване"
-
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr ""
 "Едновременното задаване на опциите „--reverse“ и „--first-parent“ изисква "
@@ -1985,10 +2010,6 @@
 msgid "'%s' is already checked out at '%s'"
 msgstr "„%s“ вече е изтеглен в „%s“"
 
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "Указателят „HEAD“ на работното дърво „%s“ не е обновен"
-
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [ОПЦИЯ…] [--] ПЪТ…"
 
@@ -3081,6 +3102,14 @@
 msgstr "следящият клон „%s“ не може да бъде открит."
 
 #, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"клонът „%s“ не може да бъде открит.\n"
+"Пробвахте ли опцията „--remote“?"
+
+#, c-format
 msgid "branch '%s' not found."
 msgstr "клонът „%s“ не може да бъде открит."
 
@@ -3111,6 +3140,10 @@
 msgstr "Търси се двоично в клона „%s“ при „%s“"
 
 #, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "Указателят „HEAD“ на работното дърво „%s“ не е обновен"
+
+#, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "Неправилно име на клон: „%s“"
 
@@ -3213,6 +3246,9 @@
 msgid "move/rename a branch, even if target exists"
 msgstr "преместване/преименуване на клон, дори ако има вече клон с такова име"
 
+msgid "do not output a newline after empty formatted refs"
+msgstr "без извеждане на нов ред след празен форматиран указател"
+
 msgid "copy a branch and its reflog"
 msgstr "копиране на клон и принадлежащия му журнал на указателите"
 
@@ -3436,12 +3472,10 @@
 msgstr "Новият доклад е създаден в „%s“.\n"
 
 msgid ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress ]\n"
 "                  [--version=ВЕРСИЯ] ФАЙЛ ОПЦИЯ_ЗА_git-rev-list…"
 
 msgid "git bundle verify [-q | --quiet] <file>"
@@ -3462,12 +3496,11 @@
 msgid "show progress meter"
 msgstr "извеждане на напредъка"
 
-msgid "show progress meter during object writing phase"
-msgstr "извеждане на напредъка във фазата на запазване на обектите"
+msgid "historical; same as --progress"
+msgstr "изоставена опция, същото като „--progress“"
 
-msgid "similar to --all-progress when progress meter is shown"
-msgstr ""
-"същото действие като опцията „--all-progress“ при извеждането на напредъка"
+msgid "historical; does nothing"
+msgstr "изоставена опция, нищо не прави"
 
 msgid "specify bundle format version"
 msgstr "версия на пратката"
@@ -4499,6 +4532,10 @@
 msgstr "„%s“ съществува и не е директория"
 
 #, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "„%s“ е символна връзка, не може да се клонира с опцията „--local“"
+
+#, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "неуспешно итериране по „%s“"
 
@@ -6071,6 +6108,181 @@
 msgid "fetch.parallel cannot be negative"
 msgstr "опцията „fetch.parallel“ трябва да е неотрицателна"
 
+msgid "couldn't find remote ref HEAD"
+msgstr "указателят „HEAD“ в отдалеченото хранилище не може да бъде открит"
+
+#, c-format
+msgid "From %.*s\n"
+msgstr "От %.*s\n"
+
+#, c-format
+msgid "object %s not found"
+msgstr "обектът „%s“ липсва"
+
+msgid "[up to date]"
+msgstr "[актуален]"
+
+msgid "[rejected]"
+msgstr "[отхвърлен]"
+
+msgid "can't fetch into checked-out branch"
+msgstr "в текущия клон не може да се доставя"
+
+msgid "[tag update]"
+msgstr "[обновяване на етикетите]"
+
+msgid "unable to update local ref"
+msgstr "локален указател не може да бъде обновен"
+
+msgid "would clobber existing tag"
+msgstr "съществуващ етикет ще бъде презаписан"
+
+msgid "[new tag]"
+msgstr "[нов етикет]"
+
+msgid "[new branch]"
+msgstr "[нов клон]"
+
+msgid "[new ref]"
+msgstr "[нов указател]"
+
+msgid "forced update"
+msgstr "принудително обновяване"
+
+msgid "non-fast-forward"
+msgstr "същинско сливане"
+
+#, c-format
+msgid "cannot open '%s'"
+msgstr "„%s“ не може да бъде отворен"
+
+msgid ""
+"fetch normally indicates which branches had a forced update,\n"
+"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
+"flag or run 'git config fetch.showForcedUpdates true'"
+msgstr ""
+"Обичайно при доставяне се извежда, кои клони са били принудително обновени,\n"
+"но тази проверка е изключена.  За да я включите за командата, ползвайте "
+"опцията\n"
+"„--show-forced-updates“, а за да я включите за постоянно, изпълнете:\n"
+"\n"
+"    git config fetch.showForcedUpdates true"
+
+#, c-format
+msgid ""
+"it took %.2f seconds to check forced updates; you can use\n"
+"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
+"false'\n"
+"to avoid this check\n"
+msgstr ""
+"Проверката за принудителни изтласквания отне %.2f сек.  Може да я прескочите "
+"еднократно с опцията „--no-show-forced-updates“, а за да я изключите за "
+"постоянно, изпълнете:\n"
+"\n"
+"    git config fetch.showForcedUpdates false\n"
+
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "хранилището „%s“ не изпрати всички необходими обекти\n"
+
+#, c-format
+msgid "rejected %s because shallow roots are not allowed to be updated"
+msgstr ""
+"отхвърляне на „%s“, защото плитките върхове не може да бъдат обновявани"
+
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+"някои локални указатели не може да бъдат обновени.  Изпълнете командата\n"
+"„git remote prune %s“, за да премахнете остарелите клони, които\n"
+"предизвикват конфликта"
+
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr "   (обектът „%s“ ще се окаже извън клон)"
+
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr "   (обектът „%s“ вече е извън клон)"
+
+msgid "[deleted]"
+msgstr "[изтрит]"
+
+msgid "(none)"
+msgstr "(нищо)"
+
+#, c-format
+msgid "refusing to fetch into branch '%s' checked out at '%s'"
+msgstr "не може да доставите в клона „%s“, който е изтеглен в пътя „%s“"
+
+#, c-format
+msgid "option \"%s\" value \"%s\" is not valid for %s"
+msgstr "стойността „%2$s“ за опцията „%1$s“ не е съвместима с „%3$s“"
+
+#, c-format
+msgid "option \"%s\" is ignored for %s\n"
+msgstr "опцията „%s“ се прескача при „%s“\n"
+
+#, c-format
+msgid "%s is not a valid object"
+msgstr "„%s“ е неправилен обект"
+
+#, c-format
+msgid "the object %s does not exist"
+msgstr "обектът „%s“ не съществува"
+
+msgid "multiple branches detected, incompatible with --set-upstream"
+msgstr ""
+"засечени са множество клони, това е несъвместимо с опцията „--set-upstream“"
+
+#, c-format
+msgid ""
+"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
+"any branch."
+msgstr ""
+"следеното от „HEAD“ не може да се смени от „%2$s“ на „%1$s“, защото второто "
+"не сочи към никой клон."
+
+msgid "not setting upstream for a remote remote-tracking branch"
+msgstr "не може да указвате клон за следене на отдалечен етикет"
+
+msgid "not setting upstream for a remote tag"
+msgstr "не може да указвате клон за следене на отдалечен етикет"
+
+msgid "unknown branch type"
+msgstr "непознат вид клон"
+
+msgid ""
+"no source branch found;\n"
+"you need to specify exactly one branch with the --set-upstream option"
+msgstr ""
+"не е открит клон за следене;\n"
+"трябва изрично да зададете точно един клон с опцията „--set-upstream“"
+
+#, c-format
+msgid "Fetching %s\n"
+msgstr "Доставяне на „%s“\n"
+
+#, c-format
+msgid "could not fetch %s"
+msgstr "„%s“ не може да се достави"
+
+#, c-format
+msgid "could not fetch '%s' (exit code: %d)\n"
+msgstr "„%s“ не може да се достави (изходният код е: %d)\n"
+
+msgid ""
+"no remote repository specified; please specify either a URL or a\n"
+"remote name from which new revisions should be fetched"
+msgstr ""
+"не сте указали отдалечено хранилище; задайте или адрес, или име\n"
+"на отдалечено хранилище, откъдето да се доставят новите версии."
+
+msgid "you need to specify a tag name"
+msgstr "трябва да укажете име на етикет"
+
 msgid "fetch from all remotes"
 msgstr "доставяне от всички отдалечени хранилища"
 
@@ -6180,181 +6392,6 @@
 msgid "accept refspecs from stdin"
 msgstr "четене на указателите от стандартния вход"
 
-msgid "couldn't find remote ref HEAD"
-msgstr "указателят „HEAD“ в отдалеченото хранилище не може да бъде открит"
-
-#, c-format
-msgid "object %s not found"
-msgstr "обектът „%s“ липсва"
-
-msgid "[up to date]"
-msgstr "[актуален]"
-
-msgid "[rejected]"
-msgstr "[отхвърлен]"
-
-msgid "can't fetch into checked-out branch"
-msgstr "в текущия клон не може да се доставя"
-
-msgid "[tag update]"
-msgstr "[обновяване на етикетите]"
-
-msgid "unable to update local ref"
-msgstr "локален указател не може да бъде обновен"
-
-msgid "would clobber existing tag"
-msgstr "съществуващ етикет ще бъде презаписан"
-
-msgid "[new tag]"
-msgstr "[нов етикет]"
-
-msgid "[new branch]"
-msgstr "[нов клон]"
-
-msgid "[new ref]"
-msgstr "[нов указател]"
-
-msgid "forced update"
-msgstr "принудително обновяване"
-
-msgid "non-fast-forward"
-msgstr "същинско сливане"
-
-#, c-format
-msgid "cannot open '%s'"
-msgstr "„%s“ не може да бъде отворен"
-
-msgid ""
-"fetch normally indicates which branches had a forced update,\n"
-"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
-"flag or run 'git config fetch.showForcedUpdates true'"
-msgstr ""
-"Обичайно при доставяне се извежда, кои клони са били принудително обновени,\n"
-"но тази проверка е изключена.  За да я включите за командата, ползвайте "
-"опцията\n"
-"„--show-forced-updates“, а за да я включите за постоянно, изпълнете:\n"
-"\n"
-"    git config fetch.showForcedUpdates true"
-
-#, c-format
-msgid ""
-"it took %.2f seconds to check forced updates; you can use\n"
-"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
-"false'\n"
-"to avoid this check\n"
-msgstr ""
-"Проверката за принудителни изтласквания отне %.2f сек.  Може да я прескочите "
-"еднократно с опцията „--no-show-forced-updates“, а за да я изключите за "
-"постоянно, изпълнете:\n"
-"\n"
-"    git config fetch.showForcedUpdates false\n"
-
-#, c-format
-msgid "%s did not send all necessary objects\n"
-msgstr "хранилището „%s“ не изпрати всички необходими обекти\n"
-
-#, c-format
-msgid "rejected %s because shallow roots are not allowed to be updated"
-msgstr ""
-"отхвърляне на „%s“, защото плитките върхове не може да бъдат обновявани"
-
-#, c-format
-msgid "From %.*s\n"
-msgstr "От %.*s\n"
-
-#, c-format
-msgid ""
-"some local refs could not be updated; try running\n"
-" 'git remote prune %s' to remove any old, conflicting branches"
-msgstr ""
-"някои локални указатели не може да бъдат обновени.  Изпълнете командата\n"
-"„git remote prune %s“, за да премахнете остарелите клони, които\n"
-"предизвикват конфликта"
-
-#, c-format
-msgid "   (%s will become dangling)"
-msgstr "   (обектът „%s“ ще се окаже извън клон)"
-
-#, c-format
-msgid "   (%s has become dangling)"
-msgstr "   (обектът „%s“ вече е извън клон)"
-
-msgid "[deleted]"
-msgstr "[изтрит]"
-
-msgid "(none)"
-msgstr "(нищо)"
-
-#, c-format
-msgid "refusing to fetch into branch '%s' checked out at '%s'"
-msgstr "не може да доставите в клона „%s“, който е изтеглен в пътя „%s“"
-
-#, c-format
-msgid "option \"%s\" value \"%s\" is not valid for %s"
-msgstr "стойността „%2$s“ за опцията „%1$s“ не е съвместима с „%3$s“"
-
-#, c-format
-msgid "option \"%s\" is ignored for %s\n"
-msgstr "опцията „%s“ се прескача при „%s“\n"
-
-#, c-format
-msgid "%s is not a valid object"
-msgstr "„%s“ е неправилен обект"
-
-#, c-format
-msgid "the object %s does not exist"
-msgstr "обектът „%s“ не съществува"
-
-msgid "multiple branches detected, incompatible with --set-upstream"
-msgstr ""
-"засечени са множество клони, това е несъвместимо с опцията „--set-upstream“"
-
-#, c-format
-msgid ""
-"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
-"any branch."
-msgstr ""
-"следеното от „HEAD“ не може да се смени от „%2$s“ на „%1$s“, защото второто "
-"не сочи към никой клон."
-
-msgid "not setting upstream for a remote remote-tracking branch"
-msgstr "не може да указвате клон за следене на отдалечен етикет"
-
-msgid "not setting upstream for a remote tag"
-msgstr "не може да указвате клон за следене на отдалечен етикет"
-
-msgid "unknown branch type"
-msgstr "непознат вид клон"
-
-msgid ""
-"no source branch found;\n"
-"you need to specify exactly one branch with the --set-upstream option"
-msgstr ""
-"не е открит клон за следене;\n"
-"трябва изрично да зададете точно един клон с опцията „--set-upstream“"
-
-#, c-format
-msgid "Fetching %s\n"
-msgstr "Доставяне на „%s“\n"
-
-#, c-format
-msgid "could not fetch %s"
-msgstr "„%s“ не може да се достави"
-
-#, c-format
-msgid "could not fetch '%s' (exit code: %d)\n"
-msgstr "„%s“ не може да се достави (изходният код е: %d)\n"
-
-msgid ""
-"no remote repository specified; please specify either a URL or a\n"
-"remote name from which new revisions should be fetched"
-msgstr ""
-"не сте указали отдалечено хранилище; задайте или адрес, или име\n"
-"на отдалечено хранилище, откъдето да се доставят новите версии."
-
-msgid "you need to specify a tag name"
-msgstr "трябва да укажете име на етикет"
-
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr ""
 "Опцията „--negotiate-only“ изисква една или повече опции „--negotiation-"
@@ -6473,6 +6510,12 @@
 msgid "print only refs which don't contain the commit"
 msgstr "извеждане само на указателите, които не съдържат това ПОДАВАНЕ"
 
+msgid "read reference patterns from stdin"
+msgstr "изчитане на шаблоните за указатели от стандартния вход"
+
+msgid "unknown arguments supplied with --stdin"
+msgstr "непознат аргумент към опцията „--stdin“"
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=НАСТРОЙКА [--] АРГУМЕНТ…"
 
@@ -6485,6 +6528,10 @@
 msgid "missing --config=<config>"
 msgstr "липсва --config=НАСТРОЙКА"
 
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "получена е неправилена настройка „--config=%s“"
+
 msgid "unknown"
 msgstr "непознат"
 
@@ -6631,19 +6678,28 @@
 msgid "notice: %s points to an unborn branch (%s)"
 msgstr "предупреждение: „%s“ сочи към все още несъществуващ клон (%s)"
 
-msgid "Checking cache tree"
-msgstr "Проверка на кеша на обектите-дървета"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "Проверка на кеша на обектите-дървета на „%s“"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "„%s“: неправилен указател за SHA1 в кеша на обектите-дървета"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "„%s“: неправилен указател за SHA1 в кеша на обектите-дървета на „%s“"
 
 msgid "non-tree in cache-tree"
 msgstr "в кеша на обектите-дървета има нещо, което не е дърво"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in resolve-undo"
-msgstr "„%s“: неправилен указател за отмяна на разрешените подавания"
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "„%s“: неправилен указател за отмяна на разрешените подавания на „%s“"
+
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "обратният индекс на пакета „%s“ не може да бъде зареден"
+
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "неправилен обратен индекс за пакета „%s“"
 
 msgid ""
 "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
@@ -9584,6 +9640,13 @@
 msgid "bad index version '%s'"
 msgstr "неправилна версия на индекса „%s“"
 
+msgid "show progress meter during object writing phase"
+msgstr "извеждане на напредъка във фазата на запазване на обектите"
+
+msgid "similar to --all-progress when progress meter is shown"
+msgstr ""
+"същото действие като опцията „--all-progress“ при извеждането на напредъка"
+
 msgid "<version>[,<offset>]"
 msgstr "ВЕРСИЯ[,ОТМЕСТВАНЕ]"
 
@@ -9788,6 +9851,9 @@
 "ни известите с е-писмо до пощенския списък:\n"
 "<git@vger.kernel.org>.\n"
 
+msgid "refusing to run without --i-still-use-this"
+msgstr "трябва да добавите и опцията „--i-still-use-this“"
+
 msgid "git pack-refs [--all] [--no-prune]"
 msgstr "git pack-refs [--all] [--no-prune]"
 
@@ -9962,8 +10028,8 @@
 msgid "pull with rebase"
 msgstr "издърпване с пребазиране"
 
-msgid "please commit or stash them."
-msgstr "трябва да подадете или скатаете промѐните."
+msgid "Please commit or stash them."
+msgstr "Промѐните трябва или да се подадат, или да се скатаят."
 
 #, c-format
 msgid ""
@@ -10001,7 +10067,7 @@
 
 msgid "Need to specify how to reconcile divergent branches."
 msgstr ""
-"Трябва да укажете как да се решават разликите при разминаване на клоните."
+"Трябва да укажете как да се решават разликите при раздалечаване на клоните."
 
 msgid "cannot rebase with locally recorded submodule modifications"
 msgstr ""
@@ -10210,8 +10276,8 @@
 msgid "repository"
 msgstr "хранилище"
 
-msgid "push all refs"
-msgstr "изтласкване на всички указатели"
+msgid "push all branches"
+msgstr "изтласкване на всички клони"
 
 msgid "mirror all refs"
 msgstr "огледално копие на всички указатели"
@@ -10219,8 +10285,10 @@
 msgid "delete refs"
 msgstr "изтриване на указателите"
 
-msgid "push tags (can't be used with --all or --mirror)"
-msgstr "изтласкване на етикетите (несъвместимо с опциите „--all“ и „--mirror“)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr ""
+"изтласкване на етикетите (несъвместимо с опциите „--all“, „--branches“ и „--"
+"mirror“)"
 
 msgid "force updates"
 msgstr "принудително обновяване"
@@ -10485,6 +10553,10 @@
 "В резултат те не може да се пребазират."
 
 #, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "Неправилен режим за „--rebase-merges“: %s"
+
+#, c-format
 msgid "could not switch to %s"
 msgstr "не може да се премине към „%s“"
 
@@ -10499,6 +10571,15 @@
 "неправилна стойност „%s“: вариантите са „drop“ (прескачане), "
 "„keep“ (запазване) и „ask“ (питане)"
 
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"ползването на „--rebase-merges“ с празен низ за аргумент е остаряло и в "
+"бъдеще ще спре да работи. Ползвайте опцията „--rebase-merges“ без аргумент, "
+"за да постигнете същия резултат."
+
 #, c-format
 msgid ""
 "%s\n"
@@ -10728,22 +10809,25 @@
 msgid "switch `C' expects a numerical value"
 msgstr "опцията „C“ очаква число за аргумент"
 
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "Неизвестна стратегия: „%s“"
-
 msgid "--strategy requires --merge or --interactive"
 msgstr ""
 "опцията „--strategy“ изисква някоя от опциите „--merge“ или „--interactive“"
 
 msgid ""
-"apply options are incompatible with rebase.autosquash.  Consider adding --no-"
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
 "autosquash"
 msgstr ""
-"опциите за прилагане са несъвместими с „rebase.autosquash“.  Пробвайте да "
+"опциите за прилагане са несъвместими с „rebase.autoSquash“.  Пробвайте да "
 "добавите опцията „--no-autosquash“"
 
 msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr ""
+"опциите за прилагане са несъвместими с „rebase.rebaseMerges“.  Пробвайте да "
+"добавите опцията „--no-rebase-merges“"
+
+msgid ""
 "apply options are incompatible with rebase.updateRefs.  Consider adding --no-"
 "update-refs"
 msgstr ""
@@ -10789,9 +10873,6 @@
 msgid "Does not point to a valid commit '%s'"
 msgstr "Указателят „%s“ не сочи към подаване"
 
-msgid "Please commit or stash them."
-msgstr "Промѐните трябва или да се подадат, или да се скатаят."
-
 msgid "HEAD is up to date."
 msgstr "Указателят „HEAD“ е напълно актуален."
 
@@ -11476,9 +11557,9 @@
 msgid "approxidate"
 msgstr "евристична дата"
 
-msgid "with -C, expire objects older than this"
+msgid "with --cruft, expire objects older than this"
 msgstr ""
-"с опцията „-C“: обявяване на обектите по-стари от това ВРЕМЕ за остарели"
+"с опцията „--cruft“: обявяване на обектите по-стари от това ВРЕМЕ за остарели"
 
 msgid "remove redundant packs, and run git-prune-packed"
 msgstr ""
@@ -12158,6 +12239,9 @@
 msgid "remote name"
 msgstr "име на отдалечено хранилище"
 
+msgid "push all refs"
+msgstr "изтласкване на всички указатели"
+
 msgid "use stateless RPC protocol"
 msgstr "използване на протокол без запазване на състоянието за RPC"
 
@@ -12364,9 +12448,11 @@
 "локалното хранилище"
 
 msgid ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable) ОПЦИЯ…"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) ОПЦИЯ…"
 
 msgid "this worktree is not sparse"
 msgstr "това работно дърво не е частично"
@@ -12492,6 +12578,24 @@
 msgid "error while refreshing working directory"
 msgstr "грешка при обновяване на работната директория"
 
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks] [--[no-]cone] [--rules-"
+"file ФАЙЛ]"
+
+msgid "terminate input and output files by a NUL character"
+msgstr "разделяне на входните и изходните файлове с нулевия знак „NUL“"
+
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr ""
+"когато е придружено с „--rules-file“ шаблоните се третират като шаблони в "
+"пътеводен режим"
+
+msgid "use patterns in <file> instead of the current ones."
+msgstr "ползване на шаблоните във ФАЙЛа вместо текущите."
+
 msgid "git stash list [<log-options>]"
 msgstr "git stash list [ОПЦИЯ_ЗА_ЖУРНАЛ…]"
 
@@ -15421,8 +15525,8 @@
 msgid "bad zlib compression level %d"
 msgstr "неправилно ниво на компресиране: %d"
 
-msgid "core.commentChar should only be one character"
-msgstr "настройката „core.commentChar“ трябва да е само един знак"
+msgid "core.commentChar should only be one ASCII character"
+msgstr "настройката „core.commentChar“ трябва да е само един знак от ASCII"
 
 #, c-format
 msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15540,6 +15644,10 @@
 msgstr "неправилно име на раздел: %s"
 
 #, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr "ред %2$<PRIuMAX> в „%1$s“ е прекалено дълъг"
+
+#, c-format
 msgid "missing value for '%s'"
 msgstr "липсва стойност за „%s“"
 
@@ -16235,6 +16343,9 @@
 msgid "do not show any source or destination prefix"
 msgstr "без префикс за източника и целта"
 
+msgid "use default prefixes a/ and b/"
+msgstr "ползване на стандартните префикси „a/“ и „b/“"
+
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr ""
 "извеждане на контекст между последователните парчета с разлики от указания "
@@ -16541,6 +16652,14 @@
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "Подсказка: чака се редакторът ви да затвори файла …%c"
 
+#, c-format
+msgid "could not write to '%s'"
+msgstr "в „%s“ не може да се пише"
+
+#, c-format
+msgid "could not edit '%s'"
+msgstr "„%s“ не може да се редактира"
+
 msgid "Filtering content"
 msgstr "Филтриране на съдържанието"
 
@@ -16846,6 +16965,10 @@
 msgstr "опцията „--config-env“ изисква ключ\n"
 
 #, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "опцията „--attr-source“ изисква източник на атрибути\n"
+
+#, c-format
 msgid "unknown option: %s\n"
 msgstr "непозната опция: „%s“\n"
 
@@ -18588,6 +18711,10 @@
 msgstr "използваното място за съхранение на „%s“ не може да бъде получено"
 
 #, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "неправилна сума за проверка за файла с битови маски „%s“"
+
+#, c-format
 msgid "mtimes file %s is too small"
 msgstr "файлът с времето на промяна (mtime) „%s“ е твърде малък"
 
@@ -18633,6 +18760,14 @@
 "идентификатор на контролна сума %2$<PRIu32> на файла с обратен индекс „%1$s“ "
 "не се поддържа"
 
+msgid "invalid checksum"
+msgstr "неправилна сума за проверка"
+
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr ""
+"неправилна позиция в обратния индекс при %<PRIu64>: %<PRIu32> != %<PRIu32>"
+
 msgid "cannot both write and verify reverse index"
 msgstr "обратният индекс не може едновременно да се записва и да се проверява"
 
@@ -19379,6 +19514,10 @@
 msgstr "очаква се положителна широчина с лексемата „%%(align)“"
 
 #, c-format
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "очакван формат: %%(ahead-behind:ПОДАВАНЕ)"
+
+#, c-format
 msgid "malformed field name: %.*s"
 msgstr "неправилно име на обект: „%.*s“"
 
@@ -19929,10 +20068,10 @@
 "Your branch and '%s' have diverged,\n"
 "and have %d and %d different commits each, respectively.\n"
 msgstr[0] ""
-"Текущият клон се е отделил от „%s“,\n"
+"Текущият клон се е раздалечил от „%s“,\n"
 "двата имат съответно по %d и %d несъвпадащи подавания.\n"
 msgstr[1] ""
-"Текущият клон се е отделил от „%s“,\n"
+"Текущият клон се е раздалечил от „%s“,\n"
 "двата имат съответно по %d и %d несъвпадащи подавания.\n"
 
 msgid "  (use \"git pull\" to merge the remote branch into yours)\n"
@@ -20012,10 +20151,6 @@
 msgstr "липсва запазена корекция на конфликт при „%s“"
 
 #, c-format
-msgid "cannot unlink '%s'"
-msgstr "„%s“ не може да се изтрие"
-
-#, c-format
 msgid "Updated preimage for '%s'"
 msgstr "Предварителният вариант на „%s“ е обновен"
 
@@ -20384,10 +20519,6 @@
 msgstr "„%s“ не може да се заключи"
 
 #, c-format
-msgid "could not write to '%s'"
-msgstr "в „%s“ не може да се пише"
-
-#, c-format
 msgid "could not write eol to '%s'"
 msgstr "краят на ред не може да се запише в „%s“"
 
@@ -20757,9 +20888,6 @@
 "директорията за определянето на последователността „%s“ не може да бъде "
 "създадена"
 
-msgid "could not lock HEAD"
-msgstr "указателят „HEAD“ не може да се заключи"
-
 msgid "no cherry-pick or revert in progress"
 msgstr ""
 "в момента не се извършва отбиране на подавания или пребазиране на клона"
@@ -20862,13 +20990,13 @@
 "    git rebase --continue\n"
 "\n"
 
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "и променѝ индекса и/или работното дърво\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "и променѝ индекса и/или работното дърво.\n"
 
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
@@ -21325,10 +21453,6 @@
 msgstr[1] "%u байта/сек."
 
 #, c-format
-msgid "could not edit '%s'"
-msgstr "„%s“ не може да се редактира"
-
-#, c-format
 msgid "ignoring suspicious submodule name: %s"
 msgstr "игнориране на подозрително име на подмодул: „%s“"
 
@@ -23085,13 +23209,17 @@
 msgstr "(%s) Не може да бъде се изпълни „%s“"
 
 #, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) Добавяне на „%s: %s“ от: „%s“\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) Неправилен изход от: „%s“."
 
 #, perl-format
 msgid "(%s) failed to close pipe to '%s'"
 msgstr "(%s) програмният канал не може да се затвори за изпълнението на „%s“"
 
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) Добавяне на „%s: %s“ от: „%s“\n"
+
 msgid "cannot send message as 7bit"
 msgstr "съобщението не може да се изпрати чрез 7 битови знаци"
 
diff --git a/po/ca.po b/po/ca.po
index c6d2dd6..4b164f2 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -68,8 +68,8 @@
 msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-03-01 01:20+0000\n"
-"PO-Revision-Date: 2023-03-01 19:00-0600\n"
+"POT-Creation-Date: 2023-05-20 14:03+0200\n"
+"PO-Revision-Date: 2023-05-26 19:00-0600\n"
 "Last-Translator: Jordi Mas i Hernàndez <jmas@softcatala.org>\n"
 "Language-Team: Catalan\n"
 "Language: ca\n"
@@ -584,7 +584,6 @@
 #. Consider translating (saying "no" discards!) as
 #. (saying "n" for "no" discards!) if the translation
 #. of the word "no" does not start with n.
-#.
 msgid ""
 "Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
 msgstr ""
@@ -723,6 +722,23 @@
 msgid "Exiting because of unfinished merge."
 msgstr "S'està sortint a causa d'una fusió no terminada."
 
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"Les branques divergents no es poden avançar ràpidament, cal que feu:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"o:\n"
+"\n"
+"\tgit rebase\n"
+
 msgid "Not possible to fast-forward, aborting."
 msgstr "No és possible avançar ràpidament, s'està avortant."
 
@@ -1174,6 +1190,10 @@
 msgstr "no es pot obrir %s"
 
 #, c-format
+msgid "cannot unlink '%s'"
+msgstr "no es pot fer «unlink» de «%s»"
+
+#, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "El tros #%d s'ha aplicat netament."
 
@@ -1365,6 +1385,11 @@
 msgstr "no es pot llegir «%s»"
 
 #, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr ""
+"l'específicació de camí «%s» coincideix amb fitxers fora del directori actual"
+
+#, c-format
 msgid "pathspec '%s' did not match any files"
 msgstr "l'especificació de camí «%s» no ha coincidit amb cap fitxer"
 
@@ -1380,9 +1405,6 @@
 msgid "not a tree object: %s"
 msgstr "no és un objecte d'arbre: %s"
 
-msgid "current working directory is untracked"
-msgstr "no se segueix el directori de treball actual"
-
 #, c-format
 msgid "File not found: %s"
 msgstr "Fitxer no trobat: %s"
@@ -1503,11 +1525,14 @@
 
 #, c-format
 msgid "ignoring overly large gitattributes file '%s'"
-msgstr "s'ignorarà el fitxer «%s» gitattributes per massa gran"
+msgstr "s'ignorarà el fitxer «%s» gitattributes per ser massa gran"
 
 #, c-format
 msgid "ignoring overly large gitattributes blob '%s'"
-msgstr "s'ignorarà la blob «%s» gitattributes per massa gran"
+msgstr "s'ignorarà el blob «%s» gitattributes per ser massa gran"
+
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr "--attr-source incorrecte o GIT_ATTR_SOURCE"
 
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
@@ -1605,7 +1630,6 @@
 
 #. TRANSLATORS: the last %s will be replaced with "(roughly %d
 #. steps)" translation.
-#.
 #, c-format
 msgid "Bisecting: %d revision left to test after this %s\n"
 msgid_plural "Bisecting: %d revisions left to test after this %s\n"
@@ -1615,9 +1639,6 @@
 msgid "--contents and --reverse do not blend well."
 msgstr "--contents i --reverse no funcionen bé juntes."
 
-msgid "cannot use --contents with final commit object name"
-msgstr "no es pot usar --contents amb el nom d'objecte de la comissió final"
-
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr ""
 "--reverse i --first-parent junts requereixen una última comissió especificada"
@@ -1694,20 +1715,17 @@
 #. TRANSLATORS: This is a line listing a remote with duplicate
 #. refspecs in the advice message below. For RTL languages you'll
 #. probably want to swap the "%s" and leading "  " space around.
-#.
 #. #-#-#-#-#  object-name.c.po  #-#-#-#-#
 #. TRANSLATORS: This is line item of ambiguous object output
 #. from describe_ambiguous_object() above. For RTL languages
 #. you'll probably want to swap the "%s" and leading " " space
 #. around.
-#.
 #, c-format
 msgid "  %s\n"
 msgstr "  %s\n"
 
 #. TRANSLATORS: The second argument is a \n-delimited list of
 #. duplicate refspecs, composed above.
-#.
 #, c-format
 msgid ""
 "There are multiple remotes whose fetch refspecs map to the remote\n"
@@ -1802,10 +1820,6 @@
 msgid "'%s' is already checked out at '%s'"
 msgstr "«%s» ja s'ha agafat a «%s»"
 
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "HEAD de l'arbre de treball %s no està actualitzat"
-
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<opcions>] [--] <especificació-de-camí>..."
 
@@ -2125,7 +2139,6 @@
 #. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
 #. in your translation. The program will only accept English
 #. input at this point.
-#.
 #, c-format
 msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "
 msgstr ""
@@ -2474,7 +2487,6 @@
 #. TRANSLATORS: Make sure to include [Y] and [n] in your
 #. translation. The program will only accept English input
 #. at this point.
-#.
 msgid "Are you sure [Y/n]? "
 msgstr "N'esteu segur [Y/n]? "
 
@@ -2552,7 +2564,6 @@
 #. TRANSLATORS: Make sure to include [Y] and [n] in your
 #. translation. The program will only accept English input
 #. at this point.
-#.
 msgid "Do you want me to do it for you [Y/n]? "
 msgstr "Voleu que ho faci per vostè [Y/n]? "
 
@@ -2709,7 +2720,7 @@
 msgstr "mostra la marca de temps en cru (per defecte: desactivat)"
 
 msgid "show long commit SHA1 (Default: off)"
-msgstr "mostra l'SHA1 de comissió llarg (per defecte: desactivat)"
+msgstr "mostra l'SHA1 de la comissió en format llarg (per defecte: desactivat)"
 
 msgid "suppress author name and timestamp (Default: off)"
 msgstr "omet el nom d'autor i la marca de temps (per defecte: desactivat)"
@@ -2773,7 +2784,6 @@
 #. among various forms of relative timestamps, but
 #. your language may need more or fewer display
 #. columns.
-#.
 msgid "4 years, 11 months ago"
 msgstr "fa 4 anys i 11 mesos"
 
@@ -2859,6 +2869,14 @@
 msgstr "no s'ha trobat la branca amb seguiment remot «%s»."
 
 #, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"no s'ha trobat la branca «%s».\n"
+"Us heu oblidat de --remote?"
+
+#, c-format
 msgid "branch '%s' not found."
 msgstr "no s'ha trobat la branca «%s»."
 
@@ -2889,6 +2907,10 @@
 msgstr "La branca %s s'està bisecant a %s"
 
 #, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "HEAD de l'arbre de treball %s no està actualitzat"
+
+#, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "Nom de branca no vàlid: «%s»"
 
@@ -2992,6 +3014,9 @@
 msgid "move/rename a branch, even if target exists"
 msgstr "mou/canvia de nom una branca, encara que el destí existeixi"
 
+msgid "do not output a newline after empty formatted refs"
+msgstr "no emetis cap línia nova després de refs amb format buit"
+
 msgid "copy a branch and its reflog"
 msgstr "copia una branca i el seu registre de referència"
 
@@ -3210,12 +3235,10 @@
 msgstr "S'ha creat un nou informe a «%s».\n"
 
 msgid ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<versió>] <fitxer> <git-rev-list-args>"
 
 msgid "git bundle verify [-q | --quiet] <file>"
@@ -3236,11 +3259,11 @@
 msgid "show progress meter"
 msgstr "mostra l'indicador de progrés"
 
-msgid "show progress meter during object writing phase"
-msgstr "mostra l'indicador de progrés durant la fase d'escriptura d'objectes"
+msgid "historical; same as --progress"
+msgstr "històric; el mateix que --progress"
 
-msgid "similar to --all-progress when progress meter is shown"
-msgstr "similar a --all-progress quan l'indicador de progrés es mostra"
+msgid "historical; does nothing"
+msgstr "històric; no fa res"
 
 msgid "specify bundle format version"
 msgstr "especifica la versió del format del farcell"
@@ -4250,12 +4273,16 @@
 msgstr "%s existeix i no és directori"
 
 #, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "«%s» és un enllaç simbòlic, es rebutja clonar amb --local"
+
+#, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "no s'ha pogut iniciar l'iterador sobre «%s»"
 
 #, c-format
 msgid "symlink '%s' exists, refusing to clone with --local"
-msgstr "l'enllaç simbòlic «%s» existeix, es nega a clonar amb --local"
+msgstr "l'enllaç simbòlic «%s» existeix, es rebutja a clonar amb --local"
 
 #, c-format
 msgid "failed to unlink '%s'"
@@ -4979,7 +5006,6 @@
 
 #. TRANSLATORS: Leave "[(amend|reword):]" as-is,
 #. and only translate <commit>.
-#.
 msgid "[(amend|reword):]commit"
 msgstr "[(amend|reword):]commit"
 
@@ -5263,7 +5289,7 @@
 msgstr "no s'admet escriure a stdin"
 
 msgid "writing config blobs is not supported"
-msgstr "no s'ha admet l'escriptura de blobs de configuració"
+msgstr "no s'admet l'escriptura de blobs de configuració"
 
 #, c-format
 msgid ""
@@ -5778,6 +5804,178 @@
 msgid "fetch.parallel cannot be negative"
 msgstr "fetch.parallel no pot ser negatiu"
 
+msgid "couldn't find remote ref HEAD"
+msgstr "no s'ha pogut trobar la referència HEAD remota"
+
+#, c-format
+msgid "From %.*s\n"
+msgstr "De %.*s\n"
+
+#, c-format
+msgid "object %s not found"
+msgstr "objecte %s no trobat"
+
+msgid "[up to date]"
+msgstr "[al dia]"
+
+msgid "[rejected]"
+msgstr "[rebutjat]"
+
+msgid "can't fetch into checked-out branch"
+msgstr "no es pot obtenir en la branca actual"
+
+msgid "[tag update]"
+msgstr "[actualització d'etiqueta]"
+
+msgid "unable to update local ref"
+msgstr "no s'ha pogut actualitzar la referència local"
+
+msgid "would clobber existing tag"
+msgstr "s'adjuntaria l'etiqueta existent"
+
+msgid "[new tag]"
+msgstr "[etiqueta nova]"
+
+msgid "[new branch]"
+msgstr "[branca nova]"
+
+msgid "[new ref]"
+msgstr "[referència nova]"
+
+msgid "forced update"
+msgstr "actualització forçada"
+
+msgid "non-fast-forward"
+msgstr "sense avanç ràpid"
+
+#, c-format
+msgid "cannot open '%s'"
+msgstr "no es pot obrir «%s»"
+
+msgid ""
+"fetch normally indicates which branches had a forced update,\n"
+"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
+"flag or run 'git config fetch.showForcedUpdates true'"
+msgstr ""
+"en obtenir normalment indica quines branques tenien una actualització "
+"forçada,\n"
+"però aquesta comprovació s'ha desactivat. Per a tornar a habilitar-la, "
+"utilitzeu\n"
+"«--show-forced-updates» o executeu «git config fetch.showForcedUpdates true»"
+
+#, c-format
+msgid ""
+"it took %.2f seconds to check forced updates; you can use\n"
+"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
+"false'\n"
+"to avoid this check\n"
+msgstr ""
+"s'ha trigat %.2f segons a comprovar les actualitzacions forçades. Podeu\n"
+"utilitzar «--no-show-forced-updates» o executar «git config \n"
+"fetch.showForcedUpdates false» per a evitar aquesta comprovació.\n"
+
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s no ha enviat tots els objectes necessaris\n"
+
+#, c-format
+msgid "rejected %s because shallow roots are not allowed to be updated"
+msgstr ""
+"s'ha rebutjat %s perquè no es permeten actualitzar les arrels superficials"
+
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" '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"
+" qualsevol branca antiga o conflictiva"
+
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr "   (%s es tornarà penjant)"
+
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr "   (%s s'ha tornat penjant)"
+
+msgid "[deleted]"
+msgstr "[suprimit]"
+
+msgid "(none)"
+msgstr "(cap)"
+
+#, c-format
+msgid "refusing to fetch into branch '%s' checked out at '%s'"
+msgstr "s'ha rebutjat l'obtenció en la branca «%s» agafada a «%s»"
+
+#, c-format
+msgid "option \"%s\" value \"%s\" is not valid for %s"
+msgstr "l'opció «%s» amb valor «%s» no és vàlida per a %s"
+
+#, c-format
+msgid "option \"%s\" is ignored for %s\n"
+msgstr "s'ignora l'opció «%s» per a %s\n"
+
+#, c-format
+msgid "%s is not a valid object"
+msgstr "%s no és un objecte vàlid"
+
+#, c-format
+msgid "the object %s does not exist"
+msgstr "l'objecte %s no existeix"
+
+msgid "multiple branches detected, incompatible with --set-upstream"
+msgstr "s'han detectat múltiples branques, incompatible amb --set-upstream"
+
+#, c-format
+msgid ""
+"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
+"any branch."
+msgstr ""
+"no s'ha pogut establir la font de HEAD a «%s» des de «%s» quan no assenyala "
+"cap branca."
+
+msgid "not setting upstream for a remote remote-tracking branch"
+msgstr ""
+"no s'està configurant la font per a una branca remota amb seguiment remot"
+
+msgid "not setting upstream for a remote tag"
+msgstr "no s'està configurant la font d'una etiqueta remota"
+
+msgid "unknown branch type"
+msgstr "tipus de branca desconegut"
+
+msgid ""
+"no source branch found;\n"
+"you need to specify exactly one branch with the --set-upstream option"
+msgstr ""
+"no s'ha trobat cap branca d'origen.\n"
+"heu d'especificar exactament una branca amb l'opció --set-upstream"
+
+#, c-format
+msgid "Fetching %s\n"
+msgstr "S'està obtenint %s\n"
+
+#, c-format
+msgid "could not fetch %s"
+msgstr "no s'ha pogut obtenir %s"
+
+#, c-format
+msgid "could not fetch '%s' (exit code: %d)\n"
+msgstr "no s'ha pogut obtenir «%s» (codi de sortida: %d)\n"
+
+msgid ""
+"no remote repository specified; please specify either a URL or a\n"
+"remote name from which new revisions should be fetched"
+msgstr ""
+"no s'ha especificat cap repositori remot. Especifiqueu un URL o\n"
+"un nom remot del qual s'han d'obtenir les revisions noves"
+
+msgid "you need to specify a tag name"
+msgstr "necessiteu especificar un nom d'etiqueta"
+
 msgid "fetch from all remotes"
 msgstr "obtén de tots els remots"
 
@@ -5888,178 +6086,6 @@
 msgid "accept refspecs from stdin"
 msgstr "llegeix les especificacions de referència des de stdin"
 
-msgid "couldn't find remote ref HEAD"
-msgstr "no s'ha pogut trobar la referència HEAD remota"
-
-#, c-format
-msgid "object %s not found"
-msgstr "objecte %s no trobat"
-
-msgid "[up to date]"
-msgstr "[al dia]"
-
-msgid "[rejected]"
-msgstr "[rebutjat]"
-
-msgid "can't fetch into checked-out branch"
-msgstr "no es pot obtenir en la branca actual"
-
-msgid "[tag update]"
-msgstr "[actualització d'etiqueta]"
-
-msgid "unable to update local ref"
-msgstr "no s'ha pogut actualitzar la referència local"
-
-msgid "would clobber existing tag"
-msgstr "s'adjuntaria l'etiqueta existent"
-
-msgid "[new tag]"
-msgstr "[etiqueta nova]"
-
-msgid "[new branch]"
-msgstr "[branca nova]"
-
-msgid "[new ref]"
-msgstr "[referència nova]"
-
-msgid "forced update"
-msgstr "actualització forçada"
-
-msgid "non-fast-forward"
-msgstr "sense avanç ràpid"
-
-#, c-format
-msgid "cannot open '%s'"
-msgstr "no es pot obrir «%s»"
-
-msgid ""
-"fetch normally indicates which branches had a forced update,\n"
-"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
-"flag or run 'git config fetch.showForcedUpdates true'"
-msgstr ""
-"en obtenir normalment indica quines branques tenien una actualització "
-"forçada,\n"
-"però aquesta comprovació s'ha desactivat. Per a tornar a habilitar-la, "
-"utilitzeu\n"
-"«--show-forced-updates» o executeu «git config fetch.showForcedUpdates true»"
-
-#, c-format
-msgid ""
-"it took %.2f seconds to check forced updates; you can use\n"
-"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
-"false'\n"
-"to avoid this check\n"
-msgstr ""
-"s'ha trigat %.2f segons a comprovar les actualitzacions forçades. Podeu\n"
-"utilitzar «--no-show-forced-updates» o executar «git config \n"
-"fetch.showForcedUpdates false» per a evitar aquesta comprovació.\n"
-
-#, c-format
-msgid "%s did not send all necessary objects\n"
-msgstr "%s no ha enviat tots els objectes necessaris\n"
-
-#, c-format
-msgid "rejected %s because shallow roots are not allowed to be updated"
-msgstr ""
-"s'ha rebutjat %s perquè no es permeten actualitzar les arrels superficials"
-
-#, c-format
-msgid "From %.*s\n"
-msgstr "De %.*s\n"
-
-#, c-format
-msgid ""
-"some local refs could not be updated; try running\n"
-" '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"
-" qualsevol branca antiga o conflictiva"
-
-#, c-format
-msgid "   (%s will become dangling)"
-msgstr "   (%s es tornarà penjant)"
-
-#, c-format
-msgid "   (%s has become dangling)"
-msgstr "   (%s s'ha tornat penjant)"
-
-msgid "[deleted]"
-msgstr "[suprimit]"
-
-msgid "(none)"
-msgstr "(cap)"
-
-#, c-format
-msgid "refusing to fetch into branch '%s' checked out at '%s'"
-msgstr "s'ha rebutjat l'obtenció en la branca «%s» agafada a «%s»"
-
-#, c-format
-msgid "option \"%s\" value \"%s\" is not valid for %s"
-msgstr "l'opció «%s» amb valor «%s» no és vàlida per a %s"
-
-#, c-format
-msgid "option \"%s\" is ignored for %s\n"
-msgstr "s'ignora l'opció «%s» per a %s\n"
-
-#, c-format
-msgid "%s is not a valid object"
-msgstr "%s no és un objecte vàlid"
-
-#, c-format
-msgid "the object %s does not exist"
-msgstr "l'objecte %s no existeix"
-
-msgid "multiple branches detected, incompatible with --set-upstream"
-msgstr "s'han detectat múltiples branques, incompatible amb --set-upstream"
-
-#, c-format
-msgid ""
-"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
-"any branch."
-msgstr ""
-"no s'ha pogut establir la font de HEAD a «%s» des de «%s» quan no assenyala "
-"cap branca."
-
-msgid "not setting upstream for a remote remote-tracking branch"
-msgstr ""
-"no s'està configurant la font per a una branca remota amb seguiment remot"
-
-msgid "not setting upstream for a remote tag"
-msgstr "no s'està configurant la font d'una etiqueta remota"
-
-msgid "unknown branch type"
-msgstr "tipus de branca desconegut"
-
-msgid ""
-"no source branch found;\n"
-"you need to specify exactly one branch with the --set-upstream option"
-msgstr ""
-"no s'ha trobat cap branca d'origen.\n"
-"heu d'especificar exactament una branca amb l'opció --set-upstream"
-
-#, c-format
-msgid "Fetching %s\n"
-msgstr "S'està obtenint %s\n"
-
-#, c-format
-msgid "could not fetch %s"
-msgstr "no s'ha pogut obtenir %s"
-
-#, c-format
-msgid "could not fetch '%s' (exit code: %d)\n"
-msgstr "no s'ha pogut obtenir «%s» (codi de sortida: %d)\n"
-
-msgid ""
-"no remote repository specified; please specify either a URL or a\n"
-"remote name from which new revisions should be fetched"
-msgstr ""
-"no s'ha especificat cap repositori remot. Especifiqueu un URL o\n"
-"un nom remot del qual s'han d'obtenir les revisions noves"
-
-msgid "you need to specify a tag name"
-msgstr "necessiteu especificar un nom d'etiqueta"
-
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr "--negotiate-only necessita un o més --negotiation-tip=*"
 
@@ -6176,6 +6202,12 @@
 msgid "print only refs which don't contain the commit"
 msgstr "imprimeix només les referències que no continguin la comissió"
 
+msgid "read reference patterns from stdin"
+msgstr "llegeix els patrons de referència de l'entrada estàndard"
+
+msgid "unknown arguments supplied with --stdin"
+msgstr "s'han proporcionat arguments desconeguts amb --stdin"
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<config> [--] <arguments>"
 
@@ -6188,6 +6220,10 @@
 msgid "missing --config=<config>"
 msgstr "falta --config=<config>"
 
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "s'ha obtingut una configuració incorrecta --config=%s"
+
 msgid "unknown"
 msgstr "desconegut"
 
@@ -6334,19 +6370,28 @@
 msgid "notice: %s points to an unborn branch (%s)"
 msgstr "avís: %s apunta a una branca no nascuda (%s)"
 
-msgid "Checking cache tree"
-msgstr "S'està comprovant l'arbre de la memòria cau"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "S'està comprovant l'arbre de la memòria cau %s"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "%s: apuntador sha1 no vàlid a l'arbre de la memòria cau"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s: punter sha1 no vàlid a l'arbre de la memòria cau %s"
 
 msgid "non-tree in cache-tree"
 msgstr "un no arbre en l'arbre de la memòria cau"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in resolve-undo"
-msgstr "%s: el punter sha1 no és vàlid a «resolve-undo»"
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s: punter sha1 no vàlid a «resolve-undo» de %s"
+
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "no s'ha pogut carregar l'índex de reversió per al paquet «%s»"
+
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "rev-index no vàlid per al paquet «%s»"
 
 msgid ""
 "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
@@ -6768,7 +6813,6 @@
 #. TRANSLATORS: %s is the configuration
 #. variable for tweaking threads, currently
 #. grep.threads
-#.
 #, c-format
 msgid "no threads support, ignoring %s"
 msgstr "no s'admeten fils, s'ignorarà %s"
@@ -8851,7 +8895,6 @@
 
 #. TRANSLATORS: the first %s will be replaced by a git
 #. notes command: 'add', 'merge', 'remove', etc.
-#.
 #, c-format
 msgid "refusing to %s notes in %s (outside of refs/notes/)"
 msgstr "s'està refusant %s les notes en %s (fora de refs/notes/)"
@@ -9236,6 +9279,12 @@
 msgid "bad index version '%s'"
 msgstr "versió d'índex incorrecta «%s»"
 
+msgid "show progress meter during object writing phase"
+msgstr "mostra l'indicador de progrés durant la fase d'escriptura d'objectes"
+
+msgid "similar to --all-progress when progress meter is shown"
+msgstr "similar a --all-progress quan l'indicador de progrés es mostra"
+
 msgid "<version>[,<offset>]"
 msgstr "<versió>[,<desplaçament>]"
 
@@ -9435,6 +9484,9 @@
 "i feu-nos saber que encara l'useu enviant un correu electrònic\n"
 "a <git@vger.kernel.org>.  Gràcies.\n"
 
+msgid "refusing to run without --i-still-use-this"
+msgstr "es rebutja a executar sense --i-still-use-this"
+
 msgid "git pack-refs [--all] [--no-prune]"
 msgstr "git pack-refs [--all] [--no-prune]"
 
@@ -9609,8 +9661,8 @@
 msgid "pull with rebase"
 msgstr "baixar fent «rebase»"
 
-msgid "please commit or stash them."
-msgstr "cometeu-los o emmagatzemeu-los."
+msgid "Please commit or stash them."
+msgstr "Cometeu-los o emmagatzemeu-los."
 
 #, c-format
 msgid ""
@@ -9854,7 +9906,7 @@
 msgid "repository"
 msgstr "repositori"
 
-msgid "push all refs"
+msgid "push all branches"
 msgstr "puja totes les referències"
 
 msgid "mirror all refs"
@@ -9863,8 +9915,8 @@
 msgid "delete refs"
 msgstr "suprimeix les referències"
 
-msgid "push tags (can't be used with --all or --mirror)"
-msgstr "puja les etiquetes (no es pot usar amb --all o --mirror)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr "puja les etiquetes (no es pot usar amb --all, --branches o --mirror)"
 
 msgid "force updates"
 msgstr "força les actualitzacions"
@@ -10130,6 +10182,10 @@
 "Com a resultat, git no pot fer un «rebase» d'elles."
 
 #, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "Mode de fusió de rebase desconegut: %s"
+
+#, c-format
 msgid "could not switch to %s"
 msgstr "no s'ha pogut commutar a %s"
 
@@ -10143,6 +10199,15 @@
 msgstr ""
 "tipus buit no reconegut «%s»; els valors vàlids són «drop», «keep» i «ask»."
 
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"--rebase-merges amb un argument de cadena buit està obsolet i deixarà de "
+"funcionar en una versió futura del Git. Utilitzeu --rebase-merges sense un "
+"argument, que fa el mateix."
+
 #, c-format
 msgid ""
 "%s\n"
@@ -10357,21 +10422,24 @@
 msgid "switch `C' expects a numerical value"
 msgstr "«switch» «c» espera un valor numèric"
 
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "Mode desconegut: %s"
-
 msgid "--strategy requires --merge or --interactive"
 msgstr "--strategy requereix --merge o --interactive"
 
 msgid ""
-"apply options are incompatible with rebase.autosquash.  Consider adding --no-"
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
 "autosquash"
 msgstr ""
-"les opcions «apply» són incompatibles amb rebase.autosquash. Considereu "
+"les opcions «apply» són incompatibles amb rebase.autoSquash. Considereu "
 "afegir-hi --no-autosquash"
 
 msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr ""
+"les opcions «apply» són incompatibles amb rebase.rebaseMerges. Considereu "
+"afegir-hi --no-rebase-merges"
+
+msgid ""
 "apply options are incompatible with rebase.updateRefs.  Consider adding --no-"
 "update-refs"
 msgstr ""
@@ -10415,9 +10483,6 @@
 msgid "Does not point to a valid commit '%s'"
 msgstr "No apunta a una comissió vàlida «%s»"
 
-msgid "Please commit or stash them."
-msgstr "Cometeu-los o emmagatzemeu-los."
-
 msgid "HEAD is up to date."
 msgstr "HEAD està al dia."
 
@@ -10884,7 +10949,6 @@
 #. TRANSLATORS: the colon ':' should align
 #. with the one in " Fetch URL: %s"
 #. translation.
-#.
 #, c-format
 msgid "  Push  URL: %s"
 msgstr "  URL de pujada: %s"
@@ -11091,8 +11155,8 @@
 msgid "approxidate"
 msgstr "data aproximada"
 
-msgid "with -C, expire objects older than this"
-msgstr "amb -C, venç els objectes més antics que aquest"
+msgid "with --cruft, expire objects older than this"
+msgstr "amb --cruft, vencen els objectes més antics que aquest"
 
 msgid "remove redundant packs, and run git-prune-packed"
 msgstr "elimina els paquets redundants, i executeu git-prune-packed"
@@ -11764,6 +11828,9 @@
 msgid "remote name"
 msgstr "nom del remot"
 
+msgid "push all refs"
+msgstr "puja totes les referències"
+
 msgid "use stateless RPC protocol"
 msgstr "usa el protocol RPC sense estat"
 
@@ -11968,9 +12035,11 @@
 msgstr "mostra les referències de stdin que no siguin en el repositori local"
 
 msgid ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<opcions>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<opcions>]"
 
 msgid "this worktree is not sparse"
 msgstr "aquest arbre de treball no és dispers"
@@ -12094,6 +12163,24 @@
 msgid "error while refreshing working directory"
 msgstr "s'ha produït un error en actualitzar el directori de treball"
 
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <fitxer>]"
+
+msgid "terminate input and output files by a NUL character"
+msgstr "acaba els fitxers d'entrada i de sortida amb un caràcter NUL"
+
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr ""
+"quan s'utilitza amb --rules-file, interpreta els patrons com a patrons del "
+"mode con"
+
+msgid "use patterns in <file> instead of the current ones."
+msgstr "utilitza patrons en <file> en lloc dels actuals."
+
 msgid "git stash list [<log-options>]"
 msgstr "git stash list [<log-options>]"
 
@@ -14994,8 +15081,8 @@
 msgid "bad zlib compression level %d"
 msgstr "nivell de compressió de zlib incorrecte %d"
 
-msgid "core.commentChar should only be one character"
-msgstr "core.commentChar només hauria de ser un caràcter"
+msgid "core.commentChar should only be one ASCII character"
+msgstr "core.commentChar només hauria de ser un caràcter ASCII"
 
 #, c-format
 msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15108,6 +15195,11 @@
 msgstr "nom de secció no vàlida: %s"
 
 #, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr ""
+"es rebutja treballar amb una línia massa llarga a «%s» a la línia %<PRIuMAX>"
+
+#, c-format
 msgid "missing value for '%s'"
 msgstr "falta el valor per «%s»"
 
@@ -15790,6 +15882,9 @@
 msgid "do not show any source or destination prefix"
 msgstr "no mostris cap prefix d'origen o destí"
 
+msgid "use default prefixes a/ and b/"
+msgstr "utilitza els prefixos per defecte a/ i b/"
+
 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 "
@@ -16101,6 +16196,14 @@
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "consell: s'està esperant que el vostre editor tanqui el fitxer...%c"
 
+#, c-format
+msgid "could not write to '%s'"
+msgstr "no s'ha pogut escriure a «%s»"
+
+#, c-format
+msgid "could not edit '%s'"
+msgstr "no s'ha pogut editar «%s»"
+
 msgid "Filtering content"
 msgstr "S'està filtrant el contingut"
 
@@ -16268,14 +16371,12 @@
 
 #. TRANSLATORS: The parameter will be 'ready', a protocol
 #. keyword.
-#.
 #, c-format
 msgid "expected packfile to be sent after '%s'"
 msgstr "s'esperava que el fitxer de paquet s'enviés després de «%s»"
 
 #. TRANSLATORS: The parameter will be 'ready', a protocol
 #. keyword.
-#.
 #, c-format
 msgid "expected no other sections to be sent after no '%s'"
 msgstr "no s'esperava que cap altra secció s'enviés després de «%s»"
@@ -16399,6 +16500,10 @@
 msgstr "no s'ha indicat cap clau de configuració per a --config-env\n"
 
 #, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "no s'ha donat d'atribut font per a --attr-source\n"
+
+#, c-format
 msgid "unknown option: %s\n"
 msgstr "opció desconeguda: %s\n"
 
@@ -17089,7 +17194,6 @@
 #. name, and the second argument is the abbreviated id of the
 #. commit that needs to be merged.  For example:
 #.  - go to submodule (mysubmodule), and either merge commit abc1234"
-#.
 #, c-format
 msgid ""
 " - go to submodule (%s), and either merge commit %s\n"
@@ -17124,7 +17228,6 @@
 
 #. TRANSLATORS: The %s arguments are: 1) tree hash of a merge
 #. base, and 2-3) the trees for the two trees we're merging.
-#.
 #, c-format
 msgid "collecting merge info failed for trees %s, %s, %s"
 msgstr ""
@@ -17598,7 +17701,6 @@
 #. TRANSLATORS: The first %s is the name of
 #. the environment variable, the second %s is
 #. its value.
-#.
 #, c-format
 msgid "Bad %s value: '%s'"
 msgstr "Valor erroni de %s: «%s»"
@@ -17768,7 +17870,7 @@
 msgstr "l'objecte ha fallat fsck: %s"
 
 msgid "refusing to create malformed object"
-msgstr "es nega a crear un objecte mal format"
+msgstr "es rebutja crear un objecte mal format"
 
 #, c-format
 msgid "read error while indexing %s"
@@ -17817,7 +17919,6 @@
 #. TRANSLATORS: This is a line of ambiguous object
 #. output shown when we cannot look up or parse the
 #. object in question. E.g. "deadbeef [bad object]".
-#.
 #, c-format
 msgid "%s [bad object]"
 msgstr "%s [objecte incorrecte]"
@@ -17826,7 +17927,6 @@
 #. object output. E.g.:
 #. *
 #.    "deadbeef commit 2021-01-01 - Some Commit Message"
-#.
 #, c-format
 msgid "%s commit %s - %s"
 msgstr "%s comissió %s - %s"
@@ -17841,7 +17941,6 @@
 #. *
 #. The third argument is the "tag" string
 #. from object.c.
-#.
 #, c-format
 msgid "%s tag %s - %s"
 msgstr "%s etiqueta %s - %s"
@@ -17851,21 +17950,18 @@
 #. the tag itself. E.g.:
 #. *
 #.    "deadbeef [bad tag, could not parse it]"
-#.
 #, c-format
 msgid "%s [bad tag, could not parse it]"
 msgstr "%s [etiqueta malmesa, no s'ha pogut analitzar]"
 
 #. TRANSLATORS: This is a line of ambiguous <type>
 #. object output. E.g. "deadbeef tree".
-#.
 #, c-format
 msgid "%s tree"
 msgstr "arbre %s"
 
 #. TRANSLATORS: This is a line of ambiguous <type>
 #. object output. E.g. "deadbeef blob".
-#.
 #, c-format
 msgid "%s blob"
 msgstr "blob %s"
@@ -17877,7 +17973,6 @@
 #. TRANSLATORS: The argument is the list of ambiguous
 #. objects composed in show_ambiguous_object(). See
 #. its "TRANSLATORS" comments for details.
-#.
 #, c-format
 msgid ""
 "The candidates are:\n"
@@ -18110,6 +18205,10 @@
 msgstr "no s'ha pogut obtenir l'ús del disc de «%s»"
 
 #, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "el fitxer de mapa de bits «%s» té una suma de verificació no vàlida"
+
+#, c-format
 msgid "mtimes file %s is too small"
 msgstr "el fitxer mtimes %s és massa petit"
 
@@ -18149,6 +18248,14 @@
 msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
 msgstr "el fitxer d'índex invers %s té un ID de resum %<PRIu32> no admès"
 
+msgid "invalid checksum"
+msgstr "suma de verificació no vàlida"
+
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr ""
+"posició no vàlida de l'índex de reversió a %<PRIu64>: %<PRIu32> != %<PRIu32>"
+
 msgid "cannot both write and verify reverse index"
 msgstr "no es pot escriure i verificar l'índex invers"
 
@@ -18257,7 +18364,6 @@
 
 #. TRANSLATORS: the colon here should align with the
 #. one in "usage: %s" translation.
-#.
 #, c-format
 msgid "   or: %s"
 msgstr "   o: %s"
@@ -18280,7 +18386,6 @@
 #. function. The "%s" is a line in the (hopefully already
 #. translated) N_() usage string, which contained embedded
 #. newlines before we split it up.
-#.
 #, c-format
 msgid "%*s%s"
 msgstr "%*s%s"
@@ -18879,6 +18984,10 @@
 msgstr "amplada positiva esperada amb l'àtom %%(align)"
 
 #, c-format
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "format esperat: %%(ahead-behind:<committish>)"
+
+#, c-format
 msgid "malformed field name: %.*s"
 msgstr "nom de camp mal format: %.*s"
 
@@ -19262,7 +19371,6 @@
 #. TRANSLATORS: "matches '%s'%" is the <dst> part of "git push
 #. <remote> <src>:<dst>" push, and "being pushed ('%s')" is
 #. the <src>.
-#.
 #, c-format
 msgid ""
 "The destination you provided is not a full refname (i.e.,\n"
@@ -19513,10 +19621,6 @@
 msgstr "no hi ha cap resolució recordada per a «%s»"
 
 #, c-format
-msgid "cannot unlink '%s'"
-msgstr "no es pot fer «unlink» de «%s»"
-
-#, c-format
 msgid "Updated preimage for '%s'"
 msgstr "Imatge prèvia actualitzada per a «%s»"
 
@@ -19855,10 +19959,6 @@
 msgstr "no s'ha pogut bloquejar «%s»"
 
 #, c-format
-msgid "could not write to '%s'"
-msgstr "no s'ha pogut escriure a «%s»"
-
-#, c-format
 msgid "could not write eol to '%s'"
 msgstr "no s'ha pogut escriure el terminador de línia a «%s»"
 
@@ -19875,7 +19975,6 @@
 
 #. TRANSLATORS: %s will be "revert", "cherry-pick" or
 #. "rebase".
-#.
 #, c-format
 msgid "%s: Unable to write new index file"
 msgstr "%s: No s'ha pogut escriure un fitxer d'índex nou"
@@ -20221,9 +20320,6 @@
 msgid "could not create sequencer directory '%s'"
 msgstr "no s'ha pogut crear el directori de seqüenciador «%s»"
 
-msgid "could not lock HEAD"
-msgstr "no s'ha pogut bloquejar HEAD"
-
 msgid "no cherry-pick or revert in progress"
 msgstr "ni hi ha cap «cherry pick» ni cap reversió en curs"
 
@@ -20318,13 +20414,13 @@
 " git rebase --continue\n"
 "\n"
 
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "i ha fet canvis a l'índex i/o l'arbre de treball\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "i ha fet canvis a l'índex i/o a l'arbre de treball.\n"
 
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
@@ -20334,7 +20430,8 @@
 "però ha deixat canvis a l'índex i/o l'arbre de treball\n"
 "Cometeu o feu «stash» dels vostres canvis, i llavors executeu\n"
 "\n"
-" git rebase --continue\n"
+"  git rebase --continue\n"
+"\n"
 
 #, c-format
 msgid "illegal label name: '%.*s'"
@@ -20772,10 +20869,6 @@
 msgstr[1] "%u bytes/s"
 
 #, c-format
-msgid "could not edit '%s'"
-msgstr "no s'ha pogut editar «%s»"
-
-#, c-format
 msgid "ignoring suspicious submodule name: %s"
 msgstr "s'està ignorant el nom de submòdul sospitós %s"
 
@@ -22512,13 +22605,17 @@
 msgstr "(%s) no s'ha pogut executar «%s»"
 
 #, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) S'està afegint %s: %s des de: «%s»\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) Sortida mal formada de «%s»"
 
 #, perl-format
 msgid "(%s) failed to close pipe to '%s'"
 msgstr "(%s) s'ha produït un error en tancar el conducte «%s»"
 
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) S'està afegint %s: %s des de: «%s»\n"
+
 msgid "cannot send message as 7bit"
 msgstr "no es pot enviar el missatge en 7 bits"
 
@@ -22555,367 +22652,3 @@
 #, perl-format
 msgid "Do you really want to send %s? [y|N]: "
 msgstr "Esteu segur que voleu enviar %s? [y|N]: "
-
-#~ msgid "git bisect--helper --bisect-state (bad|new) [<rev>]"
-#~ msgstr "git bisect--helper --bisect-state (bad|new) [<rev>]"
-
-#~ msgid "won't bisect on cg-seek'ed tree"
-#~ msgstr "no es bisecarà en un arbre en el qual s'ha fet cg-seek"
-
-#~ msgid "--bisect-terms requires 0 or 1 argument"
-#~ msgstr "--bisect-terms requereix 0 o 1 argument"
-
-#~ msgid "--bisect-next requires 0 arguments"
-#~ msgstr "--bisect-next no requereix cap argument"
-
-#~ msgid "--bisect-log requires 0 arguments"
-#~ msgstr "--bisect-log no requereix cap argument"
-
-#~ msgid "git env--helper --type=[bool|ulong] <options> <env-var>"
-#~ msgstr "git env--helper --type=[bool|ulong] <opcions> <env-var>"
-
-#~ msgid "default for git_env_*(...) to fall back on"
-#~ msgstr "valor per defecte per a git_env_*(...) en cas d'absència"
-
-#~ msgid "be quiet only use git_env_*() value as exit code"
-#~ msgstr "silenciós només utilitza el valor git_env_*() com a codi de sortida"
-
-#, c-format
-#~ msgid ""
-#~ "option `--default' expects a boolean value with `--type=bool`, not `%s`"
-#~ msgstr ""
-#~ "l'opció «--default» espera un valor booleà amb «--type=bool», no «%s»"
-
-#, c-format
-#~ msgid ""
-#~ "option `--default' expects an unsigned long value with `--type=ulong`, "
-#~ "not `%s`"
-#~ msgstr ""
-#~ "l'opció «--default» espera un valor llarg sense signe amb «--type=ulong», "
-#~ "no «%s»"
-
-#, c-format
-#~ msgid "%s doesn't support --super-prefix"
-#~ msgstr "%s no admet --super-prefix"
-
-#, c-format
-#~ msgid "no prefix given for --super-prefix\n"
-#~ msgstr "no s'ha especificat cap prefix per a --super-prefix\n"
-
-#, c-format
-#~ msgid "failed to read object %s"
-#~ msgstr "s'ha produït un error en llegir l'objecte %s"
-
-#~ msgid "file write error"
-#~ msgstr "s'ha produït un error en escriure al fitxer"
-
-#~ msgid "corrupt commit"
-#~ msgstr "comissió corrupta"
-
-#~ msgid "corrupt tag"
-#~ msgstr "etiqueta corrupta"
-
-#, c-format
-#~ msgid "%%(objecttype) does not take arguments"
-#~ msgstr "%%(objecttype) no accepta arguments"
-
-#, c-format
-#~ msgid "%%(deltabase) does not take arguments"
-#~ msgstr "%%(deltabase) no accepta arguments"
-
-#, c-format
-#~ msgid "%%(body) does not take arguments"
-#~ msgstr "%%(body) no accepta arguments"
-
-#, c-format
-#~ msgid "unrecognized email option: %s"
-#~ msgstr "opció del correu electrònic no reconeguda: «%s»"
-
-#, c-format
-#~ msgid ""
-#~ "It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
-#~ "may speed it up, but you have to be careful not to forget to add\n"
-#~ "new files yourself (see 'git help status')."
-#~ msgstr ""
-#~ "S'ha trigat %.2f segons enumerar els fitxers no seguits.\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»)."
-
-#, perl-format
-#~ msgid "%12s %12s %s"
-#~ msgstr "%12s %12s %s"
-
-#, perl-format
-#~ msgid "touched %d path\n"
-#~ msgid_plural "touched %d paths\n"
-#~ msgstr[0] "modificat %d camí\n"
-#~ msgstr[1] "modificat %d camins\n"
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for staging."
-#~ msgstr ""
-#~ "Si el pedaç s'aplica correctament, el tros editat es marcarà "
-#~ "immediatament\n"
-#~ "per «staging»."
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for stashing."
-#~ msgstr ""
-#~ "Si el pedaç s'aplica correctament, el tros editat es marcarà "
-#~ "immediatament\n"
-#~ "per «stashing»."
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for unstaging."
-#~ msgstr ""
-#~ "Si el pedaç s'aplica correctament, el tros editat es marcarà "
-#~ "immediatament\n"
-#~ "per «unstaging»."
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for applying."
-#~ msgstr ""
-#~ "Si el pedaç s'aplica correctament, el tros editat es marcarà "
-#~ "immediatament\n"
-#~ "per a aplicar-se."
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for discarding."
-#~ msgstr ""
-#~ "Si el pedaç s'aplica correctament, el tros editat es marcarà "
-#~ "immediatament\n"
-#~ "per a descartar-se."
-
-#, perl-format
-#~ msgid "failed to open hunk edit file for writing: %s"
-#~ msgstr "s'ha produït un error en escriure al fitxer d'edició del tros: %s"
-
-#, perl-format
-#~ msgid ""
-#~ "---\n"
-#~ "To remove '%s' lines, make them ' ' lines (context).\n"
-#~ "To remove '%s' lines, delete them.\n"
-#~ "Lines starting with %s will be removed.\n"
-#~ msgstr ""
-#~ "---\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"
-
-#, perl-format
-#~ msgid "failed to open hunk edit file for reading: %s"
-#~ msgstr "s'ha produït un error en llegir al fitxer d'edició del tros: %s"
-
-#~ msgid ""
-#~ "y - stage this hunk\n"
-#~ "n - do not stage this hunk\n"
-#~ "q - quit; do not stage this hunk or any of the remaining ones\n"
-#~ "a - stage this hunk and all later hunks in the file\n"
-#~ "d - do not stage this hunk or any of the later hunks in the file"
-#~ 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"
-
-#~ msgid ""
-#~ "y - stash this hunk\n"
-#~ "n - do not stash this hunk\n"
-#~ "q - quit; do not stash this hunk or any of the remaining ones\n"
-#~ "a - stash this hunk and all later hunks in the file\n"
-#~ "d - do not stash this hunk or any of the later hunks in the file"
-#~ 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"
-
-#~ msgid ""
-#~ "y - unstage this hunk\n"
-#~ "n - do not unstage this hunk\n"
-#~ "q - quit; do not unstage this hunk or any of the remaining ones\n"
-#~ "a - unstage this hunk and all later hunks in the file\n"
-#~ "d - do not unstage this hunk or any of the later hunks in the file"
-#~ 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"
-
-#~ msgid ""
-#~ "y - apply this hunk to index\n"
-#~ "n - do not apply this hunk to index\n"
-#~ "q - quit; do not apply this hunk or any of the remaining ones\n"
-#~ "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"
-#~ msgstr ""
-#~ "y - aplica aquest tros a l'índex\n"
-#~ "n - no apliquis aquest tros a l'índex\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"
-
-#~ msgid ""
-#~ "y - discard this hunk from worktree\n"
-#~ "n - do not discard this hunk from worktree\n"
-#~ "q - quit; do not discard this hunk or any of the remaining ones\n"
-#~ "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"
-#~ msgstr ""
-#~ "y - descarta aquest tros de l'arbre de treball\n"
-#~ "n - no descartis aquest tros des de l'arbre de treball\n"
-#~ "q - surt; no descartis 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"
-
-#~ msgid ""
-#~ "y - discard this hunk from index and worktree\n"
-#~ "n - do not discard this hunk from index and worktree\n"
-#~ "q - quit; do not discard this hunk or any of the remaining ones\n"
-#~ "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"
-#~ msgstr ""
-#~ "y - descarta aquest tros de l'índex i de l'arbre de treball\n"
-#~ "n - no descartis aquest tros des de l'índex i de l'arbre de treball\n"
-#~ "q - surt; no descartis 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"
-
-#~ msgid ""
-#~ "y - apply this hunk to index and worktree\n"
-#~ "n - do not apply this hunk to index and worktree\n"
-#~ "q - quit; do not apply this hunk or any of the remaining ones\n"
-#~ "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"
-#~ 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"
-#~ "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"
-
-#~ msgid ""
-#~ "y - apply this hunk to worktree\n"
-#~ "n - do not apply this hunk to worktree\n"
-#~ "q - quit; do not apply this hunk or any of the remaining ones\n"
-#~ "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"
-#~ msgstr ""
-#~ "y - aplica aquest tros a l'arbre de treball\n"
-#~ "n - no apliquis aquest tros 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"
-
-#~ msgid ""
-#~ "g - select a hunk to go to\n"
-#~ "/ - search for a hunk matching the given regex\n"
-#~ "j - leave this hunk undecided, see next undecided hunk\n"
-#~ "J - leave this hunk undecided, see next hunk\n"
-#~ "k - leave this hunk undecided, see previous undecided hunk\n"
-#~ "K - leave this hunk undecided, see previous hunk\n"
-#~ "s - split the current hunk into smaller hunks\n"
-#~ "e - manually edit the current hunk\n"
-#~ "? - print help\n"
-#~ msgstr ""
-#~ "g - selecciona el tros on voleu anar\n"
-#~ "/ - cerca un tros que coincideixi amb l'expressió regular donada\n"
-#~ "j - deixa aquest tros sense decidir, veure el tros sense decidir següent\n"
-#~ "J - deixa aquest tros sense decidir, veure el tros següent\n"
-#~ "k - deixa aquest tros sense decidir, veure el tros sense decidir "
-#~ "anterior\n"
-#~ "K - deixa aquest tros sense decidir, veure el tros anterior\n"
-#~ "s - divideix el tros actual en trossos més petits\n"
-#~ "e - edita manualment el tros actual\n"
-#~ "? - mostra l'ajuda\n"
-
-#~ msgid "The selected hunks do not apply to the index!\n"
-#~ msgstr "Els trossos seleccionats no apliquen a l'índex\n"
-
-#, perl-format
-#~ msgid "ignoring unmerged: %s\n"
-#~ msgstr "s'està ignorant %s no fusionat\n"
-
-#~ msgid "No other hunks to goto\n"
-#~ msgstr "No hi ha altres trossos on anar-hi\n"
-
-#, perl-format
-#~ msgid "Invalid number: '%s'\n"
-#~ msgstr "Número no vàlid: «%s»\n"
-
-#, perl-format
-#~ msgid "Sorry, only %d hunk available.\n"
-#~ msgid_plural "Sorry, only %d hunks available.\n"
-#~ msgstr[0] "Només %d tros disponible.\n"
-#~ msgstr[1] "Només %d trossos disponibles.\n"
-
-#~ msgid "No other hunks to search\n"
-#~ msgstr "No hi ha cap altre tros a cercar\n"
-
-#, perl-format
-#~ msgid "Malformed search regexp %s: %s\n"
-#~ msgstr "Expressió regular de cerca mal formada %s: %s\n"
-
-#~ msgid "No hunk matches the given pattern\n"
-#~ msgstr "No hi ha trossos que coincideixin amb el patró donat\n"
-
-#~ msgid "No previous hunk\n"
-#~ msgstr "Sense tros previ\n"
-
-#~ msgid "No next hunk\n"
-#~ msgstr "No hi ha tros següent\n"
-
-#~ msgid "Sorry, cannot split this hunk\n"
-#~ msgstr "No es pot dividir aquest tros\n"
-
-#, perl-format
-#~ msgid "Split into %d hunk.\n"
-#~ msgid_plural "Split into %d hunks.\n"
-#~ msgstr[0] "Divideix en %d tros.\n"
-#~ msgstr[1] "Divideix en %d trossos.\n"
-
-#~ msgid "Sorry, cannot edit this hunk\n"
-#~ msgstr "No es pot editar aquest tros\n"
-
-#~ msgid ""
-#~ "status        - show paths with changes\n"
-#~ "update        - add working tree state to the staged set of changes\n"
-#~ "revert        - revert staged set of changes back to the HEAD version\n"
-#~ "patch         - pick hunks and update selectively\n"
-#~ "diff          - view diff between HEAD and index\n"
-#~ "add untracked - add contents of untracked files to the staged set of "
-#~ "changes\n"
-#~ msgstr ""
-#~ "status        - mostra els camins amb canvis\n"
-#~ "update        - afegeix l'estat de l'arbre de treball al conjunt de "
-#~ "canvis «staged»\n"
-#~ "revert        - reverteix el conjunt de canvis de «staged» a la versió "
-#~ "HEAD\n"
-#~ "patch         - selecciona trossos i actualitza'ls selectivament\n"
-#~ "diff          - mostra la diferència entre HEAD i l'índex\n"
-#~ "add untracked - afegeix el contingut dels fitxers no seguits al conjunt "
-#~ "de canvis «staged»\n"
-
-#~ msgid "missing --"
-#~ msgstr "manca --"
-
-#, perl-format
-#~ msgid "unknown --patch mode: %s"
-#~ msgstr "desconegut --patch mode: %s"
-
-#, perl-format
-#~ msgid "invalid argument %s, expecting --"
-#~ msgstr "argument %s no vàlid, s'esperava --"
-
-#, c-format
-#~ msgid "unable to normalize object directory: %s"
-#~ msgstr "no s'ha pogut normalitzar el directori de l'objecte: %s"
diff --git a/po/de.po b/po/de.po
index 7559a8c..2ef0dc7 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: 2023-03-03 17:13+0100\n"
-"PO-Revision-Date: 2023-03-03 13:46+0100\n"
+"POT-Creation-Date: 2023-05-22 17:14+0200\n"
+"PO-Revision-Date: 2023-05-22 17:16+0200\n"
 "Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n"
 "Language-Team: German\n"
 "Language: de\n"
@@ -17,7 +17,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 3.2.2\n"
+"X-Generator: Poedit 3.3.1\n"
 
 #, c-format
 msgid "Huh (%s)?"
@@ -688,6 +688,24 @@
 msgid "Exiting because of unfinished merge."
 msgstr "Beende wegen nicht abgeschlossenem Merge."
 
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"Abweichende Branches können nicht vorgespult werden, benutzen Sie "
+"stattdessen:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"oder:\n"
+"\n"
+"\tgit rebase\n"
+
 msgid "Not possible to fast-forward, aborting."
 msgstr "Vorspulen nicht möglich, breche ab."
 
@@ -1144,6 +1162,10 @@
 msgstr "kann '%s' nicht öffnen"
 
 #, c-format
+msgid "cannot unlink '%s'"
+msgstr "Kann '%s' nicht löschen."
+
+#, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "Patch-Bereich #%d sauber angewendet."
 
@@ -1341,6 +1363,11 @@
 msgstr "kann '%s' nicht lesen"
 
 #, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr ""
+"Pfadspezifikation '%s' findet Dateien außerhalb des aktuellen Verzeichnisses"
+
+#, c-format
 msgid "pathspec '%s' did not match any files"
 msgstr "Pfadspezifikation '%s' stimmt mit keinen Dateien überein"
 
@@ -1356,9 +1383,6 @@
 msgid "not a tree object: %s"
 msgstr "Kein Tree-Objekt: %s"
 
-msgid "current working directory is untracked"
-msgstr "aktuelles Arbeitsverzeichnis ist unversioniert"
-
 #, c-format
 msgid "File not found: %s"
 msgstr "Datei nicht gefunden: %s"
@@ -1485,6 +1509,9 @@
 msgid "ignoring overly large gitattributes blob '%s'"
 msgstr "ignoriere übermäßig großen gitattribute-Blob '%s'"
 
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr "ungültiges --attr-source oder GIT_ATTR_SOURCE"
+
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
 msgstr "Ungültiger Inhalt bzgl. Anführungszeichen in Datei '%s': %s"
@@ -1591,10 +1618,6 @@
 msgid "--contents and --reverse do not blend well."
 msgstr "--contents und --reverse funktionieren gemeinsam nicht."
 
-msgid "cannot use --contents with final commit object name"
-msgstr ""
-"kann --contents nicht mit endgültigem Namen des Commit-Objektes benutzen"
-
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr ""
 "--reverse und --first-parent zusammen erfordern die Angabe eines "
@@ -1782,10 +1805,6 @@
 msgid "'%s' is already checked out at '%s'"
 msgstr "'%s' ist bereits in '%s' ausgecheckt"
 
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "HEAD des Arbeitsverzeichnisses %s ist nicht aktualisiert"
-
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<Optionen>] [--] <Pfadspezifikation>..."
 
@@ -2849,6 +2868,14 @@
 msgstr "Remote-Tracking-Branch '%s' nicht gefunden"
 
 #, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"Branch '%s' nicht gefunden.\n"
+"Haben Sie --remote vergessen?"
+
+#, c-format
 msgid "branch '%s' not found."
 msgstr "Branch '%s' nicht gefunden."
 
@@ -2879,6 +2906,10 @@
 msgstr "Binäre Suche von Branch %s zu %s im Gange"
 
 #, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "HEAD des Arbeitsverzeichnisses %s ist nicht aktualisiert"
+
+#, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "Ungültiger Branchname: '%s'"
 
@@ -2983,6 +3014,9 @@
 msgstr ""
 "einen Branch verschieben/umbenennen, auch wenn das Ziel bereits existiert"
 
+msgid "do not output a newline after empty formatted refs"
+msgstr "keinen Zeilenumbruch nach leer formatierten Referenzen ausgeben"
+
 msgid "copy a branch and its reflog"
 msgstr "einen Branch und dessen Reflog kopieren"
 
@@ -3212,12 +3246,10 @@
 msgstr "Neuer Bericht unter '%s' erstellt.\n"
 
 msgid ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<Version>] <Datei> <git-rev-list-Argumente>"
 
 msgid "git bundle verify [-q | --quiet] <file>"
@@ -3238,11 +3270,11 @@
 msgid "show progress meter"
 msgstr "Fortschrittsanzeige anzeigen"
 
-msgid "show progress meter during object writing phase"
-msgstr "Forschrittsanzeige während des Schreibens von Objekten anzeigen"
+msgid "historical; same as --progress"
+msgstr "historisch; dasselbe wie --progress"
 
-msgid "similar to --all-progress when progress meter is shown"
-msgstr "ähnlich zu --all-progress wenn Fortschrittsanzeige darstellt wird"
+msgid "historical; does nothing"
+msgstr "historisch; kein Effekt"
 
 msgid "specify bundle format version"
 msgstr "Version des Paket-Formats angeben"
@@ -4275,6 +4307,11 @@
 msgstr "%s existiert und ist kein Verzeichnis"
 
 #, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr ""
+"'%s' ist eine symbolische Verknüpfung, verweigere das Klonen mit --local"
+
+#, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "Fehler beim Starten der Iteration über '%s'"
 
@@ -5828,6 +5865,178 @@
 msgid "fetch.parallel cannot be negative"
 msgstr "fetch.parallel kann nicht negativ sein"
 
+msgid "couldn't find remote ref HEAD"
+msgstr "konnte Remote-Referenz von HEAD nicht finden"
+
+#, c-format
+msgid "From %.*s\n"
+msgstr "Von %.*s\n"
+
+#, c-format
+msgid "object %s not found"
+msgstr "Objekt %s nicht gefunden"
+
+msgid "[up to date]"
+msgstr "[aktuell]"
+
+msgid "[rejected]"
+msgstr "[zurückgewiesen]"
+
+msgid "can't fetch into checked-out branch"
+msgstr "fetch kann in den ausgecheckten Branch nicht durchgeführt werden"
+
+msgid "[tag update]"
+msgstr "[Tag Aktualisierung]"
+
+msgid "unable to update local ref"
+msgstr "kann lokale Referenz nicht aktualisieren"
+
+msgid "would clobber existing tag"
+msgstr "würde bestehende Tags verändern"
+
+msgid "[new tag]"
+msgstr "[neues Tag]"
+
+msgid "[new branch]"
+msgstr "[neuer Branch]"
+
+msgid "[new ref]"
+msgstr "[neue Referenz]"
+
+msgid "forced update"
+msgstr "Aktualisierung erzwungen"
+
+msgid "non-fast-forward"
+msgstr "kein Vorspulen"
+
+#, c-format
+msgid "cannot open '%s'"
+msgstr "kann '%s' nicht öffnen"
+
+msgid ""
+"fetch normally indicates which branches had a forced update,\n"
+"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
+"flag or run 'git config fetch.showForcedUpdates true'"
+msgstr ""
+"Normalerweise zeigt 'fetch' welche Branches eine erzwungene Aktualisierung\n"
+"hatten, aber diese Überprüfung wurde deaktiviert. Um diese wieder zu\n"
+"aktivieren, nutzen Sie die Option '--show-forced-updates' oder führen\n"
+"Sie 'git config fetch.showForcedUpdates true' aus."
+
+#, c-format
+msgid ""
+"it took %.2f seconds to check forced updates; you can use\n"
+"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
+"false'\n"
+"to avoid this check\n"
+msgstr ""
+"Es brauchte %.2f Sekunden, um erzwungene Aktualisierungen zu überprüfen.\n"
+"Sie können die Option '--no-show-forced-updates' benutzen oder\n"
+"'git config fetch.showForcedUpdates false' ausführen, um diese Überprüfung\n"
+"zu umgehen.\n"
+
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s hat nicht alle erforderlichen Objekte gesendet\n"
+
+#, c-format
+msgid "rejected %s because shallow roots are not allowed to be updated"
+msgstr ""
+"%s zurückgewiesen, da Root-Commits von Repositories mit unvollständiger\n"
+"Historie (shallow) nicht aktualisiert werden dürfen."
+
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+"Einige lokale Referenzen konnten nicht aktualisiert werden; versuchen Sie\n"
+"'git remote prune %s', um jeden älteren, widersprüchlichen Branch zu löschen."
+
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr "   (%s wird unreferenziert)"
+
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr "   (%s wurde unreferenziert)"
+
+msgid "[deleted]"
+msgstr "[gelöscht]"
+
+msgid "(none)"
+msgstr "(nichts)"
+
+#, c-format
+msgid "refusing to fetch into branch '%s' checked out at '%s'"
+msgstr "Anfordern in Branch '%s' verweigert, ausgecheckt in '%s'"
+
+#, c-format
+msgid "option \"%s\" value \"%s\" is not valid for %s"
+msgstr "Option \"%s\" Wert \"%s\" ist nicht gültig für %s"
+
+#, c-format
+msgid "option \"%s\" is ignored for %s\n"
+msgstr "Option \"%s\" wird ignoriert für %s\n"
+
+#, c-format
+msgid "%s is not a valid object"
+msgstr "%s ist kein gültiges Objekt"
+
+#, c-format
+msgid "the object %s does not exist"
+msgstr "das Objekt %s ist nicht vorhanden"
+
+msgid "multiple branches detected, incompatible with --set-upstream"
+msgstr "mehrere Branches erkannt, inkompatibel mit --set-upstream"
+
+#, c-format
+msgid ""
+"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
+"any branch."
+msgstr ""
+"konnte keinen Upstream-Branch von HEAD auf '%s' von '%s' setzen, da dieser "
+"auf keinen Branch zeigt."
+
+msgid "not setting upstream for a remote remote-tracking branch"
+msgstr "setze keinen Upstream für einen entfernten Remote-Tracking-Branch"
+
+msgid "not setting upstream for a remote tag"
+msgstr "setze keinen Upstream für einen Tag eines Remote-Repositories"
+
+msgid "unknown branch type"
+msgstr "unbekannter Branch-Typ"
+
+msgid ""
+"no source branch found;\n"
+"you need to specify exactly one branch with the --set-upstream option"
+msgstr ""
+"kein Quell-Branch gefunden;\n"
+"Sie müssen bei der Option --set-upstream genau einen Branch angeben"
+
+#, c-format
+msgid "Fetching %s\n"
+msgstr "Fordere an von %s\n"
+
+#, c-format
+msgid "could not fetch %s"
+msgstr "konnte %s nicht anfordern"
+
+#, c-format
+msgid "could not fetch '%s' (exit code: %d)\n"
+msgstr "Konnte '%s' nicht anfordern (Exit-Code: %d)\n"
+
+msgid ""
+"no remote repository specified; please specify either a URL or a\n"
+"remote name from which new revisions should be fetched"
+msgstr ""
+"kein Remote-Repository angegeben; bitte geben Sie entweder eine URL\n"
+"oder den Namen des Remote-Repositories an, von welchem neue\n"
+"Commits angefordert werden sollen"
+
+msgid "you need to specify a tag name"
+msgstr "Sie müssen den Namen des Tags angeben"
+
 msgid "fetch from all remotes"
 msgstr "fordert von allen Remote-Repositories an"
 
@@ -5945,178 +6154,6 @@
 msgid "accept refspecs from stdin"
 msgstr "akzeptiere Refspecs von der Standard-Eingabe"
 
-msgid "couldn't find remote ref HEAD"
-msgstr "konnte Remote-Referenz von HEAD nicht finden"
-
-#, c-format
-msgid "object %s not found"
-msgstr "Objekt %s nicht gefunden"
-
-msgid "[up to date]"
-msgstr "[aktuell]"
-
-msgid "[rejected]"
-msgstr "[zurückgewiesen]"
-
-msgid "can't fetch into checked-out branch"
-msgstr "fetch kann in den ausgecheckten Branch nicht durchgeführt werden"
-
-msgid "[tag update]"
-msgstr "[Tag Aktualisierung]"
-
-msgid "unable to update local ref"
-msgstr "kann lokale Referenz nicht aktualisieren"
-
-msgid "would clobber existing tag"
-msgstr "würde bestehende Tags verändern"
-
-msgid "[new tag]"
-msgstr "[neues Tag]"
-
-msgid "[new branch]"
-msgstr "[neuer Branch]"
-
-msgid "[new ref]"
-msgstr "[neue Referenz]"
-
-msgid "forced update"
-msgstr "Aktualisierung erzwungen"
-
-msgid "non-fast-forward"
-msgstr "kein Vorspulen"
-
-#, c-format
-msgid "cannot open '%s'"
-msgstr "kann '%s' nicht öffnen"
-
-msgid ""
-"fetch normally indicates which branches had a forced update,\n"
-"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
-"flag or run 'git config fetch.showForcedUpdates true'"
-msgstr ""
-"Normalerweise zeigt 'fetch' welche Branches eine erzwungene Aktualisierung\n"
-"hatten, aber diese Überprüfung wurde deaktiviert. Um diese wieder zu\n"
-"aktivieren, nutzen Sie die Option '--show-forced-updates' oder führen\n"
-"Sie 'git config fetch.showForcedUpdates true' aus."
-
-#, c-format
-msgid ""
-"it took %.2f seconds to check forced updates; you can use\n"
-"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
-"false'\n"
-"to avoid this check\n"
-msgstr ""
-"Es brauchte %.2f Sekunden, um erzwungene Aktualisierungen zu überprüfen.\n"
-"Sie können die Option '--no-show-forced-updates' benutzen oder\n"
-"'git config fetch.showForcedUpdates false' ausführen, um diese Überprüfung\n"
-"zu umgehen.\n"
-
-#, c-format
-msgid "%s did not send all necessary objects\n"
-msgstr "%s hat nicht alle erforderlichen Objekte gesendet\n"
-
-#, c-format
-msgid "rejected %s because shallow roots are not allowed to be updated"
-msgstr ""
-"%s zurückgewiesen, da Root-Commits von Repositories mit unvollständiger\n"
-"Historie (shallow) nicht aktualisiert werden dürfen."
-
-#, c-format
-msgid "From %.*s\n"
-msgstr "Von %.*s\n"
-
-#, c-format
-msgid ""
-"some local refs could not be updated; try running\n"
-" 'git remote prune %s' to remove any old, conflicting branches"
-msgstr ""
-"Einige lokale Referenzen konnten nicht aktualisiert werden; versuchen Sie\n"
-"'git remote prune %s', um jeden älteren, widersprüchlichen Branch zu löschen."
-
-#, c-format
-msgid "   (%s will become dangling)"
-msgstr "   (%s wird unreferenziert)"
-
-#, c-format
-msgid "   (%s has become dangling)"
-msgstr "   (%s wurde unreferenziert)"
-
-msgid "[deleted]"
-msgstr "[gelöscht]"
-
-msgid "(none)"
-msgstr "(nichts)"
-
-#, c-format
-msgid "refusing to fetch into branch '%s' checked out at '%s'"
-msgstr "Anfordern in Branch '%s' verweigert, ausgecheckt in '%s'"
-
-#, c-format
-msgid "option \"%s\" value \"%s\" is not valid for %s"
-msgstr "Option \"%s\" Wert \"%s\" ist nicht gültig für %s"
-
-#, c-format
-msgid "option \"%s\" is ignored for %s\n"
-msgstr "Option \"%s\" wird ignoriert für %s\n"
-
-#, c-format
-msgid "%s is not a valid object"
-msgstr "%s ist kein gültiges Objekt"
-
-#, c-format
-msgid "the object %s does not exist"
-msgstr "das Objekt %s ist nicht vorhanden"
-
-msgid "multiple branches detected, incompatible with --set-upstream"
-msgstr "mehrere Branches erkannt, inkompatibel mit --set-upstream"
-
-#, c-format
-msgid ""
-"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
-"any branch."
-msgstr ""
-"konnte keinen Upstream-Branch von HEAD auf '%s' von '%s' setzen, da dieser "
-"auf keinen Branch zeigt."
-
-msgid "not setting upstream for a remote remote-tracking branch"
-msgstr "setze keinen Upstream für einen entfernten Remote-Tracking-Branch"
-
-msgid "not setting upstream for a remote tag"
-msgstr "setze keinen Upstream für einen Tag eines Remote-Repositories"
-
-msgid "unknown branch type"
-msgstr "unbekannter Branch-Typ"
-
-msgid ""
-"no source branch found;\n"
-"you need to specify exactly one branch with the --set-upstream option"
-msgstr ""
-"kein Quell-Branch gefunden;\n"
-"Sie müssen bei der Option --set-upstream genau einen Branch angeben"
-
-#, c-format
-msgid "Fetching %s\n"
-msgstr "Fordere an von %s\n"
-
-#, c-format
-msgid "could not fetch %s"
-msgstr "konnte %s nicht anfordern"
-
-#, c-format
-msgid "could not fetch '%s' (exit code: %d)\n"
-msgstr "Konnte '%s' nicht anfordern (Exit-Code: %d)\n"
-
-msgid ""
-"no remote repository specified; please specify either a URL or a\n"
-"remote name from which new revisions should be fetched"
-msgstr ""
-"kein Remote-Repository angegeben; bitte geben Sie entweder eine URL\n"
-"oder den Namen des Remote-Repositories an, von welchem neue\n"
-"Commits angefordert werden sollen"
-
-msgid "you need to specify a tag name"
-msgstr "Sie müssen den Namen des Tags angeben"
-
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr "--negotiate-only benötigt einen oder mehrere --negotiation-tip=*"
 
@@ -6239,6 +6276,12 @@
 msgid "print only refs which don't contain the commit"
 msgstr "nur Referenzen ausgeben, die diesen Commit nicht enthalten"
 
+msgid "read reference patterns from stdin"
+msgstr "Referenzmuster von Standard-Eingabe lesen"
+
+msgid "unknown arguments supplied with --stdin"
+msgstr "unbekannte Argumente mit --stdin geliefert"
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<Konfiguration> [--] <Argumente>"
 
@@ -6251,6 +6294,10 @@
 msgid "missing --config=<config>"
 msgstr "Option --config=<Konfiguration> fehlt"
 
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "ungültige Konfiguration --config=%s"
+
 msgid "unknown"
 msgstr "unbekannt"
 
@@ -6397,19 +6444,28 @@
 msgid "notice: %s points to an unborn branch (%s)"
 msgstr "Notiz: %s zeigt auf einen ungeborenen Branch (%s)"
 
-msgid "Checking cache tree"
-msgstr "Prüfe Cache-Verzeichnis"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "Prüfe Cache-Verzeichnis von %s"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "%s: Ungültiger SHA1-Zeiger in Cache-Verzeichnis"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s: ungültiger SHA1-Zeiger im Cache-Verzeichnis von %s"
 
 msgid "non-tree in cache-tree"
 msgstr "non-tree in Cache-Verzeichnis"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in resolve-undo"
-msgstr "%s: Ungültiger sha1-Zeiger in resolve-undo"
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s: ungültiger SHA1-Zeiger in resolve-undo von %s"
+
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "rev-Index für Pack-Datei '%s' kann nicht geladen werden"
+
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "ungültiger Rev-Index für Pack-Datei '%s'"
 
 msgid ""
 "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
@@ -9326,6 +9382,12 @@
 msgid "bad index version '%s'"
 msgstr "ungültige Index-Version '%s'"
 
+msgid "show progress meter during object writing phase"
+msgstr "Forschrittsanzeige während des Schreibens von Objekten anzeigen"
+
+msgid "similar to --all-progress when progress meter is shown"
+msgstr "ähnlich zu --all-progress wenn Fortschrittsanzeige darstellt wird"
+
 msgid "<version>[,<offset>]"
 msgstr "<Version>[,<Offset>]"
 
@@ -9530,6 +9592,9 @@
 "Sie es immer noch verwenden, indem Sie eine E-Mail an\n"
 "<git@vger.kernel.org> senden. Danke.\n"
 
+msgid "refusing to run without --i-still-use-this"
+msgstr "Ausführung ohne --i-still-use-this verweigert"
+
 msgid "git pack-refs [--all] [--no-prune]"
 msgstr "git pack-refs [--all] [--no-prune]"
 
@@ -9712,7 +9777,7 @@
 msgid "pull with rebase"
 msgstr "Pull mit Rebase"
 
-msgid "please commit or stash them."
+msgid "Please commit or stash them."
 msgstr "Bitte committen Sie die Änderungen oder benutzen Sie \"stash\"."
 
 #, c-format
@@ -9962,8 +10027,8 @@
 msgid "repository"
 msgstr "Repository"
 
-msgid "push all refs"
-msgstr "alle Referenzen versenden"
+msgid "push all branches"
+msgstr "alle Branches versenden"
 
 msgid "mirror all refs"
 msgstr "alle Referenzen spiegeln"
@@ -9971,8 +10036,10 @@
 msgid "delete refs"
 msgstr "Referenzen löschen"
 
-msgid "push tags (can't be used with --all or --mirror)"
-msgstr "Tags versenden (kann nicht mit --all oder --mirror verwendet werden)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr ""
+"Tags versenden (kann nicht mit --all, --branches oder --mirror verwendet "
+"werden)"
 
 msgid "force updates"
 msgstr "Aktualisierung erzwingen"
@@ -10242,6 +10309,10 @@
 "ausführen."
 
 #, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "Unbekannter rebase-merges Modus: %s"
+
+#, c-format
 msgid "could not switch to %s"
 msgstr "Konnte nicht zu %s wechseln."
 
@@ -10258,6 +10329,15 @@
 "nicht erkannter leerer Typ '%s'; gültige Werte sind \"drop\", \"keep\", und "
 "\"ask\"."
 
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"--rebase-merges mit einem leeren String-Argument ist veraltet und wird in "
+"einer zukünftigen Version von Git nicht mehr funktionieren. Verwenden Sie "
+"stattdessen --rebase-merges ohne ein Argument, was dasselbe bewirkt."
+
 #, c-format
 msgid ""
 "%s\n"
@@ -10483,21 +10563,24 @@
 msgid "switch `C' expects a numerical value"
 msgstr "Schalter `C' erwartet einen numerischen Wert."
 
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "Unbekannter Modus: %s"
-
 msgid "--strategy requires --merge or --interactive"
 msgstr "--strategy erfordert --merge oder --interactive"
 
 msgid ""
-"apply options are incompatible with rebase.autosquash.  Consider adding --no-"
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
 "autosquash"
 msgstr ""
-"apply-Optionen sind mit rebase.autosquash nicht kompatibel. Erwägen Sie das "
+"apply-Optionen sind mit rebase.autoSquash nicht kompatibel. Erwägen Sie das "
 "Hinzufügen von --no-autosquash"
 
 msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr ""
+"apply-Optionen sind nicht kompatibel mit rebase.rebaseMerges. Erwägen Sie "
+"das Hinzufügen von --no-rebase-merges"
+
+msgid ""
 "apply options are incompatible with rebase.updateRefs.  Consider adding --no-"
 "update-refs"
 msgstr ""
@@ -10541,9 +10624,6 @@
 msgid "Does not point to a valid commit '%s'"
 msgstr "'%s' zeigt auf keinen gültigen Commit."
 
-msgid "Please commit or stash them."
-msgstr "Bitte committen Sie die Änderungen oder benutzen Sie \"stash\"."
-
 msgid "HEAD is up to date."
 msgstr "HEAD ist aktuell."
 
@@ -11221,8 +11301,8 @@
 msgid "approxidate"
 msgstr "Datumsangabe"
 
-msgid "with -C, expire objects older than this"
-msgstr "mit -C, Objekte älter als angegeben verfallen lassen"
+msgid "with --cruft, expire objects older than this"
+msgstr "mit --cruft, Objekte verfallen lassen, die älter sind als das"
 
 msgid "remove redundant packs, and run git-prune-packed"
 msgstr "redundante Pakete entfernen und \"git-prune-packed\" ausführen"
@@ -11902,6 +11982,9 @@
 msgid "remote name"
 msgstr "Name des Remote-Repositories"
 
+msgid "push all refs"
+msgstr "alle Referenzen versenden"
+
 msgid "use stateless RPC protocol"
 msgstr "zustandsloses RPC-Protokoll verwenden"
 
@@ -12107,10 +12190,11 @@
 "Repository befinden"
 
 msgid ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable) "
-"[<Optionen>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<Optionen>]"
 
 msgid "this worktree is not sparse"
 msgstr "dieses Arbeitsverzeichnis ist nicht partiell"
@@ -12241,6 +12325,24 @@
 msgid "error while refreshing working directory"
 msgstr "Fehler während der Aktualisierung des Arbeitsverzeichnisses."
 
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <Datei>]"
+
+msgid "terminate input and output files by a NUL character"
+msgstr "Eingabe- und Ausgabedateien durch ein NUL-Zeichen abschließen"
+
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr ""
+"bei Verwendung mit --rules-file werden die Muster als Cone-Modus Muster "
+"interpretiert"
+
+msgid "use patterns in <file> instead of the current ones."
+msgstr "Muster aus <Datei> anstelle der aktuellen Muster verwenden"
+
 msgid "git stash list [<log-options>]"
 msgstr "git stash list [<log-Optionen>]"
 
@@ -15181,8 +15283,8 @@
 msgid "bad zlib compression level %d"
 msgstr "ungültiger zlib Komprimierungsgrad %d"
 
-msgid "core.commentChar should only be one character"
-msgstr "core.commentChar sollte nur ein Zeichen sein"
+msgid "core.commentChar should only be one ASCII character"
+msgstr "core.commentChar sollte nur ein ASCII-Zeichen sein"
 
 #, c-format
 msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15300,6 +15402,11 @@
 msgstr "Ungültiger Sektionsname: %s"
 
 #, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr ""
+"Ausführung mit übermäßig langer Zeile in '%s' bei Zeile %<PRIuMAX> verweigert"
+
+#, c-format
 msgid "missing value for '%s'"
 msgstr "Fehlender Wert für '%s'"
 
@@ -15980,6 +16087,9 @@
 msgid "do not show any source or destination prefix"
 msgstr "keine Quell- oder Ziel-Präfixe anzeigen"
 
+msgid "use default prefixes a/ and b/"
+msgstr "Standardpräfixe a/ und b/ verwenden"
+
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr ""
 "Kontext zwischen Unterschied-Blöcken bis zur angegebenen Anzahl von Zeilen "
@@ -16294,6 +16404,14 @@
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "Hinweis: Warte auf das Schließen der Datei durch Ihren Editor...%c"
 
+#, c-format
+msgid "could not write to '%s'"
+msgstr "Konnte nicht nach '%s' schreiben."
+
+#, c-format
+msgid "could not edit '%s'"
+msgstr "Konnte '%s' nicht editieren."
+
 msgid "Filtering content"
 msgstr "Filtere Inhalt"
 
@@ -16591,6 +16709,10 @@
 msgstr "kein Konfigurationsschlüssel für --config-env angegeben\n"
 
 #, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "keine Attributquelle für --attr-source angegeben\n"
+
+#, c-format
 msgid "unknown option: %s\n"
 msgstr "Unbekannte Option: %s\n"
 
@@ -18304,6 +18426,10 @@
 msgstr "Festplattennutzung von '%s' kann nicht abgerufen werden"
 
 #, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "Bitmap-Datei '%s' hat eine ungültige Prüfsumme"
+
+#, c-format
 msgid "mtimes file %s is too small"
 msgstr "mtimes-Datei %s ist zu klein"
 
@@ -18343,6 +18469,13 @@
 msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
 msgstr "Reverse-Index-Datei %s hat nicht unterstützte Hash-ID %<PRIu32>"
 
+msgid "invalid checksum"
+msgstr "ungültige Prüfsumme"
+
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr "ungültige rev-index Position bei %<PRIu64>: %<PRIu32> != %<PRIu32>"
+
 msgid "cannot both write and verify reverse index"
 msgstr ""
 "Reverse-Index kann nicht gleichzeitig geschrieben und verifiziert werden"
@@ -19072,6 +19205,10 @@
 msgstr "Positive Breitenangabe für %%(align) erwartet"
 
 #, c-format
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "erwartetes Format: %%(ahead-behind:<Commit>)"
+
+#, c-format
 msgid "malformed field name: %.*s"
 msgstr "Fehlerhafter Feldname: %.*s"
 
@@ -19711,10 +19848,6 @@
 msgstr "Keine aufgezeichnete Konfliktauflösung für '%s'."
 
 #, c-format
-msgid "cannot unlink '%s'"
-msgstr "Kann '%s' nicht löschen."
-
-#, c-format
 msgid "Updated preimage for '%s'"
 msgstr "Preimage für '%s' aktualisiert."
 
@@ -20053,10 +20186,6 @@
 msgstr "Konnte '%s' nicht sperren"
 
 #, c-format
-msgid "could not write to '%s'"
-msgstr "Konnte nicht nach '%s' schreiben."
-
-#, c-format
 msgid "could not write eol to '%s'"
 msgstr "Konnte EOL nicht nach '%s' schreiben."
 
@@ -20424,9 +20553,6 @@
 msgid "could not create sequencer directory '%s'"
 msgstr "konnte \"sequencer\"-Verzeichnis '%s' nicht erstellen"
 
-msgid "could not lock HEAD"
-msgstr "konnte HEAD nicht sperren"
-
 msgid "no cherry-pick or revert in progress"
 msgstr "kein \"cherry-pick\" oder \"revert\" im Gange"
 
@@ -20523,20 +20649,20 @@
 "\n"
 "ausführen.\n"
 
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "Der Index und/oder das Arbeitsverzeichnis wurde geändert.\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "und Änderungen am Index und/oder am Arbeitsverzeichnis vorgenommen.\n"
 
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
 msgstr ""
 "Ausführung erfolgreich: %s\n"
-"Aber Änderungen in Index oder Arbeitsverzeichnis verblieben.\n"
+"Aber es sind Änderungen im Index oder Arbeitsverzeichnis verblieben.\n"
 "Committen Sie Ihre Änderungen oder benutzen Sie \"stash\".\n"
 "Führen Sie dann aus:\n"
 "\n"
@@ -20982,10 +21108,6 @@
 msgstr[1] "%u Bytes/s"
 
 #, c-format
-msgid "could not edit '%s'"
-msgstr "Konnte '%s' nicht editieren."
-
-#, c-format
 msgid "ignoring suspicious submodule name: %s"
 msgstr "Ignoriere verdächtigen Submodulnamen: %s"
 
@@ -22794,13 +22916,17 @@
 msgstr "(%s) Konnte '%s' nicht ausführen"
 
 #, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) Füge %s: %s hinzu von: '%s'\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) Fehlerhafte Ausgabe von '%s'"
 
 #, perl-format
 msgid "(%s) failed to close pipe to '%s'"
 msgstr "(%s) Fehler beim Schließen der Pipe nach '%s'"
 
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) Füge %s: %s hinzu von: '%s'\n"
+
 msgid "cannot send message as 7bit"
 msgstr "kann Nachricht nicht als 7bit versenden"
 
@@ -22837,377 +22963,3 @@
 #, perl-format
 msgid "Do you really want to send %s? [y|N]: "
 msgstr "Wollen Sie %s wirklich versenden? [y|N]: "
-
-#~ msgid "git bisect--helper --bisect-state (bad|new) [<rev>]"
-#~ msgstr "git bisect--helper --bisect-state (bad|new) [<Commit>]"
-
-#~ msgid "won't bisect on cg-seek'ed tree"
-#~ msgstr ""
-#~ "binäre Suche auf einem durch 'cg-seek' geändertem Verzeichnis nicht "
-#~ "möglich"
-
-#~ msgid "--bisect-terms requires 0 or 1 argument"
-#~ msgstr "--bisect-terms benötigt 0 oder 1 Argument"
-
-#~ msgid "--bisect-next requires 0 arguments"
-#~ msgstr "--bisect-next benötigt 0 Argumente"
-
-#~ msgid "--bisect-log requires 0 arguments"
-#~ msgstr "--bisect-log benötigt 0 Argumente"
-
-#~ msgid "git env--helper --type=[bool|ulong] <options> <env-var>"
-#~ msgstr "git env--helper --type=[bool|ulong] <Optionen> <Umgebungsvariable>"
-
-#~ msgid "default for git_env_*(...) to fall back on"
-#~ msgstr "Standard für git_env_*(...), um darauf zurückzugreifen"
-
-#~ msgid "be quiet only use git_env_*() value as exit code"
-#~ msgstr ""
-#~ "Ausgaben unterdrücken; nur git_env_*() Werte als Exit-Code verwenden"
-
-#, c-format
-#~ msgid ""
-#~ "option `--default' expects a boolean value with `--type=bool`, not `%s`"
-#~ msgstr ""
-#~ "Option `--default' erwartet einen booleschen Wert bei `--type=bool`, "
-#~ "nicht `%s`"
-
-#, c-format
-#~ msgid ""
-#~ "option `--default' expects an unsigned long value with `--type=ulong`, "
-#~ "not `%s`"
-#~ msgstr ""
-#~ "Option `--default' erwartet einen vorzeichenlosen Long-Wert bei `--"
-#~ "type=ulong`, nicht `%s`"
-
-#, c-format
-#~ msgid "%s doesn't support --super-prefix"
-#~ msgstr "%s unterstützt kein --super-prefix"
-
-#, c-format
-#~ msgid "no prefix given for --super-prefix\n"
-#~ msgstr "Kein Präfix für --super-prefix angegeben.\n"
-
-#, c-format
-#~ msgid "failed to read object %s"
-#~ msgstr "Konnte Objekt %s nicht lesen."
-
-#~ msgid "file write error"
-#~ msgstr "Fehler beim Schreiben einer Datei."
-
-#~ msgid "corrupt commit"
-#~ msgstr "fehlerhafter Commit"
-
-#~ msgid "corrupt tag"
-#~ msgstr "fehlerhaftes Tag"
-
-#, c-format
-#~ msgid "%%(objecttype) does not take arguments"
-#~ msgstr "%%(objecttype) akzeptiert keine Argumente"
-
-#, c-format
-#~ msgid "%%(deltabase) does not take arguments"
-#~ msgstr "%%(deltabase) akzeptiert keine Argumente"
-
-#, c-format
-#~ msgid "%%(body) does not take arguments"
-#~ msgstr "%%(body) akzeptiert keine Argumente"
-
-#, c-format
-#~ msgid "unrecognized email option: %s"
-#~ msgstr "nicht erkannte E-Mail Option: %s"
-
-#, c-format
-#~ msgid ""
-#~ "It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
-#~ "may speed it up, but you have to be careful not to forget to add\n"
-#~ "new files yourself (see 'git help status')."
-#~ msgstr ""
-#~ "Es dauerte %.2f Sekunden die unversionierten Dateien zu bestimmen.\n"
-#~ "'status -uno' könnte das beschleunigen, aber Sie müssen darauf achten,\n"
-#~ "neue Dateien selbstständig hinzuzufügen (siehe 'git help status')."
-
-#, perl-format
-#~ msgid "%12s %12s %s"
-#~ msgstr "%28s %25s %s"
-
-#, perl-format
-#~ msgid "touched %d path\n"
-#~ msgid_plural "touched %d paths\n"
-#~ msgstr[0] "%d Pfad angefasst\n"
-#~ msgstr[1] "%d Pfade angefasst\n"
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for staging."
-#~ msgstr ""
-#~ "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete\n"
-#~ "Patch-Block direkt zum Hinzufügen zur Staging-Area markiert."
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for stashing."
-#~ msgstr ""
-#~ "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete\n"
-#~ "Patch-Block direkt zum Hinzufügen zum Stash markiert."
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for unstaging."
-#~ msgstr ""
-#~ "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete\n"
-#~ "Patch-Block direkt zum Entfernen aus der Staging-Area markiert."
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for applying."
-#~ msgstr ""
-#~ "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete\n"
-#~ "Patch-Block direkt zum Anwenden markiert."
-
-#~ msgid ""
-#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
-#~ "marked for discarding."
-#~ msgstr ""
-#~ "Wenn der Patch sauber angewendet werden kann, wird der bearbeitete\n"
-#~ "Patch-Block direkt zum Verwerfen markiert."
-
-#, perl-format
-#~ msgid "failed to open hunk edit file for writing: %s"
-#~ msgstr ""
-#~ "Fehler beim Öffnen von Editier-Datei eines Patch-Blocks zum Schreiben: %s"
-
-#, perl-format
-#~ msgid ""
-#~ "---\n"
-#~ "To remove '%s' lines, make them ' ' lines (context).\n"
-#~ "To remove '%s' lines, delete them.\n"
-#~ "Lines starting with %s will be removed.\n"
-#~ msgstr ""
-#~ "---\n"
-#~ "Um '%s' Zeilen zu entfernen, machen Sie aus diesen ' ' Zeilen (Kontext).\n"
-#~ "Um '%s' Zeilen zu entfernen, löschen Sie diese.\n"
-#~ "Zeilen, die mit %s beginnen, werden entfernt.\n"
-
-#, perl-format
-#~ msgid "failed to open hunk edit file for reading: %s"
-#~ msgstr ""
-#~ "Fehler beim Öffnen von Editier-Datei eines Patch-Blocks zum Lesen: %s"
-
-#~ msgid ""
-#~ "y - stage this hunk\n"
-#~ "n - do not stage this hunk\n"
-#~ "q - quit; do not stage this hunk or any of the remaining ones\n"
-#~ "a - stage this hunk and all later hunks in the file\n"
-#~ "d - do not stage this hunk or any of the later hunks in the file"
-#~ msgstr ""
-#~ "y - diesen Patch-Block zum Commit vormerken\n"
-#~ "n - diesen Patch-Block nicht zum Commit vormerken\n"
-#~ "q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht zum Commit "
-#~ "vormerken\n"
-#~ "a - diesen und alle weiteren Patch-Blöcke dieser Datei zum Commit "
-#~ "vormerken\n"
-#~ "d - diesen oder alle weiteren Patch-Blöcke in dieser Datei nicht zum "
-#~ "Commit vormerken"
-
-#~ msgid ""
-#~ "y - stash this hunk\n"
-#~ "n - do not stash this hunk\n"
-#~ "q - quit; do not stash this hunk or any of the remaining ones\n"
-#~ "a - stash this hunk and all later hunks in the file\n"
-#~ "d - do not stash this hunk or any of the later hunks in the file"
-#~ msgstr ""
-#~ "y - diesen Patch-Block stashen\n"
-#~ "n - diesen Patch-Block nicht stashen\n"
-#~ "q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht stashen\n"
-#~ "a - diesen und alle weiteren Patch-Blöcke dieser Datei stashen\n"
-#~ "d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht stashen"
-
-#~ msgid ""
-#~ "y - unstage this hunk\n"
-#~ "n - do not unstage this hunk\n"
-#~ "q - quit; do not unstage this hunk or any of the remaining ones\n"
-#~ "a - unstage this hunk and all later hunks in the file\n"
-#~ "d - do not unstage this hunk or any of the later hunks in the file"
-#~ msgstr ""
-#~ "y - diesen Patch-Block unstashen\n"
-#~ "n - diesen Patch-Block nicht unstashen\n"
-#~ "q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht unstashen\n"
-#~ "a - diesen und alle weiteren Patch-Blöcke dieser Datei unstashen\n"
-#~ "d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht unstashen"
-
-#~ msgid ""
-#~ "y - apply this hunk to index\n"
-#~ "n - do not apply this hunk to index\n"
-#~ "q - quit; do not apply this hunk or any of the remaining ones\n"
-#~ "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"
-#~ msgstr ""
-#~ "y - diesen Patch-Block auf den Index anwenden\n"
-#~ "n - diesen Patch-Block nicht auf den Index anwenden\n"
-#~ "q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht auf den "
-#~ "Index anwenden\n"
-#~ "a - diesen und alle weiteren Patch-Blöcke dieser Datei auf den Index "
-#~ "anwenden\n"
-#~ "d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht auf den "
-#~ "Index anwenden"
-
-#~ msgid ""
-#~ "y - discard this hunk from worktree\n"
-#~ "n - do not discard this hunk from worktree\n"
-#~ "q - quit; do not discard this hunk or any of the remaining ones\n"
-#~ "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"
-#~ msgstr ""
-#~ "y - diesen Patch-Block im Arbeitsverzeichnis verwerfen\n"
-#~ "n - diesen Patch-Block im Arbeitsverzeichnis nicht verwerfen\n"
-#~ "q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht im "
-#~ "Arbeitsverzeichnis verwerfen\n"
-#~ "a - diesen und alle weiteren Patch-Blöcke dieser Datei im "
-#~ "Arbeitsverzeichnis verwerfen\n"
-#~ "d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht im "
-#~ "Arbeitsverzeichnis verwerfen"
-
-#~ msgid ""
-#~ "y - discard this hunk from index and worktree\n"
-#~ "n - do not discard this hunk from index and worktree\n"
-#~ "q - quit; do not discard this hunk or any of the remaining ones\n"
-#~ "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"
-#~ msgstr ""
-#~ "y - diesen Patch-Block im Index und Arbeitsverzeichnis verwerfen\n"
-#~ "n - diesen Patch-Block nicht im Index und Arbeitsverzeichnis verwerfen\n"
-#~ "q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht im Index "
-#~ "und Arbeitsverzeichnis verwerfen\n"
-#~ "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"
-
-#~ msgid ""
-#~ "y - apply this hunk to index and worktree\n"
-#~ "n - do not apply this hunk to index and worktree\n"
-#~ "q - quit; do not apply this hunk or any of the remaining ones\n"
-#~ "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"
-#~ msgstr ""
-#~ "y - diesen Patch-Block im Index und auf Arbeitsverzeichnis anwenden\n"
-#~ "n - diesen Patch-Block nicht im Index und auf Arbeitsverzeichnis "
-#~ "anwenden\n"
-#~ "q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht anwenden\n"
-#~ "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"
-
-#~ msgid ""
-#~ "y - apply this hunk to worktree\n"
-#~ "n - do not apply this hunk to worktree\n"
-#~ "q - quit; do not apply this hunk or any of the remaining ones\n"
-#~ "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"
-#~ msgstr ""
-#~ "y - diesen Patch-Block auf das Arbeitsverzeichnis anwenden\n"
-#~ "n - diesen Patch-Block nicht auf das Arbeitsverzeichnis anwenden\n"
-#~ "q - Beenden; diesen und alle verbleibenden Patch-Blöcke nicht anwenden\n"
-#~ "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"
-
-#~ msgid ""
-#~ "g - select a hunk to go to\n"
-#~ "/ - search for a hunk matching the given regex\n"
-#~ "j - leave this hunk undecided, see next undecided hunk\n"
-#~ "J - leave this hunk undecided, see next hunk\n"
-#~ "k - leave this hunk undecided, see previous undecided hunk\n"
-#~ "K - leave this hunk undecided, see previous hunk\n"
-#~ "s - split the current hunk into smaller hunks\n"
-#~ "e - manually edit the current hunk\n"
-#~ "? - print help\n"
-#~ msgstr ""
-#~ "g - Patch-Block zum Hinspringen auswählen\n"
-#~ "/ - nach Patch-Block suchen, der gegebenem regulärem Ausdruck entspricht\n"
-#~ "j - diesen Patch-Block unbestimmt lassen, nächsten unbestimmten Patch-"
-#~ "Block anzeigen\n"
-#~ "J - diesen Patch-Block unbestimmt lassen, nächsten Patch-Block anzeigen\n"
-#~ "k - diesen Patch-Block unbestimmt lassen, vorherigen unbestimmten Patch-"
-#~ "Block anzeigen\n"
-#~ "K - diesen Patch-Block unbestimmt lassen, vorherigen Patch-Block "
-#~ "anzeigen\n"
-#~ "s - aktuellen Patch-Block in kleinere Patch-Blöcke aufteilen\n"
-#~ "e - aktuellen Patch-Block manuell editieren\n"
-#~ "? - Hilfe anzeigen\n"
-
-#~ msgid "The selected hunks do not apply to the index!\n"
-#~ msgstr ""
-#~ "Die ausgewählten Patch-Blöcke können nicht auf den Index angewendet "
-#~ "werden!\n"
-
-#, perl-format
-#~ msgid "ignoring unmerged: %s\n"
-#~ msgstr "ignoriere nicht zusammengeführte Datei: %s\n"
-
-#~ msgid "No other hunks to goto\n"
-#~ msgstr "Keine anderen Patch-Blöcke verbleibend\n"
-
-#, perl-format
-#~ msgid "Invalid number: '%s'\n"
-#~ msgstr "Ungültige Nummer: '%s'\n"
-
-#, perl-format
-#~ msgid "Sorry, only %d hunk available.\n"
-#~ msgid_plural "Sorry, only %d hunks available.\n"
-#~ msgstr[0] "Entschuldigung, nur %d Patch-Block verfügbar.\n"
-#~ msgstr[1] "Entschuldigung, nur %d Patch-Blöcke verfügbar.\n"
-
-#~ msgid "No other hunks to search\n"
-#~ msgstr "Keine anderen Patch-Blöcke zum Durchsuchen\n"
-
-#, perl-format
-#~ msgid "Malformed search regexp %s: %s\n"
-#~ msgstr "Fehlerhafter regulärer Ausdruck für Suche %s: %s\n"
-
-#~ msgid "No hunk matches the given pattern\n"
-#~ msgstr "Kein Patch-Block entspricht dem angegebenen Muster\n"
-
-#~ msgid "No previous hunk\n"
-#~ msgstr "Kein vorheriger Patch-Block\n"
-
-#~ msgid "No next hunk\n"
-#~ msgstr "Kein folgender Patch-Block\n"
-
-#~ msgid "Sorry, cannot split this hunk\n"
-#~ msgstr "Entschuldigung, kann diesen Patch-Block nicht aufteilen.\n"
-
-#, perl-format
-#~ msgid "Split into %d hunk.\n"
-#~ msgid_plural "Split into %d hunks.\n"
-#~ msgstr[0] "In %d Patch-Block aufgeteilt.\n"
-#~ msgstr[1] "In %d Patch-Blöcke aufgeteilt.\n"
-
-#~ msgid "Sorry, cannot edit this hunk\n"
-#~ msgstr "Entschuldigung, kann diesen Patch-Block nicht bearbeiten.\n"
-
-#~ msgid ""
-#~ "status        - show paths with changes\n"
-#~ "update        - add working tree state to the staged set of changes\n"
-#~ "revert        - revert staged set of changes back to the HEAD version\n"
-#~ "patch         - pick hunks and update selectively\n"
-#~ "diff          - view diff between HEAD and index\n"
-#~ "add untracked - add contents of untracked files to the staged set of "
-#~ "changes\n"
-#~ msgstr ""
-#~ "status        - Pfade mit Änderungen anzeigen\n"
-#~ "update        - Zustand des Arbeitsverzeichnisses den zum Commit "
-#~ "vorgemerkten Änderungen hinzufügen\n"
-#~ "revert        - zum Commit vorgemerkte Änderungen auf HEAD Version "
-#~ "zurücksetzen\n"
-#~ "patch         - Patch-Blöcke auswählen und selektiv aktualisieren\n"
-#~ "diff          - Unterschiede zwischen HEAD und Index anzeigen\n"
-#~ "add untracked - Inhalte von unversionierten Dateien zum Commit vormerken\n"
-
-#~ msgid "missing --"
-#~ msgstr "-- fehlt"
-
-#, perl-format
-#~ msgid "unknown --patch mode: %s"
-#~ msgstr "Unbekannter --patch Modus: %s"
-
-#, perl-format
-#~ msgid "invalid argument %s, expecting --"
-#~ msgstr "ungültiges Argument %s, erwarte --"
diff --git a/po/fr.po b/po/fr.po
index f032441..db6efc0 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -78,8 +78,8 @@
 msgstr ""
 "Project-Id-Version: git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-03-01 01:20+0000\n"
-"PO-Revision-Date: 2023-03-02 18:44+0100\n"
+"POT-Creation-Date: 2023-05-20 12:25+0200\n"
+"PO-Revision-Date: 2023-05-18 18:50+0200\n"
 "Last-Translator: Cédric Malard <c.malard-git@valdun.net>\n"
 "Language-Team: Jean-Noël Avila <jn.avila@free.fr>\n"
 "Language: fr\n"
@@ -739,6 +739,24 @@
 msgid "Exiting because of unfinished merge."
 msgstr "Abandon à cause d'une fusion non terminée."
 
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"Des branches divergentes ne peuvent pas être gérées en avance rapide, vous "
+"devez soit :\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"ou :\n"
+"\n"
+"\tgit rebase\n"
+
 msgid "Not possible to fast-forward, aborting."
 msgstr "Pas possible d'avancer rapidement, abandon."
 
@@ -1200,6 +1218,10 @@
 msgstr "impossible d'ouvrir %s"
 
 #, c-format
+msgid "cannot unlink '%s'"
+msgstr "impossible de délier '%s'"
+
+#, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "Section n°%d appliquée proprement."
 
@@ -1391,6 +1413,12 @@
 msgstr "impossible de lire '%s'"
 
 #, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr ""
+"le spécificateur de chemin '%s' correspond à des fichiers hors du répertoire "
+"actuel"
+
+#, c-format
 msgid "pathspec '%s' did not match any files"
 msgstr "le chemin '%s' ne correspond à aucun fichier"
 
@@ -1406,9 +1434,6 @@
 msgid "not a tree object: %s"
 msgstr "objet arbre invalide : %s"
 
-msgid "current working directory is untracked"
-msgstr "l'arbre de travail actuel est non-suivi"
-
 #, c-format
 msgid "File not found: %s"
 msgstr "Fichier non trouvé : %s"
@@ -1535,6 +1560,9 @@
 msgid "ignoring overly large gitattributes blob '%s'"
 msgstr "blob gitattributes trop gros ignoré '%s'"
 
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr "mauvais --attr-source ou GIT_ATTR_SOURCE"
+
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
 msgstr "Contenu mal cité dans le fichier '%s' : %s"
@@ -1641,9 +1669,6 @@
 msgid "--contents and --reverse do not blend well."
 msgstr "--contents et --reverse ne font pas bon ménage."
 
-msgid "cannot use --contents with final commit object name"
-msgstr "on ne peut pas utiliser --contents avec un nom d'objet commit final"
-
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr ""
 "--reverse et --first-parent ensemble nécessitent la spécification d'un "
@@ -1827,10 +1852,6 @@
 msgid "'%s' is already checked out at '%s'"
 msgstr "'%s' est déjà extrait dans '%s'"
 
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "la HEAD de la copie de travail %s n'est pas mise à jour"
-
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<options>] [--] <chemin>..."
 
@@ -2889,6 +2910,14 @@
 msgstr "branche de suivi '%s' non trouvée."
 
 #, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"branche '%s' non trouvée.\n"
+"Avez-vous oublié --remote ?"
+
+#, c-format
 msgid "branch '%s' not found."
 msgstr "branche '%s' non trouvée."
 
@@ -2919,6 +2948,10 @@
 msgstr "La branche %s est en cours de bissection sur %s"
 
 #, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "la HEAD de la copie de travail %s n'est pas mise à jour"
+
+#, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "Nom de branche invalide : '%s'"
 
@@ -3022,6 +3055,9 @@
 msgid "move/rename a branch, even if target exists"
 msgstr "déplacer/renommer une branche, même si la cible existe"
 
+msgid "do not output a newline after empty formatted refs"
+msgstr "ne pas générer de nouvelle ligne après des réfs formatées vides"
+
 msgid "copy a branch and its reflog"
 msgstr "copier une branche et son reflog"
 
@@ -3247,13 +3283,11 @@
 msgstr "Nouveau rapport créé à '%s'.\n"
 
 msgid ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
-"                  [--version=<version>] <file> <args-de-git-rev-list>"
+"git bundle create [-q | --quiet | --progress]\n"
+"                  [--version=<version>] <fichier> <args-de-git-rev-list>"
 
 msgid "git bundle verify [-q | --quiet] <file>"
 msgstr "git bundle verify [-q | --quiet] <fichier>"
@@ -3273,11 +3307,11 @@
 msgid "show progress meter"
 msgstr "afficher la barre de progression"
 
-msgid "show progress meter during object writing phase"
-msgstr "afficher la barre de progression durant la phase d'écrite des objets"
+msgid "historical; same as --progress"
+msgstr "option historique ; identique à --progress"
 
-msgid "similar to --all-progress when progress meter is shown"
-msgstr "similaire à --all-progress quand la barre de progression est affichée"
+msgid "historical; does nothing"
+msgstr "option historique ; ne fait rien"
 
 msgid "specify bundle format version"
 msgstr "spécifier la version du format de colis"
@@ -4301,6 +4335,10 @@
 msgstr "%s existe et n'est pas un répertoire"
 
 #, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "'%s' est un lien symbolique, refus de cloner avec --local"
+
+#, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "échec du démarrage un itérateur sur '%s'"
 
@@ -5841,6 +5879,175 @@
 msgid "fetch.parallel cannot be negative"
 msgstr "fetch.parallel ne peut pas être négatif"
 
+msgid "couldn't find remote ref HEAD"
+msgstr "impossible de trouver la référence HEAD distante"
+
+#, c-format
+msgid "From %.*s\n"
+msgstr "Depuis %.*s\n"
+
+#, c-format
+msgid "object %s not found"
+msgstr "objet %s non trouvé"
+
+msgid "[up to date]"
+msgstr "[à jour]"
+
+msgid "[rejected]"
+msgstr "[rejeté]"
+
+msgid "can't fetch into checked-out branch"
+msgstr "impossible de récupérer dans la branche extraite"
+
+msgid "[tag update]"
+msgstr "[mise à jour de l'étiquette]"
+
+msgid "unable to update local ref"
+msgstr "impossible de mettre à jour la référence locale"
+
+msgid "would clobber existing tag"
+msgstr "écraserait l'étiquette existante"
+
+msgid "[new tag]"
+msgstr "[nouvelle étiquette]"
+
+msgid "[new branch]"
+msgstr "[nouvelle branche]"
+
+msgid "[new ref]"
+msgstr "[nouvelle référence]"
+
+msgid "forced update"
+msgstr "mise à jour forcée"
+
+msgid "non-fast-forward"
+msgstr "pas en avance rapide"
+
+#, c-format
+msgid "cannot open '%s'"
+msgstr "impossible d'ouvrir '%s'"
+
+msgid ""
+"fetch normally indicates which branches had a forced update,\n"
+"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
+"flag or run 'git config fetch.showForcedUpdates true'"
+msgstr ""
+"fetch indique normalement quelles branches ont subi une mise à jour forcée,\n"
+"mais ceci a été désactivé. Pour ré-activer, utilisez le drapeau\n"
+"'--show-forced-updates' ou lancez 'git config fetch.showForcedUpdates true'"
+
+#, c-format
+msgid ""
+"it took %.2f seconds to check forced updates; you can use\n"
+"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
+"false'\n"
+"to avoid this check\n"
+msgstr ""
+"%.2f secondes ont été nécessaires pour vérifier les mises à jour forcées ;\n"
+"Vous pouvez utiliser '--no-show-forced-updates' ou lancer\n"
+"'git config fetch.showForcedUpdates false' pour éviter cette vérification\n"
+
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s n'a pas envoyé tous les objets nécessaires\n"
+
+#, c-format
+msgid "rejected %s because shallow roots are not allowed to be updated"
+msgstr ""
+"%s rejeté parce que les  mises à jour de racines superficielles ne sont pas "
+"permises"
+
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+"des références locales n'ont pas pu être mises à jour ; essayez de lancer\n"
+" 'git remote prune %s' pour supprimer des branches anciennes en conflit"
+
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr "   (%s sera en suspens)"
+
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr "   (%s est devenu en suspens)"
+
+msgid "[deleted]"
+msgstr "[supprimé]"
+
+msgid "(none)"
+msgstr "(aucun(e))"
+
+#, c-format
+msgid "refusing to fetch into branch '%s' checked out at '%s'"
+msgstr "refus de récupérer dans la branche '%s' extraite dans '%s'"
+
+#, c-format
+msgid "option \"%s\" value \"%s\" is not valid for %s"
+msgstr "la valeur \"%2$s\" de l'option \"%1$s\" est invalide pour %3$s"
+
+#, c-format
+msgid "option \"%s\" is ignored for %s\n"
+msgstr "l'option \"%s\" est ignorée pour %s\n"
+
+#, c-format
+msgid "%s is not a valid object"
+msgstr "%s n'est pas un objet valide"
+
+#, c-format
+msgid "the object %s does not exist"
+msgstr "l'objet %s n'existe pas"
+
+msgid "multiple branches detected, incompatible with --set-upstream"
+msgstr "branches multiples détectées, imcompatible avec --set-upstream"
+
+#, c-format
+msgid ""
+"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
+"any branch."
+msgstr ""
+"impossible de régler la branche amont de HEAD à '%s' depuis '%s' qui ne "
+"pointe sur aucune branche."
+
+msgid "not setting upstream for a remote remote-tracking branch"
+msgstr "dépôt amont non défini pour la branche de suivi à distance"
+
+msgid "not setting upstream for a remote tag"
+msgstr "dépôt amont non défini pour l'étiquette distante"
+
+msgid "unknown branch type"
+msgstr "type de branche inconnu"
+
+msgid ""
+"no source branch found;\n"
+"you need to specify exactly one branch with the --set-upstream option"
+msgstr ""
+"aucune branche source trouvée.\n"
+"Vous devez spécifier exactement une branche avec l'option --set-upstream"
+
+#, c-format
+msgid "Fetching %s\n"
+msgstr "Récupération de %s\n"
+
+#, c-format
+msgid "could not fetch %s"
+msgstr "impossible de récupérer %s"
+
+#, c-format
+msgid "could not fetch '%s' (exit code: %d)\n"
+msgstr "impossible de récupérer '%s' (code de sortie : %d)\n"
+
+msgid ""
+"no remote repository specified; please specify either a URL or a\n"
+"remote name from which new revisions should be fetched"
+msgstr ""
+"Aucun dépôt distant spécifié. Veuillez spécifier une URL ou un nom\n"
+"distant depuis lesquels les nouvelles révisions devraient être récupérées"
+
+msgid "you need to specify a tag name"
+msgstr "Vous devez spécifier un nom d'étiquette"
+
 msgid "fetch from all remotes"
 msgstr "récupérer depuis tous les dépôts distants"
 
@@ -5954,175 +6161,6 @@
 msgid "accept refspecs from stdin"
 msgstr "lire les spécificateurs de référence depuis l'entrée standard"
 
-msgid "couldn't find remote ref HEAD"
-msgstr "impossible de trouver la référence HEAD distante"
-
-#, c-format
-msgid "object %s not found"
-msgstr "objet %s non trouvé"
-
-msgid "[up to date]"
-msgstr "[à jour]"
-
-msgid "[rejected]"
-msgstr "[rejeté]"
-
-msgid "can't fetch into checked-out branch"
-msgstr "impossible de récupérer dans la branche extraite"
-
-msgid "[tag update]"
-msgstr "[mise à jour de l'étiquette]"
-
-msgid "unable to update local ref"
-msgstr "impossible de mettre à jour la référence locale"
-
-msgid "would clobber existing tag"
-msgstr "écraserait l'étiquette existante"
-
-msgid "[new tag]"
-msgstr "[nouvelle étiquette]"
-
-msgid "[new branch]"
-msgstr "[nouvelle branche]"
-
-msgid "[new ref]"
-msgstr "[nouvelle référence]"
-
-msgid "forced update"
-msgstr "mise à jour forcée"
-
-msgid "non-fast-forward"
-msgstr "pas en avance rapide"
-
-#, c-format
-msgid "cannot open '%s'"
-msgstr "impossible d'ouvrir '%s'"
-
-msgid ""
-"fetch normally indicates which branches had a forced update,\n"
-"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
-"flag or run 'git config fetch.showForcedUpdates true'"
-msgstr ""
-"fetch indique normalement quelles branches ont subi une mise à jour forcée,\n"
-"mais ceci a été désactivé. Pour ré-activer, utilisez le drapeau\n"
-"'--show-forced-updates' ou lancez 'git config fetch.showForcedUpdates true'"
-
-#, c-format
-msgid ""
-"it took %.2f seconds to check forced updates; you can use\n"
-"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
-"false'\n"
-"to avoid this check\n"
-msgstr ""
-"%.2f secondes ont été nécessaires pour vérifier les mises à jour forcées ;\n"
-"Vous pouvez utiliser '--no-show-forced-updates' ou lancer\n"
-"'git config fetch.showForcedUpdates false' pour éviter cette vérification\n"
-
-#, c-format
-msgid "%s did not send all necessary objects\n"
-msgstr "%s n'a pas envoyé tous les objets nécessaires\n"
-
-#, c-format
-msgid "rejected %s because shallow roots are not allowed to be updated"
-msgstr ""
-"%s rejeté parce que les  mises à jour de racines superficielles ne sont pas "
-"permises"
-
-#, c-format
-msgid "From %.*s\n"
-msgstr "Depuis %.*s\n"
-
-#, c-format
-msgid ""
-"some local refs could not be updated; try running\n"
-" 'git remote prune %s' to remove any old, conflicting branches"
-msgstr ""
-"des références locales n'ont pas pu être mises à jour ; essayez de lancer\n"
-" 'git remote prune %s' pour supprimer des branches anciennes en conflit"
-
-#, c-format
-msgid "   (%s will become dangling)"
-msgstr "   (%s sera en suspens)"
-
-#, c-format
-msgid "   (%s has become dangling)"
-msgstr "   (%s est devenu en suspens)"
-
-msgid "[deleted]"
-msgstr "[supprimé]"
-
-msgid "(none)"
-msgstr "(aucun(e))"
-
-#, c-format
-msgid "refusing to fetch into branch '%s' checked out at '%s'"
-msgstr "refus de récupérer dans la branche '%s' extraite dans '%s'"
-
-#, c-format
-msgid "option \"%s\" value \"%s\" is not valid for %s"
-msgstr "la valeur \"%2$s\" de l'option \"%1$s\" est invalide pour %3$s"
-
-#, c-format
-msgid "option \"%s\" is ignored for %s\n"
-msgstr "l'option \"%s\" est ignorée pour %s\n"
-
-#, c-format
-msgid "%s is not a valid object"
-msgstr "%s n'est pas un objet valide"
-
-#, c-format
-msgid "the object %s does not exist"
-msgstr "l'objet %s n'existe pas"
-
-msgid "multiple branches detected, incompatible with --set-upstream"
-msgstr "branches multiples détectées, imcompatible avec --set-upstream"
-
-#, c-format
-msgid ""
-"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
-"any branch."
-msgstr ""
-"impossible de régler la branche amont de HEAD à '%s' depuis '%s' qui ne "
-"pointe sur aucune branche."
-
-msgid "not setting upstream for a remote remote-tracking branch"
-msgstr "dépôt amont non défini pour la branche de suivi à distance"
-
-msgid "not setting upstream for a remote tag"
-msgstr "dépôt amont non défini pour l'étiquette distante"
-
-msgid "unknown branch type"
-msgstr "type de branche inconnu"
-
-msgid ""
-"no source branch found;\n"
-"you need to specify exactly one branch with the --set-upstream option"
-msgstr ""
-"aucune branche source trouvée.\n"
-"Vous devez spécifier exactement une branche avec l'option --set-upstream"
-
-#, c-format
-msgid "Fetching %s\n"
-msgstr "Récupération de %s\n"
-
-#, c-format
-msgid "could not fetch %s"
-msgstr "impossible de récupérer %s"
-
-#, c-format
-msgid "could not fetch '%s' (exit code: %d)\n"
-msgstr "impossible de récupérer '%s' (code de sortie : %d)\n"
-
-msgid ""
-"no remote repository specified; please specify either a URL or a\n"
-"remote name from which new revisions should be fetched"
-msgstr ""
-"Aucun dépôt distant spécifié. Veuillez spécifier une URL ou un nom\n"
-"distant depuis lesquels les nouvelles révisions devraient être récupérées"
-
-msgid "you need to specify a tag name"
-msgstr "Vous devez spécifier un nom d'étiquette"
-
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr "--negotiate-only nécessite au moins un --negotiation-tip=*"
 
@@ -6238,6 +6276,12 @@
 msgid "print only refs which don't contain the commit"
 msgstr "afficher seulement les références qui ne contiennent pas le commit"
 
+msgid "read reference patterns from stdin"
+msgstr "lire les motifs de références depuis l'entrée standard"
+
+msgid "unknown arguments supplied with --stdin"
+msgstr "arguments inconnus fournis avec l'option --stdin"
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<config> [--] <arguments>"
 
@@ -6250,6 +6294,10 @@
 msgid "missing --config=<config>"
 msgstr "--config=<config> manquant"
 
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "config incorrecte --config=%s"
+
 msgid "unknown"
 msgstr "inconnu"
 
@@ -6396,19 +6444,28 @@
 msgid "notice: %s points to an unborn branch (%s)"
 msgstr "note : %s pointe sur une branche non-née (%s)"
 
-msgid "Checking cache tree"
-msgstr "Vérification de l'arbre cache"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "Vérification de l'arbre cache de %s"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "%s : pointer sha1 invalide dans l'arbre de cache"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s : pointer sha1 invalide dans l'arbre de cache de %s"
 
 msgid "non-tree in cache-tree"
 msgstr "non-arbre dans l'arbre de cache"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in resolve-undo"
-msgstr "%s : pointeur sha1 invalide dans resolve-undo"
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s : pointeur sha1 invalide dans resolve-undo de %s"
+
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "impossible de charger le rev-index pour le paquet '%s'"
+
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "rev-index invalide pour le paquet '%s'"
 
 msgid ""
 "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
@@ -9321,6 +9378,12 @@
 msgid "bad index version '%s'"
 msgstr "mauvaise version d'index '%s'"
 
+msgid "show progress meter during object writing phase"
+msgstr "afficher la barre de progression durant la phase d'écrite des objets"
+
+msgid "similar to --all-progress when progress meter is shown"
+msgstr "similaire à --all-progress quand la barre de progression est affichée"
+
 msgid "<version>[,<offset>]"
 msgstr "<version>[,<décalage>]"
 
@@ -9518,6 +9581,9 @@
 "sur la ligne de commande pour nous avertir par\n"
 "un courriel à <git@vger.kernel.org>. Merci.\n"
 
+msgid "refusing to run without --i-still-use-this"
+msgstr "refus de lancer sans --i-still-use-this"
+
 msgid "git pack-refs [--all] [--no-prune]"
 msgstr "git pack-refs [--all] [--no-prune]"
 
@@ -9694,8 +9760,8 @@
 msgid "pull with rebase"
 msgstr "tirer avec un rebasage"
 
-msgid "please commit or stash them."
-msgstr "veuillez les valider ou les remiser."
+msgid "Please commit or stash them."
+msgstr "Veuillez les valider ou les remiser."
 
 #, c-format
 msgid ""
@@ -9946,8 +10012,8 @@
 msgid "repository"
 msgstr "dépôt"
 
-msgid "push all refs"
-msgstr "pousser toutes les références"
+msgid "push all branches"
+msgstr "pousser toutes les branches"
 
 msgid "mirror all refs"
 msgstr "refléter toutes les références"
@@ -9955,9 +10021,10 @@
 msgid "delete refs"
 msgstr "supprimer les références"
 
-msgid "push tags (can't be used with --all or --mirror)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
 msgstr ""
-"pousser les étiquettes (ne peut pas être utilisé avec --all ou --mirror)"
+"pousser les étiquettes (ne peut pas être utilisé avec --all, --branches ou --"
+"mirror)"
 
 msgid "force updates"
 msgstr "forcer les mises à jour"
@@ -10225,6 +10292,10 @@
 "Résultat, git ne peut pas les rebaser."
 
 #, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "Mode de rebase-merges inconnu : %s"
+
+#, c-format
 msgid "could not switch to %s"
 msgstr "impossible de basculer vers %s"
 
@@ -10240,6 +10311,15 @@
 "type vide non connu '%s' ; les valeurs valides sont \"drop\" (abandonner), "
 "\"keep\" (garder) et \"ask\" (demander)."
 
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"--rebase-merges avec un argument chaîne vide est obsolète et cessera de "
+"fonctionner dans une version future de Git. Utilisez à la place --rebase-"
+"merges sans argument, qui a le même effet."
+
 #, c-format
 msgid ""
 "%s\n"
@@ -10460,21 +10540,24 @@
 msgid "switch `C' expects a numerical value"
 msgstr "l'option `C' attend un valeur numérique"
 
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "Mode inconnu : %s"
-
 msgid "--strategy requires --merge or --interactive"
 msgstr "--strategy requiert --merge ou --interactive"
 
 msgid ""
-"apply options are incompatible with rebase.autosquash.  Consider adding --no-"
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
 "autosquash"
 msgstr ""
-"les options d'application sont incompatibles avec rebase.autosquash. "
+"les options d'application sont incompatibles avec rebase.autoSquash. "
 "Considérez l'ajout de --no-autosquash"
 
 msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr ""
+"les options d'application sont incompatibles avec rebase.rebaseMerges. "
+"Considérez l'ajout de --no-rebase-merges"
+
+msgid ""
 "apply options are incompatible with rebase.updateRefs.  Consider adding --no-"
 "update-refs"
 msgstr ""
@@ -10518,9 +10601,6 @@
 msgid "Does not point to a valid commit '%s'"
 msgstr "Ne pointe pas sur une validation valide : '%s'"
 
-msgid "Please commit or stash them."
-msgstr "Veuillez les valider ou les remiser."
-
 msgid "HEAD is up to date."
 msgstr "HEAD est à jour."
 
@@ -11197,8 +11277,8 @@
 msgid "approxidate"
 msgstr "date approximative"
 
-msgid "with -C, expire objects older than this"
-msgstr "avec -C, faire expirer les objets plus vieux que celui-ci"
+msgid "with --cruft, expire objects older than this"
+msgstr "avec --cruft, faire expirer les objets plus vieux que celui-ci"
 
 msgid "remove redundant packs, and run git-prune-packed"
 msgstr "supprimer les paquets redondants et lancer git-prune-packed"
@@ -11871,6 +11951,9 @@
 msgid "remote name"
 msgstr "nom distant"
 
+msgid "push all refs"
+msgstr "pousser toutes les références"
+
 msgid "use stateless RPC protocol"
 msgstr "utiliser un protocole RPC sans état"
 
@@ -12081,9 +12164,11 @@
 "local"
 
 msgid ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 
 msgid "this worktree is not sparse"
 msgstr "cet arbre de travail n'est pas clairsemé"
@@ -12213,6 +12298,24 @@
 msgid "error while refreshing working directory"
 msgstr "erreur lors du rafraîchissement du répertoire de travail"
 
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <fichier>]"
+
+msgid "terminate input and output files by a NUL character"
+msgstr "terminer les fichiers en entrée et en sortie par un caractère NUL"
+
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr ""
+"quand utilisé avec --rules-file, interpréter les motifs comme des motifs en "
+"mode cone"
+
+msgid "use patterns in <file> instead of the current ones."
+msgstr "utiliser les motifs dans <fichier> plutôt que les actuels."
+
 msgid "git stash list [<log-options>]"
 msgstr "git stash list [<options-de-log>]"
 
@@ -12419,7 +12522,7 @@
 msgstr "remiser seulement les modifications indexées"
 
 msgid "stash in patch mode"
-msgstr "remiser une mode rustine"
+msgstr "remiser en mode rustine"
 
 msgid "quiet mode"
 msgstr "mode silencieux"
@@ -15146,8 +15249,8 @@
 msgid "bad zlib compression level %d"
 msgstr "niveau de compression zlib incorrect %d"
 
-msgid "core.commentChar should only be one character"
-msgstr "core.commentChar ne devrait être qu'un unique caractère"
+msgid "core.commentChar should only be one ASCII character"
+msgstr "core.commentChar ne devrait être qu'un unique caractère ASCII"
 
 #, c-format
 msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15262,6 +15365,12 @@
 msgstr "nom de section invalide : %s"
 
 #, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr ""
+"refus de travailler avec des lignes trop longues dans '%s' à la ligne "
+"%<PRIuMAX>"
+
+#, c-format
 msgid "missing value for '%s'"
 msgstr "valeur manquante pour '%s'"
 
@@ -15950,6 +16059,9 @@
 msgid "do not show any source or destination prefix"
 msgstr "n'afficher aucun préfixe, ni de source, ni de destination"
 
+msgid "use default prefixes a/ and b/"
+msgstr "utiliser les préfixes par défaut a/ et b/"
+
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr ""
 "afficher le contexte entre les sections à concurrence du nombre de ligne "
@@ -16271,6 +16383,14 @@
 "suggestion : en attente de la fermeture du fichier par votre éditeur de "
 "texte…%c"
 
+#, c-format
+msgid "could not write to '%s'"
+msgstr "impossible d'écrire dans '%s'"
+
+#, c-format
+msgid "could not edit '%s'"
+msgstr "impossible d'éditer '%s'"
+
 msgid "Filtering content"
 msgstr "Filtrage du contenu"
 
@@ -16570,6 +16690,10 @@
 msgstr "aucune clé de configuration fournie pour --config-env\n"
 
 #, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "aucune source d'attribut fournie pour --attr-source\n"
+
+#, c-format
 msgid "unknown option: %s\n"
 msgstr "option inconnue : %s\n"
 
@@ -18265,6 +18389,10 @@
 msgstr "impossible de récupérer l'utilisation du disque de '%s'"
 
 #, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "le fichier bitmap '%s' a une somme de contrôle invalide"
+
+#, c-format
 msgid "mtimes file %s is too small"
 msgstr "le fichier de mtimes %s est trop petit"
 
@@ -18304,6 +18432,13 @@
 msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
 msgstr "le fichier d'index inverse %s a un id d'empreinte non géré %<PRIu32>"
 
+msgid "invalid checksum"
+msgstr "somme de contrôle invalide"
+
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr "position de rev-index invalide à %<PRIu64> : %<PRIu32> != %<PRIu32>"
+
 msgid "cannot both write and verify reverse index"
 msgstr "impossible de lire et vérifier à la fois l'index inverse"
 
@@ -19038,6 +19173,10 @@
 msgstr "valeur positive attendue avec l'atome %%(align)"
 
 #, c-format
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "format attendu : %%(ahead-behind:<commit-esque>)"
+
+#, c-format
 msgid "malformed field name: %.*s"
 msgstr "nom de champ malformé %.*s"
 
@@ -19672,10 +19811,6 @@
 msgstr "aucune résolution enregistrée pour '%s'"
 
 #, c-format
-msgid "cannot unlink '%s'"
-msgstr "impossible de délier '%s'"
-
-#, c-format
 msgid "Updated preimage for '%s'"
 msgstr "Pré-image mise à jour pour '%s'"
 
@@ -20014,10 +20149,6 @@
 msgstr "impossible de verrouiller '%s'"
 
 #, c-format
-msgid "could not write to '%s'"
-msgstr "impossible d'écrire dans '%s'"
-
-#, c-format
 msgid "could not write eol to '%s'"
 msgstr "impossible d'écrire la fin de ligne dans '%s'"
 
@@ -20382,9 +20513,6 @@
 msgid "could not create sequencer directory '%s'"
 msgstr "impossible de créer le répertoire de séquenceur '%s'"
 
-msgid "could not lock HEAD"
-msgstr "impossible de verrouiller HEAD"
-
 msgid "no cherry-pick or revert in progress"
 msgstr "aucun picorage ou retour en cours"
 
@@ -20480,20 +20608,20 @@
 "git rebase --continue\n"
 "\n"
 
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "et a mis à jour l'index ou l'arbre de travail\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "et a mis à jour l'index ou l'arbre de travail.\n"
 
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
 msgstr ""
 "l'exécution a réussi : %s\n"
-"mais a laissé des modifications dans l'index ou la copie de travail\n"
+"mais a laissé des modifications dans l'index ou la copie de travail.\n"
 "Validez ou remisez vos modification, puis lancez\n"
 "\n"
 "  git rebase --continue\n"
@@ -20937,10 +21065,6 @@
 msgstr[1] "%u octets/s"
 
 #, c-format
-msgid "could not edit '%s'"
-msgstr "impossible d'éditer '%s'"
-
-#, c-format
 msgid "ignoring suspicious submodule name: %s"
 msgstr "nom de sous-module suspicieux %s ignoré"
 
@@ -22698,13 +22822,17 @@
 msgstr "(%s) Impossible d'exécuter '%s'"
 
 #, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) Ajout de %s : %s depuis : '%s'\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) Sortie malformée depuis '%s'"
 
 #, perl-format
 msgid "(%s) failed to close pipe to '%s'"
 msgstr "(%s) échec de la fermeture du pipe vers '%s'"
 
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) Ajout de %s : %s depuis : '%s'\n"
+
 msgid "cannot send message as 7bit"
 msgstr "impossible d'envoyer un message comme 7bit"
 
@@ -22741,3 +22869,19 @@
 #, perl-format
 msgid "Do you really want to send %s? [y|N]: "
 msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : "
+
+#~ msgid "current working directory is untracked"
+#~ msgstr "l'arbre de travail actuel est non-suivi"
+
+#~ msgid "cannot use --contents with final commit object name"
+#~ msgstr "on ne peut pas utiliser --contents avec un nom d'objet commit final"
+
+#~ msgid "please commit or stash them."
+#~ msgstr "veuillez les valider ou les remiser."
+
+#, c-format
+#~ msgid "Unknown mode: %s"
+#~ msgstr "Mode inconnu : %s"
+
+#~ msgid "could not lock HEAD"
+#~ msgstr "impossible de verrouiller HEAD"
diff --git a/po/id.po b/po/id.po
index e468b6d..ccd3842 100644
--- a/po/id.po
+++ b/po/id.po
@@ -7,8 +7,8 @@
 msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-03-02 15:18+0700\n"
-"PO-Revision-Date: 2023-03-02 17:52+0700\n"
+"POT-Creation-Date: 2023-05-19 19:57+0000\n"
+"PO-Revision-Date: 2023-05-22 15:24+0700\n"
 "Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n"
 "Language-Team: Indonesian\n"
 "Language: id\n"
@@ -793,6 +793,25 @@
 msgstr "Keluar karena penggabungan belum selesai."
 
 #: advice.c
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"Cabang yang menyebar tidak dapat dimajucepatkan, Anda perlu salah satu "
+"dari:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"atau:\n"
+"\n"
+"\tgit rebase\n"
+
+#: advice.c
 msgid "Not possible to fast-forward, aborting."
 msgstr "Tidak mungkin untuk maju cepat, batalkan."
 
@@ -1339,6 +1358,11 @@
 msgid "cannot open %s"
 msgstr "tidak dapat membuka %s"
 
+#: apply.c rerere.c
+#, c-format
+msgid "cannot unlink '%s'"
+msgstr "tidak dapat batal taut '%s'"
+
 #: apply.c
 #, c-format
 msgid "Hunk #%d applied cleanly."
@@ -1579,6 +1603,11 @@
 msgid "cannot read '%s'"
 msgstr "tidak dapat membaca '%s'"
 
+#: archive.c
+#, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr "spek jalur '%s' mencocoki berkas di luar direktori saat ini"
+
 #: archive.c builtin/add.c builtin/rm.c
 #, c-format
 msgid "pathspec '%s' did not match any files"
@@ -1600,10 +1629,6 @@
 msgstr "bukan objek pohon: %s"
 
 #: archive.c
-msgid "current working directory is untracked"
-msgstr "direktori kerja saat ini tak terlacak"
-
-#: archive.c
 #, c-format
 msgid "File not found: %s"
 msgstr "Berkas tidak ditemukan: %s"
@@ -1771,6 +1796,10 @@
 msgid "ignoring overly large gitattributes blob '%s'"
 msgstr "mengabaikan blob gitattributes '%s' yang terlalu besar"
 
+#: attr.c
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr "--attr-source atau GIT_ATTR_SOURCE jelek"
+
 #: bisect.c
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
@@ -1895,17 +1924,13 @@
 msgstr "--contents dan --reverse tidak dapat dipadu dengan baik."
 
 #: blame.c
-msgid "cannot use --contents with final commit object name"
-msgstr "tidak dapat menggunakan --contents dengan nama objek komit final"
-
-#: blame.c
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr ""
 "--reverse dan --first-parent bersama-sama butuh komit terbaru yang disebutkan"
 
 #: blame.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c ref-filter.c
-#: remote.c sequencer.c submodule.c
+#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c remote.c
+#: sequencer.c submodule.c
 msgid "revision walk setup failed"
 msgstr "persiapan jalan revisi gagal"
 
@@ -2111,11 +2136,6 @@
 msgid "'%s' is already checked out at '%s'"
 msgstr "'%s' sudah di-checkout pada '%s'"
 
-#: branch.c
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "HEAD dari pohon kerja %s tidak diperbarui"
-
 #: builtin/add.c
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<opsi>] [--] <pathspec>..."
@@ -2386,7 +2406,7 @@
 msgid "could not open '%s' for reading"
 msgstr "tidak dapat membuka '%s' untuk dibaca"
 
-#: builtin/am.c builtin/rebase.c sequencer.c strbuf.c wrapper.c
+#: builtin/am.c builtin/rebase.c editor.c sequencer.c wrapper.c
 #, c-format
 msgid "could not open '%s' for writing"
 msgstr "tidak dapat membuka '%s' untuk ditulis"
@@ -3431,6 +3451,15 @@
 
 #: builtin/branch.c
 #, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"cabang '%s' tidak ditemukan.\n"
+"Mungkin anda lupa menambahkan --remote?"
+
+#: builtin/branch.c
+#, c-format
 msgid "branch '%s' not found."
 msgstr "cabang '%s' tidak ditemukan."
 
@@ -3469,6 +3498,11 @@
 
 #: builtin/branch.c
 #, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "HEAD dari pohon kerja %s tidak diperbarui"
+
+#: builtin/branch.c
+#, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "Nama cabang tidak valid: '%s'"
 
@@ -3596,6 +3630,10 @@
 msgid "move/rename a branch, even if target exists"
 msgstr "pindah/ganti nama cabang, walaupun target ada"
 
+#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c
+msgid "do not output a newline after empty formatted refs"
+msgstr "jangan keluarkan baris baru setelah referensi terformat kosong"
+
 #: builtin/branch.c
 msgid "copy a branch and its reflog"
 msgstr "salin cabang dan reflog-nya"
@@ -3872,12 +3910,10 @@
 
 #: builtin/bundle.c
 msgid ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [-all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<versi>] <berkas> <argumen git-rev-list>"
 
 #: builtin/bundle.c
@@ -3904,13 +3940,13 @@
 msgid "show progress meter"
 msgstr "perlihatkan meteran perkembangan"
 
-#: builtin/bundle.c builtin/pack-objects.c
-msgid "show progress meter during object writing phase"
-msgstr "perlihatkan meteran perkembangan saat fase penulisan objek"
+#: builtin/bundle.c
+msgid "historical; same as --progress"
+msgstr "opsi bersejarah; sama dengan --progress"
 
-#: builtin/bundle.c builtin/pack-objects.c
-msgid "similar to --all-progress when progress meter is shown"
-msgstr "sama seperti --all-progress ketika meteran perkembangan diperlihatkan"
+#: builtin/bundle.c
+msgid "historical; does nothing"
+msgstr "opsi bersejarah: tidak apa-apa"
 
 #: builtin/bundle.c
 msgid "specify bundle format version"
@@ -5181,6 +5217,11 @@
 
 #: builtin/clone.c
 #, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "'%s' tautan simbolik, menolak mengkloning dengan --local"
+
+#: builtin/clone.c
+#, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "gagal memulai iterator pada '%s'"
 
@@ -5983,7 +6024,7 @@
 msgid "version"
 msgstr "versi"
 
-#: builtin/commit.c builtin/push.c builtin/worktree.c
+#: builtin/commit.c builtin/fetch.c builtin/push.c builtin/worktree.c
 msgid "machine-readable output"
 msgstr "keluaran yang dapat dibaca mesin"
 
@@ -7078,6 +7119,216 @@
 msgid "fetch.parallel cannot be negative"
 msgstr "fetch.parallel tidak dapat bernilai negatif"
 
+#: builtin/fetch.c
+msgid "couldn't find remote ref HEAD"
+msgstr "tidak dapat menemukan referensi remote HEAD"
+
+#: builtin/fetch.c
+#, c-format
+msgid "From %.*s\n"
+msgstr "Dari %.*s\n"
+
+#: builtin/fetch.c
+#, c-format
+msgid "object %s not found"
+msgstr "objek %s tidak ditemukan"
+
+#: builtin/fetch.c
+msgid "[up to date]"
+msgstr "[terkini]"
+
+#: builtin/fetch.c
+msgid "[rejected]"
+msgstr "[tertolak]"
+
+#: builtin/fetch.c
+msgid "can't fetch into checked-out branch"
+msgstr "tidak dapat mengambil ke dalam cabang ter-checkout"
+
+#: builtin/fetch.c
+msgid "[tag update]"
+msgstr "[pembaruan tag]"
+
+#: builtin/fetch.c
+msgid "unable to update local ref"
+msgstr "tidak dapat memperbarui referensi lokal"
+
+#: builtin/fetch.c
+msgid "would clobber existing tag"
+msgstr "akan klob tag yang ada"
+
+#: builtin/fetch.c
+msgid "[new tag]"
+msgstr "[tag baru]"
+
+#: builtin/fetch.c
+msgid "[new branch]"
+msgstr "[cabang baru]"
+
+#: builtin/fetch.c
+msgid "[new ref]"
+msgstr "[referensi baru]"
+
+#: builtin/fetch.c
+msgid "forced update"
+msgstr "pembaruan terpaksa"
+
+#: builtin/fetch.c
+msgid "non-fast-forward"
+msgstr "bukan-maju-cepat"
+
+#: builtin/fetch.c builtin/grep.c sequencer.c
+#, c-format
+msgid "cannot open '%s'"
+msgstr "tidak dapat membuka '%s'"
+
+#: builtin/fetch.c
+msgid ""
+"fetch normally indicates which branches had a forced update,\n"
+"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
+"flag or run 'git config fetch.showForcedUpdates true'"
+msgstr ""
+"fetch secara normal mengindikasikan cabang mana ada pembaruan terpaksa,\n"
+"tapi pemeriksaan tersebut sudah dinonaktifkan. Untuk aktifkan kembali, "
+"gunakan\n"
+"bendera '--show-forced-updates' atau jalankan 'git config fetch."
+"showForcedUpdates true'."
+
+#: builtin/fetch.c
+#, c-format
+msgid ""
+"it took %.2f seconds to check forced updates; you can use\n"
+"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
+"false'\n"
+"to avoid this check\n"
+msgstr ""
+"Butuh waktu %2.f detik untuk memeriksa pembaruan terpaksa; Anda dapat\n"
+"menggunakan '--no-show-forced-updates' atau jalankan\n"
+"'git config fetch.showForcedUpdates false'\n"
+"untuk menghindari pemeriksaan ini.\n"
+
+#: builtin/fetch.c
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s tidak mengirim semua objek yang diperlukan\n"
+
+#: builtin/fetch.c
+#, c-format
+msgid "rejected %s because shallow roots are not allowed to be updated"
+msgstr "tolak %s karena akar dangkal tidak diperkenankan untuk diperbarui"
+
+#: builtin/fetch.c
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+"beberapa referensi lokal tidak dapat diperbarui; coba jalankan\n"
+" 'git remote prune %s' untuk hapus cabang yang lama dan berkonflik"
+
+#: builtin/fetch.c
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr "   (%s akan menjadi terjuntai)"
+
+#: builtin/fetch.c
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr "   (%s telah menjadi terjuntai)"
+
+#: builtin/fetch.c
+msgid "[deleted]"
+msgstr "[dihapus]"
+
+#: builtin/fetch.c builtin/remote.c
+msgid "(none)"
+msgstr "(tidak ada)"
+
+#: builtin/fetch.c
+#, c-format
+msgid "refusing to fetch into branch '%s' checked out at '%s'"
+msgstr "menolak mengambil ke dalam cabang '%s' yang ter-checkout pada '%s'"
+
+#: builtin/fetch.c
+#, c-format
+msgid "option \"%s\" value \"%s\" is not valid for %s"
+msgstr "opsi \"%s\" nilai \"%s\" tidak valid untuk %s"
+
+#: builtin/fetch.c
+#, c-format
+msgid "option \"%s\" is ignored for %s\n"
+msgstr "opsi \"%s\" diabaikan untuk %s\n"
+
+#: builtin/fetch.c object-file.c
+#, c-format
+msgid "%s is not a valid object"
+msgstr "%s bukan sebuah objek valid"
+
+#: builtin/fetch.c
+#, c-format
+msgid "the object %s does not exist"
+msgstr "objek '%s' tidak ada"
+
+#: builtin/fetch.c
+msgid "multiple branches detected, incompatible with --set-upstream"
+msgstr "banyak cabang terdeteksi, tidak kompatibel dengan --set-upstream"
+
+#: builtin/fetch.c
+#, c-format
+msgid ""
+"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
+"any branch."
+msgstr ""
+"tidak dapat menyetel hulu HEAD ke %s dari '%s' ketika itu tak menunjuk pada "
+"cabang apapun."
+
+#: builtin/fetch.c
+msgid "not setting upstream for a remote remote-tracking branch"
+msgstr "tidak setel hulu untuk cabang remote pelacak remote"
+
+#: builtin/fetch.c
+msgid "not setting upstream for a remote tag"
+msgstr "tidak setel hulu untuk tag remote"
+
+#: builtin/fetch.c
+msgid "unknown branch type"
+msgstr "tipe cabang tidak diketahui"
+
+#: builtin/fetch.c
+msgid ""
+"no source branch found;\n"
+"you need to specify exactly one branch with the --set-upstream option"
+msgstr ""
+"cabang sumber tidak ditemukan;\n"
+"Anda harus sebutkan tepat satu cabang dengan opsi --set-upstream."
+
+#: builtin/fetch.c
+#, c-format
+msgid "Fetching %s\n"
+msgstr "Mengambil %s\n"
+
+#: builtin/fetch.c
+#, c-format
+msgid "could not fetch %s"
+msgstr "tidak dapat mengambil %s"
+
+#: builtin/fetch.c
+#, c-format
+msgid "could not fetch '%s' (exit code: %d)\n"
+msgstr "tidak dapat mengambil '%s' (kode keluar: %d)\n"
+
+#: builtin/fetch.c
+msgid ""
+"no remote repository specified; please specify either a URL or a\n"
+"remote name from which new revisions should be fetched"
+msgstr ""
+"repositori remote tidak disebutkan; mohon sebutkan baik URL atau nama\n"
+"remote yang mana revisi baru sebaiknya diambil"
+
+#: builtin/fetch.c
+msgid "you need to specify a tag name"
+msgstr "Anda perlu sebutkan sebuah nama tag"
+
 #: builtin/fetch.c builtin/pull.c
 msgid "fetch from all remotes"
 msgstr "ambil dari semua remote"
@@ -7219,216 +7470,6 @@
 msgstr "terima spek referensi dari masukan standar"
 
 #: builtin/fetch.c
-msgid "couldn't find remote ref HEAD"
-msgstr "tidak dapat menemukan referensi remote HEAD"
-
-#: builtin/fetch.c
-#, c-format
-msgid "object %s not found"
-msgstr "objek %s tidak ditemukan"
-
-#: builtin/fetch.c
-msgid "[up to date]"
-msgstr "[terkini]"
-
-#: builtin/fetch.c
-msgid "[rejected]"
-msgstr "[tertolak]"
-
-#: builtin/fetch.c
-msgid "can't fetch into checked-out branch"
-msgstr "tidak dapat mengambil ke dalam cabang ter-checkout"
-
-#: builtin/fetch.c
-msgid "[tag update]"
-msgstr "[pembaruan tag]"
-
-#: builtin/fetch.c
-msgid "unable to update local ref"
-msgstr "tidak dapat memperbarui referensi lokal"
-
-#: builtin/fetch.c
-msgid "would clobber existing tag"
-msgstr "akan klob tag yang ada"
-
-#: builtin/fetch.c
-msgid "[new tag]"
-msgstr "[tag baru]"
-
-#: builtin/fetch.c
-msgid "[new branch]"
-msgstr "[cabang baru]"
-
-#: builtin/fetch.c
-msgid "[new ref]"
-msgstr "[referensi baru]"
-
-#: builtin/fetch.c
-msgid "forced update"
-msgstr "pembaruan terpaksa"
-
-#: builtin/fetch.c
-msgid "non-fast-forward"
-msgstr "bukan-maju-cepat"
-
-#: builtin/fetch.c builtin/grep.c sequencer.c
-#, c-format
-msgid "cannot open '%s'"
-msgstr "tidak dapat membuka '%s'"
-
-#: builtin/fetch.c
-msgid ""
-"fetch normally indicates which branches had a forced update,\n"
-"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
-"flag or run 'git config fetch.showForcedUpdates true'"
-msgstr ""
-"fetch secara normal mengindikasikan cabang mana ada pembaruan terpaksa,\n"
-"tapi pemeriksaan tersebut sudah dinonaktifkan. Untuk aktifkan kembali, "
-"gunakan\n"
-"bendera '--show-forced-updates' atau jalankan 'git config fetch."
-"showForcedUpdates true'."
-
-#: builtin/fetch.c
-#, c-format
-msgid ""
-"it took %.2f seconds to check forced updates; you can use\n"
-"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
-"false'\n"
-"to avoid this check\n"
-msgstr ""
-"Butuh waktu %2.f detik untuk memeriksa pembaruan terpaksa; Anda dapat\n"
-"menggunakan '--no-show-forced-updates' atau jalankan\n"
-"'git config fetch.showForcedUpdates false'\n"
-"untuk menghindari pemeriksaan ini.\n"
-
-#: builtin/fetch.c
-#, c-format
-msgid "%s did not send all necessary objects\n"
-msgstr "%s tidak mengirim semua objek yang diperlukan\n"
-
-#: builtin/fetch.c
-#, c-format
-msgid "rejected %s because shallow roots are not allowed to be updated"
-msgstr "tolak %s karena akar dangkal tidak diperkenankan untuk diperbarui"
-
-#: builtin/fetch.c
-#, c-format
-msgid "From %.*s\n"
-msgstr "Dari %.*s\n"
-
-#: builtin/fetch.c
-#, c-format
-msgid ""
-"some local refs could not be updated; try running\n"
-" 'git remote prune %s' to remove any old, conflicting branches"
-msgstr ""
-"beberapa referensi lokal tidak dapat diperbarui; coba jalankan\n"
-" 'git remote prune %s' untuk hapus cabang yang lama dan berkonflik"
-
-#: builtin/fetch.c
-#, c-format
-msgid "   (%s will become dangling)"
-msgstr "   (%s akan menjadi terjuntai)"
-
-#: builtin/fetch.c
-#, c-format
-msgid "   (%s has become dangling)"
-msgstr "   (%s telah menjadi terjuntai)"
-
-#: builtin/fetch.c
-msgid "[deleted]"
-msgstr "[dihapus]"
-
-#: builtin/fetch.c builtin/remote.c
-msgid "(none)"
-msgstr "(tidak ada)"
-
-#: builtin/fetch.c
-#, c-format
-msgid "refusing to fetch into branch '%s' checked out at '%s'"
-msgstr "menolak mengambil ke dalam cabang '%s' yang ter-checkout pada '%s'"
-
-#: builtin/fetch.c
-#, c-format
-msgid "option \"%s\" value \"%s\" is not valid for %s"
-msgstr "opsi \"%s\" nilai \"%s\" tidak valid untuk %s"
-
-#: builtin/fetch.c
-#, c-format
-msgid "option \"%s\" is ignored for %s\n"
-msgstr "opsi \"%s\" diabaikan untuk %s\n"
-
-#: builtin/fetch.c object-file.c
-#, c-format
-msgid "%s is not a valid object"
-msgstr "%s bukan sebuah objek valid"
-
-#: builtin/fetch.c
-#, c-format
-msgid "the object %s does not exist"
-msgstr "objek '%s' tidak ada"
-
-#: builtin/fetch.c
-msgid "multiple branches detected, incompatible with --set-upstream"
-msgstr "banyak cabang terdeteksi, tidak kompatibel dengan --set-upstream"
-
-#: builtin/fetch.c
-#, c-format
-msgid ""
-"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
-"any branch."
-msgstr ""
-"tidak dapat menyetel hulu HEAD ke %s dari '%s' ketika itu tak menunjuk pada "
-"cabang apapun."
-
-#: builtin/fetch.c
-msgid "not setting upstream for a remote remote-tracking branch"
-msgstr "tidak setel hulu untuk cabang remote pelacak remote"
-
-#: builtin/fetch.c
-msgid "not setting upstream for a remote tag"
-msgstr "tidak setel hulu untuk tag remote"
-
-#: builtin/fetch.c
-msgid "unknown branch type"
-msgstr "tipe cabang tidak diketahui"
-
-#: builtin/fetch.c
-msgid ""
-"no source branch found;\n"
-"you need to specify exactly one branch with the --set-upstream option"
-msgstr ""
-"cabang sumber tidak ditemukan;\n"
-"Anda harus sebutkan tepat satu cabang dengan opsi --set-upstream."
-
-#: builtin/fetch.c
-#, c-format
-msgid "Fetching %s\n"
-msgstr "Mengambil %s\n"
-
-#: builtin/fetch.c
-#, c-format
-msgid "could not fetch %s"
-msgstr "tidak dapat mengambil %s"
-
-#: builtin/fetch.c
-#, c-format
-msgid "could not fetch '%s' (exit code: %d)\n"
-msgstr "tidak dapat mengambil '%s' (kode keluar: %d)\n"
-
-#: builtin/fetch.c
-msgid ""
-"no remote repository specified; please specify either a URL or a\n"
-"remote name from which new revisions should be fetched"
-msgstr ""
-"repositori remote tidak disebutkan; mohon sebutkan baik URL atau nama\n"
-"remote yang mana revisi baru sebaiknya diambil"
-
-#: builtin/fetch.c
-msgid "you need to specify a tag name"
-msgstr "Anda perlu sebutkan sebuah nama tag"
-
-#: builtin/fetch.c
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr "--negotiate-only perlu satu atau lebih --negotiation-tip=*"
 
@@ -7576,6 +7617,14 @@
 msgid "print only refs which don't contain the commit"
 msgstr "hanya cetak referensi yang tidak berisi komit"
 
+#: builtin/for-each-ref.c
+msgid "read reference patterns from stdin"
+msgstr "baca pola referensi dari masukan standar"
+
+#: builtin/for-each-ref.c
+msgid "unknown arguments supplied with --stdin"
+msgstr "argumen tidak dikenal diberikan dengan --stdin"
+
 #: builtin/for-each-repo.c
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<konfigurasi> [--] <argumen perintah>"
@@ -7592,6 +7641,11 @@
 msgid "missing --config=<config>"
 msgstr "kehilangan --config=<config>"
 
+#: builtin/for-each-repo.c
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "dapat konfigurasi jelek --config=%s"
+
 #: builtin/fsck.c
 msgid "unknown"
 msgstr "tidak dikenal"
@@ -7777,13 +7831,14 @@
 msgstr "catatan: %s menunjuk ke cabang yang belum lahir (%s)"
 
 #: builtin/fsck.c
-msgid "Checking cache tree"
-msgstr "Memeriksa pohon tembolok"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "Memeriksa pohon tembolok %s"
 
 #: builtin/fsck.c
 #, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "%s: penunjuk sha1 tidak valid pada pohon tembolok"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s: penunjuk sha1 tidak valid pada pohon tembolok %s"
 
 #: builtin/fsck.c
 msgid "non-tree in cache-tree"
@@ -7791,8 +7846,18 @@
 
 #: builtin/fsck.c
 #, c-format
-msgid "%s: invalid sha1 pointer in resolve-undo"
-msgstr "%s: penunjuk sha1 tidak valid di resolve-undo"
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s: penunjuk sha1 tidak valid di resolve-undo %s"
+
+#: builtin/fsck.c
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "tidak dapat memuat indeks balik untuk pak '%s'"
+
+#: builtin/fsck.c
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "indeks balik tidak valid untuk pak '%s'"
 
 #: builtin/fsck.c
 msgid ""
@@ -10422,7 +10487,7 @@
 msgid "Bad value '%s' in environment '%s'"
 msgstr "Nilai jelek '%s' dalam lingkungan '%s'"
 
-#: builtin/merge.c read-cache.c strbuf.c wrapper.c
+#: builtin/merge.c editor.c read-cache.c wrapper.c
 #, c-format
 msgid "could not close '%s'"
 msgstr "tidak dapat menutup '%s'"
@@ -11278,7 +11343,7 @@
 msgid "wrote %<PRIu32> objects while expecting %<PRIu32>"
 msgstr "%<PRIu32> objek ditulish ketika mengharapkan %<PRIu32>"
 
-#: builtin/pack-objects.c
+#: builtin/pack-objects.c builtin/repack.c
 msgid "disabling bitmap writing, as some objects are not being packed"
 msgstr "menonaktifkan penulisan bitmap, saat beberapa objek tidak sedang dipak"
 
@@ -11447,6 +11512,14 @@
 msgstr "versi indeks jelek '%s'"
 
 #: builtin/pack-objects.c
+msgid "show progress meter during object writing phase"
+msgstr "perlihatkan meteran perkembangan saat fase penulisan objek"
+
+#: builtin/pack-objects.c
+msgid "similar to --all-progress when progress meter is shown"
+msgstr "sama seperti --all-progress ketika meteran perkembangan diperlihatkan"
+
+#: builtin/pack-objects.c
 msgid "<version>[,<offset>]"
 msgstr "<versi>[,<offset>]"
 
@@ -11693,6 +11766,10 @@
 "Anda masih menggunakannya dengan mengirimkan surel ke\n"
 "<git@vger.kernel.org>. Terima kasih.\n"
 
+#: builtin/pack-redundant.c
+msgid "refusing to run without --i-still-use-this"
+msgstr "menolak menjalankan tanpa --i-still-use-this"
+
 #: builtin/pack-refs.c
 msgid "git pack-refs [--all] [--no-prune]"
 msgstr "git pack-refs [--all] [--no-prune]"
@@ -11909,9 +11986,9 @@
 msgid "pull with rebase"
 msgstr "tarik dengan pendasaran ulang"
 
-#: builtin/pull.c
-msgid "please commit or stash them."
-msgstr "mohon komit atau stase."
+#: builtin/pull.c builtin/rebase.c
+msgid "Please commit or stash them."
+msgstr "Mohon komit atau stase."
 
 #: builtin/pull.c
 #, c-format
@@ -12174,9 +12251,9 @@
 msgid "repository"
 msgstr "repositori"
 
-#: builtin/push.c builtin/send-pack.c
-msgid "push all refs"
-msgstr "dorong semua referensi"
+#: builtin/push.c
+msgid "push all branches"
+msgstr "dorong semua cabang"
 
 #: builtin/push.c builtin/send-pack.c
 msgid "mirror all refs"
@@ -12187,8 +12264,10 @@
 msgstr "hapus referensi"
 
 #: builtin/push.c
-msgid "push tags (can't be used with --all or --mirror)"
-msgstr "dorong tag (tidak dapat digunakan dengan --all atau --mirror)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr ""
+"dorong tag (tidak dapat digunakan bersamaan dengan --all, --branches, atau --"
+"mirror)"
 
 #: builtin/push.c builtin/send-pack.c
 msgid "force updates"
@@ -12520,6 +12599,11 @@
 
 #: builtin/rebase.c
 #, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "Mode rebase-merges tidak dikenal: %s"
+
+#: builtin/rebase.c
+#, c-format
 msgid "could not switch to %s"
 msgstr "tidak dapat mengganti ke %s"
 
@@ -12537,6 +12621,16 @@
 "dan \"ask\"."
 
 #: builtin/rebase.c
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"--rebase-merges dengan argumen untai kosong usang dan akan berhenti bekerja "
+"pada versi Git berikutnya. Sebagai gantinya, gunakan --rebase-merges tanpa "
+"argumen, yang melakukan hal yang sama."
+
+#: builtin/rebase.c
 #, c-format
 msgid ""
 "%s\n"
@@ -12803,24 +12897,27 @@
 msgstr "tombol `C' harap nilai numerik"
 
 #: builtin/rebase.c
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "Mode tidak dikenal: %s"
-
-#: builtin/rebase.c
 msgid "--strategy requires --merge or --interactive"
 msgstr "--strategy butuh --merge atau --interactive"
 
 #: builtin/rebase.c
 msgid ""
-"apply options are incompatible with rebase.autosquash.  Consider adding --no-"
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
 "autosquash"
 msgstr ""
-"opsi penerapan tidak kompatibel dengan rebase.autosquash. "
+"opsi penerapan tidak kompatibel dengan rebase.autoSquash. "
 "Pertimbangkanmenambahkan --no-autosquash"
 
 #: builtin/rebase.c
 msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr ""
+"opsi penerapan tidak kompatibel dengan rebase.rebaseMerges. "
+"Pertimbangkanmenambahkan --no-rebase-merges"
+
+#: builtin/rebase.c
+msgid ""
 "apply options are incompatible with rebase.updateRefs.  Consider adding --no-"
 "update-refs"
 msgstr ""
@@ -12875,10 +12972,6 @@
 msgstr "Tidak menunjuk pada komit yang valid '%s'"
 
 #: builtin/rebase.c
-msgid "Please commit or stash them."
-msgstr "Mohon komit atau stase."
-
-#: builtin/rebase.c
 msgid "HEAD is up to date."
 msgstr "HEAD terbaru."
 
@@ -13693,8 +13786,8 @@
 msgstr "tanggal aproksimasi"
 
 #: builtin/repack.c
-msgid "with -C, expire objects older than this"
-msgstr "dengan -C, jangan kadaluarsakan objek lebih lama dari ini"
+msgid "with --cruft, expire objects older than this"
+msgstr "dengan --cruft, kadaluarsakan objek yang lebih tua dari ini"
 
 #: builtin/repack.c
 msgid "remove redundant packs, and run git-prune-packed"
@@ -14539,6 +14632,10 @@
 msgstr "nama remote"
 
 #: builtin/send-pack.c
+msgid "push all refs"
+msgstr "dorong semua referensi"
+
+#: builtin/send-pack.c
 msgid "use stateless RPC protocol"
 msgstr "gunakan protokol RPC nirkeadaan"
 
@@ -14798,9 +14895,11 @@
 
 #: builtin/sparse-checkout.c
 msgid ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<opsi>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<opsi>]"
 
 #: builtin/sparse-checkout.c
 msgid "this worktree is not sparse"
@@ -14951,6 +15050,27 @@
 msgid "error while refreshing working directory"
 msgstr "kesalahan saat menyegarkan direktori kerja"
 
+#: builtin/sparse-checkout.c
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no]-cone] [--rules-"
+"file <file>]"
+
+#: builtin/sparse-checkout.c
+msgid "terminate input and output files by a NUL character"
+msgstr "akhiri berkas masukan dan keluaran oleh satu karakter NUL"
+
+#: builtin/sparse-checkout.c
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr ""
+"ketika digunakan dengan --rules-file tafsirkan pola sebagai pola mode kerucut"
+
+#: builtin/sparse-checkout.c
+msgid "use patterns in <file> instead of the current ones."
+msgstr "gunakan pola di dalam <berkas> daripada yang saat ini."
+
 #: builtin/stash.c
 msgid "git stash list [<log-options>]"
 msgstr "git stash list [<opsi log>]"
@@ -18547,8 +18667,8 @@
 msgstr "level kompresi zlib jelek %d"
 
 #: config.c
-msgid "core.commentChar should only be one character"
-msgstr "core.commentChar harusnya hanya satu karakter"
+msgid "core.commentChar should only be one ASCII character"
+msgstr "core.commentChar seharusnya hanya satu karakter ASCII"
 
 #: config.c
 #, c-format
@@ -18688,6 +18808,13 @@
 
 #: config.c
 #, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr ""
+"menolak bekerja dengan baris yang terlalu panjang di '%s' pada baris "
+"%<PRIuMAX>"
+
+#: config.c
+#, c-format
 msgid "missing value for '%s'"
 msgstr "nilai hilang untuk '%s'"
 
@@ -19518,6 +19645,10 @@
 msgstr "jangan perlihatkan prefiks sumber atau tujuan apapun"
 
 #: diff.c
+msgid "use default prefixes a/ and b/"
+msgstr "gunakan awalan asali a/ dan b/"
+
+#: diff.c
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr ""
 "perlihatkan konteks diantara bingkah diff hingga jumlah baris yang disebutkan"
@@ -19901,6 +20032,16 @@
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "petunjuk: Menunggu penyunting Anda untuk menutup berkas...%c"
 
+#: editor.c sequencer.c wrapper.c
+#, c-format
+msgid "could not write to '%s'"
+msgstr "tidak dapat menulis ke '%s'"
+
+#: editor.c
+#, c-format
+msgid "could not edit '%s'"
+msgstr "tidak dapat menyunting '%s'"
+
 #: entry.c
 msgid "Filtering content"
 msgstr "Menyaring isi"
@@ -20273,6 +20414,11 @@
 
 #: git.c
 #, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "tidak ada atribut yang diberikan untuk --attr-source\n"
+
+#: git.c
+#, c-format
 msgid "unknown option: %s\n"
 msgstr "opsi tidak dikenal: %s\n"
 
@@ -22304,6 +22450,11 @@
 msgid "unable to get disk usage of '%s'"
 msgstr "tidak dapat mendapatkan penggunaan disk dari '%s'"
 
+#: pack-bitmap.c
+#, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "checksum berkas bitmap '%s' tidak valid"
+
 #: pack-mtimes.c
 #, c-format
 msgid "mtimes file %s is too small"
@@ -22354,6 +22505,15 @@
 msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
 msgstr "berkas indeks balik %s punya id hash tidak didukung %<PRIu32>"
 
+#: pack-revindex.c
+msgid "invalid checksum"
+msgstr "checksum tidak valid"
+
+#: pack-revindex.c
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr "posisi indeks balik tidak valid pada %<PRIu64>: %<PRIu32> != %<PRIu32>"
+
 #: pack-write.c
 msgid "cannot both write and verify reverse index"
 msgstr "tidak dapat kedua-duanya menulis dan memverifikasi indeks balik"
@@ -23230,6 +23390,11 @@
 
 #: ref-filter.c
 #, c-format
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "format yang diharapkan: %%(ahead-behind:<mirip komit>)"
+
+#: ref-filter.c
+#, c-format
 msgid "malformed field name: %.*s"
 msgstr "nama bidang rusak: %.*s"
 
@@ -23995,11 +24160,6 @@
 
 #: rerere.c
 #, c-format
-msgid "cannot unlink '%s'"
-msgstr "tidak dapat batal taut '%s'"
-
-#: rerere.c
-#, c-format
 msgid "Updated preimage for '%s'"
 msgstr "Pracitra diperbarui untuk '%s'"
 
@@ -24419,11 +24579,6 @@
 msgid "could not lock '%s'"
 msgstr "tidak dapat mengunci '%s'"
 
-#: sequencer.c strbuf.c wrapper.c
-#, c-format
-msgid "could not write to '%s'"
-msgstr "tidak dapat menulis ke '%s'"
-
 #: sequencer.c
 #, c-format
 msgid "could not write eol to '%s'"
@@ -24867,10 +25022,6 @@
 msgstr "tidak dapat membuat direktori pembaris '%s'"
 
 #: sequencer.c
-msgid "could not lock HEAD"
-msgstr "tidak dapat mengunci HEAD"
-
-#: sequencer.c
 msgid "no cherry-pick or revert in progress"
 msgstr "tidak ada pemetikan ceri atau pembalikkan yang sedang berjalan"
 
@@ -24986,21 +25137,21 @@
 "\n"
 
 #: sequencer.c
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "dan buat perubahan ke indeks dan/atau pohon kerja\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "dan buat perubahan ke indeks dan/atau pohon kerja.\n"
 
 #: sequencer.c
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
 msgstr ""
 "eksekusi berhasil: %s\n"
-"tapi meninggalkan perubahan ke indeks dan/atau pohon kerja\n"
+"tapi meninggalkan perubahan ke indeks dan/atau pohon kerja.\n"
 "Komit atau stase perubahan Anda, lalu jalankan\n"
 "\n"
 "  git rebase --continue\n"
@@ -25528,11 +25679,6 @@
 msgstr[0] "%u bita/detik"
 msgstr[1] "%u bita/detik"
 
-#: strbuf.c
-#, c-format
-msgid "could not edit '%s'"
-msgstr "tidak dapat menyunting '%s'"
-
 #: submodule-config.c
 #, c-format
 msgid "ignoring suspicious submodule name: %s"
@@ -27643,8 +27789,8 @@
 
 #: git-send-email.perl
 #, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) Menambahkan %s: %s dari: '%s'\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) Baris masukan salah format: '%s'"
 
 #: git-send-email.perl
 #, perl-format
@@ -27652,6 +27798,11 @@
 msgstr "(%s) gagal menutup pipa ke '%s'"
 
 #: git-send-email.perl
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) Menambahkan %s: %s dari: '%s'\n"
+
+#: git-send-email.perl
 msgid "cannot send message as 7bit"
 msgstr "tidak dapat mengirim pesan sebagai 7bit"
 
diff --git a/po/sv.po b/po/sv.po
index 0ba8585..284da90 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: git 2.40.0\n"
+"Project-Id-Version: git 2.41.0\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-03-02 09:34+0100\n"
-"PO-Revision-Date: 2023-03-02 09:35+0100\n"
+"POT-Creation-Date: 2023-05-31 13:14+0100\n"
+"PO-Revision-Date: 2023-05-31 13:15+0100\n"
 "Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
 "Language: sv\n"
@@ -665,6 +665,23 @@
 msgid "Exiting because of unfinished merge."
 msgstr "Avslutar på grund av ofullbordad sammanslagning."
 
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"Divergerande grenar kan inte snabbspolas, du måste antingen använda:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"eller:\n"
+"\n"
+"\tgit rebase\n"
+
 msgid "Not possible to fast-forward, aborting."
 msgstr "Kan inte snabbspola, avbryter."
 
@@ -1110,6 +1127,10 @@
 msgstr "kan inte öppna %s"
 
 #, c-format
+msgid "cannot unlink '%s'"
+msgstr "kan inte ta bort länken \"%s\""
+
+#, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "Stycke %d tillämpades rent."
 
@@ -1296,6 +1317,10 @@
 msgstr "kunde inte läsa \"%s\""
 
 #, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr "sökvägsangivelsen \"%s\" motsvarar filer utanför aktuell katalog"
+
+#, c-format
 msgid "pathspec '%s' did not match any files"
 msgstr "sökvägsangivelsen \"%s\" motsvarade inte några filer"
 
@@ -1311,9 +1336,6 @@
 msgid "not a tree object: %s"
 msgstr "inte ett trädobjekt: %s"
 
-msgid "current working directory is untracked"
-msgstr "aktuell arbetskatalog är inte spårad"
-
 #, c-format
 msgid "File not found: %s"
 msgstr "Hittar inte filen: %s"
@@ -1440,6 +1462,9 @@
 msgid "ignoring overly large gitattributes blob '%s'"
 msgstr "ignorerar allt för stor gitattributes-objekt \"%s\""
 
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr "felaktig --attr-source eller GIT_ATTR_SOURCE"
+
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
 msgstr "Felaktigt citerat innehåll i filen \"%s\": %s"
@@ -1546,9 +1571,6 @@
 msgid "--contents and --reverse do not blend well."
 msgstr "--contents och --reverse fungerar inte så bra tillsammans."
 
-msgid "cannot use --contents with final commit object name"
-msgstr "kan inte använda --contents med namn på slutgiltigt incheckningsobjekt"
-
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr ""
 "--reverse och --first-parent tillsammans kräver att du anger senaste "
@@ -1731,10 +1753,6 @@
 msgid "'%s' is already checked out at '%s'"
 msgstr "\"%s\" är redan utcheckad på \"%s\""
 
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "HEAD i arbetskatalogen %s har inte uppdaterats"
-
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<flaggor>] [--] <sökväg>..."
 
@@ -2765,6 +2783,14 @@
 msgstr "fjärrspårande grenen \"%s\" hittades inte."
 
 #, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"grenen \"%s\" hittades inte.\n"
+"Glömde du --remote?"
+
+#, c-format
 msgid "branch '%s' not found."
 msgstr "grenen \"%s\" hittades inte."
 
@@ -2795,6 +2821,10 @@
 msgstr "Grenen %s är i en \"bisect\" på %s"
 
 #, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "HEAD i arbetskatalogen %s har inte uppdaterats"
+
+#, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "Felaktigt namn på gren: \"%s\""
 
@@ -2894,6 +2924,9 @@
 msgid "move/rename a branch, even if target exists"
 msgstr "flytta/ta bort en gren, även om målet finns"
 
+msgid "do not output a newline after empty formatted refs"
+msgstr "skriv inte ut ett nyradstecken efter tomma formaterade referenser"
+
 msgid "copy a branch and its reflog"
 msgstr "kopiera en gren och dess reflogg"
 
@@ -3115,12 +3148,10 @@
 msgstr "Skapade ny rapport på \"%s\"\n"
 
 msgid ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <fil> <git-rev-list-flaggor>"
 
 msgid "git bundle verify [-q | --quiet] <file>"
@@ -3141,11 +3172,11 @@
 msgid "show progress meter"
 msgstr "visa förloppsindikator"
 
-msgid "show progress meter during object writing phase"
-msgstr "visa förloppsindikator under objektskrivningsfasen"
+msgid "historical; same as --progress"
+msgstr "historisk; samma som --progress"
 
-msgid "similar to --all-progress when progress meter is shown"
-msgstr "som --all-progress när förloppsindikatorn visas"
+msgid "historical; does nothing"
+msgstr "historisk flagga; gör ingenting"
 
 msgid "specify bundle format version"
 msgstr "ange formatversion för bunten."
@@ -3171,7 +3202,7 @@
 msgstr "kan inte läsa objektet %s: \"%s\""
 
 msgid "flush is only for --buffer mode"
-msgstr "flush är endast till för --buffer-läge"
+msgstr "flush är endast till för \"--buffer\"-läge"
 
 msgid "empty command in input"
 msgstr "tomt kommando i indata"
@@ -4148,6 +4179,10 @@
 msgstr "%s finns och är ingen katalog"
 
 #, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "\"%s\" är en symbolisk länk, vägrar klona med --local"
+
+#, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "misslyckades starta iterator över \"%s\""
 
@@ -5649,6 +5684,175 @@
 msgid "fetch.parallel cannot be negative"
 msgstr "fetch.parallel kan inte vara negativt"
 
+msgid "couldn't find remote ref HEAD"
+msgstr "kunde inte hitta fjärr-referensen HEAD"
+
+#, c-format
+msgid "From %.*s\n"
+msgstr "Från %.*s\n"
+
+#, c-format
+msgid "object %s not found"
+msgstr "objektet %s hittades inte"
+
+msgid "[up to date]"
+msgstr "[àjour]"
+
+msgid "[rejected]"
+msgstr "[refuserad]"
+
+msgid "can't fetch into checked-out branch"
+msgstr "kan inte hämta i utcheckad gren"
+
+msgid "[tag update]"
+msgstr "[uppdaterad tagg]"
+
+msgid "unable to update local ref"
+msgstr "kunde inte uppdatera lokal ref"
+
+msgid "would clobber existing tag"
+msgstr "skulle skriva över befintlig tagg"
+
+msgid "[new tag]"
+msgstr "[ny tagg]"
+
+msgid "[new branch]"
+msgstr "[ny gren]"
+
+msgid "[new ref]"
+msgstr "[ny ref]"
+
+msgid "forced update"
+msgstr "tvingad uppdatering"
+
+msgid "non-fast-forward"
+msgstr "ej snabbspolad"
+
+#, c-format
+msgid "cannot open '%s'"
+msgstr "kan inte öppna \"%s\""
+
+msgid ""
+"fetch normally indicates which branches had a forced update,\n"
+"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
+"flag or run 'git config fetch.showForcedUpdates true'"
+msgstr ""
+"fetch visar normalt vilka grenar som tvångsuppdaterats, men testet har "
+"slagits\n"
+"av; för att slå på igen, använd flaggan \"--show-forced-updates\" eller kör\n"
+"\"git config fetch.showForcedUpdates true\""
+
+#, c-format
+msgid ""
+"it took %.2f seconds to check forced updates; you can use\n"
+"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
+"false'\n"
+"to avoid this check\n"
+msgstr ""
+"det tog %.2f sekunder att se efter tvångsuppdateringar; Du kan använda\n"
+"\"--no-show-forced-updates\" eller köra \"git config fetch."
+"showForcedUpdates\n"
+"false\" för att undvika testet\n"
+
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s sände inte alla nödvändiga objekt\n"
+
+#, c-format
+msgid "rejected %s because shallow roots are not allowed to be updated"
+msgstr "avvisade %s då grunda rötter inte tillåts uppdateras"
+
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+"vissa lokala referenser kunde inte uppdateras; testa att köra\n"
+" \"git remote prune %s\" för att ta bort gamla grenar som står i konflikt"
+
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr "   (%s kommer bli dinglande)"
+
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr "   (%s har blivit dinglande)"
+
+msgid "[deleted]"
+msgstr "[borttagen]"
+
+msgid "(none)"
+msgstr "(ingen)"
+
+#, c-format
+msgid "refusing to fetch into branch '%s' checked out at '%s'"
+msgstr "vägrar hämta till grenen \"%s\" som är utcheckad på \"%s\""
+
+#, c-format
+msgid "option \"%s\" value \"%s\" is not valid for %s"
+msgstr "flaggan \"%s\" med värdet \"%s\" är inte giltigt för %s"
+
+#, c-format
+msgid "option \"%s\" is ignored for %s\n"
+msgstr "flaggan \"%s\" ignoreras för %s\n"
+
+#, c-format
+msgid "%s is not a valid object"
+msgstr "%s är inte ett giltigt objekt"
+
+#, c-format
+msgid "the object %s does not exist"
+msgstr "objektet %s finns inte"
+
+msgid "multiple branches detected, incompatible with --set-upstream"
+msgstr "flera grenar upptäcktes, inkompatibelt med --set-upstream"
+
+#, c-format
+msgid ""
+"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
+"any branch."
+msgstr ""
+"kunde inte sätta uppström för HEAD till \"%s\" från \"%s\" när det inte "
+"pekar mot någon gren."
+
+msgid "not setting upstream for a remote remote-tracking branch"
+msgstr "ställer inte in uppströmsgren för en fjärrspårande gren på fjärren"
+
+msgid "not setting upstream for a remote tag"
+msgstr "ställer inte in uppström för en fjärrtag"
+
+msgid "unknown branch type"
+msgstr "okänd grentyp"
+
+msgid ""
+"no source branch found;\n"
+"you need to specify exactly one branch with the --set-upstream option"
+msgstr ""
+"hittade ingen källgren;\n"
+"du måste ange exakt en gren med flaggan --set-upstream"
+
+#, c-format
+msgid "Fetching %s\n"
+msgstr "Hämtar %s\n"
+
+#, c-format
+msgid "could not fetch %s"
+msgstr "kunde inte hämta %s"
+
+#, c-format
+msgid "could not fetch '%s' (exit code: %d)\n"
+msgstr "kunde inte hämta \"%s\" (felkod: %d)\n"
+
+msgid ""
+"no remote repository specified; please specify either a URL or a\n"
+"remote name from which new revisions should be fetched"
+msgstr ""
+"inget fjärrarkiv angavs; ange antingen en URL eller namnet på ett\n"
+"fjärrarkiv som nya incheckningar ska hämtas från"
+
+msgid "you need to specify a tag name"
+msgstr "du måste ange namnet på en tagg"
+
 msgid "fetch from all remotes"
 msgstr "hämta från alla fjärrar"
 
@@ -5755,175 +5959,6 @@
 msgid "accept refspecs from stdin"
 msgstr "ta emot referenser från standard in"
 
-msgid "couldn't find remote ref HEAD"
-msgstr "kunde inte hitta fjärr-referensen HEAD"
-
-#, c-format
-msgid "object %s not found"
-msgstr "objektet %s hittades inte"
-
-msgid "[up to date]"
-msgstr "[àjour]"
-
-msgid "[rejected]"
-msgstr "[refuserad]"
-
-msgid "can't fetch into checked-out branch"
-msgstr "kan inte hämta i utcheckad gren"
-
-msgid "[tag update]"
-msgstr "[uppdaterad tagg]"
-
-msgid "unable to update local ref"
-msgstr "kunde inte uppdatera lokal ref"
-
-msgid "would clobber existing tag"
-msgstr "skulle skriva över befintlig tagg"
-
-msgid "[new tag]"
-msgstr "[ny tagg]"
-
-msgid "[new branch]"
-msgstr "[ny gren]"
-
-msgid "[new ref]"
-msgstr "[ny ref]"
-
-msgid "forced update"
-msgstr "tvingad uppdatering"
-
-msgid "non-fast-forward"
-msgstr "ej snabbspolad"
-
-#, c-format
-msgid "cannot open '%s'"
-msgstr "kan inte öppna \"%s\""
-
-msgid ""
-"fetch normally indicates which branches had a forced update,\n"
-"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
-"flag or run 'git config fetch.showForcedUpdates true'"
-msgstr ""
-"fetch visar normalt vilka grenar som tvångsuppdaterats, men testet har "
-"slagits\n"
-"av; för att slå på igen, använd flaggan \"--show-forced-updates\" eller kör\n"
-"\"git config fetch.showForcedUpdates true\""
-
-#, c-format
-msgid ""
-"it took %.2f seconds to check forced updates; you can use\n"
-"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
-"false'\n"
-"to avoid this check\n"
-msgstr ""
-"det tog %.2f sekunder att se efter tvångsuppdateringar; Du kan använda\n"
-"\"--no-show-forced-updates\" eller köra \"git config fetch."
-"showForcedUpdates\n"
-"false\" för att undvika testet\n"
-
-#, c-format
-msgid "%s did not send all necessary objects\n"
-msgstr "%s sände inte alla nödvändiga objekt\n"
-
-#, c-format
-msgid "rejected %s because shallow roots are not allowed to be updated"
-msgstr "avvisade %s då grunda rötter inte tillåts uppdateras"
-
-#, c-format
-msgid "From %.*s\n"
-msgstr "Från %.*s\n"
-
-#, c-format
-msgid ""
-"some local refs could not be updated; try running\n"
-" 'git remote prune %s' to remove any old, conflicting branches"
-msgstr ""
-"vissa lokala referenser kunde inte uppdateras; testa att köra\n"
-" \"git remote prune %s\" för att ta bort gamla grenar som står i konflikt"
-
-#, c-format
-msgid "   (%s will become dangling)"
-msgstr "   (%s kommer bli dinglande)"
-
-#, c-format
-msgid "   (%s has become dangling)"
-msgstr "   (%s har blivit dinglande)"
-
-msgid "[deleted]"
-msgstr "[borttagen]"
-
-msgid "(none)"
-msgstr "(ingen)"
-
-#, c-format
-msgid "refusing to fetch into branch '%s' checked out at '%s'"
-msgstr "vägrar hämta till grenen \"%s\" som är utcheckad på \"%s\""
-
-#, c-format
-msgid "option \"%s\" value \"%s\" is not valid for %s"
-msgstr "flaggan \"%s\" med värdet \"%s\" är inte giltigt för %s"
-
-#, c-format
-msgid "option \"%s\" is ignored for %s\n"
-msgstr "flaggan \"%s\" ignoreras för %s\n"
-
-#, c-format
-msgid "%s is not a valid object"
-msgstr "%s är inte ett giltigt objekt"
-
-#, c-format
-msgid "the object %s does not exist"
-msgstr "objektet %s finns inte"
-
-msgid "multiple branches detected, incompatible with --set-upstream"
-msgstr "flera grenar upptäcktes, inkompatibelt med --set-upstream"
-
-#, c-format
-msgid ""
-"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
-"any branch."
-msgstr ""
-"kunde inte sätta uppström för HEAD till \"%s\" från \"%s\" när det inte "
-"pekar mot någon gren."
-
-msgid "not setting upstream for a remote remote-tracking branch"
-msgstr "ställer inte in uppströmsgren för en fjärrspårande gren på fjärren"
-
-msgid "not setting upstream for a remote tag"
-msgstr "ställer inte in uppström för en fjärrtag"
-
-msgid "unknown branch type"
-msgstr "okänd grentyp"
-
-msgid ""
-"no source branch found;\n"
-"you need to specify exactly one branch with the --set-upstream option"
-msgstr ""
-"hittade ingen källgren;\n"
-"du måste ange exakt en gren med flaggan --set-upstream"
-
-#, c-format
-msgid "Fetching %s\n"
-msgstr "Hämtar %s\n"
-
-#, c-format
-msgid "could not fetch %s"
-msgstr "kunde inte hämta %s"
-
-#, c-format
-msgid "could not fetch '%s' (exit code: %d)\n"
-msgstr "kunde inte hämta \"%s\" (felkod: %d)\n"
-
-msgid ""
-"no remote repository specified; please specify either a URL or a\n"
-"remote name from which new revisions should be fetched"
-msgstr ""
-"inget fjärrarkiv angavs; ange antingen en URL eller namnet på ett\n"
-"fjärrarkiv som nya incheckningar ska hämtas från"
-
-msgid "you need to specify a tag name"
-msgstr "du måste ange namnet på en tagg"
-
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr "--negotiate-only behöver en eller flera --negotiation-tip=*"
 
@@ -6039,6 +6074,12 @@
 msgid "print only refs which don't contain the commit"
 msgstr "visa endast referenser som inte innehåller incheckningen"
 
+msgid "read reference patterns from stdin"
+msgstr "läs referensmönster från standard in"
+
+msgid "unknown arguments supplied with --stdin"
+msgstr "okända argument angavs tillsammans med --stdin"
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<konfig> [--] <argument>"
 
@@ -6051,6 +6092,10 @@
 msgid "missing --config=<config>"
 msgstr "saknar --config=<konfig>"
 
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "fick felaktig konfiguration --config=%s"
+
 msgid "unknown"
 msgstr "okänd"
 
@@ -6201,19 +6246,28 @@
 msgid "notice: %s points to an unborn branch (%s)"
 msgstr "obs: %s pekar på en ofödd gren (%s)"
 
-msgid "Checking cache tree"
-msgstr "Kontrollerar cacheträd"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "Kontrollerar cacheträd för %s"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "%s: ogiltig sha1-pekare i cacheträd"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s: ogiltig sha1-pekare i cacheträd för %s"
 
 msgid "non-tree in cache-tree"
 msgstr "icke-träd i cacheträd"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in resolve-undo"
-msgstr "%s: ogiltig sha1-pekare i resolve-undo"
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s: ogiltig sha1-pekare i resolve-undo för %s"
+
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "kunde inte läsa rev-index för paketfil \"%s\""
+
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "ogiltigt rev-index för paketet \"%s\""
 
 msgid ""
 "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
@@ -9055,6 +9109,12 @@
 msgid "bad index version '%s'"
 msgstr "felaktig indexversion \"%s\""
 
+msgid "show progress meter during object writing phase"
+msgstr "visa förloppsindikator under objektskrivningsfasen"
+
+msgid "similar to --all-progress when progress meter is shown"
+msgstr "som --all-progress när förloppsindikatorn visas"
+
 msgid "<version>[,<offset>]"
 msgstr "<version>[,<offset>]"
 
@@ -9243,6 +9303,9 @@
 "oss att du fortfarande använder det på e-post till\n"
 "<git@vger.kernel.org>. Tack.\n"
 
+msgid "refusing to run without --i-still-use-this"
+msgstr "vägrar köra utan --i-still-use-this"
+
 msgid "git pack-refs [--all] [--no-prune]"
 msgstr "git pack-refs [--all] [--no-prune]"
 
@@ -9413,8 +9476,8 @@
 msgid "pull with rebase"
 msgstr "pull med ombasering"
 
-msgid "please commit or stash them."
-msgstr "checka in eller använd \"stash\" på dem."
+msgid "Please commit or stash them."
+msgstr "Checka in eller använd \"stash\" på dem."
 
 #, c-format
 msgid ""
@@ -9648,8 +9711,8 @@
 msgid "repository"
 msgstr "arkiv"
 
-msgid "push all refs"
-msgstr "sänd alla referenser"
+msgid "push all branches"
+msgstr "sänd alla grenar"
 
 msgid "mirror all refs"
 msgstr "spegla alla referenser"
@@ -9657,8 +9720,9 @@
 msgid "delete refs"
 msgstr "ta bort referenser"
 
-msgid "push tags (can't be used with --all or --mirror)"
-msgstr "sänd taggar (kan inte användas med --all eller --mirror)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr ""
+"sänd taggar (kan inte användas med --all eller --branches eller --mirror)"
 
 msgid "force updates"
 msgstr "tvinga uppdateringar"
@@ -9921,6 +9985,10 @@
 "Därför kan inte git ombasera dessa."
 
 #, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "Okänd rebase-merges-läge: %s"
+
+#, c-format
 msgid "could not switch to %s"
 msgstr "kunde inte växla till %s"
 
@@ -9935,6 +10003,15 @@
 msgstr ""
 "okänd tom-typ \"%s\"; giltiga värden är \"drop\", \"keep\" och \"ask\"."
 
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"--rebase-merges med en tom sträng som argument avråds från och kommer sluta "
+"fungera i en framtida version av Git. Använd istället --rebase-merges utan "
+"argument, vilket har samma effekt."
+
 #, c-format
 msgid ""
 "%s\n"
@@ -10149,21 +10226,24 @@
 msgid "switch `C' expects a numerical value"
 msgstr "flaggan \"C\" förväntar ett numeriskt värde"
 
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "Okänt läge: %s"
-
 msgid "--strategy requires --merge or --interactive"
 msgstr "--strategy kräver --merge eller --interactive"
 
 msgid ""
-"apply options are incompatible with rebase.autosquash.  Consider adding --no-"
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
 "autosquash"
 msgstr ""
-"argument för \"apply\" är inkompatibla med rebase.autosquash. Överväg att "
+"argument för \"apply\" är inkompatibla med rebase.autoSquash. Överväg att "
 "lägga till --no-autosquash"
 
 msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr ""
+"argument för \"apply\" är inkompatibla med rebase.rebaseMerges. Överväg att "
+"lägga till --no-rebase-merges"
+
+msgid ""
 "apply options are incompatible with rebase.updateRefs.  Consider adding --no-"
 "update-refs"
 msgstr ""
@@ -10207,9 +10287,6 @@
 msgid "Does not point to a valid commit '%s'"
 msgstr "Pekar inte på en giltig incheckning: \"%s\""
 
-msgid "Please commit or stash them."
-msgstr "Checka in eller använd \"stash\" på dem."
-
 msgid "HEAD is up to date."
 msgstr "HEAD är à jour."
 
@@ -10863,8 +10940,8 @@
 msgid "approxidate"
 msgstr "cirkadatum"
 
-msgid "with -C, expire objects older than this"
-msgstr "med -C, låt tid gå ut för objekt äldre än detta"
+msgid "with --cruft, expire objects older than this"
+msgstr "med --cruft, låt tid gå ut för objekt äldre än detta"
 
 msgid "remove redundant packs, and run git-prune-packed"
 msgstr "ta bort överflödiga paket, och kör git-prune-packed"
@@ -11528,6 +11605,9 @@
 msgid "remote name"
 msgstr "fjärrnamn"
 
+msgid "push all refs"
+msgstr "sänd alla referenser"
+
 msgid "use stateless RPC protocol"
 msgstr "använd tillståndslöst RPC-protokoll"
 
@@ -11728,9 +11808,11 @@
 msgstr "visa referenser från standard in som inte finns i lokalt arkiv"
 
 msgid ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable) <flaggor>"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) <flaggor>"
 
 msgid "this worktree is not sparse"
 msgstr "arbetskatalogen är inte gren"
@@ -11853,6 +11935,22 @@
 msgid "error while refreshing working directory"
 msgstr "fel vid uppdatering av arbetskatalog"
 
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks] [--[no-]cone] [--rules-"
+"file <fil>]"
+
+msgid "terminate input and output files by a NUL character"
+msgstr "avsluta in- och utdatafiler med NUL-tecken"
+
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr "om används med --rules-file tolka mönster som kon-lägemönster"
+
+msgid "use patterns in <file> instead of the current ones."
+msgstr "använd mönster i <fil> istället för de nuvarande."
+
 msgid "git stash list [<log-options>]"
 msgstr "git stash list [<\"log\"-flaggor>]"
 
@@ -14685,8 +14783,8 @@
 msgid "bad zlib compression level %d"
 msgstr "felaktigt zlib-komprimeringsgrad %d"
 
-msgid "core.commentChar should only be one character"
-msgstr "core.commentChar kan bara vara ett tecken"
+msgid "core.commentChar should only be one ASCII character"
+msgstr "core.commentChar kan bara vara ett ASCII-tecken"
 
 #, c-format
 msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -14798,6 +14896,10 @@
 msgstr "felaktigt namn på stycke: %s"
 
 #, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr "vägrar arbeta med för långa rader i \"%s\" på rad %<PRIuMAX>"
+
+#, c-format
 msgid "missing value for '%s'"
 msgstr "värde saknas för \"%s\""
 
@@ -15466,6 +15568,9 @@
 msgid "do not show any source or destination prefix"
 msgstr "visa inte käll- eller målprefix"
 
+msgid "use default prefixes a/ and b/"
+msgstr "använd standardprefixen a/ och b/"
+
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr "visa sammnhang mellan diff-stycken upp till angivet antal rader"
 
@@ -15759,6 +15864,14 @@
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "tips: Väntar på att textredigeringsprogrammet ska stänga filen...%c"
 
+#, c-format
+msgid "could not write to '%s'"
+msgstr "kunde inte skriva till \"%s\""
+
+#, c-format
+msgid "could not edit '%s'"
+msgstr "kunde inte redigera \"%s\""
+
 msgid "Filtering content"
 msgstr "Filtrerar innehåll"
 
@@ -16057,6 +16170,10 @@
 msgstr "ingen konfigurationsnyckel angavs för --config-env\n"
 
 #, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "ingen attributkälla angavs för --attr-source\n"
+
+#, c-format
 msgid "unknown option: %s\n"
 msgstr "okänd flagga: %s\n"
 
@@ -17716,6 +17833,10 @@
 msgstr "kan inte hämta diskanvändning för \"%s\""
 
 #, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "bitkartefilen \"%s\" har ogiltig kontrollsumma"
+
+#, c-format
 msgid "mtimes file %s is too small"
 msgstr "mtimes-filen %s är för liten"
 
@@ -17755,6 +17876,13 @@
 msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
 msgstr "reverse-index-filen %s har hash-ID %<PRIu32> som inte stöds"
 
+msgid "invalid checksum"
+msgstr "ogiltig kontrollsumma"
+
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr "ogiltig rev-indexposition vid %<PRIu64>: %<PRIu32> != %<PRIu32>"
+
 msgid "cannot both write and verify reverse index"
 msgstr "kan inte både skriva och bekräfta reverse-index"
 
@@ -18477,6 +18605,10 @@
 msgstr "positiv bredd förväntad med atomen %%(align)"
 
 #, c-format
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "förväntat format: %%(ahead-behind:<incheckning-igt>)"
+
+#, c-format
 msgid "malformed field name: %.*s"
 msgstr "felformat fältnamn: %.*s"
 
@@ -19096,10 +19228,6 @@
 msgstr "inget sparat sammanslagningsresultat för \"%s\""
 
 #, c-format
-msgid "cannot unlink '%s'"
-msgstr "kan inte ta bort länken \"%s\""
-
-#, c-format
 msgid "Updated preimage for '%s'"
 msgstr "Uppdaterade förhandsbild för \"%s\""
 
@@ -19432,10 +19560,6 @@
 msgstr "kunde inte låsa \"%s\""
 
 #, c-format
-msgid "could not write to '%s'"
-msgstr "kunde inte skriva till \"%s\""
-
-#, c-format
 msgid "could not write eol to '%s'"
 msgstr "kunde inte skriva radslut till \"%s\""
 
@@ -19795,9 +19919,6 @@
 msgid "could not create sequencer directory '%s'"
 msgstr "kunde inte skapa \"sequencer\"-katalogen \"%s\""
 
-msgid "could not lock HEAD"
-msgstr "kunde inte låsa HEAD"
-
 msgid "no cherry-pick or revert in progress"
 msgstr "ingen \"cherry-pick\" eller \"revert\" pågår"
 
@@ -19894,20 +20015,20 @@
 "\tgit rebase --continue\n"
 "\n"
 
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "och gjorde ändringar till indexet och/eller arbetskatalogen\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "och gjorde ändringar till indexet och/eller arbetskatalogen.\n"
 
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
 msgstr ""
 "körningen lyckades: %s\n"
-"men lämnade kvar ändringar i indexet och/eller arbetskatalogen\n"
+"men lämnade kvar ändringar i indexet och/eller arbetskatalogen.\n"
 "Checka in eller utför \"stash\" på ändringarna och kör sedan\n"
 "\n"
 "\tgit rebase --continue\n"
@@ -20342,10 +20463,6 @@
 msgstr[1] "%u bytes/s"
 
 #, c-format
-msgid "could not edit '%s'"
-msgstr "kunde inte redigera \"%s\""
-
-#, c-format
 msgid "ignoring suspicious submodule name: %s"
 msgstr "ignorerar misstänkt undermodulnamn: %s"
 
@@ -22058,13 +22175,17 @@
 msgstr "(%s) Kunde inte köra \"%s\""
 
 #, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) Lägger till %s: %s från: \"%s\"\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) Felformaterad utdata från \"%s\""
 
 #, perl-format
 msgid "(%s) failed to close pipe to '%s'"
 msgstr "(%s) misslyckades stänga röret till \"%s\""
 
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) Lägger till %s: %s från: \"%s\"\n"
+
 msgid "cannot send message as 7bit"
 msgstr "kan inte sända brev som sjubitars"
 
diff --git a/po/tr.po b/po/tr.po
index a24a7ae..d788dfe 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -92,8 +92,8 @@
 msgstr ""
 "Project-Id-Version: Git Turkish Localization Project\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-03-03 11:32+0300\n"
-"PO-Revision-Date: 2023-03-03 11:40+0300\n"
+"POT-Creation-Date: 2023-05-20 12:55+0300\n"
+"PO-Revision-Date: 2023-05-20 14:00+0300\n"
 "Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
 "Language-Team: Turkish (https://github.com/bitigchi/git-po/)\n"
 "Language: tr\n"
@@ -741,6 +741,23 @@
 msgid "Exiting because of unfinished merge."
 msgstr "Tamamlanmamış birleştirmeden dolayı çıkılıyor."
 
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"Iraksak dallar ileri sarılamaz; şunlardan birini yapmanız gerekiyor:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"veya\n"
+"\n"
+"\tgit rebase\n"
+
 msgid "Not possible to fast-forward, aborting."
 msgstr "İleri sarma olanaklı değil, iptal ediliyor."
 
@@ -1183,6 +1200,10 @@
 msgstr "%s açılamıyor"
 
 #, c-format
+msgid "cannot unlink '%s'"
+msgstr "'%s' bağlantısı kesilemiyor"
+
+#, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "Parça #%d sorunsuzca uygulandı."
 
@@ -1366,8 +1387,12 @@
 msgstr "'%s' okunamıyor"
 
 #, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr "yol belirteci '%s', geçerli dizinin dışındaki dosyalarla eşleşiyor"
+
+#, c-format
 msgid "pathspec '%s' did not match any files"
-msgstr "yol belirteci '%s' hiçbir dosya ile eşleşmedi"
+msgstr "yol belirteci '%s', hiçbir dosya ile eşleşmedi"
 
 #, c-format
 msgid "no such ref: %.*s"
@@ -1381,9 +1406,6 @@
 msgid "not a tree object: %s"
 msgstr "bir ağaç nesnesi değil: %s"
 
-msgid "current working directory is untracked"
-msgstr "geçerli çalışma dizini izlenmiyor"
-
 #, c-format
 msgid "File not found: %s"
 msgstr "Dosya bulunamadı: %s"
@@ -1510,6 +1532,9 @@
 msgid "ignoring overly large gitattributes blob '%s'"
 msgstr "pek büyük gitattributes ikili nesnesi '%s' yok sayılıyor"
 
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr "hatalı --attr-source veya GIT_ATTR_SOURCE"
+
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
 msgstr "'%s' dosyasında hatalı tırnağa alınmış içerik: %s"
@@ -1615,9 +1640,6 @@
 msgid "--contents and --reverse do not blend well."
 msgstr "--contents ve --reverse birlikte pek iyi gitmiyor."
 
-msgid "cannot use --contents with final commit object name"
-msgstr "--contents son işleme nesnesi adı ile kullanılamıyor"
-
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr ""
 "--reverse ve --first-parent birlikte en son işlemenin belirtilmesini "
@@ -1800,10 +1822,6 @@
 msgid "'%s' is already checked out at '%s'"
 msgstr "'%s' çıkışı '%s' konumunda halihazırda yapılmış"
 
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "%s çalışma ağacının HEAD'i güncellenmemiş"
-
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<seçenekler>] [--] <yol-blrtç>..."
 
@@ -2838,6 +2856,14 @@
 msgstr "Uzak izleme dalı '%s' bulunamadı."
 
 #, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"'%s' dalı bulunamadı.\n"
+"--remote yazmayı mı unuttunuz?"
+
+#, c-format
 msgid "branch '%s' not found."
 msgstr "'%s' dalı bulunamadı."
 
@@ -2868,6 +2894,10 @@
 msgstr "%s dalı %s konumunda ikili aranıyor"
 
 #, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "%s çalışma ağacının HEAD'i güncellenmemiş"
+
+#, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "Geçersiz dal adı: '%s'"
 
@@ -2967,6 +2997,9 @@
 msgid "move/rename a branch, even if target exists"
 msgstr "bir dalı taşı/yeniden adlandır, hedef var olsa bile"
 
+msgid "do not output a newline after empty formatted refs"
+msgstr "boş biçimli başvurulardan sonra bir yenisatır çıktılama"
+
 msgid "copy a branch and its reflog"
 msgstr "bir dalı ve onun başvuru günlüğünü kopyala"
 
@@ -3185,13 +3218,11 @@
 msgstr "Hata raporu '%s' dosyasına yazıldı.\n"
 
 msgid ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
-"                  [--version=<sürüm>] <dosya> <git-rev-liste-argümanları>"
+"git bundle create [-q | --quiet | --progress]\n"
+"                  [--version=<sürüm>] <dosya> <git-rev-listesi-argümanları>"
 
 msgid "git bundle verify [-q | --quiet] <file>"
 msgstr "git bundle verify [-q | --quiet] <dosya>"
@@ -3211,11 +3242,11 @@
 msgid "show progress meter"
 msgstr "ilerleme çubuğunu göster"
 
-msgid "show progress meter during object writing phase"
-msgstr "ilerleme çubuğunu nesne yazımı aşaması sırasında göster"
+msgid "historical; same as --progress"
+msgstr "eski seçenek; --progress ile aynı"
 
-msgid "similar to --all-progress when progress meter is shown"
-msgstr "ilerleme çubuğu gösterildiğinde --all-progress'e benzer"
+msgid "historical; does nothing"
+msgstr "eski seçenek; bir şey yapmaz"
 
 msgid "specify bundle format version"
 msgstr "demet biçim sürümünü belirt"
@@ -4221,6 +4252,10 @@
 msgstr "%s var ve bir dizin değil"
 
 #, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "'%s' bir sembolik bağlantı; --local ile klonlama reddediliyor"
+
+#, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "yineleyici '%s' üzerinden çalıştırılamadı"
 
@@ -5733,6 +5768,174 @@
 msgid "fetch.parallel cannot be negative"
 msgstr "fetch.parallel negatif olamaz"
 
+msgid "couldn't find remote ref HEAD"
+msgstr "uzak HEAD başvurusu bulunamadı"
+
+#, c-format
+msgid "From %.*s\n"
+msgstr "Şu konumdan: %.*s\n"
+
+#, c-format
+msgid "object %s not found"
+msgstr "%s nesnesi bulunamadı"
+
+msgid "[up to date]"
+msgstr "[güncel]"
+
+msgid "[rejected]"
+msgstr "[reddedildi]"
+
+msgid "can't fetch into checked-out branch"
+msgstr "çıkış yapılmış dala getirilemiyor"
+
+msgid "[tag update]"
+msgstr "[etiket güncellemesi]"
+
+msgid "unable to update local ref"
+msgstr "yerel başvuru güncellenemiyor"
+
+msgid "would clobber existing tag"
+msgstr "var olan etiketi değiştirecektir"
+
+msgid "[new tag]"
+msgstr "[yeni etiket]"
+
+msgid "[new branch]"
+msgstr "[yeni dal]"
+
+msgid "[new ref]"
+msgstr "[yeni başvuru]"
+
+msgid "forced update"
+msgstr "zorlanmış güncelleme"
+
+msgid "non-fast-forward"
+msgstr "ileri sarım değil"
+
+#, c-format
+msgid "cannot open '%s'"
+msgstr "'%s' açılamıyor"
+
+msgid ""
+"fetch normally indicates which branches had a forced update,\n"
+"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
+"flag or run 'git config fetch.showForcedUpdates true'"
+msgstr ""
+"Getirme, normalde hangi dallarda zorla güncelleme yapıldığını belirtir;\n"
+"ancak bu denetleme kapatılmış; yeniden açmak için '--show-forced-updates'\n"
+"bayrağını kullanın veya 'git config fetch.showForcedUpdates true' çalıştırın"
+
+#, c-format
+msgid ""
+"it took %.2f seconds to check forced updates; you can use\n"
+"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
+"false'\n"
+"to avoid this check\n"
+msgstr ""
+"Zorla güncellemeleri denetleme %.2f saniye sürdü. '--no-show-forced-"
+"updates'\n"
+"kullanarak veya 'git config fetch.showForcedUpdates false' çalıştırarak\n"
+"bu denetlemeden kaçınabilirsiniz.\n"
+
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s tüm gerekli nesneleri göndermedi\n"
+
+#, c-format
+msgid "rejected %s because shallow roots are not allowed to be updated"
+msgstr "%s reddedildi; çünkü sığ köklerin güncellenmesine izin verilmiyor"
+
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+"bazı yerel başvurular güncellenemedi; 'git remote prune %s'\n"
+"kullanarak eski ve çakışan dalları kaldırmayı deneyin"
+
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr "   (%s sarkacak)"
+
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr "   (%s sarkmaya başladı)"
+
+msgid "[deleted]"
+msgstr "[silindi]"
+
+msgid "(none)"
+msgstr "(hiçbiri)"
+
+#, c-format
+msgid "refusing to fetch into branch '%s' checked out at '%s'"
+msgstr "'%s' dalına getirme reddediliyor, '%s' konumunda çıkış yapıldı"
+
+#, c-format
+msgid "option \"%s\" value \"%s\" is not valid for %s"
+msgstr "\"%s\" seçeneği \"%s\" değeri %s için geçerli değil"
+
+#, c-format
+msgid "option \"%s\" is ignored for %s\n"
+msgstr "\"%s\" seçeneği %s için yok sayılıyor\n"
+
+#, c-format
+msgid "%s is not a valid object"
+msgstr "%s geçerli bir nesne değil"
+
+#, c-format
+msgid "the object %s does not exist"
+msgstr "%s diye bir nesne yok"
+
+msgid "multiple branches detected, incompatible with --set-upstream"
+msgstr "birden çok dal algılandı, --set-upstream ile uyumsuz"
+
+#, c-format
+msgid ""
+"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
+"any branch."
+msgstr ""
+"HEAD'in üst kaynağı '%s' olarak '%s' konumundan ayarlanamadı; çünkü herhangi "
+"bir dala işaret etmiyor."
+
+msgid "not setting upstream for a remote remote-tracking branch"
+msgstr "bir uzak konum uzak izleme dalı için üstkaynak ayarlanmıyor"
+
+msgid "not setting upstream for a remote tag"
+msgstr "bir uzak konum etiketi için üstkaynak ayarlanmıyor"
+
+msgid "unknown branch type"
+msgstr "bilinmeyen dal türü"
+
+msgid ""
+"no source branch found;\n"
+"you need to specify exactly one branch with the --set-upstream option"
+msgstr ""
+"Kaynak dal bulunamadı;\n"
+"--set-upstream seçeneği ile tam olarak bir dal belirtmeniz gerekiyor"
+
+#, c-format
+msgid "Fetching %s\n"
+msgstr "%s getiriliyor\n"
+
+#, c-format
+msgid "could not fetch %s"
+msgstr "%s getirilemedi"
+
+#, c-format
+msgid "could not fetch '%s' (exit code: %d)\n"
+msgstr "'%s' getirilemedi (çıkış kodu: %d)\n"
+
+msgid ""
+"no remote repository specified; please specify either a URL or a\n"
+"remote name from which new revisions should be fetched"
+msgstr ""
+"Bir uzak dal belirtilmedi; lütfen yeni revizyonların\n"
+"getirileceği bir URL veya uzak konum adı belirtin"
+
+msgid "you need to specify a tag name"
+msgstr "bir etiket adı belirtmeniz gerekiyor"
+
 msgid "fetch from all remotes"
 msgstr "tüm uzak konumlardan getir"
 
@@ -5842,174 +6045,6 @@
 msgid "accept refspecs from stdin"
 msgstr "başvuru belirteçlerini stdin'den oku"
 
-msgid "couldn't find remote ref HEAD"
-msgstr "uzak HEAD başvurusu bulunamadı"
-
-#, c-format
-msgid "object %s not found"
-msgstr "%s nesnesi bulunamadı"
-
-msgid "[up to date]"
-msgstr "[güncel]"
-
-msgid "[rejected]"
-msgstr "[reddedildi]"
-
-msgid "can't fetch into checked-out branch"
-msgstr "çıkış yapılmış dala getirilemiyor"
-
-msgid "[tag update]"
-msgstr "[etiket güncellemesi]"
-
-msgid "unable to update local ref"
-msgstr "yerel başvuru güncellenemiyor"
-
-msgid "would clobber existing tag"
-msgstr "var olan etiketi değiştirecektir"
-
-msgid "[new tag]"
-msgstr "[yeni etiket]"
-
-msgid "[new branch]"
-msgstr "[yeni dal]"
-
-msgid "[new ref]"
-msgstr "[yeni başvuru]"
-
-msgid "forced update"
-msgstr "zorlanmış güncelleme"
-
-msgid "non-fast-forward"
-msgstr "ileri sarım değil"
-
-#, c-format
-msgid "cannot open '%s'"
-msgstr "'%s' açılamıyor"
-
-msgid ""
-"fetch normally indicates which branches had a forced update,\n"
-"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
-"flag or run 'git config fetch.showForcedUpdates true'"
-msgstr ""
-"Getirme, normalde hangi dallarda zorla güncelleme yapıldığını belirtir;\n"
-"ancak bu denetleme kapatılmış; yeniden açmak için '--show-forced-updates'\n"
-"bayrağını kullanın veya 'git config fetch.showForcedUpdates true' çalıştırın"
-
-#, c-format
-msgid ""
-"it took %.2f seconds to check forced updates; you can use\n"
-"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
-"false'\n"
-"to avoid this check\n"
-msgstr ""
-"Zorla güncellemeleri denetleme %.2f saniye sürdü. '--no-show-forced-"
-"updates'\n"
-"kullanarak veya 'git config fetch.showForcedUpdates false' çalıştırarak\n"
-"bu denetlemeden kaçınabilirsiniz.\n"
-
-#, c-format
-msgid "%s did not send all necessary objects\n"
-msgstr "%s tüm gerekli nesneleri göndermedi\n"
-
-#, c-format
-msgid "rejected %s because shallow roots are not allowed to be updated"
-msgstr "%s reddedildi; çünkü sığ köklerin güncellenmesine izin verilmiyor"
-
-#, c-format
-msgid "From %.*s\n"
-msgstr "Şu konumdan: %.*s\n"
-
-#, c-format
-msgid ""
-"some local refs could not be updated; try running\n"
-" 'git remote prune %s' to remove any old, conflicting branches"
-msgstr ""
-"bazı yerel başvurular güncellenemedi; 'git remote prune %s'\n"
-"kullanarak eski ve çakışan dalları kaldırmayı deneyin"
-
-#, c-format
-msgid "   (%s will become dangling)"
-msgstr "   (%s sarkacak)"
-
-#, c-format
-msgid "   (%s has become dangling)"
-msgstr "   (%s sarkmaya başladı)"
-
-msgid "[deleted]"
-msgstr "[silindi]"
-
-msgid "(none)"
-msgstr "(hiçbiri)"
-
-#, c-format
-msgid "refusing to fetch into branch '%s' checked out at '%s'"
-msgstr "'%s' dalına getirme reddediliyor, '%s' konumunda çıkış yapıldı"
-
-#, c-format
-msgid "option \"%s\" value \"%s\" is not valid for %s"
-msgstr "\"%s\" seçeneği \"%s\" değeri %s için geçerli değil"
-
-#, c-format
-msgid "option \"%s\" is ignored for %s\n"
-msgstr "\"%s\" seçeneği %s için yok sayılıyor\n"
-
-#, c-format
-msgid "%s is not a valid object"
-msgstr "%s geçerli bir nesne değil"
-
-#, c-format
-msgid "the object %s does not exist"
-msgstr "%s diye bir nesne yok"
-
-msgid "multiple branches detected, incompatible with --set-upstream"
-msgstr "birden çok dal algılandı, --set-upstream ile uyumsuz"
-
-#, c-format
-msgid ""
-"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
-"any branch."
-msgstr ""
-"HEAD'in üst kaynağı '%s' olarak '%s' konumundan ayarlanamadı; çünkü herhangi "
-"bir dala işaret etmiyor."
-
-msgid "not setting upstream for a remote remote-tracking branch"
-msgstr "bir uzak konum uzak izleme dalı için üstkaynak ayarlanmıyor"
-
-msgid "not setting upstream for a remote tag"
-msgstr "bir uzak konum etiketi için üstkaynak ayarlanmıyor"
-
-msgid "unknown branch type"
-msgstr "bilinmeyen dal türü"
-
-msgid ""
-"no source branch found;\n"
-"you need to specify exactly one branch with the --set-upstream option"
-msgstr ""
-"Kaynak dal bulunamadı;\n"
-"--set-upstream seçeneği ile tam olarak bir dal belirtmeniz gerekiyor"
-
-#, c-format
-msgid "Fetching %s\n"
-msgstr "%s getiriliyor\n"
-
-#, c-format
-msgid "could not fetch %s"
-msgstr "%s getirilemedi"
-
-#, c-format
-msgid "could not fetch '%s' (exit code: %d)\n"
-msgstr "'%s' getirilemedi (çıkış kodu: %d)\n"
-
-msgid ""
-"no remote repository specified; please specify either a URL or a\n"
-"remote name from which new revisions should be fetched"
-msgstr ""
-"Bir uzak dal belirtilmedi; lütfen yeni revizyonların\n"
-"getirileceği bir URL veya uzak konum adı belirtin"
-
-msgid "you need to specify a tag name"
-msgstr "bir etiket adı belirtmeniz gerekiyor"
-
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr "--negotiate-only'e bir veya daha çok --negotiation-tip=* gerekiyor"
 
@@ -6125,6 +6160,12 @@
 msgid "print only refs which don't contain the commit"
 msgstr "yalnızca işlemeyi içermeyen başvuruları yazdır"
 
+msgid "read reference patterns from stdin"
+msgstr "başvuru dizgilerini stdin'den oku"
+
+msgid "unknown arguments supplied with --stdin"
+msgstr "--stdin ile bilinmeyen argümanlar verilmiş"
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<yapılandırma> [--] <argümanlar>"
 
@@ -6137,6 +6178,10 @@
 msgid "missing --config=<config>"
 msgstr "--config=<yapılandırma> eksik"
 
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "hatayı yapılandırma alındı, --config=%s"
+
 msgid "unknown"
 msgstr "bilinmeyen"
 
@@ -6283,19 +6328,28 @@
 msgid "notice: %s points to an unborn branch (%s)"
 msgstr "Uyarı: %s henüz doğmamış bir dala işaret ediyor (%s)"
 
-msgid "Checking cache tree"
-msgstr "Önbellek ağacı denetleniyor"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "%s ögesinin önbellek ağacı denetleniyor"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "%s: cache-tree içinde geçersiz sha1 işaretçisi"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s: %s ögesinin cache-tree'si içinde geçersiz sha1 işaretçisi"
 
 msgid "non-tree in cache-tree"
 msgstr "cache-tree içinde ağaç olmayan öge"
 
 #, c-format
-msgid "%s: invalid sha1 pointer in resolve-undo"
-msgstr "%s: resolve-undo içinde geçersiz sha1 işaretçisi"
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s: %s ögesinin resolve-undo'su içinde geçersiz sha1 işaretçisi"
+
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "'%s' paketi için rev-index yüklenemiyor"
+
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "'%s' paketi için geçersiz rev-index"
 
 msgid ""
 "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
@@ -9139,6 +9193,12 @@
 msgid "bad index version '%s'"
 msgstr "hatalı indeks sürümü '%s'"
 
+msgid "show progress meter during object writing phase"
+msgstr "ilerleme çubuğunu nesne yazımı aşaması sırasında göster"
+
+msgid "similar to --all-progress when progress meter is shown"
+msgstr "ilerleme çubuğu gösterildiğinde --all-progress'e benzer"
+
 msgid "<version>[,<offset>]"
 msgstr "<sürüm>[,<ofset>]"
 
@@ -9329,6 +9389,9 @@
 "<git@vger.kernel.org> adresine bir e-posta atarak\n"
 "bize haber verin. Sağ olun.\n"
 
+msgid "refusing to run without --i-still-use-this"
+msgstr "--i-still-use-this olmadan çalıştırma reddediliyor"
+
 msgid "git pack-refs [--all] [--no-prune]"
 msgstr "git pack-refs [--all] [--no-prune]"
 
@@ -9499,7 +9562,7 @@
 msgid "pull with rebase"
 msgstr "yeniden temellendirme ile çekim"
 
-msgid "please commit or stash them."
+msgid "Please commit or stash them."
 msgstr "Lütfen onları işleyin veya zulalayın."
 
 #, c-format
@@ -9735,8 +9798,8 @@
 msgid "repository"
 msgstr "depo"
 
-msgid "push all refs"
-msgstr "tüm başvuruları it"
+msgid "push all branches"
+msgstr "tüm dalları it"
 
 msgid "mirror all refs"
 msgstr "tüm başvuruları yansıla"
@@ -9744,11 +9807,11 @@
 msgid "delete refs"
 msgstr "başvuruları sil"
 
-msgid "push tags (can't be used with --all or --mirror)"
-msgstr "etiketleri it (--all veya --mirror ile kullanılamaz)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr "etiketleri it (--all, --branches  veya --mirror ile kullanılamaz)"
 
 msgid "force updates"
-msgstr "zorla güncelle"
+msgstr "güncellemeleri zorla"
 
 msgid "<refname>:<expect>"
 msgstr "<bşvr-adı>:<bekle>"
@@ -10009,6 +10072,10 @@
 "Bunun sonucu olarak git onları yeniden temellendiremiyor."
 
 #, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "Bilinmeyen rebase-merges kipi: %s"
+
+#, c-format
 msgid "could not switch to %s"
 msgstr "şuraya geçilemedi: %s"
 
@@ -10022,6 +10089,15 @@
 msgstr ""
 "Tanımlanamayan boş tür '%s'; geçerli türler: \"drop\", \"keep\" ve \"ask\"."
 
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"bir boş dizi argümanıyla --rebase-merges yapmak artık kullanılmıyor ve "
+"Git'in ileriki bir sürümünde tümüyle kaldırılacak. Bunun yerine, aynı şeyi "
+"yapan argümansız bir --rebase-merges kullanın."
+
 #, c-format
 msgid ""
 "%s\n"
@@ -10243,18 +10319,21 @@
 msgid "switch `C' expects a numerical value"
 msgstr "'C' anahtarı sayısal bir değer bekliyor"
 
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "Bilinmeyen kip: %s"
-
 msgid "--strategy requires --merge or --interactive"
 msgstr "--strategy, --merge veya --interactive gerektiriyor"
 
 msgid ""
-"apply options are incompatible with rebase.autosquash.  Consider adding --no-"
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
 "autosquash"
 msgstr ""
-"uygulama seçenekleri, rebase.autosquash ile uyumlu değil. --no-autosquash "
+"seçenekleri uygula, rebase.autoSquash ile uyumlu değil. --no-autosquash "
+"eklemeyi düşünün"
+
+msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr ""
+"seçenekleri uygula, rebase.rebaseMerges ile uyumlu değil. --no-rebase-merges "
 "eklemeyi düşünün"
 
 msgid ""
@@ -10301,9 +10380,6 @@
 msgid "Does not point to a valid commit '%s'"
 msgstr "'%s' geçerli bir işlemeye işaret etmiyor"
 
-msgid "Please commit or stash them."
-msgstr "Lütfen onları işleyin veya zulalayın."
-
 msgid "HEAD is up to date."
 msgstr "HEAD güncel."
 
@@ -10965,8 +11041,8 @@
 msgid "approxidate"
 msgstr "yaklaşık tarih"
 
-msgid "with -C, expire objects older than this"
-msgstr "-C ile, bundan daha eski nesneleri yürürlükten kaldır"
+msgid "with --cruft, expire objects older than this"
+msgstr "--cruft ile, bundan daha eski nesneleri yürürlükten kaldır"
 
 msgid "remove redundant packs, and run git-prune-packed"
 msgstr "gereksiz paketleri kaldır ve 'git-prune-packed' çalıştır"
@@ -11634,6 +11710,9 @@
 msgid "remote name"
 msgstr "uzak konum adı"
 
+msgid "push all refs"
+msgstr "tüm başvuruları it"
+
 msgid "use stateless RPC protocol"
 msgstr "durumsuz RPC protokolünü kullan"
 
@@ -11834,9 +11913,11 @@
 msgstr "stdin'den yerel bir depoda olmayan başvuruları göster"
 
 msgid ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<sçnklr>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<seçenekler>]"
 
 msgid "this worktree is not sparse"
 msgstr "bu çalışma ağacı aralıklı değil"
@@ -11958,6 +12039,23 @@
 msgid "error while refreshing working directory"
 msgstr "çalışma dizini yenilenirken hata"
 
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <dosya>]"
+
+msgid "terminate input and output files by a NUL character"
+msgstr "girdi ve çıktı dosyalarını bir NUL karakteri ile sonlandır"
+
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr ""
+"--rules-file ile kullanıldığında dizgileri koni kipi dizgileri olarak yorumla"
+
+msgid "use patterns in <file> instead of the current ones."
+msgstr "geçerli dizgiler yerine <dosya> içindekileri kullan."
+
 msgid "git stash list [<log-options>]"
 msgstr "git stash list [<günlük-seçenekleri>]"
 
@@ -14778,8 +14876,8 @@
 msgid "bad zlib compression level %d"
 msgstr "hatalı zlib sıkıştırma düzeyi %d"
 
-msgid "core.commentChar should only be one character"
-msgstr "core.commentChar yalnızca bir karakter olmalı"
+msgid "core.commentChar should only be one ASCII character"
+msgstr "core.commentChar yalnızca bir ASCII karakter olmalı"
 
 #, c-format
 msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -14890,6 +14988,10 @@
 msgstr "geçersiz bölüm adı: %s"
 
 #, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr "'%s' içindeki haddinden uzun %<PRIuMAX>. satırla çalışma reddediliyor"
+
+#, c-format
 msgid "missing value for '%s'"
 msgstr "'%s' için değer eksik"
 
@@ -15559,6 +15661,9 @@
 msgid "do not show any source or destination prefix"
 msgstr "hiçbir kaynak ve hedef önekini gösterme"
 
+msgid "use default prefixes a/ and b/"
+msgstr "a/ ve b/ ögelerinin öntanımlı öneklerini kullan"
+
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr "diff parçaları arasındaki bağlamı belirtilen satır sayısı kadar göster"
 
@@ -15856,6 +15961,14 @@
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "İpucu: Düzenleyicinizin dosyayı kapatması bekleniyor...%c"
 
+#, c-format
+msgid "could not write to '%s'"
+msgstr "şuraya yazılamadı: '%s'"
+
+#, c-format
+msgid "could not edit '%s'"
+msgstr "'%s' düzenlenemedi"
+
 msgid "Filtering content"
 msgstr "İçerik süzülüyor"
 
@@ -16151,6 +16264,10 @@
 msgstr "--config-env için bir yapılandırma anahtarı verilmedi\n"
 
 #, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "--attr-source için öznitelik kaynağı verilmedi\n"
+
+#, c-format
 msgid "unknown option: %s\n"
 msgstr "bilinmeyen seçenek: %s\n"
 
@@ -17823,6 +17940,10 @@
 msgstr "'%s' ögesinin disk kullanımı alınamadı"
 
 #, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "biteşlem dosyası '%s', geçersiz sağlama toplamına iye"
+
+#, c-format
 msgid "mtimes file %s is too small"
 msgstr "mtimes dosyası %s pek küçük"
 
@@ -17862,6 +17983,13 @@
 msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
 msgstr "%s reverse-index dosyasının sağlama numarası %<PRIu32> desteklenmiyor"
 
+msgid "invalid checksum"
+msgstr "geçersiz sağlama toplamı"
+
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr "%<PRIu64> konumunda geçersiz rev-index konumu: %<PRIu32> != %<PRIu32>"
+
 msgid "cannot both write and verify reverse index"
 msgstr "ters indeks dosyası hem yazılıp hem doğrulanamıyor"
 
@@ -18573,6 +18701,10 @@
 msgstr "pozitif genişlik %%(align) ögeciği ile birlikte bekleniyordu"
 
 #, c-format
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "beklenen biçim: %%(ahead-behind:<işlememsi>)"
+
+#, c-format
 msgid "malformed field name: %.*s"
 msgstr "hatalı oluşturulmuş alan adı: %.*s"
 
@@ -19194,10 +19326,6 @@
 msgstr "'%s' için hatırlanan çözüm yok"
 
 #, c-format
-msgid "cannot unlink '%s'"
-msgstr "'%s' bağlantısı kesilemiyor"
-
-#, c-format
 msgid "Updated preimage for '%s'"
 msgstr "'%s' için öngörüntü güncellendi"
 
@@ -19531,10 +19659,6 @@
 msgstr "'%s' kilitlenemedi"
 
 #, c-format
-msgid "could not write to '%s'"
-msgstr "şuraya yazılamadı: '%s'"
-
-#, c-format
 msgid "could not write eol to '%s'"
 msgstr "satır sonu şuraya yazılamadı: '%s'"
 
@@ -19894,9 +20018,6 @@
 msgid "could not create sequencer directory '%s'"
 msgstr "ardıştırıcı dizini '%s' oluşturulamadı"
 
-msgid "could not lock HEAD"
-msgstr "HEAD kilitlenemedi"
-
 msgid "no cherry-pick or revert in progress"
 msgstr "süren bir seç-al veya geri al yok"
 
@@ -19991,20 +20112,20 @@
 "\tgit rebase --continue\n"
 "\n"
 
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "ve indekse ve/veya çalışma ağacına değişiklikler yapıldı\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "ve indekse ve/veya çalışma ağacına değişiklikler yapıldı.\n"
 
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
 msgstr ""
-"Yürütme başarılı oldu: %s,\n"
-"ancak indeksinize ve/veya çalışma ağacınıza değişiklikler bıraktı\n"
+"Yürütme başarılı oldu: %s;\n"
+"ancak indeksinize ve/veya çalışma ağacınıza değişiklikler bıraktı.\n"
 "Değişikliklerinizi işleyin veya zulalayın, ardından şunu çalıştırın:\n"
 "\n"
 "\tgit rebase --continue\n"
@@ -20438,10 +20559,6 @@
 msgstr[1] "%u bayt/sn"
 
 #, c-format
-msgid "could not edit '%s'"
-msgstr "'%s' düzenlenemedi"
-
-#, c-format
 msgid "ignoring suspicious submodule name: %s"
 msgstr "kuşku doğuran altmodül yok sayılıyor: %s"
 
@@ -22147,12 +22264,16 @@
 msgstr "(%s) '%s' yürütülemedi"
 
 #, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) %s: %s, '%s' konumundan ekleniyor\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) '%s' ögesinden hatalı oluşturulmuş çıktı"
 
 #, perl-format
 msgid "(%s) failed to close pipe to '%s'"
-msgstr "(%s) şuraya olan veri yolu kapatılamadı: '%s'"
+msgstr "(%s) şuraya olan veriyolu kapatılamadı: '%s'"
+
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) %s: %s, '%s' konumundan ekleniyor\n"
 
 msgid "cannot send message as 7bit"
 msgstr "ileti 7 bit olarak gönderilemiyor"
diff --git a/po/uk.po b/po/uk.po
new file mode 100644
index 0000000..11c57b9
--- /dev/null
+++ b/po/uk.po
@@ -0,0 +1,21554 @@
+# Ukrainian translation for Git package.
+# Український переклад пакету Git.
+# Copyright (c) 2023 Arkadii Yakovets.
+# Copyright (c) 2023 Kateryna Golovanova.
+# This file is distributed under the same license as the Git package.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Git v2.41\n"
+"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
+"POT-Creation-Date: 2023-05-15 23:57+0000\n"
+"PO-Revision-Date: 2023-05-17 13:51-0700\n"
+"Last-Translator: Arkadii Yakovets <ark@cho.red>\n"
+"Language-Team: Ukrainian <https://github.com/arkid15r/git-ukrainian-l10n/>\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
+"X-Generator: Poedit 3.3.1\n"
+
+#, c-format
+msgid "Huh (%s)?"
+msgstr "Га (%s)?"
+
+msgid "could not read index"
+msgstr "не вдалося прочитати індекс"
+
+msgid "binary"
+msgstr "бінарний"
+
+msgid "nothing"
+msgstr "нічого"
+
+msgid "unchanged"
+msgstr "без змін"
+
+msgid "Update"
+msgstr "Оновити"
+
+#, c-format
+msgid "could not stage '%s'"
+msgstr "не вдалося додати до індекса %s"
+
+msgid "could not write index"
+msgstr "не вдалося записати індекс"
+
+#, c-format
+msgid "updated %d path\n"
+msgid_plural "updated %d paths\n"
+msgstr[0] "оновлено %d шлях\n"
+msgstr[1] "оновлено %d шляхи\n"
+msgstr[2] "оновлено %d шляхів\n"
+
+#, c-format
+msgid "note: %s is untracked now.\n"
+msgstr "примітка: %s зараз не відстежується.\n"
+
+#, c-format
+msgid "make_cache_entry failed for path '%s'"
+msgstr "невдала спроба make_cache_entry для шляху '%s'"
+
+msgid "Revert"
+msgstr "Вивернути"
+
+msgid "Could not parse HEAD^{tree}"
+msgstr "Не вдалося розібрати HEAD^{tree}"
+
+#, c-format
+msgid "reverted %d path\n"
+msgid_plural "reverted %d paths\n"
+msgstr[0] "вивернуто %d шлях\n"
+msgstr[1] "вивернуто %d шляхи\n"
+msgstr[2] "вивернуто %d шляхів\n"
+
+#, c-format
+msgid "No untracked files.\n"
+msgstr "Невідстежуваних файлів немає\n"
+
+msgid "Add untracked"
+msgstr "Додати невідстежувані"
+
+#, c-format
+msgid "added %d path\n"
+msgid_plural "added %d paths\n"
+msgstr[0] "додано %d шлях\n"
+msgstr[1] "додано %d шляхи\n"
+msgstr[2] "додано %d шляхів\n"
+
+#, c-format
+msgid "ignoring unmerged: %s"
+msgstr "ігноруються незлиті записи: %s"
+
+#, c-format
+msgid "Only binary files changed.\n"
+msgstr "Змінилися лише бінарні файли.\n"
+
+#, c-format
+msgid "No changes.\n"
+msgstr "Нічого не змінено.\n"
+
+msgid "Patch update"
+msgstr "Оновлення патча"
+
+msgid "Review diff"
+msgstr "Переглянути різницю"
+
+msgid "show paths with changes"
+msgstr "показати шляхи зі змінами"
+
+msgid "add working tree state to the staged set of changes"
+msgstr "додати стан робочого дерева до індексу"
+
+msgid "revert staged set of changes back to the HEAD version"
+msgstr "вивернути зміни індексу до версії HEAD"
+
+msgid "pick hunks and update selectively"
+msgstr "вибирати шматки і оновлювати вибірково"
+
+msgid "view diff between HEAD and index"
+msgstr "переглянути різницю між HEAD та індексом"
+
+msgid "add contents of untracked files to the staged set of changes"
+msgstr "додати вміст невідстежуваних файлів до індексу"
+
+msgid "Prompt help:"
+msgstr "Інформація про опції:"
+
+msgid "select a single item"
+msgstr "вибрати один елемент"
+
+msgid "select a range of items"
+msgstr "вибрати діапазон елементів"
+
+msgid "select multiple ranges"
+msgstr "вибрати кілька діапазонів"
+
+msgid "select item based on unique prefix"
+msgstr "вибрати елемент за унікальним префіксом"
+
+msgid "unselect specified items"
+msgstr "зняти позначку із зазначених елементів"
+
+msgid "choose all items"
+msgstr "вибрати всі елементи"
+
+msgid "(empty) finish selecting"
+msgstr "(пусто) закінчити вибір"
+
+msgid "select a numbered item"
+msgstr "вибрати пронумерований елемент"
+
+msgid "(empty) select nothing"
+msgstr "(пусто) нічого не вибирати"
+
+msgid "*** Commands ***"
+msgstr "*** Команди ***"
+
+msgid "What now"
+msgstr "Що тепер"
+
+msgid "staged"
+msgstr "в індексі"
+
+msgid "unstaged"
+msgstr "поза індексом"
+
+msgid "path"
+msgstr "шлях"
+
+msgid "could not refresh index"
+msgstr "не вдалося оновити індекс"
+
+#, c-format
+msgid "Bye.\n"
+msgstr "До побачення.\n"
+
+#, c-format
+msgid "Stage mode change [y,n,q,a,d%s,?]? "
+msgstr "Індексувати зміну режиму [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Stage deletion [y,n,q,a,d%s,?]? "
+msgstr "Індексувати видалення [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Stage addition [y,n,q,a,d%s,?]? "
+msgstr "Індексувати додавання [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Stage this hunk [y,n,q,a,d%s,?]? "
+msgstr "Індексувати цей шматок [y,n,q,a,d%s,?]? "
+
+msgid ""
+"If the patch applies cleanly, the edited hunk will immediately be marked for "
+"staging."
+msgstr ""
+"Якщо патч буде застосовано без помилок, відредагований шматок буде одразу ж "
+"позначено для індексації."
+
+msgid ""
+"y - stage this hunk\n"
+"n - do not stage this hunk\n"
+"q - quit; do not stage this hunk or any of the remaining ones\n"
+"a - stage this hunk and all later hunks in the file\n"
+"d - do not stage this hunk or any of the later hunks in the file\n"
+msgstr ""
+"y - індексувати цей шматок\n"
+"n - не індексувати цей шматок\n"
+"q - вийти; не індексувати ні цей шматок, ні решту\n"
+"a - індексувати цей шматок і всі наступні шматки у файлі\n"
+"d - не індексувати цей шматок і всі наступні шматки у файлі\n"
+
+#, c-format
+msgid "Stash mode change [y,n,q,a,d%s,?]? "
+msgstr "Сховати зміну режиму [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Stash deletion [y,n,q,a,d%s,?]? "
+msgstr "Сховати видалення [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Stash addition [y,n,q,a,d%s,?]? "
+msgstr "Сховати додавання [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Stash this hunk [y,n,q,a,d%s,?]? "
+msgstr "Сховати цей шматок [y,n,q,a,d%s,?]? "
+
+msgid ""
+"If the patch applies cleanly, the edited hunk will immediately be marked for "
+"stashing."
+msgstr ""
+"Якщо патч буде застосовано без помилок, відредагований шматок буде одразу ж "
+"позначено для схову."
+
+msgid ""
+"y - stash this hunk\n"
+"n - do not stash this hunk\n"
+"q - quit; do not stash this hunk or any of the remaining ones\n"
+"a - stash this hunk and all later hunks in the file\n"
+"d - do not stash this hunk or any of the later hunks in the file\n"
+msgstr ""
+"y - сховати цей шматок\n"
+"n - не ховати цей шматок\n"
+"q - вийти; не ховати ні цей шматок, ні решту\n"
+"a - сховати цей шматок і всі наступні шматки у файлі\n"
+"d - не ховати цей шматок і всі наступні шматки у файлі\n"
+
+#, c-format
+msgid "Unstage mode change [y,n,q,a,d%s,?]? "
+msgstr "Розіндексувати зміну режиму [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Unstage deletion [y,n,q,a,d%s,?]? "
+msgstr "Розіндексувати видалення [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Unstage addition [y,n,q,a,d%s,?]? "
+msgstr "Розіндексувати додавання [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Unstage this hunk [y,n,q,a,d%s,?]? "
+msgstr "Розіндексувати цей шматок [y,n,q,a,d%s,?]? "
+
+msgid ""
+"If the patch applies cleanly, the edited hunk will immediately be marked for "
+"unstaging."
+msgstr ""
+"Якщо патч буде застосовано без помилок, відредагований шматок буде одразу ж "
+"позначено для розіндексації."
+
+msgid ""
+"y - unstage this hunk\n"
+"n - do not unstage this hunk\n"
+"q - quit; do not unstage this hunk or any of the remaining ones\n"
+"a - unstage this hunk and all later hunks in the file\n"
+"d - do not unstage this hunk or any of the later hunks in the file\n"
+msgstr ""
+"y - розіндексувати цей шматок\n"
+"n - не розіндексовувати цей шматок\n"
+"q - вийти; не розіндексовувати ні цей шматок, ні решту\n"
+"a - розіндексувати цей шматок і всі наступні шматки у файлі\n"
+"d - не розіндексувати цей шматок і всі наступні шматки у файлі\n"
+
+#, c-format
+msgid "Apply mode change to index [y,n,q,a,d%s,?]? "
+msgstr "Застосувати зміну режиму до індексу [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Apply deletion to index [y,n,q,a,d%s,?]? "
+msgstr "Застосувати видалення до індексу [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Apply addition to index [y,n,q,a,d%s,?]? "
+msgstr "Застосувати додавання до індексу [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Apply this hunk to index [y,n,q,a,d%s,?]? "
+msgstr "Застосувати цей шматок до індексу [y,n,q,a,d%s,?]? "
+
+msgid ""
+"If the patch applies cleanly, the edited hunk will immediately be marked for "
+"applying."
+msgstr ""
+"Якщо патч буде застосовано без помилок, відредагований шматок буде одразу ж "
+"позначено для застосування."
+
+msgid ""
+"y - apply this hunk to index\n"
+"n - do not apply this hunk to index\n"
+"q - quit; do not apply this hunk or any of the remaining ones\n"
+"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 - застосувати цей шматок до індексу\n"
+"n - не застосовувати цей шматок до індексу\n"
+"q - вийти; не застосовувати ні цей шматок, ні решту\n"
+"a - застосувати цей шматок і всі наступні шматки у файлі\n"
+"d - не застосовувати цей шматок і всі наступні шматки у файлі\n"
+
+#, c-format
+msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? "
+msgstr "Відкинути зміну режиму з робочого дерева [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? "
+msgstr "Відкинути видалення з робочого дерева [y,n,q,a,d%s,?] "
+
+#, c-format
+msgid "Discard addition from worktree [y,n,q,a,d%s,?]? "
+msgstr "Відкинути додавання з робочого дерева [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? "
+msgstr "Відкинути цей шматок з робочого дерева [y,n,q,a,d%s,?]? "
+
+msgid ""
+"If the patch applies cleanly, the edited hunk will immediately be marked for "
+"discarding."
+msgstr ""
+"Якщо патч буде застосовано без помилок, відредагований шматок буде одразу ж "
+"позначено для відкидання."
+
+msgid ""
+"y - discard this hunk from worktree\n"
+"n - do not discard this hunk from worktree\n"
+"q - quit; do not discard this hunk or any of the remaining ones\n"
+"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 - відкинути цей шматок з робочого дерева\n"
+"n - не відкидати цей шматок з робочого дерева\n"
+"q - вийти; не відкидати ні цей шматок, ні решту\n"
+"a - відкинути цей шматок і всі наступні шматки у файлі\n"
+"d - не відкидати цей шматок і всі наступні шматки у файлі\n"
+
+#, c-format
+msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? "
+msgstr "Відкинути зміну режиму з індексу та робочого дерева [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? "
+msgstr "Відкинути видалення з індексу та робочого дерева [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? "
+msgstr "Відкинути додавання з індексу та робочого дерева [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? "
+msgstr "Відкинути цей шматок з індексу та робочого дерева [y,n,q,a,d%s,?]? "
+
+msgid ""
+"y - discard this hunk from index and worktree\n"
+"n - do not discard this hunk from index and worktree\n"
+"q - quit; do not discard this hunk or any of the remaining ones\n"
+"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 - відкинути цей шматок з індексу та робочого дерева\n"
+"n - не відкидати цей шматок з індексу та робочого дерева\n"
+"q - вийти; не відкидати ні цей шматок, ні решту\n"
+"a - відкинути цей шматок і всі наступні шматки у файлі\n"
+"d - не відкидати цей шматок і всі наступні шматки у файлі\n"
+
+#, c-format
+msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? "
+msgstr ""
+"Застосувати зміну режиму до індексу та робочого дерева [y,n,q,a,d%s,?] "
+
+#, c-format
+msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? "
+msgstr "Застосувати видалення до індексу та робочого дерева [y,n,q,a,d%s,?] "
+
+#, c-format
+msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? "
+msgstr "Застосувати додавання до індексу та робочого дерева [y,n,q,a,d%s,?] "
+
+#, c-format
+msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "
+msgstr "Застосувати цей шматок до індексу та робочого дерева [y,n,q,a,d%s,?] "
+
+msgid ""
+"y - apply this hunk to index and worktree\n"
+"n - do not apply this hunk to index and worktree\n"
+"q - quit; do not apply this hunk or any of the remaining ones\n"
+"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 - застосувати цей шматок до індексу та робочого дерева\n"
+"n - не застосовувати цей шматок до індексу та робочого дерева\n"
+"q - вийти; не застосовувати ні цей шматок, ні решту\n"
+"a - застосувати цей шматок і всі наступні шматки у файлі\n"
+"d - не застосовувати цей шматок і всі наступні шматки у файлі\n"
+
+#, c-format
+msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? "
+msgstr "Застосувати зміну режиму до робочого дерева [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? "
+msgstr "Застосувати видалення до робочого дерева [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Apply addition to worktree [y,n,q,a,d%s,?]? "
+msgstr "Застосувати додавання до робочого дерева [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? "
+msgstr "Застосувати цей шматок до робочого дерева [y,n,q,a,d%s,?]? "
+
+msgid ""
+"y - apply this hunk to worktree\n"
+"n - do not apply this hunk to worktree\n"
+"q - quit; do not apply this hunk or any of the remaining ones\n"
+"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 - застосувати цей шматок до робочого дерева\n"
+"n - не застосовувати цей шматок до робочого дерева\n"
+"q - вийти; не застосовувати ні цей шматок, ні решту\n"
+"a - застосувати цей шматок і всі наступні шматки у файлі\n"
+"d - не застосовувати цей шматок і всі наступні шматки у файлі\n"
+
+#, c-format
+msgid "could not parse hunk header '%.*s'"
+msgstr "не вдалося розібрати заголовок шматка \"%.*s\""
+
+msgid "could not parse diff"
+msgstr "не вдалося розібрати різницю"
+
+msgid "could not parse colored diff"
+msgstr "не вдалося розібрати кольоровану різницю"
+
+#, c-format
+msgid "failed to run '%s'"
+msgstr "не вдалося запустити \"%s\""
+
+msgid "mismatched output from interactive.diffFilter"
+msgstr "неспівпадіння виводу з interactive.diffFilter"
+
+msgid ""
+"Your filter must maintain a one-to-one correspondence\n"
+"between its input and output lines."
+msgstr ""
+"Ваш фільтр повинен підтримувати один до одного відповідність\n"
+"між його вхідними та вихідними рядками."
+
+#, c-format
+msgid ""
+"expected context line #%d in\n"
+"%.*s"
+msgstr ""
+"очікувався рядок контексту #%d в\n"
+"%.*s"
+
+#, c-format
+msgid ""
+"hunks do not overlap:\n"
+"%.*s\n"
+"\tdoes not end with:\n"
+"%.*s"
+msgstr ""
+"шматки не перетинаються:\n"
+"%.*s\n"
+"\tне закінчується на:\n"
+"%.*s"
+
+msgid "Manual hunk edit mode -- see bottom for a quick guide.\n"
+msgstr "Режим ручного редагування шматка -- див. короткий посібник внизу.\n"
+
+#, c-format
+msgid ""
+"---\n"
+"To remove '%c' lines, make them ' ' lines (context).\n"
+"To remove '%c' lines, delete them.\n"
+"Lines starting with %c will be removed.\n"
+msgstr ""
+"---\n"
+"Щоб видалити рядки \"%c\", зробіть їх рядками \" \" (контекст).\n"
+"Щоб видалити рядки \"%c\", вилучіть їх.\n"
+"Буде видалено рядки, що починаються з %c.\n"
+
+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"
+"aborted and the hunk is left unchanged.\n"
+msgstr ""
+"Якщо шматок буде застосований з помилками, вам буде надана можливість\n"
+"відредагувати ще раз.  Якщо всі рядки шматка буде вилучено, то редагування "
+"буде\n"
+"перервано, і шматок залишиться без змін.\n"
+
+msgid "could not parse hunk header"
+msgstr "не вдалося розібрати заголовок шматка"
+
+msgid "'git apply --cached' failed"
+msgstr "\"git apply --cached\" завершився невдало"
+
+#. TRANSLATORS: do not translate [y/n]
+#. The program will only accept that input at this point.
+#. Consider translating (saying "no" discards!) as
+#. (saying "n" for "no" discards!) if the translation
+#. of the word "no" does not start with n.
+#.
+
+msgid ""
+"Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
+msgstr ""
+"Ваш відредагований шматок неможливо застосувати. Відредагувати ще раз "
+"(\"no\" - відкинути!) [y/n]? "
+
+msgid "The selected hunks do not apply to the index!"
+msgstr "Вибрані шматки неможливо застосувати до індексу!"
+
+msgid "Apply them to the worktree anyway? "
+msgstr "Все одно застосувати їх до робочого дерева? "
+
+msgid "Nothing was applied.\n"
+msgstr "Нічого не застосовано.\n"
+
+msgid ""
+"j - leave this hunk undecided, see next undecided hunk\n"
+"J - leave this hunk undecided, see next hunk\n"
+"k - leave this hunk undecided, see previous undecided hunk\n"
+"K - leave this hunk undecided, see previous hunk\n"
+"g - select a hunk to go to\n"
+"/ - search for a hunk matching the given regex\n"
+"s - split the current hunk into smaller hunks\n"
+"e - manually edit the current hunk\n"
+"? - print help\n"
+msgstr ""
+"j - залишити цей шматок невизначеним, перейти до наступного невизначеного "
+"шматка\n"
+"J - залишити цей шматок невизначеним, перейти до наступного шматка\n"
+"k - залишити цей шматок невизначеним, перейти до попереднього невизначеного "
+"шматка\n"
+"K - залишити цей шматок невизначеним, перейти до попереднього шматка\n"
+"g - вибрати шматок, до якого ви хочете перейти\n"
+"/ - шукати шматок, що відповідає заданому регвиру\n"
+"s - розбити поточний шматок на менші шматки\n"
+"e - редагувати поточний шматок вручну\n"
+"? - показати довідку\n"
+
+msgid "No previous hunk"
+msgstr "Немає попереднього шматка"
+
+msgid "No next hunk"
+msgstr "Немає наступного шматка"
+
+msgid "No other hunks to goto"
+msgstr "Немає інших шматків для переходу"
+
+msgid "go to which hunk (<ret> to see more)? "
+msgstr "до якого шматка перейти (<ret>, щоб побачити більше)? "
+
+msgid "go to which hunk? "
+msgstr "до якого шматка перейти? "
+
+#, c-format
+msgid "Invalid number: '%s'"
+msgstr "Неприпустиме число: \"%s\""
+
+#, c-format
+msgid "Sorry, only %d hunk available."
+msgid_plural "Sorry, only %d hunks available."
+msgstr[0] "Вибачте, доступний лише %d шматок."
+msgstr[1] "Вибачте, доступно лише %d шматки."
+msgstr[2] "Вибачте, доступно лише %d шматків."
+
+msgid "No other hunks to search"
+msgstr "Немає інших шматків для пошуку"
+
+msgid "search for regex? "
+msgstr "шукати регвир? "
+
+#, c-format
+msgid "Malformed search regexp %s: %s"
+msgstr "Невірно сформований регвир пошуку %s: %s"
+
+msgid "No hunk matches the given pattern"
+msgstr "Жоден шматок не відповідає заданому шаблону"
+
+msgid "Sorry, cannot split this hunk"
+msgstr "Вибачте, не можу розділити цей шматок"
+
+#, c-format
+msgid "Split into %d hunks."
+msgstr "Розділити на %d шматків."
+
+msgid "Sorry, cannot edit this hunk"
+msgstr "Вибачте, не можу редагувати цей шматок"
+
+msgid "'git apply' failed"
+msgstr "\"git apply\" завершився невдало"
+
+#, c-format
+msgid ""
+"\n"
+"Disable this message with \"git config advice.%s false\""
+msgstr ""
+"\n"
+"Вимкнути це повідомлення можна за допомогою \"git config advice.%s false\""
+
+#, c-format
+msgid "%shint: %.*s%s\n"
+msgstr "%sпідказка: %.*s%s\n"
+
+msgid "Cherry-picking is not possible because you have unmerged files."
+msgstr "Висмикування неможливе, оскільки у вас є не злиті файли."
+
+msgid "Committing is not possible because you have unmerged files."
+msgstr "Створення коміту неможливе, оскільки у вас є не злиті файли."
+
+msgid "Merging is not possible because you have unmerged files."
+msgstr "Злиття неможливе, оскільки у вас є не злиті файли."
+
+msgid "Pulling is not possible because you have unmerged files."
+msgstr "Отримання неможливе, оскільки у вас є не злиті файли."
+
+msgid "Reverting is not possible because you have unmerged files."
+msgstr "Вивертання неможливе, оскільки у вас є не злиті файли."
+
+#, c-format
+msgid "It is not possible to %s because you have unmerged files."
+msgstr "Неможливо виконати %s, оскільки у вас є не злиті файли."
+
+msgid ""
+"Fix them up in the work tree, and then use 'git add/rm <file>'\n"
+"as appropriate to mark resolution and make a commit."
+msgstr ""
+"Виправте їх у робочому дереві, а потім скористайтеся командою \"git add/rm "
+"<файл>\"\n"
+"щоб позначити розвʼязання і зробити коміт."
+
+msgid "Exiting because of an unresolved conflict."
+msgstr "Вихід через нерозв’язаний конфлікт."
+
+msgid "You have not concluded your merge (MERGE_HEAD exists)."
+msgstr "Ви не завершили злиття (існує MERGE_HEAD)."
+
+msgid "Please, commit your changes before merging."
+msgstr "Будь ласка, зробіть коміт ваших змін перед злиттям."
+
+msgid "Exiting because of unfinished merge."
+msgstr "Вихід через незавершене злиття."
+
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"Гілки, що розходяться, не можуть бути перемотані вперед, вам потрібно "
+"зробити:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"або\n"
+"\n"
+"\tgit rebase\n"
+
+msgid "Not possible to fast-forward, aborting."
+msgstr "Неможливо перемотати вперед, переривання."
+
+#, c-format
+msgid ""
+"The following paths and/or pathspecs matched paths that exist\n"
+"outside of your sparse-checkout definition, so will not be\n"
+"updated in the index:\n"
+msgstr ""
+"Наступні шляхи та/або визначники шляхів відповідають шляхам, які існують\n"
+"за межами визначення вашого часткового переходу, тому не будуть\n"
+"оновлені в індексі:\n"
+
+msgid ""
+"If you intend to update such entries, try one of the following:\n"
+"* Use the --sparse option.\n"
+"* Disable or modify the sparsity rules."
+msgstr ""
+"Якщо ви маєте намір оновити такі записи, спробуйте один із наведених нижче "
+"способів:\n"
+"* Використайте параметр --sparse.\n"
+"* Вимкніть або змініть правила частковості."
+
+#, c-format
+msgid ""
+"Note: switching to '%s'.\n"
+"\n"
+"You are in 'detached HEAD' state. You can look around, make experimental\n"
+"changes and commit them, and you can discard any commits you make in this\n"
+"state without impacting any branches by switching back to a branch.\n"
+"\n"
+"If you want to create a new branch to retain commits you create, you may\n"
+"do so (now or later) by using -c with the switch command. Example:\n"
+"\n"
+"  git switch -c <new-branch-name>\n"
+"\n"
+"Or undo this operation with:\n"
+"\n"
+"  git switch -\n"
+"\n"
+"Turn off this advice by setting config variable advice.detachedHead to "
+"false\n"
+"\n"
+msgstr ""
+"Примітка: перемикання на \"%s\".\n"
+"\n"
+"Ви перебуваєте в стані \"відʼєднаного HEAD\". Ви можете озирнутися довкола, "
+"внести експериментальні\n"
+"зміни і зробити коміт, також ви можете відкинути будь-які коміти, зроблені у "
+"цьому\n"
+"стані, не впливаючи на інші гілки, просто перейшовши до іншної гілки.\n"
+"\n"
+"Якщо ви хочете створити нову гілку для збереження зроблених вами комітів, ви "
+"можете\n"
+"використати (зараз або пізніше) -c з командою switch. Наприклад:\n"
+"\n"
+"  git switch -c <назва-нової-гілки\n"
+"\n"
+"Або скасувати цю операцію за допомогою:\n"
+"\n"
+"  git switch -\n"
+"\n"
+"Щоб вимкнути цю пораду, встановіть конфігураційний параметр advice."
+"detachedHead у false\n"
+
+#, c-format
+msgid ""
+"The following paths have been moved outside the\n"
+"sparse-checkout definition but are not sparse due to local\n"
+"modifications.\n"
+msgstr ""
+"Наступні шляхи, що було винесено за межі визначення часткового\n"
+"переходу, не є частковими через локальні\n"
+"зміни.\n"
+
+msgid ""
+"To correct the sparsity of these paths, do the following:\n"
+"* Use \"git add --sparse <paths>\" to update the index\n"
+"* Use \"git sparse-checkout reapply\" to apply the sparsity rules"
+msgstr ""
+"Щоб виправити частковість цих шляхів, виконайте наступне:\n"
+"* Використайте \"git add --sparse <шляхи>\" для оновлення індексу\n"
+"* Використайте \"git sparse-checkout reapply\", щоб застосувати правила "
+"частковості"
+
+msgid "cmdline ends with \\"
+msgstr "cmdline завершується символом \\"
+
+msgid "unclosed quote"
+msgstr "незакриті лапки"
+
+msgid "too many arguments"
+msgstr "забагато аргументів"
+
+#, c-format
+msgid "unrecognized whitespace option '%s'"
+msgstr "нерозпізнана опція пробільних символів \"%s\""
+
+#, c-format
+msgid "unrecognized whitespace ignore option '%s'"
+msgstr "нерозпізнана опція ігнорування пробільних символів \"%s\""
+
+#, c-format
+msgid "options '%s' and '%s' cannot be used together"
+msgstr "опції '%s' і '%s' не можна використовувати разом"
+
+#, c-format
+msgid "'%s' outside a repository"
+msgstr "\"%s\" поза сховищем"
+
+#, c-format
+msgid "Cannot prepare timestamp regexp %s"
+msgstr "Неможливо підготувати регвир позначки часу %s"
+
+#, c-format
+msgid "regexec returned %d for input: %s"
+msgstr "regexec повернув %d для вводу: %s"
+
+#, c-format
+msgid "unable to find filename in patch at line %d"
+msgstr "не вдалося знайти ім’я файлу у латці в рядку %d"
+
+#, c-format
+msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d"
+msgstr ""
+"git apply: невірний git-diff - очікувався /dev/null, отримано %s у рядку %d"
+
+#, c-format
+msgid "git apply: bad git-diff - inconsistent new filename on line %d"
+msgstr ""
+"git apply: невірний git-diff - невідповідне ім’я нового файлу у рядку %d"
+
+#, c-format
+msgid "git apply: bad git-diff - inconsistent old filename on line %d"
+msgstr ""
+"git apply: невірний git-diff - невідповідне ім’я старого файлу у рядку %d"
+
+#, c-format
+msgid "git apply: bad git-diff - expected /dev/null on line %d"
+msgstr "git apply: невірний git-diff - очікувався /dev/null у рядку %d"
+
+#, c-format
+msgid "invalid mode on line %d: %s"
+msgstr "недійсний режим у рядку %d: %s"
+
+#, c-format
+msgid "inconsistent header lines %d and %d"
+msgstr "невідповідні рядки заголовка %d та %d"
+
+#, c-format
+msgid ""
+"git diff header lacks filename information when removing %d leading pathname "
+"component (line %d)"
+msgid_plural ""
+"git diff header lacks filename information when removing %d leading pathname "
+"components (line %d)"
+msgstr[0] ""
+"у заголовку git diff відсутня інформація про назву файла при видаленні %d "
+"провідного компонента назви шляху (рядок %d)"
+msgstr[1] ""
+"у заголовку git diff відсутня інформація про назву файла при видаленні %d "
+"провідних компонентів назви шляху (рядок %d)"
+msgstr[2] ""
+"у заголовку git diff відсутня інформація про назву файла при видаленні %d "
+"провідних компонентів назви шляху (рядок %d)"
+
+#, c-format
+msgid "git diff header lacks filename information (line %d)"
+msgstr "у заголовку git diff відсутня інформація про назву файла (рядок %d)"
+
+#, c-format
+msgid "recount: unexpected line: %.*s"
+msgstr "recount: неочікуваний рядок: %.*s"
+
+#, c-format
+msgid "patch fragment without header at line %d: %.*s"
+msgstr "фрагмент латки без заголовка у рядку %d: %.*s"
+
+msgid "new file depends on old contents"
+msgstr "новий файл залежить від старого вмісту"
+
+msgid "deleted file still has contents"
+msgstr "видалений файл все ще має вміст"
+
+#, c-format
+msgid "corrupt patch at line %d"
+msgstr "пошкоджена латка у рядку %d"
+
+#, c-format
+msgid "new file %s depends on old contents"
+msgstr "новий файл %s залежить від старого вмісту"
+
+#, c-format
+msgid "deleted file %s still has contents"
+msgstr "видалений файл %s все ще має вміст"
+
+#, c-format
+msgid "** warning: file %s becomes empty but is not deleted"
+msgstr "** попередження: файл %s стане порожнім, але не буде видалений"
+
+#, c-format
+msgid "corrupt binary patch at line %d: %.*s"
+msgstr "пошкоджена бінарна латка у рядку %d: %.*s"
+
+#, c-format
+msgid "unrecognized binary patch at line %d"
+msgstr "нерозпізнана бінарна латка у рядку %d"
+
+#, c-format
+msgid "patch with only garbage at line %d"
+msgstr "латка, що містить лише непотріб у рядку %d"
+
+#, c-format
+msgid "unable to read symlink %s"
+msgstr "не вдалося прочитати символьне посилання %s"
+
+#, c-format
+msgid "unable to open or read %s"
+msgstr "не вдалося відкрити або прочитати %s"
+
+#, c-format
+msgid "invalid start of line: '%c'"
+msgstr "неприпустимий початок рядка: \"%c\""
+
+#, c-format
+msgid "Hunk #%d succeeded at %d (offset %d line)."
+msgid_plural "Hunk #%d succeeded at %d (offset %d lines)."
+msgstr[0] "Шматок #%d успішно застосовано на позиції %d (зміщення %d рядок)."
+msgstr[1] "Шматок #%d успішно застосовано на позиції %d (зміщення %d рядки)."
+msgstr[2] "Шматок #%d успішно застосовано на позиції %d (зміщення %d рядків)."
+
+#, c-format
+msgid "Context reduced to (%ld/%ld) to apply fragment at %d"
+msgstr ""
+"Контекст скорочено до (%ld/%ld), щоб застосувати фрагмент на позиції %d"
+
+#, c-format
+msgid ""
+"while searching for:\n"
+"%.*s"
+msgstr ""
+"поки йде пошук:\n"
+"%.*s"
+
+#, c-format
+msgid "missing binary patch data for '%s'"
+msgstr "відсутні дані бінарної латки для \"%s\""
+
+#, c-format
+msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'"
+msgstr ""
+"неможливо виконати reverse-apply бінарної латки без зворотнього шматка до "
+"\"%s\""
+
+#, c-format
+msgid "cannot apply binary patch to '%s' without full index line"
+msgstr ""
+"неможливо застосувати бінарну латку до \"%s\" без повного індексного рядка"
+
+#, c-format
+msgid ""
+"the patch applies to '%s' (%s), which does not match the current contents."
+msgstr ""
+"латка застосовується до \"%s\" (%s), який не збігається з поточним вмістом."
+
+#, c-format
+msgid "the patch applies to an empty '%s' but it is not empty"
+msgstr "латка застосовується до порожнього \"%s\", який не є порожнім"
+
+#, c-format
+msgid "the necessary postimage %s for '%s' cannot be read"
+msgstr "неможливо прочитати необхідний postimage %s для \"%s\""
+
+#, c-format
+msgid "binary patch does not apply to '%s'"
+msgstr "бінарна латка не застосовується до \"%s\""
+
+#, c-format
+msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)"
+msgstr ""
+"бінарна латка для \"%s\" призводить до некоректного результату (очікувалося "
+"%s, отримано %s)"
+
+#, c-format
+msgid "patch failed: %s:%ld"
+msgstr "латання не вдалося: %s:%ld"
+
+#, c-format
+msgid "cannot checkout %s"
+msgstr "неможливо переключити стан %s"
+
+#, c-format
+msgid "failed to read %s"
+msgstr "не вдалося прочитати %s"
+
+#, c-format
+msgid "reading from '%s' beyond a symbolic link"
+msgstr "читання з \"%s\" за символьним посиланням"
+
+#, c-format
+msgid "path %s has been renamed/deleted"
+msgstr "шлях %s перейменовано/видалено"
+
+#, c-format
+msgid "%s: does not exist in index"
+msgstr "%s: не існує в індексі"
+
+#, c-format
+msgid "%s: does not match index"
+msgstr "%s: не співпадає з індексом"
+
+msgid "repository lacks the necessary blob to perform 3-way merge."
+msgstr ""
+"у сховищі відсутній необхідний blob для виконання тристороннього злиття."
+
+#, c-format
+msgid "Performing three-way merge...\n"
+msgstr "Виконання тристороннього злиття...\n"
+
+#, c-format
+msgid "cannot read the current contents of '%s'"
+msgstr "неможливо прочитати поточний вміст \"%s\""
+
+#, c-format
+msgid "Failed to perform three-way merge...\n"
+msgstr "Не вдалося виконати тристороннє злиття...\n"
+
+#, c-format
+msgid "Applied patch to '%s' with conflicts.\n"
+msgstr "Латка до \"%s\" застосована з конфліктами.\n"
+
+#, c-format
+msgid "Applied patch to '%s' cleanly.\n"
+msgstr "Латка до \"%s\" застосована чисто.\n"
+
+#, c-format
+msgid "Falling back to direct application...\n"
+msgstr "Повернення до прямого застосування...\n"
+
+msgid "removal patch leaves file contents"
+msgstr "латка видалення залишає вміст файлу"
+
+#, c-format
+msgid "%s: wrong type"
+msgstr "%s: невірний тип"
+
+#, c-format
+msgid "%s has type %o, expected %o"
+msgstr "%s має тип %o, очікувався %o"
+
+#, c-format
+msgid "invalid path '%s'"
+msgstr "неприпустимий шлях \"%s\""
+
+#, c-format
+msgid "%s: already exists in index"
+msgstr "%s: вже існує в індексі"
+
+#, c-format
+msgid "%s: already exists in working directory"
+msgstr "%s: вже існує в робочій директорії"
+
+#, c-format
+msgid "new mode (%o) of %s does not match old mode (%o)"
+msgstr "новий режим (%o) для %s не відповідає старому режиму (%o)"
+
+#, c-format
+msgid "new mode (%o) of %s does not match old mode (%o) of %s"
+msgstr "новий режим (%o) для %s не відповідає старому режиму (%o) для %s"
+
+#, c-format
+msgid "affected file '%s' is beyond a symbolic link"
+msgstr "уражений файл \"%s\" знаходиться за межами символічного посилання"
+
+#, c-format
+msgid "%s: patch does not apply"
+msgstr "%s: латка не може бути застосована"
+
+#, c-format
+msgid "Checking patch %s..."
+msgstr "Перевірка латки %s..."
+
+#, c-format
+msgid "sha1 information is lacking or useless for submodule %s"
+msgstr "sha1 інформація відсутня або марна для підмодуля %s"
+
+#, c-format
+msgid "mode change for %s, which is not in current HEAD"
+msgstr "зміна режиму для %s, якого немає в поточному HEAD"
+
+#, c-format
+msgid "sha1 information is lacking or useless (%s)."
+msgstr "sha1 інформація відсутня або марна (%s)."
+
+#, c-format
+msgid "could not add %s to temporary index"
+msgstr "не вдалося додати %s до тимчасового індексу"
+
+#, c-format
+msgid "could not write temporary index to %s"
+msgstr "не вдалося записати тимчасовий індекс у %s"
+
+#, c-format
+msgid "unable to remove %s from index"
+msgstr "не вдалося видалити %s з індексу"
+
+#, c-format
+msgid "corrupt patch for submodule %s"
+msgstr "пошкоджена латка для підмодуля %s"
+
+#, c-format
+msgid "unable to stat newly created file '%s'"
+msgstr "не вдалося отримати інформацію про щойно створений файл \"%s\""
+
+#, c-format
+msgid "unable to create backing store for newly created file %s"
+msgstr "не вдалося створити підтримуюче сховище для щойно створеного файлу %s"
+
+#, c-format
+msgid "unable to add cache entry for %s"
+msgstr "не вдалося додати запис кешу для %s"
+
+#, c-format
+msgid "failed to write to '%s'"
+msgstr "не вдалося записати в \"%s\""
+
+#, c-format
+msgid "closing file '%s'"
+msgstr "закриття файлу \"%s\""
+
+#, c-format
+msgid "unable to write file '%s' mode %o"
+msgstr "не вдалося записати файл \"%s\" в режимі %o"
+
+#, c-format
+msgid "Applied patch %s cleanly."
+msgstr "Латка %s застосована чисто."
+
+msgid "internal error"
+msgstr "внутрішня помилка"
+
+#, c-format
+msgid "Applying patch %%s with %d reject..."
+msgid_plural "Applying patch %%s with %d rejects..."
+msgstr[0] "Застосування латки %%s з %d відкиданням..."
+msgstr[1] "Застосування латки %%s з %d відкиданнями..."
+msgstr[2] "Застосування латки %%s з %d відкиданнями..."
+
+#, c-format
+msgid "truncating .rej filename to %.*s.rej"
+msgstr "скорочення назви файлу .rej до %.*s.rej"
+
+#, c-format
+msgid "cannot open %s"
+msgstr "неможливо відкрити %s"
+
+#, c-format
+msgid "cannot unlink '%s'"
+msgstr "неможливо відʼєднати \"%s\""
+
+#, c-format
+msgid "Hunk #%d applied cleanly."
+msgstr "Шматок #%d застосовано чисто."
+
+#, c-format
+msgid "Rejected hunk #%d."
+msgstr "Шматок #%d відкинуто."
+
+#, c-format
+msgid "Skipped patch '%s'."
+msgstr "Пропущена латка \"%s\"."
+
+msgid "No valid patches in input (allow with \"--allow-empty\")"
+msgstr "Немає коректних латок на вході (дозволити через \"--allow-empty\")"
+
+msgid "unable to read index file"
+msgstr "не вдалося прочитати індексний файл"
+
+#, c-format
+msgid "can't open patch '%s': %s"
+msgstr "неможливо відкрити латку \"%s\": %s"
+
+#, c-format
+msgid "squelched %d whitespace error"
+msgid_plural "squelched %d whitespace errors"
+msgstr[0] "ігнорована %d помилка пробільних символів"
+msgstr[1] "ігноровані %d помилки пробільних символів"
+msgstr[2] "ігноровані %d помилок пробільних символів"
+
+#, c-format
+msgid "%d line adds whitespace errors."
+msgid_plural "%d lines add whitespace errors."
+msgstr[0] "%d рядок додає помилки пробільних символів."
+msgstr[1] "%d рядки додають помилки пробільних символів."
+msgstr[2] "%d рядків додають помилки пробільних символів."
+
+#, c-format
+msgid "%d line applied after fixing whitespace errors."
+msgid_plural "%d lines applied after fixing whitespace errors."
+msgstr[0] "%d рядок застосовано після виправлення помилок пробільних символів."
+msgstr[1] "%d рядки застосовано після виправлення помилок пробільних символів."
+msgstr[2] ""
+"%d рядків застосовано після виправлення помилок пробільних символів."
+
+msgid "Unable to write new index file"
+msgstr "Не вдалося записати новий файл індексу"
+
+msgid "don't apply changes matching the given path"
+msgstr "не застосовувати зміни, що відповідають вказаному шляху"
+
+msgid "apply changes matching the given path"
+msgstr "застосувати зміни, що відповідають вказаному шляху"
+
+msgid "num"
+msgstr "число"
+
+msgid "remove <num> leading slashes from traditional diff paths"
+msgstr "видалити <num> перших слешів з традиційних diff-шляхів"
+
+msgid "ignore additions made by the patch"
+msgstr "ігнорувати доповнення, зроблені латкою"
+
+msgid "instead of applying the patch, output diffstat for the input"
+msgstr "замість застосування латки вивести diffstat для вхідних даних"
+
+msgid "show number of added and deleted lines in decimal notation"
+msgstr "показати кількість доданих і видалених рядків у десятковій нотації"
+
+msgid "instead of applying the patch, output a summary for the input"
+msgstr "замість застосування латки вивести підсумок для вхідних даних"
+
+msgid "instead of applying the patch, see if the patch is applicable"
+msgstr "замість застосування латки перевірити можливість її застосування"
+
+msgid "make sure the patch is applicable to the current index"
+msgstr "переконатися, що латка може бути застосовна до поточного індексу"
+
+msgid "mark new files with `git add --intent-to-add`"
+msgstr "позначити нові файли командою \"git add --intent-to-add\""
+
+msgid "apply a patch without touching the working tree"
+msgstr "застосувати латку, не торкаючись робочого дерева"
+
+msgid "accept a patch that touches outside the working area"
+msgstr "прийняти латку, яка виходить за межі робочого простору"
+
+msgid "also apply the patch (use with --stat/--summary/--check)"
+msgstr "також застосувати патч (використовуйте з --stat/--summary/--check)"
+
+msgid "attempt three-way merge, fall back on normal patch if that fails"
+msgstr ""
+"спробувати тристороннє злиття, повернутися до звичайного латання, якщо це не "
+"вдасться"
+
+msgid "build a temporary index based on embedded index information"
+msgstr "створити тимчасовий індекс на основі вбудованої індексної інформації"
+
+msgid "paths are separated with NUL character"
+msgstr "шляхи відокремлюються символом NUL"
+
+msgid "ensure at least <n> lines of context match"
+msgstr "забезпечити збіг принаймні <n> рядків контексту"
+
+msgid "action"
+msgstr "дія"
+
+msgid "detect new or modified lines that have whitespace errors"
+msgstr "виявляти нові або змінені рядки з помилками пробільних символів"
+
+msgid "ignore changes in whitespace when finding context"
+msgstr "ігнорувати зміни пробільних символів при пошуку контексту"
+
+msgid "apply the patch in reverse"
+msgstr "застосувати латку у зворотному порядку"
+
+msgid "don't expect at least one line of context"
+msgstr "не очікувати на хоча б один рядок контексту"
+
+msgid "leave the rejected hunks in corresponding *.rej files"
+msgstr "залишити відкинуті шматки у відповідних *.rej файлах"
+
+msgid "allow overlapping hunks"
+msgstr "дозволити перекриття шматків"
+
+msgid "tolerate incorrectly detected missing new-line at the end of file"
+msgstr "дозволяти некоректно виявлену відсутність нового рядка в кінці файлу"
+
+msgid "do not trust the line counts in the hunk headers"
+msgstr "не довіряти кількості рядків у заголовках шматків"
+
+msgid "root"
+msgstr "корінь"
+
+msgid "prepend <root> to all filenames"
+msgstr "додати <корінь> до всіх назв файлів"
+
+msgid "don't return error for empty patches"
+msgstr "не повертати помилку для порожніх латок"
+
+#, c-format
+msgid "cannot stream blob %s"
+msgstr "неможливо транслювати blob %s"
+
+#, c-format
+msgid "unsupported file mode: 0%o (SHA1: %s)"
+msgstr "непідтримуваний режим файлу: 0%o (SHA1: %s)"
+
+#, c-format
+msgid "deflate error (%d)"
+msgstr "помилка пакування (%d)"
+
+#, c-format
+msgid "unable to start '%s' filter"
+msgstr "не вдалося запустити \"%s\" фільтр"
+
+msgid "unable to redirect descriptor"
+msgstr "не вдалося перенаправити дескриптор"
+
+#, c-format
+msgid "'%s' filter reported error"
+msgstr "Фільтр \"%s\" повідомив про помилку"
+
+#, c-format
+msgid "path is not valid UTF-8: %s"
+msgstr "шлях не є припустимим UTF-8: %s"
+
+#, c-format
+msgid "path too long (%d chars, SHA1: %s): %s"
+msgstr "шлях занадто довгий (%d символів, SHA1: %s): %s"
+
+#, c-format
+msgid "timestamp too large for this system: %<PRIuMAX>"
+msgstr "позначка часу занадто велика для цієї системи: %<PRIuMAX>"
+
+msgid "git archive [<options>] <tree-ish> [<path>...]"
+msgstr "git archive [<опції>] <деревоподібне джерело> [<шлях>...]"
+
+msgid ""
+"git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"
+msgstr ""
+"git archive --remote <сховище> [--exec <команда>] [<опції>] <деревоподібне "
+"джерело> [<шлях>...]"
+
+msgid "git archive --remote <repo> [--exec <cmd>] --list"
+msgstr "git archive --remote <сховище> [--exec <команда>] --list"
+
+#, c-format
+msgid "cannot read '%s'"
+msgstr "неможливо прочитати \"%s\""
+
+#, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr ""
+
+#, c-format
+msgid "pathspec '%s' did not match any files"
+msgstr "визначник шляxу \"%s\" не відповідає жодному файлу"
+
+#, c-format
+msgid "no such ref: %.*s"
+msgstr "немає такого посилання: %.*s"
+
+#, c-format
+msgid "not a valid object name: %s"
+msgstr "невірне ім’я об’єкта: %s"
+
+#, c-format
+msgid "not a tree object: %s"
+msgstr "не є об’єктом дерева: %s"
+
+#, c-format
+msgid "File not found: %s"
+msgstr "Файл не знайдено: %s"
+
+#, c-format
+msgid "Not a regular file: %s"
+msgstr "Не звичайний файл: %s"
+
+#, c-format
+msgid "unclosed quote: '%s'"
+msgstr "незакриті лапки: \"%s\""
+
+#, c-format
+msgid "missing colon: '%s'"
+msgstr "відсутня двокрапка: \"%s\""
+
+#, c-format
+msgid "empty file name: '%s'"
+msgstr "порожня назва файлу: \"%s\""
+
+msgid "fmt"
+msgstr "fmt"
+
+msgid "archive format"
+msgstr "формат архіву"
+
+msgid "prefix"
+msgstr "префікс"
+
+msgid "prepend prefix to each pathname in the archive"
+msgstr "додати префікс до кожної назви шляху в архіві"
+
+msgid "file"
+msgstr "файл"
+
+msgid "add untracked file to archive"
+msgstr "додати невідстежуваний файл до архіву"
+
+msgid "path:content"
+msgstr "шлях:вміст"
+
+msgid "write the archive to this file"
+msgstr "записати архів до цього файлу"
+
+msgid "read .gitattributes in working directory"
+msgstr "прочитати .gitattributes робочої директорії"
+
+msgid "report archived files on stderr"
+msgstr "звітувати про заархівовані файли в stderr"
+
+msgid "time"
+msgstr "час"
+
+msgid "set modification time of archive entries"
+msgstr "встановити час модифікації архівних записів"
+
+msgid "set compression level"
+msgstr "встановити рівень компресії"
+
+msgid "list supported archive formats"
+msgstr "показати список підтримуваних форматів архівів"
+
+msgid "repo"
+msgstr "сховище"
+
+msgid "retrieve the archive from remote repository <repo>"
+msgstr "отримати архів з віддаленого <сховища>"
+
+msgid "command"
+msgstr "команда"
+
+msgid "path to the remote git-upload-archive command"
+msgstr "шлях до віддаленої команди git-upload-archive"
+
+msgid "Unexpected option --remote"
+msgstr "Неочікувана опція --remote"
+
+#, c-format
+msgid "the option '%s' requires '%s'"
+msgstr "опція \"%s\" вимагає \"%s\""
+
+msgid "Unexpected option --output"
+msgstr "Неочікувана опція --output"
+
+#, c-format
+msgid "Unknown archive format '%s'"
+msgstr "Невідомий формат архіву \"%s\""
+
+#, c-format
+msgid "Argument not supported for format '%s': -%d"
+msgstr "Аргумент не підтримується для формату \"%s\": -%d"
+
+#, c-format
+msgid "%.*s is not a valid attribute name"
+msgstr "%.*s не є припустимою назвою атрибута"
+
+msgid "unable to add additional attribute"
+msgstr "не вдалося додати додатковий атрибут"
+
+#, c-format
+msgid "ignoring overly long attributes line %d"
+msgstr "ігнорування надто довгого рядка атрибутів %d"
+
+#, c-format
+msgid "%s not allowed: %s:%d"
+msgstr "%s не дозволено: %s:%d"
+
+msgid ""
+"Negative patterns are ignored in git attributes\n"
+"Use '\\!' for literal leading exclamation."
+msgstr ""
+"Негативні шаблони ігноруються в git атрибутах\n"
+"Використовуйте \"\\!\" для додання знака оклику."
+
+#, c-format
+msgid "cannot fstat gitattributes file '%s'"
+msgstr "неможливо виконати fstat для файла git атрибутів \"%s\""
+
+#, c-format
+msgid "ignoring overly large gitattributes file '%s'"
+msgstr "ігнорування надто великого файлу gitattributes \"%s\""
+
+#, c-format
+msgid "ignoring overly large gitattributes blob '%s'"
+msgstr "ігнорування надто великих gitattributes blob \"%s\""
+
+#, c-format
+msgid "Badly quoted content in file '%s': %s"
+msgstr "Невірно процитований вміст у файлі \"%s\": %s"
+
+#, c-format
+msgid "We cannot bisect more!\n"
+msgstr "Неможливо бісектувати більше!\n"
+
+#, c-format
+msgid "Not a valid commit name %s"
+msgstr "Не є дійсною назвою коміта %s"
+
+#, c-format
+msgid ""
+"The merge base %s is bad.\n"
+"This means the bug has been fixed between %s and [%s].\n"
+msgstr ""
+"База злиття %s є невірною.\n"
+"Це означає, що помилку було виправлено між %s та [%s].\n"
+
+#, c-format
+msgid ""
+"The merge base %s is new.\n"
+"The property has changed between %s and [%s].\n"
+msgstr ""
+"База злиття %s є новою.\n"
+"Властивість змінилася між %s та [%s].\n"
+
+#, c-format
+msgid ""
+"The merge base %s is %s.\n"
+"This means the first '%s' commit is between %s and [%s].\n"
+msgstr ""
+"Базою злиття %s є %s.\n"
+"Це означає, що перший \"%s\" коміт знаходиться між %s і [%s].\n"
+
+#, c-format
+msgid ""
+"Some %s revs are not ancestors of the %s rev.\n"
+"git bisect cannot work properly in this case.\n"
+"Maybe you mistook %s and %s revs?\n"
+msgstr ""
+"Деякі %s revs не є предками %s rev.\n"
+"git bisect не може працювати належним чином в таких випадках.\n"
+"Можливо, ви переплутали %s і %s revs?\n"
+
+#, c-format
+msgid ""
+"the merge base between %s and [%s] must be skipped.\n"
+"So we cannot be sure the first %s commit is between %s and %s.\n"
+"We continue anyway."
+msgstr ""
+"базу злиття між %s і [%s] потрібно пропустити.\n"
+"Тому ми не можемо бути впевнені, що перший коміт %s знаходиться між %s і "
+"%s.\n"
+"Ми все одно продовжимо."
+
+#, c-format
+msgid "Bisecting: a merge base must be tested\n"
+msgstr "Бісекція: база злиття повинна бути протестована\n"
+
+#, c-format
+msgid "a %s revision is needed"
+msgstr "необхідна ревізія %s"
+
+#, c-format
+msgid "could not create file '%s'"
+msgstr "не вдалося створити файл \"%s\""
+
+#, c-format
+msgid "could not read file '%s'"
+msgstr "не вдалося прочитати файл \"%s\""
+
+msgid "reading bisect refs failed"
+msgstr "не вдалося прочитати бісекційні посилання"
+
+#, c-format
+msgid "%s was both %s and %s\n"
+msgstr "%s був одночасно і %s, і %s\n"
+
+#, c-format
+msgid ""
+"No testable commit found.\n"
+"Maybe you started with bad path arguments?\n"
+msgstr ""
+"Не знайдено коміт для тестування.\n"
+"Можливо, ви почали з неправильних аргументів шляху?\n"
+
+#, c-format
+msgid "(roughly %d step)"
+msgid_plural "(roughly %d steps)"
+msgstr[0] "(приблизно %d крок)"
+msgstr[1] "(приблизно %d кроки)"
+msgstr[2] "(приблизно %d кроків)"
+
+#. TRANSLATORS: the last %s will be replaced with "(roughly %d
+#. steps)" translation.
+#.
+
+#, c-format
+msgid "Bisecting: %d revision left to test after this %s\n"
+msgid_plural "Bisecting: %d revisions left to test after this %s\n"
+msgstr[0] "Бісекція: залишилося протестувати %d ревізію після цього %s\n"
+msgstr[1] "Бісекція: залишилося протестувати %d ревізії після цього %s\n"
+msgstr[2] "Бісекція: залишилося протестувати %d ревізій після цього %s\n"
+
+msgid "--contents and --reverse do not blend well."
+msgstr "--contents і --reverse поєднуються не дуже добре."
+
+msgid "--reverse and --first-parent together require specified latest commit"
+msgstr "--reverse і --first-parent разом вимагають вказівки останнього коміту"
+
+msgid "revision walk setup failed"
+msgstr "не вдалося налаштувати проходження по ревізіям"
+
+msgid ""
+"--reverse --first-parent together require range along first-parent chain"
+msgstr ""
+"--reverse --first-parent разом вимагають вказівки діапазона вздовж ланцюжка "
+"першого батька"
+
+#, c-format
+msgid "no such path %s in %s"
+msgstr "немає шляху %s в %s"
+
+#, c-format
+msgid "cannot read blob %s for path %s"
+msgstr "неможливо прочитати blob %s для шляху %s"
+
+msgid ""
+"cannot inherit upstream tracking configuration of multiple refs when "
+"rebasing is requested"
+msgstr ""
+"неможливо успадковувати першоджерельну конфігурацію відстежування декількох "
+"посилань при запиті перебазування"
+
+#, c-format
+msgid "not setting branch '%s' as its own upstream"
+msgstr "гілку \"%s\" не встановлено власним першоджерельним сховищем"
+
+#, c-format
+msgid "branch '%s' set up to track '%s' by rebasing."
+msgstr "гілку \"%s\" налаштовано на відстежування \"%s\" через перебазування."
+
+#, c-format
+msgid "branch '%s' set up to track '%s'."
+msgstr "гілку \"%s\" налаштовано на відстежуваня \"%s\"."
+
+#, c-format
+msgid "branch '%s' set up to track:"
+msgstr "гілку \"%s\" налаштовано на відстежування:"
+
+msgid "unable to write upstream branch configuration"
+msgstr "не вдалося записати конфігурацію гілки першоджерельного сховища"
+
+msgid ""
+"\n"
+"After fixing the error cause you may try to fix up\n"
+"the remote tracking information by invoking:"
+msgstr ""
+"\n"
+"Після усунення причини помилки ви можете спробувати виправити\n"
+"інформацію про віддалене відстежування здійснівши виклик:"
+
+#, c-format
+msgid "asked to inherit tracking from '%s', but no remote is set"
+msgstr ""
+"просили успадкувати відстежування з \"%s\", але віддалене призначення не "
+"встановлено"
+
+#, c-format
+msgid "asked to inherit tracking from '%s', but no merge configuration is set"
+msgstr ""
+"просили успадкувати відстежування з \"%s\", але конфігурацію злиття не задано"
+
+#, c-format
+msgid "not tracking: ambiguous information for ref '%s'"
+msgstr "не відстежується: неоднозначна інформація для посилання \"%s\""
+
+#. TRANSLATORS: This is a line listing a remote with duplicate
+#. refspecs in the advice message below. For RTL languages you'll
+#. probably want to swap the "%s" and leading "  " space around.
+#.
+#. TRANSLATORS: This is line item of ambiguous object output
+#. from describe_ambiguous_object() above. For RTL languages
+#. you'll probably want to swap the "%s" and leading " " space
+#. around.
+#.
+
+#, c-format
+msgid "  %s\n"
+msgstr "  %s\n"
+
+#. TRANSLATORS: The second argument is a \n-delimited list of
+#. duplicate refspecs, composed above.
+#.
+
+#, c-format
+msgid ""
+"There are multiple remotes whose fetch refspecs map to the remote\n"
+"tracking ref '%s':\n"
+"%s\n"
+"This is typically a configuration error.\n"
+"\n"
+"To support setting up tracking branches, ensure that\n"
+"different remotes' fetch refspecs map into different\n"
+"tracking namespaces."
+msgstr ""
+"Існує декілька віддалених призначень, визначники отримування посилань яких "
+"розвʼязуються у віддалено \n"
+"відстежуване посилання \"%s\":\n"
+"%s\n"
+"Зазвичай це помилка конфігурації.\n"
+"\n"
+"Щоб підтримувати налаштування гілок відстежування, переконайтеся, що\n"
+"визначники отримування посилань різних віддалених призначень розвʼязуються у "
+"різні\n"
+" простори імен відстежування."
+
+#, c-format
+msgid "'%s' is not a valid branch name"
+msgstr "\"%s\" не є допустимою назвою гілки"
+
+#, c-format
+msgid "a branch named '%s' already exists"
+msgstr "гілка з ім’ям \"%s\" вже існує"
+
+#, c-format
+msgid "cannot force update the branch '%s' checked out at '%s'"
+msgstr "неможливо примусово оновити гілку \"%s\", розташовану в \"%s\""
+
+#, c-format
+msgid "cannot set up tracking information; starting point '%s' is not a branch"
+msgstr ""
+"неможливо налаштувати інформацію про відстежування; початкова точка \"%s\" "
+"не є гілкою"
+
+#, c-format
+msgid "the requested upstream branch '%s' does not exist"
+msgstr "запитувана гілка \"%s\" не існує у першоджерельному сховищі"
+
+msgid ""
+"\n"
+"If you are planning on basing your work on an upstream\n"
+"branch that already exists at the remote, you may need to\n"
+"run \"git fetch\" to retrieve it.\n"
+"\n"
+"If you are planning to push out a new local branch that\n"
+"will track its remote counterpart, you may want to use\n"
+"\"git push -u\" to set the upstream config as you push."
+msgstr ""
+"\n"
+"Якщо ви плануєте базувати свою роботу на основі першоджерельної\n"
+"гілки, яка вже існує на віддаленому призначенні, вам може знадобитися\n"
+"запустити \"git fetch\", щоб отримати її.\n"
+"\n"
+"Якщо ви плануєте надіслати нову локальну гілку, яка\n"
+"буде відстежувати свою віддалену гілку, вам слід скористатися командою\n"
+"\"git push -u\", щоб встановити конфігурацію першоджерельного сховища під "
+"час надсилання."
+
+#, c-format
+msgid "not a valid object name: '%s'"
+msgstr "не є допустимим ім’ям об’єкта: \"%s\""
+
+#, c-format
+msgid "ambiguous object name: '%s'"
+msgstr "неоднозначне ім’я об’єкта: \"%s\""
+
+#, c-format
+msgid "not a valid branch point: '%s'"
+msgstr "не є допустимим ім’ям точки розгалуження: \"%s\""
+
+#, c-format
+msgid "submodule '%s': unable to find submodule"
+msgstr "підмодуль \"%s\": не вдалося знайти підмодуль"
+
+#, c-format
+msgid ""
+"You may try updating the submodules using 'git checkout --no-recurse-"
+"submodules %s && git submodule update --init'"
+msgstr ""
+"Ви можете спробувати оновити підмодулі за допомогою \"git checkout --no-"
+"recurse-submodules %s && git submodule update --init\"."
+
+#, c-format
+msgid "submodule '%s': cannot create branch '%s'"
+msgstr "підмодуль \"%s\": неможливо створити гілку \"%s\""
+
+#, c-format
+msgid "'%s' is already checked out at '%s'"
+msgstr "\"%s\" вже існує в \"%s\""
+
+msgid "git add [<options>] [--] <pathspec>..."
+msgstr "git add [<опції>] [--] <визначник шляху>..."
+
+#, c-format
+msgid "cannot chmod %cx '%s'"
+msgstr "неможливо виконати chmod %cx \"%s\""
+
+#, c-format
+msgid "unexpected diff status %c"
+msgstr "неочікуваний статус diff %c"
+
+msgid "updating files failed"
+msgstr "не вдалося оновити файли"
+
+#, c-format
+msgid "remove '%s'\n"
+msgstr "видалити \"%s\"\n"
+
+msgid "Unstaged changes after refreshing the index:"
+msgstr "Неіндексовані зміни після оновлення індексу:"
+
+msgid ""
+"the add.interactive.useBuiltin setting has been removed!\n"
+"See its entry in 'git help config' for details."
+msgstr ""
+"параметр add.interactive.useBuiltin було видалено!\n"
+"Дивіться запис у \"git help config\" для більш детальної інформації."
+
+msgid "Could not read the index"
+msgstr "Не вдалося прочитати індекс"
+
+msgid "Could not write patch"
+msgstr "Не вдалося записати латку"
+
+msgid "editing patch failed"
+msgstr "не вдалося відредагувати латку"
+
+#, c-format
+msgid "Could not stat '%s'"
+msgstr "Не вдалося виконати stat \"%s\""
+
+msgid "Empty patch. Aborted."
+msgstr "Порожня латка. Перервано."
+
+#, c-format
+msgid "Could not apply '%s'"
+msgstr "Не вдалося застосувати \"%s\""
+
+msgid "The following paths are ignored by one of your .gitignore files:\n"
+msgstr "Наступні шляхи ігноруються одним з ваших .gitignore файлів:\n"
+
+msgid "dry run"
+msgstr "пробний запуск"
+
+msgid "be verbose"
+msgstr "розгорнутий вивід"
+
+msgid "interactive picking"
+msgstr "інтерактивний вибір"
+
+msgid "select hunks interactively"
+msgstr "обирати шматки інтерактивно"
+
+msgid "edit current diff and apply"
+msgstr "відредагувати поточну різницю і застосувати"
+
+msgid "allow adding otherwise ignored files"
+msgstr "дозволити додавання ігнорованих файлів"
+
+msgid "update tracked files"
+msgstr "оновити відстежувані файли"
+
+msgid "renormalize EOL of tracked files (implies -u)"
+msgstr "перенормувати EOL відстежуваних файлів (мається на увазі -u)"
+
+msgid "record only the fact that the path will be added later"
+msgstr "записати лише той факт, що шлях будe додано пізніше"
+
+msgid "add changes from all tracked and untracked files"
+msgstr "додати зміни з усіх відстежуваних і невідстежуваних файлів"
+
+msgid "ignore paths removed in the working tree (same as --no-all)"
+msgstr "ігнорувати шляхи, видалені у робочому дереві (те саме, що й --no-all)"
+
+msgid "don't add, only refresh the index"
+msgstr "не додавати, лише оновити індекс"
+
+msgid "just skip files which cannot be added because of errors"
+msgstr "просто пропустити файли, які не можуть бути додані через помилки"
+
+msgid "check if - even missing - files are ignored in dry run"
+msgstr ""
+"перевірити, чи ігноруються файли, навіть якщо вони відсутні, під час "
+"пробного запуску"
+
+msgid "allow updating entries outside of the sparse-checkout cone"
+msgstr "дозволити оновлення записів за межами конуса часткового переходу"
+
+msgid "override the executable bit of the listed files"
+msgstr "перевизначити біт виконання для зазначених файлів"
+
+msgid "warn when adding an embedded repository"
+msgstr "попереджувати при додаванні вбудованого сховища"
+
+#, c-format
+msgid ""
+"You've added another git repository inside your current repository.\n"
+"Clones of the outer repository will not contain the contents of\n"
+"the embedded repository and will not know how to obtain it.\n"
+"If you meant to add a submodule, use:\n"
+"\n"
+"\tgit submodule add <url> %s\n"
+"\n"
+"If you added this path by mistake, you can remove it from the\n"
+"index with:\n"
+"\n"
+"\tgit rm --cached %s\n"
+"\n"
+"See \"git help submodule\" for more information."
+msgstr ""
+"Ви додали ще одне git сховище всередині вашого поточного сховища.\n"
+"Клони зовнішнього сховища не міститимуть вмісту\n"
+"вбудованого сховища і не знатимуть, як його отримати.\n"
+"Якщо ви хочете додати підмодуль, скористайтеся командою\n"
+"\n"
+"\tgit submodule add <url> %s\n"
+"\n"
+"Якщо ви додали цей шлях помилково, ви можете видалити його з\n"
+"індексу за допомогою:\n"
+"\n"
+"\tgit rm --cached %s\n"
+"\n"
+"Докладніше дивіться у \"git help submodule\"."
+
+#, c-format
+msgid "adding embedded git repository: %s"
+msgstr "додавання вбудованого git сховища: %s"
+
+msgid ""
+"Use -f if you really want to add them.\n"
+"Turn this message off by running\n"
+"\"git config advice.addIgnoredFile false\""
+msgstr ""
+"Використовуйте -f, якщо ви дійсно хочете їх додати.\n"
+"Щоб вимкнути це повідомлення, виконайте\n"
+"\"git config advice.addIgnoredFile false\""
+
+msgid "adding files failed"
+msgstr "додавання файлів завершилося невдало"
+
+#, c-format
+msgid "--chmod param '%s' must be either -x or +x"
+msgstr "--chmod параметр \"%s\" має бути -x або +x"
+
+#, c-format
+msgid "'%s' and pathspec arguments cannot be used together"
+msgstr "\"%s\" та аргументи визначника шляху не можна використовувати разом"
+
+#, c-format
+msgid "Nothing specified, nothing added.\n"
+msgstr "Нічого не зазначено, нічого не додано.\n"
+
+msgid ""
+"Maybe you wanted to say 'git add .'?\n"
+"Turn this message off by running\n"
+"\"git config advice.addEmptyPathspec false\""
+msgstr ""
+"Можливо, ви хотіли вказати \"git add .\"?\n"
+"Щоб вимкнути це повідомлення, виконайте\n"
+"\"git config advice.addEmptyPathspec false\""
+
+msgid "index file corrupt"
+msgstr "індексний файл пошкоджено"
+
+#, c-format
+msgid "bad action '%s' for '%s'"
+msgstr "невірна дія \"%s\" для \"%s\""
+
+#, c-format
+msgid "invalid value for '%s': '%s'"
+msgstr "неприпустиме значення для \"%s\": \"%s\""
+
+#, c-format
+msgid "could not read '%s'"
+msgstr "не вдалося прочитати \"%s\""
+
+msgid "could not parse author script"
+msgstr "не вдалося розібрати author script"
+
+#, c-format
+msgid "could not parse %s"
+msgstr "не вдалося розібрати %s"
+
+#, c-format
+msgid "'%s' was deleted by the applypatch-msg hook"
+msgstr "\"%s\" було видалено applypatch-msg гачком"
+
+#, c-format
+msgid "Malformed input line: '%s'."
+msgstr "Невірно сформований рядок вводу: \"%s\"."
+
+#, c-format
+msgid "Failed to copy notes from '%s' to '%s'"
+msgstr "Не вдалося скопіювати нотатки з \"%s\" в \"%s\""
+
+msgid "fseek failed"
+msgstr "fseek завершився невдало"
+
+#, c-format
+msgid "could not open '%s' for reading"
+msgstr "не вдалося відкрити \"%s\" для читання"
+
+#, c-format
+msgid "could not open '%s' for writing"
+msgstr "не вдалося відкрити \"%s\" для запису"
+
+#, c-format
+msgid "could not parse patch '%s'"
+msgstr "не вдалося розібрати латку \"%s\""
+
+msgid "Only one StGIT patch series can be applied at once"
+msgstr "Можна застосовувати лише одну серію StGIT латок одразу"
+
+msgid "invalid timestamp"
+msgstr "неприпустима позначка часу"
+
+msgid "invalid Date line"
+msgstr "неприпустимий рядок дати"
+
+msgid "invalid timezone offset"
+msgstr "неприпустиме зміщення часового поясу"
+
+msgid "Patch format detection failed."
+msgstr "Не вдалося визначити формат латки."
+
+#, c-format
+msgid "failed to create directory '%s'"
+msgstr "не вдалося створити директорію \"%s\""
+
+msgid "Failed to split patches."
+msgstr "Не вдалося розділити латки."
+
+#, c-format
+msgid "When you have resolved this problem, run \"%s --continue\"."
+msgstr "Коли ви вирішите цю проблему, виконайте \"%s --continue\"."
+
+#, c-format
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
+msgstr ""
+"Якщо ви бажаєте пропустити цю латку, виконайте \"%s --skip\" замість цього."
+
+#, c-format
+msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
+msgstr ""
+"Щоб записати порожню латку як порожній коміт, виконайте \"%s --allow-empty\"."
+
+#, c-format
+msgid "To restore the original branch and stop patching, run \"%s --abort\"."
+msgstr ""
+"Щоб повернути гілку до початкового стану і зупинити латання, виконайте \"%s "
+"--abort\"."
+
+msgid "Patch sent with format=flowed; space at the end of lines might be lost."
+msgstr ""
+"Латку надіслано з параметром format=flowed; пробіли в кінці рядків можуть "
+"бути втрачені."
+
+#, c-format
+msgid "missing author line in commit %s"
+msgstr "відсутній рядок автора в коміті %s"
+
+#, c-format
+msgid "invalid ident line: %.*s"
+msgstr "неприпустимий ідентифікаційний рядок: %.*s"
+
+#, c-format
+msgid "unable to parse commit %s"
+msgstr "не вдалося розібрати коміт %s"
+
+msgid "Repository lacks necessary blobs to fall back on 3-way merge."
+msgstr ""
+"У сховищі не вистачає необхідних blob-обʼєктів, щоб повернутися до "
+"тристороннього злиття."
+
+msgid "Using index info to reconstruct a base tree..."
+msgstr ""
+"Використання індексної інформації для реконстрування базового дерева..."
+
+msgid ""
+"Did you hand edit your patch?\n"
+"It does not apply to blobs recorded in its index."
+msgstr ""
+"Ви відредагували свою латку вручну?\n"
+"Це не стосується blob-обʼєктів, записаних у його індексі."
+
+msgid "Falling back to patching base and 3-way merge..."
+msgstr "Повернення до бази латки та тристороннього злиття..."
+
+msgid "Failed to merge in the changes."
+msgstr "Не вдалося злити зміни."
+
+msgid "git write-tree failed to write a tree"
+msgstr "git write-tree не вдалося записати дерево"
+
+msgid "applying to an empty history"
+msgstr "застосування до порожньої історії"
+
+msgid "failed to write commit object"
+msgstr "не вдалося записати об’єкт коміту"
+
+#, c-format
+msgid "cannot resume: %s does not exist."
+msgstr "неможливо продовжити: %s не існує."
+
+msgid "Commit Body is:"
+msgstr "Тіло коміту:"
+
+#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
+#. in your translation. The program will only accept English
+#. input at this point.
+#.
+
+#, c-format
+msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "
+msgstr ""
+"Застосувати? [y]-так / [n]-ні / [e]-редагувати / [v]-переглянути латку / [a]-"
+"застосувати все: "
+
+msgid "unable to write index file"
+msgstr "не вдалося записати індексний файл"
+
+#, c-format
+msgid "Dirty index: cannot apply patches (dirty: %s)"
+msgstr "Індекс забруднено: неможливо застосувати латки (забруднено: %s)"
+
+#, c-format
+msgid "Skipping: %.*s"
+msgstr "Пропуск: %.*s"
+
+#, c-format
+msgid "Creating an empty commit: %.*s"
+msgstr "Створення порожнього коміту: %.*s"
+
+msgid "Patch is empty."
+msgstr "Латка порожня."
+
+#, c-format
+msgid "Applying: %.*s"
+msgstr "Застосування: %.*s"
+
+msgid "No changes -- Patch already applied."
+msgstr "Без змін - латку вже застосовано."
+
+#, c-format
+msgid "Patch failed at %s %.*s"
+msgstr "Латання не вдалося на %s %.*s"
+
+msgid "Use 'git am --show-current-patch=diff' to see the failed patch"
+msgstr ""
+"Використовуйте \"git am --show-current-patch=diff\", щоб побачити невдалу "
+"латку"
+
+msgid "No changes - recorded it as an empty commit."
+msgstr "Без змін - записаний як порожній коміт."
+
+msgid ""
+"No changes - did you forget to use 'git add'?\n"
+"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 ""
+"Без змін - ви забули використати \"git add\"?\n"
+"Якщо нічого індексувати, є ймовірність того, що хтось інший\n"
+"вже вніс ті самі зміни; можливо, ви захочете пропустити цю латку."
+
+msgid ""
+"You still have unmerged paths in your index.\n"
+"You should 'git add' each file with resolved conflicts to mark them as "
+"such.\n"
+"You might run `git rm` on a file to accept \"deleted by them\" for it."
+msgstr ""
+"У вашому індексі все ще залишаються не злиті шляхи.\n"
+"Вам слід виконати \"git add\" для кожного файлу з розвʼязаними конфліктами, "
+"щоб позначити їх як такі.\n"
+"Ви можете виконати \"git rm\" для файлу, щоб прийняти \"видалено ними\"."
+
+msgid "unable to write new index file"
+msgstr "не вдалося записати новий файл індексу"
+
+#, c-format
+msgid "Could not parse object '%s'."
+msgstr "Не вдалося розібрати об'єкт '%s'."
+
+msgid "failed to clean index"
+msgstr "не вдалося очистити індекс"
+
+msgid ""
+"You seem to have moved HEAD since the last 'am' failure.\n"
+"Not rewinding to ORIG_HEAD"
+msgstr ""
+"Здається, ви пересунули HEAD після останньої невдачі з \"am\".\n"
+"Не відбувається перемотування до ORIG_HEAD"
+
+#, c-format
+msgid "failed to read '%s'"
+msgstr "не вдалося прочитати \"%s\""
+
+#, c-format
+msgid "options '%s=%s' and '%s=%s' cannot be used together"
+msgstr "опції \"%s=%s\" and \"%s=%s\" не можна використовувати разом"
+
+msgid "git am [<options>] [(<mbox> | <Maildir>)...]"
+msgstr "git am [<опції>] [(<скринька> [<поштова директорія>)...]"
+
+msgid "git am [<options>] (--continue | --skip | --abort)"
+msgstr "git am [<опції>] (--continue | --skip | --abort)"
+
+msgid "run interactively"
+msgstr "запустити інтерактивно"
+
+msgid "bypass pre-applypatch and applypatch-msg hooks"
+msgstr "обійти pre-applypatch та applypatch-msg гачки"
+
+msgid "historical option -- no-op"
+msgstr "стара опція -- не працює"
+
+msgid "allow fall back on 3way merging if needed"
+msgstr "дозволити повернутися до тристороннього злиття у разі потреби"
+
+msgid "be quiet"
+msgstr "працювати тихесенько"
+
+msgid "add a Signed-off-by trailer to the commit message"
+msgstr "додати Signed-off-by причеп у допис до коміту"
+
+msgid "recode into utf8 (default)"
+msgstr "перекодувати в utf8 (за замовчуванням)"
+
+msgid "pass -k flag to git-mailinfo"
+msgstr "передати -k прапорець до git-mailinfo"
+
+msgid "pass -b flag to git-mailinfo"
+msgstr "передати -b прапорець до git-mailinfo"
+
+msgid "pass -m flag to git-mailinfo"
+msgstr "передати -m прапорець до git-mailinfo"
+
+msgid "pass --keep-cr flag to git-mailsplit for mbox format"
+msgstr "передати --keep-cr прапорець до git-mailsplit для формату mbox"
+
+msgid "do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"
+msgstr ""
+"не передавати --keep-cr прапорець до git-mailsplit незалежно від am.keepcr"
+
+msgid "strip everything before a scissors line"
+msgstr "прибрати все раніше відрізної лінії"
+
+msgid "pass it through git-mailinfo"
+msgstr "передати через git-mailinfo"
+
+msgid "pass it through git-apply"
+msgstr "передати через git-apply"
+
+msgid "n"
+msgstr "n"
+
+msgid "format"
+msgstr "формат"
+
+msgid "format the patch(es) are in"
+msgstr "формат латки(-ок)"
+
+msgid "override error message when patch failure occurs"
+msgstr "перевизначити повідомлення про помилку при збої латання"
+
+msgid "continue applying patches after resolving a conflict"
+msgstr "продовжити застосування латки після розвʼязання конфлікту"
+
+msgid "synonyms for --continue"
+msgstr "те ж саме, що й --continue"
+
+msgid "skip the current patch"
+msgstr "пропустити поточну латку"
+
+msgid "restore the original branch and abort the patching operation"
+msgstr "відновити початкову гілку і перервати операцію латання"
+
+msgid "abort the patching operation but keep HEAD where it is"
+msgstr "перервати латання, але залишити HEAD на тому місці, де він знаходиться"
+
+msgid "show the patch being applied"
+msgstr "показати латку, що застосовується"
+
+msgid "record the empty patch as an empty commit"
+msgstr "записати порожню латку як порожній коміт"
+
+msgid "lie about committer date"
+msgstr "брехати про дату комітера"
+
+msgid "use current timestamp for author date"
+msgstr "використовувати поточну мітку часу для дати автора"
+
+msgid "key-id"
+msgstr "key-id"
+
+msgid "GPG-sign commits"
+msgstr "підписати коміти GPG-підписом"
+
+msgid "how to handle empty patches"
+msgstr "як обробляти порожні латки"
+
+msgid "(internal use for git-rebase)"
+msgstr "(внутрішнє використання для git-rebase)"
+
+msgid ""
+"The -b/--binary option has been a no-op for long time, and\n"
+"it will be removed. Please do not use it anymore."
+msgstr ""
+"Опція -b/--binary вже давно не працює і\n"
+"буде видалена. Будь ласка, не використовуйте її більше."
+
+msgid "failed to read the index"
+msgstr "не вдалося прочитати індекс"
+
+#, c-format
+msgid "previous rebase directory %s still exists but mbox given."
+msgstr ""
+"попередня директорія перебазування %s все ще існує, але було надано mbox."
+
+#, c-format
+msgid ""
+"Stray %s directory found.\n"
+"Use \"git am --abort\" to remove it."
+msgstr ""
+"Знайдено блукаючу директорію %s.\n"
+"Скористайтеся командою \"git am --abort\", щоб вилучити її."
+
+msgid "Resolve operation not in progress, we are not resuming."
+msgstr "Наразі не виконується операція розвʼязання, ми не продовжуємо."
+
+msgid "interactive mode requires patches on the command line"
+msgstr "інтерактивний режим вимагає латки у командному рядку"
+
+msgid "git apply [<options>] [<patch>...]"
+msgstr "git apply [<опції>] [<латка>...]"
+
+msgid "could not redirect output"
+msgstr "неможливо перенаправити вивід"
+
+msgid "git archive: Remote with no URL"
+msgstr "git archive: віддалене призначення без URL"
+
+msgid "git archive: expected ACK/NAK, got a flush packet"
+msgstr "git archive: очікувалося ACK/NAK, отримано flush-пакет"
+
+#, c-format
+msgid "git archive: NACK %s"
+msgstr "git archive: NACK %s"
+
+msgid "git archive: protocol error"
+msgstr "git archive: помилка протоколу"
+
+msgid "git archive: expected a flush"
+msgstr "git archive: очікувався flush"
+
+msgid ""
+"git bisect start [--term-{new,bad}=<term> --term-{old,good}=<term>]    [--no-"
+"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+msgstr ""
+"git bisect start [--term-{new,bad}=<термін> --term-{old,good}=<термін>]    "
+"[--no-checkout] [--first-parent] [<поганий> [<добрий>...]] [--]    "
+"[<визначник шляху>...]"
+
+msgid "git bisect (good|bad) [<rev>...]"
+msgstr "git bisect (добрий|поганий) [<ревізія>...]"
+
+msgid "git bisect skip [(<rev>|<range>)...]"
+msgstr "git bisect skip [(<ревізія>|<діапазон>)...]"
+
+msgid "git bisect reset [<commit>]"
+msgstr "git bisect reset [<коміт>]"
+
+msgid "git bisect replay <logfile>"
+msgstr "git bisect replay <лог файл>"
+
+msgid "git bisect run <cmd>..."
+msgstr "git bisect run <команда>..."
+
+#, c-format
+msgid "cannot open file '%s' in mode '%s'"
+msgstr "неможливо відкрити файл \"%s\" у режимі \"%s\""
+
+#, c-format
+msgid "could not write to file '%s'"
+msgstr "не вдалося записати в файл \"%s\""
+
+#, c-format
+msgid "cannot open file '%s' for reading"
+msgstr "неможливо відкрити файл \"%s\" для читання"
+
+#, c-format
+msgid "'%s' is not a valid term"
+msgstr "\"%s\" не є допустимим терміном"
+
+#, c-format
+msgid "can't use the builtin command '%s' as a term"
+msgstr "неможливо використати вбудовану команду \"%s\" як термін"
+
+#, c-format
+msgid "can't change the meaning of the term '%s'"
+msgstr "неможливо змінити значення терміну \"%s\""
+
+msgid "please use two different terms"
+msgstr "будь ласка, використовуйте два різних терміна"
+
+#, c-format
+msgid "We are not bisecting.\n"
+msgstr "Ми не робимо бісекцію.\n"
+
+#, c-format
+msgid "'%s' is not a valid commit"
+msgstr "\"%s\" не є дійсним комітом"
+
+#, c-format
+msgid ""
+"could not check out original HEAD '%s'. Try 'git bisect reset <commit>'."
+msgstr ""
+"не вдалося переключитися на початковий HEAD \"%s\". Спробуйте \"git bisect "
+"reset <коміт>\"."
+
+#, c-format
+msgid "Bad bisect_write argument: %s"
+msgstr "Невірний bisect_write аргумент: %s"
+
+#, c-format
+msgid "couldn't get the oid of the rev '%s'"
+msgstr "не вдалося отримати oid для rev \"%s\""
+
+#, c-format
+msgid "couldn't open the file '%s'"
+msgstr "не вдалося відкрити файл \"%s\""
+
+#, c-format
+msgid "Invalid command: you're currently in a %s/%s bisect"
+msgstr "Неприпустима команда: наразі ви в процесі %s/%s бісекції"
+
+#, c-format
+msgid ""
+"You 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 ""
+"Ви маєте надати принаймні одну %s та %s ревізію.\n"
+"Для цього ви можете скористатися командами \"git bisect %s\" і \"git bisect "
+"%s\"."
+
+#, c-format
+msgid ""
+"You need to start by \"git bisect start\".\n"
+"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 ""
+"Вам потрібно почати з \"git bisect start\".\n"
+"Потім вам потрібно надати принаймні одну %s і %s ревізію.\n"
+"Для цього ви можете скористатися командами \"git bisect %s\" і \"git bisect "
+"%s\"."
+
+#, c-format
+msgid "bisecting only with a %s commit"
+msgstr "бісекція лише з %s комітом"
+
+#. TRANSLATORS: Make sure to include [Y] and [n] in your
+#. translation. The program will only accept English input
+#. at this point.
+#.
+
+msgid "Are you sure [Y/n]? "
+msgstr "Ви впевнені [Y/n]? "
+
+msgid "status: waiting for both good and bad commits\n"
+msgstr "статус: чекаємо на добрий і поганий коміти\n"
+
+#, c-format
+msgid "status: waiting for bad commit, %d good commit known\n"
+msgid_plural "status: waiting for bad commit, %d good commits known\n"
+msgstr[0] "статус: чекаємо на поганий коміт, відомий %d добрий коміт\n"
+msgstr[1] "статус: чекаємо на поганий коміт, відомі %d добрих коміти\n"
+msgstr[2] "статус: чекаємо на поганий коміт, відомі %d добрих комітів\n"
+
+msgid "status: waiting for good commit(s), bad commit known\n"
+msgstr "статус: чекаємо на добрий коміт(и), поганий коміт відомий\n"
+
+msgid "no terms defined"
+msgstr "терміни не визначені"
+
+#, c-format
+msgid ""
+"Your current terms are %s for the old state\n"
+"and %s for the new state.\n"
+msgstr ""
+"Ваші поточні терміни: %s для старого стану\n"
+"і %s для нового стану.\n"
+
+#, c-format
+msgid ""
+"invalid argument %s for 'git bisect terms'.\n"
+"Supported options are: --term-good|--term-old and --term-bad|--term-new."
+msgstr ""
+"неприпустимий аргумент %s для \"git bisect terms\".\n"
+"Підтримувані опції: --term-good|--term-old і --term-bad|--term-new."
+
+msgid "revision walk setup failed\n"
+msgstr "не вдалося налаштувати проходження по ревізіям\n"
+
+#, c-format
+msgid "could not open '%s' for appending"
+msgstr "не вдалося відкрити \"%s\" для додавання"
+
+msgid "'' is not a valid term"
+msgstr "\"\" не є допустимим терміном"
+
+#, c-format
+msgid "unrecognized option: '%s'"
+msgstr "нерозпізнана опція: \"%s\""
+
+#, c-format
+msgid "'%s' does not appear to be a valid revision"
+msgstr "\"%s\" не є дійсною ревізією"
+
+msgid "bad HEAD - I need a HEAD"
+msgstr "невірний HEAD - потрібен HEAD"
+
+#, c-format
+msgid "checking out '%s' failed. Try 'git bisect start <valid-branch>'."
+msgstr ""
+"переключення на \"%s\" завершилося невдало. Спробуйте \"git bisect start "
+"<дійсна-гілка>\"."
+
+msgid "bad HEAD - strange symbolic ref"
+msgstr "невірний HEAD - дивне символьне посилання"
+
+#, c-format
+msgid "invalid ref: '%s'"
+msgstr "неприпустиме посилання: \"%s\""
+
+msgid "You need to start by \"git bisect start\"\n"
+msgstr "Вам потрібно почати з \"git bisect start\"\n"
+
+#. TRANSLATORS: Make sure to include [Y] and [n] in your
+#. translation. The program will only accept English input
+#. at this point.
+#.
+
+msgid "Do you want me to do it for you [Y/n]? "
+msgstr "Ви хочете, щоб я зробив це для вас [Y/n]? "
+
+msgid "Please call `--bisect-state` with at least one argument"
+msgstr ""
+"Будь ласка, використовуйте \"--bisect-state\" з принаймні одним аргументом"
+
+#, c-format
+msgid "'git bisect %s' can take only one argument."
+msgstr "\"git bisect %s\" приймає лише один аргумент."
+
+#, c-format
+msgid "Bad rev input: %s"
+msgstr "Невірне значення ревізії: %s"
+
+#, c-format
+msgid "Bad rev input (not a commit): %s"
+msgstr "Невірне значення ревізії (не є комітом): %s"
+
+msgid "We are not bisecting."
+msgstr "Наразі ви не робите бісекцію."
+
+#, c-format
+msgid "'%s'?? what are you talking about?"
+msgstr "\"%s\"? Що ви маєте на увазі?"
+
+#, c-format
+msgid "cannot read file '%s' for replaying"
+msgstr "не вдалося прочитати файл \"%s\" для відтворення"
+
+#, c-format
+msgid "running %s\n"
+msgstr "виконання %s\n"
+
+msgid "bisect run failed: no command provided."
+msgstr "бісекція завершилася невдало: не надано команду."
+
+#, c-format
+msgid "unable to verify %s on good revision"
+msgstr "не вдалося розпізнати %s як припустиму ревізію"
+
+#, c-format
+msgid "bogus exit code %d for good revision"
+msgstr "хибний код виходу %d для доброї ревізії"
+
+#, c-format
+msgid "bisect run failed: exit code %d from %s is < 0 or >= 128"
+msgstr "бісекція завершилася невдало: код виходу %d з %s є < 0 або >= 128"
+
+#, c-format
+msgid "cannot open file '%s' for writing"
+msgstr "не вдалося відкрити файл \"%s\" для запису"
+
+msgid "bisect run cannot continue any more"
+msgstr "неможливо продовжити бісекцію"
+
+msgid "bisect run success"
+msgstr "бісекцію завершено успішно"
+
+msgid "bisect found first bad commit"
+msgstr "бісекція знайшла перший поганий коміт"
+
+#, c-format
+msgid "bisect run failed: 'git bisect %s' exited with error code %d"
+msgstr ""
+"бісекція завершилася невдало: \"git bisect %s\" завершено з кодом помилки %d"
+
+#, c-format
+msgid "'%s' requires either no argument or a commit"
+msgstr "\"%s\" вимагає або відсутності аргументу, або коміт"
+
+#, c-format
+msgid "'%s' requires 0 or 1 argument"
+msgstr "\"%s\" вимагає 0 або 1 аргумент"
+
+#, c-format
+msgid "'%s' requires 0 arguments"
+msgstr "\"%s\" вимагає 0 аргументів"
+
+msgid "no logfile given"
+msgstr "не надано лог-файл"
+
+#, c-format
+msgid "'%s' failed: no command provided."
+msgstr "\"%s\" завершено невдало: не надано команду."
+
+msgid "need a command"
+msgstr "потрібна команда"
+
+#, c-format
+msgid "unknown command: '%s'"
+msgstr "невідома команда: \"%s\""
+
+msgid "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"
+msgstr "git blame [<опції>] [<rev-опції>] [<ревізія>] [--] <файл>"
+
+msgid "git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>"
+msgstr "git annotate [<опції>] [<rev-опції>] [<ревізія>] [--] <файл>"
+
+msgid "<rev-opts> are documented in git-rev-list(1)"
+msgstr "<rev-опції> задокументовані у git-rev-list(1)"
+
+#, c-format
+msgid "expecting a color: %s"
+msgstr "очікування кольору: %s"
+
+msgid "must end with a color"
+msgstr "повинно закінчуватися кольором"
+
+#, c-format
+msgid "cannot find revision %s to ignore"
+msgstr "неможливо знайти ревізію %s для ігнорування"
+
+msgid "show blame entries as we find them, incrementally"
+msgstr "показувати blame записи по мірі того, як ми їх знаходимо, поступово"
+
+msgid "do not show object names of boundary commits (Default: off)"
+msgstr "не показувати назви об’єктів межевих комітів (за замовчуванням: off)"
+
+msgid "do not treat root commits as boundaries (Default: off)"
+msgstr "не розглядати кореневі коміти як межі (за замовчуванням: off)"
+
+msgid "show work cost statistics"
+msgstr "показати статистику вартості робіт"
+
+msgid "force progress reporting"
+msgstr "примусово звітувати прогрес"
+
+msgid "show output score for blame entries"
+msgstr "показати вихідний показник для blame записів"
+
+msgid "show original filename (Default: auto)"
+msgstr "показати оригінальне ім’я файлу (за замовчуванням: auto)"
+
+msgid "show original linenumber (Default: off)"
+msgstr "показати початковий номер рядка (за замовчуванням: off)"
+
+msgid "show in a format designed for machine consumption"
+msgstr ""
+
+msgid "show porcelain format with per-line commit information"
+msgstr ""
+
+msgid "use the same output mode as git-annotate (Default: off)"
+msgstr ""
+
+msgid "show raw timestamp (Default: off)"
+msgstr ""
+
+msgid "show long commit SHA1 (Default: off)"
+msgstr ""
+
+msgid "suppress author name and timestamp (Default: off)"
+msgstr ""
+
+msgid "show author email instead of name (Default: off)"
+msgstr ""
+
+msgid "ignore whitespace differences"
+msgstr ""
+
+msgid "rev"
+msgstr ""
+
+msgid "ignore <rev> when blaming"
+msgstr ""
+
+msgid "ignore revisions from <file>"
+msgstr ""
+
+msgid "color redundant metadata from previous line differently"
+msgstr ""
+
+msgid "color lines by age"
+msgstr ""
+
+msgid "spend extra cycles to find better match"
+msgstr ""
+
+msgid "use revisions from <file> instead of calling git-rev-list"
+msgstr ""
+
+msgid "use <file>'s contents as the final image"
+msgstr ""
+
+msgid "score"
+msgstr ""
+
+msgid "find line copies within and across files"
+msgstr ""
+
+msgid "find line movements within and across files"
+msgstr ""
+
+msgid "range"
+msgstr ""
+
+msgid "process only line range <start>,<end> or function :<funcname>"
+msgstr ""
+
+msgid "--progress can't be used with --incremental or porcelain formats"
+msgstr ""
+"--progress не можна використовувати з форматами --incremental або porcelain"
+
+#. TRANSLATORS: This string is used to tell us the
+#. maximum display width for a relative timestamp in
+#. "git blame" output.  For C locale, "4 years, 11
+#. months ago", which takes 22 places, is the longest
+#. among various forms of relative timestamps, but
+#. your language may need more or fewer display
+#. columns.
+#.
+
+msgid "4 years, 11 months ago"
+msgstr ""
+
+#, c-format
+msgid "file %s has only %lu line"
+msgid_plural "file %s has only %lu lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Blaming lines"
+msgstr ""
+
+msgid "git branch [<options>] [-r | -a] [--merged] [--no-merged]"
+msgstr ""
+
+msgid ""
+"git branch [<options>] [-f] [--recurse-submodules] <branch-name> [<start-"
+"point>]"
+msgstr ""
+
+msgid "git branch [<options>] [-l] [<pattern>...]"
+msgstr "git branch [<опції>] [-l] [<шаблон>...]"
+
+msgid "git branch [<options>] [-r] (-d | -D) <branch-name>..."
+msgstr "git branch [<опції>] [-r] (-d | -D) <имʼя-гілки>..."
+
+msgid "git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"
+msgstr "git branch [<опції>] (-m | -M) [<стара-гілка>] <нова-гілка>"
+
+msgid "git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"
+msgstr "git branch [<опції>] (-c | -C) [<стара-гілка>] <нова-гілка>"
+
+msgid "git branch [<options>] [-r | -a] [--points-at]"
+msgstr "git branch [<опції>] [-r | -a] [--points-at]"
+
+msgid "git branch [<options>] [-r | -a] [--format]"
+msgstr "git branch [<опції>] [-r | -a] [--format]"
+
+#, c-format
+msgid ""
+"deleting branch '%s' that has been merged to\n"
+"         '%s', but not yet merged to HEAD."
+msgstr ""
+
+#, c-format
+msgid ""
+"not deleting branch '%s' that is not yet merged to\n"
+"         '%s', even though it is merged to HEAD."
+msgstr ""
+
+#, c-format
+msgid "Couldn't look up commit object for '%s'"
+msgstr "Не вдалося знайти об’єкт коміту для \"%s\""
+
+#, c-format
+msgid ""
+"The branch '%s' is not fully merged.\n"
+"If you are sure you want to delete it, run 'git branch -D %s'."
+msgstr ""
+
+msgid "Update of config-file failed"
+msgstr ""
+
+msgid "cannot use -a with -d"
+msgstr "не можна використовувати -a з -d"
+
+#, c-format
+msgid "Cannot delete branch '%s' checked out at '%s'"
+msgstr "Неможливо видалити гілку \"%s\" за адресою \"%s\""
+
+#, c-format
+msgid "remote-tracking branch '%s' not found."
+msgstr "віддалено відстежувана гілка \"%s\" не знайдена."
+
+#, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"гілка \"%s\" не знайдена.\n"
+"Ви забули --remote?"
+
+#, c-format
+msgid "branch '%s' not found."
+msgstr "гілка \"%s\" не знайдена."
+
+#, c-format
+msgid "Deleted remote-tracking branch %s (was %s).\n"
+msgstr ""
+
+#, c-format
+msgid "Deleted branch %s (was %s).\n"
+msgstr "Видалено гілку %s (була %s).\n"
+
+msgid "unable to parse format string"
+msgstr "не вдалося розібрати рядок форматування"
+
+msgid "could not resolve HEAD"
+msgstr "не вдалося розвʼязати HEAD"
+
+#, c-format
+msgid "HEAD (%s) points outside of refs/heads/"
+msgstr "HEAD (%s) пунктів за межами refs/heads/"
+
+#, c-format
+msgid "Branch %s is being rebased at %s"
+msgstr ""
+
+#, c-format
+msgid "Branch %s is being bisected at %s"
+msgstr "Гілка %s бісектується в точці %s"
+
+#, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "HEAD робочого дерева %s не оновлено"
+
+#, c-format
+msgid "Invalid branch name: '%s'"
+msgstr "Неприпустима назва гілки: \"%s\""
+
+#, c-format
+msgid "No commit on branch '%s' yet."
+msgstr "Поки що немає комітів в гілці \"%s\"."
+
+#, c-format
+msgid "No branch named '%s'."
+msgstr "Немає гілки з ім’ям \"%s\"."
+
+msgid "Branch rename failed"
+msgstr ""
+
+msgid "Branch copy failed"
+msgstr ""
+
+#, c-format
+msgid "Created a copy of a misnamed branch '%s'"
+msgstr "Створено копію неправильно названої гілки \"%s\""
+
+#, c-format
+msgid "Renamed a misnamed branch '%s' away"
+msgstr "Перейменовано неправильно названу гілку \"%s\""
+
+#, c-format
+msgid "Branch renamed to %s, but HEAD is not updated!"
+msgstr ""
+
+msgid "Branch is renamed, but update of config-file failed"
+msgstr ""
+
+msgid "Branch is copied, but update of config-file failed"
+msgstr ""
+
+#, c-format
+msgid ""
+"Please edit the description for the branch\n"
+"  %s\n"
+"Lines starting with '%c' will be stripped.\n"
+msgstr ""
+
+msgid "Generic options"
+msgstr ""
+
+msgid "show hash and subject, give twice for upstream branch"
+msgstr ""
+
+msgid "suppress informational messages"
+msgstr ""
+
+msgid "set branch tracking configuration"
+msgstr "налаштувати конфігурацію відстежуваних гілок"
+
+msgid "do not use"
+msgstr ""
+
+msgid "upstream"
+msgstr ""
+
+msgid "change the upstream info"
+msgstr ""
+
+msgid "unset the upstream info"
+msgstr ""
+
+msgid "use colored output"
+msgstr ""
+
+msgid "act on remote-tracking branches"
+msgstr "працювати з віддалено відстежуваними гілками"
+
+msgid "print only branches that contain the commit"
+msgstr ""
+
+msgid "print only branches that don't contain the commit"
+msgstr ""
+
+msgid "Specific git-branch actions:"
+msgstr ""
+
+msgid "list both remote-tracking and local branches"
+msgstr ""
+
+msgid "delete fully merged branch"
+msgstr ""
+
+msgid "delete branch (even if not merged)"
+msgstr ""
+
+msgid "move/rename a branch and its reflog"
+msgstr ""
+
+msgid "move/rename a branch, even if target exists"
+msgstr ""
+
+msgid "do not output a newline after empty formatted refs"
+msgstr ""
+
+msgid "copy a branch and its reflog"
+msgstr ""
+
+msgid "copy a branch, even if target exists"
+msgstr ""
+
+msgid "list branch names"
+msgstr "показати назви гілок"
+
+msgid "show current branch name"
+msgstr "показати назву поточної гілки"
+
+msgid "create the branch's reflog"
+msgstr ""
+
+msgid "edit the description for the branch"
+msgstr "редагувати опис гілки"
+
+msgid "force creation, move/rename, deletion"
+msgstr ""
+
+msgid "print only branches that are merged"
+msgstr ""
+
+msgid "print only branches that are not merged"
+msgstr ""
+
+msgid "list branches in columns"
+msgstr ""
+
+msgid "object"
+msgstr ""
+
+msgid "print only branches of the object"
+msgstr ""
+
+msgid "sorting and filtering are case insensitive"
+msgstr ""
+
+msgid "recurse through submodules"
+msgstr "рекурсивно через підмодулі"
+
+msgid "format to use for the output"
+msgstr ""
+
+msgid "Failed to resolve HEAD as a valid ref."
+msgstr "Не вдалося розпізнати HEAD як дійсне посилання."
+
+msgid "HEAD not found below refs/heads!"
+msgstr "HEAD не знайдено під посиланнями/заголовками!"
+
+msgid ""
+"branch with --recurse-submodules can only be used if submodule."
+"propagateBranches is enabled"
+msgstr ""
+
+msgid "--recurse-submodules can only be used to create branches"
+msgstr ""
+
+msgid "branch name required"
+msgstr ""
+
+msgid "Cannot give description to detached HEAD"
+msgstr ""
+
+msgid "cannot edit description of more than one branch"
+msgstr ""
+
+msgid "cannot copy the current branch while not on any."
+msgstr ""
+
+msgid "cannot rename the current branch while not on any."
+msgstr ""
+
+msgid "too many branches for a copy operation"
+msgstr ""
+
+msgid "too many arguments for a rename operation"
+msgstr ""
+
+msgid "too many arguments to set new upstream"
+msgstr ""
+
+#, c-format
+msgid ""
+"could not set upstream of HEAD to %s when it does not point to any branch."
+msgstr ""
+
+#, c-format
+msgid "no such branch '%s'"
+msgstr "немає такої гілки \"%s\""
+
+#, c-format
+msgid "branch '%s' does not exist"
+msgstr "гілка \"%s\" не існує"
+
+msgid "too many arguments to unset upstream"
+msgstr "забагато аргументів для скидання значення першоджерельного сховища"
+
+msgid "could not unset upstream of HEAD when it does not point to any branch."
+msgstr ""
+"неможливво скинути значення першоджерельного сховища для HEAD, якщо він не "
+"вказує на жодну гілку."
+
+#, c-format
+msgid "Branch '%s' has no upstream information"
+msgstr "Гілка \"%s\" не має інформації щодо першоджерельного сховища"
+
+msgid ""
+"The -a, and -r, options to 'git branch' do not take a branch name.\n"
+"Did you mean to use: -a|-r --list <pattern>?"
+msgstr ""
+
+msgid ""
+"the '--set-upstream' option is no longer supported. Please use '--track' or "
+"'--set-upstream-to' instead."
+msgstr ""
+
+msgid "git version:\n"
+msgstr ""
+
+#, c-format
+msgid "uname() failed with error '%s' (%d)\n"
+msgstr ""
+
+msgid "compiler info: "
+msgstr ""
+
+msgid "libc info: "
+msgstr ""
+
+msgid "not run from a git repository - no hooks to show\n"
+msgstr ""
+
+msgid ""
+"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"              [--diagnose[=<mode>]]"
+msgstr ""
+
+msgid ""
+"Thank you for filling out a Git bug report!\n"
+"Please answer the following questions to help us understand your issue.\n"
+"\n"
+"What did you do before the bug happened? (Steps to reproduce your issue)\n"
+"\n"
+"What did you expect to happen? (Expected behavior)\n"
+"\n"
+"What happened instead? (Actual behavior)\n"
+"\n"
+"What's different between what you expected and what actually happened?\n"
+"\n"
+"Anything else you want to add:\n"
+"\n"
+"Please review the rest of the bug report below.\n"
+"You can delete any lines you don't wish to share.\n"
+msgstr ""
+
+msgid "mode"
+msgstr ""
+
+msgid ""
+"create an additional zip archive of detailed diagnostics (default 'stats')"
+msgstr ""
+
+msgid "specify a destination for the bugreport file(s)"
+msgstr ""
+
+msgid "specify a strftime format suffix for the filename(s)"
+msgstr ""
+
+#, c-format
+msgid "could not create leading directories for '%s'"
+msgstr "не вдалося створити провідні каталоги для \"%s\""
+
+#, c-format
+msgid "unable to create diagnostics archive %s"
+msgstr "не вдалося створити архів діагностики %s"
+
+msgid "System Info"
+msgstr ""
+
+msgid "Enabled Hooks"
+msgstr ""
+
+#, c-format
+msgid "unable to write to %s"
+msgstr "не вдалося записати до %s"
+
+#, c-format
+msgid "Created new report at '%s'.\n"
+msgstr ""
+
+msgid ""
+"git bundle create [-q | --quiet | --progress]\n"
+"                  [--version=<version>] <file> <git-rev-list-args>"
+msgstr ""
+
+msgid "git bundle verify [-q | --quiet] <file>"
+msgstr ""
+
+msgid "git bundle list-heads <file> [<refname>...]"
+msgstr ""
+
+msgid "git bundle unbundle [--progress] <file> [<refname>...]"
+msgstr ""
+
+msgid "need a <file> argument"
+msgstr ""
+
+msgid "do not show progress meter"
+msgstr ""
+
+msgid "show progress meter"
+msgstr "показувати прогрес виконання"
+
+msgid "historical; same as --progress"
+msgstr ""
+
+msgid "historical; does nothing"
+msgstr "історична; не робить нічогісенько"
+
+msgid "specify bundle format version"
+msgstr ""
+
+msgid "Need a repository to create a bundle."
+msgstr ""
+
+msgid "do not show bundle details"
+msgstr ""
+
+#, c-format
+msgid "%s is okay\n"
+msgstr ""
+
+msgid "Need a repository to unbundle."
+msgstr "Потрібне сховище для розділення."
+
+msgid "Unbundling objects"
+msgstr "Розділення об’єктів"
+
+#, c-format
+msgid "cannot read object %s '%s'"
+msgstr "неможливо прочитати об’єкт %s \"%s\""
+
+msgid "flush is only for --buffer mode"
+msgstr ""
+
+msgid "empty command in input"
+msgstr ""
+
+#, c-format
+msgid "whitespace before command: '%s'"
+msgstr ""
+
+#, c-format
+msgid "%s requires arguments"
+msgstr ""
+
+#, c-format
+msgid "%s takes no arguments"
+msgstr "%s не потребує аргументів"
+
+msgid "only one batch option may be specified"
+msgstr ""
+
+msgid "git cat-file <type> <object>"
+msgstr ""
+
+msgid "git cat-file (-e | -p) <object>"
+msgstr ""
+
+msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>"
+msgstr ""
+
+msgid ""
+"git cat-file (--batch | --batch-check | --batch-command) [--batch-all-"
+"objects]\n"
+"             [--buffer] [--follow-symlinks] [--unordered]\n"
+"             [--textconv | --filters] [-z]"
+msgstr ""
+
+msgid ""
+"git cat-file (--textconv | --filters)\n"
+"             [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"
+msgstr ""
+
+msgid "Check object existence or emit object contents"
+msgstr ""
+
+msgid "check if <object> exists"
+msgstr "перевірити, чи існує <об’єкт>"
+
+msgid "pretty-print <object> content"
+msgstr ""
+
+msgid "Emit [broken] object attributes"
+msgstr ""
+
+msgid "show object type (one of 'blob', 'tree', 'commit', 'tag', ...)"
+msgstr ""
+
+msgid "show object size"
+msgstr ""
+
+msgid "allow -s and -t to work with broken/corrupt objects"
+msgstr ""
+
+msgid "use mail map file"
+msgstr ""
+
+msgid "Batch objects requested on stdin (or --batch-all-objects)"
+msgstr ""
+
+msgid "show full <object> or <rev> contents"
+msgstr ""
+
+msgid "like --batch, but don't emit <contents>"
+msgstr ""
+
+msgid "stdin is NUL-terminated"
+msgstr ""
+
+msgid "read commands from stdin"
+msgstr "читати команди з stdin"
+
+msgid "with --batch[-check]: ignores stdin, batches all known objects"
+msgstr ""
+
+msgid "Change or optimize batch output"
+msgstr ""
+
+msgid "buffer --batch output"
+msgstr ""
+
+msgid "follow in-tree symlinks"
+msgstr ""
+
+msgid "do not order objects before emitting them"
+msgstr ""
+
+msgid ""
+"Emit object (blob or tree) with conversion or filter (stand-alone, or with "
+"batch)"
+msgstr ""
+
+msgid "run textconv on object's content"
+msgstr ""
+
+msgid "run filters on object's content"
+msgstr ""
+
+msgid "blob|tree"
+msgstr ""
+
+msgid "use a <path> for (--textconv | --filters); Not with 'batch'"
+msgstr ""
+
+#, c-format
+msgid "'%s=<%s>' needs '%s' or '%s'"
+msgstr ""
+
+msgid "path|tree-ish"
+msgstr ""
+
+#, c-format
+msgid "'%s' requires a batch mode"
+msgstr ""
+
+#, c-format
+msgid "'-%c' is incompatible with batch mode"
+msgstr ""
+
+msgid "batch modes take no arguments"
+msgstr ""
+
+#, c-format
+msgid "<rev> required with '%s'"
+msgstr ""
+
+#, c-format
+msgid "<object> required with '-%c'"
+msgstr ""
+
+#, c-format
+msgid "only two arguments allowed in <type> <object> mode, not %d"
+msgstr ""
+
+msgid ""
+"git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] "
+"<pathname>..."
+msgstr ""
+
+msgid ""
+"git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]"
+msgstr ""
+"git check-attr --stdin [-z] [--source <деревоподібне джерело>] [-a | --all | "
+"<атрибут>...]"
+
+msgid "report all attributes set on file"
+msgstr ""
+
+msgid "use .gitattributes only from the index"
+msgstr ""
+
+msgid "read file names from stdin"
+msgstr ""
+
+msgid "terminate input and output records by a NUL character"
+msgstr ""
+
+msgid "<tree-ish>"
+msgstr ""
+
+msgid "which tree-ish to check attributes at"
+msgstr "атрибути якого деревоподібного джерела перевіряти"
+
+msgid "suppress progress reporting"
+msgstr "не звітувати прогрес"
+
+msgid "show non-matching input paths"
+msgstr ""
+
+msgid "ignore index when checking"
+msgstr ""
+
+msgid "cannot specify pathnames with --stdin"
+msgstr ""
+
+msgid "-z only makes sense with --stdin"
+msgstr ""
+
+msgid "no path specified"
+msgstr "шлях не вказано"
+
+msgid "--quiet is only valid with a single pathname"
+msgstr ""
+
+msgid "cannot have both --quiet and --verbose"
+msgstr ""
+
+msgid "--non-matching is only valid with --verbose"
+msgstr ""
+
+msgid "git check-mailmap [<options>] <contact>..."
+msgstr "git check-mailmap [<опції>] <контакт>..."
+
+msgid "also read contacts from stdin"
+msgstr ""
+
+#, c-format
+msgid "unable to parse contact: %s"
+msgstr "не вдалося розібрати контакт: %s"
+
+msgid "no contacts specified"
+msgstr ""
+
+msgid "git checkout--worker [<options>]"
+msgstr "git checkout--worker [<опції>]"
+
+msgid "string"
+msgstr ""
+
+msgid "when creating files, prepend <string>"
+msgstr ""
+
+msgid "git checkout-index [<options>] [--] [<file>...]"
+msgstr "git checkout-index [<опції>] [—] [<файл>...]"
+
+msgid "stage should be between 1 and 3 or all"
+msgstr ""
+
+msgid "check out all files in the index"
+msgstr ""
+
+msgid "do not skip files with skip-worktree set"
+msgstr ""
+
+msgid "force overwrite of existing files"
+msgstr ""
+
+msgid "no warning for existing files and files not in index"
+msgstr ""
+
+msgid "don't checkout new files"
+msgstr ""
+
+msgid "update stat information in the index file"
+msgstr "оновити статистичну інформацію в індексному файлі"
+
+msgid "read list of paths from the standard input"
+msgstr ""
+
+msgid "write the content to temporary files"
+msgstr ""
+
+msgid "copy out the files from named stage"
+msgstr ""
+
+msgid "git checkout [<options>] <branch>"
+msgstr "git checkout [<опції>] <гілка>"
+
+msgid "git checkout [<options>] [<branch>] -- <file>..."
+msgstr "git checkout [<опції>] [<гілка>] -- <файл>..."
+
+msgid "git switch [<options>] [<branch>]"
+msgstr "git switch [<опції>] [<гілка>]"
+
+msgid "git restore [<options>] [--source=<branch>] <file>..."
+msgstr "git restore [<опції>] [--source=<гілка>] <файл>..."
+
+#, c-format
+msgid "path '%s' does not have our version"
+msgstr "шлях '%s' не містить нашої версії"
+
+#, c-format
+msgid "path '%s' does not have their version"
+msgstr "шлях '%s' не містить їхньої версії"
+
+#, c-format
+msgid "path '%s' does not have all necessary versions"
+msgstr "шлях '%s' не містить всіх необхідних версій"
+
+#, c-format
+msgid "path '%s' does not have necessary versions"
+msgstr "шлях '%s' не містить необхідних версій"
+
+#, c-format
+msgid "path '%s': cannot merge"
+msgstr "шлях '%s': неможливо злити"
+
+#, c-format
+msgid "Unable to add merge result for '%s'"
+msgstr "Неможливо додати результат злиття для '%s'"
+
+#, c-format
+msgid "Recreated %d merge conflict"
+msgid_plural "Recreated %d merge conflicts"
+msgstr[0] "Відтворено %d конфлікт злиття"
+msgstr[1] "Відтворено %d конфлікта злиття"
+msgstr[2] "Відтворено %d конфліктів злиття"
+
+#, c-format
+msgid "Updated %d path from %s"
+msgid_plural "Updated %d paths from %s"
+msgstr[0] "Оновлено %d шлях з %s"
+msgstr[1] "Оновлено %d шляхи з %s"
+msgstr[2] "Оновлено %d шляхів з %s"
+
+#, c-format
+msgid "Updated %d path from the index"
+msgid_plural "Updated %d paths from the index"
+msgstr[0] "Оновлено %d шлях з індексу"
+msgstr[1] "Оновлено %d шляхи з індексу"
+msgstr[2] "Оновлено %d шляхів з індексу"
+
+#, c-format
+msgid "'%s' cannot be used with updating paths"
+msgstr "'%s' не можна використовувати зі шляхами оновлення"
+
+#, c-format
+msgid "Cannot update paths and switch to branch '%s' at the same time."
+msgstr "Неможливо одночасно оновити шляхи та переключитись на гілку '%s'."
+
+#, c-format
+msgid "neither '%s' or '%s' is specified"
+msgstr "не вказано ні '%s', ні '%s'"
+
+#, c-format
+msgid "'%s' must be used when '%s' is not specified"
+msgstr "'%s' повинен використовуватися, якщо не вказано '%s'"
+
+#, c-format
+msgid "'%s' or '%s' cannot be used with %s"
+msgstr "'%s' або '%s' не можна використовувати з %s"
+
+#, c-format
+msgid "path '%s' is unmerged"
+msgstr "шлях '%s' не злитий"
+
+msgid "you need to resolve your current index first"
+msgstr "спочатку потрібно розібратись з вашим поточним індексом"
+
+#, c-format
+msgid ""
+"cannot continue with staged changes in the following files:\n"
+"%s"
+msgstr ""
+"неможливо продовжити з індексованими змінами в наступних файлах:\n"
+"%s"
+
+#, c-format
+msgid "Can not do reflog for '%s': %s\n"
+msgstr "Неможливо виконати reflog для '%s': %s\n"
+
+msgid "HEAD is now at"
+msgstr "HEAD зараз на"
+
+msgid "unable to update HEAD"
+msgstr "не вдалося оновити HEAD"
+
+#, c-format
+msgid "Reset branch '%s'\n"
+msgstr "Скинути гілку '%s'\n"
+
+#, c-format
+msgid "Already on '%s'\n"
+msgstr "Вже на '%s'\n"
+
+#, c-format
+msgid "Switched to and reset branch '%s'\n"
+msgstr "Переключено на та скинуто гілку '%s'\n"
+
+#, c-format
+msgid "Switched to a new branch '%s'\n"
+msgstr "Переключено на нову гілку '%s'\n"
+
+#, c-format
+msgid "Switched to branch '%s'\n"
+msgstr "Переключено на гілку '%s'\n"
+
+#, c-format
+msgid " ... and %d more.\n"
+msgstr " ... та ще %d.\n"
+
+#, c-format
+msgid ""
+"Warning: you are leaving %d commit behind, not connected to\n"
+"any of your branches:\n"
+"\n"
+"%s\n"
+msgid_plural ""
+"Warning: you are leaving %d commits behind, not connected to\n"
+"any of your branches:\n"
+"\n"
+"%s\n"
+msgstr[0] ""
+"Попередження: ви залишаєте позаду %d коміт, не підключений до\n"
+"жодної з ваших гілок:\n"
+"\n"
+"%s\n"
+msgstr[1] ""
+"Попередження: ви залишаєте позаду %d коміта, не підключених до\n"
+"жодної з ваших гілок:\n"
+"\n"
+"%s\n"
+msgstr[2] ""
+"Попередження: ви залишаєте позаду %d комітів, не підключених до\n"
+"жодної з ваших гілок:\n"
+"\n"
+"%s\n"
+
+#, c-format
+msgid ""
+"If you want to keep it by creating a new branch, this may be a good time\n"
+"to do so with:\n"
+"\n"
+" git branch <new-branch-name> %s\n"
+"\n"
+msgid_plural ""
+"If you want to keep them by creating a new branch, this may be a good time\n"
+"to do so with:\n"
+"\n"
+" git branch <new-branch-name> %s\n"
+"\n"
+msgstr[0] ""
+"Якщо ви хочете зберегти його, створивши нову гілку, то зараз є чудова "
+"нагода\n"
+"зробити це за допомогою:\n"
+"git branch <назва-нової-гілки> %s\n"
+"\n"
+msgstr[1] ""
+"Якщо ви хочете зберегти їх, створивши нову гілку, то зараз є чудова нагода\n"
+"зробити це за допомогою:\n"
+"git branch <назва-нової-гілки> %s\n"
+"\n"
+msgstr[2] ""
+"Якщо ви хочете зберегти їх, створивши нову гілку, то зараз є чудова нагода\n"
+"зробити це за допомогою:\n"
+"git branch <назва-нової-гілки> %s\n"
+"\n"
+
+msgid "internal error in revision walk"
+msgstr "внутрішня помилка при проходженні по ревізіям"
+
+msgid "Previous HEAD position was"
+msgstr "Попередня позиція HEAD була"
+
+msgid "You are on a branch yet to be born"
+msgstr "Ви на гілці, яка ще не iснує"
+
+#, c-format
+msgid ""
+"'%s' could be both a local file and a tracking branch.\n"
+"Please use -- (and optionally --no-guess) to disambiguate"
+msgstr ""
+"\"%s\" може бути як локальним файлом, так і відстежуваною гілкою.\n"
+"Будь ласка, використовуйте -- (і, за бажанням, --no-guess), для визначення"
+
+msgid ""
+"If you meant to check out a remote tracking branch on, e.g. 'origin',\n"
+"you can do so by fully qualifying the name with the --track option:\n"
+"\n"
+"    git checkout --track origin/<name>\n"
+"\n"
+"If you'd like to always have checkouts of an ambiguous <name> prefer\n"
+"one remote, e.g. the 'origin' remote, consider setting\n"
+"checkout.defaultRemote=origin in your config."
+msgstr ""
+"Якщо ви хотіли переключитись на віддалено відстежувану гілку, наприклад, "
+"'origin',\n"
+"ви можете зробити це, повністю вказавши назву з опцією --track:\n"
+"\n"
+"    git checkout --track origin/<назва>.\n"
+"\n"
+"Якщо при переключенні з неоднозначною <назвою> ви бажаєте завжди віддавати "
+"перевагу\n"
+"певному віддаленому сховищу, наприклад, 'origin', розгляньте можливість "
+"додання\n"
+"checkout.defaultRemote=origin до вашого конфігураційного файлу."
+
+#, c-format
+msgid "'%s' matched multiple (%d) remote tracking branches"
+msgstr "\"%s\" відповідає декільком (%d) гілкам віддаленого відстежування"
+
+msgid "only one reference expected"
+msgstr "очікувалось тільки одне посилання"
+
+#, c-format
+msgid "only one reference expected, %d given."
+msgstr "очікувалось тільки одне посилання, надано %d."
+
+#, c-format
+msgid "invalid reference: %s"
+msgstr "неприпустиме посилання: %s"
+
+#, c-format
+msgid "reference is not a tree: %s"
+msgstr "посилання не є деревом: %s"
+
+#, c-format
+msgid "a branch is expected, got tag '%s'"
+msgstr "очікувалась гілка, надано тег '%s'"
+
+#, c-format
+msgid "a branch is expected, got remote branch '%s'"
+msgstr "очікувалась гілка, надана віддалена гілка '%s'"
+
+#, c-format
+msgid "a branch is expected, got '%s'"
+msgstr "очікувалась гілка, надано '%s'"
+
+#, c-format
+msgid "a branch is expected, got commit '%s'"
+msgstr "очікувалась гілка, надано коміт '%s'"
+
+msgid ""
+"If you want to detach HEAD at the commit, try again with the --detach option."
+msgstr ""
+"Якщо ви хочете від'єднати HEAD на цьому коміті, спробуйте ще раз з опцією --"
+"detach."
+
+msgid ""
+"cannot switch branch while merging\n"
+"Consider \"git merge --quit\" or \"git worktree add\"."
+msgstr ""
+"неможливо змінити гілку під час злиття\n"
+"Спробуйте \"git merge --quit\" або \"git worktree add\"."
+
+msgid ""
+"cannot switch branch in the middle of an am session\n"
+"Consider \"git am --quit\" or \"git worktree add\"."
+msgstr ""
+"неможливо змінити гілку під час am сеансу\n"
+"Спробуйте \"git am --quit\" або \"git worktree add\"."
+
+msgid ""
+"cannot switch branch while rebasing\n"
+"Consider \"git rebase --quit\" or \"git worktree add\"."
+msgstr ""
+"неможливо змінити гілку під час перебазування\n"
+"Спробуйте \"git rebase --quit\" або \"git worktree add\"."
+
+msgid ""
+"cannot switch branch while cherry-picking\n"
+"Consider \"git cherry-pick --quit\" or \"git worktree add\"."
+msgstr ""
+"неможливо змінити гілку під час висмикування\n"
+"Спробуйте \"git cherry-pick --quit\" або \"git worktree add\"."
+
+msgid ""
+"cannot switch branch while reverting\n"
+"Consider \"git revert --quit\" or \"git worktree add\"."
+msgstr ""
+"неможливо змінити гілку під час вивертання\n"
+"Спробуйте \"git revert --quit\" або \"git worktree add\"."
+
+msgid "you are switching branch while bisecting"
+msgstr "ви переключаєте гілку під час бісекції"
+
+msgid "paths cannot be used with switching branches"
+msgstr "шляхи не можуть використовуватись при переключенні гілок"
+
+#, c-format
+msgid "'%s' cannot be used with switching branches"
+msgstr "'%s' не може використовуватись при переключенні гілок"
+
+#, c-format
+msgid "'%s' cannot be used with '%s'"
+msgstr "'%s' не може використовуватись з '%s'"
+
+#, c-format
+msgid "'%s' cannot take <start-point>"
+msgstr "'%s' не може прийняти <стартова-точка>"
+
+#, c-format
+msgid "Cannot switch branch to a non-commit '%s'"
+msgstr "Неможливо переключити гілку на не коміт '%s'"
+
+msgid "missing branch or commit argument"
+msgstr "відсутня гілка або коміт"
+
+msgid "perform a 3-way merge with the new branch"
+msgstr "здійснити 3-стороннє злиття з новою гілкою"
+
+msgid "style"
+msgstr "стиль"
+
+msgid "conflict style (merge, diff3, or zdiff3)"
+msgstr "конфлікт стилю (merge, diff3 або zdiff3)"
+
+msgid "detach HEAD at named commit"
+msgstr "відʼєднати HEAD на вказаному коміті"
+
+msgid "force checkout (throw away local modifications)"
+msgstr "переключити примусово (викинути локальні зміни)"
+
+msgid "new-branch"
+msgstr "нова-гілка"
+
+msgid "new unparented branch"
+msgstr "нова гілка без джерела"
+
+msgid "update ignored files (default)"
+msgstr "оновити ігноровані файли (за замовчуванням)"
+
+msgid "do not check if another worktree is holding the given ref"
+msgstr "не перевіряти, чи інше робоче дерево містить дане посилання"
+
+msgid "checkout our version for unmerged files"
+msgstr "використовувати нашу версію для незлитих файлів"
+
+msgid "checkout their version for unmerged files"
+msgstr "використовувати їхню версію для незлитих файлів"
+
+msgid "do not limit pathspecs to sparse entries only"
+msgstr "не обмежувати визначники шляхів лише розрідженими записами"
+
+#, c-format
+msgid "options '-%c', '-%c', and '%s' cannot be used together"
+msgstr "опції '-%c', '-%c' та '%s' не можуть використовуватись разом"
+
+msgid "--track needs a branch name"
+msgstr "--track потребує назви гілки"
+
+#, c-format
+msgid "missing branch name; try -%c"
+msgstr "відсутня назва гілки; спробуйте -%c"
+
+#, c-format
+msgid "could not resolve %s"
+msgstr "не вдалося розвʼязати %s"
+
+msgid "invalid path specification"
+msgstr "неприпустиме зазначення шляху"
+
+#, c-format
+msgid "'%s' is not a commit and a branch '%s' cannot be created from it"
+msgstr "'%s' не є комітом, і з нього не можна створити гілку '%s'"
+
+#, c-format
+msgid "git checkout: --detach does not take a path argument '%s'"
+msgstr "git checkout: --detach не приймає аргумент шляху '%s'"
+
+msgid ""
+"git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
+"checking out of the index."
+msgstr ""
+"git checkout: --ours/--theirs, --force та --merge несумісні при\n"
+"при прееключенні індексу."
+
+msgid "you must specify path(s) to restore"
+msgstr "необхідно вказати шлях(и) для відновлення"
+
+msgid "branch"
+msgstr "гілка"
+
+msgid "create and checkout a new branch"
+msgstr "створити та перейти до нової гілки"
+
+msgid "create/reset and checkout a branch"
+msgstr "створити/скинути та перейти до нової гілки"
+
+msgid "create reflog for new branch"
+msgstr "створити reflog для нової гілки"
+
+msgid "second guess 'git checkout <no-such-branch>' (default)"
+msgstr "друга здогадка \"git checkout <гілка-не-існує>\" (за замовчуванням)"
+
+msgid "use overlay mode (default)"
+msgstr "використовувати режим накладення (за замовчуванням)"
+
+msgid "create and switch to a new branch"
+msgstr "створити та переключити на нову гілку"
+
+msgid "create/reset and switch to a branch"
+msgstr "створити/скинути та переключити на гілку"
+
+msgid "second guess 'git switch <no-such-branch>'"
+msgstr "друга здогадка \"git switch <гілка-не-існує>\" (за замовчуванням)"
+
+msgid "throw away local modifications"
+msgstr "викинути локальні зміни"
+
+msgid "which tree-ish to checkout from"
+msgstr "з якого деревоподібного джерела створювати"
+
+msgid "restore the index"
+msgstr "відновити індекс"
+
+msgid "restore the working tree (default)"
+msgstr "відновити робоче дерево (за замовчуванням)"
+
+msgid "ignore unmerged entries"
+msgstr "ігнорувати незлиті записи"
+
+msgid "use overlay mode"
+msgstr "використовувати режим накладення"
+
+msgid ""
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] "
+"[<pathspec>...]"
+msgstr ""
+
+#, c-format
+msgid "Removing %s\n"
+msgstr "Видалення %s\n"
+
+#, c-format
+msgid "Would remove %s\n"
+msgstr "Було б видалено %s\n"
+
+#, c-format
+msgid "Skipping repository %s\n"
+msgstr "Пропуск сховища %s\n"
+
+#, c-format
+msgid "Would skip repository %s\n"
+msgstr "Було б пропущено сховище %s\n"
+
+#, c-format
+msgid "failed to remove %s"
+msgstr "не вдалося видалити %s"
+
+#, c-format
+msgid "could not lstat %s\n"
+msgstr "не вдалося виконати lstat %s\n"
+
+msgid "Refusing to remove current working directory\n"
+msgstr "Відмова в видаленні поточної робочої директорії\n"
+
+msgid "Would refuse to remove current working directory\n"
+msgstr "Було б відмовлено в видаленні поточної робочої директорії\n"
+
+#, c-format
+msgid ""
+"Prompt help:\n"
+"1          - select a numbered item\n"
+"foo        - select item based on unique prefix\n"
+"           - (empty) select nothing\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"Prompt help:\n"
+"1          - select a single item\n"
+"3-5        - select a range of items\n"
+"2-3,6-9    - select multiple ranges\n"
+"foo        - select item based on unique prefix\n"
+"-...       - unselect specified items\n"
+"*          - choose all items\n"
+"           - (empty) finish selecting\n"
+msgstr ""
+
+#, c-format
+msgid "Huh (%s)?\n"
+msgstr ""
+
+#, c-format
+msgid "Input ignore patterns>> "
+msgstr ""
+
+#, c-format
+msgid "WARNING: Cannot find items matched by: %s"
+msgstr ""
+
+msgid "Select items to delete"
+msgstr ""
+
+#. TRANSLATORS: Make sure to keep [y/N] as is
+
+#, c-format
+msgid "Remove %s [y/N]? "
+msgstr ""
+
+msgid ""
+"clean               - start cleaning\n"
+"filter by pattern   - exclude items from deletion\n"
+"select by numbers   - select items to be deleted by numbers\n"
+"ask each            - confirm each deletion (like \"rm -i\")\n"
+"quit                - stop cleaning\n"
+"help                - this screen\n"
+"?                   - help for prompt selection"
+msgstr ""
+
+msgid "Would remove the following item:"
+msgid_plural "Would remove the following items:"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "No more files to clean, exiting."
+msgstr ""
+
+msgid "do not print names of files removed"
+msgstr ""
+
+msgid "force"
+msgstr ""
+
+msgid "interactive cleaning"
+msgstr ""
+
+msgid "remove whole directories"
+msgstr ""
+
+msgid "pattern"
+msgstr ""
+
+msgid "add <pattern> to ignore rules"
+msgstr ""
+
+msgid "remove ignored files, too"
+msgstr "видалити також ігноровані файли"
+
+msgid "remove only ignored files"
+msgstr "видалити лише ігноровані файли"
+
+msgid ""
+"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
+"clean"
+msgstr ""
+
+msgid ""
+"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
+"refusing to clean"
+msgstr ""
+
+msgid "-x and -X cannot be used together"
+msgstr "-x та -X не можна використовувати разом"
+
+msgid "git clone [<options>] [--] <repo> [<dir>]"
+msgstr "git clone [<опції>] [--] <сховище> [<директорія>]"
+
+msgid "don't clone shallow repository"
+msgstr "не клонувати неглибоке сховище"
+
+msgid "don't create a checkout"
+msgstr "не переходити до гілки"
+
+msgid "create a bare repository"
+msgstr "створити порожнє сховище"
+
+msgid "create a mirror repository (implies bare)"
+msgstr "створити дзеркальне сховище (включає опцію bare)"
+
+msgid "to clone from a local repository"
+msgstr "клонувати з локального сховища"
+
+msgid "don't use local hardlinks, always copy"
+msgstr "не використовувати локальні жорсткі посилання, завжди копіювати"
+
+msgid "setup as shared repository"
+msgstr "налаштувати як спільне сховище"
+
+msgid "pathspec"
+msgstr "визначник шляху"
+
+msgid "initialize submodules in the clone"
+msgstr "ініціалізувати підмодулі в клоні"
+
+msgid "number of submodules cloned in parallel"
+msgstr "кількість підмодулів, що клонуються паралельно"
+
+msgid "template-directory"
+msgstr "директорія-шаблонів"
+
+msgid "directory from which templates will be used"
+msgstr "директорія, з якої брати шаблони"
+
+msgid "reference repository"
+msgstr "посилання на сховище"
+
+msgid "use --reference only while cloning"
+msgstr "використовуйте --reference тільки під час клонування"
+
+msgid "name"
+msgstr "назва"
+
+msgid "use <name> instead of 'origin' to track upstream"
+msgstr ""
+"використовуйте <назва> замість \"origin\" для відстежування першоджерельного "
+"сховища"
+
+msgid "checkout <branch> instead of the remote's HEAD"
+msgstr "перейти до <гілки> замість HEAD віддаленого сховища"
+
+msgid "path to git-upload-pack on the remote"
+msgstr "шлях до git-upload-pack на віддаленому сервері"
+
+msgid "depth"
+msgstr "глибина"
+
+msgid "create a shallow clone of that depth"
+msgstr "створити поверхневий клон вказаної глибини"
+
+msgid "create a shallow clone since a specific time"
+msgstr "створити поверхневий клон з певного часу"
+
+msgid "revision"
+msgstr "ревізія"
+
+msgid "deepen history of shallow clone, excluding rev"
+msgstr "поглибити історію поверхневого клону, за винятком rev"
+
+msgid "clone only one branch, HEAD or --branch"
+msgstr "клонувати лише одну гілку, HEAD або --branch"
+
+msgid "don't clone any tags, and make later fetches not to follow them"
+msgstr ""
+"не клонувати жодних тегів і не слідувати за ними під час отримувань пізніше"
+
+msgid "any cloned submodules will be shallow"
+msgstr "будь-які клоновані підмодулі будуть поверхневими"
+
+msgid "gitdir"
+msgstr "git-директорія"
+
+msgid "separate git dir from working tree"
+msgstr "відокремити git-директорію від робочого дерева"
+
+msgid "key=value"
+msgstr "ключ=значення"
+
+msgid "set config inside the new repository"
+msgstr "встановити конфігурацію всередині нового сховища"
+
+msgid "server-specific"
+msgstr "тільки для сервера"
+
+msgid "option to transmit"
+msgstr "опція для передачі"
+
+msgid "use IPv4 addresses only"
+msgstr "використовувати тільки IPv4 адреси"
+
+msgid "use IPv6 addresses only"
+msgstr "використовувати тільки IPv6 адреси"
+
+msgid "apply partial clone filters to submodules"
+msgstr "застосувати часткові фільтри клонів до підмодулів"
+
+msgid "any cloned submodules will use their remote-tracking branch"
+msgstr ""
+"будь-які клоновані підмодулі будуть використовувати свою віддалено "
+"відстежувану гілку"
+
+msgid "initialize sparse-checkout file to include only files at root"
+msgstr ""
+"ініціалізувати, щоб файл часткового переходу включав лише файли в корені"
+
+msgid "uri"
+msgstr "uri"
+
+msgid "a URI for downloading bundles before fetching from origin remote"
+msgstr "URI для завантаження пакунків перед отриманням з віддаленого джерела"
+
+#, c-format
+msgid "info: Could not add alternate for '%s': %s\n"
+msgstr "инфо: Не вдалося додати альтернативу для '%s': %s\n"
+
+#, c-format
+msgid "failed to stat '%s'"
+msgstr "не вдалося виконати stat '%s'"
+
+#, c-format
+msgid "%s exists and is not a directory"
+msgstr "%s існує і не є директорією"
+
+#, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "\"%s\" є символьним посиланням, відмова від клонування з --local"
+
+#, c-format
+msgid "failed to start iterator over '%s'"
+msgstr "не вдалося запустити перебір для '%s'"
+
+#, c-format
+msgid "symlink '%s' exists, refusing to clone with --local"
+msgstr "символьне посилання '%s' існує, не можу клонувати з --local"
+
+#, c-format
+msgid "failed to unlink '%s'"
+msgstr "не вдалося розʼєднати '%s'"
+
+#, c-format
+msgid "failed to create link '%s'"
+msgstr "не вдалося створити посилання '%s'"
+
+#, c-format
+msgid "failed to copy file to '%s'"
+msgstr "не вдалося скопіювати файл у '%s'"
+
+#, c-format
+msgid "failed to iterate over '%s'"
+msgstr "не вдалося перебрати '%s'"
+
+#, c-format
+msgid "done.\n"
+msgstr "готово.\n"
+
+msgid ""
+"Clone succeeded, but checkout failed.\n"
+"You can inspect what was checked out with 'git status'\n"
+"and retry with 'git restore --source=HEAD :/'\n"
+msgstr ""
+"Клонування пройшло успішно, але не вдалося перейти до гілки.\n"
+"Ви можете перевірити, що було додано за допомогою 'git status'\n"
+"і повторити спробу за допомогою 'git restore --source=HEAD :/'\n"
+
+#, c-format
+msgid "Could not find remote branch %s to clone."
+msgstr "Не вдалося знайти віддалену гілку %s для клонування."
+
+msgid "remote did not send all necessary objects"
+msgstr "віддалене сховище не надіслало всі необхідні обʼєкти"
+
+#, c-format
+msgid "unable to update %s"
+msgstr "не вдалося оновити %s"
+
+msgid "failed to initialize sparse-checkout"
+msgstr "не вдалося ініціалізувати частковий перехід"
+
+msgid "remote HEAD refers to nonexistent ref, unable to checkout"
+msgstr "віддалений HEAD посилається на неіснуючого рефа, неможливо перейти"
+
+msgid "unable to checkout working tree"
+msgstr "не вдалося завантажити стан робочої директорії"
+
+msgid "unable to write parameters to config file"
+msgstr "не вдалося записати параметри до конфігураційного файлу"
+
+msgid "cannot repack to clean up"
+msgstr "неможливо перепакувати, щоб очистити"
+
+msgid "cannot unlink temporary alternates file"
+msgstr "не вдається розʼєднати файл тимчасових альтернатив"
+
+msgid "Too many arguments."
+msgstr "Забагато аргументів."
+
+msgid "You must specify a repository to clone."
+msgstr "Треба вказати сховище для клонування."
+
+msgid ""
+"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
+"exclude"
+msgstr ""
+"--bundle-uri несумісний з --depth, --shallow-since та --shallow-exclude"
+
+#, c-format
+msgid "repository '%s' does not exist"
+msgstr "сховище '%s' не існує"
+
+#, c-format
+msgid "depth %s is not a positive number"
+msgstr "глибина %s не є додатнім числом"
+
+#, c-format
+msgid "destination path '%s' already exists and is not an empty directory."
+msgstr "шлях призначення '%s' вже існує і не є порожньою директорією."
+
+#, c-format
+msgid "repository path '%s' already exists and is not an empty directory."
+msgstr "шлях до сховища '%s' вже існує і не є порожньою директорією."
+
+#, c-format
+msgid "working tree '%s' already exists."
+msgstr "робоче дерево '%s' вже існує."
+
+#, c-format
+msgid "could not create leading directories of '%s'"
+msgstr "не вдалося створити провідні директорії для '%s'"
+
+#, c-format
+msgid "could not create work tree dir '%s'"
+msgstr "не вдалося створити директорію робочого дерева '%s'"
+
+#, c-format
+msgid "Cloning into bare repository '%s'...\n"
+msgstr "Клонування у порожнє сховище '%s'...\n"
+
+#, c-format
+msgid "Cloning into '%s'...\n"
+msgstr "Клонування в '%s'...\n"
+
+msgid ""
+"clone --recursive is not compatible with both --reference and --reference-if-"
+"able"
+msgstr ""
+"clone --recursive не сумісне з --reference та --reference-if-able одночасно"
+
+#, c-format
+msgid "'%s' is not a valid remote name"
+msgstr "\"%s\" не є дійсною назвою віддаленого сховища"
+
+msgid "--depth is ignored in local clones; use file:// instead."
+msgstr ""
+"--depth ігнорується у локальних клонах; використовуйте file:// замість цього."
+
+msgid "--shallow-since is ignored in local clones; use file:// instead."
+msgstr ""
+"--shallow-since ігнорується у локальних клонах; використовуйте file:// "
+"замість цього."
+
+msgid "--shallow-exclude is ignored in local clones; use file:// instead."
+msgstr ""
+"--shallow-exclude ігнорується у локальних клонах; використовуйте file:// "
+"замість цього."
+
+msgid "--filter is ignored in local clones; use file:// instead."
+msgstr ""
+"--filter ігнорується у локальних клонах; використовуйте file:// замість "
+"нього."
+
+msgid "source repository is shallow, reject to clone."
+msgstr "джерельне сховище є неглибоким, клонування відхилено."
+
+msgid "source repository is shallow, ignoring --local"
+msgstr "джерельне сховище є неглибоким, --local ігнорується"
+
+msgid "--local is ignored"
+msgstr "--local ігнорується"
+
+msgid "cannot clone from filtered bundle"
+msgstr "неможливо клонувати з відфільтрованого пакета"
+
+msgid "failed to initialize the repo, skipping bundle URI"
+msgstr "не вдалося ініціалізувати репо, URI пакета пропускається"
+
+#, c-format
+msgid "failed to fetch objects from bundle URI '%s'"
+msgstr "не вдалося отримати об'єкти з пакету URI '%s'"
+
+msgid "failed to fetch advertised bundles"
+msgstr "не вдалося отримати обіцяні пакети"
+
+msgid "remote transport reported error"
+msgstr "операція віддаленного отримання повідомила про помилку"
+
+#, c-format
+msgid "Remote branch %s not found in upstream %s"
+msgstr "Віддалену гілку %s не знайдено у першоджерельному сховищі %s"
+
+msgid "You appear to have cloned an empty repository."
+msgstr "Здається, ви клонували порожнє сховище."
+
+msgid "git column [<options>]"
+msgstr "git column [<опції>]"
+
+msgid "lookup config vars"
+msgstr ""
+
+msgid "layout to use"
+msgstr ""
+
+msgid "maximum width"
+msgstr ""
+
+msgid "padding space on left border"
+msgstr ""
+
+msgid "padding space on right border"
+msgstr ""
+
+msgid "padding space between columns"
+msgstr ""
+
+msgid "--command must be the first argument"
+msgstr ""
+
+msgid ""
+"git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]"
+msgstr ""
+
+msgid ""
+"git commit-graph write [--object-dir <dir>] [--append]\n"
+"                       [--split[=<strategy>]] [--reachable | --stdin-packs | "
+"--stdin-commits]\n"
+"                       [--changed-paths] [--[no-]max-new-filters <n>] [--"
+"[no-]progress]\n"
+"                       <split options>"
+msgstr ""
+
+msgid "dir"
+msgstr "dir"
+
+msgid "the object directory to store the graph"
+msgstr ""
+
+msgid "if the commit-graph is split, only verify the tip file"
+msgstr ""
+
+#, c-format
+msgid "Could not open commit-graph '%s'"
+msgstr "Не вдалося відкрити коміт-граф \"%s\""
+
+#, c-format
+msgid "unrecognized --split argument, %s"
+msgstr ""
+
+#, c-format
+msgid "unexpected non-hex object ID: %s"
+msgstr ""
+
+#, c-format
+msgid "invalid object: %s"
+msgstr "неприпустимий об’єкт: %s"
+
+#, c-format
+msgid "option `%s' expects a numerical value"
+msgstr ""
+
+msgid "start walk at all refs"
+msgstr ""
+
+msgid "scan pack-indexes listed by stdin for commits"
+msgstr ""
+
+msgid "start walk at commits listed by stdin"
+msgstr ""
+
+msgid "include all commits already in the commit-graph file"
+msgstr ""
+
+msgid "enable computation for changed paths"
+msgstr ""
+
+msgid "allow writing an incremental commit-graph file"
+msgstr ""
+
+msgid "maximum number of commits in a non-base split commit-graph"
+msgstr ""
+
+msgid "maximum ratio between two levels of a split commit-graph"
+msgstr ""
+
+msgid "only expire files older than a given date-time"
+msgstr ""
+
+msgid "maximum number of changed-path Bloom filters to compute"
+msgstr ""
+
+msgid "use at most one of --reachable, --stdin-commits, or --stdin-packs"
+msgstr ""
+
+msgid "Collecting commits from input"
+msgstr ""
+
+msgid "git commit-tree <tree> [(-p <parent>)...]"
+msgstr ""
+
+msgid ""
+"git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n"
+"                [(-F <file>)...] <tree>"
+msgstr ""
+
+#, c-format
+msgid "duplicate parent %s ignored"
+msgstr ""
+
+#, c-format
+msgid "not a valid object name %s"
+msgstr "невірне ім’я об’єкта %s"
+
+#, c-format
+msgid "git commit-tree: failed to read '%s'"
+msgstr ""
+
+#, c-format
+msgid "git commit-tree: failed to close '%s'"
+msgstr ""
+
+msgid "parent"
+msgstr ""
+
+msgid "id of a parent commit object"
+msgstr ""
+
+msgid "message"
+msgstr ""
+
+msgid "commit message"
+msgstr ""
+
+msgid "read commit log message from file"
+msgstr ""
+
+msgid "GPG sign commit"
+msgstr "підписати коміт за допомогою GPG"
+
+msgid "must give exactly one tree"
+msgstr ""
+
+msgid "git commit-tree: failed to read"
+msgstr ""
+
+msgid ""
+"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n"
+"           [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|"
+"reword):]<commit>)]\n"
+"           [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n"
+"           [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n"
+"           [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n"
+"           [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
+"           [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n"
+"           [--] [<pathspec>...]"
+msgstr ""
+
+msgid "git status [<options>] [--] [<pathspec>...]"
+msgstr "git status [<опції>] [--] [<визначник шляху>...]"
+
+msgid ""
+"You asked to amend the most recent commit, but doing so would make\n"
+"it empty. You can repeat your command with --allow-empty, or you can\n"
+"remove the commit entirely with \"git reset HEAD^\".\n"
+msgstr ""
+
+msgid ""
+"The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
+"If you wish to commit it anyway, use:\n"
+"\n"
+"    git commit --allow-empty\n"
+"\n"
+msgstr ""
+
+msgid "Otherwise, please use 'git rebase --skip'\n"
+msgstr ""
+
+msgid "Otherwise, please use 'git cherry-pick --skip'\n"
+msgstr ""
+
+msgid ""
+"and then use:\n"
+"\n"
+"    git cherry-pick --continue\n"
+"\n"
+"to resume cherry-picking the remaining commits.\n"
+"If you wish to skip this commit, use:\n"
+"\n"
+"    git cherry-pick --skip\n"
+"\n"
+msgstr ""
+
+msgid "failed to unpack HEAD tree object"
+msgstr ""
+
+msgid "No paths with --include/--only does not make sense."
+msgstr ""
+
+msgid "unable to create temporary index"
+msgstr "не вдалося створити тимчасовий індекс"
+
+msgid "interactive add failed"
+msgstr ""
+
+msgid "unable to update temporary index"
+msgstr "не вдалося оновити тимчасовий індекс"
+
+msgid "Failed to update main cache tree"
+msgstr ""
+
+msgid "unable to write new_index file"
+msgstr "не вдалося записати new_index файл"
+
+msgid "cannot do a partial commit during a merge."
+msgstr "неможливо зробити частковий коміт під час злиття."
+
+msgid "cannot do a partial commit during a cherry-pick."
+msgstr ""
+
+msgid "cannot do a partial commit during a rebase."
+msgstr "неможливо зробити частковий коміт під час перебазування."
+
+msgid "cannot read the index"
+msgstr "неможливо прочитати індекс"
+
+msgid "unable to write temporary index file"
+msgstr "не вдалося записати тимчасовий файл індексу"
+
+#, c-format
+msgid "commit '%s' lacks author header"
+msgstr ""
+
+#, c-format
+msgid "commit '%s' has malformed author line"
+msgstr ""
+
+msgid "malformed --author parameter"
+msgstr ""
+
+#, c-format
+msgid "invalid date format: %s"
+msgstr "неприпустимий формат дати: %s"
+
+msgid ""
+"unable to select a comment character that is not used\n"
+"in the current commit message"
+msgstr ""
+
+#, c-format
+msgid "could not lookup commit %s"
+msgstr "не вдалося знайти коміт %s"
+
+#, c-format
+msgid "(reading log message from standard input)\n"
+msgstr ""
+
+msgid "could not read log from standard input"
+msgstr ""
+
+#, c-format
+msgid "could not read log file '%s'"
+msgstr "не вдалося прочитати лог файл \"%s\""
+
+#, c-format
+msgid "options '%s' and '%s:%s' cannot be used together"
+msgstr "опції \"%s\" та \"%s:%s\" не можна використовувати разом"
+
+msgid "could not read SQUASH_MSG"
+msgstr ""
+
+msgid "could not read MERGE_MSG"
+msgstr ""
+
+#, c-format
+msgid "could not open '%s'"
+msgstr "не вдалося відкрити \"%s\""
+
+msgid "could not write commit template"
+msgstr "не вдалося записати шаблон комітів"
+
+#, c-format
+msgid ""
+"Please enter the commit message for your changes. Lines starting\n"
+"with '%c' will be ignored.\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"Please enter the commit message for your changes. Lines starting\n"
+"with '%c' will be ignored, and an empty message aborts the commit.\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"Please enter the commit message for your changes. Lines starting\n"
+"with '%c' will be kept; you may remove them yourself if you want to.\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"Please enter the commit message for your changes. Lines starting\n"
+"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"An empty message aborts the commit.\n"
+msgstr ""
+
+msgid ""
+"\n"
+"It looks like you may be committing a merge.\n"
+"If this is not correct, please run\n"
+"\tgit update-ref -d MERGE_HEAD\n"
+"and try again.\n"
+msgstr ""
+
+msgid ""
+"\n"
+"It looks like you may be committing a cherry-pick.\n"
+"If this is not correct, please run\n"
+"\tgit update-ref -d CHERRY_PICK_HEAD\n"
+"and try again.\n"
+msgstr ""
+
+#, c-format
+msgid "%sAuthor:    %.*s <%.*s>"
+msgstr ""
+
+#, c-format
+msgid "%sDate:      %s"
+msgstr ""
+
+#, c-format
+msgid "%sCommitter: %.*s <%.*s>"
+msgstr ""
+
+msgid "Cannot read index"
+msgstr "Неможливо прочитати індекс"
+
+msgid "unable to pass trailers to --trailers"
+msgstr "не вдалося передати trailers до --trailers"
+
+msgid "Error building trees"
+msgstr ""
+
+#, c-format
+msgid "Please supply the message using either -m or -F option.\n"
+msgstr ""
+
+#, c-format
+msgid "--author '%s' is not 'Name <email>' and matches no existing author"
+msgstr ""
+
+#, c-format
+msgid "Invalid ignored mode '%s'"
+msgstr "Неприпустимий режим ігнорування \"%s\""
+
+#, c-format
+msgid "Invalid untracked files mode '%s'"
+msgstr "Неприпустимий режим невідстежуваних файлів \"%s\""
+
+msgid "You are in the middle of a merge -- cannot reword."
+msgstr "Ви перебуваєте в процесі злиття -- неможливо переформулювати."
+
+msgid "You are in the middle of a cherry-pick -- cannot reword."
+msgstr ""
+"Ви перебуваєте в середині процесу висмикування -- неможливо переформулювати."
+
+#, c-format
+msgid "reword option of '%s' and path '%s' cannot be used together"
+msgstr ""
+"параметр переформулювання \"%s\" і шлях \"%s\" не можна використовувати разом"
+
+#, c-format
+msgid "reword option of '%s' and '%s' cannot be used together"
+msgstr "опція переформулювання \"%s\" і \"%s\" не може бути використана разом"
+
+msgid "You have nothing to amend."
+msgstr ""
+
+msgid "You are in the middle of a merge -- cannot amend."
+msgstr "Ви перебуваєте в процесі злиття -- не можна вносити зміни."
+
+msgid "You are in the middle of a cherry-pick -- cannot amend."
+msgstr "Ви перебуваєте в процесі висмикування - не можна вносити зміни."
+
+msgid "You are in the middle of a rebase -- cannot amend."
+msgstr "Ви перебуваєте в процесі перебазуавння -- не можна вносити зміни."
+
+msgid "--reset-author can be used only with -C, -c or --amend."
+msgstr ""
+
+#, c-format
+msgid "unknown option: --fixup=%s:%s"
+msgstr ""
+
+#, c-format
+msgid "paths '%s ...' with -a does not make sense"
+msgstr "шляхи \"%s ...\" з -a не мають сенсу"
+
+msgid "show status concisely"
+msgstr ""
+
+msgid "show branch information"
+msgstr "показати інформацію про гілку"
+
+msgid "show stash information"
+msgstr ""
+
+msgid "compute full ahead/behind values"
+msgstr ""
+
+msgid "version"
+msgstr "версія"
+
+msgid "machine-readable output"
+msgstr "машинозчитуваний вивід"
+
+msgid "show status in long format (default)"
+msgstr ""
+
+msgid "terminate entries with NUL"
+msgstr ""
+
+msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
+msgstr ""
+
+msgid ""
+"show ignored files, optional modes: traditional, matching, no. (Default: "
+"traditional)"
+msgstr ""
+
+msgid "when"
+msgstr ""
+
+msgid ""
+"ignore changes to submodules, optional when: all, dirty, untracked. "
+"(Default: all)"
+msgstr ""
+
+msgid "list untracked files in columns"
+msgstr "показати невідстежувані файли в стовпчиках"
+
+msgid "do not detect renames"
+msgstr ""
+
+msgid "detect renames, optionally set similarity index"
+msgstr ""
+
+msgid "Unsupported combination of ignored and untracked-files arguments"
+msgstr ""
+
+msgid "suppress summary after successful commit"
+msgstr ""
+
+msgid "show diff in commit message template"
+msgstr ""
+
+msgid "Commit message options"
+msgstr ""
+
+msgid "read message from file"
+msgstr ""
+
+msgid "author"
+msgstr ""
+
+msgid "override author for commit"
+msgstr ""
+
+msgid "date"
+msgstr ""
+
+msgid "override date for commit"
+msgstr ""
+
+msgid "commit"
+msgstr "коміт"
+
+msgid "reuse and edit message from specified commit"
+msgstr ""
+
+msgid "reuse message from specified commit"
+msgstr ""
+
+#. TRANSLATORS: Leave "[(amend|reword):]" as-is,
+#. and only translate <commit>.
+#.
+
+msgid "[(amend|reword):]commit"
+msgstr ""
+
+msgid ""
+"use autosquash formatted message to fixup or amend/reword specified commit"
+msgstr ""
+
+msgid "use autosquash formatted message to squash specified commit"
+msgstr ""
+
+msgid "the commit is authored by me now (used with -C/-c/--amend)"
+msgstr ""
+
+msgid "trailer"
+msgstr ""
+
+msgid "add custom trailer(s)"
+msgstr ""
+
+msgid "add a Signed-off-by trailer"
+msgstr ""
+
+msgid "use specified template file"
+msgstr ""
+
+msgid "force edit of commit"
+msgstr "редагувати коміт примусово"
+
+msgid "include status in commit message template"
+msgstr ""
+
+msgid "Commit contents options"
+msgstr ""
+
+msgid "commit all changed files"
+msgstr ""
+
+msgid "add specified files to index for commit"
+msgstr ""
+
+msgid "interactively add files"
+msgstr "додавати файли інтерактивно"
+
+msgid "interactively add changes"
+msgstr ""
+
+msgid "commit only specified files"
+msgstr ""
+
+msgid "bypass pre-commit and commit-msg hooks"
+msgstr ""
+
+msgid "show what would be committed"
+msgstr "показати, що буде додано до коміту"
+
+msgid "amend previous commit"
+msgstr ""
+
+msgid "bypass post-rewrite hook"
+msgstr "обійти post-rewrite гачок"
+
+msgid "ok to record an empty change"
+msgstr ""
+
+msgid "ok to record a change with an empty message"
+msgstr ""
+
+msgid "could not parse HEAD commit"
+msgstr "не вдалося розібрати HEAD коміт"
+
+#, c-format
+msgid "Corrupt MERGE_HEAD file (%s)"
+msgstr ""
+
+msgid "could not read MERGE_MODE"
+msgstr ""
+
+#, c-format
+msgid "could not read commit message: %s"
+msgstr "не вдалося прочитати допис до коміта: %s"
+
+#, c-format
+msgid "Aborting commit due to empty commit message.\n"
+msgstr ""
+
+#, c-format
+msgid "Aborting commit; you did not edit the message.\n"
+msgstr ""
+
+#, c-format
+msgid "Aborting commit due to empty commit message body.\n"
+msgstr ""
+
+msgid ""
+"repository has been updated, but unable to write\n"
+"new_index file. Check that disk is not full and quota is\n"
+"not exceeded, and then \"git restore --staged :/\" to recover."
+msgstr ""
+
+msgid "git config [<options>]"
+msgstr "git config [<опції>]"
+
+#, c-format
+msgid "unrecognized --type argument, %s"
+msgstr ""
+
+msgid "only one type at a time"
+msgstr ""
+
+msgid "Config file location"
+msgstr ""
+
+msgid "use global config file"
+msgstr ""
+
+msgid "use system config file"
+msgstr ""
+
+msgid "use repository config file"
+msgstr "використовувати конфігураційний файл сховища"
+
+msgid "use per-worktree config file"
+msgstr "використовувати конфігураційний файл робочого дерева"
+
+msgid "use given config file"
+msgstr ""
+
+msgid "blob-id"
+msgstr ""
+
+msgid "read config from given blob object"
+msgstr ""
+
+msgid "Action"
+msgstr ""
+
+msgid "get value: name [value-pattern]"
+msgstr ""
+
+msgid "get all values: key [value-pattern]"
+msgstr ""
+
+msgid "get values for regexp: name-regex [value-pattern]"
+msgstr ""
+
+msgid "get value specific for the URL: section[.var] URL"
+msgstr ""
+
+msgid "replace all matching variables: name value [value-pattern]"
+msgstr ""
+
+msgid "add a new variable: name value"
+msgstr ""
+
+msgid "remove a variable: name [value-pattern]"
+msgstr ""
+
+msgid "remove all matches: name [value-pattern]"
+msgstr ""
+
+msgid "rename section: old-name new-name"
+msgstr ""
+
+msgid "remove a section: name"
+msgstr ""
+
+msgid "list all"
+msgstr ""
+
+msgid "use string equality when comparing values to 'value-pattern'"
+msgstr ""
+
+msgid "open an editor"
+msgstr ""
+
+msgid "find the color configured: slot [default]"
+msgstr ""
+
+msgid "find the color setting: slot [stdout-is-tty]"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "type"
+msgstr ""
+
+msgid "value is given this type"
+msgstr ""
+
+msgid "value is \"true\" or \"false\""
+msgstr ""
+
+msgid "value is decimal number"
+msgstr ""
+
+msgid "value is --bool or --int"
+msgstr ""
+
+msgid "value is --bool or string"
+msgstr ""
+
+msgid "value is a path (file or directory name)"
+msgstr ""
+
+msgid "value is an expiry date"
+msgstr ""
+
+msgid "Other"
+msgstr ""
+
+msgid "terminate values with NUL byte"
+msgstr ""
+
+msgid "show variable names only"
+msgstr ""
+
+msgid "respect include directives on lookup"
+msgstr ""
+
+msgid "show origin of config (file, standard input, blob, command line)"
+msgstr ""
+
+msgid "show scope of config (worktree, local, global, system, command)"
+msgstr ""
+
+msgid "value"
+msgstr "значення"
+
+msgid "with --get, use default value when missing entry"
+msgstr ""
+
+#, c-format
+msgid "wrong number of arguments, should be %d"
+msgstr ""
+
+#, c-format
+msgid "wrong number of arguments, should be from %d to %d"
+msgstr ""
+
+#, c-format
+msgid "invalid key pattern: %s"
+msgstr "неприпустимий шаблон ключа: %s"
+
+#, c-format
+msgid "invalid pattern: %s"
+msgstr "неприпустимий шаблон: %s"
+
+#, c-format
+msgid "failed to format default config value: %s"
+msgstr "не вдалося відформатувати початкове значення конфігурації: %s"
+
+#, c-format
+msgid "cannot parse color '%s'"
+msgstr "не вдалося розібрати колір \"%s\""
+
+msgid "unable to parse default color value"
+msgstr "не вдалося розібрати початкове значення кольору"
+
+msgid "not in a git directory"
+msgstr "не в директорії git"
+
+msgid "writing to stdin is not supported"
+msgstr ""
+
+msgid "writing config blobs is not supported"
+msgstr ""
+
+#, c-format
+msgid ""
+"# This is Git's per-user configuration file.\n"
+"[user]\n"
+"# Please adapt and uncomment the following lines:\n"
+"#\tname = %s\n"
+"#\temail = %s\n"
+msgstr ""
+
+msgid "only one config file at a time"
+msgstr ""
+
+msgid "--local can only be used inside a git repository"
+msgstr "--local можна використовувати лише всередині git сховища"
+
+msgid "--blob can only be used inside a git repository"
+msgstr "--blob можна використовувати лише всередині git сховища"
+
+msgid "--worktree can only be used inside a git repository"
+msgstr "--worktree можна використовувати лише всередині git сховища"
+
+msgid "$HOME not set"
+msgstr ""
+
+msgid ""
+"--worktree cannot be used with multiple working trees unless the config\n"
+"extension worktreeConfig is enabled. Please read \"CONFIGURATION FILE\"\n"
+"section in \"git help worktree\" for details"
+msgstr ""
+
+msgid "--get-color and variable type are incoherent"
+msgstr ""
+
+msgid "only one action at a time"
+msgstr ""
+
+msgid "--name-only is only applicable to --list or --get-regexp"
+msgstr ""
+
+msgid ""
+"--show-origin is only applicable to --get, --get-all, --get-regexp, and --"
+"list"
+msgstr ""
+
+msgid "--default is only applicable to --get"
+msgstr ""
+
+msgid "--fixed-value only applies with 'value-pattern'"
+msgstr ""
+
+#, c-format
+msgid "unable to read config file '%s'"
+msgstr "не вдалося прочитати файл конфігурації \"%s\""
+
+msgid "error processing config file(s)"
+msgstr "помилка при обробці файлу(ів) конфігурації"
+
+msgid "editing stdin is not supported"
+msgstr ""
+
+msgid "editing blobs is not supported"
+msgstr ""
+
+#, c-format
+msgid "cannot create configuration file %s"
+msgstr "неможливо створити конфігураційний файл %s"
+
+#, c-format
+msgid ""
+"cannot overwrite multiple values with a single value\n"
+"       Use a regexp, --add or --replace-all to change %s."
+msgstr ""
+
+#, c-format
+msgid "no such section: %s"
+msgstr "немає такого розділу: %s"
+
+msgid "print sizes in human readable format"
+msgstr ""
+
+#, c-format
+msgid ""
+"The permissions on your socket directory are too loose; other\n"
+"users may be able to read your cached credentials. Consider running:\n"
+"\n"
+"\tchmod 0700 %s"
+msgstr ""
+
+msgid "print debugging messages to stderr"
+msgstr ""
+
+msgid "credential-cache--daemon unavailable; no unix socket support"
+msgstr ""
+
+msgid "credential-cache unavailable; no unix socket support"
+msgstr ""
+
+#, c-format
+msgid "unable to get credential storage lock in %d ms"
+msgstr ""
+
+msgid ""
+"git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]"
+msgstr ""
+
+msgid ""
+"git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]"
+msgstr ""
+
+msgid "git describe <blob>"
+msgstr ""
+
+msgid "head"
+msgstr "head"
+
+msgid "lightweight"
+msgstr ""
+
+msgid "annotated"
+msgstr ""
+
+#, c-format
+msgid "annotated tag %s not available"
+msgstr ""
+
+#, c-format
+msgid "tag '%s' is externally known as '%s'"
+msgstr ""
+
+#, c-format
+msgid "no tag exactly matches '%s'"
+msgstr ""
+
+#, c-format
+msgid "No exact match on refs or tags, searching to describe\n"
+msgstr ""
+
+#, c-format
+msgid "finished search at %s\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"No annotated tags can describe '%s'.\n"
+"However, there were unannotated tags: try --tags."
+msgstr ""
+
+#, c-format
+msgid ""
+"No tags can describe '%s'.\n"
+"Try --always, or create some tags."
+msgstr ""
+
+#, c-format
+msgid "traversed %lu commits\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"more than %i tags found; listed %i most recent\n"
+"gave up search at %s\n"
+msgstr ""
+
+#, c-format
+msgid "describe %s\n"
+msgstr ""
+
+#, c-format
+msgid "Not a valid object name %s"
+msgstr "Неприпустиме ім’я об’єкта %s"
+
+#, c-format
+msgid "%s is neither a commit nor blob"
+msgstr ""
+
+msgid "find the tag that comes after the commit"
+msgstr ""
+
+msgid "debug search strategy on stderr"
+msgstr ""
+
+msgid "use any ref"
+msgstr "використати будь-яке посилання"
+
+msgid "use any tag, even unannotated"
+msgstr ""
+
+msgid "always use long format"
+msgstr ""
+
+msgid "only follow first parent"
+msgstr ""
+
+msgid "only output exact matches"
+msgstr ""
+
+msgid "consider <n> most recent tags (default: 10)"
+msgstr ""
+
+msgid "only consider tags matching <pattern>"
+msgstr ""
+
+msgid "do not consider tags matching <pattern>"
+msgstr ""
+
+msgid "show abbreviated commit object as fallback"
+msgstr ""
+
+msgid "mark"
+msgstr ""
+
+msgid "append <mark> on dirty working tree (default: \"-dirty\")"
+msgstr ""
+"додати <mark> на брудному робочому дереві (за замовчуванням: \\”-dirty\\”)"
+
+msgid "append <mark> on broken working tree (default: \"-broken\")"
+msgstr ""
+
+msgid "No names found, cannot describe anything."
+msgstr ""
+
+#, c-format
+msgid "option '%s' and commit-ishes cannot be used together"
+msgstr "опцію \"%s\" не можна використовувати разом з комітоподібними"
+
+msgid ""
+"git diagnose [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"             [--mode=<mode>]"
+msgstr ""
+
+msgid "specify a destination for the diagnostics archive"
+msgstr ""
+
+msgid "specify a strftime format suffix for the filename"
+msgstr ""
+
+msgid "specify the content of the diagnostic archive"
+msgstr ""
+
+msgid "--merge-base only works with two commits"
+msgstr ""
+
+#, c-format
+msgid "'%s': not a regular file or symlink"
+msgstr ""
+
+msgid "no merge given, only parents."
+msgstr ""
+
+#, c-format
+msgid "invalid option: %s"
+msgstr "неприпустима опція %s"
+
+#, c-format
+msgid "%s...%s: no merge base"
+msgstr ""
+
+msgid "Not a git repository"
+msgstr "Не є git сховищем"
+
+#, c-format
+msgid "invalid object '%s' given."
+msgstr "надано неприпустимий об’єкт \"%s\"."
+
+#, c-format
+msgid "more than two blobs given: '%s'"
+msgstr ""
+
+#, c-format
+msgid "unhandled object '%s' given."
+msgstr "надано необроблений об’єкт \"%s\"."
+
+#, c-format
+msgid "%s...%s: multiple merge bases, using %s"
+msgstr ""
+
+msgid "git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"
+msgstr ""
+
+#, c-format
+msgid "could not read symlink %s"
+msgstr "не вдалося прочитати символьне посилання %s"
+
+#, c-format
+msgid "could not read symlink file %s"
+msgstr "не вдалося прочитати файл символьного посилання %s"
+
+#, c-format
+msgid "could not read object %s for symlink %s"
+msgstr "не вдалося прочитати об’єкт %s для символьного посилання %s"
+
+msgid ""
+"combined diff formats ('-c' and '--cc') are not supported in\n"
+"directory diff mode ('-d' and '--dir-diff')."
+msgstr ""
+
+#, c-format
+msgid "both files modified: '%s' and '%s'."
+msgstr ""
+
+msgid "working tree file has been left."
+msgstr "залишено файл робочого дерева."
+
+#, c-format
+msgid "could not copy '%s' to '%s'"
+msgstr "не вдалося скопіювати \"%s\" в \"%s\""
+
+#, c-format
+msgid "temporary files exist in '%s'."
+msgstr ""
+
+msgid "you may want to cleanup or recover these."
+msgstr ""
+
+#, c-format
+msgid "failed: %d"
+msgstr ""
+
+msgid "use `diff.guitool` instead of `diff.tool`"
+msgstr ""
+
+msgid "perform a full-directory diff"
+msgstr ""
+
+msgid "do not prompt before launching a diff tool"
+msgstr ""
+
+msgid "use symlinks in dir-diff mode"
+msgstr ""
+
+msgid "tool"
+msgstr ""
+
+msgid "use the specified diff tool"
+msgstr ""
+
+msgid "print a list of diff tools that may be used with `--tool`"
+msgstr ""
+
+msgid ""
+"make 'git-difftool' exit when an invoked diff tool returns a non-zero exit "
+"code"
+msgstr ""
+
+msgid "specify a custom command for viewing diffs"
+msgstr ""
+
+msgid "passed to `diff`"
+msgstr ""
+
+msgid "difftool requires worktree or --no-index"
+msgstr ""
+
+msgid "no <tool> given for --tool=<tool>"
+msgstr ""
+
+msgid "no <cmd> given for --extcmd=<cmd>"
+msgstr ""
+
+msgid "git fast-export [<rev-list-opts>]"
+msgstr ""
+
+msgid "Error: Cannot export nested tags unless --mark-tags is specified."
+msgstr ""
+
+msgid "--anonymize-map token cannot be empty"
+msgstr ""
+
+msgid "show progress after <n> objects"
+msgstr ""
+
+msgid "select handling of signed tags"
+msgstr ""
+
+msgid "select handling of tags that tag filtered objects"
+msgstr ""
+
+msgid "select handling of commit messages in an alternate encoding"
+msgstr ""
+
+msgid "dump marks to this file"
+msgstr ""
+
+msgid "import marks from this file"
+msgstr ""
+
+msgid "import marks from this file if it exists"
+msgstr ""
+
+msgid "fake a tagger when tags lack one"
+msgstr ""
+
+msgid "output full tree for each commit"
+msgstr ""
+
+msgid "use the done feature to terminate the stream"
+msgstr ""
+
+msgid "skip output of blob data"
+msgstr ""
+
+msgid "refspec"
+msgstr ""
+
+msgid "apply refspec to exported refs"
+msgstr ""
+
+msgid "anonymize output"
+msgstr ""
+
+msgid "from:to"
+msgstr ""
+
+msgid "convert <from> to <to> in anonymized output"
+msgstr ""
+
+msgid "reference parents which are not in fast-export stream by object id"
+msgstr ""
+
+msgid "show original object ids of blobs/commits"
+msgstr ""
+
+msgid "label tags with mark ids"
+msgstr ""
+
+#, c-format
+msgid "Missing from marks for submodule '%s'"
+msgstr ""
+
+#, c-format
+msgid "Missing to marks for submodule '%s'"
+msgstr ""
+
+#, c-format
+msgid "Expected 'mark' command, got %s"
+msgstr ""
+
+#, c-format
+msgid "Expected 'to' command, got %s"
+msgstr ""
+
+msgid "Expected format name:filename for submodule rewrite option"
+msgstr ""
+
+#, c-format
+msgid "feature '%s' forbidden in input without --allow-unsafe-features"
+msgstr ""
+
+#, c-format
+msgid "Lockfile created but not reported: %s"
+msgstr "Файл блокування створено, але не звітовано: %s"
+
+msgid "git fetch [<options>] [<repository> [<refspec>...]]"
+msgstr "git fetch [<опції>] [<сховище> [<визначник посилання>...]]"
+
+msgid "git fetch [<options>] <group>"
+msgstr "git fetch [<опції>] [<група>]"
+
+msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]"
+msgstr "git fetch --multiple [<опції>] [(<сховище> | <група>)...]"
+
+msgid "git fetch --all [<options>]"
+msgstr "git fetch --all [<опції>]"
+
+msgid "fetch.parallel cannot be negative"
+msgstr ""
+
+msgid "couldn't find remote ref HEAD"
+msgstr "не вдалося знайти посилання віддаленого HEAD"
+
+#, c-format
+msgid "From %.*s\n"
+msgstr ""
+
+#, c-format
+msgid "object %s not found"
+msgstr "об’єкт %s не знайдено"
+
+msgid "[up to date]"
+msgstr ""
+
+msgid "[rejected]"
+msgstr ""
+
+msgid "can't fetch into checked-out branch"
+msgstr "неможливо виконати отримання в активну гілку"
+
+msgid "[tag update]"
+msgstr ""
+
+msgid "unable to update local ref"
+msgstr "не вдалося оновити локальне посилання"
+
+msgid "would clobber existing tag"
+msgstr ""
+
+msgid "[new tag]"
+msgstr ""
+
+msgid "[new branch]"
+msgstr "[нова гілка]"
+
+msgid "[new ref]"
+msgstr "[нове посилання]"
+
+msgid "forced update"
+msgstr "примусове оновлення"
+
+msgid "non-fast-forward"
+msgstr ""
+
+#, c-format
+msgid "cannot open '%s'"
+msgstr "неможливо відкрити \"%s\""
+
+msgid ""
+"fetch normally indicates which branches had a forced update,\n"
+"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
+"flag or run 'git config fetch.showForcedUpdates true'"
+msgstr ""
+
+#, c-format
+msgid ""
+"it took %.2f seconds to check forced updates; you can use\n"
+"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
+"false'\n"
+"to avoid this check\n"
+msgstr ""
+
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s не надіслав всі необхідні обʼєкти\n"
+
+#, c-format
+msgid "rejected %s because shallow roots are not allowed to be updated"
+msgstr ""
+
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr ""
+
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr ""
+
+msgid "[deleted]"
+msgstr "[видалено]"
+
+msgid "(none)"
+msgstr ""
+
+#, c-format
+msgid "refusing to fetch into branch '%s' checked out at '%s'"
+msgstr ""
+
+#, c-format
+msgid "option \"%s\" value \"%s\" is not valid for %s"
+msgstr ""
+
+#, c-format
+msgid "option \"%s\" is ignored for %s\n"
+msgstr ""
+
+#, c-format
+msgid "%s is not a valid object"
+msgstr "%s не є припустимим об’єктом"
+
+#, c-format
+msgid "the object %s does not exist"
+msgstr "об’єкт %s не існує"
+
+msgid "multiple branches detected, incompatible with --set-upstream"
+msgstr ""
+
+#, c-format
+msgid ""
+"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
+"any branch."
+msgstr ""
+
+msgid "not setting upstream for a remote remote-tracking branch"
+msgstr ""
+"не встановлено першоджерельне сховище для віддалено відстежуваної гілки"
+
+msgid "not setting upstream for a remote tag"
+msgstr "не встановлено першоджерельне сховище для віддаленого тега"
+
+msgid "unknown branch type"
+msgstr "невідомий тип гілки"
+
+msgid ""
+"no source branch found;\n"
+"you need to specify exactly one branch with the --set-upstream option"
+msgstr ""
+
+#, c-format
+msgid "Fetching %s\n"
+msgstr "Отримання %s\n"
+
+#, c-format
+msgid "could not fetch %s"
+msgstr "не вдалося отримати %s"
+
+#, c-format
+msgid "could not fetch '%s' (exit code: %d)\n"
+msgstr ""
+
+msgid ""
+"no remote repository specified; please specify either a URL or a\n"
+"remote name from which new revisions should be fetched"
+msgstr ""
+
+msgid "you need to specify a tag name"
+msgstr ""
+
+msgid "fetch from all remotes"
+msgstr ""
+
+msgid "set upstream for git pull/fetch"
+msgstr "встановити першоджерельне сховище для git pull/fetch"
+
+msgid "append to .git/FETCH_HEAD instead of overwriting"
+msgstr ""
+
+msgid "use atomic transaction to update references"
+msgstr "використати атомарну транзакцію для оновлення посилань"
+
+msgid "path to upload pack on remote end"
+msgstr "шлях для завантаження пакунка на віддаленій стороні"
+
+msgid "force overwrite of local reference"
+msgstr ""
+
+msgid "fetch from multiple remotes"
+msgstr ""
+
+msgid "fetch all tags and associated objects"
+msgstr ""
+
+msgid "do not fetch all tags (--no-tags)"
+msgstr ""
+
+msgid "number of submodules fetched in parallel"
+msgstr "кількість підмодулів, що завантажуються паралельно"
+
+msgid "modify the refspec to place all refs within refs/prefetch/"
+msgstr ""
+
+msgid "prune remote-tracking branches no longer on remote"
+msgstr ""
+
+msgid "prune local tags no longer on remote and clobber changed tags"
+msgstr ""
+
+msgid "on-demand"
+msgstr ""
+
+msgid "control recursive fetching of submodules"
+msgstr "контролювати рекурсивне отримання підмодулів"
+
+msgid "write fetched references to the FETCH_HEAD file"
+msgstr ""
+
+msgid "keep downloaded pack"
+msgstr ""
+
+msgid "allow updating of HEAD ref"
+msgstr ""
+
+msgid "deepen history of shallow clone"
+msgstr "поглибити історію поверхневого клону"
+
+msgid "deepen history of shallow repository based on time"
+msgstr "поглибити історію поверхневого клону залежно від часу"
+
+msgid "convert to a complete repository"
+msgstr "перетворити на повне сховище"
+
+msgid "re-fetch without negotiating common commits"
+msgstr ""
+
+msgid "prepend this to submodule path output"
+msgstr ""
+
+msgid ""
+"default for recursive fetching of submodules (lower priority than config "
+"files)"
+msgstr ""
+
+msgid "accept refs that update .git/shallow"
+msgstr ""
+
+msgid "refmap"
+msgstr ""
+
+msgid "specify fetch refmap"
+msgstr ""
+
+msgid "report that we have only objects reachable from this object"
+msgstr ""
+
+msgid "do not fetch a packfile; instead, print ancestors of negotiation tips"
+msgstr ""
+
+msgid "run 'maintenance --auto' after fetching"
+msgstr ""
+
+msgid "check for forced-updates on all updated branches"
+msgstr ""
+
+msgid "write the commit-graph after fetching"
+msgstr ""
+
+msgid "accept refspecs from stdin"
+msgstr ""
+
+msgid "--negotiate-only needs one or more --negotiation-tip=*"
+msgstr ""
+
+msgid "negative depth in --deepen is not supported"
+msgstr ""
+
+msgid "--unshallow on a complete repository does not make sense"
+msgstr ""
+
+#, c-format
+msgid "failed to fetch bundles from '%s'"
+msgstr "не вдалося отримати пакунки з \"%s\""
+
+msgid "fetch --all does not take a repository argument"
+msgstr "fetch --all не приймає сховище як аргумент"
+
+msgid "fetch --all does not make sense with refspecs"
+msgstr "fetch --all не має сенсу з визначниками посилань"
+
+#, c-format
+msgid "no such remote or remote group: %s"
+msgstr ""
+
+msgid "fetching a group and specifying refspecs does not make sense"
+msgstr ""
+
+msgid "must supply remote when using --negotiate-only"
+msgstr ""
+
+msgid "protocol does not support --negotiate-only, exiting"
+msgstr ""
+
+msgid ""
+"--filter can only be used with the remote configured in extensions."
+"partialclone"
+msgstr ""
+
+msgid "--atomic can only be used when fetching from one remote"
+msgstr ""
+"--atomic може бути використано лише при отриманні з одного віддаленого "
+"джерела"
+
+msgid "--stdin can only be used when fetching from one remote"
+msgstr ""
+
+msgid ""
+"git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]"
+msgstr ""
+
+msgid "populate log with at most <n> entries from shortlog"
+msgstr ""
+
+msgid "alias for --log (deprecated)"
+msgstr ""
+
+msgid "text"
+msgstr ""
+
+msgid "use <text> as start of message"
+msgstr ""
+
+msgid "use <name> instead of the real target branch"
+msgstr "використовувати <назва> замість реальної цільової гілки"
+
+msgid "file to read from"
+msgstr "файл, з якого читати"
+
+msgid "git for-each-ref [<options>] [<pattern>]"
+msgstr "git for-each-ref [<опції>] [<шаблон>]"
+
+msgid "git for-each-ref [--points-at <object>]"
+msgstr ""
+
+msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
+msgstr ""
+
+msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
+msgstr ""
+
+msgid "quote placeholders suitably for shells"
+msgstr ""
+
+msgid "quote placeholders suitably for perl"
+msgstr ""
+
+msgid "quote placeholders suitably for python"
+msgstr ""
+
+msgid "quote placeholders suitably for Tcl"
+msgstr ""
+
+msgid "show only <n> matched refs"
+msgstr ""
+
+msgid "respect format colors"
+msgstr ""
+
+msgid "print only refs which points at the given object"
+msgstr ""
+
+msgid "print only refs that are merged"
+msgstr ""
+
+msgid "print only refs that are not merged"
+msgstr ""
+
+msgid "print only refs which contain the commit"
+msgstr ""
+
+msgid "print only refs which don't contain the commit"
+msgstr ""
+
+msgid "read reference patterns from stdin"
+msgstr "читати шаблони посилань з stdin"
+
+msgid "unknown arguments supplied with --stdin"
+msgstr ""
+
+msgid "git for-each-repo --config=<config> [--] <arguments>"
+msgstr ""
+
+msgid "config"
+msgstr ""
+
+msgid "config key storing a list of repository paths"
+msgstr ""
+
+msgid "missing --config=<config>"
+msgstr ""
+
+#, c-format
+msgid "got bad config --config=%s"
+msgstr ""
+
+msgid "unknown"
+msgstr "невідомо"
+
+#. TRANSLATORS: e.g. error in tree 01bfda: <more explanation>
+
+#, c-format
+msgid "error in %s %s: %s"
+msgstr ""
+
+#. TRANSLATORS: e.g. warning in tree 01bfda: <more explanation>
+
+#, c-format
+msgid "warning in %s %s: %s"
+msgstr ""
+
+#, c-format
+msgid "broken link from %7s %s"
+msgstr ""
+
+msgid "wrong object type in link"
+msgstr "невірний тип об’єкта в посиланні"
+
+#, c-format
+msgid ""
+"broken link from %7s %s\n"
+"              to %7s %s"
+msgstr ""
+
+msgid "Checking connectivity"
+msgstr "Перевірка підключення"
+
+#, c-format
+msgid "missing %s %s"
+msgstr ""
+
+#, c-format
+msgid "unreachable %s %s"
+msgstr ""
+
+#, c-format
+msgid "dangling %s %s"
+msgstr ""
+
+msgid "could not create lost-found"
+msgstr "не вдалося створити lost-found"
+
+#, c-format
+msgid "could not write '%s'"
+msgstr "не вдалося записати \"%s\""
+
+#, c-format
+msgid "could not finish '%s'"
+msgstr "не вдалося завершити \"%s\""
+
+#, c-format
+msgid "Checking %s"
+msgstr "Перевірка %s"
+
+#, c-format
+msgid "Checking connectivity (%d objects)"
+msgstr "Перевірка підключення (%d обʼєктів)"
+
+#, c-format
+msgid "Checking %s %s"
+msgstr "Перевірка %s %s"
+
+msgid "broken links"
+msgstr ""
+
+#, c-format
+msgid "root %s"
+msgstr ""
+
+#, c-format
+msgid "tagged %s %s (%s) in %s"
+msgstr ""
+
+#, c-format
+msgid "%s: object corrupt or missing"
+msgstr ""
+
+#, c-format
+msgid "%s: invalid reflog entry %s"
+msgstr "%s: неприпустимий запис reflog %s"
+
+#, c-format
+msgid "Checking reflog %s->%s"
+msgstr ""
+
+#, c-format
+msgid "%s: invalid sha1 pointer %s"
+msgstr "%s: невірний вказівник sha1 %s"
+
+#, c-format
+msgid "%s: not a commit"
+msgstr "%s не є комітом"
+
+msgid "notice: No default references"
+msgstr ""
+
+#, c-format
+msgid "%s: hash-path mismatch, found at: %s"
+msgstr ""
+
+#, c-format
+msgid "%s: object corrupt or missing: %s"
+msgstr ""
+
+#, c-format
+msgid "%s: object is of unknown type '%s': %s"
+msgstr ""
+
+#, c-format
+msgid "%s: object could not be parsed: %s"
+msgstr ""
+
+#, c-format
+msgid "bad sha1 file: %s"
+msgstr ""
+
+msgid "Checking object directory"
+msgstr "Перевірка директорії об’єкта"
+
+msgid "Checking object directories"
+msgstr "Перевірка директорій обʼєкта"
+
+#, c-format
+msgid "Checking %s link"
+msgstr "Перевірка %s посилання"
+
+#, c-format
+msgid "invalid %s"
+msgstr "неприпустимий %s"
+
+#, c-format
+msgid "%s points to something strange (%s)"
+msgstr ""
+
+#, c-format
+msgid "%s: detached HEAD points at nothing"
+msgstr ""
+
+#, c-format
+msgid "notice: %s points to an unborn branch (%s)"
+msgstr ""
+
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "Перевірка дерева кеша для \"%s\""
+
+#, c-format
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s: невірний sha1 вказівник в cache-tree для %s"
+
+msgid "non-tree in cache-tree"
+msgstr ""
+
+#, c-format
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s: невірний sha1 вказівник в resolve-undo для %s"
+
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "не вдалося завантажити rev-index для пакуна \"%s\""
+
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "невірний rev-index для пакуна \"%s\""
+
+msgid ""
+"git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
+"         [--[no-]full] [--strict] [--verbose] [--lost-found]\n"
+"         [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n"
+"         [--[no-]name-objects] [<object>...]"
+msgstr ""
+
+msgid "show unreachable objects"
+msgstr ""
+
+msgid "show dangling objects"
+msgstr "показувати висячі об’єкти"
+
+msgid "report tags"
+msgstr ""
+
+msgid "report root nodes"
+msgstr ""
+
+msgid "make index objects head nodes"
+msgstr ""
+
+msgid "make reflogs head nodes (default)"
+msgstr "зробити reflogs головними вузлами (за замовчуванням)"
+
+msgid "also consider packs and alternate objects"
+msgstr ""
+
+msgid "check only connectivity"
+msgstr ""
+
+msgid "enable more strict checking"
+msgstr ""
+
+msgid "write dangling objects in .git/lost-found"
+msgstr ""
+
+msgid "show progress"
+msgstr ""
+
+msgid "show verbose names for reachable objects"
+msgstr ""
+
+msgid "Checking objects"
+msgstr "Перевірка обʼєктів"
+
+#, c-format
+msgid "%s: object missing"
+msgstr ""
+
+#, c-format
+msgid "invalid parameter: expected sha1, got '%s'"
+msgstr "неприпустимий параметр: очікувався sha1, надано \"%s\""
+
+msgid "git fsmonitor--daemon start [<options>]"
+msgstr ""
+
+msgid "git fsmonitor--daemon run [<options>]"
+msgstr ""
+
+#, c-format
+msgid "value of '%s' out of range: %d"
+msgstr ""
+
+#, c-format
+msgid "value of '%s' not bool or int: %d"
+msgstr ""
+
+#, c-format
+msgid "fsmonitor-daemon is watching '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "fsmonitor-daemon is not watching '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "could not create fsmonitor cookie '%s'"
+msgstr "не вдалося створити fsmonitor cookie \"%s\""
+
+#, c-format
+msgid "fsmonitor: cookie_result '%d' != SEEN"
+msgstr ""
+
+#, c-format
+msgid "could not start IPC thread pool on '%s'"
+msgstr "не вдалося запустити пул потоків IPC на \"%s\""
+
+msgid "could not start fsmonitor listener thread"
+msgstr ""
+
+msgid "could not start fsmonitor health thread"
+msgstr ""
+
+msgid "could not initialize listener thread"
+msgstr ""
+
+msgid "could not initialize health thread"
+msgstr ""
+
+#, c-format
+msgid "could not cd home '%s'"
+msgstr "не вдалося виконати cd home \"%s\""
+
+#, c-format
+msgid "fsmonitor--daemon is already running '%s'"
+msgstr ""
+
+#, c-format
+msgid "running fsmonitor-daemon in '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "starting fsmonitor-daemon in '%s'\n"
+msgstr ""
+
+msgid "daemon failed to start"
+msgstr "не вдалося запустити демон"
+
+msgid "daemon not online yet"
+msgstr ""
+
+msgid "daemon terminated"
+msgstr ""
+
+msgid "detach from console"
+msgstr "від’єднати від консолі"
+
+msgid "use <n> ipc worker threads"
+msgstr ""
+
+msgid "max seconds to wait for background daemon startup"
+msgstr ""
+
+#, c-format
+msgid "invalid 'ipc-threads' value (%d)"
+msgstr "невірне значення \"ipc-threads\" (%d)"
+
+#, c-format
+msgid "Unhandled subcommand '%s'"
+msgstr ""
+
+msgid "fsmonitor--daemon not supported on this platform"
+msgstr ""
+
+msgid "git gc [<options>]"
+msgstr "git gc [<опції>]"
+
+#, c-format
+msgid "Failed to fstat %s: %s"
+msgstr "Не вдалося виконати fstat %s: %s"
+
+#, c-format
+msgid "failed to parse '%s' value '%s'"
+msgstr "не вдалося розібрати \"%s\" значення \"%s\""
+
+#, c-format
+msgid "cannot stat '%s'"
+msgstr "неможливо виконати stat \"%s\""
+
+#, c-format
+msgid ""
+"The last gc run reported the following. Please correct the root cause\n"
+"and remove %s\n"
+"Automatic cleanup will not be performed until the file is removed.\n"
+"\n"
+"%s"
+msgstr ""
+
+msgid "prune unreferenced objects"
+msgstr "видалити об’єкти без посилань"
+
+msgid "pack unreferenced objects separately"
+msgstr ""
+
+msgid "be more thorough (increased runtime)"
+msgstr ""
+
+msgid "enable auto-gc mode"
+msgstr ""
+
+msgid "force running gc even if there may be another gc running"
+msgstr ""
+
+msgid "repack all other packs except the largest pack"
+msgstr ""
+
+#, c-format
+msgid "failed to parse gc.logExpiry value %s"
+msgstr "не вдалося розібрати gc.logExpiry значення %s"
+
+#, c-format
+msgid "failed to parse prune expiry value %s"
+msgstr ""
+
+#, c-format
+msgid "Auto packing the repository in background for optimum performance.\n"
+msgstr ""
+
+#, c-format
+msgid "Auto packing the repository for optimum performance.\n"
+msgstr ""
+
+#, c-format
+msgid "See \"git help gc\" for manual housekeeping.\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"gc is already running on machine '%s' pid %<PRIuMAX> (use --force if not)"
+msgstr ""
+
+msgid ""
+"There are too many unreachable loose objects; run 'git prune' to remove them."
+msgstr ""
+
+msgid ""
+"git maintenance run [--auto] [--[no-]quiet] [--task=<task>] [--schedule]"
+msgstr ""
+
+msgid "--no-schedule is not allowed"
+msgstr ""
+
+#, c-format
+msgid "unrecognized --schedule argument '%s'"
+msgstr ""
+
+msgid "failed to write commit-graph"
+msgstr "не вдалося записати граф комітів"
+
+msgid "failed to prefetch remotes"
+msgstr "не вдалося виконати попереднє отримання з віддалених сховищ"
+
+msgid "failed to start 'git pack-objects' process"
+msgstr "не вдалося розпочати \"git pack-objects\" процес"
+
+msgid "failed to finish 'git pack-objects' process"
+msgstr ""
+
+msgid "failed to write multi-pack-index"
+msgstr ""
+
+msgid "'git multi-pack-index expire' failed"
+msgstr ""
+
+msgid "'git multi-pack-index repack' failed"
+msgstr ""
+
+msgid ""
+"skipping incremental-repack task because core.multiPackIndex is disabled"
+msgstr ""
+
+#, c-format
+msgid "lock file '%s' exists, skipping maintenance"
+msgstr ""
+
+#, c-format
+msgid "task '%s' failed"
+msgstr ""
+
+#, c-format
+msgid "'%s' is not a valid task"
+msgstr "\"%s\" не є припустимим завданням"
+
+#, c-format
+msgid "task '%s' cannot be selected multiple times"
+msgstr "завдання \"%s\" не можна вибрати кілька разів"
+
+msgid "run tasks based on the state of the repository"
+msgstr ""
+
+msgid "frequency"
+msgstr ""
+
+msgid "run tasks based on frequency"
+msgstr ""
+
+msgid "do not report progress or other information over stderr"
+msgstr ""
+
+msgid "task"
+msgstr ""
+
+msgid "run a specific task"
+msgstr ""
+
+msgid "use at most one of --auto and --schedule=<frequency>"
+msgstr ""
+
+#, c-format
+msgid "unable to add '%s' value of '%s'"
+msgstr "не вдалося додати значення \"%s\" до \"%s\""
+
+msgid "return success even if repository was not registered"
+msgstr ""
+
+#, c-format
+msgid "unable to unset '%s' value of '%s'"
+msgstr "не вдалося скинути значення \"%s\" для \"%s\""
+
+#, c-format
+msgid "repository '%s' is not registered"
+msgstr "сховище \"%s\" не зареєстровано"
+
+#, c-format
+msgid "failed to expand path '%s'"
+msgstr "не вдалося розгорнути шлях \"%s\""
+
+msgid "failed to start launchctl"
+msgstr "не вдалося запустити launchctl"
+
+#, c-format
+msgid "failed to create directories for '%s'"
+msgstr "не вдалося створити директорії для \"%s\""
+
+#, c-format
+msgid "failed to bootstrap service %s"
+msgstr "не вдалося розгорнути службу %s"
+
+msgid "failed to create temp xml file"
+msgstr "не вдалося створити тимчасовий xml файл"
+
+msgid "failed to start schtasks"
+msgstr "не вдалося запустити schtasks"
+
+msgid "failed to run 'crontab -l'; your system might not support 'cron'"
+msgstr ""
+
+msgid "failed to create crontab temporary file"
+msgstr "не вдалося створити тимчасовий crontab файл"
+
+msgid "failed to open temporary file"
+msgstr "не вдалося відкрити тимчасовий файл"
+
+msgid "failed to run 'crontab'; your system might not support 'cron'"
+msgstr ""
+
+msgid "'crontab' died"
+msgstr ""
+
+msgid "failed to start systemctl"
+msgstr "не вдалося стартувати systemctl"
+
+msgid "failed to run systemctl"
+msgstr "не вдалося запустити systemctl"
+
+#, c-format
+msgid "failed to delete '%s'"
+msgstr "не вдалося видалити \"%s\""
+
+#, c-format
+msgid "failed to flush '%s'"
+msgstr "не вдалося очистити \"%s\""
+
+#, c-format
+msgid "unrecognized --scheduler argument '%s'"
+msgstr ""
+
+msgid "neither systemd timers nor crontab are available"
+msgstr ""
+
+#, c-format
+msgid "%s scheduler is not available"
+msgstr ""
+
+msgid "another process is scheduling background maintenance"
+msgstr ""
+
+msgid "git maintenance start [--scheduler=<scheduler>]"
+msgstr ""
+
+msgid "scheduler"
+msgstr ""
+
+msgid "scheduler to trigger git maintenance run"
+msgstr ""
+
+msgid "failed to add repo to global config"
+msgstr ""
+
+msgid "git maintenance <subcommand> [<options>]"
+msgstr ""
+
+msgid "git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"
+msgstr "git grep [<опції>] [-e] <шаблон> [<ревізія>...] [[--] <шлях>...]"
+
+#, c-format
+msgid "grep: failed to create thread: %s"
+msgstr "grep: не вдалося створити потік: %s"
+
+#, c-format
+msgid "invalid number of threads specified (%d) for %s"
+msgstr "невірно вказано кількість потоків (%d) для %s"
+
+#. TRANSLATORS: %s is the configuration
+#. variable for tweaking threads, currently
+#. grep.threads
+#.
+
+#, c-format
+msgid "no threads support, ignoring %s"
+msgstr "немає підтримки потоків, ігноруються %s"
+
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "не вдалося прочитати дерево (%s)"
+
+#, c-format
+msgid "unable to grep from object of type %s"
+msgstr "не вдалося виконати grep з об’єкта типу %s"
+
+#, c-format
+msgid "switch `%c' expects a numerical value"
+msgstr ""
+
+msgid "search in index instead of in the work tree"
+msgstr "шукати в індексі замість робочого дерева"
+
+msgid "find in contents not managed by git"
+msgstr ""
+
+msgid "search in both tracked and untracked files"
+msgstr "шукати як у відстежуваних, так і в невідстежуваних файлах"
+
+msgid "ignore files specified via '.gitignore'"
+msgstr ""
+
+msgid "recursively search in each submodule"
+msgstr "шукати рекурсивно в кожному підмодулі"
+
+msgid "show non-matching lines"
+msgstr ""
+
+msgid "case insensitive matching"
+msgstr ""
+
+msgid "match patterns only at word boundaries"
+msgstr ""
+
+msgid "process binary files as text"
+msgstr ""
+
+msgid "don't match patterns in binary files"
+msgstr ""
+
+msgid "process binary files with textconv filters"
+msgstr ""
+
+msgid "search in subdirectories (default)"
+msgstr ""
+
+msgid "descend at most <depth> levels"
+msgstr ""
+
+msgid "use extended POSIX regular expressions"
+msgstr ""
+
+msgid "use basic POSIX regular expressions (default)"
+msgstr ""
+
+msgid "interpret patterns as fixed strings"
+msgstr ""
+
+msgid "use Perl-compatible regular expressions"
+msgstr ""
+
+msgid "show line numbers"
+msgstr ""
+
+msgid "show column number of first match"
+msgstr ""
+
+msgid "don't show filenames"
+msgstr ""
+
+msgid "show filenames"
+msgstr ""
+
+msgid "show filenames relative to top directory"
+msgstr ""
+
+msgid "show only filenames instead of matching lines"
+msgstr ""
+
+msgid "synonym for --files-with-matches"
+msgstr ""
+
+msgid "show only the names of files without match"
+msgstr ""
+
+msgid "print NUL after filenames"
+msgstr ""
+
+msgid "show only matching parts of a line"
+msgstr ""
+
+msgid "show the number of matches instead of matching lines"
+msgstr ""
+
+msgid "highlight matches"
+msgstr ""
+
+msgid "print empty line between matches from different files"
+msgstr ""
+
+msgid "show filename only once above matches from same file"
+msgstr ""
+
+msgid "show <n> context lines before and after matches"
+msgstr ""
+
+msgid "show <n> context lines before matches"
+msgstr ""
+
+msgid "show <n> context lines after matches"
+msgstr ""
+
+msgid "use <n> worker threads"
+msgstr ""
+
+msgid "shortcut for -C NUM"
+msgstr ""
+
+msgid "show a line with the function name before matches"
+msgstr ""
+
+msgid "show the surrounding function"
+msgstr ""
+
+msgid "read patterns from file"
+msgstr ""
+
+msgid "match <pattern>"
+msgstr ""
+
+msgid "combine patterns specified with -e"
+msgstr ""
+
+msgid "indicate hit with exit status without output"
+msgstr ""
+
+msgid "show only matches from files that match all patterns"
+msgstr ""
+
+msgid "pager"
+msgstr ""
+
+msgid "show matching files in the pager"
+msgstr ""
+
+msgid "allow calling of grep(1) (ignored by this build)"
+msgstr ""
+
+msgid "maximum number of results per file"
+msgstr ""
+
+msgid "no pattern given"
+msgstr ""
+
+msgid "--no-index or --untracked cannot be used with revs"
+msgstr "--no-index або --untracked не можна використовувати з ревізіями"
+
+#, c-format
+msgid "unable to resolve revision: %s"
+msgstr "не вдалося розвʼязати ревізію: %s"
+
+msgid "--untracked not supported with --recurse-submodules"
+msgstr ""
+
+msgid "invalid option combination, ignoring --threads"
+msgstr ""
+
+msgid "no threads support, ignoring --threads"
+msgstr "немає підтримки потоків, ігнорування --threads"
+
+#, c-format
+msgid "invalid number of threads specified (%d)"
+msgstr "вказано неприпустиму кількість потоків (%d)"
+
+msgid "--open-files-in-pager only works on the worktree"
+msgstr ""
+
+msgid "--[no-]exclude-standard cannot be used for tracked contents"
+msgstr ""
+
+msgid "both --cached and trees are given"
+msgstr ""
+
+msgid ""
+"git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n"
+"                [--stdin [--literally]] [--] <file>..."
+msgstr ""
+
+msgid "git hash-object [-t <type>] [-w] --stdin-paths [--no-filters]"
+msgstr ""
+
+msgid "object type"
+msgstr "тип обʼєкта"
+
+msgid "write the object into the object database"
+msgstr ""
+
+msgid "read the object from stdin"
+msgstr ""
+
+msgid "store file as is without filters"
+msgstr ""
+
+msgid ""
+"just hash any random garbage to create corrupt objects for debugging Git"
+msgstr ""
+
+msgid "process file as it were from this path"
+msgstr ""
+
+msgid "print all available commands"
+msgstr ""
+
+msgid "show external commands in --all"
+msgstr ""
+
+msgid "show aliases in --all"
+msgstr ""
+
+msgid "exclude guides"
+msgstr ""
+
+msgid "show man page"
+msgstr ""
+
+msgid "show manual in web browser"
+msgstr ""
+
+msgid "show info page"
+msgstr ""
+
+msgid "print command description"
+msgstr ""
+
+msgid "print list of useful guides"
+msgstr ""
+
+msgid "print list of user-facing repository, command and file interfaces"
+msgstr ""
+
+msgid "print list of file formats, protocols and other developer interfaces"
+msgstr ""
+
+msgid "print all configuration variable names"
+msgstr ""
+
+msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>|<doc>]"
+msgstr ""
+
+#, c-format
+msgid "unrecognized help format '%s'"
+msgstr ""
+
+msgid "Failed to start emacsclient."
+msgstr "Не вдалося запустити emacs клієнт."
+
+msgid "Failed to parse emacsclient version."
+msgstr "Не вдалося розібрати версію emacs клієнта."
+
+#, c-format
+msgid "emacsclient version '%d' too old (< 22)."
+msgstr ""
+
+#, c-format
+msgid "failed to exec '%s'"
+msgstr "не вдалося виконати \"%s\""
+
+#, c-format
+msgid ""
+"'%s': path for unsupported man viewer.\n"
+"Please consider using 'man.<tool>.cmd' instead."
+msgstr ""
+
+#, c-format
+msgid ""
+"'%s': cmd for supported man viewer.\n"
+"Please consider using 'man.<tool>.path' instead."
+msgstr ""
+
+#, c-format
+msgid "'%s': unknown man viewer."
+msgstr ""
+
+msgid "no man viewer handled the request"
+msgstr ""
+
+msgid "no info viewer handled the request"
+msgstr ""
+
+#, c-format
+msgid "'%s' is aliased to '%s'"
+msgstr "\"%s\" є псевдонімом для \"%s\""
+
+#, c-format
+msgid "bad alias.%s string: %s"
+msgstr ""
+
+#, c-format
+msgid "the '%s' option doesn't take any non-option arguments"
+msgstr ""
+
+msgid ""
+"the '--no-[external-commands|aliases]' options can only be used with '--all'"
+msgstr ""
+
+#, c-format
+msgid "usage: %s%s"
+msgstr ""
+
+msgid "'git help config' for more information"
+msgstr ""
+
+msgid ""
+"git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-"
+"args>]"
+msgstr ""
+
+msgid "silently ignore missing requested <hook-name>"
+msgstr ""
+
+msgid "file to read into hooks' stdin"
+msgstr "файл, з якого читати stdin хука"
+
+#, c-format
+msgid "object type mismatch at %s"
+msgstr "не співпадає тип обʼєкта для %s"
+
+#, c-format
+msgid "did not receive expected object %s"
+msgstr "очікуваних обʼєктів не отримано %s"
+
+#, c-format
+msgid "object %s: expected type %s, found %s"
+msgstr "обʼєкт %s: очікувався тип %s, знайдено %s"
+
+#, c-format
+msgid "cannot fill %d byte"
+msgid_plural "cannot fill %d bytes"
+msgstr[0] "не вдається заповнити %d байт"
+msgstr[1] "не вдається заповнити %d байти"
+msgstr[2] "не вдається заповнити %d байтів"
+
+msgid "early EOF"
+msgstr "ранній EOF"
+
+msgid "read error on input"
+msgstr "помилка зчитування на вході"
+
+msgid "used more bytes than were available"
+msgstr "використано більше байтів, ніж було доступно"
+
+msgid "pack too large for current definition of off_t"
+msgstr "пакунок занадто великий для поточного визначення off_t"
+
+#, c-format
+msgid "pack exceeds maximum allowed size (%s)"
+msgstr "пакунок перевищує максимально дозволений розмір (%s)"
+
+msgid "pack signature mismatch"
+msgstr "не співпадає підпис пакунка"
+
+#, c-format
+msgid "pack version %<PRIu32> unsupported"
+msgstr "версія пакунка %<PRIu32> не підтримується"
+
+#, c-format
+msgid "pack has bad object at offset %<PRIuMAX>: %s"
+msgstr "пакунок має невірний обʼєкт зі зміщенням %<PRIuMAX>: %s"
+
+#, c-format
+msgid "inflate returned %d"
+msgstr "розпаковувач повернув %d"
+
+msgid "offset value overflow for delta base object"
+msgstr "переповнення значення зсуву для обʼєкту дельти з базою"
+
+msgid "delta base offset is out of bound"
+msgstr "зсув дельти з базою виходить за межі"
+
+#, c-format
+msgid "unknown object type %d"
+msgstr "невідомий тип обʼєкта %d"
+
+msgid "cannot pread pack file"
+msgstr "неможливо прочитати файл пакунка"
+
+#, c-format
+msgid "premature end of pack file, %<PRIuMAX> byte missing"
+msgid_plural "premature end of pack file, %<PRIuMAX> bytes missing"
+msgstr[0] "передчасний кінець файлу пакунка, %<PRIuMAX> байт відсутній"
+msgstr[1] "передчасний кінець файлу пакунка, %<PRIuMAX> байта відсутні"
+msgstr[2] "передчасний кінець файлу пакунка, %<PRIuMAX> байтів відсутні"
+
+msgid "serious inflate inconsistency"
+msgstr "серйозне неспівпадіння під час розпакування"
+
+#, c-format
+msgid "SHA1 COLLISION FOUND WITH %s !"
+msgstr "ВИЯВЛЕНО SHA1 КОЛІЗІЮ З %s!"
+
+#, c-format
+msgid "unable to read %s"
+msgstr "не вдалося прочитати %s"
+
+#, c-format
+msgid "cannot read existing object info %s"
+msgstr "неможливо прочитати інформацію про існуючий об’єкт %s"
+
+#, c-format
+msgid "cannot read existing object %s"
+msgstr "неможливо прочитати існуючий об’єкт %s"
+
+#, c-format
+msgid "invalid blob object %s"
+msgstr "неприпустимий об’єкт blob %s"
+
+msgid "fsck error in packed object"
+msgstr "помилка fsck у запакованому обʼєкті"
+
+#, c-format
+msgid "Not all child objects of %s are reachable"
+msgstr "Не всі дочірні об’єкти %s доступні"
+
+msgid "failed to apply delta"
+msgstr "не вдалося застосувати дельту"
+
+msgid "Receiving objects"
+msgstr "Отримання об’єктів"
+
+msgid "Indexing objects"
+msgstr "Індексація об’єктів"
+
+msgid "pack is corrupted (SHA1 mismatch)"
+msgstr "пакунок пошкоджено (SHA1 не співпадає)"
+
+msgid "cannot fstat packfile"
+msgstr "неможливо зробити fstat файла пакунка"
+
+msgid "pack has junk at the end"
+msgstr "мотлох наприкінці пакунка"
+
+msgid "confusion beyond insanity in parse_pack_objects()"
+msgstr "плутанина на межі пекельного борошна в parse_pack_objects()"
+
+msgid "Resolving deltas"
+msgstr "Розв’язання дельт"
+
+#, c-format
+msgid "unable to create thread: %s"
+msgstr "не вдалося створити потік: %s"
+
+msgid "confusion beyond insanity"
+msgstr "плутанина на межі пекельного борошна"
+
+#, c-format
+msgid "completed with %d local object"
+msgid_plural "completed with %d local objects"
+msgstr[0] "завершено з %d локальним об’єктом"
+msgstr[1] "завершено з %d локальними об’єктами"
+msgstr[2] "завершено з %d локальними об’єктами"
+
+#, c-format
+msgid "Unexpected tail checksum for %s (disk corruption?)"
+msgstr "Неочікувана контрольна сума наприкінці %s (пошкодження диска?)"
+
+#, c-format
+msgid "pack has %d unresolved delta"
+msgid_plural "pack has %d unresolved deltas"
+msgstr[0] "пакунок має %d невирішену дельту"
+msgstr[1] "пакунок має %d невирішених дельти"
+msgstr[2] "пакунок має %d невирішених дельт"
+
+#, c-format
+msgid "unable to deflate appended object (%d)"
+msgstr "не вдалося запакувати доданий об’єкт (%d)"
+
+#, c-format
+msgid "local object %s is corrupt"
+msgstr "локальний обʼєкт %s пошкоджено"
+
+#, c-format
+msgid "packfile name '%s' does not end with '.%s'"
+msgstr "ім’я файла пакунка '%s' не закінчується на '.%s'"
+
+#, c-format
+msgid "cannot write %s file '%s'"
+msgstr "неможливо записати %s файл '%s'"
+
+#, c-format
+msgid "cannot close written %s file '%s'"
+msgstr "неможливо закрити записаний %s файл '%s'"
+
+#, c-format
+msgid "unable to rename temporary '*.%s' file to '%s'"
+msgstr "не вдається перейменувати тимчасовий файл '*.%s' на '%s'"
+
+msgid "error while closing pack file"
+msgstr "помилка під час закриття файлу пакунка"
+
+#, c-format
+msgid "bad pack.indexVersion=%<PRIu32>"
+msgstr "невірний pack.indexVersion=%<PRIu32>"
+
+#, c-format
+msgid "Cannot open existing pack file '%s'"
+msgstr "Неможливо відкрити існуючий файл пакунка '%s"
+
+#, c-format
+msgid "Cannot open existing pack idx file for '%s'"
+msgstr "Неможливо відкрити існуючий індексний файл пакунка для '%s"
+
+#, c-format
+msgid "non delta: %d object"
+msgid_plural "non delta: %d objects"
+msgstr[0] "не дельта: %d об’єкт"
+msgstr[1] "не дельта: %d об’єкта"
+msgstr[2] "не дельта: %d об’єктів"
+
+#, c-format
+msgid "chain length = %d: %lu object"
+msgid_plural "chain length = %d: %lu objects"
+msgstr[0] "довжина ланцюжка = %d: %lu об’єкт"
+msgstr[1] "довжина ланцюжка = %d: %lu об’єкти"
+msgstr[2] "довжина ланцюжка = %d: %lu об’єктів"
+
+msgid "Cannot come back to cwd"
+msgstr "Неможливо повернутися до поточної робочої директорії"
+
+#, c-format
+msgid "bad %s"
+msgstr "невірний %s"
+
+#, c-format
+msgid "unknown hash algorithm '%s'"
+msgstr "невідомий хеш-алгоритм '%s'"
+
+msgid "--stdin requires a git repository"
+msgstr "--stdin вимагає наявності git сховища"
+
+msgid "--verify with no packfile name given"
+msgstr "--verify без зазначення имені файла пакунка"
+
+msgid "fsck error in pack objects"
+msgstr "помилка fsck в об’єктах пакунка"
+
+#, c-format
+msgid "cannot stat template '%s'"
+msgstr "неможливо виконати stat шаблона \"%s\""
+
+#, c-format
+msgid "cannot opendir '%s'"
+msgstr "неможливо виконати opendir \"%s\""
+
+#, c-format
+msgid "cannot readlink '%s'"
+msgstr "неможливо виконати readlink \"%s\""
+
+#, c-format
+msgid "cannot symlink '%s' '%s'"
+msgstr "неможливо виконати symlink \"%s\" \"%s\""
+
+#, c-format
+msgid "cannot copy '%s' to '%s'"
+msgstr "неможливо скопіювати \"%s\" до \"%s\""
+
+#, c-format
+msgid "ignoring template %s"
+msgstr ""
+
+#, c-format
+msgid "templates not found in %s"
+msgstr "шаблонів не знайдено в %s"
+
+#, c-format
+msgid "not copying templates from '%s': %s"
+msgstr "не копіюються шаблони з \"%s\": %s"
+
+#, c-format
+msgid "invalid initial branch name: '%s'"
+msgstr "неприпустиме початкове ім’я гілки: \"%s\""
+
+#, c-format
+msgid "unable to handle file type %d"
+msgstr "не вдалося обробити тип файлу %d"
+
+#, c-format
+msgid "unable to move %s to %s"
+msgstr "не вдалося перемістити %s на %s"
+
+msgid "attempt to reinitialize repository with different hash"
+msgstr ""
+
+#, c-format
+msgid "%s already exists"
+msgstr "%s вже існує"
+
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr ""
+
+#, c-format
+msgid "Reinitialized existing shared Git repository in %s%s\n"
+msgstr ""
+
+#, c-format
+msgid "Reinitialized existing Git repository in %s%s\n"
+msgstr ""
+
+#, c-format
+msgid "Initialized empty shared Git repository in %s%s\n"
+msgstr ""
+
+#, c-format
+msgid "Initialized empty Git repository in %s%s\n"
+msgstr ""
+
+msgid ""
+"git init [-q | --quiet] [--bare] [--template=<template-directory>]\n"
+"         [--separate-git-dir <git-dir>] [--object-format=<format>]\n"
+"         [-b <branch-name> | --initial-branch=<branch-name>]\n"
+"         [--shared[=<permissions>]] [<directory>]"
+msgstr ""
+
+msgid "permissions"
+msgstr "права доступу"
+
+msgid "specify that the git repository is to be shared amongst several users"
+msgstr ""
+
+msgid "override the name of the initial branch"
+msgstr ""
+
+msgid "hash"
+msgstr ""
+
+msgid "specify the hash algorithm to use"
+msgstr ""
+
+#, c-format
+msgid "cannot mkdir %s"
+msgstr ""
+
+#, c-format
+msgid "cannot chdir to %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"%s (or --work-tree=<directory>) not allowed without specifying %s (or --git-"
+"dir=<directory>)"
+msgstr ""
+
+#, c-format
+msgid "Cannot access work tree '%s'"
+msgstr "Не вдається отримати доступ до робочого дерева \"%s\""
+
+msgid "--separate-git-dir incompatible with bare repository"
+msgstr "--separate-git-dir несумісна з порожнім сховищем"
+
+msgid ""
+"git interpret-trailers [--in-place] [--trim-empty]\n"
+"                       [(--trailer <token>[(=|:)<value>])...]\n"
+"                       [--parse] [<file>...]"
+msgstr ""
+
+msgid "edit files in place"
+msgstr ""
+
+msgid "trim empty trailers"
+msgstr ""
+
+msgid "where to place the new trailer"
+msgstr ""
+
+msgid "action if trailer already exists"
+msgstr "що робити, якщо trailer вже існує"
+
+msgid "action if trailer is missing"
+msgstr ""
+
+msgid "output only the trailers"
+msgstr ""
+
+msgid "do not apply config rules"
+msgstr ""
+
+msgid "join whitespace-continued values"
+msgstr ""
+
+msgid "set parsing options"
+msgstr ""
+
+msgid "do not treat --- specially"
+msgstr ""
+
+msgid "trailer(s) to add"
+msgstr ""
+
+msgid "--trailer with --only-input does not make sense"
+msgstr ""
+
+msgid "no input file given for in-place editing"
+msgstr ""
+
+msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
+msgstr "git log [<опції>] [<діапазон-ревізій>] [[--] <шлях>...]"
+
+msgid "git show [<options>] <object>..."
+msgstr "git show [<опції>] <обʼєкт>..."
+
+#, c-format
+msgid "invalid --decorate option: %s"
+msgstr "неприпустима --decorate опція: %s"
+
+msgid "suppress diff output"
+msgstr ""
+
+msgid "show source"
+msgstr ""
+
+msgid "clear all previously-defined decoration filters"
+msgstr ""
+
+msgid "only decorate refs that match <pattern>"
+msgstr ""
+
+msgid "do not decorate refs that match <pattern>"
+msgstr ""
+
+msgid "decorate options"
+msgstr ""
+
+msgid ""
+"trace the evolution of line range <start>,<end> or function :<funcname> in "
+"<file>"
+msgstr ""
+
+#, c-format
+msgid "unrecognized argument: %s"
+msgstr ""
+
+msgid "-L<range>:<file> cannot be used with pathspec"
+msgstr "-L<діапазон>:<файл> не можна використовувати з визначником шляху"
+
+#, c-format
+msgid "Final output: %d %s\n"
+msgstr ""
+
+msgid "unable to create temporary object directory"
+msgstr "не вдалося створити тимчасову директорію об’єкта"
+
+#, c-format
+msgid "git show %s: bad file"
+msgstr ""
+
+#, c-format
+msgid "could not read object %s"
+msgstr "не вдалося прочитати об’єкт %s"
+
+#, c-format
+msgid "unknown type: %d"
+msgstr "невідомий тип: %d"
+
+#, c-format
+msgid "%s: invalid cover from description mode"
+msgstr ""
+
+msgid "format.headers without value"
+msgstr ""
+
+#, c-format
+msgid "cannot open patch file %s"
+msgstr "не вдається відкрити файл латки %s"
+
+msgid "need exactly one range"
+msgstr ""
+
+msgid "not a range"
+msgstr ""
+
+msgid "cover letter needs email format"
+msgstr ""
+
+msgid "failed to create cover-letter file"
+msgstr "не вдалося створити файл супровідного листа"
+
+#, c-format
+msgid "insane in-reply-to: %s"
+msgstr ""
+
+msgid "git format-patch [<options>] [<since> | <revision-range>]"
+msgstr "git format-patch [<опції>] [<відколи> | <діапазон-ревізій>]"
+
+msgid "two output directories?"
+msgstr ""
+
+#, c-format
+msgid "unknown commit %s"
+msgstr "невідомий коміт %s"
+
+#, c-format
+msgid "failed to resolve '%s' as a valid ref"
+msgstr "не вдалося розпізнати \"%s\" як припустиме посилання"
+
+msgid "could not find exact merge base"
+msgstr "не вдалося знайти точну базу для злиття"
+
+msgid ""
+"failed to get upstream, if you want to record base commit automatically,\n"
+"please use git branch --set-upstream-to to track a remote branch.\n"
+"Or you could specify base commit by --base=<base-commit-id> manually"
+msgstr ""
+
+msgid "failed to find exact merge base"
+msgstr "не вдалося знайти точну базу для злиття"
+
+msgid "base commit should be the ancestor of revision list"
+msgstr ""
+
+msgid "base commit shouldn't be in revision list"
+msgstr ""
+
+msgid "cannot get patch id"
+msgstr "неможливо отримати ідентифікатор латки"
+
+msgid "failed to infer range-diff origin of current series"
+msgstr ""
+
+#, c-format
+msgid "using '%s' as range-diff origin of current series"
+msgstr ""
+
+msgid "use [PATCH n/m] even with a single patch"
+msgstr ""
+
+msgid "use [PATCH] even with multiple patches"
+msgstr ""
+
+msgid "print patches to standard out"
+msgstr ""
+
+msgid "generate a cover letter"
+msgstr ""
+
+msgid "use simple number sequence for output file names"
+msgstr ""
+
+msgid "sfx"
+msgstr ""
+
+msgid "use <sfx> instead of '.patch'"
+msgstr ""
+
+msgid "start numbering patches at <n> instead of 1"
+msgstr ""
+
+msgid "reroll-count"
+msgstr ""
+
+msgid "mark the series as Nth re-roll"
+msgstr ""
+
+msgid "max length of output filename"
+msgstr ""
+
+msgid "use [RFC PATCH] instead of [PATCH]"
+msgstr ""
+
+msgid "cover-from-description-mode"
+msgstr ""
+
+msgid "generate parts of a cover letter based on a branch's description"
+msgstr ""
+
+msgid "use [<prefix>] instead of [PATCH]"
+msgstr ""
+
+msgid "store resulting files in <dir>"
+msgstr ""
+
+msgid "don't strip/add [PATCH]"
+msgstr ""
+
+msgid "don't output binary diffs"
+msgstr ""
+
+msgid "output all-zero hash in From header"
+msgstr ""
+
+msgid "don't include a patch matching a commit upstream"
+msgstr ""
+
+msgid "show patch format instead of default (patch + stat)"
+msgstr ""
+
+msgid "Messaging"
+msgstr ""
+
+msgid "header"
+msgstr "заголовок"
+
+msgid "add email header"
+msgstr ""
+
+msgid "email"
+msgstr ""
+
+msgid "add To: header"
+msgstr ""
+
+msgid "add Cc: header"
+msgstr ""
+
+msgid "ident"
+msgstr ""
+
+msgid "set From address to <ident> (or committer ident if absent)"
+msgstr ""
+
+msgid "message-id"
+msgstr ""
+
+msgid "make first mail a reply to <message-id>"
+msgstr ""
+
+msgid "boundary"
+msgstr ""
+
+msgid "attach the patch"
+msgstr ""
+
+msgid "inline the patch"
+msgstr ""
+
+msgid "enable message threading, styles: shallow, deep"
+msgstr ""
+
+msgid "signature"
+msgstr ""
+
+msgid "add a signature"
+msgstr ""
+
+msgid "base-commit"
+msgstr ""
+
+msgid "add prerequisite tree info to the patch series"
+msgstr ""
+
+msgid "add a signature from a file"
+msgstr ""
+
+msgid "don't print the patch filenames"
+msgstr ""
+
+msgid "show progress while generating patches"
+msgstr ""
+
+msgid "show changes against <rev> in cover letter or single patch"
+msgstr ""
+
+msgid "show changes against <refspec> in cover letter or single patch"
+msgstr ""
+
+msgid "percentage by which creation is weighted"
+msgstr ""
+
+msgid "show in-body From: even if identical to the e-mail header"
+msgstr ""
+
+#, c-format
+msgid "invalid ident line: %s"
+msgstr "неприпустимий рядок ідентифікатора: %s"
+
+msgid "--name-only does not make sense"
+msgstr ""
+
+msgid "--name-status does not make sense"
+msgstr ""
+
+msgid "--check does not make sense"
+msgstr ""
+
+msgid "--remerge-diff does not make sense"
+msgstr ""
+
+#, c-format
+msgid "could not create directory '%s'"
+msgstr "не вдалося створити директорію \"%s\""
+
+msgid "--interdiff requires --cover-letter or single patch"
+msgstr ""
+
+msgid "Interdiff:"
+msgstr ""
+
+#, c-format
+msgid "Interdiff against v%d:"
+msgstr ""
+
+msgid "--range-diff requires --cover-letter or single patch"
+msgstr ""
+
+msgid "Range-diff:"
+msgstr ""
+
+#, c-format
+msgid "Range-diff against v%d:"
+msgstr ""
+
+#, c-format
+msgid "unable to read signature file '%s'"
+msgstr "не вдалося прочитати файл підпису \"%s\""
+
+msgid "Generating patches"
+msgstr "Створення латок"
+
+msgid "failed to create output files"
+msgstr "не вдалося створити вихідні файли"
+
+msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]"
+msgstr ""
+
+#, c-format
+msgid ""
+"Could not find a tracked remote branch, please specify <upstream> manually.\n"
+msgstr ""
+
+#, c-format
+msgid "bad ls-files format: element '%s' does not start with '('"
+msgstr "невірний формат ls-файлів: елемент \"%s\" не починається з \"(\""
+
+#, c-format
+msgid "bad ls-files format: element '%s' does not end in ')'"
+msgstr "невірний формат ls-файлів: елемент \"%s\" не закінчується на \")\""
+
+#, c-format
+msgid "bad ls-files format: %%%.*s"
+msgstr ""
+
+msgid "git ls-files [<options>] [<file>...]"
+msgstr "git ls-files [<опції>] [<файл>...]"
+
+msgid "separate paths with the NUL character"
+msgstr ""
+
+msgid "identify the file status with tags"
+msgstr ""
+
+msgid "use lowercase letters for 'assume unchanged' files"
+msgstr ""
+
+msgid "use lowercase letters for 'fsmonitor clean' files"
+msgstr ""
+
+msgid "show cached files in the output (default)"
+msgstr ""
+
+msgid "show deleted files in the output"
+msgstr ""
+
+msgid "show modified files in the output"
+msgstr ""
+
+msgid "show other files in the output"
+msgstr ""
+
+msgid "show ignored files in the output"
+msgstr ""
+
+msgid "show staged contents' object name in the output"
+msgstr ""
+
+msgid "show files on the filesystem that need to be removed"
+msgstr ""
+
+msgid "show 'other' directories' names only"
+msgstr ""
+
+msgid "show line endings of files"
+msgstr ""
+
+msgid "don't show empty directories"
+msgstr ""
+
+msgid "show unmerged files in the output"
+msgstr ""
+
+msgid "show resolve-undo information"
+msgstr ""
+
+msgid "skip files matching pattern"
+msgstr ""
+
+msgid "read exclude patterns from <file>"
+msgstr ""
+
+msgid "read additional per-directory exclude patterns in <file>"
+msgstr ""
+
+msgid "add the standard git exclusions"
+msgstr ""
+
+msgid "make the output relative to the project top directory"
+msgstr ""
+
+msgid "if any <file> is not in the index, treat this as an error"
+msgstr ""
+
+msgid "tree-ish"
+msgstr ""
+
+msgid "pretend that paths removed since <tree-ish> are still present"
+msgstr ""
+
+msgid "show debugging data"
+msgstr ""
+
+msgid "suppress duplicate entries"
+msgstr ""
+
+msgid "show sparse directories in the presence of a sparse index"
+msgstr ""
+
+msgid ""
+"--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, "
+"--eol"
+msgstr ""
+
+msgid ""
+"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
+"              [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n"
+"              [--symref] [<repository> [<patterns>...]]"
+msgstr ""
+
+msgid "do not print remote URL"
+msgstr ""
+
+msgid "exec"
+msgstr ""
+
+msgid "path of git-upload-pack on the remote host"
+msgstr "шлях до git-upload-pack на віддаленому сервері"
+
+msgid "limit to tags"
+msgstr ""
+
+msgid "limit to heads"
+msgstr ""
+
+msgid "do not show peeled tags"
+msgstr ""
+
+msgid "take url.<base>.insteadOf into account"
+msgstr ""
+
+msgid "exit with exit code 2 if no matching refs are found"
+msgstr ""
+
+msgid "show underlying ref in addition to the object pointed by it"
+msgstr ""
+
+msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
+msgstr "git ls-tree [<опції>] <деревоподібне-джерело> [<шлях>...]"
+
+#, c-format
+msgid "could not get object info about '%s'"
+msgstr "не вдалося отримати інформацію про обʼєкт \"%s\""
+
+#, c-format
+msgid "bad ls-tree format: element '%s' does not start with '('"
+msgstr "невірний формат ls-дерева: елемент \"%s\" не починається з \"(\""
+
+#, c-format
+msgid "bad ls-tree format: element '%s' does not end in ')'"
+msgstr "невірний формат ls-дерева: елемент \"%s\" не закінчується на \")\""
+
+#, c-format
+msgid "bad ls-tree format: %%%.*s"
+msgstr ""
+
+msgid "only show trees"
+msgstr ""
+
+msgid "recurse into subtrees"
+msgstr ""
+
+msgid "show trees when recursing"
+msgstr ""
+
+msgid "terminate entries with NUL byte"
+msgstr ""
+
+msgid "include object size"
+msgstr "включити розмір об’єкта"
+
+msgid "list only filenames"
+msgstr ""
+
+msgid "list only objects"
+msgstr "показати лише обʼєкти"
+
+msgid "use full path names"
+msgstr ""
+
+msgid "list entire tree; not just current directory (implies --full-name)"
+msgstr ""
+
+msgid "--format can't be combined with other format-altering options"
+msgstr "--format не можна комбінувати з іншими опціями зміни формату"
+
+#. TRANSLATORS: keep <> in "<" mail ">" info.
+
+msgid "git mailinfo [<options>] <msg> <patch> < mail >info"
+msgstr ""
+
+msgid "keep subject"
+msgstr ""
+
+msgid "keep non patch brackets in subject"
+msgstr ""
+
+msgid "copy Message-ID to the end of commit message"
+msgstr ""
+
+msgid "re-code metadata to i18n.commitEncoding"
+msgstr ""
+
+msgid "disable charset re-coding of metadata"
+msgstr ""
+
+msgid "encoding"
+msgstr ""
+
+msgid "re-code metadata to this encoding"
+msgstr ""
+
+msgid "use scissors"
+msgstr ""
+
+msgid "<action>"
+msgstr ""
+
+msgid "action when quoted CR is found"
+msgstr ""
+
+msgid "use headers in message's body"
+msgstr ""
+
+msgid "reading patches from stdin/tty..."
+msgstr ""
+
+#, c-format
+msgid "empty mbox: '%s'"
+msgstr ""
+
+msgid "git merge-base [-a | --all] <commit> <commit>..."
+msgstr ""
+
+msgid "git merge-base [-a | --all] --octopus <commit>..."
+msgstr ""
+
+msgid "git merge-base --is-ancestor <commit> <commit>"
+msgstr ""
+
+msgid "git merge-base --independent <commit>..."
+msgstr ""
+
+msgid "git merge-base --fork-point <ref> [<commit>]"
+msgstr ""
+
+msgid "output all common ancestors"
+msgstr ""
+
+msgid "find ancestors for a single n-way merge"
+msgstr ""
+
+msgid "list revs not reachable from others"
+msgstr ""
+
+msgid "is the first one ancestor of the other?"
+msgstr ""
+
+msgid "find where <commit> forked from reflog of <ref>"
+msgstr ""
+
+msgid ""
+"git merge-file [<options>] [-L <name1> [-L <orig> [-L <name2>]]] <file1> "
+"<orig-file> <file2>"
+msgstr ""
+
+msgid "send results to standard output"
+msgstr ""
+
+msgid "use a diff3 based merge"
+msgstr ""
+
+msgid "use a zealous diff3 based merge"
+msgstr ""
+
+msgid "for conflicts, use our version"
+msgstr ""
+
+msgid "for conflicts, use their version"
+msgstr ""
+
+msgid "for conflicts, use a union version"
+msgstr ""
+
+msgid "for conflicts, use this marker size"
+msgstr ""
+
+msgid "do not warn about conflicts"
+msgstr ""
+
+msgid "set labels for file1/orig-file/file2"
+msgstr ""
+
+#, c-format
+msgid "unknown option %s"
+msgstr "невідома опція %s"
+
+#, c-format
+msgid "could not parse object '%s'"
+msgstr "не вдалося розібрати обʼєкт \"%s\""
+
+#, c-format
+msgid "cannot handle more than %d base. Ignoring %s."
+msgid_plural "cannot handle more than %d bases. Ignoring %s."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "not handling anything other than two heads merge."
+msgstr ""
+
+#, c-format
+msgid "could not resolve ref '%s'"
+msgstr "не вдалося розвʼязати посилання \"%s\""
+
+#, c-format
+msgid "Merging %s with %s\n"
+msgstr ""
+
+msgid "not something we can merge"
+msgstr ""
+
+msgid "refusing to merge unrelated histories"
+msgstr ""
+
+msgid "failure to merge"
+msgstr ""
+
+msgid "git merge-tree [--write-tree] [<options>] <branch1> <branch2>"
+msgstr ""
+
+msgid "git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>"
+msgstr ""
+
+msgid "do a real merge instead of a trivial merge"
+msgstr ""
+
+msgid "do a trivial merge only"
+msgstr ""
+
+msgid "also show informational/conflict messages"
+msgstr ""
+
+msgid "list filenames without modes/oids/stages"
+msgstr ""
+
+msgid "allow merging unrelated histories"
+msgstr ""
+
+msgid "perform multiple merges, one per line of input"
+msgstr ""
+
+msgid "specify a merge-base for the merge"
+msgstr "вказати базу для злиття"
+
+msgid "--trivial-merge is incompatible with all other options"
+msgstr ""
+
+msgid "--merge-base is incompatible with --stdin"
+msgstr ""
+
+#, c-format
+msgid "malformed input line: '%s'."
+msgstr "невірно сформований рядок вводу: \"%s\"."
+
+#, c-format
+msgid "merging cannot continue; got unclean result of %d"
+msgstr ""
+
+msgid "git merge [<options>] [<commit>...]"
+msgstr "git merge [<опції>] [<коміт>...]"
+
+msgid "switch `m' requires a value"
+msgstr ""
+
+#, c-format
+msgid "option `%s' requires a value"
+msgstr "опція \"%s\" вимагає значення"
+
+#, c-format
+msgid "Could not find merge strategy '%s'.\n"
+msgstr "Не вдалося знайти стратегію злиття \"%s\".\n"
+
+#, c-format
+msgid "Available strategies are:"
+msgstr ""
+
+#, c-format
+msgid "Available custom strategies are:"
+msgstr ""
+
+msgid "do not show a diffstat at the end of the merge"
+msgstr ""
+
+msgid "show a diffstat at the end of the merge"
+msgstr ""
+
+msgid "(synonym to --stat)"
+msgstr ""
+
+msgid "add (at most <n>) entries from shortlog to merge commit message"
+msgstr ""
+
+msgid "create a single commit instead of doing a merge"
+msgstr ""
+
+msgid "perform a commit if the merge succeeds (default)"
+msgstr ""
+
+msgid "edit message before committing"
+msgstr "редагувати повідомлення перед комітом"
+
+msgid "allow fast-forward (default)"
+msgstr ""
+
+msgid "abort if fast-forward is not possible"
+msgstr ""
+
+msgid "verify that the named commit has a valid GPG signature"
+msgstr ""
+
+msgid "strategy"
+msgstr ""
+
+msgid "merge strategy to use"
+msgstr ""
+
+msgid "option=value"
+msgstr ""
+
+msgid "option for selected merge strategy"
+msgstr ""
+
+msgid "merge commit message (for a non-fast-forward merge)"
+msgstr ""
+
+msgid "use <name> instead of the real target"
+msgstr "використовувати <назва> замість реальної цілі"
+
+msgid "abort the current in-progress merge"
+msgstr "перервати поточне злиття"
+
+msgid "--abort but leave index and working tree alone"
+msgstr "--abort, але зберегти стан індекса і робочого дерева"
+
+msgid "continue the current in-progress merge"
+msgstr "продовжити поточний процес злиття"
+
+msgid "bypass pre-merge-commit and commit-msg hooks"
+msgstr ""
+
+msgid "could not run stash."
+msgstr "не вдалося виконати stash."
+
+msgid "stash failed"
+msgstr ""
+
+#, c-format
+msgid "not a valid object: %s"
+msgstr "не є припустимим обʼєктом: %s"
+
+msgid "read-tree failed"
+msgstr ""
+
+msgid "Already up to date. (nothing to squash)"
+msgstr ""
+
+msgid "Already up to date."
+msgstr ""
+
+#, c-format
+msgid "Squash commit -- not updating HEAD\n"
+msgstr ""
+
+#, c-format
+msgid "No merge message -- not updating HEAD\n"
+msgstr ""
+
+#, c-format
+msgid "'%s' does not point to a commit"
+msgstr "\"%s\" не вказує на коміт"
+
+#, c-format
+msgid "Bad branch.%s.mergeoptions string: %s"
+msgstr ""
+
+msgid "Unable to write index."
+msgstr "Не вдалося записати індекс."
+
+msgid "Not handling anything other than two heads merge."
+msgstr ""
+
+#, c-format
+msgid "unknown strategy option: -X%s"
+msgstr ""
+
+#, c-format
+msgid "unable to write %s"
+msgstr "не вдалося записати %s"
+
+#, c-format
+msgid "Could not read from '%s'"
+msgstr "Не вдалося прочитати з \"%s\""
+
+#, c-format
+msgid "Not committing merge; use 'git commit' to complete the merge.\n"
+msgstr ""
+"Не виконується злиття; використовуйте \"git commit\" для завершення злиття.\n"
+
+msgid ""
+"Please enter a commit message to explain why this merge is necessary,\n"
+"especially if it merges an updated upstream into a topic branch.\n"
+"\n"
+msgstr ""
+
+msgid "An empty message aborts the commit.\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"the commit.\n"
+msgstr ""
+
+msgid "Empty commit message."
+msgstr ""
+
+#, c-format
+msgid "Wonderful.\n"
+msgstr ""
+
+#, c-format
+msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
+msgstr ""
+
+msgid "No current branch."
+msgstr "Немає поточної гілки."
+
+msgid "No remote for the current branch."
+msgstr "Немає віддаленого призначення для поточної гілки."
+
+msgid "No default upstream defined for the current branch."
+msgstr ""
+
+#, c-format
+msgid "No remote-tracking branch for %s from %s"
+msgstr ""
+
+#, c-format
+msgid "Bad value '%s' in environment '%s'"
+msgstr ""
+
+#, c-format
+msgid "could not close '%s'"
+msgstr "не вдалося закрити \"%s\""
+
+#, c-format
+msgid "not something we can merge in %s: %s"
+msgstr ""
+
+msgid "--abort expects no arguments"
+msgstr ""
+
+msgid "There is no merge to abort (MERGE_HEAD missing)."
+msgstr ""
+
+msgid "--quit expects no arguments"
+msgstr ""
+
+msgid "--continue expects no arguments"
+msgstr ""
+
+msgid "There is no merge in progress (MERGE_HEAD missing)."
+msgstr ""
+
+msgid ""
+"You have not concluded your merge (MERGE_HEAD exists).\n"
+"Please, commit your changes before you merge."
+msgstr ""
+
+msgid ""
+"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
+"Please, commit your changes before you merge."
+msgstr ""
+
+msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
+msgstr ""
+
+msgid "No commit specified and merge.defaultToUpstream not set."
+msgstr ""
+
+msgid "Squash commit into empty head not supported yet"
+msgstr ""
+
+msgid "Non-fast-forward commit does not make sense into an empty head"
+msgstr "Не fast-forward коміт не має сенсу з порожнім HEAD"
+
+#, c-format
+msgid "%s - not something we can merge"
+msgstr ""
+
+msgid "Can merge only exactly one commit into empty head"
+msgstr ""
+
+#, c-format
+msgid "Updating %s..%s\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"Your local changes to the following files would be overwritten by merge:\n"
+"  %s"
+msgstr ""
+
+#, c-format
+msgid "Trying really trivial in-index merge...\n"
+msgstr ""
+
+#, c-format
+msgid "Nope.\n"
+msgstr ""
+
+#, c-format
+msgid "Rewinding the tree to pristine...\n"
+msgstr ""
+
+#, c-format
+msgid "Trying merge strategy %s...\n"
+msgstr ""
+
+#, c-format
+msgid "No merge strategy handled the merge.\n"
+msgstr ""
+
+#, c-format
+msgid "Merge with strategy %s failed.\n"
+msgstr ""
+
+#, c-format
+msgid "Using the %s strategy to prepare resolving by hand.\n"
+msgstr ""
+
+#, c-format
+msgid "Automatic merge went well; stopped before committing as requested\n"
+msgstr ""
+
+#, c-format
+msgid "When finished, apply stashed changes with `git stash pop`\n"
+msgstr ""
+
+#, c-format
+msgid "warning: tag input does not pass fsck: %s"
+msgstr ""
+
+#, c-format
+msgid "error: tag input does not pass fsck: %s"
+msgstr ""
+
+#, c-format
+msgid "%d (FSCK_IGNORE?) should never trigger this callback"
+msgstr ""
+
+#, c-format
+msgid "could not read tagged object '%s'"
+msgstr "не вдалося прочитати тегований об’єкт \"%s\""
+
+#, c-format
+msgid "object '%s' tagged as '%s', but is a '%s' type"
+msgstr ""
+
+msgid "could not read from stdin"
+msgstr "не вдалося прочитати з stdin"
+
+msgid "tag on stdin did not pass our strict fsck check"
+msgstr ""
+
+msgid "tag on stdin did not refer to a valid object"
+msgstr ""
+
+msgid "unable to write tag file"
+msgstr "не вдалося записати файл тегів"
+
+msgid "input is NUL terminated"
+msgstr ""
+
+msgid "allow missing objects"
+msgstr "дозволити відсутні об’єкти"
+
+msgid "allow creation of more than one tree"
+msgstr ""
+
+msgid ""
+"git multi-pack-index [<options>] write [--preferred-pack=<pack>][--refs-"
+"snapshot=<path>]"
+msgstr ""
+
+msgid "git multi-pack-index [<options>] verify"
+msgstr "git multi-pack-index [<опції>] verify"
+
+msgid "git multi-pack-index [<options>] expire"
+msgstr "git multi-pack-index [<опції>] expire"
+
+msgid "git multi-pack-index [<options>] repack [--batch-size=<size>]"
+msgstr ""
+
+msgid "directory"
+msgstr "директорія"
+
+msgid "object directory containing set of packfile and pack-index pairs"
+msgstr ""
+
+msgid "preferred-pack"
+msgstr ""
+
+msgid "pack for reuse when computing a multi-pack bitmap"
+msgstr ""
+
+msgid "write multi-pack bitmap"
+msgstr ""
+
+msgid "write multi-pack index containing only given indexes"
+msgstr ""
+
+msgid "refs snapshot for selecting bitmap commits"
+msgstr ""
+
+msgid ""
+"during repack, collect pack-files of smaller size into a batch that is "
+"larger than this size"
+msgstr ""
+
+msgid "git mv [<options>] <source>... <destination>"
+msgstr "git mv [<опції>] <джерело>... <призначення>"
+
+#, c-format
+msgid "Directory %s is in index and no submodule?"
+msgstr ""
+
+msgid "Please stage your changes to .gitmodules or stash them to proceed"
+msgstr ""
+
+#, c-format
+msgid "%.*s is in index"
+msgstr ""
+
+msgid "force move/rename even if target exists"
+msgstr ""
+
+msgid "skip move/rename errors"
+msgstr ""
+
+#, c-format
+msgid "destination '%s' is not a directory"
+msgstr "місце призначення \"%s\" не є директорією"
+
+#, c-format
+msgid "Checking rename of '%s' to '%s'\n"
+msgstr ""
+
+msgid "bad source"
+msgstr "невірне джерело"
+
+msgid "destination exists"
+msgstr ""
+
+msgid "can not move directory into itself"
+msgstr ""
+
+msgid "cannot move directory over file"
+msgstr ""
+
+msgid "source directory is empty"
+msgstr ""
+
+msgid "not under version control"
+msgstr ""
+
+msgid "conflicted"
+msgstr ""
+
+#, c-format
+msgid "overwriting '%s'"
+msgstr ""
+
+msgid "Cannot overwrite"
+msgstr ""
+
+msgid "multiple sources for the same target"
+msgstr ""
+
+msgid "destination directory does not exist"
+msgstr "директорія призначення не існує"
+
+msgid "destination exists in the index"
+msgstr "призначення існує в індексі"
+
+#, c-format
+msgid "%s, source=%s, destination=%s"
+msgstr ""
+
+#, c-format
+msgid "Renaming %s to %s\n"
+msgstr "Перейменування %s на %s\n"
+
+#, c-format
+msgid "renaming '%s' failed"
+msgstr ""
+
+msgid "git name-rev [<options>] <commit>..."
+msgstr "git name-rev [<опції>] <коміт>..."
+
+msgid "git name-rev [<options>] --all"
+msgstr "git name-rev [<опції>] --all"
+
+msgid "git name-rev [<options>] --annotate-stdin"
+msgstr ""
+
+msgid "print only ref-based names (no object names)"
+msgstr ""
+
+msgid "only use tags to name the commits"
+msgstr ""
+
+msgid "only use refs matching <pattern>"
+msgstr ""
+
+msgid "ignore refs matching <pattern>"
+msgstr ""
+
+msgid "list all commits reachable from all refs"
+msgstr ""
+
+msgid "deprecated: use --annotate-stdin instead"
+msgstr ""
+
+msgid "annotate text from stdin"
+msgstr ""
+
+msgid "allow to print `undefined` names (default)"
+msgstr ""
+
+msgid "dereference tags in the input (internal use)"
+msgstr ""
+
+msgid "git notes [--ref <notes-ref>] [list [<object>]]"
+msgstr ""
+
+msgid ""
+"git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> "
+"| (-c | -C) <object>] [<object>]"
+msgstr ""
+
+msgid "git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>"
+msgstr ""
+
+msgid ""
+"git notes [--ref <notes-ref>] append [--allow-empty] [-m <msg> | -F <file> | "
+"(-c | -C) <object>] [<object>]"
+msgstr ""
+
+msgid "git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"
+msgstr ""
+
+msgid "git notes [--ref <notes-ref>] show [<object>]"
+msgstr ""
+
+msgid ""
+"git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"
+msgstr ""
+
+msgid "git notes [--ref <notes-ref>] remove [<object>...]"
+msgstr ""
+
+msgid "git notes [--ref <notes-ref>] prune [-n] [-v]"
+msgstr ""
+
+msgid "git notes [--ref <notes-ref>] get-ref"
+msgstr ""
+
+msgid "git notes [list [<object>]]"
+msgstr ""
+
+msgid "git notes add [<options>] [<object>]"
+msgstr "git notes add [<опції>] [<обʼєкт>]"
+
+msgid "git notes copy [<options>] <from-object> <to-object>"
+msgstr ""
+
+msgid "git notes copy --stdin [<from-object> <to-object>]..."
+msgstr ""
+
+msgid "git notes append [<options>] [<object>]"
+msgstr "git notes append [<опції>] [<обʼєкт>]"
+
+msgid "git notes edit [<object>]"
+msgstr ""
+
+msgid "git notes show [<object>]"
+msgstr ""
+
+msgid "git notes merge [<options>] <notes-ref>"
+msgstr "git notes merge [<опції>] <посилання-нотатки>"
+
+msgid "git notes merge --commit [<options>]"
+msgstr ""
+
+msgid "git notes merge --abort [<options>]"
+msgstr ""
+
+msgid "git notes remove [<object>]"
+msgstr ""
+
+msgid "git notes prune [<options>]"
+msgstr "git notes prune [<опції>]"
+
+msgid "Write/edit the notes for the following object:"
+msgstr ""
+
+#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "не вдалося запустити \"show\" для об’єкта \"%s\""
+
+msgid "could not read 'show' output"
+msgstr "не вдалося прочитати вивід \"show\""
+
+#, c-format
+msgid "failed to finish 'show' for object '%s'"
+msgstr "не вдалося завершити \"show\" для об’єкта \"%s\""
+
+msgid "please supply the note contents using either -m or -F option"
+msgstr ""
+
+msgid "unable to write note object"
+msgstr "не вдалося записати об’єкт нотатки"
+
+#, c-format
+msgid "the note contents have been left in %s"
+msgstr ""
+
+#, c-format
+msgid "could not open or read '%s'"
+msgstr "не вдалося відкрити або прочитати \"%s\""
+
+#, c-format
+msgid "failed to resolve '%s' as a valid ref."
+msgstr "не вдалося розпізнати \"%s\" як припустиме посилання."
+
+#, c-format
+msgid "failed to read object '%s'."
+msgstr "не вдалося прочитати обʼєкт \"%s\"."
+
+#, c-format
+msgid "cannot read note data from non-blob object '%s'."
+msgstr "неможливо прочитати дані нотатки з не-blob обʼєкту \"%s\"."
+
+#, c-format
+msgid "failed to copy notes from '%s' to '%s'"
+msgstr "не вдалося скопіювати нотатки з \"%s\" в \"%s\""
+
+#. TRANSLATORS: the first %s will be replaced by a git
+#. notes command: 'add', 'merge', 'remove', etc.
+#.
+
+#, c-format
+msgid "refusing to %s notes in %s (outside of refs/notes/)"
+msgstr ""
+
+#, c-format
+msgid "no note found for object %s."
+msgstr "для обʼєкта %s не знайдено жодної нотатки."
+
+msgid "note contents as a string"
+msgstr ""
+
+msgid "note contents in a file"
+msgstr ""
+
+msgid "reuse and edit specified note object"
+msgstr ""
+
+msgid "reuse specified note object"
+msgstr ""
+
+msgid "allow storing empty note"
+msgstr ""
+
+msgid "replace existing notes"
+msgstr "замінити існуючі нотатки"
+
+#, c-format
+msgid ""
+"Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
+"existing notes"
+msgstr ""
+
+#, c-format
+msgid "Overwriting existing notes for object %s\n"
+msgstr ""
+
+#, c-format
+msgid "Removing note for object %s\n"
+msgstr "Видалення нотатки для обʼєкта %s\n"
+
+msgid "read objects from stdin"
+msgstr ""
+
+msgid "load rewriting config for <command> (implies --stdin)"
+msgstr ""
+
+msgid "too few arguments"
+msgstr "замало аргументів"
+
+#, c-format
+msgid ""
+"Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
+"existing notes"
+msgstr ""
+
+#, c-format
+msgid "missing notes on source object %s. Cannot copy."
+msgstr ""
+
+#, c-format
+msgid ""
+"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 ""
+
+msgid "failed to delete ref NOTES_MERGE_PARTIAL"
+msgstr ""
+
+msgid "failed to delete ref NOTES_MERGE_REF"
+msgstr ""
+
+msgid "failed to remove 'git notes merge' worktree"
+msgstr ""
+
+msgid "failed to read ref NOTES_MERGE_PARTIAL"
+msgstr ""
+
+msgid "could not find commit from NOTES_MERGE_PARTIAL."
+msgstr ""
+
+msgid "could not parse commit from NOTES_MERGE_PARTIAL."
+msgstr ""
+
+msgid "failed to resolve NOTES_MERGE_REF"
+msgstr ""
+
+msgid "failed to finalize notes merge"
+msgstr "не вдалося завершити злиття нотаток"
+
+#, c-format
+msgid "unknown notes merge strategy %s"
+msgstr ""
+
+msgid "General options"
+msgstr ""
+
+msgid "Merge options"
+msgstr ""
+
+msgid ""
+"resolve notes conflicts using the given strategy (manual/ours/theirs/union/"
+"cat_sort_uniq)"
+msgstr ""
+
+msgid "Committing unmerged notes"
+msgstr "Виконнання коміту незлитих нотаток"
+
+msgid "finalize notes merge by committing unmerged notes"
+msgstr ""
+
+msgid "Aborting notes merge resolution"
+msgstr ""
+
+msgid "abort notes merge"
+msgstr "перервати злиття нотаток"
+
+msgid "cannot mix --commit, --abort or -s/--strategy"
+msgstr ""
+
+msgid "must specify a notes ref to merge"
+msgstr "необхідно вказати посилання нотаток для злиття"
+
+#, c-format
+msgid "unknown -s/--strategy: %s"
+msgstr ""
+
+#, c-format
+msgid "a notes merge into %s is already in-progress at %s"
+msgstr ""
+
+#, c-format
+msgid "failed to store link to current notes ref (%s)"
+msgstr "не вдалося зберегти ланку на поточні нотатки посилання (%s)"
+
+#, c-format
+msgid ""
+"Automatic notes merge failed. Fix conflicts in %s and commit the result with "
+"'git notes merge --commit', or abort the merge with 'git notes merge --"
+"abort'.\n"
+msgstr ""
+
+#, c-format
+msgid "Failed to resolve '%s' as a valid ref."
+msgstr "Не вдалося розвʼязати \"%s\" як припустиме посилання."
+
+#, c-format
+msgid "Object %s has no note\n"
+msgstr ""
+
+msgid "attempt to remove non-existent note is not an error"
+msgstr ""
+
+msgid "read object names from the standard input"
+msgstr ""
+
+msgid "do not remove, show only"
+msgstr ""
+
+msgid "report pruned notes"
+msgstr ""
+
+msgid "notes-ref"
+msgstr ""
+
+msgid "use notes from <notes-ref>"
+msgstr ""
+
+#, c-format
+msgid "unknown subcommand: `%s'"
+msgstr ""
+
+msgid "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]"
+msgstr ""
+
+msgid ""
+"git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]"
+msgstr ""
+
+#, c-format
+msgid ""
+"write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in "
+"pack %s"
+msgstr ""
+
+#, c-format
+msgid "bad packed object CRC for %s"
+msgstr ""
+
+#, c-format
+msgid "corrupt packed object for %s"
+msgstr "пошкоджений запакований обʼєкт для %s"
+
+#, c-format
+msgid "recursive delta detected for object %s"
+msgstr "виявлено рекурсивну дельту для обʼєкта %s"
+
+#, c-format
+msgid "ordered %u objects, expected %<PRIu32>"
+msgstr ""
+
+#, c-format
+msgid "expected object at offset %<PRIuMAX> in pack %s"
+msgstr "очікувався обʼєкт на зміщенні %<PRIuMAX> пакунка %s"
+
+msgid "disabling bitmap writing, packs are split due to pack.packSizeLimit"
+msgstr ""
+
+msgid "Writing objects"
+msgstr "Запис обʼєктів"
+
+#, c-format
+msgid "failed to stat %s"
+msgstr "не вдалося виконати stat %s"
+
+#, c-format
+msgid "failed utime() on %s"
+msgstr "не вдалося виконати utime() на %s"
+
+msgid "failed to write bitmap index"
+msgstr "не вдалося записати bitmap індекс"
+
+#, c-format
+msgid "wrote %<PRIu32> objects while expecting %<PRIu32>"
+msgstr ""
+
+msgid "disabling bitmap writing, as some objects are not being packed"
+msgstr ""
+
+#, c-format
+msgid "delta base offset overflow in pack for %s"
+msgstr "переповнення зміщення дельти бази у пакунку для %s"
+
+#, c-format
+msgid "delta base offset out of bound for %s"
+msgstr "зміщення бази дельти виходить за межі для %s"
+
+msgid "Counting objects"
+msgstr "Підрахунок обʼєктів"
+
+#, c-format
+msgid "unable to get size of %s"
+msgstr "не вдалося отримати розмір %s"
+
+#, c-format
+msgid "unable to parse object header of %s"
+msgstr "не вдалося розібрати заголовок обʼєкта %s"
+
+#, c-format
+msgid "object %s cannot be read"
+msgstr "обʼєкт %s не може бути прочитаний"
+
+#, c-format
+msgid "object %s inconsistent object length (%<PRIuMAX> vs %<PRIuMAX>)"
+msgstr ""
+
+msgid "suboptimal pack - out of memory"
+msgstr ""
+
+#, c-format
+msgid "Delta compression using up to %d threads"
+msgstr ""
+
+#, c-format
+msgid "unable to pack objects reachable from tag %s"
+msgstr "не вдалося запакувати обʼєкти, доступні з тегу %s"
+
+#, c-format
+msgid "unable to get type of object %s"
+msgstr "не вдалося отримати тип обʼєкта %s"
+
+msgid "Compressing objects"
+msgstr "Компресія обʼєктів"
+
+msgid "inconsistency with delta count"
+msgstr ""
+
+#, c-format
+msgid ""
+"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
+"hash> <uri>' (got '%s')"
+msgstr ""
+
+#, c-format
+msgid ""
+"object already configured in another uploadpack.blobpackfileuri (got '%s')"
+msgstr ""
+
+#, c-format
+msgid "could not get type of object %s in pack %s"
+msgstr "не вдалося отримати тип обʼєкта %s у пакунку %s"
+
+#, c-format
+msgid "could not find pack '%s'"
+msgstr "не вдалося знайти пакунок \"%s\""
+
+#, c-format
+msgid "packfile %s cannot be accessed"
+msgstr ""
+
+msgid "Enumerating cruft objects"
+msgstr "Перерахування марних обʼєктів"
+
+msgid "unable to add cruft objects"
+msgstr "не вдалося додати марні обʼєкти"
+
+msgid "Traversing cruft objects"
+msgstr "Проходження по марним обʼєктам"
+
+#, c-format
+msgid ""
+"expected edge object ID, got garbage:\n"
+" %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"expected object ID, got garbage:\n"
+" %s"
+msgstr ""
+
+msgid "could not load cruft pack .mtimes"
+msgstr ""
+
+msgid "cannot open pack index"
+msgstr "не вдалося відкрити індекс пакунка"
+
+#, c-format
+msgid "loose object at %s could not be examined"
+msgstr ""
+
+msgid "unable to force loose object"
+msgstr "не вдалося примусово вивільнити обʼєкт"
+
+#, c-format
+msgid "not a rev '%s'"
+msgstr ""
+
+#, c-format
+msgid "bad revision '%s'"
+msgstr "невірна ревізія \"%s\""
+
+msgid "unable to add recent objects"
+msgstr "не вдалося додати нещодавні обʼєкти"
+
+#, c-format
+msgid "unsupported index version %s"
+msgstr ""
+
+#, c-format
+msgid "bad index version '%s'"
+msgstr "невірна версія індексу \"%s\""
+
+msgid "show progress meter during object writing phase"
+msgstr ""
+
+msgid "similar to --all-progress when progress meter is shown"
+msgstr ""
+
+msgid "<version>[,<offset>]"
+msgstr ""
+
+msgid "write the pack index file in the specified idx format version"
+msgstr ""
+
+msgid "maximum size of each output pack file"
+msgstr ""
+
+msgid "ignore borrowed objects from alternate object store"
+msgstr ""
+
+msgid "ignore packed objects"
+msgstr "ігнорувати запаковані обʼєкти"
+
+msgid "limit pack window by objects"
+msgstr ""
+
+msgid "limit pack window by memory in addition to object limit"
+msgstr ""
+
+msgid "maximum length of delta chain allowed in the resulting pack"
+msgstr ""
+
+msgid "reuse existing deltas"
+msgstr "повторно використати існуючі дельти"
+
+msgid "reuse existing objects"
+msgstr "повторно використати існуючі обʼєкти"
+
+msgid "use OFS_DELTA objects"
+msgstr ""
+
+msgid "use threads when searching for best delta matches"
+msgstr ""
+
+msgid "do not create an empty pack output"
+msgstr "не створювати вивід порожнього пакунка"
+
+msgid "read revision arguments from standard input"
+msgstr ""
+
+msgid "limit the objects to those that are not yet packed"
+msgstr ""
+
+msgid "include objects reachable from any reference"
+msgstr ""
+
+msgid "include objects referred by reflog entries"
+msgstr ""
+
+msgid "include objects referred to by the index"
+msgstr ""
+
+msgid "read packs from stdin"
+msgstr ""
+
+msgid "output pack to stdout"
+msgstr ""
+
+msgid "include tag objects that refer to objects to be packed"
+msgstr ""
+
+msgid "keep unreachable objects"
+msgstr ""
+
+msgid "pack loose unreachable objects"
+msgstr ""
+
+msgid "unpack unreachable objects newer than <time>"
+msgstr ""
+
+msgid "create a cruft pack"
+msgstr ""
+
+msgid "expire cruft objects older than <time>"
+msgstr ""
+
+msgid "use the sparse reachability algorithm"
+msgstr ""
+
+msgid "create thin packs"
+msgstr "створити тонкі пакунки"
+
+msgid "create packs suitable for shallow fetches"
+msgstr ""
+
+msgid "ignore packs that have companion .keep file"
+msgstr ""
+
+msgid "ignore this pack"
+msgstr "ігнорувати цей пакунок"
+
+msgid "pack compression level"
+msgstr ""
+
+msgid "do not hide commits by grafts"
+msgstr ""
+
+msgid "use a bitmap index if available to speed up counting objects"
+msgstr ""
+
+msgid "write a bitmap index together with the pack index"
+msgstr ""
+
+msgid "write a bitmap index if possible"
+msgstr ""
+
+msgid "handling for missing objects"
+msgstr "обробка для відсутніх обʼєктів"
+
+msgid "do not pack objects in promisor packfiles"
+msgstr ""
+
+msgid "respect islands during delta compression"
+msgstr ""
+
+msgid "protocol"
+msgstr ""
+
+msgid "exclude any configured uploadpack.blobpackfileuri with this protocol"
+msgstr ""
+
+#, c-format
+msgid "delta chain depth %d is too deep, forcing %d"
+msgstr ""
+
+#, c-format
+msgid "pack.deltaCacheLimit is too high, forcing %d"
+msgstr ""
+
+#, c-format
+msgid "bad pack compression level %d"
+msgstr ""
+
+msgid "--max-pack-size cannot be used to build a pack for transfer"
+msgstr ""
+
+msgid "minimum pack size limit is 1 MiB"
+msgstr ""
+
+msgid "--thin cannot be used to build an indexable pack"
+msgstr ""
+
+msgid "cannot use --filter without --stdout"
+msgstr ""
+
+msgid "cannot use --filter with --stdin-packs"
+msgstr ""
+
+msgid "cannot use internal rev list with --stdin-packs"
+msgstr ""
+
+msgid "cannot use internal rev list with --cruft"
+msgstr ""
+
+msgid "cannot use --stdin-packs with --cruft"
+msgstr ""
+
+msgid "cannot use --max-pack-size with --cruft"
+msgstr ""
+
+msgid "Enumerating objects"
+msgstr "Перерахування обʼєктів"
+
+#, c-format
+msgid ""
+"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
+"reused %<PRIu32>"
+msgstr ""
+
+msgid ""
+"'git pack-redundant' is nominated for removal.\n"
+"If you still use this command, please add an extra\n"
+"option, '--i-still-use-this', on the command line\n"
+"and let us know you still use it by sending an e-mail\n"
+"to <git@vger.kernel.org>.  Thanks.\n"
+msgstr ""
+
+msgid "refusing to run without --i-still-use-this"
+msgstr ""
+
+msgid "git pack-refs [--all] [--no-prune]"
+msgstr ""
+
+msgid "pack everything"
+msgstr ""
+
+msgid "prune loose refs (default)"
+msgstr "видалити вивільнені посилання (за замовчуванням)"
+
+msgid "git patch-id [--stable | --unstable | --verbatim]"
+msgstr ""
+
+msgid "use the unstable patch-id algorithm"
+msgstr ""
+
+msgid "use the stable patch-id algorithm"
+msgstr ""
+
+msgid "don't strip whitespace from the patch"
+msgstr ""
+
+msgid "git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]"
+msgstr ""
+
+msgid "report pruned objects"
+msgstr ""
+
+msgid "expire objects older than <time>"
+msgstr ""
+
+msgid "limit traversal to objects outside promisor packfiles"
+msgstr ""
+
+msgid "cannot prune in a precious-objects repo"
+msgstr "неможливо виконати видалення в precious-objects сховищі"
+
+msgid "git pull [<options>] [<repository> [<refspec>...]]"
+msgstr "git pull [<опції>] [<сховище> [<визначник посилання>...]]"
+
+msgid "control for recursive fetching of submodules"
+msgstr "управління рекурсивним отриманням підмодулів"
+
+msgid "Options related to merging"
+msgstr ""
+
+msgid "incorporate changes by rebasing rather than merging"
+msgstr ""
+
+msgid "allow fast-forward"
+msgstr ""
+
+msgid "control use of pre-merge-commit and commit-msg hooks"
+msgstr ""
+
+msgid "automatically stash/stash pop before and after"
+msgstr ""
+
+msgid "Options related to fetching"
+msgstr ""
+
+msgid "force overwrite of local branch"
+msgstr ""
+
+msgid "number of submodules pulled in parallel"
+msgstr "кількість підмодулів, що затягуються паралельно"
+
+msgid ""
+"There is no candidate for rebasing against among the refs that you just "
+"fetched."
+msgstr ""
+
+msgid ""
+"There are no candidates for merging among the refs that you just fetched."
+msgstr ""
+
+msgid ""
+"Generally this means that you provided a wildcard refspec which had no\n"
+"matches on the remote end."
+msgstr ""
+
+#, c-format
+msgid ""
+"You asked to pull from the remote '%s', but did not specify\n"
+"a branch. Because this is not the default configured remote\n"
+"for your current branch, you must specify a branch on the command line."
+msgstr ""
+
+msgid "You are not currently on a branch."
+msgstr "Наразі ви не на гілці."
+
+msgid "Please specify which branch you want to rebase against."
+msgstr ""
+
+msgid "Please specify which branch you want to merge with."
+msgstr ""
+
+msgid "See git-pull(1) for details."
+msgstr ""
+
+msgid "<remote>"
+msgstr ""
+
+msgid "<branch>"
+msgstr "<гілка>"
+
+msgid "There is no tracking information for the current branch."
+msgstr ""
+
+msgid ""
+"If you wish to set tracking information for this branch you can do so with:"
+msgstr ""
+
+#, c-format
+msgid ""
+"Your configuration specifies to merge with the ref '%s'\n"
+"from the remote, but no such ref was fetched."
+msgstr ""
+
+#, c-format
+msgid "unable to access commit %s"
+msgstr "не вдалося отримати доступ до коміту %s"
+
+msgid "ignoring --verify-signatures for rebase"
+msgstr ""
+
+msgid ""
+"You have divergent branches and need to specify how to reconcile them.\n"
+"You can do so by running one of the following commands sometime before\n"
+"your next pull:\n"
+"\n"
+"  git config pull.rebase false  # merge\n"
+"  git config pull.rebase true   # rebase\n"
+"  git config pull.ff only       # fast-forward only\n"
+"\n"
+"You can replace \"git config\" with \"git config --global\" to set a "
+"default\n"
+"preference for all repositories. You can also pass --rebase, --no-rebase,\n"
+"or --ff-only on the command line to override the configured default per\n"
+"invocation.\n"
+msgstr ""
+
+msgid "Updating an unborn branch with changes added to the index."
+msgstr ""
+
+msgid "pull with rebase"
+msgstr ""
+
+msgid "Please commit or stash them."
+msgstr ""
+
+#, c-format
+msgid ""
+"fetch updated the current branch head.\n"
+"fast-forwarding your working tree from\n"
+"commit %s."
+msgstr ""
+
+#, c-format
+msgid ""
+"Cannot fast-forward your working tree.\n"
+"After making sure that you saved anything precious from\n"
+"$ git diff %s\n"
+"output, run\n"
+"$ git reset --hard\n"
+"to recover."
+msgstr ""
+
+msgid "Cannot merge multiple branches into empty head."
+msgstr ""
+
+msgid "Cannot rebase onto multiple branches."
+msgstr ""
+
+msgid "Cannot fast-forward to multiple branches."
+msgstr ""
+
+msgid "Need to specify how to reconcile divergent branches."
+msgstr ""
+
+msgid "cannot rebase with locally recorded submodule modifications"
+msgstr ""
+
+msgid "git push [<options>] [<repository> [<refspec>...]]"
+msgstr "git push [<опції>] [<сховище> [<визначник посилання>...]]"
+
+msgid "tag shorthand without <tag>"
+msgstr "скорочення тегу без <тег>"
+
+msgid "--delete only accepts plain target ref names"
+msgstr "--delete приймає лише прості назви посилань"
+
+msgid ""
+"\n"
+"To choose either option permanently, see push.default in 'git help config'.\n"
+msgstr ""
+"\n"
+"Щоб обрати будь-яку з опцій постійною, скористайтесь опцією push.default у "
+"'git help config'.\n"
+
+msgid ""
+"\n"
+"To avoid automatically configuring an upstream branch when its name\n"
+"won't match the local branch, see option 'simple' of branch.autoSetupMerge\n"
+"in 'git help config'.\n"
+msgstr ""
+"\n"
+"Щоб уникнути автоматичного налаштування гілки перводжерельного сховища, якщо "
+"її назва\n"
+"не збігається з назвою локальної гілки, скористайтесь опцією 'simple' для "
+"branch.autoSetupMerge\n"
+"у “git help config”.\n"
+
+#, c-format
+msgid ""
+"The upstream branch of your current branch does not match\n"
+"the name of your current branch.  To push to the upstream branch\n"
+"on the remote, use\n"
+"\n"
+"    git push %s HEAD:%s\n"
+"\n"
+"To push to the branch of the same name on the remote, use\n"
+"\n"
+"    git push %s HEAD\n"
+"%s%s"
+msgstr ""
+"Назва гілки перводжерельного сховища для вашої поточної гілки не збігається "
+"з\n"
+"назвою вашої поточної гілки.  Щоб надіслати до гілки\n"
+"першоджерельного сховища, скористайтесь командою\n"
+"\n"
+"    git push %s HEAD:%s\n"
+"\n"
+"Щоб надіслати до однойменної гілки на віддаленому сервері скористайтесь\n"
+"\n"
+"    git push %s HEAD\n"
+"%s%s"
+
+#, c-format
+msgid ""
+"You are not currently on a branch.\n"
+"To push the history leading to the current (detached HEAD)\n"
+"state now, use\n"
+"\n"
+"    git push %s HEAD:<name-of-remote-branch>\n"
+msgstr ""
+"Ви зараз не перебуваєте на гілці.\n"
+"Щоб надіслати історію, що веде до поточного (відокремленого HEAD)\n"
+"стану, скористайтесь командою\n"
+"\n"
+"    git push %s HEAD:<назва-віддаленої-гілки>\n"
+
+msgid ""
+"\n"
+"To have this happen automatically for branches without a tracking\n"
+"upstream, see 'push.autoSetupRemote' in 'git help config'.\n"
+msgstr ""
+"\n"
+"Щоб це відбувалося автоматично для невідстежуваних гілок\n"
+"першоджерельного сховища, дивіться 'push.autoSetupRemote' у 'git help "
+"config'.\n"
+
+#, c-format
+msgid ""
+"The current branch %s has no upstream branch.\n"
+"To push the current branch and set the remote as upstream, use\n"
+"\n"
+"    git push --set-upstream %s %s\n"
+"%s"
+msgstr ""
+"Поточна гілка %s не має гілки у першоджeрельному сховищі.\n"
+"Щоб надіслати поточну гілку і встановити віддалене призначення "
+"першоджерельним сховищем, скористайтеся\n"
+"\n"
+"    git push --set-upstream %s %s\n"
+"%s"
+
+#, c-format
+msgid "The current branch %s has multiple upstream branches, refusing to push."
+msgstr "Поточна гілка %s має декілька висхідних гілок, відмова надсилання."
+
+msgid ""
+"You didn't specify any refspecs to push, and push.default is \"nothing\"."
+msgstr ""
+"Ви не вказали жодних визначників посилань для надсилання, і push.default "
+"дорівнює \"nothing\"."
+
+#, c-format
+msgid ""
+"You are pushing to remote '%s', which is not the upstream of\n"
+"your current branch '%s', without telling me what to push\n"
+"to update which remote branch."
+msgstr ""
+"Ви надсилаєте до віддаленої гілки '%s', яка не є першоджерелом\n"
+"вашої поточної гілки '%s', не кажучі мені, що надсилати\n"
+"і яку віддалену гілку оновлювати."
+
+msgid ""
+"Updates were rejected because the tip of your current branch is behind\n"
+"its remote counterpart. Integrate the remote changes (e.g.\n"
+"'git pull ...') before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+"Оновлення було відхилено, оскільки верхівка вашої поточної гілки знаходиться "
+"позаду\n"
+"її віддаленого аналога. Інтегруйте віддалені зміни (наприклад, через\n"
+"'git pull ...') перед повторним надсиланням.\n"
+"Докладніше у \"Примітці про перемотування\" команди \"git push --help\"."
+
+msgid ""
+"Updates were rejected because a pushed branch tip is behind its remote\n"
+"counterpart. Check out this branch and integrate the remote changes\n"
+"(e.g. 'git pull ...') before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+"Оновлення було відхилено, оскільки верхівка вашої поточної гілки знаходиться "
+"позаду\n"
+"її віддаленого аналога. Стягнить цю гілку та інтегруйте віддалені зміни\n"
+"(наприклад, через 'git pull...') перед повторним надсиланням.\n"
+"Докладніше у \"Примітці про перемотування\" команди \"git push --help\"."
+
+msgid ""
+"Updates were rejected because the remote contains work that you do\n"
+"not have locally. This is usually caused by another repository pushing\n"
+"to the same ref. You may want to first integrate the remote changes\n"
+"(e.g., 'git pull ...') before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+"Оновлення було відхилено, оскільки у віддаленому сховищі міститься робота, "
+"якої\n"
+"немає локально. Зазвичай це стається, коли інше сховище надсилає\n"
+"до того самого посилання. Можливо, вам слід спочатку інтегрувати віддалені "
+"зміни\n"
+"(наприклад, через 'git pull ...') перед повторним надсиланням.\n"
+"Докладніше у \"Примітці про перемотування\" команди \"git push --help\"."
+
+msgid "Updates were rejected because the tag already exists in the remote."
+msgstr ""
+"Оновлення було відхилено, оскільки тег вже існує на віддаленому сховищі."
+
+msgid ""
+"You cannot update a remote ref that points at a non-commit object,\n"
+"or update a remote ref to make it point at a non-commit object,\n"
+"without using the '--force' option.\n"
+msgstr ""
+"Ви не можете оновити віддалене посилання, яке вказує на об’єкт, що не є "
+"об’єктом коміту,\n"
+"або оновити віддалене посилання так, щоб воно вказувало на об’єкт, що не є "
+"об’єктом коміту,\n"
+"без використання опції '--force'.\n"
+
+msgid ""
+"Updates were rejected because the tip of the remote-tracking\n"
+"branch has been updated since the last checkout. You may want\n"
+"to integrate those changes locally (e.g., 'git pull ...')\n"
+"before forcing an update.\n"
+msgstr ""
+"Оновлення було відхилено, оскільки верхівка віддалено відстежуваної \n"
+"гілки була оновлена з моменту останнього стягування. Можливо, ви захочете\n"
+"інтегрувати ці зміни локально (наприклад, через 'git pull ...')\n"
+"перед примусовим оновленням.\n"
+
+#, c-format
+msgid "Pushing to %s\n"
+msgstr "Надсилання до %s\n"
+
+#, c-format
+msgid "failed to push some refs to '%s'"
+msgstr "не вдалося надіслати деякі посилання до '%s'"
+
+msgid ""
+"recursing into submodule with push.recurseSubmodules=only; using on-demand "
+"instead"
+msgstr ""
+"рекурсія в підмодулі з push.recurseSubmodules=only; натомість використовую "
+"on-demand"
+
+#, c-format
+msgid "invalid value for '%s'"
+msgstr "неприпустиме значення для '%s'"
+
+msgid "repository"
+msgstr "сховище"
+
+msgid "push all branches"
+msgstr "надіслати всі гілки"
+
+msgid "mirror all refs"
+msgstr "віддзеркалити всі посилання"
+
+msgid "delete refs"
+msgstr "видалити посилання"
+
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr "надіслати теги (не може бути використано з --all, --branches або --mirror)"
+
+msgid "force updates"
+msgstr "оновити примусово"
+
+msgid "<refname>:<expect>"
+msgstr "<refname>:<expect>"
+
+msgid "require old value of ref to be at this value"
+msgstr "вимагати, щоб старе значення посилання було рівним цьому значенню"
+
+msgid "require remote updates to be integrated locally"
+msgstr "вимагати локальної інтеграції віддалених оновлень"
+
+msgid "control recursive pushing of submodules"
+msgstr "контролювати рекурсивне надсилання підмодулів"
+
+msgid "use thin pack"
+msgstr "використовуйте тонке пакування"
+
+msgid "receive pack program"
+msgstr "отримати пакетну програму"
+
+msgid "set upstream for git pull/status"
+msgstr "встановити першоджерельне сховище для git pull/status"
+
+msgid "prune locally removed refs"
+msgstr "обрізати локально видалені посилання"
+
+msgid "bypass pre-push hook"
+msgstr "обійти pre-push гачок"
+
+msgid "push missing but relevant tags"
+msgstr "надсилання відсутнє, але є релевантні теги"
+
+msgid "GPG sign the push"
+msgstr "підписати надсилання за допомогою GPG"
+
+msgid "request atomic transaction on remote side"
+msgstr "запросити атомарну транзакцію на віддаленій стороні"
+
+msgid "--delete doesn't make sense without any refs"
+msgstr "--delete не має сенсу без рефів"
+
+#, c-format
+msgid "bad repository '%s'"
+msgstr "невірне сховище \"%s\""
+
+msgid ""
+"No configured push destination.\n"
+"Either specify the URL from the command-line or configure a remote "
+"repository using\n"
+"\n"
+"    git remote add <name> <url>\n"
+"\n"
+"and then push using the remote name\n"
+"\n"
+"    git push <name>\n"
+msgstr ""
+"Немає налаштованого місця призначення надсилання.\n"
+"Або зазначте URL-адресу з командного рядка, або налаштуйте віддалене сховище "
+"за допомогою\n"
+"\n"
+"    git remote add <назва> <адреса>\n"
+"\n"
+"а потім виконайте надсилання, використовуючи назву віддаленого сховища\n"
+"\n"
+"    git push <ім'я>\n"
+
+msgid "--all can't be combined with refspecs"
+msgstr "--all не можна комбінувати з визначниками посилань"
+
+msgid "--mirror can't be combined with refspecs"
+msgstr "--mirror не можна комбінувати з визначниками посилань"
+
+msgid "push options must not have new line characters"
+msgstr "опції push не можуть містити символи нового рядка"
+
+msgid "git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"
+msgstr ""
+
+msgid "git range-diff [<options>] <old-tip>...<new-tip>"
+msgstr ""
+
+msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
+msgstr ""
+
+msgid "use simple diff colors"
+msgstr ""
+
+msgid "notes"
+msgstr ""
+
+msgid "passed to 'git log'"
+msgstr ""
+
+msgid "only emit output related to the first range"
+msgstr ""
+
+msgid "only emit output related to the second range"
+msgstr ""
+
+#, c-format
+msgid "not a revision: '%s'"
+msgstr "не є ревізією: \"%s\""
+
+#, c-format
+msgid "not a commit range: '%s'"
+msgstr "не діапазон комітів: \"%s\""
+
+#, c-format
+msgid "not a symmetric range: '%s'"
+msgstr "не симетричний діапазон: \"%s\""
+
+msgid "need two commit ranges"
+msgstr "потрібно два діапазони комітів"
+
+msgid ""
+"git read-tree [(-m [--trivial] [--aggressive] | --reset | --"
+"prefix=<prefix>)\n"
+"              [-u | -i]] [--index-output=<file>] [--no-sparse-checkout]\n"
+"              (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"
+msgstr ""
+
+msgid "write resulting index to <file>"
+msgstr ""
+
+msgid "only empty the index"
+msgstr "тільки очистити індекс"
+
+msgid "Merging"
+msgstr ""
+
+msgid "perform a merge in addition to a read"
+msgstr "виконати злиття на додачу до читання"
+
+msgid "3-way merge if no file level merging required"
+msgstr ""
+
+msgid "3-way merge in presence of adds and removes"
+msgstr ""
+
+msgid "same as -m, but discard unmerged entries"
+msgstr "те саме, що й -m, але відкидає незлиті записи"
+
+msgid "<subdirectory>/"
+msgstr ""
+
+msgid "read the tree into the index under <subdirectory>/"
+msgstr ""
+
+msgid "update working tree with merge result"
+msgstr ""
+
+msgid "gitignore"
+msgstr ""
+
+msgid "allow explicitly ignored files to be overwritten"
+msgstr ""
+
+msgid "don't check the working tree after merging"
+msgstr "не перевіряти робоче дерево після злиття"
+
+msgid "don't update the index or the work tree"
+msgstr ""
+
+msgid "skip applying sparse checkout filter"
+msgstr "пропустити застосування sparse checkout фільтра"
+
+msgid "debug unpack-trees"
+msgstr ""
+
+msgid "suppress feedback messages"
+msgstr ""
+
+msgid "You need to resolve your current index first"
+msgstr "Спочатку вам потрібно розвʼязати поточний індекс"
+
+msgid ""
+"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase> | --keep-base] "
+"[<upstream> [<branch>]]"
+msgstr ""
+
+msgid ""
+"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]"
+msgstr ""
+
+#, c-format
+msgid "could not read '%s'."
+msgstr "не вдалося прочитати \"%s\"."
+
+#, c-format
+msgid "could not create temporary %s"
+msgstr "не вдалося створити тимчасовий %s"
+
+msgid "could not mark as interactive"
+msgstr "не вдалося позначити як інтерактивний"
+
+msgid "could not generate todo list"
+msgstr "не вдалося створити список справ"
+
+msgid "a base commit must be provided with --upstream or --onto"
+msgstr ""
+
+#, c-format
+msgid "%s requires the merge backend"
+msgstr ""
+
+#, c-format
+msgid "invalid onto: '%s'"
+msgstr "неприпустимий onto: \"%s\""
+
+#, c-format
+msgid "invalid orig-head: '%s'"
+msgstr "неприпустимий orig-head: \"%s\""
+
+#, c-format
+msgid "ignoring invalid allow_rerere_autoupdate: '%s'"
+msgstr ""
+
+#, c-format
+msgid "could not remove '%s'"
+msgstr "не вдалося видалити \"%s\""
+
+msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+
+#, c-format
+msgid ""
+"\n"
+"git encountered an error while preparing the patches to replay\n"
+"these revisions:\n"
+"\n"
+"    %s\n"
+"\n"
+"As a result, git cannot rebase them."
+msgstr ""
+
+#, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr ""
+
+#, c-format
+msgid "could not switch to %s"
+msgstr "не вдалося переключитись на %s"
+
+msgid "apply options and merge options cannot be used together"
+msgstr "apply опції не можна використовувати разом з merge опціями"
+
+#, c-format
+msgid ""
+"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
+"\"ask\"."
+msgstr ""
+
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+
+#, c-format
+msgid ""
+"%s\n"
+"Please specify which branch you want to rebase against.\n"
+"See git-rebase(1) for details.\n"
+"\n"
+"    git rebase '<branch>'\n"
+"\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"If you wish to set tracking information for this branch you can do so with:\n"
+"\n"
+"    git branch --set-upstream-to=%s/<branch> %s\n"
+"\n"
+msgstr ""
+"Якщо ви бажаєте налаштувати відстежування для цієї гілки, ви можете зробити "
+"це за допомогою:\n"
+"\n"
+"    git branch --set-upstream-to=%s/<гілка> %s\n"
+"\n"
+
+msgid "exec commands cannot contain newlines"
+msgstr ""
+
+msgid "empty exec command"
+msgstr ""
+
+msgid "rebase onto given branch instead of upstream"
+msgstr ""
+
+msgid "use the merge-base of upstream and branch as the current base"
+msgstr ""
+
+msgid "allow pre-rebase hook to run"
+msgstr ""
+
+msgid "be quiet. implies --no-stat"
+msgstr ""
+
+msgid "display a diffstat of what changed upstream"
+msgstr ""
+
+msgid "do not show diffstat of what changed upstream"
+msgstr ""
+
+msgid "add a Signed-off-by trailer to each commit"
+msgstr ""
+
+msgid "make committer date match author date"
+msgstr ""
+
+msgid "ignore author date and use current date"
+msgstr ""
+
+msgid "synonym of --reset-author-date"
+msgstr ""
+
+msgid "passed to 'git apply'"
+msgstr ""
+
+msgid "ignore changes in whitespace"
+msgstr ""
+
+msgid "cherry-pick all commits, even if unchanged"
+msgstr ""
+
+msgid "continue"
+msgstr ""
+
+msgid "skip current patch and continue"
+msgstr ""
+
+msgid "abort and check out the original branch"
+msgstr "перервати і перейти до початкової гілки"
+
+msgid "abort but keep HEAD where it is"
+msgstr ""
+
+msgid "edit the todo list during an interactive rebase"
+msgstr ""
+
+msgid "show the patch file being applied or merged"
+msgstr ""
+
+msgid "use apply strategies to rebase"
+msgstr ""
+
+msgid "use merging strategies to rebase"
+msgstr ""
+
+msgid "let the user edit the list of commits to rebase"
+msgstr ""
+
+msgid "(REMOVED) was: try to recreate merges instead of ignoring them"
+msgstr ""
+
+msgid "how to handle commits that become empty"
+msgstr ""
+
+msgid "keep commits which start empty"
+msgstr ""
+
+msgid "move commits that begin with squash!/fixup! under -i"
+msgstr ""
+
+msgid "update branches that point to commits that are being rebased"
+msgstr ""
+
+msgid "add exec lines after each commit of the editable list"
+msgstr ""
+
+msgid "allow rebasing commits with empty messages"
+msgstr ""
+
+msgid "try to rebase merges instead of skipping them"
+msgstr ""
+
+msgid "use 'merge-base --fork-point' to refine upstream"
+msgstr ""
+"використовуйте \"merge-base --fork-point\" для уточнення першоджерельного "
+"сховища"
+
+msgid "use the given merge strategy"
+msgstr ""
+
+msgid "option"
+msgstr ""
+
+msgid "pass the argument through to the merge strategy"
+msgstr ""
+
+msgid "rebase all reachable commits up to the root(s)"
+msgstr ""
+
+msgid "automatically re-schedule any `exec` that fails"
+msgstr ""
+
+msgid "apply all changes, even those already present upstream"
+msgstr ""
+
+msgid "It looks like 'git am' is in progress. Cannot rebase."
+msgstr ""
+
+msgid ""
+"`rebase --preserve-merges` (-p) is no longer supported.\n"
+"Use `git rebase --abort` to terminate current rebase.\n"
+"Or downgrade to v2.33, or earlier, to complete the rebase."
+msgstr ""
+
+msgid ""
+"--preserve-merges was replaced by --rebase-merges\n"
+"Note: Your `pull.rebase` configuration may also be set to 'preserve',\n"
+"which is no longer supported; use 'merges' instead"
+msgstr ""
+
+msgid "No rebase in progress?"
+msgstr "Перебазування не відбувається?"
+
+msgid "The --edit-todo action can only be used during interactive rebase."
+msgstr ""
+
+msgid "Cannot read HEAD"
+msgstr ""
+
+msgid ""
+"You must edit all merge conflicts and then\n"
+"mark them as resolved using git add"
+msgstr ""
+
+msgid "could not discard worktree changes"
+msgstr "не вдалося відкинути зміни робочого дерева"
+
+#, c-format
+msgid "could not move back to %s"
+msgstr "не вдалося повернутися до %s"
+
+#, c-format
+msgid ""
+"It seems that there is already a %s directory, and\n"
+"I wonder if you are in the middle of another rebase.  If that is the\n"
+"case, please try\n"
+"\t%s\n"
+"If that is not the case, please\n"
+"\t%s\n"
+"and run me again.  I am stopping in case you still have something\n"
+"valuable there.\n"
+msgstr ""
+
+msgid "switch `C' expects a numerical value"
+msgstr ""
+
+msgid "--strategy requires --merge or --interactive"
+msgstr ""
+
+msgid ""
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
+"autosquash"
+msgstr ""
+
+msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr ""
+
+msgid ""
+"apply options are incompatible with rebase.updateRefs.  Consider adding --no-"
+"update-refs"
+msgstr ""
+
+#, c-format
+msgid "Unknown rebase backend: %s"
+msgstr ""
+
+msgid "--reschedule-failed-exec requires --exec or --interactive"
+msgstr ""
+
+#, c-format
+msgid "invalid upstream '%s'"
+msgstr "неприпустиме першоджерельне сховище \"%s\""
+
+msgid "Could not create new root commit"
+msgstr "Не вдалося створити новий кореневий коміт"
+
+#, c-format
+msgid "no such branch/commit '%s'"
+msgstr "немає такої гілки/коміту \"%s\""
+
+#, c-format
+msgid "No such ref: %s"
+msgstr "Немає такого посилання: %s"
+
+msgid "Could not resolve HEAD to a commit"
+msgstr "Не вдалося розвʼязати HEAD у коміт"
+
+#, c-format
+msgid "'%s': need exactly one merge base with branch"
+msgstr ""
+
+#, c-format
+msgid "'%s': need exactly one merge base"
+msgstr ""
+
+#, c-format
+msgid "Does not point to a valid commit '%s'"
+msgstr "Не вказує на припустимий коміт \"%s\""
+
+msgid "HEAD is up to date."
+msgstr "HEAD знаходиться в актуальному стані."
+
+#, c-format
+msgid "Current branch %s is up to date.\n"
+msgstr "Поточна гілка %s знаходиться в актуальному стані.\n"
+
+msgid "HEAD is up to date, rebase forced."
+msgstr ""
+
+#, c-format
+msgid "Current branch %s is up to date, rebase forced.\n"
+msgstr ""
+"Поточна гілка %s знаходиться в актуальному стані, перебазовуйте примусово.\n"
+
+msgid "The pre-rebase hook refused to rebase."
+msgstr ""
+
+#, c-format
+msgid "Changes to %s:\n"
+msgstr "Зміни у %s:\n"
+
+#, c-format
+msgid "Changes from %s to %s:\n"
+msgstr ""
+
+#, c-format
+msgid "First, rewinding head to replay your work on top of it...\n"
+msgstr ""
+
+msgid "Could not detach HEAD"
+msgstr "Не вдалося відʼєднати HEAD"
+
+#, c-format
+msgid "Fast-forwarded %s to %s.\n"
+msgstr ""
+
+msgid "git receive-pack <git-dir>"
+msgstr "git receive-pack <git-директорія>"
+
+msgid ""
+"By default, updating the current branch in a non-bare repository\n"
+"is denied, because it will make the index and work tree inconsistent\n"
+"with what you pushed, and will require 'git reset --hard' to match\n"
+"the work tree to HEAD.\n"
+"\n"
+"You can set the 'receive.denyCurrentBranch' configuration variable\n"
+"to 'ignore' or 'warn' in the remote repository to allow pushing into\n"
+"its current branch; however, this is not recommended unless you\n"
+"arranged to update its work tree to match what you pushed in some\n"
+"other way.\n"
+"\n"
+"To squelch this message and still keep the default behaviour, set\n"
+"'receive.denyCurrentBranch' configuration variable to 'refuse'."
+msgstr ""
+
+msgid ""
+"By default, deleting the current branch is denied, because the next\n"
+"'git clone' won't result in any file checked out, causing confusion.\n"
+"\n"
+"You can set 'receive.denyDeleteCurrent' configuration variable to\n"
+"'warn' or 'ignore' in the remote repository to allow deleting the\n"
+"current branch, with or without a warning message.\n"
+"\n"
+"To squelch this message, you can set it to 'refuse'."
+msgstr ""
+
+msgid "quiet"
+msgstr ""
+
+msgid "you must specify a directory"
+msgstr "необхідно вказати директорію"
+
+msgid "git reflog [show] [<log-options>] [<ref>]"
+msgstr "git reflog [show] [<лог-опції>] [<посилання>]"
+
+msgid ""
+"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
+"<refs>...]"
+msgstr ""
+
+msgid ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+msgstr ""
+
+msgid "git reflog exists <ref>"
+msgstr ""
+
+#, c-format
+msgid "invalid timestamp '%s' given to '--%s'"
+msgstr "неприпустима позначка часу \"%s\" передана до \"--%s\""
+
+msgid "do not actually prune any entries"
+msgstr ""
+
+msgid ""
+"rewrite the old SHA1 with the new SHA1 of the entry that now precedes it"
+msgstr ""
+
+msgid "update the reference to the value of the top reflog entry"
+msgstr ""
+
+msgid "print extra information on screen"
+msgstr ""
+
+msgid "timestamp"
+msgstr "позначка часу"
+
+msgid "prune entries older than the specified time"
+msgstr ""
+
+msgid ""
+"prune entries older than <time> that are not reachable from the current tip "
+"of the branch"
+msgstr ""
+
+msgid "prune any reflog entries that point to broken commits"
+msgstr ""
+
+msgid "process the reflogs of all references"
+msgstr ""
+
+msgid "limits processing to reflogs from the current worktree only"
+msgstr ""
+
+#, c-format
+msgid "Marking reachable objects..."
+msgstr ""
+
+#, c-format
+msgid "%s points nowhere!"
+msgstr ""
+
+msgid "no reflog specified to delete"
+msgstr ""
+
+#, c-format
+msgid "invalid ref format: %s"
+msgstr "неприпустимий формат посилання: %s"
+
+msgid ""
+"git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
+"mirror=<fetch|push>] <name> <url>"
+msgstr ""
+
+msgid "git remote rename [--[no-]progress] <old> <new>"
+msgstr ""
+
+msgid "git remote remove <name>"
+msgstr ""
+
+msgid "git remote set-head <name> (-a | --auto | -d | --delete | <branch>)"
+msgstr ""
+
+msgid "git remote [-v | --verbose] show [-n] <name>"
+msgstr ""
+
+msgid "git remote prune [-n | --dry-run] <name>"
+msgstr ""
+
+msgid ""
+"git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"
+msgstr ""
+
+msgid "git remote set-branches [--add] <name> <branch>..."
+msgstr ""
+
+msgid "git remote get-url [--push] [--all] <name>"
+msgstr ""
+
+msgid "git remote set-url [--push] <name> <newurl> [<oldurl>]"
+msgstr ""
+
+msgid "git remote set-url --add <name> <newurl>"
+msgstr ""
+
+msgid "git remote set-url --delete <name> <url>"
+msgstr ""
+
+msgid "git remote add [<options>] <name> <url>"
+msgstr "git remote add [<опції>] <назва> <url>"
+
+msgid "git remote set-branches <name> <branch>..."
+msgstr ""
+
+msgid "git remote set-branches --add <name> <branch>..."
+msgstr ""
+
+msgid "git remote show [<options>] <name>"
+msgstr "git remote show [<опції>] <назва>"
+
+msgid "git remote prune [<options>] <name>"
+msgstr "git remote prune [<опції>] <назва>"
+
+msgid "git remote update [<options>] [<group> | <remote>]..."
+msgstr "git remote update [<опції>] [<група> | <віддаленe-призначення>]..."
+
+#, c-format
+msgid "Updating %s"
+msgstr ""
+
+#, c-format
+msgid "Could not fetch %s"
+msgstr "Не вдалося отримати %s"
+
+msgid ""
+"--mirror is dangerous and deprecated; please\n"
+"\t use --mirror=fetch or --mirror=push instead"
+msgstr ""
+
+#, c-format
+msgid "unknown mirror argument: %s"
+msgstr ""
+
+msgid "fetch the remote branches"
+msgstr ""
+
+msgid "import all tags and associated objects when fetching"
+msgstr ""
+
+msgid "or do not fetch any tag at all (--no-tags)"
+msgstr ""
+
+msgid "branch(es) to track"
+msgstr ""
+
+msgid "master branch"
+msgstr "master гілка"
+
+msgid "set up remote as a mirror to push to or fetch from"
+msgstr ""
+
+msgid "specifying a master branch makes no sense with --mirror"
+msgstr ""
+
+msgid "specifying branches to track makes sense only with fetch mirrors"
+msgstr ""
+
+#, c-format
+msgid "remote %s already exists."
+msgstr "віддалений %s вже існує."
+
+#, c-format
+msgid "Could not setup master '%s'"
+msgstr "Не вдалося налаштувати master \"%s\""
+
+#, c-format
+msgid "more than one %s"
+msgstr ""
+
+#, c-format
+msgid "unhandled branch.%s.rebase=%s; assuming 'true'"
+msgstr ""
+
+#, c-format
+msgid "Could not get fetch map for refspec %s"
+msgstr "Не вдалося забрати карту отримання для визначника посилання %s"
+
+msgid "(matching)"
+msgstr ""
+
+msgid "(delete)"
+msgstr "(видалити)"
+
+#, c-format
+msgid "could not set '%s'"
+msgstr "не вдалося встановити \"%s\""
+
+#, c-format
+msgid "could not unset '%s'"
+msgstr "не вдалося скинути \"%s\""
+
+#, c-format
+msgid ""
+"The %s configuration remote.pushDefault in:\n"
+"\t%s:%d\n"
+"now names the non-existent remote '%s'"
+msgstr ""
+
+#, c-format
+msgid "No such remote: '%s'"
+msgstr "Немає такого віддаленого призначення: \"%s\""
+
+#, c-format
+msgid "Could not rename config section '%s' to '%s'"
+msgstr "Не вдалося перейменувати розділ конфігурації з \"%s\" на \"%s\""
+
+#, c-format
+msgid ""
+"Not updating non-default fetch refspec\n"
+"\t%s\n"
+"\tPlease update the configuration manually if necessary."
+msgstr ""
+
+msgid "Renaming remote references"
+msgstr ""
+
+#, c-format
+msgid "deleting '%s' failed"
+msgstr ""
+
+#, c-format
+msgid "creating '%s' failed"
+msgstr ""
+
+msgid ""
+"Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
+"to delete it, use:"
+msgid_plural ""
+"Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
+"to delete them, use:"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "Could not remove config section '%s'"
+msgstr "Не вдалося видалити секцію конфігурації \"%s\""
+
+#, c-format
+msgid " new (next fetch will store in remotes/%s)"
+msgstr ""
+
+msgid " tracked"
+msgstr " відстежується"
+
+msgid " skipped"
+msgstr ""
+
+msgid " stale (use 'git remote prune' to remove)"
+msgstr ""
+
+msgid " ???"
+msgstr ""
+
+#, c-format
+msgid "invalid branch.%s.merge; cannot rebase onto > 1 branch"
+msgstr ""
+
+#, c-format
+msgid "rebases interactively onto remote %s"
+msgstr "перебазувати інтерактивно у віддалену %s"
+
+#, c-format
+msgid "rebases interactively (with merges) onto remote %s"
+msgstr ""
+
+#, c-format
+msgid "rebases onto remote %s"
+msgstr ""
+
+#, c-format
+msgid " merges with remote %s"
+msgstr ""
+
+#, c-format
+msgid "merges with remote %s"
+msgstr ""
+
+#, c-format
+msgid "%-*s    and with remote %s\n"
+msgstr ""
+
+msgid "create"
+msgstr ""
+
+msgid "delete"
+msgstr "видалити"
+
+msgid "up to date"
+msgstr "в актуальному стані"
+
+msgid "fast-forwardable"
+msgstr ""
+
+msgid "local out of date"
+msgstr ""
+
+#, c-format
+msgid "    %-*s forces to %-*s (%s)"
+msgstr ""
+
+#, c-format
+msgid "    %-*s pushes to %-*s (%s)"
+msgstr ""
+
+#, c-format
+msgid "    %-*s forces to %s"
+msgstr ""
+
+#, c-format
+msgid "    %-*s pushes to %s"
+msgstr ""
+
+msgid "do not query remotes"
+msgstr ""
+
+#, c-format
+msgid "* remote %s"
+msgstr ""
+
+#, c-format
+msgid "  Fetch URL: %s"
+msgstr ""
+
+msgid "(no URL)"
+msgstr ""
+
+#. TRANSLATORS: the colon ':' should align
+#. with the one in " Fetch URL: %s"
+#. translation.
+#.
+
+#, c-format
+msgid "  Push  URL: %s"
+msgstr ""
+
+#, c-format
+msgid "  HEAD branch: %s"
+msgstr "  HEAD гілка: %s"
+
+msgid "(not queried)"
+msgstr ""
+
+msgid "(unknown)"
+msgstr "(невідомо)"
+
+#, c-format
+msgid ""
+"  HEAD branch (remote HEAD is ambiguous, may be one of the following):\n"
+msgstr ""
+
+#, c-format
+msgid "  Remote branch:%s"
+msgid_plural "  Remote branches:%s"
+msgstr[0] " Віддалена гілка:%s"
+msgstr[1] " Віддалені гілки:%s"
+msgstr[2] " Віддалених гілок:%s"
+
+msgid " (status not queried)"
+msgstr ""
+
+msgid "  Local branch configured for 'git pull':"
+msgid_plural "  Local branches configured for 'git pull':"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "  Local refs will be mirrored by 'git push'"
+msgstr ""
+
+#, c-format
+msgid "  Local ref configured for 'git push'%s:"
+msgid_plural "  Local refs configured for 'git push'%s:"
+msgstr[0] "  Локальне посилання налаштовано для \"git push\"%s:"
+msgstr[1] "  Локальних посилання налаштовано для \"git push\"%s:"
+msgstr[2] "  Локальних посилань налаштовано для \"git push\"%s:"
+
+msgid "set refs/remotes/<name>/HEAD according to remote"
+msgstr ""
+
+msgid "delete refs/remotes/<name>/HEAD"
+msgstr ""
+
+msgid "Cannot determine remote HEAD"
+msgstr ""
+
+msgid "Multiple remote HEAD branches. Please choose one explicitly with:"
+msgstr ""
+
+#, c-format
+msgid "Could not delete %s"
+msgstr "Не вдалося видалити %s"
+
+#, c-format
+msgid "Not a valid ref: %s"
+msgstr "Не є припустимим посиланням: %s"
+
+#, c-format
+msgid "Could not setup %s"
+msgstr "Не вдалося налаштувати %s"
+
+#, c-format
+msgid " %s will become dangling!"
+msgstr ""
+
+#, c-format
+msgid " %s has become dangling!"
+msgstr ""
+
+#, c-format
+msgid "Pruning %s"
+msgstr "Видалення %s"
+
+#, c-format
+msgid "URL: %s"
+msgstr ""
+
+#, c-format
+msgid " * [would prune] %s"
+msgstr ""
+
+#, c-format
+msgid " * [pruned] %s"
+msgstr ""
+
+msgid "prune remotes after fetching"
+msgstr ""
+
+#, c-format
+msgid "No such remote '%s'"
+msgstr "Немає такого віддаленого призначення \"%s\""
+
+msgid "add branch"
+msgstr "додати гілку"
+
+msgid "no remote specified"
+msgstr ""
+
+msgid "query push URLs rather than fetch URLs"
+msgstr ""
+
+msgid "return all URLs"
+msgstr ""
+
+#, c-format
+msgid "no URLs configured for remote '%s'"
+msgstr "не налаштовано URL-адреси для віддаленого \"%s\""
+
+msgid "manipulate push URLs"
+msgstr ""
+
+msgid "add URL"
+msgstr ""
+
+msgid "delete URLs"
+msgstr "видалити URL-адреси"
+
+msgid "--add --delete doesn't make sense"
+msgstr "--add --delete не має сенсу"
+
+#, c-format
+msgid "Invalid old URL pattern: %s"
+msgstr ""
+
+#, c-format
+msgid "No such URL found: %s"
+msgstr ""
+
+msgid "Will not delete all non-push URLs"
+msgstr ""
+
+msgid "be verbose; must be placed before a subcommand"
+msgstr ""
+
+msgid "git repack [<options>]"
+msgstr "git repack [<опції>]"
+
+msgid ""
+"Incremental repacks are incompatible with bitmap indexes.  Use\n"
+"--no-write-bitmap-index or disable the pack.writeBitmaps configuration."
+msgstr ""
+
+msgid "could not start pack-objects to repack promisor objects"
+msgstr ""
+
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr ""
+
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr ""
+
+#, c-format
+msgid "cannot open index for %s"
+msgstr "неможливо відкрити індекс для %s"
+
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr ""
+
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr ""
+
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr ""
+
+msgid "could not close refs snapshot tempfile"
+msgstr ""
+
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "не вдалося видалити застарілий bitmap: %s"
+
+msgid "pack everything in a single pack"
+msgstr ""
+
+msgid "same as -a, and turn unreachable objects loose"
+msgstr ""
+
+msgid "same as -a, pack unreachable cruft objects separately"
+msgstr ""
+
+msgid "approxidate"
+msgstr ""
+
+msgid "with --cruft, expire objects older than this"
+msgstr ""
+
+msgid "remove redundant packs, and run git-prune-packed"
+msgstr ""
+
+msgid "pass --no-reuse-delta to git-pack-objects"
+msgstr ""
+
+msgid "pass --no-reuse-object to git-pack-objects"
+msgstr ""
+
+msgid "do not run git-update-server-info"
+msgstr ""
+
+msgid "pass --local to git-pack-objects"
+msgstr ""
+
+msgid "write bitmap index"
+msgstr "записати bitmap індекс"
+
+msgid "pass --delta-islands to git-pack-objects"
+msgstr ""
+
+msgid "with -A, do not loosen objects older than this"
+msgstr ""
+
+msgid "with -a, repack unreachable objects"
+msgstr ""
+
+msgid "size of the window used for delta compression"
+msgstr ""
+
+msgid "bytes"
+msgstr ""
+
+msgid "same as the above, but limit memory size instead of entries count"
+msgstr ""
+
+msgid "limits the maximum delta depth"
+msgstr ""
+
+msgid "limits the maximum number of threads"
+msgstr ""
+
+msgid "maximum size of each packfile"
+msgstr ""
+
+msgid "repack objects in packs marked with .keep"
+msgstr ""
+
+msgid "do not repack this pack"
+msgstr ""
+
+msgid "find a geometric progression with factor <N>"
+msgstr ""
+
+msgid "write a multi-pack index of the resulting packs"
+msgstr ""
+
+msgid "pack prefix to store a pack containing pruned objects"
+msgstr ""
+
+msgid "cannot delete packs in a precious-objects repo"
+msgstr ""
+
+msgid "Nothing new to pack."
+msgstr ""
+
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "префікс пакунку %s не починається з objdir %s"
+
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr ""
+
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr ""
+
+#, c-format
+msgid "could not unlink: %s"
+msgstr "не вдалося відʼєднати %s"
+
+msgid "git replace [-f] <object> <replacement>"
+msgstr ""
+
+msgid "git replace [-f] --edit <object>"
+msgstr ""
+
+msgid "git replace [-f] --graft <commit> [<parent>...]"
+msgstr ""
+
+msgid "git replace -d <object>..."
+msgstr ""
+
+msgid "git replace [--format=<format>] [-l [<pattern>]]"
+msgstr ""
+
+#, c-format
+msgid ""
+"invalid replace format '%s'\n"
+"valid formats are 'short', 'medium' and 'long'"
+msgstr ""
+
+#, c-format
+msgid "replace ref '%s' not found"
+msgstr ""
+
+#, c-format
+msgid "Deleted replace ref '%s'"
+msgstr ""
+
+#, c-format
+msgid "'%s' is not a valid ref name"
+msgstr "\"%s\" не є припустимою назвою посилання"
+
+#, c-format
+msgid "replace ref '%s' already exists"
+msgstr "змінний ref \"%s\" вже існує"
+
+#, c-format
+msgid ""
+"Objects must be of the same type.\n"
+"'%s' points to a replaced object of type '%s'\n"
+"while '%s' points to a replacement object of type '%s'."
+msgstr ""
+
+#, c-format
+msgid "unable to open %s for writing"
+msgstr "не вдалося відкрити %s для запису"
+
+msgid "cat-file reported failure"
+msgstr ""
+
+#, c-format
+msgid "unable to open %s for reading"
+msgstr "не вдалося відкрити %s для читання"
+
+msgid "unable to spawn mktree"
+msgstr "не вдалося породити mktree"
+
+msgid "unable to read from mktree"
+msgstr "не вдалося прочитати з mktree"
+
+msgid "mktree reported failure"
+msgstr ""
+
+msgid "mktree did not return an object name"
+msgstr "mktree не повернув назву обʼєкта"
+
+#, c-format
+msgid "unable to fstat %s"
+msgstr "не вдалося виконати fstat %s"
+
+msgid "unable to write object to database"
+msgstr "не вдалося записати обʼєкт до бази даних"
+
+#, c-format
+msgid "unable to get object type for %s"
+msgstr "не вдалося отримати тип обʼєкта для %s"
+
+msgid "editing object file failed"
+msgstr ""
+
+#, c-format
+msgid "new object is the same as the old one: '%s'"
+msgstr ""
+
+#, c-format
+msgid "could not parse %s as a commit"
+msgstr "не вдалося розібрати %s як коміт"
+
+#, c-format
+msgid "bad mergetag in commit '%s'"
+msgstr "неправильний mergetag в коміті \"%s\""
+
+#, c-format
+msgid "malformed mergetag in commit '%s'"
+msgstr ""
+
+#, c-format
+msgid ""
+"original commit '%s' contains mergetag '%s' that is discarded; use --edit "
+"instead of --graft"
+msgstr ""
+
+#, c-format
+msgid "the original commit '%s' has a gpg signature"
+msgstr ""
+
+msgid "the signature will be removed in the replacement commit!"
+msgstr ""
+
+#, c-format
+msgid "could not write replacement commit for: '%s'"
+msgstr "не вдалося записати коміт заміни для: \"%s\""
+
+#, c-format
+msgid "graft for '%s' unnecessary"
+msgstr ""
+
+#, c-format
+msgid "new commit is the same as the old one: '%s'"
+msgstr ""
+
+#, c-format
+msgid ""
+"could not convert the following graft(s):\n"
+"%s"
+msgstr ""
+
+msgid "list replace refs"
+msgstr ""
+
+msgid "delete replace refs"
+msgstr "видалити змінні посилання"
+
+msgid "edit existing object"
+msgstr "редагувати існуючий обʼєкт"
+
+msgid "change a commit's parents"
+msgstr ""
+
+msgid "convert existing graft file"
+msgstr ""
+
+msgid "replace the ref if it exists"
+msgstr ""
+
+msgid "do not pretty-print contents for --edit"
+msgstr ""
+
+msgid "use this format"
+msgstr "використати цей формат"
+
+msgid "--format cannot be used when not listing"
+msgstr "--format не можна використовувати без list"
+
+msgid "-f only makes sense when writing a replacement"
+msgstr ""
+
+msgid "--raw only makes sense with --edit"
+msgstr ""
+
+msgid "-d needs at least one argument"
+msgstr ""
+
+msgid "bad number of arguments"
+msgstr ""
+
+msgid "-e needs exactly one argument"
+msgstr ""
+
+msgid "-g needs at least one argument"
+msgstr ""
+
+msgid "--convert-graft-file takes no argument"
+msgstr ""
+
+msgid "only one pattern can be given with -l"
+msgstr ""
+
+msgid ""
+"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
+msgstr ""
+
+msgid "register clean resolutions in index"
+msgstr ""
+
+msgid "'git rerere forget' without paths is deprecated"
+msgstr ""
+
+#, c-format
+msgid "unable to generate diff for '%s'"
+msgstr "не вдалося згенерувати diff для \"%s\""
+
+msgid ""
+"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
+msgstr ""
+"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
+
+msgid "git reset [-q] [<tree-ish>] [--] <pathspec>..."
+msgstr "git reset [-q] [<деревоподібне джерело>] [--] <визначник шляху>..."
+
+msgid ""
+"git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"
+msgstr ""
+"git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<деревоподібне "
+"джерело>]"
+
+msgid "git reset --patch [<tree-ish>] [--] [<pathspec>...]"
+msgstr ""
+"git reset --patch [<деревоподібне джерело>] [--] [<визначник шляху>...]"
+
+msgid "mixed"
+msgstr "змішане"
+
+msgid "soft"
+msgstr "м’яке"
+
+msgid "hard"
+msgstr "жорстке"
+
+msgid "merge"
+msgstr "злити"
+
+msgid "keep"
+msgstr "зберегти"
+
+msgid "You do not have a valid HEAD."
+msgstr "У вас немає дійсного HEAD."
+
+msgid "Failed to find tree of HEAD."
+msgstr "Не вдалося знайти дерево HEAD."
+
+#, c-format
+msgid "Failed to find tree of %s."
+msgstr "Не вдалося знайти дерево %s."
+
+#, c-format
+msgid "HEAD is now at %s"
+msgstr "HEAD зараз на %s"
+
+#, c-format
+msgid "Cannot do a %s reset in the middle of a merge."
+msgstr "Неможливо виконати %s скидання посеред злиття."
+
+msgid "be quiet, only report errors"
+msgstr "тихесенько, повідомляти лише про помилки"
+
+msgid "skip refreshing the index after reset"
+msgstr "пропустити оновлення індексу після скидання"
+
+msgid "reset HEAD and index"
+msgstr "скинути HEAD та індекс"
+
+msgid "reset only HEAD"
+msgstr "скинути тільки HEAD"
+
+msgid "reset HEAD, index and working tree"
+msgstr "скинути HEAD, індекс та робоче дерево"
+
+msgid "reset HEAD but keep local changes"
+msgstr "скинути HEAD, але зберегти локальні зміни"
+
+msgid "record only the fact that removed paths will be added later"
+msgstr "записати лише той факт, що вилучені шляхи будуть додані пізніше"
+
+#, c-format
+msgid "Failed to resolve '%s' as a valid revision."
+msgstr "Не вдалося розпізнати '%s' як припустиму ревізію."
+
+#, c-format
+msgid "Failed to resolve '%s' as a valid tree."
+msgstr "Не вдалося розпізнати '%s' як припустиме дерево."
+
+msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
+msgstr ""
+"використання --mixed зі шляхами застаріло; використовуйте 'git reset -- "
+"<paths>' замість цього."
+
+#, c-format
+msgid "Cannot do %s reset with paths."
+msgstr "Неможливо виконати %s скидання зі шляхами."
+
+#, c-format
+msgid "%s reset is not allowed in a bare repository"
+msgstr "%s скидання не дозволяється у порожньому сховищі"
+
+msgid "Unstaged changes after reset:"
+msgstr "Неіндексовані зміни після скидання:"
+
+#, c-format
+msgid ""
+"It took %.2f seconds to refresh the index after reset.  You can use\n"
+"'--no-refresh' to avoid this."
+msgstr ""
+"Оновлення індексу після скидання зайняло %.2f секунд.  Ви можете "
+"скористатися параметром\n"
+"'--no-refresh', щоб уникнути цього."
+
+#, c-format
+msgid "Could not reset index file to revision '%s'."
+msgstr "Не вдалося скинути індексний файл до ревізії '%s'."
+
+msgid "Could not write new index file."
+msgstr "Не вдалося записати новий індексний файл."
+
+#, c-format
+msgid "unable to get disk usage of %s"
+msgstr "не вдалося отримати дані про використання диска %s"
+
+#, c-format
+msgid "invalid value for '%s': '%s', the only allowed format is '%s'"
+msgstr ""
+
+msgid "rev-list does not support display of notes"
+msgstr ""
+
+#, c-format
+msgid "marked counting and '%s' cannot be used together"
+msgstr "позначений підрахунок та \"%s\" не можна використовувати разом"
+
+msgid "git rev-parse --parseopt [<options>] -- [<args>...]"
+msgstr "git rev-parse --parseopt [<опції>] -- [<аргументи>...]"
+
+msgid "keep the `--` passed as an arg"
+msgstr ""
+
+msgid "stop parsing after the first non-option argument"
+msgstr ""
+
+msgid "output in stuck long form"
+msgstr ""
+
+msgid "premature end of input"
+msgstr "передчасне закінчення вхідних даних"
+
+msgid "no usage string given before the `--' separator"
+msgstr ""
+
+msgid "missing opt-spec before option flags"
+msgstr ""
+
+msgid "Needed a single revision"
+msgstr ""
+
+msgid ""
+"git rev-parse --parseopt [<options>] -- [<args>...]\n"
+"   or: git rev-parse --sq-quote [<arg>...]\n"
+"   or: git rev-parse [<options>] [<arg>...]\n"
+"\n"
+"Run \"git rev-parse --parseopt -h\" for more information on the first usage."
+msgstr ""
+
+msgid "--resolve-git-dir requires an argument"
+msgstr ""
+
+#, c-format
+msgid "not a gitdir '%s'"
+msgstr ""
+
+msgid "--git-path requires an argument"
+msgstr ""
+
+msgid "-n requires an argument"
+msgstr "-n потребує аргумент"
+
+msgid "--path-format requires an argument"
+msgstr ""
+
+#, c-format
+msgid "unknown argument to --path-format: %s"
+msgstr ""
+
+msgid "--default requires an argument"
+msgstr ""
+
+msgid "--prefix requires an argument"
+msgstr ""
+
+#, c-format
+msgid "unknown mode for --abbrev-ref: %s"
+msgstr ""
+
+msgid "--exclude-hidden cannot be used together with --branches"
+msgstr "--exclude-hidden неможливо використати разом з --branches"
+
+msgid "--exclude-hidden cannot be used together with --tags"
+msgstr ""
+
+msgid "--exclude-hidden cannot be used together with --remotes"
+msgstr ""
+
+msgid "this operation must be run in a work tree"
+msgstr ""
+
+#, c-format
+msgid "unknown mode for --show-object-format: %s"
+msgstr ""
+
+msgid ""
+"git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] "
+"<commit>..."
+msgstr ""
+
+msgid "git revert (--continue | --skip | --abort | --quit)"
+msgstr ""
+
+msgid ""
+"git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n"
+"                [-S[<keyid>]] <commit>..."
+msgstr ""
+
+msgid "git cherry-pick (--continue | --skip | --abort | --quit)"
+msgstr "git cherry-pick (--continue | --skip | --abort | --quit)"
+
+#, c-format
+msgid "option `%s' expects a number greater than zero"
+msgstr ""
+
+#, c-format
+msgid "%s: %s cannot be used with %s"
+msgstr "%s: %s неможливо використовувати з %s"
+
+msgid "end revert or cherry-pick sequence"
+msgstr ""
+
+msgid "resume revert or cherry-pick sequence"
+msgstr ""
+
+msgid "cancel revert or cherry-pick sequence"
+msgstr ""
+
+msgid "skip current commit and continue"
+msgstr ""
+
+msgid "don't automatically commit"
+msgstr "не комітити автоматично"
+
+msgid "edit the commit message"
+msgstr ""
+
+msgid "parent-number"
+msgstr ""
+
+msgid "select mainline parent"
+msgstr ""
+
+msgid "merge strategy"
+msgstr ""
+
+msgid "option for merge strategy"
+msgstr "опція для стратегії злиття"
+
+msgid "append commit name"
+msgstr ""
+
+msgid "preserve initially empty commits"
+msgstr ""
+
+msgid "allow commits with empty messages"
+msgstr ""
+
+msgid "keep redundant, empty commits"
+msgstr ""
+
+msgid "use the 'reference' format to refer to commits"
+msgstr ""
+
+msgid "revert failed"
+msgstr "вивертання не вдалося"
+
+msgid "cherry-pick failed"
+msgstr ""
+
+msgid ""
+"git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch]\n"
+"       [--quiet] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
+"       [--] [<pathspec>...]"
+msgstr ""
+
+msgid ""
+"the following file has staged content different from both the\n"
+"file and the HEAD:"
+msgid_plural ""
+"the following files have staged content different from both the\n"
+"file and the HEAD:"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid ""
+"\n"
+"(use -f to force removal)"
+msgstr ""
+
+msgid "the following file has changes staged in the index:"
+msgid_plural "the following files have changes staged in the index:"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid ""
+"\n"
+"(use --cached to keep the file, or -f to force removal)"
+msgstr ""
+
+msgid "the following file has local modifications:"
+msgid_plural "the following files have local modifications:"
+msgstr[0] "наступний файл має локальні зміни:"
+msgstr[1] "наступні файли мають локальні зміни:"
+msgstr[2] "наступних файлів мають локальні зміни:"
+
+msgid "do not list removed files"
+msgstr ""
+
+msgid "only remove from the index"
+msgstr "видалити тільки з індексу"
+
+msgid "override the up-to-date check"
+msgstr ""
+
+msgid "allow recursive removal"
+msgstr ""
+
+msgid "exit with a zero status even if nothing matched"
+msgstr ""
+
+msgid "No pathspec was given. Which files should I remove?"
+msgstr ""
+
+msgid "please stage your changes to .gitmodules or stash them to proceed"
+msgstr ""
+
+#, c-format
+msgid "not removing '%s' recursively without -r"
+msgstr ""
+
+#, c-format
+msgid "git rm: unable to remove %s"
+msgstr "git rm: не вдалося видалити %s"
+
+msgid ""
+"git send-pack [--mirror] [--dry-run] [--force]\n"
+"              [--receive-pack=<git-receive-pack>]\n"
+"              [--verbose] [--thin] [--atomic]\n"
+"              [--[no-]signed | --signed=(true|false|if-asked)]\n"
+"              [<host>:]<directory> (--all | <ref>...)"
+msgstr ""
+
+msgid "remote name"
+msgstr "віддалена назва"
+
+msgid "push all refs"
+msgstr "надіслати всі посилання"
+
+msgid "use stateless RPC protocol"
+msgstr ""
+
+msgid "read refs from stdin"
+msgstr ""
+
+msgid "print status from remote helper"
+msgstr ""
+
+msgid "git shortlog [<options>] [<revision-range>] [[--] <path>...]"
+msgstr "git shortlog [<опції>] [<діапазон-ревізій>] [[--] <шлях>...]"
+
+msgid "git log --pretty=short | git shortlog [<options>]"
+msgstr ""
+
+msgid "using multiple --group options with stdin is not supported"
+msgstr ""
+
+#, c-format
+msgid "using %s with stdin is not supported"
+msgstr ""
+
+#, c-format
+msgid "unknown group type: %s"
+msgstr "невідомий тип групи: %s"
+
+msgid "group by committer rather than author"
+msgstr ""
+
+msgid "sort output according to the number of commits per author"
+msgstr ""
+
+msgid "suppress commit descriptions, only provides commit count"
+msgstr ""
+
+msgid "show the email address of each author"
+msgstr ""
+
+msgid "<w>[,<i1>[,<i2>]]"
+msgstr ""
+
+msgid "linewrap output"
+msgstr "обгортати рядки виводу"
+
+msgid "field"
+msgstr ""
+
+msgid "group by field"
+msgstr ""
+
+msgid "too many arguments given outside repository"
+msgstr ""
+
+msgid ""
+"git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
+"                [--current] [--color[=<when>] | --no-color] [--sparse]\n"
+"                [--more=<n> | --list | --independent | --merge-base]\n"
+"                [--no-name | --sha1-name] [--topics]\n"
+"                [(<rev> | <glob>)...]"
+msgstr ""
+
+msgid "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]"
+msgstr ""
+
+#, c-format
+msgid "ignoring %s; cannot handle more than %d ref"
+msgid_plural "ignoring %s; cannot handle more than %d refs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "no matching refs with %s"
+msgstr ""
+
+msgid "show remote-tracking and local branches"
+msgstr ""
+
+msgid "show remote-tracking branches"
+msgstr "показати віддалено відстежувані гілки"
+
+msgid "color '*!+-' corresponding to the branch"
+msgstr ""
+
+msgid "show <n> more commits after the common ancestor"
+msgstr ""
+
+msgid "synonym to more=-1"
+msgstr ""
+
+msgid "suppress naming strings"
+msgstr "не показувати назву"
+
+msgid "include the current branch"
+msgstr "включити поточну гілку"
+
+msgid "name commits with their object names"
+msgstr ""
+
+msgid "show possible merge bases"
+msgstr ""
+
+msgid "show refs unreachable from any other ref"
+msgstr ""
+
+msgid "show commits in topological order"
+msgstr ""
+
+msgid "show only commits not on the first branch"
+msgstr ""
+
+msgid "show merges reachable from only one tip"
+msgstr ""
+
+msgid "topologically sort, maintaining date order where possible"
+msgstr ""
+
+msgid "<n>[,<base>]"
+msgstr ""
+
+msgid "show <n> most recent ref-log entries starting at base"
+msgstr ""
+
+msgid "no branches given, and HEAD is not valid"
+msgstr ""
+
+msgid "--reflog option needs one branch name"
+msgstr "--reflog потребує одну назву гілки"
+
+#, c-format
+msgid "only %d entry can be shown at one time."
+msgid_plural "only %d entries can be shown at one time."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "no such ref %s"
+msgstr "немає такого посилання %s"
+
+#, c-format
+msgid "cannot handle more than %d rev."
+msgid_plural "cannot handle more than %d revs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "'%s' is not a valid ref."
+msgstr "\"%s\" не є припустимим посиланням."
+
+#, c-format
+msgid "cannot find commit %s (%s)"
+msgstr ""
+
+msgid "hash-algorithm"
+msgstr "хеш-алгоритм"
+
+msgid "Unknown hash algorithm"
+msgstr "Невідомий хеш-алгоритм"
+
+msgid ""
+"git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference]\n"
+"             [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n"
+"             [--heads] [--] [<pattern>...]"
+msgstr ""
+
+msgid "git show-ref --exclude-existing[=<pattern>]"
+msgstr ""
+
+msgid "only show tags (can be combined with heads)"
+msgstr "показати тільки теги (можна комбінувати з heads)"
+
+msgid "only show heads (can be combined with tags)"
+msgstr "показати тільки верхівки (можна комбінувати з tags)"
+
+msgid "stricter reference checking, requires exact ref path"
+msgstr ""
+
+msgid "show the HEAD reference, even if it would be filtered out"
+msgstr ""
+
+msgid "dereference tags into object IDs"
+msgstr "розіменувати теги в ідентифікатори обʼєктів"
+
+msgid "only show SHA1 hash using <n> digits"
+msgstr ""
+
+msgid "do not print results to stdout (useful with --verify)"
+msgstr ""
+
+msgid "show refs from stdin that aren't in local repository"
+msgstr "показати посилання з stdin, яких немає в локальному сховищі"
+
+msgid ""
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
+msgstr ""
+
+msgid "this worktree is not sparse"
+msgstr ""
+
+msgid "this worktree is not sparse (sparse-checkout file may not exist)"
+msgstr ""
+
+#, c-format
+msgid ""
+"directory '%s' contains untracked files, but is not in the sparse-checkout "
+"cone"
+msgstr ""
+
+#, c-format
+msgid "failed to remove directory '%s'"
+msgstr "не вдалося видалити директорію \"%s\""
+
+msgid "failed to create directory for sparse-checkout file"
+msgstr "не вдалося створити директорію для файлу часткового переходу"
+
+msgid "failed to initialize worktree config"
+msgstr "не вдалося ініціалізувати конфігурацію робочого дерева"
+
+msgid "failed to modify sparse-index config"
+msgstr "не вдалося змінити sparse-index конфігурацію"
+
+msgid "initialize the sparse-checkout in cone mode"
+msgstr "ініціалізувати частковий перехід в режимі конуса"
+
+msgid "toggle the use of a sparse index"
+msgstr ""
+
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "не вдалося створити провідні директорії %s"
+
+#, c-format
+msgid "failed to open '%s'"
+msgstr "не вдалося відкрити \"%s\""
+
+#, c-format
+msgid "could not normalize path %s"
+msgstr "не вдалося нормалізувати шлях %s"
+
+#, c-format
+msgid "unable to unquote C-style string '%s'"
+msgstr ""
+
+msgid "unable to load existing sparse-checkout patterns"
+msgstr "не вдалося завантажити існуючі шаблони часткових переходів"
+
+msgid "existing sparse-checkout patterns do not use cone mode"
+msgstr ""
+
+msgid "please run from the toplevel directory in non-cone mode"
+msgstr ""
+
+msgid "specify directories rather than patterns (no leading slash)"
+msgstr ""
+
+msgid ""
+"specify directories rather than patterns.  If your directory starts with a "
+"'!', pass --skip-checks"
+msgstr ""
+
+msgid ""
+"specify directories rather than patterns.  If your directory really has any "
+"of '*?[]\\' in it, pass --skip-checks"
+msgstr ""
+
+#, c-format
+msgid ""
+"'%s' is not a directory; to treat it as a directory anyway, rerun with --"
+"skip-checks"
+msgstr ""
+
+#, c-format
+msgid ""
+"pass a leading slash before paths such as '%s' if you want a single file "
+"(see NON-CONE PROBLEMS in the git-sparse-checkout manual)."
+msgstr ""
+
+msgid "git sparse-checkout add [--skip-checks] (--stdin | <patterns>)"
+msgstr ""
+
+msgid ""
+"skip some sanity checks on the given paths that might give false positives"
+msgstr ""
+
+msgid "read patterns from standard in"
+msgstr ""
+
+msgid "no sparse-checkout to add to"
+msgstr ""
+
+msgid ""
+"git sparse-checkout set [--[no-]cone] [--[no-]sparse-index] [--skip-checks] "
+"(--stdin | <patterns>)"
+msgstr ""
+
+msgid "must be in a sparse-checkout to reapply sparsity patterns"
+msgstr ""
+
+msgid "error while refreshing working directory"
+msgstr "помилка під час оновлення робочої директорії"
+
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+
+msgid "terminate input and output files by a NUL character"
+msgstr ""
+
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr ""
+
+msgid "use patterns in <file> instead of the current ones."
+msgstr "використовувати шаблони з <file> замість поточних."
+
+msgid "git stash list [<log-options>]"
+msgstr "git stash list [<лог-опції>]"
+
+msgid ""
+"git stash show [-u | --include-untracked | --only-untracked] [<diff-"
+"options>] [<stash>]"
+msgstr ""
+
+msgid "git stash drop [-q | --quiet] [<stash>]"
+msgstr ""
+
+msgid "git stash pop [--index] [-q | --quiet] [<stash>]"
+msgstr ""
+
+msgid "git stash apply [--index] [-q | --quiet] [<stash>]"
+msgstr ""
+
+msgid "git stash branch <branchname> [<stash>]"
+msgstr ""
+
+msgid "git stash store [(-m | --message) <message>] [-q | --quiet] <commit>"
+msgstr ""
+
+msgid ""
+"git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q "
+"| --quiet]\n"
+"          [-u | --include-untracked] [-a | --all] [(-m | --message) "
+"<message>]\n"
+"          [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
+"          [--] [<pathspec>...]]"
+msgstr ""
+
+msgid ""
+"git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | "
+"--quiet]\n"
+"          [-u | --include-untracked] [-a | --all] [<message>]"
+msgstr ""
+
+msgid "git stash create [<message>]"
+msgstr ""
+
+#, c-format
+msgid "'%s' is not a stash-like commit"
+msgstr "\"%s\" не є сховоподібним комітом"
+
+#, c-format
+msgid "Too many revisions specified:%s"
+msgstr ""
+
+msgid "No stash entries found."
+msgstr ""
+
+#, c-format
+msgid "%s is not a valid reference"
+msgstr "%s не є припустимим посиланням"
+
+msgid "git stash clear with arguments is unimplemented"
+msgstr ""
+
+#, c-format
+msgid ""
+"WARNING: Untracked file in way of tracked file!  Renaming\n"
+"            %s -> %s\n"
+"         to make room.\n"
+msgstr ""
+
+msgid "cannot apply a stash in the middle of a merge"
+msgstr "неможливо застосувати схов посеред злиття"
+
+#, c-format
+msgid "could not generate diff %s^!."
+msgstr "не вдалося згенерувати різницю %s^!."
+
+msgid "conflicts in index. Try without --index."
+msgstr ""
+
+msgid "could not save index tree"
+msgstr "не вдалося зберегти дерево індекса"
+
+#, c-format
+msgid "Merging %s with %s"
+msgstr ""
+
+msgid "Index was not unstashed."
+msgstr ""
+
+msgid "could not restore untracked files from stash"
+msgstr "не вдалося відновити невідстежувані файли зі схову"
+
+msgid "attempt to recreate the index"
+msgstr "спроба відтворити індекс"
+
+#, c-format
+msgid "Dropped %s (%s)"
+msgstr ""
+
+#, c-format
+msgid "%s: Could not drop stash entry"
+msgstr ""
+
+#, c-format
+msgid "'%s' is not a stash reference"
+msgstr "\"%s\" не є посиланням схова"
+
+msgid "The stash entry is kept in case you need it again."
+msgstr ""
+
+msgid "No branch name specified"
+msgstr ""
+
+msgid "failed to parse tree"
+msgstr "не вдалося розібрати дерево"
+
+msgid "failed to unpack trees"
+msgstr "не вдалося розпакувати дерева"
+
+msgid "include untracked files in the stash"
+msgstr "в тому числі невідстежувані файли схову"
+
+msgid "only show untracked files in the stash"
+msgstr "показувати тільки невідстежувані файли схову"
+
+#, c-format
+msgid "Cannot update %s with %s"
+msgstr "Неможливо оновити %s з %s"
+
+msgid "stash message"
+msgstr ""
+
+msgid "\"git stash store\" requires one <commit> argument"
+msgstr ""
+
+msgid "No staged changes"
+msgstr "Немає індексованих змін"
+
+msgid "No changes selected"
+msgstr "Не обрано жодних змін"
+
+msgid "You do not have the initial commit yet"
+msgstr "У вас ще немає початкового коміту"
+
+msgid "Cannot save the current index state"
+msgstr "Неможливо зберегти поточний стан індексу"
+
+msgid "Cannot save the untracked files"
+msgstr "Неможливо зберегти невідстежувані файли"
+
+msgid "Cannot save the current worktree state"
+msgstr ""
+
+msgid "Cannot save the current staged state"
+msgstr "Неможливо зберегти поточний індексований стан"
+
+msgid "Cannot record working tree state"
+msgstr "Неможливо записати стан робочого дерева"
+
+msgid "Can't use --patch and --include-untracked or --all at the same time"
+msgstr ""
+"Не можна використовувати --patch і --include-untracked або --all одночасно"
+
+msgid "Can't use --staged and --include-untracked or --all at the same time"
+msgstr ""
+
+msgid "Did you forget to 'git add'?"
+msgstr ""
+
+msgid "No local changes to save"
+msgstr ""
+
+msgid "Cannot initialize stash"
+msgstr "Неможливо ініціалізувати схов"
+
+msgid "Cannot save the current status"
+msgstr ""
+
+#, c-format
+msgid "Saved working directory and index state %s"
+msgstr ""
+
+msgid "Cannot remove worktree changes"
+msgstr ""
+
+msgid "keep index"
+msgstr ""
+
+msgid "stash staged changes only"
+msgstr ""
+
+msgid "stash in patch mode"
+msgstr ""
+
+msgid "quiet mode"
+msgstr ""
+
+msgid "include untracked files in stash"
+msgstr "в тому числі невідстежувані файли схову"
+
+msgid "include ignore files"
+msgstr "в тому числи файли ігнорування"
+
+msgid "skip and remove all lines starting with comment character"
+msgstr ""
+
+msgid "prepend comment character and space to each line"
+msgstr ""
+
+#, c-format
+msgid "Expecting a full ref name, got %s"
+msgstr ""
+
+#, c-format
+msgid "could not get a repository handle for submodule '%s'"
+msgstr ""
+
+#, c-format
+msgid ""
+"could not look up configuration '%s'. Assuming this repository is its own "
+"authoritative upstream."
+msgstr ""
+
+#, c-format
+msgid "No url found for submodule path '%s' in .gitmodules"
+msgstr ""
+
+#, c-format
+msgid "Entering '%s'\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"run_command returned non-zero status for %s\n"
+"."
+msgstr ""
+
+#, c-format
+msgid ""
+"run_command returned non-zero status while recursing in the nested "
+"submodules of %s\n"
+"."
+msgstr ""
+
+msgid "suppress output of entering each submodule command"
+msgstr ""
+
+msgid "recurse into nested submodules"
+msgstr "рекурсивно у вкладених підмодулях"
+
+msgid "git submodule foreach [--quiet] [--recursive] [--] <command>"
+msgstr ""
+
+#, c-format
+msgid "Failed to register url for submodule path '%s'"
+msgstr "Не вдалося зареєструвати url для підмодуля за шляхом \"%s\""
+
+#, c-format
+msgid "Submodule '%s' (%s) registered for path '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "warning: command update mode suggested for submodule '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "Failed to register update mode for submodule path '%s'"
+msgstr ""
+"Не вдалося зареєструвати режим оновлення для підмодуля за шляхом \"%s\""
+
+msgid "suppress output for initializing a submodule"
+msgstr ""
+
+msgid "git submodule init [<options>] [<path>]"
+msgstr "git submodule init [<опції>] [<шлях>]"
+
+#, c-format
+msgid "no submodule mapping found in .gitmodules for path '%s'"
+msgstr ""
+
+#, c-format
+msgid "could not resolve HEAD ref inside the submodule '%s'"
+msgstr ""
+
+#, c-format
+msgid "failed to recurse into submodule '%s'"
+msgstr "не вдалося обробити рекурсивно підмодуль \"%s\""
+
+msgid "suppress submodule status output"
+msgstr ""
+
+msgid ""
+"use commit stored in the index instead of the one stored in the submodule "
+"HEAD"
+msgstr ""
+
+msgid "git submodule status [--quiet] [--cached] [--recursive] [<path>...]"
+msgstr ""
+
+#, c-format
+msgid "* %s %s(blob)->%s(submodule)"
+msgstr ""
+
+#, c-format
+msgid "* %s %s(submodule)->%s(blob)"
+msgstr ""
+
+#, c-format
+msgid "%s"
+msgstr ""
+
+#, c-format
+msgid "couldn't hash object from '%s'"
+msgstr "не вдалося хешувати обʼєкт з \"%s\""
+
+#, c-format
+msgid "unexpected mode %o\n"
+msgstr ""
+
+msgid "use the commit stored in the index instead of the submodule HEAD"
+msgstr "використати коміт, збережений в індексі, замість підмодуля HEAD"
+
+msgid "compare the commit in the index with that in the submodule HEAD"
+msgstr ""
+
+msgid "skip submodules with 'ignore_config' value set to 'all'"
+msgstr ""
+
+msgid "limit the summary size"
+msgstr ""
+
+msgid "git submodule summary [<options>] [<commit>] [--] [<path>]"
+msgstr ""
+
+msgid "could not fetch a revision for HEAD"
+msgstr ""
+
+#, c-format
+msgid "Synchronizing submodule url for '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "failed to register url for submodule path '%s'"
+msgstr "не вдалося зареєструвати url для підмодуля за шляхом \"%s\""
+
+#, c-format
+msgid "failed to update remote for submodule '%s'"
+msgstr "не вдалося оновити віддалене призначення для підмодуля \"%s\""
+
+msgid "suppress output of synchronizing submodule url"
+msgstr ""
+
+msgid "git submodule sync [--quiet] [--recursive] [<path>]"
+msgstr ""
+
+#, c-format
+msgid ""
+"Submodule work tree '%s' contains a .git directory. This will be replaced "
+"with a .git file by using absorbgitdirs."
+msgstr ""
+
+#, c-format
+msgid ""
+"Submodule work tree '%s' contains local modifications; use '-f' to discard "
+"them"
+msgstr ""
+
+#, c-format
+msgid "Cleared directory '%s'\n"
+msgstr "Очищено директорію \"%s\"\n"
+
+#, c-format
+msgid "Could not remove submodule work tree '%s'\n"
+msgstr "Не вдалося видалити робоче дерево підмодуля \"%s\"\n"
+
+#, c-format
+msgid "could not create empty submodule directory %s"
+msgstr "не вдалося створити порожню директорію підмодуля %s"
+
+#, c-format
+msgid "Submodule '%s' (%s) unregistered for path '%s'\n"
+msgstr ""
+
+msgid "remove submodule working trees even if they contain local changes"
+msgstr ""
+
+msgid "unregister all submodules"
+msgstr ""
+
+msgid ""
+"git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"
+msgstr ""
+
+msgid "Use '--all' if you really want to deinitialize all submodules"
+msgstr ""
+
+msgid ""
+"An alternate computed from a superproject's alternate is invalid.\n"
+"To allow Git to clone without an alternate in such a case, set\n"
+"submodule.alternateErrorStrategy to 'info' or, equivalently, clone with\n"
+"'--reference-if-able' instead of '--reference'."
+msgstr ""
+
+#, c-format
+msgid "could not get a repository handle for gitdir '%s'"
+msgstr "не вдалося отримати дескриптор сховища для gitdir \"%s\""
+
+#, c-format
+msgid "submodule '%s' cannot add alternate: %s"
+msgstr "підмодуль \"%s\" не може додати спільний обʼєкт: %s"
+
+#, c-format
+msgid "Value '%s' for submodule.alternateErrorStrategy is not recognized"
+msgstr ""
+
+#, c-format
+msgid "Value '%s' for submodule.alternateLocation is not recognized"
+msgstr ""
+
+#, c-format
+msgid "refusing to create/use '%s' in another submodule's git dir"
+msgstr ""
+
+#, c-format
+msgid "clone of '%s' into submodule path '%s' failed"
+msgstr ""
+
+#, c-format
+msgid "directory not empty: '%s'"
+msgstr ""
+
+#, c-format
+msgid "could not get submodule directory for '%s'"
+msgstr "не вдалося отримати директорію підмодуля для \"%s\""
+
+msgid "alternative anchor for relative paths"
+msgstr ""
+
+msgid "where the new submodule will be cloned to"
+msgstr "куди буде клоновано новий підмодуль"
+
+msgid "name of the new submodule"
+msgstr ""
+
+msgid "url where to clone the submodule from"
+msgstr ""
+
+msgid "depth for shallow clones"
+msgstr ""
+
+msgid "force cloning progress"
+msgstr "примусово звітувати прогрес клонування"
+
+msgid "disallow cloning into non-empty directory"
+msgstr ""
+
+msgid ""
+"git submodule--helper clone [--prefix=<path>] [--quiet] [--reference "
+"<repository>] [--name <name>] [--depth <depth>] [--single-branch] [--filter "
+"<filter-spec>] --url <url> --path <path>"
+msgstr ""
+
+#, c-format
+msgid "Invalid update mode '%s' configured for submodule path '%s'"
+msgstr ""
+"Неприпустимий режим оновлення \"%s\" налаштовано для підмодуля за шляхом "
+"\"%s\""
+
+#, c-format
+msgid "Submodule path '%s' not initialized"
+msgstr ""
+
+msgid "Maybe you want to use 'update --init'?"
+msgstr ""
+
+#, c-format
+msgid "Skipping unmerged submodule %s"
+msgstr ""
+
+#, c-format
+msgid "Skipping submodule '%s'"
+msgstr ""
+
+#, c-format
+msgid "Failed to clone '%s'. Retry scheduled"
+msgstr ""
+
+#, c-format
+msgid "Failed to clone '%s' a second time, aborting"
+msgstr ""
+
+#, c-format
+msgid "Unable to checkout '%s' in submodule path '%s'"
+msgstr ""
+
+#, c-format
+msgid "Unable to rebase '%s' in submodule path '%s'"
+msgstr "Не вдалося перебазувати \"%s\" в підмодулі за шляхом \"%s\""
+
+#, c-format
+msgid "Unable to merge '%s' in submodule path '%s'"
+msgstr "Не вдалося злити \"%s\" в підмодулі за шляхом \"%s\""
+
+#, c-format
+msgid "Execution of '%s %s' failed in submodule path '%s'"
+msgstr ""
+
+#, c-format
+msgid "Submodule path '%s': checked out '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "Submodule path '%s': rebased into '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "Submodule path '%s': merged in '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "Submodule path '%s': '%s %s'\n"
+msgstr ""
+
+#, c-format
+msgid "Unable to fetch in submodule path '%s'; trying to directly fetch %s:"
+msgstr ""
+
+#, c-format
+msgid ""
+"Fetched in submodule path '%s', but it did not contain %s. Direct fetching "
+"of that commit failed."
+msgstr ""
+
+#, c-format
+msgid "could not initialize submodule at path '%s'"
+msgstr "не вдалося ініціалізувати підмодуль за шляхом \"%s\""
+
+#, c-format
+msgid ""
+"Submodule (%s) branch configured to inherit branch from superproject, but "
+"the superproject is not on any branch"
+msgstr ""
+
+#, c-format
+msgid "Unable to find current revision in submodule path '%s'"
+msgstr ""
+
+#, c-format
+msgid "Unable to fetch in submodule path '%s'"
+msgstr ""
+
+#, c-format
+msgid "Unable to find %s revision in submodule path '%s'"
+msgstr ""
+
+#, c-format
+msgid "Failed to recurse into submodule path '%s'"
+msgstr "Не вдалося обробити рекурсивно підмодуль за шляхом \"%s\""
+
+msgid "force checkout updates"
+msgstr "переключитися на оновлення примусово"
+
+msgid "initialize uninitialized submodules before update"
+msgstr "ініціалізувати неініціалізовані підмодулі перед оновленням"
+
+msgid "use SHA-1 of submodule's remote tracking branch"
+msgstr "використовувати SHA-1 гілки віддаленого відстежування підмодуля"
+
+msgid "traverse submodules recursively"
+msgstr ""
+
+msgid "don't fetch new objects from the remote site"
+msgstr ""
+
+msgid "use the 'checkout' update strategy (default)"
+msgstr ""
+
+msgid "use the 'merge' update strategy"
+msgstr ""
+
+msgid "use the 'rebase' update strategy"
+msgstr ""
+
+msgid "create a shallow clone truncated to the specified number of revisions"
+msgstr "створити поверхневий клон, урізаний до вказаної кількості ревізій"
+
+msgid "parallel jobs"
+msgstr ""
+
+msgid "whether the initial clone should follow the shallow recommendation"
+msgstr ""
+
+msgid "don't print cloning progress"
+msgstr ""
+
+msgid "disallow cloning into non-empty directory, implies --init"
+msgstr ""
+
+msgid ""
+"git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] "
+"[-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-"
+"shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] "
+"[--] [<path>...]"
+msgstr ""
+
+msgid "git submodule absorbgitdirs [<options>] [<path>...]"
+msgstr "git submodule absorbgitdirs [<опції>] [<шлях>...]"
+
+msgid "suppress output for setting url of a submodule"
+msgstr ""
+
+msgid "git submodule set-url [--quiet] <path> <newurl>"
+msgstr ""
+
+msgid "set the default tracking branch to master"
+msgstr ""
+
+msgid "set the default tracking branch"
+msgstr "встановити гілку відстежування за замовчуванням"
+
+msgid "git submodule set-branch [-q|--quiet] (-d|--default) <path>"
+msgstr ""
+
+msgid "git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>"
+msgstr ""
+
+msgid "--branch or --default required"
+msgstr ""
+
+msgid "print only error messages"
+msgstr ""
+
+msgid "force creation"
+msgstr ""
+
+msgid "show whether the branch would be created"
+msgstr ""
+
+msgid ""
+"git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--"
+"quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>"
+msgstr ""
+
+#, c-format
+msgid "creating branch '%s'"
+msgstr "створення гілки \"%s\""
+
+#, c-format
+msgid "Adding existing repo at '%s' to the index\n"
+msgstr ""
+
+#, c-format
+msgid "'%s' already exists and is not a valid git repo"
+msgstr "\"%s\" вже існує і не є припустимим git сховищем"
+
+#, c-format
+msgid "A git directory for '%s' is found locally with remote(s):\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"If you want to reuse this local git directory instead of cloning again from\n"
+"  %s\n"
+"use the '--force' option. If the local git directory is not the correct "
+"repo\n"
+"or you are unsure what this means choose another name with the '--name' "
+"option."
+msgstr ""
+
+#, c-format
+msgid "Reactivating local git directory for submodule '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "unable to checkout submodule '%s'"
+msgstr "не вдалося переключитись на підмодуль \"%s\""
+
+msgid "please make sure that the .gitmodules file is in the working tree"
+msgstr ""
+
+#, c-format
+msgid "Failed to add submodule '%s'"
+msgstr "Не вдалося додати підмодуль \"%s\""
+
+#, c-format
+msgid "Failed to register submodule '%s'"
+msgstr "Не вдалося зареєструвати підмодуль \"%s\""
+
+#, c-format
+msgid "'%s' already exists in the index"
+msgstr ""
+
+#, c-format
+msgid "'%s' already exists in the index and is not a submodule"
+msgstr ""
+
+#, c-format
+msgid "'%s' does not have a commit checked out"
+msgstr "\"%s\" не має активного коміту"
+
+msgid "branch of repository to add as submodule"
+msgstr ""
+
+msgid "allow adding an otherwise ignored submodule path"
+msgstr ""
+
+msgid "borrow the objects from reference repositories"
+msgstr ""
+
+msgid ""
+"sets the submodule's name to the given string instead of defaulting to its "
+"path"
+msgstr ""
+
+msgid "git submodule add [<options>] [--] <repository> [<path>]"
+msgstr "git submodule add [<опції>] [--] <сховище> [<шлях>]"
+
+msgid "Relative path can only be used from the toplevel of the working tree"
+msgstr ""
+
+#, c-format
+msgid "repo URL: '%s' must be absolute or begin with ./|../"
+msgstr ""
+
+#, c-format
+msgid "'%s' is not a valid submodule name"
+msgstr "\"%s\" не є припустимою назвою підмодуля"
+
+msgid "git submodule--helper <command>"
+msgstr ""
+
+msgid "git symbolic-ref [-m <reason>] <name> <ref>"
+msgstr ""
+
+msgid "git symbolic-ref [-q] [--short] [--no-recurse] <name>"
+msgstr ""
+
+msgid "git symbolic-ref --delete [-q] <name>"
+msgstr ""
+
+msgid "suppress error message for non-symbolic (detached) refs"
+msgstr ""
+
+msgid "delete symbolic ref"
+msgstr "видалити символьне посилання"
+
+msgid "shorten ref output"
+msgstr ""
+
+msgid "recursively dereference (default)"
+msgstr "рекурсивне розіменування (за замовчуванням)"
+
+msgid "reason"
+msgstr ""
+
+msgid "reason of the update"
+msgstr ""
+
+msgid ""
+"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n"
+"        <tagname> [<commit> | <object>]"
+msgstr ""
+
+msgid "git tag -d <tagname>..."
+msgstr ""
+
+msgid ""
+"git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]\n"
+"        [--points-at <object>] [--column[=<options>] | --no-column]\n"
+"        [--create-reflog] [--sort=<key>] [--format=<format>]\n"
+"        [--merged <commit>] [--no-merged <commit>] [<pattern>...]"
+msgstr ""
+
+msgid "git tag -v [--format=<format>] <tagname>..."
+msgstr ""
+
+#, c-format
+msgid "tag '%s' not found."
+msgstr ""
+
+#, c-format
+msgid "Deleted tag '%s' (was %s)\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"\n"
+"Write a message for tag:\n"
+"  %s\n"
+"Lines starting with '%c' will be ignored.\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"\n"
+"Write a message for tag:\n"
+"  %s\n"
+"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"want to.\n"
+msgstr ""
+
+msgid "unable to sign the tag"
+msgstr "не вдалося підписати тег"
+
+#, c-format
+msgid ""
+"You have created a nested tag. The object referred to by your new tag is\n"
+"already a tag. If you meant to tag the object that it points to, use:\n"
+"\n"
+"\tgit tag -f %s %s^{}"
+msgstr ""
+
+msgid "bad object type."
+msgstr "невірний тип обʼєкта."
+
+msgid "no tag message?"
+msgstr ""
+
+#, c-format
+msgid "The tag message has been left in %s\n"
+msgstr ""
+
+msgid "list tag names"
+msgstr ""
+
+msgid "print <n> lines of each tag message"
+msgstr ""
+
+msgid "delete tags"
+msgstr "видалити теги"
+
+msgid "verify tags"
+msgstr ""
+
+msgid "Tag creation options"
+msgstr ""
+
+msgid "annotated tag, needs a message"
+msgstr ""
+
+msgid "tag message"
+msgstr ""
+
+msgid "force edit of tag message"
+msgstr ""
+
+msgid "annotated and GPG-signed tag"
+msgstr ""
+
+msgid "use another key to sign the tag"
+msgstr ""
+
+msgid "replace the tag if exists"
+msgstr ""
+
+msgid "create a reflog"
+msgstr "створити reflog"
+
+msgid "Tag listing options"
+msgstr ""
+
+msgid "show tag list in columns"
+msgstr ""
+
+msgid "print only tags that contain the commit"
+msgstr ""
+
+msgid "print only tags that don't contain the commit"
+msgstr ""
+
+msgid "print only tags that are merged"
+msgstr ""
+
+msgid "print only tags that are not merged"
+msgstr ""
+
+msgid "print only tags of the object"
+msgstr ""
+
+#, c-format
+msgid "the '%s' option is only allowed in list mode"
+msgstr ""
+
+#, c-format
+msgid "'%s' is not a valid tag name."
+msgstr "\"%s\" не є припустимою назвою тега."
+
+#, c-format
+msgid "tag '%s' already exists"
+msgstr "тег \"%s\" вже існує"
+
+#, c-format
+msgid "Invalid cleanup mode %s"
+msgstr "Неприпустимий режим очищення %s"
+
+#, c-format
+msgid "Updated tag '%s' (was %s)\n"
+msgstr ""
+
+msgid "pack exceeds maximum allowed size"
+msgstr "пакунок перевищує максимально дозволений розмір"
+
+msgid "failed to write object in stream"
+msgstr "не вдалося записати обʼєкт потоку"
+
+#, c-format
+msgid "inflate returned (%d)"
+msgstr "розпаковувач повернув (%d)"
+
+msgid "invalid blob object from stream"
+msgstr "неприпустимий обʼєкт blob з потоку"
+
+msgid "Unpacking objects"
+msgstr "Розпакування обʼєктів"
+
+#, c-format
+msgid "failed to create directory %s"
+msgstr "не вдалося створити директорію %s"
+
+#, c-format
+msgid "failed to delete file %s"
+msgstr "не вдалося видалити файл %s"
+
+#, c-format
+msgid "failed to delete directory %s"
+msgstr "не вдалося видалити директорію %s"
+
+#, c-format
+msgid "Testing mtime in '%s' "
+msgstr ""
+
+msgid "directory stat info does not change after adding a new file"
+msgstr ""
+
+msgid "directory stat info does not change after adding a new directory"
+msgstr ""
+
+msgid "directory stat info changes after updating a file"
+msgstr ""
+
+msgid "directory stat info changes after adding a file inside subdirectory"
+msgstr ""
+
+msgid "directory stat info does not change after deleting a file"
+msgstr ""
+
+msgid "directory stat info does not change after deleting a directory"
+msgstr ""
+
+msgid " OK"
+msgstr ""
+
+msgid "git update-index [<options>] [--] [<file>...]"
+msgstr "git update-index [<опції>] [--] [<файл>...]"
+
+msgid "continue refresh even when index needs update"
+msgstr ""
+
+msgid "refresh: ignore submodules"
+msgstr "оновити: ігнорувати підмодулі"
+
+msgid "do not ignore new files"
+msgstr "не ігнорувати нові файли"
+
+msgid "let files replace directories and vice-versa"
+msgstr ""
+
+msgid "notice files missing from worktree"
+msgstr ""
+
+msgid "refresh even if index contains unmerged entries"
+msgstr ""
+
+msgid "refresh stat information"
+msgstr ""
+
+msgid "like --refresh, but ignore assume-unchanged setting"
+msgstr ""
+
+msgid "<mode>,<object>,<path>"
+msgstr ""
+
+msgid "add the specified entry to the index"
+msgstr "додати вказаний запис до індексу"
+
+msgid "mark files as \"not changing\""
+msgstr ""
+
+msgid "clear assumed-unchanged bit"
+msgstr ""
+
+msgid "mark files as \"index-only\""
+msgstr ""
+
+msgid "clear skip-worktree bit"
+msgstr ""
+
+msgid "do not touch index-only entries"
+msgstr ""
+
+msgid "add to index only; do not add content to object database"
+msgstr ""
+
+msgid "remove named paths even if present in worktree"
+msgstr ""
+
+msgid "with --stdin: input lines are terminated by null bytes"
+msgstr ""
+
+msgid "read list of paths to be updated from standard input"
+msgstr ""
+
+msgid "add entries from standard input to the index"
+msgstr ""
+
+msgid "repopulate stages #2 and #3 for the listed paths"
+msgstr ""
+
+msgid "only update entries that differ from HEAD"
+msgstr ""
+
+msgid "ignore files missing from worktree"
+msgstr ""
+
+msgid "report actions to standard output"
+msgstr ""
+
+msgid "(for porcelains) forget saved unresolved conflicts"
+msgstr ""
+
+msgid "write index in this format"
+msgstr ""
+
+msgid "enable or disable split index"
+msgstr ""
+
+msgid "enable/disable untracked cache"
+msgstr ""
+
+msgid "test if the filesystem supports untracked cache"
+msgstr ""
+
+msgid "enable untracked cache without testing the filesystem"
+msgstr ""
+
+msgid "write out the index even if is not flagged as changed"
+msgstr ""
+
+msgid "enable or disable file system monitor"
+msgstr ""
+
+msgid "mark files as fsmonitor valid"
+msgstr ""
+
+msgid "clear fsmonitor valid bit"
+msgstr ""
+
+msgid ""
+"core.splitIndex is set to false; remove or change it, if you really want to "
+"enable split index"
+msgstr ""
+
+msgid ""
+"core.splitIndex is set to true; remove or change it, if you really want to "
+"disable split index"
+msgstr ""
+
+msgid ""
+"core.untrackedCache is set to true; remove or change it, if you really want "
+"to disable the untracked cache"
+msgstr ""
+
+msgid "Untracked cache disabled"
+msgstr "Невідстежуваний кеш вимкнено"
+
+msgid ""
+"core.untrackedCache is set to false; remove or change it, if you really want "
+"to enable the untracked cache"
+msgstr ""
+
+#, c-format
+msgid "Untracked cache enabled for '%s'"
+msgstr "Увімкнено невідстежуваний кеш для \"%s\""
+
+msgid "core.fsmonitor is unset; set it if you really want to enable fsmonitor"
+msgstr ""
+
+msgid "fsmonitor enabled"
+msgstr ""
+
+msgid ""
+"core.fsmonitor is set; remove it if you really want to disable fsmonitor"
+msgstr ""
+
+msgid "fsmonitor disabled"
+msgstr ""
+
+msgid "git update-ref [<options>] -d <refname> [<old-val>]"
+msgstr "git update-ref [<опції>] -d <назва посилання> [<старе значення>]"
+
+msgid "git update-ref [<options>]    <refname> <new-val> [<old-val>]"
+msgstr ""
+
+msgid "git update-ref [<options>] --stdin [-z]"
+msgstr ""
+
+msgid "delete the reference"
+msgstr "видалити посилання"
+
+msgid "update <refname> not the one it points to"
+msgstr ""
+
+msgid "stdin has NUL-terminated arguments"
+msgstr ""
+
+msgid "read updates from stdin"
+msgstr ""
+
+msgid "update the info files from scratch"
+msgstr "оновити інформаційні файли з чистого аркуша"
+
+msgid ""
+"git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n"
+"                [--advertise-refs] <directory>"
+msgstr ""
+
+msgid "quit after a single request/response exchange"
+msgstr ""
+
+msgid "serve up the info/refs for git-http-backend"
+msgstr ""
+
+msgid "do not try <directory>/.git/ if <directory> is no Git directory"
+msgstr ""
+
+msgid "interrupt transfer after <n> seconds of inactivity"
+msgstr ""
+
+msgid "git verify-commit [-v | --verbose] [--raw] <commit>..."
+msgstr ""
+
+msgid "print commit contents"
+msgstr ""
+
+msgid "print raw gpg status output"
+msgstr ""
+
+msgid "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..."
+msgstr ""
+
+msgid "verbose"
+msgstr ""
+
+msgid "show statistics only"
+msgstr ""
+
+msgid "git verify-tag [-v | --verbose] [--format=<format>] [--raw] <tag>..."
+msgstr ""
+
+msgid "print tag contents"
+msgstr ""
+
+msgid ""
+"git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]\n"
+"                 [-b <new-branch>] <path> [<commit-ish>]"
+msgstr ""
+
+msgid "git worktree list [-v | --porcelain [-z]]"
+msgstr ""
+
+msgid "git worktree lock [--reason <string>] <worktree>"
+msgstr ""
+
+msgid "git worktree move <worktree> <new-path>"
+msgstr ""
+
+msgid "git worktree prune [-n] [-v] [--expire <expire>]"
+msgstr ""
+
+msgid "git worktree remove [-f] <worktree>"
+msgstr ""
+
+msgid "git worktree repair [<path>...]"
+msgstr ""
+
+msgid "git worktree unlock <worktree>"
+msgstr ""
+
+#, c-format
+msgid "Removing %s/%s: %s"
+msgstr ""
+
+msgid "report pruned working trees"
+msgstr "звітувати про видалення робочих дерев"
+
+msgid "expire working trees older than <time>"
+msgstr ""
+
+#, c-format
+msgid "'%s' already exists"
+msgstr "\"%s\" вже існує"
+
+#, c-format
+msgid "unusable worktree destination '%s'"
+msgstr "непридатне місце призначення робочого дерева \"%s\""
+
+#, c-format
+msgid ""
+"'%s' is a missing but locked worktree;\n"
+"use '%s -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"
+msgstr ""
+
+#, c-format
+msgid ""
+"'%s' is a missing but already registered worktree;\n"
+"use '%s -f' to override, or 'prune' or 'remove' to clear"
+msgstr ""
+
+#, c-format
+msgid "failed to copy '%s' to '%s'; sparse-checkout may not work correctly"
+msgstr ""
+
+#, c-format
+msgid "failed to copy worktree config from '%s' to '%s'"
+msgstr "не вдалося скопіювати конфігурацію робочого дерева з \"%s\" до \"%s\""
+
+#, c-format
+msgid "failed to unset '%s' in '%s'"
+msgstr "не вдалося скинути \"%s\" в \"%s\""
+
+#, c-format
+msgid "could not create directory of '%s'"
+msgstr "не вдалося створити директорію \"%s\""
+
+msgid "initializing"
+msgstr ""
+
+#, c-format
+msgid "Preparing worktree (new branch '%s')"
+msgstr ""
+
+#, c-format
+msgid "Preparing worktree (resetting branch '%s'; was at %s)"
+msgstr ""
+
+#, c-format
+msgid "Preparing worktree (checking out '%s')"
+msgstr ""
+
+#, c-format
+msgid "Preparing worktree (detached HEAD %s)"
+msgstr ""
+
+msgid "checkout <branch> even if already checked out in other worktree"
+msgstr ""
+
+msgid "create a new branch"
+msgstr "створити нову гілку"
+
+msgid "create or reset a branch"
+msgstr "створити або скинути гілку"
+
+msgid "populate the new working tree"
+msgstr "заповнити нове робоче дерево"
+
+msgid "keep the new working tree locked"
+msgstr "зберегти нове робоче дерево зафіксованим"
+
+msgid "reason for locking"
+msgstr ""
+
+msgid "set up tracking mode (see git-branch(1))"
+msgstr ""
+
+msgid "try to match the new branch name with a remote-tracking branch"
+msgstr ""
+"спробуйте співставити нову назву гілки з назвою віддалено відстежуваної гілки"
+
+#, c-format
+msgid "options '%s', '%s', and '%s' cannot be used together"
+msgstr "опції \"%s\", \"%s\" та \"%s\" не можна використовувати разом"
+
+msgid "added with --lock"
+msgstr ""
+
+msgid "--[no-]track can only be used if a new branch is created"
+msgstr ""
+
+msgid "show extended annotations and reasons, if available"
+msgstr ""
+
+msgid "add 'prunable' annotation to worktrees older than <time>"
+msgstr ""
+
+msgid "terminate records with a NUL character"
+msgstr ""
+
+#, c-format
+msgid "'%s' is not a working tree"
+msgstr "\"%s\" не є робочим деревом"
+
+msgid "The main working tree cannot be locked or unlocked"
+msgstr ""
+
+#, c-format
+msgid "'%s' is already locked, reason: %s"
+msgstr ""
+
+#, c-format
+msgid "'%s' is already locked"
+msgstr ""
+
+#, c-format
+msgid "'%s' is not locked"
+msgstr "\"%s\" не зафіксовано"
+
+msgid "working trees containing submodules cannot be moved or removed"
+msgstr ""
+
+msgid "force move even if worktree is dirty or locked"
+msgstr ""
+
+#, c-format
+msgid "'%s' is a main working tree"
+msgstr "\"%s\" є головним робочим деревом"
+
+#, c-format
+msgid "could not figure out destination name from '%s'"
+msgstr ""
+
+#, c-format
+msgid ""
+"cannot move a locked working tree, lock reason: %s\n"
+"use 'move -f -f' to override or unlock first"
+msgstr ""
+
+msgid ""
+"cannot move a locked working tree;\n"
+"use 'move -f -f' to override or unlock first"
+msgstr ""
+
+#, c-format
+msgid "validation failed, cannot move working tree: %s"
+msgstr ""
+
+#, c-format
+msgid "failed to move '%s' to '%s'"
+msgstr "не вдалося перенести \"%s\" до \"%s\""
+
+#, c-format
+msgid "failed to run 'git status' on '%s'"
+msgstr "не вдалося виконати \"git status\" на \"%s\""
+
+#, c-format
+msgid "'%s' contains modified or untracked files, use --force to delete it"
+msgstr ""
+
+#, c-format
+msgid "failed to run 'git status' on '%s', code %d"
+msgstr "не вдалося виконати \"git status\" на \"%s\", код %d"
+
+msgid "force removal even if worktree is dirty or locked"
+msgstr ""
+
+#, c-format
+msgid ""
+"cannot remove a locked working tree, lock reason: %s\n"
+"use 'remove -f -f' to override or unlock first"
+msgstr ""
+
+msgid ""
+"cannot remove a locked working tree;\n"
+"use 'remove -f -f' to override or unlock first"
+msgstr ""
+
+#, c-format
+msgid "validation failed, cannot remove working tree: %s"
+msgstr ""
+
+#, c-format
+msgid "repair: %s: %s"
+msgstr ""
+
+#, c-format
+msgid "error: %s: %s"
+msgstr ""
+
+msgid "git write-tree [--missing-ok] [--prefix=<prefix>/]"
+msgstr ""
+
+msgid "<prefix>/"
+msgstr ""
+
+msgid "write tree object for a subdirectory <prefix>"
+msgstr ""
+
+msgid "only useful for debugging"
+msgstr ""
+
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr ""
+
+#, c-format
+msgid "could not parse bundle list key %s with value '%s'"
+msgstr "не вдалося розібрати ключ списку пакунків %s зі значенням \"%s\""
+
+#, c-format
+msgid "bundle list at '%s' has no mode"
+msgstr ""
+
+msgid "failed to create temporary file"
+msgstr "не вдалося створити тимчасовий файл"
+
+msgid "insufficient capabilities"
+msgstr ""
+
+#, c-format
+msgid "file downloaded from '%s' is not a bundle"
+msgstr "файл, завантажений з \"%s\", не є пакунком"
+
+msgid "failed to store maximum creation token"
+msgstr "не вдалося зберегти токен максимального створення"
+
+#, c-format
+msgid "unrecognized bundle mode from URI '%s'"
+msgstr ""
+
+#, c-format
+msgid "exceeded bundle URI recursion limit (%d)"
+msgstr ""
+
+#, c-format
+msgid "failed to download bundle from URI '%s'"
+msgstr "не вдалося завантажити пакунок з URI \"%s\""
+
+#, c-format
+msgid "file at URI '%s' is not a bundle or bundle list"
+msgstr ""
+
+#, c-format
+msgid "bundle-uri: unexpected argument: '%s'"
+msgstr ""
+
+msgid "bundle-uri: expected flush after arguments"
+msgstr ""
+
+msgid "bundle-uri: got an empty line"
+msgstr ""
+
+msgid "bundle-uri: line is not of the form 'key=value'"
+msgstr ""
+
+msgid "bundle-uri: line has empty key or value"
+msgstr ""
+
+#, c-format
+msgid "unrecognized bundle hash algorithm: %s"
+msgstr "нерозпізнаний хеш-алгоритм пакунка: %s"
+
+#, c-format
+msgid "unknown capability '%s'"
+msgstr "невідома властивість \"%s\""
+
+#, c-format
+msgid "'%s' does not look like a v2 or v3 bundle file"
+msgstr ""
+
+#, c-format
+msgid "unrecognized header: %s%s (%d)"
+msgstr ""
+
+msgid "Repository lacks these prerequisite commits:"
+msgstr ""
+
+msgid "need a repository to verify a bundle"
+msgstr ""
+
+msgid ""
+"some prerequisite commits exist in the object store, but are not connected "
+"to the repository's history"
+msgstr ""
+
+#, c-format
+msgid "The bundle contains this ref:"
+msgid_plural "The bundle contains these %<PRIuMAX> refs:"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "The bundle records a complete history."
+msgstr ""
+
+#, c-format
+msgid "The bundle requires this ref:"
+msgid_plural "The bundle requires these %<PRIuMAX> refs:"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "unable to dup bundle descriptor"
+msgstr "не вдалося продублювати дескриптор пакунка"
+
+msgid "Could not spawn pack-objects"
+msgstr "Не вдалося розмножити об’єкти пакунків"
+
+msgid "pack-objects died"
+msgstr ""
+
+#, c-format
+msgid "ref '%s' is excluded by the rev-list options"
+msgstr ""
+
+#, c-format
+msgid "unsupported bundle version %d"
+msgstr ""
+
+#, c-format
+msgid "cannot write bundle version %d with algorithm %s"
+msgstr ""
+
+msgid "Refusing to create empty bundle."
+msgstr ""
+
+#, c-format
+msgid "cannot create '%s'"
+msgstr "неможливо створити \"%s\""
+
+msgid "index-pack died"
+msgstr ""
+
+msgid "terminating chunk id appears earlier than expected"
+msgstr ""
+
+#, c-format
+msgid "improper chunk offset(s) %<PRIx64> and %<PRIx64>"
+msgstr ""
+
+#, c-format
+msgid "duplicate chunk ID %<PRIx32> found"
+msgstr ""
+
+#, c-format
+msgid "final chunk has non-zero id %<PRIx32>"
+msgstr ""
+
+msgid "invalid hash version"
+msgstr "неприпустима версія хешу"
+
+#, c-format
+msgid "invalid color value: %.*s"
+msgstr "неприпустиме значення кольору: %.*s"
+
+msgid "Add file contents to the index"
+msgstr ""
+
+msgid "Apply a series of patches from a mailbox"
+msgstr ""
+
+msgid "Annotate file lines with commit information"
+msgstr ""
+
+msgid "Apply a patch to files and/or to the index"
+msgstr ""
+
+msgid "Import a GNU Arch repository into Git"
+msgstr ""
+
+msgid "Create an archive of files from a named tree"
+msgstr ""
+
+msgid "Use binary search to find the commit that introduced a bug"
+msgstr ""
+
+msgid "Show what revision and author last modified each line of a file"
+msgstr ""
+
+msgid "List, create, or delete branches"
+msgstr "Показати, створити або видалити гілки"
+
+msgid "Collect information for user to file a bug report"
+msgstr ""
+
+msgid "Move objects and refs by archive"
+msgstr ""
+
+msgid "Provide content or type and size information for repository objects"
+msgstr ""
+
+msgid "Display gitattributes information"
+msgstr ""
+
+msgid "Debug gitignore / exclude files"
+msgstr ""
+
+msgid "Show canonical names and email addresses of contacts"
+msgstr ""
+
+msgid "Ensures that a reference name is well formed"
+msgstr ""
+
+msgid "Switch branches or restore working tree files"
+msgstr "Перемкнути гілки або відновити файли робочого дерева"
+
+msgid "Copy files from the index to the working tree"
+msgstr ""
+
+msgid "Find commits yet to be applied to upstream"
+msgstr ""
+
+msgid "Apply the changes introduced by some existing commits"
+msgstr ""
+
+msgid "Graphical alternative to git-commit"
+msgstr ""
+
+msgid "Remove untracked files from the working tree"
+msgstr "Видалити невідстежувані файли з робочого дерева"
+
+msgid "Clone a repository into a new directory"
+msgstr ""
+
+msgid "Display data in columns"
+msgstr ""
+
+msgid "Record changes to the repository"
+msgstr "Записати зміни у сховище"
+
+msgid "Write and verify Git commit-graph files"
+msgstr ""
+
+msgid "Create a new commit object"
+msgstr ""
+
+msgid "Get and set repository or global options"
+msgstr ""
+
+msgid "Count unpacked number of objects and their disk consumption"
+msgstr ""
+
+msgid "Retrieve and store user credentials"
+msgstr ""
+
+msgid "Helper to temporarily store passwords in memory"
+msgstr ""
+
+msgid "Helper to store credentials on disk"
+msgstr ""
+
+msgid "Export a single commit to a CVS checkout"
+msgstr ""
+
+msgid "Salvage your data out of another SCM people love to hate"
+msgstr ""
+
+msgid "A CVS server emulator for Git"
+msgstr ""
+
+msgid "A really simple server for Git repositories"
+msgstr ""
+
+msgid "Give an object a human readable name based on an available ref"
+msgstr ""
+
+msgid "Generate a zip archive of diagnostic information"
+msgstr ""
+
+msgid "Show changes between commits, commit and working tree, etc"
+msgstr "Показати зміни між комітами, комітом та робочим деревом, тощо"
+
+msgid "Compares files in the working tree and the index"
+msgstr ""
+
+msgid "Compare a tree to the working tree or index"
+msgstr "Порівняти дерево з робочим деревом або індексом"
+
+msgid "Compares the content and mode of blobs found via two tree objects"
+msgstr ""
+
+msgid "Show changes using common diff tools"
+msgstr ""
+
+msgid "Git data exporter"
+msgstr ""
+
+msgid "Backend for fast Git data importers"
+msgstr ""
+
+msgid "Download objects and refs from another repository"
+msgstr ""
+
+msgid "Receive missing objects from another repository"
+msgstr ""
+
+msgid "Rewrite branches"
+msgstr "Перезаписати гілки"
+
+msgid "Produce a merge commit message"
+msgstr ""
+
+msgid "Output information on each ref"
+msgstr ""
+
+msgid "Run a Git command on a list of repositories"
+msgstr ""
+
+msgid "Prepare patches for e-mail submission"
+msgstr ""
+
+msgid "Verifies the connectivity and validity of the objects in the database"
+msgstr ""
+
+msgid "Cleanup unnecessary files and optimize the local repository"
+msgstr ""
+
+msgid "Extract commit ID from an archive created using git-archive"
+msgstr ""
+
+msgid "Print lines matching a pattern"
+msgstr ""
+
+msgid "A portable graphical interface to Git"
+msgstr ""
+
+msgid "Compute object ID and optionally creates a blob from a file"
+msgstr ""
+
+msgid "Display help information about Git"
+msgstr ""
+
+msgid "Run git hooks"
+msgstr ""
+
+msgid "Server side implementation of Git over HTTP"
+msgstr ""
+
+msgid "Download from a remote Git repository via HTTP"
+msgstr ""
+
+msgid "Push objects over HTTP/DAV to another repository"
+msgstr ""
+
+msgid "Send a collection of patches from stdin to an IMAP folder"
+msgstr ""
+
+msgid "Build pack index file for an existing packed archive"
+msgstr ""
+
+msgid "Create an empty Git repository or reinitialize an existing one"
+msgstr ""
+
+msgid "Instantly browse your working repository in gitweb"
+msgstr ""
+
+msgid "Add or parse structured information in commit messages"
+msgstr ""
+
+msgid "Show commit logs"
+msgstr "Показати лог коміта"
+
+msgid "Show information about files in the index and the working tree"
+msgstr ""
+
+msgid "List references in a remote repository"
+msgstr "Показати посилання у віддаленому сховищі"
+
+msgid "List the contents of a tree object"
+msgstr ""
+
+msgid "Extracts patch and authorship from a single e-mail message"
+msgstr ""
+
+msgid "Simple UNIX mbox splitter program"
+msgstr ""
+
+msgid "Run tasks to optimize Git repository data"
+msgstr ""
+
+msgid "Join two or more development histories together"
+msgstr ""
+
+msgid "Find as good common ancestors as possible for a merge"
+msgstr ""
+
+msgid "Run a three-way file merge"
+msgstr ""
+
+msgid "Run a merge for files needing merging"
+msgstr ""
+
+msgid "The standard helper program to use with git-merge-index"
+msgstr ""
+
+msgid "Perform merge without touching index or working tree"
+msgstr ""
+
+msgid "Run merge conflict resolution tools to resolve merge conflicts"
+msgstr ""
+
+msgid "Creates a tag object with extra validation"
+msgstr ""
+
+msgid "Build a tree-object from ls-tree formatted text"
+msgstr ""
+
+msgid "Write and verify multi-pack-indexes"
+msgstr ""
+
+msgid "Move or rename a file, a directory, or a symlink"
+msgstr ""
+
+msgid "Find symbolic names for given revs"
+msgstr ""
+
+msgid "Add or inspect object notes"
+msgstr "Додайте або перевірте нотатки до обʼєктів"
+
+msgid "Import from and submit to Perforce repositories"
+msgstr ""
+
+msgid "Create a packed archive of objects"
+msgstr ""
+
+msgid "Find redundant pack files"
+msgstr "Знайти зайві файли пакунків"
+
+msgid "Pack heads and tags for efficient repository access"
+msgstr ""
+
+msgid "Compute unique ID for a patch"
+msgstr ""
+
+msgid "Prune all unreachable objects from the object database"
+msgstr ""
+
+msgid "Remove extra objects that are already in pack files"
+msgstr ""
+
+msgid "Fetch from and integrate with another repository or a local branch"
+msgstr ""
+
+msgid "Update remote refs along with associated objects"
+msgstr ""
+
+msgid "Applies a quilt patchset onto the current branch"
+msgstr ""
+
+msgid "Compare two commit ranges (e.g. two versions of a branch)"
+msgstr ""
+
+msgid "Reads tree information into the index"
+msgstr ""
+
+msgid "Reapply commits on top of another base tip"
+msgstr ""
+
+msgid "Receive what is pushed into the repository"
+msgstr ""
+
+msgid "Manage reflog information"
+msgstr ""
+
+msgid "Manage set of tracked repositories"
+msgstr "Керувати набором відстежуваних сховищ"
+
+msgid "Pack unpacked objects in a repository"
+msgstr ""
+
+msgid "Create, list, delete refs to replace objects"
+msgstr ""
+
+msgid "Generates a summary of pending changes"
+msgstr ""
+
+msgid "Reuse recorded resolution of conflicted merges"
+msgstr ""
+
+msgid "Reset current HEAD to the specified state"
+msgstr ""
+
+msgid "Restore working tree files"
+msgstr "Відновити файли робочого дерева"
+
+msgid "Lists commit objects in reverse chronological order"
+msgstr ""
+
+msgid "Pick out and massage parameters"
+msgstr ""
+
+msgid "Revert some existing commits"
+msgstr ""
+
+msgid "Remove files from the working tree and from the index"
+msgstr ""
+
+msgid "Send a collection of patches as emails"
+msgstr ""
+
+msgid "Push objects over Git protocol to another repository"
+msgstr ""
+
+msgid "Git's i18n setup code for shell scripts"
+msgstr ""
+
+msgid "Common Git shell script setup code"
+msgstr ""
+
+msgid "Restricted login shell for Git-only SSH access"
+msgstr ""
+
+msgid "Summarize 'git log' output"
+msgstr ""
+
+msgid "Show various types of objects"
+msgstr ""
+
+msgid "Show branches and their commits"
+msgstr "Показати гілки та їхні коміти"
+
+msgid "Show packed archive index"
+msgstr ""
+
+msgid "List references in a local repository"
+msgstr "Показати посилання у локальному сховищі"
+
+msgid "Reduce your working tree to a subset of tracked files"
+msgstr "Скоротити робоче дерево до підмножини відстежуваних файлів"
+
+msgid "Add file contents to the staging area"
+msgstr ""
+
+msgid "Stash the changes in a dirty working directory away"
+msgstr ""
+
+msgid "Show the working tree status"
+msgstr "Показати стан робочого дерева"
+
+msgid "Remove unnecessary whitespace"
+msgstr ""
+
+msgid "Initialize, update or inspect submodules"
+msgstr ""
+
+msgid "Bidirectional operation between a Subversion repository and Git"
+msgstr ""
+
+msgid "Switch branches"
+msgstr "Переключити гілки"
+
+msgid "Read, modify and delete symbolic refs"
+msgstr ""
+
+msgid "Create, list, delete or verify a tag object signed with GPG"
+msgstr ""
+
+msgid "Creates a temporary file with a blob's contents"
+msgstr ""
+
+msgid "Unpack objects from a packed archive"
+msgstr ""
+
+msgid "Register file contents in the working tree to the index"
+msgstr ""
+
+msgid "Update the object name stored in a ref safely"
+msgstr ""
+
+msgid "Update auxiliary info file to help dumb servers"
+msgstr ""
+
+msgid "Send archive back to git-archive"
+msgstr ""
+
+msgid "Send objects packed back to git-fetch-pack"
+msgstr ""
+
+msgid "Show a Git logical variable"
+msgstr ""
+
+msgid "Check the GPG signature of commits"
+msgstr ""
+
+msgid "Validate packed Git archive files"
+msgstr ""
+
+msgid "Check the GPG signature of tags"
+msgstr ""
+
+msgid "Display version information about Git"
+msgstr ""
+
+msgid "Show logs with difference each commit introduces"
+msgstr ""
+
+msgid "Manage multiple working trees"
+msgstr "Керувати кількома робочими деревами"
+
+msgid "Create a tree object from the current index"
+msgstr ""
+
+msgid "Defining attributes per path"
+msgstr ""
+
+msgid "Git command-line interface and conventions"
+msgstr ""
+
+msgid "A Git core tutorial for developers"
+msgstr ""
+
+msgid "Providing usernames and passwords to Git"
+msgstr ""
+
+msgid "Git for CVS users"
+msgstr ""
+
+msgid "Tweaking diff output"
+msgstr ""
+
+msgid "A useful minimum set of commands for Everyday Git"
+msgstr ""
+
+msgid "Frequently asked questions about using Git"
+msgstr ""
+
+msgid "The bundle file format"
+msgstr "Формат файлу пакета"
+
+msgid "Chunk-based file formats"
+msgstr ""
+
+msgid "Git commit-graph format"
+msgstr ""
+
+msgid "Git index format"
+msgstr ""
+
+msgid "Git pack format"
+msgstr ""
+
+msgid "Git cryptographic signature formats"
+msgstr ""
+
+msgid "A Git Glossary"
+msgstr ""
+
+msgid "Hooks used by Git"
+msgstr ""
+
+msgid "Specifies intentionally untracked files to ignore"
+msgstr ""
+
+msgid "The Git repository browser"
+msgstr ""
+
+msgid "Map author/committer names and/or E-Mail addresses"
+msgstr ""
+
+msgid "Defining submodule properties"
+msgstr ""
+
+msgid "Git namespaces"
+msgstr ""
+
+msgid "Protocol v0 and v1 capabilities"
+msgstr ""
+
+msgid "Things common to various protocols"
+msgstr ""
+
+msgid "Git HTTP-based protocols"
+msgstr ""
+
+msgid "How packs are transferred over-the-wire"
+msgstr ""
+
+msgid "Git Wire Protocol, Version 2"
+msgstr ""
+
+msgid "Helper programs to interact with remote repositories"
+msgstr ""
+
+msgid "Git Repository Layout"
+msgstr ""
+
+msgid "Specifying revisions and ranges for Git"
+msgstr ""
+
+msgid "Mounting one repository inside another"
+msgstr ""
+
+msgid "A tutorial introduction to Git"
+msgstr ""
+
+msgid "A tutorial introduction to Git: part two"
+msgstr ""
+
+msgid "Git web interface (web frontend to Git repositories)"
+msgstr ""
+
+msgid "An overview of recommended workflows with Git"
+msgstr ""
+
+msgid "A tool for managing large Git repositories"
+msgstr ""
+
+msgid "commit-graph file is too small"
+msgstr ""
+
+#, c-format
+msgid "commit-graph signature %X does not match signature %X"
+msgstr ""
+
+#, c-format
+msgid "commit-graph version %X does not match version %X"
+msgstr ""
+
+#, c-format
+msgid "commit-graph hash version %X does not match version %X"
+msgstr ""
+
+#, c-format
+msgid "commit-graph file is too small to hold %u chunks"
+msgstr ""
+
+msgid "commit-graph has no base graphs chunk"
+msgstr ""
+
+msgid "commit-graph chain does not match"
+msgstr ""
+
+#, c-format
+msgid "invalid commit-graph chain: line '%s' not a hash"
+msgstr ""
+
+msgid "unable to find all commit-graph files"
+msgstr "не вдалося знайти всі файли графа комітів"
+
+msgid "invalid commit position. commit-graph is likely corrupt"
+msgstr ""
+
+#, c-format
+msgid "could not find commit %s"
+msgstr "не вдалося знайти коміт %s"
+
+msgid "commit-graph requires overflow generation data but has none"
+msgstr ""
+
+msgid "Loading known commits in commit graph"
+msgstr ""
+
+msgid "Expanding reachable commits in commit graph"
+msgstr ""
+
+msgid "Clearing commit marks in commit graph"
+msgstr ""
+
+msgid "Computing commit graph topological levels"
+msgstr ""
+
+msgid "Computing commit graph generation numbers"
+msgstr ""
+
+msgid "Computing commit changed paths Bloom filters"
+msgstr ""
+
+msgid "Collecting referenced commits"
+msgstr ""
+
+#, c-format
+msgid "Finding commits for commit graph in %<PRIuMAX> pack"
+msgid_plural "Finding commits for commit graph in %<PRIuMAX> packs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "error adding pack %s"
+msgstr "помилка додавання пакету %s"
+
+#, c-format
+msgid "error opening index for %s"
+msgstr ""
+
+msgid "Finding commits for commit graph among packed objects"
+msgstr ""
+
+msgid "Finding extra edges in commit graph"
+msgstr ""
+
+msgid "failed to write correct number of base graph ids"
+msgstr ""
+
+msgid "unable to create temporary graph layer"
+msgstr "не вдалося створити тимчасовий шар графа"
+
+#, c-format
+msgid "unable to adjust shared permissions for '%s'"
+msgstr "не вдалося налаштувати спільні дозволи для \"%s\""
+
+#, c-format
+msgid "Writing out commit graph in %d pass"
+msgid_plural "Writing out commit graph in %d passes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "unable to open commit-graph chain file"
+msgstr "не вдалося відкрити ланцюжковий файл графа комітів"
+
+msgid "failed to rename base commit-graph file"
+msgstr ""
+
+msgid "failed to rename temporary commit-graph file"
+msgstr "не вдалося перейменувати тимчасовий файл графа комітів"
+
+msgid "Scanning merged commits"
+msgstr ""
+
+msgid "Merging commit-graph"
+msgstr ""
+
+msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled"
+msgstr ""
+
+msgid "too many commits to write graph"
+msgstr ""
+
+msgid "the commit-graph file has incorrect checksum and is likely corrupt"
+msgstr ""
+
+#, c-format
+msgid "commit-graph has incorrect OID order: %s then %s"
+msgstr ""
+
+#, c-format
+msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u"
+msgstr ""
+
+#, c-format
+msgid "failed to parse commit %s from commit-graph"
+msgstr "не вдалося розібрати коміт %s з графа комітв"
+
+msgid "Verifying commits in commit graph"
+msgstr ""
+
+#, c-format
+msgid "failed to parse commit %s from object database for commit-graph"
+msgstr ""
+
+#, c-format
+msgid "root tree OID for commit %s in commit-graph is %s != %s"
+msgstr ""
+
+#, c-format
+msgid "commit-graph parent list for commit %s is too long"
+msgstr ""
+
+#, c-format
+msgid "commit-graph parent for %s is %s != %s"
+msgstr ""
+
+#, c-format
+msgid "commit-graph parent list for commit %s terminates early"
+msgstr ""
+
+#, c-format
+msgid ""
+"commit-graph has generation number zero for commit %s, but non-zero elsewhere"
+msgstr ""
+
+#, c-format
+msgid ""
+"commit-graph has non-zero generation number for commit %s, but zero elsewhere"
+msgstr ""
+
+#, c-format
+msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>"
+msgstr ""
+
+#, c-format
+msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>"
+msgstr ""
+
+#, c-format
+msgid "%s %s is not a commit!"
+msgstr ""
+
+msgid ""
+"Support for <GIT_DIR>/info/grafts is deprecated\n"
+"and will be removed in a future Git version.\n"
+"\n"
+"Please use \"git replace --convert-graft-file\"\n"
+"to convert the grafts into replace refs.\n"
+"\n"
+"Turn this message off by running\n"
+"\"git config advice.graftFileDeprecated false\""
+msgstr ""
+
+#, c-format
+msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
+msgstr ""
+
+#, c-format
+msgid "Commit %s has a bad GPG signature allegedly by %s."
+msgstr ""
+
+#, c-format
+msgid "Commit %s does not have a GPG signature."
+msgstr "Коміт %s не має GPG підпису."
+
+#, c-format
+msgid "Commit %s has a good GPG signature by %s\n"
+msgstr ""
+
+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"
+"variable i18n.commitEncoding to the encoding your project uses.\n"
+msgstr ""
+
+msgid "no compiler information available\n"
+msgstr ""
+
+msgid "no libc information available\n"
+msgstr ""
+
+#, c-format
+msgid "could not determine free disk size for '%s'"
+msgstr "не вдалося визначити вільний розмір диска для \"%s\""
+
+#, c-format
+msgid "could not get info for '%s'"
+msgstr "не вдалося отримати інформацію для \"%s\""
+
+#, c-format
+msgid "[GLE %ld] health thread could not open '%ls'"
+msgstr ""
+
+#, c-format
+msgid "[GLE %ld] health thread getting BHFI for '%ls'"
+msgstr ""
+
+#, c-format
+msgid "could not convert to wide characters: '%s'"
+msgstr "не вдалося перетворити в широкі символи: \"%s\""
+
+#, c-format
+msgid "BHFI changed '%ls'"
+msgstr ""
+
+#, c-format
+msgid "unhandled case in 'has_worktree_moved': %d"
+msgstr ""
+
+#, c-format
+msgid "health thread wait failed [GLE %ld]"
+msgstr ""
+
+#, c-format
+msgid "Invalid path: %s"
+msgstr "Неприпустимий шлях: %s"
+
+msgid "Unable to create FSEventStream."
+msgstr "Не вдалося створити FSEventStream."
+
+msgid "Failed to start the FSEventStream"
+msgstr "Не вдалося запустити потік FSEventStream"
+
+#, c-format
+msgid "[GLE %ld] could not convert path to UTF-8: '%.*ls'"
+msgstr ""
+
+#, c-format
+msgid "[GLE %ld] could not watch '%s'"
+msgstr ""
+
+#, c-format
+msgid "[GLE %ld] could not get longname of '%s'"
+msgstr ""
+
+#, c-format
+msgid "ReadDirectoryChangedW failed on '%s' [GLE %ld]"
+msgstr ""
+
+#, c-format
+msgid "GetOverlappedResult failed on '%s' [GLE %ld]"
+msgstr ""
+
+#, c-format
+msgid "could not read directory changes [GLE %ld]"
+msgstr "не вдалося прочитати зміни директорії [GLE %ld]"
+
+#, c-format
+msgid "opendir('%s') failed"
+msgstr ""
+
+#, c-format
+msgid "lstat('%s') failed"
+msgstr ""
+
+#, c-format
+msgid "strbuf_readlink('%s') failed"
+msgstr ""
+
+#, c-format
+msgid "closedir('%s') failed"
+msgstr ""
+
+#, c-format
+msgid "[GLE %ld] unable to open for read '%ls'"
+msgstr "[GLE %ld] не вдалося відкрити для читання \"%ls\""
+
+#, c-format
+msgid "[GLE %ld] unable to get protocol information for '%ls'"
+msgstr ""
+
+#, c-format
+msgid "failed to copy SID (%ld)"
+msgstr "не вдалося скопіювати SID (%ld)"
+
+#, c-format
+msgid "failed to get owner for '%s' (%ld)"
+msgstr "не вдалося отримати власника для \"%s\" (%ld)"
+
+msgid "memory exhausted"
+msgstr ""
+
+msgid "Success"
+msgstr ""
+
+msgid "No match"
+msgstr ""
+
+msgid "Invalid regular expression"
+msgstr ""
+
+msgid "Invalid collation character"
+msgstr ""
+
+msgid "Invalid character class name"
+msgstr ""
+
+msgid "Trailing backslash"
+msgstr ""
+
+msgid "Invalid back reference"
+msgstr "Неприпустиме зворотнє посилання"
+
+msgid "Unmatched [ or [^"
+msgstr ""
+
+msgid "Unmatched ( or \\("
+msgstr ""
+
+msgid "Unmatched \\{"
+msgstr ""
+
+msgid "Invalid content of \\{\\}"
+msgstr ""
+
+msgid "Invalid range end"
+msgstr ""
+
+msgid "Memory exhausted"
+msgstr ""
+
+msgid "Invalid preceding regular expression"
+msgstr ""
+
+msgid "Premature end of regular expression"
+msgstr ""
+
+msgid "Regular expression too big"
+msgstr ""
+
+msgid "Unmatched ) or \\)"
+msgstr ""
+
+msgid "No previous regular expression"
+msgstr ""
+
+msgid "could not send IPC command"
+msgstr ""
+
+msgid "could not read IPC response"
+msgstr "не вдалося прочитати IPC відповідь"
+
+#, c-format
+msgid "could not start accept_thread '%s'"
+msgstr "не вдалося розпочати accept_thread \"%s\""
+
+#, c-format
+msgid "could not start worker[0] for '%s'"
+msgstr "не вдалося запустити worker[0] для \"%s\""
+
+#, c-format
+msgid "ConnectNamedPipe failed for '%s' (%lu)"
+msgstr ""
+
+#, c-format
+msgid "could not create fd from pipe for '%s'"
+msgstr "не вдалося створити fd з каналу для \"%s\""
+
+#, c-format
+msgid "could not start thread[0] for '%s'"
+msgstr "не вдалося запустити thread[0] для \"%s\""
+
+#, c-format
+msgid "wait for hEvent failed for '%s'"
+msgstr "очікування на hEvent не вдалося для \"%s\""
+
+msgid "cannot resume in the background, please use 'fg' to resume"
+msgstr ""
+
+msgid "cannot restore terminal settings"
+msgstr ""
+
+#, c-format
+msgid ""
+"exceeded maximum include depth (%d) while including\n"
+"\t%s\n"
+"from\n"
+"\t%s\n"
+"This might be due to circular includes."
+msgstr ""
+
+#, c-format
+msgid "could not expand include path '%s'"
+msgstr "не вдалося визначити include path \"%s\""
+
+msgid "relative config includes must come from files"
+msgstr ""
+
+msgid "relative config include conditionals must come from files"
+msgstr ""
+
+msgid ""
+"remote URLs cannot be configured in file directly or indirectly included by "
+"includeIf.hasconfig:remote.*.url"
+msgstr ""
+
+#, c-format
+msgid "invalid config format: %s"
+msgstr "неприпустимий формат конфігурації: %s"
+
+#, c-format
+msgid "missing environment variable name for configuration '%.*s'"
+msgstr ""
+
+#, c-format
+msgid "missing environment variable '%s' for configuration '%.*s'"
+msgstr ""
+
+#, c-format
+msgid "key does not contain a section: %s"
+msgstr ""
+
+#, c-format
+msgid "key does not contain variable name: %s"
+msgstr ""
+
+#, c-format
+msgid "invalid key: %s"
+msgstr "неприпустимий ключ: %s"
+
+#, c-format
+msgid "invalid key (newline): %s"
+msgstr "неприпустимий ключ (новий рядок): %s"
+
+msgid "empty config key"
+msgstr ""
+
+#, c-format
+msgid "bogus config parameter: %s"
+msgstr ""
+
+#, c-format
+msgid "bogus format in %s"
+msgstr ""
+
+#, c-format
+msgid "bogus count in %s"
+msgstr ""
+
+#, c-format
+msgid "too many entries in %s"
+msgstr ""
+
+#, c-format
+msgid "missing config key %s"
+msgstr ""
+
+#, c-format
+msgid "missing config value %s"
+msgstr ""
+
+#, c-format
+msgid "bad config line %d in blob %s"
+msgstr ""
+
+#, c-format
+msgid "bad config line %d in file %s"
+msgstr ""
+
+#, c-format
+msgid "bad config line %d in standard input"
+msgstr ""
+
+#, c-format
+msgid "bad config line %d in submodule-blob %s"
+msgstr ""
+
+#, c-format
+msgid "bad config line %d in command line %s"
+msgstr ""
+
+#, c-format
+msgid "bad config line %d in %s"
+msgstr ""
+
+msgid "out of range"
+msgstr ""
+
+msgid "invalid unit"
+msgstr "неприпустима одиниця виміру"
+
+#, c-format
+msgid "bad numeric config value '%s' for '%s': %s"
+msgstr ""
+
+#, c-format
+msgid "bad numeric config value '%s' for '%s' in blob %s: %s"
+msgstr ""
+
+#, c-format
+msgid "bad numeric config value '%s' for '%s' in file %s: %s"
+msgstr ""
+
+#, c-format
+msgid "bad numeric config value '%s' for '%s' in standard input: %s"
+msgstr ""
+
+#, c-format
+msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s"
+msgstr ""
+
+#, c-format
+msgid "bad numeric config value '%s' for '%s' in command line %s: %s"
+msgstr ""
+
+#, c-format
+msgid "bad numeric config value '%s' for '%s' in %s: %s"
+msgstr ""
+
+#, c-format
+msgid "invalid value for variable %s"
+msgstr "неприпустиме значення для змінної %s"
+
+#, c-format
+msgid "ignoring unknown core.fsync component '%s'"
+msgstr ""
+
+#, c-format
+msgid "bad boolean config value '%s' for '%s'"
+msgstr "неправильне булеве значення конфігурації \"%s\" для \"%s\""
+
+#, c-format
+msgid "failed to expand user dir in: '%s'"
+msgstr "не вдалося визначити директорію користувача в: \"%s\""
+
+#, c-format
+msgid "'%s' for '%s' is not a valid timestamp"
+msgstr "\"%s\" для \"%s\" не є припустимою міткою часу"
+
+#, c-format
+msgid "abbrev length out of range: %d"
+msgstr ""
+
+#, c-format
+msgid "bad zlib compression level %d"
+msgstr ""
+
+msgid "core.commentChar should only be one ASCII character"
+msgstr ""
+
+#, c-format
+msgid "ignoring unknown core.fsyncMethod value '%s'"
+msgstr ""
+
+msgid "core.fsyncObjectFiles is deprecated; use core.fsync instead"
+msgstr ""
+
+#, c-format
+msgid "invalid mode for object creation: %s"
+msgstr "неприпустимий режим створення обʼєкта: %s"
+
+#, c-format
+msgid "malformed value for %s"
+msgstr "неправильно сформоване значення для %s"
+
+#, c-format
+msgid "malformed value for %s: %s"
+msgstr "неправильно сформоване значення для %s: %s"
+
+msgid "must be one of nothing, matching, simple, upstream or current"
+msgstr ""
+
+#, c-format
+msgid "unable to load config blob object '%s'"
+msgstr "не вдалося завантажити config blob обʼєкт \"%s\""
+
+#, c-format
+msgid "reference '%s' does not point to a blob"
+msgstr "посилання \"%s\" не вказує на blob"
+
+#, c-format
+msgid "unable to resolve config blob '%s'"
+msgstr "не вдалося розпізнати config blob \"%s\""
+
+#, c-format
+msgid "failed to parse %s"
+msgstr "не вдалося розібрати %s"
+
+msgid "unable to parse command-line config"
+msgstr "не вдалося розібрати конфігурацію командного рядка"
+
+msgid "unknown error occurred while reading the configuration files"
+msgstr ""
+
+#, c-format
+msgid "Invalid %s: '%s'"
+msgstr "Неприпустимий %s: \"%s\""
+
+#, c-format
+msgid "splitIndex.maxPercentChange value '%d' should be between 0 and 100"
+msgstr ""
+
+#, c-format
+msgid "unable to parse '%s' from command-line config"
+msgstr "не вдалося розібрати \"%s\" з конфігурації командного рядка"
+
+#, c-format
+msgid "bad config variable '%s' in file '%s' at line %d"
+msgstr ""
+
+#, c-format
+msgid "invalid section name '%s'"
+msgstr "неприпустима назва секції \"%s\""
+
+#, c-format
+msgid "%s has multiple values"
+msgstr ""
+
+#, c-format
+msgid "failed to write new configuration file %s"
+msgstr "не вдалося записати новий конфігураційний файл %s"
+
+#, c-format
+msgid "could not lock config file %s"
+msgstr "не вдалося зафіксувати файл конфігурації %s"
+
+#, c-format
+msgid "opening %s"
+msgstr ""
+
+#, c-format
+msgid "invalid config file %s"
+msgstr "неприпустимий конфігураційний файл %s"
+
+#, c-format
+msgid "fstat on %s failed"
+msgstr ""
+
+#, c-format
+msgid "unable to mmap '%s'%s"
+msgstr "не вдалося виконати mmap \"%s\"%s"
+
+#, c-format
+msgid "chmod on %s failed"
+msgstr ""
+
+#, c-format
+msgid "could not write config file %s"
+msgstr "не вдалося записати конфігураційний файл %s"
+
+#, c-format
+msgid "could not set '%s' to '%s'"
+msgstr "не вдалося встановити \"%s\" в \"%s\""
+
+#, c-format
+msgid "invalid section name: %s"
+msgstr "неприпустима назва секції: %s"
+
+#, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr ""
+
+#, c-format
+msgid "missing value for '%s'"
+msgstr "відсутнє значення для \"%s\""
+
+msgid "the remote end hung up upon initial contact"
+msgstr ""
+
+msgid ""
+"Could not read from remote repository.\n"
+"\n"
+"Please make sure you have the correct access rights\n"
+"and the repository exists."
+msgstr ""
+
+#, c-format
+msgid "server doesn't support '%s'"
+msgstr ""
+
+#, c-format
+msgid "server doesn't support feature '%s'"
+msgstr ""
+
+msgid "expected flush after capabilities"
+msgstr ""
+
+#, c-format
+msgid "ignoring capabilities after first line '%s'"
+msgstr ""
+
+msgid "protocol error: unexpected capabilities^{}"
+msgstr ""
+
+#, c-format
+msgid "protocol error: expected shallow sha-1, got '%s'"
+msgstr ""
+
+msgid "repository on the other end cannot be shallow"
+msgstr ""
+
+msgid "invalid packet"
+msgstr "неприпустимий пакет"
+
+#, c-format
+msgid "protocol error: unexpected '%s'"
+msgstr ""
+
+#, c-format
+msgid "unknown object format '%s' specified by server"
+msgstr ""
+
+#, c-format
+msgid "error on bundle-uri response line %d: %s"
+msgstr ""
+
+msgid "expected flush after bundle-uri listing"
+msgstr ""
+
+msgid "expected response end packet after ref listing"
+msgstr ""
+
+#, c-format
+msgid "invalid ls-refs response: %s"
+msgstr "неприпустима ls-refs відповідь: %s"
+
+msgid "expected flush after ref listing"
+msgstr ""
+
+#, c-format
+msgid "protocol '%s' is not supported"
+msgstr "протокол \"%s\" не підтримується"
+
+msgid "unable to set SO_KEEPALIVE on socket"
+msgstr ""
+
+#, c-format
+msgid "Looking up %s ... "
+msgstr ""
+
+#, c-format
+msgid "unable to look up %s (port %s) (%s)"
+msgstr "не вдалося знайти %s (порт %s) (%s)"
+
+#. TRANSLATORS: this is the end of "Looking up %s ... "
+
+#, c-format
+msgid ""
+"done.\n"
+"Connecting to %s (port %s) ... "
+msgstr ""
+
+#, c-format
+msgid ""
+"unable to connect to %s:\n"
+"%s"
+msgstr ""
+"не вдалося приєднатися до %s:\n"
+"%s"
+
+#. TRANSLATORS: this is the end of "Connecting to %s (port %s) ... "
+
+msgid "done."
+msgstr "готово."
+
+#, c-format
+msgid "unable to look up %s (%s)"
+msgstr "не вдалося знайти %s (%s)"
+
+#, c-format
+msgid "unknown port %s"
+msgstr "невідомий порт %s"
+
+#, c-format
+msgid "strange hostname '%s' blocked"
+msgstr ""
+
+#, c-format
+msgid "strange port '%s' blocked"
+msgstr ""
+
+#, c-format
+msgid "cannot start proxy %s"
+msgstr "неможливо запустити проксі %s"
+
+msgid "no path specified; see 'git help pull' for valid url syntax"
+msgstr ""
+
+msgid "newline is forbidden in git:// hosts and repo paths"
+msgstr ""
+
+msgid "ssh variant 'simple' does not support -4"
+msgstr ""
+
+msgid "ssh variant 'simple' does not support -6"
+msgstr ""
+
+msgid "ssh variant 'simple' does not support setting port"
+msgstr ""
+
+#, c-format
+msgid "strange pathname '%s' blocked"
+msgstr ""
+
+msgid "unable to fork"
+msgstr "неможливо розгалужити"
+
+msgid "Could not run 'git rev-list'"
+msgstr "Не вдалося запустити \"git rev-list\""
+
+msgid "failed write to rev-list"
+msgstr "не вдалося записати до rev-list"
+
+msgid "failed to close rev-list's stdin"
+msgstr ""
+
+#, c-format
+msgid "illegal crlf_action %d"
+msgstr ""
+
+#, c-format
+msgid "CRLF would be replaced by LF in %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"in the working copy of '%s', CRLF will be replaced by LF the next time Git "
+"touches it"
+msgstr ""
+
+#, c-format
+msgid "LF would be replaced by CRLF in %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"in the working copy of '%s', LF will be replaced by CRLF the next time Git "
+"touches it"
+msgstr ""
+
+#, c-format
+msgid "BOM is prohibited in '%s' if encoded as %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"The file '%s' contains a byte order mark (BOM). Please use UTF-%.*s as "
+"working-tree-encoding."
+msgstr ""
+
+#, c-format
+msgid "BOM is required in '%s' if encoded as %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"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 ""
+
+#, c-format
+msgid "failed to encode '%s' from %s to %s"
+msgstr "не вдалося закодувати \"%s\" з %s в %s"
+
+#, c-format
+msgid "encoding '%s' from %s to %s and back is not the same"
+msgstr ""
+
+#, c-format
+msgid "cannot fork to run external filter '%s'"
+msgstr "неможливо розгалужити для запуску зовнішнього фільтра \"%s\""
+
+#, c-format
+msgid "cannot feed the input to external filter '%s'"
+msgstr "неможливо подати вхідні дані на зовнішній фільтр \"%s\""
+
+#, c-format
+msgid "external filter '%s' failed %d"
+msgstr ""
+
+#, c-format
+msgid "read from external filter '%s' failed"
+msgstr ""
+
+#, c-format
+msgid "external filter '%s' failed"
+msgstr ""
+
+msgid "unexpected filter type"
+msgstr ""
+
+msgid "path name too long for external filter"
+msgstr ""
+
+#, c-format
+msgid ""
+"external filter '%s' is not available anymore although not all paths have "
+"been filtered"
+msgstr ""
+
+msgid "true/false are no valid working-tree-encodings"
+msgstr ""
+
+#, c-format
+msgid "%s: clean filter '%s' failed"
+msgstr ""
+
+#, c-format
+msgid "%s: smudge filter %s failed"
+msgstr ""
+
+#, c-format
+msgid "skipping credential lookup for key: credential.%s"
+msgstr ""
+
+msgid "refusing to work with credential missing host field"
+msgstr ""
+
+msgid "refusing to work with credential missing protocol field"
+msgstr ""
+
+#, c-format
+msgid "url contains a newline in its %s component: %s"
+msgstr ""
+
+#, c-format
+msgid "url has no scheme: %s"
+msgstr ""
+
+#, c-format
+msgid "credential url cannot be parsed: %s"
+msgstr ""
+
+msgid "in the future"
+msgstr ""
+
+#, c-format
+msgid "%<PRIuMAX> second ago"
+msgid_plural "%<PRIuMAX> seconds ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "%<PRIuMAX> minute ago"
+msgid_plural "%<PRIuMAX> minutes ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "%<PRIuMAX> hour ago"
+msgid_plural "%<PRIuMAX> hours ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "%<PRIuMAX> day ago"
+msgid_plural "%<PRIuMAX> days ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "%<PRIuMAX> week ago"
+msgid_plural "%<PRIuMAX> weeks ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "%<PRIuMAX> month ago"
+msgid_plural "%<PRIuMAX> months ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "%<PRIuMAX> year"
+msgid_plural "%<PRIuMAX> years"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#. TRANSLATORS: "%s" is "<n> years"
+
+#, c-format
+msgid "%s, %<PRIuMAX> month ago"
+msgid_plural "%s, %<PRIuMAX> months ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid "%<PRIuMAX> year ago"
+msgid_plural "%<PRIuMAX> years ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Propagating island marks"
+msgstr ""
+
+#, c-format
+msgid "bad tree object %s"
+msgstr "невірний обʼєкт дерева %s"
+
+#, c-format
+msgid "failed to load island regex for '%s': %s"
+msgstr "не вдалося завантажити island регвир для \"%s\": %s"
+
+#, c-format
+msgid "island regex from config has too many capture groups (max=%d)"
+msgstr ""
+
+#, c-format
+msgid "Marked %d islands, done.\n"
+msgstr ""
+
+#, c-format
+msgid "invalid --%s value '%s'"
+msgstr "неприпустиме --%s значення \"%s\""
+
+#, c-format
+msgid "could not archive missing directory '%s'"
+msgstr "не вдалося заархівувати відсутню директорію \"%s\""
+
+#, c-format
+msgid "could not open directory '%s'"
+msgstr "не вдалося відкрити директорію \"%s\""
+
+#, c-format
+msgid "skipping '%s', which is neither file nor directory"
+msgstr ""
+
+msgid "could not duplicate stdout"
+msgstr "не вдалося продублювати stdout"
+
+#, c-format
+msgid "could not add directory '%s' to archiver"
+msgstr "не вдалося додати директорію \"%s\" до архіватора"
+
+msgid "failed to write archive"
+msgstr "не вдалося записати архів"
+
+msgid "--merge-base does not work with ranges"
+msgstr ""
+
+msgid "--merge-base only works with commits"
+msgstr ""
+
+msgid "unable to get HEAD"
+msgstr "не вдалося отримати HEAD"
+
+msgid "no merge base found"
+msgstr ""
+
+msgid "multiple merge bases found"
+msgstr ""
+
+msgid "git diff --no-index [<options>] <path> <path>"
+msgstr "git diff --no-index [<опції>] <шлях> <шлях>"
+
+msgid ""
+"Not a git repository. Use --no-index to compare two paths outside a working "
+"tree"
+msgstr ""
+
+#, c-format
+msgid "  Failed to parse dirstat cut-off percentage '%s'\n"
+msgstr ""
+
+#, c-format
+msgid "  Unknown dirstat parameter '%s'\n"
+msgstr ""
+
+msgid ""
+"color moved setting must be one of 'no', 'default', 'blocks', 'zebra', "
+"'dimmed-zebra', 'plain'"
+msgstr ""
+
+#, c-format
+msgid ""
+"unknown color-moved-ws mode '%s', possible values are 'ignore-space-change', "
+"'ignore-space-at-eol', 'ignore-all-space', 'allow-indentation-change'"
+msgstr ""
+
+msgid ""
+"color-moved-ws: allow-indentation-change cannot be combined with other "
+"whitespace modes"
+msgstr ""
+
+#, c-format
+msgid "Unknown value for 'diff.submodule' config variable: '%s'"
+msgstr ""
+
+#, c-format
+msgid ""
+"Found errors in 'diff.dirstat' config variable:\n"
+"%s"
+msgstr ""
+
+#, c-format
+msgid "external diff died, stopping at %s"
+msgstr ""
+
+#, c-format
+msgid "options '%s', '%s', '%s', and '%s' cannot be used together"
+msgstr "опції \"%s\", \"%s\", \"%s\" та \"%s\" неможливо використовувати разом"
+
+#, c-format
+msgid "options '%s' and '%s' cannot be used together, use '%s' with '%s'"
+msgstr ""
+"опції \"%s\" і \"%s\" неможливо використати разом, використовуйте \"%s\" з "
+"\"%s\""
+
+#, c-format
+msgid ""
+"options '%s' and '%s' cannot be used together, use '%s' with '%s' and '%s'"
+msgstr ""
+"опції \"%s\" і \"%s\" неможливо використати разом, використовуйте \"%s\" з "
+"\"%s\" та \"%s\""
+
+msgid "--follow requires exactly one pathspec"
+msgstr ""
+
+#, c-format
+msgid "invalid --stat value: %s"
+msgstr "неприпустиме --stat значення: %s"
+
+#, c-format
+msgid "%s expects a numerical value"
+msgstr ""
+
+#, c-format
+msgid ""
+"Failed to parse --dirstat/-X option parameter:\n"
+"%s"
+msgstr ""
+
+#, c-format
+msgid "unknown change class '%c' in --diff-filter=%s"
+msgstr ""
+
+#, c-format
+msgid "unknown value after ws-error-highlight=%.*s"
+msgstr ""
+
+#, c-format
+msgid "unable to resolve '%s'"
+msgstr "не вдалося розпізнати \"%s\""
+
+#, c-format
+msgid "%s expects <n>/<m> form"
+msgstr ""
+
+#, c-format
+msgid "%s expects a character, got '%s'"
+msgstr "%s очікує символ, отримано \"%s\""
+
+#, c-format
+msgid "bad --color-moved argument: %s"
+msgstr ""
+
+#, c-format
+msgid "invalid mode '%s' in --color-moved-ws"
+msgstr ""
+
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+
+#, c-format
+msgid "invalid argument to %s"
+msgstr "неприпустимий аргумент до %s"
+
+#, c-format
+msgid "invalid regex given to -I: '%s'"
+msgstr "неприпустимий regex, переданий до -I: \"%s\""
+
+#, c-format
+msgid "failed to parse --submodule option parameter: '%s'"
+msgstr "не вдалося розібрати параметр опції --submodule: \"%s\""
+
+#, c-format
+msgid "bad --word-diff argument: %s"
+msgstr ""
+
+msgid "Diff output format options"
+msgstr ""
+
+msgid "generate patch"
+msgstr "згенерувати латку"
+
+msgid "<n>"
+msgstr ""
+
+msgid "generate diffs with <n> lines context"
+msgstr ""
+
+msgid "generate the diff in raw format"
+msgstr ""
+
+msgid "synonym for '-p --raw'"
+msgstr ""
+
+msgid "synonym for '-p --stat'"
+msgstr ""
+
+msgid "machine friendly --stat"
+msgstr "машинний вивід --stat"
+
+msgid "output only the last line of --stat"
+msgstr ""
+
+msgid "<param1,param2>..."
+msgstr ""
+
+msgid ""
+"output the distribution of relative amount of changes for each sub-directory"
+msgstr ""
+
+msgid "synonym for --dirstat=cumulative"
+msgstr ""
+
+msgid "synonym for --dirstat=files,param1,param2..."
+msgstr ""
+
+msgid "warn if changes introduce conflict markers or whitespace errors"
+msgstr ""
+
+msgid "condensed summary such as creations, renames and mode changes"
+msgstr ""
+
+msgid "show only names of changed files"
+msgstr ""
+
+msgid "show only names and status of changed files"
+msgstr ""
+
+msgid "<width>[,<name-width>[,<count>]]"
+msgstr ""
+
+msgid "generate diffstat"
+msgstr ""
+
+msgid "<width>"
+msgstr ""
+
+msgid "generate diffstat with a given width"
+msgstr ""
+
+msgid "generate diffstat with a given name width"
+msgstr ""
+
+msgid "generate diffstat with a given graph width"
+msgstr ""
+
+msgid "<count>"
+msgstr ""
+
+msgid "generate diffstat with limited lines"
+msgstr ""
+
+msgid "generate compact summary in diffstat"
+msgstr ""
+
+msgid "output a binary diff that can be applied"
+msgstr ""
+
+msgid "show full pre- and post-image object names on the \"index\" lines"
+msgstr ""
+
+msgid "show colored diff"
+msgstr ""
+
+msgid "<kind>"
+msgstr ""
+
+msgid ""
+"highlight whitespace errors in the 'context', 'old' or 'new' lines in the "
+"diff"
+msgstr ""
+
+msgid ""
+"do not munge pathnames and use NULs as output field terminators in --raw or "
+"--numstat"
+msgstr ""
+
+msgid "<prefix>"
+msgstr ""
+
+msgid "show the given source prefix instead of \"a/\""
+msgstr ""
+
+msgid "show the given destination prefix instead of \"b/\""
+msgstr ""
+
+msgid "prepend an additional prefix to every line of output"
+msgstr ""
+
+msgid "do not show any source or destination prefix"
+msgstr ""
+
+msgid "use default prefixes a/ and b/"
+msgstr ""
+
+msgid "show context between diff hunks up to the specified number of lines"
+msgstr ""
+
+msgid "<char>"
+msgstr ""
+
+msgid "specify the character to indicate a new line instead of '+'"
+msgstr ""
+
+msgid "specify the character to indicate an old line instead of '-'"
+msgstr ""
+
+msgid "specify the character to indicate a context instead of ' '"
+msgstr ""
+
+msgid "Diff rename options"
+msgstr ""
+
+msgid "<n>[/<m>]"
+msgstr ""
+
+msgid "break complete rewrite changes into pairs of delete and create"
+msgstr ""
+
+msgid "detect renames"
+msgstr ""
+
+msgid "omit the preimage for deletes"
+msgstr ""
+
+msgid "detect copies"
+msgstr ""
+
+msgid "use unmodified files as source to find copies"
+msgstr ""
+
+msgid "disable rename detection"
+msgstr ""
+
+msgid "use empty blobs as rename source"
+msgstr ""
+
+msgid "continue listing the history of a file beyond renames"
+msgstr ""
+
+msgid ""
+"prevent rename/copy detection if the number of rename/copy targets exceeds "
+"given limit"
+msgstr ""
+
+msgid "Diff algorithm options"
+msgstr ""
+
+msgid "produce the smallest possible diff"
+msgstr ""
+
+msgid "ignore whitespace when comparing lines"
+msgstr ""
+
+msgid "ignore changes in amount of whitespace"
+msgstr ""
+
+msgid "ignore changes in whitespace at EOL"
+msgstr ""
+
+msgid "ignore carrier-return at the end of line"
+msgstr ""
+
+msgid "ignore changes whose lines are all blank"
+msgstr ""
+
+msgid "<regex>"
+msgstr ""
+
+msgid "ignore changes whose all lines match <regex>"
+msgstr ""
+
+msgid "heuristic to shift diff hunk boundaries for easy reading"
+msgstr ""
+
+msgid "generate diff using the \"patience diff\" algorithm"
+msgstr ""
+
+msgid "generate diff using the \"histogram diff\" algorithm"
+msgstr ""
+
+msgid "<algorithm>"
+msgstr ""
+
+msgid "choose a diff algorithm"
+msgstr ""
+
+msgid "<text>"
+msgstr ""
+
+msgid "generate diff using the \"anchored diff\" algorithm"
+msgstr ""
+
+msgid "<mode>"
+msgstr ""
+
+msgid "show word diff, using <mode> to delimit changed words"
+msgstr ""
+
+msgid "use <regex> to decide what a word is"
+msgstr ""
+
+msgid "equivalent to --word-diff=color --word-diff-regex=<regex>"
+msgstr ""
+
+msgid "moved lines of code are colored differently"
+msgstr ""
+
+msgid "how white spaces are ignored in --color-moved"
+msgstr ""
+
+msgid "Other diff options"
+msgstr ""
+
+msgid "when run from subdir, exclude changes outside and show relative paths"
+msgstr ""
+
+msgid "treat all files as text"
+msgstr ""
+
+msgid "swap two inputs, reverse the diff"
+msgstr ""
+
+msgid "exit with 1 if there were differences, 0 otherwise"
+msgstr ""
+
+msgid "disable all output of the program"
+msgstr ""
+
+msgid "allow an external diff helper to be executed"
+msgstr ""
+
+msgid "run external text conversion filters when comparing binary files"
+msgstr ""
+
+msgid "<when>"
+msgstr ""
+
+msgid "ignore changes to submodules in the diff generation"
+msgstr ""
+
+msgid "<format>"
+msgstr ""
+
+msgid "specify how differences in submodules are shown"
+msgstr ""
+
+msgid "hide 'git add -N' entries from the index"
+msgstr "приховати записи \"git add -N\" з індексу"
+
+msgid "treat 'git add -N' entries as real in the index"
+msgstr ""
+
+msgid "<string>"
+msgstr ""
+
+msgid ""
+"look for differences that change the number of occurrences of the specified "
+"string"
+msgstr ""
+
+msgid ""
+"look for differences that change the number of occurrences of the specified "
+"regex"
+msgstr ""
+
+msgid "show all changes in the changeset with -S or -G"
+msgstr ""
+
+msgid "treat <string> in -S as extended POSIX regular expression"
+msgstr ""
+
+msgid "control the order in which files appear in the output"
+msgstr ""
+
+msgid "<path>"
+msgstr "<шлях>"
+
+msgid "show the change in the specified path first"
+msgstr ""
+
+msgid "skip the output to the specified path"
+msgstr ""
+
+msgid "<object-id>"
+msgstr ""
+
+msgid ""
+"look for differences that change the number of occurrences of the specified "
+"object"
+msgstr ""
+
+msgid "[(A|C|D|M|R|T|U|X|B)...[*]]"
+msgstr ""
+
+msgid "select files by diff type"
+msgstr ""
+
+msgid "<file>"
+msgstr ""
+
+msgid "output to a specific file"
+msgstr ""
+
+msgid "exhaustive rename detection was skipped due to too many files."
+msgstr ""
+
+msgid "only found copies from modified paths due to too many files."
+msgstr ""
+
+#, c-format
+msgid ""
+"you may want to set your %s variable to at least %d and retry the command."
+msgstr ""
+
+#, c-format
+msgid "failed to read orderfile '%s'"
+msgstr "не вдалося прочитати orderfile \"%s\""
+
+msgid "Performing inexact rename detection"
+msgstr ""
+
+#, c-format
+msgid "No such path '%s' in the diff"
+msgstr ""
+
+#, c-format
+msgid "pathspec '%s' did not match any file(s) known to git"
+msgstr ""
+
+#, c-format
+msgid "unrecognized pattern: '%s'"
+msgstr "нерозпізнаний шаблон: \"%s\""
+
+#, c-format
+msgid "unrecognized negative pattern: '%s'"
+msgstr "нерозпізнаний негативний шаблон: \"%s\""
+
+#, c-format
+msgid "your sparse-checkout file may have issues: pattern '%s' is repeated"
+msgstr ""
+
+msgid "disabling cone pattern matching"
+msgstr ""
+
+#, c-format
+msgid "cannot use %s as an exclude file"
+msgstr "неможливо використовувати %s як файл виключення"
+
+msgid "failed to get kernel name and information"
+msgstr ""
+
+msgid "untracked cache is disabled on this system or location"
+msgstr ""
+
+msgid ""
+"No directory name could be guessed.\n"
+"Please specify a directory on the command line"
+msgstr ""
+
+#, c-format
+msgid "index file corrupt in repo %s"
+msgstr "пошкоджено індексний файл у сховищі %s"
+
+#, c-format
+msgid "could not create directories for %s"
+msgstr "не вдалося створити директорії для %s"
+
+#, c-format
+msgid "could not migrate git directory from '%s' to '%s'"
+msgstr "не вдалося перенести git директорію з \"%s\" до \"%s\""
+
+#, c-format
+msgid "hint: Waiting for your editor to close the file...%c"
+msgstr ""
+
+#, c-format
+msgid "could not write to '%s'"
+msgstr "не вдалося записати в \"%s\""
+
+#, c-format
+msgid "could not edit '%s'"
+msgstr "не вдалося відредагувати \"%s\""
+
+msgid "Filtering content"
+msgstr ""
+
+#, c-format
+msgid "could not stat file '%s'"
+msgstr "не вдалося виконати stat для %s"
+
+#, c-format
+msgid "bad git namespace path \"%s\""
+msgstr ""
+
+#, c-format
+msgid "too many args to run %s"
+msgstr "забагато аргументів для запуску %s"
+
+msgid "git fetch-pack: expected shallow list"
+msgstr ""
+
+msgid "git fetch-pack: expected a flush packet after shallow list"
+msgstr ""
+
+msgid "git fetch-pack: expected ACK/NAK, got a flush packet"
+msgstr ""
+
+#, c-format
+msgid "git fetch-pack: expected ACK/NAK, got '%s'"
+msgstr "git fetch-pack: очікувалось ACK/NAK, отримано \"%s\""
+
+msgid "unable to write to remote"
+msgstr "не вдалося записати до віддаленого сховища"
+
+msgid "Server supports filter"
+msgstr ""
+
+#, c-format
+msgid "invalid shallow line: %s"
+msgstr "неприпустимий shallow рядок: %s"
+
+#, c-format
+msgid "invalid unshallow line: %s"
+msgstr "неприпустимий unshallow рядок: %s"
+
+#, c-format
+msgid "object not found: %s"
+msgstr ""
+
+#, c-format
+msgid "error in object: %s"
+msgstr "помилка в обʼєкті: %s"
+
+#, c-format
+msgid "no shallow found: %s"
+msgstr ""
+
+#, c-format
+msgid "expected shallow/unshallow, got %s"
+msgstr ""
+
+#, c-format
+msgid "got %s %d %s"
+msgstr ""
+
+#, c-format
+msgid "invalid commit %s"
+msgstr "неприпустимий коміт %s"
+
+msgid "giving up"
+msgstr ""
+
+msgid "done"
+msgstr "готово"
+
+#, c-format
+msgid "got %s (%d) %s"
+msgstr ""
+
+#, c-format
+msgid "Marking %s as complete"
+msgstr ""
+
+#, c-format
+msgid "already have %s (%s)"
+msgstr ""
+
+msgid "fetch-pack: unable to fork off sideband demultiplexer"
+msgstr ""
+
+msgid "protocol error: bad pack header"
+msgstr ""
+
+#, c-format
+msgid "fetch-pack: unable to fork off %s"
+msgstr ""
+
+msgid "fetch-pack: invalid index-pack output"
+msgstr ""
+
+#, c-format
+msgid "%s failed"
+msgstr ""
+
+msgid "error in sideband demultiplexer"
+msgstr ""
+
+#, c-format
+msgid "Server version is %.*s"
+msgstr ""
+
+#, c-format
+msgid "Server supports %s"
+msgstr ""
+
+msgid "Server does not support shallow clients"
+msgstr ""
+
+msgid "Server does not support --shallow-since"
+msgstr ""
+
+msgid "Server does not support --shallow-exclude"
+msgstr ""
+
+msgid "Server does not support --deepen"
+msgstr ""
+
+msgid "Server does not support this repository's object format"
+msgstr ""
+
+msgid "no common commits"
+msgstr "немає спільних комітів"
+
+msgid "git fetch-pack: fetch failed."
+msgstr ""
+
+#, c-format
+msgid "mismatched algorithms: client %s; server %s"
+msgstr ""
+
+#, c-format
+msgid "the server does not support algorithm '%s'"
+msgstr "сервер не підтримує алгоритм \"%s\""
+
+msgid "Server does not support shallow requests"
+msgstr ""
+
+msgid "unable to write request to remote"
+msgstr "не вдалося записати запит до віддаленого сховища"
+
+#, c-format
+msgid "expected '%s', received '%s'"
+msgstr "очікувалось \"%s\", отримано \"%s\""
+
+#, c-format
+msgid "expected '%s'"
+msgstr "очікувалось \"%s\""
+
+#, c-format
+msgid "unexpected acknowledgment line: '%s'"
+msgstr ""
+
+#, c-format
+msgid "error processing acks: %d"
+msgstr ""
+
+#. TRANSLATORS: The parameter will be 'ready', a protocol
+#. keyword.
+#.
+
+#, c-format
+msgid "expected packfile to be sent after '%s'"
+msgstr ""
+
+#. TRANSLATORS: The parameter will be 'ready', a protocol
+#. keyword.
+#.
+
+#, c-format
+msgid "expected no other sections to be sent after no '%s'"
+msgstr ""
+
+#, c-format
+msgid "error processing shallow info: %d"
+msgstr ""
+
+#, c-format
+msgid "expected wanted-ref, got '%s'"
+msgstr "очікувалося wanted-ref, отримано \"%s\""
+
+#, c-format
+msgid "unexpected wanted-ref: '%s'"
+msgstr ""
+
+#, c-format
+msgid "error processing wanted refs: %d"
+msgstr ""
+
+msgid "git fetch-pack: expected response end packet"
+msgstr ""
+
+msgid "no matching remote head"
+msgstr ""
+
+msgid "unexpected 'ready' from remote"
+msgstr ""
+
+#, c-format
+msgid "no such remote ref %s"
+msgstr "немає такого віддаленного посилання %s"
+
+#, c-format
+msgid "Server does not allow request for unadvertised object %s"
+msgstr ""
+
+#, c-format
+msgid "fsmonitor_ipc__send_query: invalid path '%s'"
+msgstr ""
+
+#, c-format
+msgid "fsmonitor_ipc__send_query: unspecified error on '%s'"
+msgstr ""
+
+msgid "fsmonitor--daemon is not running"
+msgstr ""
+
+#, c-format
+msgid "could not send '%s' command to fsmonitor--daemon"
+msgstr ""
+
+#, c-format
+msgid "bare repository '%s' is incompatible with fsmonitor"
+msgstr "порожнє сховище \"%s\" несумісне з fsmonitor"
+
+#, c-format
+msgid "repository '%s' is incompatible with fsmonitor due to errors"
+msgstr ""
+
+#, c-format
+msgid "remote repository '%s' is incompatible with fsmonitor"
+msgstr "віддалене сховище \"%s\" несумісне з fsmonitor"
+
+#, c-format
+msgid "virtual repository '%s' is incompatible with fsmonitor"
+msgstr ""
+
+#, c-format
+msgid ""
+"socket directory '%s' is incompatible with fsmonitor due to lack of Unix "
+"sockets support"
+msgstr ""
+
+msgid ""
+"git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n"
+"           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
+"           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--"
+"bare]\n"
+"           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
+"           [--config-env=<name>=<envvar>] <command> [<args>]"
+msgstr ""
+
+msgid ""
+"'git help -a' and 'git help -g' list available subcommands and some\n"
+"concept guides. See 'git help <command>' or 'git help <concept>'\n"
+"to read about a specific subcommand or concept.\n"
+"See 'git help git' for an overview of the system."
+msgstr ""
+
+#, c-format
+msgid "unsupported command listing type '%s'"
+msgstr ""
+
+#, c-format
+msgid "no directory given for '%s' option\n"
+msgstr ""
+
+#, c-format
+msgid "no namespace given for --namespace\n"
+msgstr ""
+
+#, c-format
+msgid "-c expects a configuration string\n"
+msgstr ""
+
+#, c-format
+msgid "no config key given for --config-env\n"
+msgstr ""
+
+#, c-format
+msgid "unknown option: %s\n"
+msgstr ""
+
+#, c-format
+msgid "while expanding alias '%s': '%s'"
+msgstr ""
+
+#, c-format
+msgid ""
+"alias '%s' changes environment variables.\n"
+"You can use '!git' in the alias to do this"
+msgstr ""
+
+#, c-format
+msgid "empty alias for %s"
+msgstr ""
+
+#, c-format
+msgid "recursive alias: %s"
+msgstr ""
+
+msgid "write failure on standard output"
+msgstr ""
+
+msgid "unknown write failure on standard output"
+msgstr ""
+
+msgid "close failed on standard output"
+msgstr ""
+
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr ""
+
+#, c-format
+msgid "cannot handle %s as a builtin"
+msgstr ""
+
+#, c-format
+msgid ""
+"usage: %s\n"
+"\n"
+msgstr ""
+
+#, c-format
+msgid "expansion of alias '%s' failed; '%s' is not a git command\n"
+msgstr ""
+
+#, c-format
+msgid "failed to run command '%s': %s\n"
+msgstr "не вдалося виконати команду \"%s\": %s\n"
+
+msgid "could not create temporary file"
+msgstr "не вдалося створити тимчасовий файл"
+
+#, c-format
+msgid "failed writing detached signature to '%s'"
+msgstr "не вдалося записати відʼєднаний підпис до \"%s\""
+
+msgid ""
+"gpg.ssh.allowedSignersFile needs to be configured and exist for ssh "
+"signature verification"
+msgstr ""
+
+msgid ""
+"ssh-keygen -Y find-principals/verify is needed for ssh signature "
+"verification (available in openssh version 8.2p1+)"
+msgstr ""
+
+#, c-format
+msgid "ssh signing revocation file configured but not found: %s"
+msgstr ""
+
+#, c-format
+msgid "bad/incompatible signature '%s'"
+msgstr ""
+
+#, c-format
+msgid "failed to get the ssh fingerprint for key '%s'"
+msgstr "не вдалося отримати ssh відбиток для ключа \"%s\""
+
+msgid ""
+"either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
+msgstr ""
+
+#, c-format
+msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
+msgstr ""
+
+#, c-format
+msgid "gpg.ssh.defaultKeyCommand failed: %s %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"gpg failed to sign the data:\n"
+"%s"
+msgstr ""
+"gpg не вдалося підписати дані:\n"
+"%s"
+
+msgid "user.signingKey needs to be set for ssh signing"
+msgstr ""
+
+#, c-format
+msgid "failed writing ssh signing key to '%s'"
+msgstr "не вдалося записати ssh ключ підпису до \"%s\""
+
+#, c-format
+msgid "failed writing ssh signing key buffer to '%s'"
+msgstr "не вдалося записати буфер ssh ключа підпису в \"%s\""
+
+msgid ""
+"ssh-keygen -Y sign is needed for ssh signing (available in openssh version "
+"8.2p1+)"
+msgstr ""
+
+#, c-format
+msgid "failed reading ssh signing data buffer from '%s'"
+msgstr ""
+
+#, c-format
+msgid "ignored invalid color '%.*s' in log.graphColors"
+msgstr ""
+
+msgid ""
+"given pattern contains NULL byte (via -f <file>). This is only supported "
+"with -P under PCRE v2"
+msgstr ""
+
+#, c-format
+msgid "'%s': unable to read %s"
+msgstr "\"%s\": не вдалося прочитати %s"
+
+#, c-format
+msgid "'%s': short read"
+msgstr ""
+
+msgid "start a working area (see also: git help tutorial)"
+msgstr ""
+
+msgid "work on the current change (see also: git help everyday)"
+msgstr ""
+
+msgid "examine the history and state (see also: git help revisions)"
+msgstr ""
+
+msgid "grow, mark and tweak your common history"
+msgstr ""
+
+msgid "collaborate (see also: git help workflows)"
+msgstr ""
+
+msgid "Main Porcelain Commands"
+msgstr ""
+
+msgid "Ancillary Commands / Manipulators"
+msgstr ""
+
+msgid "Ancillary Commands / Interrogators"
+msgstr ""
+
+msgid "Interacting with Others"
+msgstr ""
+
+msgid "Low-level Commands / Manipulators"
+msgstr ""
+
+msgid "Low-level Commands / Interrogators"
+msgstr ""
+
+msgid "Low-level Commands / Syncing Repositories"
+msgstr ""
+
+msgid "Low-level Commands / Internal Helpers"
+msgstr ""
+
+msgid "User-facing repository, command and file interfaces"
+msgstr ""
+
+msgid "Developer-facing file formats, protocols and other interfaces"
+msgstr ""
+
+#, c-format
+msgid "available git commands in '%s'"
+msgstr "доступні команди git в \"%s\""
+
+msgid "git commands available from elsewhere on your $PATH"
+msgstr ""
+
+msgid "These are common Git commands used in various situations:"
+msgstr ""
+
+msgid "The Git concept guides are:"
+msgstr ""
+
+msgid "User-facing repository, command and file interfaces:"
+msgstr ""
+
+msgid "File formats, protocols and other developer interfaces:"
+msgstr ""
+
+msgid "External commands"
+msgstr ""
+
+msgid "Command aliases"
+msgstr ""
+
+msgid "See 'git help <command>' to read about a specific subcommand"
+msgstr ""
+
+#, c-format
+msgid ""
+"'%s' appears to be a git command, but we were not\n"
+"able to execute it. Maybe git-%s is broken?"
+msgstr ""
+
+#, c-format
+msgid "git: '%s' is not a git command. See 'git --help'."
+msgstr ""
+
+msgid "Uh oh. Your system reports no Git commands at all."
+msgstr ""
+
+#, c-format
+msgid "WARNING: You called a Git command named '%s', which does not exist."
+msgstr ""
+
+#, c-format
+msgid "Continuing under the assumption that you meant '%s'."
+msgstr ""
+
+#, c-format
+msgid "Run '%s' instead [y/N]? "
+msgstr ""
+
+#, c-format
+msgid "Continuing in %0.1f seconds, assuming that you meant '%s'."
+msgstr ""
+
+msgid ""
+"\n"
+"The most similar command is"
+msgid_plural ""
+"\n"
+"The most similar commands are"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "git version [--build-options]"
+msgstr ""
+
+#, c-format
+msgid "%s: %s - %s"
+msgstr ""
+
+msgid ""
+"\n"
+"Did you mean this?"
+msgid_plural ""
+"\n"
+"Did you mean one of these?"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#, c-format
+msgid ""
+"The '%s' hook was ignored because it's not set as executable.\n"
+"You can disable this warning with `git config advice.ignoredHook false`."
+msgstr ""
+
+#, c-format
+msgid "argument to --packfile must be a valid hash (got '%s')"
+msgstr ""
+
+msgid "not a git repository"
+msgstr "не є git сховищем"
+
+#, c-format
+msgid "negative value for http.postBuffer; defaulting to %d"
+msgstr ""
+
+msgid "Delegation control is not supported with cURL < 7.22.0"
+msgstr ""
+
+msgid "Public key pinning not supported with cURL < 7.39.0"
+msgstr ""
+
+msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0"
+msgstr ""
+
+#, c-format
+msgid "Unsupported SSL backend '%s'. Supported SSL backends:"
+msgstr ""
+
+#, c-format
+msgid "Could not set SSL backend to '%s': cURL was built without SSL backends"
+msgstr ""
+
+#, c-format
+msgid "Could not set SSL backend to '%s': already set"
+msgstr ""
+
+#, c-format
+msgid ""
+"unable to update url base from redirection:\n"
+"  asked for: %s\n"
+"   redirect: %s"
+msgstr ""
+
+msgid "Author identity unknown\n"
+msgstr ""
+
+msgid "Committer identity unknown\n"
+msgstr ""
+
+msgid ""
+"\n"
+"*** Please tell me who you are.\n"
+"\n"
+"Run\n"
+"\n"
+"  git config --global user.email \"you@example.com\"\n"
+"  git config --global user.name \"Your Name\"\n"
+"\n"
+"to set your account's default identity.\n"
+"Omit --global to set the identity only in this repository.\n"
+"\n"
+msgstr ""
+
+msgid "no email was given and auto-detection is disabled"
+msgstr ""
+
+#, c-format
+msgid "unable to auto-detect email address (got '%s')"
+msgstr ""
+
+msgid "no name was given and auto-detection is disabled"
+msgstr ""
+
+#, c-format
+msgid "unable to auto-detect name (got '%s')"
+msgstr "не вдалося автоматично визначити назву (отримано \"%s\")"
+
+#, c-format
+msgid "empty ident name (for <%s>) not allowed"
+msgstr ""
+
+#, c-format
+msgid "name consists only of disallowed characters: %s"
+msgstr ""
+
+msgid "expected 'tree:<depth>'"
+msgstr ""
+
+msgid "sparse:path filters support has been dropped"
+msgstr ""
+
+#, c-format
+msgid "'%s' for 'object:type=<type>' is not a valid object type"
+msgstr ""
+
+#, c-format
+msgid "invalid filter-spec '%s'"
+msgstr "неприпустимий визначник фільтра \"%s\""
+
+#, c-format
+msgid "must escape char in sub-filter-spec: '%c'"
+msgstr ""
+
+msgid "expected something after combine:"
+msgstr ""
+
+msgid "multiple filter-specs cannot be combined"
+msgstr ""
+
+msgid "unable to upgrade repository format to support partial clone"
+msgstr ""
+
+msgid "args"
+msgstr ""
+
+msgid "object filtering"
+msgstr ""
+
+#, c-format
+msgid "unable to access sparse blob in '%s'"
+msgstr "не вдалося отримати доступ до часткового blob в \"%s\""
+
+#, c-format
+msgid "unable to parse sparse filter data in %s"
+msgstr "не вдалося розібрати дані часткового фільтра в %s"
+
+#, c-format
+msgid "entry '%s' in tree %s has tree mode, but is not a tree"
+msgstr ""
+
+#, c-format
+msgid "entry '%s' in tree %s has blob mode, but is not a blob"
+msgstr ""
+
+#, c-format
+msgid "unable to load root tree for commit %s"
+msgstr "не вдалося завантажити кореневе дерево для коміту %s"
+
+#, c-format
+msgid ""
+"Unable to create '%s.lock': %s.\n"
+"\n"
+"Another git process seems to be running in this repository, e.g.\n"
+"an editor opened by 'git commit'. Please make sure all processes\n"
+"are terminated then try again. If it still fails, a git process\n"
+"may have crashed in this repository earlier:\n"
+"remove the file manually to continue."
+msgstr ""
+
+#, c-format
+msgid "Unable to create '%s.lock': %s"
+msgstr "Не вдалося створити \"%s.lock\": %s"
+
+#, c-format
+msgid "unexpected line: '%s'"
+msgstr ""
+
+msgid "expected flush after ls-refs arguments"
+msgstr ""
+
+msgid "quoted CRLF detected"
+msgstr ""
+
+#, c-format
+msgid "Failed to merge submodule %s (not checked out)"
+msgstr ""
+
+#, c-format
+msgid "Failed to merge submodule %s (no merge base)"
+msgstr ""
+
+#, c-format
+msgid "Failed to merge submodule %s (commits not present)"
+msgstr ""
+
+#, c-format
+msgid "Failed to merge submodule %s (commits don't follow merge-base)"
+msgstr ""
+
+#, c-format
+msgid "Note: Fast-forwarding submodule %s to %s"
+msgstr ""
+
+#, c-format
+msgid "Failed to merge submodule %s"
+msgstr "Не вдалося злити підмодуль %s"
+
+#, c-format
+msgid ""
+"Failed to merge submodule %s, but a possible merge resolution exists: %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"Failed to merge submodule %s, but multiple possible merges exist:\n"
+"%s"
+msgstr ""
+
+msgid "Failed to execute internal merge"
+msgstr ""
+
+#, c-format
+msgid "Unable to add %s to database"
+msgstr "Не вдалося додати %s до бази даних"
+
+#, c-format
+msgid "Auto-merging %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (implicit dir rename): Existing file/dir at %s in the way of "
+"implicit directory rename(s) putting the following path(s) there: %s."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (implicit dir rename): Cannot map more than one path to %s; "
+"implicit directory renames tried to put these paths there: %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (directory rename split): Unclear where to rename %s to; it was "
+"renamed to multiple other directories, with no destination getting a "
+"majority of the files."
+msgstr ""
+
+#, c-format
+msgid ""
+"WARNING: Avoiding applying %s -> %s rename to %s, because %s itself was "
+"renamed."
+msgstr ""
+
+#, c-format
+msgid ""
+"Path updated: %s added in %s inside a directory that was renamed in %s; "
+"moving it to %s."
+msgstr ""
+
+#, c-format
+msgid ""
+"Path updated: %s renamed to %s in %s, inside a directory that was renamed in "
+"%s; moving it to %s."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (file location): %s added in %s inside a directory that was renamed "
+"in %s, suggesting it should perhaps be moved to %s."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (file location): %s renamed to %s in %s, inside a directory that "
+"was renamed in %s, suggesting it should perhaps be moved to %s."
+msgstr ""
+
+#, c-format
+msgid "CONFLICT (rename/rename): %s renamed to %s in %s and to %s in %s."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (rename involved in collision): rename of %s -> %s has content "
+"conflicts AND collides with another path; this may result in nested conflict "
+"markers."
+msgstr ""
+
+#, c-format
+msgid "CONFLICT (rename/delete): %s renamed to %s in %s, but deleted in %s."
+msgstr ""
+
+#, c-format
+msgid "cannot read object %s"
+msgstr "неможливо прочитати обʼєкт %s"
+
+#, c-format
+msgid "object %s is not a blob"
+msgstr "обʼєкт %s не є blob"
+
+#, c-format
+msgid ""
+"CONFLICT (file/directory): directory in the way of %s from %s; moving it to "
+"%s instead."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (distinct types): %s had different types on each side; renamed both "
+"of them so each can be recorded somewhere."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (distinct types): %s had different types on each side; renamed one "
+"of them so each can be recorded somewhere."
+msgstr ""
+
+msgid "content"
+msgstr ""
+
+msgid "add/add"
+msgstr ""
+
+msgid "submodule"
+msgstr ""
+
+#, c-format
+msgid "CONFLICT (%s): Merge conflict in %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (modify/delete): %s deleted in %s and modified in %s.  Version %s "
+"of %s left in tree."
+msgstr ""
+
+#. TRANSLATORS: This is a line of advice to resolve a merge
+#. conflict in a submodule. The first argument is the submodule
+#. name, and the second argument is the abbreviated id of the
+#. commit that needs to be merged.  For example:
+#. - go to submodule (mysubmodule), and either merge commit abc1234"
+#.
+
+#, c-format
+msgid ""
+" - go to submodule (%s), and either merge commit %s\n"
+"   or update to an existing commit which has merged those changes\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"Recursive merging with submodules currently only supports trivial cases.\n"
+"Please manually handle the merging of each conflicted submodule.\n"
+"This can be accomplished with the following steps:\n"
+"%s - come back to superproject and run:\n"
+"\n"
+"      git add %s\n"
+"\n"
+"   to record the above merge or update\n"
+" - resolve any other conflicts in the superproject\n"
+" - commit the resulting index in the superproject\n"
+msgstr ""
+
+#. TRANSLATORS: The %s arguments are: 1) tree hash of a merge
+#. base, and 2-3) the trees for the two trees we're merging.
+#.
+
+#, c-format
+msgid "collecting merge info failed for trees %s, %s, %s"
+msgstr ""
+
+msgid "(bad commit)\n"
+msgstr ""
+
+#, c-format
+msgid "add_cacheinfo failed for path '%s'; merge aborting."
+msgstr "невдала спроба add_cacheinfo для шляху \"%s\"; переривання злиття."
+
+#, c-format
+msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting."
+msgstr ""
+
+#, c-format
+msgid "failed to create path '%s'%s"
+msgstr "не вдалося створити шлях \"%s\"%s"
+
+#, c-format
+msgid "Removing %s to make room for subdirectory\n"
+msgstr ""
+
+msgid ": perhaps a D/F conflict?"
+msgstr ""
+
+#, c-format
+msgid "refusing to lose untracked file at '%s'"
+msgstr "відмова від втрати невідстежуваного файла \"%s\""
+
+#, c-format
+msgid "blob expected for %s '%s'"
+msgstr "blob очікується для %s \"%s\""
+
+#, c-format
+msgid "failed to open '%s': %s"
+msgstr "не вдалося відкрити \"%s\": %s"
+
+#, c-format
+msgid "failed to symlink '%s': %s"
+msgstr "не вдалося зробити символьне посилання \"%s\": %s"
+
+#, c-format
+msgid "do not know what to do with %06o %s '%s'"
+msgstr ""
+
+#, c-format
+msgid "Fast-forwarding submodule %s to the following commit:"
+msgstr ""
+
+#, c-format
+msgid "Fast-forwarding submodule %s"
+msgstr ""
+
+#, c-format
+msgid "Failed to merge submodule %s (merge following commits not found)"
+msgstr ""
+
+#, c-format
+msgid "Failed to merge submodule %s (not fast-forward)"
+msgstr ""
+
+msgid "Found a possible merge resolution for the submodule:\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"If this is correct simply add it to the index for example\n"
+"by using:\n"
+"\n"
+"  git update-index --cacheinfo 160000 %s \"%s\"\n"
+"\n"
+"which will accept this suggestion.\n"
+msgstr ""
+
+#, c-format
+msgid "Failed to merge submodule %s (multiple merges found)"
+msgstr ""
+
+#, c-format
+msgid "Error: Refusing to lose untracked file at %s; writing to %s instead."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
+"in tree."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s "
+"left in tree."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
+"in tree at %s."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s "
+"left in tree at %s."
+msgstr ""
+
+msgid "rename"
+msgstr "перейменувати"
+
+msgid "renamed"
+msgstr "перейменовано"
+
+#, c-format
+msgid "Refusing to lose dirty file at %s"
+msgstr "Відмова від втрати брудного файла %s"
+
+#, c-format
+msgid "Refusing to lose untracked file at %s, even though it's in the way."
+msgstr ""
+
+#, c-format
+msgid "CONFLICT (rename/add): Rename %s->%s in %s.  Added %s in %s"
+msgstr ""
+
+#, c-format
+msgid "%s is a directory in %s adding as %s instead"
+msgstr ""
+
+#, c-format
+msgid "Refusing to lose untracked file at %s; adding as %s instead"
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename "
+"\"%s\"->\"%s\" in \"%s\"%s"
+msgstr ""
+
+msgid " (left unresolved)"
+msgstr ""
+
+#, c-format
+msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (directory rename split): Unclear where to place %s because "
+"directory %s was renamed to multiple other directories, with no destination "
+"getting a majority of the files."
+msgstr ""
+
+#, c-format
+msgid ""
+"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-"
+">%s in %s"
+msgstr ""
+
+msgid "modify"
+msgstr "змінити"
+
+msgid "modified"
+msgstr "змінено"
+
+#, c-format
+msgid "Skipped %s (merged same as existing)"
+msgstr ""
+
+#, c-format
+msgid "Adding as %s instead"
+msgstr ""
+
+#, c-format
+msgid "Removing %s"
+msgstr "Видалення %s"
+
+msgid "file/directory"
+msgstr "файл/директорія"
+
+msgid "directory/file"
+msgstr ""
+
+#, c-format
+msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s"
+msgstr ""
+
+#, c-format
+msgid "Adding %s"
+msgstr ""
+
+#, c-format
+msgid "CONFLICT (add/add): Merge conflict in %s"
+msgstr ""
+
+#, c-format
+msgid "merging of trees %s and %s failed"
+msgstr ""
+
+msgid "Merging:"
+msgstr ""
+
+#, c-format
+msgid "found %u common ancestor:"
+msgid_plural "found %u common ancestors:"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "merge returned no commit"
+msgstr ""
+
+#, c-format
+msgid "Could not parse object '%s'"
+msgstr "Не вдалося розібрати обʼєкт \"%s\""
+
+msgid "failed to read the cache"
+msgstr "не вдалося прочитати кеш"
+
+msgid "multi-pack-index OID fanout is of the wrong size"
+msgstr ""
+
+#, c-format
+msgid "multi-pack-index file %s is too small"
+msgstr ""
+
+#, c-format
+msgid "multi-pack-index signature 0x%08x does not match signature 0x%08x"
+msgstr ""
+
+#, c-format
+msgid "multi-pack-index version %d not recognized"
+msgstr ""
+
+#, c-format
+msgid "multi-pack-index hash version %u does not match version %u"
+msgstr ""
+
+msgid "multi-pack-index missing required pack-name chunk"
+msgstr ""
+
+msgid "multi-pack-index missing required OID fanout chunk"
+msgstr ""
+
+msgid "multi-pack-index missing required OID lookup chunk"
+msgstr ""
+
+msgid "multi-pack-index missing required object offsets chunk"
+msgstr ""
+
+#, c-format
+msgid "multi-pack-index pack names out of order: '%s' before '%s'"
+msgstr ""
+
+#, c-format
+msgid "bad pack-int-id: %u (%u total packs)"
+msgstr ""
+
+msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
+msgstr ""
+
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "не вдалося додати packfile \"%s\""
+
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "не вдалося відкрити pack-index \"%s\""
+
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr ""
+
+msgid "cannot store reverse index file"
+msgstr "неможливо зберегти файл зворотнього індексу"
+
+#, c-format
+msgid "could not parse line: %s"
+msgstr "не вдалося розібрати рядок: %s"
+
+#, c-format
+msgid "malformed line: %s"
+msgstr ""
+
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr ""
+
+msgid "could not load pack"
+msgstr "не вдалося завантажити пакет"
+
+#, c-format
+msgid "could not open index for %s"
+msgstr "не вдалося відкрити індекс для %s"
+
+msgid "Adding packfiles to multi-pack-index"
+msgstr ""
+
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr ""
+
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr ""
+
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr ""
+
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr ""
+
+msgid "no pack files to index."
+msgstr ""
+
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr ""
+
+msgid "could not write multi-pack bitmap"
+msgstr ""
+
+msgid "could not write multi-pack-index"
+msgstr "не вдалося записати multi-pack-index"
+
+#, c-format
+msgid "failed to clear multi-pack-index at %s"
+msgstr "не вдалося очистити multi-pack-index при %s"
+
+msgid "multi-pack-index file exists, but failed to parse"
+msgstr ""
+
+msgid "incorrect checksum"
+msgstr ""
+
+msgid "Looking for referenced packfiles"
+msgstr "Пошук файлів пакунків, на які є посилання"
+
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr ""
+
+msgid "the midx contains no oid"
+msgstr ""
+
+msgid "Verifying OID order in multi-pack-index"
+msgstr ""
+
+#, c-format
+msgid "oid lookup out of order: oid[%d] = %s >= %s = oid[%d]"
+msgstr ""
+
+msgid "Sorting objects by packfile"
+msgstr ""
+
+msgid "Verifying object offsets"
+msgstr "Перевірка зміщень обʼєкта"
+
+#, c-format
+msgid "failed to load pack entry for oid[%d] = %s"
+msgstr ""
+
+#, c-format
+msgid "failed to load pack-index for packfile %s"
+msgstr ""
+
+#, c-format
+msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
+msgstr ""
+
+msgid "Counting referenced objects"
+msgstr "Підрахунок обʼєктів, на які є посилання"
+
+msgid "Finding and deleting unreferenced packfiles"
+msgstr ""
+
+msgid "could not start pack-objects"
+msgstr "не вдалося розпочати pack-objects"
+
+msgid "could not finish pack-objects"
+msgstr "не вдалося завершити pack-objects"
+
+#, c-format
+msgid "unable to create lazy_dir thread: %s"
+msgstr "не вдалося створити lazy_dir потік: %s"
+
+#, c-format
+msgid "unable to create lazy_name thread: %s"
+msgstr "не вдалося створити lazy_name потік: %s"
+
+#, c-format
+msgid "unable to join lazy_name thread: %s"
+msgstr "не вдалося приєднатися до lazy_name потоку: %s"
+
+#, c-format
+msgid ""
+"You have not concluded your previous notes merge (%s exists).\n"
+"Please, use 'git notes merge --commit' or 'git notes merge --abort' to "
+"commit/abort the previous merge before you start a new notes merge."
+msgstr ""
+
+#, c-format
+msgid "You have not concluded your notes merge (%s exists)."
+msgstr ""
+
+msgid "Cannot commit uninitialized/unreferenced notes tree"
+msgstr ""
+
+#, c-format
+msgid "Bad notes.rewriteMode value: '%s'"
+msgstr ""
+
+#, c-format
+msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
+msgstr ""
+
+#. TRANSLATORS: The first %s is the name of
+#. the environment variable, the second %s is
+#. its value.
+#.
+
+#, c-format
+msgid "Bad %s value: '%s'"
+msgstr "Невірне %s значення: \"%s\""
+
+#, c-format
+msgid "object directory %s does not exist; check .git/objects/info/alternates"
+msgstr ""
+
+#, c-format
+msgid "unable to normalize alternate object path: %s"
+msgstr "не вдалося нормалізувати шлях альтернативного обʼєкта: %s"
+
+#, c-format
+msgid "%s: ignoring alternate object stores, nesting too deep"
+msgstr ""
+
+msgid "unable to fdopen alternates lockfile"
+msgstr "не вдалося виконати fdopen для файла блокування спільних обʼєктів"
+
+msgid "unable to read alternates file"
+msgstr "не вдалося прочитати файл спільних обʼєктів"
+
+msgid "unable to move new alternates file into place"
+msgstr "не вдалося перемістити файл нових спільних обʼєктів на місце"
+
+#, c-format
+msgid "path '%s' does not exist"
+msgstr "шлях \"%s\" не існує"
+
+#, c-format
+msgid "reference repository '%s' as a linked checkout is not supported yet."
+msgstr ""
+
+#, c-format
+msgid "reference repository '%s' is not a local repository."
+msgstr "сховище посилання \"%s\" не є локальним сховищем."
+
+#, c-format
+msgid "reference repository '%s' is shallow"
+msgstr "сховище посилання \"%s\" є поверхневим"
+
+#, c-format
+msgid "reference repository '%s' is grafted"
+msgstr "сховище посилання \"%s\" прищеплено"
+
+#, c-format
+msgid "could not find object directory matching %s"
+msgstr "не вдалося знайти директорію обʼєктів, що відповідає %s"
+
+#, c-format
+msgid "invalid line while parsing alternate refs: %s"
+msgstr ""
+
+#, c-format
+msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>"
+msgstr ""
+
+#, c-format
+msgid "mmap failed%s"
+msgstr ""
+
+#, c-format
+msgid "object file %s is empty"
+msgstr "обʼєктний файл %s порожній"
+
+#, c-format
+msgid "corrupt loose object '%s'"
+msgstr "пошкоджено вільний обʼєкт \"%s\""
+
+#, c-format
+msgid "garbage at end of loose object '%s'"
+msgstr ""
+
+#, c-format
+msgid "unable to open loose object %s"
+msgstr "не вдалося відкрити вільний обʼєкт %s"
+
+#, c-format
+msgid "unable to parse %s header"
+msgstr "не вдалося розібрати заголовок %s"
+
+msgid "invalid object type"
+msgstr "неприпустимий тип обʼєкта"
+
+#, c-format
+msgid "unable to unpack %s header"
+msgstr "не вдалося розпакувати %s заголовок"
+
+#, c-format
+msgid "header for %s too long, exceeds %d bytes"
+msgstr ""
+
+#, c-format
+msgid "loose object %s (stored in %s) is corrupt"
+msgstr "вільний обʼєкт %s (що зберігається у %s) пошкоджено"
+
+#, c-format
+msgid "replacement %s not found for %s"
+msgstr "заміна %s не знайдена для %s"
+
+#, c-format
+msgid "packed object %s (stored in %s) is corrupt"
+msgstr "упакований обʼєкт %s (що зберігається у %s) пошкоджено"
+
+#, c-format
+msgid "unable to write file %s"
+msgstr "не вдалося записати файл %s"
+
+#, c-format
+msgid "unable to set permission to '%s'"
+msgstr "не вдалося встановити права доступу до \"%s\""
+
+msgid "error when closing loose object file"
+msgstr "помилка при закритті файла вільного об’єкта"
+
+#, c-format
+msgid "insufficient permission for adding an object to repository database %s"
+msgstr ""
+
+msgid "unable to create temporary file"
+msgstr "не вдалося створити тимчасовий файл"
+
+msgid "unable to write loose object file"
+msgstr "не вдалося записати файл вільного об’єкта"
+
+#, c-format
+msgid "unable to deflate new object %s (%d)"
+msgstr "не вдалося запакувати новий обʼєкт %s (%d)"
+
+#, c-format
+msgid "deflateEnd on object %s failed (%d)"
+msgstr ""
+
+#, c-format
+msgid "confused by unstable object source data for %s"
+msgstr ""
+
+#, c-format
+msgid "write stream object %ld != %<PRIuMAX>"
+msgstr ""
+
+#, c-format
+msgid "unable to stream deflate new object (%d)"
+msgstr "не вдалося запакувати новий обʼєкт (%d) при передачі"
+
+#, c-format
+msgid "deflateEnd on stream object failed (%d)"
+msgstr ""
+
+#, c-format
+msgid "unable to create directory %s"
+msgstr "не вдалося створити директорію %s"
+
+#, c-format
+msgid "cannot read object for %s"
+msgstr "неможливо прочитати обʼєкт для %s"
+
+#, c-format
+msgid "object fails fsck: %s"
+msgstr ""
+
+msgid "refusing to create malformed object"
+msgstr ""
+
+#, c-format
+msgid "read error while indexing %s"
+msgstr ""
+
+#, c-format
+msgid "short read while indexing %s"
+msgstr ""
+
+#, c-format
+msgid "%s: failed to insert into database"
+msgstr ""
+
+#, c-format
+msgid "%s: unsupported file type"
+msgstr ""
+
+#, c-format
+msgid "%s is not a valid '%s' object"
+msgstr "%s не є допустимим \"%s\" обʼєктом"
+
+#, c-format
+msgid "unable to open %s"
+msgstr "не вдалося відкрити %s"
+
+#, c-format
+msgid "hash mismatch for %s (expected %s)"
+msgstr ""
+
+#, c-format
+msgid "unable to mmap %s"
+msgstr "не вдалося виконати mmap %s"
+
+#, c-format
+msgid "unable to unpack header of %s"
+msgstr "не вдалося розпакувати заголовок %s"
+
+#, c-format
+msgid "unable to parse header of %s"
+msgstr "не вдалося розібрати заголовок %s"
+
+#, c-format
+msgid "unable to unpack contents of %s"
+msgstr "не вдалося розпакувати вміст %s"
+
+#. TRANSLATORS: This is a line of ambiguous object
+#. output shown when we cannot look up or parse the
+#. object in question. E.g. "deadbeef [bad object]".
+#.
+
+#, c-format
+msgid "%s [bad object]"
+msgstr ""
+
+#. TRANSLATORS: This is a line of ambiguous commit
+#. object output. E.g.:
+#. *
+#. "deadbeef commit 2021-01-01 - Some Commit Message"
+#.
+
+#, c-format
+msgid "%s commit %s - %s"
+msgstr "%s коміт %s - %s"
+
+#. TRANSLATORS: This is a line of ambiguous
+#. tag object output. E.g.:
+#. *
+#. "deadbeef tag 2022-01-01 - Some Tag Message"
+#. *
+#. The second argument is the YYYY-MM-DD found
+#. in the tag.
+#. *
+#. The third argument is the "tag" string
+#. from object.c.
+#.
+
+#, c-format
+msgid "%s tag %s - %s"
+msgstr "%s тег %s - %s"
+
+#. TRANSLATORS: This is a line of ambiguous
+#. tag object output where we couldn't parse
+#. the tag itself. E.g.:
+#. *
+#. "deadbeef [bad tag, could not parse it]"
+#.
+
+#, c-format
+msgid "%s [bad tag, could not parse it]"
+msgstr ""
+
+#. TRANSLATORS: This is a line of ambiguous <type>
+#. object output. E.g. "deadbeef tree".
+#.
+
+#, c-format
+msgid "%s tree"
+msgstr ""
+
+#. TRANSLATORS: This is a line of ambiguous <type>
+#. object output. E.g. "deadbeef blob".
+#.
+
+#, c-format
+msgid "%s blob"
+msgstr ""
+
+#, c-format
+msgid "short object ID %s is ambiguous"
+msgstr ""
+
+#. TRANSLATORS: The argument is the list of ambiguous
+#. objects composed in show_ambiguous_object(). See
+#. its "TRANSLATORS" comments for details.
+#.
+
+#, c-format
+msgid ""
+"The candidates are:\n"
+"%s"
+msgstr ""
+
+msgid ""
+"Git normally never creates a ref that ends with 40 hex characters\n"
+"because it will be ignored when you just specify 40-hex. These refs\n"
+"may be created by mistake. For example,\n"
+"\n"
+"  git switch -c $br $(git rev-parse ...)\n"
+"\n"
+"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
+"examine these refs and maybe delete them. Turn this message off by\n"
+"running \"git config advice.objectNameWarning false\""
+msgstr ""
+
+#, c-format
+msgid "log for '%.*s' only goes back to %s"
+msgstr "лог для \"%.*s\" містить записи тільки до %s"
+
+#, c-format
+msgid "log for '%.*s' only has %d entries"
+msgstr "лог для \"%.*s\" містить лише %d записів"
+
+#, c-format
+msgid "path '%s' exists on disk, but not in '%.*s'"
+msgstr "шлях \"%s\" існує на диску, але не в \"%.*s\""
+
+#, c-format
+msgid ""
+"path '%s' exists, but not '%s'\n"
+"hint: Did you mean '%.*s:%s' aka '%.*s:./%s'?"
+msgstr ""
+"шлях \"%s\" існує, але не \"%s\"\n"
+"підказка: ви мали на увазі \"%.*s:%s\" або \"%.*s:./%s\"?"
+
+#, c-format
+msgid "path '%s' does not exist in '%.*s'"
+msgstr "шлях \"%s\" не існує в \"%.*s\""
+
+#, c-format
+msgid ""
+"path '%s' is in the index, but not at stage %d\n"
+"hint: Did you mean ':%d:%s'?"
+msgstr ""
+"шлях \"%s\" є в індексі, але відсутній на стадії %d\n"
+"підказка: ви мали на увазі \":%d:%s\"?"
+
+#, c-format
+msgid ""
+"path '%s' is in the index, but not '%s'\n"
+"hint: Did you mean ':%d:%s' aka ':%d:./%s'?"
+msgstr ""
+"шлях \"%s\" є в індексі, але не \"%s\"\n"
+"підказка: ви мали на увазі \"%d:%s\" або \"%d:./%s\"?"
+
+#, c-format
+msgid "path '%s' exists on disk, but not in the index"
+msgstr "шлях \"%s\" існує на диску, але відсутній в індексі"
+
+#, c-format
+msgid "path '%s' does not exist (neither on disk nor in the index)"
+msgstr "шлях \"%s\" не існує (ні на диску, ні в індексі)"
+
+msgid "relative path syntax can't be used outside working tree"
+msgstr ""
+"синтаксис відносного шляху не можна використовувати поза робочим деревом"
+
+#, c-format
+msgid "<object>:<path> required, only <object> '%s' given"
+msgstr "потрібно <обʼєкт>:<шлях>, надано лише <обʼєкт> \"%s\""
+
+#, c-format
+msgid "invalid object name '%.*s'."
+msgstr "неприпустима назва обʼєкта \"%.*s\"."
+
+#, c-format
+msgid "invalid object type \"%s\""
+msgstr "неприпустимий тип обʼєкту \"%s\""
+
+#, c-format
+msgid "object %s is a %s, not a %s"
+msgstr "обʼєкт %s є %s, а не %s"
+
+#, c-format
+msgid "object %s has unknown type id %d"
+msgstr "обʼєкт %s має невідомий тип ідентифікатора %d"
+
+#, c-format
+msgid "unable to parse object: %s"
+msgstr "не вдалося розібрати обʼєкт: %s"
+
+#, c-format
+msgid "hash mismatch %s"
+msgstr "невідповідність хешу %s"
+
+msgid "trying to write commit not in index"
+msgstr "спроба записати коміт, якого немає в індексі"
+
+msgid "failed to load bitmap index (corrupted?)"
+msgstr "не вдалося завантажити bitmap індекс (пошкоджено?)"
+
+msgid "corrupted bitmap index (too small)"
+msgstr "пошкоджений bitmap індекс (занадто малий)"
+
+msgid "corrupted bitmap index file (wrong header)"
+msgstr "пошкоджений файл bitmap індексу (занадто малий)"
+
+#, c-format
+msgid "unsupported version '%d' for bitmap index file"
+msgstr "непідтримувана версія \"%d\" для файлу bitmap індексу"
+
+msgid "corrupted bitmap index file (too short to fit hash cache)"
+msgstr ""
+"пошкоджений файл bitmap індексу (занадто короткий щоб умістити кеш хеша)"
+
+msgid "corrupted bitmap index file (too short to fit lookup table)"
+msgstr ""
+"пошкоджений файл bitmap індексу (занадто короткий, щоб вмістити таблицю "
+"пошуку)"
+
+#, c-format
+msgid "duplicate entry in bitmap index: '%s'"
+msgstr "дубльований запис в bitmap індексі: \"%s\""
+
+#, c-format
+msgid "corrupt ewah bitmap: truncated header for entry %d"
+msgstr "пошкоджений ewah bitmap: урізаний заголовок для запису %d"
+
+#, c-format
+msgid "corrupt ewah bitmap: commit index %u out of range"
+msgstr "пошкоджений ewah bitmap: індекс коміту %u поза межами діапазону"
+
+msgid "corrupted bitmap pack index"
+msgstr "пошкоджений bitmap індекс пакунка"
+
+msgid "invalid XOR offset in bitmap pack index"
+msgstr "невірне XOR зміщення в bitmap індексі пакунка"
+
+msgid "cannot fstat bitmap file"
+msgstr "неможливо виконати fstat для bitmap файла"
+
+msgid "checksum doesn't match in MIDX and bitmap"
+msgstr "контрольна сума не збігається в MIDX і bitmap"
+
+msgid "multi-pack bitmap is missing required reverse index"
+msgstr "у мультіпакунковому bitmap відсутній необхідний зворотний індекс"
+
+#, c-format
+msgid "could not open pack %s"
+msgstr "не вдалося відкрити пакунок %s"
+
+#, c-format
+msgid "preferred pack (%s) is invalid"
+msgstr "бажаний пакунок (%s) є неприпустимим"
+
+msgid "corrupt bitmap lookup table: triplet position out of index"
+msgstr "пошкоджена bitmap таблиця пошуку: триплетна позиція поза індексом"
+
+msgid "corrupt bitmap lookup table: xor chain exceeds entry count"
+msgstr ""
+"пошкоджена bitmap таблиця пошуку: xor ланцюжок перевищує кількість записів"
+
+#, c-format
+msgid "corrupt bitmap lookup table: commit index %u out of range"
+msgstr ""
+"пошкоджена bitmap таблиця пошуку: індекс коміту %u поза межами діапазону"
+
+#, c-format
+msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
+msgstr "пошкоджений ewah bitmap: урізаний заголовок для bitmap коміту \"%s\""
+
+#, c-format
+msgid "object '%s' not found in type bitmaps"
+msgstr "обʼєкт \"%s\" не знайдено в типах bitmap"
+
+#, c-format
+msgid "object '%s' does not have a unique type"
+msgstr "обʼєкт \"%s\" не має унікального типу"
+
+#, c-format
+msgid "object '%s': real type '%s', expected: '%s'"
+msgstr "обʼєкт \"%s\": дійсний тип \"%s\", очікуваний: \"%s\""
+
+#, c-format
+msgid "object not in bitmap: '%s'"
+msgstr "обʼєкт не у bitmap: \"%s\""
+
+msgid "failed to load bitmap indexes"
+msgstr "не вдалося завантажити bitmap індекси"
+
+msgid "you must specify exactly one commit to test"
+msgstr "ви маєте вказати тільки один коміт для тестування"
+
+#, c-format
+msgid "commit '%s' doesn't have an indexed bitmap"
+msgstr "коміт \"%s\" не має індексованого bitmap"
+
+msgid "mismatch in bitmap results"
+msgstr "розбіжність в bitmap результатах"
+
+#, c-format
+msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>"
+msgstr "не вдалося знайти \"%s\" у пакунку \"%s\" зі зміщенням %<PRIuMAX>"
+
+#, c-format
+msgid "unable to get disk usage of '%s'"
+msgstr ""
+"не вдалося отримати дані про використання дискового простору для \"%s\""
+
+#, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "bitmap файл \"%s\" має невірну контрольну суму"
+
+#, c-format
+msgid "mtimes file %s is too small"
+msgstr "mtimes файл %s занадто малий"
+
+#, c-format
+msgid "mtimes file %s has unknown signature"
+msgstr "mtimes файл %s має невідомий підпис"
+
+#, c-format
+msgid "mtimes file %s has unsupported version %<PRIu32>"
+msgstr "mtimes файл %s має непідтримувану версію %<PRIu32>."
+
+#, c-format
+msgid "mtimes file %s has unsupported hash id %<PRIu32>"
+msgstr "mtimes файл %s має непідтримуваний хеш-ідентифікатор %<PRIu32>"
+
+#, c-format
+msgid "mtimes file %s is corrupt"
+msgstr "mtimes файл %s пошкоджено"
+
+#, c-format
+msgid "reverse-index file %s is too small"
+msgstr "файл зворотного індексу %s занадто малий"
+
+#, c-format
+msgid "reverse-index file %s is corrupt"
+msgstr "файл зворотнього індексу %s пошкоджено"
+
+#, c-format
+msgid "reverse-index file %s has unknown signature"
+msgstr "файл зворотного індексу %s має невідомий підпис"
+
+#, c-format
+msgid "reverse-index file %s has unsupported version %<PRIu32>"
+msgstr "файл зворотного індексу %s має непідтримувану версію %<PRIu32>"
+
+#, c-format
+msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
+msgstr ""
+"файл зворотного індексу %s має непідтримуваний хеш-ідентифікатор %<PRIu32>"
+
+msgid "invalid checksum"
+msgstr "невірна контрольна сума"
+
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr ""
+"невірна позиція зворортного індексу у %<PRIu64>: %<PRIu32> != %<PRIu32>"
+
+msgid "cannot both write and verify reverse index"
+msgstr "неможливо одночасно записувати та звіряти зворотний індекс"
+
+#, c-format
+msgid "could not stat: %s"
+msgstr "не вдалося виконати stat: %s"
+
+#, c-format
+msgid "failed to make %s readable"
+msgstr "не вдалося зробити %s читабельним"
+
+#, c-format
+msgid "could not write '%s' promisor file"
+msgstr "не вдалося записати promisor файл \"%s\""
+
+msgid "offset before end of packfile (broken .idx?)"
+msgstr "зміщення перед кінцем файла пакунка (пошкоджений .idx?)"
+
+#, c-format
+msgid "packfile %s cannot be mapped%s"
+msgstr "файл пакунка %s не може бути mapped%s"
+
+#, c-format
+msgid "offset before start of pack index for %s (corrupt index?)"
+msgstr "зміщення перед початком індекса пакунка для %s (пошкоджений індекс?)"
+
+#, c-format
+msgid "offset beyond end of pack index for %s (truncated index?)"
+msgstr "зміщення за межою кінця індекса пакунка для %s (зрізаний індекс?)"
+
+#, c-format
+msgid "malformed expiration date '%s'"
+msgstr "неправильно сформована дата закінчення терміну дії \"%s\""
+
+#, c-format
+msgid "option `%s' expects \"always\", \"auto\", or \"never\""
+msgstr "опція \"%s\" очікує \"always\", \"auto\" або \"never\""
+
+#, c-format
+msgid "malformed object name '%s'"
+msgstr "неправильно сформована назва обʼєкта \"%s\""
+
+#, c-format
+msgid "option `%s' expects \"%s\" or \"%s\""
+msgstr "опція \"%s\" очікує \"%s\" або \"%s\""
+
+#, c-format
+msgid "%s requires a value"
+msgstr "%s потребує значення"
+
+#, c-format
+msgid "%s is incompatible with %s"
+msgstr "%s несумісний з %s"
+
+#, c-format
+msgid "%s : incompatible with something else"
+msgstr "%s : несумісний з чимось іншим"
+
+#, c-format
+msgid "%s takes no value"
+msgstr "%s не приймає значення"
+
+#, c-format
+msgid "%s isn't available"
+msgstr "%s недоступний"
+
+#, c-format
+msgid "%s expects a non-negative integer value with an optional k/m/g suffix"
+msgstr "%s очікує невід'ємне ціле значення з опціональним суфіксом k/m/g"
+
+#, c-format
+msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
+msgstr "неоднозначна опція: %s (може бути --%s%s або --%s%s)"
+
+#, c-format
+msgid "did you mean `--%s` (with two dashes)?"
+msgstr "ви мали на увазі \"--%s\" (з двома рисками)?"
+
+#, c-format
+msgid "alias of --%s"
+msgstr "псевдонім --%s"
+
+msgid "need a subcommand"
+msgstr "потрібна підкоманда"
+
+#, c-format
+msgid "unknown option `%s'"
+msgstr "невідома опція \"%s\""
+
+#, c-format
+msgid "unknown switch `%c'"
+msgstr "невідомий перемикач \"%c\""
+
+#, c-format
+msgid "unknown non-ascii option in string: `%s'"
+msgstr "невідомий non-ascii параметр у рядку: \"%s\""
+
+msgid "..."
+msgstr "..."
+
+#, c-format
+msgid "usage: %s"
+msgstr "використання: %s"
+
+#. TRANSLATORS: the colon here should align with the
+#. one in "usage: %s" translation.
+#.
+
+#, c-format
+msgid "   or: %s"
+msgstr "         або: %s"
+
+#. TRANSLATORS: You should only need to translate this format
+#. string if your language is a RTL language (e.g. Arabic,
+#. Hebrew etc.), not if it's a LTR language (e.g. German,
+#. Russian, Chinese etc.).
+#. *
+#. When a translated usage string has an embedded "\n" it's
+#. because options have wrapped to the next line. The line
+#. after the "\n" will then be padded to align with the
+#. command name, such as N_("git cmd [opt]\n<8
+#. spaces>[opt2]"), where the 8 spaces are the same length as
+#. "git cmd ".
+#. *
+#. This format string prints out that already-translated
+#. line. The "%*s" is whitespace padding to account for the
+#. padding at the start of the line that we add in this
+#. function. The "%s" is a line in the (hopefully already
+#. translated) N_() usage string, which contained embedded
+#. newlines before we split it up.
+#.
+
+#, c-format
+msgid "%*s%s"
+msgstr "%*s%s"
+
+#, c-format
+msgid "    %s"
+msgstr "    %s"
+
+msgid "-NUM"
+msgstr "-NUM"
+
+msgid "expiry-date"
+msgstr "закінчення строку дії"
+
+msgid "no-op (backward compatibility)"
+msgstr "не працює (зворотна сумісність)"
+
+msgid "be more verbose"
+msgstr "надавати більш розгорнутий вивід"
+
+msgid "be more quiet"
+msgstr "надавати менш розгорнутий вивід"
+
+msgid "use <n> digits to display object names"
+msgstr "використовувати <n> цифр для відображення назв обʼєктів"
+
+msgid "prefixed path to initial superproject"
+msgstr "префіксний шлях до початкового суперпроекту"
+
+msgid "how to strip spaces and #comments from message"
+msgstr "як прибирати пробіли та #коментарі з допису"
+
+msgid "read pathspec from file"
+msgstr "прочитати визначник шляху з файлу"
+
+msgid ""
+"with --pathspec-from-file, pathspec elements are separated with NUL character"
+msgstr ""
+"за допомогою --pathspec-from-file елементи визначника шляху відокремлюються "
+"символом NUL"
+
+#, c-format
+msgid "Could not make %s writable by group"
+msgstr "Не вдалося зробити %s доступним для запису групою"
+
+msgid "Escape character '\\' not allowed as last character in attr value"
+msgstr ""
+"Символ екранування \"\\\" не дозволяється як останній символ у значенні "
+"атрибута"
+
+msgid "Only one 'attr:' specification is allowed."
+msgstr "Дозволений лише один визначник \"attr:\"."
+
+msgid "attr spec must not be empty"
+msgstr "визначник атрибута повинен бути не порожнім"
+
+#, c-format
+msgid "invalid attribute name %s"
+msgstr "невірна назва атрибуту %s"
+
+msgid "global 'glob' and 'noglob' pathspec settings are incompatible"
+msgstr "глобальні параметри визначника шляху \"glob\" та \"noglob\" несумісні"
+
+msgid ""
+"global 'literal' pathspec setting is incompatible with all other global "
+"pathspec settings"
+msgstr ""
+"глобальний параметр \"literal\" визначника шляху несумісний з усіма іншими "
+"глобальними параметрами визначника шляху"
+
+msgid "invalid parameter for pathspec magic 'prefix'"
+msgstr ""
+"неприпустимий параметр для магічного значення \"prefix\" визначника шляху"
+
+#, c-format
+msgid "Invalid pathspec magic '%.*s' in '%s'"
+msgstr "Неприпустиме магічне значення \"%.*s\" для визначника шляху в \"%s\""
+
+#, c-format
+msgid "Missing ')' at the end of pathspec magic in '%s'"
+msgstr ""
+"Пропущено \")\" наприкінці магічного значення для визначника шляху в \"%s\""
+
+#, c-format
+msgid "Unimplemented pathspec magic '%c' in '%s'"
+msgstr "Нереалізоване магічне значення \"%c\" для визначника шляху в \"%s\""
+
+#, c-format
+msgid "%s: 'literal' and 'glob' are incompatible"
+msgstr "%s: \"literal\" та \"glob\" несумісні"
+
+#, c-format
+msgid "%s: '%s' is outside repository at '%s'"
+msgstr "%s: \"%s\" знаходиться за межами сховища за адресою \"%s\""
+
+#, c-format
+msgid "'%s' (mnemonic: '%c')"
+msgstr "\"%s\" (мнемонічно: \"%c\")"
+
+#, c-format
+msgid "%s: pathspec magic not supported by this command: %s"
+msgstr ""
+"%s: магічне значення для визначника шляху не підтримується цією командою: %s"
+
+#, c-format
+msgid "pathspec '%s' is beyond a symbolic link"
+msgstr "визначник шляху \"%s\" знаходиться за межами символьного посилання"
+
+#, c-format
+msgid "line is badly quoted: %s"
+msgstr "рядок взято в лапки невірно: %s"
+
+msgid "unable to write flush packet"
+msgstr "не вдалося записати flush пакет"
+
+msgid "unable to write delim packet"
+msgstr "не вдалося записати delim пакет"
+
+msgid "unable to write response end packet"
+msgstr "не вдалося записати response end пакет"
+
+msgid "flush packet write failed"
+msgstr "не вдалося записати flush пакет"
+
+msgid "protocol error: impossibly long line"
+msgstr "помилка протоколу: неймовірно довгий рядок"
+
+msgid "packet write with format failed"
+msgstr "не вдалося записати пакет з форматуванням"
+
+msgid "packet write failed - data exceeds max packet size"
+msgstr ""
+"не вдалося записати пакет - дані перевищують максимальний розмір пакета"
+
+#, c-format
+msgid "packet write failed: %s"
+msgstr "не вдалося записати пакет: %s"
+
+msgid "read error"
+msgstr "помилка зчитування"
+
+msgid "the remote end hung up unexpectedly"
+msgstr "віддалене призначення несподівано відключилося"
+
+#, c-format
+msgid "protocol error: bad line length character: %.4s"
+msgstr "помилка протоколу: невірний символ довжини рядка: %.4s"
+
+#, c-format
+msgid "protocol error: bad line length %d"
+msgstr "помилка протоколу: невірна довжина рядка %d"
+
+#, c-format
+msgid "remote error: %s"
+msgstr "помилка віддаленого призначення: %s"
+
+msgid "Refreshing index"
+msgstr "Оновлення індекса"
+
+#, c-format
+msgid "unable to create threaded lstat: %s"
+msgstr "не вдалося створити потоковий lstat: %s"
+
+msgid "unable to parse --pretty format"
+msgstr "не вдалося розібрати --pretty формат"
+
+msgid "promisor-remote: unable to fork off fetch subprocess"
+msgstr "promisor-remote: не вдалося розгалужити підпроцес отримання"
+
+msgid "promisor-remote: could not write to fetch subprocess"
+msgstr "promisor-remote: не вдалося записати до підпроцесу отримання"
+
+msgid "promisor-remote: could not close stdin to fetch subprocess"
+msgstr "promisor-remote: не вдалося закрити stdin для підпроцесу отримання"
+
+#, c-format
+msgid "promisor remote name cannot begin with '/': %s"
+msgstr "назва віддаленого promisor не може починатися з \"/\": %s"
+
+#, c-format
+msgid "could not fetch %s from promisor remote"
+msgstr "не вдалося отримати %s з віддаленого promisor"
+
+msgid "object-info: expected flush after arguments"
+msgstr "object-info: очікувався flush після аргументів"
+
+msgid "Removing duplicate objects"
+msgstr "Видалення дублікатів обʼєктів"
+
+msgid "could not start `log`"
+msgstr "не вдалося розпочати \"log\""
+
+msgid "could not read `log` output"
+msgstr "не вдалося прочитати \"log\" вивід"
+
+#, c-format
+msgid "could not parse commit '%s'"
+msgstr "не вдалося розібрати коміт \"%s\""
+
+#, c-format
+msgid ""
+"could not parse first line of `log` output: did not start with 'commit ': "
+"'%s'"
+msgstr ""
+"не вдалося розібрати перший рядок \"log\" виводу: не починався з \"commit "
+"\"': \"%s\""
+
+#, c-format
+msgid "could not parse git header '%.*s'"
+msgstr "не вдалося розібрати git заголовок \"%.*s\""
+
+msgid "failed to generate diff"
+msgstr "не вдалося згенерувати різницю"
+
+#, c-format
+msgid "could not parse log for '%s'"
+msgstr "не вдалося розібрати лог для \"%s\""
+
+#, c-format
+msgid "will not add file alias '%s' ('%s' already exists in index)"
+msgstr "не додаємо псевдонім файлу \"%s\" (\"%s\" вже існує в індексі)"
+
+msgid "cannot create an empty blob in the object database"
+msgstr "неможливо створити порожній blob в базі даних обʼєктів"
+
+#, c-format
+msgid "%s: can only add regular files, symbolic links or git-directories"
+msgstr ""
+"%s: може додавати лише звичайні файли, символьні посилання або git-директорії"
+
+#, c-format
+msgid "unable to index file '%s'"
+msgstr "не вдалося проіндексувати файл \"%s\""
+
+#, c-format
+msgid "unable to add '%s' to index"
+msgstr "не вдалося додати \"%s\" до індексу"
+
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "не вдалося виконати stat для \"%s\""
+
+#, c-format
+msgid "'%s' appears as both a file and as a directory"
+msgstr "\"%s\" відображається як файл і як каталог"
+
+msgid "Refresh index"
+msgstr "Оновити індекс"
+
+#, c-format
+msgid ""
+"index.version set, but the value is invalid.\n"
+"Using version %i"
+msgstr ""
+"index.version встановлено, але значення неприпустиме.\n"
+"Використання версії %i"
+
+#, c-format
+msgid ""
+"GIT_INDEX_VERSION set, but the value is invalid.\n"
+"Using version %i"
+msgstr ""
+"GIT_INDEX_VERSION встановлено, але значення неприпустиме.\n"
+"Використання версії %i"
+
+#, c-format
+msgid "bad signature 0x%08x"
+msgstr "невірний підпис 0x%08x"
+
+#, c-format
+msgid "bad index version %d"
+msgstr "невірна версія індексу %d"
+
+msgid "bad index file sha1 signature"
+msgstr "невірний sha1 підпис індексного файлу"
+
+#, c-format
+msgid "index uses %.4s extension, which we do not understand"
+msgstr "індекс використовує %.4s розширення, яке ми не розуміємо"
+
+#, c-format
+msgid "ignoring %.4s extension"
+msgstr "ігнорування %.4s розширення"
+
+#, c-format
+msgid "unknown index entry format 0x%08x"
+msgstr "невідомий формат запису індексу 0x%08x"
+
+#, c-format
+msgid "malformed name field in the index, near path '%s'"
+msgstr "невірно сформоване поле назви в індексі біля шляху \"%s\""
+
+msgid "unordered stage entries in index"
+msgstr "невпорядковані записи в індексі"
+
+#, c-format
+msgid "multiple stage entries for merged file '%s'"
+msgstr "багатоступеневі записи для злитого файлу \"%s\""
+
+#, c-format
+msgid "unordered stage entries for '%s'"
+msgstr "невпорядковані записи індексу для '%s'"
+
+#, c-format
+msgid "unable to create load_cache_entries thread: %s"
+msgstr "не вдалося створити потік load_cache_entries: %s"
+
+#, c-format
+msgid "unable to join load_cache_entries thread: %s"
+msgstr "не вдалося приєднатися до потоку load_cache_entries: %s"
+
+#, c-format
+msgid "%s: index file open failed"
+msgstr "%s: не вдалося відкрити індексний файл"
+
+#, c-format
+msgid "%s: cannot stat the open index"
+msgstr "%s: не вдалося виконати stat відкритого індексу"
+
+#, c-format
+msgid "%s: index file smaller than expected"
+msgstr "%s: індексний файл менший, ніж очікувалося"
+
+#, c-format
+msgid "%s: unable to map index file%s"
+msgstr "%s: не вдалося зіставити індексний файл%s"
+
+#, c-format
+msgid "unable to create load_index_extensions thread: %s"
+msgstr "не вдалося створити потік load_index_extensions: %s"
+
+#, c-format
+msgid "unable to join load_index_extensions thread: %s"
+msgstr "не вдалося приєднатися до потоку load_index_extensions: %s"
+
+#, c-format
+msgid "could not freshen shared index '%s'"
+msgstr "не вдалося оновити спільний індекс \"%s\""
+
+#, c-format
+msgid "broken index, expect %s in %s, got %s"
+msgstr "пошкоджений індекс, очікувався %s у %s, отримано %s"
+
+msgid "cannot write split index for a sparse index"
+msgstr "неможливо записати розділений індекс для часткового індексу"
+
+msgid "failed to convert to a sparse-index"
+msgstr "не вдалося перетворити в sparse-index"
+
+#, c-format
+msgid "could not stat '%s'"
+msgstr "не вдалося виконати stat '%s'"
+
+#, c-format
+msgid "unable to open git dir: %s"
+msgstr "не вдалося відкрити git-директорію: %s"
+
+#, c-format
+msgid "unable to unlink: %s"
+msgstr "не вдалося відʼєднати: %s"
+
+#, c-format
+msgid "cannot fix permission bits on '%s'"
+msgstr "неможливо виправити біти дозволу на \"%s\""
+
+#, c-format
+msgid "%s: cannot drop to stage #0"
+msgstr "%s: неможливо скинути індекс до стану #0"
+
+msgid ""
+"You can fix this with 'git rebase --edit-todo' and then run 'git rebase --"
+"continue'.\n"
+"Or you can abort the rebase with 'git rebase --abort'.\n"
+msgstr ""
+"Ви можете виправити це командою \"git rebase --edit-todo\", а потім "
+"запустити \"git rebase --continue\".\n"
+"Або ви можете перервати перебазування за допомогою \"git rebase --abort\".\n"
+
+#, c-format
+msgid ""
+"unrecognized setting %s for option rebase.missingCommitsCheck. Ignoring."
+msgstr ""
+"нерозпізнане значення %s для опції rebase.missingCommitsCheck. Ігнорується."
+
+msgid ""
+"\n"
+"Commands:\n"
+"p, pick <commit> = use commit\n"
+"r, reword <commit> = use commit, but edit the commit message\n"
+"e, edit <commit> = use commit, but stop for amending\n"
+"s, squash <commit> = use commit, but meld into previous commit\n"
+"f, fixup [-C | -c] <commit> = like \"squash\" but keep only the previous\n"
+"                   commit's log message, unless -C is used, in which case\n"
+"                   keep only this commit's message; -c is same as -C but\n"
+"                   opens the editor\n"
+"x, exec <command> = run command (the rest of the line) using shell\n"
+"b, break = stop here (continue rebase later with 'git rebase --continue')\n"
+"d, drop <commit> = remove commit\n"
+"l, label <label> = label current HEAD with a name\n"
+"t, reset <label> = reset HEAD to a label\n"
+"m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]\n"
+"        create a merge commit using the original merge commit's\n"
+"        message (or the oneline, if no original merge commit was\n"
+"        specified); use -c <commit> to reword the commit message\n"
+"u, update-ref <ref> = track a placeholder for the <ref> to be updated\n"
+"                      to this position in the new commits. The <ref> is\n"
+"                      updated at the end of the rebase\n"
+"\n"
+"These lines can be re-ordered; they are executed from top to bottom.\n"
+msgstr ""
+"\n"
+"Команди:\n"
+"p, pick <коміт> = використати коміт\n"
+"r, reword <коміт> = використати коміт, але відредагувати допис до коміту\n"
+"e, edit <коміт> = використати коміт, але зупинитись для внесення поправок\n"
+"s, squash <коміт> = використати коміт, але обʼєднати з попереднім комітом\n"
+"f, fixup [-C | -c] <коміт> = як \"squash\", але зберігає лише попередній\n"
+"                   допис до коміту, якщо тільки не вказана опція -С, у якому "
+"разі\n"
+"                   зберігається лише допис до цього коміту; -c - те саме, що "
+"й -C, але\n"
+"                   відкриває редактор\n"
+"x, exec <команда> = виконати команду (решту рядка) за допомогою shell\n"
+"b, break = зупинитись тут (продовжити перебазування пізніше за допомогою "
+"'git rebase --continue')\n"
+"d, drop <коміт> = видалити коміт\n"
+"l, label <мітка> = помітити поточний HEAD назвою\n"
+"t, reset <мітка> = скинути HEAD до мітки\n"
+"m, merge [-C <коміт> | -c <коміт>] <мітка> [# <однорядковий допис>]\n"
+"        створити коміт злиття, використовуючи допис до початкового коміту\n"
+"        злиття (або однорядковий допис, якщо не було вказано коміт\n"
+"        злиття); використовуйте -c <коміт>, щоб перефразувати допис до "
+"коміту\n"
+"u, update-ref <посилання> = відстежити заповнювач для <посилання>, яке "
+"потрібно оновити\n"
+"                      до цієї позиції у нових комітах. <посилання>\n"
+"                      оновлюється в кінці перебазування\n"
+"\n"
+"Ці рядки можна переупорядкувати; вони виконуються зверху вниз.\n"
+
+#, c-format
+msgid "Rebase %s onto %s (%d command)"
+msgid_plural "Rebase %s onto %s (%d commands)"
+msgstr[0] "Перебазування %s на %s (%d команда)"
+msgstr[1] "Перебазування %s на %s (%d команди)"
+msgstr[2] "Перебазування %s на %s (%d команд)"
+
+msgid ""
+"\n"
+"Do not remove any line. Use 'drop' explicitly to remove a commit.\n"
+msgstr ""
+"\n"
+"Не видаляйте жодного рядка. Використовуйте \"drop\", щоб явно видалити "
+"коміт.\n"
+
+msgid ""
+"\n"
+"If you remove a line here THAT COMMIT WILL BE LOST.\n"
+msgstr ""
+"\n"
+"Якщо ви видалите тут рядок, ЦЕЙ КОМІТ БУДЕ ВТРАЧЕНО.\n"
+
+msgid ""
+"\n"
+"You are editing the todo file of an ongoing interactive rebase.\n"
+"To continue rebase after editing, run:\n"
+"    git rebase --continue\n"
+"\n"
+msgstr ""
+"\n"
+"Ви редагуєте файл todo поточного інтерактивного перебазування.\n"
+"Щоб продовжити перебазування після редагування, виконайте:\n"
+"    git rebase --continue\n"
+
+msgid ""
+"\n"
+"However, if you remove everything, the rebase will be aborted.\n"
+"\n"
+msgstr ""
+"\n"
+"Однак, якщо ви видалите все, перебазування буде перервано.\n"
+"\n"
+
+#, c-format
+msgid "could not write '%s'."
+msgstr "не вдалося записати \"%s\"."
+
+#, c-format
+msgid ""
+"Warning: some commits may have been dropped accidentally.\n"
+"Dropped commits (newer to older):\n"
+msgstr ""
+"Попередження: деякі коміти могли бути видалені випадково.\n"
+"Скинуті коміти (від новіших до старіших):\n"
+
+#, c-format
+msgid ""
+"To avoid this message, use \"drop\" to explicitly remove a commit.\n"
+"\n"
+"Use 'git config rebase.missingCommitsCheck' to change the level of "
+"warnings.\n"
+"The possible behaviours are: ignore, warn, error.\n"
+"\n"
+msgstr ""
+"Щоб уникнути цього повідомлення, використовуйте \"drop\" для явного "
+"видалення коміту.\n"
+"\n"
+"Використовуйте \"git config rebase.missingCommitsCheck\" для зміни рівня "
+"попереджень.\n"
+"Можливі варіанти поведінки: ignore, warn, error.\n"
+
+#, c-format
+msgid "%s: 'preserve' superseded by 'merges'"
+msgstr "%s: \"preserve\" замінено на \"merges\""
+
+msgid "gone"
+msgstr "відсутнє"
+
+#, c-format
+msgid "ahead %d"
+msgstr "попереду %d"
+
+#, c-format
+msgid "behind %d"
+msgstr "позаду %d"
+
+#, c-format
+msgid "ahead %d, behind %d"
+msgstr "попереду %d, позаду %d"
+
+#, c-format
+msgid "%%(%.*s) does not take arguments"
+msgstr "%%(%.*s) не приймає аргументів"
+
+#, c-format
+msgid "unrecognized %%(%.*s) argument: %s"
+msgstr "нерозпізнаний %%(%.*s) аргумент: %s"
+
+#, c-format
+msgid "expected format: %%(color:<color>)"
+msgstr "очікуваний формат: %%(color:<колір>)"
+
+#, c-format
+msgid "unrecognized color: %%(color:%s)"
+msgstr "нерозпізнаний колір: %%(color:%s)"
+
+#, c-format
+msgid "Integer value expected refname:lstrip=%s"
+msgstr "Очікувалось ціле число refname:lstrip=%s"
+
+#, c-format
+msgid "Integer value expected refname:rstrip=%s"
+msgstr "Очікувалось ціле число refname:rstrip=%s"
+
+#, c-format
+msgid "expected %%(trailers:key=<value>)"
+msgstr "очікувалось %%(trailers:key=<значення>)"
+
+#, c-format
+msgid "unknown %%(trailers) argument: %s"
+msgstr "невідомий %%(trailers) аргумент: %s"
+
+#, c-format
+msgid "positive value expected contents:lines=%s"
+msgstr "очікувалось додатне значення contents:lines=%s"
+
+#, c-format
+msgid "positive value expected '%s' in %%(%s)"
+msgstr "очікувалось додатне значення \"%s\" у %%(%s)"
+
+#, c-format
+msgid "expected format: %%(align:<width>,<position>)"
+msgstr "очікуваний формат: %%(align:<ширина>,<позиція>)"
+
+#, c-format
+msgid "unrecognized position:%s"
+msgstr "нерозпізнана позиція:%s"
+
+#, c-format
+msgid "unrecognized width:%s"
+msgstr "нерозпізнана ширина:%s"
+
+#, c-format
+msgid "unrecognized %%(%s) argument: %s"
+msgstr "нерозпізнаний %%(%s) аргумент: %s"
+
+#, c-format
+msgid "positive width expected with the %%(align) atom"
+msgstr "очікувалась додатна ширина з %%(align) часткою"
+
+#, c-format
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "очікуваний формат: %%(ahead-behind:<комітоподібне>)"
+
+#, c-format
+msgid "malformed field name: %.*s"
+msgstr "неправильно сформована назва поля: %.*s"
+
+#, c-format
+msgid "unknown field name: %.*s"
+msgstr "невідома назва поля: %.*s"
+
+#, c-format
+msgid ""
+"not a git repository, but the field '%.*s' requires access to object data"
+msgstr "не git сховище, але поле \"%.*s\" потребує доступу до даних обʼєкта"
+
+#, c-format
+msgid "format: %%(%s) atom used without a %%(%s) atom"
+msgstr "формат: частка %%(%s) використано без частки %%(%s)"
+
+#, c-format
+msgid "format: %%(then) atom used more than once"
+msgstr "формат: %%(then) частка використана більше одного разу"
+
+#, c-format
+msgid "format: %%(then) atom used after %%(else)"
+msgstr "формат: %%(then) частка використана після %%(else)"
+
+#, c-format
+msgid "format: %%(else) atom used more than once"
+msgstr "формат: %%(else) частка використана більше одного разу"
+
+#, c-format
+msgid "format: %%(end) atom used without corresponding atom"
+msgstr "формат: %%(end) частка використана без відповідної частки"
+
+#, c-format
+msgid "malformed format string %s"
+msgstr "неправильно сформований рядок форматування %s"
+
+#, c-format
+msgid "this command reject atom %%(%.*s)"
+msgstr "ця команда відхиляє частку %%(%.*s)"
+
+#, c-format
+msgid "--format=%.*s cannot be used with --python, --shell, --tcl"
+msgstr "--format=%.*s не може бути використаний з --python, --shell, --tcl"
+
+#, c-format
+msgid "(no branch, rebasing %s)"
+msgstr "(немає гілки, перебазування %s)"
+
+#, c-format
+msgid "(no branch, rebasing detached HEAD %s)"
+msgstr "(немає гілки, перебазування відокремленого HEAD %s)"
+
+#, c-format
+msgid "(no branch, bisect started on %s)"
+msgstr "(немає гілки, бісекцію розпочато на %s)"
+
+#, c-format
+msgid "(HEAD detached at %s)"
+msgstr "(HEAD відʼєднано на %s)"
+
+#, c-format
+msgid "(HEAD detached from %s)"
+msgstr "(HEAD відʼєднано від %s)"
+
+msgid "(no branch)"
+msgstr "(немає гілки)"
+
+#, c-format
+msgid "missing object %s for %s"
+msgstr "відсутній обʼєкт %s для %s"
+
+#, c-format
+msgid "parse_object_buffer failed on %s for %s"
+msgstr "parse_object_buffer завершився невдало на %s для %s"
+
+#, c-format
+msgid "malformed object at '%s'"
+msgstr "неправильно сформований обʼєкт за адресою \"%s\""
+
+#, c-format
+msgid "ignoring ref with broken name %s"
+msgstr "ігнорування посилання з пошкодженою назвою %s"
+
+#, c-format
+msgid "ignoring broken ref %s"
+msgstr "ігнорування пошкоджених посилань %s"
+
+#, c-format
+msgid "format: %%(end) atom missing"
+msgstr "формат: %%(end) частка відсутня"
+
+#, c-format
+msgid "malformed object name %s"
+msgstr "неправильно сформована назва обʼєкта %s"
+
+#, c-format
+msgid "option `%s' must point to a commit"
+msgstr "опція \"%s\" повинна вказувати на коміт"
+
+msgid "key"
+msgstr "ключ"
+
+msgid "field name to sort on"
+msgstr "назва поля для сортування"
+
+#, c-format
+msgid "not a reflog: %s"
+msgstr "не reflog: %s"
+
+#, c-format
+msgid "no reflog for '%s'"
+msgstr "немає reflog для \"%s\""
+
+#, c-format
+msgid "%s does not point to a valid object!"
+msgstr "%s не вказує на допустимий обʼєкт!"
+
+#, c-format
+msgid ""
+"Using '%s' as the name for the initial branch. This default branch name\n"
+"is subject to change. To configure the initial branch name to use in all\n"
+"of your new repositories, which will suppress this warning, call:\n"
+"\n"
+"\tgit config --global init.defaultBranch <name>\n"
+"\n"
+"Names commonly chosen instead of 'master' are 'main', 'trunk' and\n"
+"'development'. The just-created branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m <name>\n"
+msgstr ""
+"Використання \"%s\" як назви початкової гілки. Назву гілки за замовчуванням\n"
+"може бути змінено. Щоб налаштувати назву початкової гілки для використання у "
+"всіх\n"
+"ваших нових сховищах, що приховуватиме це попередження, викличте\n"
+"\n"
+"\tgit config --global init.defaultBranch <назва>.\n"
+"\n"
+"Замість \"master\" зазвичай використовують такі назви, як \"main\", "
+"\"trunk\" та\n"
+"\"development\". Щойно створену гілку можна перейменувати за допомогою цієї "
+"команди:\n"
+"\n"
+"\tgit branch -m <назва>\n"
+
+#, c-format
+msgid "could not retrieve `%s`"
+msgstr "не вдалося отримати \"%s\""
+
+#, c-format
+msgid "invalid branch name: %s = %s"
+msgstr "неприпустима назва гілки: %s = %s"
+
+#, c-format
+msgid "ignoring dangling symref %s"
+msgstr "ігнорування висячих symref %s"
+
+#, c-format
+msgid "log for ref %s has gap after %s"
+msgstr "лог для посилання %s має пропуск після %s"
+
+#, c-format
+msgid "log for ref %s unexpectedly ended on %s"
+msgstr "лог для посилання %s несподівано завершився на %s"
+
+#, c-format
+msgid "log for %s is empty"
+msgstr "лог для %s порожній"
+
+#, c-format
+msgid "refusing to update ref with bad name '%s'"
+msgstr "відмова оновлення посилання з невірною назвою \"%s\""
+
+#, c-format
+msgid "update_ref failed for ref '%s': %s"
+msgstr "update_ref завершився невдало для посилання \"%s\": %s"
+
+#, c-format
+msgid "multiple updates for ref '%s' not allowed"
+msgstr "багатократні оновлення для посилання \"%s\" заборонені"
+
+msgid "ref updates forbidden inside quarantine environment"
+msgstr "оновлення посилань заборонено у карантинному середовищі"
+
+msgid "ref updates aborted by hook"
+msgstr "оновлення посилань перервано гачком"
+
+#, c-format
+msgid "'%s' exists; cannot create '%s'"
+msgstr "\"%s\" існує; неможливо створити \"%s\""
+
+#, c-format
+msgid "cannot process '%s' and '%s' at the same time"
+msgstr "неможливо обробити \"%s\" і \"%s\" одночасно"
+
+#, c-format
+msgid "could not remove reference %s"
+msgstr "не вдалося видалити посилання %s"
+
+#, c-format
+msgid "could not delete reference %s: %s"
+msgstr "не вдалося видалити посилання %s: %s"
+
+#, c-format
+msgid "could not delete references: %s"
+msgstr "не вдалося видалити посилання: %s"
+
+#, c-format
+msgid "invalid refspec '%s'"
+msgstr "неприпустимий визначник посилання \"%s\""
+
+#, c-format
+msgid "invalid quoting in push-option value: '%s'"
+msgstr "неприпустимі лапки у значенні push-опції: \"%s\""
+
+#, c-format
+msgid "%sinfo/refs not valid: is this a git repository?"
+msgstr "%sinfo/refs не дійсні: це git сховище?"
+
+msgid "invalid server response; expected service, got flush packet"
+msgstr ""
+"неприпустима відповідь сервера; очікувався service, отримано flush пакет"
+
+#, c-format
+msgid "invalid server response; got '%s'"
+msgstr "неприпустима відповідь сервера; отримано \"%s\""
+
+#, c-format
+msgid "repository '%s' not found"
+msgstr "сховище \"%s\" не знайдено"
+
+#, c-format
+msgid "Authentication failed for '%s'"
+msgstr "Невдала аутентифікація для \"%s\""
+
+#, c-format
+msgid "unable to access '%s' with http.pinnedPubkey configuration: %s"
+msgstr ""
+"не вдалося отримати доступ до \"%s\" з конфігурацією http.pinnedPubkey: %s"
+
+#, c-format
+msgid "unable to access '%s': %s"
+msgstr "не вдалося отримати доступ до \"%s\": %s"
+
+#, c-format
+msgid "redirecting to %s"
+msgstr "перенаправлення на %s"
+
+msgid "shouldn't have EOF when not gentle on EOF"
+msgstr "не повинен мати EOF, якщо не є обережним з EOF"
+
+msgid "remote server sent unexpected response end packet"
+msgstr "віддалений сервер надіслав неочікуваний response end пакет"
+
+msgid "unable to rewind rpc post data - try increasing http.postBuffer"
+msgstr ""
+"не вдалося перемотати rpc post дані - спробуйте збільшити http.postBuffer"
+
+#, c-format
+msgid "remote-curl: bad line length character: %.4s"
+msgstr "remote-curl: невірний символ довжини рядка: %.4s"
+
+msgid "remote-curl: unexpected response end packet"
+msgstr "remote-curl: неочікуваний response end пакет"
+
+#, c-format
+msgid "RPC failed; %s"
+msgstr "RPC завершився невдало; %s"
+
+msgid "cannot handle pushes this big"
+msgstr "неможливо впоратися з такими великими надсиланнями"
+
+#, c-format
+msgid "cannot deflate request; zlib deflate error %d"
+msgstr "неможливо запакувати запит; zlib помилка пакування %d"
+
+#, c-format
+msgid "cannot deflate request; zlib end error %d"
+msgstr "неможливо запакувати запит; zlib помилка завершення %d"
+
+#, c-format
+msgid "%d bytes of length header were received"
+msgstr "%d байтів заголовку було отримано"
+
+#, c-format
+msgid "%d bytes of body are still expected"
+msgstr "%d байтів тіла все ще очікуються"
+
+msgid "dumb http transport does not support shallow capabilities"
+msgstr "засіб передачі dumb http не підтримує shallow здібності"
+
+msgid "fetch failed."
+msgstr "отримання завершилось невдало."
+
+msgid "cannot fetch by sha1 over smart http"
+msgstr "неможливо отримати дані за допомогою sha1 через smart http"
+
+#, c-format
+msgid "protocol error: expected sha/ref, got '%s'"
+msgstr "помилка протоколу: очікувалося sha/ref, отримано \"%s\""
+
+#, c-format
+msgid "http transport does not support %s"
+msgstr "http засіб передачі не підтримує %s"
+
+msgid "protocol error: expected '<url> <path>', missing space"
+msgstr "помилка протоколу: очікувалося \"<url> <шлях>\", пропущено пробіл"
+
+#, c-format
+msgid "failed to download file at URL '%s'"
+msgstr "не вдалося завантажити файл за URL-адресою \"%s\""
+
+msgid "git-http-push failed"
+msgstr "git-http-push завершився невдало"
+
+msgid "remote-curl: usage: git remote-curl <remote> [<url>]"
+msgstr ""
+"remote-curl: використання: git remote-curl <віддаленe-призначення> [<url>]"
+
+msgid "remote-curl: error reading command stream from git"
+msgstr "remote-curl: помилка зчитування потоку команд з git"
+
+msgid "remote-curl: fetch attempted without a local repo"
+msgstr "remote-curl: спроба отримання без локального сховища"
+
+#, c-format
+msgid "remote-curl: unknown command '%s' from git"
+msgstr "remote-curl: невідома команда \"%s\" з git"
+
+#, c-format
+msgid "config remote shorthand cannot begin with '/': %s"
+msgstr "скорочення віддаленної конфігураціі не може починатися з '/': %s"
+
+msgid "more than one receivepack given, using the first"
+msgstr "надано більше одного пакунка для отримання, використано перший"
+
+msgid "more than one uploadpack given, using the first"
+msgstr "надано більше одного пакунка для завантаження, використано перший"
+
+#, c-format
+msgid "unrecognized value transfer.credentialsInUrl: '%s'"
+msgstr "нерозпізнане значення transfer.credentialsInUrl: '%s'"
+
+#, c-format
+msgid "URL '%s' uses plaintext credentials"
+msgstr "URL-адреса '%s' використовує облікові дані у відкритому тексті"
+
+#, c-format
+msgid "Cannot fetch both %s and %s to %s"
+msgstr "Неможливо отримати як %s, так і %s до %s"
+
+#, c-format
+msgid "%s usually tracks %s, not %s"
+msgstr "%s зазвичай відстежує %s, а не %s"
+
+#, c-format
+msgid "%s tracks both %s and %s"
+msgstr "%s відстежує як %s, так і %s"
+
+#, c-format
+msgid "key '%s' of pattern had no '*'"
+msgstr "ключ '%s' шаблону не містив '*'"
+
+#, c-format
+msgid "value '%s' of pattern has no '*'"
+msgstr "значення '%s' шаблону не містить '*'"
+
+#, c-format
+msgid "src refspec %s does not match any"
+msgstr "визначник посилання джерела %s не збігається з жодним"
+
+#, c-format
+msgid "src refspec %s matches more than one"
+msgstr "визначник посилання джерела %s збігається з більш ніж одним"
+
+#. TRANSLATORS: "matches '%s'%" is the <dst> part of "git push
+#. <remote> <src>:<dst>" push, and "being pushed ('%s')" is
+#. the <src>.
+#.
+
+#, c-format
+msgid ""
+"The destination you provided is not a full refname (i.e.,\n"
+"starting with \"refs/\"). We tried to guess what you meant by:\n"
+"\n"
+"- Looking for a ref that matches '%s' on the remote side.\n"
+"- Checking if the <src> being pushed ('%s')\n"
+"  is a ref in \"refs/{heads,tags}/\". If so we add a corresponding\n"
+"  refs/{heads,tags}/ prefix on the remote side.\n"
+"\n"
+"Neither worked, so we gave up. You must fully qualify the ref."
+msgstr ""
+"Призначення, що ви вказали, не є повною назвою посилання (такою,\n"
+"що починається з \"refs/\"). Ми спробували вгадати, що ви мали на увазі "
+"через:\n"
+"\n"
+"- Пошук посилання, яке відповідає '%s' на віддаленій стороні.\n"
+"- Перевірку, чи є <джерело> надсилання, ('%s')\n"
+"  посиланням у \"refs/{heads,tags}/\". Якщо так, то ми додаємо відповідний\n"
+"  refs/{heads,tags}/ префікс на віддаленій стороні.\n"
+"\n"
+"Ні те, ні інше не спрацювало, тому ми здалися. Ви повинні повністю "
+"кваліфікувати посилання."
+
+#, c-format
+msgid ""
+"The <src> part of the refspec is a commit object.\n"
+"Did you mean to create a new branch by pushing to\n"
+"'%s:refs/heads/%s'?"
+msgstr ""
+"Частина <джерело> визаначника посилання є об’єктом коміту.\n"
+"Ви хотіли створити нову гілку, надіславши зміни до\n"
+"'%s:refs/heads/%s'?"
+
+#, c-format
+msgid ""
+"The <src> part of the refspec is a tag object.\n"
+"Did you mean to create a new tag by pushing to\n"
+"'%s:refs/tags/%s'?"
+msgstr ""
+"Частина <джерело> визаначника посилання є об’єктом тегу.\n"
+"Ви хотіли створити новий тег, надіславши зміни до\n"
+"'%s:refs/tags/%s'?"
+
+#, c-format
+msgid ""
+"The <src> part of the refspec is a tree object.\n"
+"Did you mean to tag a new tree by pushing to\n"
+"'%s:refs/tags/%s'?"
+msgstr ""
+"Частина <джерело> визаначника посилання є об’єктом дерева.\n"
+"Ви хотіли позначити нове дерево, надіславши зміни до\n"
+"'%s:refs/tags/%s'?"
+
+#, c-format
+msgid ""
+"The <src> part of the refspec is a blob object.\n"
+"Did you mean to tag a new blob by pushing to\n"
+"'%s:refs/tags/%s'?"
+msgstr ""
+"Частина <джерело> визаначника посилання є об’єктом blob.\n"
+"Ви хотіли позначити новий blob, надіславши зміни до\n"
+"'%s:refs/tags/%s'?"
+
+#, c-format
+msgid "%s cannot be resolved to branch"
+msgstr "%s неможливо розвʼязати в гілку"
+
+#, c-format
+msgid "unable to delete '%s': remote ref does not exist"
+msgstr "не вдалося видалити '%s': віддалене посилання не існує"
+
+#, c-format
+msgid "dst refspec %s matches more than one"
+msgstr "визаначник посилання призначення %s збігається з більш ніж одним"
+
+#, c-format
+msgid "dst ref %s receives from more than one src"
+msgstr "посилання призначення %s отримує з більш ніж одного src"
+
+msgid "HEAD does not point to a branch"
+msgstr "HEAD не вказує на гілку"
+
+#, c-format
+msgid "no such branch: '%s'"
+msgstr "немає такої гілки: '%s'"
+
+#, c-format
+msgid "no upstream configured for branch '%s'"
+msgstr "першоджерельне сховище не налаштовано для гілки '%s'"
+
+#, c-format
+msgid "upstream branch '%s' not stored as a remote-tracking branch"
+msgstr ""
+"гілка '%s' першоджерельного сховища не збережена як віддалено відстежувана "
+"гілка"
+
+#, c-format
+msgid "push destination '%s' on remote '%s' has no local tracking branch"
+msgstr ""
+"шлях призначення надсилання '%s' на віддаленому '%s' не має гілки локального "
+"відстежування"
+
+#, c-format
+msgid "branch '%s' has no remote for pushing"
+msgstr "гілка '%s' не має віддаленого призначення для надсилання"
+
+#, c-format
+msgid "push refspecs for '%s' do not include '%s'"
+msgstr "надіслані визначники посилань для \"%s\" не включають \"%s\""
+
+msgid "push has no destination (push.default is 'nothing')"
+msgstr "надсилання не має призначення (push.default дорівнює 'nothing')"
+
+msgid "cannot resolve 'simple' push to a single destination"
+msgstr ""
+"неможливо розвʼязати \"simple\" надсилання до одного пункту призначення"
+
+#, c-format
+msgid "couldn't find remote ref %s"
+msgstr "не вдалося знайти віддалене посилання %s"
+
+#, c-format
+msgid "* Ignoring funny ref '%s' locally"
+msgstr "* Ігнорування кумедних рефів '%s' локально"
+
+#, c-format
+msgid "Your branch is based on '%s', but the upstream is gone.\n"
+msgstr "Ваша гілка базується на '%s', але першоджерельне сховище зникло.\n"
+
+msgid "  (use \"git branch --unset-upstream\" to fixup)\n"
+msgstr ""
+"  (використовуйте команду \"git branch --unset-upstream\", щоб виправити)\n"
+
+#, c-format
+msgid "Your branch is up to date with '%s'.\n"
+msgstr "Ваша гілка не відрізняється від '%s'.\n"
+
+#, c-format
+msgid "Your branch and '%s' refer to different commits.\n"
+msgstr "Ваша гілка та гілка '%s' посилаються до різних комітів.\n"
+
+#, c-format
+msgid "  (use \"%s\" for details)\n"
+msgstr "  (використовуйте \"%s\" для отримання детальної інформації)\n"
+
+#, c-format
+msgid "Your branch is ahead of '%s' by %d commit.\n"
+msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
+msgstr[0] "Ваша гілка випереджає '%s' на %d коміт.\n"
+msgstr[1] "Ваша гілка випереджає '%s' на %d коміти.\n"
+msgstr[2] "Ваша гілка випереджає '%s' на %d комітів.\n"
+
+msgid "  (use \"git push\" to publish your local commits)\n"
+msgstr "  (використовуйте \"git push\" для публікації локальних комітів)\n"
+
+#, c-format
+msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
+msgid_plural ""
+"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
+msgstr[0] ""
+"Ваша гілка відстає від \"%s\" на %d коміт, і її можна перемотати вперед.\n"
+msgstr[1] ""
+"Ваша гілка відстає від \"%s\" на %d коміти, і її можна перемотати вперед.\n"
+msgstr[2] ""
+"Ваша гілка відстає від гілки '%s' на %d комітів, і її можна перемотати "
+"вперед.\n"
+
+msgid "  (use \"git pull\" to update your local branch)\n"
+msgstr "  (використовуйте \"git pull\", щоб оновити вашу локальну гілку)\n"
+
+#, c-format
+msgid ""
+"Your branch and '%s' have diverged,\n"
+"and have %d and %d different commit each, respectively.\n"
+msgid_plural ""
+"Your branch and '%s' have diverged,\n"
+"and have %d and %d different commits each, respectively.\n"
+msgstr[0] ""
+"Ваша гілка і гілка '%s' розійшлися,\n"
+"і мають %d і %d різний коміт відповідно.\n"
+msgstr[1] ""
+"Ваша гілка і гілка '%s' розійшлися,\n"
+"і мають %d і %d різних коміта відповідно.\n"
+msgstr[2] ""
+"Ваша гілка і гілка '%s' розійшлися,\n"
+"і мають %d і %d різних комітів відповідно.\n"
+
+msgid "  (use \"git pull\" to merge the remote branch into yours)\n"
+msgstr "  (використовуйте \"git pull\", щоб злити віддалену гілку з вашою)\n"
+
+#, c-format
+msgid "cannot parse expected object name '%s'"
+msgstr "неможливо розібрати очікувану назву обʼєкту \"%s\""
+
+#, c-format
+msgid "cannot strip one component off url '%s'"
+msgstr "неможливо вилучити один компонент з url '%s'"
+
+#, c-format
+msgid "bad replace ref name: %s"
+msgstr "неприпустима назва змінного посилання: %s"
+
+#, c-format
+msgid "duplicate replace ref: %s"
+msgstr "дубльована заміна посилання: %s"
+
+#, c-format
+msgid "replace depth too high for object %s"
+msgstr "глибина заміни занадто висока для обʼєкта %s"
+
+msgid "corrupt MERGE_RR"
+msgstr "пошкоджений MERGE_RR"
+
+msgid "unable to write rerere record"
+msgstr "неможливо зробити rerere запис"
+
+#, c-format
+msgid "there were errors while writing '%s' (%s)"
+msgstr "виникли помилки під час запису \"%s\" (%s)"
+
+#, c-format
+msgid "could not parse conflict hunks in '%s'"
+msgstr "не вдалося розібрати конфліктні шматки в \"%s\""
+
+#, c-format
+msgid "failed utime() on '%s'"
+msgstr "невдалий utime() на \"%s\""
+
+#, c-format
+msgid "writing '%s' failed"
+msgstr "запис \"%s\" завершився невдало"
+
+#, c-format
+msgid "Staged '%s' using previous resolution."
+msgstr "Індексовано \"%s\" з використанням попереднього розвʼязання."
+
+#, c-format
+msgid "Recorded resolution for '%s'."
+msgstr "Записано розвʼязання для \"%s\"."
+
+#, c-format
+msgid "Resolved '%s' using previous resolution."
+msgstr "Розвʼязано \"%s\" з використанням попереднього розвʼязання."
+
+#, c-format
+msgid "cannot unlink stray '%s'"
+msgstr "неможливо відʼєднати блукаючий \"%s\""
+
+#, c-format
+msgid "Recorded preimage for '%s'"
+msgstr "Записано попереднє зображення для \"%s\""
+
+#, c-format
+msgid "failed to update conflicted state in '%s'"
+msgstr "не вдалося оновити конфліктний стан у \"%s\""
+
+#, c-format
+msgid "no remembered resolution for '%s'"
+msgstr "немає записаного вирішення для \"%s\""
+
+#, c-format
+msgid "Updated preimage for '%s'"
+msgstr "Оновлено попереднє зображення для \"%s\""
+
+#, c-format
+msgid "Forgot resolution for '%s'\n"
+msgstr "Забуто розвʼязання для \"%s\"\n"
+
+msgid "unable to open rr-cache directory"
+msgstr "неможливо відкрити rr-cache директорію"
+
+msgid "update the index with reused conflict resolution if possible"
+msgstr ""
+"оновити індекс з повторним використанням розвʼязання конфліктів, якщо це "
+"можливо"
+
+msgid "could not determine HEAD revision"
+msgstr "не вдалося визначити ревізію HEAD"
+
+#, c-format
+msgid "failed to find tree of %s"
+msgstr "не вдалося знайти дерево %s"
+
+#, c-format
+msgid "unsupported section for hidden refs: %s"
+msgstr "непідтримувана секція для прихованих посилань: %s"
+
+msgid "--exclude-hidden= passed more than once"
+msgstr "--exclude-hidden= передано більше одного разу"
+
+#, c-format
+msgid "resolve-undo records `%s` which is missing"
+msgstr ""
+
+#, c-format
+msgid "could not get commit for ancestry-path argument %s"
+msgstr ""
+
+msgid "--unpacked=<packfile> no longer supported"
+msgstr "--unpacked=<файл пакунка> більше не підтримується"
+
+msgid "your current branch appears to be broken"
+msgstr "ваша поточна гілка виглядає зламаною"
+
+#, c-format
+msgid "your current branch '%s' does not have any commits yet"
+msgstr "ваша поточна гілка \"%s\" ще не має жодних комітів"
+
+msgid "object filtering requires --objects"
+msgstr "для фільтрації обʼєктів потрібен параметр --objects"
+
+msgid "-L does not yet support diff formats besides -p and -s"
+msgstr "-L поки що не підтримує diff формати, окрім -p та -s"
+
+#, c-format
+msgid "cannot create async thread: %s"
+msgstr "неможливо створити асинхронний потік: %s"
+
+#, c-format
+msgid "'%s' does not exist"
+msgstr "\"%s\" не існує"
+
+#, c-format
+msgid "could not switch to '%s'"
+msgstr "не вдалося переключитися на \"%s\""
+
+msgid "need a working directory"
+msgstr "потрібна робоча директорія"
+
+msgid "Scalar enlistments require a worktree"
+msgstr ""
+
+#, c-format
+msgid "could not configure %s=%s"
+msgstr "не вдалося налаштувати %s=%s"
+
+msgid "could not configure log.excludeDecoration"
+msgstr "не вдалося налаштувати log.excludeDecoration"
+
+msgid "could not add enlistment"
+msgstr "не вдалося додати кореневу директорію проекту"
+
+msgid "could not set recommended config"
+msgstr "не вдалося встановити рекомендовану конфігурацію"
+
+msgid "could not turn on maintenance"
+msgstr "не вдалося ввімкнути технічне обслуговування"
+
+msgid "could not start the FSMonitor daemon"
+msgstr "не вдалося запустити FSMonitor демон"
+
+msgid "could not turn off maintenance"
+msgstr "не вдалося вимкнути технічне обслуговування"
+
+msgid "could not remove enlistment"
+msgstr "не вдалося видалити директорію верхнього рівня"
+
+#, c-format
+msgid "remote HEAD is not a branch: '%.*s'"
+msgstr "віддалений HEAD не є гілкою: \"%.*s\""
+
+msgid "failed to get default branch name from remote; using local default"
+msgstr ""
+"не вдалося отримати назву гілки за замовчуванням з віддаленого сховища; "
+"використано локальне значення за замовчуванням"
+
+msgid "failed to get default branch name"
+msgstr "не вдалося отримати назву гілки за замовчуванням"
+
+msgid "failed to unregister repository"
+msgstr "не вдалося скасувати реєстрацію сховища"
+
+msgid "failed to stop the FSMonitor daemon"
+msgstr "не вдалося зупинити FSMonitor демон"
+
+msgid "failed to delete enlistment directory"
+msgstr "не вдалося видалити директорію верхнього рівня"
+
+msgid "branch to checkout after clone"
+msgstr "гілка, на яку перейти після клонування"
+
+msgid "when cloning, create full working directory"
+msgstr "при клонуванні створювати повну робочу директорію"
+
+msgid "only download metadata for the branch that will be checked out"
+msgstr ""
+"завантажити метадані тільки для гілки, на яку буде здійснюватися перехід"
+
+msgid "scalar clone [<options>] [--] <repo> [<dir>]"
+msgstr "скалярний клон [<опції>] [--] <сховище> [<директорія>]"
+
+#, c-format
+msgid "cannot deduce worktree name from '%s'"
+msgstr "неможливо вивести назву робочого дерева з \"%s\""
+
+#, c-format
+msgid "directory '%s' exists already"
+msgstr "директорія \"%s\" вже існує"
+
+#, c-format
+msgid "failed to get default branch for '%s'"
+msgstr "не вдалося отримати гілку за замовчуванням для \"%s\""
+
+#, c-format
+msgid "could not configure remote in '%s'"
+msgstr "не вдалося налаштувати віддалене сховище в \"%s\""
+
+#, c-format
+msgid "could not configure '%s'"
+msgstr "не вдалося налаштувати \"%s\""
+
+msgid "partial clone failed; attempting full clone"
+msgstr "не вдалося зробити частковий клон; спроба зробити повний клон"
+
+msgid "could not configure for full clone"
+msgstr "не вдалося налаштувати для повного клона"
+
+msgid "scalar diagnose [<enlistment>]"
+msgstr "scalar diagnose [<коренева-директорія-проекту>]"
+
+msgid "`scalar list` does not take arguments"
+msgstr "\"scalar list\" не приймає аргументів"
+
+msgid "scalar register [<enlistment>]"
+msgstr "scalar register [<коренева-директорія-проекту>]"
+
+msgid "reconfigure all registered enlistments"
+msgstr "переналаштувати всі зареєстровані кореневі директорії проекту"
+
+msgid "scalar reconfigure [--all | <enlistment>]"
+msgstr "scalar reconfigure [--all | <коренева-директорія-проекту>]"
+
+msgid "--all or <enlistment>, but not both"
+msgstr "--all або <коренева-директорія-проекту>, але не обидва"
+
+#, c-format
+msgid "could not remove stale scalar.repo '%s'"
+msgstr "неможливо видалити застаріле scalar.repo \"%s\""
+
+#, c-format
+msgid "removing stale scalar.repo '%s'"
+msgstr "видалення застарілого scalar.repo \"%s\""
+
+#, c-format
+msgid "git repository gone in '%s'"
+msgstr "git сховище зникло у \"%s\""
+
+msgid ""
+"scalar run <task> [<enlistment>]\n"
+"Tasks:\n"
+msgstr ""
+"scalar run <завдання> [<коренева-директорія-проекту>]\n"
+"Завдання:\n"
+
+#, c-format
+msgid "no such task: '%s'"
+msgstr "немає такого завдання: \"%s\""
+
+msgid "scalar unregister [<enlistment>]"
+msgstr "scalar unregister [<коренева-директорія-проекту>]"
+
+msgid "scalar delete <enlistment>"
+msgstr "scalar delete <коренева-директорія-проекту>"
+
+msgid "refusing to delete current working directory"
+msgstr "відмова видалення поточної робочої директорії"
+
+msgid "include Git version"
+msgstr "включити версію Git"
+
+msgid "include Git's build options"
+msgstr "включити опції збірки Git"
+
+msgid "scalar verbose [-v | --verbose] [--build-options]"
+msgstr ""
+
+msgid "-C requires a <directory>"
+msgstr "-C потребує наявності <директорії>"
+
+#, c-format
+msgid "could not change to '%s'"
+msgstr "не вдалося змінити на \"%s\""
+
+msgid "-c requires a <key>=<value> argument"
+msgstr "-c потребує <ключ>=<значення> аргумент"
+
+msgid ""
+"scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n"
+"\n"
+"Commands:\n"
+msgstr ""
+"scalar [-C <директорія>] [-c <ключ>=<значення>] <команда> [<опції>]\n"
+"\n"
+"Команди:\n"
+
+msgid "unexpected flush packet while reading remote unpack status"
+msgstr ""
+"несподіваний flush пакет під час зчитування статусу віддаленого розпакування"
+
+#, c-format
+msgid "unable to parse remote unpack status: %s"
+msgstr "не вдалося розібрати стан розпакування віддаленого сховища: %s"
+
+#, c-format
+msgid "remote unpack failed: %s"
+msgstr "віддалене розпакування не вдалося: %s"
+
+msgid "failed to sign the push certificate"
+msgstr "не вдалося підписати сертифікат надсилання"
+
+msgid "send-pack: unable to fork off fetch subprocess"
+msgstr "send-pack: не вдалося розгалужити підпроцес отримання"
+
+msgid "push negotiation failed; proceeding anyway with push"
+msgstr "переговори з надсилання не вдалися; все одно продовжуємо надсилання"
+
+msgid "the receiving end does not support this repository's hash algorithm"
+msgstr "отримуюча сторона не підтримує хеш-алгоритм цього сховища"
+
+msgid "the receiving end does not support --signed push"
+msgstr "отримуюча сторона не підтримує --signed push"
+
+msgid ""
+"not sending a push certificate since the receiving end does not support --"
+"signed push"
+msgstr ""
+"сертифікат надсилання не відправлено, оскільки отримуюча сторона не "
+"підтримує --signed push"
+
+msgid "the receiving end does not support --atomic push"
+msgstr "отримуюча сторона не підтримує --atomic push"
+
+msgid "the receiving end does not support push options"
+msgstr "отримуюча сторона не підтримує опції push"
+
+#, c-format
+msgid "invalid commit message cleanup mode '%s'"
+msgstr "неприпустимий режим очищення дописів до коміту \"%s\""
+
+#, c-format
+msgid "could not delete '%s'"
+msgstr "не вдалося видалити \"%s\""
+
+msgid "revert"
+msgstr "вивертання"
+
+msgid "cherry-pick"
+msgstr "висмикування"
+
+msgid "rebase"
+msgstr "перебазування"
+
+#, c-format
+msgid "unknown action: %d"
+msgstr "невідома дія: %d"
+
+msgid ""
+"after resolving the conflicts, mark the corrected paths\n"
+"with 'git add <paths>' or 'git rm <paths>'"
+msgstr ""
+"після розвʼязання конфліктів позначте виправлені шляхи\n"
+"за допомогою \"git add <шляхи>\" або \"git rm <шляхи>\""
+
+msgid ""
+"After resolving the conflicts, mark them with\n"
+"\"git add/rm <pathspec>\", then run\n"
+"\"git cherry-pick --continue\".\n"
+"You can instead skip this commit with \"git cherry-pick --skip\".\n"
+"To abort and get back to the state before \"git cherry-pick\",\n"
+"run \"git cherry-pick --abort\"."
+msgstr ""
+"Після розвʼязання конфліктів позначте їх за допомогою\n"
+"\"git add/rm <визначник шляху>\", а потім виконайте\n"
+"\"git cherry-pick --continue\".\n"
+"Замість цього ви можете пропустити цей комміт за допомогою \"git cherry-pick "
+"--skip\".\n"
+"Щоб перервати процес і повернутися до стану перед \"git cherry-pick\",\n"
+"виконайте \"git cherry-pick --abort\"."
+
+msgid ""
+"After resolving the conflicts, mark them with\n"
+"\"git add/rm <pathspec>\", then run\n"
+"\"git revert --continue\".\n"
+"You can instead skip this commit with \"git revert --skip\".\n"
+"To abort and get back to the state before \"git revert\",\n"
+"run \"git revert --abort\"."
+msgstr ""
+"Після розвʼязання конфліктів позначте їх за допомогою\n"
+"\"git add/rm <визначник шляху>\", а потім виконайте\n"
+"\"git revert --continue\".\n"
+"Замість цього ви можете пропустити цей коміт за допомогою \"git revert --"
+"skip\".\n"
+"Щоб перервати і повернутися до стану перед \"git revert\",\n"
+"виконайте \"git revert --abort\"."
+
+#, c-format
+msgid "could not lock '%s'"
+msgstr "не вдалося зафіксувати \"%s\""
+
+#, c-format
+msgid "could not write eol to '%s'"
+msgstr "не вдалося записати eol в \"%s\""
+
+#, c-format
+msgid "failed to finalize '%s'"
+msgstr "не вдалося завершити \"%s\""
+
+#, c-format
+msgid "your local changes would be overwritten by %s."
+msgstr "ваші локальні зміни будуть перезаписані %s."
+
+msgid "commit your changes or stash them to proceed."
+msgstr "зробіть коміт або додайте ваші зміни до схову, щоб продовжити."
+
+#. TRANSLATORS: %s will be "revert", "cherry-pick" or
+#. "rebase".
+#.
+
+#, c-format
+msgid "%s: Unable to write new index file"
+msgstr "%s: Не вдалося записати новий індексний файл"
+
+msgid "unable to update cache tree"
+msgstr "не вдалося оновити дерево кешу"
+
+msgid "could not resolve HEAD commit"
+msgstr "не вдалося розпізнати HEAD коміт"
+
+#, c-format
+msgid "no key present in '%.*s'"
+msgstr "немає ключа у \"%.*s\""
+
+#, c-format
+msgid "unable to dequote value of '%s'"
+msgstr "не вдалося вилучити лапки зі значення \"%s\""
+
+msgid "'GIT_AUTHOR_NAME' already given"
+msgstr "\"GIT_AUTHOR_NAME\" вже надано"
+
+msgid "'GIT_AUTHOR_EMAIL' already given"
+msgstr "\"GIT_AUTHOR_EMAIL\" вже надано"
+
+msgid "'GIT_AUTHOR_DATE' already given"
+msgstr "\"GIT_AUTHOR_DATE\" вже надано"
+
+#, c-format
+msgid "unknown variable '%s'"
+msgstr "невідома змінна \"%s\""
+
+msgid "missing 'GIT_AUTHOR_NAME'"
+msgstr "бракує \"GIT_AUTHOR_NAME\""
+
+msgid "missing 'GIT_AUTHOR_EMAIL'"
+msgstr "бракує \"GIT_AUTHOR_EMAIL\""
+
+msgid "missing 'GIT_AUTHOR_DATE'"
+msgstr "бракує \"GIT_AUTHOR_DATE\""
+
+#, c-format
+msgid ""
+"you have staged changes in your working tree\n"
+"If these changes are meant to be squashed into the previous commit, run:\n"
+"\n"
+"  git commit --amend %s\n"
+"\n"
+"If they are meant to go into a new commit, run:\n"
+"\n"
+"  git commit %s\n"
+"\n"
+"In both cases, once you're done, continue with:\n"
+"\n"
+"  git rebase --continue\n"
+msgstr ""
+"ви маєте індексовані зміни у вашому робочому дереві\n"
+"Якщо ці зміни мають бути стиснуті у попередній коміт, запустіть:\n"
+"\n"
+"  git commit --amend %s\n"
+"\n"
+"Якщо вони мають потрапити до нового коміту, виконайте:\n"
+"\n"
+"  git commit %s\n"
+"\n"
+"В обох випадках, як тільки ви закінчите, продовжуйте за допомогою:\n"
+"\n"
+"  git rebase --continue\n"
+
+msgid "'prepare-commit-msg' hook failed"
+msgstr "\"prepare-commit-msg\" гачок завершився невдало"
+
+msgid ""
+"Your name and email address were configured automatically based\n"
+"on your username and hostname. Please check that they are accurate.\n"
+"You can suppress this message by setting them explicitly. Run the\n"
+"following command and follow the instructions in your editor to edit\n"
+"your configuration file:\n"
+"\n"
+"    git config --global --edit\n"
+"\n"
+"After doing this, you may fix the identity used for this commit with:\n"
+"\n"
+"    git commit --amend --reset-author\n"
+msgstr ""
+"Ваше імʼя та адреса електронної пошти були налаштовані автоматично на "
+"основі\n"
+"вашого імені користувача та назви хосту. Будь ласка, перевірте їх "
+"правильність.\n"
+"Ви можете приховати це повідомлення, встановивши їх явно. Запустіть\n"
+"наступну команду і дотримуйтесь інструкцій у вашому редакторі, щоб "
+"відредагувати\n"
+"ваш конфігураційний файл:\n"
+"\n"
+"    git config --global --edit\n"
+"\n"
+"Після цього ви можете виправити особистість автора, використану для цього "
+"коміту, за допомогою\n"
+"\n"
+"    git commit --amend --reset-author\n"
+
+msgid ""
+"Your name and email address were configured automatically based\n"
+"on your username and hostname. Please check that they are accurate.\n"
+"You can suppress this message by setting them explicitly:\n"
+"\n"
+"    git config --global user.name \"Your Name\"\n"
+"    git config --global user.email you@example.com\n"
+"\n"
+"After doing this, you may fix the identity used for this commit with:\n"
+"\n"
+"    git commit --amend --reset-author\n"
+msgstr ""
+"Ваше імʼя та адреса електронної пошти були налаштовані автоматично на "
+"основі\n"
+"вашого імені користувача та назви хосту. Будь ласка, перевірте їх "
+"правильність.\n"
+"Ви можете приховати це повідомлення, вказавши їх явно:\n"
+"\n"
+"    git config --global user.name \"Ваше імʼя\"\n"
+"    git config --global user.email you@example.com\n"
+"\n"
+"Після цього ви можете виправити особистість автора, використану для цього "
+"коміту, за допомогою\n"
+"\n"
+"    git commit --amend --reset-author\n"
+
+msgid "couldn't look up newly created commit"
+msgstr "не вдалося знайти новостворений коміт"
+
+msgid "could not parse newly created commit"
+msgstr "не вдалося розібрати новостворений коміт"
+
+msgid "unable to resolve HEAD after creating commit"
+msgstr "не вдалося розвʼязати HEAD після створення коміту"
+
+msgid "detached HEAD"
+msgstr "відʼєднаний HEAD"
+
+msgid " (root-commit)"
+msgstr " (кореневий комміт)"
+
+msgid "could not parse HEAD"
+msgstr "неможливо розібрати HEAD"
+
+#, c-format
+msgid "HEAD %s is not a commit!"
+msgstr "HEAD %s не є комітом!"
+
+msgid "unable to parse commit author"
+msgstr "не вдалося розібрати автора коміту"
+
+#, c-format
+msgid "unable to read commit message from '%s'"
+msgstr "не вдалося прочитати допис до коміта від \"%s\""
+
+#, c-format
+msgid "invalid author identity '%s'"
+msgstr "неприпустима ідентичність автора \"%s\""
+
+msgid "corrupt author: missing date information"
+msgstr "пошкоджені дані про автора: відсутня інформація про дату"
+
+#, c-format
+msgid "could not update %s"
+msgstr "не вдалося оновити %s"
+
+#, c-format
+msgid "could not parse commit %s"
+msgstr "не вдалося розібрати коміт %s"
+
+#, c-format
+msgid "could not parse parent commit %s"
+msgstr "не вдалося розібрати джерельний коміт %s"
+
+#, c-format
+msgid "unknown command: %d"
+msgstr "невідома команда: %d"
+
+msgid "This is the 1st commit message:"
+msgstr "Це перший допис до коміта:"
+
+#, c-format
+msgid "This is the commit message #%d:"
+msgstr "Це допис до коміта #%d:"
+
+msgid "The 1st commit message will be skipped:"
+msgstr "Перший допис до коміта буде пропущено:"
+
+#, c-format
+msgid "The commit message #%d will be skipped:"
+msgstr "Допис до коміта #%d буде пропущено:"
+
+#, c-format
+msgid "This is a combination of %d commits."
+msgstr "Це комбінація %d комітів."
+
+#, c-format
+msgid "cannot write '%s'"
+msgstr "неможливо записати \"%s\""
+
+msgid "need a HEAD to fixup"
+msgstr "потрібен HEAD, щоб виправити"
+
+msgid "could not read HEAD"
+msgstr "не вдалося прочитати HEAD"
+
+msgid "could not read HEAD's commit message"
+msgstr "не вдалося прочитати допис до коміта HEAD"
+
+#, c-format
+msgid "could not read commit message of %s"
+msgstr "не вдалося прочитати допис до коміта %s"
+
+msgid "your index file is unmerged."
+msgstr "ваш індексний файл не злитий."
+
+msgid "cannot fixup root commit"
+msgstr "не вдалося виправити кореневий коміт"
+
+#, c-format
+msgid "commit %s is a merge but no -m option was given."
+msgstr "коміт %s - це злиття, але опція -m не була вказана."
+
+#, c-format
+msgid "commit %s does not have parent %d"
+msgstr "коміт %s не має джерела %d"
+
+#, c-format
+msgid "cannot get commit message for %s"
+msgstr "неможливо отримати допис до коміта для %s"
+
+#. TRANSLATORS: The first %s will be a "todo" command like
+#. "revert" or "pick", the second %s a SHA1.
+
+#, c-format
+msgid "%s: cannot parse parent commit %s"
+msgstr "%s: не вдалося розібрати джерельний коміт %s"
+
+#, c-format
+msgid "could not rename '%s' to '%s'"
+msgstr "не вдалося перейменувати \"%s\" на \"%s\""
+
+#, c-format
+msgid "could not revert %s... %s"
+msgstr "не вдалося зробити вивертання %s... %s"
+
+#, c-format
+msgid "could not apply %s... %s"
+msgstr "не вдалося застосувати %s... %s"
+
+#, c-format
+msgid "dropping %s %s -- patch contents already upstream\n"
+msgstr ""
+"скидання %s %s -- вміст латки вже знаходиться у першоджерельному сховищі\n"
+
+#, c-format
+msgid "git %s: failed to read the index"
+msgstr "git %s: не вдалося прочитати індекс"
+
+#, c-format
+msgid "git %s: failed to refresh the index"
+msgstr "git %s: не вдалося оновити індекс"
+
+#, c-format
+msgid "'%s' is not a valid label"
+msgstr "\"%s\" не є припустимою міткою"
+
+#, c-format
+msgid "'%s' is not a valid refname"
+msgstr "\"%s\" не є припустимою назвою посилання"
+
+#, c-format
+msgid "update-ref requires a fully qualified refname e.g. refs/heads/%s"
+msgstr "update-ref потребує повної назви посилання, наприклад, refs/heads/%s"
+
+#, c-format
+msgid "invalid command '%.*s'"
+msgstr "неприпустима команда \"%.*s\""
+
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s не приймає аргументи: \"%s\""
+
+#, c-format
+msgid "missing arguments for %s"
+msgstr "відсутні аргументи для %s"
+
+#, c-format
+msgid "could not parse '%s'"
+msgstr "не вдалося розібрати \"%s\""
+
+#, c-format
+msgid "invalid line %d: %.*s"
+msgstr "невірний рядок %d: %.*s"
+
+#, c-format
+msgid "cannot '%s' without a previous commit"
+msgstr "неможливо зробити \"%s\" без попереднього коміту"
+
+msgid "cancelling a cherry picking in progress"
+msgstr "скасування поточного висмикування"
+
+msgid "cancelling a revert in progress"
+msgstr "наразі йде скасування вивертання"
+
+msgid "please fix this using 'git rebase --edit-todo'."
+msgstr "будь ласка, виправте це за допомогою \"git rebase --edit-todo\"."
+
+#, c-format
+msgid "unusable instruction sheet: '%s'"
+msgstr "непридатна інструкція: \"%s\""
+
+msgid "no commits parsed."
+msgstr "не розібрано жодного коміту."
+
+msgid "cannot cherry-pick during a revert."
+msgstr "неможливо зробити висмикування під час вивертання."
+
+msgid "cannot revert during a cherry-pick."
+msgstr "неможливо зробити вивертання під час висмикування."
+
+msgid "unusable squash-onto"
+msgstr "непридатний squash-onto"
+
+#, c-format
+msgid "malformed options sheet: '%s'"
+msgstr "невірно сформований список опцій: \"%s\""
+
+msgid "empty commit set passed"
+msgstr "передано порожній набір комітів"
+
+msgid "revert is already in progress"
+msgstr "наразі виконується операція вивертання"
+
+#, c-format
+msgid "try \"git revert (--continue | %s--abort | --quit)\""
+msgstr "спробуйте \"git revert (--continue | %s--abort | --quit)\""
+
+msgid "cherry-pick is already in progress"
+msgstr "наразі вже триває висмикування"
+
+#, c-format
+msgid "try \"git cherry-pick (--continue | %s--abort | --quit)\""
+msgstr "спробуйте \"git cherry-pick (--continue | %s--abort | --quit)\""
+
+#, c-format
+msgid "could not create sequencer directory '%s'"
+msgstr "не вдалося створити директорію секвенсора \"%s\""
+
+msgid "no cherry-pick or revert in progress"
+msgstr "наразі не триває ні скасування, ні висмикування"
+
+msgid "cannot resolve HEAD"
+msgstr "неможливо розпізнати HEAD"
+
+msgid "cannot abort from a branch yet to be born"
+msgstr "неможливо перервати з гілки, яка ще не народилася"
+
+#, c-format
+msgid "cannot read '%s': %s"
+msgstr "неможливо прочитати \"%s\": %s"
+
+msgid "unexpected end of file"
+msgstr "несподіваний кінець файлу"
+
+#, c-format
+msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
+msgstr "збережений pre-cherry-pick HEAD файл \"%s\" пошкоджено"
+
+msgid "You seem to have moved HEAD. Not rewinding, check your HEAD!"
+msgstr ""
+"Здається, ви пересунули HEAD. Перемотування не виконується, перевірте свій "
+"HEAD!"
+
+msgid "no revert in progress"
+msgstr "наразі операція вивертання не виконується"
+
+msgid "no cherry-pick in progress"
+msgstr "наразі висмикування не виконується"
+
+msgid "failed to skip the commit"
+msgstr "не вдалося пропустити коміт"
+
+msgid "there is nothing to skip"
+msgstr "немає чого пропускати"
+
+#, c-format
+msgid ""
+"have you committed already?\n"
+"try \"git %s --continue\""
+msgstr ""
+"ви вже зробили коміт?\n"
+"спробуйте \"git %s --continue\""
+
+msgid "cannot read HEAD"
+msgstr "неможливо прочитати HEAD"
+
+#, c-format
+msgid "unable to copy '%s' to '%s'"
+msgstr "не вдалося скопіювати \"%s\" в \"%s\""
+
+#, c-format
+msgid ""
+"You can amend the commit now, with\n"
+"\n"
+"  git commit --amend %s\n"
+"\n"
+"Once you are satisfied with your changes, run\n"
+"\n"
+"  git rebase --continue\n"
+msgstr ""
+"Ви можете внести зміни до коміту зараз за допомогою\n"
+"\n"
+"  git commit --amend %s\n"
+"\n"
+"Після того, як ви будете задоволені своїми змінами, виконайте\n"
+"\n"
+"  git rebase --continue\n"
+
+#, c-format
+msgid "Could not apply %s... %.*s"
+msgstr "Не вдалося застосувати %s... %.*s"
+
+#, c-format
+msgid "Could not merge %.*s"
+msgstr "Не вдалося злити %.*s"
+
+#, c-format
+msgid "Executing: %s\n"
+msgstr "Виконання: %s\n"
+
+#, c-format
+msgid ""
+"execution failed: %s\n"
+"%sYou can fix the problem, and then run\n"
+"\n"
+"  git rebase --continue\n"
+"\n"
+msgstr ""
+"не вдалося виконати : %s\n"
+"%sВи можете виправити проблему, а потім виконати\n"
+"\n"
+"  git rebase --continue\n"
+
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "та внесли зміни до індексу та/або робочого дерева\n"
+
+#, c-format
+msgid ""
+"execution succeeded: %s\n"
+"but left changes to the index and/or the working tree.\n"
+"Commit or stash your changes, and then run\n"
+"\n"
+"  git rebase --continue\n"
+"\n"
+msgstr ""
+"виконання пройшло успішно: %s\n"
+"але залишило зміни в індексі та/або робочому дереві.\n"
+"Зробіть коміт або додайте зміни до схову, а потім запустіть\n"
+"\n"
+"  git rebase --continue\n"
+"\n"
+
+#, c-format
+msgid "illegal label name: '%.*s'"
+msgstr "неприпустима назва мітки: \"%.*s\""
+
+#, c-format
+msgid "could not resolve '%s'"
+msgstr "не вдалося розпізнати \"%s\""
+
+msgid "writing fake root commit"
+msgstr "написання підробленого кореневого коміту"
+
+msgid "writing squash-onto"
+msgstr "запис squash-onto"
+
+msgid "cannot merge without a current revision"
+msgstr "неможливо злити без поточної ревізії"
+
+#, c-format
+msgid "unable to parse '%.*s'"
+msgstr "не вдалося розібрати \"%.*s\""
+
+#, c-format
+msgid "nothing to merge: '%.*s'"
+msgstr "нічого зливати: \"%.*s\""
+
+msgid "octopus merge cannot be executed on top of a [new root]"
+msgstr "octopus злиття неможливо виконати поверх [new root]"
+
+#, c-format
+msgid "could not get commit message of '%s'"
+msgstr "не вдалося отримати допис до коміта \"%s\""
+
+#, c-format
+msgid "could not even attempt to merge '%.*s'"
+msgstr "не вдалося навіть спробувати злити \"%.*s\""
+
+msgid "merge: Unable to write new index file"
+msgstr "злиття: Не вдалося записати новий файл індексу"
+
+#, c-format
+msgid ""
+"another 'rebase' process appears to be running; '%s.lock' already exists"
+msgstr "здається, запущено інший процес \"rebase\"; \"%s.lock\" вже існує"
+
+#, c-format
+msgid ""
+"Updated the following refs with %s:\n"
+"%s"
+msgstr ""
+"Оновлені наступні посилання з %s:\n"
+"%s"
+
+#, c-format
+msgid ""
+"Failed to update the following refs with %s:\n"
+"%s"
+msgstr ""
+"Не вдалося оновити наступні посилання з %s:\n"
+"%s"
+
+msgid "Cannot autostash"
+msgstr "Неможливо зробити автосхов"
+
+#, c-format
+msgid "Unexpected stash response: '%s'"
+msgstr "Неочікувана відповідь схову: \"%s\""
+
+#, c-format
+msgid "Could not create directory for '%s'"
+msgstr "Не вдалося створити директорію для \"%s\""
+
+#, c-format
+msgid "Created autostash: %s\n"
+msgstr "Створено автосхов: %s\n"
+
+msgid "could not reset --hard"
+msgstr "не вдалося виконати скидання з --hard"
+
+#, c-format
+msgid "Applied autostash.\n"
+msgstr "Застосовано автосхов.\n"
+
+#, c-format
+msgid "cannot store %s"
+msgstr "неможливо зберегти %s"
+
+#, c-format
+msgid ""
+"%s\n"
+"Your changes are safe in the stash.\n"
+"You can run \"git stash pop\" or \"git stash drop\" at any time.\n"
+msgstr ""
+"%s\n"
+"Ваші зміни в безпеці у схову.\n"
+"Ви можете запустити \"git stash pop\" або \"git stash drop\" у будь-який "
+"час.\n"
+
+msgid "Applying autostash resulted in conflicts."
+msgstr "Застосування автосхову призвело до конфліктів."
+
+msgid "Autostash exists; creating a new stash entry."
+msgstr "Автосхов існує; створення нового запису схову."
+
+msgid "could not detach HEAD"
+msgstr "не вдалося відʼєднати HEAD"
+
+#, c-format
+msgid "Stopped at HEAD\n"
+msgstr "Зупинено на HEAD\n"
+
+#, c-format
+msgid "Stopped at %s\n"
+msgstr "Зупинено на %s\n"
+
+#, c-format
+msgid ""
+"Could not execute the todo command\n"
+"\n"
+"    %.*s\n"
+"It has been rescheduled; To edit the command before continuing, please\n"
+"edit the todo list first:\n"
+"\n"
+"    git rebase --edit-todo\n"
+"    git rebase --continue\n"
+msgstr ""
+"Не вдалося виконати команду todo\n"
+"\n"
+"    %.*s\n"
+"Її було перенесено; Щоб відредагувати команду перед продовженням, будь "
+"ласка\n"
+"спочатку відредагуйте список справ:\n"
+"\n"
+"    git rebase --edit-todo\n"
+"    git rebase --continue\n"
+
+#, c-format
+msgid "Rebasing (%d/%d)%s"
+msgstr "Перебазування (%d/%d)%s"
+
+#, c-format
+msgid "Stopped at %s...  %.*s\n"
+msgstr "Зупинено на %s... %.*s\n"
+
+#, c-format
+msgid "unknown command %d"
+msgstr "невідома команда %d"
+
+msgid "could not read orig-head"
+msgstr "не вдалося прочитати orig-head"
+
+msgid "could not read 'onto'"
+msgstr "не вдалося прочитати  \"onto\""
+
+#, c-format
+msgid "could not update HEAD to %s"
+msgstr "не вдалося оновити HEAD до %s"
+
+#, c-format
+msgid "Successfully rebased and updated %s.\n"
+msgstr "Успішно перебазовано та оновлено %s.\n"
+
+msgid "cannot rebase: You have unstaged changes."
+msgstr "неможливо перебазувати: у вас є неіндексовані зміни."
+
+msgid "cannot amend non-existing commit"
+msgstr "неможливо виправити неіснуючий коміт"
+
+#, c-format
+msgid "invalid file: '%s'"
+msgstr "неприпустимий файл: \"%s\""
+
+#, c-format
+msgid "invalid contents: '%s'"
+msgstr "неприпустимий вміст: \"%s\""
+
+msgid ""
+"\n"
+"You have uncommitted changes in your working tree. Please, commit them\n"
+"first and then run 'git rebase --continue' again."
+msgstr ""
+"\n"
+"У вас є незакомічені зміни у вашому робочому дереві. Будь ласка, спочатку "
+"зробіть коміт,\n"
+"а потім знову виконайте \"git rebase --continue\"."
+
+#, c-format
+msgid "could not write file: '%s'"
+msgstr "не вдалося записати файл: \"%s\""
+
+msgid "could not remove CHERRY_PICK_HEAD"
+msgstr "не вдалося видалити CHERRY_PICK_HEAD"
+
+msgid "could not commit staged changes."
+msgstr "не вдалося записати індексовані зміни."
+
+#, c-format
+msgid "%s: can't cherry-pick a %s"
+msgstr "%s: неможливо зробити висмикування %s"
+
+#, c-format
+msgid "%s: bad revision"
+msgstr "%s: невірна ревізія"
+
+msgid "can't revert as initial commit"
+msgstr "неможливо зробити вивертання як початковий коміт"
+
+#, c-format
+msgid "skipped previously applied commit %s"
+msgstr "пропущено попередньо застосований коміт %s"
+
+msgid "use --reapply-cherry-picks to include skipped commits"
+msgstr "використовуйте --reapply-cherry-picks, щоб включити пропущені коміти"
+
+msgid "make_script: unhandled options"
+msgstr "make_script: необроблені опції"
+
+msgid "make_script: error preparing revisions"
+msgstr "make_script: помилка при підготовці ревізій"
+
+msgid "nothing to do"
+msgstr "нічого робити"
+
+msgid "could not skip unnecessary pick commands"
+msgstr "не вдалося пропустити непотрібні команди вибору"
+
+msgid "the script was already rearranged."
+msgstr "скрипт вже був перероблений."
+
+#, c-format
+msgid "update-refs file at '%s' is invalid"
+msgstr "файл update-refs за адресою \"%s\" є неприпустимим"
+
+#, c-format
+msgid "'%s' is outside repository at '%s'"
+msgstr "\"%s\" зовнішнє сховище в \"%s\""
+
+#, c-format
+msgid ""
+"%s: no such path in the working tree.\n"
+"Use 'git <command> -- <path>...' to specify paths that do not exist locally."
+msgstr ""
+"%s: немає такого шляху у робочому дереві.\n"
+"Використовуйте \"git <команда> -- <шлях>...\", щоб вказати шляхи, які не "
+"існують локально."
+
+#, c-format
+msgid ""
+"ambiguous argument '%s': unknown revision or path not in the working tree.\n"
+"Use '--' to separate paths from revisions, like this:\n"
+"'git <command> [<revision>...] -- [<file>...]'"
+msgstr ""
+"неоднозначний аргумент \"%s\": невідома ревізія або шлях не у робочому "
+"дереві.\n"
+"Використовуйте \"--\", щоб відокремити шлях від ревізій, наприклад, так:\n"
+"\"git <команда> [<ревізія>...] -- [<файл>...]\""
+
+#, c-format
+msgid "option '%s' must come before non-option arguments"
+msgstr "опція \"%s\" повинна стояти перед аргументами без опцій"
+
+#, c-format
+msgid ""
+"ambiguous argument '%s': both revision and filename\n"
+"Use '--' to separate paths from revisions, like this:\n"
+"'git <command> [<revision>...] -- [<file>...]'"
+msgstr ""
+"неоднозначний аргумент \"%s\": і ревізія, і назва файлу\n"
+"Використовуйте \"--\", щоб відокремити шляхи від ревізій, наприклад, так:\n"
+"\"git <команда> [<ревізія>...] -- [<файл>...]\""
+
+msgid "unable to set up work tree using invalid config"
+msgstr ""
+"не вдалося налаштувати робоче дерево, використовуючи неприпустиму "
+"конфігурацію"
+
+#, c-format
+msgid "Expected git repo version <= %d, found %d"
+msgstr "Очікувалось git сховищe версії <= %d, знайдено %d"
+
+msgid "unknown repository extension found:"
+msgid_plural "unknown repository extensions found:"
+msgstr[0] "знайдено невідомих розширень сховища:"
+msgstr[1] "знайдено невідомих розширень сховища:"
+msgstr[2] "знайдено невідомих розширень сховища:"
+
+msgid "repo version is 0, but v1-only extension found:"
+msgid_plural "repo version is 0, but v1-only extensions found:"
+msgstr[0] "версія сховища дорівнює 0, але знайдено v1-only розширень:"
+msgstr[1] "версія сховища дорівнює 0, але знайдено v1-only розширень:"
+msgstr[2] "версія сховища дорівнює 0, але знайдено v1-only розширень:"
+
+#, c-format
+msgid "error opening '%s'"
+msgstr "помилка при відкритті \"%s\""
+
+#, c-format
+msgid "too large to be a .git file: '%s'"
+msgstr "занадто великий для .git-файлу: \"%s\""
+
+#, c-format
+msgid "error reading %s"
+msgstr "помилка зчитування %s"
+
+#, c-format
+msgid "invalid gitfile format: %s"
+msgstr "неприпустимий формат git файлу: %s"
+
+#, c-format
+msgid "no path in gitfile: %s"
+msgstr "немає шляху в gitfile: %s"
+
+#, c-format
+msgid "not a git repository: %s"
+msgstr "не є git сховищем: %s"
+
+#, c-format
+msgid "'$%s' too big"
+msgstr "\"$%s\" занадто великий"
+
+#, c-format
+msgid "not a git repository: '%s'"
+msgstr "не є git сховищем: \"%s\""
+
+#, c-format
+msgid "cannot chdir to '%s'"
+msgstr "неможливо змінити директорію на \"%s\""
+
+msgid "cannot come back to cwd"
+msgstr "неможливо повернутися до поточної робочої директорії"
+
+#, c-format
+msgid "failed to stat '%*s%s%s'"
+msgstr "не вдалося записати \"%*s%s%s\""
+
+msgid "Unable to read current working directory"
+msgstr "Не вдалося прочитати поточну робочу директорію"
+
+#, c-format
+msgid "cannot change to '%s'"
+msgstr "неможливо змінити на \"%s\""
+
+#, c-format
+msgid "not a git repository (or any of the parent directories): %s"
+msgstr "не є git сховищем (як і жодна з батьківських директорій): %s"
+
+#, c-format
+msgid ""
+"not a git repository (or any parent up to mount point %s)\n"
+"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)."
+msgstr ""
+"не є git сховищем (як і жодна з батьківських директорій до місця монтування "
+"%s)\n"
+"Зупинка на межі файлової системи (GIT_DISCOVERY_ACROSS_FILESYSTEM не "
+"встановлено)."
+
+#, c-format
+msgid ""
+"detected dubious ownership in repository at '%s'\n"
+"%sTo add an exception for this directory, call:\n"
+"\n"
+"\tgit config --global --add safe.directory %s"
+msgstr ""
+"виявлено сумнівне право власності у сховищі за адресою \"%s\"\n"
+"%sЩоб додати виняток для цієї директорії, виконайте:\n"
+"\n"
+"\tgit config --global --add safe.directory %s"
+
+#, c-format
+msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')"
+msgstr ""
+"неможливо використати порожнє сховище \"%s\" (safe.bareRepository "
+"встановлено в \"%s\")"
+
+#, c-format
+msgid ""
+"problem with core.sharedRepository filemode value (0%.3o).\n"
+"The owner of files must always have read and write permissions."
+msgstr ""
+"проблема зі значенням файлового режиму core.sharedRepository (0%.3o).\n"
+"Власник файлів завжди повинен мати права на читання та запис."
+
+msgid "fork failed"
+msgstr "fork завершився невдало"
+
+msgid "setsid failed"
+msgstr "setsid завершився невдало"
+
+#, c-format
+msgid "index entry is a directory, but not sparse (%08x)"
+msgstr "індексний запис є директорією, але не є частковим (%08x)"
+
+msgid "cannot use split index with a sparse index"
+msgstr "не можна використовувати розділений індекс з частковим індексом"
+
+#, c-format
+msgid "%u.%2.2u GiB"
+msgstr "%u.%2.2u ГіБ"
+
+#, c-format
+msgid "%u.%2.2u GiB/s"
+msgstr "%u.%2.2u ГіБ/с"
+
+#, c-format
+msgid "%u.%2.2u MiB"
+msgstr "%u.%2.2u МіБ"
+
+#, c-format
+msgid "%u.%2.2u MiB/s"
+msgstr "%u.%2.2u МіБ/с"
+
+#, c-format
+msgid "%u.%2.2u KiB"
+msgstr "%u.%2.2u КіБ"
+
+#, c-format
+msgid "%u.%2.2u KiB/s"
+msgstr "%u.%2.2u КіБ/с"
+
+#, c-format
+msgid "%u byte"
+msgid_plural "%u bytes"
+msgstr[0] "%u байт"
+msgstr[1] "%u байти"
+msgstr[2] "%u байтів"
+
+#, c-format
+msgid "%u byte/s"
+msgid_plural "%u bytes/s"
+msgstr[0] "%u байт/s"
+msgstr[1] "%u байти/s"
+msgstr[2] "%u байтів/s"
+
+#, c-format
+msgid "ignoring suspicious submodule name: %s"
+msgstr "ігнорування підозрілої назви підмодуля: %s"
+
+msgid "negative values not allowed for submodule.fetchJobs"
+msgstr "негативні значення не дозволені для submodule.fetchJobs"
+
+#, c-format
+msgid "ignoring '%s' which may be interpreted as a command-line option: %s"
+msgstr ""
+"ігнорування \"%s\", який може бути інтерпретований як параметр командного "
+"рядка: %s"
+
+#, c-format
+msgid "Could not update .gitmodules entry %s"
+msgstr "Не вдалося оновити запис %s у .gitmodules"
+
+msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first"
+msgstr ""
+"Неможливо змінити незлиті .gitmodules, спочатку розвʼяжіть конфлікти злиття"
+
+#, c-format
+msgid "Could not find section in .gitmodules where path=%s"
+msgstr "Не вдалося знайти розділ у .gitmodules де path=%s"
+
+#, c-format
+msgid "Could not remove .gitmodules entry for %s"
+msgstr "Не вдалося видалити запис .gitmodules для %s"
+
+msgid "staging updated .gitmodules failed"
+msgstr "індексація оновленого .gitmodules завершилася невдало"
+
+#, c-format
+msgid "in unpopulated submodule '%s'"
+msgstr "у незаповненому підмодулі \"%s\""
+
+#, c-format
+msgid "Pathspec '%s' is in submodule '%.*s'"
+msgstr "Визначник шляху \"%s\" знаходиться у підмодулі \"%.*s\""
+
+#, c-format
+msgid "bad --ignore-submodules argument: %s"
+msgstr "невірний --ignore-submodules аргумент: %s"
+
+#, c-format
+msgid ""
+"Submodule in commit %s at path: '%s' collides with a submodule named the "
+"same. Skipping it."
+msgstr ""
+"Підмодуль у коміті %s за шляхом \"%s\" зіткнувся з підмодулем з такою самою "
+"назвою. Пропускаємо його."
+
+#, c-format
+msgid "submodule entry '%s' (%s) is a %s, not a commit"
+msgstr "запис підмодуля \"%s\" (%s) є %s, а не комітом"
+
+#, c-format
+msgid ""
+"Could not run 'git rev-list <commits> --not --remotes -n 1' command in "
+"submodule %s"
+msgstr ""
+"Не вдалося виконати команду \"git rev-list <коміти> --not --remotes -n 1\" у "
+"підмодулі %s"
+
+#, c-format
+msgid "process for submodule '%s' failed"
+msgstr "процес для підмодуля \"%s\" завершився невдало"
+
+#, c-format
+msgid "Pushing submodule '%s'\n"
+msgstr "Надсилання підмодуля \"%s\"\n"
+
+#, c-format
+msgid "Unable to push submodule '%s'\n"
+msgstr "Не вдалося надіслати підмодуль \"%s\"\n"
+
+#, c-format
+msgid "Fetching submodule %s%s\n"
+msgstr "Отримання підмодуля %s%s\n"
+
+#, c-format
+msgid "Could not access submodule '%s'\n"
+msgstr "Не вдалося отримати доступ до підмодуля \"%s\"\n"
+
+#, c-format
+msgid "Could not access submodule '%s' at commit %s\n"
+msgstr "Не вдалося отримати доступ до підмодуля \"%s\" для коміта %s\n"
+
+#, c-format
+msgid "Fetching submodule %s%s at commit %s\n"
+msgstr "Отримання підмодуля %s%s для коміта %s\n"
+
+#, c-format
+msgid ""
+"Errors during submodule fetch:\n"
+"%s"
+msgstr ""
+"Помилки під час отримання підмодуля:\n"
+"%s"
+
+#, c-format
+msgid "'%s' not recognized as a git repository"
+msgstr "\"%s\" не розпізнано як git сховище"
+
+#, c-format
+msgid "Could not run 'git status --porcelain=2' in submodule %s"
+msgstr ""
+"Не вдалося виконати команду \"git status --porcelain=2\" у підмодулі %s"
+
+#, c-format
+msgid "'git status --porcelain=2' failed in submodule %s"
+msgstr "\"git status --porcelain=2\" завершився невдало у підмодулі %s"
+
+#, c-format
+msgid "could not start 'git status' in submodule '%s'"
+msgstr "не вдалося запустити \"git status\" у підмодулі \"%s\""
+
+#, c-format
+msgid "could not run 'git status' in submodule '%s'"
+msgstr "не вдалося запустити \"git status\" у підмодулі \"%s\""
+
+#, c-format
+msgid "Could not unset core.worktree setting in submodule '%s'"
+msgstr "Не вдалося скинути налаштування core.worktree у підмодулі \"%s\""
+
+#, c-format
+msgid "could not recurse into submodule '%s'"
+msgstr "не вдалося рекурсивно перейти в підмодуль \"%s\""
+
+msgid "could not reset submodule index"
+msgstr "не вдалося скинути індекс підмодуля"
+
+#, c-format
+msgid "submodule '%s' has dirty index"
+msgstr "підмодуль \"%s\" має брудний індекс"
+
+#, c-format
+msgid "Submodule '%s' could not be updated."
+msgstr "Не вдалося оновити підмодуль \"%s\"."
+
+#, c-format
+msgid "submodule git dir '%s' is inside git dir '%.*s'"
+msgstr "підмодуль git dir \"%s\" знаходиться всередині git директорії \"%.*s\""
+
+#, c-format
+msgid ""
+"relocate_gitdir for submodule '%s' with more than one worktree not supported"
+msgstr ""
+"relocate_gitdir для підмодуля \"%s\" з більш ніж одним робочим деревом не "
+"підтримується"
+
+#, c-format
+msgid "could not lookup name for submodule '%s'"
+msgstr "не вдалося знайти назву для підмодуля \"%s\""
+
+#, c-format
+msgid "refusing to move '%s' into an existing git dir"
+msgstr "відмова переміщення \"%s\" до існуючої git директорії"
+
+#, c-format
+msgid ""
+"Migrating git directory of '%s%s' from\n"
+"'%s' to\n"
+"'%s'\n"
+msgstr ""
+"Міграція git-директорії \"%s%s\" з\n"
+"\"%s\" до\n"
+"\"%s\"\n"
+
+msgid "could not start ls-files in .."
+msgstr "не вдалося запустити ls-файли в .."
+
+#, c-format
+msgid "ls-tree returned unexpected return code %d"
+msgstr "ls-tree повернув неочікуваний код повернення %d"
+
+#, c-format
+msgid "failed to lstat '%s'"
+msgstr "не вдалося виконати lstat для \"%s\""
+
+msgid "no remote configured to get bundle URIs from"
+msgstr ""
+"немає налаштованого віддаленого призначення для отримання URI пакунків з "
+"нього"
+
+#, c-format
+msgid "remote '%s' has no configured URL"
+msgstr "віддалений \"%s\" не має налаштованої URL-адреси"
+
+msgid "could not get the bundle-uri list"
+msgstr "не вдалося отримати список bundle-uri"
+
+msgid "test-tool cache-tree <options> (control|prime|update)"
+msgstr "test-tool cache-tree <опції> (control|prime|update)"
+
+msgid "clear the cache tree before each iteration"
+msgstr "очищати дерево кешу перед кожною ітерацією"
+
+msgid "number of entries in the cache tree to invalidate (default 0)"
+msgstr ""
+"кількість записів у дереві кешу, які потрібно анулювати (за замовчуванням 0)"
+
+msgid "unhandled options"
+msgstr "необроблені опції"
+
+msgid "error preparing revisions"
+msgstr "помилка при підготовці ревізій"
+
+#, c-format
+msgid "commit %s is not marked reachable"
+msgstr "коміт %s не позначений як досяжний"
+
+msgid "too many commits marked reachable"
+msgstr "забагато комітів позначено як досяжні"
+
+msgid "test-tool serve-v2 [<options>]"
+msgstr "test-tool serve-v2 [<опції>]"
+
+msgid "exit immediately after advertising capabilities"
+msgstr "вихід відразу після показу здібностей"
+
+msgid "test-helper simple-ipc is-active    [<name>] [<options>]"
+msgstr "test-helper simple-ipc is-active    [<назва>] [<опції>]"
+
+msgid "test-helper simple-ipc run-daemon   [<name>] [<threads>]"
+msgstr "test-helper simple-ipc run-daemon   [<назва>] [<потоки>]"
+
+msgid "test-helper simple-ipc start-daemon [<name>] [<threads>] [<max-wait>]"
+msgstr ""
+"test-helper simple-ipc start-daemon [<назва>] [<потоки>] [<максимальний час "
+"очікування>]"
+
+msgid "test-helper simple-ipc stop-daemon  [<name>] [<max-wait>]"
+msgstr ""
+"test-helper simple-ipc stop-daemon  [<назва>] [<максимальний час очікування>]"
+
+msgid "test-helper simple-ipc send         [<name>] [<token>]"
+msgstr "test-helper simple-ipc send         [<назва>] [<токен>]"
+
+msgid "test-helper simple-ipc sendbytes    [<name>] [<bytecount>] [<byte>]"
+msgstr ""
+"test-helper simple-ipc sendbytes    [<назва>] [<кількість байт>] [<байт>]"
+
+msgid ""
+"test-helper simple-ipc multiple     [<name>] [<threads>] [<bytecount>] "
+"[<batchsize>]"
+msgstr ""
+"test-helper simple-ipc multiple     [<назва>] [<потоки>] [<кількість байт>] "
+"[<розмір пакетів>]"
+
+msgid "name or pathname of unix domain socket"
+msgstr "назва або назва шляху сокета домену unix"
+
+msgid "named-pipe name"
+msgstr ""
+
+msgid "number of threads in server thread pool"
+msgstr "кількість потоків у пулі потоків сервера"
+
+msgid "seconds to wait for daemon to start or stop"
+msgstr "секунд чекати на запуск або зупинку демона"
+
+msgid "number of bytes"
+msgstr "кількість байтів"
+
+msgid "number of requests per thread"
+msgstr "кількість запитів на потік"
+
+msgid "byte"
+msgstr "байт"
+
+msgid "ballast character"
+msgstr "баластний символ"
+
+msgid "token"
+msgstr "токен"
+
+msgid "command token to send to the server"
+msgstr "токен команди для відправки на сервер"
+
+#, c-format
+msgid "running trailer command '%s' failed"
+msgstr "не вдалося виконати команду трейлера \"%s\""
+
+#, c-format
+msgid "unknown value '%s' for key '%s'"
+msgstr "невідоме значення \"%s\" для ключа \"%s\""
+
+#, c-format
+msgid "empty trailer token in trailer '%.*s'"
+msgstr "порожній токен трейлера в трейлері \"%.*s\""
+
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "не вдалося прочитати вхідний файл \"%s\""
+
+#, c-format
+msgid "could not stat %s"
+msgstr "не вдалося прочитати %s"
+
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "файл %s не є звичайним файлом"
+
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "файл %s не доступний для запису користувачем"
+
+msgid "could not open temporary file"
+msgstr "не вдалося відкрити тимчасовий файл"
+
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "не вдалося перейменувати тимчасовий файл на %s"
+
+msgid "full write to remote helper failed"
+msgstr "не вдалося виконати повний запис до віддаленого помічника"
+
+#, c-format
+msgid "unable to find remote helper for '%s'"
+msgstr "не вдалося знайти віддаленого помічника для \"%s\""
+
+msgid "can't dup helper output fd"
+msgstr "неможливо зробити копію дескриптора файла виводу помічника"
+
+#, c-format
+msgid ""
+"unknown mandatory capability %s; this remote helper probably needs newer "
+"version of Git"
+msgstr ""
+"невідома обовʼязкова здібність %s; цей віддалений помічник напевно потребує "
+"новішої версії Git"
+
+msgid "this remote helper should implement refspec capability"
+msgstr "цей віддалений помічник має реалізовувати здібність refspec"
+
+#, c-format
+msgid "%s unexpectedly said: '%s'"
+msgstr "%s несподівано сказав: \"%s\""
+
+#, c-format
+msgid "%s also locked %s"
+msgstr "%s також заблокувало %s"
+
+msgid "couldn't run fast-import"
+msgstr "не вдалося запустити fast-import"
+
+msgid "error while running fast-import"
+msgstr "помилка під час виконання швидкого імпорту"
+
+#, c-format
+msgid "could not read ref %s"
+msgstr "не вдалося прочитати посилання %s"
+
+#, c-format
+msgid "unknown response to connect: %s"
+msgstr "невідома відповідь на зʼєднання: %s"
+
+msgid "setting remote service path not supported by protocol"
+msgstr "встановлення шляху до віддаленого сервісу не підтримується протоколом"
+
+msgid "invalid remote service path"
+msgstr "неприпустимий шлях до віддаленої служби"
+
+msgid "operation not supported by protocol"
+msgstr "операція не підтримується протоколом"
+
+#, c-format
+msgid "can't connect to subservice %s"
+msgstr "неможливо підключитися до підсервісу %s"
+
+msgid "--negotiate-only requires protocol v2"
+msgstr "--negotiate-only потребує протоколу v2"
+
+msgid "'option' without a matching 'ok/error' directive"
+msgstr "\"option\" без відповідної директиви \"ok/error\""
+
+#, c-format
+msgid "expected ok/error, helper said '%s'"
+msgstr "очікувалося ok/error, помічник сказав \"%s\""
+
+#, c-format
+msgid "helper reported unexpected status of %s"
+msgstr "helper повідомив про неочікуваний статус %s"
+
+#, c-format
+msgid "helper %s does not support dry-run"
+msgstr "помічник %s не підтримує dry-run"
+
+#, c-format
+msgid "helper %s does not support --signed"
+msgstr "помічник %s не підтримує --signed"
+
+#, c-format
+msgid "helper %s does not support --signed=if-asked"
+msgstr "помічник %s не підтримує --signed=if-asked"
+
+#, c-format
+msgid "helper %s does not support --atomic"
+msgstr "помічник %s не підтримує --atomic"
+
+#, c-format
+msgid "helper %s does not support --%s"
+msgstr "помічник %s не підтримує --%s"
+
+#, c-format
+msgid "helper %s does not support 'push-option'"
+msgstr "помічник %s не підтримує \"push-option\""
+
+msgid "remote-helper doesn't support push; refspec needed"
+msgstr "remote-helper не підтримує push; потрібен refspec"
+
+#, c-format
+msgid "helper %s does not support 'force'"
+msgstr "помічник %s не підтримує \"force\""
+
+msgid "couldn't run fast-export"
+msgstr "не вдалося запустити fast-export"
+
+msgid "error while running fast-export"
+msgstr "помилка під час виконання швидкого експорту"
+
+#, c-format
+msgid ""
+"No refs in common and none specified; doing nothing.\n"
+"Perhaps you should specify a branch.\n"
+msgstr ""
+"Немає спільних посилань і жодного не вказано; нічого не робиться.\n"
+"Можливо, вам слід вказати гілку.\n"
+
+#, c-format
+msgid "unsupported object format '%s'"
+msgstr "непідтримуваний обʼєкт формата \"%s\""
+
+#, c-format
+msgid "malformed response in ref list: %s"
+msgstr "неправильно сформована відповідь у списку посилань: %s"
+
+#, c-format
+msgid "read(%s) failed"
+msgstr "read(%s) завершився невдало"
+
+#, c-format
+msgid "write(%s) failed"
+msgstr "write(%s) завершився невдало"
+
+#, c-format
+msgid "%s thread failed"
+msgstr "%s потік завершився невдало"
+
+#, c-format
+msgid "%s thread failed to join: %s"
+msgstr "%s потік не зміг приєднатись: %s"
+
+#, c-format
+msgid "can't start thread for copying data: %s"
+msgstr "неможливо запустити потік для копіювання даних: %s"
+
+#, c-format
+msgid "%s process failed to wait"
+msgstr "%s процес не зміг дочекатися"
+
+#, c-format
+msgid "%s process failed"
+msgstr "%s процес завершився невдало"
+
+msgid "can't start thread for copying data"
+msgstr "неможливо запустити потік для копіювання даних"
+
+#, c-format
+msgid "Would set upstream of '%s' to '%s' of '%s'\n"
+msgstr "Встановить першоджерельне сховище для \"%s\" на \"%s\" в \"%s\"\n"
+
+#, c-format
+msgid "could not read bundle '%s'"
+msgstr "не вдалося прочитати пакет \"%s\""
+
+#, c-format
+msgid "transport: invalid depth option '%s'"
+msgstr "transport: неприпустимий параметр глибини \"%s\""
+
+msgid "see protocol.version in 'git help config' for more details"
+msgstr ""
+"дивіться protocol.version у \"git help config\" для більш детальної "
+"інформації"
+
+msgid "server options require protocol version 2 or later"
+msgstr "опції сервера вимагають протокол версії 2 або пізнішої"
+
+msgid "server does not support wait-for-done"
+msgstr "сервер не підтримує wait-for-done"
+
+msgid "could not parse transport.color.* config"
+msgstr "не вдалося розібрати конфігурацію transport.color.*"
+
+msgid "support for protocol v2 not implemented yet"
+msgstr "підтримка протоколу v2 ще не запроваджена"
+
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "невідоме значення для конфігурації \"%s\": %s"
+
+#, c-format
+msgid "transport '%s' not allowed"
+msgstr "засіб передачі \"%s\" не дозволений"
+
+msgid "git-over-rsync is no longer supported"
+msgstr "git-over-rsync більше не підтримується"
+
+#, c-format
+msgid ""
+"The following submodule paths contain changes that can\n"
+"not be found on any remote:\n"
+msgstr ""
+"Наступні шляхи до підмодулів містять зміни, які неможливо\n"
+"знайти в жодному віддаленому призначенні:\n"
+
+#, c-format
+msgid ""
+"\n"
+"Please try\n"
+"\n"
+"\tgit push --recurse-submodules=on-demand\n"
+"\n"
+"or cd to the path and use\n"
+"\n"
+"\tgit push\n"
+"\n"
+"to push them to a remote.\n"
+"\n"
+msgstr ""
+"\n"
+"Будь ласка, спробуйте\n"
+"\n"
+"\tgit push --recurse-submodules=on-demand\n"
+"\n"
+"або перейдіть до директорії та використайте\n"
+"\n"
+"\tgit push\n"
+"\n"
+"щоб надіслати їх до віддаленого призначення.\n"
+
+msgid "Aborting."
+msgstr "Відміна."
+
+msgid "failed to push all needed submodules"
+msgstr "не вдалося надіслати всі необхідні підмодулі"
+
+msgid "bundle-uri operation not supported by protocol"
+msgstr "bundle-uri операція не підтримується протоколом"
+
+msgid "could not retrieve server-advertised bundle-uri list"
+msgstr "не вдалося отримати список адрес пакетів, оголошений сервером"
+
+msgid "too-short tree object"
+msgstr "занадто короткий обʼєкт дерева"
+
+msgid "malformed mode in tree entry"
+msgstr "невірно визначений режим у записі дерева"
+
+msgid "empty filename in tree entry"
+msgstr "порожня назва файлу у записі дерева"
+
+msgid "too-short tree file"
+msgstr "занадто короткий файл дерева"
+
+#, c-format
+msgid ""
+"Your local changes to the following files would be overwritten by checkout:\n"
+"%%sPlease commit your changes or stash them before you switch branches."
+msgstr ""
+"Ваші локальні зміни в наступних файлах будуть перезаписані при переключенні "
+"стану:\n"
+"%%sБудь ласка, зробіть коміт або додайте їх до схову перед переходом до "
+"іншої гілки."
+
+#, c-format
+msgid ""
+"Your local changes to the following files would be overwritten by checkout:\n"
+"%%s"
+msgstr ""
+"Ваші локальні зміни в наступних файлах будуть перезаписані при переключенні "
+"стану:\n"
+"%%s"
+
+#, c-format
+msgid ""
+"Your local changes to the following files would be overwritten by merge:\n"
+"%%sPlease commit your changes or stash them before you merge."
+msgstr ""
+"Ваші локальні зміни у наступних файлах будуть перезаписані під час злиття:\n"
+"%%sБудь ласка, зробіть коміт або додайте їх до схову перед злиттям."
+
+#, c-format
+msgid ""
+"Your local changes to the following files would be overwritten by merge:\n"
+"%%s"
+msgstr ""
+"Ваші локальні зміни у наступних файлах будуть перезаписані під час злиття:\n"
+"%%s"
+
+#, c-format
+msgid ""
+"Your local changes to the following files would be overwritten by %s:\n"
+"%%sPlease commit your changes or stash them before you %s."
+msgstr ""
+"Ваші локальні зміни у наступних файлах будуть перезаписані %s:\n"
+"%%sБудь ласка, зробіть коміт або додайте їх до схову перед %s."
+
+#, c-format
+msgid ""
+"Your local changes to the following files would be overwritten by %s:\n"
+"%%s"
+msgstr ""
+"Ваші локальні зміни у наступних файлах будуть перезаписані %s:\n"
+"%%s"
+
+#, c-format
+msgid ""
+"Updating the following directories would lose untracked files in them:\n"
+"%s"
+msgstr ""
+"Оновлення наступних директорій призведе до втрати невідстежуваних файлів у "
+"цих директоріях:\n"
+"%s"
+
+#, c-format
+msgid ""
+"Refusing to remove the current working directory:\n"
+"%s"
+msgstr ""
+"Відмова видалення поточної робочої директорії:\n"
+"%s"
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be removed by checkout:\n"
+"%%sPlease move or remove them before you switch branches."
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть видалені під час "
+"переключення:\n"
+"%%sБудь ласка, перемістіть або видаліть їх перед переходом до іншої гілки."
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be removed by checkout:\n"
+"%%s"
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть видалені під час "
+"переключення:\n"
+"%%s"
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be removed by merge:\n"
+"%%sPlease move or remove them before you merge."
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть видалені при виконанні "
+"злиття:\n"
+"%%sБудь ласка, перемістіть або видаліть їх перед злиттям."
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be removed by merge:\n"
+"%%s"
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть видалені при виконанні "
+"злиття:\n"
+"%%s"
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be removed by %s:\n"
+"%%sPlease move or remove them before you %s."
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть видалені при виконанні "
+"%s:\n"
+"%%sБудь ласка, перемістіть або видаліть їх перед %s."
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be removed by %s:\n"
+"%%s"
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть видалені при виконанні "
+"%s:\n"
+"%%s"
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be overwritten by "
+"checkout:\n"
+"%%sPlease move or remove them before you switch branches."
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть перезаписані при "
+"переключенні стану\n"
+"%%sБудь ласка, перемістіть або видаліть їх перед переходом до іншої гілки."
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be overwritten by "
+"checkout:\n"
+"%%s"
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть перезаписані при "
+"переключенні стану:\n"
+"%%s"
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be overwritten by merge:\n"
+"%%sPlease move or remove them before you merge."
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть перезаписані при "
+"злитті:\n"
+"%%sБудь ласка, перемістіть або видаліть їх перед злиттям."
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be overwritten by merge:\n"
+"%%s"
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть перезаписані при "
+"виконанні злиття:\n"
+"%%s"
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be overwritten by %s:\n"
+"%%sPlease move or remove them before you %s."
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть перезаписані %s:\n"
+"%%sБудь ласка, перемістіть або видаліть їх перед %s."
+
+#, c-format
+msgid ""
+"The following untracked working tree files would be overwritten by %s:\n"
+"%%s"
+msgstr ""
+"Наступні невідстежувані файли робочого дерева будуть перезаписані %s:\n"
+"%%s"
+
+#, c-format
+msgid "Entry '%s' overlaps with '%s'.  Cannot bind."
+msgstr "Запис \"%s\" перетинається з \"%s\".  Неможливо звʼязати."
+
+#, c-format
+msgid ""
+"Cannot update submodule:\n"
+"%s"
+msgstr ""
+"Не вдалося оновити підмодуль:\n"
+"%s"
+
+#, c-format
+msgid ""
+"The following paths are not up to date and were left despite sparse "
+"patterns:\n"
+"%s"
+msgstr ""
+"Наступні шляхи не є актуальними і були залишені, незважаючи на часткові "
+"шаблони:\n"
+"%s"
+
+#, c-format
+msgid ""
+"The following paths are unmerged and were left despite sparse patterns:\n"
+"%s"
+msgstr ""
+"Наступні шляхи не злиті і були залишені, незважаючи на часткові шаблони:\n"
+"%s"
+
+#, c-format
+msgid ""
+"The following paths were already present and thus not updated despite sparse "
+"patterns:\n"
+"%s"
+msgstr ""
+"Наступні шляхи вже існували і тому не були оновлені, незважаючи на часткові "
+"шаблони:\n"
+"%s"
+
+#, c-format
+msgid "Aborting\n"
+msgstr "Переривання\n"
+
+#, c-format
+msgid ""
+"After fixing the above paths, you may want to run `git sparse-checkout "
+"reapply`.\n"
+msgstr ""
+"Після виправлення наведених вище шляхів можливо ви забажаєте виконати \"git "
+"sparse-checkout reapply\".\n"
+
+msgid "Updating files"
+msgstr "Оновлення файлів"
+
+msgid ""
+"the following paths have collided (e.g. case-sensitive paths\n"
+"on a case-insensitive filesystem) and only one from the same\n"
+"colliding group is in the working tree:\n"
+msgstr ""
+"зіткнулися наступні шляхи (наприклад, шляхи, чутливі до регістру\n"
+"у файловій системі, не чутливій до регістру) і лише один шлях з тієї \n"
+"групи, що зіткнулися, знаходиться у робочому дереві:\n"
+
+msgid "Updating index flags"
+msgstr "Оновлення прапорців індексу"
+
+#, c-format
+msgid "worktree and untracked commit have duplicate entries: %s"
+msgstr "робоче дерево та невідстежуваний коміт мають дубльовані записи: %s"
+
+msgid "expected flush after fetch arguments"
+msgstr "очікувалось flush після аргументів отримання"
+
+msgid "invalid URL scheme name or missing '://' suffix"
+msgstr "неприпустима назва схеми URL-адреси або відсутній \"://\" суфікс"
+
+#, c-format
+msgid "invalid %XX escape sequence"
+msgstr "неприпустима %XX екрануюча послідовність"
+
+msgid "missing host and scheme is not 'file:'"
+msgstr "відсутній хост і схема не \"file:\""
+
+msgid "a 'file:' URL may not have a port number"
+msgstr "\"file:\" URL-адреса не може мати номера порту"
+
+msgid "invalid characters in host name"
+msgstr "неприпустимі символи в назві хоста"
+
+msgid "invalid port number"
+msgstr "неприпустимий номер порту"
+
+msgid "invalid '..' path segment"
+msgstr "неприпустимий \"..\" сегмент шляху"
+
+msgid "usage: "
+msgstr "використання: "
+
+msgid "fatal: "
+msgstr "збій: "
+
+msgid "error: "
+msgstr "помилка: "
+
+msgid "warning: "
+msgstr "попередження: "
+
+msgid "Fetching objects"
+msgstr "Отримання обʼєктів"
+
+#, c-format
+msgid "'%s' at main working tree is not the repository directory"
+msgstr "\"%s\" у головному робочому дереві не є директорією сховища"
+
+#, c-format
+msgid "'%s' file does not contain absolute path to the working tree location"
+msgstr ""
+"\"%s\" файл не містить абсолютного шляху до розташування робочого дерева"
+
+#, c-format
+msgid "'%s' is not a .git file, error code %d"
+msgstr "\"%s\" не є .git-файлом, код помилки %d"
+
+#, c-format
+msgid "'%s' does not point back to '%s'"
+msgstr "\"%s\" не вказує назад на \"%s\""
+
+msgid "not a directory"
+msgstr "не є директорією"
+
+msgid ".git is not a file"
+msgstr ".git не є файлом"
+
+msgid ".git file broken"
+msgstr ".git файл пошкоджено"
+
+msgid ".git file incorrect"
+msgstr "Неправильний файл .git"
+
+msgid "not a valid path"
+msgstr "неприпустимий шлях"
+
+msgid "unable to locate repository; .git is not a file"
+msgstr "не вдалося знайти сховище; .git не є файлом"
+
+msgid "unable to locate repository; .git file does not reference a repository"
+msgstr "не вдалося знайти сховище; .git-файл не посилається на сховище"
+
+msgid "unable to locate repository; .git file broken"
+msgstr "не вдалося знайти сховище; файл .git пошкоджено"
+
+msgid "gitdir unreadable"
+msgstr "git-директорія нечитабельна"
+
+msgid "gitdir incorrect"
+msgstr "git-директорія неправильна"
+
+msgid "not a valid directory"
+msgstr "неприпустима директорія"
+
+msgid "gitdir file does not exist"
+msgstr "файл git директорії не існує"
+
+#, c-format
+msgid "unable to read gitdir file (%s)"
+msgstr "не вдалося прочитати файл git директорії (%s)"
+
+#, c-format
+msgid "short read (expected %<PRIuMAX> bytes, read %<PRIuMAX>)"
+msgstr ""
+"помилка при зчитуванні (очікувалось %<PRIuMAX> байтів, прочитано %<PRIuMAX>)"
+
+msgid "invalid gitdir file"
+msgstr "неприпустимий файл git-директорії"
+
+msgid "gitdir file points to non-existent location"
+msgstr "файл git-директорії вказує на неіснуюче розташування"
+
+#, c-format
+msgid "unable to set %s in '%s'"
+msgstr "не вдалося задати %s в \"%s\""
+
+#, c-format
+msgid "unable to unset %s in '%s'"
+msgstr "не вдалося скинути %s в \"%s\""
+
+msgid "failed to set extensions.worktreeConfig setting"
+msgstr "не вдалося встановити extensions.worktreeConfig параметр"
+
+#, c-format
+msgid "could not setenv '%s'"
+msgstr "не вдалося встановити оточення \"%s\""
+
+#, c-format
+msgid "unable to create '%s'"
+msgstr "не вдалося створити \"%s\""
+
+#, c-format
+msgid "could not open '%s' for reading and writing"
+msgstr "не вдалося відкрити \"%s\" для читання та запису"
+
+#, c-format
+msgid "unable to access '%s'"
+msgstr "не вдалося отримати доступ до \"%s\""
+
+msgid "unable to get current working directory"
+msgstr "не вдалося завантажити поточну робочу директорію"
+
+msgid "Unmerged paths:"
+msgstr "Не злиті шляхи:"
+
+msgid "  (use \"git restore --staged <file>...\" to unstage)"
+msgstr ""
+"  (використовуйте \"git restore --staged <файл>...\", щоб вилучити з індексу)"
+
+#, c-format
+msgid "  (use \"git restore --source=%s --staged <file>...\" to unstage)"
+msgstr ""
+"  (використовуйте \"git restore --source=%s --staged <file>...\", щоб "
+"видалити з індексу)"
+
+msgid "  (use \"git rm --cached <file>...\" to unstage)"
+msgstr ""
+"  (використовуйте \"git rm --cached <file>...\", щоб вилучити з індексу)"
+
+msgid "  (use \"git add <file>...\" to mark resolution)"
+msgstr "  (використовуйте \"git add <файл>...\", щоб позначити як вирішене)"
+
+msgid "  (use \"git add/rm <file>...\" as appropriate to mark resolution)"
+msgstr ""
+"  (використовуйте \"git add/rm <файл>...\" за потребою, щоб позначити як "
+"вирішене)"
+
+msgid "  (use \"git rm <file>...\" to mark resolution)"
+msgstr "  (використовуйте \"git rm <файл>...\", щоб позначити як вирішене)"
+
+msgid "Changes to be committed:"
+msgstr "Зміни, що будуть додані до коміту:"
+
+msgid "Changes not staged for commit:"
+msgstr "Зміни, що не будуть додані до коміту:"
+
+msgid "  (use \"git add <file>...\" to update what will be committed)"
+msgstr ""
+"  (використовуйте \"git add <файл>...\", для оновлення того, що буде "
+"закомічено)"
+
+msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
+msgstr ""
+"  (використовуйте \"git add/rm <файл>...\" для оновлення того, що буде "
+"закомічено)"
+
+msgid ""
+"  (use \"git restore <file>...\" to discard changes in working directory)"
+msgstr ""
+"  (використовуйте \"git restore <файл>...\", щоб скасувати зміни в робочій "
+"директорії)"
+
+msgid "  (commit or discard the untracked or modified content in submodules)"
+msgstr ""
+"  (зробіть коміт або скасуйте невідстежуваний або змінений контент у "
+"підмодулях)"
+
+#, c-format
+msgid "  (use \"git %s <file>...\" to include in what will be committed)"
+msgstr ""
+"  (використовуйте \"git %s <файл>...\" для включення до того, що буде "
+"закомічено)"
+
+msgid "both deleted:"
+msgstr "видалено обома:"
+
+msgid "added by us:"
+msgstr "додано нами:"
+
+msgid "deleted by them:"
+msgstr "видалено ними:"
+
+msgid "added by them:"
+msgstr "додано ними:"
+
+msgid "deleted by us:"
+msgstr "видалено нами:"
+
+msgid "both added:"
+msgstr "додано обома:"
+
+msgid "both modified:"
+msgstr "змінено обома:"
+
+msgid "new file:"
+msgstr "новий файл:"
+
+msgid "copied:"
+msgstr "скопійовано:"
+
+msgid "deleted:"
+msgstr "видалено:"
+
+msgid "modified:"
+msgstr "змінено:"
+
+msgid "renamed:"
+msgstr "перейменовано:"
+
+msgid "typechange:"
+msgstr "змінено тип:"
+
+msgid "unknown:"
+msgstr "невідомо:"
+
+msgid "unmerged:"
+msgstr "не злито:"
+
+msgid "new commits, "
+msgstr "нові коміти, "
+
+msgid "modified content, "
+msgstr "змінений контент, "
+
+msgid "untracked content, "
+msgstr "невідстежуваний контент, "
+
+#, c-format
+msgid "Your stash currently has %d entry"
+msgid_plural "Your stash currently has %d entries"
+msgstr[0] "У вашій схованці наразі є %d запис"
+msgstr[1] "У вашій схованці наразі є %d записи"
+msgstr[2] "У вашій схованці наразі є %d записів"
+
+msgid "Submodules changed but not updated:"
+msgstr "Підмодулі змінено, але не оновлено:"
+
+msgid "Submodule changes to be committed:"
+msgstr "Зміни в підмодулі, які будуть закомічені:"
+
+msgid ""
+"Do not modify or remove the line above.\n"
+"Everything below it will be ignored."
+msgstr ""
+"Не змінюйте та не видаляйте рядок вище.\n"
+"Все, що нижче, буде проігноровано."
+
+#, c-format
+msgid ""
+"\n"
+"It took %.2f seconds to compute the branch ahead/behind values.\n"
+"You can use '--no-ahead-behind' to avoid this.\n"
+msgstr ""
+"\n"
+"Обчислення значень попереду/позаду для гілки зайняло %.2f секунд.\n"
+"Ви можете використати параметр '--no-ahead-behind', щоб уникнути цього.\n"
+
+msgid "You have unmerged paths."
+msgstr "У вас є не злиті шляхи."
+
+msgid "  (fix conflicts and run \"git commit\")"
+msgstr "  (виправте конфлікти та виконайте \"git commit\")"
+
+msgid "  (use \"git merge --abort\" to abort the merge)"
+msgstr ""
+"  (використовуйте команду \"git merge --abort\", щоб перервати злиття)."
+
+msgid "All conflicts fixed but you are still merging."
+msgstr "Усі конфлікти виправлено, але ви все ще продовжуєте злиття."
+
+msgid "  (use \"git commit\" to conclude merge)"
+msgstr "  (використовуйте \"git commit\" для завершення злиття)"
+
+msgid "You are in the middle of an am session."
+msgstr "Ви всередині am сеансу."
+
+msgid "The current patch is empty."
+msgstr "Поточна латка порожня."
+
+msgid "  (fix conflicts and then run \"git am --continue\")"
+msgstr "  (виправте конфлікти, а потім виконайте \"git am --continue\")"
+
+msgid "  (use \"git am --skip\" to skip this patch)"
+msgstr "  (використовуйте команду \"git am --skip\", щоб пропустити цю латку)"
+
+msgid ""
+"  (use \"git am --allow-empty\" to record this patch as an empty commit)"
+msgstr ""
+"  (використовуйте \"git am --allow-empty\", щоб записати цю латку як "
+"порожній коміт)"
+
+msgid "  (use \"git am --abort\" to restore the original branch)"
+msgstr "  (використовуйте \"git am --abort\", щоб відновити початкову гілку)"
+
+msgid "git-rebase-todo is missing."
+msgstr "git-rebase-todo відсутній."
+
+msgid "No commands done."
+msgstr "Не виконано жодної команди."
+
+#, c-format
+msgid "Last command done (%<PRIuMAX> command done):"
+msgid_plural "Last commands done (%<PRIuMAX> commands done):"
+msgstr[0] "Останню команду виконано (%<PRIuMAX> команду виконано):"
+msgstr[1] "Останні команди виконано (%<PRIuMAX> команди виконано):"
+msgstr[2] "Останніх команд виконано (%<PRIuMAX> команд виконано):"
+
+#, c-format
+msgid "  (see more in file %s)"
+msgstr "  (дивіться більше у файлі %s)"
+
+msgid "No commands remaining."
+msgstr "Не залишилось команд."
+
+#, c-format
+msgid "Next command to do (%<PRIuMAX> remaining command):"
+msgid_plural "Next commands to do (%<PRIuMAX> remaining commands):"
+msgstr[0] "Наступна команда для виконання (залишилась %<PRIuMAX> команда):"
+msgstr[1] "Наступні команди для виконання (залишилось %<PRIuMAX> команди):"
+msgstr[2] "Наступні команди для виконання (залишилось %<PRIuMAX> команд):"
+
+msgid "  (use \"git rebase --edit-todo\" to view and edit)"
+msgstr ""
+"  (використовуйте \"git rebase --edit-todo\" для перегляду та редагування)"
+
+#, c-format
+msgid "You are currently rebasing branch '%s' on '%s'."
+msgstr "Наразі ви перебазовуєте гілку '%s' на '%s'."
+
+msgid "You are currently rebasing."
+msgstr "Наразі йде перебазування."
+
+msgid "  (fix conflicts and then run \"git rebase --continue\")"
+msgstr "  (виправте конфлікти, а потім виконайте \"git rebase --continue\")"
+
+msgid "  (use \"git rebase --skip\" to skip this patch)"
+msgstr "  (використовуйте \"git rebase --skip\", щоб пропустити цю латку)"
+
+msgid "  (use \"git rebase --abort\" to check out the original branch)"
+msgstr ""
+"  (використовуйте \"git rebase --abort\", щоб перейти до початкової гілки)"
+
+msgid "  (all conflicts fixed: run \"git rebase --continue\")"
+msgstr "  (усі конфлікти виправлено: виконайте \"git rebase --continue\")"
+
+#, c-format
+msgid ""
+"You are currently splitting a commit while rebasing branch '%s' on '%s'."
+msgstr ""
+"Наразі виконується розділення коміту під час перебазування гілки \"%s\" на "
+"\"%s\"."
+
+msgid "You are currently splitting a commit during a rebase."
+msgstr "Ви розбиваєте коміт під час перебазування."
+
+msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
+msgstr ""
+"  (Після очищення робочої директорії виконайте \"git rebase --continue\")"
+
+#, c-format
+msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
+msgstr "Ви редагуєте комміт під час перебазування гілки '%s' на '%s'."
+
+msgid "You are currently editing a commit during a rebase."
+msgstr "Ви редагуєте коміт під час перебазування."
+
+msgid "  (use \"git commit --amend\" to amend the current commit)"
+msgstr ""
+"  (використовуйте \"git commit --amend\" для внесення змін до поточного "
+"коміту)"
+
+msgid ""
+"  (use \"git rebase --continue\" once you are satisfied with your changes)"
+msgstr ""
+"  (скористайтесь командою \"git rebase --continue\", коли ви будете "
+"задоволені своїми змінами)"
+
+msgid "Cherry-pick currently in progress."
+msgstr "Наразі триває висмикування."
+
+#, c-format
+msgid "You are currently cherry-picking commit %s."
+msgstr "Наразі ви висмикуєте коміт %s."
+
+msgid "  (fix conflicts and run \"git cherry-pick --continue\")"
+msgstr "  (виправте конфлікти і виконайте \"git cherry-pick --continue\")"
+
+msgid "  (run \"git cherry-pick --continue\" to continue)"
+msgstr "  (виконайте \"git cherry-pick --continue\", щоб продовжити)"
+
+msgid "  (all conflicts fixed: run \"git cherry-pick --continue\")"
+msgstr "  (усі конфлікти виправлено: виконайте \"git cherry-pick --continue\")"
+
+msgid "  (use \"git cherry-pick --skip\" to skip this patch)"
+msgstr ""
+"  (скористайтесь командою \"git cherry-pick --skip\", щоб пропустити цю "
+"латку)"
+
+msgid "  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
+msgstr ""
+" (скористайтесь командою \"git cherry-pick --abort\", щоб скасувати операцію "
+"висмикування)"
+
+msgid "Revert currently in progress."
+msgstr "Наразі виконується операція вивертання."
+
+#, c-format
+msgid "You are currently reverting commit %s."
+msgstr "Наразі ви вивертаєте коміт %s."
+
+msgid "  (fix conflicts and run \"git revert --continue\")"
+msgstr "  (виправте конфлікти і виконайте \"git revert --continue\")"
+
+msgid "  (run \"git revert --continue\" to continue)"
+msgstr "  (виконайте \"git revert --continue\", щоб продовжити)"
+
+msgid "  (all conflicts fixed: run \"git revert --continue\")"
+msgstr "  (усі конфлікти виправлено: виконайте \"git revert --continue\")"
+
+msgid "  (use \"git revert --skip\" to skip this patch)"
+msgstr "  (використовуйте \"git revert --skip\", щоб пропустити цю латку)"
+
+msgid "  (use \"git revert --abort\" to cancel the revert operation)"
+msgstr ""
+"  (використовуйте \"git revert --abort\", щоб скасувати операцію повернення)"
+
+#, c-format
+msgid "You are currently bisecting, started from branch '%s'."
+msgstr "Наразі ви робите бісекцію, починаючи з гілки '%s'."
+
+msgid "You are currently bisecting."
+msgstr "Наразі ви робите бісекцію."
+
+msgid "  (use \"git bisect reset\" to get back to the original branch)"
+msgstr ""
+"  (використовуйте \"git bisect reset\", щоб повернутись до початкової гілки)"
+
+msgid "You are in a sparse checkout."
+msgstr "Ви перебуваєте в частковому переході до гілки."
+
+#, c-format
+msgid "You are in a sparse checkout with %d%% of tracked files present."
+msgstr ""
+"Ви перебуваєте в частковому переході до гілки з %d%% відстежуваних файлів."
+
+msgid "On branch "
+msgstr "На гілці "
+
+msgid "interactive rebase in progress; onto "
+msgstr "інтерактивне перебазовування в процесі; на "
+
+msgid "rebase in progress; onto "
+msgstr "перебазовування в процесі; на "
+
+msgid "HEAD detached at "
+msgstr "HEAD відʼєднано на "
+
+msgid "HEAD detached from "
+msgstr "HEAD відʼєднано від "
+
+msgid "Not currently on any branch."
+msgstr "Наразі не знаходитесь в жодній гілці."
+
+msgid "Initial commit"
+msgstr "Початковий коміт"
+
+msgid "No commits yet"
+msgstr "Поки що немає комітів"
+
+msgid "Untracked files"
+msgstr "Невідстежувані файли"
+
+msgid "Ignored files"
+msgstr "Ігноровані файли"
+
+#, c-format
+msgid ""
+"It took %.2f seconds to enumerate untracked files,\n"
+"but the results were cached, and subsequent runs may be faster."
+msgstr ""
+"На перерахування невідстежуваних файлів пішло %.2f секунд,\n"
+"але результат було додано у кеш, тому наступні запуски можуть бути швидшими."
+
+#, c-format
+msgid "It took %.2f seconds to enumerate untracked files."
+msgstr "На перерахування невідстежуваних файлів пішло %.2f секунд."
+
+msgid "See 'git help status' for information on how to improve this."
+msgstr "Дивіться 'git help status' для інформаціі з того, як це покращити."
+
+#, c-format
+msgid "Untracked files not listed%s"
+msgstr "Невідстежувані файли не вказано%s"
+
+msgid " (use -u option to show untracked files)"
+msgstr " (використовуйте опцію -u для відображення невідстежуваних файлів)"
+
+msgid "No changes"
+msgstr "Немає змін"
+
+#, c-format
+msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
+msgstr ""
+"не додано жодних змін до коміту (використовуйте \"git add\" та/або \"git "
+"commit -a\")\n"
+
+#, c-format
+msgid "no changes added to commit\n"
+msgstr "нічого не додано до коміту\n"
+
+#, c-format
+msgid ""
+"nothing added to commit but untracked files present (use \"git add\" to "
+"track)\n"
+msgstr ""
+"нічого не додано до коміту, але присутні невідстежувані файли (скористайтесь "
+"\"git add\" щоб почати відстежувати)\n"
+
+#, c-format
+msgid "nothing added to commit but untracked files present\n"
+msgstr "нічого не додано до коміту, але присутні невідстежувані файли\n"
+
+#, c-format
+msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
+msgstr ""
+"нічого комітити (створіть/скопіюйте файли та скористайтесь \"git add\" для "
+"відстежування)\n"
+
+#, c-format
+msgid "nothing to commit\n"
+msgstr "нічого комітити\n"
+
+#, c-format
+msgid "nothing to commit (use -u to show untracked files)\n"
+msgstr ""
+"нічого комітити (скористайтесь -u щоб подивитись невідстежувані файли)\n"
+
+#, c-format
+msgid "nothing to commit, working tree clean\n"
+msgstr "нічого комітити, робоче дерево чисте\n"
+
+msgid "No commits yet on "
+msgstr "Наразі немає комітів на "
+
+msgid "HEAD (no branch)"
+msgstr "HEAD (немає гілки)"
+
+msgid "different"
+msgstr "різниться"
+
+msgid "behind "
+msgstr "позаду "
+
+msgid "ahead "
+msgstr "попереду "
+
+#. TRANSLATORS: the action is e.g. "pull with rebase"
+
+#, c-format
+msgid "cannot %s: You have unstaged changes."
+msgstr "не можливо %s: У вас є не індексовані зміни."
+
+msgid "additionally, your index contains uncommitted changes."
+msgstr "крім того, ваш індекс містить не закомічені зміни."
+
+#, c-format
+msgid "cannot %s: Your index contains uncommitted changes."
+msgstr "не можливо %s: Ваш індекс містить не закомічені зміни."
+
+msgid ""
+"Error: Your local changes to the following files would be overwritten by "
+"merge"
+msgstr ""
+"Помилка: Ваші локальні зміни в наступних файлах буде перезаписано під час "
+"злиття"
+
+msgid "Automated merge did not work."
+msgstr "Автоматичне злиття не спрацювало."
+
+msgid "Should not be doing an octopus."
+msgstr "Не варто робити octopus злиття."
+
+#, sh-format
+msgid "Unable to find common commit with $pretty_name"
+msgstr "Не вдалося знайти спільний коміт з $pretty_name"
+
+#, sh-format
+msgid "Already up to date with $pretty_name"
+msgstr "Вже в актуальному стані з $pretty_name"
+
+#, sh-format
+msgid "Fast-forwarding to: $pretty_name"
+msgstr "Перемотування вперед до: $pretty_name"
+
+#, sh-format
+msgid "Trying simple merge with $pretty_name"
+msgstr "Спроба простого злиття з $pretty_name"
+
+msgid "Simple merge did not work, trying automatic merge."
+msgstr "Просте злиття не спрацювало, спроба автоматичного злиття."
+
+#, sh-format
+msgid "usage: $dashless $USAGE"
+msgstr "використання: $dashless $USAGE"
+
+#, sh-format
+msgid "Cannot chdir to $cdup, the toplevel of the working tree"
+msgstr "Неможливо chdir до $cdup, верхнього рівня робочого дерева"
+
+#, sh-format
+msgid "fatal: $program_name cannot be used without a working tree."
+msgstr "збій: $program_name неможливо використовувати без робочого дерева."
+
+msgid "Cannot rewrite branches: You have unstaged changes."
+msgstr "Неможливо переписати гілку: у вас є неіндексовані зміни."
+
+#, sh-format
+msgid "Cannot $action: You have unstaged changes."
+msgstr "Неможливо $action: у вас є неіндексовані зміни."
+
+#, sh-format
+msgid "Cannot $action: Your index contains uncommitted changes."
+msgstr "Неможливо $action: ваш індекс містить незакомічені зміни."
+
+msgid "Additionally, your index contains uncommitted changes."
+msgstr "Крім того, ваш індекс містить незакомічені зміни."
+
+msgid "You need to run this command from the toplevel of the working tree."
+msgstr "Цю команду потрібно запускати з верхнього рівня робочого дерева."
+
+msgid "Unable to determine absolute path of git directory"
+msgstr "Не вдалося визначити абсолютний шлях git директорії"
+
+msgid "local zone differs from GMT by a non-minute interval\n"
+msgstr "місцева зона відрізняється від GMT на нехвилинний інтервал\n"
+
+msgid "local time offset greater than or equal to 24 hours\n"
+msgstr "зміщення місцевого часу більше або дорівнює 24 годинам\n"
+
+#, perl-format
+msgid "fatal: command '%s' died with exit code %d"
+msgstr "збій: команда \"%s\" завершилася невдало з кодом виходу %d"
+
+msgid "the editor exited uncleanly, aborting everything"
+msgstr "редактор вийшов неналежним чином, перервано всі процеси"
+
+#, perl-format
+msgid ""
+"'%s' contains an intermediate version of the email you were composing.\n"
+msgstr "\"%s\" містить проміжну версію листа, який ви створювали.\n"
+
+#, perl-format
+msgid "'%s.final' contains the composed email.\n"
+msgstr "\"%s.final\" містить створений лист.\n"
+
+msgid "--dump-aliases incompatible with other options\n"
+msgstr "--dump-aliases несумісна з іншими опціями\n"
+
+msgid ""
+"fatal: found configuration options for 'sendmail'\n"
+"git-send-email is configured with the sendemail.* options - note the 'e'.\n"
+"Set sendemail.forbidSendmailVariables to false to disable this check.\n"
+msgstr ""
+"збій: знайдено опції конфігурації для \"sendmail\"\n"
+"git-send-email налаштовано з параметрами sendemail.* options - зверніть "
+"увагу на \"e\".\n"
+"Встановіть sendemail.forbidSendmailVariables у false, щоб вимкнути цю "
+"перевірку.\n"
+
+msgid "Cannot run git format-patch from outside a repository\n"
+msgstr "Неможливо запустити git format-patch за межами сховища\n"
+
+msgid ""
+"`batch-size` and `relogin` must be specified together (via command-line or "
+"configuration option)\n"
+msgstr ""
+"\"batch-size\" і \"relogin\" повинні бути вказані разом (через командний "
+"рядок або опції конфігурації)\n"
+
+#, perl-format
+msgid "Unknown --suppress-cc field: '%s'\n"
+msgstr "Невідоме --suppress-cc поле: \"%s\"\n"
+
+#, perl-format
+msgid "Unknown --confirm setting: '%s'\n"
+msgstr "Невідомий --confirm параметр: \"%s\"\n"
+
+#, perl-format
+msgid "warning: sendmail alias with quotes is not supported: %s\n"
+msgstr "попередження: sendmail аліас у лапках не підтримується: %s\n"
+
+#, perl-format
+msgid "warning: `:include:` not supported: %s\n"
+msgstr "попередження: \":include:\" не підтримується: %s\n"
+
+#, perl-format
+msgid "warning: `/file` or `|pipe` redirection not supported: %s\n"
+msgstr ""
+"попередження: \"/file\" або \"|pipe\" перенаправлення не підтримуються: %s\n"
+
+#, perl-format
+msgid "warning: sendmail line is not recognized: %s\n"
+msgstr "попередження: рядок sendmail не розпізнано: %s\n"
+
+#, perl-format
+msgid ""
+"File '%s' exists but it could also be the range of commits\n"
+"to produce patches for.  Please disambiguate by...\n"
+"\n"
+"    * Saying \"./%s\" if you mean a file; or\n"
+"    * Giving --format-patch option if you mean a range.\n"
+msgstr ""
+"Файл \"%s\" існує, але це також може бути діапазон комітів\n"
+"для яких випускаються латки.  Будь ласка, розтлумачте...\n"
+"\n"
+"    * Вказавши \"./%s\", якщо на увазі мається файл або\n"
+"    * Додавши --format-patch, якщо на увазі мається діапазон.\n"
+
+#, perl-format
+msgid "Failed to opendir %s: %s"
+msgstr "Не вдалося відкрити директорію %s: %s"
+
+msgid ""
+"\n"
+"No patch files specified!\n"
+"\n"
+msgstr ""
+"\n"
+"Файли латок не вказано!\n"
+"\n"
+
+#, perl-format
+msgid "No subject line in %s?"
+msgstr "Немає рядка теми в %s?"
+
+#, perl-format
+msgid "Failed to open for writing %s: %s"
+msgstr "Не вдалося відкрити для запису %s: %s"
+
+msgid ""
+"Lines beginning in \"GIT:\" will be removed.\n"
+"Consider including an overall diffstat or table of contents\n"
+"for the patch you are writing.\n"
+"\n"
+"Clear the body content if you don't wish to send a summary.\n"
+msgstr ""
+"Рядки, що починаються з \"GIT:\", будуть вилучені.\n"
+"Подумайте про те, щоб додати загальний diffstat або зміст\n"
+"для латки, яку ви пишете.\n"
+"\n"
+"Очистіть вміст тіла, якщо ви не бажаєте надсилати підсумок.\n"
+
+#, perl-format
+msgid "Failed to open %s: %s"
+msgstr "Не вдалося відкрити %s: %s"
+
+#, perl-format
+msgid "Failed to open %s.final: %s"
+msgstr "Не вдалося відкрити %s.final: %s"
+
+msgid "Summary email is empty, skipping it\n"
+msgstr "Підсумковий лист порожній, перескочено\n"
+
+#. TRANSLATORS: please keep [y/N] as is.
+
+#, perl-format
+msgid "Are you sure you want to use <%s> [y/N]? "
+msgstr "Ви впевнені, що хочете використати <%s> [y/N]? "
+
+msgid ""
+"The following files are 8bit, but do not declare a Content-Transfer-"
+"Encoding.\n"
+msgstr ""
+
+msgid "Which 8bit encoding should I declare [UTF-8]? "
+msgstr "Яке 8-бітне кодування слід оголосити [UTF-8]? "
+
+#, perl-format
+msgid ""
+"Refusing to send because the patch\n"
+"\t%s\n"
+"has the template subject '*** SUBJECT HERE ***'. Pass --force if you really "
+"want to send.\n"
+msgstr ""
+"Відмова у надсиланні, тому що латка\n"
+"\t%s\n"
+"має шаблонну тему \"*** SUBJECT HERE ***\". Додайте --force, якщо ви дійсно "
+"хочете відправити.\n"
+
+msgid "To whom should the emails be sent (if anyone)?"
+msgstr "Кому слід надсилати електронні листи (якщо комусь)?"
+
+#, perl-format
+msgid "fatal: alias '%s' expands to itself\n"
+msgstr "збій: аліас \"%s\" розгортається на самого себе\n"
+
+msgid "Message-ID to be used as In-Reply-To for the first email (if any)? "
+msgstr ""
+
+#, perl-format
+msgid "error: unable to extract a valid address from: %s\n"
+msgstr "помилка: не вдалося витягти дійсну адресу з: %s\n"
+
+#. TRANSLATORS: Make sure to include [q] [d] [e] in your
+#. translation. The program will only accept English input
+#. at this point.
+
+msgid "What to do with this address? ([q]uit|[d]rop|[e]dit): "
+msgstr "Що робити з цією адресою? ([q]uit|[d]rop|[e]dit): "
+
+#, perl-format
+msgid "CA path \"%s\" does not exist"
+msgstr "Шлях до ЦВС \"%s\" не існує"
+
+msgid ""
+"    The Cc list above has been expanded by additional\n"
+"    addresses found in the patch commit message. By default\n"
+"    send-email prompts before sending whenever this occurs.\n"
+"    This behavior is controlled by the sendemail.confirm\n"
+"    configuration setting.\n"
+"\n"
+"    For additional information, run 'git send-email --help'.\n"
+"    To retain the current behavior, but squelch this message,\n"
+"    run 'git config --global sendemail.confirm auto'.\n"
+"\n"
+msgstr ""
+"    Наведений вище список копій було розширено додатковими\n"
+"    адресами, знайденими у повідомленні коміта латки. Зазвичай\n"
+"    send-email запитує перед надсиланням, коли це трапляється.\n"
+"    Цю поведінку можна контролювати за допомогою параметра sendemail."
+"confirm\n"
+"    налаштування конфігурації.\n"
+"\n"
+"    Для отримання додаткової інформації виконайте команду \"git send-email --"
+"help\".\n"
+"Для утримання поточної поведінки, але без цього повідомлення,\n"
+"    виконайте \"git config --global sendemail.confirm auto\".\n"
+
+#. TRANSLATORS: Make sure to include [y] [n] [e] [q] [a] in your
+#. translation. The program will only accept English input
+#. at this point.
+
+msgid "Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): "
+msgstr "Надіслати цей лист? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): "
+
+msgid "Send this email reply required"
+msgstr ""
+
+msgid "The required SMTP server is not properly defined."
+msgstr "Потрібний SMTP-сервер не визначено належним чином."
+
+#, perl-format
+msgid "Server does not support STARTTLS! %s"
+msgstr "Сервер не підтримує STARTTLS! %s"
+
+#, perl-format
+msgid "STARTTLS failed! %s"
+msgstr ""
+
+msgid "Unable to initialize SMTP properly. Check config and use --smtp-debug."
+msgstr ""
+"Не вдалося правильно ініціалізувати SMTP. Перевірте конфігурацію і "
+"скористайтеся --smtp-debug."
+
+#, perl-format
+msgid "Failed to send %s\n"
+msgstr "Не вдалося надіслати %s\n"
+
+#, perl-format
+msgid "Dry-Sent %s\n"
+msgstr "Пробно відправлено %s\n"
+
+#, perl-format
+msgid "Sent %s\n"
+msgstr "Відправлено %s\n"
+
+msgid "Dry-OK. Log says:\n"
+msgstr ""
+
+msgid "OK. Log says:\n"
+msgstr "ОК. Лог каже:\n"
+
+msgid "Result: "
+msgstr "Результат: "
+
+msgid "Result: OK\n"
+msgstr "Результат: OK\n"
+
+#, perl-format
+msgid "can't open file %s"
+msgstr "неможливо відкрити файл %s"
+
+#, perl-format
+msgid "(mbox) Adding cc: %s from line '%s'\n"
+msgstr "(mbox) Додавання cc: %s з рядка \"%s\"\n"
+
+#, perl-format
+msgid "(mbox) Adding to: %s from line '%s'\n"
+msgstr "(mbox) Додавання до: %s з рядка \"%s\"\n"
+
+#, perl-format
+msgid "(non-mbox) Adding cc: %s from line '%s'\n"
+msgstr "(non-mbox) Додавання cc: %s з рядка \"%s\"\n"
+
+#, perl-format
+msgid "(body) Adding cc: %s from line '%s'\n"
+msgstr "(тіло) Додавання cc: %s з рядка \"%s\"\n"
+
+#, perl-format
+msgid "(%s) Could not execute '%s'"
+msgstr "(%s) Не вдалося виконати \"%s\""
+
+#, perl-format
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) Невірно сформований рядок виводу з \"%s\"."
+
+#, perl-format
+msgid "(%s) failed to close pipe to '%s'"
+msgstr "(%s) не вдалося закрити канал до \"%s\""
+
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) Додавання %s: %s з: \"%s\"\n"
+
+msgid "cannot send message as 7bit"
+msgstr "неможливо надіслати повідомлення як 7bit"
+
+msgid "invalid transfer encoding"
+msgstr "неприпустиме кодування передачі"
+
+#, perl-format
+msgid ""
+"fatal: %s: rejected by %s hook\n"
+"%s\n"
+"warning: no patches were sent\n"
+msgstr ""
+"збій: %s: відхилено %s хуком\n"
+"%s\n"
+"попередження: не було надіслано жодних латок\n"
+
+#, perl-format
+msgid "unable to open %s: %s\n"
+msgstr "не вдалося відкрити %s: %s\n"
+
+#, perl-format
+msgid ""
+"fatal: %s:%d is longer than 998 characters\n"
+"warning: no patches were sent\n"
+msgstr ""
+"збій: %s:%d довше ніж 998 символів\n"
+"попередження: не було надіслано жодних латок\n"
+
+#, perl-format
+msgid "Skipping %s with backup suffix '%s'.\n"
+msgstr "Пропуск %s з резервним суфіксом \"%s\".\n"
+
+#. TRANSLATORS: please keep "[y|N]" as is.
+
+#, perl-format
+msgid "Do you really want to send %s? [y|N]: "
+msgstr "Ви дійсно хочете відправити %s? [y|N]: "
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 2b88f9b..aa25e9a 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -22,11 +22,13 @@
 #   3-way merge                      |  三方合并
 #   abbreviate                       |  简写(的 SHA-1 值)
 #   alternate object database        |  备用对象库
+#   attribute source                 |  属性来源
 #   amend                            |  修补
 #   ancestor                         |  祖先,祖先提交
 #   annotated tag                    |  附注标签
 #   bare repository                  |  纯仓库
 #   bisect                           |  二分查找
+#   bitmap                           |  位图
 #   blob object                      |  数据对象
 #   bloom filter                     |  布隆过滤器
 #   branch                           |  分支
@@ -102,6 +104,7 @@
 #   rebase                           |  变基
 #   ref                              |  引用
 #   reflog                           |  引用日志
+#   refmap                           |  引用映射
 #   refspec                          |  引用规格
 #   remote                           |  远程,远程仓库
 #   remote-tracking branch           |  远程跟踪分支
@@ -145,10 +148,10 @@
 msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-03-07 23:37+0000\n"
-"PO-Revision-Date: 2023-03-07 23:40+0000\n"
-"Last-Translator: Fangyi Zhou <me@fangyi.io>\n"
-"Language-Team: GitHub <https://github.com/fangyi-zhou/git-po/>\n"
+"POT-Creation-Date: 2023-05-20 12:27+0800\n"
+"PO-Revision-Date: 2023-05-20 12:38+0800\n"
+"Last-Translator: Teng Long <dyroneteng@gmail.com>\n"
+"Language-Team: GitHub <https://github.com/dyrone/git/>\n"
 "Language: zh_CN\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -917,6 +920,24 @@
 msgstr "因为存在未完成的合并而退出。"
 
 #: advice.c
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"无法在偏离的分支上进行快进操作,您需要:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"或者:\n"
+"\n"
+"\tgit rebase\n"
+
+#: advice.c
 msgid "Not possible to fast-forward, aborting."
 msgstr "无法快进,终止。"
 
@@ -1444,6 +1465,11 @@
 msgid "cannot open %s"
 msgstr "不能打开 %s"
 
+#: apply.c rerere.c
+#, c-format
+msgid "cannot unlink '%s'"
+msgstr "不能删除 '%s'"
+
 #: apply.c
 #, c-format
 msgid "Hunk #%d applied cleanly."
@@ -1681,6 +1707,11 @@
 msgid "cannot read '%s'"
 msgstr "不能读取 '%s'"
 
+#: archive.c
+#, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr "路径规格 '%s' 匹配了当前目录外的文件'"
+
 #: archive.c builtin/add.c builtin/rm.c
 #, c-format
 msgid "pathspec '%s' did not match any files"
@@ -1702,10 +1733,6 @@
 msgstr "不是一个树对象:%s"
 
 #: archive.c
-msgid "current working directory is untracked"
-msgstr "当前工作目录未被跟踪"
-
-#: archive.c
 #, c-format
 msgid "File not found: %s"
 msgstr "文件未找到:%s"
@@ -1873,6 +1900,10 @@
 msgid "ignoring overly large gitattributes blob '%s'"
 msgstr "忽略过大的 gitattributes 数据对象 '%s'"
 
+#: attr.c
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr "错误的 --attr-source 或 GIT_ATTR_SOURCE"
+
 #: bisect.c
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
@@ -1997,16 +2028,12 @@
 msgstr "--contents 和 --reverse 不能混用。"
 
 #: blame.c
-msgid "cannot use --contents with final commit object name"
-msgstr "不能将 --contents 和最终的提交对象名共用"
-
-#: blame.c
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr "--reverse 和 --first-parent 共用,需要指定最新的提交"
 
 #: blame.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c ref-filter.c
-#: remote.c sequencer.c submodule.c
+#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c remote.c
+#: sequencer.c submodule.c
 msgid "revision walk setup failed"
 msgstr "版本遍历初始化失败"
 
@@ -2200,11 +2227,6 @@
 msgid "'%s' is already checked out at '%s'"
 msgstr "'%s' 已经检出到 '%s'"
 
-#: branch.c
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "工作区 %s 的 HEAD 指向没有被更新"
-
 #: builtin/add.c
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<选项>] [--] <路径规格>..."
@@ -2472,7 +2494,7 @@
 msgid "could not open '%s' for reading"
 msgstr "无法打开 '%s' 进行读取"
 
-#: builtin/am.c builtin/rebase.c sequencer.c strbuf.c wrapper.c
+#: builtin/am.c builtin/rebase.c editor.c sequencer.c wrapper.c
 #, c-format
 msgid "could not open '%s' for writing"
 msgstr "无法打开 '%s' 进行写入"
@@ -3496,6 +3518,15 @@
 
 #: builtin/branch.c
 #, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"分支 '%s' 未找到。\n"
+"是否忘记指定 --remote 选项?"
+
+#: builtin/branch.c
+#, c-format
 msgid "branch '%s' not found."
 msgstr "分支 '%s' 未发现。"
 
@@ -3534,6 +3565,11 @@
 
 #: builtin/branch.c
 #, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "工作区 %s 的 HEAD 指向没有被更新"
+
+#: builtin/branch.c
+#, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "无效的分支名:'%s'"
 
@@ -3661,6 +3697,10 @@
 msgid "move/rename a branch, even if target exists"
 msgstr "移动/重命名一个分支,即使目标已存在"
 
+#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c
+msgid "do not output a newline after empty formatted refs"
+msgstr "在格式化引用结果为空之后,不输出换行符"
+
 #: builtin/branch.c
 msgid "copy a branch and its reflog"
 msgstr "拷贝一个分支和它的引用日志"
@@ -3928,12 +3968,10 @@
 
 #: builtin/bundle.c
 msgid ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<版本>] <文件> <git-rev-list-参数>"
 
 #: builtin/bundle.c
@@ -3960,13 +3998,13 @@
 msgid "show progress meter"
 msgstr "显示进度表"
 
-#: builtin/bundle.c builtin/pack-objects.c
-msgid "show progress meter during object writing phase"
-msgstr "在对象写入阶段显示进度表"
+#: builtin/bundle.c
+msgid "historical; same as --progress"
+msgstr "老的参数;等同于 --progress"
 
-#: builtin/bundle.c builtin/pack-objects.c
-msgid "similar to --all-progress when progress meter is shown"
-msgstr "当进度表显示时类似于 --all-progress"
+#: builtin/bundle.c
+msgid "historical; does nothing"
+msgstr "老的参数;无作用"
 
 #: builtin/bundle.c
 msgid "specify bundle format version"
@@ -5216,6 +5254,11 @@
 
 #: builtin/clone.c
 #, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "'%s' 为符号链接,拒绝用 --local 克隆"
+
+#: builtin/clone.c
+#, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "无法在 '%s' 上启动迭代器"
 
@@ -6001,7 +6044,7 @@
 msgid "version"
 msgstr "版本"
 
-#: builtin/commit.c builtin/push.c builtin/worktree.c
+#: builtin/commit.c builtin/fetch.c builtin/push.c builtin/worktree.c
 msgid "machine-readable output"
 msgstr "机器可读的输出"
 
@@ -7076,147 +7119,17 @@
 msgid "fetch.parallel cannot be negative"
 msgstr "fetch.parallel 不能为负数"
 
-#: builtin/fetch.c builtin/pull.c
-msgid "fetch from all remotes"
-msgstr "从所有的远程抓取"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "set upstream for git pull/fetch"
-msgstr "为 git pull/fetch 设置上游"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "append to .git/FETCH_HEAD instead of overwriting"
-msgstr "追加到 .git/FETCH_HEAD 而不是覆盖它"
-
-#: builtin/fetch.c
-msgid "use atomic transaction to update references"
-msgstr "使用原子事务更新引用"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "path to upload pack on remote end"
-msgstr "上传包到远程的路径"
-
-#: builtin/fetch.c
-msgid "force overwrite of local reference"
-msgstr "强制覆盖本地引用"
-
-#: builtin/fetch.c
-msgid "fetch from multiple remotes"
-msgstr "从多个远程抓取"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "fetch all tags and associated objects"
-msgstr "抓取所有的标签和关联对象"
-
-#: builtin/fetch.c
-msgid "do not fetch all tags (--no-tags)"
-msgstr "不抓取任何标签(--no-tags)"
-
-#: builtin/fetch.c
-msgid "number of submodules fetched in parallel"
-msgstr "子模组获取的并发数"
-
-#: builtin/fetch.c
-msgid "modify the refspec to place all refs within refs/prefetch/"
-msgstr "修改引用规格以将所有引用放入 refs/prefetch/"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "prune remote-tracking branches no longer on remote"
-msgstr "清除远程已经不存在的分支的跟踪分支"
-
-#: builtin/fetch.c
-msgid "prune local tags no longer on remote and clobber changed tags"
-msgstr "清除远程不存在的本地标签,并且替换变更标签"
-
-#  译者:可选值,不能翻译
-#: builtin/fetch.c builtin/pull.c
-msgid "on-demand"
-msgstr "on-demand"
-
-#: builtin/fetch.c
-msgid "control recursive fetching of submodules"
-msgstr "控制子模组的递归抓取"
-
-#: builtin/fetch.c
-msgid "write fetched references to the FETCH_HEAD file"
-msgstr "将获取到的引用写入 FETCH_HEAD 文件"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "keep downloaded pack"
-msgstr "保持下载包"
-
-#: builtin/fetch.c
-msgid "allow updating of HEAD ref"
-msgstr "允许更新 HEAD 引用"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "deepen history of shallow clone"
-msgstr "深化浅克隆的历史"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "deepen history of shallow repository based on time"
-msgstr "基于时间来深化浅克隆的历史"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "convert to a complete repository"
-msgstr "转换为一个完整的仓库"
-
-#: builtin/fetch.c
-msgid "re-fetch without negotiating common commits"
-msgstr "不协商共有提交重新获取"
-
-#: builtin/fetch.c
-msgid "prepend this to submodule path output"
-msgstr "在子模组路径输出的前面加上此目录"
-
-#: builtin/fetch.c
-msgid ""
-"default for recursive fetching of submodules (lower priority than config "
-"files)"
-msgstr "递归获取子模组的缺省值(比配置文件优先级低)"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "accept refs that update .git/shallow"
-msgstr "接受更新 .git/shallow 的引用"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "refmap"
-msgstr "引用映射"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "specify fetch refmap"
-msgstr "指定获取操作的引用映射"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "report that we have only objects reachable from this object"
-msgstr "报告我们只拥有从该对象开始可达的对象"
-
-#: builtin/fetch.c
-msgid "do not fetch a packfile; instead, print ancestors of negotiation tips"
-msgstr "不获取包文件;而是打印协商的祖先提交"
-
-#: builtin/fetch.c
-msgid "run 'maintenance --auto' after fetching"
-msgstr "获取后执行 'maintenance --auto'"
-
-#: builtin/fetch.c builtin/pull.c
-msgid "check for forced-updates on all updated branches"
-msgstr "在所有更新分支上检查强制更新"
-
-#: builtin/fetch.c
-msgid "write the commit-graph after fetching"
-msgstr "抓取后写提交图"
-
-#: builtin/fetch.c
-msgid "accept refspecs from stdin"
-msgstr "从标准输入获取引用规格"
-
 #: builtin/fetch.c
 msgid "couldn't find remote ref HEAD"
 msgstr "无法发现远程 HEAD 引用"
 
 #: builtin/fetch.c
 #, c-format
+msgid "From %.*s\n"
+msgstr "来自 %.*s\n"
+
+#: builtin/fetch.c
+#, c-format
 msgid "object %s not found"
 msgstr "对象 %s 未发现"
 
@@ -7302,11 +7215,6 @@
 
 #: builtin/fetch.c
 #, c-format
-msgid "From %.*s\n"
-msgstr "来自 %.*s\n"
-
-#: builtin/fetch.c
-#, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
 " 'git remote prune %s' to remove any old, conflicting branches"
@@ -7415,6 +7323,141 @@
 msgid "you need to specify a tag name"
 msgstr "您需要指定一个标签名称"
 
+#: builtin/fetch.c builtin/pull.c
+msgid "fetch from all remotes"
+msgstr "从所有远程抓取"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "set upstream for git pull/fetch"
+msgstr "为 git pull/fetch 设置上游"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "append to .git/FETCH_HEAD instead of overwriting"
+msgstr "追加到 .git/FETCH_HEAD 而不是覆盖它"
+
+#: builtin/fetch.c
+msgid "use atomic transaction to update references"
+msgstr "使用原子事务更新引用"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "path to upload pack on remote end"
+msgstr "上传包到远程的路径"
+
+#: builtin/fetch.c
+msgid "force overwrite of local reference"
+msgstr "强制覆盖本地引用"
+
+#: builtin/fetch.c
+msgid "fetch from multiple remotes"
+msgstr "从多个远程抓取"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "fetch all tags and associated objects"
+msgstr "抓取所有的标签和关联对象"
+
+#: builtin/fetch.c
+msgid "do not fetch all tags (--no-tags)"
+msgstr "不抓取任何标签(--no-tags)"
+
+#: builtin/fetch.c
+msgid "number of submodules fetched in parallel"
+msgstr "获取子模组的并发数"
+
+#: builtin/fetch.c
+msgid "modify the refspec to place all refs within refs/prefetch/"
+msgstr "修改引用规格以将所有引用放入 refs/prefetch/"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "prune remote-tracking branches no longer on remote"
+msgstr "清除远程已经不存在的分支的跟踪分支"
+
+#: builtin/fetch.c
+msgid "prune local tags no longer on remote and clobber changed tags"
+msgstr "清除远程不存在的本地标签,并且替换变更标签"
+
+#  译者:可选值,不能翻译
+#: builtin/fetch.c builtin/pull.c
+msgid "on-demand"
+msgstr "on-demand"
+
+#: builtin/fetch.c
+msgid "control recursive fetching of submodules"
+msgstr "控制子模组的递归抓取"
+
+#: builtin/fetch.c
+msgid "write fetched references to the FETCH_HEAD file"
+msgstr "将获取到的引用写入 FETCH_HEAD 文件"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "keep downloaded pack"
+msgstr "保持已下载的包"
+
+#: builtin/fetch.c
+msgid "allow updating of HEAD ref"
+msgstr "允许更新 HEAD 引用"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "deepen history of shallow clone"
+msgstr "深化浅克隆的历史"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "deepen history of shallow repository based on time"
+msgstr "基于时间来深化浅克隆的历史"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "convert to a complete repository"
+msgstr "转换为一个完整的仓库"
+
+#: builtin/fetch.c
+msgid "re-fetch without negotiating common commits"
+msgstr "重新获取而不协商共同提交"
+
+#: builtin/fetch.c
+msgid "prepend this to submodule path output"
+msgstr "在子模组路径输出的前面加上此目录"
+
+#: builtin/fetch.c
+msgid ""
+"default for recursive fetching of submodules (lower priority than config "
+"files)"
+msgstr "递归获取子模组的缺省值(比配置文件优先级低)"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "accept refs that update .git/shallow"
+msgstr "接受更新 .git/shallow 的引用"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "refmap"
+msgstr "引用映射"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "specify fetch refmap"
+msgstr "指定获取操作的引用映射"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "report that we have only objects reachable from this object"
+msgstr "报告我们只拥有从该对象开始可达的对象"
+
+#: builtin/fetch.c
+msgid "do not fetch a packfile; instead, print ancestors of negotiation tips"
+msgstr "不获取包文件;而是打印协商的祖先提交"
+
+#: builtin/fetch.c
+msgid "run 'maintenance --auto' after fetching"
+msgstr "获取后执行 'maintenance --auto'"
+
+#: builtin/fetch.c builtin/pull.c
+msgid "check for forced-updates on all updated branches"
+msgstr "在所有更新分支上检查强制更新"
+
+#: builtin/fetch.c
+msgid "write the commit-graph after fetching"
+msgstr "抓取后写提交图"
+
+#: builtin/fetch.c
+msgid "accept refspecs from stdin"
+msgstr "从标准输入获取引用规格"
+
 #: builtin/fetch.c
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr "--negotiate-only 需要一个或多个 --negotiation-tip=*"
@@ -7560,6 +7603,14 @@
 msgid "print only refs which don't contain the commit"
 msgstr "只打印不包含该提交的引用"
 
+#: builtin/for-each-ref.c
+msgid "read reference patterns from stdin"
+msgstr "从标准输入读取引用的模式"
+
+#: builtin/for-each-ref.c
+msgid "unknown arguments supplied with --stdin"
+msgstr "为 --stdin 提供了未知的命令参数"
+
 #: builtin/for-each-repo.c
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<配置> [--] <命令参数>"
@@ -7576,6 +7627,11 @@
 msgid "missing --config=<config>"
 msgstr "缺少 --config=<配置>"
 
+#: builtin/for-each-repo.c
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "发现错误的配置行 --config=%s"
+
 #: builtin/fsck.c
 msgid "unknown"
 msgstr "未知"
@@ -7761,13 +7817,14 @@
 msgstr "注意:%s 指向一个尚未诞生的分支(%s)"
 
 #: builtin/fsck.c
-msgid "Checking cache tree"
-msgstr "正在检查缓存树"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "正在检查缓存树 %s"
 
 #: builtin/fsck.c
 #, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "%s:cache-tree 中无效的 sha1 指针"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s:cache-tree %s 中存在无效的 sha1 指针"
 
 #: builtin/fsck.c
 msgid "non-tree in cache-tree"
@@ -7775,8 +7832,18 @@
 
 #: builtin/fsck.c
 #, c-format
-msgid "%s: invalid sha1 pointer in resolve-undo"
-msgstr "%s:resolve-undo 中无效的 sha1 指针"
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s:resolve-undo %s 中存在无效的 sha1 指针"
+
+#: builtin/fsck.c
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "无法为包文件 %s 加载反向索引"
+
+#: builtin/fsck.c
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "包文件 '%s' 的反向索引文件无效"
 
 #: builtin/fsck.c
 msgid ""
@@ -10371,7 +10438,7 @@
 msgid "Bad value '%s' in environment '%s'"
 msgstr "环境 '%2$s' 中存在坏的取值 '%1$s'"
 
-#: builtin/merge.c read-cache.c strbuf.c wrapper.c
+#: builtin/merge.c editor.c read-cache.c wrapper.c
 #, c-format
 msgid "could not close '%s'"
 msgstr "不能关闭 '%s'"
@@ -11204,7 +11271,7 @@
 msgid "wrote %<PRIu32> objects while expecting %<PRIu32>"
 msgstr "写入 %<PRIu32> 个对象而预期 %<PRIu32> 个"
 
-#: builtin/pack-objects.c
+#: builtin/pack-objects.c builtin/repack.c
 msgid "disabling bitmap writing, as some objects are not being packed"
 msgstr "禁用 bitmap 写入,因为一些对象将不会被打包"
 
@@ -11371,6 +11438,14 @@
 msgstr "坏的索引版本 '%s'"
 
 #: builtin/pack-objects.c
+msgid "show progress meter during object writing phase"
+msgstr "在对象写入阶段显示进度表"
+
+#: builtin/pack-objects.c
+msgid "similar to --all-progress when progress meter is shown"
+msgstr "当进度表显示时类似于 --all-progress"
+
+#: builtin/pack-objects.c
 msgid "<version>[,<offset>]"
 msgstr "<版本>[,<偏移>]"
 
@@ -11611,6 +11686,10 @@
 "并通过发送邮件到 <git@vger.kernel.org> 让我们知道您仍旧\n"
 "使用它。 谢谢。\n"
 
+#: builtin/pack-redundant.c
+msgid "refusing to run without --i-still-use-this"
+msgstr "拒绝在未指定 --i-still-use-this 选项时运行"
+
 #: builtin/pack-refs.c
 msgid "git pack-refs [--all] [--no-prune]"
 msgstr "git pack-refs [--all] [--no-prune]"
@@ -11812,9 +11891,9 @@
 msgid "pull with rebase"
 msgstr "变基式拉取"
 
-#: builtin/pull.c
-msgid "please commit or stash them."
-msgstr "请提交或贮藏它们。"
+#: builtin/pull.c builtin/rebase.c
+msgid "Please commit or stash them."
+msgstr "请提交或贮藏修改。"
 
 #: builtin/pull.c
 #, c-format
@@ -12061,9 +12140,9 @@
 msgid "repository"
 msgstr "仓库"
 
-#: builtin/push.c builtin/send-pack.c
-msgid "push all refs"
-msgstr "推送所有引用"
+#: builtin/push.c
+msgid "push all branches"
+msgstr "推送所有分支"
 
 #: builtin/push.c builtin/send-pack.c
 msgid "mirror all refs"
@@ -12074,8 +12153,8 @@
 msgstr "删除引用"
 
 #: builtin/push.c
-msgid "push tags (can't be used with --all or --mirror)"
-msgstr "推送标签(不能使用 --all or --mirror)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr "推送标签(不能使用 --all or --branches or --mirror)"
 
 #: builtin/push.c builtin/send-pack.c
 msgid "force updates"
@@ -12399,6 +12478,11 @@
 
 #: builtin/rebase.c
 #, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "未知的变基合并模式:%s"
+
+#: builtin/rebase.c
+#, c-format
 msgid "could not switch to %s"
 msgstr "无法切换到 %s"
 
@@ -12414,6 +12498,16 @@
 msgstr "无法识别的空类型 '%s';有效值有 \"drop\"、\"keep\" 和 \"ask\"。"
 
 #: builtin/rebase.c
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"为 --rebase-merges 指定空值参数的方式已经被废弃并且在 Git 未来\n"
+"的版本中将不再支持。 支持使用无参数 --rebase-merges 的方式进行替\n"
+"代,它们具有相同的作用。"
+
+#: builtin/rebase.c
 #, c-format
 msgid ""
 "%s\n"
@@ -12676,19 +12770,20 @@
 msgstr "开关 `C' 期望一个数字值"
 
 #: builtin/rebase.c
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "未知模式:%s"
-
-#: builtin/rebase.c
 msgid "--strategy requires --merge or --interactive"
 msgstr "--strategy 需要 --merge 或 --interactive"
 
 #: builtin/rebase.c
 msgid ""
-"apply options are incompatible with rebase.autosquash.  Consider adding --no-"
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
 "autosquash"
-msgstr "应用的选项与 rebase.autosquash 不兼容。考虑加上 --no-autosquash"
+msgstr "应用的选项与 rebase.autoSquash 不兼容。考虑加上 --no-autosquash"
+
+#: builtin/rebase.c
+msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr "应用的选项与 rebase.rebaseMerges 不兼容。考虑加上 --no-rebase-merges"
 
 #: builtin/rebase.c
 msgid ""
@@ -12744,10 +12839,6 @@
 msgstr "没有指向一个有效的提交 '%s'"
 
 #: builtin/rebase.c
-msgid "Please commit or stash them."
-msgstr "请提交或贮藏修改。"
-
-#: builtin/rebase.c
 msgid "HEAD is up to date."
 msgstr "HEAD 是最新的。"
 
@@ -13549,8 +13640,8 @@
 msgstr "近似日期"
 
 #: builtin/repack.c
-msgid "with -C, expire objects older than this"
-msgstr "使用 -C,使早于给定时间的对象过期"
+msgid "with --cruft, expire objects older than this"
+msgstr "使用 --cruft,使早于给定时间的对象过期"
 
 #: builtin/repack.c
 msgid "remove redundant packs, and run git-prune-packed"
@@ -14382,6 +14473,10 @@
 msgstr "远程名称"
 
 #: builtin/send-pack.c
+msgid "push all refs"
+msgstr "推送所有引用"
+
+#: builtin/send-pack.c
 msgid "use stateless RPC protocol"
 msgstr "使用无状态的 RPC 协议"
 
@@ -14638,9 +14733,11 @@
 
 #: builtin/sparse-checkout.c
 msgid ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<选项>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check\n"
+"-rules) [<选项>]"
 
 #: builtin/sparse-checkout.c
 msgid "this worktree is not sparse"
@@ -14780,6 +14877,26 @@
 msgid "error while refreshing working directory"
 msgstr "刷新工作目录时出错"
 
+#: builtin/sparse-checkout.c
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <文件>]"
+
+#: builtin/sparse-checkout.c
+msgid "terminate input and output files by a NUL character"
+msgstr "输入和输出的文件使用 NUL 字符终结"
+
+#: builtin/sparse-checkout.c
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr "通过 --rules-file 选项传递的模型将被作为锥形(稀疏检出模型)进行解析"
+
+#: builtin/sparse-checkout.c
+msgid "use patterns in <file> instead of the current ones."
+msgstr "从 <文件> 参数中读取模式,而不是从标准输入"
+
 #: builtin/stash.c
 msgid "git stash list [<log-options>]"
 msgstr "git stash list [<日志选项>]"
@@ -18313,8 +18430,8 @@
 msgstr "错误的 zlib 压缩级别 %d"
 
 #: config.c
-msgid "core.commentChar should only be one character"
-msgstr "core.commentChar 应该是一个字符"
+msgid "core.commentChar should only be one ASCII character"
+msgstr "core.commentChar 应该是一个 ASCII 编码的字符"
 
 #: config.c
 #, c-format
@@ -18454,6 +18571,11 @@
 
 #: config.c
 #, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr "拒绝支持内容过长的行,位于文件 '%s' 中的第 %<PRIuMAX> 行"
+
+#: config.c
+#, c-format
 msgid "missing value for '%s'"
 msgstr "%s 的取值缺失"
 
@@ -19263,6 +19385,10 @@
 msgstr "不显示任何源和目标前缀"
 
 #: diff.c
+msgid "use default prefixes a/ and b/"
+msgstr "使用 a/ 和 b/ 作为默认前缀"
+
+#: diff.c
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr "显示指定行数的差异块间的上下文"
 
@@ -19631,6 +19757,16 @@
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "提示:等待您的编辑器关闭文件...%c"
 
+#: editor.c sequencer.c wrapper.c
+#, c-format
+msgid "could not write to '%s'"
+msgstr "不能写入 '%s'"
+
+#: editor.c
+#, c-format
+msgid "could not edit '%s'"
+msgstr "不能编辑 '%s'"
+
 #: entry.c
 msgid "Filtering content"
 msgstr "过滤内容"
@@ -19999,6 +20135,11 @@
 
 #: git.c
 #, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "没有为 --attr-source 提供属性来源\n"
+
+#: git.c
+#, c-format
 msgid "unknown option: %s\n"
 msgstr "未知选项:%s\n"
 
@@ -21978,6 +22119,11 @@
 msgid "unable to get disk usage of '%s'"
 msgstr "无法得到 '%s' 的磁盘使用量"
 
+#: pack-bitmap.c
+#, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "位图文件 '%s' 有无效的校验码"
+
 #: pack-mtimes.c
 #, c-format
 msgid "mtimes file %s is too small"
@@ -22028,6 +22174,15 @@
 msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
 msgstr "反向索引文件 %s 有不支持的哈希 ID %<PRIu32>"
 
+#: pack-revindex.c
+msgid "invalid checksum"
+msgstr "无效的校验码 %s"
+
+#: pack-revindex.c
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr "位于 %<PRIu64> 的无效的反向索引:%<PRIu32> != %<PRIu32>"
+
 #: pack-write.c
 msgid "cannot both write and verify reverse index"
 msgstr "无法同时写入和校验反向索引"
@@ -22884,6 +23039,11 @@
 
 #: ref-filter.c
 #, c-format
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "期望的格式:%%(ahead-behind:<提交号>)"
+
+#: ref-filter.c
+#, c-format
 msgid "malformed field name: %.*s"
 msgstr "格式错误的字段名:%.*s"
 
@@ -23637,11 +23797,6 @@
 
 #: rerere.c
 #, c-format
-msgid "cannot unlink '%s'"
-msgstr "不能删除 '%s'"
-
-#: rerere.c
-#, c-format
 msgid "Updated preimage for '%s'"
 msgstr "已为 '%s' 更新 preimage"
 
@@ -24052,11 +24207,6 @@
 msgid "could not lock '%s'"
 msgstr "不能锁定 '%s'"
 
-#: sequencer.c strbuf.c wrapper.c
-#, c-format
-msgid "could not write to '%s'"
-msgstr "不能写入 '%s'"
-
 #: sequencer.c
 #, c-format
 msgid "could not write eol to '%s'"
@@ -24495,10 +24645,6 @@
 msgstr "不能创建序列目录 '%s'"
 
 #: sequencer.c
-msgid "could not lock HEAD"
-msgstr "不能锁定 HEAD"
-
-#: sequencer.c
 msgid "no cherry-pick or revert in progress"
 msgstr "拣选或还原操作并未进行"
 
@@ -24612,21 +24758,21 @@
 "\n"
 
 #: sequencer.c
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "并且修改索引和/或工作区\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "并且修改索引和/或工作区。\n"
 
 #: sequencer.c
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
 msgstr ""
 "执行成功:%s\n"
-"但是在索引和/或工作区中存在变更\n"
+"但是在索引和/或工作区中存在变更。\n"
 "提交或贮藏修改,然后运行\n"
 "\n"
 "  git rebase --continue\n"
@@ -25148,11 +25294,6 @@
 msgstr[0] "%u 字节/秒"
 msgstr[1] "%u 字节/秒"
 
-#: strbuf.c
-#, c-format
-msgid "could not edit '%s'"
-msgstr "不能编辑 '%s'"
-
 #: submodule-config.c
 #, c-format
 msgid "ignoring suspicious submodule name: %s"
@@ -27244,8 +27385,8 @@
 
 #: git-send-email.perl
 #, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) 添加 %s: %s 自:'%s'\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) 非法的输出信息,来自于: '%s'"
 
 #: git-send-email.perl
 #, perl-format
@@ -27253,6 +27394,11 @@
 msgstr "(%s) 无法关闭管道至 '%s'"
 
 #: git-send-email.perl
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) 添加 %s: %s 自:'%s'\n"
+
+#: git-send-email.perl
 msgid "cannot send message as 7bit"
 msgstr "不能以 7bit 形式发送信息"
 
diff --git a/po/zh_TW.po b/po/zh_TW.po
index aa59a8e..1c549b8 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -19,14 +19,14 @@
 # - Yichao Yu <yyc1992 AT gmail.com>
 # - Zhuang Ya <zhuangya AT me.com>
 #
-# Yi-Jyun Pan <pan93412@gmail.com>, 2021, 2022.
+# Yi-Jyun Pan <pan93412@gmail.com>, 2021, 2022, 2023.
 # Kaiyang Wu <self@origincode.me>, 2022.
 msgid ""
 msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2022-12-11 00:28+0800\n"
-"PO-Revision-Date: 2022-12-10 17:12+0000\n"
+"POT-Creation-Date: 2023-05-19 19:57+0000\n"
+"PO-Revision-Date: 2023-05-31 23:41+0800\n"
 "Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\n"
 "Language-Team: Chinese (Traditional) <http://weblate.slat.org/projects/git-"
 "po/git-cli/zh_Hant/>\n"
@@ -35,7 +35,7 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.14.2\n"
+"X-Generator: Poedit 3.3.1\n"
 "X-ZhConverter: 繁化姬 dict-f4bc617e-r910 @ 2019/11/16 20:23:12 | https://"
 "zhconvert.org\n"
 
@@ -48,19 +48,19 @@
 msgid "could not read index"
 msgstr "無法讀取索引"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "binary"
 msgstr "二進位"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "nothing"
 msgstr "無"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "unchanged"
 msgstr "未變更"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "Update"
 msgstr "更新"
 
@@ -73,14 +73,14 @@
 msgid "could not write index"
 msgstr "無法寫入索引"
 
-#: add-interactive.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-interactive.c
+#, c-format
 msgid "updated %d path\n"
 msgid_plural "updated %d paths\n"
 msgstr[0] "已更新 %d 個路徑\n"
 
-#: add-interactive.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-interactive.c
+#, c-format
 msgid "note: %s is untracked now.\n"
 msgstr "註:現已不再追蹤 %s。\n"
 
@@ -89,7 +89,7 @@
 msgid "make_cache_entry failed for path '%s'"
 msgstr "對 “%s” 路徑執行 make_cache_entry 失敗"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "Revert"
 msgstr "還原"
 
@@ -97,23 +97,23 @@
 msgid "Could not parse HEAD^{tree}"
 msgstr "無法解析 HEAD^{tree}"
 
-#: add-interactive.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-interactive.c
+#, c-format
 msgid "reverted %d path\n"
 msgid_plural "reverted %d paths\n"
 msgstr[0] "已還原 %d 個路徑\n"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 #, c-format
 msgid "No untracked files.\n"
 msgstr "沒有未追蹤的檔案。\n"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "Add untracked"
 msgstr "加入未追蹤項目"
 
-#: add-interactive.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-interactive.c
+#, c-format
 msgid "added %d path\n"
 msgid_plural "added %d paths\n"
 msgstr[0] "已加入 %d 個路徑\n"
@@ -123,21 +123,21 @@
 msgid "ignoring unmerged: %s"
 msgstr "忽略未合併項目:%s"
 
-#: add-interactive.c add-patch.c git-add--interactive.perl
+#: add-interactive.c add-patch.c
 #, c-format
 msgid "Only binary files changed.\n"
 msgstr "只變更二進位檔案。\n"
 
-#: add-interactive.c add-patch.c git-add--interactive.perl
+#: add-interactive.c add-patch.c
 #, c-format
 msgid "No changes.\n"
 msgstr "沒有更動。\n"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "Patch update"
 msgstr "修補檔更新"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "Review diff"
 msgstr "檢閱差異"
 
@@ -205,25 +205,25 @@
 msgid "(empty) select nothing"
 msgstr "(空)全部不選取"
 
-#: add-interactive.c builtin/clean.c git-add--interactive.perl
+#: add-interactive.c builtin/clean.c
 msgid "*** Commands ***"
 msgstr "*** 命令 ***"
 
-#: add-interactive.c builtin/clean.c git-add--interactive.perl
+#: add-interactive.c builtin/clean.c
 msgid "What now"
 msgstr "請選擇"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "staged"
 msgstr "已暫存"
 
-#: add-interactive.c git-add--interactive.perl
+#: add-interactive.c
 msgid "unstaged"
 msgstr "未暫存"
 
 #: add-interactive.c apply.c builtin/am.c builtin/bugreport.c builtin/clone.c
-#: builtin/diagnose.c builtin/fetch.c builtin/merge.c builtin/pull.c
-#: builtin/submodule--helper.c git-add--interactive.perl
+#: builtin/diagnose.c builtin/fetch.c builtin/hook.c builtin/merge.c
+#: builtin/pull.c builtin/submodule--helper.c
 msgid "path"
 msgstr "路徑"
 
@@ -231,28 +231,28 @@
 msgid "could not refresh index"
 msgstr "無法重新整理索引"
 
-#: add-interactive.c builtin/clean.c git-add--interactive.perl
+#: add-interactive.c builtin/clean.c
 #, c-format
 msgid "Bye.\n"
 msgstr "再見。\n"
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Stage mode change [y,n,q,a,d%s,?]? "
 msgstr "暫存模式更動 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Stage deletion [y,n,q,a,d%s,?]? "
 msgstr "暫存刪除動作 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Stage addition [y,n,q,a,d%s,?]? "
 msgstr "暫存加入動作 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Stage this hunk [y,n,q,a,d%s,?]? "
 msgstr "暫存此區塊 [y,n,q,a,d%s,?]? "
 
@@ -276,23 +276,23 @@
 "a - 暫存此區塊和本檔案中後面的全部區塊\n"
 "d - 不暫存此區塊和本檔案中後面的全部區塊\n"
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Stash mode change [y,n,q,a,d%s,?]? "
 msgstr "貯存模式更動 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Stash deletion [y,n,q,a,d%s,?]? "
 msgstr "貯存刪除動作 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Stash addition [y,n,q,a,d%s,?]? "
 msgstr "貯存加入動作 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Stash this hunk [y,n,q,a,d%s,?]? "
 msgstr "貯存此區塊 [y,n,q,a,d%s,?]? "
 
@@ -316,23 +316,23 @@
 "a - 貯存此區塊和本檔案中後面的全部區塊\n"
 "d - 不貯存此區塊和本檔案中後面的全部區塊\n"
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Unstage mode change [y,n,q,a,d%s,?]? "
 msgstr "取消暫存模式更動 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Unstage deletion [y,n,q,a,d%s,?]? "
 msgstr "取消暫存刪除動作 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Unstage addition [y,n,q,a,d%s,?]? "
 msgstr "取消暫存加入動作 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Unstage this hunk [y,n,q,a,d%s,?]? "
 msgstr "取消暫存此區塊 [y,n,q,a,d%s,?]? "
 
@@ -356,23 +356,23 @@
 "a - 不暫存此區塊和本檔案中後面的全部區塊\n"
 "d - 不要不暫存此區塊和本檔案中後面的全部區塊\n"
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply mode change to index [y,n,q,a,d%s,?]? "
 msgstr "將模式更動套用到索引 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply deletion to index [y,n,q,a,d%s,?]? "
 msgstr "將刪除動作套用至索引 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply addition to index [y,n,q,a,d%s,?]? "
 msgstr "將加入動作套用至索引 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply this hunk to index [y,n,q,a,d%s,?]? "
 msgstr "將此區塊套用到索引 [y,n,q,a,d%s,?]? "
 
@@ -396,23 +396,23 @@
 "a - 套用此區塊和本檔案中後面的全部區塊\n"
 "d - 不要套用此區塊和本檔案中後面的全部區塊\n"
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? "
 msgstr "從工作區捨棄模式更動 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? "
 msgstr "從工作區捨棄刪除動作 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Discard addition from worktree [y,n,q,a,d%s,?]? "
 msgstr "從工作區捨棄加入動作 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? "
 msgstr "從工作區捨棄此區塊 [y,n,q,a,d%s,?]? "
 
@@ -436,23 +436,23 @@
 "a - 捨棄此區塊和本檔案中後面的全部區塊\n"
 "d - 不要捨棄此區塊和本檔案中後面的全部區塊\n"
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? "
 msgstr "從索引和工作區捨棄模式更動 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? "
 msgstr "從索引和工作區捨棄刪除 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? "
 msgstr "從索引和工作區捨棄加入動作 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? "
 msgstr "從索引和工作區捨棄此區塊 [y,n,q,a,d%s,?]? "
 
@@ -470,23 +470,23 @@
 "a - 捨棄此區塊和本檔案中後面的全部區塊\n"
 "d - 不要捨棄此區塊和本檔案中後面的全部區塊\n"
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? "
 msgstr "將模式更動套用到索引和工作區 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? "
 msgstr "將刪除動作套用到索引和工作區 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? "
 msgstr "將加入動作套用到索引和工作區 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "
 msgstr "將此區塊套用到索引和工作區 [y,n,q,a,d%s,?]? "
 
@@ -504,23 +504,23 @@
 "a - 套用此區塊和本檔案中後面的全部區塊\n"
 "d - 不要套用此區塊和本檔案中後面的全部區塊\n"
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? "
 msgstr "將模式更動套用到工作區 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? "
 msgstr "將刪除動作套用到工作區 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply addition to worktree [y,n,q,a,d%s,?]? "
 msgstr "將加入動作套用到工作區 [y,n,q,a,d%s,?]? "
 
-#: add-patch.c git-add--interactive.perl
-#, c-format, perl-format
+#: add-patch.c
+#, c-format
 msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? "
 msgstr "將此區塊套用到工作區 [y,n,q,a,d%s,?]? "
 
@@ -590,7 +590,7 @@
 "\t結尾不是:\n"
 "%.*s"
 
-#: add-patch.c git-add--interactive.perl
+#: add-patch.c
 msgid "Manual hunk edit mode -- see bottom for a quick guide.\n"
 msgstr "手動區塊編輯模式——檢視底部的快速指引。\n"
 
@@ -607,9 +607,7 @@
 "要刪除 “%c” 開頭的列,請直接刪除。\n"
 "開頭是 %c 的列將會被移除。\n"
 
-#. #-#-#-#-#  git-add--interactive.perl.po  #-#-#-#-#
-#. TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.
-#: add-patch.c git-add--interactive.perl
+#: add-patch.c
 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"
@@ -627,21 +625,13 @@
 msgid "'git apply --cached' failed"
 msgstr "“git apply --cached” 失敗"
 
-#. #-#-#-#-#  add-patch.c.po  #-#-#-#-#
 #. TRANSLATORS: do not translate [y/n]
 #. The program will only accept that input at this point.
 #. Consider translating (saying "no" discards!) as
 #. (saying "n" for "no" discards!) if the translation
 #. of the word "no" does not start with n.
 #.
-#. #-#-#-#-#  git-add--interactive.perl.po  #-#-#-#-#
-#. TRANSLATORS: do not translate [y/n]
-#. The program will only accept that input
-#. at this point.
-#. 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 git-add--interactive.perl
+#: add-patch.c
 msgid ""
 "Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
 msgstr "未套用您編輯的區塊。是否重新編輯(輸入 “no” 捨棄!) [y/n]? "
@@ -650,11 +640,11 @@
 msgid "The selected hunks do not apply to the index!"
 msgstr "選取的區塊無法套用至索引!"
 
-#: add-patch.c git-add--interactive.perl
+#: add-patch.c
 msgid "Apply them to the worktree anyway? "
 msgstr "無論如何都要套用到工作區嗎? "
 
-#: add-patch.c git-add--interactive.perl
+#: add-patch.c
 msgid "Nothing was applied.\n"
 msgstr "未套用。\n"
 
@@ -692,11 +682,11 @@
 msgid "No other hunks to goto"
 msgstr "沒有其它可以跳轉的區塊"
 
-#: add-patch.c git-add--interactive.perl
+#: add-patch.c
 msgid "go to which hunk (<ret> to see more)? "
 msgstr "要跳轉到哪個區塊(<ret> 檢視更多)? "
 
-#: add-patch.c git-add--interactive.perl
+#: add-patch.c
 msgid "go to which hunk? "
 msgstr "跳轉到哪個區塊? "
 
@@ -715,7 +705,7 @@
 msgid "No other hunks to search"
 msgstr "沒有其它可以尋找的區塊"
 
-#: add-patch.c git-add--interactive.perl
+#: add-patch.c
 msgid "search for regex? "
 msgstr "使用常規表示式搜尋? "
 
@@ -809,6 +799,24 @@
 msgstr "存在未完成的合併,離開。"
 
 #: advice.c
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"岔開的分支不能快轉,您得執行:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"或者:\n"
+"\n"
+"\tgit rebase\n"
+
+#: advice.c
 msgid "Not possible to fast-forward, aborting."
 msgstr "無法快轉,中止。"
 
@@ -1295,7 +1303,7 @@
 msgid "unable to add cache entry for %s"
 msgstr "無法為 %s 加入快取項目"
 
-#: apply.c builtin/bisect--helper.c builtin/gc.c
+#: apply.c builtin/bisect.c builtin/gc.c
 #, c-format
 msgid "failed to write to '%s'"
 msgstr "無法寫入 “%s”"
@@ -1335,6 +1343,11 @@
 msgid "cannot open %s"
 msgstr "無法開啟 %s"
 
+#: apply.c rerere.c
+#, c-format
+msgid "cannot unlink '%s'"
+msgstr "無法刪除 “%s”"
+
 #: apply.c
 #, c-format
 msgid "Hunk #%d applied cleanly."
@@ -1569,6 +1582,11 @@
 msgid "cannot read '%s'"
 msgstr "無法讀取 “%s”"
 
+#: archive.c
+#, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr "符合路徑規格「%s」的檔案在目前目錄之外"
+
 #: archive.c builtin/add.c builtin/rm.c
 #, c-format
 msgid "pathspec '%s' did not match any files"
@@ -1590,10 +1608,6 @@
 msgstr "非樹狀物件:%s"
 
 #: archive.c
-msgid "current working directory is untracked"
-msgstr "尚未追蹤目前的工作目錄"
-
-#: archive.c
 #, c-format
 msgid "File not found: %s"
 msgstr "找不到檔案:%s"
@@ -1626,7 +1640,7 @@
 msgid "archive format"
 msgstr "封存格式"
 
-#: archive.c builtin/log.c
+#: archive.c builtin/log.c parse-options.h
 msgid "prefix"
 msgstr "前綴"
 
@@ -1660,6 +1674,15 @@
 msgid "report archived files on stderr"
 msgstr "在 stderr 上回報封存的檔案"
 
+#: archive.c builtin/clone.c builtin/fetch.c builtin/pack-objects.c
+#: builtin/pull.c
+msgid "time"
+msgstr "time"
+
+#: archive.c
+msgid "set modification time of archive entries"
+msgstr "設定封存項目的修改時間"
+
 #: archive.c
 msgid "set compression level"
 msgstr "設定壓縮級別"
@@ -1716,6 +1739,15 @@
 msgstr "%.*s 不是有效的屬性名稱"
 
 #: attr.c
+msgid "unable to add additional attribute"
+msgstr "無法加入其他屬性"
+
+#: attr.c
+#, c-format
+msgid "ignoring overly long attributes line %d"
+msgstr "忽略過長的屬性列 (第 %d 列)"
+
+#: attr.c
 #, c-format
 msgid "%s not allowed: %s:%d"
 msgstr "不允許 %s:%s:%d"
@@ -1728,6 +1760,25 @@
 "git attributes 會忽略反向模式\n"
 "當字串確定要以驚嘆號開始時,請使用 “\\!”。"
 
+#: attr.c
+#, c-format
+msgid "cannot fstat gitattributes file '%s'"
+msgstr "無法 fstat gitattributes 檔案 “%s”"
+
+#: attr.c
+#, c-format
+msgid "ignoring overly large gitattributes file '%s'"
+msgstr "忽略過大的 gitattributes 檔案 “%s”"
+
+#: attr.c
+#, c-format
+msgid "ignoring overly large gitattributes blob '%s'"
+msgstr "忽略過大的 gitattributes 資料物件 “%s”"
+
+#: attr.c
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr "無效的 --attr-source 或 GIT_ATTR_SOURCE"
+
 #: bisect.c
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
@@ -1850,16 +1901,12 @@
 msgstr "--contents 和 --reverse 不能混用。"
 
 #: blame.c
-msgid "cannot use --contents with final commit object name"
-msgstr "無法將 --contents 與最終的提交物件名稱共用"
-
-#: blame.c
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr "--reverse 和 --first-parent 共用,需要指定最新的提交"
 
 #: blame.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c bundle.c midx.c pack-bitmap.c
-#: ref-filter.c remote.c sequencer.c submodule.c
+#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c remote.c
+#: sequencer.c submodule.c
 msgid "revision walk setup failed"
 msgstr "修訂版遍歷設定失敗"
 
@@ -1934,12 +1981,10 @@
 msgstr "未追蹤:“%s” 引用有歧義"
 
 #  譯者:為保證在輸出中對齊,注意調整句中空格!
-#. #-#-#-#-#  branch.c.po  #-#-#-#-#
 #. TRANSLATORS: This is a line listing a remote with duplicate
 #. refspecs in the advice message below. For RTL languages you'll
 #. probably want to swap the "%s" and leading "  " space around.
 #.
-#. #-#-#-#-#  object-name.c.po  #-#-#-#-#
 #. TRANSLATORS: This is line item of ambiguous object output
 #. from describe_ambiguous_object() above. For RTL languages
 #. you'll probably want to swap the "%s" and leading " " space
@@ -2040,11 +2085,11 @@
 #: branch.c
 #, c-format
 msgid ""
-"You may try updating the submodules using 'git checkout %s && git submodule "
-"update --init'"
+"You may try updating the submodules using 'git checkout --no-recurse-"
+"submodules %s && git submodule update --init'"
 msgstr ""
-"您可以嘗試使用 “git checkout %s && git submodule update --init” 命令,更新子"
-"模組"
+"您可以使用 “git checkout --no-recurse-submodules %s && git submodule update "
+"--init” 命令嘗試更新子模組"
 
 #: branch.c
 #, c-format
@@ -2056,11 +2101,6 @@
 msgid "'%s' is already checked out at '%s'"
 msgstr "“%s” 已在 “%s” 點簽出"
 
-#: branch.c
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "%s 工作區的 HEAD 指針未被更新"
-
 #: builtin/add.c
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<options>] [--] <pathspec>..."
@@ -2088,6 +2128,14 @@
 msgid "Unstaged changes after refreshing the index:"
 msgstr "重新整理索引之後,尚未被暫存的更動:"
 
+#: builtin/add.c
+msgid ""
+"the add.interactive.useBuiltin setting has been removed!\n"
+"See its entry in 'git help config' for details."
+msgstr ""
+"add.interactive.useBuiltin 設定已被移除!\n"
+"深入了解請參閱 “git help config” 中的對應條目。"
+
 #: builtin/add.c builtin/rev-parse.c
 msgid "Could not read the index"
 msgstr "無法讀取索引"
@@ -2323,7 +2371,7 @@
 msgid "could not open '%s' for reading"
 msgstr "無法開啟 “%s” 進行讀取"
 
-#: builtin/am.c builtin/rebase.c sequencer.c strbuf.c wrapper.c
+#: builtin/am.c builtin/rebase.c editor.c sequencer.c wrapper.c
 #, c-format
 msgid "could not open '%s' for writing"
 msgstr "無法開啟 “%s” 進行寫入"
@@ -2545,7 +2593,7 @@
 "您似乎在上一次 “am” 失敗後移動了 HEAD。\n"
 "未倒轉回 ORIG_HEAD"
 
-#: builtin/am.c builtin/bisect--helper.c worktree.c
+#: builtin/am.c builtin/bisect.c worktree.c
 #, c-format
 msgid "failed to read '%s'"
 msgstr "無法讀取 “%s”"
@@ -2568,6 +2616,10 @@
 msgstr "互動式執行"
 
 #: builtin/am.c
+msgid "bypass pre-applypatch and applypatch-msg hooks"
+msgstr "繞過 pre-applypatch 和 applypatch-msg 掛鉤"
+
+#: builtin/am.c
 msgid "historical option -- no-op"
 msgstr "歷史遺留選項——無作用"
 
@@ -2586,7 +2638,7 @@
 
 #: builtin/am.c
 msgid "recode into utf8 (default)"
-msgstr "使用 utf8 字元集(預設)"
+msgstr "使用 utf8 字元集(預設值)"
 
 #: builtin/am.c
 msgid "pass -k flag to git-mailinfo"
@@ -2756,111 +2808,105 @@
 msgid "git archive: expected a flush"
 msgstr "git archive:預期收到 flush 封包"
 
-#: builtin/bisect--helper.c
-msgid "git bisect--helper --bisect-reset [<commit>]"
-msgstr "git bisect--helper --bisect-reset [<commit>]"
-
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid ""
-"git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}"
-"=<term>] [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
-"[<paths>...]"
+"git bisect start [--term-{new,bad}=<term> --term-{old,good}=<term>]    [--no-"
+"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
 msgstr ""
-"git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}"
-"=<term>] [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
-"[<paths>...]"
+"git bisect start [--term-{new,bad}=<term> --term-{old,good}=<term>]    [--no-"
+"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
 
-#: builtin/bisect--helper.c
-msgid "git bisect--helper --bisect-state (bad|new) [<rev>]"
-msgstr "git bisect--helper --bisect-state (bad|new) [<rev>]"
+#: builtin/bisect.c
+msgid "git bisect (good|bad) [<rev>...]"
+msgstr "git bisect (good|bad) [<rev>...]"
 
-#: builtin/bisect--helper.c
-msgid "git bisect--helper --bisect-state (good|old) [<rev>...]"
-msgstr "git bisect--helper --bisect-state (good|old) [<rev>...]"
+#: builtin/bisect.c
+msgid "git bisect skip [(<rev>|<range>)...]"
+msgstr "git bisect skip [(<rev>|<range>)...]"
 
-#: builtin/bisect--helper.c
-msgid "git bisect--helper --bisect-replay <filename>"
-msgstr "git bisect--helper --bisect-replay <filename>"
+#: builtin/bisect.c
+msgid "git bisect reset [<commit>]"
+msgstr "git bisect reset [<commit>]"
 
-#: builtin/bisect--helper.c
-msgid "git bisect--helper --bisect-skip [(<rev>|<range>)...]"
-msgstr "git bisect--helper --bisect-skip [(<rev>|<range>)...]"
+#: builtin/bisect.c
+msgid "git bisect replay <logfile>"
+msgstr "git bisect replay <logfile>"
 
-#: builtin/bisect--helper.c
-msgid "git bisect--helper --bisect-run <cmd>..."
-msgstr "git bisect--helper --bisect-run <cmd>..."
+#: builtin/bisect.c
+msgid "git bisect run <cmd>..."
+msgstr "git bisect run <cmd>..."
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "cannot open file '%s' in mode '%s'"
 msgstr "無法以 “%2$s” 模式開啟 “%1$s” 檔案"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "could not write to file '%s'"
 msgstr "無法寫入 “%s” 檔案"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "cannot open file '%s' for reading"
 msgstr "無法開啟 “%s” 檔案進行讀取"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "'%s' is not a valid term"
 msgstr "“%s” 不是有效術語"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "can't use the builtin command '%s' as a term"
 msgstr "不能將內建命令 “%s” 當作術語使用"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "can't change the meaning of the term '%s'"
 msgstr "不能變更術語 “%s” 的含義"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "please use two different terms"
 msgstr "請使用兩個不同的術語"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "We are not bisecting.\n"
 msgstr "我們沒有在二分搜尋。\n"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "'%s' is not a valid commit"
 msgstr "“%s” 不是有效的提交"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid ""
 "could not check out original HEAD '%s'. Try 'git bisect reset <commit>'."
 msgstr "不能簽出原始 HEAD “%s”。請嘗試 “git bisect reset <commit>”。"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "Bad bisect_write argument: %s"
 msgstr "bisect_write 引數無效:%s"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "couldn't get the oid of the rev '%s'"
 msgstr "無法取得修訂版 “%s” 的物件 ID"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "couldn't open the file '%s'"
 msgstr "無法開啟檔案 “%s”"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "Invalid command: you're currently in a %s/%s bisect"
 msgstr "命令無效:您目前正處於二分搜尋 %s/%s 的狀態"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid ""
 "You need to give me at least one %s and %s revision.\n"
@@ -2869,7 +2915,7 @@
 "需指定至少一個 %s 和一個 %s 修訂版。\n"
 "為此您可以用 “git bisect %s” 和 “git bisect %s”。"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid ""
 "You need to start by \"git bisect start\".\n"
@@ -2880,7 +2926,7 @@
 "接著提供至少一個 %s 和一個 %s 修訂版。\n"
 "為此您可以用 “git bisect %s” 和 “git bisect %s”。"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "bisecting only with a %s commit"
 msgstr "在只有一個 %s 提交的情況下二分搜尋"
@@ -2890,29 +2936,29 @@
 #. translation. The program will only accept English input
 #. at this point.
 #.
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "Are you sure [Y/n]? "
 msgstr "是否確定 [Y/n]? "
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "status: waiting for both good and bad commits\n"
 msgstr "狀態:正在等待好和壞的提交\n"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "status: waiting for bad commit, %d good commit known\n"
 msgid_plural "status: waiting for bad commit, %d good commits known\n"
 msgstr[0] "狀態:正在等待壞的提交,已知有 %d 個好的提交\n"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "status: waiting for good commit(s), bad commit known\n"
 msgstr "狀態:正在等待好的提交,已知有壞的提交\n"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "no terms defined"
 msgstr "未定義術語"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid ""
 "Your current terms are %s for the old state\n"
@@ -2921,7 +2967,7 @@
 "您目前針對舊狀態的術語是 %s;\n"
 "對新狀態的術語是 %s。\n"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid ""
 "invalid argument %s for 'git bisect terms'.\n"
@@ -2930,52 +2976,48 @@
 "傳入 “git bisect terms” 的 %s 引數無效。\n"
 "支援的選項有:--term-good|--term-old 和 --term-bad|--term-new。"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "revision walk setup failed\n"
 msgstr "修訂版遍歷設定失敗\n"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "could not open '%s' for appending"
 msgstr "無法開啟 “%s” 進行附加"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "'' is not a valid term"
 msgstr "“ ” 不是有效術語"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "unrecognized option: '%s'"
 msgstr "無法識別選項:“%s”"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "'%s' does not appear to be a valid revision"
 msgstr "“%s” 似乎不是有效修訂版"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "bad HEAD - I need a HEAD"
 msgstr "HEAD 無效 — 需要一個 HEAD"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "checking out '%s' failed. Try 'git bisect start <valid-branch>'."
 msgstr "簽出 “%s” 失敗。請嘗試 “git bisect start <valid-branch>”。"
 
-#: builtin/bisect--helper.c
-msgid "won't bisect on cg-seek'ed tree"
-msgstr "不會在做了 cg-seek 的樹狀物件上進行二分搜尋"
-
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "bad HEAD - strange symbolic ref"
 msgstr "HEAD 無效 — 異常符號引用"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "invalid ref: '%s'"
 msgstr "引用無效:“%s”"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "You need to start by \"git bisect start\"\n"
 msgstr "要開始,請執行 “git bisect start”\n"
 
@@ -2984,151 +3026,159 @@
 #. translation. The program will only accept English input
 #. at this point.
 #.
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "Do you want me to do it for you [Y/n]? "
 msgstr "是否要這麼做 [Y/n]? "
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "Please call `--bisect-state` with at least one argument"
 msgstr "要呼叫 `--bisect-state`,請傳入一個以上的引數"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "'git bisect %s' can take only one argument."
 msgstr "“git bisect %s” 只取一個引數。"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "Bad rev input: %s"
 msgstr "rev 輸入格式錯誤:%s"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "Bad rev input (not a commit): %s"
 msgstr "rev 輸入有誤(不是提交):%s"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "We are not bisecting."
 msgstr "我們沒有在二分搜尋。"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "'%s'?? what are you talking about?"
 msgstr "「%s」??您在說什麼?"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "cannot read file '%s' for replaying"
 msgstr "無法讀取「%s」檔案進行重放"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "running %s\n"
 msgstr "正在執行 %s\n"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "bisect run failed: no command provided."
 msgstr "二分搜尋執行失敗:沒有提供命令。"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
-msgid "unable to verify '%s' on good revision"
-msgstr "無法在好的修訂版上驗證 “%s”"
+msgid "unable to verify %s on good revision"
+msgstr "無法在好的修訂版上驗證 %s"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "bogus exit code %d for good revision"
 msgstr "好的修訂版回傳偽造的錯誤碼 %d"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
-msgid "bisect run failed: exit code %d from '%s' is < 0 or >= 128"
-msgstr "二分搜尋執行失敗:“%2$s” 回傳的離開碼 %1$d 小於 0 或 >= 128"
+msgid "bisect run failed: exit code %d from %s is < 0 or >= 128"
+msgstr "二分搜尋執行失敗:%2$s 回傳的離開碼 %1$d 小於 0 或大於 128"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
 msgid "cannot open file '%s' for writing"
 msgstr "無法開啟 “%s” 檔案進行寫入"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "bisect run cannot continue any more"
 msgstr "二分搜尋不能繼續執行"
 
-#: builtin/bisect--helper.c
-#, c-format
+#: builtin/bisect.c
 msgid "bisect run success"
 msgstr "二分搜尋執行成功"
 
-#: builtin/bisect--helper.c
-#, c-format
+#: builtin/bisect.c
 msgid "bisect found first bad commit"
 msgstr "二分搜尋發現到第一個有問題的提交"
 
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 #, c-format
-msgid ""
-"bisect run failed: 'git bisect--helper --bisect-state %s' exited with error "
-"code %d"
-msgstr ""
-"二分搜尋執行失敗:“git bisect--helper --bisect-state %s” 以錯誤碼 %d 離開"
+msgid "bisect run failed: 'git bisect %s' exited with error code %d"
+msgstr "二分搜尋執行失敗:“git bisect %s” 以錯誤碼 %d 離開"
 
-#: builtin/bisect--helper.c
-msgid "--bisect-reset requires either no argument or a commit"
-msgstr "--bisect-reset 可以不需要引數,或者得傳入一個提交"
+#: builtin/bisect.c
+#, c-format
+msgid "'%s' requires either no argument or a commit"
+msgstr "“%s” 不需要引數,或者得傳入一個提交"
 
-#: builtin/bisect--helper.c
-msgid "--bisect-terms requires 0 or 1 argument"
-msgstr "--bisect-terms 需要 0 或 1 個引數"
+#: builtin/bisect.c
+#, c-format
+msgid "'%s' requires 0 or 1 argument"
+msgstr "“%s” 需要 0 或 1 個引數"
 
-#: builtin/bisect--helper.c
-msgid "--bisect-next requires 0 arguments"
-msgstr "--bisect-next 需要 0 個引數"
+#: builtin/bisect.c
+#, c-format
+msgid "'%s' requires 0 arguments"
+msgstr "“%s” 不需引數"
 
-#: builtin/bisect--helper.c
-msgid "--bisect-log requires 0 arguments"
-msgstr "--bisect-log 需要 0 個引數"
-
-#: builtin/bisect--helper.c
+#: builtin/bisect.c
 msgid "no logfile given"
 msgstr "未提供日誌檔案"
 
+#: builtin/bisect.c
+#, c-format
+msgid "'%s' failed: no command provided."
+msgstr "“%s” 失敗:沒有提供命令。"
+
+#: builtin/bisect.c
+msgid "need a command"
+msgstr "需要提供命令"
+
+#: builtin/bisect.c builtin/cat-file.c
+#, c-format
+msgid "unknown command: '%s'"
+msgstr "未知命令:“%s”"
+
 #: builtin/blame.c
 msgid "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"
-msgstr "git blame [<選項>] [<版本選項>] [<版本>] [--] <檔案>"
+msgstr "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"
 
 #: builtin/blame.c
 msgid "git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>"
-msgstr "git annotate [<選項>] [<版本選項>] [<版本>] [--] <檔案>"
+msgstr "git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>"
 
 #: builtin/blame.c
 msgid "<rev-opts> are documented in git-rev-list(1)"
-msgstr "<版本選項> 的檔案記錄在 git-rev-list(1) 中"
+msgstr "<rev-opts> 的文件在 git-rev-list(1)"
 
 #: builtin/blame.c
 #, c-format
 msgid "expecting a color: %s"
-msgstr "期望一個顏色:%s"
+msgstr "預期是個顏色:%s"
 
 #: builtin/blame.c
 msgid "must end with a color"
-msgstr "必須以一個顏色結尾"
+msgstr "結尾必須是一個顏色"
 
 #: builtin/blame.c
 #, c-format
 msgid "cannot find revision %s to ignore"
-msgstr "不能找到要忽略的版本 %s"
+msgstr "不能找到要忽略的 %s 修訂版"
 
 #: builtin/blame.c
 msgid "show blame entries as we find them, incrementally"
-msgstr "增量式顯示發現的 blame 條目"
+msgstr "漸進式顯示發現的溯源項目"
 
 #: builtin/blame.c
 msgid "do not show object names of boundary commits (Default: off)"
-msgstr "不要顯示邊界提交的物件名稱(預設值: off)"
+msgstr "不要顯示邊界提交的物件名稱(預設值:off)"
 
 #: builtin/blame.c
 msgid "do not treat root commits as boundaries (Default: off)"
-msgstr "不將根提交看作邊界(預設值:off)"
+msgstr "不把根提交當作邊界(預設值:off)"
 
 #: builtin/blame.c
 msgid "show work cost statistics"
@@ -3142,7 +3192,7 @@
 
 #: builtin/blame.c
 msgid "show output score for blame entries"
-msgstr "顯示判斷 blame 條目位移的得分診斷訊息"
+msgstr "顯示溯源項目的輸出得分"
 
 #: builtin/blame.c
 msgid "show original filename (Default: auto)"
@@ -3150,7 +3200,7 @@
 
 #: builtin/blame.c
 msgid "show original linenumber (Default: off)"
-msgstr "顯示原始檔案名稱(預設值:off)"
+msgstr "顯示原始列碼(預設值:off)"
 
 #: builtin/blame.c
 msgid "show in a format designed for machine consumption"
@@ -3158,7 +3208,7 @@
 
 #: builtin/blame.c
 msgid "show porcelain format with per-line commit information"
-msgstr "顯示每一列適合機器的提交說明"
+msgstr "顯示包含每一列提交資訊,適合機器讀取的格式"
 
 #: builtin/blame.c
 msgid "use the same output mode as git-annotate (Default: off)"
@@ -3186,15 +3236,15 @@
 
 #: builtin/blame.c builtin/log.c
 msgid "rev"
-msgstr "版本"
+msgstr "rev"
 
 #: builtin/blame.c
 msgid "ignore <rev> when blaming"
-msgstr "在執行 blame 動作時忽略 <修訂版>"
+msgstr "在執行溯源動作時忽略 <rev>"
 
 #: builtin/blame.c
 msgid "ignore revisions from <file>"
-msgstr "忽略 <檔案> 中的修訂版"
+msgstr "忽略 <file> 中的修訂版"
 
 #: builtin/blame.c
 msgid "color redundant metadata from previous line differently"
@@ -3202,31 +3252,31 @@
 
 #: builtin/blame.c
 msgid "color lines by age"
-msgstr "依據時間著色"
+msgstr "根據時間著色"
 
 #: builtin/blame.c
 msgid "spend extra cycles to find better match"
-msgstr "循環更多次以找到更佳符合"
+msgstr "循環更多次來找到更佳符合項目"
 
 #: builtin/blame.c
 msgid "use revisions from <file> instead of calling git-rev-list"
-msgstr "使用來自 <檔案> 的修訂集而不是呼叫 git-rev-list"
+msgstr "使用來自 <file> 的修訂集而不是呼叫 git-rev-list"
 
 #: builtin/blame.c
 msgid "use <file>'s contents as the final image"
-msgstr "將 <檔案> 的內容當成是最終 image"
+msgstr "將 <file> 的內容當成是最終印象"
 
 #: builtin/blame.c
 msgid "score"
-msgstr "得分"
+msgstr "score"
 
 #: builtin/blame.c
 msgid "find line copies within and across files"
-msgstr "找到檔案內及跨檔案的複製列"
+msgstr "找到檔案內及跨檔案的列拷貝動作"
 
 #: builtin/blame.c
 msgid "find line movements within and across files"
-msgstr "找到檔案內及跨檔案的移動列"
+msgstr "找到檔案內及跨檔案的列移動動作"
 
 #: builtin/blame.c
 msgid "range"
@@ -3256,45 +3306,47 @@
 #, c-format
 msgid "file %s has only %lu line"
 msgid_plural "file %s has only %lu lines"
-msgstr[0] "檔案 %s 只有 %lu 行"
+msgstr[0] "檔案 %s 只有 %lu 列"
 
 #: builtin/blame.c
 msgid "Blaming lines"
-msgstr "追蹤程式碼行"
+msgstr "溯源文字列"
 
 #: builtin/branch.c
 msgid "git branch [<options>] [-r | -a] [--merged] [--no-merged]"
-msgstr "git branch [<選項>] [-r | -a] [--merged] [--no-merged]"
+msgstr "git branch [<options>] [-r | -a] [--merged] [--no-merged]"
 
 #: builtin/branch.c
 msgid ""
 "git branch [<options>] [-f] [--recurse-submodules] <branch-name> [<start-"
 "point>]"
-msgstr "git branch [<選項>] [-f] [--recurse-submodules] <分支名> [<起始點>]"
+msgstr ""
+"git branch [<options>] [-f] [--recurse-submodules] <branch-name> [<start-"
+"point>]"
 
 #: builtin/branch.c
 msgid "git branch [<options>] [-l] [<pattern>...]"
-msgstr "git branch [<選項>] [-l] [<模式>...]"
+msgstr "git branch [<options>] [-l] [<pattern>...]"
 
 #: builtin/branch.c
 msgid "git branch [<options>] [-r] (-d | -D) <branch-name>..."
-msgstr "git branch [<選項>] [-r] (-d | -D) <分支名>..."
+msgstr "git branch [<options>] [-r] (-d | -D) <branch-name>..."
 
 #: builtin/branch.c
 msgid "git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"
-msgstr "git branch [<選項>] (-m | -M) [<舊分支>] <新分支>"
+msgstr "git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"
 
 #: builtin/branch.c
 msgid "git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"
-msgstr "git branch [<選項>] (-c | -C) [<老分支>] <新分支>"
+msgstr "git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"
 
 #: builtin/branch.c
 msgid "git branch [<options>] [-r | -a] [--points-at]"
-msgstr "git branch [<選項>] [-r | -a] [--points-at]"
+msgstr "git branch [<options>] [-r | -a] [--points-at]"
 
 #: builtin/branch.c
 msgid "git branch [<options>] [-r | -a] [--format]"
-msgstr "git branch [<選項>] [-r | -a] [--format]"
+msgstr "git branch [<options>] [-r | -a] [--format]"
 
 #  譯者:保持原換行格式,在輸出時 %s 的替代內容會讓字串變長
 #: builtin/branch.c
@@ -3303,8 +3355,8 @@
 "deleting branch '%s' that has been merged to\n"
 "         '%s', but not yet merged to HEAD."
 msgstr ""
-"將要刪除的分支 '%s' 已經被合併到\n"
-"         '%s',但未合併到 HEAD。"
+"將要刪除的 “%s” 分支已經被合併到\n"
+"         “%s”,但尚未合併到 HEAD。"
 
 #  譯者:保持原換行格式,在輸出時 %s 的替代內容會讓字串變長
 #: builtin/branch.c
@@ -3313,13 +3365,13 @@
 "not deleting branch '%s' that is not yet merged to\n"
 "         '%s', even though it is merged to HEAD."
 msgstr ""
-"並未刪除分支 '%s', 雖然它已經合併到 HEAD,\n"
-"         然而卻尚未被合併到分支 '%s' 。"
+"並未刪除分支 “%s”, 雖然已經合併到 HEAD,\n"
+"         卻尚未被合併至 “%s” 分支。"
 
 #: builtin/branch.c
 #, c-format
 msgid "Couldn't look up commit object for '%s'"
-msgstr "無法查詢 '%s' 指向的提交物件"
+msgstr "無法查詢 “%s” 指向的提交物件"
 
 #: builtin/branch.c
 #, c-format
@@ -3327,12 +3379,12 @@
 "The branch '%s' is not fully merged.\n"
 "If you are sure you want to delete it, run 'git branch -D %s'."
 msgstr ""
-"分支 '%s' 沒有完全合併。\n"
-"如果您確認要刪除它,執行 'git branch -D %s'。"
+"分支 “%s” 沒有完全合併。\n"
+"如果確定要刪除它,請執行 “git branch -D %s”。"
 
 #: builtin/branch.c
 msgid "Update of config-file failed"
-msgstr "更新設定檔案失敗"
+msgstr "更新組態檔案失敗"
 
 #: builtin/branch.c
 msgid "cannot use -a with -d"
@@ -3341,17 +3393,26 @@
 #: builtin/branch.c
 #, c-format
 msgid "Cannot delete branch '%s' checked out at '%s'"
-msgstr "無法刪除在「%2$s」簽出的「%1$s」分支"
+msgstr "無法刪除在 “%2$s” 簽出的 “%1$s” 分支"
 
 #: builtin/branch.c
 #, c-format
 msgid "remote-tracking branch '%s' not found."
-msgstr "未能找到遠端追蹤分支 '%s'。"
+msgstr "找不到 “%s” 遠端追蹤分支。"
+
+#: builtin/branch.c
+#, c-format
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"找不到 “%s” 分支。\n"
+"您可能要加上 --remote?"
 
 #: builtin/branch.c
 #, c-format
 msgid "branch '%s' not found."
-msgstr "分支 '%s' 未發現。"
+msgstr "找不到 “%s” 分支。"
 
 #: builtin/branch.c
 #, c-format
@@ -3365,41 +3426,46 @@
 
 #: builtin/branch.c builtin/tag.c
 msgid "unable to parse format string"
-msgstr "不能解析格式化字串"
+msgstr "無法解析格式化字串"
 
 #: builtin/branch.c
 msgid "could not resolve HEAD"
-msgstr "不能解析 HEAD 提交"
+msgstr "無法解析 HEAD 指針"
 
 #: builtin/branch.c
 #, c-format
 msgid "HEAD (%s) points outside of refs/heads/"
-msgstr "HEAD (%s) 指向 refs/heads/ 之外"
+msgstr "HEAD 指針 (%s) 指向 refs/heads/ 之外"
 
 #: builtin/branch.c
 #, c-format
 msgid "Branch %s is being rebased at %s"
-msgstr "分支 %s 正被重定基底到 %s"
+msgstr "%s 分支正在重定基底至 %s"
 
 #: builtin/branch.c
 #, c-format
 msgid "Branch %s is being bisected at %s"
-msgstr "分支 %s 正被二分搜尋於 %s"
+msgstr "%s 分支正於 %s 進行二分搜尋"
+
+#: builtin/branch.c
+#, c-format
+msgid "HEAD of working tree %s is not updated"
+msgstr "%s 工作區的 HEAD 指針未被更新"
 
 #: builtin/branch.c
 #, c-format
 msgid "Invalid branch name: '%s'"
-msgstr "無效的分支名:'%s'"
+msgstr "分支名稱無效:“%s”"
 
 #: builtin/branch.c
 #, c-format
 msgid "No commit on branch '%s' yet."
-msgstr "分支 '%s' 尚無提交。"
+msgstr "分支 “%s” 尚無提交。"
 
 #: builtin/branch.c
 #, c-format
 msgid "No branch named '%s'."
-msgstr "沒有分支 '%s'。"
+msgstr "沒有名為 “%s” 的分支。"
 
 #: builtin/branch.c
 msgid "Branch rename failed"
@@ -3407,30 +3473,30 @@
 
 #: builtin/branch.c
 msgid "Branch copy failed"
-msgstr "分支複製失敗"
+msgstr "分支拷貝失敗"
 
 #: builtin/branch.c
 #, c-format
 msgid "Created a copy of a misnamed branch '%s'"
-msgstr "已為錯誤命名的分支 '%s' 建立了一個副本"
+msgstr "已為誤命名的 “%s” 分支建立拷貝"
 
 #: builtin/branch.c
 #, c-format
 msgid "Renamed a misnamed branch '%s' away"
-msgstr "已將錯誤命名的分支 '%s' 重新命名"
+msgstr "已更改誤命名的 “%s” 分支的名稱"
 
 #: builtin/branch.c
 #, c-format
 msgid "Branch renamed to %s, but HEAD is not updated!"
-msgstr "分支重新命名為 %s,但 HEAD 沒有更新!"
+msgstr "分支已重新命名為 %s,但 HEAD 指針尚未更新!"
 
 #: builtin/branch.c
 msgid "Branch is renamed, but update of config-file failed"
-msgstr "分支被重新命名,但更新設定檔案失敗"
+msgstr "分支已重新命名,但無法更新組態檔案"
 
 #: builtin/branch.c
 msgid "Branch is copied, but update of config-file failed"
-msgstr "分支已複製,但更新設定檔案失敗"
+msgstr "分支已拷貝,但無法更新組態檔案"
 
 #: builtin/branch.c
 #, c-format
@@ -3439,41 +3505,41 @@
 "  %s\n"
 "Lines starting with '%c' will be stripped.\n"
 msgstr ""
-"請編輯分支的描述\n"
+"請編輯下述分支的描述\n"
 "  %s\n"
-"以 '%c' 開頭的行將被過濾。\n"
+"開頭是 “%c” 的列將被刪除。\n"
 
 #: builtin/branch.c
 msgid "Generic options"
-msgstr "通用選項"
+msgstr "一般性選項"
 
 #: builtin/branch.c
 msgid "show hash and subject, give twice for upstream branch"
-msgstr "顯示雜湊值和主題,若參數出現兩次則顯示上游分支"
+msgstr "顯示雜湊值和主旨,若傳入兩次則顯示上游分支"
 
 #: builtin/branch.c
 msgid "suppress informational messages"
-msgstr "不顯示訊息"
+msgstr "不顯示資訊訊息"
 
 #: builtin/branch.c builtin/checkout.c builtin/submodule--helper.c
 msgid "set branch tracking configuration"
-msgstr "設定分支追蹤設定"
+msgstr "設定分支追蹤組態"
 
 #: builtin/branch.c
 msgid "do not use"
-msgstr "不要使用"
+msgstr "請勿使用"
 
 #: builtin/branch.c
 msgid "upstream"
-msgstr "上游"
+msgstr "upstream"
 
 #: builtin/branch.c
 msgid "change the upstream info"
-msgstr "改變上游訊息"
+msgstr "變更上游資訊"
 
 #: builtin/branch.c
 msgid "unset the upstream info"
-msgstr "取消上游資訊設定"
+msgstr "取消設定上游資訊"
 
 #: builtin/branch.c
 msgid "use colored output"
@@ -3485,19 +3551,19 @@
 
 #: builtin/branch.c
 msgid "print only branches that contain the commit"
-msgstr "只列印包含該提交的分支"
+msgstr "只輸出包含此提交的分支"
 
 #: builtin/branch.c
 msgid "print only branches that don't contain the commit"
-msgstr "只列印不包含該提交的分支"
+msgstr "只輸出不包含此提交的分支"
 
 #: builtin/branch.c
 msgid "Specific git-branch actions:"
-msgstr "具體的 git-branch 動作:"
+msgstr "特定的 git-branch 動作:"
 
 #: builtin/branch.c
 msgid "list both remote-tracking and local branches"
-msgstr "列出遠端追蹤及本機分支"
+msgstr "列出遠端追蹤和本機分支"
 
 #: builtin/branch.c
 msgid "delete fully merged branch"
@@ -3505,31 +3571,35 @@
 
 #: builtin/branch.c
 msgid "delete branch (even if not merged)"
-msgstr "刪除分支(即使沒有合併)"
+msgstr "刪除分支(即使尚未合併)"
 
 #: builtin/branch.c
 msgid "move/rename a branch and its reflog"
-msgstr "移動/重新命名一個分支,以及它的引用日誌"
+msgstr "移動或重新命名分支及其引用日誌"
 
 #: builtin/branch.c
 msgid "move/rename a branch, even if target exists"
-msgstr "移動/重新命名一個分支,即使目標已存在"
+msgstr "即使目標已存在,仍移動或重新命名分支"
+
+#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c
+msgid "do not output a newline after empty formatted refs"
+msgstr "在格式化引用結果為空之後,不要輸出換列符號"
 
 #: builtin/branch.c
 msgid "copy a branch and its reflog"
-msgstr "複製分支及其引用日誌"
+msgstr "拷貝分支及其引用日誌"
 
 #: builtin/branch.c
 msgid "copy a branch, even if target exists"
-msgstr "複製一個分支,即使目標已存在"
+msgstr "即使目標已存在仍拷貝分支"
 
 #: builtin/branch.c
 msgid "list branch names"
-msgstr "列出分支名"
+msgstr "列出分支名稱"
 
 #: builtin/branch.c
 msgid "show current branch name"
-msgstr "顯示目前分支名"
+msgstr "顯示目前分支名稱"
 
 #: builtin/branch.c builtin/submodule--helper.c
 msgid "create the branch's reflog"
@@ -3537,7 +3607,7 @@
 
 #: builtin/branch.c
 msgid "edit the description for the branch"
-msgstr "標記分支的描述"
+msgstr "編輯分支的描述"
 
 #: builtin/branch.c
 msgid "force creation, move/rename, deletion"
@@ -3545,27 +3615,27 @@
 
 #: builtin/branch.c
 msgid "print only branches that are merged"
-msgstr "只列印已經合併的分支"
+msgstr "只輸出已經合併的分支"
 
 #: builtin/branch.c
 msgid "print only branches that are not merged"
-msgstr "只列印尚未合併的分支"
+msgstr "只輸出尚未合併的分支"
 
 #: builtin/branch.c
 msgid "list branches in columns"
-msgstr "以列的方式顯示分支"
+msgstr "以行的形式列出分支"
 
 #: builtin/branch.c builtin/for-each-ref.c builtin/notes.c builtin/tag.c
 msgid "object"
-msgstr "物件"
+msgstr "object"
 
 #: builtin/branch.c
 msgid "print only branches of the object"
-msgstr "只列印指向該物件的分支"
+msgstr "只輸出指向此物件的分支"
 
 #: builtin/branch.c builtin/for-each-ref.c builtin/tag.c
 msgid "sorting and filtering are case insensitive"
-msgstr "排序和過濾屬於大小寫不敏感"
+msgstr "排序和過濾不區分大小寫"
 
 #: builtin/branch.c builtin/ls-files.c
 msgid "recurse through submodules"
@@ -3582,14 +3652,14 @@
 
 #: builtin/branch.c builtin/clone.c
 msgid "HEAD not found below refs/heads!"
-msgstr "HEAD 沒有位於 /refs/heads 之下!"
+msgstr "HEAD 指針不在 /refs/heads 中!"
 
 #: builtin/branch.c
 msgid ""
 "branch with --recurse-submodules can only be used if submodule."
 "propagateBranches is enabled"
 msgstr ""
-"有 --recurse-submodules 的分支只能在啟用 submodule.propagateBranches 時使用"
+"有 --recurse-submodules 的分支,只能在啟用 submodule.propagateBranches 時使用"
 
 #: builtin/branch.c
 msgid "--recurse-submodules can only be used to create branches"
@@ -3597,79 +3667,79 @@
 
 #: builtin/branch.c
 msgid "branch name required"
-msgstr "必須提供分支名"
+msgstr "必須提供分支名稱"
 
 #: builtin/branch.c
 msgid "Cannot give description to detached HEAD"
-msgstr "不能向分離開頭指標提供描述"
+msgstr "無法向分離 HEAD 指針提供描述"
 
 #: builtin/branch.c
 msgid "cannot edit description of more than one branch"
-msgstr "不能為一個以上的分支編輯描述"
+msgstr "無法編輯超過一個分支的描述"
 
 #: builtin/branch.c
 msgid "cannot copy the current branch while not on any."
-msgstr "無法複製目前分支因為不處於任何分支上。"
+msgstr "不在任何分支上,無法拷貝目前分支。"
 
 #: builtin/branch.c
 msgid "cannot rename the current branch while not on any."
-msgstr "無法重新命名目前分支因為不處於任何分支上。"
+msgstr "不在任何分支上,無法重新命名目前分支。"
 
 #: builtin/branch.c
 msgid "too many branches for a copy operation"
-msgstr "為複製動作提供了太多的分支名"
+msgstr "要進行拷貝動作的分支太多"
 
 #: builtin/branch.c
 msgid "too many arguments for a rename operation"
-msgstr "為重新命名動作提供了太多的參數"
+msgstr "傳入重新命名動作的引數太多"
 
 #: builtin/branch.c
 msgid "too many arguments to set new upstream"
-msgstr "為設定新上游提供了太多的參數"
+msgstr "要設定新上游的引數太多"
 
 #: builtin/branch.c
 #, c-format
 msgid ""
 "could not set upstream of HEAD to %s when it does not point to any branch."
-msgstr "無法設定 HEAD 的上游為 %s,因為 HEAD 沒有指向任何分支。"
+msgstr "無法將 HEAD 的上游設為 %s:其未指向任何分支。"
 
 #: builtin/branch.c
 #, c-format
 msgid "no such branch '%s'"
-msgstr "沒有此分支 '%s'"
+msgstr "無 “%s” 分支"
 
 #: builtin/branch.c
 #, c-format
 msgid "branch '%s' does not exist"
-msgstr "分支 '%s' 不存在"
+msgstr "沒有 “%s” 分支"
 
 #: builtin/branch.c
 msgid "too many arguments to unset upstream"
-msgstr "為取消上游設定動作提供了太多的參數"
+msgstr "要取消設定上游的引數太多"
 
 #: builtin/branch.c
 msgid "could not unset upstream of HEAD when it does not point to any branch."
-msgstr "在 HEAD 的上游未指向任何分支時無法取消設定。"
+msgstr "無法取消設定 HEAD 的上游:其未指向任何分支。"
 
 #: builtin/branch.c
 #, c-format
 msgid "Branch '%s' has no upstream information"
-msgstr "分支 '%s' 沒有上游訊息"
+msgstr "分支 “%s” 沒有上游資訊"
 
 #: builtin/branch.c
 msgid ""
 "The -a, and -r, options to 'git branch' do not take a branch name.\n"
 "Did you mean to use: -a|-r --list <pattern>?"
 msgstr ""
-"'git branch' 的 -a 和 -r 選項不帶一個分支名。\n"
-"您是否想要使用:-a|-r --list <模式>?"
+"“git branch” 的 -a 和 -r 選項不取分支名稱。\n"
+"您是想使用:-a|-r --list <pattern> 嗎?"
 
 #: builtin/branch.c
 msgid ""
 "the '--set-upstream' option is no longer supported. Please use '--track' or "
 "'--set-upstream-to' instead."
 msgstr ""
-"不再支援選項 '--set-upstream'。請使用 '--track' 或 '--set-upstream-to'。"
+"不再支援選項 “--set-upstream”。請改用 “--track” 或 “--set-upstream-to”。"
 
 #: builtin/bugreport.c
 msgid "git version:\n"
@@ -3678,7 +3748,7 @@
 #: builtin/bugreport.c
 #, c-format
 msgid "uname() failed with error '%s' (%d)\n"
-msgstr "uname() 失敗,錯誤:「%s」(%d)\n"
+msgstr "uname() 失敗,錯誤:“%s” (%d)\n"
 
 #: builtin/bugreport.c
 msgid "compiler info: "
@@ -3690,7 +3760,7 @@
 
 #: builtin/bugreport.c
 msgid "not run from a git repository - no hooks to show\n"
-msgstr "不是從 git 版本庫執行 - 沒有可顯示的掛鉤\n"
+msgstr "不是在 git 版本庫執行 — 沒有可顯示的掛鉤\n"
 
 #: builtin/bugreport.c
 msgid ""
@@ -3719,15 +3789,15 @@
 "You can delete any lines you don't wish to share.\n"
 msgstr ""
 "感謝您填寫 Git 臭蟲報告!\n"
-"請回答下列問題,以讓我們能夠了解您的問題。\n"
+"請回答下列詢問,協助我們了解您的問題。\n"
 "\n"
 "臭蟲發生前,您做了什麼?(重現問題的步驟)\n"
 "\n"
-"你原本期望發生什麼?(期望行為)\n"
+"原本您預期發生什麼?(預期行為)\n"
 "\n"
 "那實際上發生了什麼?(實際行為)\n"
 "\n"
-"期望行為跟實際發生的行為有什麼不同?\n"
+"預期發生的行為,跟實際發生的行為有什麼不同?\n"
 "\n"
 "其他您想加入的:\n"
 "\n"
@@ -3737,25 +3807,25 @@
 #: builtin/bugreport.c builtin/commit.c builtin/fast-export.c builtin/rebase.c
 #: parse-options.h
 msgid "mode"
-msgstr "模式"
+msgstr "mode"
 
 #: builtin/bugreport.c
 msgid ""
 "create an additional zip archive of detailed diagnostics (default 'stats')"
-msgstr "建立詳細診斷資訊的額外 zip 封存檔案(預設值是 “stats”)"
+msgstr "另外建立有詳細診斷資訊的 ZIP 封存檔(預設值 “stats”)"
 
 #: builtin/bugreport.c
 msgid "specify a destination for the bugreport file(s)"
-msgstr "請指定臭蟲報告檔案的目的地"
+msgstr "指定臭蟲報告檔案的目的地"
 
 #: builtin/bugreport.c
 msgid "specify a strftime format suffix for the filename(s)"
-msgstr "指定檔名,strftime 格式的後綴"
+msgstr "指定用於檔名的 strftime 格式後綴"
 
 #: builtin/bugreport.c builtin/diagnose.c
 #, c-format
 msgid "could not create leading directories for '%s'"
-msgstr "無法建立 '%s' 的前置目錄"
+msgstr "無法建立 “%s” 的前置目錄"
 
 #: builtin/bugreport.c builtin/diagnose.c
 #, c-format
@@ -3778,16 +3848,14 @@
 #: builtin/bugreport.c
 #, c-format
 msgid "Created new report at '%s'.\n"
-msgstr "已在「%s」建立新報告。\n"
+msgstr "已在 “%s” 建立新報告。\n"
 
 #: builtin/bundle.c
 msgid ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"git bundle create [-q | --quiet | --progress | --all-progress] [--all-"
-"progress-implied]\n"
+"git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 
 #: builtin/bundle.c
@@ -3796,27 +3864,31 @@
 
 #: builtin/bundle.c
 msgid "git bundle list-heads <file> [<refname>...]"
-msgstr "git bundle list-heads <檔案> [<引用名稱>...]"
+msgstr "git bundle list-heads <file> [<refname>...]"
 
 #: builtin/bundle.c
 msgid "git bundle unbundle [--progress] <file> [<refname>...]"
 msgstr "git bundle unbundle [--progress] <file> [<refname>...]"
 
+#: builtin/bundle.c
+msgid "need a <file> argument"
+msgstr "需要提供 <file> 引數"
+
 #: builtin/bundle.c builtin/pack-objects.c
 msgid "do not show progress meter"
-msgstr "不顯示進度表"
+msgstr "不顯示進度列"
 
 #: builtin/bundle.c builtin/pack-objects.c
 msgid "show progress meter"
-msgstr "顯示進度表"
+msgstr "顯示進度列"
 
-#: builtin/bundle.c builtin/pack-objects.c
-msgid "show progress meter during object writing phase"
-msgstr "在物件寫入階段顯示進度表"
+#: builtin/bundle.c
+msgid "historical; same as --progress"
+msgstr "歷史遺留選項;和 --progress 相同"
 
-#: builtin/bundle.c builtin/pack-objects.c
-msgid "similar to --all-progress when progress meter is shown"
-msgstr "當進度表顯示時類似於 --all-progress"
+#: builtin/bundle.c
+msgid "historical; does nothing"
+msgstr "歷史遺留選項;沒有作用"
 
 #: builtin/bundle.c
 msgid "specify bundle format version"
@@ -3841,12 +3913,12 @@
 
 #: builtin/bundle.c
 msgid "Unbundling objects"
-msgstr "正在解包物件"
+msgstr "正在拆分物件"
 
 #: builtin/cat-file.c merge-recursive.c
 #, c-format
 msgid "cannot read object %s '%s'"
-msgstr "不能讀取物件 %s '%s'"
+msgstr "無法讀取物件 %s “%s”"
 
 #: builtin/cat-file.c
 msgid "flush is only for --buffer mode"
@@ -3859,7 +3931,7 @@
 #: builtin/cat-file.c
 #, c-format
 msgid "whitespace before command: '%s'"
-msgstr "命令前空格:「%s」"
+msgstr "命令前有空格:“%s”"
 
 #: builtin/cat-file.c
 #, c-format
@@ -3872,11 +3944,6 @@
 msgstr "%s 不取引數"
 
 #: builtin/cat-file.c
-#, c-format
-msgid "unknown command: '%s'"
-msgstr "未知命令:「%s」"
-
-#: builtin/cat-file.c
 msgid "only one batch option may be specified"
 msgstr "只能指定一個批次處理選項"
 
@@ -3926,7 +3993,7 @@
 
 #: builtin/cat-file.c
 msgid "Emit [broken] object attributes"
-msgstr "輸出 [損壞的] 物件屬性"
+msgstr "輸出 [損壞的] ([broken]) 物件屬性"
 
 #: builtin/cat-file.c
 msgid "show object type (one of 'blob', 'tree', 'commit', 'tag', ...)"
@@ -3958,15 +4025,15 @@
 
 #: builtin/cat-file.c
 msgid "stdin is NUL-terminated"
-msgstr "標準輸入以 NUL 字元終止"
+msgstr "stdin 以 NUL 字元終止"
 
 #: builtin/cat-file.c
 msgid "read commands from stdin"
-msgstr "從標準輸入讀取命令"
+msgstr "從 stdin 讀取命令"
 
 #: builtin/cat-file.c
 msgid "with --batch[-check]: ignores stdin, batches all known objects"
-msgstr "傳入 --batch[-check]:忽略標準輸入,批次處理所有已知物件"
+msgstr "傳入 --batch[-check]:忽略 stdin,批次處理所有已知物件"
 
 #: builtin/cat-file.c
 msgid "Change or optimize batch output"
@@ -3978,21 +4045,21 @@
 
 #: builtin/cat-file.c
 msgid "follow in-tree symlinks"
-msgstr "追蹤樹中的符號連結"
+msgstr "追蹤樹狀物件中的符號連結"
 
 #: builtin/cat-file.c
 msgid "do not order objects before emitting them"
-msgstr "不要在輸出物件前排序"
+msgstr "不要在輸出前排序物件"
 
 #: builtin/cat-file.c
 msgid ""
 "Emit object (blob or tree) with conversion or filter (stand-alone, or with "
 "batch)"
-msgstr "轉換或過濾後輸出物件(blob 或樹)(單獨或批次處理)"
+msgstr "轉換或過濾後輸出物件 (blob 或 tree)(單獨或批次處理)"
 
 #: builtin/cat-file.c
 msgid "run textconv on object's content"
-msgstr "在物件內容執行 textconv"
+msgstr "對物件內容進行文字轉換 (textconv)"
 
 #: builtin/cat-file.c
 msgid "run filters on object's content"
@@ -4009,7 +4076,7 @@
 #: builtin/cat-file.c
 #, c-format
 msgid "'%s=<%s>' needs '%s' or '%s'"
-msgstr "「%s=<%s>」需要「%s」或「%s」"
+msgstr "“%s=<%s>” 需要 “%s” 或 “%s”"
 
 #: builtin/cat-file.c
 msgid "path|tree-ish"
@@ -4018,12 +4085,12 @@
 #: builtin/cat-file.c
 #, c-format
 msgid "'%s' requires a batch mode"
-msgstr "「%s」需要批次處理模式"
+msgstr "“%s” 需要批次處理模式"
 
 #: builtin/cat-file.c
 #, c-format
 msgid "'-%c' is incompatible with batch mode"
-msgstr "「-%c」與批次處理模式不相容"
+msgstr "“-%c” 與批次處理模式不相容"
 
 #: builtin/cat-file.c
 msgid "batch modes take no arguments"
@@ -4032,12 +4099,12 @@
 #: builtin/cat-file.c
 #, c-format
 msgid "<rev> required with '%s'"
-msgstr "<rev> 需要搭配「%s」"
+msgstr "“%s” 需要 <rev>"
 
 #: builtin/cat-file.c
 #, c-format
 msgid "<object> required with '-%c'"
-msgstr "<object> 需要搭配「-%c」"
+msgstr "“-%c” 需要 <object>"
 
 #: builtin/cat-file.c
 #, c-format
@@ -4045,16 +4112,22 @@
 msgstr "只允許在 <type> <object> 模式傳入兩個引數,但傳了 %d 個"
 
 #: builtin/check-attr.c
-msgid "git check-attr [-a | --all | <attr>...] [--] <pathname>..."
-msgstr "git check-attr [-a | --all | <屬性>...] [--] <路徑名>..."
+msgid ""
+"git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] "
+"<pathname>..."
+msgstr ""
+"git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] "
+"<pathname>..."
 
 #: builtin/check-attr.c
-msgid "git check-attr --stdin [-z] [-a | --all | <attr>...]"
-msgstr "git check-attr --stdin [-z] [-a | --all | <屬性>...]"
+msgid ""
+"git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]"
+msgstr ""
+"git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]"
 
 #: builtin/check-attr.c
 msgid "report all attributes set on file"
-msgstr "報告設定在檔案上的所有屬性"
+msgstr "回報設定在檔案上的所有屬性"
 
 #: builtin/check-attr.c
 msgid "use .gitattributes only from the index"
@@ -4062,11 +4135,19 @@
 
 #: builtin/check-attr.c builtin/check-ignore.c builtin/hash-object.c
 msgid "read file names from stdin"
-msgstr "從標準輸入讀出檔案名"
+msgstr "從 stdin 讀出檔案名稱"
 
 #: builtin/check-attr.c builtin/check-ignore.c
 msgid "terminate input and output records by a NUL character"
-msgstr "輸入和輸出的紀錄使用 NUL 字元終結"
+msgstr "輸入和輸出的紀錄使用 NUL 字元終止"
+
+#: builtin/check-attr.c
+msgid "<tree-ish>"
+msgstr "<tree-ish>"
+
+#: builtin/check-attr.c
+msgid "which tree-ish to check attributes at"
+msgstr "要用哪一個樹狀物件檢查屬性"
 
 #: builtin/check-ignore.c builtin/checkout.c builtin/gc.c builtin/worktree.c
 msgid "suppress progress reporting"
@@ -4074,7 +4155,7 @@
 
 #: builtin/check-ignore.c
 msgid "show non-matching input paths"
-msgstr "顯示未符合的輸入路徑"
+msgstr "顯示不符合的輸入路徑"
 
 #: builtin/check-ignore.c
 msgid "ignore index when checking"
@@ -4082,11 +4163,11 @@
 
 #: builtin/check-ignore.c
 msgid "cannot specify pathnames with --stdin"
-msgstr "不能同時指定路徑及 --stdin 參數"
+msgstr "無法同時指定路徑名稱及 --stdin"
 
 #: builtin/check-ignore.c
 msgid "-z only makes sense with --stdin"
-msgstr "-z 需要和 --stdin 參數共用才有意義"
+msgstr "-z 需要和 --stdin 同時使用才有意義"
 
 #: builtin/check-ignore.c
 msgid "no path specified"
@@ -4094,11 +4175,11 @@
 
 #: builtin/check-ignore.c
 msgid "--quiet is only valid with a single pathname"
-msgstr "參數 --quiet 只在提供一個路徑名時有效"
+msgstr "引數 --quiet 只在提供一個路徑名稱時有效"
 
 #: builtin/check-ignore.c
 msgid "cannot have both --quiet and --verbose"
-msgstr "不能同時提供 --quiet 和 --verbose 參數"
+msgstr "無法同時傳入 --quiet 和 --verbose"
 
 #: builtin/check-ignore.c
 msgid "--non-matching is only valid with --verbose"
@@ -4106,41 +4187,41 @@
 
 #: builtin/check-mailmap.c
 msgid "git check-mailmap [<options>] <contact>..."
-msgstr "git check-mailmap [<選項>] <聯繫位址>..."
+msgstr "git check-mailmap [<options>] <contact>..."
 
 #: builtin/check-mailmap.c
 msgid "also read contacts from stdin"
-msgstr "還從標準輸入讀取聯繫位址"
+msgstr "亦從 stdin 讀取聯絡地址"
 
 #: builtin/check-mailmap.c
 #, c-format
 msgid "unable to parse contact: %s"
-msgstr "不能解析聯繫位址:%s"
+msgstr "無法解析聯絡地址:%s"
 
 #: builtin/check-mailmap.c
 msgid "no contacts specified"
-msgstr "未指定聯繫位址"
+msgstr "未指定聯絡地址"
 
 #: builtin/checkout--worker.c
 msgid "git checkout--worker [<options>]"
-msgstr "git checkout--worker [<選項>]"
+msgstr "git checkout--worker [<options>]"
 
 #: builtin/checkout--worker.c builtin/checkout-index.c builtin/column.c
 #: builtin/submodule--helper.c builtin/worktree.c
 msgid "string"
-msgstr "字串"
+msgstr "string"
 
 #: builtin/checkout--worker.c builtin/checkout-index.c
 msgid "when creating files, prepend <string>"
-msgstr "在建立檔案時,在前面加上 <字串>"
+msgstr "建立檔案時,在前面加上 <string>"
 
 #: builtin/checkout-index.c
 msgid "git checkout-index [<options>] [--] [<file>...]"
-msgstr "git checkout-index [<選項>] [--] [<檔案>...]"
+msgstr "git checkout-index [<options>] [--] [<file>...]"
 
 #: builtin/checkout-index.c
 msgid "stage should be between 1 and 3 or all"
-msgstr "索引值應該取值 1 到 3 或者 all"
+msgstr "stage 應該是 1 到 3 的值,或者是 all"
 
 #: builtin/checkout-index.c
 msgid "check out all files in the index"
@@ -4164,11 +4245,11 @@
 
 #: builtin/checkout-index.c
 msgid "update stat information in the index file"
-msgstr "更新索引中檔案的狀態訊息"
+msgstr "更新索引檔案的狀態訊息"
 
 #: builtin/checkout-index.c
 msgid "read list of paths from the standard input"
-msgstr "從標準輸入讀取路徑列表"
+msgstr "從標準輸入讀取路徑清單"
 
 #: builtin/checkout-index.c
 msgid "write the content to temporary files"
@@ -4180,49 +4261,49 @@
 
 #: builtin/checkout.c
 msgid "git checkout [<options>] <branch>"
-msgstr "git checkout [<選項>] <分支>"
+msgstr "git checkout [<options>] <branch>"
 
 #: builtin/checkout.c
 msgid "git checkout [<options>] [<branch>] -- <file>..."
-msgstr "git checkout [<選項>] [<分支>] -- <檔案>..."
+msgstr "git checkout [<options>] [<branch>] -- <file>..."
 
 #: builtin/checkout.c
 msgid "git switch [<options>] [<branch>]"
-msgstr "git switch [<選項>] [<分支>]"
+msgstr "git switch [<options>] [<branch>]"
 
 #: builtin/checkout.c
 msgid "git restore [<options>] [--source=<branch>] <file>..."
-msgstr "git restore [<選項>] [--source=<分支>] <檔案>..."
+msgstr "git restore [<options>] [--source=<branch>] <file>..."
 
 #: builtin/checkout.c
 #, c-format
 msgid "path '%s' does not have our version"
-msgstr "路徑 '%s' 沒有我們的版本"
+msgstr "“%s” 路徑沒有我們的版本"
 
 #: builtin/checkout.c
 #, c-format
 msgid "path '%s' does not have their version"
-msgstr "路徑 '%s' 沒有他們的版本"
+msgstr "“%s” 路徑沒有他們的版本"
 
 #: builtin/checkout.c
 #, c-format
 msgid "path '%s' does not have all necessary versions"
-msgstr "路徑 '%s' 沒有全部必需的版本"
+msgstr "“%s” 路徑沒有所有必須的版本"
 
 #: builtin/checkout.c
 #, c-format
 msgid "path '%s' does not have necessary versions"
-msgstr "路徑 '%s' 沒有必需的版本"
+msgstr "“%s” 路徑沒有必須的版本"
 
 #: builtin/checkout.c
 #, c-format
 msgid "path '%s': cannot merge"
-msgstr "path '%s':無法合併"
+msgstr "path “%s”:無法合併"
 
 #: builtin/checkout.c
 #, c-format
 msgid "Unable to add merge result for '%s'"
-msgstr "無法為 '%s' 新增合併結果"
+msgstr "無法為 “%s” 加上合併結果"
 
 #: builtin/checkout.c
 #, c-format
@@ -4240,41 +4321,41 @@
 #, c-format
 msgid "Updated %d path from the index"
 msgid_plural "Updated %d paths from the index"
-msgstr[0] "從索引區更新了 %d 個路徑"
+msgstr[0] "已從索引區更新 %d 個路徑"
 
 #: builtin/checkout.c
 #, c-format
 msgid "'%s' cannot be used with updating paths"
-msgstr "'%s' 不能在更新路徑時使用"
+msgstr "無法在更新路徑時使用 “%s”"
 
 #: builtin/checkout.c
 #, c-format
 msgid "Cannot update paths and switch to branch '%s' at the same time."
-msgstr "不能同時更新路徑並切換到分支'%s'。"
+msgstr "無法同時更新路徑和切換至 “%s” 分支。"
 
 #: builtin/checkout.c
 #, c-format
 msgid "neither '%s' or '%s' is specified"
-msgstr "'%s' 或 '%s' 都沒有指定"
+msgstr "“%s” 或 “%s” 皆未指定"
 
 #: builtin/checkout.c
 #, c-format
 msgid "'%s' must be used when '%s' is not specified"
-msgstr "未指定 '%2$s' 時,必須使用 '%1$s'"
+msgstr "未指定 “%2$s” 時,必須使用 “%1$s”"
 
 #: builtin/checkout.c
 #, c-format
 msgid "'%s' or '%s' cannot be used with %s"
-msgstr "'%s' 或 '%s' 不能和 %s 一起使用"
+msgstr "“%s” 或 “%s” 無法與 %s 一起使用"
 
 #: builtin/checkout.c
 #, c-format
 msgid "path '%s' is unmerged"
-msgstr "路徑 '%s' 未合併"
+msgstr "路徑 “%s” 未合併"
 
 #: builtin/checkout.c
 msgid "you need to resolve your current index first"
-msgstr "您需要先解決目前索引的衝突"
+msgstr "您需要先解決目前索引區的衝突"
 
 #: builtin/checkout.c
 #, c-format
@@ -4282,13 +4363,13 @@
 "cannot continue with staged changes in the following files:\n"
 "%s"
 msgstr ""
-"不能繼續,下列檔案有暫存的修改:\n"
+"無法繼續,下列檔案有暫存的更動:\n"
 "%s"
 
 #: builtin/checkout.c
 #, c-format
 msgid "Can not do reflog for '%s': %s\n"
-msgstr "不能對 '%s' 執行 reflog 動作:%s\n"
+msgstr "無法對 “%s” 執行 reflog 動作:%s\n"
 
 #: builtin/checkout.c
 msgid "HEAD is now at"
@@ -4296,38 +4377,38 @@
 
 #: builtin/checkout.c builtin/clone.c t/helper/test-fast-rebase.c
 msgid "unable to update HEAD"
-msgstr "不能更新 HEAD"
+msgstr "無法更新 HEAD"
 
 #: builtin/checkout.c
 #, c-format
 msgid "Reset branch '%s'\n"
-msgstr "重設分支 '%s'\n"
+msgstr "重設分支 “%s”\n"
 
 #: builtin/checkout.c
 #, c-format
 msgid "Already on '%s'\n"
-msgstr "已經位於 '%s'\n"
+msgstr "已經位於 “%s”\n"
 
 #: builtin/checkout.c
 #, c-format
 msgid "Switched to and reset branch '%s'\n"
-msgstr "切換並重設分支 '%s'\n"
+msgstr "已切換並重設分支 “%s”\n"
 
 #: builtin/checkout.c
 #, c-format
 msgid "Switched to a new branch '%s'\n"
-msgstr "切換到一個新分支 '%s'\n"
+msgstr "已切換至新分支 “%s”\n"
 
 #: builtin/checkout.c
 #, c-format
 msgid "Switched to branch '%s'\n"
-msgstr "切換到分支 '%s'\n"
+msgstr "已切換至分支 “%s”\n"
 
 #  譯者:請維持前導空格
 #: builtin/checkout.c
 #, c-format
 msgid " ... and %d more.\n"
-msgstr " ... 及其它 %d 個。\n"
+msgstr " …… 及其它 %d 個。\n"
 
 #: builtin/checkout.c
 #, c-format
@@ -4342,7 +4423,8 @@
 "\n"
 "%s\n"
 msgstr[0] ""
-"警告:您正丟下 %d 個提交,未和任何分支關聯:\n"
+"警告:您正丟下 %d 個\n"
+"未和任何分支關聯的提交:\n"
 "\n"
 "%s\n"
 
@@ -4361,23 +4443,23 @@
 " git branch <new-branch-name> %s\n"
 "\n"
 msgstr[0] ""
-"如果您想要透過建立新分支儲存它,這可能是一個好時候。\n"
-"如下動作:\n"
+"如果您想要透過建立新分支留下這些提交,\n"
+"現在很適合執行:\n"
 "\n"
-" git branch <新分支名> %s\n"
+" git branch <新分支名稱> %s\n"
 "\n"
 
 #: builtin/checkout.c
 msgid "internal error in revision walk"
-msgstr "在版本遍歷時遇到內部錯誤"
+msgstr "在修訂版遍歷時遇到內部錯誤"
 
 #: builtin/checkout.c
 msgid "Previous HEAD position was"
-msgstr "之前的 HEAD 位置是"
+msgstr "之前的 HEAD 指針位置在"
 
 #: builtin/checkout.c
 msgid "You are on a branch yet to be born"
-msgstr "您位於一個尚未初始化的分支"
+msgstr "您正位於一個尚未初始化的分支"
 
 #: builtin/checkout.c
 #, c-format
@@ -4385,7 +4467,7 @@
 "'%s' could be both a local file and a tracking branch.\n"
 "Please use -- (and optionally --no-guess) to disambiguate"
 msgstr ""
-"'%s' 既可以是一個本機檔案,也可以是一個追蹤分支。\n"
+"“%s” 既可以是本機檔案,也可以是追蹤分支。\n"
 "請使用 --(和可選的 --no-guess)來消除歧義"
 
 #: builtin/checkout.c
@@ -4399,18 +4481,19 @@
 "one remote, e.g. the 'origin' remote, consider setting\n"
 "checkout.defaultRemote=origin in your config."
 msgstr ""
-"如果您想要簽出一個遠端追蹤分支,例如 'origin',您可以\n"
-"使用 --track 選項寫出全名:\n"
+"如果您想要簽出遠端追蹤分支,例如 “origin”,\n"
+"您可以使用 --track 選項寫出全名:\n"
 "\n"
 "    git checkout --track origin/<name>\n"
 "\n"
-"如果您總是喜歡使用模糊的簡短分支名 <name>,而不喜歡如 'origin' 的遠端\n"
-"版本庫名,可以在設定中設定 checkout.defaultRemote=origin。"
+"如果您平時比較想要使用模糊的簡短分支名稱 <name>,\n"
+"而不太想寫如 “origin” 的遠端版本庫名稱,\n"
+"可以在組態中設定 checkout.defaultRemote=origin。"
 
 #: builtin/checkout.c
 #, c-format
 msgid "'%s' matched multiple (%d) remote tracking branches"
-msgstr "'%s' 符合多個 (%d) 遠端追蹤分支"
+msgstr "“%s” 符合多個 (%d) 遠端追蹤分支"
 
 #: builtin/checkout.c
 msgid "only one reference expected"
@@ -4419,7 +4502,7 @@
 #: builtin/checkout.c
 #, c-format
 msgid "only one reference expected, %d given."
-msgstr "應只有一個引用,卻提供了 %d 個。"
+msgstr "預期只有一個引用,卻提供了 %d 個。"
 
 #: builtin/checkout.c builtin/worktree.c
 #, c-format
@@ -4429,112 +4512,112 @@
 #: builtin/checkout.c
 #, c-format
 msgid "reference is not a tree: %s"
-msgstr "引用不是一個樹:%s"
+msgstr "引用不是樹狀物件:%s"
 
 #: builtin/checkout.c
 #, c-format
 msgid "a branch is expected, got tag '%s'"
-msgstr "期望一個分支,得到標籤 '%s'"
+msgstr "預期收到分支,卻收到標籤 “%s”"
 
 #: builtin/checkout.c
 #, c-format
 msgid "a branch is expected, got remote branch '%s'"
-msgstr "期望一個分支,得到遠端分支 '%s'"
+msgstr "預期收到分支,卻收到遠端分支 “%s”"
 
 #: builtin/checkout.c
 #, c-format
 msgid "a branch is expected, got '%s'"
-msgstr "期望一個分支,得到 '%s'"
+msgstr "預期收到分支,卻收到 “%s”"
 
 #: builtin/checkout.c
 #, c-format
 msgid "a branch is expected, got commit '%s'"
-msgstr "期望一個分支,得到提交 '%s'"
+msgstr "預期收到分支,卻收到提交 “%s”"
 
 #: builtin/checkout.c
 msgid ""
 "If you want to detach HEAD at the commit, try again with the --detach option."
-msgstr "若您想要分離提交的 HEAD,請傳入 --detach 選項重試。"
+msgstr "若您想要在此提交分離 HEAD 指針,請傳入 --detach 選項重試。"
 
 #: builtin/checkout.c
 msgid ""
 "cannot switch branch while merging\n"
 "Consider \"git merge --quit\" or \"git worktree add\"."
 msgstr ""
-"不能在合併時切換分支\n"
-"考慮使用 \"git merge --quit\" 或 \"git worktree add\"。"
+"無法在合併時切換分支\n"
+"請試試 “git merge --quit” 或 “git worktree add”。"
 
 #: builtin/checkout.c
 msgid ""
 "cannot switch branch in the middle of an am session\n"
 "Consider \"git am --quit\" or \"git worktree add\"."
 msgstr ""
-"不能在 am 工作階段期間切換分支\n"
-"考慮使用 \"git am --quit\" 或 \"git worktree add\"。"
+"無法在 am 工作階段期間時切換分支\n"
+"請試試 “git am --quit” 或 “git worktree add”。"
 
 #: builtin/checkout.c
 msgid ""
 "cannot switch branch while rebasing\n"
 "Consider \"git rebase --quit\" or \"git worktree add\"."
 msgstr ""
-"不能在重定基底時切換分支\n"
-"考慮使用 \"git rebase --quit\" 或 \"git worktree add\"。"
+"無法在重定基底時切換分支\n"
+"請試試 “git rebase --quit” 或 “git worktree add”。"
 
 #: builtin/checkout.c
 msgid ""
 "cannot switch branch while cherry-picking\n"
 "Consider \"git cherry-pick --quit\" or \"git worktree add\"."
 msgstr ""
-"不能在揀選時切換分支\n"
-"考慮使用 \"git cherry-pick --quit\" 或 \"git worktree add\"。"
+"無法在揀選時切換分支\n"
+"請試試 “git cherry-pick --quit” 或 “git worktree add”。"
 
 #: builtin/checkout.c
 msgid ""
 "cannot switch branch while reverting\n"
 "Consider \"git revert --quit\" or \"git worktree add\"."
 msgstr ""
-"不能在還原時切換分支\n"
-"考慮使用 \"git revert --quit\" 或 \"git worktree add\"。"
+"無法在還原時切換分支\n"
+"請試試 “git revert --quit” 或 “git worktree add”。"
 
 #: builtin/checkout.c
 msgid "you are switching branch while bisecting"
-msgstr "您在執行二分搜尋時切換分支"
+msgstr "您在進行二分搜尋時切換分支"
 
 #: builtin/checkout.c
 msgid "paths cannot be used with switching branches"
-msgstr "路徑不能和切換分支同時使用"
+msgstr "路徑不能與切換分支同時使用"
 
 #: builtin/checkout.c
 #, c-format
 msgid "'%s' cannot be used with switching branches"
-msgstr "'%s' 不能和切換分支同時使用"
+msgstr "“%s” 不能與切換分支同時使用"
 
 #: builtin/checkout.c
 #, c-format
 msgid "'%s' cannot be used with '%s'"
-msgstr "'%s' 不能和 '%s' 同時使用"
+msgstr "“%s” 不能與 “%s” 同時使用"
 
 #: builtin/checkout.c
 #, c-format
 msgid "'%s' cannot take <start-point>"
-msgstr "'%s' 不帶 <起始點>"
+msgstr "“%s” 不取 <start-point>"
 
 #: builtin/checkout.c
 #, c-format
 msgid "Cannot switch branch to a non-commit '%s'"
-msgstr "不能切換分支到一個非提交 '%s'"
+msgstr "無法將分支切換至非提交項目 “%s”"
 
 #: builtin/checkout.c
 msgid "missing branch or commit argument"
-msgstr "缺少分支或提交參數"
+msgstr "缺少分支或提交引數"
 
 #: builtin/checkout.c
 msgid "perform a 3-way merge with the new branch"
-msgstr "和新的分支執行三方合併"
+msgstr "和新分支進行三方合併"
 
 #: builtin/checkout.c builtin/log.c parse-options.h
 msgid "style"
-msgstr "風格"
+msgstr "style"
 
 #: builtin/checkout.c
 msgid "conflict style (merge, diff3, or zdiff3)"
@@ -4542,7 +4625,7 @@
 
 #: builtin/checkout.c builtin/worktree.c
 msgid "detach HEAD at named commit"
-msgstr "HEAD 從指定的提交分離"
+msgstr "自指定提交分離 HEAD 指針"
 
 #: builtin/checkout.c
 msgid "force checkout (throw away local modifications)"
@@ -4550,19 +4633,19 @@
 
 #: builtin/checkout.c
 msgid "new-branch"
-msgstr "新分支"
+msgstr "new-branch"
 
 #: builtin/checkout.c
 msgid "new unparented branch"
-msgstr "新的沒有父提交的分支"
+msgstr "新的,沒有父提交的分支"
 
 #: builtin/checkout.c builtin/merge.c
 msgid "update ignored files (default)"
-msgstr "更新忽略的檔案(預設)"
+msgstr "更新忽略的檔案(預設值)"
 
 #: builtin/checkout.c
 msgid "do not check if another worktree is holding the given ref"
-msgstr "不檢查指定的引用是否被其他工作區所占用"
+msgstr "不檢查其他工作區是否正在佔用指定的引用"
 
 #: builtin/checkout.c
 msgid "checkout our version for unmerged files"
@@ -4574,16 +4657,16 @@
 
 #: builtin/checkout.c
 msgid "do not limit pathspecs to sparse entries only"
-msgstr "對路徑不做稀疏簽出的限制"
+msgstr "對路徑規格不做稀疏簽出的限制"
 
 #: builtin/checkout.c
 #, c-format
 msgid "options '-%c', '-%c', and '%s' cannot be used together"
-msgstr "「-%c」、「-%c」和「%s」選項不得同時使用"
+msgstr "“-%c”、“-%c” 和 “%s” 選項不得同時使用"
 
 #: builtin/checkout.c
 msgid "--track needs a branch name"
-msgstr "--track 需要一個分支名"
+msgstr "--track 需要分支名稱"
 
 #: builtin/checkout.c
 #, c-format
@@ -4602,60 +4685,61 @@
 #: builtin/checkout.c
 #, c-format
 msgid "'%s' is not a commit and a branch '%s' cannot be created from it"
-msgstr "'%s' 不是一個提交,不能基於它建立分支 '%s'"
+msgstr "“%s” 不是提交,因此不能以這為基礎建立 “%s” 分支"
 
 #: builtin/checkout.c
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
-msgstr "git checkout:--detach 不能接收路徑參數 '%s'"
+msgstr "git checkout:--detach 不取路徑引數 “%s”"
 
 #: builtin/checkout.c
 msgid ""
 "git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 "checking out of the index."
 msgstr ""
-"git checkout:在從索引簽出時,--ours/--theirs、--force 和 --merge 不相容。"
+"git checkout:在從索引簽出時,--ours/--theirs、--force\n"
+"和 --merge 不相容。"
 
 #: builtin/checkout.c
 msgid "you must specify path(s) to restore"
-msgstr "您必須指定一個要復原的路徑"
+msgstr "您必須指定要還原的路徑"
 
 #: builtin/checkout.c builtin/clone.c builtin/remote.c
 #: builtin/submodule--helper.c builtin/worktree.c
 msgid "branch"
-msgstr "分支"
+msgstr "branch"
 
 #: builtin/checkout.c
 msgid "create and checkout a new branch"
-msgstr "建立並簽出一個新的分支"
+msgstr "建立並簽出新分支"
 
 #: builtin/checkout.c
 msgid "create/reset and checkout a branch"
-msgstr "建立/重設並簽出一個分支"
+msgstr "建立/重設並簽出分支"
 
 #: builtin/checkout.c
 msgid "create reflog for new branch"
-msgstr "為新的分支建立引用日誌"
+msgstr "為新分支建立引用日誌"
 
 #: builtin/checkout.c
 msgid "second guess 'git checkout <no-such-branch>' (default)"
-msgstr "二次猜測 'git checkout <無此分支>'(預設)"
+msgstr "二次猜測 “git checkout <無此分支>”(預設值)"
 
 #: builtin/checkout.c
 msgid "use overlay mode (default)"
-msgstr "使用疊加模式(預設)"
+msgstr "使用疊加模式(預設值)"
 
 #: builtin/checkout.c
 msgid "create and switch to a new branch"
-msgstr "建立並切換一個新分支"
+msgstr "建立並切換至新分支"
 
 #: builtin/checkout.c
 msgid "create/reset and switch to a branch"
-msgstr "建立/重設並切換一個分支"
+msgstr "建立/重設並切換至指定分支"
 
 #: builtin/checkout.c
 msgid "second guess 'git switch <no-such-branch>'"
-msgstr "二次猜測 'git switch <無此分支>'"
+msgstr "二次猜測 “git switch <無此分支>”"
 
 #: builtin/checkout.c
 msgid "throw away local modifications"
@@ -4663,19 +4747,19 @@
 
 #: builtin/checkout.c
 msgid "which tree-ish to checkout from"
-msgstr "要簽出哪一個樹"
+msgstr "要自哪一個樹狀物件指示元簽出"
 
 #: builtin/checkout.c
 msgid "restore the index"
-msgstr "復原索引"
+msgstr "還原索引"
 
 #: builtin/checkout.c
 msgid "restore the working tree (default)"
-msgstr "復原工作區(預設)"
+msgstr "還原工作區(預設值)"
 
 #: builtin/checkout.c
 msgid "ignore unmerged entries"
-msgstr "忽略未合併條目"
+msgstr "忽略未合併項目"
 
 #: builtin/checkout.c
 msgid "use overlay mode"
@@ -4686,17 +4770,18 @@
 "git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] "
 "[<pathspec>...]"
 msgstr ""
-"git clean [-d] [-f] [-i] [-n] [-q] [-e <模式>] [-x | -X] [--] [<路徑規格>...]"
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] "
+"[<pathspec>...]"
 
 #: builtin/clean.c
 #, c-format
 msgid "Removing %s\n"
-msgstr "正刪除 %s\n"
+msgstr "正在刪除 %s\n"
 
 #: builtin/clean.c
 #, c-format
 msgid "Would remove %s\n"
-msgstr "將刪除 %s\n"
+msgstr "將會刪除 %s\n"
 
 #: builtin/clean.c
 #, c-format
@@ -4711,12 +4796,12 @@
 #: builtin/clean.c midx.c
 #, c-format
 msgid "failed to remove %s"
-msgstr "刪除 %s 失敗"
+msgstr "無法移除 %s"
 
 #: builtin/clean.c
 #, c-format
 msgid "could not lstat %s\n"
-msgstr "不能對 %s 呼叫 lstat\n"
+msgstr "不能對 %s 進行 lstat\n"
 
 #: builtin/clean.c
 msgid "Refusing to remove current working directory\n"
@@ -4726,7 +4811,7 @@
 msgid "Would refuse to remove current working directory\n"
 msgstr "會拒絕移除目前的工作目錄\n"
 
-#: builtin/clean.c git-add--interactive.perl
+#: builtin/clean.c
 #, c-format
 msgid ""
 "Prompt help:\n"
@@ -4734,12 +4819,12 @@
 "foo        - select item based on unique prefix\n"
 "           - (empty) select nothing\n"
 msgstr ""
-"協助:\n"
-"1          - 透過編號選擇一個選項\n"
-"foo        - 透過唯一前綴選擇一個選項\n"
+"提示說明:\n"
+"1          - 透過編號選擇項目\n"
+"foo        - 根據獨特前綴選擇項目\n"
 "           - (空)什麼也不選擇\n"
 
-#: builtin/clean.c git-add--interactive.perl
+#: builtin/clean.c
 #, c-format
 msgid ""
 "Prompt help:\n"
@@ -4751,39 +4836,39 @@
 "*          - choose all items\n"
 "           - (empty) finish selecting\n"
 msgstr ""
-"協助:\n"
-"1          - 選擇一個選項\n"
-"3-5        - 選擇一個範圍內的所有選項\n"
-"2-3,6-9    - 選擇多個範圍內的所有選項\n"
-"foo        - 透過唯一前綴選擇一個選項\n"
-"-...       - 反選特定的選項\n"
-"*          - 選擇所有選項\n"
-"           - (空)結束選擇\n"
+"提示說明:\n"
+"1          - 選擇一個項目\n"
+"3-5        - 選擇一個項目範圍\n"
+"2-3,6-9    - 選擇多個項目範圍\n"
+"foo        - 根據獨特前綴選擇項目\n"
+"-...       - 取消選取指定項目\n"
+"*          - 選擇所有項目\n"
+"           - (空)完成選擇\n"
 
-#: builtin/clean.c git-add--interactive.perl
-#, c-format, perl-format
+#: builtin/clean.c
+#, c-format
 msgid "Huh (%s)?\n"
-msgstr "嗯(%s)?\n"
+msgstr "嗯(%s)?\n"
 
 #: builtin/clean.c
 #, c-format
 msgid "Input ignore patterns>> "
-msgstr "輸入範本以排除條目>> "
+msgstr "輸入要忽略的模式項目>> "
 
 #: builtin/clean.c
 #, c-format
 msgid "WARNING: Cannot find items matched by: %s"
-msgstr "警告:無法找到和 %s 符合的條目"
+msgstr "警告:無法找到和 %s 符合的項目"
 
 #: builtin/clean.c
 msgid "Select items to delete"
-msgstr "選擇要刪除的條目"
+msgstr "選擇要刪除的項目"
 
 #. TRANSLATORS: Make sure to keep [y/N] as is
 #: builtin/clean.c
 #, c-format
 msgid "Remove %s [y/N]? "
-msgstr "移除 %s [y/N]? "
+msgstr "移除 %s [y/N]? "
 
 #: builtin/clean.c
 msgid ""
@@ -4798,15 +4883,15 @@
 "clean               - 開始清理\n"
 "filter by pattern   - 透過範本排除要刪除的條目\n"
 "select by numbers   - 透過數字選擇要刪除的條目\n"
-"ask each            - 針對刪除逐一詢問(就像 \"rm -i\")\n"
+"ask each            - 針對刪除逐一詢問(就像 “rm -i”)\n"
 "quit                - 停止刪除並離開\n"
-"help                - 顯示本協助\n"
-"?                   - 顯示如何在提示符下選擇的協助"
+"help                - 顯示本輔助說明\n"
+"?                   - 顯示如何在提示下選擇的協助"
 
 #: builtin/clean.c
 msgid "Would remove the following item:"
 msgid_plural "Would remove the following items:"
-msgstr[0] "將刪除如下條目:"
+msgstr[0] "將移除以下項目:"
 
 #: builtin/clean.c
 msgid "No more files to clean, exiting."
@@ -4814,11 +4899,11 @@
 
 #: builtin/clean.c
 msgid "do not print names of files removed"
-msgstr "不列印刪除檔案的名稱"
+msgstr "不輸出移除的檔案的名稱"
 
 #: builtin/clean.c
 msgid "force"
-msgstr "強制"
+msgstr "force"
 
 #: builtin/clean.c
 msgid "interactive cleaning"
@@ -4826,24 +4911,24 @@
 
 #: builtin/clean.c
 msgid "remove whole directories"
-msgstr "刪除整個目錄"
+msgstr "移除整個目錄"
 
 #: builtin/clean.c builtin/describe.c builtin/grep.c builtin/log.c
 #: builtin/ls-files.c builtin/name-rev.c builtin/show-ref.c
 msgid "pattern"
-msgstr "模式"
+msgstr "pattern"
 
 #: builtin/clean.c
 msgid "add <pattern> to ignore rules"
-msgstr "新增 <模式> 到忽略規則"
+msgstr "將 <pattern> 加到忽略規則"
 
 #: builtin/clean.c
 msgid "remove ignored files, too"
-msgstr "也刪除忽略的檔案"
+msgstr "亦移除忽略的檔案"
 
 #: builtin/clean.c
 msgid "remove only ignored files"
-msgstr "只刪除忽略的檔案"
+msgstr "只移除忽略的檔案"
 
 #: builtin/clean.c
 msgid ""
@@ -4865,23 +4950,23 @@
 
 #: builtin/clone.c
 msgid "git clone [<options>] [--] <repo> [<dir>]"
-msgstr "git clone [<選項>] [--] <版本庫> [<路徑>]"
+msgstr "git clone [<options>] [--] <repo> [<dir>]"
 
 #: builtin/clone.c
 msgid "don't clone shallow repository"
-msgstr "不要複製淺版本庫"
+msgstr "不要複製淺層版本庫"
 
 #: builtin/clone.c
 msgid "don't create a checkout"
-msgstr "不建立一個簽出"
+msgstr "不要建立簽出"
 
 #: builtin/clone.c builtin/init-db.c
 msgid "create a bare repository"
-msgstr "建立一個純版本庫"
+msgstr "建立裸版本庫"
 
 #: builtin/clone.c
 msgid "create a mirror repository (implies bare)"
-msgstr "建立一個鏡像版本庫(也是純版本庫)"
+msgstr "建立鏡像版本庫(亦即裸版本庫)"
 
 #: builtin/clone.c
 msgid "to clone from a local repository"
@@ -4889,7 +4974,7 @@
 
 #: builtin/clone.c
 msgid "don't use local hardlinks, always copy"
-msgstr "不使用本機硬連結,始終複製"
+msgstr "不使用本機硬連結,始終拷貝"
 
 #: builtin/clone.c
 msgid "setup as shared repository"
@@ -4905,15 +4990,15 @@
 
 #: builtin/clone.c
 msgid "number of submodules cloned in parallel"
-msgstr "並行複製的子模組數"
+msgstr "平行複製的子模組數量"
 
 #: builtin/clone.c builtin/init-db.c
 msgid "template-directory"
-msgstr "範本目錄"
+msgstr "模板目錄"
 
 #: builtin/clone.c builtin/init-db.c
 msgid "directory from which templates will be used"
-msgstr "範本目錄將被使用"
+msgstr "將被使用的模板目錄"
 
 #: builtin/clone.c builtin/submodule--helper.c
 msgid "reference repository"
@@ -4921,21 +5006,21 @@
 
 #: builtin/clone.c builtin/submodule--helper.c
 msgid "use --reference only while cloning"
-msgstr "僅在複製時參考 --reference 指向的本機版本庫"
+msgstr "僅在複製時使用 --reference"
 
 #: builtin/clone.c builtin/column.c builtin/fmt-merge-msg.c builtin/init-db.c
 #: builtin/merge-file.c builtin/merge.c builtin/pack-objects.c builtin/repack.c
 #: builtin/submodule--helper.c t/helper/test-simple-ipc.c
 msgid "name"
-msgstr "名稱"
+msgstr "name"
 
 #: builtin/clone.c
 msgid "use <name> instead of 'origin' to track upstream"
-msgstr "使用 <名稱> 而不是 'origin' 去追蹤上游"
+msgstr "使用 <name> 而不是 “origin” 追蹤上游"
 
 #: builtin/clone.c
 msgid "checkout <branch> instead of the remote's HEAD"
-msgstr "簽出 <分支> 而不是遠端 HEAD"
+msgstr "簽出 <branch> 而不是遠端 HEAD"
 
 #: builtin/clone.c
 msgid "path to git-upload-pack on the remote"
@@ -4943,27 +5028,23 @@
 
 #: builtin/clone.c builtin/fetch.c builtin/grep.c builtin/pull.c
 msgid "depth"
-msgstr "深度"
+msgstr "depth"
 
 #: builtin/clone.c
 msgid "create a shallow clone of that depth"
-msgstr "建立一個指定深度的淺複製"
-
-#: builtin/clone.c builtin/fetch.c builtin/pack-objects.c builtin/pull.c
-msgid "time"
-msgstr "時間"
+msgstr "建立指定深度的淺層複製"
 
 #: builtin/clone.c
 msgid "create a shallow clone since a specific time"
-msgstr "建立從指定時間到現在的淺複製"
+msgstr "建立從指定時間到現在的淺層複製"
 
 #: builtin/clone.c builtin/fetch.c builtin/pull.c builtin/rebase.c
 msgid "revision"
-msgstr "修訂版"
+msgstr "revision"
 
 #: builtin/clone.c builtin/fetch.c builtin/pull.c
 msgid "deepen history of shallow clone, excluding rev"
-msgstr "取得更多淺複製的過去歷史記錄,除了特定版本"
+msgstr "取得更多淺層複製的過去歷史記錄,除了特定修訂版"
 
 #: builtin/clone.c builtin/submodule--helper.c
 msgid "clone only one branch, HEAD or --branch"
@@ -4979,11 +5060,11 @@
 
 #: builtin/clone.c builtin/init-db.c
 msgid "gitdir"
-msgstr "git目錄"
+msgstr "gitdir"
 
 #: builtin/clone.c builtin/init-db.c
 msgid "separate git dir from working tree"
-msgstr "git目錄和工作區分離"
+msgstr "git 目錄和工作區分離"
 
 #: builtin/clone.c
 msgid "key=value"
@@ -5048,6 +5129,11 @@
 
 #: builtin/clone.c
 #, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "“%s” 是個符號連結,故不能使用 --local 複製"
+
+#: builtin/clone.c
+#, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "無法在 '%s' 上啟動疊代器"
 
@@ -5059,7 +5145,7 @@
 #: builtin/clone.c compat/precompose_utf8.c
 #, c-format
 msgid "failed to unlink '%s'"
-msgstr "刪除 '%s' 失敗"
+msgstr "無法刪除 “%s”"
 
 #: builtin/clone.c
 #, c-format
@@ -5127,7 +5213,7 @@
 
 #: builtin/clone.c
 msgid "cannot unlink temporary alternates file"
-msgstr "無法刪除暫時的 alternates 檔案"
+msgstr "無法刪除暫存 alternates 檔案"
 
 #: builtin/clone.c
 msgid "Too many arguments."
@@ -5241,6 +5327,10 @@
 msgstr "無法從套件包 URL “%s” 抓取物件"
 
 #: builtin/clone.c
+msgid "failed to fetch advertised bundles"
+msgstr "無法抓取公佈的套件包"
+
+#: builtin/clone.c
 msgid "remote transport reported error"
 msgstr "遠端傳輸回報錯誤"
 
@@ -5609,7 +5699,7 @@
 "in the current commit message"
 msgstr "無法選擇一個未被目前提交說明使用的備註字元"
 
-#: builtin/commit.c
+#: builtin/commit.c builtin/merge-tree.c
 #, c-format
 msgid "could not lookup commit %s"
 msgstr "不能查詢提交 %s"
@@ -5834,13 +5924,13 @@
 msgid "version"
 msgstr "版本"
 
-#: builtin/commit.c builtin/push.c builtin/worktree.c
+#: builtin/commit.c builtin/fetch.c builtin/push.c builtin/worktree.c
 msgid "machine-readable output"
 msgstr "機器可讀的輸出"
 
 #: builtin/commit.c
 msgid "show status in long format (default)"
-msgstr "以長格式顯示狀態(預設)"
+msgstr "以長格式顯示狀態(預設值)"
 
 #: builtin/commit.c
 msgid "terminate entries with NUL"
@@ -5917,7 +6007,7 @@
 msgid "override date for commit"
 msgstr "提交時覆蓋日期"
 
-#: builtin/commit.c parse-options.h ref-filter.h
+#: builtin/commit.c builtin/merge-tree.c parse-options.h ref-filter.h
 msgid "commit"
 msgstr "提交"
 
@@ -6068,7 +6158,7 @@
 msgid "git config [<options>]"
 msgstr "git config [<選項>]"
 
-#: builtin/config.c builtin/env--helper.c
+#: builtin/config.c
 #, c-format
 msgid "unrecognized --type argument, %s"
 msgstr "無法識別的 --type 參數,%s"
@@ -6167,7 +6257,7 @@
 
 #: builtin/config.c
 msgid "find the color configured: slot [default]"
-msgstr "獲得設定的顏色:設定 [預設]"
+msgstr "獲得設定的顏色:設定 [預設值]"
 
 #: builtin/config.c
 msgid "find the color setting: slot [stdout-is-tty]"
@@ -6177,11 +6267,11 @@
 msgid "Type"
 msgstr "類型"
 
-#: builtin/config.c builtin/env--helper.c builtin/hash-object.c
+#: builtin/config.c builtin/hash-object.c
 msgid "type"
 msgstr "類型"
 
-#: builtin/config.c builtin/env--helper.c
+#: builtin/config.c
 msgid "value is given this type"
 msgstr "取值為該類型"
 
@@ -6235,7 +6325,7 @@
 "顯示設定檔的作用域 (工作區 worktree、本機 local、全域 global、系統 system、指"
 "令 command)"
 
-#: builtin/config.c builtin/env--helper.c
+#: builtin/config.c
 msgid "value"
 msgstr "取值"
 
@@ -6770,30 +6860,6 @@
 msgid "no <cmd> given for --extcmd=<cmd>"
 msgstr "沒有為 --extcmd=<命令> 參數提供 <命令>"
 
-#: builtin/env--helper.c
-msgid "git env--helper --type=[bool|ulong] <options> <env-var>"
-msgstr "git env--helper --type=[bool|ulong] <選項> <環境變數>"
-
-#: builtin/env--helper.c
-msgid "default for git_env_*(...) to fall back on"
-msgstr "git_env_*(...) 的預設值"
-
-#: builtin/env--helper.c
-msgid "be quiet only use git_env_*() value as exit code"
-msgstr "安靜模式,只使用 git_env_*() 的值作為離開碼"
-
-#: builtin/env--helper.c
-#, c-format
-msgid "option `--default' expects a boolean value with `--type=bool`, not `%s`"
-msgstr "選項「--default」預期收到「--type=bool」的布林值,而非「%s」"
-
-#: builtin/env--helper.c
-#, c-format
-msgid ""
-"option `--default' expects an unsigned long value with `--type=ulong`, not "
-"`%s`"
-msgstr "選項「--default」預期收到「--type=ulong」的無號 long 數值,而非「%s」"
-
 #: builtin/fast-export.c
 msgid "git fast-export [<rev-list-opts>]"
 msgstr "git fast-export [<rev-list-opts>]"
@@ -6936,6 +7002,213 @@
 msgid "fetch.parallel cannot be negative"
 msgstr "fetch.parallel 不能為負數"
 
+#: builtin/fetch.c
+msgid "couldn't find remote ref HEAD"
+msgstr "找不到遠端 HEAD 引用"
+
+#: builtin/fetch.c
+#, c-format
+msgid "From %.*s\n"
+msgstr "來自 %.*s\n"
+
+#: builtin/fetch.c
+#, c-format
+msgid "object %s not found"
+msgstr "物件 %s 未發現"
+
+#: builtin/fetch.c
+msgid "[up to date]"
+msgstr "[最新]"
+
+#: builtin/fetch.c
+msgid "[rejected]"
+msgstr "[已拒絕]"
+
+#: builtin/fetch.c
+msgid "can't fetch into checked-out branch"
+msgstr "無法抓取至已簽出分支"
+
+#: builtin/fetch.c
+msgid "[tag update]"
+msgstr "[標籤更新]"
+
+#: builtin/fetch.c
+msgid "unable to update local ref"
+msgstr "不能更新本機引用"
+
+#: builtin/fetch.c
+msgid "would clobber existing tag"
+msgstr "會破壞現有的標籤"
+
+#: builtin/fetch.c
+msgid "[new tag]"
+msgstr "[新標籤]"
+
+#: builtin/fetch.c
+msgid "[new branch]"
+msgstr "[新分支]"
+
+#: builtin/fetch.c
+msgid "[new ref]"
+msgstr "[新引用]"
+
+#: builtin/fetch.c
+msgid "forced update"
+msgstr "強制更新"
+
+#: builtin/fetch.c
+msgid "non-fast-forward"
+msgstr "非快轉"
+
+#: builtin/fetch.c builtin/grep.c sequencer.c
+#, c-format
+msgid "cannot open '%s'"
+msgstr "不能開啟 '%s'"
+
+#: builtin/fetch.c
+msgid ""
+"fetch normally indicates which branches had a forced update,\n"
+"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
+"flag or run 'git config fetch.showForcedUpdates true'"
+msgstr ""
+"取得 (fetch) 動作通常會指示哪些分支發生了強制更新,但該檢查已被停用。\n"
+"要重新啟用,請使用「--show-forced-updates」選項,或執行\n"
+"「git config fetch.showForcedUpdates true」"
+
+#: builtin/fetch.c
+#, c-format
+msgid ""
+"it took %.2f seconds to check forced updates; you can use\n"
+"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
+"false'\n"
+"to avoid this check\n"
+msgstr ""
+"花了 %.2f 秒檢查強制更新。您可以使用「--no-show-forced-updates」\n"
+"或執行「git config fetch.showForcedUpdates false」避免此項檢查\n"
+
+#: builtin/fetch.c
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s 未傳送所有必需的物件\n"
+
+#: builtin/fetch.c
+#, c-format
+msgid "rejected %s because shallow roots are not allowed to be updated"
+msgstr "已拒絕 %s,不允許更新淺複製"
+
+#: builtin/fetch.c
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+"一些本機引用不能被更新;嘗試執行\n"
+" 'git remote prune %s' 來刪除舊的、有衝突的分支"
+
+#  譯者:請維持前導空格
+#: builtin/fetch.c
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr "   (%s 將成為懸空狀態)"
+
+#  譯者:請維持前導空格
+#: builtin/fetch.c
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr "   (%s 已成為懸空狀態)"
+
+#: builtin/fetch.c
+msgid "[deleted]"
+msgstr "[已刪除]"
+
+#: builtin/fetch.c builtin/remote.c
+msgid "(none)"
+msgstr "(無)"
+
+#: builtin/fetch.c
+#, c-format
+msgid "refusing to fetch into branch '%s' checked out at '%s'"
+msgstr "拒絕取得在「%2$s」簽出的「%1$s」分支"
+
+#: builtin/fetch.c
+#, c-format
+msgid "option \"%s\" value \"%s\" is not valid for %s"
+msgstr "選項「%s」的值「%s」對 %s 無效"
+
+#: builtin/fetch.c
+#, c-format
+msgid "option \"%s\" is ignored for %s\n"
+msgstr "選項「%s」被 %s 忽略\n"
+
+#: builtin/fetch.c object-file.c
+#, c-format
+msgid "%s is not a valid object"
+msgstr "%s 不是一個有效的物件"
+
+#: builtin/fetch.c
+#, c-format
+msgid "the object %s does not exist"
+msgstr "%s 物件不存在"
+
+#: builtin/fetch.c
+msgid "multiple branches detected, incompatible with --set-upstream"
+msgstr "檢測到多分支,和 --set-upstream 不相容"
+
+#: builtin/fetch.c
+#, c-format
+msgid ""
+"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
+"any branch."
+msgstr ""
+"無法將 HEAD 的上游從「%2$s」設定為「%1$s」,因為 HEAD 沒有指向任何分支。"
+
+#: builtin/fetch.c
+msgid "not setting upstream for a remote remote-tracking branch"
+msgstr "沒有為一個遠端追蹤分支設定上游"
+
+#: builtin/fetch.c
+msgid "not setting upstream for a remote tag"
+msgstr "沒有為一個遠端標籤設定上游"
+
+#: builtin/fetch.c
+msgid "unknown branch type"
+msgstr "未知的分支類型"
+
+#: builtin/fetch.c
+msgid ""
+"no source branch found;\n"
+"you need to specify exactly one branch with the --set-upstream option"
+msgstr ""
+"找不到來源分支。\n"
+"您得使用 --set-upstream 選項明確指定一個分支"
+
+#: builtin/fetch.c
+#, c-format
+msgid "Fetching %s\n"
+msgstr "正在取得 %s\n"
+
+#: builtin/fetch.c
+#, c-format
+msgid "could not fetch %s"
+msgstr "不能取得 %s"
+
+#: builtin/fetch.c
+#, c-format
+msgid "could not fetch '%s' (exit code: %d)\n"
+msgstr "無法取得 '%s'(離開碼:%d)\n"
+
+#: builtin/fetch.c
+msgid ""
+"no remote repository specified; please specify either a URL or a\n"
+"remote name from which new revisions should be fetched"
+msgstr ""
+"未指定遠端版本庫。請指定用以取得新修訂版本之\n"
+"來源 URL 或者遠端版本庫名稱"
+
+#: builtin/fetch.c
+msgid "you need to specify a tag name"
+msgstr "您需要指定標籤名稱"
+
 #: builtin/fetch.c builtin/pull.c
 msgid "fetch from all remotes"
 msgstr "從所有的遠端抓取"
@@ -7072,213 +7345,6 @@
 msgstr "從標準輸入中接受引用規格"
 
 #: builtin/fetch.c
-msgid "couldn't find remote ref HEAD"
-msgstr "找不到遠端 HEAD 引用"
-
-#: builtin/fetch.c
-#, c-format
-msgid "object %s not found"
-msgstr "物件 %s 未發現"
-
-#: builtin/fetch.c
-msgid "[up to date]"
-msgstr "[最新]"
-
-#: builtin/fetch.c
-msgid "[rejected]"
-msgstr "[已拒絕]"
-
-#: builtin/fetch.c
-msgid "can't fetch into checked-out branch"
-msgstr "無法抓取至已簽出分支"
-
-#: builtin/fetch.c
-msgid "[tag update]"
-msgstr "[標籤更新]"
-
-#: builtin/fetch.c
-msgid "unable to update local ref"
-msgstr "不能更新本機引用"
-
-#: builtin/fetch.c
-msgid "would clobber existing tag"
-msgstr "會破壞現有的標籤"
-
-#: builtin/fetch.c
-msgid "[new tag]"
-msgstr "[新標籤]"
-
-#: builtin/fetch.c
-msgid "[new branch]"
-msgstr "[新分支]"
-
-#: builtin/fetch.c
-msgid "[new ref]"
-msgstr "[新引用]"
-
-#: builtin/fetch.c
-msgid "forced update"
-msgstr "強制更新"
-
-#: builtin/fetch.c
-msgid "non-fast-forward"
-msgstr "非快轉"
-
-#: builtin/fetch.c builtin/grep.c sequencer.c
-#, c-format
-msgid "cannot open '%s'"
-msgstr "不能開啟 '%s'"
-
-#: builtin/fetch.c
-msgid ""
-"fetch normally indicates which branches had a forced update,\n"
-"but that check has been disabled; to re-enable, use '--show-forced-updates'\n"
-"flag or run 'git config fetch.showForcedUpdates true'"
-msgstr ""
-"取得 (fetch) 動作通常會指示哪些分支發生了強制更新,但該檢查已被停用。\n"
-"要重新啟用,請使用「--show-forced-updates」選項,或執行\n"
-"「git config fetch.showForcedUpdates true」"
-
-#: builtin/fetch.c
-#, c-format
-msgid ""
-"it took %.2f seconds to check forced updates; you can use\n"
-"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates "
-"false'\n"
-"to avoid this check\n"
-msgstr ""
-"花了 %.2f 秒檢查強制更新。您可以使用「--no-show-forced-updates」\n"
-"或執行「git config fetch.showForcedUpdates false」避免此項檢查\n"
-
-#: builtin/fetch.c
-#, c-format
-msgid "%s did not send all necessary objects\n"
-msgstr "%s 未傳送所有必需的物件\n"
-
-#: builtin/fetch.c
-#, c-format
-msgid "rejected %s because shallow roots are not allowed to be updated"
-msgstr "已拒絕 %s,不允許更新淺複製"
-
-#: builtin/fetch.c
-#, c-format
-msgid "From %.*s\n"
-msgstr "來自 %.*s\n"
-
-#: builtin/fetch.c
-#, c-format
-msgid ""
-"some local refs could not be updated; try running\n"
-" 'git remote prune %s' to remove any old, conflicting branches"
-msgstr ""
-"一些本機引用不能被更新;嘗試執行\n"
-" 'git remote prune %s' 來刪除舊的、有衝突的分支"
-
-#  譯者:請維持前導空格
-#: builtin/fetch.c
-#, c-format
-msgid "   (%s will become dangling)"
-msgstr "   (%s 將成為懸空狀態)"
-
-#  譯者:請維持前導空格
-#: builtin/fetch.c
-#, c-format
-msgid "   (%s has become dangling)"
-msgstr "   (%s 已成為懸空狀態)"
-
-#: builtin/fetch.c
-msgid "[deleted]"
-msgstr "[已刪除]"
-
-#: builtin/fetch.c builtin/remote.c
-msgid "(none)"
-msgstr "(無)"
-
-#: builtin/fetch.c
-#, c-format
-msgid "refusing to fetch into branch '%s' checked out at '%s'"
-msgstr "拒絕取得在「%2$s」簽出的「%1$s」分支"
-
-#: builtin/fetch.c
-#, c-format
-msgid "option \"%s\" value \"%s\" is not valid for %s"
-msgstr "選項「%s」的值「%s」對 %s 無效"
-
-#: builtin/fetch.c
-#, c-format
-msgid "option \"%s\" is ignored for %s\n"
-msgstr "選項「%s」被 %s 忽略\n"
-
-#: builtin/fetch.c object-file.c
-#, c-format
-msgid "%s is not a valid object"
-msgstr "%s 不是一個有效的物件"
-
-#: builtin/fetch.c
-#, c-format
-msgid "the object %s does not exist"
-msgstr "%s 物件不存在"
-
-#: builtin/fetch.c
-msgid "multiple branches detected, incompatible with --set-upstream"
-msgstr "檢測到多分支,和 --set-upstream 不相容"
-
-#: builtin/fetch.c
-#, c-format
-msgid ""
-"could not set upstream of HEAD to '%s' from '%s' when it does not point to "
-"any branch."
-msgstr ""
-"無法將 HEAD 的上游從「%2$s」設定為「%1$s」,因為 HEAD 沒有指向任何分支。"
-
-#: builtin/fetch.c
-msgid "not setting upstream for a remote remote-tracking branch"
-msgstr "沒有為一個遠端追蹤分支設定上游"
-
-#: builtin/fetch.c
-msgid "not setting upstream for a remote tag"
-msgstr "沒有為一個遠端標籤設定上游"
-
-#: builtin/fetch.c
-msgid "unknown branch type"
-msgstr "未知的分支類型"
-
-#: builtin/fetch.c
-msgid ""
-"no source branch found;\n"
-"you need to specify exactly one branch with the --set-upstream option"
-msgstr ""
-"找不到來源分支。\n"
-"您得使用 --set-upstream 選項明確指定一個分支"
-
-#: builtin/fetch.c
-#, c-format
-msgid "Fetching %s\n"
-msgstr "正在取得 %s\n"
-
-#: builtin/fetch.c
-#, c-format
-msgid "could not fetch %s"
-msgstr "不能取得 %s"
-
-#: builtin/fetch.c
-#, c-format
-msgid "could not fetch '%s' (exit code: %d)\n"
-msgstr "無法取得 '%s'(離開碼:%d)\n"
-
-#: builtin/fetch.c
-msgid ""
-"no remote repository specified; please specify either a URL or a\n"
-"remote name from which new revisions should be fetched"
-msgstr ""
-"未指定遠端版本庫。請指定用以取得新修訂版本之\n"
-"來源 URL 或者遠端版本庫名稱"
-
-#: builtin/fetch.c
-msgid "you need to specify a tag name"
-msgstr "您需要指定標籤名稱"
-
-#: builtin/fetch.c
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr "--negotiate-only 需要一或多個 --negotiation-tip=*"
 
@@ -7291,6 +7357,11 @@
 msgstr "對於一個完整的版本庫,參數 --unshallow 沒有意義"
 
 #: builtin/fetch.c
+#, c-format
+msgid "failed to fetch bundles from '%s'"
+msgstr "無法自「%s」抓取套件包"
+
+#: builtin/fetch.c
 msgid "fetch --all does not take a repository argument"
 msgstr "fetch --all 不能帶一個版本庫參數"
 
@@ -7418,6 +7489,14 @@
 msgid "print only refs which don't contain the commit"
 msgstr "只列印不包含該提交的引用"
 
+#: builtin/for-each-ref.c
+msgid "read reference patterns from stdin"
+msgstr "從 stdin 讀取引用模式"
+
+#: builtin/for-each-ref.c
+msgid "unknown arguments supplied with --stdin"
+msgstr "為 --stdin 提供的引數未知"
+
 #: builtin/for-each-repo.c
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<config> [--] <arguments>"
@@ -7434,6 +7513,11 @@
 msgid "missing --config=<config>"
 msgstr "缺少 --config=<設定>"
 
+#: builtin/for-each-repo.c
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "收到無效的組態 --config=%s"
+
 #: builtin/fsck.c
 msgid "unknown"
 msgstr "未知"
@@ -7619,13 +7703,14 @@
 msgstr "注意:%s 指向一個尚未誕生的分支(%s)"
 
 #: builtin/fsck.c
-msgid "Checking cache tree"
-msgstr "正在檢查快取樹"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "正在檢查 %s 的快取樹"
 
 #: builtin/fsck.c
 #, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "%s:cache-tree 中無效的 sha1 指標"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s:%s 的 cache-tree 中的 sha1 指標無效"
 
 #: builtin/fsck.c
 msgid "non-tree in cache-tree"
@@ -7633,8 +7718,18 @@
 
 #: builtin/fsck.c
 #, c-format
-msgid "%s: invalid sha1 pointer in resolve-undo"
-msgstr "%s:resolve-undo 的 sha1 指針無效"
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s:%s 的 resolve-undo 中的 sha1 指標無效"
+
+#: builtin/fsck.c
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "無法讀取 “%s” 封裝的修訂版索引 (rev-index)"
+
+#: builtin/fsck.c
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "“%s” 封裝的修訂版索引 (rev-index) 無效"
 
 #: builtin/fsck.c
 msgid ""
@@ -7670,7 +7765,7 @@
 
 #: builtin/fsck.c
 msgid "make reflogs head nodes (default)"
-msgstr "將引用日誌作為檢查的 HEAD 節點(預設)"
+msgstr "將引用日誌作為檢查的 HEAD 節點(預設值)"
 
 #: builtin/fsck.c
 msgid "also consider packs and alternate objects"
@@ -8152,7 +8247,6 @@
 msgid "invalid number of threads specified (%d) for %s"
 msgstr "為 %2$s 設定的執行緒數 (%1$d) 無效"
 
-#. #-#-#-#-#  grep.c.po  #-#-#-#-#
 #. TRANSLATORS: %s is the configuration
 #. variable for tweaking threads, currently
 #. grep.threads
@@ -8224,7 +8318,7 @@
 
 #: builtin/grep.c
 msgid "search in subdirectories (default)"
-msgstr "在子目錄中尋找(預設)"
+msgstr "在子目錄中尋找(預設值)"
 
 #: builtin/grep.c
 msgid "descend at most <depth> levels"
@@ -8236,7 +8330,7 @@
 
 #: builtin/grep.c
 msgid "use basic POSIX regular expressions (default)"
-msgstr "使用基本的 POSIX 常規表示式(預設)"
+msgstr "使用基本的 POSIX 常規表示式(預設值)"
 
 #: builtin/grep.c
 msgid "interpret patterns as fixed strings"
@@ -8581,13 +8675,21 @@
 msgstr "'git help config' 取得更多訊息"
 
 #: builtin/hook.c
-msgid "git hook run [--ignore-missing] <hook-name> [-- <hook-args>]"
-msgstr "git hook run [--ignore-missing] <hook-name> [-- <hook-args>]"
+msgid ""
+"git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-"
+"args>]"
+msgstr ""
+"git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-"
+"args>]"
 
 #: builtin/hook.c
 msgid "silently ignore missing requested <hook-name>"
 msgstr "靜默忽略不存在而請求的 <hook-name>"
 
+#: builtin/hook.c
+msgid "file to read into hooks' stdin"
+msgstr "要讀進掛鉤 stdin 的檔案"
+
 #: builtin/index-pack.c
 #, c-format
 msgid "object type mismatch at %s"
@@ -9314,7 +9416,7 @@
 
 #: builtin/log.c
 msgid "show patch format instead of default (patch + stat)"
-msgstr "顯示純修補檔格式而非預設的(修補檔+狀態)"
+msgstr "顯示純修補檔格式而非預設值(修補檔+狀態)"
 
 #: builtin/log.c
 msgid "Messaging"
@@ -9330,7 +9432,7 @@
 
 #: builtin/log.c
 msgid "email"
-msgstr "信件位址"
+msgstr "信箱"
 
 #: builtin/log.c
 msgid "add To: header"
@@ -9528,7 +9630,7 @@
 
 #: builtin/ls-files.c
 msgid "show cached files in the output (default)"
-msgstr "顯示快取的檔案(預設)"
+msgstr "顯示快取的檔案(預設值)"
 
 #: builtin/ls-files.c
 msgid "show deleted files in the output"
@@ -9629,11 +9731,11 @@
 msgid ""
 "git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
 "              [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n"
-"              [--symref] [<repository> [<refs>...]]"
+"              [--symref] [<repository> [<patterns>...]]"
 msgstr ""
 "git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
 "              [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n"
-"              [--symref] [<repository> [<refs>...]]"
+"              [--symref] [<repository> [<patterns>...]]"
 
 #: builtin/ls-remote.c
 msgid "do not print remote URL"
@@ -9952,9 +10054,17 @@
 msgstr "執行多次合併,一次執行輸入一列"
 
 #: builtin/merge-tree.c
+msgid "specify a merge-base for the merge"
+msgstr "指定用來合併的合併基底"
+
+#: builtin/merge-tree.c
 msgid "--trivial-merge is incompatible with all other options"
 msgstr "--trivial-merge 和其他所有選項都不相容"
 
+#: builtin/merge-tree.c
+msgid "--merge-base is incompatible with --stdin"
+msgstr "--merge-base 與 --stdin 不相容"
+
 #: builtin/merge-tree.c builtin/notes.c
 #, c-format
 msgid "malformed input line: '%s'."
@@ -10015,7 +10125,7 @@
 
 #: builtin/merge.c builtin/pull.c
 msgid "perform a commit if the merge succeeds (default)"
-msgstr "如果合併成功,執行一次提交(預設)"
+msgstr "如果合併成功,執行一次提交(預設值)"
 
 #: builtin/merge.c builtin/pull.c
 msgid "edit message before committing"
@@ -10023,7 +10133,7 @@
 
 #: builtin/merge.c
 msgid "allow fast-forward (default)"
-msgstr "允許快轉(預設)"
+msgstr "允許快轉(預設值)"
 
 #: builtin/merge.c builtin/pull.c
 msgid "abort if fast-forward is not possible"
@@ -10206,7 +10316,7 @@
 msgid "Bad value '%s' in environment '%s'"
 msgstr "環境 '%2$s' 中存在壞的取值 '%1$s'"
 
-#: builtin/merge.c read-cache.c strbuf.c wrapper.c
+#: builtin/merge.c editor.c read-cache.c wrapper.c
 #, c-format
 msgid "could not close '%s'"
 msgstr "不能關閉 '%s'"
@@ -10585,7 +10695,7 @@
 
 #: builtin/name-rev.c
 msgid "allow to print `undefined` names (default)"
-msgstr "允許列印 `未定義` 的名稱(預設)"
+msgstr "允許列印 `未定義` 的名稱(預設值)"
 
 #: builtin/name-rev.c
 msgid "dereference tags in the input (internal use)"
@@ -11039,7 +11149,7 @@
 msgid "wrote %<PRIu32> objects while expecting %<PRIu32>"
 msgstr "寫入 %<PRIu32> 個物件而預期 %<PRIu32> 個"
 
-#: builtin/pack-objects.c
+#: builtin/pack-objects.c builtin/repack.c
 msgid "disabling bitmap writing, as some objects are not being packed"
 msgstr "停用 bitmap 寫入,因為一些物件將不會被打包"
 
@@ -11206,6 +11316,14 @@
 msgstr "壞的索引版本 '%s'"
 
 #: builtin/pack-objects.c
+msgid "show progress meter during object writing phase"
+msgstr "在物件寫入階段顯示進度列"
+
+#: builtin/pack-objects.c
+msgid "similar to --all-progress when progress meter is shown"
+msgstr "顯示進度列時類似 --all-progress"
+
+#: builtin/pack-objects.c
 msgid "<version>[,<offset>]"
 msgstr "<版本>[,<位移>]"
 
@@ -11447,6 +11565,10 @@
 "<git@vger.kernel.org> 讓我們知道您還在使用。\n"
 "感謝。\n"
 
+#: builtin/pack-redundant.c
+msgid "refusing to run without --i-still-use-this"
+msgstr "傳入 --i-still-use-this 前拒絕執行"
+
 #: builtin/pack-refs.c
 msgid "git pack-refs [--all] [--no-prune]"
 msgstr "git pack-refs [--all] [--no-prune]"
@@ -11457,7 +11579,7 @@
 
 #: builtin/pack-refs.c
 msgid "prune loose refs (default)"
-msgstr "剪除鬆散引用(預設)"
+msgstr "剪除鬆散引用(預設值)"
 
 #: builtin/patch-id.c
 msgid "git patch-id [--stable | --unstable | --verbatim]"
@@ -11650,9 +11772,9 @@
 msgid "pull with rebase"
 msgstr "重定基底式拉取"
 
-#: builtin/pull.c
-msgid "please commit or stash them."
-msgstr "請提交或貯存它們。"
+#: builtin/pull.c builtin/rebase.c
+msgid "Please commit or stash them."
+msgstr "請提交或貯存修改。"
 
 #: builtin/pull.c
 #, c-format
@@ -11900,9 +12022,9 @@
 msgid "repository"
 msgstr "版本庫"
 
-#: builtin/push.c builtin/send-pack.c
-msgid "push all refs"
-msgstr "推送所有引用"
+#: builtin/push.c
+msgid "push all branches"
+msgstr "推送所有分支"
 
 #: builtin/push.c builtin/send-pack.c
 msgid "mirror all refs"
@@ -11913,8 +12035,8 @@
 msgstr "刪除引用"
 
 #: builtin/push.c
-msgid "push tags (can't be used with --all or --mirror)"
-msgstr "推送標籤(不能使用 --all or --mirror)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr "推送標籤(不能和 --all、--branches 或 --mirror 一起使用)"
 
 #: builtin/push.c builtin/send-pack.c
 msgid "force updates"
@@ -11972,7 +12094,7 @@
 msgid "--delete doesn't make sense without any refs"
 msgstr "--delete 未接任何引用沒有意義"
 
-#: builtin/push.c
+#: builtin/push.c t/helper/test-bundle-uri.c
 #, c-format
 msgid "bad repository '%s'"
 msgstr "壞的版本庫 '%s'"
@@ -12239,10 +12361,19 @@
 
 #: builtin/rebase.c
 #, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "未知的 rebase-merges 模式:%s"
+
+#: builtin/rebase.c
+#, c-format
 msgid "could not switch to %s"
 msgstr "無法切換到 %s"
 
 #: builtin/rebase.c
+msgid "apply options and merge options cannot be used together"
+msgstr "套用選項與合併選項不得同時使用"
+
+#: builtin/rebase.c
 #, c-format
 msgid ""
 "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
@@ -12250,6 +12381,15 @@
 msgstr "無法識別的 '%s' 空類型;有效的數值有 \"drop\"、\"keep\" 跟 \"ask\"。"
 
 #: builtin/rebase.c
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"有字串引數的 --rebase-merges 已被棄用,而且會在未來的 Git 版本停止運作。請改"
+"用無引數的 --rebase-merges,功能相同。"
+
+#: builtin/rebase.c
 #, c-format
 msgid ""
 "%s\n"
@@ -12513,17 +12653,26 @@
 msgstr "開關 `C' 期望一個數字值"
 
 #: builtin/rebase.c
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "未知模式:%s"
-
-#: builtin/rebase.c
 msgid "--strategy requires --merge or --interactive"
 msgstr "--strategy 需要 --merge 或 --interactive"
 
 #: builtin/rebase.c
-msgid "apply options and merge options cannot be used together"
-msgstr "套用選項與合併選項不得同時使用"
+msgid ""
+"apply options are incompatible with rebase.autoSquash.  Consider adding --no-"
+"autosquash"
+msgstr "apply 選項與 rebase.autoSquash 不相容。請考慮加上 --no-autosquash"
+
+#: builtin/rebase.c
+msgid ""
+"apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
+"no-rebase-merges"
+msgstr "apply 選項與 rebase.rebaseMerges 不相容。請考慮加上 --no-rebase-merges"
+
+#: builtin/rebase.c
+msgid ""
+"apply options are incompatible with rebase.updateRefs.  Consider adding --no-"
+"update-refs"
+msgstr "apply 選項與 rebase.updateRefs 不相容。請考慮加上 --no-update-refs"
 
 #: builtin/rebase.c
 #, c-format
@@ -12573,10 +12722,6 @@
 msgstr "沒有指向一個有效的提交 '%s'"
 
 #: builtin/rebase.c
-msgid "Please commit or stash them."
-msgstr "請提交或貯存修改。"
-
-#: builtin/rebase.c
 msgid "HEAD is up to date."
 msgstr "HEAD 是最新的。"
 
@@ -13375,8 +13520,8 @@
 msgstr "近似日期"
 
 #: builtin/repack.c
-msgid "with -C, expire objects older than this"
-msgstr "搭配 -C 會將早於此的物件設為過期"
+msgid "with --cruft, expire objects older than this"
+msgstr "搭配 --cruft 會將早於此的物件標為過期"
 
 #: builtin/repack.c
 msgid "remove redundant packs, and run git-prune-packed"
@@ -13484,7 +13629,7 @@
 #: builtin/repack.c sequencer.c
 #, c-format
 msgid "could not unlink: %s"
-msgstr "無法取消連結:%s"
+msgstr "無法刪除:%s"
 
 #: builtin/replace.c
 msgid "git replace [-f] <object> <replacement>"
@@ -14209,6 +14354,10 @@
 msgstr "遠端名稱"
 
 #: builtin/send-pack.c
+msgid "push all refs"
+msgstr "推送所有引用"
+
+#: builtin/send-pack.c
 msgid "use stateless RPC protocol"
 msgstr "使用無狀態的 RPC 協定"
 
@@ -14462,9 +14611,11 @@
 
 #: builtin/sparse-checkout.c
 msgid ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable) [<options>]"
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
 
 #: builtin/sparse-checkout.c
 msgid "this worktree is not sparse"
@@ -14605,6 +14756,27 @@
 msgid "error while refreshing working directory"
 msgstr "重新整理工作目錄時發生錯誤"
 
+#: builtin/sparse-checkout.c
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+
+#: builtin/sparse-checkout.c
+msgid "terminate input and output files by a NUL character"
+msgstr "使用 NUL 字元終止輸入和輸出檔案"
+
+#: builtin/sparse-checkout.c
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr ""
+"與 --rules-file 搭配使用時,將 patterns (模式) 解釋為 cone 模式的 patterns"
+
+#: builtin/sparse-checkout.c
+msgid "use patterns in <file> instead of the current ones."
+msgstr "使用 <file> 中的(而非目前使用的)模式。"
+
 #: builtin/stash.c
 msgid "git stash list [<log-options>]"
 msgstr "git stash list [<log-options>]"
@@ -15562,11 +15734,6 @@
 msgid "git submodule--helper <command>"
 msgstr "git submodule--helper <command>"
 
-#: builtin/submodule--helper.c git.c
-#, c-format
-msgid "%s doesn't support --super-prefix"
-msgstr "%s 不支援 --super-prefix"
-
 #: builtin/symbolic-ref.c
 msgid "git symbolic-ref [-m <reason>] <name> <ref>"
 msgstr "git symbolic-ref [-m <reason>] <name> <ref>"
@@ -16470,6 +16637,11 @@
 
 #: bundle-uri.c
 #, c-format
+msgid "could not parse bundle list key %s with value '%s'"
+msgstr "無法解析套件包清單鍵 %s 的值 “%s”"
+
+#: bundle-uri.c
+#, c-format
 msgid "bundle list at '%s' has no mode"
 msgstr "位於 “%s” 的套件包清單沒有模式"
 
@@ -16483,6 +16655,15 @@
 
 #: bundle-uri.c
 #, c-format
+msgid "file downloaded from '%s' is not a bundle"
+msgstr "從 “%s” 下載的檔案不是套件包"
+
+#: bundle-uri.c
+msgid "failed to store maximum creation token"
+msgstr "無法儲存最大的建立權杖"
+
+#: bundle-uri.c
+#, c-format
 msgid "unrecognized bundle mode from URI '%s'"
 msgstr "無法識別從 URI “%s” 取回的套件包模式"
 
@@ -16502,6 +16683,15 @@
 msgstr "位於 URI “%s” 的檔案不是套件包或套件包清單"
 
 #: bundle-uri.c
+#, c-format
+msgid "bundle-uri: unexpected argument: '%s'"
+msgstr "bundle-uri: 非預期的引數:“%s”"
+
+#: bundle-uri.c
+msgid "bundle-uri: expected flush after arguments"
+msgstr "bundle-uri: 引數後應該有一個 flush 包"
+
+#: bundle-uri.c
 msgid "bundle-uri: got an empty line"
 msgstr "bundle-uri: 收到空白列"
 
@@ -16542,6 +16732,12 @@
 msgstr "需要版本庫驗證套件包"
 
 #: bundle.c
+msgid ""
+"some prerequisite commits exist in the object store, but are not connected "
+"to the repository's history"
+msgstr "一些前提提交存在於物件儲存區,但未連接到版本庫的歷史記錄"
+
+#: bundle.c
 #, c-format
 msgid "The bundle contains this ref:"
 msgid_plural "The bundle contains these %<PRIuMAX> refs:"
@@ -16739,7 +16935,7 @@
 
 #: command-list.h
 msgid "Count unpacked number of objects and their disk consumption"
-msgstr "計算未打包物件的數量和磁碟空間占用"
+msgstr "計算未打包物件的數量和磁碟空間佔用"
 
 #: command-list.h
 msgid "Retrieve and store user credentials"
@@ -18108,8 +18304,8 @@
 msgstr "錯誤的 zlib 壓縮級別 %d"
 
 #: config.c
-msgid "core.commentChar should only be one character"
-msgstr "core.commentChar 應該是一個字元"
+msgid "core.commentChar should only be one ASCII character"
+msgstr "core.commentChar 應該是一個 ASCII 字元"
 
 #: config.c
 #, c-format
@@ -18249,6 +18445,11 @@
 
 #: config.c
 #, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr "因為第 %2$<PRIuMAX> 列中 “%1$s” 的文字列太長,故拒絕運作"
+
+#: config.c
+#, c-format
 msgid "missing value for '%s'"
 msgstr "%s 的取值缺少"
 
@@ -18315,6 +18516,19 @@
 
 #: connect.c
 #, c-format
+msgid "error on bundle-uri response line %d: %s"
+msgstr "在 bundle-uri 回應的第 %d 列發現錯誤:%s"
+
+#: connect.c
+msgid "expected flush after bundle-uri listing"
+msgstr "在 bundle-uri 清單後應該有一個 flush 包"
+
+#: connect.c
+msgid "expected response end packet after ref listing"
+msgstr "在引用列表後預期要有回應結束封包"
+
+#: connect.c
+#, c-format
 msgid "invalid ls-refs response: %s"
 msgstr "無效的 ls-refs 回應:%s"
 
@@ -18323,10 +18537,6 @@
 msgstr "在引用列表之後應該有一個 flush 包"
 
 #: connect.c
-msgid "expected response end packet after ref listing"
-msgstr "在引用列表後預期要有回應結束封包"
-
-#: connect.c
 #, c-format
 msgid "protocol '%s' is not supported"
 msgstr "不支援 '%s' 協定"
@@ -18926,7 +19136,7 @@
 #: diff.c
 msgid ""
 "output the distribution of relative amount of changes for each sub-directory"
-msgstr "輸出每個子目錄相對變更的分布"
+msgstr "輸出每個子目錄相對變更的分佈"
 
 #: diff.c
 msgid "synonym for --dirstat=cumulative"
@@ -19039,6 +19249,10 @@
 msgstr "不顯示任何來源和目的地前綴"
 
 #: diff.c
+msgid "use default prefixes a/ and b/"
+msgstr "使用預設的前置名稱 a/ 和 b/"
+
+#: diff.c
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr "顯示指定行數的差異區塊間的上下文"
 
@@ -19407,6 +19621,16 @@
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "提示:等待您的編輯器關閉檔案...%c"
 
+#: editor.c sequencer.c wrapper.c
+#, c-format
+msgid "could not write to '%s'"
+msgstr "不能寫入 '%s'"
+
+#: editor.c
+#, c-format
+msgid "could not edit '%s'"
+msgstr "無法編輯 '%s'"
+
 #: entry.c
 msgid "Filtering content"
 msgstr "過濾內容"
@@ -19727,16 +19951,14 @@
 "           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--"
 "bare]\n"
 "           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
-"           [--super-prefix=<path>] [--config-env=<name>=<envvar>]\n"
-"           <command> [<args>]"
+"           [--config-env=<name>=<envvar>] <command> [<args>]"
 msgstr ""
 "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n"
 "           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
 "           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--"
 "bare]\n"
 "           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
-"           [--super-prefix=<path>] [--config-env=<name>=<envvar>]\n"
-"           <command> [<args>]"
+"           [--config-env=<name>=<envvar>] <command> [<args>]"
 
 #: git.c
 msgid ""
@@ -19767,11 +19989,6 @@
 
 #: git.c
 #, c-format
-msgid "no prefix given for --super-prefix\n"
-msgstr "沒有為 --super-prefix 提供前綴\n"
-
-#: git.c
-#, c-format
 msgid "-c expects a configuration string\n"
 msgstr "應為 -c 提供一個設定字串\n"
 
@@ -19782,6 +19999,11 @@
 
 #: git.c
 #, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "沒有為 --attr-source 提供屬性來源\n"
+
+#: git.c
+#, c-format
 msgid "unknown option: %s\n"
 msgstr "未知選項:%s\n"
 
@@ -19904,8 +20126,13 @@
 msgstr "gpg.ssh.defaultKeyCommand 執行失敗:%s %s"
 
 #: gpg-interface.c
-msgid "gpg failed to sign the data"
-msgstr "gpg 無法為資料簽名"
+#, c-format
+msgid ""
+"gpg failed to sign the data:\n"
+"%s"
+msgstr ""
+"gpg 無法簽名資料:\n"
+"%s"
 
 #: gpg-interface.c
 msgid "user.signingKey needs to be set for ssh signing"
@@ -20566,7 +20793,7 @@
 #. conflict in a submodule. The first argument is the submodule
 #. name, and the second argument is the abbreviated id of the
 #. commit that needs to be merged.  For example:
-#.  - go to submodule (mysubmodule), and either merge commit abc1234"
+#. - go to submodule (mysubmodule), and either merge commit abc1234"
 #.
 #: merge-ort.c
 #, c-format
@@ -20755,7 +20982,7 @@
 
 #: merge-recursive.c
 msgid "renamed"
-msgstr "重新命名"
+msgstr "已重新命名"
 
 #: merge-recursive.c
 #, c-format
@@ -21250,6 +21477,11 @@
 
 #: object-file.c
 #, c-format
+msgid "unable to open loose object %s"
+msgstr "無法打開鬆散物件 %s"
+
+#: object-file.c
+#, c-format
 msgid "unable to parse %s header"
 msgstr "無法解析 %s 頭部"
 
@@ -21269,8 +21501,8 @@
 
 #: object-file.c
 #, c-format
-msgid "failed to read object %s"
-msgstr "讀取物件 %s 失敗"
+msgid "loose object %s (stored in %s) is corrupt"
+msgstr "鬆散物件 %s(儲存在 %s)已損壞"
 
 #: object-file.c
 #, c-format
@@ -21279,11 +21511,6 @@
 
 #: object-file.c
 #, c-format
-msgid "loose object %s (stored in %s) is corrupt"
-msgstr "鬆散物件 %s(儲存在 %s)已損壞"
-
-#: object-file.c
-#, c-format
 msgid "packed object %s (stored in %s) is corrupt"
 msgstr "打包物件 %s(儲存在 %s)已損壞"
 
@@ -21298,10 +21525,6 @@
 msgstr "無法為 '%s' 設定權限"
 
 #: object-file.c
-msgid "file write error"
-msgstr "檔案寫錯誤"
-
-#: object-file.c
 msgid "error when closing loose object file"
 msgstr "關閉鬆散物件檔案時發生錯誤"
 
@@ -21359,12 +21582,13 @@
 msgstr "不能讀取物件 %s"
 
 #: object-file.c
-msgid "corrupt commit"
-msgstr "損壞的提交"
+#, c-format
+msgid "object fails fsck: %s"
+msgstr "物件 fsck 失敗:%s"
 
 #: object-file.c
-msgid "corrupt tag"
-msgstr "損壞的標籤"
+msgid "refusing to create malformed object"
+msgstr "拒絕建立格式錯誤的物件"
 
 #: object-file.c
 #, c-format
@@ -21433,7 +21657,7 @@
 #. TRANSLATORS: This is a line of ambiguous commit
 #. object output. E.g.:
 #. *
-#.    "deadbeef commit 2021-01-01 - Some Commit Message"
+#. "deadbeef commit 2021-01-01 - Some Commit Message"
 #.
 #: object-name.c
 #, c-format
@@ -21443,7 +21667,7 @@
 #. TRANSLATORS: This is a line of ambiguous
 #. tag object output. E.g.:
 #. *
-#.    "deadbeef tag 2022-01-01 - Some Tag Message"
+#. "deadbeef tag 2022-01-01 - Some Tag Message"
 #. *
 #. The second argument is the YYYY-MM-DD found
 #. in the tag.
@@ -21460,7 +21684,7 @@
 #. tag object output where we couldn't parse
 #. the tag itself. E.g.:
 #. *
-#.    "deadbeef [bad tag, could not parse it]"
+#. "deadbeef [bad tag, could not parse it]"
 #.
 #: object-name.c
 #, c-format
@@ -21676,11 +21900,6 @@
 msgstr "無法 fstat 位圖檔案"
 
 #: pack-bitmap.c
-#, c-format
-msgid "ignoring extra bitmap file: '%s'"
-msgstr "忽略多出來的位圖檔案:「%s」"
-
-#: pack-bitmap.c
 msgid "checksum doesn't match in MIDX and bitmap"
 msgstr "總和檢查碼在 MIDX 和位圖中無符合項目"
 
@@ -21763,6 +21982,11 @@
 msgid "unable to get disk usage of '%s'"
 msgstr "無法取得「%s」的磁碟用量"
 
+#: pack-bitmap.c
+#, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "“%s” 位圖檔案的總和檢查碼無效"
+
 #: pack-mtimes.c
 #, c-format
 msgid "mtimes file %s is too small"
@@ -21813,6 +22037,15 @@
 msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
 msgstr "倒排索引檔案 %s 有不支援的雜湊 ID %<PRIu32>"
 
+#: pack-revindex.c
+msgid "invalid checksum"
+msgstr "無效的總和檢查碼"
+
+#: pack-revindex.c
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr "%<PRIu64> 位置的修訂版索引 (rev-index) 無效:%<PRIu32> != %<PRIu32>"
+
 #: pack-write.c
 msgid "cannot both write and verify reverse index"
 msgstr "無法同時寫入和驗證倒排索引"
@@ -22007,6 +22240,10 @@
 msgstr "用 <n> 位數字顯示物件名稱"
 
 #: parse-options.h
+msgid "prefixed path to initial superproject"
+msgstr "初始父專案的前綴路徑"
+
+#: parse-options.h
 msgid "how to strip spaces and #comments from message"
 msgstr "設定如何刪除提交說明裡的空格和 #備註"
 
@@ -22589,6 +22826,16 @@
 
 #: ref-filter.c
 #, c-format
+msgid "%%(%.*s) does not take arguments"
+msgstr "%%(%.*s) 不取引數"
+
+#: ref-filter.c
+#, c-format
+msgid "unrecognized %%(%.*s) argument: %s"
+msgstr "無法識別的 %%(%.*s) 引數:%s"
+
+#: ref-filter.c
+#, c-format
 msgid "expected format: %%(color:<color>)"
 msgstr "期望的格式:%%(color:<顏色>)"
 
@@ -22609,26 +22856,6 @@
 
 #: ref-filter.c
 #, c-format
-msgid "unrecognized %%(%s) argument: %s"
-msgstr "無法識別的 %%(%s) 參數:%s"
-
-#: ref-filter.c
-#, c-format
-msgid "%%(objecttype) does not take arguments"
-msgstr "%%(objecttype) 不帶參數"
-
-#: ref-filter.c
-#, c-format
-msgid "%%(deltabase) does not take arguments"
-msgstr "%%(deltabase) 不帶參數"
-
-#: ref-filter.c
-#, c-format
-msgid "%%(body) does not take arguments"
-msgstr "%%(body) 不帶參數"
-
-#: ref-filter.c
-#, c-format
 msgid "expected %%(trailers:key=<value>)"
 msgstr "預期是 %%(trailers:key=<value>)"
 
@@ -22649,11 +22876,6 @@
 
 #: ref-filter.c
 #, c-format
-msgid "unrecognized email option: %s"
-msgstr "無法識別的 email 選項:%s"
-
-#: ref-filter.c
-#, c-format
 msgid "expected format: %%(align:<width>,<position>)"
 msgstr "期望的格式:%%(align:<寬度>,<位置>)"
 
@@ -22669,13 +22891,18 @@
 
 #: ref-filter.c
 #, c-format
+msgid "unrecognized %%(%s) argument: %s"
+msgstr "無法識別的 %%(%s) 參數:%s"
+
+#: ref-filter.c
+#, c-format
 msgid "positive width expected with the %%(align) atom"
 msgstr "元素 %%(align) 需要一個正數的寬度"
 
 #: ref-filter.c
 #, c-format
-msgid "%%(rest) does not take arguments"
-msgstr "%%(rest) 未取引數"
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "預期格式:%%(ahead-behind:<committish>)"
 
 #: ref-filter.c
 #, c-format
@@ -23413,7 +23640,7 @@
 #: rerere.c
 #, c-format
 msgid "cannot unlink stray '%s'"
-msgstr "不能刪除 stray '%s'"
+msgstr "無法刪除失散檔案 “%s”"
 
 #: rerere.c
 #, c-format
@@ -23432,11 +23659,6 @@
 
 #: rerere.c
 #, c-format
-msgid "cannot unlink '%s'"
-msgstr "不能刪除 '%s'"
-
-#: rerere.c
-#, c-format
 msgid "Updated preimage for '%s'"
 msgstr "已為 '%s' 更新 preimage"
 
@@ -23851,11 +24073,6 @@
 msgid "could not lock '%s'"
 msgstr "不能鎖定 '%s'"
 
-#: sequencer.c strbuf.c wrapper.c
-#, c-format
-msgid "could not write to '%s'"
-msgstr "不能寫入 '%s'"
-
 #: sequencer.c
 #, c-format
 msgid "could not write eol to '%s'"
@@ -24185,6 +24402,26 @@
 
 #: sequencer.c
 #, c-format
+msgid "'%s' is not a valid label"
+msgstr "“%s” 不是有效的標籤"
+
+#: sequencer.c
+#, c-format
+msgid "'%s' is not a valid refname"
+msgstr "“%s” 不是有效的引用名稱"
+
+#: sequencer.c
+#, c-format
+msgid "update-ref requires a fully qualified refname e.g. refs/heads/%s"
+msgstr "update-ref 需要完全限定的引用名稱,比如:refs/heads/%s"
+
+#: sequencer.c
+#, c-format
+msgid "invalid command '%.*s'"
+msgstr "無效的命令 “%.*s”"
+
+#: sequencer.c
+#, c-format
 msgid "%s does not accept arguments: '%s'"
 msgstr "%s 不接受參數:'%s'"
 
@@ -24274,10 +24511,6 @@
 msgstr "不能建立序列目錄 '%s'"
 
 #: sequencer.c
-msgid "could not lock HEAD"
-msgstr "不能鎖定 HEAD"
-
-#: sequencer.c
 msgid "no cherry-pick or revert in progress"
 msgstr "揀選或還原動作並未進行"
 
@@ -24392,22 +24625,22 @@
 "\n"
 
 #: sequencer.c
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "並且修改索引和/或工作區\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "並且更改索引和(或)工作區。\n"
 
 #: sequencer.c
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
 msgstr ""
 "執行成功:%s\n"
-"但是在索引和/或工作區中存在變更\n"
-"提交或貯存修改,然後執行\n"
+"但是在索引和(或)工作區中存在變更。\n"
+"請提交或貯存修改,然後執行\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
@@ -24924,11 +25157,6 @@
 msgid_plural "%u bytes/s"
 msgstr[0] "%u 位元組/秒"
 
-#: strbuf.c
-#, c-format
-msgid "could not edit '%s'"
-msgstr "無法編輯 '%s'"
-
 #: submodule-config.c
 #, c-format
 msgid "ignoring suspicious submodule name: %s"
@@ -25139,6 +25367,19 @@
 msgid "failed to lstat '%s'"
 msgstr "無法 lstat “%s”"
 
+#: t/helper/test-bundle-uri.c
+msgid "no remote configured to get bundle URIs from"
+msgstr "沒有設定可以用來取得套件包 URIs 的遠端"
+
+#: t/helper/test-bundle-uri.c
+#, c-format
+msgid "remote '%s' has no configured URL"
+msgstr "“%s” 遠端未設定 URL"
+
+#: t/helper/test-bundle-uri.c
+msgid "could not get the bundle-uri list"
+msgstr "無法取得 bundle-uri 清單"
+
 #: t/helper/test-cache-tree.c
 msgid "test-tool cache-tree <options> (control|prime|update)"
 msgstr "test-tool cache-tree <options> (control|prime|update)"
@@ -25575,6 +25816,14 @@
 msgid "failed to push all needed submodules"
 msgstr "不能推送全部需要的子模組"
 
+#: transport.c
+msgid "bundle-uri operation not supported by protocol"
+msgstr "通訊協定不支援 bundle-uri 動作"
+
+#: transport.c
+msgid "could not retrieve server-advertised bundle-uri list"
+msgstr "無法取得伺服器公佈的 bundle-uri 清單"
+
 #: tree-walk.c
 msgid "too-short tree object"
 msgstr "太短的樹狀物件"
@@ -26489,12 +26738,20 @@
 #: wt-status.c
 #, c-format
 msgid ""
-"It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
-"may speed it up, but you have to be careful not to forget to add\n"
-"new files yourself (see 'git help status')."
+"It took %.2f seconds to enumerate untracked files,\n"
+"but the results were cached, and subsequent runs may be faster."
 msgstr ""
-"耗費了 %.2f 秒以枚舉未追蹤的檔案。'status -uno' 也許能提高速度,\n"
-"但您需要小心不要忘了新增新檔案(參見 'git help status')。"
+"列舉未追蹤檔案花費 %.2f 秒,\n"
+"不過已經快取結果,之後執行的速度或許能比較快。"
+
+#: wt-status.c
+#, c-format
+msgid "It took %.2f seconds to enumerate untracked files."
+msgstr "列舉未追蹤檔案花費 %.2f 秒。"
+
+#: wt-status.c
+msgid "See 'git help status' for information on how to improve this."
+msgstr "請參閱 “git help status” 深入了解如何改善。"
 
 #: wt-status.c
 #, c-format
@@ -26670,297 +26927,6 @@
 msgid "Unable to determine absolute path of git directory"
 msgstr "不能確定 git 目錄的絕對路徑"
 
-#. TRANSLATORS: you can adjust this to align "git add -i" status menu
-#: git-add--interactive.perl
-#, perl-format
-msgid "%12s %12s %s"
-msgstr "%12s %12s %s"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "touched %d path\n"
-msgid_plural "touched %d paths\n"
-msgstr[0] "建立了 %d 個路徑\n"
-
-#: git-add--interactive.perl
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for staging."
-msgstr "如果修補檔能完全套用,編輯區塊將立即標記為暫存。"
-
-#: git-add--interactive.perl
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for stashing."
-msgstr "如果修補檔能完全套用,編輯區塊將立即標記為貯存。"
-
-#: git-add--interactive.perl
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for unstaging."
-msgstr "如果修補檔能完全套用,編輯區塊將立即標記為未暫存。"
-
-#: git-add--interactive.perl
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for applying."
-msgstr "如果修補檔能完全套用,編輯區塊將立即標記為套用。"
-
-#: git-add--interactive.perl
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for discarding."
-msgstr "如果修補檔能完全套用,編輯塊將立即標記為捨棄。"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "failed to open hunk edit file for writing: %s"
-msgstr "為寫入開啟區塊編輯檔案失敗:%s"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid ""
-"---\n"
-"To remove '%s' lines, make them ' ' lines (context).\n"
-"To remove '%s' lines, delete them.\n"
-"Lines starting with %s will be removed.\n"
-msgstr ""
-"---\n"
-"要刪除 '%s' 開始的行,使其成為 ' ' 開始的行(上下文)。\n"
-"要刪除 '%s' 開始的行,刪除它們。\n"
-"以 %s 開始的行將被刪除。\n"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "failed to open hunk edit file for reading: %s"
-msgstr "無法讀取區塊編輯檔案:%s"
-
-#: git-add--interactive.perl
-msgid ""
-"y - stage this hunk\n"
-"n - do not stage this hunk\n"
-"q - quit; do not stage this hunk or any of the remaining ones\n"
-"a - stage this hunk and all later hunks in the file\n"
-"d - do not stage this hunk or any of the later hunks in the file"
-msgstr ""
-"y - 暫存此區塊\n"
-"n - 不要暫存此區塊\n"
-"q - 離開。不暫存此區塊及後面的全部區塊\n"
-"a - 暫存此區塊和本檔案中後面的全部區塊\n"
-"d - 不暫存此區塊和本檔案中後面的全部區塊"
-
-#: git-add--interactive.perl
-msgid ""
-"y - stash this hunk\n"
-"n - do not stash this hunk\n"
-"q - quit; do not stash this hunk or any of the remaining ones\n"
-"a - stash this hunk and all later hunks in the file\n"
-"d - do not stash this hunk or any of the later hunks in the file"
-msgstr ""
-"y - 貯存此區塊\n"
-"n - 不要貯存此區塊\n"
-"q - 離開。不貯存此區塊及後面的全部區塊\n"
-"a - 貯存此區塊和本檔案中後面的全部區塊\n"
-"d - 不貯存此區塊和本檔案中後面的全部區塊"
-
-#: git-add--interactive.perl
-msgid ""
-"y - unstage this hunk\n"
-"n - do not unstage this hunk\n"
-"q - quit; do not unstage this hunk or any of the remaining ones\n"
-"a - unstage this hunk and all later hunks in the file\n"
-"d - do not unstage this hunk or any of the later hunks in the file"
-msgstr ""
-"y - 不暫存此區塊\n"
-"n - 不要不暫存此區塊\n"
-"q - 離開。不要不暫存此區塊及後面的全部區塊\n"
-"a - 不暫存此區塊和本檔案中後面的全部區塊\n"
-"d - 不要不暫存此區塊和本檔案中後面的全部區塊"
-
-#: git-add--interactive.perl
-msgid ""
-"y - apply this hunk to index\n"
-"n - do not apply this hunk to index\n"
-"q - quit; do not apply this hunk or any of the remaining ones\n"
-"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"
-msgstr ""
-"y - 在索引中套用此區塊\n"
-"n - 不要在索引中套用此區塊\n"
-"q - 離開。不要套用此區塊及後面的全部區塊\n"
-"a - 套用此區塊和本檔案中後面的全部區塊\n"
-"d - 不要套用此區塊和本檔案中後面的全部區塊"
-
-#: git-add--interactive.perl
-msgid ""
-"y - discard this hunk from worktree\n"
-"n - do not discard this hunk from worktree\n"
-"q - quit; do not discard this hunk or any of the remaining ones\n"
-"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"
-msgstr ""
-"y - 在工作區中捨棄此區塊\n"
-"n - 不要在工作區中捨棄此區塊\n"
-"q - 離開。不要捨棄此區塊及後面的全部區塊\n"
-"a - 捨棄此區塊和本檔案中後面的全部區塊\n"
-"d - 不要捨棄此區塊和本檔案中後面的全部區塊"
-
-#: git-add--interactive.perl
-msgid ""
-"y - discard this hunk from index and worktree\n"
-"n - do not discard this hunk from index and worktree\n"
-"q - quit; do not discard this hunk or any of the remaining ones\n"
-"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"
-msgstr ""
-"y - 在索引和工作區中捨棄此區塊\n"
-"n - 不要在索引和工作區中捨棄此區塊\n"
-"q - 離開。不要捨棄此區塊及後面的全部區塊\n"
-"a - 捨棄此區塊和本檔案中後面的全部區塊\n"
-"d - 不要捨棄此區塊和本檔案中後面的全部區塊"
-
-#: git-add--interactive.perl
-msgid ""
-"y - apply this hunk to index and worktree\n"
-"n - do not apply this hunk to index and worktree\n"
-"q - quit; do not apply this hunk or any of the remaining ones\n"
-"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"
-msgstr ""
-"y - 在索引和工作區中套用此區塊\n"
-"n - 不要在索引和工作區中套用此區塊\n"
-"q - 離開。不要套用此區塊及後面的全部區塊\n"
-"a - 套用此區塊和本檔案中後面的全部區塊\n"
-"d - 不要套用此區塊和本檔案中後面的全部區塊"
-
-#: git-add--interactive.perl
-msgid ""
-"y - apply this hunk to worktree\n"
-"n - do not apply this hunk to worktree\n"
-"q - quit; do not apply this hunk or any of the remaining ones\n"
-"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"
-msgstr ""
-"y - 在工作區中套用此區塊\n"
-"n - 不要在工作區中套用此區塊\n"
-"q - 離開。不要套用此區塊及後面的全部區塊\n"
-"a - 套用此區塊和本檔案中後面的全部區塊\n"
-"d - 不要套用此區塊和本檔案中後面的全部區塊"
-
-#: git-add--interactive.perl
-msgid ""
-"g - select a hunk to go to\n"
-"/ - search for a hunk matching the given regex\n"
-"j - leave this hunk undecided, see next undecided hunk\n"
-"J - leave this hunk undecided, see next hunk\n"
-"k - leave this hunk undecided, see previous undecided hunk\n"
-"K - leave this hunk undecided, see previous hunk\n"
-"s - split the current hunk into smaller hunks\n"
-"e - manually edit the current hunk\n"
-"? - print help\n"
-msgstr ""
-"g - 選擇跳轉到一個區塊\n"
-"/ - 尋找和提供常規表示式符合的區塊\n"
-"j - 維持此區塊未決狀態,檢視下一個未決定區塊\n"
-"J - 維持此區塊未決狀態,檢視下一個區塊\n"
-"k - 維持此區塊未決狀態,檢視上一個未決定區塊\n"
-"K - 維持此區塊未決狀態,檢視上一個區塊\n"
-"s - 分割目前區塊為更小的區塊\n"
-"e - 手動編輯目前區塊\n"
-"? - 顯示說明\n"
-
-#: git-add--interactive.perl
-msgid "The selected hunks do not apply to the index!\n"
-msgstr "選取區塊不能套用到索引!\n"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "ignoring unmerged: %s\n"
-msgstr "忽略未套用的:%s\n"
-
-#: git-add--interactive.perl
-msgid "No other hunks to goto\n"
-msgstr "沒有其它可供跳轉的區塊\n"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "Invalid number: '%s'\n"
-msgstr "無效數字:'%s'\n"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "Sorry, only %d hunk available.\n"
-msgid_plural "Sorry, only %d hunks available.\n"
-msgstr[0] "對不起,只有 %d 個可用區塊。\n"
-
-#: git-add--interactive.perl
-msgid "No other hunks to search\n"
-msgstr "沒有其它可供尋找的區塊\n"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "Malformed search regexp %s: %s\n"
-msgstr "錯誤的常規表示式 %s:%s\n"
-
-#: git-add--interactive.perl
-msgid "No hunk matches the given pattern\n"
-msgstr "沒有和提供模式相符合的區塊\n"
-
-#: git-add--interactive.perl
-msgid "No previous hunk\n"
-msgstr "沒有上一個區塊\n"
-
-#: git-add--interactive.perl
-msgid "No next hunk\n"
-msgstr "沒有下一個區塊\n"
-
-#: git-add--interactive.perl
-msgid "Sorry, cannot split this hunk\n"
-msgstr "對不起,不能分割這個區塊\n"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "Split into %d hunk.\n"
-msgid_plural "Split into %d hunks.\n"
-msgstr[0] "分割為 %d 塊。\n"
-
-#: git-add--interactive.perl
-msgid "Sorry, cannot edit this hunk\n"
-msgstr "對不起,不能編輯這個區塊\n"
-
-#. TRANSLATORS: please do not translate the command names
-#. 'status', 'update', 'revert', etc.
-#: git-add--interactive.perl
-msgid ""
-"status        - show paths with changes\n"
-"update        - add working tree state to the staged set of changes\n"
-"revert        - revert staged set of changes back to the HEAD version\n"
-"patch         - pick hunks and update selectively\n"
-"diff          - view diff between HEAD and index\n"
-"add untracked - add contents of untracked files to the staged set of "
-"changes\n"
-msgstr ""
-"status        - 顯示含變更的路徑\n"
-"update        - 新增工作區狀態至暫存列表\n"
-"revert        - 還原修改的暫存集至 HEAD 版本\n"
-"patch         - 挑選區塊並且有選擇地更新\n"
-"diff          - 顯示 HEAD 和索引間差異\n"
-"add untracked - 新增未追蹤檔案的內容至暫存列表\n"
-
-#: git-add--interactive.perl
-msgid "missing --"
-msgstr "缺少 --"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "unknown --patch mode: %s"
-msgstr "未知的 --patch 模式:%s"
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "invalid argument %s, expecting --"
-msgstr "無效的參數 %s,期望是 --"
-
 #: git-send-email.perl
 msgid "local zone differs from GMT by a non-minute interval\n"
 msgstr "本機時間和 GMT 有不到一分鐘間隔\n"
@@ -27282,8 +27248,8 @@
 
 #: git-send-email.perl
 #, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) 新增 %s: %s 自:'%s'\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) 從 “%s” 讀到格式錯誤的輸出"
 
 #: git-send-email.perl
 #, perl-format
@@ -27291,6 +27257,11 @@
 msgstr "(%s) 無法關閉管道至 '%s'"
 
 #: git-send-email.perl
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) 新增 %s: %s 自:'%s'\n"
+
+#: git-send-email.perl
 msgid "cannot send message as 7bit"
 msgstr "不能以 7bit 形式傳送訊息"
 
@@ -27334,6 +27305,356 @@
 msgid "Do you really want to send %s? [y|N]: "
 msgstr "您真的要傳送 %s?[y|N]: "
 
+#~ msgid "current working directory is untracked"
+#~ msgstr "尚未追蹤目前的工作目錄"
+
+#~ msgid "cannot use --contents with final commit object name"
+#~ msgstr "無法將 --contents 與最終的提交物件名稱共用"
+
+#~ msgid "git bisect--helper --bisect-state (bad|new) [<rev>]"
+#~ msgstr "git bisect--helper --bisect-state (bad|new) [<rev>]"
+
+#~ msgid "won't bisect on cg-seek'ed tree"
+#~ msgstr "不會在做了 cg-seek 的樹狀物件上進行二分搜尋"
+
+#~ msgid "--bisect-terms requires 0 or 1 argument"
+#~ msgstr "--bisect-terms 需要 0 或 1 個引數"
+
+#~ msgid "--bisect-next requires 0 arguments"
+#~ msgstr "--bisect-next 需要 0 個引數"
+
+#~ msgid "--bisect-log requires 0 arguments"
+#~ msgstr "--bisect-log 需要 0 個引數"
+
+#~ msgid "git env--helper --type=[bool|ulong] <options> <env-var>"
+#~ msgstr "git env--helper --type=[bool|ulong] <選項> <環境變數>"
+
+#~ msgid "default for git_env_*(...) to fall back on"
+#~ msgstr "git_env_*(...) 的預設值"
+
+#~ msgid "be quiet only use git_env_*() value as exit code"
+#~ msgstr "安靜模式,只使用 git_env_*() 的值作為離開碼"
+
+#, c-format
+#~ msgid ""
+#~ "option `--default' expects a boolean value with `--type=bool`, not `%s`"
+#~ msgstr "選項「--default」預期收到「--type=bool」的布林值,而非「%s」"
+
+#, c-format
+#~ msgid ""
+#~ "option `--default' expects an unsigned long value with `--type=ulong`, "
+#~ "not `%s`"
+#~ msgstr ""
+#~ "選項「--default」預期收到「--type=ulong」的無號 long 數值,而非「%s」"
+
+#~ msgid "please commit or stash them."
+#~ msgstr "請提交或貯存它們。"
+
+#, c-format
+#~ msgid "Unknown mode: %s"
+#~ msgstr "未知模式:%s"
+
+#, c-format
+#~ msgid "%s doesn't support --super-prefix"
+#~ msgstr "%s 不支援 --super-prefix"
+
+#, c-format
+#~ msgid "no prefix given for --super-prefix\n"
+#~ msgstr "沒有為 --super-prefix 提供前綴\n"
+
+#, c-format
+#~ msgid "failed to read object %s"
+#~ msgstr "讀取物件 %s 失敗"
+
+#~ msgid "file write error"
+#~ msgstr "檔案寫錯誤"
+
+#~ msgid "corrupt commit"
+#~ msgstr "損壞的提交"
+
+#~ msgid "corrupt tag"
+#~ msgstr "損壞的標籤"
+
+#, c-format
+#~ msgid "%%(objecttype) does not take arguments"
+#~ msgstr "%%(objecttype) 不帶參數"
+
+#, c-format
+#~ msgid "%%(deltabase) does not take arguments"
+#~ msgstr "%%(deltabase) 不帶參數"
+
+#, c-format
+#~ msgid "%%(body) does not take arguments"
+#~ msgstr "%%(body) 不帶參數"
+
+#, c-format
+#~ msgid "unrecognized email option: %s"
+#~ msgstr "無法識別的 email 選項:%s"
+
+#~ msgid "could not lock HEAD"
+#~ msgstr "不能鎖定 HEAD"
+
+#, c-format
+#~ msgid ""
+#~ "It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
+#~ "may speed it up, but you have to be careful not to forget to add\n"
+#~ "new files yourself (see 'git help status')."
+#~ msgstr ""
+#~ "耗費了 %.2f 秒以枚舉未追蹤的檔案。'status -uno' 也許能提高速度,\n"
+#~ "但您需要小心不要忘了新增新檔案(參見 'git help status')。"
+
+#, perl-format
+#~ msgid "%12s %12s %s"
+#~ msgstr "%12s %12s %s"
+
+#, perl-format
+#~ msgid "touched %d path\n"
+#~ msgid_plural "touched %d paths\n"
+#~ msgstr[0] "建立了 %d 個路徑\n"
+
+#~ msgid ""
+#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
+#~ "marked for staging."
+#~ msgstr "如果修補檔能完全套用,編輯區塊將立即標記為暫存。"
+
+#~ msgid ""
+#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
+#~ "marked for stashing."
+#~ msgstr "如果修補檔能完全套用,編輯區塊將立即標記為貯存。"
+
+#~ msgid ""
+#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
+#~ "marked for unstaging."
+#~ msgstr "如果修補檔能完全套用,編輯區塊將立即標記為未暫存。"
+
+#~ msgid ""
+#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
+#~ "marked for applying."
+#~ msgstr "如果修補檔能完全套用,編輯區塊將立即標記為套用。"
+
+#~ msgid ""
+#~ "If the patch applies cleanly, the edited hunk will immediately be\n"
+#~ "marked for discarding."
+#~ msgstr "如果修補檔能完全套用,編輯塊將立即標記為捨棄。"
+
+#, perl-format
+#~ msgid "failed to open hunk edit file for writing: %s"
+#~ msgstr "為寫入開啟區塊編輯檔案失敗:%s"
+
+#, perl-format
+#~ msgid ""
+#~ "---\n"
+#~ "To remove '%s' lines, make them ' ' lines (context).\n"
+#~ "To remove '%s' lines, delete them.\n"
+#~ "Lines starting with %s will be removed.\n"
+#~ msgstr ""
+#~ "---\n"
+#~ "要刪除 '%s' 開始的行,使其成為 ' ' 開始的行(上下文)。\n"
+#~ "要刪除 '%s' 開始的行,刪除它們。\n"
+#~ "以 %s 開始的行將被刪除。\n"
+
+#, perl-format
+#~ msgid "failed to open hunk edit file for reading: %s"
+#~ msgstr "無法讀取區塊編輯檔案:%s"
+
+#~ msgid ""
+#~ "y - stage this hunk\n"
+#~ "n - do not stage this hunk\n"
+#~ "q - quit; do not stage this hunk or any of the remaining ones\n"
+#~ "a - stage this hunk and all later hunks in the file\n"
+#~ "d - do not stage this hunk or any of the later hunks in the file"
+#~ msgstr ""
+#~ "y - 暫存此區塊\n"
+#~ "n - 不要暫存此區塊\n"
+#~ "q - 離開。不暫存此區塊及後面的全部區塊\n"
+#~ "a - 暫存此區塊和本檔案中後面的全部區塊\n"
+#~ "d - 不暫存此區塊和本檔案中後面的全部區塊"
+
+#~ msgid ""
+#~ "y - stash this hunk\n"
+#~ "n - do not stash this hunk\n"
+#~ "q - quit; do not stash this hunk or any of the remaining ones\n"
+#~ "a - stash this hunk and all later hunks in the file\n"
+#~ "d - do not stash this hunk or any of the later hunks in the file"
+#~ msgstr ""
+#~ "y - 貯存此區塊\n"
+#~ "n - 不要貯存此區塊\n"
+#~ "q - 離開。不貯存此區塊及後面的全部區塊\n"
+#~ "a - 貯存此區塊和本檔案中後面的全部區塊\n"
+#~ "d - 不貯存此區塊和本檔案中後面的全部區塊"
+
+#~ msgid ""
+#~ "y - unstage this hunk\n"
+#~ "n - do not unstage this hunk\n"
+#~ "q - quit; do not unstage this hunk or any of the remaining ones\n"
+#~ "a - unstage this hunk and all later hunks in the file\n"
+#~ "d - do not unstage this hunk or any of the later hunks in the file"
+#~ msgstr ""
+#~ "y - 不暫存此區塊\n"
+#~ "n - 不要不暫存此區塊\n"
+#~ "q - 離開。不要不暫存此區塊及後面的全部區塊\n"
+#~ "a - 不暫存此區塊和本檔案中後面的全部區塊\n"
+#~ "d - 不要不暫存此區塊和本檔案中後面的全部區塊"
+
+#~ msgid ""
+#~ "y - apply this hunk to index\n"
+#~ "n - do not apply this hunk to index\n"
+#~ "q - quit; do not apply this hunk or any of the remaining ones\n"
+#~ "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"
+#~ msgstr ""
+#~ "y - 在索引中套用此區塊\n"
+#~ "n - 不要在索引中套用此區塊\n"
+#~ "q - 離開。不要套用此區塊及後面的全部區塊\n"
+#~ "a - 套用此區塊和本檔案中後面的全部區塊\n"
+#~ "d - 不要套用此區塊和本檔案中後面的全部區塊"
+
+#~ msgid ""
+#~ "y - discard this hunk from worktree\n"
+#~ "n - do not discard this hunk from worktree\n"
+#~ "q - quit; do not discard this hunk or any of the remaining ones\n"
+#~ "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"
+#~ msgstr ""
+#~ "y - 在工作區中捨棄此區塊\n"
+#~ "n - 不要在工作區中捨棄此區塊\n"
+#~ "q - 離開。不要捨棄此區塊及後面的全部區塊\n"
+#~ "a - 捨棄此區塊和本檔案中後面的全部區塊\n"
+#~ "d - 不要捨棄此區塊和本檔案中後面的全部區塊"
+
+#~ msgid ""
+#~ "y - discard this hunk from index and worktree\n"
+#~ "n - do not discard this hunk from index and worktree\n"
+#~ "q - quit; do not discard this hunk or any of the remaining ones\n"
+#~ "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"
+#~ msgstr ""
+#~ "y - 在索引和工作區中捨棄此區塊\n"
+#~ "n - 不要在索引和工作區中捨棄此區塊\n"
+#~ "q - 離開。不要捨棄此區塊及後面的全部區塊\n"
+#~ "a - 捨棄此區塊和本檔案中後面的全部區塊\n"
+#~ "d - 不要捨棄此區塊和本檔案中後面的全部區塊"
+
+#~ msgid ""
+#~ "y - apply this hunk to index and worktree\n"
+#~ "n - do not apply this hunk to index and worktree\n"
+#~ "q - quit; do not apply this hunk or any of the remaining ones\n"
+#~ "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"
+#~ msgstr ""
+#~ "y - 在索引和工作區中套用此區塊\n"
+#~ "n - 不要在索引和工作區中套用此區塊\n"
+#~ "q - 離開。不要套用此區塊及後面的全部區塊\n"
+#~ "a - 套用此區塊和本檔案中後面的全部區塊\n"
+#~ "d - 不要套用此區塊和本檔案中後面的全部區塊"
+
+#~ msgid ""
+#~ "y - apply this hunk to worktree\n"
+#~ "n - do not apply this hunk to worktree\n"
+#~ "q - quit; do not apply this hunk or any of the remaining ones\n"
+#~ "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"
+#~ msgstr ""
+#~ "y - 在工作區中套用此區塊\n"
+#~ "n - 不要在工作區中套用此區塊\n"
+#~ "q - 離開。不要套用此區塊及後面的全部區塊\n"
+#~ "a - 套用此區塊和本檔案中後面的全部區塊\n"
+#~ "d - 不要套用此區塊和本檔案中後面的全部區塊"
+
+#~ msgid ""
+#~ "g - select a hunk to go to\n"
+#~ "/ - search for a hunk matching the given regex\n"
+#~ "j - leave this hunk undecided, see next undecided hunk\n"
+#~ "J - leave this hunk undecided, see next hunk\n"
+#~ "k - leave this hunk undecided, see previous undecided hunk\n"
+#~ "K - leave this hunk undecided, see previous hunk\n"
+#~ "s - split the current hunk into smaller hunks\n"
+#~ "e - manually edit the current hunk\n"
+#~ "? - print help\n"
+#~ msgstr ""
+#~ "g - 選擇跳轉到一個區塊\n"
+#~ "/ - 尋找和提供常規表示式符合的區塊\n"
+#~ "j - 維持此區塊未決狀態,檢視下一個未決定區塊\n"
+#~ "J - 維持此區塊未決狀態,檢視下一個區塊\n"
+#~ "k - 維持此區塊未決狀態,檢視上一個未決定區塊\n"
+#~ "K - 維持此區塊未決狀態,檢視上一個區塊\n"
+#~ "s - 分割目前區塊為更小的區塊\n"
+#~ "e - 手動編輯目前區塊\n"
+#~ "? - 顯示說明\n"
+
+#~ msgid "The selected hunks do not apply to the index!\n"
+#~ msgstr "選取區塊不能套用到索引!\n"
+
+#, perl-format
+#~ msgid "ignoring unmerged: %s\n"
+#~ msgstr "忽略未套用的:%s\n"
+
+#~ msgid "No other hunks to goto\n"
+#~ msgstr "沒有其它可供跳轉的區塊\n"
+
+#, perl-format
+#~ msgid "Invalid number: '%s'\n"
+#~ msgstr "無效數字:'%s'\n"
+
+#, perl-format
+#~ msgid "Sorry, only %d hunk available.\n"
+#~ msgid_plural "Sorry, only %d hunks available.\n"
+#~ msgstr[0] "對不起,只有 %d 個可用區塊。\n"
+
+#~ msgid "No other hunks to search\n"
+#~ msgstr "沒有其它可供尋找的區塊\n"
+
+#, perl-format
+#~ msgid "Malformed search regexp %s: %s\n"
+#~ msgstr "錯誤的常規表示式 %s:%s\n"
+
+#~ msgid "No hunk matches the given pattern\n"
+#~ msgstr "沒有和提供模式相符合的區塊\n"
+
+#~ msgid "No previous hunk\n"
+#~ msgstr "沒有上一個區塊\n"
+
+#~ msgid "No next hunk\n"
+#~ msgstr "沒有下一個區塊\n"
+
+#~ msgid "Sorry, cannot split this hunk\n"
+#~ msgstr "對不起,不能分割這個區塊\n"
+
+#, perl-format
+#~ msgid "Split into %d hunk.\n"
+#~ msgid_plural "Split into %d hunks.\n"
+#~ msgstr[0] "分割為 %d 塊。\n"
+
+#~ msgid "Sorry, cannot edit this hunk\n"
+#~ msgstr "對不起,不能編輯這個區塊\n"
+
+#~ msgid ""
+#~ "status        - show paths with changes\n"
+#~ "update        - add working tree state to the staged set of changes\n"
+#~ "revert        - revert staged set of changes back to the HEAD version\n"
+#~ "patch         - pick hunks and update selectively\n"
+#~ "diff          - view diff between HEAD and index\n"
+#~ "add untracked - add contents of untracked files to the staged set of "
+#~ "changes\n"
+#~ msgstr ""
+#~ "status        - 顯示含變更的路徑\n"
+#~ "update        - 新增工作區狀態至暫存列表\n"
+#~ "revert        - 還原修改的暫存集至 HEAD 版本\n"
+#~ "patch         - 挑選區塊並且有選擇地更新\n"
+#~ "diff          - 顯示 HEAD 和索引間差異\n"
+#~ "add untracked - 新增未追蹤檔案的內容至暫存列表\n"
+
+#~ msgid "missing --"
+#~ msgstr "缺少 --"
+
+#, perl-format
+#~ msgid "unknown --patch mode: %s"
+#~ msgstr "未知的 --patch 模式:%s"
+
+#, perl-format
+#~ msgid "invalid argument %s, expecting --"
+#~ msgstr "無效的參數 %s,期望是 --"
+
 #, c-format
 #~ msgid "unable to normalize object directory: %s"
 #~ msgstr "無法規範化物件目錄: %s"
diff --git a/preload-index.c b/preload-index.c
index 100f7a3..7a26b08 100644
--- a/preload-index.c
+++ b/preload-index.c
@@ -4,11 +4,15 @@
 #include "cache.h"
 #include "pathspec.h"
 #include "dir.h"
+#include "environment.h"
 #include "fsmonitor.h"
+#include "gettext.h"
 #include "config.h"
 #include "progress.h"
 #include "thread-utils.h"
 #include "repository.h"
+#include "symlinks.h"
+#include "trace2.h"
 
 /*
  * Mostly randomly chosen maximum thread counts: we
diff --git a/pretty.c b/pretty.c
index 1e1e218..0bb9380 100644
--- a/pretty.c
+++ b/pretty.c
@@ -1,8 +1,13 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
 #include "commit.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "utf8.h"
 #include "diff.h"
+#include "pager.h"
 #include "revision.h"
 #include "string-list.h"
 #include "mailmap.h"
@@ -719,7 +724,7 @@ const char *repo_logmsg_reencode(struct repository *r,
 		 * Otherwise, we still want to munge the encoding header in the
 		 * result, which will be done by modifying the buffer. If we
 		 * are using a fresh copy, we can reuse it. But if we are using
-		 * the cached copy from get_commit_buffer, we need to duplicate it
+		 * the cached copy from repo_get_commit_buffer, we need to duplicate it
 		 * to avoid munging the cached copy.
 		 */
 		if (msg == get_cached_commit_buffer(r, commit, NULL))
@@ -1857,7 +1862,8 @@ static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
 	return consumed + 1;
 }
 
-static size_t userformat_want_item(struct strbuf *sb, const char *placeholder,
+static size_t userformat_want_item(struct strbuf *sb UNUSED,
+				   const char *placeholder,
 				   void *context)
 {
 	struct userformat_want *w = context;
@@ -2199,12 +2205,14 @@ void pretty_print_commit(struct pretty_print_context *pp,
 	int need_8bit_cte = pp->need_8bit_cte;
 
 	if (pp->fmt == CMIT_FMT_USERFORMAT) {
-		format_commit_message(commit, user_format, sb, pp);
+		repo_format_commit_message(the_repository, commit,
+					   user_format, sb, pp);
 		return;
 	}
 
 	encoding = get_log_output_encoding();
-	msg = reencoded = logmsg_reencode(commit, NULL, encoding);
+	msg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL,
+					       encoding);
 
 	if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt))
 		indent = 0;
@@ -2261,7 +2269,7 @@ void pretty_print_commit(struct pretty_print_context *pp,
 	if (cmit_fmt_is_mail(pp->fmt) && sb->len <= beginning_of_body)
 		strbuf_addch(sb, '\n');
 
-	unuse_commit_buffer(commit, reencoded);
+	repo_unuse_commit_buffer(the_repository, commit, reencoded);
 }
 
 void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
diff --git a/pretty.h b/pretty.h
index f34e24c..421209e 100644
--- a/pretty.h
+++ b/pretty.h
@@ -1,11 +1,11 @@
 #ifndef PRETTY_H
 #define PRETTY_H
 
-#include "cache.h"
 #include "date.h"
 #include "string-list.h"
 
 struct commit;
+struct repository;
 struct strbuf;
 struct process_trailer_options;
 
@@ -120,10 +120,6 @@ void repo_format_commit_message(struct repository *r,
 			const struct commit *commit,
 			const char *format, struct strbuf *sb,
 			const struct pretty_print_context *context);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define format_commit_message(c, f, s, con) \
-	repo_format_commit_message(the_repository, c, f, s, con)
-#endif
 
 /*
  * Parse given arguments from "arg", check it for correctness and
@@ -153,6 +149,8 @@ int commit_format_is_empty(enum cmit_fmt);
 /* Make subject of commit message suitable for filename */
 void format_sanitized_subject(struct strbuf *sb, const char *msg, size_t len);
 
+int has_non_ascii(const char *text);
+
 /*
  * Set values of fields in "struct process_trailer_options"
  * according to trailers arguments.
diff --git a/prio-queue.c b/prio-queue.c
index d31b48e..dc2476b 100644
--- a/prio-queue.c
+++ b/prio-queue.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "prio-queue.h"
 
 static inline int compare(struct prio_queue *queue, int i, int j)
diff --git a/progress.c b/progress.c
index 0cdd875..f695798 100644
--- a/progress.c
+++ b/progress.c
@@ -9,11 +9,13 @@
  */
 
 #define GIT_TEST_PROGRESS_ONLY
-#include "cache.h"
-#include "gettext.h"
+#include "git-compat-util.h"
+#include "pager.h"
 #include "progress.h"
+#include "repository.h"
 #include "strbuf.h"
 #include "trace.h"
+#include "trace2.h"
 #include "utf8.h"
 #include "config.h"
 
@@ -59,7 +61,7 @@ void progress_test_force_update(void)
 }
 
 
-static void progress_interval(int signum)
+static void progress_interval(int signum UNUSED)
 {
 	progress_update = 1;
 }
diff --git a/promisor-remote.c b/promisor-remote.c
index faa7612..1adcd6f 100644
--- a/promisor-remote.c
+++ b/promisor-remote.c
@@ -1,7 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
+#include "hex.h"
 #include "object-store.h"
 #include "promisor-remote.h"
 #include "config.h"
+#include "trace2.h"
 #include "transport.h"
 #include "strvec.h"
 #include "packfile.h"
diff --git a/promisor-remote.h b/promisor-remote.h
index df36eb0..2cb9eda 100644
--- a/promisor-remote.h
+++ b/promisor-remote.h
@@ -18,24 +18,9 @@ struct promisor_remote {
 };
 
 void repo_promisor_remote_reinit(struct repository *r);
-static inline void promisor_remote_reinit(void)
-{
-	repo_promisor_remote_reinit(the_repository);
-}
-
 void promisor_remote_clear(struct promisor_remote_config *config);
-
 struct promisor_remote *repo_promisor_remote_find(struct repository *r, const char *remote_name);
-static inline struct promisor_remote *promisor_remote_find(const char *remote_name)
-{
-	return repo_promisor_remote_find(the_repository, remote_name);
-}
-
 int repo_has_promisor_remote(struct repository *r);
-static inline int has_promisor_remote(void)
-{
-	return repo_has_promisor_remote(the_repository);
-}
 
 /*
  * Fetches all requested objects from all promisor remotes, trying them one at
diff --git a/prompt.c b/prompt.c
index 50df172..3baa33f 100644
--- a/prompt.c
+++ b/prompt.c
@@ -1,5 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "environment.h"
 #include "run-command.h"
 #include "strbuf.h"
 #include "prompt.h"
diff --git a/protocol-caps.c b/protocol-caps.c
index bbde918..a90c488 100644
--- a/protocol-caps.c
+++ b/protocol-caps.c
@@ -1,9 +1,11 @@
 #include "git-compat-util.h"
 #include "protocol-caps.h"
 #include "gettext.h"
+#include "hex.h"
 #include "pkt-line.h"
 #include "strvec.h"
-#include "hash.h"
+#include "hash-ll.h"
+#include "hex.h"
 #include "object.h"
 #include "object-store.h"
 #include "string-list.h"
@@ -77,7 +79,7 @@ static void send_info(struct repository *r, struct packet_writer *writer,
 
 int cap_object_info(struct repository *r, struct packet_reader *request)
 {
-	struct requested_info info;
+	struct requested_info info = { 0 };
 	struct packet_writer writer;
 	struct string_list oid_str_list = STRING_LIST_INIT_DUP;
 
diff --git a/protocol.c b/protocol.c
index c53f7df..079ba75 100644
--- a/protocol.c
+++ b/protocol.c
@@ -1,6 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "environment.h"
 #include "protocol.h"
+#include "trace2.h"
 
 static enum protocol_version parse_protocol_version(const char *value)
 {
diff --git a/protocol.h b/protocol.h
index cef1a4a..de66bf8 100644
--- a/protocol.h
+++ b/protocol.h
@@ -1,6 +1,27 @@
 #ifndef PROTOCOL_H
 #define PROTOCOL_H
 
+/*
+ * Intensive research over the course of many years has shown that
+ * port 9418 is totally unused by anything else. Or
+ *
+ *	Your search - "port 9418" - did not match any documents.
+ *
+ * as www.google.com puts it.
+ *
+ * This port has been properly assigned for git use by IANA:
+ * git (Assigned-9418) [I06-050728-0001].
+ *
+ *	git  9418/tcp   git pack transfer service
+ *	git  9418/udp   git pack transfer service
+ *
+ * with Linus Torvalds <torvalds@osdl.org> as the point of
+ * contact. September 2005.
+ *
+ * See http://www.iana.org/assignments/port-numbers
+ */
+#define DEFAULT_GIT_PORT 9418
+
 enum protocol_version {
 	protocol_unknown_version = -1,
 	protocol_v0 = 0,
diff --git a/prune-packed.c b/prune-packed.c
index 261520b..58412b4 100644
--- a/prune-packed.c
+++ b/prune-packed.c
@@ -1,3 +1,6 @@
+#include "git-compat-util.h"
+#include "environment.h"
+#include "gettext.h"
 #include "object-store.h"
 #include "packfile.h"
 #include "progress.h"
diff --git a/quote.c b/quote.c
index 26719d2..43c7396 100644
--- a/quote.c
+++ b/quote.c
@@ -1,5 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
+#include "path.h"
 #include "quote.h"
+#include "strbuf.h"
 #include "strvec.h"
 
 int quote_path_fully = 1;
diff --git a/quote.h b/quote.h
index 87ff458..0300c29 100644
--- a/quote.h
+++ b/quote.h
@@ -3,6 +3,8 @@
 
 struct strbuf;
 
+extern int quote_path_fully;
+
 /* Help to copy the thing properly quoted for the shell safety.
  * any single quote is replaced with '\'', any exclamation point
  * is replaced with '\!', and the whole thing is enclosed in a
diff --git a/range-diff.c b/range-diff.c
index 4bd65ab..6a704e6 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -1,5 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "environment.h"
+#include "gettext.h"
 #include "range-diff.h"
+#include "object-name.h"
 #include "string-list.h"
 #include "run-command.h"
 #include "strvec.h"
@@ -8,6 +11,7 @@
 #include "linear-assignment.h"
 #include "diffcore.h"
 #include "commit.h"
+#include "pager.h"
 #include "pretty.h"
 #include "userdiff.h"
 #include "apply.h"
@@ -94,7 +98,7 @@ static int read_patches(const char *range, struct string_list *list,
 				strbuf_reset(&buf);
 			}
 			CALLOC_ARRAY(util, 1);
-			if (get_oid(p, &util->oid)) {
+			if (repo_get_oid(the_repository, p, &util->oid)) {
 				error(_("could not parse commit '%s'"), p);
 				FREE_AND_NULL(util);
 				string_list_clear(list, 1);
@@ -390,7 +394,7 @@ static void output_pair_header(struct diff_options *diffopt,
 
 	if (!dashes->len)
 		strbuf_addchars(dashes, '-',
-				strlen(find_unique_abbrev(oid, abbrev)));
+				strlen(repo_find_unique_abbrev(the_repository, oid, abbrev)));
 
 	if (!b_util) {
 		color = color_old;
@@ -412,7 +416,7 @@ static void output_pair_header(struct diff_options *diffopt,
 		strbuf_addf(buf, "%*s:  %s ", patch_no_width, "-", dashes->buf);
 	else
 		strbuf_addf(buf, "%*d:  %s ", patch_no_width, a_util->i + 1,
-			    find_unique_abbrev(&a_util->oid, abbrev));
+			    repo_find_unique_abbrev(the_repository, &a_util->oid, abbrev));
 
 	if (status == '!')
 		strbuf_addf(buf, "%s%s", color_reset, color);
@@ -424,7 +428,7 @@ static void output_pair_header(struct diff_options *diffopt,
 		strbuf_addf(buf, " %*s:  %s", patch_no_width, "-", dashes->buf);
 	else
 		strbuf_addf(buf, " %*d:  %s", patch_no_width, b_util->i + 1,
-			    find_unique_abbrev(&b_util->oid, abbrev));
+			    repo_find_unique_abbrev(the_repository, &b_util->oid, abbrev));
 
 	commit = lookup_commit_reference(the_repository, oid);
 	if (commit) {
@@ -485,7 +489,7 @@ static void output(struct string_list *a, struct string_list *b,
 	if (range_diff_opts->diffopt)
 		memcpy(&opts, range_diff_opts->diffopt, sizeof(opts));
 	else
-		diff_setup(&opts);
+		repo_diff_setup(the_repository, &opts);
 
 	opts.no_free = 1;
 	if (!opts.output_format)
@@ -588,7 +592,7 @@ int is_range_diff_range(const char *arg)
 	int i, positive = 0, negative = 0;
 	struct rev_info revs;
 
-	init_revisions(&revs, NULL);
+	repo_init_revisions(the_repository, &revs, NULL);
 	if (setup_revisions(3, argv, &revs, NULL) == 1) {
 		for (i = 0; i < revs.pending.nr; i++)
 			if (revs.pending.objects[i].item->flags & UNINTERESTING)
diff --git a/reachable.c b/reachable.c
index aba63eb..55bb114 100644
--- a/reachable.c
+++ b/reachable.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
 #include "tag.h"
 #include "commit.h"
@@ -48,7 +50,9 @@ static int add_one_ref(const char *path, const struct object_id *oid,
  * The traversal will have already marked us as SEEN, so we
  * only need to handle any progress reporting here.
  */
-static void mark_object(struct object *obj, const char *name, void *data)
+static void mark_object(struct object *obj UNUSED,
+			const char *name UNUSED,
+			void *data)
 {
 	update_progress(data);
 }
@@ -152,7 +156,8 @@ static int add_recent_loose(const struct object_id *oid,
 }
 
 static int add_recent_packed(const struct object_id *oid,
-			     struct packed_git *p, uint32_t pos,
+			     struct packed_git *p,
+			     uint32_t pos,
 			     void *data)
 {
 	struct object *obj;
@@ -202,10 +207,10 @@ int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
 
 static int mark_object_seen(const struct object_id *oid,
 			     enum object_type type,
-			     int exclude,
-			     uint32_t name_hash,
-			     struct packed_git *found_pack,
-			     off_t found_offset)
+			     int exclude UNUSED,
+			     uint32_t name_hash UNUSED,
+			     struct packed_git *found_pack UNUSED,
+			     off_t found_offset UNUSED)
 {
 	struct object *obj = lookup_object_by_type(the_repository, oid, type);
 	if (!obj)
diff --git a/read-cache.c b/read-cache.c
index 35e5657..f4c31a6 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -4,23 +4,34 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "alloc.h"
 #include "config.h"
+#include "date.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "hex.h"
 #include "tempfile.h"
 #include "lockfile.h"
 #include "cache-tree.h"
 #include "refs.h"
 #include "dir.h"
+#include "object-file.h"
 #include "object-store.h"
+#include "oid-array.h"
 #include "tree.h"
 #include "commit.h"
 #include "blob.h"
+#include "environment.h"
+#include "gettext.h"
+#include "mem-pool.h"
+#include "object-name.h"
 #include "resolve-undo.h"
 #include "run-command.h"
 #include "strbuf.h"
+#include "trace2.h"
 #include "varint.h"
 #include "split-index.h"
+#include "symlinks.h"
 #include "utf8.h"
 #include "fsmonitor.h"
 #include "thread-utils.h"
@@ -29,6 +40,7 @@
 #include "csum-file.h"
 #include "promisor-remote.h"
 #include "hook.h"
+#include "wrapper.h"
 
 /* Mask for the name length in ce_flags in the on-disk index */
 
@@ -263,7 +275,7 @@ static int ce_compare_link(const struct cache_entry *ce, size_t expected_size)
 	if (strbuf_readlink(&sb, ce->name, expected_size))
 		return -1;
 
-	buffer = read_object_file(&ce->oid, &type, &size);
+	buffer = repo_read_object_file(the_repository, &ce->oid, &type, &size);
 	if (buffer) {
 		if (size == sb.len)
 			match = memcmp(buffer, sb.buf, size);
@@ -488,75 +500,8 @@ int ie_modified(struct index_state *istate,
 	return 0;
 }
 
-int base_name_compare(const char *name1, size_t len1, int mode1,
-		      const char *name2, size_t len2, int mode2)
-{
-	unsigned char c1, c2;
-	size_t len = len1 < len2 ? len1 : len2;
-	int cmp;
-
-	cmp = memcmp(name1, name2, len);
-	if (cmp)
-		return cmp;
-	c1 = name1[len];
-	c2 = name2[len];
-	if (!c1 && S_ISDIR(mode1))
-		c1 = '/';
-	if (!c2 && S_ISDIR(mode2))
-		c2 = '/';
-	return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
-}
-
-/*
- * df_name_compare() is identical to base_name_compare(), except it
- * compares conflicting directory/file entries as equal. Note that
- * while a directory name compares as equal to a regular file, they
- * then individually compare _differently_ to a filename that has
- * a dot after the basename (because '\0' < '.' < '/').
- *
- * This is used by routines that want to traverse the git namespace
- * but then handle conflicting entries together when possible.
- */
-int df_name_compare(const char *name1, size_t len1, int mode1,
-		    const char *name2, size_t len2, int mode2)
-{
-	unsigned char c1, c2;
-	size_t len = len1 < len2 ? len1 : len2;
-	int cmp;
-
-	cmp = memcmp(name1, name2, len);
-	if (cmp)
-		return cmp;
-	/* Directories and files compare equal (same length, same name) */
-	if (len1 == len2)
-		return 0;
-	c1 = name1[len];
-	if (!c1 && S_ISDIR(mode1))
-		c1 = '/';
-	c2 = name2[len];
-	if (!c2 && S_ISDIR(mode2))
-		c2 = '/';
-	if (c1 == '/' && !c2)
-		return 0;
-	if (c2 == '/' && !c1)
-		return 0;
-	return c1 - c2;
-}
-
-int name_compare(const char *name1, size_t len1, const char *name2, size_t len2)
-{
-	size_t min_len = (len1 < len2) ? len1 : len2;
-	int cmp = memcmp(name1, name2, min_len);
-	if (cmp)
-		return cmp;
-	if (len1 < len2)
-		return -1;
-	if (len1 > len2)
-		return 1;
-	return 0;
-}
-
-int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2)
+static int cache_name_stage_compare(const char *name1, int len1, int stage1,
+				    const char *name2, int len2, int stage2)
 {
 	int cmp;
 
@@ -571,6 +516,16 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char
 	return 0;
 }
 
+int cmp_cache_name_compare(const void *a_, const void *b_)
+{
+	const struct cache_entry *ce1, *ce2;
+
+	ce1 = *((const struct cache_entry **)a_);
+	ce2 = *((const struct cache_entry **)b_);
+	return cache_name_stage_compare(ce1->name, ce1->ce_namelen, ce_stage(ce1),
+				  ce2->name, ce2->ce_namelen, ce_stage(ce2));
+}
+
 static int index_name_stage_pos(struct index_state *istate,
 				const char *name, int namelen,
 				int stage,
@@ -2628,7 +2583,7 @@ int repo_index_has_changes(struct repository *repo,
 
 	if (tree)
 		cmp = tree->object.oid;
-	if (tree || !get_oid_tree("HEAD", &cmp)) {
+	if (tree || !repo_get_oid_tree(repo, "HEAD", &cmp)) {
 		struct diff_options opt;
 
 		repo_diff_setup(repo, &opt);
@@ -2901,6 +2856,16 @@ static int record_ieot(void)
 	return !git_config_get_index_threads(&val) && val != 1;
 }
 
+enum write_extensions {
+	WRITE_NO_EXTENSION =              0,
+	WRITE_SPLIT_INDEX_EXTENSION =     1<<0,
+	WRITE_CACHE_TREE_EXTENSION =      1<<1,
+	WRITE_RESOLVE_UNDO_EXTENSION =    1<<2,
+	WRITE_UNTRACKED_CACHE_EXTENSION = 1<<3,
+	WRITE_FSMONITOR_EXTENSION =       1<<4,
+};
+#define WRITE_ALL_EXTENSIONS ((enum write_extensions)-1)
+
 /*
  * On success, `tempfile` is closed. If it is the temporary file
  * of a `struct lock_file`, we will therefore effectively perform
@@ -2909,7 +2874,7 @@ static int record_ieot(void)
  * rely on it.
  */
 static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
-			  int strip_extensions, unsigned flags)
+			  enum write_extensions write_extensions, unsigned flags)
 {
 	uint64_t start = getnanotime();
 	struct hashfile *f;
@@ -2947,7 +2912,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
 	}
 
 	if (!istate->version)
-		istate->version = get_index_format_default(the_repository);
+		istate->version = get_index_format_default(r);
 
 	/* demote version 3 to version 2 when the latter suffices */
 	if (istate->version == 3 || istate->version == 2)
@@ -3082,8 +3047,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
 			return -1;
 	}
 
-	if (!strip_extensions && istate->split_index &&
-	    !is_null_oid(&istate->split_index->base_oid)) {
+	if (write_extensions & WRITE_SPLIT_INDEX_EXTENSION &&
+	    istate->split_index) {
 		struct strbuf sb = STRBUF_INIT;
 
 		if (istate->sparse_index)
@@ -3097,7 +3062,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
 		if (err)
 			return -1;
 	}
-	if (!strip_extensions && !drop_cache_tree && istate->cache_tree) {
+	if (write_extensions & WRITE_CACHE_TREE_EXTENSION &&
+	    !drop_cache_tree && istate->cache_tree) {
 		struct strbuf sb = STRBUF_INIT;
 
 		cache_tree_write(&sb, istate->cache_tree);
@@ -3107,7 +3073,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
 		if (err)
 			return -1;
 	}
-	if (!strip_extensions && istate->resolve_undo) {
+	if (write_extensions & WRITE_RESOLVE_UNDO_EXTENSION &&
+	    istate->resolve_undo) {
 		struct strbuf sb = STRBUF_INIT;
 
 		resolve_undo_write(&sb, istate->resolve_undo);
@@ -3118,7 +3085,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
 		if (err)
 			return -1;
 	}
-	if (!strip_extensions && istate->untracked) {
+	if (write_extensions & WRITE_UNTRACKED_CACHE_EXTENSION &&
+	    istate->untracked) {
 		struct strbuf sb = STRBUF_INIT;
 
 		write_untracked_extension(&sb, istate->untracked);
@@ -3129,7 +3097,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
 		if (err)
 			return -1;
 	}
-	if (!strip_extensions && istate->fsmonitor_last_update) {
+	if (write_extensions & WRITE_FSMONITOR_EXTENSION &&
+	    istate->fsmonitor_last_update) {
 		struct strbuf sb = STRBUF_INIT;
 
 		write_fsmonitor_extension(&sb, istate);
@@ -3203,8 +3172,10 @@ static int commit_locked_index(struct lock_file *lk)
 		return commit_lock_file(lk);
 }
 
-static int do_write_locked_index(struct index_state *istate, struct lock_file *lock,
-				 unsigned flags)
+static int do_write_locked_index(struct index_state *istate,
+				 struct lock_file *lock,
+				 unsigned flags,
+				 enum write_extensions write_extensions)
 {
 	int ret;
 	int was_full = istate->sparse_index == INDEX_EXPANDED;
@@ -3222,7 +3193,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
 	 */
 	trace2_region_enter_printf("index", "do_write_index", the_repository,
 				   "%s", get_lock_file_path(lock));
-	ret = do_write_index(istate, lock->tempfile, 0, flags);
+	ret = do_write_index(istate, lock->tempfile, write_extensions, flags);
 	trace2_region_leave_printf("index", "do_write_index", the_repository,
 				   "%s", get_lock_file_path(lock));
 
@@ -3251,7 +3222,7 @@ static int write_split_index(struct index_state *istate,
 {
 	int ret;
 	prepare_to_write_split_index(istate);
-	ret = do_write_locked_index(istate, lock, flags);
+	ret = do_write_locked_index(istate, lock, flags, WRITE_ALL_EXTENSIONS);
 	finish_writing_split_index(istate);
 	return ret;
 }
@@ -3326,7 +3297,7 @@ static int write_shared_index(struct index_state *istate,
 
 	trace2_region_enter_printf("index", "shared/do_write_index",
 				   the_repository, "%s", get_tempfile_path(*temp));
-	ret = do_write_index(si->base, *temp, 1, flags);
+	ret = do_write_index(si->base, *temp, WRITE_NO_EXTENSION, flags);
 	trace2_region_leave_printf("index", "shared/do_write_index",
 				   the_repository, "%s", get_tempfile_path(*temp));
 
@@ -3403,9 +3374,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
 	if ((!si && !test_split_index_env) ||
 	    alternate_index_output ||
 	    (istate->cache_changed & ~EXTMASK)) {
-		if (si)
-			oidclr(&si->base_oid);
-		ret = do_write_locked_index(istate, lock, flags);
+		ret = do_write_locked_index(istate, lock, flags,
+					    ~WRITE_SPLIT_INDEX_EXTENSION);
 		goto out;
 	}
 
@@ -3431,8 +3401,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
 		/* Same initial permissions as the main .git/index file */
 		temp = mks_tempfile_sm(git_path("sharedindex_XXXXXX"), 0, 0666);
 		if (!temp) {
-			oidclr(&si->base_oid);
-			ret = do_write_locked_index(istate, lock, flags);
+			ret = do_write_locked_index(istate, lock, flags,
+						    ~WRITE_SPLIT_INDEX_EXTENSION);
 			goto out;
 		}
 		ret = write_shared_index(istate, &temp, flags);
@@ -3553,7 +3523,8 @@ void *read_blob_data_from_index(struct index_state *istate,
 	}
 	if (pos < 0)
 		return NULL;
-	data = read_object_file(&istate->cache[pos]->oid, &type, &sz);
+	data = repo_read_object_file(the_repository, &istate->cache[pos]->oid,
+				     &type, &sz);
 	if (!data || type != OBJ_BLOB) {
 		free(data);
 		return NULL;
diff --git a/rebase-interactive.c b/rebase-interactive.c
index 7407c59..852a331 100644
--- a/rebase-interactive.c
+++ b/rebase-interactive.c
@@ -1,11 +1,17 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "commit.h"
+#include "editor.h"
+#include "environment.h"
+#include "gettext.h"
 #include "sequencer.h"
 #include "rebase-interactive.h"
+#include "repository.h"
 #include "strbuf.h"
 #include "commit-slab.h"
 #include "config.h"
 #include "dir.h"
+#include "object-name.h"
+#include "wrapper.h"
 
 static const char edit_todo_list_advice[] =
 N_("You can fix this with 'git rebase --edit-todo' "
@@ -187,7 +193,7 @@ int todo_list_check(struct todo_list *old_todo, struct todo_list *new_todo)
 		struct commit *commit = item->commit;
 		if (commit && !*commit_seen_at(&commit_seen, commit)) {
 			strbuf_addf(&missing, " - %s %.*s\n",
-				    find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV),
+				    repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV),
 				    item->arg_len,
 				    todo_item_get_arg(old_todo, item));
 			*commit_seen_at(&commit_seen, commit) = 1;
diff --git a/rebase.c b/rebase.c
index 6775cdd..17a570f 100644
--- a/rebase.c
+++ b/rebase.c
@@ -1,3 +1,4 @@
+#include "git-compat-util.h"
 #include "rebase.h"
 #include "config.h"
 #include "gettext.h"
diff --git a/ref-filter.c b/ref-filter.c
index f8203c6..4991cd4 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1,9 +1,15 @@
-#include "builtin.h"
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
+#include "gpg-interface.h"
+#include "hex.h"
 #include "parse-options.h"
 #include "refs.h"
 #include "wildmatch.h"
+#include "object-name.h"
 #include "object-store.h"
+#include "oid-array.h"
 #include "repository.h"
 #include "commit.h"
 #include "remote.h"
@@ -13,8 +19,8 @@
 #include "ref-filter.h"
 #include "revision.h"
 #include "utf8.h"
-#include "git-compat-util.h"
 #include "version.h"
+#include "versioncmp.h"
 #include "trailer.h"
 #include "wt-status.h"
 #include "commit-slab.h"
@@ -158,6 +164,7 @@ enum atom_type {
 	ATOM_THEN,
 	ATOM_ELSE,
 	ATOM_REST,
+	ATOM_AHEADBEHIND,
 };
 
 /*
@@ -282,7 +289,8 @@ static int refname_atom_parser_internal(struct refname_atom *atom, const char *a
 	return 0;
 }
 
-static int remote_ref_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int remote_ref_atom_parser(struct ref_format *format UNUSED,
+				  struct used_atom *atom,
 				  const char *arg, struct strbuf *err)
 {
 	struct string_list params = STRING_LIST_INIT_DUP;
@@ -329,7 +337,8 @@ static int remote_ref_atom_parser(struct ref_format *format, struct used_atom *a
 	return 0;
 }
 
-static int objecttype_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int objecttype_atom_parser(struct ref_format *format UNUSED,
+				  struct used_atom *atom,
 				  const char *arg, struct strbuf *err)
 {
 	if (arg)
@@ -341,7 +350,8 @@ static int objecttype_atom_parser(struct ref_format *format, struct used_atom *a
 	return 0;
 }
 
-static int objectsize_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int objectsize_atom_parser(struct ref_format *format UNUSED,
+				  struct used_atom *atom,
 				  const char *arg, struct strbuf *err)
 {
 	if (!arg) {
@@ -361,7 +371,8 @@ static int objectsize_atom_parser(struct ref_format *format, struct used_atom *a
 	return 0;
 }
 
-static int deltabase_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int deltabase_atom_parser(struct ref_format *format UNUSED,
+				 struct used_atom *atom,
 				 const char *arg, struct strbuf *err)
 {
 	if (arg)
@@ -373,7 +384,8 @@ static int deltabase_atom_parser(struct ref_format *format, struct used_atom *at
 	return 0;
 }
 
-static int body_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int body_atom_parser(struct ref_format *format UNUSED,
+			    struct used_atom *atom,
 			    const char *arg, struct strbuf *err)
 {
 	if (arg)
@@ -382,7 +394,8 @@ static int body_atom_parser(struct ref_format *format, struct used_atom *atom,
 	return 0;
 }
 
-static int subject_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int subject_atom_parser(struct ref_format *format UNUSED,
+			       struct used_atom *atom,
 			       const char *arg, struct strbuf *err)
 {
 	if (!arg)
@@ -394,7 +407,8 @@ static int subject_atom_parser(struct ref_format *format, struct used_atom *atom
 	return 0;
 }
 
-static int trailers_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int trailers_atom_parser(struct ref_format *format UNUSED,
+				struct used_atom *atom,
 				const char *arg, struct strbuf *err)
 {
 	atom->u.contents.trailer_opts.no_divider = 1;
@@ -448,8 +462,9 @@ static int contents_atom_parser(struct ref_format *format, struct used_atom *ato
 	return 0;
 }
 
-static int raw_atom_parser(struct ref_format *format, struct used_atom *atom,
-				const char *arg, struct strbuf *err)
+static int raw_atom_parser(struct ref_format *format UNUSED,
+			   struct used_atom *atom,
+			   const char *arg, struct strbuf *err)
 {
 	if (!arg)
 		atom->u.raw_data.option = RAW_BARE;
@@ -460,7 +475,8 @@ static int raw_atom_parser(struct ref_format *format, struct used_atom *atom,
 	return 0;
 }
 
-static int oid_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int oid_atom_parser(struct ref_format *format UNUSED,
+			   struct used_atom *atom,
 			   const char *arg, struct strbuf *err)
 {
 	if (!arg)
@@ -479,7 +495,8 @@ static int oid_atom_parser(struct ref_format *format, struct used_atom *atom,
 	return 0;
 }
 
-static int person_email_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int person_email_atom_parser(struct ref_format *format UNUSED,
+				    struct used_atom *atom,
 				    const char *arg, struct strbuf *err)
 {
 	if (!arg)
@@ -493,7 +510,8 @@ static int person_email_atom_parser(struct ref_format *format, struct used_atom
 	return 0;
 }
 
-static int refname_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int refname_atom_parser(struct ref_format *format UNUSED,
+			       struct used_atom *atom,
 			       const char *arg, struct strbuf *err)
 {
 	return refname_atom_parser_internal(&atom->u.refname, arg, atom->name, err);
@@ -510,7 +528,8 @@ static align_type parse_align_position(const char *s)
 	return -1;
 }
 
-static int align_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int align_atom_parser(struct ref_format *format UNUSED,
+			     struct used_atom *atom,
 			     const char *arg, struct strbuf *err)
 {
 	struct align *align = &atom->u.align;
@@ -562,7 +581,8 @@ static int align_atom_parser(struct ref_format *format, struct used_atom *atom,
 	return 0;
 }
 
-static int if_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int if_atom_parser(struct ref_format *format UNUSED,
+			  struct used_atom *atom,
 			  const char *arg, struct strbuf *err)
 {
 	if (!arg) {
@@ -577,16 +597,33 @@ static int if_atom_parser(struct ref_format *format, struct used_atom *atom,
 	return 0;
 }
 
-static int rest_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int rest_atom_parser(struct ref_format *format,
+			    struct used_atom *atom UNUSED,
 			    const char *arg, struct strbuf *err)
 {
 	if (arg)
 		return err_no_arg(err, "rest");
-	format->use_rest = 1;
 	return 0;
 }
 
-static int head_atom_parser(struct ref_format *format, struct used_atom *atom,
+static int ahead_behind_atom_parser(struct ref_format *format, struct used_atom *atom,
+				    const char *arg, struct strbuf *err)
+{
+	struct string_list_item *item;
+
+	if (!arg)
+		return strbuf_addf_ret(err, -1, _("expected format: %%(ahead-behind:<committish>)"));
+
+	item = string_list_append(&format->bases, arg);
+	item->util = lookup_commit_reference_by_name(arg);
+	if (!item->util)
+		die("failed to find '%s'", arg);
+
+	return 0;
+}
+
+static int head_atom_parser(struct ref_format *format UNUSED,
+			    struct used_atom *atom,
 			    const char *arg, struct strbuf *err)
 {
 	if (arg)
@@ -645,6 +682,7 @@ static struct {
 	[ATOM_THEN] = { "then", SOURCE_NONE },
 	[ATOM_ELSE] = { "else", SOURCE_NONE },
 	[ATOM_REST] = { "rest", SOURCE_NONE, FIELD_STR, rest_atom_parser },
+	[ATOM_AHEADBEHIND] = { "ahead-behind", SOURCE_OTHER, FIELD_STR, ahead_behind_atom_parser },
 	/*
 	 * Please update $__git_ref_fieldlist in git-completion.bash
 	 * when you add new atoms
@@ -791,7 +829,7 @@ static void quote_formatting(struct strbuf *s, const char *str, ssize_t len, int
 }
 
 static int append_atom(struct atom_value *v, struct ref_formatting_state *state,
-		       struct strbuf *unused_err)
+		       struct strbuf *err UNUSED)
 {
 	/*
 	 * Quote formatting is only done when the stack has a single
@@ -841,7 +879,7 @@ static void end_align_handler(struct ref_formatting_stack **stack)
 }
 
 static int align_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state,
-			      struct strbuf *unused_err)
+			      struct strbuf *err UNUSED)
 {
 	struct ref_formatting_stack *new_stack;
 
@@ -888,7 +926,7 @@ static void if_then_else_handler(struct ref_formatting_stack **stack)
 }
 
 static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state,
-			   struct strbuf *unused_err)
+			   struct strbuf *err UNUSED)
 {
 	struct ref_formatting_stack *new_stack;
 	struct if_then_else *if_then_else = xcalloc(1,
@@ -915,7 +953,8 @@ static int is_empty(struct strbuf *buf)
 	return cur == end;
  }
 
-static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state,
+static int then_atom_handler(struct atom_value *atomv UNUSED,
+			     struct ref_formatting_state *state,
 			     struct strbuf *err)
 {
 	struct ref_formatting_stack *cur = state->stack;
@@ -952,7 +991,8 @@ static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	return 0;
 }
 
-static int else_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state,
+static int else_atom_handler(struct atom_value *atomv UNUSED,
+			     struct ref_formatting_state *state,
 			     struct strbuf *err)
 {
 	struct ref_formatting_stack *prev = state->stack;
@@ -973,7 +1013,8 @@ static int else_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	return 0;
 }
 
-static int end_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state,
+static int end_atom_handler(struct atom_value *atomv UNUSED,
+			    struct ref_formatting_state *state,
 			    struct strbuf *err)
 {
 	struct ref_formatting_stack *current = state->stack;
@@ -1075,9 +1116,11 @@ static const char *do_grab_oid(const char *field, const struct object_id *oid,
 	case O_FULL:
 		return oid_to_hex(oid);
 	case O_LENGTH:
-		return find_unique_abbrev(oid, atom->u.oid.length);
+		return repo_find_unique_abbrev(the_repository, oid,
+					       atom->u.oid.length);
 	case O_SHORT:
-		return find_unique_abbrev(oid, DEFAULT_ABBREV);
+		return repo_find_unique_abbrev(the_repository, oid,
+					       DEFAULT_ABBREV);
 	default:
 		BUG("unknown %%(%s) option", field);
 	}
@@ -1822,7 +1865,7 @@ static void lazy_init_worktree_map(void)
 	populate_worktree_map(&(ref_to_worktree_map.map), ref_to_worktree_map.worktrees);
 }
 
-static char *get_worktree_path(const struct used_atom *atom, const struct ref_array_item *ref)
+static char *get_worktree_path(const struct ref_array_item *ref)
 {
 	struct hashmap_entry entry, *e;
 	struct ref_to_worktree_entry *lookup_result;
@@ -1848,6 +1891,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
 	struct object *obj;
 	int i;
 	struct object_info empty = OBJECT_INFO_INIT;
+	int ahead_behind_atoms = 0;
 
 	CALLOC_ARRAY(ref->value, used_atom_cnt);
 
@@ -1881,7 +1925,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
 			refname = get_refname(atom, ref);
 		else if (atom_type == ATOM_WORKTREEPATH) {
 			if (ref->kind == FILTER_REFS_BRANCHES)
-				v->s = get_worktree_path(atom, ref);
+				v->s = get_worktree_path(ref);
 			else
 				v->s = xstrdup("");
 			continue;
@@ -1978,6 +2022,16 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
 			else
 				v->s = xstrdup("");
 			continue;
+		} else if (atom_type == ATOM_AHEADBEHIND) {
+			if (ref->counts) {
+				const struct ahead_behind_count *count;
+				count = ref->counts[ahead_behind_atoms++];
+				v->s = xstrfmt("%d %d", count->ahead, count->behind);
+			} else {
+				/* Not a commit. */
+				v->s = xstrdup("");
+			}
+			continue;
 		} else
 			continue;
 
@@ -2328,6 +2382,7 @@ static void free_array_item(struct ref_array_item *item)
 			free((char *)item->value[i].s);
 		free(item->value);
 	}
+	free(item->counts);
 	free(item);
 }
 
@@ -2356,6 +2411,8 @@ void ref_array_clear(struct ref_array *array)
 		free_worktrees(ref_to_worktree_map.worktrees);
 		ref_to_worktree_map.worktrees = NULL;
 	}
+
+	FREE_AND_NULL(array->counts);
 }
 
 #define EXCLUDE_REACHED 0
@@ -2364,33 +2421,22 @@ static void reach_filter(struct ref_array *array,
 			 struct commit_list *check_reachable,
 			 int include_reached)
 {
-	struct rev_info revs;
 	int i, old_nr;
 	struct commit **to_clear;
-	struct commit_list *cr;
 
 	if (!check_reachable)
 		return;
 
 	CALLOC_ARRAY(to_clear, array->nr);
-
-	repo_init_revisions(the_repository, &revs, NULL);
-
 	for (i = 0; i < array->nr; i++) {
 		struct ref_array_item *item = array->items[i];
-		add_pending_object(&revs, &item->commit->object, item->refname);
 		to_clear[i] = item->commit;
 	}
 
-	for (cr = check_reachable; cr; cr = cr->next) {
-		struct commit *merge_commit = cr->item;
-		merge_commit->object.flags |= UNINTERESTING;
-		add_pending_object(&revs, &merge_commit->object, "");
-	}
-
-	revs.limited = 1;
-	if (prepare_revision_walk(&revs))
-		die(_("revision walk setup failed"));
+	tips_reachable_from_bases(the_repository,
+				  check_reachable,
+				  to_clear, array->nr,
+				  UNINTERESTING);
 
 	old_nr = array->nr;
 	array->nr = 0;
@@ -2414,10 +2460,50 @@ static void reach_filter(struct ref_array *array,
 		clear_commit_marks(merge_commit, ALL_REV_FLAGS);
 	}
 
-	release_revisions(&revs);
 	free(to_clear);
 }
 
+void filter_ahead_behind(struct repository *r,
+			 struct ref_format *format,
+			 struct ref_array *array)
+{
+	struct commit **commits;
+	size_t commits_nr = format->bases.nr + array->nr;
+
+	if (!format->bases.nr || !array->nr)
+		return;
+
+	ALLOC_ARRAY(commits, commits_nr);
+	for (size_t i = 0; i < format->bases.nr; i++)
+		commits[i] = format->bases.items[i].util;
+
+	ALLOC_ARRAY(array->counts, st_mult(format->bases.nr, array->nr));
+
+	commits_nr = format->bases.nr;
+	array->counts_nr = 0;
+	for (size_t i = 0; i < array->nr; i++) {
+		const char *name = array->items[i]->refname;
+		commits[commits_nr] = lookup_commit_reference_by_name(name);
+
+		if (!commits[commits_nr])
+			continue;
+
+		CALLOC_ARRAY(array->items[i]->counts, format->bases.nr);
+		for (size_t j = 0; j < format->bases.nr; j++) {
+			struct ahead_behind_count *count;
+			count = &array->counts[array->counts_nr++];
+			count->tip_index = commits_nr;
+			count->base_index = j;
+
+			array->items[i]->counts[j] = count;
+		}
+		commits_nr++;
+	}
+
+	ahead_behind(r, commits, commits_nr, array->counts, array->counts_nr);
+	free(commits);
+}
+
 /*
  * API for filtering a set of refs. Based on the type of refs the user
  * has requested, we iterate through those refs and apply filters
@@ -2765,7 +2851,7 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)
 
 	BUG_ON_OPT_NEG(unset);
 
-	if (get_oid(arg, &oid))
+	if (repo_get_oid(the_repository, arg, &oid))
 		die(_("malformed object name %s"), arg);
 
 	merge_commit = lookup_commit_reference_gently(the_repository, &oid, 0);
diff --git a/ref-filter.h b/ref-filter.h
index aa0eea4..430701c 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -1,10 +1,11 @@
 #ifndef REF_FILTER_H
 #define REF_FILTER_H
 
+#include "gettext.h"
 #include "oid-array.h"
 #include "refs.h"
 #include "commit.h"
-#include "parse-options.h"
+#include "string-list.h"
 
 /* Quoting styles */
 #define QUOTE_NONE 0
@@ -24,6 +25,8 @@
 
 struct atom_value;
 struct ref_sorting;
+struct ahead_behind_count;
+struct option;
 
 enum ref_sorting_order {
 	REF_SORTING_REVERSE = 1<<0,
@@ -40,6 +43,8 @@ struct ref_array_item {
 	const char *symref;
 	struct commit *commit;
 	struct atom_value *value;
+	struct ahead_behind_count **counts;
+
 	char refname[FLEX_ARRAY];
 };
 
@@ -47,6 +52,9 @@ struct ref_array {
 	int nr, alloc;
 	struct ref_array_item **items;
 	struct rev_info *revs;
+
+	struct ahead_behind_count *counts;
+	size_t counts_nr;
 };
 
 struct ref_filter {
@@ -75,14 +83,19 @@ struct ref_format {
 	const char *format;
 	const char *rest;
 	int quote_style;
-	int use_rest;
 	int use_color;
 
 	/* Internal state to ref-filter */
 	int need_color_reset_at_eol;
+
+	/* List of bases for ahead-behind counts. */
+	struct string_list bases;
 };
 
-#define REF_FORMAT_INIT { .use_color = -1 }
+#define REF_FORMAT_INIT {             \
+	.use_color = -1,              \
+	.bases = STRING_LIST_INIT_DUP, \
+}
 
 /*  Macros for checking --merged and --no-merged options */
 #define _OPT_MERGED_NO_MERGED(option, filter, h) \
@@ -143,4 +156,15 @@ struct ref_array_item *ref_array_push(struct ref_array *array,
 				      const char *refname,
 				      const struct object_id *oid);
 
+/*
+ * If the provided format includes ahead-behind atoms, then compute the
+ * ahead-behind values for the array of filtered references. Must be
+ * called after filter_refs() but before outputting the formatted refs.
+ *
+ * If this is not called, then any ahead-behind atoms will be blank.
+ */
+void filter_ahead_behind(struct repository *r,
+			 struct ref_format *format,
+			 struct ref_array *array);
+
 #endif /*  REF_FILTER_H  */
diff --git a/reflog-walk.c b/reflog-walk.c
index 8a4d8fa..4ba1a10 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "commit.h"
 #include "refs.h"
 #include "diff.h"
diff --git a/reflog-walk.h b/reflog-walk.h
index 8076f10..4d93a26 100644
--- a/reflog-walk.h
+++ b/reflog-walk.h
@@ -1,8 +1,6 @@
 #ifndef REFLOG_WALK_H
 #define REFLOG_WALK_H
 
-#include "cache.h"
-
 struct commit;
 struct reflog_walk_info;
 struct date_mode;
diff --git a/reflog.c b/reflog.c
index 04630f5..ee1bf5d 100644
--- a/reflog.c
+++ b/reflog.c
@@ -1,8 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
 #include "object-store.h"
 #include "reflog.h"
 #include "refs.h"
 #include "revision.h"
+#include "tree.h"
+#include "tree-walk.h"
 #include "worktree.h"
 
 /* Remember to update object flag allocation in object.h */
@@ -28,7 +31,8 @@ static int tree_is_complete(const struct object_id *oid)
 	if (!tree->buffer) {
 		enum object_type type;
 		unsigned long size;
-		void *data = read_object_file(oid, &type, &size);
+		void *data = repo_read_object_file(the_repository, oid, &type,
+						   &size);
 		if (!data) {
 			tree->object.flags |= INCOMPLETE;
 			return 0;
@@ -39,7 +43,7 @@ static int tree_is_complete(const struct object_id *oid)
 	init_tree_desc(&desc, tree->buffer, tree->size);
 	complete = 1;
 	while (tree_entry(&desc, &entry)) {
-		if (!has_object_file(&entry.oid) ||
+		if (!repo_has_object_file(the_repository, &entry.oid) ||
 		    (S_ISDIR(entry.mode) && !tree_is_complete(&entry.oid))) {
 			tree->object.flags |= INCOMPLETE;
 			complete = 0;
@@ -186,7 +190,7 @@ static void mark_reachable(struct expire_reflog_policy_cb *cb)
 		struct commit *commit = pop_commit(&pending);
 		if (commit->object.flags & REACHABLE)
 			continue;
-		if (parse_commit(commit))
+		if (repo_parse_commit(the_repository, commit))
 			continue;
 		commit->object.flags |= REACHABLE;
 		if (commit->date < expire_limit) {
diff --git a/refs.c b/refs.c
index aeae31c..d2a98e1 100644
--- a/refs.c
+++ b/refs.c
@@ -2,15 +2,21 @@
  * The backend-independent part of the reference module.
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
 #include "hashmap.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "iterator.h"
 #include "refs.h"
 #include "refs/refs-internal.h"
 #include "run-command.h"
 #include "hook.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "object.h"
 #include "tag.h"
@@ -18,9 +24,11 @@
 #include "worktree.h"
 #include "strvec.h"
 #include "repository.h"
+#include "setup.h"
 #include "sigchain.h"
 #include "date.h"
 #include "commit.h"
+#include "wrapper.h"
 
 /*
  * List of all available backends
@@ -1821,7 +1829,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 			return NULL;
 
 		/*
-		 * dwim_ref() uses REF_ISBROKEN to distinguish between
+		 * repo_dwim_ref() uses REF_ISBROKEN to distinguish between
 		 * missing refs and refs that were present but invalid,
 		 * to complain about the latter to stderr.
 		 *
diff --git a/refs.h b/refs.h
index 935cdd1..123cfa4 100644
--- a/refs.h
+++ b/refs.h
@@ -1,7 +1,6 @@
 #ifndef REFS_H
 #define REFS_H
 
-#include "cache.h"
 #include "commit.h"
 
 struct object_id;
@@ -159,12 +158,6 @@ int expand_ref(struct repository *r, const char *str, int len, struct object_id
 int repo_dwim_ref(struct repository *r, const char *str, int len,
 		  struct object_id *oid, char **ref, int nonfatal_dangling_mark);
 int repo_dwim_log(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
-static inline int dwim_ref(const char *str, int len, struct object_id *oid,
-			   char **ref, int nonfatal_dangling_mark)
-{
-	return repo_dwim_ref(the_repository, str, len, oid, ref,
-			     nonfatal_dangling_mark);
-}
 int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
 
 /*
diff --git a/refs/debug.c b/refs/debug.c
index eed8bc9..6f11e6d 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -1,5 +1,7 @@
-
+#include "git-compat-util.h"
+#include "hex.h"
 #include "refs-internal.h"
+#include "string-list.h"
 #include "trace.h"
 
 static struct trace_key trace_refs = TRACE_KEY_INIT(REFS);
diff --git a/refs/files-backend.c b/refs/files-backend.c
index b899543..bca7b85 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1,16 +1,26 @@
 #include "../cache.h"
 #include "../config.h"
+#include "../copy.h"
+#include "../environment.h"
+#include "../gettext.h"
+#include "../hash.h"
+#include "../hex.h"
 #include "../refs.h"
 #include "refs-internal.h"
 #include "ref-cache.h"
 #include "packed-backend.h"
+#include "../ident.h"
 #include "../iterator.h"
 #include "../dir-iterator.h"
 #include "../lockfile.h"
 #include "../object.h"
+#include "../object-file.h"
 #include "../dir.h"
 #include "../chdir-notify.h"
-#include "worktree.h"
+#include "../setup.h"
+#include "../worktree.h"
+#include "../wrapper.h"
+#include "../write-or-die.h"
 
 /*
  * This backend uses the following flags in `ref_update::flags` for
diff --git a/refs/iterator.c b/refs/iterator.c
index c9fd0bc..6b680f6 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -3,7 +3,7 @@
  * documentation about the design and use of reference iterators.
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
 #include "refs.h"
 #include "refs/refs-internal.h"
 #include "iterator.h"
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 6f5a070..5b412a1 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -1,11 +1,17 @@
 #include "../cache.h"
+#include "../alloc.h"
 #include "../config.h"
+#include "../gettext.h"
+#include "../hash.h"
+#include "../hex.h"
 #include "../refs.h"
 #include "refs-internal.h"
 #include "packed-backend.h"
 #include "../iterator.h"
 #include "../lockfile.h"
 #include "../chdir-notify.h"
+#include "../wrapper.h"
+#include "../write-or-die.h"
 
 enum mmap_strategy {
 	/*
@@ -646,7 +652,7 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
 					 snapshot->buf,
 					 snapshot->eof - snapshot->buf);
 
-		string_list_split_in_place(&traits, p, ' ', -1);
+		string_list_split_in_place(&traits, p, " ", -1);
 
 		if (unsorted_string_list_has_string(&traits, "fully-peeled"))
 			snapshot->peeled = PEELED_FULLY;
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index 32afd8a..2294c45 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -1,5 +1,8 @@
-#include "../cache.h"
+#include "../git-compat-util.h"
+#include "../alloc.h"
+#include "../hash.h"
 #include "../refs.h"
+#include "../repository.h"
 #include "refs-internal.h"
 #include "ref-cache.h"
 #include "../iterator.h"
diff --git a/refs/ref-cache.h b/refs/ref-cache.h
index 850d9d3..95c76e2 100644
--- a/refs/ref-cache.h
+++ b/refs/ref-cache.h
@@ -1,10 +1,11 @@
 #ifndef REFS_REF_CACHE_H
 #define REFS_REF_CACHE_H
 
-#include "cache.h"
+#include "hash-ll.h"
 
 struct ref_dir;
 struct ref_store;
+struct repository;
 
 /*
  * If this ref_cache is filled lazily, this function is used to load
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 69f93b0..a85d113 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -1,7 +1,6 @@
 #ifndef REFS_REFS_INTERNAL_H
 #define REFS_REFS_INTERNAL_H
 
-#include "cache.h"
 #include "refs.h"
 #include "iterator.h"
 
diff --git a/refspec.c b/refspec.c
index 63e3112..57f6c2a 100644
--- a/refspec.c
+++ b/refspec.c
@@ -1,7 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
+#include "gettext.h"
+#include "hash.h"
+#include "hex.h"
 #include "strvec.h"
 #include "refs.h"
 #include "refspec.h"
+#include "strbuf.h"
 
 static struct refspec_item s_tag_refspec = {
 	.force = 0,
diff --git a/reftable/dump.c b/reftable/dump.c
index 155953d..ce936b4 100644
--- a/reftable/dump.c
+++ b/reftable/dump.c
@@ -7,7 +7,7 @@ license that can be found in the LICENSE file or at
 */
 
 #include "git-compat-util.h"
-#include "hash.h"
+#include "hash-ll.h"
 
 #include "reftable-blocksource.h"
 #include "reftable-error.h"
diff --git a/reftable/error.c b/reftable/error.c
index 93941f2..0d17667 100644
--- a/reftable/error.c
+++ b/reftable/error.c
@@ -6,6 +6,7 @@ license that can be found in the LICENSE file or at
 https://developers.google.com/open-source/licenses/bsd
 */
 
+#include "system.h"
 #include "reftable-error.h"
 
 #include <stdio.h>
diff --git a/reftable/publicbasics.c b/reftable/publicbasics.c
index 0ad7d5c..bcb8253 100644
--- a/reftable/publicbasics.c
+++ b/reftable/publicbasics.c
@@ -6,10 +6,10 @@ license that can be found in the LICENSE file or at
 https://developers.google.com/open-source/licenses/bsd
 */
 
+#include "system.h"
 #include "reftable-malloc.h"
 
 #include "basics.h"
-#include "system.h"
 
 static void *(*reftable_malloc_ptr)(size_t sz);
 static void *(*reftable_realloc_ptr)(void *, size_t);
diff --git a/reftable/system.h b/reftable/system.h
index 18f9207..6b74a81 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -13,7 +13,7 @@ license that can be found in the LICENSE file or at
 
 #include "git-compat-util.h"
 #include "strbuf.h"
-#include "hash.h" /* hash ID, sizes.*/
+#include "hash-ll.h" /* hash ID, sizes.*/
 #include "dir.h" /* remove_dir_recursively, for tests.*/
 
 int hash_size(uint32_t id);
diff --git a/reftable/tree.c b/reftable/tree.c
index b8899e0..a5bf880 100644
--- a/reftable/tree.c
+++ b/reftable/tree.c
@@ -6,10 +6,10 @@ license that can be found in the LICENSE file or at
 https://developers.google.com/open-source/licenses/bsd
 */
 
+#include "system.h"
 #include "tree.h"
 
 #include "basics.h"
-#include "system.h"
 
 struct tree_node *tree_search(void *key, struct tree_node **rootp,
 			      int (*compare)(const void *, const void *),
diff --git a/reftable/tree_test.c b/reftable/tree_test.c
index cbff125..ac3a045 100644
--- a/reftable/tree_test.c
+++ b/reftable/tree_test.c
@@ -6,6 +6,7 @@ license that can be found in the LICENSE file or at
 https://developers.google.com/open-source/licenses/bsd
 */
 
+#include "system.h"
 #include "tree.h"
 
 #include "basics.h"
diff --git a/remote-curl.c b/remote-curl.c
index a76b640..acf7b2b 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -1,5 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "remote.h"
 #include "connect.h"
 #include "strbuf.h"
@@ -14,9 +18,12 @@
 #include "credential.h"
 #include "oid-array.h"
 #include "send-pack.h"
+#include "setup.h"
 #include "protocol.h"
 #include "quote.h"
+#include "trace2.h"
 #include "transport.h"
+#include "write-or-die.h"
 
 static struct remote *remote;
 /* always ends with a trailing slash */
@@ -472,10 +479,11 @@ static struct discovery *discover_refs(const char *service, int for_push)
 
 	/*
 	 * NEEDSWORK: If we are trying to use protocol v2 and we are planning
-	 * to perform a push, then fallback to v0 since the client doesn't know
-	 * how to push yet using v2.
+	 * to perform any operation that doesn't involve upload-pack (i.e., a
+	 * fetch, ls-remote, etc), then fallback to v0 since we don't know how
+	 * to do anything else (like push or remote archive) via v2.
 	 */
-	if (version == protocol_v2 && !strcmp("git-receive-pack", service))
+	if (version == protocol_v2 && strcmp("git-upload-pack", service))
 		version = protocol_v0;
 
 	/* Add the extra Git-Protocol header */
diff --git a/remote.c b/remote.c
index 60869be..0764fca 100644
--- a/remote.c
+++ b/remote.c
@@ -1,20 +1,28 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "remote.h"
 #include "urlmatch.h"
 #include "refs.h"
 #include "refspec.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "commit.h"
 #include "diff.h"
 #include "revision.h"
 #include "dir.h"
 #include "tag.h"
+#include "setup.h"
 #include "string-list.h"
 #include "strvec.h"
 #include "commit-reach.h"
 #include "advice.h"
 #include "connect.h"
+#include "parse-options.h"
 
 enum map_direction { FROM_SRC, FROM_DST };
 
@@ -1163,7 +1171,7 @@ static int try_explicit_object_name(const char *name,
 		return 0;
 	}
 
-	if (get_oid(name, &oid))
+	if (repo_get_oid(the_repository, name, &oid))
 		return -1;
 
 	if (match) {
@@ -1251,7 +1259,7 @@ static void show_push_unqualified_ref_name_error(const char *dst_value,
 	if (!advice_enabled(ADVICE_PUSH_UNQUALIFIED_REF_NAME))
 		return;
 
-	if (get_oid(matched_src_name, &oid))
+	if (repo_get_oid(the_repository, matched_src_name, &oid))
 		BUG("'%s' is not a valid object, "
 		    "match_explicit_lhs() should catch this!",
 		    matched_src_name);
@@ -1759,7 +1767,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
 		if (!reject_reason && !ref->deletion && !is_null_oid(&ref->old_oid)) {
 			if (starts_with(ref->name, "refs/tags/"))
 				reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS;
-			else if (!has_object_file(&ref->old_oid))
+			else if (!repo_has_object_file(the_repository, &ref->old_oid))
 				reject_reason = REF_STATUS_REJECT_FETCH_FIRST;
 			else if (!lookup_commit_reference_gently(the_repository, &ref->old_oid, 1) ||
 				 !lookup_commit_reference_gently(the_repository, &ref->new_oid, 1))
@@ -1808,8 +1816,9 @@ static void set_merge(struct remote_state *remote_state, struct branch *ret)
 		if (!remote_find_tracking(remote, ret->merge[i]) ||
 		    strcmp(ret->remote_name, "."))
 			continue;
-		if (dwim_ref(ret->merge_name[i], strlen(ret->merge_name[i]),
-			     &oid, &ref, 0) == 1)
+		if (repo_dwim_ref(the_repository, ret->merge_name[i],
+				  strlen(ret->merge_name[i]), &oid, &ref,
+				  0) == 1)
 			ret->merge[i]->dst = ref;
 		else
 			ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
@@ -2505,7 +2514,7 @@ static int parse_push_cas_option(struct push_cas_option *cas, const char *arg, i
 		entry->use_tracking = 1;
 	else if (!colon[1])
 		oidclr(&entry->expect);
-	else if (get_oid(colon + 1, &entry->expect))
+	else if (repo_get_oid(the_repository, colon + 1, &entry->expect))
 		return error(_("cannot parse expected object name '%s'"),
 			     colon + 1);
 	return 0;
@@ -2662,7 +2671,7 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)
 		if (MERGE_BASES_BATCH_SIZE < size)
 			size = MERGE_BASES_BATCH_SIZE;
 
-		if ((ret = in_merge_bases_many(commit, size, chunk)))
+		if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk)))
 			break;
 	}
 
diff --git a/remote.h b/remote.h
index 1ebbe42..73638ce 100644
--- a/remote.h
+++ b/remote.h
@@ -1,11 +1,10 @@
 #ifndef REMOTE_H
 #define REMOTE_H
 
-#include "cache.h"
-#include "parse-options.h"
 #include "hashmap.h"
 #include "refspec.h"
 
+struct option;
 struct transport_ls_refs_options;
 
 /**
diff --git a/replace-object.c b/replace-object.c
index 320be25..e98825d 100644
--- a/replace-object.c
+++ b/replace-object.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
+#include "hex.h"
 #include "oidmap.h"
 #include "object-store.h"
 #include "replace-object.h"
diff --git a/replace-object.h b/replace-object.h
index 3fbc32e..500482b 100644
--- a/replace-object.h
+++ b/replace-object.h
@@ -5,6 +5,14 @@
 #include "repository.h"
 #include "object-store.h"
 
+/*
+ * Do replace refs need to be checked this run?  This variable is
+ * initialized to true unless --no-replace-object is used or
+ * $GIT_NO_REPLACE_OBJECTS is set, but is set to false by some
+ * commands that do not want replace references to be active.
+ */
+extern int read_replace_refs;
+
 struct replace_object {
 	struct oidmap_entry original;
 	struct object_id replacement;
diff --git a/repo-settings.c b/repo-settings.c
index 3dbd3f0..d220c5d 100644
--- a/repo-settings.c
+++ b/repo-settings.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "repository.h"
 #include "midx.h"
@@ -41,10 +41,8 @@ void prepare_repo_settings(struct repository *r)
 	repo_cfg_bool(r, "feature.experimental", &experimental, 0);
 
 	/* Defaults modified by feature.* */
-	if (experimental) {
+	if (experimental)
 		r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING;
-		r->settings.gc_cruft_packs = 1;
-	}
 	if (manyfiles) {
 		r->settings.index_version = 4;
 		r->settings.index_skip_hash = 1;
@@ -63,6 +61,7 @@ void prepare_repo_settings(struct repository *r)
 	repo_cfg_bool(r, "core.multipackindex", &r->settings.core_multi_pack_index, 1);
 	repo_cfg_bool(r, "index.sparse", &r->settings.sparse_index, 0);
 	repo_cfg_bool(r, "index.skiphash", &r->settings.index_skip_hash, r->settings.index_skip_hash);
+	repo_cfg_bool(r, "pack.readreverseindex", &r->settings.pack_read_reverse_index, 1);
 
 	/*
 	 * The GIT_TEST_MULTI_PACK_INDEX variable is special in that
diff --git a/repository.c b/repository.c
index 937fa97..c53e480 100644
--- a/repository.c
+++ b/repository.c
@@ -4,14 +4,17 @@
  */
 #define USE_THE_INDEX_VARIABLE
 #include "cache.h"
+#include "abspath.h"
 #include "repository.h"
 #include "object-store.h"
 #include "config.h"
 #include "object.h"
 #include "lockfile.h"
 #include "remote.h"
+#include "setup.h"
 #include "submodule-config.h"
 #include "sparse-index.h"
+#include "trace2.h"
 #include "promisor-remote.h"
 
 /* The main repository */
diff --git a/repository.h b/repository.h
index e8c67ff..1a13ff2 100644
--- a/repository.h
+++ b/repository.h
@@ -1,7 +1,6 @@
 #ifndef REPOSITORY_H
 #define REPOSITORY_H
 
-#include "git-compat-util.h"
 #include "path.h"
 
 struct config_set;
@@ -34,10 +33,10 @@ struct repo_settings {
 	int commit_graph_generation_version;
 	int commit_graph_read_changed_paths;
 	int gc_write_commit_graph;
-	int gc_cruft_packs;
 	int fetch_write_commit_graph;
 	int command_requires_full_index;
 	int sparse_index;
+	int pack_read_reverse_index;
 
 	struct fsmonitor_settings *fsmonitor; /* lazily loaded */
 
diff --git a/rerere.c b/rerere.c
index 876ab43..e968d41 100644
--- a/rerere.c
+++ b/rerere.c
@@ -1,5 +1,10 @@
 #include "cache.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "config.h"
+#include "copy.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "string-list.h"
 #include "rerere.h"
@@ -9,9 +14,11 @@
 #include "ll-merge.h"
 #include "attr.h"
 #include "pathspec.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "hash-lookup.h"
 #include "strmap.h"
+#include "wrapper.h"
 
 #define RESOLVED 0
 #define PUNTED 1
@@ -965,8 +972,9 @@ static int handle_cache(struct index_state *istate,
 			break;
 		i = ce_stage(ce) - 1;
 		if (!mmfile[i].ptr) {
-			mmfile[i].ptr = read_object_file(&ce->oid, &type,
-							 &size);
+			mmfile[i].ptr = repo_read_object_file(the_repository,
+							      &ce->oid, &type,
+							      &size);
 			mmfile[i].size = size;
 		}
 	}
diff --git a/rerere.h b/rerere.h
index c32d79c..5d6cb63 100644
--- a/rerere.h
+++ b/rerere.h
@@ -1,6 +1,7 @@
 #ifndef RERERE_H
 #define RERERE_H
 
+#include "gettext.h"
 #include "string-list.h"
 
 struct pathspec;
@@ -24,9 +25,6 @@ struct rerere_id {
 };
 
 int setup_rerere(struct repository *,struct string_list *, int);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define rerere(flags) repo_rerere(the_repository, flags)
-#endif
 int repo_rerere(struct repository *, int);
 /*
  * Given the conflict ID and the name of a "file" used for replaying
diff --git a/reset.c b/reset.c
index 5ded236..48da0ad 100644
--- a/reset.c
+++ b/reset.c
@@ -1,6 +1,9 @@
 #include "git-compat-util.h"
 #include "cache-tree.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
+#include "object-name.h"
 #include "refs.h"
 #include "reset.h"
 #include "run-command.h"
@@ -38,7 +41,7 @@ static int update_refs(const struct reset_head_opts *opts,
 	prefix_len = msg.len;
 
 	if (update_orig_head) {
-		if (!get_oid("ORIG_HEAD", &oid_old_orig))
+		if (!repo_get_oid(the_repository, "ORIG_HEAD", &oid_old_orig))
 			old_orig = &oid_old_orig;
 		if (head) {
 			if (!reflog_orig_head) {
@@ -106,7 +109,7 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts)
 		goto leave_reset_head;
 	}
 
-	if (!get_oid("HEAD", &head_oid)) {
+	if (!repo_get_oid(r, "HEAD", &head_oid)) {
 		head = &head_oid;
 	} else if (!oid || !reset_hard) {
 		ret = error(_("could not determine HEAD revision"));
diff --git a/reset.h b/reset.h
index a28f818..10708d8 100644
--- a/reset.h
+++ b/reset.h
@@ -1,7 +1,7 @@
 #ifndef RESET_H
 #define RESET_H
 
-#include "hash.h"
+#include "hash-ll.h"
 #include "repository.h"
 
 #define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
diff --git a/resolve-undo.c b/resolve-undo.c
index e81096e..70a6db5 100644
--- a/resolve-undo.c
+++ b/resolve-undo.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "dir.h"
+#include "hash.h"
 #include "resolve-undo.h"
 #include "string-list.h"
 
diff --git a/resolve-undo.h b/resolve-undo.h
index 2b3f0f9..c5deafc 100644
--- a/resolve-undo.h
+++ b/resolve-undo.h
@@ -1,7 +1,12 @@
 #ifndef RESOLVE_UNDO_H
 #define RESOLVE_UNDO_H
 
-#include "cache.h"
+struct cache_entry;
+struct index_state;
+struct pathspec;
+struct string_list;
+
+#include "hash-ll.h"
 
 struct resolve_undo_info {
 	unsigned int mode[3];
diff --git a/revision.c b/revision.c
index 21f5f57..b33cc1d 100644
--- a/revision.c
+++ b/revision.c
@@ -1,5 +1,11 @@
 #include "cache.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "tag.h"
 #include "blob.h"
@@ -25,7 +31,9 @@
 #include "bisect.h"
 #include "packfile.h"
 #include "worktree.h"
+#include "setup.h"
 #include "strvec.h"
+#include "trace2.h"
 #include "commit-reach.h"
 #include "commit-graph.h"
 #include "prio-queue.h"
@@ -35,6 +43,7 @@
 #include "json-writer.h"
 #include "list-objects-filter-options.h"
 #include "resolve-undo.h"
+#include "parse-options.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -324,7 +333,8 @@ static void add_pending_object_with_path(struct rev_info *revs,
 	if (revs->reflog_info && obj->type == OBJ_COMMIT) {
 		struct strbuf buf = STRBUF_INIT;
 		size_t namelen = strlen(name);
-		int len = interpret_branch_name(name, namelen, &buf, &options);
+		int len = repo_interpret_branch_name(the_repository, name,
+						     namelen, &buf, &options);
 
 		if (0 < len && len < namelen && buf.len)
 			strbuf_addstr(&buf, name + len);
@@ -354,7 +364,7 @@ void add_head_to_pending(struct rev_info *revs)
 {
 	struct object_id oid;
 	struct object *obj;
-	if (get_oid("HEAD", &oid))
+	if (repo_get_oid(the_repository, "HEAD", &oid))
 		return;
 	obj = parse_object(revs->repo, &oid);
 	if (!obj)
@@ -777,8 +787,8 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs,
 static int rev_compare_tree(struct rev_info *revs,
 			    struct commit *parent, struct commit *commit, int nth_parent)
 {
-	struct tree *t1 = get_commit_tree(parent);
-	struct tree *t2 = get_commit_tree(commit);
+	struct tree *t1 = repo_get_commit_tree(the_repository, parent);
+	struct tree *t2 = repo_get_commit_tree(the_repository, commit);
 	int bloom_ret = 1;
 
 	if (!t1)
@@ -824,7 +834,7 @@ static int rev_compare_tree(struct rev_info *revs,
 
 static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
 {
-	struct tree *t1 = get_commit_tree(commit);
+	struct tree *t1 = repo_get_commit_tree(the_repository, commit);
 
 	if (!t1)
 		return 0;
@@ -962,7 +972,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
 	if (!revs->prune)
 		return;
 
-	if (!get_commit_tree(commit))
+	if (!repo_get_commit_tree(the_repository, commit))
 		return;
 
 	if (!commit->parents) {
@@ -1574,7 +1584,8 @@ void exclude_hidden_refs(struct ref_exclusions *exclusions, const char *section)
 {
 	struct exclude_hidden_refs_cb cb;
 
-	if (strcmp(section, "receive") && strcmp(section, "uploadpack"))
+	if (strcmp(section, "fetch") && strcmp(section, "receive") &&
+			strcmp(section, "uploadpack"))
 		die(_("unsupported section for hidden refs: %s"), section);
 
 	if (exclusions->hidden_refs_configured)
@@ -1867,7 +1878,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg_, int flags,
 		flags ^= UNINTERESTING | BOTTOM;
 		arg++;
 	}
-	if (get_oid_committish(arg, &oid))
+	if (repo_get_oid_committish(the_repository, arg, &oid))
 		return 0;
 	while (1) {
 		it = get_reference(revs, arg, &oid, 0);
@@ -1948,15 +1959,15 @@ static void prepare_show_merge(struct rev_info *revs)
 	int i, prune_num = 1; /* counting terminating NULL */
 	struct index_state *istate = revs->repo->index;
 
-	if (get_oid("HEAD", &oid))
+	if (repo_get_oid(the_repository, "HEAD", &oid))
 		die("--merge without HEAD?");
 	head = lookup_commit_or_die(&oid, "HEAD");
-	if (get_oid("MERGE_HEAD", &oid))
+	if (repo_get_oid(the_repository, "MERGE_HEAD", &oid))
 		die("--merge without MERGE_HEAD?");
 	other = lookup_commit_or_die(&oid, "MERGE_HEAD");
 	add_pending_object(revs, &head->object, "HEAD");
 	add_pending_object(revs, &other->object, "MERGE_HEAD");
-	bases = get_merge_bases(head, other);
+	bases = repo_get_merge_bases(the_repository, head, other);
 	add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
 	add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
 	free_commit_list(bases);
@@ -2051,7 +2062,7 @@ static int handle_dotdot_1(const char *arg, char *dotdot,
 		if (!a || !b)
 			return dotdot_missing(arg, dotdot, revs, symmetric);
 
-		exclude = get_merge_bases(a, b);
+		exclude = repo_get_merge_bases(the_repository, a, b);
 		add_rev_cmdline_list(revs, exclude, REV_CMD_MERGE_BASE,
 				     flags_exclude);
 		add_pending_commit_list(revs, exclude, flags_exclude);
@@ -3440,8 +3451,8 @@ void reset_revision_walk(void)
 }
 
 static int mark_uninteresting(const struct object_id *oid,
-			      struct packed_git *pack,
-			      uint32_t pos,
+			      struct packed_git *pack UNUSED,
+			      uint32_t pos UNUSED,
 			      void *cb)
 {
 	struct rev_info *revs = cb;
@@ -3877,7 +3888,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
 	 * in it.
 	 */
 	encoding = get_log_output_encoding();
-	message = logmsg_reencode(commit, NULL, encoding);
+	message = repo_logmsg_reencode(the_repository, commit, NULL, encoding);
 
 	/* Copy the commit to temporary if we are using "fake" headers */
 	if (buf.len)
@@ -3913,7 +3924,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
 		retval = grep_buffer(&opt->grep_filter,
 				     (char *)message, strlen(message));
 	strbuf_release(&buf);
-	unuse_commit_buffer(commit, message);
+	repo_unuse_commit_buffer(the_repository, commit, message);
 	return retval;
 }
 
@@ -4159,7 +4170,7 @@ static struct commit *get_revision_1(struct rev_info *revs)
  * Return true for entries that have not yet been shown.  (This is an
  * object_array_each_func_t.)
  */
-static int entry_unshown(struct object_array_entry *entry, void *cb_data_unused)
+static int entry_unshown(struct object_array_entry *entry, void *cb_data UNUSED)
 {
 	return !(entry->item->flags & SHOWN);
 }
diff --git a/revision.h b/revision.h
index 30febad..3182874 100644
--- a/revision.h
+++ b/revision.h
@@ -2,12 +2,13 @@
 #define REVISION_H
 
 #include "commit.h"
-#include "parse-options.h"
 #include "grep.h"
 #include "notes.h"
 #include "pretty.h"
 #include "diff.h"
 #include "commit-slab-decl.h"
+#include "decorate.h"
+#include "ident.h"
 #include "list-objects-filter-options.h"
 
 /**
@@ -61,6 +62,8 @@ struct string_list;
 struct saved_parents;
 struct bloom_key;
 struct bloom_filter_settings;
+struct option;
+struct parse_opt_ctx_t;
 define_shared_commit_slab(revision_sources, char *);
 
 struct rev_cmdline_info {
@@ -415,9 +418,6 @@ struct rev_info {
 void repo_init_revisions(struct repository *r,
 			 struct rev_info *revs,
 			 const char *prefix);
-#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
-#define init_revisions(revs, prefix) repo_init_revisions(the_repository, revs, prefix)
-#endif
 
 /**
  * Parse revision information, filling in the `rev_info` structure, and
diff --git a/run-command.c b/run-command.c
index 6bd16ac..60c9419 100644
--- a/run-command.c
+++ b/run-command.c
@@ -1,16 +1,22 @@
 #include "cache.h"
 #include "run-command.h"
+#include "environment.h"
 #include "exec-cmd.h"
+#include "gettext.h"
 #include "sigchain.h"
 #include "strvec.h"
+#include "symlinks.h"
 #include "thread-utils.h"
 #include "strbuf.h"
 #include "string-list.h"
+#include "trace.h"
+#include "trace2.h"
 #include "quote.h"
 #include "config.h"
 #include "packfile.h"
 #include "hook.h"
 #include "compat/nonblock.h"
+#include "alloc.h"
 
 void child_process_init(struct child_process *child)
 {
@@ -341,19 +347,19 @@ static void child_close_pair(int fd[2])
 	child_close(fd[1]);
 }
 
-static void child_error_fn(const char *err, va_list params)
+static void child_error_fn(const char *err UNUSED, va_list params UNUSED)
 {
 	const char msg[] = "error() should not be called in child\n";
 	xwrite(2, msg, sizeof(msg) - 1);
 }
 
-static void child_warn_fn(const char *err, va_list params)
+static void child_warn_fn(const char *err UNUSED, va_list params UNUSED)
 {
 	const char msg[] = "warn() should not be called in child\n";
 	xwrite(2, msg, sizeof(msg) - 1);
 }
 
-static void NORETURN child_die_fn(const char *err, va_list params)
+static void NORETURN child_die_fn(const char *err UNUSED, va_list params UNUSED)
 {
 	const char msg[] = "die() should not be called in child\n";
 	xwrite(2, msg, sizeof(msg) - 1);
diff --git a/scalar.c b/scalar.c
index ca19b95..1326e1f 100644
--- a/scalar.c
+++ b/scalar.c
@@ -2,7 +2,8 @@
  * The Scalar command-line interface.
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
 #include "gettext.h"
 #include "parse-options.h"
 #include "config.h"
@@ -14,6 +15,8 @@
 #include "dir.h"
 #include "packfile.h"
 #include "help.h"
+#include "setup.h"
+#include "trace2.h"
 
 static void setup_enlistment_directory(int argc, const char **argv,
 				       const char * const *usagestr,
@@ -563,7 +566,7 @@ static int cmd_diagnose(int argc, const char **argv)
 	return res;
 }
 
-static int cmd_list(int argc, const char **argv)
+static int cmd_list(int argc, const char **argv UNUSED)
 {
 	if (argc != 1)
 		die(_("`scalar list` does not take arguments"));
diff --git a/send-pack.c b/send-pack.c
index f2e1983..0c7ccae 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -1,6 +1,9 @@
-#include "builtin.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "commit.h"
+#include "date.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
 #include "object-store.h"
 #include "pkt-line.h"
@@ -12,10 +15,13 @@
 #include "quote.h"
 #include "transport.h"
 #include "version.h"
+#include "wrapper.h"
 #include "oid-array.h"
 #include "gpg-interface.h"
-#include "cache.h"
 #include "shallow.h"
+#include "parse-options.h"
+#include "trace2.h"
+#include "write-or-die.h"
 
 int option_parse_push_signed(const struct option *opt,
 			     const char *arg, int unset)
@@ -42,9 +48,9 @@ int option_parse_push_signed(const struct option *opt,
 static void feed_object(const struct object_id *oid, FILE *fh, int negative)
 {
 	if (negative &&
-	    !has_object_file_with_flags(oid,
-					OBJECT_INFO_SKIP_FETCH_OBJECT |
-					OBJECT_INFO_QUICK))
+	    !repo_has_object_file_with_flags(the_repository, oid,
+					     OBJECT_INFO_SKIP_FETCH_OBJECT |
+					     OBJECT_INFO_QUICK))
 		return;
 
 	if (negative)
@@ -534,7 +540,7 @@ int send_pack(struct send_pack_args *args,
 		die(_("the receiving end does not support this repository's hash algorithm"));
 
 	if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {
-		int len;
+		size_t len;
 		push_cert_nonce = server_feature_value("push-cert", &len);
 		if (push_cert_nonce) {
 			reject_invalid_nonce(push_cert_nonce, len);
diff --git a/sequencer.c b/sequencer.c
index 1c96a75..bceb6ab 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1,9 +1,19 @@
 #include "cache.h"
+#include "abspath.h"
+#include "advice.h"
+#include "alloc.h"
 #include "config.h"
+#include "copy.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "dir.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "object.h"
+#include "pager.h"
 #include "commit.h"
 #include "sequencer.h"
 #include "tag.h"
@@ -36,6 +46,7 @@
 #include "rebase-interactive.h"
 #include "reset.h"
 #include "branch.h"
+#include "wrapper.h"
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
@@ -263,10 +274,6 @@ static int git_sequencer_config(const char *k, const char *v, void *cb)
 	if (opts->action == REPLAY_REVERT && !strcmp(k, "revert.reference"))
 		opts->commit_use_reference = git_config_bool(k, v);
 
-	status = git_gpg_config(k, v, NULL);
-	if (status)
-		return status;
-
 	return git_diff_basic_config(k, v, NULL);
 }
 
@@ -357,9 +364,7 @@ void replay_opts_release(struct replay_opts *opts)
 	free(opts->reflog_action);
 	free(opts->default_strategy);
 	free(opts->strategy);
-	for (size_t i = 0; i < opts->xopts_nr; i++)
-		free(opts->xopts[i]);
-	free(opts->xopts);
+	strvec_clear (&opts->xopts);
 	strbuf_release(&opts->current_fixups);
 	if (opts->revs)
 		release_revisions(opts->revs);
@@ -419,7 +424,8 @@ struct commit_message {
 
 static const char *short_commit_name(struct commit *commit)
 {
-	return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV);
+	return repo_find_unique_abbrev(the_repository, &commit->object.oid,
+				       DEFAULT_ABBREV);
 }
 
 static int get_message(struct commit *commit, struct commit_message *out)
@@ -427,7 +433,8 @@ static int get_message(struct commit *commit, struct commit_message *out)
 	const char *abbrev, *subject;
 	int subject_len;
 
-	out->message = logmsg_reencode(commit, NULL, get_commit_output_encoding());
+	out->message = repo_logmsg_reencode(the_repository, commit, NULL,
+					    get_commit_output_encoding());
 	abbrev = short_commit_name(commit);
 
 	subject_len = find_commit_subject(out->message, &subject);
@@ -444,7 +451,7 @@ static void free_message(struct commit *commit, struct commit_message *msg)
 	free(msg->parent_label);
 	free(msg->label);
 	free(msg->subject);
-	unuse_commit_buffer(commit, msg->message);
+	repo_unuse_commit_buffer(the_repository, commit, msg->message);
 }
 
 static void print_advice(struct repository *r, int show_hint,
@@ -561,7 +568,7 @@ static void update_abort_safety_file(void)
 	if (!file_exists(git_path_seq_dir()))
 		return;
 
-	if (!get_oid("HEAD", &head))
+	if (!repo_get_oid(the_repository, "HEAD", &head))
 		write_file(git_path_abort_safety_file(), "%s", oid_to_hex(&head));
 	else
 		write_file(git_path_abort_safety_file(), "%s", "");
@@ -692,11 +699,11 @@ static int do_recursive_merge(struct repository *r,
 	o.show_rename_progress = 1;
 
 	head_tree = parse_tree_indirect(head);
-	next_tree = next ? get_commit_tree(next) : empty_tree(r);
-	base_tree = base ? get_commit_tree(base) : empty_tree(r);
+	next_tree = next ? repo_get_commit_tree(r, next) : empty_tree(r);
+	base_tree = base ? repo_get_commit_tree(r, base) : empty_tree(r);
 
-	for (i = 0; i < opts->xopts_nr; i++)
-		parse_merge_opt(&o, opts->xopts[i]);
+	for (i = 0; i < opts->xopts.nr; i++)
+		parse_merge_opt(&o, opts->xopts.v[i]);
 
 	if (!opts->strategy || !strcmp(opts->strategy, "ort")) {
 		memset(&result, 0, sizeof(result));
@@ -766,12 +773,12 @@ static int is_index_unchanged(struct repository *r)
 	/*
 	 * If head_commit is NULL, check_commit, called from
 	 * lookup_commit, would have indicated that head_commit is not
-	 * a commit object already.  parse_commit() will return failure
+	 * a commit object already.  repo_parse_commit() will return failure
 	 * without further complaints in such a case.  Otherwise, if
-	 * the commit is invalid, parse_commit() will complain.  So
+	 * the commit is invalid, repo_parse_commit() will complain.  So
 	 * there is nothing for us to say here.  Just return failure.
 	 */
-	if (parse_commit(head_commit))
+	if (repo_parse_commit(r, head_commit))
 		return -1;
 
 	if (!(cache_tree_oid = get_cache_tree_oid(istate)))
@@ -1336,13 +1343,15 @@ void print_commit_summary(struct repository *r,
 	commit = lookup_commit(r, oid);
 	if (!commit)
 		die(_("couldn't look up newly created commit"));
-	if (parse_commit(commit))
+	if (repo_parse_commit(r, commit))
 		die(_("could not parse newly created commit"));
 
 	strbuf_addstr(&format, "format:%h] %s");
 
-	format_commit_message(commit, "%an <%ae>", &author_ident, &pctx);
-	format_commit_message(commit, "%cn <%ce>", &committer_ident, &pctx);
+	repo_format_commit_message(r, commit, "%an <%ae>", &author_ident,
+				   &pctx);
+	repo_format_commit_message(r, commit, "%cn <%ce>", &committer_ident,
+				   &pctx);
 	if (strbuf_cmp(&author_ident, &committer_ident)) {
 		strbuf_addstr(&format, "\n Author: ");
 		strbuf_addbuf_percentquote(&format, &author_ident);
@@ -1350,7 +1359,7 @@ void print_commit_summary(struct repository *r,
 	if (flags & SUMMARY_SHOW_AUTHOR_DATE) {
 		struct strbuf date = STRBUF_INIT;
 
-		format_commit_message(commit, "%ad", &date, &pctx);
+		repo_format_commit_message(r, commit, "%ad", &date, &pctx);
 		strbuf_addstr(&format, "\n Date: ");
 		strbuf_addbuf_percentquote(&format, &date);
 		strbuf_release(&date);
@@ -1380,7 +1389,7 @@ void print_commit_summary(struct repository *r,
 	rev.diffopt.detect_rename = DIFF_DETECT_RENAME;
 	diff_setup_done(&rev.diffopt);
 
-	refs = get_main_ref_store(the_repository);
+	refs = get_main_ref_store(r);
 	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL);
 	if (!head)
 		die(_("unable to resolve HEAD after creating commit"));
@@ -1406,7 +1415,7 @@ static int parse_head(struct repository *r, struct commit **head)
 	struct commit *current_head;
 	struct object_id oid;
 
-	if (get_oid("HEAD", &oid)) {
+	if (repo_get_oid(r, "HEAD", &oid)) {
 		current_head = NULL;
 	} else {
 		current_head = lookup_commit_reference(r, &oid);
@@ -1416,7 +1425,7 @@ static int parse_head(struct repository *r, struct commit **head)
 			warning(_("HEAD %s is not a commit!"),
 				oid_to_hex(&oid));
 		}
-		if (parse_commit(current_head))
+		if (repo_parse_commit(r, current_head))
 			return error(_("could not parse HEAD commit"));
 	}
 	*head = current_head;
@@ -1459,8 +1468,8 @@ static int try_to_commit(struct repository *r,
 	if (flags & AMEND_MSG) {
 		const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
 		const char *out_enc = get_commit_output_encoding();
-		const char *message = logmsg_reencode(current_head, NULL,
-						      out_enc);
+		const char *message = repo_logmsg_reencode(r, current_head,
+							   NULL, out_enc);
 
 		if (!msg) {
 			const char *orig_message = NULL;
@@ -1471,7 +1480,8 @@ static int try_to_commit(struct repository *r,
 			hook_commit = "HEAD";
 		}
 		author = amend_author = get_author(message);
-		unuse_commit_buffer(current_head, message);
+		repo_unuse_commit_buffer(r, current_head,
+					 message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
 			goto out;
@@ -1668,12 +1678,12 @@ static int is_original_commit_empty(struct commit *commit)
 {
 	const struct object_id *ptree_oid;
 
-	if (parse_commit(commit))
+	if (repo_parse_commit(the_repository, commit))
 		return error(_("could not parse commit %s"),
 			     oid_to_hex(&commit->object.oid));
 	if (commit->parents) {
 		struct commit *parent = commit->parents->item;
-		if (parse_commit(parent))
+		if (repo_parse_commit(the_repository, parent))
 			return error(_("could not parse parent commit %s"),
 				oid_to_hex(&parent->object.oid));
 		ptree_oid = get_commit_tree_oid(parent);
@@ -1997,17 +2007,18 @@ static int update_squash_messages(struct repository *r,
 		struct commit *head_commit;
 		const char *head_message, *body;
 
-		if (get_oid("HEAD", &head))
+		if (repo_get_oid(r, "HEAD", &head))
 			return error(_("need a HEAD to fixup"));
 		if (!(head_commit = lookup_commit_reference(r, &head)))
 			return error(_("could not read HEAD"));
-		if (!(head_message = logmsg_reencode(head_commit, NULL, encoding)))
+		if (!(head_message = repo_logmsg_reencode(r, head_commit, NULL,
+							  encoding)))
 			return error(_("could not read HEAD's commit message"));
 
 		find_commit_subject(head_message, &body);
 		if (command == TODO_FIXUP && !flag && write_message(body, strlen(body),
 							rebase_path_fixup_msg(), 0) < 0) {
-			unuse_commit_buffer(head_commit, head_message);
+			repo_unuse_commit_buffer(r, head_commit, head_message);
 			return error(_("cannot write '%s'"), rebase_path_fixup_msg());
 		}
 		strbuf_addf(&buf, "%c ", comment_line_char);
@@ -2022,10 +2033,10 @@ static int update_squash_messages(struct repository *r,
 		else
 			strbuf_addstr(&buf, body);
 
-		unuse_commit_buffer(head_commit, head_message);
+		repo_unuse_commit_buffer(r, head_commit, head_message);
 	}
 
-	if (!(message = logmsg_reencode(commit, NULL, encoding)))
+	if (!(message = repo_logmsg_reencode(r, commit, NULL, encoding)))
 		return error(_("could not read commit message of %s"),
 			     oid_to_hex(&commit->object.oid));
 	find_commit_subject(message, &body);
@@ -2040,7 +2051,7 @@ static int update_squash_messages(struct repository *r,
 		strbuf_add_commented_lines(&buf, body, strlen(body));
 	} else
 		return error(_("unknown command: %d"), command);
-	unuse_commit_buffer(commit, message);
+	repo_unuse_commit_buffer(r, commit, message);
 
 	if (!res)
 		res = write_message(buf.buf, buf.len, rebase_path_squash_msg(),
@@ -2067,7 +2078,7 @@ static void flush_rewritten_pending(void)
 	FILE *out;
 
 	if (strbuf_read_file(&buf, rebase_path_rewritten_pending(), (GIT_MAX_HEXSZ + 1) * 2) > 0 &&
-	    !get_oid("HEAD", &newoid) &&
+	    !repo_get_oid(the_repository, "HEAD", &newoid) &&
 	    (out = fopen_or_warn(rebase_path_rewritten_list(), "a"))) {
 		char *bol = buf.buf, *eol;
 
@@ -2119,7 +2130,8 @@ static void refer_to_commit(struct replay_opts *opts,
 			.abbrev = DEFAULT_ABBREV,
 			.date_mode.type = DATE_SHORT,
 		};
-		format_commit_message(commit, "%h (%s, %ad)", msgbuf, &ctx);
+		repo_format_commit_message(the_repository, commit,
+					   "%h (%s, %ad)", msgbuf, &ctx);
 	} else {
 		strbuf_addstr(msgbuf, oid_to_hex(&commit->object.oid));
 	}
@@ -2152,7 +2164,7 @@ static int do_pick_commit(struct repository *r,
 		if (write_index_as_tree(&head, r->index, r->index_file, 0, NULL))
 			return error(_("your index file is unmerged."));
 	} else {
-		unborn = get_oid("HEAD", &head);
+		unborn = repo_get_oid(r, "HEAD", &head);
 		/* Do we want to generate a root commit? */
 		if (is_pick_or_similar(command) && opts->have_squash_onto &&
 		    oideq(&head, &opts->squash_onto)) {
@@ -2214,7 +2226,7 @@ static int do_pick_commit(struct repository *r,
 		msg_file = NULL;
 		goto fast_forward_edit;
 	}
-	if (parent && parse_commit(parent) < 0)
+	if (parent && repo_parse_commit(r, parent) < 0)
 		/* TRANSLATORS: The first %s will be a "todo" command like
 		   "revert" or "pick", the second %s a SHA1. */
 		return error(_("%s: cannot parse parent commit %s"),
@@ -2327,7 +2339,7 @@ static int do_pick_commit(struct repository *r,
 		commit_list_insert(base, &common);
 		commit_list_insert(next, &remotes);
 		res |= try_merge_command(r, opts->strategy,
-					 opts->xopts_nr, (const char **)opts->xopts,
+					 opts->xopts.nr, opts->xopts.v,
 					common, oid_to_hex(&head), remotes);
 		free_commit_list(common);
 		free_commit_list(remotes);
@@ -2465,7 +2477,6 @@ void todo_list_release(struct todo_list *todo_list)
 static struct todo_item *append_new_todo(struct todo_list *todo_list)
 {
 	ALLOC_GROW(todo_list->items, todo_list->nr + 1, todo_list->alloc);
-	todo_list->total_nr++;
 	return todo_list->items + todo_list->nr++;
 }
 
@@ -2606,7 +2617,7 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
 	end_of_object_name = (char *) bol + strcspn(bol, " \t\n");
 	saved = *end_of_object_name;
 	*end_of_object_name = '\0';
-	status = get_oid(bol, &commit_oid);
+	status = repo_get_oid(r, bol, &commit_oid);
 	if (status < 0)
 		error(_("could not parse '%s'"), bol); /* return later */
 	*end_of_object_name = saved;
@@ -2656,7 +2667,7 @@ int todo_list_parse_insn_buffer(struct repository *r, char *buf,
 	char *p = buf, *next_p;
 	int i, res = 0, fixup_okay = file_exists(rebase_path_done());
 
-	todo_list->current = todo_list->nr = 0;
+	todo_list->current = todo_list->nr = todo_list->total_nr = 0;
 
 	for (i = 1; *p; i++, p = next_p) {
 		char *eol = strchrnul(p, '\n');
@@ -2677,6 +2688,9 @@ int todo_list_parse_insn_buffer(struct repository *r, char *buf,
 			item->commit = NULL;
 		}
 
+		if (item->command != TODO_COMMENT)
+			todo_list->total_nr++;
+
 		if (fixup_okay)
 			; /* do nothing */
 		else if (is_fixup(item->command))
@@ -2900,8 +2914,7 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
 	else if (!strcmp(key, "options.gpg-sign"))
 		git_config_string_dup(&opts->gpg_sign, key, value);
 	else if (!strcmp(key, "options.strategy-option")) {
-		ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
-		opts->xopts[opts->xopts_nr++] = xstrdup(value);
+		strvec_push(&opts->xopts, value);
 	} else if (!strcmp(key, "options.allow-rerere-auto"))
 		opts->allow_rerere_auto =
 			git_config_bool_or_int(key, value, &error_flag) ?
@@ -2918,22 +2931,27 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
 	return 0;
 }
 
-void parse_strategy_opts(struct replay_opts *opts, char *raw_opts)
+static void parse_strategy_opts(struct replay_opts *opts, char *raw_opts)
 {
 	int i;
+	int count;
+	const char **argv;
 	char *strategy_opts_string = raw_opts;
 
 	if (*strategy_opts_string == ' ')
 		strategy_opts_string++;
 
-	opts->xopts_nr = split_cmdline(strategy_opts_string,
-				       (const char ***)&opts->xopts);
-	for (i = 0; i < opts->xopts_nr; i++) {
-		const char *arg = opts->xopts[i];
+	count = split_cmdline(strategy_opts_string, &argv);
+	if (count < 0)
+		BUG("could not split '%s': %s", strategy_opts_string,
+			    split_cmdline_strerror(count));
+	for (i = 0; i < count; i++) {
+		const char *arg = argv[i];
 
 		skip_prefix(arg, "--", &arg);
-		opts->xopts[i] = xstrdup(arg);
+		strvec_push(&opts->xopts, arg);
 	}
+	free(argv);
 }
 
 static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
@@ -2941,7 +2959,6 @@ static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
 	strbuf_reset(buf);
 	if (!read_oneliner(buf, rebase_path_strategy(), 0))
 		return;
-	free(opts->strategy);
 	opts->strategy = strbuf_detach(buf, NULL);
 	if (!read_oneliner(buf, rebase_path_strategy_opts(), 0))
 		return;
@@ -3022,7 +3039,7 @@ static int read_populate_opts(struct replay_opts *opts)
 		}
 
 		if (read_oneliner(&buf, rebase_path_squash_onto(), 0)) {
-			if (get_oid_committish(buf.buf, &opts->squash_onto) < 0) {
+			if (repo_get_oid_committish(the_repository, buf.buf, &opts->squash_onto) < 0) {
 				ret = error(_("unusable squash-onto"));
 				goto done_rebase_i;
 			}
@@ -3050,12 +3067,13 @@ static int read_populate_opts(struct replay_opts *opts)
 
 static void write_strategy_opts(struct replay_opts *opts)
 {
-	int i;
 	struct strbuf buf = STRBUF_INIT;
 
-	for (i = 0; i < opts->xopts_nr; ++i)
-		strbuf_addf(&buf, " --%s", opts->xopts[i]);
-
+	/*
+	 * Quote strategy options so that they can be read correctly
+	 * by split_cmdline().
+	 */
+	quote_cmdline(&buf, opts->xopts.v);
 	write_file(rebase_path_strategy_opts(), "%s\n", buf.buf);
 	strbuf_release(&buf);
 }
@@ -3078,7 +3096,7 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_verbose(), "%s", "");
 	if (opts->strategy)
 		write_file(rebase_path_strategy(), "%s\n", opts->strategy);
-	if (opts->xopts_nr > 0)
+	if (opts->xopts.nr > 0)
 		write_strategy_opts(opts);
 
 	if (opts->allow_rerere_auto == RERERE_AUTOUPDATE)
@@ -3122,7 +3140,9 @@ static int walk_revs_populate_todo(struct todo_list *todo_list,
 
 	while ((commit = get_revision(opts->revs))) {
 		struct todo_item *item = append_new_todo(todo_list);
-		const char *commit_buffer = logmsg_reencode(commit, NULL, encoding);
+		const char *commit_buffer = repo_logmsg_reencode(the_repository,
+								 commit, NULL,
+								 encoding);
 		const char *subject;
 		int subject_len;
 
@@ -3134,7 +3154,8 @@ static int walk_revs_populate_todo(struct todo_list *todo_list,
 		subject_len = find_commit_subject(commit_buffer, &subject);
 		strbuf_addf(&todo_list->buf, "%s %s %.*s\n", command_string,
 			short_commit_name(commit), subject_len, subject);
-		unuse_commit_buffer(commit, commit_buffer);
+		repo_unuse_commit_buffer(the_repository, commit,
+					 commit_buffer);
 	}
 
 	if (!todo_list->nr)
@@ -3184,25 +3205,7 @@ static int create_seq_dir(struct repository *r)
 
 static int save_head(const char *head)
 {
-	struct lock_file head_lock = LOCK_INIT;
-	struct strbuf buf = STRBUF_INIT;
-	int fd;
-	ssize_t written;
-
-	fd = hold_lock_file_for_update(&head_lock, git_path_head_file(), 0);
-	if (fd < 0)
-		return error_errno(_("could not lock HEAD"));
-	strbuf_addf(&buf, "%s\n", head);
-	written = write_in_full(fd, buf.buf, buf.len);
-	strbuf_release(&buf);
-	if (written < 0) {
-		error_errno(_("could not write to '%s'"), git_path_head_file());
-		rollback_lock_file(&head_lock);
-		return -1;
-	}
-	if (commit_lock_file(&head_lock) < 0)
-		return error(_("failed to finalize '%s'"), git_path_head_file());
-	return 0;
+	return write_message(head, strlen(head), git_path_head_file(), 1);
 }
 
 static int rollback_is_safe(void)
@@ -3223,7 +3226,7 @@ static int rollback_is_safe(void)
 	else
 		die_errno(_("could not read '%s'"), git_path_abort_safety_file());
 
-	if (get_oid("HEAD", &actual_head))
+	if (repo_get_oid(the_repository, "HEAD", &actual_head))
 		oidclr(&actual_head);
 
 	return oideq(&actual_head, &expected_head);
@@ -3462,13 +3465,10 @@ static int save_opts(struct replay_opts *opts)
 	if (opts->gpg_sign)
 		res |= git_config_set_in_file_gently(opts_file,
 					"options.gpg-sign", opts->gpg_sign);
-	if (opts->xopts) {
-		int i;
-		for (i = 0; i < opts->xopts_nr; i++)
-			res |= git_config_set_multivar_in_file_gently(opts_file,
-					"options.strategy-option",
-					opts->xopts[i], "^$", 0);
-	}
+	for (size_t i = 0; i < opts->xopts.nr; i++)
+		res |= git_config_set_multivar_in_file_gently(opts_file,
+				"options.strategy-option",
+				opts->xopts.v[i], "^$", 0);
 	if (opts->allow_rerere_auto)
 		res |= git_config_set_in_file_gently(opts_file,
 				"options.allow-rerere-auto",
@@ -3518,10 +3518,13 @@ static int make_patch(struct repository *r,
 	strbuf_addf(&buf, "%s/message", get_dir(opts));
 	if (!file_exists(buf.buf)) {
 		const char *encoding = get_commit_output_encoding();
-		const char *commit_buffer = logmsg_reencode(commit, NULL, encoding);
+		const char *commit_buffer = repo_logmsg_reencode(r,
+								 commit, NULL,
+								 encoding);
 		find_commit_subject(commit_buffer, &subject);
 		res |= write_message(subject, strlen(subject), buf.buf, 1);
-		unuse_commit_buffer(commit, commit_buffer);
+		repo_unuse_commit_buffer(r, commit,
+					 commit_buffer);
 	}
 	strbuf_release(&buf);
 	release_revisions(&log_tree_opt);
@@ -3534,7 +3537,7 @@ static int intend_to_amend(void)
 	struct object_id head;
 	char *p;
 
-	if (get_oid("HEAD", &head))
+	if (repo_get_oid(the_repository, "HEAD", &head))
 		return error(_("cannot read HEAD"));
 
 	p = oid_to_hex(&head);
@@ -3625,14 +3628,14 @@ static int do_exec(struct repository *r, const char *command_line)
 			  "  git rebase --continue\n"
 			  "\n"),
 			command_line,
-			dirty ? N_("and made changes to the index and/or the "
-				"working tree\n") : "");
+			dirty ? _("and made changes to the index and/or the "
+				"working tree.\n") : "");
 		if (status == 127)
 			/* command not found */
 			status = 1;
 	} else if (dirty) {
 		warning(_("execution succeeded: %s\nbut "
-			  "left changes to the index and/or the working tree\n"
+			  "left changes to the index and/or the working tree.\n"
 			  "Commit or stash your changes, and then run\n"
 			  "\n"
 			  "  git rebase --continue\n"
@@ -3673,7 +3676,6 @@ static int safe_append(const char *filename, const char *fmt, ...)
 	}
 	if (commit_lock_file(&lock) < 0) {
 		strbuf_release(&buf);
-		rollback_lock_file(&lock);
 		return error(_("failed to finalize '%s'"), filename);
 	}
 
@@ -3700,7 +3702,7 @@ static int do_label(struct repository *r, const char *name, int len)
 	if (!transaction) {
 		error("%s", err.buf);
 		ret = -1;
-	} else if (get_oid("HEAD", &head_oid)) {
+	} else if (repo_get_oid(r, "HEAD", &head_oid)) {
 		error(_("could not read HEAD"));
 		ret = -1;
 	} else if (ref_transaction_update(transaction, ref_name.buf, &head_oid,
@@ -3878,7 +3880,7 @@ static int do_merge(struct repository *r,
 	struct commit *head_commit, *merge_commit, *i;
 	struct commit_list *bases, *j;
 	struct commit_list *to_merge = NULL, **tail = &to_merge;
-	const char *strategy = !opts->xopts_nr &&
+	const char *strategy = !opts->xopts.nr &&
 		(!opts->strategy ||
 		 !strcmp(opts->strategy, "recursive") ||
 		 !strcmp(opts->strategy, "ort")) ?
@@ -3988,7 +3990,8 @@ static int do_merge(struct repository *r,
 
 	if (commit) {
 		const char *encoding = get_commit_output_encoding();
-		const char *message = logmsg_reencode(commit, NULL, encoding);
+		const char *message = repo_logmsg_reencode(r, commit, NULL,
+							   encoding);
 		const char *body;
 		int len;
 
@@ -4001,7 +4004,7 @@ static int do_merge(struct repository *r,
 		find_commit_subject(message, &body);
 		len = strlen(body);
 		ret = write_message(body, len, git_path_merge_msg(r), 0);
-		unuse_commit_buffer(commit, message);
+		repo_unuse_commit_buffer(r, commit, message);
 		if (ret) {
 			error_errno(_("could not write '%s'"),
 				    git_path_merge_msg(r));
@@ -4061,9 +4064,9 @@ static int do_merge(struct repository *r,
 			strvec_push(&cmd.args, "octopus");
 		else {
 			strvec_push(&cmd.args, strategy);
-			for (k = 0; k < opts->xopts_nr; k++)
+			for (k = 0; k < opts->xopts.nr; k++)
 				strvec_pushf(&cmd.args,
-					     "-X%s", opts->xopts[k]);
+					     "-X%s", opts->xopts.v[k]);
 		}
 		if (!(flags & TODO_EDIT_MERGE_MSG))
 			strvec_push(&cmd.args, "--no-edit");
@@ -4101,7 +4104,7 @@ static int do_merge(struct repository *r,
 	}
 
 	merge_commit = to_merge->item;
-	bases = get_merge_bases(head_commit, merge_commit);
+	bases = repo_get_merge_bases(r, head_commit, merge_commit);
 	if (bases && oideq(&merge_commit->object.oid,
 			   &bases->item->object.oid)) {
 		ret = 0;
@@ -4269,7 +4272,7 @@ void todo_list_filter_update_refs(struct repository *r,
 		if (!is_null_oid(&rec->after))
 			continue;
 
-		for (j = 0; !found && j < todo_list->total_nr; j++) {
+		for (j = 0; !found && j < todo_list->nr; j++) {
 			struct todo_item *item = &todo_list->items[j];
 			const char *arg = todo_list->buf.buf + item->arg_offset;
 
@@ -4299,7 +4302,7 @@ void todo_list_filter_update_refs(struct repository *r,
 	 * For each todo_item, check if its ref is in the update_refs list.
 	 * If not, then add it as an un-updated ref.
 	 */
-	for (i = 0; i < todo_list->total_nr; i++) {
+	for (i = 0; i < todo_list->nr; i++) {
 		struct todo_item *item = &todo_list->items[i];
 		const char *arg = todo_list->buf.buf + item->arg_offset;
 		int j, found = 0;
@@ -4456,7 +4459,7 @@ void create_autostash(struct repository *r, const char *path)
 		if (capture_command(&stash, &buf, GIT_MAX_HEXSZ))
 			die(_("Cannot autostash"));
 		strbuf_trim_trailing_newline(&buf);
-		if (get_oid(buf.buf, &oid))
+		if (repo_get_oid(r, buf.buf, &oid))
 			die(_("Unexpected stash response: '%s'"),
 			    buf.buf);
 		strbuf_reset(&buf);
@@ -4581,9 +4584,9 @@ static int stopped_at_head(struct repository *r)
 	struct commit *commit;
 	struct commit_message message;
 
-	if (get_oid("HEAD", &head) ||
+	if (repo_get_oid(r, "HEAD", &head) ||
 	    !(commit = lookup_commit(r, &head)) ||
-	    parse_commit(commit) || get_message(commit, &message))
+	    repo_parse_commit(r, commit) || get_message(commit, &message))
 		fprintf(stderr, _("Stopped at HEAD\n"));
 	else {
 		fprintf(stderr, _("Stopped at %s\n"), message.label);
@@ -4731,7 +4734,7 @@ static int pick_commits(struct repository *r,
 				 * otherwise we do not.
 				 */
 				if (item->command == TODO_REWORD &&
-				    !get_oid("HEAD", &oid) &&
+				    !repo_get_oid(r, "HEAD", &oid) &&
 				    (oideq(&item->commit->object.oid, &oid) ||
 				     (opts->have_squash_onto &&
 				      oideq(&opts->squash_onto, &oid))))
@@ -4820,7 +4823,7 @@ static int pick_commits(struct repository *r,
 			struct object_id head, orig;
 			int res;
 
-			if (get_oid("HEAD", &head)) {
+			if (repo_get_oid(r, "HEAD", &head)) {
 				res = error(_("cannot read HEAD"));
 cleanup_head_ref:
 				strbuf_release(&head_ref);
@@ -4867,8 +4870,8 @@ static int pick_commits(struct repository *r,
 			log_tree_opt.disable_stdin = 1;
 
 			if (read_oneliner(&buf, rebase_path_orig_head(), 0) &&
-			    !get_oid(buf.buf, &orig) &&
-			    !get_oid("HEAD", &head)) {
+			    !repo_get_oid(r, buf.buf, &orig) &&
+			    !repo_get_oid(r, "HEAD", &head)) {
 				diff_tree_oid(&orig, &head, "",
 					      &log_tree_opt.diffopt);
 				log_tree_diff_flush(&log_tree_opt);
@@ -4960,7 +4963,7 @@ static int commit_staged_changes(struct repository *r,
 		struct strbuf rev = STRBUF_INIT;
 		struct object_id head, to_amend;
 
-		if (get_oid("HEAD", &head))
+		if (repo_get_oid(r, "HEAD", &head))
 			return error(_("cannot amend non-existing commit"));
 		if (!read_oneliner(&rev, rebase_path_amend(), 0))
 			return error(_("invalid file: '%s'"), rebase_path_amend());
@@ -5040,13 +5043,14 @@ static int commit_staged_changes(struct repository *r,
 				const char *encoding = get_commit_output_encoding();
 
 				if (parse_head(r, &commit) ||
-				    !(p = logmsg_reencode(commit, NULL, encoding)) ||
+				    !(p = repo_logmsg_reencode(r, commit, NULL, encoding)) ||
 				    write_message(p, strlen(p), path, 0)) {
-					unuse_commit_buffer(commit, p);
+					repo_unuse_commit_buffer(r, commit, p);
 					return error(_("could not write file: "
 						       "'%s'"), path);
 				}
-				unuse_commit_buffer(commit, p);
+				repo_unuse_commit_buffer(r,
+							 commit, p);
 			}
 		}
 
@@ -5185,7 +5189,7 @@ int sequencer_pick_revisions(struct repository *r,
 		if (!strlen(name))
 			continue;
 
-		if (!get_oid(name, &oid)) {
+		if (!repo_get_oid(r, name, &oid)) {
 			if (!lookup_commit_reference_gently(r, &oid, 1)) {
 				enum object_type type = oid_object_info(r,
 									&oid,
@@ -5228,7 +5232,7 @@ int sequencer_pick_revisions(struct repository *r,
 	if (walk_revs_populate_todo(&todo_list, opts) ||
 			create_seq_dir(r) < 0)
 		return -1;
-	if (get_oid("HEAD", &oid) && (opts->action == REPLAY_REVERT))
+	if (repo_get_oid(r, "HEAD", &oid) && (opts->action == REPLAY_REVERT))
 		return error(_("can't revert as initial commit"));
 	if (save_head(oid_to_hex(&oid)))
 		return -1;
@@ -5344,7 +5348,7 @@ static const char *label_oid(struct object_id *oid, const char *label,
 	 * For "uninteresting" commits, i.e. commits that are not to be
 	 * rebased, and which can therefore not be labeled, we use a unique
 	 * abbreviation of the commit name. This is slightly more complicated
-	 * than calling find_unique_abbrev() because we also need to make
+	 * than calling repo_find_unique_abbrev() because we also need to make
 	 * sure that the abbreviation does not conflict with any other
 	 * label.
 	 *
@@ -5360,7 +5364,8 @@ static const char *label_oid(struct object_id *oid, const char *label,
 		strbuf_grow(&state->buf, GIT_MAX_HEXSZ);
 		label = p = state->buf.buf;
 
-		find_unique_abbrev_r(p, oid, default_abbrev);
+		repo_find_unique_abbrev_r(the_repository, p, oid,
+					  default_abbrev);
 
 		/*
 		 * We may need to extend the abbreviated hash so that there is
@@ -5922,7 +5927,7 @@ static int skip_unnecessary_picks(struct repository *r,
 			continue;
 		if (item->command != TODO_PICK)
 			break;
-		if (parse_commit(item->commit)) {
+		if (repo_parse_commit(r, item->commit)) {
 			return error(_("could not parse commit '%s'"),
 				oid_to_hex(&item->commit->object.oid));
 		}
@@ -6093,7 +6098,8 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
 	struct object_id oid = onto->object.oid;
 	int res;
 
-	find_unique_abbrev_r(shortonto, &oid, DEFAULT_ABBREV);
+	repo_find_unique_abbrev_r(r, shortonto, &oid,
+				  DEFAULT_ABBREV);
 
 	if (buf->len == 0) {
 		struct todo_item *item = append_new_todo(todo_list);
@@ -6144,7 +6150,8 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
 	todo_list_to_strbuf(r, &new_todo, &buf2, -1, 0);
 	strbuf_swap(&new_todo.buf, &buf2);
 	strbuf_release(&buf2);
-	new_todo.total_nr -= new_todo.nr;
+	/* Nothing is done yet, and we're reparsing, so let's reset the count */
+	new_todo.total_nr = 0;
 	if (todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo) < 0)
 		BUG("invalid todo list after expanding IDs:\n%s",
 		    new_todo.buf.buf);
@@ -6254,12 +6261,15 @@ int todo_list_rearrange_squash(struct todo_list *todo_list)
 			return error(_("the script was already rearranged."));
 		}
 
-		parse_commit(item->commit);
-		commit_buffer = logmsg_reencode(item->commit, NULL, "UTF-8");
+		repo_parse_commit(the_repository, item->commit);
+		commit_buffer = repo_logmsg_reencode(the_repository,
+						     item->commit, NULL,
+						     "UTF-8");
 		find_commit_subject(commit_buffer, &subject);
 		format_subject(&buf, subject, " ");
 		subject = subjects[i] = strbuf_detach(&buf, &subject_len);
-		unuse_commit_buffer(item->commit, commit_buffer);
+		repo_unuse_commit_buffer(the_repository, item->commit,
+					 commit_buffer);
 		if (skip_fixupish(subject, &p)) {
 			struct commit *commit2;
 
@@ -6369,8 +6379,8 @@ int sequencer_determine_whence(struct repository *r, enum commit_whence *whence)
 		if (file_exists(git_path_seq_dir()))
 			*whence = FROM_CHERRY_PICK_MULTI;
 		if (file_exists(rebase_path()) &&
-		    !get_oid("REBASE_HEAD", &rebase_head) &&
-		    !get_oid("CHERRY_PICK_HEAD", &cherry_pick_head) &&
+		    !repo_get_oid(r, "REBASE_HEAD", &rebase_head) &&
+		    !repo_get_oid(r, "CHERRY_PICK_HEAD", &cherry_pick_head) &&
 		    oideq(&rebase_head, &cherry_pick_head))
 			*whence = FROM_REBASE_PICK;
 		else
diff --git a/sequencer.h b/sequencer.h
index 3bcdfa1..913a0f6 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -1,11 +1,12 @@
 #ifndef SEQUENCER_H
 #define SEQUENCER_H
 
-#include "cache.h"
 #include "strbuf.h"
+#include "strvec.h"
 #include "wt-status.h"
 
 struct commit;
+struct index_state;
 struct repository;
 
 const char *git_path_commit_editmsg(void);
@@ -60,8 +61,7 @@ struct replay_opts {
 	/* Merge strategy */
 	char *default_strategy;  /* from config options */
 	char *strategy;
-	char **xopts;
-	size_t xopts_nr, xopts_alloc;
+	struct strvec xopts;
 
 	/* Reflog */
 	char *reflog_action;
@@ -80,7 +80,12 @@ struct replay_opts {
 	/* Private use */
 	const char *reflog_message;
 };
-#define REPLAY_OPTS_INIT { .edit = -1, .action = -1, .current_fixups = STRBUF_INIT }
+#define REPLAY_OPTS_INIT {			\
+	.edit = -1,				\
+	.action = -1,				\
+	.current_fixups = STRBUF_INIT,		\
+	.xopts = STRVEC_INIT,			\
+}
 
 /*
  * Note that ordering matters in this enum. Not only must it match the mapping
@@ -247,7 +252,6 @@ int read_oneliner(struct strbuf *buf,
 	const char *path, unsigned flags);
 int read_author_script(const char *path, char **name, char **email, char **date,
 		       int allow_missing);
-void parse_strategy_opts(struct replay_opts *opts, char *raw_opts);
 int write_basic_state(struct replay_opts *opts, const char *head_name,
 		      struct commit *onto, const struct object_id *orig_head);
 void sequencer_post_commit_cleanup(struct repository *r, int verbose);
diff --git a/serve.c b/serve.c
index cbf4a14..5329c91 100644
--- a/serve.c
+++ b/serve.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "repository.h"
 #include "config.h"
 #include "pkt-line.h"
@@ -8,17 +8,18 @@
 #include "serve.h"
 #include "upload-pack.h"
 #include "bundle-uri.h"
+#include "trace2.h"
 
 static int advertise_sid = -1;
 static int client_hash_algo = GIT_HASH_SHA1;
 
-static int always_advertise(struct repository *r,
-			    struct strbuf *value)
+static int always_advertise(struct repository *r UNUSED,
+			    struct strbuf *value UNUSED)
 {
 	return 1;
 }
 
-static int agent_advertise(struct repository *r,
+static int agent_advertise(struct repository *r UNUSED,
 			   struct strbuf *value)
 {
 	if (value)
@@ -34,7 +35,7 @@ static int object_format_advertise(struct repository *r,
 	return 1;
 }
 
-static void object_format_receive(struct repository *r,
+static void object_format_receive(struct repository *r UNUSED,
 				  const char *algo_name)
 {
 	if (!algo_name)
@@ -48,7 +49,7 @@ static void object_format_receive(struct repository *r,
 static int session_id_advertise(struct repository *r, struct strbuf *value)
 {
 	if (advertise_sid == -1 &&
-	    git_config_get_bool("transfer.advertisesid", &advertise_sid))
+	    repo_config_get_bool(r, "transfer.advertisesid", &advertise_sid))
 		advertise_sid = 0;
 	if (!advertise_sid)
 		return 0;
@@ -57,7 +58,7 @@ static int session_id_advertise(struct repository *r, struct strbuf *value)
 	return 1;
 }
 
-static void session_id_receive(struct repository *r,
+static void session_id_receive(struct repository *r UNUSED,
 			       const char *client_sid)
 {
 	if (!client_sid)
diff --git a/server-info.c b/server-info.c
index 0ec6c0c..55aa04f 100644
--- a/server-info.c
+++ b/server-info.c
@@ -1,13 +1,19 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "dir.h"
+#include "environment.h"
+#include "hex.h"
 #include "repository.h"
 #include "refs.h"
 #include "object.h"
 #include "commit.h"
 #include "tag.h"
 #include "packfile.h"
+#include "object-file.h"
 #include "object-store.h"
+#include "server-info.h"
 #include "strbuf.h"
+#include "wrapper.h"
 
 struct update_info_ctx {
 	FILE *cur_fp;
diff --git a/server-info.h b/server-info.h
new file mode 100644
index 0000000..13bbde2
--- /dev/null
+++ b/server-info.h
@@ -0,0 +1,7 @@
+#ifndef SERVER_INFO_H
+#define SERVER_INFO_H
+
+/* Dumb servers support */
+int update_server_info(int);
+
+#endif /* SERVER_INFO_H */
diff --git a/setup.c b/setup.c
index cefd5f6..4585822 100644
--- a/setup.c
+++ b/setup.c
@@ -1,11 +1,18 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "environment.h"
+#include "gettext.h"
+#include "object-name.h"
 #include "repository.h"
 #include "config.h"
 #include "dir.h"
+#include "setup.h"
 #include "string-list.h"
 #include "chdir-notify.h"
 #include "promisor-remote.h"
 #include "quote.h"
+#include "trace2.h"
+#include "wrapper.h"
 
 static int inside_git_dir = -1;
 static int inside_work_tree = -1;
@@ -1345,6 +1352,7 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
 		}
 
 		if (is_git_directory(dir->buf)) {
+			trace2_data_string("setup", NULL, "implicit-bare-repository", dir->buf);
 			if (get_allowed_bare_repo() == ALLOWED_BARE_REPO_EXPLICIT)
 				return GIT_DIR_DISALLOWED_BARE;
 			if (!ensure_valid_ownership(NULL, NULL, dir->buf, report))
diff --git a/setup.h b/setup.h
new file mode 100644
index 0000000..4c1ca9d
--- /dev/null
+++ b/setup.h
@@ -0,0 +1,168 @@
+#ifndef SETUP_H
+#define SETUP_H
+
+#include "string-list.h"
+
+int is_inside_git_dir(void);
+int is_inside_work_tree(void);
+int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
+int get_common_dir(struct strbuf *sb, const char *gitdir);
+
+/*
+ * Return true if the given path is a git directory; note that this _just_
+ * looks at the directory itself. If you want to know whether "foo/.git"
+ * is a repository, you must feed that path, not just "foo".
+ */
+int is_git_directory(const char *path);
+
+/*
+ * Return 1 if the given path is the root of a git repository or
+ * submodule, else 0. Will not return 1 for bare repositories with the
+ * exception of creating a bare repository in "foo/.git" and calling
+ * is_git_repository("foo").
+ *
+ * If we run into read errors, we err on the side of saying "yes, it is",
+ * as we usually consider sub-repos precious, and would prefer to err on the
+ * side of not disrupting or deleting them.
+ */
+int is_nonbare_repository_dir(struct strbuf *path);
+
+#define READ_GITFILE_ERR_STAT_FAILED 1
+#define READ_GITFILE_ERR_NOT_A_FILE 2
+#define READ_GITFILE_ERR_OPEN_FAILED 3
+#define READ_GITFILE_ERR_READ_FAILED 4
+#define READ_GITFILE_ERR_INVALID_FORMAT 5
+#define READ_GITFILE_ERR_NO_PATH 6
+#define READ_GITFILE_ERR_NOT_A_REPO 7
+#define READ_GITFILE_ERR_TOO_LARGE 8
+void read_gitfile_error_die(int error_code, const char *path, const char *dir);
+const char *read_gitfile_gently(const char *path, int *return_error_code);
+#define read_gitfile(path) read_gitfile_gently((path), NULL)
+const char *resolve_gitdir_gently(const char *suspect, int *return_error_code);
+#define resolve_gitdir(path) resolve_gitdir_gently((path), NULL)
+
+void setup_work_tree(void);
+/*
+ * Find the commondir and gitdir of the repository that contains the current
+ * working directory, without changing the working directory or other global
+ * state. The result is appended to commondir and gitdir.  If the discovered
+ * gitdir does not correspond to a worktree, then 'commondir' and 'gitdir' will
+ * both have the same result appended to the buffer.  The return value is
+ * either 0 upon success and non-zero if no repository was found.
+ */
+int discover_git_directory(struct strbuf *commondir,
+			   struct strbuf *gitdir);
+const char *setup_git_directory_gently(int *);
+const char *setup_git_directory(void);
+char *prefix_path(const char *prefix, int len, const char *path);
+char *prefix_path_gently(const char *prefix, int len, int *remaining, const char *path);
+
+int check_filename(const char *prefix, const char *name);
+void verify_filename(const char *prefix,
+		     const char *name,
+		     int diagnose_misspelt_rev);
+void verify_non_filename(const char *prefix, const char *name);
+int path_inside_repo(const char *prefix, const char *path);
+
+void sanitize_stdfds(void);
+int daemonize(void);
+
+/*
+ * GIT_REPO_VERSION is the version we write by default. The
+ * _READ variant is the highest number we know how to
+ * handle.
+ */
+#define GIT_REPO_VERSION 0
+#define GIT_REPO_VERSION_READ 1
+
+/*
+ * You _have_ to initialize a `struct repository_format` using
+ * `= REPOSITORY_FORMAT_INIT` before calling `read_repository_format()`.
+ */
+struct repository_format {
+	int version;
+	int precious_objects;
+	char *partial_clone; /* value of extensions.partialclone */
+	int worktree_config;
+	int is_bare;
+	int hash_algo;
+	int sparse_index;
+	char *work_tree;
+	struct string_list unknown_extensions;
+	struct string_list v1_only_extensions;
+};
+
+/*
+ * Always use this to initialize a `struct repository_format`
+ * to a well-defined, default state before calling
+ * `read_repository()`.
+ */
+#define REPOSITORY_FORMAT_INIT \
+{ \
+	.version = -1, \
+	.is_bare = -1, \
+	.hash_algo = GIT_HASH_SHA1, \
+	.unknown_extensions = STRING_LIST_INIT_DUP, \
+	.v1_only_extensions = STRING_LIST_INIT_DUP, \
+}
+
+/*
+ * Read the repository format characteristics from the config file "path" into
+ * "format" struct. Returns the numeric version. On error, or if no version is
+ * found in the configuration, -1 is returned, format->version is set to -1,
+ * and all other fields in the struct are set to the default configuration
+ * (REPOSITORY_FORMAT_INIT). Always initialize the struct using
+ * REPOSITORY_FORMAT_INIT before calling this function.
+ */
+int read_repository_format(struct repository_format *format, const char *path);
+
+/*
+ * Free the memory held onto by `format`, but not the struct itself.
+ * (No need to use this after `read_repository_format()` fails.)
+ */
+void clear_repository_format(struct repository_format *format);
+
+/*
+ * Verify that the repository described by repository_format is something we
+ * can read. If it is, return 0. Otherwise, return -1, and "err" will describe
+ * any errors encountered.
+ */
+int verify_repository_format(const struct repository_format *format,
+			     struct strbuf *err);
+
+/*
+ * Check the repository format version in the path found in get_git_dir(),
+ * and die if it is a version we don't understand. Generally one would
+ * set_git_dir() before calling this, and use it only for "are we in a valid
+ * repo?".
+ *
+ * If successful and fmt is not NULL, fill fmt with data.
+ */
+void check_repository_format(struct repository_format *fmt);
+
+/*
+ * NOTE NOTE NOTE!!
+ *
+ * PERM_UMASK, OLD_PERM_GROUP and OLD_PERM_EVERYBODY enumerations must
+ * not be changed. Old repositories have core.sharedrepository written in
+ * numeric format, and therefore these values are preserved for compatibility
+ * reasons.
+ */
+enum sharedrepo {
+	PERM_UMASK          = 0,
+	OLD_PERM_GROUP      = 1,
+	OLD_PERM_EVERYBODY  = 2,
+	PERM_GROUP          = 0660,
+	PERM_EVERYBODY      = 0664
+};
+int git_config_perm(const char *var, const char *value);
+
+struct startup_info {
+	int have_repository;
+	const char *prefix;
+	const char *original_cwd;
+};
+extern struct startup_info *startup_info;
+extern const char *tmp_original_cwd;
+
+#endif /* SETUP_H */
diff --git a/sha1dc_git.c b/sha1dc_git.c
index 5c300e8..9b675a0 100644
--- a/sha1dc_git.c
+++ b/sha1dc_git.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "sha1dc_git.h"
+#include "hex.h"
 
 #ifdef DC_SHA1_EXTERNAL
 /*
diff --git a/shallow.c b/shallow.c
index 17f9bcd..128f561 100644
--- a/shallow.c
+++ b/shallow.c
@@ -1,4 +1,6 @@
 #include "cache.h"
+#include "alloc.h"
+#include "hex.h"
 #include "repository.h"
 #include "tempfile.h"
 #include "lockfile.h"
@@ -15,6 +17,8 @@
 #include "list-objects.h"
 #include "commit-reach.h"
 #include "shallow.h"
+#include "trace.h"
+#include "wrapper.h"
 
 void set_alternate_shallow_file(struct repository *r, const char *path, int override)
 {
@@ -30,7 +34,7 @@ int register_shallow(struct repository *r, const struct object_id *oid)
 {
 	struct commit_graft *graft =
 		xmalloc(sizeof(struct commit_graft));
-	struct commit *commit = lookup_commit(the_repository, oid);
+	struct commit *commit = lookup_commit(r, oid);
 
 	oidcpy(&graft->oid, oid);
 	graft->nr_parent = -1;
@@ -247,7 +251,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,
 		struct commit *c = p->item;
 		struct commit_list *parent;
 
-		if (parse_commit(c))
+		if (repo_parse_commit(the_repository, c))
 			die("unable to parse commit %s",
 			    oid_to_hex(&c->object.oid));
 
@@ -301,7 +305,7 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
 	if (graft->nr_parent != -1)
 		return 0;
 	if (data->flags & QUICK) {
-		if (!has_object_file(&graft->oid))
+		if (!repo_has_object_file(the_repository, &graft->oid))
 			return 0;
 	} else if (data->flags & SEEN_ONLY) {
 		struct commit *c = lookup_commit(the_repository, &graft->oid);
@@ -466,7 +470,7 @@ void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa)
 	ALLOC_ARRAY(info->ours, sa->nr);
 	ALLOC_ARRAY(info->theirs, sa->nr);
 	for (i = 0; i < sa->nr; i++) {
-		if (has_object_file(sa->oid + i)) {
+		if (repo_has_object_file(the_repository, sa->oid + i)) {
 			struct commit_graft *graft;
 			graft = lookup_commit_graft(the_repository,
 						    &sa->oid[i]);
@@ -494,7 +498,7 @@ void remove_nonexistent_theirs_shallow(struct shallow_info *info)
 	for (i = dst = 0; i < info->nr_theirs; i++) {
 		if (i != dst)
 			info->theirs[dst] = info->theirs[i];
-		if (has_object_file(oid + info->theirs[i]))
+		if (repo_has_object_file(the_repository, oid + info->theirs[i]))
 			dst++;
 	}
 	info->nr_theirs = dst;
@@ -583,7 +587,7 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,
 		if (c->object.flags & BOTTOM)
 			continue;
 
-		if (parse_commit(c))
+		if (repo_parse_commit(the_repository, c))
 			die("unable to parse commit %s",
 			    oid_to_hex(&c->object.oid));
 
@@ -791,7 +795,7 @@ static void post_assign_shallow(struct shallow_info *info,
 		for (j = 0; j < bitmap_nr; j++)
 			if (bitmap[0][j] &&
 			    /* Step 7, reachability test at commit level */
-			    !in_merge_bases_many(c, ca.nr, ca.commits)) {
+			    !repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits)) {
 				update_refstatus(ref_status, info->ref->nr, *bitmap);
 				dst++;
 				break;
@@ -819,9 +823,10 @@ int delayed_reachability_test(struct shallow_info *si, int c)
 			si->nr_commits = ca.nr;
 		}
 
-		si->reachable[c] = in_merge_bases_many(commit,
-						       si->nr_commits,
-						       si->commits);
+		si->reachable[c] = repo_in_merge_bases_many(the_repository,
+							    commit,
+							    si->nr_commits,
+							    si->commits);
 		si->need_reachability_test[c] = 0;
 	}
 	return si->reachable[c];
diff --git a/shallow.h b/shallow.h
index aba6ff5..e9ca7e4 100644
--- a/shallow.h
+++ b/shallow.h
@@ -6,6 +6,8 @@
 #include "repository.h"
 #include "strbuf.h"
 
+struct oid_array;
+
 void set_alternate_shallow_file(struct repository *r, const char *path, int override);
 int register_shallow(struct repository *r, const struct object_id *oid);
 int unregister_shallow(const struct object_id *oid);
diff --git a/shell.c b/shell.c
index af0d7c7..5c67e7b 100644
--- a/shell.c
+++ b/shell.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "quote.h"
 #include "exec-cmd.h"
 #include "strbuf.h"
diff --git a/sideband.c b/sideband.c
index 85bddfd..6cbfd39 100644
--- a/sideband.c
+++ b/sideband.c
@@ -1,9 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "color.h"
 #include "config.h"
+#include "editor.h"
+#include "gettext.h"
 #include "sideband.h"
 #include "help.h"
 #include "pkt-line.h"
+#include "write-or-die.h"
 
 struct keyword_entry {
 	/*
diff --git a/sigchain.c b/sigchain.c
index 022677b..ee778c0 100644
--- a/sigchain.c
+++ b/sigchain.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "sigchain.h"
 
 #define SIGCHAIN_MAX_SIGNALS 32
diff --git a/sparse-index.c b/sparse-index.c
index 147a133..8860547 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -1,4 +1,7 @@
 #include "cache.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
 #include "repository.h"
 #include "sparse-index.h"
 #include "tree.h"
diff --git a/split-index.c b/split-index.c
index 5d0f047..40e5476 100644
--- a/split-index.c
+++ b/split-index.c
@@ -1,5 +1,10 @@
 #include "cache.h"
+#include "alloc.h"
+#include "gettext.h"
+#include "hash.h"
+#include "mem-pool.h"
 #include "split-index.h"
+#include "strbuf.h"
 #include "ewah/ewok.h"
 
 struct split_index *init_split_index(struct index_state *istate)
diff --git a/split-index.h b/split-index.h
index 7a435ca..15a29cd 100644
--- a/split-index.h
+++ b/split-index.h
@@ -1,7 +1,7 @@
 #ifndef SPLIT_INDEX_H
 #define SPLIT_INDEX_H
 
-#include "cache.h"
+#include "hash-ll.h"
 
 struct index_state;
 struct strbuf;
diff --git a/statinfo.h b/statinfo.h
new file mode 100644
index 0000000..e49e305
--- /dev/null
+++ b/statinfo.h
@@ -0,0 +1,24 @@
+#ifndef STATINFO_H
+#define STATINFO_H
+
+/*
+ * The "cache_time" is just the low 32 bits of the
+ * time. It doesn't matter if it overflows - we only
+ * check it for equality in the 32 bits we save.
+ */
+struct cache_time {
+	uint32_t sec;
+	uint32_t nsec;
+};
+
+struct stat_data {
+	struct cache_time sd_ctime;
+	struct cache_time sd_mtime;
+	unsigned int sd_dev;
+	unsigned int sd_ino;
+	unsigned int sd_uid;
+	unsigned int sd_gid;
+	unsigned int sd_size;
+};
+
+#endif
diff --git a/strbuf.c b/strbuf.c
index c383f41..08eec8f 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -1,8 +1,16 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "refs.h"
+#include "repository.h"
 #include "string-list.h"
 #include "utf8.h"
 #include "date.h"
+#include "wrapper.h"
 
 int starts_with(const char *str, const char *prefix)
 {
@@ -1173,34 +1181,6 @@ int strbuf_normalize_path(struct strbuf *src)
 	return 0;
 }
 
-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
-			      const char *const *env)
-{
-	char *path2 = NULL;
-	int fd, res = 0;
-
-	if (!is_absolute_path(path))
-		path = path2 = xstrdup(git_path("%s", path));
-
-	fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
-	if (fd < 0)
-		res = error_errno(_("could not open '%s' for writing"), path);
-	else if (write_in_full(fd, buffer->buf, buffer->len) < 0) {
-		res = error_errno(_("could not write to '%s'"), path);
-		close(fd);
-	} else if (close(fd) < 0)
-		res = error_errno(_("could not close '%s'"), path);
-	else {
-		strbuf_reset(buffer);
-		if (launch_editor(path, buffer, env) < 0)
-			res = error_errno(_("could not edit '%s'"), path);
-		unlink(path);
-	}
-
-	free(path2);
-	return res;
-}
-
 void strbuf_strip_file_from_path(struct strbuf *sb)
 {
 	char *path_sep = find_last_dir_sep(sb->buf);
diff --git a/strbuf.h b/strbuf.h
index f6dbb96..3dfeadb 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -631,7 +631,7 @@ void strbuf_add_separated_string_list(struct strbuf *str,
 void strbuf_list_free(struct strbuf **list);
 
 /**
- * Add the abbreviation, as generated by find_unique_abbrev, of `sha1` to
+ * Add the abbreviation, as generated by repo_find_unique_abbrev(), of `sha1` to
  * the strbuf `sb`.
  */
 struct repository;
@@ -640,30 +640,6 @@ void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo,
 void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
 			      int abbrev_len);
 
-/**
- * Launch the user preferred editor to edit a file and fill the buffer
- * with the file's contents upon the user completing their editing. The
- * third argument can be used to set the environment which the editor is
- * run in. If the buffer is NULL the editor is launched as usual but the
- * file's contents are not read into the buffer upon completion.
- */
-int launch_editor(const char *path, struct strbuf *buffer,
-		  const char *const *env);
-
-int launch_sequence_editor(const char *path, struct strbuf *buffer,
-			   const char *const *env);
-
-/*
- * In contrast to `launch_editor()`, this function writes out the contents
- * of the specified file first, then clears the `buffer`, then launches
- * the editor and reads back in the file contents into the `buffer`.
- * Finally, it deletes the temporary file.
- *
- * If `path` is relative, it refers to a file in the `.git` directory.
- */
-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
-			      const char *const *env);
-
 /*
  * Remove the filename from the provided path string. If the path
  * contains a trailing separator, then the path is considered a directory
@@ -706,14 +682,14 @@ static inline void strbuf_complete_line(struct strbuf *sb)
 
 /*
  * Copy "name" to "sb", expanding any special @-marks as handled by
- * interpret_branch_name(). The result is a non-qualified branch name
+ * repo_interpret_branch_name(). The result is a non-qualified branch name
  * (so "foo" or "origin/master" instead of "refs/heads/foo" or
  * "refs/remotes/origin/master").
  *
  * Note that the resulting name may not be a syntactically valid refname.
  *
  * If "allowed" is non-zero, restrict the set of allowed expansions. See
- * interpret_branch_name() for details.
+ * repo_interpret_branch_name() for details.
  */
 void strbuf_branchname(struct strbuf *sb, const char *name,
 		       unsigned allowed);
diff --git a/streaming.c b/streaming.c
index 27841dc..21e3958 100644
--- a/streaming.c
+++ b/streaming.c
@@ -1,12 +1,16 @@
 /*
  * Copyright (c) 2011, Google Inc.
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "convert.h"
+#include "environment.h"
 #include "streaming.h"
 #include "repository.h"
+#include "object-file.h"
 #include "object-store.h"
 #include "replace-object.h"
 #include "packfile.h"
+#include "wrapper.h"
 
 typedef int (*open_istream_fn)(struct git_istream *,
 			       struct repository *,
diff --git a/streaming.h b/streaming.h
index 5e4e6ac..bd27f59 100644
--- a/streaming.h
+++ b/streaming.h
@@ -3,10 +3,12 @@
  */
 #ifndef STREAMING_H
 #define STREAMING_H 1
-#include "cache.h"
+
+#include "object.h"
 
 /* opaque */
 struct git_istream;
+struct stream_filter;
 
 struct git_istream *open_istream(struct repository *, const struct object_id *,
 				 enum object_type *, unsigned long *,
diff --git a/string-list.c b/string-list.c
index 42bacae..0f8ac11 100644
--- a/string-list.c
+++ b/string-list.c
@@ -1,5 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "string-list.h"
+#include "alloc.h"
 
 void string_list_init_nodup(struct string_list *list)
 {
@@ -202,6 +203,15 @@ void string_list_clear_func(struct string_list *list, string_list_clear_func_t c
 	list->nr = list->alloc = 0;
 }
 
+void string_list_setlen(struct string_list *list, size_t nr)
+{
+	if (list->strdup_strings)
+		BUG("cannot setlen a string_list which owns its entries");
+	if (nr > list->nr)
+		BUG("cannot grow a string_list with setlen");
+	list->nr = nr;
+}
+
 struct string_list_item *string_list_append_nodup(struct string_list *list,
 						  char *string)
 {
@@ -300,7 +310,7 @@ int string_list_split(struct string_list *list, const char *string,
 }
 
 int string_list_split_in_place(struct string_list *list, char *string,
-			       int delim, int maxsplit)
+			       const char *delim, int maxsplit)
 {
 	int count = 0;
 	char *p = string, *end;
@@ -314,7 +324,7 @@ int string_list_split_in_place(struct string_list *list, char *string,
 			string_list_append(list, p);
 			return count;
 		}
-		end = strchr(p, delim);
+		end = strpbrk(p, delim);
 		if (end) {
 			*end = '\0';
 			string_list_append(list, p);
diff --git a/string-list.h b/string-list.h
index c7b0d5d..122b318 100644
--- a/string-list.h
+++ b/string-list.h
@@ -134,6 +134,16 @@ typedef void (*string_list_clear_func_t)(void *p, const char *str);
 /** Call a custom clear function on each util pointer */
 void string_list_clear_func(struct string_list *list, string_list_clear_func_t clearfunc);
 
+/*
+ * Set the length of a string_list to `nr`, provided that (a) `list`
+ * does not own its own storage, and (b) that `nr` is no larger than
+ * `list->nr`.
+ *
+ * Useful when "shrinking" `list` to write over existing entries that
+ * are no longer used without reallocating.
+ */
+void string_list_setlen(struct string_list *list, size_t nr);
+
 /**
  * Apply `func` to each item. If `func` returns nonzero, the
  * iteration aborts and the return value is propagated.
@@ -270,5 +280,5 @@ int string_list_split(struct string_list *list, const char *string,
  * list->strdup_strings must *not* be set.
  */
 int string_list_split_in_place(struct string_list *list, char *string,
-			       int delim, int maxsplit);
+			       const char *delim, int maxsplit);
 #endif /* STRING_LIST_H */
diff --git a/strvec.c b/strvec.c
index 61a76ce..17d54b6 100644
--- a/strvec.c
+++ b/strvec.c
@@ -1,5 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "strvec.h"
+#include "alloc.h"
+#include "hex.h"
 #include "strbuf.h"
 
 const char *empty_strvec[] = { NULL };
diff --git a/sub-process.c b/sub-process.c
index 6d42322..1daf5a9 100644
--- a/sub-process.c
+++ b/sub-process.c
@@ -1,6 +1,7 @@
 /*
  * Generic implementation of background process infrastructure.
  */
+#include "git-compat-util.h"
 #include "sub-process.h"
 #include "sigchain.h"
 #include "pkt-line.h"
diff --git a/sub-process.h b/sub-process.h
index e85f21f..6a61638 100644
--- a/sub-process.h
+++ b/sub-process.h
@@ -1,7 +1,6 @@
 #ifndef SUBPROCESS_H
 #define SUBPROCESS_H
 
-#include "git-compat-util.h"
 #include "hashmap.h"
 #include "run-command.h"
 
diff --git a/submodule-config.c b/submodule-config.c
index 4dc61b3..58dfbde 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -1,12 +1,18 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "repository.h"
 #include "config.h"
 #include "submodule-config.h"
 #include "submodule.h"
 #include "strbuf.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "parse-options.h"
+#include "thread-utils.h"
 #include "tree-walk.h"
 
 /*
@@ -535,7 +541,7 @@ static int gitmodule_oid_from_commit(const struct object_id *treeish_name,
 	}
 
 	strbuf_addf(rev, "%s:.gitmodules", oid_to_hex(treeish_name));
-	if (get_oid(rev->buf, gitmodules_oid) >= 0)
+	if (repo_get_oid(the_repository, rev->buf, gitmodules_oid) >= 0)
 		ret = 1;
 
 	return ret;
@@ -588,7 +594,8 @@ static const struct submodule *config_from(struct submodule_cache *cache,
 	if (submodule)
 		goto out;
 
-	config = read_object_file(&oid, &type, &config_size);
+	config = repo_read_object_file(the_repository, &oid, &type,
+				       &config_size);
 	if (!config || type != OBJ_BLOB)
 		goto out;
 
diff --git a/submodule-config.h b/submodule-config.h
index 28a8ca6..c204587 100644
--- a/submodule-config.h
+++ b/submodule-config.h
@@ -1,7 +1,6 @@
 #ifndef SUBMODULE_CONFIG_CACHE_H
 #define SUBMODULE_CONFIG_CACHE_H
 
-#include "cache.h"
 #include "config.h"
 #include "hashmap.h"
 #include "submodule.h"
diff --git a/submodule.c b/submodule.c
index 3a0dfc4..2e78f51 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1,5 +1,6 @@
-
 #include "cache.h"
+#include "abspath.h"
+#include "alloc.h"
 #include "repository.h"
 #include "config.h"
 #include "submodule-config.h"
@@ -7,6 +8,9 @@
 #include "dir.h"
 #include "diff.h"
 #include "commit.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "revision.h"
 #include "run-command.h"
 #include "diffcore.h"
@@ -20,9 +24,13 @@
 #include "remote.h"
 #include "worktree.h"
 #include "parse-options.h"
+#include "object-file.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "commit-reach.h"
+#include "setup.h"
 #include "shallow.h"
+#include "trace2.h"
 
 static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
 static int initialized_fetch_ref_tips;
@@ -65,7 +73,7 @@ int is_writing_gitmodules_ok(void)
 {
 	struct object_id oid;
 	return file_exists(GITMODULES_FILE) ||
-		(get_oid(GITMODULES_INDEX, &oid) < 0 && get_oid(GITMODULES_HEAD, &oid) < 0);
+		(repo_get_oid(the_repository, GITMODULES_INDEX, &oid) < 0 && repo_get_oid(the_repository, GITMODULES_HEAD, &oid) < 0);
 }
 
 /*
@@ -274,8 +282,7 @@ int is_tree_submodule_active(struct repository *repo,
 	free(key);
 
 	/* submodule.active is set */
-	sl = repo_config_get_value_multi(repo, "submodule.active");
-	if (sl) {
+	if (!repo_config_get_string_multi(repo, "submodule.active", &sl)) {
 		struct pathspec ps;
 		struct strvec args = STRVEC_INIT;
 		const struct string_list_item *item;
@@ -1625,7 +1632,7 @@ get_fetch_task_from_changed(struct submodule_parallel_fetch *spf,
 		if (!task->repo) {
 			strbuf_addf(err, _("Could not access submodule '%s' at commit %s\n"),
 				    cs_data->path,
-				    find_unique_abbrev(cs_data->super_oid, DEFAULT_ABBREV));
+				    repo_find_unique_abbrev(the_repository, cs_data->super_oid, DEFAULT_ABBREV));
 
 			fetch_task_release(task);
 			free(task);
@@ -1636,8 +1643,8 @@ get_fetch_task_from_changed(struct submodule_parallel_fetch *spf,
 			strbuf_addf(err,
 				    _("Fetching submodule %s%s at commit %s\n"),
 				    spf->prefix, task->sub->path,
-				    find_unique_abbrev(cs_data->super_oid,
-						       DEFAULT_ABBREV));
+				    repo_find_unique_abbrev(the_repository, cs_data->super_oid,
+							    DEFAULT_ABBREV));
 
 		spf->changed_count++;
 		/*
@@ -1739,7 +1746,7 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err,
 	return 0;
 }
 
-static int fetch_start_failure(struct strbuf *err,
+static int fetch_start_failure(struct strbuf *err UNUSED,
 			       void *cb, void *task_cb)
 {
 	struct submodule_parallel_fetch *spf = cb;
@@ -1760,7 +1767,7 @@ static int commit_missing_in_sub(const struct object_id *oid, void *data)
 	return type != OBJ_COMMIT;
 }
 
-static int fetch_finish(int retvalue, struct strbuf *err,
+static int fetch_finish(int retvalue, struct strbuf *err UNUSED,
 			void *cb, void *task_cb)
 {
 	struct submodule_parallel_fetch *spf = cb;
diff --git a/symlinks.c b/symlinks.c
index c667baa..b29e340 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -1,4 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
+#include "setup.h"
+#include "symlinks.h"
 
 static int threaded_check_leading_path(struct cache_def *cache, const char *name,
 				       int len, int warn_on_lstat_err);
diff --git a/symlinks.h b/symlinks.h
new file mode 100644
index 0000000..7ae3d5b
--- /dev/null
+++ b/symlinks.h
@@ -0,0 +1,28 @@
+#ifndef SYMLINKS_H
+#define SYMLINKS_H
+
+#include "strbuf.h"
+
+struct cache_def {
+	struct strbuf path;
+	int flags;
+	int track_flags;
+	int prefix_len_stat_func;
+};
+#define CACHE_DEF_INIT { \
+	.path = STRBUF_INIT, \
+}
+static inline void cache_def_clear(struct cache_def *cache)
+{
+	strbuf_release(&cache->path);
+}
+
+int has_symlink_leading_path(const char *name, int len);
+int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
+int check_leading_path(const char *name, int len, int warn_on_lstat_err);
+int has_dirs_only_path(const char *name, int len, int prefix_len);
+void invalidate_lstat_cache(void);
+void schedule_dir_for_removal(const char *name, int len);
+void remove_scheduled_dirs(void);
+
+#endif /* SYMLINKS_H */
diff --git a/t/Makefile b/t/Makefile
index 2c2b252..3e00cdd 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -44,8 +44,8 @@
 
 # `test-chainlint` (which is a dependency of `test-lint`, `test` and `prove`)
 # checks all tests in all scripts via a single invocation, so tell individual
-# scripts not to "chainlint" themselves
-CHAINLINTSUPPRESS = GIT_TEST_CHAIN_LINT=0 && export GIT_TEST_CHAIN_LINT &&
+# scripts not to run the external "chainlint.pl" script themselves
+CHAINLINTSUPPRESS = GIT_TEST_EXT_CHAIN_LINT=0 && export GIT_TEST_EXT_CHAIN_LINT &&
 
 all: $(DEFAULT_TEST_TARGET)
 
@@ -140,9 +140,7 @@
 	$(MAKE) clean
 
 aggregate-results:
-	for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \
-		echo "$$f"; \
-	done | '$(SHELL_PATH_SQ)' ./aggregate-results.sh
+	@'$(SHELL_PATH_SQ)' ./aggregate-results.sh '$(TEST_RESULTS_DIRECTORY_SQ)'
 
 valgrind:
 	$(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind"
diff --git a/t/README b/t/README
index 29576c3..bdfac4c 100644
--- a/t/README
+++ b/t/README
@@ -475,7 +475,7 @@
 use in the test scripts. Recognized values for <hash-algo> are "sha1"
 and "sha256".
 
-GIT_TEST_WRITE_REV_INDEX=<boolean>, when true enables the
+GIT_TEST_NO_WRITE_REV_INDEX=<boolean>, when true disables the
 'pack.writeReverseIndex' setting.
 
 GIT_TEST_SPARSE_INDEX=<boolean>, when true enables index writes to use the
diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh
index 7f2b83b..6e3bcc4 100755
--- a/t/aggregate-results.sh
+++ b/t/aggregate-results.sh
@@ -8,7 +8,7 @@
 total=0
 missing_prereq=
 
-while read file
+for file in "$1"/t*-*.counts
 do
 	while read type value
 	do
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index f1b9a6c..2ef7023 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -72,6 +72,23 @@
 	check_count A 2
 '
 
+test_expect_success 'blame working copy' '
+	test_when_finished "git restore file" &&
+	echo "1A quick brown fox jumps over the" >file &&
+	echo "another lazy dog" >>file &&
+	check_count A 1 "Not Committed Yet" 1
+'
+
+test_expect_success 'blame with --contents' '
+	check_count --contents=file A 2
+'
+
+test_expect_success 'blame with --contents changed' '
+	echo "1A quick brown fox jumps over the" >contents &&
+	echo "another lazy dog" >>contents &&
+	check_count --contents=contents A 1 "External file (--contents)" 1
+'
+
 test_expect_success 'blame in a bare repo without starting commit' '
 	git clone --bare . bare.git &&
 	(
@@ -98,6 +115,10 @@
 	check_count A 2 B 2
 '
 
+test_expect_success 'blame with --contents and revision' '
+	check_count -h testTag --contents=file A 2 "External file (--contents)" 2
+'
+
 test_expect_success 'setup B1 lines (branch1)' '
 	git checkout -b branch1 main &&
 	echo "3A slow green fox jumps into the" >>file &&
diff --git a/t/chainlint.pl b/t/chainlint.pl
index e966412..556ee91 100755
--- a/t/chainlint.pl
+++ b/t/chainlint.pl
@@ -80,7 +80,8 @@
 	return "<<$indented" unless $token;
 	my $tag = $token->[0];
 	$tag =~ s/['"\\]//g;
-	push(@{$self->{heretags}}, $indented ? "\t$tag" : "$tag");
+	$$token[0] = $indented ? "\t$tag" : "$tag";
+	push(@{$self->{heretags}}, $token);
 	return "<<$indented$tag";
 }
 
@@ -169,10 +170,18 @@
 	my $tags = $self->{heretags};
 	while (my $tag = shift @$tags) {
 		my $start = pos($$b);
-		my $indent = $tag =~ s/^\t// ? '\\s*' : '';
-		$$b =~ /(?:\G|\n)$indent\Q$tag\E(?:\n|\z)/gc;
+		my $indent = $$tag[0] =~ s/^\t// ? '\\s*' : '';
+		$$b =~ /(?:\G|\n)$indent\Q$$tag[0]\E(?:\n|\z)/gc;
+		if (pos($$b) > $start) {
+			my $body = substr($$b, $start, pos($$b) - $start);
+			$self->{lineno} += () = $body =~ /\n/sg;
+			next;
+		}
+		push(@{$self->{parser}->{problems}}, ['UNCLOSED-HEREDOC', $tag]);
+		$$b =~ /(?:\G|\n).*\z/gc; # consume rest of input
 		my $body = substr($$b, $start, pos($$b) - $start);
 		$self->{lineno} += () = $body =~ /\n/sg;
+		last;
 	}
 }
 
diff --git a/t/chainlint/unclosed-here-doc-indent.expect b/t/chainlint/unclosed-here-doc-indent.expect
new file mode 100644
index 0000000..7c30a1a
--- /dev/null
+++ b/t/chainlint/unclosed-here-doc-indent.expect
@@ -0,0 +1,4 @@
+command_which_is_run &&
+cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! &&
+we forget to end the here-doc
+command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc-indent.test b/t/chainlint/unclosed-here-doc-indent.test
new file mode 100644
index 0000000..5c841a9
--- /dev/null
+++ b/t/chainlint/unclosed-here-doc-indent.test
@@ -0,0 +1,4 @@
+command_which_is_run &&
+cat >expect <<-\EOF &&
+we forget to end the here-doc
+command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc.expect b/t/chainlint/unclosed-here-doc.expect
new file mode 100644
index 0000000..d65e50f
--- /dev/null
+++ b/t/chainlint/unclosed-here-doc.expect
@@ -0,0 +1,7 @@
+command_which_is_run &&
+cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! &&
+	we try to end the here-doc below,
+	but the indentation throws us off
+	since the operator is not "<<-".
+	EOF
+command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc.test b/t/chainlint/unclosed-here-doc.test
new file mode 100644
index 0000000..69d3786
--- /dev/null
+++ b/t/chainlint/unclosed-here-doc.test
@@ -0,0 +1,7 @@
+command_which_is_run &&
+cat >expect <<\EOF &&
+	we try to end the here-doc below,
+	but the indentation throws us off
+	since the operator is not "<<-".
+	EOF
+command_which_is_gobbled
diff --git a/t/helper/test-advise.c b/t/helper/test-advise.c
index cb88113..8a3fd00 100644
--- a/t/helper/test-advise.c
+++ b/t/helper/test-advise.c
@@ -1,7 +1,7 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "advice.h"
 #include "config.h"
+#include "setup.h"
 
 int cmd__advise_if_enabled(int argc, const char **argv)
 {
diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c
index ff35f59..af43ee1 100644
--- a/t/helper/test-bitmap.c
+++ b/t/helper/test-bitmap.c
@@ -1,6 +1,7 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "git-compat-util.h"
 #include "pack-bitmap.h"
+#include "setup.h"
 
 static int bitmap_list_commits(void)
 {
diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c
index 6c900ca..aabe31d 100644
--- a/t/helper/test-bloom.c
+++ b/t/helper/test-bloom.c
@@ -1,7 +1,9 @@
-#include "git-compat-util.h"
-#include "bloom.h"
 #include "test-tool.h"
+#include "bloom.h"
+#include "hex.h"
 #include "commit.h"
+#include "repository.h"
+#include "setup.h"
 
 static struct bloom_filter_settings settings = DEFAULT_BLOOM_FILTER_SETTINGS;
 
diff --git a/t/helper/test-bundle-uri.c b/t/helper/test-bundle-uri.c
index b18e760..4750585 100644
--- a/t/helper/test-bundle-uri.c
+++ b/t/helper/test-bundle-uri.c
@@ -1,6 +1,7 @@
 #include "test-tool.h"
 #include "parse-options.h"
 #include "bundle-uri.h"
+#include "gettext.h"
 #include "strbuf.h"
 #include "string-list.h"
 #include "transport.h"
diff --git a/t/helper/test-cache-tree.c b/t/helper/test-cache-tree.c
index 9159a17..9507b35 100644
--- a/t/helper/test-cache-tree.c
+++ b/t/helper/test-cache-tree.c
@@ -1,9 +1,13 @@
 #define USE_THE_INDEX_VARIABLE
 #include "test-tool.h"
 #include "cache.h"
+#include "gettext.h"
+#include "hex.h"
 #include "tree.h"
 #include "cache-tree.h"
 #include "parse-options.h"
+#include "repository.h"
+#include "setup.h"
 
 static char const * const test_cache_tree_usage[] = {
 	N_("test-tool cache-tree <options> (control|prime|update)"),
diff --git a/t/helper/test-chmtime.c b/t/helper/test-chmtime.c
index dc28890..0e55388 100644
--- a/t/helper/test-chmtime.c
+++ b/t/helper/test-chmtime.c
@@ -94,7 +94,7 @@ int cmd__chmtime(int argc, const char **argv)
 	if (timespec_arg(argv[i], &set_time, &set_eq)) {
 		++i;
 	} else {
-		if (get == 0) {
+		if (get == 0 && verbose == 0) {
 			fprintf(stderr, "Not a base-10 integer: %s\n", argv[i] + 1);
 			goto usage;
 		}
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 4ba9eb6..ad78fc1 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -1,6 +1,6 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "config.h"
+#include "setup.h"
 #include "string-list.h"
 
 /*
@@ -14,6 +14,8 @@
  * get_value_multi -> prints all values for the entered key in increasing order
  *		     of priority
  *
+ * get -> print return value for the entered key
+ *
  * get_int -> print integer value for the entered key or die
  *
  * get_bool -> print bool value for the entered key or die
@@ -30,6 +32,9 @@
  * iterate -> iterate over all values using git_config(), and print some
  *            data for each
  *
+ * git_config_int -> iterate over all values using git_config() and print the
+ *                   integer value for the entered key or die
+ *
  * Examples:
  *
  * To print the value with highest priority for key "foo.bAr Baz.rock":
@@ -54,6 +59,17 @@ static int iterate_cb(const char *var, const char *value, void *data UNUSED)
 	return 0;
 }
 
+static int parse_int_cb(const char *var, const char *value, void *data)
+{
+	const char *key_to_match = data;
+
+	if (!strcmp(key_to_match, var)) {
+		int parsed = git_config_int(value, value);
+		printf("%d\n", parsed);
+	}
+	return 0;
+}
+
 static int early_config_cb(const char *var, const char *value, void *vdata)
 {
 	const char *key = vdata;
@@ -95,8 +111,7 @@ int cmd__config(int argc, const char **argv)
 			goto exit1;
 		}
 	} else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
-		strptr = git_config_get_value_multi(argv[2]);
-		if (strptr) {
+		if (!git_config_get_value_multi(argv[2], &strptr)) {
 			for (i = 0; i < strptr->nr; i++) {
 				v = strptr->items[i].string;
 				if (!v)
@@ -109,6 +124,26 @@ int cmd__config(int argc, const char **argv)
 			printf("Value not found for \"%s\"\n", argv[2]);
 			goto exit1;
 		}
+	} else if (argc == 3 && !strcmp(argv[1], "get")) {
+		int ret;
+
+		if (!(ret = git_config_get(argv[2])))
+			goto exit0;
+		else if (ret == 1)
+			printf("Value not found for \"%s\"\n", argv[2]);
+		else if (ret == -CONFIG_INVALID_KEY)
+			printf("Key \"%s\" is invalid\n", argv[2]);
+		else if (ret == -CONFIG_NO_SECTION_OR_NAME)
+			printf("Key \"%s\" has no section\n", argv[2]);
+		else
+			/*
+			 * A normal caller should just check "ret <
+			 * 0", but for our own tests let's BUG() if
+			 * our whitelist of git_config_parse_key()
+			 * return values isn't exhaustive.
+			 */
+			BUG("Key \"%s\" has unknown return %d", argv[2], ret);
+		goto exit1;
 	} else if (argc == 3 && !strcmp(argv[1], "get_int")) {
 		if (!git_config_get_int(argv[2], &val)) {
 			printf("%d\n", val);
@@ -159,8 +194,7 @@ int cmd__config(int argc, const char **argv)
 				goto exit2;
 			}
 		}
-		strptr = git_configset_get_value_multi(&cs, argv[2]);
-		if (strptr) {
+		if (!git_configset_get_value_multi(&cs, argv[2], &strptr)) {
 			for (i = 0; i < strptr->nr; i++) {
 				v = strptr->items[i].string;
 				if (!v)
@@ -176,6 +210,9 @@ int cmd__config(int argc, const char **argv)
 	} else if (!strcmp(argv[1], "iterate")) {
 		git_config(iterate_cb, NULL);
 		goto exit0;
+	} else if (argc == 3 && !strcmp(argv[1], "git_config_int")) {
+		git_config(parse_int_cb, (void *) argv[2]);
+		goto exit0;
 	}
 
 	die("%s: Please check the syntax and the function name", argv[0]);
diff --git a/t/helper/test-crontab.c b/t/helper/test-crontab.c
index e6c1b1e..597027a 100644
--- a/t/helper/test-crontab.c
+++ b/t/helper/test-crontab.c
@@ -1,5 +1,4 @@
 #include "test-tool.h"
-#include "cache.h"
 
 /*
  * Usage: test-tool crontab <file> -l|<input>
diff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c
index b21bd67..e5659df 100644
--- a/t/helper/test-ctype.c
+++ b/t/helper/test-ctype.c
@@ -1,5 +1,4 @@
 #include "test-tool.h"
-#include "cache.h"
 
 static int rc;
 
@@ -28,6 +27,8 @@ static int is_in(const char *s, int ch)
 		if (is_in(s, i) != t(i))	\
 			report_error(#t, i);	\
 	}					\
+	if (t(EOF))				\
+		report_error(#t, EOF);		\
 }
 
 #define DIGIT "0123456789"
@@ -48,7 +49,7 @@ static int is_in(const char *s, int ch)
 	"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
 	"\x7f"
 
-int cmd__ctype(int argc, const char **argv)
+int cmd__ctype(int argc UNUSED, const char **argv UNUSED)
 {
 	TEST_CLASS(isdigit, DIGIT);
 	TEST_CLASS(isspace, " \n\r\t");
diff --git a/t/helper/test-date.c b/t/helper/test-date.c
index 45951b1..0683d46 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -1,6 +1,6 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "date.h"
+#include "trace.h"
 
 static const char *usage_msg = "\n"
 "  test-tool date relative [time_t]...\n"
@@ -81,7 +81,7 @@ static void parse_approxidate(const char **argv)
 {
 	for (; *argv; argv++) {
 		timestamp_t t;
-		t = approxidate_relative(*argv);
+		t = approxidate(*argv);
 		printf("%s -> %s\n", *argv, show_date(t, 0, DATE_MODE(ISO8601)));
 	}
 }
@@ -90,7 +90,7 @@ static void parse_approx_timestamp(const char **argv)
 {
 	for (; *argv; argv++) {
 		timestamp_t t;
-		t = approxidate_relative(*argv);
+		t = approxidate(*argv);
 		printf("%s -> %"PRItime"\n", *argv, t);
 	}
 }
@@ -104,7 +104,7 @@ static void getnanos(const char **argv)
 	printf("%lf\n", seconds);
 }
 
-int cmd__date(int argc, const char **argv)
+int cmd__date(int argc UNUSED, const char **argv)
 {
 	const char *x;
 
diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c
index b15481e..e7d134e 100644
--- a/t/helper/test-delta.c
+++ b/t/helper/test-delta.c
@@ -11,7 +11,7 @@
 #include "test-tool.h"
 #include "git-compat-util.h"
 #include "delta.h"
-#include "cache.h"
+#include "wrapper.h"
 
 static const char usage_str[] =
 	"test-tool delta (-d|-p) <from_file> <data_file> <out_file>";
diff --git a/t/helper/test-drop-caches.c b/t/helper/test-drop-caches.c
index e37396d..73e551c 100644
--- a/t/helper/test-drop-caches.c
+++ b/t/helper/test-drop-caches.c
@@ -155,7 +155,7 @@ static int cmd_dropcaches(void)
 
 #endif
 
-int cmd__drop_caches(int argc, const char **argv)
+int cmd__drop_caches(int argc UNUSED, const char **argv UNUSED)
 {
 	cmd_sync();
 	return cmd_dropcaches();
diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c
index 454f17b..f22f7bd 100644
--- a/t/helper/test-dump-cache-tree.c
+++ b/t/helper/test-dump-cache-tree.c
@@ -1,9 +1,12 @@
 #define USE_THE_INDEX_VARIABLE
 #include "test-tool.h"
 #include "cache.h"
+#include "hash.h"
+#include "hex.h"
 #include "tree.h"
 #include "cache-tree.h"
-
+#include "repository.h"
+#include "setup.h"
 
 static void dump_one(struct cache_tree *it, const char *pfx, const char *x)
 {
@@ -56,7 +59,7 @@ static int dump_cache_tree(struct cache_tree *it,
 	return errs;
 }
 
-int cmd__dump_cache_tree(int ac, const char **av)
+int cmd__dump_cache_tree(int ac UNUSED, const char **av UNUSED)
 {
 	struct index_state istate;
 	struct cache_tree *another = cache_tree();
diff --git a/t/helper/test-dump-fsmonitor.c b/t/helper/test-dump-fsmonitor.c
index 975f0ac..9a098a2 100644
--- a/t/helper/test-dump-fsmonitor.c
+++ b/t/helper/test-dump-fsmonitor.c
@@ -1,7 +1,9 @@
 #include "test-tool.h"
 #include "cache.h"
+#include "repository.h"
+#include "setup.h"
 
-int cmd__dump_fsmonitor(int ac, const char **av)
+int cmd__dump_fsmonitor(int ac UNUSED, const char **av UNUSED)
 {
 	struct index_state *istate = the_repository->index;
 	int i;
diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c
index 0ea97b8..d1badd7 100644
--- a/t/helper/test-dump-split-index.c
+++ b/t/helper/test-dump-split-index.c
@@ -1,6 +1,8 @@
 #define USE_THE_INDEX_VARIABLE
 #include "test-tool.h"
 #include "cache.h"
+#include "hex.h"
+#include "setup.h"
 #include "split-index.h"
 #include "ewah/ewok.h"
 
@@ -9,7 +11,7 @@ static void show_bit(size_t pos, void *data)
 	printf(" %d", (int)pos);
 }
 
-int cmd__dump_split_index(int ac, const char **av)
+int cmd__dump_split_index(int ac UNUSED, const char **av)
 {
 	struct split_index *si;
 	int i;
diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index 6d53683..df70be5 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -2,6 +2,9 @@
 #include "test-tool.h"
 #include "cache.h"
 #include "dir.h"
+#include "hex.h"
+#include "repository.h"
+#include "setup.h"
 
 static int compare_untracked(const void *a_, const void *b_)
 {
@@ -40,7 +43,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base)
 	strbuf_setlen(base, len);
 }
 
-int cmd__dump_untracked_cache(int ac, const char **av)
+int cmd__dump_untracked_cache(int ac UNUSED, const char **av UNUSED)
 {
 	struct untracked_cache *uc;
 	struct strbuf base = STRBUF_INIT;
diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c
index b9d1200..2ed910a 100644
--- a/t/helper/test-example-decorate.c
+++ b/t/helper/test-example-decorate.c
@@ -1,9 +1,10 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "git-compat-util.h"
 #include "object.h"
 #include "decorate.h"
+#include "repository.h"
 
-int cmd__example_decorate(int argc, const char **argv)
+int cmd__example_decorate(int argc UNUSED, const char **argv UNUSED)
 {
 	struct decoration n;
 	struct object_id one_oid = { {1} };
diff --git a/t/helper/test-fast-rebase.c b/t/helper/test-fast-rebase.c
index efc82dd..d1d63fe 100644
--- a/t/helper/test-fast-rebase.c
+++ b/t/helper/test-fast-rebase.c
@@ -12,20 +12,26 @@
 
 #define USE_THE_INDEX_VARIABLE
 #include "test-tool.h"
-
+#include "cache.h"
 #include "cache-tree.h"
 #include "commit.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "lockfile.h"
 #include "merge-ort.h"
+#include "object-name.h"
 #include "refs.h"
 #include "revision.h"
 #include "sequencer.h"
+#include "setup.h"
 #include "strvec.h"
 #include "tree.h"
 
 static const char *short_commit_name(struct commit *commit)
 {
-	return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV);
+	return repo_find_unique_abbrev(the_repository, &commit->object.oid,
+				       DEFAULT_ABBREV);
 }
 
 static struct commit *peel_committish(const char *name)
@@ -33,10 +39,11 @@ static struct commit *peel_committish(const char *name)
 	struct object *obj;
 	struct object_id oid;
 
-	if (get_oid(name, &oid))
+	if (repo_get_oid(the_repository, name, &oid))
 		return NULL;
 	obj = parse_object(the_repository, &oid);
-	return (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
+	return (struct commit *)repo_peel_to_type(the_repository, name, 0, obj,
+						  OBJ_COMMIT);
 }
 
 static char *get_author(const char *message)
@@ -63,7 +70,8 @@ static struct commit *create_commit(struct tree *tree,
 	struct commit_extra_header *extra;
 	struct strbuf msg = STRBUF_INIT;
 	const char *out_enc = get_commit_output_encoding();
-	const char *message = logmsg_reencode(based_on, NULL, out_enc);
+	const char *message = repo_logmsg_reencode(the_repository, based_on,
+						   NULL, out_enc);
 	const char *orig_message = NULL;
 	const char *exclude_gpgsig[] = { "gpgsig", NULL };
 
@@ -119,7 +127,7 @@ int cmd__fast_rebase(int argc, const char **argv)
 	strbuf_addf(&branch_name, "refs/heads/%s", argv[4]);
 
 	/* Sanity check */
-	if (get_oid("HEAD", &head))
+	if (repo_get_oid(the_repository, "HEAD", &head))
 		die(_("Cannot read HEAD"));
 	assert(oideq(&onto->object.oid, &head));
 
@@ -154,7 +162,7 @@ int cmd__fast_rebase(int argc, const char **argv)
 	memset(&result, 0, sizeof(result));
 	merge_opt.show_rename_progress = 1;
 	merge_opt.branch1 = "HEAD";
-	head_tree = get_commit_tree(onto);
+	head_tree = repo_get_commit_tree(the_repository, onto);
 	result.tree = head_tree;
 	last_commit = onto;
 	while ((commit = get_revision(&revs))) {
@@ -165,8 +173,8 @@ int cmd__fast_rebase(int argc, const char **argv)
 		assert(commit->parents && !commit->parents->next);
 		base = commit->parents->item;
 
-		next_tree = get_commit_tree(commit);
-		base_tree = get_commit_tree(base);
+		next_tree = repo_get_commit_tree(the_repository, commit);
+		base_tree = repo_get_commit_tree(the_repository, base);
 
 		merge_opt.branch2 = short_commit_name(commit);
 		merge_opt.ancestor = xstrfmt("parent of %s", merge_opt.branch2);
diff --git a/t/helper/test-fsmonitor-client.c b/t/helper/test-fsmonitor-client.c
index 54a4856..9f18c68 100644
--- a/t/helper/test-fsmonitor-client.c
+++ b/t/helper/test-fsmonitor-client.c
@@ -7,11 +7,14 @@
 #include "cache.h"
 #include "parse-options.h"
 #include "fsmonitor-ipc.h"
+#include "repository.h"
+#include "setup.h"
 #include "thread-utils.h"
 #include "trace2.h"
+#include "wrapper.h"
 
 #ifndef HAVE_FSMONITOR_DAEMON_BACKEND
-int cmd__fsmonitor_client(int argc, const char **argv)
+int cmd__fsmonitor_client(int argc UNUSED, const char **argv UNUSED)
 {
 	die("fsmonitor--daemon not available on this platform");
 }
diff --git a/t/helper/test-hash.c b/t/helper/test-hash.c
index 5860dab..45d829c 100644
--- a/t/helper/test-hash.c
+++ b/t/helper/test-hash.c
@@ -1,5 +1,5 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
 
 int cmd_hash_impl(int ac, const char **av, int algo)
 {
diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c
index 36ff07b..0eb0b3d 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -2,6 +2,7 @@
 #include "git-compat-util.h"
 #include "hashmap.h"
 #include "strbuf.h"
+#include "string-list.h"
 
 struct test_entry
 {
@@ -150,6 +151,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
  */
 int cmd__hashmap(int argc, const char **argv)
 {
+	struct string_list parts = STRING_LIST_INIT_NODUP;
 	struct strbuf line = STRBUF_INIT;
 	int icase;
 	struct hashmap map = HASHMAP_INIT(test_entry_cmp, &icase);
@@ -159,21 +161,26 @@ int cmd__hashmap(int argc, const char **argv)
 
 	/* process commands from stdin */
 	while (strbuf_getline(&line, stdin) != EOF) {
-		char *cmd, *p1 = NULL, *p2 = NULL;
+		char *cmd, *p1, *p2;
 		unsigned int hash = 0;
 		struct test_entry *entry;
 
 		/* break line into command and up to two parameters */
-		cmd = strtok(line.buf, DELIM);
+		string_list_setlen(&parts, 0);
+		string_list_split_in_place(&parts, line.buf, DELIM, 2);
+		string_list_remove_empty_items(&parts, 0);
+
 		/* ignore empty lines */
-		if (!cmd || *cmd == '#')
+		if (!parts.nr)
+			continue;
+		if (!*parts.items[0].string || *parts.items[0].string == '#')
 			continue;
 
-		p1 = strtok(NULL, DELIM);
-		if (p1) {
+		cmd = parts.items[0].string;
+		p1 = parts.nr >= 1 ? parts.items[1].string : NULL;
+		p2 = parts.nr >= 2 ? parts.items[2].string : NULL;
+		if (p1)
 			hash = icase ? strihash(p1) : strhash(p1);
-			p2 = strtok(NULL, DELIM);
-		}
 
 		if (!strcmp("add", cmd) && p1 && p2) {
 
@@ -260,6 +267,7 @@ int cmd__hashmap(int argc, const char **argv)
 		}
 	}
 
+	string_list_clear(&parts, 0);
 	strbuf_release(&line);
 	hashmap_clear_and_free(&map, struct test_entry, ent);
 	return 0;
diff --git a/t/helper/test-hexdump.c b/t/helper/test-hexdump.c
index 811e89c..05f55ec 100644
--- a/t/helper/test-hexdump.c
+++ b/t/helper/test-hexdump.c
@@ -4,7 +4,7 @@
 /*
  * Read stdin and print a hexdump to stdout.
  */
-int cmd__hexdump(int argc, const char **argv)
+int cmd__hexdump(int argc UNUSED, const char **argv UNUSED)
 {
 	char buf[1024];
 	ssize_t i, len;
diff --git a/t/helper/test-index-version.c b/t/helper/test-index-version.c
index fcd1096..a06c45c 100644
--- a/t/helper/test-index-version.c
+++ b/t/helper/test-index-version.c
@@ -1,7 +1,7 @@
 #include "test-tool.h"
 #include "cache.h"
 
-int cmd__index_version(int argc, const char **argv)
+int cmd__index_version(int argc UNUSED, const char **argv UNUSED)
 {
 	struct cache_header hdr;
 	int version;
diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c
index 8c3edac..afe393f 100644
--- a/t/helper/test-json-writer.c
+++ b/t/helper/test-json-writer.c
@@ -1,6 +1,6 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "json-writer.h"
+#include "string-list.h"
 
 static const char *expect_obj1 = "{\"a\":\"abc\",\"b\":42,\"c\":true}";
 static const char *expect_obj2 = "{\"a\":-1,\"b\":2147483647,\"c\":0}";
@@ -395,35 +395,41 @@ static int unit_tests(void)
 	return 0;
 }
 
-static void get_s(int line_nr, char **s_in)
+struct line {
+	struct string_list *parts;
+	size_t consumed_nr;
+	int nr;
+};
+
+static void get_s(struct line *line, char **s_in)
 {
-	*s_in = strtok(NULL, " ");
-	if (!*s_in)
-		die("line[%d]: expected: <s>", line_nr);
+	if (line->consumed_nr > line->parts->nr)
+		die("line[%d]: expected: <s>", line->nr);
+	*s_in = line->parts->items[line->consumed_nr++].string;
 }
 
-static void get_i(int line_nr, intmax_t *s_in)
+static void get_i(struct line *line, intmax_t *s_in)
 {
 	char *s;
 	char *endptr;
 
-	get_s(line_nr, &s);
+	get_s(line, &s);
 
 	*s_in = strtol(s, &endptr, 10);
 	if (*endptr || errno == ERANGE)
-		die("line[%d]: invalid integer value", line_nr);
+		die("line[%d]: invalid integer value", line->nr);
 }
 
-static void get_d(int line_nr, double *s_in)
+static void get_d(struct line *line, double *s_in)
 {
 	char *s;
 	char *endptr;
 
-	get_s(line_nr, &s);
+	get_s(line, &s);
 
 	*s_in = strtod(s, &endptr);
 	if (*endptr || errno == ERANGE)
-		die("line[%d]: invalid float value", line_nr);
+		die("line[%d]: invalid float value", line->nr);
 }
 
 static int pretty;
@@ -454,6 +460,7 @@ static char *get_trimmed_line(char *buf, int buf_size)
 
 static int scripted(void)
 {
+	struct string_list parts = STRING_LIST_INIT_NODUP;
 	struct json_writer jw = JSON_WRITER_INIT;
 	char buf[MAX_LINE_LENGTH];
 	char *line;
@@ -471,66 +478,77 @@ static int scripted(void)
 		die("expected first line to be 'object' or 'array'");
 
 	while ((line = get_trimmed_line(buf, MAX_LINE_LENGTH)) != NULL) {
+		struct line state = { 0 };
 		char *verb;
 		char *key;
 		char *s_value;
 		intmax_t i_value;
 		double d_value;
 
-		line_nr++;
+		state.parts = &parts;
+		state.nr = ++line_nr;
 
-		verb = strtok(line, " ");
+		/* break line into command and zero or more tokens */
+		string_list_setlen(&parts, 0);
+		string_list_split_in_place(&parts, line, " ", -1);
+		string_list_remove_empty_items(&parts, 0);
+
+		/* ignore empty lines */
+		if (!parts.nr || !*parts.items[0].string)
+			continue;
+
+		verb = parts.items[state.consumed_nr++].string;
 
 		if (!strcmp(verb, "end")) {
 			jw_end(&jw);
 		}
 		else if (!strcmp(verb, "object-string")) {
-			get_s(line_nr, &key);
-			get_s(line_nr, &s_value);
+			get_s(&state, &key);
+			get_s(&state, &s_value);
 			jw_object_string(&jw, key, s_value);
 		}
 		else if (!strcmp(verb, "object-int")) {
-			get_s(line_nr, &key);
-			get_i(line_nr, &i_value);
+			get_s(&state, &key);
+			get_i(&state, &i_value);
 			jw_object_intmax(&jw, key, i_value);
 		}
 		else if (!strcmp(verb, "object-double")) {
-			get_s(line_nr, &key);
-			get_i(line_nr, &i_value);
-			get_d(line_nr, &d_value);
+			get_s(&state, &key);
+			get_i(&state, &i_value);
+			get_d(&state, &d_value);
 			jw_object_double(&jw, key, i_value, d_value);
 		}
 		else if (!strcmp(verb, "object-true")) {
-			get_s(line_nr, &key);
+			get_s(&state, &key);
 			jw_object_true(&jw, key);
 		}
 		else if (!strcmp(verb, "object-false")) {
-			get_s(line_nr, &key);
+			get_s(&state, &key);
 			jw_object_false(&jw, key);
 		}
 		else if (!strcmp(verb, "object-null")) {
-			get_s(line_nr, &key);
+			get_s(&state, &key);
 			jw_object_null(&jw, key);
 		}
 		else if (!strcmp(verb, "object-object")) {
-			get_s(line_nr, &key);
+			get_s(&state, &key);
 			jw_object_inline_begin_object(&jw, key);
 		}
 		else if (!strcmp(verb, "object-array")) {
-			get_s(line_nr, &key);
+			get_s(&state, &key);
 			jw_object_inline_begin_array(&jw, key);
 		}
 		else if (!strcmp(verb, "array-string")) {
-			get_s(line_nr, &s_value);
+			get_s(&state, &s_value);
 			jw_array_string(&jw, s_value);
 		}
 		else if (!strcmp(verb, "array-int")) {
-			get_i(line_nr, &i_value);
+			get_i(&state, &i_value);
 			jw_array_intmax(&jw, i_value);
 		}
 		else if (!strcmp(verb, "array-double")) {
-			get_i(line_nr, &i_value);
-			get_d(line_nr, &d_value);
+			get_i(&state, &i_value);
+			get_d(&state, &d_value);
 			jw_array_double(&jw, i_value, d_value);
 		}
 		else if (!strcmp(verb, "array-true"))
@@ -553,6 +571,7 @@ static int scripted(void)
 	printf("%s\n", jw.json.buf);
 
 	jw_release(&jw);
+	string_list_clear(&parts, 0);
 	return 0;
 }
 
diff --git a/t/helper/test-lazy-init-name-hash.c b/t/helper/test-lazy-init-name-hash.c
index ab86c14..b83a75d 100644
--- a/t/helper/test-lazy-init-name-hash.c
+++ b/t/helper/test-lazy-init-name-hash.c
@@ -1,7 +1,11 @@
 #define USE_THE_INDEX_VARIABLE
 #include "test-tool.h"
 #include "cache.h"
+#include "environment.h"
 #include "parse-options.h"
+#include "repository.h"
+#include "setup.h"
+#include "trace.h"
 
 static int single;
 static int multi;
diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c
index 4079fde..d0db5ff 100644
--- a/t/helper/test-match-trees.c
+++ b/t/helper/test-match-trees.c
@@ -1,17 +1,21 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
+#include "match-trees.h"
+#include "object-name.h"
+#include "repository.h"
+#include "setup.h"
 #include "tree.h"
 
-int cmd__match_trees(int ac, const char **av)
+int cmd__match_trees(int ac UNUSED, const char **av)
 {
 	struct object_id hash1, hash2, shifted;
 	struct tree *one, *two;
 
 	setup_git_directory();
 
-	if (get_oid(av[1], &hash1))
+	if (repo_get_oid(the_repository, av[1], &hash1))
 		die("cannot parse %s as an object name", av[1]);
-	if (get_oid(av[2], &hash2))
+	if (repo_get_oid(the_repository, av[2], &hash2))
 		die("cannot parse %s as an object name", av[2]);
 	one = parse_tree_indirect(&hash1);
 	if (!one)
diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c
index 335e5bb..42ccc87 100644
--- a/t/helper/test-mergesort.c
+++ b/t/helper/test-mergesort.c
@@ -1,6 +1,7 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "mem-pool.h"
 #include "mergesort.h"
+#include "strbuf.h"
 
 static uint32_t minstd_rand(uint32_t *state)
 {
diff --git a/t/helper/test-oid-array.c b/t/helper/test-oid-array.c
index d1324d0..eef6883 100644
--- a/t/helper/test-oid-array.c
+++ b/t/helper/test-oid-array.c
@@ -1,6 +1,8 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
 #include "oid-array.h"
+#include "setup.h"
+#include "strbuf.h"
 
 static int print_oid(const struct object_id *oid, void *data)
 {
@@ -8,7 +10,7 @@ static int print_oid(const struct object_id *oid, void *data)
 	return 0;
 }
 
-int cmd__oid_array(int argc, const char **argv)
+int cmd__oid_array(int argc UNUSED, const char **argv UNUSED)
 {
 	struct oid_array array = OID_ARRAY_INIT;
 	struct strbuf line = STRBUF_INIT;
diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c
index 0acf999..bd30244 100644
--- a/t/helper/test-oidmap.c
+++ b/t/helper/test-oidmap.c
@@ -1,7 +1,11 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
+#include "object-name.h"
 #include "oidmap.h"
+#include "repository.h"
+#include "setup.h"
 #include "strbuf.h"
+#include "string-list.h"
 
 /* key is an oid and value is a name (could be a refname for example) */
 struct test_entry {
@@ -21,8 +25,9 @@ struct test_entry {
  * iterate -> oidkey1 namevalue1\noidkey2 namevalue2\n...
  *
  */
-int cmd__oidmap(int argc, const char **argv)
+int cmd__oidmap(int argc UNUSED, const char **argv UNUSED)
 {
+	struct string_list parts = STRING_LIST_INIT_NODUP;
 	struct strbuf line = STRBUF_INIT;
 	struct oidmap map = OIDMAP_INIT;
 
@@ -33,23 +38,28 @@ int cmd__oidmap(int argc, const char **argv)
 
 	/* process commands from stdin */
 	while (strbuf_getline(&line, stdin) != EOF) {
-		char *cmd, *p1 = NULL, *p2 = NULL;
+		char *cmd, *p1, *p2;
 		struct test_entry *entry;
 		struct object_id oid;
 
 		/* break line into command and up to two parameters */
-		cmd = strtok(line.buf, DELIM);
+		string_list_setlen(&parts, 0);
+		string_list_split_in_place(&parts, line.buf, DELIM, 2);
+		string_list_remove_empty_items(&parts, 0);
+
 		/* ignore empty lines */
-		if (!cmd || *cmd == '#')
+		if (!parts.nr)
+			continue;
+		if (!*parts.items[0].string || *parts.items[0].string == '#')
 			continue;
 
-		p1 = strtok(NULL, DELIM);
-		if (p1)
-			p2 = strtok(NULL, DELIM);
+		cmd = parts.items[0].string;
+		p1 = parts.nr >= 1 ? parts.items[1].string : NULL;
+		p2 = parts.nr >= 2 ? parts.items[2].string : NULL;
 
 		if (!strcmp("put", cmd) && p1 && p2) {
 
-			if (get_oid(p1, &oid)) {
+			if (repo_get_oid(the_repository, p1, &oid)) {
 				printf("Unknown oid: %s\n", p1);
 				continue;
 			}
@@ -67,7 +77,7 @@ int cmd__oidmap(int argc, const char **argv)
 
 		} else if (!strcmp("get", cmd) && p1) {
 
-			if (get_oid(p1, &oid)) {
+			if (repo_get_oid(the_repository, p1, &oid)) {
 				printf("Unknown oid: %s\n", p1);
 				continue;
 			}
@@ -80,7 +90,7 @@ int cmd__oidmap(int argc, const char **argv)
 
 		} else if (!strcmp("remove", cmd) && p1) {
 
-			if (get_oid(p1, &oid)) {
+			if (repo_get_oid(the_repository, p1, &oid)) {
 				printf("Unknown oid: %s\n", p1);
 				continue;
 			}
@@ -106,6 +116,7 @@ int cmd__oidmap(int argc, const char **argv)
 		}
 	}
 
+	string_list_clear(&parts, 0);
 	strbuf_release(&line);
 	oidmap_free(&map, 1);
 	return 0;
diff --git a/t/helper/test-oidtree.c b/t/helper/test-oidtree.c
index d48a409..c7a1d4c 100644
--- a/t/helper/test-oidtree.c
+++ b/t/helper/test-oidtree.c
@@ -1,14 +1,16 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
 #include "oidtree.h"
+#include "setup.h"
+#include "strbuf.h"
 
-static enum cb_next print_oid(const struct object_id *oid, void *data)
+static enum cb_next print_oid(const struct object_id *oid, void *data UNUSED)
 {
 	puts(oid_to_hex(oid));
 	return CB_CONTINUE;
 }
 
-int cmd__oidtree(int argc, const char **argv)
+int cmd__oidtree(int argc UNUSED, const char **argv UNUSED)
 {
 	struct oidtree ot;
 	struct strbuf line = STRBUF_INIT;
diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
index 8cb0d53..47dc211 100644
--- a/t/helper/test-online-cpus.c
+++ b/t/helper/test-online-cpus.c
@@ -2,7 +2,7 @@
 #include "git-compat-util.h"
 #include "thread-utils.h"
 
-int cmd__online_cpus(int argc, const char **argv)
+int cmd__online_cpus(int argc UNUSED, const char **argv UNUSED)
 {
 	printf("%d\n", online_cpus());
 	return 0;
diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c
index f7b79da..0f3fbee 100644
--- a/t/helper/test-pack-mtimes.c
+++ b/t/helper/test-pack-mtimes.c
@@ -1,9 +1,10 @@
-#include "git-compat-util.h"
 #include "test-tool.h"
+#include "hex.h"
 #include "strbuf.h"
 #include "object-store.h"
 #include "packfile.h"
 #include "pack-mtimes.h"
+#include "setup.h"
 
 static void dump_mtimes(struct packed_git *p)
 {
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index 5068355..00fa281 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -1,6 +1,6 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "parse-options.h"
+#include "strbuf.h"
 #include "string-list.h"
 #include "trace2.h"
 
@@ -263,14 +263,14 @@ int cmd__parse_options_flags(int argc, const char **argv)
 	return parse_options_flags__cmd(argc, argv, test_flags);
 }
 
-static int subcmd_one(int argc, const char **argv, const char *prefix)
+static int subcmd_one(int argc, const char **argv, const char *prefix UNUSED)
 {
 	printf("fn: subcmd_one\n");
 	print_args(argc, argv);
 	return 0;
 }
 
-static int subcmd_two(int argc, const char **argv, const char *prefix)
+static int subcmd_two(int argc, const char **argv, const char *prefix UNUSED)
 {
 	printf("fn: subcmd_two\n");
 	print_args(argc, argv);
diff --git a/t/helper/test-parse-pathspec-file.c b/t/helper/test-parse-pathspec-file.c
index b3e08ce..89ecefd 100644
--- a/t/helper/test-parse-pathspec-file.c
+++ b/t/helper/test-parse-pathspec-file.c
@@ -1,12 +1,11 @@
 #include "test-tool.h"
 #include "parse-options.h"
 #include "pathspec.h"
-#include "gettext.h"
 
 int cmd__parse_pathspec_file(int argc, const char **argv)
 {
 	struct pathspec pathspec;
-	const char *pathspec_from_file = NULL;
+	char *pathspec_from_file = NULL;
 	int pathspec_file_nul = 0, i;
 
 	static const char *const usage[] = {
@@ -29,5 +28,6 @@ int cmd__parse_pathspec_file(int argc, const char **argv)
 		printf("%s\n", pathspec.items[i].original);
 
 	clear_pathspec(&pathspec);
+	free(pathspec_from_file);
 	return 0;
 }
diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c
index 3f102cf..362bd64 100644
--- a/t/helper/test-partial-clone.c
+++ b/t/helper/test-partial-clone.c
@@ -1,7 +1,8 @@
-#include "cache.h"
 #include "test-tool.h"
+#include "hex.h"
 #include "repository.h"
 #include "object-store.h"
+#include "setup.h"
 
 /*
  * Prints the size of the object corresponding to the given hash in a specific
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index f69709d..2ef53d5 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -1,6 +1,11 @@
 #include "test-tool.h"
 #include "cache.h"
+#include "abspath.h"
+#include "environment.h"
+#include "path.h"
+#include "setup.h"
 #include "string-list.h"
+#include "trace.h"
 #include "utf8.h"
 
 /*
diff --git a/t/helper/test-pcre2-config.c b/t/helper/test-pcre2-config.c
index 5258fdd..5d0b2a2 100644
--- a/t/helper/test-pcre2-config.c
+++ b/t/helper/test-pcre2-config.c
@@ -1,5 +1,4 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "grep.h"
 
 int cmd__pcre2_config(int argc, const char **argv)
diff --git a/t/helper/test-pkt-line.c b/t/helper/test-pkt-line.c
index c5e052e..f4d134a 100644
--- a/t/helper/test-pkt-line.c
+++ b/t/helper/test-pkt-line.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "test-tool.h"
 #include "pkt-line.h"
+#include "write-or-die.h"
 
 static void pack_line(const char *line)
 {
diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c
index 133b5e6..f0bf255 100644
--- a/t/helper/test-prio-queue.c
+++ b/t/helper/test-prio-queue.c
@@ -1,8 +1,7 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "prio-queue.h"
 
-static int intcmp(const void *va, const void *vb, void *data)
+static int intcmp(const void *va, const void *vb, void *data UNUSED)
 {
 	const int *a = va, *b = vb;
 	return *a - *b;
@@ -17,7 +16,7 @@ static void show(int *v)
 	free(v);
 }
 
-int cmd__prio_queue(int argc, const char **argv)
+int cmd__prio_queue(int argc UNUSED, const char **argv)
 {
 	struct prio_queue pq = { intcmp };
 
diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c
index a4b305f..f30022d 100644
--- a/t/helper/test-proc-receive.c
+++ b/t/helper/test-proc-receive.c
@@ -1,9 +1,10 @@
-#include "cache.h"
+#include "test-tool.h"
 #include "connect.h"
+#include "hex.h"
 #include "parse-options.h"
 #include "pkt-line.h"
+#include "setup.h"
 #include "sigchain.h"
-#include "test-tool.h"
 
 static const char *proc_receive_usage[] = {
 	"test-tool proc-receive [<options>]",
diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c
index 6cc9735..66acb6a 100644
--- a/t/helper/test-progress.c
+++ b/t/helper/test-progress.c
@@ -19,7 +19,6 @@
  */
 #define GIT_TEST_PROGRESS_ONLY
 #include "test-tool.h"
-#include "gettext.h"
 #include "parse-options.h"
 #include "progress.h"
 #include "strbuf.h"
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 2f65c7f..5b6f217 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -1,10 +1,14 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "alloc.h"
 #include "commit.h"
 #include "commit-reach.h"
 #include "config.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "parse-options.h"
 #include "ref-filter.h"
+#include "setup.h"
 #include "string-list.h"
 #include "tag.h"
 
@@ -57,7 +61,7 @@ int cmd__reach(int ac, const char **av)
 		if (buf.len < 3)
 			continue;
 
-		if (get_oid_committish(buf.buf + 2, &oid))
+		if (repo_get_oid_committish(the_repository, buf.buf + 2, &oid))
 			die("failed to resolve %s", buf.buf + 2);
 
 		orig = parse_object(r, &oid);
@@ -106,13 +110,17 @@ int cmd__reach(int ac, const char **av)
 	if (!strcmp(av[1], "ref_newer"))
 		printf("%s(A,B):%d\n", av[1], ref_newer(&oid_A, &oid_B));
 	else if (!strcmp(av[1], "in_merge_bases"))
-		printf("%s(A,B):%d\n", av[1], in_merge_bases(A, B));
+		printf("%s(A,B):%d\n", av[1],
+		       repo_in_merge_bases(the_repository, A, B));
 	else if (!strcmp(av[1], "in_merge_bases_many"))
-		printf("%s(A,X):%d\n", av[1], in_merge_bases_many(A, X_nr, X_array));
+		printf("%s(A,X):%d\n", av[1],
+		       repo_in_merge_bases_many(the_repository, A, X_nr, X_array));
 	else if (!strcmp(av[1], "is_descendant_of"))
 		printf("%s(A,X):%d\n", av[1], repo_is_descendant_of(r, A, X));
 	else if (!strcmp(av[1], "get_merge_bases_many")) {
-		struct commit_list *list = get_merge_bases_many(A, X_nr, X_array);
+		struct commit_list *list = repo_get_merge_bases_many(the_repository,
+								     A, X_nr,
+								     X_array);
 		printf("%s(A,X):\n", av[1]);
 		print_sorted_commit_ids(list);
 	} else if (!strcmp(av[1], "reduce_heads")) {
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index 23e9e27..c1ae276 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -2,6 +2,9 @@
 #include "test-tool.h"
 #include "cache.h"
 #include "config.h"
+#include "repository.h"
+#include "setup.h"
+#include "wrapper.h"
 
 int cmd__read_cache(int argc, const char **argv)
 {
diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c
index 98b73bb..3ac496e 100644
--- a/t/helper/test-read-graph.c
+++ b/t/helper/test-read-graph.c
@@ -1,11 +1,11 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "commit-graph.h"
 #include "repository.h"
 #include "object-store.h"
 #include "bloom.h"
+#include "setup.h"
 
-int cmd__read_graph(int argc, const char **argv)
+int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
 {
 	struct commit_graph *graph = NULL;
 	struct object_directory *odb;
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index 27072ba..211adda 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -1,9 +1,11 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
 #include "midx.h"
 #include "repository.h"
 #include "object-store.h"
 #include "pack-bitmap.h"
+#include "packfile.h"
+#include "setup.h"
 
 static int read_midx_file(const char *object_dir, int show_objects)
 {
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index ae8a564..6d8f844 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -1,6 +1,7 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
 #include "refs.h"
+#include "setup.h"
 #include "worktree.h"
 #include "object-store.h"
 #include "repository.h"
@@ -200,7 +201,8 @@ static int cmd_verify_ref(struct ref_store *refs, const char **argv)
 	return ret;
 }
 
-static int cmd_for_each_reflog(struct ref_store *refs, const char **argv)
+static int cmd_for_each_reflog(struct ref_store *refs,
+			       const char **argv UNUSED)
 {
 	return refs_for_each_reflog(refs, each_ref, NULL);
 }
@@ -322,7 +324,7 @@ static struct command commands[] = {
 	{ NULL, NULL }
 };
 
-int cmd__ref_store(int argc, const char **argv)
+int cmd__ref_store(int argc UNUSED, const char **argv)
 {
 	struct ref_store *refs;
 	const char *func;
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index 1f0a28c..00237ef 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -1,3 +1,4 @@
+#include "reftable/system.h"
 #include "reftable/reftable-tests.h"
 #include "test-tool.h"
 
diff --git a/t/helper/test-repository.c b/t/helper/test-repository.c
index 56f0e3c..bafd2a5 100644
--- a/t/helper/test-repository.c
+++ b/t/helper/test-repository.c
@@ -1,11 +1,13 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "commit-graph.h"
 #include "commit.h"
 #include "config.h"
+#include "environment.h"
+#include "hex.h"
 #include "object-store.h"
 #include "object.h"
 #include "repository.h"
+#include "setup.h"
 #include "tree.h"
 
 static void test_parse_commit_in_graph(const char *gitdir, const char *worktree,
diff --git a/t/helper/test-revision-walking.c b/t/helper/test-revision-walking.c
index 4a45d5b..0c62b9d 100644
--- a/t/helper/test-revision-walking.c
+++ b/t/helper/test-revision-walking.c
@@ -9,17 +9,18 @@
  */
 
 #include "test-tool.h"
-#include "cache.h"
 #include "commit.h"
 #include "diff.h"
 #include "revision.h"
+#include "setup.h"
 
 static void print_commit(struct commit *commit)
 {
 	struct strbuf sb = STRBUF_INIT;
 	struct pretty_print_context ctx = {0};
 	ctx.date_mode.type = DATE_NORMAL;
-	format_commit_message(commit, " %m %s", &sb, &ctx);
+	repo_format_commit_message(the_repository, commit, " %m %s", &sb,
+				   &ctx);
 	printf("%s\n", sb.buf);
 	strbuf_release(&sb);
 }
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index 3ecb830..c0ed872 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -9,8 +9,6 @@
  */
 
 #include "test-tool.h"
-#include "git-compat-util.h"
-#include "cache.h"
 #include "run-command.h"
 #include "strvec.h"
 #include "strbuf.h"
@@ -18,13 +16,12 @@
 #include "string-list.h"
 #include "thread-utils.h"
 #include "wildmatch.h"
-#include "gettext.h"
 
 static int number_callbacks;
 static int parallel_next(struct child_process *cp,
 			 struct strbuf *err,
 			 void *cb,
-			 void **task_cb)
+			 void **task_cb UNUSED)
 {
 	struct child_process *d = cb;
 	if (number_callbacks >= 4)
@@ -40,10 +37,10 @@ static int parallel_next(struct child_process *cp,
 	return 1;
 }
 
-static int no_job(struct child_process *cp,
+static int no_job(struct child_process *cp UNUSED,
 		  struct strbuf *err,
-		  void *cb,
-		  void **task_cb)
+		  void *cb UNUSED,
+		  void **task_cb UNUSED)
 {
 	if (err)
 		strbuf_addstr(err, "no further jobs available\n");
@@ -52,10 +49,10 @@ static int no_job(struct child_process *cp,
 	return 0;
 }
 
-static int task_finished(int result,
+static int task_finished(int result UNUSED,
 			 struct strbuf *err,
-			 void *pp_cb,
-			 void *pp_task_cb)
+			 void *pp_cb UNUSED,
+			 void *pp_task_cb UNUSED)
 {
 	if (err)
 		strbuf_addstr(err, "asking for a quick stop\n");
diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c
index a26107e..6e17f50 100644
--- a/t/helper/test-scrap-cache-tree.c
+++ b/t/helper/test-scrap-cache-tree.c
@@ -2,10 +2,12 @@
 #include "test-tool.h"
 #include "cache.h"
 #include "lockfile.h"
+#include "repository.h"
+#include "setup.h"
 #include "tree.h"
 #include "cache-tree.h"
 
-int cmd__scrap_cache_tree(int ac, const char **av)
+int cmd__scrap_cache_tree(int ac UNUSED, const char **av UNUSED)
 {
 	struct lock_file index_lock = LOCK_INIT;
 
diff --git a/t/helper/test-serve-v2.c b/t/helper/test-serve-v2.c
index 824e5c0..054cbcf 100644
--- a/t/helper/test-serve-v2.c
+++ b/t/helper/test-serve-v2.c
@@ -1,7 +1,8 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "gettext.h"
 #include "parse-options.h"
 #include "serve.h"
+#include "setup.h"
 
 static char const * const serve_usage[] = {
 	N_("test-tool serve-v2 [<options>]"),
diff --git a/t/helper/test-sigchain.c b/t/helper/test-sigchain.c
index d013bcc..2d5ecf7 100644
--- a/t/helper/test-sigchain.c
+++ b/t/helper/test-sigchain.c
@@ -1,5 +1,4 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "sigchain.h"
 
 #define X(f) \
@@ -14,7 +13,7 @@ X(two)
 X(three)
 #undef X
 
-int cmd__sigchain(int argc, const char **argv)
+int cmd__sigchain(int argc UNUSED, const char **argv UNUSED)
 {
 	sigchain_push(SIGTERM, one);
 	sigchain_push(SIGTERM, two);
diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
index 28365ff..3d1436d 100644
--- a/t/helper/test-simple-ipc.c
+++ b/t/helper/test-simple-ipc.c
@@ -3,13 +3,14 @@
  */
 
 #include "test-tool.h"
-#include "cache.h"
+#include "gettext.h"
 #include "strbuf.h"
 #include "simple-ipc.h"
 #include "parse-options.h"
 #include "thread-utils.h"
 #include "strvec.h"
 #include "run-command.h"
+#include "trace2.h"
 
 #ifndef SUPPORTS_SIMPLE_IPC
 int cmd__simple_ipc(int argc, const char **argv)
diff --git a/t/helper/test-strcmp-offset.c b/t/helper/test-strcmp-offset.c
index 44e4a6d..96b9a5b 100644
--- a/t/helper/test-strcmp-offset.c
+++ b/t/helper/test-strcmp-offset.c
@@ -1,7 +1,7 @@
 #include "test-tool.h"
 #include "cache.h"
 
-int cmd__strcmp_offset(int argc, const char **argv)
+int cmd__strcmp_offset(int argc UNUSED, const char **argv)
 {
 	int result;
 	size_t offset;
diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c
index 2123dda..e2aad61 100644
--- a/t/helper/test-string-list.c
+++ b/t/helper/test-string-list.c
@@ -1,5 +1,5 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "strbuf.h"
 #include "string-list.h"
 
 /*
@@ -62,7 +62,7 @@ int cmd__string_list(int argc, const char **argv)
 		struct string_list list = STRING_LIST_INIT_NODUP;
 		int i;
 		char *s = xstrdup(argv[2]);
-		int delim = *argv[3];
+		const char *delim = argv[3];
 		int maxsplit = atoi(argv[4]);
 
 		i = string_list_split_in_place(&list, s, delim, maxsplit);
@@ -111,7 +111,7 @@ int cmd__string_list(int argc, const char **argv)
 		 */
 		if (sb.len && sb.buf[sb.len - 1] == '\n')
 			strbuf_setlen(&sb, sb.len - 1);
-		string_list_split_in_place(&list, sb.buf, '\n', -1);
+		string_list_split_in_place(&list, sb.buf, "\n", -1);
 
 		string_list_sort(&list);
 
diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index 22a41c4..9df2f03 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -1,10 +1,13 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "config.h"
+#include "hash.h"
+#include "object-name.h"
+#include "repository.h"
+#include "setup.h"
 #include "submodule-config.h"
 #include "submodule.h"
 
-static void die_usage(int argc, const char **argv, const char *msg)
+static void die_usage(int argc UNUSED, const char **argv, const char *msg)
 {
 	fprintf(stderr, "%s\n", msg);
 	fprintf(stderr, "Usage: %s [<commit> <submodulepath>] ...\n", argv[0]);
@@ -42,7 +45,7 @@ int cmd__submodule_config(int argc, const char **argv)
 
 		if (commit[0] == '\0')
 			oidclr(&commit_oid);
-		else if (get_oid(commit, &commit_oid) < 0)
+		else if (repo_get_oid(the_repository, commit, &commit_oid) < 0)
 			die_usage(argc, argv, "Commit not found.");
 
 		if (lookup_name) {
diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c
index dc1c14b..ecd40de 100644
--- a/t/helper/test-submodule-nested-repo-config.c
+++ b/t/helper/test-submodule-nested-repo-config.c
@@ -1,4 +1,6 @@
 #include "test-tool.h"
+#include "repository.h"
+#include "setup.h"
 #include "submodule-config.h"
 
 static void die_usage(const char **argv, const char *msg)
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index e060cc6..356e0a2 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -1,8 +1,9 @@
 #include "test-tool.h"
 #include "test-tool-utils.h"
-#include "cache.h"
 #include "parse-options.h"
 #include "remote.h"
+#include "repository.h"
+#include "setup.h"
 #include "submodule-config.h"
 #include "submodule.h"
 
@@ -174,7 +175,7 @@ static int cmd__submodule_config_unset(int argc, const char **argv)
 	usage_with_options(usage, options);
 }
 
-static int cmd__submodule_config_writeable(int argc, const char **argv)
+static int cmd__submodule_config_writeable(int argc, const char **argv UNUSED)
 {
 	struct option options[] = {
 		OPT_END()
diff --git a/t/helper/test-subprocess.c b/t/helper/test-subprocess.c
index ff22f2f..c344f16 100644
--- a/t/helper/test-subprocess.c
+++ b/t/helper/test-subprocess.c
@@ -1,6 +1,6 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "run-command.h"
+#include "setup.h"
 
 int cmd__subprocess(int argc, const char **argv)
 {
diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c
index f374c21..20c7495 100644
--- a/t/helper/test-trace2.c
+++ b/t/helper/test-trace2.c
@@ -1,9 +1,10 @@
 #include "test-tool.h"
-#include "cache.h"
 #include "strvec.h"
 #include "run-command.h"
 #include "exec-cmd.h"
 #include "config.h"
+#include "repository.h"
+#include "trace2.h"
 
 typedef int(fn_unit_test)(int argc, const char **argv);
 
@@ -208,7 +209,7 @@ static int ut_007BUG(int argc, const char **argv)
 	BUG("the bug message");
 }
 
-static int ut_008bug(int argc, const char **argv)
+static int ut_008bug(int argc UNUSED, const char **argv UNUSED)
 {
 	bug("a bug message");
 	bug("another bug message");
@@ -216,7 +217,7 @@ static int ut_008bug(int argc, const char **argv)
 	return 0;
 }
 
-static int ut_009bug_BUG(int argc, const char **argv)
+static int ut_009bug_BUG(int argc UNUSED, const char **argv UNUSED)
 {
 	bug("a bug message");
 	bug("another bug message");
@@ -224,7 +225,7 @@ static int ut_009bug_BUG(int argc, const char **argv)
 	return 0;
 }
 
-static int ut_010bug_BUG(int argc, const char **argv)
+static int ut_010bug_BUG(int argc UNUSED, const char **argv UNUSED)
 {
 	bug("a %s message", "bug");
 	BUG("a %s message", "BUG");
diff --git a/t/helper/test-userdiff.c b/t/helper/test-userdiff.c
index a2b56b9..680124a 100644
--- a/t/helper/test-userdiff.c
+++ b/t/helper/test-userdiff.c
@@ -1,5 +1,5 @@
 #include "test-tool.h"
-#include "cache.h"
+#include "setup.h"
 #include "userdiff.h"
 #include "config.h"
 
diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c
index 2c103d1..a95bb4d 100644
--- a/t/helper/test-wildmatch.c
+++ b/t/helper/test-wildmatch.c
@@ -1,5 +1,4 @@
 #include "test-tool.h"
-#include "cache.h"
 
 int cmd__wildmatch(int argc, const char **argv)
 {
diff --git a/t/helper/test-write-cache.c b/t/helper/test-write-cache.c
index 7d45cd6..eace080 100644
--- a/t/helper/test-write-cache.c
+++ b/t/helper/test-write-cache.c
@@ -2,6 +2,8 @@
 #include "test-tool.h"
 #include "cache.h"
 #include "lockfile.h"
+#include "repository.h"
+#include "setup.h"
 
 int cmd__write_cache(int argc, const char **argv)
 {
diff --git a/t/helper/test-xml-encode.c b/t/helper/test-xml-encode.c
index a648bbd..b2f330d 100644
--- a/t/helper/test-xml-encode.c
+++ b/t/helper/test-xml-encode.c
@@ -6,7 +6,7 @@ static const char *utf8_replace_character = "&#xfffd;";
  * Encodes (possibly incorrect) UTF-8 on <stdin> to <stdout>, to be embedded
  * in an XML file.
  */
-int cmd__xml_encode(int argc, const char **argv)
+int cmd__xml_encode(int argc UNUSED, const char **argv UNUSED)
 {
 	unsigned char buf[1024], tmp[4], *tmp2 = NULL;
 	ssize_t cur = 0, len = 1, remaining = 0;
diff --git a/t/lib-credential.sh b/t/lib-credential.sh
index 5ea8bc9..f1ab92b 100644
--- a/t/lib-credential.sh
+++ b/t/lib-credential.sh
@@ -43,6 +43,7 @@
 	reject $1 https example.com store-user
 	reject $1 https example.com user1
 	reject $1 https example.com user2
+	reject $1 https example.com user4
 	reject $1 http path.tld user
 	reject $1 https timeout.tld user
 	reject $1 https sso.tld
@@ -270,6 +271,35 @@
 		password=
 		EOF
 	'
+
+	: ${GIT_TEST_LONG_CRED_BUFFER:=1024}
+	# 23 bytes accounts for "wwwauth[]=basic realm=" plus NUL
+	LONG_VALUE_LEN=$((GIT_TEST_LONG_CRED_BUFFER - 23))
+	LONG_VALUE=$(perl -e 'print "a" x shift' $LONG_VALUE_LEN)
+
+	test_expect_success "helper ($HELPER) not confused by long header" '
+		check approve $HELPER <<-\EOF &&
+		protocol=https
+		host=victim.example.com
+		username=user
+		password=to-be-stolen
+		EOF
+
+		check fill $HELPER <<-EOF
+		protocol=https
+		host=badguy.example.com
+		wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com
+		--
+		protocol=https
+		host=badguy.example.com
+		username=askpass-username
+		password=askpass-password
+		wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com
+		--
+		askpass: Username for '\''https://badguy.example.com'\'':
+		askpass: Password for '\''https://askpass-username@badguy.example.com'\'':
+		EOF
+	'
 }
 
 helper_test_timeout() {
@@ -298,6 +328,35 @@
 	'
 }
 
+helper_test_oauth_refresh_token() {
+	HELPER=$1
+
+	test_expect_success "helper ($HELPER) stores oauth_refresh_token" '
+		check approve $HELPER <<-\EOF
+		protocol=https
+		host=example.com
+		username=user4
+		password=pass
+		oauth_refresh_token=xyzzy
+		EOF
+	'
+
+	test_expect_success "helper ($HELPER) gets oauth_refresh_token" '
+		check fill $HELPER <<-\EOF
+		protocol=https
+		host=example.com
+		username=user4
+		--
+		protocol=https
+		host=example.com
+		username=user4
+		password=pass
+		oauth_refresh_token=xyzzy
+		--
+		EOF
+	'
+}
+
 write_script askpass <<\EOF
 echo >&2 askpass: $*
 what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z)
diff --git a/t/lib-diff-alternative.sh b/t/lib-diff-alternative.sh
index a8f5d32..c4dc2d4 100644
--- a/t/lib-diff-alternative.sh
+++ b/t/lib-diff-alternative.sh
@@ -112,15 +112,36 @@
 
 	STRATEGY=$1
 
-	test_expect_success "$STRATEGY diff from attributes" '
+	test_expect_success "setup attributes files for tests with $STRATEGY" '
+		git checkout -b master &&
 		echo "file* diff=driver" >.gitattributes &&
-		git config diff.driver.algorithm "$STRATEGY" &&
-		test_must_fail git diff --no-index file1 file2 > output &&
-		cat expect &&
-		cat output &&
+		git add file1 file2 .gitattributes &&
+		git commit -m "adding files" &&
+		git checkout -b branchA &&
+		echo "file* diff=driverA" >.gitattributes &&
+		git add .gitattributes &&
+		git commit -m "adding driverA as diff driver" &&
+		git checkout master &&
+		git clone --bare --no-local . bare.git
+	'
+
+	test_expect_success "$STRATEGY diff from attributes" '
+		test_must_fail git -c diff.driver.algorithm=$STRATEGY diff --no-index file1 file2 > output &&
 		test_cmp expect output
 	'
 
+	test_expect_success "diff from attributes with bare repo with source" '
+		git -C bare.git --attr-source=branchA -c diff.driver.algorithm=myers \
+			-c diff.driverA.algorithm=$STRATEGY \
+			diff HEAD:file1 HEAD:file2 >output &&
+		test_cmp expect output
+	'
+
+	test_expect_success "diff from attributes with bare repo with invalid source" '
+		test_must_fail git -C bare.git --attr-source=invalid-branch diff \
+			HEAD:file1 HEAD:file2
+	'
+
 	test_expect_success "$STRATEGY diff from attributes has valid diffstat" '
 		echo "file* diff=driver" >.gitattributes &&
 		git config diff.driver.algorithm "$STRATEGY" &&
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index 09cf5ed..2fb1b2a 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -142,6 +142,7 @@
 	install_script error-smart-http.sh
 	install_script error.sh
 	install_script apply-one-time-perl.sh
+	install_script nph-custom-auth.sh
 
 	ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
 
@@ -190,6 +191,20 @@
 	test_set_prereq HTTP2
 }
 
+enable_cgipassauth () {
+	# We are looking for 2.4.13 or more recent. Since we only support
+	# 2.4 and up, no need to check for older major/minor.
+	if test "$HTTPD_VERSION_MAJOR" = 2 &&
+	   test "$HTTPD_VERSION_MINOR" = 4 &&
+	   test "$(echo $HTTPD_VERSION | cut -d. -f3)" -lt 13
+	then
+		echo >&4 "apache $HTTPD_VERSION too old for CGIPassAuth"
+		return
+	fi
+	HTTPD_PARA="$HTTPD_PARA -DUSE_CGIPASSAUTH"
+	test_set_prereq CGIPASSAUTH
+}
+
 start_httpd() {
 	prepare_httpd >&3 2>&4
 
@@ -227,8 +242,12 @@
 		git commit -a -m path2 --amend &&
 
 		test_must_fail git push -v origin >output 2>&1 &&
-		(cd "$REMOTE_REPO" &&
-		 test $HEAD = $(git rev-parse --verify HEAD))
+		(
+			cd "$REMOTE_REPO" &&
+			echo "$HEAD" >expect &&
+			git rev-parse --verify HEAD >actual &&
+			test_cmp expect actual
+		)
 	'
 
 	test_expect_success 'non-fast-forward push show ref status' '
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 31f82fa..a22d138 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -101,6 +101,8 @@
 Alias /dumb/ www/
 Alias /auth/dumb/ www/auth/dumb/
 
+SetEnv PERL_PATH ${PERL_PATH}
+
 <LocationMatch /smart/>
 	SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
 	SetEnv GIT_HTTP_EXPORT_ALL
@@ -141,6 +143,13 @@
 	SetEnv GIT_HTTP_EXPORT_ALL
 	SetEnv GIT_PROTOCOL
 </LocationMatch>
+<LocationMatch /custom_auth/>
+	SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
+	SetEnv GIT_HTTP_EXPORT_ALL
+	<IfDefine USE_CGIPASSAUTH>
+	CGIPassAuth on
+	</IfDefine>
+</LocationMatch>
 ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
 ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/
 ScriptAlias /smart/no_report/git-receive-pack error-no-report.sh/
@@ -150,6 +159,7 @@
 ScriptAlias /error_smart/ error-smart-http.sh/
 ScriptAlias /error/ error.sh/
 ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1
+ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1
 <Directory ${GIT_EXEC_PATH}>
 	Options FollowSymlinks
 </Directory>
diff --git a/t/lib-httpd/apply-one-time-perl.sh b/t/lib-httpd/apply-one-time-perl.sh
index 09a0abd..d7f9fed 100644
--- a/t/lib-httpd/apply-one-time-perl.sh
+++ b/t/lib-httpd/apply-one-time-perl.sh
@@ -13,7 +13,7 @@
 	export LC_ALL
 
 	"$GIT_EXEC_PATH/git-http-backend" >out
-	perl -pe "$(cat one-time-perl)" out >out_modified
+	"$PERL_PATH" -pe "$(cat one-time-perl)" out >out_modified
 
 	if cmp -s out out_modified
 	then
diff --git a/t/lib-httpd/nph-custom-auth.sh b/t/lib-httpd/nph-custom-auth.sh
new file mode 100644
index 0000000..f5345e7
--- /dev/null
+++ b/t/lib-httpd/nph-custom-auth.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+VALID_CREDS_FILE=custom-auth.valid
+CHALLENGE_FILE=custom-auth.challenge
+
+#
+# If $VALID_CREDS_FILE exists in $HTTPD_ROOT_PATH, consider each line as a valid
+# credential for the current request. Each line in the file is considered a
+# valid HTTP Authorization header value. For example:
+#
+# Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+#
+# If $CHALLENGE_FILE exists in $HTTPD_ROOT_PATH, output the contents as headers
+# in a 401 response if no valid authentication credentials were included in the
+# request. For example:
+#
+# WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
+# WWW-Authenticate: Basic realm="example.com"
+#
+
+if test -n "$HTTP_AUTHORIZATION" && \
+	grep -Fqsx "${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE"
+then
+	# Note that although git-http-backend returns a status line, it
+	# does so using a CGI 'Status' header. Because this script is an
+	# No Parsed Headers (NPH) script, we must return a real HTTP
+	# status line.
+	# This is only a test script, so we don't bother to check for
+	# the actual status from git-http-backend and always return 200.
+	echo 'HTTP/1.1 200 OK'
+	exec "$GIT_EXEC_PATH"/git-http-backend
+fi
+
+echo 'HTTP/1.1 401 Authorization Required'
+if test -f "$CHALLENGE_FILE"
+then
+	cat "$CHALLENGE_FILE"
+fi
+echo
diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh
index cfd76bf..89ca1f7 100644
--- a/t/lib-patch-mode.sh
+++ b/t/lib-patch-mode.sh
@@ -29,8 +29,12 @@
 
 # verify_state <path> <expected-worktree-content> <expected-index-content>
 verify_state () {
-	test "$(cat "$1")" = "$2" &&
-	test "$(git show :"$1")" = "$3"
+	echo "$2" >expect &&
+	test_cmp expect "$1" &&
+
+	echo "$3" >expect &&
+	git show :"$1" >actual &&
+	test_cmp expect actual
 }
 
 # verify_saved_state <path>
@@ -46,5 +50,6 @@
 }
 
 verify_saved_head () {
-	test "$(cat _head)" = "$(git rev-parse HEAD)"
+	git rev-parse HEAD >actual &&
+	test_cmp _head actual
 }
diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh
index 2d31fcf..9acb0d5 100644
--- a/t/lib-submodule-update.sh
+++ b/t/lib-submodule-update.sh
@@ -168,20 +168,16 @@
 # Note that this only supports submodules at the root level of the
 # superproject, with the default name, i.e. same as its path.
 test_git_directory_is_unchanged () {
-	(
-		cd ".git/modules/$1" &&
-		# does core.worktree point at the right place?
-		test "$(git config core.worktree)" = "../../../$1" &&
-		# remove it temporarily before comparing, as
-		# "$1/.git/config" lacks it...
-		git config --unset core.worktree
-	) &&
+	# does core.worktree point at the right place?
+	echo "../../../$1" >expect &&
+	git -C ".git/modules/$1" config core.worktree >actual &&
+	test_cmp expect actual &&
+	# remove it temporarily before comparing, as
+	# "$1/.git/config" lacks it...
+	git -C ".git/modules/$1" config --unset core.worktree &&
 	diff -r ".git/modules/$1" "$1/.git" &&
-	(
-		# ... and then restore.
-		cd ".git/modules/$1" &&
-		git config core.worktree "../../../$1"
-	)
+	# ... and then restore.
+	git -C ".git/modules/$1" config core.worktree "../../../$1"
 }
 
 test_git_directory_exists () {
@@ -189,7 +185,9 @@
 	if test -f sub1/.git
 	then
 		# does core.worktree point at the right place?
-		test "$(git -C .git/modules/$1 config core.worktree)" = "../../../$1"
+		echo "../../../$1" >expect &&
+		git -C ".git/modules/$1" config core.worktree >actual &&
+		test_cmp expect actual
 	fi
 }
 
@@ -804,7 +802,7 @@
 			git branch -t no_submodule origin/no_submodule &&
 			$command no_submodule &&
 			test_superproject_content origin/no_submodule &&
-			! test_path_is_dir sub1 &&
+			test_path_is_missing sub1 &&
 			test_must_fail git config -f .git/modules/sub1/config core.worktree &&
 			test_must_fail git config -f .git/modules/sub1/modules/sub2/config core.worktree
 		)
diff --git a/t/perf/p1500-graph-walks.sh b/t/perf/p1500-graph-walks.sh
new file mode 100755
index 0000000..e14e762
--- /dev/null
+++ b/t/perf/p1500-graph-walks.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='Commit walk performance tests'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+test_expect_success 'setup' '
+	git for-each-ref --format="%(refname)" "refs/heads/*" "refs/tags/*" >allrefs &&
+	sort -r allrefs | head -n 50 >refs &&
+	for ref in $(cat refs)
+	do
+		git branch -f ref-$ref $ref &&
+		echo ref-$ref ||
+		return 1
+	done >branches &&
+	for ref in $(cat refs)
+	do
+		git tag -f tag-$ref $ref &&
+		echo tag-$ref ||
+		return 1
+	done >tags &&
+	git commit-graph write --reachable
+'
+
+test_perf 'ahead-behind counts: git for-each-ref' '
+	git for-each-ref --format="%(ahead-behind:HEAD)" --stdin <refs
+'
+
+test_perf 'ahead-behind counts: git branch' '
+	xargs git branch -l --format="%(ahead-behind:HEAD)" <branches
+'
+
+test_perf 'ahead-behind counts: git tag' '
+	xargs git tag -l --format="%(ahead-behind:HEAD)" <tags
+'
+
+test_perf 'contains: git for-each-ref --merged' '
+	git for-each-ref --merged=HEAD --stdin <refs
+'
+
+test_perf 'contains: git branch --merged' '
+	xargs git branch --merged=HEAD <branches
+'
+
+test_perf 'contains: git tag --merged' '
+	xargs git tag --merged=HEAD <tags
+'
+
+test_done
diff --git a/t/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh
index 3242cfe..901cc49 100755
--- a/t/perf/p2000-sparse-operations.sh
+++ b/t/perf/p2000-sparse-operations.sh
@@ -43,6 +43,7 @@
 	done &&
 
 	git sparse-checkout init --cone &&
+	git tag -a v1.0 -m "Final" &&
 	git sparse-checkout set $SPARSE_CONE &&
 	git checkout -b wide $OLD_COMMIT &&
 
@@ -124,6 +125,11 @@
 test_perf_on_all git checkout-index -f --all
 test_perf_on_all git update-index --add --remove $SPARSE_CONE/a
 test_perf_on_all "git rm -f $SPARSE_CONE/a && git checkout HEAD -- $SPARSE_CONE/a"
-test_perf_on_all git grep --cached --sparse bogus -- "f2/f1/f1/*"
+test_perf_on_all git grep --cached bogus -- "f2/f1/f1/*"
+test_perf_on_all git write-tree
+test_perf_on_all git describe --dirty
+test_perf_on_all 'echo >>new && git describe --dirty'
+test_perf_on_all git diff-files
+test_perf_on_all git diff-files -- $SPARSE_CONE/a
 
 test_done
diff --git a/t/perf/p5312-pack-bitmaps-revs.sh b/t/perf/p5312-pack-bitmaps-revs.sh
index 0684b69..ceec606 100755
--- a/t/perf/p5312-pack-bitmaps-revs.sh
+++ b/t/perf/p5312-pack-bitmaps-revs.sh
@@ -12,8 +12,7 @@
 	test_perf_large_repo
 
 	test_expect_success 'setup bitmap config' '
-		git config pack.writebitmaps true &&
-		git config pack.writeReverseIndex true
+		git config pack.writebitmaps true
 	'
 
 	# we need to create the tag up front such that it is covered by the repack and
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index d479303..30a6edc 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -598,9 +598,14 @@
 test_expect_success 'branch -m with the initial branch' '
 	git init rename-initial &&
 	git -C rename-initial branch -m renamed &&
-	test renamed = $(git -C rename-initial symbolic-ref --short HEAD) &&
+	echo renamed >expect &&
+	git -C rename-initial symbolic-ref --short HEAD >actual &&
+	test_cmp expect actual &&
+
 	git -C rename-initial branch -m renamed again &&
-	test again = $(git -C rename-initial symbolic-ref --short HEAD)
+	echo again >expect &&
+	git -C rename-initial symbolic-ref --short HEAD >actual &&
+	test_cmp expect actual
 '
 
 test_done
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
index 26eaca0..e013d38 100755
--- a/t/t0002-gitfile.sh
+++ b/t/t0002-gitfile.sh
@@ -33,7 +33,9 @@
 
 test_expect_success 'final setup + check rev-parse --git-dir' '
 	echo "gitdir: $REAL" >.git &&
-	test "$REAL" = "$(git rev-parse --git-dir)"
+	echo "$REAL" >expect &&
+	git rev-parse --git-dir >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'check hash-object' '
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 89b306c..26e082f 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -30,8 +30,17 @@
 attr_check_source () {
 	path="$1" expect="$2" source="$3" git_opts="$4" &&
 
-	git $git_opts check-attr --source $source test -- "$path" >actual 2>err &&
 	echo "$path: test: $expect" >expect &&
+
+	git $git_opts check-attr --source $source test -- "$path" >actual 2>err &&
+	test_cmp expect actual &&
+	test_must_be_empty err &&
+
+	git $git_opts --attr-source="$source" check-attr test -- "$path" >actual 2>err &&
+	test_cmp expect actual &&
+	test_must_be_empty err
+
+	GIT_ATTR_SOURCE="$source" git $git_opts check-attr test -- "$path" >actual 2>err &&
 	test_cmp expect actual &&
 	test_must_be_empty err
 }
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 35cc8c3..81946e8 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -125,7 +125,7 @@
 	munge_cr append dir/two &&
 	git update-index -- one dir/two &&
 	differs=$(git diff-index --cached HEAD) &&
-	verbose test -z "$differs"
+	test -z "$differs"
 
 '
 
@@ -138,7 +138,7 @@
 	munge_cr append dir/two &&
 	git update-index -- one dir/two &&
 	differs=$(git diff-index --cached HEAD) &&
-	verbose test -z "$differs"
+	test -z "$differs"
 
 '
 
@@ -153,7 +153,7 @@
 	test "$one" = $(git hash-object --stdin <one) &&
 	test "$two" = $(git hash-object --stdin <dir/two) &&
 	differs=$(git diff-index --cached HEAD) &&
-	verbose test -z "$differs"
+	test -z "$differs"
 '
 
 test_expect_success 'checkout with autocrlf=input' '
@@ -167,7 +167,7 @@
 	test "$one" = $(git hash-object --stdin <one) &&
 	test "$two" = $(git hash-object --stdin <dir/two) &&
 	differs=$(git diff-index --cached HEAD) &&
-	verbose test -z "$differs"
+	test -z "$differs"
 '
 
 test_expect_success 'apply patch (autocrlf=input)' '
@@ -177,7 +177,7 @@
 	git read-tree --reset -u HEAD &&
 
 	git apply patch.file &&
-	verbose test "$patched" = "$(git hash-object --stdin <one)"
+	test "$patched" = "$(git hash-object --stdin <one)"
 '
 
 test_expect_success 'apply patch --cached (autocrlf=input)' '
@@ -187,7 +187,7 @@
 	git read-tree --reset -u HEAD &&
 
 	git apply --cached patch.file &&
-	verbose test "$patched" = $(git rev-parse :one)
+	test "$patched" = $(git rev-parse :one)
 '
 
 test_expect_success 'apply patch --index (autocrlf=input)' '
@@ -197,8 +197,8 @@
 	git read-tree --reset -u HEAD &&
 
 	git apply --index patch.file &&
-	verbose test "$patched" = $(git rev-parse :one) &&
-	verbose test "$patched" = $(git hash-object --stdin <one)
+	test "$patched" = $(git rev-parse :one) &&
+	test "$patched" = $(git hash-object --stdin <one)
 '
 
 test_expect_success 'apply patch (autocrlf=true)' '
@@ -208,7 +208,7 @@
 	git read-tree --reset -u HEAD &&
 
 	git apply patch.file &&
-	verbose test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
+	test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
 '
 
 test_expect_success 'apply patch --cached (autocrlf=true)' '
@@ -218,7 +218,7 @@
 	git read-tree --reset -u HEAD &&
 
 	git apply --cached patch.file &&
-	verbose test "$patched" = $(git rev-parse :one)
+	test "$patched" = $(git rev-parse :one)
 '
 
 test_expect_success 'apply patch --index (autocrlf=true)' '
@@ -228,8 +228,8 @@
 	git read-tree --reset -u HEAD &&
 
 	git apply --index patch.file &&
-	verbose test "$patched" = $(git rev-parse :one) &&
-	verbose test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
+	test "$patched" = $(git rev-parse :one) &&
+	test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
 '
 
 test_expect_success '.gitattributes says two is binary' '
@@ -240,7 +240,7 @@
 	git read-tree --reset -u HEAD &&
 
 	! has_cr dir/two &&
-	verbose has_cr one &&
+	has_cr one &&
 	! has_cr three
 '
 
@@ -259,8 +259,8 @@
 	echo "t* crlf" >.gitattributes &&
 	git read-tree --reset -u HEAD &&
 
-	verbose has_cr dir/two &&
-	verbose has_cr three
+	has_cr dir/two &&
+	has_cr three
 '
 
 test_expect_success 'in-tree .gitattributes (1)' '
@@ -273,7 +273,7 @@
 	git read-tree --reset -u HEAD &&
 
 	! has_cr one &&
-	verbose has_cr three
+	has_cr three
 '
 
 test_expect_success 'in-tree .gitattributes (2)' '
@@ -283,7 +283,7 @@
 	git checkout-index -f -q -u -a &&
 
 	! has_cr one &&
-	verbose has_cr three
+	has_cr three
 '
 
 test_expect_success 'in-tree .gitattributes (3)' '
@@ -294,7 +294,7 @@
 	git checkout-index -u one dir/two three &&
 
 	! has_cr one &&
-	verbose has_cr three
+	has_cr three
 '
 
 test_expect_success 'in-tree .gitattributes (4)' '
@@ -305,7 +305,7 @@
 	git checkout-index -u .gitattributes &&
 
 	! has_cr one &&
-	verbose has_cr three
+	has_cr three
 '
 
 test_expect_success 'checkout with existing .gitattributes' '
diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh
index a94ac1e..2f57c86 100755
--- a/t/t0027-auto-crlf.sh
+++ b/t/t0027-auto-crlf.sh
@@ -70,7 +70,8 @@
 				cp CRLF        ${pfx}_CRLF.txt &&
 				cp CRLF_mix_LF ${pfx}_CRLF_mix_LF.txt &&
 				cp LF_mix_CR   ${pfx}_LF_mix_CR.txt &&
-				cp CRLF_nul    ${pfx}_CRLF_nul.txt
+				cp CRLF_nul    ${pfx}_CRLF_nul.txt ||
+				return 1
 			done
 		done
 	done
@@ -101,7 +102,8 @@
 	do
 		fname=${pfx}_$f.txt &&
 		cp $f $fname &&
-		git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
+		git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" ||
+		return 1
 	done &&
 	git commit -m "core.autocrlf $crlf" &&
 	check_warning "$lfname" ${pfx}_LF.err &&
@@ -121,15 +123,19 @@
 	lfmixcr=$1 ; shift
 	crlfnul=$1 ; shift
 	pfx=NNO_attr_${attr}_aeol_${aeol}_${crlf}
-	#Commit files on top of existing file
-	create_gitattributes "$attr" $aeol &&
-	for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
-	do
-		fname=${pfx}_$f.txt &&
-		cp $f $fname &&
-		printf Z >>"$fname" &&
-		git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
-	done
+
+	test_expect_success 'setup commit NNO files' '
+		#Commit files on top of existing file
+		create_gitattributes "$attr" $aeol &&
+		for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+		do
+			fname=${pfx}_$f.txt &&
+			cp $f $fname &&
+			printf Z >>"$fname" &&
+			git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" ||
+			return 1
+		done
+	'
 
 	test_expect_success "commit NNO files crlf=$crlf attr=$attr LF" '
 		check_warning "$lfwarn" ${pfx}_LF.err
@@ -163,15 +169,19 @@
 	lfmixcr=$1 ; shift
 	crlfnul=$1 ; shift
 	pfx=MIX_attr_${attr}_aeol_${aeol}_${crlf}
-	#Commit file with CLRF_mix_LF on top of existing file
-	create_gitattributes "$attr" $aeol &&
-	for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
-	do
-		fname=${pfx}_$f.txt &&
-		cp CRLF_mix_LF $fname &&
-		printf Z >>"$fname" &&
-		git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
-	done
+
+	test_expect_success 'setup commit file with mixed EOL' '
+		#Commit file with CLRF_mix_LF on top of existing file
+		create_gitattributes "$attr" $aeol &&
+		for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+		do
+			fname=${pfx}_$f.txt &&
+			cp CRLF_mix_LF $fname &&
+			printf Z >>"$fname" &&
+			git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" ||
+			return 1
+		done
+	'
 
 	test_expect_success "commit file with mixed EOL onto LF crlf=$crlf attr=$attr" '
 		check_warning "$lfwarn" ${pfx}_LF.err
@@ -289,17 +299,17 @@
 	lfmixcrlf=$1 ; shift
 	lfmixcr=$1 ; shift
 	crlfnul=$1 ; shift
-	create_gitattributes "$attr" $ident $aeol &&
-	git config core.autocrlf $crlf &&
+	test_expect_success "setup config for checkout attr=$attr ident=$ident aeol=$aeol core.autocrlf=$crlf" '
+		create_gitattributes "$attr" $ident $aeol &&
+		git config core.autocrlf $crlf
+	'
 	pfx=eol_${ceol}_crlf_${crlf}_attr_${attr}_ &&
 	for f in LF CRLF LF_mix_CR CRLF_mix_LF LF_nul
 	do
-		rm crlf_false_attr__$f.txt &&
-		if test -z "$ceol"; then
-			git checkout -- crlf_false_attr__$f.txt
-		else
-			git -c core.eol=$ceol checkout -- crlf_false_attr__$f.txt
-		fi
+		test_expect_success "setup $f checkout ${ceol:+ with -c core.eol=$ceol}"  '
+			rm -f crlf_false_attr__$f.txt &&
+			git ${ceol:+-c core.eol=$ceol} checkout -- crlf_false_attr__$f.txt
+		'
 	done
 
 	test_expect_success "ls-files --eol attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol" '
diff --git a/t/t0035-safe-bare-repository.sh b/t/t0035-safe-bare-repository.sh
index 11c15a4..038b8b7 100755
--- a/t/t0035-safe-bare-repository.sh
+++ b/t/t0035-safe-bare-repository.sh
@@ -7,13 +7,26 @@
 
 pwd="$(pwd)"
 
-expect_accepted () {
-	git "$@" rev-parse --git-dir
+expect_accepted_implicit () {
+	test_when_finished 'rm "$pwd/trace.perf"' &&
+	GIT_TRACE2_PERF="$pwd/trace.perf" git "$@" rev-parse --git-dir &&
+	# Note: we're intentionally only checking that the bare repo has a
+	# directory *prefix* of $pwd
+	grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf"
+}
+
+expect_accepted_explicit () {
+	test_when_finished 'rm "$pwd/trace.perf"' &&
+	GIT_DIR="$1" GIT_TRACE2_PERF="$pwd/trace.perf" git rev-parse --git-dir &&
+	! grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf"
 }
 
 expect_rejected () {
-	test_must_fail git "$@" rev-parse --git-dir 2>err &&
-	grep -F "cannot use bare repository" err
+	test_when_finished 'rm "$pwd/trace.perf"' &&
+	test_env GIT_TRACE2_PERF="$pwd/trace.perf" \
+		test_must_fail git "$@" rev-parse --git-dir 2>err &&
+	grep -F "cannot use bare repository" err &&
+	grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf"
 }
 
 test_expect_success 'setup bare repo in worktree' '
@@ -22,12 +35,13 @@
 '
 
 test_expect_success 'safe.bareRepository unset' '
-	expect_accepted -C outer-repo/bare-repo
+	test_unconfig --global safe.bareRepository &&
+	expect_accepted_implicit -C outer-repo/bare-repo
 '
 
 test_expect_success 'safe.bareRepository=all' '
 	test_config_global safe.bareRepository all &&
-	expect_accepted -C outer-repo/bare-repo
+	expect_accepted_implicit -C outer-repo/bare-repo
 '
 
 test_expect_success 'safe.bareRepository=explicit' '
@@ -47,7 +61,7 @@
 
 test_expect_success 'safe.bareRepository on the command line' '
 	test_config_global safe.bareRepository explicit &&
-	expect_accepted -C outer-repo/bare-repo \
+	expect_accepted_implicit -C outer-repo/bare-repo \
 		-c safe.bareRepository=all
 '
 
@@ -60,4 +74,8 @@
 	expect_rejected -C outer-repo/bare-repo
 '
 
+test_expect_success 'no trace when GIT_DIR is explicitly provided' '
+	expect_accepted_explicit "$pwd/outer-repo/bare-repo"
+'
+
 test_done
diff --git a/t/t0055-beyond-symlinks.sh b/t/t0055-beyond-symlinks.sh
index 6bada37..c3eb115 100755
--- a/t/t0055-beyond-symlinks.sh
+++ b/t/t0055-beyond-symlinks.sh
@@ -15,12 +15,22 @@
 
 test_expect_success SYMLINKS 'update-index --add beyond symlinks' '
 	test_must_fail git update-index --add c/d &&
-	! ( git ls-files | grep c/d )
+	cat >expect <<-\EOF &&
+	a
+	b/d
+	EOF
+	git ls-files >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success SYMLINKS 'add beyond symlinks' '
 	test_must_fail git add c/d &&
-	! ( git ls-files | grep c/d )
+	cat >expect <<-\EOF &&
+	a
+	b/d
+	EOF
+	git ls-files >actual &&
+	test_cmp expect actual
 '
 
 test_done
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 68e29c9..0afa3d0 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -10,20 +10,27 @@
 
 norm_path() {
 	expected=$(test-tool path-utils print_path "$2")
-	test_expect_success $3 "normalize path: $1 => $2" \
-	"test \"\$(test-tool path-utils normalize_path_copy '$1')\" = '$expected'"
+	test_expect_success $3 "normalize path: $1 => $2" "
+		echo '$expected' >expect &&
+		test-tool path-utils normalize_path_copy '$1' >actual &&
+		test_cmp expect actual
+	"
 }
 
 relative_path() {
 	expected=$(test-tool path-utils print_path "$3")
-	test_expect_success $4 "relative path: $1 $2 => $3" \
-	"test \"\$(test-tool path-utils relative_path '$1' '$2')\" = '$expected'"
+	test_expect_success $4 "relative path: $1 $2 => $3" "
+		echo '$expected' >expect &&
+		test-tool path-utils relative_path '$1' '$2' >actual &&
+		test_cmp expect actual
+	"
 }
 
 test_submodule_relative_url() {
 	test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" "
-		actual=\$(test-tool submodule resolve-relative-url '$1' '$2' '$3') &&
-		test \"\$actual\" = '$4'
+		echo '$4' >expect &&
+		test-tool submodule resolve-relative-url '$1' '$2' '$3' >actual &&
+		test_cmp expect actual
 	"
 }
 
@@ -64,9 +71,11 @@
 		expected=$(($expected-$rootslash+$rootoff))
 		;;
 	esac
-	test_expect_success $4 "longest ancestor: $1 $2 => $expected" \
-	"actual=\$(test-tool path-utils longest_ancestor_length '$1' '$2') &&
-	 test \"\$actual\" = '$expected'"
+	test_expect_success $4 "longest ancestor: $1 $2 => $expected" "
+		echo '$expected' >expect &&
+		test-tool path-utils longest_ancestor_length '$1' '$2' >actual &&
+		test_cmp expect actual
+	"
 }
 
 # Some absolute path tests should be skipped on Windows due to path mangling
@@ -166,8 +175,10 @@
 ancestor //server/share/my-directory //server/share/ 14 MINGW
 
 test_expect_success 'strip_path_suffix' '
-	test c:/msysgit = $(test-tool path-utils strip_path_suffix \
-		c:/msysgit/libexec//git-core libexec/git-core)
+	echo c:/msysgit >expect &&
+	test-tool path-utils strip_path_suffix \
+		c:/msysgit/libexec//git-core libexec/git-core >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'absolute path rejects the empty string' '
@@ -188,35 +199,61 @@
 '
 
 test_expect_success POSIX 'real path works on absolute paths 1' '
+	echo / >expect &&
+	test-tool path-utils real_path "/" >actual &&
+	test_cmp expect actual &&
+
 	nopath="hopefully-absent-path" &&
-	test "/" = "$(test-tool path-utils real_path "/")" &&
-	test "/$nopath" = "$(test-tool path-utils real_path "/$nopath")"
+	echo "/$nopath" >expect &&
+	test-tool path-utils real_path "/$nopath" >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'real path works on absolute paths 2' '
-	nopath="hopefully-absent-path" &&
 	# Find an existing top-level directory for the remaining tests:
 	d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
-	test "$d" = "$(test-tool path-utils real_path "$d")" &&
-	test "$d/$nopath" = "$(test-tool path-utils real_path "$d/$nopath")"
+	echo "$d" >expect &&
+	test-tool path-utils real_path "$d" >actual &&
+	test_cmp expect actual &&
+
+	nopath="hopefully-absent-path" &&
+	echo "$d/$nopath" >expect &&
+	test-tool path-utils real_path "$d/$nopath" >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success POSIX 'real path removes extra leading slashes' '
+	echo "/" >expect &&
+	test-tool path-utils real_path "///" >actual &&
+	test_cmp expect actual &&
+
 	nopath="hopefully-absent-path" &&
-	test "/" = "$(test-tool path-utils real_path "///")" &&
-	test "/$nopath" = "$(test-tool path-utils real_path "///$nopath")" &&
+	echo "/$nopath" >expect &&
+	test-tool path-utils real_path "///$nopath" >actual &&
+	test_cmp expect actual &&
+
 	# Find an existing top-level directory for the remaining tests:
 	d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
-	test "$d" = "$(test-tool path-utils real_path "//$d")" &&
-	test "$d/$nopath" = "$(test-tool path-utils real_path "//$d/$nopath")"
+	echo "$d" >expect &&
+	test-tool path-utils real_path "//$d" >actual &&
+	test_cmp expect actual &&
+
+	echo "$d/$nopath" >expect &&
+	test-tool path-utils real_path "//$d/$nopath" >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'real path removes other extra slashes' '
-	nopath="hopefully-absent-path" &&
 	# Find an existing top-level directory for the remaining tests:
 	d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
-	test "$d" = "$(test-tool path-utils real_path "$d///")" &&
-	test "$d/$nopath" = "$(test-tool path-utils real_path "$d///$nopath")"
+	echo "$d" >expect &&
+	test-tool path-utils real_path "$d///" >actual &&
+	test_cmp expect actual &&
+
+	nopath="hopefully-absent-path" &&
+	echo "$d/$nopath" >expect &&
+	test-tool path-utils real_path "$d///$nopath" >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success SYMLINKS 'real path works on symlinks' '
@@ -227,19 +264,29 @@
 	mkdir third &&
 	dir="$(cd .git && pwd -P)" &&
 	dir2=third/../second/other/.git &&
-	test "$dir" = "$(test-tool path-utils real_path $dir2)" &&
+	echo "$dir" >expect &&
+	test-tool path-utils real_path $dir2 >actual &&
+	test_cmp expect actual &&
 	file="$dir"/index &&
-	test "$file" = "$(test-tool path-utils real_path $dir2/index)" &&
+	echo "$file" >expect &&
+	test-tool path-utils real_path $dir2/index >actual &&
+	test_cmp expect actual &&
 	basename=blub &&
-	test "$dir/$basename" = "$(cd .git && test-tool path-utils real_path "$basename")" &&
+	echo "$dir/$basename" >expect &&
+	test-tool -C .git path-utils real_path "$basename" >actual &&
+	test_cmp expect actual &&
 	ln -s ../first/file .git/syml &&
 	sym="$(cd first && pwd -P)"/file &&
-	test "$sym" = "$(test-tool path-utils real_path "$dir2/syml")"
+	echo "$sym" >expect &&
+	test-tool path-utils real_path "$dir2/syml" >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success SYMLINKS 'prefix_path works with absolute paths to work tree symlinks' '
 	ln -s target symlink &&
-	test "$(test-tool path-utils prefix_path prefix "$(pwd)/symlink")" = "symlink"
+	echo "symlink" >expect &&
+	test-tool path-utils prefix_path prefix "$(pwd)/symlink" >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'prefix_path works with only absolute path to work tree' '
@@ -255,7 +302,10 @@
 test_expect_success SYMLINKS 'prefix_path works with absolute path to a symlink to work tree having  same beginning as work tree' '
 	git init repo &&
 	ln -s repo repolink &&
-	test "a" = "$(cd repo && test-tool path-utils prefix_path prefix "$(pwd)/../repolink/a")"
+	echo "a" >expect &&
+	repo_path="$(cd repo && pwd)" &&
+	test-tool -C repo path-utils prefix_path prefix "$repo_path/../repolink/a" >actual &&
+	test_cmp expect actual
 '
 
 relative_path /foo/a/b/c/	/foo/a/b/	c/
diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh
index 46d4839..1fee6d9 100755
--- a/t/t0063-string-list.sh
+++ b/t/t0063-string-list.sh
@@ -18,6 +18,14 @@
 	"
 }
 
+test_split_in_place() {
+	cat >expected &&
+	test_expect_success "split (in place) $1 at $2, max $3" "
+		test-tool string-list split_in_place '$1' '$2' '$3' >actual &&
+		test_cmp expected actual
+	"
+}
+
 test_split "foo:bar:baz" ":" "-1" <<EOF
 3
 [0]: "foo"
@@ -61,6 +69,49 @@
 [1]: ""
 EOF
 
+test_split_in_place "foo:;:bar:;:baz:;:" ":;" "-1" <<EOF
+10
+[0]: "foo"
+[1]: ""
+[2]: ""
+[3]: "bar"
+[4]: ""
+[5]: ""
+[6]: "baz"
+[7]: ""
+[8]: ""
+[9]: ""
+EOF
+
+test_split_in_place "foo:;:bar:;:baz" ":;" "0" <<EOF
+1
+[0]: "foo:;:bar:;:baz"
+EOF
+
+test_split_in_place "foo:;:bar:;:baz" ":;" "1" <<EOF
+2
+[0]: "foo"
+[1]: ";:bar:;:baz"
+EOF
+
+test_split_in_place "foo:;:bar:;:baz" ":;" "2" <<EOF
+3
+[0]: "foo"
+[1]: ""
+[2]: ":bar:;:baz"
+EOF
+
+test_split_in_place "foo:;:bar:;:" ":;" "-1" <<EOF
+7
+[0]: "foo"
+[1]: ""
+[2]: ""
+[3]: "bar"
+[4]: ""
+[5]: ""
+[6]: ""
+EOF
+
 test_expect_success "test filter_string_list" '
 	test "x-" = "x$(test-tool string-list filter - y)" &&
 	test "x-" = "x$(test-tool string-list filter no y)" &&
diff --git a/t/t0068-for-each-repo.sh b/t/t0068-for-each-repo.sh
index 3648d43..4b90b74 100755
--- a/t/t0068-for-each-repo.sh
+++ b/t/t0068-for-each-repo.sh
@@ -40,4 +40,23 @@
 	git for-each-repo --config=bogus.config -- help --no-such-option
 '
 
+test_expect_success 'error on bad config keys' '
+	test_expect_code 129 git for-each-repo --config=a &&
+	test_expect_code 129 git for-each-repo --config=a.b. &&
+	test_expect_code 129 git for-each-repo --config="'\''.b"
+'
+
+test_expect_success 'error on NULL value for config keys' '
+	cat >>.git/config <<-\EOF &&
+	[empty]
+		key
+	EOF
+	cat >expect <<-\EOF &&
+	error: missing value for '\''empty.key'\''
+	EOF
+	test_expect_code 129 git for-each-repo --config=empty.key 2>actual.raw &&
+	grep ^error actual.raw >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t0100-previous.sh b/t/t0100-previous.sh
index a16cc3d..70a3223 100755
--- a/t/t0100-previous.sh
+++ b/t/t0100-previous.sh
@@ -12,7 +12,9 @@
 	test_commit A &&
 	git checkout -b junk &&
 	git checkout - &&
-	test "$(git symbolic-ref HEAD)" = refs/heads/main &&
+	echo refs/heads/main >expect &&
+	git symbolic-ref HEAD >actual &&
+	test_cmp expect actual &&
 	git branch -d @{-1} &&
 	test_must_fail git rev-parse --verify refs/heads/junk
 '
@@ -21,7 +23,9 @@
 	git reflog expire --expire=now &&
 	git checkout -b junk2 &&
 	git checkout - &&
-	test "$(git symbolic-ref HEAD)" = refs/heads/main &&
+	echo refs/heads/main >expect &&
+	git symbolic-ref HEAD >actual &&
+	test_cmp expect actual &&
 	test_must_fail git branch -d @{-12} &&
 	git rev-parse --verify refs/heads/main
 '
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index c66d91e..a4f5bba 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -214,6 +214,24 @@
 	EOF
 '
 
+test_expect_success 'credential_approve stores oauth refresh token' '
+	check approve useless <<-\EOF
+	protocol=http
+	host=example.com
+	username=foo
+	password=bar
+	oauth_refresh_token=xyzzy
+	--
+	--
+	useless: store
+	useless: protocol=http
+	useless: host=example.com
+	useless: username=foo
+	useless: password=bar
+	useless: oauth_refresh_token=xyzzy
+	EOF
+'
+
 test_expect_success 'do not bother storing password-less credential' '
 	check approve useless <<-\EOF
 	protocol=http
@@ -808,7 +826,7 @@
 
 	git -c credential.$partial.helper=yep \
 		-c credential.with%0anewline.username=uh-oh \
-		credential fill <stdin >stdout 2>stderr &&
+		credential fill <stdin 2>stderr &&
 	test_i18ngrep "skipping credential lookup for key" stderr
 '
 
diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh
index 698b715..c02a3b5 100755
--- a/t/t0301-credential-cache.sh
+++ b/t/t0301-credential-cache.sh
@@ -29,6 +29,7 @@
 
 # test that the daemon works with no special setup
 helper_test cache
+helper_test_oauth_refresh_token cache
 
 test_expect_success 'socket defaults to ~/.cache/git/credential/socket' '
 	test_when_finished "
diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh
index 12e30d7..26be4a2 100755
--- a/t/t1005-read-tree-reset.sh
+++ b/t/t1005-read-tree-reset.sh
@@ -41,7 +41,8 @@
 	git ls-files -s &&
 	read_tree_u_must_succeed --reset -u HEAD &&
 	git ls-files -s >actual &&
-	! test -f old
+	! test -f old &&
+	test_cmp expect actual
 '
 
 test_expect_success 'two-way reset should remove remnants too' '
@@ -56,7 +57,8 @@
 	git ls-files -s &&
 	read_tree_u_must_succeed --reset -u HEAD HEAD &&
 	git ls-files -s >actual &&
-	! test -f old
+	! test -f old &&
+	test_cmp expect actual
 '
 
 test_expect_success 'Porcelain reset should remove remnants too' '
@@ -71,7 +73,8 @@
 	git ls-files -s &&
 	git reset --hard &&
 	git ls-files -s >actual &&
-	! test -f old
+	! test -f old &&
+	test_cmp expect actual
 '
 
 test_expect_success 'Porcelain checkout -f should remove remnants too' '
@@ -86,7 +89,8 @@
 	git ls-files -s &&
 	git checkout -f &&
 	git ls-files -s >actual &&
-	! test -f old
+	! test -f old &&
+	test_cmp expect actual
 '
 
 test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '
@@ -101,7 +105,8 @@
 	git ls-files -s &&
 	git checkout -f HEAD &&
 	git ls-files -s >actual &&
-	! test -f old
+	! test -f old &&
+	test_cmp expect actual
 '
 
 test_done
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 2d875b1..8eac74b 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -603,7 +603,8 @@
 			fatal: Not a valid object name $(test_oid deadbeef_short)
 			EOF
 			test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef_short) >out 2>err.actual &&
-			test_must_be_empty out
+			test_must_be_empty out &&
+			test_cmp expect.err err.actual
 		'
 
 		test_expect_success "cat-file $arg1 $arg2 error on missing full OID" '
diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh
index 3c08194..22875ba 100755
--- a/t/t1010-mktree.sh
+++ b/t/t1010-mktree.sh
@@ -60,11 +60,11 @@
 '
 
 test_expect_success 'mktree refuses to read ls-tree -r output (1)' '
-	test_must_fail git mktree <all >actual
+	test_must_fail git mktree <all
 '
 
 test_expect_success 'mktree refuses to read ls-tree -r output (2)' '
-	test_must_fail git mktree <all.withsub >actual
+	test_must_fail git mktree <all.withsub
 '
 
 test_done
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index 627267b..9ceb17f 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -555,7 +555,7 @@
 	check_files repo a folder1
 '
 
-test_expect_success 'interaction with submodules' '
+test_expect_success 'setup submodules' '
 	git clone repo super &&
 	(
 		cd super &&
@@ -566,11 +566,22 @@
 		git commit -m "add submodule" &&
 		git sparse-checkout init --cone &&
 		git sparse-checkout set folder1
-	) &&
+	)
+'
+
+test_expect_success 'interaction with submodules' '
 	check_files super a folder1 modules &&
 	check_files super/modules/child a deep folder1 folder2
 '
 
+test_expect_success 'check-rules interaction with submodules' '
+	git -C super ls-tree --name-only -r HEAD >all-files &&
+	git -C super sparse-checkout check-rules >check-rules-matches <all-files &&
+
+	test_i18ngrep ! "modules/" check-rules-matches &&
+	test_i18ngrep "folder1/" check-rules-matches
+'
+
 test_expect_success 'different sparse-checkouts with worktrees' '
 	git -C repo sparse-checkout set --cone deep folder1 &&
 	git -C repo worktree add --detach ../worktree &&
@@ -882,4 +893,156 @@
 	grep "pass a leading slash before paths.*if you want a single file" warning
 '
 
+test_expect_success 'setup bare repo' '
+	git clone --bare "file://$(pwd)/repo" bare
+'
+test_expect_success 'list fails outside work tree' '
+	test_must_fail git -C bare sparse-checkout list 2>err &&
+	test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'add fails outside work tree' '
+	test_must_fail git -C bare sparse-checkout add deeper 2>err &&
+	test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'set fails outside work tree' '
+	test_must_fail git -C bare sparse-checkout set deeper 2>err &&
+	test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'init fails outside work tree' '
+	test_must_fail git -C bare sparse-checkout init 2>err &&
+	test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'reapply fails outside work tree' '
+	test_must_fail git -C bare sparse-checkout reapply 2>err &&
+	test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'disable fails outside work tree' '
+	test_must_fail git -C bare sparse-checkout disable 2>err &&
+	test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'setup clean' '
+	git -C repo clean -fdx
+'
+
+test_expect_success 'check-rules cone mode' '
+	cat >rules <<-\EOF &&
+	folder1
+	deep/deeper1/deepest
+	EOF
+
+	git -C bare ls-tree -r --name-only HEAD >all-files &&
+	git -C bare sparse-checkout check-rules --cone \
+		--rules-file ../rules >check-rules-file <all-files &&
+
+	git -C repo sparse-checkout set --cone --stdin <rules&&
+	git -C repo ls-files -t >out &&
+	sed -n "/^S /!s/^. //p" out >ls-files &&
+
+	git -C repo sparse-checkout check-rules >check-rules-default <all-files &&
+
+	test_i18ngrep "deep/deeper1/deepest/a" check-rules-file &&
+	test_i18ngrep ! "deep/deeper2" check-rules-file &&
+
+	test_cmp check-rules-file ls-files &&
+	test_cmp check-rules-file check-rules-default
+'
+
+test_expect_success 'check-rules non-cone mode' '
+	cat >rules <<-\EOF &&
+	deep/deeper1/deepest/a
+	EOF
+
+	git -C bare ls-tree -r --name-only HEAD >all-files &&
+	git -C bare sparse-checkout check-rules --no-cone --rules-file ../rules\
+		>check-rules-file <all-files &&
+
+	cat rules | git -C repo sparse-checkout set --no-cone --stdin &&
+	git -C repo ls-files -t >out &&
+	sed -n "/^S /!s/^. //p" out >ls-files &&
+
+	git -C repo sparse-checkout check-rules >check-rules-default <all-files &&
+
+	cat >expect <<-\EOF &&
+	deep/deeper1/deepest/a
+	EOF
+
+	test_cmp expect check-rules-file &&
+	test_cmp check-rules-file ls-files &&
+	test_cmp check-rules-file check-rules-default
+'
+
+test_expect_success 'check-rules cone mode is default' '
+	cat >rules <<-\EOF &&
+	folder1
+	EOF
+
+	cat >all-files <<-\EOF &&
+	toplevel
+	folder2/file
+	folder1/file
+	EOF
+
+	cat >expect <<-\EOF &&
+	toplevel
+	folder1/file
+	EOF
+
+	git -C repo sparse-checkout set --no-cone &&
+	git -C repo sparse-checkout check-rules \
+		--rules-file ../rules >actual <all-files &&
+
+	git -C bare sparse-checkout check-rules \
+		--rules-file ../rules >actual-bare <all-files &&
+
+	test_cmp expect actual &&
+	test_cmp expect actual-bare
+'
+
+test_expect_success 'check-rules quoting' '
+	cat >rules <<-EOF &&
+	"folder\" a"
+	EOF
+	cat >files <<-EOF &&
+	"folder\" a/file"
+	"folder\" b/file"
+	EOF
+	cat >expect <<-EOF &&
+	"folder\" a/file"
+	EOF
+	git sparse-checkout check-rules --cone \
+		--rules-file rules >actual <files &&
+
+	test_cmp expect actual
+'
+
+test_expect_success 'check-rules null termination' '
+	cat >rules <<-EOF &&
+	"folder\" a"
+	EOF
+
+	lf_to_nul >files <<-EOF &&
+	folder" a/a
+	folder" a/b
+	folder" b/fileQ
+	EOF
+
+	cat >expect <<-EOF &&
+	folder" a/aQfolder" a/bQ
+	EOF
+
+	git sparse-checkout check-rules --cone -z \
+		--rules-file rules >actual.nul <files &&
+	nul_to_q <actual.nul >actual &&
+	echo >>actual &&
+
+	test_cmp expect actual
+'
+
+
 test_done
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 8019190..a63d0cc 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -1377,7 +1377,7 @@
 	! test_region index ensure_full_index trace2.txt
 '
 
-ensure_not_expanded () {
+run_sparse_index_trace2 () {
 	rm -f trace2.txt &&
 	if test -z "$WITHOUT_UNTRACKED_TXT"
 	then
@@ -1397,7 +1397,16 @@
 			git -C sparse-index "$@" \
 			>sparse-index-out \
 			2>sparse-index-error || return 1
-	fi &&
+	fi
+}
+
+ensure_expanded () {
+	run_sparse_index_trace2 "$@" &&
+	test_region index ensure_full_index trace2.txt
+}
+
+ensure_not_expanded () {
+	run_sparse_index_trace2 "$@" &&
 	test_region ! index ensure_full_index trace2.txt
 }
 
@@ -1514,6 +1523,31 @@
 	ensure_not_expanded stash pop
 '
 
+test_expect_success 'describe tested on all' '
+	init_repos &&
+
+	# Add tag to be read by describe
+
+	run_on_all git tag -a v1.0 -m "Version 1" &&
+	test_all_match git describe --dirty &&
+	run_on_all rm g &&
+	test_all_match git describe --dirty
+'
+
+
+test_expect_success 'sparse-index is not expanded: describe' '
+	init_repos &&
+
+	# Add tag to be read by describe
+
+	git -C sparse-index tag -a v1.0 -m "Version 1" &&
+
+	ensure_not_expanded describe --dirty &&
+	echo "test" >>sparse-index/g &&
+	ensure_not_expanded describe --dirty &&
+	ensure_not_expanded describe
+'
+
 test_expect_success 'sparse index is not expanded: diff' '
 	init_repos &&
 
@@ -2055,4 +2089,95 @@
 	test_cmp actual expect
 '
 
+test_expect_success 'write-tree' '
+	init_repos &&
+
+	test_all_match git write-tree &&
+
+	write_script edit-contents <<-\EOF &&
+	echo text >>"$1"
+	EOF
+
+	# make a change inside the sparse cone
+	run_on_all ../edit-contents deep/a &&
+	test_all_match git update-index deep/a &&
+	test_all_match git write-tree &&
+	test_all_match git status --porcelain=v2 &&
+
+	# make a change outside the sparse cone
+	run_on_all mkdir -p folder1 &&
+	run_on_all cp a folder1/a &&
+	run_on_all ../edit-contents folder1/a &&
+	test_all_match git update-index folder1/a &&
+	test_all_match git write-tree &&
+	test_all_match git status --porcelain=v2 &&
+
+	# check that SKIP_WORKTREE files are not materialized
+	test_path_is_missing sparse-checkout/folder2/a &&
+	test_path_is_missing sparse-index/folder2/a
+'
+
+test_expect_success 'sparse-index is not expanded: write-tree' '
+	init_repos &&
+
+	ensure_not_expanded write-tree &&
+
+	echo "test1" >>sparse-index/a &&
+	git -C sparse-index update-index a &&
+	ensure_not_expanded write-tree
+'
+
+test_expect_success 'diff-files with pathspec inside sparse definition' '
+	init_repos &&
+
+	write_script edit-contents <<-\EOF &&
+	echo text >>"$1"
+	EOF
+
+	run_on_all ../edit-contents deep/a &&
+
+	test_all_match git diff-files &&
+
+	test_all_match git diff-files -- deep/a &&
+
+	# test wildcard
+	test_all_match git diff-files -- "deep/*"
+'
+
+test_expect_success 'diff-files with pathspec outside sparse definition' '
+	init_repos &&
+
+	test_sparse_match git diff-files -- folder2/a &&
+
+	write_script edit-contents <<-\EOF &&
+	echo text >>"$1"
+	EOF
+
+	# The directory "folder1" is outside the cone of interest
+	# and will not exist in the sparse checkout repositories.
+	# Create it as needed, add file "folder1/a" there with
+	# contents that is different from the staged version.
+	run_on_all mkdir -p folder1 &&
+	run_on_all cp a folder1/a &&
+
+	run_on_all ../edit-contents folder1/a &&
+	test_all_match git diff-files &&
+	test_all_match git diff-files -- folder1/a &&
+	test_all_match git diff-files -- "folder*/a"
+'
+
+test_expect_success 'sparse index is not expanded: diff-files' '
+	init_repos &&
+
+	write_script edit-contents <<-\EOF &&
+	echo text >>"$1"
+	EOF
+
+	run_on_all ../edit-contents deep/a &&
+
+	ensure_not_expanded diff-files &&
+	ensure_not_expanded diff-files -- deep/a &&
+	ensure_not_expanded diff-files -- "deep/*"
+'
+
 test_done
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 2575279..86bfbc2 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -98,6 +98,23 @@
 	test_cmp_config two section.SubSection.key
 '
 
+test_missing_key () {
+	local key="$1" &&
+	local title="$2" &&
+	test_expect_success "value for $title is not printed" '
+		test_must_fail git config "$key" >out 2>err &&
+		test_must_be_empty out &&
+		test_must_be_empty err
+	'
+}
+
+test_missing_key 'missingsection.missingkey' 'missing section and missing key'
+test_missing_key 'missingsection.penguin' 'missing section and existing key'
+test_missing_key 'section.missingkey' 'existing section and missing key'
+test_missing_key 'section.MissingSubSection.missingkey' 'missing subsection and missing key'
+test_missing_key 'section.SubSection.missingkey' 'existing subsection and missing key'
+test_missing_key 'section.MissingSubSection.key' 'missing subsection and existing key'
+
 cat > .git/config <<\EOF
 [alpha]
 bar = foo
@@ -617,6 +634,36 @@
 	test_must_fail git config --rename-section branch.zwei "bogus name"
 '
 
+test_expect_success 'renaming a section with a long line' '
+	{
+		printf "[b]\\n" &&
+		printf "  c = d %1024s [a] e = f\\n" " " &&
+		printf "[a] g = h\\n"
+	} >y &&
+	git config -f y --rename-section a xyz &&
+	test_must_fail git config -f y b.e
+'
+
+test_expect_success 'renaming an embedded section with a long line' '
+	{
+		printf "[b]\\n" &&
+		printf "  c = d %1024s [a] [foo] e = f\\n" " " &&
+		printf "[a] g = h\\n"
+	} >y &&
+	git config -f y --rename-section a xyz &&
+	test_must_fail git config -f y foo.e
+'
+
+test_expect_success 'renaming a section with an overly-long line' '
+	{
+		printf "[b]\\n" &&
+		printf "  c = d %525000s e" " " &&
+		printf "[a] g = h\\n"
+	} >y &&
+	test_must_fail git config -f y --rename-section a xyz 2>err &&
+	grep "refusing to work with overly long line in .y. on line 2" err
+'
+
 cat >> .git/config << EOF
   [branch "zwei"] a = 1 [branch "vier"]
 EOF
@@ -1458,35 +1505,29 @@
 	test_must_be_empty error
 '
 
-test_expect_success 'git config ignores pairs with zero count' '
-	test_must_fail env \
-		GIT_CONFIG_COUNT=0 \
-		GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
-		git config pair.one
-'
-
 test_expect_success 'git config ignores pairs exceeding count' '
 	GIT_CONFIG_COUNT=1 \
 		GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
 		GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="value" \
-		git config --get-regexp "pair.*" >actual &&
+		git config --get-regexp "pair.*" >actual 2>error &&
 	cat >expect <<-EOF &&
 	pair.one value
 	EOF
-	test_cmp expect actual
+	test_cmp expect actual &&
+	test_must_be_empty error
 '
 
 test_expect_success 'git config ignores pairs with zero count' '
 	test_must_fail env \
 		GIT_CONFIG_COUNT=0 GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
-		git config pair.one >error &&
+		git config pair.one 2>error &&
 	test_must_be_empty error
 '
 
 test_expect_success 'git config ignores pairs with empty count' '
 	test_must_fail env \
 		GIT_CONFIG_COUNT= GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
-		git config pair.one >error &&
+		git config pair.one 2>error &&
 	test_must_be_empty error
 '
 
@@ -1571,11 +1612,11 @@
 # malformed configuration files
 test_expect_success 'barf on syntax error' '
 	cat >.git/config <<-\EOF &&
-	# broken section line
+	# broken key=value
 	[section]
 	key garbage
 	EOF
-	test_must_fail git config --get section.key >actual 2>error &&
+	test_must_fail git config --get section.key 2>error &&
 	test_i18ngrep " line 3 " error
 '
 
@@ -1585,17 +1626,17 @@
 	[section
 	key = value
 	EOF
-	test_must_fail git config --get section.key >actual 2>error &&
+	test_must_fail git config --get section.key 2>error &&
 	test_i18ngrep " line 2 " error
 '
 
 test_expect_success 'barf on incomplete string' '
 	cat >.git/config <<-\EOF &&
-	# broken section line
+	# broken value string
 	[section]
 	key = "value string
 	EOF
-	test_must_fail git config --get section.key >actual 2>error &&
+	test_must_fail git config --get section.key 2>error &&
 	test_i18ngrep " line 3 " error
 '
 
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 1b6437e..ae5cd3f 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -89,7 +89,7 @@
 		rm -f .git/info/refs &&
 		git update-server-info &&
 		actual="$(test_modebits .git/info/refs)" &&
-		verbose test "x$actual" = "x-$y"
+		test "x$actual" = "x-$y"
 
 	'
 
@@ -99,7 +99,7 @@
 		rm -f .git/info/refs &&
 		git update-server-info &&
 		actual="$(test_modebits .git/info/refs)" &&
-		verbose test "x$actual" = "x-$x"
+		test "x$actual" = "x-$x"
 
 	'
 
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 70389fa..179474f 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -37,7 +37,7 @@
 
 test_expect_success 'gitdir selection on unsupported repo' '
 	# Make sure it would stop at test2, not trash
-	test_expect_code 1 git -C test2 config core.repositoryformatversion >actual
+	test_expect_code 1 git -C test2 config core.repositoryformatversion
 '
 
 test_expect_success 'gitdir not required mode' '
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index b38e158..7776487 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -58,6 +58,8 @@
 		skin = false
 		nose = 1
 		horns
+	[value]
+		less
 	EOF
 '
 
@@ -116,10 +118,53 @@
 	check_config get_value case.baz "hask"
 '
 
+test_expect_success 'return value for an existing key' '
+	test-tool config get lamb.chop >out 2>err &&
+	test_must_be_empty out &&
+	test_must_be_empty err
+'
+
+test_expect_success 'return value for value-less key' '
+	test-tool config get value.less >out 2>err &&
+	test_must_be_empty out &&
+	test_must_be_empty err
+'
+
+test_expect_success 'return value for a missing key' '
+	cat >expect <<-\EOF &&
+	Value not found for "missing.key"
+	EOF
+	test_expect_code 1 test-tool config get missing.key >actual 2>err &&
+	test_cmp actual expect &&
+	test_must_be_empty err
+'
+
+test_expect_success 'return value for a bad key: CONFIG_INVALID_KEY' '
+	cat >expect <<-\EOF &&
+	Key "fails.iskeychar.-" is invalid
+	EOF
+	test_expect_code 1 test-tool config get fails.iskeychar.- >actual 2>err &&
+	test_cmp actual expect &&
+	test_must_be_empty out
+'
+
+test_expect_success 'return value for a bad key: CONFIG_NO_SECTION_OR_NAME' '
+	cat >expect <<-\EOF &&
+	Key "keynosection" has no section
+	EOF
+	test_expect_code 1 test-tool config get keynosection >actual 2>err &&
+	test_cmp actual expect &&
+	test_must_be_empty out
+'
+
 test_expect_success 'find integer value for a key' '
 	check_config get_int lamb.chop 65
 '
 
+test_expect_success 'parse integer value during iteration' '
+	check_config git_config_int lamb.chop 65
+'
+
 test_expect_success 'find string value for a key' '
 	check_config get_string case.baz hask &&
 	check_config expect_code 1 get_string case.ba "Value not found for \"case.ba\""
@@ -134,6 +179,11 @@
 	check_config expect_code 128 get_int lamb.head
 '
 
+test_expect_success 'non parse-able integer value during iteration' '
+	check_config expect_code 128 git_config_int lamb.head 2>result &&
+	grep "fatal: bad numeric config value .* in file \.git/config" result
+'
+
 test_expect_success 'find bool value for the entered key' '
 	check_config get_bool goat.head 1 &&
 	check_config get_bool goat.skin 0 &&
@@ -146,6 +196,71 @@
 	check_config get_value_multi case.baz sam bat hask
 '
 
+test_NULL_in_multi () {
+	local op="$1" &&
+	local file="$2" &&
+
+	test_expect_success "$op: NULL value in config${file:+ in $file}" '
+		config="$file" &&
+		if test -z "$config"
+		then
+			config=.git/config &&
+			test_when_finished "mv $config.old $config" &&
+			mv "$config" "$config".old
+		fi &&
+
+		# Value-less in the middle of a list
+		cat >"$config" <<-\EOF &&
+		[a]key=x
+		[a]key
+		[a]key=y
+		EOF
+		case "$op" in
+		*_multi)
+			cat >expect <<-\EOF
+			x
+			(NULL)
+			y
+			EOF
+			;;
+		*)
+			cat >expect <<-\EOF
+			y
+			EOF
+			;;
+		esac &&
+		test-tool config "$op" a.key $file >actual &&
+		test_cmp expect actual &&
+
+		# Value-less at the end of a least
+		cat >"$config" <<-\EOF &&
+		[a]key=x
+		[a]key=y
+		[a]key
+		EOF
+		case "$op" in
+		*_multi)
+			cat >expect <<-\EOF
+			x
+			y
+			(NULL)
+			EOF
+			;;
+		*)
+			cat >expect <<-\EOF
+			(NULL)
+			EOF
+			;;
+		esac &&
+		test-tool config "$op" a.key $file >actual &&
+		test_cmp expect actual
+	'
+}
+
+test_NULL_in_multi "get_value_multi"
+test_NULL_in_multi "configset_get_value" "my.config"
+test_NULL_in_multi "configset_get_value_multi" "my.config"
+
 test_expect_success 'find value from a configset' '
 	cat >config2 <<-\EOF &&
 	[case]
@@ -207,7 +322,7 @@
 	cp .git/config .git/config.old &&
 	test_when_finished "mv .git/config.old .git/config" &&
 	echo "[" >>.git/config &&
-	echo "fatal: bad config line 34 in file .git/config" >expect &&
+	echo "fatal: bad config line 36 in file .git/config" >expect &&
 	test_expect_code 128 test-tool config get_value foo.bar 2>actual &&
 	test_cmp expect actual
 '
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index cf58cf0..4d66cd7 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -1568,6 +1568,7 @@
 	EOF
 	git update-ref --stdin <stdin >actual &&
 	printf "%s: ok\n" start commit start commit >expect &&
+	test_cmp expect actual &&
 	test_must_fail git show-ref --verify refs/heads/create-and-delete
 '
 
@@ -1595,6 +1596,8 @@
 	commit
 	EOF
 	test_must_fail git update-ref --stdin <stdin >actual &&
+	printf "%s: ok\n" start >expect &&
+	test_cmp expect actual &&
 	test_must_fail git show-ref --verify refs/heads/restart
 '
 
diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh
index be23be3..c7745e1 100755
--- a/t/t1401-symbolic-ref.sh
+++ b/t/t1401-symbolic-ref.sh
@@ -33,7 +33,8 @@
 reset_to_sane
 
 test_expect_success 'symbolic-ref refuses bare sha1' '
-	test_must_fail git symbolic-ref HEAD $(git rev-parse HEAD)
+	rev=$(git rev-parse HEAD) &&
+	test_must_fail git symbolic-ref HEAD "$rev"
 '
 
 reset_to_sane
diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh
index b5606d9..937ae0d 100755
--- a/t/t1404-update-ref-errors.sh
+++ b/t/t1404-update-ref-errors.sh
@@ -551,7 +551,6 @@
 	git update-ref $prefix/foo $C &&
 	git pack-refs --all &&
 	git update-ref $prefix/foo $D &&
-	git for-each-ref $prefix >unchanged &&
 	# Now try to update the reference, but hold the `packed-refs` lock
 	# for a while to see what happens while the process is blocked:
 	: >.git/packed-refs.lock &&
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index fdb886d..8c442ad 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -989,10 +989,7 @@
 
 		garbage_blob=$(git hash-object --stdin -w -t garbage --literally </dev/null) &&
 
-		cat >err.expect <<-\EOF &&
-		fatal: invalid object type
-		EOF
-		test_must_fail git fsck >out 2>err &&
+		test_must_fail git fsck 2>err &&
 		grep -e "^error" -e "^fatal" err >errors &&
 		test_line_count = 1 errors &&
 		grep "$garbage_blob: object is of unknown type '"'"'garbage'"'"':" err
@@ -1023,4 +1020,34 @@
 	test_cmp expected actual
 '
 
+test_expect_success 'fsck detects problems in worktree index' '
+	test_when_finished "git worktree remove -f wt" &&
+	git worktree add wt &&
+
+	echo "this will be removed to break the worktree index" >wt/file &&
+	git -C wt add file &&
+	blob=$(git -C wt rev-parse :file) &&
+	remove_object $blob &&
+
+	test_must_fail git fsck --name-objects >actual 2>&1 &&
+	cat >expect <<-EOF &&
+	missing blob $blob (.git/worktrees/wt/index:file)
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'fsck reports problems in main index without filename' '
+	test_when_finished "rm -f .git/index && git read-tree HEAD" &&
+	echo "this object will be removed to break the main index" >file &&
+	git add file &&
+	blob=$(git rev-parse :file) &&
+	remove_object $blob &&
+
+	test_must_fail git fsck --name-objects >actual 2>&1 &&
+	cat >expect <<-EOF &&
+	missing blob $blob (:file)
+	EOF
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index de1d48f..dd811b7 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -302,14 +302,14 @@
 	|EOF
 	END_EXPECT
 
-	test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+	test_must_fail git rev-parse --parseopt -- -h <spec >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success 'test --parseopt invalid opt-spec' '
 	test_write_lines x -- "=, x" >spec &&
 	echo "fatal: missing opt-spec before option flags" >expect &&
-	test_must_fail git rev-parse --parseopt -- >out <spec 2>err &&
+	test_must_fail git rev-parse --parseopt -- <spec 2>err &&
 	test_cmp expect err
 '
 
@@ -339,7 +339,7 @@
 	|EOF
 	END_EXPECT
 
-	test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+	test_must_fail git rev-parse --parseopt -- -h <spec >actual &&
 	test_cmp expect actual
 '
 
diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh
index 0fafcf9..c1679e3 100755
--- a/t/t1504-ceiling-dirs.sh
+++ b/t/t1504-ceiling-dirs.sh
@@ -6,8 +6,12 @@
 . ./test-lib.sh
 
 test_prefix() {
-	test_expect_success "$1" \
-	"test '$2' = \"\$(git rev-parse --show-prefix)\""
+	local expect="$2" &&
+	test_expect_success "$1: git rev-parse --show-prefix is '$2'" '
+		echo "$expect" >expect &&
+		git rev-parse --show-prefix >actual &&
+		test_cmp expect actual
+	'
 }
 
 test_fail() {
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index c34714f..cb9ef7e 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -97,7 +97,8 @@
 	commit_subject my-side >actual &&
 	test_cmp expect actual &&
 	echo 5 >expect &&
-	commit_subject my-side@{u} >actual
+	commit_subject my-side@{u} >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'not-tracking@{u} fails' '
@@ -183,6 +184,11 @@
 	test_cmp expect actual
 '
 
+test_expect_success '@{u} silent error when no upstream' '
+	test_must_fail git rev-parse --verify --quiet @{u} 2>actual &&
+	test_must_be_empty actual
+'
+
 test_expect_success 'branch@{u} error message with misspelt branch' '
 	cat >expect <<-EOF &&
 	fatal: no such branch: ${SQ}no-such-branch${SQ}
@@ -258,7 +264,8 @@
 	git add @{yesterday} &&
 	git commit -m "funny reflog file" &&
 	git hash-object @{yesterday} >expect &&
-	git rev-parse HEAD:@{yesterday} >actual
+	git rev-parse HEAD:@{yesterday} >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success '@{upstream}-parsing does not look beyond colon' '
@@ -266,7 +273,8 @@
 	git add @{upstream} &&
 	git commit -m "funny upstream file" &&
 	git hash-object @{upstream} >expect &&
-	git rev-parse HEAD:@{upstream} >actual
+	git rev-parse HEAD:@{upstream} >actual &&
+	test_cmp expect actual
 '
 
 test_done
diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh
index 112682a..67d18cf 100755
--- a/t/t2005-checkout-index-symlinks.sh
+++ b/t/t2005-checkout-index-symlinks.sh
@@ -22,8 +22,10 @@
 git checkout-index symlink &&
 test -f symlink'
 
-test_expect_success \
-'the file must be the blob we added during the setup' '
-test "$(git hash-object -t blob symlink)" = $l'
+test_expect_success 'the file must be the blob we added during the setup' '
+	echo "$l" >expect &&
+	git hash-object -t blob symlink >actual &&
+	test_cmp expect actual
+'
 
 test_done
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
index 2c8c926..9540588 100755
--- a/t/t2019-checkout-ambiguous-ref.sh
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -16,7 +16,7 @@
 '
 
 test_expect_success 'checkout ambiguous ref succeeds' '
-	git checkout ambiguity >stdout 2>stderr
+	git checkout ambiguity 2>stderr
 '
 
 test_expect_success 'checkout produces ambiguity warning' '
@@ -37,7 +37,7 @@
 '
 
 test_expect_success 'checkout vague ref succeeds' '
-	git checkout vagueness >stdout 2>stderr &&
+	git checkout vagueness 2>stderr &&
 	test_set_prereq VAGUENESS_SUCCESS
 '
 
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
index 713c3fa..ecfacf0 100755
--- a/t/t2021-checkout-overwrite.sh
+++ b/t/t2021-checkout-overwrite.sh
@@ -50,10 +50,13 @@
 
 test_expect_success SYMLINKS 'the symlink remained' '
 
-	test_when_finished "rm a/b" &&
 	test -h a/b
 '
 
+test_expect_success 'cleanup after previous symlink tests' '
+	rm a/b
+'
+
 test_expect_success SYMLINKS 'checkout -f must not follow symlinks when removing entries' '
 	git checkout -f start &&
 	mkdir dir &&
@@ -66,4 +69,15 @@
 	test_path_is_file untracked/f
 '
 
+test_expect_success 'checkout --overwrite-ignore should succeed if only ignored files in the way' '
+	git checkout -b df_conflict &&
+	test_commit contents some_dir &&
+	git checkout start &&
+	mkdir some_dir &&
+	echo autogenerated information >some_dir/ignore &&
+	echo ignore >.git/info/exclude &&
+	git checkout --overwrite-ignore df_conflict &&
+	test_path_is_file some_dir
+'
+
 test_done
diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh
index 4a1c901..74049a9 100755
--- a/t/t2024-checkout-dwim.sh
+++ b/t/t2024-checkout-dwim.sh
@@ -305,10 +305,13 @@
 	test_config branch.strict.merge refs/heads/main &&
 	test_config branch.loose.merge main &&
 
-	git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect &&
+	git checkout strict >expect.raw 2>&1 &&
+	sed -e "s/strict/BRANCHNAME/g" <expect.raw >expect &&
 	status_uno_is_clean &&
-	git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual &&
+	git checkout loose >actual.raw 2>&1 &&
+	sed -e "s/loose/BRANCHNAME/g" <actual.raw >actual &&
 	status_uno_is_clean &&
+	grep BRANCHNAME actual &&
 
 	test_cmp expect actual
 '
diff --git a/t/t2060-switch.sh b/t/t2060-switch.sh
index 5a7caf9..e247a47 100755
--- a/t/t2060-switch.sh
+++ b/t/t2060-switch.sh
@@ -146,4 +146,33 @@
 	test_cmp_config "" --default "" branch.main2.merge
 '
 
+test_expect_success 'switch back when temporarily detached and checked out elsewhere ' '
+	test_when_finished "
+		git worktree remove wt1 ||:
+		git worktree remove wt2 ||:
+		git checkout - ||:
+		git branch -D shared ||:
+	" &&
+	git checkout -b shared &&
+	test_commit shared-first &&
+	HASH1=$(git rev-parse --verify HEAD) &&
+	test_commit shared-second &&
+	test_commit shared-third &&
+	HASH2=$(git rev-parse --verify HEAD) &&
+	git worktree add wt1 -f shared &&
+	git -C wt1 bisect start &&
+	git -C wt1 bisect good $HASH1 &&
+	git -C wt1 bisect bad $HASH2 &&
+	git worktree add wt2 -f shared &&
+	git -C wt2 bisect start &&
+	git -C wt2 bisect good $HASH1 &&
+	git -C wt2 bisect bad $HASH2 &&
+	# we test in both worktrees to ensure that works
+	# as expected with "first" and "next" worktrees
+	test_must_fail git -C wt1 switch shared &&
+	git -C wt1 switch --ignore-other-worktrees shared &&
+	test_must_fail git -C wt2 switch shared &&
+	git -C wt2 switch --ignore-other-worktrees shared
+'
+
 test_done
diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh
index 7c43ddf..c5d19dd 100755
--- a/t/t2070-restore.sh
+++ b/t/t2070-restore.sh
@@ -137,4 +137,20 @@
 	test_must_fail git rev-parse HEAD:new1
 '
 
+test_expect_success 'restore with merge options rejects --staged' '
+	for opts in \
+		"--staged --ours" \
+		"--staged --theirs" \
+		"--staged --merge" \
+		"--staged --conflict=diff3" \
+		"--staged --worktree --ours" \
+		"--staged --worktree --theirs" \
+		"--staged --worktree --merge" \
+		"--staged --worktree --conflict=zdiff3"
+	do
+		test_must_fail git restore $opts . 2>err &&
+		grep "cannot be used with --staged" err || return
+	done
+'
+
 test_done
diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh
index 07e6de8..89b285f 100755
--- a/t/t2107-update-index-basic.sh
+++ b/t/t2107-update-index-basic.sh
@@ -83,7 +83,7 @@
 	cd repo &&
 	git config core.worktree ../../worktree &&
 	# --refresh triggers late setup_work_tree,
-	# active_cache_changed is zero, rollback_lock_file fails
+	# the_index.cache_changed is zero, rollback_lock_file fails
 	git update-index --refresh --verbose >out &&
 	test_must_be_empty out &&
 	! test -f .git/index.lock
diff --git a/t/t3013-ls-files-format.sh b/t/t3013-ls-files-format.sh
index efb7450..ef6fb53 100755
--- a/t/t3013-ls-files-format.sh
+++ b/t/t3013-ls-files-format.sh
@@ -54,6 +54,22 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'git ls-files --format with relative path' '
+	cat >expect <<-\EOF &&
+	../o1.txt
+	../o2.txt
+	../o3.txt
+	../o4.txt
+	../o5.txt
+	../o6.txt
+	EOF
+	mkdir sub &&
+	cd sub &&
+	git ls-files --format="%(path)" ":/" >../actual &&
+	cd .. &&
+	test_cmp expect actual
+'
+
 test_expect_success 'git ls-files --format with -m' '
 	echo change >o1.txt &&
 	cat >expect <<-\EOF &&
diff --git a/t/t3060-ls-files-with-tree.sh b/t/t3060-ls-files-with-tree.sh
index c4a72ae..5a06732 100755
--- a/t/t3060-ls-files-with-tree.sh
+++ b/t/t3060-ls-files-with-tree.sh
@@ -40,7 +40,7 @@
 	git commit -a -m "remove them all" &&
 
 	# The bug also requires some entry before our directory so that
-	# prune_path will modify the_index.cache
+	# prune_index will modify the_repository->index.cache
 
 	mkdir a_directory_that_sorts_before_sub &&
 	>a_directory_that_sorts_before_sub/file &&
@@ -56,7 +56,7 @@
 '
 
 test_expect_success 'git ls-files --with-tree should succeed from subdir' '
-	# We have to run from a sub-directory to trigger prune_path
+	# We have to run from a sub-directory to trigger prune_index
 	# Then we finally get to run our --with-tree test
 	(
 		cd sub &&
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 5d871fd..4dd42df 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -431,4 +431,15 @@
 match 0 1 0 1 'z' '[Z-y]'
 match 1 1 1 1 'Z' '[Z-y]'
 
+test_expect_success 'matching does not exhibit exponential behavior' '
+	{
+		test-tool wildmatch wildmatch \
+			aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab \
+			"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a" &
+		pid=$!
+	} &&
+	sleep 2 &&
+	! kill $!
+'
+
 test_done
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 5a169b6..98b6c8a 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -239,15 +239,34 @@
 	git worktree prune
 '
 
+test_expect_success 'git branch -M fails if updating any linked working tree fails' '
+	git worktree add -b baz bazdir1 &&
+	git worktree add -f bazdir2 baz &&
+	touch .git/worktrees/bazdir1/HEAD.lock &&
+	test_must_fail git branch -M baz bam &&
+	test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam &&
+	git branch -M bam baz &&
+	rm .git/worktrees/bazdir1/HEAD.lock &&
+	touch .git/worktrees/bazdir2/HEAD.lock &&
+	test_must_fail git branch -M baz bam &&
+	test $(git -C bazdir1 rev-parse --abbrev-ref HEAD) = bam &&
+	rm -rf bazdir1 bazdir2 &&
+	git worktree prune
+'
+
 test_expect_success 'git branch -M baz bam should succeed within a worktree in which baz is checked out' '
 	git checkout -b baz &&
 	git worktree add -f bazdir baz &&
 	(
 		cd bazdir &&
 		git branch -M baz bam &&
-		test $(git rev-parse --abbrev-ref HEAD) = bam
+		echo bam >expect &&
+		git rev-parse --abbrev-ref HEAD >actual &&
+		test_cmp expect actual
 	) &&
-	test $(git rev-parse --abbrev-ref HEAD) = bam &&
+	echo bam >expect &&
+	git rev-parse --abbrev-ref HEAD >actual &&
+	test_cmp expect actual &&
 	rm -r bazdir &&
 	git worktree prune
 '
@@ -279,6 +298,20 @@
 	test_cmp expect err
 '
 
+test_expect_success 'git branch -m should work with orphan branches' '
+	test_when_finished git checkout - &&
+	test_when_finished git worktree remove -f wt &&
+	git worktree add wt --detach &&
+	# rename orphan in another worktreee
+	git -C wt checkout --orphan orphan-foo-wt &&
+	git branch -m orphan-foo-wt orphan-bar-wt &&
+	test orphan-bar-wt=$(git -C orphan-worktree branch --show-current) &&
+	# rename orphan in the current worktree
+	git checkout --orphan orphan-foo &&
+	git branch -m orphan-foo orphan-bar &&
+	test orphan-bar=$(git branch --show-current)
+'
+
 test_expect_success 'git branch -d on orphan HEAD (merged)' '
 	test_when_finished git checkout main &&
 	git checkout --orphan orphan &&
diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh
index ea7cfd1..be20ebe 100755
--- a/t/t3202-show-branch.sh
+++ b/t/t3202-show-branch.sh
@@ -221,4 +221,22 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'error descriptions on orphan branch' '
+	test_when_finished git worktree remove -f wt &&
+	git worktree add wt --detach &&
+	git -C wt checkout --orphan orphan-branch &&
+	test_branch_op_in_wt() {
+		test_orphan_error() {
+			test_must_fail git $* 2>actual &&
+			test_i18ngrep "No commit on branch .orphan-branch. yet.$" actual
+		} &&
+		test_orphan_error -C wt branch $1 $2 &&                # implicit branch
+		test_orphan_error -C wt branch $1 orphan-branch $2 &&  # explicit branch
+		test_orphan_error branch $1 orphan-branch $2           # different worktree
+	} &&
+	test_branch_op_in_wt --edit-description &&
+	test_branch_op_in_wt --set-upstream-to=ne &&
+	test_branch_op_in_wt -c new-branch
+'
+
 test_done
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
index d34d77f..93f8295 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -337,10 +337,48 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'git branch --format with ahead-behind' '
+	cat >expect <<-\EOF &&
+	(HEAD detached from fromtag) 0 0
+	refs/heads/ambiguous 0 0
+	refs/heads/branch-one 1 0
+	refs/heads/branch-two 0 0
+	refs/heads/main 1 0
+	refs/heads/ref-to-branch 1 0
+	refs/heads/ref-to-remote 1 0
+	EOF
+	git branch --format="%(refname) %(ahead-behind:HEAD)" >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'git branch with --format=%(rest) must fail' '
 	test_must_fail git branch --format="%(rest)" >actual
 '
 
+test_expect_success 'git branch --format --omit-empty' '
+	cat >expect <<-\EOF &&
+	Refname is (HEAD detached from fromtag)
+	Refname is refs/heads/ambiguous
+	Refname is refs/heads/branch-one
+	Refname is refs/heads/branch-two
+
+	Refname is refs/heads/ref-to-branch
+	Refname is refs/heads/ref-to-remote
+	EOF
+	git branch --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
+	test_cmp expect actual &&
+	cat >expect <<-\EOF &&
+	Refname is (HEAD detached from fromtag)
+	Refname is refs/heads/ambiguous
+	Refname is refs/heads/branch-one
+	Refname is refs/heads/branch-two
+	Refname is refs/heads/ref-to-branch
+	Refname is refs/heads/ref-to-remote
+	EOF
+	git branch --omit-empty --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'worktree colors correct' '
 	cat >expect <<-EOF &&
 	* <GREEN>(HEAD detached from fromtag)<RESET>
diff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh
index 141d3e4..9bd5dbf 100755
--- a/t/t3309-notes-merge-auto-resolve.sh
+++ b/t/t3309-notes-merge-auto-resolve.sh
@@ -360,7 +360,12 @@
 
 test_expect_success 'merge z into y with invalid configuration option => Fail/No changes' '
 	git config core.notesRef refs/notes/y &&
-	test_must_fail git -c notes.mergeStrategy="foo" notes merge z &&
+	cat >expect <<-\EOF &&
+	error: unknown notes merge strategy foo
+	fatal: unable to parse '\''notes.mergeStrategy'\'' from command-line config
+	EOF
+	test_must_fail git -c notes.mergeStrategy="foo" notes merge z 2>actual &&
+	test_cmp expect actual &&
 	# Verify no changes (y)
 	verify_notes y y
 '
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index d5a8ee3..3ce918f 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -388,6 +388,20 @@
 	git rebase main main
 '
 
+test_expect_success 'switch to branch checked out elsewhere fails' '
+	test_when_finished "
+		git worktree remove wt1 &&
+		git worktree remove wt2 &&
+		git branch -d shared
+	" &&
+	git worktree add wt1 -b shared &&
+	git worktree add wt2 -f shared &&
+	# we test in both worktrees to ensure that works
+	# as expected with "first" and "next" worktrees
+	test_must_fail git -C wt1 rebase shared shared &&
+	test_must_fail git -C wt2 rebase shared shared
+'
+
 test_expect_success 'switch to branch not checked out' '
 	git checkout main &&
 	git branch other &&
diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh
index 7e46f4c..79b0640 100755
--- a/t/t3402-rebase-merge.sh
+++ b/t/t3402-rebase-merge.sh
@@ -131,27 +131,6 @@
 	esac
 '
 
-test_expect_success 'rebase -s funny -Xopt' '
-	test_when_finished "rm -fr test-bin funny.was.run" &&
-	mkdir test-bin &&
-	cat >test-bin/git-merge-funny <<-EOF &&
-	#!$SHELL_PATH
-	case "\$1" in --opt) ;; *) exit 2 ;; esac
-	shift &&
-	>funny.was.run &&
-	exec git merge-recursive "\$@"
-	EOF
-	chmod +x test-bin/git-merge-funny &&
-	git reset --hard &&
-	git checkout -b test-funny main^ &&
-	test_commit funny &&
-	(
-		PATH=./test-bin:$PATH &&
-		git rebase -s funny -Xopt main
-	) &&
-	test -f funny.was.run
-'
-
 test_expect_success 'rebase --skip works with two conflicts in a row' '
 	git checkout second-side  &&
 	tr "[A-Z]" "[a-z]" <newfile >tmp &&
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index 130e2f9..2d0789e 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -62,61 +62,39 @@
 	rm -fr .git/rebase-* &&
 	git reset --hard commit-new-file-F2-on-topic-branch &&
 	test_commit "commit-new-file-F3-on-topic-branch" F3 32 &&
-	test_when_finished "rm -fr test-bin funny.was.run" &&
+	test_when_finished "rm -fr test-bin" &&
 	mkdir test-bin &&
-	cat >test-bin/git-merge-funny <<-EOF &&
-	#!$SHELL_PATH
-	case "\$1" in --opt) ;; *) exit 2 ;; esac
-	shift &&
-	>funny.was.run &&
-	exec git merge-recursive "\$@"
-	EOF
-	chmod +x test-bin/git-merge-funny &&
-	(
-		PATH=./test-bin:$PATH &&
-		test_must_fail git rebase -s funny -Xopt main topic
-	) &&
-	test -f funny.was.run &&
-	rm funny.was.run &&
-	echo "Resolved" >F2 &&
-	git add F2 &&
-	(
-		PATH=./test-bin:$PATH &&
-		git rebase --continue
-	) &&
-	test -f funny.was.run
-'
 
-test_expect_success 'rebase -i --continue handles merge strategy and options' '
-	rm -fr .git/rebase-* &&
-	git reset --hard commit-new-file-F2-on-topic-branch &&
-	test_commit "commit-new-file-F3-on-topic-branch-for-dash-i" F3 32 &&
-	test_when_finished "rm -fr test-bin funny.was.run funny.args" &&
-	mkdir test-bin &&
-	cat >test-bin/git-merge-funny <<-EOF &&
-	#!$SHELL_PATH
-	echo "\$@" >>funny.args
-	case "\$1" in --opt) ;; *) exit 2 ;; esac
-	case "\$2" in --foo) ;; *) exit 2 ;; esac
-	case "\$4" in --) ;; *) exit 2 ;; esac
-	shift 2 &&
-	>funny.was.run &&
-	exec git merge-recursive "\$@"
+	write_script test-bin/git-merge-funny <<-\EOF &&
+	printf "[%s]\n" $# "$1" "$2" "$3" "$5" >actual
+	shift 3 &&
+	exec git merge-recursive "$@"
 	EOF
-	chmod +x test-bin/git-merge-funny &&
+
+	cat >expect <<-\EOF &&
+	[7]
+	[--option=arg with space]
+	[--op"tion\]
+	[--new
+	line ]
+	[--]
+	EOF
+
+	rm -f actual &&
 	(
 		PATH=./test-bin:$PATH &&
-		test_must_fail git rebase -i -s funny -Xopt -Xfoo main topic
+		test_must_fail git rebase -s funny -X"option=arg with space" \
+				-Xop\"tion\\ -X"new${LF}line " main topic
 	) &&
-	test -f funny.was.run &&
-	rm funny.was.run &&
+	test_cmp expect actual &&
+	rm actual &&
 	echo "Resolved" >F2 &&
 	git add F2 &&
 	(
 		PATH=./test-bin:$PATH &&
 		git rebase --continue
 	) &&
-	test -f funny.was.run
+	test_cmp expect actual
 '
 
 test_expect_success 'rebase -r passes merge strategy options correctly' '
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 4711b37..2eba00b 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -85,6 +85,11 @@
 		test_must_fail git rebase $opt --reapply-cherry-picks A
 	"
 
+	test_expect_success "$opt incompatible with --rebase-merges" "
+		git checkout B^0 &&
+		test_must_fail git rebase $opt --rebase-merges A
+	"
+
 	test_expect_success "$opt incompatible with --update-refs" "
 		git checkout B^0 &&
 		test_must_fail git rebase $opt --update-refs A
@@ -101,6 +106,12 @@
 		grep -e --no-autosquash err
 	"
 
+	test_expect_success "$opt incompatible with rebase.rebaseMerges" "
+		git checkout B^0 &&
+		test_must_fail git -c rebase.rebaseMerges=true rebase $opt A 2>err &&
+		grep -e --no-rebase-merges err
+	"
+
 	test_expect_success "$opt incompatible with rebase.updateRefs" "
 		git checkout B^0 &&
 		test_must_fail git -c rebase.updateRefs=true rebase $opt A 2>err &&
@@ -113,6 +124,12 @@
 		git -c rebase.autosquash=true rebase --no-autosquash $opt A
 	"
 
+	test_expect_success "$opt okay with overridden rebase.rebaseMerges" "
+		test_when_finished \"git reset --hard B^0\" &&
+		git checkout B^0 &&
+		git -c rebase.rebaseMerges=true rebase --no-rebase-merges $opt A
+	"
+
 	test_expect_success "$opt okay with overridden rebase.updateRefs" "
 		test_when_finished \"git reset --hard B^0\" &&
 		git checkout B^0 &&
diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh
index 48b76f8..1b3e97c 100755
--- a/t/t3427-rebase-subtree.sh
+++ b/t/t3427-rebase-subtree.sh
@@ -74,9 +74,9 @@
 	test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --onto files-main main &&
 	: first pick results in no changes &&
 	git rebase --skip &&
-	verbose test "$(commit_message HEAD~2)" = "topic_4" &&
-	verbose test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
-	verbose test "$(commit_message HEAD)" = "Empty commit"
+	test "$(commit_message HEAD~2)" = "topic_4" &&
+	test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
+	test "$(commit_message HEAD)" = "Empty commit"
 '
 
 test_expect_success 'Rebase -Xsubtree --empty=ask --rebase-merges --onto commit' '
@@ -85,9 +85,9 @@
 	test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --rebase-merges --onto files-main --root &&
 	: first pick results in no changes &&
 	git rebase --skip &&
-	verbose test "$(commit_message HEAD~2)" = "topic_4" &&
-	verbose test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
-	verbose test "$(commit_message HEAD)" = "Empty commit"
+	test "$(commit_message HEAD~2)" = "topic_4" &&
+	test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
+	test "$(commit_message HEAD)" = "Empty commit"
 '
 
 test_done
diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh
index fa2a06c..96ae0ed 100755
--- a/t/t3430-rebase-merges.sh
+++ b/t/t3430-rebase-merges.sh
@@ -250,6 +250,16 @@
 	EOF
 '
 
+test_expect_success '--no-rebase-merges countermands --rebase-merges' '
+	git checkout -b no-rebase-merges E &&
+	git rebase --rebase-merges --no-rebase-merges C &&
+	test_cmp_graph C.. <<-\EOF
+	* B
+	* D
+	o C
+	EOF
+'
+
 test_expect_success 'do not rebase cousins unless asked for' '
 	git checkout -b cousins main &&
 	before="$(git rev-parse --verify HEAD)" &&
@@ -268,6 +278,40 @@
 	EOF
 '
 
+test_expect_success 'rebase.rebaseMerges=rebase-cousins is equivalent to --rebase-merges=rebase-cousins' '
+	test_config rebase.rebaseMerges rebase-cousins &&
+	git checkout -b config-rebase-cousins main &&
+	git rebase HEAD^ &&
+	test_cmp_graph HEAD^.. <<-\EOF
+	*   Merge the topic branch '\''onebranch'\''
+	|\
+	| * D
+	| * G
+	|/
+	o H
+	EOF
+'
+
+test_expect_success '--no-rebase-merges overrides rebase.rebaseMerges=no-rebase-cousins' '
+	test_config rebase.rebaseMerges no-rebase-cousins &&
+	git checkout -b override-config-no-rebase-cousins E &&
+	git rebase --no-rebase-merges C &&
+	test_cmp_graph C.. <<-\EOF
+	* B
+	* D
+	o C
+	EOF
+'
+
+test_expect_success '--rebase-merges overrides rebase.rebaseMerges=rebase-cousins' '
+	test_config rebase.rebaseMerges rebase-cousins &&
+	git checkout -b override-config-rebase-cousins E &&
+	before="$(git rev-parse --verify HEAD)" &&
+	test_tick &&
+	git rebase --rebase-merges C &&
+	test_cmp_rev HEAD $before
+'
+
 test_expect_success 'refs/rewritten/* is worktree-local' '
 	git worktree add wt &&
 	cat >wt/script-from-scratch <<-\EOF &&
@@ -534,4 +578,12 @@
 	EOF
 '
 
+test_expect_success 'progress shows the correct total' '
+	git checkout -b progress H &&
+	git rebase --rebase-merges --force-rebase --verbose A 2> err &&
+	# Expecting "Rebasing (N/14)" here, no bogus total number
+	grep "^Rebasing.*/14.$" err >progress &&
+	test_line_count = 14 progress
+'
+
 test_done
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 2f3e3e2..e2ef619 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -1,14 +1,6 @@
 #!/bin/sh
 
-test_description='test cherry-pick and revert with renames
-
-  --
-   + rename2: renames oops to opos
-  +  rename1: renames oops to spoo
-  +  added:   adds extra line to oops
-  ++ initial: has lines in oops
-
-'
+test_description='miscellaneous basic tests for cherry-pick and revert'
 
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
@@ -63,6 +55,14 @@
 	test_i18ngrep "[Uu]sage:" msg
 '
 
+# the following two test cherry-pick and revert with renames
+#
+# --
+#  + rename2: renames oops to opos
+# +  rename1: renames oops to spoo
+# +  added:   adds extra line to oops
+# ++ initial: has lines in oops
+
 test_expect_success 'cherry-pick after renaming branch' '
 
 	git checkout rename2 &&
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 51afbd7..82dd768 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -106,24 +106,32 @@
 
 test_expect_success '.gitignore is honored' '
 	git add . &&
-	! (git ls-files | grep "\\.ig")
+	git ls-files >files &&
+	sed -n "/\\.ig/p" <files >actual &&
+	test_must_be_empty actual
 '
 
 test_expect_success 'error out when attempting to add ignored ones without -f' '
 	test_must_fail git add a.?? &&
-	! (git ls-files | grep "\\.ig")
+	git ls-files >files &&
+	sed -n "/\\.ig/p" <files >actual &&
+	test_must_be_empty actual
 '
 
 test_expect_success 'error out when attempting to add ignored ones without -f' '
 	test_must_fail git add d.?? &&
-	! (git ls-files | grep "\\.ig")
+	git ls-files >files &&
+	sed -n "/\\.ig/p" <files >actual &&
+	test_must_be_empty actual
 '
 
 test_expect_success 'error out when attempting to add ignored ones but add others' '
 	touch a.if &&
 	test_must_fail git add a.?? &&
-	! (git ls-files | grep "\\.ig") &&
-	(git ls-files | grep a.if)
+	git ls-files >files &&
+	sed -n "/\\.ig/p" <files >actual &&
+	test_must_be_empty actual &&
+	grep a.if files
 '
 
 test_expect_success 'add ignored ones with -f' '
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 3a99837..3982b6b 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -7,12 +7,6 @@
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
-if test_have_prereq !PERL
-then
-	skip_all='skipping add -i (scripted) tests, perl not available'
-	test_done
-fi
-
 diff_cmp () {
 	for x
 	do
@@ -311,9 +305,11 @@
 	echo content >>file &&
 	chmod +x file &&
 	printf "y\\ny\\n" | git add -p &&
-	git diff --cached file | grep "new mode" &&
-	git diff --cached file | grep "+content" &&
-	test -z "$(git diff file)"
+	git diff --cached file >out &&
+	grep "new mode" out &&
+	grep "+content" out &&
+	git diff file >out &&
+	test_must_be_empty out
 '
 
 # end of tests disabled when filemode is not usable
@@ -1075,4 +1071,25 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'reset -p with unmerged files' '
+	test_when_finished "git checkout --force main" &&
+	test_commit one conflict &&
+	git checkout -B side HEAD^ &&
+	test_commit two conflict &&
+	test_must_fail git merge one &&
+
+	# this is a noop with only an unmerged entry
+	git reset -p &&
+
+	# add files that sort before and after unmerged entry
+	echo a >a &&
+	echo z >z &&
+	git add a z &&
+
+	# confirm that we can reset those files
+	printf "%s\n" y y | git reset -p &&
+	git diff-index --cached --diff-filter=u HEAD >staged &&
+	test_must_be_empty staged
+'
+
 test_done
diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh
index bfcaae3..8d50331 100755
--- a/t/t4000-diff-format.sh
+++ b/t/t4000-diff-format.sh
@@ -5,6 +5,9 @@
 
 test_description='Test built-in diff output engine.
 
+We happen to know that all diff plumbing and diff Porcelain share the
+same command line parser, so testing one should be sufficient; pick
+diff-files as a representative.
 '
 
 TEST_PASSES_SANITIZE_LEAK=true
@@ -16,9 +19,11 @@
 line 3'
 cat path0 >path1
 chmod +x path1
+mkdir path2
+>path2/path3
 
 test_expect_success 'update-index --add two files with and without +x.' '
-	git update-index --add path0 path1
+	git update-index --add path0 path1 path2/path3
 '
 
 mv path0 path0-
@@ -91,4 +96,31 @@
 	test_must_be_empty err
 '
 
+
+# Smudge path2/path3 so that dirstat has something to show
+date >path2/path3
+
+for format in stat raw numstat shortstat summary \
+	dirstat cumulative dirstat-by-file \
+	patch-with-raw patch-with-stat compact-summary
+do
+	test_expect_success "--no-patch in 'git diff-files --no-patch --$format' is a no-op" '
+		git diff-files --no-patch "--$format" >actual &&
+		git diff-files "--$format" >expect &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "--no-patch clears all previous ones" '
+		git diff-files --$format -s -p >actual &&
+		git diff-files -p >expect &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "--no-patch in 'git diff --no-patch --$format' is a no-op" '
+		git diff --no-patch "--$format" >actual &&
+		git diff "--$format" >expect &&
+		test_cmp expect actual
+	'
+done
+
 test_done
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index dfcf3a0..5de1d19 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -616,4 +616,46 @@
 	test_i18ngrep "invalid regex given to -I: " error
 '
 
+# check_prefix <patch> <src> <dst>
+# check only lines with paths to avoid dependency on exact oid/contents
+check_prefix () {
+	grep -E '^(diff|---|\+\+\+) ' "$1" >actual.paths &&
+	cat >expect <<-EOF &&
+	diff --git $2 $3
+	--- $2
+	+++ $3
+	EOF
+	test_cmp expect actual.paths
+}
+
+test_expect_success 'diff-files does not respect diff.noprefix' '
+	git -c diff.noprefix diff-files -p >actual &&
+	check_prefix actual a/file0 b/file0
+'
+
+test_expect_success 'diff-files respects --no-prefix' '
+	git diff-files -p --no-prefix >actual &&
+	check_prefix actual file0 file0
+'
+
+test_expect_success 'diff respects diff.noprefix' '
+	git -c diff.noprefix diff >actual &&
+	check_prefix actual file0 file0
+'
+
+test_expect_success 'diff --default-prefix overrides diff.noprefix' '
+	git -c diff.noprefix diff --default-prefix >actual &&
+	check_prefix actual a/file0 b/file0
+'
+
+test_expect_success 'diff respects diff.mnemonicprefix' '
+	git -c diff.mnemonicprefix diff >actual &&
+	check_prefix actual i/file0 w/file0
+'
+
+test_expect_success 'diff --default-prefix overrides diff.mnemonicprefix' '
+	git -c diff.mnemonicprefix diff --default-prefix >actual &&
+	check_prefix actual a/file0 b/file0
+'
+
 test_done
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index f3313b8..3cf2b7a 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -59,6 +59,10 @@
 	test_tick &&
 	git commit -m "patchid 3" &&
 
+	git checkout -b empty main &&
+	test_tick &&
+	git commit --allow-empty -m "empty commit" &&
+
 	git checkout main
 '
 
@@ -128,6 +132,12 @@
 	grep "^Side .* with .* backslash-n" actual
 '
 
+test_expect_success 'format-patch empty commit' '
+	git format-patch --stdout main..empty >empty &&
+	grep "^From " empty >from &&
+	test_line_count = 1 from
+'
+
 test_expect_success 'extra headers' '
 	git config format.headers "To: R E Cipient <rcipient@example.com>
 " &&
@@ -445,13 +455,13 @@
 
 cat >expect.thread <<EOF
 ---
-Message-Id: <0>
+Message-ID: <0>
 ---
-Message-Id: <1>
+Message-ID: <1>
 In-Reply-To: <0>
 References: <0>
 ---
-Message-Id: <2>
+Message-ID: <2>
 In-Reply-To: <0>
 References: <0>
 EOF
@@ -460,17 +470,22 @@
 	check_threading expect.thread --thread main
 '
 
+test_expect_success '--thread overrides format.thread=deep' '
+	test_config format.thread deep &&
+	check_threading expect.thread --thread main
+'
+
 cat >expect.in-reply-to <<EOF
 ---
-Message-Id: <0>
+Message-ID: <0>
 In-Reply-To: <1>
 References: <1>
 ---
-Message-Id: <2>
+Message-ID: <2>
 In-Reply-To: <1>
 References: <1>
 ---
-Message-Id: <3>
+Message-ID: <3>
 In-Reply-To: <1>
 References: <1>
 EOF
@@ -482,17 +497,17 @@
 
 cat >expect.cover-letter <<EOF
 ---
-Message-Id: <0>
+Message-ID: <0>
 ---
-Message-Id: <1>
+Message-ID: <1>
 In-Reply-To: <0>
 References: <0>
 ---
-Message-Id: <2>
+Message-ID: <2>
 In-Reply-To: <0>
 References: <0>
 ---
-Message-Id: <3>
+Message-ID: <3>
 In-Reply-To: <0>
 References: <0>
 EOF
@@ -503,21 +518,21 @@
 
 cat >expect.cl-irt <<EOF
 ---
-Message-Id: <0>
+Message-ID: <0>
 In-Reply-To: <1>
 References: <1>
 ---
-Message-Id: <2>
+Message-ID: <2>
 In-Reply-To: <0>
 References: <1>
 	<0>
 ---
-Message-Id: <3>
+Message-ID: <3>
 In-Reply-To: <0>
 References: <1>
 	<0>
 ---
-Message-Id: <4>
+Message-ID: <4>
 In-Reply-To: <0>
 References: <1>
 	<0>
@@ -535,13 +550,13 @@
 
 cat >expect.deep <<EOF
 ---
-Message-Id: <0>
+Message-ID: <0>
 ---
-Message-Id: <1>
+Message-ID: <1>
 In-Reply-To: <0>
 References: <0>
 ---
-Message-Id: <2>
+Message-ID: <2>
 In-Reply-To: <1>
 References: <0>
 	<1>
@@ -553,16 +568,16 @@
 
 cat >expect.deep-irt <<EOF
 ---
-Message-Id: <0>
+Message-ID: <0>
 In-Reply-To: <1>
 References: <1>
 ---
-Message-Id: <2>
+Message-ID: <2>
 In-Reply-To: <0>
 References: <1>
 	<0>
 ---
-Message-Id: <3>
+Message-ID: <3>
 In-Reply-To: <2>
 References: <1>
 	<0>
@@ -576,18 +591,18 @@
 
 cat >expect.deep-cl <<EOF
 ---
-Message-Id: <0>
+Message-ID: <0>
 ---
-Message-Id: <1>
+Message-ID: <1>
 In-Reply-To: <0>
 References: <0>
 ---
-Message-Id: <2>
+Message-ID: <2>
 In-Reply-To: <1>
 References: <0>
 	<1>
 ---
-Message-Id: <3>
+Message-ID: <3>
 In-Reply-To: <2>
 References: <0>
 	<1>
@@ -600,22 +615,22 @@
 
 cat >expect.deep-cl-irt <<EOF
 ---
-Message-Id: <0>
+Message-ID: <0>
 In-Reply-To: <1>
 References: <1>
 ---
-Message-Id: <2>
+Message-ID: <2>
 In-Reply-To: <0>
 References: <1>
 	<0>
 ---
-Message-Id: <3>
+Message-ID: <3>
 In-Reply-To: <2>
 References: <1>
 	<0>
 	<2>
 ---
-Message-Id: <4>
+Message-ID: <4>
 In-Reply-To: <3>
 References: <1>
 	<0>
@@ -2386,4 +2401,20 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'format-patch does not respect diff.noprefix' '
+	git -c diff.noprefix format-patch -1 --stdout >actual &&
+	grep "^--- a/blorp" actual
+'
+
+test_expect_success 'format-patch respects format.noprefix' '
+	git -c format.noprefix format-patch -1 --stdout >actual &&
+	grep "^--- blorp" actual
+'
+
+test_expect_success 'format-patch --default-prefix overrides format.noprefix' '
+	git -c format.noprefix \
+		format-patch -1 --default-prefix --stdout >actual &&
+	grep "^--- a/blorp" actual
+'
+
 test_done
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 42a2b9a..c8d5557 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -63,6 +63,25 @@
 		test_i18ngrep ! fatal msg &&
 		test_i18ngrep ! error msg
 	'
+
+	test_expect_success "builtin $p pattern compiles on bare repo with --attr-source" '
+		test_when_finished "rm -rf bare.git" &&
+		git checkout -B master &&
+		git add . &&
+		echo "*.java diff=notexist" >.gitattributes &&
+		git add .gitattributes &&
+		git commit -am "changing gitattributes" &&
+		git checkout -B branchA &&
+		echo "*.java diff=$p" >.gitattributes &&
+		git add .gitattributes &&
+		git commit -am "changing gitattributes" &&
+		git clone --bare --no-local . bare.git &&
+		git -C bare.git symbolic-ref HEAD refs/heads/master &&
+		test_expect_code 1 git -C bare.git --attr-source=branchA \
+			diff --exit-code HEAD:A.java HEAD:B.java 2>msg &&
+		test_i18ngrep ! fatal msg &&
+		test_i18ngrep ! error msg
+	'
 done
 
 test_expect_success 'last regexp must not be negated' '
diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh
index 1c89050..6fed993 100755
--- a/t/t4022-diff-rewrite.sh
+++ b/t/t4022-diff-rewrite.sh
@@ -24,7 +24,7 @@
 test_expect_success 'detect rewrite' '
 
 	actual=$(git diff-files -B --summary test) &&
-	verbose expr "$actual" : " rewrite test ([0-9]*%)$"
+	expr "$actual" : " rewrite test ([0-9]*%)$"
 
 '
 
diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh
index 15764ee..74586f3 100755
--- a/t/t4034-diff-words.sh
+++ b/t/t4034-diff-words.sh
@@ -69,6 +69,10 @@
 		echo "* diff='"$lang"'" >.gitattributes &&
 		word_diff --color-words
 	'
+	test_expect_success "diff driver '$lang' in Islandic" '
+		LANG=is_IS.UTF-8 LANGUAGE=is LC_ALL="$is_IS_locale" \
+		word_diff --color-words
+	'
 }
 
 test_expect_success setup '
diff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh
index 7fec2cb..70224c3 100755
--- a/t/t4047-diff-dirstat.sh
+++ b/t/t4047-diff-dirstat.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='diff --dirstat tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # set up two commits where the second commit has these files
diff --git a/t/t4062-diff-pickaxe.sh b/t/t4062-diff-pickaxe.sh
index 9aaa068..a90b46b 100755
--- a/t/t4062-diff-pickaxe.sh
+++ b/t/t4062-diff-pickaxe.sh
@@ -24,7 +24,7 @@
 
 test_expect_success '-S --pickaxe-regex' '
 	git diff --name-only -S0 --pickaxe-regex HEAD^ >out &&
-	verbose test 4096-zeroes.txt = "$(cat out)"
+	test 4096-zeroes.txt = "$(cat out)"
 '
 
 test_done
diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh
index f60f5cb..7af3a08 100755
--- a/t/t4067-diff-partial-clone.sh
+++ b/t/t4067-diff-partial-clone.sh
@@ -151,7 +151,7 @@
 
 	# Ensure no fetches.
 	GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD &&
-	! test_path_exists trace
+	test_path_is_missing trace
 '
 
 test_expect_success 'diff --break-rewrites fetches only if necessary, and batches blobs if it does' '
@@ -171,7 +171,7 @@
 
 	# Ensure no fetches.
 	GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD &&
-	! test_path_exists trace &&
+	test_path_is_missing trace &&
 
 	# But with --break-rewrites, ensure that there is exactly 1 negotiation
 	# by checking that there is only 1 "done" line sent. ("done" marks the
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index 65ac7df..a22a90d 100755
--- a/t/t4115-apply-symlink.sh
+++ b/t/t4115-apply-symlink.sh
@@ -74,7 +74,7 @@
 	error: affected file ${SQ}renamed-symlink/create-me${SQ} is beyond a symbolic link
 	EOF
 	test_cmp expected_stderr stderr &&
-	! test_path_exists .git/create-me
+	test_path_is_missing .git/create-me
 '
 
 test_expect_success SYMLINKS 'symlink escape when modifying file' '
@@ -126,4 +126,19 @@
 	test_path_is_file .git/delete-me
 '
 
+test_expect_success SYMLINKS '--reject removes .rej symlink if it exists' '
+	test_when_finished "git reset --hard && git clean -dfx" &&
+
+	test_commit file &&
+	echo modified >file.t &&
+	git diff -- file.t >patch &&
+	echo modified-again >file.t &&
+
+	ln -s foo file.t.rej &&
+	test_must_fail git apply patch --reject 2>err &&
+	test_i18ngrep "Rejected hunk" err &&
+	test_path_is_missing foo &&
+	test_path_is_file file.t.rej
+'
+
 test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 78cf1c8..2935fe1 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -103,7 +103,7 @@
 
 	git format-patch --stdout first >patch1 &&
 	{
-		echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
+		echo "Message-ID: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
 		echo "X-Fake-Field: Line One" &&
 		echo "X-Fake-Field: Line Two" &&
 		echo "X-Fake-Field: Line Three" &&
@@ -942,7 +942,7 @@
 	git am --message-id patch1.eml &&
 	test_path_is_missing .git/rebase-apply &&
 	git cat-file commit HEAD | tail -n1 >actual &&
-	grep Message-Id patch1.eml >expected &&
+	grep Message-ID patch1.eml >expected &&
 	test_cmp expected actual
 '
 
@@ -954,7 +954,7 @@
 	git am patch1.eml &&
 	test_path_is_missing .git/rebase-apply &&
 	git cat-file commit HEAD | tail -n1 >actual &&
-	grep Message-Id patch1.eml >expected &&
+	grep Message-ID patch1.eml >expected &&
 	test_cmp expected actual
 '
 
@@ -965,7 +965,7 @@
 	git am -s --message-id patch1.eml &&
 	test_path_is_missing .git/rebase-apply &&
 	git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
-	grep Message-Id patch1.eml >expected &&
+	grep Message-ID patch1.eml >expected &&
 	test_cmp expected actual
 '
 
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 2ce2b41..ae73aef 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -835,6 +835,21 @@
 
 '
 
+test_expect_success 'parse log.excludeDecoration with no value' '
+	cp .git/config .git/config.orig &&
+	test_when_finished mv .git/config.orig .git/config &&
+
+	cat >>.git/config <<-\EOF &&
+	[log]
+		excludeDecoration
+	EOF
+	cat >expect <<-\EOF &&
+	error: missing value for '\''log.excludeDecoration'\''
+	EOF
+	git log --decorate=short 2>actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'decorate-refs with glob' '
 	cat >expect.decorate <<-\EOF &&
 	Merge-tag-reach
diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh
index e89e1f5..85e90ac 100755
--- a/t/t4212-log-corrupt.sh
+++ b/t/t4212-log-corrupt.sh
@@ -8,8 +8,9 @@
 test_expect_success 'setup' '
 	test_commit foo &&
 
-	git cat-file commit HEAD |
-	sed "/^author /s/>/>-<>/" >broken_email.commit &&
+	git cat-file commit HEAD >ok.commit &&
+	sed "s/>/>-<>/" <ok.commit >broken_email.commit &&
+
 	git hash-object --literally -w -t commit broken_email.commit >broken_email.hash &&
 	git update-ref refs/heads/broken_email $(cat broken_email.hash)
 '
@@ -43,6 +44,11 @@
 	test_must_be_empty actual.err
 '
 
+test_expect_success '--until handles broken email' '
+	git rev-list --until=1980-01-01 broken_email >actual &&
+	test_must_be_empty actual
+'
+
 munge_author_date () {
 	git cat-file commit "$1" >commit.orig &&
 	sed "s/^\(author .*>\) [0-9]*/\1 $2/" <commit.orig >commit.munge &&
@@ -86,4 +92,45 @@
 	git log -1 --format=%ad $commit
 '
 
+test_expect_success 'create commits with whitespace committer dates' '
+	# It is important that this subject line is numeric, since we want to
+	# be sure we are not confused by skipping whitespace and accidentally
+	# parsing the subject as a timestamp.
+	#
+	# Do not use munge_author_date here. Besides not hitting the committer
+	# line, it leaves the timezone intact, and we want nothing but
+	# whitespace.
+	#
+	# We will make two munged commits here. The first, ws_commit, will
+	# be purely spaces. The second contains a vertical tab, which is
+	# considered a space by strtoumax(), but not by our isspace().
+	test_commit 1234567890 &&
+	git cat-file commit HEAD >commit.orig &&
+	sed "s/>.*/>    /" <commit.orig >commit.munge &&
+	ws_commit=$(git hash-object --literally -w -t commit commit.munge) &&
+	sed "s/>.*/>   $(printf "\013")/" <commit.orig >commit.munge &&
+	vt_commit=$(git hash-object --literally -w -t commit commit.munge)
+'
+
+test_expect_success '--until treats whitespace date as sentinel' '
+	echo $ws_commit >expect &&
+	git rev-list --until=1980-01-01 $ws_commit >actual &&
+	test_cmp expect actual &&
+
+	echo $vt_commit >expect &&
+	git rev-list --until=1980-01-01 $vt_commit >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'pretty-printer handles whitespace date' '
+	# as with the %ad test above, we will show these as the empty string,
+	# not the 1970 epoch date. This is intentional; see 7d9a281941 (t4212:
+	# test bogus timestamps with git-log, 2014-02-24) for more discussion.
+	echo : >expect &&
+	git log -1 --format="%at:%ct" $ws_commit >actual &&
+	test_cmp expect actual &&
+	git log -1 --format="%at:%ct" $vt_commit >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t4258/mbox b/t/t4258/mbox
index c62819f..1ae528b 100644
--- a/t/t4258/mbox
+++ b/t/t4258/mbox
@@ -2,7 +2,7 @@
 To: list@example.org
 Subject: [PATCH v2] sample
 Date: Mon,  3 Aug 2020 22:40:55 +0700
-Message-Id: <msg-id@example.com>
+Message-ID: <msg-id@example.com>
 Content-Type: text/plain; charset="utf-8"
 Content-Transfer-Encoding: base64
 
diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh
index c52c8a2..57c4f26 100755
--- a/t/t4300-merge-tree.sh
+++ b/t/t4300-merge-tree.sh
@@ -334,4 +334,22 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'merge-tree respects core.useReplaceRefs=false' '
+	test_commit merge-to &&
+	test_commit valid base &&
+	git reset --hard HEAD^ &&
+	test_commit malicious base &&
+
+	test_when_finished "git replace -d $(git rev-parse valid^0)" &&
+	git replace valid^0 malicious^0 &&
+
+	tree=$(git -c core.useReplaceRefs=true merge-tree --write-tree merge-to valid) &&
+	merged=$(git cat-file -p $tree:base) &&
+	test malicious = $merged &&
+
+	tree=$(git -c core.useReplaceRefs=false merge-tree --write-tree merge-to valid) &&
+	merged=$(git cat-file -p $tree:base) &&
+	test valid = $merged
+'
+
 test_done
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 918a2fc..4b4c331 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -185,6 +185,7 @@
 '
 
 check_tar b
+check_mtime b a/a 1117231200
 
 test_expect_success 'git archive --mtime' '
 	git archive --mtime=2002-02-02T02:02:02-0200 HEAD >with_mtime.tar
@@ -257,14 +258,6 @@
 	test_cmp_bin b.tar b5-nick.tar
 '
 
-test_expect_success 'validate file modification time' '
-	mkdir extract &&
-	"$TAR" xf b.tar -C extract a/a &&
-	test-tool chmtime --get extract/a/a >b.mtime &&
-	echo "1117231200" >expected.mtime &&
-	test_cmp expected.mtime b.mtime
-'
-
 test_expect_success 'git get-tar-commit-id' '
 	git get-tar-commit-id <b.tar >actual &&
 	git rev-parse HEAD >expect &&
@@ -433,6 +426,19 @@
 	test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
 '
 
+test_expect_success 'reject paths outside the current directory' '
+	test_must_fail git -C a/bin archive HEAD .. >/dev/null 2>err &&
+	grep "outside the current directory" err
+'
+
+test_expect_success 'allow pathspecs that resolve to the current directory' '
+	git -C a/bin archive -v HEAD ../bin >/dev/null 2>actual &&
+	cat >expect <<-\EOF &&
+	sh
+	EOF
+	test_cmp expect actual
+'
+
 # Pull the size and date of each entry in a tarfile using the system tar.
 #
 # We'll pull out only the year from the date; that avoids any question of
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 04d300e..0ff47a2 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -33,6 +33,13 @@
 	echo ignored-by-tree.d export-ignore >>.gitattributes &&
 	git add ignored-by-tree ignored-by-tree.d .gitattributes &&
 
+	mkdir subdir &&
+	>subdir/included &&
+	>subdir/ignored-by-subtree &&
+	>subdir/ignored-by-tree &&
+	echo ignored-by-subtree export-ignore >subdir/.gitattributes &&
+	git add subdir &&
+
 	echo ignored by worktree >ignored-by-worktree &&
 	echo ignored-by-worktree export-ignore >.gitattributes &&
 	git add ignored-by-worktree &&
@@ -93,6 +100,15 @@
 test_expect_missing	archive-pathspec-wildcard/excluded-by-pathspec.d
 test_expect_missing	archive-pathspec-wildcard/excluded-by-pathspec.d/file
 
+test_expect_success 'git -C subdir archive' '
+	git -C subdir archive HEAD >archive-subdir.tar &&
+	extract_tar_to_dir archive-subdir
+'
+
+test_expect_exists	archive-subdir/included
+test_expect_missing	archive-subdir/ignored-by-subtree
+test_expect_missing	archive-subdir/ignored-by-tree
+
 test_expect_success 'git archive with worktree attributes' '
 	git archive --worktree-attributes HEAD >worktree.tar &&
 	(mkdir worktree && cd worktree && "$TAR" xf -) <worktree.tar
diff --git a/t/t5100/msg0002 b/t/t5100/msg0002
index e2546ec..1089382 100644
--- a/t/t5100/msg0002
+++ b/t/t5100/msg0002
@@ -3,7 +3,7 @@
 
 From: Nit Picker <nit.picker@example.net>
 Subject: foo is too old
-Message-Id: <nitpicker.12121212@example.net>
+Message-ID: <nitpicker.12121212@example.net>
 
 Hopefully this would fix the problem stated there.
 
diff --git a/t/t5100/msg0003 b/t/t5100/msg0003
index 1ac6810..3402b53 100644
--- a/t/t5100/msg0003
+++ b/t/t5100/msg0003
@@ -3,7 +3,7 @@
 
 From: Nit Picker <nit.picker@example.net>
 Subject: foo is too old
-Message-Id: <nitpicker.12121212@example.net>
+Message-ID: <nitpicker.12121212@example.net>
 
 Hopefully this would fix the problem stated there.
 
diff --git a/t/t5100/msg0012--message-id b/t/t5100/msg0012--message-id
index 376e26e..4448295 100644
--- a/t/t5100/msg0012--message-id
+++ b/t/t5100/msg0012--message-id
@@ -5,4 +5,4 @@
 python-docutils. В то время как сам rest2web не нужен.
 
 Signed-off-by: Dmitriy Blinov <bda@mnsspb.ru>
-Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
+Message-ID: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
diff --git a/t/t5100/quoted-cr.mbox b/t/t5100/quoted-cr.mbox
index 909021b..a529d4d 100644
--- a/t/t5100/quoted-cr.mbox
+++ b/t/t5100/quoted-cr.mbox
@@ -3,7 +3,7 @@
 To: list@example.org
 Subject: [PATCH v2] sample
 Date: Mon,  3 Aug 2020 22:40:55 +0700
-Message-Id: <msg-id@example.com>
+Message-ID: <msg-id@example.com>
 Content-Type: text/plain; charset="utf-8"
 Content-Transfer-Encoding: base64
 
@@ -27,7 +27,7 @@
 To: list@example.org
 Subject: [PATCH v2] sample
 Date: Mon,  3 Aug 2020 22:40:55 +0700
-Message-Id: <msg-id2@example.com>
+Message-ID: <msg-id2@example.com>
 Content-Type: text/plain; charset="utf-8"
 Content-Transfer-Encoding: base64
 
diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox
index 6d4d0e4..4a54ee5 100644
--- a/t/t5100/sample.mbox
+++ b/t/t5100/sample.mbox
@@ -35,7 +35,7 @@
 
 From: Nit Picker <nit.picker@example.net>
 Subject: foo is too old
-Message-Id: <nitpicker.12121212@example.net>
+Message-ID: <nitpicker.12121212@example.net>
 
 Hopefully this would fix the problem stated there.
 
@@ -78,7 +78,7 @@
 
 From: Nit Picker <nit.picker@example.net>
 Subject: foo is too old
-Message-Id: <nitpicker.12121212@example.net>
+Message-ID: <nitpicker.12121212@example.net>
 
 Hopefully this would fix the problem stated there.
 
@@ -508,7 +508,7 @@
 From: Dmitriy Blinov <bda@mnsspb.ru>
 To: navy-patches@dinar.mns.mnsspb.ru
 Date: Wed, 12 Nov 2008 17:54:41 +0300
-Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
+Message-ID: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
 X-Mailer: git-send-email 1.5.6.5
 MIME-Version: 1.0
 Content-Type: text/plain;
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index f8a0f30..d2ce236 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -589,141 +589,6 @@
 	test_line_count = 1 donelines
 '
 
-test_expect_success 'setup for --stdin-packs tests' '
-	git init stdin-packs &&
-	(
-		cd stdin-packs &&
-
-		test_commit A &&
-		test_commit B &&
-		test_commit C &&
-
-		for id in A B C
-		do
-			git pack-objects .git/objects/pack/pack-$id \
-				--incremental --revs <<-EOF || exit 1
-			refs/tags/$id
-			EOF
-		done &&
-
-		ls -la .git/objects/pack
-	)
-'
-
-test_expect_success '--stdin-packs with excluded packs' '
-	(
-		cd stdin-packs &&
-
-		PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
-		PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
-		PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
-
-		git pack-objects test --stdin-packs <<-EOF &&
-		$PACK_A
-		^$PACK_B
-		$PACK_C
-		EOF
-
-		(
-			git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
-			git show-index <$(ls .git/objects/pack/pack-C-*.idx)
-		) >expect.raw &&
-		git show-index <$(ls test-*.idx) >actual.raw &&
-
-		cut -d" " -f2 <expect.raw | sort >expect &&
-		cut -d" " -f2 <actual.raw | sort >actual &&
-		test_cmp expect actual
-	)
-'
-
-test_expect_success '--stdin-packs is incompatible with --filter' '
-	(
-		cd stdin-packs &&
-		test_must_fail git pack-objects --stdin-packs --stdout \
-			--filter=blob:none </dev/null 2>err &&
-		test_i18ngrep "cannot use --filter with --stdin-packs" err
-	)
-'
-
-test_expect_success '--stdin-packs is incompatible with --revs' '
-	(
-		cd stdin-packs &&
-		test_must_fail git pack-objects --stdin-packs --revs out \
-			</dev/null 2>err &&
-		test_i18ngrep "cannot use internal rev list with --stdin-packs" err
-	)
-'
-
-test_expect_success '--stdin-packs with loose objects' '
-	(
-		cd stdin-packs &&
-
-		PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
-		PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
-		PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
-
-		test_commit D && # loose
-
-		git pack-objects test2 --stdin-packs --unpacked <<-EOF &&
-		$PACK_A
-		^$PACK_B
-		$PACK_C
-		EOF
-
-		(
-			git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
-			git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
-			git rev-list --objects --no-object-names \
-				refs/tags/C..refs/tags/D
-
-		) >expect.raw &&
-		ls -la . &&
-		git show-index <$(ls test2-*.idx) >actual.raw &&
-
-		cut -d" " -f2 <expect.raw | sort >expect &&
-		cut -d" " -f2 <actual.raw | sort >actual &&
-		test_cmp expect actual
-	)
-'
-
-test_expect_success '--stdin-packs with broken links' '
-	(
-		cd stdin-packs &&
-
-		# make an unreachable object with a bogus parent
-		git cat-file -p HEAD >commit &&
-		sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
-		git hash-object -w -t commit --stdin >in &&
-
-		git pack-objects .git/objects/pack/pack-D <in &&
-
-		PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
-		PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
-		PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
-		PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
-
-		git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
-		$PACK_A
-		^$PACK_B
-		$PACK_C
-		$PACK_D
-		EOF
-
-		(
-			git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
-			git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
-			git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
-			git rev-list --objects --no-object-names \
-				refs/tags/C..refs/tags/D
-		) >expect.raw &&
-		git show-index <$(ls test3-*.idx) >actual.raw &&
-
-		cut -d" " -f2 <expect.raw | sort >expect &&
-		cut -d" " -f2 <actual.raw | sort >actual &&
-		test_cmp expect actual
-	)
-'
-
 test_expect_success 'negative window clamps to 0' '
 	git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr &&
 	check_deltas stderr = 0
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index d65a5f9..f367327 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -16,7 +16,7 @@
 	before=$(git count-objects | sed "s/ .*//") &&
 	BLOB=$(echo aleph_0 | git hash-object -w --stdin) &&
 	BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
-	verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+	test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
 	test_path_is_file $BLOB_FILE &&
 	test-tool chmtime =+0 $BLOB_FILE
 }
@@ -51,34 +51,42 @@
 test_expect_success 'prune --expire' '
 	add_blob &&
 	git prune --expire=1.hour.ago &&
-	verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+	test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
 	test_path_is_file $BLOB_FILE &&
 	test-tool chmtime =-86500 $BLOB_FILE &&
 	git prune --expire 1.day &&
-	verbose test $before = $(git count-objects | sed "s/ .*//") &&
+	test $before = $(git count-objects | sed "s/ .*//") &&
 	test_path_is_missing $BLOB_FILE
 '
 
 test_expect_success 'gc: implicit prune --expire' '
 	add_blob &&
 	test-tool chmtime =-$((2*$week-30)) $BLOB_FILE &&
-	git gc &&
-	verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+	git gc --no-cruft &&
+	test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
 	test_path_is_file $BLOB_FILE &&
 	test-tool chmtime =-$((2*$week+1)) $BLOB_FILE &&
-	git gc &&
-	verbose test $before = $(git count-objects | sed "s/ .*//") &&
+	git gc --no-cruft &&
+	test $before = $(git count-objects | sed "s/ .*//") &&
 	test_path_is_missing $BLOB_FILE
 '
 
 test_expect_success 'gc: refuse to start with invalid gc.pruneExpire' '
-	git config gc.pruneExpire invalid &&
-	test_must_fail git gc
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	>repo/.git/config &&
+	git -C repo config gc.pruneExpire invalid &&
+	cat >expect <<-\EOF &&
+	error: Invalid gc.pruneexpire: '\''invalid'\''
+	fatal: bad config variable '\''gc.pruneexpire'\'' in file '\''.git/config'\'' at line 2
+	EOF
+	test_must_fail git -C repo gc 2>actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'gc: start with ok gc.pruneExpire' '
 	git config gc.pruneExpire 2.days.ago &&
-	git gc
+	git gc --no-cruft
 '
 
 test_expect_success 'prune: prune nonsense parameters' '
@@ -129,44 +137,44 @@
 	add_blob &&
 	test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
 	git config gc.pruneExpire 2.days.ago &&
-	git gc --no-prune &&
-	verbose test 1 = $(git count-objects | sed "s/ .*//") &&
+	git gc --no-prune --no-cruft &&
+	test 1 = $(git count-objects | sed "s/ .*//") &&
 	test_path_is_file $BLOB_FILE
 '
 
 test_expect_success 'gc respects gc.pruneExpire' '
 	git config gc.pruneExpire 5002.days.ago &&
-	git gc &&
+	git gc --no-cruft &&
 	test_path_is_file $BLOB_FILE &&
 	git config gc.pruneExpire 5000.days.ago &&
-	git gc &&
+	git gc --no-cruft &&
 	test_path_is_missing $BLOB_FILE
 '
 
 test_expect_success 'gc --prune=<date>' '
 	add_blob &&
 	test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
-	git gc --prune=5002.days.ago &&
+	git gc --prune=5002.days.ago --no-cruft &&
 	test_path_is_file $BLOB_FILE &&
-	git gc --prune=5000.days.ago &&
+	git gc --prune=5000.days.ago --no-cruft &&
 	test_path_is_missing $BLOB_FILE
 '
 
 test_expect_success 'gc --prune=never' '
 	add_blob &&
-	git gc --prune=never &&
+	git gc --prune=never --no-cruft &&
 	test_path_is_file $BLOB_FILE &&
-	git gc --prune=now &&
+	git gc --prune=now --no-cruft &&
 	test_path_is_missing $BLOB_FILE
 '
 
 test_expect_success 'gc respects gc.pruneExpire=never' '
 	git config gc.pruneExpire never &&
 	add_blob &&
-	git gc &&
+	git gc --no-cruft &&
 	test_path_is_file $BLOB_FILE &&
 	git config gc.pruneExpire now &&
-	git gc &&
+	git gc --no-cruft &&
 	test_path_is_missing $BLOB_FILE
 '
 
@@ -184,10 +192,10 @@
 	git clone --no-hardlinks . aclone &&
 	(
 		cd aclone &&
-		verbose test 1 = $(git count-objects | sed "s/ .*//") &&
+		test 1 = $(git count-objects | sed "s/ .*//") &&
 		test_path_is_file $BLOB_FILE &&
-		git gc --prune &&
-		verbose test 0 = $(git count-objects | sed "s/ .*//") &&
+		git gc --prune --no-cruft &&
+		test 0 = $(git count-objects | sed "s/ .*//") &&
 		test_path_is_missing $BLOB_FILE
 	)
 '
@@ -229,7 +237,7 @@
 	>.git/objects/pack/fake2.keep &&
 	>.git/objects/pack/fake2.idx &&
 	>.git/objects/pack/fake3.keep &&
-	git gc &&
+	git gc --no-cruft &&
 	git count-objects -v 2>stderr &&
 	grep "^warning:" stderr | sort >actual &&
 	cat >expected <<\EOF &&
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index 7d8dee4..526a5a5 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -404,6 +404,26 @@
 		)
 	'
 
+	test_expect_success 'pack.preferBitmapTips' '
+		git init repo &&
+		test_when_finished "rm -rf repo" &&
+		(
+			cd repo &&
+			git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
+			test_commit_bulk --message="%s" 103 &&
+
+			cat >>.git/config <<-\EOF &&
+			[pack]
+				preferBitmapTips
+			EOF
+			cat >expect <<-\EOF &&
+			error: missing value for '\''pack.preferbitmaptips'\''
+			EOF
+			git repack -adb 2>actual &&
+			test_cmp expect actual
+		)
+	'
+
 	test_expect_success 'complains about multiple pack bitmaps' '
 		rm -fr repo &&
 		git init repo &&
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 049c5fc..b6e1211 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -630,7 +630,7 @@
 
 test_expect_success 'detect incorrect generation number' '
 	corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\01" \
-		"non-zero generation number"
+		"commit-graph generation for commit"
 '
 
 test_expect_success 'detect incorrect commit date' '
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index 499d5d4..0883c7c 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -183,6 +183,18 @@
 
 compare_results_with_midx "mixed mode (one pack + extra)"
 
+test_expect_success 'write with no objects and preferred pack' '
+	test_when_finished "rm -rf empty" &&
+	git init empty &&
+	test_must_fail git -C empty multi-pack-index write \
+		--stdin-packs --preferred-pack=does-not-exist </dev/null 2>err &&
+	cat >expect <<-EOF &&
+	warning: unknown preferred pack: ${SQ}does-not-exist${SQ}
+	error: no pack files to index.
+	EOF
+	test_cmp expect err
+'
+
 test_expect_success 'write progress off for redirected stderr' '
 	git multi-pack-index --object-dir=$objdir write 2>err &&
 	test_line_count = 0 err
diff --git a/t/t5325-reverse-index.sh b/t/t5325-reverse-index.sh
index d042d26..431a603 100755
--- a/t/t5325-reverse-index.sh
+++ b/t/t5325-reverse-index.sh
@@ -1,17 +1,20 @@
 #!/bin/sh
 
 test_description='on-disk reverse index'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # The below tests want control over the 'pack.writeReverseIndex' setting
 # themselves to assert various combinations of it with other options.
-sane_unset GIT_TEST_WRITE_REV_INDEX
+sane_unset GIT_TEST_NO_WRITE_REV_INDEX
 
 packdir=.git/objects/pack
 
 test_expect_success 'setup' '
 	test_commit base &&
 
+	test_config pack.writeReverseIndex false &&
 	pack=$(git pack-objects --all $packdir/pack) &&
 	rev=$packdir/pack-$pack.rev &&
 
@@ -94,6 +97,17 @@
 		--batch-check="%(objectsize:disk)" <tip
 '
 
+test_expect_success 'reverse index is ignored when pack.readReverseIndex is false' '
+	test_index_pack true &&
+	test_path_is_file $rev &&
+
+	test_config pack.readReverseIndex false &&
+
+	git rev-parse HEAD >tip &&
+	GIT_TEST_REV_INDEX_DIE_ON_DISK=1 git cat-file \
+		--batch-check="%(objectsize:disk)" <tip
+'
+
 test_expect_success 'revindex in-memory vs on-disk' '
 	git init repo &&
 	test_when_finished "rm -fr repo" &&
@@ -117,4 +131,78 @@
 		test_cmp on-disk in-core
 	)
 '
+
+test_expect_success 'fsck succeeds on good rev-index' '
+	test_when_finished rm -fr repo &&
+	git init repo &&
+	(
+		cd repo &&
+
+		test_commit commit &&
+		git -c pack.writeReverseIndex=true repack -ad &&
+		git fsck 2>err &&
+		test_must_be_empty err
+	)
+'
+
+test_expect_success 'set up rev-index corruption tests' '
+	git init corrupt &&
+	(
+		cd corrupt &&
+
+		test_commit commit &&
+		git -c pack.writeReverseIndex=true repack -ad &&
+
+		revfile=$(ls .git/objects/pack/pack-*.rev) &&
+		chmod a+w $revfile &&
+		cp $revfile $revfile.bak
+	)
+'
+
+corrupt_rev_and_verify () {
+	(
+		pos="$1" &&
+		value="$2" &&
+		error="$3" &&
+
+		cd corrupt &&
+		revfile=$(ls .git/objects/pack/pack-*.rev) &&
+
+		# Reset to original rev-file.
+		cp $revfile.bak $revfile &&
+
+		printf "$value" | dd of=$revfile bs=1 seek="$pos" conv=notrunc &&
+		test_must_fail git fsck 2>err &&
+		grep "$error" err
+	)
+}
+
+test_expect_success 'fsck catches invalid checksum' '
+	revfile=$(ls corrupt/.git/objects/pack/pack-*.rev) &&
+	orig_size=$(wc -c <$revfile) &&
+	hashpos=$((orig_size - 10)) &&
+	corrupt_rev_and_verify $hashpos bogus \
+		"invalid checksum"
+'
+
+test_expect_success 'fsck catches invalid row position' '
+	corrupt_rev_and_verify 14 "\07" \
+		"invalid rev-index position"
+'
+
+test_expect_success 'fsck catches invalid header: magic number' '
+	corrupt_rev_and_verify 1 "\07" \
+		"reverse-index file .* has unknown signature"
+'
+
+test_expect_success 'fsck catches invalid header: version' '
+	corrupt_rev_and_verify 7 "\02" \
+		"reverse-index file .* has unsupported version"
+'
+
+test_expect_success 'fsck catches invalid header: hash function' '
+	corrupt_rev_and_verify 11 "\03" \
+		"reverse-index file .* has unsupported hash id"
+'
+
 test_done
diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh
index 0882cbb..f771c44 100755
--- a/t/t5326-multi-pack-bitmaps.sh
+++ b/t/t5326-multi-pack-bitmaps.sh
@@ -434,4 +434,48 @@
 	)
 '
 
+corrupt_file () {
+	chmod a+w "$1" &&
+	printf "bogus" | dd of="$1" bs=1 seek="12" conv=notrunc
+}
+
+test_expect_success 'git fsck correctly identifies good and bad bitmaps' '
+	git init valid &&
+	test_when_finished rm -rf valid &&
+
+	test_commit_bulk 20 &&
+	git repack -adbf &&
+
+	# Move pack-bitmap aside so it is not deleted
+	# in next repack.
+	packbitmap=$(ls .git/objects/pack/pack-*.bitmap) &&
+	mv "$packbitmap" "$packbitmap.bak" &&
+
+	test_commit_bulk 10 &&
+	git repack -b --write-midx &&
+	midxbitmap=$(ls .git/objects/pack/multi-pack-index-*.bitmap) &&
+
+	# Copy MIDX bitmap to backup. Copy pack bitmap from backup.
+	cp "$midxbitmap" "$midxbitmap.bak" &&
+	cp "$packbitmap.bak" "$packbitmap" &&
+
+	# fsck works at first
+	git fsck 2>err &&
+	test_must_be_empty err &&
+
+	corrupt_file "$packbitmap" &&
+	test_must_fail git fsck 2>err &&
+	grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err &&
+
+	cp "$packbitmap.bak" "$packbitmap" &&
+	corrupt_file "$midxbitmap" &&
+	test_must_fail git fsck 2>err &&
+	grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
+
+	corrupt_file "$packbitmap" &&
+	test_must_fail git fsck 2>err &&
+	grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
+	grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err
+'
+
 test_done
diff --git a/t/t5328-commit-graph-64bit-time.sh b/t/t5328-commit-graph-64bit-time.sh
index 093f0c0..57e4d9c 100755
--- a/t/t5328-commit-graph-64bit-time.sh
+++ b/t/t5328-commit-graph-64bit-time.sh
@@ -63,4 +63,13 @@
 
 graph_git_behavior 'overflow 2' repo left right
 
+test_expect_success 'single commit with generation data exceeding UINT32_MAX' '
+	git init repo-uint32-max &&
+	cd repo-uint32-max &&
+	test_commit --date "@4294967297 +0000" 1 &&
+	git commit-graph write --reachable &&
+	graph_read_expect 1 "generation_data" &&
+	git commit-graph verify
+'
+
 test_done
diff --git a/t/t5331-pack-objects-stdin.sh b/t/t5331-pack-objects-stdin.sh
new file mode 100755
index 0000000..acab316
--- /dev/null
+++ b/t/t5331-pack-objects-stdin.sh
@@ -0,0 +1,240 @@
+#!/bin/sh
+
+test_description='pack-objects --stdin'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+packed_objects () {
+	git show-index <"$1" >tmp-object-list &&
+	cut -d' ' -f2 tmp-object-list | sort &&
+	rm tmp-object-list
+ }
+
+test_expect_success 'setup for --stdin-packs tests' '
+	git init stdin-packs &&
+	(
+		cd stdin-packs &&
+
+		test_commit A &&
+		test_commit B &&
+		test_commit C &&
+
+		for id in A B C
+		do
+			git pack-objects .git/objects/pack/pack-$id \
+				--incremental --revs <<-EOF || exit 1
+			refs/tags/$id
+			EOF
+		done &&
+
+		ls -la .git/objects/pack
+	)
+'
+
+test_expect_success '--stdin-packs with excluded packs' '
+	(
+		cd stdin-packs &&
+
+		PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+		PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+		PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+		git pack-objects test --stdin-packs <<-EOF &&
+		$PACK_A
+		^$PACK_B
+		$PACK_C
+		EOF
+
+		(
+			git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+			git show-index <$(ls .git/objects/pack/pack-C-*.idx)
+		) >expect.raw &&
+		git show-index <$(ls test-*.idx) >actual.raw &&
+
+		cut -d" " -f2 <expect.raw | sort >expect &&
+		cut -d" " -f2 <actual.raw | sort >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success '--stdin-packs is incompatible with --filter' '
+	(
+		cd stdin-packs &&
+		test_must_fail git pack-objects --stdin-packs --stdout \
+			--filter=blob:none </dev/null 2>err &&
+		test_i18ngrep "cannot use --filter with --stdin-packs" err
+	)
+'
+
+test_expect_success '--stdin-packs is incompatible with --revs' '
+	(
+		cd stdin-packs &&
+		test_must_fail git pack-objects --stdin-packs --revs out \
+			</dev/null 2>err &&
+		test_i18ngrep "cannot use internal rev list with --stdin-packs" err
+	)
+'
+
+test_expect_success '--stdin-packs with loose objects' '
+	(
+		cd stdin-packs &&
+
+		PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+		PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+		PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+		test_commit D && # loose
+
+		git pack-objects test2 --stdin-packs --unpacked <<-EOF &&
+		$PACK_A
+		^$PACK_B
+		$PACK_C
+		EOF
+
+		(
+			git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+			git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+			git rev-list --objects --no-object-names \
+				refs/tags/C..refs/tags/D
+
+		) >expect.raw &&
+		ls -la . &&
+		git show-index <$(ls test2-*.idx) >actual.raw &&
+
+		cut -d" " -f2 <expect.raw | sort >expect &&
+		cut -d" " -f2 <actual.raw | sort >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success '--stdin-packs with broken links' '
+	(
+		cd stdin-packs &&
+
+		# make an unreachable object with a bogus parent
+		git cat-file -p HEAD >commit &&
+		sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
+		git hash-object -w -t commit --stdin >in &&
+
+		git pack-objects .git/objects/pack/pack-D <in &&
+
+		PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+		PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+		PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+		PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
+
+		git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
+		$PACK_A
+		^$PACK_B
+		$PACK_C
+		$PACK_D
+		EOF
+
+		(
+			git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+			git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+			git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
+			git rev-list --objects --no-object-names \
+				refs/tags/C..refs/tags/D
+		) >expect.raw &&
+		git show-index <$(ls test3-*.idx) >actual.raw &&
+
+		cut -d" " -f2 <expect.raw | sort >expect &&
+		cut -d" " -f2 <actual.raw | sort >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'pack-objects --stdin with duplicate packfile' '
+	test_when_finished "rm -fr repo" &&
+
+	git init repo &&
+	(
+		cd repo &&
+		test_commit "commit" &&
+		git repack -ad &&
+
+		{
+			basename .git/objects/pack/pack-*.pack &&
+			basename .git/objects/pack/pack-*.pack
+		} >packfiles &&
+
+		git pack-objects --stdin-packs generated-pack <packfiles &&
+		packed_objects .git/objects/pack/pack-*.idx >expect &&
+		packed_objects generated-pack-*.idx >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'pack-objects --stdin with same packfile excluded and included' '
+	test_when_finished "rm -fr repo" &&
+
+	git init repo &&
+	(
+		cd repo &&
+		test_commit "commit" &&
+		git repack -ad &&
+
+		{
+			basename .git/objects/pack/pack-*.pack &&
+			printf "^%s\n" "$(basename .git/objects/pack/pack-*.pack)"
+		} >packfiles &&
+
+		git pack-objects --stdin-packs generated-pack <packfiles &&
+		packed_objects generated-pack-*.idx >packed-objects &&
+		test_must_be_empty packed-objects
+	)
+'
+
+test_expect_success 'pack-objects --stdin with packfiles from alternate object database' '
+	test_when_finished "rm -fr shared member" &&
+
+	# Set up a shared repository with a single packfile.
+	git init shared &&
+	test_commit -C shared "shared-objects" &&
+	git -C shared repack -ad &&
+	basename shared/.git/objects/pack/pack-*.pack >packfile &&
+
+	# Set up a repository that is connected to the shared repository. This
+	# repository has no objects on its own, but we still expect to be able
+	# to pack objects from its alternate.
+	git clone --shared shared member &&
+	git -C member pack-objects --stdin-packs generated-pack <packfile &&
+	test_cmp shared/.git/objects/pack/pack-*.pack member/generated-pack-*.pack
+'
+
+test_expect_success 'pack-objects --stdin with packfiles from main and alternate object database' '
+	test_when_finished "rm -fr shared member" &&
+
+	# Set up a shared repository with a single packfile.
+	git init shared &&
+	test_commit -C shared "shared-commit" &&
+	git -C shared repack -ad &&
+
+	# Set up a repository that is connected to the shared repository. This
+	# repository has a second packfile so that we can verify that it is
+	# possible to write packs that include packfiles from different object
+	# databases.
+	git clone --shared shared member &&
+	test_commit -C member "local-commit" &&
+	git -C member repack -dl &&
+
+	{
+		basename shared/.git/objects/pack/pack-*.pack &&
+		basename member/.git/objects/pack/pack-*.pack
+	} >packfiles &&
+
+	{
+		packed_objects shared/.git/objects/pack/pack-*.idx &&
+		packed_objects member/.git/objects/pack/pack-*.idx
+	} | sort >expected-objects &&
+
+	git -C member pack-objects --stdin-packs generated-pack <packfiles &&
+	packed_objects member/generated-pack-*.idx >actual-objects &&
+	test_cmp expected-objects actual-objects
+'
+
+test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 34a1261..4f28906 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -1118,58 +1118,14 @@
 	)
 '
 
-test_expect_success 'fetch aligned output' '
-	git clone . full-output &&
-	test_commit looooooooooooong-tag &&
-	(
-		cd full-output &&
-		git -c fetch.output=full fetch origin >actual 2>&1 &&
-		grep -e "->" actual | cut -c 22- >../actual
-	) &&
-	cat >expect <<-\EOF &&
-	main                 -> origin/main
-	looooooooooooong-tag -> looooooooooooong-tag
-	EOF
-	test_cmp expect actual
-'
-
-test_expect_success 'fetch compact output' '
-	git clone . compact &&
-	test_commit extraaa &&
-	(
-		cd compact &&
-		git -c fetch.output=compact fetch origin >actual 2>&1 &&
-		grep -e "->" actual | cut -c 22- >../actual
-	) &&
-	cat >expect <<-\EOF &&
-	main       -> origin/*
-	extraaa    -> *
-	EOF
-	test_cmp expect actual
-'
-
-test_expect_success '--no-show-forced-updates' '
-	mkdir forced-updates &&
-	(
-		cd forced-updates &&
-		git init &&
-		test_commit 1 &&
-		test_commit 2
-	) &&
-	git clone forced-updates forced-update-clone &&
-	git clone forced-updates no-forced-update-clone &&
-	git -C forced-updates reset --hard HEAD~1 &&
-	(
-		cd forced-update-clone &&
-		git fetch --show-forced-updates origin 2>output &&
-		test_i18ngrep "(forced update)" output
-	) &&
-	(
-		cd no-forced-update-clone &&
-		git fetch --no-show-forced-updates origin 2>output &&
-		test_i18ngrep ! "(forced update)" output
-	)
-'
+for section in fetch transfer
+do
+	test_expect_success "$section.hideRefs affects connectivity check" '
+		GIT_TRACE="$PWD"/trace git -c $section.hideRefs=refs -c \
+			$section.hideRefs="!refs/tags/" fetch &&
+		grep "git rev-list .*--exclude-hidden=fetch" trace
+	'
+done
 
 setup_negotiation_tip () {
 	SERVER="$1"
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 20d063f..151c76e 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -15,6 +15,19 @@
 	done
 }
 
+test_expect_success 'set up fake upload-pack' '
+	# This can be used to simulate an upload-pack that just shows the
+	# contents of the "input" file (prepared with the test-tool pkt-line
+	# helper), and does not do any negotiation (since ls-remote does not
+	# need it).
+	write_script cat-input <<-\EOF
+	# send our initial advertisement/response
+	cat input
+	# soak up the flush packet from the client
+	cat
+	EOF
+'
+
 test_expect_success 'dies when no remote found' '
 	test_must_fail git ls-remote
 '
@@ -231,22 +244,25 @@
 
 test_expect_success 'ls-remote --symref' '
 	git fetch origin &&
-	echo "ref: refs/heads/main	HEAD" >expect &&
+	echo "ref: refs/heads/main	HEAD" >expect.v2 &&
 	generate_references \
 		HEAD \
-		refs/heads/main >>expect &&
+		refs/heads/main >>expect.v2 &&
+	echo "ref: refs/remotes/origin/main	refs/remotes/origin/HEAD" >>expect.v2 &&
 	oid=$(git rev-parse HEAD) &&
-	echo "$oid	refs/remotes/origin/HEAD" >>expect &&
+	echo "$oid	refs/remotes/origin/HEAD" >>expect.v2 &&
 	generate_references \
 		refs/remotes/origin/main \
 		refs/tags/mark \
 		refs/tags/mark1.1 \
 		refs/tags/mark1.10 \
-		refs/tags/mark1.2 >>expect &&
-	# Protocol v2 supports sending symrefs for refs other than HEAD, so use
-	# protocol v0 here.
-	GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref >actual &&
-	test_cmp expect actual
+		refs/tags/mark1.2 >>expect.v2 &&
+	# v0 does not show non-HEAD symrefs
+	grep -v "ref: refs/remotes" <expect.v2 >expect.v0 &&
+	git -c protocol.version=0 ls-remote --symref >actual.v0 &&
+	test_cmp expect.v0 actual.v0 &&
+	git -c protocol.version=2 ls-remote --symref >actual.v2 &&
+	test_cmp expect.v2 actual.v2
 '
 
 test_expect_success 'ls-remote with filtered symref (refname)' '
@@ -255,76 +271,41 @@
 	ref: refs/heads/main	HEAD
 	$rev	HEAD
 	EOF
-	# Protocol v2 supports sending symrefs for refs other than HEAD, so use
-	# protocol v0 here.
-	GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . HEAD >actual &&
+	git ls-remote --symref . HEAD >actual &&
 	test_cmp expect actual
 '
 
-test_expect_failure 'ls-remote with filtered symref (--heads)' '
+test_expect_success 'ls-remote with filtered symref (--heads)' '
 	git symbolic-ref refs/heads/foo refs/tags/mark &&
-	cat >expect <<-EOF &&
+	cat >expect.v2 <<-EOF &&
 	ref: refs/tags/mark	refs/heads/foo
 	$rev	refs/heads/foo
 	$rev	refs/heads/main
 	EOF
-	# Protocol v2 supports sending symrefs for refs other than HEAD, so use
-	# protocol v0 here.
-	GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
-	test_cmp expect actual
+	grep -v "^ref: refs/tags/" <expect.v2 >expect.v0 &&
+	git -c protocol.version=0 ls-remote --symref --heads . >actual.v0 &&
+	test_cmp expect.v0 actual.v0 &&
+	git -c protocol.version=2 ls-remote --symref --heads . >actual.v2 &&
+	test_cmp expect.v2 actual.v2
 '
 
-test_expect_success 'ls-remote --symref omits filtered-out matches' '
-	cat >expect <<-EOF &&
-	$rev	refs/heads/foo
-	$rev	refs/heads/main
+test_expect_success 'indicate no refs in v0 standards-compliant empty remote' '
+	# Git does not produce an output like this, but it does match the
+	# standard and is produced by other implementations like JGit. So
+	# hard-code the case we care about.
+	#
+	# The actual capabilities do not matter; there are none that would
+	# change how ls-remote behaves.
+	oid=0000000000000000000000000000000000000000 &&
+	test-tool pkt-line pack >input.q <<-EOF &&
+	$oid capabilities^{}Qcaps-go-here
+	0000
 	EOF
-	# Protocol v2 supports sending symrefs for refs other than HEAD, so use
-	# protocol v0 here.
-	GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
-	test_cmp expect actual &&
-	GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . "refs/heads/*" >actual &&
-	test_cmp expect actual
-'
+	q_to_nul <input.q >input &&
 
-test_lazy_prereq GIT_DAEMON '
-	test_bool_env GIT_TEST_GIT_DAEMON true
-'
-
-# This test spawns a daemon, so run it only if the user would be OK with
-# testing with git-daemon.
-test_expect_success PIPE,JGIT,GIT_DAEMON 'indicate no refs in standards-compliant empty remote' '
-	test_set_port JGIT_DAEMON_PORT &&
-	JGIT_DAEMON_PID= &&
-	git init --bare empty.git &&
-	>empty.git/git-daemon-export-ok &&
-	mkfifo jgit_daemon_output &&
-	{
-		jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
-		JGIT_DAEMON_PID=$!
-	} &&
-	test_when_finished kill "$JGIT_DAEMON_PID" &&
-	{
-		read line &&
-		case $line in
-		Exporting*)
-			;;
-		*)
-			echo "Expected: Exporting" &&
-			false;;
-		esac &&
-		read line &&
-		case $line in
-		"Listening on"*)
-			;;
-		*)
-			echo "Expected: Listening on" &&
-			false;;
-		esac
-	} <jgit_daemon_output &&
 	# --exit-code asks the command to exit with 2 when no
 	# matching refs are found.
-	test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
+	test_expect_code 2 git ls-remote --exit-code --upload-pack=./cat-input .
 '
 
 test_expect_success 'ls-remote works outside repository' '
@@ -345,8 +326,8 @@
 test_expect_success 'ls-remote patterns work with all protocol versions' '
 	git for-each-ref --format="%(objectname)	%(refname)" \
 		refs/heads/main refs/remotes/origin/main >expect &&
-	git -c protocol.version=1 ls-remote . main >actual.v1 &&
-	test_cmp expect actual.v1 &&
+	git -c protocol.version=0 ls-remote . main >actual.v0 &&
+	test_cmp expect actual.v0 &&
 	git -c protocol.version=2 ls-remote . main >actual.v2 &&
 	test_cmp expect actual.v2
 '
@@ -354,10 +335,49 @@
 test_expect_success 'ls-remote prefixes work with all protocol versions' '
 	git for-each-ref --format="%(objectname)	%(refname)" \
 		refs/heads/ refs/tags/ >expect &&
-	git -c protocol.version=1 ls-remote --heads --tags . >actual.v1 &&
-	test_cmp expect actual.v1 &&
+	git -c protocol.version=0 ls-remote --heads --tags . >actual.v0 &&
+	test_cmp expect actual.v0 &&
 	git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 &&
 	test_cmp expect actual.v2
 '
 
+test_expect_success 'v0 clients can handle multiple symrefs' '
+	# Modern versions of Git will not return multiple symref capabilities
+	# for v0, so we have to hard-code the response. Note that we will
+	# always use both v0 and object-format=sha1 here, as the hard-coded
+	# response reflects a server that only supports those.
+	oid=1234567890123456789012345678901234567890 &&
+	symrefs="symref=refs/remotes/origin/HEAD:refs/remotes/origin/main" &&
+	symrefs="$symrefs symref=HEAD:refs/heads/main" &&
+
+	# Likewise we want to make sure our parser is not fooled by the string
+	# "symref" appearing as part of an earlier cap. But there is no way to
+	# do that via upload-pack, as arbitrary strings can appear only in a
+	# "symref" value itself (where we skip past the values as a whole)
+	# and "agent" (which always appears after "symref", so putting our
+	# parser in a confused state is less interesting).
+	caps="some other caps including a-fake-symref-cap" &&
+
+	test-tool pkt-line pack >input.q <<-EOF &&
+	$oid HEADQ$caps $symrefs
+	$oid refs/heads/main
+	$oid refs/remotes/origin/HEAD
+	$oid refs/remotes/origin/main
+	0000
+	EOF
+	q_to_nul <input.q >input &&
+
+	cat >expect <<-EOF &&
+	ref: refs/heads/main	HEAD
+	$oid	HEAD
+	$oid	refs/heads/main
+	ref: refs/remotes/origin/main	refs/remotes/origin/HEAD
+	$oid	refs/remotes/origin/HEAD
+	$oid	refs/remotes/origin/main
+	EOF
+
+	git ls-remote --symref --upload-pack=./cat-input . >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh
index 54f422c..98f034a 100755
--- a/t/t5514-fetch-multiple.sh
+++ b/t/t5514-fetch-multiple.sh
@@ -58,6 +58,13 @@
 	 test_cmp expect output)
 '
 
+test_expect_success 'git fetch --all --no-write-fetch-head' '
+	(cd test &&
+	rm -f .git/FETCH_HEAD &&
+	git fetch --all --no-write-fetch-head &&
+	test_path_is_missing .git/FETCH_HEAD)
+'
+
 test_expect_success 'git fetch --all should continue if a remote has errors' '
 	(git clone one test2 &&
 	 cd test2 &&
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 98a27a29..19ebefa 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -401,6 +401,11 @@
 
 '
 
+test_expect_success 'push with onelevel ref' '
+	mk_test testrepo heads/main &&
+	test_must_fail git push testrepo HEAD:refs/onelevel
+'
+
 test_expect_success 'push with colon-less refspec (1)' '
 
 	mk_test testrepo heads/frotz tags/frotz &&
@@ -898,6 +903,13 @@
 	test_must_fail git push testrepo --delete ""
 '
 
+test_expect_success 'push --delete onelevel refspecs' '
+	mk_test testrepo heads/main &&
+	git -C testrepo update-ref refs/onelevel refs/heads/main &&
+	git push testrepo --delete refs/onelevel &&
+	test_must_fail git -C testrepo rev-parse --verify refs/onelevel
+'
+
 test_expect_success 'warn on push to HEAD of non-bare repository' '
 	mk_test testrepo heads/main &&
 	(
diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh
index 394bc60..cc5496e 100755
--- a/t/t5522-pull-symlink.sh
+++ b/t/t5522-pull-symlink.sh
@@ -79,7 +79,9 @@
 		git commit -m push ./file &&
 		git push
 	) &&
-	test push = $(git show HEAD:subdir/file)
+	echo push >expect &&
+	git show HEAD:subdir/file >actual &&
+	test_cmp expect actual
 '
 
 test_done
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index c9acc07..1b8d609 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -61,12 +61,20 @@
 	check_config topic_2 upstream refs/heads/other2
 '
 
-test_expect_success 'push -u --all' '
+test_expect_success 'push -u --all(the same behavior with--branches)' '
 	git branch all1 &&
 	git branch all2 &&
 	git push -u --all &&
 	check_config all1 upstream refs/heads/all1 &&
-	check_config all2 upstream refs/heads/all2
+	check_config all2 upstream refs/heads/all2 &&
+	git config --get-regexp branch.all* > expect &&
+	git config --remove-section branch.all1 &&
+	git config --remove-section branch.all2 &&
+	git push -u --branches &&
+	check_config all1 upstream refs/heads/all1 &&
+	check_config all2 upstream refs/heads/all2 &&
+	git config --get-regexp branch.all* > actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'push -u HEAD' '
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index b9546ef..26e933f 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -167,6 +167,19 @@
 	verify_fetch_result actual.err
 '
 
+test_expect_success "fetch --recurse-submodules honors --no-write-fetch-head" '
+	(
+		cd downstream &&
+		git submodule foreach --recursive \
+		sh -c "cd \"\$(git rev-parse --git-dir)\" && rm -f FETCH_HEAD" &&
+
+		git fetch --recurse-submodules --no-write-fetch-head &&
+
+		git submodule foreach --recursive \
+		sh -c "cd \"\$(git rev-parse --git-dir)\" && ! test -f FETCH_HEAD"
+	)
+'
+
 test_expect_success "submodule.recurse option triggers recursive fetch" '
 	add_submodule_commits &&
 	(
@@ -1167,4 +1180,17 @@
 	test_line_count = 2 fetch-subs
 '
 
+test_expect_success "fetch --all with --no-recurse-submodules only fetches superproject" '
+	test_when_finished "rm -rf src_clone" &&
+
+	git clone --recurse-submodules src src_clone &&
+	(
+		cd src_clone &&
+		git remote add secondary ../src &&
+		git config submodule.recurse true &&
+		git fetch --all --no-recurse-submodules 2>../fetch-log
+	) &&
+	! grep "Fetching submodule" fetch-log
+'
+
 test_done
diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh
index 7043112..04b47ad 100755
--- a/t/t5543-atomic-push.sh
+++ b/t/t5543-atomic-push.sh
@@ -117,7 +117,10 @@
 		test_commit five &&
 		git checkout main &&
 		test_commit six &&
-		test_must_fail git push --atomic --all up
+		test_must_fail git push --atomic --all up >output-all 2>&1 &&
+		# --all and --branches have the same behavior when be combined with --atomic
+		test_must_fail git push --atomic --branches up >output-branches 2>&1 &&
+		test_cmp output-all output-branches
 	) &&
 	test_refs main HEAD@{7} &&
 	test_refs second HEAD@{4}
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 0908534..21b7767 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -611,6 +611,33 @@
 	grep symref=HEAD:refs/heads/ trace
 '
 
+test_expect_success 'create empty http-accessible SHA-256 repository' '
+	mkdir "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
+	(cd "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
+	 git --bare init --object-format=sha256
+	)
+'
+
+test_expect_success 'clone empty SHA-256 repository with protocol v2' '
+	rm -fr sha256 &&
+	echo sha256 >expected &&
+	git -c protocol.version=2 clone "$HTTPD_URL/smart/sha256.git" &&
+	git -C sha256 rev-parse --show-object-format >actual &&
+	test_cmp actual expected &&
+	git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
+	test_must_be_empty actual
+'
+
+test_expect_success 'clone empty SHA-256 repository with protocol v0' '
+	rm -fr sha256 &&
+	echo sha256 >expected &&
+	GIT_TRACE=1 GIT_TRACE_PACKET=1 git -c protocol.version=0 clone "$HTTPD_URL/smart/sha256.git" &&
+	git -C sha256 rev-parse --show-object-format >actual &&
+	test_cmp actual expected &&
+	git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
+	test_must_be_empty actual
+'
+
 test_expect_success 'passing hostname resolution information works' '
 	BOGUS_HOST=gitbogusexamplehost.invalid &&
 	BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT &&
diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh
index 165427d..b55a9f6 100755
--- a/t/t5552-skipping-fetch-negotiator.sh
+++ b/t/t5552-skipping-fetch-negotiator.sh
@@ -3,6 +3,22 @@
 test_description='test skipping fetch negotiator'
 . ./test-lib.sh
 
+test_expect_success 'fetch.negotiationalgorithm config' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	cat >repo/.git/config <<-\EOF &&
+	[fetch]
+	negotiationAlgorithm
+	EOF
+	cat >expect <<-\EOF &&
+	error: missing value for '\''fetch.negotiationalgorithm'\''
+	fatal: bad config variable '\''fetch.negotiationalgorithm'\'' in file '\''.git/config'\'' at line 2
+	EOF
+	test_expect_code 128 git -C repo fetch >out 2>actual &&
+	test_must_be_empty out &&
+	test_cmp expect actual
+'
+
 have_sent () {
 	while test "$#" -ne 0
 	do
diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh
index afd5692..996a08e 100755
--- a/t/t5558-clone-bundle-uri.sh
+++ b/t/t5558-clone-bundle-uri.sh
@@ -1018,6 +1018,40 @@
 	test_cmp expect refs
 '
 
+test_expect_success 'bundles are downloaded once during fetch --all' '
+	test_when_finished rm -rf download-* trace*.txt fetch-mult &&
+
+	cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+	[bundle]
+		version = 1
+		mode = all
+		heuristic = creationToken
+
+	[bundle "bundle-1"]
+		uri = bundle-1.bundle
+		creationToken = 1
+
+	[bundle "bundle-2"]
+		uri = bundle-2.bundle
+		creationToken = 2
+
+	[bundle "bundle-3"]
+		uri = bundle-3.bundle
+		creationToken = 3
+	EOF
+
+	git clone --single-branch --branch=left \
+		--bundle-uri="$HTTPD_URL/bundle-list" \
+		"$HTTPD_URL/smart/fetch.git" fetch-mult &&
+	git -C fetch-mult remote add dup1 "$HTTPD_URL/smart/fetch.git" &&
+	git -C fetch-mult remote add dup2 "$HTTPD_URL/smart/fetch.git" &&
+
+	GIT_TRACE2_EVENT="$(pwd)/trace-mult.txt" \
+		git -C fetch-mult fetch --all &&
+	grep "\"child_start\".*\"git-remote-https\",\"$HTTPD_URL/bundle-list\"" \
+		trace-mult.txt >bundle-fetches &&
+	test_line_count = 1 bundle-fetches
+'
 # Do not add tests here unless they use the HTTP server, as they will
 # not run unless the HTTP dependencies exist.
 
diff --git a/t/t5563-simple-http-auth.sh b/t/t5563-simple-http-auth.sh
new file mode 100755
index 0000000..ab8a721
--- /dev/null
+++ b/t/t5563-simple-http-auth.sh
@@ -0,0 +1,329 @@
+#!/bin/sh
+
+test_description='test http auth header and credential helper interop'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-httpd.sh
+
+enable_cgipassauth
+if ! test_have_prereq CGIPASSAUTH
+then
+	skip_all="no CGIPassAuth support"
+	test_done
+fi
+start_httpd
+
+test_expect_success 'setup_credential_helper' '
+	mkdir "$TRASH_DIRECTORY/bin" &&
+	PATH=$PATH:"$TRASH_DIRECTORY/bin" &&
+	export PATH &&
+
+	CREDENTIAL_HELPER="$TRASH_DIRECTORY/bin/git-credential-test-helper" &&
+	write_script "$CREDENTIAL_HELPER" <<-\EOF
+	cmd=$1
+	teefile=$cmd-query.cred
+	catfile=$cmd-reply.cred
+	sed -n -e "/^$/q" -e "p" >>$teefile
+	if test "$cmd" = "get"
+	then
+		cat $catfile
+	fi
+	EOF
+'
+
+set_credential_reply () {
+	cat >"$TRASH_DIRECTORY/$1-reply.cred"
+}
+
+expect_credential_query () {
+	cat >"$TRASH_DIRECTORY/$1-expect.cred" &&
+	test_cmp "$TRASH_DIRECTORY/$1-expect.cred" \
+		 "$TRASH_DIRECTORY/$1-query.cred"
+}
+
+per_test_cleanup () {
+	rm -f *.cred &&
+	rm -f "$HTTPD_ROOT_PATH"/custom-auth.valid \
+	      "$HTTPD_ROOT_PATH"/custom-auth.challenge
+}
+
+test_expect_success 'setup repository' '
+	test_commit foo &&
+	git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+	git push --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git"
+'
+
+test_expect_success 'access using basic auth' '
+	test_when_finished "per_test_cleanup" &&
+
+	set_credential_reply get <<-EOF &&
+	username=alice
+	password=secret-passwd
+	EOF
+
+	# Basic base64(alice:secret-passwd)
+	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+	EOF
+
+	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+	WWW-Authenticate: Basic realm="example.com"
+	EOF
+
+	test_config_global credential.helper test-helper &&
+	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+	expect_credential_query get <<-EOF &&
+	protocol=http
+	host=$HTTPD_DEST
+	wwwauth[]=Basic realm="example.com"
+	EOF
+
+	expect_credential_query store <<-EOF
+	protocol=http
+	host=$HTTPD_DEST
+	username=alice
+	password=secret-passwd
+	EOF
+'
+
+test_expect_success 'access using basic auth invalid credentials' '
+	test_when_finished "per_test_cleanup" &&
+
+	set_credential_reply get <<-EOF &&
+	username=baduser
+	password=wrong-passwd
+	EOF
+
+	# Basic base64(alice:secret-passwd)
+	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+	EOF
+
+	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+	WWW-Authenticate: Basic realm="example.com"
+	EOF
+
+	test_config_global credential.helper test-helper &&
+	test_must_fail git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+	expect_credential_query get <<-EOF &&
+	protocol=http
+	host=$HTTPD_DEST
+	wwwauth[]=Basic realm="example.com"
+	EOF
+
+	expect_credential_query erase <<-EOF
+	protocol=http
+	host=$HTTPD_DEST
+	username=baduser
+	password=wrong-passwd
+	wwwauth[]=Basic realm="example.com"
+	EOF
+'
+
+test_expect_success 'access using basic auth with extra challenges' '
+	test_when_finished "per_test_cleanup" &&
+
+	set_credential_reply get <<-EOF &&
+	username=alice
+	password=secret-passwd
+	EOF
+
+	# Basic base64(alice:secret-passwd)
+	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+	EOF
+
+	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+	WWW-Authenticate: FooBar param1="value1" param2="value2"
+	WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
+	WWW-Authenticate: Basic realm="example.com"
+	EOF
+
+	test_config_global credential.helper test-helper &&
+	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+	expect_credential_query get <<-EOF &&
+	protocol=http
+	host=$HTTPD_DEST
+	wwwauth[]=FooBar param1="value1" param2="value2"
+	wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+	wwwauth[]=Basic realm="example.com"
+	EOF
+
+	expect_credential_query store <<-EOF
+	protocol=http
+	host=$HTTPD_DEST
+	username=alice
+	password=secret-passwd
+	EOF
+'
+
+test_expect_success 'access using basic auth mixed-case wwwauth header name' '
+	test_when_finished "per_test_cleanup" &&
+
+	set_credential_reply get <<-EOF &&
+	username=alice
+	password=secret-passwd
+	EOF
+
+	# Basic base64(alice:secret-passwd)
+	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+	EOF
+
+	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+	www-authenticate: foobar param1="value1" param2="value2"
+	WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0
+	WwW-aUtHeNtIcAtE: baSiC realm="example.com"
+	EOF
+
+	test_config_global credential.helper test-helper &&
+	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+	expect_credential_query get <<-EOF &&
+	protocol=http
+	host=$HTTPD_DEST
+	wwwauth[]=foobar param1="value1" param2="value2"
+	wwwauth[]=BEARER authorize_uri="id.example.com" p=1 q=0
+	wwwauth[]=baSiC realm="example.com"
+	EOF
+
+	expect_credential_query store <<-EOF
+	protocol=http
+	host=$HTTPD_DEST
+	username=alice
+	password=secret-passwd
+	EOF
+'
+
+test_expect_success 'access using basic auth with wwwauth header continuations' '
+	test_when_finished "per_test_cleanup" &&
+
+	set_credential_reply get <<-EOF &&
+	username=alice
+	password=secret-passwd
+	EOF
+
+	# Basic base64(alice:secret-passwd)
+	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+	EOF
+
+	# Note that leading and trailing whitespace is important to correctly
+	# simulate a continuation/folded header.
+	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+	WWW-Authenticate: FooBar param1="value1"
+	 param2="value2"
+	WWW-Authenticate: Bearer authorize_uri="id.example.com"
+	 p=1
+	 q=0
+	WWW-Authenticate: Basic realm="example.com"
+	EOF
+
+	test_config_global credential.helper test-helper &&
+	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+	expect_credential_query get <<-EOF &&
+	protocol=http
+	host=$HTTPD_DEST
+	wwwauth[]=FooBar param1="value1" param2="value2"
+	wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+	wwwauth[]=Basic realm="example.com"
+	EOF
+
+	expect_credential_query store <<-EOF
+	protocol=http
+	host=$HTTPD_DEST
+	username=alice
+	password=secret-passwd
+	EOF
+'
+
+test_expect_success 'access using basic auth with wwwauth header empty continuations' '
+	test_when_finished "per_test_cleanup" &&
+
+	set_credential_reply get <<-EOF &&
+	username=alice
+	password=secret-passwd
+	EOF
+
+	# Basic base64(alice:secret-passwd)
+	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+	EOF
+
+	CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
+
+	# Note that leading and trailing whitespace is important to correctly
+	# simulate a continuation/folded header.
+	printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" &&
+	printf " \r\n" >>"$CHALLENGE" &&
+	printf " param2=\"value2\"\r\n" >>"$CHALLENGE" &&
+	printf "WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>"$CHALLENGE" &&
+	printf " p=1\r\n" >>"$CHALLENGE" &&
+	printf " \r\n" >>"$CHALLENGE" &&
+	printf " q=0\r\n" >>"$CHALLENGE" &&
+	printf "WWW-Authenticate: Basic realm=\"example.com\"\r\n" >>"$CHALLENGE" &&
+
+	test_config_global credential.helper test-helper &&
+	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+	expect_credential_query get <<-EOF &&
+	protocol=http
+	host=$HTTPD_DEST
+	wwwauth[]=FooBar param1="value1" param2="value2"
+	wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+	wwwauth[]=Basic realm="example.com"
+	EOF
+
+	expect_credential_query store <<-EOF
+	protocol=http
+	host=$HTTPD_DEST
+	username=alice
+	password=secret-passwd
+	EOF
+'
+
+test_expect_success 'access using basic auth with wwwauth header mixed line-endings' '
+	test_when_finished "per_test_cleanup" &&
+
+	set_credential_reply get <<-EOF &&
+	username=alice
+	password=secret-passwd
+	EOF
+
+	# Basic base64(alice:secret-passwd)
+	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+	EOF
+
+	CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
+
+	# Note that leading and trailing whitespace is important to correctly
+	# simulate a continuation/folded header.
+	printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" &&
+	printf " \r\n" >>"$CHALLENGE" &&
+	printf "\tparam2=\"value2\"\r\n" >>"$CHALLENGE" &&
+	printf "WWW-Authenticate: Basic realm=\"example.com\"" >>"$CHALLENGE" &&
+
+	test_config_global credential.helper test-helper &&
+	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+	expect_credential_query get <<-EOF &&
+	protocol=http
+	host=$HTTPD_DEST
+	wwwauth[]=FooBar param1="value1" param2="value2"
+	wwwauth[]=Basic realm="example.com"
+	EOF
+
+	expect_credential_query store <<-EOF
+	protocol=http
+	host=$HTTPD_DEST
+	username=alice
+	password=secret-passwd
+	EOF
+'
+
+test_done
diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh
index 09097ef..4e917bf 100755
--- a/t/t5572-pull-submodule.sh
+++ b/t/t5572-pull-submodule.sh
@@ -121,7 +121,7 @@
 	sub_oid=$(git -C child rev-parse HEAD) &&
 	git -C super/sub cat-file -e $sub_oid &&
 	# Check that the submodule worktree did not update
-	! test_path_is_file super/sub/merge_strategy_5.t
+	test_path_is_missing super/sub/merge_strategy_5.t
 '
 
 test_expect_success "fetch.recurseSubmodules takes precedence over submodule.recurse" '
@@ -134,7 +134,7 @@
 	sub_oid=$(git -C child rev-parse HEAD) &&
 	git -C super/sub cat-file -e $sub_oid &&
 	# Check that the submodule worktree did not update
-	! test_path_is_file super/sub/merge_strategy_6.t
+	test_path_is_missing super/sub/merge_strategy_6.t
 '
 
 test_expect_success 'pull --rebase --recurse-submodules (remote superproject submodule changes, local submodule changes)' '
diff --git a/t/t5574-fetch-output.sh b/t/t5574-fetch-output.sh
new file mode 100755
index 0000000..90e6dcb
--- /dev/null
+++ b/t/t5574-fetch-output.sh
@@ -0,0 +1,293 @@
+#!/bin/sh
+
+test_description='git fetch output format'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+test_expect_success 'fetch with invalid output format configuration' '
+	test_when_finished "rm -rf clone" &&
+	git clone . clone &&
+
+	test_must_fail git -C clone -c fetch.output fetch origin 2>actual.err &&
+	cat >expect <<-EOF &&
+	error: missing value for ${SQ}fetch.output${SQ}
+	fatal: unable to parse ${SQ}fetch.output${SQ} from command-line config
+	EOF
+	test_cmp expect actual.err &&
+
+	test_must_fail git -C clone -c fetch.output= fetch origin 2>actual.err &&
+	cat >expect <<-EOF &&
+	fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}${SQ}
+	EOF
+	test_cmp expect actual.err &&
+
+	test_must_fail git -C clone -c fetch.output=garbage fetch origin 2>actual.err &&
+	cat >expect <<-EOF &&
+	fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}garbage${SQ}
+	EOF
+	test_cmp expect actual.err
+'
+
+test_expect_success 'fetch aligned output' '
+	git clone . full-output &&
+	test_commit looooooooooooong-tag &&
+	(
+		cd full-output &&
+		git -c fetch.output=full fetch origin >actual 2>&1 &&
+		grep -e "->" actual | cut -c 22- >../actual
+	) &&
+	cat >expect <<-\EOF &&
+	main                 -> origin/main
+	looooooooooooong-tag -> looooooooooooong-tag
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'fetch compact output' '
+	git clone . compact &&
+	test_commit extraaa &&
+	(
+		cd compact &&
+		git -c fetch.output=compact fetch origin >actual 2>&1 &&
+		grep -e "->" actual | cut -c 22- >../actual
+	) &&
+	cat >expect <<-\EOF &&
+	main       -> origin/*
+	extraaa    -> *
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'fetch porcelain output' '
+	test_when_finished "rm -rf porcelain" &&
+
+	# Set up a bunch of references that we can use to demonstrate different
+	# kinds of flag symbols in the output format.
+	MAIN_OLD=$(git rev-parse HEAD) &&
+	git branch "fast-forward" &&
+	git branch "deleted-branch" &&
+	git checkout -b force-updated &&
+	test_commit --no-tag force-update-old &&
+	FORCE_UPDATED_OLD=$(git rev-parse HEAD) &&
+	git checkout main &&
+
+	# Clone and pre-seed the repositories. We fetch references into two
+	# namespaces so that we can test that rejected and force-updated
+	# references are reported properly.
+	refspecs="refs/heads/*:refs/unforced/* +refs/heads/*:refs/forced/*" &&
+	git clone . porcelain &&
+	git -C porcelain fetch origin $refspecs &&
+
+	# Now that we have set up the client repositories we can change our
+	# local references.
+	git branch new-branch &&
+	git branch -d deleted-branch &&
+	git checkout fast-forward &&
+	test_commit --no-tag fast-forward-new &&
+	FAST_FORWARD_NEW=$(git rev-parse HEAD) &&
+	git checkout force-updated &&
+	git reset --hard HEAD~ &&
+	test_commit --no-tag force-update-new &&
+	FORCE_UPDATED_NEW=$(git rev-parse HEAD) &&
+
+	cat >expect <<-EOF &&
+	- $MAIN_OLD $ZERO_OID refs/forced/deleted-branch
+	- $MAIN_OLD $ZERO_OID refs/unforced/deleted-branch
+	  $MAIN_OLD $FAST_FORWARD_NEW refs/unforced/fast-forward
+	! $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/unforced/force-updated
+	* $ZERO_OID $MAIN_OLD refs/unforced/new-branch
+	  $MAIN_OLD $FAST_FORWARD_NEW refs/forced/fast-forward
+	+ $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/forced/force-updated
+	* $ZERO_OID $MAIN_OLD refs/forced/new-branch
+	  $MAIN_OLD $FAST_FORWARD_NEW refs/remotes/origin/fast-forward
+	+ $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/remotes/origin/force-updated
+	* $ZERO_OID $MAIN_OLD refs/remotes/origin/new-branch
+	EOF
+
+	# Execute a dry-run fetch first. We do this to assert that the dry-run
+	# and non-dry-run fetches produces the same output. Execution of the
+	# fetch is expected to fail as we have a rejected reference update.
+	test_must_fail git -C porcelain fetch \
+		--porcelain --dry-run --prune origin $refspecs >actual &&
+	test_cmp expect actual &&
+
+	# And now we perform a non-dry-run fetch.
+	test_must_fail git -C porcelain fetch \
+		--porcelain --prune origin $refspecs >actual 2>stderr &&
+	test_cmp expect actual &&
+	test_must_be_empty stderr
+'
+
+test_expect_success 'fetch porcelain with multiple remotes' '
+	test_when_finished "rm -rf porcelain" &&
+
+	git switch --create multiple-remotes &&
+	git clone . porcelain &&
+	git -C porcelain remote add second-remote "$PWD" &&
+	git -C porcelain fetch second-remote &&
+
+	test_commit --no-tag multi-commit &&
+	old_commit=$(git rev-parse HEAD~) &&
+	new_commit=$(git rev-parse HEAD) &&
+
+	cat >expect <<-EOF &&
+	  $old_commit $new_commit refs/remotes/origin/multiple-remotes
+	  $old_commit $new_commit refs/remotes/second-remote/multiple-remotes
+	EOF
+
+	git -C porcelain fetch --porcelain --all >actual 2>stderr &&
+	test_cmp expect actual &&
+	test_must_be_empty stderr
+'
+
+test_expect_success 'fetch porcelain refuses to work with submodules' '
+	test_when_finished "rm -rf porcelain" &&
+
+	cat >expect <<-EOF &&
+	fatal: options ${SQ}--porcelain${SQ} and ${SQ}--recurse-submodules${SQ} cannot be used together
+	EOF
+
+	git init porcelain &&
+	test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=yes 2>stderr &&
+	test_cmp expect stderr &&
+
+	test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=on-demand 2>stderr &&
+	test_cmp expect stderr
+'
+
+test_expect_success 'fetch porcelain overrides fetch.output config' '
+	test_when_finished "rm -rf porcelain" &&
+
+	git switch --create config-override &&
+	git clone . porcelain &&
+	test_commit new-commit &&
+	old_commit=$(git rev-parse HEAD~) &&
+	new_commit=$(git rev-parse HEAD) &&
+
+	cat >expect <<-EOF &&
+	  $old_commit $new_commit refs/remotes/origin/config-override
+	* $ZERO_OID $new_commit refs/tags/new-commit
+	EOF
+
+	git -C porcelain -c fetch.output=compact fetch --porcelain >stdout 2>stderr &&
+	test_must_be_empty stderr &&
+	test_cmp expect stdout
+'
+
+test_expect_success 'fetch --no-porcelain overrides previous --porcelain' '
+	test_when_finished "rm -rf no-porcelain" &&
+
+	git switch --create no-porcelain &&
+	git clone . no-porcelain &&
+	test_commit --no-tag no-porcelain &&
+	old_commit=$(git rev-parse --short HEAD~) &&
+	new_commit=$(git rev-parse --short HEAD) &&
+
+	cat >expect <<-EOF &&
+	From $(test-tool path-utils real_path .)/.
+	   $old_commit..$new_commit  no-porcelain -> origin/no-porcelain
+	EOF
+
+	git -C no-porcelain fetch --porcelain --no-porcelain >stdout 2>stderr &&
+	test_cmp expect stderr &&
+	test_must_be_empty stdout
+'
+
+test_expect_success 'fetch output with HEAD' '
+	test_when_finished "rm -rf head" &&
+	git clone . head &&
+
+	git -C head fetch --dry-run origin HEAD >actual.out 2>actual.err &&
+	cat >expect <<-EOF &&
+	From $(test-tool path-utils real_path .)/.
+	 * branch            HEAD       -> FETCH_HEAD
+	EOF
+	test_must_be_empty actual.out &&
+	test_cmp expect actual.err &&
+
+	git -C head fetch origin HEAD >actual.out 2>actual.err &&
+	test_must_be_empty actual.out &&
+	test_cmp expect actual.err &&
+
+	git -C head fetch --dry-run origin HEAD:foo >actual.out 2>actual.err &&
+	cat >expect <<-EOF &&
+	From $(test-tool path-utils real_path .)/.
+	 * [new ref]         HEAD       -> foo
+	EOF
+	test_must_be_empty actual.out &&
+	test_cmp expect actual.err &&
+
+	git -C head fetch origin HEAD:foo >actual.out 2>actual.err &&
+	test_must_be_empty actual.out &&
+	test_cmp expect actual.err
+'
+
+test_expect_success 'fetch porcelain output with HEAD' '
+	test_when_finished "rm -rf head" &&
+	git clone . head &&
+	COMMIT_ID=$(git rev-parse HEAD) &&
+
+	git -C head fetch --porcelain --dry-run origin HEAD >actual &&
+	cat >expect <<-EOF &&
+	* $ZERO_OID $COMMIT_ID FETCH_HEAD
+	EOF
+	test_cmp expect actual &&
+
+	git -C head fetch --porcelain origin HEAD >actual &&
+	test_cmp expect actual &&
+
+	git -C head fetch --porcelain --dry-run origin HEAD:foo >actual &&
+	cat >expect <<-EOF &&
+	* $ZERO_OID $COMMIT_ID refs/heads/foo
+	EOF
+	test_cmp expect actual &&
+
+	git -C head fetch --porcelain origin HEAD:foo >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'fetch output with object ID' '
+	test_when_finished "rm -rf object-id" &&
+	git clone . object-id &&
+	commit=$(git rev-parse HEAD) &&
+
+	git -C object-id fetch --dry-run origin $commit:object-id >actual.out 2>actual.err &&
+	cat >expect <<-EOF &&
+	From $(test-tool path-utils real_path .)/.
+	 * [new ref]         $commit -> object-id
+	EOF
+	test_must_be_empty actual.out &&
+	test_cmp expect actual.err &&
+
+	git -C object-id fetch origin $commit:object-id >actual.out 2>actual.err &&
+	test_must_be_empty actual.out &&
+	test_cmp expect actual.err
+'
+
+test_expect_success '--no-show-forced-updates' '
+	mkdir forced-updates &&
+	(
+		cd forced-updates &&
+		git init &&
+		test_commit 1 &&
+		test_commit 2
+	) &&
+	git clone forced-updates forced-update-clone &&
+	git clone forced-updates no-forced-update-clone &&
+	git -C forced-updates reset --hard HEAD~1 &&
+	(
+		cd forced-update-clone &&
+		git fetch --show-forced-updates origin 2>output &&
+		test_i18ngrep "(forced update)" output
+	) &&
+	(
+		cd no-forced-update-clone &&
+		git fetch --no-show-forced-updates origin 2>output &&
+		test_i18ngrep ! "(forced update)" output
+	)
+'
+
+test_done
diff --git a/t/t5583-push-branches.sh b/t/t5583-push-branches.sh
new file mode 100755
index 0000000..e7e1b6d
--- /dev/null
+++ b/t/t5583-push-branches.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+
+test_description='check the consisitency of behavior of --all and --branches'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+delete_refs() {
+	dir=$1
+	shift
+	rm -rf deletes
+	for arg in $*
+	do
+		echo "delete ${arg}" >>deletes
+	done
+	git -C $dir update-ref --stdin < deletes
+}
+
+test_expect_success 'setup bare remote' '
+	git init --bare remote-1 &&
+	git -C remote-1 config gc.auto 0 &&
+	test_commit one &&
+	git push remote-1 HEAD
+'
+
+test_expect_success 'setup different types of references' '
+	cat >refs <<-EOF &&
+	update refs/heads/branch-1 HEAD
+	update refs/heads/branch-2 HEAD
+	EOF
+
+	git tag -a -m "annotated" annotated-1 HEAD &&
+	git tag -a -m "annotated" annotated-2 HEAD &&
+	git update-ref --stdin < refs
+'
+
+test_expect_success '--all and --branches have the same behavior' '
+	test_when_finished "delete_refs remote-1 \
+			   refs/heads/branch-1 \
+			   refs/heads/branch-2" &&
+	git push remote-1 --all &&
+	commit=$(git rev-parse HEAD) &&
+	cat >expect <<-EOF &&
+	$commit refs/heads/branch-1
+	$commit refs/heads/branch-2
+	$commit refs/heads/main
+	EOF
+
+	git -C remote-1 show-ref --heads >actual.all &&
+	delete_refs remote-1 refs/heads/branch-1 refs/heads/branch-2 &&
+	git push remote-1 --branches &&
+	git -C remote-1 show-ref --heads >actual.branches &&
+	test_cmp actual.all actual.branches &&
+	test_cmp expect actual.all
+'
+
+test_expect_success '--all or --branches can not be combined with refspecs' '
+	test_must_fail git push remote-1 --all main >actual.all 2>&1 &&
+	test_must_fail git push remote-1 --branches main >actual.branches 2>&1 &&
+	test_cmp actual.all actual.branches &&
+	grep "be combined with refspecs" actual.all
+'
+
+test_expect_success '--all or --branches can not be combined with --mirror' '
+	test_must_fail git push remote-1 --all --mirror >actual.all 2>&1 &&
+	test_must_fail git push remote-1 --branches --mirror >actual.branches 2>&1 &&
+	test_cmp actual.all actual.branches &&
+	grep "cannot be used together" actual.all
+'
+
+test_expect_success '--all or --branches can not be combined with --tags' '
+	test_must_fail git push remote-1 --all --tags >actual.all 2>&1 &&
+	test_must_fail git push remote-1 --branches --tags >actual.branches 2>&1 &&
+	test_cmp actual.all actual.branches &&
+	grep "cannot be used together" actual.all
+'
+
+
+test_expect_success '--all or --branches can not be combined with --delete' '
+	test_must_fail git push remote-1 --all --delete >actual.all 2>&1 &&
+	test_must_fail git push remote-1 --branches --delete >actual.branches 2>&1 &&
+	test_cmp actual.all actual.branches &&
+	grep "cannot be used together" actual.all
+'
+
+test_expect_success '--all or --branches combines with --follow-tags have same behavior' '
+	test_when_finished "delete_refs remote-1 \
+			   refs/heads/branch-1 \
+			   refs/heads/branch-2 \
+			   refs/tags/annotated-1 \
+			   refs/tags/annotated-2" &&
+	git push remote-1 --all --follow-tags &&
+	git -C remote-1 show-ref > actual.all &&
+	cat >expect <<-EOF &&
+	$commit refs/heads/branch-1
+	$commit refs/heads/branch-2
+	$commit refs/heads/main
+	$(git rev-parse annotated-1) refs/tags/annotated-1
+	$(git rev-parse annotated-2) refs/tags/annotated-2
+	EOF
+
+	delete_refs remote-1 \
+		    refs/heads/branch-1 \
+		    refs/heads/branch-2 \
+		    refs/tags/annotated-1 \
+		    refs/tags/annotated-2 &&
+	git push remote-1 --branches --follow-tags &&
+	git -C remote-1 show-ref >actual.branches &&
+	test_cmp actual.all actual.branches &&
+	test_cmp expect actual.all
+'
+
+test_done
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 83e3c97..9845fc0 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -358,7 +358,7 @@
 	test_must_fail git clone --local malicious clone 2>err &&
 
 	test_path_is_missing clone &&
-	grep "failed to start iterator over" err
+	grep "is a symlink, refusing to clone with --local" err
 '
 
 test_done
diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh
index 38b850c..1d7b1ab 100755
--- a/t/t5605-clone-local.sh
+++ b/t/t5605-clone-local.sh
@@ -15,8 +15,12 @@
 	: >file && git add . && git commit -m1 &&
 	git clone --bare . a.git &&
 	git clone --bare . x &&
-	test "$(cd a.git && git config --bool core.bare)" = true &&
-	test "$(cd x && git config --bool core.bare)" = true &&
+	echo true >expect &&
+	git -C a.git config --bool core.bare >actual &&
+	test_cmp expect actual &&
+	echo true >expect &&
+	git -C x config --bool core.bare >actual &&
+	test_cmp expect actual &&
 	git bundle create b1.bundle --all &&
 	git bundle create b2.bundle main &&
 	mkdir dir &&
@@ -29,7 +33,9 @@
 test_expect_success 'local clone without .git suffix' '
 	git clone -l -s a b &&
 	(cd b &&
-	test "$(git config --bool core.bare)" = false &&
+	echo false >expect &&
+	git config --bool core.bare >actual &&
+	test_cmp expect actual &&
 	git fetch)
 '
 
diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh
index 6c8d4c6..a73b4d4 100755
--- a/t/t5700-protocol-v1.sh
+++ b/t/t5700-protocol-v1.sh
@@ -244,15 +244,28 @@
 	grep "push< version 1" log
 '
 
+test_expect_success 'clone propagates object-format from empty repo' '
+	test_when_finished "rm -fr src256 dst256" &&
+
+	echo sha256 >expect &&
+	git init --object-format=sha256 src256 &&
+	git clone --no-local src256 dst256 &&
+	git -C dst256 rev-parse --show-object-format >actual &&
+
+	test_cmp expect actual
+'
+
 # Test protocol v1 with 'http://' transport
 #
 . "$TEST_DIRECTORY"/lib-httpd.sh
 start_httpd
 
-test_expect_success 'create repo to be served by http:// transport' '
+test_expect_success 'create repos to be served by http:// transport' '
 	git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
 	git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" config http.receivepack true &&
-	test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one
+	test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one &&
+	git init --object-format=sha256 "$HTTPD_DOCUMENT_ROOT_PATH/sha256" &&
+	git -C "$HTTPD_DOCUMENT_ROOT_PATH/sha256" config http.receivepack true
 '
 
 test_expect_success 'clone with http:// using protocol v1' '
@@ -269,6 +282,20 @@
 	grep "git< version 1" log
 '
 
+test_expect_success 'clone with http:// using protocol v1 with empty SHA-256 repo' '
+	GIT_TRACE_PACKET=1 GIT_TRACE_CURL=1 git -c protocol.version=1 \
+		clone "$HTTPD_URL/smart/sha256" sha256 2>log &&
+
+	echo sha256 >expect &&
+	git -C sha256 rev-parse --show-object-format >actual &&
+	test_cmp expect actual &&
+
+	# Client requested to use protocol v1
+	grep "Git-Protocol: version=1" log &&
+	# Server responded using protocol v1
+	grep "git< version 1" log
+'
+
 test_expect_success 'fetch with http:// using protocol v1' '
 	test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two &&
 
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index e4db751..6af5c20 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -269,6 +269,17 @@
 	grep "warning: remote HEAD refers to nonexistent ref" stderr
 '
 
+test_expect_success 'clone propagates object-format from empty repo' '
+	test_when_finished "rm -fr src256 dst256" &&
+
+	echo sha256 >expect &&
+	git init --object-format=sha256 src256 &&
+	git clone src256 dst256 &&
+	git -C dst256 rev-parse --show-object-format >actual &&
+
+	test_cmp expect actual
+'
+
 test_expect_success 'bare clone propagates unborn HEAD from non-empty repo' '
 	test_when_finished "rm -rf file_unborn_parent file_unborn_child.git" &&
 
@@ -728,6 +739,33 @@
 	test_i18ngrep "negotiate-only requires protocol v2" err
 '
 
+test_expect_success 'push with custom path does not request v2' '
+	rm -f env.trace &&
+	git -C client push \
+		--receive-pack="env >../env.trace; git-receive-pack" \
+		origin HEAD:refs/heads/custom-push-test &&
+	test_path_is_file env.trace &&
+	! grep ^GIT_PROTOCOL env.trace
+'
+
+test_expect_success 'fetch with custom path does request v2' '
+	rm -f env.trace &&
+	git -C client fetch \
+		--upload-pack="env >../env.trace; git-upload-pack" \
+		origin HEAD &&
+	grep ^GIT_PROTOCOL=version=2 env.trace
+'
+
+test_expect_success 'archive with custom path does not request v2' '
+	rm -f env.trace &&
+	git -C client archive \
+		--exec="env >../env.trace; git-upload-archive" \
+		--remote=origin \
+		HEAD >/dev/null &&
+	test_path_is_file env.trace &&
+	! grep ^GIT_PROTOCOL env.trace
+'
+
 # Test protocol v2 with 'http://' transport
 #
 . "$TEST_DIRECTORY"/lib-httpd.sh
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 41d0ca0..573eb97 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -493,7 +493,7 @@
 	test_tick &&
 	C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) &&
 	A=$(git show --pretty=format:%an,%ae,%ad%n -s $C) &&
-	verbose test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700"
+	test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700"
 '
 
 test_expect_success 'del LF before empty (1)' '
diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh
index aabf590..67d523d 100755
--- a/t/t6018-rev-list-glob.sh
+++ b/t/t6018-rev-list-glob.sh
@@ -187,7 +187,7 @@
 	compare rev-parse "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two"
 '
 
-for section in receive uploadpack
+for section in fetch receive uploadpack
 do
 	test_expect_success "rev-parse --exclude-hidden=$section with --all" '
 		compare "-c transfer.hideRefs=refs/remotes/ rev-parse" "--branches --tags" "--exclude-hidden=$section --all"
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
index 7d40994..dface8b 100755
--- a/t/t6020-bundle-misc.sh
+++ b/t/t6020-bundle-misc.sh
@@ -10,6 +10,7 @@
 
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-bundle.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
 
 for cmd in create verify list-heads unbundle
 do
@@ -606,4 +607,42 @@
 	)
 '
 
+test_expect_success 'bundle progress includes write phase' '
+	GIT_PROGRESS_DELAY=0 \
+		git bundle create --progress out.bundle --all 2>err &&
+	grep 'Writing' err
+'
+
+test_expect_success TTY 'create --quiet disables all bundle progress' '
+	test_terminal env GIT_PROGRESS_DELAY=0 \
+		git bundle create --quiet out.bundle --all 2>err &&
+	test_must_be_empty err
+'
+
+test_expect_success 'read bundle over stdin' '
+	git bundle create some.bundle HEAD &&
+
+	git bundle verify - <some.bundle 2>err &&
+	grep "<stdin> is okay" err &&
+
+	git bundle list-heads some.bundle >expect &&
+	git bundle list-heads - <some.bundle >actual &&
+	test_cmp expect actual &&
+
+	git bundle unbundle some.bundle >expect &&
+	git bundle unbundle - <some.bundle >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'send a bundle to standard output' '
+	git bundle create - --all HEAD >bundle-one &&
+	mkdir -p down &&
+	git -C down bundle create - --all HEAD >bundle-two &&
+	git bundle verify bundle-one &&
+	git bundle verify bundle-two &&
+	git ls-remote bundle-one >expect &&
+	git ls-remote bundle-two >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
index 11c50b7..1a9d37e 100755
--- a/t/t6021-rev-list-exclude-hidden.sh
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -22,7 +22,7 @@
 	test_cmp expected err
 '
 
-for section in receive uploadpack
+for section in fetch receive uploadpack
 do
 	test_expect_success "$section: passed multiple times" '
 		echo "fatal: --exclude-hidden= passed more than once" >expected &&
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 3ba4fdf..fb01bd6 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -122,6 +122,29 @@
 	grep bar ".git/BISECT_NAMES"
 '
 
+test_expect_success 'bisect reset: back in a branch checked out also elsewhere' '
+	echo "shared" > branch.expect &&
+	test_bisect_reset() {
+		git -C $1 bisect start &&
+		git -C $1 bisect good $HASH1 &&
+		git -C $1 bisect bad $HASH3 &&
+		git -C $1 bisect reset &&
+		git -C $1 branch --show-current > branch.output &&
+		cmp branch.expect branch.output
+	} &&
+	test_when_finished "
+		git worktree remove wt1 &&
+		git worktree remove wt2 &&
+		git branch -d shared
+	" &&
+	git worktree add wt1 -b shared &&
+	git worktree add wt2 -f shared &&
+	# we test in both worktrees to ensure that works
+	# as expected with "first" and "next" worktrees
+	test_bisect_reset wt1 &&
+	test_bisect_reset wt2
+'
+
 test_expect_success 'bisect reset: back in the main branch' '
 	git bisect reset &&
 	echo "* main" > branch.expect &&
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index c466fd9..5c00607 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -1374,6 +1374,14 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'for-each-ref --omit-empty works' '
+	git for-each-ref --format="%(refname)" >actual &&
+	test_line_count -gt 1 actual &&
+	git for-each-ref --format="%(if:equals=refs/heads/main)%(refname)%(then)%(refname)%(end)" --omit-empty >actual &&
+	echo refs/heads/main >expect &&
+	test_cmp expect actual
+'
+
 test_expect_success 'for-each-ref --ignore-case works on multiple sort keys' '
 	# name refs numerically to avoid case-insensitive filesystem conflicts
 	nr=0 &&
@@ -1464,4 +1472,54 @@
 sig_crlf=${sig_crlf%dummy}
 test_atom refs/tags/fake-sig-crlf contents:signature "$sig_crlf"
 
+test_expect_success 'git for-each-ref --stdin: empty' '
+	>in &&
+	git for-each-ref --format="%(refname)" --stdin <in >actual &&
+	git for-each-ref --format="%(refname)" >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'git for-each-ref --stdin: fails if extra args' '
+	>in &&
+	test_must_fail git for-each-ref --format="%(refname)" \
+		--stdin refs/heads/extra <in 2>err &&
+	grep "unknown arguments supplied with --stdin" err
+'
+
+test_expect_success 'git for-each-ref --stdin: matches' '
+	cat >in <<-EOF &&
+	refs/tags/multi*
+	refs/heads/amb*
+	EOF
+
+	cat >expect <<-EOF &&
+	refs/heads/ambiguous
+	refs/tags/multi-ref1-100000-user1
+	refs/tags/multi-ref1-100000-user2
+	refs/tags/multi-ref1-200000-user1
+	refs/tags/multi-ref1-200000-user2
+	refs/tags/multi-ref2-100000-user1
+	refs/tags/multi-ref2-100000-user2
+	refs/tags/multi-ref2-200000-user1
+	refs/tags/multi-ref2-200000-user2
+	refs/tags/multiline
+	EOF
+
+	git for-each-ref --format="%(refname)" --stdin <in >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'git for-each-ref with non-existing refs' '
+	cat >in <<-EOF &&
+	refs/heads/this-ref-does-not-exist
+	refs/tags/bogus
+	EOF
+
+	git for-each-ref --format="%(refname)" --stdin <in >actual &&
+	test_must_be_empty actual &&
+
+	xargs git for-each-ref --format="%(refname)" <in >actual &&
+	test_must_be_empty actual
+'
+
 test_done
diff --git a/t/t6301-for-each-ref-errors.sh b/t/t6301-for-each-ref-errors.sh
index bfda1f4..2667dd1 100755
--- a/t/t6301-for-each-ref-errors.sh
+++ b/t/t6301-for-each-ref-errors.sh
@@ -54,4 +54,18 @@
 	test_must_be_empty brief-err
 '
 
+test_expect_success 'ahead-behind requires an argument' '
+	test_must_fail git for-each-ref \
+		--format="%(ahead-behind)" 2>err &&
+	echo "fatal: expected format: %(ahead-behind:<committish>)" >expect &&
+	test_cmp expect err
+'
+
+test_expect_success 'missing ahead-behind base' '
+	test_must_fail git for-each-ref \
+		--format="%(ahead-behind:refs/heads/missing)" 2>err &&
+	echo "fatal: failed to find '\''refs/heads/missing'\''" >expect &&
+	test_cmp expect err
+'
+
 test_done
diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh
index d9acb63..69509d0 100755
--- a/t/t6500-gc.sh
+++ b/t/t6500-gc.sh
@@ -210,90 +210,95 @@
 	git reset HEAD^^
 }
 
-assert_cruft_packs () {
-	find .git/objects/pack -name "*.mtimes" >mtimes &&
-	sed -e 's/\.mtimes$/\.pack/g' mtimes >packs &&
-
-	test_file_not_empty packs &&
-	while read pack
-	do
-		test_path_is_file "$pack" || return 1
-	done <packs
-}
-
 assert_no_cruft_packs () {
 	find .git/objects/pack -name "*.mtimes" >mtimes &&
 	test_must_be_empty mtimes
 }
 
-test_expect_success 'gc --cruft generates a cruft pack' '
-	test_when_finished "rm -fr crufts" &&
-	git init crufts &&
-	(
-		cd crufts &&
+for argv in \
+	"gc" \
+	"-c gc.cruftPacks=true gc" \
+	"-c gc.cruftPacks=false gc --cruft"
+do
+	test_expect_success "git $argv generates a cruft pack" '
+		test_when_finished "rm -fr repo" &&
+		git init repo &&
+		(
+			cd repo &&
 
+			prepare_cruft_history &&
+			git $argv &&
+
+			find .git/objects/pack -name "*.mtimes" >mtimes &&
+			sed -e 's/\.mtimes$/\.pack/g' mtimes >packs &&
+
+			test_file_not_empty packs &&
+			while read pack
+			do
+				test_path_is_file "$pack" || return 1
+			done <packs
+		)
+	'
+done
+
+for argv in \
+	"gc --no-cruft" \
+	"-c gc.cruftPacks=false gc" \
+	"-c gc.cruftPacks=true gc --no-cruft"
+do
+	test_expect_success "git $argv does not generate a cruft pack" '
+		test_when_finished "rm -fr repo" &&
+		git init repo &&
+		(
+			cd repo &&
+
+			prepare_cruft_history &&
+			git $argv &&
+
+			assert_no_cruft_packs
+		)
+	'
+done
+
+test_expect_success '--keep-largest-pack ignores cruft packs' '
+	test_when_finished "rm -fr repo" &&
+	git init repo &&
+	(
+		cd repo &&
+
+		# Generate a pack for reachable objects (of which there
+		# are 3), and one for unreachable objects (of which
+		# there are 6).
 		prepare_cruft_history &&
 		git gc --cruft &&
-		assert_cruft_packs
-	)
-'
 
-test_expect_success 'gc.cruftPacks=true generates a cruft pack' '
-	test_when_finished "rm -fr crufts" &&
-	git init crufts &&
-	(
-		cd crufts &&
+		mtimes="$(find .git/objects/pack -type f -name "pack-*.mtimes")" &&
+		sz="$(test_file_size "${mtimes%.mtimes}.pack")" &&
 
-		prepare_cruft_history &&
-		git -c gc.cruftPacks=true gc &&
-		assert_cruft_packs
-	)
-'
+		# Ensure that the cruft pack gets removed (due to
+		# `--prune=now`) despite it being the largest pack.
+		git -c gc.bigPackThreshold=$sz gc --cruft --prune=now &&
 
-test_expect_success 'feature.experimental=true generates a cruft pack' '
-	git init crufts &&
-	test_when_finished "rm -fr crufts" &&
-	(
-		cd crufts &&
-
-		prepare_cruft_history &&
-		git -c feature.experimental=true gc &&
-		assert_cruft_packs
-	)
-'
-
-test_expect_success 'feature.experimental=false allows explicit cruft packs' '
-	git init crufts &&
-	test_when_finished "rm -fr crufts" &&
-	(
-		cd crufts &&
-
-		prepare_cruft_history &&
-		git -c gc.cruftPacks=true -c feature.experimental=false gc &&
-		assert_cruft_packs
-	)
-'
-
-test_expect_success 'feature.experimental=true can be overridden' '
-	git init crufts &&
-	test_when_finished "rm -fr crufts" &&
-	(
-		cd crufts &&
-
-		prepare_cruft_history &&
-		git -c feature.expiremental=true -c gc.cruftPacks=false gc &&
 		assert_no_cruft_packs
 	)
 '
 
-test_expect_success 'feature.experimental=false avoids cruft packs by default' '
-	git init crufts &&
-	test_when_finished "rm -fr crufts" &&
+test_expect_success 'gc.bigPackThreshold ignores cruft packs' '
+	test_when_finished "rm -fr repo" &&
+	git init repo &&
 	(
-		cd crufts &&
+		cd repo &&
 
+		# Generate a pack for reachable objects (of which there
+		# are 3), and one for unreachable objects (of which
+		# there are 6).
 		prepare_cruft_history &&
-		git -c feature.experimental=false gc &&
+		git gc --cruft &&
+
+		# Ensure that the cruft pack gets removed (due to
+		# `--prune=now`) despite it being the largest pack.
+		git gc --cruft --prune=now --keep-largest-pack &&
+
 		assert_no_cruft_packs
 	)
 '
diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh
index 3968b47..4521508 100755
--- a/t/t6501-freshen-objects.sh
+++ b/t/t6501-freshen-objects.sh
@@ -101,7 +101,7 @@
 	'
 
 	test_expect_success "simultaneous gc ($title)" '
-		git gc --prune=12.hours.ago
+		git gc --no-cruft --prune=12.hours.ago
 	'
 
 	test_expect_success "finish writing out commit ($title)" '
@@ -131,7 +131,7 @@
 	'
 
 	test_expect_success "simultaneous gc ($title)" '
-		git gc --prune=12.hours.ago
+		git gc --no-cruft --prune=12.hours.ago
 	'
 
 	# tree should have been refreshed by write-tree
@@ -151,8 +151,8 @@
 	some message
 	EOF
 	commit=$(git hash-object -t commit -w broken-commit) &&
-	git gc -q 2>stderr &&
-	verbose git cat-file -e $commit &&
+	git gc --no-cruft -q 2>stderr &&
+	git cat-file -e $commit &&
 	test_must_be_empty stderr
 '
 
@@ -161,7 +161,7 @@
 	100644 blob $(test_oid 003)	foo
 	EOF
 	tree=$(git mktree --missing <broken-tree) &&
-	git gc -q 2>stderr &&
+	git gc --no-cruft -q 2>stderr &&
 	git cat-file -e $tree &&
 	test_must_be_empty stderr
 '
@@ -176,7 +176,7 @@
 	this is a broken tag
 	EOF
 	tag=$(git hash-object -t tag -w broken-tag) &&
-	git gc -q 2>stderr &&
+	git gc --no-cruft -q 2>stderr &&
 	git cat-file -e $tag &&
 	test_must_be_empty stderr
 '
diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh
index 338a9c4..b330945 100755
--- a/t/t6600-test-reach.sh
+++ b/t/t6600-test-reach.sh
@@ -443,4 +443,173 @@
 	test_all_modes get_reachable_subset
 '
 
+test_expect_success 'for-each-ref ahead-behind:linear' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-1-3
+	refs/heads/commit-1-5
+	refs/heads/commit-1-8
+	EOF
+	cat >expect <<-\EOF &&
+	refs/heads/commit-1-1 0 8
+	refs/heads/commit-1-3 0 6
+	refs/heads/commit-1-5 0 4
+	refs/heads/commit-1-8 0 1
+	EOF
+	run_all_modes git for-each-ref \
+		--format="%(refname) %(ahead-behind:commit-1-9)" --stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:all' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-2-4
+	refs/heads/commit-4-2
+	refs/heads/commit-4-4
+	EOF
+	cat >expect <<-\EOF &&
+	refs/heads/commit-1-1 0 24
+	refs/heads/commit-2-4 0 17
+	refs/heads/commit-4-2 0 17
+	refs/heads/commit-4-4 0 9
+	EOF
+	run_all_modes git for-each-ref \
+		--format="%(refname) %(ahead-behind:commit-5-5)" --stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:some' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-5-3
+	refs/heads/commit-4-8
+	refs/heads/commit-9-9
+	EOF
+	cat >expect <<-\EOF &&
+	refs/heads/commit-1-1 0 53
+	refs/heads/commit-4-8 8 30
+	refs/heads/commit-5-3 0 39
+	refs/heads/commit-9-9 27 0
+	EOF
+	run_all_modes git for-each-ref \
+		--format="%(refname) %(ahead-behind:commit-9-6)" --stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:some, multibase' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-5-3
+	refs/heads/commit-7-8
+	refs/heads/commit-4-8
+	refs/heads/commit-9-9
+	EOF
+	cat >expect <<-\EOF &&
+	refs/heads/commit-1-1 0 53 0 53
+	refs/heads/commit-4-8 8 30 0 22
+	refs/heads/commit-5-3 0 39 0 39
+	refs/heads/commit-7-8 14 12 8 6
+	refs/heads/commit-9-9 27 0 27 0
+	EOF
+	run_all_modes git for-each-ref \
+		--format="%(refname) %(ahead-behind:commit-9-6) %(ahead-behind:commit-6-9)" \
+		--stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:none' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-7-5
+	refs/heads/commit-4-8
+	refs/heads/commit-9-9
+	EOF
+	cat >expect <<-\EOF &&
+	refs/heads/commit-4-8 16 16
+	refs/heads/commit-7-5 7 4
+	refs/heads/commit-9-9 49 0
+	EOF
+	run_all_modes git for-each-ref \
+		--format="%(refname) %(ahead-behind:commit-8-4)" --stdin
+'
+
+test_expect_success 'for-each-ref merged:linear' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-1-3
+	refs/heads/commit-1-5
+	refs/heads/commit-1-8
+	refs/heads/commit-2-1
+	refs/heads/commit-5-1
+	refs/heads/commit-9-1
+	EOF
+	cat >expect <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-1-3
+	refs/heads/commit-1-5
+	refs/heads/commit-1-8
+	EOF
+	run_all_modes git for-each-ref --merged=commit-1-9 \
+		--format="%(refname)" --stdin
+'
+
+test_expect_success 'for-each-ref merged:all' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-2-4
+	refs/heads/commit-4-2
+	refs/heads/commit-4-4
+	EOF
+	cat >expect <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-2-4
+	refs/heads/commit-4-2
+	refs/heads/commit-4-4
+	EOF
+	run_all_modes git for-each-ref --merged=commit-5-5 \
+		--format="%(refname)" --stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:some' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-5-3
+	refs/heads/commit-4-8
+	refs/heads/commit-9-9
+	EOF
+	cat >expect <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-5-3
+	EOF
+	run_all_modes git for-each-ref --merged=commit-9-6 \
+		--format="%(refname)" --stdin
+'
+
+test_expect_success 'for-each-ref merged:some, multibase' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-5-3
+	refs/heads/commit-7-8
+	refs/heads/commit-4-8
+	refs/heads/commit-9-9
+	EOF
+	cat >expect <<-\EOF &&
+	refs/heads/commit-1-1
+	refs/heads/commit-4-8
+	refs/heads/commit-5-3
+	EOF
+	run_all_modes git for-each-ref \
+		--merged=commit-5-8 \
+		--merged=commit-8-5 \
+		--format="%(refname)" \
+		--stdin
+'
+
+test_expect_success 'for-each-ref merged:none' '
+	cat >input <<-\EOF &&
+	refs/heads/commit-7-5
+	refs/heads/commit-4-8
+	refs/heads/commit-9-9
+	EOF
+	>expect &&
+	run_all_modes git for-each-ref --merged=commit-8-4 \
+		--format="%(refname)" --stdin
+'
+
 test_done
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index d72cef8..898a920 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -4,6 +4,10 @@
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-diff-data.sh
 
+index_at_path () {
+	git ls-files --format='%(objectmode) %(objectname) %(stage)' "$@"
+}
+
 test_expect_success 'mv -f refreshes updated index entry' '
 	echo test >bar &&
 	git add bar &&
@@ -187,7 +191,8 @@
 	git mv papers/unsorted/Thesis.pdf papers/all-papers/moo-blah.pdf &&
 
 	T=$(git write-tree) &&
-	git ls-tree -r $T | verbose grep partA/outline.txt
+	git ls-tree -r $T >out &&
+	grep partA/outline.txt out
 '
 
 rm -fr papers partA path?
@@ -260,12 +265,12 @@
 	git init &&
 	echo 1 >dirty &&
 	git add dirty &&
-	entry="$(git ls-files --stage dirty | cut -f 1)" &&
+	entry="$(index_at_path dirty)" &&
 	git mv dirty dirty2 &&
-	test "$entry" = "$(git ls-files --stage dirty2 | cut -f 1)" &&
+	test "$entry" = "$(index_at_path dirty2)" &&
 	echo 2 >dirty2 &&
 	git mv dirty2 dirty &&
-	test "$entry" = "$(git ls-files --stage dirty | cut -f 1)"
+	test "$entry" = "$(index_at_path dirty)"
 '
 
 rm -f dirty dirty2
@@ -342,7 +347,7 @@
 '
 
 test_expect_success 'git mv moves a submodule with a .git directory and no .gitmodules' '
-	entry="$(git ls-files --stage sub | cut -f 1)" &&
+	entry="$(index_at_path sub)" &&
 	git rm .gitmodules &&
 	(
 		cd sub &&
@@ -353,7 +358,7 @@
 	mkdir mod &&
 	git mv sub mod/sub &&
 	test_path_is_missing sub &&
-	test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+	test "$entry" = "$(index_at_path mod/sub)" &&
 	git -C mod/sub status &&
 	git update-index --refresh &&
 	git diff-files --quiet
@@ -363,7 +368,7 @@
 	rm -rf mod &&
 	git reset --hard &&
 	git submodule update &&
-	entry="$(git ls-files --stage sub | cut -f 1)" &&
+	entry="$(index_at_path sub)" &&
 	(
 		cd sub &&
 		rm -f .git &&
@@ -373,7 +378,7 @@
 	mkdir mod &&
 	git mv sub mod/sub &&
 	test_path_is_missing sub &&
-	test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+	test "$entry" = "$(index_at_path mod/sub)" &&
 	git -C mod/sub status &&
 	echo mod/sub >expected &&
 	git config -f .gitmodules submodule.sub.path >actual &&
@@ -386,11 +391,11 @@
 	rm -rf mod &&
 	git reset --hard &&
 	git submodule update &&
-	entry="$(git ls-files --stage sub | cut -f 1)" &&
+	entry="$(index_at_path sub)" &&
 	mkdir mod &&
 	git -C mod mv ../sub/ . &&
 	test_path_is_missing sub &&
-	test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+	test "$entry" = "$(index_at_path mod/sub)" &&
 	git -C mod/sub status &&
 	echo mod/sub >expected &&
 	git config -f .gitmodules submodule.sub.path >actual &&
@@ -404,12 +409,12 @@
 	git reset --hard &&
 	git submodule update &&
 	git rm .gitmodules &&
-	entry="$(git ls-files --stage sub | cut -f 1)" &&
+	entry="$(index_at_path sub)" &&
 	mkdir mod &&
 	git mv sub mod/sub 2>actual.err &&
 	test_must_be_empty actual.err &&
 	test_path_is_missing sub &&
-	test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+	test "$entry" = "$(index_at_path mod/sub)" &&
 	git -C mod/sub status &&
 	git update-index --refresh &&
 	git diff-files --quiet
@@ -420,7 +425,7 @@
 	git reset --hard &&
 	git submodule update &&
 	git config -f .gitmodules foo.bar true &&
-	entry="$(git ls-files --stage sub | cut -f 1)" &&
+	entry="$(index_at_path sub)" &&
 	mkdir mod &&
 	test_must_fail git mv sub mod/sub 2>actual.err &&
 	test_file_not_empty actual.err &&
@@ -430,7 +435,7 @@
 	git mv sub mod/sub 2>actual.err &&
 	test_must_be_empty actual.err &&
 	test_path_is_missing sub &&
-	test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+	test "$entry" = "$(index_at_path mod/sub)" &&
 	git -C mod/sub status &&
 	git update-index --refresh &&
 	git diff-files --quiet
@@ -442,13 +447,13 @@
 	git submodule update &&
 	git config -f .gitmodules --remove-section submodule.sub &&
 	git add .gitmodules &&
-	entry="$(git ls-files --stage sub | cut -f 1)" &&
+	entry="$(index_at_path sub)" &&
 	echo "warning: Could not find section in .gitmodules where path=sub" >expect.err &&
 	mkdir mod &&
 	git mv sub mod/sub 2>actual.err &&
 	test_cmp expect.err actual.err &&
 	test_path_is_missing sub &&
-	test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+	test "$entry" = "$(index_at_path mod/sub)" &&
 	git -C mod/sub status &&
 	git update-index --refresh &&
 	git diff-files --quiet
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 9aa1660..e689db4 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -792,6 +792,34 @@
 	test_cmp expect actual
 '
 
+# Run this before doing any signing, so the test has the same results
+# regardless of the GPG prereq.
+test_expect_success 'git tag --format with ahead-behind' '
+	test_when_finished git reset --hard tag-one-line &&
+	git commit --allow-empty -m "left" &&
+	git tag -a -m left tag-left &&
+	git reset --hard HEAD~1 &&
+	git commit --allow-empty -m "right" &&
+	git tag -a -m left tag-right &&
+
+	# Use " !" at the end to demonstrate whitespace
+	# around empty ahead-behind token for tag-blob.
+	cat >expect <<-EOF &&
+	refs/tags/tag-blob  !
+	refs/tags/tag-left 1 1 !
+	refs/tags/tag-lines 0 1 !
+	refs/tags/tag-one-line 0 1 !
+	refs/tags/tag-right 0 0 !
+	refs/tags/tag-zero-lines 0 1 !
+	EOF
+	git tag -l --format="%(refname) %(ahead-behind:HEAD) !" >actual 2>err &&
+	grep "refs/tags/tag" actual >actual.focus &&
+	test_cmp expect actual.focus &&
+
+	# Error reported for tags that point to non-commits.
+	grep "error: object [0-9a-f]* is a blob, not a commit" err
+'
+
 # trying to verify annotated non-signed tags:
 
 test_expect_success GPG \
@@ -1843,6 +1871,23 @@
 	test_must_fail git tag -l "foo*"
 '
 
+test_expect_success 'version sort handles empty value for versionsort.{prereleaseSuffix,suffix}' '
+	cp .git/config .git/config.orig &&
+	test_when_finished mv .git/config.orig .git/config &&
+
+	cat >>.git/config <<-\EOF &&
+	[versionsort]
+		prereleaseSuffix
+		suffix
+	EOF
+	cat >expect <<-\EOF &&
+	error: missing value for '\''versionsort.suffix'\''
+	error: missing value for '\''versionsort.prereleasesuffix'\''
+	EOF
+	git tag -l --sort=version:refname 2>actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'version sort with prerelease reordering' '
 	test_config versionsort.prereleaseSuffix -rc &&
 	git tag foo1.6-rc1 &&
@@ -2001,6 +2046,22 @@
 	test_cmp expect actual
 '
 
+test_expect_success '--format --omit-empty works' '
+	cat >expect <<-\EOF &&
+	refname : refs/tags/v1.0
+
+	refname : refs/tags/v1.1.3
+	EOF
+	git tag -l --format="%(if:notequals=refs/tags/v1.0.1)%(refname)%(then)refname : %(refname)%(end)" "v1*" >actual &&
+	test_cmp expect actual &&
+	cat >expect <<-\EOF &&
+	refname : refs/tags/v1.0
+	refname : refs/tags/v1.1.3
+	EOF
+	git tag -l --omit-empty --format="%(if:notequals=refs/tags/v1.0.1)%(refname)%(then)refname : %(refname)%(end)" "v1*" >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'git tag -l with --format="%(rest)" must fail' '
 	test_must_fail git tag -l --format="%(rest)" "v1*"
 '
@@ -2127,4 +2188,23 @@
 	test_cmp expected actual
 '
 
+test_expect_success 'If tag is created then tag message file is unlinked' '
+	test_when_finished "git tag -d foo" &&
+	write_script fakeeditor <<-\EOF &&
+	echo Message >.git/TAG_EDITMSG
+	EOF
+	GIT_EDITOR=./fakeeditor git tag -a foo &&
+	test_path_is_missing .git/TAG_EDITMSG
+'
+
+test_expect_success 'If tag cannot be created then tag message file is not unlinked' '
+	test_when_finished "git tag -d foo/bar && rm .git/TAG_EDITMSG" &&
+	write_script fakeeditor <<-\EOF &&
+	echo Message >.git/TAG_EDITMSG
+	EOF
+	git tag foo/bar &&
+	test_must_fail env GIT_EDITOR=./fakeeditor git tag -a foo &&
+	test_path_exists .git/TAG_EDITMSG
+'
+
 test_done
diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh
index 36eb86a..20913b3 100755
--- a/t/t7031-verify-tag-signed-ssh.sh
+++ b/t/t7031-verify-tag-signed-ssh.sh
@@ -200,4 +200,14 @@
 	test_must_be_empty actual-forged
 '
 
+test_expect_success GPGSSH 'rev-list --format=%G' '
+	test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+	git rev-list -1 --format="%G? %H" sixth-signed >actual &&
+	cat >expect <<-EOF &&
+	commit $(git rev-parse sixth-signed^0)
+	G $(git rev-parse sixth-signed^0)
+	EOF
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index c975eb5..0ef7b78 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -120,7 +120,7 @@
 		grep part3 |
 		sed -n -e "s|^Would remove ||p"
 	) &&
-	verbose test "$would_clean" = ../src/part3.c
+	test "$would_clean" = ../src/part3.c
 '
 
 test_expect_success 'git clean with absolute path' '
@@ -133,7 +133,7 @@
 		grep part3 |
 		sed -n -e "s|^Would remove ||p"
 	) &&
-	verbose test "$would_clean" = ../src/part3.c
+	test "$would_clean" = ../src/part3.c
 '
 
 test_expect_success 'git clean with out of work tree relative path' '
diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh
index b19792b..2b3c363 100755
--- a/t/t7402-submodule-rebase.sh
+++ b/t/t7402-submodule-rebase.sh
@@ -56,12 +56,15 @@
 
 test_expect_success 'interactive rebase with a dirty submodule' '
 
-	test submodule = $(git diff --name-only) &&
+	echo submodule >expect &&
+	git diff --name-only >actual &&
+	test_cmp expect actual &&
 	HEAD=$(git rev-parse HEAD) &&
 	GIT_EDITOR="\"$(pwd)/fake-editor.sh\"" EDITOR_TEXT="pick $HEAD" \
 		git rebase -i HEAD^ &&
-	test submodule = $(git diff --name-only)
-
+	echo submodule >expect &&
+	git diff --name-only >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'rebase with dirty file and submodule fails' '
@@ -83,11 +86,19 @@
 	CURRENT=$(cd submodule && git rev-parse HEAD) &&
 	git stash &&
 	test new != $(cat file) &&
-	test submodule = $(git diff --name-only) &&
-	test $CURRENT = $(cd submodule && git rev-parse HEAD) &&
+	echo submodule >expect &&
+	git diff --name-only >actual &&
+	test_cmp expect actual &&
+
+	echo "$CURRENT" >expect &&
+	git -C submodule rev-parse HEAD >actual &&
+	test_cmp expect actual &&
+
 	git stash apply &&
 	test new = $(cat file) &&
-	test $CURRENT = $(cd submodule && git rev-parse HEAD)
+	echo "$CURRENT" >expect &&
+	git -C submodule rev-parse HEAD >actual &&
+	test_cmp expect actual
 
 '
 
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index 7cdc263..887d181 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -51,6 +51,22 @@
 	test-tool -C super submodule is-active sub1
 '
 
+test_expect_success 'is-active handles submodule.active config missing a value' '
+	cp super/.git/config super/.git/config.orig &&
+	test_when_finished mv super/.git/config.orig super/.git/config &&
+
+	cat >>super/.git/config <<-\EOF &&
+	[submodule]
+		active
+	EOF
+
+	cat >expect <<-\EOF &&
+	error: missing value for '\''submodule.active'\''
+	EOF
+	test-tool -C super submodule is-active sub1 2>actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'is-active works with basic submodule.active config' '
 	test_when_finished "git -C super config submodule.sub1.URL ../sub" &&
 	test_when_finished "git -C super config --unset-all submodule.active" &&
diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh
index 07ca46f..d125522 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -102,7 +102,9 @@
 '
 
 commit_msg_is () {
-	test "$(git log --pretty=format:%s%b -1)" = "$1"
+	printf "%s" "$1" >expect &&
+	git log --pretty=format:%s%b -1 >actual &&
+	test_cmp expect actual
 }
 
 test_expect_success 'with failing hook' '
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 48f86cb..ccbc416 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -221,84 +221,91 @@
 test_expect_success GPG 'show good signature with custom format' '
 	cat >expect <<-\EOF &&
 	G
-	13B6F51ECDDE430D
-	C O Mitter <committer@example.com>
-	73D758744BE721698EC54E8713B6F51ECDDE430D
-	73D758744BE721698EC54E8713B6F51ECDDE430D
-	EOF
-	git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success GPG 'show bad signature with custom format' '
-	cat >expect <<-\EOF &&
-	B
-	13B6F51ECDDE430D
-	C O Mitter <committer@example.com>
-
-
-	EOF
-	git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success GPG 'show untrusted signature with custom format' '
-	cat >expect <<-\EOF &&
-	U
-	65A0EEA02E30CAD7
-	Eris Discordia <discord@example.net>
-	F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
-	D4BE22311AD3131E5EDA29A461092E85B7227189
-	EOF
-	git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success GPG 'show untrusted signature with undefined trust level' '
-	cat >expect <<-\EOF &&
-	undefined
-	65A0EEA02E30CAD7
-	Eris Discordia <discord@example.net>
-	F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
-	D4BE22311AD3131E5EDA29A461092E85B7227189
-	EOF
-	git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success GPG 'show untrusted signature with ultimate trust level' '
-	cat >expect <<-\EOF &&
 	ultimate
 	13B6F51ECDDE430D
 	C O Mitter <committer@example.com>
 	73D758744BE721698EC54E8713B6F51ECDDE430D
 	73D758744BE721698EC54E8713B6F51ECDDE430D
 	EOF
-	git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+	git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success GPG 'show bad signature with custom format' '
+	cat >expect <<-\EOF &&
+	B
+	undefined
+	13B6F51ECDDE430D
+	C O Mitter <committer@example.com>
+
+
+	EOF
+	git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success GPG 'show untrusted signature with custom format' '
+	cat >expect <<-\EOF &&
+	U
+	undefined
+	65A0EEA02E30CAD7
+	Eris Discordia <discord@example.net>
+	F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
+	D4BE22311AD3131E5EDA29A461092E85B7227189
+	EOF
+	git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success GPG 'show untrusted signature with undefined trust level' '
+	cat >expect <<-\EOF &&
+	U
+	undefined
+	65A0EEA02E30CAD7
+	Eris Discordia <discord@example.net>
+	F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
+	D4BE22311AD3131E5EDA29A461092E85B7227189
+	EOF
+	git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success GPG 'show untrusted signature with ultimate trust level' '
+	cat >expect <<-\EOF &&
+	G
+	ultimate
+	13B6F51ECDDE430D
+	C O Mitter <committer@example.com>
+	73D758744BE721698EC54E8713B6F51ECDDE430D
+	73D758744BE721698EC54E8713B6F51ECDDE430D
+	EOF
+	git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success GPG 'show unknown signature with custom format' '
 	cat >expect <<-\EOF &&
 	E
+	undefined
 	65A0EEA02E30CAD7
 
 
 
 	EOF
-	GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+	GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success GPG 'show lack of signature with custom format' '
 	cat >expect <<-\EOF &&
 	N
+	undefined
 
 
 
 
 	EOF
-	git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
+	git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
 	test_cmp expect actual
 '
 
diff --git a/t/t7516-commit-races.sh b/t/t7516-commit-races.sh
index f2ce14e..2d38a16 100755
--- a/t/t7516-commit-races.sh
+++ b/t/t7516-commit-races.sh
@@ -10,7 +10,8 @@
 	test_must_fail env EDITOR=./hare-editor git commit --allow-empty -m tortoise -e &&
 	git show -s --pretty=format:%s >subject &&
 	grep hare subject &&
-	test -z "$(git show -s --pretty=format:%P)"
+	git show -s --pretty=format:%P >out &&
+	test_must_be_empty out
 '
 
 test_expect_success 'race to create non-orphan commit' '
diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh
index 4c0327b..0c241d6 100755
--- a/t/t7527-builtin-fsmonitor.sh
+++ b/t/t7527-builtin-fsmonitor.sh
@@ -995,4 +995,41 @@
 	grep -E "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace
 '
 
+test_expect_success 'split-index and FSMonitor work well together' '
+	git init split-index &&
+	test_when_finished "git -C \"$PWD/split-index\" \
+		fsmonitor--daemon stop" &&
+	(
+		cd split-index &&
+		git config core.splitIndex true &&
+		# force split-index in most cases
+		git config splitIndex.maxPercentChange 99 &&
+		git config core.fsmonitor true &&
+
+		# Create the following commit topology:
+		#
+		# *   merge three
+		# |\
+		# | * three
+		# * | merge two
+		# |\|
+		# | * two
+		# * | one
+		# |/
+		# * 5a5efd7 initial
+
+		test_commit initial &&
+		test_commit two &&
+		test_commit three &&
+		git reset --hard initial &&
+		test_commit one &&
+		test_tick &&
+		git merge two &&
+		test_tick &&
+		git merge three &&
+
+		git rebase --force-rebase -r one
+	)
+'
+
 test_done
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 7b95702..22b3a85 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -860,4 +860,42 @@
 	git commit -m "test resolved with mergetool"
 '
 
+test_expect_success 'mergetool with guiDefault' '
+	test_config merge.guitool myguitool &&
+	test_config mergetool.myguitool.cmd "(printf \"gui \" && cat \"\$REMOTE\") >\"\$MERGED\"" &&
+	test_config mergetool.myguitool.trustExitCode true &&
+	test_when_finished "git reset --hard" &&
+	git checkout -b test$test_count branch1 &&
+	git submodule update -N &&
+	test_must_fail git merge main &&
+
+	test_config mergetool.guiDefault auto &&
+	DISPLAY=SOMETHING && export DISPLAY &&
+	yes "" | git mergetool both &&
+	yes "" | git mergetool file1 file1 &&
+
+	DISPLAY= && export DISPLAY &&
+	yes "" | git mergetool file2 "spaced name" &&
+
+	test_config mergetool.guiDefault true &&
+	yes "" | git mergetool subdir/file3 &&
+
+	yes "d" | git mergetool file11 &&
+	yes "d" | git mergetool file12 &&
+	yes "l" | git mergetool submod &&
+
+	echo "gui main updated" >expect &&
+	test_cmp expect file1 &&
+
+	echo "main new" >expect &&
+	test_cmp expect file2 &&
+
+	echo "gui main new sub" >expect &&
+	test_cmp expect subdir/file3 &&
+
+	echo "branch1 submodule" >expect &&
+	test_cmp expect submod/bar &&
+	git commit -m "branch1 resolved with mergetool"
+'
+
 test_done
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 4aabe98..faa739e 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -106,6 +106,23 @@
 	test_cmp expect actual
 '
 
+test_expect_success '--local disables writing bitmaps when connected to alternate ODB' '
+	test_when_finished "rm -rf shared member" &&
+
+	git init shared &&
+	git clone --shared shared member &&
+	(
+		cd member &&
+		test_commit "object" &&
+		GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adl --write-bitmap-index 2>err &&
+		cat >expect <<-EOF &&
+		warning: disabling bitmap writing, as some objects are not being packed
+		EOF
+		test_cmp expect err &&
+		test_path_is_missing .git/objects/pack-*.bitmap
+	)
+'
+
 test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
 	mkdir alt_objects/pack &&
 	mv .git/objects/pack/* alt_objects/pack &&
diff --git a/t/t7703-repack-geometric.sh b/t/t7703-repack-geometric.sh
index 8821fbd..00f28fb 100755
--- a/t/t7703-repack-geometric.sh
+++ b/t/t7703-repack-geometric.sh
@@ -10,6 +10,12 @@
 packdir=$objdir/pack
 midx=$objdir/pack/multi-pack-index
 
+packed_objects () {
+	git show-index <"$1" >tmp-object-list &&
+	cut -d' ' -f2 tmp-object-list | sort &&
+	rm tmp-object-list
+ }
+
 test_expect_success '--geometric with no packs' '
 	git init geometric &&
 	test_when_finished "rm -fr geometric" &&
@@ -281,4 +287,162 @@
 	)
 '
 
+test_expect_success '--geometric --write-midx with packfiles in main and alternate ODB' '
+	test_when_finished "rm -fr shared member" &&
+
+	# Create a shared repository that will serve as the alternate object
+	# database for the member linked to it. It has got some objects on its
+	# own that are packed into a single packfile.
+	git init shared &&
+	test_commit -C shared common-object &&
+	git -C shared repack -ad &&
+
+	# We create member so that its alternates file points to the shared
+	# repository. We then create a commit in it so that git-repack(1) has
+	# something to repack.
+	# of the shared object database.
+	git clone --shared shared member &&
+	test_commit -C member unique-object &&
+	git -C member repack --geometric=2 --write-midx 2>err &&
+	test_must_be_empty err &&
+
+	# We should see that a new packfile was generated.
+	find shared/.git/objects/pack -type f -name "*.pack" >packs &&
+	test_line_count = 1 packs &&
+
+	# We should also see a multi-pack-index. This multi-pack-index should
+	# never refer to any packfiles in the alternate object database.
+	test_path_is_file member/.git/objects/pack/multi-pack-index &&
+	test-tool read-midx member/.git/objects >packs.midx &&
+	grep "^pack-.*\.idx$" packs.midx | sort >actual &&
+	basename member/.git/objects/pack/pack-*.idx >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success '--geometric --with-midx with no local objects' '
+	test_when_finished "rm -fr shared member" &&
+
+	# Create a repository with a single packfile that acts as alternate
+	# object database.
+	git init shared &&
+	test_commit -C shared "shared-objects" &&
+	git -C shared repack -ad &&
+
+	# Create a second repository linked to the first one and perform a
+	# geometric repack on it.
+	git clone --shared shared member &&
+	git -C member repack --geometric 2 --write-midx 2>err &&
+	test_must_be_empty err &&
+
+	# Assert that we wrote neither a new packfile nor a multi-pack-index.
+	# We should not have a packfile because the single packfile in the
+	# alternate object database does not invalidate the geometric sequence.
+	# And we should not have a multi-pack-index because these only index
+	# local packfiles, and there are none.
+	test_dir_is_empty member/$packdir
+'
+
+test_expect_success '--geometric with same pack in main and alternate ODB' '
+	test_when_finished "rm -fr shared member" &&
+
+	# Create a repository with a single packfile that acts as alternate
+	# object database.
+	git init shared &&
+	test_commit -C shared "shared-objects" &&
+	git -C shared repack -ad &&
+
+	# We create the member repository as an exact copy so that it has the
+	# same packfile.
+	cp -r shared member &&
+	test-tool path-utils real_path shared/.git/objects >member/.git/objects/info/alternates &&
+	find shared/.git/objects -type f >expected-files &&
+
+	# Verify that we can repack objects as expected without observing any
+	# error. Having the same packfile in both ODBs used to cause an error
+	# in git-pack-objects(1).
+	git -C member repack --geometric 2 2>err &&
+	test_must_be_empty err &&
+	# Nothing should have changed.
+	find shared/.git/objects -type f >actual-files &&
+	test_cmp expected-files actual-files
+'
+
+test_expect_success '--geometric -l with non-intact geometric sequence across ODBs' '
+	test_when_finished "rm -fr shared member" &&
+
+	git init shared &&
+	test_commit_bulk -C shared --start=1 1 &&
+
+	git clone --shared shared member &&
+	test_commit_bulk -C member --start=2 1 &&
+
+	# Verify that our assumptions actually hold: both generated packfiles
+	# should have three objects and should be non-equal.
+	packed_objects shared/.git/objects/pack/pack-*.idx >shared-objects &&
+	packed_objects member/.git/objects/pack/pack-*.idx >member-objects &&
+	test_line_count = 3 shared-objects &&
+	test_line_count = 3 member-objects &&
+	! test_cmp shared-objects member-objects &&
+
+	# Perform the geometric repack. With `-l`, we should only see the local
+	# packfile and thus arrive at the conclusion that the geometric
+	# sequence is intact. We thus expect no changes.
+	#
+	# Note that we are tweaking mtimes of the packfiles so that we can
+	# verify they did not change. This is done in order to detect the case
+	# where we do repack objects, but the resulting packfile is the same.
+	test-tool chmtime --verbose =0 member/.git/objects/pack/* >expected-member-packs &&
+	git -C member repack --geometric=2 -l -d &&
+	test-tool chmtime --verbose member/.git/objects/pack/* >actual-member-packs &&
+	test_cmp expected-member-packs actual-member-packs &&
+
+	{
+		packed_objects shared/.git/objects/pack/pack-*.idx &&
+		packed_objects member/.git/objects/pack/pack-*.idx
+	} | sort >expected-objects &&
+
+	# On the other hand, when doing a non-local geometric repack we should
+	# see both packfiles and thus repack them. We expect that the shared
+	# object database was not changed.
+	test-tool chmtime --verbose =0 shared/.git/objects/pack/* >expected-shared-packs &&
+	git -C member repack --geometric=2 -d &&
+	test-tool chmtime --verbose shared/.git/objects/pack/* >actual-shared-packs &&
+	test_cmp expected-shared-packs actual-shared-packs &&
+
+	# Furthermore, we expect that the member repository now has a single
+	# packfile that contains the combined shared and non-shared objects.
+	ls member/.git/objects/pack/pack-*.idx >actual &&
+	test_line_count = 1 actual &&
+	packed_objects member/.git/objects/pack/pack-*.idx >actual-objects &&
+	test_line_count = 6 actual-objects &&
+	test_cmp expected-objects actual-objects
+'
+
+test_expect_success '--geometric -l disables writing bitmaps with non-local packfiles' '
+	test_when_finished "rm -fr shared member" &&
+
+	git init shared &&
+	test_commit_bulk -C shared --start=1 1 &&
+
+	git clone --shared shared member &&
+	test_commit_bulk -C member --start=2 1 &&
+
+	# When performing a geometric repack with `-l` while connected to an
+	# alternate object database that has a packfile we do not have full
+	# coverage of objects. As a result, we expect that writing the bitmap
+	# will be disabled.
+	git -C member repack -l --geometric=2 --write-midx --write-bitmap-index 2>err &&
+	cat >expect <<-EOF &&
+	warning: disabling bitmap writing, as some objects are not being packed
+	EOF
+	test_cmp expect err &&
+	test_path_is_missing member/.git/objects/pack/multi-pack-index-*.bitmap &&
+
+	# On the other hand, when we repack without `-l`, we should see that
+	# the bitmap gets created.
+	git -C member repack --geometric=2 --write-midx --write-bitmap-index 2>err &&
+	test_must_be_empty err &&
+	test_path_is_file member/.git/objects/pack/multi-pack-index-*.bitmap
+'
+
 test_done
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 24297e2..59d3847 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -155,6 +155,58 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'difftool with guiDefault auto selects gui tool when there is DISPLAY' '
+	difftool_test_setup &&
+	test_config merge.tool bogus-tool &&
+	test_config diff.tool bogus-tool &&
+	test_config diff.guitool test-tool &&
+	test_config difftool.guiDefault auto &&
+	DISPLAY=SOMETHING && export DISPLAY &&
+
+	echo branch >expect &&
+	git difftool --no-prompt branch >actual &&
+	test_cmp expect actual
+'
+test_expect_success 'difftool with guiDefault auto selects regular tool when no DISPLAY' '
+	difftool_test_setup &&
+	test_config diff.guitool bogus-tool &&
+	test_config diff.tool test-tool &&
+	test_config difftool.guiDefault Auto &&
+	DISPLAY= && export DISPLAY &&
+
+	echo branch >expect &&
+	git difftool --no-prompt branch >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'difftool with guiDefault true selects gui tool' '
+	difftool_test_setup &&
+	test_config diff.tool bogus-tool &&
+	test_config diff.guitool test-tool &&
+	test_config difftool.guiDefault true &&
+
+	DISPLAY= && export DISPLAY &&
+	echo branch >expect &&
+	git difftool --no-prompt branch >actual &&
+	test_cmp expect actual &&
+
+	DISPLAY=Something && export DISPLAY &&
+	echo branch >expect &&
+	git difftool --no-prompt branch >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'difftool --no-gui trumps config guiDefault' '
+	difftool_test_setup &&
+	test_config diff.guitool bogus-tool &&
+	test_config diff.tool test-tool &&
+	test_config difftool.guiDefault true &&
+
+	echo branch >expect &&
+	git difftool --no-prompt --no-gui branch >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'difftool --gui last setting wins' '
 	difftool_test_setup &&
 	: >expect &&
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 8eded6a..39d6d71 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -1001,7 +1001,9 @@
 test_expect_success 'grep with CE_VALID file' '
 	git update-index --assume-unchanged t/t &&
 	rm t/t &&
-	test "$(git grep test)" = "t/t:test" &&
+	echo "t/t:test" >expect &&
+	git grep test >actual &&
+	test_cmp expect actual &&
 	git update-index --no-assume-unchanged t/t &&
 	git checkout t/t
 '
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 823331e..487e326 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -524,6 +524,44 @@
 	git maintenance unregister --config-file ./other --force
 '
 
+test_expect_success 'register with no value for maintenance.repo' '
+	cp .git/config .git/config.orig &&
+	test_when_finished mv .git/config.orig .git/config &&
+
+	cat >>.git/config <<-\EOF &&
+	[maintenance]
+		repo
+	EOF
+	cat >expect <<-\EOF &&
+	error: missing value for '\''maintenance.repo'\''
+	EOF
+	git maintenance register 2>actual &&
+	test_cmp expect actual &&
+	git config maintenance.repo
+'
+
+test_expect_success 'unregister with no value for maintenance.repo' '
+	cp .git/config .git/config.orig &&
+	test_when_finished mv .git/config.orig .git/config &&
+
+	cat >>.git/config <<-\EOF &&
+	[maintenance]
+		repo
+	EOF
+	cat >expect <<-\EOF &&
+	error: missing value for '\''maintenance.repo'\''
+	EOF
+	test_expect_code 128 git maintenance unregister 2>actual.raw &&
+	grep ^error actual.raw >actual &&
+	test_cmp expect actual &&
+	git config maintenance.repo &&
+
+	git maintenance unregister --force 2>actual.raw &&
+	grep ^error actual.raw >actual &&
+	test_cmp expect actual &&
+	git config maintenance.repo
+'
+
 test_expect_success !MINGW 'register and unregister with regex metacharacters' '
 	META="a+b*c" &&
 	git init "$META" &&
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 323952a..22fc908 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -4,7 +4,7 @@
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
-TEST_PASSES_SANITIZE_LEAK=true
+# no longer TEST_PASSES_SANITIZE_LEAK=true - format-patch --thread leaks
 . ./test-lib.sh
 
 # May be altered later in the test
@@ -12,7 +12,7 @@
 
 replace_variable_fields () {
 	sed	-e "s/^\(Date:\).*/\1 DATE-STRING/" \
-		-e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
+		-e "s/^\(Message-ID:\).*/\1 MESSAGE-ID-STRING/" \
 		-e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/"
 }
 
@@ -47,7 +47,7 @@
 
 test_expect_success $PREREQ 'Extract patches' '
 	patches=$(git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1) &&
-	threaded_patches=$(git format-patch -o threaded -s --in-reply-to="format" HEAD^1)
+	threaded_patches=$(git format-patch -o threaded --thread=shallow -s --in-reply-to="format" HEAD^1)
 '
 
 # Test no confirm early to ensure remaining tests will not hang
@@ -225,7 +225,7 @@
 	two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 In-Reply-To: <unique-message-id@example.com>
 References: <unique-message-id@example.com>
@@ -374,13 +374,16 @@
 	)
 '
 
-test_expect_success $PREREQ 'setup tocmd and cccmd scripts' '
+test_expect_success $PREREQ 'setup cmd scripts' '
 	write_script tocmd-sed <<-\EOF &&
 	sed -n -e "s/^tocmd--//p" "$1"
 	EOF
-	write_script cccmd-sed <<-\EOF
+	write_script cccmd-sed <<-\EOF &&
 	sed -n -e "s/^cccmd--//p" "$1"
 	EOF
+	write_script headercmd-sed <<-\EOF
+	sed -n -e "s/^headercmd--//p" "$1"
+	EOF
 '
 
 test_expect_success $PREREQ 'tocmd works' '
@@ -410,6 +413,70 @@
 	grep "^	cccmd@example.com" msgtxt1
 '
 
+test_expect_success $PREREQ 'headercmd works' '
+	clean_fake_sendmail &&
+	cp $patches headercmd.patch &&
+	echo "headercmd--X-Debbugs-CC: dummy@example.com" >>headercmd.patch &&
+	git send-email \
+		--from="Example <nobody@example.com>" \
+		--to=nobody@example.com \
+		--header-cmd=./headercmd-sed \
+		--smtp-server="$(pwd)/fake.sendmail" \
+		headercmd.patch \
+		&&
+	grep "^X-Debbugs-CC: dummy@example.com" msgtxt1
+'
+
+test_expect_success $PREREQ '--no-header-cmd works' '
+	clean_fake_sendmail &&
+	cp $patches headercmd.patch &&
+	echo "headercmd--X-Debbugs-CC: dummy@example.com" >>headercmd.patch &&
+	git send-email \
+		--from="Example <nobody@example.com>" \
+		--to=nobody@example.com \
+		--header-cmd=./headercmd-sed \
+		--no-header-cmd \
+		--smtp-server="$(pwd)/fake.sendmail" \
+		headercmd.patch \
+		&&
+	! grep "^X-Debbugs-CC: dummy@example.com" msgtxt1
+'
+
+test_expect_success $PREREQ 'multiline fields are correctly unfolded' '
+	clean_fake_sendmail &&
+	cp $patches headercmd.patch &&
+	write_script headercmd-multiline <<-\EOF &&
+	echo "X-Debbugs-CC: someone@example.com
+FoldedField: This is a tale
+ best told using
+ multiple lines."
+	EOF
+	git send-email \
+		--from="Example <nobody@example.com>" \
+		--to=nobody@example.com \
+		--header-cmd=./headercmd-multiline \
+		--smtp-server="$(pwd)/fake.sendmail" \
+		headercmd.patch &&
+	grep "^FoldedField: This is a tale best told using multiple lines.$" msgtxt1
+'
+
+# Blank lines in the middle of the output of a command are invalid.
+test_expect_success $PREREQ 'malform output reported on blank lines in command output' '
+	clean_fake_sendmail &&
+	cp $patches headercmd.patch &&
+	write_script headercmd-malformed-output <<-\EOF &&
+	echo "X-Debbugs-CC: someone@example.com
+
+SomeOtherField: someone-else@example.com"
+	EOF
+	! git send-email \
+		--from="Example <nobody@example.com>" \
+		--to=nobody@example.com \
+		--header-cmd=./headercmd-malformed-output \
+		--smtp-server="$(pwd)/fake.sendmail" \
+		headercmd.patch
+'
+
 test_expect_success $PREREQ 'reject long lines' '
 	z8=zzzzzzzz &&
 	z64=$z8$z8$z8$z8$z8$z8$z8$z8 &&
@@ -540,7 +607,7 @@
 	test_path_is_file my-hooks.ran &&
 	cat >expect <<-EOF &&
 	fatal: longline.patch: rejected by sendemail-validate hook
-	fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
+	fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1
 	warning: no patches were sent
 	EOF
 	test_cmp expect actual
@@ -559,12 +626,50 @@
 	test_path_is_file my-hooks.ran &&
 	cat >expect <<-EOF &&
 	fatal: longline.patch: rejected by sendemail-validate hook
-	fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
+	fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1
 	warning: no patches were sent
 	EOF
 	test_cmp expect actual
 '
 
+test_expect_success $PREREQ "--validate hook supports header argument" '
+	write_script my-hooks/sendemail-validate <<-\EOF &&
+	if test "$#" -ge 2
+	then
+		grep "X-test-header: v1.0" "$2"
+	else
+		echo "No header arg passed"
+		exit 1
+	fi
+	EOF
+	test_config core.hooksPath "my-hooks" &&
+	rm -fr outdir &&
+	git format-patch \
+		--add-header="X-test-header: v1.0" \
+		-n HEAD^1 -o outdir &&
+	git send-email \
+		--dry-run \
+		--to=nobody@example.com \
+		--smtp-server="$(pwd)/fake.sendmail" \
+		--validate \
+		outdir/000?-*.patch
+'
+
+test_expect_success $PREREQ 'clear message-id before parsing a new message' '
+	clean_fake_sendmail &&
+	echo true | write_script my-hooks/sendemail-validate &&
+	test_config core.hooksPath my-hooks &&
+	GIT_SEND_EMAIL_NOTTY=1 \
+	git send-email --validate --to=recipient@example.com \
+		--smtp-server="$(pwd)/fake.sendmail" \
+		$patches $threaded_patches &&
+	id0=$(grep "^Message-ID: " $threaded_patches) &&
+	id1=$(grep "^Message-ID: " msgtxt1) &&
+	id2=$(grep "^Message-ID: " msgtxt2) &&
+	test "z$id0" = "z$id2" &&
+	test "z$id1" != "z$id2"
+'
+
 for enc in 7bit 8bit quoted-printable base64
 do
 	test_expect_success $PREREQ "--transfer-encoding=$enc produces correct header" '
@@ -617,7 +722,7 @@
 	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt1 >actual &&
 	test_cmp expect actual &&
 	# Second and subsequent messages are replies to the first one
-	sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt1 >expect &&
+	sed -n -e "s/^Message-ID: *\(.*\)/\1/p" msgtxt1 >expect &&
 	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt2 >actual &&
 	test_cmp expect actual &&
 	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt3 >actual &&
@@ -637,10 +742,10 @@
 		2>errors &&
 	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt1 >actual &&
 	test_cmp expect actual &&
-	sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt1 >expect &&
+	sed -n -e "s/^Message-ID: *\(.*\)/\1/p" msgtxt1 >expect &&
 	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt2 >actual &&
 	test_cmp expect actual &&
-	sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt2 >expect &&
+	sed -n -e "s/^Message-ID: *\(.*\)/\1/p" msgtxt2 >expect &&
 	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt3 >actual &&
 	test_cmp expect actual
 '
@@ -713,7 +818,7 @@
 	two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 MIME-Version: 1.0
 Content-Transfer-Encoding: 8bit
@@ -759,7 +864,7 @@
 	two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 MIME-Version: 1.0
 Content-Transfer-Encoding: 8bit
@@ -796,7 +901,7 @@
 	C O Mitter <committer@example.com>
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 MIME-Version: 1.0
 Content-Transfer-Encoding: 8bit
@@ -824,7 +929,7 @@
 To: to@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 MIME-Version: 1.0
 Content-Transfer-Encoding: 8bit
@@ -860,7 +965,7 @@
 	cc-cmd@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 MIME-Version: 1.0
 Content-Transfer-Encoding: 8bit
@@ -893,7 +998,7 @@
 	two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 MIME-Version: 1.0
 Content-Transfer-Encoding: 8bit
@@ -926,7 +1031,7 @@
 	two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 MIME-Version: 1.0
 Content-Transfer-Encoding: 8bit
@@ -963,7 +1068,7 @@
 	C O Mitter <committer@example.com>
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 MIME-Version: 1.0
 Content-Transfer-Encoding: 8bit
@@ -993,7 +1098,7 @@
 	C O Mitter <committer@example.com>
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
 X-Mailer: X-MAILER-STRING
 MIME-Version: 1.0
 Content-Transfer-Encoding: 8bit
@@ -1478,7 +1583,7 @@
 test_expect_success $PREREQ 'setup expect' '
 cat >email-using-8bit <<\EOF
 From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-Message-Id: <bogus-message-id@example.com>
+Message-ID: <bogus-message-id@example.com>
 From: author@example.com
 Date: Sat, 12 Jun 2010 15:53:58 +0200
 Subject: subject goes here
@@ -1564,7 +1669,7 @@
 test_expect_success $PREREQ 'setup expect' '
 	cat >email-using-8bit <<-\EOF
 	From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-	Message-Id: <bogus-message-id@example.com>
+	Message-ID: <bogus-message-id@example.com>
 	From: author@example.com
 	Date: Sat, 12 Jun 2010 15:53:58 +0200
 	Subject: Dieser Betreff enthält auch einen Umlaut!
@@ -1593,7 +1698,7 @@
 test_expect_success $PREREQ 'setup expect' '
 	cat >email-using-8bit <<-\EOF
 	From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-	Message-Id: <bogus-message-id@example.com>
+	Message-ID: <bogus-message-id@example.com>
 	From: A U Thor <author@example.com>
 	Date: Sat, 12 Jun 2010 15:53:58 +0200
 	Content-Type: text/plain; charset=UTF-8
@@ -1674,7 +1779,7 @@
 test_expect_success $PREREQ 'setup expect' '
 	cat >email-using-qp <<-\EOF
 	From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-	Message-Id: <bogus-message-id@example.com>
+	Message-ID: <bogus-message-id@example.com>
 	From: A U Thor <author@example.com>
 	Date: Sat, 12 Jun 2010 15:53:58 +0200
 	MIME-Version: 1.0
@@ -1700,7 +1805,7 @@
 test_expect_success $PREREQ 'setup expect' "
 tr -d '\\015' | tr '%' '\\015' >email-using-crlf <<EOF
 From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-Message-Id: <bogus-message-id@example.com>
+Message-ID: <bogus-message-id@example.com>
 From: A U Thor <author@example.com>
 Date: Sat, 12 Jun 2010 15:53:58 +0200
 Content-Type: text/plain; charset=UTF-8
@@ -2326,6 +2431,37 @@
 	)
 '
 
+expected_file_counter_output () {
+	total=$1
+	count=0
+	while test $count -ne $total
+	do
+		count=$((count + 1)) &&
+		echo "$count/$total" || return
+	done
+}
+
+test_expect_success $PREREQ '--validate hook allows counting of messages' '
+	test_when_finished "rm -rf my-hooks.log" &&
+	test_config core.hooksPath "my-hooks" &&
+	mkdir -p my-hooks &&
+
+	write_script my-hooks/sendemail-validate <<-\EOF &&
+		num=$GIT_SENDEMAIL_FILE_COUNTER &&
+		tot=$GIT_SENDEMAIL_FILE_TOTAL &&
+		echo "$num/$tot" >>my-hooks.log || exit 1
+	EOF
+
+	>my-hooks.log &&
+	expected_file_counter_output 4 >expect &&
+	git send-email \
+		--from="Example <from@example.com>" \
+		--to=nobody@example.com \
+		--smtp-server="$(pwd)/fake.sendmail" \
+		--validate -3 --cover-letter --force &&
+	test_cmp expect my-hooks.log
+'
+
 test_expect_success $PREREQ 'test that send-email works outside a repo' '
 	nongit git send-email \
 		--from="Example <nobody@example.com>" \
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index aa55b41..ac237a1 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -388,9 +388,7 @@
 
 	INPUT_END
 
-	test_when_finished "rm -f .git/TEMP_TAG
-		git gc
-		git prune" &&
+	test_when_finished "rm -f .git/TEMP_TAG && git gc --prune=now" &&
 	git fast-import <input &&
 	test $(test-tool ref-store main resolve-ref TEMP_TAG 0 | cut -f1 -d " " ) != "$ZERO_OID" &&
 	test $(git rev-parse main) = $(git rev-parse TEMP_TAG^)
@@ -406,8 +404,7 @@
 	INPUT_END
 
 	test_when_finished "git update-ref -d refs/heads/empty-committer-1
-		git gc
-		git prune" &&
+		git gc --prune=now" &&
 	git fast-import <input &&
 	out=$(git fsck) &&
 	echo "$out" &&
@@ -452,8 +449,7 @@
 	INPUT_END
 
 	test_when_finished "git update-ref -d refs/heads/empty-committer-2
-		git gc
-		git prune" &&
+		git gc --prune=now" &&
 	git fast-import <input &&
 	out=$(git fsck) &&
 	echo "$out" &&
@@ -1778,8 +1774,7 @@
 	INPUT_END
 
 	git branch -D sub &&
-	git gc &&
-	git prune &&
+	git gc --prune=now &&
 	git fast-import <input &&
 	test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)
 '
diff --git a/t/t9304-fast-import-marks.sh b/t/t9304-fast-import-marks.sh
index a98ef03..410a871 100755
--- a/t/t9304-fast-import-marks.sh
+++ b/t/t9304-fast-import-marks.sh
@@ -49,4 +49,33 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'paths adjusted for relative subdir' '
+	git init deep-dst &&
+	mkdir deep-dst/subdir &&
+	>deep-dst/subdir/empty-marks &&
+	git -C deep-dst/subdir fast-import \
+		--rewrite-submodules-from=sub:../../from \
+		--rewrite-submodules-to=sub:../../to \
+		--import-marks=empty-marks \
+		--export-marks=exported-marks \
+		--export-pack-edges=exported-edges \
+		<dump &&
+	# we do not bother checking resulting repo; we just care that nothing
+	# complained about failing to open files for reading, and that files
+	# for writing were created in the expected spot
+	test_path_is_file deep-dst/subdir/exported-marks &&
+	test_path_is_file deep-dst/subdir/exported-edges
+'
+
+test_expect_success 'relative marks are not affected by subdir' '
+	git init deep-relative &&
+	mkdir deep-relative/subdir &&
+	git -C deep-relative/subdir fast-import \
+		--relative-marks \
+		--export-marks=exported-marks \
+		<dump &&
+	test_path_is_missing deep-relative/subdir/exported-marks &&
+	test_path_is_file deep-relative/.git/info/fast-import/exported-marks
+'
+
 test_done
diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh
index 77047e2..156a647 100755
--- a/t/t9351-fast-export-anonymize.sh
+++ b/t/t9351-fast-export-anonymize.sh
@@ -25,6 +25,7 @@
 test_expect_success 'export anonymized stream' '
 	git fast-export --anonymize --all \
 		--anonymize-map=retain-me \
+		--anonymize-map=xyzzy:should-not-appear \
 		--anonymize-map=xyzzy:custom-name \
 		--anonymize-map=other \
 		>stream
@@ -41,6 +42,7 @@
 
 test_expect_success 'stream contains user-specified names' '
 	grep retain-me stream &&
+	! grep should-not-appear stream &&
 	grep custom-name stream
 '
 
diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh
index dc88d0e..a4b3cb9 100755
--- a/t/t9800-git-p4-basic.sh
+++ b/t/t9800-git-p4-basic.sh
@@ -330,7 +330,7 @@
 	test_when_finished cleanup_git &&
 	(
 		cd "$git" &&
-		gittime=$(git show -s --raw --pretty=format:%at HEAD) &&
+		gittime=$(git show -s --pretty=format:%at HEAD) &&
 		echo $p4time $gittime &&
 		test $p4time = $gittime
 	)
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index d6c0478..8835e16 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -405,40 +405,40 @@
 
 test_expect_success '__git_dequote - plain unquoted word' '
 	__git_dequote unquoted-word &&
-	verbose test unquoted-word = "$dequoted_word"
+	test unquoted-word = "$dequoted_word"
 '
 
 # input:    b\a\c\k\'\\\"s\l\a\s\h\es
 # expected: back'\"slashes
 test_expect_success '__git_dequote - backslash escaped' '
 	__git_dequote "b\a\c\k\\'\''\\\\\\\"s\l\a\s\h\es" &&
-	verbose test "back'\''\\\"slashes" = "$dequoted_word"
+	test "back'\''\\\"slashes" = "$dequoted_word"
 '
 
 # input:    sin'gle\' '"quo'ted
 # expected: single\ "quoted
 test_expect_success '__git_dequote - single quoted' '
 	__git_dequote "'"sin'gle\\\\' '\\\"quo'ted"'" &&
-	verbose test '\''single\ "quoted'\'' = "$dequoted_word"
+	test '\''single\ "quoted'\'' = "$dequoted_word"
 '
 
 # input:    dou"ble\\" "\"\quot"ed
 # expected: double\ "\quoted
 test_expect_success '__git_dequote - double quoted' '
 	__git_dequote '\''dou"ble\\" "\"\quot"ed'\'' &&
-	verbose test '\''double\ "\quoted'\'' = "$dequoted_word"
+	test '\''double\ "\quoted'\'' = "$dequoted_word"
 '
 
 # input: 'open single quote
 test_expect_success '__git_dequote - open single quote' '
 	__git_dequote "'\''open single quote" &&
-	verbose test "open single quote" = "$dequoted_word"
+	test "open single quote" = "$dequoted_word"
 '
 
 # input: "open double quote
 test_expect_success '__git_dequote - open double quote' '
 	__git_dequote "\"open double quote" &&
-	verbose test "open double quote" = "$dequoted_word"
+	test "open double quote" = "$dequoted_word"
 '
 
 
@@ -616,7 +616,7 @@
 	test_when_finished "git remote remove remote_2" &&
 	git remote add remote_2 git://remote_2 &&
 	(
-		verbose __git_is_configured_remote remote_2 &&
+		__git_is_configured_remote remote_2 &&
 		test_must_fail __git_is_configured_remote non-existent
 	)
 '
@@ -2596,30 +2596,30 @@
 test_expect_success 'sourcing the completion script clears cached commands' '
 	(
 		__git_compute_all_commands &&
-		verbose test -n "$__git_all_commands" &&
+		test -n "$__git_all_commands" &&
 		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
-		verbose test -z "$__git_all_commands"
+		test -z "$__git_all_commands"
 	)
 '
 
 test_expect_success 'sourcing the completion script clears cached merge strategies' '
 	(
 		__git_compute_merge_strategies &&
-		verbose test -n "$__git_merge_strategies" &&
+		test -n "$__git_merge_strategies" &&
 		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
-		verbose test -z "$__git_merge_strategies"
+		test -z "$__git_merge_strategies"
 	)
 '
 
 test_expect_success 'sourcing the completion script clears cached --options' '
 	(
 		__gitcomp_builtin checkout &&
-		verbose test -n "$__gitcomp_builtin_checkout" &&
+		test -n "$__gitcomp_builtin_checkout" &&
 		__gitcomp_builtin notes_edit &&
-		verbose test -n "$__gitcomp_builtin_notes_edit" &&
+		test -n "$__gitcomp_builtin_notes_edit" &&
 		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
-		verbose test -z "$__gitcomp_builtin_checkout" &&
-		verbose test -z "$__gitcomp_builtin_notes_edit"
+		test -z "$__gitcomp_builtin_checkout" &&
+		test -z "$__gitcomp_builtin_notes_edit"
 	)
 '
 
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index d459fae..d667dda 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -13,10 +13,10 @@
 . "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh"
 
 actual="$TRASH_DIRECTORY/actual"
-c_red='\\[\\e[31m\\]'
-c_green='\\[\\e[32m\\]'
-c_lblue='\\[\\e[1;34m\\]'
-c_clear='\\[\\e[0m\\]'
+c_red='\001\e[31m\002'
+c_green='\001\e[32m\002'
+c_lblue='\001\e[1;34m\002'
+c_clear='\001\e[0m\002'
 
 test_expect_success 'setup for prompt tests' '
 	git init otherrepo &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 999d46f..6e19ebc 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1227,15 +1227,6 @@
 	return 1
 }
 
-# Call any command "$@" but be more verbose about its
-# failure. This is handy for commands like "test" which do
-# not output anything when they fail.
-verbose () {
-	"$@" && return 0
-	echo >&4 "command failed: $(git rev-parse --sq-quote "$@")"
-	return 1
-}
-
 # Check if the file expected to be empty is indeed empty, and barfs
 # otherwise.
 
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 62136ca..293caf0 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1041,10 +1041,7 @@
 # (and we want to make sure we run any cleanup like
 # "set +x").
 test_eval_inner_ () {
-	# Do not add anything extra (including LF) after '$*'
-	eval "
-		want_trace && trace_level_=$(($trace_level_+1)) && set -x
-		$*"
+	eval "$*"
 }
 
 test_eval_ () {
@@ -1069,7 +1066,10 @@
 	#     be _inside_ the block to avoid polluting the "set -x" output
 	#
 
-	test_eval_inner_ "$@" </dev/null >&3 2>&4
+	# Do not add anything extra (including LF) after '$*'
+	test_eval_inner_ </dev/null >&3 2>&4 "
+		want_trace && trace_level_=$(($trace_level_+1)) && set -x
+		$*"
 	{
 		test_eval_ret_=$?
 		if want_trace
@@ -1086,22 +1086,22 @@
 	return $test_eval_ret_
 }
 
+fail_117 () {
+	return 117
+}
+
 test_run_ () {
 	test_cleanup=:
 	expecting_failure=$2
 
 	if test "${GIT_TEST_CHAIN_LINT:-1}" != 0; then
-		# turn off tracing for this test-eval, as it simply creates
-		# confusing noise in the "-x" output
-		trace_tmp=$trace
-		trace=
 		# 117 is magic because it is unlikely to match the exit
 		# code of other programs
-		if test "OK-117" != "$(test_eval_ "(exit 117) && $1${LF}${LF}echo OK-\$?" 3>&1)"
+		test_eval_inner_ "fail_117 && $1" </dev/null >&3 2>&4
+		if test $? != 117
 		then
-			BUG "broken &&-chain or run-away HERE-DOC: $1"
+			BUG "broken &&-chain: $1"
 		fi
-		trace=$trace_tmp
 	fi
 
 	setup_malloc_check
@@ -1593,7 +1593,8 @@
 	BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_SANITIZE_LEAK_LOG=true"
 fi
 
-if test "${GIT_TEST_CHAIN_LINT:-1}" != 0
+if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 &&
+   test "${GIT_TEST_EXT_CHAIN_LINT:-1}" != 0
 then
 	"$PERL_PATH" "$TEST_DIRECTORY/chainlint.pl" "$0" ||
 		BUG "lint error (see '?!...!? annotations above)"
diff --git a/tag.c b/tag.c
index dfbcd7f..96dbd5b 100644
--- a/tag.c
+++ b/tag.c
@@ -1,12 +1,16 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "environment.h"
 #include "tag.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "commit.h"
 #include "tree.h"
 #include "blob.h"
 #include "alloc.h"
 #include "gpg-interface.h"
+#include "hex.h"
 #include "packfile.h"
+#include "wrapper.h"
 
 const char *tag_type = "tag";
 
@@ -51,15 +55,15 @@ int gpg_verify_tag(const struct object_id *oid, const char *name_to_report,
 		return error("%s: cannot verify a non-tag object of type %s.",
 				name_to_report ?
 				name_to_report :
-				find_unique_abbrev(oid, DEFAULT_ABBREV),
+				repo_find_unique_abbrev(the_repository, oid, DEFAULT_ABBREV),
 				type_name(type));
 
-	buf = read_object_file(oid, &type, &size);
+	buf = repo_read_object_file(the_repository, oid, &type, &size);
 	if (!buf)
 		return error("%s: unable to read file.",
 				name_to_report ?
 				name_to_report :
-				find_unique_abbrev(oid, DEFAULT_ABBREV));
+				repo_find_unique_abbrev(the_repository, oid, DEFAULT_ABBREV));
 
 	ret = run_gpg_verify(buf, size, flags);
 
@@ -216,7 +220,8 @@ int parse_tag(struct tag *item)
 
 	if (item->object.parsed)
 		return 0;
-	data = read_object_file(&item->object.oid, &type, &size);
+	data = repo_read_object_file(the_repository, &item->object.oid, &type,
+				     &size);
 	if (!data)
 		return error("Could not read %s",
 			     oid_to_hex(&item->object.oid));
diff --git a/tempfile.c b/tempfile.c
index e27048f..50c3771 100644
--- a/tempfile.c
+++ b/tempfile.c
@@ -42,9 +42,11 @@
  * file created by its parent.
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
+#include "path.h"
 #include "tempfile.h"
 #include "sigchain.h"
+#include "wrapper.h"
 
 static VOLATILE_LIST_HEAD(tempfile_list);
 
diff --git a/templates/hooks--sendemail-validate.sample b/templates/hooks--sendemail-validate.sample
new file mode 100755
index 0000000..640bcf8
--- /dev/null
+++ b/templates/hooks--sendemail-validate.sample
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+# An example hook script to validate a patch (and/or patch series) before
+# sending it via email.
+#
+# The hook should exit with non-zero status after issuing an appropriate
+# message if it wants to prevent the email(s) from being sent.
+#
+# To enable this hook, rename this file to "sendemail-validate".
+#
+# By default, it will only check that the patch(es) can be applied on top of
+# the default upstream branch without conflicts in a secondary worktree. After
+# validation (successful or not) of the last patch of a series, the worktree
+# will be deleted.
+#
+# The following config variables can be set to change the default remote and
+# remote ref that are used to apply the patches against:
+#
+#   sendemail.validateRemote (default: origin)
+#   sendemail.validateRemoteRef (default: HEAD)
+#
+# Replace the TODO placeholders with appropriate checks according to your
+# needs.
+
+validate_cover_letter () {
+	file="$1"
+	# TODO: Replace with appropriate checks (e.g. spell checking).
+	true
+}
+
+validate_patch () {
+	file="$1"
+	# Ensure that the patch applies without conflicts.
+	git am -3 "$file" || return
+	# TODO: Replace with appropriate checks for this patch
+	# (e.g. checkpatch.pl).
+	true
+}
+
+validate_series () {
+	# TODO: Replace with appropriate checks for the whole series
+	# (e.g. quick build, coding style checks, etc.).
+	true
+}
+
+# main -------------------------------------------------------------------------
+
+if test "$GIT_SENDEMAIL_FILE_COUNTER" = 1
+then
+	remote=$(git config --default origin --get sendemail.validateRemote) &&
+	ref=$(git config --default HEAD --get sendemail.validateRemoteRef) &&
+	worktree=$(mktemp --tmpdir -d sendemail-validate.XXXXXXX) &&
+	git worktree add -fd --checkout "$worktree" "refs/remotes/$remote/$ref" &&
+	git config --replace-all sendemail.validateWorktree "$worktree"
+else
+	worktree=$(git config --get sendemail.validateWorktree)
+fi || {
+	echo "sendemail-validate: error: failed to prepare worktree" >&2
+	exit 1
+}
+
+unset GIT_DIR GIT_WORK_TREE
+cd "$worktree" &&
+
+if grep -q "^diff --git " "$1"
+then
+	validate_patch "$1"
+else
+	validate_cover_letter "$1"
+fi &&
+
+if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL"
+then
+	git config --unset-all sendemail.validateWorktree &&
+	trap 'git worktree remove -ff "$worktree"' EXIT &&
+	validate_series
+fi
diff --git a/thread-utils.c b/thread-utils.c
index 5329845..1f89ffa 100644
--- a/thread-utils.c
+++ b/thread-utils.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "thread-utils.h"
 
 #if defined(hpux) || defined(__hpux) || defined(_hpux)
diff --git a/tmp-objdir.c b/tmp-objdir.c
index 2a2012e..c33a554 100644
--- a/tmp-objdir.c
+++ b/tmp-objdir.c
@@ -1,7 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "tmp-objdir.h"
+#include "abspath.h"
 #include "chdir-notify.h"
 #include "dir.h"
+#include "environment.h"
+#include "object-file.h"
 #include "sigchain.h"
 #include "string-list.h"
 #include "strbuf.h"
diff --git a/trace.c b/trace.c
index efa4e2d..592c141 100644
--- a/trace.c
+++ b/trace.c
@@ -21,8 +21,13 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "environment.h"
 #include "quote.h"
+#include "setup.h"
+#include "trace.h"
+#include "wrapper.h"
 
 struct trace_key trace_default_key = { "GIT_TRACE", 0, 0, 0 };
 struct trace_key trace_perf_key = TRACE_KEY_INIT(PERFORMANCE);
diff --git a/trace.h b/trace.h
index b6e35b9..d304d55 100644
--- a/trace.h
+++ b/trace.h
@@ -1,7 +1,6 @@
 #ifndef TRACE_H
 #define TRACE_H
 
-#include "git-compat-util.h"
 #include "strbuf.h"
 
 /**
diff --git a/trace2.c b/trace2.c
index 279bddf..0efc4e7 100644
--- a/trace2.c
+++ b/trace2.c
@@ -1,11 +1,14 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "json-writer.h"
 #include "quote.h"
+#include "repository.h"
 #include "run-command.h"
 #include "sigchain.h"
 #include "thread-utils.h"
 #include "version.h"
+#include "trace.h"
+#include "trace2.h"
 #include "trace2/tr2_cfg.h"
 #include "trace2/tr2_cmd_name.h"
 #include "trace2/tr2_ctr.h"
diff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c
index ec9ac1a..78cfc15 100644
--- a/trace2/tr2_cfg.c
+++ b/trace2/tr2_cfg.c
@@ -1,5 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "strbuf.h"
+#include "trace2.h"
 #include "trace2/tr2_cfg.h"
 #include "trace2/tr2_sysenv.h"
 
diff --git a/trace2/tr2_cmd_name.c b/trace2/tr2_cmd_name.c
index dd31320..b7b5a86 100644
--- a/trace2/tr2_cmd_name.c
+++ b/trace2/tr2_cmd_name.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "strbuf.h"
 #include "trace2/tr2_cmd_name.h"
 
 #define TR2_ENVVAR_PARENT_NAME "GIT_TRACE2_PARENT_NAME"
diff --git a/trace2/tr2_ctr.c b/trace2/tr2_ctr.c
index 483ca7c..b342d3b 100644
--- a/trace2/tr2_ctr.c
+++ b/trace2/tr2_ctr.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "thread-utils.h"
 #include "trace2/tr2_tgt.h"
 #include "trace2/tr2_tls.h"
diff --git a/trace2/tr2_dst.c b/trace2/tr2_dst.c
index 8a21dd2..5be892c 100644
--- a/trace2/tr2_dst.c
+++ b/trace2/tr2_dst.c
@@ -1,5 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
 #include "sigchain.h"
+#include "strbuf.h"
 #include "trace2/tr2_dst.h"
 #include "trace2/tr2_sid.h"
 #include "trace2/tr2_sysenv.h"
diff --git a/trace2/tr2_sid.c b/trace2/tr2_sid.c
index dc6e75e..09c4ef0 100644
--- a/trace2/tr2_sid.c
+++ b/trace2/tr2_sid.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "hex.h"
+#include "strbuf.h"
 #include "trace2/tr2_tbuf.h"
 #include "trace2/tr2_sid.h"
 
diff --git a/trace2/tr2_sysenv.c b/trace2/tr2_sysenv.c
index a380dcf..069786c 100644
--- a/trace2/tr2_sysenv.c
+++ b/trace2/tr2_sysenv.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "dir.h"
 #include "tr2_sysenv.h"
diff --git a/trace2/tr2_tbuf.c b/trace2/tr2_tbuf.c
index 2498482..c3b3822 100644
--- a/trace2/tr2_tbuf.c
+++ b/trace2/tr2_tbuf.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "tr2_tbuf.h"
 
 void tr2_tbuf_local_time(struct tr2_tbuf *tb)
diff --git a/trace2/tr2_tgt_event.c b/trace2/tr2_tgt_event.c
index 16f6332..2af53e5 100644
--- a/trace2/tr2_tgt_event.c
+++ b/trace2/tr2_tgt_event.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "json-writer.h"
+#include "repository.h"
 #include "run-command.h"
 #include "version.h"
 #include "trace2/tr2_dst.h"
diff --git a/trace2/tr2_tgt_normal.c b/trace2/tr2_tgt_normal.c
index fbbef68..1ebfb46 100644
--- a/trace2/tr2_tgt_normal.c
+++ b/trace2/tr2_tgt_normal.c
@@ -1,5 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "repository.h"
 #include "run-command.h"
 #include "quote.h"
 #include "version.h"
diff --git a/trace2/tr2_tgt_perf.c b/trace2/tr2_tgt_perf.c
index adae803..328e483 100644
--- a/trace2/tr2_tgt_perf.c
+++ b/trace2/tr2_tgt_perf.c
@@ -1,5 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "repository.h"
 #include "run-command.h"
 #include "quote.h"
 #include "version.h"
diff --git a/trace2/tr2_tls.c b/trace2/tr2_tls.c
index 04900bb..9f46ae1 100644
--- a/trace2/tr2_tls.c
+++ b/trace2/tr2_tls.c
@@ -1,5 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "thread-utils.h"
+#include "trace.h"
 #include "trace2/tr2_tls.h"
 
 /*
diff --git a/trace2/tr2_tmr.c b/trace2/tr2_tmr.c
index 786762d..31d0e4d 100644
--- a/trace2/tr2_tmr.c
+++ b/trace2/tr2_tmr.c
@@ -1,8 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "thread-utils.h"
 #include "trace2/tr2_tgt.h"
 #include "trace2/tr2_tls.h"
 #include "trace2/tr2_tmr.h"
+#include "trace.h"
 
 #define MY_MAX(a, b) ((a) > (b) ? (a) : (b))
 #define MY_MIN(a, b) ((a) < (b) ? (a) : (b))
diff --git a/trailer.c b/trailer.c
index 0fd5b14..a2c3ed6 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1,5 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
 #include "string-list.h"
 #include "run-command.h"
 #include "commit.h"
diff --git a/transport-helper.c b/transport-helper.c
index 3ea7c2b..6b81694 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1,9 +1,13 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "transport.h"
 #include "quote.h"
 #include "run-command.h"
 #include "commit.h"
 #include "diff.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "revision.h"
 #include "remote.h"
 #include "string-list.h"
@@ -14,6 +18,7 @@
 #include "refspec.h"
 #include "transport-internal.h"
 #include "protocol.h"
+#include "wrapper.h"
 
 static int debug;
 
@@ -1081,7 +1086,7 @@ static int push_refs_with_export(struct transport *transport,
 		struct object_id oid;
 
 		private = apply_refspecs(&data->rs, ref->name);
-		if (private && !get_oid(private, &oid)) {
+		if (private && !repo_get_oid(the_repository, private, &oid)) {
 			strbuf_addf(&buf, "^%s", private);
 			string_list_append_nodup(&revlist_args,
 						 strbuf_detach(&buf, NULL));
diff --git a/transport.c b/transport.c
index 77a61a9..67afdae 100644
--- a/transport.c
+++ b/transport.c
@@ -1,5 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
+#include "alloc.h"
 #include "config.h"
+#include "environment.h"
+#include "hex.h"
 #include "transport.h"
 #include "hook.h"
 #include "pkt-line.h"
@@ -10,6 +14,7 @@
 #include "walker.h"
 #include "bundle.h"
 #include "dir.h"
+#include "gettext.h"
 #include "refs.h"
 #include "refspec.h"
 #include "branch.h"
@@ -18,11 +23,14 @@
 #include "string-list.h"
 #include "oid-array.h"
 #include "sigchain.h"
+#include "trace2.h"
 #include "transport-internal.h"
 #include "protocol.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "color.h"
 #include "bundle-uri.h"
+#include "wrapper.h"
 
 static int transport_use_color = -1;
 static char transport_colors[][COLOR_MAXLEN] = {
@@ -167,7 +175,8 @@ static struct ref *get_refs_from_bundle(struct transport *transport,
 }
 
 static int fetch_refs_from_bundle(struct transport *transport,
-			       int nr_heads, struct ref **to_fetch)
+				  int nr_heads UNUSED,
+				  struct ref **to_fetch UNUSED)
 {
 	struct bundle_transport_data *data = transport->data;
 	struct strvec extra_index_pack_args = STRVEC_INIT;
@@ -276,8 +285,12 @@ static int connect_setup(struct transport *transport, int for_push)
 	}
 
 	data->conn = git_connect(data->fd, transport->url,
-				 for_push ? data->options.receivepack :
-				 data->options.uploadpack,
+				 for_push ?
+					"git-receive-pack" :
+					"git-upload-pack",
+				 for_push ?
+					data->options.receivepack :
+					data->options.uploadpack,
 				 flags);
 
 	return 0;
@@ -307,7 +320,7 @@ static struct ref *handshake(struct transport *transport, int for_push,
 	struct git_transport_data *data = transport->data;
 	struct ref *refs = NULL;
 	struct packet_reader reader;
-	int sid_len;
+	size_t sid_len;
 	const char *server_sid;
 
 	connect_setup(transport, for_push);
@@ -776,7 +789,8 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count,
 static int measure_abbrev(const struct object_id *oid, int sofar)
 {
 	char hex[GIT_MAX_HEXSZ + 1];
-	int w = find_unique_abbrev_r(hex, oid, DEFAULT_ABBREV);
+	int w = repo_find_unique_abbrev_r(the_repository, hex, oid,
+					  DEFAULT_ABBREV);
 
 	return (w < sofar) ? sofar : w;
 }
@@ -911,7 +925,7 @@ static int connect_git(struct transport *transport, const char *name,
 {
 	struct git_transport_data *data = transport->data;
 	data->conn = git_connect(data->fd, transport->url,
-				 executable, 0);
+				 name, executable, 0);
 	fd[0] = data->fd[0];
 	fd[1] = data->fd[1];
 	return 0;
diff --git a/transport.h b/transport.h
index 85150f5..6393cd9 100644
--- a/transport.h
+++ b/transport.h
@@ -1,7 +1,6 @@
 #ifndef TRANSPORT_H
 #define TRANSPORT_H
 
-#include "cache.h"
 #include "run-command.h"
 #include "remote.h"
 #include "list-objects-filter-options.h"
diff --git a/tree-diff.c b/tree-diff.c
index 69031d7..20bb15f 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -1,10 +1,24 @@
 /*
  * Helper functions for tree diff generation
  */
-#include "cache.h"
+#include "git-compat-util.h"
 #include "diff.h"
 #include "diffcore.h"
 #include "tree.h"
+#include "tree-walk.h"
+
+/*
+ * Some mode bits are also used internally for computations.
+ *
+ * They *must* not overlap with any valid modes, and they *must* not be emitted
+ * to outside world - i.e. appear on disk or network. In other words, it's just
+ * temporary fields, which we internally use, but they have to stay in-house.
+ *
+ * ( such approach is valid, as standard S_IF* fits into 16 bits, and in Git
+ *   codebase mode is `unsigned int` which is assumed to be at least 32 bits )
+ */
+
+#define S_DIFFTREE_IFXMIN_NEQ	0x80000000
 
 /*
  * internal mode marker, saying a tree entry != entry of tp[imin]
diff --git a/tree-walk.c b/tree-walk.c
index 74f4d71..d3c48e0 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -1,7 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "tree-walk.h"
+#include "alloc.h"
 #include "dir.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-file.h"
 #include "object-store.h"
+#include "trace2.h"
 #include "tree.h"
 #include "pathspec.h"
 #include "json-writer.h"
diff --git a/tree-walk.h b/tree-walk.h
index 6305d53..01a9d8e 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -1,7 +1,10 @@
 #ifndef TREE_WALK_H
 #define TREE_WALK_H
 
-#include "cache.h"
+#include "hash-ll.h"
+
+struct index_state;
+struct repository;
 
 #define MAX_TRAVERSE_TREES 8
 
diff --git a/tree.c b/tree.c
index 410e3b4..0dd2029 100644
--- a/tree.c
+++ b/tree.c
@@ -1,6 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "cache-tree.h"
+#include "hex.h"
 #include "tree.h"
+#include "object-name.h"
 #include "object-store.h"
 #include "blob.h"
 #include "commit.h"
@@ -58,7 +60,7 @@ int read_tree_at(struct repository *r,
 				    oid_to_hex(&entry.oid),
 				    base->buf, entry.path);
 
-			if (parse_commit(commit))
+			if (repo_parse_commit(r, commit))
 				die("Invalid commit %s in submodule path %s%s",
 				    oid_to_hex(&entry.oid),
 				    base->buf, entry.path);
@@ -92,14 +94,72 @@ int read_tree(struct repository *r,
 	return ret;
 }
 
-int cmp_cache_name_compare(const void *a_, const void *b_)
+int base_name_compare(const char *name1, size_t len1, int mode1,
+		      const char *name2, size_t len2, int mode2)
 {
-	const struct cache_entry *ce1, *ce2;
+	unsigned char c1, c2;
+	size_t len = len1 < len2 ? len1 : len2;
+	int cmp;
 
-	ce1 = *((const struct cache_entry **)a_);
-	ce2 = *((const struct cache_entry **)b_);
-	return cache_name_stage_compare(ce1->name, ce1->ce_namelen, ce_stage(ce1),
-				  ce2->name, ce2->ce_namelen, ce_stage(ce2));
+	cmp = memcmp(name1, name2, len);
+	if (cmp)
+		return cmp;
+	c1 = name1[len];
+	c2 = name2[len];
+	if (!c1 && S_ISDIR(mode1))
+		c1 = '/';
+	if (!c2 && S_ISDIR(mode2))
+		c2 = '/';
+	return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
+}
+
+/*
+ * df_name_compare() is identical to base_name_compare(), except it
+ * compares conflicting directory/file entries as equal. Note that
+ * while a directory name compares as equal to a regular file, they
+ * then individually compare _differently_ to a filename that has
+ * a dot after the basename (because '\0' < '.' < '/').
+ *
+ * This is used by routines that want to traverse the git namespace
+ * but then handle conflicting entries together when possible.
+ */
+int df_name_compare(const char *name1, size_t len1, int mode1,
+		    const char *name2, size_t len2, int mode2)
+{
+	unsigned char c1, c2;
+	size_t len = len1 < len2 ? len1 : len2;
+	int cmp;
+
+	cmp = memcmp(name1, name2, len);
+	if (cmp)
+		return cmp;
+	/* Directories and files compare equal (same length, same name) */
+	if (len1 == len2)
+		return 0;
+	c1 = name1[len];
+	if (!c1 && S_ISDIR(mode1))
+		c1 = '/';
+	c2 = name2[len];
+	if (!c2 && S_ISDIR(mode2))
+		c2 = '/';
+	if (c1 == '/' && !c2)
+		return 0;
+	if (c2 == '/' && !c1)
+		return 0;
+	return c1 - c2;
+}
+
+int name_compare(const char *name1, size_t len1, const char *name2, size_t len2)
+{
+	size_t min_len = (len1 < len2) ? len1 : len2;
+	int cmp = memcmp(name1, name2, min_len);
+	if (cmp)
+		return cmp;
+	if (len1 < len2)
+		return -1;
+	if (len1 > len2)
+		return 1;
+	return 0;
 }
 
 struct tree *lookup_tree(struct repository *r, const struct object_id *oid)
@@ -129,7 +189,8 @@ int parse_tree_gently(struct tree *item, int quiet_on_missing)
 
 	if (item->object.parsed)
 		return 0;
-	buffer = read_object_file(&item->object.oid, &type, &size);
+	buffer = repo_read_object_file(the_repository, &item->object.oid,
+				       &type, &size);
 	if (!buffer)
 		return quiet_on_missing ? -1 :
 			error("Could not read %s",
diff --git a/tree.h b/tree.h
index 6efff00..1b5ecbd 100644
--- a/tree.h
+++ b/tree.h
@@ -3,6 +3,7 @@
 
 #include "object.h"
 
+struct pathspec;
 struct repository;
 struct strbuf;
 
@@ -28,7 +29,15 @@ void free_tree_buffer(struct tree *tree);
 /* Parses and returns the tree in the given ent, chasing tags and commits. */
 struct tree *parse_tree_indirect(const struct object_id *oid);
 
-int cmp_cache_name_compare(const void *a_, const void *b_);
+/*
+ * Functions for comparing pathnames
+ */
+int base_name_compare(const char *name1, size_t len1, int mode1,
+		      const char *name2, size_t len2, int mode2);
+int df_name_compare(const char *name1, size_t len1, int mode1,
+		    const char *name2, size_t len2, int mode2);
+int name_compare(const char *name1, size_t len1,
+		 const char *name2, size_t len2);
 
 #define READ_TREE_RECURSIVE 1
 typedef int (*read_tree_fn_t)(const struct object_id *, struct strbuf *, const char *, unsigned int, void *);
diff --git a/unicode-width.h b/unicode-width.h
index 97c851b..e15fb04 100644
--- a/unicode-width.h
+++ b/unicode-width.h
@@ -94,7 +94,7 @@
 { 0x0E47, 0x0E4E },
 { 0x0EB1, 0x0EB1 },
 { 0x0EB4, 0x0EBC },
-{ 0x0EC8, 0x0ECD },
+{ 0x0EC8, 0x0ECE },
 { 0x0F18, 0x0F19 },
 { 0x0F35, 0x0F35 },
 { 0x0F37, 0x0F37 },
@@ -228,6 +228,7 @@
 { 0x10AE5, 0x10AE6 },
 { 0x10D24, 0x10D27 },
 { 0x10EAB, 0x10EAC },
+{ 0x10EFD, 0x10EFF },
 { 0x10F46, 0x10F50 },
 { 0x10F82, 0x10F85 },
 { 0x11001, 0x11001 },
@@ -252,6 +253,7 @@
 { 0x11234, 0x11234 },
 { 0x11236, 0x11237 },
 { 0x1123E, 0x1123E },
+{ 0x11241, 0x11241 },
 { 0x112DF, 0x112DF },
 { 0x112E3, 0x112EA },
 { 0x11300, 0x11301 },
@@ -313,7 +315,12 @@
 { 0x11D95, 0x11D95 },
 { 0x11D97, 0x11D97 },
 { 0x11EF3, 0x11EF4 },
-{ 0x13430, 0x13438 },
+{ 0x11F00, 0x11F01 },
+{ 0x11F36, 0x11F3A },
+{ 0x11F40, 0x11F40 },
+{ 0x11F42, 0x11F42 },
+{ 0x13430, 0x13440 },
+{ 0x13447, 0x13455 },
 { 0x16AF0, 0x16AF4 },
 { 0x16B30, 0x16B36 },
 { 0x16F4F, 0x16F4F },
@@ -339,9 +346,11 @@
 { 0x1E01B, 0x1E021 },
 { 0x1E023, 0x1E024 },
 { 0x1E026, 0x1E02A },
+{ 0x1E08F, 0x1E08F },
 { 0x1E130, 0x1E136 },
 { 0x1E2AE, 0x1E2AE },
 { 0x1E2EC, 0x1E2EF },
+{ 0x1E4EC, 0x1E4EF },
 { 0x1E8D0, 0x1E8D6 },
 { 0x1E944, 0x1E94A },
 { 0xE0001, 0xE0001 },
@@ -417,7 +426,9 @@ static const struct interval double_width[] = {
 { 0x1AFF5, 0x1AFFB },
 { 0x1AFFD, 0x1AFFE },
 { 0x1B000, 0x1B122 },
+{ 0x1B132, 0x1B132 },
 { 0x1B150, 0x1B152 },
+{ 0x1B155, 0x1B155 },
 { 0x1B164, 0x1B167 },
 { 0x1B170, 0x1B2FB },
 { 0x1F004, 0x1F004 },
@@ -451,7 +462,7 @@ static const struct interval double_width[] = {
 { 0x1F6CC, 0x1F6CC },
 { 0x1F6D0, 0x1F6D2 },
 { 0x1F6D5, 0x1F6D7 },
-{ 0x1F6DD, 0x1F6DF },
+{ 0x1F6DC, 0x1F6DF },
 { 0x1F6EB, 0x1F6EC },
 { 0x1F6F4, 0x1F6FC },
 { 0x1F7E0, 0x1F7EB },
@@ -459,15 +470,13 @@ static const struct interval double_width[] = {
 { 0x1F90C, 0x1F93A },
 { 0x1F93C, 0x1F945 },
 { 0x1F947, 0x1F9FF },
-{ 0x1FA70, 0x1FA74 },
-{ 0x1FA78, 0x1FA7C },
-{ 0x1FA80, 0x1FA86 },
-{ 0x1FA90, 0x1FAAC },
-{ 0x1FAB0, 0x1FABA },
-{ 0x1FAC0, 0x1FAC5 },
-{ 0x1FAD0, 0x1FAD9 },
-{ 0x1FAE0, 0x1FAE7 },
-{ 0x1FAF0, 0x1FAF6 },
+{ 0x1FA70, 0x1FA7C },
+{ 0x1FA80, 0x1FA88 },
+{ 0x1FA90, 0x1FABD },
+{ 0x1FABF, 0x1FAC5 },
+{ 0x1FACE, 0x1FADB },
+{ 0x1FAE0, 0x1FAE8 },
+{ 0x1FAF0, 0x1FAF8 },
 { 0x20000, 0x2FFFD },
 { 0x30000, 0x3FFFD }
 };
diff --git a/unix-socket.c b/unix-socket.c
index e0be1ba..79800d8 100644
--- a/unix-socket.c
+++ b/unix-socket.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "strbuf.h"
 #include "unix-socket.h"
 
 #define DEFAULT_UNIX_STREAM_LISTEN_BACKLOG (5)
diff --git a/unix-stream-server.c b/unix-stream-server.c
index efa2a20..22ac237 100644
--- a/unix-stream-server.c
+++ b/unix-stream-server.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "lockfile.h"
 #include "unix-socket.h"
 #include "unix-stream-server.h"
diff --git a/unpack-trees.c b/unpack-trees.c
index 3d05e45..e8c32a4 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1,8 +1,12 @@
 #include "cache.h"
+#include "advice.h"
 #include "strvec.h"
 #include "repository.h"
 #include "config.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "cache-tree.h"
@@ -14,11 +18,14 @@
 #include "sparse-index.h"
 #include "submodule.h"
 #include "submodule-config.h"
+#include "symlinks.h"
+#include "trace2.h"
 #include "fsmonitor.h"
 #include "object-store.h"
 #include "promisor-remote.h"
 #include "entry.h"
 #include "parallel-checkout.h"
+#include "setup.h"
 
 /*
  * Error messages expected by scripts out of plumbing commands such as
@@ -66,8 +73,8 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_WARNING_TYPES] = {
 };
 
 #define ERRORMSG(o,type) \
-	( ((o) && (o)->msgs[(type)]) \
-	  ? ((o)->msgs[(type)])      \
+	( ((o) && (o)->internal.msgs[(type)]) \
+	  ? ((o)->internal.msgs[(type)])      \
 	  : (unpack_plumbing_errors[(type)]) )
 
 static const char *super_prefixed(const char *path, const char *super_prefix)
@@ -108,10 +115,10 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
 				  const char *cmd)
 {
 	int i;
-	const char **msgs = opts->msgs;
+	const char **msgs = opts->internal.msgs;
 	const char *msg;
 
-	strvec_init(&opts->msgs_to_free);
+	strvec_init(&opts->internal.msgs_to_free);
 
 	if (!strcmp(cmd, "checkout"))
 		msg = advice_enabled(ADVICE_COMMIT_BEFORE_MERGE)
@@ -129,7 +136,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
 			  "Please commit your changes or stash them before you %s.")
 		      : _("Your local changes to the following files would be overwritten by %s:\n%%s");
 	msgs[ERROR_WOULD_OVERWRITE] = msgs[ERROR_NOT_UPTODATE_FILE] =
-		strvec_pushf(&opts->msgs_to_free, msg, cmd, cmd);
+		strvec_pushf(&opts->internal.msgs_to_free, msg, cmd, cmd);
 
 	msgs[ERROR_NOT_UPTODATE_DIR] =
 		_("Updating the following directories would lose untracked files in them:\n%s");
@@ -153,7 +160,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
 			  "Please move or remove them before you %s.")
 		      : _("The following untracked working tree files would be removed by %s:\n%%s");
 	msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] =
-		strvec_pushf(&opts->msgs_to_free, msg, cmd, cmd);
+		strvec_pushf(&opts->internal.msgs_to_free, msg, cmd, cmd);
 
 	if (!strcmp(cmd, "checkout"))
 		msg = advice_enabled(ADVICE_COMMIT_BEFORE_MERGE)
@@ -171,7 +178,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
 			  "Please move or remove them before you %s.")
 		      : _("The following untracked working tree files would be overwritten by %s:\n%%s");
 	msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] =
-		strvec_pushf(&opts->msgs_to_free, msg, cmd, cmd);
+		strvec_pushf(&opts->internal.msgs_to_free, msg, cmd, cmd);
 
 	/*
 	 * Special case: ERROR_BIND_OVERLAP refers to a pair of paths, we
@@ -189,16 +196,16 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
 	msgs[WARNING_SPARSE_ORPHANED_NOT_OVERWRITTEN] =
 		_("The following paths were already present and thus not updated despite sparse patterns:\n%s");
 
-	opts->show_all_errors = 1;
+	opts->internal.show_all_errors = 1;
 	/* rejected paths may not have a static buffer */
-	for (i = 0; i < ARRAY_SIZE(opts->unpack_rejects); i++)
-		opts->unpack_rejects[i].strdup_strings = 1;
+	for (i = 0; i < ARRAY_SIZE(opts->internal.unpack_rejects); i++)
+		opts->internal.unpack_rejects[i].strdup_strings = 1;
 }
 
 void clear_unpack_trees_porcelain(struct unpack_trees_options *opts)
 {
-	strvec_clear(&opts->msgs_to_free);
-	memset(opts->msgs, 0, sizeof(opts->msgs));
+	strvec_clear(&opts->internal.msgs_to_free);
+	memset(opts->internal.msgs, 0, sizeof(opts->internal.msgs));
 }
 
 static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
@@ -210,7 +217,7 @@ static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
 		set |= CE_WT_REMOVE;
 
 	ce->ce_flags = (ce->ce_flags & ~clear) | set;
-	return add_index_entry(&o->result, ce,
+	return add_index_entry(&o->internal.result, ce,
 			       ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
 }
 
@@ -218,7 +225,7 @@ static void add_entry(struct unpack_trees_options *o,
 		      const struct cache_entry *ce,
 		      unsigned int set, unsigned int clear)
 {
-	do_add_entry(o, dup_cache_entry(ce, &o->result), set, clear);
+	do_add_entry(o, dup_cache_entry(ce, &o->internal.result), set, clear);
 }
 
 /*
@@ -233,7 +240,7 @@ static int add_rejected_path(struct unpack_trees_options *o,
 	if (o->quiet)
 		return -1;
 
-	if (!o->show_all_errors)
+	if (!o->internal.show_all_errors)
 		return error(ERRORMSG(o, e), super_prefixed(path,
 							    o->super_prefix));
 
@@ -241,7 +248,7 @@ static int add_rejected_path(struct unpack_trees_options *o,
 	 * Otherwise, insert in a list for future display by
 	 * display_(error|warning)_msgs()
 	 */
-	string_list_append(&o->unpack_rejects[e], path);
+	string_list_append(&o->internal.unpack_rejects[e], path);
 	return -1;
 }
 
@@ -253,7 +260,7 @@ static void display_error_msgs(struct unpack_trees_options *o)
 	int e;
 	unsigned error_displayed = 0;
 	for (e = 0; e < NB_UNPACK_TREES_ERROR_TYPES; e++) {
-		struct string_list *rejects = &o->unpack_rejects[e];
+		struct string_list *rejects = &o->internal.unpack_rejects[e];
 
 		if (rejects->nr > 0) {
 			int i;
@@ -281,7 +288,7 @@ static void display_warning_msgs(struct unpack_trees_options *o)
 	unsigned warning_displayed = 0;
 	for (e = NB_UNPACK_TREES_ERROR_TYPES + 1;
 	     e < NB_UNPACK_TREES_WARNING_TYPES; e++) {
-		struct string_list *rejects = &o->unpack_rejects[e];
+		struct string_list *rejects = &o->internal.unpack_rejects[e];
 
 		if (rejects->nr > 0) {
 			int i;
@@ -458,7 +465,7 @@ static int check_updates(struct unpack_trees_options *o,
 	if (should_update_submodules())
 		load_gitmodules_file(index, &state);
 
-	if (has_promisor_remote())
+	if (repo_has_promisor_remote(the_repository))
 		/*
 		 * Prefetch the objects that are to be checked out in the loop
 		 * below.
@@ -600,13 +607,14 @@ static void mark_ce_used(struct cache_entry *ce, struct unpack_trees_options *o)
 {
 	ce->ce_flags |= CE_UNPACKED;
 
-	if (o->cache_bottom < o->src_index->cache_nr &&
-	    o->src_index->cache[o->cache_bottom] == ce) {
-		int bottom = o->cache_bottom;
+	if (o->internal.cache_bottom < o->src_index->cache_nr &&
+	    o->src_index->cache[o->internal.cache_bottom] == ce) {
+		int bottom = o->internal.cache_bottom;
+
 		while (bottom < o->src_index->cache_nr &&
 		       o->src_index->cache[bottom]->ce_flags & CE_UNPACKED)
 			bottom++;
-		o->cache_bottom = bottom;
+		o->internal.cache_bottom = bottom;
 	}
 }
 
@@ -652,7 +660,7 @@ static void mark_ce_used_same_name(struct cache_entry *ce,
 static struct cache_entry *next_cache_entry(struct unpack_trees_options *o)
 {
 	const struct index_state *index = o->src_index;
-	int pos = o->cache_bottom;
+	int pos = o->internal.cache_bottom;
 
 	while (pos < index->cache_nr) {
 		struct cache_entry *ce = index->cache[pos];
@@ -711,7 +719,7 @@ static void restore_cache_bottom(struct traverse_info *info, int bottom)
 
 	if (o->diff_index_cached)
 		return;
-	o->cache_bottom = bottom;
+	o->internal.cache_bottom = bottom;
 }
 
 static int switch_cache_bottom(struct traverse_info *info)
@@ -721,13 +729,13 @@ static int switch_cache_bottom(struct traverse_info *info)
 
 	if (o->diff_index_cached)
 		return 0;
-	ret = o->cache_bottom;
+	ret = o->internal.cache_bottom;
 	pos = find_cache_pos(info->prev, info->name, info->namelen);
 
 	if (pos < -1)
-		o->cache_bottom = -2 - pos;
+		o->internal.cache_bottom = -2 - pos;
 	else if (pos < 0)
-		o->cache_bottom = o->src_index->cache_nr;
+		o->internal.cache_bottom = o->src_index->cache_nr;
 	return ret;
 }
 
@@ -838,7 +846,7 @@ static int traverse_by_cache_tree(int pos, int nr_entries, int nr_names,
 		mark_ce_used(src[0], o);
 	}
 	free(tree_ce);
-	if (o->debug_unpack)
+	if (o->internal.debug_unpack)
 		printf("Unpacked %d entries from %s to %s using cache-tree\n",
 		       nr_entries,
 		       o->src_index->cache[pos]->name,
@@ -873,9 +881,9 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
 		 * save and restore cache_bottom anyway to not miss
 		 * unprocessed entries before 'pos'.
 		 */
-		bottom = o->cache_bottom;
+		bottom = o->internal.cache_bottom;
 		ret = traverse_by_cache_tree(pos, nr_entries, n, info);
-		o->cache_bottom = bottom;
+		o->internal.cache_bottom = bottom;
 		return ret;
 	}
 
@@ -1212,8 +1220,8 @@ static int unpack_single_entry(int n, unsigned long mask,
 		 * cache entry from the index aware logic.
 		 */
 		src[i + o->merge] = create_ce_entry(info, names + i, stage,
-						    &o->result, o->merge,
-						    bit & dirmask);
+						    &o->internal.result,
+						    o->merge, bit & dirmask);
 	}
 
 	if (o->merge) {
@@ -1237,7 +1245,7 @@ static int unpack_single_entry(int n, unsigned long mask,
 
 static int unpack_failed(struct unpack_trees_options *o, const char *message)
 {
-	discard_index(&o->result);
+	discard_index(&o->internal.result);
 	if (!o->quiet && !o->exiting_early) {
 		if (message)
 			return error("%s", message);
@@ -1260,7 +1268,7 @@ static int find_cache_pos(struct traverse_info *info,
 	struct index_state *index = o->src_index;
 	int pfxlen = info->pathlen;
 
-	for (pos = o->cache_bottom; pos < index->cache_nr; pos++) {
+	for (pos = o->internal.cache_bottom; pos < index->cache_nr; pos++) {
 		const struct cache_entry *ce = index->cache[pos];
 		const char *ce_name, *ce_slash;
 		int cmp, ce_len;
@@ -1271,8 +1279,8 @@ static int find_cache_pos(struct traverse_info *info,
 			 * we can never match it; don't check it
 			 * again.
 			 */
-			if (pos == o->cache_bottom)
-				++o->cache_bottom;
+			if (pos == o->internal.cache_bottom)
+				++o->internal.cache_bottom;
 			continue;
 		}
 		if (!ce_in_traverse_path(ce, info)) {
@@ -1450,7 +1458,7 @@ static int unpack_sparse_callback(int n, unsigned long mask, unsigned long dirma
 	 */
 	if (!is_null_oid(&names[0].oid)) {
 		src[0] = create_ce_entry(info, &names[0], 0,
-					&o->result, 1,
+					&o->internal.result, 1,
 					dirmask & (1ul << 0));
 		src[0]->ce_flags |= (CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);
 	}
@@ -1487,7 +1495,7 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
 	while (!p->mode)
 		p++;
 
-	if (o->debug_unpack)
+	if (o->internal.debug_unpack)
 		debug_unpack_callback(n, mask, dirmask, names, info);
 
 	/* Are we supposed to look at the index too? */
@@ -1560,7 +1568,7 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
 				 * in 'mark_ce_used()'
 				 */
 				if (!src[0] || !S_ISSPARSEDIR(src[0]->ce_mode))
-					o->cache_bottom += matches;
+					o->internal.cache_bottom += matches;
 				return mask;
 			}
 		}
@@ -1809,7 +1817,7 @@ static void populate_from_existing_patterns(struct unpack_trees_options *o,
 	if (get_sparse_checkout_patterns(pl) < 0)
 		o->skip_sparse_checkout = 1;
 	else
-		o->pl = pl;
+		o->internal.pl = pl;
 }
 
 static void update_sparsity_for_prefix(const char *prefix,
@@ -1871,8 +1879,12 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 
 	if (len > MAX_UNPACK_TREES)
 		die("unpack_trees takes at most %d trees", MAX_UNPACK_TREES);
-	if (o->dir)
-		BUG("o->dir is for internal use only");
+	if (o->internal.dir)
+		BUG("o->internal.dir is for internal use only");
+	if (o->internal.pl)
+		BUG("o->internal.pl is for internal use only");
+	if (o->df_conflict_entry)
+		BUG("o->df_conflict_entry is an output only field");
 
 	trace_performance_enter();
 	trace2_region_enter("unpack_trees", "unpack_trees", the_repository);
@@ -1889,9 +1901,9 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 		BUG("UNPACK_RESET_OVERWRITE_UNTRACKED incompatible with preserved ignored files");
 
 	if (!o->preserve_ignored) {
-		o->dir = &dir;
-		o->dir->flags |= DIR_SHOW_IGNORED;
-		setup_standard_excludes(o->dir);
+		o->internal.dir = &dir;
+		o->internal.dir->flags |= DIR_SHOW_IGNORED;
+		setup_standard_excludes(o->internal.dir);
 	}
 
 	if (o->prefix)
@@ -1899,49 +1911,52 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 
 	if (!core_apply_sparse_checkout || !o->update)
 		o->skip_sparse_checkout = 1;
-	if (!o->skip_sparse_checkout && !o->pl) {
+	if (!o->skip_sparse_checkout) {
 		memset(&pl, 0, sizeof(pl));
 		free_pattern_list = 1;
 		populate_from_existing_patterns(o, &pl);
 	}
 
-	index_state_init(&o->result, o->src_index->repo);
-	o->result.initialized = 1;
-	o->result.timestamp.sec = o->src_index->timestamp.sec;
-	o->result.timestamp.nsec = o->src_index->timestamp.nsec;
-	o->result.version = o->src_index->version;
+	index_state_init(&o->internal.result, o->src_index->repo);
+	o->internal.result.initialized = 1;
+	o->internal.result.timestamp.sec = o->src_index->timestamp.sec;
+	o->internal.result.timestamp.nsec = o->src_index->timestamp.nsec;
+	o->internal.result.version = o->src_index->version;
 	if (!o->src_index->split_index) {
-		o->result.split_index = NULL;
+		o->internal.result.split_index = NULL;
 	} else if (o->src_index == o->dst_index) {
 		/*
 		 * o->dst_index (and thus o->src_index) will be discarded
-		 * and overwritten with o->result at the end of this function,
-		 * so just use src_index's split_index to avoid having to
-		 * create a new one.
+		 * and overwritten with o->internal.result at the end of
+		 * this function, so just use src_index's split_index to
+		 * avoid having to create a new one.
 		 */
-		o->result.split_index = o->src_index->split_index;
-		o->result.split_index->refcount++;
+		o->internal.result.split_index = o->src_index->split_index;
+		if (o->src_index->cache_changed & SPLIT_INDEX_ORDERED)
+			o->internal.result.cache_changed |= SPLIT_INDEX_ORDERED;
+		o->internal.result.split_index->refcount++;
 	} else {
-		o->result.split_index = init_split_index(&o->result);
+		o->internal.result.split_index =
+			init_split_index(&o->internal.result);
 	}
-	oidcpy(&o->result.oid, &o->src_index->oid);
-	o->merge_size = len;
+	oidcpy(&o->internal.result.oid, &o->src_index->oid);
+	o->internal.merge_size = len;
 	mark_all_ce_unused(o->src_index);
 
-	o->result.fsmonitor_last_update =
+	o->internal.result.fsmonitor_last_update =
 		xstrdup_or_null(o->src_index->fsmonitor_last_update);
-	o->result.fsmonitor_has_run_once = o->src_index->fsmonitor_has_run_once;
+	o->internal.result.fsmonitor_has_run_once = o->src_index->fsmonitor_has_run_once;
 
 	if (!o->src_index->initialized &&
 	    !repo->settings.command_requires_full_index &&
-	    is_sparse_index_allowed(&o->result, 0))
-		o->result.sparse_index = 1;
+	    is_sparse_index_allowed(&o->internal.result, 0))
+		o->internal.result.sparse_index = 1;
 
 	/*
 	 * Sparse checkout loop #1: set NEW_SKIP_WORKTREE on existing entries
 	 */
 	if (!o->skip_sparse_checkout)
-		mark_new_skip_worktree(o->pl, o->src_index, 0,
+		mark_new_skip_worktree(o->internal.pl, o->src_index, 0,
 				       CE_NEW_SKIP_WORKTREE, o->verbose_update);
 
 	if (!dfc)
@@ -1955,7 +1970,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 		setup_traverse_info(&info, prefix);
 		info.fn = unpack_callback;
 		info.data = o;
-		info.show_all_errors = o->show_all_errors;
+		info.show_all_errors = o->internal.show_all_errors;
 		info.pathspec = o->pathspec;
 
 		if (o->prefix) {
@@ -1996,7 +2011,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 	}
 	mark_all_ce_unused(o->src_index);
 
-	if (o->trivial_merges_only && o->nontrivial_merge) {
+	if (o->trivial_merges_only && o->internal.nontrivial_merge) {
 		ret = unpack_failed(o, "Merge requires file-level merging");
 		goto done;
 	}
@@ -2007,13 +2022,13 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 		 * If they will have NEW_SKIP_WORKTREE, also set CE_SKIP_WORKTREE
 		 * so apply_sparse_checkout() won't attempt to remove it from worktree
 		 */
-		mark_new_skip_worktree(o->pl, &o->result,
+		mark_new_skip_worktree(o->internal.pl, &o->internal.result,
 				       CE_ADDED, CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE,
 				       o->verbose_update);
 
 		ret = 0;
-		for (i = 0; i < o->result.cache_nr; i++) {
-			struct cache_entry *ce = o->result.cache[i];
+		for (i = 0; i < o->internal.result.cache_nr; i++) {
+			struct cache_entry *ce = o->internal.result.cache[i];
 
 			/*
 			 * Entries marked with CE_ADDED in merged_entry() do not have
@@ -2027,7 +2042,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 			    verify_absent(ce, WARNING_SPARSE_ORPHANED_NOT_OVERWRITTEN, o))
 				ret = 1;
 
-			if (apply_sparse_checkout(&o->result, ce, o))
+			if (apply_sparse_checkout(&o->internal.result, ce, o))
 				ret = 1;
 		}
 		if (ret == 1) {
@@ -2035,46 +2050,47 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 			 * Inability to sparsify or de-sparsify individual
 			 * paths is not an error, but just a warning.
 			 */
-			if (o->show_all_errors)
+			if (o->internal.show_all_errors)
 				display_warning_msgs(o);
 			ret = 0;
 		}
 	}
 
-	ret = check_updates(o, &o->result) ? (-2) : 0;
+	ret = check_updates(o, &o->internal.result) ? (-2) : 0;
 	if (o->dst_index) {
-		move_index_extensions(&o->result, o->src_index);
+		move_index_extensions(&o->internal.result, o->src_index);
 		if (!ret) {
 			if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0))
-				cache_tree_verify(the_repository, &o->result);
+				cache_tree_verify(the_repository,
+						  &o->internal.result);
 			if (!o->skip_cache_tree_update &&
-			    !cache_tree_fully_valid(o->result.cache_tree))
-				cache_tree_update(&o->result,
+			    !cache_tree_fully_valid(o->internal.result.cache_tree))
+				cache_tree_update(&o->internal.result,
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
 
-		o->result.updated_workdir = 1;
+		o->internal.result.updated_workdir = 1;
 		discard_index(o->dst_index);
-		*o->dst_index = o->result;
+		*o->dst_index = o->internal.result;
 	} else {
-		discard_index(&o->result);
+		discard_index(&o->internal.result);
 	}
 	o->src_index = NULL;
 
 done:
 	if (free_pattern_list)
 		clear_pattern_list(&pl);
-	if (o->dir) {
-		dir_clear(o->dir);
-		o->dir = NULL;
+	if (o->internal.dir) {
+		dir_clear(o->internal.dir);
+		o->internal.dir = NULL;
 	}
 	trace2_region_leave("unpack_trees", "unpack_trees", the_repository);
 	trace_performance_leave("unpack_trees");
 	return ret;
 
 return_failed:
-	if (o->show_all_errors)
+	if (o->internal.show_all_errors)
 		display_error_msgs(o);
 	mark_all_ce_unused(o->src_index);
 	ret = unpack_failed(o, NULL);
@@ -2089,16 +2105,17 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
  *
  * CE_NEW_SKIP_WORKTREE is used internally.
  */
-enum update_sparsity_result update_sparsity(struct unpack_trees_options *o)
+enum update_sparsity_result update_sparsity(struct unpack_trees_options *o,
+					    struct pattern_list *pl)
 {
 	enum update_sparsity_result ret = UPDATE_SPARSITY_SUCCESS;
-	struct pattern_list pl;
 	int i;
 	unsigned old_show_all_errors;
 	int free_pattern_list = 0;
 
-	old_show_all_errors = o->show_all_errors;
-	o->show_all_errors = 1;
+	old_show_all_errors = o->internal.show_all_errors;
+	o->internal.show_all_errors = 1;
+	index_state_init(&o->internal.result, o->src_index->repo);
 
 	/* Sanity checks */
 	if (!o->update || o->index_only || o->skip_sparse_checkout)
@@ -2109,20 +2126,19 @@ enum update_sparsity_result update_sparsity(struct unpack_trees_options *o)
 	trace_performance_enter();
 
 	/* If we weren't given patterns, use the recorded ones */
-	if (!o->pl) {
-		memset(&pl, 0, sizeof(pl));
+	if (!pl) {
 		free_pattern_list = 1;
-		populate_from_existing_patterns(o, &pl);
-		if (o->skip_sparse_checkout)
-			goto skip_sparse_checkout;
+		pl = xcalloc(1, sizeof(*pl));
+		populate_from_existing_patterns(o, pl);
 	}
+	o->internal.pl = pl;
 
 	/* Expand sparse directories as needed */
-	expand_index(o->src_index, o->pl);
+	expand_index(o->src_index, o->internal.pl);
 
 	/* Set NEW_SKIP_WORKTREE on existing entries. */
 	mark_all_ce_unused(o->src_index);
-	mark_new_skip_worktree(o->pl, o->src_index, 0,
+	mark_new_skip_worktree(o->internal.pl, o->src_index, 0,
 			       CE_NEW_SKIP_WORKTREE, o->verbose_update);
 
 	/* Then loop over entries and update/remove as needed */
@@ -2142,14 +2158,16 @@ enum update_sparsity_result update_sparsity(struct unpack_trees_options *o)
 			ret = UPDATE_SPARSITY_WARNINGS;
 	}
 
-skip_sparse_checkout:
 	if (check_updates(o, o->src_index))
 		ret = UPDATE_SPARSITY_WORKTREE_UPDATE_FAILURES;
 
 	display_warning_msgs(o);
-	o->show_all_errors = old_show_all_errors;
-	if (free_pattern_list)
-		clear_pattern_list(&pl);
+	o->internal.show_all_errors = old_show_all_errors;
+	if (free_pattern_list) {
+		clear_pattern_list(pl);
+		free(pl);
+		o->internal.pl = NULL;
+	}
 	trace_performance_leave("update_sparsity");
 	return ret;
 }
@@ -2244,15 +2262,15 @@ static int verify_uptodate_sparse(const struct cache_entry *ce,
 }
 
 /*
- * TODO: We should actually invalidate o->result, not src_index [1].
+ * TODO: We should actually invalidate o->internal.result, not src_index [1].
  * But since cache tree and untracked cache both are not copied to
- * o->result until unpacking is complete, we invalidate them on
+ * o->internal.result until unpacking is complete, we invalidate them on
  * src_index instead with the assumption that they will be copied to
  * dst_index at the end.
  *
  * [1] src_index->cache_tree is also used in unpack_callback() so if
- * we invalidate o->result, we need to update it to use
- * o->result.cache_tree as well.
+ * we invalidate o->internal.result, we need to update it to use
+ * o->internal.result.cache_tree as well.
  */
 static void invalidate_ce_path(const struct cache_entry *ce,
 			       struct unpack_trees_options *o)
@@ -2336,8 +2354,8 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
 	pathbuf = xstrfmt("%.*s/", namelen, ce->name);
 
 	memset(&d, 0, sizeof(d));
-	if (o->dir)
-		d.exclude_per_dir = o->dir->exclude_per_dir;
+	if (o->internal.dir)
+		setup_standard_excludes(&d);
 	i = read_directory(&d, o->src_index, pathbuf, namelen+1, NULL);
 	dir_clear(&d);
 	free(pathbuf);
@@ -2391,8 +2409,8 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
 	if (ignore_case && icase_exists(o, name, len, st))
 		return 0;
 
-	if (o->dir &&
-	    is_excluded(o->dir, o->src_index, name, &dtype))
+	if (o->internal.dir &&
+	    is_excluded(o->internal.dir, o->src_index, name, &dtype))
 		/*
 		 * ce->name is explicitly excluded, so it is Ok to
 		 * overwrite it.
@@ -2420,7 +2438,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
 	 * delete this path, which is in a subdirectory that
 	 * is being replaced with a blob.
 	 */
-	result = index_file_exists(&o->result, name, len, 0);
+	result = index_file_exists(&o->internal.result, name, len, 0);
 	if (result) {
 		if (result->ce_flags & CE_REMOVE)
 			return 0;
@@ -2521,7 +2539,7 @@ static int merged_entry(const struct cache_entry *ce,
 			struct unpack_trees_options *o)
 {
 	int update = CE_UPDATE;
-	struct cache_entry *merge = dup_cache_entry(ce, &o->result);
+	struct cache_entry *merge = dup_cache_entry(ce, &o->internal.result);
 
 	if (!old) {
 		/*
@@ -2616,7 +2634,7 @@ static int merged_sparse_dir(const struct cache_entry * const *src, int n,
 	setup_traverse_info(&info, src[0]->name);
 	info.fn = unpack_sparse_callback;
 	info.data = o;
-	info.show_all_errors = o->show_all_errors;
+	info.show_all_errors = o->internal.show_all_errors;
 	info.pathspec = o->pathspec;
 
 	/* Get the tree descriptors of the sparse directory in each of the merging trees */
@@ -2834,7 +2852,7 @@ int threeway_merge(const struct cache_entry * const *stages,
 			return -1;
 	}
 
-	o->nontrivial_merge = 1;
+	o->internal.nontrivial_merge = 1;
 
 	/* #2, #3, #4, #6, #7, #9, #10, #11. */
 	count = 0;
@@ -2875,9 +2893,9 @@ int twoway_merge(const struct cache_entry * const *src,
 	const struct cache_entry *oldtree = src[1];
 	const struct cache_entry *newtree = src[2];
 
-	if (o->merge_size != 2)
+	if (o->internal.merge_size != 2)
 		return error("Cannot do a twoway merge of %d trees",
-			     o->merge_size);
+			     o->internal.merge_size);
 
 	if (oldtree == o->df_conflict_entry)
 		oldtree = NULL;
@@ -2957,9 +2975,9 @@ int bind_merge(const struct cache_entry * const *src,
 	const struct cache_entry *old = src[0];
 	const struct cache_entry *a = src[1];
 
-	if (o->merge_size != 1)
+	if (o->internal.merge_size != 1)
 		return error("Cannot do a bind merge of %d trees",
-			     o->merge_size);
+			     o->internal.merge_size);
 	if (a && old)
 		return o->quiet ? -1 :
 			error(ERRORMSG(o, ERROR_BIND_OVERLAP),
@@ -2983,9 +3001,9 @@ int oneway_merge(const struct cache_entry * const *src,
 	const struct cache_entry *old = src[0];
 	const struct cache_entry *a = src[1];
 
-	if (o->merge_size != 1)
+	if (o->internal.merge_size != 1)
 		return error("Cannot do a oneway merge of %d trees",
-			     o->merge_size);
+			     o->internal.merge_size);
 
 	if (!a || a == o->df_conflict_entry)
 		return deleted_entry(old, old, o);
@@ -3020,8 +3038,8 @@ int stash_worktree_untracked_merge(const struct cache_entry * const *src,
 	const struct cache_entry *worktree = src[1];
 	const struct cache_entry *untracked = src[2];
 
-	if (o->merge_size != 2)
-		BUG("invalid merge_size: %d", o->merge_size);
+	if (o->internal.merge_size != 2)
+		BUG("invalid merge_size: %d", o->internal.merge_size);
 
 	if (worktree && untracked)
 		return error(_("worktree and untracked commit have duplicate entries: %s"),
diff --git a/unpack-trees.h b/unpack-trees.h
index 3a7b3e5..30622ae 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -2,6 +2,7 @@
 #define UNPACK_TREES_H
 
 #include "cache.h"
+#include "convert.h"
 #include "strvec.h"
 #include "string-list.h"
 #include "tree-walk.h"
@@ -59,47 +60,54 @@ struct unpack_trees_options {
 		     preserve_ignored,
 		     clone,
 		     index_only,
-		     nontrivial_merge,
 		     trivial_merges_only,
 		     verbose_update,
 		     aggressive,
 		     skip_unmerged,
 		     initial_checkout,
 		     diff_index_cached,
-		     debug_unpack,
 		     skip_sparse_checkout,
 		     quiet,
 		     exiting_early,
-		     show_all_errors,
 		     dry_run,
 		     skip_cache_tree_update;
 	enum unpack_trees_reset_type reset;
 	const char *prefix;
 	const char *super_prefix;
-	int cache_bottom;
 	struct pathspec *pathspec;
 	merge_fn_t fn;
-	const char *msgs[NB_UNPACK_TREES_WARNING_TYPES];
-	struct strvec msgs_to_free;
-	/*
-	 * Store error messages in an array, each case
-	 * corresponding to a error message type
-	 */
-	struct string_list unpack_rejects[NB_UNPACK_TREES_WARNING_TYPES];
 
 	int head_idx;
-	int merge_size;
 
-	struct cache_entry *df_conflict_entry;
+	struct cache_entry *df_conflict_entry; /* output only */
 	void *unpack_data;
 
 	struct index_state *dst_index;
 	struct index_state *src_index;
-	struct index_state result;
 
-	struct pattern_list *pl; /* for internal use */
-	struct dir_struct *dir; /* for internal use only */
 	struct checkout_metadata meta;
+
+	struct unpack_trees_options_internal {
+		unsigned int nontrivial_merge,
+			     show_all_errors,
+			     debug_unpack; /* used by read-tree debugging */
+
+		int merge_size; /* used by read-tree debugging */
+		int cache_bottom;
+		const char *msgs[NB_UNPACK_TREES_WARNING_TYPES];
+		struct strvec msgs_to_free;
+
+		/*
+		 * Store error messages in an array, each case
+		 * corresponding to a error message type
+		 */
+		struct string_list unpack_rejects[NB_UNPACK_TREES_WARNING_TYPES];
+
+		struct index_state result;
+
+		struct pattern_list *pl;
+		struct dir_struct *dir;
+	} internal;
 };
 
 int unpack_trees(unsigned n, struct tree_desc *t,
@@ -112,7 +120,8 @@ enum update_sparsity_result {
 	UPDATE_SPARSITY_WORKTREE_UPDATE_FAILURES = -2
 };
 
-enum update_sparsity_result update_sparsity(struct unpack_trees_options *options);
+enum update_sparsity_result update_sparsity(struct unpack_trees_options *options,
+					    struct pattern_list *pl);
 
 int verify_uptodate(const struct cache_entry *ce,
 		    struct unpack_trees_options *o);
diff --git a/upload-pack.c b/upload-pack.c
index 551f22f..d331200 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1,10 +1,14 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "refs.h"
 #include "pkt-line.h"
 #include "sideband.h"
 #include "repository.h"
 #include "object-store.h"
+#include "oid-array.h"
 #include "tag.h"
 #include "object.h"
 #include "commit.h"
@@ -19,6 +23,7 @@
 #include "version.h"
 #include "string-list.h"
 #include "strvec.h"
+#include "trace2.h"
 #include "prio-queue.h"
 #include "protocol.h"
 #include "quote.h"
@@ -27,6 +32,8 @@
 #include "commit-graph.h"
 #include "commit-reach.h"
 #include "shallow.h"
+#include "wrapper.h"
+#include "write-or-die.h"
 
 /* Remember to update object flag allocation in object.h */
 #define THEY_HAVE	(1u << 11)
@@ -113,6 +120,7 @@ struct upload_pack_data {
 	unsigned allow_ref_in_want : 1;				/* v2 only */
 	unsigned allow_sideband_all : 1;			/* v2 only */
 	unsigned advertise_sid : 1;
+	unsigned sent_capabilities : 1;
 };
 
 static void upload_pack_data_init(struct upload_pack_data *data)
@@ -499,8 +507,8 @@ static int got_oid(struct upload_pack_data *data,
 {
 	if (get_oid_hex(hex, oid))
 		die("git upload-pack: expected SHA1 object, got '%s'", hex);
-	if (!has_object_file_with_flags(oid,
-					OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT))
+	if (!repo_has_object_file_with_flags(the_repository, oid,
+					     OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT))
 		return -1;
 	return do_got_oid(data, oid);
 }
@@ -1063,7 +1071,7 @@ static void receive_needs(struct upload_pack_data *data,
 		const char *features;
 		struct object_id oid_buf;
 		const char *arg;
-		int feature_len;
+		size_t feature_len;
 
 		reset_timeout(data->timeout);
 		if (packet_reader_read(reader) != PACKET_READ_NORMAL)
@@ -1199,18 +1207,17 @@ static void format_session_id(struct strbuf *buf, struct upload_pack_data *d) {
 		strbuf_addf(buf, " session-id=%s", trace2_session_id());
 }
 
-static int send_ref(const char *refname, const struct object_id *oid,
-		    int flag UNUSED, void *cb_data)
+static void write_v0_ref(struct upload_pack_data *data,
+			const char *refname, const char *refname_nons,
+			const struct object_id *oid)
 {
 	static const char *capabilities = "multi_ack thin-pack side-band"
 		" side-band-64k ofs-delta shallow deepen-since deepen-not"
 		" deepen-relative no-progress include-tag multi_ack_detailed";
-	const char *refname_nons = strip_namespace(refname);
 	struct object_id peeled;
-	struct upload_pack_data *data = cb_data;
 
 	if (mark_our_ref(refname_nons, refname, oid, &data->hidden_refs))
-		return 0;
+		return;
 
 	if (capabilities) {
 		struct strbuf symref_info = STRBUF_INIT;
@@ -1233,12 +1240,20 @@ static int send_ref(const char *refname, const struct object_id *oid,
 			     git_user_agent_sanitized());
 		strbuf_release(&symref_info);
 		strbuf_release(&session_id);
+		data->sent_capabilities = 1;
 	} else {
 		packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons);
 	}
 	capabilities = NULL;
 	if (!peel_iterated_oid(oid, &peeled))
 		packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
+	return;
+}
+
+static int send_ref(const char *refname, const struct object_id *oid,
+		    int flag UNUSED, void *cb_data)
+{
+	write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
 	return 0;
 }
 
@@ -1372,6 +1387,10 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
 			data.no_done = 1;
 		head_ref_namespaced(send_ref, &data);
 		for_each_namespaced_ref(send_ref, &data);
+		if (!data.sent_capabilities) {
+			const char *refname = "capabilities^{}";
+			write_v0_ref(&data, refname, refname, null_oid());
+		}
 		/*
 		 * fflush stdout before calling advertise_shallow_grafts because send_ref
 		 * uses stdio.
@@ -1600,8 +1619,8 @@ static int process_haves(struct upload_pack_data *data, struct oid_array *common
 	for (i = 0; i < data->haves.nr; i++) {
 		const struct object_id *oid = &data->haves.oid[i];
 
-		if (!has_object_file_with_flags(oid,
-						OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT))
+		if (!repo_has_object_file_with_flags(the_repository, oid,
+						     OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT))
 			continue;
 
 		oid_array_append(common, oid);
@@ -1699,7 +1718,7 @@ enum fetch_state {
 	FETCH_DONE,
 };
 
-int upload_pack_v2(struct repository *r, struct packet_reader *request)
+int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request)
 {
 	enum fetch_state state = FETCH_PROCESS_ARGS;
 	struct upload_pack_data data;
@@ -1775,26 +1794,26 @@ int upload_pack_advertise(struct repository *r,
 
 		strbuf_addstr(value, "shallow wait-for-done");
 
-		if (!repo_config_get_bool(the_repository,
+		if (!repo_config_get_bool(r,
 					 "uploadpack.allowfilter",
 					 &allow_filter_value) &&
 		    allow_filter_value)
 			strbuf_addstr(value, " filter");
 
-		if (!repo_config_get_bool(the_repository,
+		if (!repo_config_get_bool(r,
 					 "uploadpack.allowrefinwant",
 					 &allow_ref_in_want) &&
 		    allow_ref_in_want)
 			strbuf_addstr(value, " ref-in-want");
 
 		if (git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) ||
-		    (!repo_config_get_bool(the_repository,
+		    (!repo_config_get_bool(r,
 					   "uploadpack.allowsidebandall",
 					   &allow_sideband_all_value) &&
 		     allow_sideband_all_value))
 			strbuf_addstr(value, " sideband-all");
 
-		if (!repo_config_get_string(the_repository,
+		if (!repo_config_get_string(r,
 					    "uploadpack.blobpackfileuri",
 					    &str) &&
 		    str) {
diff --git a/url.c b/url.c
index e04bd60..2e1a9f6 100644
--- a/url.c
+++ b/url.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "hex.h"
+#include "strbuf.h"
 #include "url.h"
 
 int is_urlschemechar(int first_flag, int ch)
diff --git a/urlmatch.c b/urlmatch.c
index 620a648..eba0bdd 100644
--- a/urlmatch.c
+++ b/urlmatch.c
@@ -1,4 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
+#include "hex.h"
+#include "strbuf.h"
 #include "urlmatch.h"
 
 #define URL_ALPHA "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
diff --git a/usage.c b/usage.c
index 5a7c6c3..46d99f8 100644
--- a/usage.c
+++ b/usage.c
@@ -4,7 +4,9 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "git-compat-util.h"
-#include "cache.h"
+#include "gettext.h"
+#include "trace2.h"
+#include "wrapper.h"
 
 static void vreportf(const char *prefix, const char *err, va_list params)
 {
diff --git a/userdiff.c b/userdiff.c
index 58a3d59..664c7c1 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -1,7 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "alloc.h"
 #include "config.h"
 #include "userdiff.h"
 #include "attr.h"
+#include "strbuf.h"
 
 static struct userdiff_driver *drivers;
 static int ndrivers;
@@ -15,6 +17,7 @@ static int drivers_alloc;
 		.cflags = REG_EXTENDED, \
 	}, \
 	.word_regex = wrx "|[^[:space:]]|[\xc0-\xff][\x80-\xbf]+", \
+	.word_regex_multi_byte = wrx "|[^[:space:]]", \
 }
 #define IPATTERN(lang, rx, wrx) { \
 	.name = lang, \
@@ -24,6 +27,7 @@ static int drivers_alloc;
 		.cflags = REG_EXTENDED | REG_ICASE, \
 	}, \
 	.word_regex = wrx "|[^[:space:]]|[\xc0-\xff][\x80-\xbf]+", \
+	.word_regex_multi_byte = wrx "|[^[:space:]]", \
 }
 
 /*
@@ -292,7 +296,7 @@ PATTERNS("scheme",
 	 /* All other words should be delimited by spaces or parentheses */
 	 "|([^][)(}{[ \t])+"),
 PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
-	 "\\\\[a-zA-Z@]+|\\\\.|[a-zA-Z0-9\x80-\xff]+"),
+	 "\\\\[a-zA-Z@]+|\\\\.|([a-zA-Z0-9]|[^\x01-\x7f])+"),
 { "default", NULL, NULL, -1, { NULL, 0 } },
 };
 #undef PATTERNS
@@ -328,6 +332,25 @@ static int userdiff_find_by_namelen_cb(struct userdiff_driver *driver,
 	return 0;
 }
 
+static int regexec_supports_multi_byte_chars(void)
+{
+	static const char not_space[] = "[^[:space:]]";
+	static const char utf8_multi_byte_char[] = "\xc2\xa3";
+	regex_t re;
+	regmatch_t match;
+	static int result = -1;
+
+	if (result != -1)
+		return result;
+	if (regcomp(&re, not_space, REG_EXTENDED))
+		BUG("invalid regular expression: %s", not_space);
+	result = !regexec(&re, utf8_multi_byte_char, 1, &match, 0) &&
+		match.rm_so == 0 &&
+		match.rm_eo == strlen(utf8_multi_byte_char);
+	regfree(&re);
+	return result;
+}
+
 static struct userdiff_driver *userdiff_find_by_namelen(const char *name, size_t len)
 {
 	struct find_by_namelen_data udcbdata = {
@@ -403,7 +426,13 @@ int userdiff_config(const char *k, const char *v)
 struct userdiff_driver *userdiff_find_by_name(const char *name)
 {
 	int len = strlen(name);
-	return userdiff_find_by_namelen(name, len);
+	struct userdiff_driver *driver = userdiff_find_by_namelen(name, len);
+	if (driver && driver->word_regex_multi_byte) {
+		if (regexec_supports_multi_byte_chars())
+			driver->word_regex = driver->word_regex_multi_byte;
+		driver->word_regex_multi_byte = NULL;
+	}
+	return driver;
 }
 
 struct userdiff_driver *userdiff_find_by_path(struct index_state *istate,
@@ -415,7 +444,7 @@ struct userdiff_driver *userdiff_find_by_path(struct index_state *istate,
 		check = attr_check_initl("diff", NULL);
 	if (!path)
 		return NULL;
-	git_check_attr(istate, NULL, path, check);
+	git_check_attr(istate, path, check);
 
 	if (ATTR_TRUE(check->items[0].value))
 		return &driver_true;
diff --git a/userdiff.h b/userdiff.h
index 24419db..d726804 100644
--- a/userdiff.h
+++ b/userdiff.h
@@ -18,6 +18,7 @@ struct userdiff_driver {
 	int binary;
 	struct userdiff_funcname funcname;
 	const char *word_regex;
+	const char *word_regex_multi_byte;
 	const char *textconv;
 	struct notes_cache *textconv_cache;
 	int textconv_want_cache;
diff --git a/versioncmp.c b/versioncmp.c
index 069ee94..74cc7c4 100644
--- a/versioncmp.c
+++ b/versioncmp.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "string-list.h"
+#include "versioncmp.h"
 
 /*
  * versioncmp(): copied from string/strverscmp.c in glibc commit
@@ -160,15 +161,21 @@ int versioncmp(const char *s1, const char *s2)
 	}
 
 	if (!initialized) {
-		const struct string_list *deprecated_prereleases;
+		const char *const newk = "versionsort.suffix";
+		const char *const oldk = "versionsort.prereleasesuffix";
+		const struct string_list *newl;
+		const struct string_list *oldl;
+		int new = git_config_get_string_multi(newk, &newl);
+		int old = git_config_get_string_multi(oldk, &oldl);
+
+		if (!new && !old)
+			warning("ignoring %s because %s is set", oldk, newk);
+		if (!new)
+			prereleases = newl;
+		else if (!old)
+			prereleases = oldl;
+
 		initialized = 1;
-		prereleases = git_config_get_value_multi("versionsort.suffix");
-		deprecated_prereleases = git_config_get_value_multi("versionsort.prereleasesuffix");
-		if (prereleases) {
-			if (deprecated_prereleases)
-				warning("ignoring versionsort.prereleasesuffix because versionsort.suffix is set");
-		} else
-			prereleases = deprecated_prereleases;
 	}
 	if (prereleases && swap_prereleases(s1, s2, (const char *) p1 - s1 - 1,
 					    &diff))
diff --git a/versioncmp.h b/versioncmp.h
new file mode 100644
index 0000000..879b510
--- /dev/null
+++ b/versioncmp.h
@@ -0,0 +1,6 @@
+#ifndef VERSIONCMP_H
+#define VERSIONCMP_H
+
+int versioncmp(const char *s1, const char *s2);
+
+#endif /* VERSIONCMP_H */
diff --git a/walker.c b/walker.c
index 99d0e0e..24ff7df 100644
--- a/walker.c
+++ b/walker.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
+#include "hex.h"
 #include "walker.h"
 #include "repository.h"
 #include "object-store.h"
@@ -79,7 +81,7 @@ static int process_commit(struct walker *walker, struct commit *commit)
 {
 	struct commit_list *parents;
 
-	if (parse_commit(commit))
+	if (repo_parse_commit(the_repository, commit))
 		return -1;
 
 	while (complete && complete->item->date >= commit->date) {
@@ -93,7 +95,7 @@ static int process_commit(struct walker *walker, struct commit *commit)
 
 	walker_say(walker, "walk %s\n", oid_to_hex(&commit->object.oid));
 
-	if (process(walker, &get_commit_tree(commit)->object))
+	if (process(walker, &repo_get_commit_tree(the_repository, commit)->object))
 		return -1;
 
 	for (parents = commit->parents; parents; parents = parents->next) {
@@ -145,7 +147,7 @@ static int process(struct walker *walker, struct object *obj)
 		return 0;
 	obj->flags |= SEEN;
 
-	if (has_object_file(&obj->oid)) {
+	if (repo_has_object_file(the_repository, &obj->oid)) {
 		/* We already have it, so we should scan it now. */
 		obj->flags |= TO_SCAN;
 	}
diff --git a/wildmatch.c b/wildmatch.c
index 7e5a7ea..8ea2914 100644
--- a/wildmatch.c
+++ b/wildmatch.c
@@ -9,11 +9,15 @@
 **  work differently than '*', and to fix the character-class code.
 */
 
-#include "cache.h"
+#include "git-compat-util.h"
 #include "wildmatch.h"
 
 typedef unsigned char uchar;
 
+/* Internal return values */
+#define WM_ABORT_ALL -1
+#define WM_ABORT_TO_STARSTAR -2
+
 /* What character marks an inverted character class? */
 #define NEGATE_CLASS	'!'
 #define NEGATE_CLASS2	'^'
@@ -83,12 +87,12 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
 			continue;
 		case '*':
 			if (*++p == '*') {
-				const uchar *prev_p = p - 2;
+				const uchar *prev_p = p;
 				while (*++p == '*') {}
 				if (!(flags & WM_PATHNAME))
 					/* without WM_PATHNAME, '*' == '**' */
 					match_slash = 1;
-				else if ((prev_p < pattern || *prev_p == '/') &&
+				else if ((prev_p - pattern < 2 || *(prev_p - 2) == '/') &&
 				    (*p == '\0' || *p == '/' ||
 				     (p[0] == '\\' && p[1] == '/'))) {
 					/*
@@ -114,7 +118,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
 				 * only if there are no more slash characters. */
 				if (!match_slash) {
 					if (strchr((char *)text, '/'))
-						return WM_NOMATCH;
+						return WM_ABORT_TO_STARSTAR;
 				}
 				return WM_MATCH;
 			} else if (!match_slash && *p == '/') {
@@ -125,7 +129,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
 				 */
 				const char *slash = strchr((char*)text, '/');
 				if (!slash)
-					return WM_NOMATCH;
+					return WM_ABORT_ALL;
 				text = (const uchar*)slash;
 				/* the slash is consumed by the top-level for loop */
 				break;
@@ -153,8 +157,12 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
 							break;
 						text++;
 					}
-					if (t_ch != p_ch)
-						return WM_NOMATCH;
+					if (t_ch != p_ch) {
+						if (match_slash)
+							return WM_ABORT_ALL;
+						else
+							return WM_ABORT_TO_STARSTAR;
+					}
 				}
 				if ((matched = dowild(p, text, flags)) != WM_NOMATCH) {
 					if (!match_slash || matched != WM_ABORT_TO_STARSTAR)
@@ -274,5 +282,6 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
 /* Match the "pattern" against the "text" string. */
 int wildmatch(const char *pattern, const char *text, unsigned int flags)
 {
-	return dowild((const uchar*)pattern, (const uchar*)text, flags);
+	int res = dowild((const uchar*)pattern, (const uchar*)text, flags);
+	return res == WM_MATCH ? WM_MATCH : WM_NOMATCH;
 }
diff --git a/wildmatch.h b/wildmatch.h
index 5993696..0c890cb 100644
--- a/wildmatch.h
+++ b/wildmatch.h
@@ -6,8 +6,6 @@
 
 #define WM_NOMATCH 1
 #define WM_MATCH 0
-#define WM_ABORT_ALL -1
-#define WM_ABORT_TO_STARSTAR -2
 
 int wildmatch(const char *pattern, const char *text, unsigned int flags);
 #endif
diff --git a/worktree.c b/worktree.c
index aa43c64..b5ee71c 100644
--- a/worktree.c
+++ b/worktree.c
@@ -1,11 +1,17 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
+#include "environment.h"
+#include "gettext.h"
 #include "repository.h"
 #include "refs.h"
+#include "setup.h"
 #include "strbuf.h"
 #include "worktree.h"
 #include "dir.h"
 #include "wt-status.h"
 #include "config.h"
+#include "wrapper.h"
 
 void free_worktrees(struct worktree **worktrees)
 {
@@ -403,44 +409,43 @@ int is_worktree_being_bisected(const struct worktree *wt,
  * bisect). New commands that do similar things should update this
  * function as well.
  */
+int is_shared_symref(const struct worktree *wt, const char *symref,
+		     const char *target)
+{
+	const char *symref_target;
+	struct ref_store *refs;
+	int flags;
+
+	if (wt->is_bare)
+		return 0;
+
+	if (wt->is_detached && !strcmp(symref, "HEAD")) {
+		if (is_worktree_being_rebased(wt, target))
+			return 1;
+		if (is_worktree_being_bisected(wt, target))
+			return 1;
+	}
+
+	refs = get_worktree_ref_store(wt);
+	symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
+						NULL, &flags);
+	if ((flags & REF_ISSYMREF) &&
+	    symref_target && !strcmp(symref_target, target))
+		return 1;
+
+	return 0;
+}
+
 const struct worktree *find_shared_symref(struct worktree **worktrees,
 					  const char *symref,
 					  const char *target)
 {
-	const struct worktree *existing = NULL;
-	int i = 0;
 
-	for (i = 0; worktrees[i]; i++) {
-		struct worktree *wt = worktrees[i];
-		const char *symref_target;
-		struct ref_store *refs;
-		int flags;
+	for (int i = 0; worktrees[i]; i++)
+		if (is_shared_symref(worktrees[i], symref, target))
+			return worktrees[i];
 
-		if (wt->is_bare)
-			continue;
-
-		if (wt->is_detached && !strcmp(symref, "HEAD")) {
-			if (is_worktree_being_rebased(wt, target)) {
-				existing = wt;
-				break;
-			}
-			if (is_worktree_being_bisected(wt, target)) {
-				existing = wt;
-				break;
-			}
-		}
-
-		refs = get_worktree_ref_store(wt);
-		symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
-							NULL, &flags);
-		if ((flags & REF_ISSYMREF) &&
-		    symref_target && !strcmp(symref_target, target)) {
-			existing = wt;
-			break;
-		}
-	}
-
-	return existing;
+	return NULL;
 }
 
 int submodule_uses_worktrees(const char *path)
diff --git a/worktree.h b/worktree.h
index 9dcea6f..ce45b66 100644
--- a/worktree.h
+++ b/worktree.h
@@ -1,7 +1,6 @@
 #ifndef WORKTREE_H
 #define WORKTREE_H
 
-#include "cache.h"
 #include "refs.h"
 
 struct strbuf;
@@ -150,6 +149,12 @@ const struct worktree *find_shared_symref(struct worktree **worktrees,
 					  const char *target);
 
 /*
+ * Returns true if a symref points to a ref in a worktree.
+ */
+int is_shared_symref(const struct worktree *wt,
+		     const char *symref, const char *target);
+
+/*
  * Similar to head_ref() for all HEADs _except_ one from the current
  * worktree, which is covered by head_ref().
  */
diff --git a/wrapper.c b/wrapper.c
index 299d648..67f5f5d 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -1,8 +1,15 @@
 /*
  * Various trivial helper wrappers around standard functions
  */
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
 #include "config.h"
+#include "gettext.h"
+#include "object.h"
+#include "repository.h"
+#include "strbuf.h"
+#include "trace2.h"
+#include "wrapper.h"
 
 static intmax_t count_fsync_writeout_only;
 static intmax_t count_fsync_hardware_flush;
diff --git a/wrapper.h b/wrapper.h
new file mode 100644
index 0000000..f0c7d06
--- /dev/null
+++ b/wrapper.h
@@ -0,0 +1,36 @@
+#ifndef WRAPPER_H
+#define WRAPPER_H
+
+/* set default permissions by passing mode arguments to open(2) */
+int git_mkstemps_mode(char *pattern, int suffix_len, int mode);
+int git_mkstemp_mode(char *pattern, int mode);
+
+ssize_t read_in_full(int fd, void *buf, size_t count);
+ssize_t write_in_full(int fd, const void *buf, size_t count);
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
+
+static inline ssize_t write_str_in_full(int fd, const char *str)
+{
+	return write_in_full(fd, str, strlen(str));
+}
+
+/**
+ * Open (and truncate) the file at path, write the contents of buf to it,
+ * and close it. Dies if any errors are encountered.
+ */
+void write_file_buf(const char *path, const char *buf, size_t len);
+
+/**
+ * Like write_file_buf(), but format the contents into a buffer first.
+ * Additionally, write_file() will append a newline if one is not already
+ * present, making it convenient to write text files:
+ *
+ *   write_file(path, "counter: %d", ctr);
+ */
+__attribute__((format (printf, 2, 3)))
+void write_file(const char *path, const char *fmt, ...);
+
+/* Return 1 if the file is empty or does not exists, 0 otherwise. */
+int is_empty_or_missing_file(const char *filename);
+
+#endif /* WRAPPER_H */
diff --git a/write-or-die.c b/write-or-die.c
index aaa0318..cc9e078 100644
--- a/write-or-die.c
+++ b/write-or-die.c
@@ -1,6 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
 #include "run-command.h"
+#include "wrapper.h"
+#include "write-or-die.h"
 
 /*
  * Some cases use stdio, but want to flush after the write
diff --git a/write-or-die.h b/write-or-die.h
new file mode 100644
index 0000000..65a5c42
--- /dev/null
+++ b/write-or-die.h
@@ -0,0 +1,78 @@
+#ifndef WRITE_OR_DIE_H
+#define WRITE_OR_DIE_H
+
+void maybe_flush_or_die(FILE *, const char *);
+__attribute__((format (printf, 2, 3)))
+void fprintf_or_die(FILE *, const char *fmt, ...);
+void fwrite_or_die(FILE *f, const void *buf, size_t count);
+void fflush_or_die(FILE *f);
+void write_or_die(int fd, const void *buf, size_t count);
+
+/*
+ * These values are used to help identify parts of a repository to fsync.
+ * FSYNC_COMPONENT_NONE identifies data that will not be a persistent part of the
+ * repository and so shouldn't be fsynced.
+ */
+enum fsync_component {
+	FSYNC_COMPONENT_NONE,
+	FSYNC_COMPONENT_LOOSE_OBJECT		= 1 << 0,
+	FSYNC_COMPONENT_PACK			= 1 << 1,
+	FSYNC_COMPONENT_PACK_METADATA		= 1 << 2,
+	FSYNC_COMPONENT_COMMIT_GRAPH		= 1 << 3,
+	FSYNC_COMPONENT_INDEX			= 1 << 4,
+	FSYNC_COMPONENT_REFERENCE		= 1 << 5,
+};
+
+#define FSYNC_COMPONENTS_OBJECTS (FSYNC_COMPONENT_LOOSE_OBJECT | \
+				  FSYNC_COMPONENT_PACK)
+
+#define FSYNC_COMPONENTS_DERIVED_METADATA (FSYNC_COMPONENT_PACK_METADATA | \
+					   FSYNC_COMPONENT_COMMIT_GRAPH)
+
+#define FSYNC_COMPONENTS_DEFAULT ((FSYNC_COMPONENTS_OBJECTS | \
+				   FSYNC_COMPONENTS_DERIVED_METADATA) & \
+				  ~FSYNC_COMPONENT_LOOSE_OBJECT)
+
+#define FSYNC_COMPONENTS_COMMITTED (FSYNC_COMPONENTS_OBJECTS | \
+				    FSYNC_COMPONENT_REFERENCE)
+
+#define FSYNC_COMPONENTS_ADDED (FSYNC_COMPONENTS_COMMITTED | \
+				FSYNC_COMPONENT_INDEX)
+
+#define FSYNC_COMPONENTS_ALL (FSYNC_COMPONENT_LOOSE_OBJECT | \
+			      FSYNC_COMPONENT_PACK | \
+			      FSYNC_COMPONENT_PACK_METADATA | \
+			      FSYNC_COMPONENT_COMMIT_GRAPH | \
+			      FSYNC_COMPONENT_INDEX | \
+			      FSYNC_COMPONENT_REFERENCE)
+
+#ifndef FSYNC_COMPONENTS_PLATFORM_DEFAULT
+#define FSYNC_COMPONENTS_PLATFORM_DEFAULT FSYNC_COMPONENTS_DEFAULT
+#endif
+
+/* IO helper functions */
+void fsync_or_die(int fd, const char *);
+int fsync_component(enum fsync_component component, int fd);
+void fsync_component_or_die(enum fsync_component component, int fd, const char *msg);
+
+/*
+ * A bitmask indicating which components of the repo should be fsynced.
+ */
+extern enum fsync_component fsync_components;
+extern int fsync_object_files;
+extern int use_fsync;
+
+enum fsync_method {
+	FSYNC_METHOD_FSYNC,
+	FSYNC_METHOD_WRITEOUT_ONLY,
+	FSYNC_METHOD_BATCH,
+};
+
+extern enum fsync_method fsync_method;
+
+static inline int batch_fsync_enabled(enum fsync_component component)
+{
+	return (fsync_components & component) && (fsync_method == FSYNC_METHOD_BATCH);
+}
+
+#endif /* WRITE_OR_DIE_H */
diff --git a/ws.c b/ws.c
index da3d0e2..9456e2f 100644
--- a/ws.c
+++ b/ws.c
@@ -3,8 +3,12 @@
  *
  * Copyright (c) 2007 Junio C Hamano
  */
-#include "cache.h"
+#include "git-compat-util.h"
 #include "attr.h"
+#include "strbuf.h"
+#include "ws.h"
+
+unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 
 static struct whitespace_rule {
 	const char *rule_name;
@@ -79,7 +83,7 @@ unsigned whitespace_rule(struct index_state *istate, const char *pathname)
 	if (!attr_whitespace_rule)
 		attr_whitespace_rule = attr_check_initl("whitespace", NULL);
 
-	git_check_attr(istate, NULL, pathname, attr_whitespace_rule);
+	git_check_attr(istate, pathname, attr_whitespace_rule);
 	value = attr_whitespace_rule->items[0].value;
 	if (ATTR_TRUE(value)) {
 		/* true (whitespace) */
diff --git a/ws.h b/ws.h
new file mode 100644
index 0000000..5ba676c
--- /dev/null
+++ b/ws.h
@@ -0,0 +1,33 @@
+#ifndef WS_H
+#define WS_H
+
+struct index_state;
+struct strbuf;
+
+/*
+ * whitespace rules.
+ * used by both diff and apply
+ * last two digits are tab width
+ */
+#define WS_BLANK_AT_EOL         0100
+#define WS_SPACE_BEFORE_TAB     0200
+#define WS_INDENT_WITH_NON_TAB  0400
+#define WS_CR_AT_EOL           01000
+#define WS_BLANK_AT_EOF        02000
+#define WS_TAB_IN_INDENT       04000
+#define WS_TRAILING_SPACE      (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
+#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
+#define WS_TAB_WIDTH_MASK        077
+/* All WS_* -- when extended, adapt diff.c emit_symbol */
+#define WS_RULE_MASK           07777
+extern unsigned whitespace_rule_cfg;
+unsigned whitespace_rule(struct index_state *, const char *);
+unsigned parse_whitespace_rule(const char *);
+unsigned ws_check(const char *line, int len, unsigned ws_rule);
+void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
+char *whitespace_error_string(unsigned ws);
+void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
+int ws_blank_line(const char *line, int len);
+#define ws_tab_width(rule)     ((rule) & WS_TAB_WIDTH_MASK)
+
+#endif /* WS_H */
diff --git a/wt-status.c b/wt-status.c
index 3162241..068b76e 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1,9 +1,14 @@
 #include "cache.h"
+#include "advice.h"
 #include "wt-status.h"
 #include "object.h"
 #include "dir.h"
 #include "commit.h"
 #include "diff.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
 #include "revision.h"
 #include "diffcore.h"
 #include "quote.h"
@@ -13,7 +18,11 @@
 #include "refs.h"
 #include "submodule.h"
 #include "column.h"
+#include "setup.h"
 #include "strbuf.h"
+#include "trace.h"
+#include "trace2.h"
+#include "tree.h"
 #include "utf8.h"
 #include "worktree.h"
 #include "lockfile.h"
@@ -1337,7 +1346,7 @@ static void abbrev_oid_in_line(struct strbuf *line)
 		 * it after abbreviation.
 		 */
 		strbuf_trim(split[1]);
-		if (!get_oid(split[1]->buf, &oid)) {
+		if (!repo_get_oid(the_repository, split[1]->buf, &oid)) {
 			strbuf_reset(split[1]);
 			strbuf_add_unique_abbrev(split[1], &oid,
 						 DEFAULT_ABBREV);
@@ -1503,8 +1512,8 @@ static void show_cherry_pick_in_progress(struct wt_status *s,
 	else
 		status_printf_ln(s, color,
 			_("You are currently cherry-picking commit %s."),
-			find_unique_abbrev(&s->state.cherry_pick_head_oid,
-					   DEFAULT_ABBREV));
+			repo_find_unique_abbrev(the_repository, &s->state.cherry_pick_head_oid,
+						DEFAULT_ABBREV));
 
 	if (s->hints) {
 		if (has_unmerged(s))
@@ -1533,8 +1542,8 @@ static void show_revert_in_progress(struct wt_status *s,
 	else
 		status_printf_ln(s, color,
 			_("You are currently reverting commit %s."),
-			find_unique_abbrev(&s->state.revert_head_oid,
-					   DEFAULT_ABBREV));
+			repo_find_unique_abbrev(the_repository, &s->state.revert_head_oid,
+						DEFAULT_ABBREV));
 	if (s->hints) {
 		if (has_unmerged(s))
 			status_printf_ln(s, color,
@@ -1664,7 +1673,8 @@ static void wt_status_get_detached_from(struct repository *r,
 		return;
 	}
 
-	if (dwim_ref(cb.buf.buf, cb.buf.len, &oid, &ref, 1) == 1 &&
+	if (repo_dwim_ref(r, cb.buf.buf, cb.buf.len, &oid, &ref,
+			  1) == 1 &&
 	    /* oid is a commit? match without further lookup */
 	    (oideq(&cb.noid, &oid) ||
 	     /* perhaps oid is a tag, try to dereference to a commit */
@@ -1676,9 +1686,9 @@ static void wt_status_get_detached_from(struct repository *r,
 		state->detached_from = xstrdup(from);
 	} else
 		state->detached_from =
-			xstrdup(find_unique_abbrev(&cb.noid, DEFAULT_ABBREV));
+			xstrdup(repo_find_unique_abbrev(r, &cb.noid, DEFAULT_ABBREV));
 	oidcpy(&state->detached_oid, &cb.noid);
-	state->detached_at = !get_oid("HEAD", &oid) &&
+	state->detached_at = !repo_get_oid(r, "HEAD", &oid) &&
 			     oideq(&oid, &state->detached_oid);
 
 	free(ref);
@@ -1769,13 +1779,13 @@ void wt_status_get_state(struct repository *r,
 	} else if (wt_status_check_rebase(NULL, state)) {
 		;		/* all set */
 	} else if (refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
-		   !get_oid("CHERRY_PICK_HEAD", &oid)) {
+		   !repo_get_oid(r, "CHERRY_PICK_HEAD", &oid)) {
 		state->cherry_pick_in_progress = 1;
 		oidcpy(&state->cherry_pick_head_oid, &oid);
 	}
 	wt_status_check_bisect(NULL, state);
 	if (refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD") &&
-	    !get_oid("REVERT_HEAD", &oid)) {
+	    !repo_get_oid(r, "REVERT_HEAD", &oid)) {
 		state->revert_in_progress = 1;
 		oidcpy(&state->revert_head_oid, &oid);
 	}
diff --git a/xdiff-interface.c b/xdiff-interface.c
index e87950d..0460e03 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -1,5 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
 #include "config.h"
+#include "hex.h"
 #include "object-store.h"
 #include "xdiff-interface.h"
 #include "xdiff/xtypes.h"
@@ -183,7 +184,7 @@ void read_mmblob(mmfile_t *ptr, const struct object_id *oid)
 		return;
 	}
 
-	ptr->ptr = read_object_file(oid, &type, &size);
+	ptr->ptr = repo_read_object_file(the_repository, oid, &type, &size);
 	if (!ptr->ptr || type != OBJ_BLOB)
 		die("unable to read blob object %s", oid_to_hex(oid));
 	ptr->size = size;
diff --git a/xdiff-interface.h b/xdiff-interface.h
index 4301a7e..733c364 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -1,7 +1,7 @@
 #ifndef XDIFF_INTERFACE_H
 #define XDIFF_INTERFACE_H
 
-#include "cache.h"
+#include "hash-ll.h"
 #include "xdiff/xdiff.h"
 
 /*