Merge branch 'en/ort-rename-another-fix'

Yet another corner case fix around renames in the "ort" merge
strategy.

* en/ort-rename-another-fix:
  merge-ort: fix failing merges in special corner case
  merge-ort: remove debugging crud
  t6429: update comment to mention correct tool
diff --git a/.gitattributes b/.gitattributes
index 3258314..6e66623 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,4 +1,4 @@
-* whitespace=!indent,trail,space
+* whitespace=trail,space
 *.[ch] whitespace=indent,trail,space diff=cpp
 *.sh whitespace=indent,trail,space text eol=lf
 *.perl text eol=lf diff=perl
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index aa6bce6..816d5a3 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -123,7 +123,7 @@
     - name: zip up tracked files
       run: git archive -o artifacts/tracked.tar.gz HEAD
     - name: upload tracked files and build artifacts
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@v5
       with:
         name: windows-artifacts
         path: artifacts
@@ -140,7 +140,7 @@
       cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
     steps:
     - name: download tracked files and build artifacts
-      uses: actions/download-artifact@v5
+      uses: actions/download-artifact@v6
       with:
         name: windows-artifacts
         path: ${{github.workspace}}
@@ -157,7 +157,7 @@
       run: ci/print-test-failures.sh
     - name: Upload failed tests' directories
       if: failure() && env.FAILED_TEST_ARTIFACTS != ''
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@v5
       with:
         name: failed-tests-windows-${{ matrix.nr }}
         path: ${{env.FAILED_TEST_ARTIFACTS}}
@@ -208,7 +208,7 @@
     - name: zip up tracked files
       run: git archive -o artifacts/tracked.tar.gz HEAD
     - name: upload tracked files and build artifacts
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@v5
       with:
         name: vs-artifacts
         path: artifacts
@@ -226,7 +226,7 @@
     steps:
     - uses: git-for-windows/setup-git-for-windows-sdk@v1
     - name: download tracked files and build artifacts
-      uses: actions/download-artifact@v5
+      uses: actions/download-artifact@v6
       with:
         name: vs-artifacts
         path: ${{github.workspace}}
@@ -244,7 +244,7 @@
       run: ci/print-test-failures.sh
     - name: Upload failed tests' directories
       if: failure() && env.FAILED_TEST_ARTIFACTS != ''
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@v5
       with:
         name: failed-tests-windows-vs-${{ matrix.nr }}
         path: ${{env.FAILED_TEST_ARTIFACTS}}
@@ -270,7 +270,7 @@
       shell: pwsh
       run: meson compile -C build
     - name: Upload build artifacts
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@v5
       with:
         name: windows-meson-artifacts
         path: build
@@ -292,7 +292,7 @@
       shell: pwsh
       run: pip install meson ninja
     - name: Download build artifacts
-      uses: actions/download-artifact@v5
+      uses: actions/download-artifact@v6
       with:
         name: windows-meson-artifacts
         path: build
@@ -313,16 +313,16 @@
         vector:
           - jobname: osx-clang
             cc: clang
-            pool: macos-13
+            pool: macos-14
           - jobname: osx-reftable
             cc: clang
-            pool: macos-13
+            pool: macos-14
           - jobname: osx-gcc
             cc: gcc-13
-            pool: macos-13
+            pool: macos-14
           - jobname: osx-meson
             cc: clang
-            pool: macos-13
+            pool: macos-14
     env:
       CC: ${{matrix.vector.cc}}
       CC_PACKAGE: ${{matrix.vector.cc_package}}
@@ -339,7 +339,7 @@
       run: ci/print-test-failures.sh
     - name: Upload failed tests' directories
       if: failure() && env.FAILED_TEST_ARTIFACTS != ''
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@v5
       with:
         name: failed-tests-${{matrix.vector.jobname}}
         path: ${{env.FAILED_TEST_ARTIFACTS}}
@@ -379,6 +379,8 @@
         - jobname: linux-breaking-changes
           cc: gcc
           image: ubuntu:rolling
+        - jobname: fedora-breaking-changes-meson
+          image: fedora:latest
         - jobname: linux-leaks
           image: ubuntu:rolling
           cc: gcc
@@ -396,8 +398,6 @@
         # Supported until 2025-04-02.
         - jobname: linux32
           image: i386/ubuntu:focal
-        - jobname: pedantic
-          image: fedora:latest
         # A RHEL 8 compatible distro.  Supported until 2029-05-31.
         - jobname: almalinux-8
           image: almalinux:8
@@ -439,7 +439,7 @@
       run: sudo --preserve-env --set-home --user=builder ci/print-test-failures.sh
     - name: Upload failed tests' directories
       if: failure() && env.FAILED_TEST_ARTIFACTS != ''
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@v5
       with:
         name: failed-tests-${{matrix.vector.jobname}}
         path: ${{env.FAILED_TEST_ARTIFACTS}}
@@ -458,6 +458,21 @@
     - run: ci/install-dependencies.sh
     - run: ci/run-static-analysis.sh
     - run: ci/check-directional-formatting.bash
+  rust-analysis:
+    needs: ci-config
+    if: needs.ci-config.outputs.enabled == 'yes'
+    env:
+      jobname: RustAnalysis
+      CI_JOB_IMAGE: ubuntu:rolling
+    runs-on: ubuntu-latest
+    container: ubuntu:rolling
+    concurrency:
+      group: rust-analysis-${{ github.ref }}
+      cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
+    steps:
+    - uses: actions/checkout@v4
+    - run: ci/install-dependencies.sh
+    - run: ci/run-rust-checks.sh
   sparse:
     needs: ci-config
     if: needs.ci-config.outputs.enabled == 'yes'
diff --git a/.gitignore b/.gitignore
index 04c4444..78a45cb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
 /fuzz_corpora
+/target/
+/Cargo.lock
 /GIT-BUILD-DIR
 /GIT-BUILD-OPTIONS
 /GIT-CFLAGS
@@ -87,6 +89,7 @@
 /git-init-db
 /git-interpret-trailers
 /git-instaweb
+/git-last-modified
 /git-log
 /git-ls-files
 /git-ls-remote
@@ -139,6 +142,7 @@
 /git-repack
 /git-replace
 /git-replay
+/git-repo
 /git-request-pull
 /git-rerere
 /git-reset
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index cf122e7..b419a84 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -45,6 +45,8 @@
       - jobname: linux-breaking-changes
         image: ubuntu:20.04
         CC: gcc
+      - jobname: fedora-breaking-changes-meson
+        image: fedora:latest
       - jobname: linux-TEST-vars
         image: ubuntu:20.04
         CC: gcc
@@ -58,8 +60,6 @@
       - jobname: linux-asan-ubsan
         image: ubuntu:rolling
         CC: clang
-      - jobname: pedantic
-        image: fedora:latest
       - jobname: linux-musl-meson
         image: alpine:latest
       - jobname: linux32
@@ -70,6 +70,8 @@
   artifacts:
     paths:
       - t/failed-test-artifacts
+    reports:
+      junit: build/meson-logs/testlog.junit.xml
     when: on_failure
 
 test:osx:
@@ -110,8 +112,16 @@
   artifacts:
     paths:
       - t/failed-test-artifacts
+    reports:
+      junit: build/meson-logs/testlog.junit.xml
     when: on_failure
 
+.windows_before_script: &windows_before_script
+  # Disabling realtime monitoring fails on some of the runners, but it
+  # significantly speeds up test execution in the case where it works. We thus
+  # try our luck, but ignore any failures.
+  - Set-MpPreference -DisableRealtimeMonitoring $true; $true
+
 build:mingw64:
   stage: build
   tags:
@@ -119,7 +129,7 @@
   variables:
     NO_PERL: 1
   before_script:
-    - Set-MpPreference -DisableRealtimeMonitoring $true
+    - *windows_before_script
     - ./ci/install-sdk.ps1 -directory "git-sdk"
   script:
     - git-sdk/usr/bin/bash.exe -l -c 'ci/make-test-artifacts.sh artifacts'
@@ -136,7 +146,7 @@
     - job: "build:mingw64"
       artifacts: true
   before_script:
-    - Set-MpPreference -DisableRealtimeMonitoring $true
+    - *windows_before_script
     - git-sdk/usr/bin/bash.exe -l -c 'tar xf artifacts/artifacts.tar.gz'
     - New-Item -Path .git/info -ItemType Directory
     - New-Item .git/info/exclude -ItemType File -Value "/git-sdk"
@@ -150,18 +160,10 @@
   tags:
     - saas-windows-medium-amd64
   before_script:
-    - Set-MpPreference -DisableRealtimeMonitoring $true
-    - choco install -y git meson ninja openssl
+    - *windows_before_script
+    - choco install -y git meson ninja rust-ms
     - Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
     - refreshenv
-    # The certificate store for Python on Windows is broken and fails to fetch
-    # certificates, see https://bugs.python.org/issue36011. This seems to
-    # mostly be an issue with how the GitLab image is set up as it is a
-    # non-issue on GitHub Actions. Work around the issue by importing
-    # cetrificates manually.
-    - Invoke-WebRequest https://curl.haxx.se/ca/cacert.pem -OutFile cacert.pem
-    - openssl pkcs12 -export -nokeys -in cacert.pem -out certs.pfx -passout "pass:"
-    - Import-PfxCertificate -CertStoreLocation Cert:\LocalMachine\Root -FilePath certs.pfx
 
 build:msvc-meson:
   extends: .msvc-meson
@@ -183,6 +185,9 @@
   script:
     - meson test -C build --no-rebuild --print-errorlogs --slice $Env:CI_NODE_INDEX/$Env:CI_NODE_TOTAL
   parallel: 10
+  artifacts:
+    reports:
+      junit: build/meson-logs/testlog.junit.xml
 
 test:fuzz-smoke-tests:
   image: ubuntu:latest
@@ -207,6 +212,17 @@
     - ./ci/run-static-analysis.sh
     - ./ci/check-directional-formatting.bash
 
+rust-analysis:
+  image: ubuntu:rolling
+  stage: analyze
+  needs: [ ]
+  variables:
+    jobname: RustAnalysis
+  before_script:
+    - ./ci/install-dependencies.sh
+  script:
+    - ./ci/run-rust-checks.sh
+
 check-whitespace:
   image: ubuntu:latest
   stage: analyze
diff --git a/.mailmap b/.mailmap
index 96c2740..7b31981 100644
--- a/.mailmap
+++ b/.mailmap
@@ -81,6 +81,8 @@
 Frédéric Heitzmann <frederic.heitzmann@gmail.com>
 Garry Dolley <gdolley@ucla.edu> <gdolley@arpnetworks.com>
 Glen Choo <glencbz@gmail.com> <chooglen@google.com>
+Greg Hurrell <greg@hurrell.net> <greg.hurrell@datadoghq.com>
+Greg Hurrell <greg@hurrell.net> <win@wincent.com>
 Greg Price <price@mit.edu> <price@MIT.EDU>
 Greg Price <price@mit.edu> <price@ksplice.com>
 Heiko Voigt <hvoigt@hvoigt.net> <git-list@hvoigt.net>
@@ -124,6 +126,7 @@
 Jon Seymour <jon.seymour@gmail.com> <jon@blackcubes.dyndns.org>
 Jonathan Nieder <jrnieder@gmail.com> <jrnieder@uchicago.edu>
 Jonathan del Strother <jon.delStrother@bestbefore.tv> <maillist@steelskies.com>
+Jonathan Tan <jonathantanmy@fastmail.com> <jonathantanmy@google.com>
 Josh Triplett <josh@joshtriplett.org> <josh@freedesktop.org>
 Josh Triplett <josh@joshtriplett.org> <josht@us.ibm.com>
 Julian Phillips <julian@quantumfyre.co.uk> <jp3@quantumfyre.co.uk>
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..2f51bf5
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "gitcore"
+version = "0.1.0"
+edition = "2018"
+rust-version = "1.49.0"
+
+[lib]
+crate-type = ["staticlib"]
+
+[dependencies]
diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc
index c498516..f814450 100644
--- a/Documentation/BreakingChanges.adoc
+++ b/Documentation/BreakingChanges.adoc
@@ -165,6 +165,57 @@
 "reftable" format. Most importantly, alternative implementations of Git like
 JGit, libgit2 and Gitoxide need to support it.
 
+* In new repositories, the default branch name will be `main`. We have been
+  warning that the default name will change since 675704c74dd (init:
+  provide useful advice about init.defaultBranch, 2020-12-11).  The new name
+  matches the default branch name used in new repositories by many of the
+  big Git forges.
+
+* Git will require Rust as a mandatory part of the build process. While Git
+  already started to adopt Rust in Git 2.49, all parts written in Rust are
+  optional for the time being. This includes:
++
+  ** The Rust wrapper around libgit.a that is part of "contrib/" and which has
+     been introduced in Git 2.49.
+  ** Subsystems that have an alternative implementation in Rust to test
+     interoperability between our C and Rust codebase.
+  ** Newly written features that are not mission critical for a fully functional
+     Git client.
++
+These changes are meant as test balloons to allow distributors of Git to prepare
+for Rust becoming a mandatory part of the build process. There will be multiple
+milestones for the introduction of Rust:
++
+--
+1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and
+   disabled in our Makefile so that the project can sort out the initial
+   infrastructure.
+2. In Git 2.53, both build systems will default-enable support for Rust.
+   Consequently, builds will break by default if Rust is not available on the
+   build host. The use of Rust can still be explicitly disabled via build
+   flags.
+3. In Git 3.0, the build options will be removed and support for Rust is
+   mandatory.
+--
++
+You can explicitly ask both Meson and our Makefile-based system to enable Rust
+by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,
+respectively.
++
+The Git project will declare the last version before Git 3.0 to be a long-term
+support release. This long-term release will receive important bug fixes for at
+least four release cycles and security fixes for six release cycles. The Git
+project will hand over maintainership of the long-term release to distributors
+in case they need to extend the life of that long-term release even further.
+Details of how this long-term release will be handed over to the community will
+be discussed once the Git project decides to stop officially supporting it.
++
+We will evaluate the impact on downstream distributions before making Rust
+mandatory in Git 3.0. If we see that the impact on downstream distributions
+would be significant, we may decide to defer this change to a subsequent minor
+release. This evaluation will also take into account our own experience with
+how painful it is to keep Rust an optional component.
+
 === Removals
 
 * Support for grafting commits has long been superseded by git-replace(1).
@@ -239,6 +290,31 @@
 +
 The command will be removed.
 
+* Support for `core.commentString=auto` has been deprecated and will
+  be removed in Git 3.0.
++
+cf. <xmqqa59i45wc.fsf@gitster.g>
+
+* Support for `core.preferSymlinkRefs=true` has been deprecated and will be
+  removed in Git 3.0. Writing symbolic refs as symbolic links will be phased
+  out in favor of using plain files using the textual representation of
+  symbolic refs.
++
+Symbolic references were initially always stored as a symbolic link. This was
+changed in 9b143c6e15 (Teach update-ref about a symbolic ref stored in a
+textfile., 2005-09-25), where a new textual symref format was introduced to
+store those symbolic refs in a plain file. In 9f0bb90d16
+(core.prefersymlinkrefs: use symlinks for .git/HEAD, 2006-05-02), the Git
+project switched the default to use the textual symrefs in favor of symbolic
+links.
++
+The migration away from symbolic links has happened almost 20 years ago by now,
+and there is no known reason why one should prefer them nowadays. Furthermore,
+symbolic links are not supported on some platforms.
++
+Note that only the writing side for such symbolic links is deprecated. Reading
+such symbolic links is still supported for now.
+
 == Superseded features that will not be deprecated
 
 Some features have gained newer replacements that aim to improve the design in
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index 224f097..df72fe0 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -650,6 +650,12 @@
    cases. However, it is recommended to find a more descriptive name wherever
    possible to improve the readability and maintainability of the code.
 
+ - Bit fields should be defined without a space around the colon. E.g.
+
+   unsigned my_field:1;
+   unsigned other_field:1;
+   unsigned field_with_longer_name:1;
+
 For Perl programs:
 
  - Most of the C guidelines above apply.
diff --git a/Documentation/Makefile b/Documentation/Makefile
index df2ce18..04e9e10 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -34,6 +34,7 @@
 MAN5_TXT += gitformat-chunk.adoc
 MAN5_TXT += gitformat-commit-graph.adoc
 MAN5_TXT += gitformat-index.adoc
+MAN5_TXT += gitformat-loose.adoc
 MAN5_TXT += gitformat-pack.adoc
 MAN5_TXT += gitformat-signature.adoc
 MAN5_TXT += githooks.adoc
@@ -119,18 +120,27 @@
 TECH_DOCS += technical/bitmap-format
 TECH_DOCS += technical/build-systems
 TECH_DOCS += technical/bundle-uri
+TECH_DOCS += technical/commit-graph
+TECH_DOCS += technical/directory-rename-detection
 TECH_DOCS += technical/hash-function-transition
+TECH_DOCS += technical/large-object-promisors
 TECH_DOCS += technical/long-running-process-protocol
 TECH_DOCS += technical/multi-pack-index
+TECH_DOCS += technical/packfile-uri
 TECH_DOCS += technical/pack-heuristics
 TECH_DOCS += technical/parallel-checkout
 TECH_DOCS += technical/partial-clone
 TECH_DOCS += technical/platform-support
 TECH_DOCS += technical/racy-git
 TECH_DOCS += technical/reftable
+TECH_DOCS += technical/remembering-renames
+TECH_DOCS += technical/repository-version
+TECH_DOCS += technical/rerere
 TECH_DOCS += technical/scalar
 TECH_DOCS += technical/send-pack-pipeline
 TECH_DOCS += technical/shallow
+TECH_DOCS += technical/sparse-checkout
+TECH_DOCS += technical/sparse-index
 TECH_DOCS += technical/trivial-merge
 TECH_DOCS += technical/unit-tests
 SP_ARTICLES += $(TECH_DOCS)
@@ -497,9 +507,26 @@
 	$(call mkdir_p_parent_template)
 	$(QUIET_GEN)$(PERL_PATH) lint-fsck-msgids.perl \
 		../fsck.h fsck-msgids.adoc $@
-
 lint-docs-fsck-msgids: $(LINT_DOCS_FSCK_MSGIDS)
 
+## Lint: delimited sections
+LINT_DOCS_DELIMITED_SECTIONS = $(patsubst %.adoc,.build/lint-docs/delimited-sections/%.ok,$(MAN_TXT))
+$(LINT_DOCS_DELIMITED_SECTIONS): lint-delimited-sections.perl
+$(LINT_DOCS_DELIMITED_SECTIONS): .build/lint-docs/delimited-sections/%.ok: %.adoc
+	$(call mkdir_p_parent_template)
+	$(QUIET_LINT_DELIMSEC)$(PERL_PATH) lint-delimited-sections.perl $< >$@
+.PHONY: lint-docs-delimited-sections
+lint-docs-delimited-sections: $(LINT_DOCS_DELIMITED_SECTIONS)
+
+## Lint: Documentation style
+LINT_DOCS_DOC_STYLE = $(patsubst %.adoc,.build/lint-docs/doc-style/%.ok,$(DOC_DEP_TXT))
+$(LINT_DOCS_DOC_STYLE): lint-documentation-style.perl
+$(LINT_DOCS_DOC_STYLE): .build/lint-docs/doc-style/%.ok: %.adoc
+	$(call mkdir_p_parent_template)
+	$(QUIET_LINT_DOCSTYLE)$(PERL_PATH) lint-documentation-style.perl $< >$@
+.PHONY: lint-docs-doc-style
+lint-docs-doc-style: $(LINT_DOCS_DOC_STYLE)
+
 lint-docs-manpages:
 	$(QUIET_GEN)./lint-manpages.sh
 
@@ -528,6 +555,8 @@
 lint-docs: lint-docs-gitlink
 lint-docs: lint-docs-man-end-blurb
 lint-docs: lint-docs-man-section-order
+lint-docs: lint-docs-delimited-sections
+lint-docs: lint-docs-doc-style
 lint-docs: lint-docs-manpages
 lint-docs: lint-docs-meson
 
diff --git a/Documentation/MyFirstContribution.adoc b/Documentation/MyFirstContribution.adoc
index bbb7b45..f186dfb 100644
--- a/Documentation/MyFirstContribution.adoc
+++ b/Documentation/MyFirstContribution.adoc
@@ -52,6 +52,15 @@
 can be answered if you disconnect and so that others can learn from the
 conversation.
 
+==== https://discord.gg/GRFVkzgxRd[#discord] on Discord
+This is an unofficial Git Discord server for everyone, from people just
+starting out with Git to those who develop it. It's a great place to ask
+questions, share tips, and connect with the broader Git community in real time.
+
+The server has channels for general discussions and specific channels for those
+who use Git and those who develop it. The server's search functionality also
+allows you to find previous conversations and answers to common questions.
+
 [[getting-started]]
 == Getting Started
 
@@ -1144,6 +1153,11 @@
 please don't send your patchset from the tutorial to the real mailing list! For
 now, you can send it to yourself, to make sure you understand how it will look.
 
+NOTE: After sending your patches, you can confirm that they reached the mailing
+list by visiting https://lore.kernel.org/git/. Use the search bar to find your
+name or the subject of your patch. If it appears, your email was successfully
+delivered.
+
 After you run the command above, you will be presented with an interactive
 prompt for each patch that's about to go out. This gives you one last chance to
 edit or quit sending something (but again, don't edit code this way). Once you
diff --git a/Documentation/RelNotes/1.6.2.4.adoc b/Documentation/RelNotes/1.6.2.4.adoc
index f4bf1d0..053dbb6 100644
--- a/Documentation/RelNotes/1.6.2.4.adoc
+++ b/Documentation/RelNotes/1.6.2.4.adoc
@@ -37,3 +37,4 @@
 echo O=$(git describe maint)
 O=v1.6.2.3-38-g318b847
 git shortlog --no-merges $O..maint
+---
diff --git a/Documentation/RelNotes/2.52.0.adoc b/Documentation/RelNotes/2.52.0.adoc
new file mode 100644
index 0000000..fc78d22
--- /dev/null
+++ b/Documentation/RelNotes/2.52.0.adoc
@@ -0,0 +1,454 @@
+Git v2.52 Release Notes
+=======================
+
+UI, Workflows & Features
+------------------------
+
+ * The "list" subcommand of "git refs" acts as a front-end for
+   "git for-each-ref".
+
+ * "git cmd --help-all" now works outside repositories.
+
+ * "git diff-tree" learned "--max-depth" option.
+
+ * A new subcommand "git repo" gives users a way to grab various
+   repository characteristics.
+
+ * A new command "git last-modified" has been added to show the closest
+   ancestor commit that touched each path.
+
+ * The "git refs exists" command that works like "git show-ref --exists"
+   has been added.
+
+ * "git repo info" learns the short-hand option "-z" that is the same as
+   "--format=nul", and learns to report the objects format used in the
+   repository.
+
+ * "core.commentChar=auto" that attempts to dynamically pick a
+   suitable comment character is non-workable, as it is too much
+   trouble to support for little benefit, and is marked as deprecated.
+
+ * "git send-email" learned to drive "git imap-send" to store already
+   sent e-mails in an IMAP folder.
+
+ * The "promisor-remote" capability mechanism has been updated to
+   allow the "partialCloneFilter" settings and the "token" value to be
+   communicated from the server side.
+
+ * Declare that "git init" that is not otherwise configured uses
+   'main' as the initial branch, not 'master', starting Git 3.0.
+
+ * Keep giving hint about the default initial branch name for users
+   who may be surprised after Git 3.0 switch-over.
+
+ * The stash.index configuration variable can be set to make "git stash
+   pop/apply" pretend that it was invoked with "--index".
+
+ * "git fast-import" learned that "--signed-commits=<how>" option that
+   corresponds to that of "git fast-export".
+
+ * Marking a hunk 'selected' in "git add -p" and then splitting made
+   all the split pieces 'selected'; this has been changed to make them
+   all 'undecided', which gives better end-user experience.
+
+ * Configuration variables that take a pathname as a value
+   (e.g. blame.ignorerevsfile) can be marked as optional by prefixing
+   ":(optional)" before its value.
+
+ * Show 'P'ipe command in "git add -p".
+
+ * "git sparse-checkout" subcommand learned a new "clean" action to
+   prune otherwise unused working-tree files that are outside the
+   areas of interest.
+
+ * "git fast-import" is taught to handle signed tags, just like it
+   recently learned to handle signed commits, in different ways.
+
+ * A new configuration variable commitGraph.changedPaths allows to
+   turn "--changed-paths" on by default for "git commit-graph".
+
+ * "Symlink symref" has been added to the list of things that will
+   disappear at Git 3.0 boundary.
+
+ * "git maintenance" command learns the "geometric" strategy where it
+   avoids doing maintenance tasks that rebuilds everything from
+   scratch.
+
+ * "git repo structure", a new command.
+
+ * The help text and manual page of "git bisect" command have been
+   made consistent with each other.
+
+
+Performance, Internal Implementation, Development Support etc.
+--------------------------------------------------------------
+
+ * string_list_split*() family of functions have been extended to
+   simplify common use cases.
+
+ * Arrays of strbuf is often a wrong data structure to use, and
+   strbuf_split*() family of functions that create them often have
+   better alternatives.  Update several code paths and replace
+   strbuf_split*().
+
+ * Revision traversal limited with pathspec, like "git log dir/*",
+   used to ignore changed-paths Bloom filter when the pathspec
+   contained wildcards; now they take advantage of the filter when
+   they can.
+
+ * Doc lint updates to encourage the newer and easier-to-use
+   `synopsis` format, with fixes to a handful of existing uses.
+
+ * Remove dependency on the_repository and other globals from the
+   commit-graph code, and other changes unrelated to de-globaling.
+
+ * Discord has been added to the first contribution documentation as
+   another way to ask for help.
+
+ * Inspired by Ezekiel's recent effort to showcase Rust interface, the
+   hash function implementation used to hash lines have been updated
+   to the one used for ELF symbol lookup by Glibc.
+
+ * Instead of scanning for the remaining items to see if there are
+   still commits to be explored in the queue, use khash to remember
+   which items are still on the queue (an unacceptable alternative is
+   to reserve one object flag bits).
+
+ * The bulk-checkin code used to depend on a file-scope static
+   singleton variable, which has been updated to pass an instance
+   throughout the callchain.
+
+ * The work to build on the bulk-checkin infrastructure to create many
+   objects at once in a transaction and to abstract it into the
+   generic object layer continues.
+
+ * CodingGuidelines now spells out how bitfields are to be written.
+
+ * Adjust to the way newer versions of cURL selectively enable tracing
+   options, so that our tests can continue to work.
+
+ * The clear_alloc_state() API function was not fully clearing the
+   structure for reuse, but since nobody reuses it, replace it with a
+   variant that frees the structure as well, making the callers simpler.
+
+ * "git range-diff" learned a way to limit the memory consumed by
+   O(N*N) cost matrix.
+
+ * Some places in the code confused a variable that is *not* a boolean
+   to enable color but is an enum that records what the user requested
+   to do about color.  A couple of bugs of this sort have been fixed,
+   while the code has been cleaned up to prevent similar bugs in the
+   future.
+
+ * The build procedure based on meson learned a target to only build
+   documentation, similar to "make doc".
+   (merge ff4ec8ded0 ps/meson-build-docs later to maint).
+
+ * Dip our toes a bit to (optionally) use Rust implemented helper
+   called from our C code.
+
+ * Documentation for "git log --pretty" options has been updated
+   to make it easier to translate.
+
+ * Instead of three library archives (one for git, one for reftable,
+   and one for xdiff), roll everything into a single libgit.a archive.
+   This would help later effort to FFI into Rust.
+
+ * The beginning of SHA1-SHA256 interoperability work.
+
+ * Build procedure for a few credential helpers (in contrib/) have
+   been updated.
+
+ * CI improvements to handle the recent Rust integration better.
+
+ * The code in "git repack" machinery has been cleaned up to prepare
+   for incremental update of midx files.
+
+ * Two slightly different ways to get at "all the packfiles" in API
+   has been cleaned up.
+
+ * The code to walk revision graph to compute merge base has been
+   optimized.
+
+ * AI guidelines has been added to our documentation set.
+
+ * Contributed credential helpers (obviously in contrib/) now have "cd
+   $there && make install" target.
+
+ * The "MyFirstContribution" tutorial tells the reader how to send out
+   their patches; the section gained a hint to verify the message
+   reached the mailing list.
+
+ * The "debug" ref-backend was missing a method implementation, which
+   has been corrected.
+
+ * Build procedure for Wincred credential helper has been updated.
+
+ * The build procedure based on meson learned to allow builders to
+   specify the directory to install HTML documents.
+
+ * Building "git contacts" script (in contrib/) left the resulting
+   file unexecutable, which has been corrected.
+
+
+Fixes since v2.51
+-----------------
+
+Unless otherwise noted, all the changes in 2.51.X maintenance track,
+including security updates, are included in this release.
+
+ * During interactive rebase, using 'drop' on a merge commit lead to
+   an error, which was incorrect.
+
+ * "git refs migrate" to migrate the reflog entries from a refs
+   backend to another had a handful of bugs squashed.
+
+ * "git remote rename origin upstream" failed to move origin/HEAD to
+   upstream/HEAD when origin/HEAD is unborn and performed other
+   renames extremely inefficiently, which has been corrected.
+   (merge 16c4fa26b9 ps/remote-rename-fix later to maint).
+
+ * "git describe" has been optimized by using better data structure.
+   (merge 08bb69d70f rs/describe-with-prio-queue later to maint).
+
+ * "git push" had a code path that led to BUG() but it should have
+   been a die(), as it is a response to a usual but invalid end-user
+   action to attempt pushing an object that does not exist.
+
+ * Various bugs about rename handling in "ort" merge strategy have
+   been fixed.
+
+ * "git jump" (in contrib/) fails to parse the diff header correctly
+   when a file has a space in its name, which has been corrected.
+   (merge 621ce9c1c6 gh/git-jump-pathname-with-sp later to maint).
+
+ * "git diff --no-index" run inside a subdirectory under control of a
+   Git repository operated at the top of the working tree and stripped
+   the prefix from the output, and oddballs like "-" (stdin) did not
+   work correctly because of it.  Correct the set-up by undoing what
+   the set-up sequence did to cwd and prefix.
+
+ * Various options to "git diff" that makes comparison ignore certain
+   aspects of the differences (like "space changes are ignored",
+   "differences in lines that match these regular expressions are
+   ignored") did not work well with "--name-only" and friends.
+   (merge b55e6d36eb ly/diff-name-only-with-diff-from-content later to maint).
+
+ * The above caused regressions, which has been corrected.
+
+ * Documentation for "git rebase" has been updated.
+   (merge 3f7f2b0359 je/doc-rebase later to maint).
+
+ * The start_delayed_progress() function in the progress eye-candy API
+   did not clear its internal state, making an initial delay value
+   larger than 1 second ineffective, which has been corrected.
+
+ * The compatObjectFormat extension is used to hide an incomplete
+   feature that is not yet usable for any purpose other than
+   developing the feature further.  Document it as such to discourage
+   its use by mere mortals.
+
+ * "git log -L..." compared trees of multiple parents with the tree of the
+   merge result in an unnecessarily inefficient way.
+   (merge 0a15bb634c sg/line-log-merge-optim later to maint).
+
+ * Under a race against another process that is repacking the
+   repository, especially a partially cloned one, "git fetch" may
+   mistakenly think some objects we do have are missing, which has
+   been corrected.
+
+ * "git fetch" can clobber a symref that is dangling when the
+   remote-tracking HEAD is set to auto update, which has been
+   corrected.
+
+ * "git describe <blob>" misbehaves and/or crashes in some corner
+   cases, which has been taught to exit with failure gracefully.
+   (merge 7c10e48e81 jk/describe-blob later to maint).
+
+ * Manual page for "gitk" is updated with the current maintainer's
+   name.
+
+ * Update the instructions for using GGG in the MyFirstContribution
+   document to say that a GitHub PR could be made against `git/git`
+   instead of `gitgitgadget/git`.
+
+ * Makefile tried to run multiple "cargo build" which would not work
+   very well; serialize their execution to work around this problem.
+
+ * "git repack --path-walk" lost objects in some corner cases, which
+   has been corrected.
+
+ * "git ls-files <pathspec>..." should not necessarily have to expand
+   the index fully if a sparsified directory is excluded by the
+   pathspec; the code is taught to expand the index on demand to avoid
+   this.
+   (merge 681f26bccc ds/ls-files-lazy-unsparse later to maint).
+
+ * Windows "real-time monitoring" interferes with the execution of
+   tests and affects negatively in both correctness and performance,
+   which has been disabled in Gitlab CI.
+
+ * A broken or malicious "git fetch" can say that it has the same
+   object for many many times, and the upload-pack serving it can
+   exhaust memory storing them redundantly, which has been corrected.
+
+ * A corner case bug in "git log -L..." has been corrected.
+
+ * "git rev-parse --short" and friends failed to disambiguate two
+   objects with object names that share common prefix longer than 32
+   characters, which has been fixed.
+   (merge 8655908b9e jc/longer-disambiguation-fix later to maint).
+
+ * Some among "git add -p" and friends ignored color.diff and/or
+   color.ui configuration variables, which is an old regression, which
+   has been corrected.
+
+ * "git subtree" (in contrib/) did not work correctly when splitting
+   squashed subtrees, which has been improved.
+
+ * Import a newer version of the clar unit testing framework.
+   (merge 93dbb6b3c5 ps/clar-updates later to maint).
+
+ * "git send-email --compose --reply-to=<address>" used to add
+   duplicated Reply-To: header, which made mailservers unhappy.  This
+   has been corrected.
+   (merge f448f65719 nb/send-email-no-dup-reply-to later to maint).
+
+ * "git rebase -i" failed to clean-up the commit log message when the
+   command commits the final one in a chain of "fixup" commands, which
+   has been corrected.
+
+ * There are double frees and leaks around setup_revisions() API used
+   in "git stash show", which has been fixed, and setup_revisions()
+   API gained a wrapper to make it more ergonomic when using it with
+   strvec-manged argc/argv pairs.
+   (merge a04bc71725 jk/setup-revisions-freefix later to maint).
+
+ * Deal more gracefully with directory / file conflicts when the files
+   backend is used for ref storage, by failing only the ones that are
+   involved in the conflict while allowing others.
+
+ * "git last-modified" operating in non-recursive mode used to trigger
+   a BUG(), which has been corrected.
+
+ * The use of "git config get" command to learn how ANSI color
+   sequence is for a particular type, e.g., "git config get
+   --type=color --default=reset no.such.thing", isn't very ergonomic.
+   (merge e4dabf4fd6 ps/config-get-color-fixes later to maint).
+
+ * The "do you still use it?" message given by a command that is
+   deeply deprecated and allow us to suggest alternatives has been
+   updated.
+
+ * Clang-format update to let our control macros be formatted the way we
+   had them traditionally, e.g., "for_each_string_list_item()" without
+   space before the parentheses.
+
+ * A few places where a size_t value was cast to curl_off_t without
+   checking has been updated to use the existing helper function.
+
+ * "git reflog write" did not honor the configured user.name/email
+   which has been corrected.
+
+ * Handling of an empty subdirectory of .git/refs/ in the ref-files
+   backend has been corrected.
+
+ * Our CI script requires "sudo" that can be told to preserve
+   environment, but Ubuntu replaced with "sudo" with an implementation
+   that lacks the feature.  Work this around by reinstalling the
+   original version.
+
+ * The reftable backend learned to sanity check its on-disk data more
+   carefully.
+   (merge 466a3a1afd kn/reftable-consistency-checks later to maint).
+
+ * A lot of code clean-up of xdiff.
+   Split out of a larger topic.
+   (merge 8b9c5d2e3a en/xdiff-cleanup later to maint).
+
+ * "git format-patch --range-diff=... --notes=..." did not drive the
+   underlying range-diff with correct --notes parameter, ending up
+   comparing with different set of notes from its main patch output
+   you would get from "git format-patch --notes=..." for a singleton
+   patch.
+
+ * The code in "git add -p" and friends to iterate over hunks was
+   riddled with bugs, which has been corrected.
+
+ * A few more things that patch authors can do to help maintainer to
+   keep track of their topics better.
+   (merge 1a41698841 tb/doc-submitting-patches later to maint).
+
+ * An earlier addition to "git diff --no-index A B" to limit the
+   output with pathspec after the two directories misbehaved when
+   these directories were given with a trailing slash, which has been
+   corrected.
+
+ * The "--short" option of "git status" that meant output for humans
+   and "-z" option to show NUL delimited output format did not mix
+   well, and colored some but not all things.  The command has been
+   updated to color all elements consistently in such a case.
+
+ * Unicode width table update.
+
+ * GPG signing test set-up has been broken for a year, which has been
+   corrected.
+   (merge 516bf45749 jc/t1016-setup-fix later to maint).
+
+ * Recent OpenSSH creates the Unix domain socket to communicate with
+   ssh-agent under $HOME instead of /tmp, which causes our test to
+   fail doe to overly long pathname in our test environment, which has
+   been worked around by using "ssh-agent -T".
+
+ * strbuf_split*() to split a string into multiple strbufs is often a
+   wrong API to use.  A few uses of it have been removed by
+   simplifying the code.
+   (merge 2ab72a16d9 ob/gpg-interface-cleanup later to maint).
+
+ * "git shortlog" knows "--committer" and "--author" options, which
+   the command line completion (in contrib/) did not handle well,
+   which has been corrected.
+   (merge c568fa8e1c kf/log-shortlog-completion-fix later to maint).
+
+ * "git bisect" command did not react correctly to "git bisect help"
+   and "git bisect unknown", which has been corrected.
+   (merge 2bb3a012f3 rz/bisect-help-unknown later to maint).
+
+ * The 'q'(uit) command in "git add -p" has been improved to quit
+   without doing any meaningless work before leaving, and giving EOF
+   (typically control-D) to the prompt is made to behave the same way.
+
+ * The wildmatch code had a corner case bug that mistakenly makes
+   "foo**/bar" match with "foobar", which has been corrected.
+   (merge 1940a02dc1 jk/match-pathname-fix later to maint).
+
+ * Tests did not set up GNUPGHOME correctly, which is fixed but some
+   flaky tests are exposed in t1016, which needs to be addressed
+   before this topic can move forward.
+   (merge 6cd8369ef3 tz/test-prepare-gnupghome later to maint).
+
+ * The patterns used in the .gitignore files use backslash in the way
+   documented for fnmatch(3); document as such to reduce confusion.
+   (merge 8a6d158a1d jk/doc-backslash-in-exclude later to maint).
+
+ * The version of macos image used in GitHub CI has been updated to
+   macos-14, as the macos-13 that we have been using got deprecated.
+   Perforce binary used there has been changed to arm64 version to
+   match.
+   (merge 73b9cdb7c4 jc/ci-use-macos-14 later to maint).
+   (merge ffff0bb0da jc/ci-use-arm64-p4-on-macos later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+   (merge 529a60a885 ua/t1517-short-help-tests later to maint).
+   (merge 22d421fed9 ac/deglobal-fmt-merge-log-config later to maint).
+   (merge a60203a015 dk/t7005-editor-updates later to maint).
+   (merge 16684b6fae ps/reftable-libgit2-cleanup later to maint).
+   (merge e5c27bd3d8 je/doc-add later to maint).
+   (merge 13296ac909 ps/object-store-midx-dedup-info later to maint).
+   (merge f9a6705d9a tc/t0450-harden later to maint).
+   (merge a66fc22bf9 rs/get-oid-with-flags-cleanup later to maint).
+   (merge 15b8abde07 js/mingw-includes-cleanup later to maint).
+   (merge 2cebca0582 tb/cat-file-objectmode-update later to maint).
+   (merge 8f487db07a kh/doc-patch-id-1 later to maint).
+   (merge f711f37b05 eb/t1016-hash-transition-fix later to maint).
+   (merge 85333aa1af jk/test-delete-gpgsig-leakfix later to maint).
diff --git a/Documentation/RelNotes/2.53.0.adoc b/Documentation/RelNotes/2.53.0.adoc
new file mode 100644
index 0000000..7882bc5
--- /dev/null
+++ b/Documentation/RelNotes/2.53.0.adoc
@@ -0,0 +1,62 @@
+Git v2.53 Release Notes
+=======================
+
+UI, Workflows & Features
+------------------------
+
+ * "git maintenance" command learned "is-needed" subcommand to tell if
+   it is necessary to perform various maintenance tasks.
+
+ * "git replay" (experimental) learned to perform ref updates itself
+   in a transaction by default, instead of emitting where each refs
+   should point at and leaving the actual update to another command.
+
+
+Performance, Internal Implementation, Development Support etc.
+--------------------------------------------------------------
+
+ * The list of packfiles used in a running Git process is moved from
+   the packed_git structure into the packfile store.
+
+ * Some ref backend storage can hold not just the object name of an
+   annotated tag, but the object name of the object the tag points at.
+   The code to handle this information has been streamlined.
+
+ * As "git diff --quiet" only cares about the existence of any
+   changes, disable rename/copy detection to skip more expensive
+   processing whose result will be discarded anyway.
+
+ * A part of code paths that deals with loose objects has been cleaned
+   up.
+
+
+Fixes since v2.52
+-----------------
+
+ * Ever since we added whitespace rules for this project, we misspelt
+   an entry, which has been corrected.
+   (merge 358e94dc70 jc/gitattributes-whitespace-no-indent-fix later to maint).
+
+ * The code to expand attribute macros has been rewritten to avoid
+   recursion to avoid running out of stack space in an uncontrolled
+   way.
+   (merge 42ed046866 jk/attr-macroexpand-wo-recursion later to maint).
+
+ * Adding a repository that uses a different hash function is a no-no,
+   but "git submodule add" did nt prevent it, which has been corrected.
+   (merge 6fe288bfbc bc/submodule-force-same-hash later to maint).
+
+ * An earlier check added to osx keychain credential helper to avoid
+   storing the credential itself supplied was overeager and rejected
+   credential material supplied by other helper backends that it would
+   have wanted to store, which has been corrected.
+   (merge 4580bcd235 kn/osxkeychain-idempotent-store-fix later to maint).
+
+ * The "git repo structure" subcommand tried to align its output but
+   mixed up byte count and display column width, which has been
+   corrected.
+   (merge 7a03a10a3a jx/repo-struct-utf8width-fix later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+   (merge 46207a54cc qj/doc-http-bad-want-response later to maint).
+   (merge df90eccd93 kh/doc-commit-extra-references later to maint).
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 86ca7f6..e270ccb 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -446,6 +446,34 @@
 Only capitalize the very first letter of the trailer, i.e. favor
 "Signed-off-by" over "Signed-Off-By" and "Acked-by:" over "Acked-By".
 
+[[ai]]
+=== Use of Artificial Intelligence (AI)
+
+The Developer's Certificate of Origin requires contributors to certify
+that they know the origin of their contributions to the project and
+that they have the right to submit it under the project's license.
+It's not yet clear that this can be legally satisfied when submitting
+significant amount of content that has been generated by AI tools.
+
+Another issue with AI generated content is that AIs still often
+hallucinate or just produce bad code, commit messages, documentation
+or output, even when you point out their mistakes.
+
+To avoid these issues, we will reject anything that looks AI
+generated, that sounds overly formal or bloated, that looks like AI
+slop, that looks good on the surface but makes no sense, or that
+senders don’t understand or cannot explain.
+
+We strongly recommend using AI tools carefully and responsibly.
+
+Contributors would often benefit more from AI by using it to guide and
+help them step by step towards producing a solution by themselves
+rather than by asking for a full solution that they would then mostly
+copy-paste. They can also use AI to help with debugging, or with
+checking for obvious mistakes, things that can be improved, things
+that don’t match our style, guidelines or our feedback, before sending
+it to us.
+
 [[git-tools]]
 === Generate your patch using Git tools out of your commits.
 
@@ -579,14 +607,27 @@
 [[the-topic-summary]]
 *This is EXPERIMENTAL*.
 
-When sending a topic, you can propose a one-paragraph summary that
-should appear in the "What's cooking" report when it is picked up to
-explain the topic.  If you choose to do so, please write a 2-5 line
-paragraph that will fit well in our release notes (see many bulleted
-entries in the Documentation/RelNotes/* files for examples), and make
-it the first paragraph of the cover letter.  For a single-patch
-series, use the space between the three-dash line and the diffstat, as
-described earlier.
+When sending a topic, you can optionally propose a topic name and/or a
+one-paragraph summary that should appear in the "What's cooking"
+report when it is picked up to explain the topic.  If you choose to do
+so, please write a 2-5 line paragraph that will fit well in our
+release notes (see many bulleted entries in the
+Documentation/RelNotes/* files for examples), and make it the first
+(or second, if including a suggested topic name) paragraph of the
+cover letter.  If suggesting a topic name, use the format
+"XX/your-topic-name", where "XX" is a stand-in for the primary
+author's initials, and "your-topic-name" is a brief, dash-delimited
+description of what your topic does.  For a single-patch series, use
+the space between the three-dash line and the diffstat, as described
+earlier.
+
+[[multi-series-efforts]]
+If your patch series is part of a larger effort spanning multiple
+patch series, briefly describe the broader goal, and state where the
+current series fits into that goal.  If you are suggesting a topic
+name as in <<the-topic-summary, section above>>, consider
+"XX/the-broader-goal-part-one", "XX/the-broader-goal-part-two", and so
+on.
 
 [[attachment]]
 Do not attach the patch as a MIME attachment, compressed or not.
diff --git a/Documentation/blame-options.adoc b/Documentation/blame-options.adoc
index 19ea187..1fb948f 100644
--- a/Documentation/blame-options.adoc
+++ b/Documentation/blame-options.adoc
@@ -75,7 +75,8 @@
 	iso format is used. For supported values, see the discussion
 	of the --date option at linkgit:git-log[1].
 
---[no-]progress::
+--progress::
+--no-progress::
 	Progress status is reported on the standard error stream
 	by default when it is attached to a terminal. This flag
 	enables progress reporting even if not attached to a
diff --git a/Documentation/config.adoc b/Documentation/config.adoc
index 05f1ca7..62eebe7 100644
--- a/Documentation/config.adoc
+++ b/Documentation/config.adoc
@@ -357,7 +357,9 @@
 substituted instead. In the unlikely event that a literal path needs to
 be specified that should _not_ be expanded, it needs to be prefixed by
 `./`, like so: `./%(prefix)/bin`.
-
++
+If prefixed with `:(optional)`, the configuration variable is treated
+as if it does not exist, if the named path does not exist.
 
 Variables
 ~~~~~~~~~
diff --git a/Documentation/config/commitgraph.adoc b/Documentation/config/commitgraph.adoc
index 7f8c9d6..70a56c5 100644
--- a/Documentation/config/commitgraph.adoc
+++ b/Documentation/config/commitgraph.adoc
@@ -8,6 +8,17 @@
 	Specifies the default value for the `--max-new-filters` option of `git
 	commit-graph write` (c.f., linkgit:git-commit-graph[1]).
 
+commitGraph.changedPaths::
+	If true, then `git commit-graph write` will compute and write
+	changed-path Bloom filters by default, equivalent to passing
+	`--changed-paths`. If false or unset, changed-paths Bloom filters will
+	be written during `git commit-graph write` only if the filters already
+	exist in the current commit-graph file. This matches the default
+	behavior of `git commit-graph write` without any `--[no-]changed-paths`
+	option. To rewrite a commit-graph file without any filters, use the
+	`--no-changed-paths` option. Command-line option `--[no-]changed-paths`
+	always takes precedence over this configuration. Defaults to unset.
+
 commitGraph.readChangedPaths::
 	Deprecated. Equivalent to commitGraph.changedPathsVersion=-1 if true, and
 	commitGraph.changedPathsVersion=0 if false. (If commitGraph.changedPathVersion
diff --git a/Documentation/config/core.adoc b/Documentation/config/core.adoc
index 8866ed2..11efad1 100644
--- a/Documentation/config/core.adoc
+++ b/Documentation/config/core.adoc
@@ -290,6 +290,9 @@
 	and other symbolic reference files, use symbolic links.
 	This is sometimes needed to work with old scripts that
 	expect HEAD to be a symbolic link.
++
+This configuration is deprecated and will be removed in Git 3.0. Symbolic refs
+will always be written as textual symrefs.
 
 core.alternateRefsCommand::
 	When advertising tips of available history from an alternate, use the shell to
@@ -531,9 +534,25 @@
 	commented, and removes them after the editor returns
 	(default '#').
 +
-If set to "auto", `git-commit` would select a character that is not
+ifndef::with-breaking-changes[]
+If set to "auto", `git-commit` will select a character that is not
 the beginning character of any line in existing commit messages.
+Support for this value is deprecated and will be removed in Git 3.0
+due to the following limitations:
 +
+--
+* It is incompatible with adding comments in a commit message
+  template. This includes the conflicts comments added to
+  the commit message by `cherry-pick`, `merge`, `rebase` and
+  `revert`.
+* It is incompatible with adding comments to the commit message
+  in the `prepare-commit-msg` hook.
+* It is incompatible with the `fixup` and `squash` commands when
+  rebasing,
+* It is not respected by `git notes`
+--
++
+endif::with-breaking-changes[]
 Note that these two variables are aliases of each other, and in modern
 versions of Git you are free to use a string (e.g., `//` or `⁑⁕⁑`) with
 `commentChar`. Versions of Git prior to v2.45.0 will ignore
diff --git a/Documentation/config/maintenance.adoc b/Documentation/config/maintenance.adoc
index 2f71934..d0c38f0 100644
--- a/Documentation/config/maintenance.adoc
+++ b/Documentation/config/maintenance.adoc
@@ -16,19 +16,36 @@
 
 maintenance.strategy::
 	This string config option provides a way to specify one of a few
-	recommended schedules for background maintenance. This only affects
-	which tasks are run during `git maintenance run --schedule=X`
-	commands, provided no `--task=<task>` arguments are provided.
-	Further, if a `maintenance.<task>.schedule` config value is set,
-	then that value is used instead of the one provided by
-	`maintenance.strategy`. The possible strategy strings are:
+	recommended strategies for repository maintenance. This affects
+	which tasks are run during `git maintenance run`, provided no
+	`--task=<task>` arguments are provided. This setting impacts manual
+	maintenance, auto-maintenance as well as scheduled maintenance. The
+	tasks that run may be different depending on the maintenance type.
 +
-* `none`: This default setting implies no tasks are run at any schedule.
+The maintenance strategy can be further tweaked by setting
+`maintenance.<task>.enabled` and `maintenance.<task>.schedule`. If set, these
+values are used instead of the defaults provided by `maintenance.strategy`.
++
+The possible strategies are:
++
+* `none`: This strategy implies no tasks are run at all. This is the default
+  strategy for scheduled maintenance.
+* `gc`: This strategy runs the `gc` task. This is the default strategy for
+  manual maintenance.
+* `geometric`: This strategy performs geometric repacking of packfiles and
+  keeps auxiliary data structures up-to-date. The strategy expires data in the
+  reflog and removes worktrees that cannot be located anymore. When the
+  geometric repacking strategy would decide to do an all-into-one repack, then
+  the strategy generates a cruft pack for all unreachable objects. Objects that
+  are already part of a cruft pack will be expired.
++
+This repacking strategy is a full replacement for the `gc` strategy and is
+recommended for large repositories.
 * `incremental`: This setting optimizes for performing small maintenance
   activities that do not delete any data. This does not schedule the `gc`
   task, but runs the `prefetch` and `commit-graph` tasks hourly, the
   `loose-objects` and `incremental-repack` tasks daily, and the `pack-refs`
-  task weekly.
+  task weekly. Manual repository maintenance uses the `gc` task.
 
 maintenance.<task>.enabled::
 	This boolean config option controls whether the maintenance task
@@ -75,6 +92,22 @@
 	number of pack-files not in the multi-pack-index is at least the value
 	of `maintenance.incremental-repack.auto`. The default value is 10.
 
+maintenance.geometric-repack.auto::
+	This integer config option controls how often the `geometric-repack`
+	task should be run as part of `git maintenance run --auto`. If zero,
+	then the `geometric-repack` task will not run with the `--auto`
+	option. A negative value will force the task to run every time.
+	Otherwise, a positive value implies the command should run either when
+	there are packfiles that need to be merged together to retain the
+	geometric progression, or when there are at least this many loose
+	objects that would be written into a new packfile. The default value is
+	100.
+
+maintenance.geometric-repack.splitFactor::
+	This integer config option controls the factor used for the geometric
+	sequence. See the `--geometric=` option in linkgit:git-repack[1] for
+	more details. Defaults to `2`.
+
 maintenance.reflog-expire.auto::
 	This integer config option controls how often the `reflog-expire` task
 	should be run as part of `git maintenance run --auto`. If zero, then
diff --git a/Documentation/config/promisor.adoc b/Documentation/config/promisor.adoc
index 2638b01..93e5e0d 100644
--- a/Documentation/config/promisor.adoc
+++ b/Documentation/config/promisor.adoc
@@ -9,6 +9,28 @@
 	"false", which means the "promisor-remote" capability is not
 	advertised.
 
+promisor.sendFields::
+	A comma or space separated list of additional remote related
+	field names. A server sends these field names and the
+	associated field values from its configuration when
+	advertising its promisor remotes using the "promisor-remote"
+	capability, see linkgit:gitprotocol-v2[5]. Currently, only the
+	"partialCloneFilter" and "token" field names are supported.
++
+`partialCloneFilter`:: contains the partial clone filter
+used for the remote.
++
+`token`:: contains an authentication token for the remote.
++
+When a field name is part of this list and a corresponding
+"remote.foo.<field-name>" config variable is set on the server to a
+non-empty value, then the field name and value are sent when
+advertising the promisor remote "foo".
++
+This list has no effect unless the "promisor.advertise" config
+variable is set to "true", and the "name" and "url" fields are always
+advertised regardless of this setting.
+
 promisor.acceptFromServer::
 	If set to "all", a client will accept all the promisor remotes
 	a server might advertise using the "promisor-remote"
@@ -28,3 +50,42 @@
 	lazily fetchable from this promisor remote from its responses
 	to "fetch" and "clone" requests from the client. Name and URL
 	comparisons are case sensitive. See linkgit:gitprotocol-v2[5].
+
+promisor.checkFields::
+	A comma or space separated list of additional remote related
+	field names. A client checks if the values of these fields
+	transmitted by a server correspond to the values of these
+	fields in its own configuration before accepting a promisor
+	remote. Currently, "partialCloneFilter" and "token" are the
+	only supported field names.
++
+If one of these field names (e.g., "token") is being checked for an
+advertised promisor remote (e.g., "foo"), three conditions must be met
+for the check of this specific field to pass:
++
+1. The corresponding local configuration (e.g., `remote.foo.token`)
+   must be set.
+2. The server must advertise the "token" field for remote "foo".
+3. The value of the locally configured `remote.foo.token` must exactly
+   match the value advertised by the server for the "token" field.
++
+If any of these conditions is not met for any field name listed in
+`promisor.checkFields`, the advertised remote "foo" is rejected.
++
+For the "partialCloneFilter" field, this allows the client to ensure
+that the server's filter matches what it expects locally, preventing
+inconsistencies in filtering behavior. For the "token" field, this can
+be used to verify that authentication credentials match expected
+values.
++
+Field values are compared case-sensitively.
++
+The "name" and "url" fields are always checked according to the
+`promisor.acceptFromServer` policy, independently of this setting.
++
+The field names and values should be passed by the server through the
+"promisor-remote" capability by using the `promisor.sendFields` config
+variable. The fields are checked only if the
+`promisor.acceptFromServer` config variable is not set to "None". If
+set to "None", this config variable has no effect. See
+linkgit:gitprotocol-v2[5].
diff --git a/Documentation/config/replay.adoc b/Documentation/config/replay.adoc
new file mode 100644
index 0000000..7d549d2
--- /dev/null
+++ b/Documentation/config/replay.adoc
@@ -0,0 +1,11 @@
+replay.refAction::
+	Specifies the default mode for handling reference updates in
+	`git replay`. The value can be:
++
+--
+	* `update`: Update refs directly using an atomic transaction (default behavior).
+	* `print`: Output update-ref commands for pipeline use.
+--
++
+This setting can be overridden with the `--ref-action` command-line option.
+When not configured, `git replay` defaults to `update` mode.
diff --git a/Documentation/config/sendemail.adoc b/Documentation/config/sendemail.adoc
index 4722334..90164c7 100644
--- a/Documentation/config/sendemail.adoc
+++ b/Documentation/config/sendemail.adoc
@@ -88,6 +88,8 @@
 sendemail.smtpServerPort::
 sendemail.smtpServerOption::
 sendemail.smtpUser::
+sendemail.imapSentFolder::
+sendemail.useImapOnly::
 sendemail.thread::
 sendemail.transferEncoding::
 sendemail.validate::
diff --git a/Documentation/config/stash.adoc b/Documentation/config/stash.adoc
index ec1edae..a1197ff 100644
--- a/Documentation/config/stash.adoc
+++ b/Documentation/config/stash.adoc
@@ -1,14 +1,32 @@
-stash.showIncludeUntracked::
-	If this is set to true, the `git stash show` command will show
-	the untracked files of a stash entry.  Defaults to false. See
-	the description of the 'show' command in linkgit:git-stash[1].
+ifndef::git-stash[]
+:see-show: See the description of the 'show' command in linkgit:git-stash[1].
+endif::git-stash[]
 
-stash.showPatch::
+ifdef::git-stash[]
+:see-show:
+endif::git-stash[]
+
+`stash.index`::
+	If this is set to true, `git stash apply` and `git stash pop` will
+	behave as if `--index` was supplied. Defaults to false.
+ifndef::git-stash[]
+See the descriptions in linkgit:git-stash[1].
++
+This also affects invocations of linkgit:git-stash[1] via `--autostash` from
+commands like linkgit:git-merge[1], linkgit:git-rebase[1], and
+linkgit:git-pull[1].
+endif::git-stash[]
+
+`stash.showIncludeUntracked`::
+	If this is set to true, the `git stash show` command will show
+	the untracked files of a stash entry. Defaults to false. {see-show}
+
+`stash.showPatch`::
 	If this is set to true, the `git stash show` command without an
 	option will show the stash entry in patch form.  Defaults to false.
-	See the description of the 'show' command in linkgit:git-stash[1].
+	{see-show}
 
-stash.showStat::
+`stash.showStat`::
 	If this is set to true, the `git stash show` command without an
 	option will show a diffstat of the stash entry.  Defaults to true.
-	See the description of the 'show' command in linkgit:git-stash[1].
+	{see-show}
diff --git a/Documentation/config/tag.adoc b/Documentation/config/tag.adoc
index 5062a05..d878da9 100644
--- a/Documentation/config/tag.adoc
+++ b/Documentation/config/tag.adoc
@@ -1,17 +1,23 @@
-tag.forceSignAnnotated::
+`tag.forceSignAnnotated`::
 	A boolean to specify whether annotated tags created should be GPG signed.
 	If `--annotate` is specified on the command line, it takes
 	precedence over this option.
 
-tag.sort::
-	This variable controls the sort ordering of tags when displayed by
-	linkgit:git-tag[1]. Without the "--sort=<value>" option provided, the
-	value of this variable will be used as the default.
+`tag.sort`::
+ifdef::git-tag[]
+This variable controls the sort ordering of tags when displayed by `git-tag`.
+endif::git-tag[]
+ifndef::git-tag[]
+This variable controls the sort ordering of tags when displayed by
+linkgit:git-tag[1].
+endif::git-tag[]
+Without the `--sort=<value>` option provided, the value of this variable will
+be used as the default.
 
-tag.gpgSign::
+`tag.gpgSign`::
 	A boolean to specify whether all tags should be GPG signed.
 	Use of this option when running in an automated script can
 	result in a large number of tags being signed. It is therefore
-	convenient to use an agent to avoid typing your gpg passphrase
+	convenient to use an agent to avoid typing your GPG passphrase
 	several times. Note that this option doesn't affect tag signing
-	behavior enabled by "-u <keyid>" or "--local-user=<keyid>" options.
+	behavior enabled by `-u <keyid>` or `--local-user=<keyid>` options.
diff --git a/Documentation/config/worktree.adoc b/Documentation/config/worktree.adoc
index 9e3f84f..a248076 100644
--- a/Documentation/config/worktree.adoc
+++ b/Documentation/config/worktree.adoc
@@ -1,4 +1,4 @@
-worktree.guessRemote::
+`worktree.guessRemote`::
 	If no branch is specified and neither `-b` nor `-B` nor
 	`--detach` is used, then `git worktree add` defaults to
 	creating a new branch from HEAD.  If `worktree.guessRemote` is
@@ -6,14 +6,14 @@
 	branch whose name uniquely matches the new branch name.  If
 	such a branch exists, it is checked out and set as "upstream"
 	for the new branch.  If no such match can be found, it falls
-	back to creating a new branch from the current HEAD.
+	back to creating a new branch from the current `HEAD`.
 
-worktree.useRelativePaths::
-	Link worktrees using relative paths (when "true") or absolute
-	paths (when "false"). This is particularly useful for setups
+`worktree.useRelativePaths`::
+	Link worktrees using relative paths (when "`true`") or absolute
+	paths (when "`false`"). This is particularly useful for setups
 	where the repository and worktrees may be moved between
-	different locations or environments. Defaults to "false".
+	different locations or environments. Defaults to "`false`".
 +
-Note that setting `worktree.useRelativePaths` to "true" implies enabling the
+Note that setting `worktree.useRelativePaths` to "`true`" implies enabling the
 `extensions.relativeWorktrees` config (see linkgit:git-config[1]),
 thus making it incompatible with older versions of Git.
diff --git a/Documentation/diff-format.adoc b/Documentation/diff-format.adoc
index 80e36e1..9f7e988 100644
--- a/Documentation/diff-format.adoc
+++ b/Documentation/diff-format.adoc
@@ -103,6 +103,7 @@
 followed by the name of the path in the merge commit.
 
 Examples for `-c` and `--cc` without `--combined-all-paths`:
+
 ------------------------------------------------
 ::100644 100644 100644 fabadb8 cc95eb0 4866510 MM	desc.c
 ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM	bar.sh
diff --git a/Documentation/diff-options.adoc b/Documentation/diff-options.adoc
index f3a35d8..ae31520 100644
--- a/Documentation/diff-options.adoc
+++ b/Documentation/diff-options.adoc
@@ -505,7 +505,8 @@
 	Turn off rename detection, even when the configuration
 	file gives the default to do so.
 
-`--[no-]rename-empty`::
+`--rename-empty`::
+`--no-rename-empty`::
 	Whether to use empty blobs as rename source.
 
 ifndef::git-format-patch[]
@@ -893,5 +894,33 @@
 	reverted with `--ita-visible-in-index`. Both options are
 	experimental and could be removed in future.
 
+--max-depth=<depth>::
+	For each pathspec given on command line, descend at most `<depth>`
+	levels of directories. A value of `-1` means no limit.
+	Cannot be combined with wildcards in the pathspec.
+	Given a tree containing `foo/bar/baz`, the following list shows the
+	matches generated by each set of options:
++
+--
+ - `--max-depth=0 -- foo`: `foo`
+
+ - `--max-depth=1 -- foo`: `foo/bar`
+
+ - `--max-depth=1 -- foo/bar`: `foo/bar/baz`
+
+ - `--max-depth=1 -- foo foo/bar`: `foo/bar/baz`
+
+ - `--max-depth=2 -- foo`: `foo/bar/baz`
+--
++
+If no pathspec is given, the depth is measured as if all
+top-level entries were specified. Note that this is different
+than measuring from the root, in that `--max-depth=0` would
+still return `foo`. This allows you to still limit depth while
+asking for a subset of the top-level entries.
++
+Note that this option is only supported for diffs between tree objects,
+not against the index or working tree.
+
 For more detailed explanation on these common options, see also
 linkgit:gitdiffcore[7].
diff --git a/Documentation/fetch-options.adoc b/Documentation/fetch-options.adoc
index 65f7d1e..ad1e1f4 100644
--- a/Documentation/fetch-options.adoc
+++ b/Documentation/fetch-options.adoc
@@ -1,4 +1,5 @@
---[no-]all::
+--all::
+--no-all::
 	Fetch all remotes, except for the ones that has the
 	`remote.<name>.skipFetchAll` configuration variable set.
 	This overrides the configuration variable `fetch.all`.
@@ -88,7 +89,8 @@
 precedence over the `fetch.output` config option.
 
 ifndef::git-pull[]
---[no-]write-fetch-head::
+--write-fetch-head::
+--no-write-fetch-head::
 	Write the list of remote refs fetched in the `FETCH_HEAD`
 	file directly under `$GIT_DIR`.  This is the default.
 	Passing `--no-write-fetch-head` from the command line tells
@@ -118,13 +120,16 @@
 	Allow several <repository> and <group> arguments to be
 	specified. No <refspec>s may be specified.
 
---[no-]auto-maintenance::
---[no-]auto-gc::
+--auto-maintenance::
+--no-auto-maintenance::
+--auto-gc::
+--no-auto-gc::
 	Run `git maintenance run --auto` at the end to perform automatic
 	repository maintenance if needed. (`--[no-]auto-gc` is a synonym.)
 	This is enabled by default.
 
---[no-]write-commit-graph::
+--write-commit-graph::
+--no-write-commit-graph::
 	Write a commit-graph after fetching. This overrides the config
 	setting `fetch.writeCommitGraph`.
 endif::git-pull[]
diff --git a/Documentation/for-each-ref-options.adoc b/Documentation/for-each-ref-options.adoc
new file mode 100644
index 0000000..f13efb5
--- /dev/null
+++ b/Documentation/for-each-ref-options.adoc
@@ -0,0 +1,85 @@
+`<pattern>...`::
+	If one or more _<pattern>_ parameters are given, only refs are shown that
+	match against at least one pattern, either using `fnmatch`(3) or
+	literally, in the latter case matching completely or from the
+	beginning up to a slash.
+
+`--stdin`::
+	The list of patterns is read from standard input instead of from
+	the argument list.
+
+`--count=<count>`::
+	Stop after showing _<count>_ refs.
+
+`--sort=<key>`::
+	Sort on the field name _<key>_.  Prefix `-` to sort in
+	descending order of the value.  When unspecified,
+	`refname` is used.  You may use the `--sort=<key>` option
+	multiple times, in which case the last key becomes the primary
+	key.
+
+`--format[=<format>]`::
+	A string that interpolates `%(fieldname)` from a ref being shown and
+	the object it points at. In addition, the string literal `%%`
+	renders as `%` and `%xx` - where `xx` are hex digits - renders as
+	the character with hex code `xx`. For example, `%00` interpolates to
+	`\0` (_NUL_), `%09` to `\t` (_TAB_), and `%0a` to `\n` (_LF_).
+
+When unspecified, _<format>_ defaults to `%(objectname) SPC %(objecttype)
+TAB %(refname)`.
+
+`--color[=<when>]`::
+	Respect any colors specified in the `--format` option. The
+	_<when__ field must be one of `always`, `never`, or `auto` (if
+	`<when>` is absent, behave as if `always` was given).
+
+`--shell`::
+`--perl`::
+`--python`::
+`--tcl`::
+	If given, strings that substitute `%(fieldname)`
+	placeholders are quoted as string literals suitable for
+	the specified host language.  This is meant to produce
+	a scriptlet that can directly be "eval"ed.
+
+`--points-at=<object>`::
+	Only list refs which points at the given object.
+
+`--merged[=<object>]`::
+	Only list refs whose tips are reachable from the
+	specified commit (`HEAD` if not specified).
+
+`--no-merged[=<object>]`::
+	Only list refs whose tips are not reachable from _<object>_(`HEAD` if not
+	specified).
+
+`--contains[=<object>]`::
+	Only list refs which contain _<object>_(`HEAD` if not specified).
+
+`--no-contains[=<object>]`::
+	Only list refs which don't contain _<object>_ (`HEAD`
+	if not specified).
+
+`--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.
+
+`--exclude=<excluded-pattern>`::
+	If one or more `--exclude` options are given, only refs which do not
+	match any _<excluded-pattern>_ parameters are shown. Matching is done
+	using the same rules as _<pattern>_ above.
+
+`--include-root-refs`::
+	List root refs (`HEAD` and pseudorefs) apart from regular refs.
+
+`--start-after=<marker>`::
+    Allows paginating the output by skipping references up to and including the
+    specified marker. When paging, it should be noted that references may be
+    deleted, modified or added between invocations. Output will only yield those
+    references which follow the marker lexicographically. Output begins from the
+    first reference that would come after the marker alphabetically. Cannot be
+    used with `--sort=<key>` or `--stdin` options, or the _<pattern>_ argument(s)
+    to limit the refs.
diff --git a/Documentation/fsck-msgids.adoc b/Documentation/fsck-msgids.adoc
index 0ba4f9a..acac968 100644
--- a/Documentation/fsck-msgids.adoc
+++ b/Documentation/fsck-msgids.adoc
@@ -10,6 +10,12 @@
 `badFilemode`::
 	(INFO) A tree contains a bad filemode entry.
 
+`badGpgsig`::
+	(ERROR) A tag contains a bad (truncated) signature (e.g., `gpgsig`) header.
+
+`badHeaderContinuation`::
+	(ERROR) A continuation header (such as for `gpgsig`) is unexpectedly truncated.
+
 `badName`::
 	(ERROR) An author/committer name is empty.
 
@@ -38,6 +44,9 @@
 `badReferentName`::
 	(ERROR) The referent name of a symref is invalid.
 
+`badReftableTableName`::
+	(WARN) A reftable table has an invalid name.
+
 `badTagName`::
 	(INFO) A tag has an invalid format.
 
@@ -104,9 +113,6 @@
 `gitmodulesParse`::
 	(INFO) Could not parse `.gitmodules` blob.
 
-`gitmodulesLarge`;
-	(ERROR) `.gitmodules` blob is too large to parse.
-
 `gitmodulesPath`::
 	(ERROR) `.gitmodules` path is invalid.
 
diff --git a/Documentation/git-add.adoc b/Documentation/git-add.adoc
index b7a7358..6192dae 100644
--- a/Documentation/git-add.adoc
+++ b/Documentation/git-add.adoc
@@ -16,18 +16,18 @@
 
 DESCRIPTION
 -----------
-This command updates the index using the current content found in
-the working tree, to prepare the content staged for the next commit.
-It typically adds the current content of existing paths as a whole,
-but with some options it can also be used to add content with
-only part of the changes made to the working tree files applied, or
-remove paths that do not exist in the working tree anymore.
+Add contents of new or changed files to the index. The "index" (also
+known as the "staging area") is what you use to prepare the contents of
+the next commit.
 
-The "index" holds a snapshot of the content of the working tree, and it
-is this snapshot that is taken as the contents of the next commit.  Thus
-after making any changes to the working tree, and before running
-the commit command, you must use the `add` command to add any new or
-modified files to the index.
+When you run `git commit` without any other arguments, it will only
+commit staged changes. For example, if you've edited `file.c` and want
+to commit your changes to that file, you can run:
+
+   git add file.c
+   git commit
+
+You can also add only part of your changes to a file with `git add -p`.
 
 This command can be performed multiple times before a commit.  It only
 adds the content of the specified file(s) at the time the add command is
@@ -37,12 +37,10 @@
 The `git status` command can be used to obtain a summary of which
 files have changes that are staged for the next commit.
 
-The `git add` command will not add ignored files by default.  If any
-ignored files were explicitly specified on the command line, `git add`
-will fail with a list of ignored files.  Ignored files reached by
-directory recursion or filename globbing performed by Git (quote your
-globs before the shell) will be silently ignored.  The `git add` command can
-be used to add ignored files with the `-f` (force) option.
+The `git add` command will not add ignored files by default. You can
+use the `--force` option to add ignored files. If you specify the exact
+filename of an ignored file, `git add` will fail with a list of ignored
+files. Otherwise it will silently ignore the file.
 
 Please see linkgit:git-commit[1] for alternative ways to add content to a
 commit.
@@ -344,13 +342,14 @@
        d - do not stage this hunk or any of the later hunks in the file
        g - select a hunk to go to
        / - search for a hunk matching the given regex
-       j - leave this hunk undecided, see next undecided hunk
-       J - leave this hunk undecided, see next hunk
-       k - leave this hunk undecided, see previous undecided hunk
-       K - leave this hunk undecided, see previous hunk
+       j - go to the next undecided hunk, roll over at the bottom
+       J - go to the next hunk, roll over at the bottom
+       k - go to the previous undecided hunk, roll over at the top
+       K - go to the previous hunk, roll over at the top
        s - split the current hunk into smaller hunks
        e - manually edit the current hunk
        p - print the current hunk
+       P - print the current hunk using the pager
        ? - print help
 +
 After deciding the fate for all hunks, if there is any hunk
diff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc
index 221070d..b23b4fb 100644
--- a/Documentation/git-am.adoc
+++ b/Documentation/git-am.adoc
@@ -48,7 +48,8 @@
 --keep-non-patch::
 	Pass `-b` flag to 'git mailinfo' (see linkgit:git-mailinfo[1]).
 
---[no-]keep-cr::
+--keep-cr::
+--no-keep-cr::
 	With `--keep-cr`, call 'git mailsplit' (see linkgit:git-mailsplit[1])
 	with the same option, to prevent it from stripping CR at the end of
 	lines. `am.keepcr` configuration variable can be used to specify the
diff --git a/Documentation/git-backfill.adoc b/Documentation/git-backfill.adoc
index 9562305..b8394dc 100644
--- a/Documentation/git-backfill.adoc
+++ b/Documentation/git-backfill.adoc
@@ -57,7 +57,8 @@
 	blobs seen at a given path. The default minimum batch size is
 	50,000.
 
-`--[no-]sparse`::
+`--sparse`::
+`--no-sparse`::
 	Only download objects if they appear at a path that matches the
 	current sparse-checkout. If the sparse-checkout feature is enabled,
 	then `--sparse` is assumed and can be disabled with `--no-sparse`.
diff --git a/Documentation/git-bisect.adoc b/Documentation/git-bisect.adoc
index 58dbb74..b0078dd 100644
--- a/Documentation/git-bisect.adoc
+++ b/Documentation/git-bisect.adoc
@@ -9,26 +9,22 @@
 SYNOPSIS
 --------
 [verse]
-'git bisect' <subcommand> <options>
+'git bisect' start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]
+		   [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]
+'git bisect' (bad|new|<term-new>) [<rev>]
+'git bisect' (good|old|<term-old>) [<rev>...]
+'git bisect' terms [--term-(good|old) | --term-(bad|new)]
+'git bisect' skip [(<rev>|<range>)...]
+'git bisect' next
+'git bisect' reset [<commit>]
+'git bisect' (visualize|view)
+'git bisect' replay <logfile>
+'git bisect' log
+'git bisect' run <cmd> [<arg>...]
+'git bisect' help
 
 DESCRIPTION
 -----------
-The command takes various subcommands, and different options depending
-on the subcommand:
-
- git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]
-		  [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]
- git bisect (bad|new|<term-new>) [<rev>]
- git bisect (good|old|<term-old>) [<rev>...]
- git bisect terms [--term-(good|old) | --term-(bad|new)]
- git bisect skip [(<rev>|<range>)...]
- git bisect reset [<commit>]
- git bisect (visualize|view)
- git bisect replay <logfile>
- git bisect log
- git bisect run <cmd> [<arg>...]
- git bisect help
-
 This command uses a binary search algorithm to find which commit in
 your project's history introduced a bug. You use it by first telling
 it a "bad" commit that is known to contain the bug, and a "good"
@@ -295,6 +291,19 @@
 This tells the bisect process that the commits between `v2.5` and
 `v2.6` (inclusive) should be skipped.
 
+Bisect next
+~~~~~~~~~~~
+
+Normally, after marking a revision as good or bad, Git automatically
+computes and checks out the next revision to test. However, if you need to
+explicitly request the next bisection step, you can use:
+
+------------
+$ git bisect next
+------------
+
+You might use this to resume the bisection process after interrupting it
+by checking out a different revision.
 
 Cutting down bisection by giving more parameters to bisect start
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc
index 180d1ad..c139f55 100644
--- a/Documentation/git-cat-file.adoc
+++ b/Documentation/git-cat-file.adoc
@@ -62,8 +62,10 @@
 	or to ask for a "blob" with `<object>` being a tag object that
 	points at it.
 
---[no-]mailmap::
---[no-]use-mailmap::
+--mailmap::
+--no-mailmap::
+--use-mailmap::
+--no-use-mailmap::
        Use mailmap file to map author, committer and tagger names
        and email addresses to canonical real names and email addresses.
        See linkgit:git-shortlog[1].
diff --git a/Documentation/git-check-attr.adoc b/Documentation/git-check-attr.adoc
index 503b644..15a37a3 100644
--- a/Documentation/git-check-attr.adoc
+++ b/Documentation/git-check-attr.adoc
@@ -19,7 +19,8 @@
 
 OPTIONS
 -------
--a, --all::
+-a::
+--all::
 	List all attributes that are associated with the specified
 	paths.  If this option is used, then 'unspecified' attributes
 	will not be included in the output.
diff --git a/Documentation/git-check-ignore.adoc b/Documentation/git-check-ignore.adoc
index 3e3b4e3..a6c6c1b 100644
--- a/Documentation/git-check-ignore.adoc
+++ b/Documentation/git-check-ignore.adoc
@@ -25,11 +25,13 @@
 
 OPTIONS
 -------
--q, --quiet::
+-q::
+--quiet::
 	Don't output anything, just set exit status.  This is only
 	valid with a single pathname.
 
--v, --verbose::
+-v::
+--verbose::
 	Instead of printing the paths that are excluded, for each path
 	that matches an exclude pattern, print the exclude pattern
 	together with the path.  (Matching an exclude pattern usually
@@ -49,7 +51,8 @@
 	below).  If `--stdin` is also given, input paths are separated
 	with a NUL character instead of a linefeed character.
 
--n, --non-matching::
+-n::
+--non-matching::
 	Show given paths which don't match any pattern.  This only
 	makes sense when `--verbose` is enabled, otherwise it would
 	not be possible to distinguish between paths which match a
diff --git a/Documentation/git-check-ref-format.adoc b/Documentation/git-check-ref-format.adoc
index 2aacfd1..0c3abf9 100644
--- a/Documentation/git-check-ref-format.adoc
+++ b/Documentation/git-check-ref-format.adoc
@@ -98,7 +98,8 @@
 
 OPTIONS
 -------
---[no-]allow-onelevel::
+--allow-onelevel::
+--no-allow-onelevel::
 	Controls whether one-level refnames are accepted (i.e.,
 	refnames that do not contain multiple `/`-separated
 	components).  The default is `--no-allow-onelevel`.
diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
index 40e02cf..6f281b2 100644
--- a/Documentation/git-checkout.adoc
+++ b/Documentation/git-checkout.adoc
@@ -12,25 +12,29 @@
 git checkout [-q] [-f] [-m] --detach [<branch>]
 git checkout [-q] [-f] [-m] [--detach] <commit>
 git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new-branch>] [<start-point>]
-git checkout [-f] <tree-ish> [--] <pathspec>...
-git checkout [-f] <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul]
+git checkout <tree-ish> [--] <pathspec>...
+git checkout <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul]
 git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>...
 git checkout [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul]
 git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]
 
 DESCRIPTION
 -----------
-Updates files in the working tree to match the version in the index
-or the specified tree.  If no pathspec was given, `git checkout` will
-also update `HEAD` to set the specified branch as the current
-branch.
+
+`git checkout` has two main modes:
+
+1. **Switch branches**, with `git checkout <branch>`
+2. **Restore a different version of a file**, for example with
+   `git checkout <commit> <filename>` or `git checkout <filename>`
+
+See ARGUMENT DISAMBIGUATION below for how Git decides which one to do.
 
 `git checkout [<branch>]`::
-	To prepare for working on _<branch>_, switch to it by updating
-	the index and the files in the working tree, and by pointing
-	`HEAD` at the branch. Local modifications to the files in the
-	working tree are kept, so that they can be committed to the
-	_<branch>_.
+	Switch to _<branch>_. This sets the current branch to _<branch>_ and
+	updates the files in your working directory. The checkout will fail
+	if there are uncommitted changes to any files where _<branch>_ and
+	your current commit have different content. Uncommitted changes will
+	otherwise be kept.
 +
 If _<branch>_ is not found but there does exist a tracking branch in
 exactly one remote (call it _<remote>_) with a matching name and
@@ -40,68 +44,63 @@
 $ git checkout -b <branch> --track <remote>/<branch>
 ------------
 +
-You could omit _<branch>_, in which case the command degenerates to
-"check out the current branch", which is a glorified no-op with
-rather expensive side-effects to show only the tracking information,
-if it exists, for the current branch.
+Running `git checkout` without specifying a branch has no effect except
+to print out the tracking information for the current branch.
 
-`git checkout (-b|-B) <new-branch> [<start-point>]`::
+`git checkout -b <new-branch> [<start-point>]`::
 
-	Specifying `-b` causes a new branch to be created as if
-	linkgit:git-branch[1] were called and then checked out.  In
-	this case you can use the `--track` or `--no-track` options,
-	which will be passed to `git branch`.  As a convenience,
-	`--track` without `-b` implies branch creation; see the
-	description of `--track` below.
+	Create a new branch named _<new-branch>_, start it at _<start-point>_
+	(defaults to the current commit), and check out the new branch.
+	You can use the `--track` or `--no-track` options to set the branch's
+	upstream tracking information.
 +
-If `-B` is given, _<new-branch>_ is created if it doesn't exist; otherwise, it
-is reset. This is the transactional equivalent of
-+
-------------
-$ git branch -f <branch> [<start-point>]
-$ git checkout <branch>
-------------
-+
-that is to say, the branch is not reset/created unless "git checkout" is
-successful (e.g., when the branch is in use in another worktree, not
-just the current branch stays the same, but the branch is not reset to
-the start-point, either).
+This will fail if there's an error checking out _<new-branch>_, for
+example if checking out the `<start-point>` commit would overwrite your
+uncommitted changes.
+
+`git checkout -B <branch> [<start-point>]`::
+
+	The same as `-b`, except that if the branch already exists it
+	resets _<branch>_ to the start point instead of failing.
 
 `git checkout --detach [<branch>]`::
 `git checkout [--detach] <commit>`::
 
-	Prepare to work on top of _<commit>_, by detaching `HEAD` at it
-	(see "DETACHED HEAD" section), and updating the index and the
-	files in the working tree.  Local modifications to the files
-	in the working tree are kept, so that the resulting working
-	tree will be the state recorded in the commit plus the local
-	modifications.
-+
-When the _<commit>_ argument is a branch name, the `--detach` option can
-be used to detach `HEAD` at the tip of the branch (`git checkout
-<branch>` would check out that branch without detaching `HEAD`).
+	The same as `git checkout <branch>`, except that instead of pointing
+	`HEAD` at the branch, it points `HEAD` at the commit ID.
+	See the "DETACHED HEAD" section below for more.
 +
 Omitting _<branch>_ detaches `HEAD` at the tip of the current branch.
 
-`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...`::
-`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]`::
+`git checkout <tree-ish> [--] <pathspec>...`::
+`git checkout <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul]`::
 
-	Overwrite the contents of the files that match the pathspec.
-	When the _<tree-ish>_ (most often a commit) is not given,
-	overwrite working tree with the contents in the index.
-	When the _<tree-ish>_ is given, overwrite both the index and
-	the working tree with the contents at the _<tree-ish>_.
+	Replace the specified files and/or directories with the version from
+	the given commit or tree and add them to the index
+	(also known as "staging area").
 +
-The index may contain unmerged entries because of a previous failed merge.
-By default, if you try to check out such an entry from the index, the
-checkout operation will fail and nothing will be checked out.
-Using `-f` will ignore these unmerged entries.  The contents from a
-specific side of the merge can be checked out of the index by
-using `--ours` or `--theirs`.  With `-m`, changes made to the working tree
-file can be discarded to re-create the original conflicted merge result.
+For example, `git checkout main file.txt` will replace `file.txt`
+with the version from `main`.
+
+`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>...`::
+`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul]`::
+
+	Replace the specified files and/or directories with the version from
+	the index.
++
+For example, if you check out a commit, edit `file.txt`, and then
+decide those changes were a mistake, `git checkout file.txt` will
+discard any unstaged changes to `file.txt`.
++
+This will fail if the file has a merge conflict and you haven't yet run
+`git add file.txt` (or something equivalent) to mark it as resolved.
+You can use `-f` to ignore the unmerged files instead of failing, use
+`--ours` or `--theirs` to replace them with the version from a specific
+side of the merge, or use `-m` to replace them with the original
+conflicted merge result.
 
 `git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]`::
-	This is similar to the previous mode, but lets you use the
+	This is similar to the previous two modes, but lets you use the
 	interactive interface to show the "diff" output and choose which
 	hunks to use in the result.  See below for the description of
 	`--patch` option.
@@ -155,16 +154,14 @@
 	see linkgit:git-branch[1] for details.
 
 `-B <new-branch>`::
-	Creates the branch _<new-branch>_, start it at _<start-point>_;
-	if it already exists, then reset it to _<start-point>_. And then
-	check the resulting branch out.  This is equivalent to running
-	`git branch` with `-f` followed by `git checkout` of that branch;
-	see linkgit:git-branch[1] for details.
+	The same as `-b`, except that if the branch already exists it
+	resets _<branch>_ to the start point instead of failing.
 
 `-t`::
 `--track[=(direct|inherit)]`::
 	When creating a new branch, set up "upstream" configuration. See
-	`--track` in linkgit:git-branch[1] for details.
+	`--track` in linkgit:git-branch[1] for details. As a convenience,
+	--track without -b implies branch creation.
 +
 If no `-b` option is given, the name of the new branch will be
 derived from the remote-tracking branch, by looking at the local part of
@@ -334,7 +331,7 @@
 	separated with _NUL_ character and all other characters are taken
 	literally (including newlines and quotes).
 
-<branch>::
+`<branch>`::
 	Branch to checkout; if it refers to a branch (i.e., a name that,
 	when prepended with "refs/heads/", is a valid ref), then that
 	branch is checked out. Otherwise, if it refers to a valid
@@ -511,14 +508,18 @@
 ARGUMENT DISAMBIGUATION
 -----------------------
 
-When there is only one argument given and it is not `--` (e.g. `git
-checkout abc`), and when the argument is both a valid _<tree-ish>_
-(e.g. a branch `abc` exists) and a valid _<pathspec>_ (e.g. a file
-or a directory whose name is "abc" exists), Git would usually ask
-you to disambiguate.  Because checking out a branch is so common an
-operation, however, `git checkout abc` takes "abc" as a _<tree-ish>_
-in such a situation.  Use `git checkout -- <pathspec>` if you want
-to checkout these paths out of the index.
+When you run `git checkout <something>`, Git tries to guess whether
+`<something>` is intended to be a branch, a commit, or a set of file(s),
+and then either switches to that branch or commit, or restores the
+specified files.
+
+If there's any ambiguity, Git will treat `<something>` as a branch or
+commit, but you can use the double dash `--` to force Git to treat the
+parameter as a list of files and/or directories, like this:
+
+----------
+git checkout -- file.txt
+----------
 
 EXAMPLES
 --------
diff --git a/Documentation/git-clone.adoc b/Documentation/git-clone.adoc
index d829206..57cdfb7 100644
--- a/Documentation/git-clone.adoc
+++ b/Documentation/git-clone.adoc
@@ -272,7 +272,8 @@
 	reachable from a specified remote branch or tag.  This option
 	can be specified multiple times.
 
-`--[no-]single-branch`::
+`--single-branch`::
+`--no-single-branch`::
 	Clone only the history leading to the tip of a single branch,
 	either specified by the `--branch` option or the primary
 	branch remote's `HEAD` points at.
@@ -282,7 +283,8 @@
 	branch when `--single-branch` clone was made, no remote-tracking
 	branch is created.
 
-`--[no-]tags`::
+`--tags`::
+`--no-tags`::
 	Control whether or not tags will be cloned. When `--no-tags` is
 	given, the option will be become permanent by setting the
 	`remote.<remote>.tagOpt=--no-tags` configuration. This ensures that
@@ -313,10 +315,12 @@
 not have a worktree/checkout (i.e. if any of `--no-checkout`/`-n`, `--bare`,
 or `--mirror` is given)
 
-`--[no-]shallow-submodules`::
+`--shallow-submodules`::
+`--no-shallow-submodules`::
 	All submodules which are cloned will be shallow with a depth of 1.
 
-`--[no-]remote-submodules`::
+`--remote-submodules`::
+`--no-remote-submodules`::
 	All submodules which are cloned will use the status of the submodule's
 	remote-tracking branch to update the submodule, rather than the
 	superproject's recorded SHA-1. Equivalent to passing `--remote` to
diff --git a/Documentation/git-commit-graph.adoc b/Documentation/git-commit-graph.adoc
index 50b5016..6d19026 100644
--- a/Documentation/git-commit-graph.adoc
+++ b/Documentation/git-commit-graph.adoc
@@ -34,7 +34,8 @@
 	object directory, `git commit-graph ...` will exit with non-zero
 	status.
 
---[no-]progress::
+--progress::
+--no-progress::
 	Turn progress on/off explicitly. If neither is specified, progress is
 	shown if standard error is connected to a terminal.
 
@@ -70,7 +71,7 @@
 for getting history of a directory or a file with `git log -- <path>`. If
 this option is given, future commit-graph writes will automatically assume
 that this option was intended. Use `--no-changed-paths` to stop storing this
-data.
+data. `--changed-paths` is implied by config `commitGraph.changedPaths=true`.
 +
 With the `--max-new-filters=<n>` option, generate at most `n` new Bloom
 filters (if `--changed-paths` is specified). If `n` is `-1`, no limit is
diff --git a/Documentation/git-commit.adoc b/Documentation/git-commit.adoc
index ae988a8..8329c10 100644
--- a/Documentation/git-commit.adoc
+++ b/Documentation/git-commit.adoc
@@ -146,7 +146,8 @@
 	linkgit:git-status[1] for details. Implies `--dry-run`.
 
 `--branch`::
-	Show the branch and tracking info even in short-format.
+	Show the branch and tracking info even in short-format. See
+	linkgit:git-status[1] for details.
 
 `--porcelain`::
 	When doing a dry-run, give the output in a porcelain-ready
@@ -154,12 +155,13 @@
 	`--dry-run`.
 
 `--long`::
-	When doing a dry-run, give the output in the long-format.
-	Implies `--dry-run`.
+	When doing a dry-run, give the output in the long-format. This
+	is the default output of linkgit:git-status[1]. Implies
+	`--dry-run`.
 
 `-z`::
 `--null`::
-	When showing `short` or `porcelain` status output, print the
+	When showing `short` or `porcelain` linkgit:git-status[1] output, print the
 	filename verbatim and terminate the entries with _NUL_, instead of _LF_.
 	If no format is given, implies the `--porcelain` output format.
 	Without the `-z` option, filenames with "unusual" characters are
@@ -214,7 +216,8 @@
 	each trailer would appear, and other details.
 
 `-n`::
-`--[no-]verify`::
+`--verify`::
+`--no-verify`::
 	Bypass the `pre-commit` and `commit-msg` hooks.
 	See also linkgit:githooks[5].
 
@@ -281,6 +284,7 @@
 +
 --
 It is a rough equivalent for:
+
 ------
 	$ git reset --soft HEAD^
 	$ ... do something else to come up with the right tree ...
diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc
index a633ab8..cc054fa 100644
--- a/Documentation/git-config.adoc
+++ b/Documentation/git-config.adoc
@@ -295,7 +295,8 @@
 	When the color setting for `name` is undefined, the command uses
 	`color.ui` as fallback.
 
---[no-]includes::
+--includes::
+--no-includes::
 	Respect `include.*` directives in config files when looking up
 	values. Defaults to `off` when a specific file is given (e.g.,
 	using `--file`, `--global`, etc) and `on` when searching all
diff --git a/Documentation/git-difftool.adoc b/Documentation/git-difftool.adoc
index d596205..064bc68 100644
--- a/Documentation/git-difftool.adoc
+++ b/Documentation/git-difftool.adoc
@@ -77,7 +77,8 @@
 --tool-help::
 	Print a list of diff tools that may be used with `--tool`.
 
---[no-]symlinks::
+--symlinks::
+--no-symlinks::
 	'git difftool''s default behavior is to create symlinks to the
 	working tree when run in `--dir-diff` mode and the right-hand
 	side of the comparison yields the same content as the file in
@@ -94,7 +95,8 @@
 	Additionally, `$BASE` is set in the environment.
 
 -g::
---[no-]gui::
+--gui::
+--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`. This may be
@@ -104,7 +106,8 @@
 	fallback in the order of `merge.guitool`, `diff.tool`,
 	`merge.tool` until a tool is found.
 
---[no-]trust-exit-code::
+--trust-exit-code::
+--no-trust-exit-code::
 	Errors reported by the diff tool are ignored by default.
 	Use `--trust-exit-code` to make 'git-difftool' exit when an
 	invoked diff tool returns a non-zero exit code.
diff --git a/Documentation/git-fast-import.adoc b/Documentation/git-fast-import.adoc
index 37d8aa3..b74179a 100644
--- a/Documentation/git-fast-import.adoc
+++ b/Documentation/git-fast-import.adoc
@@ -66,6 +66,16 @@
 remote-helpers that use the `import` capability, as they are
 already trusted to run their own code.
 
+--signed-tags=(verbatim|warn-verbatim|warn-strip|strip|abort)::
+	Specify how to handle signed tags.  Behaves in the same way
+	as the same option in linkgit:git-fast-export[1], except that
+	default is 'verbatim' (instead of 'abort').
+
+--signed-commits=(verbatim|warn-verbatim|warn-strip|strip|abort)::
+	Specify how to handle signed commits.  Behaves in the same way
+	as the same option in linkgit:git-fast-export[1], except that
+	default is 'verbatim' (instead of 'abort').
+
 Options for Frontends
 ~~~~~~~~~~~~~~~~~~~~~
 
@@ -111,7 +121,8 @@
 	Like --import-marks but instead of erroring out, silently
 	skips the file if it does not exist.
 
---[no-]relative-marks::
+--relative-marks::
+--no-relative-marks::
 	After specifying --relative-marks the paths specified
 	with --import-marks= and --export-marks= are relative
 	to an internal directory in the current repository.
@@ -605,9 +616,11 @@
 
 The special case of restarting an incremental import from the
 current branch value should be written as:
+
 ----
 	from refs/heads/branch^0
 ----
+
 The `^0` suffix is necessary as fast-import does not permit a branch to
 start from itself, and the branch is created in memory before the
 `from` command is even read from the input.  Adding `^0` will force
diff --git a/Documentation/git-fmt-merge-msg.adoc b/Documentation/git-fmt-merge-msg.adoc
index 0f33289..6d91620 100644
--- a/Documentation/git-fmt-merge-msg.adoc
+++ b/Documentation/git-fmt-merge-msg.adoc
@@ -35,7 +35,8 @@
 	Do not list one-line descriptions from the actual commits being
 	merged.
 
---[no-]summary::
+--summary::
+--no-summary::
 	Synonyms to --log and --no-log; these are deprecated and will be
 	removed in the future.
 
diff --git a/Documentation/git-for-each-ref.adoc b/Documentation/git-for-each-ref.adoc
index 0609409..c02cb7f 100644
--- a/Documentation/git-for-each-ref.adoc
+++ b/Documentation/git-for-each-ref.adoc
@@ -14,108 +14,21 @@
 		   [--merged[=<object>]] [--no-merged[=<object>]]
 		   [--contains[=<object>]] [--no-contains[=<object>]]
 		   [(--exclude=<pattern>)...] [--start-after=<marker>]
-		   [ --stdin | <pattern>... ]
+		   [ --stdin | (<pattern>...)]
 
 DESCRIPTION
 -----------
 
-Iterate over all refs that match `<pattern>` and show them
-according to the given `<format>`, after sorting them according
-to the given set of `<key>`.  If `<count>` is given, stop after
-showing that many refs.  The interpolated values in `<format>`
+Iterate over all refs that match _<pattern>_ and show them
+according to the given _<format>_, after sorting them according
+to the given set of _<key>_.  If _<count>_ is given, stop after
+showing that many refs.  The interpolated values in _<format>_
 can optionally be quoted as string literals in the specified
 host language allowing their direct evaluation in that language.
 
 OPTIONS
 -------
-<pattern>...::
-	If one or more patterns are given, only refs are shown that
-	match against at least one pattern, either using fnmatch(3) or
-	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
-	that many refs.
-
---sort=<key>::
-	A field name to sort on.  Prefix `-` to sort in
-	descending order of the value.  When unspecified,
-	`refname` is used.  You may use the --sort=<key> option
-	multiple times, in which case the last key becomes the primary
-	key.
-
---format=<format>::
-	A string that interpolates `%(fieldname)` from a ref being shown and
-	the object it points at. In addition, the string literal `%%`
-	renders as `%` and `%xx` - where `xx` are hex digits - renders as
-	the character with hex code `xx`. For example, `%00` interpolates to
-	`\0` (NUL), `%09` to `\t` (TAB), and `%0a` to `\n` (LF).
-+
-When unspecified, `<format>` defaults to `%(objectname) SPC %(objecttype)
-TAB %(refname)`.
-
---color[=<when>]::
-	Respect any colors specified in the `--format` option. The
-	`<when>` field must be one of `always`, `never`, or `auto` (if
-	`<when>` is absent, behave as if `always` was given).
-
---shell::
---perl::
---python::
---tcl::
-	If given, strings that substitute `%(fieldname)`
-	placeholders are quoted as string literals suitable for
-	the specified host language.  This is meant to produce
-	a scriptlet that can directly be `eval`ed.
-
---points-at=<object>::
-	Only list refs which points at the given object.
-
---merged[=<object>]::
-	Only list refs whose tips are reachable from the
-	specified commit (HEAD if not specified).
-
---no-merged[=<object>]::
-	Only list refs whose tips are not reachable from the
-	specified commit (HEAD if not specified).
-
---contains[=<object>]::
-	Only list refs which contain the specified commit (HEAD if not
-	specified).
-
---no-contains[=<object>]::
-	Only list refs which don't contain the specified commit (HEAD
-	if not specified).
-
---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.
-
---exclude=<pattern>::
-	If one or more patterns are given, only refs which do not match
-	any excluded pattern(s) are shown. Matching is done using the
-	same rules as `<pattern>` above.
-
---include-root-refs::
-	List root refs (HEAD and pseudorefs) apart from regular refs.
-
---start-after=<marker>::
-    Allows paginating the output by skipping references up to and including the
-    specified marker. When paging, it should be noted that references may be
-    deleted, modified or added between invocations. Output will only yield those
-    references which follow the marker lexicographically. Output begins from the
-    first reference that would come after the marker alphabetically. Cannot be
-    used with `--sort=<key>` or `--stdin` options, or the _<pattern>_ argument(s)
-    to limit the refs.
+include::for-each-ref-options.adoc[]
 
 FIELD NAMES
 -----------
@@ -126,44 +39,44 @@
 
 For all objects, the following names can be used:
 
-refname::
-	The name of the ref (the part after $GIT_DIR/).
+`refname`::
+	The name of the ref (the part after `$GIT_DIR/`).
 	For a non-ambiguous short name of the ref append `:short`.
-	The option core.warnAmbiguousRefs is used to select the strict
-	abbreviation mode. If `lstrip=<N>` (`rstrip=<N>`) is appended, strips `<N>`
+	The option `core.warnAmbiguousRefs` is used to select the strict
+	abbreviation mode. If `lstrip=<n>` (`rstrip=<n>`) is appended, strip _<n>_
 	slash-separated path components from the front (back) of the refname
 	(e.g. `%(refname:lstrip=2)` turns `refs/tags/foo` into `foo` and
 	`%(refname:rstrip=2)` turns `refs/tags/foo` into `refs`).
-	If `<N>` is a negative number, strip as many path components as
-	necessary from the specified end to leave `-<N>` path components
+	If _<n>_ is a negative number, strip as many path components as
+	necessary from the specified end to leave `-<n>` path components
 	(e.g. `%(refname:lstrip=-2)` turns
 	`refs/tags/foo` into `tags/foo` and `%(refname:rstrip=-1)`
 	turns `refs/tags/foo` into `refs`). When the ref does not have
 	enough components, the result becomes an empty string if
-	stripping with positive <N>, or it becomes the full refname if
-	stripping with negative <N>.  Neither is an error.
+	stripping with positive _<n>_, or it becomes the full refname if
+	stripping with negative _<N>_.  Neither is an error.
 +
 `strip` can be used as a synonym to `lstrip`.
 
-objecttype::
+`objecttype`::
 	The type of the object (`blob`, `tree`, `commit`, `tag`).
 
-objectsize::
+`objectsize`::
 	The size of the object (the same as 'git cat-file -s' reports).
 	Append `:disk` to get the size, in bytes, that the object takes up on
-	disk. See the note about on-disk sizes in the `CAVEATS` section below.
-objectname::
+	disk. See the note about on-disk sizes in the 'CAVEATS' section below.
+`objectname`::
 	The object name (aka SHA-1).
 	For a non-ambiguous abbreviation of the object name append `:short`.
 	For an abbreviation of the object name with desired length append
-	`:short=<length>`, where the minimum length is MINIMUM_ABBREV. The
+	`:short=<length>`, where the minimum length is `MINIMUM_ABBREV`. The
 	length may be exceeded to ensure unique object names.
-deltabase::
+`deltabase`::
 	This expands to the object name of the delta base for the
 	given object, if it is stored as a delta.  Otherwise it
 	expands to the null object name (all zeroes).
 
-upstream::
+`upstream`::
 	The name of a local ref which can be considered ``upstream''
 	from the displayed ref. Respects `:short`, `:lstrip` and
 	`:rstrip` in the same way as `refname` above.  Additionally
@@ -185,100 +98,103 @@
 with it.  All the options apart from `nobracket` are mutually exclusive,
 but if used together the last option is selected.
 
-push::
+`push`::
 	The name of a local ref which represents the `@{push}`
 	location for the displayed ref. Respects `:short`, `:lstrip`,
 	`:rstrip`, `:track`, `:trackshort`, `:remotename`, and `:remoteref`
 	options as `upstream` does. Produces an empty string if no `@{push}`
 	ref is configured.
 
-HEAD::
-	'*' if HEAD matches current ref (the checked out branch), ' '
+`HEAD`::
+	`*` if `HEAD` matches current ref (the checked out branch), ' '
 	otherwise.
 
-color::
+`color`::
 	Change output color. Followed by `:<colorname>`, where color
 	names are described under Values in the "CONFIGURATION FILE"
 	section of linkgit:git-config[1].  For example,
 	`%(color:bold red)`.
 
-align::
+`align`::
 	Left-, middle-, or right-align the content between
-	%(align:...) and %(end). The "align:" is followed by
+	`%(align:...)` and `%(end)`. The "`align:`" is followed by
 	`width=<width>` and `position=<position>` in any order
-	separated by a comma, where the `<position>` is either left,
-	right or middle, default being left and `<width>` is the total
+	separated by a comma, where the _<position>_ is either `left`,
+	`right` or `middle`, default being `left` and _<width>_ is the total
 	length of the content with alignment. For brevity, the
 	"width=" and/or "position=" prefixes may be omitted, and bare
-	<width> and <position> used instead.  For instance,
+	_<width>_ and _<position>_ used instead.  For instance,
 	`%(align:<width>,<position>)`. If the contents length is more
 	than the width then no alignment is performed. If used with
-	`--quote` everything in between %(align:...) and %(end) is
+	`--quote` everything in between `%(align:...)` and `%(end)` is
 	quoted, but if nested then only the topmost level performs
 	quoting.
 
-if::
-	Used as %(if)...%(then)...%(end) or
-	%(if)...%(then)...%(else)...%(end).  If there is an atom with
-	value or string literal after the %(if) then everything after
-	the %(then) is printed, else if the %(else) atom is used, then
+`if`::
+	Used as `%(if)...%(then)...%(end)` or
+	`%(if)...%(then)...%(else)...%(end)`.  If there is an atom with
+	value or string literal after the `%(if)` then everything after
+	the `%(then)` is printed, else if the `%(else)` atom is used, then
 	everything after %(else) is printed. We ignore space when
-	evaluating the string before %(then), this is useful when we
-	use the %(HEAD) atom which prints either "*" or " " and we
-	want to apply the 'if' condition only on the 'HEAD' ref.
-	Append ":equals=<string>" or ":notequals=<string>" to compare
-	the value between the %(if:...) and %(then) atoms with the
+	evaluating the string before `%(then)`, this is useful when we
+	use the `%(HEAD)` atom which prints either "`*`" or " " and we
+	want to apply the 'if' condition only on the `HEAD` ref.
+	Append "`:equals=<string>`" or "`:notequals=<string>`" to compare
+	the value between the `%(if:...)` and `%(then)` atoms with the
 	given string.
 
-symref::
+`symref`::
 	The ref which the given symbolic ref refers to. If not a
 	symbolic ref, nothing is printed. Respects the `:short`,
 	`:lstrip` and `:rstrip` options in the same way as `refname`
 	above.
 
-signature::
+`signature`::
 	The GPG signature of a commit.
 
-signature:grade::
-	Show "G" for a good (valid) signature, "B" for a bad
-	signature, "U" for a good signature with unknown validity, "X"
-	for a good signature that has expired, "Y" for a good
-	signature made by an expired key, "R" for a good signature
-	made by a revoked key, "E" if the signature cannot be
-	checked (e.g. missing key) and "N" for no signature.
+`signature:grade`::
+	Show
+`G`;; for a good (valid) signature
+`B`;; for a bad signature
+`U`;; for a good signature with unknown validity
+`X`;;	for a good signature that has expired
+`Y`;; for a good signature made by an expired key
+`R`;; for a good signature made by a revoked key
+`E`;; if the signature cannot be checked (e.g. missing key)
+`N`;; for no signature.
 
-signature:signer::
+`signature:signer`::
 	The signer of the GPG signature of a commit.
 
-signature:key::
+`signature:key`::
 	The key of the GPG signature of a commit.
 
-signature:fingerprint::
+`signature:fingerprint`::
 	The fingerprint of the GPG signature of a commit.
 
-signature:primarykeyfingerprint::
+`signature:primarykeyfingerprint`::
 	The primary key fingerprint of the GPG signature of a commit.
 
-signature:trustlevel::
+`signature:trustlevel`::
 	The trust level of the GPG signature of a commit. Possible
 	outputs are `ultimate`, `fully`, `marginal`, `never` and `undefined`.
 
-worktreepath::
+`worktreepath`::
 	The absolute path to the worktree in which the ref is checked
 	out, if it is checked out in any linked worktree. Empty string
 	otherwise.
 
-ahead-behind:<committish>::
+`ahead-behind:<commit-ish>`::
 	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.
+	ref to the _<committish>_ specified in the format.
 
-is-base:<committish>::
-	In at most one row, `(<committish>)` will appear to indicate the ref
+`is-base:<commit-ish>`::
+	In at most one row, `(<commit-ish>)` will appear to indicate the ref
 	that is most likely the ref used as a starting point for the branch
-	that produced `<committish>`. This choice is made using a heuristic:
+	that produced _<commit-ish>_. This choice is made using a heuristic:
 	choose the ref that minimizes the number of commits in the
-	first-parent history of `<committish>` and not in the first-parent
+	first-parent history of _<commit-ish>_ and not in the first-parent
 	history of the ref.
 +
 For example, consider the following figure of first-parent histories of
@@ -312,29 +228,29 @@
 earliest ref in the sorted order.
 +
 Note that this token will not appear if the first-parent history of
-`<committish>` does not intersect the first-parent histories of the
+_<commit-ish>_ does not intersect the first-parent histories of the
 filtered refs.
 
-describe[:options]::
+`describe[:<option>,...]`::
 	A human-readable name, like linkgit:git-describe[1];
 	empty string for undescribable commits. The `describe` string may
 	be followed by a colon and one or more comma-separated options.
 +
 --
-tags=<bool-value>;;
+`tags=<bool-value>`;;
 	Instead of only considering annotated tags, consider
 	lightweight tags as well; see the corresponding option in
 	linkgit:git-describe[1] for details.
-abbrev=<number>;;
-	Use at least <number> hexadecimal digits; see the corresponding
+`abbrev=<number>`;;
+	Use at least _<number>_ hexadecimal digits; see the corresponding
 	option in linkgit:git-describe[1] for details.
-match=<pattern>;;
-	Only consider tags matching the given `glob(7)` pattern,
-	excluding the "refs/tags/" prefix; see the corresponding option
+`match=<pattern>`;;
+	Only consider tags matching the `glob`(7) _<pattern>_,
+	excluding the `refs/tags/` prefix; see the corresponding option
 	in linkgit:git-describe[1] for details.
-exclude=<pattern>;;
-	Do not consider tags matching the given `glob(7)` pattern,
-	excluding the "refs/tags/" prefix; see the corresponding option
+`exclude=<pattern>`;;
+	Do not consider tags matching the `glob`(7) _<pattern>_,
+	excluding the `refs/tags/` prefix; see the corresponding option
 	in linkgit:git-describe[1] for details.
 --
 
@@ -366,7 +282,7 @@
 
 The raw data in an object is `raw`.
 
-raw:size::
+`raw:size`::
 	The raw data size of the object.
 
 Note that `--format=%(raw)` can not be used with `--python`, `--shell`, `--tcl`,
@@ -376,10 +292,10 @@
 The message in a commit or a tag object is `contents`, from which
 `contents:<part>` can be used to extract various parts out of:
 
-contents:size::
+`contents:size`::
 	The size in bytes of the commit or tag message.
 
-contents:subject::
+`contents:subject`::
 	The first paragraph of the message, which typically is a
 	single line, is taken as the "subject" of the commit or the
 	tag message.
@@ -387,19 +303,19 @@
 	obtain same results. `:sanitize` can be appended to `subject` for
 	subject line suitable for filename.
 
-contents:body::
+`contents:body`::
 	The remainder of the commit or the tag message that follows
 	the "subject".
 
-contents:signature::
+`contents:signature`::
 	The optional GPG signature of the tag.
 
-contents:lines=N::
-	The first `N` lines of the message.
+`contents:lines=<n>`::
+	The first _<n>_ lines of the message.
 
 Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1]
-are obtained as `trailers[:options]` (or by using the historical alias
-`contents:trailers[:options]`). For valid [:option] values see `trailers`
+are obtained as `trailers[:<option>,...]` (or by using the historical alias
+`contents:trailers[:<option>,...]`). For valid _<option>_ values see `trailers`
 section of linkgit:git-log[1].
 
 For sorting purposes, fields with numeric values sort in numeric order
@@ -419,8 +335,8 @@
 a `--sort` key, references will be sorted according to the byte-value of the
 formatted string rather than the numeric value of the underlying timestamp.
 
-Some atoms like %(align) and %(if) always require a matching %(end).
-We call them "opening atoms" and sometimes denote them as %($open).
+Some atoms like `%(align)` and `%(if)` always require a matching `%(end)`.
+We call them "opening atoms" and sometimes denote them as `%($open)`.
 
 When a scripting language specific quoting is in effect, everything
 between a top-level opening atom and its matching %(end) is evaluated
@@ -438,7 +354,7 @@
 #!/bin/sh
 
 git for-each-ref --count=3 --sort='-*authordate' \
---format='From: %(*authorname) %(*authoremail)
+`--format='From: %(*authorname) %(*authoremail)
 Subject: %(*subject)
 Date: %(*authordate)
 Ref: %(*refname)
@@ -449,7 +365,7 @@
 
 
 A simple example showing the use of shell eval on the output,
-demonstrating the use of --shell.  List the prefixes of all heads:
+demonstrating the use of `--shell`.  List the prefixes of all heads:
 
 ------------
 #!/bin/sh
@@ -517,7 +433,7 @@
 ------------
 
 
-An example to show the usage of %(if)...%(then)...%(else)...%(end).
+An example to show the usage of `%(if)...%(then)...%(else)...%(end)`.
 This prefixes the current branch with a star.
 
 ------------
@@ -525,7 +441,7 @@
 ------------
 
 
-An example to show the usage of %(if)...%(then)...%(end).
+An example to show the usage of `%(if)...%(then)...%(end)`.
 This prints the authorname, if present.
 
 ------------
diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc
index a9cf371..9a7807c 100644
--- a/Documentation/git-format-patch.adoc
+++ b/Documentation/git-format-patch.adoc
@@ -295,7 +295,8 @@
 transformation for you, and this option should not be used if you are
 feeding the result to `git send-email`.
 
---[no-]force-in-body-from::
+--force-in-body-from::
+--no-force-in-body-from::
 	With the e-mail sender specified via the `--from` option, by
 	default, an in-body "From:" to identify the real author of
 	the commit is added at the top of the commit log message if
@@ -314,7 +315,8 @@
 	`Cc:`, and custom) headers added so far from config or command
 	line.
 
---[no-]cover-letter::
+--cover-letter::
+--no-cover-letter::
 	In addition to the patches, generate a cover letter file
 	containing the branch description, shortlog and the overall diffstat.  You can
 	fill in a description in the file before sending it out.
@@ -379,7 +381,8 @@
 The default is `--no-notes`, unless the `format.notes` configuration is
 set.
 
---[no-]signature=<signature>::
+--signature=<signature>::
+--no-signature::
 	Add a signature to each message produced. Per RFC 3676 the signature
 	is separated from the body by a line with '-- ' on it. If the
 	signature option is omitted the signature defaults to the Git version
@@ -411,7 +414,8 @@
   Output an all-zero hash in each patch's From header instead
   of the hash of the commit.
 
---[no-]base[=<commit>]::
+--no-base::
+--base[=<commit>]::
 	Record the base tree information to identify the state the
 	patch series applies to.  See the BASE TREE INFORMATION section
 	below for details. If <commit> is "auto", a base commit is
diff --git a/Documentation/git-fsck.adoc b/Documentation/git-fsck.adoc
index 11203ba..1751f69 100644
--- a/Documentation/git-fsck.adoc
+++ b/Documentation/git-fsck.adoc
@@ -31,7 +31,8 @@
 	Print out objects that exist but that aren't reachable from any
 	of the reference nodes.
 
---[no-]dangling::
+--dangling::
+--no-dangling::
 	Print objects that exist but that are never 'directly' used (default).
 	`--no-dangling` can be used to omit this information from the output.
 
@@ -97,14 +98,16 @@
 	compatible with linkgit:git-rev-parse[1], e.g.
 	`HEAD@{1234567890}~25^2:src/`.
 
---[no-]progress::
+--progress::
+--no-progress::
 	Progress status is reported on the standard error stream by
 	default when it is attached to a terminal, unless
 	--no-progress or --verbose is specified. --progress forces
 	progress status even if the standard error stream is not
 	directed to a terminal.
 
---[no-]references::
+--references::
+--no-references::
 	Control whether to check the references database consistency
 	via 'git refs verify'. See linkgit:git-refs[1] for details.
 	The default is to check the references database.
diff --git a/Documentation/git-gc.adoc b/Documentation/git-gc.adoc
index 526ce01..6fed646 100644
--- a/Documentation/git-gc.adoc
+++ b/Documentation/git-gc.adoc
@@ -53,11 +53,13 @@
 other housekeeping tasks (e.g. rerere, working trees, reflog...) will
 be performed as well.
 
---[no-]detach::
+--detach::
+--no-detach::
 	Run in the background if the system supports it. This option overrides
 	the `gc.autoDetach` config.
 
---[no-]cruft::
+--cruft::
+--no-cruft::
 	When expiring unreachable objects, pack them separately into a
 	cruft pack instead of storing them as loose objects. `--cruft`
 	is on by default.
diff --git a/Documentation/git-http-fetch.adoc b/Documentation/git-http-fetch.adoc
index 4ec7c68..2200f07 100644
--- a/Documentation/git-http-fetch.adoc
+++ b/Documentation/git-http-fetch.adoc
@@ -25,8 +25,11 @@
         Either the hash or the filename under [URL]/refs/ to
         pull.
 
--a, -c, -t::
+-a::
+-c::
+-t::
 	These options are ignored for historical reasons.
+
 -v::
 	Report what is downloaded.
 
diff --git a/Documentation/git-index-pack.adoc b/Documentation/git-index-pack.adoc
index 270056c..1803695 100644
--- a/Documentation/git-index-pack.adoc
+++ b/Documentation/git-index-pack.adoc
@@ -36,7 +36,8 @@
 	fails if the name of packed archive does not end
 	with .pack).
 
---[no-]rev-index::
+--rev-index::
+--no-rev-index::
 	When this flag is provided, generate a reverse index
 	(a `.rev` file) corresponding to the given pack. If
 	`--verify` is given, ensure that the existing
diff --git a/Documentation/git-init.adoc b/Documentation/git-init.adoc
index a0dffba..bab99b9 100644
--- a/Documentation/git-init.adoc
+++ b/Documentation/git-init.adoc
@@ -77,9 +77,15 @@
 `-b <branch-name>`::
 `--initial-branch=<branch-name>`::
 Use _<branch-name>_ for the initial branch in the newly created
-repository.  If not specified, fall back to the default name (currently
-`master`, but this is subject to change in the future; the name can be
-customized via the `init.defaultBranch` configuration variable).
+repository.  If not specified, fall back to the default name
+ifndef::with-breaking-changes[]
+(currently `master`, but this will change to `main` when Git 3.0 is released).
+endif::with-breaking-changes[]
+ifdef::with-breaking-changes[]
+`main`.
+endif::with-breaking-changes[]
+The default name can be customized via the `init.defaultBranch` configuration
+variable.
 
 `--shared[=(false|true|umask|group|all|world|everybody|<perm>)]`::
 
diff --git a/Documentation/git-last-modified.adoc b/Documentation/git-last-modified.adoc
new file mode 100644
index 0000000..602843e
--- /dev/null
+++ b/Documentation/git-last-modified.adoc
@@ -0,0 +1,54 @@
+git-last-modified(1)
+====================
+
+NAME
+----
+git-last-modified - EXPERIMENTAL: Show when files were last modified
+
+
+SYNOPSIS
+--------
+[synopsis]
+git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] <path>...]
+
+DESCRIPTION
+-----------
+
+Shows which commit last modified each of the relevant files and subdirectories.
+A commit renaming a path, or changing it's mode is also taken into account.
+
+THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
+
+OPTIONS
+-------
+
+`-r`::
+`--recursive`::
+	Instead of showing tree entries, step into subtrees and show all entries
+	inside them recursively.
+
+`-t`::
+`--show-trees`::
+	Show tree entries even when recursing into them. It has no effect
+	without `--recursive`.
+
+`<revision-range>`::
+	Only traverse commits in the specified revision range. When no
+	`<revision-range>` is specified, it defaults to `HEAD` (i.e. the whole
+	history leading to the current commit). For a complete list of ways to
+	spell `<revision-range>`, see the 'Specifying Ranges' section of
+	linkgit:gitrevisions[7].
+
+`[--] <path>...`::
+	For each _<path>_ given, the commit which last modified it is returned.
+	Without an optional path parameter, all files and subdirectories
+	in path traversal the are included in the output.
+
+SEE ALSO
+--------
+linkgit:git-blame[1],
+linkgit:git-log[1].
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-log.adoc b/Documentation/git-log.adoc
index b6f3d92..e304739 100644
--- a/Documentation/git-log.adoc
+++ b/Documentation/git-log.adoc
@@ -73,8 +73,10 @@
 	Print out the ref name given on the command line by which each
 	commit was reached.
 
-`--[no-]mailmap`::
-`--[no-]use-mailmap`::
+`--mailmap`::
+`--no-mailmap`::
+`--use-mailmap`::
+`--no-use-mailmap`::
 	Use mailmap file to map author and committer names and email
 	addresses to canonical real names and email addresses. See
 	linkgit:git-shortlog[1].
diff --git a/Documentation/git-maintenance.adoc b/Documentation/git-maintenance.adoc
index 540b5cf..bda616f 100644
--- a/Documentation/git-maintenance.adoc
+++ b/Documentation/git-maintenance.adoc
@@ -12,6 +12,7 @@
 'git maintenance' run [<options>]
 'git maintenance' start [--scheduler=<scheduler>]
 'git maintenance' (stop|register|unregister) [<options>]
+'git maintenance' is-needed [<options>]
 
 
 DESCRIPTION
@@ -84,6 +85,16 @@
 is not already registered. Use the `--force` option to return success even
 when the current repository is not registered.
 
+is-needed::
+    Check whether maintenance needs to be run without actually running it.
+    Exits with a 0 status code if maintenance needs to be run, 1 otherwise.
+    Ideally used with the '--auto' flag.
++
+If one or more `--task` options are specified, then those tasks are checked
+in that order. Otherwise, the tasks are determined by which
+`maintenance.<task>.enabled` config options are true. By default, only
+`maintenance.gc.enabled` is true.
+
 TASKS
 -----
 
@@ -183,6 +194,8 @@
 	in the `gc.auto` config setting, or when the number of pack-files
 	exceeds the `gc.autoPackLimit` config setting. Not compatible with
 	the `--schedule` option.
+	When combined with the `is-needed` subcommand, check if the required
+	thresholds are met without actually running maintenance.
 
 --schedule::
 	When combined with the `run` subcommand, run maintenance tasks
diff --git a/Documentation/git-merge-tree.adoc b/Documentation/git-merge-tree.adoc
index 4e13ed3..4391bbe 100644
--- a/Documentation/git-merge-tree.adoc
+++ b/Documentation/git-merge-tree.adoc
@@ -59,7 +59,8 @@
 	do not list filenames multiple times if they have multiple
 	conflicting stages).
 
---[no-]messages::
+--messages::
+--no-messages::
 	Write any informational messages such as "Auto-merging <path>"
 	or CONFLICT notices to the end of stdout.  If unspecified, the
 	default is to include these messages if there are merge
diff --git a/Documentation/git-multi-pack-index.adoc b/Documentation/git-multi-pack-index.adoc
index 85be5b8..2f64269 100644
--- a/Documentation/git-multi-pack-index.adoc
+++ b/Documentation/git-multi-pack-index.adoc
@@ -25,7 +25,8 @@
 +
 `<dir>` must be an alternate of the current repository.
 
---[no-]progress::
+--progress::
+--no-progress::
 	Turn progress on/off explicitly. If neither is specified, progress is
 	shown if standard error is connected to a terminal. Supported by
 	sub-commands `write`, `verify`, `expire`, and `repack`.
diff --git a/Documentation/git-p4.adoc b/Documentation/git-p4.adoc
index f97b786..59edd24 100644
--- a/Documentation/git-p4.adoc
+++ b/Documentation/git-p4.adoc
@@ -66,6 +66,7 @@
 ~~~~~
 Generally, 'git p4 clone' is used to create a new Git directory
 from an existing p4 repository:
+
 ------------
 $ git p4 clone //depot/path/project
 ------------
diff --git a/Documentation/git-pack-objects.adoc b/Documentation/git-pack-objects.adoc
index eba014c..71b9682 100644
--- a/Documentation/git-pack-objects.adoc
+++ b/Documentation/git-pack-objects.adoc
@@ -243,7 +243,8 @@
 	Add --no-reuse-object if you want to force a uniform compression
 	level on all data no matter the source.
 
---[no-]sparse::
+--sparse::
+--no-sparse::
 	Toggle the "sparse" algorithm to determine which objects to include in
 	the pack, when combined with the "--revs" option. This algorithm
 	only walks trees that appear in paths that introduce new objects.
diff --git a/Documentation/git-pack-refs.adoc b/Documentation/git-pack-refs.adoc
index 42b9005..fde9f2f 100644
--- a/Documentation/git-pack-refs.adoc
+++ b/Documentation/git-pack-refs.adoc
@@ -45,58 +45,7 @@
 OPTIONS
 -------
 
---all::
-
-The command by default packs all tags and refs that are already
-packed, and leaves other refs
-alone.  This is because branches are expected to be actively
-developed and packing their tips does not help performance.
-This option causes all refs to be packed as well, with the exception
-of hidden refs, broken refs, and symbolic refs. Useful for a repository
-with many branches of historical interests.
-
---no-prune::
-
-The command usually removes loose refs under `$GIT_DIR/refs`
-hierarchy after packing them.  This option tells it not to.
-
---auto::
-
-Pack refs as needed depending on the current state of the ref database. The
-behavior depends on the ref format used by the repository and may change in the
-future.
-+
-	- "files": Loose references are packed into the `packed-refs` file
-	  based on the ratio of loose references to the size of the
-	  `packed-refs` file. The bigger the `packed-refs` file, the more loose
-	  references need to exist before we repack.
-+
-	- "reftable": Tables are compacted such that they form a geometric
-	  sequence. For two tables N and N+1, where N+1 is newer, this
-	  maintains the property that N is at least twice as big as N+1. Only
-	  tables that violate this property are compacted.
-
---include <pattern>::
-
-Pack refs based on a `glob(7)` pattern. Repetitions of this option
-accumulate inclusion patterns. If a ref is both included in `--include` and
-`--exclude`, `--exclude` takes precedence. Using `--include` will preclude all
-tags from being included by default. Symbolic refs and broken refs will never
-be packed. When used with `--all`, it will be a noop. Use `--no-include` to clear
-and reset the list of patterns.
-
---exclude <pattern>::
-
-Do not pack refs matching the given `glob(7)` pattern. Repetitions of this option
-accumulate exclusion patterns. Use `--no-exclude` to clear and reset the list of
-patterns. If a ref is already packed, including it with `--exclude` will not
-unpack it.
-+
-When used with `--all`, pack only loose refs which do not match any of
-the provided `--exclude` patterns.
-+
-When used with `--include`, refs provided to `--include`, minus refs that are
-provided to `--exclude` will be packed.
+include::pack-refs-options.adoc[]
 
 
 BUGS
diff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc
index 45da0f2..92a1af3 100644
--- a/Documentation/git-patch-id.adoc
+++ b/Documentation/git-patch-id.adoc
@@ -7,8 +7,8 @@
 
 SYNOPSIS
 --------
-[verse]
-'git patch-id' [--stable | --unstable | --verbatim]
+[synopsis]
+git patch-id [--stable | --unstable | --verbatim]
 
 DESCRIPTION
 -----------
@@ -21,7 +21,7 @@
 
 The main usecase for this command is to look for likely duplicate commits.
 
-When dealing with 'git diff-tree' output, it takes advantage of
+When dealing with `git diff-tree` output, it takes advantage of
 the fact that the patch is prefixed with the object name of the
 commit, and outputs two 40-byte hexadecimal strings.  The first
 string is the patch ID, and the second string is the commit ID.
@@ -30,35 +30,35 @@
 OPTIONS
 -------
 
---verbatim::
+`--verbatim`::
 	Calculate the patch-id of the input as it is given, do not strip
 	any whitespace.
 +
-This is the default if patchid.verbatim is true.
+This is the default if `patchid.verbatim` is `true`.
 
---stable::
+`--stable`::
 	Use a "stable" sum of hashes as the patch ID. With this option:
 +
 --
 - Reordering file diffs that make up a patch does not affect the ID.
   In particular, two patches produced by comparing the same two trees
-  with two different settings for "-O<orderfile>" result in the same
+  with two different settings for `-O<orderfile>` result in the same
   patch ID signature, thereby allowing the computed result to be used
   as a key to index some meta-information about the change between
   the two trees;
 
 - Result is different from the value produced by git 1.9 and older
-  or produced when an "unstable" hash (see --unstable below) is
+  or produced when an "unstable" hash (see `--unstable` below) is
   configured - even when used on a diff output taken without any use
-  of "-O<orderfile>", thereby making existing databases storing such
+  of `-O<orderfile>`, thereby making existing databases storing such
   "unstable" or historical patch-ids unusable.
 
 - All whitespace within the patch is ignored and does not affect the id.
 --
 +
-This is the default if patchid.stable is set to true.
+This is the default if `patchid.stable` is set to `true`.
 
---unstable::
+`--unstable`::
 	Use an "unstable" hash as the patch ID. With this option,
 	the result produced is compatible with the patch-id value produced
 	by git 1.9 and older and whitespace is ignored.  Users with pre-existing
diff --git a/Documentation/git-pull.adoc b/Documentation/git-pull.adoc
index 3f4ecc4..cd3bbc9 100644
--- a/Documentation/git-pull.adoc
+++ b/Documentation/git-pull.adoc
@@ -15,68 +15,54 @@
 DESCRIPTION
 -----------
 
-Incorporates changes from a remote repository into the current branch.
-If the current branch is behind the remote, then by default it will
-fast-forward the current branch to match the remote.  If the current
-branch and the remote have diverged, the user needs to specify how to
-reconcile the divergent branches with `--rebase` or `--no-rebase` (or
-the corresponding configuration option in `pull.rebase`).
+Integrate changes from a remote repository into the current branch.
 
-More precisely, `git pull` runs `git fetch` with the given parameters
-and then depending on configuration options or command line flags,
-will call either `git rebase` or `git merge` to reconcile diverging
-branches.
+First, `git pull` runs `git fetch` with the same arguments
+(excluding merge options) to fetch remote branch(es).
+Then it decides which remote branch to integrate: if you run `git pull`
+with no arguments this defaults to the <<UPSTREAM-BRANCHES,upstream>>
+for the current branch.
+Then it integrates that branch into the current branch.
 
-<repository> should be the name of a remote repository as
-passed to linkgit:git-fetch[1].  <refspec> can name an
-arbitrary remote ref (for example, the name of a tag) or even
-a collection of refs with corresponding remote-tracking branches
-(e.g., refs/heads/{asterisk}:refs/remotes/origin/{asterisk}),
-but usually it is the name of a branch in the remote repository.
+There are 4 main options for integrating the remote branch:
 
-Default values for <repository> and <branch> are read from the
-"remote" and "merge" configuration for the current branch
-as set by linkgit:git-branch[1] `--track`.
+1. `git pull --ff-only` will only do "fast-forward" updates: it
+   fails if your local branch has diverged from the remote branch.
+   This is the default.
+2. `git pull --rebase` runs `git rebase`
+3. `git pull --no-rebase` runs `git merge`.
+4. `git pull --squash` runs `git merge --squash`
 
-Assume the following history exists and the current branch is
-"`master`":
+You can also set the configuration options `pull.rebase`, `pull.squash`,
+or `pull.ff` with your preferred behaviour.
 
-------------
-	  A---B---C master on origin
-	 /
-    D---E---F---G master
-	^
-	origin/master in your repository
-------------
-
-Then "`git pull`" will fetch and replay the changes from the remote
-`master` branch since it diverged from the local `master` (i.e., `E`)
-until its current commit (`C`) on top of `master` and record the
-result in a new commit along with the names of the two parent commits
-and a log message from the user describing the changes.
-
-------------
-	  A---B---C origin/master
-	 /         \
-    D---E---F---G---H master
-------------
-
-See linkgit:git-merge[1] for details, including how conflicts
-are presented and handled.
-
-In Git 1.7.0 or later, to cancel a conflicting merge, use
-`git reset --merge`.  *Warning*: In older versions of Git, running 'git pull'
-with uncommitted changes is discouraged: while possible, it leaves you
-in a state that may be hard to back out of in the case of a conflict.
-
-If any of the remote changes overlap with local uncommitted changes,
-the merge will be automatically canceled and the work tree untouched.
-It is generally best to get any local changes in working order before
-pulling or stash them away with linkgit:git-stash[1].
+If there's a merge conflict during the merge or rebase that you don't
+want to handle, you can safely abort it with `git merge --abort` or `git
+--rebase abort`.
 
 OPTIONS
 -------
 
+<repository>::
+	The "remote" repository to pull from.  This can be either
+	a URL (see the section <<URLS,GIT URLS>> below) or the name
+	of a remote (see the section <<REMOTES,REMOTES>> below).
++
+Defaults to the configured upstream for the current branch, or `origin`.
+See <<UPSTREAM-BRANCHES,UPSTREAM BRANCHES>> below for more on how to
+configure upstreams.
+
+<refspec>::
+	Which branch or other reference(s) to fetch and integrate into the
+	current branch, for example `main` in `git pull origin main`.
+	Defaults to the configured upstream for the current branch.
++
+This can be a branch, tag, or other collection of reference(s).
+See <<fetch-refspec,<refspec>>> below under "Options related to fetching"
+for the full syntax, and <<DEFAULT-BEHAVIOUR,DEFAULT BEHAVIOUR>> below
+for how `git pull` uses this argument to determine which remote branch
+to integrate.
+
 -q::
 --quiet::
 	This is passed to both underlying git-fetch to squelch reporting of
@@ -87,7 +73,8 @@
 --verbose::
 	Pass --verbose to git-fetch and git-merge.
 
---[no-]recurse-submodules[=(yes|on-demand|no)]::
+--recurse-submodules[=(yes|on-demand|no)]::
+--no-recurse-submodules::
 	This option controls if new commits of populated submodules should
 	be fetched, and if the working trees of active submodules should be
 	updated, too (see linkgit:git-fetch[1], linkgit:git-config[1] and
@@ -144,6 +131,7 @@
 
 include::merge-strategies.adoc[]
 
+[[DEFAULT-BEHAVIOUR]]
 DEFAULT BEHAVIOUR
 -----------------
 
diff --git a/Documentation/git-push.adoc b/Documentation/git-push.adoc
index d197865..864b0d0 100644
--- a/Documentation/git-push.adoc
+++ b/Documentation/git-push.adoc
@@ -19,31 +19,36 @@
 DESCRIPTION
 -----------
 
-Updates remote refs using local refs, while sending objects
-necessary to complete the given refs.
+Updates one or more branches, tags, or other references in a remote
+repository from your local repository, and sends all necessary data
+that isn't already on the remote.
+
+The simplest way to push is `git push <remote> <branch>`.
+`git push origin main` will push the local `main` branch to the `main`
+branch on the remote named `origin`.
+
+The `<repository>` argument defaults to the upstream for the current branch,
+or `origin` if there's no configured upstream.
+
+To decide which branches, tags, or other refs to push, Git uses
+(in order of precedence):
+
+1. The `<refspec>` argument(s) (for example `main` in `git push origin main`)
+   or the `--all`, `--mirror`, or `--tags` options
+2. The `remote.*.push` configuration for the repository being pushed to
+3. The `push.default` configuration. The default is `push.default=simple`,
+   which will push to a branch with the same name as the current branch.
+   See the <<CONFIGURATION,CONFIGURATION>> section below for more on `push.default`.
+
+`git push` may fail if you haven't set an upstream for the current branch,
+depending on what `push.default` is set to.
+See the <<UPSTREAM-BRANCHES,UPSTREAM BRANCHES>> section below for more
+on how to set and use upstreams.
 
 You can make interesting things happen to a repository
 every time you push into it, by setting up 'hooks' there.  See
 documentation for linkgit:git-receive-pack[1].
 
-When the command line does not specify where to push with the
-`<repository>` argument, `branch.*.remote` configuration for the
-current branch is consulted to determine where to push.  If the
-configuration is missing, it defaults to 'origin'.
-
-When the command line does not specify what to push with `<refspec>...`
-arguments or `--all`, `--mirror`, `--tags` options, the command finds
-the default `<refspec>` by consulting `remote.*.push` configuration,
-and if it is not found, honors `push.default` configuration to decide
-what to push (See linkgit:git-config[1] for the meaning of `push.default`).
-
-When neither the command-line nor the configuration specifies what to
-push, the default behavior is used, which corresponds to the `simple`
-value for `push.default`: the current branch is pushed to the
-corresponding upstream branch, but as a safety measure, the push is
-aborted if the upstream branch does not have the same name as the
-local one.
-
 
 OPTIONS[[OPTIONS]]
 ------------------
@@ -55,96 +60,66 @@
 
 <refspec>...::
 	Specify what destination ref to update with what source object.
-	The format of a <refspec> parameter is an optional plus
-	`+`, followed by the source object <src>, followed
-	by a colon `:`, followed by the destination ref <dst>.
 +
-The <src> is often the name of the branch you would want to push, but
-it can be any arbitrary "SHA-1 expression", such as `master~4` or
-`HEAD` (see linkgit:gitrevisions[7]).
+The format for a refspec is [+]<src>[:<dst>], for example `main`,
+`main:other`, or `HEAD^:refs/heads/main`.
 +
-The <dst> tells which ref on the remote side is updated with this
-push. Arbitrary expressions cannot be used here, an actual ref must
-be named.
-If `git push [<repository>]` without any `<refspec>` argument is set to
-update some ref at the destination with `<src>` with
-`remote.<repository>.push` configuration variable, `:<dst>` part can
-be omitted--such a push will update a ref that `<src>` normally updates
-without any `<refspec>` on the command line.  Otherwise, missing
-`:<dst>` means to update the same ref as the `<src>`.
+The `<src>` is often the name of the local branch to push, but it can be
+any arbitrary "SHA-1 expression" (see linkgit:gitrevisions[7]).
 +
-If <dst> doesn't start with `refs/` (e.g. `refs/heads/master`) we will
-try to infer where in `refs/*` on the destination <repository> it
-belongs based on the type of <src> being pushed and whether <dst>
-is ambiguous.
+The `<dst>` determines what ref to update on the remote side. It must be the
+name of a branch, tag, or other ref, not an arbitrary expression.
 +
---
-* If <dst> unambiguously refers to a ref on the <repository> remote,
-  then push to that ref.
+The `+` is optional and does the same thing as `--force`.
++
+You can write a refspec using the fully expanded form (for
+example `refs/heads/main:refs/heads/main`) which specifies the exact source
+and destination, or with a shorter form (for example `main` or
+`main:other`). Here are the rules for how refspecs are expanded,
+as well as various other special refspec forms:
++
+ *  `<src>` without a `:<dst>` means to update the same ref as the
+    `<src>`, unless the `remote.<repository>.push` configuration specifies a
+    different <dst>. For example, if `main` is a branch, then the refspec
+    `main` expands to `main:refs/heads/main`.
+ *  If `<dst>` unambiguously refers to a ref on the <repository> remote,
+    then expand it to that ref. For example, if `v1.0` is a tag on the
+    remote, then `HEAD:v1.0` expands to `HEAD:refs/tags/v1.0`.
+ *  If `<src>` resolves to a ref starting with `refs/heads/` or `refs/tags/`,
+    then prepend that to <dst>. For example, if `main` is a branch, then
+    `main:other` expands to `main:refs/heads/other`
+ *  The special refspec `:` (or `+:` to allow non-fast-forward updates)
+    directs Git to push "matching" branches: for every branch that exists on
+    the local side, the remote side is updated if a branch of the same name
+    already exists on the remote side.
+ *  <src> may contain a * to indicate a simple pattern match.
+    This works like a glob that matches any ref matching the pattern.
+    There must be only one * in both the `<src>` and `<dst>`.
+    It will map refs to the destination by replacing the * with the
+    contents matched from the source. For example, `refs/heads/*:refs/heads/*`
+    will push all branches.
+ *  A refspec starting with `^` is a negative refspec.
+    This specifies refs to exclude. A ref will be considered to
+    match if it matches at least one positive refspec, and does not
+    match any negative refspec. Negative refspecs can be pattern refspecs.
+    They must only contain a `<src>`.
+    Fully spelled out hex object names are also not supported.
+    For example, `git push origin 'refs/heads/*' '^refs/heads/dev-*'`
+    will push all branches except for those starting with `dev-`
+ *  If `<src>` is empty, it deletes the `<dst>` ref from the remote
+    repository. For example, `git push origin :dev` will
+    delete the `dev` branch.
+ *  `tag <tag>` expands to `refs/tags/<tag>:refs/tags/<tag>`.
+	This is technically a special syntax for `git push` and not a refspec,
+	since in `git push origin tag v1.0` the arguments `tag` and `v1.0`
+	are separate.
+ *  If the refspec can't be expanded unambiguously, error out
+    with an error indicating what was tried, and depending
+    on the `advice.pushUnqualifiedRefname` configuration (see
+    linkgit:git-config[1]) suggest what refs/ namespace you may have
+    wanted to push to.
 
-* If <src> resolves to a ref starting with refs/heads/ or refs/tags/,
-  then prepend that to <dst>.
-
-* Other ambiguity resolutions might be added in the future, but for
-  now any other cases will error out with an error indicating what we
-  tried, and depending on the `advice.pushUnqualifiedRefname`
-  configuration (see linkgit:git-config[1]) suggest what refs/
-  namespace you may have wanted to push to.
-
---
-+
-The object referenced by <src> is used to update the <dst> reference
-on the remote side. Whether this is allowed depends on where in
-`refs/*` the <dst> reference lives as described in detail below, in
-those sections "update" means any modifications except deletes, which
-as noted after the next few sections are treated differently.
-+
-The `refs/heads/*` namespace will only accept commit objects, and
-updates only if they can be fast-forwarded.
-+
-The `refs/tags/*` namespace will accept any kind of object (as
-commits, trees and blobs can be tagged), and any updates to them will
-be rejected.
-+
-It's possible to push any type of object to any namespace outside of
-`refs/{tags,heads}/*`. In the case of tags and commits, these will be
-treated as if they were the commits inside `refs/heads/*` for the
-purposes of whether the update is allowed.
-+
-I.e. a fast-forward of commits and tags outside `refs/{tags,heads}/*`
-is allowed, even in cases where what's being fast-forwarded is not a
-commit, but a tag object which happens to point to a new commit which
-is a fast-forward of the commit the last tag (or commit) it's
-replacing. Replacing a tag with an entirely different tag is also
-allowed, if it points to the same commit, as well as pushing a peeled
-tag, i.e. pushing the commit that existing tag object points to, or a
-new tag object which an existing commit points to.
-+
-Tree and blob objects outside of `refs/{tags,heads}/*` will be treated
-the same way as if they were inside `refs/tags/*`, any update of them
-will be rejected.
-+
-All of the rules described above about what's not allowed as an update
-can be overridden by adding an the optional leading `+` to a refspec
-(or using `--force` command line option). The only exception to this
-is that no amount of forcing will make the `refs/heads/*` namespace
-accept a non-commit object. Hooks and configuration can also override
-or amend these rules, see e.g. `receive.denyNonFastForwards` in
-linkgit:git-config[1] and `pre-receive` and `update` in
-linkgit:githooks[5].
-+
-Pushing an empty <src> allows you to delete the <dst> ref from the
-remote repository. Deletions are always accepted without a leading `+`
-in the refspec (or `--force`), except when forbidden by configuration
-or hooks. See `receive.denyDeletes` in linkgit:git-config[1] and
-`pre-receive` and `update` in linkgit:githooks[5].
-+
-The special refspec `:` (or `+:` to allow non-fast-forward updates)
-directs Git to push "matching" branches: for every branch that exists on
-the local side, the remote side is updated if a branch of the same name
-already exists on the remote side.
-+
-`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
+Not all updates are allowed: see PUSH RULES below for the details.
 
 --all::
 --branches::
@@ -197,7 +172,8 @@
 	with configuration variable `push.followTags`.  For more
 	information, see `push.followTags` in linkgit:git-config[1].
 
---[no-]signed::
+--signed::
+--no-signed::
 --signed=(true|false|if-asked)::
 	GPG-sign the push request to update refs on the receiving
 	side, to allow it to be checked by the hooks and/or be
@@ -208,7 +184,8 @@
 	will also fail if the actual call to `gpg --sign` fails.  See
 	linkgit:git-receive-pack[1] for the details on the receiving end.
 
---[no-]atomic::
+--atomic::
+--no-atomic::
 	Use an atomic transaction on the remote side if available.
 	Either all refs are updated, or on error, no refs are updated.
 	If the server does not support atomic pushes the push will fail.
@@ -232,7 +209,8 @@
 	repository over ssh, and you do not have the program in
 	a directory on the default $PATH.
 
---[no-]force-with-lease::
+--force-with-lease::
+--no-force-with-lease::
 --force-with-lease=<refname>::
 --force-with-lease=<refname>:<expect>::
 	Usually, "git push" refuses to update a remote ref that is
@@ -332,14 +310,12 @@
 
 -f::
 --force::
-	Usually, the command refuses to update a remote ref that is
-	not an ancestor of the local ref used to overwrite it.
-	Also, when `--force-with-lease` option is used, the command refuses
-	to update a remote ref whose current value does not match
-	what is expected.
+	Usually, `git push` will refuse to update a branch that is not an
+	ancestor of the commit being pushed.
 +
-This flag disables these checks, and can cause the remote repository
-to lose commits; use it with care.
+This flag disables that check, the other safety checks in PUSH RULES
+below, and the checks in --force-with-lease. It can cause the remote
+repository to lose commits; use it with care.
 +
 Note that `--force` applies to all the refs that are pushed, hence
 using it with `push.default` set to `matching` or with multiple push
@@ -350,7 +326,8 @@
 origin +master` to force a push to the `master` branch). See the
 `<refspec>...` section above for details.
 
---[no-]force-if-includes::
+--force-if-includes::
+--no-force-if-includes::
 	Force an update only if the tip of the remote-tracking ref
 	has been integrated locally.
 +
@@ -377,7 +354,8 @@
 	linkgit:git-pull[1] and other commands. For more information,
 	see `branch.<name>.merge` in linkgit:git-config[1].
 
---[no-]thin::
+--thin::
+--no-thin::
 	These options are passed to linkgit:git-send-pack[1]. A thin transfer
 	significantly reduces the amount of sent data when the sender and
 	receiver share many of the same objects in common. The default is
@@ -419,7 +397,8 @@
 "push.recurseSubmodules={on-demand,only}" or "submodule.recurse" configuration,
 further recursion will occur. In this case, "only" is treated as "on-demand".
 
---[no-]verify::
+--verify::
+--no-verify::
 	Toggle the pre-push hook (see linkgit:githooks[5]).  The
 	default is --verify, giving the hook a chance to prevent the
 	push.  With --no-verify, the hook is bypassed completely.
@@ -508,6 +487,45 @@
 	refs, no explanation is needed. For a failed ref, the reason for
 	failure is described.
 
+PUSH RULES
+----------
+
+As a safety feature, the `git push` command only allows certain kinds of
+updates to prevent you from accidentally losing data on the remote.
+
+Because branches and tags are intended to be used differently, the
+safety rules for pushing to a branch are different from the rules
+for pushing to a tag. In the following rules "update" means any
+modifications except deletions and creations. Deletions and creations
+are always allowed, except when forbidden by configuration or hooks.
+
+1. If the push destination is a **branch** (`refs/heads/*`): only
+   fast-forward updates are allowed, which means the destination must be
+   an ancestor of the source commit. The source must be a commit.
+2. If the push destination is a **tag** (`refs/tags/*`): all updates will
+   be rejected. The source can be any object.
+3. If the push destination is not a branch or tag:
+   * If the source is a tree or blob object, any updates will be rejected
+   * If the source is a tag or commit object, any fast-forward update
+     is allowed, even in cases where what's being fast-forwarded is not a
+     commit, but a tag object which happens to point to a new commit which
+     is a fast-forward of the commit the last tag (or commit) it's
+     replacing. Replacing a tag with an entirely different tag is also
+     allowed, if it points to the same commit, as well as pushing a peeled
+     tag, i.e. pushing the commit that existing tag object points to, or a
+     new tag object which an existing commit points to.
+
+You can override these rules by passing `--force` or by adding the
+optional leading `+` to a refspec. The only exceptions are that no
+amount of forcing will make a branch accept a non-commit object,
+and forcing won't make the remote repository accept a push that it's
+configured to deny.
+
+Hooks and configuration can also override or amend these rules,
+see e.g. `receive.denyNonFastForwards` and `receive.denyDeletes`
+in linkgit:git-config[1] and `pre-receive` and `update` in
+linkgit:githooks[5].
+
 NOTE ABOUT FAST-FORWARDS
 ------------------------
 
@@ -697,6 +715,7 @@
 
 include::transfer-data-leaks.adoc[]
 
+[[CONFIGURATION]]
 CONFIGURATION
 -------------
 
diff --git a/Documentation/git-range-diff.adoc b/Documentation/git-range-diff.adoc
index db0e427..b5e85d3 100644
--- a/Documentation/git-range-diff.adoc
+++ b/Documentation/git-range-diff.adoc
@@ -96,7 +96,8 @@
 --remerge-diff::
 	Convenience option, equivalent to `--diff-merges=remerge`.
 
---[no-]notes[=<ref>]::
+--notes[=<ref>]::
+--no-notes::
 	This flag is passed to the `git log` program
 	(see linkgit:git-log[1]) that generates the patches.
 
diff --git a/Documentation/git-read-tree.adoc b/Documentation/git-read-tree.adoc
index 1c48c28..1c04bba 100644
--- a/Documentation/git-read-tree.adoc
+++ b/Documentation/git-read-tree.adoc
@@ -100,7 +100,8 @@
 	directories the index file and index output file are
 	located in.
 
---[no-]recurse-submodules::
+--recurse-submodules::
+--no-recurse-submodules::
 	Using --recurse-submodules will update the content of all active
 	submodules according to the commit recorded in the superproject by
 	calling read-tree recursively, also setting the submodules' HEAD to be
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d304..005caf6 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,49 +16,12 @@
 
 DESCRIPTION
 -----------
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
+Transplant a series of commits onto a different starting point.
+You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
+MODE below for how to do that.
 
-If `<upstream>` is not specified, the upstream configured in
-`branch.<name>.remote` and `branch.<name>.merge` options will be used (see
-linkgit:git-config[1] for details) and the `--fork-point` option is
-assumed.  If you are currently not on any branch or if the current
-branch does not have a configured upstream, the rebase will abort.
-
-All changes made by commits in the current branch but that are not
-in `<upstream>` are saved to a temporary area.  This is the same set
-of commits that would be shown by `git log <upstream>..HEAD`; or by
-`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
-description on `--fork-point` below); or by `git log HEAD`, if the
-`--root` option is specified.
-
-The current branch is reset to `<upstream>` or `<newbase>` if the
-`--onto` option was supplied.  This has the exact same effect as
-`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
-to point at the tip of the branch before the reset.
-
-[NOTE]
-`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
-at the end of the rebase if other commands that write that pseudo-ref
-(e.g. `git reset`) are used during the rebase. The previous branch tip,
-however, is accessible using the reflog of the current branch
-(i.e. `@{1}`, see linkgit:gitrevisions[7]).
-
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
-Assume the following history exists and the current branch is "topic":
+For example, imagine that you have been working on the `topic` branch in this
+history, and you want to "catch up" to the work done on the `master` branch.
 
 ------------
           A---B---C topic
@@ -66,13 +29,11 @@
     D---E---F---G master
 ------------
 
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
+You want to transplant the commits you made on `topic` since it diverged from
+`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
+by running `git rebase master` while the `topic` branch is checked out.  If you
+want to rebase `topic` while on another branch, `git rebase master topic` is a
+shortcut for `git checkout topic && git rebase master`.
 
 ------------
                   A'--B'--C' topic
@@ -80,30 +41,56 @@
     D---E---F---G master
 ------------
 
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
 
-If the upstream branch already contains a change you have made (e.g.,
-because you mailed a patch which was applied upstream), then that commit
-will be skipped and warnings will be issued (if the 'merge' backend is
-used).  For example, running `git rebase master` on the following
-history (in which `A'` and `A` introduce the same set of changes, but
-have different committer information):
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can do
+one of these things:
 
-------------
-          A---B---C topic
-         /
-    D---E---A'---F master
-------------
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. You can mark the conflict as
+   resolved with  `git add <filename>`. After resolving all of the conflicts,
+   you can continue the rebasing process with
 
-will result in:
+   git rebase --continue
 
-------------
-                   B'---C' topic
-                  /
-    D---E---A'---F master
-------------
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
+`branch.<name>.remote` and `branch.<name>.merge` options will be used (see
+linkgit:git-config[1] for details) and the `--fork-point` option is
+assumed.  If you are currently not on any branch or if the current
+branch does not have a configured upstream, the rebase will abort.
+
+Here is a simplified description of what `git rebase <upstream>` does:
+
+1. Make a list of all commits on your current branch since it branched
+   off from `<upstream>` that do not have an equivalent commit in
+   `<upstream>`.
+2. Check out `<upstream>` with the equivalent of
+   `git checkout --detach <upstream>`.
+3. Replay the commits, one by one, in order. This is similar to running
+   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
+   are handled.
+4. Update your branch to point to the final commit with the equivalent
+   of `git checkout -B <branch>`.
+
+[NOTE]
+When starting the rebase, `ORIG_HEAD` is set to point to the commit at the tip
+of the to-be-rebased branch. However, `ORIG_HEAD` is not guaranteed to still
+point to that commit at the end of the rebase if other commands that change
+`ORIG_HEAD` (like `git reset`) are used during the rebase. The previous branch
+tip, however, is accessible using the reflog of the current branch (i.e. `@{1}`,
+see linkgit:gitrevisions[7].
+
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
 
 Here is how you would transplant a topic branch based on one
 branch to another, to pretend that you forked the topic branch
@@ -186,28 +173,6 @@
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
@@ -253,6 +218,8 @@
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO above for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
@@ -687,7 +654,7 @@
  * --fork-point and --root
 
 BEHAVIORAL DIFFERENCES
------------------------
+----------------------
 
 `git rebase` has two primary backends: 'apply' and 'merge'.  (The 'apply'
 backend used to be known as the 'am' backend, but the name led to
diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index 4d6dc99..fa33680 100644
--- a/Documentation/git-refs.adoc
+++ b/Documentation/git-refs.adoc
@@ -11,6 +11,15 @@
 [synopsis]
 git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]
 git refs verify [--strict] [--verbose]
+git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
+		   [(--sort=<key>)...] [--format=<format>]
+		   [--include-root-refs] [--points-at=<object>]
+		   [--merged[=<object>]] [--no-merged[=<object>]]
+		   [--contains[=<object>]] [--no-contains[=<object>]]
+		   [(--exclude=<pattern>)...] [--start-after=<marker>]
+		   [ --stdin | (<pattern>...)]
+git refs exists <ref>
+git refs optimize [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude <pattern>]
 
 DESCRIPTION
 -----------
@@ -20,43 +29,67 @@
 COMMANDS
 --------
 
-migrate::
+`migrate`::
 	Migrate ref store between different formats.
 
-verify::
+`verify`::
 	Verify reference database consistency.
 
+list::
+	List references in the repository with support for filtering,
+	formatting, and sorting. This subcommand is an alias for
+	linkgit:git-for-each-ref[1] and offers identical functionality.
+
+exists::
+	Check whether the given reference exists. Returns an exit code of 0 if
+	it does, 2 if it is missing, and 1 in case looking up the reference
+	failed with an error other than the reference being missing. This does
+	not verify whether the reference resolves to an actual object.
+
+optimize::
+	Optimizes references to improve repository performance and reduce disk
+	usage. This subcommand is an alias for linkgit:git-pack-refs[1] and
+	offers identical functionality.
+
 OPTIONS
 -------
 
-The following options are specific to 'git refs migrate':
+The following options are specific to `git refs migrate`:
 
---ref-format=<format>::
+`--ref-format=<format>`::
 	The ref format to migrate the ref store to. Can be one of:
 +
 include::ref-storage-format.adoc[]
 
---dry-run::
+`--dry-run`::
 	Perform the migration, but do not modify the repository. The migrated
 	refs will be written into a separate directory that can be inspected
 	separately. The name of the directory will be reported on stdout. This
 	can be used to double check that the migration works as expected before
 	performing the actual migration.
 
---reflog::
---no-reflog::
+`--reflog`::
+`--no-reflog`::
 	Choose between migrating the reflog data to the new backend,
 	and discarding them.  The default is "--reflog", to migrate.
 
-The following options are specific to 'git refs verify':
+The following options are specific to `git refs verify`:
 
---strict::
+`--strict`::
 	Enable stricter error checking. This will cause warnings to be
 	reported as errors. See linkgit:git-fsck[1].
 
---verbose::
+`--verbose`::
 	When verifying the reference database consistency, be chatty.
 
+The following options are specific to 'git refs list':
+
+include::for-each-ref-options.adoc[]
+
+The following options are specific to 'git refs optimize':
+
+include::pack-refs-options.adoc[]
+
 KNOWN LIMITATIONS
 -----------------
 
diff --git a/Documentation/git-replay.adoc b/Documentation/git-replay.adoc
index 0b12bf8..dcb26e8 100644
--- a/Documentation/git-replay.adoc
+++ b/Documentation/git-replay.adoc
@@ -9,15 +9,16 @@
 SYNOPSIS
 --------
 [verse]
-(EXPERIMENTAL!) 'git replay' ([--contained] --onto <newbase> | --advance <branch>) <revision-range>...
+(EXPERIMENTAL!) 'git replay' ([--contained] --onto <newbase> | --advance <branch>) [--ref-action[=<mode>]] <revision-range>...
 
 DESCRIPTION
 -----------
 
 Takes ranges of commits and replays them onto a new location. Leaves
-the working tree and the index untouched, and updates no references.
-The output of this command is meant to be used as input to
-`git update-ref --stdin`, which would update the relevant branches
+the working tree and the index untouched. By default, updates the
+relevant references using an atomic transaction (all refs update or
+none). Use `--ref-action=print` to avoid automatic ref updates and
+instead get update commands that can be piped to `git update-ref --stdin`
 (see the OUTPUT section below).
 
 THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
@@ -29,18 +30,29 @@
 	Starting point at which to create the new commits.  May be any
 	valid commit, and not just an existing branch name.
 +
-When `--onto` is specified, the update-ref command(s) in the output will
-update the branch(es) in the revision range to point at the new
-commits, similar to the way how `git rebase --update-refs` updates
-multiple branches in the affected range.
+When `--onto` is specified, the branch(es) in the revision range will be
+updated to point at the new commits, similar to the way `git rebase --update-refs`
+updates multiple branches in the affected range.
 
 --advance <branch>::
 	Starting point at which to create the new commits; must be a
 	branch name.
 +
-When `--advance` is specified, the update-ref command(s) in the output
-will update the branch passed as an argument to `--advance` to point at
-the new commits (in other words, this mimics a cherry-pick operation).
+The history is replayed on top of the <branch> and <branch> is updated to
+point at the tip of the resulting history. This is different from `--onto`,
+which uses the target only as a starting point without updating it.
+
+--ref-action[=<mode>]::
+	Control how references are updated. The mode can be:
++
+--
+	* `update` (default): Update refs directly using an atomic transaction.
+	  All refs are updated or none are (all-or-nothing behavior).
+	* `print`: Output update-ref commands for pipeline use. This is the
+	  traditional behavior where output can be piped to `git update-ref --stdin`.
+--
++
+The default mode can be configured via the `replay.refAction` configuration variable.
 
 <revision-range>::
 	Range of commits to replay. More than one <revision-range> can
@@ -54,8 +66,11 @@
 OUTPUT
 ------
 
-When there are no conflicts, the output of this command is usable as
-input to `git update-ref --stdin`.  It is of the form:
+By default, or with `--ref-action=update`, this command produces no output on
+success, as refs are updated directly using an atomic transaction.
+
+When using `--ref-action=print`, the output is usable as input to
+`git update-ref --stdin`. It is of the form:
 
 	update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
 	update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
@@ -81,6 +96,14 @@
 
 ------------
 $ git replay --onto target origin/main..mybranch
+------------
+
+The refs are updated atomically and no output is produced on success.
+
+To see what would be updated without actually updating:
+
+------------
+$ git replay --ref-action=print --onto target origin/main..mybranch
 update refs/heads/mybranch ${NEW_mybranch_HASH} ${OLD_mybranch_HASH}
 ------------
 
@@ -88,33 +111,29 @@
 
 ------------
 $ git replay --advance target origin/main..mybranch
-update refs/heads/target ${NEW_target_HASH} ${OLD_target_HASH}
 ------------
 
 Note that the first two examples replay the exact same commits and on
 top of the exact same new base, they only differ in that the first
-provides instructions to make mybranch point at the new commits and
-the second provides instructions to make target point at them.
+updates mybranch to point at the new commits and the second updates
+target to point at them.
 
 What if you have a stack of branches, one depending upon another, and
 you'd really like to rebase the whole set?
 
 ------------
 $ git replay --contained --onto origin/main origin/main..tipbranch
-update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
-update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
-update refs/heads/tipbranch ${NEW_tipbranch_HASH} ${OLD_tipbranch_HASH}
 ------------
 
+All three branches (`branch1`, `branch2`, and `tipbranch`) are updated
+atomically.
+
 When calling `git replay`, one does not need to specify a range of
 commits to replay using the syntax `A..B`; any range expression will
 do:
 
 ------------
 $ git replay --onto origin/main ^base branch1 branch2 branch3
-update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
-update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
-update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH}
 ------------
 
 This will simultaneously rebase `branch1`, `branch2`, and `branch3`,
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
new file mode 100644
index 0000000..ce43cb1
--- /dev/null
+++ b/Documentation/git-repo.adoc
@@ -0,0 +1,119 @@
+git-repo(1)
+===========
+
+NAME
+----
+git-repo - Retrieve information about the repository
+
+SYNOPSIS
+--------
+[synopsis]
+git repo info [--format=(keyvalue|nul)] [-z] [<key>...]
+git repo structure [--format=(table|keyvalue|nul)]
+
+DESCRIPTION
+-----------
+Retrieve information about the repository.
+
+THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
+
+COMMANDS
+--------
+`info [--format=(keyvalue|nul)] [-z] [<key>...]`::
+	Retrieve metadata-related information about the current repository. Only
+	the requested data will be returned based on their keys (see "INFO KEYS"
+	section below).
++
+The values are returned in the same order in which their respective keys were
+requested.
++
+The output format can be chosen through the flag `--format`. Two formats are
+supported:
++
+`keyvalue`:::
+	output key-value pairs one per line using the `=` character as
+	the delimiter between the key and the value. Values containing "unusual"
+	characters are quoted as explained for the configuration variable
+	`core.quotePath` (see linkgit:git-config[1]). This is the default.
+
+`nul`:::
+	similar to `keyvalue`, but using a newline character as the delimiter
+	between the key and the value and using a NUL character after each value.
+	This format is better suited for being parsed by another applications than
+	`keyvalue`. Unlike in the `keyvalue` format, the values are never quoted.
++
+`-z` is an alias for `--format=nul`.
+
+`structure [--format=(table|keyvalue|nul)]`::
+	Retrieve statistics about the current repository structure. The
+	following kinds of information are reported:
++
+* Reference counts categorized by type
+* Reachable object counts categorized by type
+
++
+The output format can be chosen through the flag `--format`. Three formats are
+supported:
++
+`table`:::
+	Outputs repository stats in a human-friendly table. This format may
+	change and is not intended for machine parsing. This is the default
+	format.
+
+`keyvalue`:::
+	Each line of output contains a key-value pair for a repository stat.
+	The '=' character is used to delimit between the key and the value.
+	Values containing "unusual" characters are quoted as explained for the
+	configuration variable `core.quotePath` (see linkgit:git-config[1]).
+
+`nul`:::
+	Similar to `keyvalue`, but uses a NUL character to delimit between
+	key-value pairs instead of a newline. Also uses a newline character as
+	the delimiter between the key and value instead of '='. Unlike the
+	`keyvalue` format, values containing "unusual" characters are never
+	quoted.
+
+INFO KEYS
+---------
+In order to obtain a set of values from `git repo info`, you should provide
+the keys that identify them. Here's a list of the available keys and the
+values that they return:
+
+`layout.bare`::
+	`true` if this is a bare repository, otherwise `false`.
+
+`layout.shallow`::
+	`true` if this is a shallow repository, otherwise `false`.
+
+`object.format`::
+	The object format (hash algorithm) used in the repository.
+
+`references.format`::
+	The reference storage format. The valid values are:
++
+include::ref-storage-format.adoc[]
+
+EXAMPLES
+--------
+
+* Retrieves the reference format of the current repository:
++
+------------
+git repo info references.format
+------------
++
+
+* Retrieves whether the current repository is bare and whether it is shallow
+using the `nul` format:
++
+------------
+git repo info --format=nul layout.bare layout.shallow
+------------
+
+SEE ALSO
+--------
+linkgit:git-rev-parse[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-reset.adoc b/Documentation/git-reset.adoc
index 50e8a0b..3b9ba9a 100644
--- a/Documentation/git-reset.adoc
+++ b/Documentation/git-reset.adoc
@@ -90,7 +90,8 @@
 	If a file that is different between _<commit>_ and `HEAD` has local
 	changes, reset is aborted.
 
-`--[no-]recurse-submodules`::
+`--recurse-submodules`::
+`--no-recurse-submodules`::
 	When the working tree is updated, using `--recurse-submodules` will
 	also recursively reset the working tree of all active submodules
 	according to the commit recorded in the superproject, also setting
diff --git a/Documentation/git-rev-parse.adoc b/Documentation/git-rev-parse.adoc
index 18383e5..5398691 100644
--- a/Documentation/git-rev-parse.adoc
+++ b/Documentation/git-rev-parse.adoc
@@ -324,11 +324,12 @@
 	path of the current directory relative to the top-level
 	directory.
 
---show-object-format[=(storage|input|output)]::
-	Show the object format (hash algorithm) used for the repository
-	for storage inside the `.git` directory, input, or output. For
-	input, multiple algorithms may be printed, space-separated.
-	If not specified, the default is "storage".
+--show-object-format[=(storage|input|output|compat)]::
+	Show the object format (hash algorithm) used for the repository for storage
+	inside the `.git` directory, input, output, or compatibility. For input,
+	multiple algorithms may be printed, space-separated. If `compat` is
+	requested and no compatibility algorithm is enabled, prints an empty line. If
+	not specified, the default is "storage".
 
 --show-ref-format::
 	Show the reference storage format used for the repository.
diff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc
index c610909..263b977 100644
--- a/Documentation/git-send-email.adoc
+++ b/Documentation/git-send-email.adoc
@@ -115,7 +115,8 @@
 Only necessary if `--compose` is also set.  If `--compose`
 is not set, this will be prompted for.
 
---[no-]outlook-id-fix::
+--outlook-id-fix::
+--no-outlook-id-fix::
 	Microsoft Outlook SMTP servers discard the Message-ID sent via email and
 	assign a new random Message-ID, thus breaking threads.
 +
@@ -299,6 +300,32 @@
 	commands and replies will be printed. Useful to debug TLS
 	connection and authentication problems.
 
+--imap-sent-folder=<folder>::
+	Some email providers (e.g. iCloud) do not send a copy of the emails sent
+	using SMTP to the `Sent` folder or similar in your mailbox. Use this option
+	to use `git imap-send` to send a copy of the emails to the folder specified
+	using this option. You can run `git imap-send --list` to get a list of
+	valid folder names, including the correct name of the `Sent` folder in
+	your mailbox. You can also use this option to send emails to a dedicated
+	IMAP folder of your choice.
++
+This feature requires setting up `git imap-send`. See linkgit:git-imap-send[1]
+for instructions.
+
+--use-imap-only::
+--no-use-imap-only::
+	If this is set, all emails will only be copied to the IMAP folder specified
+	with `--imap-sent-folder` or `sendemail.imapSentFolder` and will not be sent
+	to the recipients. Useful if you just want to create a draft of the emails
+	and use another email client to send them.
+	If disabled with `--no-use-imap-only`, the emails will be sent like usual.
+	Disabled by default, but the `sendemail.useImapOnly` configuration
+	variable can be used to enable it.
+
++
+This feature requires setting up `git imap-send`. See linkgit:git-imap-send[1]
+for instructions.
+
 --batch-size=<num>::
 	Some email servers (e.g. 'smtp.163.com') limit the number of emails to be
 	sent per session (connection) and this will lead to a failure when
@@ -350,7 +377,8 @@
 --no-header-cmd::
 	Disable any header command in use.
 
---[no-]chain-reply-to::
+--chain-reply-to::
+--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
 	the first will be sent as replies to the first email sent.  When using
@@ -364,19 +392,22 @@
 	values in the `sendemail` section. The default identity is
 	the value of `sendemail.identity`.
 
---[no-]signed-off-by-cc::
+--signed-off-by-cc::
+--no-signed-off-by-cc::
 	If this is set, add emails found in the `Signed-off-by` trailer or `Cc:`
 	lines to the cc list. Default is the value of `sendemail.signedOffByCc`
 	configuration value; if that is unspecified, default to
 	`--signed-off-by-cc`.
 
---[no-]cc-cover::
+--cc-cover::
+--no-cc-cover::
 	If this is set, emails found in `Cc:` headers in the first patch of
 	the series (typically the cover letter) are added to the cc list
 	for each email set. Default is the value of `sendemail.ccCover`
 	configuration value; if that is unspecified, default to `--no-cc-cover`.
 
---[no-]to-cover::
+--to-cover::
+--no-to-cover::
 	If this is set, emails found in `To:` headers in the first patch of
 	the series (typically the cover letter) are added to the to list
 	for each email set. Default is the value of `sendemail.toCover`
@@ -407,12 +438,14 @@
 that is unspecified, default to `self` if `--suppress-from` is
 specified, as well as `body` if `--no-signed-off-cc` is specified.
 
---[no-]suppress-from::
+--suppress-from::
+--no-suppress-from::
 	If this is set, do not add the `From:` address to the `Cc:` list.
 	Default is the value of `sendemail.suppressFrom` configuration
 	value; if that is unspecified, default to `--no-suppress-from`.
 
---[no-]thread::
+--thread::
+--no-thread::
 	If this is set, the `In-Reply-To` and `References` headers will be
 	added to each email sent.  Whether each mail refers to the
 	previous email (`deep` threading per `git format-patch`
@@ -430,7 +463,8 @@
 Failure to do so may not produce the expected result in the
 recipient's MUA.
 
---[no-]mailmap::
+--mailmap::
+--no-mailmap::
 	Use the mailmap file (see linkgit:gitmailmap[5]) to map all
 	addresses to their canonical real name and email address. Additional
 	mailmap data specific to `git send-email` may be provided using the
@@ -459,7 +493,8 @@
 --dry-run::
 	Do everything except actually send the emails.
 
---[no-]format-patch::
+--format-patch::
+--no-format-patch::
 	When an argument may be understood either as a reference or as a file name,
 	choose to understand it as a format-patch argument (`--format-patch`)
 	or as a file name (`--no-format-patch`). By default, when such a conflict
@@ -469,7 +504,8 @@
 	Make `git send-email` less verbose.  One line per email should be
 	all that is output.
 
---[no-]validate::
+--validate::
+--no-validate::
 	Perform sanity checks on patches.
 	Currently, validation means the following:
 +
diff --git a/Documentation/git-send-pack.adoc b/Documentation/git-send-pack.adoc
index b9e73f2..811193f 100644
--- a/Documentation/git-send-pack.adoc
+++ b/Documentation/git-send-pack.adoc
@@ -71,7 +71,8 @@
 	fails to update then the entire push will fail without changing any
 	refs.
 
---[no-]signed::
+--signed::
+--no-signed::
 --signed=(true|false|if-asked)::
 	GPG-sign the push request to update refs on the receiving
 	side, to allow it to be checked by the hooks and/or be
diff --git a/Documentation/git-sparse-checkout.adoc b/Documentation/git-sparse-checkout.adoc
index b5fe5da..0d1618f 100644
--- a/Documentation/git-sparse-checkout.adoc
+++ b/Documentation/git-sparse-checkout.adoc
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git sparse-checkout' (init | list | set | add | reapply | disable | check-rules) [<options>]
+'git sparse-checkout' (init | list | set | add | reapply | disable | check-rules | clean) [<options>]
 
 
 DESCRIPTION
@@ -111,6 +111,37 @@
 to change which sparsity mode you are using without needing to also respecify
 all sparsity paths.
 
+'clean'::
+	Opportunistically remove files outside of the sparse-checkout
+	definition. This command requires cone mode to use recursive
+	directory matches to determine which files should be removed. A
+	file is considered for removal if it is contained within a tracked
+	directory that is outside of the sparse-checkout definition.
++
+Some special cases, such as merge conflicts or modified files outside of
+the sparse-checkout definition could lead to keeping files that would
+otherwise be removed. Resolve conflicts, stage modifications, and use
+`git sparse-checkout reapply` in conjunction with `git sparse-checkout
+clean` to resolve these cases.
++
+This command can be used to be sure the sparse index works efficiently,
+though it does not require enabling the sparse index feature via the
+`index.sparse=true` configuration.
++
+To prevent accidental deletion of worktree files, the `clean` subcommand
+will not delete any files without the `-f` or `--force` option, unless
+the `clean.requireForce` config option is set to `false`.
++
+The `--dry-run` option will list the directories that would be removed
+without deleting them. Running in this mode can be helpful to predict the
+behavior of the clean comand or to determine which kinds of files are left
+in the sparse directories.
++
+The `--verbose` option will list every file within the directories that
+are considered for removal. This option is helpful to determine if those
+files are actually important or perhaps to explain why the directory is
+still present despite the current sparse-checkout.
+
 'disable'::
 	Disable the `core.sparseCheckout` config setting, and restore the
 	working directory to include all files.
diff --git a/Documentation/git-stash.adoc b/Documentation/git-stash.adoc
index e2300a1..235d57d 100644
--- a/Documentation/git-stash.adoc
+++ b/Documentation/git-stash.adoc
@@ -7,24 +7,24 @@
 
 SYNOPSIS
 --------
-[verse]
-'git stash' list [<log-options>]
-'git stash' show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]
-'git stash' drop [-q | --quiet] [<stash>]
-'git stash' pop [--index] [-q | --quiet] [<stash>]
-'git stash' apply [--index] [-q | --quiet] [<stash>]
-'git stash' branch <branchname> [<stash>]
-'git stash' [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
+[synopsis]
+git stash list [<log-options>]
+git stash show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]
+git stash drop [-q | --quiet] [<stash>]
+git stash pop [--index] [-q | --quiet] [<stash>]
+git stash apply [--index] [-q | --quiet] [<stash>]
+git stash branch <branchname> [<stash>]
+git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
 	     [-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
 	     [--pathspec-from-file=<file> [--pathspec-file-nul]]
 	     [--] [<pathspec>...]]
-'git stash' save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
-	     [-u | --include-untracked] [-a | --all] [<message>]
-'git stash' clear
-'git stash' create [<message>]
-'git stash' store [(-m | --message) <message>] [-q | --quiet] <commit>
-'git stash' export (--print | --to-ref <ref>) [<stash>...]
-'git stash' import <commit>
+git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
+           [-u | --include-untracked] [-a | --all] [<message>]
+git stash clear
+git stash create [<message>]
+git stash store [(-m | --message) <message>] [-q | --quiet] <commit>
+git stash export (--print | --to-ref <ref>) [<stash>...]
+git stash import <commit>
 
 DESCRIPTION
 -----------
@@ -38,7 +38,7 @@
 `git stash list`, inspected with `git stash show`, and restored
 (potentially on top of a different commit) with `git stash apply`.
 Calling `git stash` without any arguments is equivalent to `git stash push`.
-A stash is by default listed as "WIP on 'branchname' ...", but
+A stash is by default listed as "WIP on '<branchname>' ...", but
 you can give a more descriptive message on the command line when
 you create one.
 
@@ -47,16 +47,16 @@
 the usual reflog syntax (e.g. `stash@{0}` is the most recently
 created stash, `stash@{1}` is the one before it, `stash@{2.hours.ago}`
 is also possible). Stashes may also be referenced by specifying just the
-stash index (e.g. the integer `n` is equivalent to `stash@{n}`).
+stash index (e.g. the integer `<n>` is equivalent to `stash@{<n>}`).
 
 COMMANDS
 --------
 
-push [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [(-m|--message) <message>] [--pathspec-from-file=<file> [--pathspec-file-nul]] [--] [<pathspec>...]::
+`push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-u | --include-untracked] [ -a | --all] [-q | --quiet] [(-m|--message) <message>] [--pathspec-from-file=<file> [--pathspec-file-nul]] [--] [<pathspec>...]`::
 
 	Save your local modifications to a new 'stash entry' and roll them
-	back to HEAD (in the working tree and in the index).
-	The <message> part is optional and gives
+	back to `HEAD` (in the working tree and in the index).
+	The _<message>_ part is optional and gives
 	the description along with the stashed state.
 +
 For quickly making a snapshot, you can omit "push".  In this mode,
@@ -65,14 +65,14 @@
 are `stash -p` which acts as alias for `stash push -p` and pathspec elements,
 which are allowed after a double hyphen `--` for disambiguation.
 
-save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
+`save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-u | --include-untracked] [-a | --all] [-q | --quiet] [<message>]`::
 
 	This option is deprecated in favour of 'git stash push'.  It
 	differs from "stash push" in that it cannot take pathspec.
 	Instead, all non-option arguments are concatenated to form the stash
 	message.
 
-list [<log-options>]::
+`list [<log-options>]`::
 
 	List the stash entries that you currently have.  Each 'stash entry' is
 	listed with its name (e.g. `stash@{0}` is the latest entry, `stash@{1}` is
@@ -88,7 +88,7 @@
 The command takes options applicable to the 'git log'
 command to control what is shown and how. See linkgit:git-log[1].
 
-show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]::
+`show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]`::
 
 	Show the changes recorded in the stash entry as a diff between the
 	stashed contents and the commit back when the stash entry was first
@@ -96,12 +96,12 @@
 	By default, the command shows the diffstat, but it will accept any
 	format known to 'git diff' (e.g., `git stash show -p stash@{1}`
 	to view the second most recent entry in patch form).
-	If no `<diff-option>` is provided, the default behavior will be given
+	If no _<diff-option>_ is provided, the default behavior will be given
 	by the `stash.showStat`, and `stash.showPatch` config variables. You
 	can also use `stash.showIncludeUntracked` to set whether
 	`--include-untracked` is enabled by default.
 
-pop [--index] [-q|--quiet] [<stash>]::
+`pop [--index] [-q | --quiet] [<stash>]`::
 
 	Remove a single stashed state from the stash list and apply it
 	on top of the current working tree state, i.e., do the inverse
@@ -112,19 +112,19 @@
 removed from the stash list. You need to resolve the conflicts by hand
 and call `git stash drop` manually afterwards.
 
-apply [--index] [-q|--quiet] [<stash>]::
+`apply [--index] [-q | --quiet] [<stash>]`::
 
 	Like `pop`, but do not remove the state from the stash list. Unlike `pop`,
 	`<stash>` may be any commit that looks like a commit created by
 	`stash push` or `stash create`.
 
-branch <branchname> [<stash>]::
+`branch <branchname> [<stash>]`::
 
-	Creates and checks out a new branch named `<branchname>` starting from
-	the commit at which the `<stash>` was originally created, applies the
-	changes recorded in `<stash>` to the new working tree and index.
-	If that succeeds, and `<stash>` is a reference of the form
-	`stash@{<revision>}`, it then drops the `<stash>`.
+	Creates and checks out a new branch named _<branchname>_ starting from
+	the commit at which the _<stash>_ was originally created, applies the
+	changes recorded in _<stash>_ to the new working tree and index.
+	If that succeeds, and _<stash>_ is a reference of the form
+	`stash@{<revision>}`, it then drops the _<stash>_.
 +
 This is useful if the branch on which you ran `git stash push` has
 changed enough that `git stash apply` fails due to conflicts. Since
@@ -132,54 +132,51 @@
 time `git stash` was run, it restores the originally stashed state
 with no conflicts.
 
-clear::
+`clear`::
 	Remove all the stash entries. Note that those entries will then
 	be subject to pruning, and may be impossible to recover (see
-	'Examples' below for a possible strategy).
+	'EXAMPLES' below for a possible strategy).
 
-drop [-q|--quiet] [<stash>]::
-
+`drop [-q | --quiet] [<stash>]`::
 	Remove a single stash entry from the list of stash entries.
 
-create::
-
+`create`::
 	Create a stash entry (which is a regular commit object) and
 	return its object name, without storing it anywhere in the ref
 	namespace.
 	This is intended to be useful for scripts.  It is probably not
 	the command you want to use; see "push" above.
 
-store::
+`store`::
 
 	Store a given stash created via 'git stash create' (which is a
 	dangling merge commit) in the stash ref, updating the stash
 	reflog.  This is intended to be useful for scripts.  It is
 	probably not the command you want to use; see "push" above.
 
-export ( --print | --to-ref <ref> ) [<stash>...]::
+`export ( --print | --to-ref <ref> ) [<stash>...]`::
 
 	Export the specified stashes, or all of them if none are specified, to
 	a chain of commits which can be transferred using the normal fetch and
 	push mechanisms, then imported using the `import` subcommand.
 
-import <commit>::
-
+`import <commit>`::
 	Import the specified stashes from the specified commit, which must have been
 	created by `export`, and add them to the list of stashes.  To replace the
 	existing stashes, use `clear` first.
 
 OPTIONS
 -------
--a::
---all::
+`-a`::
+`--all`::
 	This option is only valid for `push` and `save` commands.
 +
 All ignored and untracked files are also stashed and then cleaned
 up with `git clean`.
 
--u::
---include-untracked::
---no-include-untracked::
+`-u`::
+`--include-untracked`::
+`--no-include-untracked`::
 	When used with the `push` and `save` commands,
 	all untracked files are also stashed and then cleaned up with
 	`git clean`.
@@ -187,12 +184,12 @@
 When used with the `show` command, show the untracked files in the stash
 entry as part of the diff.
 
---only-untracked::
+`--only-untracked`::
 	This option is only valid for the `show` command.
 +
 Show only the untracked files in the stash entry as part of the diff.
 
---index::
+`--index`::
 	This option is only valid for `pop` and `apply` commands.
 +
 Tries to reinstate not only the working tree's changes, but also
@@ -200,15 +197,15 @@
 (which are stored in the index, where you therefore can no longer
 apply the changes as they were originally).
 
--k::
---keep-index::
---no-keep-index::
+`-k`::
+`--keep-index`::
+`--no-keep-index`::
 	This option is only valid for `push` and `save` commands.
 +
 All changes already added to the index are left intact.
 
--p::
---patch::
+`-p`::
+`--patch`::
 	This option is only valid for `push` and `save` commands.
 +
 Interactively select hunks from the diff between HEAD and the
@@ -224,8 +221,8 @@
 
 include::diff-context-options.adoc[]
 
--S::
---staged::
+`-S`::
+`--staged`::
 	This option is only valid for `push` and `save` commands.
 +
 Stash only the changes that are currently staged. This is similar to
@@ -234,49 +231,49 @@
 +
 The `--patch` option has priority over this one.
 
---pathspec-from-file=<file>::
+`--pathspec-from-file=<file>`::
 	This option is only valid for `push` command.
 +
-Pathspec is passed in `<file>` instead of commandline args. If
-`<file>` is exactly `-` then standard input is used. Pathspec
+Pathspec is passed in _<file>_ instead of commandline args. If
+_<file>_ is exactly `-` then standard input is used. Pathspec
 elements are separated by LF or CR/LF. Pathspec elements can be
 quoted as explained for the configuration variable `core.quotePath`
 (see linkgit:git-config[1]). See also `--pathspec-file-nul` and
 global `--literal-pathspecs`.
 
---pathspec-file-nul::
+`--pathspec-file-nul`::
 	This option is only valid for `push` command.
 +
 Only meaningful with `--pathspec-from-file`. Pathspec elements are
 separated with NUL character and all other characters are taken
 literally (including newlines and quotes).
 
--q::
---quiet::
+`-q`::
+`--quiet`::
 	This option is only valid for `apply`, `drop`, `pop`, `push`,
 	`save`, `store` commands.
 +
 Quiet, suppress feedback messages.
 
---print::
+`--print`::
 	This option is only valid for the `export` command.
 +
 Create the chain of commits representing the exported stashes without
 storing it anywhere in the ref namespace and print the object ID to
 standard output.  This is designed for scripts.
 
---to-ref::
+`--to-ref`::
 	This option is only valid for the `export` command.
 +
 Create the chain of commits representing the exported stashes and store
 it to the specified ref.
 
-\--::
+`--`::
 	This option is only valid for `push` command.
 +
 Separates pathspec from options for disambiguation purposes.
 
-<pathspec>...::
+`<pathspec>...`::
 	This option is only valid for `push` command.
 +
 The new stash entry records the modified states only for the files
@@ -286,11 +283,11 @@
 +
 For more details, see the 'pathspec' entry in linkgit:gitglossary[7].
 
-<stash>::
+_<stash>_::
 	This option is only valid for `apply`, `branch`, `drop`, `pop`,
 	`show`, and `export` commands.
 +
-A reference of the form `stash@{<revision>}`. When no `<stash>` is
+A reference of the form `stash@{<revision>}`. When no _<stash>_ is
 given, the latest stash is assumed (that is, `stash@{0}`).
 
 DISCUSSION
@@ -419,6 +416,7 @@
 
 include::includes/cmd-config-section-all.adoc[]
 
+:git-stash: 1
 include::config/stash.adoc[]
 
 
diff --git a/Documentation/git-submodule.adoc b/Documentation/git-submodule.adoc
index 503c84a..95beaee 100644
--- a/Documentation/git-submodule.adoc
+++ b/Documentation/git-submodule.adoc
@@ -442,7 +442,8 @@
 	clone with a history truncated to the specified number of revisions.
 	See linkgit:git-clone[1]
 
---[no-]recommend-shallow::
+--recommend-shallow::
+--no-recommend-shallow::
 	This option is only valid for the update command.
 	The initial clone of a submodule will use the recommended
 	`submodule.<name>.shallow` as provided by the `.gitmodules` file
@@ -454,7 +455,8 @@
 	Clone new submodules in parallel with as many jobs.
 	Defaults to the `submodule.fetchJobs` option.
 
---[no-]single-branch::
+--single-branch::
+--no-single-branch::
 	This option is only valid for the update command.
 	Clone only one branch during update: HEAD or one specified by --branch.
 
diff --git a/Documentation/git-svn.adoc b/Documentation/git-svn.adoc
index bcf7d84..c26c12b 100644
--- a/Documentation/git-svn.adoc
+++ b/Documentation/git-svn.adoc
@@ -1012,9 +1012,11 @@
 
 If you do merge, note the following rule: 'git svn dcommit' will
 attempt to commit on top of the SVN commit named in
+
 ------------------------------------------------------------------------
 git log --grep=^git-svn-id: --first-parent -1
 ------------------------------------------------------------------------
+
 You 'must' therefore ensure that the most recent commit of the branch
 you want to dcommit to is the 'first' parent of the merge.  Chaos will
 ensue otherwise, especially if the first parent is an older commit on
diff --git a/Documentation/git-tag.adoc b/Documentation/git-tag.adoc
index a4b1c0e..cea3202 100644
--- a/Documentation/git-tag.adoc
+++ b/Documentation/git-tag.adoc
@@ -3,26 +3,26 @@
 
 NAME
 ----
-git-tag - Create, list, delete or verify a tag object signed with GPG
+git-tag - Create, list, delete or verify tags
 
 
 SYNOPSIS
 --------
-[verse]
-'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]
+[synopsis]
+git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]
 	[(--trailer <token>[(=|:)<value>])...]
 	<tagname> [<commit> | <object>]
-'git tag' -d <tagname>...
-'git tag' [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]
+git tag -d <tagname>...
+git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]
 	[--points-at <object>] [--column[=<options>] | --no-column]
 	[--create-reflog] [--sort=<key>] [--format=<format>]
 	[--merged <commit>] [--no-merged <commit>] [<pattern>...]
-'git tag' -v [--format=<format>] <tagname>...
+git tag -v [--format=<format>] <tagname>...
 
 DESCRIPTION
 -----------
 
-Add a tag reference in `refs/tags/`, unless `-d/-l/-v` is given
+Add a tag reference in `refs/tags/`, unless `-d`/`-l`/`-v` is given
 to delete, list or verify tags.
 
 Unless `-f` is given, the named tag must not yet exist.
@@ -38,15 +38,17 @@
 Otherwise, a tag reference that points directly at the given object
 (i.e., a lightweight tag) is created.
 
-A GnuPG signed tag object will be created when `-s` or `-u
-<key-id>` is used.  When `-u <key-id>` is not used, the
-committer identity for the current user is used to find the
-GnuPG key for signing. 	The configuration variable `gpg.program`
-is used to specify custom GnuPG binary.
+A cryptographically signed tag object will be created when `-s` or
+`-u <key-id>` is used. The signing backend (GPG, X.509, SSH, etc.) is
+controlled by the `gpg.format` configuration variable, defaulting to
+OpenPGP. When `-u <key-id>` is not used, the committer identity for
+the current user is used to find the key for signing. The
+configuration variable `gpg.program` is used to specify a custom
+signing binary.
 
 Tag objects (created with `-a`, `-s`, or `-u`) are called "annotated"
 tags; they contain a creation date, the tagger name and e-mail, a
-tagging message, and an optional GnuPG signature. Whereas a
+tagging message, and an optional cryptographic signature. Whereas a
 "lightweight" tag is simply a name for an object (usually a commit
 object).
 
@@ -58,129 +60,134 @@
 
 OPTIONS
 -------
--a::
---annotate::
+`-a`::
+`--annotate`::
 	Make an unsigned, annotated tag object
 
--s::
---sign::
-	Make a GPG-signed tag, using the default e-mail address's key.
-	The default behavior of tag GPG-signing is controlled by `tag.gpgSign`
-	configuration variable if it exists, or disabled otherwise.
-	See linkgit:git-config[1].
+`-s`::
+`--sign`::
+	Make a cryptographically signed tag, using the default signing
+	key. The signing backend used depends on the `gpg.format`
+	configuration variable. The default key is determined by the
+	backend. For GPG, it's based on the committer's email address,
+	while for SSH it may be a specific key file or agent
+	identity. See linkgit:git-config[1].
 
---no-sign::
+`--no-sign`::
 	Override `tag.gpgSign` configuration variable that is
 	set to force each and every tag to be signed.
 
--u <key-id>::
---local-user=<key-id>::
-	Make a GPG-signed tag, using the given key.
+`-u <key-id>`::
+`--local-user=<key-id>`::
+	Make a cryptographically signed tag using the given key. The
+	format of the <key-id> and the backend used depend on the
+	`gpg.format` configuration variable. See
+	linkgit:git-config[1].
 
--f::
---force::
+`-f`::
+`--force`::
 	Replace an existing tag with the given name (instead of failing)
 
--d::
---delete::
+`-d`::
+`--delete`::
 	Delete existing tags with the given names.
 
--v::
---verify::
-	Verify the GPG signature of the given tag names.
+`-v`::
+`--verify`::
+	Verify the cryptographic signature of the given tags.
 
--n<num>::
-	<num> specifies how many lines from the annotation, if any,
-	are printed when using -l. Implies `--list`.
+`-n<num>`::
+	_<num>_ specifies how many lines from the annotation, if any,
+	are printed when using `-l`. Implies `--list`.
 +
 The default is not to print any annotation lines.
 If no number is given to `-n`, only the first line is printed.
 If the tag is not annotated, the commit message is displayed instead.
 
--l::
---list::
+`-l`::
+`--list`::
 	List tags. With optional `<pattern>...`, e.g. `git tag --list
 	'v-*'`, list only the tags that match the pattern(s).
 +
-Running "git tag" without arguments also lists all tags. The pattern
-is a shell wildcard (i.e., matched using fnmatch(3)). Multiple
+Running `git tag` without arguments also lists all tags. The pattern
+is a shell wildcard (i.e., matched using `fnmatch`(3)). Multiple
 patterns may be given; if any of them matches, the tag is shown.
 +
 This option is implicitly supplied if any other list-like option such
 as `--contains` is provided. See the documentation for each of those
 options for details.
 
---sort=<key>::
+`--sort=<key>`::
 	Sort based on the key given.  Prefix `-` to sort in
-	descending order of the value. You may use the --sort=<key> option
-	multiple times, in which case the last key becomes the primary
-	key. Also supports "version:refname" or "v:refname" (tag
-	names are treated as versions). The "version:refname" sort
-	order can also be affected by the "versionsort.suffix"
+	descending order of the value. You may use the `--sort=<key>` option
+	multiple times, in which case the last _<key>_ becomes the primary
+	key. Also supports "`version:refname`" or "`v:refname`" (tag
+	names are treated as versions). The "`version:refname`" sort
+	order can also be affected by the "`versionsort.suffix`"
 	configuration variable.
 	The keys supported are the same as those in `git for-each-ref`.
 	Sort order defaults to the value configured for the `tag.sort`
 	variable if it exists, or lexicographic order otherwise. See
 	linkgit:git-config[1].
 
---color[=<when>]::
+`--color[=<when>]`::
 	Respect any colors specified in the `--format` option. The
-	`<when>` field must be one of `always`, `never`, or `auto` (if
-	`<when>` is absent, behave as if `always` was given).
+	_<when>_ field must be one of `always`, `never`, or `auto` (if
+	_<when>_ is absent, behave as if `always` was given).
 
--i::
---ignore-case::
+`-i`::
+`--ignore-case`::
 	Sorting and filtering tags are case insensitive.
 
---omit-empty::
+`--omit-empty`::
 	Do not print a newline after formatted refs where the format expands
 	to the empty string.
 
---column[=<options>]::
---no-column::
+`--column[=<options>]`::
+`--no-column`::
 	Display tag listing in columns. See configuration variable
 	`column.tag` for option syntax. `--column` and `--no-column`
-	without options are equivalent to 'always' and 'never' respectively.
+	without options are equivalent to `always` and `never` respectively.
 +
 This option is only applicable when listing tags without annotation lines.
 
---contains [<commit>]::
-	Only list tags which contain the specified commit (HEAD if not
+`--contains [<commit>]`::
+	Only list tags which contain _<commit>_ (`HEAD` if not
 	specified). Implies `--list`.
 
---no-contains [<commit>]::
-	Only list tags which don't contain the specified commit (HEAD if
+`--no-contains [<commit>]`::
+	Only list tags which don't contain _<commit>_ (`HEAD` if
 	not specified). Implies `--list`.
 
---merged [<commit>]::
-	Only list tags whose commits are reachable from the specified
-	commit (`HEAD` if not specified).
+`--merged [<commit>]`::
+	Only list tags whose commits are reachable from
+	_<commit>_ (`HEAD` if not specified).
 
---no-merged [<commit>]::
-	Only list tags whose commits are not reachable from the specified
-	commit (`HEAD` if not specified).
+`--no-merged [<commit>]`::
+	Only list tags whose commits are not reachable from
+	_<commit>_ (`HEAD` if not specified).
 
---points-at <object>::
-	Only list tags of the given object (HEAD if not
+`--points-at [<object>]`::
+	Only list tags of _<object>_ (`HEAD` if not
 	specified). Implies `--list`.
 
--m <msg>::
---message=<msg>::
-	Use the given tag message (instead of prompting).
+`-m <msg>`::
+`--message=<msg>`::
+	Use _<msg>_ (instead of prompting).
 	If multiple `-m` options are given, their values are
 	concatenated as separate paragraphs.
 	Implies `-a` if none of `-a`, `-s`, or `-u <key-id>`
 	is given.
 
--F <file>::
---file=<file>::
-	Take the tag message from the given file.  Use '-' to
+`-F <file>`::
+`--file=<file>`::
+	Take the tag message from _<file>_.  Use `-` to
 	read the message from the standard input.
 	Implies `-a` if none of `-a`, `-s`, or `-u <key-id>`
 	is given.
 
---trailer <token>[(=|:)<value>]::
-	Specify a (<token>, <value>) pair that should be applied as a
+`--trailer <token>[(=|:)<value>]`::
+	Specify a (_<token>_, _<value>_) pair that should be applied as a
 	trailer. (e.g. `git tag --trailer "Custom-Key: value"`
 	will add a "Custom-Key" trailer to the tag message.)
 	The `trailer.*` configuration variables
@@ -190,58 +197,68 @@
 	The trailers can be extracted in `git tag --list`, using
 	`--format="%(trailers)"` placeholder.
 
--e::
---edit::
-	The message taken from file with `-F` and command line with
-	`-m` are usually used as the tag message unmodified.
-	This option lets you further edit the message taken from these sources.
+`-e`::
+`--edit`::
+	Let further edit the message taken from file with `-F` and command line with
+	`-m`.
 
---cleanup=<mode>::
-	This option sets how the tag message is cleaned up.
-	The  '<mode>' can be one of 'verbatim', 'whitespace' and 'strip'.  The
-	'strip' mode is default. The 'verbatim' mode does not change message at
-	all, 'whitespace' removes just leading/trailing whitespace lines and
-	'strip' removes both whitespace and commentary.
+`--cleanup=<mode>`::
+	Set how the tag message is cleaned up.
+	The  _<mode>_ can be one of `verbatim`, `whitespace` and `strip`.  The
+	`strip` mode is default. The `verbatim` mode does not change message at
+	all, `whitespace` removes just leading/trailing whitespace lines and
+	`strip` removes both whitespace and commentary.
 
---create-reflog::
+`--create-reflog`::
 	Create a reflog for the tag. To globally enable reflogs for tags, see
 	`core.logAllRefUpdates` in linkgit:git-config[1].
 	The negated form `--no-create-reflog` only overrides an earlier
 	`--create-reflog`, but currently does not negate the setting of
 	`core.logAllRefUpdates`.
 
---format=<format>::
+`--format=<format>`::
 	A string that interpolates `%(fieldname)` from a tag ref being shown
 	and the object it points at.  The format is the same as
 	that of linkgit:git-for-each-ref[1].  When unspecified,
 	defaults to `%(refname:strip=2)`.
 
-<tagname>::
+_<tagname>_::
 	The name of the tag to create, delete, or describe.
 	The new tag name must pass all checks defined by
 	linkgit:git-check-ref-format[1].  Some of these checks
 	may restrict the characters allowed in a tag name.
 
-<commit>::
-<object>::
+_<commit>_::
+_<object>_::
 	The object that the new tag will refer to, usually a commit.
-	Defaults to HEAD.
+	Defaults to `HEAD`.
 
 CONFIGURATION
 -------------
-By default, 'git tag' in sign-with-default mode (-s) will use your
+By default, `git tag` in sign-with-default mode (`-s`) will use your
 committer identity (of the form `Your Name <your@email.address>`) to
 find a key.  If you want to use a different default key, you can specify
 it in the repository configuration as follows:
 
 -------------------------------------
 [user]
-    signingKey = <gpg-key-id>
+    signingKey = <key-id>
 -------------------------------------
 
+The signing backend can be chosen via the `gpg.format` configuration
+variable, which defaults to `openpgp`. See linkgit:git-config[1]
+for a list of other supported formats.
+
+The path to the program used for each signing backend can be specified
+with the `gpg.<format>.program` configuration variable. For the
+`openpgp` backend, `gpg.program` can be used as a synonym for
+`gpg.openpgp.program`. See linkgit:git-config[1] for details.
+
 `pager.tag` is only respected when listing tags, i.e., when `-l` is
 used or implied. The default is to use a pager.
-See linkgit:git-config[1].
+
+See linkgit:git-config[1] for more details and other configuration
+variables.
 
 DISCUSSION
 ----------
@@ -252,7 +269,7 @@
 What should you do when you tag a wrong commit and you would
 want to re-tag?
 
-If you never pushed anything out, just re-tag it. Use "-f" to
+If you never pushed anything out, just re-tag it. Use `-f` to
 replace the old one. And you're done.
 
 But if you have pushed things out (or others could just read
@@ -268,12 +285,12 @@
 
 . The insane thing.
   You really want to call the new version "X" too, 'even though'
-  others have already seen the old one. So just use 'git tag -f'
+  others have already seen the old one. So just use `git tag -f`
   again, as if you hadn't already published the old one.
 
 However, Git does *not* (and it should not) change tags behind
 users back. So if somebody already got the old tag, doing a
-'git pull' on your tree shouldn't just make them overwrite the old
+`git pull` on your tree shouldn't just make them overwrite the old
 one.
 
 If somebody got a release tag from you, you cannot just change
@@ -325,7 +342,7 @@
 
 Often, "please pull" messages on the mailing list just provide
 two pieces of information: a repo URL and a branch name; this
-is designed to be easily cut&pasted at the end of a 'git fetch'
+is designed to be easily cut&pasted at the end of a `git fetch`
 command line:
 
 ------------
@@ -403,6 +420,14 @@
 	user in an editor session will be available in this file, but
 	may be overwritten by the next invocation of `git tag`.
 
+CONFIGURATION
+-------------
+
+include::includes/cmd-config-section-all.adoc[]
+
+:git-tag: 1
+include::config/tag.adoc[]
+
 NOTES
 -----
 
diff --git a/Documentation/git-update-index.adoc b/Documentation/git-update-index.adoc
index 7128aed..9bea9fa 100644
--- a/Documentation/git-update-index.adoc
+++ b/Documentation/git-update-index.adoc
@@ -86,7 +86,8 @@
 --chmod=(+|-)x::
         Set the execute permissions on the updated files.
 
---[no-]assume-unchanged::
+--assume-unchanged::
+--no-assume-unchanged::
 	When this flag is specified, the object names recorded
 	for the paths are not updated.  Instead, this option
 	sets/unsets the "assume unchanged" bit for the
@@ -108,18 +109,21 @@
 	Like `--refresh`, but checks stat information unconditionally,
 	without regard to the "assume unchanged" setting.
 
---[no-]skip-worktree::
+--skip-worktree::
+--no-skip-worktree::
 	When one of these flags is specified, the object names recorded
 	for the paths are not updated. Instead, these options
 	set and unset the "skip-worktree" bit for the paths. See
 	section "Skip-worktree bit" below for more information.
 
 
---[no-]ignore-skip-worktree-entries::
+--ignore-skip-worktree-entries::
+--no-ignore-skip-worktree-entries::
 	Do not remove skip-worktree (AKA "index-only") entries even when
 	the `--remove` option was specified.
 
---[no-]fsmonitor-valid::
+--fsmonitor-valid::
+--no-fsmonitor-valid::
 	When one of these flags is specified, the object names recorded
 	for the paths are not updated. Instead, these options
 	set and unset the "fsmonitor valid" bit for the paths. See
diff --git a/Documentation/git-upload-pack.adoc b/Documentation/git-upload-pack.adoc
index 516d163..9167a32 100644
--- a/Documentation/git-upload-pack.adoc
+++ b/Documentation/git-upload-pack.adoc
@@ -25,7 +25,8 @@
 OPTIONS
 -------
 
---[no-]strict::
+--strict::
+--no-strict::
 	Do not try <directory>/.git/ if <directory> is not a Git directory.
 
 --timeout=<n>::
diff --git a/Documentation/git-worktree.adoc b/Documentation/git-worktree.adoc
index 8340b7f..f272f79 100644
--- a/Documentation/git-worktree.adoc
+++ b/Documentation/git-worktree.adoc
@@ -8,16 +8,16 @@
 
 SYNOPSIS
 --------
-[verse]
-'git worktree add' [-f] [--detach] [--checkout] [--lock [--reason <string>]]
-		   [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]
-'git worktree list' [-v | --porcelain [-z]]
-'git worktree lock' [--reason <string>] <worktree>
-'git worktree move' <worktree> <new-path>
-'git worktree prune' [-n] [-v] [--expire <expire>]
-'git worktree remove' [-f] <worktree>
-'git worktree repair' [<path>...]
-'git worktree unlock' <worktree>
+[synopsis]
+git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]
+		 [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]
+git worktree list [-v | --porcelain [-z]]
+git worktree lock [--reason <string>] <worktree>
+git worktree move <worktree> <new-path>
+git worktree prune [-n] [-v] [--expire <expire>]
+git worktree remove [-f] <worktree>
+git worktree repair [<path>...]
+git worktree unlock <worktree>
 
 DESCRIPTION
 -----------
@@ -37,7 +37,7 @@
 remove it with `git worktree remove`.
 
 In its simplest form, `git worktree add <path>` automatically creates a
-new branch whose name is the final component of `<path>`, which is
+new branch whose name is the final component of _<path>_, which is
 convenient if you plan to work on a new topic. For instance, `git
 worktree add ../hotfix` creates new branch `hotfix` and checks it out at
 path `../hotfix`. To instead work on an existing branch in a new worktree,
@@ -63,16 +63,16 @@
 
 COMMANDS
 --------
-add <path> [<commit-ish>]::
+`add <path> [<commit-ish>]`::
 
-Create a worktree at `<path>` and checkout `<commit-ish>` into it. The new worktree
+Create a worktree at _<path>_ and checkout _<commit-ish>_ into it. The new worktree
 is linked to the current repository, sharing everything except per-worktree
-files such as `HEAD`, `index`, etc. As a convenience, `<commit-ish>` may
+files such as `HEAD`, `index`, etc. As a convenience, _<commit-ish>_ may
 be a bare "`-`", which is synonymous with `@{-1}`.
 +
-If `<commit-ish>` is a branch name (call it `<branch>`) and is not found,
+If _<commit-ish>_ is a branch name (call it _<branch>_) and is not found,
 and neither `-b` nor `-B` nor `--detach` are used, but there does
-exist a tracking branch in exactly one remote (call it `<remote>`)
+exist a tracking branch in exactly one remote (call it _<remote>_)
 with a matching name, treat as equivalent to:
 +
 ------------
@@ -81,32 +81,32 @@
 +
 If the branch exists in multiple remotes and one of them is named by
 the `checkout.defaultRemote` configuration variable, we'll use that
-one for the purposes of disambiguation, even if the `<branch>` isn't
+one for the purposes of disambiguation, even if the _<branch>_ isn't
 unique across all remotes. Set it to
 e.g. `checkout.defaultRemote=origin` to always checkout remote
-branches from there if `<branch>` is ambiguous but exists on the
+branches from there if _<branch>_ is ambiguous but exists on the
 `origin` remote. See also `checkout.defaultRemote` in
 linkgit:git-config[1].
 +
-If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,
+If _<commit-ish>_ is omitted and neither `-b` nor `-B` nor `--detach` used,
 then, as a convenience, the new worktree is associated with a branch (call
-it `<branch>`) named after `$(basename <path>)`.  If `<branch>` doesn't
+it _<branch>_) named after `$(basename <path>)`.  If _<branch>_ doesn't
 exist, a new branch based on `HEAD` is automatically created as if
-`-b <branch>` was given.  If `<branch>` does exist, it will be checked out
+`-b <branch>` was given.  If _<branch>_ does exist, it will be checked out
 in the new worktree, if it's not checked out anywhere else, otherwise the
 command will refuse to create the worktree (unless `--force` is used).
 +
-If `<commit-ish>` is omitted, neither `--detach`, or `--orphan` is
+If _<commit-ish>_ is omitted, neither `--detach`, or `--orphan` is
 used, and there are no valid local branches (or remote branches if
 `--guess-remote` is specified) then, as a convenience, the new worktree is
-associated with a new unborn branch named `<branch>` (after
+associated with a new unborn branch named _<branch>_ (after
 `$(basename <path>)` if neither `-b` or `-B` is used) as if `--orphan` was
 passed to the command. In the event the repository has a remote and
 `--guess-remote` is used, but no remote or local branches exist, then the
 command fails with a warning reminding the user to fetch from their remote
 first (or override by using `-f/--force`).
 
-list::
+`list`::
 
 List details of each worktree.  The main worktree is listed first,
 followed by each of the linked worktrees.  The output details include
@@ -115,32 +115,32 @@
 the worktree is locked, "prunable" if the worktree can be pruned by the
 `prune` command.
 
-lock::
+`lock`::
 
 If a worktree is on a portable device or network share which is not always
 mounted, lock it to prevent its administrative files from being pruned
 automatically. This also prevents it from being moved or deleted.
 Optionally, specify a reason for the lock with `--reason`.
 
-move::
+`move`::
 
 Move a worktree to a new location. Note that the main worktree or linked
 worktrees containing submodules cannot be moved with this command. (The
 `git worktree repair` command, however, can reestablish the connection
 with linked worktrees if you move the main worktree manually.)
 
-prune::
+`prune`::
 
 Prune worktree information in `$GIT_DIR/worktrees`.
 
-remove::
+`remove`::
 
 Remove a worktree. Only clean worktrees (no untracked files and no
 modification in tracked files) can be removed. Unclean worktrees or ones
 with submodules can be removed with `--force`. The main worktree cannot be
 removed.
 
-repair [<path>...]::
+`repair [<path>...]`::
 
 Repair worktree administrative files, if possible, if they have become
 corrupted or outdated due to external factors.
@@ -154,69 +154,72 @@
 using `git worktree move`, the main worktree (or bare repository) will be
 unable to locate it. Running `repair` within the recently-moved worktree
 will reestablish the connection. If multiple linked worktrees are moved,
-running `repair` from any worktree with each tree's new `<path>` as an
+running `repair` from any worktree with each tree's new _<path>_ as an
 argument, will reestablish the connection to all the specified paths.
 +
 If both the main worktree and linked worktrees have been moved or copied manually,
-then running `repair` in the main worktree and specifying the new `<path>`
+then running `repair` in the main worktree and specifying the new _<path>_
 of each linked worktree will reestablish all connections in both
 directions.
 
-unlock::
+`unlock`::
 
 Unlock a worktree, allowing it to be pruned, moved or deleted.
 
 OPTIONS
 -------
 
--f::
---force::
+`-f`::
+`--force`::
 	By default, `add` refuses to create a new worktree when
-	`<commit-ish>` is a branch name and is already checked out by
-	another worktree, or if `<path>` is already assigned to some
-	worktree but is missing (for instance, if `<path>` was deleted
+	_<commit-ish>_ is a branch name and is already checked out by
+	another worktree, or if _<path>_ is already assigned to some
+	worktree but is missing (for instance, if _<path>_ was deleted
 	manually). This option overrides these safeguards. To add a missing but
 	locked worktree path, specify `--force` twice.
 +
 `move` refuses to move a locked worktree unless `--force` is specified
 twice. If the destination is already assigned to some other worktree but is
-missing (for instance, if `<new-path>` was deleted manually), then `--force`
+missing (for instance, if _<new-path>_ was deleted manually), then `--force`
 allows the move to proceed; use `--force` twice if the destination is locked.
 +
 `remove` refuses to remove an unclean worktree unless `--force` is used.
 To remove a locked worktree, specify `--force` twice.
 
--b <new-branch>::
--B <new-branch>::
-	With `add`, create a new branch named `<new-branch>` starting at
-	`<commit-ish>`, and check out `<new-branch>` into the new worktree.
-	If `<commit-ish>` is omitted, it defaults to `HEAD`.
+`-b <new-branch>`::
+`-B <new-branch>`::
+	With `add`, create a new branch named _<new-branch>_ starting at
+	_<commit-ish>_, and check out _<new-branch>_ into the new worktree.
+	If _<commit-ish>_ is omitted, it defaults to `HEAD`.
 	By default, `-b` refuses to create a new branch if it already
-	exists. `-B` overrides this safeguard, resetting `<new-branch>` to
-	`<commit-ish>`.
+	exists. `-B` overrides this safeguard, resetting _<new-branch>_ to
+	_<commit-ish>_.
 
--d::
---detach::
+`-d`::
+`--detach`::
 	With `add`, detach `HEAD` in the new worktree. See "DETACHED HEAD"
 	in linkgit:git-checkout[1].
 
---[no-]checkout::
-	By default, `add` checks out `<commit-ish>`, however, `--no-checkout` can
+`--checkout`::
+`--no-checkout`::
+	By default, `add` checks out _<commit-ish>_, however, `--no-checkout` can
 	be used to suppress checkout in order to make customizations,
 	such as configuring sparse-checkout. See "Sparse checkout"
 	in linkgit:git-read-tree[1].
 
---[no-]guess-remote::
-	With `worktree add <path>`, without `<commit-ish>`, instead
+`--guess-remote`::
+`--no-guess-remote`::
+	With `worktree add <path>`, without _<commit-ish>_, instead
 	of creating a new branch from `HEAD`, if there exists a tracking
-	branch in exactly one remote matching the basename of `<path>`,
+	branch in exactly one remote matching the basename of _<path>_,
 	base the new branch on the remote-tracking branch, and mark
 	the remote-tracking branch as "upstream" from the new branch.
 +
 This can also be set up as the default behaviour by using the
 `worktree.guessRemote` config option.
 
---[no-]relative-paths::
+`--relative-paths`::
+`--no-relative-paths`::
 	Link worktrees using relative paths or absolute paths (default).
 	Overrides the `worktree.useRelativePaths` config option, see
 	linkgit:git-config[1].
@@ -224,59 +227,60 @@
 With `repair`, the linking files will be updated if there's an absolute/relative
 mismatch, even if the links are correct.
 
---[no-]track::
-	When creating a new branch, if `<commit-ish>` is a branch,
+`--track`::
+`--no-track`::
+	When creating a new branch, if _<commit-ish>_ is a branch,
 	mark it as "upstream" from the new branch.  This is the
-	default if `<commit-ish>` is a remote-tracking branch.  See
+	default if _<commit-ish>_ is a remote-tracking branch.  See
 	`--track` in linkgit:git-branch[1] for details.
 
---lock::
+`--lock`::
 	Keep the worktree locked after creation. This is the
 	equivalent of `git worktree lock` after `git worktree add`,
 	but without a race condition.
 
--n::
---dry-run::
+`-n`::
+`--dry-run`::
 	With `prune`, do not remove anything; just report what it would
 	remove.
 
---orphan::
+`--orphan`::
 	With `add`, make the new worktree and index empty, associating
-	the worktree with a new unborn branch named `<new-branch>`.
+	the worktree with a new unborn branch named _<new-branch>_.
 
---porcelain::
+`--porcelain`::
 	With `list`, output in an easy-to-parse format for scripts.
 	This format will remain stable across Git versions and regardless of user
 	configuration.  It is recommended to combine this with `-z`.
 	See below for details.
 
--z::
-	Terminate each line with a NUL rather than a newline when
+`-z`::
+	Terminate each line with a _NUL_ rather than a newline when
 	`--porcelain` is specified with `list`. This makes it possible
 	to parse the output when a worktree path contains a newline
 	character.
 
--q::
---quiet::
+`-q`::
+`--quiet`::
 	With `add`, suppress feedback messages.
 
--v::
---verbose::
+`-v`::
+`--verbose`::
 	With `prune`, report all removals.
 +
 With `list`, output additional information about worktrees (see below).
 
---expire <time>::
-	With `prune`, only expire unused worktrees older than `<time>`.
+`--expire <time>`::
+	With `prune`, only expire unused worktrees older than _<time>_.
 +
 With `list`, annotate missing worktrees as prunable if they are older than
-`<time>`.
+_<time>_.
 
---reason <string>::
+`--reason <string>`::
 	With `lock` or with `add --lock`, an explanation why the worktree
 	is locked.
 
-<worktree>::
+_<worktree>_::
 	Worktrees can be identified by path, either relative or absolute.
 +
 If the last path components in the worktree's path is unique among
@@ -518,6 +522,13 @@
 $ git worktree remove ../temp
 ------------
 
+CONFIGURATION
+-------------
+
+include::includes/cmd-config-section-all.adoc[]
+
+include::config/worktree.adoc[]
+
 BUGS
 ----
 Multiple checkout in general is still experimental, and the support
diff --git a/Documentation/gitcli.adoc b/Documentation/gitcli.adoc
index 1ea681b..6815d6b 100644
--- a/Documentation/gitcli.adoc
+++ b/Documentation/gitcli.adoc
@@ -216,6 +216,20 @@
 $ git describe --abbrev 10 HEAD  # NOT WHAT YOU MEANT
 ----------------------------
 
+
+Magic filename options
+~~~~~~~~~~~~~~~~~~~~~~
+Options that take a filename allow a prefix `:(optional)`. For example:
+
+----------------------------
+git commit -F :(optional)COMMIT_EDITMSG
+# if COMMIT_EDITMSG does not exist, the above is equivalent to
+git commit
+----------------------------
+
+Like with configuration values, if the named file is missing Git behaves as if
+the option was not given at all. See "Values" in linkgit:git-config[1].
+
 NOTES ON FREQUENTLY CONFUSED OPTIONS
 ------------------------------------
 
diff --git a/Documentation/gitformat-loose.adoc b/Documentation/gitformat-loose.adoc
new file mode 100644
index 0000000..9479936
--- /dev/null
+++ b/Documentation/gitformat-loose.adoc
@@ -0,0 +1,53 @@
+gitformat-loose(5)
+==================
+
+NAME
+----
+gitformat-loose - Git loose object format
+
+
+SYNOPSIS
+--------
+[verse]
+$GIT_DIR/objects/[0-9a-f][0-9a-f]/*
+
+DESCRIPTION
+-----------
+
+Loose objects are how Git stores individual objects, where every object is
+written as a separate file.
+
+Over the lifetime of a repository, objects are usually written as loose objects
+initially.  Eventually, these loose objects will be compacted into packfiles
+via repository maintenance to improve disk space usage and speed up the lookup
+of these objects.
+
+== Loose objects
+
+Each loose object contains a prefix, followed immediately by the data of the
+object.  The prefix contains `<type> <size>\0`.  `<type>` is one of `blob`,
+`tree`, `commit`, or `tag` and `size` is the size of the data (without the
+prefix) as a decimal integer expressed in ASCII.
+
+The entire contents, prefix and data concatenated, is then compressed with zlib
+and the compressed data is stored in the file.  The object ID of the object is
+the SHA-1 or SHA-256 (as appropriate) hash of the uncompressed data.
+
+The file for the loose object is stored under the `objects` directory, with the
+first two hex characters of the object ID being the directory and the remaining
+characters being the file name.  This is done to shard the data and avoid too
+many files being in one directory, since some file systems perform poorly with
+many items in a directory.
+
+As an example, the empty tree contains the data (when uncompressed) `tree 0\0`
+and, in a SHA-256 repository, would have the object ID
+`6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321` and would be
+stored under
+`$GIT_DIR/objects/6e/f19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321`.
+
+Similarly, a blob containing the contents `abc` would have the uncompressed
+data of `blob 3\0abc`.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/gitformat-pack.adoc b/Documentation/gitformat-pack.adoc
index d6ae229..1b4db4a 100644
--- a/Documentation/gitformat-pack.adoc
+++ b/Documentation/gitformat-pack.adoc
@@ -32,6 +32,10 @@
 and object IDs (object names) mentioned below are all computed using SHA-1.
 Similarly, in SHA-256 repositories, these values are computed using SHA-256.
 
+CRC32 checksums are always computed over the entire packed object, including
+the header (n-byte type and length); the base object name or offset, if any;
+and the entire compressed object.  The CRC32 algorithm used is that of zlib.
+
 == pack-*.pack files have the following format:
 
    - A header appears at the beginning and consists of the following:
@@ -80,6 +84,16 @@
 
 Type 5 is reserved for future expansion. Type 0 is invalid.
 
+=== Object encoding
+
+Unlike loose objects, packed objects do not have a prefix containing the type,
+size, and a NUL byte. These are not necessary because they can be determined by
+the n-byte type and length that prefixes the data and so they are omitted from
+the compressed and deltified data.
+
+The computation of the object ID still uses this prefix by reconstructing it
+from the type and length as needed.
+
 === Size encoding
 
 This document uses the following "size encoding" of non-negative
@@ -92,6 +106,11 @@
 This size encoding should not be confused with the "offset encoding",
 which is also used in this document.
 
+When encoding the size of an undeltified object in a pack, the size is that of
+the uncompressed raw object. For deltified objects, it is the size of the
+uncompressed delta.  The base object name or offset is not included in the size
+computation.
+
 === Deltified representation
 
 Conceptually there are only four object types: commit, tree, tag and
diff --git a/Documentation/gitignore.adoc b/Documentation/gitignore.adoc
index 5e0964e..9fccab4 100644
--- a/Documentation/gitignore.adoc
+++ b/Documentation/gitignore.adoc
@@ -111,6 +111,11 @@
    one of the characters in a range. See fnmatch(3) and the
    FNM_PATHNAME flag for a more detailed description.
 
+ - A backslash ("`\`") can be used to escape any character. E.g., "`\*`"
+   matches a literal asterisk (and "`\a`" matches "`a`", even though
+   there is no need for escaping there). As with fnmatch(3), a backslash
+   at the end of a pattern is an invalid pattern that never matches.
+
 Two consecutive asterisks ("`**`") in patterns matched against
 full pathname may have special meaning:
 
diff --git a/Documentation/gitprotocol-http.adoc b/Documentation/gitprotocol-http.adoc
index ec40a55..e2ef7f0 100644
--- a/Documentation/gitprotocol-http.adoc
+++ b/Documentation/gitprotocol-http.adoc
@@ -318,7 +318,7 @@
 
 
 Smart Service git-upload-pack
-------------------------------
+-----------------------------
 This service reads from the repository pointed to by `$GIT_URL`.
 
 Clients MUST first perform ref discovery with
@@ -443,7 +443,8 @@
 TODO: Define error if no "want" lines are requested.
 
 If any "want" object is not reachable, send an error:
-TODO: Define error if an invalid "want" is requested.
+When a Git server receives an invalid or malformed `want` line, it
+responds with an error message that includes the offending object name.
 
 Create an empty list, `s_common`.
 
diff --git a/Documentation/gitprotocol-v2.adoc b/Documentation/gitprotocol-v2.adoc
index 9a57005..c7db103 100644
--- a/Documentation/gitprotocol-v2.adoc
+++ b/Documentation/gitprotocol-v2.adoc
@@ -785,33 +785,64 @@
 save themselves and the server(s) the request(s) needed to inspect the
 headers of that bundle or bundles.
 
-promisor-remote=<pr-infos>
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+promisor-remote=<pr-info>
+~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The server may advertise some promisor remotes it is using or knows
 about to a client which may want to use them as its promisor remotes,
-instead of this repository. In this case <pr-infos> should be of the
+instead of this repository. In this case <pr-info> should be of the
 form:
 
-	pr-infos = pr-info | pr-infos ";" pr-info
+	pr-info = pr-fields | pr-info ";" pr-fields
 
-	pr-info = "name=" pr-name | "name=" pr-name "," "url=" pr-url
+	pr-fields = pr-field | pr-fields "," pr-field
 
-where `pr-name` is the urlencoded name of a promisor remote, and
-`pr-url` the urlencoded URL of that promisor remote.
+	pr-field = field-name "=" field-value
 
-In this case, if the client decides to use one or more promisor
-remotes the server advertised, it can reply with
-"promisor-remote=<pr-names>" where <pr-names> should be of the form:
+where all the `field-name` and `field-value` in a given `pr-fields`
+are field names and values related to a single promisor remote. A
+given `field-name` MUST NOT appear more than once in given
+`pr-fields`.
+
+The server MUST advertise at least the "name" and "url" field names
+along with the associated field values, which are the name of a valid
+remote and its URL, in each `pr-fields`. The "name" and "url" fields
+MUST appear first in each pr-fields, in that order.
+
+After these mandatory fields, the server MAY advertise the following
+optional fields in any order:
+
+`partialCloneFilter`:: The filter specification used by the remote.
+Clients can use this to determine if the remote's filtering strategy
+is compatible with their needs (e.g., checking if both use "blob:none").
+It corresponds to the "remote.<name>.partialCloneFilter" config setting.
+
+`token`:: An authentication token that clients can use when
+connecting to the remote. It corresponds to the "remote.<name>.token"
+config setting.
+
+No other fields are defined by the protocol at this time. Field names
+are case-sensitive and MUST be transmitted exactly as specified
+above. Clients MUST ignore fields they don't recognize to allow for
+future protocol extensions.
+
+For now, the client can only use information transmitted through these
+fields to decide if it accepts the advertised promisor remote. In the
+future that information might be used for other purposes though.
+
+Field values MUST be urlencoded.
+
+If the client decides to use one or more promisor remotes the server
+advertised, it can reply with "promisor-remote=<pr-names>" where
+<pr-names> should be of the form:
 
 	pr-names = pr-name | pr-names ";" pr-name
 
 where `pr-name` is the urlencoded name of a promisor remote the server
 advertised and the client accepts.
 
-Note that, everywhere in this document, `pr-name` MUST be a valid
-remote name, and the ';' and ',' characters MUST be encoded if they
-appear in `pr-name` or `pr-url`.
+Note that, everywhere in this document, the ';' and ',' characters
+MUST be encoded if they appear in `pr-name` or `field-value`.
 
 If the server doesn't know any promisor remote that could be good for
 a client to use, or prefers a client not to use any promisor remote it
@@ -822,9 +853,10 @@
 the server advertised, the client shouldn't advertise the
 "promisor-remote" capability at all in its reply.
 
-The "promisor.advertise" and "promisor.acceptFromServer" configuration
-options can be used on the server and client side to control what they
-advertise or accept respectively. See the documentation of these
+On the server side, the "promisor.advertise" and "promisor.sendFields"
+configuration options can be used to control what it advertises. On
+the client side, the "promisor.acceptFromServer" configuration option
+can be used to control what it accepts. See the documentation of these
 configuration options for more information.
 
 Note that in the future it would be nice if the "promisor-remote"
diff --git a/Documentation/gitsubmodules.adoc b/Documentation/gitsubmodules.adoc
index f7b5a25..2082296 100644
--- a/Documentation/gitsubmodules.adoc
+++ b/Documentation/gitsubmodules.adoc
@@ -8,6 +8,7 @@
 SYNOPSIS
 --------
  .gitmodules, $GIT_DIR/config
+
 ------------------
 git submodule
 git <command> --recurse-submodules
@@ -240,7 +241,7 @@
 
 
 Workflow for an artificially split repo
---------------------------------------
+---------------------------------------
 
   # Enable recursion for relevant commands, such that
   # regular commands recurse into submodules by default
diff --git a/Documentation/gitweb.conf.adoc b/Documentation/gitweb.conf.adoc
index 1348e9b..64bebb8 100644
--- a/Documentation/gitweb.conf.adoc
+++ b/Documentation/gitweb.conf.adoc
@@ -178,7 +178,7 @@
 	Show repository only if this file exists (in repository).  Only
 	effective if this variable evaluates to true.  Can be set when
 	building gitweb by setting `GITWEB_EXPORT_OK`.  This path is
-	relative to `GIT_DIR`.  git-daemon[1] uses 'git-daemon-export-ok',
+	relative to `GIT_DIR`.  linkgit:git-daemon[1] uses 'git-daemon-export-ok',
 	unless started with `--export-all`.  By default this variable is
 	not set, which means that this feature is turned off.
 
diff --git a/Documentation/howto/meson.build b/Documentation/howto/meson.build
index 8100002..16b9056 100644
--- a/Documentation/howto/meson.build
+++ b/Documentation/howto/meson.build
@@ -29,13 +29,13 @@
   output: 'howto-index.adoc',
 )
 
-custom_target(
+doc_targets += custom_target(
   command: asciidoc_html_options,
   input: howto_index,
   output: 'howto-index.html',
   depends: documentation_deps,
   install: true,
-  install_dir: get_option('datadir') / 'doc/git-doc',
+  install_dir: htmldir,
 )
 
 foreach howto : howto_sources
@@ -51,12 +51,12 @@
     capture: true,
   )
 
-  custom_target(
+  doc_targets += custom_target(
     command: asciidoc_html_options,
     input: howto_stripped,
     output: fs.stem(howto_stripped.full_path()) + '.html',
     depends: documentation_deps,
     install: true,
-    install_dir: get_option('datadir') / 'doc/git-doc/howto',
+    install_dir: htmldir / 'howto',
   )
 endforeach
diff --git a/Documentation/lint-delimited-sections.perl b/Documentation/lint-delimited-sections.perl
new file mode 100755
index 0000000..140b852
--- /dev/null
+++ b/Documentation/lint-delimited-sections.perl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my $exit_code = 0;
+sub report {
+	my ($msg) = @_;
+	print STDERR "$ARGV:$.: $msg\n";
+	$exit_code = 1;
+}
+
+my $line_length = 0;
+my $in_section = 0;
+my $section_header = "";
+
+
+while (my $line = <>) {
+	if (($line =~ /^\+?$/) ||
+	    ($line =~ /^\[.*\]$/) ||
+	    ($line =~ /^ifdef::/)) {
+		$line_length = 0;
+	} elsif ($line =~ /^[^-.]/) {
+		$line_length = length($line);
+	} elsif (($line =~ /^-{3,}$/) || ($line =~ /^\.{3,}$/)) {
+		if ($in_section) {
+			if ($line eq $section_header) {
+				$in_section = 0;
+			}
+		next;
+		}
+		if ($line_length == 0) {
+			$in_section = 1;
+			$section_header = $line;
+			next;
+		}
+		if (($line_length != 0) && (length($line) != $line_length)) {
+			report("section delimiter not preceded by an empty line");
+		}
+		$line_length = 0;
+	}
+}
+
+if ($in_section) {
+	report("section not finished");
+}
+
+exit $exit_code;
diff --git a/Documentation/lint-documentation-style.perl b/Documentation/lint-documentation-style.perl
new file mode 100755
index 0000000..d7ab732
--- /dev/null
+++ b/Documentation/lint-documentation-style.perl
@@ -0,0 +1,33 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my $exit_code = 0;
+sub report {
+	my ($line, $msg) = @_;
+	chomp $line;
+	print STDERR "$ARGV:$.: '$line' $msg\n";
+	$exit_code = 1;
+}
+
+my $synopsis_style = 0;
+
+while (my $line = <>) {
+	if ($line =~ /^[ \t]*`?[-a-z0-9.]+`?(, `?[-a-z0-9.]+`?)+(::|;;)$/) {
+
+		report($line, "multiple parameters in a definition list item");
+	}
+	if ($line =~ /^`?--\[no-\][a-z0-9-]+.*(::|;;)$/) {
+		report($line, "definition list item with a `--[no-]` parameter");
+	}
+	if ($line =~ /^\[synopsis\]$/) {
+		$synopsis_style = 1;
+	}
+	if (($line =~ /^(-[-a-z].*|<[-a-z0-9]+>(\.{3})?)(::|;;)$/) && ($synopsis_style)) {
+			report($line, "synopsis style and definition list item not backquoted");
+	}
+}
+
+
+exit $exit_code;
diff --git a/Documentation/lint-gitlink.perl b/Documentation/lint-gitlink.perl
index aea564d..f183a18 100755
--- a/Documentation/lint-gitlink.perl
+++ b/Documentation/lint-gitlink.perl
@@ -41,6 +41,13 @@
 @ARGV = $to_check;
 while (<>) {
 	my $line = $_;
+	while ($line =~ m/(.{,8})((git[-a-z]+|scalar)\[(\d)*\])/g) {
+	    my $pos = pos $line;
+	    my ($macro, $target, $page, $section) = ($1, $2, $3, $4);
+		if ( $macro ne "linkgit:" && $macro !~ "ifn?def::" && $macro ne "endif::" ) {
+			report($pos, $line, $target, "linkgit: macro expected");
+		}
+	}
 	while ($line =~ m/linkgit:((.*?)\[(\d)\])/g) {
 		my $pos = pos $line;
 		my ($target, $page, $section) = ($1, $2, $3);
diff --git a/Documentation/merge-options.adoc b/Documentation/merge-options.adoc
index 95ef491..9d43326 100644
--- a/Documentation/merge-options.adoc
+++ b/Documentation/merge-options.adoc
@@ -135,7 +135,8 @@
 Only useful when merging.
 endif::git-pull[]
 
-`--[no-]verify`::
+`--verify`::
+`--no-verify`::
 	By default, the pre-merge and commit-msg hooks are run.
 	When `--no-verify` is given, these are bypassed.
 	See also linkgit:githooks[5].
diff --git a/Documentation/mergetools/vimdiff.adoc b/Documentation/mergetools/vimdiff.adoc
index abfd426..b4ab83a 100644
--- a/Documentation/mergetools/vimdiff.adoc
+++ b/Documentation/mergetools/vimdiff.adoc
@@ -3,6 +3,7 @@
 
 When specifying `--tool=vimdiff` in `git mergetool` Git will open Vim with a 4
 windows layout distributed in the following way:
+
 ....
 ------------------------------------------
 |             |           |              |
@@ -56,6 +57,7 @@
 +
 --
 If, for some reason, we are not interested in the `BASE` buffer.
+
 ....
 ------------------------------------------
 |             |           |              |
@@ -72,6 +74,7 @@
 Only the `MERGED` buffer will be shown. Note, however, that all the other
 ones are still loaded in vim, and you can access them with the "buffers"
 command.
+
 ....
 ------------------------------------------
 |                                        |
@@ -88,6 +91,7 @@
 When `MERGED` is not present in the layout, you must "mark" one of the
 buffers with an arobase (`@`). That will become the buffer you need to edit and
 save after resolving the conflicts.
+
 ....
 ------------------------------------------
 |                   |                    |
@@ -106,6 +110,7 @@
 Three tabs will open: the first one is a copy of the default layout, while
 the other two only show the differences between (`BASE` and `LOCAL`) and
 (`BASE` and `REMOTE`) respectively.
+
 ....
 ------------------------------------------
 | <TAB #1> |  TAB #2  |  TAB #3  |       |
@@ -119,6 +124,7 @@
 |                                        |
 ------------------------------------------
 ....
+
 ....
 ------------------------------------------
 |  TAB #1  | <TAB #2> |  TAB #3  |       |
@@ -132,6 +138,7 @@
 |                   |                    |
 ------------------------------------------
 ....
+
 ....
 ------------------------------------------
 |  TAB #1  |  TAB #2  | <TAB #3> |       |
@@ -151,6 +158,7 @@
 --
 Same as the previous example, but adds a fourth tab with the same
 information as the first tab, with a different layout.
+
 ....
 ---------------------------------------------
 |  TAB #1  |  TAB #2  |  TAB #3  | <TAB #4> |
diff --git a/Documentation/meson.build b/Documentation/meson.build
index 4404c62..c00c9fe 100644
--- a/Documentation/meson.build
+++ b/Documentation/meson.build
@@ -74,6 +74,7 @@
   'git-init.adoc' : 1,
   'git-instaweb.adoc' : 1,
   'git-interpret-trailers.adoc' : 1,
+  'git-last-modified.adoc' : 1,
   'git-log.adoc' : 1,
   'git-ls-files.adoc' : 1,
   'git-ls-remote.adoc' : 1,
@@ -116,6 +117,7 @@
   'git-repack.adoc' : 1,
   'git-replace.adoc' : 1,
   'git-replay.adoc' : 1,
+  'git-repo.adoc' : 1,
   'git-request-pull.adoc' : 1,
   'git-rerere.adoc' : 1,
   'git-reset.adoc' : 1,
@@ -171,6 +173,7 @@
   'gitformat-chunk.adoc' : 5,
   'gitformat-commit-graph.adoc' : 5,
   'gitformat-index.adoc' : 5,
+  'gitformat-loose.adoc' : 5,
   'gitformat-pack.adoc' : 5,
   'gitformat-signature.adoc' : 5,
   'githooks.adoc' : 5,
@@ -375,7 +378,7 @@
       output: fs.stem(manpage) + '.xml',
     )
 
-    custom_target(
+    doc_targets += custom_target(
       command: [
         xmlto,
         '-m', '@INPUT0@',
@@ -398,7 +401,7 @@
   endif
 
   if get_option('docs').contains('html')
-    custom_target(
+    doc_targets += custom_target(
       command: asciidoc_common_options + [
         '--backend=' + asciidoc_html,
         '--doctype=manpage',
@@ -409,7 +412,7 @@
       input: manpage,
       output: fs.stem(manpage) + '.html',
       install: true,
-      install_dir: get_option('datadir') / 'doc/git-doc',
+      install_dir: htmldir,
     )
   endif
 endforeach
@@ -420,7 +423,7 @@
     output: 'docinfo.html',
     copy: true,
     install: true,
-    install_dir: get_option('datadir') / 'doc/git-doc',
+    install_dir: htmldir,
   )
 
   configure_file(
@@ -428,11 +431,11 @@
     output: 'docbook-xsl.css',
     copy: true,
     install: true,
-    install_dir: get_option('datadir') / 'doc/git-doc',
+    install_dir: htmldir,
   )
 
   install_symlink('index.html',
-    install_dir: get_option('datadir') / 'doc/git-doc',
+    install_dir: htmldir,
     pointing_to: 'git.html',
   )
 
@@ -450,7 +453,7 @@
     depends: documentation_deps,
   )
 
-  custom_target(
+  doc_targets += custom_target(
     command: [
       xsltproc,
       '--xinclude',
@@ -463,7 +466,7 @@
     input: 'docbook.xsl',
     output: 'user-manual.html',
     install: true,
-    install_dir: get_option('datadir') / 'doc/git-doc',
+    install_dir: htmldir,
   )
 
   articles = [
@@ -479,7 +482,7 @@
   ]
 
   foreach article : articles
-    custom_target(
+    doc_targets += custom_target(
       command: asciidoc_common_options + [
         '--backend=' + asciidoc_html,
         '--out-file=@OUTPUT@',
@@ -489,7 +492,7 @@
       output: fs.stem(article) + '.html',
       depends: documentation_deps,
       install: true,
-      install_dir: get_option('datadir') / 'doc/git-doc',
+      install_dir: htmldir,
     )
   endforeach
 
diff --git a/Documentation/pack-refs-options.adoc b/Documentation/pack-refs-options.adoc
new file mode 100644
index 0000000..0b11282
--- /dev/null
+++ b/Documentation/pack-refs-options.adoc
@@ -0,0 +1,52 @@
+--all::
+
+The command by default packs all tags and refs that are already
+packed, and leaves other refs
+alone.  This is because branches are expected to be actively
+developed and packing their tips does not help performance.
+This option causes all refs to be packed as well, with the exception
+of hidden refs, broken refs, and symbolic refs. Useful for a repository
+with many branches of historical interests.
+
+--no-prune::
+
+The command usually removes loose refs under `$GIT_DIR/refs`
+hierarchy after packing them.  This option tells it not to.
+
+--auto::
+
+Pack refs as needed depending on the current state of the ref database. The
+behavior depends on the ref format used by the repository and may change in the
+future.
++
+	- "files": Loose references are packed into the `packed-refs` file
+	  based on the ratio of loose references to the size of the
+	  `packed-refs` file. The bigger the `packed-refs` file, the more loose
+	  references need to exist before we repack.
++
+	- "reftable": Tables are compacted such that they form a geometric
+	  sequence. For two tables N and N+1, where N+1 is newer, this
+	  maintains the property that N is at least twice as big as N+1. Only
+	  tables that violate this property are compacted.
+
+--include <pattern>::
+
+Pack refs based on a `glob(7)` pattern. Repetitions of this option
+accumulate inclusion patterns. If a ref is both included in `--include` and
+`--exclude`, `--exclude` takes precedence. Using `--include` will preclude all
+tags from being included by default. Symbolic refs and broken refs will never
+be packed. When used with `--all`, it will be a noop. Use `--no-include` to clear
+and reset the list of patterns.
+
+--exclude <pattern>::
+
+Do not pack refs matching the given `glob(7)` pattern. Repetitions of this option
+accumulate exclusion patterns. Use `--no-exclude` to clear and reset the list of
+patterns. If a ref is already packed, including it with `--exclude` will not
+unpack it.
++
+When used with `--all`, pack only loose refs which do not match any of
+the provided `--exclude` patterns.
++
+When used with `--include`, refs provided to `--include`, minus refs that are
+provided to `--exclude` will be packed.
diff --git a/Documentation/pretty-options.adoc b/Documentation/pretty-options.adoc
index 8aac51d..658e462 100644
--- a/Documentation/pretty-options.adoc
+++ b/Documentation/pretty-options.adoc
@@ -61,15 +61,16 @@
 ifndef::git-rev-list[]
 `--notes[=<ref>]`::
 	Show the notes (see linkgit:git-notes[1]) that annotate the
-	commit, when showing the commit log message.  This is the default
+	commit, when showing the commit log message.
 ifndef::with-breaking-changes[]
-	for `git log`, `git show` and `git whatchanged` commands when
+This is the default for `git log`, `git show` and `git whatchanged`
+commands when there is no `--pretty`, `--format`, or `--oneline` option given
+on the command line.
 endif::with-breaking-changes[]
 ifdef::with-breaking-changes[]
-	for `git log` and `git show` commands when
+This is the default for `git log` and `git show` commands when there is no
+`--pretty`, `--format`, or `--oneline` option given on the command line.
 endif::with-breaking-changes[]
-	there is no `--pretty`, `--format`, or `--oneline` option given
-	on the command line.
 +
 By default, the notes shown are from the notes refs listed in the
 `core.notesRef` and `notes.displayRef` variables (or corresponding
diff --git a/Documentation/pull-fetch-param.adoc b/Documentation/pull-fetch-param.adoc
index d79d2f6..bb2cf6a 100644
--- a/Documentation/pull-fetch-param.adoc
+++ b/Documentation/pull-fetch-param.adoc
@@ -11,6 +11,7 @@
 	(See linkgit:git-config[1]).
 endif::git-pull[]
 
+[[fetch-refspec]]
 <refspec>::
 	Specifies which refs to fetch and which local refs to update.
 	When no <refspec>s appear on the command line, the refs to fetch
diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc
index 4bd5b15..f81b283 100644
--- a/Documentation/scalar.adoc
+++ b/Documentation/scalar.adoc
@@ -71,7 +71,8 @@
 	Instead of checking out the branch pointed to by the cloned
 	repository's HEAD, check out the `<name>` branch instead.
 
---[no-]single-branch::
+--single-branch::
+--no-single-branch::
 	Clone only the history leading to the tip of a single branch, either
 	specified by the `--branch` option or the primary branch remote's
 	`HEAD` points at.
@@ -81,23 +82,27 @@
 cloning. If the HEAD at the remote did not point at any branch when
 `--single-branch` clone was made, no remote-tracking branch is created.
 
---[no-]src::
+--src::
+--no-src::
 	By default, `scalar clone` places the cloned repository within a
 	`<entlistment>/src` directory. Use `--no-src` to place the cloned
 	repository directly in the `<enlistment>` directory.
 
---[no-]tags::
+--tags::
+--no-tags::
 	By default, `scalar clone` will fetch the tag objects advertised by
 	the remote and future `git fetch` commands will do the same. Use
 	`--no-tags` to avoid fetching tags in `scalar clone` and to configure
 	the repository to avoid fetching tags in the future. To fetch tags after
 	cloning with `--no-tags`, run `git fetch --tags`.
 
---[no-]full-clone::
+--full-clone::
+--no-full-clone::
 	A sparse-checkout is initialized by default. This behavior can be
 	turned off via `--full-clone`.
 
---[no-]maintenance::
+--maintenance::
+--no-maintenance::
 	By default, `scalar clone` configures the enlistment to use Git's
 	background maintenance feature. Use the `--no-maintenance` to skip
 	this configuration.
@@ -122,7 +127,8 @@
 parent directory is considered to be the Scalar enlistment. If the worktree is
 _not_ called `src/`, it itself will be considered to be the Scalar enlistment.
 
---[no-]maintenance::
+--maintenance::
+--no-maintenance::
 	By default, `scalar register` configures the enlistment to use Git's
 	background maintenance feature. Use the `--no-maintenance` to skip
 	this configuration. This does not disable any maintenance that may
diff --git a/Documentation/technical/api-path-walk.adoc b/Documentation/technical/api-path-walk.adoc
index 34c905e..a67de1b 100644
--- a/Documentation/technical/api-path-walk.adoc
+++ b/Documentation/technical/api-path-walk.adoc
@@ -39,7 +39,10 @@
 the objects will be walked in a separate way based on those starting
 commits.
 
-`commits`, `blobs`, `trees`, `tags`::
+`commits`::
+`blobs`::
+`trees`::
+`tags`::
 	By default, these members are enabled and signal that the path-walk
 	API should call the `path_fn` on objects of these types. Specialized
 	applications could disable some options to make it simpler to walk
diff --git a/Documentation/technical/commit-graph.adoc b/Documentation/technical/commit-graph.adoc
index 2c26e95..a259d15 100644
--- a/Documentation/technical/commit-graph.adoc
+++ b/Documentation/technical/commit-graph.adoc
@@ -39,6 +39,7 @@
 Values 1-4 satisfy the requirements of parse_commit_gently().
 
 There are two definitions of generation number:
+
 1. Corrected committer dates (generation number v2)
 2. Topological levels (generation number v1)
 
@@ -158,7 +159,8 @@
 we enable fast writes of new commit data without rewriting the entire commit
 history -- at least, most of the time.
 
-## File Layout
+File Layout
+~~~~~~~~~~~
 
 A commit-graph chain uses multiple files, and we use a fixed naming convention
 to organize these files. Each commit-graph file has a name
@@ -170,11 +172,11 @@
 
 For example, if the `commit-graph-chain` file contains the lines
 
-```
+----
 	{hash0}
 	{hash1}
 	{hash2}
-```
+----
 
 then the commit-graph chain looks like the following diagram:
 
@@ -213,7 +215,8 @@
 `graph-{hash1}.graph` contains `{hash0}` while `graph-{hash2}.graph` contains
 `{hash0}` and `{hash1}`.
 
-## Merging commit-graph files
+Merging commit-graph files
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 If we only added a new commit-graph file on every write, we would run into a
 linear search problem through many commit-graph files.  Instead, we use a merge
@@ -225,6 +228,7 @@
 the commits in `graph-{hash1}` should be combined into a new `graph-{hash3}`
 file.
 
+....
 			    +---------------------+
 			    |                     |
 			    |    (new commits)    |
@@ -250,6 +254,7 @@
  |                       |
  |                       |
  +-----------------------+
+....
 
 During this process, the commits to write are combined, sorted and we write the
 contents to a temporary file, all while holding a `commit-graph-chain.lock`
@@ -257,14 +262,15 @@
 according to the computed `{hash3}`. Finally, we write the new chain data to
 `commit-graph-chain.lock`:
 
-```
+----
 	{hash3}
 	{hash0}
-```
+----
 
 We then close the lock-file.
 
-## Merge Strategy
+Merge Strategy
+~~~~~~~~~~~~~~
 
 When writing a set of commits that do not exist in the commit-graph stack of
 height N, we default to creating a new file at level N + 1. We then decide to
@@ -289,7 +295,8 @@
 number of commits) could be extracted into config settings for full
 flexibility.
 
-## Handling Mixed Generation Number Chains
+Handling Mixed Generation Number Chains
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 With the introduction of generation number v2 and generation data chunk, the
 following scenario is possible:
@@ -318,7 +325,8 @@
 rewriting split commit-graph as a single file (`--split=replace`) creates a
 single layer with corrected commit dates.
 
-## Deleting graph-{hash} files
+Deleting graph-\{hash\} files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 After a new tip file is written, some `graph-{hash}` files may no longer
 be part of a chain. It is important to remove these files from disk, eventually.
@@ -333,7 +341,8 @@
 defaults to zero, but can be changed using command-line arguments or a config
 setting.
 
-## Chains across multiple object directories
+Chains across multiple object directories
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 In a repo with alternates, we look for the `commit-graph-chain` file starting
 in the local object directory and then in each alternate. The first file that
diff --git a/Documentation/technical/hash-function-transition.adoc b/Documentation/technical/hash-function-transition.adoc
index f047fd8..2359d7d 100644
--- a/Documentation/technical/hash-function-transition.adoc
+++ b/Documentation/technical/hash-function-transition.adoc
@@ -227,9 +227,9 @@
     ** 4-byte length in bytes of shortened object names. This is the
       shortest possible length needed to make names in the shortened
       object name table unambiguous.
-    ** 4-byte integer, recording where tables relating to this format
+    ** 8-byte integer, recording where tables relating to this format
       are stored in this index file, as an offset from the beginning.
-  * 4-byte offset to the trailer from the beginning of this file.
+  * 8-byte offset to the trailer from the beginning of this file.
   * Zero or more additional key/value pairs (4-byte key, 4-byte
     value). Only one key is supported: 'PSRC'. See the "Loose objects
     and unreachable objects" section for supported values and how this
@@ -260,12 +260,10 @@
     compressed data to be copied directly from pack to pack during
     repacking without undetected data corruption.
 
-  * A table of 4-byte offset values. For an object in the table of
-    sorted shortened object names, the value at the corresponding
-    index in this table indicates where that object can be found in
-    the pack file. These are usually 31-bit pack file offsets, but
-    large offsets are encoded as an index into the next table with the
-    most significant bit set.
+  * A table of 4-byte offset values. The index of this table in pack order
+    indicates where that object can be found in the pack file. These are
+    usually 31-bit pack file offsets, but large offsets are encoded as
+    an index into the next table with the most significant bit set.
 
   * A table of 8-byte offset entries (empty for pack files less than
     2 GiB). Pack files are organized with heavily used objects toward
@@ -276,10 +274,14 @@
   up to and not including the table of CRC32 values.
 - Zero or more NUL bytes.
 - The trailer consists of the following:
-  * A copy of the 20-byte SHA-256 checksum at the end of the
+  * A copy of the full main hash checksum at the end of the
     corresponding packfile.
 
-  * 20-byte SHA-256 checksum of all of the above.
+  * Full main hash checksum of all of the above.
+
+The "full main hash" is a full-length hash of the main (not compatibility)
+algorithm in the repository.  Thus, if the main algorithm is SHA-256, this is
+a 32-byte SHA-256 hash and for SHA-1, it's a 20-byte SHA-1 hash.
 
 Loose object index
 ~~~~~~~~~~~~~~~~~~
@@ -427,17 +429,19 @@
 
 Signed Tags
 ~~~~~~~~~~~
-We add a new field "gpgsig-sha256" to the tag object format to allow
-signing tags without relying on SHA-1. Its signed payload is the
-SHA-256 content of the tag with its gpgsig-sha256 field and "-----BEGIN PGP
-SIGNATURE-----" delimited in-body signature removed.
+We add new fields "gpgsig" and "gpgsig-sha256" to the tag object format to
+allow signing tags in both formats.  The in-body signature is used for the
+signature in the current hash algorithm and the header is used for the
+signature in the other algorithm.  Thus, a dual-signature tag will contain both
+an in-body signature and a gpgsig-sha256 header for the SHA-1 format of an
+object or both an in-body signature and a gpgsig header for the SHA-256 format
+of and object.
 
-This means tags can be signed
+The signed payload of the tag is the content of the tag in the current
+algorithm with both its gpgsig and gpgsig-sha256 fields and
+"-----BEGIN PGP SIGNATURE-----" delimited in-body signature removed.
 
-1. using SHA-1 only, as in existing signed tag objects
-2. using both SHA-1 and SHA-256, by using gpgsig-sha256 and an in-body
-   signature.
-3. using only SHA-256, by only using the gpgsig-sha256 field.
+This means tags can be signed using one or both algorithms.
 
 Mergetag embedding
 ~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/technical/large-object-promisors.adoc b/Documentation/technical/large-object-promisors.adoc
index dea8daf..2aa815e 100644
--- a/Documentation/technical/large-object-promisors.adoc
+++ b/Documentation/technical/large-object-promisors.adoc
@@ -34,8 +34,8 @@
 
 https://lore.kernel.org/git/xmqqbkdometi.fsf@gitster.g/
 
-0) Non goals
-------------
+Non goals
+---------
 
 - We will not discuss those client side improvements here, as they
   would require changes in different parts of Git than this effort.
@@ -90,8 +90,8 @@
     even more to host content with larger blobs or more large blobs
     than currently.
 
-I) Issues with the current situation
-------------------------------------
+I Issues with the current situation
+-----------------------------------
 
 - Some statistics made on GitLab repos have shown that more than 75%
   of the disk space is used by blobs that are larger than 1MB and
@@ -138,8 +138,8 @@
   complaining that these tools require significant effort to set up,
   learn and use correctly.
 
-II) Main features of the "Large Object Promisors" solution
-----------------------------------------------------------
+II Main features of the "Large Object Promisors" solution
+---------------------------------------------------------
 
 The main features below should give a rough overview of how the
 solution may work. Details about needed elements can be found in
@@ -166,7 +166,7 @@
 other objects.
 
 Note 1
-++++++
+^^^^^^
 
 To clarify, a LOP is a normal promisor remote, except that:
 
@@ -178,7 +178,7 @@
   itself.
 
 Note 2
-++++++
+^^^^^^
 
 Git already makes it possible for a main remote to also be a promisor
 remote storing both regular objects and large blobs for a client that
@@ -186,13 +186,13 @@
 to avoid that.
 
 Rationale
-+++++++++
+^^^^^^^^^
 
 LOPs aim to be good at handling large blobs while main remotes are
 already good at handling other objects.
 
 Implementation
-++++++++++++++
+^^^^^^^^^^^^^^
 
 Git already has support for multiple promisor remotes, see
 link:partial-clone.html#using-many-promisor-remotes[the partial clone documentation].
@@ -213,19 +213,19 @@
 underlying object storage appear like a remote to Git.
 
 Note
-++++
+^^^^
 
 A LOP can be a promisor remote accessed using a remote helper by
 both some clients and the main remote.
 
 Rationale
-+++++++++
+^^^^^^^^^
 
 This looks like the simplest way to create LOPs that can cheaply
 handle many large blobs.
 
 Implementation
-++++++++++++++
+^^^^^^^^^^^^^^
 
 Remote helpers are quite easy to write as shell scripts, but it might
 be more efficient and maintainable to write them using other languages
@@ -247,7 +247,7 @@
 storage for large files handled by Git LFS.
 
 Rationale
-+++++++++
+^^^^^^^^^
 
 This would simplify the server side if it wants to both use a LOP and
 act as a Git LFS server.
@@ -259,7 +259,7 @@
 LOP all its blobs with a size over a configurable threshold.
 
 Rationale
-+++++++++
+^^^^^^^^^
 
 This makes it easy to set things up and to clean things up. For
 example, an admin could use this to manually convert a repo not using
@@ -268,7 +268,7 @@
 to regularly make sure the large blobs are moved to the LOP.
 
 Implementation
-++++++++++++++
+^^^^^^^^^^^^^^
 
 Using something based on `git repack --filter=...` to separate the
 blobs we want to offload from the other Git objects could be a good
@@ -284,13 +284,13 @@
 perhaps pushed, into it.
 
 Rationale
-+++++++++
+^^^^^^^^^
 
 A main remote containing many oversize blobs would defeat the purpose
 of LOPs.
 
 Implementation
-++++++++++++++
+^^^^^^^^^^^^^^
 
 The way to offload to a LOP discussed in 4) above can be used to
 regularly offload oversize blobs. About preventing oversize blobs from
@@ -326,18 +326,18 @@
 fetch those blobs from the LOP to be able to serve the client.
 
 Note
-++++
+^^^^
 
 For fetches instead of clones, a protocol negotiation might not always
 happen, see the "What about fetches?" FAQ entry below for details.
 
 Rationale
-+++++++++
+^^^^^^^^^
 
 Security, configurability and efficiency of setting things up.
 
 Implementation
-++++++++++++++
+^^^^^^^^^^^^^^
 
 A "promisor-remote" protocol v2 capability looks like a good way to
 implement this. The way the client and server use this capability
@@ -356,7 +356,7 @@
 but might not need anymore, to the LOP.
 
 Note
-++++
+^^^^
 
 It might depend on the context if it should be OK or not for clients
 to offload large blobs they have created, instead of fetched, directly
@@ -367,13 +367,13 @@
 implementing this feature.
 
 Rationale
-+++++++++
+^^^^^^^^^
 
 On the client, the easiest way to deal with unneeded large blobs is to
 offload them.
 
 Implementation
-++++++++++++++
+^^^^^^^^^^^^^^
 
 This is very similar to what 4) above is about, except on the client
 side instead of the server side. So a good solution to 4) could likely
@@ -385,8 +385,8 @@
 a LOP, it is likely, and can easily be confirmed, that the LOP still
 has them, so that they can just be removed from the client.
 
-III) Benefits of using LOPs
----------------------------
+III Benefits of using LOPs
+--------------------------
 
 Many benefits are related to the issues discussed in "I) Issues with
 the current situation" above:
@@ -406,8 +406,8 @@
 
 - Reduced storage needs on the client side.
 
-IV) FAQ
--------
+IV FAQ
+------
 
 What about using multiple LOPs on the server and client side?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -533,7 +533,7 @@
 on a promisor remote.
 
 Regular fetch
-+++++++++++++
+^^^^^^^^^^^^^
 
 In a regular fetch, the client will contact the main remote and a
 protocol negotiation will happen between them. It's a good thing that
@@ -551,7 +551,7 @@
 using, or not using, the same LOP(s) as last time.
 
 "Backfill" or "lazy" fetch
-++++++++++++++++++++++++++
+^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 When there is a backfill fetch, the client doesn't necessarily contact
 the main remote first. It will try to fetch from its promisor remotes
@@ -576,8 +576,8 @@
 token when performing a protocol negotiation with the main remote (see
 section II.6 above).
 
-V) Future improvements
-----------------------
+V Future improvements
+---------------------
 
 It is expected that at the beginning using LOPs will be mostly worth
 it either in a corporate context where the Git version that clients
diff --git a/Documentation/technical/long-running-process-protocol.adoc b/Documentation/technical/long-running-process-protocol.adoc
index 6f33654..39bd89d 100644
--- a/Documentation/technical/long-running-process-protocol.adoc
+++ b/Documentation/technical/long-running-process-protocol.adoc
@@ -24,6 +24,7 @@
 it supports and a flush packet. Git expects to read a list of desired
 capabilities, which must be a subset of the supported capabilities list,
 and a flush packet as response:
+
 ------------------------
 packet:          git> git-filter-client
 packet:          git> version=2
diff --git a/Documentation/technical/meson.build b/Documentation/technical/meson.build
index a13aafc..faff396 100644
--- a/Documentation/technical/meson.build
+++ b/Documentation/technical/meson.build
@@ -13,6 +13,7 @@
   'commit-graph.adoc',
   'directory-rename-detection.adoc',
   'hash-function-transition.adoc',
+  'large-object-promisors.adoc',
   'long-running-process-protocol.adoc',
   'multi-pack-index.adoc',
   'packfile-uri.adoc',
@@ -46,22 +47,22 @@
   output: 'api-index.adoc',
 )
 
-custom_target(
+doc_targets += custom_target(
   command: asciidoc_html_options,
   input: api_index,
   output: 'api-index.html',
   depends: documentation_deps,
   install: true,
-  install_dir: get_option('datadir') / 'doc/git-doc/technical',
+  install_dir: htmldir / 'technical',
 )
 
 foreach article : api_docs + articles
-  custom_target(
+  doc_targets += custom_target(
     command: asciidoc_html_options,
     input: article,
     output: fs.stem(article) + '.html',
     depends: documentation_deps,
     install: true,
-    install_dir: get_option('datadir') / 'doc/git-doc/technical',
+    install_dir: htmldir / 'technical',
   )
 endforeach
diff --git a/Documentation/technical/remembering-renames.adoc b/Documentation/technical/remembering-renames.adoc
index 73f4176..6155f36c7 100644
--- a/Documentation/technical/remembering-renames.adoc
+++ b/Documentation/technical/remembering-renames.adoc
@@ -10,32 +10,32 @@
 
 Outline:
 
-  0. Assumptions
+  1. Assumptions
 
-  1. How rebasing and cherry-picking work
+  2. How rebasing and cherry-picking work
 
-  2. Why the renames on MERGE_SIDE1 in any given pick are *always* a
+  3. Why the renames on MERGE_SIDE1 in any given pick are *always* a
      superset of the renames on MERGE_SIDE1 for the next pick.
 
-  3. Why any rename on MERGE_SIDE1 in any given pick is _almost_ always also
+  4. Why any rename on MERGE_SIDE1 in any given pick is _almost_ always also
      a rename on MERGE_SIDE1 for the next pick
 
-  4. A detailed description of the counter-examples to #3.
+  5. A detailed description of the counter-examples to #4.
 
-  5. Why the special cases in #4 are still fully reasonable to use to pair
+  6. Why the special cases in #5 are still fully reasonable to use to pair
      up files for three-way content merging in the merge machinery, and why
      they do not affect the correctness of the merge.
 
-  6. Interaction with skipping of "irrelevant" renames
+  7. Interaction with skipping of "irrelevant" renames
 
-  7. Additional items that need to be cached
+  8. Additional items that need to be cached
 
-  8. How directory rename detection interacts with the above and why this
+  9. How directory rename detection interacts with the above and why this
      optimization is still safe even if merge.directoryRenames is set to
      "true".
 
 
-=== 0. Assumptions ===
+== 1. Assumptions ==
 
 There are two assumptions that will hold throughout this document:
 
@@ -44,8 +44,8 @@
 
   * All merges are fully automatic
 
-and a third that will hold in sections 2-5 for simplicity, that I'll later
-address in section 8:
+and a third that will hold in sections 3-6 for simplicity, that I'll later
+address in section 9:
 
   * No directory renames occur
 
@@ -77,9 +77,9 @@
 stored on disk, and thus is thrown away as soon as the rebase or cherry
 pick stops for the user to resolve the operation.
 
-The third assumption makes sections 2-5 simpler, and allows people to
+The third assumption makes sections 3-6 simpler, and allows people to
 understand the basics of why this optimization is safe and effective, and
-then I can go back and address the specifics in section 8.  It is probably
+then I can go back and address the specifics in section 9.  It is probably
 also worth noting that if directory renames do occur, then the default of
 merge.directoryRenames being set to "conflict" means that the operation
 will stop for users to resolve the conflicts and the cache will be thrown
@@ -88,22 +88,26 @@
 users will have set merge.directoryRenames to "true" to allow the merges to
 continue to proceed automatically.  The optimization is still safe with
 this config setting, but we have to discuss a few more cases to show why;
-this discussion is deferred until section 8.
+this discussion is deferred until section 9.
 
 
-=== 1. How rebasing and cherry-picking work ===
+== 2. How rebasing and cherry-picking work ==
 
 Consider the following setup (from the git-rebase manpage):
 
+------------
 		     A---B---C topic
 		    /
 	       D---E---F---G main
+------------
 
 After rebasing or cherry-picking topic onto main, this will appear as:
 
+------------
 			     A'--B'--C' topic
 			    /
 	       D---E---F---G main
+------------
 
 The way the commits A', B', and C' are created is through a series of
 merges, where rebase or cherry-pick sequentially uses each of the three
@@ -111,6 +115,7 @@
 in the merge operation as MERGE_BASE, MERGE_SIDE1, and MERGE_SIDE2.  For
 this picture, the three commits for each of the three merges would be:
 
+....
 To create A':
    MERGE_BASE:   E
    MERGE_SIDE1:  G
@@ -125,6 +130,7 @@
    MERGE_BASE:   B
    MERGE_SIDE1:  B'
    MERGE_SIDE2:  C
+....
 
 Sometimes, folks are surprised that these three-way merges are done.  It
 can be useful in understanding these three-way merges to view them in a
@@ -138,8 +144,7 @@
 B, B', and C, at least the parts before you decide to record a commit.
 
 
-=== 2. Why the renames on MERGE_SIDE1 in any given pick are always a ===
-===    superset of the renames on MERGE_SIDE1 for the next pick.     ===
+== 3. Why the renames on MERGE_SIDE1 in any given pick are always a superset of the renames on MERGE_SIDE1 for the next pick. ==
 
 The merge machinery uses the filenames it is fed from MERGE_BASE,
 MERGE_SIDE1, and MERGE_SIDE2.  It will only move content to a different
@@ -156,6 +161,7 @@
 First, let's remember what commits are involved in the first and second
 picks of the cherry-pick or rebase sequence:
 
+....
 To create A':
    MERGE_BASE:   E
    MERGE_SIDE1:  G
@@ -165,6 +171,7 @@
    MERGE_BASE:   A
    MERGE_SIDE1:  A'
    MERGE_SIDE2:  B
+....
 
 So, in particular, we need to show that the renames between E and G are a
 superset of those between A and A'.
@@ -181,11 +188,11 @@
 and G are a superset of those between A and A'.
 
 
-=== 3. Why any rename on MERGE_SIDE1 in any given pick is _almost_   ===
-===    always also a rename on MERGE_SIDE1 for the next pick.        ===
+== 4. Why any rename on MERGE_SIDE1 in any given pick is _almost_ always also a rename on MERGE_SIDE1 for the next pick. ==
 
 Let's again look at the first two picks:
 
+....
 To create A':
    MERGE_BASE:   E
    MERGE_SIDE1:  G
@@ -195,17 +202,25 @@
    MERGE_BASE:   A
    MERGE_SIDE1:  A'
    MERGE_SIDE2:  B
+....
 
 Now let's look at any given rename from MERGE_SIDE1 of the first pick, i.e.
 any given rename from E to G.  Let's use the filenames 'oldfile' and
 'newfile' for demonstration purposes.  That first pick will function as
 follows; when the rename is detected, the merge machinery will do a
 three-way content merge of the following:
+
+....
     E:oldfile
     G:newfile
     A:oldfile
+....
+
 and produce a new result:
+
+....
     A':newfile
+....
 
 Note above that I've assumed that E->A did not rename oldfile.  If that
 side did rename, then we most likely have a rename/rename(1to2) conflict
@@ -254,19 +269,21 @@
 detectable as renames almost always.
 
 
-=== 4. A detailed description of the counter-examples to #3.         ===
+== 5. A detailed description of the counter-examples to #4. ==
 
-We already noted in section 3 that rename/rename(1to1) (i.e. both sides
+We already noted in section 4 that rename/rename(1to1) (i.e. both sides
 renaming a file the same way) was one counter-example.  The more
 interesting bit, though, is why did we need to use the "almost" qualifier
 when stating that A:oldfile and A':newfile are "almost" always detectable
 as renames?
 
-Let's repeat an earlier point that section 3 made:
+Let's repeat an earlier point that section 4 made:
 
+....
   A':newfile was created by applying the changes between E:oldfile and
   G:newfile to A:oldfile.  The changes between E:oldfile and G:newfile were
   <50% of the size of E:oldfile.
+....
 
 If those changes that were <50% of the size of E:oldfile are also <50% of
 the size of A:oldfile, then A:oldfile and A':newfile will be detectable as
@@ -276,18 +293,21 @@
 detect A:oldfile and A':newfile as renames.
 
 Here's an example where that can happen:
+
   * E:oldfile had 20 lines
   * G:newfile added 10 new lines at the beginning of the file
   * A:oldfile kept the first 3 lines of the file, and deleted all the rest
+
 then
+
+....
   => A':newfile would have 13 lines, 3 of which matches those in A:oldfile.
-E:oldfile -> G:newfile would be detected as a rename, but A:oldfile and
-A':newfile would not be.
+  E:oldfile -> G:newfile would be detected as a rename, but A:oldfile and
+  A':newfile would not be.
+....
 
 
-=== 5. Why the special cases in #4 are still fully reasonable to use to    ===
-===    pair up files for three-way content merging in the merge machinery, ===
-===    and why they do not affect the correctness of the merge.            ===
+== 6. Why the special cases in #5 are still fully reasonable to use to pair up files for three-way content merging in the merge machinery, and why they do not affect the correctness of the merge. ==
 
 In the rename/rename(1to1) case, A:newfile and A':newfile are not renames
 since they use the *same* filename.  However, files with the same filename
@@ -295,14 +315,14 @@
 machinery has never employed break detection).  The interesting
 counter-example case is thus not the rename/rename(1to1) case, but the case
 where A did not rename oldfile.  That was the case that we spent most of
-the time discussing in sections 3 and 4.  The remainder of this section
+the time discussing in sections 4 and 5.  The remainder of this section
 will be devoted to that case as well.
 
 So, even if A:oldfile and A':newfile aren't detectable as renames, why is
 it still reasonable to pair them up for three-way content merging in the
 merge machinery?  There are multiple reasons:
 
-  * As noted in sections 3 and 4, the diff between A:oldfile and A':newfile
+  * As noted in sections 4 and 5, the diff between A:oldfile and A':newfile
     is *exactly* the same as the diff between E:oldfile and G:newfile.  The
     latter pair were detected as renames, so it seems unlikely to surprise
     users for us to treat A:oldfile and A':newfile as renames.
@@ -394,7 +414,7 @@
 optimization than without.
 
 
-=== 6. Interaction with skipping of "irrelevant" renames ===
+== 7. Interaction with skipping of "irrelevant" renames ==
 
 Previous optimizations involved skipping rename detection for paths
 considered to be "irrelevant".  See for example the following commits:
@@ -421,24 +441,27 @@
 already detected renames.
 
 
-=== 7. Additional items that need to be cached ===
+== 8. Additional items that need to be cached ==
 
 It turns out we have to cache more than just renames; we also cache:
 
+....
   A) non-renames (i.e. unpaired deletes)
   B) counts of renames within directories
   C) sources that were marked as RELEVANT_LOCATION, but which were
      downgraded to RELEVANT_NO_MORE
   D) the toplevel trees involved in the merge
+....
 
 These are all stored in struct rename_info, and respectively appear in
+
   * cached_pairs (along side actual renames, just with a value of NULL)
   * dir_rename_counts
   * cached_irrelevant
   * merge_trees
 
-The reason for (A) comes from the irrelevant renames skipping
-optimization discussed in section 6.  The fact that irrelevant renames
+The reason for `(A)` comes from the irrelevant renames skipping
+optimization discussed in section 7.  The fact that irrelevant renames
 are skipped means we only get a subset of the potential renames
 detected and subsequent commits may need to run rename detection on
 the upstream side on a subset of the remaining renames (to get the
@@ -447,23 +470,24 @@
 repeatedly check that those paths remain unpaired on the upstream side
 with every commit we are transplanting.
 
-The reason for (B) is that diffcore_rename_extended() is what
+The reason for `(B)` is that diffcore_rename_extended() is what
 generates the counts of renames by directory which is needed in
 directory rename detection, and if we don't run
 diffcore_rename_extended() again then we need to have the output from
 it, including dir_rename_counts, from the previous run.
 
-The reason for (C) is that merge-ort's tree traversal will again think
+The reason for `(C)` is that merge-ort's tree traversal will again think
 those paths are relevant (marking them as RELEVANT_LOCATION), but the
 fact that they were downgraded to RELEVANT_NO_MORE means that
 dir_rename_counts already has the information we need for directory
 rename detection.  (A path which becomes RELEVANT_CONTENT in a
 subsequent commit will be removed from cached_irrelevant.)
 
-The reason for (D) is that is how we determine whether the remember
+The reason for `(D)` is that is how we determine whether the remember
 renames optimization can be used.  In particular, remembering that our
 sequence of merges looks like:
 
+....
    Merge 1:
    MERGE_BASE:   E
    MERGE_SIDE1:  G
@@ -475,6 +499,7 @@
    MERGE_SIDE1:  A'
    MERGE_SIDE2:  B
    => Creates    B'
+....
 
 It is the fact that the trees A and A' appear both in Merge 1 and in
 Merge 2, with A as a parent of A' that allows this optimization.  So
@@ -482,12 +507,11 @@
 time.
 
 
-=== 8. How directory rename detection interacts with the above and   ===
-===    why this optimization is still safe even if                   ===
-===    merge.directoryRenames is set to "true".                      ===
+== 9. How directory rename detection interacts with the above and why this optimization is still safe even if merge.directoryRenames is set to "true". ==
 
 As noted in the assumptions section:
 
+....
     """
     ...if directory renames do occur, then the default of
     merge.directoryRenames being set to "conflict" means that the operation
@@ -497,11 +521,13 @@
     is that some users will have set merge.directoryRenames to "true" to
     allow the merges to continue to proceed automatically.
     """
+....
 
 Let's remember that we need to look at how any given pick affects the next
 one.  So let's again use the first two picks from the diagram in section
 one:
 
+....
   First pick does this three-way merge:
     MERGE_BASE:   E
     MERGE_SIDE1:  G
@@ -513,6 +539,7 @@
     MERGE_SIDE1:  A'
     MERGE_SIDE2:  B
     => creates B'
+....
 
 Now, directory rename detection exists so that if one side of history
 renames a directory, and the other side adds a new file to the old
@@ -545,7 +572,7 @@
     concerned; see the assumptions section).  Two interesting sub-notes
     about these counts:
 
-    * If we need to perform rename-detection again on the given side (e.g.
+   ** If we need to perform rename-detection again on the given side (e.g.
       some paths are relevant for rename detection that weren't before),
       then we clear dir_rename_counts and recompute it, making use of
       cached_pairs.  The reason it is important to do this is optimizations
@@ -556,7 +583,7 @@
       easiest way to "fix up" dir_rename_counts in such cases is to just
       recompute it.
 
-    * If we prune rename/rename(1to1) entries from the cache, then we also
+   ** If we prune rename/rename(1to1) entries from the cache, then we also
       need to update dir_rename_counts to decrement the counts for the
       involved directory and any relevant parent directories (to undo what
       update_dir_rename_counts() in diffcore-rename.c incremented when the
@@ -578,6 +605,7 @@
 
 Case 1: MERGE_SIDE1 renames old dir, MERGE_SIDE2 adds new file to old dir
 
+....
   This case looks like this:
 
     MERGE_BASE:   E,   Has olddir/
@@ -595,10 +623,13 @@
     * MERGE_SIDE1 has cached olddir/newfile -> newdir/newfile
   Given the cached rename noted above, the second merge can proceed as
   expected without needing to perform rename detection from A -> A'.
+....
 
 Case 2: MERGE_SIDE1 renames old dir, MERGE_SIDE2 renames  file into old dir
 
+....
   This case looks like this:
+
     MERGE_BASE:   E    oldfile, olddir/
     MERGE_SIDE1:  G    oldfile, olddir/ -> newdir/
     MERGE_SIDE2:  A    oldfile -> olddir/newfile
@@ -617,9 +648,11 @@
 
   Given the cached rename noted above, the second merge can proceed as
   expected without needing to perform rename detection from A -> A'.
+....
 
 Case 3: MERGE_SIDE1 adds new file to   old dir, MERGE_SIDE2 renames old dir
 
+....
   This case looks like this:
 
     MERGE_BASE:   E,   Has olddir/
@@ -635,9 +668,11 @@
   In this case, with the optimization, note that after the first commit there
   were no renames on MERGE_SIDE1, and any renames on MERGE_SIDE2 are tossed.
   But the second merge didn't need any renames so this is fine.
+....
 
 Case 4: MERGE_SIDE1 renames  file into old dir, MERGE_SIDE2 renames old dir
 
+....
   This case looks like this:
 
     MERGE_BASE:   E,   Has olddir/
@@ -658,6 +693,7 @@
 
   Given the cached rename noted above, the second merge can proceed as
   expected without needing to perform rename detection from A -> A'.
+....
 
 Finally, I'll just note here that interactions with the
 skip-irrelevant-renames optimization means we sometimes don't detect
diff --git a/Documentation/technical/sparse-checkout.adoc b/Documentation/technical/sparse-checkout.adoc
index 0f750ef..3fa8e53 100644
--- a/Documentation/technical/sparse-checkout.adoc
+++ b/Documentation/technical/sparse-checkout.adoc
@@ -14,37 +14,41 @@
   * Reference Emails
 
 
-=== Terminology ===
+== Terminology ==
 
-cone mode: one of two modes for specifying the desired subset of files
+*`cone mode`*::
+	one of two modes for specifying the desired subset of files
 	in a sparse-checkout.  In cone-mode, the user specifies
 	directories (getting both everything under that directory as
 	well as everything in leading directories), while in non-cone
 	mode, the user specifies gitignore-style patterns.  Controlled
 	by the --[no-]cone option to sparse-checkout init|set.
 
-SKIP_WORKTREE: When tracked files do not match the sparse specification and
+*`SKIP_WORKTREE`*::
+	When tracked files do not match the sparse specification and
 	are removed from the working tree, the file in the index is marked
 	with a SKIP_WORKTREE bit.  Note that if a tracked file has the
 	SKIP_WORKTREE bit set but the file is later written by the user to
 	the working tree anyway, the SKIP_WORKTREE bit will be cleared at
 	the beginning of any subsequent Git operation.
++
+Most sparse checkout users are unaware of this implementation
+detail, and the term should generally be avoided in user-facing
+descriptions and command flags.  Unfortunately, prior to the
+`sparse-checkout` subcommand this low-level detail was exposed,
+and as of time of writing, is still exposed in various places.
 
-	Most sparse checkout users are unaware of this implementation
-	detail, and the term should generally be avoided in user-facing
-	descriptions and command flags.  Unfortunately, prior to the
-	`sparse-checkout` subcommand this low-level detail was exposed,
-	and as of time of writing, is still exposed in various places.
-
-sparse-checkout: a subcommand in git used to reduce the files present in
+*`sparse-checkout`*::
+	a subcommand in git used to reduce the files present in
 	the working tree to a subset of all tracked files.  Also, the
 	name of the file in the $GIT_DIR/info directory used to track
 	the sparsity patterns corresponding to the user's desired
 	subset.
 
-sparse cone: see cone mode
+*`sparse cone`*:: see cone mode
 
-sparse directory: An entry in the index corresponding to a directory, which
+*`sparse directory`*::
+	An entry in the index corresponding to a directory, which
 	appears in the index instead of all the files under that directory
 	that would normally appear.  See also sparse-index.  Something that
 	can cause confusion is that the "sparse directory" does NOT match
@@ -52,7 +56,8 @@
 	working tree.  May be renamed in the future (e.g. to "skipped
 	directory").
 
-sparse index: A special mode for sparse-checkout that also makes the
+*`sparse index`*::
+	A special mode for sparse-checkout that also makes the
 	index sparse by recording a directory entry in lieu of all the
 	files underneath that directory (thus making that a "skipped
 	directory" which unfortunately has also been called a "sparse
@@ -60,7 +65,8 @@
 	directories.  Controlled by the --[no-]sparse-index option to
 	init|set|reapply.
 
-sparsity patterns: patterns from $GIT_DIR/info/sparse-checkout used to
+*`sparsity patterns`*::
+	patterns from $GIT_DIR/info/sparse-checkout used to
 	define the set of files of interest.  A warning: It is easy to
 	over-use this term (or the shortened "patterns" term), for two
 	reasons: (1) users in cone mode specify directories rather than
@@ -70,7 +76,8 @@
 	transiently differ in the working tree or index from the sparsity
 	patterns (see "Sparse specification vs. sparsity patterns").
 
-sparse specification: The set of paths in the user's area of focus.  This
+*`sparse specification`*::
+	The set of paths in the user's area of focus.  This
 	is typically just the tracked files that match the sparsity
 	patterns, but the sparse specification can temporarily differ and
 	include additional files.  (See also "Sparse specification
@@ -87,12 +94,13 @@
 	* If working with the index and the working copy, the sparse
 	  specification is the union of the paths from above.
 
-vivifying: When a command restores a tracked file to the working tree (and
+*`vivifying`*::
+	When a command restores a tracked file to the working tree (and
 	hopefully also clears the SKIP_WORKTREE bit in the index for that
 	file), this is referred to as "vivifying" the file.
 
 
-=== Purpose of sparse-checkouts ===
+== Purpose of sparse-checkouts ==
 
 sparse-checkouts exist to allow users to work with a subset of their
 files.
@@ -120,14 +128,12 @@
 half dozen different ways.  Let's start by considering the high level
 usecases:
 
-  A) Users are _only_ interested in the sparse portion of the repo
-
-  A*) Users are _only_ interested in the sparse portion of the repo
-      that they have downloaded so far
-
-  B) Users want a sparse working tree, but are working in a larger whole
-
-  C) sparse-checkout is a behind-the-scenes implementation detail allowing
+[horizontal]
+A):: Users are _only_ interested in the sparse portion of the repo
+A*):: Users are _only_ interested in the sparse portion of the repo
+     that they have downloaded so far
+B):: Users want a sparse working tree, but are working in a larger whole
+C):: sparse-checkout is a behind-the-scenes implementation detail allowing
      Git to work with a specially crafted in-house virtual file system;
      users are actually working with a "full" working tree that is
      lazily populated, and sparse-checkout helps with the lazy population
@@ -136,7 +142,7 @@
 It may be worth explaining each of these in a bit more detail:
 
 
-  (Behavior A) Users are _only_ interested in the sparse portion of the repo
+=== (Behavior A) Users are _only_ interested in the sparse portion of the repo
 
 These folks might know there are other things in the repository, but
 don't care.  They are uninterested in other parts of the repository, and
@@ -163,8 +169,7 @@
 after a merge or pull) can lead to worries about local repository size
 growing unnecessarily[10].
 
-  (Behavior A*) Users are _only_ interested in the sparse portion of the repo
-      that they have downloaded so far (a variant on the first usecase)
+=== (Behavior A*) Users are _only_ interested in the sparse portion of the repo that they have downloaded so far (a variant on the first usecase)
 
 This variant is driven by folks who using partial clones together with
 sparse checkouts and do disconnected development (so far sounding like a
@@ -173,15 +178,14 @@
 through history within their sparse specification may be too much, so they
 only download some.  They would still like operations to succeed without
 network connectivity, though, so things like `git log -S${SEARCH_TERM} -p`
-or `git grep ${SEARCH_TERM} OLDREV ` would need to be prepared to provide
+or `git grep ${SEARCH_TERM} OLDREV` would need to be prepared to provide
 partial results that depend on what happens to have been downloaded.
 
 This variant could be viewed as Behavior A with the sparse specification
 for history querying operations modified from "sparsity patterns" to
 "sparsity patterns limited to the blobs we have already downloaded".
 
-  (Behavior B) Users want a sparse working tree, but are working in a
-      larger whole
+=== (Behavior B) Users want a sparse working tree, but are working in a larger whole
 
 Stolee described this usecase this way[11]:
 
@@ -229,8 +233,7 @@
 prefer getting "unrelated" results from their history queries over having
 slow commands.
 
-  (Behavior C) sparse-checkout is an implementational detail supporting a
-	       special VFS.
+=== (Behavior C) sparse-checkout is an implementational detail supporting a special VFS.
 
 This usecase goes slightly against the traditional definition of
 sparse-checkout in that it actually tries to present a full or dense
@@ -255,13 +258,13 @@
 all files are present.
 
 
-=== Usecases of primary concern ===
+== Usecases of primary concern ==
 
 Most of the rest of this document will focus on Behavior A and Behavior
 B.  Some notes about the other two cases and why we are not focusing on
 them:
 
-  (Behavior A*)
+=== (Behavior A*)
 
 Supporting this usecase is estimated to be difficult and a lot of work.
 There are no plans to implement it currently, but it may be a potential
@@ -275,7 +278,7 @@
 sparse specification to restrict it to already-downloaded blobs.  The hard
 part is in making commands capable of respecting that modified definition.
 
-  (Behavior C)
+=== (Behavior C)
 
 This usecase violates some of the early sparse-checkout documented
 assumptions (since files marked as SKIP_WORKTREE will be displayed to users
@@ -300,20 +303,20 @@
 patches that break things for the real Behavior B folks.
 
 
-=== Oversimplified mental models ===
+== Oversimplified mental models ==
 
 An oversimplification of the differences in the above behaviors is:
 
-  Behavior A: Restrict worktree and history operations to sparse specification
-  Behavior B: Restrict worktree operations to sparse specification; have any
-	      history operations work across all files
-  Behavior C: Do not restrict either worktree or history operations to the
-	      sparse specification...with the exception of branch checkouts or
-	      switches which avoid writing files that will match the index so
-	      they can later lazily be populated instead.
+(Behavior A):: Restrict worktree and history operations to sparse specification
+(Behavior B):: Restrict worktree operations to sparse specification; have any
+	     history operations work across all files
+(Behavior C):: Do not restrict either worktree or history operations to the
+	     sparse specification...with the exception of branch checkouts or
+	     switches which avoid writing files that will match the index so
+	     they can later lazily be populated instead.
 
 
-=== Desired behavior ===
+== Desired behavior ==
 
 As noted previously, despite the simple idea of just working with a subset
 of files, there are a range of different behavioral changes that need to be
@@ -326,37 +329,38 @@
 
 * Commands behaving the same regardless of high-level use-case
 
-  * commands that only look at files within the sparsity specification
+  ** commands that only look at files within the sparsity specification
 
-      * diff (without --cached or REVISION arguments)
-      * grep (without --cached or REVISION arguments)
-      * diff-files
+      *** diff (without --cached or REVISION arguments)
+      *** grep (without --cached or REVISION arguments)
+      *** diff-files
 
-  * commands that restore files to the working tree that match sparsity
+  ** commands that restore files to the working tree that match sparsity
     patterns, and remove unmodified files that don't match those
     patterns:
 
-      * switch
-      * checkout (the switch-like half)
-      * read-tree
-      * reset --hard
+      *** switch
+      *** checkout (the switch-like half)
+      *** read-tree
+      *** reset --hard
 
-  * commands that write conflicted files to the working tree, but otherwise
+  ** commands that write conflicted files to the working tree, but otherwise
     will omit writing files to the working tree that do not match the
     sparsity patterns:
 
-      * merge
-      * rebase
-      * cherry-pick
-      * revert
+      *** merge
+      *** rebase
+      *** cherry-pick
+      *** revert
 
-      * `am` and `apply --cached` should probably be in this section but
+      *** `am` and `apply --cached` should probably be in this section but
 	are buggy (see the "Known bugs" section below)
 
     The behavior for these commands somewhat depends upon the merge
     strategy being used:
-      * `ort` behaves as described above
-      * `octopus` and `resolve` will always vivify any file changed in the merge
+
+      *** `ort` behaves as described above
+      *** `octopus` and `resolve` will always vivify any file changed in the merge
 	relative to the first parent, which is rather suboptimal.
 
     It is also important to note that these commands WILL update the index
@@ -372,21 +376,21 @@
     specification and the sparsity patterns (much like the commands in the
     previous section).
 
-  * commands that always ignore sparsity since commits must be full-tree
+  ** commands that always ignore sparsity since commits must be full-tree
 
-      * archive
-      * bundle
-      * commit
-      * format-patch
-      * fast-export
-      * fast-import
-      * commit-tree
+      *** archive
+      *** bundle
+      *** commit
+      *** format-patch
+      *** fast-export
+      *** fast-import
+      *** commit-tree
 
-  * commands that write any modified file to the working tree (conflicted
+  ** commands that write any modified file to the working tree (conflicted
     or not, and whether those paths match sparsity patterns or not):
 
-      * stash
-      * apply (without `--index` or `--cached`)
+      *** stash
+      *** apply (without `--index` or `--cached`)
 
 * Commands that may slightly differ for behavior A vs. behavior B:
 
@@ -394,19 +398,20 @@
   behaviors, but may differ in verbosity and types of warning and error
   messages.
 
-  * commands that make modifications to which files are tracked:
-      * add
-      * rm
-      * mv
-      * update-index
+  ** commands that make modifications to which files are tracked:
+
+      *** add
+      *** rm
+      *** mv
+      *** update-index
 
     The fact that files can move between the 'tracked' and 'untracked'
     categories means some commands will have to treat untracked files
     differently.  But if we have to treat untracked files differently,
     then additional commands may also need changes:
 
-      * status
-      * clean
+      *** status
+      *** clean
 
     In particular, `status` may need to report any untracked files outside
     the sparsity specification as an erroneous condition (especially to
@@ -420,9 +425,10 @@
     may need to ignore the sparse specification by its nature.  Also, its
     current --[no-]ignore-skip-worktree-entries default is totally bogus.
 
-  * commands for manually tweaking paths in both the index and the working tree
-      * `restore`
-      * the restore-like half of `checkout`
+  ** commands for manually tweaking paths in both the index and the working tree
+
+      *** `restore`
+      *** the restore-like half of `checkout`
 
     These commands should be similar to add/rm/mv in that they should
     only operate on the sparse specification by default, and require a
@@ -433,18 +439,19 @@
 
 * Commands that significantly differ for behavior A vs. behavior B:
 
-  * commands that query history
-      * diff (with --cached or REVISION arguments)
-      * grep (with --cached or REVISION arguments)
-      * show (when given commit arguments)
-      * blame (only matters when one or more -C flags are passed)
-	* and annotate
-      * log
-      * whatchanged (may not exist anymore)
-      * ls-files
-      * diff-index
-      * diff-tree
-      * ls-tree
+  ** commands that query history
+
+      *** diff (with --cached or REVISION arguments)
+      *** grep (with --cached or REVISION arguments)
+      *** show (when given commit arguments)
+      *** blame (only matters when one or more -C flags are passed)
+	**** and annotate
+      *** log
+      *** whatchanged (may not exist anymore)
+      *** ls-files
+      *** diff-index
+      *** diff-tree
+      *** ls-tree
 
     Note: for log and whatchanged, revision walking logic is unaffected
     but displaying of patches is affected by scoping the command to the
@@ -458,91 +465,91 @@
 
 * Commands I don't know how to classify
 
-  * range-diff
+  ** range-diff
 
     Is this like `log` or `format-patch`?
 
-  * cherry
+  ** cherry
 
     See range-diff
 
 * Commands unaffected by sparse-checkouts
 
-  * shortlog
-  * show-branch
-  * rev-list
-  * bisect
+  ** shortlog
+  ** show-branch
+  ** rev-list
+  ** bisect
 
-  * branch
-  * describe
-  * fetch
-  * gc
-  * init
-  * maintenance
-  * notes
-  * pull (merge & rebase have the necessary changes)
-  * push
-  * submodule
-  * tag
+  ** branch
+  ** describe
+  ** fetch
+  ** gc
+  ** init
+  ** maintenance
+  ** notes
+  ** pull (merge & rebase have the necessary changes)
+  ** push
+  ** submodule
+  ** tag
 
-  * config
-  * filter-branch (works in separate checkout without sparse-checkout setup)
-  * pack-refs
-  * prune
-  * remote
-  * repack
-  * replace
+  ** config
+  ** filter-branch (works in separate checkout without sparse-checkout setup)
+  ** pack-refs
+  ** prune
+  ** remote
+  ** repack
+  ** replace
 
-  * bugreport
-  * count-objects
-  * fsck
-  * gitweb
-  * help
-  * instaweb
-  * merge-tree (doesn't touch worktree or index, and merges always compute full-tree)
-  * rerere
-  * verify-commit
-  * verify-tag
+  ** bugreport
+  ** count-objects
+  ** fsck
+  ** gitweb
+  ** help
+  ** instaweb
+  ** merge-tree (doesn't touch worktree or index, and merges always compute full-tree)
+  ** rerere
+  ** verify-commit
+  ** verify-tag
 
-  * commit-graph
-  * hash-object
-  * index-pack
-  * mktag
-  * mktree
-  * multi-pack-index
-  * pack-objects
-  * prune-packed
-  * symbolic-ref
-  * unpack-objects
-  * update-ref
-  * write-tree (operates on index, possibly optimized to use sparse dir entries)
+  ** commit-graph
+  ** hash-object
+  ** index-pack
+  ** mktag
+  ** mktree
+  ** multi-pack-index
+  ** pack-objects
+  ** prune-packed
+  ** symbolic-ref
+  ** unpack-objects
+  ** update-ref
+  ** write-tree (operates on index, possibly optimized to use sparse dir entries)
 
-  * for-each-ref
-  * get-tar-commit-id
-  * ls-remote
-  * merge-base (merges are computed full tree, so merge base should be too)
-  * name-rev
-  * pack-redundant
-  * rev-parse
-  * show-index
-  * show-ref
-  * unpack-file
-  * var
-  * verify-pack
+  ** for-each-ref
+  ** get-tar-commit-id
+  ** ls-remote
+  ** merge-base (merges are computed full tree, so merge base should be too)
+  ** name-rev
+  ** pack-redundant
+  ** rev-parse
+  ** show-index
+  ** show-ref
+  ** unpack-file
+  ** var
+  ** verify-pack
 
-  * <Everything under 'Interacting with Others' in 'git help --all'>
-  * <Everything under 'Low-level...Syncing' in 'git help --all'>
-  * <Everything under 'Low-level...Internal Helpers' in 'git help --all'>
-  * <Everything under 'External commands' in 'git help --all'>
+  ** <Everything under 'Interacting with Others' in 'git help --all'>
+  ** <Everything under 'Low-level...Syncing' in 'git help --all'>
+  ** <Everything under 'Low-level...Internal Helpers' in 'git help --all'>
+  ** <Everything under 'External commands' in 'git help --all'>
 
 * Commands that might be affected, but who cares?
 
-  * merge-file
-  * merge-index
-  * gitk?
+  ** merge-file
+  ** merge-index
+  ** gitk?
 
 
-=== Behavior classes ===
+== Behavior classes ==
 
 From the above there are a few classes of behavior:
 
@@ -573,18 +580,19 @@
 
     Commands in this class generally behave like the "restrict" class,
     except that:
-      (1) they will ignore the sparse specification and write files with
-	  conflicts to the working tree (thus temporarily expanding the
-	  sparse specification to include such files.)
-      (2) they are grouped with commands which move to a new commit, since
-	  they often create a commit and then move to it, even though we
-	  know there are many exceptions to moving to the new commit.  (For
-	  example, the user may rebase a commit that becomes empty, or have
-	  a cherry-pick which conflicts, or a user could run `merge
-	  --no-commit`, and we also view `apply --index` kind of like `am
-	  --no-commit`.)  As such, these commands can make changes to index
-	  files outside the sparse specification, though they'll mark such
-	  files with SKIP_WORKTREE.
+
+	(1) they will ignore the sparse specification and write files with
+	    conflicts to the working tree (thus temporarily expanding the
+	    sparse specification to include such files.)
+	(2) they are grouped with commands which move to a new commit, since
+	    they often create a commit and then move to it, even though we
+	    know there are many exceptions to moving to the new commit.  (For
+	    example, the user may rebase a commit that becomes empty, or have
+	    a cherry-pick which conflicts, or a user could run `merge
+	    --no-commit`, and we also view `apply --index` kind of like `am
+	    --no-commit`.)  As such, these commands can make changes to index
+	    files outside the sparse specification, though they'll mark such
+	    files with SKIP_WORKTREE.
 
   * "restrict also specially applied to untracked files"
 
@@ -609,37 +617,39 @@
     specification.
 
 
-=== Subcommand-dependent defaults ===
+== Subcommand-dependent defaults ==
 
 Note that we have different defaults depending on the command for the
 desired behavior :
 
   * Commands defaulting to "restrict":
-    * diff-files
-    * diff (without --cached or REVISION arguments)
-    * grep (without --cached or REVISION arguments)
-    * switch
-    * checkout (the switch-like half)
-    * reset (<commit>)
 
-    * restore
-    * checkout (the restore-like half)
-    * checkout-index
-    * reset (with pathspec)
+    ** diff-files
+    ** diff (without --cached or REVISION arguments)
+    ** grep (without --cached or REVISION arguments)
+    ** switch
+    ** checkout (the switch-like half)
+    ** reset (<commit>)
+
+    ** restore
+    ** checkout (the restore-like half)
+    ** checkout-index
+    ** reset (with pathspec)
 
     This behavior makes sense; these interact with the working tree.
 
   * Commands defaulting to "restrict modulo conflicts":
-    * merge
-    * rebase
-    * cherry-pick
-    * revert
 
-    * am
-    * apply --index (which is kind of like an `am --no-commit`)
+    ** merge
+    ** rebase
+    ** cherry-pick
+    ** revert
 
-    * read-tree (especially with -m or -u; is kind of like a --no-commit merge)
-    * reset (<tree-ish>, due to similarity to read-tree)
+    ** am
+    ** apply --index (which is kind of like an `am --no-commit`)
+
+    ** read-tree (especially with -m or -u; is kind of like a --no-commit merge)
+    ** reset (<tree-ish>, due to similarity to read-tree)
 
     These also interact with the working tree, but require slightly
     different behavior either so that (a) conflicts can be resolved or (b)
@@ -648,16 +658,17 @@
     (See also the "Known bugs" section below regarding `am` and `apply`)
 
   * Commands defaulting to "no restrict":
-    * archive
-    * bundle
-    * commit
-    * format-patch
-    * fast-export
-    * fast-import
-    * commit-tree
 
-    * stash
-    * apply (without `--index`)
+    ** archive
+    ** bundle
+    ** commit
+    ** format-patch
+    ** fast-export
+    ** fast-import
+    ** commit-tree
+
+    ** stash
+    ** apply (without `--index`)
 
     These have completely different defaults and perhaps deserve the most
     detailed explanation:
@@ -679,53 +690,59 @@
     sparse specification then we'll lose changes from the user.
 
   * Commands defaulting to "restrict also specially applied to untracked files":
-    * add
-    * rm
-    * mv
-    * update-index
-    * status
-    * clean (?)
 
-    Our original implementation for the first three of these commands was
-    "no restrict", but it had some severe usability issues:
-      * `git add <somefile>` if honored and outside the sparse
-	specification, can result in the file randomly disappearing later
-	when some subsequent command is run (since various commands
-	automatically clean up unmodified files outside the sparse
-	specification).
-      * `git rm '*.jpg'` could very negatively surprise users if it deletes
-	files outside the range of the user's interest.
-      * `git mv` has similar surprises when moving into or out of the cone,
-	so best to restrict by default
+    ** add
+    ** rm
+    ** mv
+    ** update-index
+    ** status
+    ** clean (?)
 
-    So, we switched `add` and `rm` to default to "restrict", which made
-    usability problems much less severe and less frequent, but we still got
-    complaints because commands like:
-	git add <file-outside-sparse-specification>
-	git rm <file-outside-sparse-specification>
-    would silently do nothing.  We should instead print an error in those
-    cases to get usability right.
+....
+        Our original implementation for the first three of these commands was
+        "no restrict", but it had some severe usability issues:
 
-    update-index needs to be updated to match, and status and maybe clean
-    also need to be updated to specially handle untracked paths.
+          * `git add <somefile>` if honored and outside the sparse
+	    specification, can result in the file randomly disappearing later
+	    when some subsequent command is run (since various commands
+	    automatically clean up unmodified files outside the sparse
+	    specification).
+          * `git rm '*.jpg'` could very negatively surprise users if it deletes
+	    files outside the range of the user's interest.
+          * `git mv` has similar surprises when moving into or out of the cone,
+	    so best to restrict by default
 
-    There may be a difference in here between behavior A and behavior B in
-    terms of verboseness of errors or additional warnings.
+        So, we switched `add` and `rm` to default to "restrict", which made
+        usability problems much less severe and less frequent, but we still got
+        complaints because commands like:
+
+	    git add <file-outside-sparse-specification>
+	    git rm <file-outside-sparse-specification>
+
+        would silently do nothing.  We should instead print an error in those
+        cases to get usability right.
+
+        update-index needs to be updated to match, and status and maybe clean
+        also need to be updated to specially handle untracked paths.
+
+        There may be a difference in here between behavior A and behavior B in
+        terms of verboseness of errors or additional warnings.
+....
 
   * Commands falling under "restrict or no restrict dependent upon behavior
     A vs. behavior B"
 
-    * diff (with --cached or REVISION arguments)
-    * grep (with --cached or REVISION arguments)
-    * show (when given commit arguments)
-    * blame (only matters when one or more -C flags passed)
-      * and annotate
-    * log
-      * and variants: shortlog, gitk, show-branch, whatchanged, rev-list
-    * ls-files
-    * diff-index
-    * diff-tree
-    * ls-tree
+    ** diff (with --cached or REVISION arguments)
+    ** grep (with --cached or REVISION arguments)
+    ** show (when given commit arguments)
+    ** blame (only matters when one or more -C flags passed)
+      *** and annotate
+    ** log
+      *** and variants: shortlog, gitk, show-branch, whatchanged, rev-list
+    ** ls-files
+    ** diff-index
+    ** diff-tree
+    ** ls-tree
 
     For now, we default to behavior B for these, which want a default of
     "no restrict".
@@ -749,7 +766,7 @@
     implemented.
 
 
-=== Sparse specification vs. sparsity patterns ===
+== Sparse specification vs. sparsity patterns ==
 
 In a well-behaved situation, the sparse specification is given directly
 by the $GIT_DIR/info/sparse-checkout file.  However, it can transiently
@@ -821,45 +838,48 @@
 operate full-tree.
 
 
-=== Implementation Questions ===
+== Implementation Questions ==
 
-  * Do the options --scope={sparse,all} sound good to others?  Are there better
-    options?
-    * Names in use, or appearing in patches, or previously suggested:
-      * --sparse/--dense
-      * --ignore-skip-worktree-bits
-      * --ignore-skip-worktree-entries
-      * --ignore-sparsity
-      * --[no-]restrict-to-sparse-paths
-      * --full-tree/--sparse-tree
-      * --[no-]restrict
-      * --scope={sparse,all}
-      * --focus/--unfocus
-      * --limit/--unlimited
-    * Rationale making me lean slightly towards --scope={sparse,all}:
-      * We want a name that works for many commands, so we need a name that
+  * Do the options --scope={sparse,all} sound good to others?  Are there better options?
+
+    ** Names in use, or appearing in patches, or previously suggested:
+
+      *** --sparse/--dense
+      *** --ignore-skip-worktree-bits
+      *** --ignore-skip-worktree-entries
+      *** --ignore-sparsity
+      *** --[no-]restrict-to-sparse-paths
+      *** --full-tree/--sparse-tree
+      *** --[no-]restrict
+      *** --scope={sparse,all}
+      *** --focus/--unfocus
+      *** --limit/--unlimited
+
+    ** Rationale making me lean slightly towards --scope={sparse,all}:
+
+      *** We want a name that works for many commands, so we need a name that
 	does not conflict
-      * We know that we have more than two possible usecases, so it is best
+      *** We know that we have more than two possible usecases, so it is best
 	to avoid a flag that appears to be binary.
-      * --scope={sparse,all} isn't overly long and seems relatively
+      *** --scope={sparse,all} isn't overly long and seems relatively
 	explanatory
-      * `--sparse`, as used in add/rm/mv, is totally backwards for
+      *** `--sparse`, as used in add/rm/mv, is totally backwards for
 	grep/log/etc.  Changing the meaning of `--sparse` for these
 	commands would fix the backwardness, but possibly break existing
 	scripts.  Using a new name pairing would allow us to treat
 	`--sparse` in these commands as a deprecated alias.
-      * There is a different `--sparse`/`--dense` pair for commands using
+      *** There is a different `--sparse`/`--dense` pair for commands using
 	revision machinery, so using that naming might cause confusion
-      * There is also a `--sparse` in both pack-objects and show-branch, which
+      *** There is also a `--sparse` in both pack-objects and show-branch, which
 	don't conflict but do suggest that `--sparse` is overloaded
-      * The name --ignore-skip-worktree-bits is a double negative, is
+      *** The name --ignore-skip-worktree-bits is a double negative, is
 	quite a mouthful, refers to an implementation detail that many
 	users may not be familiar with, and we'd need a negation for it
 	which would probably be even more ridiculously long.  (But we
 	can make --ignore-skip-worktree-bits a deprecated alias for
 	--no-restrict.)
 
-  * If a config option is added (sparse.scope?) what should the values and
+  ** If a config option is added (sparse.scope?) what should the values and
     description be?  "sparse" (behavior A), "worktree-sparse-history-dense"
     (behavior B), "dense" (behavior C)?  There's a risk of confusion,
     because even for Behaviors A and B we want some commands to be
@@ -868,19 +888,20 @@
     the primary difference we are focusing is just the history-querying
     commands (log/diff/grep).  Previous config suggestion here: [13]
 
-  * Is `--no-expand` a good alias for ls-files's `--sparse` option?
+  ** Is `--no-expand` a good alias for ls-files's `--sparse` option?
     (`--sparse` does not map to either `--scope=sparse` or `--scope=all`,
     because in non-cone mode it does nothing and in cone-mode it shows the
     sparse directory entries which are technically outside the sparse
     specification)
 
-  * Under Behavior A:
-    * Does ls-files' `--no-expand` override the default `--scope=all`, or
-      does it need an extra flag?
-    * Does ls-files' `-t` option imply `--scope=all`?
-    * Does update-index's `--[no-]skip-worktree` option imply `--scope=all`?
+  ** Under Behavior A:
 
-  * sparse-checkout: once behavior A is fully implemented, should we take
+    *** Does ls-files' `--no-expand` override the default `--scope=all`, or
+      does it need an extra flag?
+    *** Does ls-files' `-t` option imply `--scope=all`?
+    *** Does update-index's `--[no-]skip-worktree` option imply `--scope=all`?
+
+  ** sparse-checkout: once behavior A is fully implemented, should we take
     an interim measure to ease people into switching the default?  Namely,
     if folks are not already in a sparse checkout, then require
     `sparse-checkout init/set` to take a
@@ -892,7 +913,7 @@
     is seamless for them.
 
 
-=== Implementation Goals/Plans ===
+== Implementation Goals/Plans ==
 
  * Get buy-in on this document in general.
 
@@ -910,25 +931,26 @@
    request that they not trigger this bug." flag
 
  * Flags & Config
-   * Make `--sparse` in add/rm/mv a deprecated alias for `--scope=all`
-   * Make `--ignore-skip-worktree-bits` in checkout-index/checkout/restore
+
+   ** Make `--sparse` in add/rm/mv a deprecated alias for `--scope=all`
+   ** Make `--ignore-skip-worktree-bits` in checkout-index/checkout/restore
      a deprecated aliases for `--scope=all`
-   * Create config option (sparse.scope?), tie it to the "Cliff notes"
+   ** Create config option (sparse.scope?), tie it to the "Cliff notes"
      overview
 
-   * Add --scope=sparse (and --scope=all) flag to each of the history querying
+   ** Add --scope=sparse (and --scope=all) flag to each of the history querying
      commands.  IMPORTANT: make sure diff machinery changes don't mess with
      format-patch, fast-export, etc.
 
-=== Known bugs ===
+== Known bugs ==
 
 This list used to be a lot longer (see e.g. [1,2,3,4,5,6,7,8,9]), but we've
 been working on it.
 
-0. Behavior A is not well supported in Git.  (Behavior B didn't used to
+1. Behavior A is not well supported in Git.  (Behavior B didn't used to
    be either, but was the easier of the two to implement.)
 
-1. am and apply:
+2. am and apply:
 
    apply, without `--index` or `--cached`, relies on files being present
    in the working copy, and also writes to them unconditionally.  As
@@ -948,7 +970,7 @@
    files and then complain that those vivified files would be
    overwritten by merge.
 
-2. reset --hard:
+3. reset --hard:
 
    reset --hard provides confusing error message (works correctly, but
    misleads the user into believing it didn't):
@@ -971,13 +993,13 @@
     `git reset --hard` DID remove addme from the index and the working tree, contrary
     to the error message, but in line with how reset --hard should behave.
 
-3. read-tree
+4. read-tree
 
    `read-tree` doesn't apply the 'SKIP_WORKTREE' bit to *any* of the
    entries it reads into the index, resulting in all your files suddenly
    appearing to be "deleted".
 
-4. Checkout, restore:
+5. Checkout, restore:
 
    These command do not handle path & revision arguments appropriately:
 
@@ -1030,7 +1052,7 @@
     S tracked
     H tracked-but-maybe-skipped
 
-5. checkout and restore --staged, continued:
+6. checkout and restore --staged, continued:
 
    These commands do not correctly scope operations to the sparse
    specification, and make it worse by not setting important SKIP_WORKTREE
@@ -1046,56 +1068,82 @@
    the sparse specification, but then it will be important to set the
    SKIP_WORKTREE bits appropriately.
 
-6. Performance issues; see:
-    https://lore.kernel.org/git/CABPp-BEkJQoKZsQGCYioyga_uoDQ6iBeW+FKr8JhyuuTMK1RDw@mail.gmail.com/
+7. Performance issues; see:
+
+   https://lore.kernel.org/git/CABPp-BEkJQoKZsQGCYioyga_uoDQ6iBeW+FKr8JhyuuTMK1RDw@mail.gmail.com/
 
 
-=== Reference Emails ===
+== Reference Emails ==
 
 Emails that detail various bugs we've had in sparse-checkout:
 
-[1] (Original descriptions of behavior A & behavior B)
-    https://lore.kernel.org/git/CABPp-BGJ_Nvi5TmgriD9Bh6eNXE2EDq2f8e8QKXAeYG3BxZafA@mail.gmail.com/
-[2] (Fix stash applications in sparse checkouts; bugs from behavioral differences)
-    https://lore.kernel.org/git/ccfedc7140dbf63ba26a15f93bd3885180b26517.1606861519.git.gitgitgadget@gmail.com/
-[3] (Present-despite-skipped entries)
-    https://lore.kernel.org/git/11d46a399d26c913787b704d2b7169cafc28d639.1642175983.git.gitgitgadget@gmail.com/
-[4] (Clone --no-checkout interaction)
-    https://lore.kernel.org/git/pull.801.v2.git.git.1591324899170.gitgitgadget@gmail.com/ (clone --no-checkout)
-[5] (The need for update_sparsity() and avoiding `read-tree -mu HEAD`)
-    https://lore.kernel.org/git/3a1f084641eb47515b5a41ed4409a36128913309.1585270142.git.gitgitgadget@gmail.com/
-[6] (SKIP_WORKTREE is advisory, not mandatory)
-    https://lore.kernel.org/git/844306c3e86ef67591cc086decb2b760e7d710a3.1585270142.git.gitgitgadget@gmail.com/
-[7] (`worktree add` should copy sparsity settings from current worktree)
-    https://lore.kernel.org/git/c51cb3714e7b1d2f8c9370fe87eca9984ff4859f.1644269584.git.gitgitgadget@gmail.com/
-[8] (Avoid negative surprises in add, rm, and mv)
-    https://lore.kernel.org/git/cover.1617914011.git.matheus.bernardino@usp.br/
-    https://lore.kernel.org/git/pull.1018.v4.git.1632497954.gitgitgadget@gmail.com/
-[9] (Move from out-of-cone to in-cone)
-    https://lore.kernel.org/git/20220630023737.473690-6-shaoxuan.yuan02@gmail.com/
-    https://lore.kernel.org/git/20220630023737.473690-4-shaoxuan.yuan02@gmail.com/
-[10] (Unnecessarily downloading objects outside sparse specification)
-     https://lore.kernel.org/git/CAOLTT8QfwOi9yx_qZZgyGa8iL8kHWutEED7ok_jxwTcYT_hf9Q@mail.gmail.com/
+[1] (Original descriptions of behavior A & behavior B):
 
-[11] (Stolee's comments on high-level usecases)
-     https://lore.kernel.org/git/1a1e33f6-3514-9afc-0a28-5a6b85bd8014@gmail.com/
+https://lore.kernel.org/git/CABPp-BGJ_Nvi5TmgriD9Bh6eNXE2EDq2f8e8QKXAeYG3BxZafA@mail.gmail.com/
+
+[2] (Fix stash applications in sparse checkouts; bugs from behavioral differences):
+
+https://lore.kernel.org/git/ccfedc7140dbf63ba26a15f93bd3885180b26517.1606861519.git.gitgitgadget@gmail.com/
+
+[3] (Present-despite-skipped entries):
+
+https://lore.kernel.org/git/11d46a399d26c913787b704d2b7169cafc28d639.1642175983.git.gitgitgadget@gmail.com/
+
+[4] (Clone --no-checkout interaction):
+
+https://lore.kernel.org/git/pull.801.v2.git.git.1591324899170.gitgitgadget@gmail.com/ (clone --no-checkout)
+
+[5] (The need for update_sparsity() and avoiding `read-tree -mu HEAD`):
+
+https://lore.kernel.org/git/3a1f084641eb47515b5a41ed4409a36128913309.1585270142.git.gitgitgadget@gmail.com/
+
+[6] (SKIP_WORKTREE is advisory, not mandatory):
+
+https://lore.kernel.org/git/844306c3e86ef67591cc086decb2b760e7d710a3.1585270142.git.gitgitgadget@gmail.com/
+
+[7] (`worktree add` should copy sparsity settings from current worktree):
+
+https://lore.kernel.org/git/c51cb3714e7b1d2f8c9370fe87eca9984ff4859f.1644269584.git.gitgitgadget@gmail.com/
+
+[8] (Avoid negative surprises in add, rm, and mv):
+
+  * https://lore.kernel.org/git/cover.1617914011.git.matheus.bernardino@usp.br/
+  * https://lore.kernel.org/git/pull.1018.v4.git.1632497954.gitgitgadget@gmail.com/
+
+[9] (Move from out-of-cone to in-cone):
+
+  * https://lore.kernel.org/git/20220630023737.473690-6-shaoxuan.yuan02@gmail.com/
+  * https://lore.kernel.org/git/20220630023737.473690-4-shaoxuan.yuan02@gmail.com/
+
+[10] (Unnecessarily downloading objects outside sparse specification):
+
+https://lore.kernel.org/git/CAOLTT8QfwOi9yx_qZZgyGa8iL8kHWutEED7ok_jxwTcYT_hf9Q@mail.gmail.com/
+
+[11] (Stolee's comments on high-level usecases):
+
+https://lore.kernel.org/git/1a1e33f6-3514-9afc-0a28-5a6b85bd8014@gmail.com/
 
 [12] Others commenting on eventually switching default to behavior A:
+
   * https://lore.kernel.org/git/xmqqh719pcoo.fsf@gitster.g/
   * https://lore.kernel.org/git/xmqqzgeqw0sy.fsf@gitster.g/
   * https://lore.kernel.org/git/a86af661-cf58-a4e5-0214-a67d3a794d7e@github.com/
 
-[13] Previous config name suggestion and description
-  * https://lore.kernel.org/git/CABPp-BE6zW0nJSStcVU=_DoDBnPgLqOR8pkTXK3dW11=T01OhA@mail.gmail.com/
+[13] Previous config name suggestion and description:
+
+   https://lore.kernel.org/git/CABPp-BE6zW0nJSStcVU=_DoDBnPgLqOR8pkTXK3dW11=T01OhA@mail.gmail.com/
 
 [14] Tangential issue: switch to cone mode as default sparse specification mechanism:
-  https://lore.kernel.org/git/a1b68fd6126eb341ef3637bb93fedad4309b36d0.1650594746.git.gitgitgadget@gmail.com/
+
+https://lore.kernel.org/git/a1b68fd6126eb341ef3637bb93fedad4309b36d0.1650594746.git.gitgitgadget@gmail.com/
 
 [15] Lengthy email on grep behavior, covering what should be searched:
-  * https://lore.kernel.org/git/CABPp-BGVO3QdbfE84uF_3QDF0-y2iHHh6G5FAFzNRfeRitkuHw@mail.gmail.com/
+
+https://lore.kernel.org/git/CABPp-BGVO3QdbfE84uF_3QDF0-y2iHHh6G5FAFzNRfeRitkuHw@mail.gmail.com/
 
 [16] Email explaining sparsity patterns vs. SKIP_WORKTREE and history operations,
      search for the parenthetical comment starting "We do not check".
-    https://lore.kernel.org/git/CABPp-BFsCPPNOZ92JQRJeGyNd0e-TCW-LcLyr0i_+VSQJP+GCg@mail.gmail.com/
+
+https://lore.kernel.org/git/CABPp-BFsCPPNOZ92JQRJeGyNd0e-TCW-LcLyr0i_+VSQJP+GCg@mail.gmail.com/
 
 [17] https://lore.kernel.org/git/20220207190320.2960362-1-jonathantanmy@google.com/
diff --git a/Documentation/urls-remotes.adoc b/Documentation/urls-remotes.adoc
index 9b10151..57b1646 100644
--- a/Documentation/urls-remotes.adoc
+++ b/Documentation/urls-remotes.adoc
@@ -92,5 +92,47 @@
 ------------
 
 
+[[UPSTREAM-BRANCHES]]
+UPSTREAM BRANCHES
+-----------------
 
+Branches in Git can optionally have an upstream remote branch.
+Git defaults to using the upstream branch for remote operations, for example:
 
+* It's the default for `git pull` or `git fetch` with no arguments.
+* It's the default for `git push` with no arguments, with some exceptions.
+  For example, you can use the `branch.<name>.pushRemote` option to push
+  to a different remote than you pull from, and by default with
+  `push.default=simple` the upstream branch you configure must have
+  the same name.
+* Various commands, including `git checkout` and `git status`, will
+  show you how many commits have been added to your current branch and
+  the upstream since you forked from it, for example "Your branch and
+  'origin/main' have diverged, and have 2 and 3 different commits each
+  respectively".
+
+The upstream is stored in `.git/config`, in the "remote" and "merge"
+fields. For example, if `main`'s upstream is `origin/main`:
+
+------------
+[branch "main"]
+   remote = origin
+   merge = refs/heads/main
+------------
+
+You can set an upstream branch explicitly with
+`git push --set-upstream <remote> <branch>`
+but Git will often automatically set the upstream for you, for example:
+
+* When you clone a repository, Git will automatically set the upstream
+  for the default branch.
+* If you have the `push.autoSetupRemote` configuration option set,
+  `git push` will automatically set the upstream the first time you push
+  a branch.
+* Checking out a remote-tracking branch with `git checkout <branch>`
+  will automatically create a local branch with that name and set
+  the upstream to the remote branch.
+
+[NOTE]
+Upstream branches are sometimes referred to as "tracking information",
+as in "set the branch's tracking information".
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 309bccb..1f7af03 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-DEF_VER=v2.51.2
+DEF_VER=v2.52.GIT
 
 LF='
 '
diff --git a/Makefile b/Makefile
index 1f444ee..2a67546 100644
--- a/Makefile
+++ b/Makefile
@@ -483,6 +483,14 @@
 # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are
 # in /foo/bar/include and /foo/bar/lib directories.
 #
+# == Optional Rust support ==
+#
+# Define WITH_RUST if you want to include features and subsystems written in
+# Rust into Git. For now, Rust is still an optional feature of the build
+# process. With Git 3.0 though, Rust will always be enabled.
+#
+# Building Rust code requires Cargo.
+#
 # == SHA-1 and SHA-256 defines ==
 #
 # === SHA-1 backend ===
@@ -683,6 +691,7 @@
 OTHER_PROGRAMS =
 PROGRAM_OBJS =
 PROGRAMS =
+RUST_SOURCES =
 EXCLUDED_PROGRAMS =
 SCRIPT_PERL =
 SCRIPT_PYTHON =
@@ -918,8 +927,114 @@
 TEST_SHELL_PATH = $(SHELL_PATH)
 
 LIB_FILE = libgit.a
-XDIFF_LIB = xdiff/lib.a
-REFTABLE_LIB = reftable/libreftable.a
+
+ifdef DEBUG
+RUST_TARGET_DIR = target/debug
+else
+RUST_TARGET_DIR = target/release
+endif
+
+ifeq ($(uname_S),Windows)
+RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib
+else
+RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a
+endif
+
+GITLIBS = common-main.o $(LIB_FILE)
+EXTLIBS =
+
+GIT_USER_AGENT = git/$(GIT_VERSION)
+
+ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)
+DC_SHA1_SUBMODULE = auto
+endif
+
+# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be
+# tweaked by config.* below as well as the command-line, both of
+# which'll override these defaults.
+# Older versions of GCC may require adding "-std=gnu99" at the end.
+CFLAGS = -g -O2 -Wall
+LDFLAGS =
+CC_LD_DYNPATH = -Wl,-rpath,
+BASIC_CFLAGS = -I.
+BASIC_LDFLAGS =
+
+# library flags
+ARFLAGS = rcs
+PTHREAD_CFLAGS =
+
+# Rust flags
+CARGO_ARGS =
+ifndef V
+CARGO_ARGS += --quiet
+endif
+ifndef DEBUG
+CARGO_ARGS += --release
+endif
+
+# For the 'sparse' target
+SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__
+SP_EXTRA_FLAGS =
+
+# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets
+SANITIZE_LEAK =
+SANITIZE_ADDRESS =
+
+# For the 'coccicheck' target
+SPATCH_INCLUDE_FLAGS = --all-includes
+SPATCH_FLAGS =
+SPATCH_TEST_FLAGS =
+
+# If *.o files are present, have "coccicheck" depend on them, with
+# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of
+# only needing to re-generate coccicheck results for the users of a
+# given API if it's changed, and not all files in the project. If
+# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.
+SPATCH_USE_O_DEPENDENCIES = YesPlease
+
+# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci
+# files into a single contrib/cocci/ALL.cocci before running
+# "coccicheck".
+#
+# Pros:
+#
+# - Speeds up a one-shot run of "make coccicheck", as we won't have to
+#   parse *.[ch] files N times for the N *.cocci rules
+#
+# Cons:
+#
+# - Will make incremental development of *.cocci slower, as
+#   e.g. changing strbuf.cocci will re-run all *.cocci.
+#
+# - Makes error and performance analysis harder, as rules will be
+#   applied from a monolithic ALL.cocci, rather than
+#   e.g. strbuf.cocci. To work around this either undefine this, or
+#   generate a specific patch, e.g. this will always use strbuf.cocci,
+#   not ALL.cocci:
+#
+#	make contrib/coccinelle/strbuf.cocci.patch
+SPATCH_CONCAT_COCCI = YesPlease
+
+# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change
+TRACK_SPATCH_DEFINES =
+TRACK_SPATCH_DEFINES += $(SPATCH)
+TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)
+TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)
+TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)
+GIT-SPATCH-DEFINES: FORCE
+	@FLAGS='$(TRACK_SPATCH_DEFINES)'; \
+	    if test x"$$FLAGS" != x"`cat GIT-SPATCH-DEFINES 2>/dev/null`" ; then \
+		echo >&2 "    * new spatch flags"; \
+		echo "$$FLAGS" >GIT-SPATCH-DEFINES; \
+            fi
+
+include config.mak.uname
+-include config.mak.autogen
+-include config.mak
+
+ifdef DEVELOPER
+include config.mak.dev
+endif
 
 GENERATED_H += command-list.h
 GENERATED_H += config-list.h
@@ -976,7 +1091,6 @@
 LIB_OBJS += blob.o
 LIB_OBJS += bloom.o
 LIB_OBJS += branch.o
-LIB_OBJS += bulk-checkin.o
 LIB_OBJS += bundle-uri.o
 LIB_OBJS += bundle.o
 LIB_OBJS += cache-tree.o
@@ -1096,6 +1210,7 @@
 LIB_OBJS += pack-check.o
 LIB_OBJS += pack-mtimes.o
 LIB_OBJS += pack-objects.o
+LIB_OBJS += pack-refs.o
 LIB_OBJS += pack-revindex.o
 LIB_OBJS += pack-write.o
 LIB_OBJS += packfile.o
@@ -1137,7 +1252,27 @@
 LIB_OBJS += refs/packed-backend.o
 LIB_OBJS += refs/ref-cache.o
 LIB_OBJS += refspec.o
+LIB_OBJS += reftable/basics.o
+LIB_OBJS += reftable/block.o
+LIB_OBJS += reftable/blocksource.o
+LIB_OBJS += reftable/error.o
+LIB_OBJS += reftable/fsck.o
+LIB_OBJS += reftable/iter.o
+LIB_OBJS += reftable/merged.o
+LIB_OBJS += reftable/pq.o
+LIB_OBJS += reftable/record.o
+LIB_OBJS += reftable/stack.o
+LIB_OBJS += reftable/system.o
+LIB_OBJS += reftable/table.o
+LIB_OBJS += reftable/tree.o
+LIB_OBJS += reftable/writer.o
 LIB_OBJS += remote.o
+LIB_OBJS += repack.o
+LIB_OBJS += repack-cruft.o
+LIB_OBJS += repack-filtered.o
+LIB_OBJS += repack-geometry.o
+LIB_OBJS += repack-midx.o
+LIB_OBJS += repack-promisor.o
 LIB_OBJS += replace-object.o
 LIB_OBJS += repo-settings.o
 LIB_OBJS += repository.o
@@ -1198,7 +1333,9 @@
 LIB_OBJS += usage.o
 LIB_OBJS += userdiff.o
 LIB_OBJS += utf8.o
+ifndef WITH_RUST
 LIB_OBJS += varint.o
+endif
 LIB_OBJS += version.o
 LIB_OBJS += versioncmp.o
 LIB_OBJS += walker.o
@@ -1209,6 +1346,13 @@
 LIB_OBJS += ws.o
 LIB_OBJS += wt-status.o
 LIB_OBJS += xdiff-interface.o
+LIB_OBJS += xdiff/xdiffi.o
+LIB_OBJS += xdiff/xemit.o
+LIB_OBJS += xdiff/xhistogram.o
+LIB_OBJS += xdiff/xmerge.o
+LIB_OBJS += xdiff/xpatience.o
+LIB_OBJS += xdiff/xprepare.o
+LIB_OBJS += xdiff/xutils.o
 
 BUILTIN_OBJS += builtin/add.o
 BUILTIN_OBJS += builtin/am.o
@@ -1267,6 +1411,7 @@
 BUILTIN_OBJS += builtin/index-pack.o
 BUILTIN_OBJS += builtin/init-db.o
 BUILTIN_OBJS += builtin/interpret-trailers.o
+BUILTIN_OBJS += builtin/last-modified.o
 BUILTIN_OBJS += builtin/log.o
 BUILTIN_OBJS += builtin/ls-files.o
 BUILTIN_OBJS += builtin/ls-remote.o
@@ -1308,6 +1453,7 @@
 BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/replay.o
+BUILTIN_OBJS += builtin/repo.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
 BUILTIN_OBJS += builtin/rev-list.o
@@ -1356,6 +1502,7 @@
 THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/%
 
 CLAR_TEST_SUITES += u-ctype
+CLAR_TEST_SUITES += u-dir
 CLAR_TEST_SUITES += u-example-decorate
 CLAR_TEST_SUITES += u-hash
 CLAR_TEST_SUITES += u-hashmap
@@ -1378,6 +1525,7 @@
 CLAR_TEST_SUITES += u-strvec
 CLAR_TEST_SUITES += u-trailer
 CLAR_TEST_SUITES += u-urlmatch-normalization
+CLAR_TEST_SUITES += u-utf8-width
 CLAR_TEST_PROG = $(UNIT_TEST_BIN)/unit-tests$(X)
 CLAR_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(CLAR_TEST_SUITES))
 CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/clar/clar.o
@@ -1387,93 +1535,8 @@
 
 UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o
 
-# xdiff and reftable libs may in turn depend on what is in libgit.a
-GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)
-EXTLIBS =
-
-GIT_USER_AGENT = git/$(GIT_VERSION)
-
-ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)
-DC_SHA1_SUBMODULE = auto
-endif
-
-# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be
-# tweaked by config.* below as well as the command-line, both of
-# which'll override these defaults.
-# Older versions of GCC may require adding "-std=gnu99" at the end.
-CFLAGS = -g -O2 -Wall
-LDFLAGS =
-CC_LD_DYNPATH = -Wl,-rpath,
-BASIC_CFLAGS = -I.
-BASIC_LDFLAGS =
-
-# library flags
-ARFLAGS = rcs
-PTHREAD_CFLAGS =
-
-# For the 'sparse' target
-SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__
-SP_EXTRA_FLAGS =
-
-# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets
-SANITIZE_LEAK =
-SANITIZE_ADDRESS =
-
-# For the 'coccicheck' target
-SPATCH_INCLUDE_FLAGS = --all-includes
-SPATCH_FLAGS =
-SPATCH_TEST_FLAGS =
-
-# If *.o files are present, have "coccicheck" depend on them, with
-# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of
-# only needing to re-generate coccicheck results for the users of a
-# given API if it's changed, and not all files in the project. If
-# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.
-SPATCH_USE_O_DEPENDENCIES = YesPlease
-
-# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci
-# files into a single contrib/cocci/ALL.cocci before running
-# "coccicheck".
-#
-# Pros:
-#
-# - Speeds up a one-shot run of "make coccicheck", as we won't have to
-#   parse *.[ch] files N times for the N *.cocci rules
-#
-# Cons:
-#
-# - Will make incremental development of *.cocci slower, as
-#   e.g. changing strbuf.cocci will re-run all *.cocci.
-#
-# - Makes error and performance analysis harder, as rules will be
-#   applied from a monolithic ALL.cocci, rather than
-#   e.g. strbuf.cocci. To work around this either undefine this, or
-#   generate a specific patch, e.g. this will always use strbuf.cocci,
-#   not ALL.cocci:
-#
-#	make contrib/coccinelle/strbuf.cocci.patch
-SPATCH_CONCAT_COCCI = YesPlease
-
-# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change
-TRACK_SPATCH_DEFINES =
-TRACK_SPATCH_DEFINES += $(SPATCH)
-TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)
-TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)
-TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)
-GIT-SPATCH-DEFINES: FORCE
-	@FLAGS='$(TRACK_SPATCH_DEFINES)'; \
-	    if test x"$$FLAGS" != x"`cat GIT-SPATCH-DEFINES 2>/dev/null`" ; then \
-		echo >&2 "    * new spatch flags"; \
-		echo "$$FLAGS" >GIT-SPATCH-DEFINES; \
-            fi
-
-include config.mak.uname
--include config.mak.autogen
--include config.mak
-
-ifdef DEVELOPER
-include config.mak.dev
-endif
+RUST_SOURCES += src/lib.rs
+RUST_SOURCES += src/varint.rs
 
 GIT-VERSION-FILE: FORCE
 	@OLD=$$(cat $@ 2>/dev/null || :) && \
@@ -1504,6 +1567,14 @@
 ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)
 ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)
 
+ifdef WITH_RUST
+BASIC_CFLAGS += -DWITH_RUST
+GITLIBS += $(RUST_LIB)
+ifeq ($(uname_S),Windows)
+EXTLIBS += -luserenv
+endif
+endif
+
 ifdef SANITIZE
 SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))
 BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)
@@ -2720,30 +2791,6 @@
 .PHONY: reconfigure # This is a convenience target.
 endif
 
-XDIFF_OBJS += xdiff/xdiffi.o
-XDIFF_OBJS += xdiff/xemit.o
-XDIFF_OBJS += xdiff/xhistogram.o
-XDIFF_OBJS += xdiff/xmerge.o
-XDIFF_OBJS += xdiff/xpatience.o
-XDIFF_OBJS += xdiff/xprepare.o
-XDIFF_OBJS += xdiff/xutils.o
-.PHONY: xdiff-objs
-xdiff-objs: $(XDIFF_OBJS)
-
-REFTABLE_OBJS += reftable/basics.o
-REFTABLE_OBJS += reftable/error.o
-REFTABLE_OBJS += reftable/block.o
-REFTABLE_OBJS += reftable/blocksource.o
-REFTABLE_OBJS += reftable/iter.o
-REFTABLE_OBJS += reftable/merged.o
-REFTABLE_OBJS += reftable/pq.o
-REFTABLE_OBJS += reftable/record.o
-REFTABLE_OBJS += reftable/stack.o
-REFTABLE_OBJS += reftable/system.o
-REFTABLE_OBJS += reftable/table.o
-REFTABLE_OBJS += reftable/tree.o
-REFTABLE_OBJS += reftable/writer.o
-
 TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
 
 .PHONY: test-objs
@@ -2764,9 +2811,8 @@
 OBJECTS += $(SCALAR_OBJS)
 OBJECTS += $(PROGRAM_OBJS)
 OBJECTS += $(TEST_OBJS)
-OBJECTS += $(XDIFF_OBJS)
 OBJECTS += $(FUZZ_OBJS)
-OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS)
+OBJECTS += $(REFTABLE_TEST_OBJS)
 OBJECTS += $(UNIT_TEST_OBJS)
 OBJECTS += $(CLAR_TEST_OBJS)
 OBJECTS += $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
@@ -2918,11 +2964,11 @@
 $(LIB_FILE): $(LIB_OBJS)
 	$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
 
-$(XDIFF_LIB): $(XDIFF_OBJS)
-	$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
+$(RUST_LIB): Cargo.toml $(RUST_SOURCES)
+	$(QUIET_CARGO)cargo build $(CARGO_ARGS)
 
-$(REFTABLE_LIB): $(REFTABLE_OBJS)
-	$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
+.PHONY: rust
+rust: $(RUST_LIB)
 
 export DEFAULT_EDITOR DEFAULT_PAGER
 
@@ -3762,12 +3808,13 @@
 	$(RM) git.rc git.res
 	$(RM) $(OBJECTS)
 	$(RM) headless-git.o
-	$(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB)
+	$(RM) $(LIB_FILE)
 	$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS)
 	$(RM) $(TEST_PROGRAMS)
 	$(RM) $(FUZZ_PROGRAMS)
 	$(RM) $(SP_OBJ)
 	$(RM) $(HCC)
+	$(RM) -r Cargo.lock target/
 	$(RM) version-def.h
 	$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json
 	$(RM) $(test_bindir_programs)
@@ -3955,8 +4002,6 @@
 
 LIBGIT_PUB_OBJS += contrib/libgit-sys/public_symbol_export.o
 LIBGIT_PUB_OBJS += libgit.a
-LIBGIT_PUB_OBJS += reftable/libreftable.a
-LIBGIT_PUB_OBJS += xdiff/lib.a
 
 LIBGIT_PARTIAL_EXPORT = contrib/libgit-sys/partial_symbol_export.o
 
diff --git a/RelNotes b/RelNotes
index 8e03a73..6dfd3d1 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.51.2.adoc
\ No newline at end of file
+Documentation/RelNotes/2.53.0.adoc
\ No newline at end of file
diff --git a/add-interactive.c b/add-interactive.c
index 4604c69..68fc095 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -20,14 +20,14 @@
 #include "prompt.h"
 #include "tree.h"
 
-static void init_color(struct repository *r, int use_color,
+static void init_color(struct repository *r, enum git_colorbool use_color,
 		       const char *section_and_slot, char *dst,
 		       const char *default_color)
 {
 	char *key = xstrfmt("color.%s", section_and_slot);
 	const char *value;
 
-	if (!use_color)
+	if (!want_color(use_color))
 		dst[0] = '\0';
 	else if (repo_config_get_value(r, key, &value) ||
 		 color_parse(value, dst))
@@ -36,13 +36,13 @@ static void init_color(struct repository *r, int use_color,
 	free(key);
 }
 
-static int check_color_config(struct repository *r, const char *var)
+static enum git_colorbool check_color_config(struct repository *r, const char *var)
 {
 	const char *value;
-	int ret;
+	enum git_colorbool ret;
 
 	if (repo_config_get_value(r, var, &value))
-		ret = -1;
+		ret = GIT_COLOR_UNKNOWN;
 	else
 		ret = git_config_colorbool(var, value);
 
@@ -51,10 +51,11 @@ static int check_color_config(struct repository *r, const char *var)
 	 * the value parsed by git_color_config(), which may not have been
 	 * called by the main command.
 	 */
-	if (ret < 0 && !repo_config_get_value(r, "color.ui", &value))
+	if (ret == GIT_COLOR_UNKNOWN &&
+	    !repo_config_get_value(r, "color.ui", &value))
 		ret = git_config_colorbool("color.ui", value);
 
-	return want_color(ret);
+	return ret;
 }
 
 void init_add_i_state(struct add_i_state *s, struct repository *r,
@@ -75,7 +76,7 @@ void init_add_i_state(struct add_i_state *s, struct repository *r,
 	init_color(r, s->use_color_interactive, "interactive.error",
 		   s->error_color, GIT_COLOR_BOLD_RED);
 	strlcpy(s->reset_color_interactive,
-		s->use_color_interactive ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
+		want_color(s->use_color_interactive) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
 
 	s->use_color_diff = check_color_config(r, "color.diff");
 
@@ -92,7 +93,7 @@ void init_add_i_state(struct add_i_state *s, struct repository *r,
 	init_color(r, s->use_color_diff, "diff.new", s->file_new_color,
 		   diff_get_color(s->use_color_diff, DIFF_FILE_NEW));
 	strlcpy(s->reset_color_diff,
-		s->use_color_diff ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
+		want_color(s->use_color_diff) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
 
 	FREE_AND_NULL(s->interactive_diff_filter);
 	repo_config_get_string(r, "interactive.difffilter",
@@ -130,8 +131,8 @@ void clear_add_i_state(struct add_i_state *s)
 	FREE_AND_NULL(s->interactive_diff_filter);
 	FREE_AND_NULL(s->interactive_diff_algorithm);
 	memset(s, 0, sizeof(*s));
-	s->use_color_interactive = -1;
-	s->use_color_diff = -1;
+	s->use_color_interactive = GIT_COLOR_UNKNOWN;
+	s->use_color_diff = GIT_COLOR_UNKNOWN;
 }
 
 /*
@@ -243,7 +244,8 @@ static void find_unique_prefixes(struct prefix_item_list *list)
 
 static ssize_t find_unique(const char *string, struct prefix_item_list *list)
 {
-	int index = string_list_find_insert_index(&list->sorted, string, 1);
+	bool exact_match;
+	size_t index = string_list_find_insert_index(&list->sorted, string, &exact_match);
 	struct string_list_item *item;
 
 	if (list->items.nr != list->sorted.nr)
@@ -251,8 +253,8 @@ static ssize_t find_unique(const char *string, struct prefix_item_list *list)
 		    " vs %"PRIuMAX")",
 		    (uintmax_t)list->items.nr, (uintmax_t)list->sorted.nr);
 
-	if (index < 0)
-		item = list->sorted.items[-1 - index].util;
+	if (exact_match)
+		item = list->sorted.items[index].util;
 	else if (index > 0 &&
 		 starts_with(list->sorted.items[index - 1].string, string))
 		return -1;
@@ -1210,7 +1212,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps,
 	 * When color was asked for, use the prompt color for
 	 * highlighting, otherwise use square brackets.
 	 */
-	if (s.use_color_interactive) {
+	if (want_color(s.use_color_interactive)) {
 		data.color = s.prompt_color;
 		data.reset = s.reset_color_interactive;
 	}
diff --git a/add-interactive.h b/add-interactive.h
index ceadfa6..da49502 100644
--- a/add-interactive.h
+++ b/add-interactive.h
@@ -12,8 +12,8 @@ struct add_p_opt {
 
 struct add_i_state {
 	struct repository *r;
-	int use_color_interactive;
-	int use_color_diff;
+	enum git_colorbool use_color_interactive;
+	enum git_colorbool use_color_diff;
 	char header_color[COLOR_MAXLEN];
 	char help_color[COLOR_MAXLEN];
 	char prompt_color[COLOR_MAXLEN];
diff --git a/add-patch.c b/add-patch.c
index b0389c5..173a532 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -956,6 +956,7 @@ static int split_hunk(struct add_p_state *s, struct file_diff *file_diff,
 			* sizeof(*hunk));
 	hunk = file_diff->hunk + hunk_index;
 	hunk->splittable_into = 1;
+	hunk->use = UNDECIDED_HUNK;
 	memset(hunk + 1, 0, (splittable_into - 1) * sizeof(*hunk));
 
 	header = &hunk->header;
@@ -1057,7 +1058,7 @@ static int split_hunk(struct add_p_state *s, struct file_diff *file_diff,
 
 		hunk++;
 		hunk->splittable_into = 1;
-		hunk->use = hunk[-1].use;
+		hunk->use = UNDECIDED_HUNK;
 		header = &hunk->header;
 
 		header->old_count = header->new_count = context_line_count;
@@ -1184,19 +1185,29 @@ static ssize_t recount_edited_hunk(struct add_p_state *s, struct hunk *hunk,
 {
 	struct hunk_header *header = &hunk->header;
 	size_t i;
+	char ch, marker = ' ';
 
+	hunk->splittable_into = 0;
 	header->old_count = header->new_count = 0;
 	for (i = hunk->start; i < hunk->end; ) {
-		switch(normalize_marker(&s->plain.buf[i])) {
+		ch = normalize_marker(&s->plain.buf[i]);
+		switch (ch) {
 		case '-':
 			header->old_count++;
+			if (marker == ' ')
+				hunk->splittable_into++;
+			marker = ch;
 			break;
 		case '+':
 			header->new_count++;
+			if (marker == ' ')
+				hunk->splittable_into++;
+			marker = ch;
 			break;
 		case ' ':
 			header->old_count++;
 			header->new_count++;
+			marker = ch;
 			break;
 		}
 
@@ -1397,17 +1408,39 @@ static size_t display_hunks(struct add_p_state *s,
 }
 
 static const char help_patch_remainder[] =
-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"
+N_("j - go to the next undecided hunk, roll over at the bottom\n"
+   "J - go to the next hunk, roll over at the bottom\n"
+   "k - go to the previous undecided hunk, roll over at the top\n"
+   "K - go to the previous hunk, roll over at the top\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"
-   "p - print the current hunk, 'P' to use the pager\n"
+   "p - print the current hunk\n"
+   "P - print the current hunk using the pager\n"
    "? - print help\n");
 
+static size_t dec_mod(size_t a, size_t m)
+{
+	return a > 0 ? a - 1 : m - 1;
+}
+
+static size_t inc_mod(size_t a, size_t m)
+{
+	return a < m - 1 ? a + 1 : 0;
+}
+
+static bool get_first_undecided(const struct file_diff *file_diff, size_t *idx)
+{
+	for (size_t i = 0; i < file_diff->hunk_nr; i++) {
+		if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
+			*idx = i;
+			return true;
+		}
+	}
+	return false;
+}
+
 static int patch_update_file(struct add_p_state *s,
 			     struct file_diff *file_diff)
 {
@@ -1418,15 +1451,6 @@ static int patch_update_file(struct add_p_state *s,
 	struct child_process cp = CHILD_PROCESS_INIT;
 	int colored = !!s->colored.len, quit = 0, use_pager = 0;
 	enum prompt_mode_type prompt_mode_type;
-	enum {
-		ALLOW_GOTO_PREVIOUS_HUNK = 1 << 0,
-		ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK = 1 << 1,
-		ALLOW_GOTO_NEXT_HUNK = 1 << 2,
-		ALLOW_GOTO_NEXT_UNDECIDED_HUNK = 1 << 3,
-		ALLOW_SEARCH_AND_GOTO = 1 << 4,
-		ALLOW_SPLIT = 1 << 5,
-		ALLOW_EDIT = 1 << 6
-	} permitted = 0;
 
 	/* Empty added files have no hunks */
 	if (!file_diff->hunk_nr && !file_diff->added)
@@ -1436,6 +1460,16 @@ static int patch_update_file(struct add_p_state *s,
 	render_diff_header(s, file_diff, colored, &s->buf);
 	fputs(s->buf.buf, stdout);
 	for (;;) {
+		enum {
+			ALLOW_GOTO_PREVIOUS_HUNK = 1 << 0,
+			ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK = 1 << 1,
+			ALLOW_GOTO_NEXT_HUNK = 1 << 2,
+			ALLOW_GOTO_NEXT_UNDECIDED_HUNK = 1 << 3,
+			ALLOW_SEARCH_AND_GOTO = 1 << 4,
+			ALLOW_SPLIT = 1 << 5,
+			ALLOW_EDIT = 1 << 6
+		} permitted = 0;
+
 		if (hunk_index >= file_diff->hunk_nr)
 			hunk_index = 0;
 		hunk = file_diff->hunk_nr
@@ -1445,13 +1479,17 @@ static int patch_update_file(struct add_p_state *s,
 		undecided_next = -1;
 
 		if (file_diff->hunk_nr) {
-			for (i = hunk_index - 1; i >= 0; i--)
+			for (i = dec_mod(hunk_index, file_diff->hunk_nr);
+			     i != hunk_index;
+			     i = dec_mod(i, file_diff->hunk_nr))
 				if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
 					undecided_previous = i;
 					break;
 				}
 
-			for (i = hunk_index + 1; i < file_diff->hunk_nr; i++)
+			for (i = inc_mod(hunk_index, file_diff->hunk_nr);
+			     i != hunk_index;
+			     i = inc_mod(i, file_diff->hunk_nr))
 				if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
 					undecided_next = i;
 					break;
@@ -1485,7 +1523,7 @@ static int patch_update_file(struct add_p_state *s,
 				permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK;
 				strbuf_addstr(&s->buf, ",k");
 			}
-			if (hunk_index) {
+			if (file_diff->hunk_nr > 1) {
 				permitted |= ALLOW_GOTO_PREVIOUS_HUNK;
 				strbuf_addstr(&s->buf, ",K");
 			}
@@ -1493,7 +1531,7 @@ static int patch_update_file(struct add_p_state *s,
 				permitted |= ALLOW_GOTO_NEXT_UNDECIDED_HUNK;
 				strbuf_addstr(&s->buf, ",j");
 			}
-			if (hunk_index + 1 < file_diff->hunk_nr) {
+			if (file_diff->hunk_nr > 1) {
 				permitted |= ALLOW_GOTO_NEXT_HUNK;
 				strbuf_addstr(&s->buf, ",J");
 			}
@@ -1510,7 +1548,7 @@ static int patch_update_file(struct add_p_state *s,
 				permitted |= ALLOW_EDIT;
 				strbuf_addstr(&s->buf, ",e");
 			}
-			strbuf_addstr(&s->buf, ",p");
+			strbuf_addstr(&s->buf, ",p,P");
 		}
 		if (file_diff->deleted)
 			prompt_mode_type = PROMPT_DELETION;
@@ -1531,8 +1569,10 @@ static int patch_update_file(struct add_p_state *s,
 		if (*s->s.reset_color_interactive)
 			fputs(s->s.reset_color_interactive, stdout);
 		fflush(stdout);
-		if (read_single_character(s) == EOF)
+		if (read_single_character(s) == EOF) {
+			quit = 1;
 			break;
+		}
 
 		if (!s->answer.len)
 			continue;
@@ -1558,43 +1598,47 @@ static int patch_update_file(struct add_p_state *s,
 					if (hunk->use == UNDECIDED_HUNK)
 						hunk->use = USE_HUNK;
 				}
+				if (!get_first_undecided(file_diff, &hunk_index))
+					hunk_index = 0;
 			} else if (hunk->use == UNDECIDED_HUNK) {
 				hunk->use = USE_HUNK;
 			}
-		} else if (ch == 'd' || ch == 'q') {
+		} else if (ch == 'd') {
 			if (file_diff->hunk_nr) {
 				for (; hunk_index < file_diff->hunk_nr; hunk_index++) {
 					hunk = file_diff->hunk + hunk_index;
 					if (hunk->use == UNDECIDED_HUNK)
 						hunk->use = SKIP_HUNK;
 				}
+				if (!get_first_undecided(file_diff, &hunk_index))
+					hunk_index = 0;
 			} else if (hunk->use == UNDECIDED_HUNK) {
 				hunk->use = SKIP_HUNK;
 			}
-			if (ch == 'q') {
-				quit = 1;
-				break;
-			}
+		} else if (ch == 'q') {
+			quit = 1;
+			break;
 		} else if (s->answer.buf[0] == 'K') {
 			if (permitted & ALLOW_GOTO_PREVIOUS_HUNK)
-				hunk_index--;
+				hunk_index = dec_mod(hunk_index,
+						     file_diff->hunk_nr);
 			else
-				err(s, _("No previous hunk"));
+				err(s, _("No other hunk"));
 		} else if (s->answer.buf[0] == 'J') {
 			if (permitted & ALLOW_GOTO_NEXT_HUNK)
 				hunk_index++;
 			else
-				err(s, _("No next hunk"));
+				err(s, _("No other hunk"));
 		} else if (s->answer.buf[0] == 'k') {
 			if (permitted & ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK)
 				hunk_index = undecided_previous;
 			else
-				err(s, _("No previous hunk"));
+				err(s, _("No other undecided hunk"));
 		} else if (s->answer.buf[0] == 'j') {
 			if (permitted & ALLOW_GOTO_NEXT_UNDECIDED_HUNK)
 				hunk_index = undecided_next;
 			else
-				err(s, _("No next hunk"));
+				err(s, _("No other undecided hunk"));
 		} else if (s->answer.buf[0] == 'g') {
 			char *pend;
 			unsigned long response;
diff --git a/advice.c b/advice.c
index e5f0ff8..0018501 100644
--- a/advice.c
+++ b/advice.c
@@ -7,7 +7,7 @@
 #include "help.h"
 #include "string-list.h"
 
-static int advice_use_color = -1;
+static enum git_colorbool advice_use_color = GIT_COLOR_UNKNOWN;
 static char advice_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_RESET,
 	GIT_COLOR_YELLOW,	/* HINT */
diff --git a/advice.h b/advice.h
index 727dcec..8def280 100644
--- a/advice.h
+++ b/advice.h
@@ -18,7 +18,7 @@ enum advice_type {
 	ADVICE_AM_WORK_DIR,
 	ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME,
 	ADVICE_COMMIT_BEFORE_MERGE,
-	ADVICE_DEFAULT_BRANCH_NAME,
+	ADVICE_DEFAULT_BRANCH_NAME, /* To be retired sometime after Git 3.0 */
 	ADVICE_DETACHED_HEAD,
 	ADVICE_DIVERGING,
 	ADVICE_FETCH_SET_HEAD_WARN,
diff --git a/alloc.c b/alloc.c
index 377e80f..533a045 100644
--- a/alloc.c
+++ b/alloc.c
@@ -36,19 +36,25 @@ struct alloc_state {
 	int slab_nr, slab_alloc;
 };
 
-struct alloc_state *allocate_alloc_state(void)
+struct alloc_state *alloc_state_alloc(void)
 {
 	return xcalloc(1, sizeof(struct alloc_state));
 }
 
-void clear_alloc_state(struct alloc_state *s)
+void alloc_state_free_and_null(struct alloc_state **s_)
 {
+	struct alloc_state *s = *s_;
+
+	if (!s)
+		return;
+
 	while (s->slab_nr > 0) {
 		s->slab_nr--;
 		free(s->slabs[s->slab_nr]);
 	}
 
 	FREE_AND_NULL(s->slabs);
+	FREE_AND_NULL(*s_);
 }
 
 static inline void *alloc_node(struct alloc_state *s, size_t node_size)
diff --git a/alloc.h b/alloc.h
index 3f4a0ad..87a47a9 100644
--- a/alloc.h
+++ b/alloc.h
@@ -14,7 +14,7 @@ void *alloc_commit_node(struct repository *r);
 void *alloc_tag_node(struct repository *r);
 void *alloc_object_node(struct repository *r);
 
-struct alloc_state *allocate_alloc_state(void);
-void clear_alloc_state(struct alloc_state *s);
+struct alloc_state *alloc_state_alloc(void);
+void alloc_state_free_and_null(struct alloc_state **s_);
 
 #endif
diff --git a/attr.c b/attr.c
index d1daeb0..4999b7e 100644
--- a/attr.c
+++ b/attr.c
@@ -1064,24 +1064,52 @@ static int path_matches(const char *pathname, int pathlen,
 			      pattern, prefix, pat->patternlen);
 }
 
-static int macroexpand_one(struct all_attrs_item *all_attrs, int nr, int rem);
+struct attr_state_queue {
+	const struct attr_state **items;
+	size_t alloc, nr;
+};
+
+static void attr_state_queue_push(struct attr_state_queue *t,
+				 const struct match_attr *a)
+{
+	for (size_t i = 0; i < a->num_attr; i++) {
+		ALLOC_GROW(t->items, t->nr + 1, t->alloc);
+		t->items[t->nr++] = &a->state[i];
+	}
+}
+
+static const struct attr_state *attr_state_queue_pop(struct attr_state_queue *t)
+{
+	return t->nr ? t->items[--t->nr] : NULL;
+}
+
+static void attr_state_queue_release(struct attr_state_queue *t)
+{
+	free(t->items);
+}
 
 static int fill_one(struct all_attrs_item *all_attrs,
 		    const struct match_attr *a, int rem)
 {
-	size_t i;
+	struct attr_state_queue todo = { 0 };
+	const struct attr_state *state;
 
-	for (i = a->num_attr; rem > 0 && i > 0; i--) {
-		const struct git_attr *attr = a->state[i - 1].attr;
+	attr_state_queue_push(&todo, a);
+	while (rem > 0 && (state = attr_state_queue_pop(&todo))) {
+		const struct git_attr *attr = state->attr;
 		const char **n = &(all_attrs[attr->attr_nr].value);
-		const char *v = a->state[i - 1].setto;
+		const char *v = state->setto;
 
 		if (*n == ATTR__UNKNOWN) {
+			const struct all_attrs_item *item =
+				&all_attrs[attr->attr_nr];
 			*n = v;
 			rem--;
-			rem = macroexpand_one(all_attrs, attr->attr_nr, rem);
+			if (item->macro && item->value == ATTR__TRUE)
+				attr_state_queue_push(&todo, item->macro);
 		}
 	}
+	attr_state_queue_release(&todo);
 	return rem;
 }
 
@@ -1106,16 +1134,6 @@ static int fill(const char *path, int pathlen, int basename_offset,
 	return rem;
 }
 
-static int macroexpand_one(struct all_attrs_item *all_attrs, int nr, int rem)
-{
-	const struct all_attrs_item *item = &all_attrs[nr];
-
-	if (item->macro && item->value == ATTR__TRUE)
-		return fill_one(all_attrs, item->macro, rem);
-	else
-		return rem;
-}
-
 /*
  * Marks the attributes which are macros based on the attribute stack.
  * This prevents having to search through the attribute stack each time
diff --git a/bisect.c b/bisect.c
index f244745..326b59c 100644
--- a/bisect.c
+++ b/bisect.c
@@ -450,21 +450,20 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
 	clear_commit_weight(&commit_weight);
 }
 
-static int register_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			int flags UNUSED, void *cb_data UNUSED)
+static int register_ref(const struct reference *ref, void *cb_data UNUSED)
 {
 	struct strbuf good_prefix = STRBUF_INIT;
 	strbuf_addstr(&good_prefix, term_good);
 	strbuf_addstr(&good_prefix, "-");
 
-	if (!strcmp(refname, term_bad)) {
+	if (!strcmp(ref->name, term_bad)) {
 		free(current_bad_oid);
 		current_bad_oid = xmalloc(sizeof(*current_bad_oid));
-		oidcpy(current_bad_oid, oid);
-	} else if (starts_with(refname, good_prefix.buf)) {
-		oid_array_append(&good_revs, oid);
-	} else if (starts_with(refname, "skip-")) {
-		oid_array_append(&skipped_revs, oid);
+		oidcpy(current_bad_oid, ref->oid);
+	} else if (starts_with(ref->name, good_prefix.buf)) {
+		oid_array_append(&good_revs, ref->oid);
+	} else if (starts_with(ref->name, "skip-")) {
+		oid_array_append(&skipped_revs, ref->oid);
 	}
 
 	strbuf_release(&good_prefix);
@@ -674,9 +673,6 @@ static void bisect_rev_setup(struct repository *r, struct rev_info *revs,
 			     const char *bad_format, const char *good_format,
 			     int read_paths)
 {
-	struct setup_revision_opt opt = {
-		.free_removed_argv_elements = 1,
-	};
 	int i;
 
 	repo_init_revisions(r, revs, prefix);
@@ -693,7 +689,7 @@ static void bisect_rev_setup(struct repository *r, struct rev_info *revs,
 	if (read_paths)
 		read_bisect_paths(rev_argv);
 
-	setup_revisions(rev_argv->nr, rev_argv->v, revs, &opt);
+	setup_revisions_from_strvec(rev_argv, revs, NULL);
 }
 
 static void bisect_common(struct rev_info *revs)
@@ -1181,14 +1177,11 @@ int estimate_bisect_steps(int all)
 	return (e < 3 * x) ? n : n - 1;
 }
 
-static int mark_for_removal(const char *refname,
-			    const char *referent UNUSED,
-			    const struct object_id *oid UNUSED,
-			    int flag UNUSED, void *cb_data)
+static int mark_for_removal(const struct reference *ref, void *cb_data)
 {
 	struct string_list *refs = cb_data;
-	char *ref = xstrfmt("refs/bisect%s", refname);
-	string_list_append(refs, ref);
+	char *bisect_ref = xstrfmt("refs/bisect%s", ref->name);
+	string_list_append(refs, bisect_ref);
 	return 0;
 }
 
diff --git a/blame.c b/blame.c
index f1c0670..cb0b083 100644
--- a/blame.c
+++ b/blame.c
@@ -2909,9 +2909,6 @@ void setup_blame_bloom_data(struct blame_scoreboard *sb)
 	struct blame_bloom_data *bd;
 	struct bloom_filter_settings *bs;
 
-	if (!sb->repo->objects->commit_graph)
-		return;
-
 	bs = get_bloom_filter_settings(sb->repo);
 	if (!bs)
 		return;
diff --git a/bloom.c b/bloom.c
index b86015f..2d7b951 100644
--- a/bloom.c
+++ b/bloom.c
@@ -452,10 +452,12 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
 	filter = bloom_filter_slab_at(&bloom_filters, c);
 
 	if (!filter->data) {
+		struct commit_graph *g;
 		uint32_t graph_pos;
-		if (repo_find_commit_pos_in_graph(r, c, &graph_pos))
-			load_bloom_filter_from_graph(r->objects->commit_graph,
-						     filter, graph_pos);
+
+		g = repo_find_commit_pos_in_graph(r, c, &graph_pos);
+		if (g)
+			load_bloom_filter_from_graph(g, filter, graph_pos);
 	}
 
 	if (filter->data && filter->len) {
diff --git a/builtin.h b/builtin.h
index bff13e3..1b35565 100644
--- a/builtin.h
+++ b/builtin.h
@@ -176,6 +176,7 @@ int cmd_hook(int argc, const char **argv, const char *prefix, struct repository
 int cmd_index_pack(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_init_db(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_interpret_trailers(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_last_modified(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_log_reflog(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_log(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_ls_files(int argc, const char **argv, const char *prefix, struct repository *repo);
@@ -216,6 +217,7 @@ int cmd_remote_ext(int argc, const char **argv, const char *prefix, struct repos
 int cmd_remote_fd(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_repack(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_replay(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_repo(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_rerere(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_reset(int argc, const char **argv, const char *prefix, struct repository *repo);
 int cmd_restore(int argc, const char **argv, const char *prefix, struct repository *repo);
diff --git a/builtin/add.c b/builtin/add.c
index 0235854..3270979 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -14,13 +14,14 @@
 #include "gettext.h"
 #include "pathspec.h"
 #include "run-command.h"
+#include "object-file.h"
+#include "odb.h"
 #include "parse-options.h"
 #include "path.h"
 #include "preload-index.h"
 #include "diff.h"
 #include "read-cache.h"
 #include "revision.h"
-#include "bulk-checkin.h"
 #include "strvec.h"
 #include "submodule.h"
 #include "add-interactive.h"
@@ -200,7 +201,7 @@ static int edit_patch(struct repository *repo,
 
 	argc = setup_revisions(argc, argv, &rev, NULL);
 	rev.diffopt.output_format = DIFF_FORMAT_PATCH;
-	rev.diffopt.use_color = 0;
+	rev.diffopt.use_color = GIT_COLOR_NEVER;
 	rev.diffopt.flags.ignore_dirty_submodules = 1;
 	out = xopen(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
 	rev.diffopt.file = xfdopen(out, "w");
@@ -389,6 +390,7 @@ int cmd_add(int argc,
 	char *seen = NULL;
 	char *ps_matched = NULL;
 	struct lock_file lock_file = LOCK_INIT;
+	struct odb_transaction *transaction;
 
 	repo_config(repo, add_config, NULL);
 
@@ -574,7 +576,7 @@ int cmd_add(int argc,
 		string_list_clear(&only_match_skip_worktree, 0);
 	}
 
-	begin_odb_transaction();
+	transaction = odb_transaction_begin(repo->objects);
 
 	ps_matched = xcalloc(pathspec.nr, 1);
 	if (add_renormalize)
@@ -593,7 +595,7 @@ int cmd_add(int argc,
 
 	if (chmod_arg && pathspec.nr)
 		exit_status |= chmod_pathspec(repo, &pathspec, chmod_arg[0], show_only);
-	end_odb_transaction();
+	odb_transaction_commit(transaction);
 
 finish:
 	if (write_locked_index(repo->index, &lock_file,
diff --git a/builtin/am.c b/builtin/am.c
index 6073d64..277c2e7 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1408,7 +1408,7 @@ static void write_commit_patch(const struct am_state *state, struct commit *comm
 	rev_info.no_commit_id = 1;
 	rev_info.diffopt.flags.binary = 1;
 	rev_info.diffopt.flags.full_index = 1;
-	rev_info.diffopt.use_color = 0;
+	rev_info.diffopt.use_color = GIT_COLOR_NEVER;
 	rev_info.diffopt.file = fp;
 	rev_info.diffopt.close_file = 1;
 	add_pending_object(&rev_info, &commit->object, "");
@@ -1441,7 +1441,7 @@ static void write_index_patch(const struct am_state *state)
 	rev_info.disable_stdin = 1;
 	rev_info.no_commit_id = 1;
 	rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
-	rev_info.diffopt.use_color = 0;
+	rev_info.diffopt.use_color = GIT_COLOR_NEVER;
 	rev_info.diffopt.file = fp;
 	rev_info.diffopt.close_file = 1;
 	add_pending_object(&rev_info, &tree->object, "");
diff --git a/builtin/backfill.c b/builtin/backfill.c
index 80056ab..e80fc1b 100644
--- a/builtin/backfill.c
+++ b/builtin/backfill.c
@@ -53,7 +53,7 @@ static void download_batch(struct backfill_context *ctx)
 	 * We likely have a new packfile. Add it to the packed list to
 	 * avoid possible duplicate downloads of the same objects.
 	 */
-	reprepare_packed_git(ctx->repo);
+	odb_reprepare(ctx->repo->objects);
 }
 
 static int fill_missing_blobs(const char *path UNUSED,
diff --git a/builtin/bisect.c b/builtin/bisect.c
index 8b8d870..4cc118f 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -27,13 +27,14 @@ static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
 static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
 
 #define BUILTIN_GIT_BISECT_START_USAGE \
-	N_("git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]" \
-	   "    [--no-checkout] [--first-parent] [<bad> [<good>...]] [--]" \
-	   "    [<pathspec>...]")
-#define BUILTIN_GIT_BISECT_STATE_USAGE \
-	N_("git bisect (good|bad) [<rev>...]")
+	N_("git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n" \
+	   "                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]")
+#define BUILTIN_GIT_BISECT_BAD_USAGE \
+	N_("git bisect (bad|new|<term-new>) [<rev>]")
+#define BUILTIN_GIT_BISECT_GOOD_USAGE \
+	N_("git bisect (good|old|<term-old>) [<rev>...]")
 #define BUILTIN_GIT_BISECT_TERMS_USAGE \
-	"git bisect terms [--term-good | --term-bad]"
+	"git bisect terms [--term-(good|old) | --term-(bad|new)]"
 #define BUILTIN_GIT_BISECT_SKIP_USAGE \
 	N_("git bisect skip [(<rev>|<range>)...]")
 #define BUILTIN_GIT_BISECT_NEXT_USAGE \
@@ -41,17 +42,20 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
 #define BUILTIN_GIT_BISECT_RESET_USAGE \
 	N_("git bisect reset [<commit>]")
 #define BUILTIN_GIT_BISECT_VISUALIZE_USAGE \
-	"git bisect visualize"
+	"git bisect (visualize|view)"
 #define BUILTIN_GIT_BISECT_REPLAY_USAGE \
 	N_("git bisect replay <logfile>")
 #define BUILTIN_GIT_BISECT_LOG_USAGE \
 	"git bisect log"
 #define BUILTIN_GIT_BISECT_RUN_USAGE \
 	N_("git bisect run <cmd> [<arg>...]")
+#define BUILTIN_GIT_BISECT_HELP_USAGE \
+	"git bisect help"
 
 static const char * const git_bisect_usage[] = {
 	BUILTIN_GIT_BISECT_START_USAGE,
-	BUILTIN_GIT_BISECT_STATE_USAGE,
+	BUILTIN_GIT_BISECT_BAD_USAGE,
+	BUILTIN_GIT_BISECT_GOOD_USAGE,
 	BUILTIN_GIT_BISECT_TERMS_USAGE,
 	BUILTIN_GIT_BISECT_SKIP_USAGE,
 	BUILTIN_GIT_BISECT_NEXT_USAGE,
@@ -60,6 +64,7 @@ static const char * const git_bisect_usage[] = {
 	BUILTIN_GIT_BISECT_REPLAY_USAGE,
 	BUILTIN_GIT_BISECT_LOG_USAGE,
 	BUILTIN_GIT_BISECT_RUN_USAGE,
+	BUILTIN_GIT_BISECT_HELP_USAGE,
 	NULL
 };
 
@@ -358,10 +363,7 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
 	return 0;
 }
 
-static int inc_nr(const char *refname UNUSED,
-		  const char *referent UNUSED,
-		  const struct object_id *oid UNUSED,
-		  int flag UNUSED, void *cb_data)
+static int inc_nr(const struct reference *ref UNUSED, void *cb_data)
 {
 	unsigned int *nr = (unsigned int *)cb_data;
 	(*nr)++;
@@ -549,12 +551,11 @@ static int bisect_append_log_quoted(const char **argv)
 	return res;
 }
 
-static int add_bisect_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			  int flags UNUSED, void *cb)
+static int add_bisect_ref(const struct reference *ref, void *cb)
 {
 	struct add_bisect_ref_data *data = cb;
 
-	add_pending_oid(data->revs, refname, oid, data->object_flags);
+	add_pending_oid(data->revs, ref->name, ref->oid, data->object_flags);
 
 	return 0;
 }
@@ -1165,12 +1166,9 @@ static int bisect_visualize(struct bisect_terms *terms, int argc,
 	return run_command(&cmd);
 }
 
-static int get_first_good(const char *refname UNUSED,
-			  const char *referent UNUSED,
-			  const struct object_id *oid,
-			  int flag UNUSED, void *cb_data)
+static int get_first_good(const struct reference *ref, void *cb_data)
 {
-	oidcpy(cb_data, oid);
+	oidcpy(cb_data, ref->oid);
 	return 1;
 }
 
@@ -1453,9 +1451,13 @@ int cmd_bisect(int argc,
 		if (!argc)
 			usage_msg_opt(_("need a command"), git_bisect_usage, options);
 
+		if (!strcmp(argv[0], "help"))
+			usage_with_options(git_bisect_usage, options);
+
 		set_terms(&terms, "bad", "good");
 		get_terms(&terms);
-		if (check_and_set_terms(&terms, argv[0]))
+		if (check_and_set_terms(&terms, argv[0]) ||
+		    !one_of(argv[0], terms.term_good, terms.term_bad, NULL))
 			usage_msg_optf(_("unknown command: '%s'"), git_bisect_usage,
 				       options, argv[0]);
 		res = bisect_state(&terms, argc, argv);
diff --git a/builtin/blame.c b/builtin/blame.c
index 5b10e84..2703820 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -413,7 +413,7 @@ static void parse_color_fields(const char *s)
 	colorfield_nr = 0;
 
 	/* Ideally this would be stripped and split at the same time? */
-	string_list_split(&l, s, ',', -1);
+	string_list_split(&l, s, ",", -1);
 	ALLOC_GROW(colorfield, colorfield_nr + 1, colorfield_alloc);
 
 	for_each_string_list_item(item, &l) {
diff --git a/builtin/branch.c b/builtin/branch.c
index fa5ced4..9fcf04b 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -46,7 +46,7 @@ static struct object_id head_oid;
 static int recurse_submodules = 0;
 static int submodule_propagate_branches = 0;
 
-static int branch_use_color = -1;
+static enum git_colorbool branch_use_color = GIT_COLOR_UNKNOWN;
 static char branch_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_RESET,
 	GIT_COLOR_NORMAL,       /* PLAIN */
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index fce0b06..983ecec 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -495,7 +495,7 @@ static void batch_object_write(const char *obj_name,
 							    OBJECT_INFO_LOOKUP_REPLACE);
 		if (ret < 0) {
 			if (data->mode == S_IFGITLINK)
-				report_object_status(opt, oid_to_hex(&data->oid), &data->oid, "submodule");
+				report_object_status(opt, NULL, &data->oid, "submodule");
 			else
 				report_object_status(opt, obj_name, &data->oid, "missing");
 			return;
@@ -854,7 +854,7 @@ static void batch_each_object(struct batch_options *opt,
 						 batch_one_object_bitmapped, &payload)) {
 		struct packed_git *pack;
 
-		for (pack = get_all_packs(the_repository); pack; pack = pack->next) {
+		repo_for_each_pack(the_repository, pack) {
 			if (bitmap_index_contains_pack(bitmap, pack) ||
 			    open_pack_index(pack))
 				continue;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index f945347..66b69df 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1063,11 +1063,9 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
 		report_tracking(new_branch_info);
 }
 
-static int add_pending_uninteresting_ref(const char *refname, const char *referent UNUSED,
-					 const struct object_id *oid,
-					 int flags UNUSED, void *cb_data)
+static int add_pending_uninteresting_ref(const struct reference *ref, void *cb_data)
 {
-	add_pending_oid(cb_data, refname, oid, UNINTERESTING);
+	add_pending_oid(cb_data, ref->name, ref->oid, UNINTERESTING);
 	return 0;
 }
 
diff --git a/builtin/clean.c b/builtin/clean.c
index a1977b9..1d5e7e5 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -64,7 +64,7 @@ static const char *color_interactive_slots[] = {
 	[CLEAN_COLOR_RESET]  = "reset",
 };
 
-static int clean_use_color = -1;
+static enum git_colorbool clean_use_color = GIT_COLOR_UNKNOWN;
 static char clean_colors[][COLOR_MAXLEN] = {
 	[CLEAN_COLOR_ERROR] = GIT_COLOR_BOLD_RED,
 	[CLEAN_COLOR_HEADER] = GIT_COLOR_BOLD,
@@ -478,43 +478,39 @@ static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
  */
 static int parse_choice(struct menu_stuff *menu_stuff,
 			int is_single,
-			struct strbuf input,
+			char *input,
 			int **chosen)
 {
-	struct strbuf **choice_list, **ptr;
+	struct string_list choice = STRING_LIST_INIT_NODUP;
+	struct string_list_item *item;
 	int nr = 0;
 	int i;
 
-	if (is_single) {
-		choice_list = strbuf_split_max(&input, '\n', 0);
-	} else {
-		char *p = input.buf;
-		do {
-			if (*p == ',')
-				*p = ' ';
-		} while (*p++);
-		choice_list = strbuf_split_max(&input, ' ', 0);
-	}
+	string_list_split_in_place_f(&choice, input,
+				     is_single ? "\n" : ", ", -1,
+				     STRING_LIST_SPLIT_TRIM);
 
-	for (ptr = choice_list; *ptr; ptr++) {
-		char *p;
-		int choose = 1;
+	for_each_string_list_item(item, &choice) {
+		const char *string;
+		int choose;
 		int bottom = 0, top = 0;
 		int is_range, is_number;
 
-		strbuf_trim(*ptr);
-		if (!(*ptr)->len)
+		string = item->string;
+		if (!*string)
 			continue;
 
 		/* Input that begins with '-'; unchoose */
-		if (*(*ptr)->buf == '-') {
+		if (string[0] == '-') {
 			choose = 0;
-			strbuf_remove((*ptr), 0, 1);
+			string++;
+		} else {
+			choose = 1;
 		}
 
 		is_range = 0;
 		is_number = 1;
-		for (p = (*ptr)->buf; *p; p++) {
+		for (const char *p = string; *p; p++) {
 			if ('-' == *p) {
 				if (!is_range) {
 					is_range = 1;
@@ -532,27 +528,27 @@ static int parse_choice(struct menu_stuff *menu_stuff,
 		}
 
 		if (is_number) {
-			bottom = atoi((*ptr)->buf);
+			bottom = atoi(string);
 			top = bottom;
 		} else if (is_range) {
-			bottom = atoi((*ptr)->buf);
+			bottom = atoi(string);
 			/* a range can be specified like 5-7 or 5- */
-			if (!*(strchr((*ptr)->buf, '-') + 1))
+			if (!*(strchr(string, '-') + 1))
 				top = menu_stuff->nr;
 			else
-				top = atoi(strchr((*ptr)->buf, '-') + 1);
-		} else if (!strcmp((*ptr)->buf, "*")) {
+				top = atoi(strchr(string, '-') + 1);
+		} else if (!strcmp(string, "*")) {
 			bottom = 1;
 			top = menu_stuff->nr;
 		} else {
-			bottom = find_unique((*ptr)->buf, menu_stuff);
+			bottom = find_unique(string, menu_stuff);
 			top = bottom;
 		}
 
 		if (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||
 		    (is_single && bottom != top)) {
 			clean_print_color(CLEAN_COLOR_ERROR);
-			printf(_("Huh (%s)?\n"), (*ptr)->buf);
+			printf(_("Huh (%s)?\n"), string);
 			clean_print_color(CLEAN_COLOR_RESET);
 			continue;
 		}
@@ -561,7 +557,7 @@ static int parse_choice(struct menu_stuff *menu_stuff,
 			(*chosen)[i-1] = choose;
 	}
 
-	strbuf_list_free(choice_list);
+	string_list_clear(&choice, 0);
 
 	for (i = 0; i < menu_stuff->nr; i++)
 		nr += (*chosen)[i];
@@ -631,7 +627,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
 
 		nr = parse_choice(stuff,
 				  opts->flags & MENU_OPTS_SINGLETON,
-				  choice,
+				  choice.buf,
 				  &chosen);
 
 		if (opts->flags & MENU_OPTS_SINGLETON) {
@@ -679,12 +675,13 @@ static int filter_by_patterns_cmd(void)
 {
 	struct dir_struct dir = DIR_INIT;
 	struct strbuf confirm = STRBUF_INIT;
-	struct strbuf **ignore_list;
-	struct string_list_item *item;
 	struct pattern_list *pl;
 	int changed = -1, i;
 
 	for (;;) {
+		struct string_list ignore_list = STRING_LIST_INIT_NODUP;
+		struct string_list_item *item;
+
 		if (!del_list.nr)
 			break;
 
@@ -702,14 +699,15 @@ static int filter_by_patterns_cmd(void)
 			break;
 
 		pl = add_pattern_list(&dir, EXC_CMDL, "manual exclude");
-		ignore_list = strbuf_split_max(&confirm, ' ', 0);
 
-		for (i = 0; ignore_list[i]; i++) {
-			strbuf_trim(ignore_list[i]);
-			if (!ignore_list[i]->len)
+		string_list_split_in_place_f(&ignore_list, confirm.buf, " ", -1,
+					     STRING_LIST_SPLIT_TRIM);
+
+		for (i = 0; i < ignore_list.nr; i++) {
+			item = &ignore_list.items[i];
+			if (!*item->string)
 				continue;
-
-			add_pattern(ignore_list[i]->buf, "", 0, pl, -(i+1));
+			add_pattern(item->string, "", 0, pl, -(i+1));
 		}
 
 		changed = 0;
@@ -730,7 +728,7 @@ static int filter_by_patterns_cmd(void)
 			clean_print_color(CLEAN_COLOR_RESET);
 		}
 
-		strbuf_list_free(ignore_list);
+		string_list_clear(&ignore_list, 0);
 		dir_clear(&dir);
 	}
 
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 4992ac1..d62005e 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -102,14 +102,15 @@ static int graph_verify(int argc, const char **argv, const char *prefix,
 	if (opts.progress)
 		flags |= COMMIT_GRAPH_WRITE_PROGRESS;
 
-	source = odb_find_source(the_repository->objects, opts.obj_dir);
+	source = odb_find_source_or_die(the_repository->objects, opts.obj_dir);
 	graph_name = get_commit_graph_filename(source);
 	chain_name = get_commit_graph_chain_filename(source);
 	if (open_commit_graph(graph_name, &fd, &st))
 		opened = OPENED_GRAPH;
 	else if (errno != ENOENT)
 		die_errno(_("Could not open commit-graph '%s'"), graph_name);
-	else if (open_commit_graph_chain(chain_name, &fd, &st))
+	else if (open_commit_graph_chain(chain_name, &fd, &st,
+					 the_repository->hash_algo))
 		opened = OPENED_CHAIN;
 	else if (errno != ENOENT)
 		die_errno(_("could not open commit-graph chain '%s'"), chain_name);
@@ -121,15 +122,15 @@ static int graph_verify(int argc, const char **argv, const char *prefix,
 	if (opened == OPENED_NONE)
 		return 0;
 	else if (opened == OPENED_GRAPH)
-		graph = load_commit_graph_one_fd_st(the_repository, fd, &st, source);
+		graph = load_commit_graph_one_fd_st(source, fd, &st);
 	else
-		graph = load_commit_graph_chain_fd_st(the_repository, fd, &st,
+		graph = load_commit_graph_chain_fd_st(the_repository->objects, fd, &st,
 						      &incomplete_chain);
 
 	if (!graph)
 		return 1;
 
-	ret = verify_commit_graph(the_repository, graph, flags);
+	ret = verify_commit_graph(graph, flags);
 	free_commit_graph(graph);
 
 	if (incomplete_chain) {
@@ -209,6 +210,8 @@ static int git_commit_graph_write_config(const char *var, const char *value,
 {
 	if (!strcmp(var, "commitgraph.maxnewfilters"))
 		write_opts.max_new_filters = git_config_int(var, value, ctx->kvi);
+	else if (!strcmp(var, "commitgraph.changedpaths"))
+		opts.enable_changed_paths = git_config_bool(var, value) ? 1 : -1;
 	/*
 	 * No need to fall-back to 'git_default_config', since this was already
 	 * called in 'cmd_commit_graph()'.
@@ -290,7 +293,7 @@ static int graph_write(int argc, const char **argv, const char *prefix,
 	    git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0))
 		flags |= COMMIT_GRAPH_WRITE_BLOOM_FILTERS;
 
-	source = odb_find_source(the_repository->objects, opts.obj_dir);
+	source = odb_find_source_or_die(the_repository->objects, opts.obj_dir);
 
 	if (opts.reachable) {
 		if (write_commit_graph_reachable(source, flags, &write_opts))
diff --git a/builtin/commit.c b/builtin/commit.c
index b5b9608..0243f17 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -695,6 +695,7 @@ static int author_date_is_interesting(void)
 	return author_message || force_date;
 }
 
+#ifndef WITH_BREAKING_CHANGES
 static void adjust_comment_line_char(const struct strbuf *sb)
 {
 	char candidates[] = "#;@!$%^&|:";
@@ -732,6 +733,7 @@ static void adjust_comment_line_char(const struct strbuf *sb)
 	free(comment_line_str_to_free);
 	comment_line_str = comment_line_str_to_free = xstrfmt("%c", *p);
 }
+#endif /* !WITH_BREAKING_CHANGES */
 
 static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
 				struct pretty_print_context *ctx)
@@ -928,15 +930,17 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 	if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
 		die_errno(_("could not write commit template"));
 
+#ifndef WITH_BREAKING_CHANGES
 	if (auto_comment_line_char)
 		adjust_comment_line_char(&sb);
+#endif /* !WITH_BREAKING_CHANGES */
 	strbuf_release(&sb);
 
 	/* This checks if committer ident is explicitly given */
 	strbuf_addstr(&committer_ident, git_committer_info(IDENT_STRICT));
 	if (use_editor && include_status) {
 		int ident_shown = 0;
-		int saved_color_setting;
+		enum git_colorbool saved_color_setting;
 		struct ident_split ci, ai;
 		const char *hint_cleanup_all = allow_empty_message ?
 			_("Please enter the commit message for your changes."
@@ -1016,7 +1020,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); /* Add new line for clarity */
 
 		saved_color_setting = s->use_color;
-		s->use_color = 0;
+		s->use_color = GIT_COLOR_NEVER;
 		committable = run_status(s->fp, index_file, prefix, 1, s);
 		s->use_color = saved_color_setting;
 		string_list_clear_func(&s->change, change_data_free);
@@ -1793,6 +1797,9 @@ int cmd_commit(int argc,
 	show_usage_with_options_if_asked(argc, argv,
 					 builtin_commit_usage, builtin_commit_options);
 
+#ifndef WITH_BREAKING_CHANGES
+	warn_on_auto_comment_char = true;
+#endif /* !WITH_BREAKING_CHANGES */
 	prepare_repo_settings(the_repository);
 	the_repository->settings.command_requires_full_index = 0;
 
@@ -1947,7 +1954,7 @@ int cmd_commit(int argc,
 		      "new index file. Check that disk is not full and quota is\n"
 		      "not exceeded, and then \"git restore --staged :/\" to recover."));
 
-	git_test_write_commit_graph_or_die();
+	git_test_write_commit_graph_or_die(the_repository->objects->sources);
 
 	repo_rerere(the_repository, 0);
 	run_auto_maintenance(quiet);
diff --git a/builtin/config.c b/builtin/config.c
index 59fb113..75852bd 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -547,30 +547,37 @@ static int git_get_color_config(const char *var, const char *value,
 	return 0;
 }
 
-static void get_color(const struct config_location_options *opts,
+static int get_color(const struct config_location_options *opts,
 		      const char *var, const char *def_color)
 {
 	struct get_color_config_data data = {
 		.get_color_slot = var,
 		.parsed_color[0] = '\0',
 	};
+	int ret;
 
 	config_with_options(git_get_color_config, &data,
 			    &opts->source, the_repository,
 			    &opts->options);
 
 	if (!data.get_color_found && def_color) {
-		if (color_parse(def_color, data.parsed_color) < 0)
-			die(_("unable to parse default color value"));
+		if (color_parse(def_color, data.parsed_color) < 0) {
+			ret = error(_("unable to parse default color value"));
+			goto out;
+		}
 	}
 
+	ret = 0;
+
+out:
 	fputs(data.parsed_color, stdout);
+	return ret;
 }
 
 struct get_colorbool_config_data {
-	int get_colorbool_found;
-	int get_diff_color_found;
-	int get_color_ui_found;
+	enum git_colorbool get_colorbool_found;
+	enum git_colorbool get_diff_color_found;
+	enum git_colorbool get_color_ui_found;
 	const char *get_colorbool_slot;
 };
 
@@ -594,33 +601,34 @@ static int get_colorbool(const struct config_location_options *opts,
 {
 	struct get_colorbool_config_data data = {
 		.get_colorbool_slot = var,
-		.get_colorbool_found = -1,
-		.get_diff_color_found = -1,
-		.get_color_ui_found = -1,
+		.get_colorbool_found = GIT_COLOR_UNKNOWN,
+		.get_diff_color_found = GIT_COLOR_UNKNOWN,
+		.get_color_ui_found = GIT_COLOR_UNKNOWN,
 	};
+	bool result;
 
 	config_with_options(git_get_colorbool_config, &data,
 			    &opts->source, the_repository,
 			    &opts->options);
 
-	if (data.get_colorbool_found < 0) {
+	if (data.get_colorbool_found == GIT_COLOR_UNKNOWN) {
 		if (!strcmp(data.get_colorbool_slot, "color.diff"))
 			data.get_colorbool_found = data.get_diff_color_found;
-		if (data.get_colorbool_found < 0)
+		if (data.get_colorbool_found == GIT_COLOR_UNKNOWN)
 			data.get_colorbool_found = data.get_color_ui_found;
 	}
 
-	if (data.get_colorbool_found < 0)
+	if (data.get_colorbool_found == GIT_COLOR_UNKNOWN)
 		/* default value if none found in config */
 		data.get_colorbool_found = GIT_COLOR_AUTO;
 
-	data.get_colorbool_found = want_color(data.get_colorbool_found);
+	result = want_color(data.get_colorbool_found);
 
 	if (print) {
-		printf("%s\n", data.get_colorbool_found ? "true" : "false");
+		printf("%s\n", result ? "true" : "false");
 		return 0;
 	} else
-		return data.get_colorbool_found ? 0 : 1;
+		return result ? 0 : 1;
 }
 
 static void check_write(const struct git_config_source *source)
@@ -912,10 +920,13 @@ static int cmd_config_get(int argc, const char **argv, const char *prefix,
 	location_options_init(&location_opts, prefix);
 	display_options_init(&display_opts);
 
-	setup_auto_pager("config", 1);
+	if (display_opts.type != TYPE_COLOR)
+		setup_auto_pager("config", 1);
 
 	if (url)
 		ret = get_urlmatch(&location_opts, &display_opts, argv[0], url);
+	else if (display_opts.type == TYPE_COLOR && !strlen(argv[0]) && display_opts.default_value)
+		ret = get_color(&location_opts, "", display_opts.default_value);
 	else
 		ret = get_value(&location_opts, &display_opts, argv[0], value_pattern,
 				get_value_flags, flags);
@@ -1390,7 +1401,7 @@ static int cmd_config_actions(int argc, const char **argv, const char *prefix)
 	}
 	else if (actions == ACTION_GET_COLOR) {
 		check_argc(argc, 1, 2);
-		get_color(&location_opts, argv[0], argv[1]);
+		ret = get_color(&location_opts, argv[0], argv[1]);
 	}
 	else if (actions == ACTION_GET_COLORBOOL) {
 		check_argc(argc, 1, 2);
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index a61d3b4..18f6e33b 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -129,7 +129,7 @@ int cmd_count_objects(int argc,
 		struct strbuf pack_buf = STRBUF_INIT;
 		struct strbuf garbage_buf = STRBUF_INIT;
 
-		for (p = get_all_packs(the_repository); p; p = p->next) {
+		repo_for_each_pack(the_repository, p) {
 			if (!p->pack_local)
 				continue;
 			if (open_pack_index(p))
diff --git a/builtin/describe.c b/builtin/describe.c
index d7dd813..443546a 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -23,6 +23,8 @@
 #include "list-objects.h"
 #include "commit-slab.h"
 #include "wildmatch.h"
+#include "prio-queue.h"
+#include "oidset.h"
 
 #define MAX_TAGS	(FLAG_BITS - 1)
 #define DEFAULT_CANDIDATES 10
@@ -152,20 +154,19 @@ static void add_to_known_names(const char *path,
 	}
 }
 
-static int get_name(const char *path, const char *referent UNUSED, const struct object_id *oid,
-		    int flag UNUSED, void *cb_data UNUSED)
+static int get_name(const struct reference *ref, void *cb_data UNUSED)
 {
 	int is_tag = 0;
 	struct object_id peeled;
 	int is_annotated, prio;
 	const char *path_to_match = NULL;
 
-	if (skip_prefix(path, "refs/tags/", &path_to_match)) {
+	if (skip_prefix(ref->name, "refs/tags/", &path_to_match)) {
 		is_tag = 1;
 	} else if (all) {
 		if ((exclude_patterns.nr || patterns.nr) &&
-		    !skip_prefix(path, "refs/heads/", &path_to_match) &&
-		    !skip_prefix(path, "refs/remotes/", &path_to_match)) {
+		    !skip_prefix(ref->name, "refs/heads/", &path_to_match) &&
+		    !skip_prefix(ref->name, "refs/remotes/", &path_to_match)) {
 			/* Only accept reference of known type if there are match/exclude patterns */
 			return 0;
 		}
@@ -207,10 +208,10 @@ static int get_name(const char *path, const char *referent UNUSED, const struct
 	}
 
 	/* Is it annotated? */
-	if (!peel_iterated_oid(the_repository, oid, &peeled)) {
-		is_annotated = !oideq(oid, &peeled);
+	if (!reference_get_peeled_oid(the_repository, ref, &peeled)) {
+		is_annotated = !oideq(ref->oid, &peeled);
 	} else {
-		oidcpy(&peeled, oid);
+		oidcpy(&peeled, ref->oid);
 		is_annotated = 0;
 	}
 
@@ -227,7 +228,8 @@ static int get_name(const char *path, const char *referent UNUSED, const struct
 	else
 		prio = 0;
 
-	add_to_known_names(all ? path + 5 : path + 10, &peeled, prio, oid);
+	add_to_known_names(all ? ref->name + 5 : ref->name + 10,
+			   &peeled, prio, ref->oid);
 	return 0;
 }
 
@@ -249,36 +251,83 @@ static int compare_pt(const void *a_, const void *b_)
 	return 0;
 }
 
-static unsigned long finish_depth_computation(
-	struct commit_list **list,
-	struct possible_tag *best)
+struct lazy_queue {
+	struct prio_queue queue;
+	bool get_pending;
+};
+
+#define LAZY_QUEUE_INIT { { compare_commits_by_commit_date }, false }
+
+static void *lazy_queue_get(struct lazy_queue *queue)
+{
+	if (queue->get_pending)
+		prio_queue_get(&queue->queue);
+	else
+		queue->get_pending = true;
+	return prio_queue_peek(&queue->queue);
+}
+
+static void lazy_queue_put(struct lazy_queue *queue, void *thing)
+{
+	if (queue->get_pending)
+		prio_queue_replace(&queue->queue, thing);
+	else
+		prio_queue_put(&queue->queue, thing);
+	queue->get_pending = false;
+}
+
+static bool lazy_queue_empty(const struct lazy_queue *queue)
+{
+	return queue->queue.nr == (queue->get_pending ? 1 : 0);
+}
+
+static void lazy_queue_clear(struct lazy_queue *queue)
+{
+	clear_prio_queue(&queue->queue);
+	queue->get_pending = false;
+}
+
+static unsigned long finish_depth_computation(struct lazy_queue *queue,
+					      struct possible_tag *best)
 {
 	unsigned long seen_commits = 0;
-	while (*list) {
-		struct commit *c = pop_commit(list);
+	struct oidset unflagged = OIDSET_INIT;
+
+	for (size_t i = queue->get_pending ? 1 : 0; i < queue->queue.nr; i++) {
+		struct commit *commit = queue->queue.array[i].data;
+		if (!(commit->object.flags & best->flag_within))
+			oidset_insert(&unflagged, &commit->object.oid);
+	}
+
+	while (!lazy_queue_empty(queue)) {
+		struct commit *c = lazy_queue_get(queue);
 		struct commit_list *parents = c->parents;
 		seen_commits++;
 		if (c->object.flags & best->flag_within) {
-			struct commit_list *a = *list;
-			while (a) {
-				struct commit *i = a->item;
-				if (!(i->object.flags & best->flag_within))
-					break;
-				a = a->next;
-			}
-			if (!a)
+			if (!oidset_size(&unflagged))
 				break;
-		} else
+		} else {
+			oidset_remove(&unflagged, &c->object.oid);
 			best->depth++;
+		}
 		while (parents) {
+			unsigned seen, flag_before, flag_after;
 			struct commit *p = parents->item;
 			repo_parse_commit(the_repository, p);
-			if (!(p->object.flags & SEEN))
-				commit_list_insert_by_date(p, list);
+			seen = p->object.flags & SEEN;
+			if (!seen)
+				lazy_queue_put(queue, p);
+			flag_before = p->object.flags & best->flag_within;
 			p->object.flags |= c->object.flags;
+			flag_after = p->object.flags & best->flag_within;
+			if (!seen && !flag_after)
+				oidset_insert(&unflagged, &p->object.oid);
+			if (seen && !flag_before && flag_after)
+				oidset_remove(&unflagged, &p->object.oid);
 			parents = parents->next;
 		}
 	}
+	oidset_clear(&unflagged);
 	return seen_commits;
 }
 
@@ -313,18 +362,16 @@ static void append_suffix(int depth, const struct object_id *oid, struct strbuf
 		    repo_find_unique_abbrev(the_repository, oid, abbrev));
 }
 
-static void describe_commit(struct object_id *oid, struct strbuf *dst)
+static void describe_commit(struct commit *cmit, struct strbuf *dst)
 {
-	struct commit *cmit, *gave_up_on = NULL;
-	struct commit_list *list;
+	struct commit *gave_up_on = NULL;
+	struct lazy_queue queue = LAZY_QUEUE_INIT;
 	struct commit_name *n;
 	struct possible_tag all_matches[MAX_TAGS];
 	unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
 	unsigned long seen_commits = 0;
 	unsigned int unannotated_cnt = 0;
 
-	cmit = lookup_commit_reference(the_repository, oid);
-
 	n = find_commit_name(&cmit->object.oid);
 	if (n && (tags || all || n->prio == 2)) {
 		/*
@@ -332,7 +379,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 		 */
 		append_name(n, dst);
 		if (n->misnamed || longformat)
-			append_suffix(0, n->tag ? get_tagged_oid(n->tag) : oid, dst);
+			append_suffix(0, n->tag ? get_tagged_oid(n->tag) : &cmit->object.oid, dst);
 		if (suffix)
 			strbuf_addstr(dst, suffix);
 		return;
@@ -359,11 +406,10 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 		have_util = 1;
 	}
 
-	list = NULL;
 	cmit->object.flags = SEEN;
-	commit_list_insert(cmit, &list);
-	while (list) {
-		struct commit *c = pop_commit(&list);
+	lazy_queue_put(&queue, cmit);
+	while (!lazy_queue_empty(&queue)) {
+		struct commit *c = lazy_queue_get(&queue);
 		struct commit_list *parents = c->parents;
 		struct commit_name **slot;
 
@@ -397,7 +443,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 				t->depth++;
 		}
 		/* Stop if last remaining path already covered by best candidate(s) */
-		if (annotated_cnt && !list) {
+		if (annotated_cnt && lazy_queue_empty(&queue)) {
 			int best_depth = INT_MAX;
 			unsigned best_within = 0;
 			for (cur_match = 0; cur_match < match_cnt; cur_match++) {
@@ -420,7 +466,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 			struct commit *p = parents->item;
 			repo_parse_commit(the_repository, p);
 			if (!(p->object.flags & SEEN))
-				commit_list_insert_by_date(p, &list);
+				lazy_queue_put(&queue, p);
 			p->object.flags |= c->object.flags;
 			parents = parents->next;
 
@@ -435,6 +481,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 			strbuf_add_unique_abbrev(dst, cmit_oid, abbrev);
 			if (suffix)
 				strbuf_addstr(dst, suffix);
+			lazy_queue_clear(&queue);
 			return;
 		}
 		if (unannotated_cnt)
@@ -450,11 +497,11 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 	QSORT(all_matches, match_cnt, compare_pt);
 
 	if (gave_up_on) {
-		commit_list_insert_by_date(gave_up_on, &list);
+		lazy_queue_put(&queue, gave_up_on);
 		seen_commits--;
 	}
-	seen_commits += finish_depth_computation(&list, &all_matches[0]);
-	free_commit_list(list);
+	seen_commits += finish_depth_computation(&queue, &all_matches[0]);
+	lazy_queue_clear(&queue);
 
 	if (debug) {
 		static int label_width = -1;
@@ -489,8 +536,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 }
 
 struct process_commit_data {
-	struct object_id current_commit;
-	struct object_id looking_for;
+	struct commit *current_commit;
+	const struct object_id *looking_for;
 	struct strbuf *dst;
 	struct rev_info *revs;
 };
@@ -498,34 +545,43 @@ struct process_commit_data {
 static void process_commit(struct commit *commit, void *data)
 {
 	struct process_commit_data *pcd = data;
-	pcd->current_commit = commit->object.oid;
+	pcd->current_commit = commit;
 }
 
 static void process_object(struct object *obj, const char *path, void *data)
 {
 	struct process_commit_data *pcd = data;
 
-	if (oideq(&pcd->looking_for, &obj->oid) && !pcd->dst->len) {
+	if (oideq(pcd->looking_for, &obj->oid) && !pcd->dst->len) {
 		reset_revision_walk();
-		describe_commit(&pcd->current_commit, pcd->dst);
-		strbuf_addf(pcd->dst, ":%s", path);
+		if (pcd->current_commit) {
+			describe_commit(pcd->current_commit, pcd->dst);
+			strbuf_addf(pcd->dst, ":%s", path);
+		}
 		free_commit_list(pcd->revs->commits);
 		pcd->revs->commits = NULL;
 	}
 }
 
-static void describe_blob(struct object_id oid, struct strbuf *dst)
+static void describe_blob(const struct object_id *oid, struct strbuf *dst)
 {
 	struct rev_info revs;
 	struct strvec args = STRVEC_INIT;
-	struct process_commit_data pcd = { *null_oid(the_hash_algo), oid, dst, &revs};
+	struct object_id head_oid;
+	struct process_commit_data pcd = { NULL, oid, dst, &revs};
+
+	if (repo_get_oid(the_repository, "HEAD", &head_oid))
+		die(_("cannot search for blob '%s' on an unborn branch"),
+		    oid_to_hex(oid));
 
 	strvec_pushl(&args, "internal: The first arg is not parsed",
-		     "--objects", "--in-commit-order", "--reverse", "HEAD",
+		     "--objects", "--in-commit-order", "--reverse",
+		     oid_to_hex(&head_oid),
 		     NULL);
 
 	repo_init_revisions(the_repository, &revs, NULL);
-	if (setup_revisions(args.nr, args.v, &revs, NULL) > 1)
+	setup_revisions_from_strvec(&args, &revs, NULL);
+	if (args.nr > 1)
 		BUG("setup_revisions could not handle all args?");
 
 	if (prepare_revision_walk(&revs))
@@ -535,6 +591,9 @@ static void describe_blob(struct object_id oid, struct strbuf *dst)
 	reset_revision_walk();
 	release_revisions(&revs);
 	strvec_clear(&args);
+
+	if (!dst->len)
+		die(_("blob '%s' not reachable from HEAD"), oid_to_hex(oid));
 }
 
 static void describe(const char *arg, int last_one)
@@ -551,10 +610,10 @@ static void describe(const char *arg, int last_one)
 	cmit = lookup_commit_reference_gently(the_repository, &oid, 1);
 
 	if (cmit)
-		describe_commit(&oid, &sb);
+		describe_commit(cmit, &sb);
 	else if (odb_read_object_info(the_repository->objects,
 				      &oid, NULL) == OBJ_BLOB)
-		describe_blob(oid, &sb);
+		describe_blob(&oid, &sb);
 	else
 		die(_("%s is neither a commit nor blob"), arg);
 
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index c06ee0b..0421360 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -37,8 +37,6 @@ static const char *const fast_export_usage[] = {
 	NULL
 };
 
-enum sign_mode { SIGN_ABORT, SIGN_VERBATIM, SIGN_STRIP, SIGN_WARN_VERBATIM, SIGN_WARN_STRIP };
-
 static int progress;
 static enum sign_mode signed_tag_mode = SIGN_ABORT;
 static enum sign_mode signed_commit_mode = SIGN_STRIP;
@@ -59,23 +57,16 @@ static struct hashmap anonymized_seeds;
 static struct revision_sources revision_sources;
 
 static int parse_opt_sign_mode(const struct option *opt,
-				     const char *arg, int unset)
+			       const char *arg, int unset)
 {
 	enum sign_mode *val = opt->value;
+
 	if (unset)
 		return 0;
-	else if (!strcmp(arg, "abort"))
-		*val = SIGN_ABORT;
-	else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore"))
-		*val = SIGN_VERBATIM;
-	else if (!strcmp(arg, "warn-verbatim") || !strcmp(arg, "warn"))
-		*val = SIGN_WARN_VERBATIM;
-	else if (!strcmp(arg, "warn-strip"))
-		*val = SIGN_WARN_STRIP;
-	else if (!strcmp(arg, "strip"))
-		*val = SIGN_STRIP;
-	else
-		return error("Unknown %s mode: %s", opt->long_name, arg);
+
+	if (parse_sign_mode(arg, val))
+		return error(_("unknown %s mode: %s"), opt->long_name, arg);
+
 	return 0;
 }
 
@@ -91,7 +82,7 @@ static int parse_opt_tag_of_filtered_mode(const struct option *opt,
 	else if (!strcmp(arg, "rewrite"))
 		*val = REWRITE;
 	else
-		return error("Unknown tag-of-filtered mode: %s", arg);
+		return error(_("unknown tag-of-filtered mode: %s"), arg);
 	return 0;
 }
 
@@ -116,7 +107,7 @@ static int parse_opt_reencode_mode(const struct option *opt,
 		if (!strcasecmp(arg, "abort"))
 			*val = REENCODE_ABORT;
 		else
-			return error("Unknown reencoding mode: %s", arg);
+			return error(_("unknown reencoding mode: %s"), arg);
 	}
 
 	return 0;
@@ -327,16 +318,16 @@ static void export_blob(const struct object_id *oid)
 	} else {
 		buf = odb_read_object(the_repository->objects, oid, &type, &size);
 		if (!buf)
-			die("could not read blob %s", oid_to_hex(oid));
+			die(_("could not read blob %s"), oid_to_hex(oid));
 		if (check_object_signature(the_repository, oid, buf, size,
 					   type) < 0)
-			die("oid mismatch in blob %s", oid_to_hex(oid));
+			die(_("oid mismatch in blob %s"), oid_to_hex(oid));
 		object = parse_object_buffer(the_repository, oid, type,
 					     size, buf, &eaten);
 	}
 
 	if (!object)
-		die("Could not read blob %s", oid_to_hex(oid));
+		die(_("could not read blob %s"), oid_to_hex(oid));
 
 	mark_next_object(object);
 
@@ -345,7 +336,7 @@ static void export_blob(const struct object_id *oid)
 		printf("original-oid %s\n", oid_to_hex(oid));
 	printf("data %"PRIuMAX"\n", (uintmax_t)size);
 	if (size && fwrite(buf, size, 1, stdout) != 1)
-		die_errno("could not write blob '%s'", oid_to_hex(oid));
+		die_errno(_("could not write blob '%s'"), oid_to_hex(oid));
 	printf("\n");
 
 	show_progress();
@@ -508,10 +499,10 @@ static void show_filemodify(struct diff_queue_struct *q,
 			break;
 
 		default:
-			die("Unexpected comparison status '%c' for %s, %s",
-				q->queue[i]->status,
-				ospec->path ? ospec->path : "none",
-				spec->path ? spec->path : "none");
+			die(_("unexpected comparison status '%c' for %s, %s"),
+			    q->queue[i]->status,
+			    ospec->path ? ospec->path : _("none"),
+			    spec->path ? spec->path : _("none"));
 		}
 	}
 }
@@ -708,14 +699,14 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
 
 	author = strstr(commit_buffer_cursor, "\nauthor ");
 	if (!author)
-		die("could not find author in commit %s",
+		die(_("could not find author in commit %s"),
 		    oid_to_hex(&commit->object.oid));
 	author++;
 	commit_buffer_cursor = author_end = strchrnul(author, '\n');
 
 	committer = strstr(commit_buffer_cursor, "\ncommitter ");
 	if (!committer)
-		die("could not find committer in commit %s",
+		die(_("could not find committer in commit %s"),
 		    oid_to_hex(&commit->object.oid));
 	committer++;
 	commit_buffer_cursor = committer_end = strchrnul(committer, '\n');
@@ -790,8 +781,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
 		case REENCODE_NO:
 			break;
 		case REENCODE_ABORT:
-			die("Encountered commit-specific encoding %.*s in commit "
-			    "%s; use --reencode=[yes|no] to handle it",
+			die(_("encountered commit-specific encoding %.*s in commit "
+			      "%s; use --reencode=[yes|no] to handle it"),
 			    (int)encoding_len, encoding,
 			    oid_to_hex(&commit->object.oid));
 		}
@@ -807,11 +798,11 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
 	if (signatures.nr) {
 		switch (signed_commit_mode) {
 		case SIGN_ABORT:
-			die("encountered signed commit %s; use "
-			    "--signed-commits=<mode> to handle it",
+			die(_("encountered signed commit %s; use "
+			      "--signed-commits=<mode> to handle it"),
 			    oid_to_hex(&commit->object.oid));
 		case SIGN_WARN_VERBATIM:
-			warning("exporting %"PRIuMAX" signature(s) for commit %s",
+			warning(_("exporting %"PRIuMAX" signature(s) for commit %s"),
 				(uintmax_t)signatures.nr, oid_to_hex(&commit->object.oid));
 			/* fallthru */
 		case SIGN_VERBATIM:
@@ -821,7 +812,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
 			}
 			break;
 		case SIGN_WARN_STRIP:
-			warning("stripping signature(s) from commit %s",
+			warning(_("stripping signature(s) from commit %s"),
 				oid_to_hex(&commit->object.oid));
 			/* fallthru */
 		case SIGN_STRIP:
@@ -899,7 +890,8 @@ static void handle_tag(const char *name, struct tag *tag)
 		tagged = ((struct tag *)tagged)->tagged;
 	}
 	if (tagged->type == OBJ_TREE) {
-		warning("Omitting tag %s,\nsince tags of trees (or tags of tags of trees, etc.) are not supported.",
+		warning(_("omitting tag %s,\nsince tags of trees (or tags "
+			  "of tags of trees, etc.) are not supported."),
 			oid_to_hex(&tag->object.oid));
 		return;
 	}
@@ -907,7 +899,7 @@ static void handle_tag(const char *name, struct tag *tag)
 	buf = odb_read_object(the_repository->objects, &tag->object.oid,
 			      &type, &size);
 	if (!buf)
-		die("could not read tag %s", oid_to_hex(&tag->object.oid));
+		die(_("could not read tag %s"), oid_to_hex(&tag->object.oid));
 	message = memmem(buf, size, "\n\n", 2);
 	if (message) {
 		message += 2;
@@ -940,26 +932,25 @@ static void handle_tag(const char *name, struct tag *tag)
 
 	/* handle signed tags */
 	if (message) {
-		const char *signature = strstr(message,
-					       "\n-----BEGIN PGP SIGNATURE-----\n");
-		if (signature)
+		size_t sig_offset = parse_signed_buffer(message, message_size);
+		if (sig_offset < message_size)
 			switch (signed_tag_mode) {
 			case SIGN_ABORT:
-				die("encountered signed tag %s; use "
-				    "--signed-tags=<mode> to handle it",
+				die(_("encountered signed tag %s; use "
+				      "--signed-tags=<mode> to handle it"),
 				    oid_to_hex(&tag->object.oid));
 			case SIGN_WARN_VERBATIM:
-				warning("exporting signed tag %s",
+				warning(_("exporting signed tag %s"),
 					oid_to_hex(&tag->object.oid));
 				/* fallthru */
 			case SIGN_VERBATIM:
 				break;
 			case SIGN_WARN_STRIP:
-				warning("stripping signature from tag %s",
+				warning(_("stripping signature from tag %s"),
 					oid_to_hex(&tag->object.oid));
 				/* fallthru */
 			case SIGN_STRIP:
-				message_size = signature + 1 - message;
+				message_size = sig_offset;
 				break;
 			}
 	}
@@ -970,8 +961,8 @@ static void handle_tag(const char *name, struct tag *tag)
 	if (!tagged_mark) {
 		switch (tag_of_filtered_mode) {
 		case TAG_FILTERING_ABORT:
-			die("tag %s tags unexported object; use "
-			    "--tag-of-filtered-object=<mode> to handle it",
+			die(_("tag %s tags unexported object; use "
+			      "--tag-of-filtered-object=<mode> to handle it"),
 			    oid_to_hex(&tag->object.oid));
 		case DROP:
 			/* Ignore this tag altogether */
@@ -979,7 +970,7 @@ static void handle_tag(const char *name, struct tag *tag)
 			return;
 		case REWRITE:
 			if (tagged->type == OBJ_TAG && !mark_tags) {
-				die(_("Error: Cannot export nested tags unless --mark-tags is specified."));
+				die(_("cannot export nested tags unless --mark-tags is specified."));
 			} else if (tagged->type == OBJ_COMMIT) {
 				p = rewrite_commit((struct commit *)tagged);
 				if (!p) {
@@ -1035,7 +1026,7 @@ static struct commit *get_commit(struct rev_cmdline_entry *e, const char *full_n
 			tag = (struct tag *)tag->tagged;
 		}
 		if (!tag)
-			die("Tag %s points nowhere?", e->name);
+			die(_("tag %s points nowhere?"), e->name);
 		return (struct commit *)tag;
 	}
 	default:
@@ -1073,7 +1064,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
 
 		commit = get_commit(e, full_name);
 		if (!commit) {
-			warning("%s: Unexpected object of type %s, skipping.",
+			warning(_("%s: unexpected object of type %s, skipping."),
 				e->name,
 				type_name(e->item->type));
 			free(full_name);
@@ -1088,7 +1079,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
 			free(full_name);
 			continue;
 		default: /* OBJ_TAG (nested tags) is already handled */
-			warning("Tag points to object of unexpected type %s, skipping.",
+			warning(_("tag points to object of unexpected type %s, skipping."),
 				type_name(commit->object.type));
 			free(full_name);
 			continue;
@@ -1184,7 +1175,7 @@ static void export_marks(char *file)
 
 	f = fopen_for_writing(file);
 	if (!f)
-		die_errno("Unable to open marks file %s for writing.", file);
+		die_errno(_("unable to open marks file %s for writing."), file);
 
 	for (i = 0; i < idnums.size; i++) {
 		if (deco->base && deco->base->type == 1) {
@@ -1201,7 +1192,7 @@ static void export_marks(char *file)
 	e |= ferror(f);
 	e |= fclose(f);
 	if (e)
-		error("Unable to write marks file %s.", file);
+		error(_("unable to write marks file %s."), file);
 }
 
 static void import_marks(char *input_file, int check_exists)
@@ -1224,20 +1215,20 @@ static void import_marks(char *input_file, int check_exists)
 
 		line_end = strchr(line, '\n');
 		if (line[0] != ':' || !line_end)
-			die("corrupt mark line: %s", line);
+			die(_("corrupt mark line: %s"), line);
 		*line_end = '\0';
 
 		mark = strtoumax(line + 1, &mark_end, 10);
 		if (!mark || mark_end == line + 1
 			|| *mark_end != ' ' || get_oid_hex(mark_end + 1, &oid))
-			die("corrupt mark line: %s", line);
+			die(_("corrupt mark line: %s"), line);
 
 		if (last_idnum < mark)
 			last_idnum = mark;
 
 		type = odb_read_object_info(the_repository->objects, &oid, NULL);
 		if (type < 0)
-			die("object not found: %s", oid_to_hex(&oid));
+			die(_("object not found: %s"), oid_to_hex(&oid));
 
 		if (type != OBJ_COMMIT)
 			/* only commits */
@@ -1245,12 +1236,12 @@ static void import_marks(char *input_file, int check_exists)
 
 		commit = lookup_commit(the_repository, &oid);
 		if (!commit)
-			die("not a commit? can't happen: %s", oid_to_hex(&oid));
+			die(_("not a commit? can't happen: %s"), oid_to_hex(&oid));
 
 		object = &commit->object;
 
 		if (object->flags & SHOWN)
-			error("Object %s already has a mark", oid_to_hex(&oid));
+			error(_("object %s already has a mark"), oid_to_hex(&oid));
 
 		mark_object(object, mark);
 
@@ -1404,7 +1395,7 @@ int cmd_fast_export(int argc,
 	get_tags_and_duplicates(&revs.cmdline);
 
 	if (prepare_revision_walk(&revs))
-		die("revision walk setup failed");
+		die(_("revision walk setup failed"));
 
 	revs.reverse = 1;
 	revs.diffopt.format_callback = show_filemodify;
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 2c35f93..4cd0b07 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -188,6 +188,9 @@ static int global_argc;
 static const char **global_argv;
 static const char *global_prefix;
 
+static enum sign_mode signed_tag_mode = SIGN_VERBATIM;
+static enum sign_mode signed_commit_mode = SIGN_VERBATIM;
+
 /* Memory pools */
 static struct mem_pool fi_mem_pool = {
 	.block_alloc = 2*1024*1024 - sizeof(struct mp_block),
@@ -336,12 +339,12 @@ static void write_crash_report(const char *err)
 	struct recent_command *rc;
 
 	if (!rpt) {
-		error_errno("can't write crash report %s", loc);
+		error_errno(_("can't write crash report %s"), loc);
 		free(loc);
 		return;
 	}
 
-	fprintf(stderr, "fast-import: dumping crash report to %s\n", loc);
+	fprintf(stderr, _("fast-import: dumping crash report to %s\n"), loc);
 
 	fprintf(rpt, "fast-import crash report:\n");
 	fprintf(rpt, "    fast-import process: %"PRIuMAX"\n", (uintmax_t) getpid());
@@ -585,7 +588,7 @@ static void *find_mark(struct mark_set *s, uintmax_t idnum)
 			oe = s->data.marked[idnum];
 	}
 	if (!oe)
-		die("mark :%" PRIuMAX " not declared", orig_idnum);
+		die(_("mark :%" PRIuMAX " not declared"), orig_idnum);
 	return oe;
 }
 
@@ -625,9 +628,9 @@ static struct branch *new_branch(const char *name)
 	struct branch *b = lookup_branch(name);
 
 	if (b)
-		die("Invalid attempt to create duplicate branch: %s", name);
+		die(_("invalid attempt to create duplicate branch: %s"), name);
 	if (check_refname_format(name, REFNAME_ALLOW_ONELEVEL))
-		die("Branch name doesn't conform to GIT standards: %s", name);
+		die(_("branch name doesn't conform to Git standards: %s"), name);
 
 	b = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct branch));
 	b->name = mem_pool_strdup(&fi_mem_pool, name);
@@ -798,7 +801,7 @@ static const char *create_index(void)
 				*c++ = &e->idx;
 	last = idx + object_count;
 	if (c != last)
-		die("internal consistency error creating the index");
+		die(_("internal consistency error creating the index"));
 
 	tmpfile = write_idx_file(the_repository, NULL, idx, object_count,
 				 &pack_idx_opts, pack_data->hash);
@@ -816,18 +819,18 @@ static char *keep_pack(const char *curr_index_name)
 	keep_fd = safe_create_file_with_leading_directories(pack_data->repo,
 							    name.buf);
 	if (keep_fd < 0)
-		die_errno("cannot create keep file");
+		die_errno(_("cannot create keep file"));
 	write_or_die(keep_fd, keep_msg, strlen(keep_msg));
 	if (close(keep_fd))
-		die_errno("failed to write keep file");
+		die_errno(_("failed to write keep file"));
 
 	odb_pack_name(pack_data->repo, &name, pack_data->hash, "pack");
 	if (finalize_object_file(pack_data->repo, pack_data->pack_name, name.buf))
-		die("cannot store pack file");
+		die(_("cannot store pack file"));
 
 	odb_pack_name(pack_data->repo, &name, pack_data->hash, "idx");
 	if (finalize_object_file(pack_data->repo, curr_index_name, name.buf))
-		die("cannot store index file");
+		die(_("cannot store index file"));
 	free((void *)curr_index_name);
 	return strbuf_detach(&name, NULL);
 }
@@ -850,7 +853,7 @@ static int loosen_small_pack(const struct packed_git *p)
 	struct child_process unpack = CHILD_PROCESS_INIT;
 
 	if (lseek(p->pack_fd, 0, SEEK_SET) < 0)
-		die_errno("Failed seeking to start of '%s'", p->pack_name);
+		die_errno(_("failed seeking to start of '%s'"), p->pack_name);
 
 	unpack.in = p->pack_fd;
 	unpack.git_cmd = 1;
@@ -897,11 +900,11 @@ static void end_packfile(void)
 		idx_name = keep_pack(create_index());
 
 		/* Register the packfile with core git's machinery. */
-		new_p = add_packed_git(pack_data->repo, idx_name, strlen(idx_name), 1);
+		new_p = packfile_store_load_pack(pack_data->repo->objects->packfiles,
+						 idx_name, 1);
 		if (!new_p)
-			die("core git rejected index %s", idx_name);
+			die(_("core Git rejected index %s"), idx_name);
 		all_packs[pack_id] = new_p;
-		install_packed_git(the_repository, new_p);
 		free(idx_name);
 
 		/* Print the boundary */
@@ -952,6 +955,7 @@ static int store_object(
 	struct object_id *oidout,
 	uintmax_t mark)
 {
+	struct packfile_store *packs = the_repository->objects->packfiles;
 	void *out, *delta;
 	struct object_entry *e;
 	unsigned char hdr[96];
@@ -975,7 +979,7 @@ static int store_object(
 	if (e->idx.offset) {
 		duplicate_count_by_type[type]++;
 		return 1;
-	} else if (find_oid_pack(&oid, get_all_packs(the_repository))) {
+	} else if (packfile_list_find_oid(packfile_store_get_packs(packs), &oid)) {
 		e->type = type;
 		e->pack_id = MAX_PACK_ID;
 		e->idx.offset = 1; /* just not zero! */
@@ -1086,12 +1090,13 @@ static int store_object(
 static void truncate_pack(struct hashfile_checkpoint *checkpoint)
 {
 	if (hashfile_truncate(pack_file, checkpoint))
-		die_errno("cannot truncate pack to skip duplicate");
+		die_errno(_("cannot truncate pack to skip duplicate"));
 	pack_size = checkpoint->offset;
 }
 
 static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
 {
+	struct packfile_store *packs = the_repository->objects->packfiles;
 	size_t in_sz = 64 * 1024, out_sz = 64 * 1024;
 	unsigned char *in_buf = xmalloc(in_sz);
 	unsigned char *out_buf = xmalloc(out_sz);
@@ -1133,7 +1138,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
 			size_t cnt = in_sz < len ? in_sz : (size_t)len;
 			size_t n = fread(in_buf, 1, cnt, stdin);
 			if (!n && feof(stdin))
-				die("EOF in data (%" PRIuMAX " bytes remaining)", len);
+				die(_("EOF in data (%" PRIuMAX " bytes remaining)"), len);
 
 			git_hash_update(&c, in_buf, n);
 			s.next_in = in_buf;
@@ -1157,7 +1162,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
 		case Z_STREAM_END:
 			continue;
 		default:
-			die("unexpected deflate failure: %d", status);
+			die(_("unexpected deflate failure: %d"), status);
 		}
 	}
 	git_deflate_end(&s);
@@ -1175,7 +1180,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
 		duplicate_count_by_type[OBJ_BLOB]++;
 		truncate_pack(&checkpoint);
 
-	} else if (find_oid_pack(&oid, get_all_packs(the_repository))) {
+	} else if (packfile_list_find_oid(packfile_store_get_packs(packs), &oid)) {
 		e->type = OBJ_BLOB;
 		e->pack_id = MAX_PACK_ID;
 		e->idx.offset = 1; /* just not zero! */
@@ -1259,16 +1264,16 @@ static void load_tree(struct tree_entry *root)
 	myoe = find_object(oid);
 	if (myoe && myoe->pack_id != MAX_PACK_ID) {
 		if (myoe->type != OBJ_TREE)
-			die("Not a tree: %s", oid_to_hex(oid));
+			die(_("not a tree: %s"), oid_to_hex(oid));
 		t->delta_depth = myoe->depth;
 		buf = gfi_unpack_entry(myoe, &size);
 		if (!buf)
-			die("Can't load tree %s", oid_to_hex(oid));
+			die(_("can't load tree %s"), oid_to_hex(oid));
 	} else {
 		enum object_type type;
 		buf = odb_read_object(the_repository->objects, oid, &type, &size);
 		if (!buf || type != OBJ_TREE)
-			die("Can't load tree %s", oid_to_hex(oid));
+			die(_("can't load tree %s"), oid_to_hex(oid));
 	}
 
 	c = buf;
@@ -1282,7 +1287,7 @@ static void load_tree(struct tree_entry *root)
 		e->tree = NULL;
 		c = parse_mode(c, &e->versions[1].mode);
 		if (!c)
-			die("Corrupt mode in %s", oid_to_hex(oid));
+			die(_("corrupt mode in %s"), oid_to_hex(oid));
 		e->versions[0].mode = e->versions[1].mode;
 		e->name = to_atom(c, strlen(c));
 		c += e->name->str_len + 1;
@@ -1394,7 +1399,7 @@ static void tree_content_replace(
 	struct tree_content *newtree)
 {
 	if (!S_ISDIR(mode))
-		die("Root cannot be a non-directory");
+		die(_("root cannot be a non-directory"));
 	oidclr(&root->versions[0].oid, the_repository->hash_algo);
 	oidcpy(&root->versions[1].oid, oid);
 	if (root->tree)
@@ -1417,9 +1422,9 @@ static int tree_content_set(
 	slash1 = strchrnul(p, '/');
 	n = slash1 - p;
 	if (!n)
-		die("Empty path component found in input");
+		die(_("empty path component found in input"));
 	if (!*slash1 && !S_ISDIR(mode) && subtree)
-		die("Non-directories cannot have subtrees");
+		die(_("non-directories cannot have subtrees"));
 
 	if (!root->tree)
 		load_tree(root);
@@ -1571,7 +1576,7 @@ static int tree_content_get(
 	slash1 = strchrnul(p, '/');
 	n = slash1 - p;
 	if (!n && !allow_root)
-		die("Empty path component found in input");
+		die(_("empty path component found in input"));
 
 	if (!root->tree)
 		load_tree(root);
@@ -1617,8 +1622,8 @@ static int update_branch(struct branch *b)
 	    !strcmp(b->name + strlen(replace_prefix),
 		    oid_to_hex(&b->oid))) {
 		if (!quiet)
-			warning("Dropping %s since it would point to "
-				"itself (i.e. to %s)",
+			warning(_("dropping %s since it would point to "
+				  "itself (i.e. to %s)"),
 				b->name, oid_to_hex(&b->oid));
 		refs_delete_ref(get_main_ref_store(the_repository),
 				NULL, b->name, NULL, 0);
@@ -1641,14 +1646,14 @@ static int update_branch(struct branch *b)
 		new_cmit = lookup_commit_reference_gently(the_repository,
 							  &b->oid, 0);
 		if (!old_cmit || !new_cmit)
-			return error("Branch %s is missing commits.", b->name);
+			return error(_("branch %s is missing commits."), b->name);
 
 		ret = repo_in_merge_bases(the_repository, old_cmit, new_cmit);
 		if (ret < 0)
 			exit(128);
 		if (!ret) {
-			warning("Not updating %s"
-				" (new tip %s does not contain %s)",
+			warning(_("not updating %s"
+				  " (new tip %s does not contain %s)"),
 				b->name, oid_to_hex(&b->oid),
 				oid_to_hex(&old_oid));
 			return -1;
@@ -1724,13 +1729,13 @@ static void dump_marks(void)
 		return;
 
 	if (safe_create_leading_directories_const(the_repository, export_marks_file)) {
-		failure |= error_errno("unable to create leading directories of %s",
+		failure |= error_errno(_("unable to create leading directories of %s"),
 				       export_marks_file);
 		return;
 	}
 
 	if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) {
-		failure |= error_errno("Unable to write marks file %s",
+		failure |= error_errno(_("unable to write marks file %s"),
 				       export_marks_file);
 		return;
 	}
@@ -1739,14 +1744,14 @@ static void dump_marks(void)
 	if (!f) {
 		int saved_errno = errno;
 		rollback_lock_file(&mark_lock);
-		failure |= error("Unable to write marks file %s: %s",
+		failure |= error(_("unable to write marks file %s: %s"),
 			export_marks_file, strerror(saved_errno));
 		return;
 	}
 
 	for_each_mark(marks, 0, dump_marks_fn, f);
 	if (commit_lock_file(&mark_lock)) {
-		failure |= error_errno("Unable to write file %s",
+		failure |= error_errno(_("unable to write file %s"),
 				       export_marks_file);
 		return;
 	}
@@ -1760,7 +1765,7 @@ static void insert_object_entry(struct mark_set **s, struct object_id *oid, uint
 		enum object_type type = odb_read_object_info(the_repository->objects,
 							     oid, NULL);
 		if (type < 0)
-			die("object not found: %s", oid_to_hex(oid));
+			die(_("object not found: %s"), oid_to_hex(oid));
 		e = insert_object(oid);
 		e->type = type;
 		e->pack_id = MAX_PACK_ID;
@@ -1787,13 +1792,13 @@ static void read_mark_file(struct mark_set **s, FILE *f, mark_set_inserter_t ins
 
 		end = strchr(line, '\n');
 		if (line[0] != ':' || !end)
-			die("corrupt mark line: %s", line);
+			die(_("corrupt mark line: %s"), line);
 		*end = 0;
 		mark = strtoumax(line + 1, &end, 10);
 		if (!mark || end == line + 1
 			|| *end != ' '
 			|| get_oid_hex_any(end + 1, &oid) == GIT_HASH_UNKNOWN)
-			die("corrupt mark line: %s", line);
+			die(_("corrupt mark line: %s"), line);
 		inserter(s, &oid, mark);
 	}
 }
@@ -1806,7 +1811,7 @@ static void read_marks(void)
 	else if (import_marks_file_ignore_missing && errno == ENOENT)
 		goto done; /* Marks file does not exist */
 	else
-		die_errno("cannot read '%s'", import_marks_file);
+		die_errno(_("cannot read '%s'"), import_marks_file);
 	read_mark_file(&marks, f, insert_object_entry);
 	fclose(f);
 done:
@@ -1892,7 +1897,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
 	strbuf_reset(sb);
 
 	if (!skip_prefix(command_buf.buf, "data ", &data))
-		die("Expected 'data n' command, found: %s", command_buf.buf);
+		die(_("expected 'data n' command, found: %s"), command_buf.buf);
 
 	if (skip_prefix(data, "<<", &data)) {
 		char *term = xstrdup(data);
@@ -1900,7 +1905,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
 
 		for (;;) {
 			if (strbuf_getline_lf(&command_buf, stdin) == EOF)
-				die("EOF in data (terminator '%s' not found)", term);
+				die(_("EOF in data (terminator '%s' not found)"), term);
 			if (term_len == command_buf.len
 				&& !strcmp(term, command_buf.buf))
 				break;
@@ -1918,12 +1923,12 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
 			return 0;
 		}
 		if (length < len)
-			die("data is too large to use in this context");
+			die(_("data is too large to use in this context"));
 
 		while (n < length) {
 			size_t s = strbuf_fread(sb, length - n, stdin);
 			if (!s && feof(stdin))
-				die("EOF in data (%lu bytes remaining)",
+				die(_("EOF in data (%lu bytes remaining)"),
 					(unsigned long)(length - n));
 			n += s;
 		}
@@ -1980,15 +1985,15 @@ static char *parse_ident(const char *buf)
 
 	ltgt = buf + strcspn(buf, "<>");
 	if (*ltgt != '<')
-		die("Missing < in ident string: %s", buf);
+		die(_("missing < in ident string: %s"), buf);
 	if (ltgt != buf && ltgt[-1] != ' ')
-		die("Missing space before < in ident string: %s", buf);
+		die(_("missing space before < in ident string: %s"), buf);
 	ltgt = ltgt + 1 + strcspn(ltgt + 1, "<>");
 	if (*ltgt != '>')
-		die("Missing > in ident string: %s", buf);
+		die(_("missing > in ident string: %s"), buf);
 	ltgt++;
 	if (*ltgt != ' ')
-		die("Missing space after > in ident string: %s", buf);
+		die(_("missing space after > in ident string: %s"), buf);
 	ltgt++;
 	name_len = ltgt - buf;
 	strbuf_add(&ident, buf, name_len);
@@ -1996,19 +2001,19 @@ static char *parse_ident(const char *buf)
 	switch (whenspec) {
 	case WHENSPEC_RAW:
 		if (validate_raw_date(ltgt, &ident, 1) < 0)
-			die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
+			die(_("invalid raw date \"%s\" in ident: %s"), ltgt, buf);
 		break;
 	case WHENSPEC_RAW_PERMISSIVE:
 		if (validate_raw_date(ltgt, &ident, 0) < 0)
-			die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
+			die(_("invalid raw date \"%s\" in ident: %s"), ltgt, buf);
 		break;
 	case WHENSPEC_RFC2822:
 		if (parse_date(ltgt, &ident) < 0)
-			die("Invalid rfc2822 date \"%s\" in ident: %s", ltgt, buf);
+			die(_("invalid rfc2822 date \"%s\" in ident: %s"), ltgt, buf);
 		break;
 	case WHENSPEC_NOW:
 		if (strcmp("now", ltgt))
-			die("Date in ident must be 'now': %s", buf);
+			die(_("date in ident must be 'now': %s"), buf);
 		datestamp(&ident);
 		break;
 	}
@@ -2102,7 +2107,7 @@ static void construct_path_with_fanout(const char *hex_sha1,
 {
 	unsigned int i = 0, j = 0;
 	if (fanout >= the_hash_algo->rawsz)
-		die("Too large fanout (%u)", fanout);
+		die(_("too large fanout (%u)"), fanout);
 	while (fanout) {
 		path[i++] = hex_sha1[j++];
 		path[i++] = hex_sha1[j++];
@@ -2176,7 +2181,7 @@ static uintmax_t do_change_note_fanout(
 
 			/* Rename fullpath to realpath */
 			if (!tree_content_remove(orig_root, fullpath, &leaf, 0))
-				die("Failed to remove path %s", fullpath);
+				die(_("failed to remove path %s"), fullpath);
 			tree_content_set(orig_root, realpath,
 				&leaf.versions[1].oid,
 				leaf.versions[1].mode,
@@ -2249,7 +2254,7 @@ static uintmax_t parse_mark_ref(const char *p, char **endptr)
 	p++;
 	mark = strtoumax(p, endptr, 10);
 	if (*endptr == p)
-		die("No value after ':' in mark: %s", command_buf.buf);
+		die(_("no value after ':' in mark: %s"), command_buf.buf);
 	return mark;
 }
 
@@ -2264,7 +2269,7 @@ static uintmax_t parse_mark_ref_eol(const char *p)
 
 	mark = parse_mark_ref(p, &end);
 	if (*end != '\0')
-		die("Garbage after mark: %s", command_buf.buf);
+		die(_("garbage after mark: %s"), command_buf.buf);
 	return mark;
 }
 
@@ -2279,7 +2284,7 @@ static uintmax_t parse_mark_ref_space(const char **p)
 
 	mark = parse_mark_ref(*p, &end);
 	if (*end++ != ' ')
-		die("Missing space after mark: %s", command_buf.buf);
+		die(_("missing space after mark: %s"), command_buf.buf);
 	*p = end;
 	return mark;
 }
@@ -2295,9 +2300,9 @@ static void parse_path(struct strbuf *sb, const char *p, const char **endp,
 {
 	if (*p == '"') {
 		if (unquote_c_style(sb, p, endp))
-			die("Invalid %s: %s", field, command_buf.buf);
+			die(_("invalid %s: %s"), field, command_buf.buf);
 		if (strlen(sb->buf) != sb->len)
-			die("NUL in %s: %s", field, command_buf.buf);
+			die(_("NUL in %s: %s"), field, command_buf.buf);
 	} else {
 		/*
 		 * Unless we are parsing the last field of a line,
@@ -2320,7 +2325,7 @@ static void parse_path_eol(struct strbuf *sb, const char *p, const char *field)
 
 	parse_path(sb, p, &end, 1, field);
 	if (*end)
-		die("Garbage after %s: %s", field, command_buf.buf);
+		die(_("garbage after %s: %s"), field, command_buf.buf);
 }
 
 /*
@@ -2333,7 +2338,7 @@ static void parse_path_space(struct strbuf *sb, const char *p,
 {
 	parse_path(sb, p, endp, 0, field);
 	if (**endp != ' ')
-		die("Missing space after %s: %s", field, command_buf.buf);
+		die(_("missing space after %s: %s"), field, command_buf.buf);
 	(*endp)++;
 }
 
@@ -2346,7 +2351,7 @@ static void file_change_m(const char *p, struct branch *b)
 
 	p = parse_mode(p, &mode);
 	if (!p)
-		die("Corrupt mode: %s", command_buf.buf);
+		die(_("corrupt mode: %s"), command_buf.buf);
 	switch (mode) {
 	case 0644:
 	case 0755:
@@ -2359,7 +2364,7 @@ static void file_change_m(const char *p, struct branch *b)
 		/* ok */
 		break;
 	default:
-		die("Corrupt mode: %s", command_buf.buf);
+		die(_("corrupt mode: %s"), command_buf.buf);
 	}
 
 	if (*p == ':') {
@@ -2370,10 +2375,10 @@ static void file_change_m(const char *p, struct branch *b)
 		oe = NULL; /* not used with inline_data, but makes gcc happy */
 	} else {
 		if (parse_mapped_oid_hex(p, &oid, &p))
-			die("Invalid dataref: %s", command_buf.buf);
+			die(_("invalid dataref: %s"), command_buf.buf);
 		oe = find_object(&oid);
 		if (*p++ != ' ')
-			die("Missing space after SHA1: %s", command_buf.buf);
+			die(_("missing space after SHA1: %s"), command_buf.buf);
 	}
 
 	strbuf_reset(&path);
@@ -2389,11 +2394,11 @@ static void file_change_m(const char *p, struct branch *b)
 
 	if (S_ISGITLINK(mode)) {
 		if (inline_data)
-			die("Git links cannot be specified 'inline': %s",
+			die(_("Git links cannot be specified 'inline': %s"),
 				command_buf.buf);
 		else if (oe) {
 			if (oe->type != OBJ_COMMIT)
-				die("Not a commit (actually a %s): %s",
+				die(_("not a commit (actually a %s): %s"),
 					type_name(oe->type), command_buf.buf);
 		}
 		/*
@@ -2402,7 +2407,7 @@ static void file_change_m(const char *p, struct branch *b)
 		 */
 	} else if (inline_data) {
 		if (S_ISDIR(mode))
-			die("Directories cannot be specified 'inline': %s",
+			die(_("directories cannot be specified 'inline': %s"),
 				command_buf.buf);
 		while (read_next_command() != EOF) {
 			const char *v;
@@ -2420,11 +2425,11 @@ static void file_change_m(const char *p, struct branch *b)
 					odb_read_object_info(the_repository->objects,
 							     &oid, NULL);
 		if (type < 0)
-			die("%s not found: %s",
-					S_ISDIR(mode) ?  "Tree" : "Blob",
-					command_buf.buf);
+			die(_("%s not found: %s"),
+			    S_ISDIR(mode) ?  _("tree") : _("blob"),
+			    command_buf.buf);
 		if (type != expected)
-			die("Not a %s (actually a %s): %s",
+			die(_("not a %s (actually a %s): %s"),
 				type_name(expected), type_name(type),
 				command_buf.buf);
 	}
@@ -2435,7 +2440,7 @@ static void file_change_m(const char *p, struct branch *b)
 	}
 
 	if (!verify_path(path.buf, mode))
-		die("invalid path '%s'", path.buf);
+		die(_("invalid path '%s'"), path.buf);
 	tree_content_set(&b->branch_tree, path.buf, &oid, mode, NULL);
 }
 
@@ -2465,7 +2470,7 @@ static void file_change_cr(const char *p, struct branch *b, int rename)
 	else
 		tree_content_get(&b->branch_tree, source.buf, &leaf, 1);
 	if (!leaf.versions[1].mode)
-		die("Path %s not in branch", source.buf);
+		die(_("path %s not in branch"), source.buf);
 	if (!*dest.buf) {	/* C "path/to/subdir" "" */
 		tree_content_replace(&b->branch_tree,
 			&leaf.versions[1].oid,
@@ -2474,7 +2479,7 @@ static void file_change_cr(const char *p, struct branch *b, int rename)
 		return;
 	}
 	if (!verify_path(dest.buf, leaf.versions[1].mode))
-		die("invalid path '%s'", dest.buf);
+		die(_("invalid path '%s'"), dest.buf);
 	tree_content_set(&b->branch_tree, dest.buf,
 		&leaf.versions[1].oid,
 		leaf.versions[1].mode,
@@ -2516,23 +2521,23 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
 		oe = NULL; /* not used with inline_data, but makes gcc happy */
 	} else {
 		if (parse_mapped_oid_hex(p, &oid, &p))
-			die("Invalid dataref: %s", command_buf.buf);
+			die(_("invalid dataref: %s"), command_buf.buf);
 		oe = find_object(&oid);
 		if (*p++ != ' ')
-			die("Missing space after SHA1: %s", command_buf.buf);
+			die(_("missing space after SHA1: %s"), command_buf.buf);
 	}
 
 	/* <commit-ish> */
 	s = lookup_branch(p);
 	if (s) {
 		if (is_null_oid(&s->oid))
-			die("Can't add a note on empty branch.");
+			die(_("can't add a note on empty branch."));
 		oidcpy(&commit_oid, &s->oid);
 	} else if (*p == ':') {
 		uintmax_t commit_mark = parse_mark_ref_eol(p);
 		struct object_entry *commit_oe = find_mark(marks, commit_mark);
 		if (commit_oe->type != OBJ_COMMIT)
-			die("Mark :%" PRIuMAX " not a commit", commit_mark);
+			die(_("mark :%" PRIuMAX " not a commit"), commit_mark);
 		oidcpy(&commit_oid, &commit_oe->idx.oid);
 	} else if (!repo_get_oid(the_repository, p, &commit_oid)) {
 		unsigned long size;
@@ -2540,25 +2545,25 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
 						   &commit_oid, OBJ_COMMIT, &size,
 						   &commit_oid);
 		if (!buf || size < the_hash_algo->hexsz + 6)
-			die("Not a valid commit: %s", p);
+			die(_("not a valid commit: %s"), p);
 		free(buf);
 	} else
-		die("Invalid ref name or SHA1 expression: %s", p);
+		die(_("invalid ref name or SHA1 expression: %s"), p);
 
 	if (inline_data) {
 		read_next_command();
 		parse_and_store_blob(&last_blob, &oid, 0);
 	} else if (oe) {
 		if (oe->type != OBJ_BLOB)
-			die("Not a blob (actually a %s): %s",
+			die(_("not a blob (actually a %s): %s"),
 				type_name(oe->type), command_buf.buf);
 	} else if (!is_null_oid(&oid)) {
 		enum object_type type = odb_read_object_info(the_repository->objects, &oid,
 							NULL);
 		if (type < 0)
-			die("Blob not found: %s", command_buf.buf);
+			die(_("blob not found: %s"), command_buf.buf);
 		if (type != OBJ_BLOB)
-			die("Not a blob (actually a %s): %s",
+			die(_("not a blob (actually a %s): %s"),
 			    type_name(type), command_buf.buf);
 	}
 
@@ -2587,10 +2592,10 @@ static void file_change_deleteall(struct branch *b)
 static void parse_from_commit(struct branch *b, char *buf, unsigned long size)
 {
 	if (!buf || size < the_hash_algo->hexsz + 6)
-		die("Not a valid commit: %s", oid_to_hex(&b->oid));
+		die(_("not a valid commit: %s"), oid_to_hex(&b->oid));
 	if (memcmp("tree ", buf, 5)
 		|| get_oid_hex(buf + 5, &b->branch_tree.versions[1].oid))
-		die("The commit %s is corrupt", oid_to_hex(&b->oid));
+		die(_("the commit %s is corrupt"), oid_to_hex(&b->oid));
 	oidcpy(&b->branch_tree.versions[0].oid,
 	       &b->branch_tree.versions[1].oid);
 }
@@ -2620,7 +2625,7 @@ static int parse_objectish(struct branch *b, const char *objectish)
 
 	s = lookup_branch(objectish);
 	if (b == s)
-		die("Can't create a branch from itself: %s", b->name);
+		die(_("can't create a branch from itself: %s"), b->name);
 	else if (s) {
 		struct object_id *t = &s->branch_tree.versions[1].oid;
 		oidcpy(&b->oid, &s->oid);
@@ -2630,7 +2635,7 @@ static int parse_objectish(struct branch *b, const char *objectish)
 		uintmax_t idnum = parse_mark_ref_eol(objectish);
 		struct object_entry *oe = find_mark(marks, idnum);
 		if (oe->type != OBJ_COMMIT)
-			die("Mark :%" PRIuMAX " not a commit", idnum);
+			die(_("mark :%" PRIuMAX " not a commit"), idnum);
 		if (!oideq(&b->oid, &oe->idx.oid)) {
 			oidcpy(&b->oid, &oe->idx.oid);
 			if (oe->pack_id != MAX_PACK_ID) {
@@ -2647,7 +2652,7 @@ static int parse_objectish(struct branch *b, const char *objectish)
 			b->delete = 1;
 	}
 	else
-		die("Invalid ref name or SHA1 expression: %s", objectish);
+		die(_("invalid ref name or SHA1 expression: %s"), objectish);
 
 	if (b->branch_tree.tree && !oideq(&oid, &b->branch_tree.versions[1].oid)) {
 		release_tree_content_recursive(b->branch_tree.tree);
@@ -2694,7 +2699,7 @@ static struct hash_list *parse_merge(unsigned int *count)
 			uintmax_t idnum = parse_mark_ref_eol(from);
 			struct object_entry *oe = find_mark(marks, idnum);
 			if (oe->type != OBJ_COMMIT)
-				die("Mark :%" PRIuMAX " not a commit", idnum);
+				die(_("mark :%" PRIuMAX " not a commit"), idnum);
 			oidcpy(&n->oid, &oe->idx.oid);
 		} else if (!repo_get_oid(the_repository, from, &n->oid)) {
 			unsigned long size;
@@ -2702,10 +2707,10 @@ static struct hash_list *parse_merge(unsigned int *count)
 							   &n->oid, OBJ_COMMIT,
 							   &size, &n->oid);
 			if (!buf || size < the_hash_algo->hexsz + 6)
-				die("Not a valid commit: %s", from);
+				die(_("not a valid commit: %s"), from);
 			free(buf);
 		} else
-			die("Invalid ref name or SHA1 expression: %s", from);
+			die(_("invalid ref name or SHA1 expression: %s"), from);
 
 		n->next = NULL;
 		*tail = n;
@@ -2729,8 +2734,8 @@ static void parse_one_signature(struct signature_data *sig, const char *v)
 	char *space = strchr(args, ' ');
 
 	if (!space)
-		die("Expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', "
-		    "got 'gpgsig %s'", args);
+		die(_("expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', "
+		      "got 'gpgsig %s'"), args);
 	*space = '\0';
 
 	sig->hash_algo = args;
@@ -2739,19 +2744,28 @@ static void parse_one_signature(struct signature_data *sig, const char *v)
 	/* Validate hash algorithm */
 	if (strcmp(sig->hash_algo, "sha1") &&
 	    strcmp(sig->hash_algo, "sha256"))
-		die("Unknown git hash algorithm in gpgsig: '%s'", sig->hash_algo);
+		die(_("unknown git hash algorithm in gpgsig: '%s'"), sig->hash_algo);
 
 	/* Validate signature format */
 	if (!valid_signature_format(sig->sig_format))
-		die("Invalid signature format in gpgsig: '%s'", sig->sig_format);
+		die(_("invalid signature format in gpgsig: '%s'"), sig->sig_format);
 	if (!strcmp(sig->sig_format, "unknown"))
-		warning("'unknown' signature format in gpgsig");
+		warning(_("'unknown' signature format in gpgsig"));
 
 	/* Read signature data */
 	read_next_command();
 	parse_data(&sig->data, 0, NULL);
 }
 
+static void discard_one_signature(void)
+{
+	struct strbuf data = STRBUF_INIT;
+
+	read_next_command();
+	parse_data(&data, 0, NULL);
+	strbuf_release(&data);
+}
+
 static void add_gpgsig_to_commit(struct strbuf *commit_data,
 				 const char *header,
 				 struct signature_data *sig)
@@ -2775,8 +2789,8 @@ static void store_signature(struct signature_data *stored_sig,
 			    const char *hash_type)
 {
 	if (stored_sig->hash_algo) {
-		warning("multiple %s signatures found, "
-			"ignoring additional signature",
+		warning(_("multiple %s signatures found, "
+			  "ignoring additional signature"),
 			hash_type);
 		strbuf_release(&new_sig->data);
 		free(new_sig->hash_algo);
@@ -2785,6 +2799,22 @@ static void store_signature(struct signature_data *stored_sig,
 	}
 }
 
+static void import_one_signature(struct signature_data *sig_sha1,
+				 struct signature_data *sig_sha256,
+				 const char *v)
+{
+	struct signature_data sig = { NULL, NULL, STRBUF_INIT };
+
+	parse_one_signature(&sig, v);
+
+	if (!strcmp(sig.hash_algo, "sha1"))
+		store_signature(sig_sha1, &sig, "SHA-1");
+	else if (!strcmp(sig.hash_algo, "sha256"))
+		store_signature(sig_sha256, &sig, "SHA-256");
+	else
+		die(_("parse_one_signature() returned unknown hash algo"));
+}
+
 static void parse_new_commit(const char *arg)
 {
 	static struct strbuf msg = STRBUF_INIT;
@@ -2815,21 +2845,34 @@ static void parse_new_commit(const char *arg)
 		read_next_command();
 	}
 	if (!committer)
-		die("Expected committer but didn't get one");
+		die(_("expected committer but didn't get one"));
 
-	/* Process signatures (up to 2: one "sha1" and one "sha256") */
 	while (skip_prefix(command_buf.buf, "gpgsig ", &v)) {
-		struct signature_data sig = { NULL, NULL, STRBUF_INIT };
+		switch (signed_commit_mode) {
 
-		parse_one_signature(&sig, v);
+		/* First, modes that don't need the signature to be parsed */
+		case SIGN_ABORT:
+			die(_("encountered signed commit; use "
+			      "--signed-commits=<mode> to handle it"));
+		case SIGN_WARN_STRIP:
+			warning(_("stripping a commit signature"));
+			/* fallthru */
+		case SIGN_STRIP:
+			discard_one_signature();
+			break;
 
-		if (!strcmp(sig.hash_algo, "sha1"))
-			store_signature(&sig_sha1, &sig, "SHA-1");
-		else if (!strcmp(sig.hash_algo, "sha256"))
-			store_signature(&sig_sha256, &sig, "SHA-256");
-		else
-			BUG("parse_one_signature() returned unknown hash algo");
+		/* Second, modes that parse the signature */
+		case SIGN_WARN_VERBATIM:
+			warning(_("importing a commit signature verbatim"));
+			/* fallthru */
+		case SIGN_VERBATIM:
+			import_one_signature(&sig_sha1, &sig_sha256, v);
+			break;
 
+		/* Third, BUG */
+		default:
+			BUG("invalid signed_commit_mode value %d", signed_commit_mode);
+		}
 		read_next_command();
 	}
 
@@ -2921,6 +2964,43 @@ static void parse_new_commit(const char *arg)
 	b->last_commit = object_count_by_type[OBJ_COMMIT];
 }
 
+static void handle_tag_signature(struct strbuf *msg, const char *name)
+{
+	size_t sig_offset = parse_signed_buffer(msg->buf, msg->len);
+
+	/* If there is no signature, there is nothing to do. */
+	if (sig_offset >= msg->len)
+		return;
+
+	switch (signed_tag_mode) {
+
+	/* First, modes that don't change anything */
+	case SIGN_ABORT:
+		die(_("encountered signed tag; use "
+		      "--signed-tags=<mode> to handle it"));
+	case SIGN_WARN_VERBATIM:
+		warning(_("importing a tag signature verbatim for tag '%s'"), name);
+		/* fallthru */
+	case SIGN_VERBATIM:
+		/* Nothing to do, the signature will be put into the imported tag. */
+		break;
+
+	/* Second, modes that remove the signature */
+	case SIGN_WARN_STRIP:
+		warning(_("stripping a tag signature for tag '%s'"), name);
+		/* fallthru */
+	case SIGN_STRIP:
+		/* Truncate the buffer to remove the signature */
+		strbuf_setlen(msg, sig_offset);
+		break;
+
+	/* Third, BUG */
+	default:
+		BUG("invalid signed_tag_mode value %d from tag '%s'",
+		    signed_tag_mode, name);
+	}
+}
+
 static void parse_new_tag(const char *arg)
 {
 	static struct strbuf msg = STRBUF_INIT;
@@ -2945,11 +3025,11 @@ static void parse_new_tag(const char *arg)
 
 	/* from ... */
 	if (!skip_prefix(command_buf.buf, "from ", &from))
-		die("Expected from command, got %s", command_buf.buf);
+		die(_("expected 'from' command, got '%s'"), command_buf.buf);
 	s = lookup_branch(from);
 	if (s) {
 		if (is_null_oid(&s->oid))
-			die("Can't tag an empty branch.");
+			die(_("can't tag an empty branch."));
 		oidcpy(&oid, &s->oid);
 		type = OBJ_COMMIT;
 	} else if (*from == ':') {
@@ -2964,11 +3044,11 @@ static void parse_new_tag(const char *arg)
 			type = odb_read_object_info(the_repository->objects,
 						    &oid, NULL);
 			if (type < 0)
-				die("Not a valid object: %s", from);
+				die(_("not a valid object: %s"), from);
 		} else
 			type = oe->type;
 	} else
-		die("Invalid ref name or SHA1 expression: %s", from);
+		die(_("invalid ref name or SHA1 expression: %s"), from);
 	read_next_command();
 
 	/* original-oid ... */
@@ -2984,6 +3064,8 @@ static void parse_new_tag(const char *arg)
 	/* tag payload/message */
 	parse_data(&msg, 0, NULL);
 
+	handle_tag_signature(&msg, t->name);
+
 	/* build the tag object */
 	strbuf_reset(&new_data);
 
@@ -3057,7 +3139,7 @@ static void parse_reset_branch(const char *arg)
 static void cat_blob_write(const char *buf, unsigned long size)
 {
 	if (write_in_full(cat_blob_fd, buf, size) < 0)
-		die_errno("Write to frontend failed");
+		die_errno(_("write to frontend failed"));
 }
 
 static void cat_blob(struct object_entry *oe, struct object_id *oid)
@@ -3086,9 +3168,9 @@ static void cat_blob(struct object_entry *oe, struct object_id *oid)
 		return;
 	}
 	if (!buf)
-		die("Can't read object %s", oid_to_hex(oid));
+		die(_("can't read object %s"), oid_to_hex(oid));
 	if (type != OBJ_BLOB)
-		die("Object %s is a %s but a blob was expected.",
+		die(_("object %s is a %s but a blob was expected."),
 		    oid_to_hex(oid), type_name(type));
 	strbuf_reset(&line);
 	strbuf_addf(&line, "%s %s %"PRIuMAX"\n", oid_to_hex(oid),
@@ -3112,11 +3194,11 @@ static void parse_get_mark(const char *p)
 
 	/* get-mark SP <object> LF */
 	if (*p != ':')
-		die("Not a mark: %s", p);
+		die(_("not a mark: %s"), p);
 
 	oe = find_mark(marks, parse_mark_ref_eol(p));
 	if (!oe)
-		die("Unknown mark: %s", command_buf.buf);
+		die(_("unknown mark: %s"), command_buf.buf);
 
 	xsnprintf(output, sizeof(output), "%s\n", oid_to_hex(&oe->idx.oid));
 	cat_blob_write(output, the_hash_algo->hexsz + 1);
@@ -3131,13 +3213,13 @@ static void parse_cat_blob(const char *p)
 	if (*p == ':') {
 		oe = find_mark(marks, parse_mark_ref_eol(p));
 		if (!oe)
-			die("Unknown mark: %s", command_buf.buf);
+			die(_("unknown mark: %s"), command_buf.buf);
 		oidcpy(&oid, &oe->idx.oid);
 	} else {
 		if (parse_mapped_oid_hex(p, &oid, &p))
-			die("Invalid dataref: %s", command_buf.buf);
+			die(_("invalid dataref: %s"), command_buf.buf);
 		if (*p)
-			die("Garbage after SHA1: %s", command_buf.buf);
+			die(_("garbage after SHA1: %s"), command_buf.buf);
 		oe = find_object(&oid);
 	}
 
@@ -3155,7 +3237,7 @@ static struct object_entry *dereference(struct object_entry *oe,
 		enum object_type type = odb_read_object_info(the_repository->objects,
 							     oid, NULL);
 		if (type < 0)
-			die("object not found: %s", oid_to_hex(oid));
+			die(_("object not found: %s"), oid_to_hex(oid));
 		/* cache it! */
 		oe = insert_object(oid);
 		oe->type = type;
@@ -3169,7 +3251,7 @@ static struct object_entry *dereference(struct object_entry *oe,
 	case OBJ_TAG:
 		break;
 	default:
-		die("Not a tree-ish: %s", command_buf.buf);
+		die(_("not a tree-ish: %s"), command_buf.buf);
 	}
 
 	if (oe->pack_id != MAX_PACK_ID) {	/* in a pack being written */
@@ -3180,19 +3262,19 @@ static struct object_entry *dereference(struct object_entry *oe,
 				      &unused, &size);
 	}
 	if (!buf)
-		die("Can't load object %s", oid_to_hex(oid));
+		die(_("can't load object %s"), oid_to_hex(oid));
 
 	/* Peel one layer. */
 	switch (oe->type) {
 	case OBJ_TAG:
 		if (size < hexsz + strlen("object ") ||
 		    get_oid_hex(buf + strlen("object "), oid))
-			die("Invalid SHA1 in tag: %s", command_buf.buf);
+			die(_("invalid SHA1 in tag: %s"), command_buf.buf);
 		break;
 	case OBJ_COMMIT:
 		if (size < hexsz + strlen("tree ") ||
 		    get_oid_hex(buf + strlen("tree "), oid))
-			die("Invalid SHA1 in commit: %s", command_buf.buf);
+			die(_("invalid SHA1 in commit: %s"), command_buf.buf);
 	}
 
 	free(buf);
@@ -3227,9 +3309,9 @@ static void build_mark_map(struct string_list *from, struct string_list *to)
 	for_each_string_list_item(fromp, from) {
 		top = string_list_lookup(to, fromp->string);
 		if (!fromp->util) {
-			die(_("Missing from marks for submodule '%s'"), fromp->string);
+			die(_("missing from marks for submodule '%s'"), fromp->string);
 		} else if (!top || !top->util) {
-			die(_("Missing to marks for submodule '%s'"), fromp->string);
+			die(_("missing to marks for submodule '%s'"), fromp->string);
 		}
 		build_mark_map_one(fromp->util, top->util);
 	}
@@ -3243,14 +3325,14 @@ static struct object_entry *parse_treeish_dataref(const char **p)
 	if (**p == ':') {	/* <mark> */
 		e = find_mark(marks, parse_mark_ref_space(p));
 		if (!e)
-			die("Unknown mark: %s", command_buf.buf);
+			die(_("unknown mark: %s"), command_buf.buf);
 		oidcpy(&oid, &e->idx.oid);
 	} else {	/* <sha1> */
 		if (parse_mapped_oid_hex(*p, &oid, p))
-			die("Invalid dataref: %s", command_buf.buf);
+			die(_("invalid dataref: %s"), command_buf.buf);
 		e = find_object(&oid);
 		if (*(*p)++ != ' ')
-			die("Missing space after tree-ish: %s", command_buf.buf);
+			die(_("missing space after tree-ish: %s"), command_buf.buf);
 	}
 
 	while (!e || e->type != OBJ_TREE)
@@ -3294,7 +3376,7 @@ static void parse_ls(const char *p, struct branch *b)
 	/* ls SP (<tree-ish> SP)? <path> */
 	if (*p == '"') {
 		if (!b)
-			die("Not in a commit: %s", command_buf.buf);
+			die(_("not in a commit: %s"), command_buf.buf);
 		root = &b->branch_tree;
 	} else {
 		struct object_entry *e = parse_treeish_dataref(&p);
@@ -3357,12 +3439,12 @@ static void parse_alias(void)
 	/* mark ... */
 	parse_mark();
 	if (!next_mark)
-		die(_("Expected 'mark' command, got %s"), command_buf.buf);
+		die(_("expected 'mark' command, got %s"), command_buf.buf);
 
 	/* to ... */
 	memset(&b, 0, sizeof(b));
 	if (!parse_objectish_with_prefix(&b, "to "))
-		die(_("Expected 'to' command, got %s"), command_buf.buf);
+		die(_("expected 'to' command, got %s"), command_buf.buf);
 	e = find_object(&b.oid);
 	assert(e);
 	insert_mark(&marks, next_mark, e);
@@ -3380,7 +3462,7 @@ static void option_import_marks(const char *marks,
 {
 	if (import_marks_file) {
 		if (from_stream)
-			die("Only one import-marks command allowed per stream");
+			die(_("only one import-marks command allowed per stream"));
 
 		/* read previous mark file */
 		if(!import_marks_file_from_stream)
@@ -3404,7 +3486,7 @@ static void option_date_format(const char *fmt)
 	else if (!strcmp(fmt, "now"))
 		whenspec = WHENSPEC_NOW;
 	else
-		die("unknown --date-format argument %s", fmt);
+		die(_("unknown --date-format argument %s"), fmt);
 }
 
 static unsigned long ulong_arg(const char *option, const char *arg)
@@ -3412,7 +3494,7 @@ static unsigned long ulong_arg(const char *option, const char *arg)
 	char *endptr;
 	unsigned long rv = strtoul(arg, &endptr, 0);
 	if (strchr(arg, '-') || endptr == arg || *endptr)
-		die("%s: argument must be a non-negative integer", option);
+		die(_("%s: argument must be a non-negative integer"), option);
 	return rv;
 }
 
@@ -3420,7 +3502,7 @@ static void option_depth(const char *depth)
 {
 	max_depth = ulong_arg("--depth", depth);
 	if (max_depth > MAX_DEPTH)
-		die("--depth cannot exceed %u", MAX_DEPTH);
+		die(_("--depth cannot exceed %u"), MAX_DEPTH);
 }
 
 static void option_active_branches(const char *branches)
@@ -3438,7 +3520,7 @@ static void option_cat_blob_fd(const char *fd)
 {
 	unsigned long n = ulong_arg("--cat-blob-fd", fd);
 	if (n > (unsigned long) INT_MAX)
-		die("--cat-blob-fd cannot exceed %d", INT_MAX);
+		die(_("--cat-blob-fd cannot exceed %d"), INT_MAX);
 	cat_blob_fd = (int) n;
 }
 
@@ -3458,7 +3540,7 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list)
 	char *s = xstrdup(arg);
 	char *f = strchr(s, ':');
 	if (!f)
-		die(_("Expected format name:filename for submodule rewrite option"));
+		die(_("expected format name:filename for submodule rewrite option"));
 	*f = '\0';
 	f++;
 	CALLOC_ARRAY(ms, 1);
@@ -3466,7 +3548,7 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list)
 	f = prefix_filename(global_prefix, f);
 	fp = fopen(f, "r");
 	if (!fp)
-		die_errno("cannot read '%s'", f);
+		die_errno(_("cannot read '%s'"), f);
 	read_mark_file(&ms, fp, insert_oid_entry);
 	fclose(fp);
 	free(f);
@@ -3483,10 +3565,10 @@ static int parse_one_option(const char *option)
 		if (!git_parse_ulong(option, &v))
 			return 0;
 		if (v < 8192) {
-			warning("max-pack-size is now in bytes, assuming --max-pack-size=%lum", v);
+			warning(_("max-pack-size is now in bytes, assuming --max-pack-size=%lum"), v);
 			v *= 1024 * 1024;
 		} else if (v < 1024 * 1024) {
-			warning("minimum max-pack-size is 1 MiB");
+			warning(_("minimum max-pack-size is 1 MiB"));
 			v = 1024 * 1024;
 		}
 		max_packsize = v;
@@ -3501,6 +3583,12 @@ static int parse_one_option(const char *option)
 		option_active_branches(option);
 	} else if (skip_prefix(option, "export-pack-edges=", &option)) {
 		option_export_pack_edges(option);
+	} else if (skip_prefix(option, "signed-commits=", &option)) {
+		if (parse_sign_mode(option, &signed_commit_mode))
+			usagef(_("unknown --signed-commits mode '%s'"), option);
+	} else if (skip_prefix(option, "signed-tags=", &option)) {
+		if (parse_sign_mode(option, &signed_tag_mode))
+			usagef(_("unknown --signed-tags mode '%s'"), option);
 	} else if (!strcmp(option, "quiet")) {
 		show_stats = 0;
 		quiet = 1;
@@ -3567,23 +3655,23 @@ static int parse_one_feature(const char *feature, int from_stream)
 static void parse_feature(const char *feature)
 {
 	if (seen_data_command)
-		die("Got feature command '%s' after data command", feature);
+		die(_("got feature command '%s' after data command"), feature);
 
 	if (parse_one_feature(feature, 1))
 		return;
 
-	die("This version of fast-import does not support feature %s.", feature);
+	die(_("this version of fast-import does not support feature %s."), feature);
 }
 
 static void parse_option(const char *option)
 {
 	if (seen_data_command)
-		die("Got option command '%s' after data command", option);
+		die(_("got option command '%s' after data command"), option);
 
 	if (parse_one_option(option))
 		return;
 
-	die("This version of fast-import does not support option: %s", option);
+	die(_("this version of fast-import does not support option: %s"), option);
 }
 
 static void git_pack_config(void)
@@ -3627,7 +3715,7 @@ static void parse_argv(void)
 			break;
 
 		if (!skip_prefix(a, "--", &a))
-			die("unknown option %s", a);
+			die(_("unknown option %s"), a);
 
 		if (parse_one_option(a))
 			continue;
@@ -3640,7 +3728,7 @@ static void parse_argv(void)
 			continue;
 		}
 
-		die("unknown option --%s", a);
+		die(_("unknown option --%s"), a);
 	}
 	if (i != global_argc)
 		usage(fast_import_usage);
@@ -3729,7 +3817,7 @@ int cmd_fast_import(int argc,
 		else if (starts_with(command_buf.buf, "option "))
 			/* ignore non-git options*/;
 		else
-			die("Unsupported command: %s", command_buf.buf);
+			die(_("unsupported command: %s"), command_buf.buf);
 
 		if (checkpoint_requested)
 			checkpoint();
@@ -3740,7 +3828,7 @@ int cmd_fast_import(int argc,
 		parse_argv();
 
 	if (require_explicit_termination && feof(stdin))
-		die("stream ends early");
+		die(_("stream ends early"));
 
 	end_packfile();
 
diff --git a/builtin/fetch.c b/builtin/fetch.c
index c7ff348..7052e6f 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -289,13 +289,11 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
 	return ent;
 }
 
-static int add_one_refname(const char *refname, const char *referent UNUSED,
-			   const struct object_id *oid,
-			   int flag UNUSED, void *cbdata)
+static int add_one_refname(const struct reference *ref, void *cbdata)
 {
 	struct hashmap *refname_map = cbdata;
 
-	(void) refname_hash_add(refname_map, refname, oid);
+	(void) refname_hash_add(refname_map, ref->name, ref->oid);
 	return 0;
 }
 
@@ -1416,14 +1414,11 @@ static void set_option(struct transport *transport, const char *name, const char
 }
 
 
-static int add_oid(const char *refname UNUSED,
-		   const char *referent UNUSED,
-		   const struct object_id *oid,
-		   int flags UNUSED, void *cb_data)
+static int add_oid(const struct reference *ref, void *cb_data)
 {
 	struct oid_array *oids = cb_data;
 
-	oid_array_append(oids, oid);
+	oid_array_append(oids, ref->oid);
 	return 0;
 }
 
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index edb93c0..cf4273a 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
 #include "builtin.h"
 #include "config.h"
 #include "fmt-merge-msg.h"
@@ -13,12 +12,13 @@ static const char * const fmt_merge_msg_usage[] = {
 int cmd_fmt_merge_msg(int argc,
 		      const char **argv,
 		      const char *prefix,
-		      struct repository *repo UNUSED)
+		      struct repository *repo)
 {
 	char *inpath = NULL;
 	const char *message = NULL;
 	char *into_name = NULL;
 	int shortlog_len = -1;
+	int merge_log_config = -1;
 	struct option options[] = {
 		{
 			.type = OPTION_INTEGER,
@@ -53,7 +53,7 @@ int cmd_fmt_merge_msg(int argc,
 	int ret;
 	struct fmt_merge_msg_opts opts;
 
-	repo_config(the_repository, fmt_merge_msg_config, NULL);
+	repo_config(repo, fmt_merge_msg_config, &merge_log_config);
 	argc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,
 			     0);
 	if (argc > 0)
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 222637a..4a2fc42 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -2,6 +2,7 @@
 #include "commit.h"
 #include "config.h"
 #include "environment.h"
+#include "for-each-ref.h"
 #include "gettext.h"
 #include "object.h"
 #include "parse-options.h"
@@ -9,19 +10,7 @@
 #include "strbuf.h"
 #include "strvec.h"
 
-static char const * const for_each_ref_usage[] = {
-	N_("git for-each-ref [<options>] [<pattern>]"),
-	N_("git for-each-ref [--points-at <object>]"),
-	N_("git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"),
-	N_("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"),
-	N_("git for-each-ref [--start-after <marker>]"),
-	NULL
-};
-
-int cmd_for_each_ref(int argc,
-		     const char **argv,
-		     const char *prefix,
-		     struct repository *repo)
+int for_each_ref_core(int argc, const char **argv, const char *prefix, struct repository *repo, const char *const *usage)
 {
 	struct ref_sorting *sorting;
 	struct string_list sorting_options = STRING_LIST_INIT_DUP;
@@ -70,17 +59,17 @@ int cmd_for_each_ref(int argc,
 	/* Set default (refname) sorting */
 	string_list_append(&sorting_options, "refname");
 
-	parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
+	parse_options(argc, argv, prefix, opts, usage, 0);
 	if (format.array_opts.max_count < 0) {
 		error("invalid --count argument: `%d'", format.array_opts.max_count);
-		usage_with_options(for_each_ref_usage, opts);
+		usage_with_options(usage, opts);
 	}
 	if (HAS_MULTI_BITS(format.quote_style)) {
 		error("more than one quoting style?");
-		usage_with_options(for_each_ref_usage, opts);
+		usage_with_options(usage, opts);
 	}
 	if (verify_ref_format(&format))
-		usage_with_options(for_each_ref_usage, opts);
+		usage_with_options(usage, opts);
 
 	if (filter.start_after && sorting_options.nr > 1)
 		die(_("cannot use --start-after with custom sort options"));
@@ -120,3 +109,16 @@ int cmd_for_each_ref(int argc,
 	strvec_clear(&vec);
 	return 0;
 }
+
+int cmd_for_each_ref(int argc,
+		     const char **argv,
+		     const char *prefix,
+		     struct repository *repo)
+{
+	static char const * const for_each_ref_usage[] = {
+		N_("git for-each-ref " COMMON_USAGE_FOR_EACH_REF),
+		NULL
+	};
+
+	return for_each_ref_core(argc, argv, prefix, repo, for_each_ref_usage);
+}
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 543a2cd..c489582 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -503,13 +503,12 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
 	}
 }
 
-static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid,
+static int fsck_handle_reflog_ent(const char *refname,
+				  struct object_id *ooid, struct object_id *noid,
 				  const char *email UNUSED,
 				  timestamp_t timestamp, int tz UNUSED,
-				  const char *message UNUSED, void *cb_data)
+				  const char *message UNUSED, void *cb_data UNUSED)
 {
-	const char *refname = cb_data;
-
 	if (verbose)
 		fprintf_ln(stderr, _("Checking reflog %s->%s"),
 			   oid_to_hex(ooid), oid_to_hex(noid));
@@ -526,19 +525,18 @@ static int fsck_handle_reflog(const char *logname, void *cb_data)
 	strbuf_worktree_ref(cb_data, &refname, logname);
 	refs_for_each_reflog_ent(get_main_ref_store(the_repository),
 				 refname.buf, fsck_handle_reflog_ent,
-				 refname.buf);
+				 NULL);
 	strbuf_release(&refname);
 	return 0;
 }
 
-static int fsck_handle_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			   int flag UNUSED, void *cb_data UNUSED)
+static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)
 {
 	struct object *obj;
 
-	obj = parse_object(the_repository, oid);
+	obj = parse_object(the_repository, ref->oid);
 	if (!obj) {
-		if (is_promisor_object(the_repository, oid)) {
+		if (is_promisor_object(the_repository, ref->oid)) {
 			/*
 			 * Increment default_refs anyway, because this is a
 			 * valid ref.
@@ -547,19 +545,19 @@ static int fsck_handle_ref(const char *refname, const char *referent UNUSED, con
 			 return 0;
 		}
 		error(_("%s: invalid sha1 pointer %s"),
-		      refname, oid_to_hex(oid));
+		      ref->name, oid_to_hex(ref->oid));
 		errors_found |= ERROR_REACHABLE;
 		/* We'll continue with the rest despite the error.. */
 		return 0;
 	}
-	if (obj->type != OBJ_COMMIT && is_branch(refname)) {
-		error(_("%s: not a commit"), refname);
+	if (obj->type != OBJ_COMMIT && is_branch(ref->name)) {
+		error(_("%s: not a commit"), ref->name);
 		errors_found |= ERROR_REFS;
 	}
 	default_refs++;
 	obj->flags |= USED;
 	fsck_put_object_name(&fsck_walk_options,
-			     oid, "%s", refname);
+			     ref->oid, "%s", ref->name);
 	mark_object_reachable(obj);
 
 	return 0;
@@ -581,13 +579,19 @@ static void get_default_heads(void)
 	worktrees = get_worktrees();
 	for (p = worktrees; *p; p++) {
 		struct worktree *wt = *p;
-		struct strbuf ref = STRBUF_INIT;
+		struct strbuf refname = STRBUF_INIT;
 
-		strbuf_worktree_ref(wt, &ref, "HEAD");
-		fsck_head_link(ref.buf, &head_points_at, &head_oid);
-		if (head_points_at && !is_null_oid(&head_oid))
-			fsck_handle_ref(ref.buf, NULL, &head_oid, 0, NULL);
-		strbuf_release(&ref);
+		strbuf_worktree_ref(wt, &refname, "HEAD");
+		fsck_head_link(refname.buf, &head_points_at, &head_oid);
+		if (head_points_at && !is_null_oid(&head_oid)) {
+			struct reference ref = {
+				.name = refname.buf,
+				.oid = &head_oid,
+			};
+
+			fsck_handle_ref(&ref, NULL);
+		}
+		strbuf_release(&refname);
 
 		if (include_reflogs)
 			refs_for_each_reflog(get_worktree_ref_store(wt),
@@ -869,18 +873,19 @@ static int mark_packed_for_connectivity(const struct object_id *oid,
 static int check_pack_rev_indexes(struct repository *r, int show_progress)
 {
 	struct progress *progress = NULL;
+	struct packed_git *p;
 	uint32_t pack_count = 0;
 	int res = 0;
 
 	if (show_progress) {
-		for (struct packed_git *p = get_all_packs(r); p; p = p->next)
+		repo_for_each_pack(r, p)
 			pack_count++;
 		progress = start_delayed_progress(the_repository,
 						  "Verifying reverse pack-indexes", pack_count);
 		pack_count = 0;
 	}
 
-	for (struct packed_git *p = get_all_packs(r); p; p = p->next) {
+	repo_for_each_pack(r, p) {
 		int load_error = load_pack_revindex_from_disk(p);
 
 		if (load_error < 0) {
@@ -1010,8 +1015,7 @@ int cmd_fsck(int argc,
 			struct progress *progress = NULL;
 
 			if (show_progress) {
-				for (p = get_all_packs(the_repository); p;
-				     p = p->next) {
+				repo_for_each_pack(the_repository, p) {
 					if (open_pack_index(p))
 						continue;
 					total += p->num_objects;
@@ -1020,8 +1024,8 @@ int cmd_fsck(int argc,
 				progress = start_progress(the_repository,
 							  _("Checking objects"), total);
 			}
-			for (p = get_all_packs(the_repository); p;
-			     p = p->next) {
+
+			repo_for_each_pack(the_repository, p) {
 				/* verify gives error messages itself */
 				if (verify_pack(the_repository,
 						p, fsck_obj_buffer,
diff --git a/builtin/gc.c b/builtin/gc.c
index 0edd94a..e9a7624 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -34,7 +34,9 @@
 #include "pack-objects.h"
 #include "path.h"
 #include "reflog.h"
+#include "repack.h"
 #include "rerere.h"
+#include "revision.h"
 #include "blob.h"
 #include "tree.h"
 #include "promisor-remote.h"
@@ -55,7 +57,6 @@ static const char * const builtin_gc_usage[] = {
 };
 
 static timestamp_t gc_log_expire_time;
-static struct strvec repack = STRVEC_INIT;
 static struct tempfile *pidfile;
 static struct lock_file log_lock;
 static struct string_list pack_garbage = STRING_LIST_INIT_DUP;
@@ -255,6 +256,7 @@ enum maintenance_task_label {
 	TASK_PREFETCH,
 	TASK_LOOSE_OBJECTS,
 	TASK_INCREMENTAL_REPACK,
+	TASK_GEOMETRIC_REPACK,
 	TASK_GC,
 	TASK_COMMIT_GRAPH,
 	TASK_PACK_REFS,
@@ -285,12 +287,26 @@ static void maintenance_run_opts_release(struct maintenance_run_opts *opts)
 
 static int pack_refs_condition(UNUSED struct gc_config *cfg)
 {
-	/*
-	 * The auto-repacking logic for refs is handled by the ref backends and
-	 * exposed via `git pack-refs --auto`. We thus always return truish
-	 * here and let the backend decide for us.
-	 */
-	return 1;
+	struct string_list included_refs = STRING_LIST_INIT_NODUP;
+	struct ref_exclusions excludes = REF_EXCLUSIONS_INIT;
+	struct refs_optimize_opts optimize_opts = {
+		.exclusions = &excludes,
+		.includes = &included_refs,
+		.flags = REFS_OPTIMIZE_PRUNE | REFS_OPTIMIZE_AUTO,
+	};
+	bool required;
+
+	/* Check for all refs, similar to 'git refs optimize --all'. */
+	string_list_append(optimize_opts.includes, "*");
+
+	if (refs_optimize_required(get_main_ref_store(the_repository),
+				   &optimize_opts, &required))
+		return 0;
+
+	clear_ref_exclusions(&excludes);
+	string_list_clear(&included_refs, 0);
+
+	return required;
 }
 
 static int maintenance_task_pack_refs(struct maintenance_run_opts *opts,
@@ -312,7 +328,8 @@ struct count_reflog_entries_data {
 	size_t limit;
 };
 
-static int count_reflog_entries(struct object_id *old_oid, struct object_id *new_oid,
+static int count_reflog_entries(const char *refname UNUSED,
+				struct object_id *old_oid, struct object_id *new_oid,
 				const char *committer, timestamp_t timestamp,
 				int tz, const char *msg, void *cb_data)
 {
@@ -447,7 +464,7 @@ static int rerere_gc_condition(struct gc_config *cfg UNUSED)
 	return should_gc;
 }
 
-static int too_many_loose_objects(struct gc_config *cfg)
+static int too_many_loose_objects(int limit)
 {
 	/*
 	 * Quickly check if a "gc" is needed, by estimating how
@@ -469,7 +486,7 @@ static int too_many_loose_objects(struct gc_config *cfg)
 	if (!dir)
 		return 0;
 
-	auto_threshold = DIV_ROUND_UP(cfg->gc_auto_threshold, 256);
+	auto_threshold = DIV_ROUND_UP(limit, 256);
 	while ((ent = readdir(dir)) != NULL) {
 		if (strspn(ent->d_name, "0123456789abcdef") != hexsz_loose ||
 		    ent->d_name[hexsz_loose] != '\0')
@@ -488,7 +505,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) {
+	repo_for_each_pack(the_repository, p) {
 		if (!p->pack_local || p->is_cruft)
 			continue;
 		if (limit) {
@@ -508,12 +525,12 @@ static struct packed_git *find_base_packs(struct string_list *packs,
 static int too_many_packs(struct gc_config *cfg)
 {
 	struct packed_git *p;
-	int cnt;
+	int cnt = 0;
 
 	if (cfg->gc_auto_pack_limit <= 0)
 		return 0;
 
-	for (cnt = 0, p = get_all_packs(the_repository); p; p = p->next) {
+	repo_for_each_pack(the_repository, p) {
 		if (!p->pack_local)
 			continue;
 		if (p->pack_keep)
@@ -615,48 +632,50 @@ static uint64_t estimate_repack_memory(struct gc_config *cfg,
 	return os_cache + heap;
 }
 
-static int keep_one_pack(struct string_list_item *item, void *data UNUSED)
+static int keep_one_pack(struct string_list_item *item, void *data)
 {
-	strvec_pushf(&repack, "--keep-pack=%s", basename(item->string));
+	struct strvec *args = data;
+	strvec_pushf(args, "--keep-pack=%s", basename(item->string));
 	return 0;
 }
 
 static void add_repack_all_option(struct gc_config *cfg,
-				  struct string_list *keep_pack)
+				  struct string_list *keep_pack,
+				  struct strvec *args)
 {
 	if (cfg->prune_expire && !strcmp(cfg->prune_expire, "now")
 		&& !(cfg->cruft_packs && cfg->repack_expire_to))
-		strvec_push(&repack, "-a");
+		strvec_push(args, "-a");
 	else if (cfg->cruft_packs) {
-		strvec_push(&repack, "--cruft");
+		strvec_push(args, "--cruft");
 		if (cfg->prune_expire)
-			strvec_pushf(&repack, "--cruft-expiration=%s", cfg->prune_expire);
+			strvec_pushf(args, "--cruft-expiration=%s", cfg->prune_expire);
 		if (cfg->max_cruft_size)
-			strvec_pushf(&repack, "--max-cruft-size=%lu",
+			strvec_pushf(args, "--max-cruft-size=%lu",
 				     cfg->max_cruft_size);
 		if (cfg->repack_expire_to)
-			strvec_pushf(&repack, "--expire-to=%s", cfg->repack_expire_to);
+			strvec_pushf(args, "--expire-to=%s", cfg->repack_expire_to);
 	} else {
-		strvec_push(&repack, "-A");
+		strvec_push(args, "-A");
 		if (cfg->prune_expire)
-			strvec_pushf(&repack, "--unpack-unreachable=%s", cfg->prune_expire);
+			strvec_pushf(args, "--unpack-unreachable=%s", cfg->prune_expire);
 	}
 
 	if (keep_pack)
-		for_each_string_list(keep_pack, keep_one_pack, NULL);
+		for_each_string_list(keep_pack, keep_one_pack, args);
 
 	if (cfg->repack_filter && *cfg->repack_filter)
-		strvec_pushf(&repack, "--filter=%s", cfg->repack_filter);
+		strvec_pushf(args, "--filter=%s", cfg->repack_filter);
 	if (cfg->repack_filter_to && *cfg->repack_filter_to)
-		strvec_pushf(&repack, "--filter-to=%s", cfg->repack_filter_to);
+		strvec_pushf(args, "--filter-to=%s", cfg->repack_filter_to);
 }
 
-static void add_repack_incremental_option(void)
+static void add_repack_incremental_option(struct strvec *args)
 {
-	strvec_push(&repack, "--no-write-bitmap-index");
+	strvec_push(args, "--no-write-bitmap-index");
 }
 
-static int need_to_gc(struct gc_config *cfg)
+static int need_to_gc(struct gc_config *cfg, struct strvec *repack_args)
 {
 	/*
 	 * Setting gc.auto to 0 or negative can disable the
@@ -697,10 +716,10 @@ static int need_to_gc(struct gc_config *cfg)
 				string_list_clear(&keep_pack, 0);
 		}
 
-		add_repack_all_option(cfg, &keep_pack);
+		add_repack_all_option(cfg, &keep_pack, repack_args);
 		string_list_clear(&keep_pack, 0);
-	} else if (too_many_loose_objects(cfg))
-		add_repack_incremental_option();
+	} else if (too_many_loose_objects(cfg->gc_auto_threshold))
+		add_repack_incremental_option(repack_args);
 	else
 		return 0;
 
@@ -849,6 +868,7 @@ int cmd_gc(int argc,
 	int keep_largest_pack = -1;
 	int skip_foreground_tasks = 0;
 	timestamp_t dummy;
+	struct strvec repack_args = STRVEC_INIT;
 	struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT;
 	struct gc_config cfg = GC_CONFIG_INIT;
 	const char *prune_expire_sentinel = "sentinel";
@@ -888,7 +908,7 @@ int cmd_gc(int argc,
 	show_usage_with_options_if_asked(argc, argv,
 					 builtin_gc_usage, builtin_gc_options);
 
-	strvec_pushl(&repack, "repack", "-d", "-l", NULL);
+	strvec_pushl(&repack_args, "repack", "-d", "-l", NULL);
 
 	gc_config(&cfg);
 
@@ -911,14 +931,14 @@ int cmd_gc(int argc,
 		die(_("failed to parse prune expiry value %s"), cfg.prune_expire);
 
 	if (aggressive) {
-		strvec_push(&repack, "-f");
+		strvec_push(&repack_args, "-f");
 		if (cfg.aggressive_depth > 0)
-			strvec_pushf(&repack, "--depth=%d", cfg.aggressive_depth);
+			strvec_pushf(&repack_args, "--depth=%d", cfg.aggressive_depth);
 		if (cfg.aggressive_window > 0)
-			strvec_pushf(&repack, "--window=%d", cfg.aggressive_window);
+			strvec_pushf(&repack_args, "--window=%d", cfg.aggressive_window);
 	}
 	if (opts.quiet)
-		strvec_push(&repack, "-q");
+		strvec_push(&repack_args, "-q");
 
 	if (opts.auto_flag) {
 		if (cfg.detach_auto && opts.detach < 0)
@@ -927,7 +947,7 @@ int cmd_gc(int argc,
 		/*
 		 * Auto-gc should be least intrusive as possible.
 		 */
-		if (!need_to_gc(&cfg)) {
+		if (!need_to_gc(&cfg, &repack_args)) {
 			ret = 0;
 			goto out;
 		}
@@ -949,7 +969,7 @@ int cmd_gc(int argc,
 			find_base_packs(&keep_pack, cfg.big_pack_threshold);
 		}
 
-		add_repack_all_option(&cfg, &keep_pack);
+		add_repack_all_option(&cfg, &keep_pack, &repack_args);
 		string_list_clear(&keep_pack, 0);
 	}
 
@@ -1011,9 +1031,9 @@ int cmd_gc(int argc,
 
 		repack_cmd.git_cmd = 1;
 		repack_cmd.close_object_store = 1;
-		strvec_pushv(&repack_cmd.args, repack.v);
+		strvec_pushv(&repack_cmd.args, repack_args.v);
 		if (run_command(&repack_cmd))
-			die(FAILED_RUN, repack.v[0]);
+			die(FAILED_RUN, repack_args.v[0]);
 
 		if (cfg.prune_expire) {
 			struct child_process prune_cmd = CHILD_PROCESS_INIT;
@@ -1041,7 +1061,7 @@ int cmd_gc(int argc,
 		die(FAILED_RUN, "rerere");
 
 	report_garbage = report_pack_garbage;
-	reprepare_packed_git(the_repository);
+	odb_reprepare(the_repository->objects);
 	if (pack_garbage.nr > 0) {
 		close_object_store(the_repository->objects);
 		clean_pack_garbage();
@@ -1052,7 +1072,7 @@ int cmd_gc(int argc,
 					     !opts.quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0,
 					     NULL);
 
-	if (opts.auto_flag && too_many_loose_objects(&cfg))
+	if (opts.auto_flag && too_many_loose_objects(cfg.gc_auto_threshold))
 		warning(_("There are too many unreachable loose objects; "
 			"run 'git prune' to remove them."));
 
@@ -1064,6 +1084,7 @@ int cmd_gc(int argc,
 
 out:
 	maintenance_run_opts_release(&opts);
+	strvec_clear(&repack_args);
 	gc_config_release(&cfg);
 	return 0;
 }
@@ -1089,32 +1110,26 @@ static int maintenance_opt_schedule(const struct option *opt, const char *arg,
 	return 0;
 }
 
-/* Remember to update object flag allocation in object.h */
-#define SEEN		(1u<<0)
-
 struct cg_auto_data {
 	int num_not_in_graph;
 	int limit;
 };
 
-static int dfs_on_ref(const char *refname UNUSED,
-		      const char *referent UNUSED,
-		      const struct object_id *oid,
-		      int flags UNUSED,
-		      void *cb_data)
+static int dfs_on_ref(const struct reference *ref, void *cb_data)
 {
 	struct cg_auto_data *data = (struct cg_auto_data *)cb_data;
 	int result = 0;
+	const struct object_id *maybe_peeled = ref->oid;
 	struct object_id peeled;
 	struct commit_list *stack = NULL;
 	struct commit *commit;
 
-	if (!peel_iterated_oid(the_repository, oid, &peeled))
-		oid = &peeled;
-	if (odb_read_object_info(the_repository->objects, oid, NULL) != OBJ_COMMIT)
+	if (!reference_get_peeled_oid(the_repository, ref, &peeled))
+		maybe_peeled = &peeled;
+	if (odb_read_object_info(the_repository->objects, maybe_peeled, NULL) != OBJ_COMMIT)
 		return 0;
 
-	commit = lookup_commit(the_repository, oid);
+	commit = lookup_commit(the_repository, maybe_peeled);
 	if (!commit)
 		return 0;
 	if (repo_parse_commit(the_repository, commit) ||
@@ -1266,6 +1281,19 @@ static int maintenance_task_gc_background(struct maintenance_run_opts *opts,
 	return run_command(&child);
 }
 
+static int gc_condition(struct gc_config *cfg)
+{
+	/*
+	 * Note that it's fine to drop the repack arguments here, as we execute
+	 * git-gc(1) as a separate child process anyway. So it knows to compute
+	 * these arguments again.
+	 */
+	struct strvec repack_args = STRVEC_INIT;
+	int ret = need_to_gc(cfg, &repack_args);
+	strvec_clear(&repack_args);
+	return ret;
+}
+
 static int prune_packed(struct maintenance_run_opts *opts)
 {
 	struct child_process child = CHILD_PROCESS_INIT;
@@ -1422,9 +1450,9 @@ static int incremental_repack_auto_condition(struct gc_config *cfg UNUSED)
 	if (incremental_repack_auto_limit < 0)
 		return 1;
 
-	for (p = get_packed_git(the_repository);
-	     count < incremental_repack_auto_limit && p;
-	     p = p->next) {
+	repo_for_each_pack(the_repository, p) {
+		if (count >= incremental_repack_auto_limit)
+			break;
 		if (!p->multi_pack_index)
 			count++;
 	}
@@ -1490,8 +1518,8 @@ static off_t get_auto_pack_size(void)
 	struct packed_git *p;
 	struct repository *r = the_repository;
 
-	reprepare_packed_git(r);
-	for (p = get_all_packs(r); p; p = p->next) {
+	odb_reprepare(r->objects);
+	repo_for_each_pack(r, p) {
 		if (p->pack_size > max_size) {
 			second_largest_size = max_size;
 			max_size = p->pack_size;
@@ -1547,6 +1575,108 @@ static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts
 	return 0;
 }
 
+static int maintenance_task_geometric_repack(struct maintenance_run_opts *opts,
+					     struct gc_config *cfg)
+{
+	struct pack_geometry geometry = {
+		.split_factor = 2,
+	};
+	struct pack_objects_args po_args = {
+		.local = 1,
+	};
+	struct existing_packs existing_packs = EXISTING_PACKS_INIT;
+	struct string_list kept_packs = STRING_LIST_INIT_DUP;
+	struct child_process child = CHILD_PROCESS_INIT;
+	int ret;
+
+	repo_config_get_int(the_repository, "maintenance.geometric-repack.splitFactor",
+			    &geometry.split_factor);
+
+	existing_packs.repo = the_repository;
+	existing_packs_collect(&existing_packs, &kept_packs);
+	pack_geometry_init(&geometry, &existing_packs, &po_args);
+	pack_geometry_split(&geometry);
+
+	child.git_cmd = 1;
+
+	strvec_pushl(&child.args, "repack", "-d", "-l", NULL);
+	if (geometry.split < geometry.pack_nr)
+		strvec_pushf(&child.args, "--geometric=%d",
+			     geometry.split_factor);
+	else
+		add_repack_all_option(cfg, NULL, &child.args);
+	if (opts->quiet)
+		strvec_push(&child.args, "--quiet");
+	if (the_repository->settings.core_multi_pack_index)
+		strvec_push(&child.args, "--write-midx");
+
+	if (run_command(&child)) {
+		ret = error(_("failed to perform geometric repack"));
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	existing_packs_release(&existing_packs);
+	pack_geometry_release(&geometry);
+	return ret;
+}
+
+static int geometric_repack_auto_condition(struct gc_config *cfg UNUSED)
+{
+	struct pack_geometry geometry = {
+		.split_factor = 2,
+	};
+	struct pack_objects_args po_args = {
+		.local = 1,
+	};
+	struct existing_packs existing_packs = EXISTING_PACKS_INIT;
+	struct string_list kept_packs = STRING_LIST_INIT_DUP;
+	int auto_value = 100;
+	int ret;
+
+	repo_config_get_int(the_repository, "maintenance.geometric-repack.auto",
+			    &auto_value);
+	if (!auto_value)
+		return 0;
+	if (auto_value < 0)
+		return 1;
+
+	repo_config_get_int(the_repository, "maintenance.geometric-repack.splitFactor",
+			    &geometry.split_factor);
+
+	existing_packs.repo = the_repository;
+	existing_packs_collect(&existing_packs, &kept_packs);
+	pack_geometry_init(&geometry, &existing_packs, &po_args);
+	pack_geometry_split(&geometry);
+
+	/*
+	 * When we'd merge at least two packs with one another we always
+	 * perform the repack.
+	 */
+	if (geometry.split) {
+		ret = 1;
+		goto out;
+	}
+
+	/*
+	 * Otherwise, we estimate the number of loose objects to determine
+	 * whether we want to create a new packfile or not.
+	 */
+	if (too_many_loose_objects(auto_value)) {
+		ret = 1;
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	existing_packs_release(&existing_packs);
+	pack_geometry_release(&geometry);
+	return ret;
+}
+
 typedef int (*maintenance_task_fn)(struct maintenance_run_opts *opts,
 				   struct gc_config *cfg);
 typedef int (*maintenance_auto_fn)(struct gc_config *cfg);
@@ -1589,11 +1719,16 @@ static const struct maintenance_task tasks[] = {
 		.background = maintenance_task_incremental_repack,
 		.auto_condition = incremental_repack_auto_condition,
 	},
+	[TASK_GEOMETRIC_REPACK] = {
+		.name = "geometric-repack",
+		.background = maintenance_task_geometric_repack,
+		.auto_condition = geometric_repack_auto_condition,
+	},
 	[TASK_GC] = {
 		.name = "gc",
 		.foreground = maintenance_task_gc_foreground,
 		.background = maintenance_task_gc_background,
-		.auto_condition = need_to_gc,
+		.auto_condition = gc_condition,
 	},
 	[TASK_COMMIT_GRAPH] = {
 		.name = "commit-graph",
@@ -1699,39 +1834,116 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts,
 	return result;
 }
 
+enum maintenance_type {
+	/* As invoked via `git maintenance run --schedule=`. */
+	MAINTENANCE_TYPE_SCHEDULED = (1 << 0),
+	/* As invoked via `git maintenance run` and with `--auto`. */
+	MAINTENANCE_TYPE_MANUAL    = (1 << 1),
+};
+
 struct maintenance_strategy {
 	struct {
-		int enabled;
+		unsigned type;
 		enum schedule_priority schedule;
 	} tasks[TASK__COUNT];
 };
 
 static const struct maintenance_strategy none_strategy = { 0 };
-static const struct maintenance_strategy default_strategy = {
+
+static const struct maintenance_strategy gc_strategy = {
 	.tasks = {
-		[TASK_GC].enabled = 1,
+		[TASK_GC] = {
+			.type = MAINTENANCE_TYPE_MANUAL | MAINTENANCE_TYPE_SCHEDULED,
+			.schedule = SCHEDULE_DAILY,
+		},
 	},
 };
+
 static const struct maintenance_strategy incremental_strategy = {
 	.tasks = {
-		[TASK_COMMIT_GRAPH].enabled = 1,
-		[TASK_COMMIT_GRAPH].schedule = SCHEDULE_HOURLY,
-		[TASK_PREFETCH].enabled = 1,
-		[TASK_PREFETCH].schedule = SCHEDULE_HOURLY,
-		[TASK_INCREMENTAL_REPACK].enabled = 1,
-		[TASK_INCREMENTAL_REPACK].schedule = SCHEDULE_DAILY,
-		[TASK_LOOSE_OBJECTS].enabled = 1,
-		[TASK_LOOSE_OBJECTS].schedule = SCHEDULE_DAILY,
-		[TASK_PACK_REFS].enabled = 1,
-		[TASK_PACK_REFS].schedule = SCHEDULE_WEEKLY,
+		[TASK_COMMIT_GRAPH] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED,
+			.schedule = SCHEDULE_HOURLY,
+		},
+		[TASK_PREFETCH] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED,
+			.schedule = SCHEDULE_HOURLY,
+		},
+		[TASK_INCREMENTAL_REPACK] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED,
+			.schedule = SCHEDULE_DAILY,
+		},
+		[TASK_LOOSE_OBJECTS] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED,
+			.schedule = SCHEDULE_DAILY,
+		},
+		[TASK_PACK_REFS] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED,
+			.schedule = SCHEDULE_WEEKLY,
+		},
+		/*
+		 * Historically, the "incremental" strategy was only available
+		 * in the context of scheduled maintenance when set up via
+		 * "maintenance.strategy". We have later expanded that config
+		 * to also cover manual maintenance.
+		 *
+		 * To retain backwards compatibility with the previous status
+		 * quo we thus run git-gc(1) in case manual maintenance was
+		 * requested. This is the same as the default strategy, which
+		 * would have been in use beforehand.
+		 */
+		[TASK_GC] = {
+			.type = MAINTENANCE_TYPE_MANUAL,
+		},
 	},
 };
 
+static const struct maintenance_strategy geometric_strategy = {
+	.tasks = {
+		[TASK_COMMIT_GRAPH] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+			.schedule = SCHEDULE_HOURLY,
+		},
+		[TASK_GEOMETRIC_REPACK] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+			.schedule = SCHEDULE_DAILY,
+		},
+		[TASK_PACK_REFS] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+			.schedule = SCHEDULE_DAILY,
+		},
+		[TASK_RERERE_GC] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+			.schedule = SCHEDULE_WEEKLY,
+		},
+		[TASK_REFLOG_EXPIRE] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+			.schedule = SCHEDULE_WEEKLY,
+		},
+		[TASK_WORKTREE_PRUNE] = {
+			.type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+			.schedule = SCHEDULE_WEEKLY,
+		},
+	},
+};
+
+static struct maintenance_strategy parse_maintenance_strategy(const char *name)
+{
+	if (!strcasecmp(name, "incremental"))
+		return incremental_strategy;
+	if (!strcasecmp(name, "gc"))
+		return gc_strategy;
+	if (!strcasecmp(name, "geometric"))
+		return geometric_strategy;
+	die(_("unknown maintenance strategy: '%s'"), name);
+}
+
 static void initialize_task_config(struct maintenance_run_opts *opts,
 				   const struct string_list *selected_tasks)
 {
 	struct strbuf config_name = STRBUF_INIT;
 	struct maintenance_strategy strategy;
+	enum maintenance_type type;
 	const char *config_str;
 
 	/*
@@ -1759,19 +1971,20 @@ static void initialize_task_config(struct maintenance_run_opts *opts,
 	 *   - Unscheduled maintenance uses our default strategy.
 	 *
 	 * Both of these are affected by the gitconfig though, which may
-	 * override specific aspects of our strategy.
+	 * override specific aspects of our strategy. Furthermore, both
+	 * strategies can be overridden by setting "maintenance.strategy".
 	 */
 	if (opts->schedule) {
 		strategy = none_strategy;
-
-		if (!repo_config_get_string_tmp(the_repository, "maintenance.strategy", &config_str)) {
-			if (!strcasecmp(config_str, "incremental"))
-				strategy = incremental_strategy;
-		}
+		type = MAINTENANCE_TYPE_SCHEDULED;
 	} else {
-		strategy = default_strategy;
+		strategy = gc_strategy;
+		type = MAINTENANCE_TYPE_MANUAL;
 	}
 
+	if (!repo_config_get_string_tmp(the_repository, "maintenance.strategy", &config_str))
+		strategy = parse_maintenance_strategy(config_str);
+
 	for (size_t i = 0; i < TASK__COUNT; i++) {
 		int config_value;
 
@@ -1779,8 +1992,8 @@ static void initialize_task_config(struct maintenance_run_opts *opts,
 		strbuf_addf(&config_name, "maintenance.%s.enabled",
 			    tasks[i].name);
 		if (!repo_config_get_bool(the_repository, config_name.buf, &config_value))
-			strategy.tasks[i].enabled = config_value;
-		if (!strategy.tasks[i].enabled)
+			strategy.tasks[i].type = config_value ? type : 0;
+		if (!(strategy.tasks[i].type & type))
 			continue;
 
 		if (opts->schedule) {
@@ -3243,7 +3456,67 @@ static int maintenance_stop(int argc, const char **argv, const char *prefix,
 	return update_background_schedule(NULL, 0);
 }
 
-static const char * const builtin_maintenance_usage[] = {
+static const char *const builtin_maintenance_is_needed_usage[] = {
+	"git maintenance is-needed [--task=<task>] [--schedule]",
+	NULL
+};
+
+static int maintenance_is_needed(int argc, const char **argv, const char *prefix,
+				 struct repository *repo UNUSED)
+{
+	struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT;
+	struct string_list selected_tasks = STRING_LIST_INIT_DUP;
+	struct gc_config cfg = GC_CONFIG_INIT;
+	struct option options[] = {
+		OPT_BOOL(0, "auto", &opts.auto_flag,
+			 N_("run tasks based on the state of the repository")),
+		OPT_CALLBACK_F(0, "task", &selected_tasks, N_("task"),
+			       N_("check a specific task"),
+			       PARSE_OPT_NONEG, task_option_parse),
+		OPT_END()
+	};
+	bool is_needed = false;
+
+	argc = parse_options(argc, argv, prefix, options,
+			     builtin_maintenance_is_needed_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (argc)
+		usage_with_options(builtin_maintenance_is_needed_usage, options);
+
+	gc_config(&cfg);
+	initialize_task_config(&opts, &selected_tasks);
+
+	if (opts.auto_flag) {
+		for (size_t i = 0; i < opts.tasks_nr; i++) {
+			if (tasks[opts.tasks[i]].auto_condition &&
+			    tasks[opts.tasks[i]].auto_condition(&cfg)) {
+				is_needed = true;
+				break;
+			}
+		}
+	} else {
+		/*
+		 * When not using --auto we always require maintenance right now.
+		 *
+		 * TODO: this certainly is too eager, as some maintenance tasks may
+		 * decide to not do anything because the data structures are already
+		 * fully optimized. We may eventually want to extend the auto
+		 * condition to also cover non-auto runs so that we can detect such
+		 * cases.
+		 */
+		is_needed = true;
+	}
+
+	string_list_clear(&selected_tasks, 0);
+	maintenance_run_opts_release(&opts);
+	gc_config_release(&cfg);
+
+	if (is_needed)
+		return 0;
+	return 1;
+}
+
+static const char *const builtin_maintenance_usage[] = {
 	N_("git maintenance <subcommand> [<options>]"),
 	NULL,
 };
@@ -3260,6 +3533,7 @@ int cmd_maintenance(int argc,
 		OPT_SUBCOMMAND("stop", &fn, maintenance_stop),
 		OPT_SUBCOMMAND("register", &fn, maintenance_register),
 		OPT_SUBCOMMAND("unregister", &fn, maintenance_unregister),
+		OPT_SUBCOMMAND("is-needed", &fn, maintenance_is_needed),
 		OPT_END(),
 	};
 
diff --git a/builtin/grep.c b/builtin/grep.c
index 5df6537..53cccf2 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1091,7 +1091,7 @@ int cmd_grep(int argc,
 	if (show_in_pager == default_pager)
 		show_in_pager = git_pager(the_repository, 1);
 	if (show_in_pager) {
-		opt.color = 0;
+		opt.color = GIT_COLOR_NEVER;
 		opt.name_only = 1;
 		opt.null_following_name = 1;
 		opt.output_priv = &path_list;
@@ -1214,7 +1214,7 @@ int cmd_grep(int argc,
 		if (recurse_submodules)
 			repo_read_gitmodules(the_repository, 1);
 		if (startup_info->have_repository)
-			(void)get_packed_git(the_repository);
+			packfile_store_prepare(the_repository->objects->packfiles);
 
 		start_threads(&opt);
 	} else {
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index f91c301..2b78ba7 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1640,13 +1640,9 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
 	rename_tmp_packfile(&final_index_name, curr_index_name, &index_name,
 			    hash, "idx", 1);
 
-	if (do_fsck_object) {
-		struct packed_git *p;
-		p = add_packed_git(the_repository, final_index_name,
-				   strlen(final_index_name), 0);
-		if (p)
-			install_packed_git(the_repository, p);
-	}
+	if (do_fsck_object)
+		packfile_store_load_pack(the_repository->objects->packfiles,
+					 final_index_name, 0);
 
 	if (!from_stdin) {
 		printf("%s\n", hash_to_hex(hash));
diff --git a/builtin/last-modified.c b/builtin/last-modified.c
new file mode 100644
index 0000000..b0ecbdc
--- /dev/null
+++ b/builtin/last-modified.c
@@ -0,0 +1,547 @@
+#include "git-compat-util.h"
+#include "bloom.h"
+#include "builtin.h"
+#include "commit-graph.h"
+#include "commit-slab.h"
+#include "commit.h"
+#include "config.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "environment.h"
+#include "ewah/ewok.h"
+#include "hashmap.h"
+#include "hex.h"
+#include "object-name.h"
+#include "object.h"
+#include "parse-options.h"
+#include "prio-queue.h"
+#include "quote.h"
+#include "repository.h"
+#include "revision.h"
+
+/* Remember to update object flag allocation in object.h */
+#define PARENT1 (1u<<16) /* used instead of SEEN */
+#define PARENT2 (1u<<17) /* used instead of BOTTOM, BOUNDARY */
+
+struct last_modified_entry {
+	struct hashmap_entry hashent;
+	struct object_id oid;
+	struct bloom_key key;
+	size_t diff_idx;
+	const char path[FLEX_ARRAY];
+};
+
+static int last_modified_entry_hashcmp(const void *unused UNUSED,
+				       const struct hashmap_entry *hent1,
+				       const struct hashmap_entry *hent2,
+				       const void *path)
+{
+	const struct last_modified_entry *ent1 =
+		container_of(hent1, const struct last_modified_entry, hashent);
+	const struct last_modified_entry *ent2 =
+		container_of(hent2, const struct last_modified_entry, hashent);
+	return strcmp(ent1->path, path ? path : ent2->path);
+}
+
+/*
+ * Hold a bitmap for each commit we're working with. In the bitmap, each bit
+ * represents a path in `lm->all_paths`. An active bit indicates the path still
+ * needs to be associated to a commit.
+ */
+define_commit_slab(active_paths_for_commit, struct bitmap *);
+
+struct last_modified {
+	struct hashmap paths;
+	struct rev_info rev;
+	bool recursive;
+	bool show_trees;
+
+	const char **all_paths;
+	size_t all_paths_nr;
+	struct active_paths_for_commit active_paths;
+
+	/* 'scratch' to avoid allocating a bitmap every process_parent() */
+	struct bitmap *scratch;
+};
+
+static struct bitmap *active_paths_for(struct last_modified *lm, struct commit *c)
+{
+	struct bitmap **bitmap = active_paths_for_commit_at(&lm->active_paths, c);
+	if (!*bitmap)
+		*bitmap = bitmap_word_alloc(lm->all_paths_nr / BITS_IN_EWORD + 1);
+
+	return *bitmap;
+}
+
+static void active_paths_free(struct last_modified *lm, struct commit *c)
+{
+	struct bitmap **bitmap = active_paths_for_commit_at(&lm->active_paths, c);
+	if (*bitmap) {
+		bitmap_free(*bitmap);
+		*bitmap = NULL;
+	}
+}
+
+static void last_modified_release(struct last_modified *lm)
+{
+	struct hashmap_iter iter;
+	struct last_modified_entry *ent;
+
+	hashmap_for_each_entry(&lm->paths, &iter, ent, hashent)
+		bloom_key_clear(&ent->key);
+
+	hashmap_clear_and_free(&lm->paths, struct last_modified_entry, hashent);
+	release_revisions(&lm->rev);
+
+	free(lm->all_paths);
+}
+
+struct last_modified_callback_data {
+	struct last_modified *lm;
+	struct commit *commit;
+};
+
+static void add_path_from_diff(struct diff_queue_struct *q,
+			       struct diff_options *opt UNUSED, void *data)
+{
+	struct last_modified *lm = data;
+
+	for (int i = 0; i < q->nr; i++) {
+		struct diff_filepair *p = q->queue[i];
+		struct last_modified_entry *ent;
+		const char *path = p->two->path;
+
+		FLEX_ALLOC_STR(ent, path, path);
+		oidcpy(&ent->oid, &p->two->oid);
+		if (lm->rev.bloom_filter_settings)
+			bloom_key_fill(&ent->key, path, strlen(path),
+				       lm->rev.bloom_filter_settings);
+		hashmap_entry_init(&ent->hashent, strhash(ent->path));
+		hashmap_add(&lm->paths, &ent->hashent);
+	}
+}
+
+static int populate_paths_from_revs(struct last_modified *lm)
+{
+	int num_interesting = 0;
+	struct diff_options diffopt;
+
+	/*
+	 * Create a copy of `struct diff_options`. In this copy a callback is
+	 * set that when called adds entries to `paths` in `struct last_modified`.
+	 * This copy is used to diff the tree of the target revision against an
+	 * empty tree. This results in all paths in the target revision being
+	 * listed. After `paths` is populated, we don't need this copy no more.
+	 */
+	memcpy(&diffopt, &lm->rev.diffopt, sizeof(diffopt));
+	copy_pathspec(&diffopt.pathspec, &lm->rev.diffopt.pathspec);
+	diffopt.output_format = DIFF_FORMAT_CALLBACK;
+	diffopt.format_callback = add_path_from_diff;
+	diffopt.format_callback_data = lm;
+
+	for (size_t i = 0; i < lm->rev.pending.nr; i++) {
+		struct object_array_entry *obj = lm->rev.pending.objects + i;
+
+		if (obj->item->flags & UNINTERESTING)
+			continue;
+
+		if (num_interesting++)
+			return error(_("last-modified can only operate on one tree at a time"));
+
+		diff_tree_oid(lm->rev.repo->hash_algo->empty_tree,
+			      &obj->item->oid, "", &diffopt);
+		diff_flush(&diffopt);
+	}
+	clear_pathspec(&diffopt.pathspec);
+
+	return 0;
+}
+
+static void last_modified_emit(struct last_modified *lm,
+			       const char *path, const struct commit *commit)
+
+{
+	if (commit->object.flags & BOUNDARY)
+		putchar('^');
+	printf("%s\t", oid_to_hex(&commit->object.oid));
+
+	if (lm->rev.diffopt.line_termination)
+		write_name_quoted(path, stdout, '\n');
+	else
+		printf("%s%c", path, '\0');
+}
+
+static void mark_path(const char *path, const struct object_id *oid,
+		      struct last_modified_callback_data *data)
+{
+	struct last_modified_entry *ent;
+
+	/* Is it even a path that we are interested in? */
+	ent = hashmap_get_entry_from_hash(&data->lm->paths, strhash(path), path,
+					  struct last_modified_entry, hashent);
+	if (!ent)
+		return;
+
+	/*
+	 * Is it arriving at a version of interest, or is it from a side branch
+	 * which did not contribute to the final state?
+	 */
+	if (oid && !oideq(oid, &ent->oid))
+		return;
+
+	last_modified_emit(data->lm, path, data->commit);
+
+	hashmap_remove(&data->lm->paths, &ent->hashent, path);
+	bloom_key_clear(&ent->key);
+	free(ent);
+}
+
+static void last_modified_diff(struct diff_queue_struct *q,
+			       struct diff_options *opt UNUSED, void *cbdata)
+{
+	struct last_modified_callback_data *data = cbdata;
+
+	for (int i = 0; i < q->nr; i++) {
+		struct diff_filepair *p = q->queue[i];
+		switch (p->status) {
+		case DIFF_STATUS_DELETED:
+			/*
+			 * There's no point in feeding a deletion, as it could
+			 * not have resulted in our current state, which
+			 * actually has the file.
+			 */
+			break;
+
+		default:
+			/*
+			 * Otherwise, we care only that we somehow arrived at
+			 * a final oid state. Note that this covers some
+			 * potentially controversial areas, including:
+			 *
+			 *  1. A rename or copy will be found, as it is the
+			 *     first time the content has arrived at the given
+			 *     path.
+			 *
+			 *  2. Even a non-content modification like a mode or
+			 *     type change will trigger it.
+			 *
+			 * We take the inclusive approach for now, and find
+			 * anything which impacts the path. Options to tweak
+			 * the behavior (e.g., to "--follow" the content across
+			 * renames) can come later.
+			 */
+			mark_path(p->two->path, &p->two->oid, data);
+			break;
+		}
+	}
+}
+
+static void pass_to_parent(struct bitmap *c,
+			   struct bitmap *p,
+			   size_t pos)
+{
+	bitmap_unset(c, pos);
+	bitmap_set(p, pos);
+}
+
+static bool maybe_changed_path(struct last_modified *lm,
+			       struct commit *origin,
+			       struct bitmap *active)
+{
+	struct bloom_filter *filter;
+	struct last_modified_entry *ent;
+	struct hashmap_iter iter;
+
+	if (!lm->rev.bloom_filter_settings)
+		return true;
+
+	if (commit_graph_generation(origin) == GENERATION_NUMBER_INFINITY)
+		return true;
+
+	filter = get_bloom_filter(lm->rev.repo, origin);
+	if (!filter)
+		return true;
+
+	hashmap_for_each_entry(&lm->paths, &iter, ent, hashent) {
+		if (active && !bitmap_get(active, ent->diff_idx))
+			continue;
+
+		if (bloom_filter_contains(filter, &ent->key,
+					  lm->rev.bloom_filter_settings))
+			return true;
+	}
+	return false;
+}
+
+static void process_parent(struct last_modified *lm,
+			   struct prio_queue *queue,
+			   struct commit *c, struct bitmap *active_c,
+			   struct commit *parent, int parent_i)
+{
+	struct bitmap *active_p;
+
+	repo_parse_commit(lm->rev.repo, parent);
+	active_p = active_paths_for(lm, parent);
+
+	/*
+	 * The first time entering this function for this commit (i.e. first parent)
+	 * see if Bloom filters will tell us it's worth to do the diff.
+	 */
+	if (parent_i || maybe_changed_path(lm, c, active_c)) {
+		diff_tree_oid(&parent->object.oid,
+			      &c->object.oid, "", &lm->rev.diffopt);
+		diffcore_std(&lm->rev.diffopt);
+	}
+
+	/*
+	 * Test each path for TREESAME-ness against the parent. If a path is
+	 * TREESAME, pass it on to this parent.
+	 *
+	 * First, collect all paths that are *not* TREESAME in 'scratch'.
+	 * Then, pass paths that *are* TREESAME and active to the parent.
+	 */
+	for (int i = 0; i < diff_queued_diff.nr; i++) {
+		struct diff_filepair *fp = diff_queued_diff.queue[i];
+		const char *path = fp->two->path;
+		struct last_modified_entry *ent =
+			hashmap_get_entry_from_hash(&lm->paths, strhash(path), path,
+						    struct last_modified_entry, hashent);
+		if (ent) {
+			size_t k = ent->diff_idx;
+			if (bitmap_get(active_c, k))
+				bitmap_set(lm->scratch, k);
+		}
+	}
+	for (size_t i = 0; i < lm->all_paths_nr; i++) {
+		if (bitmap_get(active_c, i) && !bitmap_get(lm->scratch, i))
+			pass_to_parent(active_c, active_p, i);
+	}
+
+	/*
+	 * If parent has any active paths, put it on the queue (if not already).
+	 */
+	if (!bitmap_is_empty(active_p) && !(parent->object.flags & PARENT1)) {
+		parent->object.flags |= PARENT1;
+		prio_queue_put(queue, parent);
+	}
+	if (!(parent->object.flags & PARENT1))
+		active_paths_free(lm, parent);
+
+	memset(lm->scratch->words, 0x0, lm->scratch->word_alloc);
+	diff_queue_clear(&diff_queued_diff);
+}
+
+static int last_modified_run(struct last_modified *lm)
+{
+	int max_count, queue_popped = 0;
+	struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
+	struct prio_queue not_queue = { compare_commits_by_gen_then_commit_date };
+	struct commit_list *list;
+	struct last_modified_callback_data data = { .lm = lm };
+
+	lm->rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
+	lm->rev.diffopt.format_callback = last_modified_diff;
+	lm->rev.diffopt.format_callback_data = &data;
+	lm->rev.no_walk = 1;
+
+	prepare_revision_walk(&lm->rev);
+
+	max_count = lm->rev.max_count;
+
+	init_active_paths_for_commit(&lm->active_paths);
+	lm->scratch = bitmap_word_alloc(lm->all_paths_nr);
+
+	/*
+	 * lm->rev.commits holds the set of boundary commits for our walk.
+	 *
+	 * Loop through each such commit, and place it in the appropriate queue.
+	 */
+	for (list = lm->rev.commits; list; list = list->next) {
+		struct commit *c = list->item;
+
+		if (c->object.flags & BOTTOM) {
+			prio_queue_put(&not_queue, c);
+			c->object.flags |= PARENT2;
+		} else if (!(c->object.flags & PARENT1)) {
+			/*
+			 * If the commit is a starting point (and hasn't been
+			 * seen yet), then initialize the set of interesting
+			 * paths, too.
+			 */
+			struct bitmap *active;
+
+			prio_queue_put(&queue, c);
+			c->object.flags |= PARENT1;
+
+			active = active_paths_for(lm, c);
+			for (size_t i = 0; i < lm->all_paths_nr; i++)
+				bitmap_set(active, i);
+		}
+	}
+
+	while (queue.nr) {
+		int parent_i;
+		struct commit_list *p;
+		struct commit *c = prio_queue_get(&queue);
+		struct bitmap *active_c = active_paths_for(lm, c);
+
+		if ((0 <= max_count && max_count < ++queue_popped) ||
+		    (c->object.flags & PARENT2)) {
+			/*
+			 * Either a boundary commit, or we have already seen too
+			 * many others. Either way, stop here.
+			 */
+			c->object.flags |= PARENT2 | BOUNDARY;
+			data.commit = c;
+			diff_tree_oid(lm->rev.repo->hash_algo->empty_tree,
+				      &c->object.oid,
+				      "", &lm->rev.diffopt);
+			diff_flush(&lm->rev.diffopt);
+			goto cleanup;
+		}
+
+		/*
+		 * Otherwise, make sure that 'c' isn't reachable from anything
+		 * in the '--not' queue.
+		 */
+		repo_parse_commit(lm->rev.repo, c);
+
+		while (not_queue.nr) {
+			struct commit_list *np;
+			struct commit *n = prio_queue_get(&not_queue);
+
+			repo_parse_commit(lm->rev.repo, n);
+
+			for (np = n->parents; np; np = np->next) {
+				if (!(np->item->object.flags & PARENT2)) {
+					prio_queue_put(&not_queue, np->item);
+					np->item->object.flags |= PARENT2;
+				}
+			}
+
+			if (commit_graph_generation(n) < commit_graph_generation(c))
+				break;
+		}
+
+		/*
+		 * Look at each parent and pass on each path that's TREESAME
+		 * with that parent. Stop early when no active paths remain.
+		 */
+		for (p = c->parents, parent_i = 0; p; p = p->next, parent_i++) {
+			process_parent(lm, &queue,
+				       c, active_c,
+				       p->item, parent_i);
+
+			if (bitmap_is_empty(active_c))
+				break;
+		}
+
+		/*
+		 * Paths that remain active, or not TREESAME with any parent,
+		 * were changed by 'c'.
+		 */
+		if (!bitmap_is_empty(active_c))  {
+			data.commit = c;
+			for (size_t i = 0; i < lm->all_paths_nr; i++) {
+				if (bitmap_get(active_c, i))
+					mark_path(lm->all_paths[i], NULL, &data);
+			}
+		}
+
+cleanup:
+		active_paths_free(lm, c);
+	}
+
+	if (hashmap_get_size(&lm->paths))
+		BUG("paths remaining beyond boundary in last-modified");
+
+	clear_prio_queue(&not_queue);
+	clear_prio_queue(&queue);
+	clear_active_paths_for_commit(&lm->active_paths);
+	bitmap_free(lm->scratch);
+
+	return 0;
+}
+
+static int last_modified_init(struct last_modified *lm, struct repository *r,
+			      const char *prefix, int argc, const char **argv)
+{
+	struct hashmap_iter iter;
+	struct last_modified_entry *ent;
+
+	hashmap_init(&lm->paths, last_modified_entry_hashcmp, NULL, 0);
+
+	repo_init_revisions(r, &lm->rev, prefix);
+	lm->rev.def = "HEAD";
+	lm->rev.combine_merges = 1;
+	lm->rev.show_root_diff = 1;
+	lm->rev.boundary = 1;
+	lm->rev.no_commit_id = 1;
+	lm->rev.diff = 1;
+	lm->rev.diffopt.flags.no_recursive_diff_tree_combined = 1;
+	lm->rev.diffopt.flags.recursive = lm->recursive;
+	lm->rev.diffopt.flags.tree_in_recursive = lm->show_trees;
+
+	argc = setup_revisions(argc, argv, &lm->rev, NULL);
+	if (argc > 1) {
+		error(_("unknown last-modified argument: %s"), argv[1]);
+		return argc;
+	}
+
+	lm->rev.bloom_filter_settings = get_bloom_filter_settings(lm->rev.repo);
+
+	if (populate_paths_from_revs(lm) < 0)
+		return error(_("unable to setup last-modified"));
+
+	CALLOC_ARRAY(lm->all_paths, hashmap_get_size(&lm->paths));
+	lm->all_paths_nr = 0;
+	hashmap_for_each_entry(&lm->paths, &iter, ent, hashent) {
+		ent->diff_idx = lm->all_paths_nr++;
+		lm->all_paths[ent->diff_idx] = ent->path;
+	}
+
+	return 0;
+}
+
+int cmd_last_modified(int argc, const char **argv, const char *prefix,
+		      struct repository *repo)
+{
+	int ret;
+	struct last_modified lm = { 0 };
+
+	const char * const last_modified_usage[] = {
+		N_("git last-modified [--recursive] [--show-trees] "
+		   "[<revision-range>] [[--] <path>...]"),
+		NULL
+	};
+
+	struct option last_modified_options[] = {
+		OPT_BOOL('r', "recursive", &lm.recursive,
+			 N_("recurse into subtrees")),
+		OPT_BOOL('t', "show-trees", &lm.show_trees,
+			 N_("show tree entries when recursing into subtrees")),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, last_modified_options,
+			     last_modified_usage,
+			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT);
+
+	repo_config(repo, git_default_config, NULL);
+
+	ret = last_modified_init(&lm, repo, prefix, argc, argv);
+	if (ret > 0)
+		usage_with_options(last_modified_usage,
+				   last_modified_options);
+	if (ret)
+		goto out;
+
+	ret = last_modified_run(&lm);
+	if (ret)
+		goto out;
+
+out:
+	last_modified_release(&lm);
+
+	return ret;
+}
diff --git a/builtin/log.c b/builtin/log.c
index 1d1e6e9..c8319b8 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1406,12 +1406,12 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
 		 * can be added later if deemed desirable.
 		 */
 		struct diff_options opts;
-		struct strvec other_arg = STRVEC_INIT;
 		struct range_diff_options range_diff_opts = {
 			.creation_factor = rev->creation_factor,
 			.dual_color = 1,
+			.max_memory = RANGE_DIFF_MAX_MEMORY_DEFAULT,
 			.diffopt = &opts,
-			.other_arg = &other_arg
+			.log_arg = &rev->rdiff_log_arg
 		};
 
 		repo_diff_setup(the_repository, &opts);
@@ -1419,9 +1419,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
 		opts.use_color = rev->diffopt.use_color;
 		diff_setup_done(&opts);
 		fprintf_ln(rev->diffopt.file, "%s", rev->rdiff_title);
-		get_notes_args(&other_arg, rev);
 		show_range_diff(rev->rdiff1, rev->rdiff2, &range_diff_opts);
-		strvec_clear(&other_arg);
 	}
 }
 
@@ -2333,6 +2331,7 @@ int cmd_format_patch(int argc,
 		rev.rdiff_title = diff_title(&rdiff_title, reroll_count,
 					     _("Range-diff:"),
 					     _("Range-diff against v%d:"));
+		get_notes_args(&(rev.rdiff_log_arg), &rev);
 	}
 
 	/*
@@ -2492,6 +2491,7 @@ int cmd_format_patch(int argc,
 	rev.diffopt.no_free = 0;
 	release_revisions(&rev);
 	format_config_release(&cfg);
+	strvec_clear(&rev.rdiff_log_arg);
 	return 0;
 }
 
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index c06a6f3..b148607 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -414,14 +414,21 @@ static void show_files(struct repository *repo, struct dir_struct *dir)
 	if (!(show_cached || show_stage || show_deleted || show_modified))
 		return;
 
-	if (!show_sparse_dirs)
-		ensure_full_index(repo->index);
-
 	for (i = 0; i < repo->index->cache_nr; i++) {
 		const struct cache_entry *ce = repo->index->cache[i];
 		struct stat st;
 		int stat_err;
 
+		if (S_ISSPARSEDIR(ce->ce_mode) && !show_sparse_dirs) {
+			/*
+			 * This is the first time we've hit a sparse dir,
+			 * so expansion will leave the first 'i' entries
+			 * alone.
+			 */
+			ensure_full_index(repo->index);
+			ce = repo->index->cache[i];
+		}
+
 		construct_fullname(&fullname, repo, ce);
 
 		if ((dir->flags & DIR_SHOW_IGNORED) &&
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index df09000..fe77829 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -156,7 +156,7 @@ int cmd_ls_remote(int argc,
 			continue;
 		if (!tail_match(&pattern, ref->name))
 			continue;
-		item = ref_array_push(&ref_array, ref->name, &ref->old_oid);
+		item = ref_array_push(&ref_array, ref->name, &ref->old_oid, NULL);
 		item->symref = xstrdup_or_null(ref->symref);
 	}
 
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 5d55731..ec6940f 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -373,7 +373,6 @@ int cmd_ls_tree(int argc,
 		OPT_END()
 	};
 	struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format;
-	struct object_context obj_context = {0};
 	int ret;
 
 	repo_config(the_repository, git_default_config, NULL);
@@ -405,9 +404,8 @@ int cmd_ls_tree(int argc,
 			ls_tree_usage, ls_tree_options);
 	if (argc < 1)
 		usage_with_options(ls_tree_usage, ls_tree_options);
-	if (get_oid_with_context(the_repository, argv[0],
-				 GET_OID_HASH_ANY, &oid,
-				 &obj_context))
+	if (repo_get_oid_with_flags(the_repository, argv[0], &oid,
+				    GET_OID_HASH_ANY))
 		die("Not a valid object name %s", argv[0]);
 
 	/*
@@ -447,6 +445,5 @@ int cmd_ls_tree(int argc,
 
 	ret = !!read_tree(the_repository, tree, &options.pathspec, fn, &options);
 	clear_pathspec(&options.pathspec);
-	object_context_release(&obj_context);
 	return ret;
 }
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index 03b5100..17aa4db 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -38,7 +38,8 @@ int cmd_merge_recursive(int argc,
 	if (argv[0] && ends_with(argv[0], "-subtree"))
 		o.subtree_shift = "";
 
-	if (argc == 2 && !strcmp(argv[1], "-h")) {
+	if (argc == 2 && (!strcmp(argv[1], "-h") ||
+			  !strcmp(argv[1], "--help-all"))) {
 		struct strbuf msg = STRBUF_INIT;
 		strbuf_addf(&msg, builtin_merge_recursive_usage, argv[0]);
 		show_usage_if_asked(argc, argv, msg.buf);
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 203f0e6..1c063d9 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -619,32 +619,34 @@ int cmd_merge_tree(int argc,
 			    "--merge-base", "--stdin");
 		line_termination = '\0';
 		while (strbuf_getline_lf(&buf, stdin) != EOF) {
-			struct strbuf **split;
+			struct string_list split = STRING_LIST_INIT_NODUP;
 			const char *input_merge_base = NULL;
 
-			split = strbuf_split(&buf, ' ');
-			if (!split[0] || !split[1])
+			string_list_split_in_place_f(&split, buf.buf, " ", -1,
+						     STRING_LIST_SPLIT_TRIM);
+
+			if (split.nr < 2)
 				die(_("malformed input line: '%s'."), buf.buf);
-			strbuf_rtrim(split[0]);
-			strbuf_rtrim(split[1]);
 
 			/* parse the merge-base */
-			if (!strcmp(split[1]->buf, "--")) {
-				input_merge_base = split[0]->buf;
+			if (!strcmp(split.items[1].string, "--")) {
+				input_merge_base = split.items[0].string;
 			}
 
-			if (input_merge_base && split[2] && split[3] && !split[4]) {
-				strbuf_rtrim(split[2]);
-				strbuf_rtrim(split[3]);
-				real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix);
-			} else if (!input_merge_base && !split[2]) {
-				real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix);
+			if (input_merge_base && split.nr == 4) {
+				real_merge(&o, input_merge_base,
+					   split.items[2].string, split.items[3].string,
+					   prefix);
+			} else if (!input_merge_base && split.nr == 2) {
+				real_merge(&o, NULL,
+					   split.items[0].string, split.items[1].string,
+					   prefix);
 			} else {
 				die(_("malformed input line: '%s'."), buf.buf);
 			}
 			maybe_flush_or_die(stdout, "stdout");
 
-			strbuf_list_free(split);
+			string_list_clear(&split, 0);
 		}
 		strbuf_release(&buf);
 
diff --git a/builtin/merge.c b/builtin/merge.c
index ce880e6..c421a11 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -875,7 +875,7 @@ static void add_strategies(const char *string, unsigned attr)
 	if (string) {
 		struct string_list list = STRING_LIST_INIT_DUP;
 		struct string_list_item *item;
-		string_list_split(&list, string, ' ', -1);
+		string_list_split(&list, string, " ", -1);
 		for_each_string_list_item(item, &list)
 			append_strategy(get_strategy(item->string));
 		string_list_clear(&list, 0);
@@ -1374,10 +1374,14 @@ int cmd_merge(int argc,
 	struct commit_list *remoteheads = NULL, *p;
 	void *branch_to_free;
 	int orig_argc = argc;
+	int merge_log_config = -1;
 
 	show_usage_with_options_if_asked(argc, argv,
 					 builtin_merge_usage, builtin_merge_options);
 
+#ifndef WITH_BREAKING_CHANGES
+	warn_on_auto_comment_char = true;
+#endif /* !WITH_BREAKING_CHANGES */
 	prepare_repo_settings(the_repository);
 	the_repository->settings.command_requires_full_index = 0;
 
@@ -1392,7 +1396,7 @@ int cmd_merge(int argc,
 		skip_prefix(branch, "refs/heads/", &branch);
 
 	init_diff_ui_defaults();
-	repo_config(the_repository, git_merge_config, NULL);
+	repo_config(the_repository, git_merge_config, &merge_log_config);
 
 	if (!branch || is_null_oid(&head_oid))
 		head_commit = NULL;
@@ -1862,7 +1866,7 @@ int cmd_merge(int argc,
 	if (squash) {
 		finish(head_commit, remoteheads, NULL, NULL);
 
-		git_test_write_commit_graph_or_die();
+		git_test_write_commit_graph_or_die(the_repository->objects->sources);
 	} else
 		write_merge_state(remoteheads);
 
diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c
index d3b9e98..5f364aa 100644
--- a/builtin/multi-pack-index.c
+++ b/builtin/multi-pack-index.c
@@ -65,12 +65,20 @@ static int parse_object_dir(const struct option *opt, const char *arg,
 	char **value = opt->value;
 	free(*value);
 	if (unset)
-		*value = xstrdup(repo_get_object_directory(the_repository));
+		*value = xstrdup(the_repository->objects->sources->path);
 	else
 		*value = real_pathdup(arg, 1);
 	return 0;
 }
 
+static struct odb_source *handle_object_dir_option(struct repository *repo)
+{
+	struct odb_source *source = odb_find_source(repo->objects, opts.object_dir);
+	if (!source)
+		source = odb_add_to_alternates_memory(repo->objects, opts.object_dir);
+	return source;
+}
+
 static struct option common_opts[] = {
 	OPT_CALLBACK(0, "object-dir", &opts.object_dir,
 	  N_("directory"),
@@ -140,6 +148,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
 			     N_("refs snapshot for selecting bitmap commits")),
 		OPT_END(),
 	};
+	struct odb_source *source;
 	int ret;
 
 	opts.flags |= MIDX_WRITE_BITMAP_HASH_CACHE;
@@ -158,6 +167,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
 	if (argc)
 		usage_with_options(builtin_multi_pack_index_write_usage,
 				   options);
+	source = handle_object_dir_option(repo);
 
 	FREE_AND_NULL(options);
 
@@ -166,7 +176,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
 
 		read_packs_from_stdin(&packs);
 
-		ret = write_midx_file_only(repo, opts.object_dir, &packs,
+		ret = write_midx_file_only(source, &packs,
 					   opts.preferred_pack,
 					   opts.refs_snapshot, opts.flags);
 
@@ -177,7 +187,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
 
 	}
 
-	ret = write_midx_file(repo, opts.object_dir, opts.preferred_pack,
+	ret = write_midx_file(source, opts.preferred_pack,
 			      opts.refs_snapshot, opts.flags);
 
 	free(opts.refs_snapshot);
@@ -194,6 +204,8 @@ static int cmd_multi_pack_index_verify(int argc, const char **argv,
 			N_("force progress reporting"), MIDX_PROGRESS),
 		OPT_END(),
 	};
+	struct odb_source *source;
+
 	options = add_common_options(builtin_multi_pack_index_verify_options);
 
 	trace2_cmd_mode(argv[0]);
@@ -206,10 +218,11 @@ static int cmd_multi_pack_index_verify(int argc, const char **argv,
 	if (argc)
 		usage_with_options(builtin_multi_pack_index_verify_usage,
 				   options);
+	source = handle_object_dir_option(the_repository);
 
 	FREE_AND_NULL(options);
 
-	return verify_midx_file(the_repository, opts.object_dir, opts.flags);
+	return verify_midx_file(source, opts.flags);
 }
 
 static int cmd_multi_pack_index_expire(int argc, const char **argv,
@@ -222,6 +235,8 @@ static int cmd_multi_pack_index_expire(int argc, const char **argv,
 			N_("force progress reporting"), MIDX_PROGRESS),
 		OPT_END(),
 	};
+	struct odb_source *source;
+
 	options = add_common_options(builtin_multi_pack_index_expire_options);
 
 	trace2_cmd_mode(argv[0]);
@@ -234,10 +249,11 @@ static int cmd_multi_pack_index_expire(int argc, const char **argv,
 	if (argc)
 		usage_with_options(builtin_multi_pack_index_expire_usage,
 				   options);
+	source = handle_object_dir_option(the_repository);
 
 	FREE_AND_NULL(options);
 
-	return expire_midx_packs(the_repository, opts.object_dir, opts.flags);
+	return expire_midx_packs(source, opts.flags);
 }
 
 static int cmd_multi_pack_index_repack(int argc, const char **argv,
@@ -252,6 +268,7 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv,
 		  N_("force progress reporting"), MIDX_PROGRESS),
 		OPT_END(),
 	};
+	struct odb_source *source;
 
 	options = add_common_options(builtin_multi_pack_index_repack_options);
 
@@ -266,11 +283,11 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv,
 	if (argc)
 		usage_with_options(builtin_multi_pack_index_repack_usage,
 				   options);
+	source = handle_object_dir_option(the_repository);
 
 	FREE_AND_NULL(options);
 
-	return midx_repack(the_repository, opts.object_dir,
-			   (size_t)opts.batch_size, opts.flags);
+	return midx_repack(source, (size_t)opts.batch_size, opts.flags);
 }
 
 int cmd_multi_pack_index(int argc,
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 74512e5..615f7d1 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -339,10 +339,9 @@ static int cmp_by_tag_and_age(const void *a_, const void *b_)
 	return a->taggerdate != b->taggerdate;
 }
 
-static int name_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
-		    int flags UNUSED, void *cb_data)
+static int name_ref(const struct reference *ref, void *cb_data)
 {
-	struct object *o = parse_object(the_repository, oid);
+	struct object *o = parse_object(the_repository, ref->oid);
 	struct name_ref_data *data = cb_data;
 	int can_abbreviate_output = data->tags_only && data->name_only;
 	int deref = 0;
@@ -350,14 +349,14 @@ static int name_ref(const char *path, const char *referent UNUSED, const struct
 	struct commit *commit = NULL;
 	timestamp_t taggerdate = TIME_MAX;
 
-	if (data->tags_only && !starts_with(path, "refs/tags/"))
+	if (data->tags_only && !starts_with(ref->name, "refs/tags/"))
 		return 0;
 
 	if (data->exclude_filters.nr) {
 		struct string_list_item *item;
 
 		for_each_string_list_item(item, &data->exclude_filters) {
-			if (subpath_matches(path, item->string) >= 0)
+			if (subpath_matches(ref->name, item->string) >= 0)
 				return 0;
 		}
 	}
@@ -378,7 +377,7 @@ static int name_ref(const char *path, const char *referent UNUSED, const struct
 			 * shouldn't stop when seeing 'refs/tags/v1.4' matches
 			 * 'refs/tags/v*'.  We should show it as 'v1.4'.
 			 */
-			switch (subpath_matches(path, item->string)) {
+			switch (subpath_matches(ref->name, item->string)) {
 			case -1: /* did not match */
 				break;
 			case 0: /* matched fully */
@@ -406,13 +405,13 @@ static int name_ref(const char *path, const char *referent UNUSED, const struct
 	}
 	if (o && o->type == OBJ_COMMIT) {
 		commit = (struct commit *)o;
-		from_tag = starts_with(path, "refs/tags/");
+		from_tag = starts_with(ref->name, "refs/tags/");
 		if (taggerdate == TIME_MAX)
 			taggerdate = commit->date;
 	}
 
-	add_to_tip_table(oid, path, can_abbreviate_output, commit, taggerdate,
-			 from_tag, deref);
+	add_to_tip_table(ref->oid, ref->name, can_abbreviate_output,
+			 commit, taggerdate, from_tag, deref);
 	return 0;
 }
 
diff --git a/builtin/notes.c b/builtin/notes.c
index 6fb4144..9af602b 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -376,18 +376,19 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
 
 	while (strbuf_getline_lf(&buf, stdin) != EOF) {
 		struct object_id from_obj, to_obj;
-		struct strbuf **split;
+		struct string_list split = STRING_LIST_INIT_NODUP;
 		int err;
 
-		split = strbuf_split(&buf, ' ');
-		if (!split[0] || !split[1])
+		string_list_split_in_place_f(&split, buf.buf, " ", -1,
+					     STRING_LIST_SPLIT_TRIM);
+		if (split.nr < 2)
 			die(_("malformed input line: '%s'."), buf.buf);
-		strbuf_rtrim(split[0]);
-		strbuf_rtrim(split[1]);
-		if (repo_get_oid(the_repository, split[0]->buf, &from_obj))
-			die(_("failed to resolve '%s' as a valid ref."), split[0]->buf);
-		if (repo_get_oid(the_repository, split[1]->buf, &to_obj))
-			die(_("failed to resolve '%s' as a valid ref."), split[1]->buf);
+		if (repo_get_oid(the_repository, split.items[0].string, &from_obj))
+			die(_("failed to resolve '%s' as a valid ref."),
+			    split.items[0].string);
+		if (repo_get_oid(the_repository, split.items[1].string, &to_obj))
+			die(_("failed to resolve '%s' as a valid ref."),
+			    split.items[1].string);
 
 		if (rewrite_cmd)
 			err = copy_note_for_rewrite(c, &from_obj, &to_obj);
@@ -397,11 +398,11 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
 
 		if (err) {
 			error(_("failed to copy notes from '%s' to '%s'"),
-			      split[0]->buf, split[1]->buf);
+			      split.items[0].string, split.items[1].string);
 			ret = 1;
 		}
 
-		strbuf_list_free(split);
+		string_list_clear(&split, 0);
 	}
 
 	if (!rewrite_cmd) {
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index ff6900b..7937106 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -831,15 +831,14 @@ static enum write_one_status write_one(struct hashfile *f,
 	return WRITE_ONE_WRITTEN;
 }
 
-static int mark_tagged(const char *path UNUSED, const char *referent UNUSED, const struct object_id *oid,
-		       int flag UNUSED, void *cb_data UNUSED)
+static int mark_tagged(const struct reference *ref, void *cb_data UNUSED)
 {
 	struct object_id peeled;
-	struct object_entry *entry = packlist_find(&to_pack, oid);
+	struct object_entry *entry = packlist_find(&to_pack, ref->oid);
 
 	if (entry)
 		entry->tagged = 1;
-	if (!peel_iterated_oid(the_repository, oid, &peeled)) {
+	if (!reference_get_peeled_oid(the_repository, ref, &peeled)) {
 		entry = packlist_find(&to_pack, &peeled);
 		if (entry)
 			entry->tagged = 1;
@@ -1706,8 +1705,8 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
 				     uint32_t found_mtime)
 {
 	int want;
+	struct packfile_list_entry *e;
 	struct odb_source *source;
-	struct list_head *pos;
 
 	if (!exclude && local) {
 		/*
@@ -1716,7 +1715,7 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
 		 */
 		struct odb_source *source = the_repository->objects->sources->next;
 		for (; source; source = source->next)
-			if (has_loose_object(source, oid))
+			if (odb_source_loose_has_object(source, oid))
 				return 0;
 	}
 
@@ -1741,19 +1740,18 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
 		struct multi_pack_index *m = get_multi_pack_index(source);
 		struct pack_entry e;
 
-		if (m && fill_midx_entry(the_repository, oid, &e, m)) {
+		if (m && fill_midx_entry(m, oid, &e)) {
 			want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime);
 			if (want != -1)
 				return want;
 		}
 	}
 
-	list_for_each(pos, get_packed_git_mru(the_repository)) {
-		struct packed_git *p = list_entry(pos, struct packed_git, mru);
+	for (e = the_repository->objects->packfiles->packs.head; e; e = e->next) {
+		struct packed_git *p = e->pack;
 		want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
 		if (!exclude && want > 0)
-			list_move(&p->mru,
-				  get_packed_git_mru(the_repository));
+			packfile_list_prepend(&the_repository->objects->packfiles->packs, p);
 		if (want != -1)
 			return want;
 	}
@@ -3306,13 +3304,13 @@ static void add_tag_chain(const struct object_id *oid)
 	}
 }
 
-static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, const struct object_id *oid,
-		       int flag UNUSED, void *cb_data UNUSED)
+static int add_ref_tag(const struct reference *ref, void *cb_data UNUSED)
 {
 	struct object_id peeled;
 
-	if (!peel_iterated_oid(the_repository, oid, &peeled) && obj_is_packed(&peeled))
-		add_tag_chain(oid);
+	if (!reference_get_peeled_oid(the_repository, ref, &peeled) &&
+	    obj_is_packed(&peeled))
+		add_tag_chain(ref->oid);
 	return 0;
 }
 
@@ -3835,7 +3833,6 @@ static void read_packs_list_from_stdin(struct rev_info *revs)
 	struct string_list include_packs = STRING_LIST_INIT_DUP;
 	struct string_list exclude_packs = STRING_LIST_INIT_DUP;
 	struct string_list_item *item = NULL;
-
 	struct packed_git *p;
 
 	while (strbuf_getline(&buf, stdin) != EOF) {
@@ -3855,7 +3852,7 @@ static void read_packs_list_from_stdin(struct rev_info *revs)
 	string_list_sort(&exclude_packs);
 	string_list_remove_duplicates(&exclude_packs, 0);
 
-	for (p = get_all_packs(the_repository); p; p = p->next) {
+	repo_for_each_pack(the_repository, p) {
 		const char *pack_name = pack_basename(p);
 
 		if ((item = string_list_lookup(&include_packs, pack_name)))
@@ -3979,7 +3976,7 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type
 			int found = 0;
 
 			for (; !found && source; source = source->next)
-				if (has_loose_object(source, oid))
+				if (odb_source_loose_has_object(source, oid))
 					found = 1;
 
 			/*
@@ -4105,7 +4102,7 @@ static void enumerate_and_traverse_cruft_objects(struct string_list *fresh_packs
 	 * Re-mark only the fresh packs as kept so that objects in
 	 * unknown packs do not halt the reachability traversal early.
 	 */
-	for (p = get_all_packs(the_repository); p; p = p->next)
+	repo_for_each_pack(the_repository, p)
 		p->pack_keep_in_core = 0;
 	mark_pack_kept_in_core(fresh_packs, 1);
 
@@ -4142,7 +4139,7 @@ static void read_cruft_objects(void)
 	string_list_sort(&discard_packs);
 	string_list_sort(&fresh_packs);
 
-	for (p = get_all_packs(the_repository); p; p = p->next) {
+	repo_for_each_pack(the_repository, p) {
 		const char *pack_name = pack_basename(p);
 		struct string_list_item *item;
 
@@ -4390,26 +4387,27 @@ static void add_unreachable_loose_objects(struct rev_info *revs)
 
 static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid)
 {
-	static struct packed_git *last_found = (void *)1;
+	static struct packed_git *last_found = NULL;
 	struct packed_git *p;
 
-	p = (last_found != (void *)1) ? last_found :
-					get_all_packs(the_repository);
+	if (last_found && find_pack_entry_one(oid, last_found))
+		return 1;
 
-	while (p) {
-		if ((!p->pack_local || p->pack_keep ||
-				p->pack_keep_in_core) &&
-			find_pack_entry_one(oid, p)) {
+	repo_for_each_pack(the_repository, p) {
+		/*
+		 * We have already checked `last_found`, so there is no need to
+		 * re-check here.
+		 */
+		if (p == last_found)
+			continue;
+
+		if ((!p->pack_local || p->pack_keep || p->pack_keep_in_core) &&
+		    find_pack_entry_one(oid, p)) {
 			last_found = p;
 			return 1;
 		}
-		if (p == last_found)
-			p = get_all_packs(the_repository);
-		else
-			p = p->next;
-		if (p == last_found)
-			p = p->next;
 	}
+
 	return 0;
 }
 
@@ -4441,7 +4439,7 @@ static void loosen_unused_packed_objects(void)
 	uint32_t loosened_objects_nr = 0;
 	struct object_id oid;
 
-	for (p = get_all_packs(the_repository); p; p = p->next) {
+	repo_for_each_pack(the_repository, p) {
 		if (!p->pack_local || p->pack_keep || p->pack_keep_in_core)
 			continue;
 
@@ -4528,19 +4526,16 @@ static void record_recent_commit(struct commit *commit, void *data UNUSED)
 	oid_array_append(&recent_objects, &commit->object.oid);
 }
 
-static int mark_bitmap_preferred_tip(const char *refname,
-				     const char *referent UNUSED,
-				     const struct object_id *oid,
-				     int flags UNUSED,
-				     void *data UNUSED)
+static int mark_bitmap_preferred_tip(const struct reference *ref, void *data UNUSED)
 {
+	const struct object_id *maybe_peeled = ref->oid;
 	struct object_id peeled;
 	struct object *object;
 
-	if (!peel_iterated_oid(the_repository, oid, &peeled))
-		oid = &peeled;
+	if (!reference_get_peeled_oid(the_repository, ref, &peeled))
+		maybe_peeled = &peeled;
 
-	object = parse_object_or_die(the_repository, oid, refname);
+	object = parse_object_or_die(the_repository, maybe_peeled, ref->name);
 	if (object->type == OBJ_COMMIT)
 		object->flags |= NEEDS_BITMAP;
 
@@ -4650,7 +4645,7 @@ static void get_object_list_path_walk(struct rev_info *revs)
 		die(_("failed to pack objects via path-walk"));
 }
 
-static void get_object_list(struct rev_info *revs, int ac, const char **av)
+static void get_object_list(struct rev_info *revs, struct strvec *argv)
 {
 	struct setup_revision_opt s_r_opt = {
 		.allow_exclude_promisor_objects = 1,
@@ -4660,7 +4655,7 @@ static void get_object_list(struct rev_info *revs, int ac, const char **av)
 	int save_warning;
 
 	save_commit_buffer = 0;
-	setup_revisions(ac, av, revs, &s_r_opt);
+	setup_revisions_from_strvec(argv, revs, &s_r_opt);
 
 	/* make sure shallows are read */
 	is_repository_shallow(the_repository);
@@ -4747,7 +4742,7 @@ static void add_extra_kept_packs(const struct string_list *names)
 	if (!names->nr)
 		return;
 
-	for (p = get_all_packs(the_repository); p; p = p->next) {
+	repo_for_each_pack(the_repository, p) {
 		const char *name = basename(p->pack_name);
 		int i;
 
@@ -5186,7 +5181,8 @@ int cmd_pack_objects(int argc,
 	add_extra_kept_packs(&keep_pack_list);
 	if (ignore_packed_keep_on_disk) {
 		struct packed_git *p;
-		for (p = get_all_packs(the_repository); p; p = p->next)
+
+		repo_for_each_pack(the_repository, p)
 			if (p->pack_local && p->pack_keep)
 				break;
 		if (!p) /* no keep-able packs found */
@@ -5199,7 +5195,8 @@ int cmd_pack_objects(int argc,
 		 * it also covers non-local objects
 		 */
 		struct packed_git *p;
-		for (p = get_all_packs(the_repository); p; p = p->next) {
+
+		repo_for_each_pack(the_repository, p) {
 			if (!p->pack_local) {
 				have_non_local_packs = 1;
 				break;
@@ -5229,7 +5226,7 @@ int cmd_pack_objects(int argc,
 			revs.include_check = is_not_in_promisor_pack;
 			revs.include_check_obj = is_not_in_promisor_pack_obj;
 		}
-		get_object_list(&revs, rp.nr, rp.v);
+		get_object_list(&revs, &rp);
 		release_revisions(&revs);
 	}
 	cleanup_preferred_base();
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index 5d5ae4a..e4ecf77 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -566,27 +566,23 @@ static struct pack_list * add_pack(struct packed_git *p)
 
 static struct pack_list * add_pack_file(const char *filename)
 {
-	struct packed_git *p = get_all_packs(the_repository);
+	struct packed_git *p;
 
 	if (strlen(filename) < 40)
 		die("Bad pack filename: %s", filename);
 
-	while (p) {
+	repo_for_each_pack(the_repository, p)
 		if (strstr(p->pack_name, filename))
 			return add_pack(p);
-		p = p->next;
-	}
 	die("Filename %s not found in packed_git", filename);
 }
 
 static void load_all(void)
 {
-	struct packed_git *p = get_all_packs(the_repository);
+	struct packed_git *p;
 
-	while (p) {
+	repo_for_each_pack(the_repository, p)
 		add_pack(p);
-		p = p->next;
-	}
 }
 
 int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) {
diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index 5e28d0f..3446b84 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -1,60 +1,16 @@
 #include "builtin.h"
-#include "config.h"
-#include "environment.h"
 #include "gettext.h"
-#include "parse-options.h"
-#include "refs.h"
-#include "revision.h"
-
-static char const * const pack_refs_usage[] = {
-	N_("git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude <pattern>]"),
-	NULL
-};
+#include "pack-refs.h"
 
 int cmd_pack_refs(int argc,
 		  const char **argv,
 		  const char *prefix,
 		  struct repository *repo)
 {
-	struct ref_exclusions excludes = REF_EXCLUSIONS_INIT;
-	struct string_list included_refs = STRING_LIST_INIT_NODUP;
-	struct pack_refs_opts pack_refs_opts = {
-		.exclusions = &excludes,
-		.includes = &included_refs,
-		.flags = PACK_REFS_PRUNE,
+	static char const * const pack_refs_usage[] = {
+		N_("git pack-refs " PACK_REFS_OPTS),
+		NULL
 	};
-	struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP;
-	struct string_list_item *item;
-	int pack_all = 0;
-	int ret;
 
-	struct option opts[] = {
-		OPT_BOOL(0, "all",   &pack_all, N_("pack everything")),
-		OPT_BIT(0, "prune", &pack_refs_opts.flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE),
-		OPT_BIT(0, "auto", &pack_refs_opts.flags, N_("auto-pack refs as needed"), PACK_REFS_AUTO),
-		OPT_STRING_LIST(0, "include", pack_refs_opts.includes, N_("pattern"),
-			N_("references to include")),
-		OPT_STRING_LIST(0, "exclude", &option_excluded_refs, N_("pattern"),
-			N_("references to exclude")),
-		OPT_END(),
-	};
-	repo_config(repo, git_default_config, NULL);
-	if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
-		usage_with_options(pack_refs_usage, opts);
-
-	for_each_string_list_item(item, &option_excluded_refs)
-		add_ref_exclusion(pack_refs_opts.exclusions, item->string);
-
-	if (pack_all)
-		string_list_append(pack_refs_opts.includes, "*");
-
-	if (!pack_refs_opts.includes->nr)
-		string_list_append(pack_refs_opts.includes, "refs/tags/*");
-
-	ret = refs_pack_refs(get_main_ref_store(repo), &pack_refs_opts);
-
-	clear_ref_exclusions(&excludes);
-	string_list_clear(&included_refs, 0);
-	string_list_clear(&option_excluded_refs, 0);
-	return ret;
+	return pack_refs_core(argc, argv, prefix, repo, pack_refs_usage);
 }
diff --git a/builtin/push.c b/builtin/push.c
index d0794b7..5b6cebb 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -27,7 +27,7 @@ static const char * const push_usage[] = {
 	NULL,
 };
 
-static int push_use_color = -1;
+static enum git_colorbool push_use_color = GIT_COLOR_UNKNOWN;
 static char push_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_RESET,
 	GIT_COLOR_RED,	/* ERROR */
diff --git a/builtin/range-diff.c b/builtin/range-diff.c
index a563abf..e54c0f7 100644
--- a/builtin/range-diff.c
+++ b/builtin/range-diff.c
@@ -6,6 +6,8 @@
 #include "parse-options.h"
 #include "range-diff.h"
 #include "config.h"
+#include "parse.h"
+#include "color.h"
 
 
 static const char * const builtin_range_diff_usage[] = {
@@ -15,18 +17,34 @@ N_("git range-diff [<options>] <base> <old-tip> <new-tip>"),
 NULL
 };
 
+static int parse_max_memory(const struct option *opt, const char *arg, int unset)
+{
+	size_t *max_memory = opt->value;
+	uintmax_t val;
+
+	if (unset)
+		return 0;
+
+	if (!git_parse_unsigned(arg, &val, SIZE_MAX))
+		return error(_("invalid max-memory value: %s"), arg);
+
+	*max_memory = (size_t)val;
+	return 0;
+}
+
 int cmd_range_diff(int argc,
 		   const char **argv,
 		   const char *prefix,
 		   struct repository *repo UNUSED)
 {
 	struct diff_options diffopt = { NULL };
-	struct strvec other_arg = STRVEC_INIT;
+	struct strvec log_arg = STRVEC_INIT;
 	struct strvec diff_merges_arg = STRVEC_INIT;
 	struct range_diff_options range_diff_opts = {
 		.creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT,
+		.max_memory = RANGE_DIFF_MAX_MEMORY_DEFAULT,
 		.diffopt = &diffopt,
-		.other_arg = &other_arg
+		.log_arg = &log_arg
 	};
 	int simple_color = -1, left_only = 0, right_only = 0;
 	struct option range_diff_options[] = {
@@ -35,11 +53,15 @@ int cmd_range_diff(int argc,
 			    N_("percentage by which creation is weighted")),
 		OPT_BOOL(0, "no-dual-color", &simple_color,
 			    N_("use simple diff colors")),
-		OPT_PASSTHRU_ARGV(0, "notes", &other_arg,
+		OPT_PASSTHRU_ARGV(0, "notes", &log_arg,
 				  N_("notes"), N_("passed to 'git log'"),
 				  PARSE_OPT_OPTARG),
 		OPT_PASSTHRU_ARGV(0, "diff-merges", &diff_merges_arg,
 				  N_("style"), N_("passed to 'git log'"), 0),
+		OPT_CALLBACK(0, "max-memory", &range_diff_opts.max_memory,
+			     N_("size"),
+			     N_("maximum memory for cost matrix (default 4G)"),
+			     parse_max_memory),
 		OPT_PASSTHRU_ARGV(0, "remerge-diff", &diff_merges_arg, NULL,
 				  N_("passed to 'git log'"), PARSE_OPT_NOARG),
 		OPT_BOOL(0, "left-only", &left_only,
@@ -66,12 +88,12 @@ int cmd_range_diff(int argc,
 
 	/* force color when --dual-color was used */
 	if (!simple_color)
-		diffopt.use_color = 1;
+		diffopt.use_color = GIT_COLOR_ALWAYS;
 
 	/* If `--diff-merges` was specified, imply `--merges` */
 	if (diff_merges_arg.nr) {
 		range_diff_opts.include_merges = 1;
-		strvec_pushv(&other_arg, diff_merges_arg.v);
+		strvec_pushv(&log_arg, diff_merges_arg.v);
 	}
 
 	for (i = 0; i < argc; i++)
@@ -103,7 +125,7 @@ int cmd_range_diff(int argc,
 		strbuf_addf(&range1, "%s..%s", argv[0], argv[1]);
 		strbuf_addf(&range2, "%s..%s", argv[0], argv[2]);
 
-		strvec_pushv(&other_arg, argv +
+		strvec_pushv(&log_arg, argv +
 			     (dash_dash < 0 ? 3 : dash_dash));
 	} else if (dash_dash == 2 ||
 		   (dash_dash < 0 && argc > 1 &&
@@ -123,7 +145,7 @@ int cmd_range_diff(int argc,
 		strbuf_addstr(&range1, argv[0]);
 		strbuf_addstr(&range2, argv[1]);
 
-		strvec_pushv(&other_arg, argv +
+		strvec_pushv(&log_arg, argv +
 			     (dash_dash < 0 ? 2 : dash_dash));
 	} else if (dash_dash == 1 ||
 		   (dash_dash < 0 && argc > 0 &&
@@ -154,7 +176,7 @@ int cmd_range_diff(int argc,
 		strbuf_addf(&range1, "%s..%.*s", b, a_len, a);
 		strbuf_addf(&range2, "%.*s..%s", a_len, a, b);
 
-		strvec_pushv(&other_arg, argv +
+		strvec_pushv(&log_arg, argv +
 			     (dash_dash < 0 ? 1 : dash_dash));
 	} else
 		usage_msg_opt(_("need two commit ranges"),
@@ -166,7 +188,7 @@ int cmd_range_diff(int argc,
 	range_diff_opts.right_only = right_only;
 	res = show_range_diff(range1.buf, range2.buf, &range_diff_opts);
 
-	strvec_clear(&other_arg);
+	strvec_clear(&log_arg);
 	strvec_clear(&diff_merges_arg);
 	strbuf_release(&range1);
 	strbuf_release(&range2);
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 3c85768..c468828 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -299,8 +299,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
 			     oid_to_hex(&opts->restrict_revision->object.oid));
 
 	ret = sequencer_make_script(the_repository, &todo_list.buf,
-				    make_script_args.nr, make_script_args.v,
-				    flags);
+				    &make_script_args, flags);
 	if (ret) {
 		error(_("could not generate todo list"));
 		goto cleanup;
@@ -1242,6 +1241,9 @@ int cmd_rebase(int argc,
 					 builtin_rebase_usage,
 					 builtin_rebase_options);
 
+#ifndef WITH_BREAKING_CHANGES
+	warn_on_auto_comment_char = true;
+#endif /* !WITH_BREAKING_CHANGES */
 	prepare_repo_settings(the_repository);
 	the_repository->settings.command_requires_full_index = 0;
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 1113137..e8ee0e7 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -305,13 +305,12 @@ static void show_ref(const char *path, const struct object_id *oid)
 	}
 }
 
-static int show_ref_cb(const char *path_full, const char *referent UNUSED, const struct object_id *oid,
-		       int flag UNUSED, void *data)
+static int show_ref_cb(const struct reference *ref, void *data)
 {
 	struct oidset *seen = data;
-	const char *path = strip_namespace(path_full);
+	const char *path = strip_namespace(ref->name);
 
-	if (ref_is_hidden(path, path_full, &hidden_refs))
+	if (ref_is_hidden(path, ref->name, &hidden_refs))
 		return 0;
 
 	/*
@@ -320,13 +319,13 @@ static int show_ref_cb(const char *path_full, const char *referent UNUSED, const
 	 * transfer but will otherwise ignore them.
 	 */
 	if (!path) {
-		if (oidset_insert(seen, oid))
+		if (oidset_insert(seen, ref->oid))
 			return 0;
 		path = ".have";
 	} else {
-		oidset_insert(seen, oid);
+		oidset_insert(seen, ref->oid);
 	}
-	show_ref(path, oid);
+	show_ref(path, ref->oid);
 	return 0;
 }
 
@@ -2389,7 +2388,7 @@ static const char *unpack(int err_fd, struct shallow_info *si)
 		status = finish_command(&child);
 		if (status)
 			return "index-pack abnormal exit";
-		reprepare_packed_git(the_repository);
+		odb_reprepare(the_repository->objects);
 	}
 	return NULL;
 }
diff --git a/builtin/reflog.c b/builtin/reflog.c
index c8f6b93..dcbfe89 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -418,6 +418,8 @@ static int cmd_reflog_write(int argc, const char **argv, const char *prefix,
 	const char *ref, *message;
 	int ret;
 
+	repo_config(repo, git_ident_config, NULL);
+
 	argc = parse_options(argc, argv, prefix, options, reflog_write_usage, 0);
 	if (argc != 4)
 		usage_with_options(reflog_write_usage, options);
diff --git a/builtin/refs.c b/builtin/refs.c
index c7ad0a2..3064f88 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -2,10 +2,13 @@
 #include "builtin.h"
 #include "config.h"
 #include "fsck.h"
+#include "pack-refs.h"
 #include "parse-options.h"
 #include "refs.h"
 #include "strbuf.h"
 #include "worktree.h"
+#include "for-each-ref.h"
+#include "refs/refs-internal.h"
 
 #define REFS_MIGRATE_USAGE \
 	N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]")
@@ -13,6 +16,12 @@
 #define REFS_VERIFY_USAGE \
 	N_("git refs verify [--strict] [--verbose]")
 
+#define REFS_EXISTS_USAGE \
+	N_("git refs exists <ref>")
+
+#define REFS_OPTIMIZE_USAGE \
+	N_("git refs optimize " PACK_REFS_OPTS)
+
 static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
 			    struct repository *repo UNUSED)
 {
@@ -101,6 +110,70 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
 	return ret;
 }
 
+static int cmd_refs_list(int argc, const char **argv, const char *prefix,
+			   struct repository *repo)
+{
+	static char const * const refs_list_usage[] = {
+		N_("git refs list " COMMON_USAGE_FOR_EACH_REF),
+		NULL
+	};
+
+	return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
+}
+
+static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
+			   struct repository *repo UNUSED)
+{
+	struct strbuf unused_referent = STRBUF_INIT;
+	struct object_id unused_oid;
+	unsigned int unused_type;
+	int failure_errno = 0;
+	const char *ref;
+	int ret = 0;
+	const char * const exists_usage[] = {
+		REFS_EXISTS_USAGE,
+		NULL,
+	};
+	struct option options[] = {
+		OPT_END(),
+	};
+
+	argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
+	if (argc != 1)
+		die(_("'git refs exists' requires a reference"));
+
+	ref = *argv++;
+	if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
+			      &unused_oid, &unused_referent, &unused_type,
+			      &failure_errno)) {
+		if (failure_errno == ENOENT || failure_errno == EISDIR) {
+			error(_("reference does not exist"));
+			ret = 2;
+		} else {
+			errno = failure_errno;
+			error_errno(_("failed to look up reference"));
+			ret = 1;
+		}
+
+		goto out;
+	}
+
+out:
+	strbuf_release(&unused_referent);
+	return ret;
+}
+
+static int cmd_refs_optimize(int argc, const char **argv, const char *prefix,
+			     struct repository *repo)
+{
+	static char const * const refs_optimize_usage[] = {
+		REFS_OPTIMIZE_USAGE,
+		NULL
+	};
+
+	return pack_refs_core(argc, argv, prefix, repo, refs_optimize_usage);
+}
+
 int cmd_refs(int argc,
 	     const char **argv,
 	     const char *prefix,
@@ -109,12 +182,18 @@ int cmd_refs(int argc,
 	const char * const refs_usage[] = {
 		REFS_MIGRATE_USAGE,
 		REFS_VERIFY_USAGE,
+		"git refs list " COMMON_USAGE_FOR_EACH_REF,
+		REFS_EXISTS_USAGE,
+		REFS_OPTIMIZE_USAGE,
 		NULL,
 	};
 	parse_opt_subcommand_fn *fn = NULL;
 	struct option opts[] = {
 		OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
 		OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
+		OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
+		OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists),
+		OPT_SUBCOMMAND("optimize", &fn, cmd_refs_optimize),
 		OPT_END(),
 	};
 
diff --git a/builtin/remote.c b/builtin/remote.c
index 8961ae6..7ffc14b 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1,9 +1,11 @@
 #define USE_THE_REPOSITORY_VARIABLE
-#define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "builtin.h"
+#include "advice.h"
 #include "config.h"
+#include "date.h"
 #include "gettext.h"
+#include "ident.h"
 #include "parse-options.h"
 #include "path.h"
 #include "transport.h"
@@ -182,7 +184,6 @@ static int add(int argc, const char **argv, const char *prefix,
 	struct remote *remote;
 	struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
 	const char *name, *url;
-	int i;
 	int result = 0;
 
 	struct option options[] = {
@@ -233,7 +234,7 @@ static int add(int argc, const char **argv, const char *prefix,
 		strbuf_addf(&buf, "remote.%s.fetch", name);
 		if (track.nr == 0)
 			string_list_append(&track, "*");
-		for (i = 0; i < track.nr; i++) {
+		for (size_t i = 0; i < track.nr; i++) {
 			add_branch(buf.buf, track.items[i].string,
 				   name, mirror, &buf2);
 		}
@@ -569,17 +570,14 @@ struct branches_for_remote {
 	struct known_remotes *keep;
 };
 
-static int add_branch_for_removal(const char *refname,
-				  const char *referent UNUSED,
-				  const struct object_id *oid UNUSED,
-				  int flags UNUSED, void *cb_data)
+static int add_branch_for_removal(const struct reference *ref, void *cb_data)
 {
 	struct branches_for_remote *branches = cb_data;
 	struct refspec_item refspec;
 	struct known_remote *kr;
 
 	memset(&refspec, 0, sizeof(refspec));
-	refspec.dst = (char *)refname;
+	refspec.dst = (char *)ref->name;
 	if (remote_find_tracking(branches->remote, &refspec))
 		return 0;
 	free(refspec.src);
@@ -587,7 +585,7 @@ static int add_branch_for_removal(const char *refname,
 	/* don't delete a branch if another remote also uses it */
 	for (kr = branches->keep->list; kr; kr = kr->next) {
 		memset(&refspec, 0, sizeof(refspec));
-		refspec.dst = (char *)refname;
+		refspec.dst = (char *)ref->name;
 		if (!remote_find_tracking(kr->remote, &refspec)) {
 			free(refspec.src);
 			return 0;
@@ -595,16 +593,16 @@ static int add_branch_for_removal(const char *refname,
 	}
 
 	/* don't delete non-remote-tracking refs */
-	if (!starts_with(refname, "refs/remotes/")) {
+	if (!starts_with(ref->name, "refs/remotes/")) {
 		/* advise user how to delete local branches */
-		if (starts_with(refname, "refs/heads/"))
+		if (starts_with(ref->name, "refs/heads/"))
 			string_list_append(branches->skipped,
-					   abbrev_branch(refname));
+					   abbrev_branch(ref->name));
 		/* silently skip over other non-remote refs */
 		return 0;
 	}
 
-	string_list_append(branches->branches, refname);
+	string_list_append(branches->branches, ref->name);
 
 	return 0;
 }
@@ -612,53 +610,169 @@ static int add_branch_for_removal(const char *refname,
 struct rename_info {
 	const char *old_name;
 	const char *new_name;
-	struct string_list *remote_branches;
-	uint32_t symrefs_nr;
+	struct ref_transaction *transaction;
+	struct progress *progress;
+	struct strbuf *err;
+	uint32_t progress_nr;
+	uint64_t index;
 };
 
-static int read_remote_branches(const char *refname, const char *referent UNUSED,
-				const struct object_id *oid UNUSED,
-				int flags UNUSED, void *cb_data)
+static void compute_renamed_ref(struct rename_info *rename,
+				const char *refname,
+				struct strbuf *out)
+{
+	strbuf_reset(out);
+	strbuf_addstr(out, refname);
+	strbuf_splice(out, strlen("refs/remotes/"), strlen(rename->old_name),
+		      rename->new_name, strlen(rename->new_name));
+}
+
+static int rename_one_reflog_entry(const char *old_refname,
+				   struct object_id *old_oid,
+				   struct object_id *new_oid,
+				   const char *committer,
+				   timestamp_t timestamp, int tz,
+				   const char *msg, void *cb_data)
 {
 	struct rename_info *rename = cb_data;
-	struct strbuf buf = STRBUF_INIT;
-	struct string_list_item *item;
-	int flag;
-	const char *symref;
+	struct strbuf new_refname = STRBUF_INIT;
+	struct strbuf identity = STRBUF_INIT;
+	struct strbuf name = STRBUF_INIT;
+	struct strbuf mail = STRBUF_INIT;
+	struct ident_split ident;
+	const char *date;
+	int error;
 
-	strbuf_addf(&buf, "refs/remotes/%s/", rename->old_name);
-	if (starts_with(refname, buf.buf)) {
-		item = string_list_append(rename->remote_branches, refname);
-		symref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
-						 refname, RESOLVE_REF_READING,
-						 NULL, &flag);
-		if (symref && (flag & REF_ISSYMREF)) {
-			item->util = xstrdup(symref);
-			rename->symrefs_nr++;
-		} else {
-			item->util = NULL;
-		}
+	compute_renamed_ref(rename, old_refname, &new_refname);
+
+	if (split_ident_line(&ident, committer, strlen(committer)) < 0) {
+		error = -1;
+		goto out;
 	}
-	strbuf_release(&buf);
 
-	return 0;
+	strbuf_add(&name, ident.name_begin, ident.name_end - ident.name_begin);
+	strbuf_add(&mail, ident.mail_begin, ident.mail_end - ident.mail_begin);
+
+	date = show_date(timestamp, tz, DATE_MODE(NORMAL));
+	strbuf_addstr(&identity, fmt_ident(name.buf, mail.buf,
+					  WANT_BLANK_IDENT, date, 0));
+
+	error = ref_transaction_update_reflog(rename->transaction, new_refname.buf,
+					      new_oid, old_oid, identity.buf, msg,
+					      rename->index++, rename->err);
+
+out:
+	strbuf_release(&new_refname);
+	strbuf_release(&identity);
+	strbuf_release(&name);
+	strbuf_release(&mail);
+	return error;
+}
+
+static int rename_one_reflog(const char *old_refname,
+			     const struct object_id *old_oid,
+			     struct rename_info *rename)
+{
+	struct strbuf new_refname = STRBUF_INIT;
+	struct strbuf message = STRBUF_INIT;
+	int error;
+
+	if (!refs_reflog_exists(get_main_ref_store(the_repository), old_refname))
+		return 0;
+
+	error = refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+					 old_refname, rename_one_reflog_entry, rename);
+	if (error < 0)
+		goto out;
+
+	compute_renamed_ref(rename, old_refname, &new_refname);
+
+	/*
+	 * Manually write the reflog entry for the now-renamed ref. We cannot
+	 * rely on `rename_one_ref()` to do this for us as that would screw
+	 * over order in which reflog entries are being written.
+	 *
+	 * Furthermore, we only append the entry in case the reference
+	 * resolves. Missing references shouldn't have reflogs anyway.
+	 */
+	strbuf_addf(&message, "remote: renamed %s to %s", old_refname,
+		    new_refname.buf);
+
+	error = ref_transaction_update_reflog(rename->transaction, new_refname.buf,
+					      old_oid, old_oid, git_committer_info(0),
+					      message.buf, rename->index++, rename->err);
+	if (error < 0)
+		return error;
+
+out:
+	strbuf_release(&new_refname);
+	strbuf_release(&message);
+	return error;
+}
+
+static int rename_one_ref(const struct reference *ref, void *cb_data)
+{
+	struct strbuf new_referent = STRBUF_INIT;
+	struct strbuf new_refname = STRBUF_INIT;
+	struct rename_info *rename = cb_data;
+	const struct object_id *oid = ref->oid;
+	const char *referent = ref->target;
+	int error;
+
+	compute_renamed_ref(rename, ref->name, &new_refname);
+
+	if (ref->flags & REF_ISSYMREF) {
+		/*
+		 * Stupidly enough `referent` is not pointing to the immediate
+		 * target of a symref, but it's the recursively resolved value.
+		 * So symrefs pointing to symrefs would be misresolved, and
+		 * unborn symrefs don't have any value for the `referent` at all.
+		 */
+		referent = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+						   ref->name, RESOLVE_REF_NO_RECURSE,
+						   NULL, NULL);
+		compute_renamed_ref(rename, referent, &new_referent);
+		oid = NULL;
+	}
+
+	error = ref_transaction_delete(rename->transaction, ref->name,
+				       oid, referent, REF_NO_DEREF, NULL, rename->err);
+	if (error < 0)
+		goto out;
+
+	error = ref_transaction_update(rename->transaction, new_refname.buf, oid, null_oid(the_hash_algo),
+				       (ref->flags & REF_ISSYMREF) ? new_referent.buf : NULL, NULL,
+				       REF_SKIP_CREATE_REFLOG | REF_NO_DEREF | REF_SKIP_OID_VERIFICATION,
+				       NULL, rename->err);
+	if (error < 0)
+		goto out;
+
+	error = rename_one_reflog(ref->name, oid, rename);
+	if (error < 0)
+		goto out;
+
+	display_progress(rename->progress, ++rename->progress_nr);
+
+out:
+	strbuf_release(&new_referent);
+	strbuf_release(&new_refname);
+	return error;
 }
 
 static int migrate_file(struct remote *remote)
 {
 	struct strbuf buf = STRBUF_INIT;
-	int i;
 
 	strbuf_addf(&buf, "remote.%s.url", remote->name);
-	for (i = 0; i < remote->url.nr; i++)
+	for (size_t i = 0; i < remote->url.nr; i++)
 		repo_config_set_multivar(the_repository, buf.buf, remote->url.v[i], "^$", 0);
 	strbuf_reset(&buf);
 	strbuf_addf(&buf, "remote.%s.push", remote->name);
-	for (i = 0; i < remote->push.nr; i++)
+	for (int i = 0; i < remote->push.nr; i++)
 		repo_config_set_multivar(the_repository, buf.buf, remote->push.items[i].raw, "^$", 0);
 	strbuf_reset(&buf);
 	strbuf_addf(&buf, "remote.%s.fetch", remote->name);
-	for (i = 0; i < remote->fetch.nr; i++)
+	for (int i = 0; i < remote->fetch.nr; i++)
 		repo_config_set_multivar(the_repository, buf.buf, remote->fetch.items[i].raw, "^$", 0);
 #ifndef WITH_BREAKING_CHANGES
 	if (remote->origin == REMOTE_REMOTES)
@@ -730,6 +844,14 @@ static void handle_push_default(const char* old_name, const char* new_name)
 	strbuf_release(&push_default.origin);
 }
 
+static const char conflicting_remote_refs_advice[] = N_(
+	"The remote you are trying to rename has conflicting references in the\n"
+	"new target refspec. This is most likely caused by you trying to nest\n"
+	"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+	"or by unnesting a remote, e.g. the other way round.\n"
+	"\n"
+	"If that is the case, you can address this by first renaming the\n"
+	"remote to a different name.\n");
 
 static int mv(int argc, const char **argv, const char *prefix,
 	      struct repository *repo UNUSED)
@@ -741,11 +863,11 @@ static int mv(int argc, const char **argv, const char *prefix,
 	};
 	struct remote *oldremote, *newremote;
 	struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT,
-		old_remote_context = STRBUF_INIT;
-	struct string_list remote_branches = STRING_LIST_INIT_DUP;
-	struct rename_info rename;
-	int i, refs_renamed_nr = 0, refspec_updated = 0;
-	struct progress *progress = NULL;
+		old_remote_context = STRBUF_INIT, err = STRBUF_INIT;
+	struct rename_info rename = {
+		.err = &err,
+	};
+	int refspecs_need_update = 0;
 	int result = 0;
 
 	argc = parse_options(argc, argv, prefix, options,
@@ -756,8 +878,6 @@ static int mv(int argc, const char **argv, const char *prefix,
 
 	rename.old_name = argv[0];
 	rename.new_name = argv[1];
-	rename.remote_branches = &remote_branches;
-	rename.symrefs_nr = 0;
 
 	oldremote = remote_get(rename.old_name);
 	if (!remote_is_configured(oldremote, 1)) {
@@ -785,19 +905,50 @@ static int mv(int argc, const char **argv, const char *prefix,
 		goto out;
 	}
 
+	strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old_name);
+
+	for (int i = 0; i < oldremote->fetch.nr && !refspecs_need_update; i++)
+		refspecs_need_update = !!strstr(oldremote->fetch.items[i].raw,
+						old_remote_context.buf);
+
+	if (refspecs_need_update) {
+		rename.transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+							       0, &err);
+		if (!rename.transaction)
+			goto out;
+
+		if (show_progress)
+			rename.progress = start_delayed_progress(the_repository,
+								 _("Renaming remote references"), 0);
+
+		strbuf_reset(&buf);
+		strbuf_addf(&buf, "refs/remotes/%s/", rename.old_name);
+
+		result = refs_for_each_rawref_in(get_main_ref_store(the_repository), buf.buf,
+				rename_one_ref, &rename);
+		if (result < 0)
+			die(_("queueing remote ref renames failed: %s"), rename.err->buf);
+
+		result = ref_transaction_prepare(rename.transaction, &err);
+		if (result < 0) {
+			error("renaming remote references failed: %s", err.buf);
+			if (result == REF_TRANSACTION_ERROR_NAME_CONFLICT)
+				advise(conflicting_remote_refs_advice);
+			die(NULL);
+		}
+	}
+
 	if (oldremote->fetch.nr) {
 		strbuf_reset(&buf);
 		strbuf_addf(&buf, "remote.%s.fetch", rename.new_name);
 		repo_config_set_multivar(the_repository, buf.buf, NULL, NULL, CONFIG_FLAGS_MULTI_REPLACE);
-		strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old_name);
-		for (i = 0; i < oldremote->fetch.nr; i++) {
+		for (int i = 0; i < oldremote->fetch.nr; i++) {
 			char *ptr;
 
 			strbuf_reset(&buf2);
 			strbuf_addstr(&buf2, oldremote->fetch.items[i].raw);
 			ptr = strstr(buf2.buf, old_remote_context.buf);
 			if (ptr) {
-				refspec_updated = 1;
 				strbuf_splice(&buf2,
 					      ptr-buf2.buf + strlen(":refs/remotes/"),
 					      strlen(rename.old_name), rename.new_name,
@@ -813,7 +964,7 @@ static int mv(int argc, const char **argv, const char *prefix,
 	}
 
 	read_branches();
-	for (i = 0; i < branch_list.nr; i++) {
+	for (size_t i = 0; i < branch_list.nr; i++) {
 		struct string_list_item *item = branch_list.items + i;
 		struct branch_info *info = item->util;
 		if (info->remote_name && !strcmp(info->remote_name, rename.old_name)) {
@@ -828,83 +979,23 @@ static int mv(int argc, const char **argv, const char *prefix,
 		}
 	}
 
-	if (!refspec_updated)
-		goto out;
+	if (refspecs_need_update) {
+		result = ref_transaction_commit(rename.transaction, &err);
+		if (result < 0)
+			die(_("renaming remote refs failed: %s"), rename.err->buf);
 
-	/*
-	 * First remove symrefs, then rename the rest, finally create
-	 * the new symrefs.
-	 */
-	refs_for_each_ref(get_main_ref_store(the_repository),
-			  read_remote_branches, &rename);
-	if (show_progress) {
-		/*
-		 * Count symrefs twice, since "renaming" them is done by
-		 * deleting and recreating them in two separate passes.
-		 */
-		progress = start_progress(the_repository,
-					  _("Renaming remote references"),
-					  rename.remote_branches->nr + rename.symrefs_nr);
+		stop_progress(&rename.progress);
+
+		handle_push_default(rename.old_name, rename.new_name);
 	}
-	for (i = 0; i < remote_branches.nr; i++) {
-		struct string_list_item *item = remote_branches.items + i;
-		struct strbuf referent = STRBUF_INIT;
-
-		if (refs_read_symbolic_ref(get_main_ref_store(the_repository), item->string,
-					   &referent))
-			continue;
-		if (refs_delete_ref(get_main_ref_store(the_repository), NULL, item->string, NULL, REF_NO_DEREF))
-			die(_("deleting '%s' failed"), item->string);
-
-		strbuf_release(&referent);
-		display_progress(progress, ++refs_renamed_nr);
-	}
-	for (i = 0; i < remote_branches.nr; i++) {
-		struct string_list_item *item = remote_branches.items + i;
-
-		if (item->util)
-			continue;
-		strbuf_reset(&buf);
-		strbuf_addstr(&buf, item->string);
-		strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old_name),
-				rename.new_name, strlen(rename.new_name));
-		strbuf_reset(&buf2);
-		strbuf_addf(&buf2, "remote: renamed %s to %s",
-				item->string, buf.buf);
-		if (refs_rename_ref(get_main_ref_store(the_repository), item->string, buf.buf, buf2.buf))
-			die(_("renaming '%s' failed"), item->string);
-		display_progress(progress, ++refs_renamed_nr);
-	}
-	for (i = 0; i < remote_branches.nr; i++) {
-		struct string_list_item *item = remote_branches.items + i;
-
-		if (!item->util)
-			continue;
-		strbuf_reset(&buf);
-		strbuf_addstr(&buf, item->string);
-		strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old_name),
-				rename.new_name, strlen(rename.new_name));
-		strbuf_reset(&buf2);
-		strbuf_addstr(&buf2, item->util);
-		strbuf_splice(&buf2, strlen("refs/remotes/"), strlen(rename.old_name),
-				rename.new_name, strlen(rename.new_name));
-		strbuf_reset(&buf3);
-		strbuf_addf(&buf3, "remote: renamed %s to %s",
-				item->string, buf.buf);
-		if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, buf3.buf))
-			die(_("creating '%s' failed"), buf.buf);
-		display_progress(progress, ++refs_renamed_nr);
-	}
-	stop_progress(&progress);
-
-	handle_push_default(rename.old_name, rename.new_name);
 
 out:
-	string_list_clear(&remote_branches, 1);
+	ref_transaction_free(rename.transaction);
 	strbuf_release(&old_remote_context);
 	strbuf_release(&buf);
 	strbuf_release(&buf2);
 	strbuf_release(&buf3);
+	strbuf_release(&err);
 	return result;
 }
 
@@ -920,7 +1011,7 @@ static int rm(int argc, const char **argv, const char *prefix,
 	struct string_list branches = STRING_LIST_INIT_DUP;
 	struct string_list skipped = STRING_LIST_INIT_DUP;
 	struct branches_for_remote cb_data;
-	int i, result;
+	int result;
 
 	memset(&cb_data, 0, sizeof(cb_data));
 	cb_data.branches = &branches;
@@ -942,7 +1033,7 @@ static int rm(int argc, const char **argv, const char *prefix,
 	for_each_remote(add_known_remote, &known_remotes);
 
 	read_branches();
-	for (i = 0; i < branch_list.nr; i++) {
+	for (size_t i = 0; i < branch_list.nr; i++) {
 		struct string_list_item *item = branch_list.items + i;
 		struct branch_info *info = item->util;
 		if (info->remote_name && !strcmp(info->remote_name, remote->name)) {
@@ -988,7 +1079,7 @@ static int rm(int argc, const char **argv, const char *prefix,
 			      "Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
 			      "to delete them, use:",
 			      skipped.nr));
-		for (i = 0; i < skipped.nr; i++)
+		for (size_t i = 0; i < skipped.nr; i++)
 			fprintf(stderr, "  git branch -d %s\n",
 				skipped.items[i].string);
 	}
@@ -1031,19 +1122,16 @@ static void free_remote_ref_states(struct ref_states *states)
 	string_list_clear_func(&states->push, clear_push_info);
 }
 
-static int append_ref_to_tracked_list(const char *refname,
-				      const char *referent UNUSED,
-				      const struct object_id *oid UNUSED,
-				      int flags, void *cb_data)
+static int append_ref_to_tracked_list(const struct reference *ref, void *cb_data)
 {
 	struct ref_states *states = cb_data;
 	struct refspec_item refspec;
 
-	if (flags & REF_ISSYMREF)
+	if (ref->flags & REF_ISSYMREF)
 		return 0;
 
 	memset(&refspec, 0, sizeof(refspec));
-	refspec.dst = (char *)refname;
+	refspec.dst = (char *)ref->name;
 	if (!remote_find_tracking(states->remote, &refspec)) {
 		string_list_append(&states->tracked, abbrev_branch(refspec.src));
 		free(refspec.src);
@@ -1166,7 +1254,6 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data)
 	struct branch_info *branch_info = item->util;
 	struct string_list *merge = &branch_info->merge;
 	int width = show_info->width + 4;
-	int i;
 
 	if (branch_info->rebase >= REBASE_TRUE && branch_info->merge.nr > 1) {
 		error(_("invalid branch.%s.merge; cannot rebase onto > 1 branch"),
@@ -1192,7 +1279,7 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data)
 	} else {
 		printf_ln(_("merges with remote %s"), merge->items[0].string);
 	}
-	for (i = 1; i < merge->nr; i++)
+	for (size_t i = 1; i < merge->nr; i++)
 		printf(_("%-*s    and with remote %s\n"), width, "",
 		       merge->items[i].string);
 
@@ -1277,7 +1364,6 @@ static int get_one_entry(struct remote *remote, void *priv)
 	struct string_list *list = priv;
 	struct strbuf remote_info_buf = STRBUF_INIT;
 	struct strvec *url;
-	int i;
 
 	if (remote->url.nr > 0) {
 		struct strbuf promisor_config = STRBUF_INIT;
@@ -1294,8 +1380,7 @@ static int get_one_entry(struct remote *remote, void *priv)
 	} else
 		string_list_append(list, remote->name)->util = NULL;
 	url = push_url_of_remote(remote);
-	for (i = 0; i < url->nr; i++)
-	{
+	for (size_t i = 0; i < url->nr; i++) {
 		strbuf_addf(&remote_info_buf, "%s (push)", url->v[i]);
 		string_list_append(list, remote->name)->util =
 				strbuf_detach(&remote_info_buf, NULL);
@@ -1312,10 +1397,8 @@ static int show_all(void)
 	result = for_each_remote(get_one_entry, &list);
 
 	if (!result) {
-		int i;
-
 		string_list_sort(&list);
-		for (i = 0; i < list.nr; i++) {
+		for (size_t i = 0; i < list.nr; i++) {
 			struct string_list_item *item = list.items + i;
 			if (verbose)
 				printf("%s\t%s\n", item->string,
@@ -1352,7 +1435,7 @@ static int show(int argc, const char **argv, const char *prefix,
 		query_flag = (GET_REF_STATES | GET_HEAD_NAMES | GET_PUSH_REF_STATES);
 
 	for (; argc; argc--, argv++) {
-		int i;
+		size_t i;
 		struct strvec *url;
 
 		get_remote_ref_states(*argv, &info.states, query_flag);
@@ -1458,7 +1541,7 @@ static void report_set_head_auto(const char *remote, const char *head_name,
 static int set_head(int argc, const char **argv, const char *prefix,
 		    struct repository *repo UNUSED)
 {
-	int i, opt_a = 0, opt_d = 0, result = 0, was_detached;
+	int opt_a = 0, opt_d = 0, result = 0, was_detached;
 	struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT,
 		b_local_head = STRBUF_INIT;
 	char *head_name = NULL;
@@ -1492,7 +1575,7 @@ static int set_head(int argc, const char **argv, const char *prefix,
 		else if (states.heads.nr > 1) {
 			result |= error(_("Multiple remote HEAD branches. "
 					  "Please choose one explicitly with:"));
-			for (i = 0; i < states.heads.nr; i++)
+			for (size_t i = 0; i < states.heads.nr; i++)
 				fprintf(stderr, "  git remote set-head %s %s\n",
 					argv[0], states.heads.items[i].string);
 		} else
@@ -1717,7 +1800,7 @@ static int set_branches(int argc, const char **argv, const char *prefix,
 static int get_url(int argc, const char **argv, const char *prefix,
 		   struct repository *repo UNUSED)
 {
-	int i, push_mode = 0, all_mode = 0;
+	int push_mode = 0, all_mode = 0;
 	const char *remotename = NULL;
 	struct remote *remote;
 	struct strvec *url;
@@ -1745,7 +1828,7 @@ static int get_url(int argc, const char **argv, const char *prefix,
 	url = push_mode ? push_url_of_remote(remote) : &remote->url;
 
 	if (all_mode) {
-		for (i = 0; i < url->nr; i++)
+		for (size_t i = 0; i < url->nr; i++)
 			printf_ln("%s", url->v[i]);
 	} else {
 		printf_ln("%s", url->v[0]);
@@ -1757,7 +1840,7 @@ static int get_url(int argc, const char **argv, const char *prefix,
 static int set_url(int argc, const char **argv, const char *prefix,
 		   struct repository *repo UNUSED)
 {
-	int i, push_mode = 0, add_mode = 0, delete_mode = 0;
+	int push_mode = 0, add_mode = 0, delete_mode = 0;
 	int matches = 0, negative_matches = 0;
 	const char *remotename = NULL;
 	const char *newurl = NULL;
@@ -1821,7 +1904,7 @@ static int set_url(int argc, const char **argv, const char *prefix,
 	if (regcomp(&old_regex, oldurl, REG_EXTENDED))
 		die(_("Invalid old URL pattern: %s"), oldurl);
 
-	for (i = 0; i < urlset->nr; i++)
+	for (size_t i = 0; i < urlset->nr; i++)
 		if (!regexec(&old_regex, urlset->v[i], 0, NULL, 0))
 			matches++;
 		else
diff --git a/builtin/repack.c b/builtin/repack.c
index a4def39..cfdb4c0 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -3,27 +3,18 @@
 
 #include "builtin.h"
 #include "config.h"
-#include "dir.h"
 #include "environment.h"
-#include "gettext.h"
-#include "hex.h"
 #include "parse-options.h"
 #include "path.h"
 #include "run-command.h"
 #include "server-info.h"
-#include "strbuf.h"
 #include "string-list.h"
-#include "strvec.h"
 #include "midx.h"
 #include "packfile.h"
 #include "prune-packed.h"
-#include "odb.h"
 #include "promisor-remote.h"
+#include "repack.h"
 #include "shallow.h"
-#include "pack.h"
-#include "pack-bitmap.h"
-#include "refs.h"
-#include "list-objects-filter-options.h"
 
 #define ALL_INTO_ONE 1
 #define LOOSEN_UNREACHABLE 2
@@ -33,8 +24,6 @@
 #define RETAIN_PACK 2
 
 static int pack_everything;
-static int delta_base_offset = 1;
-static int pack_kept_objects = -1;
 static int write_bitmaps = -1;
 static int use_delta_islands;
 static int run_update_server_info = 1;
@@ -53,31 +42,23 @@ static const char incremental_bitmap_conflict_error[] = N_(
 "--no-write-bitmap-index or disable the pack.writeBitmaps configuration."
 );
 
-struct pack_objects_args {
-	char *window;
-	char *window_memory;
-	char *depth;
-	char *threads;
-	unsigned long max_pack_size;
-	int no_reuse_delta;
-	int no_reuse_object;
-	int quiet;
-	int local;
-	int name_hash_version;
-	int path_walk;
-	struct list_objects_filter_options filter_options;
+struct repack_config_ctx {
+	struct pack_objects_args *po_args;
+	struct pack_objects_args *cruft_po_args;
 };
 
 static int repack_config(const char *var, const char *value,
 			 const struct config_context *ctx, void *cb)
 {
-	struct pack_objects_args *cruft_po_args = cb;
+	struct repack_config_ctx *repack_ctx = cb;
+	struct pack_objects_args *po_args = repack_ctx->po_args;
+	struct pack_objects_args *cruft_po_args = repack_ctx->cruft_po_args;
 	if (!strcmp(var, "repack.usedeltabaseoffset")) {
-		delta_base_offset = git_config_bool(var, value);
+		po_args->delta_base_offset = git_config_bool(var, value);
 		return 0;
 	}
 	if (!strcmp(var, "repack.packkeptobjects")) {
-		pack_kept_objects = git_config_bool(var, value);
+		po_args->pack_kept_objects = git_config_bool(var, value);
 		return 0;
 	}
 	if (!strcmp(var, "repack.writebitmaps") ||
@@ -116,1134 +97,10 @@ static int repack_config(const char *var, const char *value,
 	return git_default_config(var, value, ctx, cb);
 }
 
-static void pack_objects_args_release(struct pack_objects_args *args)
-{
-	free(args->window);
-	free(args->window_memory);
-	free(args->depth);
-	free(args->threads);
-	list_objects_filter_release(&args->filter_options);
-}
-
-struct existing_packs {
-	struct string_list kept_packs;
-	struct string_list non_kept_packs;
-	struct string_list cruft_packs;
-};
-
-#define EXISTING_PACKS_INIT { \
-	.kept_packs = STRING_LIST_INIT_DUP, \
-	.non_kept_packs = STRING_LIST_INIT_DUP, \
-	.cruft_packs = STRING_LIST_INIT_DUP, \
-}
-
-static int has_existing_non_kept_packs(const struct existing_packs *existing)
-{
-	return existing->non_kept_packs.nr || existing->cruft_packs.nr;
-}
-
-static void pack_mark_for_deletion(struct string_list_item *item)
-{
-	item->util = (void*)((uintptr_t)item->util | DELETE_PACK);
-}
-
-static void pack_unmark_for_deletion(struct string_list_item *item)
-{
-	item->util = (void*)((uintptr_t)item->util & ~DELETE_PACK);
-}
-
-static int pack_is_marked_for_deletion(struct string_list_item *item)
-{
-	return (uintptr_t)item->util & DELETE_PACK;
-}
-
-static void pack_mark_retained(struct string_list_item *item)
-{
-	item->util = (void*)((uintptr_t)item->util | RETAIN_PACK);
-}
-
-static int pack_is_retained(struct string_list_item *item)
-{
-	return (uintptr_t)item->util & RETAIN_PACK;
-}
-
-static void mark_packs_for_deletion_1(struct string_list *names,
-				      struct string_list *list)
-{
-	struct string_list_item *item;
-	const int hexsz = the_hash_algo->hexsz;
-
-	for_each_string_list_item(item, list) {
-		char *sha1;
-		size_t len = strlen(item->string);
-		if (len < hexsz)
-			continue;
-		sha1 = item->string + len - hexsz;
-
-		if (pack_is_retained(item)) {
-			pack_unmark_for_deletion(item);
-		} else if (!string_list_has_string(names, sha1)) {
-			/*
-			 * Mark this pack for deletion, which ensures
-			 * that this pack won't be included in a MIDX
-			 * (if `--write-midx` was given) and that we
-			 * will actually delete this pack (if `-d` was
-			 * given).
-			 */
-			pack_mark_for_deletion(item);
-		}
-	}
-}
-
-static void retain_cruft_pack(struct existing_packs *existing,
-			      struct packed_git *cruft)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct string_list_item *item;
-
-	strbuf_addstr(&buf, pack_basename(cruft));
-	strbuf_strip_suffix(&buf, ".pack");
-
-	item = string_list_lookup(&existing->cruft_packs, buf.buf);
-	if (!item)
-		BUG("could not find cruft pack '%s'", pack_basename(cruft));
-
-	pack_mark_retained(item);
-	strbuf_release(&buf);
-}
-
-static void mark_packs_for_deletion(struct existing_packs *existing,
-				    struct string_list *names)
-
-{
-	mark_packs_for_deletion_1(names, &existing->non_kept_packs);
-	mark_packs_for_deletion_1(names, &existing->cruft_packs);
-}
-
-static void remove_redundant_pack(const char *dir_name, const char *base_name)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct multi_pack_index *m = get_multi_pack_index(the_repository->objects->sources);
-	strbuf_addf(&buf, "%s.pack", base_name);
-	if (m && m->local && midx_contains_pack(m, buf.buf))
-		clear_midx_file(the_repository);
-	strbuf_insertf(&buf, 0, "%s/", dir_name);
-	unlink_pack_path(buf.buf, 1);
-	strbuf_release(&buf);
-}
-
-static void remove_redundant_packs_1(struct string_list *packs)
-{
-	struct string_list_item *item;
-	for_each_string_list_item(item, packs) {
-		if (!pack_is_marked_for_deletion(item))
-			continue;
-		remove_redundant_pack(packdir, item->string);
-	}
-}
-
-static void remove_redundant_existing_packs(struct existing_packs *existing)
-{
-	remove_redundant_packs_1(&existing->non_kept_packs);
-	remove_redundant_packs_1(&existing->cruft_packs);
-}
-
-static void existing_packs_release(struct existing_packs *existing)
-{
-	string_list_clear(&existing->kept_packs, 0);
-	string_list_clear(&existing->non_kept_packs, 0);
-	string_list_clear(&existing->cruft_packs, 0);
-}
-
-/*
- * Adds all packs hex strings (pack-$HASH) to either packs->non_kept
- * or packs->kept based on whether each pack has a corresponding
- * .keep file or not.  Packs without a .keep file are not to be kept
- * if we are going to pack everything into one file.
- */
-static void collect_pack_filenames(struct existing_packs *existing,
-				   const struct string_list *extra_keep)
-{
-	struct packed_git *p;
-	struct strbuf buf = STRBUF_INIT;
-
-	for (p = get_all_packs(the_repository); p; p = p->next) {
-		int i;
-		const char *base;
-
-		if (!p->pack_local)
-			continue;
-
-		base = pack_basename(p);
-
-		for (i = 0; i < extra_keep->nr; i++)
-			if (!fspathcmp(base, extra_keep->items[i].string))
-				break;
-
-		strbuf_reset(&buf);
-		strbuf_addstr(&buf, base);
-		strbuf_strip_suffix(&buf, ".pack");
-
-		if ((extra_keep->nr > 0 && i < extra_keep->nr) || p->pack_keep)
-			string_list_append(&existing->kept_packs, buf.buf);
-		else if (p->is_cruft)
-			string_list_append(&existing->cruft_packs, buf.buf);
-		else
-			string_list_append(&existing->non_kept_packs, buf.buf);
-	}
-
-	string_list_sort(&existing->kept_packs);
-	string_list_sort(&existing->non_kept_packs);
-	string_list_sort(&existing->cruft_packs);
-	strbuf_release(&buf);
-}
-
-static void prepare_pack_objects(struct child_process *cmd,
-				 const struct pack_objects_args *args,
-				 const char *out)
-{
-	strvec_push(&cmd->args, "pack-objects");
-	if (args->window)
-		strvec_pushf(&cmd->args, "--window=%s", args->window);
-	if (args->window_memory)
-		strvec_pushf(&cmd->args, "--window-memory=%s", args->window_memory);
-	if (args->depth)
-		strvec_pushf(&cmd->args, "--depth=%s", args->depth);
-	if (args->threads)
-		strvec_pushf(&cmd->args, "--threads=%s", args->threads);
-	if (args->max_pack_size)
-		strvec_pushf(&cmd->args, "--max-pack-size=%lu", args->max_pack_size);
-	if (args->no_reuse_delta)
-		strvec_pushf(&cmd->args, "--no-reuse-delta");
-	if (args->no_reuse_object)
-		strvec_pushf(&cmd->args, "--no-reuse-object");
-	if (args->name_hash_version)
-		strvec_pushf(&cmd->args, "--name-hash-version=%d", args->name_hash_version);
-	if (args->path_walk)
-		strvec_pushf(&cmd->args, "--path-walk");
-	if (args->local)
-		strvec_push(&cmd->args,  "--local");
-	if (args->quiet)
-		strvec_push(&cmd->args,  "--quiet");
-	if (delta_base_offset)
-		strvec_push(&cmd->args,  "--delta-base-offset");
-	strvec_push(&cmd->args, out);
-	cmd->git_cmd = 1;
-	cmd->out = -1;
-}
-
-/*
- * 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 UNUSED,
-		     uint32_t pos UNUSED, void *data)
-{
-	struct child_process *cmd = data;
-
-	if (cmd->in == -1) {
-		if (start_command(cmd))
-			die(_("could not start pack-objects to repack promisor objects"));
-	}
-
-	if (write_in_full(cmd->in, oid_to_hex(oid), the_hash_algo->hexsz) < 0 ||
-	    write_in_full(cmd->in, "\n", 1) < 0)
-		die(_("failed to feed promisor objects to pack-objects"));
-	return 0;
-}
-
-static struct {
-	const char *name;
-	unsigned optional:1;
-} exts[] = {
-	{".pack"},
-	{".rev", 1},
-	{".mtimes", 1},
-	{".bitmap", 1},
-	{".promisor", 1},
-	{".idx"},
-};
-
-struct generated_pack_data {
-	struct tempfile *tempfiles[ARRAY_SIZE(exts)];
-};
-
-static struct generated_pack_data *populate_pack_exts(const char *name)
-{
-	struct stat statbuf;
-	struct strbuf path = STRBUF_INIT;
-	struct generated_pack_data *data = xcalloc(1, sizeof(*data));
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(exts); i++) {
-		strbuf_reset(&path);
-		strbuf_addf(&path, "%s-%s%s", packtmp, name, exts[i].name);
-
-		if (stat(path.buf, &statbuf))
-			continue;
-
-		data->tempfiles[i] = register_tempfile(path.buf);
-	}
-
-	strbuf_release(&path);
-	return data;
-}
-
-static int has_pack_ext(const struct generated_pack_data *data,
-			const char *ext)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(exts); i++) {
-		if (strcmp(exts[i].name, ext))
-			continue;
-		return !!data->tempfiles[i];
-	}
-	BUG("unknown pack extension: '%s'", ext);
-}
-
-static void repack_promisor_objects(const struct pack_objects_args *args,
-				    struct string_list *names)
-{
-	struct child_process cmd = CHILD_PROCESS_INIT;
-	FILE *out;
-	struct strbuf line = STRBUF_INIT;
-
-	prepare_pack_objects(&cmd, args, packtmp);
-	cmd.in = -1;
-
-	/*
-	 * NEEDSWORK: Giving pack-objects only the OIDs without any ordering
-	 * hints may result in suboptimal deltas in the resulting pack. See if
-	 * the OIDs can be sent with fake paths such that pack-objects can use a
-	 * {type -> existing pack order} ordering when computing deltas instead
-	 * of a {type -> size} ordering, which may produce better deltas.
-	 */
-	for_each_packed_object(the_repository, write_oid, &cmd,
-			       FOR_EACH_OBJECT_PROMISOR_ONLY);
-
-	if (cmd.in == -1) {
-		/* No packed objects; cmd was never started */
-		child_process_clear(&cmd);
-		return;
-	}
-
-	close(cmd.in);
-
-	out = xfdopen(cmd.out, "r");
-	while (strbuf_getline_lf(&line, out) != EOF) {
-		struct string_list_item *item;
-		char *promisor_name;
-
-		if (line.len != the_hash_algo->hexsz)
-			die(_("repack: Expecting full hex object ID lines only from pack-objects."));
-		item = string_list_append(names, line.buf);
-
-		/*
-		 * pack-objects creates the .pack and .idx files, but not the
-		 * .promisor file. Create the .promisor file, which is empty.
-		 *
-		 * NEEDSWORK: fetch-pack sometimes generates non-empty
-		 * .promisor files containing the ref names and associated
-		 * hashes at the point of generation of the corresponding
-		 * packfile, but this would not preserve their contents. Maybe
-		 * concatenate the contents of all .promisor files instead of
-		 * just creating a new empty file.
-		 */
-		promisor_name = mkpathdup("%s-%s.promisor", packtmp,
-					  line.buf);
-		write_promisor_file(promisor_name, NULL, 0);
-
-		item->util = populate_pack_exts(item->string);
-
-		free(promisor_name);
-	}
-
-	fclose(out);
-	if (finish_command(&cmd))
-		die(_("could not finish pack-objects to repack promisor objects"));
-	strbuf_release(&line);
-}
-
-struct pack_geometry {
-	struct packed_git **pack;
-	uint32_t pack_nr, pack_alloc;
-	uint32_t split;
-
-	int split_factor;
-};
-
-static uint32_t geometry_pack_weight(struct packed_git *p)
-{
-	if (open_pack_index(p))
-		die(_("cannot open index for %s"), p->pack_name);
-	return p->num_objects;
-}
-
-static int geometry_cmp(const void *va, const void *vb)
-{
-	uint32_t aw = geometry_pack_weight(*(struct packed_git **)va),
-		 bw = geometry_pack_weight(*(struct packed_git **)vb);
-
-	if (aw < bw)
-		return -1;
-	if (aw > bw)
-		return 1;
-	return 0;
-}
-
-static void init_pack_geometry(struct pack_geometry *geometry,
-			       struct existing_packs *existing,
-			       const struct pack_objects_args *args)
-{
-	struct packed_git *p;
-	struct strbuf buf = STRBUF_INIT;
-
-	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 in existing->kept_packs below, but
-			 * this saves us from doing a more expensive
-			 * check.
-			 */
-			if (p->pack_keep)
-				continue;
-
-			/*
-			 * The pack may be kept via the --keep-pack
-			 * option; check 'existing->kept_packs' to
-			 * determine whether to ignore it.
-			 */
-			strbuf_reset(&buf);
-			strbuf_addstr(&buf, pack_basename(p));
-			strbuf_strip_suffix(&buf, ".pack");
-
-			if (string_list_has_string(&existing->kept_packs, buf.buf))
-				continue;
-		}
-		if (p->is_cruft)
-			continue;
-
-		ALLOC_GROW(geometry->pack,
-			   geometry->pack_nr + 1,
-			   geometry->pack_alloc);
-
-		geometry->pack[geometry->pack_nr] = p;
-		geometry->pack_nr++;
-	}
-
-	QSORT(geometry->pack, geometry->pack_nr, geometry_cmp);
-	strbuf_release(&buf);
-}
-
-static void split_pack_geometry(struct pack_geometry *geometry)
-{
-	uint32_t i;
-	uint32_t split;
-	off_t total_size = 0;
-
-	if (!geometry->pack_nr) {
-		geometry->split = geometry->pack_nr;
-		return;
-	}
-
-	/*
-	 * First, count the number of packs (in descending order of size) which
-	 * already form a geometric progression.
-	 */
-	for (i = geometry->pack_nr - 1; i > 0; i--) {
-		struct packed_git *ours = geometry->pack[i];
-		struct packed_git *prev = geometry->pack[i - 1];
-
-		if (unsigned_mult_overflows(geometry->split_factor,
-					    geometry_pack_weight(prev)))
-			die(_("pack %s too large to consider in geometric "
-			      "progression"),
-			    prev->pack_name);
-
-		if (geometry_pack_weight(ours) <
-		    geometry->split_factor * geometry_pack_weight(prev))
-			break;
-	}
-
-	split = i;
-
-	if (split) {
-		/*
-		 * Move the split one to the right, since the top element in the
-		 * last-compared pair can't be in the progression. Only do this
-		 * when we split in the middle of the array (otherwise if we got
-		 * to the end, then the split is in the right place).
-		 */
-		split++;
-	}
-
-	/*
-	 * Then, anything to the left of 'split' must be in a new pack. But,
-	 * creating that new pack may cause packs in the heavy half to no longer
-	 * form a geometric progression.
-	 *
-	 * Compute an expected size of the new pack, and then determine how many
-	 * packs in the heavy half need to be joined into it (if any) to restore
-	 * the geometric progression.
-	 */
-	for (i = 0; i < split; i++) {
-		struct packed_git *p = geometry->pack[i];
-
-		if (unsigned_add_overflows(total_size, geometry_pack_weight(p)))
-			die(_("pack %s too large to roll up"), p->pack_name);
-		total_size += geometry_pack_weight(p);
-	}
-	for (i = split; i < geometry->pack_nr; i++) {
-		struct packed_git *ours = geometry->pack[i];
-
-		if (unsigned_mult_overflows(geometry->split_factor,
-					    total_size))
-			die(_("pack %s too large to roll up"), ours->pack_name);
-
-		if (geometry_pack_weight(ours) <
-		    geometry->split_factor * total_size) {
-			if (unsigned_add_overflows(total_size,
-						   geometry_pack_weight(ours)))
-				die(_("pack %s too large to roll up"),
-				    ours->pack_name);
-
-			split++;
-			total_size += geometry_pack_weight(ours);
-		} else
-			break;
-	}
-
-	geometry->split = split;
-}
-
-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
-		 * case there is only one pack left and it is the largest) or an
-		 * incremental one.
-		 *
-		 * If repacking incrementally, then we could check the size of
-		 * all packs to determine which should be preferred, but leave
-		 * this for later.
-		 */
-		return NULL;
-	}
-	if (geometry->split == geometry->pack_nr)
-		return NULL;
-
-	/*
-	 * 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 geometry_remove_redundant_packs(struct pack_geometry *geometry,
-					    struct string_list *names,
-					    struct existing_packs *existing)
-{
-	struct strbuf buf = STRBUF_INIT;
-	uint32_t i;
-
-	for (i = 0; i < geometry->split; i++) {
-		struct packed_git *p = geometry->pack[i];
-		if (string_list_has_string(names, hash_to_hex(p->hash)))
-			continue;
-
-		strbuf_reset(&buf);
-		strbuf_addstr(&buf, pack_basename(p));
-		strbuf_strip_suffix(&buf, ".pack");
-
-		if ((p->pack_keep) ||
-		    (string_list_has_string(&existing->kept_packs, buf.buf)))
-			continue;
-
-		remove_redundant_pack(packdir, buf.buf);
-	}
-
-	strbuf_release(&buf);
-}
-
-static void free_pack_geometry(struct pack_geometry *geometry)
-{
-	if (!geometry)
-		return;
-
-	free(geometry->pack);
-}
-
-static int midx_has_unknown_packs(char **midx_pack_names,
-				  size_t midx_pack_names_nr,
-				  struct string_list *include,
-				  struct pack_geometry *geometry,
-				  struct existing_packs *existing)
-{
-	size_t i;
-
-	string_list_sort(include);
-
-	for (i = 0; i < midx_pack_names_nr; i++) {
-		const char *pack_name = midx_pack_names[i];
-
-		/*
-		 * Determine whether or not each MIDX'd pack from the existing
-		 * MIDX (if any) is represented in the new MIDX. For each pack
-		 * in the MIDX, it must either be:
-		 *
-		 *  - In the "include" list of packs to be included in the new
-		 *    MIDX. Note this function is called before the include
-		 *    list is populated with any cruft pack(s).
-		 *
-		 *  - Below the geometric split line (if using pack geometry),
-		 *    indicating that the pack won't be included in the new
-		 *    MIDX, but its contents were rolled up as part of the
-		 *    geometric repack.
-		 *
-		 *  - In the existing non-kept packs list (if not using pack
-		 *    geometry), and marked as non-deleted.
-		 */
-		if (string_list_has_string(include, pack_name)) {
-			continue;
-		} else if (geometry) {
-			struct strbuf buf = STRBUF_INIT;
-			uint32_t j;
-
-			for (j = 0; j < geometry->split; j++) {
-				strbuf_reset(&buf);
-				strbuf_addstr(&buf, pack_basename(geometry->pack[j]));
-				strbuf_strip_suffix(&buf, ".pack");
-				strbuf_addstr(&buf, ".idx");
-
-				if (!strcmp(pack_name, buf.buf)) {
-					strbuf_release(&buf);
-					break;
-				}
-			}
-
-			strbuf_release(&buf);
-
-			if (j < geometry->split)
-				continue;
-		} else {
-			struct string_list_item *item;
-
-			item = string_list_lookup(&existing->non_kept_packs,
-						  pack_name);
-			if (item && !pack_is_marked_for_deletion(item))
-				continue;
-		}
-
-		/*
-		 * If we got to this point, the MIDX includes some pack that we
-		 * don't know about.
-		 */
-		return 1;
-	}
-
-	return 0;
-}
-
-struct midx_snapshot_ref_data {
-	struct tempfile *f;
-	struct oidset seen;
-	int preferred;
-};
-
-static int midx_snapshot_ref_one(const char *refname UNUSED,
-				 const char *referent UNUSED,
-				 const struct object_id *oid,
-				 int flag UNUSED, void *_data)
-{
-	struct midx_snapshot_ref_data *data = _data;
-	struct object_id peeled;
-
-	if (!peel_iterated_oid(the_repository, oid, &peeled))
-		oid = &peeled;
-
-	if (oidset_insert(&data->seen, oid))
-		return 0; /* already seen */
-
-	if (odb_read_object_info(the_repository->objects, oid, NULL) != OBJ_COMMIT)
-		return 0;
-
-	fprintf(data->f->fp, "%s%s\n", data->preferred ? "+" : "",
-		oid_to_hex(oid));
-
-	return 0;
-}
-
-static void midx_snapshot_refs(struct tempfile *f)
-{
-	struct midx_snapshot_ref_data data;
-	const struct string_list *preferred = bitmap_preferred_tips(the_repository);
-
-	data.f = f;
-	data.preferred = 0;
-	oidset_init(&data.seen, 0);
-
-	if (!fdopen_tempfile(f, "w"))
-		 die(_("could not open tempfile %s for writing"),
-		     get_tempfile_path(f));
-
-	if (preferred) {
-		struct string_list_item *item;
-
-		data.preferred = 1;
-		for_each_string_list_item(item, preferred)
-			refs_for_each_ref_in(get_main_ref_store(the_repository),
-					     item->string,
-					     midx_snapshot_ref_one, &data);
-		data.preferred = 0;
-	}
-
-	refs_for_each_ref(get_main_ref_store(the_repository),
-			  midx_snapshot_ref_one, &data);
-
-	if (close_tempfile_gently(f)) {
-		int save_errno = errno;
-		delete_tempfile(&f);
-		errno = save_errno;
-		die_errno(_("could not close refs snapshot tempfile"));
-	}
-
-	oidset_clear(&data.seen);
-}
-
-static void midx_included_packs(struct string_list *include,
-				struct existing_packs *existing,
-				char **midx_pack_names,
-				size_t midx_pack_names_nr,
-				struct string_list *names,
-				struct pack_geometry *geometry)
-{
-	struct string_list_item *item;
-	struct strbuf buf = STRBUF_INIT;
-
-	for_each_string_list_item(item, &existing->kept_packs) {
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "%s.idx", item->string);
-		string_list_insert(include, buf.buf);
-	}
-
-	for_each_string_list_item(item, names) {
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "pack-%s.idx", item->string);
-		string_list_insert(include, buf.buf);
-	}
-
-	if (geometry->split_factor) {
-		uint32_t i;
-
-		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_reset(&buf);
-			strbuf_addstr(&buf, pack_basename(p));
-			strbuf_strip_suffix(&buf, ".pack");
-			strbuf_addstr(&buf, ".idx");
-
-			string_list_insert(include, buf.buf);
-		}
-	} else {
-		for_each_string_list_item(item, &existing->non_kept_packs) {
-			if (pack_is_marked_for_deletion(item))
-				continue;
-
-			strbuf_reset(&buf);
-			strbuf_addf(&buf, "%s.idx", item->string);
-			string_list_insert(include, buf.buf);
-		}
-	}
-
-	if (midx_must_contain_cruft ||
-	    midx_has_unknown_packs(midx_pack_names, midx_pack_names_nr,
-				   include, geometry, existing)) {
-		/*
-		 * If there are one or more unknown pack(s) present (see
-		 * midx_has_unknown_packs() for what makes a pack
-		 * "unknown") in the MIDX before the repack, keep them
-		 * as they may be required to form a reachability
-		 * closure if the MIDX is bitmapped.
-		 *
-		 * For example, a cruft pack can be required to form a
-		 * reachability closure if the MIDX is bitmapped and one
-		 * or more of the bitmap's selected commits reaches a
-		 * once-cruft object that was later made reachable.
-		 */
-		for_each_string_list_item(item, &existing->cruft_packs) {
-			/*
-			 * When doing a --geometric repack, there is no
-			 * need to check for deleted packs, since we're
-			 * by definition not doing an ALL_INTO_ONE
-			 * repack (hence no packs will be deleted).
-			 * Otherwise we must check for and exclude any
-			 * packs which are enqueued for deletion.
-			 *
-			 * So we could omit the conditional below in the
-			 * --geometric case, but doing so is unnecessary
-			 *  since no packs are marked as pending
-			 *  deletion (since we only call
-			 *  `mark_packs_for_deletion()` when doing an
-			 *  all-into-one repack).
-			 */
-			if (pack_is_marked_for_deletion(item))
-				continue;
-
-			strbuf_reset(&buf);
-			strbuf_addf(&buf, "%s.idx", item->string);
-			string_list_insert(include, buf.buf);
-		}
-	} else {
-		/*
-		 * Modern versions of Git (with the appropriate
-		 * configuration setting) will write new copies of
-		 * once-cruft objects when doing a --geometric repack.
-		 *
-		 * If the MIDX has no cruft pack, new packs written
-		 * during a --geometric repack will not rely on the
-		 * cruft pack to form a reachability closure, so we can
-		 * avoid including them in the MIDX in that case.
-		 */
-		;
-	}
-
-	strbuf_release(&buf);
-}
-
-static int write_midx_included_packs(struct string_list *include,
-				     struct pack_geometry *geometry,
-				     struct string_list *names,
-				     const char *refs_snapshot,
-				     int show_progress, int write_bitmaps)
-{
-	struct child_process cmd = CHILD_PROCESS_INIT;
-	struct string_list_item *item;
-	struct packed_git *preferred = get_preferred_pack(geometry);
-	FILE *in;
-	int ret;
-
-	if (!include->nr)
-		return 0;
-
-	cmd.in = -1;
-	cmd.git_cmd = 1;
-
-	strvec_push(&cmd.args, "multi-pack-index");
-	strvec_pushl(&cmd.args, "write", "--stdin-packs", NULL);
-
-	if (show_progress)
-		strvec_push(&cmd.args, "--progress");
-	else
-		strvec_push(&cmd.args, "--no-progress");
-
-	if (write_bitmaps)
-		strvec_push(&cmd.args, "--bitmap");
-
-	if (preferred)
-		strvec_pushf(&cmd.args, "--preferred-pack=%s",
-			     pack_basename(preferred));
-	else if (names->nr) {
-		/* The largest pack was repacked, meaning that either
-		 * one or two packs exist depending on whether the
-		 * repository has a cruft pack or not.
-		 *
-		 * Select the non-cruft one as preferred to encourage
-		 * pack-reuse among packs containing reachable objects
-		 * over unreachable ones.
-		 *
-		 * (Note we could write multiple packs here if
-		 * `--max-pack-size` was given, but any one of them
-		 * will suffice, so pick the first one.)
-		 */
-		for_each_string_list_item(item, names) {
-			struct generated_pack_data *data = item->util;
-			if (has_pack_ext(data, ".mtimes"))
-				continue;
-
-			strvec_pushf(&cmd.args, "--preferred-pack=pack-%s.pack",
-				     item->string);
-			break;
-		}
-	} else {
-		/*
-		 * No packs were kept, and no packs were written. The
-		 * only thing remaining are .keep packs (unless
-		 * --pack-kept-objects was given).
-		 *
-		 * Set the `--preferred-pack` arbitrarily here.
-		 */
-		;
-	}
-
-	if (refs_snapshot)
-		strvec_pushf(&cmd.args, "--refs-snapshot=%s", refs_snapshot);
-
-	ret = start_command(&cmd);
-	if (ret)
-		return ret;
-
-	in = xfdopen(cmd.in, "w");
-	for_each_string_list_item(item, include)
-		fprintf(in, "%s\n", item->string);
-	fclose(in);
-
-	return finish_command(&cmd);
-}
-
-static void remove_redundant_bitmaps(struct string_list *include,
-				     const char *packdir)
-{
-	struct strbuf path = STRBUF_INIT;
-	struct string_list_item *item;
-	size_t packdir_len;
-
-	strbuf_addstr(&path, packdir);
-	strbuf_addch(&path, '/');
-	packdir_len = path.len;
-
-	/*
-	 * Remove any pack bitmaps corresponding to packs which are now
-	 * included in the MIDX.
-	 */
-	for_each_string_list_item(item, include) {
-		strbuf_addstr(&path, item->string);
-		strbuf_strip_suffix(&path, ".idx");
-		strbuf_addstr(&path, ".bitmap");
-
-		if (unlink(path.buf) && errno != ENOENT)
-			warning_errno(_("could not remove stale bitmap: %s"),
-				      path.buf);
-
-		strbuf_setlen(&path, packdir_len);
-	}
-	strbuf_release(&path);
-}
-
-static int finish_pack_objects_cmd(struct child_process *cmd,
-				   struct string_list *names,
-				   int local)
-{
-	FILE *out;
-	struct strbuf line = STRBUF_INIT;
-
-	out = xfdopen(cmd->out, "r");
-	while (strbuf_getline_lf(&line, out) != EOF) {
-		struct string_list_item *item;
-
-		if (line.len != the_hash_algo->hexsz)
-			die(_("repack: Expecting full hex object ID lines only "
-			      "from pack-objects."));
-		/*
-		 * Avoid putting packs written outside of the repository in the
-		 * list of names.
-		 */
-		if (local) {
-			item = string_list_append(names, line.buf);
-			item->util = populate_pack_exts(line.buf);
-		}
-	}
-	fclose(out);
-
-	strbuf_release(&line);
-
-	return finish_command(cmd);
-}
-
-static int write_filtered_pack(const struct pack_objects_args *args,
-			       const char *destination,
-			       const char *pack_prefix,
-			       struct existing_packs *existing,
-			       struct string_list *names)
-{
-	struct child_process cmd = CHILD_PROCESS_INIT;
-	struct string_list_item *item;
-	FILE *in;
-	int ret;
-	const char *caret;
-	const char *scratch;
-	int local = skip_prefix(destination, packdir, &scratch);
-
-	prepare_pack_objects(&cmd, args, destination);
-
-	strvec_push(&cmd.args, "--stdin-packs");
-
-	if (!pack_kept_objects)
-		strvec_push(&cmd.args, "--honor-pack-keep");
-	for_each_string_list_item(item, &existing->kept_packs)
-		strvec_pushf(&cmd.args, "--keep-pack=%s", item->string);
-
-	cmd.in = -1;
-
-	ret = start_command(&cmd);
-	if (ret)
-		return ret;
-
-	/*
-	 * Here 'names' contains only the pack(s) that were just
-	 * written, which is exactly the packs we want to keep. Also
-	 * 'existing_kept_packs' already contains the packs in
-	 * 'keep_pack_list'.
-	 */
-	in = xfdopen(cmd.in, "w");
-	for_each_string_list_item(item, names)
-		fprintf(in, "^%s-%s.pack\n", pack_prefix, item->string);
-	for_each_string_list_item(item, &existing->non_kept_packs)
-		fprintf(in, "%s.pack\n", item->string);
-	for_each_string_list_item(item, &existing->cruft_packs)
-		fprintf(in, "%s.pack\n", item->string);
-	caret = pack_kept_objects ? "" : "^";
-	for_each_string_list_item(item, &existing->kept_packs)
-		fprintf(in, "%s%s.pack\n", caret, item->string);
-	fclose(in);
-
-	return finish_pack_objects_cmd(&cmd, names, local);
-}
-
-static void combine_small_cruft_packs(FILE *in, size_t combine_cruft_below_size,
-				      struct existing_packs *existing)
-{
-	struct packed_git *p;
-	struct strbuf buf = STRBUF_INIT;
-	size_t i;
-
-	for (p = get_all_packs(the_repository); p; p = p->next) {
-		if (!(p->is_cruft && p->pack_local))
-			continue;
-
-		strbuf_reset(&buf);
-		strbuf_addstr(&buf, pack_basename(p));
-		strbuf_strip_suffix(&buf, ".pack");
-
-		if (!string_list_has_string(&existing->cruft_packs, buf.buf))
-			continue;
-
-		if (p->pack_size < combine_cruft_below_size) {
-			fprintf(in, "-%s\n", pack_basename(p));
-		} else {
-			retain_cruft_pack(existing, p);
-			fprintf(in, "%s\n", pack_basename(p));
-		}
-	}
-
-	for (i = 0; i < existing->non_kept_packs.nr; i++)
-		fprintf(in, "-%s.pack\n",
-			existing->non_kept_packs.items[i].string);
-
-	strbuf_release(&buf);
-}
-
-static int write_cruft_pack(const struct pack_objects_args *args,
-			    const char *destination,
-			    const char *pack_prefix,
-			    const char *cruft_expiration,
-			    unsigned long combine_cruft_below_size,
-			    struct string_list *names,
-			    struct existing_packs *existing)
-{
-	struct child_process cmd = CHILD_PROCESS_INIT;
-	struct string_list_item *item;
-	FILE *in;
-	int ret;
-	const char *scratch;
-	int local = skip_prefix(destination, packdir, &scratch);
-
-	prepare_pack_objects(&cmd, args, destination);
-
-	strvec_push(&cmd.args, "--cruft");
-	if (cruft_expiration)
-		strvec_pushf(&cmd.args, "--cruft-expiration=%s",
-			     cruft_expiration);
-
-	strvec_push(&cmd.args, "--honor-pack-keep");
-	strvec_push(&cmd.args, "--non-empty");
-
-	cmd.in = -1;
-
-	ret = start_command(&cmd);
-	if (ret)
-		return ret;
-
-	/*
-	 * names has a confusing double use: it both provides the list
-	 * of just-written new packs, and accepts the name of the cruft
-	 * pack we are writing.
-	 *
-	 * By the time it is read here, it contains only the pack(s)
-	 * that were just written, which is exactly the set of packs we
-	 * want to consider kept.
-	 *
-	 * If `--expire-to` is given, the double-use served by `names`
-	 * ensures that the pack written to `--expire-to` excludes any
-	 * objects contained in the cruft pack.
-	 */
-	in = xfdopen(cmd.in, "w");
-	for_each_string_list_item(item, names)
-		fprintf(in, "%s-%s.pack\n", pack_prefix, item->string);
-	if (combine_cruft_below_size && !cruft_expiration) {
-		combine_small_cruft_packs(in, combine_cruft_below_size,
-					  existing);
-	} else {
-		for_each_string_list_item(item, &existing->non_kept_packs)
-			fprintf(in, "-%s.pack\n", item->string);
-		for_each_string_list_item(item, &existing->cruft_packs)
-			fprintf(in, "-%s.pack\n", item->string);
-	}
-	for_each_string_list_item(item, &existing->kept_packs)
-		fprintf(in, "%s.pack\n", item->string);
-	fclose(in);
-
-	return finish_pack_objects_cmd(&cmd, names, local);
-}
-
-static const char *find_pack_prefix(const char *packdir, const char *packtmp)
-{
-	const char *pack_prefix;
-	if (!skip_prefix(packtmp, packdir, &pack_prefix))
-		die(_("pack prefix %s does not begin with objdir %s"),
-		    packtmp, packdir);
-	if (*pack_prefix == '/')
-		pack_prefix++;
-	return pack_prefix;
-}
-
 int cmd_repack(int argc,
 	       const char **argv,
 	       const char *prefix,
-	       struct repository *repo UNUSED)
+	       struct repository *repo)
 {
 	struct child_process cmd = CHILD_PROCESS_INIT;
 	struct string_list_item *item;
@@ -1251,18 +108,17 @@ int cmd_repack(int argc,
 	struct existing_packs existing = EXISTING_PACKS_INIT;
 	struct pack_geometry geometry = { 0 };
 	struct tempfile *refs_snapshot = NULL;
-	int i, ext, ret;
+	int i, ret;
 	int show_progress;
-	char **midx_pack_names = NULL;
-	size_t midx_pack_names_nr = 0;
 
 	/* variables to be filled by option parsing */
+	struct repack_config_ctx config_ctx;
 	int delete_redundant = 0;
 	const char *unpack_unreachable = NULL;
 	int keep_unreachable = 0;
 	struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
-	struct pack_objects_args po_args = { 0 };
-	struct pack_objects_args cruft_po_args = { 0 };
+	struct pack_objects_args po_args = PACK_OBJECTS_ARGS_INIT;
+	struct pack_objects_args cruft_po_args = PACK_OBJECTS_ARGS_INIT;
 	int write_midx = 0;
 	const char *cruft_expiration = NULL;
 	const char *expire_to = NULL;
@@ -1323,7 +179,7 @@ int cmd_repack(int argc,
 		OPT_UNSIGNED(0, "max-pack-size", &po_args.max_pack_size,
 			     N_("maximum size of each packfile")),
 		OPT_PARSE_LIST_OBJECTS_FILTER(&po_args.filter_options),
-		OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects,
+		OPT_BOOL(0, "pack-kept-objects", &po_args.pack_kept_objects,
 				N_("repack objects in packs marked with .keep")),
 		OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"),
 				N_("do not repack this pack")),
@@ -1340,7 +196,11 @@ int cmd_repack(int argc,
 
 	list_objects_filter_init(&po_args.filter_options);
 
-	repo_config(the_repository, repack_config, &cruft_po_args);
+	memset(&config_ctx, 0, sizeof(config_ctx));
+	config_ctx.po_args = &po_args;
+	config_ctx.cruft_po_args = &cruft_po_args;
+
+	repo_config(repo, repack_config, &config_ctx);
 
 	argc = parse_options(argc, argv, prefix, builtin_repack_options,
 				git_repack_usage, 0);
@@ -1350,7 +210,7 @@ int cmd_repack(int argc,
 	po_args.depth = xstrdup_or_null(opt_depth);
 	po_args.threads = xstrdup_or_null(opt_threads);
 
-	if (delete_redundant && the_repository->repository_format_precious_objects)
+	if (delete_redundant && repo->repository_format_precious_objects)
 		die(_("cannot delete packs in a precious-objects repo"));
 
 	die_for_incompatible_opt3(unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE), "-A",
@@ -1365,14 +225,14 @@ int cmd_repack(int argc,
 		    (!(pack_everything & ALL_INTO_ONE) || !is_bare_repository()))
 			write_bitmaps = 0;
 	}
-	if (pack_kept_objects < 0)
-		pack_kept_objects = write_bitmaps > 0 && !write_midx;
+	if (po_args.pack_kept_objects < 0)
+		po_args.pack_kept_objects = write_bitmaps > 0 && !write_midx;
 
 	if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) && !write_midx)
 		die(_(incremental_bitmap_conflict_error));
 
 	if (write_bitmaps && po_args.local &&
-	    odb_has_alternates(the_repository->objects)) {
+	    odb_has_alternates(repo->objects)) {
 		/*
 		 * When asked to do a local repack, but we have
 		 * packfiles that are inherited from an alternate, then
@@ -1387,26 +247,28 @@ int cmd_repack(int argc,
 	if (write_midx && write_bitmaps) {
 		struct strbuf path = STRBUF_INIT;
 
-		strbuf_addf(&path, "%s/%s_XXXXXX", repo_get_object_directory(the_repository),
+		strbuf_addf(&path, "%s/%s_XXXXXX",
+			    repo_get_object_directory(repo),
 			    "bitmap-ref-tips");
 
 		refs_snapshot = xmks_tempfile(path.buf);
-		midx_snapshot_refs(refs_snapshot);
+		midx_snapshot_refs(repo, refs_snapshot);
 
 		strbuf_release(&path);
 	}
 
-	packdir = mkpathdup("%s/pack", repo_get_object_directory(the_repository));
+	packdir = mkpathdup("%s/pack", repo_get_object_directory(repo));
 	packtmp_name = xstrfmt(".tmp-%d-pack", (int)getpid());
 	packtmp = mkpathdup("%s/%s", packdir, packtmp_name);
 
-	collect_pack_filenames(&existing, &keep_pack_list);
+	existing.repo = repo;
+	existing_packs_collect(&existing, &keep_pack_list);
 
 	if (geometry.split_factor) {
 		if (pack_everything)
 			die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a");
-		init_pack_geometry(&geometry, &existing, &po_args);
-		split_pack_geometry(&geometry);
+		pack_geometry_init(&geometry, &existing, &po_args);
+		pack_geometry_split(&geometry);
 	}
 
 	prepare_pack_objects(&cmd, &po_args, packtmp);
@@ -1414,8 +276,6 @@ int cmd_repack(int argc,
 	show_progress = !po_args.quiet && isatty(2);
 
 	strvec_push(&cmd.args, "--keep-true-parents");
-	if (!pack_kept_objects)
-		strvec_push(&cmd.args, "--honor-pack-keep");
 	for (i = 0; i < keep_pack_list.nr; i++)
 		strvec_pushf(&cmd.args, "--keep-pack=%s",
 			     keep_pack_list.items[i].string);
@@ -1435,7 +295,7 @@ int cmd_repack(int argc,
 		strvec_push(&cmd.args, "--reflog");
 		strvec_push(&cmd.args, "--indexed-objects");
 	}
-	if (repo_has_promisor_remote(the_repository))
+	if (repo_has_promisor_remote(repo))
 		strvec_push(&cmd.args, "--exclude-promisor-objects");
 	if (!write_midx) {
 		if (write_bitmaps > 0)
@@ -1447,9 +307,9 @@ int cmd_repack(int argc,
 		strvec_push(&cmd.args, "--delta-islands");
 
 	if (pack_everything & ALL_INTO_ONE) {
-		repack_promisor_objects(&po_args, &names);
+		repack_promisor_objects(repo, &po_args, &names, packtmp);
 
-		if (has_existing_non_kept_packs(&existing) &&
+		if (existing_packs_has_non_kept(&existing) &&
 		    delete_redundant &&
 		    !(pack_everything & PACK_CRUFT)) {
 			for_each_string_list_item(item, &names) {
@@ -1511,9 +371,17 @@ int cmd_repack(int argc,
 		fclose(in);
 	}
 
-	ret = finish_pack_objects_cmd(&cmd, &names, 1);
-	if (ret)
-		goto cleanup;
+	{
+		struct write_pack_opts opts = {
+			.packdir = packdir,
+			.destination = packdir,
+			.packtmp = packtmp,
+		};
+		ret = finish_pack_objects_cmd(repo->hash_algo, &opts, &cmd,
+					      &names);
+		if (ret)
+			goto cleanup;
+	}
 
 	if (!names.nr) {
 		if (!po_args.quiet)
@@ -1531,12 +399,17 @@ int cmd_repack(int argc,
 		 * midx_has_unknown_packs() will make the decision for
 		 * us.
 		 */
-		if (!get_multi_pack_index(the_repository->objects->sources))
+		if (!get_multi_pack_index(repo->objects->sources))
 			midx_must_contain_cruft = 1;
 	}
 
 	if (pack_everything & PACK_CRUFT) {
-		const char *pack_prefix = find_pack_prefix(packdir, packtmp);
+		struct write_pack_opts opts = {
+			.po_args = &cruft_po_args,
+			.destination = packtmp,
+			.packtmp = packtmp,
+			.packdir = packdir,
+		};
 
 		if (!cruft_po_args.window)
 			cruft_po_args.window = xstrdup_or_null(po_args.window);
@@ -1551,9 +424,10 @@ int cmd_repack(int argc,
 
 		cruft_po_args.local = po_args.local;
 		cruft_po_args.quiet = po_args.quiet;
+		cruft_po_args.delta_base_offset = po_args.delta_base_offset;
+		cruft_po_args.pack_kept_objects = 0;
 
-		ret = write_cruft_pack(&cruft_po_args, packtmp, pack_prefix,
-				       cruft_expiration,
+		ret = write_cruft_pack(&opts, cruft_expiration,
 				       combine_cruft_below_size, &names,
 				       &existing);
 		if (ret)
@@ -1588,11 +462,8 @@ int cmd_repack(int argc,
 			 * pack, but rather removing all cruft packs from the
 			 * main repository regardless of size.
 			 */
-			ret = write_cruft_pack(&cruft_po_args, expire_to,
-					       pack_prefix,
-					       NULL,
-					       0ul,
-					       &names,
+			opts.destination = expire_to;
+			ret = write_cruft_pack(&opts, NULL, 0ul, &names,
 					       &existing);
 			if (ret)
 				goto cleanup;
@@ -1600,99 +471,63 @@ int cmd_repack(int argc,
 	}
 
 	if (po_args.filter_options.choice) {
-		if (!filter_to)
-			filter_to = packtmp;
+		struct write_pack_opts opts = {
+			.po_args = &po_args,
+			.destination = filter_to,
+			.packdir = packdir,
+			.packtmp = packtmp,
+		};
 
-		ret = write_filtered_pack(&po_args,
-					  filter_to,
-					  find_pack_prefix(packdir, packtmp),
-					  &existing,
-					  &names);
+		if (!opts.destination)
+			opts.destination = packtmp;
+
+		ret = write_filtered_pack(&opts, &existing, &names);
 		if (ret)
 			goto cleanup;
 	}
 
 	string_list_sort(&names);
 
-	if (get_multi_pack_index(the_repository->objects->sources)) {
-		struct multi_pack_index *m =
-			get_multi_pack_index(the_repository->objects->sources);
-
-		ALLOC_ARRAY(midx_pack_names,
-			    m->num_packs + m->num_packs_in_base);
-
-		for (; m; m = m->base_midx)
-			for (uint32_t i = 0; i < m->num_packs; i++)
-				midx_pack_names[midx_pack_names_nr++] =
-					xstrdup(m->pack_names[i]);
-	}
-
-	close_object_store(the_repository->objects);
+	close_object_store(repo->objects);
 
 	/*
 	 * Ok we have prepared all new packfiles.
 	 */
-	for_each_string_list_item(item, &names) {
-		struct generated_pack_data *data = item->util;
-
-		for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
-			char *fname;
-
-			fname = mkpathdup("%s/pack-%s%s",
-					packdir, item->string, exts[ext].name);
-
-			if (data->tempfiles[ext]) {
-				const char *fname_old = get_tempfile_path(data->tempfiles[ext]);
-				struct stat statbuffer;
-
-				if (!stat(fname_old, &statbuffer)) {
-					statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
-					chmod(fname_old, statbuffer.st_mode);
-				}
-
-				if (rename_tempfile(&data->tempfiles[ext], fname))
-					die_errno(_("renaming pack to '%s' failed"), fname);
-			} else if (!exts[ext].optional)
-				die(_("pack-objects did not write a '%s' file for pack %s-%s"),
-				    exts[ext].name, packtmp, item->string);
-			else if (unlink(fname) < 0 && errno != ENOENT)
-				die_errno(_("could not unlink: %s"), fname);
-
-			free(fname);
-		}
-	}
+	for_each_string_list_item(item, &names)
+		generated_pack_install(item->util, item->string, packdir,
+				       packtmp);
 	/* End of pack replacement. */
 
 	if (delete_redundant && pack_everything & ALL_INTO_ONE)
-		mark_packs_for_deletion(&existing, &names);
+		existing_packs_mark_for_deletion(&existing, &names);
 
 	if (write_midx) {
-		struct string_list include = STRING_LIST_INIT_DUP;
-		midx_included_packs(&include, &existing, midx_pack_names,
-				    midx_pack_names_nr, &names, &geometry);
+		struct repack_write_midx_opts opts = {
+			.existing = &existing,
+			.geometry = &geometry,
+			.names = &names,
+			.refs_snapshot = refs_snapshot ? get_tempfile_path(refs_snapshot) : NULL,
+			.packdir = packdir,
+			.show_progress = show_progress,
+			.write_bitmaps = write_bitmaps > 0,
+			.midx_must_contain_cruft = midx_must_contain_cruft
+		};
 
-		ret = write_midx_included_packs(&include, &geometry, &names,
-						refs_snapshot ? get_tempfile_path(refs_snapshot) : NULL,
-						show_progress, write_bitmaps > 0);
-
-		if (!ret && write_bitmaps)
-			remove_redundant_bitmaps(&include, packdir);
-
-		string_list_clear(&include, 0);
+		ret = write_midx_included_packs(&opts);
 
 		if (ret)
 			goto cleanup;
 	}
 
-	reprepare_packed_git(the_repository);
+	odb_reprepare(repo->objects);
 
 	if (delete_redundant) {
 		int opts = 0;
-		remove_redundant_existing_packs(&existing);
+		existing_packs_remove_redundant(&existing, packdir);
 
 		if (geometry.split_factor)
-			geometry_remove_redundant_packs(&geometry, &names,
-							&existing);
+			pack_geometry_remove_redundant(&geometry, &names,
+						       &existing, packdir);
 		if (show_progress)
 			opts |= PRUNE_PACKED_VERBOSE;
 		prune_packed_objects(opts);
@@ -1700,18 +535,18 @@ int cmd_repack(int argc,
 		if (!keep_unreachable &&
 		    (!(pack_everything & LOOSEN_UNREACHABLE) ||
 		     unpack_unreachable) &&
-		    is_repository_shallow(the_repository))
+		    is_repository_shallow(repo))
 			prune_shallow(PRUNE_QUICK);
 	}
 
 	if (run_update_server_info)
-		update_server_info(the_repository, 0);
+		update_server_info(repo, 0);
 
 	if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0)) {
 		unsigned flags = 0;
 		if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0))
 			flags |= MIDX_WRITE_INCREMENTAL;
-		write_midx_file(the_repository, repo_get_object_directory(the_repository),
+		write_midx_file(repo->objects->sources,
 				NULL, NULL, flags);
 	}
 
@@ -1719,10 +554,7 @@ int cmd_repack(int argc,
 	string_list_clear(&keep_pack_list, 0);
 	string_list_clear(&names, 1);
 	existing_packs_release(&existing);
-	free_pack_geometry(&geometry);
-	for (size_t i = 0; i < midx_pack_names_nr; i++)
-		free(midx_pack_names[i]);
-	free(midx_pack_names);
+	pack_geometry_release(&geometry);
 	pack_objects_args_release(&po_args);
 	pack_objects_args_release(&cruft_po_args);
 
diff --git a/builtin/replace.c b/builtin/replace.c
index 900b560..4c62c5a 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -47,30 +47,27 @@ struct show_data {
 	enum replace_format format;
 };
 
-static int show_reference(const char *refname,
-			  const char *referent UNUSED,
-			  const struct object_id *oid,
-			  int flag UNUSED, void *cb_data)
+static int show_reference(const struct reference *ref, void *cb_data)
 {
 	struct show_data *data = cb_data;
 
-	if (!wildmatch(data->pattern, refname, 0)) {
+	if (!wildmatch(data->pattern, ref->name, 0)) {
 		if (data->format == REPLACE_FORMAT_SHORT)
-			printf("%s\n", refname);
+			printf("%s\n", ref->name);
 		else if (data->format == REPLACE_FORMAT_MEDIUM)
-			printf("%s -> %s\n", refname, oid_to_hex(oid));
+			printf("%s -> %s\n", ref->name, oid_to_hex(ref->oid));
 		else { /* data->format == REPLACE_FORMAT_LONG */
 			struct object_id object;
 			enum object_type obj_type, repl_type;
 
-			if (repo_get_oid(data->repo, refname, &object))
-				return error(_("failed to resolve '%s' as a valid ref"), refname);
+			if (repo_get_oid(data->repo, ref->name, &object))
+				return error(_("failed to resolve '%s' as a valid ref"), ref->name);
 
 			obj_type = odb_read_object_info(data->repo->objects, &object, NULL);
-			repl_type = odb_read_object_info(data->repo->objects, oid, NULL);
+			repl_type = odb_read_object_info(data->repo->objects, ref->oid, NULL);
 
-			printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type),
-			       oid_to_hex(oid), type_name(repl_type));
+			printf("%s (%s) -> %s (%s)\n", ref->name, type_name(obj_type),
+			       oid_to_hex(ref->oid), type_name(repl_type));
 		}
 	}
 
diff --git a/builtin/replay.c b/builtin/replay.c
index 6172c8a..6606a2c 100644
--- a/builtin/replay.c
+++ b/builtin/replay.c
@@ -8,6 +8,7 @@
 #include "git-compat-util.h"
 
 #include "builtin.h"
+#include "config.h"
 #include "environment.h"
 #include "hex.h"
 #include "lockfile.h"
@@ -20,6 +21,11 @@
 #include <oidset.h>
 #include <tree.h>
 
+enum ref_action_mode {
+	REF_ACTION_UPDATE,
+	REF_ACTION_PRINT,
+};
+
 static const char *short_commit_name(struct repository *repo,
 				     struct commit *commit)
 {
@@ -284,6 +290,54 @@ static struct commit *pick_regular_commit(struct repository *repo,
 	return create_commit(repo, result->tree, pickme, replayed_base);
 }
 
+static enum ref_action_mode parse_ref_action_mode(const char *ref_action, const char *source)
+{
+	if (!ref_action || !strcmp(ref_action, "update"))
+		return REF_ACTION_UPDATE;
+	if (!strcmp(ref_action, "print"))
+		return REF_ACTION_PRINT;
+	die(_("invalid %s value: '%s'"), source, ref_action);
+}
+
+static enum ref_action_mode get_ref_action_mode(struct repository *repo, const char *ref_action)
+{
+	const char *config_value = NULL;
+
+	/* Command line option takes precedence */
+	if (ref_action)
+		return parse_ref_action_mode(ref_action, "--ref-action");
+
+	/* Check config value */
+	if (!repo_config_get_string_tmp(repo, "replay.refAction", &config_value))
+		return parse_ref_action_mode(config_value, "replay.refAction");
+
+	/* Default to update mode */
+	return REF_ACTION_UPDATE;
+}
+
+static int handle_ref_update(enum ref_action_mode mode,
+			     struct ref_transaction *transaction,
+			     const char *refname,
+			     const struct object_id *new_oid,
+			     const struct object_id *old_oid,
+			     const char *reflog_msg,
+			     struct strbuf *err)
+{
+	switch (mode) {
+	case REF_ACTION_PRINT:
+		printf("update %s %s %s\n",
+		       refname,
+		       oid_to_hex(new_oid),
+		       oid_to_hex(old_oid));
+		return 0;
+	case REF_ACTION_UPDATE:
+		return ref_transaction_update(transaction, refname, new_oid, old_oid,
+					      NULL, NULL, 0, reflog_msg, err);
+	default:
+		BUG("unknown ref_action_mode %d", mode);
+	}
+}
+
 int cmd_replay(int argc,
 	       const char **argv,
 	       const char *prefix,
@@ -294,6 +348,8 @@ int cmd_replay(int argc,
 	struct commit *onto = NULL;
 	const char *onto_name = NULL;
 	int contained = 0;
+	const char *ref_action = NULL;
+	enum ref_action_mode ref_mode;
 
 	struct rev_info revs;
 	struct commit *last_commit = NULL;
@@ -302,12 +358,15 @@ int cmd_replay(int argc,
 	struct merge_result result;
 	struct strset *update_refs = NULL;
 	kh_oid_map_t *replayed_commits;
+	struct ref_transaction *transaction = NULL;
+	struct strbuf transaction_err = STRBUF_INIT;
+	struct strbuf reflog_msg = STRBUF_INIT;
 	int ret = 0;
 
-	const char * const replay_usage[] = {
+	const char *const replay_usage[] = {
 		N_("(EXPERIMENTAL!) git replay "
 		   "([--contained] --onto <newbase> | --advance <branch>) "
-		   "<revision-range>..."),
+		   "[--ref-action[=<mode>]] <revision-range>..."),
 		NULL
 	};
 	struct option replay_options[] = {
@@ -319,6 +378,9 @@ int cmd_replay(int argc,
 			   N_("replay onto given commit")),
 		OPT_BOOL(0, "contained", &contained,
 			 N_("advance all branches contained in revision-range")),
+		OPT_STRING(0, "ref-action", &ref_action,
+			   N_("mode"),
+			   N_("control ref update behavior (update|print)")),
 		OPT_END()
 	};
 
@@ -330,9 +392,12 @@ int cmd_replay(int argc,
 		usage_with_options(replay_usage, replay_options);
 	}
 
-	if (advance_name_opt && contained)
-		die(_("options '%s' and '%s' cannot be used together"),
-		    "--advance", "--contained");
+	die_for_incompatible_opt2(!!advance_name_opt, "--advance",
+				  contained, "--contained");
+
+	/* Parse ref action mode from command line or config */
+	ref_mode = get_ref_action_mode(repo, ref_action);
+
 	advance_name = xstrdup_or_null(advance_name_opt);
 
 	repo_init_revisions(repo, &revs, prefix);
@@ -389,6 +454,24 @@ int cmd_replay(int argc,
 	determine_replay_mode(repo, &revs.cmdline, onto_name, &advance_name,
 			      &onto, &update_refs);
 
+	/* Build reflog message */
+	if (advance_name_opt)
+		strbuf_addf(&reflog_msg, "replay --advance %s", advance_name_opt);
+	else
+		strbuf_addf(&reflog_msg, "replay --onto %s",
+			    oid_to_hex(&onto->object.oid));
+
+	/* Initialize ref transaction if using update mode */
+	if (ref_mode == REF_ACTION_UPDATE) {
+		transaction = ref_store_transaction_begin(get_main_ref_store(repo),
+							  0, &transaction_err);
+		if (!transaction) {
+			ret = error(_("failed to begin ref transaction: %s"),
+				    transaction_err.buf);
+			goto cleanup;
+		}
+	}
+
 	if (!onto) /* FIXME: Should handle replaying down to root commit */
 		die("Replaying down to root commit is not supported yet!");
 
@@ -434,10 +517,16 @@ int cmd_replay(int argc,
 			if (decoration->type == DECORATION_REF_LOCAL &&
 			    (contained || strset_contains(update_refs,
 							  decoration->name))) {
-				printf("update %s %s %s\n",
-				       decoration->name,
-				       oid_to_hex(&last_commit->object.oid),
-				       oid_to_hex(&commit->object.oid));
+				if (handle_ref_update(ref_mode, transaction,
+						      decoration->name,
+						      &last_commit->object.oid,
+						      &commit->object.oid,
+						      reflog_msg.buf,
+						      &transaction_err) < 0) {
+					ret = error(_("failed to update ref '%s': %s"),
+						    decoration->name, transaction_err.buf);
+					goto cleanup;
+				}
 			}
 			decoration = decoration->next;
 		}
@@ -445,10 +534,24 @@ int cmd_replay(int argc,
 
 	/* In --advance mode, advance the target ref */
 	if (result.clean == 1 && advance_name) {
-		printf("update %s %s %s\n",
-		       advance_name,
-		       oid_to_hex(&last_commit->object.oid),
-		       oid_to_hex(&onto->object.oid));
+		if (handle_ref_update(ref_mode, transaction, advance_name,
+				      &last_commit->object.oid,
+				      &onto->object.oid,
+				      reflog_msg.buf,
+				      &transaction_err) < 0) {
+			ret = error(_("failed to update ref '%s': %s"),
+				    advance_name, transaction_err.buf);
+			goto cleanup;
+		}
+	}
+
+	/* Commit the ref transaction if we have one */
+	if (transaction && result.clean == 1) {
+		if (ref_transaction_commit(transaction, &transaction_err)) {
+			ret = error(_("failed to commit ref transaction: %s"),
+				    transaction_err.buf);
+			goto cleanup;
+		}
 	}
 
 	merge_finalize(&merge_opt, &result);
@@ -460,6 +563,10 @@ int cmd_replay(int argc,
 	ret = result.clean;
 
 cleanup:
+	if (transaction)
+		ref_transaction_free(transaction);
+	strbuf_release(&transaction_err);
+	strbuf_release(&reflog_msg);
 	release_revisions(&revs);
 	free(advance_name);
 
diff --git a/builtin/repo.c b/builtin/repo.c
new file mode 100644
index 0000000..40cda71
--- /dev/null
+++ b/builtin/repo.c
@@ -0,0 +1,555 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
+#include "builtin.h"
+#include "environment.h"
+#include "parse-options.h"
+#include "path-walk.h"
+#include "progress.h"
+#include "quote.h"
+#include "ref-filter.h"
+#include "refs.h"
+#include "revision.h"
+#include "strbuf.h"
+#include "string-list.h"
+#include "shallow.h"
+#include "utf8.h"
+
+static const char *const repo_usage[] = {
+	"git repo info [--format=(keyvalue|nul)] [-z] [<key>...]",
+	"git repo structure [--format=(table|keyvalue|nul)]",
+	NULL
+};
+
+typedef int get_value_fn(struct repository *repo, struct strbuf *buf);
+
+enum output_format {
+	FORMAT_TABLE,
+	FORMAT_KEYVALUE,
+	FORMAT_NUL_TERMINATED,
+};
+
+struct field {
+	const char *key;
+	get_value_fn *get_value;
+};
+
+static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	strbuf_addstr(buf, is_bare_repository() ? "true" : "false");
+	return 0;
+}
+
+static int get_layout_shallow(struct repository *repo, struct strbuf *buf)
+{
+	strbuf_addstr(buf,
+		      is_repository_shallow(repo) ? "true" : "false");
+	return 0;
+}
+
+static int get_object_format(struct repository *repo, struct strbuf *buf)
+{
+	strbuf_addstr(buf, repo->hash_algo->name);
+	return 0;
+}
+
+static int get_references_format(struct repository *repo, struct strbuf *buf)
+{
+	strbuf_addstr(buf,
+		      ref_storage_format_to_name(repo->ref_storage_format));
+	return 0;
+}
+
+/* repo_info_fields keys must be in lexicographical order */
+static const struct field repo_info_fields[] = {
+	{ "layout.bare", get_layout_bare },
+	{ "layout.shallow", get_layout_shallow },
+	{ "object.format", get_object_format },
+	{ "references.format", get_references_format },
+};
+
+static int repo_info_fields_cmp(const void *va, const void *vb)
+{
+	const struct field *a = va;
+	const struct field *b = vb;
+
+	return strcmp(a->key, b->key);
+}
+
+static get_value_fn *get_value_fn_for_key(const char *key)
+{
+	const struct field search_key = { key, NULL };
+	const struct field *found = bsearch(&search_key, repo_info_fields,
+					    ARRAY_SIZE(repo_info_fields),
+					    sizeof(*found),
+					    repo_info_fields_cmp);
+	return found ? found->get_value : NULL;
+}
+
+static int print_fields(int argc, const char **argv,
+			struct repository *repo,
+			enum output_format format)
+{
+	int ret = 0;
+	struct strbuf valbuf = STRBUF_INIT;
+	struct strbuf quotbuf = STRBUF_INIT;
+
+	for (int i = 0; i < argc; i++) {
+		get_value_fn *get_value;
+		const char *key = argv[i];
+
+		get_value = get_value_fn_for_key(key);
+
+		if (!get_value) {
+			ret = error(_("key '%s' not found"), key);
+			continue;
+		}
+
+		strbuf_reset(&valbuf);
+		strbuf_reset(&quotbuf);
+
+		get_value(repo, &valbuf);
+
+		switch (format) {
+		case FORMAT_KEYVALUE:
+			quote_c_style(valbuf.buf, &quotbuf, NULL, 0);
+			printf("%s=%s\n", key, quotbuf.buf);
+			break;
+		case FORMAT_NUL_TERMINATED:
+			printf("%s\n%s%c", key, valbuf.buf, '\0');
+			break;
+		default:
+			BUG("not a valid output format: %d", format);
+		}
+	}
+
+	strbuf_release(&valbuf);
+	strbuf_release(&quotbuf);
+	return ret;
+}
+
+static int parse_format_cb(const struct option *opt,
+			   const char *arg, int unset UNUSED)
+{
+	enum output_format *format = opt->value;
+
+	if (opt->short_name == 'z')
+		*format = FORMAT_NUL_TERMINATED;
+	else if (!strcmp(arg, "nul"))
+		*format = FORMAT_NUL_TERMINATED;
+	else if (!strcmp(arg, "keyvalue"))
+		*format = FORMAT_KEYVALUE;
+	else if (!strcmp(arg, "table"))
+		*format = FORMAT_TABLE;
+	else
+		die(_("invalid format '%s'"), arg);
+
+	return 0;
+}
+
+static int cmd_repo_info(int argc, const char **argv, const char *prefix,
+			 struct repository *repo)
+{
+	enum output_format format = FORMAT_KEYVALUE;
+	struct option options[] = {
+		OPT_CALLBACK_F(0, "format", &format, N_("format"),
+			       N_("output format"),
+			       PARSE_OPT_NONEG, parse_format_cb),
+		OPT_CALLBACK_F('z', NULL, &format, NULL,
+			       N_("synonym for --format=nul"),
+			       PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+			       parse_format_cb),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, options, repo_usage, 0);
+	if (format != FORMAT_KEYVALUE && format != FORMAT_NUL_TERMINATED)
+		die(_("unsupported output format"));
+
+	return print_fields(argc, argv, repo, format);
+}
+
+struct ref_stats {
+	size_t branches;
+	size_t remotes;
+	size_t tags;
+	size_t others;
+};
+
+struct object_stats {
+	size_t tags;
+	size_t commits;
+	size_t trees;
+	size_t blobs;
+};
+
+struct repo_structure {
+	struct ref_stats refs;
+	struct object_stats objects;
+};
+
+struct stats_table {
+	struct string_list rows;
+
+	int name_col_width;
+	int value_col_width;
+};
+
+/*
+ * Holds column data that gets stored for each row.
+ */
+struct stats_table_entry {
+	char *value;
+};
+
+static void stats_table_vaddf(struct stats_table *table,
+			      struct stats_table_entry *entry,
+			      const char *format, va_list ap)
+{
+	struct strbuf buf = STRBUF_INIT;
+	struct string_list_item *item;
+	char *formatted_name;
+	int name_width;
+
+	strbuf_vaddf(&buf, format, ap);
+	formatted_name = strbuf_detach(&buf, NULL);
+	name_width = utf8_strwidth(formatted_name);
+
+	item = string_list_append_nodup(&table->rows, formatted_name);
+	item->util = entry;
+
+	if (name_width > table->name_col_width)
+		table->name_col_width = name_width;
+	if (entry) {
+		int value_width = utf8_strwidth(entry->value);
+		if (value_width > table->value_col_width)
+			table->value_col_width = value_width;
+	}
+}
+
+static void stats_table_addf(struct stats_table *table, const char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+	stats_table_vaddf(table, NULL, format, ap);
+	va_end(ap);
+}
+
+static void stats_table_count_addf(struct stats_table *table, size_t value,
+				   const char *format, ...)
+{
+	struct stats_table_entry *entry;
+	va_list ap;
+
+	CALLOC_ARRAY(entry, 1);
+	entry->value = xstrfmt("%" PRIuMAX, (uintmax_t)value);
+
+	va_start(ap, format);
+	stats_table_vaddf(table, entry, format, ap);
+	va_end(ap);
+}
+
+static inline size_t get_total_reference_count(struct ref_stats *stats)
+{
+	return stats->branches + stats->remotes + stats->tags + stats->others;
+}
+
+static inline size_t get_total_object_count(struct object_stats *stats)
+{
+	return stats->tags + stats->commits + stats->trees + stats->blobs;
+}
+
+static void stats_table_setup_structure(struct stats_table *table,
+					struct repo_structure *stats)
+{
+	struct object_stats *objects = &stats->objects;
+	struct ref_stats *refs = &stats->refs;
+	size_t object_total;
+	size_t ref_total;
+
+	ref_total = get_total_reference_count(refs);
+	stats_table_addf(table, "* %s", _("References"));
+	stats_table_count_addf(table, ref_total, "  * %s", _("Count"));
+	stats_table_count_addf(table, refs->branches, "    * %s", _("Branches"));
+	stats_table_count_addf(table, refs->tags, "    * %s", _("Tags"));
+	stats_table_count_addf(table, refs->remotes, "    * %s", _("Remotes"));
+	stats_table_count_addf(table, refs->others, "    * %s", _("Others"));
+
+	object_total = get_total_object_count(objects);
+	stats_table_addf(table, "");
+	stats_table_addf(table, "* %s", _("Reachable objects"));
+	stats_table_count_addf(table, object_total, "  * %s", _("Count"));
+	stats_table_count_addf(table, objects->commits, "    * %s", _("Commits"));
+	stats_table_count_addf(table, objects->trees, "    * %s", _("Trees"));
+	stats_table_count_addf(table, objects->blobs, "    * %s", _("Blobs"));
+	stats_table_count_addf(table, objects->tags, "    * %s", _("Tags"));
+}
+
+static void stats_table_print_structure(const struct stats_table *table)
+{
+	const char *name_col_title = _("Repository structure");
+	const char *value_col_title = _("Value");
+	int name_col_width = utf8_strwidth(name_col_title);
+	int value_col_width = utf8_strwidth(value_col_title);
+	struct string_list_item *item;
+	struct strbuf buf = STRBUF_INIT;
+
+	if (table->name_col_width > name_col_width)
+		name_col_width = table->name_col_width;
+	if (table->value_col_width > value_col_width)
+		value_col_width = table->value_col_width;
+
+	strbuf_addstr(&buf, "| ");
+	strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, name_col_title);
+	strbuf_addstr(&buf, " | ");
+	strbuf_utf8_align(&buf, ALIGN_LEFT, value_col_width, value_col_title);
+	strbuf_addstr(&buf, " |");
+	printf("%s\n", buf.buf);
+
+	printf("| ");
+	for (int i = 0; i < name_col_width; i++)
+		putchar('-');
+	printf(" | ");
+	for (int i = 0; i < value_col_width; i++)
+		putchar('-');
+	printf(" |\n");
+
+	for_each_string_list_item(item, &table->rows) {
+		struct stats_table_entry *entry = item->util;
+		const char *value = "";
+
+		if (entry) {
+			struct stats_table_entry *entry = item->util;
+			value = entry->value;
+		}
+
+		strbuf_reset(&buf);
+		strbuf_addstr(&buf, "| ");
+		strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, item->string);
+		strbuf_addstr(&buf, " | ");
+		strbuf_utf8_align(&buf, ALIGN_RIGHT, value_col_width, value);
+		strbuf_addstr(&buf, " |");
+		printf("%s\n", buf.buf);
+	}
+
+	strbuf_release(&buf);
+}
+
+static void stats_table_clear(struct stats_table *table)
+{
+	struct stats_table_entry *entry;
+	struct string_list_item *item;
+
+	for_each_string_list_item(item, &table->rows) {
+		entry = item->util;
+		if (entry)
+			free(entry->value);
+	}
+
+	string_list_clear(&table->rows, 1);
+}
+
+static void structure_keyvalue_print(struct repo_structure *stats,
+				     char key_delim, char value_delim)
+{
+	printf("references.branches.count%c%" PRIuMAX "%c", key_delim,
+	       (uintmax_t)stats->refs.branches, value_delim);
+	printf("references.tags.count%c%" PRIuMAX "%c", key_delim,
+	       (uintmax_t)stats->refs.tags, value_delim);
+	printf("references.remotes.count%c%" PRIuMAX "%c", key_delim,
+	       (uintmax_t)stats->refs.remotes, value_delim);
+	printf("references.others.count%c%" PRIuMAX "%c", key_delim,
+	       (uintmax_t)stats->refs.others, value_delim);
+
+	printf("objects.commits.count%c%" PRIuMAX "%c", key_delim,
+	       (uintmax_t)stats->objects.commits, value_delim);
+	printf("objects.trees.count%c%" PRIuMAX "%c", key_delim,
+	       (uintmax_t)stats->objects.trees, value_delim);
+	printf("objects.blobs.count%c%" PRIuMAX "%c", key_delim,
+	       (uintmax_t)stats->objects.blobs, value_delim);
+	printf("objects.tags.count%c%" PRIuMAX "%c", key_delim,
+	       (uintmax_t)stats->objects.tags, value_delim);
+
+	fflush(stdout);
+}
+
+struct count_references_data {
+	struct ref_stats *stats;
+	struct rev_info *revs;
+	struct progress *progress;
+};
+
+static int count_references(const struct reference *ref, void *cb_data)
+{
+	struct count_references_data *data = cb_data;
+	struct ref_stats *stats = data->stats;
+	size_t ref_count;
+
+	switch (ref_kind_from_refname(ref->name)) {
+	case FILTER_REFS_BRANCHES:
+		stats->branches++;
+		break;
+	case FILTER_REFS_REMOTES:
+		stats->remotes++;
+		break;
+	case FILTER_REFS_TAGS:
+		stats->tags++;
+		break;
+	case FILTER_REFS_OTHERS:
+		stats->others++;
+		break;
+	default:
+		BUG("unexpected reference type");
+	}
+
+	/*
+	 * While iterating through references for counting, also add OIDs in
+	 * preparation for the path walk.
+	 */
+	add_pending_oid(data->revs, NULL, ref->oid, 0);
+
+	ref_count = get_total_reference_count(stats);
+	display_progress(data->progress, ref_count);
+
+	return 0;
+}
+
+static void structure_count_references(struct ref_stats *stats,
+				       struct rev_info *revs,
+				       struct repository *repo,
+				       int show_progress)
+{
+	struct count_references_data data = {
+		.stats = stats,
+		.revs = revs,
+	};
+
+	if (show_progress)
+		data.progress = start_delayed_progress(repo,
+						       _("Counting references"), 0);
+
+	refs_for_each_ref(get_main_ref_store(repo), count_references, &data);
+	stop_progress(&data.progress);
+}
+
+struct count_objects_data {
+	struct object_stats *stats;
+	struct progress *progress;
+};
+
+static int count_objects(const char *path UNUSED, struct oid_array *oids,
+			 enum object_type type, void *cb_data)
+{
+	struct count_objects_data *data = cb_data;
+	struct object_stats *stats = data->stats;
+	size_t object_count;
+
+	switch (type) {
+	case OBJ_TAG:
+		stats->tags += oids->nr;
+		break;
+	case OBJ_COMMIT:
+		stats->commits += oids->nr;
+		break;
+	case OBJ_TREE:
+		stats->trees += oids->nr;
+		break;
+	case OBJ_BLOB:
+		stats->blobs += oids->nr;
+		break;
+	default:
+		BUG("invalid object type");
+	}
+
+	object_count = get_total_object_count(stats);
+	display_progress(data->progress, object_count);
+
+	return 0;
+}
+
+static void structure_count_objects(struct object_stats *stats,
+				    struct rev_info *revs,
+				    struct repository *repo, int show_progress)
+{
+	struct path_walk_info info = PATH_WALK_INFO_INIT;
+	struct count_objects_data data = {
+		.stats = stats,
+	};
+
+	info.revs = revs;
+	info.path_fn = count_objects;
+	info.path_fn_data = &data;
+
+	if (show_progress)
+		data.progress = start_delayed_progress(repo, _("Counting objects"), 0);
+
+	walk_objects_by_path(&info);
+	path_walk_info_clear(&info);
+	stop_progress(&data.progress);
+}
+
+static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
+			      struct repository *repo)
+{
+	struct stats_table table = {
+		.rows = STRING_LIST_INIT_DUP,
+	};
+	enum output_format format = FORMAT_TABLE;
+	struct repo_structure stats = { 0 };
+	struct rev_info revs;
+	int show_progress = -1;
+	struct option options[] = {
+		OPT_CALLBACK_F(0, "format", &format, N_("format"),
+			       N_("output format"),
+			       PARSE_OPT_NONEG, parse_format_cb),
+		OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, options, repo_usage, 0);
+	if (argc)
+		usage(_("too many arguments"));
+
+	repo_init_revisions(repo, &revs, prefix);
+
+	if (show_progress < 0)
+		show_progress = isatty(2);
+
+	structure_count_references(&stats.refs, &revs, repo, show_progress);
+	structure_count_objects(&stats.objects, &revs, repo, show_progress);
+
+	switch (format) {
+	case FORMAT_TABLE:
+		stats_table_setup_structure(&table, &stats);
+		stats_table_print_structure(&table);
+		break;
+	case FORMAT_KEYVALUE:
+		structure_keyvalue_print(&stats, '=', '\n');
+		break;
+	case FORMAT_NUL_TERMINATED:
+		structure_keyvalue_print(&stats, '\n', '\0');
+		break;
+	default:
+		BUG("invalid output format");
+	}
+
+	stats_table_clear(&table);
+	release_revisions(&revs);
+
+	return 0;
+}
+
+int cmd_repo(int argc, const char **argv, const char *prefix,
+	     struct repository *repo)
+{
+	parse_opt_subcommand_fn *fn = NULL;
+	struct option options[] = {
+		OPT_SUBCOMMAND("info", &fn, cmd_repo_info),
+		OPT_SUBCOMMAND("structure", &fn, cmd_repo_structure),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, options, repo_usage, 0);
+
+	return fn(argc, argv, prefix, repo);
+}
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 44ff1b8..9032cc6 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -217,19 +217,17 @@ static int show_default(void)
 	return 0;
 }
 
-static int show_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			  int flag UNUSED, void *cb_data UNUSED)
+static int show_reference(const struct reference *ref, void *cb_data UNUSED)
 {
-	if (ref_excluded(&ref_excludes, refname))
+	if (ref_excluded(&ref_excludes, ref->name))
 		return 0;
-	show_rev(NORMAL, oid, refname);
+	show_rev(NORMAL, ref->oid, ref->name);
 	return 0;
 }
 
-static int anti_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			  int flag UNUSED, void *cb_data UNUSED)
+static int anti_reference(const struct reference *ref, void *cb_data UNUSED)
 {
-	show_rev(REVERSED, oid, refname);
+	show_rev(REVERSED, ref->oid, ref->name);
 	return 0;
 }
 
@@ -708,7 +706,6 @@ int cmd_rev_parse(int argc,
 	struct object_id oid;
 	unsigned int flags = 0;
 	const char *name = NULL;
-	struct object_context unused;
 	struct strbuf buf = STRBUF_INIT;
 	int seen_end_of_options = 0;
 	enum format_type format = FORMAT_DEFAULT;
@@ -1108,11 +1105,20 @@ int cmd_rev_parse(int argc,
 				const char *val = arg ? arg : "storage";
 
 				if (strcmp(val, "storage") &&
+				    strcmp(val, "compat") &&
 				    strcmp(val, "input") &&
 				    strcmp(val, "output"))
 					die(_("unknown mode for --show-object-format: %s"),
 					    arg);
-				puts(the_hash_algo->name);
+
+				if (!strcmp(val, "compat")) {
+					if (the_repository->compat_hash_algo)
+						puts(the_repository->compat_hash_algo->name);
+					else
+						putchar('\n');
+				} else {
+					puts(the_hash_algo->name);
+				}
 				continue;
 			}
 			if (!strcmp(arg, "--show-ref-format")) {
@@ -1141,9 +1147,8 @@ int cmd_rev_parse(int argc,
 			name++;
 			type = REVERSED;
 		}
-		if (!get_oid_with_context(the_repository, name,
-					  flags, &oid, &unused)) {
-			object_context_release(&unused);
+		if (!repo_get_oid_with_flags(the_repository, name, &oid,
+					     flags)) {
 			if (output_algo)
 				repo_oid_to_algop(the_repository, &oid,
 						  output_algo, &oid);
@@ -1153,7 +1158,6 @@ int cmd_rev_parse(int argc,
 				show_rev(type, &oid, name);
 			continue;
 		}
-		object_context_release(&unused);
 		if (verify)
 			die_no_single_rev(quiet);
 		if (has_dashdash)
diff --git a/builtin/revert.c b/builtin/revert.c
index c3f92b5..bedc40f 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -4,6 +4,7 @@
 #include "builtin.h"
 #include "parse-options.h"
 #include "diff.h"
+#include "environment.h"
 #include "gettext.h"
 #include "revision.h"
 #include "rerere.h"
@@ -285,6 +286,9 @@ int cmd_revert(int argc,
 	struct replay_opts opts = REPLAY_OPTS_INIT;
 	int res;
 
+#ifndef WITH_BREAKING_CHANGES
+	warn_on_auto_comment_char = true;
+#endif /* !WITH_BREAKING_CHANGES */
 	opts.action = REPLAY_REVERT;
 	sequencer_init_config(&opts);
 	res = run_sequencer(argc, argv, prefix, &opts);
@@ -302,6 +306,9 @@ struct repository *repo UNUSED)
 	struct replay_opts opts = REPLAY_OPTS_INIT;
 	int res;
 
+#ifndef WITH_BREAKING_CHANGES
+	warn_on_auto_comment_char = true;
+#endif /* !WITH_BREAKING_CHANGES */
 	opts.action = REPLAY_PICK;
 	sequencer_init_config(&opts);
 	res = run_sequencer(argc, argv, prefix, &opts);
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 1ab7db9..10475a6 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -29,7 +29,7 @@ static const char*const show_branch_usage[] = {
     NULL
 };
 
-static int showbranch_use_color = -1;
+static enum git_colorbool showbranch_use_color = GIT_COLOR_UNKNOWN;
 
 static struct strvec default_args = STRVEC_INIT;
 
@@ -413,34 +413,32 @@ static int append_ref(const char *refname, const struct object_id *oid,
 	return 0;
 }
 
-static int append_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			   int flag UNUSED, void *cb_data UNUSED)
+static int append_head_ref(const struct reference *ref, void *cb_data UNUSED)
 {
 	struct object_id tmp;
 	int ofs = 11;
-	if (!starts_with(refname, "refs/heads/"))
+	if (!starts_with(ref->name, "refs/heads/"))
 		return 0;
 	/* If both heads/foo and tags/foo exists, get_sha1 would
 	 * get confused.
 	 */
-	if (repo_get_oid(the_repository, refname + ofs, &tmp) || !oideq(&tmp, oid))
+	if (repo_get_oid(the_repository, ref->name + ofs, &tmp) || !oideq(&tmp, ref->oid))
 		ofs = 5;
-	return append_ref(refname + ofs, oid, 0);
+	return append_ref(ref->name + ofs, ref->oid, 0);
 }
 
-static int append_remote_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			     int flag UNUSED, void *cb_data UNUSED)
+static int append_remote_ref(const struct reference *ref, void *cb_data UNUSED)
 {
 	struct object_id tmp;
 	int ofs = 13;
-	if (!starts_with(refname, "refs/remotes/"))
+	if (!starts_with(ref->name, "refs/remotes/"))
 		return 0;
 	/* If both heads/foo and tags/foo exists, get_sha1 would
 	 * get confused.
 	 */
-	if (repo_get_oid(the_repository, refname + ofs, &tmp) || !oideq(&tmp, oid))
+	if (repo_get_oid(the_repository, ref->name + ofs, &tmp) || !oideq(&tmp, ref->oid))
 		ofs = 5;
-	return append_ref(refname + ofs, oid, 0);
+	return append_ref(ref->name + ofs, ref->oid, 0);
 }
 
 static int append_tag_ref(const char *refname, const struct object_id *oid,
@@ -454,27 +452,26 @@ static int append_tag_ref(const char *refname, const struct object_id *oid,
 static const char *match_ref_pattern = NULL;
 static int match_ref_slash = 0;
 
-static int append_matching_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			       int flag, void *cb_data)
+static int append_matching_ref(const struct reference *ref, void *cb_data)
 {
 	/* we want to allow pattern hold/<asterisk> to show all
 	 * branches under refs/heads/hold/, and v0.99.9? to show
 	 * refs/tags/v0.99.9a and friends.
 	 */
 	const char *tail;
-	int slash = count_slashes(refname);
-	for (tail = refname; *tail && match_ref_slash < slash; )
+	int slash = count_slashes(ref->name);
+	for (tail = ref->name; *tail && match_ref_slash < slash; )
 		if (*tail++ == '/')
 			slash--;
 	if (!*tail)
 		return 0;
 	if (wildmatch(match_ref_pattern, tail, 0))
 		return 0;
-	if (starts_with(refname, "refs/heads/"))
-		return append_head_ref(refname, NULL, oid, flag, cb_data);
-	if (starts_with(refname, "refs/tags/"))
-		return append_tag_ref(refname, oid, flag, cb_data);
-	return append_ref(refname, oid, 0);
+	if (starts_with(ref->name, "refs/heads/"))
+		return append_head_ref(ref, cb_data);
+	if (starts_with(ref->name, "refs/tags/"))
+		return append_tag_ref(ref->name, ref->oid, ref->flags, cb_data);
+	return append_ref(ref->name, ref->oid, 0);
 }
 
 static void snarf_refs(int head, int remotes)
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 0b6f9ed..4d4984e 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -31,31 +31,31 @@ struct show_one_options {
 };
 
 static void show_one(const struct show_one_options *opts,
-		     const char *refname, const struct object_id *oid)
+		     const struct reference *ref)
 {
 	const char *hex;
 	struct object_id peeled;
 
-	if (!odb_has_object(the_repository->objects, oid,
+	if (!odb_has_object(the_repository->objects, ref->oid,
 			    HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
-		die("git show-ref: bad ref %s (%s)", refname,
-		    oid_to_hex(oid));
+		die("git show-ref: bad ref %s (%s)", ref->name,
+		    oid_to_hex(ref->oid));
 
 	if (opts->quiet)
 		return;
 
-	hex = repo_find_unique_abbrev(the_repository, oid, opts->abbrev);
+	hex = repo_find_unique_abbrev(the_repository, ref->oid, opts->abbrev);
 	if (opts->hash_only)
 		printf("%s\n", hex);
 	else
-		printf("%s %s\n", hex, refname);
+		printf("%s %s\n", hex, ref->name);
 
 	if (!opts->deref_tags)
 		return;
 
-	if (!peel_iterated_oid(the_repository, oid, &peeled)) {
+	if (!reference_get_peeled_oid(the_repository, ref, &peeled)) {
 		hex = repo_find_unique_abbrev(the_repository, &peeled, opts->abbrev);
-		printf("%s %s^{}\n", hex, refname);
+		printf("%s %s^{}\n", hex, ref->name);
 	}
 }
 
@@ -66,26 +66,25 @@ struct show_ref_data {
 	int show_head;
 };
 
-static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-		    int flag UNUSED, void *cbdata)
+static int show_ref(const struct reference *ref, void *cbdata)
 {
 	struct show_ref_data *data = cbdata;
 
-	if (data->show_head && !strcmp(refname, "HEAD"))
+	if (data->show_head && !strcmp(ref->name, "HEAD"))
 		goto match;
 
 	if (data->patterns) {
-		int reflen = strlen(refname);
+		int reflen = strlen(ref->name);
 		const char **p = data->patterns, *m;
 		while ((m = *p++) != NULL) {
 			int len = strlen(m);
 			if (len > reflen)
 				continue;
-			if (memcmp(m, refname + reflen - len, len))
+			if (memcmp(m, ref->name + reflen - len, len))
 				continue;
 			if (len == reflen)
 				goto match;
-			if (refname[reflen - len - 1] == '/')
+			if (ref->name[reflen - len - 1] == '/')
 				goto match;
 		}
 		return 0;
@@ -94,18 +93,15 @@ static int show_ref(const char *refname, const char *referent UNUSED, const stru
 match:
 	data->found_match++;
 
-	show_one(data->show_one_opts, refname, oid);
+	show_one(data->show_one_opts, ref);
 
 	return 0;
 }
 
-static int add_existing(const char *refname,
-			const char *referent UNUSED,
-			const struct object_id *oid UNUSED,
-			int flag UNUSED, void *cbdata)
+static int add_existing(const struct reference *ref, void *cbdata)
 {
 	struct string_list *list = (struct string_list *)cbdata;
-	string_list_insert(list, refname);
+	string_list_insert(list, ref->name);
 	return 0;
 }
 
@@ -179,12 +175,18 @@ static int cmd_show_ref__verify(const struct show_one_options *show_one_opts,
 
 		if ((starts_with(*refs, "refs/") || refname_is_safe(*refs)) &&
 		    !refs_read_ref(get_main_ref_store(the_repository), *refs, &oid)) {
-			show_one(show_one_opts, *refs, &oid);
-		}
-		else if (!show_one_opts->quiet)
+			struct reference ref = {
+				.name = *refs,
+				.oid = &oid,
+			};
+
+			show_one(show_one_opts, &ref);
+		} else if (!show_one_opts->quiet) {
 			die("'%s' - not a valid ref", *refs);
-		else
+		} else {
 			return 1;
+		}
+
 		refs++;
 	}
 
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 8c333b3..15d51e6 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -2,6 +2,7 @@
 #define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "builtin.h"
+#include "abspath.h"
 #include "config.h"
 #include "dir.h"
 #include "environment.h"
@@ -23,7 +24,7 @@
 static const char *empty_base = "";
 
 static char const * const builtin_sparse_checkout_usage[] = {
-	N_("git sparse-checkout (init | list | set | add | reapply | disable | check-rules) [<options>]"),
+	N_("git sparse-checkout (init | list | set | add | reapply | disable | check-rules | clean) [<options>]"),
 	NULL
 };
 
@@ -204,12 +205,12 @@ static void clean_tracked_sparse_directories(struct repository *r)
 		ensure_full_index(r->index);
 }
 
-static int update_working_directory(struct pattern_list *pl)
+static int update_working_directory(struct repository *r,
+				    struct pattern_list *pl)
 {
 	enum update_sparsity_result result;
 	struct unpack_trees_options o;
 	struct lock_file lock_file = LOCK_INIT;
-	struct repository *r = the_repository;
 	struct pattern_list *old_pl;
 
 	/* If no branch has been checked out, there are no updates to make. */
@@ -327,7 +328,8 @@ static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
 	string_list_clear(&sl, 0);
 }
 
-static int write_patterns_and_update(struct pattern_list *pl)
+static int write_patterns_and_update(struct repository *repo,
+				     struct pattern_list *pl)
 {
 	char *sparse_filename;
 	FILE *fp;
@@ -336,15 +338,15 @@ static int write_patterns_and_update(struct pattern_list *pl)
 
 	sparse_filename = get_sparse_checkout_filename();
 
-	if (safe_create_leading_directories(the_repository, sparse_filename))
+	if (safe_create_leading_directories(repo, sparse_filename))
 		die(_("failed to create directory for sparse-checkout file"));
 
 	hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR);
 
-	result = update_working_directory(pl);
+	result = update_working_directory(repo, pl);
 	if (result) {
 		rollback_lock_file(&lk);
-		update_working_directory(NULL);
+		update_working_directory(repo, NULL);
 		goto out;
 	}
 
@@ -372,25 +374,26 @@ enum sparse_checkout_mode {
 	MODE_CONE_PATTERNS = 2,
 };
 
-static int set_config(enum sparse_checkout_mode mode)
+static int set_config(struct repository *repo,
+		      enum sparse_checkout_mode mode)
 {
 	/* Update to use worktree config, if not already. */
-	if (init_worktree_config(the_repository)) {
+	if (init_worktree_config(repo)) {
 		error(_("failed to initialize worktree config"));
 		return 1;
 	}
 
-	if (repo_config_set_worktree_gently(the_repository,
+	if (repo_config_set_worktree_gently(repo,
 					    "core.sparseCheckout",
 					    mode ? "true" : "false") ||
-	    repo_config_set_worktree_gently(the_repository,
+	    repo_config_set_worktree_gently(repo,
 					    "core.sparseCheckoutCone",
 					    mode == MODE_CONE_PATTERNS ?
 						"true" : "false"))
 		return 1;
 
 	if (mode == MODE_NO_PATTERNS)
-		return set_sparse_index_config(the_repository, 0);
+		return set_sparse_index_config(repo, 0);
 
 	return 0;
 }
@@ -410,7 +413,7 @@ static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {
 	return MODE_ALL_PATTERNS;
 }
 
-static int update_modes(int *cone_mode, int *sparse_index)
+static int update_modes(struct repository *repo, int *cone_mode, int *sparse_index)
 {
 	int mode, record_mode;
 
@@ -418,20 +421,20 @@ static int update_modes(int *cone_mode, int *sparse_index)
 	record_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;
 
 	mode = update_cone_mode(cone_mode);
-	if (record_mode && set_config(mode))
+	if (record_mode && set_config(repo, mode))
 		return 1;
 
 	/* Set sparse-index/non-sparse-index mode if specified */
 	if (*sparse_index >= 0) {
-		if (set_sparse_index_config(the_repository, *sparse_index) < 0)
+		if (set_sparse_index_config(repo, *sparse_index) < 0)
 			die(_("failed to modify sparse-index config"));
 
 		/* force an index rewrite */
-		repo_read_index(the_repository);
-		the_repository->index->updated_workdir = 1;
+		repo_read_index(repo);
+		repo->index->updated_workdir = 1;
 
 		if (!*sparse_index)
-			ensure_full_index(the_repository->index);
+			ensure_full_index(repo->index);
 	}
 
 	return 0;
@@ -448,7 +451,7 @@ static struct sparse_checkout_init_opts {
 } init_opts;
 
 static int sparse_checkout_init(int argc, const char **argv, const char *prefix,
-				struct repository *repo UNUSED)
+				struct repository *repo)
 {
 	struct pattern_list pl;
 	char *sparse_filename;
@@ -464,7 +467,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix,
 	};
 
 	setup_work_tree();
-	repo_read_index(the_repository);
+	repo_read_index(repo);
 
 	init_opts.cone_mode = -1;
 	init_opts.sparse_index = -1;
@@ -473,7 +476,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix,
 			     builtin_sparse_checkout_init_options,
 			     builtin_sparse_checkout_init_usage, 0);
 
-	if (update_modes(&init_opts.cone_mode, &init_opts.sparse_index))
+	if (update_modes(repo, &init_opts.cone_mode, &init_opts.sparse_index))
 		return 1;
 
 	memset(&pl, 0, sizeof(pl));
@@ -485,14 +488,14 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix,
 	if (res >= 0) {
 		free(sparse_filename);
 		clear_pattern_list(&pl);
-		return update_working_directory(NULL);
+		return update_working_directory(repo, NULL);
 	}
 
-	if (repo_get_oid(the_repository, "HEAD", &oid)) {
+	if (repo_get_oid(repo, "HEAD", &oid)) {
 		FILE *fp;
 
 		/* assume we are in a fresh repo, but update the sparse-checkout file */
-		if (safe_create_leading_directories(the_repository, sparse_filename))
+		if (safe_create_leading_directories(repo, sparse_filename))
 			die(_("unable to create leading directories of %s"),
 			    sparse_filename);
 		fp = xfopen(sparse_filename, "w");
@@ -511,7 +514,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix,
 	add_pattern("!/*/", empty_base, 0, &pl, 0);
 	pl.use_cone_patterns = init_opts.cone_mode;
 
-	return write_patterns_and_update(&pl);
+	return write_patterns_and_update(repo, &pl);
 }
 
 static void insert_recursive_pattern(struct pattern_list *pl, struct strbuf *path)
@@ -674,7 +677,8 @@ static void add_patterns_literal(int argc, const char **argv,
 	add_patterns_from_input(pl, argc, argv, use_stdin ? stdin : NULL);
 }
 
-static int modify_pattern_list(struct strvec *args, int use_stdin,
+static int modify_pattern_list(struct repository *repo,
+			       struct strvec *args, int use_stdin,
 			       enum modify_type m)
 {
 	int result;
@@ -696,22 +700,23 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,
 	}
 
 	if (!core_apply_sparse_checkout) {
-		set_config(MODE_ALL_PATTERNS);
+		set_config(repo, MODE_ALL_PATTERNS);
 		core_apply_sparse_checkout = 1;
 		changed_config = 1;
 	}
 
-	result = write_patterns_and_update(pl);
+	result = write_patterns_and_update(repo, pl);
 
 	if (result && changed_config)
-		set_config(MODE_NO_PATTERNS);
+		set_config(repo, MODE_NO_PATTERNS);
 
 	clear_pattern_list(pl);
 	free(pl);
 	return result;
 }
 
-static void sanitize_paths(struct strvec *args,
+static void sanitize_paths(struct repository *repo,
+			   struct strvec *args,
 			   const char *prefix, int skip_checks)
 {
 	int i;
@@ -752,7 +757,7 @@ static void sanitize_paths(struct strvec *args,
 
 	for (i = 0; i < args->nr; i++) {
 		struct cache_entry *ce;
-		struct index_state *index = the_repository->index;
+		struct index_state *index = repo->index;
 		int pos = index_name_pos(index, args->v[i], strlen(args->v[i]));
 
 		if (pos < 0)
@@ -779,7 +784,7 @@ static struct sparse_checkout_add_opts {
 } add_opts;
 
 static int sparse_checkout_add(int argc, const char **argv, const char *prefix,
-			       struct repository *repo UNUSED)
+			       struct repository *repo)
 {
 	static struct option builtin_sparse_checkout_add_options[] = {
 		OPT_BOOL_F(0, "skip-checks", &add_opts.skip_checks,
@@ -796,7 +801,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,
 	if (!core_apply_sparse_checkout)
 		die(_("no sparse-checkout to add to"));
 
-	repo_read_index(the_repository);
+	repo_read_index(repo);
 
 	argc = parse_options(argc, argv, prefix,
 			     builtin_sparse_checkout_add_options,
@@ -804,9 +809,9 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,
 
 	for (int i = 0; i < argc; i++)
 		strvec_push(&patterns, argv[i]);
-	sanitize_paths(&patterns, prefix, add_opts.skip_checks);
+	sanitize_paths(repo, &patterns, prefix, add_opts.skip_checks);
 
-	ret = modify_pattern_list(&patterns, add_opts.use_stdin, ADD);
+	ret = modify_pattern_list(repo, &patterns, add_opts.use_stdin, ADD);
 
 	strvec_clear(&patterns);
 	return ret;
@@ -825,7 +830,7 @@ static struct sparse_checkout_set_opts {
 } set_opts;
 
 static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
-			       struct repository *repo UNUSED)
+			       struct repository *repo)
 {
 	int default_patterns_nr = 2;
 	const char *default_patterns[] = {"/*", "!/*/", NULL};
@@ -847,7 +852,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
 	int ret;
 
 	setup_work_tree();
-	repo_read_index(the_repository);
+	repo_read_index(repo);
 
 	set_opts.cone_mode = -1;
 	set_opts.sparse_index = -1;
@@ -856,7 +861,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
 			     builtin_sparse_checkout_set_options,
 			     builtin_sparse_checkout_set_usage, 0);
 
-	if (update_modes(&set_opts.cone_mode, &set_opts.sparse_index))
+	if (update_modes(repo, &set_opts.cone_mode, &set_opts.sparse_index))
 		return 1;
 
 	/*
@@ -870,10 +875,10 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
 	} else {
 		for (int i = 0; i < argc; i++)
 			strvec_push(&patterns, argv[i]);
-		sanitize_paths(&patterns, prefix, set_opts.skip_checks);
+		sanitize_paths(repo, &patterns, prefix, set_opts.skip_checks);
 	}
 
-	ret = modify_pattern_list(&patterns, set_opts.use_stdin, REPLACE);
+	ret = modify_pattern_list(repo, &patterns, set_opts.use_stdin, REPLACE);
 
 	strvec_clear(&patterns);
 	return ret;
@@ -891,7 +896,7 @@ static struct sparse_checkout_reapply_opts {
 
 static int sparse_checkout_reapply(int argc, const char **argv,
 				   const char *prefix,
-				   struct repository *repo UNUSED)
+				   struct repository *repo)
 {
 	static struct option builtin_sparse_checkout_reapply_options[] = {
 		OPT_BOOL(0, "cone", &reapply_opts.cone_mode,
@@ -912,12 +917,107 @@ static int sparse_checkout_reapply(int argc, const char **argv,
 			     builtin_sparse_checkout_reapply_options,
 			     builtin_sparse_checkout_reapply_usage, 0);
 
-	repo_read_index(the_repository);
+	repo_read_index(repo);
 
-	if (update_modes(&reapply_opts.cone_mode, &reapply_opts.sparse_index))
+	if (update_modes(repo, &reapply_opts.cone_mode, &reapply_opts.sparse_index))
 		return 1;
 
-	return update_working_directory(NULL);
+	return update_working_directory(repo, NULL);
+}
+
+static char const * const builtin_sparse_checkout_clean_usage[] = {
+	"git sparse-checkout clean [-n|--dry-run]",
+	NULL
+};
+
+static int list_file_iterator(const char *path, const void *data)
+{
+	const char *msg = data;
+
+	printf(msg, path);
+	return 0;
+}
+
+static void list_every_file_in_dir(const char *msg,
+				   const char *directory)
+{
+	struct strbuf path = STRBUF_INIT;
+
+	strbuf_addstr(&path, directory);
+	for_each_file_in_dir(&path, list_file_iterator, msg);
+	strbuf_release(&path);
+}
+
+static const char *msg_remove = N_("Removing %s\n");
+static const char *msg_would_remove = N_("Would remove %s\n");
+
+static int sparse_checkout_clean(int argc, const char **argv,
+				   const char *prefix,
+				   struct repository *repo)
+{
+	struct strbuf full_path = STRBUF_INIT;
+	const char *msg = msg_remove;
+	size_t worktree_len;
+	int force = 0, dry_run = 0, verbose = 0;
+	int require_force = 1;
+
+	struct option builtin_sparse_checkout_clean_options[] = {
+		OPT__DRY_RUN(&dry_run, N_("dry run")),
+		OPT__FORCE(&force, N_("force"), PARSE_OPT_NOCOMPLETE),
+		OPT__VERBOSE(&verbose, N_("report each affected file, not just directories")),
+		OPT_END(),
+	};
+
+	setup_work_tree();
+	if (!core_apply_sparse_checkout)
+		die(_("must be in a sparse-checkout to clean directories"));
+	if (!core_sparse_checkout_cone)
+		die(_("must be in a cone-mode sparse-checkout to clean directories"));
+
+	argc = parse_options(argc, argv, prefix,
+			     builtin_sparse_checkout_clean_options,
+			     builtin_sparse_checkout_clean_usage, 0);
+
+	repo_config_get_bool(repo, "clean.requireforce", &require_force);
+	if (require_force && !force && !dry_run)
+		die(_("for safety, refusing to clean without one of --force or --dry-run"));
+
+	if (dry_run)
+		msg = msg_would_remove;
+
+	if (repo_read_index(repo) < 0)
+		die(_("failed to read index"));
+
+	if (convert_to_sparse(repo->index, SPARSE_INDEX_MEMORY_ONLY) ||
+	    repo->index->sparse_index == INDEX_EXPANDED)
+		die(_("failed to convert index to a sparse index; resolve merge conflicts and try again"));
+
+	strbuf_addstr(&full_path, repo->worktree);
+	strbuf_addch(&full_path, '/');
+	worktree_len = full_path.len;
+
+	for (size_t i = 0; i < repo->index->cache_nr; i++) {
+		struct cache_entry *ce = repo->index->cache[i];
+		if (!S_ISSPARSEDIR(ce->ce_mode))
+			continue;
+		strbuf_setlen(&full_path, worktree_len);
+		strbuf_add(&full_path, ce->name, ce->ce_namelen);
+
+		if (!is_directory(full_path.buf))
+			continue;
+
+		if (verbose)
+			list_every_file_in_dir(msg, ce->name);
+		else
+			printf(msg, ce->name);
+
+		if (dry_run <= 0 &&
+		    remove_dir_recursively(&full_path, 0))
+			warning_errno(_("failed to remove '%s'"), ce->name);
+	}
+
+	strbuf_release(&full_path);
+	return 0;
 }
 
 static char const * const builtin_sparse_checkout_disable_usage[] = {
@@ -927,7 +1027,7 @@ static char const * const builtin_sparse_checkout_disable_usage[] = {
 
 static int sparse_checkout_disable(int argc, const char **argv,
 				   const char *prefix,
-				   struct repository *repo UNUSED)
+				   struct repository *repo)
 {
 	static struct option builtin_sparse_checkout_disable_options[] = {
 		OPT_END(),
@@ -955,7 +1055,7 @@ static int sparse_checkout_disable(int argc, const char **argv,
 	 * are expecting to do that when disabling sparse-checkout.
 	 */
 	give_advice_on_expansion = 0;
-	repo_read_index(the_repository);
+	repo_read_index(repo);
 
 	memset(&pl, 0, sizeof(pl));
 	hashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);
@@ -966,13 +1066,13 @@ static int sparse_checkout_disable(int argc, const char **argv,
 	add_pattern("/*", empty_base, 0, &pl, 0);
 
 	prepare_repo_settings(the_repository);
-	the_repository->settings.sparse_index = 0;
+	repo->settings.sparse_index = 0;
 
-	if (update_working_directory(&pl))
+	if (update_working_directory(repo, &pl))
 		die(_("error while refreshing working directory"));
 
 	clear_pattern_list(&pl);
-	return set_config(MODE_NO_PATTERNS);
+	return set_config(repo, MODE_NO_PATTERNS);
 }
 
 static char const * const builtin_sparse_checkout_check_rules_usage[] = {
@@ -987,14 +1087,17 @@ static struct sparse_checkout_check_rules_opts {
 	char *rules_file;
 } check_rules_opts;
 
-static int check_rules(struct pattern_list *pl, int null_terminated) {
+static int check_rules(struct repository *repo,
+		       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;
+	repo->index->sparse_checkout_patterns = pl;
 	while (!getline_fn(&line, stdin)) {
 		path = line.buf;
 		if (!null_terminated && line.buf[0] == '"') {
@@ -1006,7 +1109,7 @@ static int check_rules(struct pattern_list *pl, int null_terminated) {
 			path = unquoted.buf;
 		}
 
-		if (path_in_sparse_checkout(path, the_repository->index))
+		if (path_in_sparse_checkout(path, repo->index))
 			write_name_quoted(path, stdout, line_terminator);
 	}
 	strbuf_release(&line);
@@ -1016,7 +1119,7 @@ static int check_rules(struct pattern_list *pl, int null_terminated) {
 }
 
 static int sparse_checkout_check_rules(int argc, const char **argv, const char *prefix,
-				       struct repository *repo UNUSED)
+				       struct repository *repo)
 {
 	static struct option builtin_sparse_checkout_check_rules_options[] = {
 		OPT_BOOL('z', NULL, &check_rules_opts.null_termination,
@@ -1055,7 +1158,7 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char *
 		free(sparse_filename);
 	}
 
-	ret = check_rules(&pl, check_rules_opts.null_termination);
+	ret = check_rules(repo, &pl, check_rules_opts.null_termination);
 	clear_pattern_list(&pl);
 	free(check_rules_opts.rules_file);
 	return ret;
@@ -1073,6 +1176,7 @@ int cmd_sparse_checkout(int argc,
 		OPT_SUBCOMMAND("set", &fn, sparse_checkout_set),
 		OPT_SUBCOMMAND("add", &fn, sparse_checkout_add),
 		OPT_SUBCOMMAND("reapply", &fn, sparse_checkout_reapply),
+		OPT_SUBCOMMAND("clean", &fn, sparse_checkout_clean),
 		OPT_SUBCOMMAND("disable", &fn, sparse_checkout_disable),
 		OPT_SUBCOMMAND("check-rules", &fn, sparse_checkout_check_rules),
 		OPT_END(),
@@ -1084,8 +1188,8 @@ int cmd_sparse_checkout(int argc,
 
 	repo_config(the_repository, git_default_config, NULL);
 
-	prepare_repo_settings(the_repository);
-	the_repository->settings.command_requires_full_index = 0;
+	prepare_repo_settings(repo);
+	repo->settings.command_requires_full_index = 0;
 
 	return fn(argc, argv, prefix, repo);
 }
diff --git a/builtin/stash.c b/builtin/stash.c
index 063208b..948eba0 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -146,6 +146,11 @@ static const char * const git_stash_import_usage[] = {
 static const char ref_stash[] = "refs/stash";
 static struct strbuf stash_index_path = STRBUF_INIT;
 
+static int show_stat = 1;
+static int show_patch;
+static int show_include_untracked;
+static int use_index;
+
 /*
  * w_commit is set to the commit containing the working tree
  * b_commit is set to the base commit
@@ -717,7 +722,7 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
 {
 	int ret = -1;
 	int quiet = 0;
-	int index = 0;
+	int index = use_index;
 	struct stash_info info = STASH_INFO_INIT;
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
@@ -738,7 +743,8 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
 	return ret;
 }
 
-static int reject_reflog_ent(struct object_id *ooid UNUSED,
+static int reject_reflog_ent(const char *refname UNUSED,
+			     struct object_id *ooid UNUSED,
 			     struct object_id *noid UNUSED,
 			     const char *email UNUSED,
 			     timestamp_t timestamp UNUSED,
@@ -814,7 +820,7 @@ static int pop_stash(int argc, const char **argv, const char *prefix,
 		     struct repository *repo UNUSED)
 {
 	int ret = -1;
-	int index = 0;
+	int index = use_index;
 	int quiet = 0;
 	struct stash_info info = STASH_INFO_INIT;
 	struct option options[] = {
@@ -904,10 +910,6 @@ static int list_stash(int argc, const char **argv, const char *prefix,
 	return run_command(&cp);
 }
 
-static int show_stat = 1;
-static int show_patch;
-static int show_include_untracked;
-
 static int git_stash_config(const char *var, const char *value,
 			    const struct config_context *ctx, void *cb)
 {
@@ -923,6 +925,10 @@ static int git_stash_config(const char *var, const char *value,
 		show_include_untracked = git_config_bool(var, value);
 		return 0;
 	}
+	if (!strcmp(var, "stash.index")) {
+		use_index = git_config_bool(var, value);
+		return 0;
+	}
 	return git_diff_basic_config(var, value, ctx, cb);
 }
 
@@ -1014,8 +1020,8 @@ static int show_stash(int argc, const char **argv, const char *prefix,
 		}
 	}
 
-	argc = setup_revisions(revision_args.nr, revision_args.v, &rev, NULL);
-	if (argc > 1)
+	setup_revisions_from_strvec(&revision_args, &rev, NULL);
+	if (revision_args.nr > 1)
 		goto usage;
 	if (!rev.diffopt.output_format) {
 		rev.diffopt.output_format = DIFF_FORMAT_PATCH;
@@ -1088,7 +1094,6 @@ static int store_stash(int argc, const char **argv, const char *prefix,
 	int quiet = 0;
 	const char *stash_msg = NULL;
 	struct object_id obj;
-	struct object_context dummy = {0};
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("be quiet")),
 		OPT_STRING('m', "message", &stash_msg, "message",
@@ -1108,9 +1113,8 @@ static int store_stash(int argc, const char **argv, const char *prefix,
 		return -1;
 	}
 
-	if (get_oid_with_context(the_repository,
-				 argv[0], quiet ? GET_OID_QUIETLY : 0, &obj,
-				 &dummy)) {
+	if (repo_get_oid_with_flags(the_repository, argv[0], &obj,
+				    quiet ? GET_OID_QUIETLY : 0)) {
 		if (!quiet)
 			fprintf_ln(stderr, _("Cannot update %s with %s"),
 					     ref_stash, argv[0]);
@@ -1121,7 +1125,6 @@ static int store_stash(int argc, const char **argv, const char *prefix,
 	ret = do_store_stash(&obj, stash_msg, quiet);
 
 out:
-	object_context_release(&dummy);
 	return ret;
 }
 
@@ -2210,7 +2213,8 @@ struct stash_entry_data {
 	size_t count;
 };
 
-static int collect_stash_entries(struct object_id *old_oid UNUSED,
+static int collect_stash_entries(const char *refname UNUSED,
+				 struct object_id *old_oid UNUSED,
 				 struct object_id *new_oid,
 				 const char *committer UNUSED,
 				 timestamp_t timestamp UNUSED,
@@ -2236,7 +2240,6 @@ static int do_export_stash(struct repository *r,
 			   const char **argv)
 {
 	struct object_id base;
-	struct object_context unused;
 	struct commit *prev;
 	struct commit_list *items = NULL, **iter = &items, *cur;
 	int res = 0;
@@ -2270,9 +2273,9 @@ static int do_export_stash(struct repository *r,
 			struct commit *stash;
 
 			if (parse_stash_revision(&revision, argv[i], 1) ||
-			    get_oid_with_context(r, revision.buf,
-						 GET_OID_QUIETLY | GET_OID_GENTLY,
-						 &oid, &unused)) {
+			    repo_get_oid_with_flags(r, revision.buf, &oid,
+						    GET_OID_QUIETLY |
+						    GET_OID_GENTLY)) {
 				res = error(_("unable to find stash entry %s"), argv[i]);
 				goto out;
 			}
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 07a1935..35f6cf7 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -593,16 +593,12 @@ static void print_status(unsigned int flags, char state, const char *path,
 	printf("\n");
 }
 
-static int handle_submodule_head_ref(const char *refname UNUSED,
-				     const char *referent UNUSED,
-				     const struct object_id *oid,
-				     int flags UNUSED,
-				     void *cb_data)
+static int handle_submodule_head_ref(const struct reference *ref, void *cb_data)
 {
 	struct object_id *output = cb_data;
 
-	if (oid)
-		oidcpy(output, oid);
+	if (ref->oid)
+		oidcpy(output, ref->oid);
 
 	return 0;
 }
@@ -616,9 +612,6 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
 	struct rev_info rev = REV_INFO_INIT;
 	struct strbuf buf = STRBUF_INIT;
 	const char *git_dir;
-	struct setup_revision_opt opt = {
-		.free_removed_argv_elements = 1,
-	};
 
 	if (validate_submodule_path(path) < 0)
 		die(NULL);
@@ -655,7 +648,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
 
 	repo_init_revisions(the_repository, &rev, NULL);
 	rev.abbrev = 0;
-	setup_revisions(diff_files_args.nr, diff_files_args.v, &rev, &opt);
+	setup_revisions_from_strvec(&diff_files_args, &rev, NULL);
 	run_diff_files(&rev, 0);
 
 	if (!diff_result_code(&rev)) {
@@ -1094,9 +1087,6 @@ static int compute_summary_module_list(struct object_id *head_oid,
 {
 	struct strvec diff_args = STRVEC_INIT;
 	struct rev_info rev;
-	struct setup_revision_opt opt = {
-		.free_removed_argv_elements = 1,
-	};
 	struct module_cb_list list = MODULE_CB_LIST_INIT;
 	int ret = 0;
 
@@ -1114,7 +1104,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
 	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);
+	setup_revisions_from_strvec(&diff_args, &rev, NULL);
 	rev.diffopt.output_format = DIFF_FORMAT_NO_OUTPUT | DIFF_FORMAT_CALLBACK;
 	rev.diffopt.format_callback = submodule_summary_callback;
 	rev.diffopt.format_callback_data = &list;
diff --git a/builtin/tag.c b/builtin/tag.c
index f0665af..01eba90 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -153,7 +153,7 @@ static int verify_tag(const char *name, const char *ref UNUSED,
 		return -1;
 
 	if (format->format)
-		pretty_print_ref(name, oid, format);
+		pretty_print_ref(name, oid, NULL, format);
 
 	return 0;
 }
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 7ae7c82..6fc64e9 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -2,7 +2,6 @@
 #define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "builtin.h"
-#include "bulk-checkin.h"
 #include "config.h"
 #include "environment.h"
 #include "gettext.h"
@@ -364,7 +363,7 @@ struct input_zstream_data {
 	int status;
 };
 
-static const void *feed_input_zstream(struct input_stream *in_stream,
+static const void *feed_input_zstream(struct odb_write_stream *in_stream,
 				      unsigned long *readlen)
 {
 	struct input_zstream_data *data = in_stream->data;
@@ -394,7 +393,7 @@ static void stream_blob(unsigned long size, unsigned nr)
 {
 	git_zstream zstream = { 0 };
 	struct input_zstream_data data = { 0 };
-	struct input_stream in_stream = {
+	struct odb_write_stream in_stream = {
 		.read = feed_input_zstream,
 		.data = &data,
 	};
@@ -403,8 +402,7 @@ static void stream_blob(unsigned long size, unsigned nr)
 	data.zstream = &zstream;
 	git_inflate_init(&zstream);
 
-	if (stream_loose_object(the_repository->objects->sources,
-				&in_stream, size, &info->oid))
+	if (odb_write_object_stream(the_repository->objects, &in_stream, size, &info->oid))
 		die(_("failed to write object in stream"));
 
 	if (data.status != Z_STREAM_END)
@@ -584,6 +582,7 @@ static void unpack_all(void)
 {
 	int i;
 	unsigned char *hdr = fill(sizeof(struct pack_header));
+	struct odb_transaction *transaction;
 
 	if (get_be32(hdr) != PACK_SIGNATURE)
 		die("bad pack file");
@@ -599,12 +598,12 @@ static void unpack_all(void)
 		progress = start_progress(the_repository,
 					  _("Unpacking objects"), nr_objects);
 	CALLOC_ARRAY(obj_list, nr_objects);
-	begin_odb_transaction();
+	transaction = odb_transaction_begin(the_repository->objects);
 	for (i = 0; i < nr_objects; i++) {
 		unpack_one(i);
 		display_progress(progress, i + 1);
 	}
-	end_odb_transaction();
+	odb_transaction_commit(transaction);
 	stop_progress(&progress);
 
 	if (delta_list)
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 2380f3c..8a59077 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -8,7 +8,6 @@
 #define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "builtin.h"
-#include "bulk-checkin.h"
 #include "config.h"
 #include "environment.h"
 #include "gettext.h"
@@ -19,6 +18,7 @@
 #include "cache-tree.h"
 #include "tree-walk.h"
 #include "object-file.h"
+#include "odb.h"
 #include "refs.h"
 #include "resolve-undo.h"
 #include "parse-options.h"
@@ -70,14 +70,6 @@ static void report(const char *fmt, ...)
 	if (!verbose)
 		return;
 
-	/*
-	 * It is possible, though unlikely, that a caller could use the verbose
-	 * output to synchronize with addition of objects to the object
-	 * database. The current implementation of ODB transactions leaves
-	 * objects invisible while a transaction is active, so flush the
-	 * transaction here before reporting a change made by update-index.
-	 */
-	flush_odb_transaction();
 	va_start(vp, fmt);
 	vprintf(fmt, vp);
 	putchar('\n');
@@ -940,6 +932,7 @@ int cmd_update_index(int argc,
 	strbuf_getline_fn getline_fn;
 	int parseopt_state = PARSE_OPT_UNKNOWN;
 	struct repository *r = the_repository;
+	struct odb_transaction *transaction;
 	struct option options[] = {
 		OPT_BIT('q', NULL, &refresh_args.flags,
 			N_("continue refresh even when index needs update"),
@@ -1130,7 +1123,7 @@ int cmd_update_index(int argc,
 	 * Allow the object layer to optimize adding multiple objects in
 	 * a batch.
 	 */
-	begin_odb_transaction();
+	transaction = odb_transaction_begin(the_repository->objects);
 	while (ctx.argc) {
 		if (parseopt_state != PARSE_OPT_DONE)
 			parseopt_state = parse_options_step(&ctx, options,
@@ -1149,6 +1142,21 @@ int cmd_update_index(int argc,
 			const char *path = ctx.argv[0];
 			char *p;
 
+			/*
+			 * It is possible, though unlikely, that a caller could
+			 * use the verbose output to synchronize with addition
+			 * of objects to the object database. The current
+			 * implementation of ODB transactions leaves objects
+			 * invisible while a transaction is active, so end the
+			 * transaction here early before processing the next
+			 * update. All further updates are performed outside of
+			 * a transaction.
+			 */
+			if (transaction && verbose) {
+				odb_transaction_commit(transaction);
+				transaction = NULL;
+			}
+
 			setup_work_tree();
 			p = prefix_path(prefix, prefix_length, path);
 			update_one(p);
@@ -1213,7 +1221,7 @@ int cmd_update_index(int argc,
 	/*
 	 * By now we have added all of the new objects
 	 */
-	end_odb_transaction();
+	odb_transaction_commit(transaction);
 
 	if (split_index > 0) {
 		if (repo_config_get_split_index(the_repository) == 0)
diff --git a/builtin/var.c b/builtin/var.c
index a2d790d..cc3a43c 100644
--- a/builtin/var.c
+++ b/builtin/var.c
@@ -182,7 +182,7 @@ static void list_vars(void)
 			if (ptr->multivalued && *val) {
 				struct string_list list = STRING_LIST_INIT_DUP;
 
-				string_list_split(&list, val, '\n', -1);
+				string_list_split(&list, val, "\n", -1);
 				for (size_t i = 0; i < list.nr; i++)
 					printf("%s=%s\n", ptr->name, list.items[i].string);
 				string_list_clear(&list, 0);
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index cd6bc11..558121e 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -67,7 +67,7 @@ int cmd_verify_tag(int argc,
 		}
 
 		if (format.format)
-			pretty_print_ref(name, &oid, &format);
+			pretty_print_ref(name, &oid, NULL, &format);
 	}
 	return had_error;
 }
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 812774a..b7f323b 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -635,11 +635,7 @@ static void print_preparing_worktree_line(int detach,
  *
  * Returns 0 on failure and non-zero on success.
  */
-static int first_valid_ref(const char *refname UNUSED,
-			   const char *referent UNUSED,
-			   const struct object_id *oid UNUSED,
-			   int flags UNUSED,
-			   void *cb_data UNUSED)
+static int first_valid_ref(const struct reference *ref UNUSED, void *cb_data UNUSED)
 {
 	return 1;
 }
diff --git a/bulk-checkin.c b/bulk-checkin.c
deleted file mode 100644
index b2809ab..0000000
--- a/bulk-checkin.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (c) 2011, Google Inc.
- */
-
-#define USE_THE_REPOSITORY_VARIABLE
-
-#include "git-compat-util.h"
-#include "bulk-checkin.h"
-#include "environment.h"
-#include "gettext.h"
-#include "hex.h"
-#include "lockfile.h"
-#include "repository.h"
-#include "csum-file.h"
-#include "pack.h"
-#include "strbuf.h"
-#include "tmp-objdir.h"
-#include "packfile.h"
-#include "object-file.h"
-#include "odb.h"
-
-static int odb_transaction_nesting;
-
-static struct tmp_objdir *bulk_fsync_objdir;
-
-static struct bulk_checkin_packfile {
-	char *pack_tmp_name;
-	struct hashfile *f;
-	off_t offset;
-	struct pack_idx_option pack_idx_opts;
-
-	struct pack_idx_entry **written;
-	uint32_t alloc_written;
-	uint32_t nr_written;
-} bulk_checkin_packfile;
-
-static void finish_tmp_packfile(struct strbuf *basename,
-				const char *pack_tmp_name,
-				struct pack_idx_entry **written_list,
-				uint32_t nr_written,
-				struct pack_idx_option *pack_idx_opts,
-				unsigned char hash[])
-{
-	char *idx_tmp_name = NULL;
-
-	stage_tmp_packfiles(the_repository, basename, pack_tmp_name,
-			    written_list, nr_written, NULL, pack_idx_opts, hash,
-			    &idx_tmp_name);
-	rename_tmp_packfile_idx(the_repository, basename, &idx_tmp_name);
-
-	free(idx_tmp_name);
-}
-
-static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)
-{
-	unsigned char hash[GIT_MAX_RAWSZ];
-	struct strbuf packname = STRBUF_INIT;
-
-	if (!state->f)
-		return;
-
-	if (state->nr_written == 0) {
-		close(state->f->fd);
-		free_hashfile(state->f);
-		unlink(state->pack_tmp_name);
-		goto clear_exit;
-	} else if (state->nr_written == 1) {
-		finalize_hashfile(state->f, hash, FSYNC_COMPONENT_PACK,
-				  CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE);
-	} else {
-		int fd = finalize_hashfile(state->f, hash, FSYNC_COMPONENT_PACK, 0);
-		fixup_pack_header_footer(the_hash_algo, fd, hash, state->pack_tmp_name,
-					 state->nr_written, hash,
-					 state->offset);
-		close(fd);
-	}
-
-	strbuf_addf(&packname, "%s/pack/pack-%s.", repo_get_object_directory(the_repository),
-		    hash_to_hex(hash));
-	finish_tmp_packfile(&packname, state->pack_tmp_name,
-			    state->written, state->nr_written,
-			    &state->pack_idx_opts, hash);
-	for (uint32_t i = 0; i < state->nr_written; i++)
-		free(state->written[i]);
-
-clear_exit:
-	free(state->pack_tmp_name);
-	free(state->written);
-	memset(state, 0, sizeof(*state));
-
-	strbuf_release(&packname);
-	/* Make objects we just wrote available to ourselves */
-	reprepare_packed_git(the_repository);
-}
-
-/*
- * Cleanup after batch-mode fsync_object_files.
- */
-static void flush_batch_fsync(void)
-{
-	struct strbuf temp_path = STRBUF_INIT;
-	struct tempfile *temp;
-
-	if (!bulk_fsync_objdir)
-		return;
-
-	/*
-	 * Issue a full hardware flush against a temporary file to ensure
-	 * that all objects are durable before any renames occur. The code in
-	 * fsync_loose_object_bulk_checkin has already issued a writeout
-	 * request, but it has not flushed any writeback cache in the storage
-	 * hardware or any filesystem logs. This fsync call acts as a barrier
-	 * to ensure that the data in each new object file is durable before
-	 * the final name is visible.
-	 */
-	strbuf_addf(&temp_path, "%s/bulk_fsync_XXXXXX", repo_get_object_directory(the_repository));
-	temp = xmks_tempfile(temp_path.buf);
-	fsync_or_die(get_tempfile_fd(temp), get_tempfile_path(temp));
-	delete_tempfile(&temp);
-	strbuf_release(&temp_path);
-
-	/*
-	 * Make the object files visible in the primary ODB after their data is
-	 * fully durable.
-	 */
-	tmp_objdir_migrate(bulk_fsync_objdir);
-	bulk_fsync_objdir = NULL;
-}
-
-static int already_written(struct bulk_checkin_packfile *state, struct object_id *oid)
-{
-	/* The object may already exist in the repository */
-	if (odb_has_object(the_repository->objects, oid,
-			   HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
-		return 1;
-
-	/* Might want to keep the list sorted */
-	for (uint32_t i = 0; i < state->nr_written; i++)
-		if (oideq(&state->written[i]->oid, oid))
-			return 1;
-
-	/* This is a new object we need to keep */
-	return 0;
-}
-
-/*
- * Read the contents from fd for size bytes, streaming it to the
- * packfile in state while updating the hash in ctx. Signal a failure
- * by returning a negative value when the resulting pack would exceed
- * the pack size limit and this is not the first object in the pack,
- * so that the caller can discard what we wrote from the current pack
- * by truncating it and opening a new one. The caller will then call
- * us again after rewinding the input fd.
- *
- * The already_hashed_to pointer is kept untouched by the caller to
- * make sure we do not hash the same byte when we are called
- * again. This way, the caller does not have to checkpoint its hash
- * status before calling us just in case we ask it to call us again
- * with a new pack.
- */
-static int stream_blob_to_pack(struct bulk_checkin_packfile *state,
-			       struct git_hash_ctx *ctx, off_t *already_hashed_to,
-			       int fd, size_t size, const char *path,
-			       unsigned flags)
-{
-	git_zstream s;
-	unsigned char ibuf[16384];
-	unsigned char obuf[16384];
-	unsigned hdrlen;
-	int status = Z_OK;
-	int write_object = (flags & INDEX_WRITE_OBJECT);
-	off_t offset = 0;
-
-	git_deflate_init(&s, pack_compression_level);
-
-	hdrlen = encode_in_pack_object_header(obuf, sizeof(obuf), OBJ_BLOB, size);
-	s.next_out = obuf + hdrlen;
-	s.avail_out = sizeof(obuf) - hdrlen;
-
-	while (status != Z_STREAM_END) {
-		if (size && !s.avail_in) {
-			size_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf);
-			ssize_t read_result = read_in_full(fd, ibuf, rsize);
-			if (read_result < 0)
-				die_errno("failed to read from '%s'", path);
-			if ((size_t)read_result != rsize)
-				die("failed to read %u bytes from '%s'",
-				    (unsigned)rsize, path);
-			offset += rsize;
-			if (*already_hashed_to < offset) {
-				size_t hsize = offset - *already_hashed_to;
-				if (rsize < hsize)
-					hsize = rsize;
-				if (hsize)
-					git_hash_update(ctx, ibuf, hsize);
-				*already_hashed_to = offset;
-			}
-			s.next_in = ibuf;
-			s.avail_in = rsize;
-			size -= rsize;
-		}
-
-		status = git_deflate(&s, size ? 0 : Z_FINISH);
-
-		if (!s.avail_out || status == Z_STREAM_END) {
-			if (write_object) {
-				size_t written = s.next_out - obuf;
-
-				/* would we bust the size limit? */
-				if (state->nr_written &&
-				    pack_size_limit_cfg &&
-				    pack_size_limit_cfg < state->offset + written) {
-					git_deflate_abort(&s);
-					return -1;
-				}
-
-				hashwrite(state->f, obuf, written);
-				state->offset += written;
-			}
-			s.next_out = obuf;
-			s.avail_out = sizeof(obuf);
-		}
-
-		switch (status) {
-		case Z_OK:
-		case Z_BUF_ERROR:
-		case Z_STREAM_END:
-			continue;
-		default:
-			die("unexpected deflate failure: %d", status);
-		}
-	}
-	git_deflate_end(&s);
-	return 0;
-}
-
-/* Lazily create backing packfile for the state */
-static void prepare_to_stream(struct bulk_checkin_packfile *state,
-			      unsigned flags)
-{
-	if (!(flags & INDEX_WRITE_OBJECT) || state->f)
-		return;
-
-	state->f = create_tmp_packfile(the_repository, &state->pack_tmp_name);
-	reset_pack_idx_option(&state->pack_idx_opts);
-
-	/* Pretend we are going to write only one object */
-	state->offset = write_pack_header(state->f, 1);
-	if (!state->offset)
-		die_errno("unable to write pack header");
-}
-
-static int deflate_blob_to_pack(struct bulk_checkin_packfile *state,
-				struct object_id *result_oid,
-				int fd, size_t size,
-				const char *path, unsigned flags)
-{
-	off_t seekback, already_hashed_to;
-	struct git_hash_ctx ctx;
-	unsigned char obuf[16384];
-	unsigned header_len;
-	struct hashfile_checkpoint checkpoint;
-	struct pack_idx_entry *idx = NULL;
-
-	seekback = lseek(fd, 0, SEEK_CUR);
-	if (seekback == (off_t) -1)
-		return error("cannot find the current offset");
-
-	header_len = format_object_header((char *)obuf, sizeof(obuf),
-					  OBJ_BLOB, size);
-	the_hash_algo->init_fn(&ctx);
-	git_hash_update(&ctx, obuf, header_len);
-
-	/* Note: idx is non-NULL when we are writing */
-	if ((flags & INDEX_WRITE_OBJECT) != 0) {
-		CALLOC_ARRAY(idx, 1);
-
-		prepare_to_stream(state, flags);
-		hashfile_checkpoint_init(state->f, &checkpoint);
-	}
-
-	already_hashed_to = 0;
-
-	while (1) {
-		prepare_to_stream(state, flags);
-		if (idx) {
-			hashfile_checkpoint(state->f, &checkpoint);
-			idx->offset = state->offset;
-			crc32_begin(state->f);
-		}
-		if (!stream_blob_to_pack(state, &ctx, &already_hashed_to,
-					 fd, size, path, flags))
-			break;
-		/*
-		 * Writing this object to the current pack will make
-		 * it too big; we need to truncate it, start a new
-		 * pack, and write into it.
-		 */
-		if (!idx)
-			BUG("should not happen");
-		hashfile_truncate(state->f, &checkpoint);
-		state->offset = checkpoint.offset;
-		flush_bulk_checkin_packfile(state);
-		if (lseek(fd, seekback, SEEK_SET) == (off_t) -1)
-			return error("cannot seek back");
-	}
-	git_hash_final_oid(result_oid, &ctx);
-	if (!idx)
-		return 0;
-
-	idx->crc32 = crc32_end(state->f);
-	if (already_written(state, result_oid)) {
-		hashfile_truncate(state->f, &checkpoint);
-		state->offset = checkpoint.offset;
-		free(idx);
-	} else {
-		oidcpy(&idx->oid, result_oid);
-		ALLOC_GROW(state->written,
-			   state->nr_written + 1,
-			   state->alloc_written);
-		state->written[state->nr_written++] = idx;
-	}
-	return 0;
-}
-
-void prepare_loose_object_bulk_checkin(void)
-{
-	/*
-	 * We lazily create the temporary object directory
-	 * the first time an object might be added, since
-	 * callers may not know whether any objects will be
-	 * added at the time they call begin_odb_transaction.
-	 */
-	if (!odb_transaction_nesting || bulk_fsync_objdir)
-		return;
-
-	bulk_fsync_objdir = tmp_objdir_create(the_repository, "bulk-fsync");
-	if (bulk_fsync_objdir)
-		tmp_objdir_replace_primary_odb(bulk_fsync_objdir, 0);
-}
-
-void fsync_loose_object_bulk_checkin(int fd, const char *filename)
-{
-	/*
-	 * If we have an active ODB transaction, we issue a call that
-	 * cleans the filesystem page cache but avoids a hardware flush
-	 * command. Later on we will issue a single hardware flush
-	 * before renaming the objects to their final names as part of
-	 * flush_batch_fsync.
-	 */
-	if (!bulk_fsync_objdir ||
-	    git_fsync(fd, FSYNC_WRITEOUT_ONLY) < 0) {
-		if (errno == ENOSYS)
-			warning(_("core.fsyncMethod = batch is unsupported on this platform"));
-		fsync_or_die(fd, filename);
-	}
-}
-
-int index_blob_bulk_checkin(struct object_id *oid,
-			    int fd, size_t size,
-			    const char *path, unsigned flags)
-{
-	int status = deflate_blob_to_pack(&bulk_checkin_packfile, oid, fd, size,
-					  path, flags);
-	if (!odb_transaction_nesting)
-		flush_bulk_checkin_packfile(&bulk_checkin_packfile);
-	return status;
-}
-
-void begin_odb_transaction(void)
-{
-	odb_transaction_nesting += 1;
-}
-
-void flush_odb_transaction(void)
-{
-	flush_batch_fsync();
-	flush_bulk_checkin_packfile(&bulk_checkin_packfile);
-}
-
-void end_odb_transaction(void)
-{
-	odb_transaction_nesting -= 1;
-	if (odb_transaction_nesting < 0)
-		BUG("Unbalanced ODB transaction nesting");
-
-	if (odb_transaction_nesting)
-		return;
-
-	flush_odb_transaction();
-}
diff --git a/bulk-checkin.h b/bulk-checkin.h
deleted file mode 100644
index 7246ea5..0000000
--- a/bulk-checkin.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2011, Google Inc.
- */
-#ifndef BULK_CHECKIN_H
-#define BULK_CHECKIN_H
-
-#include "object.h"
-
-void prepare_loose_object_bulk_checkin(void);
-void fsync_loose_object_bulk_checkin(int fd, const char *filename);
-
-/*
- * This creates one packfile per large blob unless bulk-checkin
- * machinery is "plugged".
- *
- * This also bypasses the usual "convert-to-git" dance, and that is on
- * purpose. We could write a streaming version of the converting
- * functions and insert that before feeding the data to fast-import
- * (or equivalent in-core API described above). However, that is
- * somewhat complicated, as we do not know the size of the filter
- * result, which we need to know beforehand when writing a git object.
- * Since the primary motivation for trying to stream from the working
- * tree file and to avoid mmaping it in core is to deal with large
- * binary blobs, they generally do not want to get any conversion, and
- * callers should avoid this code path when filters are requested.
- */
-int index_blob_bulk_checkin(struct object_id *oid,
-			    int fd, size_t size,
-			    const char *path, unsigned flags);
-
-/*
- * Tell the object database to optimize for adding
- * multiple objects. end_odb_transaction must be called
- * to make new objects visible. Transactions can be nested,
- * and objects are only visible after the outermost transaction
- * is complete or the transaction is flushed.
- */
-void begin_odb_transaction(void);
-
-/*
- * Make any objects that are currently part of a pending object
- * database transaction visible. It is valid to call this function
- * even if no transaction is active.
- */
-void flush_odb_transaction(void);
-
-/*
- * Tell the object database to make any objects from the
- * current transaction visible if this is the final nested
- * transaction.
- */
-void end_odb_transaction(void);
-
-#endif
diff --git a/cache-tree.c b/cache-tree.c
index 66ef2be..2aba470 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -8,7 +8,6 @@
 #include "tree.h"
 #include "tree-walk.h"
 #include "cache-tree.h"
-#include "bulk-checkin.h"
 #include "object-file.h"
 #include "odb.h"
 #include "read-cache-ll.h"
@@ -474,6 +473,7 @@ static int update_one(struct cache_tree *it,
 
 int cache_tree_update(struct index_state *istate, int flags)
 {
+	struct odb_transaction *transaction;
 	int skip, i;
 
 	i = verify_cache(istate, flags);
@@ -489,10 +489,10 @@ int cache_tree_update(struct index_state *istate, int flags)
 
 	trace_performance_enter();
 	trace2_region_enter("cache_tree", "update", the_repository);
-	begin_odb_transaction();
+	transaction = odb_transaction_begin(the_repository->objects);
 	i = update_one(istate->cache_tree, istate->cache, istate->cache_nr,
 		       "", 0, &skip, flags);
-	end_odb_transaction();
+	odb_transaction_commit(transaction);
 	trace2_region_leave("cache_tree", "update", the_repository);
 	trace_performance_leave("cache_tree_update");
 	if (i < 0)
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index 6668c4d..6ee8216 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -10,6 +10,8 @@
 P4WHENCE=https://cdist2.perforce.com/perforce/r23.2
 LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION
 JGITWHENCE=https://repo1.maven.org/maven2/org/eclipse/jgit/org.eclipse.jgit.pgm/6.8.0.202311291450-r/org.eclipse.jgit.pgm-6.8.0.202311291450-r.sh
+CARGO_MSRV_VERSION=0.18.4
+CARGO_MSRV_WHENCE=https://github.com/foresterre/cargo-msrv/releases/download/v$CARGO_MSRV_VERSION/cargo-msrv-x86_64-unknown-linux-musl-v$CARGO_MSRV_VERSION.tgz
 
 # Make sudo a no-op and execute the command directly when running as root.
 # While using sudo would be fine on most platforms when we are root already,
@@ -30,8 +32,12 @@
 		bash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null
 	;;
 fedora-*|almalinux-*)
+	case "$jobname" in
+	*-meson)
+		MESON_DEPS="meson ninja";;
+	esac
 	dnf -yq update >/dev/null &&
-	dnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null
+	dnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS cargo >/dev/null
 	;;
 ubuntu-*|i386/ubuntu-*|debian-*)
 	# Required so that apt doesn't wait for user input on certain packages.
@@ -58,7 +64,7 @@
 		make libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \
 		tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \
 		libemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \
-		libsecret-1-dev libpcre2-dev meson ninja-build pkg-config \
+		libsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \
 		${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE
 
 	# Starting with Ubuntu 25.10, sudo can now be provided via either
@@ -103,7 +109,7 @@
 	brew link --force gettext
 
 	mkdir -p "$CUSTOM_PATH"
-	wget -q "$P4WHENCE/bin.macosx1015x86_64/helix-core-server.tgz" &&
+	wget -q "$P4WHENCE/bin.macosx12arm64/helix-core-server.tgz" &&
 	tar -xf helix-core-server.tgz -C "$CUSTOM_PATH" p4 p4d &&
 	sudo xattr -d com.apple.quarantine "$CUSTOM_PATH/p4" "$CUSTOM_PATH/p4d" 2>/dev/null || true
 	rm helix-core-server.tgz
@@ -125,21 +131,28 @@
 
 case "$jobname" in
 ClangFormat)
-	sudo apt-get -q update
 	sudo apt-get -q -y install clang-format
 	;;
 StaticAnalysis)
-	sudo apt-get -q update
 	sudo apt-get -q -y install coccinelle libcurl4-openssl-dev libssl-dev \
 		libexpat-dev gettext make
 	;;
+RustAnalysis)
+	sudo apt-get -q -y install rustup
+	rustup default stable
+	rustup component add clippy rustfmt
+
+	wget -q "$CARGO_MSRV_WHENCE" -O "cargo-msvc.tgz"
+	sudo mkdir -p "$CUSTOM_PATH"
+	sudo tar -xf "cargo-msvc.tgz" --strip-components=1 \
+		--directory "$CUSTOM_PATH" --wildcards "*/cargo-msrv"
+	sudo chmod a+x "$CUSTOM_PATH/cargo-msrv"
+	;;
 sparse)
-	sudo apt-get -q update -q
 	sudo apt-get -q -y install libssl-dev libcurl4-openssl-dev \
 		libexpat-dev gettext zlib1g-dev sparse
 	;;
 Documentation)
-	sudo apt-get -q update
 	sudo apt-get -q -y install asciidoc xmlto docbook-xsl-ns make
 
 	test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||
diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh
index 01823fd..8bda62b 100755
--- a/ci/run-build-and-tests.sh
+++ b/ci/run-build-and-tests.sh
@@ -5,12 +5,12 @@
 
 . ${0%/*}/lib.sh
 
-run_tests=t
-
 case "$jobname" in
-linux-breaking-changes)
-	export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+fedora-breaking-changes-musl|linux-breaking-changes)
 	export WITH_BREAKING_CHANGES=YesPlease
+	export WITH_RUST=YesPlease
+	MESONFLAGS="$MESONFLAGS -Dbreaking_changes=true"
+	MESONFLAGS="$MESONFLAGS -Drust=enabled"
 	;;
 linux-TEST-vars)
 	export OPENSSL_SHA1_UNSAFE=YesPlease
@@ -36,12 +36,6 @@
 linux-reftable|linux-reftable-leaks|osx-reftable)
 	export GIT_TEST_DEFAULT_REF_FORMAT=reftable
 	;;
-pedantic)
-	# Don't run the tests; we only care about whether Git can be
-	# built.
-	export DEVOPTS=pedantic
-	run_tests=
-	;;
 esac
 
 case "$jobname" in
@@ -54,21 +48,15 @@
 		-Dtest_output_directory="${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}" \
 		$MESONFLAGS
 	group "Build" meson compile -C build --
-	if test -n "$run_tests"
-	then
-		group "Run tests" meson test -C build --print-errorlogs --test-args="$GIT_TEST_OPTS" || (
-			./t/aggregate-results.sh "${TEST_OUTPUT_DIRECTORY:-t}/test-results"
-			handle_failed_tests
-		)
-	fi
+	group "Run tests" meson test -C build --print-errorlogs --test-args="$GIT_TEST_OPTS" || (
+		./t/aggregate-results.sh "${TEST_OUTPUT_DIRECTORY:-t}/test-results"
+		handle_failed_tests
+	)
 	;;
 *)
 	group Build make
-	if test -n "$run_tests"
-	then
-		group "Run tests" make test ||
-		handle_failed_tests
-	fi
+	group "Run tests" make test ||
+	handle_failed_tests
 	;;
 esac
 
diff --git a/ci/run-rust-checks.sh b/ci/run-rust-checks.sh
new file mode 100755
index 0000000..b5ad9e8
--- /dev/null
+++ b/ci/run-rust-checks.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+. ${0%/*}/lib.sh
+
+set +x
+
+if ! group "Check Rust formatting" cargo fmt --all --check
+then
+	RET=1
+fi
+
+if ! group "Check for common Rust mistakes" cargo clippy --all-targets --all-features -- -Dwarnings
+then
+	RET=1
+fi
+
+if ! group "Check for minimum required Rust version" cargo msrv verify
+then
+	RET=1
+fi
+
+exit $RET
diff --git a/ci/test-documentation.sh b/ci/test-documentation.sh
index 49f87f5..5e4fd8f 100755
--- a/ci/test-documentation.sh
+++ b/ci/test-documentation.sh
@@ -48,13 +48,13 @@
 
 # Build docs with Meson and AsciiDoc
 meson setup build-asciidoc -Ddocs=html,man -Ddocs_backend=asciidoc
-meson compile -C build-asciidoc
+meson compile -C build-asciidoc docs
 check_docs build-asciidoc AsciiDoc
 rm -rf build-asciidoc
 
 # Build docs with Meson and AsciiDoctor
 meson setup build-asciidoctor -Ddocs=html,man -Ddocs_backend=asciidoctor
-meson compile -C build-asciidoctor
+meson compile -C build-asciidoctor docs
 check_docs build-asciidoctor Asciidoctor
 rm -rf build-asciidoctor
 
diff --git a/color.c b/color.c
index 7df8862..07ac8c9 100644
--- a/color.c
+++ b/color.c
@@ -9,7 +9,7 @@
 #include "pager.h"
 #include "strbuf.h"
 
-static int git_use_color_default = GIT_COLOR_AUTO;
+static enum git_colorbool git_use_color_default = GIT_COLOR_AUTO;
 int color_stdout_is_tty = -1;
 
 /*
@@ -369,29 +369,29 @@ int color_parse_mem(const char *value, int value_len, char *dst)
 #undef OUT
 }
 
-int git_config_colorbool(const char *var, const char *value)
+enum git_colorbool git_config_colorbool(const char *var, const char *value)
 {
 	if (value) {
 		if (!strcasecmp(value, "never"))
-			return 0;
+			return GIT_COLOR_NEVER;
 		if (!strcasecmp(value, "always"))
-			return 1;
+			return GIT_COLOR_ALWAYS;
 		if (!strcasecmp(value, "auto"))
 			return GIT_COLOR_AUTO;
 	}
 
 	if (!var)
-		return -1;
+		return GIT_COLOR_UNKNOWN;
 
 	/* Missing or explicit false to turn off colorization */
 	if (!git_config_bool(var, value))
-		return 0;
+		return GIT_COLOR_NEVER;
 
 	/* any normal truth value defaults to 'auto' */
 	return GIT_COLOR_AUTO;
 }
 
-static int check_auto_color(int fd)
+static bool check_auto_color(int fd)
 {
 	static int color_stderr_is_tty = -1;
 	int *is_tty_p = fd == 1 ? &color_stdout_is_tty : &color_stderr_is_tty;
@@ -399,12 +399,12 @@ static int check_auto_color(int fd)
 		*is_tty_p = isatty(fd);
 	if (*is_tty_p || (fd == 1 && pager_in_use() && pager_use_color)) {
 		if (!is_terminal_dumb())
-			return 1;
+			return true;
 	}
-	return 0;
+	return false;
 }
 
-int want_color_fd(int fd, int var)
+bool want_color_fd(int fd, enum git_colorbool var)
 {
 	/*
 	 * NEEDSWORK: This function is sometimes used from multiple threads, and
@@ -418,7 +418,7 @@ int want_color_fd(int fd, int var)
 	if (fd < 1 || fd >= ARRAY_SIZE(want_auto))
 		BUG("file descriptor out of range: %d", fd);
 
-	if (var < 0)
+	if (var == GIT_COLOR_UNKNOWN)
 		var = git_use_color_default;
 
 	if (var == GIT_COLOR_AUTO) {
@@ -426,7 +426,7 @@ int want_color_fd(int fd, int var)
 			want_auto[fd] = check_auto_color(fd);
 		return want_auto[fd];
 	}
-	return var;
+	return var == GIT_COLOR_ALWAYS;
 }
 
 int git_color_config(const char *var, const char *value, void *cb UNUSED)
diff --git a/color.h b/color.h
index 7ed259a..43e6c9a 100644
--- a/color.h
+++ b/color.h
@@ -73,10 +73,12 @@ struct strbuf;
  * returned from git_config_colorbool. The "auto" value can be returned from
  * config_colorbool, and will be converted by want_color() into either 0 or 1.
  */
-#define GIT_COLOR_UNKNOWN -1
-#define GIT_COLOR_NEVER  0
-#define GIT_COLOR_ALWAYS 1
-#define GIT_COLOR_AUTO   2
+enum git_colorbool {
+	GIT_COLOR_UNKNOWN = -1,
+	GIT_COLOR_NEVER = 0,
+	GIT_COLOR_ALWAYS = 1,
+	GIT_COLOR_AUTO = 2,
+};
 
 /* A default list of colors to use for commit graphs and show-branch output */
 extern const char *column_colors_ansi[];
@@ -98,13 +100,13 @@ int git_color_config(const char *var, const char *value, void *cb);
  * GIT_COLOR_ALWAYS for "always" or a positive boolean,
  * and GIT_COLOR_AUTO for "auto".
  */
-int git_config_colorbool(const char *var, const char *value);
+enum git_colorbool git_config_colorbool(const char *var, const char *value);
 
 /*
  * Return a boolean whether to use color, where the argument 'var' is
  * one of GIT_COLOR_UNKNOWN, GIT_COLOR_NEVER, GIT_COLOR_ALWAYS, GIT_COLOR_AUTO.
  */
-int want_color_fd(int fd, int var);
+bool want_color_fd(int fd, enum git_colorbool var);
 #define want_color(colorbool) want_color_fd(1, (colorbool))
 #define want_color_stderr(colorbool) want_color_fd(2, (colorbool))
 
diff --git a/combine-diff.c b/combine-diff.c
index 4ea2dc9..b799862 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -749,7 +749,7 @@ static void show_line_to_eol(const char *line, int len, const char *reset)
 
 static void dump_sline(struct sline *sline, const char *line_prefix,
 		       unsigned long cnt, int num_parent,
-		       int use_color, int result_deleted)
+		       enum git_colorbool use_color, int result_deleted)
 {
 	unsigned long mark = (1UL<<num_parent);
 	unsigned long no_pre_delete = (2UL<<num_parent);
@@ -1315,7 +1315,7 @@ static struct diff_filepair *combined_pair(struct combine_diff_path *p,
 	struct diff_filepair *pair;
 	struct diff_filespec *pool;
 
-	pair = xmalloc(sizeof(*pair));
+	CALLOC_ARRAY(pair, 1);
 	CALLOC_ARRAY(pool, st_add(num_parent, 1));
 	pair->one = pool + 1;
 	pair->two = pool;
@@ -1515,8 +1515,9 @@ void diff_tree_combined(const struct object_id *oid,
 
 	diffopts = *opt;
 	copy_pathspec(&diffopts.pathspec, &opt->pathspec);
-	diffopts.flags.recursive = 1;
 	diffopts.flags.allow_external = 0;
+	if (!opt->flags.no_recursive_diff_tree_combined)
+		diffopts.flags.recursive = 1;
 
 	/* find set of paths that everybody touches
 	 *
diff --git a/command-list.txt b/command-list.txt
index b7ade3a..accd3d0 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -124,6 +124,7 @@
 git-init                                mainporcelain           init
 git-instaweb                            ancillaryinterrogators          complete
 git-interpret-trailers                  purehelpers
+git-last-modified                       plumbinginterrogators
 git-log                                 mainporcelain           info
 git-ls-files                            plumbinginterrogators
 git-ls-remote                           plumbinginterrogators
@@ -164,6 +165,7 @@
 git-repack                              ancillarymanipulators           complete
 git-replace                             ancillarymanipulators           complete
 git-replay                              plumbingmanipulators
+git-repo                                plumbinginterrogators
 git-request-pull                        foreignscminterface             complete
 git-rerere                              ancillaryinterrogators
 git-reset                               mainporcelain           history
diff --git a/commit-graph.c b/commit-graph.c
index e0d92b8..80be2ff 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
 #define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "git-compat-util.h"
@@ -29,7 +28,7 @@
 #include "tree.h"
 #include "chunk-format.h"
 
-void git_test_write_commit_graph_or_die(void)
+void git_test_write_commit_graph_or_die(struct odb_source *source)
 {
 	int flags = 0;
 	if (!git_env_bool(GIT_TEST_COMMIT_GRAPH, 0))
@@ -38,8 +37,7 @@ void git_test_write_commit_graph_or_die(void)
 	if (git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0))
 		flags = COMMIT_GRAPH_WRITE_BLOOM_FILTERS;
 
-	if (write_commit_graph_reachable(the_repository->objects->sources,
-					 flags, NULL))
+	if (write_commit_graph_reachable(source, flags, NULL))
 		die("failed to write commit-graph under GIT_TEST_COMMIT_GRAPH");
 }
 
@@ -54,8 +52,6 @@ void git_test_write_commit_graph_or_die(void)
 #define GRAPH_CHUNKID_BLOOMDATA 0x42444154 /* "BDAT" */
 #define GRAPH_CHUNKID_BASE 0x42415345 /* "BASE" */
 
-#define GRAPH_DATA_WIDTH (the_hash_algo->rawsz + 16)
-
 #define GRAPH_VERSION_1 0x1
 #define GRAPH_VERSION GRAPH_VERSION_1
 
@@ -67,8 +63,6 @@ void git_test_write_commit_graph_or_die(void)
 
 #define GRAPH_HEADER_SIZE 8
 #define GRAPH_FANOUT_SIZE (4 * 256)
-#define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * CHUNK_TOC_ENTRY_SIZE \
-			+ GRAPH_FANOUT_SIZE + the_hash_algo->rawsz)
 
 #define CORRECTED_COMMIT_DATE_OFFSET_OVERFLOW (1ULL << 31)
 
@@ -81,6 +75,16 @@ define_commit_slab(topo_level_slab, uint32_t);
 define_commit_slab(commit_pos, int);
 static struct commit_pos commit_pos = COMMIT_SLAB_INIT(1, commit_pos);
 
+static size_t graph_data_width(const struct git_hash_algo *algop)
+{
+	return algop->rawsz + 16;
+}
+
+static size_t graph_min_size(const struct git_hash_algo *algop)
+{
+	return GRAPH_HEADER_SIZE + 4 * CHUNK_TOC_ENTRY_SIZE + GRAPH_FANOUT_SIZE + algop->rawsz;
+}
+
 static void set_commit_pos(struct repository *r, const struct object_id *oid)
 {
 	static int32_t max_pos;
@@ -249,9 +253,8 @@ int open_commit_graph(const char *graph_file, int *fd, struct stat *st)
 	return 1;
 }
 
-struct commit_graph *load_commit_graph_one_fd_st(struct repository *r,
-						 int fd, struct stat *st,
-						 struct odb_source *source)
+struct commit_graph *load_commit_graph_one_fd_st(struct odb_source *source,
+						 int fd, struct stat *st)
 {
 	void *graph_map;
 	size_t graph_size;
@@ -259,16 +262,15 @@ struct commit_graph *load_commit_graph_one_fd_st(struct repository *r,
 
 	graph_size = xsize_t(st->st_size);
 
-	if (graph_size < GRAPH_MIN_SIZE) {
+	if (graph_size < graph_min_size(source->odb->repo->hash_algo)) {
 		close(fd);
 		error(_("commit-graph file is too small"));
 		return NULL;
 	}
 	graph_map = xmmap(NULL, graph_size, PROT_READ, MAP_PRIVATE, fd, 0);
 	close(fd);
-	prepare_repo_settings(r);
-	ret = parse_commit_graph(&r->settings, graph_map, graph_size);
 
+	ret = parse_commit_graph(source->odb->repo, graph_map, graph_size);
 	if (ret)
 		ret->odb_source = source;
 	else
@@ -306,7 +308,7 @@ static int graph_read_oid_lookup(const unsigned char *chunk_start,
 {
 	struct commit_graph *g = data;
 	g->chunk_oid_lookup = chunk_start;
-	if (chunk_size / g->hash_len != g->num_commits)
+	if (chunk_size / g->hash_algo->rawsz != g->num_commits)
 		return error(_("commit-graph OID lookup chunk is the wrong size"));
 	return 0;
 }
@@ -315,7 +317,7 @@ static int graph_read_commit_data(const unsigned char *chunk_start,
 				  size_t chunk_size, void *data)
 {
 	struct commit_graph *g = data;
-	if (chunk_size / GRAPH_DATA_WIDTH != g->num_commits)
+	if (chunk_size / graph_data_width(g->hash_algo) != g->num_commits)
 		return error(_("commit-graph commit data chunk is wrong size"));
 	g->chunk_commit_data = chunk_start;
 	return 0;
@@ -368,7 +370,7 @@ static int graph_read_bloom_data(const unsigned char *chunk_start,
 	return 0;
 }
 
-struct commit_graph *parse_commit_graph(struct repo_settings *s,
+struct commit_graph *parse_commit_graph(struct repository *r,
 					void *graph_map, size_t graph_size)
 {
 	const unsigned char *data;
@@ -380,7 +382,7 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s,
 	if (!graph_map)
 		return NULL;
 
-	if (graph_size < GRAPH_MIN_SIZE)
+	if (graph_size < graph_min_size(r->hash_algo))
 		return NULL;
 
 	data = (const unsigned char *)graph_map;
@@ -400,22 +402,22 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s,
 	}
 
 	hash_version = *(unsigned char*)(data + 5);
-	if (hash_version != oid_version(the_hash_algo)) {
+	if (hash_version != oid_version(r->hash_algo)) {
 		error(_("commit-graph hash version %X does not match version %X"),
-		      hash_version, oid_version(the_hash_algo));
+		      hash_version, oid_version(r->hash_algo));
 		return NULL;
 	}
 
 	graph = alloc_commit_graph();
 
-	graph->hash_len = the_hash_algo->rawsz;
+	graph->hash_algo = r->hash_algo;
 	graph->num_chunks = *(unsigned char*)(data + 6);
 	graph->data = graph_map;
 	graph->data_len = graph_size;
 
 	if (graph_size < GRAPH_HEADER_SIZE +
 			 (graph->num_chunks + 1) * CHUNK_TOC_ENTRY_SIZE +
-			 GRAPH_FANOUT_SIZE + the_hash_algo->rawsz) {
+			 GRAPH_FANOUT_SIZE + r->hash_algo->rawsz) {
 		error(_("commit-graph file is too small to hold %u chunks"),
 		      graph->num_chunks);
 		free(graph);
@@ -446,7 +448,9 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s,
 	pair_chunk(cf, GRAPH_CHUNKID_BASE, &graph->chunk_base_graphs,
 		   &graph->chunk_base_graphs_size);
 
-	if (s->commit_graph_generation_version >= 2) {
+	prepare_repo_settings(r);
+
+	if (r->settings.commit_graph_generation_version >= 2) {
 		read_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA,
 			   graph_read_generation_data, graph);
 		pair_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA_OVERFLOW,
@@ -457,7 +461,7 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s,
 			graph->read_generation_data = 1;
 	}
 
-	if (s->commit_graph_changed_paths_version) {
+	if (r->settings.commit_graph_changed_paths_version) {
 		read_chunk(cf, GRAPH_CHUNKID_BLOOMINDEXES,
 			   graph_read_bloom_index, graph);
 		read_chunk(cf, GRAPH_CHUNKID_BLOOMDATA,
@@ -473,8 +477,8 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s,
 		FREE_AND_NULL(graph->bloom_filter_settings);
 	}
 
-	oidread(&graph->oid, graph->data + graph->data_len - graph->hash_len,
-		the_repository->hash_algo);
+	oidread(&graph->oid, graph->data + graph->data_len - graph->hash_algo->rawsz,
+		r->hash_algo);
 
 	free_chunkfile(cf);
 	return graph;
@@ -486,11 +490,9 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s,
 	return NULL;
 }
 
-static struct commit_graph *load_commit_graph_one(struct repository *r,
-						  const char *graph_file,
-						  struct odb_source *source)
+static struct commit_graph *load_commit_graph_one(struct odb_source *source,
+						  const char *graph_file)
 {
-
 	struct stat st;
 	int fd;
 	struct commit_graph *g;
@@ -499,19 +501,17 @@ static struct commit_graph *load_commit_graph_one(struct repository *r,
 	if (!open_ok)
 		return NULL;
 
-	g = load_commit_graph_one_fd_st(r, fd, &st, source);
-
+	g = load_commit_graph_one_fd_st(source, fd, &st);
 	if (g)
 		g->filename = xstrdup(graph_file);
 
 	return g;
 }
 
-static struct commit_graph *load_commit_graph_v1(struct repository *r,
-						 struct odb_source *source)
+static struct commit_graph *load_commit_graph_v1(struct odb_source *source)
 {
 	char *graph_name = get_commit_graph_filename(source);
-	struct commit_graph *g = load_commit_graph_one(r, graph_name, source);
+	struct commit_graph *g = load_commit_graph_one(source, graph_name);
 	free(graph_name);
 
 	return g;
@@ -579,7 +579,7 @@ static int add_graph_to_chain(struct commit_graph *g,
 		return 0;
 	}
 
-	if (g->chunk_base_graphs_size / g->hash_len < n) {
+	if (g->chunk_base_graphs_size / g->hash_algo->rawsz < n) {
 		warning(_("commit-graph base graphs chunk is too small"));
 		return 0;
 	}
@@ -589,8 +589,8 @@ static int add_graph_to_chain(struct commit_graph *g,
 
 		if (!cur_g ||
 		    !oideq(&oids[n], &cur_g->oid) ||
-		    !hasheq(oids[n].hash, g->chunk_base_graphs + st_mult(g->hash_len, n),
-			    the_repository->hash_algo)) {
+		    !hasheq(oids[n].hash, g->chunk_base_graphs + st_mult(g->hash_algo->rawsz, n),
+			    g->hash_algo)) {
 			warning(_("commit-graph chain does not match"));
 			return 0;
 		}
@@ -614,7 +614,8 @@ static int add_graph_to_chain(struct commit_graph *g,
 }
 
 int open_commit_graph_chain(const char *chain_file,
-			    int *fd, struct stat *st)
+			    int *fd, struct stat *st,
+			    const struct git_hash_algo *hash_algo)
 {
 	*fd = git_open(chain_file);
 	if (*fd < 0)
@@ -623,7 +624,7 @@ int open_commit_graph_chain(const char *chain_file,
 		close(*fd);
 		return 0;
 	}
-	if (st->st_size < the_hash_algo->hexsz) {
+	if (st->st_size < hash_algo->hexsz) {
 		close(*fd);
 		if (!st->st_size) {
 			/* treat empty files the same as missing */
@@ -637,7 +638,7 @@ int open_commit_graph_chain(const char *chain_file,
 	return 1;
 }
 
-struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r,
+struct commit_graph *load_commit_graph_chain_fd_st(struct object_database *odb,
 						   int fd, struct stat *st,
 						   int *incomplete_chain)
 {
@@ -647,10 +648,10 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r,
 	int i = 0, valid = 1, count;
 	FILE *fp = xfdopen(fd, "r");
 
-	count = st->st_size / (the_hash_algo->hexsz + 1);
+	count = st->st_size / (odb->repo->hash_algo->hexsz + 1);
 	CALLOC_ARRAY(oids, count);
 
-	odb_prepare_alternates(r->objects);
+	odb_prepare_alternates(odb);
 
 	for (i = 0; i < count; i++) {
 		struct odb_source *source;
@@ -658,7 +659,7 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r,
 		if (strbuf_getline_lf(&line, fp) == EOF)
 			break;
 
-		if (get_oid_hex(line.buf, &oids[i])) {
+		if (get_oid_hex_algop(line.buf, &oids[i], odb->repo->hash_algo)) {
 			warning(_("invalid commit-graph chain: line '%s' not a hash"),
 				line.buf);
 			valid = 0;
@@ -666,9 +667,9 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r,
 		}
 
 		valid = 0;
-		for (source = r->objects->sources; source; source = source->next) {
+		for (source = odb->sources; source; source = source->next) {
 			char *graph_name = get_split_graph_filename(source, line.buf);
-			struct commit_graph *g = load_commit_graph_one(r, graph_name, source);
+			struct commit_graph *g = load_commit_graph_one(source, graph_name);
 
 			free(graph_name);
 
@@ -701,52 +702,40 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r,
 	return graph_chain;
 }
 
-static struct commit_graph *load_commit_graph_chain(struct repository *r,
-						    struct odb_source *source)
+static struct commit_graph *load_commit_graph_chain(struct odb_source *source)
 {
 	char *chain_file = get_commit_graph_chain_filename(source);
 	struct stat st;
 	int fd;
 	struct commit_graph *g = NULL;
 
-	if (open_commit_graph_chain(chain_file, &fd, &st)) {
+	if (open_commit_graph_chain(chain_file, &fd, &st, source->odb->repo->hash_algo)) {
 		int incomplete;
 		/* ownership of fd is taken over by load function */
-		g = load_commit_graph_chain_fd_st(r, fd, &st, &incomplete);
+		g = load_commit_graph_chain_fd_st(source->odb, fd, &st, &incomplete);
 	}
 
 	free(chain_file);
 	return g;
 }
 
-struct commit_graph *read_commit_graph_one(struct repository *r,
-					   struct odb_source *source)
+struct commit_graph *read_commit_graph_one(struct odb_source *source)
 {
-	struct commit_graph *g = load_commit_graph_v1(r, source);
+	struct commit_graph *g = load_commit_graph_v1(source);
 
 	if (!g)
-		g = load_commit_graph_chain(r, source);
+		g = load_commit_graph_chain(source);
 
 	return g;
 }
 
-static void prepare_commit_graph_one(struct repository *r,
-				     struct odb_source *source)
-{
-
-	if (r->objects->commit_graph)
-		return;
-
-	r->objects->commit_graph = read_commit_graph_one(r, source);
-}
-
 /*
  * Return 1 if commit_graph is non-NULL, and 0 otherwise.
  *
  * On the first invocation, this function attempts to load the commit
- * graph if the_repository is configured to have one.
+ * graph if the repository is configured to have one.
  */
-static int prepare_commit_graph(struct repository *r)
+static struct commit_graph *prepare_commit_graph(struct repository *r)
 {
 	struct odb_source *source;
 
@@ -758,10 +747,10 @@ static int prepare_commit_graph(struct repository *r)
 	 * we want to disable even an already-loaded graph file.
 	 */
 	if (!r->gitdir || r->commit_graph_disabled)
-		return 0;
+		return NULL;
 
 	if (r->objects->commit_graph_attempted)
-		return !!r->objects->commit_graph;
+		return r->objects->commit_graph;
 	r->objects->commit_graph_attempted = 1;
 
 	prepare_repo_settings(r);
@@ -774,33 +763,32 @@ static int prepare_commit_graph(struct repository *r)
 		 * so that commit graph loading is not attempted again for this
 		 * repository.)
 		 */
-		return 0;
+		return NULL;
 
 	if (!commit_graph_compatible(r))
-		return 0;
+		return NULL;
 
 	odb_prepare_alternates(r->objects);
-	for (source = r->objects->sources;
-	     !r->objects->commit_graph && source;
-	     source = source->next)
-		prepare_commit_graph_one(r, source);
-	return !!r->objects->commit_graph;
+	for (source = r->objects->sources; source; source = source->next) {
+		r->objects->commit_graph = read_commit_graph_one(source);
+		if (r->objects->commit_graph)
+			break;
+	}
+
+	return r->objects->commit_graph;
 }
 
 int generation_numbers_enabled(struct repository *r)
 {
 	uint32_t first_generation;
 	struct commit_graph *g;
-	if (!prepare_commit_graph(r))
+
+	g = prepare_commit_graph(r);
+	if (!g || !g->num_commits)
 	       return 0;
 
-	g = r->objects->commit_graph;
-
-	if (!g->num_commits)
-		return 0;
-
 	first_generation = get_be32(g->chunk_commit_data +
-				    g->hash_len + 8) >> 2;
+				    g->hash_algo->rawsz + 8) >> 2;
 
 	return !!first_generation;
 }
@@ -808,12 +796,9 @@ int generation_numbers_enabled(struct repository *r)
 int corrected_commit_dates_enabled(struct repository *r)
 {
 	struct commit_graph *g;
-	if (!prepare_commit_graph(r))
-		return 0;
 
-	g = r->objects->commit_graph;
-
-	if (!g->num_commits)
+	g = prepare_commit_graph(r);
+	if (!g || !g->num_commits)
 		return 0;
 
 	return g->read_generation_data;
@@ -821,7 +806,12 @@ int corrected_commit_dates_enabled(struct repository *r)
 
 struct bloom_filter_settings *get_bloom_filter_settings(struct repository *r)
 {
-	struct commit_graph *g = r->objects->commit_graph;
+	struct commit_graph *g;
+
+	if (!prepare_commit_graph(r))
+	       return NULL;
+
+	g = r->objects->commit_graph;
 	while (g) {
 		if (g->bloom_filter_settings)
 			return g->bloom_filter_settings;
@@ -844,7 +834,7 @@ void close_commit_graph(struct object_database *o)
 static int bsearch_graph(struct commit_graph *g, const struct object_id *oid, uint32_t *pos)
 {
 	return bsearch_hash(oid->hash, g->chunk_oid_fanout,
-			    g->chunk_oid_lookup, g->hash_len, pos);
+			    g->chunk_oid_lookup, g->hash_algo->rawsz, pos);
 }
 
 static void load_oid_from_graph(struct commit_graph *g,
@@ -864,12 +854,11 @@ static void load_oid_from_graph(struct commit_graph *g,
 
 	lex_index = pos - g->num_commits_in_base;
 
-	oidread(oid, g->chunk_oid_lookup + st_mult(g->hash_len, lex_index),
-		the_repository->hash_algo);
+	oidread(oid, g->chunk_oid_lookup + st_mult(g->hash_algo->rawsz, lex_index),
+		g->hash_algo);
 }
 
-static struct commit_list **insert_parent_or_die(struct repository *r,
-						 struct commit_graph *g,
+static struct commit_list **insert_parent_or_die(struct commit_graph *g,
 						 uint32_t pos,
 						 struct commit_list **pptr)
 {
@@ -880,7 +869,7 @@ static struct commit_list **insert_parent_or_die(struct repository *r,
 		die("invalid parent position %"PRIu32, pos);
 
 	load_oid_from_graph(g, pos, &oid);
-	c = lookup_commit(r, &oid);
+	c = lookup_commit(g->odb_source->odb->repo, &oid);
 	if (!c)
 		die(_("could not find commit %s"), oid_to_hex(&oid));
 	commit_graph_data_at(c)->graph_pos = pos;
@@ -901,13 +890,13 @@ static void fill_commit_graph_info(struct commit *item, struct commit_graph *g,
 		die(_("invalid commit position. commit-graph is likely corrupt"));
 
 	lex_index = pos - g->num_commits_in_base;
-	commit_data = g->chunk_commit_data + st_mult(GRAPH_DATA_WIDTH, lex_index);
+	commit_data = g->chunk_commit_data + st_mult(graph_data_width(g->hash_algo), lex_index);
 
 	graph_data = commit_graph_data_at(item);
 	graph_data->graph_pos = pos;
 
-	date_high = get_be32(commit_data + g->hash_len + 8) & 0x3;
-	date_low = get_be32(commit_data + g->hash_len + 12);
+	date_high = get_be32(commit_data + g->hash_algo->rawsz + 8) & 0x3;
+	date_low = get_be32(commit_data + g->hash_algo->rawsz + 12);
 	item->date = (timestamp_t)((date_high << 32) | date_low);
 
 	if (g->read_generation_data) {
@@ -925,10 +914,10 @@ static void fill_commit_graph_info(struct commit *item, struct commit_graph *g,
 		} else
 			graph_data->generation = item->date + offset;
 	} else
-		graph_data->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
+		graph_data->generation = get_be32(commit_data + g->hash_algo->rawsz + 8) >> 2;
 
 	if (g->topo_levels)
-		*topo_level_slab_at(g->topo_levels, item) = get_be32(commit_data + g->hash_len + 8) >> 2;
+		*topo_level_slab_at(g->topo_levels, item) = get_be32(commit_data + g->hash_algo->rawsz + 8) >> 2;
 }
 
 static inline void set_commit_tree(struct commit *c, struct tree *t)
@@ -936,8 +925,7 @@ static inline void set_commit_tree(struct commit *c, struct tree *t)
 	c->maybe_tree = t;
 }
 
-static int fill_commit_in_graph(struct repository *r,
-				struct commit *item,
+static int fill_commit_in_graph(struct commit *item,
 				struct commit_graph *g, uint32_t pos)
 {
 	uint32_t edge_value;
@@ -952,7 +940,7 @@ static int fill_commit_in_graph(struct repository *r,
 	fill_commit_graph_info(item, g, pos);
 
 	lex_index = pos - g->num_commits_in_base;
-	commit_data = g->chunk_commit_data + st_mult(g->hash_len + 16, lex_index);
+	commit_data = g->chunk_commit_data + st_mult(g->hash_algo->rawsz + 16, lex_index);
 
 	item->object.parsed = 1;
 
@@ -960,16 +948,16 @@ static int fill_commit_in_graph(struct repository *r,
 
 	pptr = &item->parents;
 
-	edge_value = get_be32(commit_data + g->hash_len);
+	edge_value = get_be32(commit_data + g->hash_algo->rawsz);
 	if (edge_value == GRAPH_PARENT_NONE)
 		return 1;
-	pptr = insert_parent_or_die(r, g, edge_value, pptr);
+	pptr = insert_parent_or_die(g, edge_value, pptr);
 
-	edge_value = get_be32(commit_data + g->hash_len + 4);
+	edge_value = get_be32(commit_data + g->hash_algo->rawsz + 4);
 	if (edge_value == GRAPH_PARENT_NONE)
 		return 1;
 	if (!(edge_value & GRAPH_EXTRA_EDGES_NEEDED)) {
-		pptr = insert_parent_or_die(r, g, edge_value, pptr);
+		pptr = insert_parent_or_die(g, edge_value, pptr);
 		return 1;
 	}
 
@@ -984,7 +972,7 @@ static int fill_commit_in_graph(struct repository *r,
 		}
 		edge_value = get_be32(g->chunk_extra_edges +
 				      sizeof(uint32_t) * parent_data_pos);
-		pptr = insert_parent_or_die(r, g,
+		pptr = insert_parent_or_die(g,
 					    edge_value & GRAPH_EDGE_LAST_MASK,
 					    pptr);
 		parent_data_pos++;
@@ -1020,26 +1008,32 @@ static int find_commit_pos_in_graph(struct commit *item, struct commit_graph *g,
 	}
 }
 
-int repo_find_commit_pos_in_graph(struct repository *r, struct commit *c,
-				  uint32_t *pos)
+struct commit_graph *repo_find_commit_pos_in_graph(struct repository *r,
+						   struct commit *c,
+						   uint32_t *pos)
 {
-	if (!prepare_commit_graph(r))
-		return 0;
-	return find_commit_pos_in_graph(c, r->objects->commit_graph, pos);
+	struct commit_graph *g = prepare_commit_graph(r);
+	if (!g)
+		return NULL;
+	if (!find_commit_pos_in_graph(c, g, pos))
+		return NULL;
+	return g;
 }
 
 struct commit *lookup_commit_in_graph(struct repository *repo, const struct object_id *id)
 {
 	static int commit_graph_paranoia = -1;
+	struct commit_graph *g;
 	struct commit *commit;
 	uint32_t pos;
 
 	if (commit_graph_paranoia == -1)
 		commit_graph_paranoia = git_env_bool(GIT_COMMIT_GRAPH_PARANOIA, 0);
 
-	if (!prepare_commit_graph(repo))
+	g = prepare_commit_graph(repo);
+	if (!g)
 		return NULL;
-	if (!search_commit_pos_in_graph(id, repo->objects->commit_graph, &pos))
+	if (!search_commit_pos_in_graph(id, g, &pos))
 		return NULL;
 	if (commit_graph_paranoia && !odb_has_object(repo->objects, id, 0))
 		return NULL;
@@ -1050,14 +1044,13 @@ struct commit *lookup_commit_in_graph(struct repository *repo, const struct obje
 	if (commit->object.parsed)
 		return commit;
 
-	if (!fill_commit_in_graph(repo, commit, repo->objects->commit_graph, pos))
+	if (!fill_commit_in_graph(commit, g, pos))
 		return NULL;
 
 	return commit;
 }
 
-static int parse_commit_in_graph_one(struct repository *r,
-				     struct commit_graph *g,
+static int parse_commit_in_graph_one(struct commit_graph *g,
 				     struct commit *item)
 {
 	uint32_t pos;
@@ -1066,7 +1059,7 @@ static int parse_commit_in_graph_one(struct repository *r,
 		return 1;
 
 	if (find_commit_pos_in_graph(item, g, &pos))
-		return fill_commit_in_graph(r, item, g, pos);
+		return fill_commit_in_graph(item, g, pos);
 
 	return 0;
 }
@@ -1074,6 +1067,7 @@ static int parse_commit_in_graph_one(struct repository *r,
 int parse_commit_in_graph(struct repository *r, struct commit *item)
 {
 	static int checked_env = 0;
+	struct commit_graph *g;
 
 	if (!checked_env &&
 	    git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE, 0))
@@ -1081,20 +1075,23 @@ int parse_commit_in_graph(struct repository *r, struct commit *item)
 		    GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE);
 	checked_env = 1;
 
-	if (!prepare_commit_graph(r))
+	g = prepare_commit_graph(r);
+	if (!g)
 		return 0;
-	return parse_commit_in_graph_one(r, r->objects->commit_graph, item);
+	return parse_commit_in_graph_one(g, item);
 }
 
 void load_commit_graph_info(struct repository *r, struct commit *item)
 {
+	struct commit_graph *g;
 	uint32_t pos;
-	if (repo_find_commit_pos_in_graph(r, item, &pos))
-		fill_commit_graph_info(item, r->objects->commit_graph, pos);
+
+	g = repo_find_commit_pos_in_graph(r, item, &pos);
+	if (g)
+		fill_commit_graph_info(item, g, pos);
 }
 
-static struct tree *load_tree_for_commit(struct repository *r,
-					 struct commit_graph *g,
+static struct tree *load_tree_for_commit(struct commit_graph *g,
 					 struct commit *c)
 {
 	struct object_id oid;
@@ -1105,16 +1102,16 @@ static struct tree *load_tree_for_commit(struct repository *r,
 		g = g->base_graph;
 
 	commit_data = g->chunk_commit_data +
-			st_mult(GRAPH_DATA_WIDTH, graph_pos - g->num_commits_in_base);
+			st_mult(graph_data_width(g->hash_algo),
+				graph_pos - g->num_commits_in_base);
 
-	oidread(&oid, commit_data, the_repository->hash_algo);
-	set_commit_tree(c, lookup_tree(r, &oid));
+	oidread(&oid, commit_data, g->hash_algo);
+	set_commit_tree(c, lookup_tree(g->odb_source->odb->repo, &oid));
 
 	return c->maybe_tree;
 }
 
-static struct tree *get_commit_tree_in_graph_one(struct repository *r,
-						 struct commit_graph *g,
+static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g,
 						 const struct commit *c)
 {
 	if (c->maybe_tree)
@@ -1122,12 +1119,12 @@ static struct tree *get_commit_tree_in_graph_one(struct repository *r,
 	if (commit_graph_position(c) == COMMIT_NOT_FROM_GRAPH)
 		BUG("get_commit_tree_in_graph_one called from non-commit-graph commit");
 
-	return load_tree_for_commit(r, g, (struct commit *)c);
+	return load_tree_for_commit(g, (struct commit *)c);
 }
 
 struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit *c)
 {
-	return get_commit_tree_in_graph_one(r, r->objects->commit_graph, c);
+	return get_commit_tree_in_graph_one(r->objects->commit_graph, c);
 }
 
 struct packed_commit_list {
@@ -1213,7 +1210,7 @@ static int write_graph_chunk_oids(struct hashfile *f,
 	int count;
 	for (count = 0; count < ctx->commits.nr; count++, list++) {
 		display_progress(ctx->progress, ++ctx->progress_cnt);
-		hashwrite(f, (*list)->object.oid.hash, the_hash_algo->rawsz);
+		hashwrite(f, (*list)->object.oid.hash, f->algop->rawsz);
 	}
 
 	return 0;
@@ -1244,7 +1241,7 @@ static int write_graph_chunk_data(struct hashfile *f,
 			die(_("unable to parse commit %s"),
 				oid_to_hex(&(*list)->object.oid));
 		tree = get_commit_tree_oid(*list);
-		hashwrite(f, tree->hash, the_hash_algo->rawsz);
+		hashwrite(f, tree->hash, ctx->r->hash_algo->rawsz);
 
 		parent = (*list)->parents;
 
@@ -1534,7 +1531,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
 
 	if (ctx->report_progress)
 		ctx->progress = start_delayed_progress(
-					the_repository,
+					ctx->r,
 					_("Loading known commits in commit graph"),
 					ctx->oids.nr);
 	for (i = 0; i < ctx->oids.nr; i++) {
@@ -1552,7 +1549,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
 	 */
 	if (ctx->report_progress)
 		ctx->progress = start_delayed_progress(
-					the_repository,
+					ctx->r,
 					_("Expanding reachable commits in commit graph"),
 					0);
 	for (i = 0; i < ctx->oids.nr; i++) {
@@ -1573,7 +1570,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
 
 	if (ctx->report_progress)
 		ctx->progress = start_delayed_progress(
-					the_repository,
+					ctx->r,
 					_("Clearing commit marks in commit graph"),
 					ctx->oids.nr);
 	for (i = 0; i < ctx->oids.nr; i++) {
@@ -1691,7 +1688,7 @@ static void compute_topological_levels(struct write_commit_graph_context *ctx)
 	if (ctx->report_progress)
 		info.progress = ctx->progress
 			      = start_delayed_progress(
-					the_repository,
+					ctx->r,
 					_("Computing commit graph topological levels"),
 					ctx->commits.nr);
 
@@ -1726,7 +1723,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
 	if (ctx->report_progress)
 		info.progress = ctx->progress
 			      = start_delayed_progress(
-					the_repository,
+					ctx->r,
 					_("Computing commit graph generation numbers"),
 					ctx->commits.nr);
 
@@ -1803,7 +1800,7 @@ static void compute_bloom_filters(struct write_commit_graph_context *ctx)
 
 	if (ctx->report_progress)
 		progress = start_delayed_progress(
-			the_repository,
+			ctx->r,
 			_("Computing commit changed paths Bloom filters"),
 			ctx->commits.nr);
 
@@ -1849,22 +1846,21 @@ static void compute_bloom_filters(struct write_commit_graph_context *ctx)
 }
 
 struct refs_cb_data {
+	struct repository *repo;
 	struct oidset *commits;
 	struct progress *progress;
 };
 
-static int add_ref_to_set(const char *refname UNUSED,
-			  const char *referent UNUSED,
-			  const struct object_id *oid,
-			  int flags UNUSED, void *cb_data)
+static int add_ref_to_set(const struct reference *ref, void *cb_data)
 {
+	const struct object_id *maybe_peeled = ref->oid;
 	struct object_id peeled;
 	struct refs_cb_data *data = (struct refs_cb_data *)cb_data;
 
-	if (!peel_iterated_oid(the_repository, oid, &peeled))
-		oid = &peeled;
-	if (odb_read_object_info(the_repository->objects, oid, NULL) == OBJ_COMMIT)
-		oidset_insert(data->commits, oid);
+	if (!reference_get_peeled_oid(data->repo, ref, &peeled))
+		maybe_peeled = &peeled;
+	if (odb_read_object_info(data->repo->objects, maybe_peeled, NULL) == OBJ_COMMIT)
+		oidset_insert(data->commits, maybe_peeled);
 
 	display_progress(data->progress, oidset_size(data->commits));
 
@@ -1880,13 +1876,15 @@ int write_commit_graph_reachable(struct odb_source *source,
 	int result;
 
 	memset(&data, 0, sizeof(data));
+	data.repo = source->odb->repo;
 	data.commits = &commits;
+
 	if (flags & COMMIT_GRAPH_WRITE_PROGRESS)
 		data.progress = start_delayed_progress(
-			the_repository,
+			source->odb->repo,
 			_("Collecting referenced commits"), 0);
 
-	refs_for_each_ref(get_main_ref_store(the_repository), add_ref_to_set,
+	refs_for_each_ref(get_main_ref_store(source->odb->repo), add_ref_to_set,
 			  &data);
 
 	stop_progress(&data.progress);
@@ -1915,7 +1913,7 @@ static int fill_oids_from_packs(struct write_commit_graph_context *ctx,
 			       "Finding commits for commit graph in %"PRIuMAX" packs",
 			       pack_indexes->nr),
 			    (uintmax_t)pack_indexes->nr);
-		ctx->progress = start_delayed_progress(the_repository,
+		ctx->progress = start_delayed_progress(ctx->r,
 						       progress_title.buf, 0);
 		ctx->progress_done = 0;
 	}
@@ -1969,7 +1967,7 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
 {
 	if (ctx->report_progress)
 		ctx->progress = start_delayed_progress(
-			the_repository,
+			ctx->r,
 			_("Finding commits for commit graph among packed objects"),
 			ctx->approx_nr_objects);
 	for_each_packed_object(ctx->r, add_packed_commits, ctx,
@@ -1988,7 +1986,7 @@ static void copy_oids_to_commits(struct write_commit_graph_context *ctx)
 	ctx->num_extra_edges = 0;
 	if (ctx->report_progress)
 		ctx->progress = start_delayed_progress(
-			the_repository,
+			ctx->r,
 			_("Finding extra edges in commit graph"),
 			ctx->oids.nr);
 	oid_array_sort(&ctx->oids);
@@ -2027,7 +2025,7 @@ static int write_graph_chunk_base_1(struct hashfile *f,
 		return 0;
 
 	num = write_graph_chunk_base_1(f, g->base_graph);
-	hashwrite(f, g->oid.hash, the_hash_algo->rawsz);
+	hashwrite(f, g->oid.hash, g->hash_algo->rawsz);
 	return num + 1;
 }
 
@@ -2051,7 +2049,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 	struct hashfile *f;
 	struct tempfile *graph_layer; /* when ctx->split is non-zero */
 	struct lock_file lk = LOCK_INIT;
-	const unsigned hashsz = the_hash_algo->rawsz;
+	const unsigned hashsz = ctx->r->hash_algo->rawsz;
 	struct strbuf progress_title = STRBUF_INIT;
 	struct chunkfile *cf;
 	unsigned char file_hash[GIT_MAX_RAWSZ];
@@ -2067,7 +2065,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 		ctx->graph_name = get_commit_graph_filename(ctx->odb_source);
 	}
 
-	if (safe_create_leading_directories(the_repository, ctx->graph_name)) {
+	if (safe_create_leading_directories(ctx->r, ctx->graph_name)) {
 		error(_("unable to create leading directories of %s"),
 			ctx->graph_name);
 		return -1;
@@ -2086,18 +2084,18 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 			return -1;
 		}
 
-		if (adjust_shared_perm(the_repository, get_tempfile_path(graph_layer))) {
+		if (adjust_shared_perm(ctx->r, get_tempfile_path(graph_layer))) {
 			error(_("unable to adjust shared permissions for '%s'"),
 			      get_tempfile_path(graph_layer));
 			return -1;
 		}
 
-		f = hashfd(the_repository->hash_algo,
+		f = hashfd(ctx->r->hash_algo,
 			   get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer));
 	} else {
 		hold_lock_file_for_update_mode(&lk, ctx->graph_name,
 					       LOCK_DIE_ON_ERROR, 0444);
-		f = hashfd(the_repository->hash_algo,
+		f = hashfd(ctx->r->hash_algo,
 			   get_lock_file_fd(&lk), get_lock_file_path(&lk));
 	}
 
@@ -2139,7 +2137,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 	hashwrite_be32(f, GRAPH_SIGNATURE);
 
 	hashwrite_u8(f, GRAPH_VERSION);
-	hashwrite_u8(f, oid_version(the_hash_algo));
+	hashwrite_u8(f, oid_version(ctx->r->hash_algo));
 	hashwrite_u8(f, get_num_chunks(cf));
 	hashwrite_u8(f, ctx->num_commit_graphs_after - 1);
 
@@ -2150,7 +2148,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 			       get_num_chunks(cf)),
 			    get_num_chunks(cf));
 		ctx->progress = start_delayed_progress(
-			the_repository,
+			ctx->r,
 			progress_title.buf,
 			st_mult(get_num_chunks(cf), ctx->commits.nr));
 	}
@@ -2208,7 +2206,8 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 		}
 
 		free(ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]);
-		ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1] = xstrdup(hash_to_hex(file_hash));
+		ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1] =
+			xstrdup(hash_to_hex_algop(file_hash, ctx->r->hash_algo));
 		final_graph_name = get_split_graph_filename(ctx->odb_source,
 					ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]);
 		free(ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 1]);
@@ -2230,7 +2229,8 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 	return 0;
 }
 
-static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
+static void split_graph_merge_strategy(struct write_commit_graph_context *ctx,
+				       struct commit_graph *graph_to_merge)
 {
 	struct commit_graph *g;
 	uint32_t num_commits;
@@ -2249,7 +2249,7 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
 		flags = ctx->opts->split_flags;
 	}
 
-	g = ctx->r->objects->commit_graph;
+	g = graph_to_merge;
 	num_commits = ctx->commits.nr;
 	if (flags == COMMIT_GRAPH_SPLIT_REPLACE)
 		ctx->num_commit_graphs_after = 1;
@@ -2301,7 +2301,7 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
 		ctx->commit_graph_filenames_after[i] = xstrdup(ctx->commit_graph_filenames_before[i]);
 
 	i = ctx->num_commit_graphs_before - 1;
-	g = ctx->r->objects->commit_graph;
+	g = graph_to_merge;
 
 	while (g) {
 		if (i < ctx->num_commit_graphs_after)
@@ -2363,7 +2363,7 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
 
 	if (ctx->report_progress)
 		ctx->progress = start_delayed_progress(
-					the_repository,
+					ctx->r,
 					_("Scanning merged commits"),
 					ctx->commits.nr);
 
@@ -2399,16 +2399,16 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
 	stop_progress(&ctx->progress);
 }
 
-static void merge_commit_graphs(struct write_commit_graph_context *ctx)
+static void merge_commit_graphs(struct write_commit_graph_context *ctx,
+				struct commit_graph *g)
 {
-	struct commit_graph *g = ctx->r->objects->commit_graph;
 	uint32_t current_graph_number = ctx->num_commit_graphs_before;
 
 	while (g && current_graph_number >= ctx->num_commit_graphs_after) {
 		current_graph_number--;
 
 		if (ctx->report_progress)
-			ctx->progress = start_delayed_progress(the_repository,
+			ctx->progress = start_delayed_progress(ctx->r,
 							       _("Merging commit-graph"), 0);
 
 		merge_commit_graph(ctx, g);
@@ -2511,7 +2511,7 @@ int write_commit_graph(struct odb_source *source,
 		       enum commit_graph_write_flags flags,
 		       const struct commit_graph_opts *opts)
 {
-	struct repository *r = the_repository;
+	struct repository *r = source->odb->repo;
 	struct write_commit_graph_context ctx = {
 		.r = r,
 		.odb_source = source,
@@ -2528,6 +2528,7 @@ int write_commit_graph(struct odb_source *source,
 	int replace = 0;
 	struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
 	struct topo_level_slab topo_levels;
+	struct commit_graph *g;
 
 	prepare_repo_settings(r);
 	if (!r->settings.core_commit_graph) {
@@ -2556,23 +2557,13 @@ int write_commit_graph(struct odb_source *source,
 	init_topo_level_slab(&topo_levels);
 	ctx.topo_levels = &topo_levels;
 
-	prepare_commit_graph(ctx.r);
-	if (ctx.r->objects->commit_graph) {
-		struct commit_graph *g = ctx.r->objects->commit_graph;
-
-		while (g) {
-			g->topo_levels = &topo_levels;
-			g = g->base_graph;
-		}
-	}
+	g = prepare_commit_graph(ctx.r);
+	for (struct commit_graph *chain = g; chain; chain = chain->base_graph)
+		g->topo_levels = &topo_levels;
 
 	if (flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS)
 		ctx.changed_paths = 1;
 	if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {
-		struct commit_graph *g;
-
-		g = ctx.r->objects->commit_graph;
-
 		/* We have changed-paths already. Keep them in the next graph */
 		if (g && g->bloom_filter_settings) {
 			ctx.changed_paths = 1;
@@ -2589,36 +2580,28 @@ int write_commit_graph(struct odb_source *source,
 	bloom_settings.hash_version = bloom_settings.hash_version == 2 ? 2 : 1;
 
 	if (ctx.split) {
-		struct commit_graph *g = ctx.r->objects->commit_graph;
-
-		while (g) {
+		for (struct commit_graph *chain = g; chain; chain = chain->base_graph)
 			ctx.num_commit_graphs_before++;
-			g = g->base_graph;
-		}
 
 		if (ctx.num_commit_graphs_before) {
 			ALLOC_ARRAY(ctx.commit_graph_filenames_before, ctx.num_commit_graphs_before);
 			i = ctx.num_commit_graphs_before;
-			g = ctx.r->objects->commit_graph;
 
-			while (g) {
-				ctx.commit_graph_filenames_before[--i] = xstrdup(g->filename);
-				g = g->base_graph;
-			}
+			for (struct commit_graph *chain = g; chain; chain = chain->base_graph)
+				ctx.commit_graph_filenames_before[--i] = xstrdup(chain->filename);
 		}
 
 		if (ctx.opts)
 			replace = ctx.opts->split_flags & COMMIT_GRAPH_SPLIT_REPLACE;
 	}
 
-	ctx.approx_nr_objects = repo_approximate_object_count(the_repository);
+	ctx.approx_nr_objects = repo_approximate_object_count(r);
 
-	if (ctx.append && ctx.r->objects->commit_graph) {
-		struct commit_graph *g = ctx.r->objects->commit_graph;
+	if (ctx.append && g) {
 		for (i = 0; i < g->num_commits; i++) {
 			struct object_id oid;
-			oidread(&oid, g->chunk_oid_lookup + st_mult(g->hash_len, i),
-				the_repository->hash_algo);
+			oidread(&oid, g->chunk_oid_lookup + st_mult(g->hash_algo->rawsz, i),
+				r->hash_algo);
 			oid_array_append(&ctx.oids, &oid);
 		}
 	}
@@ -2653,14 +2636,15 @@ int write_commit_graph(struct odb_source *source,
 		goto cleanup;
 
 	if (ctx.split) {
-		split_graph_merge_strategy(&ctx);
+		split_graph_merge_strategy(&ctx, g);
 
 		if (!replace)
-			merge_commit_graphs(&ctx);
-	} else
+			merge_commit_graphs(&ctx, g);
+	} else {
 		ctx.num_commit_graphs_after = 1;
+	}
 
-	ctx.trust_generation_numbers = validate_mixed_generation_chain(ctx.r->objects->commit_graph);
+	ctx.trust_generation_numbers = validate_mixed_generation_chain(g);
 
 	compute_topological_levels(&ctx);
 	if (ctx.write_generation_data)
@@ -2726,15 +2710,15 @@ static void graph_report(const char *fmt, ...)
 
 static int commit_graph_checksum_valid(struct commit_graph *g)
 {
-	return hashfile_checksum_valid(the_repository->hash_algo,
+	return hashfile_checksum_valid(g->hash_algo,
 				       g->data, g->data_len);
 }
 
-static int verify_one_commit_graph(struct repository *r,
-				   struct commit_graph *g,
+static int verify_one_commit_graph(struct commit_graph *g,
 				   struct progress *progress,
 				   uint64_t *seen)
 {
+	struct repository *r = g->odb_source->odb->repo;
 	uint32_t i, cur_fanout_pos = 0;
 	struct object_id prev_oid, cur_oid;
 	struct commit *seen_gen_zero = NULL;
@@ -2748,8 +2732,8 @@ static int verify_one_commit_graph(struct repository *r,
 	for (i = 0; i < g->num_commits; i++) {
 		struct commit *graph_commit;
 
-		oidread(&cur_oid, g->chunk_oid_lookup + st_mult(g->hash_len, i),
-			the_repository->hash_algo);
+		oidread(&cur_oid, g->chunk_oid_lookup + st_mult(g->hash_algo->rawsz, i),
+			g->hash_algo);
 
 		if (i && oidcmp(&prev_oid, &cur_oid) >= 0)
 			graph_report(_("commit-graph has incorrect OID order: %s then %s"),
@@ -2768,7 +2752,7 @@ static int verify_one_commit_graph(struct repository *r,
 		}
 
 		graph_commit = lookup_commit(r, &cur_oid);
-		if (!parse_commit_in_graph_one(r, g, graph_commit))
+		if (!parse_commit_in_graph_one(g, graph_commit))
 			graph_report(_("failed to parse commit %s from commit-graph"),
 				     oid_to_hex(&cur_oid));
 	}
@@ -2793,8 +2777,8 @@ static int verify_one_commit_graph(struct repository *r,
 		timestamp_t generation;
 
 		display_progress(progress, ++(*seen));
-		oidread(&cur_oid, g->chunk_oid_lookup + st_mult(g->hash_len, i),
-			the_repository->hash_algo);
+		oidread(&cur_oid, g->chunk_oid_lookup + st_mult(g->hash_algo->rawsz, i),
+			g->hash_algo);
 
 		graph_commit = lookup_commit(r, &cur_oid);
 		odb_commit = (struct commit *)create_object(r, &cur_oid, alloc_commit_node(r));
@@ -2804,7 +2788,7 @@ static int verify_one_commit_graph(struct repository *r,
 			continue;
 		}
 
-		if (!oideq(&get_commit_tree_in_graph_one(r, g, graph_commit)->object.oid,
+		if (!oideq(&get_commit_tree_in_graph_one(g, graph_commit)->object.oid,
 			   get_commit_tree_oid(odb_commit)))
 			graph_report(_("root tree OID for commit %s in commit-graph is %s != %s"),
 				     oid_to_hex(&cur_oid),
@@ -2822,7 +2806,7 @@ static int verify_one_commit_graph(struct repository *r,
 			}
 
 			/* parse parent in case it is in a base graph */
-			parse_commit_in_graph_one(r, g, graph_parents->item);
+			parse_commit_in_graph_one(g, graph_parents->item);
 
 			if (!oideq(&graph_parents->item->object.oid, &odb_parents->item->object.oid))
 				graph_report(_("commit-graph parent for %s is %s != %s"),
@@ -2882,7 +2866,7 @@ static int verify_one_commit_graph(struct repository *r,
 	return verify_commit_graph_error;
 }
 
-int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags)
+int verify_commit_graph(struct commit_graph *g, int flags)
 {
 	struct progress *progress = NULL;
 	int local_error = 0;
@@ -2898,13 +2882,13 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags)
 		if (!(flags & COMMIT_GRAPH_VERIFY_SHALLOW))
 			total += g->num_commits_in_base;
 
-		progress = start_progress(the_repository,
+		progress = start_progress(g->odb_source->odb->repo,
 					  _("Verifying commits in commit graph"),
 					  total);
 	}
 
 	for (; g; g = g->base_graph) {
-		local_error |= verify_one_commit_graph(r, g, progress, &seen);
+		local_error |= verify_one_commit_graph(g, progress, &seen);
 		if (flags & COMMIT_GRAPH_VERIFY_SHALLOW)
 			break;
 	}
diff --git a/commit-graph.h b/commit-graph.h
index 78ab7b8..f6a5433 100644
--- a/commit-graph.h
+++ b/commit-graph.h
@@ -21,7 +21,7 @@
  * call this method oustide of a builtin, and only if you know what
  * you are doing!
  */
-void git_test_write_commit_graph_or_die(void);
+void git_test_write_commit_graph_or_die(struct odb_source *source);
 
 struct commit;
 struct bloom_filter_settings;
@@ -32,7 +32,8 @@ struct string_list;
 char *get_commit_graph_filename(struct odb_source *source);
 char *get_commit_graph_chain_filename(struct odb_source *source);
 int open_commit_graph(const char *graph_file, int *fd, struct stat *st);
-int open_commit_graph_chain(const char *chain_file, int *fd, struct stat *st);
+int open_commit_graph_chain(const char *chain_file, int *fd, struct stat *st,
+			    const struct git_hash_algo *hash_algo);
 
 /*
  * Given a commit struct, try to fill the commit struct info, including:
@@ -47,10 +48,9 @@ int open_commit_graph_chain(const char *chain_file, int *fd, struct stat *st);
 int parse_commit_in_graph(struct repository *r, struct commit *item);
 
 /*
- * Fills `*pos` with the graph position of `c`, and returns 1 if `c` is
- * found in the commit-graph belonging to `r`, or 0 otherwise.
- * Initializes the commit-graph belonging to `r` if it hasn't been
- * already.
+ * Fills `*pos` with the graph position of `c`, and returns the graph `c` is
+ * found in, or NULL otherwise. Initializes the commit-graphs belonging to
+ * `r` if it hasn't been already.
  *
  * Note: this is a low-level helper that does not alter any slab data
  * associated with `c`. Useful in circumstances where the slab data is
@@ -58,8 +58,9 @@ int parse_commit_in_graph(struct repository *r, struct commit *item);
  *
  * In most cases, callers should use `parse_commit_in_graph()` instead.
  */
-int repo_find_commit_pos_in_graph(struct repository *r, struct commit *c,
-				  uint32_t *pos);
+struct commit_graph *repo_find_commit_pos_in_graph(struct repository *r,
+						   struct commit *c,
+						   uint32_t *pos);
 
 /*
  * Look up the given commit ID in the commit-graph. This will only return a
@@ -84,7 +85,7 @@ struct commit_graph {
 	const unsigned char *data;
 	size_t data_len;
 
-	unsigned char hash_len;
+	const struct git_hash_algo *hash_algo;
 	unsigned char num_chunks;
 	uint32_t num_commits;
 	struct object_id oid;
@@ -113,14 +114,12 @@ struct commit_graph {
 	struct bloom_filter_settings *bloom_filter_settings;
 };
 
-struct commit_graph *load_commit_graph_one_fd_st(struct repository *r,
-						 int fd, struct stat *st,
-						 struct odb_source *source);
-struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r,
+struct commit_graph *load_commit_graph_one_fd_st(struct odb_source *source,
+						 int fd, struct stat *st);
+struct commit_graph *load_commit_graph_chain_fd_st(struct object_database *odb,
 						   int fd, struct stat *st,
 						   int *incomplete_chain);
-struct commit_graph *read_commit_graph_one(struct repository *r,
-					   struct odb_source *source);
+struct commit_graph *read_commit_graph_one(struct odb_source *source);
 
 struct repo_settings;
 
@@ -128,7 +127,7 @@ struct repo_settings;
  * Callers should initialize the repo_settings with prepare_repo_settings()
  * prior to calling parse_commit_graph().
  */
-struct commit_graph *parse_commit_graph(struct repo_settings *s,
+struct commit_graph *parse_commit_graph(struct repository *r,
 					void *graph_map, size_t graph_size);
 
 /*
@@ -184,7 +183,7 @@ int write_commit_graph(struct odb_source *source,
 
 #define COMMIT_GRAPH_VERIFY_SHALLOW	(1 << 0)
 
-int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags);
+int verify_commit_graph(struct commit_graph *g, int flags);
 
 void close_commit_graph(struct object_database *);
 void free_commit_graph(struct commit_graph *);
diff --git a/commit-reach.c b/commit-reach.c
index a339e41..cc18c86 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -60,6 +60,7 @@ static int paint_down_to_common(struct repository *r,
 	struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
 	int i;
 	timestamp_t last_gen = GENERATION_NUMBER_INFINITY;
+	struct commit_list **tail = result;
 
 	if (!min_generation && !corrected_commit_dates_enabled(r))
 		queue.compare = compare_commits_by_commit_date;
@@ -95,7 +96,7 @@ static int paint_down_to_common(struct repository *r,
 		if (flags == (PARENT1 | PARENT2)) {
 			if (!(commit->object.flags & RESULT)) {
 				commit->object.flags |= RESULT;
-				commit_list_insert_by_date(commit, result);
+				tail = commit_list_append(commit, tail);
 			}
 			/* Mark parents of a found merge stale */
 			flags |= STALE;
@@ -128,6 +129,7 @@ static int paint_down_to_common(struct repository *r,
 	}
 
 	clear_prio_queue(&queue);
+	commit_list_sort_by_date(result);
 	return 0;
 }
 
@@ -136,7 +138,7 @@ static int merge_bases_many(struct repository *r,
 			    struct commit **twos,
 			    struct commit_list **result)
 {
-	struct commit_list *list = NULL;
+	struct commit_list *list = NULL, **tail = result;
 	int i;
 
 	for (i = 0; i < n; i++) {
@@ -171,8 +173,9 @@ static int merge_bases_many(struct repository *r,
 	while (list) {
 		struct commit *commit = pop_commit(&list);
 		if (!(commit->object.flags & STALE))
-			commit_list_insert_by_date(commit, result);
+			tail = commit_list_append(commit, tail);
 	}
+	commit_list_sort_by_date(result);
 	return 0;
 }
 
@@ -425,7 +428,7 @@ static int get_merge_bases_many_0(struct repository *r,
 				  int cleanup,
 				  struct commit_list **result)
 {
-	struct commit_list *list;
+	struct commit_list *list, **tail = result;
 	struct commit **rslt;
 	size_t cnt, i;
 	int ret;
@@ -461,7 +464,8 @@ static int get_merge_bases_many_0(struct repository *r,
 		return -1;
 	}
 	for (i = 0; i < cnt; i++)
-		commit_list_insert_by_date(rslt[i], result);
+		tail = commit_list_append(rslt[i], tail);
+	commit_list_sort_by_date(result);
 	free(rslt);
 	return 0;
 }
diff --git a/commit.c b/commit.c
index d1e1061..16d91b2 100644
--- a/commit.c
+++ b/commit.c
@@ -1039,7 +1039,8 @@ static void add_one_commit(struct object_id *oid, struct rev_collect *revs)
 	commit->object.flags |= TMP_MARK;
 }
 
-static int collect_one_reflog_ent(struct object_id *ooid, struct object_id *noid,
+static int collect_one_reflog_ent(const char *refname UNUSED,
+				  struct object_id *ooid, struct object_id *noid,
 				  const char *ident UNUSED,
 				  timestamp_t timestamp UNUSED, int tz UNUSED,
 				  const char *message UNUSED, void *cbdata)
diff --git a/compat/mingw.c b/compat/mingw.c
index 8538e3d..736a07a 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1,26 +1,26 @@
 #define USE_THE_REPOSITORY_VARIABLE
 #define DISABLE_SIGN_COMPARE_WARNINGS
 
-#include "../git-compat-util.h"
-#include "win32.h"
-#include <aclapi.h>
-#include <sddl.h>
-#include <conio.h>
-#include <wchar.h>
-#include "../strbuf.h"
-#include "../run-command.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 "git-compat-util.h"
+#include "abspath.h"
+#include "alloc.h"
+#include "config.h"
 #include "dir.h"
+#include "environment.h"
 #include "gettext.h"
+#include "run-command.h"
+#include "strbuf.h"
+#include "symlinks.h"
+#include "trace2.h"
+#include "win32.h"
+#include "win32/lazyload.h"
+#include "wrapper.h"
+#include <aclapi.h>
+#include <conio.h>
+#include <sddl.h>
 #define SECURITY_WIN32
 #include <sspi.h>
+#include <wchar.h>
 #include <winternl.h>
 
 #define STATUS_DELETE_PENDING ((NTSTATUS) 0xC0000056)
diff --git a/config.c b/config.c
index 97ffef4..f1def0d 100644
--- a/config.c
+++ b/config.c
@@ -8,9 +8,11 @@
 
 #include "git-compat-util.h"
 #include "abspath.h"
+#include "advice.h"
 #include "date.h"
 #include "branch.h"
 #include "config.h"
+#include "dir.h"
 #include "parse.h"
 #include "convert.h"
 #include "environment.h"
@@ -629,31 +631,28 @@ int git_config_parse_parameter(const char *text,
 			       config_fn_t fn, void *data)
 {
 	const char *value;
-	struct strbuf **pair;
+	struct string_list pair = STRING_LIST_INIT_DUP;
 	int ret;
 	struct key_value_info kvi = KVI_INIT;
 
 	kvi_from_param(&kvi);
 
-	pair = strbuf_split_str(text, '=', 2);
-	if (!pair[0])
+	string_list_split(&pair, text, "=", 1);
+	if (!pair.nr)
 		return error(_("bogus config parameter: %s"), text);
 
-	if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=') {
-		strbuf_setlen(pair[0], pair[0]->len - 1);
-		value = pair[1] ? pair[1]->buf : "";
-	} else {
+	if (pair.nr == 1)
 		value = NULL;
-	}
+	else
+		value = pair.items[1].string;
 
-	strbuf_trim(pair[0]);
-	if (!pair[0]->len) {
-		strbuf_list_free(pair);
+	if (!*pair.items[0].string) {
+		string_list_clear(&pair, 0);
 		return error(_("bogus config parameter: %s"), text);
 	}
 
-	ret = config_parse_pair(pair[0]->buf, value, &kvi, fn, data);
-	strbuf_list_free(pair);
+	ret = config_parse_pair(pair.items[0].string, value, &kvi, fn, data);
+	string_list_clear(&pair, 0);
 	return ret;
 }
 
@@ -1279,11 +1278,23 @@ int git_config_string(char **dest, const char *var, const char *value)
 
 int git_config_pathname(char **dest, const char *var, const char *value)
 {
+	bool is_optional;
+	char *path;
+
 	if (!value)
 		return config_error_nonbool(var);
-	*dest = interpolate_path(value, 0);
-	if (!*dest)
+
+	is_optional = skip_prefix(value, ":(optional)", &value);
+	path = interpolate_path(value, 0);
+	if (!path)
 		die(_("failed to expand user dir in: '%s'"), value);
+
+	if (is_optional && is_missing_file(path)) {
+		free(path);
+		return 0;
+	}
+
+	*dest = path;
 	return 0;
 }
 
@@ -1951,10 +1962,290 @@ int git_configset_get_pathname(struct config_set *set, const char *key, char **d
 		return 1;
 }
 
+struct comment_char_config {
+	unsigned last_key_id;
+	bool auto_set;
+	bool auto_set_in_file;
+	struct strintmap key_flags;
+	size_t alloc, nr;
+	struct comment_char_config_item {
+		unsigned key_id;
+		char *path;
+		enum config_scope scope;
+	} *item;
+};
+
+#define COMMENT_CHAR_CFG_INIT {			\
+		.key_flags = STRINTMAP_INIT,	\
+	}
+
+static void comment_char_config_release(struct comment_char_config *config)
+{
+	strintmap_clear(&config->key_flags);
+	for (size_t i = 0; i < config->nr; i++)
+		free(config->item[i].path);
+	free(config->item);
+}
+
+/* Used to track whether the key occurs more than once in a given file */
+#define KEY_SEEN_ONCE 1u
+#define KEY_SEEN_TWICE 2u
+#define COMMENT_KEY_SHIFT(id) (2 * (id))
+#define COMMENT_KEY_MASK(id) (3u << COMMENT_KEY_SHIFT(id))
+
+static void set_comment_key_flags(struct comment_char_config *config,
+				  const char *path, unsigned id, unsigned value)
+{
+	unsigned old = strintmap_get(&config->key_flags, path);
+	unsigned new = (old & ~COMMENT_KEY_MASK(id)) |
+				value << COMMENT_KEY_SHIFT(id);
+
+	strintmap_set(&config->key_flags, path, new);
+}
+
+static unsigned get_comment_key_flags(struct comment_char_config *config,
+				      const char *path, unsigned id)
+{
+	unsigned value = strintmap_get(&config->key_flags, path);
+
+	return (value & COMMENT_KEY_MASK(id)) >> COMMENT_KEY_SHIFT(id);
+}
+
+static const char *comment_key_name(unsigned id)
+{
+	static const char *name[] = {
+		"core.commentChar",
+		"core.commentString",
+	};
+
+	if (id >= ARRAY_SIZE(name))
+		BUG("invalid comment key id");
+
+	return name[id];
+}
+
+static void comment_char_callback(const char *key, const char *value,
+				  const struct config_context *ctx, void *data)
+{
+	struct comment_char_config *config = data;
+	const struct key_value_info *kvi = ctx->kvi;
+	unsigned key_id;
+
+	if (!strcmp(key, "core.commentchar"))
+		key_id = 0;
+	else if (!strcmp(key, "core.commentstring"))
+		key_id = 1;
+	else
+		return;
+
+	config->last_key_id = key_id;
+	config->auto_set = value && !strcmp(value, "auto");
+	if (kvi->origin_type != CONFIG_ORIGIN_FILE) {
+		return;
+	} else if (get_comment_key_flags(config, kvi->filename, key_id)) {
+		set_comment_key_flags(config, kvi->filename, key_id,
+				      KEY_SEEN_TWICE);
+	} else {
+		struct comment_char_config_item *item;
+
+		ALLOC_GROW_BY(config->item, config->nr, 1, config->alloc);
+		item = &config->item[config->nr - 1];
+		item->key_id = key_id;
+		item->scope = kvi->scope;
+		item->path = xstrdup(kvi->filename);
+		set_comment_key_flags(config, kvi->filename, key_id,
+				      KEY_SEEN_ONCE);
+	}
+	config->auto_set_in_file = config->auto_set;
+}
+
+static void add_config_scope_arg(struct repository *repo, struct strbuf *buf,
+				 struct comment_char_config_item *item)
+{
+	char *global_config = git_global_config();
+	char *system_config = git_system_config();
+
+	if (item->scope == CONFIG_SCOPE_SYSTEM && access(item->path, W_OK)) {
+		/*
+		 * If the user cannot write to the system config recommend
+		 * setting the global config instead.
+		 */
+		strbuf_addstr(buf, "--global ");
+	} else if (fspatheq(item->path, system_config)) {
+		strbuf_addstr(buf, "--system ");
+	} else if (fspatheq(item->path, global_config)) {
+		strbuf_addstr(buf, "--global ");
+	} else if (fspatheq(item->path,
+			    mkpath("%s/config",
+				   repo_get_git_dir(repo)))) {
+		; /* --local is the default */
+	} else if (fspatheq(item->path,
+			    mkpath("%s/config.worktree",
+				   repo_get_common_dir(repo)))) {
+		strbuf_addstr(buf, "--worktree ");
+	} else {
+		const char *path = item->path;
+		const char *home = getenv("HOME");
+
+		strbuf_addstr(buf, "--file ");
+		if (home && !fspathncmp(path, home, strlen(home))) {
+			path += strlen(home);
+			if (!fspathncmp(path, "/", 1))
+				path++;
+			strbuf_addstr(buf, "~/");
+		}
+		sq_quote_buf_pretty(buf, path);
+		strbuf_addch(buf, ' ');
+	}
+
+	free(global_config);
+	free(system_config);
+}
+
+static bool can_unset_comment_char_config(struct comment_char_config *config)
+{
+	for (size_t i = 0; i < config->nr; i++) {
+		struct comment_char_config_item *item = &config->item[i];
+
+		if (item->scope == CONFIG_SCOPE_SYSTEM &&
+		    access(item->path, W_OK))
+			return false;
+	}
+
+	return true;
+}
+
+static void add_unset_auto_comment_char_advice(struct repository *repo,
+					       struct comment_char_config *config)
+{
+	struct strbuf buf = STRBUF_INIT;
+
+	if (!can_unset_comment_char_config(config))
+		return;
+
+	for (size_t i = 0; i < config->nr; i++) {
+		struct comment_char_config_item *item = &config->item[i];
+
+		strbuf_addstr(&buf, "    git config unset ");
+		add_config_scope_arg(repo, &buf, item);
+		if (get_comment_key_flags(config, item->path, item->key_id) == KEY_SEEN_TWICE)
+			strbuf_addstr(&buf, "--all ");
+		strbuf_addf(&buf, "%s\n", comment_key_name(item->key_id));
+	}
+	advise(_("\nTo use the default comment string (#) please run\n\n%s"),
+	       buf.buf);
+	strbuf_release(&buf);
+}
+
+static void add_comment_char_advice(struct repository *repo,
+				    struct comment_char_config *config)
+{
+	struct strbuf buf = STRBUF_INIT;
+	struct comment_char_config_item *item;
+	/* TRANSLATORS this is a place holder for the value of core.commentString */
+	const char *placeholder = _("<comment string>");
+
+	/*
+	 * If auto is set in the last file that we saw advise the user how to
+	 * update their config.
+	 */
+	if (!config->auto_set_in_file)
+		return;
+
+	add_unset_auto_comment_char_advice(repo, config);
+	item = &config->item[config->nr - 1];
+	strbuf_reset(&buf);
+	strbuf_addstr(&buf, "    git config set ");
+	add_config_scope_arg(repo, &buf, item);
+	strbuf_addf(&buf, "%s %s\n", comment_key_name(item->key_id),
+		    placeholder);
+	advise(_("\nTo set a custom comment string please run\n\n"
+		 "%s\nwhere '%s' is the string you wish to use.\n"),
+	       buf.buf, placeholder);
+	strbuf_release(&buf);
+}
+
+#undef KEY_SEEN_ONCE
+#undef KEY_SEEN_TWICE
+#undef COMMENT_KEY_SHIFT
+#undef COMMENT_KEY_MASK
+
+struct repo_config {
+	struct repository *repo;
+	struct comment_char_config comment_char_config;
+};
+
+#define REPO_CONFIG_INIT(repo_) {				\
+		.comment_char_config = COMMENT_CHAR_CFG_INIT,	\
+		.repo = repo_,					\
+	};
+
+static void repo_config_release(struct repo_config *config)
+{
+	comment_char_config_release(&config->comment_char_config);
+}
+
+#ifdef WITH_BREAKING_CHANGES
+static void check_auto_comment_char_config(struct repository *repo,
+					   struct comment_char_config *config)
+{
+	if (!config->auto_set)
+		return;
+
+	die_message(_("Support for '%s=auto' has been removed in Git 3.0"),
+		    comment_key_name(config->last_key_id));
+	add_comment_char_advice(repo, config);
+	die(NULL);
+}
+#else
+static void check_auto_comment_char_config(struct repository *repo,
+					   struct comment_char_config *config)
+{
+	extern bool warn_on_auto_comment_char;
+	const char *DEPRECATED_CONFIG_ENV =
+				"GIT_AUTO_COMMENT_CHAR_CONFIG_WARNING_GIVEN";
+
+	if (!config->auto_set || !warn_on_auto_comment_char)
+		return;
+
+	/*
+	 * Use an environment variable to ensure that subprocesses do not repeat
+	 * the warning.
+	 */
+	if (git_env_bool(DEPRECATED_CONFIG_ENV, false))
+		return;
+
+	setenv(DEPRECATED_CONFIG_ENV, "true", true);
+
+	warning(_("Support for '%s=auto' is deprecated and will be removed in "
+		  "Git 3.0"), comment_key_name(config->last_key_id));
+	add_comment_char_advice(repo, config);
+}
+#endif /* WITH_BREAKING_CHANGES */
+
+static void check_deprecated_config(struct repo_config *config)
+{
+	if (!config->repo->check_deprecated_config)
+			return;
+
+	check_auto_comment_char_config(config->repo,
+				       &config->comment_char_config);
+}
+
+static int repo_config_callback(const char *key, const char *value,
+				const struct config_context *ctx, void *data)
+{
+	struct repo_config *config = data;
+
+	comment_char_callback(key, value, ctx, &config->comment_char_config);
+	return config_set_callback(key, value, ctx, config->repo->config);
+}
+
 /* Functions use to read configuration from a repository */
 static void repo_read_config(struct repository *repo)
 {
 	struct config_options opts = { 0 };
+	struct repo_config config = REPO_CONFIG_INIT(repo);
 
 	opts.respect_includes = 1;
 	opts.commondir = repo->commondir;
@@ -1966,8 +2257,8 @@ static void repo_read_config(struct repository *repo)
 		git_configset_clear(repo->config);
 
 	git_configset_init(repo->config);
-	if (config_with_options(config_set_callback, repo->config, NULL,
-				repo, &opts) < 0)
+	if (config_with_options(repo_config_callback, &config, NULL, repo,
+				&opts) < 0)
 		/*
 		 * config_with_options() normally returns only
 		 * zero, as most errors are fatal, and
@@ -1980,6 +2271,8 @@ static void repo_read_config(struct repository *repo)
 		 * immediately.
 		 */
 		die(_("unknown error occurred while reading the configuration files"));
+	check_deprecated_config(&config);
+	repo_config_release(&config);
 }
 
 static void git_config_check_init(struct repository *repo)
@@ -2667,6 +2960,14 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,
 	char *contents = NULL;
 	size_t contents_sz;
 	struct config_store_data store = CONFIG_STORE_INIT;
+	bool saved_check_deprecated_config = r->check_deprecated_config;
+
+	/*
+	 * Do not warn or die if there are deprecated config settings as
+	 * we want the user to be able to change those settings by running
+	 * "git config".
+	 */
+	r->check_deprecated_config = false;
 
 	validate_comment_string(comment);
 
@@ -2898,6 +3199,7 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,
 	if (in_fd >= 0)
 		close(in_fd);
 	config_store_data_clear(&store);
+	r->check_deprecated_config = saved_check_deprecated_config;
 	return ret;
 
 write_err_out:
diff --git a/connect.c b/connect.c
index 34cac24..8352b71 100644
--- a/connect.c
+++ b/connect.c
@@ -407,7 +407,7 @@ static int process_ref_v2(struct packet_reader *reader, struct ref ***list,
 	 * name.  Subsequent fields (symref-target and peeled) are optional and
 	 * don't have a particular order.
 	 */
-	if (string_list_split(&line_sections, line, ' ', -1) < 2) {
+	if (string_list_split(&line_sections, line, " ", -1) < 2) {
 		ret = 0;
 		goto out;
 	}
diff --git a/connected.c b/connected.c
index 18c1324..7940310 100644
--- a/connected.c
+++ b/connected.c
@@ -72,11 +72,11 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 		 * Before checking for promisor packs, be sure we have the
 		 * latest pack-files loaded into memory.
 		 */
-		reprepare_packed_git(the_repository);
+		odb_reprepare(the_repository->objects);
 		do {
 			struct packed_git *p;
 
-			for (p = get_all_packs(the_repository); p; p = p->next) {
+			repo_for_each_pack(the_repository, p) {
 				if (!p->pack_promisor)
 					continue;
 				if (find_pack_entry_one(oid, p))
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index e3d88b0..73abea3 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2218,7 +2218,7 @@
 "
 # Options that go well for log and shortlog (not gitk)
 __git_log_shortlog_options="
-	--author= --committer= --grep=
+	--author= --grep= --exclude=
 	--all-match --invert-grep
 "
 # Options accepted by log and show
@@ -2296,6 +2296,7 @@
 			$__git_log_shortlog_options
 			$__git_log_gitk_options
 			$__git_log_show_options
+			--committer=
 			--root --topo-order --date-order --reverse
 			--follow --full-diff
 			--abbrev-commit --no-abbrev-commit --abbrev=
@@ -3229,7 +3230,7 @@
 		__gitcomp "
 			$__git_log_common_options
 			$__git_log_shortlog_options
-			--numbered --summary --email
+			--committer --numbered --summary --email
 			"
 		return
 		;;
diff --git a/contrib/contacts/meson.build b/contrib/contacts/meson.build
index 73d82df..4ae6b32 100644
--- a/contrib/contacts/meson.build
+++ b/contrib/contacts/meson.build
@@ -20,7 +20,7 @@
     output: 'git-contacts.xml',
   )
 
-  custom_target(
+  doc_targets += custom_target(
     command: [
       xmlto,
       '-m', '@INPUT@',
@@ -39,7 +39,7 @@
 endif
 
 if get_option('docs').contains('html')
-  custom_target(
+  doc_targets += custom_target(
     command: asciidoc_common_options + [
       '--backend=' + asciidoc_html,
       '--doctype=manpage',
@@ -50,6 +50,6 @@
     input: 'git-contacts.adoc',
     output: 'git-contacts.html',
     install: true,
-    install_dir: get_option('datadir') / 'doc/git-doc',
+    install_dir: htmldir,
   )
 endif
diff --git a/contrib/credential/libsecret/Makefile b/contrib/credential/libsecret/Makefile
index 97ce9c9..9309cfb 100644
--- a/contrib/credential/libsecret/Makefile
+++ b/contrib/credential/libsecret/Makefile
@@ -1,28 +1,32 @@
 # The default target of this Makefile is...
-all::
-
-MAIN:=git-credential-libsecret
-all:: $(MAIN)
-
-CC = gcc
-RM = rm -f
-CFLAGS = -g -O2 -Wall
-PKG_CONFIG = pkg-config
+all:: git-credential-libsecret
 
 -include ../../../config.mak.autogen
 -include ../../../config.mak
 
+prefix ?= /usr/local
+gitexecdir ?= $(prefix)/libexec/git-core
+
+CC ?= gcc
+CFLAGS ?= -g -O2 -Wall
+PKG_CONFIG ?= pkg-config
+INSTALL ?= install
+RM ?= rm -f
+
 INCS:=$(shell $(PKG_CONFIG) --cflags libsecret-1 glib-2.0)
 LIBS:=$(shell $(PKG_CONFIG) --libs libsecret-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)
+git-credential-libsecret: git-credential-libsecret.o
+	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
+
+install: git-credential-libsecret
+	$(INSTALL) -d -m 755 $(DESTDIR)$(gitexecdir)
+	$(INSTALL) -m 755 $< $(DESTDIR)$(gitexecdir)
 
 clean:
-	@$(RM) $(MAIN) $(OBJS)
+	$(RM) git-credential-libsecret git-credential-libsecret.o
+
+.PHONY: all install clean
diff --git a/contrib/credential/osxkeychain/Makefile b/contrib/credential/osxkeychain/Makefile
index 0948297..c68445b 100644
--- a/contrib/credential/osxkeychain/Makefile
+++ b/contrib/credential/osxkeychain/Makefile
@@ -1,19 +1,66 @@
 # The default target of this Makefile is...
 all:: git-credential-osxkeychain
 
-CC = gcc
-RM = rm -f
-CFLAGS = -g -O2 -Wall
-
+include ../../../config.mak.uname
 -include ../../../config.mak.autogen
 -include ../../../config.mak
 
-git-credential-osxkeychain: git-credential-osxkeychain.o
-	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) \
+ifdef ZLIB_NG
+	BASIC_CFLAGS += -DHAVE_ZLIB_NG
+        ifdef ZLIB_NG_PATH
+		BASIC_CFLAGS += -I$(ZLIB_NG_PATH)/include
+		EXTLIBS += $(call libpath_template,$(ZLIB_NG_PATH)/$(lib))
+        endif
+	EXTLIBS += -lz-ng
+else
+        ifdef ZLIB_PATH
+		BASIC_CFLAGS += -I$(ZLIB_PATH)/include
+		EXTLIBS += $(call libpath_template,$(ZLIB_PATH)/$(lib))
+        endif
+	EXTLIBS += -lz
+endif
+ifndef NO_ICONV
+        ifdef NEEDS_LIBICONV
+                ifdef ICONVDIR
+			BASIC_CFLAGS += -I$(ICONVDIR)/include
+			ICONV_LINK = $(call libpath_template,$(ICONVDIR)/$(lib))
+                else
+			ICONV_LINK =
+                endif
+                ifdef NEEDS_LIBINTL_BEFORE_LIBICONV
+			ICONV_LINK += -lintl
+                endif
+		EXTLIBS += $(ICONV_LINK) -liconv
+        endif
+endif
+ifndef LIBC_CONTAINS_LIBINTL
+	EXTLIBS += -lintl
+endif
+
+prefix ?= /usr/local
+gitexecdir ?= $(prefix)/libexec/git-core
+
+CC ?= gcc
+CFLAGS ?= -g -O2 -Wall -I../../.. $(BASIC_CFLAGS)
+LDFLAGS ?= $(BASIC_LDFLAGS) $(EXTLIBS)
+INSTALL ?= install
+RM ?= rm -f
+
+%.o: %.c
+	$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
+
+git-credential-osxkeychain: git-credential-osxkeychain.o ../../../libgit.a
+	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) \
 		-framework Security -framework CoreFoundation
 
-git-credential-osxkeychain.o: git-credential-osxkeychain.c
-	$(CC) -c $(CFLAGS) $<
+install: git-credential-osxkeychain
+	$(INSTALL) -d -m 755 $(DESTDIR)$(gitexecdir)
+	$(INSTALL) -m 755 $< $(DESTDIR)$(gitexecdir)
+
+../../../libgit.a:
+	cd ../../..; make libgit.a
 
 clean:
 	$(RM) git-credential-osxkeychain git-credential-osxkeychain.o
+
+.PHONY: all install clean
diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
index 611c979..b180267 100644
--- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
+++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
@@ -2,6 +2,9 @@
 #include <string.h>
 #include <stdlib.h>
 #include <Security/Security.h>
+#include "git-compat-util.h"
+#include "strbuf.h"
+#include "wrapper.h"
 
 #define ENCODING kCFStringEncodingUTF8
 static CFStringRef protocol; /* Stores constant strings - not memory managed */
@@ -12,7 +15,7 @@ static CFStringRef username;
 static CFDataRef password;
 static CFDataRef password_expiry_utc;
 static CFDataRef oauth_refresh_token;
-static int state_seen;
+static char *state_seen;
 
 static void clear_credential(void)
 {
@@ -48,27 +51,6 @@ static void clear_credential(void)
 
 #define STRING_WITH_LENGTH(s) s, sizeof(s) - 1
 
-__attribute__((format (printf, 1, 2), __noreturn__))
-static void die(const char *err, ...)
-{
-	char msg[4096];
-	va_list params;
-	va_start(params, err);
-	vsnprintf(msg, sizeof(msg), err, params);
-	fprintf(stderr, "%s\n", msg);
-	va_end(params);
-	clear_credential();
-	exit(1);
-}
-
-static void *xmalloc(size_t len)
-{
-	void *ret = malloc(len);
-	if (!ret)
-		die("Out of memory");
-	return ret;
-}
-
 static CFDictionaryRef create_dictionary(CFAllocatorRef allocator, ...)
 {
 	va_list args;
@@ -112,6 +94,66 @@ static void write_item(const char *what, const char *buf, size_t len)
 	putchar('\n');
 }
 
+static void write_item_strbuf(struct strbuf *sb, const char *what, const char *buf, int n)
+{
+	char s[32];
+
+	xsnprintf(s, sizeof(s), "__%s=", what);
+	strbuf_add(sb, s, strlen(s));
+	strbuf_add(sb, buf, n);
+}
+
+static void write_item_strbuf_cfstring(struct strbuf *sb, const char *what, CFStringRef ref)
+{
+	char *buf;
+	int len;
+
+	if (!ref)
+		return;
+	len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(ref), ENCODING) + 1;
+	buf = xmalloc(len);
+	if (CFStringGetCString(ref, buf, len, ENCODING))
+		write_item_strbuf(sb, what, buf, strlen(buf));
+	free(buf);
+}
+
+static void write_item_strbuf_cfnumber(struct strbuf *sb, const char *what, CFNumberRef ref)
+{
+	short n;
+	char buf[32];
+
+	if (!ref)
+		return;
+	if (!CFNumberGetValue(ref, kCFNumberShortType, &n))
+		return;
+	xsnprintf(buf, sizeof(buf), "%d", n);
+	write_item_strbuf(sb, what, buf, strlen(buf));
+}
+
+static void write_item_strbuf_cfdata(struct strbuf *sb, const char *what, CFDataRef ref)
+{
+	char *buf;
+	int len;
+
+	if (!ref)
+		return;
+	buf = (char *)CFDataGetBytePtr(ref);
+	if (!buf || strlen(buf) == 0)
+		return;
+	len = CFDataGetLength(ref);
+	write_item_strbuf(sb, what, buf, len);
+}
+
+static void encode_state_seen(struct strbuf *sb)
+{
+	strbuf_add(sb, "osxkeychain:seen=", strlen("osxkeychain:seen="));
+	write_item_strbuf_cfstring(sb, "host", host);
+	write_item_strbuf_cfnumber(sb, "port", port);
+	write_item_strbuf_cfstring(sb, "path", path);
+	write_item_strbuf_cfstring(sb, "username", username);
+	write_item_strbuf_cfdata(sb, "password", password);
+}
+
 static void find_username_in_item(CFDictionaryRef item)
 {
 	CFStringRef account_ref;
@@ -124,6 +166,7 @@ static void find_username_in_item(CFDictionaryRef item)
 		write_item("username", "", 0);
 		return;
 	}
+	username = CFStringCreateCopy(kCFAllocatorDefault, account_ref);
 
 	username_buf = (char *)CFStringGetCStringPtr(account_ref, ENCODING);
 	if (username_buf)
@@ -163,6 +206,7 @@ static OSStatus find_internet_password(void)
 	}
 
 	data = CFDictionaryGetValue(item, kSecValueData);
+	password = CFDataCreateCopy(kCFAllocatorDefault, data);
 
 	write_item("password",
 		   (const char *)CFDataGetBytePtr(data),
@@ -173,7 +217,14 @@ static OSStatus find_internet_password(void)
 	CFRelease(item);
 
 	write_item("capability[]", "state", strlen("state"));
-	write_item("state[]", "osxkeychain:seen=1", strlen("osxkeychain:seen=1"));
+	{
+		struct strbuf sb;
+
+		strbuf_init(&sb, 1024);
+		encode_state_seen(&sb);
+		write_item("state[]", sb.buf, strlen(sb.buf));
+		strbuf_release(&sb);
+	}
 
 out:
 	CFRelease(attrs);
@@ -288,13 +339,22 @@ static OSStatus add_internet_password(void)
 	CFDictionaryRef attrs;
 	OSStatus result;
 
-	if (state_seen)
-		return errSecSuccess;
-
 	/* Only store complete credentials */
 	if (!protocol || !host || !username || !password)
 		return -1;
 
+	if (state_seen) {
+		struct strbuf sb;
+
+		strbuf_init(&sb, 1024);
+		encode_state_seen(&sb);
+		if (!strcmp(state_seen, sb.buf)) {
+			strbuf_release(&sb);
+			return errSecSuccess;
+		}
+		strbuf_release(&sb);
+	}
+
 	data = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, password);
 	if (password_expiry_utc) {
 		CFDataAppendBytes(data,
@@ -403,8 +463,9 @@ static void read_credential(void)
 							   (UInt8 *)v,
 							   strlen(v));
 		else if (!strcmp(buf, "state[]")) {
-			if (!strcmp(v, "osxkeychain:seen=1"))
-				state_seen = 1;
+			int len = strlen("osxkeychain:seen=");
+			if (!strncmp(v, "osxkeychain:seen=", len))
+				state_seen = xstrdup(v);
 		}
 		/*
 		 * Ignore other lines; we don't know what they mean, but
@@ -443,5 +504,8 @@ int main(int argc, const char **argv)
 
 	clear_credential();
 
+	if (state_seen)
+		free(state_seen);
+
 	return 0;
 }
diff --git a/contrib/credential/osxkeychain/meson.build b/contrib/credential/osxkeychain/meson.build
index 3c7677f..ec91d0c 100644
--- a/contrib/credential/osxkeychain/meson.build
+++ b/contrib/credential/osxkeychain/meson.build
@@ -1,6 +1,7 @@
 executable('git-credential-osxkeychain',
   sources: 'git-credential-osxkeychain.c',
   dependencies: [
+    libgit,
     dependency('CoreFoundation'),
     dependency('Security'),
   ],
diff --git a/contrib/credential/wincred/Makefile b/contrib/credential/wincred/Makefile
index 5b795fc..d92e721 100644
--- a/contrib/credential/wincred/Makefile
+++ b/contrib/credential/wincred/Makefile
@@ -4,20 +4,22 @@
 -include ../../../config.mak.autogen
 -include ../../../config.mak
 
-CC ?= gcc
-RM ?= rm -f
-CFLAGS ?= -O2 -Wall
-
 prefix ?= /usr/local
-libexecdir ?= $(prefix)/libexec/git-core
+gitexecdir ?= $(prefix)/libexec/git-core
 
+CC ?= gcc
+CFLAGS ?= -O2 -Wall
 INSTALL ?= install
+RM ?= rm -f
 
-git-credential-wincred.exe : git-credential-wincred.c
-	$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@
+git-credential-wincred.exe: git-credential-wincred.c
+	$(LINK.c) -o $@ $^ $(LDFLAGS) $(LDLIBS)
 
 install: git-credential-wincred.exe
-	$(INSTALL) -m 755 $^ $(libexecdir)
+	$(INSTALL) -d -m 755 $(DESTDIR)$(gitexecdir)
+	$(INSTALL) -m 755 $< $(DESTDIR)$(gitexecdir)
 
 clean:
 	$(RM) git-credential-wincred.exe
+
+.PHONY: all install clean
diff --git a/contrib/git-jump/git-jump b/contrib/git-jump/git-jump
index 3f69675..8d1d5d7 100755
--- a/contrib/git-jump/git-jump
+++ b/contrib/git-jump/git-jump
@@ -44,7 +44,7 @@
 mode_diff() {
 	git diff --no-prefix --relative "$@" |
 	perl -ne '
-	if (m{^\+\+\+ (.*)}) { $file = $1 eq "/dev/null" ? undef : $1; next }
+	if (m{^\+\+\+ (.*?)\t?$}) { $file = $1 eq "/dev/null" ? undef : $1; next }
 	defined($file) or next;
 	if (m/^@@ .*?\+(\d+)/) { $line = $1; next }
 	defined($line) or next;
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 3fddba7..17106d1 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -785,20 +785,40 @@
 		die "fatal: '$1' does not look like a ref"
 }
 
-# Usage: check if a commit from another subtree should be
+# Usage: should_ignore_subtree_split_commit REV
+#
+# Check if REV is a commit from another subtree and should be
 # ignored from processing for splits
 should_ignore_subtree_split_commit () {
 	assert test $# = 1
-	local rev="$1"
-	if test -n "$(git log -1 --grep="git-subtree-dir:" $rev)"
+
+	git show \
+		--no-patch \
+		--no-show-signature \
+		--format='%(trailers:key=git-subtree-dir,key=git-subtree-mainline)' \
+		"$1" |
+	(
+	have_mainline=
+	subtree_dir=
+
+	while read -r trailer val
+	do
+		case "$trailer" in
+		git-subtree-dir:)
+			subtree_dir="${val%/}" ;;
+		git-subtree-mainline:)
+			have_mainline=y ;;
+		esac
+	done
+
+	if test -n "${subtree_dir}" &&
+		test -z "${have_mainline}" &&
+		test "${subtree_dir}" != "$arg_prefix"
 	then
-		if test -z "$(git log -1 --grep="git-subtree-mainline:" $rev)" &&
-			test -z "$(git log -1 --grep="git-subtree-dir: $arg_prefix$" $rev)"
-		then
-			return 0
-		fi
+		return 0
 	fi
 	return 1
+	)
 }
 
 # Usage: process_split_commit REV PARENTS
diff --git a/contrib/subtree/meson.build b/contrib/subtree/meson.build
index 98dd8e0..161435a 100644
--- a/contrib/subtree/meson.build
+++ b/contrib/subtree/meson.build
@@ -38,7 +38,7 @@
     output: 'git-subtree.xml',
   )
 
-  custom_target(
+  doc_targets += custom_target(
     command: [
       xmlto,
       '-m', '@INPUT@',
@@ -57,7 +57,7 @@
 endif
 
 if get_option('docs').contains('html')
-  custom_target(
+  doc_targets += custom_target(
     command: asciidoc_common_options + [
       '--backend=' + asciidoc_html,
       '--doctype=manpage',
@@ -68,6 +68,6 @@
     input: 'git-subtree.adoc',
     output: 'git-subtree.html',
     install: true,
-    install_dir: get_option('datadir') / 'doc/git-doc',
+    install_dir: htmldir,
   )
 endif
diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index 3edbb33..316dc52 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -9,6 +9,9 @@
 and push subcommands of git subtree.
 '
 
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
 TEST_DIRECTORY=$(pwd)/../../../t
 . "$TEST_DIRECTORY"/test-lib.sh
 . "$TEST_DIRECTORY"/lib-gpg.sh
@@ -68,6 +71,33 @@
 	git -C "$1-clone" replace HEAD^2 $new_commit
 }
 
+# test_create_subtree_add REPO ORPHAN PREFIX FILENAME ...
+#
+# Create a simple subtree on a new branch named ORPHAN in REPO.
+# The subtree is then merged into the current branch of REPO,
+# under PREFIX. The generated subtree has has one commit
+# with subject and tag FILENAME with a single file "FILENAME.t"
+#
+# When this method returns:
+# - the current branch of REPO will have file PREFIX/FILENAME.t
+# - REPO will have a branch named ORPHAN with subtree history
+#
+# additional arguments are forwarded to "subtree add"
+test_create_subtree_add () {
+	(
+		cd "$1" &&
+		orphan="$2" &&
+		prefix="$3" &&
+		filename="$4" &&
+		shift 4 &&
+		last="$(git branch --show-current)" &&
+		git switch --orphan "$orphan" &&
+		test_commit "$filename" &&
+		git checkout "$last" &&
+		git subtree add --prefix="$prefix" "$@" "$orphan"
+	)
+}
+
 test_expect_success 'shows short help text for -h' '
 	test_expect_code 129 git subtree -h >out 2>err &&
 	test_must_be_empty err &&
@@ -426,6 +456,47 @@
 		--squash --rejoin -d -m "Sub B Split 1" 2>&1 | grep -w "\[1\]")" = ""
 '
 
+# When subtree split-ing a directory that has other subtree
+# *merges* underneath it, the split must include those subtrees.
+# This test creates a nested subtree, `subA/subB`, and tests
+# that the tree is correct after a subtree split of `subA/`.
+# The test covers:
+# - An initial `subtree add`; and
+# - A follow-up `subtree merge`
+# both with and without `--squashed`.
+for is_squashed in '' 'y'
+do
+	test_expect_success "split keeps nested ${is_squashed:+--squash }subtrees that are part of the split" '
+		subtree_test_create_repo "$test_count" &&
+		(
+			cd "$test_count" &&
+			mkdir subA &&
+			test_commit subA/file1 &&
+			test_create_subtree_add \
+				. mksubtree subA/subB file2 ${is_squashed:+--squash} &&
+			test_path_is_file subA/file1.t &&
+			test_path_is_file subA/subB/file2.t &&
+			git subtree split --prefix=subA --branch=bsplit &&
+			git checkout bsplit &&
+			test_path_is_file file1.t &&
+			test_path_is_file subB/file2.t &&
+			git checkout mksubtree &&
+			git branch -D bsplit &&
+			test_commit file3 &&
+			git checkout main &&
+			git subtree merge \
+				${is_squashed:+--squash} \
+				--prefix=subA/subB mksubtree &&
+			test_path_is_file subA/subB/file3.t &&
+			git subtree split --prefix=subA --branch=bsplit &&
+			git checkout bsplit &&
+			test_path_is_file file1.t &&
+			test_path_is_file subB/file2.t &&
+			test_path_is_file subB/file3.t
+		)
+	'
+done
+
 test_expect_success 'split sub dir/ with --rejoin from scratch' '
 	subtree_test_create_repo "$test_count" &&
 	test_create_commit "$test_count" main1 &&
diff --git a/delta-islands.c b/delta-islands.c
index 36c9479..7cfebc4 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -390,8 +390,7 @@ static void add_ref_to_island(kh_str_t *remote_islands, const char *island_name,
 	rl->hash += sha_core;
 }
 
-static int find_island_for_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			       int flags UNUSED, void *cb)
+static int find_island_for_ref(const struct reference *ref, void *cb)
 {
 	struct island_load_data *ild = cb;
 
@@ -406,7 +405,7 @@ static int find_island_for_ref(const char *refname, const char *referent UNUSED,
 
 	/* walk backwards to get last-one-wins ordering */
 	for (i = ild->nr - 1; i >= 0; i--) {
-		if (!regexec(&ild->rx[i], refname,
+		if (!regexec(&ild->rx[i], ref->name,
 			     ARRAY_SIZE(matches), matches, 0))
 			break;
 	}
@@ -428,10 +427,10 @@ static int find_island_for_ref(const char *refname, const char *referent UNUSED,
 		if (island_name.len)
 			strbuf_addch(&island_name, '-');
 
-		strbuf_add(&island_name, refname + match->rm_so, match->rm_eo - match->rm_so);
+		strbuf_add(&island_name, ref->name + match->rm_so, match->rm_eo - match->rm_so);
 	}
 
-	add_ref_to_island(ild->remote_islands, island_name.buf, oid);
+	add_ref_to_island(ild->remote_islands, island_name.buf, ref->oid);
 	strbuf_release(&island_name);
 	return 0;
 }
diff --git a/diff-lib.c b/diff-lib.c
index 244468d..b8f8f3b 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -115,6 +115,9 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
 	uint64_t start = getnanotime();
 	struct index_state *istate = revs->diffopt.repo->index;
 
+	if (revs->diffopt.max_depth_valid)
+		die(_("max-depth is not supported for worktree diffs"));
+
 	diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
 
 	refresh_fsmonitor(istate);
@@ -560,6 +563,8 @@ static int diff_cache(struct rev_info *revs,
 	opts.dst_index = NULL;
 	opts.pathspec = &revs->diffopt.pathspec;
 	opts.pathspec->recursive = 1;
+	if (revs->diffopt.max_depth_valid)
+		die(_("max-depth is not supported for index diffs"));
 
 	init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
 	return unpack_trees(1, &t, &opts);
diff --git a/diff.c b/diff.c
index 7b5601d..efa8d97 100644
--- a/diff.c
+++ b/diff.c
@@ -57,7 +57,7 @@ static int diff_detect_rename_default;
 static int diff_indent_heuristic = 1;
 static int diff_rename_limit_default = 1000;
 static int diff_suppress_blank_empty;
-static int diff_use_color_default = -1;
+static enum git_colorbool diff_use_color_default = GIT_COLOR_UNKNOWN;
 static int diff_color_moved_default;
 static int diff_color_moved_ws_default;
 static int diff_context_default = 3;
@@ -327,29 +327,23 @@ static unsigned parse_color_moved_ws(const char *arg)
 	struct string_list l = STRING_LIST_INIT_DUP;
 	struct string_list_item *i;
 
-	string_list_split(&l, arg, ',', -1);
+	string_list_split_f(&l, arg, ",", -1, STRING_LIST_SPLIT_TRIM);
 
 	for_each_string_list_item(i, &l) {
-		struct strbuf sb = STRBUF_INIT;
-		strbuf_addstr(&sb, i->string);
-		strbuf_trim(&sb);
-
-		if (!strcmp(sb.buf, "no"))
+		if (!strcmp(i->string, "no"))
 			ret = 0;
-		else if (!strcmp(sb.buf, "ignore-space-change"))
+		else if (!strcmp(i->string, "ignore-space-change"))
 			ret |= XDF_IGNORE_WHITESPACE_CHANGE;
-		else if (!strcmp(sb.buf, "ignore-space-at-eol"))
+		else if (!strcmp(i->string, "ignore-space-at-eol"))
 			ret |= XDF_IGNORE_WHITESPACE_AT_EOL;
-		else if (!strcmp(sb.buf, "ignore-all-space"))
+		else if (!strcmp(i->string, "ignore-all-space"))
 			ret |= XDF_IGNORE_WHITESPACE;
-		else if (!strcmp(sb.buf, "allow-indentation-change"))
+		else if (!strcmp(i->string, "allow-indentation-change"))
 			ret |= COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE;
 		else {
 			ret |= COLOR_MOVED_WS_ERROR;
-			error(_("unknown color-moved-ws mode '%s', possible values are 'ignore-space-change', 'ignore-space-at-eol', 'ignore-all-space', 'allow-indentation-change'"), sb.buf);
+			error(_("unknown color-moved-ws mode '%s', possible values are 'ignore-space-change', 'ignore-space-at-eol', 'ignore-all-space', 'allow-indentation-change'"), i->string);
 		}
-
-		strbuf_release(&sb);
 	}
 
 	if ((ret & COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE) &&
@@ -1357,6 +1351,9 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
 	int len = eds->len;
 	unsigned flags = eds->flags;
 
+	if (!o->file)
+		return;
+
 	switch (s) {
 	case DIFF_SYMBOL_NO_LF_EOF:
 		context = diff_get_color_opt(o, DIFF_CONTEXT);
@@ -1678,7 +1675,7 @@ static void emit_hunk_header(struct emit_callback *ecbdata,
 	const char *frag = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO);
 	const char *func = diff_get_color(ecbdata->color_diff, DIFF_FUNCINFO);
 	const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
-	const char *reverse = ecbdata->color_diff ? GIT_COLOR_REVERSE : "";
+	const char *reverse = want_color(ecbdata->color_diff) ? GIT_COLOR_REVERSE : "";
 	static const char atat[2] = { '@', '@' };
 	const char *cp, *ep;
 	struct strbuf msgbuf = STRBUF_INIT;
@@ -1832,7 +1829,7 @@ static void emit_rewrite_diff(const char *name_a,
 	size_two = fill_textconv(o->repo, textconv_two, two, &data_two);
 
 	memset(&ecbdata, 0, sizeof(ecbdata));
-	ecbdata.color_diff = want_color(o->use_color);
+	ecbdata.color_diff = o->use_color;
 	ecbdata.ws_rule = whitespace_rule(o->repo->index, name_b);
 	ecbdata.opt = o;
 	if (ecbdata.ws_rule & WS_BLANK_AT_EOF) {
@@ -2309,7 +2306,7 @@ static void free_diff_words_data(struct emit_callback *ecbdata)
 	}
 }
 
-const char *diff_get_color(int diff_use_color, enum color_diff ix)
+const char *diff_get_color(enum git_colorbool diff_use_color, enum color_diff ix)
 {
 	if (want_color(diff_use_color))
 		return diff_colors[ix];
@@ -3738,7 +3735,7 @@ static void builtin_diff(const char *name_a,
 		if (o->flags.suppress_diff_headers)
 			lbl[0] = NULL;
 		ecbdata.label_path = lbl;
-		ecbdata.color_diff = want_color(o->use_color);
+		ecbdata.color_diff = o->use_color;
 		ecbdata.ws_rule = whitespace_rule(o->repo->index, name_b);
 		if (ecbdata.ws_rule & WS_BLANK_AT_EOF)
 			check_blank_at_eof(&mf1, &mf2, &ecbdata);
@@ -3768,9 +3765,9 @@ static void builtin_diff(const char *name_a,
 
 		if (o->word_diff)
 			init_diff_words_data(&ecbdata, o, one, two);
-		if (o->dry_run) {
+		if (!o->file) {
 			/*
-			 * Unlike the !dry_run case, we need to ignore the
+			 * Unlike the normal output case, we need to ignore the
 			 * return value from xdi_diff_outf() here, because
 			 * xdi_diff_outf() takes non-zero return from its
 			 * callback function as a sign of error and returns
@@ -4426,7 +4423,6 @@ static void run_external_diff(const struct external_diff *pgm,
 {
 	struct child_process cmd = CHILD_PROCESS_INIT;
 	struct diff_queue_struct *q = &diff_queued_diff;
-	int quiet = !(o->output_format & DIFF_FORMAT_PATCH);
 	int rc;
 
 	/*
@@ -4435,7 +4431,7 @@ static void run_external_diff(const struct external_diff *pgm,
 	 * external diff program lacks the ability to tell us whether
 	 * it's empty then we consider it non-empty without even asking.
 	 */
-	if (!pgm->trust_exit_code && quiet) {
+	if (!pgm->trust_exit_code && !o->file) {
 		o->found_changes = 1;
 		return;
 	}
@@ -4460,7 +4456,10 @@ static void run_external_diff(const struct external_diff *pgm,
 	diff_free_filespec_data(one);
 	diff_free_filespec_data(two);
 	cmd.use_shell = 1;
-	cmd.no_stdout = quiet;
+	if (!o->file)
+		cmd.no_stdout = 1;
+	else if (o->file != stdout)
+		cmd.out = xdup(fileno(o->file));
 	rc = run_command(&cmd);
 	if (!pgm->trust_exit_code && rc == 0)
 		o->found_changes = 1;
@@ -4503,7 +4502,7 @@ static void fill_metainfo(struct strbuf *msg,
 			  struct diff_options *o,
 			  struct diff_filepair *p,
 			  int *must_show_header,
-			  int use_color)
+			  enum git_colorbool use_color)
 {
 	const char *set = diff_get_color(use_color, DIFF_METAINFO);
 	const char *reset = diff_get_color(use_color, DIFF_RESET);
@@ -4602,7 +4601,7 @@ static void run_diff_cmd(const struct external_diff *pgm,
 		 */
 		fill_metainfo(msg, name, other, one, two, o, p,
 			      &must_show_header,
-			      want_color(o->use_color) && !pgm);
+			      pgm ? GIT_COLOR_NEVER : o->use_color);
 		xfrm_msg = msg->len ? msg->buf : NULL;
 	}
 
@@ -4621,7 +4620,8 @@ static void run_diff_cmd(const struct external_diff *pgm,
 		    p->status == DIFF_STATUS_RENAMED)
 			o->found_changes = 1;
 	} else {
-		fprintf(o->file, "* Unmerged path %s\n", name);
+		if (o->file)
+			fprintf(o->file, "* Unmerged path %s\n", name);
 		o->found_changes = 1;
 	}
 }
@@ -4987,6 +4987,8 @@ void diff_setup_done(struct diff_options *options)
 	if (options->flags.quick) {
 		options->output_format = DIFF_FORMAT_NO_OUTPUT;
 		options->flags.exit_with_status = 1;
+		options->detect_rename = 0;
+		options->flags.find_copies_harder = 0;
 	}
 
 	/*
@@ -5001,8 +5003,7 @@ void diff_setup_done(struct diff_options *options)
 	if (options->flags.follow_renames)
 		diff_check_follow_pathspec(&options->pathspec, 1);
 
-	if (!options->use_color ||
-	    (options->flags.allow_external && external_diff()))
+	if (options->flags.allow_external && external_diff())
 		options->color_moved = 0;
 
 	if (options->filter_not) {
@@ -5010,6 +5011,9 @@ void diff_setup_done(struct diff_options *options)
 			options->filter = ~filter_bit[DIFF_STATUS_FILTER_AON];
 		options->filter &= ~options->filter_not;
 	}
+
+	if (options->pathspec.has_wildcard && options->max_depth_valid)
+		die("max-depth cannot be used with wildcard pathspecs");
 }
 
 int parse_long_opt(const char *opt, const char **argv,
@@ -5281,7 +5285,7 @@ static int diff_opt_color_words(const struct option *opt,
 	struct diff_options *options = opt->value;
 
 	BUG_ON_OPT_NEG(unset);
-	options->use_color = 1;
+	options->use_color = GIT_COLOR_ALWAYS;
 	options->word_diff = DIFF_WORDS_COLOR;
 	options->word_regex = arg;
 	return 0;
@@ -5603,7 +5607,7 @@ static int diff_opt_word_diff(const struct option *opt,
 		if (!strcmp(arg, "plain"))
 			options->word_diff = DIFF_WORDS_PLAIN;
 		else if (!strcmp(arg, "color")) {
-			options->use_color = 1;
+			options->use_color = GIT_COLOR_ALWAYS;
 			options->word_diff = DIFF_WORDS_COLOR;
 		}
 		else if (!strcmp(arg, "porcelain"))
@@ -5644,6 +5648,23 @@ static int diff_opt_rotate_to(const struct option *opt, const char *arg, int uns
 	return 0;
 }
 
+static int diff_opt_max_depth(const struct option *opt,
+			      const char *arg, int unset)
+{
+	struct diff_options *options = opt->value;
+
+	BUG_ON_OPT_NEG(unset);
+
+	if (!git_parse_int(arg, &options->max_depth))
+		return error(_("invalid value for '%s': '%s'"),
+			     "--max-depth", arg);
+
+	options->flags.recursive = 1;
+	options->max_depth_valid = options->max_depth >= 0;
+
+	return 0;
+}
+
 /*
  * Consider adding new flags to __git_diff_common_options
  * in contrib/completion/git-completion.bash
@@ -5916,6 +5937,10 @@ struct option *add_diff_options(const struct option *opts,
 		OPT_CALLBACK_F(0, "diff-filter", options, N_("[(A|C|D|M|R|T|U|X|B)...[*]]"),
 			       N_("select files by diff type"),
 			       PARSE_OPT_NONEG, diff_opt_diff_filter),
+		OPT_CALLBACK_F(0, "max-depth", options, N_("<depth>"),
+			       N_("maximum tree depth to recurse"),
+			       PARSE_OPT_NONEG, diff_opt_max_depth),
+
 		{
 			.type = OPTION_CALLBACK,
 			.long_name = "output",
@@ -6175,15 +6200,15 @@ static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
 /* return 1 if any change is found; otherwise, return 0 */
 static int diff_flush_patch_quietly(struct diff_filepair *p, struct diff_options *o)
 {
-	int saved_dry_run = o->dry_run;
+	FILE *saved_file = o->file;
 	int saved_found_changes = o->found_changes;
 	int ret;
 
-	o->dry_run = 1;
+	o->file = NULL;
 	o->found_changes = 0;
 	diff_flush_patch(p, o);
 	ret = o->found_changes;
-	o->dry_run = saved_dry_run;
+	o->file = saved_file;
 	o->found_changes |= saved_found_changes;
 	return ret;
 }
@@ -6715,7 +6740,7 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
 	if (WSEH_NEW & WS_RULE_MASK)
 		BUG("WS rules bit mask overlaps with diff symbol flags");
 
-	if (o->color_moved)
+	if (o->color_moved && want_color(o->use_color))
 		o->emitted_symbols = &esm;
 
 	if (o->additional_path_headers)
@@ -6728,20 +6753,17 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
 	}
 
 	if (o->emitted_symbols) {
-		if (o->color_moved) {
-			struct mem_pool entry_pool;
-			struct moved_entry_list *entry_list;
+		struct mem_pool entry_pool;
+		struct moved_entry_list *entry_list;
 
-			mem_pool_init(&entry_pool, 1024 * 1024);
-			entry_list = add_lines_to_move_detection(o,
-								 &entry_pool);
-			mark_color_as_moved(o, entry_list);
-			if (o->color_moved == COLOR_MOVED_ZEBRA_DIM)
-				dim_moved_lines(o);
+		mem_pool_init(&entry_pool, 1024 * 1024);
+		entry_list = add_lines_to_move_detection(o, &entry_pool);
+		mark_color_as_moved(o, entry_list);
+		if (o->color_moved == COLOR_MOVED_ZEBRA_DIM)
+			dim_moved_lines(o);
 
-			mem_pool_discard(&entry_pool, 0);
-			free(entry_list);
-		}
+		mem_pool_discard(&entry_pool, 0);
+		free(entry_list);
 
 		for (i = 0; i < esm.nr; i++)
 			emit_diff_symbol_from_struct(o, &esm.buf[i]);
@@ -6814,38 +6836,18 @@ void diff_flush(struct diff_options *options)
 			     DIFF_FORMAT_NAME |
 			     DIFF_FORMAT_NAME_STATUS |
 			     DIFF_FORMAT_CHECKDIFF)) {
-		/*
-		 * make sure diff_Flush_patch_quietly() to be silent.
-		 */
-		FILE *dev_null = NULL;
-		int saved_color_moved = options->color_moved;
-
-		if (options->flags.diff_from_contents) {
-			dev_null = xfopen("/dev/null", "w");
-			options->color_moved = 0;
-		}
 		for (i = 0; i < q->nr; i++) {
 			struct diff_filepair *p = q->queue[i];
 
 			if (!check_pair_status(p))
 				continue;
 
-			if (options->flags.diff_from_contents) {
-				FILE *saved_file = options->file;
-				int found_changes;
+			if (options->flags.diff_from_contents &&
+			    !diff_flush_patch_quietly(p, options))
+				continue;
 
-				options->file = dev_null;
-				found_changes = diff_flush_patch_quietly(p, options);
-				options->file = saved_file;
-				if (!found_changes)
-					continue;
-			}
 			flush_one_pair(p, options);
 		}
-		if (options->flags.diff_from_contents) {
-			fclose(dev_null);
-			options->color_moved = saved_color_moved;
-		}
 		separator++;
 	}
 
@@ -6896,15 +6898,6 @@ void diff_flush(struct diff_options *options)
 	if (output_format & DIFF_FORMAT_NO_OUTPUT &&
 	    options->flags.exit_with_status &&
 	    options->flags.diff_from_contents) {
-		/*
-		 * run diff_flush_patch for the exit status. setting
-		 * options->file to /dev/null should be safe, because we
-		 * aren't supposed to produce any output anyway.
-		 */
-		diff_free_file(options);
-		options->file = xfopen("/dev/null", "w");
-		options->close_file = 1;
-		options->color_moved = 0;
 		for (i = 0; i < q->nr; i++) {
 			struct diff_filepair *p = q->queue[i];
 			if (check_pair_status(p))
diff --git a/diff.h b/diff.h
index 91b3e1c..31eedd5 100644
--- a/diff.h
+++ b/diff.h
@@ -7,6 +7,7 @@
 #include "hash.h"
 #include "pathspec.h"
 #include "strbuf.h"
+#include "color.h"
 
 struct oidset;
 
@@ -126,6 +127,13 @@ struct diff_flags {
 	unsigned recursive;
 	unsigned tree_in_recursive;
 
+	/*
+	 * Historically diff_tree_combined() overrides recursive to 1. To
+	 * suppress this behavior, set the flag below.
+	 * It has no effect if recursive is already set to 1.
+	 */
+	unsigned no_recursive_diff_tree_combined;
+
 	/* Affects the way how a file that is seemingly binary is treated. */
 	unsigned binary;
 	unsigned text;
@@ -283,7 +291,7 @@ struct diff_options {
 	/* diff-filter bits */
 	unsigned int filter, filter_not;
 
-	int use_color;
+	enum git_colorbool use_color;
 
 	/* Number of context lines to generate in patch output. */
 	int context;
@@ -400,12 +408,18 @@ struct diff_options {
 	#define COLOR_MOVED_WS_ERROR (1<<0)
 	unsigned color_moved_ws_handling;
 
-	bool dry_run;
-
 	struct repository *repo;
 	struct strmap *additional_path_headers;
 
 	int no_free;
+
+	/*
+	 * The value '0' is a valid max-depth (for no recursion), and value '-1'
+	 * also (for unlimited recursion), so the extra "valid" flag is used to
+	 * determined whether the user specified option --max-depth.
+	 */
+	int max_depth;
+	int max_depth_valid;
 };
 
 unsigned diff_filter_bit(char status);
@@ -461,7 +475,7 @@ enum color_diff {
 	DIFF_FILE_NEW_BOLD = 22,
 };
 
-const char *diff_get_color(int diff_use_color, enum color_diff ix);
+const char *diff_get_color(enum git_colorbool diff_use_color, enum color_diff ix);
 #define diff_get_color_opt(o, ix) \
 	diff_get_color((o)->use_color, ix)
 
diff --git a/dir.c b/dir.c
index dfb4d40..b00821f 100644
--- a/dir.c
+++ b/dir.c
@@ -30,6 +30,7 @@
 #include "read-cache-ll.h"
 #include "setup.h"
 #include "sparse-index.h"
+#include "strbuf.h"
 #include "submodule-config.h"
 #include "symlinks.h"
 #include "trace2.h"
@@ -87,6 +88,33 @@ struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp)
 	return e;
 }
 
+int for_each_file_in_dir(struct strbuf *path, file_iterator fn, const void *data)
+{
+	struct dirent *e;
+	int res = 0;
+	size_t baselen = path->len;
+	DIR *dir = opendir(path->buf);
+
+	if (!dir)
+		return 0;
+
+	while (!res && (e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
+		unsigned char dtype = get_dtype(e, path, 0);
+		strbuf_setlen(path, baselen);
+		strbuf_addstr(path, e->d_name);
+
+		if (dtype == DT_REG) {
+			res = fn(path->buf, data);
+		} else if (dtype == DT_DIR) {
+			strbuf_addch(path, '/');
+			res = for_each_file_in_dir(path, fn, data);
+		}
+	}
+
+	closedir(dir);
+	return res;
+}
+
 int count_slashes(const char *s)
 {
 	int cnt = 0;
@@ -277,7 +305,7 @@ int within_depth(const char *name, int namelen,
 		if (depth > max_depth)
 			return 0;
 	}
-	return 1;
+	return depth <= max_depth;
 }
 
 /*
@@ -1360,18 +1388,25 @@ int match_pathname(const char *pathname, int pathlen,
 
 		if (fspathncmp(pattern, name, prefix))
 			return 0;
-		pattern += prefix;
-		patternlen -= prefix;
-		name    += prefix;
-		namelen -= prefix;
 
 		/*
 		 * If the whole pattern did not have a wildcard,
 		 * then our prefix match is all we need; we
 		 * do not need to call fnmatch at all.
 		 */
-		if (!patternlen && !namelen)
+		if (patternlen == prefix && namelen == prefix)
 			return 1;
+
+		/*
+		 * Retain one character of the prefix to
+		 * pass to fnmatch, which lets it distinguish
+		 * the start of a directory component correctly.
+		 */
+		prefix--;
+		pattern += prefix;
+		patternlen -= prefix;
+		name    += prefix;
+		namelen -= prefix;
 	}
 
 	return fnmatch_icase_mem(pattern, patternlen,
@@ -3579,7 +3614,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,
 	struct stat_data stat_data;
 	struct strbuf *out = &wd->out;
 	unsigned char intbuf[16];
-	unsigned int intlen, value;
+	unsigned int value;
+	uint8_t intlen;
 	int i = wd->index++;
 
 	/*
@@ -3632,7 +3668,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra
 	struct ondisk_untracked_cache *ouc;
 	struct write_data wd;
 	unsigned char varbuf[16];
-	int varint_len;
+	uint8_t varint_len;
 	const unsigned hashsz = the_hash_algo->rawsz;
 
 	CALLOC_ARRAY(ouc, 1);
@@ -3738,7 +3774,7 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,
 	struct untracked_cache_dir ud, *untracked;
 	const unsigned char *data = rd->data, *end = rd->end;
 	const unsigned char *eos;
-	unsigned int value;
+	uint64_t value;
 	int i;
 
 	memset(&ud, 0, sizeof(ud));
@@ -3830,7 +3866,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
 	struct read_data rd;
 	const unsigned char *next = data, *end = (const unsigned char *)data + sz;
 	const char *ident;
-	int ident_len;
+	uint64_t ident_len;
+	uint64_t varint_len;
 	ssize_t len;
 	const char *exclude_per_dir;
 	const unsigned hashsz = the_hash_algo->rawsz;
@@ -3867,8 +3904,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
 	if (next >= end)
 		goto done2;
 
-	len = decode_varint(&next);
-	if (next > end || len == 0)
+	varint_len = decode_varint(&next);
+	if (next > end || varint_len == 0)
 		goto done2;
 
 	rd.valid      = ewah_new();
@@ -3877,9 +3914,9 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
 	rd.data	      = next;
 	rd.end	      = end;
 	rd.index      = 0;
-	ALLOC_ARRAY(rd.ucd, len);
+	ALLOC_ARRAY(rd.ucd, varint_len);
 
-	if (read_one_dir(&uc->root, &rd) || rd.index != len)
+	if (read_one_dir(&uc->root, &rd) || rd.index != varint_len)
 		goto done;
 
 	next = rd.data;
diff --git a/dir.h b/dir.h
index fc9be7b..20d4a07 100644
--- a/dir.h
+++ b/dir.h
@@ -537,6 +537,20 @@ int get_sparse_checkout_patterns(struct pattern_list *pl);
 int remove_dir_recursively(struct strbuf *path, int flag);
 
 /*
+ * This function pointer type is called on each file discovered in
+ * for_each_file_in_dir. The iteration stops if this method returns
+ * non-zero.
+ */
+typedef int (*file_iterator)(const char *path, const void *data);
+
+struct strbuf;
+/*
+ * Given a directory path, recursively visit each file within, including
+ * within subdirectories.
+ */
+int for_each_file_in_dir(struct strbuf *path, file_iterator fn, const void *data);
+
+/*
  * Tries to remove the path, along with leading empty directories so long as
  * those empty directories are not startup_info->original_cwd.  Ignores
  * ENOENT.
diff --git a/environment.c b/environment.c
index ae1427b..a770b59 100644
--- a/environment.c
+++ b/environment.c
@@ -78,7 +78,6 @@ int grafts_keep_true_parents;
 int core_apply_sparse_checkout;
 int core_sparse_checkout_cone;
 int sparse_expect_files_outside_of_patterns;
-int merge_log_config = -1;
 int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 unsigned long pack_size_limit_cfg;
 int max_allowed_tree_depth =
@@ -122,7 +121,10 @@ int protect_ntfs = PROTECT_NTFS_DEFAULT;
  */
 const char *comment_line_str = "#";
 char *comment_line_str_to_free;
+#ifndef WITH_BREAKING_CHANGES
 int auto_comment_line_char;
+bool warn_on_auto_comment_char;
+#endif /* !WITH_BREAKING_CHANGES */
 
 /* This is set by setup_git_directory_gently() and/or git_default_config() */
 char *git_work_tree_cfg;
@@ -175,10 +177,10 @@ int have_git_dir(void)
 const char *get_git_namespace(void)
 {
 	static const char *namespace;
-
 	struct strbuf buf = STRBUF_INIT;
-	struct strbuf **components, **c;
 	const char *raw_namespace;
+	struct string_list components = STRING_LIST_INIT_DUP;
+	struct string_list_item *item;
 
 	if (namespace)
 		return namespace;
@@ -190,12 +192,17 @@ const char *get_git_namespace(void)
 	}
 
 	strbuf_addstr(&buf, raw_namespace);
-	components = strbuf_split(&buf, '/');
+
+	string_list_split(&components, buf.buf, "/", -1);
 	strbuf_reset(&buf);
-	for (c = components; *c; c++)
-		if (strcmp((*c)->buf, "/") != 0)
-			strbuf_addf(&buf, "refs/namespaces/%s", (*c)->buf);
-	strbuf_list_free(components);
+
+	for_each_string_list_item(item, &components) {
+		if (item->string[0])
+			strbuf_addf(&buf, "refs/namespaces/%s/", item->string);
+	}
+	string_list_clear(&components, 0);
+
+	strbuf_trim_trailing_dir_sep(&buf);
 	if (check_refname_format(buf.buf, 0))
 		die(_("bad git namespace path \"%s\""), raw_namespace);
 	strbuf_addch(&buf, '/');
@@ -459,16 +466,22 @@ static int git_default_core_config(const char *var, const char *value,
 
 	if (!strcmp(var, "core.commentchar") ||
 	    !strcmp(var, "core.commentstring")) {
-		if (!value)
+		if (!value) {
 			return config_error_nonbool(var);
-		else if (!strcasecmp(value, "auto"))
+#ifndef WITH_BREAKING_CHANGES
+		} else if (!strcasecmp(value, "auto")) {
 			auto_comment_line_char = 1;
-		else if (value[0]) {
+			FREE_AND_NULL(comment_line_str_to_free);
+			comment_line_str = "#";
+#endif /* !WITH_BREAKING_CHANGES */
+		} else if (value[0]) {
 			if (strchr(value, '\n'))
 				return error(_("%s cannot contain newline"), var);
 			comment_line_str = value;
 			FREE_AND_NULL(comment_line_str_to_free);
+#ifndef WITH_BREAKING_CHANGES
 			auto_comment_line_char = 0;
+#endif /* !WITH_BREAKING_CHANGES */
 		} else
 			return error(_("%s must have at least one character"), var);
 		return 0;
diff --git a/environment.h b/environment.h
index 8cfce41..51898c9 100644
--- a/environment.h
+++ b/environment.h
@@ -208,7 +208,10 @@ extern char *excludes_file;
  */
 extern const char *comment_line_str;
 extern char *comment_line_str_to_free;
+#ifndef WITH_BREAKING_CHANGES
 extern int auto_comment_line_char;
+extern bool warn_on_auto_comment_char;
+#endif /* !WITH_BREAKING_CHANGES */
 
 # endif /* USE_THE_REPOSITORY_VARIABLE */
 #endif /* ENVIRONMENT_H */
diff --git a/fetch-pack.c b/fetch-pack.c
index a9f5e6b..78c45d4 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -188,13 +188,9 @@ static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
 	return 0;
 }
 
-static int rev_list_insert_ref_oid(const char *refname UNUSED,
-				   const char *referent UNUSED,
-				   const struct object_id *oid,
-				   int flag UNUSED,
-				   void *cb_data)
+static int rev_list_insert_ref_oid(const struct reference *ref, void *cb_data)
 {
-	return rev_list_insert_ref(cb_data, oid);
+	return rev_list_insert_ref(cb_data, ref->oid);
 }
 
 enum ack_type {
@@ -616,13 +612,9 @@ static int mark_complete(const struct object_id *oid)
 	return 0;
 }
 
-static int mark_complete_oid(const char *refname UNUSED,
-			     const char *referent UNUSED,
-			     const struct object_id *oid,
-			     int flag UNUSED,
-			     void *cb_data UNUSED)
+static int mark_complete_oid(const struct reference *ref, void *cb_data UNUSED)
 {
-	return mark_complete(oid);
+	return mark_complete(ref->oid);
 }
 
 static void mark_recent_complete_commits(struct fetch_pack_args *args,
@@ -1915,7 +1907,7 @@ static void fetch_pack_config(void)
 		char *str;
 
 		if (!repo_config_get_string(the_repository, "fetch.uriprotocols", &str) && str) {
-			string_list_split(&uri_protocols, str, ',', -1);
+			string_list_split(&uri_protocols, str, ",", -1);
 			free(str);
 		}
 	}
@@ -1983,7 +1975,7 @@ static void update_shallow(struct fetch_pack_args *args,
 		 * remote is shallow, but this is a clone, there are
 		 * no objects in repo to worry about. Accept any
 		 * shallow points that exist in the pack (iow in repo
-		 * after get_pack() and reprepare_packed_git())
+		 * after get_pack() and odb_reprepare())
 		 */
 		struct oid_array extra = OID_ARRAY_INIT;
 		struct object_id *oid = si->shallow->oid;
@@ -2108,7 +2100,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
 		ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
 					&si, pack_lockfiles);
 	}
-	reprepare_packed_git(the_repository);
+	odb_reprepare(the_repository->objects);
 
 	if (!args->cloning && args->deepen) {
 		struct check_connected_options opt = CHECK_CONNECTED_INIT;
diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
index 40174ef..c9085ed 100644
--- a/fmt-merge-msg.c
+++ b/fmt-merge-msg.c
@@ -26,13 +26,15 @@ static struct string_list suppress_dest_patterns = STRING_LIST_INIT_DUP;
 int fmt_merge_msg_config(const char *key, const char *value,
 			 const struct config_context *ctx, void *cb)
 {
+	int *merge_log_config = cb;
+
 	if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) {
 		int is_bool;
-		merge_log_config = git_config_bool_or_int(key, value, ctx->kvi, &is_bool);
-		if (!is_bool && merge_log_config < 0)
+		*merge_log_config = git_config_bool_or_int(key, value, ctx->kvi, &is_bool);
+		if (!is_bool && *merge_log_config < 0)
 			return error("%s: negative length %s", key, value);
-		if (is_bool && merge_log_config)
-			merge_log_config = DEFAULT_MERGE_LOG_LEN;
+		if (is_bool && *merge_log_config)
+			*merge_log_config = DEFAULT_MERGE_LOG_LEN;
 	} else if (!strcmp(key, "merge.branchdesc")) {
 		use_branch_desc = git_config_bool(key, value);
 	} else if (!strcmp(key, "merge.suppressdest")) {
diff --git a/fmt-merge-msg.h b/fmt-merge-msg.h
index 73ca3e4..c066d83 100644
--- a/fmt-merge-msg.h
+++ b/fmt-merge-msg.h
@@ -12,7 +12,6 @@ struct fmt_merge_msg_opts {
 	const char *into_name;
 };
 
-extern int merge_log_config;
 int fmt_merge_msg_config(const char *key, const char *value,
 			 const struct config_context *ctx, void *cb);
 int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
diff --git a/for-each-ref.h b/for-each-ref.h
new file mode 100644
index 0000000..c8d0219
--- /dev/null
+++ b/for-each-ref.h
@@ -0,0 +1,26 @@
+#ifndef FOR_EACH_REF_H
+#define FOR_EACH_REF_H
+
+struct repository;
+
+/*
+ * Shared usage string for options common to git-for-each-ref(1)
+ * and git-refs-list(1). The command-specific part (e.g., "git refs list ")
+ * must be prepended by the caller.
+ */
+#define COMMON_USAGE_FOR_EACH_REF \
+	"[--count=<count>] [--shell|--perl|--python|--tcl]\n" \
+	"                         [(--sort=<key>)...] [--format=<format>]\n" \
+	"                         [--include-root-refs] [--points-at=<object>]\n" \
+	"                         [--merged[=<object>]] [--no-merged[=<object>]]\n" \
+	"                         [--contains[=<object>]] [--no-contains[=<object>]]\n" \
+	"                         [(--exclude=<pattern>)...] [--start-after=<marker>]\n" \
+	"                         [ --stdin | (<pattern>...)]"
+
+/*
+ * The core logic for for-each-ref and its clones.
+ */
+int for_each_ref_core(int argc, const char **argv, const char *prefix,
+		      struct repository *repo, const char *const *usage);
+
+#endif /* FOR_EACH_REF_H */
diff --git a/fsck.c b/fsck.c
index 171b424..341e100 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1067,6 +1067,24 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
 	else
 		ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
 
+	if (buffer < buffer_end && (skip_prefix(buffer, "gpgsig ", &buffer) || skip_prefix(buffer, "gpgsig-sha256 ", &buffer))) {
+		eol = memchr(buffer, '\n', buffer_end - buffer);
+		if (!eol) {
+			ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_GPGSIG, "invalid format - unexpected end after 'gpgsig' or 'gpgsig-sha256' line");
+			goto done;
+		}
+		buffer = eol + 1;
+
+		while (buffer < buffer_end && starts_with(buffer, " ")) {
+			eol = memchr(buffer, '\n', buffer_end - buffer);
+			if (!eol) {
+				ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_HEADER_CONTINUATION, "invalid format - unexpected end in 'gpgsig' or 'gpgsig-sha256' continuation line");
+				goto done;
+			}
+			buffer = eol + 1;
+		}
+	}
+
 	if (buffer < buffer_end && !starts_with(buffer, "\n")) {
 		/*
 		 * The verify_headers() check will allow
diff --git a/fsck.h b/fsck.h
index dd7df3d..cb6ef32 100644
--- a/fsck.h
+++ b/fsck.h
@@ -25,23 +25,37 @@ enum fsck_msg_type {
 	FUNC(NUL_IN_HEADER, FATAL) \
 	FUNC(UNTERMINATED_HEADER, FATAL) \
 	/* errors */ \
+	FUNC(BAD_HEADER_CONTINUATION, ERROR) \
 	FUNC(BAD_DATE, ERROR) \
 	FUNC(BAD_DATE_OVERFLOW, ERROR) \
 	FUNC(BAD_EMAIL, ERROR) \
+	FUNC(BAD_GPGSIG, ERROR) \
 	FUNC(BAD_NAME, ERROR) \
 	FUNC(BAD_OBJECT_SHA1, ERROR) \
 	FUNC(BAD_PACKED_REF_ENTRY, ERROR) \
 	FUNC(BAD_PACKED_REF_HEADER, ERROR) \
 	FUNC(BAD_PARENT_SHA1, ERROR) \
+	FUNC(BAD_REFERENT_NAME, ERROR) \
 	FUNC(BAD_REF_CONTENT, ERROR) \
 	FUNC(BAD_REF_FILETYPE, ERROR) \
 	FUNC(BAD_REF_NAME, ERROR) \
-	FUNC(BAD_REFERENT_NAME, ERROR) \
 	FUNC(BAD_TIMEZONE, ERROR) \
 	FUNC(BAD_TREE, ERROR) \
 	FUNC(BAD_TREE_SHA1, ERROR) \
 	FUNC(BAD_TYPE, ERROR) \
 	FUNC(DUPLICATE_ENTRIES, ERROR) \
+	FUNC(GITATTRIBUTES_BLOB, ERROR) \
+	FUNC(GITATTRIBUTES_LARGE, ERROR) \
+	FUNC(GITATTRIBUTES_LINE_LENGTH, ERROR) \
+	FUNC(GITATTRIBUTES_MISSING, ERROR) \
+	FUNC(GITMODULES_BLOB, ERROR) \
+	FUNC(GITMODULES_LARGE, ERROR) \
+	FUNC(GITMODULES_MISSING, ERROR) \
+	FUNC(GITMODULES_NAME, ERROR) \
+	FUNC(GITMODULES_PATH, ERROR) \
+	FUNC(GITMODULES_SYMLINK, ERROR) \
+	FUNC(GITMODULES_UPDATE, ERROR) \
+	FUNC(GITMODULES_URL, ERROR) \
 	FUNC(MISSING_AUTHOR, ERROR) \
 	FUNC(MISSING_COMMITTER, ERROR) \
 	FUNC(MISSING_EMAIL, ERROR) \
@@ -60,39 +74,28 @@ enum fsck_msg_type {
 	FUNC(TREE_NOT_SORTED, ERROR) \
 	FUNC(UNKNOWN_TYPE, ERROR) \
 	FUNC(ZERO_PADDED_DATE, ERROR) \
-	FUNC(GITMODULES_MISSING, ERROR) \
-	FUNC(GITMODULES_BLOB, ERROR) \
-	FUNC(GITMODULES_LARGE, ERROR) \
-	FUNC(GITMODULES_NAME, ERROR) \
-	FUNC(GITMODULES_SYMLINK, ERROR) \
-	FUNC(GITMODULES_URL, ERROR) \
-	FUNC(GITMODULES_PATH, ERROR) \
-	FUNC(GITMODULES_UPDATE, ERROR) \
-	FUNC(GITATTRIBUTES_MISSING, ERROR) \
-	FUNC(GITATTRIBUTES_LARGE, ERROR) \
-	FUNC(GITATTRIBUTES_LINE_LENGTH, ERROR) \
-	FUNC(GITATTRIBUTES_BLOB, ERROR) \
 	/* warnings */ \
+	FUNC(BAD_REFTABLE_TABLE_NAME, WARN) \
 	FUNC(EMPTY_NAME, WARN) \
 	FUNC(FULL_PATHNAME, WARN) \
 	FUNC(HAS_DOT, WARN) \
 	FUNC(HAS_DOTDOT, WARN) \
 	FUNC(HAS_DOTGIT, WARN) \
-	FUNC(NULL_SHA1, WARN) \
-	FUNC(ZERO_PADDED_FILEMODE, WARN) \
-	FUNC(NUL_IN_COMMIT, WARN) \
 	FUNC(LARGE_PATHNAME, WARN) \
+	FUNC(NULL_SHA1, WARN) \
+	FUNC(NUL_IN_COMMIT, WARN) \
+	FUNC(ZERO_PADDED_FILEMODE, WARN) \
 	/* infos (reported as warnings, but ignored by default) */ \
 	FUNC(BAD_FILEMODE, INFO) \
-	FUNC(EMPTY_PACKED_REFS_FILE, INFO) \
-	FUNC(GITMODULES_PARSE, INFO) \
-	FUNC(GITIGNORE_SYMLINK, INFO) \
-	FUNC(GITATTRIBUTES_SYMLINK, INFO) \
-	FUNC(MAILMAP_SYMLINK, INFO) \
 	FUNC(BAD_TAG_NAME, INFO) \
+	FUNC(EMPTY_PACKED_REFS_FILE, INFO) \
+	FUNC(GITATTRIBUTES_SYMLINK, INFO) \
+	FUNC(GITIGNORE_SYMLINK, INFO) \
+	FUNC(GITMODULES_PARSE, INFO) \
+	FUNC(MAILMAP_SYMLINK, INFO) \
 	FUNC(MISSING_TAGGER_ENTRY, INFO) \
-	FUNC(SYMLINK_REF, INFO) \
 	FUNC(REF_MISSING_NEWLINE, INFO) \
+	FUNC(SYMLINK_REF, INFO) \
 	FUNC(SYMREF_TARGET_IS_NOT_A_REF, INFO) \
 	FUNC(TRAILING_REF_CONTENT, INFO) \
 	/* ignored (elevated when requested) */ \
diff --git a/generate-perl.sh b/generate-perl.sh
index 65f122e..796d835 100755
--- a/generate-perl.sh
+++ b/generate-perl.sh
@@ -30,7 +30,7 @@
     "$INPUT" >"$OUTPUT"
 
 case "$INPUT" in
-*.perl)
+*.perl|*git-contacts)
 	chmod a+x "$OUTPUT";;
 *)
 	;;
diff --git a/git-gui/Makefile b/git-gui/Makefile
index 27bbe05..69b0b84 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -186,6 +186,7 @@
 	$(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1)
 	$(QUIET)$(INSTALL_X0)git-gui $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 	$(QUIET)$(INSTALL_X0)git-gui--askpass $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
+	$(QUIET)$(INSTALL_X0)git-gui--askyesno $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 	$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(INSTALL_L0)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L1)'$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' $(INSTALL_L2)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L3) &&) true
 ifdef GITGUI_WINDOWS_WRAPPER
 	$(QUIET)$(INSTALL_R0)git-gui.tcl $(INSTALL_R1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
@@ -200,6 +201,7 @@
 	$(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui $(REMOVE_F1)
 	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui--askpass $(REMOVE_F1)
+	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui--askyesno $(REMOVE_F1)
 	$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/$p $(REMOVE_F1) &&) true
 ifdef GITGUI_WINDOWS_WRAPPER
 	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui.tcl $(REMOVE_F1)
diff --git a/git-gui/git-gui--askyesno b/git-gui/git-gui--askyesno
new file mode 100755
index 0000000..142d1bc
--- /dev/null
+++ b/git-gui/git-gui--askyesno
@@ -0,0 +1,63 @@
+#!/bin/sh
+# Tcl ignores the next line -*- tcl -*- \
+exec wish "$0" -- "$@"
+
+# This is an implementation of a simple yes no dialog
+# which is injected into the git commandline by git gui
+# in case a yesno question needs to be answered.
+#
+# The window title, which defaults to "Question?", can be
+# overridden via the optional `--title` command-line
+# option.
+
+set NS {}
+set use_ttk [package vsatisfies [package provide Tk] 8.5]
+if {$use_ttk} {
+	set NS ttk
+}
+
+set title "Question?"
+if {$argc < 1} {
+	puts stderr "Usage: $argv0 <question>"
+	exit 1
+} else {
+	if {$argc > 2 && [lindex $argv 0] == "--title"} {
+		set title [lindex $argv 1]
+		set argv [lreplace $argv 0 1]
+	}
+	set prompt [join $argv " "]
+}
+
+${NS}::frame .t
+${NS}::label .t.m -text $prompt -justify center -width 40
+.t.m configure -wraplength 400
+pack .t.m -side top -fill x -padx 20 -pady 20 -expand 1
+pack .t -side top -fill x -ipadx 20 -ipady 20 -expand 1
+
+${NS}::frame .b
+${NS}::frame .b.left -width 200
+${NS}::button .b.yes -text Yes -command {exit 0}
+${NS}::button .b.no  -text No  -command {exit 1}
+
+pack .b.left -side left -expand 1 -fill x
+pack .b.yes -side left -expand 1
+pack .b.no -side right -expand 1 -ipadx 5
+pack .b -side bottom -fill x -ipadx 20 -ipady 15
+
+bind . <Key-Return> {exit 0}
+bind . <Key-Escape> {exit 1}
+
+if {$::tcl_platform(platform) eq {windows}} {
+	set icopath [file dirname [file normalize $argv0]]
+	if {[file tail $icopath] eq {git-core}} {
+		set icopath [file dirname $icopath]
+	}
+	set icopath [file dirname $icopath]
+	set icopath [file join $icopath share git git-for-windows.ico]
+	if {[file exists $icopath]} {
+		wm iconbitmap . -default $icopath
+	}
+}
+
+wm title . $title
+tk::PlaceWindow .
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index a931d7f..d3d3aa1 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -103,7 +103,6 @@
 	set _path_sep {:}
 }
 
-set _search_path {}
 set _path_seen [dict create]
 foreach p [split $env(PATH) $_path_sep] {
 	# Keep only absolute paths, getting rid of ., empty, etc.
@@ -112,12 +111,9 @@
 	}
 	# Keep only the first occurence of any duplicates.
 	set norm_p [file normalize $p]
-	if {[dict exists $_path_seen $norm_p]} {
-		continue
-	}
 	dict set _path_seen $norm_p 1
-	lappend _search_path $norm_p
 }
+set _search_path [dict keys $_path_seen]
 unset _path_seen
 
 set env(PATH) [join $_search_path $_path_sep]
@@ -583,21 +579,6 @@
 	return [open |$run r]
 }
 
-proc _lappend_nice {cmd_var} {
-	global _nice
-	upvar $cmd_var cmd
-
-	if {![info exists _nice]} {
-		set _nice [_which nice]
-		if {[catch {safe_exec [list $_nice git version]}]} {
-			set _nice {}
-		}
-	}
-	if {$_nice ne {}} {
-		lappend cmd $_nice
-	}
-}
-
 proc git {args} {
 	git_redir $args {}
 }
@@ -631,15 +612,14 @@
 	return [safe_open_command $cmdp $redir]
 }
 
+set _nice [list [_which nice]]
+if {[catch {safe_exec [list {*}$_nice git version]}]} {
+	set _nice {}
+}
+
 proc git_read_nice {cmd} {
-	global _git
-	set opt [list]
-
-	_lappend_nice opt
-
-	set cmdp [concat [list $_git] $cmd]
-
-	return [safe_open_command [concat $opt $cmdp]]
+	set cmdp [list {*}$::_nice $::_git {*}$cmd]
+	return [safe_open_command $cmdp]
 }
 
 proc git_write {cmd} {
@@ -1130,6 +1110,12 @@
 if {![info exists env(SSH_ASKPASS)]} {
 	set env(SSH_ASKPASS) [file join $argv0dir git-gui--askpass]
 }
+if {![info exists env(GIT_ASKPASS)]} {
+	set env(GIT_ASKPASS) [file join $argv0dir git-gui--askpass]
+}
+if {![info exists env(GIT_ASK_YESNO)]} {
+	set env(GIT_ASK_YESNO) [file join $argv0dir git-gui--askyesno]
+}
 unset argv0dir
 
 ######################################################################
diff --git a/git-gui/lib/index.tcl b/git-gui/lib/index.tcl
index 7aa09c7..e1d38e5 100644
--- a/git-gui/lib/index.tcl
+++ b/git-gui/lib/index.tcl
@@ -425,6 +425,11 @@
 
 	if {![lock_index begin-update]} return
 
+	# Workaround for Tcl < 9.0: chord namespaces are not obeyed and
+	# operated in the global namespace. This clears an error that could
+	# have been left over from a previous operation.
+	set ::err {}
+
 	# Common "after" functionality that waits until multiple asynchronous
 	# operations are complete (by waiting for them to activate their notes
 	# on the chord).
@@ -432,7 +437,7 @@
 	# The asynchronous operations are each indicated below by a comment
 	# before the code block that starts the async operation.
 	set after_chord [SimpleChord::new {
-		if {[string trim $err] != ""} {
+		if {[info exists err] && [string trim $err] ne ""} {
 			rescan_on_error $err
 		} else {
 			unlock_index
diff --git a/git-send-email.perl b/git-send-email.perl
index 437f8ac..cd4b316 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -62,7 +62,7 @@
     --smtp-user             <str>  * Username for SMTP-AUTH.
     --smtp-pass             <str>  * Password for SMTP-AUTH; not necessary.
     --smtp-encryption       <str>  * tls or ssl; anything else disables.
-    --smtp-ssl                     * Deprecated. Use '--smtp-encryption ssl'.
+    --smtp-ssl                     * Deprecated. Use `--smtp-encryption ssl`.
     --smtp-ssl-cert-path    <str>  * Path to ca-certificates (either directory or file).
                                      Pass an empty string to disable certificate
                                      verification.
@@ -73,6 +73,10 @@
     --no-smtp-auth                 * Disable SMTP authentication. Shorthand for
                                      `--smtp-auth=none`
     --smtp-debug            <0|1>  * Disable, enable Net::SMTP debug.
+    --imap-sent-folder      <str>  * IMAP folder where a copy of the emails should be sent.
+                                     Make sure `git imap-send` is set up to use this feature.
+    --[no-]use-imap-only           * Only copy emails to the IMAP folder specified by
+                                     `--imap-sent-folder` instead of actually sending them.
 
     --batch-size            <int>  * send max <int> message per connection.
     --relogin-delay         <int>  * delay <int> seconds between two successive login.
@@ -200,7 +204,7 @@
 
 # Variables we fill in automatically, or via prompting:
 my (@to,@cc,@xh,$envelope_sender,
-	$initial_in_reply_to,$reply_to,$initial_subject,@files,
+	$initial_in_reply_to,$reply_to,$initial_subject,@files,@imap_copy,
 	$author,$sender,$smtp_authpass,$annotate,$compose,$time);
 # Things we either get from config, *or* are overridden on the
 # command-line.
@@ -277,6 +281,7 @@
 my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
 my ($batch_size, $relogin_delay);
 my ($identity, $aliasfiletype, @alias_files, $smtp_domain, $smtp_auth);
+my ($imap_sent_folder);
 my ($confirm);
 my (@suppress_cc);
 my ($auto_8bit_encoding);
@@ -293,6 +298,7 @@
 my $target_xfer_encoding = 'auto';
 my $forbid_sendmail_variables = 1;
 my $outlook_id_fix = 'auto';
+my $use_imap_only = 0;
 
 my %config_bool_settings = (
     "thread" => \$thread,
@@ -309,6 +315,7 @@
     "forbidsendmailvariables" => \$forbid_sendmail_variables,
     "mailmap" => \$mailmap,
     "outlookidfix" => \$outlook_id_fix,
+    "useimaponly" => \$use_imap_only,
 );
 
 my %config_settings = (
@@ -322,6 +329,7 @@
     "smtpauth" => \$smtp_auth,
     "smtpbatchsize" => \$batch_size,
     "smtprelogindelay" => \$relogin_delay,
+    "imapsentfolder" => \$imap_sent_folder,
     "to" => \@config_to,
     "tocmd" => \$to_cmd,
     "cc" => \@config_cc,
@@ -527,6 +535,8 @@
 		    "smtp-domain:s" => \$smtp_domain,
 		    "smtp-auth=s" => \$smtp_auth,
 		    "no-smtp-auth" => sub {$smtp_auth = 'none'},
+		    "imap-sent-folder=s" => \$imap_sent_folder,
+		    "use-imap-only!" => \$use_imap_only,
 		    "annotate!" => \$annotate,
 		    "compose" => \$compose,
 		    "quiet" => \$quiet,
@@ -1678,6 +1688,8 @@
 
 	if ($dry_run) {
 		# We don't want to send the email.
+	} elsif ($use_imap_only) {
+		die __("The destination IMAP folder is not properly defined.") if !defined $imap_sent_folder;
 	} elsif (defined $sendmail_cmd || file_name_is_absolute($smtp_server)) {
 		my $pid = open my $sm, '|-';
 		defined $pid or die $!;
@@ -1829,6 +1841,17 @@
 		print "\n";
 	}
 
+	if ($imap_sent_folder && !$dry_run) {
+		my $imap_header = $header;
+		if (@initial_bcc) {
+			# Bcc is not a part of $header, so we add it here.
+			# This is only for the IMAP copy, not for the actual email
+			# sent to the recipients.
+			$imap_header .= "Bcc: " . join(", ", @initial_bcc) . "\n";
+		}
+		push @imap_copy, "From git-send-email\n$imap_header\n$message";
+	}
+
 	return 1;
 }
 
@@ -1931,6 +1954,9 @@
 					$in_reply_to = $1;
 				}
 			}
+			elsif (/^Reply-To: (.*)/i) {
+				$reply_to = $1;
+			}
 			elsif (/^References: (.*)/i) {
 				if (!$initial_in_reply_to || $thread) {
 					$references = $1;
@@ -2223,6 +2249,19 @@
 
 $smtp->quit if $smtp;
 
+if ($imap_sent_folder && @imap_copy && !$dry_run) {
+	my $imap_input = join("\n", @imap_copy);
+	eval {
+		print "\nStarting git imap-send...\n";
+		my ($fh, $ctx) = Git::command_input_pipe(['imap-send', '-f', $imap_sent_folder]);
+		print $fh $imap_input;
+		Git::command_close_pipe($fh, $ctx);
+		1;
+	} or do {
+		warn "Warning: failed to send messages to IMAP folder $imap_sent_folder: $@";
+	};
+}
+
 sub apply_transfer_encoding {
 	my $message = shift;
 	my $from = shift;
diff --git a/git.c b/git.c
index 8c85da8..c5fad56 100644
--- a/git.c
+++ b/git.c
@@ -471,7 +471,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv, struct
 	const char *prefix;
 	int run_setup = (p->option & (RUN_SETUP | RUN_SETUP_GENTLY));
 
-	help = argc == 2 && !strcmp(argv[1], "-h");
+	help = argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help-all"));
 	if (help && (run_setup & RUN_SETUP))
 		/* demote to GENTLY to allow 'git cmd -h' outside repo */
 		run_setup = RUN_SETUP_GENTLY;
@@ -591,6 +591,7 @@ static struct cmd_struct commands[] = {
 	{ "init", cmd_init_db },
 	{ "init-db", cmd_init_db },
 	{ "interpret-trailers", cmd_interpret_trailers, RUN_SETUP_GENTLY },
+	{ "last-modified", cmd_last_modified, RUN_SETUP },
 	{ "log", cmd_log, RUN_SETUP },
 	{ "ls-files", cmd_ls_files, RUN_SETUP },
 	{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
@@ -637,6 +638,7 @@ static struct cmd_struct commands[] = {
 	{ "repack", cmd_repack, RUN_SETUP },
 	{ "replace", cmd_replace, RUN_SETUP },
 	{ "replay", cmd_replay, RUN_SETUP },
+	{ "repo", cmd_repo, RUN_SETUP },
 	{ "rerere", cmd_rerere, RUN_SETUP },
 	{ "reset", cmd_reset, RUN_SETUP },
 	{ "restore", cmd_restore, RUN_SETUP | NEED_WORK_TREE },
diff --git a/gitk-git/README.md b/gitk-git/README.md
new file mode 100644
index 0000000..2e30746
--- /dev/null
+++ b/gitk-git/README.md
@@ -0,0 +1,93 @@
+Gitk - The Git Repository Browser
+=================================
+
+Gitk is a graphical Git repository browser. It displays the commit
+history of a Git repository as a graph, showing the relationships
+between commits, branches, and tags.
+
+Usage
+=====
+
+To view the history of the current repository:
+```bash
+gitk
+```
+
+To view the history of specific files or directories:
+```bash
+gitk path/to/file
+gitk path/to/directory
+```
+
+To view a specific branch or range of commits:
+```bash
+gitk branch-name
+gitk v1.0..v2.0
+```
+
+For more usage examples and options, see the [gitk manual](https://git-scm.com/docs/gitk).
+
+Building
+========
+
+Gitk is a Tcl/Tk application. It requires Tcl/Tk to be installed on
+your system.
+
+Running directly
+----------------
+
+Gitk can be run from the source directory without installation:
+
+```bash
+./gitk
+```
+
+This allows for quick testing of changes.
+
+Installation
+------------
+
+To install system-wide, you can use either `make` or `meson`:
+
+```bash
+# Install to default location ($HOME/bin)
+make install
+
+# Install to system-wide location
+sudo make install prefix=/usr/local
+
+# Install to custom location
+make install prefix=/opt/gitk
+
+# Using Meson
+meson setup builddir
+meson compile -C builddir
+meson install -C builddir
+```
+
+Both build systems will handle setting the correct Tcl/Tk interpreter
+path and installing translation files.
+
+Contributing
+============
+
+Contributions are welcome! The preferred method for submitting patches
+is via email to the Git mailing list, as this allows for more thorough
+review and broader community feedback. However, GitHub pull requests
+are also accepted.
+
+All commits must be signed off (use `git commit --signoff`) and should
+have commit messages prefixed with `gitk:`.
+
+Email Patches
+-------------
+
+Send patches to git@vger.kernel.org and CC j6t@kdbg.org. See the Git
+project's [patch submission guidelines](https://git-scm.com/docs/SubmittingPatches)
+for detailed instructions on creating and sending patches.
+
+License
+=======
+
+Gitk is distributed under the GNU General Public License, either
+version 2, or (at your option) any later version.
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 3b6acfc..7f62c80 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -2131,12 +2131,14 @@
     return $w
 }
 
-proc make_transient {window origin} {
+proc make_transient {window origin {geometry ""}} {
     wm transient $window $origin
 
-    # Windows fails to place transient windows normally, so
-    # schedule a callback to center them on the parent.
-    if {[tk windowingsystem] eq {win32}} {
+    if {$geometry ne ""} {
+        after idle [list wm geometry $window $geometry]
+    } elseif {[tk windowingsystem] eq {win32}} {
+        # Windows fails to place transient windows normally, so
+        # schedule a callback to center them on the parent.
         after idle [list tk::PlaceWindow $window widget $origin]
     }
 }
@@ -2215,6 +2217,7 @@
 }
 
 proc setttkstyle {} {
+    global theme
     eval font configure TkDefaultFont [fontflags mainfont]
     eval font configure TkTextFont [fontflags textfont]
     eval font configure TkHeadingFont [fontflags mainfont]
@@ -2224,6 +2227,10 @@
     eval font configure TkIconFont    [fontflags uifont]
     eval font configure TkMenuFont    [fontflags uifont]
     eval font configure TkSmallCaptionFont [fontflags uifont]
+
+    if {[catch {ttk::style theme use $theme} err]} {
+        set theme [ttk::style theme use]
+    }
 }
 
 # Make a menu and submenus.
@@ -2301,6 +2308,11 @@
     return [expr int(-($D / $scroll_D0) * max(1, $kscroll-$koff))]
 }
 
+proc precisescrollval {D {koff 0}} {
+    global kscroll
+    return [expr (-($D / 10.0) * max(1, $kscroll-$koff))]
+}
+
 proc bind_mousewheel {} {
     global canv cflist ctext
     bindall <MouseWheel> {allcanvs yview scroll [scrollval %D] units}
@@ -2319,6 +2331,25 @@
         bind $cflist <Alt-MouseWheel> {$cflist yview scroll [scrollval 5*%D 2] units}
         bind $cflist <Alt-Shift-MouseWheel> break
         bind $canv <Alt-Shift-MouseWheel> {$canv xview scroll [scrollval 5*%D] units}
+
+        bindall <TouchpadScroll> {
+            lassign [tk::PreciseScrollDeltas %D] deltaX deltaY
+            allcanvs yview scroll [precisescrollval $deltaY] units
+        }
+        bind $ctext <TouchpadScroll> {
+            lassign [tk::PreciseScrollDeltas %D] deltaX deltaY
+            $ctext yview scroll [precisescrollval $deltaY 2] units
+            $ctext xview scroll [precisescrollval $deltaX 2] units
+        }
+        bind $cflist <TouchpadScroll> {
+            lassign [tk::PreciseScrollDeltas %D] deltaX deltaY
+            $cflist yview scroll [precisescrollval $deltaY 2] units
+        }
+        bind $canv <TouchpadScroll> {
+            lassign [tk::PreciseScrollDeltas %D] deltaX deltaY
+            $canv xview scroll [precisescrollval $deltaX] units
+            allcanvs yview scroll [precisescrollval $deltaY] units
+        }
     }
 }
 
@@ -2352,7 +2383,6 @@
     global highlight_files gdttype
     global searchstring sstring
     global bgcolor fgcolor bglist fglist diffcolors diffbgcolors selectbgcolor
-    global uifgcolor uifgdisabledcolor
     global filesepbgcolor filesepfgcolor
     global mergecolors foundbgcolor currentsearchhitbgcolor
     global headctxmenu progresscanv progressitem progresscoords statusw
@@ -2471,40 +2501,18 @@
     set sha1entry .tf.bar.sha1
     set entries $sha1entry
     set sha1but .tf.bar.sha1label
-    button $sha1but -text "[mc "Commit ID:"] " -state disabled -relief flat \
+    ttk::button $sha1but -text "[mc "Commit ID:"] " -state disabled \
         -command gotocommit -width 8
-    $sha1but conf -disabledforeground [$sha1but cget -foreground]
     pack .tf.bar.sha1label -side left
     ttk::entry $sha1entry -width $hashlength -font textfont -textvariable sha1string
     trace add variable sha1string write sha1change
     pack $sha1entry -side left -pady 2
 
-    set bm_left_data {
-        #define left_width 16
-        #define left_height 16
-        static unsigned char left_bits[] = {
-        0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
-        0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
-        0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
-    }
-    set bm_right_data {
-        #define right_width 16
-        #define right_height 16
-        static unsigned char right_bits[] = {
-        0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
-        0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
-        0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
-    }
-    image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor
-    image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor
-    image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor
-    image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor
-
-    ttk::button .tf.bar.leftbut -command goback -state disabled -width 26
-    .tf.bar.leftbut configure -image [list bm-left disabled bm-left-gray]
+    ttk::button .tf.bar.leftbut -command goback -state disabled 
+    .tf.bar.leftbut configure -text \u2190 -width 3
     pack .tf.bar.leftbut -side left -fill y
-    ttk::button .tf.bar.rightbut -command goforw -state disabled -width 26
-    .tf.bar.rightbut configure -image [list bm-right disabled bm-right-gray]
+    ttk::button .tf.bar.rightbut -command goforw -state disabled 
+    .tf.bar.rightbut configure -text \u2192 -width 3
     pack .tf.bar.rightbut -side left -fill y
 
     ttk::label .tf.bar.rowlabel -text [mc "Row"]
@@ -2535,31 +2543,8 @@
     # build up the bottom bar of upper window
     ttk::label .tf.lbar.flabel -text "[mc "Find"] "
 
-    set bm_down_data {
-        #define down_width 16
-        #define down_height 16
-        static unsigned char down_bits[] = {
-        0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
-        0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
-        0x87, 0xe1, 0x8e, 0x71, 0x9c, 0x39, 0xb8, 0x1d,
-        0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
-    }
-    image create bitmap bm-down -data $bm_down_data -foreground $uifgcolor
-    ttk::button .tf.lbar.fnext -width 26 -command {dofind 1 1}
-    .tf.lbar.fnext configure -image bm-down
-
-    set bm_up_data {
-        #define up_width 16
-        #define up_height 16
-        static unsigned char up_bits[] = {
-        0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
-        0xb8, 0x1d, 0x9c, 0x39, 0x8e, 0x71, 0x87, 0xe1,
-        0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
-        0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
-    }
-    image create bitmap bm-up -data $bm_up_data -foreground $uifgcolor
-    ttk::button .tf.lbar.fprev -width 26 -command {dofind -1 1}
-    .tf.lbar.fprev configure -image bm-up
+    ttk::button .tf.lbar.fnext -command {dofind 1 1} -text \u2193 -width 3
+    ttk::button .tf.lbar.fprev -command {dofind -1 1} -text \u2191 -width 3
 
     ttk::label .tf.lbar.flab2 -text " [mc "commit"] "
 
@@ -2632,7 +2617,7 @@
 
     ttk::label .bleft.mid.labeldiffcontext -text "      [mc "Lines of context"]: "
     pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left -ipadx $wgap
-    spinbox .bleft.mid.diffcontext -width 5 \
+    ttk::spinbox .bleft.mid.diffcontext -width 5 \
         -from 0 -increment 1 -to 10000000 \
         -validate all -validatecommand "diffcontextvalidate %P" \
         -textvariable diffcontextstring
@@ -2740,17 +2725,9 @@
     .pwbottom add .bright
     .ctop add .pwbottom
 
-    # restore window width & height if known
+    # restore window position if known
     if {[info exists geometry(main)]} {
-        if {[scan $geometry(main) "%dx%d" w h] >= 2} {
-            if {$w > [winfo screenwidth .]} {
-                set w [winfo screenwidth .]
-            }
-            if {$h > [winfo screenheight .]} {
-                set h [winfo screenheight .]
-            }
-            wm geometry . "${w}x$h"
-        }
+        wm geometry . "$geometry(main)"
     }
 
     if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
@@ -3090,6 +3067,11 @@
         puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sashpos 1] 1\""
         puts $f "set geometry(botwidth) [winfo width .bleft]"
         puts $f "set geometry(botheight) [winfo height .bleft]"
+        unset -nocomplain geometry
+        global geometry
+        if {[info exists geometry(showrefs)]} {
+            puts $f "set geometry(showrefs) $geometry(showrefs)"
+        }
 
         array set view_save {}
         array set views {}
@@ -3805,6 +3787,34 @@
                "revision $diffid"]
 }
 
+proc check_for_renames_in_diff {filepath} { # renames
+    global difffilestart ctext
+
+    set filename [file tail $filepath]
+    set renames {}
+
+    foreach loc $difffilestart {
+        set loclineend [string map {.0 .end} $loc]
+        set fromlineloc "$loc + 2 lines"
+        set tolineloc "$loc + 3 lines"
+        set renfromline [$ctext get $fromlineloc [string map {.0 .end} $fromlineloc]]
+        set rentoline [$ctext get $tolineloc [string map {.0 .end} $tolineloc]]
+        if {[string equal -length 12 "rename from " $renfromline]
+            && [string equal -length 10 "rename to " $rentoline]} {
+            set renfrom [string range $renfromline 12 end]
+            set rento [string range $rentoline 10 end]
+            if {[string first $filename $renfrom] != -1
+                || [string first $filename $rento] != -1} {
+                lappend renames $renfrom
+                lappend renames $rento
+                break
+            }
+        }
+    }
+
+    return $renames
+}
+
 proc external_diff {} {
     global nullid nullid2
     global flist_menu_file
@@ -3835,8 +3845,16 @@
     if {$diffdir eq {}} return
 
     # gather files to diff
-    set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
-    set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
+    set renames [check_for_renames_in_diff $flist_menu_file]
+    set renamefrom [lindex $renames 0]
+    set renameto [lindex $renames 1]
+    if {$renamefrom ne {} && $renameto ne {}} {
+        set difffromfile [external_diff_get_one_file $diffidfrom $renamefrom $diffdir]
+        set difftofile [external_diff_get_one_file $diffidto $renameto $diffdir]
+    } else {
+        set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
+        set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
+    }
 
     if {$difffromfile ne {} && $difftofile ne {}} {
         set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
@@ -8313,7 +8331,7 @@
         if {![regexp {^diff (--cc|--git) } $line m type]} {
             set line [convertfrom utf-8 $line]
             $ctext insert end "$line\n" hunksep
-            continue
+            return
         }
         # start of a new file
         set diffinhdr 1
@@ -8418,6 +8436,7 @@
             if {$i >= 0} {
                 setinlist difffilestart $i $curdiffstart
             }
+            set line "rename from $fname"
         } elseif {![string compare -length 10 $line "rename to "] ||
                   ![string compare -length 8 $line "copy to "]} {
             set fname [string range $line [expr 4 + [string first " to " $line] ] end]
@@ -8425,6 +8444,13 @@
                 set fname [lindex $fname 0]
             }
             makediffhdr $fname $ids
+            set line "[lindex $line 0] to $fname"
+        } elseif {![string compare -length 10 $line "copy from "]} {
+            set fname [string range $line 10 end]
+            if {[string index $fname 0] eq "\""} {
+                set fname [lindex $fname 0]
+            }
+            set line "copy from $fname"
         } elseif {[string compare -length 3 $line "---"] == 0} {
             # do nothing
             return
@@ -8886,9 +8912,9 @@
     }
     if {[$sha1but cget -state] == $state} return
     if {$state == "normal"} {
-        $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
+        $sha1but conf -state normal -text "[mc "Goto:"] "
     } else {
-        $sha1but conf -state disabled -relief flat -text "[mc "Commit ID:"] "
+        $sha1but conf -state disabled -text "[mc "Commit ID:"] "
     }
 }
 
@@ -10177,6 +10203,7 @@
 proc showrefs {} {
     global showrefstop bgcolor fgcolor selectbgcolor
     global bglist fglist reflistfilter reflist maincursor
+    global geometry
 
     set top .showrefs
     set showrefstop $top
@@ -10187,7 +10214,11 @@
     }
     ttk_toplevel $top
     wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
-    make_transient $top .
+    if {[info exists geometry(showrefs)]} {
+        make_transient $top . $geometry(showrefs)
+    } else {
+        make_transient $top .
+    }
     text $top.list -background $bgcolor -foreground $fgcolor \
         -selectbackground $selectbgcolor -font mainfont \
         -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
@@ -10223,6 +10254,9 @@
     bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
     set reflist {}
     refill_reflist
+    # avoid <Configure> being bound to child windows
+    bindtags $top [linsert [bindtags $top] 1 bind$top]
+    bind bind$top <Configure> {set geometry(showrefs) [wm geometry %W]}
 }
 
 proc sel_reflist {w x y} {
@@ -10270,7 +10304,9 @@
         if {![string match "remotes/*" $n] && [string match $reflistfilter $n]} {
             if {[commitinview $headids($n) $curview]} {
                 lappend localrefs [list $n H]
-                if {[info exists upstreamofref($n)] && [commitinview $headids($upstreamofref($n)) $curview]} {
+                if {[info exists upstreamofref($n)] && \
+                        [info exists headids($upstreamofref($n))] && \
+                        [commitinview $headids($upstreamofref($n)) $curview]} {
                     lappend trackedremoterefs [list $upstreamofref($n) R]
                 }
             } else {
@@ -11584,9 +11620,10 @@
     set fontpref($font) [set $font]
     ttk::button $top.${font}but -text $which \
         -command [list choosefont $font $which]
-    ttk::label $top.$font -relief flat -font $font \
-        -text $fontattr($font,family) -justify left
+    ttk::label $top.$font -font $font \
+        -text $fontattr($font,family)
     grid x $top.${font}but $top.$font -sticky w
+    grid configure $top.$font -sticky ew
 }
 
 proc centertext {w} {
@@ -11666,48 +11703,52 @@
 
     ttk::label $page.ldisp -text [mc "Commit list display options"] -font mainfontbold
     grid $page.ldisp - -sticky w -pady 10
+
     ttk::label $page.spacer -text " "
     ttk::label $page.maxwidthl -text [mc "Maximum graph width (lines)"]
-    spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
+    ttk::spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
     grid $page.spacer $page.maxwidthl $page.maxwidth -sticky w
                                          #xgettext:no-tcl-format
     ttk::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"]
-    spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
+    ttk::spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
     grid x $page.maxpctl $page.maxpct -sticky w
+
     ttk::checkbutton $page.showlocal -text [mc "Show local changes"] \
         -variable showlocalchanges
     grid x $page.showlocal -sticky w
+
     ttk::checkbutton $page.hideremotes -text [mc "Hide remote refs"] \
         -variable hideremotes
     grid x $page.hideremotes -sticky w
 
     ttk::entry $page.refstohide -textvariable refstohide
-    ttk::frame $page.refstohidef
-    ttk::label $page.refstohidef.l -text [mc "Refs to hide (space-separated globs)" ]
-    pack $page.refstohidef.l -side left
-    pack configure $page.refstohidef.l -padx 10
-    grid x $page.refstohidef $page.refstohide -sticky ew
+    ttk::label $page.refstohidel -text [mc "Refs to hide (space-separated globs)"]
+    grid x $page.refstohidel $page.refstohide -sticky ew
+    grid configure $page.refstohide -padx {0 5}
 
     ttk::checkbutton $page.autocopy -text [mc "Copy commit ID to clipboard"] \
         -variable autocopy
     grid x $page.autocopy -sticky w
+
     if {[haveselectionclipboard]} {
         ttk::checkbutton $page.autoselect -text [mc "Copy commit ID to X11 selection"] \
             -variable autoselect
         grid x $page.autoselect -sticky w
     }
 
-    spinbox $page.autosellen -from 1 -to $hashlength -width 4 -textvariable autosellen
+    ttk::spinbox $page.autosellen -from 1 -to $hashlength -width 4 -textvariable autosellen
     ttk::label $page.autosellenl -text [mc "Length of commit ID to copy"]
     grid x $page.autosellenl $page.autosellen -sticky w
+
     ttk::label $page.kscroll1 -text [mc "Wheel scrolling multiplier"]
-    spinbox $page.kscroll -from 1 -to 20 -width 4 -textvariable kscroll
+    ttk::spinbox $page.kscroll -from 1 -to 20 -width 4 -textvariable kscroll
     grid x $page.kscroll1 $page.kscroll -sticky w
 
     ttk::label $page.ddisp -text [mc "Diff display options"] -font mainfontbold
     grid $page.ddisp - -sticky w -pady 10
+
     ttk::label $page.tabstopl -text [mc "Tab spacing"]
-    spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
+    ttk::spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
     grid x $page.tabstopl $page.tabstop -sticky w
 
     ttk::label $page.wrapcommentl -text [mc "Wrap comment text"]
@@ -11721,12 +11762,15 @@
     ttk::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \
         -variable showneartags
     grid x $page.ntag -sticky w
+
     ttk::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"]
-    spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs
+    ttk::spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs
     grid x $page.maxrefsl $page.maxrefs -sticky w
+
     ttk::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \
         -variable limitdiffs
     grid x $page.ldiff -sticky w
+
     ttk::checkbutton $page.lattr -text [mc "Support per-file encodings"] \
         -variable perfile_attrs
     grid x $page.lattr -sticky w
@@ -11735,76 +11779,109 @@
     ttk::frame $page.extdifff
     ttk::label $page.extdifff.l -text [mc "External diff tool" ]
     ttk::button $page.extdifff.b -text [mc "Choose..."] -command choose_extdiff
-    pack $page.extdifff.l $page.extdifff.b -side left
-    pack configure $page.extdifff.l -padx 10
+    pack $page.extdifff.l -side left
+    pack $page.extdifff.b -side right -padx {0 5}
     grid x $page.extdifff $page.extdifft -sticky ew
+    grid configure $page.extdifft -padx {0 5}
 
     ttk::entry $page.webbrowser -textvariable web_browser
-    ttk::frame $page.webbrowserf
-    ttk::label $page.webbrowserf.l -text [mc "Web browser" ]
-    pack $page.webbrowserf.l -side left
-    pack configure $page.webbrowserf.l -padx 10
-    grid x $page.webbrowserf $page.webbrowser -sticky ew
+    ttk::label $page.webbrowserl -text [mc "Web browser" ]
+    grid x $page.webbrowserl $page.webbrowser -sticky ew
+    grid configure $page.webbrowser -padx {0 5}
+
+    grid columnconfigure $page 2 -weight 1
 
     return $page
 }
 
 proc prefspage_colors {notebook} {
-    global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
+    global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
     global diffbgcolors
+    global themeloader
 
     set page [create_prefs_page $notebook.colors]
 
+    ttk::label $page.themesel -font mainfontbold \
+        -text [mc "Themes - change requires restart"]
+    grid $page.themesel - -sticky w -pady 10
+
+    ttk::label $page.themelabel -text [mc "Theme to use after restart"]
+    makedroplist $page.theme theme {*}[lsort [ttk::style theme names]]
+    grid x $page.themelabel $page.theme -sticky w
+
+    ttk::entry $page.tloadvar -textvariable themeloader
+    ttk::frame $page.tloadframe
+    ttk::label $page.tloadframe.l -text [mc "Theme definition file"]
+    ttk::button $page.tloadframe.b -text [mc "Choose..."] \
+        -command [list choose_themeloader $page]
+    pack $page.tloadframe.l -side left
+    pack $page.tloadframe.b -side right -padx {0 5}
+    pack configure $page.tloadframe.l -padx 0
+    grid x $page.tloadframe $page.tloadvar -sticky ew
+    grid configure $page.tloadvar -padx {0 5}
+
+    ttk::label $page.themelabel2 -text \
+        [mc "The theme definition file may affect all themes."]
+    ttk::button $page.themebut2 -text [mc "Apply theme"] \
+        -command [list updatetheme $page]
+    grid x $page.themebut2 $page.themelabel2 -sticky w
+
     ttk::label $page.cdisp -text [mc "Colors: press to choose"] -font mainfontbold
     grid $page.cdisp - -sticky w -pady 10
-    label $page.ui -padx 40 -relief sunk -background $uicolor
-    ttk::button $page.uibut -text [mc "Interface"] \
-       -command [list choosecolor uicolor {} $page [mc "interface"]]
-    grid x $page.uibut $page.ui -sticky w
     label $page.bg -padx 40 -relief sunk -background $bgcolor
     ttk::button $page.bgbut -text [mc "Background"] \
         -command [list choosecolor bgcolor {} $page [mc "background"]]
     grid x $page.bgbut $page.bg -sticky w
+
     label $page.fg -padx 40 -relief sunk -background $fgcolor
     ttk::button $page.fgbut -text [mc "Foreground"] \
         -command [list choosecolor fgcolor {} $page [mc "foreground"]]
     grid x $page.fgbut $page.fg -sticky w
+
     label $page.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
     ttk::button $page.diffoldbut -text [mc "Diff: old lines"] \
         -command [list choosecolor diffcolors 0 $page [mc "diff old lines"]]
     grid x $page.diffoldbut $page.diffold -sticky w
+
     label $page.diffoldbg -padx 40 -relief sunk -background [lindex $diffbgcolors 0]
     ttk::button $page.diffoldbgbut -text [mc "Diff: old lines bg"] \
         -command [list choosecolor diffbgcolors 0 $page [mc "diff old lines bg"]]
     grid x $page.diffoldbgbut $page.diffoldbg -sticky w
+
     label $page.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
     ttk::button $page.diffnewbut -text [mc "Diff: new lines"] \
         -command [list choosecolor diffcolors 1 $page [mc "diff new lines"]]
     grid x $page.diffnewbut $page.diffnew -sticky w
+
     label $page.diffnewbg -padx 40 -relief sunk -background [lindex $diffbgcolors 1]
     ttk::button $page.diffnewbgbut -text [mc "Diff: new lines bg"] \
         -command [list choosecolor diffbgcolors 1 $page [mc "diff new lines bg"]]
     grid x $page.diffnewbgbut $page.diffnewbg -sticky w
+
     label $page.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
     ttk::button $page.hunksepbut -text [mc "Diff: hunk header"] \
         -command [list choosecolor diffcolors 2 $page [mc "diff hunk header"]]
     grid x $page.hunksepbut $page.hunksep -sticky w
+
     label $page.markbgsep -padx 40 -relief sunk -background $markbgcolor
     ttk::button $page.markbgbut -text [mc "Marked line bg"] \
         -command [list choosecolor markbgcolor {} $page [mc "marked line background"]]
     grid x $page.markbgbut $page.markbgsep -sticky w
+
     label $page.selbgsep -padx 40 -relief sunk -background $selectbgcolor
     ttk::button $page.selbgbut -text [mc "Select bg"] \
         -command [list choosecolor selectbgcolor {} $page [mc "background"]]
     grid x $page.selbgbut $page.selbgsep -sticky w
+
+    grid columnconfigure $page 2 -weight 1
+
     return $page
 }
 
 proc prefspage_set_colorswatches {page} {
-    global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
+    global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
     global diffbgcolors
 
-    $page.ui configure -background $uicolor
     $page.bg configure -background $bgcolor
     $page.fg configure -background $fgcolor
     $page.diffold configure -background [lindex $diffcolors 0]
@@ -11823,6 +11900,7 @@
     mkfontdisp mainfont $page [mc "Main font"]
     mkfontdisp textfont $page [mc "Diff display font"]
     mkfontdisp uifont $page [mc "User interface font"]
+    grid columnconfigure $page 2 -weight 1
     return $page
 }
 
@@ -11857,7 +11935,7 @@
     grid rowconfigure $notebook 1 -weight 1
     raise [lindex $pages 0]
 
-    grid $notebook -sticky news -padx 2 -pady 2
+    grid $notebook -sticky news -padx 3 -pady 3
     grid rowconfigure $top 0 -weight 1
     grid columnconfigure $top 0 -weight 1
 
@@ -11866,12 +11944,13 @@
     ttk::button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
     bind $top <Key-Return> prefsok
     bind $top <Key-Escape> prefscan
-    grid $top.buts.ok $top.buts.can
-    grid columnconfigure $top.buts 0 -weight 1 -uniform a
-    grid columnconfigure $top.buts 1 -weight 1 -uniform a
-    grid $top.buts - - -pady 10 -sticky ew
-    grid columnconfigure $top 2 -weight 1
+    grid $top.buts.ok $top.buts.can -padx 20
+    grid $top.buts -sticky w -pady 10
     bind $top <Visibility> [list focus $top.buts.ok]
+
+    # let geometry manager determine run, set minimum size
+    update idletasks
+    wm minsize $top [winfo reqwidth $top] [winfo reqheight $top]
 }
 
 proc choose_extdiff {} {
@@ -11883,6 +11962,51 @@
     }
 }
 
+proc run_themeloader {f} {
+    if {![info exists ::_themefiles_seen]} {
+        set ::_themefiles_seen [dict create]
+    }
+
+    set fn [file normalize $f]
+    if {![dict exists $::_themefiles_seen $fn]} {
+        if {[catch {source $fn} err]} {
+            error_popup "could not interpret: $fn\n$err"
+            dict set ::_themefiles_seen $fn 0
+        } else {
+            dict set ::_themefiles_seen $fn 1
+        }
+    }
+    return [dict get $::_themefiles_seen $fn]
+}
+
+proc updatetheme {prefspage {dotheme 1}} {
+    global theme
+    global themeloader
+    if {$themeloader ne {}} {
+        if {![run_themeloader $themeloader]} {
+            set themeloader {}
+            return
+        } else {
+            $prefspage.theme configure -values \
+                [lsort [ttk::style theme names]]
+        }
+    }
+    if {$dotheme} {
+        ttk::style theme use $theme
+        set_gui_colors
+        prefspage_set_colorswatches $prefspage
+    }
+}
+
+proc choose_themeloader {prefspage} {
+    global themeloader
+    set tfile [tk_getOpenFile -title [mc "Gitk: select theme definition"] -multiple false]
+    if {$tfile ne {}} {
+        set themeloader $tfile
+        updatetheme $prefspage 0
+    }
+}
+
 proc choosecolor {v vi prefspage x} {
     global $v
 
@@ -11906,21 +12030,6 @@
     allcanvs itemconf secsel -fill $c
 }
 
-# This sets the background color and the color scheme for the whole UI.
-# For some reason, tk_setPalette chooses a nasty dark red for selectColor
-# if we don't specify one ourselves, which makes the checkbuttons and
-# radiobuttons look bad.  This chooses white for selectColor if the
-# background color is light, or black if it is dark.
-proc setui {c} {
-    if {[tk windowingsystem] eq "win32"} { return }
-    set bg [winfo rgb . $c]
-    set selc black
-    if {[lindex $bg 0] + 1.5 * [lindex $bg 1] + 0.5 * [lindex $bg 2] > 100000} {
-        set selc white
-    }
-    tk_setPalette background $c selectColor $selc
-}
-
 proc setbg {c} {
     global bglist
 
@@ -11945,10 +12054,9 @@
 }
 
 proc set_gui_colors {} {
-    global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
+    global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
     global diffbgcolors
 
-    setui $uicolor
     setbg $bgcolor
     setfg $fgcolor
     $ctext tag conf d0 -foreground [lindex $diffcolors   0]
@@ -11970,6 +12078,7 @@
     catch {destroy $prefstop}
     unset prefstop
     fontcan
+    setttkstyle
     set_gui_colors
 }
 
@@ -12436,11 +12545,13 @@
 
 # on OSX bring the current Wish process window to front
 if {[tk windowingsystem] eq "aqua"} {
-    safe_exec [list osascript -e [format {
-        tell application "System Events"
-            set frontmost of processes whose unix id is %d to true
-        end tell
-    } [pid] ]]
+    catch {
+        safe_exec [list osascript -e [format {
+            tell application "System Events"
+                set frontmost of processes whose unix id is %d to true
+            end tell
+        } [pid] ]]
+    }
 }
 
 # Unset GIT_TRACE var if set
@@ -12545,17 +12656,11 @@
 
 set colors {"#00ff00" red blue magenta darkgrey brown orange}
 if {[tk windowingsystem] eq "win32"} {
-    set uicolor SystemButtonFace
-    set uifgcolor SystemButtonText
-    set uifgdisabledcolor SystemDisabledText
     set bgcolor SystemWindow
     set fgcolor SystemWindowText
     set selectbgcolor SystemHighlight
     set web_browser "cmd /c start"
 } else {
-    set uicolor grey85
-    set uifgcolor black
-    set uifgdisabledcolor "#999"
     set bgcolor white
     set fgcolor black
     set selectbgcolor gray85
@@ -12595,8 +12700,14 @@
 set foundbgcolor yellow
 set currentsearchhitbgcolor orange
 
+set theme [ttk::style theme use]
+set themeloader {}
+set uicolor {}
+set uifgcolor {}
+set uifgdisabledcolor {}
+
 # button for popping up context menus
-if {[tk windowingsystem] eq "aqua"} {
+if {[tk windowingsystem] eq "aqua" && [package vcompare $::tcl_version 8.7] < 0} {
     set ctxbut <Button-2>
 } else {
     set ctxbut <Button-3>
@@ -12678,6 +12789,8 @@
     tagfgcolor
     tagoutlinecolor
     textfont
+    theme
+    themeloader
     uicolor
     uifgcolor
     uifgdisabledcolor
@@ -12777,7 +12890,13 @@
 set nullid2 "0000000000000000000000000000000000000001"
 set nullfile "/dev/null"
 
-setttkstyle
+if {[file exists $themeloader]} {
+    if {![run_themeloader $themeloader]} {
+        puts stderr "Could not interpret themeloader: $themeloader"
+        exit 1
+    }
+}
+
 set appname "gitk"
 
 set runq {}
@@ -12893,6 +13012,7 @@
     focus -force .
 }
 
+setttkstyle
 set_gui_colors
 
 getcommits {}
diff --git a/gpg-interface.c b/gpg-interface.c
index 06e7fb5..f680ed3 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -443,7 +443,7 @@ static void parse_ssh_output(struct signature_check *sigc)
 
 	key = strstr(line, "key ");
 	if (key) {
-		sigc->fingerprint = xstrdup(strstr(line, "key ") + 4);
+		sigc->fingerprint = xstrdup(key + 4);
 		sigc->key = xstrdup(sigc->fingerprint);
 	} else {
 		/*
@@ -821,8 +821,7 @@ static char *get_ssh_key_fingerprint(const char *signing_key)
 	struct child_process ssh_keygen = CHILD_PROCESS_INIT;
 	int ret = -1;
 	struct strbuf fingerprint_stdout = STRBUF_INIT;
-	struct strbuf **fingerprint;
-	char *fingerprint_ret;
+	char *fingerprint_ret, *begin, *delim;
 	const char *literal_key = NULL;
 
 	/*
@@ -845,13 +844,17 @@ static char *get_ssh_key_fingerprint(const char *signing_key)
 		die_errno(_("failed to get the ssh fingerprint for key '%s'"),
 			  signing_key);
 
-	fingerprint = strbuf_split_max(&fingerprint_stdout, ' ', 3);
-	if (!fingerprint[1])
-		die_errno(_("failed to get the ssh fingerprint for key '%s'"),
+	begin = fingerprint_stdout.buf;
+	delim = strchr(begin, ' ');
+	if (!delim)
+		die(_("failed to get the ssh fingerprint for key %s"),
 			  signing_key);
-
-	fingerprint_ret = strbuf_detach(fingerprint[1], NULL);
-	strbuf_list_free(fingerprint);
+	begin = delim + 1;
+	delim = strchr(begin, ' ');
+	if (!delim)
+	    die(_("failed to get the ssh fingerprint for key %s"),
+			  signing_key);
+	fingerprint_ret = xmemdupz(begin, delim - begin);
 	strbuf_release(&fingerprint_stdout);
 	return fingerprint_ret;
 }
@@ -862,12 +865,12 @@ static char *get_default_ssh_signing_key(void)
 	struct child_process ssh_default_key = CHILD_PROCESS_INIT;
 	int ret = -1;
 	struct strbuf key_stdout = STRBUF_INIT, key_stderr = STRBUF_INIT;
-	struct strbuf **keys;
 	char *key_command = NULL;
 	const char **argv;
 	int n;
 	char *default_key = NULL;
 	const char *literal_key = NULL;
+	char *begin, *new_line, *first_line;
 
 	if (!ssh_default_key_command)
 		die(_("either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"));
@@ -876,7 +879,7 @@ static char *get_default_ssh_signing_key(void)
 	n = split_cmdline(key_command, &argv);
 
 	if (n < 0)
-		die("malformed build-time gpg.ssh.defaultKeyCommand: %s",
+		die(_("malformed build-time gpg.ssh.defaultKeyCommand: %s"),
 		    split_cmdline_strerror(n));
 
 	strvec_pushv(&ssh_default_key.args, argv);
@@ -884,19 +887,24 @@ static char *get_default_ssh_signing_key(void)
 			   &key_stderr, 0);
 
 	if (!ret) {
-		keys = strbuf_split_max(&key_stdout, '\n', 2);
-		if (keys[0] && is_literal_ssh_key(keys[0]->buf, &literal_key)) {
+		begin = key_stdout.buf;
+		new_line = strchr(begin, '\n');
+		if (new_line)
+			first_line = xmemdupz(begin, new_line - begin);
+		else
+			first_line = xstrdup(begin);
+		if (is_literal_ssh_key(first_line, &literal_key)) {
 			/*
 			 * We only use `is_literal_ssh_key` here to check validity
 			 * The prefix will be stripped when the key is used.
 			 */
-			default_key = strbuf_detach(keys[0], NULL);
+			default_key = first_line;
 		} else {
+			free(first_line);
 			warning(_("gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"),
 				key_stderr.buf, key_stdout.buf);
 		}
 
-		strbuf_list_free(keys);
 	} else {
 		warning(_("gpg.ssh.defaultKeyCommand failed: %s %s"),
 			key_stderr.buf, key_stdout.buf);
@@ -1125,3 +1133,20 @@ static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
 	FREE_AND_NULL(ssh_signing_key_file);
 	return ret;
 }
+
+int parse_sign_mode(const char *arg, enum sign_mode *mode)
+{
+	if (!strcmp(arg, "abort"))
+		*mode = SIGN_ABORT;
+	else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore"))
+		*mode = SIGN_VERBATIM;
+	else if (!strcmp(arg, "warn-verbatim") || !strcmp(arg, "warn"))
+		*mode = SIGN_WARN_VERBATIM;
+	else if (!strcmp(arg, "warn-strip"))
+		*mode = SIGN_WARN_STRIP;
+	else if (!strcmp(arg, "strip"))
+		*mode = SIGN_STRIP;
+	else
+		return -1;
+	return 0;
+}
diff --git a/gpg-interface.h b/gpg-interface.h
index 60ddf8b..ead1ed6 100644
--- a/gpg-interface.h
+++ b/gpg-interface.h
@@ -3,9 +3,9 @@
 
 struct strbuf;
 
-#define GPG_VERIFY_VERBOSE		1
-#define GPG_VERIFY_RAW			2
-#define GPG_VERIFY_OMIT_STATUS	4
+#define GPG_VERIFY_VERBOSE	(1<<0)
+#define GPG_VERIFY_RAW		(1<<1)
+#define GPG_VERIFY_OMIT_STATUS	(1<<2)
 
 enum signature_trust_level {
 	TRUST_UNDEFINED,
@@ -104,4 +104,19 @@ int check_signature(struct signature_check *sigc,
 void print_signature_buffer(const struct signature_check *sigc,
 			    unsigned flags);
 
+/* Modes for --signed-tags=<mode> and --signed-commits=<mode> options. */
+enum sign_mode {
+	SIGN_ABORT,
+	SIGN_WARN_VERBATIM,
+	SIGN_VERBATIM,
+	SIGN_WARN_STRIP,
+	SIGN_STRIP,
+};
+
+/*
+ * Return 0 if `arg` can be parsed into an `enum sign_mode`. Return -1
+ * otherwise.
+ */
+int parse_sign_mode(const char *arg, enum sign_mode *mode);
+
 #endif
diff --git a/grep.c b/grep.c
index 932647e..c7e1dc1 100644
--- a/grep.c
+++ b/grep.c
@@ -1263,12 +1263,12 @@ static void show_line(struct grep_opt *opt,
 		 */
 		show_line_header(opt, name, lno, cno, sign);
 	}
-	if (opt->color || opt->only_matching) {
+	if (want_color(opt->color) || opt->only_matching) {
 		regmatch_t match;
 		enum grep_context ctx = GREP_CONTEXT_BODY;
 		int eflags = 0;
 
-		if (opt->color) {
+		if (want_color(opt->color)) {
 			if (sign == ':')
 				match_color = opt->colors[GREP_COLOR_MATCH_SELECTED];
 			else
diff --git a/grep.h b/grep.h
index 926c087..13e26a9 100644
--- a/grep.h
+++ b/grep.h
@@ -159,7 +159,7 @@ struct grep_opt {
 	int pathname;
 	int null_following_name;
 	int only_matching;
-	int color;
+	enum git_colorbool color;
 	int max_depth;
 	int funcname;
 	int funcbody;
@@ -198,7 +198,7 @@ struct grep_opt {
 		[GREP_COLOR_SEP] = GIT_COLOR_CYAN, \
 	}, \
 	.only_matching = 0, \
-	.color = -1, \
+	.color = GIT_COLOR_UNKNOWN, \
 	.output = std_output, \
 }
 
diff --git a/help.c b/help.c
index bb20498..20e1144 100644
--- a/help.c
+++ b/help.c
@@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)
 		strbuf_addf(buf, "shell-path: %s\n", SHELL_PATH);
 		/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */
 
+#if defined WITH_RUST
+		strbuf_addstr(buf, "rust: enabled\n");
+#else
+		strbuf_addstr(buf, "rust: disabled\n");
+#endif
+
 		if (fsmonitor_ipc__is_supported())
 			strbuf_addstr(buf, "feature: fsmonitor--daemon\n");
 #if defined LIBCURL_VERSION
@@ -845,18 +851,16 @@ struct similar_ref_cb {
 	struct string_list *similar_refs;
 };
 
-static int append_similar_ref(const char *refname, const char *referent UNUSED,
-			      const struct object_id *oid UNUSED,
-			      int flags UNUSED, void *cb_data)
+static int append_similar_ref(const struct reference *ref, void *cb_data)
 {
 	struct similar_ref_cb *cb = (struct similar_ref_cb *)(cb_data);
-	char *branch = strrchr(refname, '/') + 1;
+	char *branch = strrchr(ref->name, '/') + 1;
 
 	/* A remote branch of the same name is deemed similar */
-	if (starts_with(refname, "refs/remotes/") &&
+	if (starts_with(ref->name, "refs/remotes/") &&
 	    !strcmp(branch, cb->base_ref))
 		string_list_append_nodup(cb->similar_refs,
-					 refs_shorten_unambiguous_ref(get_main_ref_store(the_repository), refname, 1));
+					 refs_shorten_unambiguous_ref(get_main_ref_store(the_repository), ref->name, 1));
 	return 0;
 }
 
diff --git a/http-backend.c b/http-backend.c
index d5dfe76..273ed72 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -513,18 +513,17 @@ static void run_service(const char **argv, int buffer_input)
 		exit(1);
 }
 
-static int show_text_ref(const char *name, const char *referent UNUSED, const struct object_id *oid,
-			 int flag UNUSED, void *cb_data)
+static int show_text_ref(const struct reference *ref, void *cb_data)
 {
-	const char *name_nons = strip_namespace(name);
+	const char *name_nons = strip_namespace(ref->name);
 	struct strbuf *buf = cb_data;
-	struct object *o = parse_object(the_repository, oid);
+	struct object *o = parse_object(the_repository, ref->oid);
 	if (!o)
 		return 0;
 
-	strbuf_addf(buf, "%s\t%s\n", oid_to_hex(oid), name_nons);
+	strbuf_addf(buf, "%s\t%s\n", oid_to_hex(ref->oid), name_nons);
 	if (o->type == OBJ_TAG) {
-		o = deref_tag(the_repository, o, name, 0);
+		o = deref_tag(the_repository, o, ref->name, 0);
 		if (!o)
 			return 0;
 		strbuf_addf(buf, "%s\t%s^{}\n", oid_to_hex(&o->oid),
@@ -569,21 +568,20 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
 	strbuf_release(&buf);
 }
 
-static int show_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			 int flag, void *cb_data)
+static int show_head_ref(const struct reference *ref, void *cb_data)
 {
 	struct strbuf *buf = cb_data;
 
-	if (flag & REF_ISSYMREF) {
+	if (ref->flags & REF_ISSYMREF) {
 		const char *target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
-							     refname,
+							     ref->name,
 							     RESOLVE_REF_READING,
 							     NULL, NULL);
 
 		if (target)
 			strbuf_addf(buf, "ref: %s\n", strip_namespace(target));
 	} else {
-		strbuf_addf(buf, "%s\n", oid_to_hex(oid));
+		strbuf_addf(buf, "%s\n", oid_to_hex(ref->oid));
 	}
 
 	return 0;
@@ -608,13 +606,13 @@ static void get_info_packs(struct strbuf *hdr, char *arg UNUSED)
 	size_t cnt = 0;
 
 	select_getanyfile(hdr);
-	for (p = get_all_packs(the_repository); p; p = p->next) {
+	repo_for_each_pack(the_repository, p) {
 		if (p->pack_local)
 			cnt++;
 	}
 
 	strbuf_grow(&buf, cnt * 53 + 2);
-	for (p = get_all_packs(the_repository); p; p = p->next) {
+	repo_for_each_pack(the_repository, p) {
 		if (p->pack_local)
 			strbuf_addf(&buf, "P %s\n", p->pack_name + objdirlen + 6);
 	}
diff --git a/http-push.c b/http-push.c
index 7a9b96a..d86ce77 100644
--- a/http-push.c
+++ b/http-push.c
@@ -104,7 +104,7 @@ struct repo {
 	int has_info_refs;
 	int can_update_info_refs;
 	int has_info_packs;
-	struct packed_git *packs;
+	struct packfile_list packs;
 	struct remote_lock *locks;
 };
 
@@ -311,7 +311,7 @@ static void start_fetch_packed(struct transfer_request *request)
 	struct transfer_request *check_request = request_queue_head;
 	struct http_pack_request *preq;
 
-	target = find_oid_pack(&request->obj->oid, repo->packs);
+	target = packfile_list_find_oid(repo->packs.head, &request->obj->oid);
 	if (!target) {
 		fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", oid_to_hex(&request->obj->oid));
 		repo->can_update_info_refs = 0;
@@ -683,7 +683,7 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
 		get_remote_object_list(obj->oid.hash[0]);
 	if (obj->flags & (REMOTE | PUSHING))
 		return 0;
-	target = find_oid_pack(&obj->oid, repo->packs);
+	target = packfile_list_find_oid(repo->packs.head, &obj->oid);
 	if (target) {
 		obj->flags |= REMOTE;
 		return 0;
@@ -1942,7 +1942,7 @@ int cmd_main(int argc, const char **argv)
 			strvec_pushf(&commit_argv, "^%s",
 				     oid_to_hex(&ref->old_oid));
 		repo_init_revisions(the_repository, &revs, setup_git_directory());
-		setup_revisions(commit_argv.nr, commit_argv.v, &revs, NULL);
+		setup_revisions_from_strvec(&commit_argv, &revs, NULL);
 		revs.edge_hint = 0; /* just in case */
 
 		/* Generate a list of objects that need to be pushed */
diff --git a/http-walker.c b/http-walker.c
index 0f7ae46..e886e64 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -15,7 +15,7 @@
 struct alt_base {
 	char *base;
 	int got_indices;
-	struct packed_git *packs;
+	struct packfile_list packs;
 	struct alt_base *next;
 };
 
@@ -324,11 +324,8 @@ static void process_alternates_response(void *callback_data)
 				} else if (is_alternate_allowed(target.buf)) {
 					warning("adding alternate object store: %s",
 						target.buf);
-					newalt = xmalloc(sizeof(*newalt));
-					newalt->next = NULL;
+					CALLOC_ARRAY(newalt, 1);
 					newalt->base = strbuf_detach(&target, NULL);
-					newalt->got_indices = 0;
-					newalt->packs = NULL;
 
 					while (tail->next != NULL)
 						tail = tail->next;
@@ -435,7 +432,7 @@ static int http_fetch_pack(struct walker *walker, struct alt_base *repo,
 
 	if (fetch_indices(walker, repo))
 		return -1;
-	target = find_oid_pack(oid, repo->packs);
+	target = packfile_list_find_oid(repo->packs.head, oid);
 	if (!target)
 		return -1;
 	close_pack_index(target);
@@ -584,17 +581,15 @@ static void cleanup(struct walker *walker)
 	if (data) {
 		alt = data->alt;
 		while (alt) {
-			struct packed_git *pack;
+			struct packfile_list_entry *e;
 
 			alt_next = alt->next;
 
-			pack = alt->packs;
-			while (pack) {
-				struct packed_git *pack_next = pack->next;
-				close_pack(pack);
-				free(pack);
-				pack = pack_next;
+			for (e = alt->packs.head; e; e = e->next) {
+				close_pack(e->pack);
+				free(e->pack);
 			}
+			packfile_list_clear(&alt->packs);
 
 			free(alt->base);
 			free(alt);
@@ -612,14 +607,11 @@ struct walker *get_http_walker(const char *url)
 	struct walker_data *data = xmalloc(sizeof(struct walker_data));
 	struct walker *walker = xmalloc(sizeof(struct walker));
 
-	data->alt = xmalloc(sizeof(*data->alt));
+	CALLOC_ARRAY(data->alt, 1);
 	data->alt->base = xstrdup(url);
 	for (s = data->alt->base + strlen(data->alt->base) - 1; *s == '/'; --s)
 		*s = 0;
 
-	data->alt->got_indices = 0;
-	data->alt->packs = NULL;
-	data->alt->next = NULL;
 	data->got_alternates = -1;
 
 	walker->corrupt_object_found = 0;
diff --git a/http.c b/http.c
index a7d55dc..41f850d 100644
--- a/http.c
+++ b/http.c
@@ -2413,8 +2413,9 @@ static char *fetch_pack_index(unsigned char *hash, const char *base_url)
 	return tmp;
 }
 
-static int fetch_and_setup_pack_index(struct packed_git **packs_head,
-	unsigned char *sha1, const char *base_url)
+static int fetch_and_setup_pack_index(struct packfile_list *packs,
+				      unsigned char *sha1,
+				      const char *base_url)
 {
 	struct packed_git *new_pack, *p;
 	char *tmp_idx = NULL;
@@ -2424,7 +2425,7 @@ static int fetch_and_setup_pack_index(struct packed_git **packs_head,
 	 * If we already have the pack locally, no need to fetch its index or
 	 * even add it to list; we already have all of its objects.
 	 */
-	for (p = get_all_packs(the_repository); p; p = p->next) {
+	repo_for_each_pack(the_repository, p) {
 		if (hasheq(p->hash, sha1, the_repository->hash_algo))
 			return 0;
 	}
@@ -2448,12 +2449,11 @@ static int fetch_and_setup_pack_index(struct packed_git **packs_head,
 	if (ret)
 		return -1;
 
-	new_pack->next = *packs_head;
-	*packs_head = new_pack;
+	packfile_list_prepend(packs, new_pack);
 	return 0;
 }
 
-int http_get_info_packs(const char *base_url, struct packed_git **packs_head)
+int http_get_info_packs(const char *base_url, struct packfile_list *packs)
 {
 	struct http_get_options options = {0};
 	int ret = 0;
@@ -2477,7 +2477,7 @@ int http_get_info_packs(const char *base_url, struct packed_git **packs_head)
 		    !parse_oid_hex(data, &oid, &data) &&
 		    skip_prefix(data, ".pack", &data) &&
 		    (*data == '\n' || *data == '\0')) {
-			fetch_and_setup_pack_index(packs_head, oid.hash, base_url);
+			fetch_and_setup_pack_index(packs, oid.hash, base_url);
 		} else {
 			data = strchrnul(data, '\n');
 		}
@@ -2541,15 +2541,10 @@ int finish_http_pack_request(struct http_pack_request *preq)
 }
 
 void http_install_packfile(struct packed_git *p,
-			   struct packed_git **list_to_remove_from)
+			   struct packfile_list *list_to_remove_from)
 {
-	struct packed_git **lst = list_to_remove_from;
-
-	while (*lst != p)
-		lst = &((*lst)->next);
-	*lst = (*lst)->next;
-
-	install_packed_git(the_repository, p);
+	packfile_list_remove(list_to_remove_from, p);
+	packfile_store_add_pack(the_repository->objects->packfiles, p);
 }
 
 struct http_pack_request *new_http_pack_request(
diff --git a/http.h b/http.h
index 0a36dbd..f9d4593 100644
--- a/http.h
+++ b/http.h
@@ -2,6 +2,7 @@
 #define HTTP_H
 
 struct packed_git;
+struct packfile_list;
 
 #include "git-zlib.h"
 
@@ -190,7 +191,7 @@ struct curl_slist *http_append_auth_header(const struct credential *c,
 
 /* Helpers for fetching packs */
 int http_get_info_packs(const char *base_url,
-			struct packed_git **packs_head);
+			struct packfile_list *packs);
 
 /* Helper for getting Accept-Language header */
 const char *http_get_accept_language_header(void);
@@ -220,13 +221,13 @@ int finish_http_pack_request(struct http_pack_request *preq);
 void release_http_pack_request(struct http_pack_request *preq);
 
 /*
- * Remove p from the given list, and invoke install_packed_git() on it.
+ * Remove p from the given list, and invoke packfile_store_add_pack() on it.
  *
  * This is a convenience function for users that have obtained a list of packs
  * from http_get_info_packs() and have chosen a specific pack to fetch.
  */
 void http_install_packfile(struct packed_git *p,
-			   struct packed_git **list_to_remove_from);
+			   struct packfile_list *list_to_remove_from);
 
 /* Helpers for fetching object */
 struct http_object_request {
diff --git a/imap-send.c b/imap-send.c
index 1de4dd2..26dda7f 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -1442,14 +1442,24 @@ static int count_messages(struct strbuf *all_msgs)
 
 	while (1) {
 		if (starts_with(p, "From ")) {
-			p = strstr(p+5, "\nFrom: ");
-			if (!p) break;
-			p = strstr(p+7, "\nDate: ");
-			if (!p) break;
-			p = strstr(p+7, "\nSubject: ");
-			if (!p) break;
-			p += 10;
-			count++;
+			if (starts_with(p, "From git-send-email")) {
+				p = strstr(p+5, "\nFrom: ");
+				if (!p) break;
+				p += 7;
+				p = strstr(p, "\nTo: ");
+				if (!p) break;
+				p += 5;
+				count++;
+			} else {
+				p = strstr(p+5, "\nFrom: ");
+				if (!p) break;
+				p = strstr(p+7, "\nDate: ");
+				if (!p) break;
+				p = strstr(p+7, "\nSubject: ");
+				if (!p) break;
+				p += 10;
+				count++;
+			}
 		}
 		p = strstr(p+5, "\nFrom ");
 		if (!p)
diff --git a/line-log.c b/line-log.c
index 8ab28cf..8bd4221 100644
--- a/line-log.c
+++ b/line-log.c
@@ -1096,13 +1096,6 @@ static struct diff_filepair *diff_filepair_dup(struct diff_filepair *pair)
 	return new_filepair;
 }
 
-static void free_diffqueues(int n, struct diff_queue_struct *dq)
-{
-	for (int i = 0; i < n; i++)
-		diff_queue_clear(&dq[i]);
-	free(dq);
-}
-
 static int process_all_files(struct line_log_data **range_out,
 			     struct rev_info *rev,
 			     struct diff_queue_struct *queue,
@@ -1198,7 +1191,7 @@ static int process_ranges_ordinary_commit(struct rev_info *rev, struct commit *c
 					  struct line_log_data *range)
 {
 	struct commit *parent = NULL;
-	struct diff_queue_struct queue;
+	struct diff_queue_struct queue = DIFF_QUEUE_INIT;
 	struct line_log_data *parent_range;
 	int changed;
 
@@ -1218,9 +1211,7 @@ static int process_ranges_ordinary_commit(struct rev_info *rev, struct commit *c
 static int process_ranges_merge_commit(struct rev_info *rev, struct commit *commit,
 				       struct line_log_data *range)
 {
-	struct diff_queue_struct *diffqueues;
 	struct line_log_data **cand;
-	struct commit **parents;
 	struct commit_list *p;
 	int i;
 	int nparents = commit_list_count(commit->parents);
@@ -1229,28 +1220,27 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
 	if (nparents > 1 && rev->first_parent_only)
 		nparents = 1;
 
-	ALLOC_ARRAY(diffqueues, nparents);
 	CALLOC_ARRAY(cand, nparents);
-	ALLOC_ARRAY(parents, nparents);
 
-	p = commit->parents;
-	for (i = 0; i < nparents; i++) {
-		parents[i] = p->item;
-		p = p->next;
-		queue_diffs(range, &rev->diffopt, &diffqueues[i], commit, parents[i]);
-	}
-
-	for (i = 0; i < nparents; i++) {
+	for (p = commit->parents, i = 0;
+	     p && i < nparents;
+	     p = p->next, i++) {
+		struct commit *parent = p->item;
+		struct diff_queue_struct diffqueue = DIFF_QUEUE_INIT;
 		int changed;
-		changed = process_all_files(&cand[i], rev, &diffqueues[i], range);
+
+		queue_diffs(range, &rev->diffopt, &diffqueue, commit, parent);
+
+		changed = process_all_files(&cand[i], rev, &diffqueue, range);
+		diff_queue_clear(&diffqueue);
 		if (!changed) {
 			/*
 			 * This parent can take all the blame, so we
 			 * don't follow any other path in history
 			 */
-			add_line_range(rev, parents[i], cand[i]);
+			add_line_range(rev, parent, cand[i]);
 			free_commit_list(commit->parents);
-			commit_list_append(parents[i], &commit->parents);
+			commit_list_append(parent, &commit->parents);
 
 			ret = 0;
 			goto out;
@@ -1261,14 +1251,15 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
 	 * No single parent took the blame.  We add the candidates
 	 * from the above loop to the parents.
 	 */
-	for (i = 0; i < nparents; i++)
-		add_line_range(rev, parents[i], cand[i]);
+	for (p = commit->parents, i = 0;
+	     p && i < nparents;
+	     p = p->next, i++)
+		add_line_range(rev, p->item, cand[i]);
 
 	ret = 1;
 
 out:
 	clear_commit_line_range(rev, commit);
-	free(parents);
 	for (i = 0; i < nparents; i++) {
 		if (!cand[i])
 			continue;
@@ -1276,7 +1267,6 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
 		free(cand[i]);
 	}
 	free(cand);
-	free_diffqueues(nparents, diffqueues);
 	return ret;
 
 	/* NEEDSWORK evil merge detection stuff */
@@ -1292,10 +1282,10 @@ int line_log_process_ranges_arbitrary_commit(struct rev_info *rev, struct commit
 			struct line_log_data *prange = line_log_data_copy(range);
 			add_line_range(rev, commit->parents->item, prange);
 			clear_commit_line_range(rev, commit);
-		} else if (!commit->parents || !commit->parents->next)
-			changed = process_ranges_ordinary_commit(rev, commit, range);
-		else
+		} else if (commit->parents && commit->parents->next)
 			changed = process_ranges_merge_commit(rev, commit, range);
+		else
+			changed = process_ranges_ordinary_commit(rev, commit, range);
 	}
 
 	if (!changed)
diff --git a/list-objects-filter.c b/list-objects-filter.c
index 7ecd4d9..acd65eb 100644
--- a/list-objects-filter.c
+++ b/list-objects-filter.c
@@ -524,12 +524,11 @@ static void filter_sparse_oid__init(
 	struct filter *filter)
 {
 	struct filter_sparse_data *d = xcalloc(1, sizeof(*d));
-	struct object_context oc;
 	struct object_id sparse_oid;
 
-	if (get_oid_with_context(the_repository,
-				 filter_options->sparse_oid_name,
-				 GET_OID_BLOB, &sparse_oid, &oc))
+	if (repo_get_oid_with_flags(the_repository,
+				    filter_options->sparse_oid_name,
+				    &sparse_oid, GET_OID_BLOB))
 		die(_("unable to access sparse blob in '%s'"),
 		    filter_options->sparse_oid_name);
 	if (add_patterns_from_blob_to_list(&sparse_oid, "", 0, &d->pl) < 0)
@@ -544,8 +543,6 @@ static void filter_sparse_oid__init(
 	filter->filter_data = d;
 	filter->filter_object_fn = filter_sparse;
 	filter->free_fn = filter_sparse_free;
-
-	object_context_release(&oc);
 }
 
 /*
diff --git a/log-tree.c b/log-tree.c
index 233bf9f..1729b0c 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -57,7 +57,7 @@ static const char *color_decorate_slots[] = {
 	[DECORATION_GRAFTED]	= "grafted",
 };
 
-static const char *decorate_get_color(int decorate_use_color, enum decoration_type ix)
+static const char *decorate_get_color(enum git_colorbool decorate_use_color, enum decoration_type ix)
 {
 	if (want_color(decorate_use_color))
 		return decoration_colors[ix];
@@ -147,9 +147,7 @@ static int ref_filter_match(const char *refname,
 	return 1;
 }
 
-static int add_ref_decoration(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			      int flags UNUSED,
-			      void *cb_data)
+static int add_ref_decoration(const struct reference *ref, void *cb_data)
 {
 	int i;
 	struct object *obj;
@@ -158,16 +156,16 @@ static int add_ref_decoration(const char *refname, const char *referent UNUSED,
 	struct decoration_filter *filter = (struct decoration_filter *)cb_data;
 	const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
 
-	if (filter && !ref_filter_match(refname, filter))
+	if (filter && !ref_filter_match(ref->name, filter))
 		return 0;
 
-	if (starts_with(refname, git_replace_ref_base)) {
+	if (starts_with(ref->name, git_replace_ref_base)) {
 		struct object_id original_oid;
 		if (!replace_refs_enabled(the_repository))
 			return 0;
-		if (get_oid_hex(refname + strlen(git_replace_ref_base),
+		if (get_oid_hex(ref->name + strlen(git_replace_ref_base),
 				&original_oid)) {
-			warning("invalid replace ref %s", refname);
+			warning("invalid replace ref %s", ref->name);
 			return 0;
 		}
 		obj = parse_object(the_repository, &original_oid);
@@ -176,10 +174,10 @@ static int add_ref_decoration(const char *refname, const char *referent UNUSED,
 		return 0;
 	}
 
-	objtype = odb_read_object_info(the_repository->objects, oid, NULL);
+	objtype = odb_read_object_info(the_repository->objects, ref->oid, NULL);
 	if (objtype < 0)
 		return 0;
-	obj = lookup_object_by_type(the_repository, oid, objtype);
+	obj = lookup_object_by_type(the_repository, ref->oid, objtype);
 
 	for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
 		struct ref_namespace_info *info = &ref_namespace[i];
@@ -187,24 +185,24 @@ static int add_ref_decoration(const char *refname, const char *referent UNUSED,
 		if (!info->decoration)
 			continue;
 		if (info->exact) {
-			if (!strcmp(refname, info->ref)) {
+			if (!strcmp(ref->name, info->ref)) {
 				deco_type = info->decoration;
 				break;
 			}
-		} else if (starts_with(refname, info->ref)) {
+		} else if (starts_with(ref->name, info->ref)) {
 			deco_type = info->decoration;
 			break;
 		}
 	}
 
-	add_name_decoration(deco_type, refname, obj);
+	add_name_decoration(deco_type, ref->name, obj);
 	while (obj->type == OBJ_TAG) {
 		if (!obj->parsed)
 			parse_object(the_repository, &obj->oid);
 		obj = ((struct tag *)obj)->tagged;
 		if (!obj)
 			break;
-		add_name_decoration(DECORATION_REF_TAG, refname, obj);
+		add_name_decoration(DECORATION_REF_TAG, ref->name, obj);
 	}
 	return 0;
 }
@@ -341,7 +339,7 @@ static void show_name(struct strbuf *sb, const struct name_decoration *decoratio
  */
 void format_decorations(struct strbuf *sb,
 			const struct commit *commit,
-			int use_color,
+			enum git_colorbool use_color,
 			const struct decoration_options *opts)
 {
 	const struct name_decoration *decoration;
@@ -717,7 +715,9 @@ static void show_diff_of_diff(struct rev_info *opt)
 		struct range_diff_options range_diff_opts = {
 			.creation_factor = opt->creation_factor,
 			.dual_color = 1,
-			.diffopt = &opts
+			.max_memory = RANGE_DIFF_MAX_MEMORY_DEFAULT,
+			.diffopt = &opts,
+			.log_arg = &opt->rdiff_log_arg
 		};
 
 		memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff));
diff --git a/log-tree.h b/log-tree.h
index ebe491c..07924be 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -1,6 +1,8 @@
 #ifndef LOG_TREE_H
 #define LOG_TREE_H
 
+#include "color.h"
+
 struct rev_info;
 
 struct log_info {
@@ -26,7 +28,7 @@ int log_tree_diff_flush(struct rev_info *);
 int log_tree_commit(struct rev_info *, struct commit *);
 void show_log(struct rev_info *opt);
 void format_decorations(struct strbuf *sb, const struct commit *commit,
-			int use_color, const struct decoration_options *opts);
+			enum git_colorbool use_color, const struct decoration_options *opts);
 void show_decorations(struct rev_info *opt, struct commit *commit);
 void log_write_email_headers(struct rev_info *opt, struct commit *commit,
 			     char **extra_headers_p,
diff --git a/loose.c b/loose.c
index e8ea6e7..56cf64b 100644
--- a/loose.c
+++ b/loose.c
@@ -1,6 +1,7 @@
 #include "git-compat-util.h"
 #include "hash.h"
 #include "path.h"
+#include "object-file.h"
 #include "odb.h"
 #include "hex.h"
 #include "repository.h"
@@ -48,13 +49,13 @@ static int insert_loose_map(struct odb_source *source,
 			    const struct object_id *oid,
 			    const struct object_id *compat_oid)
 {
-	struct loose_object_map *map = source->loose_map;
+	struct loose_object_map *map = source->loose->map;
 	int inserted = 0;
 
 	inserted |= insert_oid_pair(map->to_compat, oid, compat_oid);
 	inserted |= insert_oid_pair(map->to_storage, compat_oid, oid);
 	if (inserted)
-		oidtree_insert(source->loose_objects_cache, compat_oid);
+		oidtree_insert(source->loose->cache, compat_oid);
 
 	return inserted;
 }
@@ -64,11 +65,11 @@ static int load_one_loose_object_map(struct repository *repo, struct odb_source
 	struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
 	FILE *fp;
 
-	if (!source->loose_map)
-		loose_object_map_init(&source->loose_map);
-	if (!source->loose_objects_cache) {
-		ALLOC_ARRAY(source->loose_objects_cache, 1);
-		oidtree_init(source->loose_objects_cache);
+	if (!source->loose->map)
+		loose_object_map_init(&source->loose->map);
+	if (!source->loose->cache) {
+		ALLOC_ARRAY(source->loose->cache, 1);
+		oidtree_init(source->loose->cache);
 	}
 
 	insert_loose_map(source, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree);
@@ -124,7 +125,7 @@ int repo_read_loose_object_map(struct repository *repo)
 
 int repo_write_loose_object_map(struct repository *repo)
 {
-	kh_oid_map_t *map = repo->objects->sources->loose_map->to_compat;
+	kh_oid_map_t *map = repo->objects->sources->loose->map->to_compat;
 	struct lock_file lock;
 	int fd;
 	khiter_t iter;
@@ -230,7 +231,7 @@ int repo_loose_object_map_oid(struct repository *repo,
 	khiter_t pos;
 
 	for (source = repo->objects->sources; source; source = source->next) {
-		struct loose_object_map *loose_map = source->loose_map;
+		struct loose_object_map *loose_map = source->loose->map;
 		if (!loose_map)
 			continue;
 		map = (to == repo->compat_hash_algo) ?
diff --git a/ls-refs.c b/ls-refs.c
index c47acde..8641281 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -75,42 +75,42 @@ struct ls_refs_data {
 	unsigned unborn : 1;
 };
 
-static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-		    int flag, void *cb_data)
+static int send_ref(const struct reference *ref, void *cb_data)
 {
 	struct ls_refs_data *data = cb_data;
-	const char *refname_nons = strip_namespace(refname);
+	const char *refname_nons = strip_namespace(ref->name);
 
 	strbuf_reset(&data->buf);
 
-	if (ref_is_hidden(refname_nons, refname, &data->hidden_refs))
+	if (ref_is_hidden(refname_nons, ref->name, &data->hidden_refs))
 		return 0;
 
 	if (!ref_match(&data->prefixes, refname_nons))
 		return 0;
 
-	if (oid)
-		strbuf_addf(&data->buf, "%s %s", oid_to_hex(oid), refname_nons);
+	if (ref->oid)
+		strbuf_addf(&data->buf, "%s %s", oid_to_hex(ref->oid), refname_nons);
 	else
 		strbuf_addf(&data->buf, "unborn %s", refname_nons);
-	if (data->symrefs && flag & REF_ISSYMREF) {
+	if (data->symrefs && ref->flags & REF_ISSYMREF) {
+		int unused_flag;
 		struct object_id unused;
 		const char *symref_target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
-								    refname,
+								    ref->name,
 								    0,
 								    &unused,
-								    &flag);
+								    &unused_flag);
 
 		if (!symref_target)
-			die("'%s' is a symref but it is not?", refname);
+			die("'%s' is a symref but it is not?", ref->name);
 
 		strbuf_addf(&data->buf, " symref-target:%s",
 			    strip_namespace(symref_target));
 	}
 
-	if (data->peel && oid) {
+	if (data->peel && ref->oid) {
 		struct object_id peeled;
-		if (!peel_iterated_oid(the_repository, oid, &peeled))
+		if (!reference_get_peeled_oid(the_repository, ref, &peeled))
 			strbuf_addf(&data->buf, " peeled:%s", oid_to_hex(&peeled));
 	}
 
@@ -131,9 +131,17 @@ static void send_possibly_unborn_head(struct ls_refs_data *data)
 	if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), namespaced.buf, 0, &oid, &flag))
 		return; /* bad ref */
 	oid_is_null = is_null_oid(&oid);
+
 	if (!oid_is_null ||
-	    (data->unborn && data->symrefs && (flag & REF_ISSYMREF)))
-		send_ref(namespaced.buf, NULL, oid_is_null ? NULL : &oid, flag, data);
+	    (data->unborn && data->symrefs && (flag & REF_ISSYMREF))) {
+		struct reference ref = {
+			.name = namespaced.buf,
+			.oid = oid_is_null ? NULL : &oid,
+			.flags = flag,
+		};
+
+		send_ref(&ref, data);
+	}
 	strbuf_release(&namespaced);
 }
 
diff --git a/mailmap.c b/mailmap.c
index 56c7210..37fd158 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -1,5 +1,4 @@
 #define USE_THE_REPOSITORY_VARIABLE
-#define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "git-compat-util.h"
 #include "environment.h"
@@ -243,10 +242,9 @@ void clear_mailmap(struct string_list *map)
 static struct string_list_item *lookup_prefix(struct string_list *map,
 					      const char *string, size_t len)
 {
-	int i = string_list_find_insert_index(map, string, 1);
-	if (i < 0) {
-		/* exact match */
-		i = -1 - i;
+	bool exact_match;
+	size_t i = string_list_find_insert_index(map, string, &exact_match);
+	if (exact_match) {
 		if (!string[len])
 			return &map->items[i];
 		/*
@@ -267,7 +265,7 @@ static struct string_list_item *lookup_prefix(struct string_list *map,
 	 * overlong key would be inserted, which must come after the
 	 * real location of the key if one exists.
 	 */
-	while (0 <= --i && i < map->nr) {
+	while (i-- && i < map->nr) {
 		int cmp = strncasecmp(map->items[i].string, string, len);
 		if (cmp < 0)
 			/*
diff --git a/meson.build b/meson.build
index 5dd299b..1f95a06 100644
--- a/meson.build
+++ b/meson.build
@@ -220,7 +220,7 @@
   # learned to define __STDC_VERSION__ with C11 and later. We thus require
   # GNU C99 and fall back to C11. Meson only learned to handle the fallback
   # with version 1.3.0, so on older versions we use GNU C99 unconditionally.
-  default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'],
+  default_options: meson.version().version_compare('>=1.3.0') ? ['rust_std=2018', 'c_std=gnu99,c11'] : ['rust_std=2018', 'c_std=gnu99'],
 )
 
 fs = import('fs')
@@ -287,7 +287,6 @@
   'blob.c',
   'bloom.c',
   'branch.c',
-  'bulk-checkin.c',
   'bundle-uri.c',
   'bundle.c',
   'cache-tree.c',
@@ -407,6 +406,7 @@
   'pack-check.c',
   'pack-mtimes.c',
   'pack-objects.c',
+  'pack-refs.c',
   'pack-revindex.c',
   'pack-write.c',
   'packfile.c',
@@ -452,6 +452,7 @@
   'reftable/error.c',
   'reftable/block.c',
   'reftable/blocksource.c',
+  'reftable/fsck.c',
   'reftable/iter.c',
   'reftable/merged.c',
   'reftable/pq.c',
@@ -462,6 +463,12 @@
   'reftable/tree.c',
   'reftable/writer.c',
   'remote.c',
+  'repack.c',
+  'repack-cruft.c',
+  'repack-filtered.c',
+  'repack-geometry.c',
+  'repack-midx.c',
+  'repack-promisor.c',
   'replace-object.c',
   'repo-settings.c',
   'repository.c',
@@ -522,7 +529,6 @@
   'usage.c',
   'userdiff.c',
   'utf8.c',
-  'varint.c',
   'version.c',
   'versioncmp.c',
   'walker.c',
@@ -607,6 +613,7 @@
   'builtin/index-pack.c',
   'builtin/init-db.c',
   'builtin/interpret-trailers.c',
+  'builtin/last-modified.c',
   'builtin/log.c',
   'builtin/ls-files.c',
   'builtin/ls-remote.c',
@@ -645,6 +652,7 @@
   'builtin/repack.c',
   'builtin/replace.c',
   'builtin/replay.c',
+  'builtin/repo.c',
   'builtin/rerere.c',
   'builtin/reset.c',
   'builtin/rev-list.c',
@@ -760,13 +768,18 @@
   test_output_directory = meson.project_build_root() / 'test-output'
 endif
 
+htmldir = get_option('htmldir')
+if htmldir == ''
+  htmldir = get_option('datadir') / 'doc/git-doc'
+endif
+
 # These variables are used for building libgit.a.
 libgit_c_args = [
   '-DBINDIR="' + get_option('bindir') + '"',
   '-DDEFAULT_GIT_TEMPLATE_DIR="' + get_option('datadir') / 'git-core/templates' + '"',
   '-DFALLBACK_RUNTIME_PREFIX="' + get_option('prefix') + '"',
   '-DGIT_HOST_CPU="' + host_machine.cpu_family() + '"',
-  '-DGIT_HTML_PATH="' + get_option('datadir') / 'doc/git-doc"',
+  '-DGIT_HTML_PATH="' + htmldir + '"',
   '-DGIT_INFO_PATH="' + get_option('infodir') + '"',
   '-DGIT_LOCALE_PATH="' + get_option('localedir') + '"',
   '-DGIT_MAN_PATH="' + get_option('mandir') + '"',
@@ -1701,6 +1714,21 @@
 )
 libgit_sources += version_def_h
 
+cargo = find_program('cargo', dirs: program_path, native: true, required: get_option('rust'))
+rust_option = get_option('rust').disable_auto_if(not cargo.found())
+if rust_option.allowed()
+  subdir('src')
+  libgit_c_args += '-DWITH_RUST'
+
+  if host_machine.system() == 'windows'
+    libgit_dependencies += compiler.find_library('userenv')
+  endif
+else
+  libgit_sources += [
+    'varint.c',
+  ]
+endif
+
 libgit = declare_dependency(
   link_with: static_library('git',
     sources: libgit_sources,
@@ -2099,11 +2127,20 @@
 
 subdir('bin-wrappers')
 if get_option('docs') != []
+  doc_targets = []
   subdir('Documentation')
+else
+  docs_backend = 'none'
 endif
 
 subdir('contrib')
 
+# Note that the target is intentionally configured after including the
+# 'contrib' directory, as some tool there also have their own manpages.
+if get_option('docs') != []
+  alias_target('docs', doc_targets)
+endif
+
 exclude_from_check_headers = [
   'compat/',
   'unicode-width.h',
@@ -2238,10 +2275,12 @@
   'pcre2': pcre2,
   'perl': perl_features_enabled,
   'python': target_python.found(),
+  'rust': rust_option.allowed(),
 }, section: 'Auto-detected features', bool_yn: true)
 
 summary({
   'csprng': csprng_backend,
+  'docs': docs_backend,
   'https': https_backend,
   'sha1': sha1_backend,
   'sha1_unsafe': sha1_unsafe_backend,
diff --git a/meson_options.txt b/meson_options.txt
index 1668f26..e0be260 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,4 +1,6 @@
 # Configuration for Git installation
+option('htmldir', type: 'string', value: '',
+  description: 'Directory to install HTML docs to. Defaults to <datadir>/doc/git-doc')
 option('perllibdir', type: 'string', value: '',
   description: 'Directory to install perl lib to. Defaults to <datadir>/perl5')
 
@@ -71,6 +73,8 @@
 # Build tweaks.
 option('breaking_changes', type: 'boolean', value: false,
   description: 'Enable upcoming breaking changes.')
+option('rust', type: 'feature', value: 'auto',
+  description: 'Enable building with Rust.')
 option('macos_use_homebrew_gettext', type: 'boolean', value: true,
   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')
 
diff --git a/midx-write.c b/midx-write.c
index 72189f7..23e61cb 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -25,9 +25,9 @@
 #define NO_PREFERRED_PACK (~((uint32_t)0))
 
 extern int midx_checksum_valid(struct multi_pack_index *m);
-extern void clear_midx_files_ext(const char *object_dir, const char *ext,
+extern void clear_midx_files_ext(struct odb_source *source, const char *ext,
 				 const char *keep_hash);
-extern void clear_incremental_midx_files_ext(const char *object_dir,
+extern void clear_incremental_midx_files_ext(struct odb_source *source,
 					     const char *ext,
 					     const char **keep_hashes,
 					     uint32_t hashes_nr);
@@ -111,6 +111,7 @@ struct write_midx_context {
 	struct string_list *to_include;
 
 	struct repository *repo;
+	struct odb_source *source;
 };
 
 static int should_include_pack(const struct write_midx_context *ctx,
@@ -648,7 +649,6 @@ static uint32_t *midx_pack_order(struct write_midx_context *ctx)
 }
 
 static void write_midx_reverse_index(struct write_midx_context *ctx,
-				     const char *object_dir,
 				     unsigned char *midx_hash)
 {
 	struct strbuf buf = STRBUF_INIT;
@@ -657,11 +657,10 @@ static void write_midx_reverse_index(struct write_midx_context *ctx,
 	trace2_region_enter("midx", "write_midx_reverse_index", ctx->repo);
 
 	if (ctx->incremental)
-		get_split_midx_filename_ext(ctx->repo->hash_algo, &buf,
-					    object_dir, midx_hash,
-					    MIDX_EXT_REV);
+		get_split_midx_filename_ext(ctx->source, &buf,
+					    midx_hash, MIDX_EXT_REV);
 	else
-		get_midx_filename_ext(ctx->repo->hash_algo, &buf, object_dir,
+		get_midx_filename_ext(ctx->source, &buf,
 				      midx_hash, MIDX_EXT_REV);
 
 	tmp_file = write_rev_file_order(ctx->repo, NULL, ctx->pack_order,
@@ -698,28 +697,27 @@ static void prepare_midx_packing_data(struct packing_data *pdata,
 	trace2_region_leave("midx", "prepare_midx_packing_data", ctx->repo);
 }
 
-static int add_ref_to_pending(const char *refname, const char *referent UNUSED,
-			      const struct object_id *oid,
-			      int flag, void *cb_data)
+static int add_ref_to_pending(const struct reference *ref, void *cb_data)
 {
 	struct rev_info *revs = (struct rev_info*)cb_data;
+	const struct object_id *maybe_peeled = ref->oid;
 	struct object_id peeled;
 	struct object *object;
 
-	if ((flag & REF_ISSYMREF) && (flag & REF_ISBROKEN)) {
-		warning("symbolic ref is dangling: %s", refname);
+	if ((ref->flags & REF_ISSYMREF) && (ref->flags & REF_ISBROKEN)) {
+		warning("symbolic ref is dangling: %s", ref->name);
 		return 0;
 	}
 
-	if (!peel_iterated_oid(revs->repo, oid, &peeled))
-		oid = &peeled;
+	if (!reference_get_peeled_oid(revs->repo, ref, &peeled))
+		maybe_peeled = &peeled;
 
-	object = parse_object_or_die(revs->repo, oid, refname);
+	object = parse_object_or_die(revs->repo, maybe_peeled, ref->name);
 	if (object->type != OBJ_COMMIT)
 		return 0;
 
 	add_pending_object(revs, object, "");
-	if (bitmap_is_preferred_refname(revs->repo, refname))
+	if (bitmap_is_preferred_refname(revs->repo, ref->name))
 		object->flags |= NEEDS_BITMAP;
 	return 0;
 }
@@ -836,7 +834,6 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr
 }
 
 static int write_midx_bitmap(struct write_midx_context *ctx,
-			     const char *object_dir,
 			     const unsigned char *midx_hash,
 			     struct packing_data *pdata,
 			     struct commit **commits,
@@ -852,12 +849,11 @@ static int write_midx_bitmap(struct write_midx_context *ctx,
 	trace2_region_enter("midx", "write_midx_bitmap", ctx->repo);
 
 	if (ctx->incremental)
-		get_split_midx_filename_ext(ctx->repo->hash_algo, &bitmap_name,
-					    object_dir, midx_hash,
-					    MIDX_EXT_BITMAP);
+		get_split_midx_filename_ext(ctx->source, &bitmap_name,
+					    midx_hash, MIDX_EXT_BITMAP);
 	else
-		get_midx_filename_ext(ctx->repo->hash_algo, &bitmap_name,
-				      object_dir, midx_hash, MIDX_EXT_BITMAP);
+		get_midx_filename_ext(ctx->source, &bitmap_name,
+				      midx_hash, MIDX_EXT_BITMAP);
 
 	if (flags & MIDX_WRITE_BITMAP_HASH_CACHE)
 		options |= BITMAP_OPT_HASH_CACHE;
@@ -913,13 +909,6 @@ static int write_midx_bitmap(struct write_midx_context *ctx,
 	return ret;
 }
 
-static struct multi_pack_index *lookup_multi_pack_index(struct repository *r,
-							const char *object_dir)
-{
-	struct odb_source *source = odb_find_source(r->objects, object_dir);
-	return get_multi_pack_index(source);
-}
-
 static int fill_packs_from_midx(struct write_midx_context *ctx)
 {
 	struct multi_pack_index *m;
@@ -928,8 +917,7 @@ static int fill_packs_from_midx(struct write_midx_context *ctx)
 		uint32_t i;
 
 		for (i = 0; i < m->num_packs; i++) {
-			if (prepare_midx_pack(ctx->repo, m,
-					      m->num_packs_in_base + i))
+			if (prepare_midx_pack(m, m->num_packs_in_base + i))
 				return error(_("could not load pack"));
 
 			ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
@@ -969,10 +957,9 @@ static int link_midx_to_chain(struct multi_pack_index *m)
 	for (i = 0; i < ARRAY_SIZE(midx_exts); i++) {
 		const unsigned char *hash = get_midx_checksum(m);
 
-		get_midx_filename_ext(m->repo->hash_algo, &from, m->object_dir,
+		get_midx_filename_ext(m->source, &from,
 				      hash, midx_exts[i].non_split);
-		get_split_midx_filename_ext(m->repo->hash_algo, &to,
-					    m->object_dir, hash,
+		get_split_midx_filename_ext(m->source, &to, hash,
 					    midx_exts[i].split);
 
 		if (link(from.buf, to.buf) < 0 && errno != ENOENT) {
@@ -991,7 +978,7 @@ static int link_midx_to_chain(struct multi_pack_index *m)
 	return ret;
 }
 
-static void clear_midx_files(struct repository *r, const char *object_dir,
+static void clear_midx_files(struct odb_source *source,
 			     const char **hashes, uint32_t hashes_nr,
 			     unsigned incremental)
 {
@@ -1010,16 +997,16 @@ static void clear_midx_files(struct repository *r, const char *object_dir,
 	uint32_t i, j;
 
 	for (i = 0; i < ARRAY_SIZE(exts); i++) {
-		clear_incremental_midx_files_ext(object_dir, exts[i],
+		clear_incremental_midx_files_ext(source, exts[i],
 						 hashes, hashes_nr);
 		for (j = 0; j < hashes_nr; j++)
-			clear_midx_files_ext(object_dir, exts[i], hashes[j]);
+			clear_midx_files_ext(source, exts[i], hashes[j]);
 	}
 
 	if (incremental)
-		get_midx_filename(r->hash_algo, &buf, object_dir);
+		get_midx_filename(source, &buf);
 	else
-		get_midx_chain_filename(&buf, object_dir);
+		get_midx_chain_filename(source, &buf);
 
 	if (unlink(buf.buf) && errno != ENOENT)
 		die_errno(_("failed to clear multi-pack-index at %s"), buf.buf);
@@ -1027,13 +1014,14 @@ static void clear_midx_files(struct repository *r, const char *object_dir,
 	strbuf_release(&buf);
 }
 
-static int write_midx_internal(struct repository *r, const char *object_dir,
+static int write_midx_internal(struct odb_source *source,
 			       struct string_list *packs_to_include,
 			       struct string_list *packs_to_drop,
 			       const char *preferred_pack_name,
 			       const char *refs_snapshot,
 			       unsigned flags)
 {
+	struct repository *r = source->odb->repo;
 	struct strbuf midx_name = STRBUF_INIT;
 	unsigned char midx_hash[GIT_MAX_RAWSZ];
 	uint32_t start_pack;
@@ -1053,21 +1041,22 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 	trace2_region_enter("midx", "write_midx_internal", r);
 
 	ctx.repo = r;
+	ctx.source = source;
 
 	ctx.incremental = !!(flags & MIDX_WRITE_INCREMENTAL);
 
 	if (ctx.incremental)
 		strbuf_addf(&midx_name,
 			    "%s/pack/multi-pack-index.d/tmp_midx_XXXXXX",
-			    object_dir);
+			    source->path);
 	else
-		get_midx_filename(r->hash_algo, &midx_name, object_dir);
+		get_midx_filename(source, &midx_name);
 	if (safe_create_leading_directories(r, midx_name.buf))
 		die_errno(_("unable to create leading directories of %s"),
 			  midx_name.buf);
 
 	if (!packs_to_include || ctx.incremental) {
-		struct multi_pack_index *m = lookup_multi_pack_index(r, object_dir);
+		struct multi_pack_index *m = get_multi_pack_index(source);
 		if (m && !midx_checksum_valid(m)) {
 			warning(_("ignoring existing multi-pack-index; checksum mismatch"));
 			m = NULL;
@@ -1098,7 +1087,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 			if (flags & MIDX_WRITE_BITMAP && load_midx_revindex(m)) {
 				error(_("could not load reverse index for MIDX %s"),
 				      hash_to_hex_algop(get_midx_checksum(m),
-							m->repo->hash_algo));
+							m->source->odb->repo->hash_algo));
 				goto cleanup;
 			}
 			ctx.num_multi_pack_indexes_before++;
@@ -1119,7 +1108,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 
 	ctx.to_include = packs_to_include;
 
-	for_each_file_in_pack_dir(object_dir, add_pack_to_midx, &ctx);
+	for_each_file_in_pack_dir(source->path, add_pack_to_midx, &ctx);
 	stop_progress(&ctx.progress);
 
 	if ((ctx.m && ctx.nr == ctx.m->num_packs + ctx.m->num_packs_in_base) &&
@@ -1139,8 +1128,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 			 * corresponding bitmap (or one wasn't requested).
 			 */
 			if (!want_bitmap)
-				clear_midx_files_ext(object_dir, "bitmap", NULL);
-
+				clear_midx_files_ext(source, "bitmap", NULL);
 			result = 0;
 			goto cleanup;
 		}
@@ -1320,7 +1308,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 	if (ctx.incremental) {
 		struct strbuf lock_name = STRBUF_INIT;
 
-		get_midx_chain_filename(&lock_name, object_dir);
+		get_midx_chain_filename(source, &lock_name);
 		hold_lock_file_for_update(&lk, lock_name.buf, LOCK_DIE_ON_ERROR);
 		strbuf_release(&lock_name);
 
@@ -1383,7 +1371,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 
 	if (flags & MIDX_WRITE_REV_INDEX &&
 	    git_env_bool("GIT_TEST_MIDX_WRITE_REV", 0))
-		write_midx_reverse_index(&ctx, object_dir, midx_hash);
+		write_midx_reverse_index(&ctx, midx_hash);
 
 	if (flags & MIDX_WRITE_BITMAP) {
 		struct packing_data pdata;
@@ -1406,7 +1394,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 		FREE_AND_NULL(ctx.entries);
 		ctx.entries_nr = 0;
 
-		if (write_midx_bitmap(&ctx, object_dir,
+		if (write_midx_bitmap(&ctx,
 				      midx_hash, &pdata, commits, commits_nr,
 				      flags) < 0) {
 			error(_("could not write multi-pack bitmap"));
@@ -1441,8 +1429,8 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 		if (link_midx_to_chain(ctx.base_midx) < 0)
 			goto cleanup;
 
-		get_split_midx_filename_ext(r->hash_algo, &final_midx_name,
-					    object_dir, midx_hash, MIDX_EXT_MIDX);
+		get_split_midx_filename_ext(source, &final_midx_name,
+					    midx_hash, MIDX_EXT_MIDX);
 
 		if (rename_tempfile(&incr, final_midx_name.buf) < 0) {
 			error_errno(_("unable to rename new multi-pack-index layer"));
@@ -1475,7 +1463,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 	if (commit_lock_file(&lk) < 0)
 		die_errno(_("could not write multi-pack-index"));
 
-	clear_midx_files(r, object_dir, keep_hashes,
+	clear_midx_files(source, keep_hashes,
 			 ctx.num_multi_pack_indexes_before + 1,
 			 ctx.incremental);
 	result = 0;
@@ -1505,29 +1493,29 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
 	return result;
 }
 
-int write_midx_file(struct repository *r, const char *object_dir,
+int write_midx_file(struct odb_source *source,
 		    const char *preferred_pack_name,
 		    const char *refs_snapshot, unsigned flags)
 {
-	return write_midx_internal(r, object_dir, NULL, NULL,
+	return write_midx_internal(source, NULL, NULL,
 				   preferred_pack_name, refs_snapshot,
 				   flags);
 }
 
-int write_midx_file_only(struct repository *r, const char *object_dir,
+int write_midx_file_only(struct odb_source *source,
 			 struct string_list *packs_to_include,
 			 const char *preferred_pack_name,
 			 const char *refs_snapshot, unsigned flags)
 {
-	return write_midx_internal(r, object_dir, packs_to_include, NULL,
+	return write_midx_internal(source, packs_to_include, NULL,
 				   preferred_pack_name, refs_snapshot, flags);
 }
 
-int expire_midx_packs(struct repository *r, const char *object_dir, unsigned flags)
+int expire_midx_packs(struct odb_source *source, unsigned flags)
 {
 	uint32_t i, *count, result = 0;
 	struct string_list packs_to_drop = STRING_LIST_INIT_DUP;
-	struct multi_pack_index *m = lookup_multi_pack_index(r, object_dir);
+	struct multi_pack_index *m = get_multi_pack_index(source);
 	struct progress *progress = NULL;
 
 	if (!m)
@@ -1540,7 +1528,7 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla
 
 	if (flags & MIDX_PROGRESS)
 		progress = start_delayed_progress(
-					  r,
+					  source->odb->repo,
 					  _("Counting referenced objects"),
 					  m->num_objects);
 	for (i = 0; i < m->num_objects; i++) {
@@ -1552,7 +1540,7 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla
 
 	if (flags & MIDX_PROGRESS)
 		progress = start_delayed_progress(
-					  r,
+					  source->odb->repo,
 					  _("Finding and deleting unreferenced packfiles"),
 					  m->num_packs);
 	for (i = 0; i < m->num_packs; i++) {
@@ -1562,7 +1550,7 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla
 		if (count[i])
 			continue;
 
-		if (prepare_midx_pack(r, m, i))
+		if (prepare_midx_pack(m, i))
 			continue;
 
 		if (m->packs[i]->pack_keep || m->packs[i]->is_cruft)
@@ -1580,7 +1568,7 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla
 	free(count);
 
 	if (packs_to_drop.nr)
-		result = write_midx_internal(r, object_dir, NULL,
+		result = write_midx_internal(source, NULL,
 					     &packs_to_drop, NULL, NULL, flags);
 
 	string_list_clear(&packs_to_drop, 0);
@@ -1608,13 +1596,12 @@ static int compare_by_mtime(const void *a_, const void *b_)
 	return 0;
 }
 
-static int want_included_pack(struct repository *r,
-			      struct multi_pack_index *m,
+static int want_included_pack(struct multi_pack_index *m,
 			      int pack_kept_objects,
 			      uint32_t pack_int_id)
 {
 	struct packed_git *p;
-	if (prepare_midx_pack(r, m, pack_int_id))
+	if (prepare_midx_pack(m, pack_int_id))
 		return 0;
 	p = m->packs[pack_int_id];
 	if (!pack_kept_objects && p->pack_keep)
@@ -1636,7 +1623,7 @@ static void fill_included_packs_all(struct repository *r,
 	repo_config_get_bool(r, "repack.packkeptobjects", &pack_kept_objects);
 
 	for (i = 0; i < m->num_packs; i++) {
-		if (!want_included_pack(r, m, pack_kept_objects, i))
+		if (!want_included_pack(m, pack_kept_objects, i))
 			continue;
 
 		include_pack[i] = 1;
@@ -1660,7 +1647,7 @@ static void fill_included_packs_batch(struct repository *r,
 	for (i = 0; i < m->num_packs; i++) {
 		pack_info[i].pack_int_id = i;
 
-		if (prepare_midx_pack(r, m, i))
+		if (prepare_midx_pack(m, i))
 			continue;
 
 		pack_info[i].mtime = m->packs[i]->mtime;
@@ -1679,7 +1666,7 @@ static void fill_included_packs_batch(struct repository *r,
 		struct packed_git *p = m->packs[pack_int_id];
 		uint64_t expected_size;
 
-		if (!want_included_pack(r, m, pack_kept_objects, pack_int_id))
+		if (!want_included_pack(m, pack_kept_objects, pack_int_id))
 			continue;
 
 		/*
@@ -1706,14 +1693,15 @@ static void fill_included_packs_batch(struct repository *r,
 	free(pack_info);
 }
 
-int midx_repack(struct repository *r, const char *object_dir, size_t batch_size, unsigned flags)
+int midx_repack(struct odb_source *source, size_t batch_size, unsigned flags)
 {
+	struct repository *r = source->odb->repo;
 	int result = 0;
 	uint32_t i, packs_to_repack = 0;
 	unsigned char *include_pack;
 	struct child_process cmd = CHILD_PROCESS_INIT;
 	FILE *cmd_in;
-	struct multi_pack_index *m = lookup_multi_pack_index(r, object_dir);
+	struct multi_pack_index *m = get_multi_pack_index(source);
 
 	/*
 	 * When updating the default for these configuration
@@ -1747,7 +1735,7 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
 
 	strvec_push(&cmd.args, "pack-objects");
 
-	strvec_pushf(&cmd.args, "%s/pack/pack", object_dir);
+	strvec_pushf(&cmd.args, "%s/pack/pack", source->path);
 
 	if (delta_base_offset)
 		strvec_push(&cmd.args, "--delta-base-offset");
@@ -1788,7 +1776,7 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
 		goto cleanup;
 	}
 
-	result = write_midx_internal(r, object_dir, NULL, NULL, NULL, NULL,
+	result = write_midx_internal(source, NULL, NULL, NULL, NULL,
 				     flags);
 
 cleanup:
diff --git a/midx.c b/midx.c
index 7d40768..24e1e72 100644
--- a/midx.c
+++ b/midx.c
@@ -16,9 +16,9 @@
 #define MIDX_PACK_ERROR ((void *)(intptr_t)-1)
 
 int midx_checksum_valid(struct multi_pack_index *m);
-void clear_midx_files_ext(const char *object_dir, const char *ext,
+void clear_midx_files_ext(struct odb_source *source, const char *ext,
 			  const char *keep_hash);
-void clear_incremental_midx_files_ext(const char *object_dir, const char *ext,
+void clear_incremental_midx_files_ext(struct odb_source *source, const char *ext,
 				      char **keep_hashes,
 				      uint32_t hashes_nr);
 int cmp_idx_or_pack_name(const char *idx_or_pack_name,
@@ -26,22 +26,20 @@ int cmp_idx_or_pack_name(const char *idx_or_pack_name,
 
 const unsigned char *get_midx_checksum(struct multi_pack_index *m)
 {
-	return m->data + m->data_len - m->repo->hash_algo->rawsz;
+	return m->data + m->data_len - m->source->odb->repo->hash_algo->rawsz;
 }
 
-void get_midx_filename(const struct git_hash_algo *hash_algo,
-		       struct strbuf *out, const char *object_dir)
+void get_midx_filename(struct odb_source *source, struct strbuf *out)
 {
-	get_midx_filename_ext(hash_algo, out, object_dir, NULL, NULL);
+	get_midx_filename_ext(source, out, NULL, NULL);
 }
 
-void get_midx_filename_ext(const struct git_hash_algo *hash_algo,
-			   struct strbuf *out, const char *object_dir,
+void get_midx_filename_ext(struct odb_source *source, struct strbuf *out,
 			   const unsigned char *hash, const char *ext)
 {
-	strbuf_addf(out, "%s/pack/multi-pack-index", object_dir);
+	strbuf_addf(out, "%s/pack/multi-pack-index", source->path);
 	if (ext)
-		strbuf_addf(out, "-%s.%s", hash_to_hex_algop(hash, hash_algo), ext);
+		strbuf_addf(out, "-%s.%s", hash_to_hex_algop(hash, source->odb->repo->hash_algo), ext);
 }
 
 static int midx_read_oid_fanout(const unsigned char *chunk_start,
@@ -95,11 +93,16 @@ static int midx_read_object_offsets(const unsigned char *chunk_start,
 	return 0;
 }
 
-static struct multi_pack_index *load_multi_pack_index_one(struct repository *r,
-							  const char *object_dir,
-							  const char *midx_name,
-							  int local)
+struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
 {
+	packfile_store_prepare(source->odb->packfiles);
+	return source->midx;
+}
+
+static struct multi_pack_index *load_multi_pack_index_one(struct odb_source *source,
+							  const char *midx_name)
+{
+	struct repository *r = source->odb->repo;
 	struct multi_pack_index *m = NULL;
 	int fd;
 	struct stat st;
@@ -129,11 +132,10 @@ static struct multi_pack_index *load_multi_pack_index_one(struct repository *r,
 	midx_map = xmmap(NULL, midx_size, PROT_READ, MAP_PRIVATE, fd, 0);
 	close(fd);
 
-	FLEX_ALLOC_STR(m, object_dir, object_dir);
+	CALLOC_ARRAY(m, 1);
 	m->data = midx_map;
 	m->data_len = midx_size;
-	m->local = local;
-	m->repo = r;
+	m->source = source;
 
 	m->signature = get_be32(m->data);
 	if (m->signature != MIDX_SIGNATURE)
@@ -224,24 +226,23 @@ static struct multi_pack_index *load_multi_pack_index_one(struct repository *r,
 	return NULL;
 }
 
-void get_midx_chain_dirname(struct strbuf *buf, const char *object_dir)
+void get_midx_chain_dirname(struct odb_source *source, struct strbuf *buf)
 {
-	strbuf_addf(buf, "%s/pack/multi-pack-index.d", object_dir);
+	strbuf_addf(buf, "%s/pack/multi-pack-index.d", source->path);
 }
 
-void get_midx_chain_filename(struct strbuf *buf, const char *object_dir)
+void get_midx_chain_filename(struct odb_source *source, struct strbuf *buf)
 {
-	get_midx_chain_dirname(buf, object_dir);
+	get_midx_chain_dirname(source, buf);
 	strbuf_addstr(buf, "/multi-pack-index-chain");
 }
 
-void get_split_midx_filename_ext(const struct git_hash_algo *hash_algo,
-				 struct strbuf *buf, const char *object_dir,
+void get_split_midx_filename_ext(struct odb_source *source, struct strbuf *buf,
 				 const unsigned char *hash, const char *ext)
 {
-	get_midx_chain_dirname(buf, object_dir);
+	get_midx_chain_dirname(source, buf);
 	strbuf_addf(buf, "/multi-pack-index-%s.%s",
-		    hash_to_hex_algop(hash, hash_algo), ext);
+		    hash_to_hex_algop(hash, source->odb->repo->hash_algo), ext);
 }
 
 static int open_multi_pack_index_chain(const struct git_hash_algo *hash_algo,
@@ -297,19 +298,18 @@ static int add_midx_to_chain(struct multi_pack_index *midx,
 	return 1;
 }
 
-static struct multi_pack_index *load_midx_chain_fd_st(struct repository *r,
-						      const char *object_dir,
-						      int local,
+static struct multi_pack_index *load_midx_chain_fd_st(struct odb_source *source,
 						      int fd, struct stat *st,
 						      int *incomplete_chain)
 {
+	const struct git_hash_algo *hash_algo = source->odb->repo->hash_algo;
 	struct multi_pack_index *midx_chain = NULL;
 	struct strbuf buf = STRBUF_INIT;
 	int valid = 1;
 	uint32_t i, count;
 	FILE *fp = xfdopen(fd, "r");
 
-	count = st->st_size / (r->hash_algo->hexsz + 1);
+	count = st->st_size / (hash_algo->hexsz + 1);
 
 	for (i = 0; i < count; i++) {
 		struct multi_pack_index *m;
@@ -318,7 +318,7 @@ static struct multi_pack_index *load_midx_chain_fd_st(struct repository *r,
 		if (strbuf_getline_lf(&buf, fp) == EOF)
 			break;
 
-		if (get_oid_hex_algop(buf.buf, &layer, r->hash_algo)) {
+		if (get_oid_hex_algop(buf.buf, &layer, hash_algo)) {
 			warning(_("invalid multi-pack-index chain: line '%s' "
 				  "not a hash"),
 				buf.buf);
@@ -329,9 +329,9 @@ static struct multi_pack_index *load_midx_chain_fd_st(struct repository *r,
 		valid = 0;
 
 		strbuf_reset(&buf);
-		get_split_midx_filename_ext(r->hash_algo, &buf, object_dir,
+		get_split_midx_filename_ext(source, &buf,
 					    layer.hash, MIDX_EXT_MIDX);
-		m = load_multi_pack_index_one(r, object_dir, buf.buf, local);
+		m = load_multi_pack_index_one(source, buf.buf);
 
 		if (m) {
 			if (add_midx_to_chain(m, midx_chain)) {
@@ -354,40 +354,34 @@ static struct multi_pack_index *load_midx_chain_fd_st(struct repository *r,
 	return midx_chain;
 }
 
-static struct multi_pack_index *load_multi_pack_index_chain(struct repository *r,
-							    const char *object_dir,
-							    int local)
+static struct multi_pack_index *load_multi_pack_index_chain(struct odb_source *source)
 {
 	struct strbuf chain_file = STRBUF_INIT;
 	struct stat st;
 	int fd;
 	struct multi_pack_index *m = NULL;
 
-	get_midx_chain_filename(&chain_file, object_dir);
-	if (open_multi_pack_index_chain(r->hash_algo, chain_file.buf, &fd, &st)) {
+	get_midx_chain_filename(source, &chain_file);
+	if (open_multi_pack_index_chain(source->odb->repo->hash_algo, chain_file.buf, &fd, &st)) {
 		int incomplete;
 		/* ownership of fd is taken over by load function */
-		m = load_midx_chain_fd_st(r, object_dir, local, fd, &st,
-					  &incomplete);
+		m = load_midx_chain_fd_st(source, fd, &st, &incomplete);
 	}
 
 	strbuf_release(&chain_file);
 	return m;
 }
 
-struct multi_pack_index *load_multi_pack_index(struct repository *r,
-					       const char *object_dir,
-					       int local)
+struct multi_pack_index *load_multi_pack_index(struct odb_source *source)
 {
 	struct strbuf midx_name = STRBUF_INIT;
 	struct multi_pack_index *m;
 
-	get_midx_filename(r->hash_algo, &midx_name, object_dir);
+	get_midx_filename(source, &midx_name);
 
-	m = load_multi_pack_index_one(r, object_dir,
-				      midx_name.buf, local);
+	m = load_multi_pack_index_one(source, midx_name.buf);
 	if (!m)
-		m = load_multi_pack_index_chain(r, object_dir, local);
+		m = load_multi_pack_index_chain(source);
 
 	strbuf_release(&midx_name);
 
@@ -450,11 +444,11 @@ static uint32_t midx_for_pack(struct multi_pack_index **_m,
 	return pack_int_id - m->num_packs_in_base;
 }
 
-int prepare_midx_pack(struct repository *r, struct multi_pack_index *m,
+int prepare_midx_pack(struct multi_pack_index *m,
 		      uint32_t pack_int_id)
 {
+	struct repository *r = m->source->odb->repo;
 	struct strbuf pack_name = STRBUF_INIT;
-	struct strbuf key = STRBUF_INIT;
 	struct packed_git *p;
 
 	pack_int_id = midx_for_pack(&m, pack_int_id);
@@ -464,26 +458,11 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m,
 	if (m->packs[pack_int_id])
 		return 0;
 
-	strbuf_addf(&pack_name, "%s/pack/%s", m->object_dir,
+	strbuf_addf(&pack_name, "%s/pack/%s", m->source->path,
 		    m->pack_names[pack_int_id]);
-
-	/* pack_map holds the ".pack" name, but we have the .idx */
-	strbuf_addbuf(&key, &pack_name);
-	strbuf_strip_suffix(&key, ".idx");
-	strbuf_addstr(&key, ".pack");
-	p = hashmap_get_entry_from_hash(&r->objects->pack_map,
-					strhash(key.buf), key.buf,
-					struct packed_git, packmap_ent);
-	if (!p) {
-		p = add_packed_git(r, pack_name.buf, pack_name.len, m->local);
-		if (p) {
-			install_packed_git(r, p);
-			list_add_tail(&p->mru, &r->objects->packed_git_mru);
-		}
-	}
-
+	p = packfile_store_load_pack(r->objects->packfiles,
+				     pack_name.buf, m->source->local);
 	strbuf_release(&pack_name);
-	strbuf_release(&key);
 
 	if (!p) {
 		m->packs[pack_int_id] = MIDX_PACK_ERROR;
@@ -507,7 +486,7 @@ struct packed_git *nth_midxed_pack(struct multi_pack_index *m,
 
 #define MIDX_CHUNK_BITMAPPED_PACKS_WIDTH (2 * sizeof(uint32_t))
 
-int nth_bitmapped_pack(struct repository *r, struct multi_pack_index *m,
+int nth_bitmapped_pack(struct multi_pack_index *m,
 		       struct bitmapped_pack *bp, uint32_t pack_int_id)
 {
 	uint32_t local_pack_int_id = midx_for_pack(&m, pack_int_id);
@@ -515,7 +494,7 @@ int nth_bitmapped_pack(struct repository *r, struct multi_pack_index *m,
 	if (!m->chunk_bitmapped_packs)
 		return error(_("MIDX does not contain the BTMP chunk"));
 
-	if (prepare_midx_pack(r, m, pack_int_id))
+	if (prepare_midx_pack(m, pack_int_id))
 		return error(_("could not load bitmapped pack %"PRIu32), pack_int_id);
 
 	bp->p = m->packs[local_pack_int_id];
@@ -534,7 +513,8 @@ int bsearch_one_midx(const struct object_id *oid, struct multi_pack_index *m,
 		     uint32_t *result)
 {
 	int ret = bsearch_hash(oid->hash, m->chunk_oid_fanout,
-			       m->chunk_oid_lookup, m->repo->hash_algo->rawsz,
+			       m->chunk_oid_lookup,
+			       m->source->odb->repo->hash_algo->rawsz,
 			       result);
 	if (result)
 		*result += m->num_objects_in_base;
@@ -565,7 +545,7 @@ struct object_id *nth_midxed_object_oid(struct object_id *oid,
 	n = midx_for_object(&m, n);
 
 	oidread(oid, m->chunk_oid_lookup + st_mult(m->hash_len, n),
-		m->repo->hash_algo);
+		m->source->odb->repo->hash_algo);
 	return oid;
 }
 
@@ -600,10 +580,9 @@ uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos)
 					       (off_t)pos * MIDX_CHUNK_OFFSET_WIDTH);
 }
 
-int fill_midx_entry(struct repository *r,
+int fill_midx_entry(struct multi_pack_index *m,
 		    const struct object_id *oid,
-		    struct pack_entry *e,
-		    struct multi_pack_index *m)
+		    struct pack_entry *e)
 {
 	uint32_t pos;
 	uint32_t pack_int_id;
@@ -615,7 +594,7 @@ int fill_midx_entry(struct repository *r,
 	midx_for_object(&m, pos);
 	pack_int_id = nth_midxed_pack_int_id(m, pos);
 
-	if (prepare_midx_pack(r, m, pack_int_id))
+	if (prepare_midx_pack(m, pack_int_id))
 		return 0;
 	p = m->packs[pack_int_id - m->num_packs_in_base];
 
@@ -723,7 +702,7 @@ int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id)
 	return 0;
 }
 
-int prepare_multi_pack_index_one(struct odb_source *source, int local)
+int prepare_multi_pack_index_one(struct odb_source *source)
 {
 	struct repository *r = source->odb->repo;
 
@@ -734,14 +713,14 @@ int prepare_multi_pack_index_one(struct odb_source *source, int local)
 	if (source->midx)
 		return 1;
 
-	source->midx = load_multi_pack_index(r, source->path, local);
+	source->midx = load_multi_pack_index(source);
 
 	return !!source->midx;
 }
 
 int midx_checksum_valid(struct multi_pack_index *m)
 {
-	return hashfile_checksum_valid(m->repo->hash_algo,
+	return hashfile_checksum_valid(m->source->odb->repo->hash_algo,
 				       m->data, m->data_len);
 }
 
@@ -768,7 +747,7 @@ static void clear_midx_file_ext(const char *full_path, size_t full_path_len UNUS
 		die_errno(_("failed to remove %s"), full_path);
 }
 
-void clear_midx_files_ext(const char *object_dir, const char *ext,
+void clear_midx_files_ext(struct odb_source *source, const char *ext,
 			  const char *keep_hash)
 {
 	struct clear_midx_data data;
@@ -782,7 +761,7 @@ void clear_midx_files_ext(const char *object_dir, const char *ext,
 	}
 	data.ext = ext;
 
-	for_each_file_in_pack_dir(object_dir,
+	for_each_file_in_pack_dir(source->path,
 				  clear_midx_file_ext,
 				  &data);
 
@@ -791,7 +770,7 @@ void clear_midx_files_ext(const char *object_dir, const char *ext,
 	free(data.keep);
 }
 
-void clear_incremental_midx_files_ext(const char *object_dir, const char *ext,
+void clear_incremental_midx_files_ext(struct odb_source *source, const char *ext,
 				      char **keep_hashes,
 				      uint32_t hashes_nr)
 {
@@ -807,7 +786,7 @@ void clear_incremental_midx_files_ext(const char *object_dir, const char *ext,
 	data.keep_nr = hashes_nr;
 	data.ext = ext;
 
-	for_each_file_in_pack_subdir(object_dir, "multi-pack-index.d",
+	for_each_file_in_pack_subdir(source->path, "multi-pack-index.d",
 				     clear_midx_file_ext, &data);
 
 	for (i = 0; i < hashes_nr; i++)
@@ -819,7 +798,7 @@ void clear_midx_file(struct repository *r)
 {
 	struct strbuf midx = STRBUF_INIT;
 
-	get_midx_filename(r->hash_algo, &midx, r->objects->sources->path);
+	get_midx_filename(r->objects->sources, &midx);
 
 	if (r->objects) {
 		struct odb_source *source;
@@ -834,8 +813,8 @@ void clear_midx_file(struct repository *r)
 	if (remove_path(midx.buf))
 		die(_("failed to clear multi-pack-index at %s"), midx.buf);
 
-	clear_midx_files_ext(r->objects->sources->path, MIDX_EXT_BITMAP, NULL);
-	clear_midx_files_ext(r->objects->sources->path, MIDX_EXT_REV, NULL);
+	clear_midx_files_ext(r->objects->sources, MIDX_EXT_BITMAP, NULL);
+	clear_midx_files_ext(r->objects->sources, MIDX_EXT_REV, NULL);
 
 	strbuf_release(&midx);
 }
@@ -879,12 +858,13 @@ static int compare_pair_pos_vs_id(const void *_a, const void *_b)
 			display_progress(progress, _n); \
 	} while (0)
 
-int verify_midx_file(struct repository *r, const char *object_dir, unsigned flags)
+int verify_midx_file(struct odb_source *source, unsigned flags)
 {
+	struct repository *r = source->odb->repo;
 	struct pair_pos_vs_id *pairs = NULL;
 	uint32_t i;
 	struct progress *progress = NULL;
-	struct multi_pack_index *m = load_multi_pack_index(r, object_dir, 1);
+	struct multi_pack_index *m = load_multi_pack_index(source);
 	struct multi_pack_index *curr;
 	verify_midx_error = 0;
 
@@ -893,7 +873,7 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag
 		struct stat sb;
 		struct strbuf filename = STRBUF_INIT;
 
-		get_midx_filename(r->hash_algo, &filename, object_dir);
+		get_midx_filename(source, &filename);
 
 		if (!stat(filename.buf, &sb)) {
 			error(_("multi-pack-index file exists, but failed to parse"));
@@ -911,7 +891,7 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag
 						  _("Looking for referenced packfiles"),
 						  m->num_packs + m->num_packs_in_base);
 	for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) {
-		if (prepare_midx_pack(r, m, i))
+		if (prepare_midx_pack(m, i))
 			midx_report("failed to load pack in position %d", i);
 
 		display_progress(progress, i + 1);
@@ -988,7 +968,7 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag
 
 		nth_midxed_object_oid(&oid, m, pairs[i].pos);
 
-		if (!fill_midx_entry(r, &oid, &e, m)) {
+		if (!fill_midx_entry(m, &oid, &e)) {
 			midx_report(_("failed to load pack entry for oid[%d] = %s"),
 				    pairs[i].pos, oid_to_hex(&oid));
 			continue;
diff --git a/midx.h b/midx.h
index 076382d..6e54d73 100644
--- a/midx.h
+++ b/midx.h
@@ -35,6 +35,8 @@ struct odb_source;
 	"GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL"
 
 struct multi_pack_index {
+	struct odb_source *source;
+
 	const unsigned char *data;
 	size_t data_len;
 
@@ -50,7 +52,6 @@ struct multi_pack_index {
 	uint32_t num_objects;
 	int preferred_pack_idx;
 
-	int local;
 	int has_chain;
 
 	const unsigned char *chunk_pack_names;
@@ -71,10 +72,6 @@ struct multi_pack_index {
 
 	const char **pack_names;
 	struct packed_git **packs;
-
-	struct repository *repo;
-
-	char object_dir[FLEX_ARRAY];
 };
 
 #define MIDX_PROGRESS     (1 << 0)
@@ -89,24 +86,20 @@ struct multi_pack_index {
 #define MIDX_EXT_MIDX "midx"
 
 const unsigned char *get_midx_checksum(struct multi_pack_index *m);
-void get_midx_filename(const struct git_hash_algo *hash_algo,
-		       struct strbuf *out, const char *object_dir);
-void get_midx_filename_ext(const struct git_hash_algo *hash_algo,
-			   struct strbuf *out, const char *object_dir,
+void get_midx_filename(struct odb_source *source, struct strbuf *out);
+void get_midx_filename_ext(struct odb_source *source, struct strbuf *out,
 			   const unsigned char *hash, const char *ext);
-void get_midx_chain_dirname(struct strbuf *buf, const char *object_dir);
-void get_midx_chain_filename(struct strbuf *buf, const char *object_dir);
-void get_split_midx_filename_ext(const struct git_hash_algo *hash_algo,
-				 struct strbuf *buf, const char *object_dir,
+void get_midx_chain_dirname(struct odb_source *source, struct strbuf *out);
+void get_midx_chain_filename(struct odb_source *source, struct strbuf *out);
+void get_split_midx_filename_ext(struct odb_source *source, struct strbuf *buf,
 				 const unsigned char *hash, const char *ext);
 
-struct multi_pack_index *load_multi_pack_index(struct repository *r,
-					       const char *object_dir,
-					       int local);
-int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t pack_int_id);
+struct multi_pack_index *get_multi_pack_index(struct odb_source *source);
+struct multi_pack_index *load_multi_pack_index(struct odb_source *source);
+int prepare_midx_pack(struct multi_pack_index *m, uint32_t pack_int_id);
 struct packed_git *nth_midxed_pack(struct multi_pack_index *m,
 				   uint32_t pack_int_id);
-int nth_bitmapped_pack(struct repository *r, struct multi_pack_index *m,
+int nth_bitmapped_pack(struct multi_pack_index *m,
 		       struct bitmapped_pack *bp, uint32_t pack_int_id);
 int bsearch_one_midx(const struct object_id *oid, struct multi_pack_index *m,
 		     uint32_t *result);
@@ -118,27 +111,27 @@ uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos);
 struct object_id *nth_midxed_object_oid(struct object_id *oid,
 					struct multi_pack_index *m,
 					uint32_t n);
-int fill_midx_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e, struct multi_pack_index *m);
+int fill_midx_entry(struct multi_pack_index *m, const struct object_id *oid, struct pack_entry *e);
 int midx_contains_pack(struct multi_pack_index *m,
 		       const char *idx_or_pack_name);
 int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id);
-int prepare_multi_pack_index_one(struct odb_source *source, int local);
+int prepare_multi_pack_index_one(struct odb_source *source);
 
 /*
  * Variant of write_midx_file which writes a MIDX containing only the packs
  * specified in packs_to_include.
  */
-int write_midx_file(struct repository *r, const char *object_dir,
+int write_midx_file(struct odb_source *source,
 		    const char *preferred_pack_name, const char *refs_snapshot,
 		    unsigned flags);
-int write_midx_file_only(struct repository *r, const char *object_dir,
+int write_midx_file_only(struct odb_source *source,
 			 struct string_list *packs_to_include,
 			 const char *preferred_pack_name,
 			 const char *refs_snapshot, unsigned flags);
 void clear_midx_file(struct repository *r);
-int verify_midx_file(struct repository *r, const char *object_dir, unsigned flags);
-int expire_midx_packs(struct repository *r, const char *object_dir, unsigned flags);
-int midx_repack(struct repository *r, const char *object_dir, size_t batch_size, unsigned flags);
+int verify_midx_file(struct odb_source *source, unsigned flags);
+int expire_midx_packs(struct odb_source *source, unsigned flags);
+int midx_repack(struct odb_source *source, size_t batch_size, unsigned flags);
 
 void close_midx(struct multi_pack_index *m);
 
diff --git a/negotiator/default.c b/negotiator/default.c
index c479da9..116dedc 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -38,11 +38,10 @@ static void rev_list_push(struct negotiation_state *ns,
 	}
 }
 
-static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-		       int flag UNUSED,
-		       void *cb_data UNUSED)
+static int clear_marks(const struct reference *ref, void *cb_data UNUSED)
 {
-	struct object *o = deref_tag(the_repository, parse_object(the_repository, oid), refname, 0);
+	struct object *o = deref_tag(the_repository, parse_object(the_repository, ref->oid),
+				     ref->name, 0);
 
 	if (o && o->type == OBJ_COMMIT)
 		clear_commit_marks((struct commit *)o,
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index 616df6b..0a27213 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -75,11 +75,10 @@ static struct entry *rev_list_push(struct data *data, struct commit *commit, int
 	return entry;
 }
 
-static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-		       int flag UNUSED,
-		       void *cb_data UNUSED)
+static int clear_marks(const struct reference *ref, void *cb_data UNUSED)
 {
-	struct object *o = deref_tag(the_repository, parse_object(the_repository, oid), refname, 0);
+	struct object *o = deref_tag(the_repository, parse_object(the_repository, ref->oid),
+				     ref->name, 0);
 
 	if (o && o->type == OBJ_COMMIT)
 		clear_commit_marks((struct commit *)o,
diff --git a/notes.c b/notes.c
index 9736276..8e00fd8 100644
--- a/notes.c
+++ b/notes.c
@@ -894,7 +894,7 @@ static int string_list_add_note_lines(struct string_list *list,
 	 * later, along with any empty strings that came from empty
 	 * lines within the file.
 	 */
-	string_list_split(list, data, '\n', -1);
+	string_list_split(list, data, "\n", -1);
 	free(data);
 	return 0;
 }
@@ -938,13 +938,11 @@ int combine_notes_cat_sort_uniq(struct object_id *cur_oid,
 	return ret;
 }
 
-static int string_list_add_one_ref(const char *refname, const char *referent UNUSED,
-				   const struct object_id *oid UNUSED,
-				   int flag UNUSED, void *cb)
+static int string_list_add_one_ref(const struct reference *ref, void *cb)
 {
 	struct string_list *refs = cb;
-	if (!unsorted_string_list_has_string(refs, refname))
-		string_list_append(refs, refname);
+	if (!unsorted_string_list_has_string(refs, ref->name))
+		string_list_append(refs, ref->name);
 	return 0;
 }
 
@@ -973,8 +971,8 @@ 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_remove_empty_items(&split, 0);
+	string_list_split_in_place_f(&split, globs_copy, ":", -1,
+				     STRING_LIST_SPLIT_NONEMPTY);
 
 	for (i = 0; i < split.nr; i++)
 		string_list_add_refs_by_glob(list, split.items[i].string);
diff --git a/object-file.c b/object-file.c
index 2bc36ab..84c9249 100644
--- a/object-file.c
+++ b/object-file.c
@@ -10,7 +10,6 @@
 #define USE_THE_REPOSITORY_VARIABLE
 
 #include "git-compat-util.h"
-#include "bulk-checkin.h"
 #include "convert.h"
 #include "dir.h"
 #include "environment.h"
@@ -28,6 +27,8 @@
 #include "read-cache-ll.h"
 #include "setup.h"
 #include "streaming.h"
+#include "tempfile.h"
+#include "tmp-objdir.h"
 
 /* The maximum size for an object header. */
 #define MAX_HEADER_LEN 32
@@ -98,8 +99,8 @@ static int check_and_freshen_source(struct odb_source *source,
 	return check_and_freshen_file(path.buf, freshen);
 }
 
-int has_loose_object(struct odb_source *source,
-		     const struct object_id *oid)
+int odb_source_loose_has_object(struct odb_source *source,
+				const struct object_id *oid)
 {
 	return check_and_freshen_source(source, oid, 0);
 }
@@ -166,25 +167,22 @@ int stream_object_signature(struct repository *r, const struct object_id *oid)
 }
 
 /*
- * Find "oid" as a loose object in the local repository or in an alternate.
+ * Find "oid" as a loose object in given source.
  * Returns 0 on success, negative on failure.
  *
  * The "path" out-parameter will give the path of the object we found (if any).
  * Note that it may point to static storage and is only valid until another
  * call to stat_loose_object().
  */
-static int stat_loose_object(struct repository *r, const struct object_id *oid,
+static int stat_loose_object(struct odb_source_loose *loose,
+			     const struct object_id *oid,
 			     struct stat *st, const char **path)
 {
-	struct odb_source *source;
 	static struct strbuf buf = STRBUF_INIT;
 
-	odb_prepare_alternates(r->objects);
-	for (source = r->objects->sources; source; source = source->next) {
-		*path = odb_loose_path(source, &buf, oid);
-		if (!lstat(*path, st))
-			return 0;
-	}
+	*path = odb_loose_path(loose->source, &buf, oid);
+	if (!lstat(*path, st))
+		return 0;
 
 	return -1;
 }
@@ -193,39 +191,24 @@ static int stat_loose_object(struct repository *r, const struct object_id *oid,
  * Like stat_loose_object(), but actually open the object and return the
  * descriptor. See the caveats on the "path" parameter above.
  */
-static int open_loose_object(struct repository *r,
+static int open_loose_object(struct odb_source_loose *loose,
 			     const struct object_id *oid, const char **path)
 {
-	int fd;
-	struct odb_source *source;
-	int most_interesting_errno = ENOENT;
 	static struct strbuf buf = STRBUF_INIT;
+	int fd;
 
-	odb_prepare_alternates(r->objects);
-	for (source = r->objects->sources; source; source = source->next) {
-		*path = odb_loose_path(source, &buf, oid);
-		fd = git_open(*path);
-		if (fd >= 0)
-			return fd;
+	*path = odb_loose_path(loose->source, &buf, oid);
+	fd = git_open(*path);
+	if (fd >= 0)
+		return fd;
 
-		if (most_interesting_errno == ENOENT)
-			most_interesting_errno = errno;
-	}
-	errno = most_interesting_errno;
 	return -1;
 }
 
-static int quick_has_loose(struct repository *r,
+static int quick_has_loose(struct odb_source_loose *loose,
 			   const struct object_id *oid)
 {
-	struct odb_source *source;
-
-	odb_prepare_alternates(r->objects);
-	for (source = r->objects->sources; source; source = source->next) {
-		if (oidtree_contains(odb_loose_cache(source, oid), oid))
-			return 1;
-	}
-	return 0;
+	return !!oidtree_contains(odb_source_loose_cache(loose->source, oid), oid);
 }
 
 /*
@@ -251,12 +234,12 @@ static void *map_fd(int fd, const char *path, unsigned long *size)
 	return map;
 }
 
-void *map_loose_object(struct repository *r,
-		       const struct object_id *oid,
-		       unsigned long *size)
+void *odb_source_loose_map_object(struct odb_source *source,
+				  const struct object_id *oid,
+				  unsigned long *size)
 {
 	const char *p;
-	int fd = open_loose_object(r, oid, &p);
+	int fd = open_loose_object(source->loose, oid, &p);
 
 	if (fd < 0)
 		return NULL;
@@ -406,9 +389,9 @@ int parse_loose_header(const char *hdr, struct object_info *oi)
 	return 0;
 }
 
-int loose_object_info(struct repository *r,
-		      const struct object_id *oid,
-		      struct object_info *oi, int flags)
+int odb_source_loose_read_object_info(struct odb_source *source,
+				      const struct object_id *oid,
+				      struct object_info *oi, int flags)
 {
 	int status = 0;
 	int fd;
@@ -421,7 +404,7 @@ int loose_object_info(struct repository *r,
 	enum object_type type_scratch;
 
 	if (oi->delta_base_oid)
-		oidclr(oi->delta_base_oid, r->hash_algo);
+		oidclr(oi->delta_base_oid, source->odb->repo->hash_algo);
 
 	/*
 	 * If we don't care about type or size, then we don't
@@ -434,15 +417,15 @@ int loose_object_info(struct repository *r,
 	if (!oi->typep && !oi->sizep && !oi->contentp) {
 		struct stat st;
 		if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
-			return quick_has_loose(r, oid) ? 0 : -1;
-		if (stat_loose_object(r, oid, &st, &path) < 0)
+			return quick_has_loose(source->loose, oid) ? 0 : -1;
+		if (stat_loose_object(source->loose, oid, &st, &path) < 0)
 			return -1;
 		if (oi->disk_sizep)
 			*oi->disk_sizep = st.st_size;
 		return 0;
 	}
 
-	fd = open_loose_object(r, oid, &path);
+	fd = open_loose_object(source->loose, oid, &path);
 	if (fd < 0) {
 		if (errno != ENOENT)
 			error_errno(_("unable to open loose object %s"), oid_to_hex(oid));
@@ -666,6 +649,93 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,
 	write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
 }
 
+struct transaction_packfile {
+	char *pack_tmp_name;
+	struct hashfile *f;
+	off_t offset;
+	struct pack_idx_option pack_idx_opts;
+
+	struct pack_idx_entry **written;
+	uint32_t alloc_written;
+	uint32_t nr_written;
+};
+
+struct odb_transaction {
+	struct object_database *odb;
+
+	struct tmp_objdir *objdir;
+	struct transaction_packfile packfile;
+};
+
+static void prepare_loose_object_transaction(struct odb_transaction *transaction)
+{
+	/*
+	 * We lazily create the temporary object directory
+	 * the first time an object might be added, since
+	 * callers may not know whether any objects will be
+	 * added at the time they call object_file_transaction_begin.
+	 */
+	if (!transaction || transaction->objdir)
+		return;
+
+	transaction->objdir = tmp_objdir_create(transaction->odb->repo, "bulk-fsync");
+	if (transaction->objdir)
+		tmp_objdir_replace_primary_odb(transaction->objdir, 0);
+}
+
+static void fsync_loose_object_transaction(struct odb_transaction *transaction,
+					   int fd, const char *filename)
+{
+	/*
+	 * If we have an active ODB transaction, we issue a call that
+	 * cleans the filesystem page cache but avoids a hardware flush
+	 * command. Later on we will issue a single hardware flush
+	 * before renaming the objects to their final names as part of
+	 * flush_batch_fsync.
+	 */
+	if (!transaction || !transaction->objdir ||
+	    git_fsync(fd, FSYNC_WRITEOUT_ONLY) < 0) {
+		if (errno == ENOSYS)
+			warning(_("core.fsyncMethod = batch is unsupported on this platform"));
+		fsync_or_die(fd, filename);
+	}
+}
+
+/*
+ * Cleanup after batch-mode fsync_object_files.
+ */
+static void flush_loose_object_transaction(struct odb_transaction *transaction)
+{
+	struct strbuf temp_path = STRBUF_INIT;
+	struct tempfile *temp;
+
+	if (!transaction->objdir)
+		return;
+
+	/*
+	 * Issue a full hardware flush against a temporary file to ensure
+	 * that all objects are durable before any renames occur. The code in
+	 * fsync_loose_object_transaction has already issued a writeout
+	 * request, but it has not flushed any writeback cache in the storage
+	 * hardware or any filesystem logs. This fsync call acts as a barrier
+	 * to ensure that the data in each new object file is durable before
+	 * the final name is visible.
+	 */
+	strbuf_addf(&temp_path, "%s/bulk_fsync_XXXXXX",
+		    repo_get_object_directory(transaction->odb->repo));
+	temp = xmks_tempfile(temp_path.buf);
+	fsync_or_die(get_tempfile_fd(temp), get_tempfile_path(temp));
+	delete_tempfile(&temp);
+	strbuf_release(&temp_path);
+
+	/*
+	 * Make the object files visible in the primary ODB after their data is
+	 * fully durable.
+	 */
+	tmp_objdir_migrate(transaction->objdir);
+	transaction->objdir = NULL;
+}
+
 /* Finalize a file on disk, and close it. */
 static void close_loose_object(struct odb_source *source,
 			       int fd, const char *filename)
@@ -674,7 +744,7 @@ static void close_loose_object(struct odb_source *source,
 		goto out;
 
 	if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
-		fsync_loose_object_bulk_checkin(fd, filename);
+		fsync_loose_object_transaction(source->odb->transaction, fd, filename);
 	else if (fsync_object_files > 0)
 		fsync_or_die(fd, filename);
 	else
@@ -852,7 +922,7 @@ static int write_loose_object(struct odb_source *source,
 	static struct strbuf filename = STRBUF_INIT;
 
 	if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
-		prepare_loose_object_bulk_checkin();
+		prepare_loose_object_transaction(source->odb->transaction);
 
 	odb_loose_path(source, &filename, oid);
 
@@ -898,35 +968,15 @@ static int write_loose_object(struct odb_source *source,
 					  FOF_SKIP_COLLISION_CHECK);
 }
 
-static int freshen_loose_object(struct object_database *odb,
-				const struct object_id *oid)
+int odb_source_loose_freshen_object(struct odb_source *source,
+				    const struct object_id *oid)
 {
-	odb_prepare_alternates(odb);
-	for (struct odb_source *source = odb->sources; source; source = source->next)
-		if (check_and_freshen_source(source, oid, 1))
-			return 1;
-	return 0;
+	return !!check_and_freshen_source(source, oid, 1);
 }
 
-static int freshen_packed_object(struct object_database *odb,
-				 const struct object_id *oid)
-{
-	struct pack_entry e;
-	if (!find_pack_entry(odb->repo, oid, &e))
-		return 0;
-	if (e.p->is_cruft)
-		return 0;
-	if (e.p->freshened)
-		return 1;
-	if (!freshen_file(e.p->pack_name))
-		return 0;
-	e.p->freshened = 1;
-	return 1;
-}
-
-int stream_loose_object(struct odb_source *source,
-			struct input_stream *in_stream, size_t len,
-			struct object_id *oid)
+int odb_source_loose_write_stream(struct odb_source *source,
+				  struct odb_write_stream *in_stream, size_t len,
+				  struct object_id *oid)
 {
 	const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
 	struct object_id compat_oid;
@@ -941,7 +991,7 @@ int stream_loose_object(struct odb_source *source,
 	int hdrlen;
 
 	if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
-		prepare_loose_object_bulk_checkin();
+		prepare_loose_object_transaction(source->odb->transaction);
 
 	/* Since oid is not determined, save tmp file to odb path. */
 	strbuf_addf(&filename, "%s/", source->path);
@@ -1003,12 +1053,10 @@ int stream_loose_object(struct odb_source *source,
 		die(_("deflateEnd on stream object failed (%d)"), ret);
 	close_loose_object(source, fd, tmp_file.buf);
 
-	if (freshen_packed_object(source->odb, oid) ||
-	    freshen_loose_object(source->odb, oid)) {
+	if (odb_freshen_object(source->odb, oid)) {
 		unlink_or_warn(tmp_file.buf);
 		goto cleanup;
 	}
-
 	odb_loose_path(source, &filename, oid);
 
 	/* We finally know the object path, and create the missing dir. */
@@ -1036,10 +1084,10 @@ int stream_loose_object(struct odb_source *source,
 	return err;
 }
 
-int write_object_file(struct odb_source *source,
-		      const void *buf, unsigned long len,
-		      enum object_type type, struct object_id *oid,
-		      struct object_id *compat_oid_in, unsigned flags)
+int odb_source_loose_write_object(struct odb_source *source,
+				  const void *buf, unsigned long len,
+				  enum object_type type, struct object_id *oid,
+				  struct object_id *compat_oid_in, unsigned flags)
 {
 	const struct git_hash_algo *algo = source->odb->repo->hash_algo;
 	const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
@@ -1067,8 +1115,7 @@ int write_object_file(struct odb_source *source,
 	 * it out into .git/objects/??/?{38} file.
 	 */
 	write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
-	if (freshen_packed_object(source->odb, oid) ||
-	    freshen_loose_object(source->odb, oid))
+	if (odb_freshen_object(source->odb, oid))
 		return 0;
 	if (write_loose_object(source, oid, hdr, hdrlen, buf, len, 0, flags))
 		return -1;
@@ -1091,7 +1138,7 @@ int force_object_loose(struct odb_source *source,
 	int ret;
 
 	for (struct odb_source *s = source->odb->sources; s; s = s->next)
-		if (has_loose_object(s, oid))
+		if (odb_source_loose_has_object(s, oid))
 			return 0;
 
 	oi.typep = &type;
@@ -1243,6 +1290,274 @@ static int index_core(struct index_state *istate,
 	return ret;
 }
 
+static int already_written(struct odb_transaction *transaction,
+			   struct object_id *oid)
+{
+	/* The object may already exist in the repository */
+	if (odb_has_object(transaction->odb, oid,
+			   HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
+		return 1;
+
+	/* Might want to keep the list sorted */
+	for (uint32_t i = 0; i < transaction->packfile.nr_written; i++)
+		if (oideq(&transaction->packfile.written[i]->oid, oid))
+			return 1;
+
+	/* This is a new object we need to keep */
+	return 0;
+}
+
+/* Lazily create backing packfile for the state */
+static void prepare_packfile_transaction(struct odb_transaction *transaction,
+					 unsigned flags)
+{
+	struct transaction_packfile *state = &transaction->packfile;
+	if (!(flags & INDEX_WRITE_OBJECT) || state->f)
+		return;
+
+	state->f = create_tmp_packfile(transaction->odb->repo,
+				       &state->pack_tmp_name);
+	reset_pack_idx_option(&state->pack_idx_opts);
+
+	/* Pretend we are going to write only one object */
+	state->offset = write_pack_header(state->f, 1);
+	if (!state->offset)
+		die_errno("unable to write pack header");
+}
+
+/*
+ * Read the contents from fd for size bytes, streaming it to the
+ * packfile in state while updating the hash in ctx. Signal a failure
+ * by returning a negative value when the resulting pack would exceed
+ * the pack size limit and this is not the first object in the pack,
+ * so that the caller can discard what we wrote from the current pack
+ * by truncating it and opening a new one. The caller will then call
+ * us again after rewinding the input fd.
+ *
+ * The already_hashed_to pointer is kept untouched by the caller to
+ * make sure we do not hash the same byte when we are called
+ * again. This way, the caller does not have to checkpoint its hash
+ * status before calling us just in case we ask it to call us again
+ * with a new pack.
+ */
+static int stream_blob_to_pack(struct transaction_packfile *state,
+			       struct git_hash_ctx *ctx, off_t *already_hashed_to,
+			       int fd, size_t size, const char *path,
+			       unsigned flags)
+{
+	git_zstream s;
+	unsigned char ibuf[16384];
+	unsigned char obuf[16384];
+	unsigned hdrlen;
+	int status = Z_OK;
+	int write_object = (flags & INDEX_WRITE_OBJECT);
+	off_t offset = 0;
+
+	git_deflate_init(&s, pack_compression_level);
+
+	hdrlen = encode_in_pack_object_header(obuf, sizeof(obuf), OBJ_BLOB, size);
+	s.next_out = obuf + hdrlen;
+	s.avail_out = sizeof(obuf) - hdrlen;
+
+	while (status != Z_STREAM_END) {
+		if (size && !s.avail_in) {
+			size_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf);
+			ssize_t read_result = read_in_full(fd, ibuf, rsize);
+			if (read_result < 0)
+				die_errno("failed to read from '%s'", path);
+			if ((size_t)read_result != rsize)
+				die("failed to read %u bytes from '%s'",
+				    (unsigned)rsize, path);
+			offset += rsize;
+			if (*already_hashed_to < offset) {
+				size_t hsize = offset - *already_hashed_to;
+				if (rsize < hsize)
+					hsize = rsize;
+				if (hsize)
+					git_hash_update(ctx, ibuf, hsize);
+				*already_hashed_to = offset;
+			}
+			s.next_in = ibuf;
+			s.avail_in = rsize;
+			size -= rsize;
+		}
+
+		status = git_deflate(&s, size ? 0 : Z_FINISH);
+
+		if (!s.avail_out || status == Z_STREAM_END) {
+			if (write_object) {
+				size_t written = s.next_out - obuf;
+
+				/* would we bust the size limit? */
+				if (state->nr_written &&
+				    pack_size_limit_cfg &&
+				    pack_size_limit_cfg < state->offset + written) {
+					git_deflate_abort(&s);
+					return -1;
+				}
+
+				hashwrite(state->f, obuf, written);
+				state->offset += written;
+			}
+			s.next_out = obuf;
+			s.avail_out = sizeof(obuf);
+		}
+
+		switch (status) {
+		case Z_OK:
+		case Z_BUF_ERROR:
+		case Z_STREAM_END:
+			continue;
+		default:
+			die("unexpected deflate failure: %d", status);
+		}
+	}
+	git_deflate_end(&s);
+	return 0;
+}
+
+static void flush_packfile_transaction(struct odb_transaction *transaction)
+{
+	struct transaction_packfile *state = &transaction->packfile;
+	struct repository *repo = transaction->odb->repo;
+	unsigned char hash[GIT_MAX_RAWSZ];
+	struct strbuf packname = STRBUF_INIT;
+	char *idx_tmp_name = NULL;
+
+	if (!state->f)
+		return;
+
+	if (state->nr_written == 0) {
+		close(state->f->fd);
+		free_hashfile(state->f);
+		unlink(state->pack_tmp_name);
+		goto clear_exit;
+	} else if (state->nr_written == 1) {
+		finalize_hashfile(state->f, hash, FSYNC_COMPONENT_PACK,
+				  CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE);
+	} else {
+		int fd = finalize_hashfile(state->f, hash, FSYNC_COMPONENT_PACK, 0);
+		fixup_pack_header_footer(repo->hash_algo, fd, hash, state->pack_tmp_name,
+					 state->nr_written, hash,
+					 state->offset);
+		close(fd);
+	}
+
+	strbuf_addf(&packname, "%s/pack/pack-%s.",
+		    repo_get_object_directory(transaction->odb->repo),
+		    hash_to_hex_algop(hash, repo->hash_algo));
+
+	stage_tmp_packfiles(repo, &packname, state->pack_tmp_name,
+			    state->written, state->nr_written, NULL,
+			    &state->pack_idx_opts, hash, &idx_tmp_name);
+	rename_tmp_packfile_idx(repo, &packname, &idx_tmp_name);
+
+	for (uint32_t i = 0; i < state->nr_written; i++)
+		free(state->written[i]);
+
+clear_exit:
+	free(idx_tmp_name);
+	free(state->pack_tmp_name);
+	free(state->written);
+	memset(state, 0, sizeof(*state));
+
+	strbuf_release(&packname);
+	/* Make objects we just wrote available to ourselves */
+	odb_reprepare(repo->objects);
+}
+
+/*
+ * This writes the specified object to a packfile. Objects written here
+ * during the same transaction are written to the same packfile. The
+ * packfile is not flushed until the transaction is flushed. The caller
+ * is expected to ensure a valid transaction is setup for objects to be
+ * recorded to.
+ *
+ * This also bypasses the usual "convert-to-git" dance, and that is on
+ * purpose. We could write a streaming version of the converting
+ * functions and insert that before feeding the data to fast-import
+ * (or equivalent in-core API described above). However, that is
+ * somewhat complicated, as we do not know the size of the filter
+ * result, which we need to know beforehand when writing a git object.
+ * Since the primary motivation for trying to stream from the working
+ * tree file and to avoid mmaping it in core is to deal with large
+ * binary blobs, they generally do not want to get any conversion, and
+ * callers should avoid this code path when filters are requested.
+ */
+static int index_blob_packfile_transaction(struct odb_transaction *transaction,
+					   struct object_id *result_oid, int fd,
+					   size_t size, const char *path,
+					   unsigned flags)
+{
+	struct transaction_packfile *state = &transaction->packfile;
+	off_t seekback, already_hashed_to;
+	struct git_hash_ctx ctx;
+	unsigned char obuf[16384];
+	unsigned header_len;
+	struct hashfile_checkpoint checkpoint;
+	struct pack_idx_entry *idx = NULL;
+
+	seekback = lseek(fd, 0, SEEK_CUR);
+	if (seekback == (off_t)-1)
+		return error("cannot find the current offset");
+
+	header_len = format_object_header((char *)obuf, sizeof(obuf),
+					  OBJ_BLOB, size);
+	transaction->odb->repo->hash_algo->init_fn(&ctx);
+	git_hash_update(&ctx, obuf, header_len);
+
+	/* Note: idx is non-NULL when we are writing */
+	if ((flags & INDEX_WRITE_OBJECT) != 0) {
+		CALLOC_ARRAY(idx, 1);
+
+		prepare_packfile_transaction(transaction, flags);
+		hashfile_checkpoint_init(state->f, &checkpoint);
+	}
+
+	already_hashed_to = 0;
+
+	while (1) {
+		prepare_packfile_transaction(transaction, flags);
+		if (idx) {
+			hashfile_checkpoint(state->f, &checkpoint);
+			idx->offset = state->offset;
+			crc32_begin(state->f);
+		}
+		if (!stream_blob_to_pack(state, &ctx, &already_hashed_to,
+					 fd, size, path, flags))
+			break;
+		/*
+		 * Writing this object to the current pack will make
+		 * it too big; we need to truncate it, start a new
+		 * pack, and write into it.
+		 */
+		if (!idx)
+			BUG("should not happen");
+		hashfile_truncate(state->f, &checkpoint);
+		state->offset = checkpoint.offset;
+		flush_packfile_transaction(transaction);
+		if (lseek(fd, seekback, SEEK_SET) == (off_t)-1)
+			return error("cannot seek back");
+	}
+	git_hash_final_oid(result_oid, &ctx);
+	if (!idx)
+		return 0;
+
+	idx->crc32 = crc32_end(state->f);
+	if (already_written(transaction, result_oid)) {
+		hashfile_truncate(state->f, &checkpoint);
+		state->offset = checkpoint.offset;
+		free(idx);
+	} else {
+		oidcpy(&idx->oid, result_oid);
+		ALLOC_GROW(state->written,
+			   state->nr_written + 1,
+			   state->alloc_written);
+		state->written[state->nr_written++] = idx;
+	}
+	return 0;
+}
+
 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)
@@ -1253,18 +1568,27 @@ int index_fd(struct index_state *istate, struct object_id *oid,
 	 * Call xsize_t() only when needed to avoid potentially unnecessary
 	 * die() for large files.
 	 */
-	if (type == OBJ_BLOB && path && would_convert_to_git_filter_fd(istate, path))
+	if (type == OBJ_BLOB && path && would_convert_to_git_filter_fd(istate, path)) {
 		ret = index_stream_convert_blob(istate, oid, fd, path, flags);
-	else if (!S_ISREG(st->st_mode))
+	} else if (!S_ISREG(st->st_mode)) {
 		ret = index_pipe(istate, oid, fd, type, path, flags);
-	else if ((st->st_size >= 0 && (size_t) st->st_size <= repo_settings_get_big_file_threshold(istate->repo)) ||
-		 type != OBJ_BLOB ||
-		 (path && would_convert_to_git(istate, path)))
+	} else if ((st->st_size >= 0 &&
+		    (size_t)st->st_size <= repo_settings_get_big_file_threshold(istate->repo)) ||
+		   type != OBJ_BLOB ||
+		   (path && would_convert_to_git(istate, path))) {
 		ret = index_core(istate, oid, fd, xsize_t(st->st_size),
 				 type, path, flags);
-	else
-		ret = index_blob_bulk_checkin(oid, fd, xsize_t(st->st_size), path,
-					     flags);
+	} else {
+		struct odb_transaction *transaction;
+
+		transaction = odb_transaction_begin(the_repository->objects);
+		ret = index_blob_packfile_transaction(the_repository->objects->transaction,
+						      oid, fd,
+						      xsize_t(st->st_size),
+						      path, flags);
+		odb_transaction_commit(transaction);
+	}
+
 	close(fd);
 	return ret;
 }
@@ -1296,7 +1620,11 @@ int index_path(struct index_state *istate, struct object_id *oid,
 		strbuf_release(&sb);
 		break;
 	case S_IFDIR:
-		return repo_resolve_gitlink_ref(istate->repo, path, "HEAD", oid);
+		if (repo_resolve_gitlink_ref(istate->repo, path, "HEAD", oid))
+			return error(_("'%s' does not have a commit checked out"), path);
+		if (&hash_algos[oid->algo] != istate->repo->hash_algo)
+			return error(_("cannot add a submodule of a different hash algorithm"));
+		break;
 	default:
 		return error(_("%s: unsupported file type"), path);
 	}
@@ -1437,44 +1765,49 @@ static int append_loose_object(const struct object_id *oid,
 	return 0;
 }
 
-struct oidtree *odb_loose_cache(struct odb_source *source,
-				const struct object_id *oid)
+struct oidtree *odb_source_loose_cache(struct odb_source *source,
+				       const struct object_id *oid)
 {
 	int subdir_nr = oid->hash[0];
 	struct strbuf buf = STRBUF_INIT;
-	size_t word_bits = bitsizeof(source->loose_objects_subdir_seen[0]);
+	size_t word_bits = bitsizeof(source->loose->subdir_seen[0]);
 	size_t word_index = subdir_nr / word_bits;
 	size_t mask = (size_t)1u << (subdir_nr % word_bits);
 	uint32_t *bitmap;
 
 	if (subdir_nr < 0 ||
-	    (size_t) subdir_nr >= bitsizeof(source->loose_objects_subdir_seen))
+	    (size_t) subdir_nr >= bitsizeof(source->loose->subdir_seen))
 		BUG("subdir_nr out of range");
 
-	bitmap = &source->loose_objects_subdir_seen[word_index];
+	bitmap = &source->loose->subdir_seen[word_index];
 	if (*bitmap & mask)
-		return source->loose_objects_cache;
-	if (!source->loose_objects_cache) {
-		ALLOC_ARRAY(source->loose_objects_cache, 1);
-		oidtree_init(source->loose_objects_cache);
+		return source->loose->cache;
+	if (!source->loose->cache) {
+		ALLOC_ARRAY(source->loose->cache, 1);
+		oidtree_init(source->loose->cache);
 	}
 	strbuf_addstr(&buf, source->path);
 	for_each_file_in_obj_subdir(subdir_nr, &buf,
 				    source->odb->repo->hash_algo,
 				    append_loose_object,
 				    NULL, NULL,
-				    source->loose_objects_cache);
+				    source->loose->cache);
 	*bitmap |= mask;
 	strbuf_release(&buf);
-	return source->loose_objects_cache;
+	return source->loose->cache;
 }
 
-void odb_clear_loose_cache(struct odb_source *source)
+static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
 {
-	oidtree_clear(source->loose_objects_cache);
-	FREE_AND_NULL(source->loose_objects_cache);
-	memset(&source->loose_objects_subdir_seen, 0,
-	       sizeof(source->loose_objects_subdir_seen));
+	oidtree_clear(loose->cache);
+	FREE_AND_NULL(loose->cache);
+	memset(&loose->subdir_seen, 0,
+	       sizeof(loose->subdir_seen));
+}
+
+void odb_source_loose_reprepare(struct odb_source *source)
+{
+	odb_source_loose_clear_cache(source->loose);
 }
 
 static int check_stream_oid(git_zstream *stream,
@@ -1601,3 +1934,49 @@ int read_loose_object(struct repository *repo,
 		munmap(map, mapsize);
 	return ret;
 }
+
+struct odb_transaction *object_file_transaction_begin(struct odb_source *source)
+{
+	struct object_database *odb = source->odb;
+
+	if (odb->transaction)
+		return NULL;
+
+	CALLOC_ARRAY(odb->transaction, 1);
+	odb->transaction->odb = odb;
+
+	return odb->transaction;
+}
+
+void object_file_transaction_commit(struct odb_transaction *transaction)
+{
+	if (!transaction)
+		return;
+
+	/*
+	 * Ensure the transaction ending matches the pending transaction.
+	 */
+	ASSERT(transaction == transaction->odb->transaction);
+
+	flush_loose_object_transaction(transaction);
+	flush_packfile_transaction(transaction);
+	transaction->odb->transaction = NULL;
+	free(transaction);
+}
+
+struct odb_source_loose *odb_source_loose_new(struct odb_source *source)
+{
+	struct odb_source_loose *loose;
+	CALLOC_ARRAY(loose, 1);
+	loose->source = source;
+	return loose;
+}
+
+void odb_source_loose_free(struct odb_source_loose *loose)
+{
+	if (!loose)
+		return;
+	odb_source_loose_clear_cache(loose);
+	loose_object_map_clear(&loose->map);
+	free(loose);
+}
diff --git a/object-file.h b/object-file.h
index 15d9763..eeffa67 100644
--- a/object-file.h
+++ b/object-file.h
@@ -7,14 +7,6 @@
 
 struct index_state;
 
-/*
- * Set this to 0 to prevent odb_read_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;
-
 enum {
 	INDEX_WRITE_OBJECT = (1 << 0),
 	INDEX_FORMAT_CHECK = (1 << 1),
@@ -26,15 +18,65 @@ int index_path(struct index_state *istate, struct object_id *oid, const char *pa
 
 struct odb_source;
 
+struct odb_source_loose {
+	struct odb_source *source;
+
+	/*
+	 * Used to store the results of readdir(3) calls when we are OK
+	 * sacrificing accuracy due to races for speed. That includes
+	 * object existence with OBJECT_INFO_QUICK, as well as
+	 * our search for unique abbreviated hashes. Don't use it for tasks
+	 * requiring greater accuracy!
+	 *
+	 * Be sure to call odb_load_loose_cache() before using.
+	 */
+	uint32_t subdir_seen[8]; /* 256 bits */
+	struct oidtree *cache;
+
+	/* Map between object IDs for loose objects. */
+	struct loose_object_map *map;
+};
+
+struct odb_source_loose *odb_source_loose_new(struct odb_source *source);
+void odb_source_loose_free(struct odb_source_loose *loose);
+
+/* Reprepare the loose source by emptying the loose object cache. */
+void odb_source_loose_reprepare(struct odb_source *source);
+
+int odb_source_loose_read_object_info(struct odb_source *source,
+				      const struct object_id *oid,
+				      struct object_info *oi, int flags);
+
+void *odb_source_loose_map_object(struct odb_source *source,
+				  const struct object_id *oid,
+				  unsigned long *size);
+
+/*
+ * Return true iff an object database source has a loose object
+ * with the specified name.  This function does not respect replace
+ * references.
+ */
+int odb_source_loose_has_object(struct odb_source *source,
+				const struct object_id *oid);
+
+int odb_source_loose_freshen_object(struct odb_source *source,
+				    const struct object_id *oid);
+
+int odb_source_loose_write_object(struct odb_source *source,
+				  const void *buf, unsigned long len,
+				  enum object_type type, struct object_id *oid,
+				  struct object_id *compat_oid_in, unsigned flags);
+
+int odb_source_loose_write_stream(struct odb_source *source,
+				  struct odb_write_stream *stream, size_t len,
+				  struct object_id *oid);
+
 /*
  * Populate and return the loose object cache array corresponding to the
  * given object ID.
  */
-struct oidtree *odb_loose_cache(struct odb_source *source,
-				const struct object_id *oid);
-
-/* Empty the loose object cache for the specified object directory. */
-void odb_clear_loose_cache(struct odb_source *source);
+struct oidtree *odb_source_loose_cache(struct odb_source *source,
+				       const struct object_id *oid);
 
 /*
  * Put in `buf` the name of the file in the local object database that
@@ -45,17 +87,6 @@ const char *odb_loose_path(struct odb_source *source,
 			   const struct object_id *oid);
 
 /*
- * Return true iff an object database source has a loose object
- * with the specified name.  This function does not respect replace
- * references.
- */
-int has_loose_object(struct odb_source *source,
-		     const struct object_id *oid);
-
-void *map_loose_object(struct repository *r, const struct object_id *oid,
-		       unsigned long *size);
-
-/*
  * Iterate over the files in the loose-object parts of the object
  * directory "path", triggering the following callbacks:
  *
@@ -146,21 +177,6 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
 struct object_info;
 int parse_loose_header(const char *hdr, struct object_info *oi);
 
-int write_object_file(struct odb_source *source,
-		      const void *buf, unsigned long len,
-		      enum object_type type, struct object_id *oid,
-		      struct object_id *compat_oid_in, unsigned flags);
-
-struct input_stream {
-	const void *(*read)(struct input_stream *, unsigned long *len);
-	void *data;
-	int is_finished;
-};
-
-int stream_loose_object(struct odb_source *source,
-			struct input_stream *in_stream, size_t len,
-			struct object_id *oid);
-
 int force_object_loose(struct odb_source *source,
 		       const struct object_id *oid, time_t mtime);
 
@@ -182,10 +198,6 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
  */
 int stream_object_signature(struct repository *r, const struct object_id *oid);
 
-int loose_object_info(struct repository *r,
-		      const struct object_id *oid,
-		      struct object_info *oi, int flags);
-
 enum finalize_object_file_flags {
 	FOF_SKIP_COLLISION_CHECK = 1,
 };
@@ -218,4 +230,20 @@ int read_loose_object(struct repository *repo,
 		      void **contents,
 		      struct object_info *oi);
 
+struct odb_transaction;
+
+/*
+ * Tell the object database to optimize for adding
+ * multiple objects. object_file_transaction_commit must be called
+ * to make new objects visible. If a transaction is already
+ * pending, NULL is returned.
+ */
+struct odb_transaction *object_file_transaction_begin(struct odb_source *source);
+
+/*
+ * Tell the object database to make any objects from the
+ * current transaction visible.
+ */
+void object_file_transaction_commit(struct odb_transaction *transaction);
+
 #endif /* OBJECT_FILE_H */
diff --git a/object-name.c b/object-name.c
index ffd9461..fed5de5 100644
--- a/object-name.c
+++ b/object-name.c
@@ -116,7 +116,7 @@ static void find_short_object_filename(struct disambiguate_state *ds)
 	struct odb_source *source;
 
 	for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next)
-		oidtree_each(odb_loose_cache(source, &ds->bin_pfx),
+		oidtree_each(odb_source_loose_cache(source, &ds->bin_pfx),
 				&ds->bin_pfx, ds->len, match_prefix, ds);
 }
 
@@ -213,9 +213,11 @@ static void find_short_packed_object(struct disambiguate_state *ds)
 			unique_in_midx(m, ds);
 	}
 
-	for (p = get_packed_git(ds->repo); p && !ds->ambiguous;
-	     p = p->next)
+	repo_for_each_pack(ds->repo, p) {
+		if (ds->ambiguous)
+			break;
 		unique_in_pack(p, ds);
+	}
 }
 
 static int finish_object_disambiguation(struct disambiguate_state *ds,
@@ -596,7 +598,7 @@ static enum get_oid_result get_short_oid(struct repository *r,
 	 * or migrated from loose to packed.
 	 */
 	if (status == MISSING_OBJECT) {
-		reprepare_packed_git(r);
+		odb_reprepare(r->objects);
 		find_short_object_filename(&ds);
 		find_short_packed_object(&ds);
 		status = finish_object_disambiguation(&ds, oid);
@@ -703,7 +705,7 @@ static int extend_abbrev_len(const struct object_id *oid,
 	while (mad->hex[i] && mad->hex[i] == get_hex_char_from_oid(oid, i))
 		i++;
 
-	if (i < GIT_MAX_RAWSZ && i >= mad->cur_len)
+	if (mad->hex[i] && i >= mad->cur_len)
 		mad->cur_len = i + 1;
 
 	return 0;
@@ -805,7 +807,7 @@ static void find_abbrev_len_packed(struct min_abbrev_data *mad)
 			find_abbrev_len_for_midx(m, mad);
 	}
 
-	for (p = get_packed_git(mad->repo); p; p = p->next)
+	repo_for_each_pack(mad->repo, p)
 		find_abbrev_len_for_pack(p, mad);
 }
 
@@ -1444,18 +1446,16 @@ struct handle_one_ref_cb {
 	struct commit_list **list;
 };
 
-static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
-			  int flag UNUSED,
-			  void *cb_data)
+static int handle_one_ref(const struct reference *ref, void *cb_data)
 {
 	struct handle_one_ref_cb *cb = cb_data;
 	struct commit_list **list = cb->list;
-	struct object *object = parse_object(cb->repo, oid);
+	struct object *object = parse_object(cb->repo, ref->oid);
 	if (!object)
 		return 0;
 	if (object->type == OBJ_TAG) {
-		object = deref_tag(cb->repo, object, path,
-				   strlen(path));
+		object = deref_tag(cb->repo, object, ref->name,
+				   strlen(ref->name));
 		if (!object)
 			return 0;
 	}
@@ -1524,7 +1524,8 @@ struct grab_nth_branch_switch_cbdata {
 	struct strbuf *sb;
 };
 
-static int grab_nth_branch_switch(struct object_id *ooid UNUSED,
+static int grab_nth_branch_switch(const char *refname UNUSED,
+				  struct object_id *ooid UNUSED,
 				  struct object_id *noid UNUSED,
 				  const char *email UNUSED,
 				  timestamp_t timestamp UNUSED,
@@ -1856,55 +1857,35 @@ int repo_get_oid_committish(struct repository *r,
 			    const char *name,
 			    struct object_id *oid)
 {
-	struct object_context unused;
-	int ret = get_oid_with_context(r, name, GET_OID_COMMITTISH,
-				       oid, &unused);
-	object_context_release(&unused);
-	return ret;
+	return repo_get_oid_with_flags(r, name, oid, GET_OID_COMMITTISH);
 }
 
 int repo_get_oid_treeish(struct repository *r,
 			 const char *name,
 			 struct object_id *oid)
 {
-	struct object_context unused;
-	int ret = get_oid_with_context(r, name, GET_OID_TREEISH,
-				       oid, &unused);
-	object_context_release(&unused);
-	return ret;
+	return repo_get_oid_with_flags(r, name, oid, GET_OID_TREEISH);
 }
 
 int repo_get_oid_commit(struct repository *r,
 			const char *name,
 			struct object_id *oid)
 {
-	struct object_context unused;
-	int ret = get_oid_with_context(r, name, GET_OID_COMMIT,
-				       oid, &unused);
-	object_context_release(&unused);
-	return ret;
+	return repo_get_oid_with_flags(r, name, oid, GET_OID_COMMIT);
 }
 
 int repo_get_oid_tree(struct repository *r,
 		      const char *name,
 		      struct object_id *oid)
 {
-	struct object_context unused;
-	int ret = get_oid_with_context(r, name, GET_OID_TREE,
-				       oid, &unused);
-	object_context_release(&unused);
-	return ret;
+	return repo_get_oid_with_flags(r, name, oid, GET_OID_TREE);
 }
 
 int repo_get_oid_blob(struct repository *r,
 		      const char *name,
 		      struct object_id *oid)
 {
-	struct object_context unused;
-	int ret = get_oid_with_context(r, name, GET_OID_BLOB,
-				       oid, &unused);
-	object_context_release(&unused);
-	return ret;
+	return repo_get_oid_with_flags(r, name, oid, GET_OID_BLOB);
 }
 
 /* Must be called only when object_name:filename doesn't exist. */
diff --git a/object.c b/object.c
index c1553ee..b08fc7a 100644
--- a/object.c
+++ b/object.c
@@ -209,7 +209,8 @@ struct object *lookup_object_by_type(struct repository *r,
 
 enum peel_status peel_object(struct repository *r,
 			     const struct object_id *name,
-			     struct object_id *oid)
+			     struct object_id *oid,
+			     unsigned flags)
 {
 	struct object *o = lookup_unknown_object(r, name);
 
@@ -222,7 +223,20 @@ enum peel_status peel_object(struct repository *r,
 	if (o->type != OBJ_TAG)
 		return PEEL_NON_TAG;
 
-	o = deref_tag_noverify(r, o);
+	while (o && o->type == OBJ_TAG) {
+		o = parse_object(r, &o->oid);
+		if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged) {
+			o = ((struct tag *)o)->tagged;
+
+			if (flags & PEEL_OBJECT_VERIFY_TAGGED_OBJECT_TYPE) {
+				int type = odb_read_object_info(r->objects, &o->oid, NULL);
+				if (type < 0 || !object_as_type(o, type, 0))
+					return PEEL_INVALID;
+			}
+		} else {
+			o = NULL;
+		}
+	}
 	if (!o)
 		return PEEL_INVALID;
 
@@ -517,12 +531,11 @@ struct parsed_object_pool *parsed_object_pool_new(struct repository *repo)
 	memset(o, 0, sizeof(*o));
 
 	o->repo = repo;
-	o->blob_state = allocate_alloc_state();
-	o->tree_state = allocate_alloc_state();
-	o->commit_state = allocate_alloc_state();
-	o->tag_state = allocate_alloc_state();
-	o->object_state = allocate_alloc_state();
-
+	o->blob_state = alloc_state_alloc();
+	o->tree_state = alloc_state_alloc();
+	o->commit_state = alloc_state_alloc();
+	o->tag_state = alloc_state_alloc();
+	o->object_state = alloc_state_alloc();
 	o->is_shallow = -1;
 	CALLOC_ARRAY(o->shallow_stat, 1);
 
@@ -573,16 +586,11 @@ void parsed_object_pool_clear(struct parsed_object_pool *o)
 	o->buffer_slab = NULL;
 
 	parsed_object_pool_reset_commit_grafts(o);
-	clear_alloc_state(o->blob_state);
-	clear_alloc_state(o->tree_state);
-	clear_alloc_state(o->commit_state);
-	clear_alloc_state(o->tag_state);
-	clear_alloc_state(o->object_state);
+	alloc_state_free_and_null(&o->blob_state);
+	alloc_state_free_and_null(&o->tree_state);
+	alloc_state_free_and_null(&o->commit_state);
+	alloc_state_free_and_null(&o->tag_state);
+	alloc_state_free_and_null(&o->object_state);
 	stat_validity_clear(o->shallow_stat);
-	FREE_AND_NULL(o->blob_state);
-	FREE_AND_NULL(o->tree_state);
-	FREE_AND_NULL(o->commit_state);
-	FREE_AND_NULL(o->tag_state);
-	FREE_AND_NULL(o->object_state);
 	FREE_AND_NULL(o->shallow_stat);
 }
diff --git a/object.h b/object.h
index 8c3c1c4..4bca957 100644
--- a/object.h
+++ b/object.h
@@ -75,11 +75,11 @@ void object_array_init(struct object_array *array);
  * http-push.c:                          11-----14
  * commit-graph.c:                                15
  * commit-reach.c:                                  16-----19
+ * builtin/last-modified.c:                         1617
  * sha1-name.c:                                              20
  * list-objects-filter.c:                                      21
  * bloom.c:                                                    2122
  * builtin/fsck.c:           0--3
- * builtin/gc.c:             0
  * builtin/index-pack.c:                                     2021
  * reflog.c:                           10--12
  * builtin/show-branch.c:    0-------------------------------------------26
@@ -287,6 +287,17 @@ enum peel_status {
 	PEEL_BROKEN = -4
 };
 
+enum peel_object_flags {
+	/*
+	 * Always verify the object type of the tagged object, even in the case
+	 * where the looked-up object already has an object type. This can be
+	 * useful when the tagged object type may be invalid. One such case is
+	 * when looking up objects via tags, where we blindly trust the object
+	 * type declared by the tag.
+	 */
+	PEEL_OBJECT_VERIFY_TAGGED_OBJECT_TYPE = (1 << 0),
+};
+
 /*
  * Peel the named object; i.e., if the object is a tag, resolve the
  * tag recursively until a non-tag is found.  If successful, store the
@@ -295,7 +306,9 @@ enum peel_status {
  * and leave oid unchanged.
  */
 enum peel_status peel_object(struct repository *r,
-			     const struct object_id *name, struct object_id *oid);
+			     const struct object_id *name,
+			     struct object_id *oid,
+			     unsigned flags);
 
 struct object_list *object_list_insert(struct object *item,
 				       struct object_list **list_p);
diff --git a/odb.c b/odb.c
index 2a92a01..3ec21ef 100644
--- a/odb.c
+++ b/odb.c
@@ -86,17 +86,16 @@ int odb_mkstemp(struct object_database *odb,
 /*
  * Return non-zero iff the path is usable as an alternate object database.
  */
-static int alt_odb_usable(struct object_database *o,
-			  struct strbuf *path,
-			  const char *normalized_objdir, khiter_t *pos)
+static int alt_odb_usable(struct object_database *o, const char *path,
+			  const char *normalized_objdir)
 {
 	int r;
 
 	/* Detect cases where alternate disappeared */
-	if (!is_directory(path->buf)) {
+	if (!is_directory(path)) {
 		error(_("object directory %s does not exist; "
 			"check .git/objects/info/alternates"),
-		      path->buf);
+		      path);
 		return 0;
 	}
 
@@ -113,11 +112,14 @@ static int alt_odb_usable(struct object_database *o,
 		assert(r == 1); /* never used */
 		kh_value(o->source_by_path, p) = o->sources;
 	}
-	if (fspatheq(path->buf, normalized_objdir))
+
+	if (fspatheq(path, normalized_objdir))
 		return 0;
-	*pos = kh_put_odb_path_map(o->source_by_path, path->buf, &r);
-	/* r: 0 = exists, 1 = never used, 2 = deleted */
-	return r == 0 ? 0 : 1;
+
+	if (kh_get_odb_path_map(o->source_by_path, path) < kh_end(o->source_by_path))
+		return 0;
+
+	return 1;
 }
 
 /*
@@ -139,23 +141,37 @@ static void read_info_alternates(struct object_database *odb,
 				 const char *relative_base,
 				 int depth);
 
-static int link_alt_odb_entry(struct object_database *odb,
-			      const struct strbuf *entry,
-			      const char *relative_base,
-			      int depth,
-			      const char *normalized_objdir)
+struct odb_source *odb_source_new(struct object_database *odb,
+				  const char *path,
+				  bool local)
 {
-	struct odb_source *alternate;
+	struct odb_source *source;
+
+	CALLOC_ARRAY(source, 1);
+	source->odb = odb;
+	source->local = local;
+	source->path = xstrdup(path);
+	source->loose = odb_source_loose_new(source);
+
+	return source;
+}
+
+static struct odb_source *link_alt_odb_entry(struct object_database *odb,
+					     const char *dir,
+					     const char *relative_base,
+					     int depth)
+{
+	struct odb_source *alternate = NULL;
 	struct strbuf pathbuf = STRBUF_INIT;
 	struct strbuf tmp = STRBUF_INIT;
 	khiter_t pos;
-	int ret = -1;
+	int ret;
 
-	if (!is_absolute_path(entry->buf) && relative_base) {
+	if (!is_absolute_path(dir) && relative_base) {
 		strbuf_realpath(&pathbuf, relative_base, 1);
 		strbuf_addch(&pathbuf, '/');
 	}
-	strbuf_addbuf(&pathbuf, entry);
+	strbuf_addstr(&pathbuf, dir);
 
 	if (!strbuf_realpath(&tmp, pathbuf.buf, 0)) {
 		error(_("unable to normalize alternate object path: %s"),
@@ -171,28 +187,30 @@ static int link_alt_odb_entry(struct object_database *odb,
 	while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/')
 		strbuf_setlen(&pathbuf, pathbuf.len - 1);
 
-	if (!alt_odb_usable(odb, &pathbuf, normalized_objdir, &pos))
+	strbuf_reset(&tmp);
+	strbuf_realpath(&tmp, odb->sources->path, 1);
+
+	if (!alt_odb_usable(odb, pathbuf.buf, tmp.buf))
 		goto error;
 
-	CALLOC_ARRAY(alternate, 1);
-	alternate->odb = odb;
-	/* pathbuf.buf is already in r->objects->source_by_path */
-	alternate->path = strbuf_detach(&pathbuf, NULL);
+	alternate = odb_source_new(odb, pathbuf.buf, false);
 
 	/* add the alternate entry */
 	*odb->sources_tail = alternate;
 	odb->sources_tail = &(alternate->next);
-	alternate->next = NULL;
-	assert(odb->source_by_path);
+
+	pos = kh_put_odb_path_map(odb->source_by_path, alternate->path, &ret);
+	if (!ret)
+		BUG("source must not yet exist");
 	kh_value(odb->source_by_path, pos) = alternate;
 
 	/* recursively add alternates */
 	read_info_alternates(odb, alternate->path, depth + 1);
-	ret = 0;
+
  error:
 	strbuf_release(&tmp);
 	strbuf_release(&pathbuf);
-	return ret;
+	return alternate;
 }
 
 static const char *parse_alt_odb_entry(const char *string,
@@ -227,8 +245,7 @@ static const char *parse_alt_odb_entry(const char *string,
 static void link_alt_odb_entries(struct object_database *odb, const char *alt,
 				 int sep, const char *relative_base, int depth)
 {
-	struct strbuf objdirbuf = STRBUF_INIT;
-	struct strbuf entry = STRBUF_INIT;
+	struct strbuf dir = STRBUF_INIT;
 
 	if (!alt || !*alt)
 		return;
@@ -239,17 +256,13 @@ static void link_alt_odb_entries(struct object_database *odb, const char *alt,
 		return;
 	}
 
-	strbuf_realpath(&objdirbuf, odb->sources->path, 1);
-
 	while (*alt) {
-		alt = parse_alt_odb_entry(alt, sep, &entry);
-		if (!entry.len)
+		alt = parse_alt_odb_entry(alt, sep, &dir);
+		if (!dir.len)
 			continue;
-		link_alt_odb_entry(odb, &entry,
-				   relative_base, depth, objdirbuf.buf);
+		link_alt_odb_entry(odb, dir.buf, relative_base, depth);
 	}
-	strbuf_release(&entry);
-	strbuf_release(&objdirbuf);
+	strbuf_release(&dir);
 }
 
 static void read_info_alternates(struct object_database *odb,
@@ -272,7 +285,7 @@ static void read_info_alternates(struct object_database *odb,
 }
 
 void odb_add_to_alternates_file(struct object_database *odb,
-				const char *reference)
+				const char *dir)
 {
 	struct lock_file lock = LOCK_INIT;
 	char *alts = repo_git_path(odb->repo, "objects/info/alternates");
@@ -289,7 +302,7 @@ void odb_add_to_alternates_file(struct object_database *odb,
 		struct strbuf line = STRBUF_INIT;
 
 		while (strbuf_getline(&line, in) != EOF) {
-			if (!strcmp(reference, line.buf)) {
+			if (!strcmp(dir, line.buf)) {
 				found = 1;
 				break;
 			}
@@ -305,27 +318,24 @@ void odb_add_to_alternates_file(struct object_database *odb,
 	if (found) {
 		rollback_lock_file(&lock);
 	} else {
-		fprintf_or_die(out, "%s\n", reference);
+		fprintf_or_die(out, "%s\n", dir);
 		if (commit_lock_file(&lock))
 			die_errno(_("unable to move new alternates file into place"));
 		if (odb->loaded_alternates)
-			link_alt_odb_entries(odb, reference,
-					     '\n', NULL, 0);
+			link_alt_odb_entries(odb, dir, '\n', NULL, 0);
 	}
 	free(alts);
 }
 
-void odb_add_to_alternates_memory(struct object_database *odb,
-				  const char *reference)
+struct odb_source *odb_add_to_alternates_memory(struct object_database *odb,
+						const char *dir)
 {
 	/*
 	 * Make sure alternates are initialized, or else our entry may be
 	 * overwritten when they are.
 	 */
 	odb_prepare_alternates(odb);
-
-	link_alt_odb_entries(odb, reference,
-			     '\n', NULL, 0);
+	return link_alt_odb_entry(odb, dir, NULL, 0);
 }
 
 struct odb_source *odb_set_temporary_primary_source(struct object_database *odb,
@@ -343,9 +353,7 @@ struct odb_source *odb_set_temporary_primary_source(struct object_database *odb,
 	 * Make a new primary odb and link the old primary ODB in as an
 	 * alternate
 	 */
-	source = xcalloc(1, sizeof(*source));
-	source->odb = odb;
-	source->path = xstrdup(dir);
+	source = odb_source_new(odb, dir, false);
 
 	/*
 	 * Disable ref updates while a temporary odb is active, since
@@ -358,11 +366,10 @@ struct odb_source *odb_set_temporary_primary_source(struct object_database *odb,
 	return source->next;
 }
 
-static void free_object_directory(struct odb_source *source)
+static void odb_source_free(struct odb_source *source)
 {
 	free(source->path);
-	odb_clear_loose_cache(source);
-	loose_object_map_clear(&source->loose_map);
+	odb_source_loose_free(source->loose);
 	free(source);
 }
 
@@ -380,7 +387,7 @@ void odb_restore_primary_source(struct object_database *odb,
 		BUG("we expect the old primary object store to be the first alternate");
 
 	odb->sources = restore_source;
-	free_object_directory(cur_source);
+	odb_source_free(cur_source);
 }
 
 char *compute_alternate_path(const char *path, struct strbuf *err)
@@ -463,6 +470,12 @@ struct odb_source *odb_find_source(struct object_database *odb, const char *obj_
 	free(obj_dir_real);
 	strbuf_release(&odb_path_real);
 
+	return source;
+}
+
+struct odb_source *odb_find_source_or_die(struct object_database *odb, const char *obj_dir)
+{
+	struct odb_source *source = odb_find_source(odb, obj_dir);
 	if (!source)
 		die(_("could not find object directory matching %s"), obj_dir);
 	return source;
@@ -684,17 +697,22 @@ static int do_oid_object_info_extended(struct object_database *odb,
 		return 0;
 	}
 
+	odb_prepare_alternates(odb);
+
 	while (1) {
+		struct odb_source *source;
+
 		if (find_pack_entry(odb->repo, real, &e))
 			break;
 
 		/* Most likely it's a loose object. */
-		if (!loose_object_info(odb->repo, real, oi, flags))
-			return 0;
+		for (source = odb->sources; source; source = source->next)
+			if (!odb_source_loose_read_object_info(source, real, oi, flags))
+				return 0;
 
 		/* Not a loose object; someone else may have just packed it. */
 		if (!(flags & OBJECT_INFO_QUICK)) {
-			reprepare_packed_git(odb->repo);
+			odb_reprepare(odb->repo->objects);
 			if (find_pack_entry(odb->repo, real, &e))
 				break;
 		}
@@ -969,6 +987,22 @@ int odb_has_object(struct object_database *odb, const struct object_id *oid,
 	return odb_read_object_info_extended(odb, oid, NULL, object_info_flags) >= 0;
 }
 
+int odb_freshen_object(struct object_database *odb,
+		       const struct object_id *oid)
+{
+	struct odb_source *source;
+
+	if (packfile_store_freshen_object(odb->packfiles, oid))
+		return 1;
+
+	odb_prepare_alternates(odb);
+	for (source = odb->sources; source; source = source->next)
+		if (odb_source_loose_freshen_object(source, oid))
+			return 1;
+
+	return 0;
+}
+
 void odb_assert_oid_type(struct object_database *odb,
 			 const struct object_id *oid, enum object_type expect)
 {
@@ -987,7 +1021,15 @@ int odb_write_object_ext(struct object_database *odb,
 			 struct object_id *compat_oid,
 			 unsigned flags)
 {
-	return write_object_file(odb->sources, buf, len, type, oid, compat_oid, flags);
+	return odb_source_loose_write_object(odb->sources, buf, len, type,
+					     oid, compat_oid, flags);
+}
+
+int odb_write_object_stream(struct object_database *odb,
+			    struct odb_write_stream *stream, size_t len,
+			    struct object_id *oid)
+{
+	return odb_source_loose_write_stream(odb->sources, stream, len, oid);
 }
 
 struct object_database *odb_new(struct repository *repo)
@@ -996,20 +1038,19 @@ struct object_database *odb_new(struct repository *repo)
 
 	memset(o, 0, sizeof(*o));
 	o->repo = repo;
-	INIT_LIST_HEAD(&o->packed_git_mru);
-	hashmap_init(&o->pack_map, pack_map_entry_cmp, NULL, 0);
+	o->packfiles = packfile_store_new(o);
 	pthread_mutex_init(&o->replace_mutex, NULL);
 	string_list_init_dup(&o->submodule_source_paths);
 	return o;
 }
 
-static void free_object_directories(struct object_database *o)
+static void odb_free_sources(struct object_database *o)
 {
 	while (o->sources) {
 		struct odb_source *next;
 
 		next = o->sources->next;
-		free_object_directory(o->sources);
+		odb_source_free(o->sources);
 		o->sources = next;
 	}
 	kh_destroy_odb_path_map(o->source_by_path);
@@ -1027,7 +1068,7 @@ void odb_clear(struct object_database *o)
 	o->commit_graph = NULL;
 	o->commit_graph_attempted = 0;
 
-	free_object_directories(o);
+	odb_free_sources(o);
 	o->sources_tail = NULL;
 	o->loaded_alternates = 0;
 
@@ -1035,19 +1076,44 @@ void odb_clear(struct object_database *o)
 		free((char *) o->cached_objects[i].value.buf);
 	FREE_AND_NULL(o->cached_objects);
 
-	INIT_LIST_HEAD(&o->packed_git_mru);
 	close_object_store(o);
+	packfile_store_free(o->packfiles);
+	o->packfiles = NULL;
+
+	string_list_clear(&o->submodule_source_paths, 0);
+}
+
+void odb_reprepare(struct object_database *o)
+{
+	struct odb_source *source;
+
+	obj_read_lock();
 
 	/*
-	 * `close_object_store()` only closes the packfiles, but doesn't free
-	 * them. We thus have to do this manually.
+	 * 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.
 	 */
-	for (struct packed_git *p = o->packed_git, *next; p; p = next) {
-		next = p->next;
-		free(p);
-	}
-	o->packed_git = NULL;
+	o->loaded_alternates = 0;
+	odb_prepare_alternates(o);
 
-	hashmap_clear(&o->pack_map);
-	string_list_clear(&o->submodule_source_paths, 0);
+	for (source = o->sources; source; source = source->next)
+		odb_source_loose_reprepare(source);
+
+	o->approximate_object_count_valid = 0;
+
+	packfile_store_reprepare(o->packfiles);
+
+	obj_read_unlock();
+}
+
+struct odb_transaction *odb_transaction_begin(struct object_database *odb)
+{
+	return object_file_transaction_begin(odb->sources);
+}
+
+void odb_transaction_commit(struct odb_transaction *transaction)
+{
+	object_file_transaction_commit(transaction);
 }
diff --git a/odb.h b/odb.h
index e8b9dff..9bb2800 100644
--- a/odb.h
+++ b/odb.h
@@ -3,7 +3,6 @@
 
 #include "hashmap.h"
 #include "object.h"
-#include "list.h"
 #include "oidset.h"
 #include "oidmap.h"
 #include "string-list.h"
@@ -16,6 +15,14 @@ struct repository;
 struct multi_pack_index;
 
 /*
+ * Set this to 0 to prevent odb_read_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;
+
+/*
  * Compute the exact path an alternate is at and returns it. In case of
  * error NULL is returned and the human readable error is added to `err`
  * `path` may be relative and should point to $GIT_DIR.
@@ -41,20 +48,8 @@ struct odb_source {
 	/* Object database that owns this object source. */
 	struct object_database *odb;
 
-	/*
-	 * Used to store the results of readdir(3) calls when we are OK
-	 * sacrificing accuracy due to races for speed. That includes
-	 * object existence with OBJECT_INFO_QUICK, as well as
-	 * our search for unique abbreviated hashes. Don't use it for tasks
-	 * requiring greater accuracy!
-	 *
-	 * Be sure to call odb_load_loose_cache() before using.
-	 */
-	uint32_t loose_objects_subdir_seen[8]; /* 256 bits */
-	struct oidtree *loose_objects_cache;
-
-	/* Map between object IDs for loose objects. */
-	struct loose_object_map *loose_map;
+	/* Private state for loose objects. */
+	struct odb_source_loose *loose;
 
 	/*
 	 * private data
@@ -64,6 +59,14 @@ struct odb_source {
 	struct multi_pack_index *midx;
 
 	/*
+	 * Figure out whether this is the local source of the owning
+	 * repository, which would typically be its ".git/objects" directory.
+	 * This local object directory is usually where objects would be
+	 * written to.
+	 */
+	bool local;
+
+	/*
 	 * This is a temporary object store created by the tmp_objdir
 	 * facility. Disable ref updates since the objects in the store
 	 * might be discarded on rollback.
@@ -82,8 +85,14 @@ struct odb_source {
 	char *path;
 };
 
+struct odb_source *odb_source_new(struct object_database *odb,
+				  const char *path,
+				  bool local);
+
 struct packed_git;
+struct packfile_store;
 struct cached_object_entry;
+struct odb_transaction;
 
 /*
  * The object database encapsulates access to objects in a repository. It
@@ -95,6 +104,13 @@ struct object_database {
 	struct repository *repo;
 
 	/*
+	 * State of current current object database transaction. Only one
+	 * transaction may be pending at a time. Is NULL when no transaction is
+	 * configured.
+	 */
+	struct odb_transaction *transaction;
+
+	/*
 	 * Set of all object directories; the main directory is first (and
 	 * cannot be NULL after initialization). Subsequent directories are
 	 * alternates.
@@ -123,20 +139,8 @@ struct object_database {
 	struct commit_graph *commit_graph;
 	unsigned commit_graph_attempted : 1; /* if loading has been attempted */
 
-	/*
-	 * private data
-	 *
-	 * should only be accessed directly by packfile.c
-	 */
-
-	struct packed_git *packed_git;
-	/* A most-recently-used ordered version of the packed_git list. */
-	struct list_head packed_git_mru;
-
-	struct {
-		struct packed_git **packs;
-		unsigned flags;
-	} kept_pack_cache;
+	/* Should only be accessed directly by packfile.c and midx.c. */
+	struct packfile_store *packfiles;
 
 	/*
 	 * This is meant to hold a *small* number of objects that you would
@@ -148,12 +152,6 @@ struct object_database {
 	size_t cached_object_nr, cached_object_alloc;
 
 	/*
-	 * A map of packfiles to packed_git structs for tracking which
-	 * packs have been loaded already.
-	 */
-	struct hashmap pack_map;
-
-	/*
 	 * A fast, rough count of the number of objects in the repository.
 	 * These two fields are not meant for direct access. Use
 	 * repo_approximate_object_count() instead.
@@ -162,12 +160,6 @@ struct object_database {
 	unsigned approximate_object_count_valid : 1;
 
 	/*
-	 * Whether packed_git has already been populated with this repository's
-	 * packs.
-	 */
-	unsigned packed_git_initialized : 1;
-
-	/*
 	 * Submodule source paths that will be added as additional sources to
 	 * allow lookup of submodule objects via the main object database.
 	 */
@@ -178,11 +170,33 @@ struct object_database *odb_new(struct repository *repo);
 void odb_clear(struct object_database *o);
 
 /*
- * Find source by its object directory path. Dies in case the source couldn't
- * be found.
+ * Clear caches, reload alternates and then reload object sources so that new
+ * objects may become accessible.
+ */
+void odb_reprepare(struct object_database *o);
+
+/*
+ * Starts an ODB transaction. Subsequent objects are written to the transaction
+ * and not committed until odb_transaction_commit() is invoked on the
+ * transaction. If the ODB already has a pending transaction, NULL is returned.
+ */
+struct odb_transaction *odb_transaction_begin(struct object_database *odb);
+
+/*
+ * Commits an ODB transaction making the written objects visible. If the
+ * specified transaction is NULL, the function is a no-op.
+ */
+void odb_transaction_commit(struct odb_transaction *transaction);
+
+/*
+ * Find source by its object directory path. Returns a `NULL` pointer in case
+ * the source could not be found.
  */
 struct odb_source *odb_find_source(struct object_database *odb, const char *obj_dir);
 
+/* Same as `odb_find_source()`, but dies in case the source doesn't exist. */
+struct odb_source *odb_find_source_or_die(struct object_database *odb, const char *obj_dir);
+
 /*
  * Replace the current writable object directory with the specified temporary
  * object directory; returns the former primary source.
@@ -257,8 +271,8 @@ void odb_add_to_alternates_file(struct object_database *odb,
  * recursive alternates it points to), but do not modify the on-disk alternates
  * file.
  */
-void odb_add_to_alternates_memory(struct object_database *odb,
-				  const char *dir);
+struct odb_source *odb_add_to_alternates_memory(struct object_database *odb,
+						const char *dir);
 
 /*
  * Read an object from the database. Returns the object data and assigns object
@@ -382,6 +396,9 @@ int odb_has_object(struct object_database *odb,
 		   const struct object_id *oid,
 		   unsigned flags);
 
+int odb_freshen_object(struct object_database *odb,
+		       const struct object_id *oid);
+
 void odb_assert_oid_type(struct object_database *odb,
 			 const struct object_id *oid, enum object_type expect);
 
@@ -475,4 +492,14 @@ static inline int odb_write_object(struct object_database *odb,
 	return odb_write_object_ext(odb, buf, len, type, oid, NULL, 0);
 }
 
+struct odb_write_stream {
+	const void *(*read)(struct odb_write_stream *, unsigned long *len);
+	void *data;
+	int is_finished;
+};
+
+int odb_write_object_stream(struct object_database *odb,
+			    struct odb_write_stream *stream, size_t len,
+			    struct object_id *oid);
+
 #endif /* ODB_H */
diff --git a/oss-fuzz/fuzz-commit-graph.c b/oss-fuzz/fuzz-commit-graph.c
index fbb77fe..fb8b878 100644
--- a/oss-fuzz/fuzz-commit-graph.c
+++ b/oss-fuzz/fuzz-commit-graph.c
@@ -4,9 +4,6 @@
 #include "commit-graph.h"
 #include "repository.h"
 
-struct commit_graph *parse_commit_graph(struct repo_settings *s,
-					void *graph_map, size_t graph_size);
-
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
@@ -22,9 +19,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 	 * possible.
 	 */
 	repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
+	the_repository->settings.initialized = 1;
 	the_repository->settings.commit_graph_generation_version = 2;
 	the_repository->settings.commit_graph_changed_paths_version = 1;
-	g = parse_commit_graph(&the_repository->settings, (void *)data, size);
+	g = parse_commit_graph(the_repository, (void *)data, size);
 	repo_clear(the_repository);
 	free_commit_graph(g);
 
diff --git a/pack-bitmap.c b/pack-bitmap.c
index d14421e..291e1a9 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -216,7 +216,7 @@ static uint32_t bitmap_num_objects(struct bitmap_index *index)
 static struct repository *bitmap_repo(struct bitmap_index *bitmap_git)
 {
 	if (bitmap_is_midx(bitmap_git))
-		return bitmap_git->midx->repo;
+		return bitmap_git->midx->source->odb->repo;
 	return bitmap_git->pack->repo;
 }
 
@@ -418,13 +418,12 @@ char *midx_bitmap_filename(struct multi_pack_index *midx)
 {
 	struct strbuf buf = STRBUF_INIT;
 	if (midx->has_chain)
-		get_split_midx_filename_ext(midx->repo->hash_algo, &buf,
-					    midx->object_dir,
+		get_split_midx_filename_ext(midx->source, &buf,
 					    get_midx_checksum(midx),
 					    MIDX_EXT_BITMAP);
 	else
-		get_midx_filename_ext(midx->repo->hash_algo, &buf,
-				      midx->object_dir, get_midx_checksum(midx),
+		get_midx_filename_ext(midx->source, &buf,
+				      get_midx_checksum(midx),
 				      MIDX_EXT_BITMAP);
 
 	return strbuf_detach(&buf, NULL);
@@ -463,7 +462,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
 
 	if (bitmap_git->pack || bitmap_git->midx) {
 		struct strbuf buf = STRBUF_INIT;
-		get_midx_filename(midx->repo->hash_algo, &buf, midx->object_dir);
+		get_midx_filename(midx->source, &buf);
 		trace2_data_string("bitmap", bitmap_repo(bitmap_git),
 				   "ignoring extra midx bitmap file", buf.buf);
 		close(fd);
@@ -493,7 +492,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
 	}
 
 	for (i = 0; i < bitmap_git->midx->num_packs + bitmap_git->midx->num_packs_in_base; i++) {
-		if (prepare_midx_pack(bitmap_repo(bitmap_git), bitmap_git->midx, i)) {
+		if (prepare_midx_pack(bitmap_git->midx, i)) {
 			warning(_("could not open pack %s"),
 				bitmap_git->midx->pack_names[i]);
 			goto cleanup;
@@ -665,7 +664,7 @@ static int open_pack_bitmap(struct repository *r,
 	struct packed_git *p;
 	int ret = -1;
 
-	for (p = get_all_packs(r); p; p = p->next) {
+	repo_for_each_pack(r, p) {
 		if (open_pack_bitmap_1(bitmap_git, p) == 0) {
 			ret = 0;
 			/*
@@ -2466,7 +2465,7 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
 		struct multi_pack_index *m = bitmap_git->midx;
 		for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) {
 			struct bitmapped_pack pack;
-			if (nth_bitmapped_pack(r, bitmap_git->midx, &pack, i) < 0) {
+			if (nth_bitmapped_pack(bitmap_git->midx, &pack, i) < 0) {
 				warning(_("unable to load pack: '%s', disabling pack-reuse"),
 					bitmap_git->midx->pack_names[i]);
 				free(packs);
@@ -3348,6 +3347,7 @@ static int verify_bitmap_file(const struct git_hash_algo *algop,
 int verify_bitmap_files(struct repository *r)
 {
 	struct odb_source *source;
+	struct packed_git *p;
 	int res = 0;
 
 	odb_prepare_alternates(r->objects);
@@ -3363,8 +3363,7 @@ int verify_bitmap_files(struct repository *r)
 		free(midx_bitmap_name);
 	}
 
-	for (struct packed_git *p = get_all_packs(r);
-	     p; p = p->next) {
+	repo_for_each_pack(r, p) {
 		char *pack_bitmap_name = pack_bitmap_filename(p);
 		res |= verify_bitmap_file(r->hash_algo, pack_bitmap_name);
 		free(pack_bitmap_name);
diff --git a/pack-objects.c b/pack-objects.c
index 7b86ae8..48510dd 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -96,13 +96,13 @@ static void prepare_in_pack_by_idx(struct packing_data *pdata)
 	 * (i.e. in_pack_idx also zero) should return NULL.
 	 */
 	mapping[cnt++] = NULL;
-	for (p = get_all_packs(pdata->repo); p; p = p->next, cnt++) {
+	repo_for_each_pack(pdata->repo, p) {
 		if (cnt == nr) {
 			free(mapping);
 			return;
 		}
 		p->index = cnt;
-		mapping[cnt] = p;
+		mapping[cnt++] = p;
 	}
 	pdata->in_pack_by_idx = mapping;
 }
diff --git a/pack-refs.c b/pack-refs.c
new file mode 100644
index 0000000..eb6b2ba
--- /dev/null
+++ b/pack-refs.c
@@ -0,0 +1,56 @@
+#include "builtin.h"
+#include "config.h"
+#include "environment.h"
+#include "pack-refs.h"
+#include "parse-options.h"
+#include "refs.h"
+#include "revision.h"
+
+int pack_refs_core(int argc,
+		   const char **argv,
+		   const char *prefix,
+		   struct repository *repo,
+		   const char * const *usage_opts)
+{
+	struct ref_exclusions excludes = REF_EXCLUSIONS_INIT;
+	struct string_list included_refs = STRING_LIST_INIT_NODUP;
+	struct refs_optimize_opts optimize_opts = {
+		.exclusions = &excludes,
+		.includes = &included_refs,
+		.flags = REFS_OPTIMIZE_PRUNE,
+	};
+	struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP;
+	struct string_list_item *item;
+	int pack_all = 0;
+	int ret;
+
+	struct option opts[] = {
+		OPT_BOOL(0, "all",   &pack_all, N_("pack everything")),
+		OPT_BIT(0, "prune", &optimize_opts.flags, N_("prune loose refs (default)"), REFS_OPTIMIZE_PRUNE),
+		OPT_BIT(0, "auto", &optimize_opts.flags, N_("auto-pack refs as needed"), REFS_OPTIMIZE_AUTO),
+		OPT_STRING_LIST(0, "include", optimize_opts.includes, N_("pattern"),
+			N_("references to include")),
+		OPT_STRING_LIST(0, "exclude", &option_excluded_refs, N_("pattern"),
+			N_("references to exclude")),
+		OPT_END(),
+	};
+	repo_config(repo, git_default_config, NULL);
+	if (parse_options(argc, argv, prefix, opts, usage_opts, 0))
+		usage_with_options(usage_opts, opts);
+
+	for_each_string_list_item(item, &option_excluded_refs)
+		add_ref_exclusion(optimize_opts.exclusions, item->string);
+
+	if (pack_all)
+		string_list_append(optimize_opts.includes, "*");
+
+	if (!optimize_opts.includes->nr)
+		string_list_append(optimize_opts.includes, "refs/tags/*");
+
+	ret = refs_optimize(get_main_ref_store(repo), &optimize_opts);
+
+	clear_ref_exclusions(&excludes);
+	string_list_clear(&included_refs, 0);
+	string_list_clear(&option_excluded_refs, 0);
+	return ret;
+}
diff --git a/pack-refs.h b/pack-refs.h
new file mode 100644
index 0000000..5de27e7
--- /dev/null
+++ b/pack-refs.h
@@ -0,0 +1,23 @@
+#ifndef PACK_REFS_H
+#define PACK_REFS_H
+
+struct repository;
+
+/*
+ * Shared usage string for options common to git-pack-refs(1)
+ * and git-refs-optimize(1). The command-specific part (e.g., "git refs optimize ")
+ * must be prepended by the caller.
+ */
+#define PACK_REFS_OPTS \
+	"[--all] [--no-prune] [--auto] [--include <pattern>] [--exclude <pattern>]"
+
+/*
+ * The core logic for pack-refs and its clones.
+ */
+int pack_refs_core(int argc,
+		   const char **argv,
+		   const char *prefix,
+		   struct repository *repo,
+		   const char * const *usage_opts);
+
+#endif /* PACK_REFS_H */
diff --git a/pack-revindex.c b/pack-revindex.c
index 0cc422a..d0791cc 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -379,25 +379,25 @@ int load_midx_revindex(struct multi_pack_index *m)
 		 * not want to accidentally call munmap() in the middle of the
 		 * MIDX.
 		 */
-		trace2_data_string("load_midx_revindex", m->repo,
+		trace2_data_string("load_midx_revindex", m->source->odb->repo,
 				   "source", "midx");
 		m->revindex_data = (const uint32_t *)m->chunk_revindex;
 		return 0;
 	}
 
-	trace2_data_string("load_midx_revindex", m->repo,
+	trace2_data_string("load_midx_revindex", m->source->odb->repo,
 			   "source", "rev");
 
 	if (m->has_chain)
-		get_split_midx_filename_ext(m->repo->hash_algo, &revindex_name,
-					    m->object_dir, get_midx_checksum(m),
+		get_split_midx_filename_ext(m->source, &revindex_name,
+					    get_midx_checksum(m),
 					    MIDX_EXT_REV);
 	else
-		get_midx_filename_ext(m->repo->hash_algo, &revindex_name,
-				      m->object_dir, get_midx_checksum(m),
+		get_midx_filename_ext(m->source, &revindex_name,
+				      get_midx_checksum(m),
 				      MIDX_EXT_REV);
 
-	ret = load_revindex_from_disk(m->repo->hash_algo,
+	ret = load_revindex_from_disk(m->source->odb->repo->hash_algo,
 				      revindex_name.buf,
 				      m->num_objects,
 				      &m->revindex_map,
diff --git a/packfile.c b/packfile.c
index 5d73932..9cc11b6 100644
--- a/packfile.c
+++ b/packfile.c
@@ -47,6 +47,89 @@ static size_t pack_mapped;
 #define SZ_FMT PRIuMAX
 static inline uintmax_t sz_fmt(size_t s) { return s; }
 
+void packfile_list_clear(struct packfile_list *list)
+{
+	struct packfile_list_entry *e, *next;
+
+	for (e = list->head; e; e = next) {
+		next = e->next;
+		free(e);
+	}
+
+	list->head = list->tail = NULL;
+}
+
+static struct packfile_list_entry *packfile_list_remove_internal(struct packfile_list *list,
+								 struct packed_git *pack)
+{
+	struct packfile_list_entry *e, *prev;
+
+	for (e = list->head, prev = NULL; e; prev = e, e = e->next) {
+		if (e->pack != pack)
+			continue;
+
+		if (prev)
+			prev->next = e->next;
+		if (list->head == e)
+			list->head = e->next;
+		if (list->tail == e)
+			list->tail = prev;
+
+		return e;
+	}
+
+	return NULL;
+}
+
+void packfile_list_remove(struct packfile_list *list, struct packed_git *pack)
+{
+	free(packfile_list_remove_internal(list, pack));
+}
+
+void packfile_list_prepend(struct packfile_list *list, struct packed_git *pack)
+{
+	struct packfile_list_entry *entry;
+
+	entry = packfile_list_remove_internal(list, pack);
+	if (!entry) {
+		entry = xmalloc(sizeof(*entry));
+		entry->pack = pack;
+	}
+	entry->next = list->head;
+
+	list->head = entry;
+	if (!list->tail)
+		list->tail = entry;
+}
+
+void packfile_list_append(struct packfile_list *list, struct packed_git *pack)
+{
+	struct packfile_list_entry *entry;
+
+	entry = packfile_list_remove_internal(list, pack);
+	if (!entry) {
+		entry = xmalloc(sizeof(*entry));
+		entry->pack = pack;
+	}
+	entry->next = NULL;
+
+	if (list->tail) {
+		list->tail->next = entry;
+		list->tail = entry;
+	} else {
+		list->head = list->tail = entry;
+	}
+}
+
+struct packed_git *packfile_list_find_oid(struct packfile_list_entry *packs,
+					  const struct object_id *oid)
+{
+	for (; packs; packs = packs->next)
+		if (find_pack_entry_one(oid, packs->pack))
+			return packs->pack;
+	return NULL;
+}
+
 void pack_report(struct repository *repo)
 {
 	fprintf(stderr,
@@ -273,13 +356,14 @@ static void scan_windows(struct packed_git *p,
 
 static int unuse_one_window(struct packed_git *current)
 {
-	struct packed_git *p, *lru_p = NULL;
+	struct packfile_list_entry *e;
+	struct packed_git *lru_p = NULL;
 	struct pack_window *lru_w = NULL, *lru_l = NULL;
 
 	if (current)
 		scan_windows(current, &lru_p, &lru_w, &lru_l);
-	for (p = current->repo->objects->packed_git; p; p = p->next)
-		scan_windows(p, &lru_p, &lru_w, &lru_l);
+	for (e = current->repo->objects->packfiles->packs.head; e; e = e->next)
+		scan_windows(e->pack, &lru_p, &lru_w, &lru_l);
 	if (lru_p) {
 		munmap(lru_w->base, lru_w->len);
 		pack_mapped -= lru_w->len;
@@ -362,13 +446,8 @@ void close_pack(struct packed_git *p)
 void close_object_store(struct object_database *o)
 {
 	struct odb_source *source;
-	struct packed_git *p;
 
-	for (p = o->packed_git; p; p = p->next)
-		if (p->do_not_close)
-			BUG("want to close pack marked 'do-not-close'");
-		else
-			close_pack(p);
+	packfile_store_close(o->packfiles);
 
 	for (source = o->sources; source; source = source->next) {
 		if (source->midx)
@@ -464,14 +543,15 @@ static void find_lru_pack(struct packed_git *p, struct packed_git **lru_p, struc
 
 static int close_one_pack(struct repository *r)
 {
-	struct packed_git *p, *lru_p = NULL;
+	struct packfile_list_entry *e;
+	struct packed_git *lru_p = NULL;
 	struct pack_window *mru_w = NULL;
 	int accept_windows_inuse = 1;
 
-	for (p = r->objects->packed_git; p; p = p->next) {
-		if (p->pack_fd == -1)
+	for (e = r->objects->packfiles->packs.head; e; e = e->next) {
+		if (e->pack->pack_fd == -1)
 			continue;
-		find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse);
+		find_lru_pack(e->pack, &lru_p, &mru_w, &accept_windows_inuse);
 	}
 
 	if (lru_p)
@@ -784,16 +864,56 @@ struct packed_git *add_packed_git(struct repository *r, const char *path,
 	return p;
 }
 
-void install_packed_git(struct repository *r, struct packed_git *pack)
+void packfile_store_add_pack(struct packfile_store *store,
+			     struct packed_git *pack)
 {
 	if (pack->pack_fd != -1)
 		pack_open_fds++;
 
-	pack->next = r->objects->packed_git;
-	r->objects->packed_git = pack;
+	packfile_list_append(&store->packs, pack);
+	strmap_put(&store->packs_by_path, pack->pack_name, pack);
+}
 
-	hashmap_entry_init(&pack->packmap_ent, strhash(pack->pack_name));
-	hashmap_add(&r->objects->pack_map, &pack->packmap_ent);
+struct packed_git *packfile_store_load_pack(struct packfile_store *store,
+					    const char *idx_path, int local)
+{
+	struct strbuf key = STRBUF_INIT;
+	struct packed_git *p;
+
+	/*
+	 * We're being called with the path to the index file, but `pack_map`
+	 * holds the path to the packfile itself.
+	 */
+	strbuf_addstr(&key, idx_path);
+	strbuf_strip_suffix(&key, ".idx");
+	strbuf_addstr(&key, ".pack");
+
+	p = strmap_get(&store->packs_by_path, key.buf);
+	if (!p) {
+		p = add_packed_git(store->odb->repo, idx_path,
+				   strlen(idx_path), local);
+		if (p)
+			packfile_store_add_pack(store, p);
+	}
+
+	strbuf_release(&key);
+	return p;
+}
+
+int packfile_store_freshen_object(struct packfile_store *store,
+				  const struct object_id *oid)
+{
+	struct pack_entry e;
+	if (!find_pack_entry(store->odb->repo, oid, &e))
+		return 0;
+	if (e.p->is_cruft)
+		return 0;
+	if (e.p->freshened)
+		return 1;
+	if (utime(e.p->pack_name, NULL))
+		return 0;
+	e.p->freshened = 1;
+	return 1;
 }
 
 void (*report_garbage)(unsigned seen_bits, const char *path);
@@ -895,23 +1015,14 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
 			 const char *file_name, void *_data)
 {
 	struct prepare_pack_data *data = (struct prepare_pack_data *)_data;
-	struct packed_git *p;
 	size_t base_len = full_name_len;
 
 	if (strip_suffix_mem(full_name, &base_len, ".idx") &&
 	    !(data->m && midx_contains_pack(data->m, file_name))) {
-		struct hashmap_entry hent;
-		char *pack_name = xstrfmt("%.*s.pack", (int)base_len, full_name);
-		unsigned int hash = strhash(pack_name);
-		hashmap_entry_init(&hent, hash);
-
-		/* Don't reopen a pack we already have. */
-		if (!hashmap_get(&data->r->objects->pack_map, &hent, pack_name)) {
-			p = add_packed_git(data->r, full_name, full_name_len, data->local);
-			if (p)
-				install_packed_git(data->r, p);
-		}
-		free(pack_name);
+		char *trimmed_path = xstrndup(full_name, full_name_len);
+		packfile_store_load_pack(data->r->objects->packfiles,
+					 trimmed_path, data->local);
+		free(trimmed_path);
 	}
 
 	if (!report_garbage)
@@ -935,14 +1046,14 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
 		report_garbage(PACKDIR_FILE_GARBAGE, full_name);
 }
 
-static void prepare_packed_git_one(struct odb_source *source, int local)
+static void prepare_packed_git_one(struct odb_source *source)
 {
 	struct string_list garbage = STRING_LIST_INIT_DUP;
 	struct prepare_pack_data data = {
 		.m = source->midx,
 		.r = source->odb->repo,
 		.garbage = &garbage,
-		.local = local,
+		.local = source->local,
 	};
 
 	for_each_file_in_pack_dir(source->path, prepare_pack, &data);
@@ -951,7 +1062,77 @@ static void prepare_packed_git_one(struct odb_source *source, int local)
 	string_list_clear(data.garbage, 0);
 }
 
-static void prepare_packed_git(struct repository *r);
+DEFINE_LIST_SORT(static, sort_packs, struct packfile_list_entry, next);
+
+static int sort_pack(const struct packfile_list_entry *a,
+		     const struct packfile_list_entry *b)
+{
+	int st;
+
+	/*
+	 * Local packs tend to contain objects specific to our
+	 * variant of the project than remote ones.  In addition,
+	 * remote ones could be on a network mounted filesystem.
+	 * Favor local ones for these reasons.
+	 */
+	st = a->pack->pack_local - b->pack->pack_local;
+	if (st)
+		return -st;
+
+	/*
+	 * Younger packs tend to contain more recent objects,
+	 * and more recent objects tend to get accessed more
+	 * often.
+	 */
+	if (a->pack->mtime < b->pack->mtime)
+		return 1;
+	else if (a->pack->mtime == b->pack->mtime)
+		return 0;
+	return -1;
+}
+
+void packfile_store_prepare(struct packfile_store *store)
+{
+	struct odb_source *source;
+
+	if (store->initialized)
+		return;
+
+	odb_prepare_alternates(store->odb);
+	for (source = store->odb->sources; source; source = source->next) {
+		prepare_multi_pack_index_one(source);
+		prepare_packed_git_one(source);
+	}
+
+	sort_packs(&store->packs.head, sort_pack);
+	for (struct packfile_list_entry *e = store->packs.head; e; e = e->next)
+		if (!e->next)
+			store->packs.tail = e;
+
+	store->initialized = true;
+}
+
+void packfile_store_reprepare(struct packfile_store *store)
+{
+	store->initialized = false;
+	packfile_store_prepare(store);
+}
+
+struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *store)
+{
+	packfile_store_prepare(store);
+
+	for (struct odb_source *source = store->odb->sources; source; source = source->next) {
+		struct multi_pack_index *m = source->midx;
+		if (!m)
+			continue;
+		for (uint32_t i = 0; i < m->num_packs + m->num_packs_in_base; i++)
+			prepare_midx_pack(m, i);
+	}
+
+	return store->packs.head;
+}
+
 /*
  * Give a fast, rough count of the number of objects in the repository. This
  * ignores loose objects completely. If you have a lot of them, then either
@@ -966,16 +1147,16 @@ unsigned long repo_approximate_object_count(struct repository *r)
 		unsigned long count = 0;
 		struct packed_git *p;
 
-		prepare_packed_git(r);
+		odb_prepare_alternates(r->objects);
 
 		for (source = r->objects->sources; source; source = source->next) {
 			struct multi_pack_index *m = get_multi_pack_index(source);
 			if (m)
-				count += m->num_objects;
+				count += m->num_objects + m->num_objects_in_base;
 		}
 
-		for (p = r->objects->packed_git; p; p = p->next) {
-			if (open_pack_index(p))
+		repo_for_each_pack(r, p) {
+			if (p->multi_pack_index || open_pack_index(p))
 				continue;
 			count += p->num_objects;
 		}
@@ -985,125 +1166,6 @@ unsigned long repo_approximate_object_count(struct repository *r)
 	return r->objects->approximate_object_count;
 }
 
-DEFINE_LIST_SORT(static, sort_packs, struct packed_git, next);
-
-static int sort_pack(const struct packed_git *a, const struct packed_git *b)
-{
-	int st;
-
-	/*
-	 * Local packs tend to contain objects specific to our
-	 * variant of the project than remote ones.  In addition,
-	 * remote ones could be on a network mounted filesystem.
-	 * Favor local ones for these reasons.
-	 */
-	st = a->pack_local - b->pack_local;
-	if (st)
-		return -st;
-
-	/*
-	 * Younger packs tend to contain more recent objects,
-	 * and more recent objects tend to get accessed more
-	 * often.
-	 */
-	if (a->mtime < b->mtime)
-		return 1;
-	else if (a->mtime == b->mtime)
-		return 0;
-	return -1;
-}
-
-static void rearrange_packed_git(struct repository *r)
-{
-	sort_packs(&r->objects->packed_git, sort_pack);
-}
-
-static void prepare_packed_git_mru(struct repository *r)
-{
-	struct packed_git *p;
-
-	INIT_LIST_HEAD(&r->objects->packed_git_mru);
-
-	for (p = r->objects->packed_git; p; p = p->next)
-		list_add_tail(&p->mru, &r->objects->packed_git_mru);
-}
-
-static void prepare_packed_git(struct repository *r)
-{
-	struct odb_source *source;
-
-	if (r->objects->packed_git_initialized)
-		return;
-
-	odb_prepare_alternates(r->objects);
-	for (source = r->objects->sources; source; source = source->next) {
-		int local = (source == r->objects->sources);
-		prepare_multi_pack_index_one(source, local);
-		prepare_packed_git_one(source, local);
-	}
-	rearrange_packed_git(r);
-
-	prepare_packed_git_mru(r);
-	r->objects->packed_git_initialized = 1;
-}
-
-void reprepare_packed_git(struct repository *r)
-{
-	struct odb_source *source;
-
-	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;
-	odb_prepare_alternates(r->objects);
-
-	for (source = r->objects->sources; source; source = source->next)
-		odb_clear_loose_cache(source);
-
-	r->objects->approximate_object_count_valid = 0;
-	r->objects->packed_git_initialized = 0;
-	prepare_packed_git(r);
-	obj_read_unlock();
-}
-
-struct packed_git *get_packed_git(struct repository *r)
-{
-	prepare_packed_git(r);
-	return r->objects->packed_git;
-}
-
-struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
-{
-	prepare_packed_git(source->odb->repo);
-	return source->midx;
-}
-
-struct packed_git *get_all_packs(struct repository *r)
-{
-	prepare_packed_git(r);
-
-	for (struct odb_source *source = r->objects->sources; source; source = source->next) {
-		struct multi_pack_index *m = source->midx;
-		if (!m)
-			continue;
-		for (uint32_t i = 0; i < m->num_packs + m->num_packs_in_base; i++)
-			prepare_midx_pack(r, m, i);
-	}
-
-	return r->objects->packed_git;
-}
-
-struct list_head *get_packed_git_mru(struct repository *r)
-{
-	prepare_packed_git(r);
-	return &r->objects->packed_git_mru;
-}
-
 unsigned long unpack_object_header_buffer(const unsigned char *buf,
 		unsigned long len, enum object_type *type, unsigned long *sizep)
 {
@@ -1156,7 +1218,7 @@ unsigned long get_size_from_delta(struct packed_git *p,
 		 *
 		 * Other worrying sections could be the call to close_pack_fd(),
 		 * which can close packs even with in-use windows, and to
-		 * reprepare_packed_git(). Regarding the former, mmap doc says:
+		 * odb_reprepare(). Regarding the former, mmap doc says:
 		 * "closing the file descriptor does not unmap the region". And
 		 * for the latter, it won't re-open already available packs.
 		 */
@@ -1218,11 +1280,11 @@ void mark_bad_packed_object(struct packed_git *p, const struct object_id *oid)
 const struct packed_git *has_packed_and_bad(struct repository *r,
 					    const struct object_id *oid)
 {
-	struct packed_git *p;
+	struct packfile_list_entry *e;
 
-	for (p = r->objects->packed_git; p; p = p->next)
-		if (oidset_contains(&p->bad_objects, oid))
-			return p;
+	for (e = r->objects->packfiles->packs.head; e; e = e->next)
+		if (oidset_contains(&e->pack->bad_objects, oid))
+			return e->pack;
 	return NULL;
 }
 
@@ -2030,19 +2092,6 @@ int is_pack_valid(struct packed_git *p)
 	return !open_packed_git(p);
 }
 
-struct packed_git *find_oid_pack(const struct object_id *oid,
-				 struct packed_git *packs)
-{
-	struct packed_git *p;
-
-	for (p = packs; p; p = p->next) {
-		if (find_pack_entry_one(oid, p))
-			return p;
-	}
-	return NULL;
-
-}
-
 static int fill_pack_entry(const struct object_id *oid,
 			   struct pack_entry *e,
 			   struct packed_git *p)
@@ -2073,21 +2122,23 @@ static int fill_pack_entry(const struct object_id *oid,
 
 int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e)
 {
-	struct list_head *pos;
+	struct packfile_list_entry *l;
 
-	prepare_packed_git(r);
+	packfile_store_prepare(r->objects->packfiles);
 
 	for (struct odb_source *source = r->objects->sources; source; source = source->next)
-		if (source->midx && fill_midx_entry(r, oid, e, source->midx))
+		if (source->midx && fill_midx_entry(source->midx, oid, e))
 			return 1;
 
-	if (!r->objects->packed_git)
+	if (!r->objects->packfiles->packs.head)
 		return 0;
 
-	list_for_each(pos, &r->objects->packed_git_mru) {
-		struct packed_git *p = list_entry(pos, struct packed_git, mru);
+	for (l = r->objects->packfiles->packs.head; l; l = l->next) {
+		struct packed_git *p = l->pack;
+
 		if (!p->multi_pack_index && fill_pack_entry(oid, e, p)) {
-			list_move(&p->mru, &r->objects->packed_git_mru);
+			if (!r->objects->packfiles->skip_mru_updates)
+				packfile_list_prepend(&r->objects->packfiles->packs, p);
 			return 1;
 		}
 	}
@@ -2097,19 +2148,19 @@ int find_pack_entry(struct repository *r, const struct object_id *oid, struct pa
 static void maybe_invalidate_kept_pack_cache(struct repository *r,
 					     unsigned flags)
 {
-	if (!r->objects->kept_pack_cache.packs)
+	if (!r->objects->packfiles->kept_cache.packs)
 		return;
-	if (r->objects->kept_pack_cache.flags == flags)
+	if (r->objects->packfiles->kept_cache.flags == flags)
 		return;
-	FREE_AND_NULL(r->objects->kept_pack_cache.packs);
-	r->objects->kept_pack_cache.flags = 0;
+	FREE_AND_NULL(r->objects->packfiles->kept_cache.packs);
+	r->objects->packfiles->kept_cache.flags = 0;
 }
 
 struct packed_git **kept_pack_cache(struct repository *r, unsigned flags)
 {
 	maybe_invalidate_kept_pack_cache(r, flags);
 
-	if (!r->objects->kept_pack_cache.packs) {
+	if (!r->objects->packfiles->kept_cache.packs) {
 		struct packed_git **packs = NULL;
 		size_t nr = 0, alloc = 0;
 		struct packed_git *p;
@@ -2122,7 +2173,7 @@ struct packed_git **kept_pack_cache(struct repository *r, unsigned flags)
 		 * covers, one kept and one not kept, but the midx returns only
 		 * the non-kept version.
 		 */
-		for (p = get_all_packs(r); p; p = p->next) {
+		repo_for_each_pack(r, p) {
 			if ((p->pack_keep && (flags & ON_DISK_KEEP_PACKS)) ||
 			    (p->pack_keep_in_core && (flags & IN_CORE_KEEP_PACKS))) {
 				ALLOC_GROW(packs, nr + 1, alloc);
@@ -2132,11 +2183,11 @@ struct packed_git **kept_pack_cache(struct repository *r, unsigned flags)
 		ALLOC_GROW(packs, nr + 1, alloc);
 		packs[nr] = NULL;
 
-		r->objects->kept_pack_cache.packs = packs;
-		r->objects->kept_pack_cache.flags = flags;
+		r->objects->packfiles->kept_cache.packs = packs;
+		r->objects->packfiles->kept_cache.flags = flags;
 	}
 
-	return r->objects->kept_pack_cache.packs;
+	return r->objects->packfiles->kept_cache.packs;
 }
 
 int find_kept_pack_entry(struct repository *r,
@@ -2219,7 +2270,8 @@ int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
 	int r = 0;
 	int pack_errors = 0;
 
-	for (p = get_all_packs(repo); p; p = p->next) {
+	repo->objects->packfiles->skip_mru_updates = true;
+	repo_for_each_pack(repo, p) {
 		if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
 			continue;
 		if ((flags & FOR_EACH_OBJECT_PROMISOR_ONLY) &&
@@ -2239,6 +2291,8 @@ int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
 		if (r)
 			break;
 	}
+	repo->objects->packfiles->skip_mru_updates = false;
+
 	return r ? r : pack_errors;
 }
 
@@ -2333,3 +2387,31 @@ int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *l
 	*len = hdr - out;
 	return 0;
 }
+
+struct packfile_store *packfile_store_new(struct object_database *odb)
+{
+	struct packfile_store *store;
+	CALLOC_ARRAY(store, 1);
+	store->odb = odb;
+	strmap_init(&store->packs_by_path);
+	return store;
+}
+
+void packfile_store_free(struct packfile_store *store)
+{
+	for (struct packfile_list_entry *e = store->packs.head; e; e = e->next)
+		free(e->pack);
+	packfile_list_clear(&store->packs);
+
+	strmap_clear(&store->packs_by_path, 0);
+	free(store);
+}
+
+void packfile_store_close(struct packfile_store *store)
+{
+	for (struct packfile_list_entry *e = store->packs.head; e; e = e->next) {
+		if (e->pack->do_not_close)
+			BUG("want to close pack marked 'do-not-close'");
+		close_pack(e->pack);
+	}
+}
diff --git a/packfile.h b/packfile.h
index f16753f..0e178fb 100644
--- a/packfile.h
+++ b/packfile.h
@@ -5,14 +5,12 @@
 #include "object.h"
 #include "odb.h"
 #include "oidset.h"
+#include "strmap.h"
 
 /* in odb.h */
 struct object_info;
 
 struct packed_git {
-	struct hashmap_entry packmap_ent;
-	struct packed_git *next;
-	struct list_head mru;
 	struct pack_window *windows;
 	off_t pack_size;
 	const void *index_data;
@@ -52,19 +50,149 @@ struct packed_git {
 	char pack_name[FLEX_ARRAY]; /* more */
 };
 
-static inline int pack_map_entry_cmp(const void *cmp_data UNUSED,
-				     const struct hashmap_entry *entry,
-				     const struct hashmap_entry *entry2,
-				     const void *keydata)
-{
-	const char *key = keydata;
-	const struct packed_git *pg1, *pg2;
+struct packfile_list {
+	struct packfile_list_entry *head, *tail;
+};
 
-	pg1 = container_of(entry, const struct packed_git, packmap_ent);
-	pg2 = container_of(entry2, const struct packed_git, packmap_ent);
+struct packfile_list_entry {
+	struct packfile_list_entry *next;
+	struct packed_git *pack;
+};
 
-	return strcmp(pg1->pack_name, key ? key : pg2->pack_name);
-}
+void packfile_list_clear(struct packfile_list *list);
+void packfile_list_remove(struct packfile_list *list, struct packed_git *pack);
+void packfile_list_prepend(struct packfile_list *list, struct packed_git *pack);
+void packfile_list_append(struct packfile_list *list, struct packed_git *pack);
+
+/*
+ * Find the pack within the "packs" list whose index contains the object
+ * "oid". For general object lookups, you probably don't want this; use
+ * find_pack_entry() instead.
+ */
+struct packed_git *packfile_list_find_oid(struct packfile_list_entry *packs,
+					  const struct object_id *oid);
+
+/*
+ * A store that manages packfiles for a given object database.
+ */
+struct packfile_store {
+	struct object_database *odb;
+
+	/*
+	 * The list of packfiles in the order in which they have been most
+	 * recently used.
+	 */
+	struct packfile_list packs;
+
+	/*
+	 * Cache of packfiles which are marked as "kept", either because there
+	 * is an on-disk ".keep" file or because they are marked as "kept" in
+	 * memory.
+	 *
+	 * Should not be accessed directly, but via `kept_pack_cache()`. The
+	 * list of packs gets invalidated when the stored flags and the flags
+	 * passed to `kept_pack_cache()` mismatch.
+	 */
+	struct {
+		struct packed_git **packs;
+		unsigned flags;
+	} kept_cache;
+
+	/*
+	 * A map of packfile names to packed_git structs for tracking which
+	 * packs have been loaded already.
+	 */
+	struct strmap packs_by_path;
+
+	/*
+	 * Whether packfiles have already been populated with this store's
+	 * packs.
+	 */
+	bool initialized;
+
+	/*
+	 * Usually, packfiles will be reordered to the front of the `packs`
+	 * list whenever an object is looked up via them. This has the effect
+	 * that packs that contain a lot of accessed objects will be located
+	 * towards the front.
+	 *
+	 * This is usually desireable, but there are exceptions. One exception
+	 * is when the looking up multiple objects in a loop for each packfile.
+	 * In that case, we may easily end up with an infinite loop as the
+	 * packfiles get reordered to the front repeatedly.
+	 *
+	 * Setting this field to `true` thus disables these reorderings.
+	 */
+	bool skip_mru_updates;
+};
+
+/*
+ * Allocate and initialize a new empty packfile store for the given object
+ * database.
+ */
+struct packfile_store *packfile_store_new(struct object_database *odb);
+
+/*
+ * Free the packfile store and all its associated state. All packfiles
+ * tracked by the store will be closed.
+ */
+void packfile_store_free(struct packfile_store *store);
+
+/*
+ * Close all packfiles associated with this store. The packfiles won't be
+ * free'd, so they can be re-opened at a later point in time.
+ */
+void packfile_store_close(struct packfile_store *store);
+
+/*
+ * Prepare the packfile store by loading packfiles and multi-pack indices for
+ * all alternates. This becomes a no-op if the store is already prepared.
+ *
+ * It shouldn't typically be necessary to call this function directly, as
+ * functions that access the store know to prepare it.
+ */
+void packfile_store_prepare(struct packfile_store *store);
+
+/*
+ * Clear the packfile caches and try to look up any new packfiles that have
+ * appeared since last preparing the packfiles store.
+ *
+ * This function must be called under the `odb_read_lock()`.
+ */
+void packfile_store_reprepare(struct packfile_store *store);
+
+/*
+ * Add the pack to the store so that contained objects become accessible via
+ * the store. This moves ownership into the store.
+ */
+void packfile_store_add_pack(struct packfile_store *store,
+			     struct packed_git *pack);
+
+/*
+ * Load and iterate through all packs of the given repository. This helper
+ * function will yield packfiles from all object sources connected to the
+ * repository.
+ */
+#define repo_for_each_pack(repo, p) \
+	for (struct packfile_list_entry *e = packfile_store_get_packs(repo->objects->packfiles); \
+	     ((p) = (e ? e->pack : NULL)); e = e->next)
+
+/*
+ * Get all packs managed by the given store, including packfiles that are
+ * referenced by multi-pack indices.
+ */
+struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *store);
+
+/*
+ * Open the packfile and add it to the store if it isn't yet known. Returns
+ * either the newly opened packfile or the preexisting packfile. Returns a
+ * `NULL` pointer in case the packfile could not be opened.
+ */
+struct packed_git *packfile_store_load_pack(struct packfile_store *store,
+					    const char *idx_path, int local);
+
+int packfile_store_freshen_object(struct packfile_store *store,
+				  const struct object_id *oid);
 
 struct pack_window {
 	struct pack_window *next;
@@ -142,28 +270,12 @@ int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
 #define PACKDIR_FILE_GARBAGE 4
 extern void (*report_garbage)(unsigned seen_bits, const char *path);
 
-void reprepare_packed_git(struct repository *r);
-void install_packed_git(struct repository *r, struct packed_git *pack);
-
-struct packed_git *get_packed_git(struct repository *r);
-struct list_head *get_packed_git_mru(struct repository *r);
-struct multi_pack_index *get_multi_pack_index(struct odb_source *source);
-struct packed_git *get_all_packs(struct repository *r);
-
 /*
  * Give a rough count of objects in the repository. This sacrifices accuracy
  * for speed.
  */
 unsigned long repo_approximate_object_count(struct repository *r);
 
-/*
- * Find the pack within the "packs" list whose index contains the object "oid".
- * For general object lookups, you probably don't want this; use
- * find_pack_entry() instead.
- */
-struct packed_git *find_oid_pack(const struct object_id *oid,
-				 struct packed_git *packs);
-
 void pack_report(struct repository *repo);
 
 /*
diff --git a/parse-options-cb.c b/parse-options-cb.c
index 50c8afe..976cc86 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -50,12 +50,12 @@ int parse_opt_expiry_date_cb(const struct option *opt, const char *arg,
 int parse_opt_color_flag_cb(const struct option *opt, const char *arg,
 			    int unset)
 {
-	int value;
+	enum git_colorbool value;
 
 	if (!arg)
 		arg = unset ? "never" : (const char *)opt->defval;
 	value = git_config_colorbool(NULL, arg);
-	if (value < 0)
+	if (value == GIT_COLOR_UNKNOWN)
 		return error(_("option `%s' expects \"always\", \"auto\", or \"never\""),
 			     opt->long_name);
 	*(int *)opt->value = value;
diff --git a/parse-options.c b/parse-options.c
index 5224203..c9cafc2 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -133,7 +133,6 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
 {
 	const char *arg;
 	const int unset = flags & OPT_UNSET;
-	int err;
 
 	if (unset && p->opt)
 		return error(_("%s takes no value"), optname(opt, flags));
@@ -209,21 +208,29 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
 	case OPTION_FILENAME:
 	{
 		const char *value;
-
-		FREE_AND_NULL(*(char **)opt->value);
-
-		err = 0;
+		bool is_optional;
 
 		if (unset)
 			value = NULL;
 		else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
-			value = (const char *) opt->defval;
-		else
-			err = get_arg(p, opt, flags, &value);
+			value = (const char *)opt->defval;
+		else {
+			int err = get_arg(p, opt, flags, &value);
+			if (err)
+				return err;
+		}
+		if (!value)
+			return 0;
 
-		if (!err)
-			*(char **)opt->value = fix_filename(p->prefix, value);
-		return err;
+		is_optional = skip_prefix(value, ":(optional)", &value);
+		value = fix_filename(p->prefix, value);
+		if (is_optional && is_missing_file(value)) {
+			free((char *)value);
+		} else {
+			FREE_AND_NULL(*(char **)opt->value);
+			*(const char **)opt->value = value;
+		}
+		return 0;
 	}
 	case OPTION_CALLBACK:
 	{
@@ -953,10 +960,16 @@ static void free_preprocessed_options(struct option *options)
 	free(options);
 }
 
+#define USAGE_NORMAL 0
+#define USAGE_FULL 1
+#define USAGE_TO_STDOUT 0
+#define USAGE_TO_STDERR 1
+
 static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t *,
 							 const char * const *,
 							 const struct option *,
-							 int, int);
+							 int full_usage,
+							 int usage_to_stderr);
 
 enum parse_opt_result parse_options_step(struct parse_opt_ctx_t *ctx,
 					 const struct option *options,
@@ -1088,7 +1101,8 @@ enum parse_opt_result parse_options_step(struct parse_opt_ctx_t *ctx,
 		}
 
 		if (internal_help && !strcmp(arg + 2, "help-all"))
-			return usage_with_options_internal(ctx, usagestr, options, 1, 0);
+			return usage_with_options_internal(ctx, usagestr, options,
+							   USAGE_FULL, USAGE_TO_STDOUT);
 		if (internal_help && !strcmp(arg + 2, "help"))
 			goto show_usage;
 		switch (parse_long_opt(ctx, arg + 2, options)) {
@@ -1129,7 +1143,8 @@ enum parse_opt_result parse_options_step(struct parse_opt_ctx_t *ctx,
 	return PARSE_OPT_DONE;
 
  show_usage:
-	return usage_with_options_internal(ctx, usagestr, options, 0, 0);
+	return usage_with_options_internal(ctx, usagestr, options,
+					   USAGE_NORMAL, USAGE_TO_STDOUT);
 }
 
 int parse_options_end(struct parse_opt_ctx_t *ctx)
@@ -1338,7 +1353,7 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t
 		if (!saw_empty_line && !*str)
 			saw_empty_line = 1;
 
-		string_list_split(&list, str, '\n', -1);
+		string_list_split(&list, str, "\n", -1);
 		for (j = 0; j < list.nr; j++) {
 			const char *line = list.items[j].string;
 
@@ -1444,7 +1459,8 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t
 void NORETURN usage_with_options(const char * const *usagestr,
 			const struct option *opts)
 {
-	usage_with_options_internal(NULL, usagestr, opts, 0, 1);
+	usage_with_options_internal(NULL, usagestr, opts,
+				    USAGE_NORMAL, USAGE_TO_STDERR);
 	exit(129);
 }
 
@@ -1452,9 +1468,16 @@ void show_usage_with_options_if_asked(int ac, const char **av,
 				      const char * const *usagestr,
 				      const struct option *opts)
 {
-	if (ac == 2 && !strcmp(av[1], "-h")) {
-		usage_with_options_internal(NULL, usagestr, opts, 0, 0);
-		exit(129);
+	if (ac == 2) {
+		if (!strcmp(av[1], "-h")) {
+			usage_with_options_internal(NULL, usagestr, opts,
+						    USAGE_NORMAL, USAGE_TO_STDOUT);
+			exit(129);
+		} else if (!strcmp(av[1], "--help-all")) {
+			usage_with_options_internal(NULL, usagestr, opts,
+						    USAGE_FULL, USAGE_TO_STDOUT);
+			exit(129);
+		}
 	}
 }
 
diff --git a/pathspec.c b/pathspec.c
index a3ddd70..5993c4a 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -201,8 +201,7 @@ static void parse_pathspec_attr_match(struct pathspec_item *item, const char *va
 	if (!value || !*value)
 		die(_("attr spec must not be empty"));
 
-	string_list_split(&list, value, ' ', -1);
-	string_list_remove_empty_items(&list, 0);
+	string_list_split_f(&list, value, " ", -1, STRING_LIST_SPLIT_NONEMPTY);
 
 	item->attr_check = attr_check_alloc();
 	CALLOC_ARRAY(item->attr_match, list.nr);
diff --git a/po/bg.po b/po/bg.po
index d45d363..047febf 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -239,7 +239,11 @@
 # score оценка за съвпадение
 # raw необработен
 # mbox файл с поща
-#
+# cost цена
+# nominated отбелязан
+# initial branch първоначален клон
+# garbage повредени данни
+# keep file файл за запазване на директория
 #
 # ------------------------
 # „$var“ - може да не сработва за shell има gettext и eval_gettext - проверка - намират се лесно по „$
@@ -266,17 +270,17 @@
 # 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.48\n"
+"Project-Id-Version: git v2.52.0-rc1\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2025-08-13 22:06+0200\n"
-"PO-Revision-Date: 2025-08-13 22:07+0200\n"
+"POT-Creation-Date: 2025-11-06 23:58+0000\n"
+"PO-Revision-Date: 2025-11-09 18:23+0100\n"
 "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
 "Language-Team: Bulgarian <dict@fsa-bg.org>\n"
-"Language: bg\n"
+"Language: bg\\n\"\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
 #, c-format
 msgid "%s cannot be negative"
@@ -821,21 +825,24 @@
 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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
-"j — без решение за парчето, към следващото парче без решение\n"
-"J — без решение за парчето, към следващото парче\n"
-"k — без решение за парчето, към предишното парче без решение\n"
-"K — без решение за парчето, към предишното парче\n"
+"j — без решение за парчето, към следващото парче без решение, превъртане "
+"след края\n"
+"J — без решение за парчето, към следващото парче, превъртане след края\n"
+"k — без решение за парчето, към предишното парче без решение, превъртане "
+"след началото\n"
+"K — без решение за парчето, към предишното парче, превъртане след началото\n"
 "g — избор към кое парче да се премине\n"
 "/ — търсене на парче, напасващо към даден регулярен израз\n"
 "s — разделяне на текущото парче на по-малки\n"
@@ -848,11 +855,11 @@
 msgid "Only one letter is expected, got '%s'"
 msgstr "Очаква се само един знак, а не „%s“"
 
-msgid "No previous hunk"
-msgstr "Няма друго парче преди това"
+msgid "No other hunk"
+msgstr "Няма друго парче"
 
-msgid "No next hunk"
-msgstr "Няма друго парче след това"
+msgid "No other undecided hunk"
+msgstr "Няма друго парче без решение"
 
 msgid "No other hunks to goto"
 msgstr "Няма други парчета"
@@ -2683,15 +2690,20 @@
 msgstr "Ограничаване на липсващите обекти до текущото частично хранилище"
 
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-(new,bad)=УПРАВЛЯВАЩА_ДУМА --term-"
-"(old,good)=УПРАВЛЯВАЩА_ДУМА] [--no-checkout] [--first-parent] [ЛОШО "
-"[ДОБРО…]] [--] [ШАБЛОН_ЗА_ПЪТИЩА…]"
+"git bisect start [--term-(bad|new)=УПРАВЛЯВАЩА_ДУМА --term-(good|"
+"old)=УПРАВЛЯВАЩА_ДУМА]\n"
+"                 [--no-checkout] [--first-parent] [ЛОШО [ДОБРО…]]\n"
+"                 [--] [ШАБЛОН_ЗА_ПЪТИЩА…]"
 
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "git bisect (good|bad) [ВЕРСИЯ…]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (bad|new|УПРАВЛЯВАЩА_ДУМА) [ВЕРСИЯ]"
+
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (good|old|УПРАВЛЯВАЩА_ДУМА) [ВЕРСИЯ…]"
 
 msgid "git bisect skip [(<rev>|<range>)...]"
 msgstr "git bisect skip [(ВЕРСИЯ|ДИАПАЗОН)…]"
@@ -2993,7 +3005,7 @@
 "изключена)"
 
 msgid "show work cost statistics"
-msgstr "извеждане на статистика за извършените действия"
+msgstr "извеждане на статистика за цената на извършените действия"
 
 msgid "force progress reporting"
 msgstr "извеждане на напредъка"
@@ -6001,6 +6013,14 @@
 msgstr "открити са %i етикета.  Търсенето приключи при „%s“\n"
 
 #, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "обектът-BLOB „%s“ не може да се търси в неродѐн клон"
+
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "обектът-BLOB „%s“ е недостежим от HEAD"
+
+#, c-format
 msgid "describe %s\n"
 msgstr "описание на „%s“\n"
 
@@ -6143,6 +6163,9 @@
 msgid "%s...%s: no merge base"
 msgstr "„%s..%s“: липсва база за сливане"
 
+msgid "cannot come back to cwd"
+msgstr "процесът не може да се върне към предишната работна директория"
+
 msgid "Not a git repository"
 msgstr "Не е хранилище на Git"
 
@@ -6254,9 +6277,139 @@
 msgid "git fast-export [<rev-list-opts>]"
 msgstr "git fast-export [ОПЦИЯ_ЗА_СПИСЪКА_С_ВЕРСИИ…]"
 
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "непознат режим за „%s“: %s"
+
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "непознат режим за „tag-of-filtered“: „%s“"
+
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "непознат режим за прекодиране: %s"
+
+#, c-format
+msgid "could not read blob %s"
+msgstr "обектът-BLOB не може да се прочете: %s"
+
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "разлика в идентификатор в BLOB „%s“"
+
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "обектът-BLOB „%s“ не може да се запази"
+
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "неочакван изходен код при сравнение '%c' за %s, %s"
+
+msgid "none"
+msgstr "нищо"
+
+#, c-format
+msgid "could not find author in commit %s"
+msgstr "липсва автор в подаването „%s“"
+
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "липсва подаващ в подаването „%s“"
+
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
 msgstr ""
-"ГРЕШКА: непреките етикети не се изнасят, освен ако не зададете „--mark-tags“."
+"получено е кодиране „%.*s“ специфично за подаване„%s“ — ползвайте „--"
+"reencode=[yes|no]“ за обработка"
+
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr ""
+"получено е подписано подаване „%s“ — ползвайте „--signed-commits=РЕЖИМ“ за "
+"обработка"
+
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr "изнасят се %<PRIuMAX> подпис(а) за подаването „%s“"
+
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr "пропускане на подписите към подаването „%s“"
+
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+"пропускане на етикета „%s“,\n"
+"защото не се поддържат етикети на дървета (както и етикети на етикети на "
+"дървета и т.н.)"
+
+#, c-format
+msgid "could not read tag %s"
+msgstr "етикетът „%s“ не може да се прочете"
+
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr ""
+"получен е подписан етикет „%s“ — ползвайте „--signed-tags=РЕЖИМ“ за обработка"
+
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "изнасяне на подписан етикет „%s“"
+
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "пропускане на подписите към етикета „%s“"
+
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr ""
+"етикетът „%s“ сочи към обект, който не се изнася — ползвайте „--tag-of-"
+"filtered-object=РЕЖИМ“ за обработка"
+
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr "непреките етикети не се изнасят, освен ако не зададете „--mark-tags“."
+
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "етикетът „%s“ не сочи наникъде"
+
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "„%s“: неочакван обект-%s — прескача се."
+
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr "етикетът сочи към обект от неправилен вид „%s“, пропуска се."
+
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "файлът с маркерите „%s“ не може да се отвори за запис."
+
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "файлът с маркерите „%s“ не може да се запази."
+
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "грешен ред за маркер: %s"
+
+#, c-format
+msgid "object not found: %s"
+msgstr "обектът „%s“ липсва"
+
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "не е подаване?  Това не трябва да се случва: „%s“"
+
+#, c-format
+msgid "object %s already has a mark"
+msgstr "обектът „%s“ вече има маркер"
 
 msgid "--anonymize-map token cannot be empty"
 msgstr "опцията „--anonymize-map“ изисква аргумент"
@@ -6326,29 +6479,459 @@
 msgstr "задаване на идентификатори на маркери на етикетите"
 
 #, c-format
-msgid "Missing from marks for submodule '%s'"
-msgstr "Липсват маркери „от“ за подмодула „%s“"
+msgid "can't write crash report %s"
+msgstr "докладът за забиване на програмата не може де се запази: „%s“"
 
 #, c-format
-msgid "Missing to marks for submodule '%s'"
-msgstr "Липсват маркери „до“ за подмодула „%s“"
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "fast-import: докладът за грешка се извежда в „%s“\n"
 
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "Очаква се команда „mark“, а бе получена: „%s“"
+msgid "mark :%<PRIuMAX> not declared"
+msgstr "маркер :%<PRIuMAX> не е обявен"
 
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "Очаква се команда „to“, а бе получена: „%s“"
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "неправилен опит за създаване на повтарящ се клон: „%s“"
 
-msgid "Expected format name:filename for submodule rewrite option"
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "името на клон не отговаря на стандарта на Git: „%s“"
+
+msgid "internal consistency error creating the index"
+msgstr "вътрешна грешка за съвместимостта на данните при създаване на индекса"
+
+msgid "cannot create keep file"
+msgstr "файлът за запазване на директория не може да се създаде"
+
+msgid "failed to write keep file"
+msgstr "файлът за запазване на директория не може да се запази"
+
+msgid "cannot store pack file"
+msgstr "пакетният файл не може да се съхрани"
+
+msgid "cannot store index file"
+msgstr "файлът за индекса не може да се съхрани"
+
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "не може да търси началото на „%s“"
+
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "Git отхвърли индекса „%s“"
+
+msgid "cannot truncate pack to skip duplicate"
+msgstr "пакетът не може да се отреже за пропускане на повторенията"
+
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "неочакван край на данни (EOF), а остават още %<PRIuMAX> байта"
+
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "неочаквана грешка от „deflate“: %d"
+
+#, c-format
+msgid "not a tree: %s"
+msgstr "не е дърво: %s"
+
+#, c-format
+msgid "can't load tree %s"
+msgstr "дървото „%s“ не може да се зареди"
+
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "повреден обект в „%s“"
+
+msgid "root cannot be a non-directory"
+msgstr "началната директория не може да не е директория"
+
+msgid "empty path component found in input"
+msgstr "празен компонент за път на входа"
+
+msgid "non-directories cannot have subtrees"
+msgstr "обекти, които не са директории, не може да имат поддървета"
+
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
+msgstr "„%s“ се прескача, защото ще сочи себе си (т.е. „%s“)"
+
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "липсват подавания в клона „%s“."
+
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "„%s“ не се обновява (новият връх „%s“ не съдържа „%s“)"
+
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "родителските директории на „%s“ не може да бъдат създадени"
+
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "файлът с маркерите „%s“ не може да се запише"
+
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "файлът с маркерите „%s“ не може да се запише: %s"
+
+#, c-format
+msgid "unable to write file %s"
+msgstr "файлът „%s“ не може да се запише"
+
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "очаква се команда „data n“, а бе получена: „%s“"
+
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "Край на данни (EOF), липсва „%s“"
+
+msgid "data is too large to use in this context"
+msgstr "данните са прекалено големи за този контекст"
+
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "получен е край на файл (EOF) в данните, а остават още %lu байта"
+
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "липсва „<“ в низа за идентичността: %s"
+
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "липсва интервал пред „<“ в низа за идентичността: %s\""
+
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "липсва „>“ в низа за идентичността: %s"
+
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "липсва интервал след „>“ в низа за идентичността: %s"
+
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "грешна неформатирана дата „%s“ в идентичността: %s"
+
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "дата във формат различен от rfc2822 „%s“ в идентичността: %s"
+
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "датата в идентичността трябва да е „now“ (сега): %s"
+
+#, c-format
+msgid "too large fanout (%u)"
+msgstr "прекалено голям откъс за разпределение (%u)"
+
+#, c-format
+msgid "failed to remove path %s"
+msgstr "пътят „%s“ не може да се изтрие"
+
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "липсва стойност след „:“ в маркера: „%s“"
+
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "повредени данни след маркер: %s"
+
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "липсва интервал след маркера: „%s“"
+
+#, c-format
+msgid "invalid %s: %s"
+msgstr "неправилен %s: „%s“"
+
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "NUL в %s: %s"
+
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "повредени данни след %s: „%s“"
+
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "липсва интервал след %s: „%s“"
+
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "неправилен режим: „%s“"
+
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "неправилен указател към данни: „%s“"
+
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "липсва интервал след SHA1: „%s“"
+
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "връзките на Git не може да се указват вътре („inline“): %s"
+
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "не е подаване, а е %s: %s"
+
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "директориите не може да се указват вътре („inline“): %s"
+
+#, c-format
+msgid "%s not found: %s"
+msgstr "файлът „%s“ липсва: %s"
+
+msgid "tree"
+msgstr "дърво"
+
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "не е %s, а е %s: %s"
+
+#, c-format
+msgid "path %s not in branch"
+msgstr "пътят „%s“ не е в клон"
+
+msgid "can't add a note on empty branch."
+msgstr "не може да се добави бележка към празен клон."
+
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr "маркер :%<PRIuMAX> не е подаване"
+
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "не е подаване: „%s“"
+
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "неправилно име на указател или израз с SHA1: %s"
+
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "не е обект-BLOB, а е %s: %s"
+
+#, c-format
+msgid "blob not found: %s"
+msgstr "обектът-BLOB липсва: %s"
+
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "подаването „%s“ е повредено"
+
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "не може да се създаде клон от него самия: „%s“"
+
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
+msgstr ""
+"очакваше се gpgsig във формат: „gpgsig АЛГОРИТЪМ_ЗА_КОНТРОЛНА_СУМА "
+"ФОРМАТ_НА_ПОДПИСА“, а не „gpgsig %s“"
+
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "непознат алгоритъм на git за контролни суми в gpgsig: „%s“"
+
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "неправилен формат на подпис в gpgsig: %s"
+
+msgid "'unknown' signature format in gpgsig"
+msgstr "непознат („unknown“) формат на подпис в gpgsig"
+
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr "открити са много подписи „%s“.  Допълнителните се прескачат"
+
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr "„parse_one_signature()“ върна непознат алгоритъм за контролна сума"
+
+msgid "expected committer but didn't get one"
+msgstr "очакваше се подаващ, но такъв липсва"
+
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr ""
+"получено е подписано подаване — ползвайте „--signed-commits=РЕЖИМ“ за "
+"обработка"
+
+msgid "stripping a commit signature"
+msgstr "пропускане на подпис на подаване"
+
+msgid "importing a commit signature verbatim"
+msgstr "дословно внасяне на подпис на подаване"
+
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr ""
+"получен е подписан етикет — ползвайте „--signed-tags=РЕЖИМ“ за обработка"
+
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr "дословно внасяне на подпис на етикет за „%s“"
+
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr "пропускане на подписа на етикета „%s“"
+
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "очаква се команда „from“, а бе получена: „%s“"
+
+msgid "can't tag an empty branch."
+msgstr "не може да се създаде етикет за празен клон."
+
+#, c-format
+msgid "not a valid object: %s"
+msgstr "неправилен обект: „%s“"
+
+msgid "write to frontend failed"
+msgstr "неуспешен запис към интерфейса"
+
+#, c-format
+msgid "can't read object %s"
+msgstr "обектът „%s“ не може да се прочете"
+
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "обектът „%s“ е %s, а не BLOB, какъвто се очакваше."
+
+#, c-format
+msgid "not a mark: %s"
+msgstr "не е маркер: „%s“"
+
+#, c-format
+msgid "unknown mark: %s"
+msgstr "непознат маркер: „%s“"
+
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "повредени данни след SHA1: %s"
+
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "не е дърво: „%s“"
+
+#, c-format
+msgid "can't load object %s"
+msgstr "обектът за „%s“ не може да се зареди"
+
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "неправилна сума SHA1 в етикет: %s"
+
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "неправилна сума SHA1 в подаване: %s"
+
+#, c-format
+msgid "missing from marks for submodule '%s'"
+msgstr "липсват маркери „от“ за подмодула „%s“"
+
+#, c-format
+msgid "missing to marks for submodule '%s'"
+msgstr "липсват маркери „до“ за подмодула „%s“"
+
+#, c-format
+msgid "missing space after tree-ish: %s"
+msgstr "след клона липсва интервал: %s"
+
+#, c-format
+msgid "not in a commit: %s"
+msgstr "не е в подаване: „%s“"
+
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "очаква се команда „mark“, а бе получена: „%s“"
+
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "очаква се команда „to“, а бе получена: „%s“"
+
+msgid "only one import-marks command allowed per stream"
+msgstr ""
+"след поток е позволена само една команда за внасяне на маркери (import-marks)"
+
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "неправилен аргумент за „--date-format“: %s"
+
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s: аргументът трябва да е неотрицателен"
+
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr "дълбочината към „--depth“ не може да превишава %u"
+
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr "аргументът към „--cat-blob-fd“ не може да превишава %d"
+
+msgid "expected format name:filename for submodule rewrite option"
 msgstr "опцията за презапис на подмодул изисква формат: име:име_на_файл"
 
 #, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr ""
+"минималният максимален размер на пакетите (max-pack-size) вече е в байтове.  "
+"Приема се, че сте задали „--max-pack-size=%lum“"
+
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "минималният максимален размер на пакетите (max-pack-size) е 1 MiB"
+
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "непознат режим „%s“ за опцията „--signed-commits“"
+
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "непознат режим „%s“ за опцията „--signed-tags“"
+
+#, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
 msgstr "„%s“ изисква изричното задаване на опцията „--allow-unsafe-features“"
 
 #, c-format
+msgid "got feature command '%s' after data command"
+msgstr "получена е команда „%s“ след команда за данни"
+
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "тази версия на бързото внасяне (fast-import) не поддържа „%s“."
+
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr "след командата е получена команда за опция „%s“"
+
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "тази версия на бързото внасяне (fast-import) не поддържа опцията „%s“"
+
+#, c-format
+msgid "unknown option %s"
+msgstr "непозната опция: „%s“"
+
+#, c-format
+msgid "unknown option --%s"
+msgstr "непозната опция „--%s“"
+
+#, c-format
+msgid "unsupported command: %s"
+msgstr "неподдържана команда: „%s“"
+
+msgid "stream ends early"
+msgstr "ранен край на поток"
+
+#, c-format
 msgid "Lockfile created but not reported: %s"
 msgstr "Заключващият файл е създаден, но не е докладван: „%s“"
 
@@ -6496,6 +7079,39 @@
 "ще изключи предупреждението, докато отдалеченият указател HEAD не\n"
 "започне да сочи нещо друго."
 
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+"Ползвате файлова система, която не различава главни от малки букви,\n"
+"а отдалеченото хранилище, от което се опитвате да доставите обекти,\n"
+"съдържа указатели, които се различават само по регистъра си.\n"
+"Невъзможно е да запазите всички такива указатели със съхраняване\n"
+"базирано на файлове („files“).  Имате два избора:\n"
+"\n"
+"  ⁃ или приемате положението и факта, че не може да съхраните\n"
+"    всички указатели;\n"
+"  ⁃ или мигрирайте хранилището си да съхранява указатели чрез\n"
+"    таблица („reftable“) с командата:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Не всички реализации на Git поддържат новия формат.  Затова, ако ще\n"
+"ползвате други инструменти, за да достъпвате хранилището, миграцията\n"
+"към съхраняването на указателите чрез таблица може да не е подходящо\n"
+"решение за вас.\n"
+
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -6743,21 +7359,6 @@
 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 "git for-each-ref [--points ОБЕКТ]"
-
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr "git for-each-ref [--merged [ПОДАВАНЕ]] [--no-merged [ПОДАВАНЕ]]"
-
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr "git for-each-ref [--contains [ПОДАВАНЕ]] [--no-contains [ПОДАВАНЕ]]"
-
-msgid "git for-each-ref [--start-after <marker>]"
-msgstr "git for-each-ref [--start-after МАРКЕР]"
-
 msgid "quote placeholders suitably for shells"
 msgstr "цитиране подходящо за командни интерпретатори на обвивката"
 
@@ -6812,6 +7413,9 @@
 msgid "cannot use --start-after with patterns"
 msgstr "опцията „--start-after“ е несъвместима със задаването на шаблони"
 
+msgid "git for-each-ref "
+msgstr "git for-each-ref"
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=НАСТРОЙКА [--] АРГУМЕНТ…"
 
@@ -7294,6 +7898,9 @@
 "задачата „incremental-repack“ се прескача, защото настройката "
 "„core.multiPackIndex“ е изключена"
 
+msgid "failed to perform geometric repack"
+msgstr "неуспешно геометрично препакетиране"
+
 #, c-format
 msgid "task '%s' failed"
 msgstr "неуспешно изпълнение на задачата „%s“"
@@ -7303,6 +7910,10 @@
 msgstr "заключващият файл „%s“ съществува.  Действието се прескача"
 
 #, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "непозната стратегия за поддръжка: „%s“"
+
+#, c-format
 msgid "'%s' is not a valid task"
 msgstr "„%s“ не е правилна задача"
 
@@ -8187,6 +8798,29 @@
 msgid "no input file given for in-place editing"
 msgstr "не е зададен входен файл за редактиране на място"
 
+msgid "last-modified can only operate on one tree at a time"
+msgstr "командата „last-modified“ работи само с по едно дърво"
+
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "неправилен аргумент за командата „last-modified“: %s"
+
+msgid "unable to setup last-modified"
+msgstr "командата „last-modified“ не може да се настрои"
+
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+"git last-modified [--recursive] [--show-trees] [ДИАПАЗОН_НА_ВЕРСИИТЕ] [[--] "
+"ПЪТ…]"
+
+msgid "recurse into subtrees"
+msgstr "рекурсивно обхождане поддърветата"
+
+msgid "show tree entries when recursing into subtrees"
+msgstr "извеждане на дърветата при рекурсивното обхождане на поддърветата"
+
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
 msgstr "git log [ОПЦИЯ…] [ДИАПАЗОН_НА_ВЕРСИИТЕ] [[--] ПЪТ…]"
 
@@ -8225,6 +8859,22 @@
 msgid "-L<range>:<file> cannot be used with pathspec"
 msgstr "опцията „-LДИАПАЗОН:ФАЙЛ“ не може да се ползва с шаблон за пътища"
 
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+"\n"
+"ПОДСКАЗКА: Може да замените „git whatchanged ОПЦИЯ…“ с:\n"
+"ПОДСКАЗКА:     git log ОПЦИЯ… --raw --no-merges\n"
+"ПОДСКАЗКА: А може да създадете и псевдоним:\n"
+"ПОДСКАЗКА:    git config set --global alias.whatchanged 'log --raw --no-"
+"merges'\n"
+"\n"
+
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s: повреден файл"
@@ -8680,9 +9330,6 @@
 msgid "only show trees"
 msgstr "извеждане само на дървета"
 
-msgid "recurse into subtrees"
-msgstr "рекурсивно обхождане поддърветата"
-
 msgid "show trees when recursing"
 msgstr "извеждане на дърветата при рекурсивното обхождане"
 
@@ -8838,10 +9485,6 @@
 msgstr "Файлът с обекти не може да се запише"
 
 #, c-format
-msgid "unknown option %s"
-msgstr "непозната опция: „%s“"
-
-#, c-format
 msgid "could not parse object '%s'"
 msgstr "неуспешен анализ на обекта „%s“"
 
@@ -9012,10 +9655,6 @@
 msgid "stash failed"
 msgstr "неуспешно скатаване"
 
-#, c-format
-msgid "not a valid object: %s"
-msgstr "неправилен обект: „%s“"
-
 msgid "read-tree failed"
 msgstr "неуспешно прочитане на обект-дърво"
 
@@ -9954,7 +10593,7 @@
 "expected edge object ID, got garbage:\n"
 " %s"
 msgstr ""
-"очаква се идентификатор на краен обект, а не:\n"
+"очаква се идентификатор на краен обект, а не повредени данни:\n"
 " %s"
 
 #, c-format
@@ -9962,7 +10601,7 @@
 "expected object ID, got garbage:\n"
 " %s"
 msgstr ""
-"очаква се идентификатор на обект, а не:\n"
+"очаква се идентификатор на обект, а не повредени данни:\n"
 " %s"
 
 msgid "could not load cruft pack .mtimes"
@@ -10205,27 +10844,8 @@
 "Общо: %<PRIu32> (разлики: %<PRIu32>), преизползвани: %<PRIu32> (разлики: "
 "%<PRIu32>), преизползвани при пакетиране: %<PRIu32> (от %<PRIuMAX>)"
 
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include ШАБЛОН] [--exclude "
-"ШАБЛОН]"
-
-msgid "pack everything"
-msgstr "пакетиране на всичко"
-
-msgid "prune loose refs (default)"
-msgstr "окастряне на недостижимите указатели (стандартно)"
-
-msgid "auto-pack refs as needed"
-msgstr "автоматично пакетиране на указателите при нужда"
-
-msgid "references to include"
-msgstr "кои указатели да се включат"
-
-msgid "references to exclude"
-msgstr "кои указатели да се прескочат"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
 msgid "git patch-id [--stable | --unstable | --verbatim]"
 msgstr "git patch-id [--stable|--unstable|--verbatim]"
@@ -10757,6 +11377,10 @@
 msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
 msgstr "git range-diff [ОПЦИЯ…] БАЗА СТАР_ВРЪХ НОВ_ВРЪХ"
 
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "неправилна стойност за максималната памет (max-memory): %s"
+
 msgid "use simple diff colors"
 msgstr "използване на прости цветове за разликите"
 
@@ -10766,6 +11390,12 @@
 msgid "passed to 'git log'"
 msgstr "подава се на командата „git log“"
 
+msgid "size"
+msgstr "размер"
+
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr "максимална памет за матрицата за цената (стандартно е 4G)"
+
 msgid "only emit output related to the first range"
 msgstr "извеждане само на информацията за първия диапазон"
 
@@ -11337,6 +11967,24 @@
 msgid "git reflog list"
 msgstr "git reflog list"
 
+msgid "git reflog exists <ref>"
+msgstr "git reflog exists УКАЗАТЕЛ"
+
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr ""
+"git reflog write УКАЗАТЕЛ СТАР_УКАЗАТЕЛ_НА_ОБЕКТ НОВ_УКАЗАТЕЛ_НА_ОБЕКТ "
+"СЪОБЩЕНИЕ"
+
+msgid ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+msgstr ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run|-n] [--verbose] УКАЗАТЕЛ@{УТОЧНЕНИЕ}…"
+
+msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
+msgstr "git reflog drop [--all [--single-worktree]|УКАЗАТЕЛ…]"
+
 msgid ""
 "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
 "                  [--rewrite] [--updateref] [--stale-fix]\n"
@@ -11348,19 +11996,6 @@
 "                  [--dry-run|-n] [--verbose] [--all [--single-worktree]|"
 "УКАЗАТЕЛ…]"
 
-msgid ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-msgstr ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run|-n] [--verbose] УКАЗАТЕЛ@{УТОЧНЕНИЕ}…"
-
-msgid "git reflog exists <ref>"
-msgstr "git reflog exists УКАЗАТЕЛ"
-
-msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
-msgstr "git reflog drop [--all [--single-worktree]|УКАЗАТЕЛ…]"
-
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "неправилно времево клеймо „%s“ подадено към „--%s“"
@@ -11433,12 +12068,51 @@
 msgid "references specified along with --all"
 msgstr "указателите се задават с опцията „--all“"
 
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "неправилно име на указател: %s"
+
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "неправилен идентификатор на стар обект: „%s“"
+
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "старият обект „%s“ не съществува"
+
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "неправилен идентификатор на нов обект: „%s“"
+
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "новият обект „%s“ не съществува"
+
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr "транзакцията „%s“ не може да се стартира"
+
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr ""
+"обновяването „%s“ на журнала с подаванията не може да се сложи в опашката"
+
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr "„%s“ не е обновяване на журнала с подаванията"
+
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=ФОРМАТ [--no-reflog] [--dry-run]"
 
 msgid "git refs verify [--strict] [--verbose]"
 msgstr "git refs verify [--strict] [--verbose]"
 
+msgid "git refs exists <ref>"
+msgstr "git ref exists УКАЗАТЕЛ"
+
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
 msgid "specify the reference format to convert to"
 msgstr "указване на форма̀та за указател, към който да се конвертира"
 
@@ -11461,6 +12135,18 @@
 msgid "'git refs verify' takes no arguments"
 msgstr "командата „git refs verify“ не приема аргументи"
 
+msgid "git refs list "
+msgstr "git refs list "
+
+msgid "'git refs exists' requires a reference"
+msgstr "„git refs exists“ изисква указател"
+
+msgid "reference does not exist"
+msgstr "указателят не съществува"
+
+msgid "failed to look up reference"
+msgstr "соченото от указателя липсва"
+
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
 "mirror=<fetch|push>] <name> <url>"
@@ -11625,6 +12311,24 @@
 "    %s:%d\n"
 "използва отдалечено хранилище, което вече не съществува: „%s“"
 
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+"Отдалеченото хранилище, което се пробвате да преименувате, съдържа\n"
+"указатели, които предизвикват конфликти в целевото хранилище на указатели.\n"
+"Това най-често се дължи на опит да вложите отдалечено хранилище в себе си,\n"
+"напр. като преименувате „parent“ към „parent/child“ или при изваждането му\n"
+"(преименуване в обратната посока).\n"
+"\n"
+"Ако случаят е такъв, може да го заобиколите като първо преименувате\n"
+"отдалеченото хранилище с друго име.\n"
+
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "Няма отдалечено хранилище на име „%s“"
@@ -11633,6 +12337,13 @@
 msgid "Could not rename config section '%s' to '%s'"
 msgstr "Разделът „%s“ в настройките не може да се преименува на „%s“"
 
+msgid "Renaming remote references"
+msgstr "Преименуване на отдалечените указатели"
+
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr "неуспешно добавяне на имената на отдалечените указатели: %s"
+
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -11643,16 +12354,9 @@
 "    %s\n"
 "  Променете настройките ръчно, ако е необходимо."
 
-msgid "Renaming remote references"
-msgstr "Преименуване на отдалечените указатели"
-
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "неуспешно изтриване на „%s“"
-
-#, c-format
-msgid "creating '%s' failed"
-msgstr "неуспешно създаване на „%s“"
+msgid "renaming remote refs failed: %s"
+msgstr "неуспешно преименуване на отдалечените указатели: %s"
 
 msgid ""
 "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
@@ -11939,52 +12643,6 @@
 "Ползвайте опцията „--no-write-bitmap-index“ или изключете настройката\n"
 "„pack.writeBitmaps“."
 
-msgid "could not start pack-objects to repack promisor objects"
-msgstr ""
-"командата „pack-objects“ не може да се стартира за препакетирането на "
-"гарантиращите обекти"
-
-msgid "failed to feed promisor objects to pack-objects"
-msgstr ""
-"гарантиращите обекти не може да се подадат на командата „git pack-objects“"
-
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr ""
-"repack: от „pack-objects“ се изискват редове само с пълни шестнайсетични "
-"указатели."
-
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr ""
-"командата „pack-objects“ не може да завърши за препакетирането на "
-"гарантиращите обекти"
-
-#, c-format
-msgid "cannot open index for %s"
-msgstr "грешка при отваряне на индекса за „%s“"
-
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr "пакет „%s“ е твърде голям, за да е част от геометрична прогресия"
-
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "пакет „%s“ е твърде голям за свиване"
-
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "временният файл „%s“ не може да се отвори за запис"
-
-msgid "could not close refs snapshot tempfile"
-msgstr "временният файл със снимка на указателите не може да се затвори"
-
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "изтриването на остарялата битова маска „%s“ е невъзможно"
-
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "името на пакетния файл „%s“ не започва с директорията за обекти с „%s“"
-
 msgid "pack everything in a single pack"
 msgstr "пакетиране на всичко в пакет"
 
@@ -12095,18 +12753,6 @@
 msgid "Nothing new to pack."
 msgstr "Нищо ново за пакетиране"
 
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "неуспешно преименуване на пакетния файл на „%s“"
-
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "Командата „git pack-objects“ не записа файл „%s“ за пакета „%s-%s“"
-
-#, c-format
-msgid "could not unlink: %s"
-msgstr "неуспешно изтриване на „%s“"
-
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] ОБЕКТ ЗАМЯНА"
 
@@ -12362,6 +13008,62 @@
 msgid "replaying merge commits is not supported yet!"
 msgstr "не се поддържа прилагане наново и на подавания със сливане!"
 
+#, c-format
+msgid "key '%s' not found"
+msgstr "ключът „%s“ липсва"
+
+#, c-format
+msgid "invalid format '%s'"
+msgstr "неправилен формат „%s“"
+
+msgid "output format"
+msgstr "изходен формат"
+
+msgid "synonym for --format=nul"
+msgstr "псевдоним на „--format=nul“"
+
+msgid "unsupported output format"
+msgstr "неподдържан изходен формат"
+
+msgid "References"
+msgstr "Указатели"
+
+msgid "Count"
+msgstr "Брой"
+
+msgid "Branches"
+msgstr "Клони"
+
+msgid "Tags"
+msgstr "Етикети"
+
+msgid "Remotes"
+msgstr "Отдалечени хранилища"
+
+msgid "Others"
+msgstr "Други"
+
+msgid "Reachable objects"
+msgstr "Достижими обекти"
+
+msgid "Commits"
+msgstr "Подавания"
+
+msgid "Trees"
+msgstr "Дървета"
+
+msgid "Blobs"
+msgstr "Обекти-BLOB"
+
+msgid "Repository structure"
+msgstr "Структура на хранилището"
+
+msgid "Value"
+msgstr "Стойност"
+
+msgid "Counting references"
+msgstr "Преброяване на указателите"
+
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
 msgstr "git rerere [clear|forget ШАБЛОН_ЗА_ПЪТИЩА…|diff|status|remaining|gc]"
@@ -12958,12 +13660,6 @@
 msgid "git show-ref --exists <ref>"
 msgstr "git show-ref --exists УКАЗАТЕЛ"
 
-msgid "reference does not exist"
-msgstr "указателят не съществува"
-
-msgid "failed to look up reference"
-msgstr "соченото от указателя липсва"
-
 msgid "only show tags (can be combined with --branches)"
 msgstr "извеждане на етикетите (може да се комбинира с „--branches“ за клони)"
 
@@ -12997,9 +13693,10 @@
 
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
-"git sparse-checkout (init|list|set|add|reapply|disable|check-rules) ОПЦИЯ…"
+"git sparse-checkout (init|list|set|add|reapply|disable|check-rules|clean) "
+"ОПЦИЯ…"
 
 msgid "this worktree is not sparse"
 msgstr "това работно дърво не е частично"
@@ -13040,10 +13737,6 @@
 msgstr "превключване на ползването на частичен индекс"
 
 #, c-format
-msgid "unable to create leading directories of %s"
-msgstr "родителските директории на „%s“ не може да бъдат създадени"
-
-#, c-format
 msgid "failed to open '%s'"
 msgstr "„%s“ не може да се отвори"
 
@@ -13126,6 +13819,37 @@
 "шаблоните за частичност може да бъдат приложени наново само в частично "
 "изтеглено хранилище"
 
+msgid "report each affected file, not just directories"
+msgstr "извеждане на засегнатите файлове, а не само на директориите"
+
+msgid "must be in a sparse-checkout to clean directories"
+msgstr ""
+"за изчистване на директории трябва да сте в частично изтеглено хранилище"
+
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr ""
+"за изчистване на директории трябва да сте в частично изтеглено хранилище с "
+"пътеводно напасване"
+
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr ""
+"за безопасност изчистването изисква някоя от опциите „--force“ или „--dry-"
+"run“"
+
+msgid "failed to read index"
+msgstr "неуспешно изчитане на индекса"
+
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr ""
+"индексът не може да се преобразува в частичен — първо коригирайте "
+"конфликтите и тогава пробвайте отново"
+
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "„%s“ не може да се изтрие"
+
 msgid "error while refreshing working directory"
 msgstr "грешка при обновяване на работната директория"
 
@@ -14871,9 +15595,6 @@
 msgid "only useful for debugging"
 msgstr "само за изчистване на грешки"
 
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "„core.fsyncMethod = batch“ не се поддържа на тази платформа"
-
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
 msgstr ""
@@ -15280,6 +16001,9 @@
 msgstr ""
 "Добавяне или обработка на структурирана информация в съобщенията при подаване"
 
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr "ЕКСПЕРИМЕНТАЛНО: Извеждане кога файловете са променени последно"
+
 msgid "Show commit logs"
 msgstr "Извеждане на журнала с подаванията"
 
@@ -15402,6 +16126,9 @@
 "ЕКСПЕРИМЕНТАЛНО: прилагане на подавания върху нова база, работи и с голи "
 "хранилища"
 
+msgid "Retrieve information about the repository"
+msgstr "Получаване на информация за хранилището"
+
 msgid "Generates a summary of pending changes"
 msgstr "Обобщение на предстоящите промѐни"
 
@@ -15483,8 +16210,8 @@
 msgid "Read, modify and delete symbolic refs"
 msgstr "Извеждане, промяна и изтриване на символни указатели"
 
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr "Извеждане, създаване, изтриване, проверка на етикети подписани с GPG"
+msgid "Create, list, delete or verify tags"
+msgstr "Създаване, извеждане, изтриване или проверка на етикети"
 
 msgid "Creates a temporary file with a blob's contents"
 msgstr "Създаване на временен файл със същото съдържание като обектът-BLOB"
@@ -16370,6 +17097,43 @@
 msgid "unable to parse command-line config"
 msgstr "неправилни настройки от командния ред"
 
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"За да ползвате стандартния низ за коментар „#“, изпълнете\n"
+"\n"
+"%s"
+
+msgid "<comment string>"
+msgstr "НИЗ_ЗА_КОМЕНТАР"
+
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+"\n"
+"За да зададете друг низ за коментар, изпълнете\n"
+"\n"
+"%s\n"
+"където „%s“ е низът, който искате да ползвате.\n"
+
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr "Поддръжката на „%s=auto“ е премахната в Git 3.0"
+
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr "Поддръжката на „%s=auto“ е остаряла и ще бъде премахната в Git 3.0"
+
 msgid "unknown error occurred while reading the configuration files"
 msgstr "неочаквана грешка при изчитането на конфигурационните файлове"
 
@@ -16870,6 +17634,12 @@
 msgid "failed to write archive"
 msgstr "неуспешен запис на архива"
 
+msgid "max-depth is not supported for worktree diffs"
+msgstr "„max-depth“ не се поддържа за разлики в работно дърво"
+
+msgid "max-depth is not supported for index diffs"
+msgstr "„max-depth“ не се поддържа за разлики с индекса"
+
 msgid "--merge-base does not work with ranges"
 msgstr "опцията „--merge-base“ не работи с диапазони"
 
@@ -17393,6 +18163,12 @@
 msgid "select files by diff type"
 msgstr "избор на файловете по вид разлика"
 
+msgid "<depth>"
+msgstr "ДЪЛБОЧИНА"
+
+msgid "maximum tree depth to recurse"
+msgstr "максимална дълбочина на дървото за обхождане"
+
 msgid "<file>"
 msgstr "ФАЙЛ"
 
@@ -17599,10 +18375,6 @@
 msgstr "неправилен неплитък ред: „%s“"
 
 #, c-format
-msgid "object not found: %s"
-msgstr "обектът „%s“ липсва"
-
-#, c-format
 msgid "error in object: %s"
 msgstr "грешка в обекта: „%s“"
 
@@ -17885,6 +18657,10 @@
 msgid "recursive alias: %s"
 msgstr "зациклен псевдоним: „%s“"
 
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr "зацикляне в псевдонимите: заместванията на „%s“ не приключват:%s"
+
 msgid "write failure on standard output"
 msgstr "грешка при запис на стандартния изход"
 
@@ -17895,10 +18671,6 @@
 msgstr "грешка при затваряне на стандартния изход"
 
 #, c-format
-msgid "alias loop detected: expansion of '%s' does not terminate:%s"
-msgstr "зацикляне в псевдонимите: заместванията на „%s“ не приключват:%s"
-
-#, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "„%s“ не може да се обработи като вградена команда"
 
@@ -17957,6 +18729,10 @@
 msgid "failed to get the ssh fingerprint for key '%s'"
 msgstr "отпечатъкът по ssh на ключа „%s“ не може да се получи"
 
+#, 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 ""
@@ -17964,6 +18740,11 @@
 "трябва да е зададена"
 
 #, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr ""
+"неправилна команда „gpg.ssh.defaultKeyCommand“ по време на компилиране: %s"
+
+#, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr ""
 "командата „gpg.ssh.defaultKeyCommand“ завърши успешно, но не върна никакви "
@@ -18231,6 +19012,13 @@
 "    ● заявен адрес: %s\n"
 "    ● пренасочване: %s"
 
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr ""
+"числото е прекалено голямо, за да се представи като „curl_off_t“ на тази "
+"платформа: %<PRIuMAX>"
+
 msgid "Author identity unknown\n"
 msgstr "Липсва информация за автора\n"
 
@@ -18701,10 +19489,6 @@
 msgstr "пакетът не може да се зареди"
 
 #, c-format
-msgid "could not open index for %s"
-msgstr "индексът за „%s“ не може да се отвори"
-
-#, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "не може да се създаде връзка „%s“, която да сочи към „%s“"
 
@@ -18729,6 +19513,10 @@
 msgstr "непознат предпочитан пакет: %s"
 
 #, c-format
+msgid "failed to open preferred pack %s"
+msgstr "предпочитаният пакет „%s“ не може да се отвори"
+
+#, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr ""
 "не може да изберете „%s“, който не съдържа обекти, за предпочитан пакет"
@@ -18753,6 +19541,9 @@
 msgid "could not write multi-pack bitmap"
 msgstr "многопакетната битова маска не може да се запази"
 
+msgid "too many multi-pack-indexes"
+msgstr "прекалено много индекси за множество пакети"
+
 msgid "unable to open multi-pack-index chain file"
 msgstr "файлът с веригата на гра̀фа с подаванията не може да се отвори"
 
@@ -19019,7 +19810,7 @@
 
 #, c-format
 msgid "garbage at end of loose object '%s'"
-msgstr "грешни данни в края на непакетирания обект „%s“"
+msgstr "повредени данни в края на непакетирания обект „%s“"
 
 #, c-format
 msgid "unable to open loose object %s"
@@ -19053,10 +19844,6 @@
 msgstr "съдържанието на файловете „%s“ и „%s“ е различно"
 
 #, c-format
-msgid "unable to write file %s"
-msgstr "файлът „%s“ не може да се запише"
-
-#, c-format
 msgid "unable to write repeatedly vanishing file %s"
 msgstr "смаляващият се файл „%s“ не може да се запише"
 
@@ -19064,6 +19851,9 @@
 msgid "unable to set permission to '%s'"
 msgstr "права̀та за достъп до „%s“ не може да бъдат зададени"
 
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "„core.fsyncMethod = batch“ не се поддържа на тази платформа"
+
 msgid "error when closing loose object file"
 msgstr "грешка при затварянето на файла с непакетиран обект"
 
@@ -19593,6 +20383,21 @@
 msgid "mtimes file %s is corrupt"
 msgstr "файлът с времето на промяна (mtime) „%s“ е повреден"
 
+msgid "pack everything"
+msgstr "пакетиране на всичко"
+
+msgid "prune loose refs (default)"
+msgstr "окастряне на недостижимите указатели (стандартно)"
+
+msgid "auto-pack refs as needed"
+msgstr "автоматично пакетиране на указателите при нужда"
+
+msgid "references to include"
+msgstr "кои указатели да се включат"
+
+msgid "references to exclude"
+msgstr "кои указатели да се прескочат"
+
 #, c-format
 msgid "reverse-index file %s is too small"
 msgstr "файлът с обратния индекс „%s“ е твърде малък"
@@ -20033,6 +20838,10 @@
 msgstr "„%s“ не може да се достави от гарантиращото хранилище"
 
 #, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr "неподдържана поле „%s“ в настройките на „%s“"
+
+#, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "липсващ или празен адрес за отдалечено хранилище „%s“"
 
@@ -20041,12 +20850,16 @@
 msgstr "има хранилище с име „%s“, но адресът му е „%s“, а не „%s“"
 
 #, c-format
-msgid "unknown '%s' value for '%s' config option"
-msgstr "непозната стойност „%s“ за настройката „%s“"
+msgid "invalid element '%s' from remote info"
+msgstr "неправилен елемент „%s“ в информацията за отдалеченото хранилище"
 
 #, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "непознат елемент „%s“ в информацията за отдалеченото хранилище"
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr "сървърът обяви за налично хранилище-гарант без име или адрес: %s"
+
+#, c-format
+msgid "unknown '%s' value for '%s' config option"
+msgstr "непозната стойност „%s“ за настройката „%s“"
 
 #, c-format
 msgid "accepted promisor remote '%s' not found"
@@ -20145,6 +20958,16 @@
 msgstr "неуспешно търсене на разлика"
 
 #, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+"range-diff: диапазонната разлика не може да се изчисли, защото превишава "
+"максималната памет за матрицата с цените: необходими са %s (%<PRIuMAX> "
+"байта), а ограничението е %s (%<PRIuMAX> байта)"
+
+#, c-format
 msgid "could not parse log for '%s'"
 msgstr "журналът с подаванията на „%s“ не може да се анализира"
 
@@ -20688,6 +21511,9 @@
 msgid "no reflog for '%s'"
 msgstr "липсва журнал с подаванията за „%s“"
 
+msgid "Checking references consistency"
+msgstr "Проверка на валидността на указателите"
+
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "„%s“ не сочи към позволен обект!"
@@ -20703,8 +21529,9 @@
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -20713,9 +21540,10 @@
 "\n"
 "\tgit branch -m <name>\n"
 msgstr ""
-"Първоначалният клон ще се казва „%s“.  Това може да се променѝ.  Може да "
-"зададете\n"
-"настройката и да спрете това съобщение.  За това изпълнете:\n"
+"Първоначалният клон ще се казва „%s“.  Това ще се променѝ на „main“ при Git "
+"3.0.\n"
+"Може да зададете настройка, за да спрете това съобщение.  За това "
+"изпълнете:\n"
 "\n"
 "    git config --global init.defaultBranch ИМЕ\n"
 "\n"
@@ -20725,6 +21553,20 @@
 "    git branch -m ИМЕ\n"
 
 #, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"С излизането на Git 3.0 за име на първоначалния клон се\n"
+"ползва „%s“.  Ако предпочитате Git да ползва „master“,\n"
+"просто преименувайте току що създадения клон с командата:\n"
+"\n"
+"    git branch -m master\n"
+
+#, c-format
 msgid "could not retrieve `%s`"
 msgstr "„%s“ не може да се получи"
 
@@ -20811,6 +21653,28 @@
 msgid "migrated refs can be found at '%s'"
 msgstr "мигрираните указатели са в „%s“"
 
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+"„core.preferSymlinkRefs=true“ е отбелязан за изтриване.\n"
+"ПОДСКАЗКА: Ползването на символни връзки за символни указатели е остаряло и\n"
+"ПОДСКАЗКА: ще се преустанови в Git 3.0.  Настройката на Git да прави това\n"
+"ПОДСКАЗКА: по този начин също предстои да бъде премахната.  Може да я "
+"премахнете\n"
+"ПОДСКАЗКА: сами още сега с командата:\n"
+"ПОДСКАЗКА:\n"
+"ПОДСКАЗКА:     git config unset core.preferSymlinkRefs\n"
+"ПОДСКАЗКА:\n"
+"ПОДСКАЗКА: След това Git ще ползва текстов формат за файловете с указатели."
+
 #, c-format
 msgid ""
 "cannot lock ref '%s': expected symref with target '%s': but is a regular ref"
@@ -20819,6 +21683,10 @@
 "„%s“, но вместо това е обикновен указател"
 
 #, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr "опит за вписване в журнала на указателите на „%s“ с непълна стойност"
+
+#, c-format
 msgid "cannot read ref file '%s'"
 msgstr "файлът с указател „%s“ не може да се прочете"
 
@@ -20826,9 +21694,6 @@
 msgid "cannot open directory %s"
 msgstr "директорията „%s“ не може да се отвори"
 
-msgid "Checking references consistency"
-msgstr "Проверка на валидността на указателите"
-
 #, c-format
 msgid "unable to open '%s'"
 msgstr "„%s“ не може да се отвори"
@@ -20871,8 +21736,14 @@
 "символния указател „%s“)"
 
 #, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr ""
+"указателят „%s“ не може да се заключи: файлът с указател извън клон вече "
+"съществува"
+
+#, c-format
 msgid "cannot lock ref '%s': reference already exists"
-msgstr "указателят „%s“ не може да се заключи:cуказателят вече съществува"
+msgstr "указателят „%s“ не може да се заключи: указателят вече съществува"
 
 #, c-format
 msgid "cannot lock ref '%s': reference is missing but expected %s"
@@ -20978,9 +21849,6 @@
 msgid "RPC failed; %s"
 msgstr "Неуспешно отдалечено извикване.  %s"
 
-msgid "cannot handle pushes this big"
-msgstr "толкова големи изтласквания не може да се изпълнят"
-
 #, c-format
 msgid "cannot deflate request; zlib deflate error %d"
 msgstr ""
@@ -21051,7 +21919,9 @@
 "If you cannot, please let us know why you still need to use it by\n"
 "sending an e-mail to <git@vger.kernel.org>."
 msgstr ""
-"изчитането на отдалеченото хранилище от „%s/%s“ предстои да се премахне.\n"
+"изчитане на отдалеченото хранилище от „%s/%s“, което е набелязано за "
+"изтриване.\n"
+"\n"
 "Ако все още ползвате директорията „remotes/“, препоръчваме да я мигрирате\n"
 "към следящи директории на база настройки чрез командата:\n"
 "\n"
@@ -21169,6 +22039,13 @@
 "изтласкате към „%s:refs/tags/%s“?"
 
 #, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr ""
+"Частта от указателя („%s“) за ИЗТОЧНИК е идентификатор на несъществуващ "
+"обект.\n"
+
+#, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "не е открит клон съответстващ на „%s“"
 
@@ -21294,6 +22171,64 @@
 msgstr "не може да се махне компонент от адреса „%s“"
 
 #, c-format
+msgid "cannot open index for %s"
+msgstr "грешка при отваряне на индекса за „%s“"
+
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr "пакет „%s“ е твърде голям, за да е част от геометрична прогресия"
+
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "пакет „%s“ е твърде голям за свиване"
+
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "временният файл „%s“ не може да се отвори за запис"
+
+msgid "could not close refs snapshot tempfile"
+msgstr "временният файл със снимка на указателите не може да се затвори"
+
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "изтриването на остарялата битова маска „%s“ е невъзможно"
+
+msgid "could not start pack-objects to repack promisor objects"
+msgstr ""
+"командата „pack-objects“ не може да се стартира за препакетирането на "
+"гарантиращите обекти"
+
+msgid "failed to feed promisor objects to pack-objects"
+msgstr ""
+"гарантиращите обекти не може да се подадат на командата „git pack-objects“"
+
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr ""
+"repack: от „pack-objects“ се изискват редове само с пълни шестнайсетични "
+"указатели."
+
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr ""
+"командата „pack-objects“ не може да завърши за препакетирането на "
+"гарантиращите обекти"
+
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "името на пакетния файл „%s“ не започва с директорията за обекти с „%s“"
+
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr "неуспешно преименуване на пакетния файл на „%s“"
+
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "Командата „git pack-objects“ не записа файл „%s“ за пакета „%s-%s“"
+
+#, c-format
+msgid "could not unlink: %s"
+msgstr "неуспешно изтриване на „%s“"
+
+#, c-format
 msgid "bad replace ref name: %s"
 msgstr "неправилно име на указател за замяна: „%s“"
 
@@ -22663,9 +23598,6 @@
 msgid "cannot chdir to '%s'"
 msgstr "не може да се влезе в директорията „%s“"
 
-msgid "cannot come back to cwd"
-msgstr "процесът не може да се върне към предишната работна директория"
-
 #, c-format
 msgid "failed to stat '%*s%s%s'"
 msgstr "не може да се получи информация чрез „stat“ за „%*s%s%s“"
@@ -23746,18 +24678,30 @@
 msgstr "предупреждение: "
 
 #, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "„%s“ е отбелязан за изтриване.\n"
+
+#, c-format
 msgid ""
-"'%s' 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"
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
 msgstr ""
-"Предстои пълното премахване на „%s“.\n"
-"Ако все още ползвате тази команда, добавете\n"
-"опцията „--i-still-use-this“ на командния ред и молим да\n"
-"ни известите с е-писмо до пощенския списък:\n"
-"<git@vger.kernel.org>.  Предварително благодарим.\n"
+"Ако все още ползвате командата, ето какво може да направите:\n"
+"\n"
+"⁃ прочетете https://git-scm.com/docs/BreakingChanges.html ;\n"
+"⁃ проверете дали е имало дискусия за това в пощенския списък на проекта\n"
+"  и дали е намерено решение: https://lore.kernel.org/git/?q=%s ;\n"
+"⁃ пратете е-писмо на <git@vger.kernel.org>, за да ни известите, че все\n"
+"  още ползвате командата и не сте намерили подходящ заместител.\n"
+"\n"
 
 msgid "refusing to run without --i-still-use-this"
 msgstr "трябва да добавите и опцията „--i-still-use-this“"
@@ -24646,6 +25590,9 @@
 msgid "Send this email reply required"
 msgstr "Изискване на отговор към това е-писмо"
 
+msgid "The destination IMAP folder is not properly defined."
+msgstr "Целевата папка за IMAP не е дефинирана правилно."
+
 msgid "The required SMTP server is not properly defined."
 msgstr "Сървърът за SMTP не е настроен правилно."
 
diff --git a/po/fr.po b/po/fr.po
index f81fc39..6364071 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -87,8 +87,8 @@
 msgstr ""
 "Project-Id-Version: git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2025-08-12 17:01+0000\n"
-"PO-Revision-Date: 2025-08-14 19:13+0200\n"
+"POT-Creation-Date: 2025-11-07 21:01+0100\n"
+"PO-Revision-Date: 2025-11-09 14:56+0100\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"
@@ -631,37 +631,39 @@
 msgstr "Rien n'a été appliqué.\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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
-"j - laisser cette section non décidée et aller à la suivante non-décidée\n"
-"J - laisser cette section non décidée et aller à la suivante\n"
-"k - laisser cette section non décidée et aller à la précédente non-décidée\n"
-"K - laisser cette section non décidée et aller à la précédente\n"
+"j - aller à section non-décidée suivante et reboucler au début si en bas\n"
+"J - aller à section suivante et reboucler au début si en bas\n"
+"k - aller à section non-décidée précédente et reboucler à la fin si en haut\n"
+"K - aller à section précédente et reboucler à la fin si en haut\n"
 "g - sélectionner une section et s'y rendre\n"
 "/ - rechercher une section correspondant à une regex donnée\n"
 "s - découper la section en sections plus petites\n"
 "e - éditer manuellement la section actuelle\n"
-"p - afficher la section actuelle, 'P' pour utiliser un paginateur\n"
+"p - afficher la section actuelle\n"
+"P - afficher la section actuelle avec un paginateur\n"
 "? - afficher l'aide\n"
 
 #, c-format
 msgid "Only one letter is expected, got '%s'"
 msgstr "une seule lettre est attendue, mais '%s' a été reçu"
 
-msgid "No previous hunk"
-msgstr "Pas de section précédente"
+msgid "No other hunk"
+msgstr "Aucune autre section"
 
-msgid "No next hunk"
-msgstr "Pas de section suivante"
+msgid "No other undecided hunk"
+msgstr "Aucune autre section non-décidée"
 
 msgid "No other hunks to goto"
 msgstr "Aucune autre section à atteindre"
@@ -2473,15 +2475,20 @@
 msgstr "Restreindre les objets manquants à l'extraction clairsemée actuelle"
 
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-{new,bad}=<terme> --term-{old,good}=<terme>]    [--"
-"no-checkout] [--first-parent] [<mauvais> [<bon>...]] [--]    [<spéc-de-"
-"chemin>...]"
+"git bisect start [--term-(new,bad)=<terme-nouveau> --term-(old|good)=<terme-"
+"ancien>]\n"
+"                 [--no-checkout] [--first-parent] [<mauvais> [<bon>...]] "
+"[--] [<spéc-de-chemin>...]"
 
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "git bisect (good|bad) [<rév>...]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (good|bad|<terme-nouveau>) [<rév>]"
+
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (good|bad|<terme-ancien>) [<rév>...]"
 
 msgid "git bisect skip [(<rev>|<range>)...]"
 msgstr "git bisect skip [(<rév>|<plage>)...]"
@@ -5742,6 +5749,14 @@
 msgstr "%i étiquettes trouvées ; recherche abandonnée à %s\n"
 
 #, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "impossible de rechercher le blob '%s' dans une branche non-née"
+
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "le blob '%s' est inaccessibles depuis HEAD"
+
+#, c-format
 msgid "describe %s\n"
 msgstr "décrire %s\n"
 
@@ -5883,6 +5898,9 @@
 msgid "%s...%s: no merge base"
 msgstr "%s..%s: pas de base de fusion"
 
+msgid "cannot come back to cwd"
+msgstr "impossible de revenir au répertoire de travail courant"
+
 msgid "Not a git repository"
 msgstr "Ce n'est pas un dépôt git"
 
@@ -5992,10 +6010,140 @@
 msgid "git fast-export [<rev-list-opts>]"
 msgstr "git fast-export [<options-de-liste-de-révisions>]"
 
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "mode %s inconnu : %s"
+
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "mode tag-of-filtered inconnu : %s"
+
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "Mode de ré-encodage inconnu : %s"
+
+#, c-format
+msgid "could not read blob %s"
+msgstr "impossible de lire le blob %s"
+
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "incohérence d'oid dans le blob %s"
+
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "impossible d'écrire le blob '%s'"
+
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "status de comparaison inattendu '%c' pour %s, %s"
+
+msgid "none"
+msgstr "vide"
+
+#, c-format
+msgid "could not find author in commit %s"
+msgstr "impossible de trouver l'auteur dans le commit %s"
+
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "impossible de trouver le validateur dans le commit %s"
+
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
 msgstr ""
-"Erreur : impossible d'exporter des étiquettes imbriquées à moins que --mark-"
-"tags ne soit spécifié."
+"encodage spécifique à un commit %.*s rencontré dans le commit %s ; utilisez "
+"--reencode=(yes|no) pour le gérer"
+
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr ""
+"commit signé %s rencontré ; utilisez --signed-commits=<mode> pour le gérer"
+
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr "export de %<PRIuMAX> signature(s) pour le commit %s"
+
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr "suppression de signature(s) du commit %s"
+
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+"étiquette %s ignorée,\n"
+"puisque les étiquettes d'arbres (ou les étiquettes d'étiquettes d'arbres, "
+"etc.) ne sont pas gérées."
+
+#, c-format
+msgid "could not read tag %s"
+msgstr "impossible de lire l'étiquette %s"
+
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr ""
+"étiquette signée %s rencontrée ; utilisez --signed-tags=<mode> pour la gérer"
+
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "export de l'étiquette signée %s"
+
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "suppression de la signature dans l'étiquette %s"
+
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr ""
+"l'étiquette %s étiquette un objet non exporté ; utilisez --tag-of-filtered-"
+"object=<mode> pour la gérer"
+
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr ""
+"impossible d'exporter des étiquettes imbriquées à moins que --mark-tags ne "
+"soit spécifié."
+
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "l'étiquette %s ne pointe nulle part ?"
+
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "%s : objet de type %s inattendu, ignoré."
+
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr "l'étiquette point su un objet de type inaattendu %s, ignoré."
+
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "impossible d'ouvrir le fichier de marques %s en écriture."
+
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "impossible d'écrire le fichier de marques %s."
+
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "ligne de marque corrompue : %s"
+
+#, c-format
+msgid "object not found: %s"
+msgstr "objet non trouvé : %s"
+
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "pas un commit ? Cela ne se peut : %s"
+
+#, c-format
+msgid "object %s already has a mark"
+msgstr "l'objet %s a déjà une marque"
 
 msgid "--anonymize-map token cannot be empty"
 msgstr "le jeton --anonymize-map ne peut pas être vide"
@@ -6066,32 +6214,458 @@
 msgstr "marquer les étiquettes avec des ids de marque"
 
 #, c-format
-msgid "Missing from marks for submodule '%s'"
-msgstr "Champs from manquants pour le sous-module '%s'"
+msgid "can't write crash report %s"
+msgstr "impossible d'écrire le rapport de crash %s"
 
 #, c-format
-msgid "Missing to marks for submodule '%s'"
-msgstr "Champs 'to' manquants pour le sous-module '%s'"
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "fast-import : écriture du rapport de crash dans %s\n"
 
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "Commande 'mark' attendue, %s trouvé"
+msgid "mark :%<PRIuMAX> not declared"
+msgstr "marque : %<PRIuMAX> non déclarée"
 
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "Commande 'to' attendue, %s trouvé"
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "tentative invalide de création d'une branche dupliquée : %s"
 
-msgid "Expected format name:filename for submodule rewrite option"
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "le nom de la branche n'est pas conforme au standards Git : %s"
+
+msgid "internal consistency error creating the index"
+msgstr "erreur de cohérence interne à la création de l'index"
+
+msgid "cannot create keep file"
+msgstr "impossible de créer le fichier keep"
+
+msgid "failed to write keep file"
+msgstr "échec de l'écriture du fichier keep"
+
+msgid "cannot store pack file"
+msgstr "impossible de stocker le fichier paquet"
+
+msgid "cannot store index file"
+msgstr "impossible de stocker le fichier d'index"
+
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "échec de la recherche du debut de '%s'"
+
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "le cœur de Git a rejecté l'index %s"
+
+msgid "cannot truncate pack to skip duplicate"
+msgstr "impossible de tronquer le paquet pour sauté la duplication"
+
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "OEF dans les données (%<PRIuMAX> octets restant)"
+
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "échec inattendu de décompression : %d"
+
+#, c-format
+msgid "not a tree: %s"
+msgstr "pas un arbre : %s"
+
+#, c-format
+msgid "can't load tree %s"
+msgstr "impossible de charger l'arbre %s"
+
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "mode corrompu dans %s"
+
+msgid "root cannot be a non-directory"
+msgstr "la racine doit être un répertoire"
+
+msgid "empty path component found in input"
+msgstr "composant de chemin vide trouvé dans l'entrée"
+
+msgid "non-directories cannot have subtrees"
+msgstr "les composants non-répertoires ne peut pas avoir de sous-arbre"
+
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
+msgstr "suppression de %s puisqu'il pointerait sur lui-même (c-à-d sur %s)"
+
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "il manque des commits à la branche %s."
+
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "%s pas mis à jour (le nouveau sommet %s ne contient pas %s)"
+
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "impossible de créer les répertoires de premier niveau de %s"
+
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "impossible d'écrire le fichier de marques %s"
+
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "impossible d'écrire le fichier de marques %s : %s"
+
+#, c-format
+msgid "unable to write file %s"
+msgstr "impossible d'écrire le fichier %s"
+
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "Commande 'data n' attendue, %s trouvé"
+
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "OEF dans les données (terminateur '%s' non trouvé)"
+
+msgid "data is too large to use in this context"
+msgstr "les données sont trop grandes à utiliser dans ce contexte"
+
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "OEF dans les données (%lu octets restants)"
+
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "< manquant dans la chaîne d'identification : %s"
+
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "espace manquant avant < dans la chaîne d'identification : %s"
+
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "> manquant dans la chaîne d'identification : %s"
+
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "espace manquant après > dans la chaîne d'identification : %s"
+
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "date brute invalide \"%s\" dans l'ident : %s"
+
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "date rfc2822 invalide \"%s\" dans l'ident : %s"
+
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "la date dans l'ident doit être 'now' : %s"
+
+#, c-format
+msgid "too large fanout (%u)"
+msgstr "dispersion trop grande (%u)"
+
+#, c-format
+msgid "failed to remove path %s"
+msgstr "échec de la suppression du chemin %s"
+
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "aucune valeur après ':' dans la marque : %s"
+
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "déchets après la marque : %s"
+
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "espace manquant après la marque : %s"
+
+#, c-format
+msgid "invalid %s: %s"
+msgstr "%s invalide : %s"
+
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "NUL dans %s : %s"
+
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "déchets après %s : %s"
+
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "espace manquant après %s : %s"
+
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "mode corrompu : %s"
+
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "dataref invalide : %s"
+
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "espace manquant après SHA1 : %s"
+
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "les liens Git ne peuvent pas être spécifiés 'inline' :%s"
+
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "pas un commit (type %s) : %s"
+
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "les répertoires ne peut pas être 'inline' : %s"
+
+#, c-format
+msgid "%s not found: %s"
+msgstr "%s non trouvé : %s"
+
+msgid "tree"
+msgstr "arbre"
+
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "pas de type %s (type %s) : %s"
+
+#, c-format
+msgid "path %s not in branch"
+msgstr "chemin %s pas dans une branche"
+
+msgid "can't add a note on empty branch."
+msgstr "impossible d'ajouter une note à une branche vide."
+
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr "marque : %<PRIuMAX> n'est pas un commit"
+
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "pas un commit valide : %s"
+
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "nom de ref ou expression SHA1 invalide : %s"
+
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "pas un blob (type actuel %s) : %s"
+
+#, c-format
+msgid "blob not found: %s"
+msgstr "blob non trouvé : %s"
+
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "le commit %s est corrompu"
+
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "impossible de créer une branche sur elle-même : %s"
+
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
 msgstr ""
-"Format attendu nom:<nom de fichier> pour l'option de réécriture de sous-"
+"format gpgsig attendu : 'gpgsig <algo-empreinte> <format-signature>', trouvé "
+"'gpgsig %s'"
+
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "algorithme d'empreinte inconnu dans gpgsig : '%s'"
+
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "format de signature invalide dans gpgsig : '%s'"
+
+msgid "'unknown' signature format in gpgsig"
+msgstr "Format de signature 'unknown' inconnu dans gpgsig"
+
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr "multiple signatures %s trouvées, signatures additionnelles ignorées"
+
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr "parse_one_signature() a renvoyé un algo d'empreinte inconnu"
+
+msgid "expected committer but didn't get one"
+msgstr "validateur attendu mais aucune information fournie"
+
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr ""
+"commit signé rencontré ; utilisez --signed-commits=<mode> pour le gérer"
+
+msgid "stripping a commit signature"
+msgstr "une signature de commit ignorée"
+
+msgid "importing a commit signature verbatim"
+msgstr "import d'une signature de commit verbatim"
+
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr ""
+"étiquette signée rencontrée ; utilisez --signed-tags=<mode> pour la gérer"
+
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr "import d'une signature d'étiquette verbatim pour l'étiquette '%s'"
+
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr "suppression d'une signature d'étiquette de l'étiquette '%s'"
+
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "Commande 'from' attendue, '%s' trouvé"
+
+msgid "can't tag an empty branch."
+msgstr "impossible d'étiqueter une branche vide."
+
+#, c-format
+msgid "not a valid object: %s"
+msgstr "pas un objet valide : %s"
+
+msgid "write to frontend failed"
+msgstr "échec de l'écriture vers le frontend"
+
+#, c-format
+msgid "can't read object %s"
+msgstr "impossible de lire l'objet %s"
+
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "l'objet %s est de type %s, mais un blob était attendu."
+
+#, c-format
+msgid "not a mark: %s"
+msgstr "pas une marque : %s"
+
+#, c-format
+msgid "unknown mark: %s"
+msgstr "marque inconnue : %s"
+
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "déchets après SHA1 : %s"
+
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "pas un arbre-esque : %s"
+
+#, c-format
+msgid "can't load object %s"
+msgstr "impossible de charger l'objet %s"
+
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "SHA1 invalide pour l'étiquette : %s"
+
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "SHA1 invalide pour le commit : %s"
+
+#, c-format
+msgid "missing from marks for submodule '%s'"
+msgstr "marques from manquantes pour le sous-module '%s'"
+
+#, c-format
+msgid "missing to marks for submodule '%s'"
+msgstr "marques 'to' manquantes pour le sous-module '%s'"
+
+#, c-format
+msgid "missing space after tree-ish: %s"
+msgstr "espace manquant après l'arbre-esque : %s"
+
+#, c-format
+msgid "not in a commit: %s"
+msgstr "pas dans un commit : %s"
+
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "commande 'mark' attendue, %s trouvé"
+
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "commande 'to' attendue, %s trouvé"
+
+msgid "only one import-marks command allowed per stream"
+msgstr "une seule commande import-marks tolérée par flux"
+
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "argument de --date-format inconnu %s"
+
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s : l'argument doit être un entier positif ou nul"
+
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr "--depth ne peut pas être plus grand que %u"
+
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr "--cat-blob-fd ne peut pas être plus grand que %d"
+
+msgid "expected format name:filename for submodule rewrite option"
+msgstr ""
+"Format attendu <nom>:<nom de fichier> pour l'option de réécriture de sous-"
 "module"
 
 #, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr "max-pack-size est maintenant en octets, --max-pack-size=%lum supposé"
+
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "la taille limite minimale d'un paquet est 1 Mio"
+
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "mode --signed-commits inconnu '%s'"
+
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "mode --signed-tags inconnu '%s'"
+
+#, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
 msgstr ""
 "la fonctionnalité '%s' est interdite en entrée sans --allow-unsafe-features"
 
 #, c-format
+msgid "got feature command '%s' after data command"
+msgstr "commande de fonction '%s' reçue après la commande data"
+
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "cette version de fast-import ne gère pas la fonctionnalité %s."
+
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr "option de commande '%s' obtenue après la commande data"
+
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "cette version de fast-import ne supporte pas la l'option : %s"
+
+#, c-format
+msgid "unknown option %s"
+msgstr "option inconnue %s"
+
+#, c-format
+msgid "unknown option --%s"
+msgstr "option inconnue --%s"
+
+#, c-format
+msgid "unsupported command: %s"
+msgstr "commande non gérée : %s"
+
+msgid "stream ends early"
+msgstr "le flux se termine trop tôt"
+
+#, c-format
 msgid "Lockfile created but not reported: %s"
 msgstr "Fichier verrou créé mais non reporté : %s"
 
@@ -6229,6 +6803,38 @@
 "%s'\n"
 "va désactiver l'alerte jusqu'à ce que le distant change HEAD."
 
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+"Vous êtes sur un système de fichier non sensible à la casse,\n"
+"et le distant duquel vous souhaitez récupérer a des références\n"
+"qui ne diffèrent que par la casse ; il est impossible de stocker\n"
+"de telles références avec le backend 'file'. Vous pouvez l'accepter\n"
+"tel quel, auquel cas vous ne pourrez pas stocker tous les distants\n"
+"sur le disque. Ou sinon, vous pouvez migrer votre dépôt pour utiliser\n"
+"le backend 'reftable' avec la commande suivante ⋅:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Veuillez garder à l'esprit que ce format n'est pas encore géré pour toutes "
+"les\n"
+"implémentations de Git. Si vous utilisez d'autres outils que Git pour "
+"accéder\n"
+"à ce dépôt, la migration vers reftable pourrait donc ne pas être "
+"pertinente.\n"
+
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -6476,21 +7082,6 @@
 msgid "file to read from"
 msgstr "fichier d'où lire"
 
-msgid "git for-each-ref [<options>] [<pattern>]"
-msgstr "git for-each-ref [<options>] [<motif>]"
-
-msgid "git for-each-ref [--points-at <object>]"
-msgstr "git for-each-ref [--points-at <objet>]"
-
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-
-msgid "git for-each-ref [--start-after <marker>]"
-msgstr "git for-each-ref [--start-after <marqueur>]"
-
 msgid "quote placeholders suitably for shells"
 msgstr "échapper les champs réservés pour les interpréteurs de commandes"
 
@@ -6546,6 +7137,9 @@
 msgid "cannot use --start-after with patterns"
 msgstr "impossible d'utiliser --start-after avec des motifs"
 
+msgid "git for-each-ref "
+msgstr "git for-each-ref "
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<config> [--] <arguments>"
 
@@ -7021,6 +7615,9 @@
 msgstr ""
 "tâche incremental-repack ignorée parce que core.multiPackIndex est désactivé"
 
+msgid "failed to perform geometric repack"
+msgstr "échec de l'exécution du repaquetage géométrique"
+
 #, c-format
 msgid "task '%s' failed"
 msgstr "échec de la tâche '%s'"
@@ -7030,6 +7627,10 @@
 msgstr "le fichier verrou '%s' existe, pas de maintenance"
 
 #, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "stratégie de maintenance inconnue : '%s'"
+
+#, c-format
 msgid "'%s' is not a valid task"
 msgstr "'%s' n'est pas une tâche valide"
 
@@ -7913,6 +8514,29 @@
 msgid "no input file given for in-place editing"
 msgstr "aucun fichier en entrée pour l'éditon sur place"
 
+msgid "last-modified can only operate on one tree at a time"
+msgstr "last-modified ne peut opérer que sur un arbre à la fois"
+
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "argument de last-modified inconnu : %s"
+
+msgid "unable to setup last-modified"
+msgstr "impossible de renseigner last-modified"
+
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+"git last-modified [--recursive] [--show-trees] [<plage-de-révisions>] [[--] "
+"<chemin>...]"
+
+msgid "recurse into subtrees"
+msgstr "parcourir les sous-arbres"
+
+msgid "show tree entries when recursing into subtrees"
+msgstr "afficher les entrées lors de la récurssion dans les sous-arbres"
+
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
 msgstr "git log [<options>] [<plage de révisions>] [[--] <chemin>...]"
 
@@ -7952,6 +8576,21 @@
 msgstr ""
 "-L<plage>:<fichier> ne peut pas être utilisé avec une spécificateur de chemin"
 
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+"\n"
+"astuce : vous pouvez remplacer 'git whatchanged <opts>' par :\n"
+"astuce : \tgit log <opts> --raw --no-merges\n"
+"astuce : Ou créer un alias :\n"
+"astuce :\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s : fichier incorrect"
@@ -8407,9 +9046,6 @@
 msgid "only show trees"
 msgstr "afficher seulement les arbres"
 
-msgid "recurse into subtrees"
-msgstr "parcourir les sous-arbres"
-
 msgid "show trees when recursing"
 msgstr "afficher les arbres en les parcourant"
 
@@ -8561,10 +9197,6 @@
 msgstr "impossible d'écrire le fichier d'objet"
 
 #, c-format
-msgid "unknown option %s"
-msgstr "option inconnue %s"
-
-#, c-format
 msgid "could not parse object '%s'"
 msgstr "impossible d'analyser l'objet '%s'"
 
@@ -8733,10 +9365,6 @@
 msgid "stash failed"
 msgstr "échec du remisage"
 
-#, c-format
-msgid "not a valid object: %s"
-msgstr "pas un objet valide : %s"
-
 msgid "read-tree failed"
 msgstr "read-tree a échoué"
 
@@ -9905,27 +10533,8 @@
 "Total %<PRIu32> (delta %<PRIu32>), réutilisés %<PRIu32> (delta %<PRIu32>), "
 "réutilisés du paquet %<PRIu32> (depuis %<PRIuMAX>)"
 
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <motif>] [--exclude "
-"<motif>]"
-
-msgid "pack everything"
-msgstr "empaqueter tout"
-
-msgid "prune loose refs (default)"
-msgstr "élaguer les références perdues (défaut)"
-
-msgid "auto-pack refs as needed"
-msgstr "auto-empaqueter les réfs au besoin"
-
-msgid "references to include"
-msgstr "références à inclure"
-
-msgid "references to exclude"
-msgstr "références à exclure"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
 msgid "git patch-id [--stable | --unstable | --verbatim]"
 msgstr "git patch-id [--stable | --unstable | --verbatim]"
@@ -10459,6 +11068,10 @@
 msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
 msgstr "git range-diff [<options>] <base> <ancien-sommet> <nouveau-sommet>"
 
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "valeur invalide de max-memory : %s"
+
 msgid "use simple diff colors"
 msgstr "utiliser des couleurs de diff simples"
 
@@ -10468,6 +11081,12 @@
 msgid "passed to 'git log'"
 msgstr "passé à 'git log'"
 
+msgid "size"
+msgstr "taille"
+
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr "memoire maximum pour la matrice de coût (par défaut 4G)"
+
 msgid "only emit output related to the first range"
 msgstr "afficher seulement les sorties liées à la première plage"
 
@@ -11026,6 +11645,22 @@
 msgid "git reflog list"
 msgstr "git reflog list"
 
+msgid "git reflog exists <ref>"
+msgstr "git reflog exists <référence>"
+
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr "git reflog write <ref> <ancien-oid> <nouveau-oid> <message>"
+
+msgid ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+msgstr ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <réf>@{<spécificateur>}..."
+
+msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
+msgstr "git reflog drop [--all [--single-worktree] | <réf>...]"
+
 msgid ""
 "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
 "                  [--rewrite] [--updateref] [--stale-fix]\n"
@@ -11037,19 +11672,6 @@
 "                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
 "<réfs>...]"
 
-msgid ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-msgstr ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <réf>@{<spécificateur>}..."
-
-msgid "git reflog exists <ref>"
-msgstr "git reflog exists <référence>"
-
-msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
-msgstr "git reflog drop [--all [--single-worktree] | <réf>...]"
-
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "horodatage invalide '%s' fourni à '--%s'"
@@ -11120,12 +11742,50 @@
 msgid "references specified along with --all"
 msgstr "références spécifiées en même temps que --all"
 
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "nom de référence invalide : %s"
+
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "ID d'ancien objet invalide : '%s'"
+
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "l'ancien objet '%s' n'existe pas"
+
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "ID de nouvel objet invalide : '%s'"
+
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "le nouvel objet '%s' n'existe pas"
+
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr "impossible de démarrer la transaction : %s"
+
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr "impossible d'empiler la mise à jour du reflog : %s"
+
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr "impossible de valider la mise à jour du reflog : %s"
+
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 
 msgid "git refs verify [--strict] [--verbose]"
 msgstr "git refs verify [--strict] [--verbose]"
 
+msgid "git refs exists <ref>"
+msgstr "git refs exist <référence>"
+
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
 msgid "specify the reference format to convert to"
 msgstr "spécifier le format de réference vers lequel convertir"
 
@@ -11148,6 +11808,18 @@
 msgid "'git refs verify' takes no arguments"
 msgstr "'git refs verify' n'accepte aucun argument"
 
+msgid "git refs list "
+msgstr "git refs list "
+
+msgid "'git refs exists' requires a reference"
+msgstr "'git refs exists' nécessite une référence"
+
+msgid "reference does not exist"
+msgstr "la référence n'existe pas"
+
+msgid "failed to look up reference"
+msgstr "échec de la recherche de la référence"
+
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
 "mirror=<fetch|push>] <name> <url>"
@@ -11311,6 +11983,23 @@
 "\t%s%d\n"
 "nomme à présent le distant inexistant '%s'"
 
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+"Le distant que vous essayer de renommer a des réference en conflit\n"
+"dans le nouveau refspec cible. C'est probablement du à un essai de\n"
+"emboîter un distant dans lui-même, p. ex., en renommant 'parent' en\n"
+"'parent/enfant' ou à l'inverse, en dé-emboîtant un distant.\n"
+"\n"
+"Si c'est le cas, vous pouvez le résoudre en commençant par renommer\n"
+"le distant avec un nom différent.\n"
+
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "Pas de serveur remote : '%s'"
@@ -11319,6 +12008,14 @@
 msgid "Could not rename config section '%s' to '%s'"
 msgstr "Impossible de renommer la section de configuration '%s' en '%s'"
 
+msgid "Renaming remote references"
+msgstr "Renommage des références distantes"
+
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr ""
+"la mise en file d'attente des renommages des réf distante a échoué : %s"
+
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -11329,16 +12026,9 @@
 "\t%s\n"
 "\tVeuillez mettre à jour la configuration manuellement si nécessaire."
 
-msgid "Renaming remote references"
-msgstr "Renommage des références distantes"
-
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "échec de suppression de '%s'"
-
-#, c-format
-msgid "creating '%s' failed"
-msgstr "échec de création de '%s'"
+msgid "renaming remote refs failed: %s"
+msgstr "le renommage des réfs distantes a échoué : %s"
 
 msgid ""
 "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
@@ -11623,52 +12313,6 @@
 "Utilisez\n"
 "--no-write-bitmap-index ou désactivez le paramètre pack.writeBitmaps."
 
-msgid "could not start pack-objects to repack promisor objects"
-msgstr ""
-"ne pas démarrer pack-objects pour ré-empaqueter les objects de prometteur"
-
-msgid "failed to feed promisor objects to pack-objects"
-msgstr "Échéc de la fourniture les objets du prometteur à pack-objects"
-
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr ""
-"repack : attente de lignes d'Id d'objets en hexa complet seulement depuis "
-"les objects de paquet."
-
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr ""
-"impossible de terminer pack-objects  pour ré-empaqueter les objets de "
-"prometteur"
-
-#, c-format
-msgid "cannot open index for %s"
-msgstr "impossible d'ouvrir l'index pour %s"
-
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr ""
-"le paquet %s est trop gros pour être pris en compte dans un progression "
-"géométrique"
-
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "le paquet %s est trop gros à enrouler"
-
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "impossible d'ouvrir le fichier temporaire %s en écriture"
-
-msgid "could not close refs snapshot tempfile"
-msgstr "impossible de fermer le fichier temporaire d'instantané des réfs"
-
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "impossible de revenir la bitmap obsolète : %s"
-
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "le préfixe %s ne commence pas avec objdir %s"
-
 msgid "pack everything in a single pack"
 msgstr "empaqueter tout dans un seul paquet"
 
@@ -11768,18 +12412,6 @@
 msgid "Nothing new to pack."
 msgstr "Rien de neuf à empaqueter."
 
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "le renommage du paquet en '%s' a échoué"
-
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "pack-objects n'a pas écrit un fichier '%s' pour la paquet %s-%s"
-
-#, c-format
-msgid "could not unlink: %s"
-msgstr "impossible de délier : '%s'"
-
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] <objet> <remplacement>"
 
@@ -12036,6 +12668,62 @@
 msgid "replaying merge commits is not supported yet!"
 msgstr "rejouer des commits de fusion n'est pas encore géré !"
 
+#, c-format
+msgid "key '%s' not found"
+msgstr "clé '%s' non trouvée"
+
+#, c-format
+msgid "invalid format '%s'"
+msgstr "format invalide '%s'"
+
+msgid "output format"
+msgstr "format de sortie"
+
+msgid "synonym for --format=nul"
+msgstr "synonymes de --format=nul"
+
+msgid "unsupported output format"
+msgstr "format de sortie non géré"
+
+msgid "References"
+msgstr "Références"
+
+msgid "Count"
+msgstr "compte"
+
+msgid "Branches"
+msgstr "Branches"
+
+msgid "Tags"
+msgstr "Étiquettes"
+
+msgid "Remotes"
+msgstr "Distants"
+
+msgid "Others"
+msgstr "Autres"
+
+msgid "Reachable objects"
+msgstr "Objets accessibles"
+
+msgid "Commits"
+msgstr "Commits"
+
+msgid "Trees"
+msgstr "Arbres"
+
+msgid "Blobs"
+msgstr "Blobs"
+
+msgid "Repository structure"
+msgstr "Structure de dépôt"
+
+msgid "Value"
+msgstr "Valeur"
+
+msgid "Counting references"
+msgstr "Comptage des références"
+
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
 msgstr ""
@@ -12635,12 +13323,6 @@
 msgid "git show-ref --exists <ref>"
 msgstr "git show-ref --exists <réf>"
 
-msgid "reference does not exist"
-msgstr "la référence n'existe pas"
-
-msgid "failed to look up reference"
-msgstr "échec de la recherche de la référence"
-
 msgid "only show tags (can be combined with --branches)"
 msgstr "afficher seulement les étiquettes (peut être combiné avec --branches)"
 
@@ -12675,10 +13357,10 @@
 
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 
 msgid "this worktree is not sparse"
 msgstr "cet arbre de travail n'est pas clairsemé"
@@ -12721,10 +13403,6 @@
 msgstr "bascule l'utilisation d'index clairsemé"
 
 #, c-format
-msgid "unable to create leading directories of %s"
-msgstr "impossible de créer les répertoires de premier niveau de %s"
-
-#, c-format
 msgid "failed to open '%s'"
 msgstr "échec à l'ouverture de '%s'"
 
@@ -12809,6 +13487,34 @@
 "extraction clairsemée nécessaire pour pouvoir réappliquer les motifs de "
 "clairsemage"
 
+msgid "report each affected file, not just directories"
+msgstr "afficher chaque fichier affecté, pas juste les répertoires"
+
+msgid "must be in a sparse-checkout to clean directories"
+msgstr "doit être une extraction clairsemée pour nettoyer les répertoires"
+
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr ""
+"doit être une extraction clairsemée en mode cone  pour nettoyer les "
+"répertoires"
+
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr "par sécurité, refus de nettoyer s'il n'y a ni --force ni --dry-run"
+
+msgid "failed to read index"
+msgstr "échec à la lecture de l'index"
+
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr ""
+"échec de conversion de l'index en index clairsemé ; résolvez les conflits de "
+"fusion et ré-essayez"
+
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "échec de la suppression de '%s'"
+
 msgid "error while refreshing working directory"
 msgstr "erreur lors du rafraîchissement du répertoire de travail"
 
@@ -14557,9 +15263,6 @@
 msgid "only useful for debugging"
 msgstr "seulement utile pour le débogage"
 
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "core.fsyncMethod = batch non géré sur cette plateforme"
-
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
 msgstr "impossible d'analyser la clé de liste de colis %s avec la valeur '%s'"
@@ -14961,6 +15664,9 @@
 msgstr ""
 "Ajouter ou analyser l'information structurée dans les messages de validation"
 
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr "EXPÉRIMENTAL : Afficher la dernière date de modification des fichiers"
+
 msgid "Show commit logs"
 msgstr "Afficher l'historique des validations"
 
@@ -15090,6 +15796,9 @@
 "EXPÉRIMENTAL ; rejoue des commits sur une nouvelle base, fonctionne aussi "
 "avec les dépôts nus"
 
+msgid "Retrieve information about the repository"
+msgstr "Récupérer l'information à propos du dépôt"
+
 msgid "Generates a summary of pending changes"
 msgstr "Générer une résumé des modifications en attentes"
 
@@ -15171,9 +15880,8 @@
 msgid "Read, modify and delete symbolic refs"
 msgstr "Lire, modifier et supprimer les références symboliques"
 
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr ""
-"Créer, lister, supprimer ou vérifier un objet d'étiquette signé avec GPG"
+msgid "Create, list, delete or verify tags"
+msgstr "Créer, lister, supprimer ou vérifier les étiquettes"
 
 msgid "Creates a temporary file with a blob's contents"
 msgstr "Créer un fichier temporaire avec le contenu d'un blob"
@@ -16058,6 +16766,44 @@
 msgid "unable to parse command-line config"
 msgstr "lecture de la configuration de ligne de commande impossible"
 
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"Pour utiliser la chaîne de comment par défaut (#), veuillez lancer\n"
+"\n"
+"%s"
+
+msgid "<comment string>"
+msgstr "<chaîne-de-comment>"
+
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+"\n"
+"Pour paramétrer une chaîne de commentaire personnalisée, veuillez lancer\n"
+"\n"
+"%s\n"
+"où '%s' est la chaîne que vous souhaitez utiliser.\n"
+
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr "La prise en charge de '%s=auto' a été supprimée dans Git 3.0"
+
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr ""
+"La prise en charge de '%s=auto' est obsolète et sera retirée dans Git 3.0"
+
 msgid "unknown error occurred while reading the configuration files"
 msgstr "erreur inconnue pendant la lecture des fichiers de configuration"
 
@@ -16550,6 +17296,12 @@
 msgid "failed to write archive"
 msgstr "impossible d'écrire l'archive"
 
+msgid "max-depth is not supported for worktree diffs"
+msgstr "max-depth non supporté pour les diffs d'arbre-de-travail"
+
+msgid "max-depth is not supported for index diffs"
+msgstr "max-depth n'est pas géré pour les diffs d'index"
+
 msgid "--merge-base does not work with ranges"
 msgstr "--merge-base ne fonctionne pas avec des plages"
 
@@ -17085,6 +17837,12 @@
 msgid "select files by diff type"
 msgstr "sélectionner les fichiers par types de diff"
 
+msgid "<depth>"
+msgstr "<profondeur>"
+
+msgid "maximum tree depth to recurse"
+msgstr "profondeur d'arbre maximum de récursion"
+
 msgid "<file>"
 msgstr "<fichier>"
 
@@ -17288,10 +18046,6 @@
 msgstr "ligne de fin de superficiel invalide : %s"
 
 #, c-format
-msgid "object not found: %s"
-msgstr "objet non trouvé : %s"
-
-#, c-format
 msgid "error in object: %s"
 msgstr "erreur dans l'objet : %s"
 
@@ -17574,6 +18328,10 @@
 msgid "recursive alias: %s"
 msgstr "alias recursif : %s"
 
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr "boucle d'alias détectée : l'expansion de '%s' ne finit jamais : %s"
+
 msgid "write failure on standard output"
 msgstr "échec d'écriture sur la sortie standard"
 
@@ -17584,10 +18342,6 @@
 msgstr "échec de fermeture de la sortie standard"
 
 #, c-format
-msgid "alias loop detected: expansion of '%s' does not terminate:%s"
-msgstr "boucle d'alias détectée : l'expansion de '%s' ne finit jamais : %s"
-
-#, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "impossible d'utiliser %s comme une fonction intégrée"
 
@@ -17641,11 +18395,19 @@
 msgid "failed to get the ssh fingerprint for key '%s'"
 msgstr "échec d'obtention de l'empreinte ssh pour la clé '%s'"
 
+#, c-format
+msgid "failed to get the ssh fingerprint for key %s"
+msgstr "échec d'obtention de l'empreinte ssh pour la clé %s"
+
 msgid ""
 "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
 msgstr "soit user.signingkey ou gpg.ssh.defaultKeyCommand doit être configuré"
 
 #, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr "gpg.ssh.defaultKeyCommand malformée : %s"
+
+#, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr ""
 "gpg.ssh.defaultKeyCommand a réussi mais n'a retourné aucune clé : %s %s"
@@ -17906,6 +18668,13 @@
 "      demandé : %s\n"
 "  redirection : %s"
 
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr ""
+"nombre trop grand pour être représenté par curl_off_t sur cette plateforme : "
+"%<PRIuMAX>"
+
 msgid "Author identity unknown\n"
 msgstr "Identité d'auteur inconnue\n"
 
@@ -18375,10 +19144,6 @@
 msgstr "impossible de charger le paquet"
 
 #, c-format
-msgid "could not open index for %s"
-msgstr "impossible d'ouvrir l'index pour %s"
-
-#, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "impossible de lier '%s' à '%s'"
 
@@ -18402,6 +19167,10 @@
 msgstr "paquet préféré inconnu : %s"
 
 #, c-format
+msgid "failed to open preferred pack %s"
+msgstr "échec à l'ouverture du paquet préféré %s"
+
+#, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr "impossible de sélectionner le paquet préféré %s avec aucun objet"
 
@@ -18425,6 +19194,9 @@
 msgid "could not write multi-pack bitmap"
 msgstr "impossible d'écrire le bitmap multi-paquet"
 
+msgid "too many multi-pack-indexes"
+msgstr "nombre de multi-pack-index trop grand"
+
 msgid "unable to open multi-pack-index chain file"
 msgstr "impossible d'ouvrir le fichier d'index multi-paquet"
 
@@ -18704,10 +19476,6 @@
 msgstr "les fichiers '%s' et '%s' diffèrent par leur contenu"
 
 #, c-format
-msgid "unable to write file %s"
-msgstr "impossible d'écrire le fichier %s"
-
-#, c-format
 msgid "unable to write repeatedly vanishing file %s"
 msgstr "impossible d'écrire le fichier %s qui disparaît répétitivement"
 
@@ -18715,6 +19483,9 @@
 msgid "unable to set permission to '%s'"
 msgstr "impossible de régler les droits de '%s'"
 
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = batch non géré sur cette plateforme"
+
 msgid "error when closing loose object file"
 msgstr "erreur en fermeture du fichier d'objet esseulé"
 
@@ -19224,6 +19995,21 @@
 msgid "mtimes file %s is corrupt"
 msgstr "le fichier de mtimes %s est corrompu"
 
+msgid "pack everything"
+msgstr "empaqueter tout"
+
+msgid "prune loose refs (default)"
+msgstr "élaguer les références perdues (défaut)"
+
+msgid "auto-pack refs as needed"
+msgstr "auto-empaqueter les réfs au besoin"
+
+msgid "references to include"
+msgstr "références à inclure"
+
+msgid "references to exclude"
+msgstr "références à exclure"
+
 #, c-format
 msgid "reverse-index file %s is too small"
 msgstr "le fichier d'index inversé %s est trop petit"
@@ -19662,6 +20448,10 @@
 msgstr "impossible de récupérer %s depuis le distant de prometteur"
 
 #, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr "champ non géré '%s' dans le config '%s'"
+
+#, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "URL manquante ou vide annoncée pour le distant '%s'"
 
@@ -19670,12 +20460,16 @@
 msgstr "distant connu nommé '%s' mais avec l'URL '%s' au lieu de '%s'"
 
 #, c-format
-msgid "unknown '%s' value for '%s' config option"
-msgstr "valeur inconnue '%s' pour l'option de config '%s'"
+msgid "invalid element '%s' from remote info"
+msgstr "élément invalide '%s' pour l'info de distant"
 
 #, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "élément inconnu '%s' pour l'info de distant"
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr "les serveur a annoncé un distant prometteur sans nom ou URL : %s"
+
+#, c-format
+msgid "unknown '%s' value for '%s' config option"
+msgstr "valeur inconnue '%s' pour l'option de config '%s'"
 
 #, c-format
 msgid "accepted promisor remote '%s' not found"
@@ -19775,6 +20569,16 @@
 msgstr "échec de la génération de diff"
 
 #, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+"range-diff: impossible de calculer le range-diff, car il dépasse la mémoire "
+"maximum pour la matrice de coût : %s (%<PRIuMAX> octets) nécessaires, "
+"limités à %s (%<PRIuMAX> octets)"
+
+#, c-format
 msgid "could not parse log for '%s'"
 msgstr "impossible d'analyser le journal pour '%s'"
 
@@ -20308,6 +21112,9 @@
 msgid "no reflog for '%s'"
 msgstr "pas de journal de références pour '%s'"
 
+msgid "Checking references consistency"
+msgstr "Vérification de la cohérence des références"
+
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "%s ne pointe pas sur un objet valide!"
@@ -20323,8 +21130,9 @@
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -20333,18 +21141,33 @@
 "\n"
 "\tgit branch -m <name>\n"
 msgstr ""
-"Utilisation de '%s' comme nom de la branche initiale. Le nom de la branche\n"
-"par défaut peut changer. Pour configurer le nom de la branche initiale\n"
-"pour tous les nouveaux dépôts, et supprimer cet avertissement, lancez :\n"
+"Utilisation de '%s' comme nom de la branche initiale. Le nom\n"
+"de la branche par défaut va changer pour \"main\". Pour configurer\n"
+"le nom de la branche initiale pour tous les nouveaux dépôts,\n"
+"et supprimer cet avertissement, lancez :\n"
 "\n"
 "\tgit config --global init.defaultBranch <nom>\n"
 "\n"
-"Les noms les plus utilisés à la place de 'master' sont 'main', 'trunk' et\n"
-"'development'. La branche nouvellement créée peut être rénommée avec :\n"
+"Les noms les plus utilisés à la place de 'master' sont 'main', 'trunk'\n"
+"et 'development'. La branche nouvelle peut être rénommée avec :\n"
 "\n"
 "\tgit branch -m <nom>\n"
 
 #, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"L'utilisation de '%s' comme nom de branche initial depuis Git 3.0\n"
+"Si vous vous attendiez à ce que Git crée une branche 'master', la\n"
+"branche nouvellement créée peut être renommée comme suit :\n"
+"\n"
+"\tgit branch -m master\n"
+
+#, c-format
 msgid "could not retrieve `%s`"
 msgstr "impossible de récupérer `%s`"
 
@@ -20430,6 +21253,27 @@
 msgid "migrated refs can be found at '%s'"
 msgstr "les références migrées peuvent être trouvées dans '%s'"
 
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+"La suppression de 'core.preferSymlinkRefs=true' est programmée.\n"
+"astuce : L'utilisation de liens symbolique pour les réfs symboliques\n"
+"astuce : est obsolète et sera retirée pour Git 3.0. La configuration\n"
+"astuce : qui indique à Git de les utiliser va disparaître. Vous\n"
+"astuce : pouvez la désactiver avec :\n"
+"astuce :\n"
+"astuce :\tgit config unset core.preferSymlinkRefs\n"
+"astuce :\n"
+"astuce : Git utilisera alors le format textuel de symref à la place."
+
 #, c-format
 msgid ""
 "cannot lock ref '%s': expected symref with target '%s': but is a regular ref"
@@ -20438,6 +21282,10 @@
 "normale trouvée"
 
 #, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr "essai d'écriture du reflog pour '%s' avec des valeurs incomplètes"
+
+#, c-format
 msgid "cannot read ref file '%s'"
 msgstr "impossible de lire le fichier de référence '%s'"
 
@@ -20445,9 +21293,6 @@
 msgid "cannot open directory %s"
 msgstr "impossible d'ouvrir le répertoire %s"
 
-msgid "Checking references consistency"
-msgstr "Vérification de la cohérence des références"
-
 #, c-format
 msgid "unable to open '%s'"
 msgstr "impossible d'ouvrir '%s'"
@@ -20491,6 +21336,12 @@
 "mises à jour multiples pour '%s' (dont un via la symref '%s') non permises"
 
 #, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr ""
+"impossible de verrouiller la référence '%s' : une référence en suspens "
+"existe déjà"
+
+#, c-format
 msgid "cannot lock ref '%s': reference already exists"
 msgstr "impossible de verrouiller la référence '%s' : la référence existe déjà"
 
@@ -20595,9 +21446,6 @@
 msgid "RPC failed; %s"
 msgstr "échec RPC ; %s"
 
-msgid "cannot handle pushes this big"
-msgstr "impossible de gérer des poussées aussi grosses"
-
 #, c-format
 msgid "cannot deflate request; zlib deflate error %d"
 msgstr "impossible de compresser la requête ; erreur de compression zlib %d"
@@ -20689,7 +21537,7 @@
 
 #, c-format
 msgid "unrecognized followRemoteHEAD value '%s' ignored"
-msgstr "valeur '%s' de followRemoteHEAD non reconnue et ignorée "
+msgstr "valeur '%s' de followRemoteHEAD non reconnue et ignorée"
 
 #, c-format
 msgid "unrecognized value transfer.credentialsInUrl: '%s'"
@@ -20789,6 +21637,12 @@
 "'%s:refs/tags/%s' ?"
 
 #, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr ""
+"La partie <src> de la refspec ('%s') est un ID d'objet qui n'existe pas.\n"
+
+#, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "'%s' ne peut pas être résolue comme une branche"
 
@@ -20920,6 +21774,64 @@
 msgstr "impossible de supprimer un composant de l'URL '%s'"
 
 #, c-format
+msgid "cannot open index for %s"
+msgstr "impossible d'ouvrir l'index pour %s"
+
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr ""
+"le paquet %s est trop gros pour être pris en compte dans un progression "
+"géométrique"
+
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "le paquet %s est trop gros à enrouler"
+
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "impossible d'ouvrir le fichier temporaire %s en écriture"
+
+msgid "could not close refs snapshot tempfile"
+msgstr "impossible de fermer le fichier temporaire d'instantané des réfs"
+
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "impossible de revenir la bitmap obsolète : %s"
+
+msgid "could not start pack-objects to repack promisor objects"
+msgstr ""
+"ne pas démarrer pack-objects pour ré-empaqueter les objects de prometteur"
+
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "Échéc de la fourniture les objets du prometteur à pack-objects"
+
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr ""
+"repack : attente de lignes d'Id d'objets en hexa complet seulement depuis "
+"les objects de paquet."
+
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr ""
+"impossible de terminer pack-objects  pour ré-empaqueter les objets de "
+"prometteur"
+
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "le préfixe %s ne commence pas avec objdir %s"
+
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr "le renommage du paquet en '%s' a échoué"
+
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "pack-objects n'a pas écrit un fichier '%s' pour la paquet %s-%s"
+
+#, c-format
+msgid "could not unlink: %s"
+msgstr "impossible de délier : '%s'"
+
+#, c-format
 msgid "bad replace ref name: %s"
 msgstr "mauvaise références de remplacement : %s"
 
@@ -22238,9 +23150,6 @@
 msgid "cannot chdir to '%s'"
 msgstr "impossible de se déplacer vers le répertoire (chdir) '%s'"
 
-msgid "cannot come back to cwd"
-msgstr "impossible de revenir au répertoire de travail courant"
-
 #, c-format
 msgid "failed to stat '%*s%s%s'"
 msgstr "échec du stat de '%*s%s%s'"
@@ -23326,18 +24235,32 @@
 msgstr "avertissement : "
 
 #, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "'%s' est nommé pour la suppression.\n"
+
+#, c-format
 msgid ""
-"'%s' 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"
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
 msgstr ""
-"La suppression  de '%s' est prévue.\n"
-"Si vous utilisez cette commande, veuillez ajouter\n"
-"une option supplémentaire, '--i-still-use-this',\n"
-"sur la ligne de commande pour nous avertir par\n"
-"un courriel à <git@vger.kernel.org>. Merci.\n"
+"Si vous utilisez toujours cette commande, voici ce que vous pouvez faire :\n"
+"\n"
+"- lire  https://git-scm.com/docs/BreakingChanges.html\n"
+"- vérifier si quelqu'un a abordé le sujet sur la liste\n"
+"  de diffusion et si une solution à votre problème a été\n"
+"  trouvée : https://lore.kernel.org/git/?q=%s\n"
+"- envoyer un courriel à <git@vger.kernel.org> et nous\n"
+"  informer que vous utilisez toujours cette commande et\n"
+"  que vous n'avez pas trouvé de remplacement\n"
+"\n"
 
 msgid "refusing to run without --i-still-use-this"
 msgstr "refus de lancer sans --i-still-use-this"
@@ -24217,6 +25140,9 @@
 msgid "Send this email reply required"
 msgstr "Une réponse est nécessaire"
 
+msgid "The destination IMAP folder is not properly defined."
+msgstr "Le dossier IMAP destination n'est pas défini correctement."
+
 msgid "The required SMTP server is not properly defined."
 msgstr "Le serveur SMTP nécessaire n'est pas défini correctement."
 
@@ -24343,6 +25269,60 @@
 msgid "Do you really want to send %s? [y|N]: "
 msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : "
 
+#~ msgid "No previous hunk"
+#~ msgstr "Pas de section précédente"
+
+#~ msgid "No next hunk"
+#~ msgstr "Pas de section suivante"
+
+#~ msgid "git for-each-ref [<options>] [<pattern>]"
+#~ msgstr "git for-each-ref [<options>] [<motif>]"
+
+#~ msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
+#~ msgstr "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
+
+#~ msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
+#~ msgstr "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
+
+#~ msgid "git for-each-ref [--start-after <marker>]"
+#~ msgstr "git for-each-ref [--start-after <marqueur>]"
+
+#~ msgid ""
+#~ "git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--"
+#~ "exclude <pattern>]"
+#~ msgstr ""
+#~ "git pack-refs [--all] [--no-prune] [--auto] [--include <motif>] [--"
+#~ "exclude <motif>]"
+
+#, c-format
+#~ msgid "deleting '%s' failed"
+#~ msgstr "échec de suppression de '%s'"
+
+#, c-format
+#~ msgid "creating '%s' failed"
+#~ msgstr "échec de création de '%s'"
+
+#, c-format
+#~ msgid "could not open index for %s"
+#~ msgstr "impossible d'ouvrir l'index pour %s"
+
+#~ msgid "cannot handle pushes this big"
+#~ msgstr "impossible de gérer des poussées aussi grosses"
+
+#, c-format
+#~ msgid ""
+#~ "'%s' 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 ""
+#~ "La suppression  de '%s' est prévue.\n"
+#~ "Si vous utilisez cette commande, veuillez ajouter\n"
+#~ "une option supplémentaire, '--i-still-use-this',\n"
+#~ "sur la ligne de commande pour nous avertir par\n"
+#~ "un courriel à <git@vger.kernel.org>. Merci.\n"
+
 #~ msgid "start-after"
 #~ msgstr "start-after"
 
diff --git a/po/ga.po b/po/ga.po
index c03f637..bed2ea2 100644
--- a/po/ga.po
+++ b/po/ga.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: 2025-05-29 09:16+0100\n"
-"PO-Revision-Date: 2025-05-29 10:10+0100\n"
+"POT-Creation-Date: 2025-11-06 23:58+0000\n"
+"PO-Revision-Date: 2025-11-07 21:39+0000\n"
 "Last-Translator: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>\n"
 "Language-Team: none\n"
 "Language: ga\n"
@@ -16,43 +16,38 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n"
-"X-Generator: Poedit 3.4.4\n"
+"X-Generator: Poedit 3.7\n"
 
-#: add-interactive.c
+#, c-format
+msgid "%s cannot be negative"
+msgstr "Ní féidir %s a bheith diúltach"
+
 #, c-format
 msgid "Huh (%s)?"
 msgstr "Huh (%s)?"
 
-#: add-interactive.c builtin/merge.c builtin/rebase.c reset.c sequencer.c
 msgid "could not read index"
 msgstr "ní raibh in ann innéacs a léamh"
 
-#: add-interactive.c
 msgid "binary"
 msgstr "dénártha"
 
-#: add-interactive.c
 msgid "nothing"
 msgstr "rud ar bith"
 
-#: add-interactive.c
 msgid "unchanged"
 msgstr "gan athrú"
 
-#: add-interactive.c
 msgid "Update"
 msgstr "Nuashonraigh"
 
-#: add-interactive.c
 #, c-format
 msgid "could not stage '%s'"
 msgstr "ní fhéadfaí '%s' a chéim"
 
-#: add-interactive.c builtin/stash.c reset.c sequencer.c
 msgid "could not write index"
 msgstr "ní fhéadfadh innéacs a scríobh"
 
-#: add-interactive.c
 #, c-format
 msgid "updated %d path\n"
 msgid_plural "updated %d paths\n"
@@ -60,25 +55,20 @@
 msgstr[1] "nuashonraíodh %d cosán\n"
 msgstr[2] "nuashonraíodh %d cosán\n"
 
-#: add-interactive.c
 #, c-format
 msgid "note: %s is untracked now.\n"
 msgstr "nótaí: Tá %s dírianaithe anois.\n"
 
-#: add-interactive.c apply.c builtin/checkout.c builtin/reset.c
 #, c-format
 msgid "make_cache_entry failed for path '%s'"
 msgstr "theip ar make_cache_entry le haghaidh cosán '%s'"
 
-#: add-interactive.c
 msgid "Revert"
 msgstr "Aisghabháil"
 
-#: add-interactive.c
 msgid "Could not parse HEAD^{tree}"
 msgstr "Ní raibh sé in ann HEAD ^ {tree} a pharsáil"
 
-#: add-interactive.c
 #, c-format
 msgid "reverted %d path\n"
 msgid_plural "reverted %d paths\n"
@@ -86,16 +76,13 @@
 msgstr[1] "%d cosán aisiompaithe\n"
 msgstr[2] "%d cosán aisiompaithe\n"
 
-#: add-interactive.c
 #, c-format
 msgid "No untracked files.\n"
 msgstr "Gan aon chomhaid neamhrianaithe.\n"
 
-#: add-interactive.c
 msgid "Add untracked"
 msgstr "Cuir neamh-rianaithe leis"
 
-#: add-interactive.c
 #, c-format
 msgid "added %d path\n"
 msgid_plural "added %d paths\n"
@@ -103,145 +90,110 @@
 msgstr[1] "%d cosán curtha leis\n"
 msgstr[2] "%d cosán curtha leis\n"
 
-#: add-interactive.c
 #, c-format
 msgid "ignoring unmerged: %s"
 msgstr "ag neamhaird a dhéanamh de neamhchumasctha: %s"
 
-#: add-interactive.c
 #, c-format
 msgid "Only binary files changed.\n"
 msgstr "Níor athraigh ach comhaid dénártha.\n"
 
-#: add-interactive.c
 #, c-format
 msgid "No changes.\n"
 msgstr "Gan aon athruithe.\n"
 
-#: add-interactive.c
 msgid "Patch update"
 msgstr "Nuashonrú paiste"
 
-#: add-interactive.c
 msgid "Review diff"
 msgstr "Athbhreithniú diff"
 
-#: add-interactive.c
 msgid "show paths with changes"
 msgstr "taispeáin cosáin le hathruithe"
 
-#: add-interactive.c
 msgid "add working tree state to the staged set of changes"
 msgstr "cuir stát crann oibre leis an tsraith athruithe céimeádta"
 
-#: add-interactive.c
 msgid "revert staged set of changes back to the HEAD version"
 msgstr "tacar athruithe céime a chur ar ais chuig an leagan HEAD"
 
-#: add-interactive.c
 msgid "pick hunks and update selectively"
 msgstr "roghnaigh hunks agus nuashonraigh go roghnach"
 
-#: add-interactive.c
 msgid "view diff between HEAD and index"
 msgstr "féach ar an difríocht idir HEAD agus innéacs"
 
-#: add-interactive.c
 msgid "add contents of untracked files to the staged set of changes"
 msgstr "cuir ábhar comhaid neamhrianaithe leis an tacar athruithe céimeádta"
 
-#: add-interactive.c
 msgid "Prompt help:"
 msgstr "Cabhair pras:"
 
-#: add-interactive.c
 msgid "select a single item"
 msgstr "roghnaigh mír amháin"
 
-#: add-interactive.c
 msgid "select a range of items"
 msgstr "roghnaigh raon earraí"
 
-#: add-interactive.c
 msgid "select multiple ranges"
 msgstr "roghnaigh raonta iomadúla"
 
-#: add-interactive.c
 msgid "select item based on unique prefix"
 msgstr "roghnaigh mír bunaithe ar réimír uathúil"
 
-#: add-interactive.c
 msgid "unselect specified items"
 msgstr "míreanna sonraithe díroghnaigh"
 
-#: add-interactive.c
 msgid "choose all items"
 msgstr "roghnaigh gach earra"
 
-#: add-interactive.c
 msgid "(empty) finish selecting"
 msgstr "(folamh) críochnaigh a roghnú"
 
-#: add-interactive.c
 msgid "select a numbered item"
 msgstr "roghnaigh mír uimhrithe"
 
-#: add-interactive.c
 msgid "(empty) select nothing"
 msgstr "(folamh) roghnaigh aon rud"
 
-#: add-interactive.c builtin/clean.c
 msgid "*** Commands ***"
 msgstr "*** Orduithe ***"
 
-#: add-interactive.c builtin/clean.c
 msgid "What now"
 msgstr "Cad anois"
 
-#: add-interactive.c
 msgid "staged"
 msgstr "stáitse"
 
-#: add-interactive.c
 msgid "unstaged"
 msgstr "gan stáitse"
 
-#: add-interactive.c apply.c builtin/am.c builtin/bugreport.c builtin/clone.c
-#: builtin/diagnose.c builtin/fetch.c builtin/hook.c builtin/merge.c
-#: builtin/pull.c builtin/submodule--helper.c
 msgid "path"
 msgstr "cosán"
 
-#: add-interactive.c
 msgid "could not refresh index"
 msgstr "ní fhéadfadh innéacs a athnuachan"
 
-#: add-interactive.c builtin/clean.c
 #, c-format
 msgid "Bye.\n"
-msgstr "Slán..\n"
+msgstr "Slán.\n"
 
-#: add-patch.c
 #, c-format
 msgid "Stage mode change [y,n,q,a,d%s,?]? "
 msgstr "Athrú modh stáitse [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Stage deletion [y,n,q,a,d%s,?]? "
 msgstr "Scriosadh céime [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Stage addition [y,n,q,a,d%s,?]? "
 msgstr "Breiseán céime [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Stage this hunk [y,n,q,a,d%s,?]? "
 msgstr "Cuir an píosa seo ar stáitse [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "staging."
@@ -249,7 +201,6 @@
 "Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta "
 "a mharcáil láithreach le haghaidh stáitsithe."
 
-#: add-patch.c
 msgid ""
 "y - stage this hunk\n"
 "n - do not stage this hunk\n"
@@ -264,27 +215,22 @@
 "d - ná déan an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad a "
 "chéile\n"
 
-#: add-patch.c
 #, c-format
 msgid "Stash mode change [y,n,q,a,d%s,?]? "
 msgstr "Athrú modh stash [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Stash deletion [y,n,q,a,d%s,?]? "
 msgstr "Scriosadh staise [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Stash addition [y,n,q,a,d%s,?]? "
 msgstr "Breiseán stash [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Stash this hunk [y,n,q,a,d%s,?]? "
 msgstr "An bhfuil an carachtar seo [y,n,q,a,d%s,?] i bhfolach? "
 
-#: add-patch.c
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "stashing."
@@ -292,7 +238,6 @@
 "Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta "
 "a mharcáil láithreach le haghaidh stórála."
 
-#: add-patch.c
 msgid ""
 "y - stash this hunk\n"
 "n - do not stash this hunk\n"
@@ -307,27 +252,22 @@
 "d - ná déan an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad a "
 "stóráil\n"
 
-#: add-patch.c
 #, c-format
 msgid "Unstage mode change [y,n,q,a,d%s,?]? "
 msgstr "Athrú ar mhodh gan stáitse [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Unstage deletion [y,n,q,a,d%s,?]? "
 msgstr "Scriosadh gan stáitse [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Unstage addition [y,n,q,a,d%s,?]? "
 msgstr "Breiseán gan stáitse [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Unstage this hunk [y,n,q,a,d%s,?]? "
 msgstr "Dí-stáitseáil an píosa beag seo den stáitse [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "unstaging."
@@ -335,7 +275,6 @@
 "Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta "
 "a mharcáil láithreach le haghaidh dístáisithe."
 
-#: add-patch.c
 msgid ""
 "y - unstage this hunk\n"
 "n - do not unstage this hunk\n"
@@ -350,27 +289,22 @@
 "d - ná déan an hunk seo nó aon cheann de na huncanna níos déanaí sa chomhad "
 "a dhíchur\n"
 
-#: add-patch.c
 #, c-format
 msgid "Apply mode change to index [y,n,q,a,d%s,?]? "
 msgstr "Cuir athrú mód i bhfeidhm ar innéacs [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Apply deletion to index [y,n,q,a,d%s,?]? "
 msgstr "Cuir scriosadh i bhfeidhm ar innéacs [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Apply addition to index [y,n,q,a,d%s,?]? "
 msgstr "Cuir an breiseán i bhfeidhm ar innéacs [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Apply this hunk to index [y,n,q,a,d%s,?]? "
 msgstr "Cuir an píosa seo i bhfeidhm ar innéacs [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "applying."
@@ -378,7 +312,6 @@
 "Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta "
 "a mharcáil láithreach le haghaidh iarratas a dhéanamh."
 
-#: add-patch.c
 msgid ""
 "y - apply this hunk to index\n"
 "n - do not apply this hunk to index\n"
@@ -394,28 +327,23 @@
 "d - ná cuir an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad i "
 "bhfeidhm\n"
 
-#: add-patch.c
 #, c-format
 msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? "
 msgstr "Athrú modh a dhiúscairt ó chrann oibre [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? "
 msgstr "An scriosadh ón gcrann oibre [y,n,q,a,d%s,?] a sheachaint? "
 
-#: add-patch.c
 #, c-format
 msgid "Discard addition from worktree [y,n,q,a,d%s,?]? "
 msgstr "Scrios an breiseán ón gcrann oibre [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "An bhfuil an píosa beag seo le fáil réidh ón gcrann oibre [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be marked for "
 "discarding."
@@ -423,7 +351,6 @@
 "Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta "
 "a mharcáil láithreach lena dhiúscairt."
 
-#: add-patch.c
 msgid ""
 "y - discard this hunk from worktree\n"
 "n - do not discard this hunk from worktree\n"
@@ -438,31 +365,26 @@
 "d - ná caith an hunk seo ná aon cheann de na huncanna níos déanaí sa "
 "chomhad\n"
 
-#: add-patch.c
 #, c-format
 msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "Athrú modh a dhiúscairt ó innéacs agus crann oibre [y, n, q, a, d %s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "An scriosadh ón innéacs agus ón gcrann oibre [y,n,q,a,d%s,?] a dhíbirt? "
 
-#: add-patch.c
 #, c-format
 msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? "
 msgstr "Caitheamh breisiú ó innéacs agus crann oibre [y, n, q, a, d %s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "An bhfuil an píosa beag seo le fáil réidh ón innéacs agus ón gcrann oibre "
 "[y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 msgid ""
 "y - discard this hunk from index and worktree\n"
 "n - do not discard this hunk from index and worktree\n"
@@ -477,34 +399,29 @@
 "d - ná caith an hunk seo ná aon cheann de na huncanna níos déanaí sa "
 "chomhad\n"
 
-#: add-patch.c
 #, c-format
 msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "Cuir athrú mód i bhfeidhm ar an innéacs agus ar an gcrann oibre "
 "[y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "Cuir scriosadh i bhfeidhm ar innéacs agus crann oibre [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "Cuir an breiseán i bhfeidhm ar an innéacs agus ar an gcrann oibre "
 "[y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "
 msgstr ""
 "Cuir an píosa seo i bhfeidhm ar an innéacs agus ar an gcrann oibre "
 "[y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 msgid ""
 "y - apply this hunk to index and worktree\n"
 "n - do not apply this hunk to index and worktree\n"
@@ -520,27 +437,22 @@
 "d - ná cuir an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad i "
 "bhfeidhm\n"
 
-#: add-patch.c
 #, c-format
 msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? "
 msgstr "Cuir athrú mód i bhfeidhm ar an gcrann oibre [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? "
 msgstr "Cuir scriosadh i bhfeidhm ar chrann oibre [y, n, q, a, d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Apply addition to worktree [y,n,q,a,d%s,?]? "
 msgstr "Cuir an breiseán i bhfeidhm ar an gcrann oibre [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 #, c-format
 msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? "
 msgstr "Cuir an píosa seo i bhfeidhm ar an gcrann oibre [y,n,q,a,d%s,?]? "
 
-#: add-patch.c
 msgid ""
 "y - apply this hunk to worktree\n"
 "n - do not apply this hunk to worktree\n"
@@ -556,29 +468,23 @@
 "d - ná cuir an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad i "
 "bhfeidhm\n"
 
-#: add-patch.c
 #, c-format
 msgid "could not parse hunk header '%.*s'"
 msgstr "níorbh fhéidir ceanntásc an bhlúire '%.*s' a pharsáil"
 
-#: add-patch.c
 msgid "could not parse diff"
 msgstr "ní raibh sé in ann difríocht a pharsáil"
 
-#: add-patch.c
 msgid "could not parse colored diff"
 msgstr "ní raibh sé in ann difríocht daite a pháirseáil"
 
-#: add-patch.c
 #, c-format
 msgid "failed to run '%s'"
 msgstr "theip ar '%s' a reáchtáil"
 
-#: add-patch.c
 msgid "mismatched output from interactive.diffFilter"
 msgstr "aschur mí-mheaitseáilte ó interactive.diffFilter"
 
-#: add-patch.c
 msgid ""
 "Your filter must maintain a one-to-one correspondence\n"
 "between its input and output lines."
@@ -586,7 +492,6 @@
 "Caithfidh do scagaire comhfhreagras duine le duine a choinneáil\n"
 "idir a línte ionchuir agus aschuir."
 
-#: add-patch.c
 #, c-format
 msgid ""
 "expected context line #%d in\n"
@@ -595,7 +500,6 @@
 "líne comhthéacs a bhfuil súil leo #%d i\n"
 "%.*s"
 
-#: add-patch.c
 #, c-format
 msgid ""
 "hunks do not overlap:\n"
@@ -608,12 +512,10 @@
 " ní chríochnaíonn sé le:\n"
 "%.*s"
 
-#: add-patch.c
 msgid "Manual hunk edit mode -- see bottom for a quick guide.\n"
 msgstr ""
 "Modh eagarthóireachta hunk láimhe - féach an bun le haghaidh treoir thapa.\n"
 
-#: add-patch.c
 #, c-format
 msgid ""
 "---\n"
@@ -626,7 +528,6 @@
 "Chun línte '%c' a bhaint, scrios iad.\n"
 "Bainfear línte a thosaíonn le %s.\n"
 
-#: 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"
@@ -637,11 +538,9 @@
 "eagarthóireacht\n"
 "cuireadh isteach agus fágtar an hunk gan athrú.\n"
 
-#: add-patch.c
 msgid "could not parse hunk header"
 msgstr "ní fhéadfaí ceanntásc hunk a pháirseáil"
 
-#: add-patch.c
 msgid "'git apply --cached' failed"
 msgstr "Theip ar 'git apply --cached'"
 
@@ -651,80 +550,71 @@
 #. (saying "n" for "no" discards!) if the translation
 #. of the word "no" does not start with n.
 #.
-#: add-patch.c
 msgid ""
 "Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
 msgstr ""
 "Ní bhaineann do chuid eagraithe. Cuir in eagar arís (ag rá \"níl\" cuirtear "
 "i leataobh é!) [y/n]? "
 
-#: add-patch.c
 msgid "The selected hunks do not apply to the index!"
 msgstr "Ní bhaineann na hunks roghnaithe leis an innéacs!"
 
-#: add-patch.c
 msgid "Apply them to the worktree anyway? "
 msgstr "An gcuirfidh tú i bhfeidhm iad ar an gcrann oibre ar aon nós? "
 
-#: add-patch.c
 msgid "Nothing was applied.\n"
 msgstr "Ní chuirtear aon rud i bhfeidhm.\n"
 
-#: add-patch.c
 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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
-"j - fág an hunk seo gan chinneadh, féach an chéad hunk neamhchinnte eile\n"
-"J - fág an hunk seo gan chinneadh, féach an chéad hunk eile\n"
-"k - fág an hunk seo gan chinneadh, féach an hunk neamhchinnte roimhe seo\n"
-"K - fág an hunk seo gan chinneadh, féach an hunk roimhe seo\n"
-"g - roghnaigh hunk le dul chuig\n"
-"/- cuardaigh hunk a mheaitseann leis an regex a thugtar\n"
-"s - roinn an hunk reatha ina huncanna níos lú\n"
-"e - cuir an hunk reatha in eagar de láimh\n"
-"p - priontáil an hunk reatha, 'P' chun an pager a úsáid\n"
-"? - cabhair priontála\n"
+"j - téigh go dtí an chéad phíosa eile gan chinneadh, rolladh thar ag an "
+"mbun\n"
+"J - téigh go dtí an chéad phíosa eile, rolladh thar ag an mbun\n"
+"k - téigh go dtí an phíosa roimhe sin gan chinneadh, rolladh thar ag an "
+"mbarr\n"
+"K - téigh go dtí an phíosa roimhe sin, rolladh thar ag an mbarr\n"
+"g - roghnaigh píosa le dul chuige\n"
+"/ - déan cuardach ar phíosa a mheaitseálann an regex tugtha\n"
+"s - roinn an píosa reatha ina phíosaí níos lú\n"
+"e - cuir an píosa reatha in eagar de láimh\n"
+"p - priontáil an píosa reatha\n"
+"P - priontáil an píosa reatha ag baint úsáide as an ngléasóir\n"
+"? - cabhair phriontála\n"
 
-#: add-patch.c
 #, c-format
 msgid "Only one letter is expected, got '%s'"
 msgstr "Níl súil leis ach litir amháin, fuair '%s'"
 
-#: add-patch.c
-msgid "No previous hunk"
-msgstr "Níl aon hunk roimhe seo"
+msgid "No other hunk"
+msgstr "Gan aon phíosa eile"
 
-#: add-patch.c
-msgid "No next hunk"
-msgstr "Níl aon chéad hunk eile"
+msgid "No other undecided hunk"
+msgstr "Gan aon phíosa eile gan cinneadh"
 
-#: add-patch.c
 msgid "No other hunks to goto"
-msgstr "Níl aon ghuncanna eile le dul"
+msgstr "Níl aon phíosa eile le dul go"
 
-#: add-patch.c
 msgid "go to which hunk (<ret> to see more)? "
 msgstr "téigh chuig cén hunk (<ret> le tuilleadh a fheiceáil)? "
 
-#: add-patch.c
 msgid "go to which hunk? "
 msgstr "téigh chuig cén hunk? "
 
-#: add-patch.c
 #, c-format
 msgid "Invalid number: '%s'"
 msgstr "Uimhir neamhbhailí: '%s'"
 
-#: add-patch.c
 #, c-format
 msgid "Sorry, only %d hunk available."
 msgid_plural "Sorry, only %d hunks available."
@@ -732,54 +622,42 @@
 msgstr[1] "Tá brón orm, níl ach %d hunks ar fáil."
 msgstr[2] "Tá brón orm, níl ach %d hunks ar fáil."
 
-#: add-patch.c
 msgid "No other hunks to search"
-msgstr "Níl aon ghuncanna eile le cuardach"
+msgstr "Níl aon phíosa eile le cuardach"
 
-#: add-patch.c
 msgid "search for regex? "
 msgstr "cuardach a dhéanamh ar regex? "
 
-#: add-patch.c
 #, c-format
 msgid "Malformed search regexp %s: %s"
 msgstr "Regexp cuardaigh mífheidhmithe %s: %s"
 
-#: add-patch.c
 msgid "No hunk matches the given pattern"
 msgstr "Níl aon hunk ag teacht leis an bpatrún tugtha"
 
-#: add-patch.c
 msgid "Sorry, cannot split this hunk"
 msgstr "Tá brón orainn, ní féidir an hunk seo a roinnt"
 
-#: add-patch.c
 #, c-format
 msgid "Split into %d hunks."
 msgstr "Roinn ina %d hunks."
 
-#: add-patch.c
 msgid "Sorry, cannot edit this hunk"
 msgstr "Tá brón orainn, ní féidir an hunk seo a chur in eagar"
 
-#: add-patch.c
 #, c-format
 msgid "Unknown command '%s' (use '?' for help)"
 msgstr "Ordú anaithnid '%s' (bain úsáid as '?' le haghaidh cabhair)"
 
-#: add-patch.c
 msgid "'git apply' failed"
 msgstr "Theip ar 'git apply'"
 
-#: add-patch.c
 msgid "No changes."
 msgstr "Gan aon athruithe."
 
-#: add-patch.c
 msgid "Only binary files changed."
 msgstr "Níor athraigh ach comhaid dénártha."
 
-#: advice.c
 #, c-format
 msgid ""
 "\n"
@@ -788,44 +666,36 @@
 "\n"
 "Díchumasaigh an teachtaireacht seo le \"git config set advice.%s false\""
 
-#: advice.c
 #, c-format
 msgid "%shint:%s%.*s%s\n"
 msgstr "%sleid:%s%.*s%s\n"
 
-#: advice.c
 msgid "Cherry-picking is not possible because you have unmerged files."
 msgstr ""
 "Ní féidir piocadh silíní toisc go bhfuil comhaid neamh-chumasaithe agat."
 
-#: advice.c
 msgid "Committing is not possible because you have unmerged files."
 msgstr ""
 "Ní féidir tiomantas a dhéanamh toisc go bhfuil comhaid neamh-"
 "chomhcheangailte agat."
 
-#: advice.c
 msgid "Merging is not possible because you have unmerged files."
 msgstr ""
 "Ní féidir cumasc a dhéanamh toisc go bhfuil comhaid neamh-chumasaithe agat."
 
-#: advice.c
 msgid "Pulling is not possible because you have unmerged files."
 msgstr ""
 "Ní féidir tarraingt a tharraingt toisc go bhfuil comhaid neamh-chumasaithe "
 "agat."
 
-#: advice.c
 msgid "Reverting is not possible because you have unmerged files."
 msgstr ""
 "Ní féidir aisiompú toisc go bhfuil comhaid neamh-chomhcheangailte agat."
 
-#: advice.c
 msgid "Rebasing is not possible because you have unmerged files."
 msgstr ""
 "Ní féidir athbhunú a dhéanamh toisc go bhfuil comhaid neamh-chumasaithe agat."
 
-#: advice.c
 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."
@@ -833,23 +703,18 @@
 "<file>Socraigh iad sa chrann oibre, agus ansin bain úsáid as 'git add/rm '\n"
 "de réir mar is cuí chun réiteach a mharcáil agus tiomantas a dhéanamh."
 
-#: advice.c
 msgid "Exiting because of an unresolved conflict."
 msgstr "Ag imeacht mar gheall ar choimhlint neamhréitithe."
 
-#: advice.c builtin/merge.c
 msgid "You have not concluded your merge (MERGE_HEAD exists)."
 msgstr "Níor thug tú do chumasc i gcrích (MERGE_HEAD ann)."
 
-#: advice.c
 msgid "Please, commit your changes before merging."
 msgstr "Déan d'athruithe a dhéanamh le do thoil sula ndéanann tú cumasc."
 
-#: advice.c
 msgid "Exiting because of unfinished merge."
 msgstr "Ag imeacht mar gheall ar chumasc críochnaithe."
 
-#: advice.c
 msgid ""
 "Diverging branches can't be fast-forwarded, you need to either:\n"
 "\n"
@@ -867,11 +732,9 @@
 "\n"
 " git rebase\n"
 
-#: advice.c
 msgid "Not possible to fast-forward, aborting."
 msgstr "Ní féidir dul ar aghaidh go tapa, ag cur isteach."
 
-#: advice.c
 #, c-format
 msgid ""
 "The following paths and/or pathspecs matched paths that exist\n"
@@ -882,7 +745,6 @@
 "lasmuigh de do shainmhíniú seiceála neamhchoitianta, mar sin ní bheidh\n"
 "nuashonraithe san innéacs:\n"
 
-#: advice.c
 msgid ""
 "If you intend to update such entries, try one of the following:\n"
 "* Use the --sparse option.\n"
@@ -893,7 +755,6 @@
 "* Úsáid an rogha --sparse.\n"
 "* Díchumasaigh nó modhnaigh na rialacha neamhghnách."
 
-#: advice.c
 #, c-format
 msgid ""
 "Note: switching to '%s'.\n"
@@ -938,7 +799,6 @@
 "false\n"
 "\n"
 
-#: advice.c
 #, c-format
 msgid ""
 "The following paths have been moved outside the\n"
@@ -950,7 +810,6 @@
 "ar an\n"
 "modhnuithe.\n"
 
-#: advice.c
 msgid ""
 "To correct the sparsity of these paths, do the following:\n"
 "* Use \"git add --sparse <paths>\" to update the index\n"
@@ -961,102 +820,74 @@
 "* Úsáid “git sparse-checkout reapply” chun na rialacha neamhchoitianta a "
 "chur i bhfeidhm"
 
-#: alias.c
 msgid "cmdline ends with \\"
 msgstr "críochnaíonn cmdline le \\"
 
-#: alias.c
 msgid "unclosed quote"
 msgstr "luachan neamhdhúnadh"
 
-#: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c
-#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c
 msgid "too many arguments"
 msgstr "an iomarca argóintí"
 
-#: apply.c
 #, c-format
 msgid "unrecognized whitespace option '%s'"
 msgstr "rogha spás bán gan aithint '%s'"
 
-#: apply.c
 #, c-format
 msgid "unrecognized whitespace ignore option '%s'"
 msgstr "neamhaird ar spás bán gan aithint neamhaird ar rogha '%s'"
 
-#: apply.c archive.c builtin/add.c builtin/branch.c builtin/checkout-index.c
-#: builtin/checkout.c builtin/clean.c builtin/clone.c builtin/commit.c
-#: builtin/describe.c builtin/diff-tree.c builtin/difftool.c
-#: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c
-#: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c
-#: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c
-#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-parse.c
-#: builtin/show-branch.c builtin/stash.c builtin/submodule--helper.c
-#: builtin/tag.c builtin/worktree.c parse-options.c range-diff.c revision.c
 #, c-format
 msgid "options '%s' and '%s' cannot be used together"
 msgstr "ní féidir roghanna '%s' agus '%s' a úsáid le chéile"
 
-#: apply.c
 #, c-format
 msgid "'%s' outside a repository"
 msgstr "'%s' lasmuigh de stór"
 
-#: apply.c
 msgid "failed to read patch"
 msgstr "theip ar phaiste a léamh"
 
-#: apply.c
 msgid "patch too large"
 msgstr "paiste ró-mhór"
 
-#: apply.c
 #, c-format
 msgid "Cannot prepare timestamp regexp %s"
 msgstr "Ní féidir regexp %s aimstampa a ullmhú"
 
-#: apply.c
 #, c-format
 msgid "regexec returned %d for input: %s"
 msgstr "d'fhill regexec %d le haghaidh ionchur: %s"
 
-#: apply.c
 #, c-format
 msgid "unable to find filename in patch at line %d"
 msgstr "ní féidir ainm comhaid a aimsiú i bpaiste ag an líne %d"
 
-#: apply.c
 #, c-format
 msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d"
 msgstr "git apply: bad git-diff - ag súil le /dev/null, fuair %s ar líne %d"
 
-#: apply.c
 #, c-format
 msgid "git apply: bad git-diff - inconsistent new filename on line %d"
 msgstr ""
 "git apply: bad git-diff - ainm comhaid nua neamhchomhsheasmhach ar líne %d"
 
-#: apply.c
 #, c-format
 msgid "git apply: bad git-diff - inconsistent old filename on line %d"
 msgstr "git apply: bad git-diff - sean-ainm comhaid neamhréireach ar líne %d"
 
-#: apply.c
 #, c-format
 msgid "git apply: bad git-diff - expected /dev/null on line %d"
 msgstr "git apply: bad git-diff - súil leis /dev/null ar líne %d"
 
-#: apply.c
 #, c-format
 msgid "invalid mode on line %d: %s"
 msgstr "modh neamhbhailí ar líne %d: %s"
 
-#: apply.c
 #, c-format
 msgid "inconsistent header lines %d and %d"
 msgstr "línte ceanntásc neamhchomhsheasmhach %d agus %d"
 
-#: apply.c
 #, c-format
 msgid ""
 "git diff header lacks filename information when removing %d leading pathname "
@@ -1074,80 +905,64 @@
 "tá easpa eolais ainm comhaid ar cheanntásc git diff agus %d comhpháirteanna "
 "ainm cosáin tosaigh á mbaint (líne %d)"
 
-#: apply.c
 #, c-format
 msgid "git diff header lacks filename information (line %d)"
 msgstr "tá easpa eolais ainm comhaid ar cheanntásc git diff (líne %d)"
 
-#: apply.c
 #, c-format
 msgid "recount: unexpected line: %.*s"
 msgstr "atháireamh: líne gan choinne: %.*s"
 
-#: apply.c
 #, c-format
 msgid "patch fragment without header at line %d: %.*s"
 msgstr "blúirt paiste gan ceanntásc ag an líne %d: %.*s"
 
-#: apply.c
 msgid "new file depends on old contents"
 msgstr "braitheann comhad nua ar shean-ábhar"
 
-#: apply.c
 msgid "deleted file still has contents"
 msgstr "tá ábhar fós ag comhad scriosta"
 
-#: apply.c
 #, c-format
 msgid "corrupt patch at line %d"
 msgstr "paiste truaillithe ag líne %d"
 
-#: apply.c
 #, c-format
 msgid "new file %s depends on old contents"
 msgstr "braitheann an comhad nua %s ar an seanábhar"
 
-#: apply.c
 #, c-format
 msgid "deleted file %s still has contents"
 msgstr "tá ábhar fós ag comhad scriosta %s"
 
-#: apply.c
 #, c-format
 msgid "** warning: file %s becomes empty but is not deleted"
 msgstr "** rabhadh: éiríonn comhad %s folamh ach ní scriostar é"
 
-#: apply.c
 #, c-format
 msgid "corrupt binary patch at line %d: %.*s"
 msgstr "paiste dénártha truaillithe ag líne %d: %.*s"
 
-#: apply.c
 #, c-format
 msgid "unrecognized binary patch at line %d"
 msgstr "paiste dénártha gan aithint ag an líne %d"
 
-#: apply.c
 #, c-format
 msgid "patch with only garbage at line %d"
 msgstr "paiste gan ach truflais ag an líne %d"
 
-#: apply.c
 #, c-format
 msgid "unable to read symlink %s"
-msgstr "nach féidir nasc simtéarach %s a léamh"
+msgstr "ní féidir an nasc siombalach %s a léamh"
 
-#: apply.c
 #, c-format
 msgid "unable to open or read %s"
-msgstr "nach féidir %s a oscailt nó a léamh"
+msgstr "ní féidir %s a oscailt ná a léamh"
 
-#: apply.c
 #, c-format
 msgid "invalid start of line: '%c'"
 msgstr "tús neamhbhailí na líne: '%c'"
 
-#: apply.c
 #, c-format
 msgid "Hunk #%d succeeded at %d (offset %d line)."
 msgid_plural "Hunk #%d succeeded at %d (offset %d lines)."
@@ -1155,12 +970,10 @@
 msgstr[1] "D'éirigh le hunk #%d ag %d (%d líne curtha as feidhm)."
 msgstr[2] "D'éirigh le hunk #%d ag %d (%d líne curtha as feidhm)."
 
-#: apply.c
 #, c-format
 msgid "Context reduced to (%ld/%ld) to apply fragment at %d"
 msgstr "Laghdaithe comhthéacs go (%ld/%ld) chun blúire a chur i bhfeidhm ag %d"
 
-#: apply.c
 #, c-format
 msgid ""
 "while searching for:\n"
@@ -1169,25 +982,21 @@
 "agus tú ag cuardach:\n"
 "%.*s"
 
-#: apply.c
 #, c-format
 msgid "missing binary patch data for '%s'"
 msgstr "sonraí paiste dénártha in easnamh do '%s'"
 
-#: apply.c
 #, c-format
 msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'"
 msgstr ""
 "ní féidir paiste dénártha a chur i bhfeidhm ar ais gan an hunk droim ar ais "
 "chuig '%s'"
 
-#: apply.c
 #, c-format
 msgid "cannot apply binary patch to '%s' without full index line"
 msgstr ""
 "ní féidir paiste dénártha a chur i bhfeidhm ar '%s' gan líne innéacs iomlán"
 
-#: apply.c
 #, c-format
 msgid ""
 "the patch applies to '%s' (%s), which does not match the current contents."
@@ -1195,226 +1004,182 @@
 "baineann an paiste le '%s' (%s), nach bhfuil comhoiriúnach leis an ábhar "
 "reatha."
 
-#: apply.c
 #, c-format
 msgid "the patch applies to an empty '%s' but it is not empty"
 msgstr "baineann an paiste le '%s' folamh ach níl sé folamh"
 
-#: apply.c
 #, c-format
 msgid "the necessary postimage %s for '%s' cannot be read"
 msgstr "ní féidir an post riachtanach %s le haghaidh '%s' a léamh"
 
-#: apply.c
 #, c-format
 msgid "binary patch does not apply to '%s'"
 msgstr "ní bhaineann paiste dénártha le '%s'"
 
-#: apply.c
 #, c-format
 msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)"
 msgstr ""
 "cruthaíonn paiste dénártha chuig '%s' toradh mícheart (ag súil le %s, fuair "
 "%s)"
 
-#: apply.c
 #, c-format
 msgid "patch failed: %s:%ld"
 msgstr "theip ar phaiste: %s: %ld"
 
-#: apply.c builtin/mv.c
 #, c-format
 msgid "cannot checkout %s"
 msgstr "ní féidir %s a sheiceáil"
 
-#: apply.c midx.c pack-mtimes.c pack-revindex.c setup.c
 #, c-format
 msgid "failed to read %s"
 msgstr "theip ar %s a léamh"
 
-#: apply.c
 #, c-format
 msgid "reading from '%s' beyond a symbolic link"
 msgstr "léamh ó '%s' níos faide ná nasc siombalach"
 
-#: apply.c
 #, c-format
 msgid "path %s has been renamed/deleted"
 msgstr "tá conair %s athainmnithe/scriosta"
 
-#: apply.c
 #, c-format
 msgid "%s: does not exist in index"
 msgstr "%s: níl ann san innéacs"
 
-#: apply.c
 #, c-format
 msgid "%s: does not match index"
 msgstr "%s: ní mheaitseálann innéacs"
 
-#: apply.c
 msgid "repository lacks the necessary blob to perform 3-way merge."
 msgstr "níl an blob riachtanach ag stór chun cumasc trí bhealach a dhéanamh."
 
-#: apply.c
 #, c-format
 msgid "Performing three-way merge...\n"
 msgstr "Cumaisc trí bhealach a dhéanamh...\n"
 
-#: apply.c
 #, c-format
 msgid "cannot read the current contents of '%s'"
 msgstr "ní féidir ábhar reatha '%s' a léamh"
 
-#: apply.c
 #, c-format
 msgid "Failed to perform three-way merge...\n"
 msgstr "Theip ar chumasc trí bhealach a dhéanamh...\n"
 
-#: apply.c
 #, c-format
 msgid "Applied patch to '%s' with conflicts.\n"
 msgstr "Paiste cuireadh i bhfeidhm ar '%s' le coinbhleachtaí.\n"
 
-#: apply.c
 #, c-format
 msgid "Applied patch to '%s' cleanly.\n"
 msgstr "Cuireadh paiste i bhfeidhm go '%s' go glan.\n"
 
-#: apply.c
 #, c-format
 msgid "Falling back to direct application...\n"
 msgstr "Ag titim ar ais chuig feidhmchlár díreach...\n"
 
-#: apply.c
 msgid "removal patch leaves file contents"
 msgstr "fágann paiste bainte ábhar an chomhaid"
 
-#: apply.c
 #, c-format
 msgid "%s: wrong type"
 msgstr "%s: cineál mícheart"
 
-#: apply.c
 #, c-format
 msgid "%s has type %o, expected %o"
 msgstr "%s tá cineál %o air, ach bhíothas ag súil le %o"
 
-#: apply.c read-cache.c
 #, c-format
 msgid "invalid path '%s'"
 msgstr "cosán neamhbhailí '%s'"
 
-#: apply.c
 #, c-format
 msgid "%s: already exists in index"
 msgstr "%s: ann cheana féin san innéacs"
 
-#: apply.c
 #, c-format
 msgid "%s: already exists in working directory"
 msgstr "%s: ann cheana féin san eolaire oibre"
 
-#: apply.c
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o)"
 msgstr "ní mheaitseálann modh nua (%o) de %s sean-mhodh (%o)"
 
-#: apply.c
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o) of %s"
 msgstr "ní mheaitseálann modh nua (%o) de %s sean-mhodh (%o) de %s"
 
-#: apply.c
 #, c-format
 msgid "affected file '%s' is beyond a symbolic link"
 msgstr "tá an comhad tionchair '%s' níos faide ná nasc siombalach"
 
-#: apply.c
 #, c-format
 msgid "%s: patch does not apply"
 msgstr "%s: níl paiste i bhfeidhm"
 
-#: apply.c
 #, c-format
 msgid "Checking patch %s..."
 msgstr "Seiceáil paiste %s..."
 
-#: apply.c
 #, c-format
 msgid "sha1 information is lacking or useless for submodule %s"
 msgstr "tá faisnéis sha1 easpa nó gan úsáid le haghaidh fo-mhodúl %s"
 
-#: apply.c
 #, c-format
 msgid "mode change for %s, which is not in current HEAD"
 msgstr "athrú modh do %s, nach bhfuil i HEAD reatha"
 
-#: apply.c
 #, c-format
 msgid "sha1 information is lacking or useless (%s)."
 msgstr "tá faisnéis sha1 easpa nó gan úsáid (%s)."
 
-#: apply.c
 #, c-format
 msgid "could not add %s to temporary index"
 msgstr "ní fhéadfaí %s a chur le hinnéacs sealadach"
 
-#: apply.c
 #, c-format
 msgid "could not write temporary index to %s"
 msgstr "ní fhéadfaí innéacs sealadach a scríobh chuig %s"
 
-#: apply.c
 #, c-format
 msgid "unable to remove %s from index"
-msgstr "nach féidir %s a bhaint as innéacs"
+msgstr "ní féidir %s a bhaint den innéacs"
 
-#: apply.c
 #, c-format
 msgid "corrupt patch for submodule %s"
 msgstr "paiste truaillithe do fho-mhodúl %s"
 
-#: apply.c
 #, c-format
 msgid "unable to stat newly created file '%s'"
-msgstr "nach féidir an comhad nua-chruthaithe '%s' a stáil"
+msgstr "ní féidir an comhad nua-chruthaithe '%s' a atosú"
 
-#: apply.c
 #, c-format
 msgid "unable to create backing store for newly created file %s"
-msgstr "nach féidir stór tacaíochta a chruthú do chomhad nua-chruthaithe %s"
+msgstr ""
+"ní féidir stór tacaíochta a chruthú don chomhad %s a cruthaíodh le déanaí"
 
-#: apply.c
 #, c-format
 msgid "unable to add cache entry for %s"
-msgstr "nach féidir iontráil taisce a chur le haghaidh %s"
+msgstr "ní féidir iontráil taisce a chur leis le haghaidh %s"
 
-#: apply.c builtin/bisect.c builtin/gc.c
 #, c-format
 msgid "failed to write to '%s'"
 msgstr "theip ar scríobh chuig '%s'"
 
-#: apply.c
 #, c-format
 msgid "closing file '%s'"
 msgstr "comhad dúnadh '%s'"
 
-#: apply.c
 #, c-format
 msgid "unable to write file '%s' mode %o"
 msgstr "ní féidir an comhad '%s' modh %o a scríobh"
 
-#: apply.c
 #, c-format
 msgid "Applied patch %s cleanly."
 msgstr "Cuireadh paiste %s i bhfeidhm go glan."
 
-#: apply.c
 msgid "internal error"
 msgstr "earráid inmheánach"
 
-#: apply.c
 #, c-format
 msgid "Applying patch %%s with %d reject..."
 msgid_plural "Applying patch %%s with %d rejects..."
@@ -1422,45 +1187,36 @@
 msgstr[1] "Ag cur paiste %%s i bhfeidhm le %d diúltuithe..."
 msgstr[2] "Ag cur paiste %%s i bhfeidhm le %d diúltuithe..."
 
-#: apply.c
 #, c-format
 msgid "cannot open %s"
 msgstr "ní féidir %s a oscailt"
 
-#: apply.c rerere.c
 #, c-format
 msgid "cannot unlink '%s'"
 msgstr "ní féidir '%s' a dhínascadh"
 
-#: apply.c
 #, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "Cuireadh Hunk #%d i bhfeidhm go glan."
 
-#: apply.c
 #, c-format
 msgid "Rejected hunk #%d."
 msgstr "Hunk diúltaithe #%d."
 
-#: apply.c
 #, c-format
 msgid "Skipped patch '%s'."
 msgstr "Paiste scipeáilte '%s'."
 
-#: apply.c
 msgid "No valid patches in input (allow with \"--allow-empty\")"
 msgstr "Níl aon paistí bailí san ionchur (cead le “--allow-empty”)"
 
-#: apply.c t/helper/test-cache-tree.c
 msgid "unable to read index file"
-msgstr "in ann comhad innéacs a léamh"
+msgstr "ní féidir comhad innéacs a léamh"
 
-#: apply.c
 #, c-format
 msgid "can't open patch '%s': %s"
 msgstr "ní féidir paiste '%s' a oscailt: %s"
 
-#: apply.c
 #, c-format
 msgid "squelched %d whitespace error"
 msgid_plural "squelched %d whitespace errors"
@@ -1468,7 +1224,6 @@
 msgstr[1] "%d earráid spás bán múchta"
 msgstr[2] "%d earráid spás bán múchta"
 
-#: apply.c
 #, c-format
 msgid "%d line adds whitespace errors."
 msgid_plural "%d lines add whitespace errors."
@@ -1476,7 +1231,6 @@
 msgstr[1] "Cuireann %d líne earráidí spás bán leis."
 msgstr[2] "Cuireann %d líne earráidí spás bán leis."
 
-#: apply.c
 #, c-format
 msgid "%d line applied after fixing whitespace errors."
 msgid_plural "%d lines applied after fixing whitespace errors."
@@ -1484,398 +1238,303 @@
 msgstr[1] "%d líne curtha i bhfeidhm tar éis earráidí spás bán a shocrú."
 msgstr[2] "%d líne curtha i bhfeidhm tar éis earráidí spás bán a shocrú."
 
-#: apply.c builtin/mv.c builtin/rm.c
 msgid "Unable to write new index file"
 msgstr "Ní féidir comhad innéacs nua a scríobh"
 
-#: apply.c
 msgid "don't apply changes matching the given path"
 msgstr "ná cuir athruithe a mheaitseáil leis an gcosán tugtha"
 
-#: apply.c
 msgid "apply changes matching the given path"
 msgstr "athruithe a chur i bhfeidhm a mheaitseálann"
 
-#: apply.c builtin/am.c
 msgid "num"
 msgstr "uimhir"
 
-#: apply.c
 msgid "remove <num> leading slashes from traditional diff paths"
-msgstr "bain <num>slascanna ceannródaíocha ó chosáin difriúla traidisiúnta"
+msgstr "bain <num> slaiseanna tosaigh as cosáin dhifriúla traidisiúnta"
 
-#: apply.c
 msgid "ignore additions made by the patch"
 msgstr "neamhaird a dhéanamh ar bhreiseanna a dhéanann an"
 
-#: apply.c
 msgid "instead of applying the patch, output diffstat for the input"
 msgstr "in ionad an paiste a chur i bhfeidhm, diffstat aschuir don ionchur"
 
-#: apply.c
 msgid "show number of added and deleted lines in decimal notation"
 msgstr "líon na línte breise agus scriosta a thaispeáint i nótaí deachúil"
 
-#: apply.c
 msgid "instead of applying the patch, output a summary for the input"
 msgstr "in ionad an paiste a chur i bhfeidhm, aschur achoimre don ionchur"
 
-#: apply.c
 msgid "instead of applying the patch, see if the patch is applicable"
 msgstr ""
 "in ionad an paiste a chur i bhfeidhm, féach an bhfuil an paiste infheidhme"
 
-#: apply.c
 msgid "make sure the patch is applicable to the current index"
 msgstr ""
 "déan cinnte go bhfuil an paiste infheidhme maidir leis an innéacs reatha"
 
-#: apply.c
 msgid "mark new files with `git add --intent-to-add`"
 msgstr "comhad nua a mharcáil le `git add --intent-to-add`"
 
-#: apply.c
 msgid "apply a patch without touching the working tree"
 msgstr "cuir paiste i bhfeidhm gan teagmháil leis an gcrann oibre"
 
-#: apply.c
 msgid "accept a patch that touches outside the working area"
 msgstr "glacadh le paiste a théann lasmuigh den limistéar oibre"
 
-#: apply.c
 msgid "also apply the patch (use with --stat/--summary/--check)"
 msgstr ""
 "cuir an paiste i bhfeidhm freisin (bain úsáid le --stat/--summary/--check)"
 
-#: apply.c
 msgid "attempt three-way merge, fall back on normal patch if that fails"
 msgstr ""
 "iarracht a dhéanamh cumasc trí bhealach, titim ar ais ar ghnáthphaiste má "
 "theipeann"
 
-#: apply.c builtin/merge-file.c
 msgid "for conflicts, use our version"
 msgstr "le haghaidh coimhlintí, bain úsáid as ár leagan"
 
-#: apply.c builtin/merge-file.c
 msgid "for conflicts, use their version"
 msgstr "le haghaidh coimhlintí, bain úsáid as a leagan"
 
-#: apply.c builtin/merge-file.c
 msgid "for conflicts, use a union version"
 msgstr "le haghaidh coimhlintí, bain úsáid as leagan aontais"
 
-#: apply.c
 msgid "build a temporary index based on embedded index information"
 msgstr "innéacs sealadach a thógáil bunaithe ar eolas innéacs leabaithe"
 
-#: apply.c builtin/checkout-index.c
 msgid "paths are separated with NUL character"
 msgstr "tá cosáin scartha le carachtar NUL"
 
-#: apply.c
 msgid "ensure at least <n> lines of context match"
 msgstr "a chinntiú go mbe <n>adh línte comhthéacsa"
 
-#: apply.c builtin/am.c builtin/interpret-trailers.c builtin/pack-objects.c
-#: builtin/rebase.c
 msgid "action"
 msgstr "gníomh"
 
-#: apply.c
 msgid "detect new or modified lines that have whitespace errors"
 msgstr "línte nua nó modhnaithe a bhrath a bhfuil earráidí spás bán acu"
 
-#: apply.c
 msgid "ignore changes in whitespace when finding context"
 msgstr "neamhaird a dhéanamh ar athruithe ar spás bán agus comhthéacs á"
 
-#: apply.c
 msgid "apply the patch in reverse"
 msgstr "cuir an paiste i bhfeidhm ar ais"
 
-#: apply.c
 msgid "don't expect at least one line of context"
 msgstr "ná bí ag súil le líne comhthéacs amháin ar a laghad"
 
-#: apply.c
 msgid "leave the rejected hunks in corresponding *.rej files"
 msgstr "fág na hunks diúltaithe i gcomhaide*.rej comhfhreagracha"
 
-#: apply.c
 msgid "allow overlapping hunks"
 msgstr "cead a cheadú do na huncanna"
 
-#: apply.c
 msgid "tolerate incorrectly detected missing new-line at the end of file"
 msgstr ""
 "glacadh le líne nua atá in easnamh a bhraitear go mícheart ag deireadh an "
 "chomhaid"
 
-#: apply.c
 msgid "do not trust the line counts in the hunk headers"
 msgstr "ná bíodh muinín agat as na comhaireamh líne sna ceanntásca hunk"
 
-#: apply.c builtin/am.c
 msgid "root"
 msgstr "fréamh"
 
-#: apply.c
 msgid "prepend <root> to all filenames"
 msgstr "cuireadh <root>i bhfeidhm ar gach ainm comhaid"
 
-#: apply.c
 msgid "don't return error for empty patches"
 msgstr "ná tabhair earráid ar ais le haghaidh paistí folamh"
 
-#: apply.c
 msgid "--ours, --theirs, and --union require --3way"
 msgstr "Éilíonn --ours, --theirs, agus --union --3way"
 
-#: archive-tar.c archive-zip.c
 #, c-format
 msgid "cannot stream blob %s"
 msgstr "ní féidir le blob %s a shruthlú"
 
-#: archive-tar.c archive-zip.c
 #, c-format
 msgid "unsupported file mode: 0%o (SHA1: %s)"
 msgstr "modh comhad gan tacaíocht: 0%o (SHA1: %s)"
 
-#: archive-tar.c archive-zip.c builtin/pack-objects.c
 #, c-format
 msgid "deflate error (%d)"
 msgstr "earráid dífhabhtaithe (%d)"
 
-#: archive-tar.c
 #, c-format
 msgid "unable to start '%s' filter"
-msgstr "nach féidir scagaire '%s' a thosú"
+msgstr "ní féidir an scagaire '%s' a thosú"
 
-#: archive-tar.c
 msgid "unable to redirect descriptor"
-msgstr "nach féidir tuairiscí a atreorú"
+msgstr "ní féidir an tuairisceoir a atreorú"
 
-#: archive-tar.c
 #, c-format
 msgid "'%s' filter reported error"
 msgstr "Earráid a thuairiscigh scagaire '%s'"
 
-#: archive-zip.c
 #, c-format
 msgid "path is not valid UTF-8: %s"
 msgstr "níl cosán bailí UTF-8: %s"
 
-#: archive-zip.c
 #, c-format
 msgid "path too long (%d chars, SHA1: %s): %s"
 msgstr "cosán rófhada (%d chars, SHA1: %s): %s"
 
-#: archive-zip.c
 #, c-format
 msgid "timestamp too large for this system: %<PRIuMAX>"
 msgstr "stampa ama ró-mhór don chóras seo:%<PRIuMAX>"
 
-#: archive.c
 msgid "git archive [<options>] <tree-ish> [<path>...]"
-msgstr "git cartlan <options>n [] <tree-ish>[<path>...]"
+msgstr "git archive [<options>] <tree-ish> [<path>...]"
 
-#: archive.c
 msgid ""
 "git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"
 msgstr ""
-"<tree-ish><path>git archive --remote <repo>[--exec<cmd>] [] [...<options>]"
+"git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"
 
-#: archive.c
 msgid "git archive --remote <repo> [--exec <cmd>] --list"
-msgstr "<cmd>git archive --remote <repo>[--exec] --list"
+msgstr "git archive --remote <repo> [--exec <cmd>] --list"
 
-#: archive.c builtin/gc.c builtin/notes.c builtin/tag.c
 #, c-format
 msgid "cannot read '%s'"
 msgstr "ní féidir '%s' a léamh"
 
-#: archive.c
 #, c-format
 msgid "pathspec '%s' matches files outside the current directory"
 msgstr "meaitseálann pathspec '%s' comhaid lasmuigh den eolaire reatha"
 
-#: archive.c builtin/add.c builtin/rm.c
 #, c-format
 msgid "pathspec '%s' did not match any files"
 msgstr "níor mheaitseáil pathspec '%s' aon chomhaid"
 
-#: archive.c
 #, c-format
 msgid "no such ref: %.*s"
 msgstr "gan aon tagairt den sórt sin: %.*s"
 
-#: archive.c
 #, c-format
 msgid "not a valid object name: %s"
 msgstr "ní ainm réad bailí: %s"
 
-#: archive.c t/helper/test-cache-tree.c
 #, c-format
 msgid "not a tree object: %s"
 msgstr "ní réad crann: %s"
 
-#: archive.c
 #, c-format
 msgid "failed to unpack tree object %s"
 msgstr "theip ar réad crann %s a dhíphacáil"
 
-#: archive.c
 #, c-format
 msgid "File not found: %s"
 msgstr "Níor aimsíodh an comhad: %s"
 
-#: archive.c
 #, c-format
 msgid "Not a regular file: %s"
 msgstr "Ní comhad rialta: %s"
 
-#: archive.c
 #, c-format
 msgid "unclosed quote: '%s'"
 msgstr "luachan neamhdhúnadh: '%s'"
 
-#: archive.c
 #, c-format
 msgid "missing colon: '%s'"
 msgstr "colon in easnamh: '%s'"
 
-#: archive.c
 #, c-format
 msgid "empty file name: '%s'"
 msgstr "ainm comhaid folamh: '%s'"
 
-#: archive.c
 msgid "fmt"
 msgstr "fmt"
 
-#: archive.c
 msgid "archive format"
 msgstr "formáid cartlann"
 
-#: archive.c builtin/log.c parse-options.h
 msgid "prefix"
 msgstr "réimír"
 
-#: archive.c
 msgid "prepend prefix to each pathname in the archive"
 msgstr "réimír a pholadh chuig gach ainm cosán sa chartlann"
 
-#: archive.c builtin/blame.c builtin/commit-tree.c builtin/config.c
-#: builtin/fast-export.c builtin/gc.c builtin/grep.c builtin/hash-object.c
-#: builtin/ls-files.c builtin/notes.c builtin/read-tree.c parse-options.h
 msgid "file"
 msgstr "comhad"
 
-#: archive.c
 msgid "add untracked file to archive"
 msgstr "cuir comhad neamhrianaithe leis an gcartlann"
 
-#: archive.c
 msgid "path:content"
-msgstr "bealach:ábhar"
+msgstr "cosán:ábhar"
 
-#: archive.c builtin/archive.c
 msgid "write the archive to this file"
 msgstr "scríobh an cartlann chuig an gcomhad seo"
 
-#: archive.c
 msgid "read .gitattributes in working directory"
 msgstr "léite.gitattributs san eolaire oibre"
 
-#: archive.c
 msgid "report archived files on stderr"
 msgstr "tuairisciú comhaid cartlainne ar stderr"
 
-#: archive.c builtin/clone.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c
 msgid "time"
 msgstr "am"
 
-#: archive.c
 msgid "set modification time of archive entries"
 msgstr "socraigh am modhnaithe iontrálacha cartlainne"
 
-#: archive.c
 msgid "set compression level"
-msgstr "leibhéal comhbhrú a shocrú"
+msgstr "socraigh leibhéal comhbhrúite"
 
-#: archive.c
 msgid "list supported archive formats"
 msgstr "liosta formáidí cartlainne tacaíochta"
 
-#: archive.c builtin/archive.c builtin/clone.c builtin/submodule--helper.c
 msgid "repo"
 msgstr "stóras"
 
-#: archive.c builtin/archive.c
 msgid "retrieve the archive from remote repository <repo>"
 msgstr "aisghabháil an cartlann ó stór iargúlta <repo>"
 
-#: archive.c builtin/archive.c builtin/difftool.c builtin/notes.c
 msgid "command"
 msgstr "ordú"
 
-#: archive.c builtin/archive.c
 msgid "path to the remote git-upload-archive command"
 msgstr "cosán chuig an ordú iargúlta git-upload-archive"
 
-#: archive.c
 msgid "Unexpected option --remote"
 msgstr "Rogha gan choinne --remote"
 
-#: archive.c builtin/add.c builtin/checkout.c builtin/clone.c builtin/commit.c
-#: builtin/fast-export.c builtin/index-pack.c builtin/log.c builtin/reset.c
-#: builtin/rm.c builtin/stash.c builtin/worktree.c fetch-pack.c http-fetch.c
-#: revision.c
 #, c-format
 msgid "the option '%s' requires '%s'"
 msgstr "tá %s ag teastáil don rogha '%s'"
 
-#: archive.c
 msgid "Unexpected option --output"
 msgstr "Rogha gan choinne --output"
 
-#: archive.c t/unit-tests/unit-test.c
 #, c-format
 msgid "extra command line parameter '%s'"
 msgstr "paraiméadar líne ordaithe breise '%s'"
 
-#: archive.c
 #, c-format
 msgid "Unknown archive format '%s'"
 msgstr "Formáid cartlainne anaithnid '%s'"
 
-#: archive.c
 #, c-format
 msgid "Argument not supported for format '%s': -%d"
 msgstr "Argóint nach dtacaítear le haghaidh formáid '%s': -%d"
 
-#: attr.c
 #, c-format
 msgid "%.*s is not a valid attribute name"
 msgstr "%.*s ní ainm tréith bailí é"
 
-#: attr.c
 msgid "unable to add additional attribute"
-msgstr "in ann tréith bhreise a chur leis"
+msgstr "ní féidir tréith bhreise a chur leis"
 
-#: attr.c
 #, c-format
 msgid "ignoring overly long attributes line %d"
 msgstr "neamhaird a dhéanamh ar líne tréithe ró-fhada %d"
 
-#: attr.c
 #, c-format
 msgid "%s not allowed: %s:%d"
 msgstr "%s ní cheadaítear %s:%d"
 
-#: attr.c
 msgid ""
 "Negative patterns are ignored in git attributes\n"
 "Use '\\!' for literal leading exclamation."
@@ -1883,56 +1542,44 @@
 "Déantar neamhaird ar phatrúin dhiúltacha i d\n"
 "Úsáid '\\!' le haghaidh brú ceannródaíoch litriúil."
 
-#: attr.c
 #, c-format
 msgid "cannot fstat gitattributes file '%s'"
 msgstr "ní féidir an comhad gitattributeanna '%s' fstat"
 
-#: attr.c
 #, c-format
 msgid "ignoring overly large gitattributes file '%s'"
 msgstr "neamhaird a dhéanamh ar chomhad gitattributs ró-mhór '%s'"
 
-#: attr.c
 #, c-format
 msgid "ignoring overly large gitattributes blob '%s'"
 msgstr "neamhaird a dhéanamh ar ghitattributs ró-mhór blob '%s'"
 
-#: attr.c
 msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo"
 msgstr "ní féidir --attr-source nó GIT_ATTR_SOURCE a úsáid gan repo"
 
-#: attr.c
 msgid "bad --attr-source or GIT_ATTR_SOURCE"
 msgstr "olc --attr-source nó GIT_ATTR_SOURCE"
 
-#: attr.c read-cache.c refs/packed-backend.c
 #, c-format
 msgid "unable to stat '%s'"
 msgstr "ní féidir '%s' a shástáil"
 
-#: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c
-#: builtin/pack-objects.c combine-diff.c object-file.c rerere.c
 #, c-format
 msgid "unable to read %s"
-msgstr "nach féidir %s a léamh"
+msgstr "ní féidir %s a léamh"
 
-#: bisect.c
 #, c-format
 msgid "Badly quoted content in file '%s': %s"
 msgstr "Ábhar a luaitear go dona sa chomhad '%s': %s"
 
-#: bisect.c
 #, c-format
 msgid "We cannot bisect more!\n"
 msgstr "Ní féidir linn níos mó a dhícheangal!\n"
 
-#: bisect.c
 #, c-format
 msgid "Not a valid commit name %s"
 msgstr "Ní ainm tiomanta bailí %s"
 
-#: bisect.c
 #, c-format
 msgid ""
 "The merge base %s is bad.\n"
@@ -1941,7 +1588,6 @@
 "Tá an bonn cumaisc %s go dona.\n"
 "Ciallaíonn sé seo go bhfuil an fabht socraithe idir %s agus [%s].\n"
 
-#: bisect.c
 #, c-format
 msgid ""
 "The merge base %s is new.\n"
@@ -1950,7 +1596,6 @@
 "Tá an bonn cumaisc %s nua.\n"
 "Tá athrú tagtha ar an maoin idir %s agus [%s].\n"
 
-#: bisect.c
 #, c-format
 msgid ""
 "The merge base %s is %s.\n"
@@ -1959,7 +1604,6 @@
 "Is é an bonn cumaisc %s ná %s.\n"
 "Ciallaíonn sé seo go bhfuil an chéad thiomantas '%s' idir %s agus [%s].\n"
 
-#: bisect.c
 #, c-format
 msgid ""
 "Some %s revs are not ancestors of the %s rev.\n"
@@ -1970,7 +1614,6 @@
 "Ní féidir le git bisect oibriú i gceart sa chás seo.\n"
 "B'fhéidir gur mheas tú %s agus %s revs?\n"
 
-#: bisect.c
 #, c-format
 msgid ""
 "the merge base between %s and [%s] must be skipped.\n"
@@ -1982,41 +1625,33 @@
 "%s agus %s.\n"
 "Leanaimid orainn ar aon nós."
 
-#: bisect.c
 #, c-format
 msgid "Bisecting: a merge base must be tested\n"
 msgstr "Déroinnt: ní mór bonn cumaisc a thástáil\n"
 
-#: bisect.c
 #, c-format
 msgid "a %s revision is needed"
 msgstr "tá athbhreithniú %s ag teastáil"
 
-#: bisect.c
 #, c-format
 msgid "could not create file '%s'"
 msgstr "ní fhéadfaí comhad '%s' a chruthú"
 
-#: bisect.c builtin/notes.c
 #, c-format
 msgid "unable to start 'show' for object '%s'"
 msgstr "ní féidir 'show' a thosú le haghaidh réad '%s'"
 
-#: bisect.c builtin/merge.c
 #, c-format
 msgid "could not read file '%s'"
 msgstr "ní raibh in ann comhad '%s' a léamh"
 
-#: bisect.c
 msgid "reading bisect refs failed"
 msgstr "theip ar athbhreithnithe bisect a léamh"
 
-#: bisect.c
 #, c-format
 msgid "%s was both %s and %s\n"
 msgstr "Bhí %s %s agus %s araon\n"
 
-#: bisect.c
 #, c-format
 msgid ""
 "No testable commit found.\n"
@@ -2025,7 +1660,6 @@
 "Níor aimsíodh aon tiomantas intástála.\n"
 "B'fhéidir gur thosaigh tú le droch-argóintí cosáin?\n"
 
-#: bisect.c
 #, c-format
 msgid "(roughly %d step)"
 msgid_plural "(roughly %d steps)"
@@ -2036,7 +1670,6 @@
 #. TRANSLATORS: the last %s will be replaced with "(roughly %d
 #. steps)" translation.
 #.
-#: bisect.c
 #, 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"
@@ -2048,40 +1681,31 @@
 "Ag roinnt ina dhá leath: %d athbhreithniú fágtha le tástáil tar éis an %s "
 "seo\n"
 
-#: blame.c
 msgid "--contents and --reverse do not blend well."
 msgstr "Ní chumasc --contents agus --reverse go maith."
 
-#: blame.c
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr ""
 "Éilíonn --reverse agus --first-parent le chéile an tiomantas sonraithe is "
 "déanaí"
 
-#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c
-#: remote.c sequencer.c submodule.c
 msgid "revision walk setup failed"
 msgstr "theip ar socrú siúlóid ath"
 
-#: blame.c
 msgid ""
 "--reverse --first-parent together require range along first-parent chain"
 msgstr ""
 "--reverse --first-parent le chéile, teastaíonn raon feadh an tslabhra first-"
 "parent"
 
-#: blame.c
 #, c-format
 msgid "no such path %s in %s"
 msgstr "níl aon chosán den sórt sin %s i %s"
 
-#: blame.c
 #, c-format
 msgid "cannot read blob %s for path %s"
 msgstr "ní féidir le blob %s a léamh le haghaidh cosán %s"
 
-#: branch.c
 msgid ""
 "cannot inherit upstream tracking configuration of multiple refs when "
 "rebasing is requested"
@@ -2089,31 +1713,25 @@
 "ní féidir cumraíocht rianaithe suas srutha iolracha a oidhreacht nuair a "
 "iarrtar athbhunú"
 
-#: branch.c
 #, c-format
 msgid "not setting branch '%s' as its own upstream"
 msgstr "gan brainse '%s' a shocrú mar a thuas an sruth féin"
 
-#: branch.c
 #, c-format
 msgid "branch '%s' set up to track '%s' by rebasing."
 msgstr "bunaíodh brainse '%s' chun '%s' a rianú trí athbhunú."
 
-#: branch.c
 #, c-format
 msgid "branch '%s' set up to track '%s'."
 msgstr "bunaíodh brainse '%s' chun '%s' a rianú."
 
-#: branch.c
 #, c-format
 msgid "branch '%s' set up to track:"
 msgstr "bunaíodh brainse '%s' chun rianú:"
 
-#: branch.c
 msgid "unable to write upstream branch configuration"
-msgstr "in ann cumraíocht brainse suas srutha a scríobh"
+msgstr "ní féidir cumraíocht brainse suas an sruth a scríobh"
 
-#: branch.c
 msgid ""
 "\n"
 "After fixing the error cause you may try to fix up\n"
@@ -2123,33 +1741,31 @@
 "Tar éis an chúis earráide a shocrú féadfaidh tú iarracht a dhéanamh socrú\n"
 "an fhaisnéis cianrianaithe trí ghairm a dhéanamh ar:"
 
-#: branch.c
 #, c-format
 msgid "asked to inherit tracking from '%s', but no remote is set"
 msgstr "iarradh ar rianú oidhreachta ó '%s', ach níl aon iargúlta socraithe"
 
-#: branch.c
 #, c-format
 msgid "asked to inherit tracking from '%s', but no merge configuration is set"
 msgstr ""
 "iarrtar ar rianú oidhreachta ó '%s', ach níl aon chumraíocht cumaisc "
 "socraithe"
 
-#: branch.c
 #, c-format
 msgid "not tracking: ambiguous information for ref '%s'"
 msgstr "gan rianú: faisnéis dhébhríoch le haghaidh tagairt '%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
 #. around.
 #.
-#: branch.c object-name.c
 #, c-format
 msgid "  %s\n"
 msgstr "  %s\n"
@@ -2157,7 +1773,6 @@
 #. TRANSLATORS: The second argument is a \n-delimited list of
 #. duplicate refspecs, composed above.
 #.
-#: branch.c
 #, c-format
 msgid ""
 "There are multiple remotes whose fetch refspecs map to the remote\n"
@@ -2179,39 +1794,32 @@
 "faigheann ciananna éagsúla léarscáil speisiúcháin go difriúil\n"
 "spaisí ainmneacha a rianú."
 
-#: branch.c
 #, c-format
 msgid "'%s' is not a valid branch name"
 msgstr "Ní ainm brainse bailí é '%s'"
 
-#: branch.c builtin/branch.c
 msgid "See `man git check-ref-format`"
 msgstr "Féach `man git check-ref-format`"
 
-#: branch.c
 #, c-format
 msgid "a branch named '%s' already exists"
 msgstr "tá brainse darb ainm '%s' ann cheana"
 
-#: branch.c
 #, c-format
 msgid "cannot force update the branch '%s' used by worktree at '%s'"
 msgstr ""
 "ní féidir an brainse '%s' a úsáideann crann oibre a nuashonrú a chur i "
 "bhfeidhm ag '%s'"
 
-#: branch.c
 #, c-format
 msgid "cannot set up tracking information; starting point '%s' is not a branch"
 msgstr ""
 "ní féidir faisnéis rianaithe a chur ar bun; ní brainse é pointe tosaigh '%s'"
 
-#: branch.c
 #, c-format
 msgid "the requested upstream branch '%s' does not exist"
 msgstr "níl an brainse suas srutha iarrtha '%s' ann"
 
-#: branch.c
 msgid ""
 "\n"
 "If you are planning on basing your work on an upstream\n"
@@ -2231,27 +1839,22 @@
 "rianóidh sé a mhacasamhail iargúlta, b'fhéidir gur mhaith leat a úsáid\n"
 "“git push -u” chun an cumraíocht suas sruth a shocrú agus tú ag brú."
 
-#: branch.c builtin/replace.c
 #, c-format
 msgid "not a valid object name: '%s'"
 msgstr "ní ainm réad bailí: '%s'"
 
-#: branch.c
 #, c-format
 msgid "ambiguous object name: '%s'"
 msgstr "ainm réad débhríoch: '%s'"
 
-#: branch.c
 #, c-format
 msgid "not a valid branch point: '%s'"
 msgstr "ní pointe brainse bailí: '%s'"
 
-#: branch.c
 #, c-format
 msgid "submodule '%s': unable to find submodule"
 msgstr "fo-mhodúl '%s': in ann fo-mhodúl a aimsiú"
 
-#: branch.c
 #, c-format
 msgid ""
 "You may try updating the submodules using 'git checkout --no-recurse-"
@@ -2260,135 +1863,102 @@
 "Is féidir leat triail a bhaint as na fo-mhodúil a nuashonrú ag baint úsáide "
 "as 'git checkout --no-recurse-submodules %s && git submodule update --init'"
 
-#: branch.c
 #, c-format
 msgid "submodule '%s': cannot create branch '%s'"
 msgstr "fo-mhodúl '%s': ní féidir brainse '%s' a chruthú"
 
-#: branch.c
 #, c-format
 msgid "'%s' is already used by worktree at '%s'"
 msgstr "Úsáidtear '%s' cheana féin ag an gcrann oibre ag '%s'"
 
-#: builtin/add.c
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<options>] [--]<pathspec>..."
 
-#: builtin/add.c
 #, c-format
 msgid "cannot chmod %cx '%s'"
 msgstr "ní féidir chmod %cx '%s'"
 
-#: builtin/add.c
 msgid "Unstaged changes after refreshing the index:"
 msgstr "Athruithe gan stáitse tar éis an t-innéacs a athnuachan:"
 
-#: builtin/add.c
 msgid "could not read the index"
 msgstr "ní raibh in ann an t-innéacs a léamh"
 
-#: builtin/add.c
 msgid "editing patch failed"
 msgstr "theip ar paiste eagarthóire"
 
-#: builtin/add.c read-cache.c
 #, c-format
 msgid "could not stat '%s'"
 msgstr "ní fhéadfaí '%s' a stát"
 
-#: builtin/add.c
 msgid "empty patch. aborted"
 msgstr "paiste folam. a ghabhrú"
 
-#: builtin/add.c
 #, c-format
 msgid "could not apply '%s'"
 msgstr "ní fhéadfaí '%s' a chur i bhfeidhm"
 
-#: builtin/add.c
 msgid "The following paths are ignored by one of your .gitignore files:\n"
 msgstr ""
 "Déanann ceann de do chomhaid .gitignore neamhaird ar na cosáin seo a "
 "leanas:\n"
 
-#: builtin/add.c builtin/clean.c builtin/fetch.c builtin/mv.c
-#: builtin/prune-packed.c builtin/pull.c builtin/push.c builtin/remote.c
-#: builtin/rm.c builtin/send-pack.c
 msgid "dry run"
 msgstr "rith tirim"
 
-#: builtin/add.c builtin/check-ignore.c builtin/commit.c
-#: builtin/count-objects.c builtin/fsck.c builtin/log.c builtin/mv.c
-#: builtin/read-tree.c builtin/refs.c
 msgid "be verbose"
 msgstr "a bheith inearálta"
 
-#: builtin/add.c
 msgid "interactive picking"
 msgstr "piocadh idirghní"
 
-#: builtin/add.c builtin/checkout.c builtin/reset.c
 msgid "select hunks interactively"
 msgstr "roghnaigh hunks idirghníomhach"
 
-#: builtin/add.c
 msgid "edit current diff and apply"
 msgstr "athraigh an dif reatha agus cuir i bhfeidhm"
 
-#: builtin/add.c
 msgid "allow adding otherwise ignored files"
 msgstr "ligean comhaid a neamhaird a chur leis"
 
-#: builtin/add.c
 msgid "update tracked files"
 msgstr "comhaid rianaithe a nuashonrú"
 
-#: builtin/add.c
 msgid "renormalize EOL of tracked files (implies -u)"
 msgstr ""
 "athormalú a dhéanamh ar EOL na gcomhaid rianaithe (tugann le tuiscint -u)"
 
-#: builtin/add.c
 msgid "record only the fact that the path will be added later"
 msgstr "ní thaifeadadh ach an fíric go gcuirfear an cosán leis níos déanaí"
 
-#: builtin/add.c
 msgid "add changes from all tracked and untracked files"
 msgstr "cuir athruithe ó gach comhad rianaithe agus neamhrianaithe"
 
-#: builtin/add.c
 msgid "ignore paths removed in the working tree (same as --no-all)"
 msgstr ""
 "neamhaird a dhéanamh ar chosáin a bhaintear sa chrann oibre (mar an gcéanna "
 "le --no-all)"
 
-#: builtin/add.c
 msgid "don't add, only refresh the index"
 msgstr "ná cuir leis, ach an t-innéacs a athnuachan"
 
-#: builtin/add.c
 msgid "just skip files which cannot be added because of errors"
 msgstr ""
 "ní gá ach comhaid a scipeáil nach féidir a chur leis mar gheall ar earráidí"
 
-#: builtin/add.c
 msgid "check if - even missing - files are ignored in dry run"
 msgstr ""
 "seiceáil an ndéantar neamhaird ar chomhaid - fiú ar iarraidh - ar iarraidh"
 
-#: builtin/add.c builtin/mv.c builtin/rm.c
 msgid "allow updating entries outside of the sparse-checkout cone"
 msgstr "ligean iontrálacha a nuashonrú lasmuigh den chón seiceála neamh"
 
-#: builtin/add.c builtin/update-index.c
 msgid "override the executable bit of the listed files"
 msgstr "an giotán infhorghníomhaithe de na comhaid liostaithe a sháraigh"
 
-#: builtin/add.c
 msgid "warn when adding an embedded repository"
 msgstr "rabhadh agus stór leabaithe á chur leis"
 
-#: builtin/add.c
 #, c-format
 msgid ""
 "You've added another git repository inside your current repository.\n"
@@ -2419,154 +1989,120 @@
 "\n"
 "Féach “git help submodule” le haghaidh tuilleadh faisnéise."
 
-#: builtin/add.c
 #, c-format
 msgid "adding embedded git repository: %s"
 msgstr "stór git leabaithe a chur leis: %s"
 
-#: builtin/add.c
 msgid "Use -f if you really want to add them."
 msgstr "Úsáid -f más mian leat iad a chur leis i ndáiríre."
 
-#: builtin/add.c
 msgid "adding files failed"
 msgstr "theip ar chomhaid a chur leis"
 
-#: builtin/add.c
+#, c-format
+msgid "'%s' cannot be negative"
+msgstr "Caithfidh '%s' a bheith neamh-diúltach"
+
 #, c-format
 msgid "--chmod param '%s' must be either -x or +x"
 msgstr "Caithfidh --chmod param '%s' a bheith -x nó +x"
 
-#: builtin/add.c builtin/checkout.c builtin/commit.c builtin/reset.c
-#: builtin/rm.c builtin/stash.c
 #, c-format
 msgid "'%s' and pathspec arguments cannot be used together"
 msgstr "Ní féidir argóintí '%s' agus pathspec a úsáid le chéile"
 
-#: builtin/add.c
 #, c-format
 msgid "Nothing specified, nothing added.\n"
 msgstr "Níl aon rud sonraithe, ní chuir aon rud leis.\n"
 
-#: builtin/add.c
 msgid "Maybe you wanted to say 'git add .'?"
 msgstr "B'fhéidir gur mhaith leat a rá 'git add. '?"
 
-#: builtin/add.c builtin/check-ignore.c builtin/checkout.c builtin/clean.c
-#: builtin/commit.c builtin/diff-tree.c builtin/grep.c builtin/mv.c
-#: builtin/reset.c builtin/rm.c builtin/submodule--helper.c read-cache.c
-#: rerere.c submodule.c
 msgid "index file corrupt"
 msgstr "comhad innéacs truaillithe"
 
-#: builtin/add.c builtin/am.c builtin/checkout.c builtin/clone.c
-#: builtin/commit.c builtin/stash.c merge.c rerere.c
 msgid "unable to write new index file"
-msgstr "in ann comhad innéacs nua a scríobh"
+msgstr "ní féidir comhad innéacs nua a scríobh"
 
-#: builtin/am.c builtin/mailinfo.c mailinfo.c
 #, c-format
 msgid "bad action '%s' for '%s'"
 msgstr "droch-ghníomh '%s' le haghaidh '%s'"
 
-#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c builtin/revert.c config.c diff-merges.c gpg-interface.c
-#: ls-refs.c parallel-checkout.c sequencer.c setup.c
 #, c-format
 msgid "invalid value for '%s': '%s'"
 msgstr "luach neamhbhailí do '%s': '%s'"
 
-#: builtin/am.c builtin/commit.c builtin/merge.c sequencer.c
 #, c-format
 msgid "could not read '%s'"
 msgstr "ní raibh in ann '%s' a léamh"
 
-#: builtin/am.c
 msgid "could not parse author script"
 msgstr "ní raibh sé in ann script údair a pharsáil"
 
-#: builtin/am.c builtin/replace.c commit.c sequencer.c
 #, c-format
 msgid "could not parse %s"
 msgstr "ní fhéadfaí %s a pháirseáil"
 
-#: builtin/am.c
 #, c-format
 msgid "'%s' was deleted by the applypatch-msg hook"
 msgstr "Scriosadh '%s' ag an crúca applypatch-msg"
 
-#: builtin/am.c
 #, c-format
 msgid "Malformed input line: '%s'."
 msgstr "Líne ionchuir mífhoirmithe: '%s'."
 
-#: builtin/am.c
 #, c-format
 msgid "Failed to copy notes from '%s' to '%s'"
 msgstr "Theip ar nótaí a chóipeáil ó '%s' go '%s'"
 
-#: builtin/am.c
 msgid "fseek failed"
 msgstr "theip ar fseek"
 
-#: builtin/am.c builtin/rebase.c sequencer.c wrapper.c
 #, c-format
 msgid "could not open '%s' for reading"
 msgstr "ní fhéadfaí '%s' a oscailt le haghaidh léamh"
 
-#: builtin/am.c builtin/rebase.c editor.c sequencer.c wrapper.c
 #, c-format
 msgid "could not open '%s' for writing"
 msgstr "ní féidir '%s' a oscailt le haghaidh scríbhneoireachta"
 
-#: builtin/am.c
 #, c-format
 msgid "could not parse patch '%s'"
 msgstr "ní raibh sé in ann paiste '%s' a pháirseáil"
 
-#: builtin/am.c
 msgid "Only one StGIT patch series can be applied at once"
 msgstr ""
 "Ní féidir ach sraith paiste STGit amháin a chur i bhfeidhm ag an am céanna"
 
-#: builtin/am.c
 msgid "invalid timestamp"
 msgstr "stampa ama neamhbhailí"
 
-#: builtin/am.c
 msgid "invalid Date line"
 msgstr "líne dáta neamhbhailí"
 
-#: builtin/am.c
 msgid "invalid timezone offset"
 msgstr "fhritháireamh crios ama neamh"
 
-#: builtin/am.c
 msgid "Patch format detection failed."
 msgstr "Theip ar bhrath formáid paiste."
 
-#: builtin/am.c builtin/clone.c
 #, c-format
 msgid "failed to create directory '%s'"
 msgstr "theip ar eolaire '%s' a chruthú"
 
-#: builtin/am.c
 msgid "Failed to split patches."
 msgstr "Theip ar phaistí a roinnt."
 
-#: builtin/am.c
 #, c-format
 msgid "When you have resolved this problem, run \"%s --continue\".\n"
 msgstr ""
 "Nuair a bheidh an fhadhb seo réitithe agat, reáchtáil “%s --continue”.\n"
 
-#: builtin/am.c
 #, c-format
 msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
 msgstr ""
 "Más fearr leat an paiste seo a scipeáil, reáchtáil “%s --skip” ina ionad.\n"
 
-#: builtin/am.c
 #, c-format
 msgid ""
 "To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
@@ -2574,45 +2110,37 @@
 "Chun an paiste folamh a thaifeadadh mar thiomantas folamh, reáchtáil “%s --"
 "allow-empty”.\n"
 
-#: builtin/am.c
 #, c-format
 msgid "To restore the original branch and stop patching, run \"%s --abort\"."
 msgstr ""
 "Chun an brainse bunaidh a chur ar ais agus stopadh le patáil, reáchtáil “%s "
 "--abort”."
 
-#: builtin/am.c
 msgid "Patch sent with format=flowed; space at the end of lines might be lost."
 msgstr ""
 "Seoladh paiste le formáid = sreabhadh; d'fhéadfaí spás ag deireadh na línte "
 "a chailleadh."
 
-#: builtin/am.c
 #, c-format
 msgid "missing author line in commit %s"
 msgstr "líne údair ar iarraidh i dtiomantas %s"
 
-#: builtin/am.c
 #, c-format
 msgid "invalid ident line: %.*s"
 msgstr "líne aitheantais neamhbhailí: %.*s"
 
-#: builtin/am.c builtin/checkout.c builtin/clone.c commit-graph.c
 #, c-format
 msgid "unable to parse commit %s"
-msgstr "nach féidir le tiomantas %s a pharsáil"
+msgstr "ní féidir an tiomnú %s a pharsáil"
 
-#: builtin/am.c
 msgid "Repository lacks necessary blobs to fall back on 3-way merge."
 msgstr ""
 "Níl na blobanna riachtanacha ag an stór chun titim siar ar chumasc trí "
 "bhealach."
 
-#: builtin/am.c
 msgid "Using index info to reconstruct a base tree..."
 msgstr "Eolas innéacs a úsáid chun bonn crann a athchóiriú..."
 
-#: builtin/am.c
 msgid ""
 "Did you hand edit your patch?\n"
 "It does not apply to blobs recorded in its index."
@@ -2620,32 +2148,25 @@
 "Ar chuir tú do phaiste in eagar de láimh?\n"
 "Ní bhaineann sé le blobs a taifeadtar ina innéacs."
 
-#: builtin/am.c
 msgid "Falling back to patching base and 3-way merge..."
 msgstr "Ag titim ar ais go bonn paiste agus cumasc trí bhealach..."
 
-#: builtin/am.c
 msgid "Failed to merge in the changes."
 msgstr "Theip ar na hathruithe a chumasc."
 
-#: builtin/am.c builtin/merge.c sequencer.c
 msgid "git write-tree failed to write a tree"
-msgstr "theip ar git write-tree crann a scríobh"
+msgstr "git write-tree theip ar chrann a scríobh"
 
-#: builtin/am.c
 msgid "applying to an empty history"
 msgstr "iarratas a dhéanamh ar stair folamh"
 
-#: builtin/am.c builtin/commit.c builtin/merge.c builtin/replay.c sequencer.c
 msgid "failed to write commit object"
 msgstr "theip ar réad tiomanta a scríobh"
 
-#: builtin/am.c
 #, c-format
 msgid "cannot resume: %s does not exist."
 msgstr "ní féidir atosú: níl %s ann."
 
-#: builtin/am.c
 msgid "Commit Body is:"
 msgstr "Is é an Comhlacht Tiomanta:"
 
@@ -2653,59 +2174,47 @@
 #. in your translation. The program will only accept English
 #. input at this point.
 #.
-#: builtin/am.c
 #, c-format
 msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "
 msgstr ""
 "Cuir i bhfeidhm?[y]es/[n]o/[e]dit/[v]iew patch/[a]glacadh le gach rud: "
 
-#: builtin/am.c builtin/commit.c
 msgid "unable to write index file"
-msgstr "in ann comhad innéacs a scríobh"
+msgstr "ní féidir comhad innéacs a scríobh"
 
-#: builtin/am.c
 #, c-format
 msgid "Dirty index: cannot apply patches (dirty: %s)"
 msgstr "Innéacs salach: ní féidir paistí a chur i bhfeidhm (salach: %s)"
 
-#: builtin/am.c
 #, c-format
 msgid "Skipping: %.*s"
 msgstr "Scipeáil: %.*s"
 
-#: builtin/am.c
 #, c-format
 msgid "Creating an empty commit: %.*s"
 msgstr "Tiomantas folamh a chruthú: %.*s"
 
-#: builtin/am.c
 msgid "Patch is empty."
 msgstr "Tá paiste folamh."
 
-#: builtin/am.c
 #, c-format
 msgid "Applying: %.*s"
 msgstr "Iarratas a dhéanamh: %.*s"
 
-#: builtin/am.c
 msgid "No changes -- Patch already applied."
 msgstr "Gan aon athruithe - paiste curtha i bhfeidhm cheana féin."
 
-#: builtin/am.c
 #, c-format
 msgid "Patch failed at %s %.*s"
 msgstr "Theip ar phaiste ag %s%.*s"
 
-#: builtin/am.c
 msgid "Use 'git am --show-current-patch=diff' to see the failed patch"
 msgstr ""
 "Úsáid 'git am --show-current-patch=diff' chun an paiste theip a fheiceáil"
 
-#: builtin/am.c
 msgid "No changes - recorded it as an empty commit."
 msgstr "Gan aon athruithe - taifeadadh é mar thiomantas folamh."
 
-#: builtin/am.c
 msgid ""
 "No changes - did you forget to use 'git add'?\n"
 "If there is nothing left to stage, chances are that something else\n"
@@ -2717,7 +2226,6 @@
 "tugadh na hathruithe céanna isteach cheana féin; b'fhéidir gur mhaith leat "
 "an paiste seo a scipeáil."
 
-#: builtin/am.c
 msgid ""
 "You still have unmerged paths in your index.\n"
 "You should 'git add' each file with resolved conflicts to mark them as "
@@ -2730,16 +2238,13 @@
 "D'fhéadfá `git rm` a reáchtáil ar chomhad chun glacadh le “scriosta ag siad” "
 "dó."
 
-#: builtin/am.c builtin/reset.c
 #, c-format
 msgid "Could not parse object '%s'."
 msgstr "Ní fhéadfaí réad '%s' a pháirseáil."
 
-#: builtin/am.c
 msgid "failed to clean index"
 msgstr "theip ar innéacs a ghlanadh"
 
-#: builtin/am.c
 msgid ""
 "You seem to have moved HEAD since the last 'am' failure.\n"
 "Not rewinding to ORIG_HEAD"
@@ -2747,158 +2252,115 @@
 "Is cosúil gur bhogadh tú HEAD ón teip 'am' deireanach.\n"
 "Gan athfhillte chuig ORIG_HEAD"
 
-#: builtin/am.c builtin/bisect.c builtin/tag.c worktree.c
 #, c-format
 msgid "failed to read '%s'"
 msgstr "theip ar '%s' a léamh"
 
-#: builtin/am.c
 msgid "git am [<options>] [(<mbox> | <Maildir>)...]"
 msgstr "git am [<options>] [(<mbox> | <Maildir>)...]"
 
-#: builtin/am.c
 msgid "git am [<options>] (--continue | --skip | --abort)"
 msgstr "git am [<options>] (--continue | --skip | --abort)"
 
-#: builtin/am.c
 msgid "run interactively"
 msgstr "rith idirghníomhach"
 
-#: builtin/am.c
 msgid "bypass pre-applypatch and applypatch-msg hooks"
 msgstr "seachbhóthar crúcaí réamh-applypatch agus applypatch-msg"
 
-#: builtin/am.c builtin/cat-file.c
 msgid "historical option -- no-op"
 msgstr "rogha stairiúil  -- no-op"
 
-#: builtin/am.c
 msgid "allow fall back on 3way merging if needed"
 msgstr "ligean titim siar ar chumasc 3bhealach más gá"
 
-#: builtin/am.c builtin/init-db.c builtin/prune-packed.c builtin/repack.c
-#: builtin/stash.c
 msgid "be quiet"
 msgstr "a bheith ciúin"
 
-#: builtin/am.c
 msgid "add a Signed-off-by trailer to the commit message"
 msgstr "cuir leantóir sínithe amach leis an teachtaireacht tiomanta"
 
-#: builtin/am.c
 msgid "recode into utf8 (default)"
 msgstr "athchóiriú isteach i utf8 (réamhshocraithe)"
 
-#: builtin/am.c
 msgid "pass -k flag to git-mailinfo"
 msgstr "pas bratach -k chuig git-mailinfo"
 
-#: builtin/am.c
 msgid "pass -b flag to git-mailinfo"
 msgstr "pas bratach -b chuig git-mailinfo"
 
-#: builtin/am.c
 msgid "pass -m flag to git-mailinfo"
 msgstr "pas bratach -m chuig git-mailinfo"
 
-#: builtin/am.c
 msgid "pass --keep-cr flag to git-mailsplit for mbox format"
 msgstr "pas bratach --keep-cr go git-mailsplit le haghaidh formáid mbox"
 
-#: builtin/am.c
 msgid "strip everything before a scissors line"
 msgstr "gach rud a tharraingt roimh líne siosúr"
 
-#: builtin/am.c
 msgid "pass it through git-mailinfo"
 msgstr "cuir ar aghaidh trí git-mailinfo"
 
-#: builtin/am.c
 msgid "pass it through git-apply"
 msgstr "cuir isteach é trí git-apply"
 
-#: builtin/am.c builtin/commit.c builtin/fmt-merge-msg.c builtin/grep.c
-#: builtin/merge.c builtin/pull.c builtin/rebase.c builtin/repack.c
-#: builtin/show-branch.c builtin/show-ref.c builtin/tag.c parse-options.h
 msgid "n"
 msgstr "n"
 
-#: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c
-#: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c
-#: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c
-#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c
 msgid "format"
 msgstr "formáid"
 
-#: builtin/am.c
 msgid "format the patch(es) are in"
 msgstr "formáid atá na paistea/na paiste iontu"
 
-#: builtin/am.c
 msgid "override error message when patch failure occurs"
 msgstr "teachtaireacht earráide a shárú nuair a tharlaíonn teip"
 
-#: builtin/am.c
 msgid "continue applying patches after resolving a conflict"
 msgstr "leanúint ar aghaidh ag cur paistí a chur i bhfeidhm tar"
 
-#: builtin/am.c
 msgid "synonyms for --continue"
 msgstr "comhchiallaigh do --continue"
 
-#: builtin/am.c
 msgid "skip the current patch"
 msgstr "scipeáil an paiste reatha"
 
-#: builtin/am.c
 msgid "restore the original branch and abort the patching operation"
 msgstr ""
 "an bhrainse bunaidh a chur ar ais agus cuir deireadh leis an oibríocht paiste"
 
-#: builtin/am.c
 msgid "abort the patching operation but keep HEAD where it is"
 msgstr ""
 "déan deireadh leis an oibríocht paisteála ach coinnigh CEAD san áit a bhfuil "
 "sé"
 
-#: builtin/am.c
 msgid "show the patch being applied"
 msgstr "taispeáin an paiste atá á chur i bhfeidhm"
 
-#: builtin/am.c
 msgid "try to apply current patch again"
 msgstr "déan iarracht paiste reatha a chur i bhfeidhm"
 
-#: builtin/am.c
 msgid "record the empty patch as an empty commit"
 msgstr "taifeadadh an paiste folamh mar thiomantas folamh"
 
-#: builtin/am.c
 msgid "lie about committer date"
 msgstr "bréag faoi dháta an choimisiúnaithe"
 
-#: builtin/am.c
 msgid "use current timestamp for author date"
 msgstr "bain úsáid as stampa ama reatha le haghaidh dáta an údair"
 
-#: builtin/am.c builtin/commit-tree.c builtin/commit.c builtin/merge.c
-#: builtin/pull.c builtin/rebase.c builtin/revert.c builtin/tag.c
 msgid "key-id"
 msgstr "id eochair"
 
-#: builtin/am.c builtin/rebase.c
 msgid "GPG-sign commits"
 msgstr "Tiomanta comhartha GPG-Comhartha"
 
-#: builtin/am.c
 msgid "how to handle empty patches"
 msgstr "conas paistí folamh a láimhseáil"
 
-#: builtin/am.c
 msgid "(internal use for git-rebase)"
 msgstr "(úsáid inmheánach le haghaidh git-rebase)"
 
-#: builtin/am.c
 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."
@@ -2906,16 +2368,13 @@
 "Tá an rogha -b/--binary neamh-op le fada an lá, agus\n"
 "bainfear é. Ná húsáid é níos mó le do thoil."
 
-#: builtin/am.c
 msgid "failed to read the index"
 msgstr "theip ar an t-innéacs a léamh"
 
-#: builtin/am.c
 #, c-format
 msgid "previous rebase directory %s still exists but mbox given."
 msgstr "eolaire rebase roimhe seo %s ann fós ach tugadh mbox."
 
-#: builtin/am.c
 #, c-format
 msgid ""
 "Stray %s directory found.\n"
@@ -2924,128 +2383,105 @@
 "Fuarthas eolaire %s stray.\n"
 "Úsáid “git am --abort” chun é a bhaint."
 
-#: builtin/am.c
 msgid "Resolve operation not in progress, we are not resuming."
 msgstr "Réiteach oibríocht nach bhfuil ar siúl, níl muid ag atosú."
 
-#: builtin/am.c
 msgid "interactive mode requires patches on the command line"
 msgstr "éilíonn modh idirghníomhach paistí ar an líne ordaithe"
 
-#: builtin/apply.c
 msgid "git apply [<options>] [<patch>...]"
-msgstr "git feidhm [<options>] [<patch>...]"
+msgstr "git apply [<options>] [<patch>...]"
 
-#: builtin/archive.c diagnose.c
 msgid "could not redirect output"
 msgstr "ní fhéadfaí aschur a atreorú"
 
-#: builtin/archive.c
 msgid "git archive: expected ACK/NAK, got a flush packet"
-msgstr "cartlann git: ag súil le ACK/NAK, fuair sé paicéad sruthán"
+msgstr "git archive: bhíothas ag súil le ACK/NAK, fuair paicéad flush"
 
-#: builtin/archive.c
 #, c-format
 msgid "git archive: NACK %s"
 msgstr "git archive: NACK %s"
 
-#: builtin/archive.c
 msgid "git archive: protocol error"
-msgstr "git cartlann: earráid prótacal"
+msgstr "git archive: earráid prótacal"
 
-#: builtin/archive.c
 msgid "git archive: expected a flush"
 msgstr "git archive: bhíothas ag súil le sruthlú"
 
-#: builtin/backfill.c
 msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]"
 msgstr "git backfill [--min-batch-size=<n>] [-- [no-] neart]"
 
-#: builtin/backfill.c
 msgid "problem loading sparse-checkout"
 msgstr "fadhb ag luchtú seiceáil neamhchoiti"
 
-#: builtin/backfill.c
 msgid "Minimum number of objects to request at a time"
 msgstr "Líon íosta rudaí le iarraidh ag an am"
 
-#: builtin/backfill.c
 msgid "Restrict the missing objects to the current sparse-checkout"
 msgstr "Cuir srian ar na rudaí atá in easnamh don tseiceáil neamhchoitianta"
 
-#: builtin/bisect.c
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 
-#: builtin/bisect.c
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "<rev>git bisect (maith|olc) [...]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (bad|new|<term-new>) [<rev>]"
 
-#: builtin/bisect.c
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (good|old|<term-old>) [<rev>...]"
+
 msgid "git bisect skip [(<rev>|<range>)...]"
 msgstr "git bisect skip [(<rev>|<range>)...]"
 
-#: builtin/bisect.c
 msgid "git bisect reset [<commit>]"
-msgstr "<commit>athshocrú git bisect []"
+msgstr "git bisect reset [<commit>]"
 
-#: builtin/bisect.c
 msgid "git bisect replay <logfile>"
-msgstr "athsheinm git bisect <logfile>"
+msgstr "git bisect replay <logfile>"
 
-#: builtin/bisect.c
 msgid "git bisect run <cmd> [<arg>...]"
-msgstr "git bisect a rith <cmd>[<arg>...]"
+msgstr "git bisect run <cmd> [<arg>...]"
 
-#: builtin/bisect.c
 #, c-format
 msgid "cannot open file '%s' in mode '%s'"
 msgstr "ní féidir comhad '%s' a oscailt sa mhodh '%s'"
 
-#: builtin/bisect.c
 #, c-format
 msgid "could not write to file '%s'"
 msgstr "ní fhéadfaí scríobh chuig comhad '%s'"
 
-#: builtin/bisect.c
 #, c-format
 msgid "cannot open file '%s' for reading"
 msgstr "ní féidir comhad '%s' a oscailt le haghaidh léamh"
 
-#: builtin/bisect.c
 #, c-format
 msgid "'%s' is not a valid term"
 msgstr "Ní téarma bailí é '%s'"
 
-#: builtin/bisect.c
 #, c-format
 msgid "can't use the builtin command '%s' as a term"
 msgstr "ní féidir an t-ordú bunaithe '%s' a úsáid mar théarma"
 
-#: builtin/bisect.c
 #, c-format
 msgid "can't change the meaning of the term '%s'"
 msgstr "ní féidir le brí an téarma '%s' a athrú"
 
-#: builtin/bisect.c
 msgid "please use two different terms"
 msgstr "bain úsáid as dhá théarma éagsúla"
 
-#: builtin/bisect.c
 #, c-format
 msgid "We are not bisecting.\n"
 msgstr "Nílimid ag déileáil.\n"
 
-#: builtin/bisect.c
 #, c-format
 msgid "'%s' is not a valid commit"
 msgstr "Ní gealltanas bailí é '%s'"
 
-#: builtin/bisect.c
 #, c-format
 msgid ""
 "could not check out original HEAD '%s'. Try 'git bisect reset <commit>'."
@@ -3053,27 +2489,22 @@
 "ní fhéadfaí an HEAD bunaidh '%s' a sheiceáil. <commit>Bain triail as 'git "
 "bisect reset '."
 
-#: builtin/bisect.c
 #, c-format
 msgid "Bad bisect_write argument: %s"
 msgstr "Droch-argóint bisect_write: %s"
 
-#: builtin/bisect.c
 #, c-format
 msgid "couldn't get the oid of the rev '%s'"
 msgstr "ní raibh in ann oid an rev '%s' a fháil"
 
-#: builtin/bisect.c
 #, c-format
 msgid "couldn't open the file '%s'"
 msgstr "ní raibh in ann an comhad '%s' a oscailt"
 
-#: builtin/bisect.c
 #, c-format
 msgid "Invalid command: you're currently in a %s/%s bisect"
 msgstr "Ordú neamhbhailí: tá tú i mbeagán %s/%s faoi láthair"
 
-#: builtin/bisect.c
 #, c-format
 msgid ""
 "You need to give me at least one %s and %s revision.\n"
@@ -3082,7 +2513,6 @@
 "Ní mór duit athbhreithniú %s agus %s amháin ar a laghad a thabhairt dom.\n"
 "Is féidir leat “git bisect %s” agus “git bisect %s” a úsáid chuige sin."
 
-#: builtin/bisect.c
 #, c-format
 msgid ""
 "You need to start by \"git bisect start\".\n"
@@ -3094,7 +2524,6 @@
 "dom.\n"
 "Is féidir leat “git bisect %s” agus “git bisect %s” a úsáid chuige sin."
 
-#: builtin/bisect.c
 #, c-format
 msgid "bisecting only with a %s commit"
 msgstr "ag déileáil ach amháin le tiomantas %s"
@@ -3103,15 +2532,12 @@
 #. translation. The program will only accept English input
 #. at this point.
 #.
-#: builtin/bisect.c
 msgid "Are you sure [Y/n]? "
 msgstr "An bhfuil tú cinnte [Y/n]? "
 
-#: builtin/bisect.c
 msgid "status: waiting for both good and bad commits\n"
 msgstr "stádas: ag fanacht le tiomáintí mhaith agus tiomáintí dona\n"
 
-#: 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"
@@ -3121,15 +2547,12 @@
 msgstr[2] ""
 "stádas: ag fanacht le droch-thiomantas, %d dea-thiomantas ar eolas\n"
 
-#: builtin/bisect.c
 msgid "status: waiting for good commit(s), bad commit known\n"
 msgstr "stádas: ag fanacht le tiomáintí maith, droch-tiomantas ar eolas\n"
 
-#: builtin/bisect.c
 msgid "no terms defined"
 msgstr "aon téarmaí sainmhínithe"
 
-#: builtin/bisect.c
 #, c-format
 msgid ""
 "Your current terms are %s for the old state\n"
@@ -3138,7 +2561,6 @@
 "Is iad na téarmaí reatha %s don seanstát\n"
 "agus %s don stát nua.\n"
 
-#: builtin/bisect.c
 #, c-format
 msgid ""
 "invalid argument %s for 'git bisect terms'.\n"
@@ -3148,45 +2570,36 @@
 "Is iad na roghanna tacaithe ná: --term-good|--term-old agus --term-bad|--"
 "term-new."
 
-#: builtin/bisect.c
 #, c-format
 msgid "could not open '%s' for appending"
 msgstr "ní fhéadfaí '%s' a oscailt le haghaidh cur isteach"
 
-#: builtin/bisect.c
 msgid "'' is not a valid term"
 msgstr "'' ní téarma bailí é"
 
-#: builtin/bisect.c
 #, c-format
 msgid "unrecognized option: '%s'"
 msgstr "rogha gan aithint: '%s'"
 
-#: builtin/bisect.c
 #, c-format
 msgid "'%s' does not appear to be a valid revision"
 msgstr "Ní cosúil gur athbhreithniú bailí é '%s'"
 
-#: builtin/bisect.c
 msgid "bad HEAD - I need a HEAD"
 msgstr "droch HEAD - Teastaíonn HEAD uaim"
 
-#: builtin/bisect.c
 #, c-format
 msgid "checking out '%s' failed. Try 'git bisect start <valid-branch>'."
 msgstr ""
 "theip ar '%s' a sheiceáil. <valid-branch>Bain triail as 'git bisect start '."
 
-#: builtin/bisect.c
 msgid "bad HEAD - strange symbolic ref"
 msgstr "bad HEAD - tagairt siombalach aisteach"
 
-#: builtin/bisect.c
 #, c-format
 msgid "invalid ref: '%s'"
 msgstr "tagairt neamhbhailí: '%s'"
 
-#: builtin/bisect.c
 msgid "You need to start by \"git bisect start\"\n"
 msgstr "Ní mór duit tosú ag “git bisect start”\n"
 
@@ -3194,270 +2607,207 @@
 #. translation. The program will only accept English input
 #. at this point.
 #.
-#: builtin/bisect.c
 msgid "Do you want me to do it for you [Y/n]? "
 msgstr "An dteastaíonn uait go ndéanfaidh mé é duit [Y/n]? "
 
-#: builtin/bisect.c
 msgid "Please call `--bisect-state` with at least one argument"
 msgstr "Glaoigh ar `--bisect-state` le do thoil le argóint amháin ar a laghad"
 
-#: builtin/bisect.c
 #, c-format
 msgid "'git bisect %s' can take only one argument."
 msgstr "Ní féidir le 'git bisect %s' ach argóint amháin a ghlacadh."
 
-#: builtin/bisect.c
 #, c-format
 msgid "Bad rev input: %s"
 msgstr "Droch-ionchur rev: %s"
 
-#: builtin/bisect.c
 #, c-format
 msgid "Bad rev input (not a commit): %s"
 msgstr "Droch-ionchur rev (ní tiomantas): %s"
 
-#: builtin/bisect.c
 msgid "We are not bisecting."
 msgstr "Nílimid ag déileáil."
 
-#: builtin/bisect.c
 #, c-format
 msgid "'%s'?? what are you talking about?"
 msgstr "'%s'?? cad atá tú ag caint faoi?"
 
-#: builtin/bisect.c
 #, c-format
 msgid "cannot read file '%s' for replaying"
 msgstr "ní féidir comhad '%s' a léamh le haghaidh athsheinm"
 
-#: builtin/bisect.c
 #, c-format
 msgid "running %s\n"
 msgstr "ag rith %s\n"
 
-#: builtin/bisect.c
 msgid "bisect run failed: no command provided."
 msgstr "theip ar rith bioctha: níl aon ordú curtha ar fáil."
 
-#: builtin/bisect.c
 #, c-format
 msgid "unable to verify %s on good revision"
-msgstr "nach féidir %s a fhíorú ar athbhreithniú maith"
+msgstr "ní féidir %s a fhíorú ar athbhreithniú maith"
 
-#: builtin/bisect.c
 #, c-format
 msgid "bogus exit code %d for good revision"
 msgstr "cód imeachta bréagach %d le haghaidh athbhreithniú maith"
 
-#: builtin/bisect.c
 #, c-format
 msgid "bisect run failed: exit code %d from %s is < 0 or >= 128"
 msgstr "< 0 or >Theip ar rith bioctha: is é an cód imeachta %d ó %s = 128"
 
-#: builtin/bisect.c
 #, c-format
 msgid "cannot open file '%s' for writing"
 msgstr "ní féidir comhad '%s' a oscailt le haghaidh scríobh"
 
-#: builtin/bisect.c
 msgid "bisect run cannot continue any more"
 msgstr "ní féidir le rith bisect leanúint ar aghaidh níos mó"
 
-#: builtin/bisect.c
 msgid "bisect run success"
 msgstr "rath reatha dhéagsúil"
 
-#: builtin/bisect.c
 msgid "bisect found first bad commit"
 msgstr "fuarthas bisect an chéad droch-thiomantas"
 
-#: builtin/bisect.c
 #, c-format
 msgid "bisect run failed: 'git bisect %s' exited with error code %d"
 msgstr "theip ar rith bisect: D'éirigh 'git bisect %s' le cód earráide %d"
 
-#: builtin/bisect.c
 #, c-format
 msgid "'%s' requires either no argument or a commit"
 msgstr "Ní éilíonn '%s' aon argóint ná tiomantas"
 
-#: builtin/bisect.c
 #, c-format
 msgid "'%s' requires 0 or 1 argument"
 msgstr "Éilíonn '%s' argóint 0 nó 1"
 
-#: builtin/bisect.c
 #, c-format
 msgid "'%s' requires 0 arguments"
 msgstr "Éilíonn '%s' 0 argóint"
 
-#: builtin/bisect.c
 msgid "no logfile given"
 msgstr "níl aon logfile tugtha"
 
-#: builtin/bisect.c
 #, c-format
 msgid "'%s' failed: no command provided."
 msgstr "Theip ar '%s': níl aon ordú curtha ar fáil."
 
-#: builtin/bisect.c
 msgid "need a command"
 msgstr "teastaíonn ordú"
 
-#: builtin/bisect.c builtin/cat-file.c
 #, c-format
 msgid "unknown command: '%s'"
 msgstr "ordú anaithnid: '%s'"
 
-#: builtin/blame.c
 msgid "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"
-msgstr "git an mille <options>án [<rev-opts>] [<rev>] [] [--] <file>"
+msgstr "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"
 
-#: builtin/blame.c
 msgid "git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>"
 msgstr "git annotate [<options>] [] [<rev-opts><rev>] [--] <file>"
 
-#: builtin/blame.c
 msgid "<rev-opts> are documented in git-rev-list(1)"
 msgstr "<rev-opts>iad doiciméadaithe i git-rev-list (1)"
 
-#: builtin/blame.c
 #, c-format
 msgid "expecting a color: %s"
 msgstr "ag súil le dath: %s"
 
-#: builtin/blame.c
 msgid "must end with a color"
 msgstr "caithfidh deireadh a chur le dath"
 
-#: builtin/blame.c
 #, c-format
 msgid "cannot find revision %s to ignore"
 msgstr "ní féidir athbhreithniú %s a fháil le neamhair"
 
-#: builtin/blame.c
 msgid "show blame entries as we find them, incrementally"
 msgstr "taispeáint iontrálacha milleán de réir mar a aimsímid iad, go chéile"
 
-#: builtin/blame.c
 msgid "do not show object names of boundary commits (Default: off)"
 msgstr ""
 "ná taispeáin ainmneacha réada na ngealltanais teorann (Réamhshocraithe: as)"
 
-#: builtin/blame.c
 msgid "do not treat root commits as boundaries (Default: off)"
 msgstr ""
 "ná déileáil le gealltanais fréimhe mar theorainneacha (Réamhshocraithe: as)"
 
-#: builtin/blame.c
 msgid "show work cost statistics"
 msgstr "taispeáin staitisticí costas oibre"
 
-#: builtin/blame.c builtin/checkout.c builtin/clone.c builtin/commit-graph.c
-#: builtin/fetch.c builtin/merge.c builtin/multi-pack-index.c builtin/pull.c
-#: builtin/push.c builtin/remote.c builtin/send-pack.c
 msgid "force progress reporting"
 msgstr "tuairisciú dul chun cinn"
 
-#: builtin/blame.c
 msgid "show output score for blame entries"
 msgstr "taispeáin scór aschuir d'iontrálacha mille"
 
-#: builtin/blame.c
 msgid "show original filename (Default: auto)"
 msgstr "taispeáin ainm comhaid bunaidh (Réamhshocraithe: auto)"
 
-#: builtin/blame.c
 msgid "show original linenumber (Default: off)"
 msgstr "taispeáin uimhir líne bunaidh (Réamhshocraithe: as)"
 
-#: builtin/blame.c
 msgid "show in a format designed for machine consumption"
 msgstr "taispeáint i bhformáid atá deartha le haghaidh tomhaltas meaisín"
 
-#: builtin/blame.c
 msgid "show porcelain format with per-line commit information"
 msgstr "formáid poircealláin a thaispeáint le faisnéis tiomanta"
 
-#: builtin/blame.c
 msgid "use the same output mode as git-annotate (Default: off)"
 msgstr ""
 "bain úsáid as an modh aschuir céanna le git-annotate (Réamhshocraithe: as)"
 
-#: builtin/blame.c
 msgid "show raw timestamp (Default: off)"
 msgstr "taispeáin ama amh (Réamhshocraithe: as)"
 
-#: builtin/blame.c
 msgid "show long commit SHA1 (Default: off)"
 msgstr "taispeáin tiomantas fada SHA1 (Réamhshocraithe: as)"
 
-#: builtin/blame.c
 msgid "suppress author name and timestamp (Default: off)"
 msgstr "ainm an údair agus stampa ama a chur faoi chois (Réamhshocraithe: as)"
 
-#: builtin/blame.c
 msgid "show author email instead of name (Default: off)"
 msgstr "taispeáin ríomhphost an údair in ionad ainm (Réamhshocraithe: as)"
 
-#: builtin/blame.c
 msgid "ignore whitespace differences"
 msgstr "neamhaird a dhéanamh ar dhifríochtaí spás b"
 
-#: builtin/blame.c builtin/clone.c builtin/log.c
 msgid "rev"
 msgstr "rev"
 
-#: builtin/blame.c
 msgid "ignore <rev> when blaming"
 msgstr "neamhaird a <rev>dhéanamh agus an milleán"
 
-#: builtin/blame.c
 msgid "ignore revisions from <file>"
 msgstr "neamhaird ar athbhreithnithe <file>"
 
-#: builtin/blame.c
 msgid "color redundant metadata from previous line differently"
 msgstr "meiteashonraí iomarcach dath ó líne roimhe seo ar bheal"
 
-#: builtin/blame.c
 msgid "color lines by age"
 msgstr "línte datha de réir aois"
 
-#: builtin/blame.c
 msgid "spend extra cycles to find better match"
 msgstr "timthriallta breise a chaitheamh chun meaitseáil níos fearr"
 
-#: builtin/blame.c
 msgid "use revisions from <file> instead of calling git-rev-list"
 msgstr "athbhreithnithe a úsáid as in <file>ionad glaoch ar git-rev-list"
 
-#: builtin/blame.c
 msgid "use <file>'s contents as the final image"
 msgstr "úsáid <file>ábhar mar an íomhá deiridh"
 
-#: builtin/blame.c
 msgid "score"
 msgstr "scór"
 
-#: builtin/blame.c
 msgid "find line copies within and across files"
 msgstr "faigh cóipeanna líne laistigh de chomhaid agus trasna"
 
-#: builtin/blame.c
 msgid "find line movements within and across files"
 msgstr "faigh gluaiseachtaí líne laistigh de chomhaid agus trasna"
 
-#: builtin/blame.c
 msgid "range"
 msgstr "raon"
 
-#: builtin/blame.c
 msgid "process only line range <start>,<end> or function :<funcname>"
 msgstr "ach raon líne, nó feidh <start>m a <end>phróiseáil: <funcname>"
 
-#: builtin/blame.c
 msgid "--progress can't be used with --incremental or porcelain formats"
 msgstr "Ní féidir --progress a úsáid le formáidí --incremental nó poircealláin"
 
@@ -3469,11 +2819,9 @@
 #. your language may need more or fewer display
 #. columns.
 #.
-#: builtin/blame.c
 msgid "4 years, 11 months ago"
 msgstr "4 bliana, 11 mhí ó shin"
 
-#: builtin/blame.c
 #, c-format
 msgid "file %s has only %lu line"
 msgid_plural "file %s has only %lu lines"
@@ -3481,15 +2829,12 @@
 msgstr[1] "comhad %s níl ach %lu línte"
 msgstr[2] "comhad %s níl ach %lu línte"
 
-#: builtin/blame.c
 msgid "Blaming lines"
 msgstr "An milleán ar línte"
 
-#: builtin/branch.c
 msgid "git branch [<options>] [-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>]"
@@ -3497,31 +2842,24 @@
 "git branch [<options>] [-f] [--recurse-submodules] <branch-name> [<start-"
 "point>]"
 
-#: builtin/branch.c
 msgid "git branch [<options>] [-l] [<pattern>...]"
 msgstr "git branch [<options>] [-l] [<pattern>...]"
 
-#: builtin/branch.c
 msgid "git branch [<options>] [-r] (-d | -D) <branch-name>..."
 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 [<options>] (-m | -M) [<old-branch>] <new-branch>"
 
-#: builtin/branch.c
 msgid "git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"
 msgstr "git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"
 
-#: builtin/branch.c
 msgid "git branch [<options>] [-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 [<options>] [-r | -a] [--format]"
 
-#: builtin/branch.c
 #, c-format
 msgid ""
 "deleting branch '%s' that has been merged to\n"
@@ -3530,50 +2868,41 @@
 "brainse '%s' a bhfuil cumasc orthu a scriosadh\n"
 " '%s', ach níor chumasc le HEAD go fóill"
 
-#: builtin/branch.c
 #, c-format
 msgid ""
 "not deleting branch '%s' that is not yet merged to\n"
 "         '%s', even though it is merged to HEAD"
 msgstr ""
 "gan brainse '%s' a scriosadh nach bhfuil cumasc fós leis\n"
-" '%s', cé go ndéantar é a chumasc le HEAD"
+"         '%s', cé go ndéantar é a chumasc le HEAD"
 
-#: builtin/branch.c
 #, c-format
 msgid "couldn't look up commit object for '%s'"
 msgstr "ní raibh in ann réad tiomanta a lorg suas le haghaidh '%s'"
 
-#: builtin/branch.c
 #, c-format
 msgid "the branch '%s' is not fully merged"
 msgstr "níl an brainse '%s' cumaisc go hiomlán"
 
-#: builtin/branch.c
 #, c-format
 msgid "If you are sure you want to delete it, run 'git branch -D %s'"
 msgstr ""
 "Má tá tú cinnte gur mhaith leat é a scriosadh, reáchtáil 'git branch -D %s'"
 
-#: builtin/branch.c
 msgid "update of config-file failed"
 msgstr "theip ar nuashonrú comhad config-file"
 
-#: builtin/branch.c
 msgid "cannot use -a with -d"
 msgstr "ní féidir -a a úsáid le -d"
 
-#: builtin/branch.c
 #, c-format
 msgid "cannot delete branch '%s' used by worktree at '%s'"
 msgstr "ní féidir brainse '%s' a úsáideann crann oibre ag '%s' a scriosadh"
 
-#: builtin/branch.c
 #, c-format
 msgid "remote-tracking branch '%s' not found"
 msgstr "níor aimsíodh brainse cianrianaithe '%s'"
 
-#: builtin/branch.c
 #, c-format
 msgid ""
 "branch '%s' not found.\n"
@@ -3582,96 +2911,76 @@
 "níor aimsíodh brainse '%s'.\n"
 "Ar ndearna tú dearmad ar --remote?"
 
-#: builtin/branch.c
 #, c-format
 msgid "branch '%s' not found"
 msgstr "níor aimsíodh brainse '%s'"
 
-#: builtin/branch.c
 #, c-format
 msgid "Deleted remote-tracking branch %s (was %s).\n"
 msgstr "Brainse cianrianaithe scriosta %s (bhí %s).\n"
 
-#: builtin/branch.c
 #, c-format
 msgid "Deleted branch %s (was %s).\n"
 msgstr "Brainse %s scriosta (%s ba é).\n"
 
-#: builtin/branch.c builtin/tag.c
 msgid "unable to parse format string"
-msgstr "in ann teaghrán formáide a pháirseáil"
+msgstr "ní féidir an teaghrán formáidithe a pharsáil"
 
-#: builtin/branch.c
 msgid "could not resolve HEAD"
 msgstr "ní fhéadfaí HEAD a réiteach"
 
-#: builtin/branch.c
 #, c-format
 msgid "HEAD (%s) points outside of refs/heads/"
 msgstr "Pointí HEAD (%s) lasmuigh de refs/heads/"
 
-#: builtin/branch.c
 #, c-format
 msgid "branch %s is being rebased at %s"
 msgstr "tá brainse %s á athbhunú ag %s"
 
-#: builtin/branch.c
 #, c-format
 msgid "branch %s is being bisected at %s"
 msgstr "tá brainse %s á dhíscaoileadh ag %s"
 
-#: builtin/branch.c
 #, c-format
 msgid "HEAD of working tree %s is not updated"
 msgstr "Níl CEANN an chrainn oibre %s nuashonraithe"
 
-#: builtin/branch.c
 #, c-format
 msgid "invalid branch name: '%s'"
 msgstr "ainm brainse neamhbhailí: '%s'"
 
-#: builtin/branch.c
 #, c-format
 msgid "no commit on branch '%s' yet"
 msgstr "níl aon gealltanas ar bhrainse '%s' go fóill"
 
-#: builtin/branch.c
 #, c-format
 msgid "no branch named '%s'"
 msgstr "níl aon bhrainse darb ainm '%s'"
 
-#: builtin/branch.c
 msgid "branch rename failed"
 msgstr "theip ar athainmniú brainse"
 
-#: builtin/branch.c
 msgid "branch copy failed"
 msgstr "theip ar chóip brainse"
 
-#: builtin/branch.c
 #, c-format
 msgid "created a copy of a misnamed branch '%s'"
 msgstr "chruthaigh cóip de bhrainse mí-ainmnithe '%s'"
 
-#: builtin/branch.c
 #, c-format
 msgid "renamed a misnamed branch '%s' away"
 msgstr "athainmnigh brainse mí-ainmnithe '%s' ar shiúl"
 
-#: builtin/branch.c
 #, c-format
 msgid "branch renamed to %s, but HEAD is not updated"
 msgstr "athainmníodh brainse go %s, ach níl HEAD nuashonraithe"
 
-#: builtin/branch.c
 msgid "branch is renamed, but update of config-file failed"
 msgstr "athainmnítear brainse, ach theip ar nuashonrú ar chomhad config-file"
 
-#: builtin/branch.c
 msgid "branch is copied, but update of config-file failed"
 msgstr "cóipeáiltear brainse, ach theip ar nuashonrú comhad config-file"
 
-#: builtin/branch.c
 #, c-format
 msgid ""
 "Please edit the description for the branch\n"
@@ -3682,152 +2991,114 @@
 " %s\n"
 "Déanfar línte a thosaíonn le '%s' a scriosadh.\n"
 
-#: builtin/branch.c
 msgid "Generic options"
 msgstr "Roghanna cineálacha"
 
-#: builtin/branch.c
 msgid "show hash and subject, give twice for upstream branch"
 msgstr "taispeáin hash agus ábhar, tabhair faoi dhó don bhrainse suas srutha"
 
-#: builtin/branch.c
 msgid "suppress informational messages"
 msgstr "teachtaireachtaí faisnéise a chur"
 
-#: builtin/branch.c builtin/checkout.c builtin/submodule--helper.c
 msgid "set branch tracking configuration"
-msgstr "cumraíocht rianaithe brainse a shoc"
+msgstr "socraigh cumraíocht rianaithe brainse"
 
-#: builtin/branch.c
 msgid "do not use"
 msgstr "ná húsáid"
 
-#: builtin/branch.c
 msgid "upstream"
 msgstr "suas sruth"
 
-#: builtin/branch.c
 msgid "change the upstream info"
 msgstr "athraigh an fhaisnéis suas sruth"
 
-#: builtin/branch.c
 msgid "unset the upstream info"
 msgstr "díshocraigh an fhaisnéis suas sruth"
 
-#: builtin/branch.c
 msgid "use colored output"
 msgstr "úsáid aschur daite"
 
-#: builtin/branch.c
 msgid "act on remote-tracking branches"
 msgstr "gníomhú ar bhrainsí cianrianaithe"
 
-#: builtin/branch.c
 msgid "print only branches that contain the commit"
 msgstr "ach brainsí a phriontáil ina bhfuil an tiomantas"
 
-#: builtin/branch.c
 msgid "print only branches that don't contain the commit"
 msgstr "ach brainsí a phriontáil nach bhfuil an tiomantas"
 
-#: builtin/branch.c
 msgid "Specific git-branch actions:"
 msgstr "Gníomhartha sonracha git-branch:"
 
-#: builtin/branch.c
 msgid "list both remote-tracking and local branches"
 msgstr "liostáil brainsí cianrianaithe agus áitiúla araon"
 
-#: builtin/branch.c
 msgid "delete fully merged branch"
 msgstr "scrios brainse lánchumaisc"
 
-#: builtin/branch.c
 msgid "delete branch (even if not merged)"
 msgstr "brainse a scriosadh (fiú mura bhfuil sé cumasaithe)"
 
-#: builtin/branch.c
 msgid "move/rename a branch and its reflog"
 msgstr "brainse a bhogadh/athainmniú agus a athainmniú"
 
-#: builtin/branch.c
 msgid "move/rename a branch, even if target exists"
 msgstr "brainse a bhogadh/athainmniú, fiú má tá sprioc ann"
 
-#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c
 msgid "do not output a newline after empty formatted refs"
 msgstr "ná aschur líne nua tar éis aifeanna formáidithe folamh"
 
-#: builtin/branch.c
 msgid "copy a branch and its reflog"
 msgstr "cóipeáil brainse agus a reflog"
 
-#: builtin/branch.c
 msgid "copy a branch, even if target exists"
 msgstr "cóipeáil brainse, fiú má tá sprioc ann"
 
-#: builtin/branch.c
 msgid "list branch names"
 msgstr "liosta ainmneacha brainse"
 
-#: builtin/branch.c
 msgid "show current branch name"
 msgstr "taispeáin ainm brainse reatha"
 
-#: builtin/branch.c builtin/submodule--helper.c
 msgid "create the branch's reflog"
 msgstr "athbhreithniú na brainse a chruthú"
 
-#: builtin/branch.c
 msgid "edit the description for the branch"
 msgstr "cuir an tuairisc don bhrainse a chur in eagar"
 
-#: builtin/branch.c
 msgid "force creation, move/rename, deletion"
 msgstr "cruthú fórsa, gluaise/athainmniú, scriosadh"
 
-#: builtin/branch.c
 msgid "print only branches that are merged"
 msgstr "ach brainsí a chumasc a phriontáil"
 
-#: builtin/branch.c
 msgid "print only branches that are not merged"
 msgstr "ach brainsí nach ndéantar cumasc a phriontáil"
 
-#: builtin/branch.c
 msgid "list branches in columns"
 msgstr "liostáil brainsí i gcolúin"
 
-#: builtin/branch.c builtin/for-each-ref.c builtin/notes.c builtin/tag.c
 msgid "object"
 msgstr "réad"
 
-#: builtin/branch.c
 msgid "print only branches of the object"
 msgstr "ach brainsí den réad a phriontáil"
 
-#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c
 msgid "sorting and filtering are case insensitive"
 msgstr "tá sórtáil agus scagadh neamh-íogair ó thaobh cásanna de"
 
-#: builtin/branch.c builtin/ls-files.c
 msgid "recurse through submodules"
 msgstr "athshlánú trí fho-mhodúil"
 
-#: builtin/branch.c builtin/for-each-ref.c builtin/ls-files.c builtin/ls-tree.c
-#: builtin/tag.c builtin/verify-tag.c
 msgid "format to use for the output"
 msgstr "formáid le húsáid don aschur"
 
-#: builtin/branch.c
 msgid "failed to resolve HEAD as a valid ref"
 msgstr "theip ar HEAD a réiteach mar thagartha bailí"
 
-#: builtin/branch.c builtin/clone.c
 msgid "HEAD not found below refs/heads!"
 msgstr "Ní fhaightear CEAD thíos na refs/heads!"
 
-#: builtin/branch.c
 msgid ""
 "branch with --recurse-submodules can only be used if "
 "submodule.propagateBranches is enabled"
@@ -3835,43 +3106,33 @@
 "ní féidir brainse le --recurse-submodules a úsáid ach amháin má tá "
 "submodule.propagateBranches cumasaithe"
 
-#: builtin/branch.c
 msgid "--recurse-submodules can only be used to create branches"
 msgstr "Ní féidir --recurse-submodules a úsáid ach chun brainsí a chruthú"
 
-#: builtin/branch.c
 msgid "branch name required"
 msgstr "ainm brainse ag teastáil"
 
-#: builtin/branch.c
 msgid "cannot give description to detached HEAD"
 msgstr "ní féidir cur síos a thabhairt ar HEAD scoite"
 
-#: builtin/branch.c
 msgid "cannot edit description of more than one branch"
 msgstr "ní féidir cur síos ar níos mó ná brainse amháin a chur in eagar"
 
-#: builtin/branch.c
 msgid "cannot copy the current branch while not on any"
 msgstr "ní féidir leis an mbrainse reatha a chóipeáil cé nach bhfuil ar aon"
 
-#: builtin/branch.c
 msgid "cannot rename the current branch while not on any"
 msgstr "ní féidir leis an mbrainse reatha a athainmniú cé nach bhfuil ar aon"
 
-#: builtin/branch.c
 msgid "too many branches for a copy operation"
 msgstr "an iomarca brainsí le haghaidh oibríocht cóipeála"
 
-#: builtin/branch.c
 msgid "too many arguments for a rename operation"
 msgstr "an iomarca argóintí maidir le hoibríocht athainmnithe"
 
-#: builtin/branch.c
 msgid "too many arguments to set new upstream"
 msgstr "an iomarca argóintí chun suas an sruth nua a shocrú"
 
-#: builtin/branch.c
 #, c-format
 msgid ""
 "could not set upstream of HEAD to %s when it does not point to any branch"
@@ -3879,32 +3140,26 @@
 "ní fhéadfaí suas sruth de HEAD a shocrú go %s nuair nach dtugann sé in iúl "
 "go dtí aon bhrainse"
 
-#: builtin/branch.c
 #, c-format
 msgid "no such branch '%s'"
 msgstr "níl brainse den sórt sin '%s'"
 
-#: builtin/branch.c
 #, c-format
 msgid "branch '%s' does not exist"
 msgstr "níl brainse '%s' ann"
 
-#: builtin/branch.c
 msgid "too many arguments to unset upstream"
 msgstr "an iomarca argóintí le díshocrú suas an sruth"
 
-#: builtin/branch.c
 msgid "could not unset upstream of HEAD when it does not point to any branch"
 msgstr ""
 "ní fhéadfaí a dhíshuiteáil suas an sruth den HEAD nuair nach dtugann sé in "
 "iúl d'aon bhrainse"
 
-#: builtin/branch.c
 #, c-format
 msgid "branch '%s' has no upstream information"
 msgstr "níl aon fhaisnéis suas sruth ag brainse '%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>?"
@@ -3912,7 +3167,6 @@
 "ní ghlacann na roghanna -a, agus -r, le 'git branch' ainm brainse.\n"
 "<pattern>An raibh sé i gceist agat úsáid a bhaint as: -a|-r --list?"
 
-#: builtin/branch.c
 msgid ""
 "the '--set-upstream' option is no longer supported. Please use '--track' or "
 "'--set-upstream-to' instead"
@@ -3920,33 +3174,27 @@
 "ní thacaítear leis an rogha '--set-upstream' a thuilleadh. Úsáid '--track' "
 "nó '--set-upstream-to' ina ionad"
 
-#: builtin/bugreport.c
 msgid "git version:\n"
 msgstr "leagan git:\n"
 
-#: builtin/bugreport.c
 msgid "compiler info: "
 msgstr "eolas tiomsaitheora: "
 
-#: builtin/bugreport.c
 msgid "libc info: "
 msgstr "eolas libc: "
 
-#: builtin/bugreport.c
 msgid "not run from a git repository - no hooks to show\n"
 msgstr "gan rith ó stór git - gan aon chrúcaí le taispeáint\n"
 
-#: builtin/bugreport.c
 msgid ""
 "git bugreport [(-o | --output-directory) <path>]\n"
 "              [(-s | --suffix) <format> | --no-suffix]\n"
 "              [--diagnose[=<mode>]]"
 msgstr ""
-"<path>git bugreport [(-o | --output-directory)]\n"
-" <format>[(-s | --iarmhír) | --no-iarmhír]\n"
-" [--diagnóis [=<mode>]]"
+"git bugreport [(-o | --output-directory) <path>]\n"
+"              [(-s | --suffix) <format> | --no-suffix]\n"
+"              [--diagnose[=<mode>]]"
 
-#: builtin/bugreport.c
 msgid ""
 "Thank you for filling out a Git bug report!\n"
 "Please answer the following questions to help us understand your issue.\n"
@@ -3983,169 +3231,131 @@
 "Déan athbhreithniú ar an chuid eile den tuarascáil fabht thíos.\n"
 "Is féidir leat aon línte nach dteastaíonn uait a roinnt a scriosadh.\n"
 
-#: builtin/bugreport.c builtin/commit.c builtin/fast-export.c builtin/rebase.c
-#: parse-options.h
 msgid "mode"
 msgstr "mód"
 
-#: builtin/bugreport.c
 msgid ""
 "create an additional zip archive of detailed diagnostics (default 'stats')"
 msgstr ""
 "cruthú cartlann zip breise de dhiagnóiseach mionsonraithe ('stats' "
 "réamhshocraithe)"
 
-#: builtin/bugreport.c
 msgid "specify a destination for the bugreport file(s)"
 msgstr "sonraigh ceann scríbe don chomhad (í) bugreport"
 
-#: builtin/bugreport.c
 msgid "specify a strftime format suffix for the filename(s)"
 msgstr "sonraigh iarmhír formáid strftime don ainm (í) comhaid"
 
-#: builtin/bugreport.c
 #, c-format
 msgid "unknown argument `%s'"
 msgstr "argóint anaithnid `%s'"
 
-#: builtin/bugreport.c builtin/diagnose.c
 #, c-format
 msgid "could not create leading directories for '%s'"
 msgstr "ní fhéadfaí eolairí tosaigh a chruthú do '%s'"
 
-#: builtin/bugreport.c builtin/diagnose.c
 #, c-format
 msgid "unable to create diagnostics archive %s"
-msgstr "nach féidir cartlann diagnóiseach %s a chruthú"
+msgstr "ní féidir cartlann diagnóisic %s a chruthú"
 
-#: builtin/bugreport.c
 msgid "System Info"
 msgstr "Eolas Córais"
 
-#: builtin/bugreport.c
 msgid "Enabled Hooks"
 msgstr "Crúcaí Cumasaithe"
 
-#: builtin/bugreport.c
 #, c-format
 msgid "unable to write to %s"
-msgstr "nach féidir a scríobh chuig %s"
+msgstr "ní féidir scríobh chuig %s"
 
-#: builtin/bugreport.c
 #, c-format
 msgid "Created new report at '%s'.\n"
 msgstr "Cruthaíodh tuarascáil nua ag '%s'.\n"
 
-#: builtin/bundle.c
 msgid ""
 "git bundle create [-q | --quiet | --progress]\n"
 "                  [--version=<version>] <file> <git-rev-list-args>"
 msgstr ""
-"cruthaigh bonn git [-q | --quiet | --progress]\n"
-" <version>[--leagan =] <file><git-rev-list-args>"
+"git bundle create [-q | --quiet | --progress]\n"
+"                  [--version=<version>] <file> <git-rev-list-args>"
 
-#: builtin/bundle.c
 msgid "git bundle verify [-q | --quiet] <file>"
-msgstr "fíorú beartán git [-q | --quiet] <file>"
+msgstr "git bundle verify [-q | --quiet] <file>"
 
-#: builtin/bundle.c
 msgid "git bundle list-heads <file> [<refname>...]"
-msgstr "<refname>ceannairí liosta bonn git <file>[...]"
+msgstr "git bundle list-heads <file> [<refname>...]"
 
-#: builtin/bundle.c
 msgid "git bundle unbundle [--progress] <file> [<refname>...]"
-msgstr "<refname>díbhuntáil bonn git [--progress] <file>[...]"
+msgstr "git bundle unbundle [--progress] <file> [<refname>...]"
 
-#: builtin/bundle.c
 msgid "need a <file> argument"
 msgstr "teastaíonn ar <file>góint"
 
-#: builtin/bundle.c builtin/pack-objects.c
 msgid "do not show progress meter"
 msgstr "ná taispeáin méadar dul chun cinn"
 
-#: builtin/bundle.c builtin/pack-objects.c
 msgid "show progress meter"
 msgstr "taispeáin méadar dul chun cinn"
 
-#: builtin/bundle.c
 msgid "historical; same as --progress"
 msgstr "stairiúil; mar an gcéanna le --progress"
 
-#: builtin/bundle.c
 msgid "historical; does nothing"
 msgstr "stairiúil; ní dhéanann aon rud"
 
-#: builtin/bundle.c
 msgid "specify bundle format version"
 msgstr "leagan formáid beartán a shonrú"
 
-#: builtin/bundle.c
 msgid "Need a repository to create a bundle."
 msgstr "Teastaíonn stór chun beartán a chruthú."
 
-#: builtin/bundle.c
 msgid "do not show bundle details"
 msgstr "ná taispeáin sonraí beartán"
 
-#: builtin/bundle.c bundle.c
 msgid "need a repository to verify a bundle"
 msgstr "teastaíonn stór chun beartán a fhíorú"
 
-#: builtin/bundle.c
 #, c-format
 msgid "%s is okay\n"
 msgstr "%s ceart go leor\n"
 
-#: builtin/bundle.c
 msgid "Need a repository to unbundle."
 msgstr "Teastaíonn stór chun dícheangail a dhícheangal."
 
-#: builtin/bundle.c
 msgid "Unbundling objects"
 msgstr "Rudaí a dhícheangal"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "cannot read object %s '%s'"
 msgstr "ní féidir réad %s '%s' a léamh"
 
-#: builtin/cat-file.c
 msgid "flush is only for --buffer mode"
 msgstr "níl sruth ach le haghaidh mód --buffer"
 
-#: builtin/cat-file.c
 msgid "empty command in input"
 msgstr "ordú folamh san ionchur"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "whitespace before command: '%s'"
 msgstr "spás bán roimh an ordú: '%s'"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "%s requires arguments"
 msgstr "Teastaíonn argóintí %s"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "%s takes no arguments"
 msgstr "Ní ghlacann %s aon argóintí"
 
-#: builtin/cat-file.c
 msgid "only one batch option may be specified"
 msgstr "ní féidir ach rogha baisc amháin a shonrú"
 
-#: builtin/cat-file.c
 msgid "git cat-file <type> <object>"
 msgstr "git cat-file <type> <object>"
 
-#: builtin/cat-file.c
 msgid "git cat-file (-e | -p | -t | -s) <object>"
 msgstr "git cat-file (-e | -p | -t | -s) <réad>"
 
-#: builtin/cat-file.c
 msgid ""
 "git cat-file (--textconv | --filters)\n"
 "             [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"
@@ -4153,7 +3363,6 @@
 "git cat-file (--textconv | --filters)\n"
 "             [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"
 
-#: builtin/cat-file.c
 msgid ""
 "git cat-file (--batch | --batch-check | --batch-command) [--batch-all-"
 "objects]\n"
@@ -4165,82 +3374,63 @@
 "             [--buffer] [--follow-symlinks] [--unordered]\n"
 "             [--textconv | --filters] [-Z]"
 
-#: builtin/cat-file.c
 msgid "Check object existence or emit object contents"
 msgstr "Seiceáil go bhfuil réad ann nó astaigh ábhar réad"
 
-#: builtin/cat-file.c
 msgid "check if <object> exists"
 msgstr "seiceáil an bhfuil <object> ann"
 
-#: builtin/cat-file.c
 msgid "pretty-print <object> content"
 msgstr "<object> ábhar priontáil álainn"
 
-#: builtin/cat-file.c
 msgid "Emit [broken] object attributes"
 msgstr "Easaigh tréithe réada [briste]"
 
-#: builtin/cat-file.c
 msgid "show object type (one of 'blob', 'tree', 'commit', 'tag', ...)"
 msgstr ""
 "taispeáint cineál réad (ceann de 'blob', 'crann', 'tiomantas', 'tag',...)"
 
-#: builtin/cat-file.c
 msgid "show object size"
 msgstr "taispeáin méid an réad"
 
-#: builtin/cat-file.c builtin/log.c
 msgid "use mail map file"
 msgstr "úsáid comhad léarscáil ríomhphoist"
 
-#: builtin/cat-file.c
 msgid "Batch objects requested on stdin (or --batch-all-objects)"
 msgstr "Baisc rudaí a iarrtar ar stdin (nó --batch-all-objects)"
 
-#: builtin/cat-file.c
 msgid "show full <object> or <rev> contents"
 msgstr "taispeáin iomlán <object>nó á <rev>bhar"
 
-#: builtin/cat-file.c
 msgid "like --batch, but don't emit <contents>"
 msgstr "cosúil le --batch, ach ná astaíonn <contents>"
 
-#: builtin/cat-file.c
 msgid "stdin is NUL-terminated"
 msgstr "tá stdin foirceanta ag NUL"
 
-#: builtin/cat-file.c
 msgid "stdin and stdout is NUL-terminated"
 msgstr "tá stdin agus stdout foirceannta NUL"
 
-#: builtin/cat-file.c
 msgid "read commands from stdin"
 msgstr "léigh orduithe ó stdin"
 
-#: builtin/cat-file.c
 msgid "with --batch[-check]: ignores stdin, batches all known objects"
 msgstr ""
 "le --batch [-check]: déanann neamhaird ar stdin, déanann baisceanna gach rud "
 "aitheanta"
 
-#: builtin/cat-file.c
 msgid "Change or optimize batch output"
 msgstr "Athraigh nó barrfheabhsú aschur baisc"
 
-#: builtin/cat-file.c
 msgid "buffer --batch output"
 msgstr "maolán --batch baisc"
 
-#: builtin/cat-file.c
 msgid "follow in-tree symlinks"
 msgstr "lean naisc shiombailí in-chrann"
 
-#: builtin/cat-file.c
 msgid "do not order objects before emitting them"
 msgstr "ná ordaigh rudaí sula n-astaíonn tú iad"
 
-#: builtin/cat-file.c
 msgid ""
 "Emit object (blob or tree) with conversion or filter (stand-alone, or with "
 "batch)"
@@ -4248,70 +3438,55 @@
 "Rud a astaíonn (blob nó crann) le comhshó nó scagaire (neamhspleách, nó le "
 "baisc)"
 
-#: builtin/cat-file.c
 msgid "run textconv on object's content"
 msgstr "reáchtáil textconv ar ábhar an réad"
 
-#: builtin/cat-file.c
 msgid "run filters on object's content"
 msgstr "reáchtáil scagairí ar ábhar an rud"
 
-#: builtin/cat-file.c
 msgid "blob|tree"
 msgstr "blob | crann"
 
-#: builtin/cat-file.c
 msgid "use a <path> for (--textconv | --filters); Not with 'batch'"
 msgstr "úsáid a le <path>haghaidh (--textconv | --filters); Ní le 'baisc'"
 
-#: builtin/cat-file.c
 msgid "objects filter only supported in batch mode"
 msgstr "ní thacaítear scagaire rudaí ach i mód baisc"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "objects filter not supported: '%s'"
 msgstr "ní thacaítear le scagaire réadanna: '%s'"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "'%s=<%s>' needs '%s' or '%s'"
 msgstr "'%s=<%s>' teastaíonn '%s' nó '%s'"
 
-#: builtin/cat-file.c
 msgid "path|tree-ish"
 msgstr "cosán | crann-ish"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "'%s' requires a batch mode"
 msgstr "Éilíonn '%s' modh baisc"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "'-%c' is incompatible with batch mode"
 msgstr "Níl '-%c' comhoiriúnach le mód baisc"
 
-#: builtin/cat-file.c
 msgid "batch modes take no arguments"
 msgstr "ní ghlacann modhanna baisc aon argóintí"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "<rev> required with '%s'"
 msgstr "<rev>ag teastáil le '%s'"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "<object> required with '-%c'"
 msgstr "<object>ag teastáil le '-%c'"
 
-#: builtin/cat-file.c
 #, c-format
 msgid "only two arguments allowed in <type> <object> mode, not %d"
 msgstr "ní cheadaítear ach dhá argóint <type><object>sa mhodh, ní %d"
 
-#: builtin/check-attr.c
 msgid ""
 "git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] "
 "<pathname>..."
@@ -4319,202 +3494,154 @@
 "git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] "
 "<pathname>..."
 
-#: builtin/check-attr.c
 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 "tuairisc a thabhairt ar gach tréithe atá leagtha síos"
 
-#: builtin/check-attr.c
 msgid "use .gitattributes only from the index"
 msgstr "bain úsáid as .gitattributs ach ón innéacs"
 
-#: builtin/check-attr.c builtin/check-ignore.c builtin/hash-object.c
 msgid "read file names from stdin"
 msgstr "léigh ainmneacha comhaid ó stdin"
 
-#: builtin/check-attr.c builtin/check-ignore.c
 msgid "terminate input and output records by a NUL character"
 msgstr "taifid ionchuir agus aschuir a fhoirceannadh le carachtar NUL"
 
-#: builtin/check-attr.c
 msgid "<tree-ish>"
 msgstr "<tree-ish>"
 
-#: builtin/check-attr.c
 msgid "which tree-ish to check attributes at"
 msgstr "cén crainn le tréithe a sheiceáil ag"
 
-#: builtin/check-ignore.c builtin/checkout.c builtin/gc.c builtin/worktree.c
 msgid "suppress progress reporting"
 msgstr "cur chun cinn tuairiscithe"
 
-#: builtin/check-ignore.c
 msgid "show non-matching input paths"
 msgstr "cosáin ionchuir neamh-mheaitseála"
 
-#: builtin/check-ignore.c
 msgid "ignore index when checking"
 msgstr "neamhaird a dhéanamh ar innéacs agus"
 
-#: builtin/check-ignore.c
 msgid "cannot specify pathnames with --stdin"
 msgstr "ní féidir ainmneacha cosáin a shonrú le --stdin"
 
-#: builtin/check-ignore.c
 msgid "-z only makes sense with --stdin"
 msgstr "Ní dhéanann -z ciall ach le --stdin"
 
-#: builtin/check-ignore.c
 msgid "no path specified"
 msgstr "níl aon chosán sonraithe"
 
-#: builtin/check-ignore.c
 msgid "--quiet is only valid with a single pathname"
 msgstr "Níl --quiet bailí ach le ainm cosán amháin"
 
-#: builtin/check-ignore.c
 msgid "cannot have both --quiet and --verbose"
 msgstr "ní féidir --quiet agus --verbose araon a bheith agat"
 
-#: builtin/check-ignore.c
 msgid "--non-matching is only valid with --verbose"
 msgstr "Níl --non-matching bailí ach le --verbose"
 
-#: builtin/check-mailmap.c
 msgid "git check-mailmap [<options>] <contact>..."
 msgstr "git check-mailmap [<options>] <contact>..."
 
-#: builtin/check-mailmap.c
 msgid "also read contacts from stdin"
 msgstr "léigh teagmhálacha ó stdin freisin"
 
-#: builtin/check-mailmap.c
 msgid "read additional mailmap entries from file"
 msgstr "léigh iontrálacha ríomhphoist breise ón gcomhad"
 
-#: builtin/check-mailmap.c
 msgid "blob"
 msgstr "blob"
 
-#: builtin/check-mailmap.c
 msgid "read additional mailmap entries from blob"
 msgstr "léigh iontrálacha ríomhphoist breise ó blob"
 
-#: builtin/check-mailmap.c
 msgid "no contacts specified"
 msgstr "aon teagmhálacha sonraithe"
 
-#: builtin/checkout--worker.c
 msgid "git checkout--worker [<options>]"
 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 "teaghrán"
 
-#: builtin/checkout--worker.c builtin/checkout-index.c
 msgid "when creating files, prepend <string>"
 msgstr "agus comhaid á gcruthú agat, déan iarracht <string>"
 
-#: builtin/checkout-index.c
 msgid "git checkout-index [<options>] [--] [<file>...]"
 msgstr "git checkout-index [<options>] [--] [<file>...]"
 
-#: builtin/checkout-index.c
 msgid "stage should be between 1 and 3 or all"
 msgstr "ba chóir go mbeadh an chéim idir 1 agus 3 nó gach ceann"
 
-#: builtin/checkout-index.c
 msgid "check out all files in the index"
 msgstr "seiceáil gach comhad san innéacs"
 
-#: builtin/checkout-index.c
 msgid "do not skip files with skip-worktree set"
 msgstr "ná scipeáil comhaid le tacar scip-work tree"
 
-#: builtin/checkout-index.c
 msgid "force overwrite of existing files"
 msgstr "athscríobh fórsa na gcomhaid atá ann cheana"
 
-#: builtin/checkout-index.c
 msgid "no warning for existing files and files not in index"
 msgstr ""
 "gan aon rabhadh maidir le comhaid agus comhaid atá ann cheana nach bhfuil "
 "san innéacs"
 
-#: builtin/checkout-index.c
 msgid "don't checkout new files"
 msgstr "ná seiceáil comhaid nua"
 
-#: builtin/checkout-index.c
 msgid "update stat information in the index file"
 msgstr "faisnéis stat a nuashonrú sa chomhad innéacs"
 
-#: builtin/checkout-index.c
 msgid "read list of paths from the standard input"
 msgstr "léigh liosta na gcosáin ón ionchur caighdeánach"
 
-#: builtin/checkout-index.c
 msgid "write the content to temporary files"
 msgstr "scríobh an t-ábhar chuig comhaid sealadacha"
 
-#: builtin/checkout-index.c
 msgid "copy out the files from named stage"
 msgstr "cóipeáil amach na comhaid ón gcéim ainmnithe"
 
-#: builtin/checkout.c
 msgid "git checkout [<options>] <branch>"
 msgstr "git checkout [<roghanna>] <brainse>"
 
-#: builtin/checkout.c
 msgid "git checkout [<options>] [<branch>] -- <file>..."
 msgstr "git checkout [<roghanna>] [<brainse>] --<comhad>..."
 
-#: builtin/checkout.c
 msgid "git switch [<options>] [<branch>]"
-msgstr "git switch [<roghanna>] [<brainse>]"
+msgstr "git switch [<options>] [<branch>]"
 
-#: builtin/checkout.c
 msgid "git restore [<options>] [--source=<branch>] <file>..."
-msgstr "git restore [<roghanna>] [--source=<brainse>] <comhad>..."
+msgstr "git restore [<options>] [--source=<branch>] <file>..."
 
-#: builtin/checkout.c
 #, c-format
 msgid "path '%s' does not have our version"
 msgstr "níl ár leagan ag cosán '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "path '%s' does not have their version"
 msgstr "níl a leagan ag cosán '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "path '%s' does not have all necessary versions"
 msgstr "níl gach leagan riachtanach ag cosán '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "path '%s' does not have necessary versions"
 msgstr "níl leaganacha riachtanacha ag cosán '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "path '%s': cannot merge"
 msgstr "cosán '%s': ní féidir a chumasc"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Unable to add merge result for '%s'"
 msgstr "Ní féidir toradh cumaisc a chur le haghaidh '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Recreated %d merge conflict"
 msgid_plural "Recreated %d merge conflicts"
@@ -4522,7 +3649,6 @@
 msgstr[1] "Athchruthaíodh %d coinbhleachtaí chumaisc"
 msgstr[2] "Athchruthaíodh %d coinbhleachtaí chumaisc"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Updated %d path from %s"
 msgid_plural "Updated %d paths from %s"
@@ -4530,7 +3656,6 @@
 msgstr[1] "Nuashonraíodh %d cosán ó %s"
 msgstr[2] "Nuashonraíodh %d cosán ó %s"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Updated %d path from the index"
 msgid_plural "Updated %d paths from the index"
@@ -4538,54 +3663,43 @@
 msgstr[1] "Nuashonraíodh %d cosán ón innéacs"
 msgstr[2] "Nuashonraíodh %d cosán ón innéacs"
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s' cannot be used with updating paths"
 msgstr "Ní féidir '%s' a úsáid le cosáin a nuashonrú"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Cannot update paths and switch to branch '%s' at the same time."
 msgstr ""
 "Ní féidir cosáin a nuashonrú agus aistriú go brainse '%s' ag an am céanna."
 
-#: builtin/checkout.c
 #, c-format
 msgid "neither '%s' or '%s' is specified"
 msgstr "níl '%s' ná '%s' sonraithe"
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s' must be used when '%s' is not specified"
 msgstr "Ní mór '%s' a úsáid nuair nach sonraítear '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s' or '%s' cannot be used with %s"
 msgstr "Ní féidir '%s' nó '%s' a úsáid le %s"
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s', '%s', or '%s' cannot be used when checking out of a tree"
 msgstr ""
 "Ní féidir '%s', '%s', nó '%s' a úsáid agus tú ag seiceáil amach as crann"
 
-#: builtin/checkout.c
 #, c-format
 msgid "path '%s' is unmerged"
 msgstr "tá cosán '%s' neamh-chomhcheangailte"
 
-#: builtin/checkout.c builtin/grep.c builtin/merge-tree.c builtin/reset.c
-#: merge-ort.c reset.c sequencer.c tree-walk.c
 #, c-format
 msgid "unable to read tree (%s)"
-msgstr "nach féidir crann a léamh (%s)"
+msgstr "ní féidir crann a léamh (%s)"
 
-#: builtin/checkout.c
 msgid "you need to resolve your current index first"
 msgstr "ní mór duit d'innéacs reatha a réiteach ar dtús"
 
-#: builtin/checkout.c
 #, c-format
 msgid ""
 "cannot continue with staged changes in the following files:\n"
@@ -4594,50 +3708,40 @@
 "ní féidir leanúint ar aghaidh le hathruithe céime sna comhaid seo a leanas:\n"
 "%s"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Can not do reflog for '%s': %s\n"
 msgstr "Ní féidir athbhreithniú a dhéanamh le haghaidh '%s': %s\n"
 
-#: builtin/checkout.c
 msgid "HEAD is now at"
 msgstr "Tá HEAD anois ag"
 
-#: builtin/checkout.c builtin/clone.c
 msgid "unable to update HEAD"
-msgstr "in ann HEAD a nuashonrú"
+msgstr "ní féidir HEAD a nuashonrú"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Reset branch '%s'\n"
 msgstr "Athshocraigh brainse '%s'\n"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Already on '%s'\n"
 msgstr "Ar '%s' cheana féin\n"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Switched to and reset branch '%s'\n"
 msgstr "Aistrigh agus athshocraigh brainse '%s'\n"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Switched to a new branch '%s'\n"
 msgstr "Aistrithe go brainse nua '%s'\n"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Switched to branch '%s'\n"
 msgstr "Aistrithe go brainse '%s'\n"
 
-#: builtin/checkout.c
 #, c-format
 msgid " ... and %d more.\n"
 msgstr " ... agus %d níos mó.\n"
 
-#: builtin/checkout.c
 #, c-format
 msgid ""
 "Warning: you are leaving %d commit behind, not connected to\n"
@@ -4665,7 +3769,6 @@
 "\n"
 "%s\n"
 
-#: builtin/checkout.c
 #, c-format
 msgid ""
 "If you want to keep it by creating a new branch, this may be a good time\n"
@@ -4695,19 +3798,15 @@
 "\n"
 "git branch <ainm-brainse-nua> %s\n"
 
-#: builtin/checkout.c
 msgid "internal error in revision walk"
 msgstr "earráid inmheánach i dsiúlóid"
 
-#: builtin/checkout.c
 msgid "Previous HEAD position was"
 msgstr "Bhí post CEAD roimhe seo"
 
-#: builtin/checkout.c
 msgid "You are on a branch yet to be born"
 msgstr "Tá tú ar bhrainse nach rugadh fós"
 
-#: builtin/checkout.c
 #, c-format
 msgid ""
 "'%s' could be both a local file and a tracking branch.\n"
@@ -4717,7 +3816,6 @@
 "araon.\n"
 "Úsáid le do thoil -- (agus go roghnach --no-guess) chun a dhíbhriú"
 
-#: builtin/checkout.c
 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"
@@ -4740,58 +3838,47 @@
 "iargúlta amháin, e.g. an iargúlta 'origin', smaoinigh ar shocrú\n"
 "checkout.defaultRemote=origin i do chumraíocht."
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s' matched multiple (%d) remote tracking branches"
 msgstr "Mheaitseáil '%s' roinnt (%d) brainsí rianaithe iargúlta"
 
-#: builtin/checkout.c
 msgid "only one reference expected"
 msgstr "níl ach tagairt amháin ag súil leis"
 
-#: builtin/checkout.c
 #, c-format
 msgid "only one reference expected, %d given."
 msgstr "níl ach tagairt amháin ag súil leis, %d tugtha."
 
-#: builtin/checkout.c builtin/worktree.c
 #, c-format
 msgid "invalid reference: %s"
 msgstr "tagairt neamhbhailí: %s"
 
-#: builtin/checkout.c
 #, c-format
 msgid "reference is not a tree: %s"
 msgstr "ní crann é tagairt: %s"
 
-#: builtin/checkout.c
 #, c-format
 msgid "a branch is expected, got tag '%s'"
 msgstr "táthar ag súil le brainse, faightear tag '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "a branch is expected, got remote branch '%s'"
 msgstr "táthar ag súil le brainse, fuair brainse iargúlta '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "a branch is expected, got '%s'"
 msgstr "táthar ag súil le brainse, fuair '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "a branch is expected, got commit '%s'"
 msgstr "táthar ag súil le brainse, fuair sé tiomantas '%s'"
 
-#: builtin/checkout.c
 msgid ""
 "If you want to detach HEAD at the commit, try again with the --detach option."
 msgstr ""
 "Más mian leat HEAD a dhícheangal ag an tiomantas, déan iarracht arís leis an "
 "rogha --detach."
 
-#: builtin/checkout.c
 msgid ""
 "cannot switch branch while merging\n"
 "Consider \"git merge --quit\" or \"git worktree add\"."
@@ -4799,7 +3886,6 @@
 "ní féidir brainse a athrú agus cumasc á dhéanamh\n"
 "Smaoinigh ar \"git merge --quit\" nó \"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\"."
@@ -4807,7 +3893,6 @@
 "ní féidir brainse a athrú i lár seisiún am\n"
 "Smaoinigh ar \"git am --quit\" nó \"git worktree add\"."
 
-#: builtin/checkout.c
 msgid ""
 "cannot switch branch while rebasing\n"
 "Consider \"git rebase --quit\" or \"git worktree add\"."
@@ -4815,7 +3900,6 @@
 "ní féidir brainse a athrú agus athbhunú á dhéanamh\n"
 "Smaoinigh ar \"git rebase --quit\" nó \"git worktree add\"."
 
-#: builtin/checkout.c
 msgid ""
 "cannot switch branch while cherry-picking\n"
 "Consider \"git cherry-pick --quit\" or \"git worktree add\"."
@@ -4823,7 +3907,6 @@
 "ní féidir brainse a athrú agus tú ag cherry-picking\n"
 "Smaoinigh ar \"git cherry-pick --quit\" nó \"git worktree add\"."
 
-#: builtin/checkout.c
 msgid ""
 "cannot switch branch while reverting\n"
 "Consider \"git revert --quit\" or \"git worktree add\"."
@@ -4831,132 +3914,103 @@
 "ní féidir brainse a athrú agus aisiompú á dhéanamh\n"
 "Smaoinigh ar \"git revert --quit\" nó \"git worktree add\"."
 
-#: builtin/checkout.c
 msgid "you are switching branch while bisecting"
 msgstr "tá tú ag athrú brainse agus tú ag déileáil"
 
-#: builtin/checkout.c
 msgid "paths cannot be used with switching branches"
 msgstr "ní féidir cosáin a úsáid le brainsí a athrú"
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s' cannot be used with switching branches"
 msgstr "Ní féidir '%s' a úsáid le brainsí a athrú"
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s' needs the paths to check out"
 msgstr "Teastaíonn '%s' na cosáin chun seiceáil"
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s' cannot be used with '%s'"
 msgstr "Ní féidir '%s' a úsáid le '%s'"
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s' cannot take <start-point>"
 msgstr "Ní féidir '%s' a ghlacadh <start-point>"
 
-#: builtin/checkout.c
 #, c-format
 msgid "Cannot switch branch to a non-commit '%s'"
 msgstr "Ní féidir brainse a aistriú go '%s' neamh-thiomanta"
 
-#: builtin/checkout.c
 msgid "missing branch or commit argument"
 msgstr "brainse ar iarraidh nó argóint a dhéanamh"
 
-#: builtin/checkout.c
 #, c-format
 msgid "unknown conflict style '%s'"
 msgstr "stíl choimhlinte anaithnid '%s'"
 
-#: builtin/checkout.c
 msgid "perform a 3-way merge with the new branch"
 msgstr "cumasc 3 bhealach a dhéanamh leis an mbrainse nua"
 
-#: builtin/checkout.c builtin/log.c builtin/range-diff.c parse-options.h
 msgid "style"
 msgstr "stíl"
 
-#: builtin/checkout.c
 msgid "conflict style (merge, diff3, or zdiff3)"
 msgstr "stíl choimhlinte (cumaisc, diff3, nó zdiff3)"
 
-#: builtin/checkout.c builtin/worktree.c
 msgid "detach HEAD at named commit"
 msgstr "dícheangail HEAD ag an tiomnú ainmnithe"
 
-#: builtin/checkout.c
 msgid "force checkout (throw away local modifications)"
 msgstr "seiceáil fórsa (caith modhnuithe áitiúla)"
 
-#: builtin/checkout.c
 msgid "new-branch"
 msgstr "brainse-nua"
 
-#: builtin/checkout.c
 msgid "new unborn branch"
 msgstr "brainse nua gan breith"
 
-#: builtin/checkout.c builtin/merge.c
 msgid "update ignored files (default)"
 msgstr "nuashonrú comhaid a dhéantar neamhaird orthu"
 
-#: builtin/checkout.c
 msgid "do not check if another worktree is using this branch"
 msgstr ""
 "ná seiceáil an bhfuil crann oibre eile á úsáid ag baint úsáide as an "
 "mbrainse seo"
 
-#: builtin/checkout.c
 msgid "checkout our version for unmerged files"
 msgstr "seiceáil ár leagan le haghaidh comhaid neamh-chumasaithe"
 
-#: builtin/checkout.c
 msgid "checkout their version for unmerged files"
 msgstr "seiceáil a leagan le haghaidh comhaid neamh-chumasaithe"
 
-#: builtin/checkout.c
 msgid "do not limit pathspecs to sparse entries only"
 msgstr "ná teorainn le speisiúintí cosáin le hiontrálacha neamhchoitianta"
 
-#: builtin/checkout.c
 #, c-format
 msgid "options '-%c', '-%c', and '%s' cannot be used together"
 msgstr "ní féidir na roghanna '-%c', '-%c', agus '%s' a úsáid le chéile"
 
-#: builtin/checkout.c
 msgid "--track needs a branch name"
 msgstr "--track tá ainm brainse ag teastáil"
 
-#: builtin/checkout.c
 #, c-format
 msgid "missing branch name; try -%c"
 msgstr "ainm brainse ar iarraidh; iarracht -%c"
 
-#: builtin/checkout.c
 #, c-format
 msgid "could not resolve %s"
 msgstr "ní fhéadfaí %s a réiteach"
 
-#: builtin/checkout.c
 msgid "invalid path specification"
-msgstr "sonraíocht cosáin nebhail"
+msgstr "sonraíocht chosáin neamhbhailí"
 
-#: builtin/checkout.c
 #, c-format
 msgid "'%s' is not a commit and a branch '%s' cannot be created from it"
 msgstr "Ní tiomantas é '%s' agus ní féidir brainse '%s' a chruthú uaidh"
 
-#: builtin/checkout.c
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
 msgstr "git checkout: --detach ní ghlacann argóint cosáin '%s'"
 
-#: builtin/checkout.c
 msgid ""
 "git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 "checking out of the index."
@@ -4964,118 +4018,91 @@
 "git checkout: --ours/--theirs, --force agus --merge neamhoiriúnach nuair\n"
 "seiceáil amach as an innéacs."
 
-#: builtin/checkout.c
 msgid "you must specify path(s) to restore"
 msgstr "ní mór duit cosáin(í) a shonrú chun athchóiriú"
 
-#: builtin/checkout.c builtin/clone.c builtin/remote.c builtin/replay.c
-#: builtin/submodule--helper.c builtin/worktree.c
 msgid "branch"
 msgstr "brainse"
 
-#: builtin/checkout.c
 msgid "create and checkout a new branch"
 msgstr "brainse nua a chruthú agus a sheiceáil"
 
-#: builtin/checkout.c
 msgid "create/reset and checkout a branch"
 msgstr "cruthaigh/athshocraigh agus seiceáil amach brainse"
 
-#: builtin/checkout.c
 msgid "create reflog for new branch"
 msgstr "cruthú reflog do bhrainse nua"
 
-#: builtin/checkout.c
 msgid "second guess 'git checkout <no-such-branch>' (default)"
 msgstr "an dara tuairim 'git check <no-such-branch>'(réamhshocraithe)"
 
-#: builtin/checkout.c
 msgid "use overlay mode (default)"
 msgstr "úsáid modh forleagtha (réamhshocraithe)"
 
-#: builtin/checkout.c
 msgid "create and switch to a new branch"
 msgstr "cruthú agus aistrigh go brainse nua"
 
-#: builtin/checkout.c
 msgid "create/reset and switch to a branch"
 msgstr "cruthú/athshocraigh agus aistrigh go brainse"
 
-#: builtin/checkout.c
 msgid "second guess 'git switch <no-such-branch>'"
 msgstr "buille faoi thuairim eile 'git switch <gan-bhrainse-den-sórt-sin>'"
 
-#: builtin/checkout.c
 msgid "throw away local modifications"
 msgstr "modhnuithe áitiúla a chaitheamh"
 
-#: builtin/checkout.c
 msgid "which tree-ish to checkout from"
 msgstr "cén crainn le seiceáil uaidh"
 
-#: builtin/checkout.c
 msgid "restore the index"
 msgstr "an t-innéacs a chur ar ais"
 
-#: builtin/checkout.c
 msgid "restore the working tree (default)"
 msgstr "an crann oibre a chur ar ais (réamhshocraithe)"
 
-#: builtin/checkout.c
 msgid "ignore unmerged entries"
 msgstr "neamhaird a dhéanamh ar iontrálacha"
 
-#: builtin/checkout.c
 msgid "use overlay mode"
 msgstr "úsáid modh forleagtha"
 
-#: builtin/clean.c
 msgid ""
 "git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] "
 "[<pathspec>...]"
 msgstr ""
-"<pathspec>git glan [-d] [-f] [-i] [-n] [-q] [-e] [- <pattern>x | -X] [--] "
-"[...]"
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] "
+"[<pathspec>...]"
 
-#: builtin/clean.c
 #, c-format
 msgid "Removing %s\n"
 msgstr "Ag baint %s\n"
 
-#: builtin/clean.c
 #, c-format
 msgid "Would remove %s\n"
 msgstr "Bainfeadh %s\n"
 
-#: builtin/clean.c
 #, c-format
 msgid "Skipping repository %s\n"
 msgstr "Ag scipeáil an stóras %s\n"
 
-#: builtin/clean.c
 #, c-format
 msgid "Would skip repository %s\n"
 msgstr "Scaipfeadh stóras %s\n"
 
-#: builtin/clean.c midx.c
 #, c-format
 msgid "failed to remove %s"
 msgstr "theip ar %s a bhaint"
 
-#: builtin/clean.c
 #, c-format
 msgid "could not lstat %s\n"
 msgstr "ní fhéadfaí lstat %s\n"
 
-#: builtin/clean.c
 msgid "Refusing to remove current working directory\n"
 msgstr "Ag diúltú an t-eolaire oibre reatha a bhaint\n"
 
-#: builtin/clean.c
 msgid "Would refuse to remove current working directory\n"
 msgstr "Dhiúltódh sé/sí an t-eolaire oibre reatha a bhaint\n"
 
-#: builtin/clean.c
 #, c-format
 msgid ""
 "Prompt help:\n"
@@ -5084,11 +4111,10 @@
 "           - (empty) select nothing\n"
 msgstr ""
 "Cabhair pras:\n"
-"1 - roghnaigh mír uimhrithe\n"
-"foo - roghnaigh mír bunaithe ar réimír uathúil\n"
-" - (folamh) roghnaigh aon rud\n"
+"1          - roghnaigh mír uimhrithe\n"
+"foo        - roghnaigh mír bunaithe ar réimír uathúil\n"
+"            - (folamh) roghnaigh aon rud\n"
 
-#: builtin/clean.c
 #, c-format
 msgid ""
 "Prompt help:\n"
@@ -5101,40 +4127,34 @@
 "           - (empty) finish selecting\n"
 msgstr ""
 "Cabhair pras:\n"
-"1 - roghnaigh mír amháin\n"
-"3-5 - roghnaigh raon earraí\n"
+"1        - roghnaigh mír amháin\n"
+"3-5        - roghnaigh raon earraí\n"
 "2-3,6-9 - roghnaigh raonta iolracha\n"
-"foo - roghnaigh mír bunaithe ar réimír uathúil\n"
-"-... - míreanna sonraithe a dhíroghnú\n"
-"* - roghnaigh gach earra\n"
-" - (folamh) bailchríoch a roghnú\n"
+"foo        - roghnaigh mír bunaithe ar réimír uathúil\n"
+"-...        - míreanna sonraithe a dhíroghnú\n"
+"*          - roghnaigh gach earra\n"
+"           - (folamh) bailchríoch a roghnú\n"
 
-#: builtin/clean.c
 #, c-format
 msgid "Huh (%s)?\n"
 msgstr "Huh (%s)?\n"
 
-#: builtin/clean.c
 #, c-format
 msgid "Input ignore patterns>> "
 msgstr "Patrúin neamhaird ionchuir >> "
 
-#: builtin/clean.c
 #, c-format
 msgid "WARNING: Cannot find items matched by: %s"
 msgstr "RABHADH: Ní féidir míreanna a mheaitseáil le: %s a aimsiú"
 
-#: builtin/clean.c
 msgid "Select items to delete"
 msgstr "Roghnaigh míreanna le scriosadh"
 
 #. TRANSLATORS: Make sure to keep [y/N] as is
-#: builtin/clean.c
 #, c-format
 msgid "Remove %s [y/N]? "
 msgstr "Bain %s [y/N]? "
 
-#: builtin/clean.c
 msgid ""
 "clean               - start cleaning\n"
 "filter by pattern   - exclude items from deletion\n"
@@ -5144,129 +4164,104 @@
 "help                - this screen\n"
 "?                   - help for prompt selection"
 msgstr ""
-"glan - tosú ag glanadh\n"
-"scagadh de réir patrún - eisiamh míreanna ó scriosadh\n"
-"roghnaigh de réir uimhreacha - roghnaigh míreanna atá le scriosadh de réir\n"
-"fiafraigh gach ceann - deimhnigh gach scriosadh (cosúil le “rm -i”)\n"
-"scor - stop glanadh\n"
-"cabhair - an scáileán seo\n"
-"? - cabhair le haghaidh roghnú pras"
+"glan               - tosú ag glanadh\n"
+"scagadh de réir patrún   - eisiamh míreanna ó scriosadh\n"
+"roghnaigh de réir uimhreacha   - roghnaigh míreanna atá le scriosadh de "
+"réir\n"
+"fiafraigh gach ceann               - deimhnigh gach scriosadh (cosúil le “rm "
+"-i”)\n"
+"scor               - stop glanadh\n"
+"cabhair               - an scáileán seo\n"
+"?               - cabhair le haghaidh roghnú pras"
 
-#: builtin/clean.c
 msgid "Would remove the following item:"
 msgid_plural "Would remove the following items:"
 msgstr[0] "Bhainfeadh sé an mhír seo a leanas:"
 msgstr[1] "Bainfí na míreanna seo a leanas:"
 msgstr[2] "Bainfí na míreanna seo a leanas:"
 
-#: builtin/clean.c
 msgid "No more files to clean, exiting."
 msgstr "Níl aon níos mó comhaid le glanadh, ag imeacht amach."
 
-#: builtin/clean.c
 msgid "do not print names of files removed"
 msgstr "ná priontáil ainmneacha na gcomhaid a bhaintear"
 
-#: builtin/clean.c
 msgid "force"
 msgstr "fórsa"
 
-#: builtin/clean.c
 msgid "interactive cleaning"
 msgstr "glanadh idirghní"
 
-#: builtin/clean.c
 msgid "remove whole directories"
 msgstr "bain eolairí iomlána"
 
-#: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c
-#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c
-#: builtin/show-ref.c ref-filter.h
 msgid "pattern"
 msgstr "patrún"
 
-#: builtin/clean.c
 msgid "add <pattern> to ignore rules"
 msgstr "cuir leis <pattern>na rialacha a neamhaird"
 
-#: builtin/clean.c
 msgid "remove ignored files, too"
 msgstr "bain comhaid a neamhaird orthu, freisin"
 
-#: builtin/clean.c
 msgid "remove only ignored files"
 msgstr "bain ach comhaid a neamhaird orthu"
 
-#: builtin/clean.c
 msgid "clean.requireForce is true and -f not given: refusing to clean"
 msgstr "tá clean.requireForce fíor agus ní thugtar -f: diúltú glanadh"
 
-#: builtin/clone.c
 #, c-format
 msgid "info: Could not add alternate for '%s': %s\n"
 msgstr "eolas: Ní féidir malartach a chur le haghaidh '%s': %s\n"
 
-#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c
 #, c-format
 msgid "failed to stat '%s'"
 msgstr "theip ar '%s' a stáil"
 
-#: builtin/clone.c
 #, c-format
 msgid "%s exists and is not a directory"
 msgstr "Tá %s ann agus ní eolaire é"
 
-#: builtin/clone.c
 #, c-format
 msgid "'%s' is a symlink, refusing to clone with --local"
 msgstr "Is nasc comhsheasmhach é '%s', ag diúltú clónú le --local"
 
-#: builtin/clone.c
 #, c-format
 msgid "failed to start iterator over '%s'"
 msgstr "theip ar an iterator a thosú thar '%s'"
 
-#: builtin/clone.c
 #, c-format
 msgid "symlink '%s' exists, refusing to clone with --local"
 msgstr "tá nasc symlink '%s' ann, ag diúltú clónú le --local"
 
-#: builtin/clone.c compat/precompose_utf8.c
 #, c-format
 msgid "failed to unlink '%s'"
 msgstr "theip ar '%s' a dhínascadh"
 
-#: builtin/clone.c
 #, c-format
 msgid "hardlink cannot be checked at '%s'"
 msgstr "ní féidir crua-nasc a sheiceáil ag '%s'"
 
-#: builtin/clone.c
 #, c-format
 msgid "hardlink different from source at '%s'"
 msgstr "crua-nasc difriúil ó fhoinse ag '%s'"
 
-#: builtin/clone.c
 #, c-format
 msgid "failed to create link '%s'"
 msgstr "theip ar nasc '%s' a chruthú"
 
-#: builtin/clone.c
 #, c-format
 msgid "failed to copy file to '%s'"
 msgstr "theip ar chomhad a chóipeáil chuig '%s'"
 
-#: builtin/clone.c refs/files-backend.c
 #, c-format
 msgid "failed to iterate over '%s'"
 msgstr "theip ar athrá thar '%s'"
 
-#: builtin/clone.c
 #, c-format
 msgid "done.\n"
 msgstr "déanta.\n"
 
-#: builtin/clone.c
 msgid ""
 "Clone succeeded, but checkout failed.\n"
 "You can inspect what was checked out with 'git status'\n"
@@ -5277,393 +4272,300 @@
 "status'\n"
 "agus déan iarracht arís le 'git restore --source=HEAD : /'\n"
 
-#: builtin/clone.c fetch-pack.c
 msgid "remote did not send all necessary objects"
 msgstr "níor sheol iargúlta gach rud riachtanach"
 
-#: builtin/clone.c
 #, c-format
 msgid "unable to update %s"
-msgstr "nach féidir %s a nuashonrú"
+msgstr "ní féidir %s a nuashonrú"
 
-#: builtin/clone.c
 msgid "failed to initialize sparse-checkout"
 msgstr "theip ar sheiceáil éagsúil a thosú"
 
-#: builtin/clone.c
 msgid "remote HEAD refers to nonexistent ref, unable to checkout"
 msgstr ""
 "tagraíonn iargúlta HEAD do thagartha nach bhfuil ann, nach féidir a sheiceáil"
 
-#: builtin/clone.c
 msgid "unable to checkout working tree"
-msgstr "in ann crann oibre a sheiceáil"
+msgstr "ní féidir crann oibre a sheiceáil amach"
 
-#: builtin/clone.c
 msgid "unable to write parameters to config file"
-msgstr "in ann paraiméadair a scríobh chuig comhad cumraithe"
+msgstr "ní féidir paraiméadair a scríobh chuig an gcomhad cumraíochta"
 
-#: builtin/clone.c
 msgid "cannot repack to clean up"
 msgstr "ní féidir athphacáil chun glanadh"
 
-#: builtin/clone.c
 msgid "cannot unlink temporary alternates file"
 msgstr "ní féidir le comhad malartacha sealadacha a dhínascadh"
 
-#: builtin/clone.c
 msgid "don't clone shallow repository"
 msgstr "ná clóin stór éadomhain"
 
-#: builtin/clone.c
 msgid "don't create a checkout"
 msgstr "ná cruthaigh seiceáil"
 
-#: builtin/clone.c builtin/init-db.c
 msgid "create a bare repository"
 msgstr "stóras lom a chruthú"
 
-#: builtin/clone.c
 msgid "create a mirror repository (implies --bare)"
 msgstr "stóras scátháin a chruthú (tugann le tuiscint --bare)"
 
-#: builtin/clone.c
 msgid "to clone from a local repository"
 msgstr "a chlónú ó stór áitiúil"
 
-#: builtin/clone.c
 msgid "don't use local hardlinks, always copy"
 msgstr "ná húsáid crua-naisc áitiúla, cóipeáil i gcónaí"
 
-#: builtin/clone.c
 msgid "setup as shared repository"
 msgstr "socrú mar stór roinnte"
 
-#: builtin/clone.c
 msgid "pathspec"
 msgstr "sonraíocht chosáin"
 
-#: builtin/clone.c
 msgid "initialize submodules in the clone"
 msgstr "fo-mhodúil a thionscnamh sa chlón"
 
-#: builtin/clone.c
 msgid "number of submodules cloned in parallel"
 msgstr "líon na bhfo-mhodúil atá clónaithe go comhthreomhar"
 
-#: builtin/clone.c builtin/init-db.c
 msgid "template-directory"
 msgstr "eolaire teimpléad"
 
-#: builtin/clone.c builtin/init-db.c
 msgid "directory from which templates will be used"
 msgstr "eolaire as a n-úsáidfear teimpléid"
 
-#: builtin/clone.c builtin/submodule--helper.c
 msgid "reference repository"
 msgstr "stór tagartha"
 
-#: builtin/clone.c builtin/submodule--helper.c
 msgid "use --reference only while cloning"
 msgstr "bain úsáid as --reference amháin agus tú ag clónú"
 
-#: 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 "ainm"
 
-#: builtin/clone.c
 msgid "use <name> instead of 'origin' to track upstream"
 msgstr "úsáid in <name> ionad 'origin' chun suas an sruth a rianú"
 
-#: builtin/clone.c
 msgid "checkout <branch> instead of the remote's HEAD"
 msgstr "seiceáil <brainse> in ionad CEAD an iargúlta"
 
-#: builtin/clone.c
 msgid "clone single revision <rev> and check out"
 msgstr "clónáil athbhreithniú aonair <rev> agus seiceáil amach"
 
-#: builtin/clone.c
 msgid "path to git-upload-pack on the remote"
 msgstr "cosán chuig git-upload-pack ar an gcianrialtán"
 
-#: builtin/clone.c builtin/fetch.c builtin/pull.c
 msgid "depth"
 msgstr "doimhneacht"
 
-#: builtin/clone.c
 msgid "create a shallow clone of that depth"
 msgstr "clón éadomhain den doimhneacht sin a chruthú"
 
-#: builtin/clone.c
 msgid "create a shallow clone since a specific time"
 msgstr "clón éadrom a chruthú ó am ar leith"
 
-#: builtin/clone.c builtin/fetch.c builtin/pull.c
 msgid "ref"
 msgstr "tagairt"
 
-#: builtin/clone.c builtin/fetch.c builtin/pull.c
 msgid "deepen history of shallow clone, excluding ref"
 msgstr "stair an chlóin éadomhain a dhoimhniú, gan tagairt"
 
-#: builtin/clone.c builtin/submodule--helper.c
 msgid "clone only one branch, HEAD or --branch"
 msgstr "clóin ach brainse amháin, HEAD nó --branch"
 
-#: builtin/clone.c
 msgid "clone tags, and make later fetches not to follow them"
 msgstr "clibeanna clóin, agus tógáil níos déanaí a dhéanamh gan iad a leanúint"
 
-#: builtin/clone.c
 msgid "any cloned submodules will be shallow"
 msgstr "beidh aon fho-mhodúil clónaithe éadrom"
 
-#: builtin/clone.c builtin/init-db.c
 msgid "gitdir"
 msgstr "gitdir"
 
-#: builtin/clone.c builtin/init-db.c
 msgid "separate git dir from working tree"
 msgstr "git dir ar leithligh ó chrann oibre"
 
-#: builtin/clone.c builtin/init-db.c builtin/submodule--helper.c
 msgid "specify the reference format to use"
 msgstr "sonraigh an fhormáid tagartha le húsáid"
 
-#: builtin/clone.c
 msgid "key=value"
 msgstr "eochair=luach"
 
-#: builtin/clone.c
 msgid "set config inside the new repository"
 msgstr "socraigh cumraíocht taobh istigh den stór nua"
 
-#: builtin/clone.c builtin/fetch.c builtin/ls-remote.c builtin/pull.c
-#: builtin/push.c builtin/send-pack.c
 msgid "server-specific"
 msgstr "freastalaí-shonrach"
 
-#: builtin/clone.c builtin/fetch.c builtin/ls-remote.c builtin/pull.c
-#: builtin/push.c builtin/send-pack.c
 msgid "option to transmit"
 msgstr "rogha a tharchur"
 
-#: builtin/clone.c
 msgid "apply partial clone filters to submodules"
 msgstr "cuir scagairí clóin páirteacha i bhfeidhm"
 
-#: builtin/clone.c
 msgid "any cloned submodules will use their remote-tracking branch"
 msgstr "úsáidfidh aon fho-mhodúil clónaithe a mbrainse cianrianaithe"
 
-#: builtin/clone.c
 msgid "initialize sparse-checkout file to include only files at root"
 msgstr ""
 "comhad seiceála neamhchoitianta a thosú chun comhaid amháin a áireamh ag "
 "fréamh"
 
-#: builtin/clone.c
 msgid "uri"
 msgstr "uri"
 
-#: builtin/clone.c
 msgid "a URI for downloading bundles before fetching from origin remote"
 msgstr ""
 "a URI chun cuachtaí a íoslódáil sula n-iarrtar iad ó chianchéim tionscnaimh"
 
-#: builtin/clone.c
 msgid "git clone [<options>] [--] <repo> [<dir>]"
 msgstr "git clone [<roghanna>] [--] <stóras>[<eolaire>]"
 
-#: builtin/clone.c
 msgid "Too many arguments."
 msgstr "An iomarca argóintí."
 
-#: builtin/clone.c scalar.c
 msgid "You must specify a repository to clone."
 msgstr "Ní mór duit stór a shonrú le clónú."
 
-#: builtin/clone.c builtin/init-db.c builtin/refs.c builtin/submodule--helper.c
-#: setup.c
 #, c-format
 msgid "unknown ref storage format '%s'"
 msgstr "formáid stórála tagartha anaithnid '%s'"
 
-#: builtin/clone.c
 #, c-format
 msgid "repository '%s' does not exist"
 msgstr "níl an stóras '%s' ann"
 
-#: builtin/clone.c builtin/fetch.c
 #, c-format
 msgid "depth %s is not a positive number"
 msgstr "ní uimhir dhearfach é doimhneacht %s"
 
-#: builtin/clone.c
 #, c-format
 msgid "destination path '%s' already exists and is not an empty directory."
 msgstr "tá cosán ceann scríbe '%s' ann cheana féin agus ní eolaire folamh é."
 
-#: builtin/clone.c
 #, c-format
 msgid "repository path '%s' already exists and is not an empty directory."
 msgstr "tá cosán stórais '%s' ann cheana féin agus ní eolaire folamh é."
 
-#: builtin/clone.c
 #, c-format
 msgid "working tree '%s' already exists."
 msgstr "tá crann oibre '%s' ann cheana féin."
 
-#: builtin/clone.c builtin/difftool.c builtin/log.c builtin/worktree.c
 #, c-format
 msgid "could not create leading directories of '%s'"
 msgstr "ní fhéadfaí eolairí tosaigh de '%s' a chruthú"
 
-#: builtin/clone.c
 #, c-format
 msgid "could not create work tree dir '%s'"
 msgstr "ní fhéadfaí crann oibre a chruthú dir '%s'"
 
-#: builtin/clone.c
 #, c-format
 msgid "Cloning into bare repository '%s'...\n"
 msgstr "Clónáil isteach i stóras lom '%s'...\n"
 
-#: builtin/clone.c
 #, c-format
 msgid "Cloning into '%s'...\n"
 msgstr "Clónáil isteach '%s'...\n"
 
-#: builtin/clone.c
 msgid ""
 "clone --recursive is not compatible with both --reference and --reference-if-"
 "able"
 msgstr ""
 "níl clón --recursive comhoiriúnach le --reference agus --reference-if-able"
 
-#: builtin/clone.c builtin/remote.c
 #, c-format
 msgid "'%s' is not a valid remote name"
 msgstr "Ní ainm iargúlta bailí é '%s'"
 
-#: builtin/clone.c
 msgid "--depth is ignored in local clones; use file:// instead."
 msgstr ""
 "--depth déantar neamhaird de i gclóin áitiúla; bain úsáid as comhad:// ina "
 "ionad."
 
-#: builtin/clone.c
 msgid "--shallow-since is ignored in local clones; use file:// instead."
 msgstr ""
 "--shallow-since déantar neamhaird de i gclóin áitiúla; bain úsáid as file:// "
 "ina ionad."
 
-#: builtin/clone.c
 msgid "--shallow-exclude is ignored in local clones; use file:// instead."
 msgstr ""
 "--shallow-exclude déantar neamhaird de i gclóin áitiúla; bain úsáid as "
 "file:// ina ionad."
 
-#: builtin/clone.c
 msgid "--filter is ignored in local clones; use file:// instead."
 msgstr ""
 "--filter déantar neamhaird de i gclóin áitiúla; bain úsáid as file:// ina "
 "ionad."
 
-#: builtin/clone.c fetch-pack.c
 msgid "source repository is shallow, reject to clone."
 msgstr "tá stóras foinse éadrom, diúltaigh clóin."
 
-#: builtin/clone.c
 msgid "source repository is shallow, ignoring --local"
 msgstr "tá stóras foinse éadrom, ag neamhaird a dhéanamh ar --local"
 
-#: builtin/clone.c
 msgid "--local is ignored"
 msgstr "--local déantar neamhaird de"
 
-#: builtin/clone.c
 msgid "cannot clone from filtered bundle"
 msgstr "ní féidir clónú ó bhearta scagtha"
 
-#: builtin/clone.c
 msgid "failed to initialize the repo, skipping bundle URI"
 msgstr "theip ar an repo a thionscnamh, ag scipeáil URI beartán"
 
-#: builtin/clone.c
 #, c-format
 msgid "failed to fetch objects from bundle URI '%s'"
 msgstr "theip ar rudaí a fháil ó URI '%s'"
 
-#: builtin/clone.c
 msgid "failed to fetch advertised bundles"
 msgstr "theip orthu beartáin fógraithe a fháil"
 
-#: builtin/clone.c
 msgid "remote transport reported error"
 msgstr "earráid tuairiscithe ar iompar"
 
-#: builtin/clone.c
 #, c-format
 msgid "Remote branch %s not found in upstream %s"
 msgstr "Níor aimsíodh brainse iargúlta %s i suas sruth %s"
 
-#: builtin/clone.c
 #, c-format
 msgid "Remote revision %s not found in upstream %s"
 msgstr "Ní aimsíodh athbhreithniú iargúlta %s i suas sruth %s"
 
-#: builtin/clone.c
 msgid "You appear to have cloned an empty repository."
 msgstr "Is cosúil gur chlónaigh tú stór folamh."
 
-#: builtin/column.c
 msgid "git column [<options>]"
-msgstr "colún git [<options>]"
+msgstr "git column [<options>]"
 
-#: builtin/column.c
 msgid "lookup config vars"
 msgstr "earraí cumraíochta cuardaigh"
 
-#: builtin/column.c
 msgid "layout to use"
 msgstr "leagan amach le húsáid"
 
-#: builtin/column.c
 msgid "maximum width"
 msgstr "leithead uasta"
 
-#: builtin/column.c
 msgid "padding space on left border"
 msgstr "spás padding ar an teorainn chlé"
 
-#: builtin/column.c
 msgid "padding space on right border"
 msgstr "spás padding ar an teorainn dheis"
 
-#: builtin/column.c
 msgid "padding space between columns"
 msgstr "spás padding idir colúin"
 
-#: builtin/column.c
 #, c-format
 msgid "%s must be non-negative"
 msgstr "Caithfidh %s a bheith neamh-diúltach"
 
-#: builtin/column.c
 msgid "--command must be the first argument"
 msgstr "Ní mór gurb é --command an chéad argóint"
 
-#: builtin/commit-graph.c
 msgid ""
 "git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]"
 msgstr ""
 "git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]"
 
-#: builtin/commit-graph.c
 msgid ""
 "git commit-graph write [--object-dir <dir>] [--append]\n"
 "                       [--split[=<strategy>]] [--reachable | --stdin-packs | "
@@ -5679,168 +4581,129 @@
 "[no-]progress]\n"
 "                       <split-options>"
 
-#: builtin/commit-graph.c builtin/fetch.c builtin/gc.c builtin/log.c
-#: builtin/repack.c
 msgid "dir"
 msgstr "redir"
 
-#: builtin/commit-graph.c
 msgid "the object directory to store the graph"
 msgstr "an eolaire réada chun an graf a stóráil"
 
-#: builtin/commit-graph.c
 msgid "if the commit-graph is split, only verify the tip file"
 msgstr "má tá an graf coimite scoilte, ní fhíoraigh ach an comhad leid"
 
-#: builtin/commit-graph.c
 #, c-format
 msgid "Could not open commit-graph '%s'"
 msgstr "Níor féidir graf coimisiúnaithe '%s' a oscailt"
 
-#: builtin/commit-graph.c
 #, c-format
 msgid "could not open commit-graph chain '%s'"
 msgstr "ní fhéadfaí slabhra coimisi-graf '%s' a oscailt"
 
-#: builtin/commit-graph.c
 #, c-format
 msgid "unrecognized --split argument, %s"
 msgstr "argóint --split gan aithint, %s"
 
-#: builtin/commit-graph.c
 #, c-format
 msgid "unexpected non-hex object ID: %s"
 msgstr "id réada neamh-heicsidheachúlach gan choinne: %s"
 
-#: builtin/commit-graph.c
 #, c-format
 msgid "invalid object: %s"
 msgstr "réad neamhbhailí: %s"
 
-#: builtin/commit-graph.c parse-options-cb.c
 #, c-format
 msgid "option `%s' expects a numerical value"
 msgstr "tá rogha `%s' ag súil le luach uimhriúil"
 
-#: builtin/commit-graph.c
 msgid "start walk at all refs"
 msgstr "tosú ag siúl ag gach ceann"
 
-#: builtin/commit-graph.c
 msgid "scan pack-indexes listed by stdin for commits"
 msgstr ""
 "scanadh innéacsanna pacáiste atá liostaithe ag stdin le haghaidh gealltanais"
 
-#: builtin/commit-graph.c
 msgid "start walk at commits listed by stdin"
 msgstr "tosú ag siúl ag gealltanais atá liostaithe ag stdin"
 
-#: builtin/commit-graph.c
 msgid "include all commits already in the commit-graph file"
 msgstr ""
 "áireamh na gealltanais go léir cheana féin sa chomhad gráf coimisiúnaithe"
 
-#: builtin/commit-graph.c
 msgid "enable computation for changed paths"
 msgstr "ríomh a chumasú le haghaidh cosáin athraithe"
 
-#: builtin/commit-graph.c
 msgid "allow writing an incremental commit-graph file"
 msgstr "ligean comhad gráf choimisiúnaithe a scríobh"
 
-#: builtin/commit-graph.c
 msgid "maximum number of commits in a non-base split commit-graph"
 msgstr "uaslíon na ngealltanais i ngráf coiste scoilte neamh-bhonn"
 
-#: builtin/commit-graph.c
 msgid "maximum ratio between two levels of a split commit-graph"
 msgstr "cóimheas uasta idir dhá leibhéal de ghraf coimiste scoilte"
 
-#: builtin/commit-graph.c
 msgid "only expire files older than a given date-time"
 msgstr "ní rachaidh in éag ach comhaid níos sine ná dáta-am ar leith"
 
-#: builtin/commit-graph.c
 msgid "maximum number of changed-path Bloom filters to compute"
 msgstr "líon uasta scagairí Bloom cosáin athraithe le ríomh"
 
-#: builtin/commit-graph.c
 msgid "use at most one of --reachable, --stdin-commits, or --stdin-packs"
 msgstr ""
 "bain úsáid as ceann de --reachable, --stdin-commits, nó --stdin-packs ar a "
 "mhéad"
 
-#: builtin/commit-graph.c
 msgid "Collecting commits from input"
 msgstr "Gealltanais a bhailiú ó ionchur"
 
-#: builtin/commit-tree.c
 msgid "git commit-tree <tree> [(-p <parent>)...]"
-msgstr "<parent>git commit-tree <tree>[(-p)...]"
+msgstr "git commit-tree <tree> [(-p <parent>)...]"
 
-#: builtin/commit-tree.c
 msgid ""
 "git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n"
 "                [(-F <file>)...] <tree>"
 msgstr ""
-"<parent>git commit-tree [(-p)...] [-S [<keyid>]] [(-m<message>)...]\n"
-" [(-F<file>)...] <tree>"
+"git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n"
+"                [(-F <file>)...] <tree>"
 
-#: builtin/commit-tree.c
 #, c-format
 msgid "duplicate parent %s ignored"
 msgstr "neamhaird déanta ar thuismitheoir dúblach %s"
 
-#: builtin/commit-tree.c builtin/log.c
 #, c-format
 msgid "not a valid object name %s"
 msgstr "ní ainm réad bailí %s"
 
-#: builtin/commit-tree.c
 #, c-format
 msgid "git commit-tree: failed to read '%s'"
 msgstr "git commit-tree: theip ar '%s' a léamh"
 
-#: builtin/commit-tree.c
 #, c-format
 msgid "git commit-tree: failed to close '%s'"
 msgstr "git commit-tree: theip ar '%s' a dhúnadh"
 
-#: builtin/commit-tree.c
 msgid "parent"
 msgstr "tuismitheoir"
 
-#: builtin/commit-tree.c
 msgid "id of a parent commit object"
 msgstr "id réad tiomanta tuismitheora"
 
-#: builtin/commit-tree.c builtin/commit.c builtin/merge.c builtin/notes.c
-#: builtin/stash.c builtin/tag.c
 msgid "message"
 msgstr "teachtaireacht"
 
-#: builtin/commit-tree.c builtin/commit.c
 msgid "commit message"
 msgstr "teachtaireacht a thabhairt"
 
-#: builtin/commit-tree.c
 msgid "read commit log message from file"
 msgstr "léigh teachtaireacht logála tiomanta ón gcomhad"
 
-#: builtin/commit-tree.c builtin/commit.c builtin/merge.c builtin/pull.c
-#: builtin/revert.c
 msgid "GPG sign commit"
 msgstr "Tiomantas comhartha GPG"
 
-#: builtin/commit-tree.c
 msgid "must give exactly one tree"
 msgstr "caithfidh crann amháin a thabhairt go díreach"
 
-#: builtin/commit-tree.c
 msgid "git commit-tree: failed to read"
 msgstr "git commit-tree: theip ar léamh"
 
-#: builtin/commit.c
 msgid ""
 "git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n"
 "           [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|"
@@ -5862,11 +4725,9 @@
 "           [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n"
 "           [--] [<pathspec>...]"
 
-#: builtin/commit.c
 msgid "git status [<options>] [--] [<pathspec>...]"
-msgstr "stádas git [<options>] [--] [<pathspec>...]"
+msgstr "git status [<options>] [--] [<pathspec>...]"
 
-#: builtin/commit.c
 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"
@@ -5877,7 +4738,6 @@
 "leat\n"
 "bain an tiomantas go hiomlán le “git reset HEAD^”.\n"
 
-#: builtin/commit.c
 msgid ""
 "The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
 "If you wish to commit it anyway, use:\n"
@@ -5892,15 +4752,12 @@
 "    git commit --allow-empty\n"
 "\n"
 
-#: builtin/commit.c
 msgid "Otherwise, please use 'git rebase --skip'\n"
 msgstr "Seachas sin, bain úsáid as 'git rebase --skip'\n"
 
-#: builtin/commit.c
 msgid "Otherwise, please use 'git cherry-pick --skip'\n"
 msgstr "Seachas sin, bain úsáid as 'git cherry-pick --skip'\n"
 
-#: builtin/commit.c
 msgid ""
 "and then use:\n"
 "\n"
@@ -5921,123 +4778,96 @@
 "\n"
 " git cherry-pick --skip\n"
 
-#: builtin/commit.c read-cache.c
 msgid "updating files failed"
 msgstr "theip ar nuashonrú comhaid"
 
-#: builtin/commit.c
 msgid "failed to unpack HEAD tree object"
 msgstr "theip orthu réad crann HEAD a dhíphacáil"
 
-#: builtin/commit.c
 msgid "No paths with --include/--only does not make sense."
 msgstr "Níl ciall ag aon chosáin le --include/--only."
 
-#: builtin/commit.c
 msgid "unable to create temporary index"
-msgstr "in ann innéacs sealadach a chruthú"
+msgstr "ní féidir innéacs sealadach a chruthú"
 
-#: builtin/commit.c
 msgid "interactive add failed"
 msgstr "theip ar chur idirghníomh"
 
-#: builtin/commit.c
 msgid "unable to update temporary index"
-msgstr "in ann innéacs sealadach a nuashonrú"
+msgstr "ní féidir an t-innéacs sealadach a nuashonrú"
 
-#: builtin/commit.c
 msgid "Failed to update main cache tree"
 msgstr "Theip ar phríomhchrann taisce a nuashonrú"
 
-#: builtin/commit.c
 msgid "cannot do a partial commit during a merge."
 msgstr "ní féidir le tiomantas páirteach a dhéanamh le linn cumaisc."
 
-#: builtin/commit.c
 msgid "cannot do a partial commit during a cherry-pick."
 msgstr "ní féidir le tiomantas páirteach a dhéanamh le linn pioc silíní."
 
-#: builtin/commit.c
 msgid "cannot do a partial commit during a rebase."
 msgstr "ní féidir le tiomantas páirteach a dhéanamh le linn athbhunaithe."
 
-#: builtin/commit.c
 msgid "cannot read the index"
 msgstr "ní féidir leis an innéacs a léamh"
 
-#: builtin/commit.c
 msgid "unable to write temporary index file"
-msgstr "in ann comhad innéacs sealadach a scríobh"
+msgstr "ní féidir comhad innéacs sealadach a scríobh"
 
-#: builtin/commit.c
 #, c-format
 msgid "commit '%s' lacks author header"
 msgstr "níl ceannteideal údair ag comhoiriú '%s'"
 
-#: builtin/commit.c
 #, c-format
 msgid "commit '%s' has malformed author line"
 msgstr "comtal tá líne údair mífhoirmithe ag '%s'"
 
-#: builtin/commit.c
 msgid "malformed --author parameter"
 msgstr "paraiméadar --author mífhoirmithe"
 
-#: builtin/commit.c ident.c
 #, c-format
 msgid "invalid date format: %s"
 msgstr "formáid dáta neamhbhailí: %s"
 
-#: builtin/commit.c
 msgid ""
 "unable to select a comment character that is not used\n"
 "in the current commit message"
 msgstr ""
-"nach féidir carachtar tráchta a roghnú nach n-úsáidtear\n"
-"sa teachtaireacht tiomanta reatha"
+"ní féidir carachtar tráchta nach bhfuil in úsáid \n"
+"sa teachtaireacht tiomantais reatha a roghnú"
 
-#: builtin/commit.c
 #, c-format
 msgid "could not lookup commit '%s'"
 msgstr "ní fhéadfaí cuardach a dhéanamh ar '%s'"
 
-#: builtin/commit.c builtin/shortlog.c
 #, c-format
 msgid "(reading log message from standard input)\n"
 msgstr "(teachtaireacht log a léamh ó ionchur caighdeánach)\n"
 
-#: builtin/commit.c
 msgid "could not read log from standard input"
 msgstr "ní raibh in ann log a léamh ó ionchur caighdeánach"
 
-#: builtin/commit.c
 #, c-format
 msgid "could not read log file '%s'"
 msgstr "ní raibh in ann comhad logála '%s' a léamh"
 
-#: builtin/commit.c
 #, c-format
 msgid "options '%s' and '%s:%s' cannot be used together"
 msgstr "ní féidir roghanna '%s' agus '%s: %s' a úsáid le chéile"
 
-#: builtin/commit.c
 msgid "could not read SQUASH_MSG"
 msgstr "ní raibh in ann SQUASH_MSG a léamh"
 
-#: builtin/commit.c
 msgid "could not read MERGE_MSG"
 msgstr "ní raibh in ann MERGE_MSG a léamh"
 
-#: builtin/commit.c bundle.c rerere.c sequencer.c
 #, c-format
 msgid "could not open '%s'"
 msgstr "ní fhéadfaí '%s' a oscailt"
 
-#: builtin/commit.c
 msgid "could not write commit template"
 msgstr "ní raibh sé in ann teimpléad tiomanta a"
 
-#: builtin/commit.c
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -6047,7 +4877,6 @@
 "tosú\n"
 "déanfar neamhaird le '%s'.\n"
 
-#: builtin/commit.c
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -6058,7 +4887,6 @@
 "déanfar neamhaird le '%s', agus déanfar teachtaireacht folamh deireadh leis "
 "an tiomantas.\n"
 
-#: builtin/commit.c
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -6068,7 +4896,6 @@
 "tosú\n"
 "coimeádfar le '%s'; féadfaidh tú iad a bhaint féin más mian leat.\n"
 
-#: builtin/commit.c
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -6080,7 +4907,6 @@
 "coimeádfar le '%s'; féadfaidh tú iad a bhaint féin más mian leat.\n"
 "Déanann teachtaireacht folamh deireadh leis an tiomantas.\n"
 
-#: builtin/commit.c
 msgid ""
 "\n"
 "It looks like you may be committing a merge.\n"
@@ -6094,7 +4920,6 @@
 "git update-ref -d MERGE_HEAD\n"
 "agus déan iarracht arís.\n"
 
-#: builtin/commit.c
 msgid ""
 "\n"
 "It looks like you may be committing a cherry-pick.\n"
@@ -6108,143 +4933,112 @@
 "\tgit update-ref -d CHERRY_PICK_HEAD\n"
 "agus déan iarracht arís.\n"
 
-#: builtin/commit.c
 #, c-format
 msgid "%sAuthor:    %.*s <%.*s>"
 msgstr "%sÚdar:    %.*s <%.*s>"
 
-#: builtin/commit.c
 #, c-format
 msgid "%sDate:      %s"
 msgstr "%sDáta: %s"
 
-#: builtin/commit.c
 #, c-format
 msgid "%sCommitter: %.*s <%.*s>"
 msgstr "%sCeannasaí: %.*s <%.*s>"
 
-#: builtin/commit.c
 msgid "Cannot read index"
 msgstr "Ní féidir innéacs a léamh"
 
-#: builtin/commit.c builtin/tag.c
 msgid "unable to pass trailers to --trailers"
-msgstr "nach féidir leantóirí a chur chuig --trailers"
+msgstr "ní féidir trailers a thabhairt do --trailers"
 
-#: builtin/commit.c
 msgid "Error building trees"
 msgstr "Earráid ag tógáil crainn"
 
-#: builtin/commit.c builtin/tag.c
 #, c-format
 msgid "Please supply the message using either -m or -F option.\n"
 msgstr ""
 "Soláthair an teachtaireacht le do thoil ag baint úsáide as rogha -m nó -F.\n"
 
-#: builtin/commit.c
 #, c-format
 msgid "--author '%s' is not 'Name <email>' and matches no existing author"
 msgstr ""
 "Ní 'Ainm' é --author '%s' agus ní mheaitseálann <email>aon údar atá ann "
 "cheana"
 
-#: builtin/commit.c
 #, c-format
 msgid "Invalid ignored mode '%s'"
 msgstr "Modh neamhbhailí neamhaird '%s'"
 
-#: builtin/commit.c
 #, c-format
 msgid "Invalid untracked files mode '%s'"
 msgstr "Modh comhaid neamhrianaithe neamhbhailí '%s'"
 
-#: builtin/commit.c
 msgid "You are in the middle of a merge -- cannot reword."
 msgstr "Tá tú i lár cumaisc - ní féidir athfhocal a athfhocal."
 
-#: builtin/commit.c
 msgid "You are in the middle of a cherry-pick -- cannot reword."
 msgstr "Tá tú i lár pioc silíní - ní féidir athfhocal a athfhocal."
 
-#: builtin/commit.c
 #, c-format
 msgid "reword option of '%s' and path '%s' cannot be used together"
 msgstr "ní féidir rogha athfhocal de '%s' agus cosán '%s' a úsáid le chéile"
 
-#: builtin/commit.c
 #, c-format
 msgid "reword option of '%s' and '%s' cannot be used together"
 msgstr "ní féidir rogha athfhocal de '%s' agus '%s' a úsáid le chéile"
 
-#: builtin/commit.c
 msgid "You have nothing to amend."
 msgstr "Níl aon rud le leasú agat."
 
-#: builtin/commit.c
 msgid "You are in the middle of a merge -- cannot amend."
 msgstr "Tá tú i lár cumaisc - ní féidir leat leasú."
 
-#: builtin/commit.c
 msgid "You are in the middle of a cherry-pick -- cannot amend."
 msgstr "Tá tú i lár rogha silíní - ní féidir leat leasú."
 
-#: builtin/commit.c
 msgid "You are in the middle of a rebase -- cannot amend."
 msgstr "Tá tú i lár athbhunaithe - ní féidir leat leasú."
 
-#: builtin/commit.c
 msgid "--reset-author can be used only with -C, -c or --amend."
 msgstr "Ní féidir --reset-author a úsáid ach le -C, -c nó --amend."
 
-#: builtin/commit.c
 #, c-format
 msgid "unknown option: --fixup=%s:%s"
 msgstr "rogha anaithnid: --fixup=%s:%s"
 
-#: builtin/commit.c
 #, c-format
 msgid "paths '%s ...' with -a does not make sense"
 msgstr "ní chiallaíonn cosáin '%s... 'le -a"
 
-#: builtin/commit.c
 msgid "show status concisely"
 msgstr "taispeáin stádas go hachomair"
 
-#: builtin/commit.c
 msgid "show branch information"
 msgstr "taispeáin faisnéis bhrainse"
 
-#: builtin/commit.c
 msgid "show stash information"
 msgstr "taispeáin faisnéis stash"
 
-#: builtin/commit.c
 msgid "compute full ahead/behind values"
 msgstr "luachanna iomlána/taobh thiar de na luachanna a ríomh"
 
-#: builtin/commit.c
 msgid "version"
 msgstr "leagan"
 
-#: builtin/commit.c builtin/fetch.c builtin/push.c builtin/worktree.c
 msgid "machine-readable output"
 msgstr "aschur inléite meaisín"
 
-#: builtin/commit.c
 msgid "show status in long format (default)"
 msgstr "stádas taispeáint i bhformáid fhada (réamhshocraithe)"
 
-#: builtin/commit.c
 msgid "terminate entries with NUL"
 msgstr "foirceannadh na hiontrálacha"
 
-#: builtin/commit.c
 msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
 msgstr ""
 "taispeáin comhaid neamhrianaithe, modhanna roghnacha: gach, gnáth, níl. "
 "(Réamhshocraithe: gach)"
 
-#: builtin/commit.c
 msgid ""
 "show ignored files, optional modes: traditional, matching, no. (Default: "
 "traditional)"
@@ -6252,11 +5046,9 @@
 "taispeáint comhaid neamhaird orthu, modhanna roghnacha: traidisiúnta, "
 "meaitseáil, (Réamhshocraithe: traidisiúnta)"
 
-#: builtin/commit.c parse-options.h
 msgid "when"
 msgstr "nuair a"
 
-#: builtin/commit.c
 msgid ""
 "ignore changes to submodules, optional when: all, dirty, untracked. "
 "(Default: all)"
@@ -6264,197 +5056,151 @@
 "neamhaird a dhéanamh ar athruithe ar fho-mhodúil, roghnach nuair a bhíonn: "
 "gach, salach, gan rianú. (Réamhshocraithe: gach)"
 
-#: builtin/commit.c
 msgid "list untracked files in columns"
 msgstr "liostáil comhaid neamhrianaithe i gcolúin"
 
-#: builtin/commit.c
 msgid "do not detect renames"
 msgstr "ná athainmneacha a bhrath"
 
-#: builtin/commit.c
 msgid "detect renames, optionally set similarity index"
 msgstr "athainmneacha a bhrath, innéacs cosúlachta a shocrú go ro"
 
-#: builtin/commit.c
 msgid "Unsupported combination of ignored and untracked-files arguments"
 msgstr "Teaglaim gan tacaíocht d'argóintí comhaid a neamhaird agus gan rianú"
 
-#: builtin/commit.c
 msgid "suppress summary after successful commit"
 msgstr "achoimre a chur faoi chois tar éis tiomantas"
 
-#: builtin/commit.c
 msgid "show diff in commit message template"
 msgstr "taispeáin diff i teimpléad teachtaireachta tiomanta"
 
-#: builtin/commit.c
 msgid "Commit message options"
 msgstr "Tiomanta roghanna teachtaire"
 
-#: builtin/commit.c builtin/merge.c builtin/tag.c
 msgid "read message from file"
 msgstr "léigh teachtaireacht ón gcomhad"
 
-#: builtin/commit.c
 msgid "author"
 msgstr "údar"
 
-#: builtin/commit.c
 msgid "override author for commit"
 msgstr "an t-údar a shárú le haghaidh tiomantas"
 
-#: builtin/commit.c builtin/gc.c
 msgid "date"
 msgstr "dáta"
 
-#: builtin/commit.c
 msgid "override date for commit"
 msgstr "dáta athsháraithe le haghaidh tiomanta"
 
-#: builtin/commit.c parse-options.h ref-filter.h
 msgid "commit"
 msgstr "tiomantas"
 
-#: builtin/commit.c
 msgid "reuse and edit message from specified commit"
 msgstr "teachtaireacht a athúsáid agus a chur in eagar ó thiomantas"
 
-#: builtin/commit.c
 msgid "reuse message from specified commit"
 msgstr "teachtaireacht athúsáid ó thiomantas sonraithe"
 
 #. TRANSLATORS: Leave "[(amend|reword):]" as-is,
 #. and only translate <commit>.
 #.
-#: builtin/commit.c
 msgid "[(amend|reword):]commit"
 msgstr "[(leaso|athfhocal):] comhartha"
 
-#: builtin/commit.c
 msgid ""
 "use autosquash formatted message to fixup or amend/reword specified commit"
 msgstr ""
 "úsáid teachtaireacht fhormáidithe autosquash chun gealltanas sonraithe a "
 "shocrú nó a leasú/athfhocal"
 
-#: builtin/commit.c
 msgid "use autosquash formatted message to squash specified commit"
 msgstr ""
 "úsáid teachtaireacht fhormáidithe autosquash chun tiomantas sonraithe squash"
 
-#: builtin/commit.c
 msgid "the commit is authored by me now (used with -C/-c/--amend)"
 msgstr "tá an gealltanas údar agam anois (úsáidtear le -C/-c/--amend)"
 
-#: builtin/commit.c builtin/interpret-trailers.c builtin/tag.c
 msgid "trailer"
 msgstr "leantóir"
 
-#: builtin/commit.c builtin/tag.c
 msgid "add custom trailer(s)"
 msgstr "cuir leantóir (í) saincheaptha"
 
-#: builtin/commit.c builtin/log.c builtin/merge.c builtin/pull.c
-#: builtin/revert.c
 msgid "add a Signed-off-by trailer"
 msgstr "cuir leantóir sínithe as"
 
-#: builtin/commit.c
 msgid "use specified template file"
 msgstr "úsáid comhad teimpléad sonraithe"
 
-#: builtin/commit.c
 msgid "force edit of commit"
 msgstr "eagarthóireacht fórsa ar thiomantas"
 
-#: builtin/commit.c
 msgid "include status in commit message template"
 msgstr "áireamh stádas i dteimpléad teachtaireachta"
 
-#: builtin/commit.c
 msgid "Commit contents options"
 msgstr "Tiomnaigh roghanna ábhair"
 
-#: builtin/commit.c
 msgid "commit all changed files"
 msgstr "gach comhad athraithe a thiomnú"
 
-#: builtin/commit.c
 msgid "add specified files to index for commit"
 msgstr "cuir comhaid sonraithe leis an innéacs le haghaidh tiomanta"
 
-#: builtin/commit.c
 msgid "interactively add files"
 msgstr "cuir comhaid idirghníomhach"
 
-#: builtin/commit.c
 msgid "interactively add changes"
 msgstr "cuir athruithe idirghníomhach"
 
-#: builtin/commit.c
 msgid "commit only specified files"
 msgstr "ach comhaid shonraithe a dhéanamh"
 
-#: builtin/commit.c
 msgid "bypass pre-commit and commit-msg hooks"
 msgstr "seachbhóthar crúcaí réamh-thiomanta agus comh-msg"
 
-#: builtin/commit.c
 msgid "show what would be committed"
 msgstr "taispeáint cad a bheadh tiomanta"
 
-#: builtin/commit.c
 msgid "amend previous commit"
 msgstr "leasú a leasú"
 
-#: builtin/commit.c
 msgid "bypass post-rewrite hook"
 msgstr "seachbhóthar crúca iar-athsc"
 
-#: builtin/commit.c
 msgid "ok to record an empty change"
 msgstr "ceart go leor chun athrú folamh a thaifeadadh"
 
-#: builtin/commit.c
 msgid "ok to record a change with an empty message"
 msgstr "ceart go leor chun athrú a thaifeadadh le teachtaireacht folamh"
 
-#: builtin/commit.c sequencer.c
 msgid "could not parse HEAD commit"
 msgstr "ní fhéadfadh sé gealltanas HEAD a pharsáil"
 
-#: builtin/commit.c
 #, c-format
 msgid "Corrupt MERGE_HEAD file (%s)"
 msgstr "Comhad truaillithe MERGE_HEAD (%s)"
 
-#: builtin/commit.c
 msgid "could not read MERGE_MODE"
 msgstr "ní raibh in ann MERGE_MODE a léamh"
 
-#: builtin/commit.c
 #, c-format
 msgid "could not read commit message: %s"
 msgstr "ní féidir teachtaireacht tiomanta a léamh: %s"
 
-#: builtin/commit.c
 #, c-format
 msgid "Aborting commit due to empty commit message.\n"
 msgstr "Tiomantas a ghabháil mar gheall ar theachtaireacht tiomanta folamh\n"
 
-#: builtin/commit.c
 #, c-format
 msgid "Aborting commit; you did not edit the message.\n"
 msgstr "Tiomantas a ghearradh; níor chuir tú an teachtaireacht in eagar.\n"
 
-#: builtin/commit.c
 #, c-format
 msgid "Aborting commit due to empty commit message body.\n"
 msgstr ""
 "Tiomantas a ghabháil mar gheall ar chorp teachtaireachta tiomanta folamh.\n"
 
-#: builtin/commit.c
 msgid ""
 "repository has been updated, but unable to write\n"
 "new index file. Check that disk is not full and quota is\n"
@@ -6465,220 +5211,176 @@
 "lán agus nach bhfuil an cuóta sáraithe, agus ansin \"git restore --staged :/"
 "\" chun é a aisghabháil."
 
-#: builtin/config.c
 msgid "git config list [<file-option>] [<display-option>] [--includes]"
 msgstr "liosta config git [<file-option>] [<display-option>] [--include]"
 
-#: builtin/config.c
 msgid ""
 "git config get [<file-option>] [<display-option>] [--includes] [--all] [--"
-"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>"
+"regexp] [--value=<pattern>] [--fixed-value] [--default=<default>] [--"
+"url=<url>] <name>"
 msgstr ""
-"<value><default>git config a fháil [<file-option>] [] [--include<display-"
-"option>] [--all] [--regexp] [--value=] [--luach seasta] [--default=] <name>"
+"git config get [<file-option>] [<display-option>] [--includes] [--all] [--"
+"regexp] [--value=<pattern>] [--fixed-value] [--default=<default>] [--"
+"url=<url>] <name>"
 
-#: builtin/config.c
 msgid ""
-"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--"
-"fixed-value] <name> <value>"
+"git config set [<file-option>] [--type=<type>] [--all] [--value=<pattern>] "
+"[--fixed-value] <name> <value>"
 msgstr ""
-"<value>git config set [<file-option>] [--type =] [--all] [--value=<type>] [--"
-"luach seasta] <name><value>"
+"git config set [<file-option>] [--type=<type>] [--all] [--value=<pattern>] "
+"[--fixed-value] <name> <value>"
 
-#: builtin/config.c
 msgid ""
-"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] "
+"git config unset [<file-option>] [--all] [--value=<pattern>] [--fixed-value] "
 "<name>"
 msgstr ""
-"<value>git config gan socrú [] [--gach<file-option>] [--value=] [--luach "
-"seasta] <name>"
+"git config unset [<file-option>] [--all] [--value=<pattern>] [--fixed-value] "
+"<name>"
 
-#: builtin/config.c
 msgid "git config rename-section [<file-option>] <old-name> <new-name>"
 msgstr "<file-option>roinn athainmnithe git config [] <old-name><new-name>"
 
-#: builtin/config.c
 msgid "git config remove-section [<file-option>] <name>"
 msgstr "<file-option>roinn aistrithe git config [] <name>"
 
-#: builtin/config.c
 msgid "git config edit [<file-option>]"
-msgstr "<file-option>Eagarthóireacht config git []"
+msgstr "git config edit [<file-option>]"
 
-#: builtin/config.c
 msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]"
-msgstr "<name><stdout-is-tty>git config [<file-option>] --get-colorbool []"
+msgstr "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]"
 
-#: builtin/config.c
 msgid ""
 "git config get [<file-option>] [<display-option>] [--includes] [--all] [--"
-"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] "
+"regexp=<regexp>] [--value=<pattern>] [--fixed-value] [--default=<default>] "
 "<name>"
 msgstr ""
-"<value><default>git config a fháil [<file-option>] [] [--include<display-"
-"option>] [--all] [--regexp=] [-- <regexp>value=] [--luach seasta] [--"
-"default=] <name>"
+"git config get [<file-option>] [<display-option>] [--includes] [--all] [--"
+"regexp=<regexp>] [--value=<pattern>] [--fixed-value] [--default=<default>] "
+"<name>"
 
-#: builtin/config.c
 msgid ""
 "git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] "
-"[--value=<value>] [--fixed-value] <name> <value>"
+"[--value=<pattern>] [--fixed-value] <name> <value>"
 msgstr ""
-"<value>git config set [<file-option>] [--type =] [--comment =<type>] [--all] "
-"[--value=<message>] [--luach seasta] <name><value>"
+"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] "
+"[--value=<pattern>] [--fixed-value] <name> <value>"
 
-#: builtin/config.c
 msgid "Config file location"
 msgstr "Suíomh comhad Config"
 
-#: builtin/config.c
 msgid "use global config file"
 msgstr "bain úsáid as comhad cumraíochta domhanda"
 
-#: builtin/config.c
 msgid "use system config file"
 msgstr "bain úsáid as comhad cumraíochta córais"
 
-#: builtin/config.c
 msgid "use repository config file"
 msgstr "bain úsáid as comhad cumraíochta stórais"
 
-#: builtin/config.c
 msgid "use per-worktree config file"
 msgstr "bain úsáid as comhad cumraíochta in aghaidh an chrann oibre"
 
-#: builtin/config.c builtin/gc.c
 msgid "use given config file"
 msgstr "bain úsáid as comhad cumraíochta tugtha"
 
-#: builtin/config.c
 msgid "blob-id"
 msgstr "blob-id"
 
-#: builtin/config.c
 msgid "read config from given blob object"
 msgstr "léigh cumraíocht ó réad blob a thugtar"
 
-#: builtin/config.c
 msgid "Type"
 msgstr "Cineál"
 
-#: builtin/config.c builtin/hash-object.c
 msgid "type"
 msgstr "cineál"
 
-#: builtin/config.c
 msgid "value is given this type"
 msgstr "tugtar luach an cineál seo"
 
-#: builtin/config.c
 msgid "value is \"true\" or \"false\""
 msgstr "tá luach “fíor” nó “bréagach”"
 
-#: builtin/config.c
 msgid "value is decimal number"
 msgstr "is é luach uimhir deachúil"
 
-#: builtin/config.c
 msgid "value is --bool or --int"
 msgstr "is é luach --bool nó --int"
 
-#: builtin/config.c
 msgid "value is --bool or string"
 msgstr "is é luach --bool nó teaghrán"
 
-#: builtin/config.c
 msgid "value is a path (file or directory name)"
 msgstr "is cosán é luach (ainm comhad nó eolaire)"
 
-#: builtin/config.c
 msgid "value is an expiry date"
 msgstr "is dáta éaga é luach"
 
-#: builtin/config.c
 msgid "Display options"
 msgstr "Roghanna taispeána"
 
-#: builtin/config.c
 msgid "terminate values with NUL byte"
 msgstr "foirceannadh luachanna le nóta NUL"
 
-#: builtin/config.c
 msgid "show variable names only"
 msgstr "taispeáin ainmneacha athróg amháin"
 
-#: builtin/config.c
 msgid "show origin of config (file, standard input, blob, command line)"
 msgstr ""
 "taispeáint bunús an chumraíochta (comhad, ionchur caighdeánach, blob, líne "
 "ordaithe)"
 
-#: builtin/config.c
 msgid "show scope of config (worktree, local, global, system, command)"
 msgstr ""
 "taispeáin raon feidhme an chumraíochta (crann oibre, áitiúil, domhanda, "
 "córas, ordú)"
 
-#: builtin/config.c
 msgid "show config keys in addition to their values"
 msgstr "taispeáin eochracha cumraithe i dteannta lena luachanna"
 
-#: builtin/config.c
 #, c-format
 msgid "unrecognized --type argument, %s"
 msgstr "argóint --type gan aithint, %s"
 
-#: builtin/config.c
 msgid "only one type at a time"
 msgstr "ach cineál amháin ag an am"
 
-#: builtin/config.c
 #, c-format
 msgid "wrong number of arguments, should be %d"
 msgstr "líon mícheart na n-argóintí, ba chóir go mbeadh %d"
 
-#: builtin/config.c
 #, c-format
 msgid "wrong number of arguments, should be from %d to %d"
 msgstr "ba chóir go mbeadh líon mícheart na n-argóintí ó %d go %d"
 
-#: builtin/config.c
 #, c-format
 msgid "invalid key pattern: %s"
 msgstr "patrún eochair neamhbhailí: %s"
 
-#: builtin/config.c config.c
 #, c-format
 msgid "invalid pattern: %s"
 msgstr "patrún neamhbhailí: %s"
 
-#: builtin/config.c
 #, c-format
 msgid "failed to format default config value: %s"
 msgstr "theip ar luach cumraíochta réamhshocraithe a fhormáidiú: %s"
 
-#: builtin/config.c
 #, c-format
 msgid "cannot parse color '%s'"
 msgstr "ní féidir dath '%s' a pháirseáil"
 
-#: builtin/config.c
 msgid "unable to parse default color value"
-msgstr "in ann luach dath réamhshocraithe a pharsáil"
+msgstr "ní féidir luach datha réamhshocraithe a pharsáil"
 
-#: builtin/config.c
 msgid "not in a git directory"
 msgstr "nach bhfuil i eolaire git"
 
-#: builtin/config.c
 msgid "writing to stdin is not supported"
 msgstr "ní thacaítear le scríobh chuig stdin"
 
-#: builtin/config.c
 msgid "writing config blobs is not supported"
 msgstr "ní thacaítear le blobs cumraíochta a scríobh"
 
-#: builtin/config.c
 #, c-format
 msgid ""
 "# This is Git's per-user configuration file.\n"
@@ -6693,27 +5395,21 @@
 "#\tainm = %s\n"
 "#\tríomhphost = %s\n"
 
-#: builtin/config.c
 msgid "only one config file at a time"
 msgstr "ach comhad cumraithe amháin ag an am"
 
-#: builtin/config.c
 msgid "--local can only be used inside a git repository"
 msgstr "Ní féidir --local a úsáid ach taobh istigh de stór git"
 
-#: builtin/config.c
 msgid "--blob can only be used inside a git repository"
 msgstr "Ní féidir --blob a úsáid ach taobh istigh de stór git"
 
-#: builtin/config.c
 msgid "--worktree can only be used inside a git repository"
 msgstr "Ní féidir --worktree a úsáid ach taobh istigh de stór git"
 
-#: builtin/config.c builtin/gc.c
 msgid "$HOME not set"
 msgstr "Níl $HOME socraithe"
 
-#: builtin/config.c
 msgid ""
 "--worktree cannot be used with multiple working trees unless the config\n"
 "extension worktreeConfig is enabled. Please read \"CONFIGURATION FILE\"\n"
@@ -6724,99 +5420,76 @@
 "Tá síneadh WorkTreeConfig cumasaithe. Léigh “COMHAD CUMRAÍOCHTA”\n"
 "roinn i “git help worktree” le haghaidh sonraí"
 
-#: builtin/config.c
 msgid "Other"
 msgstr "Eile"
 
-#: builtin/config.c
 msgid "respect include directives on lookup"
 msgstr "meas lena n-áirítear treoracha maidir le cuardach"
 
-#: builtin/config.c
 #, c-format
 msgid "unable to read config file '%s'"
-msgstr "nach féidir an comhad cumraithe '%s' a léamh"
+msgstr "ní féidir an comhad cumraíochta '%s' a léamh"
 
-#: builtin/config.c
 msgid "error processing config file(s)"
 msgstr "comhad (í) cumraíochta próiseála earráide"
 
-#: builtin/config.c
 msgid "Filter options"
 msgstr "Roghanna scagaire"
 
-#: builtin/config.c
 msgid "return all values for multi-valued config options"
 msgstr ""
 "gach luach a thabhairt ar ais le haghaidh roghanna cumraithe illuachmhara"
 
-#: builtin/config.c
 msgid "interpret the name as a regular expression"
 msgstr "léirmhíniú an t-ainm mar abairt rialta"
 
-#: builtin/config.c
 msgid "show config with values matching the pattern"
 msgstr "taispeáin cumraíocht le luachanna a mheaitseann an phatrún"
 
-#: builtin/config.c
 msgid "use string equality when comparing values to value pattern"
 msgstr "bain úsáid as comhionannas sreangán agus luachanna á gcomparáid"
 
-#: builtin/config.c
 msgid "URL"
 msgstr "URL"
 
-#: builtin/config.c
 msgid "show config matching the given URL"
 msgstr "taispeáin configí a mheaitseáil leis an URL tugtha"
 
-#: builtin/config.c
 msgid "value"
 msgstr "luach"
 
-#: builtin/config.c
 msgid "use default value when missing entry"
 msgstr "bain úsáid as luach réamhshocraithe agus iontráil"
 
-#: builtin/config.c
 msgid "--fixed-value only applies with 'value-pattern'"
 msgstr "Ní bhaineann --fixed-value ach le 'patrún luacha'"
 
-#: builtin/config.c
 msgid "--default= cannot be used with --all or --url="
 msgstr "Ní féidir --default= a úsáid le --all nó --url ="
 
-#: builtin/config.c
 msgid "--url= cannot be used with --all, --regexp or --value"
 msgstr "Ní féidir --url = a úsáid le --all, --regexp nó --value"
 
-#: builtin/config.c
 msgid "Filter"
 msgstr "Scagaire"
 
-#: builtin/config.c
 msgid "replace multi-valued config option with new value"
 msgstr "luach nua a chur in ionad rogha cumraíochta illuachmhara"
 
-#: builtin/config.c
 msgid "human-readable comment string (# will be prepended as needed)"
 msgstr ""
 "teaghrán tráchtaireachta inléite don duine (déanfar # a ullmhú de réir mar "
 "is gá)"
 
-#: builtin/config.c
 msgid "add a new line without altering any existing values"
 msgstr "líne nua a chur leis gan aon luachanna atá ann cheana a athrú"
 
-#: builtin/config.c
 msgid "--fixed-value only applies with --value=<pattern>"
 msgstr "ní bhaineann --fixed-value ach le --value=<pattern>"
 
-#: builtin/config.c
 msgid "--append cannot be used with --value=<pattern>"
 msgstr "Ní féidir --append a úsáid le --value=<pattern>"
 
-#: builtin/config.c
 #, c-format
 msgid ""
 "cannot overwrite multiple values with a single value\n"
@@ -6825,101 +5498,77 @@
 "ní féidir luachanna iolracha a fhorscríobh le luach amháin\n"
 " Úsáid regexp, --add nó --replace-all chun %s a athrú."
 
-#: builtin/config.c
 #, c-format
 msgid "no such section: %s"
 msgstr "gan aon chuid den sórt sin: %s"
 
-#: builtin/config.c
 msgid "editing stdin is not supported"
 msgstr "ní thacaítear le stdin eagarthóireachta"
 
-#: builtin/config.c
 msgid "editing blobs is not supported"
 msgstr "ní thacaítear le blobs eagarthóireachta"
 
-#: builtin/config.c
 #, c-format
 msgid "cannot create configuration file %s"
 msgstr "ní féidir comhad cumraíochta %s a chruthú"
 
-#: builtin/config.c
 msgid "Action"
 msgstr "Gníomhaíocht"
 
-#: builtin/config.c
 msgid "get value: name [<value-pattern>]"
 msgstr "luach a fháil: ainm [<value-pattern>]"
 
-#: builtin/config.c
 msgid "get all values: key [<value-pattern>]"
 msgstr "faigh na luachanna go léir: eochair [<value-pattern>]"
 
-#: builtin/config.c
 msgid "get values for regexp: name-regex [<value-pattern>]"
 msgstr "<value-pattern>luachanna a fháil do regexp: ainm-regex []"
 
-#: builtin/config.c
 msgid "get value specific for the URL: section[.var] URL"
 msgstr "faigh luach sonrach don URL: rannán [.var] URL"
 
-#: builtin/config.c
 msgid "replace all matching variables: name value [<value-pattern>]"
 msgstr "athróg meaitseála go léir in ionad: luach ainm [<value-pattern>]"
 
-#: builtin/config.c
 msgid "add a new variable: name value"
 msgstr "cuir athróg nua leis: luach ainm"
 
-#: builtin/config.c
 msgid "remove a variable: name [<value-pattern>]"
 msgstr "bhaint athróg: ainm [<value-pattern>]"
 
-#: builtin/config.c
 msgid "remove all matches: name [<value-pattern>]"
 msgstr "bhaint gach cluiche: ainm [<value-pattern>]"
 
-#: builtin/config.c
 msgid "rename section: old-name new-name"
 msgstr "athainmnigh an chuid: sean-ainm nua-ainm"
 
-#: builtin/config.c
 msgid "remove a section: name"
 msgstr "cuid a bhaint: ainm"
 
-#: builtin/config.c
 msgid "list all"
 msgstr "liostáil go léir"
 
-#: builtin/config.c
 msgid "open an editor"
 msgstr "eagarthóir a oscailt"
 
-#: builtin/config.c
 msgid "find the color configured: slot [<default>]"
 msgstr "faigh an dath cumraithe: sliotán [<default>]"
 
-#: builtin/config.c
 msgid "find the color setting: slot [<stdout-is-tty>]"
 msgstr "faigh an socrú dath: sliotán [<stdout-is-tty>]"
 
-#: builtin/config.c
 msgid "with --get, use default value when missing entry"
 msgstr "le --get, bain úsáid as luach réamhshocraithe agus iontráil in easnamh"
 
-#: builtin/config.c
 msgid "--get-color and variable type are incoherent"
 msgstr "Tá --get-color agus cineál athraitheach neamhchomhtháite"
 
-#: builtin/config.c
 msgid "no action specified"
 msgstr "aon ghníomh sonraithe"
 
-#: builtin/config.c
 msgid "--name-only is only applicable to --list or --get-regexp"
 msgstr "Níl --name-only infheidhme ach le --list nó --get-regexp"
 
-#: builtin/config.c
 msgid ""
 "--show-origin is only applicable to --get, --get-all, --get-regexp, and --"
 "list"
@@ -6927,20 +5576,16 @@
 "Níl --show-origin infheidhme ach le --get, --get-all, --get-regexp, agus --"
 "list"
 
-#: builtin/config.c
 msgid "--default is only applicable to --get"
 msgstr "Níl --default infheidhme ach le --get"
 
-#: builtin/config.c
 msgid "--comment is only applicable to add/set/replace operations"
 msgstr ""
 "Níl --comment infheidhme ach le hoibríochtaí a chur leis /socraí/athsholáthar"
 
-#: builtin/count-objects.c
 msgid "print sizes in human readable format"
 msgstr "méideanna priontála i bhformáid inléite don duine"
 
-#: builtin/credential-cache--daemon.c
 #, c-format
 msgid ""
 "The permissions on your socket directory are too loose; other\n"
@@ -6954,79 +5599,63 @@
 "\n"
 " chmod 0700 %s"
 
-#: builtin/credential-cache--daemon.c
 msgid "print debugging messages to stderr"
 msgstr "teachtaireachtaí dífhabhtaithe a phriontáil chuig stderr"
 
-#: builtin/credential-cache--daemon.c
 msgid "credential-cache--daemon unavailable; no unix socket support"
 msgstr "credential-cache--daemon ar fáil; gan aon tacaíocht soicéad unix"
 
-#: builtin/credential-cache.c
 msgid "credential-cache unavailable; no unix socket support"
 msgstr "taisce creidiúnaithe ar fáil; gan aon tacaíocht soicéad unix"
 
-#: builtin/credential-store.c
 #, c-format
 msgid "unable to get credential storage lock in %d ms"
-msgstr "in ann glas stórála creidiúnaithe a fháil in %d ms"
+msgstr "ní féidir glas stórála dintiúir a fháil i %d ms"
 
-#: builtin/describe.c
 msgid ""
 "git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]"
 msgstr ""
 "git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]"
 
-#: builtin/describe.c
 msgid ""
 "git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]"
 msgstr ""
 "git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]"
 
-#: builtin/describe.c
 msgid "git describe <blob>"
-msgstr "git cur síos <blob>"
+msgstr "git describe <blob>"
 
-#: builtin/describe.c
 msgid "head"
-msgstr "ceann"
+msgstr "head"
 
-#: builtin/describe.c
 msgid "lightweight"
 msgstr "éadrom"
 
-#: builtin/describe.c
 msgid "annotated"
 msgstr "anótáilte"
 
-#: builtin/describe.c
 #, c-format
 msgid "annotated tag %s not available"
 msgstr "níl clib anótáilte %s ar fáil"
 
-#: builtin/describe.c
 #, c-format
 msgid "tag '%s' is externally known as '%s'"
 msgstr "tugtar '%s' ar an gclib '%s' go seachtrach"
 
-#: builtin/describe.c
 #, c-format
 msgid "no tag exactly matches '%s'"
 msgstr "níl aon chlib ag teacht go díreach le '%s'"
 
-#: builtin/describe.c
 #, c-format
 msgid "No exact match on refs or tags, searching to describe\n"
 msgstr ""
 "Níl aon mheaitseáil cruinn ar thaifeanna nó clibeanna, ag cuardach chun cur "
 "síos\n"
 
-#: builtin/describe.c
 #, c-format
 msgid "finished search at %s\n"
 msgstr "cuardach críochnaithe ag %s\n"
 
-#: builtin/describe.c
 #, c-format
 msgid ""
 "No annotated tags can describe '%s'.\n"
@@ -7035,7 +5664,6 @@
 "Ní féidir le haon chlibeanna anótaithe cur síos a dhéanamh ar '%s'.\n"
 "Mar sin féin, bhí clibeanna gan anótáil ann: triail as --tags."
 
-#: builtin/describe.c
 #, c-format
 msgid ""
 "No tags can describe '%s'.\n"
@@ -7044,242 +5672,199 @@
 "Ní féidir le clibeanna cur síos a dhéanamh ar '%s'.\n"
 "Bain triail as --always, nó cruthaigh roinnt clibeanna."
 
-#: builtin/describe.c
 #, c-format
 msgid "traversed %lu commits\n"
 msgstr "gealltanais %lu a thrasnaíodh\n"
 
-#: builtin/describe.c
 #, c-format
 msgid "found %i tags; gave up search at %s\n"
 msgstr "fuarthas %i clibeanna; thréig an cuardach ag %s\n"
 
-#: builtin/describe.c
+#, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "ní féidir cuardach a dhéanamh ar bloba '%s' ar bhrainse neamhbheirthe"
+
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "ni féidir teacht ar an blob '%s' ó HEAD"
+
 #, c-format
 msgid "describe %s\n"
 msgstr "déan cur síos ar %s\n"
 
-#: builtin/describe.c
 #, c-format
 msgid "Not a valid object name %s"
 msgstr "Ní ainm réad bailí %s"
 
-#: builtin/describe.c
 #, c-format
 msgid "%s is neither a commit nor blob"
 msgstr "Ní gealltanas ná blob é %s"
 
-#: builtin/describe.c
 msgid "find the tag that comes after the commit"
 msgstr "faigh an chlib a thagann tar éis an tiomanta"
 
-#: builtin/describe.c
 msgid "debug search strategy on stderr"
 msgstr "straitéis cuardaigh dífhabhtú ar stderr"
 
-#: builtin/describe.c
 msgid "use any ref"
 msgstr "bain úsáid as aon tagairt"
 
-#: builtin/describe.c
 msgid "use any tag, even unannotated"
 msgstr "úsáid aon chlib, fiú gan anótáil"
 
-#: builtin/describe.c
 msgid "always use long format"
 msgstr "úsáid formáid fada i gcónaí"
 
-#: builtin/describe.c
 msgid "only follow first parent"
 msgstr "lean ach an chéad thuismitheoir"
 
-#: builtin/describe.c
 msgid "only output exact matches"
 msgstr "ach cluichí cruinne aschuir"
 
-#: builtin/describe.c
 msgid "consider <n> most recent tags (default: 10)"
 msgstr "machnamh <n>ar na clibeanna is déanaí (réamhshocraithe: 10)"
 
-#: builtin/describe.c
 msgid "only consider tags matching <pattern>"
 msgstr "ní mheas ach meaitseáil clibeanna <pattern>"
 
-#: builtin/describe.c
 msgid "do not consider tags matching <pattern>"
 msgstr "ná smaoinigh ar mheaitseáil clibeanna <pattern>"
 
-#: builtin/describe.c builtin/name-rev.c
 msgid "show abbreviated commit object as fallback"
 msgstr "taispeáint réad tiomanta giorraithe mar fhilleadh"
 
-#: builtin/describe.c
 msgid "mark"
 msgstr "marc"
 
-#: builtin/describe.c
 msgid "append <mark> on dirty working tree (default: \"-dirty\")"
 msgstr "cuir isteach <mark>ar chrann oibre salach (réamhshocraithe: “-salach”)"
 
-#: builtin/describe.c
 msgid "append <mark> on broken working tree (default: \"-broken\")"
 msgstr "cuir isteach <mark>ar chrann oibre briste (réamhshocraithe: “-broken”)"
 
-#: builtin/describe.c
 msgid "No names found, cannot describe anything."
 msgstr ""
 "Níor aimsíodh aon ainmneacha, ní féidir cur síos a dhéanamh ar aon rud."
 
-#: builtin/describe.c
 #, c-format
 msgid "option '%s' and commit-ishes cannot be used together"
 msgstr "ní féidir rogha '%s' agus coimistí a úsáid le chéile"
 
-#: builtin/diagnose.c
 msgid ""
 "git diagnose [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
 "             [--mode=<mode>]"
 msgstr ""
-"<format>git diagnosis [(-o | --output-directory)] [(-s | -- <path>suffix)]\n"
-" <mode>[--mód =]"
+"git diagnose [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"             [--mode=<mode>]"
 
-#: builtin/diagnose.c
 msgid "specify a destination for the diagnostics archive"
 msgstr "sonraigh ceann scríbe don chartlann diagnóisic"
 
-#: builtin/diagnose.c
 msgid "specify a strftime format suffix for the filename"
 msgstr "sonraigh iarmhír formáid strftime don ainm comhaid"
 
-#: builtin/diagnose.c
 msgid "specify the content of the diagnostic archive"
 msgstr "sonraigh ábhar an chartlann dhiagnóiseach"
 
-#: builtin/diff-pairs.c
 #, c-format
 msgid "unable to parse mode: %s"
-msgstr "nach féidir modh a pháirseáil: %s"
+msgstr "ní féidir an modh parsála a dhéanamh: %s"
 
-#: builtin/diff-pairs.c
 #, c-format
 msgid "unable to parse object id: %s"
-msgstr "nach féidir id réad a pháirseáil: %s"
+msgstr "ní féidir aitheantas an réada a pharsáil: %s"
 
-#: builtin/diff-pairs.c
 msgid "git diff-pairs -z [<diff-options>]"
 msgstr "git diff-pairs -z [<diff-options>]"
 
-#: builtin/diff-pairs.c builtin/log.c builtin/replay.c builtin/shortlog.c
-#: bundle.c
 #, c-format
 msgid "unrecognized argument: %s"
 msgstr "argóint gan aithint: %s"
 
-#: builtin/diff-pairs.c
 msgid "working without -z is not supported"
 msgstr "ní thacaítear le bheith ag obair gan -z"
 
-#: builtin/diff-pairs.c
 msgid "pathspec arguments not supported"
 msgstr "argóintí pathspec nach dtacaítear leis"
 
-#: builtin/diff-pairs.c
 msgid "revision arguments not allowed"
 msgstr "argóintí athbhreithnithe nach"
 
-#: builtin/diff-pairs.c
 msgid "invalid raw diff input"
 msgstr "ionchur diff amh neamhbhailí"
 
-#: builtin/diff-pairs.c
 msgid "tree objects not supported"
 msgstr "rudaí crann nach dtacaítear leis"
 
-#: builtin/diff-pairs.c
 msgid "got EOF while reading path"
 msgstr "fuair EOF agus tú ag léamh cosán"
 
-#: builtin/diff-pairs.c
 msgid "got EOF while reading destination path"
 msgstr "fuair EOF agus tú ag léamh cosán ceann scríbe"
 
-#: builtin/diff-pairs.c
 #, c-format
 msgid "unable to parse rename/copy score: %s"
-msgstr "nach féidir scór athainmniú/cóipeáil a pháirseáil: %s"
+msgstr "ní féidir an scór a athainmniú/a chóipeáil a pharsáil: %s"
 
-#: builtin/diff-pairs.c
 #, c-format
 msgid "unknown diff status: %c"
 msgstr "stádas diff anaithnid: %c"
 
-#: builtin/diff-tree.c
 msgid "--merge-base only works with two commits"
 msgstr "Ní oibríonn --merge-base ach le dhá thiomantas"
 
-#: builtin/diff.c
 #, c-format
 msgid "'%s': not a regular file or symlink"
 msgstr "'%s': ní comhad rialta nó comhnasc"
 
-#: builtin/diff.c
 msgid "no merge given, only parents."
 msgstr "ní thugtar aon chumasc, tuismitheoirí amháin."
 
-#: builtin/diff.c
 #, c-format
 msgid "invalid option: %s"
 msgstr "rogha neamhbhailí: %s"
 
-#: builtin/diff.c
 #, c-format
 msgid "%s...%s: no merge base"
 msgstr "%s... %s: gan aon bhonn cumaisc"
 
-#: builtin/diff.c
-msgid "Not a git repository"
-msgstr "Ní stór git"
+msgid "cannot come back to cwd"
+msgstr "ní féidir teacht ar ais chuig cwd"
 
-#: builtin/diff.c builtin/grep.c
+msgid "Not a git repository"
+msgstr "Ní stór git é"
+
 #, c-format
 msgid "invalid object '%s' given."
 msgstr "réad neamhbhailí '%s' tugtha."
 
-#: builtin/diff.c
 #, c-format
 msgid "more than two blobs given: '%s'"
 msgstr "níos mó ná dhá bhlob a thugtar: '%s'"
 
-#: builtin/diff.c
 #, c-format
 msgid "unhandled object '%s' given."
 msgstr "réad neamh-láimhseáilte '%s' tugtha."
 
-#: builtin/diff.c
 #, c-format
 msgid "%s...%s: multiple merge bases, using %s"
 msgstr "%s... %s: bonn cumaisc iolracha, ag baint úsáide as %s"
 
-#: builtin/difftool.c
 msgid "git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"
 msgstr "git difftool [[<options>]] <commit>[[<commit>]] [--] [<path>...]"
 
-#: builtin/difftool.c
 #, c-format
 msgid "could not read symlink %s"
 msgstr "ní fhéadfaí nasc simtéarach %s a léamh"
 
-#: builtin/difftool.c
 #, c-format
 msgid "could not read symlink file %s"
 msgstr "ní raibh in ann comhad simnasc %s a léamh"
 
-#: builtin/difftool.c
 #, c-format
 msgid "could not read object %s for symlink %s"
 msgstr "ní raibh in ann réad %s a léamh le haghaidh nasc simtéarach %s"
 
-#: builtin/difftool.c
 msgid ""
 "combined diff formats ('-c' and '--cc') are not supported in\n"
 "directory diff mode ('-d' and '--dir-diff')."
@@ -7287,63 +5872,49 @@
 "ní thacaítear le formáidí diff comhcheangailte ('-c' agus '--cc') i\n"
 "modh diff eolaire ('-d' agus '--dir-diff')."
 
-#: builtin/difftool.c
 #, c-format
 msgid "both files modified: '%s' and '%s'."
 msgstr "modhnaigh an dá chomhad: '%s' agus '%s'."
 
-#: builtin/difftool.c
 msgid "working tree file has been left."
 msgstr "tá comhad crann oibre fágtha."
 
-#: builtin/difftool.c sequencer.c
 #, c-format
 msgid "could not copy '%s' to '%s'"
 msgstr "ní fhéadfaí '%s' a chóipeáil chuig '%s'"
 
-#: builtin/difftool.c
 #, c-format
 msgid "temporary files exist in '%s'."
 msgstr "tá comhaid shealadacha ann i '%s'."
 
-#: builtin/difftool.c
 msgid "you may want to cleanup or recover these."
 msgstr "b'fhéidir gur mhaith leat iad seo a ghlanadh nó a aisghabháil."
 
-#: builtin/difftool.c
 #, c-format
 msgid "failed: %d"
 msgstr "theip ar: %d"
 
-#: builtin/difftool.c
 msgid "use `diff.guitool` instead of `diff.tool`"
 msgstr "bain úsáid as `diff.guitool` in ionad `diff.tool`"
 
-#: builtin/difftool.c
 msgid "perform a full-directory diff"
 msgstr "éagsúlacht eolaire lán-eolaire a dhéanamh"
 
-#: builtin/difftool.c
 msgid "do not prompt before launching a diff tool"
 msgstr "ná spreag sula seolann tú uirlis diff"
 
-#: builtin/difftool.c
 msgid "use symlinks in dir-diff mode"
 msgstr "bain úsáid as naisc siombailte i mód dir-diff"
 
-#: builtin/difftool.c
 msgid "tool"
 msgstr "uirlis"
 
-#: builtin/difftool.c
 msgid "use the specified diff tool"
 msgstr "bain úsáid as an uirlis diff sonraithe"
 
-#: builtin/difftool.c
 msgid "print a list of diff tools that may be used with `--tool`"
 msgstr "liosta d'uirlisí diff is féidir a úsáid le `--tool` a phriontáil"
 
-#: builtin/difftool.c
 msgid ""
 "make 'git-difftool' exit when an invoked diff tool returns a non-zero exit "
 "code"
@@ -7351,240 +5922,744 @@
 "imeacht 'git-difftool' a dhéanamh nuair a fhilleann uirlis diff a ghairmtear "
 "cód imeachta neamh-nialasach"
 
-#: builtin/difftool.c
 msgid "specify a custom command for viewing diffs"
 msgstr "sonraigh ordú saincheaptha chun féachaint ar dhifríochtaí"
 
-#: builtin/difftool.c
 msgid "passed to `diff`"
 msgstr "cuireadh chuig `diff`"
 
-#: builtin/difftool.c
 msgid "difftool requires worktree or --no-index"
 msgstr "éilíonn difftool crann oibre nó --no-index"
 
-#: builtin/difftool.c
 msgid "no <tool> given for --tool=<tool>"
 msgstr "níl aon tu <tool> gadh le haghaidh --tool=<tool>"
 
-#: builtin/difftool.c
 msgid "no <cmd> given for --extcmd=<cmd>"
 msgstr "níl <cmd> tugtha do --extcmd=<cmd>"
 
-#: builtin/fast-export.c
 msgid "git fast-export [<rev-list-opts>]"
 msgstr "git fast-export [<rev-list-opts>]"
 
-#: builtin/fast-export.c
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
-msgstr ""
-"Earráid: Ní féidir clibeanna neadaithe a onnmhairiú mura sonraítear --mark-"
-"tags."
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "mód %s anaithnid: %s"
 
-#: builtin/fast-export.c
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "clib anaithnid den mhodh scagtha: %s"
+
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "samhlacha ionchódaithe anaithnid: %s"
+
+#, c-format
+msgid "could not read blob %s"
+msgstr "níorbh fhéidir bloba %s a léamh"
+
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "mí-oiriúnacht oid i mblob %s"
+
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "níorbh fhéidir bloba '%s' a scríobh"
+
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "stádas comparáide gan choinne '%c' do %s, %s"
+
+msgid "none"
+msgstr "níl aon"
+
+#, c-format
+msgid "could not find author in commit %s"
+msgstr "níorbh fhéidir an t-údar a aimsiú i dtiomantas %s"
+
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "níorbh fhéidir an tiomnóir a aimsiú i dtiomnadh %s"
+
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
+msgstr ""
+"thángthas ar ionchódú sonrach don tiomantas %.*s i dtiomantas %s; bain úsáid "
+"as --reencode=[yes|no] chun é a láimhseáil"
+
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr ""
+"bhuail an tiomantas sínithe %s; bain úsáid as --signed-commits=<mode> chun é "
+"a láimhseáil"
+
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr "ag easpórtáil %<PRIuMAX> sínithe le haghaidh tiomnú %s"
+
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr "ag baint sínithe ó thiomnadh %s"
+
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+"ag fágáil an chlib %s ar lár, ós rud é nach dtacaítear le clibeanna crainn "
+"(nó clibeanna de chlibeanna crainn, srl.)."
+
+#, c-format
+msgid "could not read tag %s"
+msgstr "níorbh fhéidir an clib %s a léamh"
+
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr ""
+"bhuail mé le clib shínithe %s; bain úsáid as --signed-tags=<mode> chun é a "
+"láimhseáil"
+
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "clib shínithe %s á onnmhairiú"
+
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "ag baint síniú ón gclib %s"
+
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr ""
+"clibeanna %s réad neamh-onnmhairithe; bain úsáid as --tag-of-filtered-"
+"object=<mode> chun é a láimhseáil"
+
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr ""
+"ní féidir clibeanna neadaithe a easpórtáil mura sonraítear --mark-tags."
+
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "clib %s pointí in áit ar bith?"
+
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "%s: réad gan choinne de chineál %s, ag scipeáil."
+
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr ""
+"tá an clib ag pointeáil chuig réad den chineál gan choinne %s, ag scipeáil."
+
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "ní féidir comhad marcanna %s a oscailt le haghaidh scríbhneoireachta."
+
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "ní féidir comhad marcanna %s a scríobh."
+
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "líne marcála truaillithe: %s"
+
+#, c-format
+msgid "object not found: %s"
+msgstr "níor aimsíodh réad: %s"
+
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "nach tiomantas é? ní féidir tarlú: %s"
+
+#, c-format
+msgid "object %s already has a mark"
+msgstr "tá marc ar réad %s cheana féin"
+
 msgid "--anonymize-map token cannot be empty"
 msgstr "Ní féidir le comhartha --anonymize-map a bheith folamh"
 
-#: builtin/fast-export.c
 msgid "show progress after <n> objects"
 msgstr "dhul chun cinn a thaispe <n>áint"
 
-#: builtin/fast-export.c
 msgid "select handling of signed tags"
 msgstr "roghnaigh láimhseáil na clibeanna"
 
-#: builtin/fast-export.c
 msgid "select handling of signed commits"
 msgstr "roghnaigh láimhseáil tiomantas sínithe"
 
-#: builtin/fast-export.c
 msgid "select handling of tags that tag filtered objects"
 msgstr "roghnaigh láimhseáil clibeanna a ligeann rudaí"
 
-#: builtin/fast-export.c
 msgid "select handling of commit messages in an alternate encoding"
 msgstr "roghnaigh láimhseáil teachtaireachtaí tiomanta i ionchódú"
 
-#: builtin/fast-export.c
 msgid "dump marks to this file"
 msgstr "marcanna dumpáil chuig an gcomhad seo"
 
-#: builtin/fast-export.c
 msgid "import marks from this file"
 msgstr "marcanna iompórtáil ón gcomhad seo"
 
-#: builtin/fast-export.c
 msgid "import marks from this file if it exists"
 msgstr "marcanna a iompórtáil ón gcomhad seo má tá sé ann"
 
-#: builtin/fast-export.c
 msgid "fake a tagger when tags lack one"
 msgstr "clibeoir bréige nuair nach bhfuil ceann ag clibeanna"
 
-#: builtin/fast-export.c
 msgid "output full tree for each commit"
 msgstr "aschur crann iomlán do gach tiomantas"
 
-#: builtin/fast-export.c
 msgid "use the done feature to terminate the stream"
 msgstr "úsáid an ghné déanta chun an sruth a fhoirceannadh"
 
-#: builtin/fast-export.c
 msgid "skip output of blob data"
 msgstr "scipeáil aschur sonraí blob"
 
-#: builtin/fast-export.c builtin/log.c
 msgid "refspec"
 msgstr "refspec"
 
-#: builtin/fast-export.c
 msgid "apply refspec to exported refs"
 msgstr "refspec a chur i bhfeidhm ar thaifeanna onnmhair"
 
-#: builtin/fast-export.c
 msgid "anonymize output"
 msgstr "aschur gan ainm"
 
-#: builtin/fast-export.c
 msgid "from:to"
 msgstr "ó:go"
 
-#: builtin/fast-export.c
 msgid "convert <from> to <to> in anonymized output"
 msgstr "tiontaigh <from>go <to>in aschur gan ainm"
 
-#: builtin/fast-export.c
 msgid "reference parents which are not in fast-export stream by object id"
 msgstr ""
 "tuismitheoirí tagartha nach bhfuil i sruth tapa onnmhairithe de réir id réad"
 
-#: builtin/fast-export.c
 msgid "show original object ids of blobs/commits"
 msgstr "taispeáin id réad bunaidh de bhlobanna/gealltanna"
 
-#: builtin/fast-export.c
 msgid "label tags with mark ids"
 msgstr "clibeanna lipéad le id marc"
 
-#: builtin/fast-import.c
 #, c-format
-msgid "Missing from marks for submodule '%s'"
-msgstr "Ar iarraidh ó mharcanna don fho-mhodúl '%s'"
+msgid "can't write crash report %s"
+msgstr "ní féidir tuarascáil tuairteála %s a scríobh"
 
-#: builtin/fast-import.c
 #, c-format
-msgid "Missing to marks for submodule '%s'"
-msgstr "Ar iarraidh marcanna don fho-mhodúl '%s'"
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "allmhairiú-tapa: ag dumpáil tuarascáil tuairteála chuig %s\n"
 
-#: builtin/fast-import.c
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "Táthar ag súil leis an ordú 'marc', fuair %s"
+msgid "mark :%<PRIuMAX> not declared"
+msgstr "marc :%<PRIuMAX> gan dearbhú"
 
-#: builtin/fast-import.c
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "Táthar ag súil leis an ordú 'to', fuair %s"
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "iarracht neamhbhailí chun brainse dúblach a chruthú: %s"
 
-#: builtin/fast-import.c
-msgid "Expected format name:filename for submodule rewrite option"
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "ní chomhlíonann ainm na brainse caighdeáin Git: %s"
+
+msgid "internal consistency error creating the index"
+msgstr "earráid chomhsheasmhachta inmheánaí agus an t-innéacs á chruthú"
+
+msgid "cannot create keep file"
+msgstr "ní féidir comhad coimeádta a chruthú"
+
+msgid "failed to write keep file"
+msgstr "theip ar an gcomhad keep a scríobh"
+
+msgid "cannot store pack file"
+msgstr "ní féidir comhad an phacáiste a stóráil"
+
+msgid "cannot store index file"
+msgstr "ní féidir comhad innéacs a stóráil"
+
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "theip ar chuardach tús '%s'"
+
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "innéacs diúltaithe Git lárnach %s"
+
+msgid "cannot truncate pack to skip duplicate"
+msgstr "ní féidir an pacáiste a ghiorrú chun dúblach a scipeáil"
+
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "EOF sna sonraí (%<PRIuMAX> beart fágtha)"
+
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "teip díbhoilscithe gan choinne: %d"
+
+#, c-format
+msgid "not a tree: %s"
+msgstr "ní crann é: %s"
+
+#, c-format
+msgid "can't load tree %s"
+msgstr "ní féidir crann %s a luchtú"
+
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "mód truaillithe i %s"
+
+msgid "root cannot be a non-directory"
+msgstr "ní féidir leis an bhfréamh a bheith ina eolaire neamh-eolaire"
+
+msgid "empty path component found in input"
+msgstr "comhpháirt chonair folamh aimsithe san ionchur"
+
+msgid "non-directories cannot have subtrees"
+msgstr "ní féidir fochrainn a bheith ag comhaid nach eolairí iad"
+
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
 msgstr ""
-"Ainm formáid a bhfuil súil leis ainm comhaid don rogha athscríobh fo-mhodúil"
+"ag fágáil %s ós rud é go mbeadh sé ag pointeáil air féin (i.e. chuig %s)"
 
-#: builtin/fast-import.c
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "tá tiomnuithe ar iarraidh sa bhrainse %s."
+
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "gan %s a nuashonrú (níl %s sa leid nua %s)"
+
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "ní féidir eolairí tosaigh %s a chruthú"
+
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "ní féidir comhad marcanna %s a scríobh"
+
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "ní féidir comhad marcanna %s a scríobh: %s"
+
+#, c-format
+msgid "unable to write file %s"
+msgstr "ní féidir comhad %s a scríobh"
+
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "ag súil le hordú 'data n', aimsíodh: %s"
+
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "EOF sna sonraí (níor aimsíodh an críochnóir '%s')"
+
+msgid "data is too large to use in this context"
+msgstr "tá an iomarca sonraí le húsáid sa chomhthéacs seo"
+
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "EOF sna sonraí (%lu bearta fágtha)"
+
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "ar iarraidh < sa teaghrán aitheantais: %s"
+
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "spás ar iarraidh roimh < sa teaghrán aitheantais: %s"
+
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "ar iarraidh > sa teaghrán aitheantais: %s"
+
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "spás ar iarraidh i ndiaidh > sa teaghrán aitheantais: %s"
+
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "dáta amh neamhbhailí \"%s\" san aitheantas: %s"
+
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "dáta rfc2822 neamhbhailí \"%s\" san aitheantas: %s"
+
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "ní mór don dáta san aitheantas a bheith 'anois': %s"
+
+#, c-format
+msgid "too large fanout (%u)"
+msgstr "ró-mhór lucht leanúna (%u)"
+
+#, c-format
+msgid "failed to remove path %s"
+msgstr "theip ar an gcosán %s a bhaint"
+
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "gan aon luach i ndiaidh ':' sa mharc: %s"
+
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "bruscar i ndiaidh marc: %s"
+
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "spás ar iarraidh i ndiaidh an mharc: %s"
+
+#, c-format
+msgid "invalid %s: %s"
+msgstr "%s neamhbhailí: %s"
+
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "NUL i %s: %s"
+
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "bruscar i ndiaidh %s: %s"
+
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "spás ar iarraidh i ndiaidh %s: %s"
+
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "mód truaillithe: %s"
+
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "tagairt neamhbhailí: %s"
+
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "spás ar iarraidh i ndiaidh SHA1: %s"
+
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "Ní féidir naisc Git a shonrú 'inlíne': %s"
+
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "ní tiomantas é (%s i ndáiríre): %s"
+
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "ní féidir eolairí a shonrú 'inlíne': %s"
+
+#, c-format
+msgid "%s not found: %s"
+msgstr "%s gan aimsiú: %s"
+
+msgid "tree"
+msgstr "crann"
+
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "ní %s é (%s i ndáiríre): %s"
+
+#, c-format
+msgid "path %s not in branch"
+msgstr "níl an cosán %s sa bhrainse"
+
+msgid "can't add a note on empty branch."
+msgstr "ní féidir nóta a chur ar bhrainse folamh."
+
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr "marc :%<PRIuMAX> ní tiomantas é"
+
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "ní tiomantas bailí é: %s"
+
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "ainm tagartha nó abairt SHA1 neamhbhailí: %s"
+
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "ní blob é (%s i ndáiríre): %s"
+
+#, c-format
+msgid "blob not found: %s"
+msgstr "bloba gan aimsiú: %s"
+
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "tá an tiomnú %s truaillithe"
+
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "ní féidir brainse a chruthú uaidh féin: %s"
+
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
+msgstr ""
+"an fhormáid gpgsign a bhíothas ag súil léi: 'gpgsign <hash-algo> <signature-"
+"format>', le haghaidh 'gpgsign %s'"
+
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "algartam haise git anaithnid i gpgsig: '%s'"
+
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "formáid shínithe neamhbhailí i gpgsig: '%s'"
+
+msgid "'unknown' signature format in gpgsig"
+msgstr "Formáid shínithe 'anaithnid' i gpgsig"
+
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr "aimsithe iolracha %s sínithe, ag déanamh neamhaird de shínithe breise"
+
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr "d’fhill parse_one_signature() algartam haise anaithnid"
+
+msgid "expected committer but didn't get one"
+msgstr "bhí mé ag súil le gealltóir ach ní bhfuair mé ceann"
+
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr ""
+"tháinig ar thiomantas sínithe; bain úsáid as --signed-commits=<mode> chun é "
+"a láimhseáil"
+
+msgid "stripping a commit signature"
+msgstr "síniú tiomantais a bhaint"
+
+msgid "importing a commit signature verbatim"
+msgstr "síniú tiomantais a allmhairiú focal ar fhocal"
+
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr ""
+"bhuail mé le clib shínithe; bain úsáid as --signed-tags=<mode> chun é a "
+"láimhseáil"
+
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr "ag allmhairiú síniú clibe focal ar fhocal don chlib '%s'"
+
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr "ag baint síniú clibe don chlib '%s'"
+
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "ag súil le hordú 'from', fuarthas '%s'"
+
+msgid "can't tag an empty branch."
+msgstr "ní féidir clib a chur ar bhrainse folamh."
+
+#, c-format
+msgid "not a valid object: %s"
+msgstr "ní réad bailí: %s"
+
+msgid "write to frontend failed"
+msgstr "theip ar scríobh chuig an tosaigh"
+
+#, c-format
+msgid "can't read object %s"
+msgstr "ní féidir an réad %s a léamh"
+
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "is %s é réad %s ach bhíothas ag súil le blob."
+
+#, c-format
+msgid "not a mark: %s"
+msgstr "ní marc é: %s"
+
+#, c-format
+msgid "unknown mark: %s"
+msgstr "marc anaithnid: %s"
+
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "bruscar i ndiaidh SHA1: %s"
+
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "ní cosúil le crann é: %s"
+
+#, c-format
+msgid "can't load object %s"
+msgstr "ní féidir an réad %s a luchtú"
+
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "neamhbhailí SHA1 sa chlib: %s"
+
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "neamhbhailí SHA1 sa tiomnú: %s"
+
+#, c-format
+msgid "missing from marks for submodule '%s'"
+msgstr "ar iarraidh ó na marcanna don fho-mhodúl '%s'"
+
+#, c-format
+msgid "missing to marks for submodule '%s'"
+msgstr "marcanna ar iarraidh don fho-mhodúl '%s'"
+
+#, c-format
+msgid "missing space after tree-ish: %s"
+msgstr "spás ar iarraidh i ndiaidh crann-mhaith: %s"
+
+#, c-format
+msgid "not in a commit: %s"
+msgstr "ní i gcóipeadh: %s"
+
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "ag súil le hordú 'mark', fuarthas %s"
+
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "ag súil le hordú 'to', fuaireadh %s"
+
+msgid "only one import-marks command allowed per stream"
+msgstr ""
+"ní cheadaítear ach ordú amháin marcanna-iompórtála in aghaidh an tsrutha"
+
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "anaithnid --date-format argóint %s"
+
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s: ní mór don argóint a bheith ina slánuimhir neamh-dhiúltach"
+
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr "--depth ní féidir dul thar %u"
+
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr "--cat-blob-fd ní féidir dul thar %d"
+
+msgid "expected format name:filename for submodule rewrite option"
+msgstr "ainm formáide ionchais: ainm comhaid don rogha athscríofa fo-mhodúil"
+
+#, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "is é 1 MiB an méid uasta íosta sa phacáiste"
+
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "anaithnid --signed-commits mód '%s'"
+
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "mód anaithnid --signed-tags '%s'"
+
 #, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
 msgstr "feature '%s' forbidden in input without --allow-unsafe-features"
 
-#: builtin/fetch-pack.c
+#, c-format
+msgid "got feature command '%s' after data command"
+msgstr "fuair an t-ordú gné '%s' i ndiaidh an ordaithe sonraí"
+
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "ní thacaíonn an leagan seo de thapa-iompórtáil leis an ngné %s."
+
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr "fuair mé an rogha '%s' i ndiaidh an ordaithe sonraí"
+
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "ní thacaíonn an leagan seo de thapa-iompórtáil leis an rogha: %s"
+
+#, c-format
+msgid "unknown option %s"
+msgstr "rogha anaithnid %s"
+
+#, c-format
+msgid "unknown option --%s"
+msgstr "rogha anaithnid --%s"
+
+#, c-format
+msgid "unsupported command: %s"
+msgstr "ordú gan tacaíocht: %s"
+
+msgid "stream ends early"
+msgstr "críochnaíonn an sruth go luath"
+
 #, c-format
 msgid "Lockfile created but not reported: %s"
 msgstr "Cruthaíodh comhad Lockfile ach nár tuairiscigh: %s"
 
-#: builtin/fetch.c
 msgid "git fetch [<options>] [<repository> [<refspec>...]]"
 msgstr "git fetch [<options>] [<repository> [<refspec>...]]"
 
-#: builtin/fetch.c
 msgid "git fetch [<options>] <group>"
 msgstr "git fetch [<options>] <group>"
 
-#: builtin/fetch.c
 msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]"
 msgstr "git fetch --multiple [<options>] [(<repository> | <group>)...]"
 
-#: builtin/fetch.c
 msgid "git fetch --all [<options>]"
 msgstr "git fetch --all [<options>]"
 
-#: builtin/fetch.c
 msgid "fetch.parallel cannot be negative"
 msgstr "ní féidir fetch.parallel a bheith diúltach"
 
-#: builtin/fetch.c
 msgid "couldn't find remote ref HEAD"
 msgstr "ní raibh in ann ciantagartha HEAD a fháil"
 
-#: builtin/fetch.c
 #, c-format
 msgid "From %.*s\n"
 msgstr "Ó %.*s\n"
 
-#: builtin/fetch.c
 #, c-format
 msgid "object %s not found"
 msgstr "níor aimsíodh réad %s"
 
-#: builtin/fetch.c
 msgid "[up to date]"
 msgstr "[cothrom le dáta]"
 
-#: builtin/fetch.c
 msgid "[rejected]"
 msgstr "[diúltaithe]"
 
-#: builtin/fetch.c
 msgid "can't fetch into checked-out branch"
 msgstr "ní féidir teacht isteach i mbrainse seiceáilte"
 
-#: builtin/fetch.c
 msgid "[tag update]"
 msgstr "[Nuashonrú tag]"
 
-#: builtin/fetch.c
 msgid "unable to update local ref"
-msgstr "in ann tagairt áitiúil a nuashonrú"
+msgstr "ní féidir tagairt áitiúil a nuashonrú"
 
-#: builtin/fetch.c
 msgid "would clobber existing tag"
 msgstr "chuirfeadh an chlib atá ann cheana"
 
-#: builtin/fetch.c
 msgid "[new tag]"
 msgstr "[tag nua]"
 
-#: builtin/fetch.c
 msgid "[new branch]"
 msgstr "[brainse nua]"
 
-#: builtin/fetch.c
 msgid "[new ref]"
 msgstr "[tagartha nua]"
 
-#: builtin/fetch.c
 msgid "forced update"
 msgstr "nuashonrú éigeant"
 
-#: builtin/fetch.c
 msgid "non-fast-forward"
 msgstr "neamh-tapa ar aghaidh"
 
-#: builtin/fetch.c builtin/grep.c sequencer.c
 #, c-format
 msgid "cannot open '%s'"
 msgstr "ní féidir '%s' a oscailt"
 
-#: 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"
@@ -7595,7 +6670,6 @@
 "forced-updates'\n"
 "bratach nó rith 'git config fetch.showForcedUpdates true'"
 
-#: builtin/fetch.c
 #, c-format
 msgid ""
 "it took %.2f seconds to check forced updates; you can use\n"
@@ -7609,69 +6683,40 @@
 "bréaga'\n"
 "chun an seiceáil seo a sheachaint\n"
 
-#: builtin/fetch.c
 #, c-format
 msgid "%s did not send all necessary objects"
 msgstr "Níor sheol %s na rudaí riachtanacha go léir"
 
-#: builtin/fetch.c
 #, c-format
 msgid "rejected %s because shallow roots are not allowed to be updated"
 msgstr "dhiúltaigh %s toisc nach gceadaítear fréamhacha éadmhara a nuashonrú"
 
-#: 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í fhéadfaí roinnt fios áitiúla a nuashonrú; déan iarracht rith\n"
-" 'git remote prune%s' chun aon bhrainsí sean-fhrithsheasmhach a bhaint"
-
-#: builtin/fetch.c
-#, c-format
-msgid "   (%s will become dangling)"
-msgstr "   (beidh %s ag crochadh)"
-
-#: builtin/fetch.c
-#, c-format
-msgid "   (%s has become dangling)"
-msgstr "   (%s has become dangling)"
-
-#: builtin/fetch.c
 msgid "[deleted]"
 msgstr "[scriosta]"
 
-#: builtin/fetch.c builtin/remote.c
 msgid "(none)"
 msgstr "(níl aon)"
 
-#: builtin/fetch.c
 #, c-format
 msgid "refusing to fetch into branch '%s' checked out at '%s'"
 msgstr "ag diúltú teacht isteach i mbrainse '%s' a sheiceáil amach ag '%s'"
 
-#: builtin/fetch.c
 #, c-format
 msgid "option \"%s\" value \"%s\" is not valid for %s"
 msgstr "níl an rogha “%s” luach “%s” bailí do %s"
 
-#: builtin/fetch.c
 #, c-format
 msgid "option \"%s\" is ignored for %s"
 msgstr "déantar neamhaird ar rogha “%s” do %s"
 
-#: builtin/fetch.c object-store.c
 #, c-format
 msgid "%s is not a valid object"
 msgstr "Ní réad bailí é %s"
 
-#: builtin/fetch.c
 #, c-format
 msgid "the object %s does not exist"
 msgstr "níl an réad %s ann"
 
-#: builtin/fetch.c
 #, c-format
 msgid ""
 "Run 'git remote set-head %s %s' to follow the change, or set\n"
@@ -7688,11 +6733,54 @@
 "díchumasófar an rabhadh go dtí go n-athraíonn an cianda HEAD go rud éigin "
 "eile."
 
-#: builtin/fetch.c
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+"Tá tú ar chóras comhad neamhíogair ó thaobh cás de, agus tá tagairtí sa "
+"chianrialtán a bhfuil tú\n"
+"ag iarraidh a fháil uaidh nach bhfuil ach difríocht idir iad ó thaobh cás "
+"de. Ní\n"
+"bhfuil sé indéanta tagairtí den sórt sin a stóráil leis an gcúlra 'comhaid'. "
+"Is féidir leat\n"
+"seo a ghlacadh mar atá, agus sa chás sin ní bheidh tú in ann\n"
+"gach tagairt chianrialtán a stóráil ar dhiosca. Nó is féidir leat\n"
+"do stór a aistriú chun an cúlra 'reftable' a úsáid leis an\n"
+"ordú seo a leanas:\n"
+"\n"
+"git refs migrate --ref-format=reftable\n"
+"\n"
+"Coinnigh i gcuimhne nach dtacaíonn gach cur i bhfeidhm de Git leis an\n"
+"formáid nua seo go fóill. Mar sin, mura n-úsáideann tú uirlisí seachas Git "
+"chun rochtain a fháil ar an\n"
+"stórra seo, b'fhéidir nach rogha é aistriú chuig reftables.\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í fhéadfaí roinnt fios áitiúla a nuashonrú; déan iarracht rith\n"
+" 'git remote prune%s' chun aon bhrainsí sean-fhrithsheasmhach a bhaint"
+
+#, c-format
+msgid "fetching ref %s failed: %s"
+msgstr "theip ar an tagairt %s a fháil: %s"
+
 msgid "multiple branches detected, incompatible with --set-upstream"
 msgstr "brainsí iolracha brainsí braite, gan oiriúint le --set-upstream"
 
-#: builtin/fetch.c
 #, c-format
 msgid ""
 "could not set upstream of HEAD to '%s' from '%s' when it does not point to "
@@ -7701,19 +6789,15 @@
 "ní fhéadfaí suas sruth de HEAD a shocrú go '%s' ó '%s' nuair nach dtugann sé "
 "in iúl go dtí aon bhrainse."
 
-#: builtin/fetch.c
 msgid "not setting upstream for a remote remote-tracking branch"
 msgstr "gan socrú suas sruth do bhrainse cianrianaithe"
 
-#: builtin/fetch.c
 msgid "not setting upstream for a remote tag"
 msgstr "gan a shocrú suas sruth le haghaidh clib iargúlta"
 
-#: builtin/fetch.c
 msgid "unknown branch type"
 msgstr "cineál brainse anaithnid"
 
-#: builtin/fetch.c
 msgid ""
 "no source branch found;\n"
 "you need to specify exactly one branch with the --set-upstream option"
@@ -7721,22 +6805,18 @@
 "ní bhfuarthas aon bhrainse foinse;\n"
 "ní mór duit brainse amháin a shonrú go díreach leis an rogha --set-upstream"
 
-#: builtin/fetch.c
 #, c-format
 msgid "Fetching %s\n"
 msgstr "Ag tarraingt %s\n"
 
-#: builtin/fetch.c
 #, c-format
 msgid "could not fetch %s"
 msgstr "ní fhéadfaí %s a fháil"
 
-#: builtin/fetch.c
 #, c-format
 msgid "could not fetch '%s' (exit code: %d)\n"
 msgstr "níorbh fhéidir '%s' a fháil (cód scoir: %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"
@@ -7744,105 +6824,80 @@
 "níl aon stór iargúlta sonraithe; sonraigh URL nó a\n"
 "ainm iargúlta ar chóir athbhreithnithe nua a fháil"
 
-#: builtin/fetch.c
 msgid "you need to specify a tag name"
 msgstr "ní mór duit ainm clib a shonrú"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "fetch from all remotes"
 msgstr "faigh ó gach iargúlta"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "set upstream for git pull/fetch"
 msgstr "socraigh suas sruth le haghaidh git pull/fetch"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "append to .git/FETCH_HEAD instead of overwriting"
 msgstr "cuir chuig .git/FETCH_HEAD in ionad athscríobh"
 
-#: builtin/fetch.c
 msgid "use atomic transaction to update references"
 msgstr "úsáid idirbheart adamach chun tagairtí a nuashonrú"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "path to upload pack on remote end"
 msgstr "cosán chun pacáiste a uaslódáil ar iargúlta"
 
-#: builtin/fetch.c
 msgid "force overwrite of local reference"
 msgstr "tagairt áitiúil a fhorscríobh"
 
-#: builtin/fetch.c
 msgid "fetch from multiple remotes"
 msgstr "a fháil ó iomadúla iargúlta"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "fetch all tags and associated objects"
 msgstr "gach clib agus rudaí gaolmhara a fháil"
 
-#: builtin/fetch.c
 msgid "do not fetch all tags (--no-tags)"
 msgstr "ná faigh gach clib (--no-tags)"
 
-#: builtin/fetch.c
 msgid "number of submodules fetched in parallel"
 msgstr "líon na bhfo-mhodúil a fuarthas go comhthreomhar"
 
-#: builtin/fetch.c
 msgid "modify the refspec to place all refs within refs/prefetch/"
 msgstr "an refspec a mhodhnú chun gach refs a chur laistigh de refs/prefetch/"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "prune remote-tracking branches no longer on remote"
 msgstr "brainsí cianrianaithe a ghearradh nach bhfuil ar iargúlta a"
 
-#: builtin/fetch.c
 msgid "prune local tags no longer on remote and clobber changed tags"
 msgstr ""
 "clibeanna áitiúla a ghearradh nach bhfuil ar chlibeanna iargúlta agus "
 "athraithe clobber"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "on-demand"
 msgstr "ar éileamh"
 
-#: builtin/fetch.c
 msgid "control recursive fetching of submodules"
 msgstr "tógáil athfhillteach fo-mhodúil a rialú"
 
-#: builtin/fetch.c
 msgid "write fetched references to the FETCH_HEAD file"
 msgstr "scríobh tagairtí faighte don chomhad FETCH_HEAD"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "keep downloaded pack"
 msgstr "pacáiste íoslódáilte"
 
-#: builtin/fetch.c
 msgid "allow updating of HEAD ref"
 msgstr "cead a thabhairt do nuashonrú HEAD ref"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "deepen history of shallow clone"
 msgstr "stair clón éadomhain a dhoimhniú"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "deepen history of shallow repository based on time"
 msgstr "stair stór éadomhain a dhoimhniú bunaithe ar am"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "convert to a complete repository"
 msgstr "tiontaigh go stór iomlán"
 
-#: builtin/fetch.c
 msgid "re-fetch without negotiating common commits"
 msgstr "athghabháil gan gealltanais choiteanna a chaibidliú"
 
-#: builtin/fetch.c
 msgid "prepend this to submodule path output"
 msgstr "é seo a chur ar aghaidh chuig aschur cosán fo-mhodúil"
 
-#: builtin/fetch.c
 msgid ""
 "default for recursive fetching of submodules (lower priority than config "
 "files)"
@@ -7850,92 +6905,71 @@
 "réamhshocraithe maidir le fo-mhodúil a fháil athshlánach (tosaíocht níos "
 "ísle ná comhaid chumraithe)"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "accept refs that update .git/shallow"
 msgstr "glacadh le hiarrachtaí a nuashonraíonn .git/shalach"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "refmap"
 msgstr "athléarscáil"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "specify fetch refmap"
 msgstr "sonraigh refmap a fháil"
 
-#: builtin/fetch.c builtin/pull.c builtin/rebase.c builtin/replay.c
 msgid "revision"
 msgstr "athbhreithiú"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "report that we have only objects reachable from this object"
 msgstr "tuairisciú nach bhfuil ach rudaí inrochtana againn ón réad seo"
 
-#: builtin/fetch.c
 msgid "do not fetch a packfile; instead, print ancestors of negotiation tips"
 msgstr ""
 "ná faigh comhad pacáiste; ina ionad sin, priontáil sinsear leideanna "
 "idirbheartaíochta"
 
-#: builtin/fetch.c
 msgid "run 'maintenance --auto' after fetching"
 msgstr "reáchtáil 'cothabháil --auto' tar éis a fháil"
 
-#: builtin/fetch.c builtin/pull.c
 msgid "check for forced-updates on all updated branches"
 msgstr "seiceáil ar nuashonruithe éigeantacha ar gach brainse nuashonraithe"
 
-#: builtin/fetch.c
 msgid "write the commit-graph after fetching"
 msgstr "scríobh an graf coimisiúnaithe tar éis a fháil"
 
-#: builtin/fetch.c
 msgid "accept refspecs from stdin"
 msgstr "glacadh le refspecs ó stdin"
 
-#: builtin/fetch.c
 msgid "--negotiate-only needs one or more --negotiation-tip=*"
 msgstr ""
 "--negotiate-only teastaíonn ceann amháin nó níos mó --negotiation-tip=*"
 
-#: builtin/fetch.c
 msgid "negative depth in --deepen is not supported"
 msgstr "ní thacaítear le doimhneacht dhiúltach i --deepen"
 
-#: builtin/fetch.c
 msgid "--unshallow on a complete repository does not make sense"
 msgstr "níl ciall le --unshallow ar stórlann iomlán"
 
-#: builtin/fetch.c
 #, c-format
 msgid "failed to fetch bundles from '%s'"
 msgstr "theip ar bhaclaí a fháil ó '%s'"
 
-#: builtin/fetch.c
 msgid "fetch --all does not take a repository argument"
 msgstr "ní ghlacann fetch --all argóint stór"
 
-#: builtin/fetch.c
 msgid "fetch --all does not make sense with refspecs"
 msgstr "ní bhíonn ciall ag teacht --all le refspecs"
 
-#: builtin/fetch.c
 #, c-format
 msgid "no such remote or remote group: %s"
 msgstr "gan aon ghrúpa iargúlta nó cianda den sórt sin: %s"
 
-#: builtin/fetch.c
 msgid "fetching a group and specifying refspecs does not make sense"
 msgstr "níl ciall grúpa a fháil agus refspecs a shonrú"
 
-#: builtin/fetch.c
 msgid "must supply remote when using --negotiate-only"
 msgstr "ní mór iargúlta a sholáthar agus tú ag úsáid --negotiate-only"
 
-#: builtin/fetch.c
 msgid "protocol does not support --negotiate-only, exiting"
 msgstr "ní thacaíonn an prótacal le --negotiate-only, ag scoir"
 
-#: builtin/fetch.c
 msgid ""
 "--filter can only be used with the remote configured in "
 "extensions.partialclone"
@@ -7943,170 +6977,134 @@
 "--filter Ní féidir ach an scagaire a úsáid ach leis an iargúlta cumraithe in "
 "extensions.partialclone"
 
-#: builtin/fetch.c
 msgid "--atomic can only be used when fetching from one remote"
 msgstr ""
 "--atomic ní féidir ach adamhach a úsáid ach amháin nuair a bhíonn sé á fháil "
 "ó chianrialtán amháin"
 
-#: builtin/fetch.c
 msgid "--stdin can only be used when fetching from one remote"
 msgstr ""
 "Ní féidir --stdin a úsáid ach amháin nuair a bhfaightear é ó iargúlta amháin"
 
-#: builtin/fmt-merge-msg.c
 msgid ""
 "git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]"
 msgstr ""
-"<n><file>git fmt-merge-msg [-m<message>] [--log [=] | --no-log] [--comhad]"
+"git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]"
 
-#: builtin/fmt-merge-msg.c
 msgid "populate log with at most <n> entries from shortlog"
 msgstr "logáil a chomhlánú le hiontrálacha is mó <n>ó ghearrlog"
 
-#: builtin/fmt-merge-msg.c
 msgid "alias for --log (deprecated)"
 msgstr "alias le haghaidh --log (mísheasmhach)"
 
-#: builtin/fmt-merge-msg.c
 msgid "text"
 msgstr "téacs"
 
-#: builtin/fmt-merge-msg.c
 msgid "use <text> as start of message"
 msgstr "úsáid <text> mar thús na teachtaireachta"
 
-#: builtin/fmt-merge-msg.c
 msgid "use <name> instead of the real target branch"
 msgstr "úsáid in <name> ionad na fíor-spriocbhrainse"
 
-#: builtin/fmt-merge-msg.c
 msgid "file to read from"
 msgstr "comhad le léamh ó"
 
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [<options>] [<pattern>]"
-msgstr "git for-each-ref [<options>] [<pattern>]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--points-at <object>]"
-msgstr "git for-each-ref [--points-at <object>]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-
-#: builtin/for-each-ref.c
 msgid "quote placeholders suitably for shells"
 msgstr "sealbhóirí áiteanna a luachan go oiriúnach do"
 
-#: builtin/for-each-ref.c
 msgid "quote placeholders suitably for perl"
 msgstr "sealbhóirí áiteanna a luachan go oiriúnach do perl"
 
-#: builtin/for-each-ref.c
 msgid "quote placeholders suitably for python"
 msgstr "sealbhóirí áiteanna a luaigh go oiriúnach do python"
 
-#: builtin/for-each-ref.c
 msgid "quote placeholders suitably for Tcl"
 msgstr "sealbhóirí áiteanna a luachan go oiriúnach do Tcl"
 
-#: builtin/for-each-ref.c
 msgid "show only <n> matched refs"
 msgstr "taispeáin ach sonraí com <n>hoiriúnaithe"
 
-#: builtin/for-each-ref.c builtin/tag.c
+msgid "marker"
+msgstr "marcóir"
+
+msgid "start iteration after the provided marker"
+msgstr "tosú athrá tar éis an mharcóra a cuireadh ar fáil"
+
 msgid "respect format colors"
 msgstr "meas dathanna formáid"
 
-#: builtin/for-each-ref.c
 msgid "print only refs which points at the given object"
 msgstr "ní phriontáil ach téacsanna a phointíonn ar an réad a thugtar"
 
-#: builtin/for-each-ref.c
 msgid "print only refs that are merged"
 msgstr "ní phriontáil ach scríbhneoireachtaí atá cumasaithe"
 
-#: builtin/for-each-ref.c
 msgid "print only refs that are not merged"
 msgstr "priontáil ach scríbhinní nach bhfuil cumasc"
 
-#: builtin/for-each-ref.c
 msgid "print only refs which contain the commit"
 msgstr "ní phriontáil ach téifeanna ina bhfuil an tiomantas"
 
-#: builtin/for-each-ref.c
 msgid "print only refs which don't contain the commit"
 msgstr "ní phriontáil ach scríbhneoirí nach bhfuil an tiomantas"
 
-#: builtin/for-each-ref.c
 msgid "read reference patterns from stdin"
 msgstr "léigh patrúin tagartha ó stdin"
 
-#: builtin/for-each-ref.c
 msgid "also include HEAD ref and pseudorefs"
 msgstr "san áireamh freisin HEAD ref agus pseudorefs"
 
-#: builtin/for-each-ref.c
+msgid "cannot use --start-after with custom sort options"
+msgstr "ní féidir --start-after a úsáid le roghanna sórtála saincheaptha"
+
 msgid "unknown arguments supplied with --stdin"
 msgstr "argóintí anaithnid a sholáthraítear le --stdin"
 
-#: builtin/for-each-repo.c
+msgid "cannot use --start-after with patterns"
+msgstr "ní féidir --start-after a úsáid le patrúin"
+
+msgid "git for-each-ref "
+msgstr "git for-each-ref "
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<config> [--] <arguments>"
 
-#: builtin/for-each-repo.c
 msgid "config"
 msgstr "cumraíocht"
 
-#: builtin/for-each-repo.c
 msgid "config key storing a list of repository paths"
 msgstr "eochair chumraithe a stóráil liosta de chosáin stórais"
 
-#: builtin/for-each-repo.c
 msgid "keep going even if command fails in a repository"
 msgstr "coinnigh ort fiú má theipeann an t-ordú i stóras"
 
-#: builtin/for-each-repo.c
 msgid "missing --config=<config>"
 msgstr "ar iarraidh --config=<config>"
 
-#: builtin/for-each-repo.c
 #, c-format
 msgid "got bad config --config=%s"
-msgstr "fuair go dona cumraíocht --config=%s"
+msgstr "fuair cumraíocht go dona --config=%s"
 
-#: builtin/fsck.c
 msgid "unknown"
 msgstr "anaithnid"
 
 #. TRANSLATORS: e.g. error in tree 01bfda: <more explanation>
-#: builtin/fsck.c
 #, c-format
 msgid "error in %s %s: %s"
 msgstr "earráid i %s %s: %s"
 
 #. TRANSLATORS: e.g. warning in tree 01bfda: <more explanation>
-#: builtin/fsck.c
 #, c-format
 msgid "warning in %s %s: %s"
 msgstr "rabhadh i %s %s: %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "broken link from %7s %s"
 msgstr "nasc briste ó %7s %s"
 
-#: builtin/fsck.c
 msgid "wrong object type in link"
 msgstr "cineál réad mícheart i nasc"
 
-#: builtin/fsck.c
 #, c-format
 msgid ""
 "broken link from %7s %s\n"
@@ -8115,185 +7113,146 @@
 "nasc briste ó %7s %s\n"
 " chuig %7s %s"
 
-#: builtin/fsck.c builtin/prune.c connected.c
 msgid "Checking connectivity"
 msgstr "Nascacht a sheiceáil"
 
-#: builtin/fsck.c
 #, c-format
 msgid "missing %s %s"
 msgstr "%s %s ar iarraidh"
 
-#: builtin/fsck.c
 #, c-format
 msgid "unreachable %s %s"
 msgstr "%s %s neamh-inrochtana"
 
-#: builtin/fsck.c
 #, c-format
 msgid "dangling %s %s"
 msgstr "ag crochadh %s %s"
 
-#: builtin/fsck.c
 msgid "could not create lost-found"
 msgstr "ní fhéadfaí a chruthú a aimsíodh caillte"
 
-#: builtin/fsck.c builtin/gc.c builtin/rebase.c rebase-interactive.c rerere.c
-#: sequencer.c
 #, c-format
 msgid "could not write '%s'"
 msgstr "ní fhéadfaí '%s' a scríobh"
 
-#: builtin/fsck.c
 #, c-format
 msgid "could not finish '%s'"
 msgstr "ní raibh '%s' in ann a chríochnú"
 
-#: builtin/fsck.c
 #, c-format
 msgid "Checking %s"
 msgstr "Seiceáil %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "Checking connectivity (%d objects)"
 msgstr "Ag seiceáil nascachta (%d réad)"
 
-#: builtin/fsck.c
 #, c-format
 msgid "Checking %s %s"
 msgstr "Seiceáil %s %s"
 
-#: builtin/fsck.c
 msgid "broken links"
 msgstr "naisc briste"
 
-#: builtin/fsck.c
 #, c-format
 msgid "root %s"
 msgstr "fréamh %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "tagged %s %s (%s) in %s"
 msgstr "clib %s %s (%s) i %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: object corrupt or missing"
 msgstr "%s: réad truaillithe nó ar iarraidh"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: invalid reflog entry %s"
 msgstr "%s: iontráil reflog neamhbhailí %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "Checking reflog %s->%s"
 msgstr "Seiceáil reflog %s->%s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: invalid sha1 pointer %s"
 msgstr "%s: pointeoir sha1 neamhbhailí %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: not a commit"
 msgstr "%s: ní gealltanas"
 
-#: builtin/fsck.c
 msgid "notice: No default references"
 msgstr "fógra: Gan aon tagairtí réamhshocraithe"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: hash-path mismatch, found at: %s"
 msgstr "%s: míchomhoiriúnú hash-path, le fáil ag: %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: object corrupt or missing: %s"
 msgstr "%s: réad truaillithe nó ar iarraidh: %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: object could not be parsed: %s"
 msgstr "%s: ní fhéadfaí réad a pháirseáil: %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "bad sha1 file: %s"
 msgstr "comhad sha1 olc: %s"
 
-#: builtin/fsck.c
 msgid "Checking object directory"
 msgstr "Seiceáil eolaire réada"
 
-#: builtin/fsck.c
 msgid "Checking object directories"
 msgstr "Seiceáil eolairí réada"
 
-#: builtin/fsck.c
 #, c-format
 msgid "Checking %s link"
 msgstr "Nasc %s a sheiceáil"
 
-#: builtin/fsck.c builtin/index-pack.c
 #, c-format
 msgid "invalid %s"
 msgstr "%s neamhbhailí"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s points to something strange (%s)"
 msgstr "Léiríonn %s rud éigin aisteach (%s)"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: detached HEAD points at nothing"
 msgstr "%s: pointí HEAD scoite ag aon rud"
 
-#: builtin/fsck.c
 #, c-format
 msgid "notice: %s points to an unborn branch (%s)"
 msgstr "fógra: Díríonn %s chuig brainse neamhbhreithe (%s)"
 
-#: builtin/fsck.c
 #, c-format
 msgid "Checking cache tree of %s"
 msgstr "Crann taisce de %s a sheiceáil"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: invalid sha1 pointer in cache-tree of %s"
 msgstr "%s: pointeoir sha1 neamhbhailí i gcrann cache-%s"
 
-#: builtin/fsck.c
 msgid "non-tree in cache-tree"
 msgstr "neamh-chrann i gcrann cache-"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: invalid sha1 pointer in resolve-undo of %s"
 msgstr "%s: pointeoir sha1 neamhbhailí i réiteach a chealú de %s"
 
-#: builtin/fsck.c
 #, c-format
 msgid "unable to load rev-index for pack '%s'"
-msgstr "in ann innéacs rev-innéacs a luchtú do phacáiste '%s'"
+msgstr "ní féidir innéacs athbhreithnithe a luchtú don phacáiste '%s'"
 
-#: builtin/fsck.c
 #, c-format
 msgid "invalid rev-index for pack '%s'"
 msgstr "innéacs rev-neamhbhailí do phacáiste '%s'"
 
-#: builtin/fsck.c
 msgid "Checking ref database"
 msgstr "Seiceáil bunachar sonraí tagairt"
 
-#: builtin/fsck.c
 msgid ""
 "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
 "         [--[no-]full] [--strict] [--verbose] [--lost-found]\n"
@@ -8305,209 +7264,162 @@
 " [-- [gan-] ag crochadh] [-- [gan-] dul chun cinn] [--nascacht amháin]\n"
 " <object>[-- [no-] ainm-rudaí] [-- [aon-] tagairtí] [...]"
 
-#: builtin/fsck.c
 msgid "show unreachable objects"
 msgstr "taispeáint rudaí dochreidte"
 
-#: builtin/fsck.c
 msgid "show dangling objects"
 msgstr "taispeáin rudaí crochtanacha"
 
-#: builtin/fsck.c
 msgid "report tags"
 msgstr "clibeanna tuarascála"
 
-#: builtin/fsck.c
 msgid "report root nodes"
 msgstr "nóid fréimhe a thuairisc"
 
-#: builtin/fsck.c
 msgid "make index objects head nodes"
 msgstr "nóid ceann rudaí innéacs a dhéanamh"
 
-#: builtin/fsck.c
 msgid "make reflogs head nodes (default)"
 msgstr "nóid ceann reflogs a dhéanamh (réamhshocraithe)"
 
-#: builtin/fsck.c
 msgid "also consider packs and alternate objects"
 msgstr "smaoinigh freisin ar phacáistí agus rudaí"
 
-#: builtin/fsck.c
 msgid "check only connectivity"
 msgstr "seiceáil ach nascacht"
 
-#: builtin/fsck.c builtin/mktag.c
 msgid "enable more strict checking"
 msgstr "cumasú seiceáil níos docht"
 
-#: builtin/fsck.c
 msgid "write dangling objects in .git/lost-found"
 msgstr "scríobh rudaí crochta in .git/lost-found"
 
-#: builtin/fsck.c builtin/prune.c
 msgid "show progress"
 msgstr "taispeáin dul chun cinn"
 
-#: builtin/fsck.c
 msgid "show verbose names for reachable objects"
 msgstr "taispeáint ainmneacha fabhracha do rudaí inrochtana"
 
-#: builtin/fsck.c
 msgid "check reference database consistency"
 msgstr "seiceáil comhsheasmhacht bunachair"
 
-#: builtin/fsck.c builtin/index-pack.c
 msgid "Checking objects"
 msgstr "Rud a sheiceáil"
 
-#: builtin/fsck.c
 #, c-format
 msgid "%s: object missing"
 msgstr "%s: réad ar iarraidh"
 
-#: builtin/fsck.c
 #, c-format
 msgid "invalid parameter: expected sha1, got '%s'"
 msgstr "paraiméadar neamhbhailí: súil le sha1, fuair '%s'"
 
-#: builtin/fsmonitor--daemon.c
 msgid "git fsmonitor--daemon start [<options>]"
 msgstr "git fsmonitor--daemon start [<options>]"
 
-#: builtin/fsmonitor--daemon.c
 msgid "git fsmonitor--daemon run [<options>]"
 msgstr "git fsmonitor--daemon run [<options>]"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "value of '%s' out of range: %d"
 msgstr "luach '%s' lasmuigh den raon: %d"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "value of '%s' not bool or int: %d"
 msgstr "luach '%s' gan bool nó int: %d"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "fsmonitor-daemon is watching '%s'\n"
 msgstr "tá fsmonitor-daemon ag féachaint ar '%s'\n"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "fsmonitor-daemon is not watching '%s'\n"
 msgstr "níl fsmonitor-daemon ag féachaint ar '%s'\n"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "could not create fsmonitor cookie '%s'"
 msgstr "ní fhéadfaí fianán fsmonitor '%s' a chruthú"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "fsmonitor: cookie_result '%d' != SEEN"
 msgstr "fsmonitor: cookie_result  '%d' != SEEN"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "could not start IPC thread pool on '%s'"
 msgstr "ní fhéadfaí linn snáithe IPC a thosú ar '%s'"
 
-#: builtin/fsmonitor--daemon.c
 msgid "could not start fsmonitor listener thread"
 msgstr "ní fhéadfaí snáithe éisteora fsmonitor a thosú"
 
-#: builtin/fsmonitor--daemon.c
 msgid "could not start fsmonitor health thread"
 msgstr "ní fhéadfaí snáithe sláinte fsmonitor a thosú"
 
-#: builtin/fsmonitor--daemon.c
 msgid "could not initialize listener thread"
 msgstr "ní fhéadfadh snáithe éisteora a thionscnamh"
 
-#: builtin/fsmonitor--daemon.c
 msgid "could not initialize health thread"
 msgstr "ní fhéadfaí snáithe sláinte a thionscnamh"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "could not cd home '%s'"
 msgstr "ní fhéadfaí cd baile '%s'"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "fsmonitor--daemon is already running '%s'"
 msgstr "tá fsmonitor--daemon ag rith '%s' cheana féin"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "running fsmonitor-daemon in '%s'\n"
 msgstr "ag rith fsmonitor-daemon i '%s'\n"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "starting fsmonitor-daemon in '%s'\n"
 msgstr "ag tosú fsmonitor-daemon i '%s'\n"
 
-#: builtin/fsmonitor--daemon.c
 msgid "daemon failed to start"
 msgstr "theip ar daemon a thosú"
 
-#: builtin/fsmonitor--daemon.c
 msgid "daemon not online yet"
 msgstr "daemon nach bhfuil ar líne fós"
 
-#: builtin/fsmonitor--daemon.c
 msgid "daemon terminated"
 msgstr "deireadh le déemon"
 
-#: builtin/fsmonitor--daemon.c
 msgid "detach from console"
 msgstr "dícheangal ón gconsól"
 
-#: builtin/fsmonitor--daemon.c
 msgid "use <n> ipc worker threads"
 msgstr "úsáid snái <n>theanna oibrithe ipc"
 
-#: builtin/fsmonitor--daemon.c
 msgid "max seconds to wait for background daemon startup"
 msgstr "soicind uasta chun fanacht le tosú daemon cúlra"
 
-#: builtin/fsmonitor--daemon.c
 #, c-format
 msgid "invalid 'ipc-threads' value (%d)"
 msgstr "luach 'ipc-snáitheanna' neamhbhailí (%d)"
 
-#: builtin/fsmonitor--daemon.c t/helper/test-cache-tree.c
 #, c-format
 msgid "Unhandled subcommand '%s'"
 msgstr "Foordú neamh-láimhseáilte '%s'"
 
-#: builtin/fsmonitor--daemon.c
 msgid "fsmonitor--daemon not supported on this platform"
 msgstr "fsmonitor--daemon  nach dtacaíonn sé ar an ardán seo"
 
-#: builtin/gc.c
 msgid "git gc [<options>]"
 msgstr "git gc [<options>]"
 
-#: builtin/gc.c
 #, c-format
 msgid "Failed to fstat %s: %s"
 msgstr "Theip ar fstat %s: %s"
 
-#: builtin/gc.c
 #, c-format
 msgid "failed to parse '%s' value '%s'"
 msgstr "theip ar luach '%s' a pharsáil '%s'"
 
-#: builtin/gc.c setup.c
 #, c-format
 msgid "cannot stat '%s'"
 msgstr "ní féidir '%s' a stát"
 
-#: builtin/gc.c
 #, c-format
 msgid ""
 "The last gc run reported the following. Please correct the root cause\n"
@@ -8523,68 +7435,56 @@
 "\n"
 "%s"
 
-#: builtin/gc.c
 msgid "prune unreferenced objects"
 msgstr "rudaí gan tagairt a ghearradh"
 
-#: builtin/gc.c
 msgid "pack unreferenced objects separately"
 msgstr "rudaí gan tagairt a phacáil ar leithligh"
 
-#: builtin/gc.c builtin/repack.c
 msgid "with --cruft, limit the size of new cruft packs"
 msgstr "le --cruft, teorainn le méid pacáistí cruft nua"
 
-#: builtin/gc.c
 msgid "be more thorough (increased runtime)"
 msgstr "a bheith níos críochnúla (tréimhse méadaithe)"
 
-#: builtin/gc.c
 msgid "enable auto-gc mode"
 msgstr "mód auto-gc a chumasú"
 
-#: builtin/gc.c
 msgid "perform garbage collection in the background"
 msgstr "bailiú truflais a dhéanamh sa chúlra"
 
-#: builtin/gc.c
 msgid "force running gc even if there may be another gc running"
 msgstr "fórsa ag rith gc fiú má d'fhéadfadh gc eile a bheith ag rith"
 
-#: builtin/gc.c
 msgid "repack all other packs except the largest pack"
 msgstr "gach pacáiste eile a athphacáil ach amháin an pacáiste is mó"
 
-#: builtin/gc.c builtin/repack.c
 msgid "pack prefix to store a pack containing pruned objects"
 msgstr "réimír pacáiste chun pacáiste ina bhfuil rudaí gearrtha a stóráil"
 
-#: builtin/gc.c
+msgid "skip maintenance tasks typically done in the foreground"
+msgstr "scipeáil tascanna cothabhála a dhéantar de ghnáth sa tulra"
+
 #, c-format
 msgid "failed to parse gc.logExpiry value %s"
 msgstr "theip ar luach gc.logExpiry %s a pháirseáil"
 
-#: builtin/gc.c
 #, c-format
 msgid "failed to parse prune expiry value %s"
 msgstr "theip ar luach éaga brúite %s a pharsáil"
 
-#: builtin/gc.c
 #, c-format
 msgid "Auto packing the repository in background for optimum performance.\n"
 msgstr "Pacáil uathoibríoch an stór sa chúlra chun an fheidhmíocht is fearr\n"
 
-#: builtin/gc.c
 #, c-format
 msgid "Auto packing the repository for optimum performance.\n"
 msgstr "Pacáil uathoibríoch an stór chun an fheidhmíocht is fearr\n"
 
-#: builtin/gc.c
 #, c-format
 msgid "See \"git help gc\" for manual housekeeping.\n"
 msgstr "Féach \"git help gc\" le haghaidh obair tí láimhe.\n"
 
-#: builtin/gc.c
 #, c-format
 msgid ""
 "gc is already running on machine '%s' pid %<PRIuMAX> (use --force if not)"
@@ -8592,217 +7492,174 @@
 "tá gc ag rith cheana féin ar mheaisín '%s' pid%<PRIuMAX>(bain úsáid as --"
 "force mura bhfuil)"
 
-#: builtin/gc.c
 msgid ""
 "There are too many unreachable loose objects; run 'git prune' to remove them."
 msgstr ""
 "Tá an iomarca rudaí scaoilte neamh-inrochtana ann; reáchtáil 'git prune' "
 "chun iad a bhaint."
 
-#: builtin/gc.c
 msgid ""
 "git maintenance run [--auto] [--[no-]quiet] [--task=<task>] [--schedule]"
 msgstr ""
-"<task>rith cothabhála git [--auto] [-- [no-] ciúin] [--task=] [--schedule]"
+"git maintenance run [--auto] [--[no-]quiet] [--task=<task>] [--schedule]"
 
-#: builtin/gc.c
 msgid "--no-schedule is not allowed"
 msgstr "Ní cheadaítear --no-schedule"
 
-#: builtin/gc.c
 #, c-format
 msgid "unrecognized --schedule argument '%s'"
 msgstr "argóint --schedule gan aithint '%s'"
 
-#: builtin/gc.c
 msgid "failed to write commit-graph"
 msgstr "theip orthu graf coimisiúnaithe a scríobh"
 
-#: builtin/gc.c
 msgid "failed to prefetch remotes"
 msgstr "theip ar iargúlta iargúlta a réamhghabháil"
 
-#: builtin/gc.c
 msgid "failed to start 'git pack-objects' process"
 msgstr "theip ar phróiseas 'git pack-objects' a thosú"
 
-#: builtin/gc.c
 msgid "failed to finish 'git pack-objects' process"
 msgstr "theip ar phróiseas 'git pack-objects' a chríochnú"
 
-#: builtin/gc.c
 msgid "failed to write multi-pack-index"
 msgstr "theip ar innéacs il-phacáiste a scríobh"
 
-#: builtin/gc.c
 msgid "'git multi-pack-index expire' failed"
 msgstr "Theip ar 'git multi-pack-index in éag'"
 
-#: builtin/gc.c
 msgid "'git multi-pack-index repack' failed"
 msgstr "Theip ar 'git multi-pack-index repack'"
 
-#: builtin/gc.c
 msgid ""
 "skipping incremental-repack task because core.multiPackIndex is disabled"
 msgstr ""
-"tasc athphacáil fáis a scipeáil toisc go bhfuil core.multiPackIndex "
-"díchumasaithe"
+"ag scipeáil an tasc athphacála incriminteach mar go bhfuil "
+"core.multiPackIndex díchumasaithe"
 
-#: builtin/gc.c
-#, c-format
-msgid "lock file '%s' exists, skipping maintenance"
-msgstr "tá comhad glasála '%s' ann, ag scipeáil cothabháil"
+msgid "failed to perform geometric repack"
+msgstr "theip ar athphacáil gheoiméadrach a dhéanamh"
 
-#: builtin/gc.c
 #, c-format
 msgid "task '%s' failed"
 msgstr "theip ar thasc '%s'"
 
-#: builtin/gc.c
+#, c-format
+msgid "lock file '%s' exists, skipping maintenance"
+msgstr "tá comhad glasála '%s' ann, ag scipeáil cothabháil"
+
+#, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "straitéis chothabhála anaithnid: '%s'"
+
 #, c-format
 msgid "'%s' is not a valid task"
 msgstr "Ní tasc bailí é '%s'"
 
-#: builtin/gc.c
 #, c-format
 msgid "task '%s' cannot be selected multiple times"
 msgstr "ní féidir tasc '%s' a roghnú arís agus arís eile"
 
-#: builtin/gc.c
 msgid "run tasks based on the state of the repository"
 msgstr "tascanna a reáchtáil bunaithe ar staid an stór"
 
-#: builtin/gc.c
 msgid "perform maintenance in the background"
 msgstr "cothabháil a dhéanamh sa chúlra"
 
-#: builtin/gc.c
 msgid "frequency"
 msgstr "minicíocht"
 
-#: builtin/gc.c
 msgid "run tasks based on frequency"
 msgstr "tascanna a rith bunaithe ar mhinicíocht"
 
-#: builtin/gc.c
 msgid "do not report progress or other information over stderr"
 msgstr "ná tuairiscigh dul chun cinn nó faisnéis eile faoi stderr"
 
-#: builtin/gc.c
 msgid "task"
 msgstr "tasc"
 
-#: builtin/gc.c
 msgid "run a specific task"
 msgstr "tasc ar leith a reáchtáil"
 
-#: builtin/gc.c
-msgid "use at most one of --auto and --schedule=<frequency>"
-msgstr "bain úsáid as --auto agus --schedule=<frequency> ar a mhéad"
-
-#: builtin/gc.c
 #, c-format
 msgid "unable to add '%s' value of '%s'"
-msgstr "nach féidir luach '%s' de '%s' a chur leis"
+msgstr "ní féidir luach '%s' de '%s' a chur leis"
 
-#: builtin/gc.c
 msgid "return success even if repository was not registered"
 msgstr "rath ar ais fiú mura raibh stór cláraithe"
 
-#: builtin/gc.c
 #, c-format
 msgid "unable to unset '%s' value of '%s'"
-msgstr "nach féidir luach '%s' de '%s' a dhíshocrú"
+msgstr "ní féidir luach '%s' de '%s' a dhíshuiteáil"
 
-#: builtin/gc.c
 #, c-format
 msgid "repository '%s' is not registered"
 msgstr "níl stór '%s' cláraithe"
 
-#: builtin/gc.c
 #, c-format
 msgid "failed to expand path '%s'"
 msgstr "theip ar an gcosán '%s' a leathnú"
 
-#: builtin/gc.c
 msgid "failed to start launchctl"
 msgstr "theip ar launchctl a thosú"
 
-#: builtin/gc.c
 #, c-format
 msgid "failed to create directories for '%s'"
 msgstr "theip ar eolairí a chruthú do '%s'"
 
-#: builtin/gc.c
 #, c-format
 msgid "failed to bootstrap service %s"
 msgstr "theip ar sheirbhís bootstrap %s"
 
-#: builtin/gc.c
 msgid "failed to create temp xml file"
 msgstr "theip ar chomhad xml temp a chruthú"
 
-#: builtin/gc.c
 msgid "failed to start schtasks"
 msgstr "theip ar schasks a thosú"
 
-#: builtin/gc.c
 msgid "failed to run 'crontab -l'; your system might not support 'cron'"
 msgstr ""
 "theip ar 'crontab -l' a reáchtáil; b'fhéidir nach dtacaíonn do chóras le "
 "'cron'"
 
-#: builtin/gc.c
 msgid "failed to create crontab temporary file"
 msgstr "theip ar chomhad sealadach crontab a chruthú"
 
-#: builtin/gc.c
 msgid "failed to open temporary file"
 msgstr "theip ar chomhad sealadach a oscailt"
 
-#: builtin/gc.c
 msgid "failed to run 'crontab'; your system might not support 'cron'"
 msgstr ""
 "theip ar 'crontab' a reáchtáil; b'fhéidir nach dtacaíonn do chóras le 'cron'"
 
-#: builtin/gc.c
 msgid "'crontab' died"
 msgstr "Fuair 'crontab' bás"
 
-#: builtin/gc.c builtin/worktree.c
 #, c-format
 msgid "failed to delete '%s'"
 msgstr "theip ar '%s' a scriosadh"
 
-#: builtin/gc.c rerere.c
 #, c-format
 msgid "failed to flush '%s'"
 msgstr "theip ar '%s' a shruthlú"
 
-#: builtin/gc.c
 msgid "failed to start systemctl"
 msgstr "theip ar systemctl a thosú"
 
-#: builtin/gc.c
 msgid "failed to run systemctl"
 msgstr "theip ar systemctl a reáchtáil"
 
-#: builtin/gc.c
 #, c-format
 msgid "unrecognized --scheduler argument '%s'"
 msgstr "argóint --scheduler gan aithint '%s'"
 
-#: builtin/gc.c
 msgid "neither systemd timers nor crontab are available"
 msgstr "níl uaireoirí systemd ná crontab ar fáil"
 
-#: builtin/gc.c
 #, c-format
 msgid "%s scheduler is not available"
 msgstr "Níl sceidealóir %s ar fáil"
 
-#: builtin/gc.c
 #, c-format
 msgid ""
 "unable to create '%s.lock': %s.\n"
@@ -8812,7 +7669,7 @@
 "then try again. If it still fails, a git-maintenance(1) process may have\n"
 "crashed in this repository earlier: remove the file manually to continue."
 msgstr ""
-"nach féidir '%s.lock' a chruthú: %s.\n"
+"ní féidir '%s.lock' a chruthú: %s.\n"
 "\n"
 "Is cosúil go bhfuil próiseas sceidealaithe eile git-maintenance(1) ag rith "
 "sa\n"
@@ -8823,305 +7680,234 @@
 "tháinig isteach sa stór seo níos luaithe: bain an comhad de láimh chun "
 "leanúint ar aghaidh."
 
-#: builtin/gc.c
 msgid "cannot acquire lock for scheduled background maintenance"
 msgstr "ní féidir glas a fháil le haghaidh cothabháil sceidealta cúlra"
 
-#: builtin/gc.c
 msgid "git maintenance start [--scheduler=<scheduler>]"
-msgstr "<scheduler>tús cothabhála git [--scheduler=]"
+msgstr "git maintenance start [--scheduler=<scheduler>]"
 
-#: builtin/gc.c
 msgid "scheduler"
 msgstr "sceidealóir"
 
-#: builtin/gc.c
 msgid "scheduler to trigger git maintenance run"
 msgstr "sceidealóir chun rith cothabhála git a spreagadh"
 
-#: builtin/gc.c
 msgid "failed to set up maintenance schedule"
 msgstr "theip ar sceideal cothabhála a chur ar bun"
 
-#: builtin/gc.c
 msgid "failed to add repo to global config"
 msgstr "theip ar repo a chur le cumraíocht domhanda"
 
-#: builtin/gc.c
 msgid "git maintenance <subcommand> [<options>]"
-msgstr "cothabháil git <subcommand>[<options>]"
+msgstr "git maintenance <subcommand> [<options>]"
 
-#: builtin/grep.c
 msgid "git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"
 msgstr "git grep [<options>] [-e] <pattern>[<rev>...] [[--]<path>...]"
 
-#: builtin/grep.c
 #, c-format
 msgid "grep: failed to create thread: %s"
 msgstr "grep: theip ar shnáithe a chruthú: %s"
 
-#: builtin/grep.c
 #, c-format
 msgid "invalid number of threads specified (%d) for %s"
 msgstr "líon neamhbhailí na snáitheanna a shonraítear (%d) do %s"
 
+#. #-#-#-#-#  grep.c.po  #-#-#-#-#
 #. TRANSLATORS: %s is the configuration
 #. variable for tweaking threads, currently
 #. grep.threads
 #.
-#: builtin/grep.c builtin/index-pack.c builtin/pack-objects.c
 #, c-format
 msgid "no threads support, ignoring %s"
 msgstr "gan tacaíocht do shnáitheanna, ag déanamh neamhaird ar %s"
 
-#: builtin/grep.c
 #, c-format
 msgid "unable to read tree %s"
-msgstr "nach féidir crann %s a léamh"
+msgstr "ní féidir crann %s a léamh"
 
-#: builtin/grep.c
 #, c-format
 msgid "unable to grep from object of type %s"
-msgstr "in ann grep ó réad de chineál %s"
+msgstr "ní féidir grep a dhéanamh ó réad de chineál %s"
 
-#: builtin/grep.c
 #, c-format
 msgid "switch `%c' expects a numerical value"
 msgstr "tá an lasc `%c' ag súil le luach uimhriúil"
 
-#: builtin/grep.c
 msgid "search in index instead of in the work tree"
 msgstr "cuardaigh san innéacs in ionad sa chrann oibre"
 
-#: builtin/grep.c
 msgid "find in contents not managed by git"
 msgstr "aimsigh in ábhar nach mbainistíonn git"
 
-#: builtin/grep.c
 msgid "search in both tracked and untracked files"
 msgstr "cuardach i gcomhaid rianaithe agus neamhrianaithe araon"
 
-#: builtin/grep.c
 msgid "ignore files specified via '.gitignore'"
 msgstr "neamhaird a dhéanamh ar chomhaid a shonraítear trí '.gitignore'"
 
-#: builtin/grep.c
 msgid "recursively search in each submodule"
 msgstr "cuardach athshlánach i ngach fo-mhodúl"
 
-#: builtin/grep.c
 msgid "show non-matching lines"
 msgstr "línte neamh-mheaitseála a"
 
-#: builtin/grep.c
 msgid "case insensitive matching"
 msgstr "meaitseáil cás neamhíogair"
 
-#: builtin/grep.c
 msgid "match patterns only at word boundaries"
 msgstr "patrúin a mheaitseáil ach ag teorainneacha focal"
 
-#: builtin/grep.c
 msgid "process binary files as text"
 msgstr "comhaid dénártha a phróiseáil mar th"
 
-#: builtin/grep.c
 msgid "don't match patterns in binary files"
 msgstr "ná meaitseáil patrúin i gcomhaid dénártha"
 
-#: builtin/grep.c
 msgid "process binary files with textconv filters"
 msgstr "comhaid dénártha a phróiseáil le scagairí textconv"
 
-#: builtin/grep.c
 msgid "search in subdirectories (default)"
 msgstr "cuardaigh i bhfo-eolairí (réamhshocrú)"
 
-#: builtin/grep.c
 msgid "descend at most <n> levels"
 msgstr "síos ag an bhformhór na <n>leibh"
 
-#: builtin/grep.c
 msgid "use extended POSIX regular expressions"
 msgstr "bain úsáid as nathanna rialta POSIX leathnaithe"
 
-#: builtin/grep.c
 msgid "use basic POSIX regular expressions (default)"
 msgstr "úsáid abairtí rialta bunúsacha POSIX (réamhshocraithe)"
 
-#: builtin/grep.c
 msgid "interpret patterns as fixed strings"
 msgstr "patrúin a léiriú mar teaghráin seasta"
 
-#: builtin/grep.c
 msgid "use Perl-compatible regular expressions"
 msgstr "úsáid abairtí rialta atá comhoiriúnach le PERL"
 
-#: builtin/grep.c
 msgid "show line numbers"
 msgstr "taispeáin uimhreacha líne"
 
-#: builtin/grep.c
 msgid "show column number of first match"
 msgstr "taispeáin uimhir cholún an chéad chluiche"
 
-#: builtin/grep.c
 msgid "don't show filenames"
 msgstr "ná taispeáin ainmneacha comhaid"
 
-#: builtin/grep.c
 msgid "show filenames"
 msgstr "taispeáin ainmneacha comhaid"
 
-#: builtin/grep.c
 msgid "show filenames relative to top directory"
 msgstr "ainmneacha comhaid a thaispeáint i gcoibhneas"
 
-#: builtin/grep.c
 msgid "show only filenames instead of matching lines"
 msgstr "taispeáint ach ainmneacha comhaid in ionad línte meaitseála"
 
-#: builtin/grep.c
 msgid "synonym for --files-with-matches"
 msgstr "comhchiallach do --files-with-matches"
 
-#: builtin/grep.c
 msgid "show only the names of files without match"
 msgstr "taispeáint ach ainmneacha na gcomhaid gan meaitseáil"
 
-#: builtin/grep.c
 msgid "print NUL after filenames"
 msgstr "priontáil NUL tar éis ainmneacha comhaid"
 
-#: builtin/grep.c
 msgid "show only matching parts of a line"
 msgstr "taispeáin ach codanna de líne a mheaitseáil"
 
-#: builtin/grep.c
 msgid "show the number of matches instead of matching lines"
 msgstr "taispeáint líon na gcluichí in ionad línte meaitseála"
 
-#: builtin/grep.c
 msgid "highlight matches"
 msgstr "cluichí aibhsithe"
 
-#: builtin/grep.c
 msgid "print empty line between matches from different files"
 msgstr "priontáil líne folamh idir cluichí ó chomhaid éagsúla"
 
-#: builtin/grep.c
 msgid "show filename only once above matches from same file"
 msgstr ""
 "taispeáin ainm comhaid ach uair amháin thuas na cluichí ón gcomhad céanna"
 
-#: builtin/grep.c
 msgid "show <n> context lines before and after matches"
-msgstr "<n>línte comhthéacs a thaispeáint roimh agus tar"
+msgstr "taispeáin línte comhthéacs <n> roimh agus i ndiaidh cluichí"
 
-#: builtin/grep.c
 msgid "show <n> context lines before matches"
-msgstr "<n>línte comhthéacs a thaispeáint"
+msgstr "taispeáin línte comhthéacs <n> roimh mheaitseálacha"
 
-#: builtin/grep.c
 msgid "show <n> context lines after matches"
-msgstr "<n>línte comhthéacs a thaispeáint"
+msgstr "taispeáin línte comhthéacs <n> i ndiaidh cluichí"
 
-#: builtin/grep.c
 msgid "use <n> worker threads"
 msgstr "úsáid sná <n>itheanna oibrithe"
 
-#: builtin/grep.c
 msgid "shortcut for -C NUM"
 msgstr "aicearra le haghaidh -C NUM"
 
-#: builtin/grep.c
 msgid "show a line with the function name before matches"
 msgstr "taispeáint líne leis an ainm feidhme roimh mheaitseálacha"
 
-#: builtin/grep.c
 msgid "show the surrounding function"
 msgstr "taispeáin an fheidhm máguaird"
 
-#: builtin/grep.c
 msgid "read patterns from file"
 msgstr "patrúin a léamh ón gcomhad"
 
-#: builtin/grep.c
 msgid "match <pattern>"
 msgstr "comhoiriúnú <pattern>"
 
-#: builtin/grep.c
 msgid "combine patterns specified with -e"
 msgstr "comhcheangal patrúin a shonraítear le -e"
 
-#: builtin/grep.c
 msgid "indicate hit with exit status without output"
 msgstr "léirigh bualadh le stádas imeachta gan aschur"
 
-#: builtin/grep.c
 msgid "show only matches from files that match all patterns"
 msgstr "taispeáin ach cluichí ó chomhaid a mheaitseálann gach patrún"
 
-#: builtin/grep.c
 msgid "pager"
 msgstr "pager"
 
-#: builtin/grep.c
 msgid "show matching files in the pager"
 msgstr "taispeáint comhaid mheaitseála sa pager"
 
-#: builtin/grep.c
 msgid "allow calling of grep(1) (ignored by this build)"
 msgstr "cead a ghlaoch grep (1) (neamhaird ag an tógáil seo)"
 
-#: builtin/grep.c
 msgid "maximum number of results per file"
 msgstr "líon uasta na dtorthaí in aghaidh an chomhad"
 
-#: builtin/grep.c
 msgid "no pattern given"
 msgstr "aon phatrún a thugtar"
 
-#: builtin/grep.c
 msgid "--no-index or --untracked cannot be used with revs"
 msgstr "Ní féidir --no-index nó --untracked a úsáid le hathairí"
 
-#: builtin/grep.c
 #, c-format
 msgid "unable to resolve revision: %s"
-msgstr "nach féidir athbhreithniú a réiteach: %s"
+msgstr "ní féidir athbhreithniú a réiteach: %s"
 
-#: builtin/grep.c
 msgid "--untracked not supported with --recurse-submodules"
 msgstr "--untracked nach dtacaítear le --recurse-submodules"
 
-#: builtin/grep.c
 msgid "invalid option combination, ignoring --threads"
 msgstr "teaglaim roghanna neamhbhailí, ag neamhaird --threads"
 
-#: builtin/grep.c builtin/pack-objects.c
 msgid "no threads support, ignoring --threads"
 msgstr "níl aon tacaíocht do shnáitheanna, ag déanamh neamhaird ar --threads"
 
-#: builtin/grep.c builtin/index-pack.c builtin/pack-objects.c
 #, c-format
 msgid "invalid number of threads specified (%d)"
 msgstr "líon neamhbhailí na snáitheanna sonraithe (%d)"
 
-#: builtin/grep.c
 msgid "--open-files-in-pager only works on the worktree"
 msgstr "Ní oibríonn --open-files-in-pager ach ar an gcrann oibre"
 
-#: builtin/grep.c
 msgid "--[no-]exclude-standard cannot be used for tracked contents"
 msgstr ""
 "- ní féidir caighdeán eisiach [no-] a úsáid le haghaidh ábhar rianaithe"
 
-#: builtin/grep.c
 msgid "both --cached and trees are given"
 msgstr "tugtar --cached agus crainn araon"
 
-#: builtin/hash-object.c
 msgid ""
 "git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n"
 "                [--stdin [--literally]] [--] <file>..."
@@ -9129,116 +7915,90 @@
 "git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n"
 "                [--stdin [--literally]] [--] <file>..."
 
-#: builtin/hash-object.c
 msgid "git hash-object [-t <type>] [-w] --stdin-paths [--no-filters]"
 msgstr "git hash-object [-t <type>] [-w] --stdin-paths [--no-filters]"
 
-#: builtin/hash-object.c
 msgid "object type"
 msgstr "cineál réad"
 
-#: builtin/hash-object.c
 msgid "write the object into the object database"
 msgstr "scríobh an réad isteach sa bhunachar sonraí réad"
 
-#: builtin/hash-object.c
 msgid "read the object from stdin"
 msgstr "léigh an réad ó stdin"
 
-#: builtin/hash-object.c
 msgid "store file as is without filters"
 msgstr "comhad a stóráil mar atá gan scagairí"
 
-#: builtin/hash-object.c
 msgid ""
 "just hash any random garbage to create corrupt objects for debugging Git"
 msgstr ""
-"ní gá ach aon truflais randamach a chur chun rudaí truaillithe a chruthú le "
-"haghaidh dífhab"
+"níl le déanamh ach aon bhruscar randamach a hasháil chun réada truaillithe a "
+"chruthú le haghaidh dífhabhtaithe Git"
 
-#: builtin/hash-object.c
 msgid "process file as it were from this path"
 msgstr "comhad próiseála mar a bhí sé ón gcosán seo"
 
-#: builtin/help.c
 msgid "print all available commands"
 msgstr "gach ordú atá ar fáil a phriontáil"
 
-#: builtin/help.c
 msgid "show external commands in --all"
 msgstr "taispeáint orduithe seachtracha i --all"
 
-#: builtin/help.c
 msgid "show aliases in --all"
 msgstr "taispeáin ainmneacha in --all"
 
-#: builtin/help.c
 msgid "exclude guides"
 msgstr "treoracha a eisiamh"
 
-#: builtin/help.c
 msgid "show man page"
 msgstr "taispeáin leathanach fear"
 
-#: builtin/help.c
 msgid "show manual in web browser"
 msgstr "taispeáin lámhleabhar sa bhrabhsála"
 
-#: builtin/help.c
 msgid "show info page"
 msgstr "taispeáin leathanach faisnéise"
 
-#: builtin/help.c
 msgid "print command description"
 msgstr "cur síos ordaithe priontála"
 
-#: builtin/help.c
 msgid "print list of useful guides"
 msgstr "liosta priontáil de threoracha úsáideacha"
 
-#: builtin/help.c
 msgid "print list of user-facing repository, command and file interfaces"
 msgstr ""
 "liosta priontála de stór, comhéadain ordaithe agus comhad atá os comhair "
 "úsáideora"
 
-#: builtin/help.c
 msgid "print list of file formats, protocols and other developer interfaces"
 msgstr ""
 "liosta priontála formáidí comhaid, prótacail agus comhéadain forbróra eile"
 
-#: builtin/help.c
 msgid "print all configuration variable names"
 msgstr "priontáil gach ainm athróg cumraíochta"
 
-#: builtin/help.c
 msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>|<doc>]"
 msgstr "<command><doc>git help [[-i|--eolas] [-m|--fear] [-w|--gréasáin]] [|]"
 
-#: builtin/help.c
 #, c-format
 msgid "unrecognized help format '%s'"
 msgstr "formáid cabhrach gan aithint '%s'"
 
-#: builtin/help.c
 msgid "Failed to start emacsclient."
 msgstr "Theip ar emacsclient a thosú."
 
-#: builtin/help.c
 msgid "Failed to parse emacsclient version."
 msgstr "Theip ar leagan emacsclient a pháirseáil."
 
-#: builtin/help.c
 #, c-format
 msgid "emacsclient version '%d' too old (< 22)."
 msgstr "leagan imacsclient '%d' ró-sean (< 22)."
 
-#: builtin/help.c
 #, c-format
 msgid "failed to exec '%s'"
 msgstr "theip ar '%s' a fheidhmiú"
 
-#: builtin/help.c
 #, c-format
 msgid ""
 "'%s': path for unsupported man viewer.\n"
@@ -9247,7 +8007,6 @@
 "'%s': cosán do lucht féachana fear gan tacaíocht.\n"
 "Smaoinigh ar 'fear a úsáid le do thoil. <tool>.cmd' ina ionad."
 
-#: builtin/help.c
 #, c-format
 msgid ""
 "'%s': cmd for supported man viewer.\n"
@@ -9256,51 +8015,41 @@
 "'%s': cmd do lucht féachana fear tacaithe.\n"
 "Smaoinigh ar 'fear a úsáid le do thoil. <tool>.path' ina ionad sin."
 
-#: builtin/help.c
 #, c-format
 msgid "'%s': unknown man viewer."
 msgstr "'%s': féachtóir fear anaithnid."
 
-#: builtin/help.c
 msgid "no man viewer handled the request"
 msgstr "níl aon fhéachtóir fear ar an iarraidh"
 
-#: builtin/help.c
 msgid "no info viewer handled the request"
 msgstr "níl aon fhéachtóir faisnéise ag láimhseáil"
 
-#: builtin/help.c git.c
 #, c-format
 msgid "'%s' is aliased to '%s'"
 msgstr "Tá '%s' aistrithe go '%s'"
 
-#: builtin/help.c git.c
 #, c-format
 msgid "bad alias.%s string: %s"
 msgstr "droch-ainm. Teagán %s: %s"
 
-#: builtin/help.c
 #, c-format
 msgid "the '%s' option doesn't take any non-option arguments"
 msgstr "ní ghlacann an rogha '%s' aon argóintí neamh-rogha"
 
-#: builtin/help.c
 msgid ""
 "the '--no-[external-commands|aliases]' options can only be used with '--all'"
 msgstr ""
 "ní féidir na roghanna '--no- [external-commands|aliases] 'a úsáid ach le' --"
 "all '"
 
-#: builtin/help.c
 #, c-format
 msgid "usage: %s%s"
 msgstr "úsáid: %s%s"
 
-#: builtin/help.c
 msgid "'git help config' for more information"
 msgstr "'git help config' le haghaidh tuilleadh faisnéise"
 
-#: builtin/hook.c
 msgid ""
 "git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-"
 "args>]"
@@ -9308,30 +8057,24 @@
 "<path><hook-name><hook-args>git hook run [--ignore-missing] [--to-stdin =] "
 "[--]"
 
-#: builtin/hook.c
 msgid "silently ignore missing requested <hook-name>"
 msgstr "neamhaird go ciúin a iarrtar ar <hook-name>"
 
-#: builtin/hook.c
 msgid "file to read into hooks' stdin"
 msgstr "comhad le léamh isteach i stdin na hracaí"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "object type mismatch at %s"
 msgstr "mímheaitseáil cineál réad ag %s"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "did not receive expected object %s"
 msgstr "nár bhfuair sé réad ag súil leis %s"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "object %s: expected type %s, found %s"
 msgstr "réad %s: súil leis an gcineál %s, aimsíodh %s"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "cannot fill %d byte"
 msgid_plural "cannot fill %d bytes"
@@ -9339,64 +8082,50 @@
 msgstr[1] "ní féidir %d beart a líonadh"
 msgstr[2] "ní féidir %d beart a líonadh"
 
-#: builtin/index-pack.c
 msgid "early EOF"
 msgstr "luath EOF"
 
-#: builtin/index-pack.c
 msgid "read error on input"
 msgstr "earráid léigh ar ionchur"
 
-#: builtin/index-pack.c
 msgid "used more bytes than were available"
 msgstr "úsáideadh níos mó bytes ná mar a bhí ar fáil"
 
-#: builtin/index-pack.c builtin/pack-objects.c
 msgid "pack too large for current definition of off_t"
 msgstr "pacáiste ró-mhór le haghaidh sainmhíniú reatha ar off_t"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "pack exceeds maximum allowed size (%s)"
 msgstr "sáraíonn an pacáiste an méid uasta ceadaithe (%s)"
 
-#: builtin/index-pack.c
 msgid "pack signature mismatch"
 msgstr "mímheaitseáil sínithe pacáiste"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "pack version %<PRIu32> unsupported"
 msgstr "leagan pacáiste %<PRIu32> gan tacaíocht"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "pack has bad object at offset %<PRIuMAX>: %s"
 msgstr "tá réad lochtach sa phacáiste ag an bhfritháireamh %<PRIuMAX>: %s"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "inflate returned %d"
 msgstr "infleáil ar ais %d"
 
-#: builtin/index-pack.c
 msgid "offset value overflow for delta base object"
 msgstr "ró-shreabhadh luacha a fhritháireamh do réad"
 
-#: builtin/index-pack.c
 msgid "delta base offset is out of bound"
 msgstr "tá fhritháireamh bonn delta as ceangailte"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "unknown object type %d"
 msgstr "cineál réad anaithnid %d"
 
-#: builtin/index-pack.c
 msgid "cannot pread pack file"
 msgstr "ní féidir comhad pacáiste a roghnú"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "premature end of pack file, %<PRIuMAX> byte missing"
 msgid_plural "premature end of pack file, %<PRIuMAX> bytes missing"
@@ -9404,81 +8133,63 @@
 msgstr[1] "deireadh roimh am comhaid phacáiste, %<PRIuMAX> beart ar iarraidh"
 msgstr[2] "deireadh roimh am comhaid phacáiste, %<PRIuMAX> beart ar iarraidh"
 
-#: builtin/index-pack.c
 msgid "serious inflate inconsistency"
 msgstr "neamhchomhsheasmhacht tromchúiseach"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "SHA1 COLLISION FOUND WITH %s !"
 msgstr "FUARTHAS IMBHALL SHA1 LE %s!"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "cannot read existing object info %s"
 msgstr "ní féidir faisnéis réad atá ann cheana %s a léamh"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "cannot read existing object %s"
 msgstr "ní féidir réad %s atá ann cheana a léamh"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "invalid blob object %s"
 msgstr "réad blob neamhbhailí %s"
 
-#: builtin/index-pack.c
 msgid "fsck error in packed object"
 msgstr "earráid fsck i réad pacáilte"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "Not all child objects of %s are reachable"
-msgstr "Níl gach réad leanbh de %s inrochtana"
+msgstr "Ní féidir rochtain a fháil ar gach réad linbh de %s"
 
-#: builtin/index-pack.c
 msgid "failed to apply delta"
 msgstr "theip ar delta a chur i bhfeidhm"
 
-#: builtin/index-pack.c
 msgid "Receiving objects"
 msgstr "Rudaí a fháil"
 
-#: builtin/index-pack.c
 msgid "Indexing objects"
 msgstr "Rudaí innéacsála"
 
-#: builtin/index-pack.c
 msgid "pack is corrupted (SHA1 mismatch)"
 msgstr "tá an pacáiste truaillithe (neamhoiriúnú SHA1)"
 
-#: builtin/index-pack.c
 msgid "cannot fstat packfile"
 msgstr "ní féidir le pacáiste fstat"
 
-#: builtin/index-pack.c
 msgid "pack has junk at the end"
 msgstr "tá bruscar ag an bpacáiste ag an deireadh"
 
-#: builtin/index-pack.c
 msgid "confusion beyond insanity in parse_pack_objects()"
 msgstr "mearbhall níos faide ná imní i parse_pack_objects()"
 
-#: builtin/index-pack.c
 msgid "Resolving deltas"
 msgstr "Deltas a réiteach"
 
-#: builtin/index-pack.c builtin/pack-objects.c
 #, c-format
 msgid "unable to create thread: %s"
-msgstr "nach féidir snáithe a chruthú: %s"
+msgstr "ní féidir snáithe a chruthú: %s"
 
-#: builtin/index-pack.c
 msgid "confusion beyond insanity"
 msgstr "mearbhall níos faide ná mar gheall"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "completed with %d local object"
 msgid_plural "completed with %d local objects"
@@ -9486,12 +8197,10 @@
 msgstr[1] "críochnaithe le %d réad áitiúil"
 msgstr[2] "críochnaithe le %d réad áitiúil"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "Unexpected tail checksum for %s (disk corruption?)"
 msgstr "Seicsum eireaball gan choinne do %s (éilliú diosca?)"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "pack has %d unresolved delta"
 msgid_plural "pack has %d unresolved deltas"
@@ -9499,56 +8208,45 @@
 msgstr[1] "tá %d deiltí gan réiteach sa phacáiste"
 msgstr[2] "tá %d deiltí gan réiteach sa phacáiste"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "unable to deflate appended object (%d)"
-msgstr "nach féidir réad cuibheangailte a dhíscaoileadh (%d)"
+msgstr "ní féidir an réad breise a dhíbhoilsciú (%d)"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "local object %s is corrupt"
 msgstr "tá réad áitiúil %s truaillithe"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "packfile name '%s' does not end with '.%s'"
 msgstr "ní chríochnaíonn ainm pacáiste '%s' le '.%s'"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "cannot write %s file '%s'"
 msgstr "ní féidir comhad %s '%s' a scríobh"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "cannot close written %s file '%s'"
 msgstr "ní féidir comhad %s scríofa '%s' a dhúnadh"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "unable to rename temporary '*.%s' file to '%s'"
-msgstr "in ann athainmniú sealadach '*.%s' comhad chuig '%s'"
+msgstr "ní féidir an comhad sealadach '*.%s' a athainmniú go '%s'"
 
-#: builtin/index-pack.c
 msgid "error while closing pack file"
 msgstr "earráid agus comhad pacáiste á dúnadh"
 
-#: builtin/index-pack.c builtin/pack-objects.c
 #, c-format
 msgid "bad pack.indexVersion=%<PRIu32>"
 msgstr "droch-pack.indexVersion=%<PRIu32>"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "Cannot open existing pack file '%s'"
 msgstr "Ní féidir comhad pacáiste atá ann cheana '%s' a oscailt"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "Cannot open existing pack idx file for '%s'"
 msgstr "Ní féidir comhad idx pacáiste atá ann cheana a oscailt do '%s'"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "non delta: %d object"
 msgid_plural "non delta: %d objects"
@@ -9556,7 +8254,6 @@
 msgstr[1] "neamh-delta: %d réad"
 msgstr[2] "neamh-delta: %d réad"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "chain length = %d: %lu object"
 msgid_plural "chain length = %d: %lu objects"
@@ -9564,60 +8261,47 @@
 msgstr[1] "fad slabhra = %d: %lu réada"
 msgstr[2] "fad slabhra = %d: %lu réada"
 
-#: builtin/index-pack.c
 msgid "could not start pack-objects to repack local links"
 msgstr "ní fhéadfaí pacáiste-earraí a thosú chun naisc áitiúla a athphacáil"
 
-#: builtin/index-pack.c
 msgid "failed to feed local object to pack-objects"
 msgstr "theip ar réad áitiúil a bheathú ar rudaí pacáiste"
 
-#: builtin/index-pack.c
 msgid "index-pack: Expecting full hex object ID lines only from pack-objects."
 msgstr ""
 "index-pack: Ag súil le línte aitheantais réada heicsidheachúlach iomlán ó "
 "pack-objects amháin."
 
-#: builtin/index-pack.c
 msgid "could not finish pack-objects to repack local links"
 msgstr "ní fhéadfaí pacáistí a chríochnú chun naisc áitiúla a athphacáil"
 
-#: builtin/index-pack.c
 msgid "Cannot come back to cwd"
 msgstr "Ní féidir teacht ar ais chuig cwd"
 
-#: builtin/index-pack.c builtin/unpack-objects.c
 #, c-format
 msgid "bad --pack_header: %s"
 msgstr "droch --pack_header: %s"
 
-#: builtin/index-pack.c
 #, c-format
 msgid "bad %s"
 msgstr "droch %s"
 
-#: builtin/index-pack.c builtin/init-db.c setup.c
 #, c-format
 msgid "unknown hash algorithm '%s'"
 msgstr "algartam hais anaithnid '%s'"
 
-#: builtin/index-pack.c
 msgid "--promisor cannot be used with a pack name"
 msgstr "--promisor ní féidir é a úsáid le hainm pacáiste"
 
-#: builtin/index-pack.c
 msgid "--stdin requires a git repository"
 msgstr "--stdin teastaíonn stórlann git"
 
-#: builtin/index-pack.c
 msgid "--verify with no packfile name given"
 msgstr "--verify gan ainm comhaid pacáiste tugtha"
 
-#: builtin/index-pack.c builtin/unpack-objects.c
 msgid "fsck error in pack objects"
 msgstr "fsck earráid i rudaí pacáiste"
 
-#: builtin/init-db.c
 msgid ""
 "git init [-q | --quiet] [--bare] [--template=<template-directory>]\n"
 "         [--separate-git-dir <git-dir>] [--object-format=<format>]\n"
@@ -9631,37 +8315,29 @@
 "         [-b <branch-name> | --initial-branch=<branch-name>]\n"
 "         [--shared[=<permissions>]] [<directory>]"
 
-#: builtin/init-db.c
 msgid "permissions"
 msgstr "ceadanna"
 
-#: builtin/init-db.c
 msgid "specify that the git repository is to be shared amongst several users"
 msgstr "sonraigh go bhfuil an stór git le roinnt i measc roinnt úsáideoirí"
 
-#: builtin/init-db.c
 msgid "override the name of the initial branch"
 msgstr "ainm na brainse tosaigh a shárú"
 
-#: builtin/init-db.c builtin/verify-pack.c
 msgid "hash"
-msgstr "hash"
+msgstr "hais"
 
-#: builtin/init-db.c builtin/show-index.c builtin/verify-pack.c
 msgid "specify the hash algorithm to use"
 msgstr "sonraigh an algartam hash le húsáid"
 
-#: builtin/init-db.c
 #, c-format
 msgid "cannot mkdir %s"
 msgstr "ní féidir teacht ar %s"
 
-#: builtin/init-db.c
 #, c-format
 msgid "cannot chdir to %s"
 msgstr "ní féidir teacht chuig %s"
 
-#: builtin/init-db.c
 #, c-format
 msgid ""
 "%s (or --work-tree=<directory>) not allowed without specifying %s (or --git-"
@@ -9670,16 +8346,13 @@
 "%s (or --work-tree=<directory>) ní cheadaítear gan sonrú %s (or --git-"
 "dir=<directory>)"
 
-#: builtin/init-db.c
 #, c-format
 msgid "Cannot access work tree '%s'"
 msgstr "Ní féidir rochtain a fháil ar chrann oibre '%s'"
 
-#: builtin/init-db.c
 msgid "--separate-git-dir incompatible with bare repository"
 msgstr "--separate-git-dir neamhoiriúnach le stór lom"
 
-#: builtin/interpret-trailers.c
 msgid ""
 "git interpret-trailers [--in-place] [--trim-empty]\n"
 "                       [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
@@ -9689,225 +8362,211 @@
 "                       [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
 "                       [--parse] [<file>...]"
 
-#: builtin/interpret-trailers.c wrapper.c
 #, c-format
 msgid "could not stat %s"
 msgstr "ní raibh ann %s a shástáil"
 
-#: builtin/interpret-trailers.c
 #, c-format
 msgid "file %s is not a regular file"
 msgstr "ní comhad rialta é comhad %s"
 
-#: builtin/interpret-trailers.c
 #, c-format
 msgid "file %s is not writable by user"
 msgstr "ní féidir an t-úsáideoir comhad %s a scríobh"
 
-#: builtin/interpret-trailers.c
 msgid "could not open temporary file"
 msgstr "ní fhéadfadh comhad sealadach a oscailt"
 
-#: builtin/interpret-trailers.c
 #, c-format
 msgid "could not read input file '%s'"
 msgstr "ní raibh in ann comhad ionchuir '%s' a léamh"
 
-#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c
 msgid "could not read from stdin"
 msgstr "ní fhéadfaí léamh ó stdin"
 
-#: builtin/interpret-trailers.c
 #, c-format
 msgid "could not rename temporary file to %s"
 msgstr "ní fhéadfaí comhad sealadach a athainmniú go %s"
 
-#: builtin/interpret-trailers.c
 msgid "edit files in place"
 msgstr "comhaid in áit a chur in eagar"
 
-#: builtin/interpret-trailers.c
 msgid "trim empty trailers"
 msgstr "leantóirí folamh a ghear"
 
-#: builtin/interpret-trailers.c
 msgid "placement"
 msgstr "socrúcháin"
 
-#: builtin/interpret-trailers.c
 msgid "where to place the new trailer"
 msgstr "cá háit a chuirfear an leantóir nua"
 
-#: builtin/interpret-trailers.c
 msgid "action if trailer already exists"
 msgstr "gníomh má tá leantóir ann cheana féin"
 
-#: builtin/interpret-trailers.c
 msgid "action if trailer is missing"
 msgstr "gníomh má tá leantóir ar iarraidh"
 
-#: builtin/interpret-trailers.c
 msgid "output only the trailers"
 msgstr "aschur ach na leantóirí"
 
-#: builtin/interpret-trailers.c
 msgid "do not apply trailer.* configuration variables"
 msgstr "ná cuir leantóir i bhfeidhm.* athróga cumraíochta"
 
-#: builtin/interpret-trailers.c
 msgid "reformat multiline trailer values as single-line values"
 msgstr "luachanna leantóra illíne a athfhormáidiú mar luachanna aon-líne"
 
-#: builtin/interpret-trailers.c
 msgid "alias for --only-trailers --only-input --unfold"
 msgstr "ainm le haghaidh --only-trailers --only-input --unfold"
 
-#: builtin/interpret-trailers.c
 msgid "do not treat \"---\" as the end of input"
 msgstr "ná déileáil le “---” mar dheireadh an ionchuir"
 
-#: builtin/interpret-trailers.c
 msgid "trailer(s) to add"
 msgstr "leantóir (í) le cur leis"
 
-#: builtin/interpret-trailers.c
 msgid "--trailer with --only-input does not make sense"
 msgstr "níl ciall le --trailer le --only-input"
 
-#: builtin/interpret-trailers.c
 msgid "no input file given for in-place editing"
 msgstr "níl aon chomhad ionchuir a thugtar le haghaidh eagarthóireachta"
 
-#: builtin/log.c
+msgid "last-modified can only operate on one tree at a time"
+msgstr ""
+"ní féidir leis an modhnaithe deireanach oibriú ach ar chrann amháin ag an am "
+"céanna"
+
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "argóint anaithnid a modhnaíodh go deireanach: %s"
+
+msgid "unable to setup last-modified"
+msgstr "ní féidir an modhnú deireanach a shocrú"
+
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+
+msgid "recurse into subtrees"
+msgstr "athshlánú isteach i bhfo-chrainn"
+
+msgid "show tree entries when recursing into subtrees"
+msgstr "taispeáin iontrálacha crainn agus tú ag athfhillteach i bhfochrainn"
+
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
-msgstr "logáil git [<options>] [<revision-range>] [[--]<path>...]"
+msgstr "git log [<options>] [<revision-range>] [[--] <path>...]"
 
-#: builtin/log.c
 msgid "git show [<options>] <object>..."
-msgstr "git show [<options>]<object>..."
+msgstr "git show [<options>] <object>..."
 
-#: builtin/log.c
 #, c-format
 msgid "invalid --decorate option: %s"
 msgstr "rogha neamhbhailí --decorate: %s"
 
-#: builtin/log.c diff.c
 msgid "suppress diff output"
 msgstr "aschur diff a chur faoi chois"
 
-#: builtin/log.c
 msgid "show source"
 msgstr "foinse taispeáin"
 
-#: builtin/log.c
 msgid "clear all previously-defined decoration filters"
 msgstr "glan na scagairí maisiúcháin atá sainmhínithe roimhe seo"
 
-#: builtin/log.c
 msgid "only decorate refs that match <pattern>"
 msgstr "ní mhaisigh ach na cinn a mheaitseálann <pattern>"
 
-#: builtin/log.c
 msgid "do not decorate refs that match <pattern>"
 msgstr "ná maisigh na cinn a mheaitseálann <pattern>"
 
-#: builtin/log.c
 msgid "decorate options"
 msgstr "roghanna maisiú"
 
-#: builtin/log.c
 msgid ""
 "trace the evolution of line range <start>,<end> or function :<funcname> in "
 "<file>"
 msgstr "éabhlóid raon líne<start>, <end>nó feidhm <funcname>a rianú: i <file>"
 
-#: builtin/log.c
 msgid "-L<range>:<file> cannot be used with pathspec"
 msgstr "-L<range>: ní <file>féidir é a úsáid le pathspec"
 
-#: builtin/log.c
-#, c-format
-msgid "Final output: %d %s\n"
-msgstr "Aschur deiridh: %d %s\n"
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+"\n"
+"leid: Is féidir leat 'git whatchanged <opts>' a athsholáthar leis an méid "
+"seo a leanas:\n"
+"leid:\tgit log <opts> --raw --no-merges\n"
+"leid: Nó leasainm a chruthú:\n"
+"leid:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
 
-#: builtin/log.c
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s: droch-chomhad"
 
-#: builtin/log.c
 #, c-format
 msgid "could not read object %s"
 msgstr "ní raibh in ann réad %s a léamh"
 
-#: builtin/log.c
 #, c-format
 msgid "unknown type: %d"
 msgstr "cineál anaithnid: %d"
 
-#: builtin/log.c
 #, c-format
 msgid "%s: invalid cover from description mode"
 msgstr "%s: clúdach neamhbhailí ó mhodh tuairisc"
 
-#: builtin/log.c
 msgid "format.headers without value"
 msgstr "format.headers gan luach"
 
-#: builtin/log.c
 #, c-format
 msgid "cannot open patch file %s"
 msgstr "ní féidir comhad paiste %s a oscailt"
 
-#: builtin/log.c
 msgid "need exactly one range"
 msgstr "teastaíonn raon amháin díreach"
 
-#: builtin/log.c
 msgid "not a range"
-msgstr "ní raon"
+msgstr "ní raon é"
 
-#: builtin/log.c
 #, c-format
 msgid "unable to read branch description file '%s'"
-msgstr "nach féidir an comhad tuairisc brainse '%s' a léamh"
+msgstr "ní féidir comhad cur síos na brainse '%s' a léamh"
 
-#: builtin/log.c
 msgid "cover letter needs email format"
 msgstr "teastaíonn formáid ríomhphoist ó litir"
 
-#: builtin/log.c
 msgid "failed to create cover-letter file"
 msgstr "theip ar chomhad litir chlúdaigh a chruthú"
 
-#: builtin/log.c
 #, c-format
 msgid "insane in-reply-to: %s"
 msgstr "in-fhreagairt daingniúil: %s"
 
-#: builtin/log.c
 msgid "git format-patch [<options>] [<since> | <revision-range>]"
 msgstr "git format-patch [<roghanna>] [<ó> | <raon-athbhreithnithe>]"
 
-#: builtin/log.c
 msgid "two output directories?"
 msgstr "dhá eolaire aschuir?"
 
-#: builtin/log.c
 #, c-format
 msgid "unknown commit %s"
 msgstr "tiomantas anaithnid %s"
 
-#: builtin/log.c builtin/replace.c
 #, c-format
 msgid "failed to resolve '%s' as a valid ref"
 msgstr "theip ar '%s' a réiteach mar thagartha bailí"
 
-#: builtin/log.c
 msgid "could not find exact merge base"
 msgstr "ní fhéadfaí bonn cumaisc cruinn a fháil"
 
-#: builtin/log.c
 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"
@@ -9918,296 +8577,225 @@
 "bain úsáid as git branch --set-upstream-to chun brainse iargúlta a rianú.\n"
 "Nó d'fhéadfá an gealltanas bonn a shonrú trí --base=<base-commit-id> de láimh"
 
-#: builtin/log.c
 msgid "failed to find exact merge base"
 msgstr "theip orthu bonn cumaisc cruinn a fháil"
 
-#: builtin/log.c
 msgid "base commit should be the ancestor of revision list"
 msgstr "ba cheart gurb é bonn tiomantas ina sinsear an liosta athbhrei"
 
-#: builtin/log.c
 msgid "base commit shouldn't be in revision list"
 msgstr "níor cheart go mbeadh tiomantas bonn sa liosta athbhrei"
 
-#: builtin/log.c
 msgid "cannot get patch id"
 msgstr "ní féidir id paiste a fháil"
 
-#: builtin/log.c
 msgid "failed to infer range-diff origin of current series"
 msgstr "theip ar thionscnamh raon difriúil na sraithe reatha a thabhairt amach"
 
-#: builtin/log.c
 #, c-format
 msgid "using '%s' as range-diff origin of current series"
 msgstr "ag baint úsáide as '%s' mar bhunús diff raon na sraithe reatha"
 
-#: builtin/log.c
 msgid "use [PATCH n/m] even with a single patch"
 msgstr "bain úsáid as [PATCH n/m] fiú le paiste amháin"
 
-#: builtin/log.c
 msgid "use [PATCH] even with multiple patches"
 msgstr "bain úsáid as [PATCH] fiú le paistí iolracha"
 
-#: builtin/log.c
 msgid "print patches to standard out"
 msgstr "paistí a phriontáil chun caighdeánach"
 
-#: builtin/log.c
 msgid "generate a cover letter"
 msgstr "litir chlúdaigh a ghiniúint"
 
-#: builtin/log.c
 msgid "use simple number sequence for output file names"
 msgstr "úsáid seicheamh uimhreacha simplí d'ainmneacha comhaid aschu"
 
-#: builtin/log.c
 msgid "sfx"
 msgstr "sfx"
 
-#: builtin/log.c
 msgid "use <sfx> instead of '.patch'"
 msgstr "úsáid <sfx>in ionad '.patch'"
 
-#: builtin/log.c
 msgid "start numbering patches at <n> instead of 1"
 msgstr "tosú ag uimhriú paistí ag <n>seachas 1"
 
-#: builtin/log.c
 msgid "reroll-count"
 msgstr "comhaireamh ath-rollta"
 
-#: builtin/log.c
 msgid "mark the series as Nth re-roll"
 msgstr "marcáil an tsraith mar Nú ath-rolla"
 
-#: builtin/log.c
 msgid "max length of output filename"
 msgstr "fad uasta ainm an chomhaid aschuir"
 
-#: builtin/log.c
 msgid "rfc"
 msgstr "rfc"
 
-#: builtin/log.c
 msgid "add <rfc> (default 'RFC') before 'PATCH'"
 msgstr "cuir <rfc>(réamhshocraithe 'RFC') roimh 'PATCH'"
 
-#: builtin/log.c
 msgid "cover-from-description-mode"
 msgstr "modh clúdaigh ó-tuairiscríbhinní"
 
-#: builtin/log.c
 msgid "generate parts of a cover letter based on a branch's description"
 msgstr "codanna de litir chlúdaigh a ghiniúint bunaithe ar thuairisc brainse"
 
-#: builtin/log.c
 msgid "use branch description from file"
 msgstr "úsáid cur síos brainse ón gcomhad"
 
-#: builtin/log.c
 msgid "use [<prefix>] instead of [PATCH]"
 msgstr "úsáid [<prefix>] in ionad [PATCH]"
 
-#: builtin/log.c
 msgid "store resulting files in <dir>"
 msgstr "comhaid mar thoradh air a stóráil i <dir>"
 
-#: builtin/log.c
 msgid "don't strip/add [PATCH]"
 msgstr "ná stiall/cuir [PATCH] leis"
 
-#: builtin/log.c
 msgid "don't output binary diffs"
 msgstr "ná aschur difríochtaí dénártha"
 
-#: builtin/log.c
 msgid "output all-zero hash in From header"
 msgstr "aschur hash uile-nialas i Ó cheanntásc"
 
-#: builtin/log.c
 msgid "don't include a patch matching a commit upstream"
 msgstr "ná cuir paiste a mheaitseann le tiomantas suas an sruth"
 
-#: builtin/log.c
 msgid "show patch format instead of default (patch + stat)"
 msgstr "taispeáin formáid paiste in ionad réamhshocraithe (paiste + stat)"
 
-#: builtin/log.c
 msgid "Messaging"
 msgstr "Teachtaireachtaí"
 
-#: builtin/log.c
 msgid "header"
 msgstr "ceanntásc"
 
-#: builtin/log.c
 msgid "add email header"
 msgstr "ceanntásc ríomhphoist leis"
 
-#: builtin/log.c
 msgid "email"
 msgstr "ríomhphost"
 
-#: builtin/log.c
 msgid "add To: header"
 msgstr "cuir Le: ceanntásc"
 
-#: builtin/log.c
 msgid "add Cc: header"
 msgstr "cuir Cc leis: ceanntásc"
 
-#: builtin/log.c
 msgid "ident"
 msgstr "idirghníomhaire"
 
-#: builtin/log.c
 msgid "set From address to <ident> (or committer ident if absent)"
 msgstr ""
 "socraigh Ó sheoladh go dtí <ident>(nó aitheantas an tiomantais mura bhfuil "
 "sé ann)"
 
-#: builtin/log.c
 msgid "message-id"
 msgstr "id teachtaireachta"
 
-#: builtin/log.c
 msgid "make first mail a reply to <message-id>"
 msgstr "déan freagra ar an gcéad phost <message-id>"
 
-#: builtin/log.c
 msgid "boundary"
 msgstr "teorainn"
 
-#: builtin/log.c
 msgid "attach the patch"
 msgstr "ceangail an paiste"
 
-#: builtin/log.c
 msgid "inline the patch"
 msgstr "inlíne an paiste"
 
-#: builtin/log.c
 msgid "enable message threading, styles: shallow, deep"
 msgstr "cumasú snáithe teachtaireachta, stíleanna: éadomhain, domhain"
 
-#: builtin/log.c
 msgid "signature"
 msgstr "síniú"
 
-#: builtin/log.c
 msgid "add a signature"
 msgstr "cuir síniú"
 
-#: builtin/log.c
 msgid "base-commit"
 msgstr "bun-tiomantas"
 
-#: builtin/log.c
 msgid "add prerequisite tree info to the patch series"
 msgstr "cuir faisnéis rainn réamhriachtanais leis an tsraith paiste"
 
-#: builtin/log.c
 msgid "add a signature from a file"
 msgstr "cuir síniú ó chomhad"
 
-#: builtin/log.c
 msgid "don't print the patch filenames"
 msgstr "ná priontáil na hainmneacha comhaid paiste"
 
-#: builtin/log.c
 msgid "show progress while generating patches"
 msgstr "dul chun cinn a thaispeáint agus paistí"
 
-#: builtin/log.c
 msgid "show changes against <rev> in cover letter or single patch"
 msgstr "athruithe a thaispeá <rev>int i gcoinne i litir chlúdaigh nó"
 
-#: builtin/log.c
 msgid "show changes against <refspec> in cover letter or single patch"
 msgstr "athruithe a thaispeá <refspec>int i gcoinne i litir chlúdaigh nó"
 
-#: builtin/log.c builtin/range-diff.c
 msgid "percentage by which creation is weighted"
 msgstr "céatadán faoina n-ualaítear an cruthú"
 
-#: builtin/log.c
 msgid "show in-body From: even if identical to the e-mail header"
 msgstr ""
 "taispeáin in-chorp Ó: fiú más comhionann leis an gceannteideal ríomhphoist"
 
-#: builtin/log.c
 #, c-format
 msgid "invalid ident line: %s"
 msgstr "líne aitheantais neamhbhailí: %s"
 
-#: builtin/log.c
 msgid "--name-only does not make sense"
 msgstr "Ní bhíonn ciall ag --name-only"
 
-#: builtin/log.c
 msgid "--name-status does not make sense"
 msgstr "Ní bhíonn ciall ag --name-status"
 
-#: builtin/log.c
 msgid "--check does not make sense"
 msgstr "Ní bhíonn ciall ag --check"
 
-#: builtin/log.c
 msgid "--remerge-diff does not make sense"
 msgstr "Ní bhíonn ciall ag --remerge-diff"
 
-#: builtin/log.c builtin/submodule--helper.c rerere.c submodule.c
 #, c-format
 msgid "could not create directory '%s'"
 msgstr "ní fhéadfaí eolaire '%s' a chruthú"
 
-#: builtin/log.c
 msgid "--interdiff requires --cover-letter or single patch"
 msgstr "éilíonn --interdiff --cover-letter nó paiste singil"
 
-#: builtin/log.c
 msgid "Interdiff:"
 msgstr "Interdiff:"
 
-#: builtin/log.c
 #, c-format
 msgid "Interdiff against v%d:"
 msgstr "Interdiff i gcoinne v%d:"
 
-#: builtin/log.c
 msgid "--range-diff requires --cover-letter or single patch"
 msgstr "Éilíonn --range-diff --cover-letter nó paiste aonair"
 
-#: builtin/log.c
 msgid "Range-diff:"
 msgstr "Difríocht raon:"
 
-#: builtin/log.c
 #, c-format
 msgid "Range-diff against v%d:"
 msgstr "Difríocht raon i gcoinne v%d:"
 
-#: builtin/log.c
 #, c-format
 msgid "unable to read signature file '%s'"
-msgstr "nach féidir an comhad sínithe '%s' a léamh"
+msgstr "ní féidir comhad sínithe '%s' a léamh"
 
-#: builtin/log.c
 msgid "Generating patches"
 msgstr "Giniúint paistí"
 
-#: builtin/log.c
 msgid "failed to create output files"
 msgstr "theip ar chomhaid aschuir a chruthú"
 
-#: builtin/log.c
 msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]"
 msgstr "git cherry [-v] [<upstream> [<head> [<limit>]]]"
 
-#: builtin/log.c
 #, c-format
 msgid ""
 "Could not find a tracked remote branch, please specify <upstream> manually.\n"
@@ -10215,127 +8803,97 @@
 "Níor féidir brainse iargúlta rianaithe a fháil, sonraigh de láimh le do th "
 "<upstream>oil.\n"
 
-#: builtin/ls-files.c builtin/ls-tree.c
 #, c-format
 msgid "could not get object info about '%s'"
 msgstr "ní fhéadfaí faisnéis réada a fháil faoi '%s'"
 
-#: builtin/ls-files.c
 msgid "git ls-files [<options>] [<file>...]"
 msgstr "git ls-files [<options>] [<file>...]"
 
-#: builtin/ls-files.c builtin/merge-tree.c
 msgid "separate paths with the NUL character"
 msgstr "cosáin ar leithligh leis an carachtar NUL"
 
-#: builtin/ls-files.c
 msgid "identify the file status with tags"
 msgstr "stádas an chomhaid a aithint le clibeanna"
 
-#: builtin/ls-files.c
 msgid "use lowercase letters for 'assume unchanged' files"
 msgstr ""
 "bain úsáid as litreacha beaga le haghaidh comhaid 'glacadh leis gan "
 "athraithe'"
 
-#: builtin/ls-files.c
 msgid "use lowercase letters for 'fsmonitor clean' files"
 msgstr "bain úsáid as litreacha beaga le haghaidh comhaid 'fsmonitor clean'"
 
-#: builtin/ls-files.c
 msgid "show cached files in the output (default)"
 msgstr "taispeáint comhaid taispeána san aschur (réamhshocraithe)"
 
-#: builtin/ls-files.c
 msgid "show deleted files in the output"
 msgstr "taispeáint comhaid scriosta san aschur"
 
-#: builtin/ls-files.c
 msgid "show modified files in the output"
 msgstr "taispeáint comhaid modhnaithe san aschur"
 
-#: builtin/ls-files.c
 msgid "show other files in the output"
 msgstr "taispeáint comhaid eile san aschur"
 
-#: builtin/ls-files.c
 msgid "show ignored files in the output"
 msgstr "taispeáint comhaid a neamhaird san aschur"
 
-#: builtin/ls-files.c
 msgid "show staged contents' object name in the output"
 msgstr "taispeáin ainm réad ábhair stáitseáilte san aschur"
 
-#: builtin/ls-files.c
 msgid "show files on the filesystem that need to be removed"
 msgstr "taispeáint comhaid ar an gcóras comhaid is gá a bhaint"
 
-#: builtin/ls-files.c
 msgid "show 'other' directories' names only"
 msgstr "taispeáin ainmneacha 'eile' amháin"
 
-#: builtin/ls-files.c
 msgid "show line endings of files"
 msgstr "taispeáint deireadh líne na gcomhaid"
 
-#: builtin/ls-files.c
 msgid "don't show empty directories"
 msgstr "ná taispeáin eolairí folamh"
 
-#: builtin/ls-files.c
 msgid "show unmerged files in the output"
 msgstr "taispeáint comhaid neamh-chumhdaithe san aschur"
 
-#: builtin/ls-files.c
 msgid "show resolve-undo information"
 msgstr "taispeáin faisnéis réitigh a chealú"
 
-#: builtin/ls-files.c
 msgid "skip files matching pattern"
-msgstr "patrún meaitseála comhaid scipeála"
+msgstr "scipeáil comhaid patrún meaitseála"
 
-#: builtin/ls-files.c
 msgid "read exclude patterns from <file>"
 msgstr "léigh patrúin eisiamh ó <file>"
 
-#: builtin/ls-files.c
 msgid "read additional per-directory exclude patterns in <file>"
 msgstr "léigh patrúin breise in aghaidh eolaire a eisiamh i <file>"
 
-#: builtin/ls-files.c
 msgid "add the standard git exclusions"
 msgstr "cuir na heisiaimh caighdeánacha git"
 
-#: builtin/ls-files.c
 msgid "make the output relative to the project top directory"
 msgstr "déan an t-aschur i gcoibhneas le barr-eolaire an tion"
 
-#: builtin/ls-files.c
 msgid "if any <file> is not in the index, treat this as an error"
 msgstr ""
 "mura <file>bhfuil aon cheann san innéacs, déileáil leis seo mar earráid"
 
-#: builtin/ls-files.c builtin/merge-tree.c
 msgid "tree-ish"
 msgstr "crainn"
 
-#: builtin/ls-files.c
 msgid "pretend that paths removed since <tree-ish> are still present"
 msgstr "ligean go bhfuil cosáin a bhain <tree-ish>tear ó shin fós i láthair"
 
-#: builtin/ls-files.c
 msgid "show debugging data"
 msgstr "taispeáin sonraí dífhabhtaithe"
 
-#: builtin/ls-files.c
 msgid "suppress duplicate entries"
 msgstr "iontrálacha dúbailte a chur"
 
-#: builtin/ls-files.c
 msgid "show sparse directories in the presence of a sparse index"
 msgstr "taispeáint eolairí neamhchoitianta i láthair innéacs neamhchoitianta"
 
-#: builtin/ls-files.c
 msgid ""
 "--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, "
 "--eol"
@@ -10343,7 +8901,6 @@
 "Ní féidir --format a úsáid le -s, -o, -k, -t, --resolve-undo, --deduplicate, "
 "--eol"
 
-#: builtin/ls-remote.c
 msgid ""
 "git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n"
 "              [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n"
@@ -10353,193 +8910,144 @@
 "              [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n"
 "              [--symref] [<repository> [<patterns>...]]"
 
-#: builtin/ls-remote.c
 msgid "do not print remote URL"
 msgstr "ná priontáil URL iargúlta"
 
-#: builtin/ls-remote.c builtin/rebase.c
 msgid "exec"
 msgstr "feidhmiúcháin"
 
-#: builtin/ls-remote.c
 msgid "path of git-upload-pack on the remote host"
 msgstr "cosán git-upload-pack ar an óstach cianda"
 
-#: builtin/ls-remote.c
 msgid "limit to tags"
 msgstr "teorainn le clibeanna"
 
-#: builtin/ls-remote.c
 msgid "limit to branches"
 msgstr "teorainn le brainsí"
 
-#: builtin/ls-remote.c builtin/show-ref.c
 msgid "deprecated synonym for --branches"
 msgstr "comhchiallach scoite do --branches"
 
-#: builtin/ls-remote.c
 msgid "do not show peeled tags"
 msgstr "ná taispeáin clibeanna scáilte"
 
-#: builtin/ls-remote.c
 msgid "take url.<base>.insteadOf into account"
 msgstr "glacadh url. <base>.insteadOf san áireamh"
 
-#: builtin/ls-remote.c
 msgid "exit with exit code 2 if no matching refs are found"
 msgstr "imeacht le cód imeachta 2 mura bhfaightear aon aifeanna meaitseála"
 
-#: builtin/ls-remote.c
 msgid "show underlying ref in addition to the object pointed by it"
 msgstr "taispeáint an tagairt bhunúsach i dteannta leis an réad a thug sé"
 
-#: builtin/ls-tree.c
 msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
-msgstr "<path>git ls-tree [<options>] [...<tree-ish>]"
+msgstr "git ls-tree [<options>] <tree-ish> [<path>...]"
 
-#: builtin/ls-tree.c
 msgid "only show trees"
 msgstr "ach crainn a thaispeáint"
 
-#: builtin/ls-tree.c
-msgid "recurse into subtrees"
-msgstr "athshlánú isteach i bhfo-chrainn"
-
-#: builtin/ls-tree.c
 msgid "show trees when recursing"
-msgstr "crainn a thaispeáint agus tú ag athf"
+msgstr "crainn a thaispeáint agus athchúrsaíocht á déanamh"
 
-#: builtin/ls-tree.c
 msgid "terminate entries with NUL byte"
 msgstr "foirceannadh iontrálacha le bait NUL"
 
-#: builtin/ls-tree.c
 msgid "include object size"
 msgstr "méid an rud san áireamh"
 
-#: builtin/ls-tree.c
 msgid "list only filenames"
 msgstr "ainmneacha comhaid amháin a liostáil"
 
-#: builtin/ls-tree.c
 msgid "list only objects"
 msgstr "rudaí amháin a liostáil"
 
-#: builtin/ls-tree.c
 msgid "use full path names"
 msgstr "úsáid ainmneacha cosáin iomlána"
 
-#: builtin/ls-tree.c
 msgid "list entire tree; not just current directory (implies --full-name)"
 msgstr ""
 "liostáil crann iomlán; ní hamháin eolaire reatha (tugann le tuiscint --full-"
 "name)"
 
-#: builtin/ls-tree.c
 msgid "--format can't be combined with other format-altering options"
 msgstr ""
 "Ní féidir --format a chomhcheangal le roghanna eile a athraíonn formáidí"
 
 #. TRANSLATORS: keep <> in "<" mail ">" info.
-#: builtin/mailinfo.c
 msgid "git mailinfo [<options>] <msg> <patch> < mail >info"
 msgstr "git mailinfo [<options>] <msg> <patch> < mail >info"
 
-#: builtin/mailinfo.c
 msgid "keep subject"
 msgstr "coinnigh ábhar"
 
-#: builtin/mailinfo.c
 msgid "keep non patch brackets in subject"
 msgstr "coinnigh lúibíní gan paiste san ábhar"
 
-#: builtin/mailinfo.c
 msgid "copy Message-ID to the end of commit message"
 msgstr ""
 "cóipeáil ID teachtaireachtaí go dtí deireadh na teachtaireachta tiomanta"
 
-#: builtin/mailinfo.c
 msgid "re-code metadata to i18n.commitEncoding"
 msgstr "meiteashonraí a athchódú chuig i18N.CommitEncoding"
 
-#: builtin/mailinfo.c
 msgid "disable charset re-coding of metadata"
 msgstr "díchumasú ath-chódú charset meiteashonraí"
 
-#: builtin/mailinfo.c
 msgid "encoding"
 msgstr "ionchódú"
 
-#: builtin/mailinfo.c
 msgid "re-code metadata to this encoding"
 msgstr "athchódú meiteashonraí don ionchódú seo"
 
-#: builtin/mailinfo.c
 msgid "use scissors"
 msgstr "siosúr a úsáid"
 
-#: builtin/mailinfo.c
 msgid "<action>"
 msgstr "<action>"
 
-#: builtin/mailinfo.c
 msgid "action when quoted CR is found"
 msgstr "gníomh nuair a aimsítear CR a luaitear"
 
-#: builtin/mailinfo.c
 msgid "use headers in message's body"
 msgstr "ceanntásca a úsáid i gcorp na teachtaireachta"
 
-#: builtin/mailsplit.c
 msgid "reading patches from stdin/tty..."
 msgstr "paistí a léamh ó stdin/tty..."
 
-#: builtin/mailsplit.c
 #, c-format
 msgid "empty mbox: '%s'"
 msgstr "mbox folamh: '%s'"
 
-#: builtin/merge-base.c
 msgid "git merge-base [-a | --all] <commit> <commit>..."
 msgstr "git merge-base [-a | --all] <commit> <commit>..."
 
-#: builtin/merge-base.c
 msgid "git merge-base [-a | --all] --octopus <commit>..."
 msgstr "git merge-base [-a | --all] --octopus <commit>..."
 
-#: builtin/merge-base.c
 msgid "git merge-base --is-ancestor <commit> <commit>"
 msgstr "git merge-base --is-ancestor <commit> <commit>"
 
-#: builtin/merge-base.c
 msgid "git merge-base --independent <commit>..."
 msgstr "git merge-base --independent <commit>..."
 
-#: builtin/merge-base.c
 msgid "git merge-base --fork-point <ref> [<commit>]"
 msgstr "git merge-base --fork-point <ref> [<commit>]"
 
-#: builtin/merge-base.c
 msgid "output all common ancestors"
 msgstr "aschur gach sinsear coitianta"
 
-#: builtin/merge-base.c
 msgid "find ancestors for a single n-way merge"
 msgstr "aimsigh sinsear le haghaidh cumasc n-bhealach amháin"
 
-#: builtin/merge-base.c
 msgid "list revs not reachable from others"
 msgstr "liosta revs nach féidir teacht ó dhaoine eile"
 
-#: builtin/merge-base.c
 msgid "is the first one ancestor of the other?"
 msgstr "an é an chéad sinsear amháin den duine eile?"
 
-#: builtin/merge-base.c
 msgid "find where <commit> forked from reflog of <ref>"
 msgstr "faigh cén áit a <commit> bhforcáladh ó athbhreithniú <ref>"
 
-#: builtin/merge-file.c
 msgid ""
 "git merge-file [<options>] [-L <name1> [-L <orig> [-L <name2>]]] <file1> "
 "<orig-file> <file2>"
@@ -10547,69 +9055,50 @@
 "git merge-file [<options>] [-L <name1> [-L <orig> [-L <name2>]]] <file1> "
 "<orig-file> <file2>"
 
-#: builtin/merge-file.c diff.c
 msgid ""
 "option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
 "\"histogram\""
 msgstr ""
 "glacann difr-algartam rogha le “myers”, “íosta”, “foighne” agus “histogram”"
 
-#: builtin/merge-file.c
 msgid "send results to standard output"
 msgstr "torthaí a sheoladh chuig aschur caigh"
 
-#: builtin/merge-file.c
 msgid "use object IDs instead of filenames"
 msgstr "úsáid ID réad in ionad ainmneacha comhaid"
 
-#: builtin/merge-file.c
 msgid "use a diff3 based merge"
 msgstr "bain úsáid as cumaisc atá bunaithe ar diff3"
 
-#: builtin/merge-file.c
 msgid "use a zealous diff3 based merge"
 msgstr "bain úsáid as cumaisc díograiseach bunaithe ar diff3"
 
-#: builtin/merge-file.c diff.c
 msgid "<algorithm>"
 msgstr "<algorithm>"
 
-#: builtin/merge-file.c diff.c
 msgid "choose a diff algorithm"
 msgstr "roghnaigh algartam diff"
 
-#: builtin/merge-file.c
 msgid "for conflicts, use this marker size"
 msgstr "le haghaidh coinbhleachtaí, bain úsáid as an méid marcóra"
 
-#: builtin/merge-file.c
 msgid "do not warn about conflicts"
 msgstr "ná tabhair rabhadh faoi choimhlintí"
 
-#: builtin/merge-file.c
 msgid "set labels for file1/orig-file/file2"
-msgstr "lipéid a shocrú le haghaidh comhad1/orig-file/file2"
+msgstr "socraigh lipéid do chomhad1/bunchomhad/comhad2"
 
-#: builtin/merge-file.c
 #, c-format
 msgid "object '%s' does not exist"
 msgstr "níl réad '%s' ann"
 
-#: builtin/merge-file.c
 msgid "Could not write object file"
 msgstr "Ní fhéadfaí comhad réad a scríobh"
 
-#: builtin/merge-recursive.c
-#, c-format
-msgid "unknown option %s"
-msgstr "rogha anaithnid %s"
-
-#: builtin/merge-recursive.c
 #, c-format
 msgid "could not parse object '%s'"
 msgstr "ní fhéadfaí réad '%s' a pháirseáil"
 
-#: builtin/merge-recursive.c
 #, c-format
 msgid "cannot handle more than %d base. Ignoring %s."
 msgid_plural "cannot handle more than %d bases. Ignoring %s."
@@ -10617,274 +9106,210 @@
 msgstr[1] "ní féidir níos mó ná %d bonn a láimhseáil. Ag neamhaird de %s."
 msgstr[2] "ní féidir níos mó ná %d bonn a láimhseáil. Ag neamhaird de %s."
 
-#: builtin/merge-recursive.c
 msgid "not handling anything other than two heads merge."
 msgstr "gan láimhseáil aon rud seachas dhá cheann a chumasc."
 
-#: builtin/merge-recursive.c
 #, c-format
 msgid "could not resolve ref '%s'"
 msgstr "ní fhéadfaí tagairt '%s' a réiteach"
 
-#: builtin/merge-recursive.c
 #, c-format
 msgid "Merging %s with %s\n"
 msgstr "Cumasc %s le %s\n"
 
-#: builtin/merge-tree.c
 #, c-format
 msgid "could not parse as tree '%s'"
 msgstr "ní fhéadfaí parsáil mar chrann '%s'"
 
-#: builtin/merge-tree.c builtin/merge.c
 msgid "not something we can merge"
 msgstr "ní rud is féidir linn a chumasc"
 
-#: builtin/merge-tree.c builtin/merge.c
 msgid "refusing to merge unrelated histories"
 msgstr "diúltú stair neamhghaolmhara a chumasc"
 
-#: builtin/merge-tree.c
 msgid "failure to merge"
 msgstr "teip a chumasc"
 
-#: builtin/merge-tree.c
 msgid "git merge-tree [--write-tree] [<options>] <branch1> <branch2>"
 msgstr "git merge-tree [--write-tree] [<options>] <branch1> <branch2>"
 
-#: builtin/merge-tree.c
 msgid "git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>"
-msgstr "git merge-tree [--trivial-cumaisc] <base-tree><branch1><branch2>"
+msgstr "git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>"
 
-#: builtin/merge-tree.c
 msgid "do a real merge instead of a trivial merge"
 msgstr "déan fíor-chumasc in ionad cumaisc triobháideach"
 
-#: builtin/merge-tree.c
 msgid "do a trivial merge only"
 msgstr "déan cumaisc thréimhseach amháin"
 
-#: builtin/merge-tree.c
 msgid "also show informational/conflict messages"
 msgstr "taispeáin teachtaireachtaí faisnéis/coinbhleachta freisin"
 
-#: builtin/merge-tree.c
 msgid "suppress all output; only exit status wanted"
 msgstr "cosc a chur ar an aschur go léir; níl uaim ach stádas scoir"
 
-#: builtin/merge-tree.c
 msgid "list filenames without modes/oids/stages"
 msgstr "ainmneacha comhaid a liostáil gan modhair/oids/céimeanna"
 
-#: builtin/merge-tree.c builtin/merge.c builtin/pull.c
 msgid "allow merging unrelated histories"
 msgstr "ligean stair neamhghaolmhara a chumasc"
 
-#: builtin/merge-tree.c
 msgid "perform multiple merges, one per line of input"
 msgstr "cumaisc iolracha a dhéanamh, ceann in aghaidh an líne ionchuir"
 
-#: builtin/merge-tree.c
 msgid "specify a merge-base for the merge"
 msgstr "sonraigh bonn cumaisc don chumasc"
 
-#: builtin/merge-tree.c builtin/merge.c builtin/pull.c
 msgid "option=value"
 msgstr "rogha = luach"
 
-#: builtin/merge-tree.c builtin/merge.c builtin/pull.c
 msgid "option for selected merge strategy"
 msgstr "rogha do straitéis cumaisc roghnaithe"
 
-#: builtin/merge-tree.c
 msgid "--trivial-merge is incompatible with all other options"
 msgstr "Tá --trivial-merge neamhoiriúnach le gach rogha eile"
 
-#: builtin/merge-tree.c builtin/merge.c
 #, c-format
 msgid "unknown strategy option: -X%s"
 msgstr "rogha straitéise anaithnid: -X%s"
 
-#: builtin/merge-tree.c builtin/notes.c
 #, c-format
 msgid "malformed input line: '%s'."
 msgstr "líne ionchuir mífhoirmithe: '%s'."
 
-#: builtin/merge.c
 msgid "git merge [<options>] [<commit>...]"
-msgstr "git cumaisc [<options>] [<commit>...]"
+msgstr "git merge [<options>] [<commit>...]"
 
-#: builtin/merge.c
 msgid "switch `m' requires a value"
 msgstr "teastaíonn luach ag lasc `m'"
 
-#: builtin/merge.c
 #, c-format
 msgid "option `%s' requires a value"
 msgstr "teastaíonn luach ag rogha `%s'"
 
-#: builtin/merge.c
 #, c-format
 msgid "Could not find merge strategy '%s'.\n"
 msgstr "Níorbh fhéidir straitéis cumaisc '%s' a fháil.\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "Available strategies are:"
 msgstr "Is iad straitéisí atá ar fáil:"
 
-#: builtin/merge.c
 #, c-format
 msgid "Available custom strategies are:"
 msgstr "Is iad seo a leanas na straitéisí saincheaptha atá ar fáil:"
 
-#: builtin/merge.c builtin/pull.c
 msgid "do not show a diffstat at the end of the merge"
 msgstr "ná taispeáin diffstat ag deireadh an chumaisc"
 
-#: builtin/merge.c builtin/pull.c
 msgid "show a diffstat at the end of the merge"
 msgstr "taispeáin diffstat ag deireadh an chumaisc"
 
-#: builtin/merge.c builtin/pull.c
 msgid "(synonym to --stat)"
 msgstr "(Comhchiallach le --stat)"
 
-#: builtin/merge.c builtin/pull.c
+msgid "show a compact-summary at the end of the merge"
+msgstr "taispeáin achoimre dhlúth ag deireadh an chumaisc"
+
 msgid "add (at most <n>) entries from shortlog to merge commit message"
 msgstr ""
 "cuir iontrálacha (ar a mh <n>éad) ó gearrlog chun teachtaireacht tiomanta a "
 "chumasc"
 
-#: builtin/merge.c builtin/pull.c
 msgid "create a single commit instead of doing a merge"
 msgstr "tiomantas amháin a chruthú in ionad cumaisc a dhéanamh"
 
-#: builtin/merge.c builtin/pull.c
 msgid "perform a commit if the merge succeeds (default)"
 msgstr "tiomantas a dhéanamh má éireoidh leis an gcumasc (réamhshocraithe)"
 
-#: builtin/merge.c builtin/pull.c
 msgid "edit message before committing"
 msgstr "teachtaireacht in eagar sula ndéanann"
 
-#: builtin/merge.c
 msgid "allow fast-forward (default)"
 msgstr "ligean go tapa ar aghaidh (réamhshocraithe)"
 
-#: builtin/merge.c builtin/pull.c
 msgid "abort if fast-forward is not possible"
 msgstr "déan deireadh a chur ar aghaidh mura féidir go tapa ar aghaidh"
 
-#: builtin/merge.c builtin/pull.c
 msgid "verify that the named commit has a valid GPG signature"
 msgstr "fíorú go bhfuil síniú bailí GPG ag an tiomantas ainmnithe"
 
-#: builtin/merge.c builtin/notes.c builtin/pull.c builtin/rebase.c
-#: builtin/revert.c
 msgid "strategy"
 msgstr "straitéis"
 
-#: builtin/merge.c builtin/pull.c
 msgid "merge strategy to use"
 msgstr "straitéis a chumasc le húsáid"
 
-#: builtin/merge.c
 msgid "merge commit message (for a non-fast-forward merge)"
 msgstr ""
 "teachtaireacht tiomanta a chumasc (le haghaidh cumaisc neamh-tapa ar aghaidh)"
 
-#: builtin/merge.c
 msgid "use <name> instead of the real target"
 msgstr "úsáid in <name>ionad an sprioc fíor"
 
-#: builtin/merge.c
 msgid "abort the current in-progress merge"
 msgstr "deireadh a chur leis an gcumasc reatha atá ar siúl"
 
-#: builtin/merge.c
 msgid "--abort but leave index and working tree alone"
 msgstr "--abort ach fág an t-innéacs agus an crann oibre ina n-aonar"
 
-#: builtin/merge.c
 msgid "continue the current in-progress merge"
 msgstr "leanúint leis an gcumasc atá ar siúl reatha"
 
-#: builtin/merge.c
 msgid "bypass pre-merge-commit and commit-msg hooks"
 msgstr "seachbhóthar crúcaí réamh-chumaisc-tiomantas agus comh-msg"
 
-#: builtin/merge.c
 msgid "could not run stash."
 msgstr "ní fhéadfadh stash a reáchtáil."
 
-#: builtin/merge.c
 msgid "stash failed"
 msgstr "theip ar stash"
 
-#: builtin/merge.c
-#, c-format
-msgid "not a valid object: %s"
-msgstr "ní réad bailí: %s"
-
-#: builtin/merge.c
 msgid "read-tree failed"
 msgstr "theip ar chrann léitheoireachta"
 
-#: builtin/merge.c
 msgid "Already up to date. (nothing to squash)"
 msgstr "Cothrom le dáta cheana féin. (rud ar bith le squash)"
 
-#: builtin/merge.c merge-ort-wrappers.c
 msgid "Already up to date."
 msgstr "Cothrom le dáta cheana féin."
 
-#: builtin/merge.c
 #, c-format
 msgid "Squash commit -- not updating HEAD\n"
 msgstr "Tiomantas Squash - gan HEAD a nuashonrú\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "No merge message -- not updating HEAD\n"
 msgstr "Gan aon teachtaireacht cumaisc - gan HEAD a nuashonrú\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "'%s' does not point to a commit"
 msgstr "Ní thugann '%s' in iúl do thiomantas"
 
-#: builtin/merge.c
 #, c-format
 msgid "Bad branch.%s.mergeoptions string: %s"
 msgstr "Drochbhrainse. %s.mergeoptions teaghrán: %s"
 
-#: builtin/merge.c merge-ort-wrappers.c
 msgid "Unable to write index."
 msgstr "Ní féidir innéacs a scríobh."
 
-#: builtin/merge.c
 msgid "Not handling anything other than two heads merge."
 msgstr "Gan aon rud a láimhseáil seachas dhá cheann cumasc."
 
-#: builtin/merge.c builtin/sparse-checkout.c
 #, c-format
 msgid "unable to write %s"
-msgstr "nach féidir %s a scríobh"
+msgstr "ní féidir %s a scríobh"
 
-#: builtin/merge.c
 #, c-format
 msgid "Could not read from '%s'"
 msgstr "Ní féidir léamh ó '%s'"
 
-#: builtin/merge.c
 #, c-format
 msgid "Not committing merge; use 'git commit' to complete the merge.\n"
 msgstr ""
 "Gan cumasc a dhéanamh; bain úsáid as 'git commit' chun an cumaisc a chur i "
 "gcrích.\n"
 
-#: builtin/merge.c
 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"
@@ -10895,11 +9320,9 @@
 "go háirithe má chomhcheanglaíonn sé nuashonraithe suas sruth i mbrainse "
 "ábhair.\n"
 
-#: builtin/merge.c
 msgid "An empty message aborts the commit.\n"
 msgstr "Cuireann teachtaireacht fholamh deireadh leis an tiomantas.\n"
 
-#: builtin/merge.c
 #, c-format
 msgid ""
 "Lines starting with '%s' will be ignored, and an empty message aborts\n"
@@ -10908,74 +9331,58 @@
 "Déanfar neamhaird ar línte a thosaíonn le '%s', \n"
 "agus cuirfidh teachtaireacht fholamh deireadh leis an tiomantas.\n"
 
-#: builtin/merge.c
 msgid "Empty commit message."
 msgstr "Teachtaireacht tiomanta folamh."
 
-#: builtin/merge.c
 #, c-format
 msgid "Wonderful.\n"
 msgstr "Iontach.\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
 msgstr ""
 "Theip ar chumasc uathoibríoch; coimhlintí a shocrú agus ansin an toradh\n"
 
-#: builtin/merge.c
 msgid "No current branch."
 msgstr "Níl aon bhrainse reatha."
 
-#: builtin/merge.c
 msgid "No remote for the current branch."
 msgstr "Níl aon iargúlta don bhrainse reatha."
 
-#: builtin/merge.c
 msgid "No default upstream defined for the current branch."
 msgstr "Níl aon réamhshocraithe suas sruth sainithe don bhrainse reatha."
 
-#: builtin/merge.c
 #, c-format
 msgid "No remote-tracking branch for %s from %s"
 msgstr "Gan aon bhrainse cianrianaithe do %s ó %s"
 
-#: builtin/merge.c
 #, c-format
 msgid "Bad value '%s' in environment '%s'"
 msgstr "Drochluach '%s' sa timpeallacht '%s'"
 
-#: builtin/merge.c editor.c read-cache.c wrapper.c
 #, c-format
 msgid "could not close '%s'"
 msgstr "ní fhéadfaí '%s' a dhúnadh"
 
-#: builtin/merge.c
 #, c-format
 msgid "not something we can merge in %s: %s"
 msgstr "ní rud is féidir linn a chumasc i %s: %s"
 
-#: builtin/merge.c
 msgid "--abort expects no arguments"
 msgstr "--abort ag súil nach bhfuil aon argóintí"
 
-#: builtin/merge.c
 msgid "There is no merge to abort (MERGE_HEAD missing)."
 msgstr "Níl aon chumasc ann chun deireadh a chur (MERGE_HEAD ar iarraidh)."
 
-#: builtin/merge.c
 msgid "--quit expects no arguments"
 msgstr "Tá --quit ag súil nach bhfuil aon argóintí"
 
-#: builtin/merge.c
 msgid "--continue expects no arguments"
 msgstr "--continue gan aon argóintí ag súil leo"
 
-#: builtin/merge.c
 msgid "There is no merge in progress (MERGE_HEAD missing)."
 msgstr "Níl aon chumasc ar siúl (MERGE_HEAD ar iarraidh)."
 
-#: builtin/merge.c
 msgid ""
 "You have not concluded your merge (MERGE_HEAD exists).\n"
 "Please, commit your changes before you merge."
@@ -10983,7 +9390,6 @@
 "Níor thug tú do chumasc i gcrích (MERGE_HEAD ann).\n"
 "Déan do chuid athruithe a dhéanamh sula ndéanann tú cumasc."
 
-#: builtin/merge.c
 msgid ""
 "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
 "Please, commit your changes before you merge."
@@ -10991,38 +9397,30 @@
 "Níor thug tú do phiocadh silíní i gcrích (CHERRY_PICK_HEAD ann).\n"
 "Déan do chuid athruithe a dhéanamh sula ndéanann tú cumasc."
 
-#: builtin/merge.c
 msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
 msgstr "Níor thug tú do phiocadh silíní i gcrích (CHERRY_PICK_HEAD ann)."
 
-#: builtin/merge.c
 msgid "No commit specified and merge.defaultToUpstream not set."
 msgstr ""
 "Níl aon tiomantas sonraithe agus níl merge.defaultToUpstream socraithe."
 
-#: builtin/merge.c
 msgid "Squash commit into empty head not supported yet"
 msgstr "Tiomann squash isteach i gceann folamh nach dtacaítear go fóill"
 
-#: builtin/merge.c
 msgid "Non-fast-forward commit does not make sense into an empty head"
 msgstr "Níl ciall ar thiomantas neamh-thapa ar aghaidh i gceann folamh"
 
-#: builtin/merge.c
 #, c-format
 msgid "%s - not something we can merge"
 msgstr "%s - ní rud is féidir linn a chumasc"
 
-#: builtin/merge.c
 msgid "Can merge only exactly one commit into empty head"
 msgstr "Ní féidir ach tiomantas amháin a chumasc i gceann folamh"
 
-#: builtin/merge.c
 #, c-format
 msgid "Updating %s..%s\n"
 msgstr "Ag nuashonrú %s..%s\n"
 
-#: builtin/merge.c merge-ort-wrappers.c
 #, c-format
 msgid ""
 "Your local changes to the following files would be overwritten by merge:\n"
@@ -11032,103 +9430,78 @@
 "chumasc:\n"
 " %s"
 
-#: builtin/merge.c
 #, c-format
 msgid "Trying really trivial in-index merge...\n"
 msgstr "Ag triail a dhéanamh cumasc in-innéacs fíor-thrá\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "Nope.\n"
 msgstr "Ní hea..\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "Rewinding the tree to pristine...\n"
 msgstr "Ag athchasadh an chrainn go dtí go mbeidh sé foirfe...\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "Trying merge strategy %s...\n"
 msgstr "Ag iarraidh straitéis cumaisc %s...\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "No merge strategy handled the merge.\n"
 msgstr "Níor láimhseáil aon straitéis chumaisc an cumasc.\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "Merge with strategy %s failed.\n"
 msgstr "Theip ar chumasc le straitéis %s.\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "Using the %s strategy to prepare resolving by hand.\n"
 msgstr "Ag baint úsáide as straitéis %s chun réiteach a ullmhú de láimh.\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "Automatic merge went well; stopped before committing as requested\n"
 msgstr "Chuaigh cumaisc uathoibríoch go maith; stad sula ndearna sé tiomanta\n"
 
-#: builtin/merge.c
 #, c-format
 msgid "When finished, apply stashed changes with `git stash pop`\n"
 msgstr ""
 "Nuair a bheidh críochnaithe, cuir athruithe stashed i bhfeidhm le `git stash "
 "pop`\n"
 
-#: builtin/mktag.c
 #, c-format
 msgid "warning: tag input does not pass fsck: %s"
 msgstr "rabhadh: ní théann ionchur clib ar fsck: %s"
 
-#: builtin/mktag.c
 #, c-format
 msgid "error: tag input does not pass fsck: %s"
 msgstr "earráid: ní théann ionchur clib ar fsck: %s"
 
-#: builtin/mktag.c
-#, c-format
-msgid "%d (FSCK_IGNORE?) should never trigger this callback"
-msgstr "%d (FSCK_IGNORE?) níor cheart go spreagfadh an t-aisghlaoch seo"
-
-#: builtin/mktag.c
 #, c-format
 msgid "could not read tagged object '%s'"
 msgstr "ní fhéadfaí réad clibeáilte '%s' a léamh"
 
-#: builtin/mktag.c
 #, c-format
 msgid "object '%s' tagged as '%s', but is a '%s' type"
 msgstr "réad '%s' clibeáilte mar '%s', ach is cineál '%s' é"
 
-#: builtin/mktag.c
 msgid "tag on stdin did not pass our strict fsck check"
 msgstr "níor rith tag ar stdin ár seiceáil dhian fsck"
 
-#: builtin/mktag.c
 msgid "tag on stdin did not refer to a valid object"
 msgstr "níor thagraigh an chlib ar stdin do réad bailí"
 
-#: builtin/mktag.c builtin/tag.c
 msgid "unable to write tag file"
-msgstr "in ann comhad clib a scríobh"
+msgstr "ní féidir comhad clibe a scríobh"
 
-#: builtin/mktree.c
 msgid "input is NUL terminated"
 msgstr "cuirtear deireadh le hionchur NUL"
 
-#: builtin/mktree.c builtin/write-tree.c
 msgid "allow missing objects"
 msgstr "cead a cheadú rudaí"
 
-#: builtin/mktree.c
 msgid "allow creation of more than one tree"
 msgstr "cead níos mó ná crann amháin a chruthú"
 
-#: builtin/multi-pack-index.c
 msgid ""
 "git multi-pack-index [<options>] write [--preferred-pack=<pack>][--refs-"
 "snapshot=<path>]"
@@ -11136,52 +9509,40 @@
 "git multi-pack-index [<options>] write [--preferred-pack=<pack>][--refs-"
 "snapshot=<path>]"
 
-#: builtin/multi-pack-index.c
 msgid "git multi-pack-index [<options>] verify"
 msgstr "git multi-pack-index [<options>] verify"
 
-#: builtin/multi-pack-index.c
 msgid "git multi-pack-index [<options>] expire"
 msgstr "git multi-pack-index [<options>] expire"
 
-#: builtin/multi-pack-index.c
 msgid "git multi-pack-index [<options>] repack [--batch-size=<size>]"
 msgstr "git multi-pack-index [<options>] repack [--batch-size=<size>]"
 
-#: builtin/multi-pack-index.c
 msgid "directory"
 msgstr "eolaire"
 
-#: builtin/multi-pack-index.c
 msgid "object directory containing set of packfile and pack-index pairs"
 msgstr ""
 "eolaire réada ina bhfuil tacar de phéirí pacáiste agus innéacs pacáiste"
 
-#: builtin/multi-pack-index.c
 msgid "preferred-pack"
 msgstr "pacáiste is fearr leat"
 
-#: builtin/multi-pack-index.c
 msgid "pack for reuse when computing a multi-pack bitmap"
 msgstr "pacáiste le húsáid agus bitmap il-phacáiste á ríomh"
 
-#: builtin/multi-pack-index.c
 msgid "write multi-pack bitmap"
 msgstr "scríobh bitmap il-phacáiste"
 
-#: builtin/multi-pack-index.c
 msgid "write a new incremental MIDX"
 msgstr "scríobh MIDX incrementach nua"
 
-#: builtin/multi-pack-index.c
 msgid "write multi-pack index containing only given indexes"
 msgstr "scríobh innéacs il-phacáiste nach bhfuil ach innéacsanna ar leith"
 
-#: builtin/multi-pack-index.c
 msgid "refs snapshot for selecting bitmap commits"
 msgstr "léargas refs chun gealltanais bitmap a roghnú"
 
-#: builtin/multi-pack-index.c
 msgid ""
 "during repack, collect pack-files of smaller size into a batch that is "
 "larger than this size"
@@ -11189,170 +9550,131 @@
 "le linn athphacáil, bailigh comhaid pacáiste de mhéid níos lú i mbaisc atá "
 "níos mó ná an méid seo"
 
-#: builtin/mv.c
 msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>"
-msgstr "git mv [-v] [-f] [-n] [-k] <source><destination>"
+msgstr "git mv [-v] [-f] [-n] [-k] <source> <destination>"
 
-#: builtin/mv.c
 msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>"
-msgstr "<source>git mv [-v] [-f] [-n] [-k]... <destination-directory>"
+msgstr "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>"
 
-#: builtin/mv.c
 #, c-format
 msgid "Directory %s is in index and no submodule?"
 msgstr "Tá eolaire %s in innéacs agus níl aon fho-mhodúl ann?"
 
-#: builtin/mv.c
 msgid "Please stage your changes to .gitmodules or stash them to proceed"
 msgstr ""
 "Cuir do chuid athruithe ar .gitmodules nó iad a stóráil chun dul ar aghaidh"
 
-#: builtin/mv.c
 #, c-format
 msgid "%.*s is in index"
 msgstr "%.*s atá san innéacs"
 
-#: builtin/mv.c
 msgid "force move/rename even if target exists"
 msgstr "aistriúin/athainmniú a fhorbairt fiú má tá sprioc ann"
 
-#: builtin/mv.c
 msgid "skip move/rename errors"
 msgstr "scipeáil earráidí a bhogadh/athainmniú"
 
-#: builtin/mv.c
 #, c-format
 msgid "destination '%s' is not a directory"
 msgstr "ní eolaire é ceann scríbe '%s'"
 
-#: builtin/mv.c
 #, c-format
 msgid "Checking rename of '%s' to '%s'\n"
 msgstr "Seiceáil athainmniú '%s' go '%s'\n"
 
-#: builtin/mv.c
 msgid "bad source"
 msgstr "droch-fhoinse"
 
-#: builtin/mv.c
 msgid "destination exists"
 msgstr "ceann scríbe ann"
 
-#: builtin/mv.c
 msgid "can not move directory into itself"
 msgstr "ní féidir eolaire a bhogadh isteach ina féin"
 
-#: builtin/mv.c
 msgid "destination already exists"
 msgstr "ceann scríbe ann cheana féin"
 
-#: builtin/mv.c
 msgid "source directory is empty"
 msgstr "tá eolaire foinse folamh"
 
-#: builtin/mv.c
 msgid "not under version control"
 msgstr "nach bhfuil faoi rialú leagan"
 
-#: builtin/mv.c
 msgid "conflicted"
 msgstr "coimhlinneach"
 
-#: builtin/mv.c
 #, c-format
 msgid "overwriting '%s'"
 msgstr "athscríobh '%s'"
 
-#: builtin/mv.c
 msgid "Cannot overwrite"
 msgstr "Ní féidir athscríobh"
 
-#: builtin/mv.c
 msgid "multiple sources for the same target"
 msgstr "foinsí iolracha don sprioc chéanna"
 
-#: builtin/mv.c
 msgid "destination directory does not exist"
 msgstr "níl eolaire ceann scríbe ann"
 
-#: builtin/mv.c
 msgid "destination exists in the index"
 msgstr "ceann scríbe ann san innéacs"
 
-#: builtin/mv.c
 #, c-format
 msgid "%s, source=%s, destination=%s"
 msgstr "%s, foinse = %s, ceann scríbe = %s"
 
-#: builtin/mv.c
 #, c-format
 msgid "cannot move both '%s' and its parent directory '%s'"
 msgstr "ní féidir '%s' agus a eolaire tuismitheora '%s' a bhogadh"
 
-#: builtin/mv.c
 #, c-format
 msgid "Renaming %s to %s\n"
 msgstr "Athainmniú %s go %s\n"
 
-#: builtin/mv.c builtin/remote.c
 #, c-format
 msgid "renaming '%s' failed"
 msgstr "theip ar athainmniú '%s'"
 
-#: builtin/name-rev.c
 msgid "git name-rev [<options>] <commit>..."
 msgstr "git name-rev [<options>] <commit>..."
 
-#: builtin/name-rev.c
 msgid "git name-rev [<options>] --all"
 msgstr "git name-rev [<options>] --all"
 
-#: builtin/name-rev.c
 msgid "git name-rev [<options>] --annotate-stdin"
 msgstr "git name-rev [<options>] --annotate-stdin"
 
-#: builtin/name-rev.c
 msgid "print only ref-based names (no object names)"
 msgstr "ainmneacha ref-bhunaithe amháin a phriontáil (gan ainmneacha réada)"
 
-#: builtin/name-rev.c
 msgid "only use tags to name the commits"
 msgstr "ní húsáid ach clibeanna chun na gealltanais a ainmniú"
 
-#: builtin/name-rev.c
 msgid "only use refs matching <pattern>"
 msgstr "ní úsáideann ach meaitseáil refs <pattern>"
 
-#: builtin/name-rev.c
 msgid "ignore refs matching <pattern>"
 msgstr "neamhaird a dhéanamh ar mheaitseáil <pattern>"
 
-#: builtin/name-rev.c
 msgid "list all commits reachable from all refs"
 msgstr "liostáil na gealltanais go léir atá inrochtana ó gach ceann"
 
-#: builtin/name-rev.c
 msgid "deprecated: use --annotate-stdin instead"
 msgstr "díscríofa: bain úsáid as --annotate-stdin ina ionad"
 
-#: builtin/name-rev.c
 msgid "annotate text from stdin"
 msgstr "téacs a anótáil ó stdin"
 
-#: builtin/name-rev.c
 msgid "allow to print `undefined` names (default)"
 msgstr ""
 "cead a thabhairt d'ainmneacha “neamhshainithe” a phriontáil (réamhshocrú"
 
-#: builtin/name-rev.c
 msgid "dereference tags in the input (internal use)"
 msgstr "clibeanna dereference san ionchur (úsáid inmheánach)"
 
-#: builtin/notes.c
 msgid "git notes [--ref <notes-ref>] [list [<object>]]"
 msgstr "git notes [--ref <notes-ref>] [list [<object>]]"
 
-#: builtin/notes.c
 msgid ""
 "git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--"
 "separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c "
@@ -11362,11 +9684,9 @@
 "separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c "
 "| -C) <object>] [<object>] [-e]"
 
-#: builtin/notes.c
 msgid "git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>"
 msgstr "git notes [--ref<notes-ref>] cóipeáil [-f] <from-object><to-object>"
 
-#: builtin/notes.c
 msgid ""
 "git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--"
 "separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c "
@@ -11376,127 +9696,98 @@
 "separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c "
 "| -C) <object>] [<object>] [-e]"
 
-#: builtin/notes.c
 msgid "git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"
 msgstr "git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"
 
-#: builtin/notes.c
 msgid "git notes [--ref <notes-ref>] show [<object>]"
 msgstr "git notes [--ref <notes-ref>] show [<object>]"
 
-#: builtin/notes.c
 msgid ""
 "git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"
 msgstr ""
 "git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"
 
-#: builtin/notes.c
 msgid "git notes [--ref <notes-ref>] remove [<object>...]"
 msgstr "git notes [--ref <notes-ref>] remove [<object>...]"
 
-#: builtin/notes.c
 msgid "git notes [--ref <notes-ref>] prune [-n] [-v]"
 msgstr "git notes [--ref <notes-ref>] prune [-n] [-v]"
 
-#: builtin/notes.c
 msgid "git notes [--ref <notes-ref>] get-ref"
 msgstr "git notes [--ref <notes-ref>] get-ref"
 
-#: builtin/notes.c
 msgid "git notes [list [<object>]]"
 msgstr "git notes [list [<object>]]"
 
-#: builtin/notes.c
 msgid "git notes add [<options>] [<object>]"
 msgstr "git notes add [<options>] [<object>]"
 
-#: builtin/notes.c
 msgid "git notes copy [<options>] <from-object> <to-object>"
 msgstr "git notes copy [<options>] <from-object> <to-object>"
 
-#: builtin/notes.c
 msgid "git notes copy --stdin [<from-object> <to-object>]..."
 msgstr "git notes copy --stdin [<from-object> <to-object>]..."
 
-#: builtin/notes.c
 msgid "git notes append [<options>] [<object>]"
 msgstr "git notes append [<options>] [<object>]"
 
-#: builtin/notes.c
 msgid "git notes edit [<object>]"
-msgstr "nótaí git a chur in eagar [<object>]"
+msgstr "git notes edit [<object>]"
 
-#: builtin/notes.c
 msgid "git notes show [<object>]"
-msgstr "taispeánann nótaí git [<object>]"
+msgstr "git notes show [<object>]"
 
-#: builtin/notes.c
 msgid "git notes merge [<options>] <notes-ref>"
-msgstr "cumaisc nótaí git [<options>] <notes-ref>"
+msgstr "git notes merge [<options>] <notes-ref>"
 
-#: builtin/notes.c
 msgid "git notes merge --commit [<options>]"
 msgstr "git notes merge --commit [<options>]"
 
-#: builtin/notes.c
 msgid "git notes merge --abort [<options>]"
 msgstr "git notes merge --abort [<options>]"
 
-#: builtin/notes.c
 msgid "git notes remove [<object>]"
 msgstr "git notes remove [<object>]"
 
-#: builtin/notes.c
 msgid "git notes prune [<options>]"
 msgstr "git notes prune [<options>]"
 
-#: builtin/notes.c
 msgid "Write/edit the notes for the following object:"
 msgstr "Scríobh/cuir in eagar na nótaí don réad seo a leanas:"
 
-#: builtin/notes.c
 msgid "could not read 'show' output"
 msgstr "ní raibh in ann aschur 'taispeáin' a léamh"
 
-#: builtin/notes.c
 #, c-format
 msgid "failed to finish 'show' for object '%s'"
 msgstr "theip ar 'show' a chríochnú le haghaidh réad '%s'"
 
-#: builtin/notes.c
 msgid "please supply the note contents using either -m or -F option"
 msgstr "soláthar ábhar an nóta le do thoil ag baint úsáide as rogha -m nó -F"
 
-#: builtin/notes.c
 msgid "unable to write note object"
-msgstr "in ann réad nótaí a scríobh"
+msgstr "ní féidir réad nóta a scríobh"
 
-#: builtin/notes.c
 #, c-format
 msgid "the note contents have been left in %s"
 msgstr "tá ábhar an nóta fágtha i %s"
 
-#: builtin/notes.c builtin/tag.c
 #, c-format
 msgid "could not open or read '%s'"
 msgstr "ní fhéadfaí '%s' a oscailt nó a léamh"
 
-#: builtin/notes.c
 #, c-format
 msgid "failed to resolve '%s' as a valid ref."
 msgstr "theip ar '%s' a réiteach mar thagartha bailí."
 
-#: builtin/notes.c
 #, c-format
 msgid "failed to read object '%s'."
 msgstr "theip ar réad '%s' a léamh."
 
-#: builtin/notes.c
 #, c-format
 msgid "cannot read note data from non-blob object '%s'."
 msgstr "ní féidir sonraí nótaí a léamh ó réad neamh-blob '%s'."
 
-#: builtin/notes.c
 #, c-format
 msgid "failed to copy notes from '%s' to '%s'"
 msgstr "theip ar nótaí a chóipeáil ó '%s' go '%s'"
@@ -11504,57 +9795,44 @@
 #. TRANSLATORS: the first %s will be replaced by a git
 #. notes command: 'add', 'merge', 'remove', etc.
 #.
-#: builtin/notes.c
 #, c-format
 msgid "refusing to %s notes in %s (outside of refs/notes/)"
 msgstr "diúltú do %s nótaí i %s (lasmuigh de refs/notes/)"
 
-#: builtin/notes.c
 #, c-format
 msgid "no note found for object %s."
 msgstr "ní bhfuarthas aon nóta do réad %s."
 
-#: builtin/notes.c
 msgid "note contents as a string"
 msgstr "tabhair faoi deara ábhar mar shreang"
 
-#: builtin/notes.c
 msgid "note contents in a file"
 msgstr "tabhair faoi deara ábhar i gcomhad"
 
-#: builtin/notes.c
 msgid "reuse and edit specified note object"
 msgstr "réad nóta sonraithe a úsáid agus a chur in eagar"
 
-#: builtin/notes.c
 msgid "edit note message in editor"
 msgstr "teachtaireacht nóta in eagar san eagarthóir"
 
-#: builtin/notes.c
 msgid "reuse specified note object"
 msgstr "réad nóta sonraithe a athúsáid"
 
-#: builtin/notes.c
 msgid "allow storing empty note"
 msgstr "ligean nóta folamh a stóráil"
 
-#: builtin/notes.c
 msgid "replace existing notes"
 msgstr "nótaí atá ann cheana in ionad"
 
-#: builtin/notes.c
 msgid "<paragraph-break>"
 msgstr "<paragraph-break>"
 
-#: builtin/notes.c
 msgid "insert <paragraph-break> between paragraphs"
 msgstr "cuir isteach <paragraph-break>idir míreanna"
 
-#: builtin/notes.c
 msgid "remove unnecessary whitespace"
 msgstr "bain spás bán neamhriachtanach"
 
-#: builtin/notes.c
 #, c-format
 msgid ""
 "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
@@ -11563,31 +9841,25 @@
 "Ní féidir nótaí a chur leis. Fuarthas nótaí atá ann cheana don réad %s. "
 "Úsáid '-f' chun nótaí atá ann cheana a fhorscríobh"
 
-#: builtin/notes.c
 #, c-format
 msgid "Overwriting existing notes for object %s\n"
 msgstr "Athscríobh nótaí atá ann cheana don réad %s\n"
 
-#: builtin/notes.c
 #, c-format
 msgid "Removing note for object %s\n"
 msgstr "Nóta a bhaint le haghaidh réad %s\n"
 
-#: builtin/notes.c
 msgid "read objects from stdin"
 msgstr "léigh rudaí ó stdin"
 
-#: builtin/notes.c
 msgid "load rewriting config for <command> (implies --stdin)"
 msgstr ""
 "cumraíocht athscríbhneoireachta ualaigh le haghaidh <command>(tugann le "
 "tuiscint --stdin)"
 
-#: builtin/notes.c
 msgid "too few arguments"
 msgstr "ró-bheag argóintí"
 
-#: builtin/notes.c
 #, c-format
 msgid ""
 "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
@@ -11596,12 +9868,10 @@
 "Ní féidir nótaí a chóipeáil. Fuarthas nótaí atá ann cheana don réad %s. "
 "Úsáid '-f' chun nótaí atá ann cheana a fhorscríobh"
 
-#: builtin/notes.c
 #, c-format
 msgid "missing notes on source object %s. Cannot copy."
 msgstr "nótaí in easnamh ar réad foinse %s. Ní féidir cóipeáil."
 
-#: builtin/notes.c
 #, c-format
 msgid ""
 "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
@@ -11610,52 +9880,40 @@
 "Tá na roghanna -M/-f/-c/-c curtha as an bhfo-ordú 'eagarthóireach'.\n"
 "Úsáid le do thoil 'git notes add -f -m/-f/-c/-C' ina ionad.\n"
 
-#: builtin/notes.c
 msgid "failed to delete ref NOTES_MERGE_PARTIAL"
 msgstr "theip ar an tagairt NOTES_MERGE_PARTIAL a scriosadh"
 
-#: builtin/notes.c
 msgid "failed to delete ref NOTES_MERGE_REF"
 msgstr "theip ar an ref a scriosadh NOTES_MERGE_REF"
 
-#: builtin/notes.c
 msgid "failed to remove 'git notes merge' worktree"
 msgstr "theip ar chrann oibre 'git notes merge' a bhaint"
 
-#: builtin/notes.c
 msgid "failed to read ref NOTES_MERGE_PARTIAL"
 msgstr "theip ar an tagairt NOTES_MERGE_PARTIAL a léamh"
 
-#: builtin/notes.c
 msgid "could not find commit from NOTES_MERGE_PARTIAL."
 msgstr "ní raibh sé in ann tiomantas a fháil ó NOTES_MERGE_PARTIAL."
 
-#: builtin/notes.c
 msgid "could not parse commit from NOTES_MERGE_PARTIAL."
 msgstr "ní raibh sé in ann tiomantas a pharsáil ó NOTES_MERGE_PARTIAL."
 
-#: builtin/notes.c
 msgid "failed to resolve NOTES_MERGE_REF"
 msgstr "theip orthu NOTES_MERGE_REF a réiteach"
 
-#: builtin/notes.c
 msgid "failed to finalize notes merge"
 msgstr "theip orthu nótaí a chumasc a chur i gcrích"
 
-#: builtin/notes.c
 #, c-format
 msgid "unknown notes merge strategy %s"
 msgstr "straitéis cumaisc nótaí anaithnid %s"
 
-#: builtin/notes.c
 msgid "General options"
 msgstr "Roghanna ginearálta"
 
-#: builtin/notes.c
 msgid "Merge options"
 msgstr "Roghanna cumaisc"
 
-#: builtin/notes.c
 msgid ""
 "resolve notes conflicts using the given strategy (manual/ours/theirs/union/"
 "cat_sort_uniq)"
@@ -11663,46 +9921,36 @@
 "coimhlintí nótaí a réiteach ag baint úsáide as an straitéis a thugtar "
 "(lámhleabhair/innir/a nd/union/cat_sort_uniq)"
 
-#: builtin/notes.c
 msgid "Committing unmerged notes"
 msgstr "Nótaí neamh-mheánaithe a dhéanamh"
 
-#: builtin/notes.c
 msgid "finalize notes merge by committing unmerged notes"
 msgstr "cumasc nótaí a chríochnú trí nótaí neamh-chumasaithe a dhéanamh"
 
-#: builtin/notes.c
 msgid "Aborting notes merge resolution"
 msgstr "Rún cumasc le nótaí a ghearradh"
 
-#: builtin/notes.c
 msgid "abort notes merge"
 msgstr "cumaisc nótaí abort"
 
-#: builtin/notes.c
 msgid "cannot mix --commit, --abort or -s/--strategy"
 msgstr "ní féidir --commit, --abort nó -s/--strategy a mheascadh"
 
-#: builtin/notes.c
 msgid "must specify a notes ref to merge"
 msgstr "ní mór tagairt nótaí a shonrú chun cumasc"
 
-#: builtin/notes.c
 #, c-format
 msgid "unknown -s/--strategy: %s"
 msgstr "anaithnid -s/--strategy: %s"
 
-#: builtin/notes.c
 #, c-format
 msgid "a notes merge into %s is already in-progress at %s"
 msgstr "tá nótaí a chumasc i %s ar siúl cheana féin ag %s"
 
-#: builtin/notes.c
 #, c-format
 msgid "failed to store link to current notes ref (%s)"
 msgstr "theip ar nasc a stóráil le nótaí reatha tagairt (%s)"
 
-#: builtin/notes.c
 #, c-format
 msgid ""
 "Automatic notes merge failed. Fix conflicts in %s and commit the result with "
@@ -11713,65 +9961,64 @@
 "an toradh a dhéanamh le 'git notes merge --commit', nó cuir deireadh leis an "
 "cumasc le 'git notes merge --abort'.\n"
 
-#: builtin/notes.c builtin/tag.c
 #, c-format
 msgid "Failed to resolve '%s' as a valid ref."
 msgstr "Theip ar '%s' a réiteach mar thagartha bailí."
 
-#: builtin/notes.c
 #, c-format
 msgid "Object %s has no note\n"
 msgstr "Níl aon nóta ag réad %s\n"
 
-#: builtin/notes.c
 msgid "attempt to remove non-existent note is not an error"
 msgstr "ní earráid é iarracht nóta nach bhfuil ann a bhaint"
 
-#: builtin/notes.c
 msgid "read object names from the standard input"
 msgstr "léigh ainmneacha réada ón ionchur caighdeánach"
 
-#: builtin/notes.c builtin/prune.c builtin/worktree.c
 msgid "do not remove, show only"
 msgstr "ná bain, taispeáin amháin"
 
-#: builtin/notes.c
 msgid "report pruned notes"
 msgstr "nótaí gearrtha a thuairisciú"
 
-#: builtin/notes.c
 msgid "notes-ref"
 msgstr "nótairea-tagairt"
 
-#: builtin/notes.c
 msgid "use notes from <notes-ref>"
 msgstr "úsáid nótaí ó <notes-ref>"
 
-#: builtin/notes.c builtin/remote.c parse-options.c
 #, c-format
 msgid "unknown subcommand: `%s'"
 msgstr "fo-ordú anaithnid: `%s'"
 
-#: builtin/pack-objects.c
-msgid "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]"
-msgstr "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]"
-
-#: builtin/pack-objects.c
 msgid ""
-"git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]"
+"git pack-objects [-q | --progress | --all-progress] [--all-progress-"
+"implied]\n"
+"                 [--no-reuse-delta] [--delta-base-offset] [--non-empty]\n"
+"                 [--local] [--incremental] [--window=<n>] [--depth=<n>]\n"
+"                 [--revs [--unpacked | --all]] [--keep-pack=<pack-name>]\n"
+"                 [--cruft] [--cruft-expiration=<time>]\n"
+"                 [--stdout [--filter=<filter-spec>] | <base-name>]\n"
+"                 [--shallow] [--keep-true-parents] [--[no-]sparse]\n"
+"                 [--name-hash-version=<n>] [--path-walk] < <object-list>"
 msgstr ""
-"git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]"
+"git pack-objects [-q | --progress | --all-progress] [--all-progress-"
+"implied]\n"
+"                 [--no-reuse-delta] [--delta-base-offset] [--non-empty]\n"
+"                 [--local] [--incremental] [--window=<n>] [--depth=<n>]\n"
+"                 [--revs [--unpacked | --all]] [--keep-pack=<pack-name>]\n"
+"                 [--cruft] [--cruft-expiration=<time>]\n"
+"                 [--stdout [--filter=<filter-spec>] | <base-name>]\n"
+"                 [--shallow] [--keep-true-parents] [--[no-]sparse]\n"
+"                 [--name-hash-version=<n>] [--path-walk] < <object-list>"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "invalid --name-hash-version option: %d"
 msgstr "rogha neamhbhailí --name-hash-version: %d"
 
-#: builtin/pack-objects.c
 msgid "currently, --write-bitmap-index requires --name-hash-version=1"
 msgstr "faoi láthair, teastaíonn --write-bitmap-index --name-hash-version=1"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid ""
 "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in "
@@ -11780,132 +10027,118 @@
 "write_reuse_object: níorbh fhéidir %s a aimsiú, bhíothas ag súil leis ag an "
 "bhfritháireamh %<PRIuMAX> sa phacáiste %s"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "bad packed object CRC for %s"
 msgstr "réad pacáilte dona CRC le haghaidh %s"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "corrupt packed object for %s"
 msgstr "réad pacáilte truaillithe do %s"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "recursive delta detected for object %s"
 msgstr "braithíodh delta athfhillteach do réad %s"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "ordered %u objects, expected %<PRIu32>"
-msgstr "rudaí %u ordaithe, súil leis% <PRIu32>"
+msgstr "%u réad ordaithe, %<PRIu32> ag súil leis"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "expected object at offset %<PRIuMAX> in pack %s"
 msgstr ""
 "réad a bhíothas ag súil leis ag an bhfritháireamh %<PRIuMAX> sa phacáiste %s"
 
-#: builtin/pack-objects.c
 msgid "disabling bitmap writing, packs are split due to pack.packSizeLimit"
 msgstr ""
 "scríobh bitmap a dhíchumasú, roinntear pacáistí mar gheall ar "
 "pack.packSizeLimit"
 
-#: builtin/pack-objects.c
 msgid "Writing objects"
 msgstr "Rudaí a scríobh"
 
-#: builtin/pack-objects.c builtin/update-index.c
 #, c-format
 msgid "failed to stat %s"
 msgstr "theip ar stát %s"
 
-#: builtin/pack-objects.c object-file.c
 #, c-format
 msgid "failed utime() on %s"
 msgstr "theip ar utime () ar %s"
 
-#: builtin/pack-objects.c
 msgid "failed to write bitmap index"
 msgstr "theip ar innéacs bitmap a scríobh"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "wrote %<PRIu32> objects while expecting %<PRIu32>"
 msgstr "scríobh %<PRIu32> rudaí agus iad ag súil leis %<PRIu32>"
 
-#: builtin/pack-objects.c builtin/repack.c
 msgid "disabling bitmap writing, as some objects are not being packed"
 msgstr "scríobh bitmap a dhíchumasú, toisc nach bhfuil roinnt rudaí á phacáil"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "delta base offset overflow in pack for %s"
 msgstr "forsreabhadh fhritháireamh bonn delta i bpacáiste do %s"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "delta base offset out of bound for %s"
 msgstr "bonn delta a fhritháireamh as ceangailte do %s"
 
-#: builtin/pack-objects.c
 msgid "Counting objects"
 msgstr "Rud a chomhaireamh"
 
-#: builtin/pack-objects.c pack-bitmap.c
 #, c-format
 msgid "unable to get size of %s"
-msgstr "nach féidir méid %s a fháil"
+msgstr "ní féidir méid %s a fháil"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "unable to parse object header of %s"
-msgstr "nach féidir ceanntásc réad %s a pháirseáil"
+msgstr "ní féidir ceanntásc réada %s a pharsáil"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "object %s cannot be read"
 msgstr "ní féidir réad %s a léamh"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "object %s inconsistent object length (%<PRIuMAX> vs %<PRIuMAX>)"
 msgstr "fad réada neamhréireach réad %s (%<PRIuMAX> vs %<PRIuMAX>)"
 
-#: builtin/pack-objects.c
 msgid "suboptimal pack - out of memory"
 msgstr "pacáiste suboptimal - as cuimhne"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "Delta compression using up to %d threads"
 msgstr "Comhbhrú Delta ag úsáid suas le snáitheanna %d"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "unable to pack objects reachable from tag %s"
-msgstr "nach féidir rudaí a phacáil inrochtana ó chlib %s"
+msgstr "ní féidir rudaí a phacáil ar féidir rochtain a fháil orthu ón gclib %s"
 
-#: builtin/pack-objects.c commit-graph.c
 #, c-format
 msgid "unable to get type of object %s"
-msgstr "nach féidir cineál réada %s a fháil"
+msgstr "ní féidir cineál réada %s a fháil"
 
-#: builtin/pack-objects.c
+msgid "Compressing objects by path"
+msgstr "Ag comhbhrú rudaí de réir cosáin"
+
+#, c-format
+msgid "Path-based delta compression using up to %d thread"
+msgid_plural "Path-based delta compression using up to %d threads"
+msgstr[0] ""
+"Comhbhrú delta bunaithe ar chonair ag baint úsáide as suas le %d snáithe"
+msgstr[1] ""
+"Comhbhrú delta bunaithe ar chonair ag baint úsáide as suas le %d snáithe"
+msgstr[2] ""
+"Comhbhrú delta bunaithe ar chonair ag baint úsáide as suas le %d snáithe"
+
 msgid "Compressing objects"
 msgstr "Rudaí comhbhrúite"
 
-#: builtin/pack-objects.c
 msgid "inconsistency with delta count"
 msgstr "neamhréireacht le comhaireamh delta"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "invalid pack.allowPackReuse value: '%s'"
 msgstr "luach pack.allowPackReuse neamhbhailí: '%s'"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid ""
 "value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
@@ -11914,41 +10147,33 @@
 "<object-hash><pack-hash><uri>caithfidh luach uploadpack.blobpackfileuri a "
 "bheith den fhoirm '' (fuair '%s')"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid ""
 "object already configured in another uploadpack.blobpackfileuri (got '%s')"
 msgstr ""
 "réad cumraithe cheana féin i uploadpack.blobpackfileuri eile (fuair '%s')"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "could not get type of object %s in pack %s"
 msgstr "ní fhéadfaí cineál réada %s a fháil i bpacáiste %s"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "could not find pack '%s'"
 msgstr "ní raibh an pacáiste '%s' in ann a aimsiú"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "packfile %s cannot be accessed"
 msgstr "ní féidir teacht ar chomhad pacáiste %s"
 
-#: builtin/pack-objects.c
 msgid "Enumerating cruft objects"
 msgstr "Ag áireamh rudaí cruft"
 
-#: builtin/pack-objects.c
 msgid "unable to add cruft objects"
-msgstr "in ann rudaí cruft a chur leis"
+msgstr "ní féidir rudaí cruft a chur leis"
 
-#: builtin/pack-objects.c
 msgid "Traversing cruft objects"
 msgstr "Ag trasnú ar rudaí cruth"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid ""
 "expected edge object ID, got garbage:\n"
@@ -11957,7 +10182,6 @@
 "ag súil le haitheantas réada imeall, fuarthas bruscar:\n"
 "%s"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid ""
 "expected object ID, got garbage:\n"
@@ -11966,278 +10190,219 @@
 "aitheantas réada a bhfuil súil leis, fuair truflais:\n"
 " %s"
 
-#: builtin/pack-objects.c reachable.c
 msgid "could not load cruft pack .mtimes"
 msgstr "ní fhéadfaí pacáiste cruft a luchtú .mtimes"
 
-#: builtin/pack-objects.c
 msgid "cannot open pack index"
 msgstr "ní féidir innéacs pacáiste a osc"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "loose object at %s could not be examined"
 msgstr "ní fhéadfaí réad scaoilte ag %s a scrúdú"
 
-#: builtin/pack-objects.c
 msgid "unable to force loose object"
-msgstr "in ann rud scaoilte a chur i bhfeidhm"
+msgstr "ní féidir fórsa réad scaoilte"
 
-#: builtin/pack-objects.c
+msgid "failed to pack objects via path-walk"
+msgstr "theip ar rudaí a phacáil tríd an gcosán-siúlóid"
+
 #, c-format
 msgid "not a rev '%s'"
 msgstr "ní rev '%s'"
 
-#: builtin/pack-objects.c builtin/rev-parse.c
 #, c-format
 msgid "bad revision '%s'"
 msgstr "droch-athbhreithniú '%s'"
 
-#: builtin/pack-objects.c
 msgid "unable to add recent objects"
-msgstr "in ann rudaí le déanaí a chur leis"
+msgstr "ní féidir rudaí le déanaí a chur leis"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "unsupported index version %s"
 msgstr "leagan innéacs neamhthacaithe %s"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "bad index version '%s'"
 msgstr "droch-leagan innéacs '%s'"
 
-#: builtin/pack-objects.c
 msgid "show progress meter during object writing phase"
 msgstr "méadar dul chun cinn a thaispeáint le linn céim sc"
 
-#: builtin/pack-objects.c
 msgid "similar to --all-progress when progress meter is shown"
 msgstr "cosúil le --all-progress nuair a thaispeántar méadar dul chun cinn"
 
-#: builtin/pack-objects.c
 msgid "<version>[,<offset>]"
 msgstr "<version>[,<offset>]"
 
-#: builtin/pack-objects.c
 msgid "write the pack index file in the specified idx format version"
 msgstr "scríobh an comhad innéacs pacáiste sa leagan formáid idx sonraithe"
 
-#: builtin/pack-objects.c
 msgid "maximum size of each output pack file"
 msgstr "uasmhéid gach comhad pacáiste aschuir"
 
-#: builtin/pack-objects.c
 msgid "ignore borrowed objects from alternate object store"
 msgstr "neamhaird a dhéanamh ar rudaí atá ar iasacht ó stór"
 
-#: builtin/pack-objects.c
 msgid "ignore packed objects"
 msgstr "neamhaird a dhéanamh ar earraí"
 
-#: builtin/pack-objects.c
 msgid "limit pack window by objects"
 msgstr "teorainn fuinneog pacáiste de réir rudaí"
 
-#: builtin/pack-objects.c
 msgid "limit pack window by memory in addition to object limit"
 msgstr "teorainn le fuinneog pacáiste de réir chuimhne i dteannta le teorainn"
 
-#: builtin/pack-objects.c
 msgid "maximum length of delta chain allowed in the resulting pack"
-msgstr "fad uasta an slabhra delta a cheadaítear sa phacáiste mar thoradh air"
+msgstr ""
+"uasfhad an tslabhra delta a cheadaítear sa phacáiste mar thoradh air sin"
 
-#: builtin/pack-objects.c
 msgid "reuse existing deltas"
 msgstr "déltaí atá ann cheana a athúsáid"
 
-#: builtin/pack-objects.c
 msgid "reuse existing objects"
 msgstr "athúsáid rudaí atá ann cheana"
 
-#: builtin/pack-objects.c
 msgid "use OFS_DELTA objects"
 msgstr "bain úsáid as rudaí OFS_DELTA"
 
-#: builtin/pack-objects.c
 msgid "use threads when searching for best delta matches"
 msgstr "úsáid snáitheanna agus tú ag cuardach na cluichí delta is fearr"
 
-#: builtin/pack-objects.c
 msgid "do not create an empty pack output"
 msgstr "ná cruthaigh aschur pacáiste folamh"
 
-#: builtin/pack-objects.c
 msgid "read revision arguments from standard input"
 msgstr "léigh argóintí athbhreithnithe ó ionchur"
 
-#: builtin/pack-objects.c
 msgid "limit the objects to those that are not yet packed"
 msgstr "teorainn leis na rudaí dóibh siúd nach bhfuil pacáilte fós"
 
-#: builtin/pack-objects.c
 msgid "include objects reachable from any reference"
 msgstr "áireamh rudaí atá inrochtana ó aon tagairt"
 
-#: builtin/pack-objects.c
 msgid "include objects referred by reflog entries"
 msgstr "áireamh rudaí a dtagraítear ag iontrálacha reflog"
 
-#: builtin/pack-objects.c
 msgid "include objects referred to by the index"
 msgstr "áireamh rudaí dá dtagraíonn an t-innéacs"
 
-#: builtin/pack-objects.c
 msgid "read packs from stdin"
 msgstr "léigh pacáistí ó stdin"
 
-#: builtin/pack-objects.c
 msgid "output pack to stdout"
 msgstr "pacáiste aschuir go stdout"
 
-#: builtin/pack-objects.c
 msgid "include tag objects that refer to objects to be packed"
 msgstr "áireamh rudaí clibeanna a thagraíonn do rudaí atá le pacáil"
 
-#: builtin/pack-objects.c
 msgid "keep unreachable objects"
 msgstr "rudaí nach féidir a choinneáil"
 
-#: builtin/pack-objects.c
 msgid "pack loose unreachable objects"
 msgstr "rudaí scaoilte nach féidir a phacáil"
 
-#: builtin/pack-objects.c
 msgid "unpack unreachable objects newer than <time>"
 msgstr "rudaí nach féidir a dhíphacáil níos nuaí ná <time>"
 
-#: builtin/pack-objects.c
 msgid "create a cruft pack"
 msgstr "cruthaigh pacáiste cruft"
 
-#: builtin/pack-objects.c
 msgid "expire cruft objects older than <time>"
 msgstr "dul in éag rudaí cruft níos sine ná <time>"
 
-#: builtin/pack-objects.c
 msgid "use the sparse reachability algorithm"
 msgstr "úsáid an algartam inrochtaineachta neamhchoitianta"
 
-#: builtin/pack-objects.c
 msgid "create thin packs"
 msgstr "cruthaigh pacáistí tanaí"
 
-#: builtin/pack-objects.c
+msgid "use the path-walk API to walk objects when possible"
+msgstr ""
+"bain úsáid as an API siúlóide cosáin chun siúlóid a dhéanamh ar rudaí nuair "
+"is féidir"
+
 msgid "create packs suitable for shallow fetches"
 msgstr "pacáistí a chruthú atá oiriúnach le haghaidh tógá"
 
-#: builtin/pack-objects.c
 msgid "ignore packs that have companion .keep file"
 msgstr "neamhaird a dhéanamh ar phacáistí a bhfuil comhad compánach"
 
-#: builtin/pack-objects.c
 msgid "ignore this pack"
 msgstr "neamhaird a dhéanamh ar an b"
 
-#: builtin/pack-objects.c
 msgid "pack compression level"
 msgstr "leibhéal comhbhrú pacáiste"
 
-#: builtin/pack-objects.c
 msgid "do not hide commits by grafts"
 msgstr "ná déan gealltanais ag grafts i bhfolach"
 
-#: builtin/pack-objects.c
 msgid "use a bitmap index if available to speed up counting objects"
 msgstr ""
 "úsáid innéacs bitmap má tá sé ar fáil chun rudaí a chomhaireamh a bhrostú"
 
-#: builtin/pack-objects.c
 msgid "write a bitmap index together with the pack index"
 msgstr "scríobh innéacs bitmap in éineacht leis an innéacs pacáiste"
 
-#: builtin/pack-objects.c
 msgid "write a bitmap index if possible"
 msgstr "scríobh innéacs bitmap más féidir"
 
-#: builtin/pack-objects.c
 msgid "handling for missing objects"
 msgstr "láimhseáil le haghaidh rudaí atá"
 
-#: builtin/pack-objects.c
 msgid "do not pack objects in promisor packfiles"
 msgstr "ná pacáil rudaí i gcomhaid pacáiste gealltanais"
 
-#: builtin/pack-objects.c
 msgid "implies --missing=allow-any"
 msgstr "tugann le tuiscint --missing=allow-any"
 
-#: builtin/pack-objects.c
 msgid "respect islands during delta compression"
 msgstr "meas ar oileáin le linn comhbhrúite delta"
 
-#: builtin/pack-objects.c
 msgid "protocol"
 msgstr "prótacal"
 
-#: builtin/pack-objects.c
 msgid "exclude any configured uploadpack.blobpackfileuri with this protocol"
 msgstr "eisiamh aon uploadpack.blobpackfileuri cumraithe leis an bprótacal seo"
 
-#: builtin/pack-objects.c
 msgid "use the specified name-hash function to group similar objects"
 msgstr ""
 "bain úsáid as an bhfeidhm sonraithe ainm-hash chun rudaí den chineál céanna a"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "delta chain depth %d is too deep, forcing %d"
 msgstr ""
 "tá doimhneacht slabhra delta %d ró-dhomhain, rud a chuireann iallach ar %d"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid "pack.deltaCacheLimit is too high, forcing %d"
 msgstr "pack.deltaCacheLimit ró-ard, ag cur %d i bhfeidhm"
 
-#: builtin/pack-objects.c config.c
+#, c-format
+msgid "cannot use %s with %s"
+msgstr "ní féidir %s a úsáid le %s"
+
 #, c-format
 msgid "bad pack compression level %d"
 msgstr "leibhéal comhbhrúite droch-phacáiste %d"
 
-#: builtin/pack-objects.c
 msgid "--max-pack-size cannot be used to build a pack for transfer"
 msgstr "Ní féidir --max-pack-size a úsáid chun pacáiste a thógáil le haistriú"
 
-#: builtin/pack-objects.c
 msgid "minimum pack size limit is 1 MiB"
 msgstr "is é teorainn íosta méid an phacáiste ná 1 MiB"
 
-#: builtin/pack-objects.c
 msgid "--thin cannot be used to build an indexable pack"
 msgstr "Ní féidir --thin a úsáid chun pacáiste innéacsaithe a thógáil"
 
-#: builtin/pack-objects.c
-msgid "cannot use --filter with --stdin-packs"
-msgstr "ní féidir --filter a úsáid le --stdin-packs"
-
-#: builtin/pack-objects.c
 msgid "cannot use internal rev list with --stdin-packs"
 msgstr "ní féidir liosta rev inmheánach a úsáid le --stdin-packs"
 
-#: builtin/pack-objects.c
 msgid "cannot use internal rev list with --cruft"
 msgstr "ní féidir liosta rev inmheánach a úsáid le --cruft"
 
-#: builtin/pack-objects.c
-msgid "cannot use --stdin-packs with --cruft"
-msgstr "ní féidir --stdin-packs a úsáid le --cruft"
-
-#: builtin/pack-objects.c
 msgid "Enumerating objects"
 msgstr "Rudaí a chur san áireamh"
 
-#: builtin/pack-objects.c
 #, c-format
 msgid ""
 "Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
@@ -12246,137 +10411,72 @@
 "%<PRIu32> iomlán (delta %<PRIu32>), %<PRIu32> athúsáidte (delta %<PRIu32>), "
 "%<PRIu32> athúsáidte sa phacáiste (ó %<PRIuMAX>)"
 
-#: builtin/pack-redundant.c
-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 ""
-"Tá 'git pack-redundant' ainmnithe le baint.\n"
-"Má úsáideann tú an t-ordú seo fós, cuir rogha b\n"
-"hreise, '--i-still-use-this', leis an líne ordaithe \n"
-"agus cuir in iúl dúinn go n-úsáideann tú fós é trí ríomhphost \n"
-"a sheoladh chuig <git@vger.kernel.org>.  Go raibh maith agat.\n"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
-#: builtin/pack-redundant.c
-msgid "refusing to run without --i-still-use-this"
-msgstr "ag diúltú rith gan --i-still-use-this fós"
-
-#: builtin/pack-refs.c
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"<pattern><pattern>git pack-refs [--all] [--no-prunes] [--auto] [--include] "
-"[--eisiamh]"
-
-#: builtin/pack-refs.c
-msgid "pack everything"
-msgstr "pacáil gach rud"
-
-#: builtin/pack-refs.c
-msgid "prune loose refs (default)"
-msgstr "briseadh scaoilte (réamhshocraithe)"
-
-#: builtin/pack-refs.c
-msgid "auto-pack refs as needed"
-msgstr "tuairiscintí uathoibríoch pacáiste"
-
-#: builtin/pack-refs.c
-msgid "references to include"
-msgstr "tagairtí lena n-áirítear"
-
-#: builtin/pack-refs.c
-msgid "references to exclude"
-msgstr "tagairtí chun eisiamh"
-
-#: builtin/patch-id.c
 msgid "git patch-id [--stable | --unstable | --verbatim]"
 msgstr "git patch-id [--seasmhach | --éagobhsaí | --verbatim]"
 
-#: builtin/patch-id.c
 msgid "use the unstable patch-id algorithm"
 msgstr "bain úsáid as an algartam paith-id éagobhsaí"
 
-#: builtin/patch-id.c
 msgid "use the stable patch-id algorithm"
 msgstr "bain úsáid as an algartam paith-id cobhsaí"
 
-#: builtin/patch-id.c
 msgid "don't strip whitespace from the patch"
 msgstr "ná tarraingt spás bán ón bpaiste"
 
-#: builtin/prune.c
 msgid "git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]"
-msgstr "<head>git plum [-n] [-v] [--progress] [--dul in éag] [<time>--] [...]"
+msgstr "git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]"
 
-#: builtin/prune.c
 msgid "report pruned objects"
 msgstr "tuairisciú rudaí gearrtha"
 
-#: builtin/prune.c
 msgid "expire objects older than <time>"
 msgstr "dul in éag rudaí níos sine ná <time>"
 
-#: builtin/prune.c
 msgid "limit traversal to objects outside promisor packfiles"
 msgstr "teorainn a chur ar thrasú le rudaí lasmuigh de phacáiste gealltan"
 
-#: builtin/prune.c
 msgid "cannot prune in a precious-objects repo"
 msgstr "ní féidir le bearradh i repo rudaí luachmhara"
 
-#: builtin/pull.c
 msgid "git pull [<options>] [<repository> [<refspec>...]]"
-msgstr "git pull [<options>] [<repository>[<refspec>...]]"
+msgstr "git pull [<options>] [<repository> [<refspec>...]]"
 
-#: builtin/pull.c
 msgid "control for recursive fetching of submodules"
 msgstr "rialú maidir le fo-mhodúil a fháil athshlánach"
 
-#: builtin/pull.c
 msgid "Options related to merging"
 msgstr "Roghanna a bhaineann le cumasc"
 
-#: builtin/pull.c
 msgid "incorporate changes by rebasing rather than merging"
 msgstr "athruithe a ionchorprú trí athbhunú seachas cumasc"
 
-#: builtin/pull.c builtin/revert.c
 msgid "allow fast-forward"
 msgstr "ligean go tapa ar aghaidh"
 
-#: builtin/pull.c
 msgid "control use of pre-merge-commit and commit-msg hooks"
 msgstr "úsáid crúcaí réamh-chumaisc agus comh-msg a rialú"
 
-#: builtin/pull.c parse-options.h
 msgid "automatically stash/stash pop before and after"
 msgstr "pop a stash/stash go huathoibríoch roimh agus tar éis"
 
-#: builtin/pull.c
 msgid "Options related to fetching"
 msgstr "Roghanna a bhaineann le tarraingt"
 
-#: builtin/pull.c
 msgid "force overwrite of local branch"
 msgstr "forscríobh fórsa ar bhrainse áitiúil"
 
-#: builtin/pull.c
 msgid "number of submodules pulled in parallel"
 msgstr "líon na bhfo-mhodúil tarraingthe go comhthreom"
 
-#: builtin/pull.c parse-options.h
 msgid "use IPv4 addresses only"
 msgstr "bain úsáid as seoltaí IPv4 amháin"
 
-#: builtin/pull.c parse-options.h
 msgid "use IPv6 addresses only"
 msgstr "bain úsáid as seoltaí IPv6 amháin"
 
-#: builtin/pull.c
 msgid ""
 "There is no candidate for rebasing against among the refs that you just "
 "fetched."
@@ -12384,13 +10484,11 @@
 "Níl aon iarrthóir ann chun athbhreithniú i measc na n-airíonna a fuair tú "
 "díreach."
 
-#: builtin/pull.c
 msgid ""
 "There are no candidates for merging among the refs that you just fetched."
 msgstr ""
 "Níl aon iarrthóirí ann chun cumasc i measc na gcomharthaí a fuair tú díreach."
 
-#: builtin/pull.c
 msgid ""
 "Generally this means that you provided a wildcard refspec which had no\n"
 "matches on the remote end."
@@ -12399,7 +10497,6 @@
 "nach raibh aon\n"
 "cluichí ar an gceann iargúlta."
 
-#: builtin/pull.c
 #, c-format
 msgid ""
 "You asked to pull from the remote '%s', but did not specify\n"
@@ -12410,42 +10507,33 @@
 "brainse. Toisc nach é seo an cianda cumraithe réamhshocraithe\n"
 "do bhrainse reatha, ní mór duit brainse a shonrú ar an líne ordaithe."
 
-#: builtin/pull.c builtin/rebase.c
 msgid "You are not currently on a branch."
 msgstr "Níl tú ar bhrainse faoi láthair."
 
-#: builtin/pull.c
 msgid "Please specify which branch you want to rebase against."
 msgstr "Sonraigh le do thoil cén brainse is mian leat a athbhunú ina choinne."
 
-#: builtin/pull.c
 msgid "Please specify which branch you want to merge with."
 msgstr "Sonraigh le do thoil cén brainse is mian leat a chumasc leis."
 
-#: builtin/pull.c
 msgid "See git-pull(1) for details."
 msgstr "Féach git-pull (1) le haghaidh sonraí."
 
-#: builtin/pull.c builtin/rebase.c
 msgid "<remote>"
 msgstr "<remote>"
 
-#: builtin/pull.c scalar.c
 msgid "<branch>"
 msgstr "<branch>"
 
-#: builtin/pull.c builtin/rebase.c
 msgid "There is no tracking information for the current branch."
 msgstr "Níl aon fhaisnéis rianaithe don bhrainse reatha."
 
-#: builtin/pull.c
 msgid ""
 "If you wish to set tracking information for this branch you can do so with:"
 msgstr ""
 "Más mian leat faisnéis rianaithe a shocrú don bhrainse seo is féidir leat é "
 "sin a dhéanamh le:"
 
-#: builtin/pull.c
 #, c-format
 msgid ""
 "Your configuration specifies to merge with the ref '%s'\n"
@@ -12454,21 +10542,17 @@
 "Sonraíonn do chumraíocht a chumasc leis an tagairt '%s'\n"
 "ón iargúlta, ach níor faightear aon tagairt den sórt sin."
 
-#: builtin/pull.c
 #, c-format
 msgid "unable to access commit %s"
-msgstr "nach féidir teacht ar thiomantas %s"
+msgstr "ní féidir rochtain a fháil ar thiomnadh %s"
 
-#: builtin/pull.c refspec.c
 #, c-format
 msgid "invalid refspec '%s'"
 msgstr "refspec neamhbhailí '%s'"
 
-#: builtin/pull.c
 msgid "ignoring --verify-signatures for rebase"
 msgstr "ag neamhaird --verify-signatures le haghaidh athbhunú"
 
-#: builtin/pull.c
 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"
@@ -12501,19 +10585,15 @@
 "shárú\n"
 "ionghairm.\n"
 
-#: builtin/pull.c
 msgid "Updating an unborn branch with changes added to the index."
 msgstr "Brainse breithe a nuashonrú le hathruithe curtha leis an innéacs."
 
-#: builtin/pull.c
 msgid "pull with rebase"
 msgstr "tarraing le rebase"
 
-#: builtin/pull.c builtin/rebase.c
 msgid "Please commit or stash them."
 msgstr "Déan iad a thiomantas nó a stóráil le do thoil."
 
-#: builtin/pull.c
 #, c-format
 msgid ""
 "fetch updated the current branch head.\n"
@@ -12524,7 +10604,6 @@
 "do chrann oibre a chur ar aghaidh go tapa ó\n"
 "tiomantas %s."
 
-#: builtin/pull.c
 #, c-format
 msgid ""
 "Cannot fast-forward your working tree.\n"
@@ -12541,39 +10620,30 @@
 "$ git reset --hard\n"
 "chun aisghabháil."
 
-#: builtin/pull.c
 msgid "Cannot merge multiple branches into empty head."
 msgstr "Ní féidir brainsí iomadúla a chumasc i gceann folamh."
 
-#: builtin/pull.c
 msgid "Cannot rebase onto multiple branches."
 msgstr "Ní féidir athbhunú ar iliomad brainsí."
 
-#: builtin/pull.c
 msgid "Cannot fast-forward to multiple branches."
 msgstr "Ní féidir dul ar aghaidh go tapa go brainsí iolracha."
 
-#: builtin/pull.c
 msgid "Need to specify how to reconcile divergent branches."
 msgstr "Ní mór a shonrú conas brainsí éagsúla a réiteach."
 
-#: builtin/pull.c
 msgid "cannot rebase with locally recorded submodule modifications"
 msgstr "ní féidir athbhunú le modhnuithe fo-mhodúil atá taifeadta"
 
-#: builtin/push.c
 msgid "git push [<options>] [<repository> [<refspec>...]]"
-msgstr "git push [<roghanna>] [<stóras> [<refspec>...]]"
+msgstr "git push [<options>] [<repository> [<refspec>...]]"
 
-#: builtin/push.c
 msgid "tag shorthand without <tag>"
 msgstr "gearrthand clib gan <tag>"
 
-#: builtin/push.c
 msgid "--delete only accepts plain target ref names"
 msgstr "--delete ní ghlacann sé ach le hainmneacha tagartha sprice simplí"
 
-#: builtin/push.c
 msgid ""
 "\n"
 "To choose either option permanently, see push.default in 'git help config'.\n"
@@ -12582,7 +10652,6 @@
 "Chun ceachtar rogha a roghnú go buan, féach push.default i 'git help "
 "config'.\n"
 
-#: builtin/push.c
 msgid ""
 "\n"
 "To avoid automatically configuring an upstream branch when its name\n"
@@ -12595,7 +10664,6 @@
 "branch.autoSetupMerge\n"
 "i 'git help config'.\n"
 
-#: builtin/push.c
 #, c-format
 msgid ""
 "The upstream branch of your current branch does not match\n"
@@ -12620,7 +10688,6 @@
 "    git push %s HEAD\n"
 "%s%s"
 
-#: builtin/push.c
 #, c-format
 msgid ""
 "You are not currently on a branch.\n"
@@ -12635,7 +10702,6 @@
 "\n"
 " git push %s HEAD:<ainm-na-brainse-cianda>\n"
 
-#: builtin/push.c
 msgid ""
 "\n"
 "To have this happen automatically for branches without a tracking\n"
@@ -12645,7 +10711,6 @@
 "Chun é seo a tharlóidh go huathoibríoch do bhrainsí gan rianú\n"
 "suas sruth, féach 'push.autoSetupRemote' i 'git help config'.\n"
 
-#: builtin/push.c
 #, c-format
 msgid ""
 "The current branch %s has no upstream branch.\n"
@@ -12661,19 +10726,16 @@
 "    git push --set-upstream %s %s\n"
 "%s"
 
-#: builtin/push.c
 #, c-format
 msgid "The current branch %s has multiple upstream branches, refusing to push."
 msgstr ""
 "Tá brainsí iolracha suas srutha ag an mbrainse reatha %s, ag diúltú brú."
 
-#: builtin/push.c
 msgid ""
 "You didn't specify any refspecs to push, and push.default is \"nothing\"."
 msgstr ""
 "Níor shonraigh tú aon refspec le brú, agus is é push.default “rud ar bith”."
 
-#: builtin/push.c
 #, c-format
 msgid ""
 "You are pushing to remote '%s', which is not the upstream of\n"
@@ -12684,7 +10746,6 @@
 "do bhrainse reatha '%s', gan insint liom cad ba cheart a bhrú\n"
 "chun an brainse iargúlta a nuashonrú."
 
-#: builtin/push.c
 msgid ""
 "Updates were rejected because the tip of your current branch is behind\n"
 "its remote counterpart. If you want to integrate the remote changes,\n"
@@ -12698,7 +10759,6 @@
 "bain úsáid as 'git pull' sula mbrú arís.\n"
 "Féach an 'Nóta faoi fast-forward 'i 'git push --help' le haghaidh sonraí."
 
-#: builtin/push.c
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
 "counterpart. If you want to integrate the remote changes, use 'git pull'\n"
@@ -12711,7 +10771,6 @@
 "sula ndéantar é a bhrú arís.\n"
 "Féach an 'Nóta faoi fast-forward 'i 'git push --help' le haghaidh sonraí."
 
-#: builtin/push.c
 msgid ""
 "Updates were rejected because the remote contains work that you do not\n"
 "have locally. This is usually caused by another repository pushing to\n"
@@ -12727,12 +10786,10 @@
 "'git tarraing' sula ndéantar é a bhrú arís.\n"
 "Féach an 'Nóta faoi fast-forward 'i 'git push --help' le haghaidh sonraí."
 
-#: builtin/push.c
 msgid "Updates were rejected because the tag already exists in the remote."
 msgstr ""
 "Diúltaíodh nuashonruithe toisc go bhfuil an clib ann cheana féin sa iargúlta."
 
-#: builtin/push.c
 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"
@@ -12744,7 +10801,6 @@
 "thiomanta,\n"
 "gan an rogha '--force' a úsáid.\n"
 
-#: builtin/push.c
 msgid ""
 "Updates were rejected because the tip of the remote-tracking branch has\n"
 "been updated since the last checkout. If you want to integrate the\n"
@@ -12756,17 +10812,14 @@
 "athruithe iargúlta, bain úsáid as 'git pull' sula mbrú arís.\n"
 "Féach an 'Nóta faoi fast-forward 'i 'git push --help' le haghaidh sonraí."
 
-#: builtin/push.c
 #, c-format
 msgid "Pushing to %s\n"
 msgstr "Ag brú chuig %s\n"
 
-#: builtin/push.c
 #, c-format
 msgid "failed to push some refs to '%s'"
 msgstr "theip ar roinnt réimsí a bhrú chuig '%s'"
 
-#: builtin/push.c
 msgid ""
 "recursing into submodule with push.recurseSubmodules=only; using on-demand "
 "instead"
@@ -12774,94 +10827,72 @@
 "athfhillteach isteach i bhfo-mhodúl le push.recurseSubmodules=only; ag baint "
 "úsáide as ar-éileamh ina ionad"
 
-#: builtin/push.c builtin/send-pack.c submodule-config.c
 #, c-format
 msgid "invalid value for '%s'"
 msgstr "luach neamhbhailí do '%s'"
 
-#: builtin/push.c builtin/submodule--helper.c
 msgid "repository"
 msgstr "stóras"
 
-#: builtin/push.c
 msgid "push all branches"
 msgstr "brúigh gach brainse"
 
-#: builtin/push.c builtin/send-pack.c
 msgid "mirror all refs"
 msgstr "scáthán gach ceann"
 
-#: builtin/push.c
 msgid "delete refs"
 msgstr "scrios réimsí"
 
-#: builtin/push.c
 msgid "push tags (can't be used with --all or --branches or --mirror)"
 msgstr ""
 "clibeanna brú (ní féidir iad a úsáid le --all nó --branches nó --mirror)"
 
-#: builtin/push.c builtin/send-pack.c
 msgid "force updates"
 msgstr "nuashonruithe fórsa"
 
-#: builtin/push.c builtin/send-pack.c
 msgid "<refname>:<expect>"
 msgstr "<refname>:<expect>"
 
-#: builtin/push.c builtin/send-pack.c
 msgid "require old value of ref to be at this value"
 msgstr "a cheangal go mbeadh seanluach an tagartha ag an luach seo"
 
-#: builtin/push.c builtin/send-pack.c
 msgid "require remote updates to be integrated locally"
 msgstr "éilíonn go ndéanfaí nuashonruithe iargúlta"
 
-#: builtin/push.c
 msgid "control recursive pushing of submodules"
 msgstr "brú athfhillteach ar fho-mhodúil a rialú"
 
-#: builtin/push.c builtin/send-pack.c
 msgid "use thin pack"
 msgstr "bain úsáid as pacáiste tanaí"
 
-#: builtin/push.c builtin/send-pack.c
 msgid "receive pack program"
 msgstr "clár pacáiste a fháil"
 
-#: builtin/push.c
 msgid "set upstream for git pull/status"
 msgstr "socraigh suas sruth le haghaidh tarraing/stádas git"
 
-#: builtin/push.c
 msgid "prune locally removed refs"
 msgstr "gearradh a bhaintear go háitiúil"
 
-#: builtin/push.c
 msgid "bypass pre-push hook"
 msgstr "seachbhóthar crúca réamh"
 
-#: builtin/push.c
 msgid "push missing but relevant tags"
 msgstr "clibeanna atá ar iarraidh ach ábhartha a"
 
-#: builtin/push.c builtin/send-pack.c
 msgid "GPG sign the push"
 msgstr "Síníonn GPG an brú"
 
-#: builtin/push.c builtin/send-pack.c
 msgid "request atomic transaction on remote side"
 msgstr "iarraidh idirbheart adamach ar an taobh iargúl"
 
-#: builtin/push.c
 msgid "--delete doesn't make sense without any refs"
 msgstr "--delete níl ciall leis gan aon réiteoirí"
 
-#: builtin/push.c t/helper/test-bundle-uri.c
 #, c-format
 msgid "bad repository '%s'"
 msgstr "droch-stóras '%s'"
 
-#: builtin/push.c
 msgid ""
 "No configured push destination.\n"
 "Either specify the URL from the command-line or configure a remote "
@@ -12883,70 +10914,64 @@
 "\n"
 "    git push <ainm>\n"
 
-#: builtin/push.c
 msgid "--all can't be combined with refspecs"
 msgstr "--all ní féidir é a chomhcheangal le refspecs"
 
-#: builtin/push.c
 msgid "--mirror can't be combined with refspecs"
 msgstr "--mirror ní féidir é a chomhcheangal le refspecs"
 
-#: builtin/push.c
 msgid "push options must not have new line characters"
 msgstr "ní chóir go mbeadh carachtair líne nua ag roghanna brú"
 
-#: builtin/range-diff.c
 msgid "git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"
 msgstr "git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"
 
-#: builtin/range-diff.c
 msgid "git range-diff [<options>] <old-tip>...<new-tip>"
-msgstr "git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"
+msgstr "git range-diff [<options>] <old-tip>...<new-tip>"
 
-#: builtin/range-diff.c
 msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
 msgstr "git range-diff [<options>] <base> <old-tip> <new-tip>"
 
-#: builtin/range-diff.c
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "uasluach cuimhne neamhbhailí: %s"
+
 msgid "use simple diff colors"
 msgstr "bain úsáid as dathanna diff simplí"
 
-#: builtin/range-diff.c
 msgid "notes"
 msgstr "nótaí"
 
-#: builtin/range-diff.c
 msgid "passed to 'git log'"
 msgstr "cuireadh chuig 'git log'"
 
-#: builtin/range-diff.c
+msgid "size"
+msgstr "méid"
+
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr "uasmhéid cuimhne don mhaitrís costais (4G réamhshocraithe)"
+
 msgid "only emit output related to the first range"
 msgstr "ní scaoileann ach aschur a bhaineann leis an gcéad raon"
 
-#: builtin/range-diff.c
 msgid "only emit output related to the second range"
 msgstr "ní scaoileann ach aschur a bhaineann leis an dara raon"
 
-#: builtin/range-diff.c
 #, c-format
 msgid "not a revision: '%s'"
 msgstr "ní athbhreithniú: '%s'"
 
-#: builtin/range-diff.c
 #, c-format
 msgid "not a commit range: '%s'"
 msgstr "ní raon tiomanta: '%s'"
 
-#: builtin/range-diff.c
 #, c-format
 msgid "not a symmetric range: '%s'"
 msgstr "ní raon siméadrach: '%s'"
 
-#: builtin/range-diff.c
 msgid "need two commit ranges"
 msgstr "dhá raon tiomanta ag teastáil"
 
-#: builtin/read-tree.c
 msgid ""
 "git read-tree [(-m [--trivial] [--aggressive] | --reset | --"
 "prefix=<prefix>)\n"
@@ -12958,140 +10983,109 @@
 "              [-u | -i]] [--index-output=<file>] [--no-sparse-checkout]\n"
 "              (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"
 
-#: builtin/read-tree.c
 msgid "write resulting index to <file>"
 msgstr "scríobh innéacs mar thoradh air go <file>"
 
-#: builtin/read-tree.c
 msgid "only empty the index"
 msgstr "ach an t-innéacs a fholmhú"
 
-#: builtin/read-tree.c
 msgid "Merging"
 msgstr "Cumaisc"
 
-#: builtin/read-tree.c
 msgid "perform a merge in addition to a read"
 msgstr "cumaisc a dhéanamh i dteannta le léamh"
 
-#: builtin/read-tree.c
 msgid "3-way merge if no file level merging required"
 msgstr "Cumaisc trí bhealach mura gá cumasc leibhéal comhaid"
 
-#: builtin/read-tree.c
 msgid "3-way merge in presence of adds and removes"
 msgstr "Cumaisc 3 bhealach i láthair breiseanna agus bainteanna"
 
-#: builtin/read-tree.c
 msgid "same as -m, but discard unmerged entries"
 msgstr "mar an gcéanna le -m, ach caith iontrálacha neamh-chumhdaithe"
 
-#: builtin/read-tree.c
 msgid "<subdirectory>/"
 msgstr "<subdirectory>/"
 
-#: builtin/read-tree.c
 msgid "read the tree into the index under <subdirectory>/"
 msgstr "léigh an crann isteach san innéacs faoi<subdirectory>/"
 
-#: builtin/read-tree.c
 msgid "update working tree with merge result"
 msgstr "crann oibre a nuashonrú le toradh cumaisc"
 
-#: builtin/read-tree.c
 msgid "gitignore"
-msgstr "gignor"
+msgstr "gitignore"
 
-#: builtin/read-tree.c
 msgid "allow explicitly ignored files to be overwritten"
 msgstr "ligean do chomhaid a dhéantar neamhaird air go sainrá"
 
-#: builtin/read-tree.c
 msgid "don't check the working tree after merging"
 msgstr "ná seiceáil an crann oibre tar éis a chumasc"
 
-#: builtin/read-tree.c
 msgid "don't update the index or the work tree"
 msgstr "ná nuashonraigh an t-innéacs nó an crann oibre"
 
-#: builtin/read-tree.c
 msgid "skip applying sparse checkout filter"
 msgstr "scipeáil scagaire seiceála neamhchoitianta a"
 
-#: builtin/read-tree.c
 msgid "debug unpack-trees"
 msgstr "crainn díphacáilte a dhífhabhtú"
 
-#: builtin/read-tree.c
 msgid "suppress feedback messages"
 msgstr "teachtaireachtaí aiseolais"
 
-#: builtin/read-tree.c
 msgid "You need to resolve your current index first"
 msgstr "Ní mór duit d'innéacs reatha a réiteach ar dtús"
 
-#: builtin/rebase.c
 msgid ""
 "git rebase [-i] [options] [--exec <cmd>] [--onto <newbase> | --keep-base] "
 "[<upstream> [<branch>]]"
 msgstr ""
-"<upstream><branch>git rebase [-i] [roghanna] [--exec<cmd>] [--onto "
-"<newbase>| --keep-base] [[]]"
+"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase> | --keep-base] "
+"[<upstream> [<branch>]]"
 
-#: builtin/rebase.c
 msgid ""
 "git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]"
 msgstr ""
-"<newbase><branch>git rebase [-i] [roghanna] [--exec] [-- <cmd>onto] --root []"
+"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]"
 
-#: builtin/rebase.c sequencer.c
 #, c-format
 msgid "could not read '%s'."
 msgstr "ní raibh '%s' in ann a léamh."
 
-#: builtin/rebase.c
 #, c-format
 msgid "could not create temporary %s"
 msgstr "ní fhéadfaí %s sealadach a chruthú"
 
-#: builtin/rebase.c
 msgid "could not mark as interactive"
 msgstr "ní fhéadfaí marcáil mar idirghníomh"
 
-#: builtin/rebase.c
 msgid "could not generate todo list"
 msgstr "ní raibh in ann liosta todo a ghiniúint"
 
-#: builtin/rebase.c
 msgid "a base commit must be provided with --upstream or --onto"
 msgstr "caithfear gealltanas bonn a sholáthar le --upstream nó --onto"
 
-#: builtin/rebase.c
 #, c-format
 msgid "%s requires the merge backend"
 msgstr "Teastaíonn %s an cúltaca cumaisc"
 
-#: builtin/rebase.c
 #, c-format
 msgid "invalid onto: '%s'"
 msgstr "neamhbhailí ar: '%s'"
 
-#: builtin/rebase.c
 #, c-format
 msgid "invalid orig-head: '%s'"
 msgstr "orig-head neamhbhailí: '%s'"
 
-#: builtin/rebase.c
 #, c-format
 msgid "ignoring invalid allow_rerere_autoupdate: '%s'"
 msgstr "neamhaird a dhéanamh de allow_rerere_autoupdate neamhbhailí: '%s'"
 
-#: builtin/rebase.c builtin/rm.c sequencer.c
 #, c-format
 msgid "could not remove '%s'"
 msgstr "ní fhéadfaí '%s' a bhaint"
 
-#: builtin/rebase.c
 #, c-format
 msgid ""
 "\n"
@@ -13110,25 +11104,20 @@
 "\n"
 "Mar thoradh air sin, ní féidir le git iad a athbhunú."
 
-#: builtin/rebase.c
 #, c-format
 msgid "Unknown rebase-merges mode: %s"
 msgstr "Modh rebase-chumaisc anaithnid: %s"
 
-#: builtin/rebase.c
 #, c-format
 msgid "could not switch to %s"
 msgstr "ní fhéadfaí aistriú go %s"
 
-#: builtin/rebase.c
 msgid "apply options and merge options cannot be used together"
 msgstr "roghanna i bhfeidhm agus ní féidir roghanna cumaisc a úsáid le chéile"
 
-#: builtin/rebase.c
 msgid "--empty=ask is deprecated; use '--empty=stop' instead."
 msgstr "Tá --empty=ask díscríofa; bain úsáid as '--empty=stop' ina ionad."
 
-#: builtin/rebase.c
 #, c-format
 msgid ""
 "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
@@ -13137,7 +11126,6 @@
 "cineál folamh gan aithint '%s'; is iad na luachanna bailí ná “drop”, “keep”, "
 "agus “stop”."
 
-#: 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 "
@@ -13147,7 +11135,6 @@
 "obair i leagan amach anseo de Git. Úsáid --rebase-merges gan argóint ina "
 "ionad sin, a dhéanann an rud céanna."
 
-#: builtin/rebase.c
 #, c-format
 msgid ""
 "%s\n"
@@ -13164,7 +11151,6 @@
 "git rebase '<brainse>'\n"
 "\n"
 
-#: builtin/rebase.c
 #, c-format
 msgid ""
 "If you wish to set tracking information for this branch you can do so with:\n"
@@ -13178,171 +11164,130 @@
 "    git branch --set-upstream-to=%s/<branch> %s\n"
 "\n"
 
-#: builtin/rebase.c
 msgid "exec commands cannot contain newlines"
 msgstr "ní féidir línte nua a bheith ag orduithe exec"
 
-#: builtin/rebase.c
 msgid "empty exec command"
 msgstr "ordú exec folamh"
 
-#: builtin/rebase.c
 msgid "rebase onto given branch instead of upstream"
 msgstr "athbhunú ar an mbrainse ar leith in ionad suas an sruth"
 
-#: builtin/rebase.c
 msgid "use the merge-base of upstream and branch as the current base"
 msgstr "bain úsáid as bonn cumaisc suas sruth agus brainse mar an bonn reatha"
 
-#: builtin/rebase.c
 msgid "allow pre-rebase hook to run"
 msgstr "ligean do chrúca réamh-athbhunaithe rith"
 
-#: builtin/rebase.c
 msgid "be quiet. implies --no-stat"
 msgstr "a bheith ciúin. tugann le tuiscint --no-stat"
 
-#: builtin/rebase.c
 msgid "display a diffstat of what changed upstream"
 msgstr "taispeáint diffstat den rud a d'athraigh suas an sruth"
 
-#: builtin/rebase.c
 msgid "do not show diffstat of what changed upstream"
 msgstr "ná taispeáin diffstat den mhéid a d'athraigh suas an sruth"
 
-#: builtin/rebase.c
 msgid "add a Signed-off-by trailer to each commit"
 msgstr "cuir leantóir sínithe le gach tiomantas"
 
-#: builtin/rebase.c
 msgid "make committer date match author date"
 msgstr "dáta an údair comhoiriúnaithe dáta a dhéanamh"
 
-#: builtin/rebase.c
 msgid "ignore author date and use current date"
 msgstr "neamhaird a dhéanamh ar dháta údair agus bain úsáid as"
 
-#: builtin/rebase.c
 msgid "synonym of --reset-author-date"
 msgstr "comhchiallach de --reset-author-date"
 
-#: builtin/rebase.c
 msgid "passed to 'git apply'"
 msgstr "cuireadh chuig 'git apply'"
 
-#: builtin/rebase.c
 msgid "ignore changes in whitespace"
 msgstr "neamhaird a dhéanamh ar athruithe i spás bán"
 
-#: builtin/rebase.c
 msgid "cherry-pick all commits, even if unchanged"
 msgstr "roghnaigh silíní gach gealltanas, fiú mura bhfuil gan athrú"
 
-#: builtin/rebase.c
 msgid "continue"
 msgstr "leanúint"
 
-#: builtin/rebase.c
 msgid "skip current patch and continue"
 msgstr "scipeáil an paiste reatha agus lean ar aghaidh"
 
-#: builtin/rebase.c
 msgid "abort and check out the original branch"
 msgstr "déan deireadh a chur agus seiceáil ar an mbrainse bunaidh"
 
-#: builtin/rebase.c
 msgid "abort but keep HEAD where it is"
 msgstr "déan deireadh ach coinnigh CEAD san áit a bhfuil sé"
 
-#: builtin/rebase.c
 msgid "edit the todo list during an interactive rebase"
 msgstr "cuir an liosta todo in eagar le linn athbhunú idirghníomhach"
 
-#: builtin/rebase.c
 msgid "show the patch file being applied or merged"
 msgstr "taispeáin an comhad paiste atá á chur i bhfeidhm nó á chumas"
 
-#: builtin/rebase.c
 msgid "use apply strategies to rebase"
 msgstr "úsáid straitéisí i bhfeidhm chun athbhunú"
 
-#: builtin/rebase.c
 msgid "use merging strategies to rebase"
 msgstr "straitéisí cumaisc a úsáid chun athbhunú"
 
-#: builtin/rebase.c
 msgid "let the user edit the list of commits to rebase"
 msgstr "lig don úsáideoir liosta na dtiomantas a athbhunú a chur in eagar"
 
-#: builtin/rebase.c
 msgid "(REMOVED) was: try to recreate merges instead of ignoring them"
 msgstr ""
 "(Bainte) a bhí: déan iarracht cumaisc a athchruthú in ionad neamhaird a "
 "dhéanamh orthu"
 
-#: builtin/rebase.c builtin/revert.c
 msgid "how to handle commits that become empty"
 msgstr "conas gealltanais a éiríonn folamh a láimhseáil"
 
-#: builtin/rebase.c
 msgid "keep commits which start empty"
 msgstr "coinnigh gealltanais a thosaíonn folamh"
 
-#: builtin/rebase.c
 msgid "move commits that begin with squash!/fixup! under -i"
 msgstr "gealltanna gluaiseachta a thosaíonn le squash! /socrú! faoi -i"
 
-#: builtin/rebase.c
 msgid "update branches that point to commits that are being rebased"
 msgstr "brainsí a nuashonrú a thugann in iúl do ghealltanais atá á athbhunú"
 
-#: builtin/rebase.c
 msgid "add exec lines after each commit of the editable list"
 msgstr ""
 "línte exec a chur leis tar éis gach tiomantas den liosta in-eagarthóireachta"
 
-#: builtin/rebase.c
 msgid "allow rebasing commits with empty messages"
 msgstr "ligean do thiomantas a athbhunú le teachtaireachtaí folamh"
 
-#: builtin/rebase.c
 msgid "try to rebase merges instead of skipping them"
 msgstr "déan iarracht cumaisc a athbhunú in ionad iad a scipeáil"
 
-#: builtin/rebase.c
 msgid "use 'merge-base --fork-point' to refine upstream"
 msgstr "bain úsáid as 'merge-base --fork-point' chun suas an sruth a bheachtú"
 
-#: builtin/rebase.c
 msgid "use the given merge strategy"
 msgstr "bain úsáid as an straitéis cumaisc tugtha"
 
-#: builtin/rebase.c builtin/revert.c
 msgid "option"
 msgstr "rogha"
 
-#: builtin/rebase.c
 msgid "pass the argument through to the merge strategy"
 msgstr "an argóint a chur ar aghaidh chuig an straitéis cumaisc"
 
-#: builtin/rebase.c
 msgid "rebase all reachable commits up to the root(s)"
 msgstr ""
 "athbhunú gach gealltanas inrochtana suas go dtí an fhréamh/na fréamhacha"
 
-#: builtin/rebase.c
 msgid "automatically re-schedule any `exec` that fails"
 msgstr "athsceidealú go huathoibríoch aon `executaithe' a the"
 
-#: builtin/rebase.c
 msgid "apply all changes, even those already present upstream"
 msgstr "gach athrú a chur i bhfeidhm, fiú iad siúd atá i láthair suas an"
 
-#: builtin/rebase.c
 msgid "It looks like 'git am' is in progress. Cannot rebase."
 msgstr "Is cosúil go bhfuil 'git am' ar siúl. Ní féidir athbhunú."
 
-#: builtin/rebase.c
 msgid ""
 "`rebase --preserve-merges` (-p) is no longer supported.\n"
 "Use `git rebase --abort` to terminate current rebase.\n"
@@ -13352,7 +11297,6 @@
 "Úsáid `git rebase --abort` chun rebase reatha a fhoirceannadh.\n"
 "Nó íosghrádú go v2.33, nó níos luaithe, chun an athbhunú a chur i gcrích."
 
-#: builtin/rebase.c
 msgid ""
 "--preserve-merges was replaced by --rebase-merges\n"
 "Note: Your `pull.rebase` configuration may also be set to 'preserve',\n"
@@ -13362,20 +11306,16 @@
 "Nóta: Féadfar do chumraíocht `pull.rebase` a shocrú chun 'caomhnú' freisin,\n"
 "nach dtacaítear leis a thuilleadh; bain úsáid as 'cumaisc' ina ionad"
 
-#: builtin/rebase.c
 msgid "no rebase in progress"
 msgstr "níl aon athbhunú ar siúl"
 
-#: builtin/rebase.c
 msgid "The --edit-todo action can only be used during interactive rebase."
 msgstr ""
 "Ní féidir an gníomh --edit-todo a úsáid ach le linn athbhunú idirghníomhach."
 
-#: builtin/rebase.c
 msgid "Cannot read HEAD"
 msgstr "Ní féidir HEAD a léamh"
 
-#: builtin/rebase.c
 msgid ""
 "You must edit all merge conflicts and then\n"
 "mark them as resolved using git add"
@@ -13383,16 +11323,13 @@
 "Ní mór duit gach coinbhleacht cumaisc a chur in eagar agus ansin\n"
 "iad a mharcáil mar réitigh ag úsáid git add"
 
-#: builtin/rebase.c
 msgid "could not discard worktree changes"
 msgstr "ní fhéadfadh athruithe crann oibre a dhiúscairt"
 
-#: builtin/rebase.c
 #, c-format
 msgid "could not move back to %s"
 msgstr "ní fhéadfaí bogadh ar ais chuig %s"
 
-#: builtin/rebase.c
 #, c-format
 msgid ""
 "It seems that there is already a %s directory, and\n"
@@ -13413,11 +11350,9 @@
 "agus rith mé arís. Táim ag stopadh i gcás go bhfuil rud éigin agat fós\n"
 "luachmhar ansin.\n"
 
-#: builtin/rebase.c
 msgid "switch `C' expects a numerical value"
 msgstr "tá an lasc `C' ag súil le luach uimhriúil"
 
-#: builtin/rebase.c
 msgid ""
 "apply options are incompatible with rebase.rebaseMerges.  Consider adding --"
 "no-rebase-merges"
@@ -13425,7 +11360,6 @@
 "tá roghanna cur i bhfeidhm neamhoiriúnach le rebase.rebaseMerges. Smaoinigh "
 "ar --no-rebase-merges a chur leis"
 
-#: builtin/rebase.c
 msgid ""
 "apply options are incompatible with rebase.updateRefs.  Consider adding --no-"
 "update-refs"
@@ -13433,105 +11367,83 @@
 "tá roghanna cur i bhfeidhm neamhoiriúnach le rebase.updateRefs. Smaoinigh ar "
 "--no-update-refs a chur leis"
 
-#: builtin/rebase.c
 #, c-format
 msgid "Unknown rebase backend: %s"
 msgstr "Cúltaca athbhunaithe anaithnid: %s"
 
-#: builtin/rebase.c
 msgid "--reschedule-failed-exec requires --exec or --interactive"
 msgstr "Éilíonn --reschedule-failed-exec --exec nó --interactive"
 
-#: builtin/rebase.c
 #, c-format
 msgid "invalid upstream '%s'"
 msgstr "neamhbhailí suas sruth '%s'"
 
-#: builtin/rebase.c
 msgid "Could not create new root commit"
 msgstr "Ní fhéadfaí tiomantas fréimhe nua a chruthú"
 
-#: builtin/rebase.c
 #, c-format
 msgid "no such branch/commit '%s'"
 msgstr "gan aon bhrainse/tiomantas '%s' den sórt sin"
 
-#: builtin/rebase.c builtin/submodule--helper.c
 #, c-format
 msgid "No such ref: %s"
 msgstr "Níl aon tagairt den sórt sin: %s"
 
-#: builtin/rebase.c
 msgid "Could not resolve HEAD to a commit"
 msgstr "Ní fhéadfaí HEAD a réiteach le tiomantas"
 
-#: builtin/rebase.c
 #, c-format
 msgid "'%s': need exactly one merge base with branch"
 msgstr "'%s': teastaíonn bonn cumaisc amháin díreach le brainse"
 
-#: builtin/rebase.c
 #, c-format
 msgid "'%s': need exactly one merge base"
 msgstr "'%s': teastaíonn bonn cumaisc amháin díreach"
 
-#: builtin/rebase.c
 #, c-format
 msgid "Does not point to a valid commit '%s'"
 msgstr "Ní thugann sé in iúl do thiomantas bailí '%s'"
 
-#: builtin/rebase.c
 msgid "HEAD is up to date."
 msgstr "Tá HEAD cothrom le dáta."
 
-#: builtin/rebase.c
 #, c-format
 msgid "Current branch %s is up to date.\n"
 msgstr "Tá an brainse reatha %s cothrom le dáta.\n"
 
-#: builtin/rebase.c
 msgid "HEAD is up to date, rebase forced."
 msgstr "Tá HEAD cothrom le dáta, athbhunú éigeantach."
 
-#: builtin/rebase.c
 #, c-format
 msgid "Current branch %s is up to date, rebase forced.\n"
 msgstr "Tá an brainse reatha %s cothrom le dáta, athbhunú éigeantach.\n"
 
-#: builtin/rebase.c
 msgid "The pre-rebase hook refused to rebase."
 msgstr "Dhiúltaigh an crúca réamh-athbhunú a athbhunú."
 
-#: builtin/rebase.c
 #, c-format
 msgid "Changes to %s:\n"
 msgstr "Athruithe ar %s:\n"
 
-#: builtin/rebase.c
 #, c-format
 msgid "Changes from %s to %s:\n"
 msgstr "Athruithe ó %s go %s:\n"
 
-#: builtin/rebase.c
 #, c-format
 msgid "First, rewinding head to replay your work on top of it...\n"
 msgstr ""
 "Ar dtús, téann athfhillte chun do chuid oibre a athsheinm ar a bharr...\n"
 
-#: builtin/rebase.c
 msgid "Could not detach HEAD"
 msgstr "Ní fhéadfaí CEAD a dhícheangal"
 
-#: builtin/rebase.c
 #, c-format
 msgid "Fast-forwarded %s to %s.\n"
 msgstr "Cuireadh %s ar aghaidh go tapa chuig %s.\n"
 
-#: builtin/receive-pack.c
 msgid "git receive-pack <git-dir>"
 msgstr "git receive-pack <git-dir>"
 
-#: builtin/receive-pack.c
 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"
@@ -13565,7 +11477,6 @@
 "choinneáil fós, socraigh\n"
 "Athróg cumraíochta 'receive.denyCurrentBranch' go 'refuse'."
 
-#: builtin/receive-pack.c
 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"
@@ -13587,86 +11498,73 @@
 "\n"
 "Chun an teachtaireacht seo a ghearradh, is féidir leat é a shocrú go 'diúlt'."
 
-#: builtin/receive-pack.c
 msgid "quiet"
 msgstr "ciúin"
 
-#: builtin/receive-pack.c
 msgid "you must specify a directory"
 msgstr "ní mór duit eolaire a shonrú"
 
-#: builtin/reflog.c
 msgid "git reflog [show] [<log-options>] [<ref>]"
-msgstr "<ref>git reflog [taispeáin] [] [<log-options>]"
+msgstr "git reflog [show] [<log-options>] [<ref>]"
 
-#: builtin/reflog.c
 msgid "git reflog list"
-msgstr "git reflog liosta"
+msgstr "git reflog list"
 
-#: builtin/reflog.c
+msgid "git reflog exists <ref>"
+msgstr "git reflog exists <ref>"
+
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr "git reflog write <ref> <old-oid> <new-oid> <message>"
+
+msgid ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+msgstr ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+
+msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
+msgstr "git reflog drop [--all [--single-worktree] | <refs>...]"
+
 msgid ""
 "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
 "                  [--rewrite] [--updateref] [--stale-fix]\n"
 "                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
 "<refs>...]"
 msgstr ""
-"<time><time>git reflog in éag [--expire=] [--expire-unreachable=]\n"
-" [--athscríobh] [--updateref] [--stale-fix]\n"
-" <refs>[--dry-run | -n] [--verbose] [--all [--one-worktree] |...]"
+"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
+"<refs>...]"
 
-#: builtin/reflog.c
-msgid ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-msgstr ""
-"git reflog scrios [--athscríobh] [--updateref]\n"
-" <ref><specifier>[--driy-run | -n] [--verbose] @ {}..."
-
-#: builtin/reflog.c
-msgid "git reflog exists <ref>"
-msgstr "git reflog ann <ref>"
-
-#: builtin/reflog.c
-msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
-msgstr "<refs>git reflog titim [--all [--one-worktree] |...]"
-
-#: builtin/reflog.c
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "stampa ama neamhbhailí '%s' a thugtar do '--%s'"
 
-#: builtin/reflog.c sequencer.c
 #, c-format
 msgid "%s does not accept arguments: '%s'"
 msgstr "Ní ghlacann %s le hargóintí: '%s'"
 
-#: builtin/reflog.c
 msgid "do not actually prune any entries"
 msgstr "ná déan aon iontrálacha a ghearradh"
 
-#: builtin/reflog.c
 msgid ""
 "rewrite the old SHA1 with the new SHA1 of the entry that now precedes it"
 msgstr ""
 "athscríobh an sean-SHA1 leis an SHA1 nua den iontráil atá roimh ré anois"
 
-#: builtin/reflog.c
 msgid "update the reference to the value of the top reflog entry"
 msgstr "an tagairt do luach an iontráil reflog barr a nuashonrú"
 
-#: builtin/reflog.c
 msgid "print extra information on screen"
 msgstr "faisnéis bhreise a phriontáil ar an sc"
 
-#: builtin/reflog.c
 msgid "timestamp"
 msgstr "stampa ama"
 
-#: builtin/reflog.c
 msgid "prune entries older than the specified time"
 msgstr "iontrálacha brónta níos sine ná an t-am sonraithe"
 
-#: builtin/reflog.c
 msgid ""
 "prune entries older than <time> that are not reachable from the current tip "
 "of the branch"
@@ -13674,89 +11572,119 @@
 "ní féidir iontrálacha br <time>ónta níos sine ná sin a bhaint amach ó bharr "
 "reatha na brainse"
 
-#: builtin/reflog.c
 msgid "prune any reflog entries that point to broken commits"
 msgstr ""
 "aon iontrálacha reflog a ghearradh a chuireann in iúl do thiomantas briste"
 
-#: builtin/reflog.c
 msgid "process the reflogs of all references"
 msgstr "athfhillteacha na dtagairtí go léir a phróiseáil"
 
-#: builtin/reflog.c
 msgid "limits processing to reflogs from the current worktree only"
 msgstr ""
 "teorann sé leis an bpróiseáil do athfhillteacha ón gcrann oibre reatha amháin"
 
-#: builtin/reflog.c
 #, c-format
 msgid "Marking reachable objects..."
 msgstr "Rudaí inrochtana a mharcáil..."
 
-#: builtin/reflog.c
 #, c-format
 msgid "reflog could not be found: '%s'"
 msgstr "ní fhéadfaí reflog a fháil: '%s'"
 
-#: builtin/reflog.c
 msgid "no reflog specified to delete"
 msgstr "níl aon reflog sonraithe le scriosadh"
 
-#: builtin/reflog.c
 #, c-format
 msgid "invalid ref format: %s"
 msgstr "formáid tagartha neamhbhailí: %s"
 
-#: builtin/reflog.c
 msgid "drop the reflogs of all references"
 msgstr "scaoil athbhreithniú na dtagairtí go léir"
 
-#: builtin/reflog.c
 msgid "drop reflogs from the current worktree only"
 msgstr "scaoil reflogs ón gcrann oibre reatha amháin"
 
-#: builtin/reflog.c
 msgid "references specified along with --all"
 msgstr "tagairtí sonraithe in éineacht le --all"
 
-#: builtin/refs.c
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "ainm tagartha neamhbhailí: %s"
+
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "iD seanréada neamhbhailí: '%s'"
+
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "níl an seanréad '%s' ann"
+
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "iD réada nua neamhbhailí: '%s'"
+
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "níl an réad nua '%s' ann"
+
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr "ní féidir an t-idirbheart a thosú: %s"
+
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr "ní féidir nuashonrú athbhlagála a chur sa scuaine: %s"
+
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr "ní féidir nuashonrú athbhlagála a dhéanamh: %s"
+
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 
-#: builtin/refs.c
 msgid "git refs verify [--strict] [--verbose]"
-msgstr "fíoraíonn git refs [--strong] [--verbose]"
+msgstr "git refs verify [--strict] [--verbose]"
 
-#: builtin/refs.c
+msgid "git refs exists <ref>"
+msgstr "git refs exists <ref>"
+
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
 msgid "specify the reference format to convert to"
 msgstr "sonraigh an fhormáid tagartha le tiontú"
 
-#: builtin/refs.c
 msgid "perform a non-destructive dry-run"
 msgstr "rith tirim neamh-millteach a dhéanamh"
 
-#: builtin/refs.c
 msgid "drop reflogs entirely during the migration"
 msgstr "titim athfhóga go hiomlán le linn na himirce"
 
-#: builtin/refs.c
 msgid "missing --ref-format=<format>"
 msgstr "ar iarraidh --ref-format=<format>"
 
-#: builtin/refs.c
 #, c-format
 msgid "repository already uses '%s' format"
 msgstr "úsáideann stór formáid '%s' cheana féin"
 
-#: builtin/refs.c
 msgid "enable strict checking"
 msgstr "cumasú seiceáil docht"
 
-#: builtin/refs.c
 msgid "'git refs verify' takes no arguments"
 msgstr "Ní ghlacann 'git refs verify' aon argóintí"
 
-#: builtin/remote.c
+msgid "git refs list "
+msgstr "git refs list "
+
+msgid "'git refs exists' requires a reference"
+msgstr "Tá tagairt ag teastáil do 'git refs exists'"
+
+msgid "reference does not exist"
+msgstr "níl tagairt ann"
+
+msgid "failed to look up reference"
+msgstr "theip ort tagairt a lorg suas"
+
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
 "mirror=<fetch|push>] <name> <url>"
@@ -13764,87 +11692,67 @@
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
 "mirror=<fetch|push>] <name> <url>"
 
-#: builtin/remote.c
 msgid "git remote rename [--[no-]progress] <old> <new>"
 msgstr "git remote rename [--[no-]progress] <old> <new>"
 
-#: builtin/remote.c
 msgid "git remote remove <name>"
 msgstr "git remote remove <name>"
 
-#: builtin/remote.c
 msgid "git remote set-head <name> (-a | --auto | -d | --delete | <branch>)"
 msgstr "git remote set-head <name> (-a | --auto | -d | --delete | <branch>)"
 
-#: builtin/remote.c
 msgid "git remote [-v | --verbose] show [-n] <name>"
 msgstr "git remote [-v | --verbose] show [-n] <name>"
 
-#: builtin/remote.c
 msgid "git remote prune [-n | --dry-run] <name>"
 msgstr "git remote prune [-n | --dry-run] <name>"
 
-#: builtin/remote.c
 msgid ""
 "git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"
 msgstr ""
 "git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"
 
-#: builtin/remote.c
 msgid "git remote set-branches [--add] <name> <branch>..."
 msgstr "git remote set-branches [--add] <name> <branch>..."
 
-#: builtin/remote.c
 msgid "git remote get-url [--push] [--all] <name>"
 msgstr "git remote get-url [--push] [--all] <name>"
 
-#: builtin/remote.c
 msgid "git remote set-url [--push] <name> <newurl> [<oldurl>]"
 msgstr "git remote set-url [--push] <name> <newurl> [<oldurl>]"
 
-#: builtin/remote.c
 msgid "git remote set-url --add <name> <newurl>"
-msgstr "git iargúlta set-url --add <name><newurl>"
+msgstr "git remote set-url --add <name> <newurl>"
 
-#: builtin/remote.c
 msgid "git remote set-url --delete <name> <url>"
-msgstr "git iargúlta set-url --delete <name><url>"
+msgstr "git remote set-url --delete <name> <url>"
 
-#: builtin/remote.c
 msgid "git remote add [<options>] <name> <url>"
 msgstr "git remote add [<options>] <name> <url>"
 
-#: builtin/remote.c
 msgid "git remote set-branches <name> <branch>..."
 msgstr "git remote set-branches <name> <branch>..."
 
-#: builtin/remote.c
 msgid "git remote set-branches --add <name> <branch>..."
 msgstr "git remote set-branches --add <name> <branch>..."
 
-#: builtin/remote.c
 msgid "git remote show [<options>] <name>"
 msgstr "git remote show [<options>] <name>"
 
-#: builtin/remote.c
 msgid "git remote prune [<options>] <name>"
 msgstr "git remote prune [<options>] <name>"
 
-#: builtin/remote.c
 msgid "git remote update [<options>] [<group> | <remote>]..."
 msgstr "git remote update [<options>] [<group> | <remote>]..."
 
-#: builtin/remote.c
 #, c-format
 msgid "Updating %s"
 msgstr "Nuashonrú %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "Could not fetch %s"
 msgstr "Níorbh fhéidir %s a fháil"
 
-#: builtin/remote.c
 msgid ""
 "--mirror is dangerous and deprecated; please\n"
 "\t use --mirror=fetch or --mirror=push instead"
@@ -13852,16 +11760,21 @@
 "--mirror tá scáthán contúirteach agus míchuir; le do thoil\n"
 " bain úsáid as --mirror=fetch nó --mirror=push ina ionad"
 
-#: builtin/remote.c
 #, c-format
 msgid "unknown --mirror argument: %s"
 msgstr "argóint --mirror anaithnid: %s"
 
-#: builtin/remote.c
+#, c-format
+msgid "remote name '%s' is a subset of existing remote '%s'"
+msgstr "is fo-thacar den chianda '%s' atá ann cheana ainm '%s'"
+
+#, c-format
+msgid "remote name '%s' is a superset of existing remote '%s'"
+msgstr "is sár-thacar den chianda '%s' atá ann cheana é ainm an chianda '%s'"
+
 msgid "fetch the remote branches"
 msgstr "faigh na brainsí iargúlta"
 
-#: builtin/remote.c
 msgid ""
 "import all tags and associated objects when fetching\n"
 "or do not fetch any tag at all (--no-tags)"
@@ -13869,70 +11782,56 @@
 "iompórtáil gach clib agus rudaí gaolmhara agus tú ag tabhairt\n"
 "nó ná faigh aon chlib ar chor ar bith (--no-tags)"
 
-#: builtin/remote.c
 msgid "branch(es) to track"
 msgstr "brainse (í) chun rianú"
 
-#: builtin/remote.c
 msgid "master branch"
 msgstr "máistirbhrainse"
 
-#: builtin/remote.c
 msgid "set up remote as a mirror to push to or fetch from"
-msgstr "cuir iargúlta ar bun mar scáthán chun brú chuig nó a fháil uaidh"
+msgstr ""
+"socraigh an cianrialtán mar scáthán le brú chuig nó le hathshlánú uaidh"
 
-#: builtin/remote.c
 msgid "specifying a master branch makes no sense with --mirror"
 msgstr "níl aon chiall ar mháistirbhrainse a shonrú le --mirror"
 
-#: builtin/remote.c
 msgid "specifying branches to track makes sense only with fetch mirrors"
 msgstr "nííl ciall le brainsí a shonrú le rianú ach le scátháin faighte"
 
-#: builtin/remote.c
 #, c-format
 msgid "remote %s already exists."
 msgstr "iargúlta %s ann cheana féin."
 
-#: builtin/remote.c
 #, c-format
 msgid "Could not setup master '%s'"
 msgstr "Ní raibh an máistir '%s' a shocrú"
 
-#: builtin/remote.c trailer.c
 #, c-format
 msgid "more than one %s"
 msgstr "níos mó ná %s amháin"
 
-#: builtin/remote.c
 #, c-format
 msgid "unhandled branch.%s.rebase=%s; assuming 'true'"
 msgstr "brainse gan láimhseáil. %s.rebase=%s; ag glacadh leis 'fíor'"
 
-#: builtin/remote.c
 #, c-format
 msgid "Could not get fetch map for refspec %s"
 msgstr "Níorbh fhéidir léarscáil a fháil do refspec %s"
 
-#: builtin/remote.c
 msgid "(matching)"
 msgstr "(meaitseáil)"
 
-#: builtin/remote.c
 msgid "(delete)"
 msgstr "(scrios)"
 
-#: builtin/remote.c
 #, c-format
 msgid "could not set '%s'"
 msgstr "ní fhéadfaí '%s' a shocrú"
 
-#: builtin/remote.c config.c
 #, c-format
 msgid "could not unset '%s'"
 msgstr "ní fhéadfaí '%s' a dhíshocrú"
 
-#: builtin/remote.c
 #, c-format
 msgid ""
 "The %s configuration remote.pushDefault in:\n"
@@ -13943,17 +11842,39 @@
 " %s: %d\n"
 "ainmníonn anois an iargúlta nach bhfuil ann '%s'"
 
-#: builtin/remote.c
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+"Tá tagairtí contrártha sa\n"
+"tagarmharc sprice nua ag an gcianrialtán atá tú ag iarraidh a athainmniú. Is "
+"dóichí gur mar gheall ar iarracht a dhéanamh cianrialtán a neadú ann féin, "
+"e.g. trí 'tuismitheoir' a athainmniú go 'tuismitheoir/leanbh'\n"
+"nó trí chianrialtán a dhí-neadú, e.g. an bealach eile.\n"
+"\n"
+"Más amhlaidh atá, is féidir leat é seo a réiteach tríd an\n"
+"chianrialtán a athainmniú go hainm difriúil ar dtús.\n"
+
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "Níl aon iargúlta den sórt sin: '%s'"
 
-#: builtin/remote.c
 #, c-format
 msgid "Could not rename config section '%s' to '%s'"
 msgstr "Ní fhéadfaí an chuid cumraithe '%s' a athainmniú go '%s'"
 
-#: builtin/remote.c
+msgid "Renaming remote references"
+msgstr "Tagairtí cianda a athainmniú"
+
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr "theip ar athainmnithe tagartha iargúlta a chur i scuaine: %s"
+
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -13964,21 +11885,10 @@
 " %s\n"
 " Nuashonraigh an chumraíocht de láimh más gá."
 
-#: builtin/remote.c
-msgid "Renaming remote references"
-msgstr "Tagairtí cianda a athainmniú"
-
-#: builtin/remote.c
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "theip ar '%s' a scriosadh"
+msgid "renaming remote refs failed: %s"
+msgstr "theip ar athainmniú na dtagairtí iargúlta: %s"
 
-#: builtin/remote.c
-#, c-format
-msgid "creating '%s' failed"
-msgstr "theip ar chruthú '%s'"
-
-#: builtin/remote.c
 msgid ""
 "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
 "to delete it, use:"
@@ -13995,117 +11905,92 @@
 "Nóta: Níor baineadh roinnt brainsí lasmuigh den ordlathas refs/remotes/;\n"
 "chun iad a scriosadh, bain úsáid as:"
 
-#: builtin/remote.c
 #, c-format
 msgid "Could not remove config section '%s'"
 msgstr "Ní raibh an chuid cumraithe '%s' in ann a bhaint"
 
-#: builtin/remote.c
 #, c-format
 msgid " new (next fetch will store in remotes/%s)"
 msgstr " nua (stóráilfidh an chéad fhaighteacht eile i iargúlta/%s)"
 
-#: builtin/remote.c
 msgid " tracked"
 msgstr " rianaithe"
 
-#: builtin/remote.c
 msgid " skipped"
 msgstr " scipeáilte"
 
-#: builtin/remote.c
 msgid " stale (use 'git remote prune' to remove)"
 msgstr " seasta (bain úsáid as 'git remote prune' chun a bhaint)"
 
-#: builtin/remote.c
 msgid " ???"
 msgstr " ???"
 
-#: builtin/remote.c
 #, c-format
 msgid "invalid branch.%s.merge; cannot rebase onto > 1 branch"
-msgstr "brainse neamhbhailí. %s.merge; ní féidir athbhunú ar> 1 bhrainse"
+msgstr "brainse neamhbhailí. %s.merge; ní féidir athbhunú ar > 1 bhrainse"
 
-#: builtin/remote.c
 #, c-format
 msgid "rebases interactively onto remote %s"
 msgstr "athbhunú go hidirghníomhach ar iargúlta %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "rebases interactively (with merges) onto remote %s"
 msgstr "athbhunú idirghníomhach (le cumaisc) ar iargúlta %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "rebases onto remote %s"
 msgstr "athbhunú ar iargúlta %s"
 
-#: builtin/remote.c
 #, c-format
 msgid " merges with remote %s"
 msgstr " merges with remote %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "merges with remote %s"
 msgstr "cumasc le iargúlta %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "%-*s    and with remote %s\n"
 msgstr "%-*s    agus le iargúlta %s\n"
 
-#: builtin/remote.c
 msgid "create"
 msgstr "cruthú"
 
-#: builtin/remote.c
 msgid "delete"
 msgstr "scriosadh"
 
-#: builtin/remote.c
 msgid "up to date"
 msgstr "cothrom le dáta"
 
-#: builtin/remote.c
 msgid "fast-forwardable"
 msgstr "tapa a sheoladh"
 
-#: builtin/remote.c
 msgid "local out of date"
 msgstr "áitiúil as dáta"
 
-#: builtin/remote.c
 #, c-format
 msgid "    %-*s forces to %-*s (%s)"
 msgstr "    fórsaí %-*s go %-*s (%s)"
 
-#: builtin/remote.c
 #, c-format
 msgid "    %-*s pushes to %-*s (%s)"
 msgstr "    %-*s ag brú go %-*s (%s)"
 
-#: builtin/remote.c
 #, c-format
 msgid "    %-*s forces to %s"
 msgstr "    feidhmíonn %-*s chuig %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "    %-*s pushes to %s"
 msgstr "    %-*s ag brú chuig %s"
 
-#: builtin/remote.c
 msgid "do not query remotes"
 msgstr "ná fiosraigh iargúlta"
 
-#: builtin/remote.c
 #, c-format
 msgid "* remote %s"
 msgstr "* iargúlta %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "  Fetch URL: %s"
 msgstr " Faigh URL: %s"
@@ -14114,29 +11999,23 @@
 #. with the one in " Fetch URL: %s"
 #. translation.
 #.
-#: builtin/remote.c
 #, c-format
 msgid "  Push  URL: %s"
 msgstr "    Brúigh  URL: %s"
 
-#: builtin/remote.c
 msgid "(no URL)"
 msgstr "(gan URL)"
 
-#: builtin/remote.c
 #, c-format
 msgid "  HEAD branch: %s"
 msgstr "  Brainse CEANN: %s"
 
-#: builtin/remote.c
 msgid "(not queried)"
 msgstr "(gan iarraidh)"
 
-#: builtin/remote.c
 msgid "(unknown)"
 msgstr "(anaithnid)"
 
-#: builtin/remote.c
 #, c-format
 msgid ""
 "  HEAD branch (remote HEAD is ambiguous, may be one of the following):\n"
@@ -14144,7 +12023,6 @@
 "  Brainse HEAD (tá CEAD iargúlta débhríoch, d'fhéadfadh a bheith ar cheann "
 "de na nithe seo a leanas)\n"
 
-#: builtin/remote.c
 #, c-format
 msgid "  Remote branch:%s"
 msgid_plural "  Remote branches:%s"
@@ -14152,22 +12030,18 @@
 msgstr[1] "  Brainsí iargúlta:%s"
 msgstr[2] "  Brainsí iargúlta:%s"
 
-#: builtin/remote.c
 msgid " (status not queried)"
 msgstr " (níor fiosraíodh an stádas)"
 
-#: builtin/remote.c
 msgid "  Local branch configured for 'git pull':"
 msgid_plural "  Local branches configured for 'git pull':"
 msgstr[0] "  Brainse áitiúil cumraithe le haghaidh 'git pull':"
 msgstr[1] "  Craobhacha áitiúla cumraithe le haghaidh 'git pull':"
 msgstr[2] "  Craobhacha áitiúla cumraithe le haghaidh 'git pull':"
 
-#: builtin/remote.c
 msgid "  Local refs will be mirrored by 'git push'"
 msgstr " Déanfar tagairtí áitiúla a léiriú le 'git push'"
 
-#: builtin/remote.c
 #, c-format
 msgid "  Local ref configured for 'git push'%s:"
 msgid_plural "  Local refs configured for 'git push'%s:"
@@ -14175,27 +12049,22 @@
 msgstr[1] "  Tagairtí áitiúla cumraithe le haghaidh 'git push'%s:"
 msgstr[2] "  Tagairtí áitiúla cumraithe le haghaidh 'git push'%s:"
 
-#: builtin/remote.c
 #, c-format
 msgid "'%s/HEAD' is unchanged and points to '%s'\n"
 msgstr "Níl '%s/head' gan athrú agus díríonn sé chuig '%s'\n"
 
-#: builtin/remote.c
 #, c-format
 msgid "'%s/HEAD' has changed from '%s' and now points to '%s'\n"
 msgstr "Tá '%s/head' athraithe ó '%s' agus léiríonn sé anois chuig '%s'\n"
 
-#: builtin/remote.c
 #, c-format
 msgid "'%s/HEAD' is now created and points to '%s'\n"
 msgstr "Cruthaítear '%s/head' anois agus léiríonn sé chuig '%s'\n"
 
-#: builtin/remote.c
 #, c-format
 msgid "'%s/HEAD' was detached at '%s' and now points to '%s'\n"
 msgstr "Bhí '%s/head' scoite ag '%s' agus díríonn sé anois chuig '%s'\n"
 
-#: builtin/remote.c
 #, c-format
 msgid ""
 "'%s/HEAD' used to point to '%s' (which is not a remote branch), but now "
@@ -14204,139 +12073,101 @@
 "Úsáidtear '%s/head' chun díriú chuig '%s' (nach brainse iargúlta é), ach "
 "léiríonn sé anois chuig '%s'\n"
 
-#: builtin/remote.c
 msgid "set refs/remotes/<name>/HEAD according to remote"
 msgstr "socraigh refs/remotes/<name>/HEAD de réir an chianrialtáin"
 
-#: builtin/remote.c
 msgid "delete refs/remotes/<name>/HEAD"
 msgstr "scrios refs/remotes/<name>/HEAD"
 
-#: builtin/remote.c
 msgid "Cannot determine remote HEAD"
 msgstr "Ní féidir CEAD cianda a chinneadh"
 
-#: builtin/remote.c
 msgid "Multiple remote HEAD branches. Please choose one explicitly with:"
 msgstr ""
 "Brainsí iomadúla HEAD iargúlta. Roghnaigh ceann go sainráite le do thoil:"
 
-#: builtin/remote.c
 #, c-format
 msgid "Could not delete %s"
 msgstr "Ní fhéadfaí %s a scriosadh"
 
-#: builtin/remote.c
 #, c-format
 msgid "Not a valid ref: %s"
 msgstr "Ní tagairt bailí: %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "Could not set up %s"
 msgstr "Níor féidir %s a chur ar bun"
 
-#: builtin/remote.c
-#, c-format
-msgid " %s will become dangling!"
-msgstr " Beidh %s ag crochadh!"
-
-#: builtin/remote.c
-#, c-format
-msgid " %s has become dangling!"
-msgstr " tá %s ag crochadh!"
-
-#: builtin/remote.c
 #, c-format
 msgid "Pruning %s"
 msgstr "Bearradh %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "URL: %s"
 msgstr "URL: %s"
 
-#: builtin/remote.c
 #, c-format
 msgid " * [would prune] %s"
 msgstr " * [bhearna] %s"
 
-#: builtin/remote.c
 #, c-format
 msgid " * [pruned] %s"
 msgstr " * [gearrtha] %s"
 
-#: builtin/remote.c
 msgid "prune remotes after fetching"
 msgstr "iomadáin brónta tar éis a fháil"
 
-#: builtin/remote.c
 #, c-format
 msgid "No such remote '%s'"
 msgstr "Níl aon iargúlta '%s' den sórt sin"
 
-#: builtin/remote.c
 msgid "add branch"
 msgstr "cuir brainse"
 
-#: builtin/remote.c
 msgid "no remote specified"
 msgstr "gan aon iargúlta sonraithe"
 
-#: builtin/remote.c
 msgid "query push URLs rather than fetch URLs"
 msgstr "cuir fiosrúcháin ar URLanna brú seachas URLanna aisghabhála"
 
-#: builtin/remote.c
 msgid "return all URLs"
 msgstr "gach URL a thabhairt ar ais"
 
-#: builtin/remote.c
 msgid "manipulate push URLs"
 msgstr "ionramháil URLanna bhrú"
 
-#: builtin/remote.c
 msgid "add URL"
 msgstr "cuir URL leis"
 
-#: builtin/remote.c
 msgid "delete URLs"
 msgstr "scrios URLanna"
 
-#: builtin/remote.c
 msgid "--add --delete doesn't make sense"
 msgstr "Níl ciall ag --add --delete"
 
-#: builtin/remote.c
 #, c-format
 msgid "Invalid old URL pattern: %s"
 msgstr "Sean-phatrún URL neamhbhailí: %s"
 
-#: builtin/remote.c
 #, c-format
 msgid "No such URL found: %s"
 msgstr "Níor aimsíodh aon URL den sórt sin: %s"
 
-#: builtin/remote.c
 msgid "Will not delete all non-push URLs"
 msgstr "Ní scriosfaidh sé gach URL neamh-bhrú"
 
-#: builtin/remote.c
 msgid "be verbose; must be placed before a subcommand"
 msgstr "a bheith inearálta; caithfear é a chur os comhair fo-ordú"
 
-#: builtin/repack.c
 msgid ""
 "git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n"
 "[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n"
-"[--write-midx] [--name-hash-version=<n>]"
+"[--write-midx] [--name-hash-version=<n>] [--path-walk]"
 msgstr ""
-"git athphacáil [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n"
-"<n><pack-name>[--fuinneog =] [-- <n>depth=] [--threads=] [--keep- <n>pack "
-"=]\n"
-"<n>[--write-midx] [--ainm-hash-leagan =]"
+"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n"
+"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n"
+"[--write-midx] [--name-hash-version=<n>] [--path-walk]"
 
-#: builtin/repack.c
 msgid ""
 "Incremental repacks are incompatible with bitmap indexes.  Use\n"
 "--no-write-bitmap-index or disable the pack.writeBitmaps configuration."
@@ -14344,222 +12175,121 @@
 "Níl ath-phacáistí incréideacha comhoiriúnach le hinnéacsanna bitmap. Úsáid\n"
 "--no-write-bitmap-index nó díchumraíocht an pack.writeBitmaps a dhíchumasú."
 
-#: builtin/repack.c
-msgid "could not start pack-objects to repack promisor objects"
-msgstr "ní fhéadfaí rudaí pacáiste a thosú chun rudaí gealltanna a athphacáil"
-
-#: builtin/repack.c
-msgid "failed to feed promisor objects to pack-objects"
-msgstr "theip ar rudaí gealltanna a bheathú ar rudaí pacáiste"
-
-#: builtin/repack.c
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr ""
-"athphacáil: Ag súil le línte aitheantais réad heicseach iomlána ach ó "
-"phacáistí."
-
-#: builtin/repack.c
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr ""
-"ní fhéadfadh sé rudaí pacáiste a chríochnú chun rudaí geallta a athphacáil"
-
-#: builtin/repack.c
-#, c-format
-msgid "cannot open index for %s"
-msgstr "ní féidir innéacs a oscailt do %s"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr "pacáiste %s ró-mhór le breithniú i ddul chun cinn geo"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "pacáiste %s ró-mhór le rolladh suas"
-
-#: builtin/repack.c
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "ní fhéadfaí teachtaireacht %s a oscailt le haghaidh scríobh"
-
-#: builtin/repack.c
-msgid "could not close refs snapshot tempfile"
-msgstr "ní raibh in ann tempfile snapshot refs a dhúnadh"
-
-#: builtin/repack.c
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "ní fhéadfaí bitmap seasta a bhaint: %s"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "ní thosaíonn réimír pacáiste %s le objdir %s"
-
-#: builtin/repack.c
 msgid "pack everything in a single pack"
 msgstr "pacáil gach rud i bpacáiste amháin"
 
-#: builtin/repack.c
 msgid "same as -a, and turn unreachable objects loose"
 msgstr ""
 "mar an gcéanna le -a, agus casadh rudaí nach féidir inrochtana scaoilte"
 
-#: builtin/repack.c
 msgid "same as -a, pack unreachable cruft objects separately"
 msgstr "mar an gcéanna le -a, pacáil rudaí cruft neamh-inrochtana ar leithligh"
 
-#: builtin/repack.c
 msgid "approxidate"
 msgstr "approxidate"
 
-#: builtin/repack.c
 msgid "with --cruft, expire objects older than this"
 msgstr "le --cruft, rachadh in éag rudaí níos sine ná seo"
 
-#: builtin/repack.c
 msgid "with --cruft, only repack cruft packs smaller than this"
 msgstr "le --cruft, ní athphacáil ach pacáistí cruft níos lú ná seo"
 
-#: builtin/repack.c
 msgid "remove redundant packs, and run git-prune-packed"
 msgstr "bain pacáistí iomarcacha, agus rith git-prune-packed"
 
-#: builtin/repack.c
 msgid "pass --no-reuse-delta to git-pack-objects"
 msgstr "pas --no-reuse-delta chuig git-pack-objects"
 
-#: builtin/repack.c
 msgid "pass --no-reuse-object to git-pack-objects"
 msgstr "pas --no-reuse-object chuig git-pack-objects"
 
-#: builtin/repack.c
 msgid ""
 "specify the name hash version to use for grouping similar objects by path"
 msgstr ""
 "sonraigh an leagan hash ainm atá le húsáid chun rudaí den chineál céanna a "
 "ghrúpáil"
 
-#: builtin/repack.c
+msgid "pass --path-walk to git-pack-objects"
+msgstr "pas --path-walk chuig git-pack-objects"
+
 msgid "do not run git-update-server-info"
 msgstr "ná reáchtáil git-update-server-info"
 
-#: builtin/repack.c
 msgid "pass --local to git-pack-objects"
 msgstr "pas --local go git-pack-objects"
 
-#: builtin/repack.c
 msgid "write bitmap index"
 msgstr "scríobh innéacs bitmap"
 
-#: builtin/repack.c
 msgid "pass --delta-islands to git-pack-objects"
 msgstr "pas --delta-islands chuig git-pack-objects"
 
-#: builtin/repack.c
 msgid "with -A, do not loosen objects older than this"
 msgstr "le -A, ná scaoil rudaí níos sine ná seo"
 
-#: builtin/repack.c
 msgid "with -a, repack unreachable objects"
 msgstr "le -a, athphacáil rudaí neamh-inrochtana"
 
-#: builtin/repack.c
 msgid "size of the window used for delta compression"
 msgstr "méid na fuinneoga a úsáidtear le haghaidh comhbhrú delta"
 
-#: builtin/repack.c
 msgid "bytes"
-msgstr "beart"
+msgstr "bearta"
 
-#: builtin/repack.c
 msgid "same as the above, but limit memory size instead of entries count"
 msgstr ""
 "mar an gcéanna leis an méid thuas, ach teorainn le méid cuimhne in ionad "
 "iontrálacha"
 
-#: builtin/repack.c
 msgid "limits the maximum delta depth"
 msgstr "teorann sé leis an doimhneacht delta uasta"
 
-#: builtin/repack.c
 msgid "limits the maximum number of threads"
 msgstr "teorainn leis an líon uasta na snáitheanna"
 
-#: builtin/repack.c
 msgid "maximum size of each packfile"
 msgstr "uasmhéid gach pacáiste"
 
-#: builtin/repack.c
 msgid "repack objects in packs marked with .keep"
 msgstr "athphacáil rudaí i bpacáistí atá marcáilte le .keep"
 
-#: builtin/repack.c
 msgid "do not repack this pack"
 msgstr "ná déan an pacáiste seo a athphacáil"
 
-#: builtin/repack.c
 msgid "find a geometric progression with factor <N>"
 msgstr "faigh dul chun cinn geoiméadrach le fachtóir <N>"
 
-#: builtin/repack.c
 msgid "write a multi-pack index of the resulting packs"
 msgstr "scríobh innéacs il-phacáiste de na pacáistí mar thoradh air"
 
-#: builtin/repack.c
 msgid "pack prefix to store a pack containing filtered out objects"
 msgstr "réimír pacáiste chun pacáiste ina bhfuil rudaí scagtha amach a stóráil"
 
-#: builtin/repack.c
 msgid "cannot delete packs in a precious-objects repo"
 msgstr "ní féidir pacáistí a scriosadh i repo rudaí luachmhara"
 
-#: builtin/repack.c
 #, c-format
 msgid "option '%s' can only be used along with '%s'"
 msgstr "ní féidir rogha '%s' a úsáid ach amháin in éineacht le '%s'"
 
-#: builtin/repack.c
 msgid "Nothing new to pack."
 msgstr "Níl aon rud nua le pacáil."
 
-#: builtin/repack.c
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "theip ar phacáiste a athainmniú go '%s'"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "níor scríobh pack-objects comhad '%s' do phacáiste %s-%s"
-
-#: builtin/repack.c sequencer.c
-#, c-format
-msgid "could not unlink: %s"
-msgstr "ní fhéadfaí dícheangal: %s"
-
-#: builtin/replace.c
 msgid "git replace [-f] <object> <replacement>"
-msgstr "git athsholáthair [-f] <object><replacement>"
+msgstr "git replace [-f] <object> <replacement>"
 
-#: builtin/replace.c
 msgid "git replace [-f] --edit <object>"
-msgstr "git athsholáthair [-f] --edit <object>"
+msgstr "git replace [-f] --edit <object>"
 
-#: builtin/replace.c
 msgid "git replace [-f] --graft <commit> [<parent>...]"
-msgstr "<commit><parent>git athsholáthair [-f] --graft [...]"
+msgstr "git replace [-f] --graft <commit> [<parent>...]"
 
-#: builtin/replace.c
 msgid "git replace -d <object>..."
-msgstr "<object>git athsholáthair -d..."
+msgstr "git replace -d <object>..."
 
-#: builtin/replace.c
 msgid "git replace [--format=<format>] [-l [<pattern>]]"
-msgstr "<pattern>git in ionad [--format =<format>] [-l []]"
+msgstr "git replace [--format=<format>] [-l [<pattern>]]"
 
-#: builtin/replace.c
 #, c-format
 msgid ""
 "invalid replace format '%s'\n"
@@ -14568,27 +12298,22 @@
 "formáid athsholáthair neamhbhailí '%s'\n"
 "is iad formáidí bailí ná 'gearr', 'meánach' agus 'fada'"
 
-#: builtin/replace.c
 #, c-format
 msgid "replace ref '%s' not found"
 msgstr "athsholáthair nach bhfuarthas tagairt '%s'"
 
-#: builtin/replace.c
 #, c-format
 msgid "Deleted replace ref '%s'"
 msgstr "Scriosta in ionad tagairt '%s'"
 
-#: builtin/replace.c
 #, c-format
 msgid "'%s' is not a valid ref name"
 msgstr "Ní ainm tagartha bailí é '%s'"
 
-#: builtin/replace.c
 #, c-format
 msgid "replace ref '%s' already exists"
 msgstr "athsholáthar tagairt '%s' atá ann cheana féin"
 
-#: builtin/replace.c
 #, c-format
 msgid ""
 "Objects must be of the same type.\n"
@@ -14599,108 +12324,86 @@
 "Tugann '%s' in iúl do réad athsholáthair de chineál '%s'\n"
 "agus díríonn '%s' ar réad athsholáthair de chineál '%s'."
 
-#: builtin/replace.c
 #, c-format
 msgid "unable to open %s for writing"
-msgstr "nach féidir %s a oscailt le haghaidh scríobh"
+msgstr "ní féidir %s a oscailt le haghaidh scríbhneoireachta"
 
-#: builtin/replace.c
 msgid "cat-file reported failure"
 msgstr "teip tuairiscithe ar chomhad cat"
 
-#: builtin/replace.c
 #, c-format
 msgid "unable to open %s for reading"
-msgstr "nach féidir %s a oscailt le haghaidh léamh"
+msgstr "ní féidir %s a oscailt le haghaidh léitheoireachta"
 
-#: builtin/replace.c
 msgid "unable to spawn mktree"
-msgstr "in ann mktree a shannadh"
+msgstr "ní féidir mktree a sceitheadh"
 
-#: builtin/replace.c
 msgid "unable to read from mktree"
-msgstr "in ann léamh ó mktree"
+msgstr "ní féidir léamh ó mktree"
 
-#: builtin/replace.c
 msgid "mktree reported failure"
 msgstr "thuairiscigh mktree teip"
 
-#: builtin/replace.c
 msgid "mktree did not return an object name"
 msgstr "níor thug mktree ainm réad ar ais"
 
-#: builtin/replace.c
 #, c-format
 msgid "unable to fstat %s"
 msgstr "ní féidir le fstat %s"
 
-#: builtin/replace.c
 msgid "unable to write object to database"
-msgstr "in ann réad a scríobh chuig bunachar sonraí"
+msgstr "ní féidir réad a scríobh chuig bunachar sonraí"
 
-#: builtin/replace.c
 #, c-format
 msgid "unable to get object type for %s"
-msgstr "nach féidir cineál réad a fháil do %s"
+msgstr "ní féidir cineál réada a fháil do %s"
 
-#: builtin/replace.c
 msgid "editing object file failed"
 msgstr "theip ar eagarthóireacht ar chomhad"
 
-#: builtin/replace.c
 #, c-format
 msgid "new object is the same as the old one: '%s'"
 msgstr "tá réad nua mar an gcéanna leis an sean-réad: '%s'"
 
-#: builtin/replace.c
 #, c-format
 msgid "could not parse %s as a commit"
 msgstr "ní fhéadfaí %s a pharsáil mar thiomantas"
 
-#: builtin/replace.c
 #, c-format
 msgid "bad mergetag in commit '%s'"
 msgstr "cliciú neamhchuspóir i gcomhad '%s'"
 
-#: builtin/replace.c
 #, c-format
 msgid "malformed mergetag in commit '%s'"
 msgstr "comharthaí mífhoirmithe i dtiomantas '%s'"
 
-#: builtin/replace.c
 #, c-format
 msgid ""
 "original commit '%s' contains mergetag '%s' that is discarded; use --edit "
 "instead of --graft"
 msgstr ""
-"tá mergetag '%s' a dhíscaoiltear as '%s' bunaidh; bain úsáid as --edit in "
-"ionad --graft"
+"tá an chlib chumasc '%s' sa tiomnú bunaidh '%s' atá caite amach; bain úsáid "
+"as --edit in ionad --graft"
 
-#: builtin/replace.c
 #, c-format
 msgid "the original commit '%s' has a gpg signature"
 msgstr "tá síniú gpg ag an tiomantas bunaidh '%s'"
 
-#: builtin/replace.c
 msgid "the signature will be removed in the replacement commit!"
 msgstr "bainfear an síniú sa tiomantas athsholáthair!"
 
-#: builtin/replace.c
 #, c-format
 msgid "could not write replacement commit for: '%s'"
 msgstr "ní fhéadfaí gealltanas athsholáthair a scríobh do: '%s'"
 
-#: builtin/replace.c
 #, c-format
 msgid "graft for '%s' unnecessary"
 msgstr "graft le haghaidh '%s' gan ghá"
 
-#: builtin/replace.c
 #, c-format
 msgid "new commit is the same as the old one: '%s'"
 msgstr "tá tiomantas nua mar an gcéanna leis an seancheann: '%s'"
 
-#: builtin/replace.c
 #, c-format
 msgid ""
 "could not convert the following graft(s):\n"
@@ -14709,87 +12412,66 @@
 "ní raibh sé in ann an graft (í) seo a leanas a thiontú:\n"
 "%s"
 
-#: builtin/replace.c
 msgid "list replace refs"
 msgstr "liosta athsholáthair refs"
 
-#: builtin/replace.c
 msgid "delete replace refs"
 msgstr "scrios athsholáthair refs"
 
-#: builtin/replace.c
 msgid "edit existing object"
 msgstr "réad atá ann cheana in eagar"
 
-#: builtin/replace.c
 msgid "change a commit's parents"
 msgstr "tuismitheoirí tiomanta a athrú"
 
-#: builtin/replace.c
 msgid "convert existing graft file"
 msgstr "tiontaigh an comhad graft atá ann cheana"
 
-#: builtin/replace.c
 msgid "replace the ref if it exists"
 msgstr "athsholáthar an tagartha má tá sé ann"
 
-#: builtin/replace.c
 msgid "do not pretty-print contents for --edit"
 msgstr "ná déan ábhar álainn a phriontáil le haghaidh --edit"
 
-#: builtin/replace.c
 msgid "use this format"
 msgstr "bain úsáid as an bhformáid seo"
 
-#: builtin/replace.c
 msgid "--format cannot be used when not listing"
 msgstr "Ní féidir --format a úsáid nuair nach bhfuil sé liostaithe"
 
-#: builtin/replace.c
 msgid "-f only makes sense when writing a replacement"
 msgstr "Ní dhéanann -f ciall ach nuair a bhíonn athsholáthar á scríobh"
 
-#: builtin/replace.c
 msgid "--raw only makes sense with --edit"
 msgstr "Ní dhéanann --raw ciall ach le --edit"
 
-#: builtin/replace.c
 msgid "-d needs at least one argument"
 msgstr "-d teastaíonn argóint amháin ar a laghad"
 
-#: builtin/replace.c
 msgid "bad number of arguments"
 msgstr "droch-líon na n-argóintí"
 
-#: builtin/replace.c
 msgid "-e needs exactly one argument"
 msgstr "Teastaíonn argóint amháin díreach ó -e"
 
-#: builtin/replace.c
 msgid "-g needs at least one argument"
 msgstr "Teastaíonn argóint amháin ar a laghad ó -g"
 
-#: builtin/replace.c
 msgid "--convert-graft-file takes no argument"
 msgstr "Ní ghlacann --convert-graft-file aon argóint"
 
-#: builtin/replace.c
 msgid "only one pattern can be given with -l"
 msgstr "ní féidir ach patrún amháin a thabhairt le -l"
 
-#: builtin/replay.c
 msgid "need some commits to replay"
 msgstr "teastaíonn roinnt gealltanais chun athsheinm"
 
-#: builtin/replay.c
 msgid "all positive revisions given must be references"
 msgstr "caithfidh gach athbhreithniú dearfach a thugtar a bheith ina"
 
-#: builtin/replay.c
 msgid "argument to --advance must be a reference"
 msgstr "caithfidh argóint chuig --advance a bheith ina thagairt"
 
-#: builtin/replay.c
 msgid ""
 "cannot advance target with multiple sources because ordering would be ill-"
 "defined"
@@ -14797,13 +12479,11 @@
 "ní féidir leis an sprioc a chur chun cinn le foinsí iolracha toisc go mbeadh "
 "ordú"
 
-#: builtin/replay.c
 msgid ""
 "cannot implicitly determine whether this is an --advance or --onto operation"
 msgstr ""
 "ní féidir a chinneadh go hinneach an oibríocht --advance nó --onto é seo"
 
-#: builtin/replay.c
 msgid ""
 "cannot advance target with multiple source branches because ordering would "
 "be ill-defined"
@@ -14811,11 +12491,9 @@
 "ní féidir leis an sprioc a chur chun cinn le brainsí foinse iolracha mar go "
 "mbeadh ordú"
 
-#: builtin/replay.c
 msgid "cannot implicitly determine correct base for --onto"
 msgstr "ní féidir leis an mbonn ceart do --onto a chinneadh go hinneach"
 
-#: builtin/replay.c
 msgid ""
 "(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
 "<branch>) <revision-range>..."
@@ -14823,23 +12501,18 @@
 "(TURGNAMHACH!) git replay ([--contained] --onto <newbase> | --advance "
 "<branch>) <revision-range>..."
 
-#: builtin/replay.c
 msgid "make replay advance given branch"
 msgstr "athsheoladh a dhéanamh roimh ré brainse ar leith"
 
-#: builtin/replay.c
 msgid "replay onto given commit"
 msgstr "athsheoladh ar thiomantas a thugtar"
 
-#: builtin/replay.c
 msgid "advance all branches contained in revision-range"
 msgstr "gach brainse atá sa raon athbhreithnithe a chur chun cinn"
 
-#: builtin/replay.c
 msgid "option --onto or --advance is mandatory"
 msgstr "tá rogha --onto nó --advance éigeantach"
 
-#: builtin/replay.c
 #, c-format
 msgid ""
 "some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
@@ -14848,160 +12521,181 @@
 "cuirfear roinnt roghanna siúil rev a athshealbhú mar go gcuirfear giotán "
 "'%s' i 'struct rev_info' iallach"
 
-#: builtin/replay.c
 msgid "error preparing revisions"
 msgstr "earráid ag ullmhú athbhreith"
 
-#: builtin/replay.c
 msgid "replaying down to root commit is not supported yet!"
 msgstr "ní thacaítear le athsheinm síos go dtí tiomantas fréimhe fós!"
 
-#: builtin/replay.c
 msgid "replaying merge commits is not supported yet!"
 msgstr "ní thacaítear le gealltanna cumaisc athsheinm fós!"
 
-#: builtin/rerere.c
+#, c-format
+msgid "key '%s' not found"
+msgstr "níor aimsíodh an eochair '%s'"
+
+#, c-format
+msgid "invalid format '%s'"
+msgstr "formáid neamhbhailí '%s'"
+
+msgid "output format"
+msgstr "formáid aschuir"
+
+msgid "synonym for --format=nul"
+msgstr "comhchiallach le --format=nul"
+
+msgid "unsupported output format"
+msgstr "formáid aschuir neamhthacaithe"
+
+msgid "References"
+msgstr "Tagairtí"
+
+msgid "Count"
+msgstr "Comhair"
+
+msgid "Branches"
+msgstr "Brainsí"
+
+msgid "Tags"
+msgstr "Clibeanna"
+
+msgid "Remotes"
+msgstr "Cianrialtáin"
+
+msgid "Others"
+msgstr "Daoine eile"
+
+msgid "Reachable objects"
+msgstr "Réada inrochtana"
+
+msgid "Commits"
+msgstr "Tiomantas"
+
+msgid "Trees"
+msgstr "Crainn"
+
+msgid "Blobs"
+msgstr "Blobaí"
+
+msgid "Repository structure"
+msgstr "Struchtúr an stórais"
+
+msgid "Value"
+msgstr "Luach"
+
+msgid "Counting references"
+msgstr "Tagairtí a chomhaireamh"
+
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
 msgstr ""
-"git rerere [glan | déan dearmad<pathspec>... | diff | stádas | fágtha | gc]"
+"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
 
-#: builtin/rerere.c
 msgid "register clean resolutions in index"
 msgstr "rúin glan a chlárú san innéacs"
 
-#: builtin/rerere.c
 msgid "'git rerere forget' without paths is deprecated"
 msgstr "Tá 'git rerere dearmad' gan cosáin scothaithe"
 
-#: builtin/rerere.c
 #, c-format
 msgid "unable to generate diff for '%s'"
-msgstr "nach féidir éagsúlacht a ghiniúint do '%s'"
+msgstr "ní féidir difríocht a ghiniúint do '%s'"
 
-#: builtin/reset.c
 msgid ""
 "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
 msgstr ""
 "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
 
-#: builtin/reset.c
 msgid "git reset [-q] [<tree-ish>] [--] <pathspec>..."
 msgstr "git reset [-q] [<tree-ish>] [--] <pathspec>..."
 
-#: builtin/reset.c
 msgid ""
 "git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"
 msgstr ""
 "git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"
 
-#: builtin/reset.c
 msgid "git reset --patch [<tree-ish>] [--] [<pathspec>...]"
 msgstr "git reset --patch [<tree-ish>] [--] [<pathspec>...]"
 
-#: builtin/reset.c
 msgid "mixed"
 msgstr "measctha"
 
-#: builtin/reset.c
 msgid "soft"
 msgstr "bog"
 
-#: builtin/reset.c
 msgid "hard"
 msgstr "crua"
 
-#: builtin/reset.c
 msgid "merge"
 msgstr "cumaisc"
 
-#: builtin/reset.c
 msgid "keep"
 msgstr "coinnigh"
 
-#: builtin/reset.c
 msgid "You do not have a valid HEAD."
 msgstr "Níl CEANN bailí agat."
 
-#: builtin/reset.c
 msgid "Failed to find tree of HEAD."
 msgstr "Theip ar chrann HEAD a aimsiú."
 
-#: builtin/reset.c
 #, c-format
 msgid "Failed to find tree of %s."
 msgstr "Theip ar chrann %s a aimsiú."
 
-#: builtin/reset.c
 #, c-format
 msgid "HEAD is now at %s"
 msgstr "Tá HEAD anois ag %s"
 
-#: builtin/reset.c
 #, c-format
 msgid "Cannot do a %s reset in the middle of a merge."
 msgstr "Ní féidir athshocrú %s a dhéanamh i lár cumaisc."
 
-#: builtin/reset.c builtin/stash.c
 msgid "be quiet, only report errors"
 msgstr "bí ciúin, ní thuairiscigh ach earráidí"
 
-#: builtin/reset.c
 msgid "skip refreshing the index after reset"
 msgstr "scipeáil an t-innéacs a athnuachan tar éis"
 
-#: builtin/reset.c
 msgid "reset HEAD and index"
 msgstr "athshocraigh HEAD agus innéacs"
 
-#: builtin/reset.c
 msgid "reset only HEAD"
 msgstr "athshocraigh CEAD amháin"
 
-#: builtin/reset.c
 msgid "reset HEAD, index and working tree"
 msgstr "athshocraigh HEAD, innéacs agus crann oibre"
 
-#: builtin/reset.c
 msgid "reset HEAD but keep local changes"
 msgstr "athshocraigh HEAD ach coinnigh athruithe áiti"
 
-#: builtin/reset.c
 msgid "record only the fact that removed paths will be added later"
 msgstr ""
 "ní thaifeadadh ach an fíric go gcuirfear cosáin bainte leis níos déanaí"
 
-#: builtin/reset.c
 #, c-format
 msgid "Failed to resolve '%s' as a valid revision."
 msgstr "Theip ar '%s' a réiteach mar athbhreithniú bailí."
 
-#: builtin/reset.c
 #, c-format
 msgid "Failed to resolve '%s' as a valid tree."
 msgstr "Theip ar '%s' a réiteach mar chrann bailí."
 
-#: builtin/reset.c
 msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
 msgstr ""
 "--mixed le cosáin imithe i léig; bain úsáid as 'git reset -- <cosáin>' ina "
 "ionad."
 
-#: builtin/reset.c
 #, c-format
 msgid "Cannot do %s reset with paths."
 msgstr "Ní féidir %s a athshocrú le cosáin."
 
-#: builtin/reset.c
 #, c-format
 msgid "%s reset is not allowed in a bare repository"
 msgstr "Ní cheadaítear athshocrú %s i stóras lom"
 
-#: builtin/reset.c
 msgid "Unstaged changes after reset:"
 msgstr "Athruithe gan stáitse tar éis athshocrú:"
 
-#: builtin/reset.c
 #, c-format
 msgid ""
 "It took %.2f seconds to refresh the index after reset.  You can use\n"
@@ -15011,71 +12705,55 @@
 "leat úsáid a bhaint as\n"
 "'--no-refresh' chun é seo a sheachaint."
 
-#: builtin/reset.c
 #, c-format
 msgid "Could not reset index file to revision '%s'."
 msgstr "Ní fhéadfaí comhad innéacs a athshocrú chun athbhreithniú '%s'."
 
-#: builtin/reset.c
 msgid "Could not write new index file."
 msgstr "Ní fhéadfaí comhad innéacs nua a scríobh."
 
-#: builtin/rev-list.c
 #, c-format
 msgid "unable to get disk usage of %s"
-msgstr "nach féidir úsáid diosca de %s a fháil"
+msgstr "ní féidir úsáid diosca %s a fháil"
 
-#: builtin/rev-list.c
 #, c-format
 msgid "invalid value for '%s': '%s', the only allowed format is '%s'"
 msgstr "luach neamhbhailí do '%s': '%s', is é '%s' an t-aon fhormáid ceadaithe"
 
-#: builtin/rev-list.c
 msgid "-z option used with unsupported option"
 msgstr "-z rogha a úsáidtear le rogha gan tacaíocht"
 
-#: builtin/rev-list.c
 msgid "rev-list does not support display of notes"
 msgstr "ní thacaíonn rev-list le taispeáint nótaí"
 
-#: builtin/rev-list.c
 #, c-format
 msgid "marked counting and '%s' cannot be used together"
 msgstr "comhaireamh marcáilte agus ní féidir '%s' a úsáid le chéile"
 
-#: builtin/rev-parse.c
 msgid "git rev-parse --parseopt [<options>] -- [<args>...]"
 msgstr "git rev-parse --parseopt [<options>] -- [<args>...]"
 
-#: builtin/rev-parse.c
 msgid "keep the `--` passed as an arg"
 msgstr "coinnigh an `--` a rith mar arg"
 
-#: builtin/rev-parse.c
 msgid "stop parsing after the first non-option argument"
 msgstr "stop a pháirseáil tar éis an chéad argóint neamh-rogha"
 
-#: builtin/rev-parse.c
 msgid "output in stuck long form"
 msgstr "aschur i bhfoirm fhada greamaithe"
 
-#: builtin/rev-parse.c
 msgid "premature end of input"
 msgstr "deireadh roimh ré an ionchuir"
 
-#: builtin/rev-parse.c
 msgid "no usage string given before the `--' separator"
 msgstr "gan aon teaghrán úsáide a thugtar roimh an deighilteoir `--'"
 
-#: builtin/rev-parse.c
 msgid "missing opt-spec before option flags"
 msgstr "sonraíocht rogha in easnamh roimh bhratacha roghanna"
 
-#: builtin/rev-parse.c
 msgid "Needed a single revision"
 msgstr "Teastaíonn athbhreithniú amháin"
 
-#: builtin/rev-parse.c
 msgid ""
 "git rev-parse --parseopt [<options>] -- [<args>...]\n"
 "   or: git rev-parse --sq-quote [<arg>...]\n"
@@ -15087,71 +12765,56 @@
 "   or: git rev-parse --sq-quote [<arg>...]\n"
 "   or: git rev-parse [<options>] [<arg>...]\n"
 "\n"
-"Rith “git rev-parse --parseopt -h” le haghaidh tuilleadh faisnéise ar an "
+"Rith \"git rev-parse --parseopt -h\" le haghaidh tuilleadh eolais faoin "
 "gcéad úsáid."
 
-#: builtin/rev-parse.c
 msgid "--resolve-git-dir requires an argument"
 msgstr "Teastaíonn argóint ag teastáil ó --resolve-git-dir"
 
-#: builtin/rev-parse.c
 #, c-format
 msgid "not a gitdir '%s'"
-msgstr "ní ghearr '%s'"
+msgstr "ní gitdir '%s'"
 
-#: builtin/rev-parse.c
 msgid "--git-path requires an argument"
 msgstr "Teastaíonn argóint ag teastáil ó --git-path"
 
-#: builtin/rev-parse.c
 msgid "-n requires an argument"
 msgstr "Éilíonn -n argóint"
 
-#: builtin/rev-parse.c
 msgid "--path-format requires an argument"
 msgstr "Éilíonn --path-format argóint"
 
-#: builtin/rev-parse.c
 #, c-format
 msgid "unknown argument to --path-format: %s"
 msgstr "argóint anaithnid chuig --path-format: %s"
 
-#: builtin/rev-parse.c
 msgid "--default requires an argument"
 msgstr "Teastaíonn argóint ar --default"
 
-#: builtin/rev-parse.c
 msgid "--prefix requires an argument"
 msgstr "Teastaíonn argóint ar --prefix"
 
-#: builtin/rev-parse.c
 msgid "no object format specified"
 msgstr "aon fhormáid réada a shonra"
 
-#: builtin/rev-parse.c
 #, c-format
 msgid "unsupported object format: %s"
 msgstr "formáid réad gan tacaíocht: %s"
 
-#: builtin/rev-parse.c
 #, c-format
 msgid "unknown mode for --abbrev-ref: %s"
 msgstr "modh anaithnid do --abbrev-ref: %s"
 
-#: builtin/rev-parse.c setup.c
 msgid "this operation must be run in a work tree"
 msgstr "caithfear an oibríocht seo a reáchtáil i gcrann oibre"
 
-#: builtin/rev-parse.c
 msgid "Could not read the index"
 msgstr "Ní fhéadfaí an t-innéacs a léamh"
 
-#: builtin/rev-parse.c
 #, c-format
 msgid "unknown mode for --show-object-format: %s"
 msgstr "modh anaithnid do --show-object-format: %s"
 
-#: builtin/revert.c
 msgid ""
 "git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] "
 "<commit>..."
@@ -15159,11 +12822,9 @@
 "git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] "
 "<commit>..."
 
-#: builtin/revert.c
 msgid "git revert (--continue | --skip | --abort | --quit)"
 msgstr "git revert (--continue | --skip | --abort | --quit)"
 
-#: builtin/revert.c
 msgid ""
 "git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n"
 "                [-S[<keyid>]] <commit>..."
@@ -15171,90 +12832,69 @@
 "git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n"
 "                [-S[<keyid>]] <commit>..."
 
-#: builtin/revert.c
 msgid "git cherry-pick (--continue | --skip | --abort | --quit)"
 msgstr "git cherry-pick (--continue | --skip | --abort | --quit)"
 
-#: builtin/revert.c
 #, c-format
 msgid "option `%s' expects a number greater than zero"
 msgstr "tá rogha `%s' ag súil go mbeidh uimhir níos mó ná nialas"
 
-#: builtin/revert.c
 #, c-format
 msgid "%s: %s cannot be used with %s"
 msgstr "%s: Ní féidir %s a úsáid le %s"
 
-#: builtin/revert.c
 msgid "end revert or cherry-pick sequence"
 msgstr "aisiompú deiridh nó seicheamh piocadh silíní"
 
-#: builtin/revert.c
 msgid "resume revert or cherry-pick sequence"
 msgstr "athosú ar ais nó seicheamh a phiocadh silíní"
 
-#: builtin/revert.c
 msgid "cancel revert or cherry-pick sequence"
 msgstr "seicheamh aisiompthe nó silíní a roghnú a chealú"
 
-#: builtin/revert.c
 msgid "skip current commit and continue"
 msgstr "scipeáil tiomantas reatha agus lean ar aghaidh"
 
-#: builtin/revert.c
 msgid "don't automatically commit"
 msgstr "ná tiomantas go huathoibríoch"
 
-#: builtin/revert.c
 msgid "edit the commit message"
 msgstr "athraigh an teachtaireacht tiomanta"
 
-#: builtin/revert.c
 msgid "parent-number"
 msgstr "uimhir tuismitheora"
 
-#: builtin/revert.c
 msgid "select mainline parent"
 msgstr "roghnaigh tuismitheoir príomh"
 
-#: builtin/revert.c
 msgid "merge strategy"
 msgstr "straitéis cumaisc"
 
-#: builtin/revert.c
 msgid "option for merge strategy"
 msgstr "rogha le haghaidh straitéis cumaisc"
 
-#: builtin/revert.c
 msgid "append commit name"
 msgstr "ainm tiomanta a chur leis"
 
-#: builtin/revert.c
 msgid "preserve initially empty commits"
 msgstr "gealltanais folamh a chaomhnú ar dt"
 
-#: builtin/revert.c
 msgid "allow commits with empty messages"
 msgstr "gealltanna a cheadú le teachtaireachtaí folamh"
 
-#: builtin/revert.c
 msgid "deprecated: use --empty=keep instead"
 msgstr "díscríofa: bain úsáid as --empty=keep ina ionad"
 
-#: builtin/revert.c
 msgid "use the 'reference' format to refer to commits"
 msgstr ""
 "bain úsáid as an bhformáid 'tagartha' chun tagairt a dhéanamh do ghealltanais"
 
-#: builtin/revert.c
 msgid "revert failed"
 msgstr "theip ar ais"
 
-#: builtin/revert.c
 msgid "cherry-pick failed"
 msgstr "theip ar an rogha silíní"
 
-#: builtin/rm.c
 msgid ""
 "git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch]\n"
 "       [--quiet] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
@@ -15264,7 +12904,6 @@
 " <file>[--quiet] [--pathspec-ó-comhad = [--pathspec-comhad-nul]]\n"
 " [--] [<pathspec>...]"
 
-#: builtin/rm.c
 msgid ""
 "the following file has staged content different from both the\n"
 "file and the HEAD:"
@@ -15281,7 +12920,6 @@
 "tá ábhar stáitseáilte difriúil idir an comhad agus \n"
 "an CEAD sna comhaid seo a leanas:"
 
-#: builtin/rm.c
 msgid ""
 "\n"
 "(use -f to force removal)"
@@ -15289,14 +12927,12 @@
 "\n"
 "(bain úsáid as -f chun a chur i bhfeidhm)"
 
-#: builtin/rm.c
 msgid "the following file has changes staged in the index:"
 msgid_plural "the following files have changes staged in the index:"
 msgstr[0] "tá athruithe céime san innéacs ag an gcomhad seo a leanas:"
 msgstr[1] "tá athruithe céimnithe san innéacs sna comhaid seo a leanas:"
 msgstr[2] "tá athruithe céimnithe san innéacs sna comhaid seo a leanas:"
 
-#: builtin/rm.c
 msgid ""
 "\n"
 "(use --cached to keep the file, or -f to force removal)"
@@ -15305,53 +12941,42 @@
 "(bain úsáid as --cached chun an comhad a choinneáil, nó -f chun a bhaint a "
 "chur i bhfeidhm)"
 
-#: builtin/rm.c
 msgid "the following file has local modifications:"
 msgid_plural "the following files have local modifications:"
 msgstr[0] "tá modhnuithe áitiúla sa chomhad seo a leanas:"
 msgstr[1] "tá modhnuithe áitiúla ar na comhaid seo a leanas:"
 msgstr[2] "tá modhnuithe áitiúla ar na comhaid seo a leanas:"
 
-#: builtin/rm.c
 msgid "do not list removed files"
 msgstr "ná liostáil comhaid a bhaintear"
 
-#: builtin/rm.c
 msgid "only remove from the index"
 msgstr "ach a bhaint as an innéacs"
 
-#: builtin/rm.c
 msgid "override the up-to-date check"
 msgstr "an seiceáil cothrom le dáta a chur ar"
 
-#: builtin/rm.c
 msgid "allow recursive removal"
 msgstr "cead a bhaint athfhillteach"
 
-#: builtin/rm.c
 msgid "exit with a zero status even if nothing matched"
 msgstr "imeacht le stádas nialasach fiú mura bhfuil aon rud comhoiriúnach"
 
-#: builtin/rm.c
 msgid "No pathspec was given. Which files should I remove?"
 msgstr "Níor tugadh aon bhealach. Cé na comhaid ba chóir dom a bhaint?"
 
-#: builtin/rm.c
 msgid "please stage your changes to .gitmodules or stash them to proceed"
 msgstr ""
 "cuir do chuid athruithe ar .gitmodules nó iad a stóráil chun dul ar aghaidh"
 
-#: builtin/rm.c
 #, c-format
 msgid "not removing '%s' recursively without -r"
 msgstr "gan '%s' a bhaint go athshlánach gan -r"
 
-#: builtin/rm.c
 #, c-format
 msgid "git rm: unable to remove %s"
 msgstr "git rm: ní féidir %s a bhaint"
 
-#: builtin/send-pack.c
 msgid ""
 "git send-pack [--mirror] [--dry-run] [--force]\n"
 "              [--receive-pack=<git-receive-pack>]\n"
@@ -15365,85 +12990,65 @@
 "              [--[no-]signed | --signed=(true|false|if-asked)]\n"
 "              [<host>:]<directory> (--all | <ref>...)"
 
-#: builtin/send-pack.c
 msgid "remote name"
 msgstr "ainm iargúlta"
 
-#: builtin/send-pack.c
 msgid "push all refs"
 msgstr "brúigh gach ceann"
 
-#: builtin/send-pack.c
 msgid "use stateless RPC protocol"
 msgstr "prótacal RPC gan stáit a úsáid"
 
-#: builtin/send-pack.c
 msgid "read refs from stdin"
 msgstr "léigh refs ó stdin"
 
-#: builtin/send-pack.c
 msgid "print status from remote helper"
 msgstr "stádas priontála ó chúntóir cianda"
 
-#: builtin/shortlog.c
 msgid "git shortlog [<options>] [<revision-range>] [[--] <path>...]"
-msgstr "git shortlog [<options>] [<revision-range>] [[--]<path>...]"
+msgstr "git shortlog [<options>] [<revision-range>] [[--] <path>...]"
 
-#: builtin/shortlog.c
 msgid "git log --pretty=short | git shortlog [<options>]"
 msgstr "git log --pretty=short | git shortlog [<options>]"
 
-#: builtin/shortlog.c
 msgid "using multiple --group options with stdin is not supported"
 msgstr "ní thacaítear le roghanna iolracha --group le stdin a úsáid"
 
-#: builtin/shortlog.c
 #, c-format
 msgid "using %s with stdin is not supported"
 msgstr "ní thacaítear le baint úsáide as %s le stdin"
 
-#: builtin/shortlog.c
 #, c-format
 msgid "unknown group type: %s"
 msgstr "cineál grúpa anaithnid: %s"
 
-#: builtin/shortlog.c
 msgid "group by committer rather than author"
 msgstr "grúpa de réir coimiteora seachas údar"
 
-#: builtin/shortlog.c
 msgid "sort output according to the number of commits per author"
 msgstr "aschur a shórtáil de réir líon na ngealltanais in aghaidh an údair"
 
-#: builtin/shortlog.c
 msgid "suppress commit descriptions, only provides commit count"
 msgstr "tuairiscí tiomanta a chur faoi chois, ní sholáthraíonn"
 
-#: builtin/shortlog.c
 msgid "show the email address of each author"
 msgstr "taispeáin seoladh ríomhphoist gach údair"
 
-#: builtin/shortlog.c
 msgid "<w>[,<i1>[,<i2>]]"
 msgstr "<w>[, <i1>[,<i2>]]"
 
-#: builtin/shortlog.c
 msgid "linewrap output"
 msgstr "aschur linewrap"
 
-#: builtin/shortlog.c
 msgid "field"
 msgstr "réimse"
 
-#: builtin/shortlog.c
 msgid "group by field"
 msgstr "grúpa de réir réimse"
 
-#: builtin/shortlog.c
 msgid "too many arguments given outside repository"
 msgstr "an iomarca argóintí a thugtar stóráil"
 
-#: builtin/show-branch.c
 msgid ""
 "git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
 "                [--current] [--color[=<when>] | --no-color] [--sparse]\n"
@@ -15457,11 +13062,9 @@
 "                [--no-name | --sha1-name] [--topics]\n"
 "                [(<rev> | <glob>)...]"
 
-#: builtin/show-branch.c
 msgid "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]"
-msgstr "<ref>git show-branch (-g | --reflog) [= [<n>,]] [--liosta] [<base>]"
+msgstr "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]"
 
-#: builtin/show-branch.c
 #, c-format
 msgid "ignoring %s; cannot handle more than %d ref"
 msgid_plural "ignoring %s; cannot handle more than %d refs"
@@ -15472,84 +13075,64 @@
 msgstr[2] ""
 "ag déanamh neamhaird de %s; ní féidir níos mó ná %d tagairtí a láimhseáil"
 
-#: builtin/show-branch.c
 #, c-format
 msgid "no matching refs with %s"
 msgstr "gan aon fhreagraí a mheaitseáil le %s"
 
-#: builtin/show-branch.c
 msgid "show remote-tracking and local branches"
 msgstr "taispeáint cianrianú agus brainsí áitiúla"
 
-#: builtin/show-branch.c
 msgid "show remote-tracking branches"
 msgstr "taispeáin brainsí cianrianaithe"
 
-#: builtin/show-branch.c
 msgid "color '*!+-' corresponding to the branch"
 msgstr "dath '*! +-' a fhreagraíonn don bhrainse"
 
-#: builtin/show-branch.c
 msgid "show <n> more commits after the common ancestor"
 msgstr "taispeáint <n>níos mó gealltanais tar éis an sinsear coiteann"
 
-#: builtin/show-branch.c
 msgid "synonym to more=-1"
 msgstr "comhchiallach le níos mó = -1"
 
-#: builtin/show-branch.c
 msgid "suppress naming strings"
 msgstr "teaghráin ainmniúcháin"
 
-#: builtin/show-branch.c
 msgid "include the current branch"
 msgstr "san áireamh an bhrainse reatha"
 
-#: builtin/show-branch.c
 msgid "name commits with their object names"
 msgstr "geallann ainm lena n-ainmneacha réad"
 
-#: builtin/show-branch.c
 msgid "show possible merge bases"
 msgstr "taispeáin bonn cumaisc féidear"
 
-#: builtin/show-branch.c
 msgid "show refs unreachable from any other ref"
 msgstr "taispeántais neamh-inrochtana ó aon tagairt eile"
 
-#: builtin/show-branch.c
 msgid "show commits in topological order"
 msgstr "gealltanna seó in ord topolaíoch"
 
-#: builtin/show-branch.c
 msgid "show only commits not on the first branch"
 msgstr "seó ní geallann ach ar an gcéad bhrainse"
 
-#: builtin/show-branch.c
 msgid "show merges reachable from only one tip"
 msgstr "cumaisc seó inrochtana ó chomhairle amháin"
 
-#: builtin/show-branch.c
 msgid "topologically sort, maintaining date order where possible"
 msgstr "a shórtáil topaiceach, ag coinneáil ord dáta nuair is féidir"
 
-#: builtin/show-branch.c
 msgid "<n>[,<base>]"
 msgstr "<n>[,<base>]"
 
-#: builtin/show-branch.c
 msgid "show <n> most recent ref-log entries starting at base"
 msgstr "taispeáin ion <n>trálacha ref-log is déanaí ag tosú ag an mbonn"
 
-#: builtin/show-branch.c
 msgid "no branches given, and HEAD is not valid"
 msgstr "aon bhrainsí a thugtar, agus níl HEAD bailí"
 
-#: builtin/show-branch.c
 msgid "--reflog option needs one branch name"
 msgstr "Teastaíonn ainm brainse amháin ag teastáil ó rogha --reflog"
 
-#: builtin/show-branch.c
 #, c-format
 msgid "only %d entry can be shown at one time."
 msgid_plural "only %d entries can be shown at one time."
@@ -15557,12 +13140,10 @@
 msgstr[1] "ní féidir ach %d iontráil a thaispeáint ag an am céanna."
 msgstr[2] "ní féidir ach %d iontráil a thaispeáint ag an am céanna."
 
-#: builtin/show-branch.c
 #, c-format
 msgid "no such ref %s"
 msgstr "aon tagairt den sórt sin %s"
 
-#: builtin/show-branch.c
 #, c-format
 msgid "cannot handle more than %d rev."
 msgid_plural "cannot handle more than %d revs."
@@ -15570,25 +13151,20 @@
 msgstr[1] "ní féidir níos mó ná %d luasghéarú a láimhseáil."
 msgstr[2] "ní féidir níos mó ná %d luasghéarú a láimhseáil."
 
-#: builtin/show-branch.c
 #, c-format
 msgid "'%s' is not a valid ref."
 msgstr "Ní tagairt bailí é '%s'."
 
-#: builtin/show-branch.c
 #, c-format
 msgid "cannot find commit %s (%s)"
 msgstr "ní féidir teacht ar thiomantas %s (%s)"
 
-#: builtin/show-index.c
 msgid "hash-algorithm"
 msgstr "hais-algartam"
 
-#: builtin/show-index.c
 msgid "Unknown hash algorithm"
 msgstr "Algartam hash anaithnid"
 
-#: builtin/show-ref.c
 msgid ""
 "git show-ref [--head] [-d | --dereference]\n"
 "             [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n"
@@ -15598,7 +13174,6 @@
 "             [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n"
 "             [--] [<pattern>...]"
 
-#: builtin/show-ref.c
 msgid ""
 "git show-ref --verify [-q | --quiet] [-d | --dereference]\n"
 "             [-s | --hash[=<n>]] [--abbrev[=<n>]]\n"
@@ -15608,78 +13183,55 @@
 "             [-s | --hash[=<n>]] [--abbrev[=<n>]]\n"
 "             [--] [<ref>...]"
 
-#: builtin/show-ref.c
 msgid "git show-ref --exclude-existing[=<pattern>]"
 msgstr "git show-ref --exclude-existing[=<pattern>]"
 
-#: builtin/show-ref.c
 msgid "git show-ref --exists <ref>"
 msgstr "git show-ref --exists <ref>"
 
-#: builtin/show-ref.c
-msgid "reference does not exist"
-msgstr "níl tagairt ann"
-
-#: builtin/show-ref.c
-msgid "failed to look up reference"
-msgstr "theip ort tagairt a lorg suas"
-
-#: builtin/show-ref.c
 msgid "only show tags (can be combined with --branches)"
 msgstr ""
 "taispeáin clibeanna amháin (is féidir iad a chomhcheangal le --branches)"
 
-#: builtin/show-ref.c
 msgid "only show branches (can be combined with --tags)"
 msgstr "ní thaispeáin ach brainsí (is féidir iad a chomhcheangal le --tags)"
 
-#: builtin/show-ref.c
 msgid "check for reference existence without resolving"
 msgstr "seiceáil chun tagartha a bheith ann gan réiteach"
 
-#: builtin/show-ref.c
 msgid "stricter reference checking, requires exact ref path"
 msgstr "seiceáil tagartha níos doichte, teastaíonn cosán tagartha"
 
-#: builtin/show-ref.c
 msgid "show the HEAD reference, even if it would be filtered out"
 msgstr "taispeáin tagairt HEAD, fiú dá ndéanfaí é a scagadh amach"
 
-#: builtin/show-ref.c
 msgid "dereference tags into object IDs"
 msgstr "clibeanna a dhíthreorú isteach in IDanna réad"
 
-#: builtin/show-ref.c
 msgid "only show SHA1 hash using <n> digits"
 msgstr "ní thaispeáin ach hais SHA1 ag úsáid <n> dhigit"
 
-#: builtin/show-ref.c
 msgid "do not print results to stdout (useful with --verify)"
 msgstr "ná priontáil torthaí chuig stdout (úsáideach le --verify)"
 
-#: builtin/show-ref.c
 msgid "show refs from stdin that aren't in local repository"
 msgstr "taispeáin airgeanna ó stdin nach bhfuil i stóras áitiúil"
 
-#: builtin/sparse-checkout.c
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 
-#: builtin/sparse-checkout.c
 msgid "this worktree is not sparse"
 msgstr "níl an crann oibre seo neamhchoitianta"
 
-#: builtin/sparse-checkout.c
 msgid "this worktree is not sparse (sparse-checkout file may not exist)"
 msgstr ""
 "níl an crann oibre seo neamhchoitianta (b'fhéidir nach bhfuil comhad "
 "seiceála neamhchoitianta ann)"
 
-#: builtin/sparse-checkout.c
 #, c-format
 msgid ""
 "directory '%s' contains untracked files, but is not in the sparse-checkout "
@@ -15688,73 +13240,53 @@
 "tá comhaid neamhrianaithe ag eolaire '%s', ach níl sé sa chón seiceála "
 "neamhchoitianta"
 
-#: builtin/sparse-checkout.c
 #, c-format
 msgid "failed to remove directory '%s'"
 msgstr "theip ar eolaire '%s' a bhaint"
 
-#: builtin/sparse-checkout.c
 msgid "failed to create directory for sparse-checkout file"
 msgstr "theip ar eolaire a chruthú do chomhad seiceála neamhchoitianta"
 
-#: builtin/sparse-checkout.c
 #, c-format
 msgid "unable to fdopen %s"
-msgstr "nach féidir %s a fdophríomhachtú"
+msgstr "ní féidir %s a fdopen"
 
-#: builtin/sparse-checkout.c
 msgid "failed to initialize worktree config"
 msgstr "theip orthu cumraíocht crann oibre a thionscnamh"
 
-#: builtin/sparse-checkout.c
 msgid "failed to modify sparse-index config"
 msgstr "theip orthu cumraíocht innéacs neamhchoitianta a mhodhnú"
 
-#: builtin/sparse-checkout.c
 msgid "initialize the sparse-checkout in cone mode"
 msgstr "an tseiceáil neamhchoitianta a thosú i mód cón"
 
-#: builtin/sparse-checkout.c
 msgid "toggle the use of a sparse index"
 msgstr "athsholáthar úsáid innéacs neamhchoitianta"
 
-#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c
-#, c-format
-msgid "unable to create leading directories of %s"
-msgstr "nach féidir eolairí tosaigh de %s a chruthú"
-
-#: builtin/sparse-checkout.c
 #, c-format
 msgid "failed to open '%s'"
 msgstr "theip ar '%s' a oscailt"
 
-#: builtin/sparse-checkout.c
 #, c-format
 msgid "could not normalize path %s"
 msgstr "ní fhéadfaí cosán %s a normalú"
 
-#: builtin/sparse-checkout.c
 #, c-format
 msgid "unable to unquote C-style string '%s'"
-msgstr "nach féidir teaghrán '%s' i stíl C a dhíluachan"
+msgstr "ní féidir ceanntásc %s a dhíphacáil"
 
-#: builtin/sparse-checkout.c
 msgid "unable to load existing sparse-checkout patterns"
-msgstr "in ann patrúin seiceála neamhchoitianta atá ann a luchtú"
+msgstr "ní féidir patrúin seiceála amach scaipthe atá ann cheana a luchtú"
 
-#: builtin/sparse-checkout.c
 msgid "existing sparse-checkout patterns do not use cone mode"
 msgstr "ní úsáideann patrúin seiceála neamhchoitianta atá ann cheana modh cón"
 
-#: builtin/sparse-checkout.c
 msgid "please run from the toplevel directory in non-cone mode"
 msgstr "rith ón eolaire topevel le do thoil i mód neamh-chón"
 
-#: builtin/sparse-checkout.c
 msgid "specify directories rather than patterns (no leading slash)"
 msgstr "eolairí a shonrú seachas patrúin (gan aon slash tosaigh)"
 
-#: builtin/sparse-checkout.c
 msgid ""
 "specify directories rather than patterns.  If your directory starts with a "
 "'!', pass --skip-checks"
@@ -15762,7 +13294,6 @@
 "eolairí a shonrú seachas patrúin. Má thosaíonn d'eolaire le '!', pas --skip-"
 "checks"
 
-#: builtin/sparse-checkout.c
 msgid ""
 "specify directories rather than patterns.  If your directory really has any "
 "of '*?[]\\' in it, pass --skip-checks"
@@ -15770,7 +13301,6 @@
 "eolairí a shonrú seachas patrúin. Má tá aon cheann de '* ag d'eolaire i "
 "ndáiríre? []\\ 'ann, pas --skip-checks"
 
-#: builtin/sparse-checkout.c
 #, c-format
 msgid ""
 "'%s' is not a directory; to treat it as a directory anyway, rerun with --"
@@ -15779,7 +13309,6 @@
 "Ní eolaire é '%s'; chun é a chóireáil mar eolaire ar aon nós, athrith le --"
 "skip-checks"
 
-#: builtin/sparse-checkout.c
 #, c-format
 msgid ""
 "pass a leading slash before paths such as '%s' if you want a single file "
@@ -15788,26 +13317,21 @@
 "téigh slasc tosaigh roimh chosáin mar '%s' más mian leat comhad amháin "
 "(féach FADHBANNA NEAMH-CONE sa lámhleabhar seiceála git-sparse-checkout)."
 
-#: builtin/sparse-checkout.c
 msgid "git sparse-checkout add [--skip-checks] (--stdin | <patterns>)"
 msgstr "git sparse-checkout add [--skip-checks] (--stdin | <patterns>)"
 
-#: builtin/sparse-checkout.c
 msgid ""
 "skip some sanity checks on the given paths that might give false positives"
 msgstr ""
 "scipeáil roinnt seiceálacha sláinte ar na cosáin a thugtar a d'fhéadfadh "
 "dearfacha bréagacha a"
 
-#: builtin/sparse-checkout.c
 msgid "read patterns from standard in"
 msgstr "léigh patrúin ó chaighdeán i"
 
-#: builtin/sparse-checkout.c
 msgid "no sparse-checkout to add to"
 msgstr "gan aon seiceáil neamhchoitianta le cur leis"
 
-#: builtin/sparse-checkout.c
 msgid ""
 "git sparse-checkout set [--[no-]cone] [--[no-]sparse-index] [--skip-checks] "
 "(--stdin | <patterns>)"
@@ -15815,17 +13339,44 @@
 "git sparse-checkout set [--[no-]cone] [--[no-]sparse-index] [--skip-checks] "
 "(--stdin | <patterns>)"
 
-#: builtin/sparse-checkout.c
 msgid "must be in a sparse-checkout to reapply sparsity patterns"
 msgstr ""
 "caithfidh sé a bheith i seiceáil neamhchoitianta chun patrúin éagsúla a "
 "athchur i bhfeidh"
 
-#: builtin/sparse-checkout.c
+msgid "report each affected file, not just directories"
+msgstr "tuairiscigh gach comhad lena mbaineann, ní hamháin eolairí"
+
+msgid "must be in a sparse-checkout to clean directories"
+msgstr "ní mór é a bheith i seiceáil amach sparse chun eolairí a ghlanadh"
+
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr ""
+"ní mór é a bheith i mód cóin le haghaidh seiceáil amach sparse chun eolairí "
+"a ghlanadh"
+
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr ""
+"ar mhaithe le sábháilteacht, diúltú glanadh gan ceann amháin de --force nó --"
+"dry-run"
+
+msgid "failed to read index"
+msgstr "theip ar an innéacs a léamh"
+
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr ""
+"theip ar an innéacs a thiontú go hinnéacs gann; réitigh coinbhleachtaí "
+"cumaisc agus déan iarracht arís"
+
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "theip ar '%s' a bhaint"
+
 msgid "error while refreshing working directory"
 msgstr "earráid agus tú ag athnuachan eolaire"
 
-#: builtin/sparse-checkout.c
 msgid ""
 "git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
 "file <file>]"
@@ -15833,24 +13384,19 @@
 "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 "comhaid ionchuir agus aschuir a fhoirceannadh le carachtar NUL"
 
-#: builtin/sparse-checkout.c
 msgid "when used with --rules-file interpret patterns as cone mode patterns"
 msgstr ""
 "nuair a úsáidtear é le --rules-file patrúin a léirmhíniú mar phatrúin mód"
 
-#: builtin/sparse-checkout.c
 msgid "use patterns in <file> instead of the current ones."
 msgstr "úsáid patrúin in <file>ionad na cinn reatha."
 
-#: builtin/stash.c
 msgid "git stash list [<log-options>]"
-msgstr "<log-options>liosta git stash []"
+msgstr "git stash list [<log-options>]"
 
-#: builtin/stash.c
 msgid ""
 "git stash show [-u | --include-untracked | --only-untracked] [<diff-"
 "options>] [<stash>]"
@@ -15858,28 +13404,21 @@
 "git stash show [-u | --include-untracked | --only-untracked] [<diff-"
 "options>] [<stash>]"
 
-#: builtin/stash.c
 msgid "git stash drop [-q | --quiet] [<stash>]"
 msgstr "git stash drop [-q | --quiet] [<stash>]"
 
-#: builtin/stash.c
 msgid "git stash pop [--index] [-q | --quiet] [<stash>]"
 msgstr "git stash pop [--index] [-q | --quiet] [<stash>]"
 
-#: builtin/stash.c
 msgid "git stash apply [--index] [-q | --quiet] [<stash>]"
 msgstr "git stash apply [--index] [-q | --quiet] [<stash>]"
 
-#: builtin/stash.c
 msgid "git stash branch <branchname> [<stash>]"
 msgstr "git stash branch <branchname> [<stash>]"
 
-#: builtin/stash.c
 msgid "git stash store [(-m | --message) <message>] [-q | --quiet] <commit>"
-msgstr ""
-"git stash store [(-m | --teachtaireacht)<message>] [-q | --ciúin] <commit>"
+msgstr "git stash store [(-m | --message) <message>] [-q | --quiet] <commit>"
 
-#: builtin/stash.c
 msgid ""
 "git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q "
 "| --quiet]\n"
@@ -15894,7 +13433,6 @@
 " <file>[--pathspec-ó-comhad = [--pathspec-comhad-nul]]\n"
 " [--] [<pathspec>...]]"
 
-#: builtin/stash.c
 msgid ""
 "git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | "
 "--quiet]\n"
@@ -15904,34 +13442,33 @@
 "--quiet]\n"
 "          [-u | --include-untracked] [-a | --all] [<message>]"
 
-#: builtin/stash.c
 msgid "git stash create [<message>]"
-msgstr "<message>git stash cruthaigh []"
+msgstr "git stash create [<message>]"
 
-#: builtin/stash.c
+msgid "git stash export (--print | --to-ref <ref>) [<stash>...]"
+msgstr "git stash export (--print | --to-ref <ref>) [<stash>...]"
+
+msgid "git stash import <commit>"
+msgstr "git stash import <commit>"
+
 #, c-format
 msgid "'%s' is not a stash-like commit"
 msgstr "Ní gealltanas cosúil le stash é '%s'"
 
-#: builtin/stash.c
+msgid "No stash entries found."
+msgstr "Níor aimsíodh aon iontrálacha stash."
+
 #, c-format
 msgid "Too many revisions specified:%s"
 msgstr "Sonraítear an iomarca athbhreithnithe: %s"
 
-#: builtin/stash.c
-msgid "No stash entries found."
-msgstr "Níor aimsíodh aon iontrálacha stash."
-
-#: builtin/stash.c
 #, c-format
 msgid "%s is not a valid reference"
 msgstr "Ní tagairt bailí é %s"
 
-#: builtin/stash.c
 msgid "git stash clear with arguments is unimplemented"
-msgstr "níl git stash clear le hargóintí neamh-chur i bhfeidhm"
+msgstr "git stash clear with arguments is unimplemented"
 
-#: builtin/stash.c
 #, c-format
 msgid ""
 "WARNING: Untracked file in way of tracked file!  Renaming\n"
@@ -15942,202 +13479,210 @@
 "            %s -> %s\n"
 "         chun seomra a dhéanamh.\n"
 
-#: builtin/stash.c
 msgid "cannot apply a stash in the middle of a merge"
 msgstr "ní féidir stash a chur i bhfeidhm i lár cumaisc"
 
-#: builtin/stash.c
 #, c-format
 msgid "could not generate diff %s^!."
 msgstr "ní fhéadfaí diff %s^ a ghiniúint!."
 
-#: builtin/stash.c
 msgid "conflicts in index. Try without --index."
 msgstr "coinbhleachtaí in innéacs. Bain triail as gan --index."
 
-#: builtin/stash.c
 msgid "could not save index tree"
 msgstr "ní fhéadfadh crann innéacs a shábháil"
 
-#: builtin/stash.c
 #, c-format
 msgid "Merging %s with %s"
 msgstr "Cumasc %s le %s"
 
-#: builtin/stash.c
 msgid "Index was not unstashed."
 msgstr "Ní raibh an t-innéacs gan stashed."
 
-#: builtin/stash.c
 msgid "could not restore untracked files from stash"
 msgstr "ní raibh in ann comhaid neamhrianaithe a chur ar ais ó stash"
 
-#: builtin/stash.c
 msgid "attempt to recreate the index"
 msgstr "iarracht an t-innéacs a athchruthú"
 
-#: builtin/stash.c
 #, c-format
 msgid "Dropped %s (%s)"
 msgstr "Scaoil %s (%s)"
 
-#: builtin/stash.c
 #, c-format
 msgid "%s: Could not drop stash entry"
 msgstr "%s: Ní fhéadfaí iontráil stash a scaoileadh"
 
-#: builtin/stash.c
 #, c-format
 msgid "'%s' is not a stash reference"
 msgstr "Ní tagairt stash é '%s'"
 
-#: builtin/stash.c
 msgid "The stash entry is kept in case you need it again."
 msgstr "Coinnítear an iontráil stash ar eagla go dteastaíonn sé uait arís."
 
-#: builtin/stash.c
 msgid "No branch name specified"
 msgstr "Níl aon ainm brainse sonraithe"
 
-#: builtin/stash.c
 msgid "failed to parse tree"
 msgstr "theip ar chrann a pháirseáil"
 
-#: builtin/stash.c
 msgid "failed to unpack trees"
 msgstr "theip ar chrainn a dhíphacáil"
 
-#: builtin/stash.c
 msgid "include untracked files in the stash"
 msgstr "comhaid neamhrianaithe san áireamh sa stash"
 
-#: builtin/stash.c
 msgid "only show untracked files in the stash"
 msgstr "ní thaispeánann ach comhaid neamhrianaithe sa stash"
 
-#: builtin/stash.c
 #, c-format
 msgid "Cannot update %s with %s"
 msgstr "Ní féidir %s a nuashonrú le %s"
 
-#: builtin/stash.c
 msgid "stash message"
 msgstr "teachtaireacht stash"
 
-#: builtin/stash.c
 msgid "\"git stash store\" requires one <commit> argument"
 msgstr "<commit>Éilíonn “git stash store” argóint amháin"
 
-#: builtin/stash.c
 msgid "No staged changes"
 msgstr "Gan aon athruithe céime"
 
-#: builtin/stash.c
 msgid "No changes selected"
 msgstr "Gan aon athruithe roghnaithe"
 
-#: builtin/stash.c
 msgid "You do not have the initial commit yet"
 msgstr "Níl an tiomantas tosaigh agat fós"
 
-#: builtin/stash.c
 msgid "Cannot save the current index state"
 msgstr "Ní féidir an staid innéacs reatha a shábháil"
 
-#: builtin/stash.c
 msgid "Cannot save the untracked files"
 msgstr "Ní féidir na comhaid neamhrianaithe a shábháil"
 
-#: builtin/stash.c
 msgid "Cannot save the current worktree state"
 msgstr "Ní féidir an stát crainn oibre reatha a shábháil"
 
-#: builtin/stash.c
 msgid "Cannot save the current staged state"
 msgstr "Ní féidir an stát stáitse reatha a shábháil"
 
-#: builtin/stash.c
 msgid "Cannot record working tree state"
 msgstr "Ní féidir stát crann oibre a thaifead"
 
-#: builtin/stash.c
 msgid "Can't use --patch and --include-untracked or --all at the same time"
 msgstr ""
 "Ní féidir --patch agus --include-untracked nó --all a úsáid ag an am céanna"
 
-#: builtin/stash.c
 msgid "Can't use --staged and --include-untracked or --all at the same time"
 msgstr ""
 "Ní féidir --staged agus --include-untracked nó --all a úsáid ag an am céanna"
 
-#: builtin/stash.c
 msgid "Did you forget to 'git add'?"
 msgstr "Ar ndearna tú dearmad 'git add'?"
 
-#: builtin/stash.c
 msgid "No local changes to save"
 msgstr "Níl aon athruithe áitiúla le sábháil"
 
-#: builtin/stash.c
 msgid "Cannot initialize stash"
 msgstr "Ní féidir stash a thionscnamh"
 
-#: builtin/stash.c
 msgid "Cannot save the current status"
 msgstr "Ní féidir an stádas reatha a shábháil"
 
-#: builtin/stash.c
 #, c-format
 msgid "Saved working directory and index state %s"
 msgstr "Eolaire oibre shábháilte agus staid innéacs %s"
 
-#: builtin/stash.c
 msgid "Cannot remove worktree changes"
 msgstr "Ní féidir athruithe crann oibre a bhaint"
 
-#: builtin/stash.c
 msgid "keep index"
 msgstr "coinnigh innéacs"
 
-#: builtin/stash.c
 msgid "stash staged changes only"
 msgstr "athruithe céimeádta stash amháin"
 
-#: builtin/stash.c
 msgid "stash in patch mode"
 msgstr "stash i mód paiste"
 
-#: builtin/stash.c
 msgid "quiet mode"
 msgstr "modh ciúin"
 
-#: builtin/stash.c
 msgid "include untracked files in stash"
 msgstr "comhaid neamhrianaithe a chur san áireamh i stash"
 
-#: builtin/stash.c
 msgid "include ignore files"
 msgstr "áireamh neamhaird a dhéanamh"
 
-#: builtin/stripspace.c
+#, c-format
+msgid "cannot parse commit %s"
+msgstr "ní féidir an tiomantas %s a pharsáil"
+
+#, c-format
+msgid "invalid author or committer for %s"
+msgstr "údar nó tiomnóir neamhbhailí do %s"
+
+msgid "could not write commit"
+msgstr "níorbh fhéidir commit a scríobh"
+
+#, c-format
+msgid "not a valid revision: %s"
+msgstr "ní athbhreithniú bailí é: %s"
+
+#, c-format
+msgid "not a commit: %s"
+msgstr "ní tiomantas é: %s"
+
+#, c-format
+msgid "%s is not a valid exported stash commit"
+msgstr "Ní tiomnú stash easpórtáilte bailí é %s"
+
+#, c-format
+msgid "found root commit %s with invalid data"
+msgstr "fuarthas an commit fréimhe %s le sonraí neamhbhailí"
+
+#, c-format
+msgid "found stash commit %s without expected prefix"
+msgstr "fuarthas an tiomnú stash %s gan an réimír a raibh súil leis"
+
+#, c-format
+msgid "cannot parse parents of commit: %s"
+msgstr "ní féidir tuismitheoirí an tiomantas a pharsáil: %s"
+
+#, c-format
+msgid "%s does not look like a stash commit"
+msgstr "Ní cosúil go bhfuil %s ina thiomantas stash"
+
+#, c-format
+msgid "cannot read commit buffer for %s"
+msgstr "ní féidir maolán tiomantais a léamh do %s"
+
+#, c-format
+msgid "cannot save the stash for %s"
+msgstr "ní féidir an stór a shábháil do %s"
+
+msgid "unable to write base commit"
+msgstr "ní féidir an bonn-thiomantas a scríobh"
+
+#, c-format
+msgid "unable to find stash entry %s"
+msgstr "ní féidir an iontráil stash %s a aimsiú"
+
+msgid "print the object ID instead of writing it to a ref"
+msgstr "priontáil an ID réada in ionad é a scríobh chuig tagairt"
+
+msgid "save the data to the given ref"
+msgstr "sábháil na sonraí chuig an tagairt tugtha"
+
+msgid "exactly one of --print and --to-ref is required"
+msgstr "tá ceann amháin de --print agus --to-ref ag teastáil"
+
 msgid "skip and remove all lines starting with comment character"
 msgstr "scipeáil agus bain gach líne ag tosú le carachtar trácht"
 
-#: builtin/stripspace.c
 msgid "prepend comment character and space to each line"
 msgstr "carachtar tráchta agus spás a chur ar fáil chuig gach líne"
 
-#: builtin/submodule--helper.c
-#, c-format
-msgid "Expecting a full ref name, got %s"
-msgstr "Ag súil le hainm tagartha iomlán, fuair %s"
-
-#: builtin/submodule--helper.c
-#, c-format
-msgid "could not get a repository handle for submodule '%s'"
-msgstr "ní fhéadfaí láimhseáil stór a fháil do fho-mhodúl '%s'"
-
-#: builtin/submodule--helper.c
 #, c-format
 msgid ""
 "could not look up configuration '%s'. Assuming this repository is its own "
@@ -16146,17 +13691,18 @@
 "ní fhéadfaí cumraíocht '%s' a fheiceáil suas. Ag glacadh leis gurb é an stór "
 "seo a údarásach suas sruth féin."
 
-#: builtin/submodule--helper.c
+#, c-format
+msgid "could not get a repository handle for submodule '%s'"
+msgstr "ní fhéadfaí láimhseáil stór a fháil do fho-mhodúl '%s'"
+
 #, c-format
 msgid "No url found for submodule path '%s' in .gitmodules"
 msgstr "Níl aon url le haghaidh cosán fo-mhodúil '%s' i .gitmodules"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Entering '%s'\n"
 msgstr "Ag iontráil '%s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid ""
 "run_command returned non-zero status for %s\n"
@@ -16165,7 +13711,6 @@
 "thug run_command stádas neamh-nialas ar ais do %s.\n"
 "."
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid ""
 "run_command returned non-zero status while recursing in the nested "
@@ -16176,67 +13721,53 @@
 "mhodúil neadaithe de %s\n"
 "."
 
-#: builtin/submodule--helper.c
 msgid "suppress output of entering each submodule command"
 msgstr "cosc a chur ar aschur gach ordú fo-mhodúil a chur isteach"
 
-#: builtin/submodule--helper.c
 msgid "recurse into nested submodules"
 msgstr "athshlánú isteach i bhfo-mhodúil neadaithe"
 
-#: builtin/submodule--helper.c
 msgid "git submodule foreach [--quiet] [--recursive] [--] <command>"
 msgstr "git submodule foreach [--quiet] [--recursive] [--] <command>"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Failed to register url for submodule path '%s'"
 msgstr "Theip ar url a chlárú le haghaidh cosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Submodule '%s' (%s) registered for path '%s'\n"
 msgstr "Fo-mhodúl '%s' (%s) cláraithe le haghaidh cosán '%s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "warning: command update mode suggested for submodule '%s'\n"
 msgstr "rabhadh: modh nuashonraithe ordaithe a mholtar don fho-mhodúl '%s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Failed to register update mode for submodule path '%s'"
 msgstr "Theip ar mhodh nuashonraithe a chlárú do chonair fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 msgid "suppress output for initializing a submodule"
 msgstr "aschur a chur faoi chois chun fo-mhodúl a thosú"
 
-#: builtin/submodule--helper.c
 msgid "git submodule init [<options>] [<path>]"
 msgstr "git submodule init [<options>] [<path>]"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "no submodule mapping found in .gitmodules for path '%s'"
 msgstr ""
 "níl aon mhapáil fo-mhodúil le fáil i .gitmodules le haghaidh cosán '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "could not resolve HEAD ref inside the submodule '%s'"
 msgstr "ní fhéadfaí tagairt HEAD a réiteach taobh istigh den fho-mhodúl '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "failed to recurse into submodule '%s'"
 msgstr "theip ar athshlánú isteach i bhfo-mhodúl '%s'"
 
-#: builtin/submodule--helper.c
 msgid "suppress submodule status output"
 msgstr "aschur stádas fo-mhodúil a chur faoi cho"
 
-#: builtin/submodule--helper.c
 msgid ""
 "use commit stored in the index instead of the one stored in the submodule "
 "HEAD"
@@ -16244,86 +13775,68 @@
 "bain úsáid as tiomantas atá stóráilte san innéacs in ionad an ceann atá "
 "stóráilte sa fho-mhodúl HEAD"
 
-#: builtin/submodule--helper.c
 msgid "git submodule status [--quiet] [--cached] [--recursive] [<path>...]"
 msgstr "git submodule status [--quiet] [--cached] [--recursive] [<path>...]"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "* %s %s(blob)->%s(submodule)"
 msgstr "* %s %s (blob) -> %s (fo-mhodúl)"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "* %s %s(submodule)->%s(blob)"
 msgstr "* %s %s (fo-mhodúl) -> %s (blob)"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "%s"
 msgstr "%s"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "couldn't hash object from '%s'"
 msgstr "ní fhéadfaí réad hash ó '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "unexpected mode %o"
 msgstr "modh gan choinne %o"
 
-#: builtin/submodule--helper.c
 msgid "use the commit stored in the index instead of the submodule HEAD"
 msgstr ""
 "bain úsáid as an gealltanas atá stóráilte san innéacs in ionad an fho-mhodúl "
 "HEAD"
 
-#: builtin/submodule--helper.c
 msgid "compare the commit in the index with that in the submodule HEAD"
 msgstr ""
 "comparáid a dhéanamh idir an tiomantas san innéacs leis an bhfo-mhodúl HEAD"
 
-#: builtin/submodule--helper.c
 msgid "skip submodules with 'ignore_config' value set to 'all'"
 msgstr "scipeáil fo-mhodúil le luach 'ignore_config' socraithe go 'go léir'"
 
-#: builtin/submodule--helper.c
 msgid "limit the summary size"
 msgstr "teorainn a chur leis an méid achoimre"
 
-#: builtin/submodule--helper.c
 msgid "git submodule summary [<options>] [<commit>] [--] [<path>]"
 msgstr "git achoimre fo-mhodúil [<options>] [<commit>] [--] [<path>]"
 
-#: builtin/submodule--helper.c
 msgid "could not fetch a revision for HEAD"
 msgstr "ní fhéadfaí athbhreithniú a fháil do HEAD"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Synchronizing submodule url for '%s'\n"
 msgstr "Url fo-mhodúil a shioncrónú do '%s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "failed to register url for submodule path '%s'"
 msgstr "theip ar url a chlárú le haghaidh cosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "failed to update remote for submodule '%s'"
 msgstr "theip ar iargúlta a nuashonrú do fho-mhodúl '%s'"
 
-#: builtin/submodule--helper.c
 msgid "suppress output of synchronizing submodule url"
 msgstr "aschur url fo-mhodúil sioncrónaithe a chur faoi chois"
 
-#: builtin/submodule--helper.c
 msgid "git submodule sync [--quiet] [--recursive] [<path>]"
 msgstr "git sioncrónú fo-mhodúil [--quiet] [--recursive] [<path>]"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid ""
 "Submodule work tree '%s' contains a .git directory. This will be replaced "
@@ -16332,7 +13845,6 @@
 "Tá eolair .git i gcrann oibre fo-mhodúil '%s'. Cuirfear comhad .git in ionad "
 "seo trí absorbgitdirs a úsáid."
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid ""
 "Submodule work tree '%s' contains local modifications; use '-f' to discard "
@@ -16341,45 +13853,36 @@
 "Tá modhnuithe áitiúla i gcrann oibre fo-mhodúil '%s'; bain úsáid as '-f' "
 "chun iad a dhiúscairt"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Cleared directory '%s'\n"
 msgstr "Glanadh an eolaire '%s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Could not remove submodule work tree '%s'\n"
 msgstr "Níor féidir crann oibre fo-mhodúil '%s' a bhaint\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "could not create empty submodule directory %s"
 msgstr "ní fhéadfaí eolaire fo-mhodúil folamh %s a chruthú"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Submodule '%s' (%s) unregistered for path '%s'\n"
 msgstr "Fo-mhodúl '%s' (%s) neamhchláraithe le haghaidh cosán '%s'\n"
 
-#: builtin/submodule--helper.c
 msgid "remove submodule working trees even if they contain local changes"
 msgstr "crainn oibre fo-mhodúil a bhaint fiú má tá athruithe áitiúla iontu"
 
-#: builtin/submodule--helper.c
 msgid "unregister all submodules"
 msgstr "gach fo-mhodúl a dhíchlárú"
 
-#: builtin/submodule--helper.c
 msgid ""
 "git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"
 msgstr ""
-"git fo-mhodúil deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"
+"git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"
 
-#: builtin/submodule--helper.c
 msgid "Use '--all' if you really want to deinitialize all submodules"
 msgstr "Úsáid '--all' más mian leat gach fo-mhodúl a dhíthionsú i ndáiríre"
 
-#: builtin/submodule--helper.c
 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"
@@ -16392,75 +13895,59 @@
 "le\n"
 "'--reference-if-able' in ionad '--reference'."
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "could not get a repository handle for gitdir '%s'"
 msgstr "ní fhéadfaí láimhseáil stór a fháil do gitdir '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "submodule '%s' cannot add alternate: %s"
 msgstr "ní féidir le fo-mhodúl '%s' malartach a chur leis: %s"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Value '%s' for submodule.alternateErrorStrategy is not recognized"
 msgstr "Luach '%s' le haghaidh submodule.alternateErrorStrategy ní aithnítear"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Value '%s' for submodule.alternateLocation is not recognized"
 msgstr "Luach '%s' le haghaidh submodule.alternateLocation ní aithnítear"
 
-#: builtin/submodule--helper.c submodule.c
 #, c-format
 msgid "refusing to create/use '%s' in another submodule's git dir"
 msgstr "diúltú '%s' a chruthú/úsáid i git dir fo-mhodúil eile"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "directory not empty: '%s'"
 msgstr "eolaire nach folamh: '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "clone of '%s' into submodule path '%s' failed"
 msgstr "theip ar chlón '%s' isteach i gcosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "could not get submodule directory for '%s'"
 msgstr "ní fhéadfaí eolaire fo-mhodúil a fháil do '%s'"
 
-#: builtin/submodule--helper.c
 msgid "alternative anchor for relative paths"
 msgstr "ancaire malartach do chonair choibhneasta"
 
-#: builtin/submodule--helper.c
 msgid "where the new submodule will be cloned to"
 msgstr "áit a gclónófar an fo-mhodúl nua"
 
-#: builtin/submodule--helper.c
 msgid "name of the new submodule"
 msgstr "ainm an fho-mhodúil nua"
 
-#: builtin/submodule--helper.c
 msgid "url where to clone the submodule from"
 msgstr "url cá háit ar féidir an fo-mhodúl a chlónáil"
 
-#: builtin/submodule--helper.c
 msgid "depth for shallow clones"
 msgstr "doimhneacht do chlóin éadomhain"
 
-#: builtin/submodule--helper.c
 msgid "force cloning progress"
 msgstr "dul chun cinn clónaithe fórsa"
 
-#: builtin/submodule--helper.c
 msgid "disallow cloning into non-empty directory"
 msgstr "clónú a dhícheadú isteach i eolaire neamh-folamh"
 
-#: builtin/submodule--helper.c
 msgid ""
 "git submodule--helper clone [--prefix=<path>] [--quiet] [--reference "
 "<repository>] [--name <name>] [--depth <depth>] [--single-branch] [--filter "
@@ -16470,94 +13957,76 @@
 "<repository>] [--name <name>] [--depth <depth>] [--single-branch] [--filter "
 "<filter-spec>] --url <url> --path <path>"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Invalid update mode '%s' configured for submodule path '%s'"
 msgstr ""
 "Modh nuashonraithe neamhbhailí '%s' cumraithe le haghaidh cosán fo-mhodúil "
 "'%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Submodule path '%s' not initialized"
 msgstr "Níor thosaigh cosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 msgid "Maybe you want to use 'update --init'?"
 msgstr "B'fhéidir gur mhaith leat 'update --init' a úsáid?"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Skipping unmerged submodule %s"
-msgstr "Fo-mhodúl neamh-mheánaithe %s a scipeáil"
+msgstr "Ag scipeáil an fho-mhodúil neamh-chomhcheangailte %s"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Skipping submodule '%s'"
-msgstr "Fo-mhodúl '%s' a scipeáil"
+msgstr "Ag scipeáil an fho-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "cannot clone submodule '%s' without a URL"
 msgstr "ní féidir le fo-mhodúl '%s' a chlónú gan URL"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Failed to clone '%s'. Retry scheduled"
 msgstr "Theip ar chlónáil '%s'. Déan iarracht sceidealta"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Failed to clone '%s' a second time, aborting"
 msgstr "Theip ar chlónáil '%s' an dara huair, ag cur isteach"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Unable to checkout '%s' in submodule path '%s'"
 msgstr "Ní féidir '%s' a sheiceáil i gcosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Unable to rebase '%s' in submodule path '%s'"
 msgstr "Ní féidir '%s' a athbhunú i gcosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Unable to merge '%s' in submodule path '%s'"
 msgstr "Ní féidir '%s' a chumasc i gcosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Execution of '%s %s' failed in submodule path '%s'"
 msgstr "Theip ar fhorghníomhú '%s %s' i gcosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Submodule path '%s': checked out '%s'\n"
 msgstr "Conair fo-mhodúil '%s': seiceáil amach '%s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Submodule path '%s': rebased into '%s'\n"
 msgstr "Conair fo-mhodúil '%s': athbhunaithe go '%s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Submodule path '%s': merged in '%s'\n"
 msgstr "Conair fo-mhodúil '%s': cumasc i '%s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Submodule path '%s': '%s %s'\n"
 msgstr "Conair fo-mhodúil '%s': '%s %s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Unable to fetch in submodule path '%s'; trying to directly fetch %s:"
 msgstr ""
 "Ní féidir cosán fo-mhodúil '%s' a fháil; ag iarraidh %s a fháil go díreach:"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid ""
 "Fetched in submodule path '%s', but it did not contain %s. Direct fetching "
@@ -16566,12 +14035,10 @@
 "Faightear i gcosán fo-mhodúil '%s', ach ní raibh %s ann. Theip ar an "
 "tiomantas sin a thógáil go díreach."
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "could not initialize submodule at path '%s'"
 msgstr "ní fhéadfaí fo-mhodúl a thosú ag cosán '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid ""
 "Submodule (%s) branch configured to inherit branch from superproject, but "
@@ -16580,81 +14047,67 @@
 "Brainse fo-mhodúil (%s) atá cumraithe chun brainse a oidhreacht ó "
 "sárthionscadal, ach níl an sárthionscadal ar aon bhrainse"
 
-#: builtin/submodule--helper.c
+#, c-format
+msgid "Expecting a full ref name, got %s"
+msgstr "Ag súil le hainm tagartha iomlán, fuair %s"
+
 #, c-format
 msgid "Unable to find current revision in submodule path '%s'"
 msgstr "Ní féidir an t-athbhreithniú reatha a fháil i gcosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Unable to fetch in submodule path '%s'"
 msgstr "Ní féidir le cosán fo-mhodúil '%s' a fháil"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Unable to find %s revision in submodule path '%s'"
 msgstr "Ní féidir athbhreithniú %s a aimsiú i gcosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Failed to recurse into submodule path '%s'"
 msgstr "Theip ar athshlánú isteach i gcosán fo-mhodúil '%s'"
 
-#: builtin/submodule--helper.c
 msgid "force checkout updates"
 msgstr "nuashonruithe seiceála de"
 
-#: builtin/submodule--helper.c
 msgid "initialize uninitialized submodules before update"
 msgstr "fo-mhodúil neamhthosaithe a thosú roimh an nuashonrú"
 
-#: builtin/submodule--helper.c
 msgid "use SHA-1 of submodule's remote tracking branch"
 msgstr "úsáid SHA-1 de bhrainse cianrianaithe an fho-mhodúil"
 
-#: builtin/submodule--helper.c
 msgid "traverse submodules recursively"
 msgstr "fo-mhodúil a thrasú go athshlánach"
 
-#: builtin/submodule--helper.c
 msgid "don't fetch new objects from the remote site"
 msgstr "ná faigh rudaí nua ón suíomh iargúlta"
 
-#: builtin/submodule--helper.c
 msgid "use the 'checkout' update strategy (default)"
 msgstr "úsáid an straitéis nuashonraithe 'tseiceáil' (réamhshocraithe)"
 
-#: builtin/submodule--helper.c
 msgid "use the 'merge' update strategy"
 msgstr "úsáid an straitéis nuashonraithe 'cumaisc'"
 
-#: builtin/submodule--helper.c
 msgid "use the 'rebase' update strategy"
 msgstr "bain úsáid as an straitéis nuashonraithe 'rebase'"
 
-#: builtin/submodule--helper.c
 msgid "create a shallow clone truncated to the specified number of revisions"
 msgstr ""
 "clón éadomhain a chruthú a ghearrtar go dtí an líon sonraithe athbhreithnithe"
 
-#: builtin/submodule--helper.c
 msgid "parallel jobs"
 msgstr "poist chomhthreomhara"
 
-#: builtin/submodule--helper.c
 msgid "whether the initial clone should follow the shallow recommendation"
 msgstr "cibé an chóir don chlón tosaigh an moladh éadrom a leanú"
 
-#: builtin/submodule--helper.c
 msgid "don't print cloning progress"
 msgstr "ná déan dul chun cinn clónaithe a phriontáil"
 
-#: builtin/submodule--helper.c
 msgid "disallow cloning into non-empty directory, implies --init"
 msgstr ""
 "clónú a dhícheadú isteach i eolaire neamh-folamh, tugann le tuiscint --init"
 
-#: builtin/submodule--helper.c
 msgid ""
 "git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] "
 "[-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-"
@@ -16666,55 +14119,42 @@
 "shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] "
 "[--] [<path>...]"
 
-#: builtin/submodule--helper.c submodule.c
 msgid "Failed to resolve HEAD as a valid ref."
 msgstr "Theip ar HEAD a réiteach mar thagartha bailí."
 
-#: builtin/submodule--helper.c
 msgid "git submodule absorbgitdirs [<options>] [<path>...]"
 msgstr "git submodule absorbgitdirs [<options>] [<path>...]"
 
-#: builtin/submodule--helper.c
 msgid "suppress output for setting url of a submodule"
 msgstr "aschur a chur faoi chois chun url fo-mhodúil a shocrú"
 
-#: builtin/submodule--helper.c
 msgid "git submodule set-url [--quiet] <path> <newurl>"
 msgstr "git submodule set-url [--quiet] <path> <newurl>"
 
-#: builtin/submodule--helper.c
 msgid "set the default tracking branch to master"
 msgstr "socraigh an mbrainse rianaithe réamhshocraithe chun"
 
-#: builtin/submodule--helper.c
 msgid "set the default tracking branch"
 msgstr "socraigh an brainse rianaithe réamhshoc"
 
-#: builtin/submodule--helper.c
 msgid "git submodule set-branch [-q|--quiet] (-d|--default) <path>"
 msgstr "git submodule set-branch [-q|--quiet] (-d|--default) <path>"
 
-#: builtin/submodule--helper.c
 msgid "git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>"
 msgstr "git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>"
 
-#: builtin/submodule--helper.c
 msgid "--branch or --default required"
 msgstr "--branch nó --default ag teastáil"
 
-#: builtin/submodule--helper.c
 msgid "print only error messages"
 msgstr "teachtaireachtaí earráide amháin a phrion"
 
-#: builtin/submodule--helper.c
 msgid "force creation"
 msgstr "cruthú fórsa"
 
-#: builtin/submodule--helper.c
 msgid "show whether the branch would be created"
 msgstr "taispeáint an cruthófaí an mbrainse"
 
-#: builtin/submodule--helper.c
 msgid ""
 "git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--"
 "quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>"
@@ -16722,27 +14162,22 @@
 "git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--"
 "quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "creating branch '%s'"
 msgstr "ag cruthú brainse '%s'"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Adding existing repo at '%s' to the index\n"
 msgstr "Ag cur repo atá ann cheana ag '%s' leis an innéacs\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "'%s' already exists and is not a valid git repo"
 msgstr "Tá '%s' ann cheana féin agus ní repo git bailí é"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "A git directory for '%s' is found locally with remote(s):\n"
 msgstr "Faightear eolaire git le haghaidh '%s' go háitiúil le cianda(í):\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid ""
 "If you want to reuse this local git directory instead of cloning again from\n"
@@ -16759,58 +14194,46 @@
 "nó níl tú cinnte cad a chiallaíonn sé seo roghnaigh ainm eile leis an rogha "
 "'--name'."
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Reactivating local git directory for submodule '%s'\n"
 msgstr "Eolaire git áitiúil a athghníomhachtú do fho-mhodúl '%s'\n"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "unable to checkout submodule '%s'"
 msgstr "ní féidir le fo-mhodúl '%s' a sheiceáil"
 
-#: builtin/submodule--helper.c
 msgid "please make sure that the .gitmodules file is in the working tree"
 msgstr "déan cinnte go bhfuil an comhad .gitmodules sa chrann oibre"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Failed to add submodule '%s'"
 msgstr "Theip ar fho-mhodúl '%s' a chur leis"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "Failed to register submodule '%s'"
 msgstr "Theip ar fho-mhodúl '%s' a chlárú"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "'%s' already exists in the index"
 msgstr "Tá '%s' ann cheana féin san innéacs"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "'%s' already exists in the index and is not a submodule"
 msgstr "Tá '%s' ann cheana féin san innéacs agus ní fo-mhodúl é"
 
-#: builtin/submodule--helper.c read-cache.c
 #, c-format
 msgid "'%s' does not have a commit checked out"
 msgstr "Níl tiomantas seiceáilte ag '%s'"
 
-#: builtin/submodule--helper.c
 msgid "branch of repository to add as submodule"
 msgstr "brainse an stór le cur mar fho-mhodúl"
 
-#: builtin/submodule--helper.c
 msgid "allow adding an otherwise ignored submodule path"
 msgstr "ligean cosán fo-mhodúil a neamhaird a chur leis"
 
-#: builtin/submodule--helper.c
 msgid "borrow the objects from reference repositories"
 msgstr "iasacht na rudaí ó stórais tagartha"
 
-#: builtin/submodule--helper.c
 msgid ""
 "sets the submodule's name to the given string instead of defaulting to its "
 "path"
@@ -16818,67 +14241,56 @@
 "socraíonn ainm an fho-mhodúil don teaghrán a thugtar in ionad réamhshocrú ar "
 "a chosán"
 
-#: builtin/submodule--helper.c
 msgid "git submodule add [<options>] [--] <repository> [<path>]"
 msgstr "git submodule add [<options>] [--] <repository> [<path>]"
 
-#: builtin/submodule--helper.c
 msgid "Relative path can only be used from the toplevel of the working tree"
 msgstr "Ní féidir cosán coibhneasta a úsáid ach ó bharr an chrainn oibre"
 
-#: builtin/submodule--helper.c
 #, c-format
 msgid "repo URL: '%s' must be absolute or begin with ./|../"
 msgstr "repo URL: caithfidh '%s' a bheith iomlán nó tosú leis. /| .. /"
 
-#: builtin/submodule--helper.c
+#, c-format
+msgid "submodule name '%s' already used for path '%s'"
+msgstr "tá ainm an fhomhodúil '%s' in úsáid cheana féin don chonair '%s'"
+
 #, c-format
 msgid "'%s' is not a valid submodule name"
 msgstr "Ní ainm bailí fo-mhodúil é '%s'"
 
-#: builtin/submodule--helper.c
 msgid "git submodule--helper <command>"
 msgstr "git submodule--helper <command>"
 
-#: builtin/symbolic-ref.c
 msgid "git symbolic-ref [-m <reason>] <name> <ref>"
 msgstr "git symbolic-ref [-m <reason>] <name> <ref>"
 
-#: builtin/symbolic-ref.c
 msgid "git symbolic-ref [-q] [--short] [--no-recurse] <name>"
 msgstr "git symbolic-ref [-q] [--short] [--no-recurse] <name>"
 
-#: builtin/symbolic-ref.c
 msgid "git symbolic-ref --delete [-q] <name>"
 msgstr "git symbolic-ref --delete [-q] <name>"
 
-#: builtin/symbolic-ref.c
 msgid "suppress error message for non-symbolic (detached) refs"
 msgstr ""
 "teachtaireacht earráide a chur faoi chois le haghaidh tuairimí neamh-"
 "shiombalacha"
 
-#: builtin/symbolic-ref.c
 msgid "delete symbolic ref"
 msgstr "scrios tagairt siombalach"
 
-#: builtin/symbolic-ref.c
 msgid "shorten ref output"
 msgstr "aschur tagairt a ghiorrú"
 
-#: builtin/symbolic-ref.c
 msgid "recursively dereference (default)"
 msgstr "dereference athshlánach (réamhshocraithe)"
 
-#: builtin/symbolic-ref.c builtin/update-ref.c
 msgid "reason"
 msgstr "cúis"
 
-#: builtin/symbolic-ref.c builtin/update-ref.c
 msgid "reason of the update"
 msgstr "cúis an nuashonraithe"
 
-#: builtin/tag.c
 msgid ""
 "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n"
 "        [(--trailer <token>[(=|:)<value>])...]\n"
@@ -16888,37 +14300,31 @@
 "        [(--trailer <token>[(=|:)<value>])...]\n"
 "        <tagname> [<commit> | <object>]"
 
-#: builtin/tag.c
 msgid "git tag -d <tagname>..."
 msgstr "git tag -d <tagname>..."
 
-#: builtin/tag.c
 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 ""
-"<commit>tag git [-n [<num>]] -l [--conté] [--no-conté<commit>]\n"
-" <options>[--points-ag<object>] [--column [=] | --no-column]\n"
-" <key><format>[--create-reflog] [--sort=] [--format =]\n"
-" <pattern>[--cumaisc<commit>] [--no-cumaisc] [...<commit>]"
+"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>...]"
 
-#: builtin/tag.c
 msgid "git tag -v [--format=<format>] <tagname>..."
-msgstr "<format><tagname>tag git -v [--format =]..."
+msgstr "git tag -v [--format=<format>] <tagname>..."
 
-#: builtin/tag.c
 #, c-format
 msgid "tag '%s' not found."
 msgstr "níor aimsíodh tag '%s'."
 
-#: builtin/tag.c
 #, c-format
 msgid "Deleted tag '%s' (was %s)\n"
 msgstr "Clib scriosta '%s' (bhí %s)\n"
 
-#: builtin/tag.c
 #, c-format
 msgid ""
 "\n"
@@ -16931,7 +14337,6 @@
 "  %s\n"
 "Déanfar neamhaird ar línte a thosaíonn le '%s'.\n"
 
-#: builtin/tag.c
 #, c-format
 msgid ""
 "\n"
@@ -16946,11 +14351,9 @@
 "Coinneofar línte a thosaíonn le '%s'; féadfaidh tú iad a bhaint féin más "
 "mian leat.\n"
 
-#: builtin/tag.c
 msgid "unable to sign the tag"
-msgstr "in ann an chlib a shíniú"
+msgstr "ní féidir an clib a shíniú"
 
-#: builtin/tag.c
 #, c-format
 msgid ""
 "You have created a nested tag. The object referred to by your new tag is\n"
@@ -16964,351 +14367,268 @@
 "\n"
 " clib git -f %s %s^ {}"
 
-#: builtin/tag.c
 msgid "bad object type."
 msgstr "droch-chineál réad."
 
-#: builtin/tag.c
 msgid "no tag message?"
 msgstr "gan aon teachtaireacht clib?"
 
-#: builtin/tag.c
 #, c-format
 msgid "The tag message has been left in %s\n"
 msgstr "Tá an teachtaireacht clib fágtha i %s\n"
 
-#: builtin/tag.c
 msgid "list tag names"
 msgstr "ainmneacha clibeanna liosta"
 
-#: builtin/tag.c
 msgid "print <n> lines of each tag message"
 msgstr "<n>línte priontála de gach teachtaireacht clib"
 
-#: builtin/tag.c
 msgid "delete tags"
 msgstr "clibeanna a scriosadh"
 
-#: builtin/tag.c
 msgid "verify tags"
 msgstr "clibeanna a fíorú"
 
-#: builtin/tag.c
 msgid "Tag creation options"
 msgstr "Roghanna cruthaithe clibeanna"
 
-#: builtin/tag.c
 msgid "annotated tag, needs a message"
 msgstr "clib anótáilte, teastaíonn teachtaireacht"
 
-#: builtin/tag.c
 msgid "tag message"
 msgstr "teachtaireacht tag"
 
-#: builtin/tag.c
 msgid "force edit of tag message"
 msgstr "eagarthóireacht fórsa ar theachtaireacht"
 
-#: builtin/tag.c
 msgid "annotated and GPG-signed tag"
 msgstr "clib anótáilte agus sínithe GPS"
 
-#: builtin/tag.c
 msgid "use another key to sign the tag"
 msgstr "bain úsáid as eochair eile chun an chlib a shíniú"
 
-#: builtin/tag.c
 msgid "replace the tag if exists"
 msgstr "athsholáthar an chlib má tá sé ann"
 
-#: builtin/tag.c builtin/update-ref.c
 msgid "create a reflog"
 msgstr "cruthaigh reflog"
 
-#: builtin/tag.c
 msgid "Tag listing options"
 msgstr "Roghanna liostaithe clibeanna"
 
-#: builtin/tag.c
 msgid "show tag list in columns"
 msgstr "taispeáin liosta clibeanna i gcolúin"
 
-#: builtin/tag.c
 msgid "print only tags that contain the commit"
 msgstr "clibeanna a phriontáil ach ina bhfuil an tiomantas"
 
-#: builtin/tag.c
 msgid "print only tags that don't contain the commit"
 msgstr "clibeanna nach bhfuil an tiomantas a phriontáil ach amháin"
 
-#: builtin/tag.c
 msgid "print only tags that are merged"
 msgstr "clibeanna a chumasc amháin a phriontáil"
 
-#: builtin/tag.c
 msgid "print only tags that are not merged"
 msgstr "clibeanna nach ndéantar cumaisc a phriontáil ach amháin"
 
-#: builtin/tag.c
 msgid "print only tags of the object"
 msgstr "clibeanna den réad amháin a phriontáil"
 
-#: builtin/tag.c
 msgid "could not start 'git column'"
 msgstr "ní fhéadfaí 'git column' a thosú"
 
-#: builtin/tag.c
 #, c-format
 msgid "the '%s' option is only allowed in list mode"
 msgstr "ní cheadaítear an rogha '%s' ach i mód liosta"
 
-#: builtin/tag.c
 #, c-format
 msgid "'%s' is not a valid tag name."
 msgstr "Ní ainm bailí clibeanna é '%s'."
 
-#: builtin/tag.c
 #, c-format
 msgid "tag '%s' already exists"
 msgstr "tá clib '%s' ann cheana féin"
 
-#: builtin/tag.c sequencer.c
 #, c-format
 msgid "Invalid cleanup mode %s"
 msgstr "Modh glantacháin neamhbhailí %s"
 
-#: builtin/tag.c
 #, c-format
 msgid "Updated tag '%s' (was %s)\n"
 msgstr "Clib nuashonraithe '%s' (bhí %s)\n"
 
-#: builtin/unpack-objects.c
 msgid "pack exceeds maximum allowed size"
 msgstr "sáraíonn an pacáiste an méid uasta a"
 
-#: builtin/unpack-objects.c
 msgid "failed to write object in stream"
 msgstr "theip ar réad a scríobh sa sruth"
 
-#: builtin/unpack-objects.c
 #, c-format
 msgid "inflate returned (%d)"
 msgstr "inflate ar ais (%d)"
 
-#: builtin/unpack-objects.c
 msgid "invalid blob object from stream"
 msgstr "réad blob neamhbhailí ón sruth"
 
-#: builtin/unpack-objects.c
 msgid "Unpacking objects"
 msgstr "Rudaí a dhíphacáil"
 
-#: builtin/update-index.c
 #, c-format
 msgid "failed to create directory %s"
 msgstr "theip ar eolaire %s a chruthú"
 
-#: builtin/update-index.c
 #, c-format
 msgid "failed to delete file %s"
 msgstr "theip ar chomhad %s a scriosadh"
 
-#: builtin/update-index.c
 #, c-format
 msgid "failed to delete directory %s"
 msgstr "theip ar eolaire %s a scriosadh"
 
-#: builtin/update-index.c
 #, c-format
 msgid "Testing mtime in '%s' "
 msgstr "Tástáil mtime i '%s' "
 
-#: builtin/update-index.c
 msgid "directory stat info does not change after adding a new file"
 msgstr "ní athraíonn eolas stat eolaire tar éis comhad nua a chur leis"
 
-#: builtin/update-index.c
 msgid "directory stat info does not change after adding a new directory"
 msgstr "ní athraíonn eolas stat eolaire tar éis eolaire nua a chur leis"
 
-#: builtin/update-index.c
 msgid "directory stat info changes after updating a file"
 msgstr "athraíonn faisnéis eolaire stat tar éis comhad a nuashonrú"
 
-#: builtin/update-index.c
 msgid "directory stat info changes after adding a file inside subdirectory"
 msgstr ""
 "athraíonn eolas stat eolaire tar éis comhad a chur taobh istigh den fho-"
 "eolaire"
 
-#: builtin/update-index.c
 msgid "directory stat info does not change after deleting a file"
 msgstr "ní athraíonn eolas stat eolaire tar éis comhad a scriosadh"
 
-#: builtin/update-index.c
 msgid "directory stat info does not change after deleting a directory"
 msgstr "ní athraíonn eolas stat eolaire tar éis eolaire a scriosadh"
 
-#: builtin/update-index.c
 msgid " OK"
 msgstr " CEART GO LEOR"
 
-#: builtin/update-index.c
 msgid "git update-index [<options>] [--] [<file>...]"
-msgstr "<file>git update-index [<options>] [--] [...]"
+msgstr "git update-index [<options>] [--] [<file>...]"
 
-#: builtin/update-index.c
 msgid "continue refresh even when index needs update"
 msgstr "leanúint ar aghaidh ar aghaidh ag athnuachan fiú nu"
 
-#: builtin/update-index.c
 msgid "refresh: ignore submodules"
 msgstr "athnuachan: neamhaird a dhéanamh ar fho"
 
-#: builtin/update-index.c
 msgid "do not ignore new files"
 msgstr "ná déan neamhaird de chomhaid nua"
 
-#: builtin/update-index.c
 msgid "let files replace directories and vice-versa"
 msgstr "lig do chomhaid eolairí in ionad agus a mhalairt"
 
-#: builtin/update-index.c
 msgid "notice files missing from worktree"
 msgstr "fógra comhaid atá ar iarraidh ón gcrann oibre"
 
-#: builtin/update-index.c
 msgid "refresh even if index contains unmerged entries"
 msgstr "athnuachan fiú má tá iontrálacha neamh-iontrálacha"
 
-#: builtin/update-index.c
 msgid "refresh stat information"
 msgstr "faisnéis stáit a athnuachan"
 
-#: builtin/update-index.c
 msgid "like --refresh, but ignore assume-unchanged setting"
 msgstr "cosúil le --refresh, ach déan neamhaird de shuíomh gan athrú"
 
-#: builtin/update-index.c
 msgid "<mode>,<object>,<path>"
 msgstr "<mode>,<object>, <path>"
 
-#: builtin/update-index.c
 msgid "add the specified entry to the index"
 msgstr "cuir an iontráil sonraithe leis an innéacs"
 
-#: builtin/update-index.c
 msgid "mark files as \"not changing\""
 msgstr "comhad a mharcáil mar “gan athrú”"
 
-#: builtin/update-index.c
 msgid "clear assumed-unchanged bit"
 msgstr "giotán soiléir glactha gan athrú"
 
-#: builtin/update-index.c
 msgid "mark files as \"index-only\""
 msgstr "comhad a mharcáil mar “innéacs amháin”"
 
-#: builtin/update-index.c
 msgid "clear skip-worktree bit"
 msgstr "giotán crainn oibre scipeála soiléir"
 
-#: builtin/update-index.c
 msgid "do not touch index-only entries"
 msgstr "ná déan teagmháil le iontrálacha innéacs amháin"
 
-#: builtin/update-index.c
 msgid "add to index only; do not add content to object database"
 msgstr "cuir le hinnéacs amháin; ná cuir ábhar le bunachar sonraí réada"
 
-#: builtin/update-index.c
 msgid "remove named paths even if present in worktree"
 msgstr "bain cosáin ainmnithe fiú má tá sé i gcrann oibre"
 
-#: builtin/update-index.c
 msgid "with --stdin: input lines are terminated by null bytes"
 msgstr "le --stdin: cuirtear deireadh le línte ionchuir le bytes null"
 
-#: builtin/update-index.c
 msgid "read list of paths to be updated from standard input"
 msgstr "léigh liosta na gcosáin atá le nuashonrú ó ionchur caighdeánach"
 
-#: builtin/update-index.c
 msgid "add entries from standard input to the index"
 msgstr "cuir iontrálacha ón ionchur caighdeánach leis an innéacs"
 
-#: builtin/update-index.c
 msgid "repopulate stages #2 and #3 for the listed paths"
 msgstr "céimeanna #2 agus #3 a athdhíonrú do na cosáin liostaithe"
 
-#: builtin/update-index.c
 msgid "only update entries that differ from HEAD"
 msgstr "ach iontrálacha a nuashonrú atá difriúil ó HEAD"
 
-#: builtin/update-index.c
 msgid "ignore files missing from worktree"
 msgstr "neamhaird a dhéanamh ar chomhaid atá in easnamh"
 
-#: builtin/update-index.c
 msgid "report actions to standard output"
 msgstr "gníomhartha a thuairisciú go dtí"
 
-#: builtin/update-index.c
 msgid "(for porcelains) forget saved unresolved conflicts"
 msgstr "(le haghaidh poircealláin) déan dearmad ar choimhlintí gan réiteach"
 
-#: builtin/update-index.c
 msgid "write index in this format"
 msgstr "scríobh innéacs san fhormáid seo"
 
-#: builtin/update-index.c
 msgid "report on-disk index format version"
 msgstr "leagan formáid innéacs ar dhiosca tuairisc"
 
-#: builtin/update-index.c
 msgid "enable or disable split index"
 msgstr "innéacs scoilte a chumasú nó a dh"
 
-#: builtin/update-index.c
 msgid "enable/disable untracked cache"
 msgstr "taisce neamhrianaithe a chumasú/a dhíchumasú"
 
-#: builtin/update-index.c
 msgid "test if the filesystem supports untracked cache"
 msgstr "tástáil an dtacaíonn an córas comhaid le taisce neamhrianaithe"
 
-#: builtin/update-index.c
 msgid "enable untracked cache without testing the filesystem"
 msgstr "taisce neamhrianaithe a chumasú gan an córas comhaid a thástáil"
 
-#: builtin/update-index.c
 msgid "write out the index even if is not flagged as changed"
 msgstr ""
 "scríobh amach an t-innéacs fiú mura bhfuil sé brataithe mar a athraítear"
 
-#: builtin/update-index.c
 msgid "enable or disable file system monitor"
 msgstr "monatóireacht chórais chomhaid a chumasú"
 
-#: builtin/update-index.c
 msgid "mark files as fsmonitor valid"
 msgstr "comhad a mharcáil mar fsmonitor bailí"
 
-#: builtin/update-index.c
 msgid "clear fsmonitor valid bit"
 msgstr "giotán bailí fsmonitor soiléir"
 
-#: builtin/update-index.c
 #, c-format
 msgid "%d\n"
 msgstr "%d\n"
 
-#: builtin/update-index.c
 #, c-format
 msgid "index-version: was %d, set to %d"
 msgstr "leagan innéacs: bhí %d, socraithe go %d"
 
-#: builtin/update-index.c
 msgid ""
 "core.splitIndex is set to false; remove or change it, if you really want to "
 "enable split index"
@@ -17316,7 +14636,6 @@
 "tá core.splitIndex socraithe go bréagach; bain nó athraigh é, más mian leat "
 "innéacs scoilte a chumasú i ndáiríre"
 
-#: builtin/update-index.c
 msgid ""
 "core.splitIndex is set to true; remove or change it, if you really want to "
 "disable split index"
@@ -17324,7 +14643,6 @@
 "tá core.splitIndex socraithe go fíor; bain nó athraigh é, más mian leat "
 "innéacs scoilte a dhíchumasú"
 
-#: builtin/update-index.c
 msgid ""
 "core.untrackedCache is set to true; remove or change it, if you really want "
 "to disable the untracked cache"
@@ -17332,11 +14650,9 @@
 "tá core.untrackedCache  go fíor; bain nó athraigh é, más mian leat an taisce "
 "neamhrianaithe a dhíchumasú"
 
-#: builtin/update-index.c
 msgid "Untracked cache disabled"
 msgstr "Taisce neamhrianaithe míchumasaithe"
 
-#: builtin/update-index.c
 msgid ""
 "core.untrackedCache is set to false; remove or change it, if you really want "
 "to enable the untracked cache"
@@ -17344,69 +14660,54 @@
 "tá core.untrackedCache socraithe go bréagach; bain nó athraigh é, más mian "
 "leat an taisce neamhrianaithe a chumasú"
 
-#: builtin/update-index.c
 #, c-format
 msgid "Untracked cache enabled for '%s'"
 msgstr "Cumasaíodh taisce neamhrianaithe do '%s'"
 
-#: builtin/update-index.c
 msgid "core.fsmonitor is unset; set it if you really want to enable fsmonitor"
 msgstr ""
 "tá core.fsmonitor díshocraithe; socraigh é más mian leat fsmonitor a chumasú "
 "i ndáiríre"
 
-#: builtin/update-index.c
 msgid "fsmonitor enabled"
 msgstr "fsmonitor cumasaithe"
 
-#: builtin/update-index.c
 msgid ""
 "core.fsmonitor is set; remove it if you really want to disable fsmonitor"
 msgstr ""
 "tá core.fsmonitor socraithe; bain é más mian leat fsmonitor a dhíchumasú i "
 "ndáiríre"
 
-#: builtin/update-index.c
 msgid "fsmonitor disabled"
 msgstr "fsmonitor míchumasaithe"
 
-#: builtin/update-ref.c
 msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
-msgstr "<refname><old-oid>git update-ref [<options>] -d []"
+msgstr "git update-ref [<options>] -d <refname> [<old-oid>]"
 
-#: builtin/update-ref.c
 msgid "git update-ref [<options>]    <refname> <new-oid> [<old-oid>]"
-msgstr "<refname><new-oid><old-oid>git update-ref [<options>] []"
+msgstr "git update-ref [<options>]    <refname> <new-oid> [<old-oid>]"
 
-#: builtin/update-ref.c
 msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]"
 msgstr "git update-ref [<options>] --stdin [-z] [--batch-updates]"
 
-#: builtin/update-ref.c
 msgid "delete the reference"
 msgstr "scrios an tagairt"
 
-#: builtin/update-ref.c
 msgid "update <refname> not the one it points to"
 msgstr "nuashon <refname>raigh ní an ceann a thugann sé in iúl"
 
-#: builtin/update-ref.c
 msgid "stdin has NUL-terminated arguments"
 msgstr "tá argóintí ag foirceannadh NUL ag stdin"
 
-#: builtin/update-ref.c
 msgid "read updates from stdin"
 msgstr "léigh nuashonruithe ó stdin"
 
-#: builtin/update-ref.c
 msgid "batch reference updates"
 msgstr "nuashonruithe tagairt baisc"
 
-#: builtin/update-server-info.c
 msgid "update the info files from scratch"
 msgstr "nuashonraigh na comhaid faisnéise ón tús"
 
-#: builtin/upload-pack.c
 msgid ""
 "git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n"
 "                [--advertise-refs] <directory>"
@@ -17414,57 +14715,44 @@
 "git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n"
 "                [--advertise-refs] <directory>"
 
-#: builtin/upload-pack.c t/helper/test-serve-v2.c
 msgid "quit after a single request/response exchange"
 msgstr "scor tar éis iarrata/malartú freagartha amháin"
 
-#: builtin/upload-pack.c
 msgid "serve up the info/refs for git-http-backend"
 msgstr "freastal suas ar na faisnéise/réimsí le haghaidh git-http-backend"
 
-#: builtin/upload-pack.c
 msgid "do not try <directory>/.git/ if <directory> is no Git directory"
 msgstr ""
 "ná déan iarracht <directory>/.git/ mura bhfuil aon eolaire G <directory> it "
 "ann"
 
-#: builtin/upload-pack.c
 msgid "interrupt transfer after <n> seconds of inactivity"
 msgstr "cur isteach ar aistriú tar éis so <n>icind neamhghníomhach"
 
-#: builtin/verify-commit.c
 msgid "git verify-commit [-v | --verbose] [--raw] <commit>..."
 msgstr "git verify-commit [-v | --verbose] [--raw] <commit>..."
 
-#: builtin/verify-commit.c
 msgid "print commit contents"
 msgstr "ábhair tiomanta priontála"
 
-#: builtin/verify-commit.c builtin/verify-tag.c
 msgid "print raw gpg status output"
 msgstr "aschur stádas amh-gpg a phriontáil"
 
-#: builtin/verify-pack.c
 msgid "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..."
 msgstr "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..."
 
-#: builtin/verify-pack.c
 msgid "verbose"
 msgstr "eolach"
 
-#: builtin/verify-pack.c
 msgid "show statistics only"
 msgstr "taispeáin staitisticí amháin"
 
-#: builtin/verify-tag.c
 msgid "git verify-tag [-v | --verbose] [--format=<format>] [--raw] <tag>..."
-msgstr "<format><tag>git verify-tag [-v | --verbose] [--format =] [--raw]..."
+msgstr "git verify-tag [-v | --verbose] [--format=<format>] [--raw] <tag>..."
 
-#: builtin/verify-tag.c
 msgid "print tag contents"
 msgstr "ábhar clib priontáil"
 
-#: builtin/worktree.c
 msgid ""
 "git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]\n"
 "                 [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]"
@@ -17472,39 +14760,30 @@
 "git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]\n"
 "                 [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]"
 
-#: builtin/worktree.c
 msgid "git worktree list [-v | --porcelain [-z]]"
 msgstr "liosta crann oibre git [-v | --poirceallán [-z]]"
 
-#: builtin/worktree.c
 msgid "git worktree lock [--reason <string>] <worktree>"
-msgstr "<string>glas crann oibre git [--reason] <worktree>"
+msgstr "git worktree lock [--reason <string>] <worktree>"
 
-#: builtin/worktree.c
 msgid "git worktree move <worktree> <new-path>"
-msgstr "gluaiseacht sraith oibre git <worktree><new-path>"
+msgstr "git worktree move <worktree> <new-path>"
 
-#: builtin/worktree.c
 msgid "git worktree prune [-n] [-v] [--expire <expire>]"
-msgstr "<expire>git worktree prun [-n] [-v] [--dul in éag]"
+msgstr "git worktree prune [-n] [-v] [--expire <expire>]"
 
-#: builtin/worktree.c
 msgid "git worktree remove [-f] <worktree>"
-msgstr "git worktree a bhaint [-f] <worktree>"
+msgstr "git worktree remove [-f] <worktree>"
 
-#: builtin/worktree.c
 msgid "git worktree repair [<path>...]"
-msgstr "deisiú crainn oibre git [<path>...]"
+msgstr "git worktree repair [<path>...]"
 
-#: builtin/worktree.c
 msgid "git worktree unlock <worktree>"
-msgstr "díghlasáil git worktree <worktree>"
+msgstr "git worktree unlock <worktree>"
 
-#: builtin/worktree.c
 msgid "No possible source branch, inferring '--orphan'"
 msgstr "Níl aon bhrainse foinse féideartha, ag tabhairt faoi deara '--orphan'"
 
-#: builtin/worktree.c
 #, c-format
 msgid ""
 "If you meant to create a worktree containing a new unborn branch\n"
@@ -17521,7 +14800,6 @@
 "\n"
 "    git worktree add --orphan -b %s %s\n"
 
-#: builtin/worktree.c
 #, c-format
 msgid ""
 "If you meant to create a worktree containing a new unborn branch\n"
@@ -17538,30 +14816,24 @@
 "\n"
 "    git worktree add --orphan %s\n"
 
-#: builtin/worktree.c
 #, c-format
 msgid "Removing %s/%s: %s"
 msgstr "Ag baint %s/%s: %s"
 
-#: builtin/worktree.c
 msgid "report pruned working trees"
 msgstr "crainn oibre gearrtha a thuairisciú"
 
-#: builtin/worktree.c
 msgid "expire working trees older than <time>"
 msgstr "dul in éag crainn oibre níos sine ná <time>"
 
-#: builtin/worktree.c
 #, c-format
 msgid "'%s' already exists"
 msgstr "Tá '%s' ann cheana féin"
 
-#: builtin/worktree.c
 #, c-format
 msgid "unusable worktree destination '%s'"
 msgstr "ceann scríbe crainn oibre neamhúsáidte '%s'"
 
-#: builtin/worktree.c
 #, c-format
 msgid ""
 "'%s' is a missing but locked worktree;\n"
@@ -17571,7 +14843,6 @@
 "bain úsáid as '%s -f 'chun athshealbhú, nó' díghlasáil 'agus' bearradh 'nó' "
 "bhaint 'chun a ghlanadh"
 
-#: builtin/worktree.c
 #, c-format
 msgid ""
 "'%s' is a missing but already registered worktree;\n"
@@ -17581,63 +14852,47 @@
 "bain úsáid as '%s -f' chun athshlánú, nó 'bearradh' nó 'bhaint' chun a "
 "ghlanadh"
 
-#: builtin/worktree.c
 #, c-format
 msgid "failed to copy '%s' to '%s'; sparse-checkout may not work correctly"
 msgstr ""
 "theip ar '%s' a chóipeáil go '%s'; b'fhéidir nach n-oibreoidh an tseiceáil "
 "neamhchoitianta i gceart"
 
-#: builtin/worktree.c
 #, c-format
 msgid "failed to copy worktree config from '%s' to '%s'"
 msgstr "theip ar chumraíocht crann oibre a chóipeáil ó '%s' go '%s'"
 
-#: builtin/worktree.c
 #, c-format
 msgid "failed to unset '%s' in '%s'"
 msgstr "theip ar '%s' a dhíshocrú i '%s'"
 
-#: builtin/worktree.c
 #, c-format
 msgid "could not create directory of '%s'"
 msgstr "ní raibh in ann eolaire de '%s' a chruthú"
 
-#: builtin/worktree.c
 msgid "initializing"
 msgstr "a thionscnamh"
 
-#: builtin/worktree.c
 #, c-format
 msgid "could not find created worktree '%s'"
 msgstr "ní raibh an crann oibre cruthaithe '%s' a aimsiú"
 
-#: builtin/worktree.c
 #, c-format
 msgid "Preparing worktree (new branch '%s')"
 msgstr "Crann oibre a ullmhú (brainse nua '%s')"
 
-#: builtin/worktree.c
 #, c-format
 msgid "Preparing worktree (resetting branch '%s'; was at %s)"
 msgstr "Ullmhú crann oibre (athshocrú brainse '%s'; bhí ag %s)"
 
-#: builtin/worktree.c
 #, c-format
 msgid "Preparing worktree (checking out '%s')"
 msgstr "Crann oibre a ullmhú (seiceáil '%s')"
 
-#: builtin/worktree.c
-#, c-format
-msgid "unreachable: invalid reference: %s"
-msgstr "unrochtana: tagairt neamhbhailí: %s"
-
-#: builtin/worktree.c
 #, c-format
 msgid "Preparing worktree (detached HEAD %s)"
 msgstr "Crann oibre a ullmhú (CEAD scoite %s)"
 
-#: builtin/worktree.c
 #, c-format
 msgid ""
 "HEAD points to an invalid (or orphaned) reference.\n"
@@ -17645,10 +14900,9 @@
 "HEAD contents: '%s'"
 msgstr ""
 "Tugann HEAD in iúl do thagairt neamhbhailí (nó dílleachta).\n"
-"Conair CEAD: '%s'\n"
-"Ábhar CEAD: '%s'"
+"Conair HEAD: '%s'\n"
+"Ábhar HEAD: '%s'"
 
-#: builtin/worktree.c
 msgid ""
 "No local or remote refs exist despite at least one remote\n"
 "present, stopping; use 'add -f' to override or fetch a remote first"
@@ -17658,121 +14912,94 @@
 "láthair, ag stopadh; bain úsáid as 'add -f' chun iargúlta a shárú nó a fháil "
 "ar dtús"
 
-#: builtin/worktree.c
 msgid "checkout <branch> even if already checked out in other worktree"
 msgstr ""
 "seiceáil <branch>fiú má tá sé seiceáilte cheana féin i gcrann oibre eile"
 
-#: builtin/worktree.c
 msgid "create a new branch"
 msgstr "brainse nua a chruthú"
 
-#: builtin/worktree.c
 msgid "create or reset a branch"
 msgstr "brainse a chruthú nó a athshocrú"
 
-#: builtin/worktree.c
 msgid "create unborn branch"
 msgstr "cruthú brainse gan breith"
 
-#: builtin/worktree.c
 msgid "populate the new working tree"
 msgstr "an crann oibre nua a dhaonrú"
 
-#: builtin/worktree.c
 msgid "keep the new working tree locked"
 msgstr "coinnigh an crann oibre nua faoi ghlas"
 
-#: builtin/worktree.c
 msgid "reason for locking"
 msgstr "cúis le glasáil"
 
-#: builtin/worktree.c
 msgid "set up tracking mode (see git-branch(1))"
-msgstr "modh rianaithe a bhunú (féach git-branch (1))"
+msgstr "socraigh mód rianaithe (féach git-branch(1))"
 
-#: builtin/worktree.c
 msgid "try to match the new branch name with a remote-tracking branch"
 msgstr ""
 "déan iarracht ainm nua na brainse a mheaitseáil le brainse cianrianaithe"
 
-#: builtin/worktree.c
 msgid "use relative paths for worktrees"
 msgstr "úsáid cosáin choibhneasta do chrainn oibre"
 
-#: builtin/worktree.c diff.c parse-options.c
 #, c-format
 msgid "options '%s', '%s', and '%s' cannot be used together"
 msgstr "ní féidir roghanna '%s', '%s', agus '%s' a úsáid le chéile"
 
-#: builtin/worktree.c
 #, c-format
 msgid "option '%s' and commit-ish cannot be used together"
 msgstr "ní féidir rogha '%s' agus comm-ish a úsáid le chéile"
 
-#: builtin/worktree.c
 msgid "added with --lock"
 msgstr "cuireadh leis le --lock"
 
-#: builtin/worktree.c
 msgid "--[no-]track can only be used if a new branch is created"
 msgstr "Ní féidir --[no-]rian a úsáid ach amháin má chruthaítear brainse nua"
 
-#: builtin/worktree.c
 msgid "show extended annotations and reasons, if available"
 msgstr "anótaí agus cúiseanna leathnaithe a thaispeáint, má tá sé ar fáil"
 
-#: builtin/worktree.c
 msgid "add 'prunable' annotation to worktrees older than <time>"
 msgstr "cuir anótáil 'prunable' le crainn oibre níos sine ná <time>"
 
-#: builtin/worktree.c
 msgid "terminate records with a NUL character"
 msgstr "deireadh a chur le taifid le carachtar NUL"
 
-#: builtin/worktree.c
 #, c-format
 msgid "'%s' is not a working tree"
 msgstr "Ní crann oibre é '%s'"
 
-#: builtin/worktree.c
 msgid "The main working tree cannot be locked or unlocked"
 msgstr "Ní féidir an príomhchrann oibre a ghlasáil nó a dhíghlasáil"
 
-#: builtin/worktree.c
 #, c-format
 msgid "'%s' is already locked, reason: %s"
 msgstr "Tá '%s' faoi ghlas cheana féin, cúis: %s"
 
-#: builtin/worktree.c
 #, c-format
 msgid "'%s' is already locked"
 msgstr "Tá '%s' faoi ghlas cheana féin"
 
-#: builtin/worktree.c
 #, c-format
 msgid "'%s' is not locked"
 msgstr "Níl '%s' faoi ghlas"
 
-#: builtin/worktree.c
 msgid "working trees containing submodules cannot be moved or removed"
 msgstr "ní féidir crainn oibre ina bhfuil fo-mhodúil a bhogadh ná a bhaint"
 
-#: builtin/worktree.c
 msgid "force move even if worktree is dirty or locked"
 msgstr "bogadh fórsa fiú má tá crann oibre salach nó faoi ghlas"
 
-#: builtin/worktree.c
 #, c-format
 msgid "'%s' is a main working tree"
 msgstr "Is príomhchrann oibre é '%s'"
 
-#: builtin/worktree.c
 #, c-format
 msgid "could not figure out destination name from '%s'"
 msgstr "ní fhéadfaí ainm ceann scríbe a fháil amach ó '%s'"
 
-#: builtin/worktree.c
 #, c-format
 msgid ""
 "cannot move a locked working tree, lock reason: %s\n"
@@ -17781,7 +15008,6 @@
 "ní féidir crann oibre faoi ghlas a bhogadh, cúis ghlasála: %s\n"
 "bain úsáid as 'move -f -f' chun athshárú nó a dhíghlasáil ar dtús"
 
-#: builtin/worktree.c
 msgid ""
 "cannot move a locked working tree;\n"
 "use 'move -f -f' to override or unlock first"
@@ -17789,38 +15015,31 @@
 "ní féidir le crann oibre faoi ghlas a bhogadh;\n"
 "bain úsáid as 'move -f -f' chun athshárú nó a dhíghlasáil ar dtús"
 
-#: builtin/worktree.c
 #, c-format
 msgid "validation failed, cannot move working tree: %s"
 msgstr "theip ar bhailíochtú, ní féidir crann oibre a bhogadh: %s"
 
-#: builtin/worktree.c
 #, c-format
 msgid "failed to move '%s' to '%s'"
 msgstr "theip ar '%s' a bhogadh go '%s'"
 
-#: builtin/worktree.c
 #, c-format
 msgid "failed to run 'git status' on '%s'"
 msgstr "theip ar 'git status' a reáchtáil ar '%s'"
 
-#: builtin/worktree.c
 #, c-format
 msgid "'%s' contains modified or untracked files, use --force to delete it"
 msgstr ""
 "Tá comhaid modhnaithe nó neamhrianaithe i '%s', bain úsáid as --force chun é "
 "a scriosadh"
 
-#: builtin/worktree.c
 #, c-format
 msgid "failed to run 'git status' on '%s', code %d"
 msgstr "theip ar 'git status' a reáchtáil ar '%s', cód %d"
 
-#: builtin/worktree.c
 msgid "force removal even if worktree is dirty or locked"
 msgstr "bhaint fórsa fiú má tá crann oibre salach nó faoi ghlas"
 
-#: builtin/worktree.c
 #, c-format
 msgid ""
 "cannot remove a locked working tree, lock reason: %s\n"
@@ -17829,7 +15048,6 @@
 "ní féidir crann oibre faoi ghlas a bhaint, cúis ghlasála: %s\n"
 "bain úsáid as 'remove -f -f' chun athshárú nó a dhíghlasáil ar dtús"
 
-#: builtin/worktree.c
 msgid ""
 "cannot remove a locked working tree;\n"
 "use 'remove -f -f' to override or unlock first"
@@ -17837,134 +15055,102 @@
 "ní féidir crann oibre faoi ghlas a bhaint;\n"
 "bain úsáid as 'remove -f -f' chun athshárú nó a dhíghlasáil ar dtús"
 
-#: builtin/worktree.c
 #, c-format
 msgid "validation failed, cannot remove working tree: %s"
 msgstr "theip ar bhailíochtú, ní féidir crann oibre a bhaint: %s"
 
-#: builtin/worktree.c
 #, c-format
 msgid "repair: %s: %s"
 msgstr "deisiú: %s: %s"
 
-#: builtin/worktree.c
 #, c-format
 msgid "error: %s: %s"
 msgstr "earráid: %s: %s"
 
-#: builtin/write-tree.c
 msgid "git write-tree [--missing-ok] [--prefix=<prefix>/]"
 msgstr "git write-tree [--missing-ok] [--prefix=<prefix>/]"
 
-#: builtin/write-tree.c
 msgid "<prefix>/"
 msgstr "<prefix>/"
 
-#: builtin/write-tree.c
 msgid "write tree object for a subdirectory <prefix>"
 msgstr "scríobh réad crann le haghaidh fo-eolaire <prefix>"
 
-#: builtin/write-tree.c
 msgid "only useful for debugging"
 msgstr "ach úsáideach le haghaidh dífhabhtú"
 
-#: bulk-checkin.c
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "core.fsyncMethod = ní thacaítear leis an bhaisc ar an ardán seo"
-
-#: bundle-uri.c
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
 msgstr "ní fhéadfaí eochair liosta beartán %s a pháirseáil le luach '%s'"
 
-#: bundle-uri.c
 #, c-format
 msgid "bundle list at '%s' has no mode"
 msgstr "níl aon mhodh ag liosta beartán ag '%s'"
 
-#: bundle-uri.c
 msgid "failed to create temporary file"
 msgstr "theip ar chomhad sealadach a chruthú"
 
-#: bundle-uri.c
 msgid "insufficient capabilities"
 msgstr "cumais neamhleor"
 
-#: bundle-uri.c
 #, c-format
 msgid "file downloaded from '%s' is not a bundle"
 msgstr "ní beartán é an comhad a íoslódáladh ó '%s'"
 
-#: bundle-uri.c
 msgid "failed to store maximum creation token"
 msgstr "theip ar an comhartha cruthaithe uasta a stórá"
 
-#: bundle-uri.c
 #, c-format
 msgid "unrecognized bundle mode from URI '%s'"
 msgstr "modh beartán neamhaithnithe ó URI '%s'"
 
-#: bundle-uri.c
 #, c-format
 msgid "exceeded bundle URI recursion limit (%d)"
 msgstr "sháraigh teorainn athshlánaithe URI beartán (%d)"
 
-#: bundle-uri.c
 #, c-format
 msgid "failed to download bundle from URI '%s'"
 msgstr "theip ar an mbeartán a íoslódáil ó URI '%s'"
 
-#: bundle-uri.c
 #, c-format
 msgid "file at URI '%s' is not a bundle or bundle list"
 msgstr "comhad ag URI ní beacán nó liosta beartán é '%s'"
 
-#: bundle-uri.c
 #, c-format
 msgid "bundle-uri: unexpected argument: '%s'"
 msgstr "bundle-uri: argóint gan choinne: '%s'"
 
-#: bundle-uri.c
 msgid "bundle-uri: expected flush after arguments"
 msgstr "bundle-uri: súil le sruth tar éis argóintí"
 
-#: bundle-uri.c
 msgid "bundle-uri: got an empty line"
 msgstr "bundle-uri: got an líne folamh"
 
-#: bundle-uri.c
 msgid "bundle-uri: line is not of the form 'key=value'"
 msgstr "bundle-uri: níl an líne den fhoirm 'key=value'"
 
-#: bundle-uri.c
 msgid "bundle-uri: line has empty key or value"
 msgstr "bundle-uri: tá eochair nó luach folamh ag líne"
 
-#: bundle.c
 #, c-format
 msgid "unrecognized bundle hash algorithm: %s"
 msgstr "algartam hash beartán gan aithint: %s"
 
-#: bundle.c
 #, c-format
 msgid "unknown capability '%s'"
 msgstr "cumas anaithnid '%s'"
 
-#: bundle.c
 #, c-format
 msgid "'%s' does not look like a v2 or v3 bundle file"
 msgstr "Níl cuma '%s' cosúil le comhad beartán v2 nó v3"
 
-#: bundle.c
 #, c-format
 msgid "unrecognized header: %s%s (%d)"
 msgstr "ceanntásc gan aithint: %s%s (%d)"
 
-#: bundle.c
 msgid "Repository lacks these prerequisite commits:"
 msgstr "Níl na tiomantas réamhriachtanais seo ag an stór:"
 
-#: bundle.c
 msgid ""
 "some prerequisite commits exist in the object store, but are not connected "
 "to the repository's history"
@@ -17972,7 +15158,6 @@
 "tá roinnt gealltanais réamhriachtanais ann sa stór réada, ach níl siad "
 "ceangailte le stair an stór"
 
-#: bundle.c
 #, c-format
 msgid "The bundle contains this ref:"
 msgid_plural "The bundle contains these %<PRIuMAX> refs:"
@@ -17980,11 +15165,9 @@
 msgstr[1] "Tá na tagairtí %<PRIuMAX> seo sa phacáiste:"
 msgstr[2] "Tá na tagairtí %<PRIuMAX> seo sa phacáiste:"
 
-#: bundle.c
 msgid "The bundle records a complete history."
 msgstr "Taifeadann an beartán stair iomlán."
 
-#: bundle.c
 #, c-format
 msgid "The bundle requires this ref:"
 msgid_plural "The bundle requires these %<PRIuMAX> refs:"
@@ -17992,907 +15175,695 @@
 msgstr[1] "Éilíonn an pacáiste seo na tagairtí %<PRIuMAX> seo:"
 msgstr[2] "Éilíonn an pacáiste seo na tagairtí %<PRIuMAX> seo:"
 
-#: bundle.c
 #, c-format
 msgid "The bundle uses this hash algorithm: %s"
 msgstr "Úsáideann an beartán an algartam hash seo: %s"
 
-#: bundle.c
 #, c-format
 msgid "The bundle uses this filter: %s"
 msgstr "Úsáideann an beartán an scagaire seo: %s"
 
-#: bundle.c
 msgid "unable to dup bundle descriptor"
-msgstr "nach féidir tuairiscí a chur ar bhearnadh"
+msgstr "ní féidir tuairisceoir an phacáiste a dhúbláil"
 
-#: bundle.c
 msgid "Could not spawn pack-objects"
 msgstr "Ní fhéadfaí rudaí pacáiste a shannadh"
 
-#: bundle.c
 msgid "pack-objects died"
 msgstr "rudaí pacáiste fuair bás"
 
-#: bundle.c
 #, c-format
 msgid "ref '%s' is excluded by the rev-list options"
 msgstr "tá ref '%s' eisiata ag na roghanna rev-list"
 
-#: bundle.c
 #, c-format
 msgid "unsupported bundle version %d"
 msgstr "leagan beartán gan tacaíocht %d"
 
-#: bundle.c
 #, c-format
 msgid "cannot write bundle version %d with algorithm %s"
 msgstr "ní féidir leagan beartán %d a scríobh le algartam %s"
 
-#: bundle.c
 msgid "Refusing to create empty bundle."
 msgstr "Diúltú beartán folamh a chruthú."
 
-#: bundle.c
 #, c-format
 msgid "cannot create '%s'"
 msgstr "ní féidir '%s' a chruthú"
 
-#: bundle.c
 msgid "index-pack died"
 msgstr "fuair an pacáiste innéacs"
 
-#: cache-tree.c
 #, c-format
 msgid "directory '%s' is present in index, but not sparse"
 msgstr "tá eolaire '%s' i láthair in innéacs, ach níl sé neamhchoitianta"
 
-#: cache-tree.c unpack-trees.c
 msgid "corrupted cache-tree has entries not present in index"
 msgstr ""
 "tá iontrálacha nach bhfuil i láthair san innéacs ag crann cache-crainn "
 "truaillte"
 
-#: cache-tree.c
 #, c-format
 msgid "%s with flags 0x%x should not be in cache-tree"
 msgstr "Níor chóir go mbeadh %s le bratacha 0x%x i gcrann cache-tree"
 
-#: cache-tree.c
 #, c-format
 msgid "bad subtree '%.*s'"
 msgstr "droch-fho-chrann '%.*s'"
 
-#: cache-tree.c
 #, c-format
 msgid "cache-tree for path %.*s does not match. Expected %s got %s"
 msgstr ""
 "ní hionann crann-taisce don chonair %.*s. Bhíothas ag súil le %s, ach fuair "
 "%s"
 
-#: chunk-format.c
 msgid "terminating chunk id appears earlier than expected"
 msgstr "is cosúil le feiceáil id cúince a fhoirceannadh níos luaithe"
 
-#: chunk-format.c
 #, c-format
 msgid "chunk id %<PRIx32> not %d-byte aligned"
-msgstr "id chosc% <PRIx32>nach bhfuil %d-byte ailínithe"
+msgstr "níl an aitheantas smután %<PRIx32> ailínithe le %d beart"
 
-#: chunk-format.c
 #, c-format
 msgid "improper chunk offset(s) %<PRIx64> and %<PRIx64>"
-msgstr "fritháireamh píosa míchuí (í)% <PRIx64>agus% <PRIx64>"
+msgstr "fritháireamh(í) smután míchuí %<PRIx64> agus %<PRIx64>"
 
-#: chunk-format.c
 #, c-format
 msgid "duplicate chunk ID %<PRIx32> found"
 msgstr "aimsíodh ID smután dúblach %<PRIx32>"
 
-#: chunk-format.c
 #, c-format
 msgid "final chunk has non-zero id %<PRIx32>"
-msgstr "tá id neamh-nialasach ag an gcuid deiridh% <PRIx32>"
+msgstr "tá aitheantas neamh-nialasach %<PRIx32> ag an smután deiridh"
 
-#: chunk-format.c
 msgid "invalid hash version"
-msgstr "leagan hash neamhbhailí"
+msgstr "leagan hais neamhbhailí"
 
-#: color.c
 #, c-format
 msgid "invalid color value: %.*s"
 msgstr "luach dath neamhbhailí: %.*s"
 
-#: command-list.h
 msgid "Add file contents to the index"
 msgstr "Cuir ábhar an chomhaid leis an innéacs"
 
-#: command-list.h
 msgid "Apply a series of patches from a mailbox"
 msgstr "Cuir sraith paistí i bhfeidhm ó bhosca poist"
 
-#: command-list.h
 msgid "Annotate file lines with commit information"
 msgstr "Línte comhaid a anótáil le faisnéis tiomanta"
 
-#: command-list.h
 msgid "Apply a patch to files and/or to the index"
 msgstr "Cuir paiste i bhfeidhm ar chomhaid agus/nó ar an innéacs"
 
-#: command-list.h
 msgid "Import a GNU Arch repository into Git"
 msgstr "Iompórtáil stór GNU Arch isteach i Git"
 
-#: command-list.h
 msgid "Create an archive of files from a named tree"
 msgstr "Cruthaigh cartlann comhaid ó chrann ainmnithe"
 
-#: command-list.h
 msgid "Download missing objects in a partial clone"
 msgstr "Íoslódáil rudaí atá in easnamh i gclón pá"
 
-#: command-list.h
 msgid "Use binary search to find the commit that introduced a bug"
 msgstr ""
 "Úsáid cuardach dénártha chun an gealltanas a thug isteach fabht a fháil"
 
-#: command-list.h
 msgid "Show what revision and author last modified each line of a file"
 msgstr ""
 "Taispeáin an t-athbhreithniú agus an t-údar a mhodhnaigh gach líne de chomhad"
 
-#: command-list.h
 msgid "List, create, or delete branches"
 msgstr "Brainsí a liostáil, a chruthú nó a scriosadh"
 
-#: command-list.h
 msgid "Collect information for user to file a bug report"
 msgstr "Bailigh faisnéis don úsáideoir chun tuarascáil fabht a chomhdú"
 
-#: command-list.h
 msgid "Move objects and refs by archive"
 msgstr "Bogadh rudaí agus scríbhinní de réir cartlann"
 
-#: command-list.h
 msgid "Provide contents or details of repository objects"
 msgstr "Ábhar nó sonraí rudaí stórais a sholáthar"
 
-#: command-list.h
 msgid "Display gitattributes information"
 msgstr "Taispeáin faisnéis gitattributs"
 
-#: command-list.h
 msgid "Debug gitignore / exclude files"
 msgstr "Dífhabhtú gitignore/eisiamh comhaid"
 
-#: command-list.h
 msgid "Show canonical names and email addresses of contacts"
 msgstr "Taispeáin ainmneacha canónach agus seoltaí ríomhphoist teagmhál"
 
-#: command-list.h
 msgid "Ensures that a reference name is well formed"
 msgstr "Cinntíonn sé go bhfuil ainm tagartha foirmithe go maith"
 
-#: command-list.h
 msgid "Switch branches or restore working tree files"
 msgstr "Athraigh brainsí nó cuir comhaid crainn oibre ar ais"
 
-#: command-list.h
 msgid "Copy files from the index to the working tree"
 msgstr "Cóipeáil comhaid ón innéacs go dtí an crann oibre"
 
-#: command-list.h
 msgid "Find commits yet to be applied to upstream"
 msgstr "Faigh gealltanais nach ndéanfar cur i bhfeidhm fós ar an sruth"
 
-#: command-list.h
 msgid "Apply the changes introduced by some existing commits"
 msgstr ""
 "Cuir isteach na hathruithe a thug isteach ag roinnt gealltanais atá ann"
 
-#: command-list.h
 msgid "Graphical alternative to git-commit"
 msgstr "Rogha eile grafach seachas git-commit"
 
-#: command-list.h
 msgid "Remove untracked files from the working tree"
 msgstr "Bain comhaid neamhrianaithe ón gcrann oibre"
 
-#: command-list.h
 msgid "Clone a repository into a new directory"
 msgstr "Clóin stór isteach i eolaire nua"
 
-#: command-list.h
 msgid "Display data in columns"
 msgstr "Taispeáin sonraí i gcolúin"
 
-#: command-list.h
 msgid "Record changes to the repository"
 msgstr "Taifeadadh athruithe ar an stór"
 
-#: command-list.h
 msgid "Write and verify Git commit-graph files"
 msgstr "Scríobh agus fíoraigh comhaid choimisi-graf Git"
 
-#: command-list.h
 msgid "Create a new commit object"
 msgstr "Cruthaigh réad tiomanta nua"
 
-#: command-list.h
 msgid "Get and set repository or global options"
 msgstr "Faigh agus socraigh stór nó roghanna domhanda"
 
-#: command-list.h
 msgid "Count unpacked number of objects and their disk consumption"
 msgstr "Líon rudaí neamhphacáilte a chomhaireamh agus a dtomhaltas"
 
-#: command-list.h
 msgid "Retrieve and store user credentials"
 msgstr "Dintiúir úsáideora a aisghabháil agus"
 
-#: command-list.h
 msgid "Helper to temporarily store passwords in memory"
 msgstr "Cúntóir chun pasfhocail a stóráil i gcuimhne"
 
-#: command-list.h
 msgid "Helper to store credentials on disk"
-msgstr "Cúntóir chun dintiúir a stóráil ar dhios"
+msgstr "Cúntóir chun dintiúir a stóráil ar dhiosca"
 
-#: command-list.h
 msgid "Export a single commit to a CVS checkout"
 msgstr "Easpórtáil tiomantas amháin chuig seiceáil CVS"
 
-#: command-list.h
 msgid "Salvage your data out of another SCM people love to hate"
 msgstr ""
 "Sábháil do chuid sonraí as SCM eile is breá le daoine fuath a thabhairt"
 
-#: command-list.h
 msgid "A CVS server emulator for Git"
 msgstr "Aithritheoir freastalaí CVS do Git"
 
-#: command-list.h
 msgid "A really simple server for Git repositories"
 msgstr "Freastalaí an-simplí do stórais Git"
 
-#: command-list.h
 msgid "Give an object a human readable name based on an available ref"
 msgstr "Tabhair ainm inléite daonna do réad bunaithe ar thagartha atá ar fáil"
 
-#: command-list.h
 msgid "Generate a zip archive of diagnostic information"
 msgstr "Cruthaigh cartlann zip faisnéise diagnóiseach"
 
-#: command-list.h
 msgid "Show changes between commits, commit and working tree, etc"
 msgstr "Taispeáin athruithe idir gealltanais, tiomantas agus crann oibre, srl"
 
-#: command-list.h
 msgid "Compares files in the working tree and the index"
 msgstr "Déanann comparáid idir comhaid sa chrann oibre agus san innéacs"
 
-#: command-list.h
 msgid "Compare a tree to the working tree or index"
 msgstr "Déan comparáid idir crann leis an gcrann oibre nó leis an innéacs"
 
-#: command-list.h
 msgid "Compare the content and mode of provided blob pairs"
 msgstr "Déan comparáid idir ábhar agus modh na bpéirí blob atá curtha ar fáil"
 
-#: command-list.h
 msgid "Compares the content and mode of blobs found via two tree objects"
 msgstr ""
 "Déanann comparáid idir ábhar agus modh blobs a fhaightear trí dhá rud crann"
 
-#: command-list.h
 msgid "Show changes using common diff tools"
 msgstr "Taispeáin athruithe ag úsáid uirlisí coitianta diff"
 
-#: command-list.h
 msgid "Git data exporter"
 msgstr "Easpórtóir sonraí Git"
 
-#: command-list.h
 msgid "Backend for fast Git data importers"
 msgstr "Backend d'allmhaireoirí sonraí tapa Git"
 
-#: command-list.h
 msgid "Download objects and refs from another repository"
 msgstr "Íoslódáil rudaí agus réimsí ó stór eile"
 
-#: command-list.h
 msgid "Receive missing objects from another repository"
 msgstr "Faigh rudaí atá in easnamh ó stór eile"
 
-#: command-list.h
 msgid "Rewrite branches"
 msgstr "Brainsí a athscríobh"
 
-#: command-list.h
 msgid "Produce a merge commit message"
 msgstr "Teachtaireacht tiomanta cumaisc a chur"
 
-#: command-list.h
 msgid "Output information on each ref"
 msgstr "Eolas aschuir ar gach tagairt"
 
-#: command-list.h
 msgid "Run a Git command on a list of repositories"
 msgstr "Rith ordú Git ar liosta stórais"
 
-#: command-list.h
 msgid "Prepare patches for e-mail submission"
 msgstr "Ullmhaigh paistí le haghaidh aighneachta"
 
-#: command-list.h
 msgid "Verifies the connectivity and validity of the objects in the database"
 msgstr "Fíoraíonn sé nascacht agus bailíocht na rudaí sa bhunachar sonraí"
 
-#: command-list.h
 msgid "Cleanup unnecessary files and optimize the local repository"
 msgstr "Glan comhaid gan ghá agus an stór áitiúil a bharrfheabhsú"
 
-#: command-list.h
 msgid "Extract commit ID from an archive created using git-archive"
 msgstr ""
 "Bain ID tiomanta as cartlann a cruthaíodh ag baint úsáide as git-archive"
 
-#: command-list.h
 msgid "Print lines matching a pattern"
 msgstr "Línte priontála a mheaitseálann"
 
-#: command-list.h
 msgid "A portable graphical interface to Git"
 msgstr "Comhéadan grafach iniompartha chuig Git"
 
-#: command-list.h
 msgid "Compute object ID and optionally create an object from a file"
 msgstr "Ríomh ID réad agus cruthaigh réad ó chomhad go roghnach"
 
-#: command-list.h
 msgid "Display help information about Git"
 msgstr "Taispeáin faisnéis chabhrach faoi Git"
 
-#: command-list.h
 msgid "Run git hooks"
 msgstr "Rith crúcaí git"
 
-#: command-list.h
 msgid "Server side implementation of Git over HTTP"
 msgstr "Cur i bhfeidhm taobh freastalaí Git thar HTTP"
 
-#: command-list.h
 msgid "Download from a remote Git repository via HTTP"
 msgstr "Íoslódáil ó stór iargúlta Git trí HTTP"
 
-#: command-list.h
 msgid "Push objects over HTTP/DAV to another repository"
 msgstr "Brúigh rudaí thar HTTP/DAV chuig stór eile"
 
-#: command-list.h
 msgid "Send a collection of patches from stdin to an IMAP folder"
 msgstr "Seol bailiúchán paistí ó stdin chuig fillteán IMAP"
 
-#: command-list.h
 msgid "Build pack index file for an existing packed archive"
 msgstr "Tóg comhad innéacs pacáiste do chartlann pacáilte atá ann"
 
-#: command-list.h
 msgid "Create an empty Git repository or reinitialize an existing one"
 msgstr "Cruthaigh stór Git folamh nó déan ceann atá ann cheana a athionsú"
 
-#: command-list.h
 msgid "Instantly browse your working repository in gitweb"
 msgstr "Brabhsáil láithreach do stór oibre i gitweb"
 
-#: command-list.h
 msgid "Add or parse structured information in commit messages"
 msgstr "Cuir nó déan faisnéis struchtúrtha i dteachtaireachtaí tiomanta"
 
-#: command-list.h
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr ""
+"TURGNAMHACH: Taispeáin cathain a rinneadh na comhaid a mhodhnú go deireanach"
+
 msgid "Show commit logs"
 msgstr "Taispeáin logaí tiomanta"
 
-#: command-list.h
 msgid "Show information about files in the index and the working tree"
 msgstr "Taispeáin faisnéis faoi chomhaid san innéacs agus sa chrann oibre"
 
-#: command-list.h
 msgid "List references in a remote repository"
 msgstr "Liostaigh tagairtí i stór iargúlta"
 
-#: command-list.h
 msgid "List the contents of a tree object"
 msgstr "Liostaigh ábhar réad crann"
 
-#: command-list.h
 msgid "Extracts patch and authorship from a single e-mail message"
 msgstr "Baineann paiste agus údaracht as teachtaireacht ríomhphoist amháin"
 
-#: command-list.h
 msgid "Simple UNIX mbox splitter program"
 msgstr "Clár scoilteora mbox UNIX simplí"
 
-#: command-list.h
 msgid "Run tasks to optimize Git repository data"
 msgstr "Rith tascanna chun sonraí stór Git a bharrfheabhsú"
 
-#: command-list.h
 msgid "Join two or more development histories together"
 msgstr "Bí le dhá stair forbartha nó níos mó le chéile"
 
-#: command-list.h
 msgid "Find as good common ancestors as possible for a merge"
 msgstr "Faigh sinsear choiteann chomh maith agus is féidir le cumasc"
 
-#: command-list.h
 msgid "Run a three-way file merge"
 msgstr "Rith cumasc comhad trí bhealach"
 
-#: command-list.h
 msgid "Run a merge for files needing merging"
 msgstr "Reáchtáil cumaisc le haghaidh comhaid a bhfuil gá le cumasc orthu"
 
-#: command-list.h
 msgid "The standard helper program to use with git-merge-index"
 msgstr "An clár cúntóra caighdeánach le húsáid le git-merge-index"
 
-#: command-list.h
 msgid "Perform merge without touching index or working tree"
 msgstr "Déan cumasc gan teagmháil a dhéanamh le hInnéacs nó crann"
 
-#: command-list.h
 msgid "Run merge conflict resolution tools to resolve merge conflicts"
 msgstr "Rith uirlisí réitigh coinbhleachtaí cumaisc chun coinbhleachtaí"
 
-#: command-list.h
 msgid "Creates a tag object with extra validation"
 msgstr "Cruthaíonn sé réad clibeanna le bailíochtú breise"
 
-#: command-list.h
 msgid "Build a tree-object from ls-tree formatted text"
 msgstr "Tóg réad crann ó théacs formáidithe ls-tree"
 
-#: command-list.h
 msgid "Write and verify multi-pack-indexes"
 msgstr "Innéacsanna il-phacáiste a scríobh agus a fhíorú"
 
-#: command-list.h
 msgid "Move or rename a file, a directory, or a symlink"
 msgstr "Bogadh nó athainmnigh comhad, eolaire, nó nasc comhsheasmhach"
 
-#: command-list.h
 msgid "Find symbolic names for given revs"
 msgstr "Faigh ainmneacha siombalacha do thiomhartha tugtha"
 
-#: command-list.h
 msgid "Add or inspect object notes"
 msgstr "Cuir nó iniúchadh nótaí réad"
 
-#: command-list.h
 msgid "Import from and submit to Perforce repositories"
 msgstr "Iompórtáil ó stórais Perforce agus cuir isteach chuig"
 
-#: command-list.h
 msgid "Create a packed archive of objects"
 msgstr "Cruthaigh cartlann pacáilte rudaí"
 
-#: command-list.h
 msgid "Find redundant pack files"
 msgstr "Faigh comhaid pacáiste iomarcacha"
 
-#: command-list.h
 msgid "Pack heads and tags for efficient repository access"
 msgstr "Ceannanna agus clibeanna pacála le haghaidh rochtain éifeachtach"
 
-#: command-list.h
 msgid "Compute unique ID for a patch"
 msgstr "Ríomh ID uathúil le haghaidh paiste"
 
-#: command-list.h
 msgid "Prune all unreachable objects from the object database"
 msgstr ""
 "Déan gach rud nach féidir inrochtana a ghearradh ón mbunachar sonraí réad"
 
-#: command-list.h
 msgid "Remove extra objects that are already in pack files"
 msgstr "Bain rudaí breise atá i gcomhaid pacáiste cheana féin"
 
-#: command-list.h
 msgid "Fetch from and integrate with another repository or a local branch"
 msgstr "Faigh ó stór eile nó brainse áitiúil agus comhtháthú leis"
 
-#: command-list.h
 msgid "Update remote refs along with associated objects"
 msgstr "Nuashonraigh iargúlta mar aon le rudaí gaolmhara"
 
-#: command-list.h
 msgid "Applies a quilt patchset onto the current branch"
 msgstr "Cuireann paistset cuilte i bhfeidhm ar an mbrainse reatha"
 
-#: command-list.h
 msgid "Compare two commit ranges (e.g. two versions of a branch)"
 msgstr "Déan comparáid idir dhá raon tiomanta (e.g. dhá leagan de bhrainse)"
 
-#: command-list.h
 msgid "Reads tree information into the index"
 msgstr "Léann faisnéis crainn isteach san innéacs"
 
-#: command-list.h
 msgid "Reapply commits on top of another base tip"
 msgstr "Déan gealltanna a athchur i bhfeidhm ar bharr leid bonn eile"
 
-#: command-list.h
 msgid "Receive what is pushed into the repository"
 msgstr "Faigh an méid a bhrúitear isteach sa stór"
 
-#: command-list.h
 msgid "Manage reflog information"
 msgstr "Bainistigh faisnéis reflog"
 
-#: command-list.h
 msgid "Low-level access to refs"
 msgstr "Rochtain ar leibhéal íseal ar réimsí"
 
-#: command-list.h
 msgid "Manage set of tracked repositories"
 msgstr "Bainistigh sraith stórais rianaithe"
 
-#: command-list.h
 msgid "Pack unpacked objects in a repository"
 msgstr "Pacáil rudaí neamhphacáilte i stóras"
 
-#: command-list.h
 msgid "Create, list, delete refs to replace objects"
 msgstr "Cruthaigh, liostáil, scrios scríobh chun rudaí a athsholáthar"
 
-#: command-list.h
 msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
 msgstr ""
 "TURGNAMHACH: Tiomann athsheoladh ar bhonn nua, oibríonn sé le repos lom "
 "freisin"
 
-#: command-list.h
+msgid "Retrieve information about the repository"
+msgstr "Aisghabh faisnéis faoin stórlann"
+
 msgid "Generates a summary of pending changes"
 msgstr "Gineann achoimre ar athruithe ar feitheamh"
 
-#: command-list.h
 msgid "Reuse recorded resolution of conflicted merges"
 msgstr "Réiteach taifeadta ar chumaisc coinbhleachta a athúsáid"
 
-#: command-list.h
 msgid "Reset current HEAD to the specified state"
 msgstr "Athshocraigh HEAD reatha go dtí an stát sonraithe"
 
-#: command-list.h
 msgid "Restore working tree files"
 msgstr "Athchóirigh comhaid crann oibre"
 
-#: command-list.h
 msgid "Lists commit objects in reverse chronological order"
 msgstr "Tiomann liostaí rudaí in ord croineolaíoch droim"
 
-#: command-list.h
 msgid "Pick out and massage parameters"
 msgstr "Paraiméadair a roghnú agus massage"
 
-#: command-list.h
 msgid "Revert some existing commits"
 msgstr "Cuir roinnt gealltanais atá ann cheana ar ais"
 
-#: command-list.h
 msgid "Remove files from the working tree and from the index"
 msgstr "Bain comhaid ón gcrann oibre agus ón innéacs"
 
-#: command-list.h
 msgid "Send a collection of patches as emails"
 msgstr "Seol bailiúchán paistí mar ríomhphoist"
 
-#: command-list.h
 msgid "Push objects over Git protocol to another repository"
 msgstr "Brúigh rudaí thar phrótacal Git chuig stór eile"
 
-#: command-list.h
 msgid "Git's i18n setup code for shell scripts"
 msgstr "Cód socraithe i18n Git le haghaidh scripteanna blaosc"
 
-#: command-list.h
 msgid "Common Git shell script setup code"
 msgstr "Cód socraithe script bhlaosc Git coitianta"
 
-#: command-list.h
 msgid "Restricted login shell for Git-only SSH access"
 msgstr "Blaosc logála isteach srianta le haghaidh rochtain SSH GIT amháin"
 
-#: command-list.h
 msgid "Summarize 'git log' output"
 msgstr "Achoimre ar aschur 'git log'"
 
-#: command-list.h
 msgid "Show various types of objects"
 msgstr "Taispeáin cineálacha éagsúla rudaí"
 
-#: command-list.h
 msgid "Show branches and their commits"
 msgstr "Taispeáin brainsí agus a ngealltanais"
 
-#: command-list.h
 msgid "Show packed archive index"
 msgstr "Taispeáin an t-innéacs cartlainne"
 
-#: command-list.h
 msgid "List references in a local repository"
 msgstr "Liostaigh tagairtí i stóras áitiúil"
 
-#: command-list.h
 msgid "Reduce your working tree to a subset of tracked files"
 msgstr "Laghdaigh do chrann oibre go fo-thacar de chomhaid rianaithe"
 
-#: command-list.h
 msgid "Add file contents to the staging area"
 msgstr "Cuir ábhar an chomhaid leis an limistéar stáitse"
 
-#: command-list.h
 msgid "Stash the changes in a dirty working directory away"
 msgstr "Stóráil na hathruithe in eolaire oibre salach ar shiúl"
 
-#: command-list.h
 msgid "Show the working tree status"
 msgstr "Taispeáin stádas an chrann oibre"
 
-#: command-list.h
 msgid "Remove unnecessary whitespace"
 msgstr "Bain spás bán gan ghá"
 
-#: command-list.h
 msgid "Initialize, update or inspect submodules"
 msgstr "Fo-mhodúil a thionscnamh, a nuashonrú nó a"
 
-#: command-list.h
 msgid "Bidirectional operation between a Subversion repository and Git"
 msgstr "Oibriú déthreorach idir stór Subversion agus Git"
 
-#: command-list.h
 msgid "Switch branches"
 msgstr "Athraigh brainsí"
 
-#: command-list.h
 msgid "Read, modify and delete symbolic refs"
 msgstr "Léigh, modhnaigh agus scriosadh taiscéalaí siombalacha"
 
-#: command-list.h
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr "Cruthaigh, liostáil, scrios nó fíorú réad clibeanna sínithe le GPG"
+msgid "Create, list, delete or verify tags"
+msgstr "Cruthaigh, liostaigh, scrios nó fíoraigh clibeanna"
 
-#: command-list.h
 msgid "Creates a temporary file with a blob's contents"
 msgstr "Cruthaíonn sé comhad sealadach le hábhar blob"
 
-#: command-list.h
 msgid "Unpack objects from a packed archive"
 msgstr "Díphacáil rudaí ó chartlann pacáilte"
 
-#: command-list.h
 msgid "Register file contents in the working tree to the index"
 msgstr "Cláraigh ábhar an chomhaid sa chrann oibre chuig an innéacs"
 
-#: command-list.h
 msgid "Update the object name stored in a ref safely"
 msgstr "Nuashonraigh ainm an réad atá stóráilte i dtagairt go sá"
 
-#: command-list.h
 msgid "Update auxiliary info file to help dumb servers"
 msgstr "Nuashonraigh comhad faisnéise cúnta chun cabhrú le freastalaithe"
 
-#: command-list.h
 msgid "Send archive back to git-archive"
 msgstr "Seol cartlann ar ais chuig git-archive"
 
-#: command-list.h
 msgid "Send objects packed back to git-fetch-pack"
 msgstr "Seol rudaí pacáilte ar ais chuig git-fetch-pack"
 
-#: command-list.h
 msgid "Show a Git logical variable"
 msgstr "Taispeáin athróg loighciúil Git"
 
-#: command-list.h
 msgid "Check the GPG signature of commits"
 msgstr "Seiceáil síniú GPG na ngealltanais"
 
-#: command-list.h
 msgid "Validate packed Git archive files"
 msgstr "Bailíochtú comhaid cartlainne Git pacáilte"
 
-#: command-list.h
 msgid "Check the GPG signature of tags"
 msgstr "Seiceáil síniú GPG na gclibeanna"
 
-#: command-list.h
 msgid "Display version information about Git"
 msgstr "Taispeáin faisnéis leagan faoi Git"
 
-#: command-list.h
 msgid "Show logs with differences each commit introduces"
 msgstr "Taispeáin logaí le difríochtaí a thugann gach tiomantas"
 
-#: command-list.h
 msgid "Manage multiple working trees"
 msgstr "Bainistigh iliomad crainn oibre"
 
-#: command-list.h
 msgid "Create a tree object from the current index"
 msgstr "Cruthaigh réad crann ón innéacs reatha"
 
-#: command-list.h
 msgid "Defining attributes per path"
 msgstr "Sainmhíniú tréithe in aghaidh an"
 
-#: command-list.h
 msgid "Git command-line interface and conventions"
 msgstr "Comhéadan agus coinbhinsiúin líne ordaithe Git"
 
-#: command-list.h
 msgid "A Git core tutorial for developers"
 msgstr "Teagaisc lárnach Git d'fhorbróirí"
 
-#: command-list.h
 msgid "Providing usernames and passwords to Git"
 msgstr "Ainmneacha úsáideora agus pasfhocail a sholáthar do"
 
-#: command-list.h
 msgid "Git for CVS users"
 msgstr "Git d'úsáideoirí CVS"
 
-#: command-list.h
 msgid "Tweaking diff output"
 msgstr "Aschur difriúil a athrú"
 
-#: command-list.h
 msgid "A useful minimum set of commands for Everyday Git"
 msgstr "Sraith íosta úsáideach orduithe do Everyday Git"
 
-#: command-list.h
 msgid "Frequently asked questions about using Git"
 msgstr "Ceisteanna coitianta faoi úsáid Git"
 
-#: command-list.h
 msgid "The bundle file format"
 msgstr "An formáid comhaid beartán"
 
-#: command-list.h
 msgid "Chunk-based file formats"
 msgstr "Formáidí comhaid bunaithe ar bhunús"
 
-#: command-list.h
 msgid "Git commit-graph format"
-msgstr "Formáid comh-graph Git"
+msgstr "Git commit-graph format"
 
-#: command-list.h
 msgid "Git index format"
-msgstr "Formáid innéacs Git"
+msgstr "Git Formáid innéacs"
 
-#: command-list.h
 msgid "Git pack format"
 msgstr "Formáid pacáiste Git"
 
-#: command-list.h
 msgid "Git cryptographic signature formats"
 msgstr "Formáidí sínithe cripteagrafach Git"
 
-#: command-list.h
 msgid "A Git Glossary"
 msgstr "Gloclóir Git"
 
-#: command-list.h
 msgid "Hooks used by Git"
 msgstr "Crúcaí a úsáideann Git"
 
-#: command-list.h
 msgid "Specifies intentionally untracked files to ignore"
 msgstr "Sonraíonn sé comhaid neamhrianaithe de ghnó le neamhaird"
 
-#: command-list.h
 msgid "The Git repository browser"
 msgstr "Brabhsálaí stór Git"
 
-#: command-list.h
 msgid "Map author/committer names and/or E-Mail addresses"
 msgstr "Léarscáil ainmneacha údar/coistí agus/nó seoltaí rí"
 
-#: command-list.h
 msgid "Defining submodule properties"
 msgstr "Airíonna fomhodúil a shainiú"
 
-#: command-list.h
 msgid "Git namespaces"
 msgstr "Spásanna ainmneacha Git"
 
-#: command-list.h
 msgid "Protocol v0 and v1 capabilities"
 msgstr "Cumais Prótacal v0 agus v1"
 
-#: command-list.h
 msgid "Things common to various protocols"
 msgstr "Rudaí coitianta le prótacail éagsúla"
 
-#: command-list.h
 msgid "Git HTTP-based protocols"
 msgstr "Prótacail Git HTTP bunaithe"
 
-#: command-list.h
 msgid "How packs are transferred over-the-wire"
 msgstr "Conas a aistrítear pacáistí thar an sreang"
 
-#: command-list.h
 msgid "Git Wire Protocol, Version 2"
 msgstr "Prótacal Wire Git, Leagan 2"
 
-#: command-list.h
 msgid "Helper programs to interact with remote repositories"
 msgstr "Cláir chúntóirí chun idirghníomhú le stórálaí"
 
-#: command-list.h
 msgid "Git Repository Layout"
 msgstr "Leagan Amach Stórála Git"
 
-#: command-list.h
 msgid "Specifying revisions and ranges for Git"
 msgstr "Athbhreithnithe agus raonta a shonrú do Git"
 
-#: command-list.h
 msgid "Mounting one repository inside another"
 msgstr "Stóra amháin a chur isteach taobh istigh de cheann"
 
-#: command-list.h
 msgid "A tutorial introduction to Git"
 msgstr "Réamhrá teagaisc ar Git"
 
-#: command-list.h
 msgid "A tutorial introduction to Git: part two"
 msgstr "Réamhrá teagaisc ar Git: cuid a dara"
 
-#: command-list.h
 msgid "Git web interface (web frontend to Git repositories)"
 msgstr "Comhéadan gréasáin Git (tosaigh gréasáin chuig stórais Git)"
 
-#: command-list.h
 msgid "An overview of recommended workflows with Git"
 msgstr "Forbhreathnú ar shreafaí oibre a mholtar le Git"
 
-#: command-list.h
 msgid "A tool for managing large Git repositories"
 msgstr "Uirlis chun stórtha móra Git a bhainistiú"
 
-#: commit-graph.c
 msgid "commit-graph file is too small"
 msgstr "tá comhad coimit-graph ró-bheag"
 
-#: commit-graph.c
 msgid "commit-graph oid fanout chunk is wrong size"
 msgstr "tá an méid mícheart ar an smután fanout oid commit-graph"
 
-#: commit-graph.c
 msgid "commit-graph fanout values out of order"
 msgstr "luachanna fanout choimisi-graph as ord"
 
-#: commit-graph.c
 msgid "commit-graph OID lookup chunk is the wrong size"
 msgstr "tá an méid mícheart ar an smután cuardaigh OID commit-graph"
 
-#: commit-graph.c
 msgid "commit-graph commit data chunk is wrong size"
 msgstr "tá méid mícheart ar an smután sonraí commit commit-graph"
 
-#: commit-graph.c
 msgid "commit-graph generations chunk is wrong size"
 msgstr "is méid mícheart é an píosa glúine ghlúin chomhghraif"
 
-#: commit-graph.c
 msgid "commit-graph changed-path index chunk is too small"
 msgstr "tá píosa innéacs cosáin athraithe coimisithe ró-bheag"
 
-#: commit-graph.c
 #, c-format
 msgid ""
 "ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
@@ -18901,41 +15872,33 @@
 "ag neamhaird a dhéanamh den smután róbheag den chonair athraithe (%<PRIuMAX> "
 "< %<PRIuMAX>) i gcomhad commit-graph"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph signature %X does not match signature %X"
 msgstr "ní mheaitseálann síniú gráf coimiteach %X síniú %X"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph version %X does not match version %X"
 msgstr "ní hionann leagan %X den commit-graph agus leagan %X"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph hash version %X does not match version %X"
 msgstr "ní hionann leagan %X den hais commit-graph agus leagan %X"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph file is too small to hold %u chunks"
 msgstr "tá comhad comh-graph ró-bheag chun codanna %u a choinneáil"
 
-#: commit-graph.c
 msgid "commit-graph required OID fanout chunk missing or corrupted"
 msgstr "teastaíonn gráf coimisiúnaithe OID ar iarraidh nó truaillithe"
 
-#: commit-graph.c
 msgid "commit-graph required OID lookup chunk missing or corrupted"
 msgstr "teastaíonn píosa cuardaigh OID atá ar iarraidh nó truaillithe"
 
-#: commit-graph.c
 msgid "commit-graph required commit data chunk missing or corrupted"
 msgstr ""
 "gráf choimisiúnaithe riachtanach a thabhairt do chuid sonraí atá ar iarraidh "
 "nó"
 
-#: commit-graph.c
 #, c-format
 msgid ""
 "disabling Bloom filters for commit-graph layer '%s' due to incompatible "
@@ -18944,86 +15907,66 @@
 "scagairí Bloom a dhíchumasú le haghaidh ciseal coimit-graf '%s' mar gheall "
 "ar shuíomhanna neamh-chomho"
 
-#: commit-graph.c
 msgid "commit-graph has no base graphs chunk"
 msgstr "níl aon phíosa graif bunghraif ag commit-graph"
 
-#: commit-graph.c
 msgid "commit-graph base graphs chunk is too small"
 msgstr "tá an píosa graif bonn coimisi-graf ró-bheag"
 
-#: commit-graph.c
 msgid "commit-graph chain does not match"
 msgstr "ní mheaitseálann slabhra graf coimisiúnaithe"
 
-#: commit-graph.c
 #, c-format
 msgid "commit count in base graph too high: %<PRIuMAX>"
 msgstr "líon tiomanta i mbonngraf ró-ard:%<PRIuMAX>"
 
-#: commit-graph.c
 msgid "commit-graph chain file too small"
 msgstr "comhad slabhra commit-graph ró-bheag"
 
-#: commit-graph.c
 #, c-format
 msgid "invalid commit-graph chain: line '%s' not a hash"
 msgstr "slabhra coimit-graf neamhbhailí: ní hash é líne '%s'"
 
-#: commit-graph.c
 msgid "unable to find all commit-graph files"
-msgstr "nach féidir gach comhad gráf coimisiúnaithe a fháil"
+msgstr "ní féidir gach comhad commit-graph a aimsiú"
 
-#: commit-graph.c
 msgid "invalid commit position. commit-graph is likely corrupt"
 msgstr "post tiomanta neamhbhailí. Is dócha go bhfuil graf coimite truaillithe"
 
-#: commit-graph.c
 #, c-format
 msgid "could not find commit %s"
 msgstr "ní raibh sé in ann teacht ar thiomantas %s"
 
-#: commit-graph.c
 msgid "commit-graph requires overflow generation data but has none"
 msgstr "teastaíonn sonraí giniúna ró-shreabhadh ach níl aon cheann acu"
 
-#: commit-graph.c
 msgid "commit-graph overflow generation data is too small"
 msgstr "tá sonraí giniúna ró-shreabha tiomnaithe-graif róbheag"
 
-#: commit-graph.c
 msgid "commit-graph extra-edges pointer out of bounds"
 msgstr "léiríonn imill shrea-ghraif choimisiúin amach as teorainneacha"
 
-#: commit-graph.c
 msgid "Loading known commits in commit graph"
 msgstr "Gealltanna aitheanta a luchtú i ngraf tiomanta"
 
-#: commit-graph.c
 msgid "Expanding reachable commits in commit graph"
 msgstr "Gealltanais inrochtana a leathnú sa ghraf tiomanta"
 
-#: commit-graph.c
 msgid "Clearing commit marks in commit graph"
 msgstr "Marcanna tiomanta a ghlanadh sa ghraf tiom"
 
-#: commit-graph.c
 msgid "Computing commit graph topological levels"
 msgstr "Tiomann ríomhaireacht leibhéil topaic"
 
-#: commit-graph.c
 msgid "Computing commit graph generation numbers"
 msgstr "Tiomann an ríomhaireacht uimhreacha"
 
-#: commit-graph.c
 msgid "Computing commit changed paths Bloom filters"
 msgstr "Déanann ríomhaireacht cosáin athraithe a"
 
-#: commit-graph.c
 msgid "Collecting referenced commits"
 msgstr "Gealltanna tagartha a bhailiú"
 
-#: commit-graph.c
 #, c-format
 msgid "Finding commits for commit graph in %<PRIuMAX> pack"
 msgid_plural "Finding commits for commit graph in %<PRIuMAX> packs"
@@ -19031,38 +15974,30 @@
 msgstr[1] "Ag aimsiú tiomantais don ghraf tiomantais i bpacáistí %<PRIuMAX>"
 msgstr[2] "Ag aimsiú tiomantais don ghraf tiomantais i bpacáistí %<PRIuMAX>"
 
-#: commit-graph.c
 #, c-format
 msgid "error adding pack %s"
 msgstr "earráid ag cur pacáiste %s"
 
-#: commit-graph.c
 #, c-format
 msgid "error opening index for %s"
 msgstr "innéacs oscailte earráide do %s"
 
-#: commit-graph.c
 msgid "Finding commits for commit graph among packed objects"
 msgstr "Tiomantas a aimsiú maidir le graf tiomanta i measc rudaí pacá"
 
-#: commit-graph.c
 msgid "Finding extra edges in commit graph"
 msgstr "Imill bhreise a aimsiú i ngraf tiomanta"
 
-#: commit-graph.c
 msgid "failed to write correct number of base graph ids"
 msgstr "theip orthu líon ceart na n-idí graif bonn a scríobh"
 
-#: commit-graph.c
 msgid "unable to create temporary graph layer"
-msgstr "in ann ciseal graf sealadach a chruthú"
+msgstr "ní féidir ciseal graif sealadach a chruthú"
 
-#: commit-graph.c midx-write.c
 #, c-format
 msgid "unable to adjust shared permissions for '%s'"
-msgstr "nach féidir ceadanna roinnte a choigeartú do '%s'"
+msgstr "ní féidir ceadanna comhroinnte a choigeartú do '%s'"
 
-#: commit-graph.c
 #, c-format
 msgid "Writing out commit graph in %d pass"
 msgid_plural "Writing out commit graph in %d passes"
@@ -19070,42 +16005,33 @@
 msgstr[1] "Ag scríobh amach graf tiomantais i %d pas"
 msgstr[2] "Ag scríobh amach graf tiomantais i %d pas"
 
-#: commit-graph.c
 msgid "unable to open commit-graph chain file"
-msgstr "nach féidir comhad slabhra coimis-graf a oscailt"
+msgstr "ní féidir comhad slabhra commit-graph a oscailt"
 
-#: commit-graph.c
 msgid "failed to rename base commit-graph file"
 msgstr "theip ar an gcomhad gráf bunchoiste a athainmniú"
 
-#: commit-graph.c
 msgid "failed to rename temporary commit-graph file"
 msgstr "theip ar chomhad gráf choiste sealadach a athainmniú"
 
-#: commit-graph.c
 #, c-format
 msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits"
 msgstr "ní féidir graif a chumasc le %<PRIuMAX>, %<PRIuMAX> tiomantais"
 
-#: commit-graph.c
 #, c-format
 msgid "cannot merge graph %s, too many commits: %<PRIuMAX>"
 msgstr "ní féidir graf %s a chumasc, an iomarca tiomantais: %<PRIuMAX>"
 
-#: commit-graph.c
 msgid "Scanning merged commits"
 msgstr "Tiomanta cumaisc ag scanadh"
 
-#: commit-graph.c
 msgid "Merging commit-graph"
 msgstr "Graf coiste a chumasc"
 
-#: commit-graph.c
 msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled"
 msgstr ""
 "ag iarraidh graf coimite a scríobh, ach tá 'core.commitGraph' díchumasaithe"
 
-#: commit-graph.c
 #, c-format
 msgid ""
 "attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' "
@@ -19114,73 +16040,60 @@
 "ag iarraidh commit-graph a scríobh, ach tá 'commitGraph.changedPathsVersion' "
 "(%d) ní thacaítear leis"
 
-#: commit-graph.c
 msgid "too many commits to write graph"
 msgstr "an iomarca gealltanais graf a scríobh"
 
-#: commit-graph.c
 msgid "the commit-graph file has incorrect checksum and is likely corrupt"
 msgstr ""
 "tá seicsum mícheart ag an gcomhad graf coimite agus is dócha go bhfuil sé "
 "truaillithe"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph has incorrect OID order: %s then %s"
 msgstr "tá ordú OID mícheart ag commit-graph: %s ansin %s"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u"
 msgstr "tá luach fanout mícheart ag commit-graph: fanout [%d] = %u! = %u"
 
-#: commit-graph.c
 #, c-format
 msgid "failed to parse commit %s from commit-graph"
 msgstr "theip ar thiomantas %s a pharsáil ó ghraif choimisiúnaithe"
 
-#: commit-graph.c
 #, c-format
 msgid "failed to parse commit %s from object database for commit-graph"
 msgstr ""
 "theip ar thiomantas %s a pharsáil ó bhunachar sonraí réad le haghaidh graf "
 "coimite"
 
-#: commit-graph.c
 #, c-format
 msgid "root tree OID for commit %s in commit-graph is %s != %s"
 msgstr ""
 "crann fréimhe Is é OID do thiomantas %s sa ghraf tiomantais ná %s != %s"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph parent list for commit %s is too long"
 msgstr "tá liosta tuismitheoirí comh-graph do thiomantas %s rófhada"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph parent for %s is %s != %s"
 msgstr "is é an tuismitheoir comh-graph do %s ná %s! = %s"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph parent list for commit %s terminates early"
 msgstr ""
 "foirceannann liosta tuismitheora commit-graph le haghaidh commit %s go luath"
 
-#: commit-graph.c
 #, c-format
 msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>"
 msgstr ""
 "is é giniúint commit-graph le haghaidh commit %s %<PRIuMAX> < %<PRIuMAX>"
 
-#: commit-graph.c
 #, c-format
 msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>"
 msgstr ""
 "is é dáta tiomantais don tiomantas %s i commit-graph %<PRIuMAX> != %<PRIuMAX>"
 
-#: commit-graph.c
 #, c-format
 msgid ""
 "commit-graph has both zero and non-zero generations (e.g., commits '%s' and "
@@ -19189,21 +16102,17 @@
 "tá glúine nialasach agus neamh-nialasach ag comh-graph (e.g., geallann sé "
 "'%s' agus '%s')"
 
-#: commit-graph.c
 msgid "Verifying commits in commit graph"
 msgstr "Gealltanna a fhíorú i ngraf tiomanta"
 
-#: commit-reach.c sequencer.c
 #, c-format
 msgid "could not parse commit %s"
 msgstr "ní fhéadfaí a pharsáil a dhéanamh ar thiomantas %s"
 
-#: commit.c
 #, c-format
 msgid "%s %s is not a commit!"
 msgstr "Ní gealltanas é %s %s!"
 
-#: commit.c
 msgid ""
 "Support for <GIT_DIR>/info/grafts is deprecated\n"
 "and will be removed in a future Git version.\n"
@@ -19223,32 +16132,26 @@
 "Cas an teachtaireacht seo as trí rith\n"
 "“git config socraigh advice.graftFileDeprecated bréagach”"
 
-#: commit.c
 #, c-format
 msgid "commit %s exists in commit-graph but not in the object database"
 msgstr "tá comhad %s ann sa choimit-graph ach níl sa bhunachar sonraí réad"
 
-#: commit.c
 #, c-format
 msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
 msgstr "Tá síniú GPG neamhiontaofa ag Commit %s, a líomhnaítear ag %s."
 
-#: commit.c
 #, c-format
 msgid "Commit %s has a bad GPG signature allegedly by %s."
 msgstr "Tá droch-shíniú GPG ag Commit %s a líomhnaítear ag %s."
 
-#: commit.c
 #, c-format
 msgid "Commit %s does not have a GPG signature."
 msgstr "Níl síniú GPG ag Teacht %s."
 
-#: commit.c
 #, c-format
 msgid "Commit %s has a good GPG signature by %s\n"
 msgstr "Tá síniú maith GPG ag Teacht %s le %s\n"
 
-#: commit.c
 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"
@@ -19259,260 +16162,203 @@
 "an cumraíocht a shocrú\n"
 "athróg i18N.CommitEncoding don ionchódú a úsáideann do thionscadal.\n"
 
-#: compat/compiler.h
 msgid "no compiler information available\n"
 msgstr "níl aon fhaisnéis tiomsaitheora ar fáil\n"
 
-#: compat/compiler.h
 msgid "no libc information available\n"
 msgstr "níl aon fhaisnéis libc ar fáil\n"
 
-#: compat/disk.h
 #, c-format
 msgid "could not determine free disk size for '%s'"
 msgstr "ní fhéadfaí méid diosca saor in aisce a chinneadh do '%s'"
 
-#: compat/disk.h
 #, c-format
 msgid "could not get info for '%s'"
 msgstr "ní fhéadfaí faisnéis a fháil do '%s'"
 
-#: compat/fsmonitor/fsm-health-win32.c
 #, c-format
 msgid "[GLE %ld] health thread could not open '%ls'"
 msgstr "[GLE %ld] ní fhéadfadh snáithe sláinte '%ls' a oscailt"
 
-#: compat/fsmonitor/fsm-health-win32.c
 #, c-format
 msgid "[GLE %ld] health thread getting BHFI for '%ls'"
 msgstr "[GLE %ld] snáithe sláinte ag fáil BHFI do '%ls'"
 
-#: compat/fsmonitor/fsm-health-win32.c compat/fsmonitor/fsm-listen-win32.c
 #, c-format
 msgid "could not convert to wide characters: '%s'"
 msgstr "ní raibh sé in ann tiontú go carachtair leathan: '%s'"
 
-#: compat/fsmonitor/fsm-health-win32.c
 #, c-format
 msgid "BHFI changed '%ls'"
 msgstr "Athraigh BHFI '%ls'"
 
-#: compat/fsmonitor/fsm-health-win32.c
 #, c-format
 msgid "unhandled case in 'has_worktree_moved': %d"
 msgstr "cás neamh-láimhseáilte i 'has_worktree_moved': %d"
 
-#: compat/fsmonitor/fsm-health-win32.c
 #, c-format
 msgid "health thread wait failed [GLE %ld]"
 msgstr "theip ar fanacht snáithe sláinte [GLE %ld]"
 
-#: compat/fsmonitor/fsm-ipc-darwin.c
 #, c-format
 msgid "Invalid path: %s"
-msgstr "Conair neamhbhailí: %s"
+msgstr "Cosán neamhbhailí: %s"
 
-#: compat/fsmonitor/fsm-listen-darwin.c
 msgid "Unable to create FSEventStream."
 msgstr "Ní féidir FSeventStream a chruthú."
 
-#: compat/fsmonitor/fsm-listen-darwin.c
 msgid "Failed to start the FSEventStream"
 msgstr "Theip ar an FSevenStream a thosú"
 
-#: compat/fsmonitor/fsm-listen-win32.c
 #, c-format
 msgid "[GLE %ld] could not convert path to UTF-8: '%.*ls'"
 msgstr "[GLE %ld] níorbh fhéidir an cosán a thiontú go UTF-8: '%.*ls'"
 
-#: compat/fsmonitor/fsm-listen-win32.c
 #, c-format
 msgid "[GLE %ld] could not watch '%s'"
 msgstr "Ní raibh [GLE %ld] in ann féachaint ar '%s'"
 
-#: compat/fsmonitor/fsm-listen-win32.c
 #, c-format
 msgid "[GLE %ld] could not get longname of '%s'"
 msgstr "Ní raibh [GLE %ld] in ann ainm fadainm '%s' a fháil"
 
-#: compat/fsmonitor/fsm-listen-win32.c
 #, c-format
 msgid "ReadDirectoryChangedW failed on '%s' [GLE %ld]"
 msgstr "Theip ar ReadDirectoryChangedW ar '%s' [GLE %ld]"
 
-#: compat/fsmonitor/fsm-listen-win32.c
 #, c-format
 msgid "GetOverlappedResult failed on '%s' [GLE %ld]"
 msgstr "Theip ar getOverlappedResult ar '%s' [GLE %ld]"
 
-#: compat/fsmonitor/fsm-listen-win32.c
 #, c-format
 msgid "could not read directory changes [GLE %ld]"
 msgstr "ní fhéadfaí athruithe eolaire a léamh [GLE %ld]"
 
-#: compat/fsmonitor/fsm-path-utils-darwin.c
 #, c-format
 msgid "opendir('%s') failed"
 msgstr "theip ar opendir ('%s')"
 
-#: compat/fsmonitor/fsm-path-utils-darwin.c
 #, c-format
 msgid "lstat('%s') failed"
 msgstr "theip ar lstat ('%s')"
 
-#: compat/fsmonitor/fsm-path-utils-darwin.c
 #, c-format
 msgid "strbuf_readlink('%s') failed"
 msgstr "theip ar strbuf_readlink ('%s')"
 
-#: compat/fsmonitor/fsm-path-utils-darwin.c
 #, c-format
 msgid "closedir('%s') failed"
 msgstr "theip ar closedir ('%s')"
 
-#: compat/fsmonitor/fsm-path-utils-win32.c
 #, c-format
 msgid "[GLE %ld] unable to open for read '%ls'"
 msgstr "[GLE %ld] nach féidir é a oscailt le haghaidh léamh '%ls'"
 
-#: compat/fsmonitor/fsm-path-utils-win32.c
 #, c-format
 msgid "[GLE %ld] unable to get protocol information for '%ls'"
 msgstr "[GLE %ld] in ann faisnéis phrótacail a fháil do '%ls'"
 
-#: compat/mingw.c
 #, c-format
 msgid "failed to copy SID (%ld)"
 msgstr "theip ar SID (%ld) a chóipeáil"
 
-#: compat/mingw.c
 #, c-format
 msgid "failed to get owner for '%s' (%ld)"
 msgstr "theip ar úinéir a fháil do '%s' (%ld)"
 
-#: compat/obstack.c
 msgid "memory exhausted"
 msgstr "cuimhne ídithe"
 
-#: compat/regex/regcomp.c
 msgid "Success"
 msgstr "Rath"
 
-#: compat/regex/regcomp.c
 msgid "No match"
 msgstr "Gan aon mheaitseáil"
 
-#: compat/regex/regcomp.c
 msgid "Invalid regular expression"
 msgstr "Léiriú rialta nebhailí"
 
-#: compat/regex/regcomp.c
 msgid "Invalid collation character"
 msgstr "Carachtar comparáide neamhbhailí"
 
-#: compat/regex/regcomp.c
 msgid "Invalid character class name"
 msgstr "Ainm ranga carachtar neamhbhailí"
 
-#: compat/regex/regcomp.c
 msgid "Trailing backslash"
 msgstr "Cúlbhraith rianaithe"
 
-#: compat/regex/regcomp.c
 msgid "Invalid back reference"
 msgstr "Tagairt cúil neamhbhailí"
 
-#: compat/regex/regcomp.c
 msgid "Unmatched [ or [^"
 msgstr "Gan chomhoiriúnú [nó [^"
 
-#: compat/regex/regcomp.c
 msgid "Unmatched ( or \\("
 msgstr "Gan chomhoiriúnú (nó\\ ("
 
-#: compat/regex/regcomp.c
 msgid "Unmatched \\{"
 msgstr "Gan comhoiriúnú\\ {"
 
-#: compat/regex/regcomp.c
 msgid "Invalid content of \\{\\}"
-msgstr "Ábhar neamhbhailí de\\ {\\}"
+msgstr "Ábhar neamhbhailí de \\{\\}"
 
-#: compat/regex/regcomp.c
 msgid "Invalid range end"
 msgstr "Deireadh raon neamhbhailí"
 
-#: compat/regex/regcomp.c
 msgid "Memory exhausted"
 msgstr "Cuimhne ídithe"
 
-#: compat/regex/regcomp.c
 msgid "Invalid preceding regular expression"
 msgstr "Léiriú rialta neamhbhailí"
 
-#: compat/regex/regcomp.c
 msgid "Premature end of regular expression"
 msgstr "Deireadh roimh am an léirithe rialta"
 
-#: compat/regex/regcomp.c
 msgid "Regular expression too big"
 msgstr "Léiriú rialta ró-mhór"
 
-#: compat/regex/regcomp.c
 msgid "Unmatched ) or \\)"
 msgstr "Gan chomhoiriúnú) nó\\)"
 
-#: compat/regex/regcomp.c
 msgid "No previous regular expression"
 msgstr "Gan aon léiriú rialta roimhe seo"
 
-#: compat/simple-ipc/ipc-unix-socket.c compat/simple-ipc/ipc-win32.c
 msgid "could not send IPC command"
 msgstr "ní fhéadfaí ordú IPC a sheoladh"
 
-#: compat/simple-ipc/ipc-unix-socket.c compat/simple-ipc/ipc-win32.c
 msgid "could not read IPC response"
 msgstr "ní raibh sé in ann freagra IPC a léamh"
 
-#: compat/simple-ipc/ipc-unix-socket.c
 #, c-format
 msgid "could not start accept_thread '%s'"
 msgstr "ní fhéadfaí tosú accept_thread '%s'"
 
-#: compat/simple-ipc/ipc-unix-socket.c
 #, c-format
 msgid "could not start worker[0] for '%s'"
 msgstr "ní fhéadfaí oibrí [0] a thosú le haghaidh '%s'"
 
-#: compat/simple-ipc/ipc-win32.c
 #, c-format
 msgid "ConnectNamedPipe failed for '%s' (%lu)"
 msgstr "Theip ar ConnectNamedPipe le haghaidh '%s' (%lu)"
 
-#: compat/simple-ipc/ipc-win32.c
 #, c-format
 msgid "could not create fd from pipe for '%s'"
 msgstr "ní fhéadfaí fd a chruthú ó phíopa do '%s'"
 
-#: compat/simple-ipc/ipc-win32.c
 #, c-format
 msgid "could not start thread[0] for '%s'"
 msgstr "ní fhéadfaí snáithe [0] a thosú le haghaidh '%s'"
 
-#: compat/simple-ipc/ipc-win32.c
 #, c-format
 msgid "wait for hEvent failed for '%s'"
 msgstr "fanacht go dtí Theip ar feadh '%s'"
 
-#: compat/terminal.c
 msgid "cannot resume in the background, please use 'fg' to resume"
 msgstr "ní féidir atosú sa chúlra, bain úsáid as 'fg' le do thoil chun atosú"
 
-#: compat/terminal.c
 msgid "cannot restore terminal settings"
 msgstr "ní féidir le socruithe teirminéil"
 
-#: config.c
 #, c-format
 msgid ""
 "exceeded maximum include depth (%d) while including\n"
@@ -19527,20 +16373,16 @@
 " %s\n"
 "D'fhéadfadh sé seo a bheith mar gheall ar áireamh ciorclach."
 
-#: config.c
 #, c-format
 msgid "could not expand include path '%s'"
 msgstr "ní fhéadfaí leathnú san áireamh cosán '%s'"
 
-#: config.c
 msgid "relative config includes must come from files"
 msgstr "folaíonn cumraíocht choibhneasta caithfidh teacht ó chomh"
 
-#: config.c
 msgid "relative config include conditionals must come from files"
 msgstr "ní mór coinníollacha a theacht ó chomhaid i gcumraíocht choibhneasta"
 
-#: config.c
 msgid ""
 "remote URLs cannot be configured in file directly or indirectly included by "
 "includeIf.hasconfig:remote.*.url"
@@ -19548,348 +16390,266 @@
 "ní féidir URLanna iargúlta a chumrú i gcomhad san áireamh go díreach nó go "
 "hindíreach ag includeIf.hasconfig:remote.*.url"
 
-#: config.c
 #, c-format
 msgid "invalid config format: %s"
 msgstr "formáid cumraíochta neamhbhailí: %s"
 
-#: config.c
 #, c-format
 msgid "missing environment variable name for configuration '%.*s'"
 msgstr "ainm athróg comhshaoil atá in easnamh do chumraíocht '%.*s'"
 
-#: config.c
 #, c-format
 msgid "missing environment variable '%s' for configuration '%.*s'"
 msgstr "athróg comhshaoil in easnamh '%s' le haghaidh cumraíocht '%.*s'"
 
-#: config.c
 #, c-format
 msgid "key does not contain a section: %s"
 msgstr "níl rannán ag eochair: %s"
 
-#: config.c
 #, c-format
 msgid "key does not contain variable name: %s"
 msgstr "níl ainm athraitheach sa eochair: %s"
 
-#: config.c sequencer.c
 #, c-format
 msgid "invalid key: %s"
 msgstr "eochair neamhbhailí: %s"
 
-#: config.c
 #, c-format
 msgid "invalid key (newline): %s"
 msgstr "eochair neamhbhailí (líne nua): %s"
 
-#: config.c
 msgid "empty config key"
 msgstr "eochair cumraíochta folamh"
 
-#: config.c
 #, c-format
 msgid "bogus config parameter: %s"
 msgstr "paraiméadar cumraíochta bréagach: %s"
 
-#: config.c
 #, c-format
 msgid "bogus format in %s"
 msgstr "formáid bhréagach i %s"
 
-#: config.c
 #, c-format
 msgid "bogus count in %s"
 msgstr "comhaireamh bréagach i %s"
 
-#: config.c
 #, c-format
 msgid "too many entries in %s"
 msgstr "an iomarca iontrálacha i %s"
 
-#: config.c
 #, c-format
 msgid "missing config key %s"
 msgstr "eochair chumraithe %s in easnamh"
 
-#: config.c
 #, c-format
 msgid "missing config value %s"
 msgstr "luach cumraíochta %s ar iarraidh"
 
-#: config.c
 #, c-format
 msgid "bad config line %d in blob %s"
 msgstr "droch-líne cumraíochta %d i mblob %s"
 
-#: config.c
 #, c-format
 msgid "bad config line %d in file %s"
 msgstr "droch-líne cumraíochta %d i gcomhad %s"
 
-#: config.c
 #, c-format
 msgid "bad config line %d in standard input"
 msgstr "droch-líne cumraíochta %d i ionchur caighdeánach"
 
-#: config.c
 #, c-format
 msgid "bad config line %d in submodule-blob %s"
 msgstr "droch-líne cumraíochta %d i bhfo-modul-blob %s"
 
-#: config.c
 #, c-format
 msgid "bad config line %d in command line %s"
 msgstr "droch-líne cumraíochta %d i líne ordaithe %s"
 
-#: config.c
 #, c-format
 msgid "bad config line %d in %s"
 msgstr "droch-líne cumraíochta %d i %s"
 
-#: config.c
 msgid "out of range"
 msgstr "lasmuigh den raon"
 
-#: config.c
 msgid "invalid unit"
 msgstr "aonad neamhbhailí"
 
-#: config.c
 #, c-format
 msgid "bad numeric config value '%s' for '%s': %s"
 msgstr "droch-luach cumraíochta uimhriúil '%s' do '%s': %s"
 
-#: config.c
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in blob %s: %s"
 msgstr "droch-luach cumraíochta uimhriúil '%s' do '%s' i mblob %s: %s"
 
-#: config.c
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in file %s: %s"
 msgstr "droch-luach cumraíochta uimhriúil '%s' do '%s' i gcomhad %s: %s"
 
-#: config.c
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in standard input: %s"
 msgstr ""
 "droch-luach cumraíochta uimhriúil '%s' do '%s' in ionchur caighdeánach: %s"
 
-#: config.c
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s"
 msgstr "droch-luach cumraíochta uimhriúil '%s' do '%s' i bhfo-mhodúl %s: %s"
 
-#: config.c
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in command line %s: %s"
 msgstr "droch-luach cumraíochta uimhriúil '%s' do '%s' i líne ordaithe %s: %s"
 
-#: config.c
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in %s: %s"
 msgstr "droch-luach cumraíochta uimhriúil '%s' do '%s' i %s: %s"
 
-#: config.c
-#, c-format
-msgid "invalid value for variable %s"
-msgstr "luach neamhbhailí don athróg %s"
-
-#: config.c
-#, c-format
-msgid "ignoring unknown core.fsync component '%s'"
-msgstr "neamhaird a dhéanamh ar chomhpháirt core.fsync anaithnid '%s'"
-
-#: config.c
 #, c-format
 msgid "bad boolean config value '%s' for '%s'"
 msgstr "droch-luach cumraíochta boolean '%s' do '%s'"
 
-#: config.c
 #, c-format
 msgid "failed to expand user dir in: '%s'"
 msgstr "theip ar dir an úsáideora a leathnú i: '%s'"
 
-#: config.c
 #, c-format
 msgid "'%s' for '%s' is not a valid timestamp"
 msgstr "Ní stampa ama bailí é '%s' do '%s'"
 
-#: config.c
-#, c-format
-msgid "abbrev length out of range: %d"
-msgstr "fad a ghiorrú lasmuigh den raon: %d"
-
-#: config.c
-#, c-format
-msgid "bad zlib compression level %d"
-msgstr "droch-leibhéal comhbhrúite zlib %d"
-
-#: config.c
-#, c-format
-msgid "%s cannot contain newline"
-msgstr "Ní féidir le líne nua a bheith ag %s"
-
-#: config.c
-#, c-format
-msgid "%s must have at least one character"
-msgstr "Ní mór carachtar amháin ar a laghad a bheith ag %s"
-
-#: config.c
-#, c-format
-msgid "ignoring unknown core.fsyncMethod value '%s'"
-msgstr "neamhaird a dhéanamh ar luach core.fsyncMethod anaithnid '%s'"
-
-#: config.c
-msgid "core.fsyncObjectFiles is deprecated; use core.fsync instead"
-msgstr ""
-"tá core.fsyncObjectFiles díscothaithe; bain úsáid as core.fsync ina ionad"
-
-#: config.c
-#, c-format
-msgid "invalid mode for object creation: %s"
-msgstr "modh neamhbhailí chun réad a chruthú: %s"
-
-#: config.c
-#, c-format
-msgid "malformed value for %s"
-msgstr "luach mífhoirmithe do %s"
-
-#: config.c
-#, c-format
-msgid "malformed value for %s: %s"
-msgstr "luach mífhoirmithe do %s: %s"
-
-#: config.c
-msgid "must be one of nothing, matching, simple, upstream or current"
-msgstr ""
-"caithfidh sé a bheith ar cheann de rud ar bith, meaitseálach, simplí, suas "
-"srutha nó reatha"
-
-#: config.c
 #, c-format
 msgid "unable to load config blob object '%s'"
-msgstr "nach féidir réad blob cumraithe '%s' a luchtú"
+msgstr "ní féidir an réad blob cumraíochta '%s' a luchtú"
 
-#: config.c
 #, c-format
 msgid "reference '%s' does not point to a blob"
 msgstr "ní thugann tagairt '%s' in iúl do bhlob"
 
-#: config.c
 #, c-format
 msgid "unable to resolve config blob '%s'"
-msgstr "in ann clob config '%s' a réiteach"
+msgstr "ní féidir bloba cumraíochta '%s' a réiteach"
 
-#: config.c
 msgid "unable to parse command-line config"
-msgstr "nach féidir cumraíocht líne ordaithe a pháirseáil"
+msgstr "ní féidir cumraíocht líne ordaithe a pharsáil"
 
-#: config.c
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"Chun an teaghrán tráchta réamhshocraithe (#) a úsáid, rith le do thoil\n"
+"\n"
+"%s"
+
+msgid "<comment string>"
+msgstr "<comment string>"
+
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+"\n"
+"Chun teaghrán tráchta saincheaptha a shocrú, rith\n"
+"\n"
+"%s\n"
+"áit a seasann '%s' don teaghrán is mian leat a úsáid.\n"
+
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr "Baineadh tacaíocht do '%s=auto' i Git 3.0"
+
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr "Tá tacaíocht do '%s=auto' imithe i léig agus bainfear í i Git 3.0"
+
 msgid "unknown error occurred while reading the configuration files"
 msgstr "tharla earráid anaithnid agus na comhaid cumraíochta á léamh"
 
-#: config.c
 #, c-format
 msgid "Invalid %s: '%s'"
 msgstr "%s neamhbhailí: '%s'"
 
-#: config.c
 #, c-format
 msgid "splitIndex.maxPercentChange value '%d' should be between 0 and 100"
 msgstr "splitIndex.maxPercentChange value '%d' bheith idir 0 agus 100"
 
-#: config.c
 #, c-format
 msgid "unable to parse '%s' from command-line config"
 msgstr "ní féidir '%s' a pháirseáil ó chumraíocht líne ordaithe"
 
-#: config.c
 #, c-format
 msgid "bad config variable '%s' in file '%s' at line %d"
 msgstr "droch-athróg cumraithe '%s' sa chomhad '%s' ag líne %d"
 
-#: config.c
 #, c-format
 msgid "invalid section name '%s'"
 msgstr "ainm rannán neamhbhailí '%s'"
 
-#: config.c
 #, c-format
 msgid "%s has multiple values"
 msgstr "Tá luachanna iolracha ag %s"
 
-#: config.c
 #, c-format
 msgid "failed to write new configuration file %s"
 msgstr "theip ar chomhad cumraíochta nua %s a scríobh"
 
-#: config.c
 #, c-format
 msgid "no multi-line comment allowed: '%s'"
 msgstr "níl aon trácht illíne ceadaithe: '%s'"
 
-#: config.c
 #, c-format
 msgid "could not lock config file %s"
 msgstr "ní fhéadfaí comhad cumraíochta %s a ghlasáil"
 
-#: config.c
 #, c-format
 msgid "opening %s"
 msgstr "oscailt %s"
 
-#: config.c
 #, c-format
 msgid "invalid config file %s"
 msgstr "comhad cumraithe neamhbhailí %s"
 
-#: config.c
 #, c-format
 msgid "fstat on %s failed"
 msgstr "theip ar fstat ar %s"
 
-#: config.c
 #, c-format
 msgid "unable to mmap '%s'%s"
 msgstr "ní féidir le '%s'%s a mmapáil"
 
-#: config.c
 #, c-format
 msgid "chmod on %s failed"
 msgstr "theip ar chmod ar %s"
 
-#: config.c
 #, c-format
 msgid "could not write config file %s"
 msgstr "ní fhéadfaí comhad cumraithe %s a scríobh"
 
-#: config.c
 #, c-format
 msgid "could not set '%s' to '%s'"
 msgstr "ní fhéadfaí '%s' a shocrú go '%s'"
 
-#: config.c
 #, c-format
 msgid "invalid section name: %s"
 msgstr "ainm rannán neamhbhailí: %s"
 
-#: config.c
 #, c-format
 msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
 msgstr "diúltú oibriú le líne rófhada i '%s' ar líne%<PRIuMAX>"
 
-#: config.c
 #, c-format
 msgid "missing value for '%s'"
 msgstr "luach ar iarraidh do '%s'"
 
-#: connect.c
 msgid "the remote end hung up upon initial contact"
 msgstr "crochadh an deireadh iargúlta ar an teagmháil tosaigh"
 
-#: connect.c
 msgid ""
 "Could not read from remote repository.\n"
 "\n"
@@ -19901,95 +16661,75 @@
 "Déan cinnte go bhfuil na cearta rochtana cearta agat\n"
 "agus tá an stór ann."
 
-#: connect.c
 #, c-format
 msgid "server doesn't support '%s'"
 msgstr "ní thacaíonn freastalaí le '%s'"
 
-#: connect.c
 #, c-format
 msgid "server doesn't support feature '%s'"
 msgstr "ní thacaíonn freastalaí le gné '%s'"
 
-#: connect.c
 msgid "expected flush after capabilities"
 msgstr "súil le sruth tar éis cumais"
 
-#: connect.c
 #, c-format
 msgid "ignoring capabilities after first line '%s'"
 msgstr "neamhaird a dhéanamh ar chumais tar éis an chéad líne '%s'"
 
-#: connect.c
 msgid "protocol error: unexpected capabilities^{}"
 msgstr "earráid prótacal: cumais gan choinne ^ {}"
 
-#: connect.c
 #, c-format
 msgid "protocol error: expected shallow sha-1, got '%s'"
 msgstr "earráid prótacal: táthar ag súil le sha-1 éadrom, fuair '%s'"
 
-#: connect.c
 msgid "repository on the other end cannot be shallow"
 msgstr "ní féidir stór ar an gceann eile a bheith éadrom"
 
-#: connect.c
 msgid "invalid packet"
-msgstr "pacáiste neamhbhail"
+msgstr "paicéad neamhbhailí"
 
-#: connect.c
 #, c-format
 msgid "protocol error: unexpected '%s'"
 msgstr "earráid prótacal: '%s' gan choinne"
 
-#: connect.c
 #, c-format
 msgid "unknown object format '%s' specified by server"
 msgstr "formáid réad anaithnid '%s' arna shonrú ag freastalaí"
 
-#: connect.c
 #, c-format
 msgid "error on bundle-uri response line %d: %s"
 msgstr "earráid ar líne freagartha cumhachta %d: %s"
 
-#: connect.c
 msgid "expected flush after bundle-uri listing"
 msgstr "súil le sruth tar éis liostú bundle-uri"
 
-#: connect.c
 msgid "expected response end packet after ref listing"
 msgstr "pacáiste deiridh freagartha a bhfuiltear ag súil leis"
 
-#: connect.c
 #, c-format
 msgid "invalid ls-refs response: %s"
 msgstr "freagra neamhbhailí ls-refs: %s"
 
-#: connect.c
 msgid "expected flush after ref listing"
 msgstr "súil le sruth tar éis liostú tagartha"
 
-#: connect.c
 #, c-format
 msgid "protocol '%s' is not supported"
 msgstr "ní thacaítear le prótacal '%s'"
 
-#: connect.c
 msgid "unable to set SO_KEEPALIVE on socket"
-msgstr "in ann SO_KEEPALIVE a shocrú ar an soicéad"
+msgstr "ní féidir SO_KEEPALIVE a shocrú ar an soicéad"
 
-#: connect.c
 #, c-format
 msgid "Looking up %s ... "
 msgstr "Ag féachaint suas %s... "
 
-#: connect.c
 #, c-format
 msgid "unable to look up %s (port %s) (%s)"
-msgstr "nach féidir a lorg suas %s (port %s) (%s)"
+msgstr "ní féidir %s a chuardach (port %s) (%s)"
 
 #. TRANSLATORS: this is the end of "Looking up %s ... "
-#: connect.c
 #, c-format
 msgid ""
 "done.\n"
@@ -19998,7 +16738,6 @@
 "déanta.\n"
 "Ag nascadh le %s (port %s)... "
 
-#: connect.c
 #, c-format
 msgid ""
 "unable to connect to %s:\n"
@@ -20008,89 +16747,70 @@
 "%s"
 
 #. TRANSLATORS: this is the end of "Connecting to %s (port %s) ... "
-#: connect.c
 msgid "done."
 msgstr "déanta."
 
-#: connect.c
 #, c-format
 msgid "unable to look up %s (%s)"
-msgstr "nach féidir a lorg suas %s (%s)"
+msgstr "ní féidir %s (%s) a chuardach"
 
-#: connect.c
 #, c-format
 msgid "unknown port %s"
 msgstr "port anaithnid %s"
 
-#: connect.c
 #, c-format
 msgid "strange hostname '%s' blocked"
 msgstr "ainm óstach aisteach '%s' blocáilte"
 
-#: connect.c
 #, c-format
 msgid "strange port '%s' blocked"
 msgstr "cosc ar chalafort aisteach '%s'"
 
-#: connect.c
 #, c-format
 msgid "cannot start proxy %s"
 msgstr "ní féidir le seachfhreastalaí %s"
 
-#: connect.c
 msgid "no path specified; see 'git help pull' for valid url syntax"
 msgstr ""
 "níl aon chosán sonraithe; féach 'git help pull' le haghaidh comhréireachta "
 "bailí url"
 
-#: connect.c
 msgid "newline is forbidden in git:// hosts and repo paths"
 msgstr "tá cosc ​​ar líne nua in óstaigh git:// agus cosáin stórais"
 
-#: connect.c
 msgid "ssh variant 'simple' does not support -4"
 msgstr "ní thacaíonn leagan ssh 'simplí' le -4"
 
-#: connect.c
 msgid "ssh variant 'simple' does not support -6"
 msgstr "ní thacaíonn leagan ssh 'simplí' le -6"
 
-#: connect.c
 msgid "ssh variant 'simple' does not support setting port"
 msgstr "ní thacaíonn leagan ssh 'simplí' le port socrú"
 
-#: connect.c
 #, c-format
 msgid "strange pathname '%s' blocked"
 msgstr "cosc ar ainm cosán aisteach '%s'"
 
-#: connect.c
 msgid "unable to fork"
-msgstr "in ann a fhorc"
+msgstr "ní féidir forc a dhéanamh"
 
-#: connected.c
 msgid "Could not run 'git rev-list'"
 msgstr "Ní fhéadfaí 'git rev-list' a reáchtáil"
 
-#: connected.c
 msgid "failed write to rev-list"
 msgstr "theip ar scríobh chuig rev-list"
 
-#: connected.c
 msgid "failed to close rev-list's stdin"
 msgstr "theip orthu stdin rev-list a dhúnadh"
 
-#: convert.c
 #, c-format
 msgid "illegal crlf_action %d"
 msgstr "crlf_action mídhleathach %d"
 
-#: convert.c
 #, c-format
 msgid "CRLF would be replaced by LF in %s"
 msgstr "Bheadh LF in ionad CRLF i %s"
 
-#: convert.c
 #, c-format
 msgid ""
 "in the working copy of '%s', CRLF will be replaced by LF the next time Git "
@@ -20099,12 +16819,10 @@
 "sa chóip oibre de '%s', cuirfear LF in ionad CRLF an chéad uair eile a "
 "théann Git leis"
 
-#: convert.c
 #, c-format
 msgid "LF would be replaced by CRLF in %s"
 msgstr "Bheadh CRLF in ionad LF i %s"
 
-#: convert.c
 #, c-format
 msgid ""
 "in the working copy of '%s', LF will be replaced by CRLF the next time Git "
@@ -20113,12 +16831,10 @@
 "sa chóip oibre de '%s', cuirfear CRLF in ionad LF an chéad uair eile a "
 "théann Git leis"
 
-#: convert.c
 #, c-format
 msgid "BOM is prohibited in '%s' if encoded as %s"
 msgstr "Tá cosc ar BOM i '%s' má tá sé ionchódaithe mar %s"
 
-#: convert.c
 #, c-format
 msgid ""
 "The file '%s' contains a byte order mark (BOM). Please use UTF-%.*s as "
@@ -20127,12 +16843,10 @@
 "Tá marc ordaithe beart (BOM) sa chomhad '%s'. Bain úsáid as UTF-%.*s mar "
 "ionchódú crann oibre le do thoil."
 
-#: convert.c
 #, c-format
 msgid "BOM is required in '%s' if encoded as %s"
 msgstr "Tá BOM ag teastáil i '%s' má tá sé ionchódaithe mar %s"
 
-#: convert.c
 #, c-format
 msgid ""
 "The file '%s' is missing a byte order mark (BOM). Please use UTF-%sBE or UTF-"
@@ -20141,50 +16855,40 @@
 "Tá marc ordaithe beart (BOM) ar iarraidh sa chomhad '%s'. Bain úsáid as UTF-"
 "%sBE nó UTF-%sLE (ag brath ar ord na mbeart) mar ionchódú crann oibre."
 
-#: convert.c
 #, c-format
 msgid "failed to encode '%s' from %s to %s"
 msgstr "theip ar '%s' a ionchódú ó %s go %s"
 
-#: convert.c
 #, c-format
 msgid "encoding '%s' from %s to %s and back is not the same"
 msgstr "ionchódú '%s' ó %s go %s agus níl sé mar an gcéanna ar ais"
 
-#: convert.c
 #, c-format
 msgid "cannot fork to run external filter '%s'"
 msgstr "ní féidir forc chun scagaire seachtrach '%s' a reáchtáil"
 
-#: convert.c
 #, c-format
 msgid "cannot feed the input to external filter '%s'"
 msgstr "ní féidir leis an ionchur a bheathú chuig scagaire seachtrach '%s'"
 
-#: convert.c
 #, c-format
 msgid "external filter '%s' failed %d"
 msgstr "theip ar scagaire seachtrach '%s' %d"
 
-#: convert.c
 #, c-format
 msgid "read from external filter '%s' failed"
 msgstr "theip ar léamh ó scagaire seachtrach '%s'"
 
-#: convert.c
 #, c-format
 msgid "external filter '%s' failed"
 msgstr "theip ar scagaire seachtrach '%s'"
 
-#: convert.c
 msgid "unexpected filter type"
 msgstr "cineál scagaire gan choinne"
 
-#: convert.c
 msgid "path name too long for external filter"
 msgstr "ainm cosáin rófhada le haghaidh scagaire seachtrach"
 
-#: convert.c
 #, c-format
 msgid ""
 "external filter '%s' is not available anymore although not all paths have "
@@ -20193,68 +16897,54 @@
 "níl an scagaire seachtrach '%s' ar fáil a thuilleadh cé nach bhfuil na "
 "cosáin uile scagtha"
 
-#: convert.c
 msgid "true/false are no valid working-tree-encodings"
 msgstr "níl aon ionchódaithe bailí crainn oibre fíor-bhréagach"
 
-#: convert.c
 #, c-format
 msgid "%s: clean filter '%s' failed"
 msgstr "%s: theip ar scagaire glan '%s'"
 
-#: convert.c
 #, c-format
 msgid "%s: smudge filter %s failed"
 msgstr "%s: theip ar scagaire smudge %s"
 
-#: credential.c
 #, c-format
 msgid "skipping credential lookup for key: credential.%s"
-msgstr "cuardach creidiúnaithe a scipeáil le haghaidh eochair: creidiúnas. %s"
+msgstr "ag scipeáil cuardach dintiúir don eochair: dintiúr.%s"
 
-#: credential.c
 msgid "refusing to work with credential missing host field"
 msgstr "diúltú oibriú le réimse óstach creidiúnaithe atá ar"
 
-#: credential.c
 msgid "refusing to work with credential missing protocol field"
 msgstr "diúltú oibriú le réimse prótacal ar iarraidh creidiú"
 
-#: credential.c
 #, c-format
 msgid "url contains a newline in its %s component: %s"
 msgstr "tá líne nua ina chomhpháirt %s ag url: %s"
 
-#: credential.c
 #, c-format
 msgid "url has no scheme: %s"
 msgstr "níl aon scéim ag url: %s"
 
-#: credential.c
 #, c-format
 msgid "credential url cannot be parsed: %s"
 msgstr "ní féidir url creidiúnaithe a pháirseáil: %s"
 
-#: daemon.c
 #, c-format
 msgid "invalid timeout '%s', expecting a non-negative integer"
 msgstr "ama neamhbhailí '%s', ag súil le sláimhir neamh-dhiúltach"
 
-#: daemon.c
 #, c-format
 msgid "invalid init-timeout '%s', expecting a non-negative integer"
 msgstr "ama init-time '%s' neamhbhailí, ag súil le sláimhir neamh-dhiúltach"
 
-#: daemon.c
 #, c-format
 msgid "invalid max-connections '%s', expecting an integer"
 msgstr "naisc uasta neamhbhailí '%s', ag súil le sláimhir"
 
-#: date.c
 msgid "in the future"
 msgstr "sa todhchaí"
 
-#: date.c
 #, c-format
 msgid "%<PRIuMAX> second ago"
 msgid_plural "%<PRIuMAX> seconds ago"
@@ -20262,7 +16952,6 @@
 msgstr[1] "%<PRIuMAX> soicind ó shin"
 msgstr[2] "%<PRIuMAX> soicind ó shin"
 
-#: date.c
 #, c-format
 msgid "%<PRIuMAX> minute ago"
 msgid_plural "%<PRIuMAX> minutes ago"
@@ -20270,7 +16959,6 @@
 msgstr[1] "%<PRIuMAX> nóiméad ó shin"
 msgstr[2] "%<PRIuMAX> nóiméad ó shin"
 
-#: date.c
 #, c-format
 msgid "%<PRIuMAX> hour ago"
 msgid_plural "%<PRIuMAX> hours ago"
@@ -20278,7 +16966,6 @@
 msgstr[1] "%<PRIuMAX> uair an chloig ó shin"
 msgstr[2] "%<PRIuMAX> uair an chloig ó shin"
 
-#: date.c
 #, c-format
 msgid "%<PRIuMAX> day ago"
 msgid_plural "%<PRIuMAX> days ago"
@@ -20286,7 +16973,6 @@
 msgstr[1] "%<PRIuMAX> lá ó shin"
 msgstr[2] "%<PRIuMAX> lá ó shin"
 
-#: date.c
 #, c-format
 msgid "%<PRIuMAX> week ago"
 msgid_plural "%<PRIuMAX> weeks ago"
@@ -20294,7 +16980,6 @@
 msgstr[1] "%<PRIuMAX> seachtain ó shin"
 msgstr[2] "%<PRIuMAX> seachtain ó shin"
 
-#: date.c
 #, c-format
 msgid "%<PRIuMAX> month ago"
 msgid_plural "%<PRIuMAX> months ago"
@@ -20302,7 +16987,6 @@
 msgstr[1] "%<PRIuMAX> mí ó shin"
 msgstr[2] "%<PRIuMAX> mí ó shin"
 
-#: date.c
 #, c-format
 msgid "%<PRIuMAX> year"
 msgid_plural "%<PRIuMAX> years"
@@ -20311,7 +16995,6 @@
 msgstr[2] "%<PRIuMAX> bliain"
 
 #. TRANSLATORS: "%s" is "<n> years"
-#: date.c
 #, c-format
 msgid "%s, %<PRIuMAX> month ago"
 msgid_plural "%s, %<PRIuMAX> months ago"
@@ -20319,7 +17002,6 @@
 msgstr[1] "%s, %<PRIuMAX> mí ó shin"
 msgstr[2] "%s, %<PRIuMAX> mí ó shin"
 
-#: date.c
 #, c-format
 msgid "%<PRIuMAX> year ago"
 msgid_plural "%<PRIuMAX> years ago"
@@ -20327,92 +17009,78 @@
 msgstr[1] "%<PRIuMAX> bliain ó shin"
 msgstr[2] "%<PRIuMAX> bliain ó shin"
 
-#: delta-islands.c
 msgid "Propagating island marks"
 msgstr "Marcanna oileáin a iomadú"
 
-#: delta-islands.c
 #, c-format
 msgid "bad tree object %s"
 msgstr "réad droch-chrann %s"
 
-#: delta-islands.c
 #, c-format
 msgid "failed to load island regex for '%s': %s"
 msgstr "theip ar an oileán regex a luchtú do '%s': %s"
 
-#: delta-islands.c
 #, c-format
 msgid "island regex from config has too many capture groups (max=%d)"
 msgstr "tá an iomarca grúpaí gabhála ag an oileán regex ó config (max = %d)"
 
-#: delta-islands.c
 #, c-format
 msgid "Marked %d islands, done.\n"
 msgstr "Oileáin %d marcáilte, déanta.\n"
 
-#: diagnose.c
 #, c-format
 msgid "invalid --%s value '%s'"
 msgstr "neamhbhailí --%s luach '%s'"
 
-#: diagnose.c
 #, c-format
 msgid "could not archive missing directory '%s'"
 msgstr "ní fhéadfaí eolaire '%s' in easnamh a chartlannú"
 
-#: diagnose.c dir.c
 #, c-format
 msgid "could not open directory '%s'"
 msgstr "ní raibh in ann eolaire '%s' a oscailt"
 
-#: diagnose.c
 #, c-format
 msgid "skipping '%s', which is neither file nor directory"
 msgstr "ag scipeáil '%s', nach comhad ná eolaire"
 
-#: diagnose.c
 msgid "could not duplicate stdout"
 msgstr "ní fhéadfaí stdout a dhúbailt"
 
-#: diagnose.c
 #, c-format
 msgid "could not add directory '%s' to archiver"
 msgstr "ní fhéadfaí eolaire '%s' a chur leis an gcartlann"
 
-#: diagnose.c
 msgid "failed to write archive"
 msgstr "theip ar chartlann a scríobh"
 
-#: diff-lib.c
+msgid "max-depth is not supported for worktree diffs"
+msgstr "ní thacaítear le doimhneacht uasta le haghaidh difríochtaí crann oibre"
+
+msgid "max-depth is not supported for index diffs"
+msgstr "ní thacaítear le doimhneacht uasta le haghaidh difríochtaí innéacs"
+
 msgid "--merge-base does not work with ranges"
 msgstr "ní oibríonn --merge-base le raonta"
 
-#: diff-lib.c
 msgid "unable to get HEAD"
-msgstr "in ann HEAD a fháil"
+msgstr "ní féidir HEAD a faigh"
 
-#: diff-lib.c
 msgid "no merge base found"
 msgstr "níl aon bhonn cumaisc le fáil"
 
-#: diff-lib.c
 msgid "multiple merge bases found"
 msgstr "fuarthas bonn cumaisc iolr"
 
-#: diff-no-index.c
 msgid "cannot compare stdin to a directory"
 msgstr "ní féidir stdin a chur i gcomparáid le eolaire"
 
-#: diff-no-index.c
 msgid "cannot compare a named pipe to a directory"
 msgstr "ní féidir píopa ainmnithe a chur i gcomparáid le eolaire"
 
-#: diff-no-index.c
-msgid "git diff --no-index [<options>] <path> <path>"
-msgstr "git diff --no-index [<options>] <path> <path>"
+msgid "git diff --no-index [<options>] <path> <path> [<pathspec>...]"
+msgstr "git diff --no-index [<options>] <path> <path> [<pathspec>...]"
 
-#: diff-no-index.c
 msgid ""
 "Not a git repository. Use --no-index to compare two paths outside a working "
 "tree"
@@ -20420,17 +17088,21 @@
 "Ní stór git. Úsáid --no-index chun dhá chosán a chur i gcomparáid lasmuigh "
 "de chrann oibre"
 
-#: diff.c
+msgid ""
+"Limiting comparison with pathspecs is only supported if both paths are "
+"directories."
+msgstr ""
+"Ní thacaítear le comparáid theorannú le speictream cosáin ach amháin má tá "
+"an dá chonair ina n-eolairí."
+
 #, c-format
 msgid "  Failed to parse dirstat cut-off percentage '%s'\n"
 msgstr "  Theip ar chéatadán scoir dirstat '%s' a pharsáil\n"
 
-#: diff.c
 #, c-format
 msgid "  Unknown dirstat parameter '%s'\n"
 msgstr "  Paraiméadar dirstat anaithnid '%s'\n"
 
-#: diff.c
 msgid ""
 "color moved setting must be one of 'no', 'default', 'blocks', 'zebra', "
 "'dimmed-zebra', 'plain'"
@@ -20438,7 +17110,6 @@
 "caithfidh socrú dath a bhogadh a bheith ar cheann de 'níl', "
 "'réamhshocraithe', 'bloic', 'zebra', 'dimmed-zebra', 'simplí'"
 
-#: diff.c
 #, c-format
 msgid ""
 "unknown color-moved-ws mode '%s', possible values are 'ignore-space-change', "
@@ -20448,7 +17119,6 @@
 "'neamhaird-spas-athrú', 'neamhaird a dhéanamh ar spás-at-eol', 'neamhaird a "
 "dhéanamh ar uile-spás', 'ligead-indentation-change'"
 
-#: diff.c
 msgid ""
 "color-moved-ws: allow-indentation-change cannot be combined with other "
 "whitespace modes"
@@ -20456,17 +17126,14 @@
 "dath-moved-ws: ní féidir athrú ligead-ionchur a chomhcheangal le modhanna "
 "spás bán eile"
 
-#: diff.c
 #, c-format
 msgid "Unknown value for 'diff.submodule' config variable: '%s'"
 msgstr "Luach anaithnid d'athróg cumraithe 'diff.submodule': '%s'"
 
-#: diff.c merge-ort.c transport.c
 #, c-format
 msgid "unknown value for config '%s': %s"
 msgstr "luach anaithnid do chumraíocht '%s': %s"
 
-#: diff.c
 #, c-format
 msgid ""
 "Found errors in 'diff.dirstat' config variable:\n"
@@ -20475,33 +17142,27 @@
 "Earráidí aimsithe in athróg config 'diff.dirstat':\n"
 "%s"
 
-#: diff.c
 #, c-format
 msgid "external diff died, stopping at %s"
 msgstr "fuair diff seachtrach bás, ag stopadh ag %s"
 
-#: diff.c
 msgid "--follow requires exactly one pathspec"
 msgstr "Teastaíonn --follow go díreach cosán amháin"
 
-#: diff.c
 #, c-format
 msgid "pathspec magic not supported by --follow: %s"
 msgstr "draíocht pathspec nach dtacaíonn --follow: %s"
 
-#: diff.c parse-options.c
 #, c-format
 msgid "options '%s', '%s', '%s', and '%s' cannot be used together"
 msgstr "ní féidir roghanna '%s', '%s', '%s', agus '%s' a úsáid le chéile"
 
-#: diff.c
 #, c-format
 msgid "options '%s' and '%s' cannot be used together, use '%s' with '%s'"
 msgstr ""
 "ní féidir roghanna '%s' agus '%s' a úsáid le chéile, bain úsáid as '%s' le "
 "'%s'"
 
-#: diff.c
 #, c-format
 msgid ""
 "options '%s' and '%s' cannot be used together, use '%s' with '%s' and '%s'"
@@ -20509,17 +17170,14 @@
 "ní féidir roghanna '%s' agus '%s' a úsáid le chéile, bain úsáid as '%s' le "
 "'%s' agus '%s'"
 
-#: diff.c
 #, c-format
 msgid "invalid --stat value: %s"
 msgstr "luach --stat neamhbhailí: %s"
 
-#: diff.c parse-options.c
 #, c-format
 msgid "%s expects a numerical value"
 msgstr "Tá %s ag súil le luach uimhriúil"
 
-#: diff.c
 #, c-format
 msgid ""
 "Failed to parse --dirstat/-X option parameter:\n"
@@ -20528,195 +17186,151 @@
 "Theip ar pharaiméadar rogha --dirstat/-X a pháirseáil:\n"
 "%s"
 
-#: diff.c
 #, c-format
 msgid "unknown change class '%c' in --diff-filter=%s"
 msgstr "aicme athraithe anaithnid '%c' i --diff-filter=%s"
 
-#: diff.c
 #, c-format
 msgid "unknown value after ws-error-highlight=%.*s"
 msgstr "luach anaithnid tar éis ws-error-highlight =%.*s"
 
-#: diff.c
 #, c-format
 msgid "unable to resolve '%s'"
-msgstr "nach féidir '%s' a réiteach"
+msgstr "ní féidir '%s' a réiteach"
 
-#: diff.c
 #, c-format
 msgid "%s expects <n>/<m> form"
 msgstr "Tá %s ag súil le<n>/fo <m>irm"
 
-#: diff.c
 #, c-format
 msgid "%s expects a character, got '%s'"
 msgstr "Tá %s ag súil le carachtar, fuair '%s'"
 
-#: diff.c
 #, c-format
 msgid "bad --color-moved argument: %s"
 msgstr "argóint lochtach --color-moved: %s"
 
-#: diff.c
 #, c-format
 msgid "invalid mode '%s' in --color-moved-ws"
 msgstr "modh neamhbhailí '%s' i --color-moved-ws"
 
-#: diff.c
 #, c-format
 msgid "invalid argument to %s"
 msgstr "argóint neamhbhailí chuig %s"
 
-#: diff.c
 #, c-format
 msgid "invalid regex given to -I: '%s'"
 msgstr "regex neamhbhailí a thugtar do -I: '%s'"
 
-#: diff.c
 msgid "-G requires a non-empty argument"
 msgstr "Éilíonn -G argóint neamh-folamh"
 
-#: diff.c
 msgid "-S requires a non-empty argument"
 msgstr "Éilíonn -S argóint neamh-folamh"
 
-#: diff.c
 #, c-format
 msgid "failed to parse --submodule option parameter: '%s'"
 msgstr "theip ar pharaiméadar rogha --submodule a pháirseáil: '%s'"
 
-#: diff.c
 #, c-format
 msgid "bad --word-diff argument: %s"
 msgstr "argóint olc --word-diff: %s"
 
-#: diff.c
 msgid "Diff output format options"
 msgstr "Roghanna formáid aschuir diff"
 
-#: diff.c
 msgid "generate patch"
 msgstr "paiste a ghiniúint"
 
-#: diff.c
 msgid "<n>"
 msgstr "<n>"
 
-#: diff.c
 msgid "generate diffs with <n> lines context"
 msgstr "difríochtaí a ghiniúint le comhthéacs <n>lín"
 
-#: diff.c
 msgid "generate the diff in raw format"
 msgstr "giniúint an diff i bhformáid amh"
 
-#: diff.c
 msgid "synonym for '-p --raw'"
 msgstr "comhchiallach do '-p --raw'"
 
-#: diff.c
 msgid "synonym for '-p --stat'"
 msgstr "comhchiallach do '-p --stat'"
 
-#: diff.c
 msgid "machine friendly --stat"
 msgstr "cairdiúil le meaisín --stat"
 
-#: diff.c
 msgid "output only the last line of --stat"
 msgstr "aschur ach an líne dheireanach de --stat"
 
-#: diff.c
 msgid "<param1>,<param2>..."
 msgstr "<param1>,<param2>..."
 
-#: diff.c
 msgid ""
 "output the distribution of relative amount of changes for each sub-directory"
 msgstr "aschur dáileadh méid coibhneasta na n-athruithe do gach fo-eolaire"
 
-#: diff.c
 msgid "synonym for --dirstat=cumulative"
 msgstr "comhchiallach do --dirstat=cumulative"
 
-#: diff.c
 msgid "synonym for --dirstat=files,<param1>,<param2>..."
 msgstr "comhchiallaigh le haghaidh --dirstat=files,<param1>,<param2>..."
 
-#: diff.c
 msgid "warn if changes introduce conflict markers or whitespace errors"
 msgstr ""
 "rabhadh má thugann athruithe marcóirí coinbhleachta nó earráidí spás bán "
 "isteach"
 
-#: diff.c
 msgid "condensed summary such as creations, renames and mode changes"
 msgstr ""
 "achoimre chomhdhlúite mar chruthúcháin, athainmneacha agus athruithe mó"
 
-#: diff.c
 msgid "show only names of changed files"
 msgstr "taispeáint ach ainmneacha comhaid athraithe"
 
-#: diff.c
 msgid "show only names and status of changed files"
 msgstr "taispeáint ach ainmneacha agus stádas na gcomhaid athraithe"
 
-#: diff.c
 msgid "<width>[,<name-width>[,<count>]]"
 msgstr "<width>[, <name-width>[,<count>]]"
 
-#: diff.c
 msgid "generate diffstat"
 msgstr "diffstat a ghiniúint"
 
-#: diff.c
 msgid "<width>"
 msgstr "<width>"
 
-#: diff.c
 msgid "generate diffstat with a given width"
 msgstr "diffstat a ghiniúint le leithead ar leith"
 
-#: diff.c
 msgid "generate diffstat with a given name width"
 msgstr "diffstat a ghiniúint le leithead ainm ar leith"
 
-#: diff.c
 msgid "generate diffstat with a given graph width"
 msgstr "diffstat a ghiniúint le leithead graf ar leith"
 
-#: diff.c
 msgid "<count>"
 msgstr "<count>"
 
-#: diff.c
 msgid "generate diffstat with limited lines"
 msgstr "diffstat a ghiniúint le línte teoranta"
 
-#: diff.c
 msgid "generate compact summary in diffstat"
 msgstr "achoimre dlúth a ghiniúint i diffstat"
 
-#: diff.c
 msgid "output a binary diff that can be applied"
 msgstr "aschur diff dénártha is féidir a chur i bhfeidhm"
 
-#: diff.c
 msgid "show full pre- and post-image object names on the \"index\" lines"
 msgstr ""
 "taispeáint ainmneacha réad réad réamh-íomhá iomlána ar na línte “innéacs”"
 
-#: diff.c
 msgid "show colored diff"
 msgstr "taispeáin éagsúlacht daite"
 
-#: diff.c
 msgid "<kind>"
 msgstr "<kind>"
 
-#: diff.c
 msgid ""
 "highlight whitespace errors in the 'context', 'old' or 'new' lines in the "
 "diff"
@@ -20724,7 +17338,6 @@
 "aird a tharraingt ar earráidí spás bán sna línte 'comhthéacs', 'sean' nó "
 "'nua' sa diff"
 
-#: diff.c
 msgid ""
 "do not munge pathnames and use NULs as output field terminators in --raw or "
 "--numstat"
@@ -20732,93 +17345,71 @@
 "ná cuir ainmneacha cosáin agus bain úsáid as NULanna mar chríochnóirí réimse "
 "aschuir i --raw nó --numstat"
 
-#: diff.c
 msgid "<prefix>"
 msgstr "<prefix>"
 
-#: diff.c
 msgid "show the given source prefix instead of \"a/\""
 msgstr "taispeáint an réimír foinse a thugtar in ionad “a/”"
 
-#: diff.c
 msgid "show the given destination prefix instead of \"b/\""
 msgstr "taispeáin an réimír ceann scríbe tugtha in ionad “b/”"
 
-#: diff.c
 msgid "prepend an additional prefix to every line of output"
 msgstr "réimír bhreise a chur ar fáil do gach líne aschuir"
 
-#: diff.c
 msgid "do not show any source or destination prefix"
 msgstr "ná taispeáin aon réimír foinse nó ceann scríbe"
 
-#: diff.c
 msgid "use default prefixes a/ and b/"
 msgstr "bain úsáid as réamhshocraithe a/ agus b/"
 
-#: diff.c
 msgid "show context between diff hunks up to the specified number of lines"
 msgstr ""
 "comhthéacs a thaispeáint idir diff hunks suas go dtí an líon sonraithe línte"
 
-#: diff.c
 msgid "<char>"
 msgstr "<char>"
 
-#: diff.c
 msgid "specify the character to indicate a new line instead of '+'"
 msgstr "sonraigh an carachtar chun líne nua a léiriú in ionad '+'"
 
-#: diff.c
 msgid "specify the character to indicate an old line instead of '-'"
 msgstr "sonraigh an carachtar chun sean-líne a chur in iúl in ionad '-'"
 
-#: diff.c
 msgid "specify the character to indicate a context instead of ' '"
 msgstr "sonraigh an carachtar chun comhthéacs in ionad '' a chur in iúl"
 
-#: diff.c
 msgid "Diff rename options"
 msgstr "Roghanna athainmnithe Diff"
 
-#: diff.c
 msgid "<n>[/<m>]"
 msgstr "<n>[/<m>]"
 
-#: diff.c
 msgid "break complete rewrite changes into pairs of delete and create"
 msgstr ""
 "athruithe iomlána athscríobh a bhriseadh i bpéirí scrios agus cruthaigh"
 
-#: diff.c
 msgid "detect renames"
 msgstr "athainmneacha a bhrath"
 
-#: diff.c
 msgid "omit the preimage for deletes"
 msgstr "fág an réamhíomhá le haghaidh scriosadh"
 
-#: diff.c
 msgid "detect copies"
 msgstr "cóipí a bhrath"
 
-#: diff.c
 msgid "use unmodified files as source to find copies"
 msgstr "úsáid comhaid neamh-mhodhnaithe mar fhoinse chun cóipeanna a fháil"
 
-#: diff.c
 msgid "disable rename detection"
 msgstr "díchumasaigh braite athainmnithe"
 
-#: diff.c
 msgid "use empty blobs as rename source"
 msgstr "bain úsáid as blobs folamh mar fhoinse athainmnithe"
 
-#: diff.c
 msgid "continue listing the history of a file beyond renames"
 msgstr "leanúint ar aghaidh ag liostáil stair chomhaid thar athainmneacha"
 
-#: diff.c
 msgid ""
 "prevent rename/copy detection if the number of rename/copy targets exceeds "
 "given limit"
@@ -20826,226 +17417,182 @@
 "cosc a chur ar athainmniú/braite cóipeála má sháraíonn líon na spriocanna "
 "athainmniúcháin/cóipeála"
 
-#: diff.c
 msgid "Diff algorithm options"
 msgstr "Roghanna algartam Diff"
 
-#: diff.c
 msgid "produce the smallest possible diff"
 msgstr "an difríocht is lú is féidir a tháirgeadh"
 
-#: diff.c
 msgid "ignore whitespace when comparing lines"
 msgstr "neamhaird a dhéanamh ar spás bán agus tú ag comparáid"
 
-#: diff.c
 msgid "ignore changes in amount of whitespace"
 msgstr "neamhaird a dhéanamh ar athruithe i méid an spás bán"
 
-#: diff.c
 msgid "ignore changes in whitespace at EOL"
 msgstr "neamhaird a dhéanamh ar athruithe i spás bán ag EOL"
 
-#: diff.c
 msgid "ignore carrier-return at the end of line"
 msgstr "neamhaird a dhéanamh ar thuairisceán iompróra ag deireadh na líne"
 
-#: diff.c
 msgid "ignore changes whose lines are all blank"
 msgstr "neamhaird a dhéanamh ar athruithe atá a línte bán"
 
-#: diff.c
 msgid "<regex>"
 msgstr "<regex>"
 
-#: diff.c
 msgid "ignore changes whose all lines match <regex>"
 msgstr "neamhaird a dhéanamh ar athruithe a mheaitseann <regex>"
 
-#: diff.c
 msgid "heuristic to shift diff hunk boundaries for easy reading"
-msgstr "heuristic chun teorainneacha éagsúla a aistriú le haghaidh léamh éasca"
+msgstr ""
+"heorastach chun teorainneacha éagsúla a aistriú le haghaidh léitheoireachta "
+"éasca"
 
-#: diff.c
 msgid "generate diff using the \"patience diff\" algorithm"
 msgstr "diff a ghiniúint ag baint úsáide as an algartam “diff foighne”"
 
-#: diff.c
 msgid "generate diff using the \"histogram diff\" algorithm"
 msgstr "diff a ghiniúint ag baint úsáide as an algartam “diff histogram”"
 
-#: diff.c
 msgid "<text>"
 msgstr "<text>"
 
-#: diff.c
 msgid "generate diff using the \"anchored diff\" algorithm"
 msgstr "diff a ghiniúint ag baint úsáide as an algartam “diff ancáraithe”"
 
-#: diff.c
 msgid "<mode>"
 msgstr "<mode>"
 
-#: diff.c
 msgid "show word diff, using <mode> to delimit changed words"
 msgstr ""
 "taispeáint diff focal, ag baint úsáide as focail <mode>athraithe a theorannú"
 
-#: diff.c
 msgid "use <regex> to decide what a word is"
 msgstr "bain úsáid <regex>as chun cinneadh a dhéanamh cad é focal"
 
-#: diff.c
 msgid "equivalent to --word-diff=color --word-diff-regex=<regex>"
 msgstr "coibhéiseach le --word-diff=color --word-diff-regex=<regex>"
 
-#: diff.c
 msgid "moved lines of code are colored differently"
 msgstr "tá línte cóid bogadh daite difriúil"
 
-#: diff.c
 msgid "how white spaces are ignored in --color-moved"
 msgstr "conas a dhéantar neamhaird de spásanna bána i --color-moved"
 
-#: diff.c
 msgid "Other diff options"
 msgstr "Roghanna diff eile"
 
-#: diff.c
 msgid "when run from subdir, exclude changes outside and show relative paths"
 msgstr ""
 "nuair a bheidh á rith ó subdir, eisiamh athruithe lasmuigh agus taispeáin "
 "coibhneasta"
 
-#: diff.c
 msgid "treat all files as text"
 msgstr "déileáil le gach comhad mar théacs"
 
-#: diff.c
 msgid "swap two inputs, reverse the diff"
 msgstr "dhá ionchur a mhalartú, an diff a aisiompú"
 
-#: diff.c
 msgid "exit with 1 if there were differences, 0 otherwise"
 msgstr "imeacht le 1 má bhí difríochtaí ann, 0 ar shlí eile"
 
-#: diff.c
 msgid "disable all output of the program"
 msgstr "díchumasú gach aschur an chláir"
 
-#: diff.c
 msgid "allow an external diff helper to be executed"
 msgstr "ligean do chúntóir diff seachtrach a fhorghníomhú"
 
-#: diff.c
 msgid "run external text conversion filters when comparing binary files"
 msgstr "reáchtáil scagairí tiontaithe téacs seachtracha agus comhaid"
 
-#: diff.c
 msgid "<when>"
 msgstr "<when>"
 
-#: diff.c
 msgid "ignore changes to submodules in the diff generation"
 msgstr "neamhaird a dhéanamh ar athruithe ar fho-mhodúil sa ghiniúint diff"
 
-#: diff.c
 msgid "<format>"
 msgstr "<format>"
 
-#: diff.c
 msgid "specify how differences in submodules are shown"
 msgstr "sonraigh conas a thaispeántar na difríochtaí i bhfo-"
 
-#: diff.c
 msgid "hide 'git add -N' entries from the index"
 msgstr "folaigh iontrálacha 'git add -N' ón innéacs"
 
-#: diff.c
 msgid "treat 'git add -N' entries as real in the index"
 msgstr "déileáil le hiontrálacha 'git add -N' mar atá fíor san innéacs"
 
-#: diff.c
 msgid "<string>"
 msgstr "<string>"
 
-#: diff.c
 msgid ""
 "look for differences that change the number of occurrences of the specified "
 "string"
 msgstr ""
 "cuardaigh difríochtaí a athraíonn líon na n-imeachtaí sa sreang sonraithe"
 
-#: diff.c
 msgid ""
 "look for differences that change the number of occurrences of the specified "
 "regex"
 msgstr ""
 "cuardaigh difríochtaí a athraíonn líon na n-imeachtaí sa regex sonraithe"
 
-#: diff.c
 msgid "show all changes in the changeset with -S or -G"
 msgstr "taispeáint na hathruithe go léir sa tacar athraithe le -S nó -G"
 
-#: diff.c
 msgid "treat <string> in -S as extended POSIX regular expression"
 msgstr "caitheamh <string>le -S mar léiriú rialta POSIX leathnaithe"
 
-#: diff.c
 msgid "control the order in which files appear in the output"
 msgstr "rialú an t-ord ina bhfuil comhaid le feiceáil san aschur"
 
-#: diff.c
 msgid "<path>"
 msgstr "<path>"
 
-#: diff.c
 msgid "show the change in the specified path first"
 msgstr "taispeáin an t-athrú ar an gcosán sonraithe ar dtús"
 
-#: diff.c
 msgid "skip the output to the specified path"
 msgstr "scipeáil an t-aschur chuig an gcosán sonraithe"
 
-#: diff.c
 msgid "<object-id>"
 msgstr "<object-id>"
 
-#: diff.c
 msgid ""
 "look for differences that change the number of occurrences of the specified "
 "object"
 msgstr "cuardaigh difríochtaí a athraíonn líon na n-earraí den réad sonraithe"
 
-#: diff.c
 msgid "[(A|C|D|M|R|T|U|X|B)...[*]]"
 msgstr "[(A|C|D|M|R|T|U|X|B)... [*]]"
 
-#: diff.c
 msgid "select files by diff type"
 msgstr "roghnaigh comhaid de réir cineál diff"
 
-#: diff.c
+msgid "<depth>"
+msgstr "<depth>"
+
+msgid "maximum tree depth to recurse"
+msgstr "uasmhéid doimhneacht crainn le hathfhillteach"
+
 msgid "<file>"
 msgstr "<file>"
 
-#: diff.c
 msgid "output to a specific file"
 msgstr "aschur chuig comhad ar leith"
 
-#: diff.c
 msgid "exhaustive rename detection was skipped due to too many files."
 msgstr ""
 "scipeánadh braite athainmnithe uileghabhálach mar gheall ar an iomarca "
 "comhaid."
 
-#: diff.c
 msgid "only found copies from modified paths due to too many files."
 msgstr ""
 "ní bhfuarthas ach cóipeanna ó chosáin modhnaithe mar gheall ar an iomarca "
 "comhaid."
 
-#: diff.c
 #, c-format
 msgid ""
 "you may want to set your %s variable to at least %d and retry the command."
@@ -21053,61 +17600,49 @@
 "b'fhéidir gur mhaith leat d'athróg %s a shocrú go %d ar a laghad agus "
 "iarracht a dhéanamh arís ar an ordú."
 
-#: diffcore-order.c
 #, c-format
 msgid "failed to read orderfile '%s'"
 msgstr "theip ar chomhad ordaithe '%s' a léamh"
 
-#: diffcore-rename.c
 msgid "Performing inexact rename detection"
 msgstr "Braite athainmnithe míchruinn a dhéanamh"
 
-#: diffcore-rotate.c
 #, c-format
 msgid "No such path '%s' in the diff"
 msgstr "Níl aon chosán den sórt sin '%s' sa diff"
 
-#: dir.c
 #, c-format
 msgid "pathspec '%s' did not match any file(s) known to git"
 msgstr "níor mheaitseáil pathspec '%s' aon chomhad (í) ar eolas ag git"
 
-#: dir.c
 #, c-format
 msgid "unrecognized pattern: '%s'"
 msgstr "patrún gan aithint: '%s'"
 
-#: dir.c
 #, c-format
 msgid "unrecognized negative pattern: '%s'"
 msgstr "patrún diúltach gan aithint: '%s'"
 
-#: dir.c
 #, c-format
 msgid "your sparse-checkout file may have issues: pattern '%s' is repeated"
 msgstr ""
 "d'fhéadfadh fadhbanna a bheith ag do chomhad seiceála neamhchoitianta: "
 "déantar patrún '%s' arís eile"
 
-#: dir.c
 msgid "disabling cone pattern matching"
 msgstr "meaitseáil patrún cón a dhíchumas"
 
-#: dir.c
 #, c-format
 msgid "cannot use %s as an exclude file"
 msgstr "ní féidir %s a úsáid mar chomhad eisiata"
 
-#: dir.c
 msgid "failed to get kernel name and information"
 msgstr "theip ar ainm eithne agus faisnéis a fháil"
 
-#: dir.c
 msgid "untracked cache is disabled on this system or location"
 msgstr ""
 "tá taisce neamhrianaithe díchumasaithe ar an gcóras nó ar an suíomh seo"
 
-#: dir.c
 msgid ""
 "No directory name could be guessed.\n"
 "Please specify a directory on the command line"
@@ -21115,56 +17650,94 @@
 "Ní fhéadfaí aon ainm eolaire a thuairim.\n"
 "Sonraigh eolaire ar an líne ordaithe le do thoil"
 
-#: dir.c
 #, c-format
 msgid "index file corrupt in repo %s"
 msgstr "comhad innéacs truaillithe i repo %s"
 
-#: dir.c
 #, c-format
 msgid "could not create directories for %s"
 msgstr "ní fhéadfaí eolairí a chruthú do %s"
 
-#: dir.c
 #, c-format
 msgid "could not migrate git directory from '%s' to '%s'"
 msgstr "ní fhéadfaí eolaire git a aistriú ó '%s' go '%s'"
 
-#: editor.c
 #, c-format
 msgid "hint: Waiting for your editor to close the file...%c"
 msgstr "leid: Ag fanacht go ndúnfaidh d'eagarthóir an comhad... %c"
 
-#: editor.c sequencer.c wrapper.c
 #, c-format
 msgid "could not write to '%s'"
 msgstr "ní fhéadfaí scríobh chuig '%s'"
 
-#: editor.c
 #, c-format
 msgid "could not edit '%s'"
 msgstr "ní fhéadfaí '%s' a chur in eagar"
 
-#: entry.c
 msgid "Filtering content"
 msgstr "Ábhar scagadh"
 
-#: entry.c
 #, c-format
 msgid "could not stat file '%s'"
 msgstr "ní fhéadfaí an comhad '%s' a statú"
 
-#: environment.c
 #, c-format
 msgid "bad git namespace path \"%s\""
 msgstr "cosán spás ainmneacha git go dona “%s”"
 
-#: exec-cmd.c
+#, c-format
+msgid "invalid value for variable %s"
+msgstr "luach neamhbhailí don athróg %s"
+
+#, c-format
+msgid "ignoring unknown core.fsync component '%s'"
+msgstr "neamhaird a dhéanamh ar chomhpháirt core.fsync anaithnid '%s'"
+
+#, c-format
+msgid "abbrev length out of range: %d"
+msgstr "fad a ghiorrú lasmuigh den raon: %d"
+
+#, c-format
+msgid "bad zlib compression level %d"
+msgstr "droch-leibhéal comhbhrúite zlib %d"
+
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "Ní féidir le líne nua a bheith ag %s"
+
+#, c-format
+msgid "%s must have at least one character"
+msgstr "Ní mór carachtar amháin ar a laghad a bheith ag %s"
+
+#, c-format
+msgid "ignoring unknown core.fsyncMethod value '%s'"
+msgstr "neamhaird a dhéanamh ar luach core.fsyncMethod anaithnid '%s'"
+
+msgid "core.fsyncObjectFiles is deprecated; use core.fsync instead"
+msgstr ""
+"tá core.fsyncObjectFiles díscothaithe; bain úsáid as core.fsync ina ionad"
+
+#, c-format
+msgid "invalid mode for object creation: %s"
+msgstr "modh neamhbhailí chun réad a chruthú: %s"
+
+#, c-format
+msgid "malformed value for %s"
+msgstr "luach mífhoirmithe do %s"
+
+#, c-format
+msgid "malformed value for %s: %s"
+msgstr "luach mífhoirmithe do %s: %s"
+
+msgid "must be one of nothing, matching, simple, upstream or current"
+msgstr ""
+"caithfidh sé a bheith ar cheann de rud ar bith, meaitseálach, simplí, suas "
+"srutha nó reatha"
+
 #, c-format
 msgid "too many args to run %s"
 msgstr "an iomarca args chun %s a rith"
 
-#: fetch-pack.c
 #, c-format
 msgid ""
 "You are attempting to fetch %s, which is in the commit graph file but not in "
@@ -21180,193 +17753,147 @@
 "easnamh a athghabháil, bain úsáid as 'git fetch --refetch' leis an réad atá "
 "ar iarraidh."
 
-#: fetch-pack.c
 msgid "git fetch-pack: expected shallow list"
 msgstr "git fetch-pack: liosta éadomhain a bhfuiltear ag súil leis"
 
-#: fetch-pack.c
 msgid "git fetch-pack: expected a flush packet after shallow list"
 msgstr ""
 "git fetch-pack: bhíothas ag súil le paicéad sruthán tar éis liosta éadrom"
 
-#: fetch-pack.c
 msgid "git fetch-pack: expected ACK/NAK, got a flush packet"
 msgstr "git fetch-pack: ag súil le ACK/NAK, fuair sé paicéad sruthán"
 
-#: fetch-pack.c
 #, c-format
 msgid "git fetch-pack: expected ACK/NAK, got '%s'"
 msgstr "git fetch-pack: ag súil le ACK/NAK, fuair '%s'"
 
-#: fetch-pack.c
 msgid "unable to write to remote"
-msgstr "in ann scríobh chuig iargúlta"
+msgstr "ní féidir scríobh chuig an gcianrialtán"
 
-#: fetch-pack.c
 msgid "Server supports filter"
 msgstr "Tacaíonn freastalaí le sc"
 
-#: fetch-pack.c
 #, c-format
 msgid "invalid shallow line: %s"
 msgstr "líne éadomhain neamhbhailí: %s"
 
-#: fetch-pack.c
 #, c-format
 msgid "invalid unshallow line: %s"
 msgstr "líne neamhéadrom neamhbhailí: %s"
 
-#: fetch-pack.c
-#, c-format
-msgid "object not found: %s"
-msgstr "níor aimsíodh réad: %s"
-
-#: fetch-pack.c
 #, c-format
 msgid "error in object: %s"
 msgstr "earráid i réad: %s"
 
-#: fetch-pack.c
 #, c-format
 msgid "no shallow found: %s"
 msgstr "níl aon éadrom aimsithe: %s"
 
-#: fetch-pack.c
 #, c-format
 msgid "expected shallow/unshallow, got %s"
 msgstr "bhíothas ag súil leis íol/neamhéadrom, fuair %s"
 
-#: fetch-pack.c
 #, c-format
 msgid "got %s %d %s"
 msgstr "fuair %s %d %s"
 
-#: fetch-pack.c
 #, c-format
 msgid "invalid commit %s"
 msgstr "tiomantas neamhbhailí %s"
 
-#: fetch-pack.c
 msgid "giving up"
 msgstr "tabhairt suas"
 
-#: fetch-pack.c progress.h
 msgid "done"
 msgstr "déanta"
 
-#: fetch-pack.c
 #, c-format
 msgid "got %s (%d) %s"
 msgstr "fuair %s (%d) %s"
 
-#: fetch-pack.c
 #, c-format
 msgid "Marking %s as complete"
 msgstr "Mharcáil %s mar iomlán"
 
-#: fetch-pack.c
 #, c-format
 msgid "already have %s (%s)"
 msgstr "tá %s ann cheana féin (%s)"
 
-#: fetch-pack.c
 msgid "fetch-pack: unable to fork off sideband demultiplexer"
 msgstr "pacáiste tarchuir: ní féidir le démultiplexer banna taobh a fhorc"
 
-#: fetch-pack.c
 msgid "protocol error: bad pack header"
 msgstr "earráid prótacal: ceanntásc an phacá"
 
-#: fetch-pack.c
 #, c-format
 msgid "fetch-pack: unable to fork off %s"
 msgstr "fetch-pack: ní féidir %s a fhorc"
 
-#: fetch-pack.c
 msgid "fetch-pack: invalid index-pack output"
 msgstr "fetch-pack: aschur pacáiste innéacs-neamhbhailí"
 
-#: fetch-pack.c
 #, c-format
 msgid "%s failed"
 msgstr "Theip ar %s"
 
-#: fetch-pack.c
 msgid "error in sideband demultiplexer"
 msgstr "earráid i demultiplexer taobhbanna"
 
-#: fetch-pack.c
 #, c-format
 msgid "Server version is %.*s"
 msgstr "Is é leagan freastalaí %.*s"
 
-#: fetch-pack.c
 #, c-format
 msgid "Server supports %s"
 msgstr "Tacaíonn freastalaí le %s"
 
-#: fetch-pack.c
 msgid "Server does not support shallow clients"
 msgstr "Ní thacaíonn freastalaí le cliaint éadrom"
 
-#: fetch-pack.c
 msgid "Server does not support --shallow-since"
 msgstr "Ní thacaíonn freastalaí le --shallow-since"
 
-#: fetch-pack.c
 msgid "Server does not support --shallow-exclude"
 msgstr "Ní thacaíonn freastalaí le --shallow-exclude"
 
-#: fetch-pack.c
 msgid "Server does not support --deepen"
 msgstr "Ní thacaíonn freastalaí le --deepen"
 
-#: fetch-pack.c
 msgid "Server does not support this repository's object format"
 msgstr "Ní thacaíonn freastalaí le formáid réad an stór seo"
 
-#: fetch-pack.c
 msgid "no common commits"
 msgstr "gan aon gealltanais choiteann"
 
-#: fetch-pack.c
 msgid "git fetch-pack: fetch failed."
 msgstr "git fetch-pack: theip ar fáil."
 
-#: fetch-pack.c
 #, c-format
 msgid "mismatched algorithms: client %s; server %s"
 msgstr "halgartaim míchomhoiriúnach: cliant %s; freastalaí %s"
 
-#: fetch-pack.c
 #, c-format
 msgid "the server does not support algorithm '%s'"
 msgstr "ní thacaíonn an freastalaí algartam '%s'"
 
-#: fetch-pack.c
 msgid "Server does not support shallow requests"
 msgstr "Ní thacaíonn an freastalaí le hiarratais"
 
-#: fetch-pack.c
 msgid "unable to write request to remote"
-msgstr "in ann iarratas a scríobh chuig iargúlta"
+msgstr "ní féidir iarratas a scríobh chuig an iargúlta"
 
-#: fetch-pack.c
 #, c-format
 msgid "expected '%s', received '%s'"
 msgstr "bhíothas ag súil le '%s', fuarthas '%s'"
 
-#: fetch-pack.c
 #, c-format
 msgid "expected '%s'"
 msgstr "ag súil le '%s'"
 
-#: fetch-pack.c
 #, c-format
 msgid "unexpected acknowledgment line: '%s'"
 msgstr "líne admhaithe gan choinne: '%s'"
 
-#: fetch-pack.c
 #, c-format
 msgid "error processing acks: %d"
 msgstr "earráidí próiseála earráide: %d"
@@ -21374,7 +17901,6 @@
 #. TRANSLATORS: The parameter will be 'ready', a protocol
 #. keyword.
 #.
-#: fetch-pack.c
 #, c-format
 msgid "expected packfile to be sent after '%s'"
 msgstr "táthar ag súil go seolfar pacáid tar éis '%s'"
@@ -21382,94 +17908,75 @@
 #. TRANSLATORS: The parameter will be 'ready', a protocol
 #. keyword.
 #.
-#: fetch-pack.c
 #, c-format
 msgid "expected no other sections to be sent after no '%s'"
 msgstr ""
 "bhíothas ag súil nach gcuirfear aon chuid eile a sheoladh tar éis gan '%s'"
 
-#: fetch-pack.c
 #, c-format
 msgid "error processing shallow info: %d"
 msgstr "earráid ag próiseáil faisnéis éadrom: %d"
 
-#: fetch-pack.c
 #, c-format
 msgid "expected wanted-ref, got '%s'"
 msgstr "bhíothas ag súil leis an tagairt a theastaigh, fuair '%s'"
 
-#: fetch-pack.c
 #, c-format
 msgid "unexpected wanted-ref: '%s'"
 msgstr "gan choinne wanted-ref: '%s'"
 
-#: fetch-pack.c
 #, c-format
 msgid "error processing wanted refs: %d"
 msgstr "próiseáil earráidí a theastaíonn referens: %d"
 
-#: fetch-pack.c
 msgid "git fetch-pack: expected response end packet"
 msgstr "git fetch-pack: paicéad deiridh freagartha ag súil leis"
 
-#: fetch-pack.c
 msgid "no matching remote head"
 msgstr "gan ceann iargúlta meaitseála"
 
-#: fetch-pack.c
 msgid "unexpected 'ready' from remote"
 msgstr "gan choinne 'réidh' ó iargúlta"
 
-#: fetch-pack.c
 #, c-format
 msgid "no such remote ref %s"
 msgstr "aon tagairt iargúlta den sórt sin %s"
 
-#: fetch-pack.c
 #, c-format
 msgid "Server does not allow request for unadvertised object %s"
 msgstr "Ní cheadaíonn freastalaí iarraidh ar réad neamhfhógraithe %s"
 
-#: fsmonitor-ipc.c
 #, c-format
 msgid "fsmonitor_ipc__send_query: invalid path '%s'"
 msgstr "fsmonitor_ipc__send_query: cosán neamhbhailí '%s'"
 
-#: fsmonitor-ipc.c
 #, c-format
 msgid "fsmonitor_ipc__send_query: unspecified error on '%s'"
 msgstr "fsmonitor_ipc__send_query: earráid neamhshonraithe ar '%s'"
 
-#: fsmonitor-ipc.c
 msgid "fsmonitor--daemon is not running"
 msgstr "níl fsmonitor--daemon ag rith"
 
-#: fsmonitor-ipc.c
 #, c-format
 msgid "could not send '%s' command to fsmonitor--daemon"
 msgstr "ní fhéadfaí ordú '%s' a sheoladh chuig fsmonitor--daemon"
 
-#: fsmonitor-settings.c
 #, c-format
 msgid "bare repository '%s' is incompatible with fsmonitor"
 msgstr "níl stór lom '%s' neamhoiriúnach le fsmonitor"
 
-#: fsmonitor-settings.c
 #, c-format
 msgid "repository '%s' is incompatible with fsmonitor due to errors"
 msgstr "tá stór '%s' neamh-chomhoiriúnach le fsmonitor de bharr earráidí"
 
-#: fsmonitor-settings.c
 #, c-format
 msgid "remote repository '%s' is incompatible with fsmonitor"
 msgstr "níl stór iargúlta '%s' neamhoiriúnach le fsmonitor"
 
-#: fsmonitor-settings.c
 #, c-format
 msgid "virtual repository '%s' is incompatible with fsmonitor"
 msgstr "níl stór fíorúil '%s' neamhoiriúnach le fsmonitor"
 
-#: fsmonitor-settings.c
 #, c-format
 msgid ""
 "socket directory '%s' is incompatible with fsmonitor due to lack of Unix "
@@ -21478,7 +17985,6 @@
 "tá eolaire soicéad '%s' neamhoiriúnach le fsmonitor mar gheall ar easpa "
 "tacaíochta soicéid Unix"
 
-#: git.c
 msgid ""
 "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n"
 "           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
@@ -21498,7 +18004,6 @@
 "env=<name>=<envvar>]\n"
 "           <command> [<args>]"
 
-#: git.c
 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"
@@ -21511,47 +18016,38 @@
 "léamh faoi fho-ordú nó coincheap ar leith.\n"
 "Féach 'git help git' le haghaidh forbhreathnú ar an gcóras."
 
-#: git.c help.c
 #, c-format
 msgid "unsupported command listing type '%s'"
 msgstr "cineál liostaithe ordaithe gan tacaíocht '%s'"
 
-#: git.c
 #, c-format
 msgid "no directory given for '%s' option\n"
 msgstr "níl aon eolaire tugtha do rogha '%s'\n"
 
-#: git.c
 #, c-format
 msgid "no namespace given for --namespace\n"
 msgstr "aon spás ainmneacha a thugtar do --namespace\n"
 
-#: git.c
 #, c-format
 msgid "-c expects a configuration string\n"
 msgstr "-c ag súil le teaghrán cumraíochta\n"
 
-#: git.c
 #, c-format
 msgid "no config key given for --config-env\n"
 msgstr "níl aon eochair chumraithe tugtha do --config-env\n"
 
-#: git.c
 #, c-format
 msgid "no attribute source given for --attr-source\n"
 msgstr "níor tugadh foinse tréith do --attr-source\n"
 
-#: git.c
 #, c-format
 msgid "unknown option: %s\n"
 msgstr "rogha anaithnid: %s\n"
 
-#: git.c
 #, c-format
 msgid "while expanding alias '%s': '%s'"
 msgstr "agus ainm '%s' á leathnú: '%s'"
 
-#: git.c
 #, c-format
 msgid ""
 "alias '%s' changes environment variables.\n"
@@ -21560,39 +18056,31 @@
 "athraíonn alias '%s' athróga comhshaoil.\n"
 "Is féidir leat úsáid a bhaint as '!git' san alias chun é seo a dhéanamh"
 
-#: git.c
 #, c-format
 msgid "empty alias for %s"
 msgstr "alias folamh do %s"
 
-#: git.c
 #, c-format
 msgid "recursive alias: %s"
 msgstr "ainm athfhillteach: %s"
 
-#: git.c
-msgid "write failure on standard output"
-msgstr "teip scríobh ar aschur caighdeánach"
-
-#: git.c
-msgid "unknown write failure on standard output"
-msgstr "teip scríbhneoireachta anaithnid ar aschur"
-
-#: git.c
-msgid "close failed on standard output"
-msgstr "theip ar dhún ar aschur caighdeánach"
-
-#: git.c
 #, c-format
 msgid "alias loop detected: expansion of '%s' does not terminate:%s"
 msgstr "aimsíodh lúb alias: ní chuirtear deireadh le leathnú '%s': %s"
 
-#: git.c
+msgid "write failure on standard output"
+msgstr "teip scríobh ar aschur caighdeánach"
+
+msgid "unknown write failure on standard output"
+msgstr "teip scríbhneoireachta anaithnid ar aschur"
+
+msgid "close failed on standard output"
+msgstr "theip ar dhún ar aschur caighdeánach"
+
 #, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "ní féidir %s a láimhseáil mar thógáil"
 
-#: git.c
 #, c-format
 msgid ""
 "usage: %s\n"
@@ -21601,26 +18089,21 @@
 "úsáid: %s\n"
 "\n"
 
-#: git.c
 #, c-format
 msgid "expansion of alias '%s' failed; '%s' is not a git command\n"
 msgstr "theip ar leathnú an leasainm '%s'; ní ordú git é '%s'\n"
 
-#: git.c
 #, c-format
 msgid "failed to run command '%s': %s\n"
 msgstr "theip ort an t-ordú '%s' a reáchtáil: %s\n"
 
-#: gpg-interface.c
 msgid "could not create temporary file"
 msgstr "ní fhéadfaí comhad sealadach a chruthú"
 
-#: gpg-interface.c
 #, c-format
 msgid "failed writing detached signature to '%s'"
 msgstr "theip ar shíniú scoite a scríobh chuig '%s'"
 
-#: gpg-interface.c
 msgid ""
 "gpg.ssh.allowedSignersFile needs to be configured and exist for ssh "
 "signature verification"
@@ -21628,7 +18111,6 @@
 "ní mór gpg.ssh.allowedSignersFile a chumrú agus a bheith ann le haghaidh "
 "fíorú sínithe ssh"
 
-#: gpg-interface.c
 msgid ""
 "ssh-keygen -Y find-principals/verify is needed for ssh signature "
 "verification (available in openssh version 8.2p1+)"
@@ -21636,39 +18118,40 @@
 "tá gá le ssh-keygen -Y aimsithe/fíorú le haghaidh fíorú sínithe ssh (ar fáil "
 "i leagan openssh 8.2p1 +)"
 
-#: gpg-interface.c
 #, c-format
 msgid "ssh signing revocation file configured but not found: %s"
 msgstr "comhad cúlghairm sínithe ssh cumraithe ach níor aimsíodh: %s"
 
-#: gpg-interface.c
 #, c-format
 msgid "bad/incompatible signature '%s'"
 msgstr "síniú droch-/neamhchomhoiriúnach '%s'"
 
-#: gpg-interface.c
 #, c-format
 msgid "failed to get the ssh fingerprint for key '%s'"
 msgstr "theip ar mhéarloirg ssh a fháil don eochair '%s'"
 
-#: gpg-interface.c
+#, c-format
+msgid "failed to get the ssh fingerprint for key %s"
+msgstr "theip ar an méarloirg ssh a fháil don eochair %s"
+
 msgid ""
 "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
 msgstr "is gá user.signingkey nó gpg.ssh.defaultKeyCommand a chumrú"
 
-#: gpg-interface.c
+#, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr "am tógála mífhoirmithe gpg.ssh.defaultKeyCommand: %s"
+
 #, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr ""
 "d’éirigh le gpg.ssh.defaultKeyCommand ach níor tugadh aon eochracha ar ais: "
 "%s %s"
 
-#: gpg-interface.c
 #, c-format
 msgid "gpg.ssh.defaultKeyCommand failed: %s %s"
 msgstr "theip ar gpg.ssh.defaultKeyCommand: %s %s"
 
-#: gpg-interface.c
 #, c-format
 msgid ""
 "gpg failed to sign the data:\n"
@@ -21677,21 +18160,17 @@
 "theip ar gpg na sonraí a shíniú:\n"
 "%s"
 
-#: gpg-interface.c
 msgid "user.signingKey needs to be set for ssh signing"
 msgstr "ní mór user.signingKey a shocrú le haghaidh síniú ssh"
 
-#: gpg-interface.c
 #, c-format
 msgid "failed writing ssh signing key to '%s'"
 msgstr "theip ar an eochair sínithe ssh a scríobh chuig '%s'"
 
-#: gpg-interface.c
 #, c-format
 msgid "failed writing ssh signing key buffer to '%s'"
 msgstr "theip ar scríobh ssh a shíniú maolán eochair chuig '%s'"
 
-#: gpg-interface.c
 msgid ""
 "ssh-keygen -Y sign is needed for ssh signing (available in openssh version "
 "8.2p1+)"
@@ -21699,17 +18178,14 @@
 "ssh-keygen -Y comhartha ag teastáil le haghaidh síniú ssh (ar fáil i leagan "
 "openssh 8.2p1+)"
 
-#: gpg-interface.c
 #, c-format
 msgid "failed reading ssh signing data buffer from '%s'"
 msgstr "theip ar mhaolán sonraí sínithe ssh a léamh ó '%s'"
 
-#: graph.c
 #, c-format
 msgid "ignored invalid color '%.*s' in log.graphColors"
 msgstr "neamhaird ar dhath neamhbhailí '%.*s' i log.graphColors"
 
-#: grep.c
 msgid ""
 "given pattern contains NULL byte (via -f <file>). This is only supported "
 "with -P under PCRE v2"
@@ -21717,117 +18193,90 @@
 "tá byte NULL (trí -f<file>) i bpatrún tugtha. Ní thacaítear leis seo ach le "
 "-P faoi PCRE v2"
 
-#: grep.c
 #, c-format
 msgid "'%s': unable to read %s"
 msgstr "'%s': ní féidir %s a léamh"
 
-#: grep.c
 #, c-format
 msgid "'%s': short read"
 msgstr "'%s': léamh gearr"
 
-#: help.c
 msgid "start a working area (see also: git help tutorial)"
 msgstr "tús a chur le limistéar oibre (féach freisin: teagaisc cabhrach git)"
 
-#: help.c
 msgid "work on the current change (see also: git help everyday)"
 msgstr "obair ar an athrú reatha (féach freisin: git help gach lá)"
 
-#: help.c
 msgid "examine the history and state (see also: git help revisions)"
 msgstr ""
 "scrúdú a dhéanamh ar an stair agus an stát (féach freisin: athbhreithnithe "
 "cabhrach git)"
 
-#: help.c
 msgid "grow, mark and tweak your common history"
 msgstr "do stair choiteann a fhás, a mharcáil agus a athrú"
 
-#: help.c
 msgid "collaborate (see also: git help workflows)"
 msgstr "comhoibriú (féach freisin: sreafaí oibre cabhrach git)"
 
-#: help.c
 msgid "Main Porcelain Commands"
 msgstr "Príomh-Orduithe Poirce"
 
-#: help.c
 msgid "Ancillary Commands / Manipulators"
 msgstr "Orduithe Coimhdeachta/Ionramhálaí"
 
-#: help.c
 msgid "Ancillary Commands / Interrogators"
 msgstr "Orduithe Coimhdeacha/Ceisteoirí"
 
-#: help.c
 msgid "Interacting with Others"
 msgstr "Idirghníomhú le daoine eile"
 
-#: help.c
 msgid "Low-level Commands / Manipulators"
 msgstr "Orduithe Ísealleibhéil/Ionramhálaithe"
 
-#: help.c
 msgid "Low-level Commands / Interrogators"
 msgstr "Orduithe ísealleibhéil/ceisteoirí"
 
-#: help.c
 msgid "Low-level Commands / Syncing Repositories"
 msgstr "Orduithe Leibhéal Íseal/Stóráin Sioncrónaithe"
 
-#: help.c
 msgid "Low-level Commands / Internal Helpers"
 msgstr "Orduithe Leibhéal Íseal/Cúntóirí Inmheánacha"
 
-#: help.c
 msgid "User-facing repository, command and file interfaces"
 msgstr "Comhéadain stór, ordaithe agus comhad atá os comhair úsáideora"
 
-#: help.c
 msgid "Developer-facing file formats, protocols and other interfaces"
 msgstr ""
 "Formáidí comhaid, prótacail agus comhéadain eile atá os comhair an fhorbróra"
 
-#: help.c
 #, c-format
 msgid "available git commands in '%s'"
 msgstr "orduithe git atá ar fáil i '%s'"
 
-#: help.c
 msgid "git commands available from elsewhere on your $PATH"
-msgstr "orduithe git ar fáil ó áiteanna eile ar do $PATH"
+msgstr "git orduithe atá ar fáil ó áit eile ar do $PATH"
 
-#: help.c
 msgid "These are common Git commands used in various situations:"
 msgstr "Seo orduithe coitianta Git a úsáidtear i gcásanna éagsúla:"
 
-#: help.c
 msgid "The Git concept guides are:"
 msgstr "Is iad na treoracha coincheap Git:"
 
-#: help.c
 msgid "User-facing repository, command and file interfaces:"
 msgstr "Stóráil, ordaithe agus comhéadain comhad atá os comhair úsáideora:"
 
-#: help.c
 msgid "File formats, protocols and other developer interfaces:"
 msgstr "Formáidí comhaid, prótacail agus comhéadain forbróra eile:"
 
-#: help.c
 msgid "External commands"
 msgstr "Orduithe seachtracha"
 
-#: help.c
 msgid "Command aliases"
 msgstr "Ainmneacha ordaithe"
 
-#: help.c
 msgid "See 'git help <command>' to read about a specific subcommand"
 msgstr "Féach 'git help <command>'chun léamh faoi fho-ordú ar leith"
 
-#: help.c
 #, c-format
 msgid ""
 "'%s' appears to be a git command, but we were not\n"
@@ -21836,39 +18285,32 @@
 "Is cosúil gur ordú git é '%s', ach ní raibh muid\n"
 "in ann é a fhorghníomhú. B'fhéidir go bhfuil git-%s briste?"
 
-#: help.c
 #, c-format
 msgid "git: '%s' is not a git command. See 'git --help'."
 msgstr "git: Ní ordú git é '%s'. Féach 'git --help'."
 
-#: help.c
 msgid "Uh oh. Your system reports no Git commands at all."
 msgstr ""
 "Ó, a Dhia. Ní thuairiscíonn do chóras aon orduithe Git ar chor ar bith."
 
-#: help.c
 #, c-format
 msgid "WARNING: You called a Git command named '%s', which does not exist."
 msgstr "RABHADH: Ghlaoigh tú ordú Git darb ainm '%s', nach bhfuil ann."
 
-#: help.c
 #, c-format
 msgid "Continuing under the assumption that you meant '%s'."
 msgstr "Ag leanúint faoin toimhde gur chiallaigh tú '%s'."
 
-#: help.c
 #, c-format
 msgid "Run '%s' instead [y/N]? "
 msgstr "Rith '%s' ina ionad sin [y/N]? "
 
-#: help.c
 #, c-format
 msgid "Continuing in %0.1f seconds, assuming that you meant '%s'."
 msgstr ""
 "Ag leanúint ar aghaidh i %0.1f soicind, ag glacadh leis gur chiallaigh tú "
 "'%s'."
 
-#: help.c
 msgid ""
 "\n"
 "The most similar command is"
@@ -21885,16 +18327,13 @@
 "\n"
 "Is iad na horduithe is cosúla ná"
 
-#: help.c
 msgid "git version [--build-options]"
-msgstr "leagan git [--build-options]"
+msgstr "git version [--build-options]"
 
-#: help.c
 #, c-format
 msgid "%s: %s - %s"
 msgstr "%s: %s - %s"
 
-#: help.c
 msgid ""
 "\n"
 "Did you mean this?"
@@ -21911,7 +18350,6 @@
 "\n"
 "An raibh ceann acu seo i gceist agat?"
 
-#: hook.c
 #, c-format
 msgid ""
 "The '%s' hook was ignored because it's not set as executable.\n"
@@ -21922,78 +18360,68 @@
 "Is féidir leat an rabhadh seo a dhíchumasú le `git config set "
 "advice.ignoredHook false `."
 
-#: http-fetch.c
 msgid "not a git repository"
-msgstr "ní stór git"
+msgstr "ní stór git é"
 
-#: http-fetch.c
 #, c-format
 msgid "argument to --packfile must be a valid hash (got '%s')"
 msgstr ""
 "caithfidh argóint chuig --packfile a bheith ina hash bailí (fuair '%s')"
 
-#: http.c
 #, c-format
 msgid "negative value for http.postBuffer; defaulting to %d"
 msgstr "luach diúltach do http.postBuffer; réamhshocraithe go %d"
 
-#: http.c
 msgid "Delegation control is not supported with cURL < 7.22.0"
 msgstr "Ní thacaítear le cURL <7.22.0 le rialú tarscaireachta"
 
-#: http.c
 msgid "Unknown value for http.proactiveauth"
 msgstr "Luach anaithnid do http.proactiveauth"
 
-#: http.c parse.c
 #, c-format
 msgid "failed to parse %s"
 msgstr "theip ar %s a pharsáil"
 
-#: http.c
 #, c-format
 msgid "Unsupported SSL backend '%s'. Supported SSL backends:"
 msgstr "'%s' cúltaca SSL gan tacaíocht. Cúltaca SSL tacaithe:"
 
-#: http.c
 #, c-format
 msgid "Could not set SSL backend to '%s': cURL was built without SSL backends"
 msgstr "Níor féidir cúltaca SSL a shocrú go '%s': Tógadh cURL gan cúltaca SSL"
 
-#: http.c
 #, c-format
 msgid "Could not set SSL backend to '%s': already set"
 msgstr "Níorbh fhéidir cúltaca SSL a shocrú go '%s': socraithe cheana féin"
 
-#: http.c
 msgid "refusing to read cookies from http.cookiefile '-'"
 msgstr "diúltú fianáin a léamh ó http.cookiefile '-'"
 
-#: http.c
 msgid "ignoring http.savecookies for empty http.cookiefile"
 msgstr ""
 "neamhaird a dhéanamh ar http.savecookies le haghaidh http.cookiefile folamh"
 
-#: http.c
 #, c-format
 msgid ""
 "unable to update url base from redirection:\n"
 "  asked for: %s\n"
 "   redirect: %s"
 msgstr ""
-"in ann bonn url a nuashonrú ó atreorú:\n"
-" iarrtha ar: %s\n"
-" atreorú: %s"
+"ní féidir bunachar url a nuashonrú ón atreorú:\n"
+"  iarrtha: %s\n"
+"  atreorú: %s"
 
-#: ident.c
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr "uimhir ró-mhór le léiriú mar curl_off_t ar an ardán seo: %<PRIuMAX>"
+
 msgid "Author identity unknown\n"
 msgstr "Céannacht an údair anaithnid\n"
 
-#: ident.c
 msgid "Committer identity unknown\n"
 msgstr "Céannacht an chomórtais anaithnid\n"
 
-#: ident.c
 msgid ""
 "\n"
 "*** Please tell me who you are.\n"
@@ -22018,103 +18446,107 @@
 "chun féiniúlacht réamhshocraithe do chuntais a shocrú.\n"
 "Fág --global chun an aitheantas a shocrú sa stór seo amháin.\n"
 
-#: ident.c
 msgid "no email was given and auto-detection is disabled"
 msgstr "níor tugadh aon ríomhphost agus tá brath uathoibríoch faoi"
 
-#: ident.c
 #, c-format
 msgid "unable to auto-detect email address (got '%s')"
-msgstr "in ann seoladh ríomhphoist a bhrath go huathoibríoch (fuair '%s')"
+msgstr ""
+"ní féidir seoladh ríomhphoist a bhrath go huathoibríoch (fuarthas '%s')"
 
-#: ident.c
 msgid "no name was given and auto-detection is disabled"
 msgstr "ní tugadh aon ainm agus tá brath uathoibríoch faoi dhíchum"
 
-#: ident.c
 #, c-format
 msgid "unable to auto-detect name (got '%s')"
 msgstr "ní féidir ainm a bhrath go huathoibríoch (fuair '%s')"
 
-#: ident.c
 #, c-format
 msgid "empty ident name (for <%s>) not allowed"
 msgstr "ainm ident folamh (le haghaidh <%s>) nach gceadaítear"
 
-#: ident.c
 #, c-format
 msgid "name consists only of disallowed characters: %s"
 msgstr "ní chuimsíonn ainm ach carachtair neamh-cheadaithe: %s"
 
-#: list-objects-filter-options.c
+msgid "git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>] < <mbox>"
+msgstr ""
+"git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>] < <mbox>"
+
+msgid "no IMAP host specified"
+msgstr "níor sonraíodh aon óstach IMAP"
+
+msgid ""
+"set the IMAP host with 'git config imap.host <host>'.\n"
+"(e.g., 'git config imap.host imaps://imap.example.com')"
+msgstr ""
+"socraigh an t-óstach IMAP le 'git config imap.host <host>'. \n"
+"(e.g., 'git config imap.host imaps://imap.example.com')"
+
+msgid "no IMAP folder specified"
+msgstr "níor sonraíodh fillteán IMAP"
+
+msgid ""
+"set the target folder with 'git config imap.folder <folder>'.\n"
+"(e.g., 'git config imap.folder Drafts')"
+msgstr ""
+"socraigh an fillteán sprice le 'git config imap.folder <folder>'. \n"
+"(e.g., 'git config imap.folder Dréachtaí')"
+
 msgid "expected 'tree:<depth>'"
 msgstr "<depth>'crann ag súil leis: '"
 
-#: list-objects-filter-options.c
 msgid "sparse:path filters support has been dropped"
 msgstr "neamhchoitianta: tá tacaíocht scagairí cosáin titim"
 
-#: list-objects-filter-options.c
 #, c-format
 msgid "'%s' for 'object:type=<type>' is not a valid object type"
 msgstr "<type>Ní cineál réad bailí é '%s' le haghaidh 'object:type='"
 
-#: list-objects-filter-options.c
 #, c-format
 msgid "invalid filter-spec '%s'"
 msgstr "scagaire neamhbhailí '%s'"
 
-#: list-objects-filter-options.c
 #, c-format
 msgid "must escape char in sub-filter-spec: '%c'"
 msgstr "ní mór don char a éalú i sub-filter-spec: '%c'"
 
-#: list-objects-filter-options.c
 msgid "expected something after combine:"
 msgstr "ag súil le rud éigin tar éis an chomhcheangail:"
 
-#: list-objects-filter-options.c
 msgid "multiple filter-specs cannot be combined"
 msgstr "ní féidir ilshonraíochtaí scagaire a chomhcheangal"
 
-#: list-objects-filter-options.c
 msgid "unable to upgrade repository format to support partial clone"
-msgstr "in ann formáid stórais a uasghrádú chun tacú le clón páirteach"
+msgstr ""
+"ní féidir formáid an stórais a uasghrádú chun tacú le clónáil pháirteach"
 
-#: list-objects-filter-options.h
 msgid "args"
 msgstr "args"
 
-#: list-objects-filter-options.h
 msgid "object filtering"
 msgstr "scagadh réad"
 
-#: list-objects-filter.c
 #, c-format
 msgid "unable to access sparse blob in '%s'"
-msgstr "ní féidir rochtain a fháil ar bhlob neamhchoitianta i '%s'"
+msgstr "ní féidir rochtain a fháil ar an blob tana i '%s'"
 
-#: list-objects-filter.c
 #, c-format
 msgid "unable to parse sparse filter data in %s"
-msgstr "nach féidir sonraí scagaire neamhchoitianta a pháirseáil i %s"
+msgstr "ní féidir sonraí scagaire tanaí a pharsáil i %s"
 
-#: list-objects.c
 #, c-format
 msgid "entry '%s' in tree %s has tree mode, but is not a tree"
 msgstr "tá modh crann ag iontráil '%s' i gcrann %s, ach ní crann í"
 
-#: list-objects.c
 #, c-format
 msgid "entry '%s' in tree %s has blob mode, but is not a blob"
 msgstr "tá modh blob ag iontráil '%s' i gcrann %s, ach ní blob í"
 
-#: list-objects.c
 #, c-format
 msgid "unable to load root tree for commit %s"
-msgstr "nach féidir crann fréimhe a luchtú le haghaidh tiomanta %s"
+msgstr "ní féidir crann fréimhe a luchtú le haghaidh an tiomnaidh %s"
 
-#: lockfile.c
 #, c-format
 msgid ""
 "Unable to create '%s.lock': %s.\n"
@@ -22134,96 +18566,77 @@
 "d'fhéadfadh go mbeadh sé titim sa stór seo níos luaithe:\n"
 "bain an comhad de láimh chun leanúint ar aghaidh."
 
-#: lockfile.c
 #, c-format
 msgid "Unable to create '%s.lock': %s"
 msgstr "Ní féidir '%s.lock' a chruthú: %s"
 
-#: log-tree.c
 msgid "unable to create temporary object directory"
-msgstr "in ann eolaire réad sealadach a chruthú"
+msgstr "ní féidir eolaire réada sealadach a chruthú"
 
-#: loose.c
 #, c-format
 msgid "could not write loose object index %s"
 msgstr "ní fhéadfaí innéacs réad scaoilte %s a scrí"
 
-#: loose.c
 #, c-format
 msgid "failed to write loose object index %s"
 msgstr "theip ar innéacs réad scaoilte %s a scríobh"
 
-#: ls-refs.c
 #, c-format
 msgid "unexpected line: '%s'"
 msgstr "líne gan choinne: '%s'"
 
-#: ls-refs.c
 msgid "expected flush after ls-refs arguments"
 msgstr "súil le sruth tar éis argóintí ls-refs"
 
-#: mailinfo.c
 msgid "quoted CRLF detected"
 msgstr "braithíodh CRLF a luaitear"
 
-#: mem-pool.c strbuf.c wrapper.c
 #, c-format
 msgid "unable to format message: %s"
-msgstr "nach féidir teachtaireacht a fhormáidiú: %s"
+msgstr "ní féidir teachtaireacht a fhormáidiú: %s"
 
-#: merge-ll.c
 #, c-format
 msgid "invalid marker-size '%s', expecting an integer"
 msgstr "méid marcóra neamhbhailí '%s', ag súil le sláimhir"
 
-#: merge-ort-wrappers.c
 #, c-format
 msgid "Could not parse object '%s'"
 msgstr "Ní fhéadfaí réad '%s' a pháirseáil"
 
-#: merge-ort.c
 #, c-format
 msgid "Failed to merge submodule %s (not checked out)"
 msgstr "Theip ar fho-mhodúl %s a chumasc (níor seiceáiltear amach)"
 
-#: merge-ort.c
 #, c-format
 msgid "Failed to merge submodule %s (no merge base)"
 msgstr "Theip ar fho-mhodúl %s a chumasc (gan aon bhonn cumaisc)"
 
-#: merge-ort.c
 #, c-format
 msgid "Failed to merge submodule %s (commits not present)"
 msgstr "Theip ar fho-mhodúl %s a chumasc (níl gealltanas ann)"
 
-#: merge-ort.c
 #, c-format
 msgid "error: failed to merge submodule %s (repository corrupt)"
 msgstr "earráid: theip ar fho-mhodúl %s a chumasc (stór truaillithe)"
 
-#: merge-ort.c
 #, c-format
 msgid "Failed to merge submodule %s (commits don't follow merge-base)"
 msgstr "Theip ar fho-mhodúl %s a chumasc (ní leanann gealltanna cumaisc bonn)"
 
-#: merge-ort.c
 #, c-format
 msgid "Note: Fast-forwarding submodule %s to %s"
 msgstr "Nóta: Fo-mhodúl %s a chur ar aghaidh go tapa chuig %s"
 
-#: merge-ort.c
 #, c-format
 msgid "Failed to merge submodule %s"
 msgstr "Theip ar fho-mhodúl %s a chumasc"
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "Failed to merge submodule %s, but a possible merge resolution exists: %s"
 msgstr ""
 "Theip ar fho-mhodúl %s a chumasc, ach tá réiteach cumaisc féideartha ann: %s"
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "Failed to merge submodule %s, but multiple possible merges exist:\n"
@@ -22232,22 +18645,18 @@
 "Theip ar fho-mhodúl %s a chumasc, ach tá go leor cumaisc féideartha ann:\n"
 "%s"
 
-#: merge-ort.c
 #, c-format
 msgid "error: failed to execute internal merge for %s"
 msgstr "earráid: theip ar chumasc inmheánach a chur i gcrích le haghaidh %s"
 
-#: merge-ort.c
 #, c-format
 msgid "error: unable to add %s to database"
 msgstr "earráid: ní féidir %s a chur leis an mbunachar sonraí"
 
-#: merge-ort.c
 #, c-format
 msgid "Auto-merging %s"
 msgstr "Cumaisc uathoibríoch %s"
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (implicit dir rename): Existing file/dir at %s in the way of "
@@ -22256,7 +18665,6 @@
 "COIMHLINT (athainmniú intuigthe dir): Comhad/dir atá ann cheana ag %s i "
 "mbealach athainmniú eolaire intuigthe ag cur na cosáin seo a leanas ann: %s."
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (implicit dir rename): Cannot map more than one path to %s; "
@@ -22266,7 +18674,6 @@
 "chuig %s; rinne athainmneacha eolaire intuigthe iarracht na cosáin seo a "
 "chur ann: %s"
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (directory rename split): Unclear where to rename %s to; it was "
@@ -22277,7 +18684,6 @@
 "athainmniú; athainmníodh é go eolairí éagsúla eile, gan aon cheann scríbe a "
 "fháil tromlach na gcomhaid."
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "WARNING: Avoiding applying %s -> %s rename to %s, because %s itself was "
@@ -22286,7 +18692,6 @@
 "RABHADH: Seachaint %s a chur i bhfeidhm -> %s a athainmniú go %s, toisc gur "
 "athainmníodh %s féin."
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "Path updated: %s added in %s inside a directory that was renamed in %s; "
@@ -22295,7 +18700,6 @@
 "Conair nuashonraithe: Cuireadh %s isteach i %s taobh istigh de eolaire a "
 "athainmníodh i %s; ag bogadh é go %s."
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "Path updated: %s renamed to %s in %s, inside a directory that was renamed in "
@@ -22304,7 +18708,6 @@
 "Conair nuashonraithe: Athainmníodh %s go %s i %s, taobh istigh de eolaire a "
 "athainmníodh i %s; é ag bogadh go %s."
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (file location): %s added in %s inside a directory that was renamed "
@@ -22314,7 +18717,6 @@
 "a athainmníodh i %s, rud a thugann le tuiscint gur cheart é a aistriú go %s "
 "b'fhéidir."
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (file location): %s renamed to %s in %s, inside a directory that "
@@ -22324,14 +18726,12 @@
 "eolaire a athainmníodh i %s, ag moladh gur cheart é a aistriú go %s "
 "b'fhéidir."
 
-#: merge-ort.c
 #, c-format
 msgid "CONFLICT (rename/rename): %s renamed to %s in %s and to %s in %s."
 msgstr ""
 "COIMHLINT (athainmniú/athainmniú): Athainmníodh %s go %s i %s agus go %s i "
 "%s."
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (rename involved in collision): rename of %s -> %s has content "
@@ -22342,24 +18742,20 @@
 "coinbhleachtaí ábhair ag %s AGUS imbhuaileann sé le cosán eile; d'fhéadfadh "
 "marcóirí coinbhleachta neadaithe a bheith mar thoradh air seo."
 
-#: merge-ort.c
 #, c-format
 msgid "CONFLICT (rename/delete): %s renamed to %s in %s, but deleted in %s."
 msgstr ""
 "COIMHLINT (athainmniú/scrios): Athainmníodh %s go %s i %s, ach scriosadh é i "
 "%s."
 
-#: merge-ort.c
 #, c-format
 msgid "error: cannot read object %s"
 msgstr "earráid: ní féidir réad %s a léamh"
 
-#: merge-ort.c
 #, c-format
 msgid "error: object %s is not a blob"
 msgstr "earráid: ní blob é réad %s"
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (file/directory): directory in the way of %s from %s; moving it to "
@@ -22368,7 +18764,6 @@
 "CONFLICT (comhad/eolaire): eolaire ar bhealach %s ó %s; é a bhogadh go %s "
 "ina ionad."
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (distinct types): %s had different types on each side; renamed both "
@@ -22378,7 +18773,6 @@
 "taobh; athainmníodh an dá cheann ionas gur féidir gach ceann a thaifeadadh "
 "áit éigin."
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (distinct types): %s had different types on each side; renamed one "
@@ -22388,24 +18782,19 @@
 "taobh; athainmníodh ceann acu ionas gur féidir gach ceann a thaifeadadh áit "
 "éigin."
 
-#: merge-ort.c
 msgid "content"
 msgstr "ábhar"
 
-#: merge-ort.c
 msgid "add/add"
 msgstr "cuirte/cuir leis"
 
-#: merge-ort.c
 msgid "submodule"
 msgstr "fo-mhodúl"
 
-#: merge-ort.c
 #, c-format
 msgid "CONFLICT (%s): Merge conflict in %s"
 msgstr "COIMHLINT (%s): Cumaisc coinbhleacht i %s"
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "CONFLICT (modify/delete): %s deleted in %s and modified in %s.  Version %s "
@@ -22420,7 +18809,6 @@
 #. commit that needs to be merged.  For example:
 #.  - go to submodule (mysubmodule), and either merge commit abc1234"
 #.
-#: merge-ort.c
 #, c-format
 msgid ""
 " - go to submodule (%s), and either merge commit %s\n"
@@ -22430,7 +18818,6 @@
 "   nó nuashonraigh chuig tiomantas atá ann cheana féin a bhfuil na "
 "hathruithe sin cumasctha aige.\n"
 
-#: merge-ort.c
 #, c-format
 msgid ""
 "Recursive merging with submodules currently only supports trivial cases.\n"
@@ -22459,336 +18846,267 @@
 #. TRANSLATORS: The %s arguments are: 1) tree hash of a merge
 #. base, and 2-3) the trees for the two trees we're merging.
 #.
-#: merge-ort.c
 #, c-format
 msgid "collecting merge info failed for trees %s, %s, %s"
 msgstr "theip ar fhaisnéis chumaisc a bhailiú do chrainn %s, %s, %s"
 
-#: merge.c
 msgid "failed to read the cache"
 msgstr "theip ar an taisce a léamh"
 
-#: midx-write.c
 #, c-format
 msgid "failed to add packfile '%s'"
 msgstr "theip ar chomhad pacáiste '%s' a chur leis"
 
-#: midx-write.c
 #, c-format
 msgid "failed to open pack-index '%s'"
 msgstr "theip ar innéacs pacáiste '%s' a oscailt"
 
-#: midx-write.c
 #, c-format
 msgid "failed to locate object %d in packfile"
 msgstr "theip ar réad %d a aimsiú i packfile"
 
-#: midx-write.c
 msgid "cannot store reverse index file"
 msgstr "ní féidir comhad innéacs droim a stóráil"
 
-#: midx-write.c
 #, c-format
 msgid "could not parse line: %s"
 msgstr "ní fhéadfaí líne a pháirseáil: %s"
 
-#: midx-write.c
 #, c-format
 msgid "malformed line: %s"
 msgstr "líne mhífhoirmithe: %s"
 
-#: midx-write.c
 msgid "could not load pack"
 msgstr "ní fhéadfaí pacáiste a luchtú"
 
-#: midx-write.c
-#, c-format
-msgid "could not open index for %s"
-msgstr "ní raibh in ann innéacs a oscailt do %s"
-
-#: midx-write.c
 #, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "ní féidir '%s' a nascadh le '%s'"
 
-#: midx-write.c midx.c
 #, c-format
 msgid "failed to clear multi-pack-index at %s"
 msgstr "theip ar innéacs il-phacáiste a ghlanadh ag %s"
 
-#: midx-write.c
 msgid "ignoring existing multi-pack-index; checksum mismatch"
 msgstr ""
 "neamhaird a dhéanamh ar innéacs il-phacáiste atá ann cheana; mímheaitseáil"
 
-#: midx-write.c
 #, c-format
 msgid "could not load reverse index for MIDX %s"
 msgstr "ní fhéadfaí innéacs droim a luchtú do MIDX %s"
 
-#: midx-write.c
 msgid "Adding packfiles to multi-pack-index"
 msgstr "Comhaid pacáiste a chur le hinnéacs il-phacáiste"
 
-#: midx-write.c
 #, c-format
 msgid "unknown preferred pack: '%s'"
 msgstr "pacáiste roghnaithe anaithnid: '%s'"
 
-#: midx-write.c
+#, c-format
+msgid "failed to open preferred pack %s"
+msgstr "theip ar an pacáiste is fearr leat %s a oscailt"
+
 #, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr "ní féidir pacáiste roghnaithe %s a roghnú gan aon rudaí"
 
-#: midx-write.c
 #, c-format
 msgid "did not see pack-file %s to drop"
 msgstr "níor chonaic sé pacáist-chomhad %s le scaoileadh"
 
-#: midx-write.c
 #, c-format
 msgid "preferred pack '%s' is expired"
 msgstr "tá an pacáiste roghnaithe '%s' in éag"
 
-#: midx-write.c
 msgid "no pack files to index."
 msgstr "gan aon phacáiste comhaid le hinnéacs."
 
-#: midx-write.c
 msgid "refusing to write multi-pack .bitmap without any objects"
 msgstr "diúltú a scríobh il-pacáiste.bitmap gan aon rudaí"
 
-#: midx-write.c
 msgid "unable to create temporary MIDX layer"
-msgstr "in ann ciseal MIDX sealadach a chruthú"
+msgstr "ní féidir ciseal MIDX sealadach a chruthú"
 
-#: midx-write.c
 msgid "could not write multi-pack bitmap"
 msgstr "ní fhéadfaí bitmap il-phacáiste a scríobh"
 
-#: midx-write.c
+msgid "too many multi-pack-indexes"
+msgstr "an iomarca innéacsanna ilphacáiste"
+
 msgid "unable to open multi-pack-index chain file"
-msgstr "in ann comhad slabhra in-innéacs il-phacáiste a oscailt"
+msgstr "ní féidir comhad slabhra innéacs ilphacáiste a oscailt"
 
-#: midx-write.c
 msgid "unable to rename new multi-pack-index layer"
-msgstr "in ann ciseal innéacs ilphacáiste nua a athainmniú"
+msgstr "ní féidir an ciseal innéacs ilphacáiste nua a athainmniú"
 
-#: midx-write.c
 msgid "could not write multi-pack-index"
 msgstr "ní fhéadfaí innéacs il-phacáiste a scríobh"
 
-#: midx-write.c
 msgid "cannot expire packs from an incremental multi-pack-index"
 msgstr ""
 "ní féidir le pacáistí a chur in éag ó innéacs ilphacáiste incriminteach"
 
-#: midx-write.c
 msgid "Counting referenced objects"
 msgstr "Rud tagartha a chomhaireamh"
 
-#: midx-write.c
 msgid "Finding and deleting unreferenced packfiles"
 msgstr "Comhaid pacáiste gan tagairt a aimsiú agus a scriosadh"
 
-#: midx-write.c
 msgid "cannot repack an incremental multi-pack-index"
 msgstr "ní féidir le hinnéacs ilphacáiste incriminteach a athphacáil"
 
-#: midx-write.c
 msgid "could not start pack-objects"
 msgstr "ní fhéadfaí pacáiste-rudaí a thosú"
 
-#: midx-write.c
 msgid "could not finish pack-objects"
 msgstr "ní raibh sé in ann pacáistí a chríochnú"
 
-#: midx.c
 msgid "multi-pack-index OID fanout is of the wrong size"
 msgstr "tá fanout OID ilphacáiste den mhéid mícheart"
 
-#: midx.c
 #, c-format
 msgid ""
 "oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr "fanout oid as ord: fanout [%d] =% <PRIx32>>% <PRIx32>= fanout [%d]"
+msgstr "oid fanout as ord: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
 
-#: midx.c
 msgid "multi-pack-index OID lookup chunk is the wrong size"
 msgstr "tá an méid mícheart ar an smután cuardaigh OID innéacs ilphacáiste"
 
-#: midx.c
 msgid "multi-pack-index object offset chunk is the wrong size"
 msgstr ""
 "tá an méid mícheart ar an smután fritháireamh réada innéacs ilphacáiste"
 
-#: midx.c
 #, c-format
 msgid "multi-pack-index file %s is too small"
 msgstr "tá comhad in-innéacs ilphacáiste %s ró-bheag"
 
-#: midx.c
 #, c-format
 msgid "multi-pack-index signature 0x%08x does not match signature 0x%08x"
 msgstr "ní mheaitseálann síniú innéacs il-phacáiste 0x%08x síniú 0x%08x"
 
-#: midx.c
 #, c-format
 msgid "multi-pack-index version %d not recognized"
 msgstr "ní aithnítear leagan innéacs il-phacáiste %d"
 
-#: midx.c
 #, c-format
 msgid "multi-pack-index hash version %u does not match version %u"
 msgstr "ní hionann leagan %u den hais innéacs ilphacáiste agus leagan %u"
 
-#: midx.c
 msgid "multi-pack-index required pack-name chunk missing or corrupted"
 msgstr ""
 "innéacs il-phacáiste teastaíonn píosa ainm pacáiste ar iarraidh nó "
 "truaillithe"
 
-#: midx.c
 msgid "multi-pack-index required OID fanout chunk missing or corrupted"
 msgstr ""
 "teastaíonn innéacs il-phacáiste le píosa fanout OID atá ar iarraidh nó "
 "truaillithe"
 
-#: midx.c
 msgid "multi-pack-index required OID lookup chunk missing or corrupted"
 msgstr ""
 "teastaíonn innéacs ilphacáiste cuardaigh OID atá ar iarraidh nó truaillithe"
 
-#: midx.c
 msgid "multi-pack-index required object offsets chunk missing or corrupted"
 msgstr ""
 "smután fritháireamh réada riachtanach innéacs ilphacáiste ar iarraidh nó "
 "truaillithe"
 
-#: midx.c
 msgid "multi-pack-index pack-name chunk is too short"
 msgstr "tá píosa ainm pacáiste innéacs il-phacáiste ró-ghearr"
 
-#: midx.c
 #, c-format
 msgid "multi-pack-index pack names out of order: '%s' before '%s'"
 msgstr "ainmneacha pacáiste in-innéacs il-phacáiste as ord: '%s' roimh '%s'"
 
-#: midx.c
 msgid "multi-pack-index chain file too small"
 msgstr "comhad slabhra in-innéacs il-phacáiste ró-bheag"
 
-#: midx.c
 #, c-format
 msgid "pack count in base MIDX too high: %<PRIuMAX>"
 msgstr "líon pacáiste i mbonn MIDX ró-ard:%<PRIuMAX>"
 
-#: midx.c
 #, c-format
 msgid "object count in base MIDX too high: %<PRIuMAX>"
 msgstr "líon rudaí i mbonn MIDX ró-ard:%<PRIuMAX>"
 
-#: midx.c
 #, c-format
 msgid "invalid multi-pack-index chain: line '%s' not a hash"
-msgstr "slabhra innéacs il-phacáiste neamhbhailí: ní hash é líne '%s'"
+msgstr "slabhra innéacs il-phacáiste neamhbhailí: ní hais é líne '%s'"
 
-#: midx.c
 msgid "unable to find all multi-pack index files"
-msgstr "in ann gach comhad innéacs il-phacáiste a fháil"
+msgstr "ní féidir gach comhad innéacs ilphacáiste a aimsiú"
 
-#: midx.c
 msgid "invalid MIDX object position, MIDX is likely corrupt"
 msgstr "suíomh réad MIDX neamhbhailí, is dócha go bhfuil MIDX truaillithe"
 
-#: midx.c
 #, c-format
 msgid "bad pack-int-id: %u (%u total packs)"
 msgstr "bad pack-int-id: %u (pacáistí iomlána %u)"
 
-#: midx.c
 msgid "MIDX does not contain the BTMP chunk"
 msgstr "Níl an píosa BTMP i MIDX"
 
-#: midx.c
 #, c-format
 msgid "could not load bitmapped pack %<PRIu32>"
-msgstr "ní fhéadfaí pacáiste bitmapped a luchtú% <PRIu32>"
+msgstr "ní fhéadfaí pacáiste bitmapped a luchtú %<PRIu32>"
 
-#: midx.c
 msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
 msgstr ""
 "stórálann innéacs il-phacáiste fritháireamh 64-giotán, ach tá off_t ró-bheag"
 
-#: midx.c
 msgid "multi-pack-index large offset out of bounds"
 msgstr "innéacs il-phacáiste fhritháireamh mór as teorainneacha"
 
-#: midx.c
 msgid "multi-pack-index file exists, but failed to parse"
 msgstr "tá comhad in-innéacs il-phacáiste ann, ach theip air a pháirseáil"
 
-#: midx.c
 msgid "incorrect checksum"
 msgstr "seiceáil mícheart"
 
-#: midx.c
 msgid "Looking for referenced packfiles"
 msgstr "Ag lorg comhaid pacáiste tagartha"
 
-#: midx.c
 msgid "the midx contains no oid"
 msgstr "níl aon oid sa midx"
 
-#: midx.c
 msgid "Verifying OID order in multi-pack-index"
 msgstr "Ordú OID a fhíorú in innéacs il-phacáiste"
 
-#: midx.c
 #, c-format
 msgid "oid lookup out of order: oid[%d] = %s >= %s = oid[%d]"
 msgstr "cuardach oid as ord: oid [%d] = %s >= %s = oid [%d]"
 
-#: midx.c
 msgid "Sorting objects by packfile"
 msgstr "Rudaí a shórtáil de réir pacáiste"
 
-#: midx.c
 msgid "Verifying object offsets"
 msgstr "Athshraith réada a fhíorú"
 
-#: midx.c
 #, c-format
 msgid "failed to load pack entry for oid[%d] = %s"
 msgstr "theip ar iontráil pacáiste a luchtú do oid [%d] = %s"
 
-#: midx.c
 #, c-format
 msgid "failed to load pack-index for packfile %s"
 msgstr "theip ar innéacs pacáiste a luchtú do phacáiste %s"
 
-#: midx.c
 #, c-format
 msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
 msgstr ""
 "fritháireamh réada mícheart le haghaidh oid[%d] = %s: %<PRIx64> != %<PRIx64>"
 
-#: name-hash.c
 #, c-format
 msgid "unable to create lazy_dir thread: %s"
-msgstr "nach féidir snáithe lazy_dir a chruthú: %s"
+msgstr "ní féidir snáithe lazy_dir a chruthú: %s"
 
-#: name-hash.c
 #, c-format
 msgid "unable to create lazy_name thread: %s"
-msgstr "nach féidir snáithe lazy_name a chruthú: %s"
+msgstr "ní féidir snáithe lazy_name a chruthú: %s"
 
-#: name-hash.c
 #, c-format
 msgid "unable to join lazy_name thread: %s"
 msgstr "ní féidir teacht le snáithe lazy_name: %s"
 
-#: notes-merge.c
 #, c-format
 msgid ""
 "You have not concluded your previous notes merge (%s exists).\n"
@@ -22800,21 +19118,17 @@
 "abort' chun an cumasc roimhe seo a cheangail/deireadh a chur leis sula "
 "dtosaíonn tú le cumasc nótaí nua."
 
-#: notes-merge.c
 #, c-format
 msgid "You have not concluded your notes merge (%s exists)."
 msgstr "Níor chríochnaigh tú do chuid nótaí a chumasc (%s ann)."
 
-#: notes-utils.c
 msgid "Cannot commit uninitialized/unreferenced notes tree"
 msgstr "Ní féidir crann nótaí neamhthionsaithe/gan tagairt a dhéanamh"
 
-#: notes-utils.c
 #, c-format
 msgid "Bad notes.rewriteMode value: '%s'"
 msgstr "Luach lochtach notes.rewriteMode: '%s'"
 
-#: notes-utils.c
 #, c-format
 msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
 msgstr "Diúltú nótaí a athscríobh i %s (lasmuigh de refs/notes/)"
@@ -22823,230 +19137,183 @@
 #. the environment variable, the second %s is
 #. its value.
 #.
-#: notes-utils.c
 #, c-format
 msgid "Bad %s value: '%s'"
 msgstr "Droch-luach %s: '%s'"
 
-#: object-file-convert.c
 msgid "failed to decode tree entry"
 msgstr "theip ar iontráil crann a dhíchódú"
 
-#: object-file-convert.c
 #, c-format
 msgid "failed to map tree entry for %s"
 msgstr "theip ar iontráil crann a mhapáil do %s"
 
-#: object-file-convert.c
 #, c-format
 msgid "bad %s in commit"
 msgstr "droch %s i dtiomantas"
 
-#: object-file-convert.c
 #, c-format
 msgid "unable to map %s %s in commit object"
-msgstr "nach féidir %s %s a mhapáil i réad tiomanta"
+msgstr "ní féidir %s %s a mhapáil sa réad commit"
 
-#: object-file-convert.c
 #, c-format
 msgid "Failed to convert object from %s to %s"
 msgstr "Theip ar réad a thiontú ó %s go %s"
 
-#: object-file.c
 #, c-format
 msgid "object file %s is empty"
 msgstr "tá comhad réad %s folamh"
 
-#: object-file.c
 #, c-format
 msgid "corrupt loose object '%s'"
 msgstr "réad scaoilte truaillithe '%s'"
 
-#: object-file.c
 #, c-format
 msgid "garbage at end of loose object '%s'"
 msgstr "truflais ag deireadh réad scaoilte '%s'"
 
-#: object-file.c
 #, c-format
 msgid "unable to open loose object %s"
-msgstr "nach féidir réad scaoilte %s a oscailt"
+msgstr "ní féidir réad scaoilte %s a oscailt"
 
-#: object-file.c
 #, c-format
 msgid "unable to parse %s header"
-msgstr "nach féidir ceannteideal %s a pháirseáil"
+msgstr "ní féidir ceanntásc %s a pharsáil"
 
-#: object-file.c
 msgid "invalid object type"
 msgstr "cineál réad neamhbhailí"
 
-#: object-file.c
 #, c-format
 msgid "unable to unpack %s header"
 msgstr "ní féidir ceannteideal %s a dhíphacáil"
 
-#: object-file.c
 #, c-format
 msgid "header for %s too long, exceeds %d bytes"
-msgstr "ceannteideal do %s rófhada, níos mó ná %d bytes"
+msgstr "ceannteideal do %s rófhada, níos mó ná %d bearta"
 
-#: object-file.c
 #, c-format
 msgid "loose object %s (stored in %s) is corrupt"
 msgstr "tá réad scaoilte %s (stóráilte i %s) truaillithe"
 
-#: object-file.c
 #, c-format
 msgid "unable to open %s"
 msgstr "ní féidir %s a oscailt"
 
-#: object-file.c
 #, c-format
 msgid "files '%s' and '%s' differ in contents"
 msgstr "tá difríocht idir comhaid '%s' agus '%s' in ábhar"
 
-#: object-file.c
-#, c-format
-msgid "unable to write file %s"
-msgstr "nach féidir comhad %s a scríobh"
-
-#: object-file.c
 #, c-format
 msgid "unable to write repeatedly vanishing file %s"
-msgstr "in ann comhad %s atá ag imeacht arís agus arís eile a scríobh"
+msgstr "ní féidir comhad %s atá ag imeacht arís agus arís eile a scríobh"
 
-#: object-file.c
 #, c-format
 msgid "unable to set permission to '%s'"
-msgstr "nach féidir cead a shocrú do '%s'"
+msgstr "ní féidir cead a shocrú go '%s'"
 
-#: object-file.c
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = ní thacaítear leis an bhaisc ar an ardán seo"
+
 msgid "error when closing loose object file"
 msgstr "earráid agus comhad réad scaoilte á ndú"
 
-#: object-file.c
 #, c-format
 msgid "insufficient permission for adding an object to repository database %s"
 msgstr "cead neamhleor chun réad a chur le bunachar sonraí stórais %s"
 
-#: object-file.c
 msgid "unable to create temporary file"
-msgstr "in ann comhad sealadach a chruthú"
+msgstr "ní féidir comhad sealadach a chruthú"
 
-#: object-file.c
 msgid "unable to write loose object file"
-msgstr "in ann comhad réad scaoilte a scríobh"
+msgstr "ní féidir comhad réada scaoilte a scríobh"
 
-#: object-file.c
 #, c-format
 msgid "unable to deflate new object %s (%d)"
-msgstr "nach féidir réad nua %s a dhíoslagadh (%d)"
+msgstr "ní féidir an réad nua %s (%d) a dhíbhoilsciú."
 
-#: object-file.c
 #, c-format
 msgid "deflateEnd on object %s failed (%d)"
 msgstr "theip ar deflateEnd ar réad %s (%d)"
 
-#: object-file.c
 #, c-format
 msgid "confused by unstable object source data for %s"
 msgstr "mearbhall de bharr sonraí foinse réada éagobhsaí do %s"
 
-#: object-file.c
 #, c-format
 msgid "write stream object %ld != %<PRIuMAX>"
 msgstr "scríobh réad srutha %ld! =%<PRIuMAX>"
 
-#: object-file.c
 #, c-format
 msgid "unable to stream deflate new object (%d)"
-msgstr "nach féidir réad nua a dhíscaoileadh a shruthlú (%d)"
+msgstr "ní féidir sruthú díbhoilsciú réad nua (%d)"
 
-#: object-file.c
 #, c-format
 msgid "deflateEnd on stream object failed (%d)"
 msgstr "theip ar réad srutha DeflateEnd (%d)"
 
-#: object-file.c
 #, c-format
 msgid "unable to create directory %s"
-msgstr "nach féidir eolaire %s a chruthú"
+msgstr "ní féidir eolaire %s a chruthú"
 
-#: object-file.c
 #, c-format
 msgid "cannot read object for %s"
 msgstr "ní féidir réad a léamh do %s"
 
-#: object-file.c
 #, c-format
 msgid "cannot map object %s to %s"
 msgstr "ní féidir réad %s a mhapáil go %s"
 
-#: object-file.c
 #, c-format
 msgid "object fails fsck: %s"
 msgstr "teipeann ar réad fsck: %s"
 
-#: object-file.c
 msgid "refusing to create malformed object"
 msgstr "diúltú réad mífhoirmithe a chruthú"
 
-#: object-file.c
 #, c-format
 msgid "read error while indexing %s"
 msgstr "earráid léite agus %s á innéacsú"
 
-#: object-file.c
 #, c-format
 msgid "short read while indexing %s"
 msgstr "léamh gearr agus %s á innéacsú"
 
-#: object-file.c
 #, c-format
 msgid "%s: failed to insert into database"
 msgstr "%s: theip ort a chur isteach sa bhunachar sonraí"
 
-#: object-file.c
 #, c-format
 msgid "%s: unsupported file type"
 msgstr "%s: cineál comhaid gan tacaíocht"
 
-#: object-file.c
 #, c-format
 msgid "hash mismatch for %s (expected %s)"
 msgstr "neamhoiriúnú hash do %s (súil leis %s)"
 
-#: object-file.c
 #, c-format
 msgid "unable to mmap %s"
-msgstr "nach féidir %s a mmapáil"
+msgstr "ní féidir %s a mhapáil"
 
-#: object-file.c
 #, c-format
 msgid "unable to unpack header of %s"
-msgstr "nach féidir ceanntásc %s a dhíphacáil"
+msgstr "ní féidir ceanntásc %s a dhíphacáil"
 
-#: object-file.c
 #, c-format
 msgid "unable to parse header of %s"
-msgstr "nach féidir ceannteideal %s a pháirseáil"
+msgstr "ní féidir ceanntásc %s a pharsáil"
 
-#: object-file.c
 #, c-format
 msgid "unable to parse type from header '%s' of %s"
 msgstr "ní féidir cineál a pharsáil ó cheanntásc '%s' de %s"
 
-#: object-file.c
 #, c-format
 msgid "unable to unpack contents of %s"
-msgstr "nach féidir ábhar %s a dhíphacáil"
+msgstr "ní féidir ábhar %s a dhíphacáil"
 
 #. 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]".
 #.
-#: object-name.c
 #, c-format
 msgid "%s [bad object]"
 msgstr "%s [droch-réad]"
@@ -23056,7 +19323,6 @@
 #. *
 #.    "deadbeef commit 2021-01-01 - Some Commit Message"
 #.
-#: object-name.c
 #, c-format
 msgid "%s commit %s - %s"
 msgstr "Déanann %s tiomanta %s - %s"
@@ -23072,7 +19338,6 @@
 #. The third argument is the "tag" string
 #. from object.c.
 #.
-#: object-name.c
 #, c-format
 msgid "%s tag %s - %s"
 msgstr "Clib %s %s - %s"
@@ -23083,7 +19348,6 @@
 #. *
 #.    "deadbeef [bad tag, could not parse it]"
 #.
-#: object-name.c
 #, c-format
 msgid "%s [bad tag, could not parse it]"
 msgstr "%s [droch-chlib, ní fhéadfaí é a pháirseáil]"
@@ -23091,7 +19355,6 @@
 #. TRANSLATORS: This is a line of ambiguous <type>
 #. object output. E.g. "deadbeef tree".
 #.
-#: object-name.c
 #, c-format
 msgid "%s tree"
 msgstr "%s crann"
@@ -23099,12 +19362,10 @@
 #. TRANSLATORS: This is a line of ambiguous <type>
 #. object output. E.g. "deadbeef blob".
 #.
-#: object-name.c
 #, c-format
 msgid "%s blob"
 msgstr "%s blob"
 
-#: object-name.c
 #, c-format
 msgid "short object ID %s is ambiguous"
 msgstr "tá ID réad gairid %s débhríoch"
@@ -23113,7 +19374,6 @@
 #. objects composed in show_ambiguous_object(). See
 #. its "TRANSLATORS" comments for details.
 #.
-#: object-name.c
 #, c-format
 msgid ""
 "The candidates are:\n"
@@ -23122,7 +19382,6 @@
 "Is iad na hiarrthóirí:\n"
 "%s"
 
-#: object-name.c
 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"
@@ -23147,22 +19406,18 @@
 "teachtaireacht seo as\n"
 "ag rith \"git config set advice.objectNameWarning false\""
 
-#: object-name.c
 #, c-format
 msgid "log for '%.*s' only goes back to %s"
 msgstr "ní théann logáil le haghaidh '%.*s' ach ar ais go %s"
 
-#: object-name.c
 #, c-format
 msgid "log for '%.*s' only has %d entries"
 msgstr "níl ach iontráil i logáil le haghaidh '%.*s' ach %d ceann"
 
-#: object-name.c
 #, c-format
 msgid "path '%s' exists on disk, but not in '%.*s'"
 msgstr "tá cosán '%s' ann ar an diosca, ach ní i '%.*s'"
 
-#: object-name.c
 #, c-format
 msgid ""
 "path '%s' exists, but not '%s'\n"
@@ -23171,12 +19426,10 @@
 "tá an cosán '%s' ann, ach níl '%s' ann\n"
 "leid: An raibh tú i gceist agat '%.*s:%s' aka '%.*s:./%s'?"
 
-#: object-name.c
 #, c-format
 msgid "path '%s' does not exist in '%.*s'"
 msgstr "níl cosán '%s' ann i '%.*s'"
 
-#: object-name.c
 #, c-format
 msgid ""
 "path '%s' is in the index, but not at stage %d\n"
@@ -23185,7 +19438,6 @@
 "tá cosán '%s' san innéacs, ach ní ag céim %d\n"
 "leid: An raibh i gceist agat ': %d: %s'?"
 
-#: object-name.c
 #, c-format
 msgid ""
 "path '%s' is in the index, but not '%s'\n"
@@ -23194,517 +19446,432 @@
 "tá an conair '%s' san innéacs, ach ní '%s'\n"
 "leideanna: an é ':%d:%s' a bhí i gceist agat, nó ':%d:./%s'?"
 
-#: object-name.c
 #, c-format
 msgid "path '%s' exists on disk, but not in the index"
 msgstr "tá cosán '%s' ann ar an diosca, ach ní san innéacs"
 
-#: object-name.c
 #, c-format
 msgid "path '%s' does not exist (neither on disk nor in the index)"
 msgstr "níl cosán '%s' ann (ní ar an diosca ná san innéacs)"
 
-#: object-name.c
 msgid "relative path syntax can't be used outside working tree"
 msgstr ""
 "ní féidir comhréir cosáin choibhneasta a úsáid lasmuigh de chrann oibre"
 
-#: object-name.c
 #, c-format
 msgid "<object>:<path> required, only <object> '%s' given"
 msgstr "<object>: ri <path>achtanach, ní <object>thugtar ach '%s'"
 
-#: object-name.c
 #, c-format
 msgid "invalid object name '%.*s'."
 msgstr "ainm réada neamhbhailí '%.*s'."
 
-#: object-store.c
-#, c-format
-msgid "object directory %s does not exist; check .git/objects/info/alternates"
-msgstr "níl an eolaire réada %s ann; seiceáil .git/objects/info/alternates"
-
-#: object-store.c
-#, c-format
-msgid "unable to normalize alternate object path: %s"
-msgstr "nach féidir cosán réad malartach a normalú: %s"
-
-#: object-store.c
-#, c-format
-msgid "%s: ignoring alternate object stores, nesting too deep"
-msgstr "%s: neamhaird a dhéanamh ar stórais rudaí malartacha, neadú ró-"
-
-#: object-store.c
-msgid "unable to fdopen alternates lockfile"
-msgstr "in ann comhad glasála malartacha a fdopen"
-
-#: object-store.c
-msgid "unable to read alternates file"
-msgstr "in ann comhad malartach a léamh"
-
-#: object-store.c
-msgid "unable to move new alternates file into place"
-msgstr "in ann comhad malartacha nua a bhogadh isteach"
-
-#: object-store.c
-#, c-format
-msgid "path '%s' does not exist"
-msgstr "níl cosán '%s' ann"
-
-#: object-store.c
-#, c-format
-msgid "reference repository '%s' as a linked checkout is not supported yet."
-msgstr "ní thacaítear le stór tagartha '%s' mar sheiceáil nasctha go fóill."
-
-#: object-store.c
-#, c-format
-msgid "reference repository '%s' is not a local repository."
-msgstr "ní stór áitiúil é stór tagartha '%s'."
-
-#: object-store.c
-#, c-format
-msgid "reference repository '%s' is shallow"
-msgstr "tá stóras tagartha '%s' éadomhain"
-
-#: object-store.c
-#, c-format
-msgid "reference repository '%s' is grafted"
-msgstr "tá stór tagartha '%s' grapháilte"
-
-#: object-store.c
-#, c-format
-msgid "could not find object directory matching %s"
-msgstr "ní fhéadfaí eolaire réada a fháil a mheaitseáil %s"
-
-#: object-store.c
-#, c-format
-msgid "invalid line while parsing alternate refs: %s"
-msgstr "líne neamhbhailí agus tú ag paráil iarmhairtí malartacha: %s"
-
-#: object-store.c
-#, c-format
-msgid "replacement %s not found for %s"
-msgstr "nach bhfuarthas %s a athsholáthar do %s"
-
-#: object-store.c
-#, c-format
-msgid "packed object %s (stored in %s) is corrupt"
-msgstr "tá réad pacáilte %s (stóráilte i %s) truaillithe"
-
-#: object-store.c
-#, c-format
-msgid "missing mapping of %s to %s"
-msgstr "mapáil atá in easnamh de %s go %s"
-
-#: object-store.c
-#, c-format
-msgid "%s is not a valid '%s' object"
-msgstr "Ní réad bailí '%s' é %s '"
-
-#: object.c
 #, c-format
 msgid "invalid object type \"%s\""
 msgstr "cineál réad neamhbhailí “%s”"
 
-#: object.c
 #, c-format
 msgid "object %s is a %s, not a %s"
 msgstr "is %s é réad %s, ní %s"
 
-#: object.c
 #, c-format
 msgid "object %s has unknown type id %d"
 msgstr "réad %s tá cineál ID anaithnid %d aige"
 
-#: object.c
 #, c-format
 msgid "unable to parse object: %s"
-msgstr "nach féidir réad a pháirseáil: %s"
+msgstr "ní féidir an réad a pharsáil: %s"
 
-#: object.c
 #, c-format
 msgid "hash mismatch %s"
 msgstr "neamhoiriúnú hash %s"
 
-#: pack-bitmap-write.c
+#, c-format
+msgid "object directory %s does not exist; check .git/objects/info/alternates"
+msgstr "níl an eolaire réada %s ann; seiceáil .git/objects/info/alternates"
+
+#, c-format
+msgid "unable to normalize alternate object path: %s"
+msgstr "ní féidir cosán réada malartach a normalú: %s"
+
+#, c-format
+msgid "%s: ignoring alternate object stores, nesting too deep"
+msgstr "%s: neamhaird a dhéanamh ar stórais rudaí malartacha, neadú ró-"
+
+msgid "unable to fdopen alternates lockfile"
+msgstr "ní féidir comhad glasála malartacha fdopen a úsáid"
+
+msgid "unable to read alternates file"
+msgstr "ní féidir comhad malartach a léamh"
+
+msgid "unable to move new alternates file into place"
+msgstr "ní féidir comhad malartach nua a bhogadh ina áit"
+
+#, c-format
+msgid "path '%s' does not exist"
+msgstr "níl cosán '%s' ann"
+
+#, c-format
+msgid "reference repository '%s' as a linked checkout is not supported yet."
+msgstr "ní thacaítear le stór tagartha '%s' mar sheiceáil nasctha go fóill."
+
+#, c-format
+msgid "reference repository '%s' is not a local repository."
+msgstr "ní stór áitiúil é stór tagartha '%s'."
+
+#, c-format
+msgid "reference repository '%s' is shallow"
+msgstr "tá stóras tagartha '%s' éadomhain"
+
+#, c-format
+msgid "reference repository '%s' is grafted"
+msgstr "tá stór tagartha '%s' grapháilte"
+
+#, c-format
+msgid "could not find object directory matching %s"
+msgstr "ní fhéadfaí eolaire réada a fháil a mheaitseáil %s"
+
+#, c-format
+msgid "invalid line while parsing alternate refs: %s"
+msgstr "líne neamhbhailí agus tú ag paráil iarmhairtí malartacha: %s"
+
+#, c-format
+msgid "replacement %s not found for %s"
+msgstr "nach bhfuarthas %s a athsholáthar do %s"
+
+#, c-format
+msgid "packed object %s (stored in %s) is corrupt"
+msgstr "tá réad pacáilte %s (stóráilte i %s) truaillithe"
+
+#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "mapáil atá in easnamh de %s go %s"
+
+#, c-format
+msgid "%s is not a valid '%s' object"
+msgstr "Ní réad bailí '%s' é %s '"
+
 #, c-format
 msgid "duplicate entry when writing bitmap index: %s"
 msgstr "iontráil dúblach agus innéacs bitmap á scríobh: %s"
 
-#: pack-bitmap-write.c
 #, c-format
 msgid "attempted to store non-selected commit: '%s'"
 msgstr "rinne iarracht tiomantas neamh-roghnaithe a stóráil: '%s'"
 
-#: pack-bitmap-write.c
 msgid "too many pseudo-merges"
 msgstr "an iomarca bréag-chumaisc"
 
-#: pack-bitmap-write.c
-msgid "trying to write commit not in index"
-msgstr "ag iarraidh tiomantas a scríobh ní in innéacs"
-
-#: pack-bitmap.c
 msgid "failed to load bitmap index (corrupted?)"
 msgstr "theip ar innéacs bitmap a luchtú (truaillithe?)"
 
-#: pack-bitmap.c
 msgid "corrupted bitmap index (too small)"
 msgstr "innéacs bitmap truaillithe (ró-bheag)"
 
-#: pack-bitmap.c
 msgid "corrupted bitmap index file (wrong header)"
 msgstr "comhad innéacs bitmap truaillithe (ceanntásc mícheart)"
 
-#: pack-bitmap.c
 #, c-format
 msgid "unsupported version '%d' for bitmap index file"
 msgstr "leagan gan tacaíocht '%d' do chomhad innéacs bitmap"
 
-#: pack-bitmap.c
 msgid "corrupted bitmap index file (too short to fit hash cache)"
 msgstr ""
 "comhad innéacs bitmap truaillithe (róghearr chun taisce hash a fheistiú)"
 
-#: pack-bitmap.c
 msgid "corrupted bitmap index file (too short to fit lookup table)"
 msgstr ""
 "comhad innéacs bitmap truaillithe (róghearr chun tábla cuardaigh a fheistiú)"
 
-#: pack-bitmap.c
 msgid ""
 "corrupted bitmap index file (too short to fit pseudo-merge table header)"
 msgstr ""
 "comhad innéacs bitmap truaillithe (ró-ghearr chun ceannteideal tábla bréag-"
 "chumasc a fheistiú)"
 
-#: pack-bitmap.c
 msgid "corrupted bitmap index file (too short to fit pseudo-merge table)"
 msgstr ""
 "comhad innéacs bitmap truaillithe (ró-ghearr chun tábla bréag-chumasc a "
 "fheistiú)"
 
-#: pack-bitmap.c
 msgid "corrupted bitmap index file, pseudo-merge table too short"
 msgstr "comhad innéacs bitmap truaillithe, tábla bréag-chumasc ró-ghearr"
 
-#: pack-bitmap.c
 #, c-format
 msgid "duplicate entry in bitmap index: '%s'"
 msgstr "iontráil dúblach in innéacs bitmap: '%s'"
 
-#: pack-bitmap.c
 #, c-format
 msgid "corrupt ewah bitmap: truncated header for entry %d"
 msgstr "bitmap ewah truaillithe: ceannteideal gearrtha le haghaidh iontráil %d"
 
-#: pack-bitmap.c
 #, c-format
 msgid "corrupt ewah bitmap: commit index %u out of range"
 msgstr "bitmap ewah truaillithe: innéacs tiomanta %u lasmuigh den raon"
 
-#: pack-bitmap.c
 msgid "corrupted bitmap pack index"
 msgstr "innéacs pacáiste bitmap truaillte"
 
-#: pack-bitmap.c
 msgid "invalid XOR offset in bitmap pack index"
 msgstr "fritháireamh XOR neamhbhailí in innéacs pacáiste bitmap"
 
-#: pack-bitmap.c
 msgid "cannot fstat bitmap file"
 msgstr "ní féidir comhad bitmap fstat"
 
-#: pack-bitmap.c
 msgid "checksum doesn't match in MIDX and bitmap"
 msgstr "ní mheaitseálann seicsum i MIDX agus bitmap"
 
-#: pack-bitmap.c
 msgid "multi-pack bitmap is missing required reverse index"
 msgstr "tá an t-innéacs droim riachtanach in easnamh ilphacáiste"
 
-#: pack-bitmap.c
 #, c-format
 msgid "could not open pack %s"
 msgstr "ní fhéadfaí pacáiste %s a oscailt"
 
-#: pack-bitmap.c
 msgid "corrupt bitmap lookup table: triplet position out of index"
 msgstr "tábla cuardaigh bitmap truaillithe: suíomh triplet as innéacs"
 
-#: pack-bitmap.c
 msgid "corrupt bitmap lookup table: xor chain exceeds entry count"
 msgstr "tábla cuardaigh bitmap truaillithe: sáraíonn slabhra xor líon iontrála"
 
-#: pack-bitmap.c
 #, c-format
 msgid "corrupt bitmap lookup table: commit index %u out of range"
 msgstr ""
 "tábla cuardaigh bitmap truaillithe: innéacs tiomanta %u lasmuigh den raon"
 
-#: pack-bitmap.c
 #, c-format
 msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
 msgstr ""
 "bitmap ewah truaillithe: ceannteideal gearrtha le haghaidh bitmap de "
 "thiomantas “%s”"
 
-#: pack-bitmap.c
 #, c-format
 msgid "unable to load pack: '%s', disabling pack-reuse"
-msgstr "in ann pacáiste a luchtú: '%s', athúsáid pacáiste a dhíchumasú"
+msgstr ""
+"ní féidir an pacáiste a luchtú: '%s', ag díchumasú athúsáid an phacáiste"
 
-#: pack-bitmap.c
 msgid "unable to compute preferred pack, disabling pack-reuse"
-msgstr "in ann pacáiste roghnaithe a ríomh, athúsáid pacáiste a dhíchumasú"
+msgstr ""
+"ní féidir an pacáiste is fearr leat a ríomh, athúsáid pacáiste a dhíchumasú"
 
-#: pack-bitmap.c
 #, c-format
 msgid "object '%s' not found in type bitmaps"
 msgstr "níor aimsíodh réad '%s' i gcineál bitmaps"
 
-#: pack-bitmap.c
 #, c-format
 msgid "object '%s' does not have a unique type"
 msgstr "níl cineál uathúil ag réad '%s'"
 
-#: pack-bitmap.c
 #, c-format
 msgid "object '%s': real type '%s', expected: '%s'"
 msgstr "réad '%s': fíor-chineál '%s', ag súil leis: '%s'"
 
-#: pack-bitmap.c
 #, c-format
 msgid "object not in bitmap: '%s'"
 msgstr "réad nach bhfuil i mbitmap: '%s'"
 
-#: pack-bitmap.c
 msgid "failed to load bitmap indexes"
 msgstr "theip ar innéacsanna bitmap a luchtú"
 
-#: pack-bitmap.c
 msgid "you must specify exactly one commit to test"
 msgstr "ní mór duit tiomantas amháin a shonrú go díreach chun tástáil"
 
-#: pack-bitmap.c
 #, c-format
 msgid "commit '%s' doesn't have an indexed bitmap"
 msgstr "cumann nach bhfuil bitmap innéacsaithe ag '%s'"
 
-#: pack-bitmap.c
 msgid "mismatch in bitmap results"
 msgstr "mímheaitseáil i dtorthaí bitmap"
 
-#: pack-bitmap.c
 #, c-format
 msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)"
 msgstr "innéacs bréag-chumaisc lasmuigh den raon (%<PRIu32> >= %<PRIuMAX>)"
 
-#: pack-bitmap.c
 #, c-format
 msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>"
 msgstr ""
 "ní raibh '%s' in ann teacht i bpacáiste '%s' ag fhritháireamh%<PRIuMAX>"
 
-#: pack-bitmap.c
 #, c-format
 msgid "unable to get disk usage of '%s'"
 msgstr "ní féidir úsáid diosca a fháil de '%s'"
 
-#: pack-bitmap.c
 #, c-format
 msgid "bitmap file '%s' has invalid checksum"
 msgstr "tá seicsum neamhbhailí ag comhad bitmap '%s'"
 
-#: pack-mtimes.c
 #, c-format
 msgid "mtimes file %s is too small"
 msgstr "tá comhad mtimes %s ró-bheag"
 
-#: pack-mtimes.c
 #, c-format
 msgid "mtimes file %s has unknown signature"
 msgstr "tá síniú anaithnid ag comhad mtimes %s"
 
-#: pack-mtimes.c
 #, c-format
 msgid "mtimes file %s has unsupported version %<PRIu32>"
-msgstr "tá leagan neamh-tacaithe ag comhad mtimes %s% <PRIu32>"
+msgstr "tá comhad mtimes %s le leagan %<PRIu32> nach dtacaítear leis"
 
-#: pack-mtimes.c
 #, c-format
 msgid "mtimes file %s has unsupported hash id %<PRIu32>"
-msgstr "tá id hash neamh-tacaithe ag comhad %s mtimes% <PRIu32>"
+msgstr ""
+"tá comhad mtimes %s le hais-aitheantas hash %<PRIu32> nach dtacaítear leis"
 
-#: pack-mtimes.c
 #, c-format
 msgid "mtimes file %s is corrupt"
 msgstr "tá comhad mtimes %s truaillithe"
 
-#: pack-revindex.c
+msgid "pack everything"
+msgstr "pacáil gach rud"
+
+msgid "prune loose refs (default)"
+msgstr "briseadh scaoilte (réamhshocraithe)"
+
+msgid "auto-pack refs as needed"
+msgstr "tuairiscintí uathoibríoch pacáiste"
+
+msgid "references to include"
+msgstr "tagairtí lena n-áirítear"
+
+msgid "references to exclude"
+msgstr "tagairtí chun eisiamh"
+
 #, c-format
 msgid "reverse-index file %s is too small"
 msgstr "tá comhad innéacs droim %s róbheag"
 
-#: pack-revindex.c
 #, c-format
 msgid "reverse-index file %s is corrupt"
 msgstr "tá comhad innéacs droim %s truaillithe"
 
-#: pack-revindex.c
 #, c-format
 msgid "reverse-index file %s has unknown signature"
 msgstr "tá síniú anaithnid ag comhad innéacs droim %s"
 
-#: pack-revindex.c
 #, c-format
 msgid "reverse-index file %s has unsupported version %<PRIu32>"
-msgstr "tá leagan neamh-tacaithe ag comhad innéacs droim %s% <PRIu32>"
+msgstr "tá comhad reverse-index %s le leagan %<PRIu32> nach dtacaítear leis"
 
-#: pack-revindex.c
 #, c-format
 msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
-msgstr "tá id hash neamh-tacaithe ag comhad innéacs droim %s% <PRIu32>"
+msgstr ""
+"tá comhad reverse-index %s le hais-aitheantas hash %<PRIu32> nach dtacaítear "
+"leis"
 
-#: pack-revindex.c
 msgid "invalid checksum"
 msgstr "seiceáil neamhbhailí"
 
-#: pack-revindex.c
 #, c-format
 msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
 msgstr ""
 "suíomh innéacs-athraithe neamhbhailí ag %<PRIu64>: %<PRIu32> != %<PRIu32>"
 
-#: pack-revindex.c
 msgid "multi-pack-index reverse-index chunk is the wrong size"
 msgstr "tá smután droim ar ais-innéacs il-phacáiste ar an méid mícheart"
 
-#: pack-revindex.c
 msgid "could not determine preferred pack"
 msgstr "ní fhéadfaí pacáiste is fearr a chinneadh"
 
-#: pack-write.c
 msgid "cannot both write and verify reverse index"
 msgstr "ní féidir innéacs droim a scríobh agus a fhíorú"
 
-#: pack-write.c
 #, c-format
 msgid "could not stat: %s"
 msgstr "ní fhéadfaí stat: %s"
 
-#: pack-write.c
 #, c-format
 msgid "failed to make %s readable"
 msgstr "theip ar %s a dhéanamh inléite"
 
-#: pack-write.c
 #, c-format
 msgid "could not write '%s' promisor file"
 msgstr "ní fhéadfaí comhad gealltanais '%s' a scríobh"
 
-#: packfile.c
 msgid "offset before end of packfile (broken .idx?)"
 msgstr "fhritháireamh roimh dheireadh an phackfile (.idx briste?)"
 
-#: packfile.c
 #, c-format
 msgid "packfile %s cannot be mapped%s"
 msgstr "ní féidir comhaid pacáiste %s a mhapáil %s"
 
-#: packfile.c
 #, c-format
 msgid "offset before start of pack index for %s (corrupt index?)"
 msgstr ""
 "fhritháireamh roimh thús an innéacs pacáiste do %s (innéacs truaillithe?)"
 
-#: packfile.c
 #, c-format
 msgid "offset beyond end of pack index for %s (truncated index?)"
 msgstr ""
 "fhritháireamh thar dheireadh an innéacs pacáiste do %s (innéacs gearrtha?)"
 
-#: parse-options-cb.c
 #, c-format
 msgid "malformed expiration date '%s'"
 msgstr "dáta éaga mífhoirmithe '%s'"
 
-#: parse-options-cb.c
 #, c-format
 msgid "option `%s' expects \"always\", \"auto\", or \"never\""
 msgstr "tá rogha `%s' ag súil le “i gcónaí”, “uathoibríoch”, nó “riamh”"
 
-#: parse-options-cb.c
 #, c-format
 msgid "malformed object name '%s'"
 msgstr "ainm réad mífhoirmithe '%s'"
 
-#: parse-options-cb.c
 #, c-format
 msgid "option `%s' expects \"%s\" or \"%s\""
 msgstr "tá rogha `%s' ag súil le “%s” nó “%s”"
 
-#: parse-options.c
 #, c-format
 msgid "%s requires a value"
 msgstr "Teastaíonn luach ó %s"
 
-#: parse-options.c
 #, c-format
 msgid "%s takes no value"
 msgstr "Ní ghlacann %s aon luach"
 
-#: parse-options.c
 #, c-format
 msgid "%s isn't available"
 msgstr "Níl %s ar fáil"
 
-#: parse-options.c
+#, c-format
+msgid "value for %s exceeds %<PRIdMAX>"
+msgstr "tá luach %s níos mó ná %<PRIdMAX>"
+
 #, c-format
 msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]"
 msgstr "luach %s do %s nach bhfuil sa raon [%<PRIdMAX>,%<PRIdMAX>]"
 
-#: parse-options.c
 #, c-format
 msgid "%s expects an integer value with an optional k/m/g suffix"
 msgstr "Tá %s ag súil le luach sláireach le iarmhír roghnach k/m/g"
 
-#: parse-options.c
 #, c-format
 msgid "%s expects a non-negative integer value with an optional k/m/g suffix"
 msgstr ""
 "Tá %s ag súil le luach sláimhir neamh-dhiúltach le iarmhír roghnach k/m/g"
 
-#: parse-options.c
 #, c-format
 msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
 msgstr "rogha débhríoch: %s (d'fhéadfadh a bheith --%s%s nó --%s%s)"
 
-#: parse-options.c
 #, c-format
 msgid "did you mean `--%s` (with two dashes)?"
 msgstr "an raibh i gceist agat `--%s` (le dhá shraith)?"
 
-#: parse-options.c
 #, c-format
 msgid "alias of --%s"
 msgstr "alias de --%s"
 
-#: parse-options.c
 msgid "need a subcommand"
 msgstr "fo-ordú ag teastáil"
 
-#: parse-options.c
 #, c-format
 msgid "unknown option `%s'"
 msgstr "rogha anaithnid `%s'"
 
-#: parse-options.c
 #, c-format
 msgid "unknown switch `%c'"
 msgstr "lasc anaithnid `%c'"
 
-#: parse-options.c
 #, c-format
 msgid "unknown non-ascii option in string: `%s'"
 msgstr "rogha neamh-ascii anaithnid i sreang: `%s'"
@@ -23721,7 +19888,6 @@
 #. "%s" without any placeholder signal.  Most
 #. translations leave this message as is.
 #.
-#: parse-options.c
 #, c-format
 msgid "[=<%s>]"
 msgstr "[=<%s>]"
@@ -23738,7 +19904,6 @@
 #. "%s" without any placeholder signal.  Most
 #. translations leave this message as is.
 #.
-#: parse-options.c
 #, c-format
 msgid "[<%s>]"
 msgstr "[<%s>]"
@@ -23753,16 +19918,13 @@
 #. may use "%s" without any placeholder signal.  Most
 #. translations leave this message as is.
 #.
-#: parse-options.c
 #, c-format
 msgid " <%s>"
 msgstr " <%s>"
 
-#: parse-options.c
 msgid "..."
 msgstr "..."
 
-#: parse-options.c
 #, c-format
 msgid "usage: %s"
 msgstr "úsáid: %s"
@@ -23770,7 +19932,6 @@
 #. TRANSLATORS: the colon here should align with the
 #. one in "usage: %s" translation.
 #.
-#: parse-options.c
 #, c-format
 msgid "   or: %s"
 msgstr "   nó: %s"
@@ -23794,115 +19955,90 @@
 #. translated) N_() usage string, which contained embedded
 #. newlines before we split it up.
 #.
-#: parse-options.c
 #, c-format
 msgid "%*s%s"
 msgstr "%*s%s"
 
-#: parse-options.c
 #, c-format
 msgid "    %s"
 msgstr "    %s"
 
-#: parse-options.c
 msgid "-NUM"
 msgstr "-NUMBER"
 
-#: parse-options.c
 #, c-format
 msgid "opposite of --no-%s"
 msgstr "os coinne de --no-%s"
 
-#: parse-options.h
 msgid "expiry-date"
 msgstr "dáta éaga"
 
-#: parse-options.h
 msgid "no-op (backward compatibility)"
 msgstr "no-op (comhoiriúnacht ar chúl)"
 
-#: parse-options.h
 msgid "be more verbose"
 msgstr "a bheith níos inbhreithnithe"
 
-#: parse-options.h
 msgid "be more quiet"
 msgstr "a bheith níos ciúine"
 
-#: parse-options.h
 msgid "use <n> digits to display object names"
 msgstr "úsáid dhigit <n>í chun ainmneacha réada a thaispe"
 
-#: parse-options.h
 msgid "prefixed path to initial superproject"
 msgstr "cosán réamhshocraithe chuig an superproject tosaigh"
 
-#: parse-options.h
 msgid "how to strip spaces and #comments from message"
 msgstr "conas spásanna agus #comments a scriosadh ó theachtaireacht"
 
-#: parse-options.h
 msgid "read pathspec from file"
 msgstr "léigh pathspec ón gcomhad"
 
-#: parse-options.h
 msgid ""
 "with --pathspec-from-file, pathspec elements are separated with NUL character"
 msgstr ""
 "le --pathspec-from-file, déantar eilimintí pathspec scartha le carachtar NUL"
 
-#: parse.c
 #, c-format
 msgid "bad boolean environment value '%s' for '%s'"
 msgstr "droch-luach timpeallachta boolean '%s' do '%s'"
 
-#: path-walk.c
 #, c-format
 msgid "failed to walk children of tree %s: not found"
 msgstr "theip ar pháistí crann %s a shiúl: níor aimsíodh"
 
-#: path-walk.c
 #, c-format
 msgid "failed to find object %s"
 msgstr "theip ar réad %s a aimsiú"
 
-#: path-walk.c
 #, c-format
 msgid "failed to find tag %s"
 msgstr "theip ar chlib %s a aimsiú"
 
-#: path-walk.c
 msgid "failed to setup revision walk"
 msgstr "theip orthu siúlóid athbhreithnithe"
 
-#: path.c
 #, c-format
 msgid "Could not make %s writable by group"
 msgstr "Ní fhéadfaí %s a dhéanamh inscríofa de réir grúpa"
 
-#: pathspec.c
 msgid "Escape character '\\' not allowed as last character in attr value"
 msgstr ""
 "Ní cheadaítear carachtar éalaithe '\\' mar charachtar deireanach i luach attr"
 
-#: pathspec.c
 msgid "Only one 'attr:' specification is allowed."
 msgstr "Ní cheadaítear ach sonraíocht 'attr: 'amháin."
 
-#: pathspec.c
 msgid "attr spec must not be empty"
 msgstr "ní chóir go mbeadh sonraíocht attr folamh"
 
-#: pathspec.c
 #, c-format
 msgid "invalid attribute name %s"
 msgstr "ainm tréithe neamhbhailí %s"
 
-#: pathspec.c
 msgid "global 'glob' and 'noglob' pathspec settings are incompatible"
 msgstr "níl socruithe pathspec domhanda 'glob' agus 'noglob' neamhoiriúnach"
 
-#: pathspec.c
 msgid ""
 "global 'literal' pathspec setting is incompatible with all other global "
 "pathspec settings"
@@ -23910,220 +20046,181 @@
 "níl suíomh cosáin domhanda 'litriúil' gan luí le gach socruithe beatháin "
 "domhanda eile"
 
-#: pathspec.c
 msgid "invalid parameter for pathspec magic 'prefix'"
 msgstr "paraiméadar neamhbhailí do 'réimír' draíochta pathspec"
 
-#: pathspec.c
 #, c-format
 msgid "Invalid pathspec magic '%.*s' in '%s'"
 msgstr "Draíocht pathspec neamhbhailí '%.*s' i '%s'"
 
-#: pathspec.c
 #, c-format
 msgid "Missing ')' at the end of pathspec magic in '%s'"
 msgstr "Ar iarraidh ')' ag deireadh draíochta pathspec i '%s'"
 
-#: pathspec.c
 #, c-format
 msgid "Unimplemented pathspec magic '%c' in '%s'"
 msgstr "Draíocht pathspec neamh-chur i bhfeidhm '%c' i '%s'"
 
-#: pathspec.c
 #, c-format
 msgid "%s: 'literal' and 'glob' are incompatible"
 msgstr "%s: Níl 'literal' agus 'glob' neamhoiriúnach"
 
-#: pathspec.c
 #, c-format
 msgid "'%s' is outside the directory tree"
 msgstr "Tá '%s' lasmuigh den chrann eolaire"
 
-#: pathspec.c
 #, c-format
 msgid "%s: '%s' is outside repository at '%s'"
 msgstr "%s: Tá '%s' an stór lasmuigh ag '%s'"
 
-#: pathspec.c
 #, c-format
 msgid "'%s' (mnemonic: '%c')"
 msgstr "'%s' (mnemonic: '%c')"
 
-#: pathspec.c
 #, c-format
 msgid "%s: pathspec magic not supported by this command: %s"
 msgstr "%s: nach dtacaíonn an t-ordú seo le draíocht pathspec: %s"
 
-#: pathspec.c
 #, c-format
 msgid "pathspec '%s' is beyond a symbolic link"
 msgstr "tá pathspec '%s' thar nasc siombalach"
 
-#: pathspec.c
 #, c-format
 msgid "line is badly quoted: %s"
 msgstr "tá an líne luaite go dona: %s"
 
-#: pkt-line.c
 msgid "unable to write flush packet"
-msgstr "in ann pacáiste srutháin a scríobh"
+msgstr "ní féidir pacáiste flush a scríobh"
 
-#: pkt-line.c
 msgid "unable to write delim packet"
-msgstr "in ann pacáiste delim a scríobh"
+msgstr "ní féidir pacáiste delim a scríobh"
 
-#: pkt-line.c
 msgid "unable to write response end packet"
-msgstr "in ann pacáiste deiridh freagartha a scríobh"
+msgstr "ní féidir pacáiste deiridh freagartha a scríobh"
 
-#: pkt-line.c
 msgid "flush packet write failed"
 msgstr "theip ar scríobh paicéad sru"
 
-#: pkt-line.c
 msgid "protocol error: impossibly long line"
 msgstr "earráid prótacal: líne fhada dodhéanta"
 
-#: pkt-line.c
 msgid "packet write with format failed"
 msgstr "theip ar scríobh pacáiste le formáid"
 
-#: pkt-line.c
 msgid "packet write failed - data exceeds max packet size"
 msgstr "theip ar scríobh paicéad - sáraíonn sonraí méid uasta an"
 
-#: pkt-line.c
 #, c-format
 msgid "packet write failed: %s"
 msgstr "theip ar scríobh pacáiste: %s"
 
-#: pkt-line.c
 msgid "read error"
 msgstr "earráid léigh"
 
-#: pkt-line.c
 msgid "the remote end hung up unexpectedly"
 msgstr "crochadh an deireadh iargúlta suas gan choinne"
 
-#: pkt-line.c
 #, c-format
 msgid "protocol error: bad line length character: %.4s"
 msgstr "earráid prótacal: carachtar fad droch-líne: %.4s"
 
-#: pkt-line.c
 #, c-format
 msgid "protocol error: bad line length %d"
 msgstr "earráid prótacal: fad droch-líne %d"
 
-#: pkt-line.c sideband.c
 #, c-format
 msgid "remote error: %s"
 msgstr "earráid iargúlta: %s"
 
-#: preload-index.c
 msgid "Refreshing index"
 msgstr "Innéacs athnuachana"
 
-#: preload-index.c
 #, c-format
 msgid "unable to create threaded lstat: %s"
-msgstr "nach féidir lstat snáithithe a chruthú: %s"
+msgstr "ní féidir lstat snáithithe a chruthú: %s"
 
-#: pretty.c
 msgid "unable to parse --pretty format"
-msgstr "in ann formáid --pretty a pháirseáil"
+msgstr "ní féidir formáid --pretty a pharsáil"
 
-#: promisor-remote.c
 msgid "lazy fetching disabled; some objects may not be available"
 msgstr ""
 "tarraingt leisciúil míchumasaithe; b'fhéidir nach mbeidh roinnt rudaí ar fáil"
 
-#: promisor-remote.c
 msgid "promisor-remote: unable to fork off fetch subprocess"
 msgstr "gealltó-iargúlta: ní féidir leis an bhfophróiseas faighte a fhorc"
 
-#: promisor-remote.c
 msgid "promisor-remote: could not write to fetch subprocess"
 msgstr "gealltó-iargúlta: ní fhéadfaí scríobh chun fophróiseas a fháil"
 
-#: promisor-remote.c
 msgid "promisor-remote: could not close stdin to fetch subprocess"
 msgstr "gealltó-iargúlta: ní fhéadfaí stdin a dhúnadh chun fophróiseas a fháil"
 
-#: promisor-remote.c
 #, c-format
 msgid "promisor remote name cannot begin with '/': %s"
 msgstr "ní féidir ainm iargúlta gealltanaí tosú le '/': %s"
 
-#: promisor-remote.c
 #, c-format
 msgid "could not fetch %s from promisor remote"
 msgstr "ní fhéadfaí %s a fháil ó iargúlta gealltanach"
 
-#: promisor-remote.c
+#, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr "réimse neamhthacaithe '%s' i gcumraíocht '%s'"
+
 #, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "níl aon URL nó folamh fógraithe le haghaidh iargúlta '%s'"
 
-#: promisor-remote.c
 #, c-format
 msgid "known remote named '%s' but with URL '%s' instead of '%s'"
 msgstr "iargúlta ar a dtugtar '%s' ach le URL '%s' in ionad '%s'"
 
-#: promisor-remote.c
+#, c-format
+msgid "invalid element '%s' from remote info"
+msgstr "eilimint neamhbhailí '%s' ó eolas iargúlta"
+
+#, c-format
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr "d’fhógair an freastalaí cianda promisor gan ainm ná URL: %s"
+
 #, c-format
 msgid "unknown '%s' value for '%s' config option"
 msgstr "luach '%s' anaithnid do rogha cumraithe '%s'"
 
-#: promisor-remote.c
-#, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "eilimint anaithnid '%s' ó fhaisnéis iargúlta"
-
-#: promisor-remote.c
 #, c-format
 msgid "accepted promisor remote '%s' not found"
 msgstr "nár aimsíodh gealltanas iargúlta '%s'"
 
-#: protocol-caps.c
 msgid "object-info: expected flush after arguments"
 msgstr "ear-eolas: súil le sruth tar éis argóintí"
 
-#: prune-packed.c
 msgid "Removing duplicate objects"
 msgstr "Rudaí dúblacha a bhaint"
 
-#: pseudo-merge.c
 #, c-format
 msgid "failed to load pseudo-merge regex for %s: '%s'"
 msgstr "theip ar régex bréag-cumaisc a luchtú do %s: '%s'"
 
-#: pseudo-merge.c
 #, c-format
 msgid "%s must be non-negative, using default"
 msgstr "Ní mór %s a bheith neamh-dhiúltach, ag baint úsáide as"
 
-#: pseudo-merge.c
 #, c-format
 msgid "%s must be between 0 and 1, using default"
 msgstr "Caithfidh %s a bheith idir 0 agus 1, ag baint úsáide as réamhshocrú"
 
-#: pseudo-merge.c
 #, c-format
 msgid "%s must be positive, using default"
 msgstr "Caithfidh %s a bheith dearfach, ag úsáid réamhshocraithe"
 
-#: pseudo-merge.c
 #, c-format
 msgid "pseudo-merge group '%s' missing required pattern"
 msgstr "grúpa bréagchumaisc '%s' ar iarraidh patrún riachtanach"
 
-#: pseudo-merge.c
 #, c-format
 msgid "pseudo-merge group '%s' has unstable threshold before stable one"
 msgstr "tá tairseach éagobhsaí ag an ngrúpa bréagchumaisc '%s' roimh cheann"
 
-#: pseudo-merge.c
 #, c-format
 msgid ""
 "pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)"
@@ -24131,57 +20228,47 @@
 "tá an iomarca grúpaí gabhála sa regex pseudo-merge ón chumraíocht "
 "(uasmhéid=%<PRIuMAX>)"
 
-#: pseudo-merge.c
 #, c-format
 msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)"
 msgstr ""
 "léamh sínte cumaisc bhréige lasmuigh de theorainneacha (%<PRIuMAX> >= "
 "%<PRIuMAX>)"
 
-#: pseudo-merge.c
 #, c-format
 msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)"
 msgstr "tá an iontráil shínte chumaisc ró-ghearr (%<PRIuMAX> >= %<PRIuMAX>)"
 
-#: pseudo-merge.c
 #, c-format
 msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>"
 msgstr ""
 "ní fhéadfaí a aimsiú bréag-chumasc do thiomantas %s ag "
 "fhritháireamh%<PRIuMAX>"
 
-#: pseudo-merge.c
 #, c-format
 msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)"
 msgstr ""
 "cuardach sínte cumaisc bhréige lasmuigh de theorainneacha (%<PRIu32> >= "
 "%<PRIu32>)"
 
-#: pseudo-merge.c
 #, c-format
 msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)"
 msgstr "léamh lasmuigh de theorainneacha: (%<PRIuMAX> >= %<PRIuMAX>)"
 
-#: pseudo-merge.c
 #, c-format
 msgid "could not read extended pseudo-merge table for commit %s"
 msgstr ""
 "ní fhéadfaí tábla bréag-chumaisc leathnaithe a léamh le haghaidh tiomanta %s"
 
-#: range-diff.c
 msgid "could not start `log`"
 msgstr "ní fhéadfaí 'log' a thosú"
 
-#: range-diff.c
 msgid "could not read `log` output"
 msgstr "ní raibh in ann aschur `log` a léamh"
 
-#: range-diff.c sequencer.c
 #, c-format
 msgid "could not parse commit '%s'"
 msgstr "ní fhéadfaí gealladh '%s' a pháirseáil"
 
-#: range-diff.c
 #, c-format
 msgid ""
 "could not parse first line of `log` output: did not start with 'commit ': "
@@ -24190,66 +20277,63 @@
 "ní raibh sé in ann an chéad líne d'aschur `log` a pháirseáil: níor thosaigh "
 "sé le 'commit': '%s'"
 
-#: range-diff.c
 #, c-format
 msgid "could not parse git header '%.*s'"
 msgstr "níorbh fhéidir ceanntásc git a pharsáil '%.*s'"
 
-#: range-diff.c
 msgid "failed to generate diff"
 msgstr "theip ar éagsúlacht a ghiniúint"
 
-#: range-diff.c
+#, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+"difríocht-raoin: ní féidir an difríocht-raoin a ríomh, ós rud é go sáraíonn "
+"sé an uasmhéid cuimhne don mhaitrís costais: %s (%<PRIuMAX> beart) ag "
+"teastáil, teoranta do %s (%<PRIuMAX> beart)"
+
 #, c-format
 msgid "could not parse log for '%s'"
 msgstr "ní raibh in ann logáil a pháirseáil le haghaidh '%s'"
 
-#: reachable.c
 #, c-format
 msgid "invalid extra cruft tip: '%s'"
 msgstr "tip cruft bhreise neamhbhailí: '%s'"
 
-#: reachable.c
 msgid "unable to enumerate additional recent objects"
-msgstr "in ann rudaí breise le déanaí a áireamh"
+msgstr "ní féidir réada breise le déanaí a liostú"
 
-#: read-cache.c
 #, c-format
 msgid "will not add file alias '%s' ('%s' already exists in index)"
 msgstr ""
 "ní chuirfidh sé alias comhad '%s' leis (tá '%s' ann cheana féin san innéacs)"
 
-#: read-cache.c
 msgid "cannot create an empty blob in the object database"
 msgstr "ní féidir le blob folamh a chruthú sa bhunachar sonraí réad"
 
-#: read-cache.c
 #, c-format
 msgid "%s: can only add regular files, symbolic links or git-directories"
 msgstr ""
 "%s: ní féidir ach comhaid rialta, naisc siombalacha nó eolairí git-eolairí a "
 "chur leis"
 
-#: read-cache.c
 #, c-format
 msgid "unable to index file '%s'"
 msgstr "ní féidir an comhad '%s' a innéacsú"
 
-#: read-cache.c
 #, c-format
 msgid "unable to add '%s' to index"
 msgstr "ní féidir '%s' a chur leis an innéacs"
 
-#: read-cache.c
 #, c-format
 msgid "'%s' appears as both a file and as a directory"
 msgstr "Tá '%s' le feiceáil mar chomhad agus mar eolaire"
 
-#: read-cache.c
 msgid "Refresh index"
 msgstr "Innéacs athnuachan"
 
-#: read-cache.c
 #, c-format
 msgid ""
 "index.version set, but the value is invalid.\n"
@@ -24258,7 +20342,6 @@
 "index.version socraithe, ach tá an luach neamhbhailí.\n"
 "Ag baint úsáide as leagan %i"
 
-#: read-cache.c
 #, c-format
 msgid ""
 "GIT_INDEX_VERSION set, but the value is invalid.\n"
@@ -24267,143 +20350,114 @@
 "socraigh GIT_INDEX_VERSION, ach tá an luach neamhbhailí.\n"
 "Ag baint úsáide as leagan %i"
 
-#: read-cache.c
 #, c-format
 msgid "bad signature 0x%08x"
 msgstr "droch-shíniú 0x%08x"
 
-#: read-cache.c
 #, c-format
 msgid "bad index version %d"
 msgstr "leagan innéacs droch%d"
 
-#: read-cache.c
 msgid "bad index file sha1 signature"
 msgstr "comhad innéacs droch-sha1 síniú"
 
-#: read-cache.c
 #, c-format
 msgid "index uses %.4s extension, which we do not understand"
 msgstr "úsáideann innéacs síneadh %.4s, nach dtuigimid"
 
-#: read-cache.c
 #, c-format
 msgid "ignoring %.4s extension"
 msgstr "neamhaird a dhéanamh le síneadh %.4s"
 
-#: read-cache.c
 #, c-format
 msgid "unknown index entry format 0x%08x"
 msgstr "formáid iontrála innéacs anaithnid 0x%08x"
 
-#: read-cache.c
 #, c-format
 msgid "malformed name field in the index, near path '%s'"
 msgstr "réimse ainm mhífhoirmithe san innéacs, in aice le cosán '%s'"
 
-#: read-cache.c
 msgid "unordered stage entries in index"
 msgstr "iontrálacha céime neamh-ordaithe san innéacs"
 
-#: read-cache.c
 #, c-format
 msgid "multiple stage entries for merged file '%s'"
 msgstr "iontrálacha ilchéime do chomhad cumaisc '%s'"
 
-#: read-cache.c
 #, c-format
 msgid "unordered stage entries for '%s'"
 msgstr "iontrálacha stáitse neamh-ordaithe do '%s'"
 
-#: read-cache.c
 #, c-format
 msgid "unable to create load_cache_entries thread: %s"
 msgstr "ní féidir an snáithe load_cache_entries a chruthú: %s"
 
-#: read-cache.c
 #, c-format
 msgid "unable to join load_cache_entries thread: %s"
 msgstr "ní féidir teacht le snáithe load_cache_entries thread: %s"
 
-#: read-cache.c
 #, c-format
 msgid "%s: index file open failed"
 msgstr "%s: theip ar oscailt comhad innéacs"
 
-#: read-cache.c
 #, c-format
 msgid "%s: cannot stat the open index"
 msgstr "%s: ní féidir an t-innéacs oscailte a stáit"
 
-#: read-cache.c
 #, c-format
 msgid "%s: index file smaller than expected"
 msgstr "%s: comhad innéacs níos lú ná mar a bhí súil leis"
 
-#: read-cache.c
 #, c-format
 msgid "%s: unable to map index file%s"
 msgstr "%s: ní féidir comhad innéacs %s a mhapáil"
 
-#: read-cache.c
 #, c-format
 msgid "unable to create load_index_extensions thread: %s"
-msgstr "nach féidir snáithe load_index_extensions a chruthú: %s"
+msgstr "ní féidir an snáithe load_index_extensions a chruthú: %s"
 
-#: read-cache.c
 #, c-format
 msgid "unable to join load_index_extensions thread: %s"
 msgstr "ní féidir teacht le snáithe load_index_extensions: %s"
 
-#: read-cache.c
 #, c-format
 msgid "could not freshen shared index '%s'"
 msgstr "ní raibh in ann innéacs roinnte '%s' a athnuachan"
 
-#: read-cache.c
 #, c-format
 msgid "broken index, expect %s in %s, got %s"
 msgstr "innéacs briste, súil le %s i %s, fuair %s"
 
-#: read-cache.c
 msgid "cannot write split index for a sparse index"
 msgstr "ní féidir innéacs scoilte a scríobh le haghaidh innéacs neall"
 
-#: read-cache.c
 msgid "failed to convert to a sparse-index"
 msgstr "theip ar thiontú go innéacs neamhchoitianta"
 
-#: read-cache.c
 #, c-format
 msgid "unable to open git dir: %s"
-msgstr "in ann git dir a oscailt: %s"
+msgstr "ní féidir an eolaire git a oscailt: %s"
 
-#: read-cache.c
 #, c-format
 msgid "unable to unlink: %s"
-msgstr "nach féidir dínasc a dhéanamh: %s"
+msgstr "ní féidir dícheangal: %s"
 
-#: read-cache.c
 #, c-format
 msgid "cannot fix permission bits on '%s'"
 msgstr "ní féidir giotáin ceada a shocrú ar '%s'"
 
-#: read-cache.c
 #, c-format
 msgid "%s: cannot drop to stage #0"
 msgstr "%s: ní féidir titim go dtí céim #0"
 
-#: read-cache.c
 #, c-format
 msgid "unexpected diff status %c"
 msgstr "stádas diff gan choinne %c"
 
-#: read-cache.c
 #, c-format
 msgid "remove '%s'\n"
 msgstr "bain '%s'\n"
 
-#: rebase-interactive.c
 msgid ""
 "You can fix this with 'git rebase --edit-todo' and then run 'git rebase --"
 "continue'.\n"
@@ -24413,7 +20467,6 @@
 "rebase --continue' a rith.\n"
 "Nó is féidir leat an rebase a chur le 'git rebase --abort'.\n"
 
-#: rebase-interactive.c
 #, c-format
 msgid ""
 "unrecognized setting %s for option rebase.missingCommitsCheck. Ignoring."
@@ -24421,7 +20474,6 @@
 "socrú neamhaithnithe %s le haghaidh rogha rebase.missingCommitsCheck. "
 "Neamhaird a dhéanamh."
 
-#: rebase-interactive.c
 msgid ""
 "\n"
 "Commands:\n"
@@ -24483,7 +20535,6 @@
 "Is féidir na línte seo a athordú; déantar iad a fhorghníomhú ó bharr go "
 "bun.\n"
 
-#: rebase-interactive.c
 #, c-format
 msgid "Rebase %s onto %s (%d command)"
 msgid_plural "Rebase %s onto %s (%d commands)"
@@ -24491,7 +20542,6 @@
 msgstr[1] "Athbhunú %s ar %s (%d orduithe)"
 msgstr[2] "Athbhunú %s ar %s (%d orduithe)"
 
-#: rebase-interactive.c
 msgid ""
 "\n"
 "Do not remove any line. Use 'drop' explicitly to remove a commit.\n"
@@ -24500,7 +20550,6 @@
 "Ná bain aon líne. Bain úsáid as 'drop' go sainráite chun tiomantas a "
 "bhaint.\n"
 
-#: rebase-interactive.c
 msgid ""
 "\n"
 "If you remove a line here THAT COMMIT WILL BE LOST.\n"
@@ -24508,7 +20557,6 @@
 "\n"
 "Má bhaineann tú líne anseo CAILLFIDH AN TIOMANTAS.\n"
 
-#: rebase-interactive.c
 msgid ""
 "\n"
 "You are editing the todo file of an ongoing interactive rebase.\n"
@@ -24523,7 +20571,6 @@
 "    git rebase --continue\n"
 "\n"
 
-#: rebase-interactive.c
 msgid ""
 "\n"
 "However, if you remove everything, the rebase will be aborted.\n"
@@ -24532,12 +20579,10 @@
 "\n"
 "Mar sin féin, má bhaineann tú gach rud, cuirfear deireadh leis an athbhunú.\n"
 
-#: rebase-interactive.c
 #, c-format
 msgid "could not write '%s'."
 msgstr "ní fhéadfaí '%s' a scríobh."
 
-#: rebase-interactive.c
 #, c-format
 msgid ""
 "Warning: some commits may have been dropped accidentally.\n"
@@ -24546,7 +20591,6 @@
 "Rabhadh: b'fhéidir gur titim roinnt gealltanna de thaisme.\n"
 "Gealltanna titim (níos nuaí go níos sine):\n"
 
-#: rebase-interactive.c
 #, c-format
 msgid ""
 "To avoid this message, use \"drop\" to explicitly remove a commit.\n"
@@ -24564,298 +20608,251 @@
 "Is iad na hiompraíochtaí féideartha: neamhaird a dhéanamh, rabhadh, "
 "earráid.\n"
 
-#: rebase.c
 #, c-format
 msgid "%s: 'preserve' superseded by 'merges'"
 msgstr "%s: cuireadh 'caomhnú' in ionad 'le' cumaisc '"
 
-#: ref-filter.c wt-status.c
 msgid "gone"
 msgstr "imithe"
 
-#: ref-filter.c
 #, c-format
 msgid "ahead %d"
 msgstr "ar aghaidh %d"
 
-#: ref-filter.c
 #, c-format
 msgid "behind %d"
 msgstr "taobh thiar de %d"
 
-#: ref-filter.c
 #, c-format
 msgid "ahead %d, behind %d"
 msgstr "tosaigh %d, taobh thiar de %d"
 
-#: ref-filter.c
 #, c-format
 msgid "%%(%.*s) does not take arguments"
 msgstr "%%(%.*s) ní ghlacann argóintí"
 
-#: ref-filter.c
 #, c-format
 msgid "unrecognized %%(%.*s) argument: %s"
 msgstr "neamhaithnithe %%(%.*s) argóint: %s"
 
-#: ref-filter.c
 #, c-format
 msgid "expected format: %%(color:<color>)"
 msgstr "formáid ionchais: %%(color:<dath>)"
 
-#: ref-filter.c
 #, c-format
 msgid "unrecognized color: %%(color:%s)"
 msgstr "dath gan aithint: %%(color:%s)"
 
-#: ref-filter.c
 #, c-format
 msgid "Integer value expected refname:lstrip=%s"
 msgstr "Luach sláimhir a bhfuiltear ag súil leis refname:lstrip=%s"
 
-#: ref-filter.c
 #, c-format
 msgid "Integer value expected refname:rstrip=%s"
 msgstr "Luach sláimhir a bhfuiltear ag súil leis refname:rstrip=%s"
 
-#: ref-filter.c
 #, c-format
 msgid "expected %%(trailers:key=<value>)"
 msgstr "ionchasach %%(trailers:key=<value>)"
 
-#: ref-filter.c
 #, c-format
 msgid "unknown %%(trailers) argument: %s"
 msgstr "argóint %%(trailers) anaithnid: %s"
 
-#: ref-filter.c
 #, c-format
 msgid "positive value expected contents:lines=%s"
 msgstr "ábhar ag súil le luach dearfach:lines=%s"
 
-#: ref-filter.c
 #, c-format
 msgid "argument expected for %s"
 msgstr "argóint ag súil le haghaidh %s"
 
-#: ref-filter.c
 #, c-format
 msgid "positive value expected %s=%s"
 msgstr "luach dearfach a bhfuiltear ag súil leis %s=%s"
 
-#: ref-filter.c
 #, c-format
 msgid "cannot fully parse %s=%s"
 msgstr "ní féidir %s=%s a pháirseáil go hiomlán"
 
-#: ref-filter.c
 #, c-format
 msgid "value expected %s="
 msgstr "luach ag súil leis %s="
 
-#: ref-filter.c
 #, c-format
 msgid "positive value expected '%s' in %%(%s)"
 msgstr "luach dearfach a bhíothas ag súil le '%s' i %%(%s)"
 
-#: ref-filter.c
 #, c-format
 msgid "expected format: %%(align:<width>,<position>)"
 msgstr "ionchasach formáid: %%(align:<width>,<position>)"
 
-#: ref-filter.c
 #, c-format
 msgid "unrecognized position:%s"
 msgstr "suíomh gan aithint:%s"
 
-#: ref-filter.c
 #, c-format
 msgid "unrecognized width:%s"
 msgstr "leithead gan aithint:%s"
 
-#: ref-filter.c
 #, c-format
 msgid "unrecognized %%(%s) argument: %s"
 msgstr "argóint %%(%s) gan aitheantas: %s"
 
-#: ref-filter.c
 #, c-format
 msgid "positive width expected with the %%(align) atom"
 msgstr "leithead dearfach a bhíothas ag súil leis leis an adamh %%(align)"
 
-#: ref-filter.c
 #, c-format
 msgid "expected format: %%(ahead-behind:<committish>)"
 msgstr "formáid ionchais:  %%(ahead-behind:<committish>)"
 
-#: ref-filter.c
 #, c-format
 msgid "expected format: %%(is-base:<committish>)"
 msgstr "formáid ionchais: %%(is-base:<committish>)"
 
-#: ref-filter.c
 #, c-format
 msgid "malformed field name: %.*s"
 msgstr "ainm réimse mífhoirmithe: %.*s"
 
-#: ref-filter.c
 #, c-format
 msgid "unknown field name: %.*s"
 msgstr "ainm réimse anaithnid: %.*s"
 
-#: ref-filter.c
 #, c-format
 msgid ""
 "not a git repository, but the field '%.*s' requires access to object data"
 msgstr ""
 "ní stórlann git é, ach éilíonn an réimse '%.*s' rochtain ar shonraí réada"
 
-#: ref-filter.c
 #, c-format
 msgid "format: %%(%s) atom used without a %%(%s) atom"
 msgstr "formáid: %%(%s) adaim a úsáidtear gan adaim %%(%s)"
 
-#: ref-filter.c
 #, c-format
 msgid "format: %%(then) atom used more than once"
 msgstr "formáid: %%(then) adaim a úsáidtear níos mó ná uair amháin"
 
-#: ref-filter.c
 #, c-format
 msgid "format: %%(then) atom used after %%(else)"
 msgstr "formáid: %%(then) adaim a úsáidtear tar éis %%(else)"
 
-#: ref-filter.c
 #, c-format
 msgid "format: %%(else) atom used more than once"
 msgstr "formáid: %%(else) adaim a úsáidtear níos mó ná uair amháin"
 
-#: ref-filter.c
 #, c-format
 msgid "format: %%(end) atom used without corresponding atom"
 msgstr "formáid: %%(end) adaim a úsáidtear gan adaim chomhfhreagrach"
 
-#: ref-filter.c
 #, c-format
 msgid "malformed format string %s"
 msgstr "teaghrán formáid mhífhoirmithe %s"
 
-#: ref-filter.c
 #, c-format
 msgid "this command reject atom %%(%.*s)"
 msgstr "diúltú an t-ordú seo adamh %%(%.*s)"
 
-#: ref-filter.c
 #, c-format
 msgid "--format=%.*s cannot be used with --python, --shell, --tcl"
 msgstr "--format=%.*s ní féidir é a úsáid le --python, --shell, --tcl"
 
-#: ref-filter.c
 msgid "failed to run 'describe'"
 msgstr "theip ar 'cur síos' a rith"
 
-#: ref-filter.c
 #, c-format
 msgid "(no branch, rebasing %s)"
 msgstr "(gan aon bhrainse, athbhunú %s)"
 
-#: ref-filter.c
 #, c-format
 msgid "(no branch, rebasing detached HEAD %s)"
 msgstr "(gan aon bhrainse, athbhunú CEAD scoite %s)"
 
-#: ref-filter.c
 #, c-format
 msgid "(no branch, bisect started on %s)"
 msgstr "(gan aon bhrainse, thosaigh bisect ar %s)"
 
-#: ref-filter.c
 #, c-format
 msgid "(HEAD detached at %s)"
 msgstr "(HEAD scoite ag %s)"
 
-#: ref-filter.c
 #, c-format
 msgid "(HEAD detached from %s)"
 msgstr "(CEAD scoite ó %s)"
 
-#: ref-filter.c
 msgid "(no branch)"
 msgstr "(gan aon bhrainse)"
 
-#: ref-filter.c
 #, c-format
 msgid "missing object %s for %s"
 msgstr "réad atá ar iarraidh %s do %s"
 
-#: ref-filter.c
 #, c-format
 msgid "parse_object_buffer failed on %s for %s"
 msgstr "theip ar parse_object_buffer ar %s do %s"
 
-#: ref-filter.c
 #, c-format
 msgid "malformed object at '%s'"
 msgstr "réad mífhoirmithe ag '%s'"
 
-#: ref-filter.c
 #, c-format
 msgid "ignoring ref with broken name %s"
 msgstr "neamhaird a dhéanamh ar tagairt le ainm briste %s"
 
-#: ref-filter.c refs.c
 #, c-format
 msgid "ignoring broken ref %s"
 msgstr "ag déanamh neamhaird ar thagairt briste %s"
 
-#: ref-filter.c
 #, c-format
 msgid "format: %%(end) atom missing"
 msgstr "formáid :%%(end) ataim ar iarraidh"
 
-#: ref-filter.c
 #, c-format
 msgid "malformed object name %s"
 msgstr "ainm réad mífhoirmithe %s"
 
-#: ref-filter.c
 #, c-format
 msgid "option `%s' must point to a commit"
 msgstr "caithfidh rogha `%s' a chur in iúl do thiomantas"
 
-#: ref-filter.h
 msgid "key"
 msgstr "eochair"
 
-#: ref-filter.h
 msgid "field name to sort on"
 msgstr "ainm réimse le sórtáil"
 
-#: ref-filter.h
 msgid "exclude refs which match pattern"
 msgstr "a eisiamh iarmhairtí a mheaitseálann patrún"
 
-#: reflog.c
 #, c-format
 msgid "not a reflog: %s"
 msgstr "ní athbhreithniú: %s"
 
-#: reflog.c
 #, c-format
 msgid "no reflog for '%s'"
 msgstr "gan aon athbhreithniú do '%s'"
 
-#: refs.c
+msgid "Checking references consistency"
+msgstr "Comhsheasmhacht tagairtí"
+
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "Ní thugann %s in iúl go réad bailí!"
 
-#: refs.c
+#, c-format
+msgid "%s%s will become dangling after %s is deleted\n"
+msgstr "Beidh %s%s crochta tar éis %s a scriosadh\n"
+
+#, c-format
+msgid "%s%s has become dangling after %s was deleted\n"
+msgstr "Tá %s%s crochta anois tar éis %s a scriosadh\n"
+
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -24864,131 +20861,144 @@
 "\n"
 "\tgit branch -m <name>\n"
 msgstr ""
-"Ag baint úsáide as '%s' mar ainm don bhrainse tosaigh. An ainm brainse "
-"réamhshocraithe\n"
-"tá sé faoi réir athraithe. Chun an t-ainm brainse tosaigh a chumrú le húsáid "
-"i ngach\n"
-"de do stór nua, a chuirfidh an rabhadh seo a chur faoi chois, glaoigh ar:\n"
+"Ag baint úsáide as '%s' mar ainm don bhrainse tosaigh. Athróidh an t-ainm "
+"réamhshocraithe brainse seo go \"main\" i Git 3.0. Chun ainm an bhrainse "
+"tosaigh a chumrú\n"
+"le húsáid i do stórtha nua go léir, rud a chuirfidh cosc ​​ar an rabhadh seo,\n"
+"glaoigh ar:\n"
 "\n"
-"\tgit config --global init.defaultBranch <name>\n"
+"git config --global init.defaultBranch <name>\n"
 "\n"
-"Is iad na hainmneacha a roghnaítear go coitianta in ionad 'máistir' príomh "
-"',' stoc 'agus\n"
-"'forbair'. Is féidir an brainse atá díreach cruthaithe a athainmniú tríd an "
+"Is iad na hainmneacha a roghnaítear go coitianta in ionad 'master' ná "
+"'main', 'trunk' agus\n"
+"'development'. Is féidir an brainse díreach cruthaithe a athainmniú tríd an "
 "ordú seo:\n"
 "\n"
-"\tgit branch -m <name>\n"
+"git branch -m <name>\n"
 
-#: refs.c
+#, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"Ag baint úsáide as '%s' mar ainm don chéad bhrainse ó Git 3.0.\n"
+"Más rud é go raibh súil agat go gcruthódh Git 'master', is féidir an brainse "
+"a cruthaíodh díreach a athainmniú tríd an ordú seo:\n"
+"\n"
+"git branch -m master\n"
+
 #, c-format
 msgid "could not retrieve `%s`"
 msgstr "ní fhéadfaí `%s` a aisghabháil"
 
-#: refs.c
 #, c-format
 msgid "invalid branch name: %s = %s"
 msgstr "ainm brainse neamhbhailí: %s = %s"
 
-#: refs.c
 #, c-format
 msgid "ignoring dangling symref %s"
 msgstr "ag déanamh neamhaird ar shiomtref crochta %s"
 
-#: refs.c
 #, c-format
 msgid "log for ref %s has gap after %s"
 msgstr "tá bearna ag logáil le haghaidh tagairt %s tar éis %s"
 
-#: refs.c
 #, c-format
 msgid "log for ref %s unexpectedly ended on %s"
 msgstr "chríochnaigh logáil le haghaidh tagairt %s gan choinne ar %s"
 
-#: refs.c
 #, c-format
 msgid "log for %s is empty"
 msgstr "tá logáil le haghaidh %s folamh"
 
-#: refs.c
 #, c-format
 msgid "refusing to update reflog for pseudoref '%s'"
 msgstr "diúltú reflog a nuashonrú do pseudoref '%s'"
 
-#: refs.c
 #, c-format
 msgid "refusing to update pseudoref '%s'"
 msgstr "diúltú pseudoref '%s' a nuashonrú"
 
-#: refs.c
 #, c-format
 msgid "refusing to update reflog with bad name '%s'"
 msgstr "diúltú reflog a nuashonrú le droch-ainm '%s'"
 
-#: refs.c
 #, c-format
 msgid "refusing to update ref with bad name '%s'"
 msgstr "diúltú tagairt a nuashonrú le droch-ainm '%s'"
 
-#: refs.c
 msgid "refusing to force and skip creation of reflog"
 msgstr "diúltú cruthú reflog a chur i bhfeidhm agus a scipeáil"
 
-#: refs.c
 #, c-format
 msgid "update_ref failed for ref '%s': %s"
 msgstr "theip ar update_ref le haghaidh tagairt '%s': %s"
 
-#: refs.c
 #, c-format
 msgid "multiple updates for ref '%s' not allowed"
 msgstr "ní cheadaítear nuashonruithe iolracha le haghaidh tagairt '%s'"
 
-#: refs.c
 msgid "ref updates forbidden inside quarantine environment"
 msgstr "nuashonruithe ref toirmiscthe laistigh de"
 
-#: refs.c
 msgid "ref updates aborted by hook"
 msgstr "nuashonruithe tagartha a chuirtear deireadh leis"
 
-#: refs.c
 #, c-format
 msgid "'%s' exists; cannot create '%s'"
 msgstr "Tá '%s' ann; ní féidir '%s' a chruthú"
 
-#: refs.c
 #, c-format
 msgid "cannot process '%s' and '%s' at the same time"
 msgstr "ní féidir '%s' agus '%s' a phróiseáil ag an am céanna"
 
-#: refs.c
 #, c-format
 msgid "could not delete reference %s: %s"
 msgstr "ní fhéadfaí tagairt %s a scriosadh: %s"
 
-#: refs.c
 #, c-format
 msgid "could not delete references: %s"
 msgstr "ní fhéadfaí tagairtí a scriosadh: %s"
 
-#: refs.c
 #, c-format
 msgid "Finished dry-run migration of refs, the result can be found at '%s'\n"
 msgstr ""
 "Imirce tirim críochnaithe na n-iarmhairc, is féidir an toradh a fháil ag "
 "'%s'\n"
 
-#: refs.c
 #, c-format
 msgid "could not remove temporary migration directory '%s'"
 msgstr "ní fhéadfaí eolaire imirce sealadach '%s' a bhaint"
 
-#: refs.c
 #, c-format
 msgid "migrated refs can be found at '%s'"
 msgstr "is féidir airgeanna imirceacha a fháil ag '%s'"
 
-#: refs/files-backend.c refs/reftable-backend.c
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+"Tá 'core.preferSymlinkRefs=true' ainmnithe le haghaidh bainte.\n"
+"leid: Tá úsáid naisc shiombalacha le haghaidh tagairtí siombalacha imithe i "
+"léig\n"
+"leid: agus bainfear iad i Git 3.0. Dá bhrí sin, tá an chumraíocht a\n"
+"leid: insíonn do Git iad a úsáid ag imeacht. Is féidir leat é a dhíchumasú\n"
+"leid: le:\n"
+"leid:\n"
+"leid:\tgit config unset core.preferSymlinkRefs\n"
+"leid:\n"
+"leid: Úsáidfidh Git an fhormáid symref téacsúil ina ionad."
+
 #, c-format
 msgid ""
 "cannot lock ref '%s': expected symref with target '%s': but is a regular ref"
@@ -24996,41 +21006,34 @@
 "ní féidir tagairt '%s' a ghlasáil: ag súil le symref le sprioc '%s': ach is "
 "tagairt rialta é"
 
-#: refs/files-backend.c
+#, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr "ag iarraidh reflog a scríobh do '%s' le luachanna neamhiomlána"
+
 #, c-format
 msgid "cannot read ref file '%s'"
 msgstr "ní féidir comhad tagartha '%s' a léamh"
 
-#: refs/files-backend.c
 #, c-format
 msgid "cannot open directory %s"
 msgstr "ní féidir eolaire %s a oscailt"
 
-#: refs/files-backend.c
-msgid "Checking references consistency"
-msgstr "Comhsheasmhacht tagairtí"
-
-#: refs/packed-backend.c
 #, c-format
 msgid "unable to open '%s'"
 msgstr "ní féidir '%s' a oscailt"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "refname is dangerous: %s"
 msgstr "tá refname contúirteach: %s"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "trying to write ref '%s' with nonexistent object %s"
 msgstr "ag iarraidh tagairt '%s' a scríobh le réad nach bhfuil %s ann"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "trying to write non-commit object %s to branch '%s'"
 msgstr "ag iarraidh réad neamh-thiomanta %s a scríobh chuig brainse '%s'"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid ""
 "multiple updates for 'HEAD' (including one via its referent '%s') are not "
@@ -25039,17 +21042,14 @@
 "ní cheadaítear nuashonruithe iolracha do 'HEAD' (lena n-áirítear ceann tríd "
 "an tagairt '%s')"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "cannot lock ref '%s': unable to resolve reference '%s'"
 msgstr "ní féidir tagairt '%s' a ghlasáil: ní féidir tagairt '%s' a réiteach"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "cannot lock ref '%s': error reading reference"
 msgstr "ní féidir tagairt '%s' a ghlasáil: earráid ag léamh tagairt"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid ""
 "multiple updates for '%s' (including one via symref '%s') are not allowed"
@@ -25057,213 +21057,172 @@
 "ní cheadaítear nuashonruithe iolracha do '%s' (lena n-áirítear ceann trí "
 "symref '%s')"
 
-#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr ""
+"ní féidir an tagairt '%s' a ghlasáil: tá an tagairt shiombalach crochta ann "
+"cheana féin"
+
 #, c-format
 msgid "cannot lock ref '%s': reference already exists"
 msgstr "ní féidir tagairt '%s' a ghlasáil: tá tagairt ann cheana féin"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "cannot lock ref '%s': reference is missing but expected %s"
 msgstr ""
 "ní féidir tagairt '%s' a ghlasáil: tá tagairt ar iarraidh ach táthar ag súil "
 "leis %s"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "cannot lock ref '%s': is at %s but expected %s"
 msgstr ""
 "ní féidir tagairt '%s' a ghlasáil: tá sé ag %s ach táthar ag súil leis %s"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "reftable: transaction prepare: %s"
 msgstr "athfhabhtaithe: ullmhú idirbheart: %s"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "reftable: transaction failure: %s"
 msgstr "athfhabhtaithe: teip ar idirbheart: %s"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "unable to compact stack: %s"
-msgstr "nach féidir cruach a dhlúthú: %s"
+msgstr "ní féidir an cruach a chomhdhlúthú: %s"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "refname %s not found"
 msgstr "ní aimsíodh refname %s"
 
-#: refs/reftable-backend.c
 #, c-format
 msgid "refname %s is a symbolic ref, copying it is not supported"
 msgstr "rs tagairt siombalach é refname %s, ní thacaítear leis a chóipeáil"
 
-#: refspec.c
 #, c-format
 msgid "pattern '%s' has no '*'"
 msgstr "níl aon '*' ag patrún '%s'"
 
-#: refspec.c
 #, c-format
 msgid "replacement '%s' has no '*'"
 msgstr "níl aon '*' ag athsholáthar '%s'"
 
-#: remote-curl.c
 #, c-format
 msgid "invalid quoting in push-option value: '%s'"
 msgstr "luachan neamhbhailí i luach brú rogha: '%s'"
 
-#: remote-curl.c
 #, c-format
 msgid "unknown value for object-format: %s"
 msgstr "luach anaithnid d'fhormáid réad: %s"
 
-#: remote-curl.c
 #, c-format
 msgid "%sinfo/refs not valid: is this a git repository?"
 msgstr "Níl %sinfo/refs bailí: an stór git é seo?"
 
-#: remote-curl.c
 msgid "invalid server response; expected service, got flush packet"
 msgstr "freagra freastalaí neamhbhailí; seirbhís a bhíothas ag súil"
 
-#: remote-curl.c
 #, c-format
 msgid "invalid server response; got '%s'"
 msgstr "freagra freastalaí neamhbhailí; fuair '%s'"
 
-#: remote-curl.c
 #, c-format
 msgid "repository '%s' not found"
 msgstr "níor aimsíodh stór '%s'"
 
-#: remote-curl.c
 #, c-format
 msgid "Authentication failed for '%s'"
 msgstr "Theip ar fhíordheimhniú do '%s'"
 
-#: remote-curl.c
 #, c-format
 msgid "unable to access '%s' with http.pinnedPubkey configuration: %s"
 msgstr "ní féidir rochtain a fháil ar '%s' le cumraíocht http.pinnedPubkey: %s"
 
-#: remote-curl.c
 #, c-format
 msgid "unable to access '%s': %s"
 msgstr "ní féidir teacht ar '%s': %s"
 
-#: remote-curl.c
 #, c-format
 msgid "redirecting to %s"
 msgstr "atreorú chuig %s"
 
-#: remote-curl.c
 msgid "shouldn't have EOF when not gentle on EOF"
 msgstr "níor chóir go mbeadh EOF ann nuair nach bhfuil sé miline ar EOF"
 
-#: remote-curl.c
 msgid "remote server sent unexpected response end packet"
 msgstr "sheol freastalaí iargúlta paicéad deiridh"
 
-#: remote-curl.c
 msgid "unable to rewind rpc post data - try increasing http.postBuffer"
 msgstr ""
-"nach féidir sonraí post rpc a athfhillt - déan iarracht http.postBuffer a "
+"ní féidir sonraí poist rpc a athchasadh - déan iarracht http.postBuffer a "
 "mhéadú"
 
-#: remote-curl.c
 #, c-format
 msgid "remote-curl: bad line length character: %.4s"
 msgstr "iargúlta: carachtar fad droch-líne: %.4s"
 
-#: remote-curl.c
 msgid "remote-curl: unexpected response end packet"
 msgstr "iargúlta: paicéad deiridh freagartha gan choinne"
 
-#: remote-curl.c
 #, c-format
 msgid "RPC failed; %s"
 msgstr "Theip ar RPC; %s"
 
-#: remote-curl.c
-msgid "cannot handle pushes this big"
-msgstr "ní féidir brú mór seo a láimhseáil"
-
-#: remote-curl.c
 #, c-format
 msgid "cannot deflate request; zlib deflate error %d"
 msgstr "ní féidir iarratas a dhíscaoileadh; earráid dífhabhtaithe zlib %d"
 
-#: remote-curl.c
 #, c-format
 msgid "cannot deflate request; zlib end error %d"
 msgstr "ní féidir iarratas a dhíscaoileadh; earráid deiridh zlib %d"
 
-#: remote-curl.c
 #, c-format
 msgid "%d bytes of length header were received"
 msgstr "Fuarthas %d bytes de cheanntásc fad"
 
-#: remote-curl.c
 #, c-format
 msgid "%d bytes of body are still expected"
 msgstr "Táthar ag súil fós ag súil le %d bytes den chorp"
 
-#: remote-curl.c
 msgid "dumb http transport does not support shallow capabilities"
 msgstr "ní thacaíonn iompar HTTP dumb le cumais éadomhain"
 
-#: remote-curl.c
 msgid "fetch failed."
 msgstr "theip ar fáil."
 
-#: remote-curl.c
 msgid "cannot fetch by sha1 over smart http"
 msgstr "ní féidir le sha1 a fháil thar http cliste"
 
-#: remote-curl.c
 #, c-format
 msgid "protocol error: expected sha/ref, got '%s'"
 msgstr "earráid prótacal: súil le sha/ref, fuair '%s'"
 
-#: remote-curl.c
 #, c-format
 msgid "http transport does not support %s"
 msgstr "ní thacaíonn iompar http le %s"
 
-#: remote-curl.c
 msgid "protocol error: expected '<url> <path>', missing space"
 msgstr "earráid prótacal: súil leis '<url><path>', spás in easnamh"
 
-#: remote-curl.c
 #, c-format
 msgid "failed to download file at URL '%s'"
 msgstr "theip ar an comhad a íoslódáil ag URL '%s'"
 
-#: remote-curl.c
 msgid "git-http-push failed"
 msgstr "theip ar git-http-push"
 
-#: remote-curl.c
 msgid "remote-curl: usage: git remote-curl <remote> [<url>]"
 msgstr "<remote><url>remote-curl: úsáid: git remote-curl []"
 
-#: remote-curl.c
 msgid "remote-curl: error reading command stream from git"
 msgstr "remote-curl: earráid ag léamh sruth ordaithe ó git"
 
-#: remote-curl.c
 msgid "remote-curl: fetch attempted without a local repo"
 msgstr "remote-curl: iarracht a fháil gan repo áitiúil"
 
-#: remote-curl.c
 #, c-format
 msgid "remote-curl: unknown command '%s' from git"
 msgstr "remote-curl: ordú anaithnid '%s' ó git"
 
-#: remote.c
 #, c-format
 msgid ""
 "reading remote from \"%s/%s\", which is nominated for removal.\n"
@@ -25286,57 +21245,46 @@
 "Mura féidir leat, cuir in iúl dúinn le do thoil cén fáth a gcaithfidh tú\n"
 "é a úsáid fós trí ríomhphost a sheoladh chuig <git@vger.kernel.org>."
 
-#: remote.c
 #, c-format
 msgid "config remote shorthand cannot begin with '/': %s"
 msgstr "ní féidir le '/' tosú le gearrthánach iargúlta config: %s"
 
-#: remote.c
 msgid "more than one receivepack given, using the first"
 msgstr ""
 "níos mó ná pacáiste glacadóra amháin a thugtar, ag baint úsáide as an gcéad"
 
-#: remote.c
 msgid "more than one uploadpack given, using the first"
 msgstr ""
 "níos mó ná pacáiste uaslódála amháin tugtha, ag baint úsáide as an gcéad"
 
-#: remote.c
 #, c-format
 msgid "unrecognized followRemoteHEAD value '%s' ignored"
 msgstr "neamhaird a dhéanamh ar luach FollowRemoteHead '%s' gan aithint"
 
-#: remote.c
 #, c-format
 msgid "unrecognized value transfer.credentialsInUrl: '%s'"
 msgstr "aistriú luacha transfer.credentialsInUrl: '%s'"
 
-#: remote.c
 #, c-format
 msgid "URL '%s' uses plaintext credentials"
 msgstr "Úsáideann URL '%s' dhintiúir téacs simplí"
 
-#: remote.c
 #, c-format
 msgid "Cannot fetch both %s and %s to %s"
 msgstr "Ní féidir %s agus %s a fháil chuig %s"
 
-#: remote.c
 #, c-format
 msgid "%s usually tracks %s, not %s"
 msgstr "Is gnách go rianann %s %s, ní %s"
 
-#: remote.c
 #, c-format
 msgid "%s tracks both %s and %s"
 msgstr "Rianann %s %s agus %s araon"
 
-#: remote.c
 #, c-format
 msgid "src refspec %s does not match any"
 msgstr "src refspec %s ní mheaitseálann aon"
 
-#: remote.c
 #, c-format
 msgid "src refspec %s matches more than one"
 msgstr "meaitseálann src refspec %s níos mó ná ceann amháin"
@@ -25345,7 +21293,6 @@
 #. <remote> <src>:<dst>" push, and "being pushed ('%s')" is
 #. the <src>.
 #.
-#: remote.c
 #, c-format
 msgid ""
 "The destination you provided is not a full refname (i.e.,\n"
@@ -25370,7 +21317,6 @@
 "Níor oibrigh ceachtar acu, mar sin thugamar suas. Caithfidh tú an tagairt a "
 "cháiliú go hiomlán."
 
-#: remote.c
 #, c-format
 msgid ""
 "The <src> part of the refspec is a commit object.\n"
@@ -25381,7 +21327,6 @@
 "An raibh i gceist agat brainse nua a chruthú trí bhrú chuig\n"
 "'%s:refs/heads/%s'?"
 
-#: remote.c
 #, c-format
 msgid ""
 "The <src> part of the refspec is a tag object.\n"
@@ -25392,7 +21337,6 @@
 "An raibh i gceist agat clib nua a chruthú trí bhrú chuig\n"
 "'%s:refs/tags/%s'?"
 
-#: remote.c
 #, c-format
 msgid ""
 "The <src> part of the refspec is a tree object.\n"
@@ -25403,7 +21347,6 @@
 "An raibh sé i gceist agat crann nua a chlibeáil trí bhrú chuig\n"
 "'%s:refs/tags/%s'?"
 
-#: remote.c
 #, c-format
 msgid ""
 "The <src> part of the refspec is a blob object.\n"
@@ -25414,105 +21357,90 @@
 "An raibh sé i gceist agat blob nua a chlibeáil trí bhrú chuig\n"
 "'%s:refs/tags/%s'?"
 
-#: remote.c
+#, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr ""
+"Is aitheantóir réada nach bhfuil ann an chuid <src> den refspec ('%s').\n"
+
 #, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "Ní féidir %s a réiteach chuig an mbrainse"
 
-#: remote.c
 #, c-format
 msgid "unable to delete '%s': remote ref does not exist"
 msgstr "ní féidir '%s' a scriosadh: níl tagairt iargúlta ann"
 
-#: remote.c
 #, c-format
 msgid "dst refspec %s matches more than one"
 msgstr "meaitseálann dst refspec %s níos mó ná ceann amháin"
 
-#: remote.c
 #, c-format
 msgid "dst ref %s receives from more than one src"
 msgstr "faigheann dst ref %s ó níos mó ná src amháin"
 
-#: remote.c
 msgid "HEAD does not point to a branch"
 msgstr "Ní chuireann HEAD in iúl do bhrainse"
 
-#: remote.c
 #, c-format
 msgid "no such branch: '%s'"
 msgstr "aon bhrainse den sórt sin: '%s'"
 
-#: remote.c
 #, c-format
 msgid "no upstream configured for branch '%s'"
 msgstr "níl aon chumrú suas srutha le haghaidh brainse '%s'"
 
-#: remote.c
 #, c-format
 msgid "upstream branch '%s' not stored as a remote-tracking branch"
 msgstr "brainse suas srutha '%s' nach stóráiltear mar bhrainse cianrianaithe"
 
-#: remote.c
 #, c-format
 msgid "push destination '%s' on remote '%s' has no local tracking branch"
 msgstr ""
 "níl aon bhrainse rianaithe áitiúil ag ceann scríbe brúite '%s' ar iargúlta "
 "'%s'"
 
-#: remote.c
 #, c-format
 msgid "branch '%s' has no remote for pushing"
 msgstr "níl aon iargúlta ag brainse '%s' chun brú"
 
-#: remote.c
 #, c-format
 msgid "push refspecs for '%s' do not include '%s'"
 msgstr "ní chuimsíonn '%s' brú refspections do '%s'"
 
-#: remote.c
 msgid "push has no destination (push.default is 'nothing')"
 msgstr "níl aon cheann scríbe ag brú (is é 'rud ar bith' push.default)"
 
-#: remote.c
 msgid "cannot resolve 'simple' push to a single destination"
 msgstr "ní féidir brú 'simplí' a réiteach chuig ceann scríbe amháin"
 
-#: remote.c
 #, c-format
 msgid "couldn't find remote ref %s"
 msgstr "ní raibh in ann tagairt iargúlta %s a fháil"
 
-#: remote.c
 #, c-format
 msgid "* Ignoring funny ref '%s' locally"
 msgstr "* Ag neamhaird den tagairt ghreannmhar '%s' go háitiúil"
 
-#: remote.c
 #, c-format
 msgid "Your branch is based on '%s', but the upstream is gone.\n"
 msgstr "Tá do bhrainse bunaithe ar '%s', ach tá an suas sruth imithe.\n"
 
-#: remote.c
 msgid "  (use \"git branch --unset-upstream\" to fixup)\n"
 msgstr " (bain úsáid as \"git branch --unset-upstream\" chun é a dheisiú)\n"
 
-#: remote.c
 #, c-format
 msgid "Your branch is up to date with '%s'.\n"
 msgstr "Tá do bhrainse cothrom le dáta le '%s'.\n"
 
-#: remote.c
 #, c-format
 msgid "Your branch and '%s' refer to different commits.\n"
 msgstr "Tagraíonn do bhrainse agus '%s' do thiomnuithe difriúla.\n"
 
-#: remote.c
 #, c-format
 msgid "  (use \"%s\" for details)\n"
 msgstr " (bain úsáid as \"%s\" le haghaidh sonraí)\n"
 
-#: remote.c
 #, 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"
@@ -25520,11 +21448,9 @@
 msgstr[1] "Tá do bhrainse chun tosaigh ar '%s' le tiomantais %d.\n"
 msgstr[2] "Tá do bhrainse chun tosaigh ar '%s' le tiomantais %d.\n"
 
-#: remote.c
 msgid "  (use \"git push\" to publish your local commits)\n"
 msgstr " (bain úsáid as “git push” chun do thiomanta áitiúla a fhoilsiú)\n"
 
-#: remote.c
 #, c-format
 msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
 msgid_plural ""
@@ -25539,11 +21465,9 @@
 "Tá do bhrainse taobh thiar de '%s' faoi %d tiomnuithe, agus is féidir é a "
 "luasghéarú ar aghaidh.\n"
 
-#: remote.c
 msgid "  (use \"git pull\" to update your local branch)\n"
 msgstr " (bain úsáid as “git pull” chun do bhrainse áitiúil a nuashonrú)\n"
 
-#: remote.c
 #, c-format
 msgid ""
 "Your branch and '%s' have diverged,\n"
@@ -25561,148 +21485,172 @@
 "Tá do bhrainse agus '%s' scartha óna chéile,\n"
 "agus tá %d agus %d tiomnuithe difriúla acu faoi seach.\n"
 
-#: remote.c
 msgid ""
 "  (use \"git pull\" if you want to integrate the remote branch with yours)\n"
 msgstr ""
 " (bain úsáid as “git pull” más mian leat an brainse iargúlta a chomhtháthú "
 "le leatsa)\n"
 
-#: remote.c
 #, c-format
 msgid "cannot parse expected object name '%s'"
 msgstr "ní féidir ainm réad a bhfuil súil leis '%s' a pharsáil"
 
-#: remote.c
 #, c-format
 msgid "cannot strip one component off url '%s'"
 msgstr "ní féidir comhpháirt amháin a bhaint as url '%s'"
 
-#: replace-object.c
+#, c-format
+msgid "cannot open index for %s"
+msgstr "ní féidir innéacs a oscailt do %s"
+
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr "pacáiste %s ró-mhór le breithniú i ddul chun cinn geo"
+
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "pacáiste %s ró-mhór le rolladh suas"
+
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "ní fhéadfaí teachtaireacht %s a oscailt le haghaidh scríobh"
+
+msgid "could not close refs snapshot tempfile"
+msgstr "ní raibh in ann tempfile snapshot refs a dhúnadh"
+
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "ní fhéadfaí bitmap seasta a bhaint: %s"
+
+msgid "could not start pack-objects to repack promisor objects"
+msgstr "ní fhéadfaí rudaí pacáiste a thosú chun rudaí gealltanna a athphacáil"
+
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "theip ar rudaí gealltanna a bheathú ar rudaí pacáiste"
+
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr ""
+"athphacáil: Ag súil le línte aitheantais réad heicseach iomlána ach ó "
+"phacáistí."
+
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr ""
+"ní fhéadfadh sé rudaí pacáiste a chríochnú chun rudaí geallta a athphacáil"
+
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "ní thosaíonn réimír pacáiste %s le objdir %s"
+
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr "theip ar phacáiste a athainmniú go '%s'"
+
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "níor scríobh pack-objects comhad '%s' do phacáiste %s-%s"
+
+#, c-format
+msgid "could not unlink: %s"
+msgstr "ní fhéadfaí dícheangal: %s"
+
 #, c-format
 msgid "bad replace ref name: %s"
 msgstr "droch-ainm tagartha athsholáthair: %s"
 
-#: replace-object.c
 #, c-format
 msgid "duplicate replace ref: %s"
 msgstr "athsholáthar dúblach tagairt: %s"
 
-#: replace-object.c
 #, c-format
 msgid "replace depth too high for object %s"
 msgstr "doimhneacht ró-ard a chur in ionad do réad %s"
 
-#: rerere.c
 msgid "corrupt MERGE_RR"
 msgstr "truaillithe MERGE_RR"
 
-#: rerere.c
 msgid "unable to write rerere record"
-msgstr "in ann taifead a scríobh arís"
+msgstr "ní féidir taifead rerere a scríobh"
 
-#: rerere.c
 #, c-format
 msgid "there were errors while writing '%s' (%s)"
 msgstr "bhí earráidí ann agus tú ag scríobh '%s' (%s)"
 
-#: rerere.c
 #, c-format
 msgid "could not parse conflict hunks in '%s'"
 msgstr "ní fhéadfaí coimhlint a pharsáil i '%s'"
 
-#: rerere.c
 #, c-format
 msgid "failed utime() on '%s'"
 msgstr "theip ar utime () ar '%s'"
 
-#: rerere.c
 #, c-format
 msgid "writing '%s' failed"
 msgstr "theip ar scríobh '%s'"
 
-#: rerere.c
 #, c-format
 msgid "Staged '%s' using previous resolution."
 msgstr "'%s 'céim ag baint úsáide as réiteach roimhe seo."
 
-#: rerere.c
 #, c-format
 msgid "Recorded resolution for '%s'."
 msgstr "Réiteach taifeadta le haghaidh '%s'."
 
-#: rerere.c
 #, c-format
 msgid "Resolved '%s' using previous resolution."
 msgstr "Réitigh '%s' ag úsáid réiteach roimhe seo."
 
-#: rerere.c
 #, c-format
 msgid "cannot unlink stray '%s'"
 msgstr "ní féidir le '%s' a dhínascadh"
 
-#: rerere.c
 #, c-format
 msgid "Recorded preimage for '%s'"
 msgstr "Réamhíomhá taifeadta do '%s'"
 
-#: rerere.c
 #, c-format
 msgid "failed to update conflicted state in '%s'"
 msgstr "theip ar an stát coinbhleachta a nuashonrú i '%s'"
 
-#: rerere.c
 #, c-format
 msgid "no remembered resolution for '%s'"
 msgstr "níl aon réiteach cuimhne ar '%s'"
 
-#: rerere.c
 #, c-format
 msgid "Updated preimage for '%s'"
 msgstr "Réamhíomhá nuashonraithe do '%s'"
 
-#: rerere.c
 #, c-format
 msgid "Forgot resolution for '%s'\n"
 msgstr "Déan dearmad dearmad ar réiteach '%s'\n"
 
-#: rerere.c
 msgid "unable to open rr-cache directory"
-msgstr "in ann eolaire rr-cache a oscailt"
+msgstr "ní féidir an t-eolaire rr-cache a oscailt"
 
-#: rerere.h
 msgid "update the index with reused conflict resolution if possible"
 msgstr "an t-innéacs a nuashonrú le réiteach coinbhleachta a athúsáidtear"
 
-#: reset.c
 msgid "could not determine HEAD revision"
 msgstr "ní raibh sé in ann athbhreithniú HEAD"
 
-#: reset.c sequencer.c
 #, c-format
 msgid "failed to find tree of %s"
 msgstr "theip ar chrann %s a aimsiú"
 
-#: revision.c
 #, c-format
 msgid "unsupported section for hidden refs: %s"
 msgstr "rannán gan tacaíocht do thaifeanna i bhfolach: %s"
 
-#: revision.c
 msgid "--exclude-hidden= passed more than once"
 msgstr "--exclude-hidden= rith níos mó ná uair amháin"
 
-#: revision.c
 #, c-format
 msgid "resolve-undo records `%s` which is missing"
 msgstr "taifid réitigh a chealú `%s` atá ar iarraidh"
 
-#: revision.c
 #, c-format
 msgid "%s exists but is a symbolic ref"
 msgstr "Tá %s ann ach is tagairt siombalach é"
 
-#: revision.c
 msgid ""
 "--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
 "REVERT_HEAD or REBASE_HEAD"
@@ -25710,144 +21658,111 @@
 "Teastaíonn --merge ceann de na pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
 "REVERT_HEAD nó REBASE_HEAD"
 
-#: revision.c
 #, c-format
 msgid "could not get commit for --ancestry-path argument %s"
 msgstr "ní fhéadfaí tiomantas a fháil le haghaidh argóint --ancestry-path %s"
 
-#: revision.c
 msgid "--unpacked=<packfile> no longer supported"
 msgstr "--unpacked=<packfile> ní thacaítear leis a thuilleadh"
 
-#: revision.c
 #, c-format
 msgid "invalid option '%s' in --stdin mode"
-msgstr "rogha neamhbhailí '%s' i mód --stdin"
+msgstr "rogha neamhbhailí '%s' in --stdin mode"
 
-#: revision.c
 msgid "your current branch appears to be broken"
 msgstr "is cosúil go bhfuil do bhrainse reatha briste"
 
-#: revision.c
 #, c-format
 msgid "your current branch '%s' does not have any commits yet"
 msgstr "níl aon gealltanais fós ag do bhrainse reatha '%s'"
 
-#: revision.c
 msgid "object filtering requires --objects"
 msgstr "teastaíonn scagadh réad --objects"
 
-#: revision.c
 msgid "-L does not yet support diff formats besides -p and -s"
 msgstr "Ní thacaíonn -L le formáidí diff fós seachas -p agus -s"
 
-#: run-command.c
 #, c-format
 msgid "cannot create async thread: %s"
 msgstr "ní féidir snáithe async a chruthú: %s"
 
-#: scalar.c worktree.c
 #, c-format
 msgid "'%s' does not exist"
 msgstr "Níl '%s' ann"
 
-#: scalar.c
 #, c-format
 msgid "could not switch to '%s'"
 msgstr "ní fhéadfaí aistriú go '%s'"
 
-#: scalar.c
 msgid "need a working directory"
 msgstr "teastaíonn eolaire oibre"
 
-#: scalar.c
 msgid "Scalar enlistments require a worktree"
 msgstr "Teastaíonn crann oibre ó liostú scalar"
 
-#: scalar.c
 #, c-format
 msgid "could not configure %s=%s"
 msgstr "ní fhéadfaí %s=%s a chumrú"
 
-#: scalar.c
 msgid "could not configure log.excludeDecoration"
 msgstr "ní fhéadfaí log.excludeDecoration a chumrú"
 
-#: scalar.c
 msgid "could not add enlistment"
 msgstr "ní fhéadfaí liostú a chur leis"
 
-#: scalar.c
 msgid "could not set recommended config"
 msgstr "ní fhéadfaí cumraíocht mholta a shocrú"
 
-#: scalar.c
 msgid "could not toggle maintenance"
 msgstr "níorbh fhéidir cothabháil a athrú"
 
-#: scalar.c
 msgid "could not start the FSMonitor daemon"
 msgstr "ní fhéadfaí an daemon FSMonitor a thosú"
 
-#: scalar.c
 msgid "could not turn off maintenance"
 msgstr "ní fhéadfadh cothabháil a mhúchadh"
 
-#: scalar.c
 msgid "could not remove enlistment"
 msgstr "ní fhéadfaí liostú a bhaint"
 
-#: scalar.c
 #, c-format
 msgid "remote HEAD is not a branch: '%.*s'"
 msgstr "ní brainse é iargúlta HEAD: '%.*s"
 
-#: scalar.c
 msgid "failed to get default branch name from remote; using local default"
 msgstr ""
 "theip ar ainm brainse réamhshocraithe a fháil ó iargúlta; ag baint úsáide as"
 
-#: scalar.c
 msgid "failed to get default branch name"
 msgstr "theip ort ainm brainse réamhshocraithe a fháil"
 
-#: scalar.c
 msgid "failed to unregister repository"
 msgstr "theip ar stór a dhíchlárú"
 
-#: scalar.c
 msgid "failed to stop the FSMonitor daemon"
 msgstr "theip ar an daemon FSMonitor a stopadh"
 
-#: scalar.c
 msgid "failed to delete enlistment directory"
 msgstr "theip ar eolaire liostála a scriosadh"
 
-#: scalar.c
 msgid "branch to checkout after clone"
 msgstr "brainse chun an tseiceáil tar éis clóin"
 
-#: scalar.c
 msgid "when cloning, create full working directory"
 msgstr "agus tú ag clónú, cruthaigh eolaire oibre iomlán"
 
-#: scalar.c
 msgid "only download metadata for the branch that will be checked out"
 msgstr "meiteashonraí a íoslódáil ach don bhrainse a sheiceálfar"
 
-#: scalar.c
 msgid "create repository within 'src' directory"
 msgstr "cruthaigh stór laistigh de eolaire 'src'"
 
-#: scalar.c
 msgid "specify if tags should be fetched during clone"
 msgstr "sonraigh an gcaithfear clibeanna a fháil le linn clóin"
 
-#: scalar.c
 msgid "specify if background maintenance should be enabled"
 msgstr "sonraigh an bhfuil cothabháil chúlra le cumasú"
 
-#: scalar.c
 msgid ""
 "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n"
 "\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]"
@@ -25855,69 +21770,54 @@
 "clón scálach [--single-branch] [--branch <príomhbhrainse>] [--full-clone]\n"
 "[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<liostáil>]"
 
-#: scalar.c
 #, c-format
 msgid "cannot deduce worktree name from '%s'"
 msgstr "ní féidir ainm crann oibre a bhaint as '%s'"
 
-#: scalar.c
 #, c-format
 msgid "directory '%s' exists already"
 msgstr "tá eolaire '%s' ann cheana féin"
 
-#: scalar.c
 #, c-format
 msgid "failed to get default branch for '%s'"
 msgstr "theip ar bhrainse réamhshocraithe a fháil do '%s'"
 
-#: scalar.c
 #, c-format
 msgid "could not configure remote in '%s'"
 msgstr "ní fhéadfaí iargúlta a chumrú i '%s'"
 
-#: scalar.c
 #, c-format
 msgid "could not disable tags in '%s'"
 msgstr "ní fhéadfaí clibeanna a dhíchumasú i '%s'"
 
-#: scalar.c
 #, c-format
 msgid "could not configure '%s'"
 msgstr "ní fhéadfaí '%s' a chumrú"
 
-#: scalar.c
 msgid "partial clone failed; attempting full clone"
 msgstr "theip ar chlón páirteach; iarracht clón iomlán"
 
-#: scalar.c
 msgid "could not configure for full clone"
 msgstr "ní fhéadfaí a chumrú le haghaidh clón iomlán"
 
-#: scalar.c
 msgid "scalar diagnose [<enlistment>]"
 msgstr "<enlistment>diagnóis scalar []"
 
-#: scalar.c
 msgid "`scalar list` does not take arguments"
 msgstr "Ní ghlacann `liosta scalar` argóintí"
 
-#: scalar.c
 msgid "scalar register [--[no-]maintenance] [<enlistment>]"
 msgstr "clár scálach [--[gan-]chothabháil] [<liostáil>]"
 
-#: scalar.c
 msgid "reconfigure all registered enlistments"
 msgstr "gach liostáil cláraithe a athchumrú"
 
-#: scalar.c
 msgid "(enable|disable|keep)"
 msgstr "(cumasaigh|díchumasaigh|coinnigh)"
 
-#: scalar.c
 msgid "signal how to adjust background maintenance"
 msgstr "comhartha a thabhairt maidir le conas cothabháil chúlra a choigeartú"
 
-#: scalar.c
 msgid ""
 "scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | "
 "<enlistment>]"
@@ -25925,41 +21825,33 @@
 "scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | "
 "<enlistment>]"
 
-#: scalar.c
 msgid "--all or <enlistment>, but not both"
 msgstr "--all nó <enlistment>, ach ní an dá cheann"
 
-#: scalar.c
 #, c-format
 msgid "unknown mode for --maintenance option: %s"
 msgstr "mód anaithnid don rogha --maintenance: %s"
 
-#: scalar.c
 #, c-format
 msgid "could not remove stale scalar.repo '%s'"
 msgstr "ní fhéadfaí scalar.repo '%s' a bhaint as scalar.repo"
 
-#: scalar.c
 #, c-format
 msgid "removed stale scalar.repo '%s'"
 msgstr "bainte scale scalar.repo '%s'"
 
-#: scalar.c
 #, c-format
 msgid "repository at '%s' has different owner"
 msgstr "tá úinéir difriúil ag an stórlann ag '%s'"
 
-#: scalar.c
 #, c-format
 msgid "repository at '%s' has a format issue"
 msgstr "tá ceist formáide ag stór ag '%s'"
 
-#: scalar.c
 #, c-format
 msgid "repository not found in '%s'"
 msgstr "ní bhfuarthas stór i '%s'"
 
-#: scalar.c
 #, c-format
 msgid ""
 "to unregister this repository from Scalar, run\n"
@@ -25968,7 +21860,6 @@
 "chun an stór seo a dhíchlárú ó Scalar, reáchtáil\n"
 " git config --global --unset --fixed-value scalar.repo “%s”"
 
-#: scalar.c
 msgid ""
 "scalar run <task> [<enlistment>]\n"
 "Tasks:\n"
@@ -25976,49 +21867,38 @@
 "rith scalar <tasc> [<liostáil>]\n"
 "Tascanna:\n"
 
-#: scalar.c
 #, c-format
 msgid "no such task: '%s'"
 msgstr "gan aon tasc den sórt sin: '%s'"
 
-#: scalar.c
 msgid "scalar unregister [<enlistment>]"
 msgstr "<enlistment>scálar díchlárú []"
 
-#: scalar.c
 msgid "scalar delete <enlistment>"
 msgstr "scriosadh scalar <enlistment>"
 
-#: scalar.c
 msgid "refusing to delete current working directory"
 msgstr "diúltú eolaire oibre reatha a scriosadh"
 
-#: scalar.c
 msgid "include Git version"
 msgstr "leagan Git san áireamh"
 
-#: scalar.c
 msgid "include Git's build options"
 msgstr "áireamh roghanna tógála Git"
 
-#: scalar.c
 msgid "scalar verbose [-v | --verbose] [--build-options]"
 msgstr "scalar verbose [-v | --verbose] [--build-options]"
 
-#: scalar.c
 msgid "-C requires a <directory>"
 msgstr "Éilíonn -C a <directory>"
 
-#: scalar.c
 #, c-format
 msgid "could not change to '%s'"
 msgstr "ní fhéadfaí athrú go '%s'"
 
-#: scalar.c
 msgid "-c requires a <key>=<value> argument"
 msgstr "<value>Éilíonn -c a <key>= argóint"
 
-#: scalar.c
 msgid ""
 "scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n"
 "\n"
@@ -26028,41 +21908,32 @@
 "\n"
 "Orduithe:\n"
 
-#: send-pack.c
 msgid "unexpected flush packet while reading remote unpack status"
 msgstr "paicéad srutháin gan choinne agus stádas díphacála iargúlta"
 
-#: send-pack.c
 #, c-format
 msgid "unable to parse remote unpack status: %s"
-msgstr "nach féidir stádas iargúlta díphacáil a pháirseáil: %s"
+msgstr "ní féidir stádas díphacála iargúlta a pharsáil: %s"
 
-#: send-pack.c
 #, c-format
 msgid "remote unpack failed: %s"
 msgstr "theip ar dhíphacáil iargúlta: %s"
 
-#: send-pack.c
 msgid "failed to sign the push certificate"
 msgstr "theip ar an deimhniú brú a shíniú"
 
-#: send-pack.c
 msgid "send-pack: unable to fork off fetch subprocess"
 msgstr "pacáiste seolta: ní féidir leis an bhfophróiseas faighte a fhorc"
 
-#: send-pack.c
 msgid "push negotiation failed; proceeding anyway with push"
 msgstr "theip ar chaibidlíocht brú; dul ar aghaidh ar aon nós"
 
-#: send-pack.c
 msgid "the receiving end does not support this repository's hash algorithm"
 msgstr "ní thacaíonn an deireadh glacadh le halgartam hash an stór seo"
 
-#: send-pack.c
 msgid "the receiving end does not support --signed push"
 msgstr "ní thacaíonn an deireadh glacadh le brú --signed"
 
-#: send-pack.c
 msgid ""
 "not sending a push certificate since the receiving end does not support --"
 "signed push"
@@ -26070,42 +21941,33 @@
 "níl teastas brú á sheoladh ós rud é nach dtacaíonn an taobh glactha le --"
 "signed brúigh"
 
-#: send-pack.c
 msgid "the receiving end does not support --atomic push"
 msgstr "ní thacaíonn an deireadh glacadh le brú --atomic"
 
-#: send-pack.c
 msgid "the receiving end does not support push options"
 msgstr "ní thacaíonn an deireadh glacadh le roghanna brú"
 
-#: sequencer.c
 #, c-format
 msgid "invalid commit message cleanup mode '%s'"
 msgstr "modh glantacháin teachtaireachta tiomanta neamhbhailí '%s'"
 
-#: sequencer.c
 #, c-format
 msgid "could not delete '%s'"
 msgstr "ní fhéadfaí '%s' a scriosadh"
 
-#: sequencer.c
 msgid "revert"
 msgstr "filleadh"
 
-#: sequencer.c
 msgid "cherry-pick"
 msgstr "pioc silíní"
 
-#: sequencer.c
 msgid "rebase"
 msgstr "athbhunú"
 
-#: sequencer.c
 #, c-format
 msgid "unknown action: %d"
 msgstr "gníomh anaithnid: %d"
 
-#: sequencer.c
 msgid ""
 "Resolve all conflicts manually, mark them as resolved with\n"
 "\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
@@ -26120,7 +21982,6 @@
 "Chun abordú agus dul ar ais go dtí an stát roimh “git rebase”, reáchtáil "
 "“git rebase --abort”."
 
-#: sequencer.c
 msgid ""
 "after resolving the conflicts, mark the corrected paths\n"
 "with 'git add <paths>' or 'git rm <paths>'"
@@ -26128,7 +21989,6 @@
 "tar éis na coinbhleachtaí a réiteach, marcáil na cosáin cearta\n"
 "<paths>le 'git add <paths>'nó 'git rm'"
 
-#: sequencer.c
 msgid ""
 "After resolving the conflicts, mark them with\n"
 "\"git add/rm <pathspec>\", then run\n"
@@ -26145,7 +22005,6 @@
 "Chun abordú agus dul ar ais go dtí an stát roimh “git cherry-pick”,\n"
 "reáchtáil “git cherry-pick --abort”."
 
-#: sequencer.c
 msgid ""
 "After resolving the conflicts, mark them with\n"
 "\"git add/rm <pathspec>\", then run\n"
@@ -26163,86 +22022,68 @@
 "revert”,\n"
 "reáchtáil “git revert --abort”."
 
-#: sequencer.c
 #, c-format
 msgid "could not lock '%s'"
 msgstr "ní fhéadfaí '%s' a ghlasáil"
 
-#: sequencer.c
 #, c-format
 msgid "could not write eol to '%s'"
 msgstr "ní fhéadfaí eol a scríobh chuig '%s'"
 
-#: sequencer.c
 #, c-format
 msgid "failed to finalize '%s'"
 msgstr "theip ar '%s' a chur i gcrích"
 
-#: sequencer.c
 #, c-format
 msgid "your local changes would be overwritten by %s."
 msgstr "d'athruithe áitiúla a fhorscríobhadh ag %s."
 
-#: sequencer.c
 msgid "commit your changes or stash them to proceed."
 msgstr "do chuid athruithe a dhéanamh nó iad a stóráil chun dul ar aghaidh."
 
 #. TRANSLATORS: %s will be "revert", "cherry-pick" or
 #. "rebase".
 #.
-#: sequencer.c
 #, c-format
 msgid "%s: Unable to write new index file"
 msgstr "%s: Ní féidir comhad innéacs nua a scríobh"
 
-#: sequencer.c
 msgid "unable to update cache tree"
-msgstr "in ann crann taisce a nuashonrú"
+msgstr "ní féidir crann taisce a nuashonrú"
 
-#: sequencer.c
 msgid "could not resolve HEAD commit"
 msgstr "ní fhéadfaí tiomantas HEAD a réiteach"
 
-#: sequencer.c
 #, c-format
 msgid "no key present in '%.*s'"
 msgstr "níl aon eochair i láthair i '%.*s"
 
-#: sequencer.c
 #, c-format
 msgid "unable to dequote value of '%s'"
-msgstr "nach féidir luach '%s' a dhíchur"
+msgstr "ní féidir luach '%s' a dhílua"
 
-#: sequencer.c
 msgid "'GIT_AUTHOR_NAME' already given"
 msgstr "'GIT_AUTHOR_NAME' tugtha cheana féin"
 
-#: sequencer.c
 msgid "'GIT_AUTHOR_EMAIL' already given"
 msgstr "'GIT_AUTHOR_EMAIL' tugtha cheana féin"
 
-#: sequencer.c
 msgid "'GIT_AUTHOR_DATE' already given"
 msgstr "'GIT_AUTHOR_DATE' tugtha cheana féin"
 
-#: sequencer.c
 #, c-format
 msgid "unknown variable '%s'"
 msgstr "athróg anaithnid '%s'"
 
-#: sequencer.c
 msgid "missing 'GIT_AUTHOR_NAME'"
 msgstr "ar iarraidh 'GIT_AUTHOR_NAME'"
 
-#: sequencer.c
 msgid "missing 'GIT_AUTHOR_EMAIL'"
 msgstr "ar iarraidh 'GIT_AUTHOR_EMAIL'"
 
-#: sequencer.c
 msgid "missing 'GIT_AUTHOR_DATE'"
 msgstr "ar iarraidh 'GIT_AUTHOR_DATE'"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "you have staged changes in your working tree\n"
@@ -26272,11 +22113,9 @@
 "\n"
 "  git rebase --continue\n"
 
-#: sequencer.c
 msgid "'prepare-commit-msg' hook failed"
 msgstr "Theip ar chroí 'prepar-chommit-msg'"
 
-#: sequencer.c
 msgid ""
 "Your name and email address were configured automatically based\n"
 "on your username and hostname. Please check that they are accurate.\n"
@@ -26306,7 +22145,6 @@
 "\n"
 "    git commit --amend --reset-author\n"
 
-#: sequencer.c
 msgid ""
 "Your name and email address were configured automatically based\n"
 "on your username and hostname. Please check that they are accurate.\n"
@@ -26332,184 +22170,145 @@
 "\n"
 "    git commit --amend --reset-author\n"
 
-#: sequencer.c
 msgid "couldn't look up newly created commit"
 msgstr "ní fhéadfadh sé gealltanas nua-chruthaithe a fheiceáil"
 
-#: sequencer.c
 msgid "could not parse newly created commit"
 msgstr "ní fhéadfadh sé gealltanas nua-chruthaithe a pháirsí"
 
-#: sequencer.c
 msgid "unable to resolve HEAD after creating commit"
-msgstr "in ann HEAD a réiteach tar éis tiomantas a chruthú"
+msgstr "ní féidir HEAD a réiteach tar éis tiomantas a chruthú"
 
-#: sequencer.c
 msgid "detached HEAD"
 msgstr "scoite CEANN"
 
-#: sequencer.c
 msgid " (root-commit)"
 msgstr " (fréamh-thiomantas)"
 
-#: sequencer.c
 msgid "could not parse HEAD"
 msgstr "ní fhéadfaí HEAD a pháirseáil"
 
-#: sequencer.c
 #, c-format
 msgid "HEAD %s is not a commit!"
 msgstr "Ní gealltanas é HEAD %s!"
 
-#: sequencer.c
 msgid "unable to parse commit author"
 msgstr "ní féidir leis an údar tiomanta a pharsáil"
 
-#: sequencer.c
 #, c-format
 msgid "unable to read commit message from '%s'"
-msgstr "nach féidir teachtaireacht tiomanta ó '%s' a léamh"
+msgstr "ní féidir teachtaireacht tiomnaithe ó '%s' a léamh"
 
-#: sequencer.c
 #, c-format
 msgid "invalid author identity '%s'"
 msgstr "aitheantas údair neamhbhailí '%s'"
 
-#: sequencer.c
 msgid "corrupt author: missing date information"
 msgstr "údar truaillithe: faisnéis dáta in easnamh"
 
-#: sequencer.c
 #, c-format
 msgid "could not update %s"
 msgstr "ní fhéadfaí %s a nuashonrú"
 
-#: sequencer.c
 #, c-format
 msgid "could not parse parent commit %s"
 msgstr "ní fhéadfaí tuismitheoir tiomantas %s a pharsáil"
 
-#: sequencer.c
 #, c-format
 msgid "unknown command: %d"
 msgstr "ordú anaithnid: %d"
 
-#: sequencer.c
 msgid "This is the 1st commit message:"
 msgstr "Seo an chéad teachtaireacht tiomanta:"
 
-#: sequencer.c
 #, c-format
 msgid "This is the commit message #%d:"
 msgstr "Seo an teachtaireacht tiomanta #%d:"
 
-#: sequencer.c
 msgid "The 1st commit message will be skipped:"
 msgstr "Scaipfear an chéad teachtaireacht tiomanta:"
 
-#: sequencer.c
 #, c-format
 msgid "The commit message #%d will be skipped:"
 msgstr "Scaipfear an teachtaireacht tiomanta #%d:"
 
-#: sequencer.c
 #, c-format
 msgid "This is a combination of %d commits."
 msgstr "Is meascán de ghealltanais %d é seo."
 
-#: sequencer.c
 #, c-format
 msgid "cannot write '%s'"
 msgstr "ní féidir '%s' a scríobh"
 
-#: sequencer.c
 msgid "need a HEAD to fixup"
 msgstr "teastaíonn CEAD ag teastáil chun socrú"
 
-#: sequencer.c
 msgid "could not read HEAD"
 msgstr "ní raibh in ann HEAD a léamh"
 
-#: sequencer.c
 msgid "could not read HEAD's commit message"
 msgstr "ní raibh sé in ann teachtaireacht tiomanta HEAD a léamh"
 
-#: sequencer.c
 #, c-format
 msgid "could not read commit message of %s"
 msgstr "ní raibh sé in ann teachtaireacht tiomanta %s a léamh"
 
-#: sequencer.c
 msgid "your index file is unmerged."
 msgstr "tá do chomhad innéacs neamh-chumasaithe."
 
-#: sequencer.c
 msgid "cannot fixup root commit"
 msgstr "ní féidir le déanamh fréimhe a shocrú"
 
-#: sequencer.c
 #, c-format
 msgid "commit %s is a merge but no -m option was given."
 msgstr "cumasc é tiomnú %s ach níor tugadh rogha -m."
 
-#: sequencer.c
 #, c-format
 msgid "commit %s does not have parent %d"
 msgstr "commiteáil %s níl tuismitheoir %d aige"
 
-#: sequencer.c
 #, c-format
 msgid "cannot get commit message for %s"
 msgstr "ní féidir teachtaireacht tiomanta a fháil do %s"
 
 #. TRANSLATORS: The first %s will be a "todo" command like
 #. "revert" or "pick", the second %s a SHA1.
-#: sequencer.c
 #, c-format
 msgid "%s: cannot parse parent commit %s"
 msgstr "%s: ní féidir le tuismitheoir tiomantas %s a pharsáil"
 
-#: sequencer.c
 #, c-format
 msgid "could not revert %s... %s"
 msgstr "ní raibh ann %s a chur ar ais... %s"
 
-#: sequencer.c
 #, c-format
 msgid "could not apply %s... %s"
 msgstr "ní fhéadfaí %s a chur i bhfeidhm... %s"
 
-#: sequencer.c
 #, c-format
 msgid "dropping %s %s -- patch contents already upstream\n"
 msgstr "scaoileadh %s %s -- ábhar paiste suas an sruth cheana féin\n"
 
-#: sequencer.c
 #, c-format
 msgid "git %s: failed to read the index"
 msgstr "git %s: theip ar an t-innéacs a léamh"
 
-#: sequencer.c
 #, c-format
 msgid "git %s: failed to refresh the index"
 msgstr "git %s: theip ar an t-innéacs a athnuachan"
 
-#: sequencer.c
 #, c-format
 msgid "'%s' is not a valid label"
 msgstr "Ní lipéad bailí é '%s'"
 
-#: sequencer.c
 #, c-format
 msgid "'%s' is not a valid refname"
 msgstr "Ní athainm bailí é '%s'"
 
-#: sequencer.c
 #, c-format
 msgid "update-ref requires a fully qualified refname e.g. refs/heads/%s"
 msgstr "teastaíonn athainm iomlán cáilithe uasghabháilte e.g. refs/heads/%s"
 
-#: sequencer.c
 #, c-format
 msgid "'%s' does not accept merge commits"
 msgstr "Ní ghlacann '%s' le gealltanais cumaisc"
@@ -26517,7 +22316,6 @@
 #. TRANSLATORS: 'pick' and 'merge -C' should not be
 #. translated.
 #.
-#: sequencer.c
 msgid ""
 "'pick' does not take a merge commit. If you wanted to\n"
 "replay the merge, use 'merge -C' on the commit."
@@ -26528,7 +22326,6 @@
 #. TRANSLATORS: 'reword' and 'merge -c' should not be
 #. translated.
 #.
-#: sequencer.c
 msgid ""
 "'reword' does not take a merge commit. If you wanted to\n"
 "replay the merge and reword the commit message, use\n"
@@ -26542,7 +22339,6 @@
 #. TRANSLATORS: 'edit', 'merge -C' and 'break' should
 #. not be translated.
 #.
-#: sequencer.c
 msgid ""
 "'edit' does not take a merge commit. If you wanted to\n"
 "replay the merge, use 'merge -C' on the commit, and then\n"
@@ -26555,148 +22351,115 @@
 "'brise' chun an rialú a thabhairt ar ais duit ionas gur féidir leat\n"
 "déan 'git commit --amend && git rebase --continue'."
 
-#: sequencer.c
 msgid "cannot squash merge commit into another commit"
 msgstr "ní féidir le squash tiomantas a chumasc i dtiomantas eile"
 
-#: sequencer.c
 #, c-format
 msgid "invalid command '%.*s'"
 msgstr "ordú neamhbhailí '%.*s"
 
-#: sequencer.c
 #, c-format
 msgid "missing arguments for %s"
 msgstr "argóintí atá in easnamh do %s"
 
-#: sequencer.c
 #, c-format
 msgid "could not parse '%s'"
 msgstr "ní fhéadfaí '%s' a pháirseáil"
 
-#: sequencer.c
 #, c-format
 msgid "invalid line %d: %.*s"
 msgstr "líne neamhbhailí %d: %.*s"
 
-#: sequencer.c
 #, c-format
 msgid "cannot '%s' without a previous commit"
 msgstr "ní féidir '%s' gan gealltanas roimhe seo"
 
-#: sequencer.c
 msgid "cancelling a cherry picking in progress"
 msgstr "piocadh silíní atá ar siúl a chur ar ceal"
 
-#: sequencer.c
 msgid "cancelling a revert in progress"
 msgstr "filleadh atá ar siúl a chealú"
 
-#: sequencer.c
 msgid "please fix this using 'git rebase --edit-todo'."
 msgstr ""
 "déan é seo a shocrú le do thoil ag baint úsáide as 'git rebase --edit-todo'."
 
-#: sequencer.c
 #, c-format
 msgid "unusable instruction sheet: '%s'"
 msgstr "bileog treoracha neamhúsáidte: '%s'"
 
-#: sequencer.c
 msgid "no commits parsed."
 msgstr "níl aon gealltanais paráilsithe."
 
-#: sequencer.c
 msgid "cannot cherry-pick during a revert."
 msgstr "ní féidir le silíní a phiocadh le linn filleadh."
 
-#: sequencer.c
 msgid "cannot revert during a cherry-pick."
 msgstr "ní féidir filleadh ar ais le linn pioc silíní."
 
-#: sequencer.c
 msgid "unusable squash-onto"
 msgstr "squash-on neamhúsáidte"
 
-#: sequencer.c
 #, c-format
 msgid "malformed options sheet: '%s'"
 msgstr "bileog roghanna mífhoirmithe: '%s'"
 
-#: sequencer.c
 msgid "empty commit set passed"
 msgstr "rith tacar tiomanta folamh"
 
-#: sequencer.c
 msgid "revert is already in progress"
 msgstr "tá filleadh ar siúl cheana féin"
 
-#: sequencer.c
 #, c-format
 msgid "try \"git revert (--continue | %s--abort | --quit)\""
 msgstr "bain triail as “git revert (--continue | %s--abort | --quit)”"
 
-#: sequencer.c
 msgid "cherry-pick is already in progress"
 msgstr "tá pioc silíní ar siúl cheana féin"
 
-#: sequencer.c
 #, c-format
 msgid "try \"git cherry-pick (--continue | %s--abort | --quit)\""
 msgstr "bain triail as “git cherry-pick (--continue | %s--abort | --quit)”"
 
-#: sequencer.c
 #, c-format
 msgid "could not create sequencer directory '%s'"
 msgstr "ní fhéadfaí eolaire seicheamhach '%s' a chruthú"
 
-#: sequencer.c
 msgid "no cherry-pick or revert in progress"
 msgstr "níl aon phiocadh silíní nó filleadh ar siúl ar siúl"
 
-#: sequencer.c
 msgid "cannot resolve HEAD"
 msgstr "ní féidir le HEAD a réiteach"
 
-#: sequencer.c
 msgid "cannot abort from a branch yet to be born"
 msgstr "ní féidir éirí as brainse nach rugadh fós"
 
-#: sequencer.c
 #, c-format
 msgid "cannot read '%s': %s"
 msgstr "ní féidir '%s' a léamh: %s"
 
-#: sequencer.c
 msgid "unexpected end of file"
 msgstr "deireadh gan choinne an chomhaid"
 
-#: sequencer.c
 #, c-format
 msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
 msgstr "tá comhad HEAD réamh-phiocadh silíní stóráilte '%s' truaillithe"
 
-#: sequencer.c
 msgid "You seem to have moved HEAD. Not rewinding, check your HEAD!"
 msgstr "Is cosúil gur bhogadh tú CEANN. Gan athfhillte, seiceáil do CHEANN!"
 
-#: sequencer.c
 msgid "no revert in progress"
 msgstr "níl aon fhilleadh ar siúl"
 
-#: sequencer.c
 msgid "no cherry-pick in progress"
 msgstr "níl aon phiocadh silíní ar siúl"
 
-#: sequencer.c
 msgid "failed to skip the commit"
 msgstr "theip ar an gealltanas a scipeáil"
 
-#: sequencer.c
 msgid "there is nothing to skip"
 msgstr "níl aon rud le scipeáil"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "have you committed already?\n"
@@ -26705,15 +22468,12 @@
 "an ndearna tú tiomanta cheana féin?\n"
 "bain triail as “git %s --continue”"
 
-#: sequencer.c
 msgid "cannot read HEAD"
 msgstr "ní féidir le HEAD a léamh"
 
-#: sequencer.c
 msgid "could not write commit message file"
 msgstr "ní raibh sé in ann comhad teachtaireachta tiomanta a"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "You can amend the commit now, with\n"
@@ -26732,22 +22492,18 @@
 "\n"
 "  git rebase --continue\n"
 
-#: sequencer.c
 #, c-format
 msgid "Could not apply %s... %.*s"
 msgstr "Níorbh fhéidir iarratas a dhéanamh %s... %.*s"
 
-#: sequencer.c
 #, c-format
 msgid "Could not merge %.*s"
 msgstr "Níorbh fhéidir cumasc %.*s"
 
-#: sequencer.c
 #, c-format
 msgid "Executing: %s\n"
 msgstr "Forghníomhú: %s\n"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "execution failed: %s\n"
@@ -26761,11 +22517,9 @@
 "\n"
 "  git rebase --continue\n"
 
-#: sequencer.c
 msgid "and made changes to the index and/or the working tree.\n"
 msgstr "agus rinne siad athruithe ar an innéacs agus/nó ar an gcrann oibre.\n"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "execution succeeded: %s\n"
@@ -26782,57 +22536,45 @@
 "  git rebase --continue\n"
 "\n"
 
-#: sequencer.c
 #, c-format
 msgid "illegal label name: '%.*s'"
 msgstr "ainm lipéid neamhdhleathach: '%.*s'"
 
-#: sequencer.c
 #, c-format
 msgid "could not resolve '%s'"
 msgstr "ní fhéadfaí '%s' a réiteach"
 
-#: sequencer.c
 msgid "writing fake root commit"
 msgstr "tiomantas fréamh bréige a scríobh"
 
-#: sequencer.c
 msgid "writing squash-onto"
 msgstr "scríobh squash-on"
 
-#: sequencer.c
 msgid "cannot merge without a current revision"
 msgstr "ní féidir a chumasc gan athbhreithniú reatha"
 
-#: sequencer.c
 #, c-format
 msgid "unable to parse '%.*s'"
-msgstr "nach féidir le parsáil a dhéanamh '%.*s"
+msgstr "ní féidir '%.*s' a pharsáil"
 
-#: sequencer.c
 #, c-format
 msgid "nothing to merge: '%.*s'"
 msgstr "níl aon rud le cumasc: '%.*s'"
 
-#: sequencer.c
 msgid "octopus merge cannot be executed on top of a [new root]"
 msgstr "ní féidir cumaisc ochtair a fhorghníomhú ar bharr [fréamh nua]"
 
-#: sequencer.c
 #, c-format
 msgid "could not get commit message of '%s'"
 msgstr "ní fhéadfaí teachtaireacht tiomanta de '%s' a fháil"
 
-#: sequencer.c
 #, c-format
 msgid "could not even attempt to merge '%.*s'"
 msgstr "níorbh fhéidir fiú iarracht a dhéanamh '%.*s' a chumasc"
 
-#: sequencer.c
 msgid "merge: Unable to write new index file"
 msgstr "cumaisc: Ní féidir comhad innéacs nua a scríobh"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "another 'rebase' process appears to be running; '%s.lock' already exists"
@@ -26840,7 +22582,6 @@
 "is cosúil go bhfuil próiseas 'rebase' eile ag rith; tá '%s.lock' ann cheana "
 "féin"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "Updated the following refs with %s:\n"
@@ -26849,7 +22590,6 @@
 "Nuashonraíodh na hifríochtaí seo a leanas le %s:\n"
 "%s"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "Failed to update the following refs with %s:\n"
@@ -26858,40 +22598,32 @@
 "Theip ar na hiarratais seo a leanas a nuashonrú le %s:\n"
 "%s"
 
-#: sequencer.c
 msgid "Cannot autostash"
 msgstr "Ní féidir uathoibriú"
 
-#: sequencer.c
 #, c-format
 msgid "Unexpected stash response: '%s'"
 msgstr "Freagra stash gan choinne: '%s'"
 
-#: sequencer.c
 #, c-format
 msgid "Could not create directory for '%s'"
 msgstr "Ní fhéadfaí eolaire a chruthú do '%s'"
 
-#: sequencer.c
 #, c-format
 msgid "Created autostash: %s\n"
 msgstr "Autostash cruthaithe: %s\n"
 
-#: sequencer.c
 msgid "could not reset --hard"
 msgstr "ní fhéadfaí athshocrú --hard"
 
-#: sequencer.c
 #, c-format
 msgid "Applied autostash.\n"
 msgstr "Autostash feidhmithe.\n"
 
-#: sequencer.c
 #, c-format
 msgid "cannot store %s"
 msgstr "ní féidir %s a stóráil"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "%s\n"
@@ -26903,33 +22635,26 @@
 "Is féidir leat \"git stash pop\" nó \"git stash drop\" a rith ag am ar "
 "bith.\n"
 
-#: sequencer.c
 msgid "Applying autostash resulted in conflicts."
 msgstr "Bhí coinbhleachtaí mar thoradh ar autostash i bhfeidhm."
 
-#: sequencer.c
 msgid "Autostash exists; creating a new stash entry."
 msgstr "Tá Autostash ann; ag cruthú iontráil nua stash."
 
-#: sequencer.c
 msgid "autostash reference is a symref"
 msgstr "is é tagairt autostash ina symref"
 
-#: sequencer.c
 msgid "could not detach HEAD"
 msgstr "ní fhéadfadh CEAD a dhícheangal"
 
-#: sequencer.c
 #, c-format
 msgid "Stopped at HEAD\n"
 msgstr "Stopadh ag HEAD\n"
 
-#: sequencer.c
 #, c-format
 msgid "Stopped at %s\n"
 msgstr "Stop ag %s\n"
 
-#: sequencer.c
 #, c-format
 msgid ""
 "Could not execute the todo command\n"
@@ -26951,58 +22676,46 @@
 "    git rebase --edit-todo\n"
 "    git rebase --continue\n"
 
-#: sequencer.c
 #, c-format
 msgid "Stopped at %s...  %.*s\n"
 msgstr "Stopadh ag %s...  %.*s\n"
 
-#: sequencer.c
 #, c-format
 msgid "Rebasing (%d/%d)%s"
 msgstr "Ag athbhunú (%d/%d) %s"
 
-#: sequencer.c
 #, c-format
 msgid "unknown command %d"
 msgstr "ordú anaithnid %d"
 
-#: sequencer.c
 msgid "could not read orig-head"
 msgstr "ní raibh sé in ann ceann orig-head a léamh"
 
-#: sequencer.c
 msgid "could not read 'onto'"
 msgstr "ní fhéadfaí 'ar' léamh"
 
-#: sequencer.c
 #, c-format
 msgid "could not update HEAD to %s"
 msgstr "ní fhéadfaí HEAD a nuashonrú go %s"
 
-#: sequencer.c
 #, c-format
 msgid "Successfully rebased and updated %s.\n"
 msgstr "Athbhunaithe agus nuashonraithe %s go rathúil.\n"
 
-#: sequencer.c
 msgid "cannot rebase: You have unstaged changes."
 msgstr "ní féidir athbhunú: Tá athruithe gan stáitse agat."
 
-#: sequencer.c
 msgid "cannot amend non-existing commit"
 msgstr "ní féidir gealltanas nach bhfuil ann a leasú"
 
-#: sequencer.c
 #, c-format
 msgid "invalid file: '%s'"
 msgstr "comhad neamhbhailí: '%s'"
 
-#: sequencer.c
 #, c-format
 msgid "invalid contents: '%s'"
 msgstr "ábhar neamhbhailí: '%s'"
 
-#: sequencer.c
 msgid ""
 "\n"
 "You have uncommitted changes in your working tree. Please, commit them\n"
@@ -27013,74 +22726,58 @@
 "iad\n"
 "ar dtús agus ansin rith 'git rebase --continue' arís."
 
-#: sequencer.c
 #, c-format
 msgid "could not write file: '%s'"
 msgstr "ní fhéadfaí comhad a scríobh: '%s'"
 
-#: sequencer.c
 msgid "could not remove CHERRY_PICK_HEAD"
 msgstr "ní fhéadfaí CHERRY_PICK_HEAD a bhaint"
 
-#: sequencer.c
 msgid "could not commit staged changes."
 msgstr "ní fhéadfadh athruithe stáitse a dhéanamh."
 
-#: sequencer.c
 #, c-format
 msgid "%s: can't cherry-pick a %s"
 msgstr "%s: ní féidir %s a roghnú silíní"
 
-#: sequencer.c
 #, c-format
 msgid "%s: bad revision"
 msgstr "%s: droch-athbhreithniú"
 
-#: sequencer.c
 msgid "can't revert as initial commit"
 msgstr "ní féidir teacht ar ais mar thiomantas tosaigh"
 
-#: sequencer.c
 #, c-format
 msgid "skipped previously applied commit %s"
-msgstr "scipeáil tiomantas %s a cuireadh i bhfeidhm"
+msgstr "scipeáil an tiomnú a cuireadh i bhfeidhm roimhe seo %s"
 
-#: sequencer.c
 msgid "use --reapply-cherry-picks to include skipped commits"
 msgstr ""
 "bain úsáid as --reapply-cherry-picks chun gealltanais scipeáilte a áireamh"
 
-#: sequencer.c
 msgid "make_script: unhandled options"
 msgstr "make_script: roghanna neamh-láimhseáilte"
 
-#: sequencer.c
 msgid "make_script: error preparing revisions"
 msgstr "make_script: earráid ag ullmhú athbhreithnithe"
 
-#: sequencer.c
 msgid "nothing to do"
 msgstr "aon rud le déanamh"
 
-#: sequencer.c
 msgid "could not skip unnecessary pick commands"
 msgstr "ní fhéadfadh orduithe pioc gan ghá a scipeáil"
 
-#: sequencer.c
 msgid "the script was already rearranged."
 msgstr "athshocraíodh an script cheana féin."
 
-#: sequencer.c
 #, c-format
 msgid "update-refs file at '%s' is invalid"
 msgstr "tá comhad update-refs ag '%s' neamhbhailí"
 
-#: setup.c
 #, c-format
 msgid "'%s' is outside repository at '%s'"
 msgstr "Tá '%s' an stór lasmuigh ag '%s'"
 
-#: setup.c
 #, c-format
 msgid ""
 "%s: no such path in the working tree.\n"
@@ -27090,7 +22787,6 @@
 "Úsáid 'git <command>--<path>... 'chun cosáin nach bhfuil ann go háitiúil a "
 "shonrú."
 
-#: setup.c
 #, c-format
 msgid ""
 "ambiguous argument '%s': unknown revision or path not in the working tree.\n"
@@ -27102,12 +22798,10 @@
 "Úsáid '--' chun cosáin a scaradh ó athbhreithnithe, mar seo:\n"
 "'git <command>[<revision>...] -- [<file>...] '"
 
-#: setup.c
 #, c-format
 msgid "option '%s' must come before non-option arguments"
 msgstr "caithfidh rogha '%s' teacht roimh argóintí neamh-rogha"
 
-#: setup.c
 #, c-format
 msgid ""
 "ambiguous argument '%s': both revision and filename\n"
@@ -27118,95 +22812,74 @@
 "Úsáid '--' chun cosáin a scaradh ó athbhreithnithe, mar seo:\n"
 "'git <command>[<revision>...] -- [<file>...] '"
 
-#: setup.c
 msgid "unable to set up work tree using invalid config"
 msgstr ""
-"in ann crann oibre a chur ar bun ag baint úsáide as cumraíocht nebhailí"
+"ní féidir crann oibre a bhunú ag baint úsáide as cumraíocht neamhbhailí"
 
-#: setup.c
 #, c-format
 msgid "'%s' already specified as '%s'"
 msgstr "'%s' sonraithe cheana féin mar '%s'"
 
-#: setup.c
 #, c-format
 msgid "Expected git repo version <= %d, found %d"
 msgstr "Leagan repo git ag súil leis <= %d, aimsíodh %d"
 
-#: setup.c
 msgid "unknown repository extension found:"
 msgid_plural "unknown repository extensions found:"
 msgstr[0] "síneadh stórais anaithnid aimsithe:"
 msgstr[1] "síntí stórais anaithnide aimsithe:"
 msgstr[2] "síntí stórais anaithnide aimsithe:"
 
-#: setup.c
 msgid "repo version is 0, but v1-only extension found:"
 msgid_plural "repo version is 0, but v1-only extensions found:"
 msgstr[0] "is é leagan repo 0, ach fuarthas síneadh v1 amháin:"
 msgstr[1] "is é 0 an leagan den stór, ach fuarthas síntí v1 amháin:"
 msgstr[2] "is é 0 an leagan den stór, ach fuarthas síntí v1 amháin:"
 
-#: setup.c
 #, c-format
 msgid "error opening '%s'"
 msgstr "earráid ag oscailt '%s'"
 
-#: setup.c
 #, c-format
 msgid "too large to be a .git file: '%s'"
 msgstr "ró-mhór le bheith ina chomhad .git: '%s'"
 
-#: setup.c
 #, c-format
 msgid "error reading %s"
 msgstr "earráid ag léamh %s"
 
-#: setup.c
 #, c-format
 msgid "invalid gitfile format: %s"
 msgstr "formáid gitfile neamhbhailí: %s"
 
-#: setup.c
 #, c-format
 msgid "no path in gitfile: %s"
 msgstr "gan aon chosán i gitfile: %s"
 
-#: setup.c
 #, c-format
 msgid "not a git repository: %s"
 msgstr "ní stór git: %s"
 
-#: setup.c
 #, c-format
 msgid "'$%s' too big"
 msgstr "'$%s' ró-mhór"
 
-#: setup.c
 #, c-format
 msgid "not a git repository: '%s'"
 msgstr "ní stór git: '%s'"
 
-#: setup.c
 #, c-format
 msgid "cannot chdir to '%s'"
 msgstr "ní féidir teacht ar '%s'"
 
-#: setup.c
-msgid "cannot come back to cwd"
-msgstr "ní féidir teacht ar ais chuig cwd"
-
-#: setup.c
 #, c-format
 msgid "failed to stat '%*s%s%s'"
 msgstr "theip ar '%*s%s%s' a thaispeáint"
 
-#: setup.c
 #, c-format
 msgid "safe.directory '%s' not absolute"
 msgstr "níl safe.directory '%s' iomlán"
 
-#: setup.c
 #, c-format
 msgid ""
 "detected dubious ownership in repository at '%s'\n"
@@ -27219,21 +22892,17 @@
 "\n"
 "git config --global --add safe.directory %s"
 
-#: setup.c
 msgid "Unable to read current working directory"
 msgstr "Ní féidir eolaire oibre reatha a léamh"
 
-#: setup.c
 #, c-format
 msgid "cannot change to '%s'"
 msgstr "ní féidir athrú go '%s'"
 
-#: setup.c
 #, c-format
 msgid "not a git repository (or any of the parent directories): %s"
 msgstr "ní stór git (nó aon cheann de na tuismitheoireolairí): %s"
 
-#: setup.c
 #, c-format
 msgid ""
 "not a git repository (or any parent up to mount point %s)\n"
@@ -27243,12 +22912,10 @@
 "Stopadh ag teorainn an chórais chomhaid (níl GIT_DISCOVERY_ACROSS_FILESYSTEM "
 "socraithe)."
 
-#: setup.c
 #, c-format
 msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')"
 msgstr "ní féidir stór lom '%s' a úsáid (safe.bareRepository is '%s')"
 
-#: setup.c
 #, c-format
 msgid ""
 "problem with core.sharedRepository filemode value (0%.3o).\n"
@@ -27258,174 +22925,141 @@
 "Ní mór ceadanna léite agus scríbhneoireachta a bheith ag úinéir na gcomhad i "
 "gcónaí."
 
-#: setup.c
 msgid "fork failed"
 msgstr "theip ar fhorc"
 
-#: setup.c
 msgid "setsid failed"
 msgstr "theip ar setsid"
 
-#: setup.c
 #, c-format
 msgid "cannot stat template '%s'"
 msgstr "ní féidir teacht ar theimpléad '%s'"
 
-#: setup.c
 #, c-format
 msgid "cannot opendir '%s'"
 msgstr "ní féidir '%s' a oscailt"
 
-#: setup.c
 #, c-format
 msgid "cannot readlink '%s'"
 msgstr "ní féidir nasc '%s' a léamh"
 
-#: setup.c
 #, c-format
 msgid "cannot symlink '%s' '%s'"
 msgstr "ní féidir '%s' '' %s 'a nascadh"
 
-#: setup.c
 #, c-format
 msgid "cannot copy '%s' to '%s'"
 msgstr "ní féidir '%s' a chóipeáil chuig '%s'"
 
-#: setup.c
 #, c-format
 msgid "ignoring template %s"
 msgstr "ag neamhaird den teimpléad %s"
 
-#: setup.c
 #, c-format
 msgid "templates not found in %s"
 msgstr "teimpléid gan aimsiú i %s"
 
-#: setup.c
 #, c-format
 msgid "not copying templates from '%s': %s"
 msgstr "gan teimpléid a chóipeáil ó '%s': %s"
 
-#: setup.c
 #, c-format
 msgid "invalid initial branch name: '%s'"
 msgstr "ainm brainse tosaigh neamhbhailí: '%s'"
 
-#: setup.c
 #, c-format
 msgid "re-init: ignored --initial-branch=%s"
 msgstr "ath-init: neamhaird a dhéanamh ar --initial-branch=%s"
 
-#: setup.c
 #, c-format
 msgid "unable to handle file type %d"
-msgstr "in ann cineál comhad %d a láimhseáil"
+msgstr "ní féidir cineál comhaid %d a láimhseáil"
 
-#: setup.c
 #, c-format
 msgid "unable to move %s to %s"
-msgstr "nach féidir %s a bhogadh go %s"
+msgstr "ní féidir %s a bhogadh go %s"
 
-#: setup.c
 msgid "attempt to reinitialize repository with different hash"
 msgstr "iarracht a dhéanamh stór a aththionsú le hash difriúil"
 
-#: setup.c
 msgid ""
 "attempt to reinitialize repository with different reference storage format"
 msgstr ""
 "iarracht a dhéanamh stór a aththionsú le formáid stórála tagartha difriúil"
 
-#: setup.c
 #, c-format
 msgid "%s already exists"
 msgstr "Tá %s ann cheana féin"
 
-#: setup.c
 #, c-format
 msgid "Reinitialized existing shared Git repository in %s%s\n"
 msgstr "Stórlann Git roinnte atá ann cheana a athsheoladh i %s%s\n"
 
-#: setup.c
 #, c-format
 msgid "Reinitialized existing Git repository in %s%s\n"
 msgstr "Aththionscnaíodh stór Git atá ann cheana i %s%s\n"
 
-#: setup.c
 #, c-format
 msgid "Initialized empty shared Git repository in %s%s\n"
 msgstr "Stórlann Git roinnte folamh tosaithe i %s%s\n"
 
-#: setup.c
 #, c-format
 msgid "Initialized empty Git repository in %s%s\n"
 msgstr "Stórlann Git folamh tosaithe i %s%s\n"
 
-#: sparse-index.c
 #, c-format
 msgid "index entry is a directory, but not sparse (%08x)"
 msgstr "is eolaire é iontráil innéacs, ach ní neamhchoitianta (%08x)"
 
-#: split-index.c
 msgid "cannot use split index with a sparse index"
 msgstr "ní féidir innéacs scoilte a úsáid le hinnéacs neamhchoitianta"
 
 #. TRANSLATORS: The first %s is a command like "ls-tree".
-#: strbuf.c
 #, c-format
 msgid "bad %s format: element '%s' does not start with '('"
 msgstr "fhormáid olc %s: ní thosaíonn eilimint '%s' le '('"
 
 #. TRANSLATORS: The first %s is a command like "ls-tree".
-#: strbuf.c
 #, c-format
 msgid "bad %s format: element '%s' does not end in ')'"
 msgstr "droch-fhormáid %s: ní chríochnaíonn eilimint '%s' i ')'"
 
 #. TRANSLATORS: %s is a command like "ls-tree".
-#: strbuf.c
 #, c-format
 msgid "bad %s format: %%%.*s"
 msgstr "fhormáid %s olc: %%%.*s"
 
 #. TRANSLATORS: IEC 80000-13:2008 gibibyte
-#: strbuf.c
 #, c-format
 msgid "%u.%2.2u GiB"
 msgstr "%u.%2.2u GiB"
 
 #. TRANSLATORS: IEC 80000-13:2008 gibibyte/second
-#: strbuf.c
 #, c-format
 msgid "%u.%2.2u GiB/s"
 msgstr "%u.%2.2u GiB/s"
 
 #. TRANSLATORS: IEC 80000-13:2008 mebibyte
-#: strbuf.c
 #, c-format
 msgid "%u.%2.2u MiB"
 msgstr "%u.%2.2u MiB"
 
 #. TRANSLATORS: IEC 80000-13:2008 mebibyte/second
-#: strbuf.c
 #, c-format
 msgid "%u.%2.2u MiB/s"
 msgstr "%u.%2.2u MiB/s"
 
 #. TRANSLATORS: IEC 80000-13:2008 kibibyte
-#: strbuf.c
 #, c-format
 msgid "%u.%2.2u KiB"
 msgstr "%u.%2.2u KiB"
 
 #. TRANSLATORS: IEC 80000-13:2008 kibibyte/second
-#: strbuf.c
 #, c-format
 msgid "%u.%2.2u KiB/s"
 msgstr "%u.%2.2u KiB/s"
 
 #. TRANSLATORS: IEC 80000-13:2008 byte
-#: strbuf.c
 #, c-format
 msgid "%u byte"
 msgid_plural "%u bytes"
@@ -27434,7 +23068,6 @@
 msgstr[2] "%u beart"
 
 #. TRANSLATORS: IEC 80000-13:2008 byte/second
-#: strbuf.c
 #, c-format
 msgid "%u byte/s"
 msgid_plural "%u bytes/s"
@@ -27442,64 +23075,52 @@
 msgstr[1] "%u beart/s"
 msgstr[2] "%u beart/s"
 
-#: submodule-config.c
 #, c-format
 msgid "ignoring suspicious submodule name: %s"
 msgstr "ag déanamh neamhaird d'ainm fo-mhodúil amhrasach: %s"
 
-#: submodule-config.c
 msgid "negative values not allowed for submodule.fetchJobs"
 msgstr "luachanna diúltacha nach gceadaítear le haghaidh submodule.fetchJobs"
 
-#: submodule-config.c
 #, c-format
 msgid "ignoring '%s' which may be interpreted as a command-line option: %s"
 msgstr ""
 "neamhaird a dhéanamh ar '%s' ar féidir a léirmhíniú mar rogha líne ordaithe: "
 "%s"
 
-#: submodule-config.c
 #, c-format
 msgid "Could not update .gitmodules entry %s"
 msgstr "Ní fhéadfaí iontráil.gitmodules %s a nuashonrú"
 
-#: submodule.c
 msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first"
 msgstr ""
 "Ní féidir .gitmodules neamh-chumhdaithe a athrú, coinbhleachtaí cumaisc a "
 "réiteach"
 
-#: submodule.c
 #, c-format
 msgid "Could not find section in .gitmodules where path=%s"
 msgstr ""
 "Níorbh fhéidir an rannóg a aimsiú i .gitmodules áit a bhfuil an cosán = %s"
 
-#: submodule.c
 #, c-format
 msgid "Could not remove .gitmodules entry for %s"
 msgstr "Ní fhéadfaí iontráil.gitmodules a bhaint do %s"
 
-#: submodule.c
 msgid "staging updated .gitmodules failed"
 msgstr "theip ar stáisiú nuashonraithe .gitmodules"
 
-#: submodule.c
 #, c-format
 msgid "in unpopulated submodule '%s'"
 msgstr "i bhfo-mhodúl neamhdhaonra '%s'"
 
-#: submodule.c
 #, c-format
 msgid "Pathspec '%s' is in submodule '%.*s'"
 msgstr "Tá pathspec '%s' i bhfo-mhodúl '%.*s"
 
-#: submodule.c
 #, c-format
 msgid "bad --ignore-submodules argument: %s"
 msgstr "argóint olc --ignore-submodules: %s"
 
-#: submodule.c
 #, c-format
 msgid ""
 "Submodule in commit %s at path: '%s' collides with a submodule named the "
@@ -27508,12 +23129,10 @@
 "Fo-mhodúl i dtiomantas %s ag an gcosán: imbhuaileann '%s' le fo-mhodúl darb "
 "ainm mar an gcéanna. Ag scipeáil é."
 
-#: submodule.c
 #, c-format
 msgid "submodule entry '%s' (%s) is a %s, not a commit"
 msgstr "is %s é iontráil an fhomhodúil '%s' (%s), ní tiomnú"
 
-#: submodule.c
 #, c-format
 msgid ""
 "Could not run 'git rev-list <commits> --not --remotes -n 1' command in "
@@ -27522,42 +23141,34 @@
 "Ní raibh an t-ordú 'git rev-list <commits>--not --remotes -n 1' a reáchtáil "
 "i bhfo-mhodúl %s"
 
-#: submodule.c
 #, c-format
 msgid "process for submodule '%s' failed"
 msgstr "theip ar phróiseas le haghaidh fo-mhodúl '%s'"
 
-#: submodule.c
 #, c-format
 msgid "Pushing submodule '%s'\n"
 msgstr "Ag brú an fho-mhodúil '%s'\n"
 
-#: submodule.c
 #, c-format
 msgid "Unable to push submodule '%s'\n"
 msgstr "Ní féidir an fho-mhodúl '%s' a bhrú\n"
 
-#: submodule.c
 #, c-format
 msgid "Fetching submodule %s%s\n"
 msgstr "Ag fáil fo-mhodúl %s%s\n"
 
-#: submodule.c
 #, c-format
 msgid "Could not access submodule '%s'\n"
 msgstr "Níorbh fhéidir rochtain a fháil ar fho-mhodúl '%s'\n"
 
-#: submodule.c
 #, c-format
 msgid "Could not access submodule '%s' at commit %s\n"
 msgstr "Níorbh fhéidir rochtain a fháil ar fho-mhodúl '%s' ag tiomantas %s\n"
 
-#: submodule.c
 #, c-format
 msgid "Fetching submodule %s%s at commit %s\n"
 msgstr "Ag fáil fo-mhodúl %s%s ag an tiomnú %s\n"
 
-#: submodule.c
 #, c-format
 msgid ""
 "Errors during submodule fetch:\n"
@@ -27566,72 +23177,58 @@
 "Earráidí le linn teacht fo-mhodúil:\n"
 "%s"
 
-#: submodule.c
 #, c-format
 msgid "'%s' not recognized as a git repository"
 msgstr "Ní aithnítear '%s' mar stór git"
 
-#: submodule.c
 #, c-format
 msgid "Could not run 'git status --porcelain=2' in submodule %s"
 msgstr "Ní féidir 'git status --porcelain=2' a reáchtáil i bhfo-mhodúl %s"
 
-#: submodule.c
 #, c-format
 msgid "'git status --porcelain=2' failed in submodule %s"
 msgstr "Theip ar 'git status --porcelain=2' i bhfo-mhodúl %s"
 
-#: submodule.c
 #, c-format
 msgid "could not start 'git status' in submodule '%s'"
 msgstr "ní fhéadfaí 'git status' a thosú i bhfo-mhodúl '%s'"
 
-#: submodule.c
 #, c-format
 msgid "could not run 'git status' in submodule '%s'"
 msgstr "ní fhéadfaí 'git status' a reáchtáil i bhfo-mhodúl '%s'"
 
-#: submodule.c
 #, c-format
 msgid "Could not unset core.worktree setting in submodule '%s'"
 msgstr "Ní fhéadfaí socrú core.worktree a dhíshocrú i bhfo-mhodúl '%s'"
 
-#: submodule.c
 #, c-format
 msgid "could not recurse into submodule '%s'"
 msgstr "ní fhéadfaí athshlánú isteach i bhfo-mhodúl '%s'"
 
-#: submodule.c
 msgid "could not reset submodule index"
 msgstr "ní fhéadfadh innéacs fo-mhodúil a athshocrú"
 
-#: submodule.c
 #, c-format
 msgid "submodule '%s' has dirty index"
 msgstr "tá innéacs salach ag fo-mhodúl '%s'"
 
-#: submodule.c
 #, c-format
 msgid "Submodule '%s' could not be updated."
 msgstr "Ní fhéadfaí fo-mhodúl '%s' a nuashonrú."
 
-#: submodule.c
 #, c-format
 msgid "submodule git dir '%s' is inside git dir '%.*s'"
 msgstr "tá fo-mhodúl git dir '%s' taobh istigh de git dir '%.*s"
 
-#: submodule.c
 #, c-format
 msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link"
 msgstr ""
 "ag súil leis '%.*s' i gcosán fo-mhodúil '%s' gan a bheith ina nasc siombalach"
 
-#: submodule.c
 #, c-format
 msgid "expected submodule path '%s' not to be a symbolic link"
 msgstr "ag súil nach mbeidh cosán fo-mhodúil '%s' ina nasc siombalach"
 
-#: submodule.c
 #, c-format
 msgid ""
 "relocate_gitdir for submodule '%s' with more than one worktree not supported"
@@ -27639,17 +23236,14 @@
 "relocate_gitdir le haghaidh fo-mhodúil '%s' le níos mó ná crann oibre amháin "
 "nach dtacaítear leis"
 
-#: submodule.c
 #, c-format
 msgid "could not lookup name for submodule '%s'"
 msgstr "ní fhéadfaí ainm a lorg don fho-mhodúl '%s'"
 
-#: submodule.c
 #, c-format
 msgid "refusing to move '%s' into an existing git dir"
 msgstr "diúltú '%s' a bhogadh isteach i git dir atá ann cheana"
 
-#: submodule.c
 #, c-format
 msgid ""
 "Migrating git directory of '%s%s' from\n"
@@ -27660,120 +23254,95 @@
 "'%s' go\n"
 "'%s'\n"
 
-#: submodule.c
 msgid "could not start ls-files in .."
 msgstr "ní fhéadfaí ls-files a thosú i.."
 
-#: submodule.c
 #, c-format
 msgid "ls-tree returned unexpected return code %d"
 msgstr "d’fhill an crann ls cód fillte gan choinne %d"
 
-#: symlinks.c
 #, c-format
 msgid "failed to lstat '%s'"
 msgstr "theip ar lstat '%s'"
 
-#: t/helper/test-bundle-uri.c
 msgid "no remote configured to get bundle URIs from"
 msgstr "gan aon iargúlta cumraithe chun URIs beartán a fháil ó"
 
-#: t/helper/test-bundle-uri.c
 msgid "could not get the bundle-uri list"
 msgstr "ní raibh in ann an liosta bundle-uri a fháil"
 
-#: t/helper/test-cache-tree.c
 msgid "test-tool cache-tree <options> (control|prime|update)"
 msgstr "test-tool cache-tree <options> (control|prime|update)"
 
-#: t/helper/test-cache-tree.c
 msgid "clear the cache tree before each iteration"
 msgstr "glan an crann taisce roimh gach athrú"
 
-#: t/helper/test-cache-tree.c
 msgid "number of entries in the cache tree to invalidate (default 0)"
 msgstr ""
 "líon na n-iontrálacha sa chrann taisce le neamhbhailí (réamhshocraithe 0)"
 
-#: t/helper/test-pack-deltas.c
 msgid "the number of objects to write"
 msgstr "líon na rudaí le scríobh"
 
-#: t/helper/test-path-walk.c
 msgid "test-tool path-walk <options> -- <revision-options>"
 msgstr "test-tool path-walk <options> -- <revision-options>"
 
-#: t/helper/test-path-walk.c
 msgid "toggle inclusion of blob objects"
 msgstr "cuimsiú rudaí blob a thógáil"
 
-#: t/helper/test-path-walk.c
 msgid "toggle inclusion of commit objects"
 msgstr "toggle áireamh rudaí tiomanta"
 
-#: t/helper/test-path-walk.c
 msgid "toggle inclusion of tag objects"
 msgstr "cuimsiú rudaí clibeanna a thosc"
 
-#: t/helper/test-path-walk.c
 msgid "toggle inclusion of tree objects"
 msgstr "cuimsiú rudaí crann a thógáil"
 
-#: t/helper/test-path-walk.c
 msgid "toggle pruning of uninteresting paths"
 msgstr "bearradh cosáin neamh-spéisiúla a thosú"
 
-#: t/helper/test-path-walk.c
+msgid "toggle aggressive edge walk"
+msgstr "siúlóid imeall ionsaitheach a scoránaigh"
+
 msgid "read a pattern list over stdin"
 msgstr "léigh liosta patrún thar stdin"
 
-#: t/helper/test-reach.c
 #, c-format
 msgid "commit %s is not marked reachable"
 msgstr "nach bhfuil comhordú %s marcáilte inrochtana"
 
-#: t/helper/test-reach.c
 msgid "too many commits marked reachable"
 msgstr "an iomarca gealltanais atá marcáilte inrochtana"
 
-#: t/helper/test-read-midx.c
 msgid "could not determine MIDX preferred pack"
 msgstr "ní fhéadfaí pacáiste is fearr MIDX a chinneadh"
 
-#: t/helper/test-serve-v2.c
 msgid "test-tool serve-v2 [<options>]"
 msgstr "test-tool serve-v2 [<options>]"
 
-#: t/helper/test-serve-v2.c
 msgid "exit immediately after advertising capabilities"
 msgstr "imeacht díreach tar éis cumais fógraíochta"
 
-#: t/helper/test-simple-ipc.c
 msgid "test-helper simple-ipc is-active    [<name>] [<options>]"
 msgstr "<name><options>tá cúntóir tástála simple-ipc gníomhach [] []"
 
-#: t/helper/test-simple-ipc.c
 msgid "test-helper simple-ipc run-daemon   [<name>] [<threads>]"
 msgstr "<name><threads>cúntóir tástála simple-ipc run-daemon [] []"
 
-#: t/helper/test-simple-ipc.c
 msgid "test-helper simple-ipc start-daemon [<name>] [<threads>] [<max-wait>]"
 msgstr ""
 "<name><threads><max-wait>cúntóir tástála simple-ipc tosaigh daemon [] [] []"
 
-#: t/helper/test-simple-ipc.c
 msgid "test-helper simple-ipc stop-daemon  [<name>] [<max-wait>]"
 msgstr "<name><max-wait>cúntóir tástála simple-ipc stad-daemon [] []"
 
-#: t/helper/test-simple-ipc.c
 msgid "test-helper simple-ipc send         [<name>] [<token>]"
 msgstr "<name><token>cúntóir tástála simple-ipc seol [] []"
 
-#: t/helper/test-simple-ipc.c
 msgid "test-helper simple-ipc sendbytes    [<name>] [<bytecount>] [<byte>]"
 msgstr "<name><bytecount><byte>test-helper simple-ipc sendbytes [] [] []"
 
-#: t/helper/test-simple-ipc.c
 msgid ""
 "test-helper simple-ipc multiple     [<name>] [<threads>] [<bytecount>] "
 "[<batchsize>]"
@@ -27781,99 +23350,76 @@
 "test-helper simple-ipc multiple     [<name>] [<threads>] [<bytecount>] "
 "[<batchsize>]"
 
-#: t/helper/test-simple-ipc.c
 msgid "name or pathname of unix domain socket"
 msgstr "ainm nó ainm cosán soicéad fearainn unix"
 
-#: t/helper/test-simple-ipc.c
 msgid "named-pipe name"
 msgstr "ainm píopa ainmnithe"
 
-#: t/helper/test-simple-ipc.c
 msgid "number of threads in server thread pool"
 msgstr "líon na snáitheanna i linn snáithe freastalaí"
 
-#: t/helper/test-simple-ipc.c
 msgid "seconds to wait for daemon to start or stop"
 msgstr "soicind chun fanacht go dtosóidh nó stopfaidh an daemon"
 
-#: t/helper/test-simple-ipc.c
 msgid "number of bytes"
 msgstr "líon na mbetaí"
 
-#: t/helper/test-simple-ipc.c
 msgid "number of requests per thread"
 msgstr "líon iarratais in aghaidh an snáithe"
 
-#: t/helper/test-simple-ipc.c
 msgid "byte"
-msgstr "bith"
+msgstr "beart"
 
-#: t/helper/test-simple-ipc.c
 msgid "ballast character"
 msgstr "carachtar balasta"
 
-#: t/helper/test-simple-ipc.c
 msgid "token"
 msgstr "comhartha"
 
-#: t/helper/test-simple-ipc.c
 msgid "command token to send to the server"
 msgstr "comhartha ordaithe le seoladh chuig an bhfreastalaí"
 
-#: t/unit-tests/unit-test.c
 msgid "unit-test [<options>]"
 msgstr "unit-test [<options>]"
 
-#: t/unit-tests/unit-test.c
 msgid "immediately exit upon the first failed test"
 msgstr "imeacht láithreach ar an gcéad tástáil theip"
 
-#: t/unit-tests/unit-test.c
 msgid "suite[::test]"
 msgstr "suite [::test]"
 
-#: t/unit-tests/unit-test.c
 msgid "run only test suite or individual test <suite[::test]>"
 msgstr "reáchtáil ach sraith tástála nó tástáil aonair <suite [::test] >"
 
-#: t/unit-tests/unit-test.c
 msgid "suite"
 msgstr "svuít"
 
-#: t/unit-tests/unit-test.c
 msgid "exclude test suite <suite>"
 msgstr "sraith tástála a eisiamh <suite>"
 
-#: trailer.c
 #, c-format
 msgid "running trailer command '%s' failed"
 msgstr "theip ar an ordú leantóir '%s' a rith"
 
-#: trailer.c
 #, c-format
 msgid "unknown value '%s' for key '%s'"
 msgstr "luach anaithnid '%s' don eochair '%s'"
 
-#: trailer.c
 #, c-format
 msgid "empty trailer token in trailer '%.*s'"
 msgstr "comhartha leantóra folamh i leantóir '%.*s'"
 
-#: transport-helper.c
 msgid "full write to remote helper failed"
 msgstr "theip ar scríobh iomlán chuig cianchúntóir"
 
-#: transport-helper.c
 #, c-format
 msgid "unable to find remote helper for '%s'"
-msgstr "in ann cúntóir iargúlta a aimsiú do '%s'"
+msgstr "ní féidir cúntóir iargúlta a aimsiú do '%s'"
 
-#: transport-helper.c
 msgid "can't dup helper output fd"
 msgstr "ní féidir le aschur cúntóra fd a dhéanamh"
 
-#: transport-helper.c
 #, c-format
 msgid ""
 "unknown mandatory capability %s; this remote helper probably needs newer "
@@ -27882,117 +23428,92 @@
 "cumas éigeantach anaithnid %s; is dócha go mbeidh leagan níos nuaí de Git ag "
 "teastáil ó"
 
-#: transport-helper.c
 msgid "this remote helper should implement refspec capability"
 msgstr "ba cheart go gcuirfeadh an cúntóir cianda seo cumas refspec"
 
-#: transport-helper.c
 #, c-format
 msgid "%s unexpectedly said: '%s'"
 msgstr "Dúirt %s gan choinne: '%s'"
 
-#: transport-helper.c
 #, c-format
 msgid "%s also locked %s"
 msgstr "Glas %s freisin %s"
 
-#: transport-helper.c
 msgid "couldn't run fast-import"
 msgstr "ní raibh in ann allmhairiú tapa a reá"
 
-#: transport-helper.c
 msgid "error while running fast-import"
 msgstr "earráid agus iompórtáil tapa á rith"
 
-#: transport-helper.c
 #, c-format
 msgid "could not read ref %s"
 msgstr "ní raibh in ann tagairt %s a léamh"
 
-#: transport-helper.c
 #, c-format
 msgid "unknown response to connect: %s"
 msgstr "freagra anaithnid chun nascadh: %s"
 
-#: transport-helper.c
 msgid "setting remote service path not supported by protocol"
-msgstr "cosán seirbhíse iargúlta a shocrú nach dtacaíonn"
+msgstr "ní thacaíonn prótacal le cosán seirbhíse cianda a shocrú"
 
-#: transport-helper.c
 msgid "invalid remote service path"
 msgstr "cosán seirbhíse iargúlta"
 
-#: transport-helper.c
 #, c-format
 msgid "can't connect to subservice %s"
 msgstr "ní féidir nasc a dhéanamh le fo-sheirbhís %s"
 
-#: transport-helper.c transport.c
 msgid "--negotiate-only requires protocol v2"
 msgstr "--negotiate-only ag teastáil prótacal v2"
 
-#: transport-helper.c
 msgid "'option' without a matching 'ok/error' directive"
 msgstr "'roghan' gan treoir 'ok/earráid' a mheaitseáil"
 
-#: transport-helper.c
 #, c-format
 msgid "expected ok/error, helper said '%s'"
 msgstr "súil le ok/earráid, dúirt an cúntóir '%s'"
 
-#: transport-helper.c
 #, c-format
 msgid "helper reported unexpected status of %s"
 msgstr "thuairiscigh cúntóir stádas gan choinne %s"
 
-#: transport-helper.c
 #, c-format
 msgid "helper %s does not support dry-run"
-msgstr "ní thacaíonn cúntóir %s le rith tirim"
+msgstr "ní thacaíonn cúntóir %s le dry-run"
 
-#: transport-helper.c
 #, c-format
 msgid "helper %s does not support --signed"
 msgstr "ní thacaíonn cúntóir %s le --signed"
 
-#: transport-helper.c
 #, c-format
 msgid "helper %s does not support --signed=if-asked"
-msgstr "ní thacaíonn cúntóir %s le --signed=if-iarrtha"
+msgstr "ní thacaíonn cúntóir %s le --signed=if-asked"
 
-#: transport-helper.c
 #, c-format
 msgid "helper %s does not support --atomic"
 msgstr "ní thacaíonn cúntóir %s le --atomic"
 
-#: transport-helper.c
 #, c-format
 msgid "helper %s does not support --%s"
 msgstr "ní thacaíonn cúntóir %s le --%s"
 
-#: transport-helper.c
 #, c-format
 msgid "helper %s does not support 'push-option'"
-msgstr "ní thacaíonn cúntóir %s le 'push-rogha'"
+msgstr "ní thacaíonn cúntóir %s le 'push-option'"
 
-#: transport-helper.c
 msgid "remote-helper doesn't support push; refspec needed"
 msgstr "ní thacaíonn cúntóir iargúlta le brú; teastaíonn refspec"
 
-#: transport-helper.c
 #, c-format
 msgid "helper %s does not support '--force'"
 msgstr "ní thacaíonn cúntóir %s le '--force'"
 
-#: transport-helper.c
 msgid "couldn't run fast-export"
 msgstr "ní raibh sé in ann onnmhairiú tapa a"
 
-#: transport-helper.c
 msgid "error while running fast-export"
 msgstr "earráid agus easpórtáil tapa á rith"
 
-#: transport-helper.c
 #, c-format
 msgid ""
 "No refs in common and none specified; doing nothing.\n"
@@ -28002,101 +23523,80 @@
 "rud.\n"
 "B'fhéidir gur chóir duit brainse a shonrú.\n"
 
-#: transport-helper.c
 #, c-format
 msgid "unsupported object format '%s'"
 msgstr "formáid réad gan tacaíocht '%s'"
 
-#: transport-helper.c
 #, c-format
 msgid "malformed response in ref list: %s"
 msgstr "freagra mífhoirmithe sa liosta tagartha: %s"
 
-#: transport-helper.c
 #, c-format
 msgid "read(%s) failed"
 msgstr "theip ar léamh (%s)"
 
-#: transport-helper.c
 #, c-format
 msgid "write(%s) failed"
 msgstr "theip ar scríobh (%s)"
 
-#: transport-helper.c
 #, c-format
 msgid "%s thread failed"
 msgstr "Theip ar snáithe %s"
 
-#: transport-helper.c
 #, c-format
 msgid "%s thread failed to join: %s"
 msgstr "Theip ar shnáithe %s a bheith páirteach: %s"
 
-#: transport-helper.c
 #, c-format
 msgid "can't start thread for copying data: %s"
 msgstr "ní féidir snáithe a thosú chun sonraí a chóipeáil: %s"
 
-#: transport-helper.c
 #, c-format
 msgid "%s process failed to wait"
 msgstr "Theip ar phróiseas %s fanacht"
 
-#: transport-helper.c
 #, c-format
 msgid "%s process failed"
 msgstr "Theip ar phróiseas %s"
 
-#: transport-helper.c
 msgid "can't start thread for copying data"
 msgstr "ní féidir snáithe a thosú chun sonraí a chóipe"
 
-#: transport.c
 #, c-format
 msgid "Would set upstream of '%s' to '%s' of '%s'\n"
 msgstr "Socródh sé suas sruth de '%s' go '%s' de '%s'\n"
 
-#: transport.c
 #, c-format
 msgid "could not read bundle '%s'"
 msgstr "ní fhéadfaí beartán '%s' a léamh"
 
-#: transport.c
 #, c-format
 msgid "transport: invalid depth option '%s'"
 msgstr "iompar: rogha doimhneachta neamhbhailí '%s'"
 
-#: transport.c
 msgid "see protocol.version in 'git help config' for more details"
 msgstr ""
 "féach protocol.version in 'git help config' le haghaidh tuilleadh sonraí"
 
-#: transport.c
 msgid "server options require protocol version 2 or later"
 msgstr "teastaíonn leagan prótacal 2 nó níos déanaí ó roghanna"
 
-#: transport.c
 msgid "server does not support wait-for-done"
 msgstr "ní thacaíonn freastalaí le fanacht le déanamh"
 
-#: transport.c
 msgid "could not parse transport.color.* config"
 msgstr "ní fhéadfaí transport.color.* config a pháirseáil"
 
-#: transport.c
 msgid "support for protocol v2 not implemented yet"
 msgstr "tacaíocht do phrótacal v2 nach bhfuil curtha i bhfeidhm"
 
-#: transport.c
 #, c-format
 msgid "transport '%s' not allowed"
 msgstr "ní cheadaítear iompar '%s'"
 
-#: transport.c
 msgid "git-over-rsync is no longer supported"
 msgstr "ní thacaítear le git-over-rsync a thuilleadh"
 
-#: transport.c
 #, c-format
 msgid ""
 "The following submodule paths contain changes that can\n"
@@ -28105,7 +23605,6 @@
 "Tá athruithe ar féidir leis na cosáin fo-mhodúil seo a leanas\n"
 "nach bhfuil le fáil ar aon iargúlta:\n"
 
-#: transport.c
 #, c-format
 msgid ""
 "\n"
@@ -28131,43 +23630,33 @@
 "\n"
 "chun iad a bhrú chuig iargúlta.\n"
 
-#: transport.c
 msgid "Aborting."
 msgstr "Ag gearradh."
 
-#: transport.c
 msgid "failed to push all needed submodules"
 msgstr "theip ar gach fo-mhodúl riachtanach a bhrú"
 
-#: transport.c
 msgid "bundle-uri operation not supported by protocol"
 msgstr "oibríocht bundle-uri nach dtacaíonn prótacal"
 
-#: transport.c
 msgid "could not retrieve server-advertised bundle-uri list"
 msgstr "ní fhéadfaí liosta bundle-uri a fógraíodh ag freastalaí a aisghab"
 
-#: transport.c
 msgid "operation not supported by protocol"
 msgstr "oibriú nach dtacaíonn prótacal"
 
-#: tree-walk.c
 msgid "too-short tree object"
 msgstr "réad crann ró-ghearr"
 
-#: tree-walk.c
 msgid "malformed mode in tree entry"
 msgstr "modh mífhoirmithe i iontráil crann"
 
-#: tree-walk.c
 msgid "empty filename in tree entry"
 msgstr "ainm comhaid folamh i iontráil crann"
 
-#: tree-walk.c
 msgid "too-short tree file"
 msgstr "comhad crann ró-ghearr"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "Your local changes to the following files would be overwritten by checkout:\n"
@@ -28177,7 +23666,6 @@
 "sheiceáil:\n"
 "%%sDéan d'athruithe nó déan iad a stóráil sula n-athraíonn tú brainsí."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "Your local changes to the following files would be overwritten by checkout:\n"
@@ -28187,7 +23675,6 @@
 "sheiceáil:\n"
 "%%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "Your local changes to the following files would be overwritten by merge:\n"
@@ -28198,7 +23685,6 @@
 "%%sDo chuid athruithe a dhéanamh nó cuir isteach iad sula ndéanann tú a "
 "chumasc."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "Your local changes to the following files would be overwritten by merge:\n"
@@ -28208,7 +23694,6 @@
 "chumasc:\n"
 "%%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "Your local changes to the following files would be overwritten by %s:\n"
@@ -28217,7 +23702,6 @@
 "Déanfadh %s d'athruithe áitiúla ar na comhaid seo a leanas a fhorscríobh:\n"
 "%%sDéan do chuid athruithe nó iad a stóráil os comhair %s."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "Your local changes to the following files would be overwritten by %s:\n"
@@ -28226,7 +23710,6 @@
 "Déanfadh %s d'athruithe áitiúla ar na comhaid seo a leanas a fhorscríobh:\n"
 "%%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "Updating the following directories would lose untracked files in them:\n"
@@ -28235,7 +23718,6 @@
 "Chaillfeadh na n-eolairí seo a leanas a nuashonrú comhaid gan rianú iontu:\n"
 "%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "Refusing to remove the current working directory:\n"
@@ -28244,7 +23726,6 @@
 "Diúltú an eolaire oibre reatha a bhaint:\n"
 "%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be removed by checkout:\n"
@@ -28253,7 +23734,6 @@
 "Bainfí na comhaid crann oibre gan rianú seo a leanas trí sheiceáil:\n"
 "%%sBogadh nó bain iad sula n-athraíonn tú brainsí."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be removed by checkout:\n"
@@ -28262,7 +23742,6 @@
 "Bainfí na comhaid crann oibre gan rianú seo a leanas trí sheiceáil:\n"
 "%%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be removed by merge:\n"
@@ -28271,7 +23750,6 @@
 "Bainfí na comhaid crann oibre gan rianú seo a leanas trí chumasc:\n"
 "%%sDo thoil bog nó bain iad sula ndéanann tú a chumasc."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be removed by merge:\n"
@@ -28280,7 +23758,6 @@
 "Bainfí na comhaid crann oibre gan rianú seo a leanas trí chumasc:\n"
 "%%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be removed by %s:\n"
@@ -28289,7 +23766,6 @@
 "Bainfí %s na comhaid crann oibre neamhrianaithe seo a leanas:\n"
 "%%sDo thoil bog nó bain iad roimh %s."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be removed by %s:\n"
@@ -28298,7 +23774,6 @@
 "Bainfí %s na comhaid crann oibre neamhrianaithe seo a leanas:\n"
 "%%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be overwritten by "
@@ -28309,7 +23784,6 @@
 "sheiceáil:\n"
 "%%sBogadh nó bain iad sula n-athraíonn tú brainsí."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be overwritten by "
@@ -28320,7 +23794,6 @@
 "sheiceáil:\n"
 "%%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be overwritten by merge:\n"
@@ -28330,7 +23803,6 @@
 "chumasc:\n"
 "%%sDo thoil bog nó bain iad sula ndéanann tú cumasc."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be overwritten by merge:\n"
@@ -28340,7 +23812,6 @@
 "chumasc:\n"
 "%%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be overwritten by %s:\n"
@@ -28349,7 +23820,6 @@
 "Bheadh %s na comhaid crann oibre neamhrianaithe seo a leanas a fhorscríobh:\n"
 "%%sDo thoil bog nó bain iad roimh %s."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following untracked working tree files would be overwritten by %s:\n"
@@ -28358,12 +23828,10 @@
 "Bheadh %s na comhaid crann oibre neamhrianaithe seo a leanas a fhorscríobh:\n"
 "%%s"
 
-#: unpack-trees.c
 #, c-format
 msgid "Entry '%s' overlaps with '%s'.  Cannot bind."
 msgstr "Tá iontráil '%s' ag forluí le '%s'. Ní féidir ceangal a dhéanamh."
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "Cannot update submodule:\n"
@@ -28372,7 +23840,6 @@
 "Ní féidir fo-mhodúl a nuashonrú:\n"
 "%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following paths are not up to date and were left despite sparse "
@@ -28383,7 +23850,6 @@
 "patrúin neamhchoitianta:\n"
 "%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following paths are unmerged and were left despite sparse patterns:\n"
@@ -28393,7 +23859,6 @@
 "neamhchoitianta:\n"
 "%s"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "The following paths were already present and thus not updated despite sparse "
@@ -28404,12 +23869,10 @@
 "nuashonraíodh in ainneoin\n"
 "%s"
 
-#: unpack-trees.c
 #, c-format
 msgid "Aborting\n"
 msgstr "Gearradh\n"
 
-#: unpack-trees.c
 #, c-format
 msgid ""
 "After fixing the above paths, you may want to run `git sparse-checkout "
@@ -28418,11 +23881,9 @@
 "Tar éis duit na cosáin thuas a shocrú, b'fhéidir gur mhaith leat `git sparse-"
 "checkout reapply` a reáchtáil.\n"
 
-#: unpack-trees.c
 msgid "Updating files"
 msgstr "Comhad a nuashonrú"
 
-#: unpack-trees.c
 msgid ""
 "the following paths have collided (e.g. case-sensitive paths\n"
 "on a case-insensitive filesystem) and only one from the same\n"
@@ -28432,381 +23893,331 @@
 "ar chóras comhaid cás-neamh-íogair) agus ach ceann amháin ón gcéanna\n"
 "tá grúpa imbhuailte sa chrann oibre:\n"
 
-#: unpack-trees.c
 msgid "Updating index flags"
 msgstr "Nuashonrú bratacha innéacs"
 
-#: unpack-trees.c
 #, c-format
 msgid "worktree and untracked commit have duplicate entries: %s"
 msgstr ""
 "tá iontrálacha dúbailte ag crann oibre agus tiomantas neamhrianaithe: %s"
 
-#: upload-pack.c
 msgid "expected flush after fetch arguments"
 msgstr "súil le sruth tar éis argóintí a fháil"
 
-#: urlmatch.c
 msgid "invalid URL scheme name or missing '://' suffix"
 msgstr "ainm scéime URL neamhbhailí nó iarmhír ': //' in easnamh"
 
-#: urlmatch.c
 #, c-format
 msgid "invalid %XX escape sequence"
 msgstr "seicheamh éalaithe %XX neamhbhailí"
 
-#: urlmatch.c
 msgid "missing host and scheme is not 'file:'"
 msgstr "ní 'comhad: 'í an óstach agus an scéim atá in easnamh:"
 
-#: urlmatch.c
 msgid "a 'file:' URL may not have a port number"
 msgstr "b'fhéidir nach mbeadh uimhir chalafoirt ag URL 'file: '"
 
-#: urlmatch.c
 msgid "invalid characters in host name"
 msgstr "carachtair neamhbhailí in ainm ósta"
 
-#: urlmatch.c
 msgid "invalid port number"
-msgstr "uimhir phort neamhbhail"
+msgstr "uimhir phoirt neamhbhailí"
 
-#: urlmatch.c
 msgid "invalid '..' path segment"
 msgstr "deighleog cosáin '..' neamhbhailí"
 
-#: usage.c
 #, c-format
 msgid "error: unable to format message: %s\n"
 msgstr "earráid: ní féidir teachtaireacht a fhormáidiú: %s\n"
 
-#: usage.c
 msgid "usage: "
 msgstr "úsáid: "
 
-#: usage.c
 msgid "fatal: "
 msgstr "marfach: "
 
-#: usage.c
 msgid "error: "
 msgstr "earráid: "
 
-#: usage.c
 msgid "warning: "
 msgstr "rabhadh: "
 
-#: version.c
+#, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "Tá '%s' ainmnithe le haghaidh bainte.\n"
+
+#, c-format
+msgid ""
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
+msgstr ""
+"Más rud é go bhfuil an t-ordú seo in úsáid agat fós, seo an méid is féidir "
+"leat a dhéanamh:\n"
+"\n"
+"- léigh https://git-scm.com/docs/BreakingChanges.html\n"
+"- seiceáil an bhfuil aon duine tar éis plé a dhéanamh ar an méid seo ar an "
+"liosta poist agus an bhfuil rud éigin acu a d'fhéadfadh cabhrú leat: https://"
+"lore.kernel.org/git/?q=%s\n"
+"- seol ríomhphost chuig <git@vger.kernel.org> chun a chur in iúl dúinn go "
+"bhfuil tú fós ag úsáid an ordaithe seo agus nár éirigh leat ceann eile "
+"oiriúnach a aimsiú\n"
+
+msgid "refusing to run without --i-still-use-this"
+msgstr "ag diúltú rith gan --i-still-use-this fós"
+
 #, c-format
 msgid "uname() failed with error '%s' (%d)\n"
 msgstr "theip ar uname () le earráid '%s' (%d)\n"
 
-#: walker.c
 msgid "Fetching objects"
 msgstr "Rudaí a fháil"
 
-#: worktree.c
 #, c-format
 msgid "'%s' at main working tree is not the repository directory"
 msgstr "Ní hé '%s' ag an bpríomhchrann oibre an eolaire stórais"
 
-#: worktree.c
 #, c-format
 msgid "'%s' file does not contain absolute path to the working tree location"
 msgstr "Níl cosán iomlán chuig suíomh an chrainn oibre i gcomhad '%s'"
 
-#: worktree.c
 #, c-format
 msgid "'%s' is not a .git file, error code %d"
 msgstr "Ní comhad .git é '%s', cód earráide %d"
 
-#: worktree.c
 #, c-format
 msgid "'%s' does not point back to '%s'"
 msgstr "Ní dhíríonn '%s' ar ais chuig '%s'"
 
-#: worktree.c
 msgid "not a directory"
-msgstr "ní eolaire"
+msgstr "ní eolaire é"
 
-#: worktree.c
 msgid ".git is not a file"
 msgstr "Ní comhad é .git"
 
-#: worktree.c
 msgid ".git file broken"
 msgstr "comhad .git briste"
 
-#: worktree.c
 msgid ".git file incorrect"
 msgstr "comhad .git mícheart"
 
-#: worktree.c
 msgid ".git file absolute/relative path mismatch"
 msgstr "comhad .git neamhoiriúnú iomlán/coibhneasta coibhneasta"
 
-#: worktree.c
 msgid "not a valid path"
 msgstr "ní cosán bailí"
 
-#: worktree.c
 msgid "unable to locate repository; .git is not a file"
-msgstr "in ann stór a aimsiú; ní comhad é .git"
+msgstr "ní féidir an stórlann a aimsiú; ní comhad é .git"
 
-#: worktree.c
 msgid "unable to locate repository; .git file does not reference a repository"
-msgstr "in ann stór a aimsiú; ní thagann comhad .git tagairt do stór"
+msgstr ""
+"ní féidir an stórlann a aimsiú; ní dhéanann an comhad .git tagairt do "
+"stórlann"
 
-#: worktree.c
 msgid "unable to locate repository; .git file broken"
-msgstr "in ann stór a aimsiú; comhad .git briste"
+msgstr "ní féidir an stórlann a aimsiú; comhad .git briste"
 
-#: worktree.c
 msgid "gitdir unreadable"
 msgstr "gitdir unreadable"
 
-#: worktree.c
 msgid "gitdir absolute/relative path mismatch"
-msgstr "mímheaitseáil cosán iomlán/coibhneasta gitdir"
+msgstr "gitdir mí-oiriúnacht chosáin absalóideach/coibhneasta"
 
-#: worktree.c
 msgid "gitdir incorrect"
 msgstr "gitdir mícheart"
 
-#: worktree.c
 msgid "not a valid directory"
 msgstr "ní eolaire bailí"
 
-#: worktree.c
 msgid "gitdir file does not exist"
 msgstr "níl comhad gitdir ann"
 
-#: worktree.c
 #, c-format
 msgid "unable to read gitdir file (%s)"
-msgstr "nach féidir comhad gitdir a léamh (%s)"
+msgstr "ní féidir comhad gitdir (%s) a léamh"
 
-#: worktree.c
 #, c-format
 msgid "short read (expected %<PRIuMAX> bytes, read %<PRIuMAX>)"
 msgstr "léamh gearr (súil leis%<PRIuMAX>bytes, léithe%<PRIuMAX>)"
 
-#: worktree.c
 msgid "invalid gitdir file"
 msgstr "comhad gitdir neamhbhailí"
 
-#: worktree.c
 msgid "gitdir file points to non-existent location"
 msgstr "pointeálann comhad gitdir chuig suíomh nach bhfuil ann"
 
-#: worktree.c
 #, c-format
 msgid "unable to set %s in '%s'"
-msgstr "nach féidir %s a shocrú i '%s'"
+msgstr "ní féidir %s a shocrú i '%s'"
 
-#: worktree.c
 #, c-format
 msgid "unable to unset %s in '%s'"
-msgstr "nach féidir %s a dhíshocrú i '%s'"
+msgstr "ní féidir %s a dhíshuiteáil i '%s'"
 
-#: worktree.c
 msgid "failed to set extensions.worktreeConfig setting"
 msgstr "theip ar shocrú extensions.worktreeConfig"
 
-#: worktree.c
 msgid "unable to upgrade repository format to support relative worktrees"
-msgstr "in ann formáid stórais a uasghrádú chun tacú le crainn oibre coibh"
+msgstr ""
+"ní féidir formáid an stórais a uasghrádú chun tacú le crainn oibre "
+"coibhneasta"
 
-#: worktree.c
 msgid "unable to set extensions.relativeWorktrees setting"
 msgstr "ní féidir an socrú extensions.relativeWorktrees a shocrú"
 
-#: wrapper.c
 #, c-format
 msgid "could not setenv '%s'"
 msgstr "ní fhéadfaí '%s' a shocrú"
 
-#: wrapper.c
 #, c-format
 msgid "unable to create '%s'"
 msgstr "ní féidir '%s' a chruthú"
 
-#: wrapper.c
 #, c-format
 msgid "could not open '%s' for reading and writing"
 msgstr "ní fhéadfaí '%s' a oscailt le haghaidh léamh agus scríbhneoireachta"
 
-#: wrapper.c
 #, c-format
 msgid "unable to access '%s'"
 msgstr "ní féidir rochtain a fháil ar '%s'"
 
-#: wrapper.c
 msgid "unable to get current working directory"
-msgstr "in ann eolaire oibre reatha a fháil"
+msgstr "ní féidir an t-eolaire oibre reatha a fháil"
 
-#: wrapper.c
 msgid "unable to get random bytes"
-msgstr "in ann bétaí randamacha a fháil"
+msgstr "ní féidir bearta randamacha a fháil"
 
-#: wrapper.c
 #, c-format
 msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>"
 msgstr "ag iarraidh mmapáil %<PRIuMAX> thar theorainn %<PRIuMAX>"
 
-#: wrapper.c
 #, c-format
 msgid "mmap failed%s"
 msgstr "theip ar mmap %s"
 
-#: wt-status.c
 msgid "Unmerged paths:"
 msgstr "Cosáin neamh-chumasaithe:"
 
-#: wt-status.c
 msgid "  (use \"git restore --staged <file>...\" to unstage)"
 msgstr ""
 " (bain úsáid as “git restore --staged <comhad>...” chun an stáitse a dhíchur)"
 
-#: wt-status.c
 #, c-format
 msgid "  (use \"git restore --source=%s --staged <file>...\" to unstage)"
 msgstr ""
 " (bain úsáid as \"git restore --source=%s --staged <comhad>...\" chun an "
 "stáitse a dhí-ardú)"
 
-#: wt-status.c
 msgid "  (use \"git rm --cached <file>...\" to unstage)"
 msgstr ""
 " (bain úsáid as “git rm --cached <comhad>...” chun an stáitse a dhíchur)"
 
-#: wt-status.c
 msgid "  (use \"git add <file>...\" to mark resolution)"
 msgstr " (bain úsáid as “git add <comhad>...” chun réiteach a mharcáil)"
 
-#: wt-status.c
 msgid "  (use \"git add/rm <file>...\" as appropriate to mark resolution)"
 msgstr ""
 " (bain úsáid \"git add/rm <comhad>...\" de réir mar is cuí chun réiteach a "
 "mharcáil)"
 
-#: wt-status.c
 msgid "  (use \"git rm <file>...\" to mark resolution)"
 msgstr " (bain úsáid as “git rm <comhad>...” chun réiteach a mharcáil)"
 
-#: wt-status.c
 msgid "Changes to be committed:"
 msgstr "Athruithe atá le déanamh:"
 
-#: wt-status.c
 msgid "Changes not staged for commit:"
 msgstr "Athruithe nach ndearnadh a chur ar stáitse le haghaidh tiomantais:"
 
-#: wt-status.c
 msgid "  (use \"git add <file>...\" to update what will be committed)"
 msgstr ""
 "  (bain úsáid as “git add <comhad>...” chun an méid a bheidh tiomanta a "
 "nuashonrú)"
 
-#: wt-status.c
 msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
 msgstr ""
 "  (bain úsáid as “git add/rm <comhad>...” chun an méid a bheidh tiomanta a "
 "nuashonrú)"
 
-#: wt-status.c
 msgid ""
 "  (use \"git restore <file>...\" to discard changes in working directory)"
 msgstr ""
 " (bain úsáid as “git restore <comhad>...” chun athruithe ar eolaire oibre a "
 "dhiúscairt)"
 
-#: wt-status.c
 msgid "  (commit or discard the untracked or modified content in submodules)"
 msgstr ""
 " (an t-ábhar neamhrianaithe nó modhnaithe i bhfo-mhodúil a thiomsú nó a "
 "dhiúscairt)"
 
-#: wt-status.c
 #, c-format
 msgid "  (use \"git %s <file>...\" to include in what will be committed)"
 msgstr ""
 " (bain úsáid as “git %s <comhad>...” chun an méid a bheidh tiomanta san "
 "áireamh)"
 
-#: wt-status.c
 msgid "both deleted:"
 msgstr "scriosta an dá cheann:"
 
-#: wt-status.c
 msgid "added by us:"
 msgstr "curtha leis againn:"
 
-#: wt-status.c
 msgid "deleted by them:"
 msgstr "scriosta ag siad:"
 
-#: wt-status.c
 msgid "added by them:"
 msgstr "a chuir siad leis:"
 
-#: wt-status.c
 msgid "deleted by us:"
 msgstr "scriosta againn:"
 
-#: wt-status.c
 msgid "both added:"
 msgstr "chuir an bheirt leis:"
 
-#: wt-status.c
 msgid "both modified:"
 msgstr "an dá cheann modhnaithe:"
 
-#: wt-status.c
 msgid "new file:"
 msgstr "comhad nua:"
 
-#: wt-status.c
 msgid "copied:"
 msgstr "cóipeáilte:"
 
-#: wt-status.c
 msgid "deleted:"
 msgstr "scriosta:"
 
-#: wt-status.c
 msgid "modified:"
 msgstr "modhnaithe:"
 
-#: wt-status.c
 msgid "renamed:"
 msgstr "athainmnithe:"
 
-#: wt-status.c
 msgid "typechange:"
 msgstr "cineál cineál:"
 
-#: wt-status.c
 msgid "unknown:"
 msgstr "anaithnid:"
 
-#: wt-status.c
 msgid "unmerged:"
 msgstr "gan chumasc:"
 
-#: wt-status.c
 msgid "new commits, "
 msgstr "tiomantais nua, "
 
-#: wt-status.c
 msgid "modified content, "
 msgstr "ábhar modhnaithe, "
 
-#: wt-status.c
 msgid "untracked content, "
 msgstr "ábhar neamhrianaithe, "
 
-#: wt-status.c
 #, c-format
 msgid "Your stash currently has %d entry"
 msgid_plural "Your stash currently has %d entries"
@@ -28814,15 +24225,12 @@
 msgstr[1] "Tá %d iontrálacha ar do stash faoi láthair"
 msgstr[2] "Tá %d iontrálacha ar do stash faoi láthair"
 
-#: wt-status.c
 msgid "Submodules changed but not updated:"
 msgstr "Fo-mhodúil athraithe ach gan nuashonrú:"
 
-#: wt-status.c
 msgid "Submodule changes to be committed:"
 msgstr "Athruithe fo-mhodúil atá le tiomantas:"
 
-#: wt-status.c
 msgid ""
 "Do not modify or remove the line above.\n"
 "Everything below it will be ignored."
@@ -28830,7 +24238,6 @@
 "Ná déan an líne thuas a mhodhnú ná a bhaint.\n"
 "Déanfar neamhaird ar gach rud thíos é."
 
-#: wt-status.c
 #, c-format
 msgid ""
 "\n"
@@ -28842,64 +24249,50 @@
 "ríomh.\n"
 "Is féidir leat '--no-ahead-behind' a úsáid chun seo a sheachaint.\n"
 
-#: wt-status.c
 msgid "You have unmerged paths."
 msgstr "Tá cosáin neamh-chumasaithe agat."
 
-#: wt-status.c
 msgid "  (fix conflicts and run \"git commit\")"
 msgstr " (coinbhleachtaí a shocrú agus reáchtáil “git commit”)"
 
-#: wt-status.c
 msgid "  (use \"git merge --abort\" to abort the merge)"
 msgstr ""
 " (bain úsáid as “git merge --abort” chun an cumaisc a chur ar deireadh)"
 
-#: wt-status.c
 msgid "All conflicts fixed but you are still merging."
 msgstr "Socraíodh gach coinbhleacht ach tá tú fós ag cumasc."
 
-#: wt-status.c
 msgid "  (use \"git commit\" to conclude merge)"
 msgstr "  (bain úsáid as “git commit” chun cumasc a thabhairt i gcrích)"
 
-#: wt-status.c
 msgid "You are in the middle of an am session."
 msgstr "Tá tú i lár seisiún am."
 
-#: wt-status.c
 msgid "The current patch is empty."
 msgstr "Tá an paiste reatha folamh."
 
-#: wt-status.c
 msgid "  (fix conflicts and then run \"git am --continue\")"
 msgstr "  (déan coinbhleachtaí a shocrú agus ansin rith “git am --continue”)"
 
-#: wt-status.c
 msgid "  (use \"git am --skip\" to skip this patch)"
 msgstr " (bain úsáid as “git am --skip” chun an paiste seo a scipeáil)"
 
-#: wt-status.c
 msgid ""
 "  (use \"git am --allow-empty\" to record this patch as an empty commit)"
 msgstr ""
 " (bain úsáid as “git am --allow-empty” chun an paiste seo a thaifeadadh mar "
 "thiomantas folamh)"
 
-#: wt-status.c
 msgid "  (use \"git am --abort\" to restore the original branch)"
 msgstr ""
 " (bain úsáid as “git am --abort” chun an bhrainse bunaidh a chur ar ais)"
 
-#: wt-status.c
 msgid "git-rebase-todo is missing."
 msgstr "tá git-rebase-todo ar iarraidh."
 
-#: wt-status.c
 msgid "No commands done."
 msgstr "Níl aon orduithe déanta."
 
-#: wt-status.c
 #, c-format
 msgid "Last command done (%<PRIuMAX> command done):"
 msgid_plural "Last commands done (%<PRIuMAX> commands done):"
@@ -28907,16 +24300,13 @@
 msgstr[1] "Na chéad orduithe eile le déanamh (%<PRIuMAX> orduithe atá fágtha):"
 msgstr[2] "Na chéad orduithe eile le déanamh (%<PRIuMAX> orduithe atá fágtha):"
 
-#: wt-status.c
 #, c-format
 msgid "  (see more in file %s)"
 msgstr " (féach tuilleadh i gcomhad %s)"
 
-#: wt-status.c
 msgid "No commands remaining."
 msgstr "Níl aon orduithe fágtha."
 
-#: wt-status.c
 #, c-format
 msgid "Next command to do (%<PRIuMAX> remaining command):"
 msgid_plural "Next commands to do (%<PRIuMAX> remaining commands):"
@@ -28924,40 +24314,32 @@
 msgstr[1] "Na chéad orduithe eile le déanamh (%<PRIuMAX> orduithe atá fágtha):"
 msgstr[2] "Na chéad orduithe eile le déanamh (%<PRIuMAX> orduithe atá fágtha):"
 
-#: wt-status.c
 msgid "  (use \"git rebase --edit-todo\" to view and edit)"
 msgstr ""
 " (bain úsáid as “git rebase --edit-todo” chun féachaint agus eagar a chur in "
 "eagar)"
 
-#: wt-status.c
 #, c-format
 msgid "You are currently rebasing branch '%s' on '%s'."
 msgstr "Tá tú ag athbhunú brainse '%s' faoi láthair ar '%s'."
 
-#: wt-status.c
 msgid "You are currently rebasing."
 msgstr "Tá tú ag athbhunú faoi láthair."
 
-#: wt-status.c
 msgid "  (fix conflicts and then run \"git rebase --continue\")"
 msgstr ""
 " (déan coinbhleachtaí a shocrú agus ansin rith “git rebase --continue”)"
 
-#: wt-status.c
 msgid "  (use \"git rebase --skip\" to skip this patch)"
 msgstr " (bain úsáid as “git rebase --skip” chun an paiste seo a scipeáil)"
 
-#: wt-status.c
 msgid "  (use \"git rebase --abort\" to check out the original branch)"
 msgstr ""
 " (bain úsáid as “git rebase --abort” chun an bhrainse bunaidh a sheiceáil)"
 
-#: wt-status.c
 msgid "  (all conflicts fixed: run \"git rebase --continue\")"
 msgstr " (gach coinbhleacht socraithe: reáchtáil “git rebase --continue”)"
 
-#: wt-status.c
 #, c-format
 msgid ""
 "You are currently splitting a commit while rebasing branch '%s' on '%s'."
@@ -28965,164 +24347,128 @@
 "Tá tiomantas á roinnt agat faoi láthair agus tú ag athbhunú brainse '%s' ar "
 "'%s'."
 
-#: wt-status.c
 msgid "You are currently splitting a commit during a rebase."
 msgstr "Tá tú ag roinnt tiomantas faoi láthair le linn athbhunaithe."
 
-#: wt-status.c
 msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
 msgstr ""
 " (Nuair a bheidh d'eolaire oibre glan, reáchtáil “git rebase --continue”)"
 
-#: wt-status.c
 #, c-format
 msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
 msgstr ""
 "Tá tú ag eagarthóireacht faoi láthair agus tú ag athbhunú brainse '%s' ar "
 "'%s'."
 
-#: wt-status.c
 msgid "You are currently editing a commit during a rebase."
 msgstr "Tá tú ag eagarthóireacht tiomanta faoi láthair le linn athbhunaithe."
 
-#: wt-status.c
 msgid "  (use \"git commit --amend\" to amend the current commit)"
 msgstr " (bain úsáid as “git commit --amend” chun an tiomantas reatha a leasú)"
 
-#: wt-status.c
 msgid ""
 "  (use \"git rebase --continue\" once you are satisfied with your changes)"
 msgstr ""
 " (bain úsáid as “git rebase --continue” nuair a bheidh tú sásta le "
 "d'athruithe)"
 
-#: wt-status.c
 msgid "Cherry-pick currently in progress."
 msgstr "Cherry-pick atá ar siúl faoi láthair."
 
-#: wt-status.c
 #, c-format
 msgid "You are currently cherry-picking commit %s."
 msgstr "Tá tiomantas %s ag piocadh silíní faoi láthair."
 
-#: wt-status.c
 msgid "  (fix conflicts and run \"git cherry-pick --continue\")"
 msgstr " (coinbhleachtaí a shocrú agus reáchtáil “git cherry-pick --continue”)"
 
-#: wt-status.c
 msgid "  (run \"git cherry-pick --continue\" to continue)"
 msgstr " (reáchtáil “git cherry-pick --continue ” chun leanúint ar aghaidh)"
 
-#: wt-status.c
 msgid "  (all conflicts fixed: run \"git cherry-pick --continue\")"
 msgstr " (gach coinbhleacht socraithe: reáchtáil “git cherry-pick --continue”)"
 
-#: wt-status.c
 msgid "  (use \"git cherry-pick --skip\" to skip this patch)"
 msgstr ""
 " (bain úsáid as “git cherry-pick --skip” chun an paiste seo a scipeáil)"
 
-#: wt-status.c
 msgid "  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
 msgstr ""
 " (bain úsáid as “git cherry-pick --abort” chun an oibríocht pioc silíní a "
 "chealú)"
 
-#: wt-status.c
 msgid "Revert currently in progress."
 msgstr "Ar ais atá ar siúl faoi láthair."
 
-#: wt-status.c
 #, c-format
 msgid "You are currently reverting commit %s."
 msgstr "Tá tiomantas %s á chur ar ais faoi láthair."
 
-#: wt-status.c
 msgid "  (fix conflicts and run \"git revert --continue\")"
 msgstr " (déan coinbhleachtaí a shocrú agus rith “git revert --continue”)"
 
-#: wt-status.c
 msgid "  (run \"git revert --continue\" to continue)"
 msgstr " (reáchtáil “git revert --continue” chun leanúint ar aghaidh)"
 
-#: wt-status.c
 msgid "  (all conflicts fixed: run \"git revert --continue\")"
 msgstr " (gach coinbhleacht socraithe: reáchtáil “git revert --continue”)"
 
-#: wt-status.c
 msgid "  (use \"git revert --skip\" to skip this patch)"
 msgstr " (bain úsáid as “git revert --skip” chun an paiste seo a scipeáil)"
 
-#: wt-status.c
 msgid "  (use \"git revert --abort\" to cancel the revert operation)"
 msgstr ""
 " (bain úsáid as “git revert --abort” chun an oibríocht aisghabhála a chealú)"
 
-#: wt-status.c
 #, c-format
 msgid "You are currently bisecting, started from branch '%s'."
 msgstr "Tá tú ag déileáil faoi láthair, tosaigh tú ó bhrainse '%s'."
 
-#: wt-status.c
 msgid "You are currently bisecting."
 msgstr "Tá tú ag déileáil faoi láthair."
 
-#: wt-status.c
 msgid "  (use \"git bisect reset\" to get back to the original branch)"
 msgstr ""
 " (bain úsáid as “git bisect reset” chun filleadh ar an mbrainse bunaidh)"
 
-#: wt-status.c
 msgid "You are in a sparse checkout."
 msgstr "Tá tú i seiceáil neamhchoitianta."
 
-#: wt-status.c
 #, c-format
 msgid "You are in a sparse checkout with %d%% of tracked files present."
 msgstr ""
 "Tá tú i seiceáil neamhchoitianta le %d%% de na comhaid rianaithe i láthair."
 
-#: wt-status.c
 msgid "On branch "
 msgstr "Ar bhrainse "
 
-#: wt-status.c
 msgid "interactive rebase in progress; onto "
 msgstr "athbhunú idirghníomhach atá ar siúl; ar "
 
-#: wt-status.c
 msgid "rebase in progress; onto "
 msgstr "athbhunú atá ar siúl; ar "
 
-#: wt-status.c
 msgid "HEAD detached at "
 msgstr "HEAD scoite ag "
 
-#: wt-status.c
 msgid "HEAD detached from "
 msgstr "CEANN scartha ó "
 
-#: wt-status.c
 msgid "Not currently on any branch."
 msgstr "Níl sé ar aon bhrainse faoi láthair."
 
-#: wt-status.c
 msgid "Initial commit"
 msgstr "Tiomantas tosaigh"
 
-#: wt-status.c
 msgid "No commits yet"
 msgstr "Níl aon gealltanais fós"
 
-#: wt-status.c
 msgid "Untracked files"
 msgstr "Comhaid neamhrianaithe"
 
-#: wt-status.c
 msgid "Ignored files"
 msgstr "Comhaid neamhaird"
 
-#: wt-status.c
 #, c-format
 msgid ""
 "It took %.2f seconds to enumerate untracked files,\n"
@@ -29132,43 +24478,35 @@
 "ach cuireadh na torthaí a chosc, agus d'fhéadfadh rith ina dhiaidh sin a "
 "bheith níos gasta."
 
-#: wt-status.c
 #, c-format
 msgid "It took %.2f seconds to enumerate untracked files."
 msgstr "Thóg sé %.2f soicind comhaid gan rianú a áireamh."
 
-#: wt-status.c
 msgid "See 'git help status' for information on how to improve this."
 msgstr ""
 "Féach 'git help status' le haghaidh faisnéise maidir le conas é seo a "
 "fheabhsú."
 
-#: wt-status.c
 #, c-format
 msgid "Untracked files not listed%s"
 msgstr "Comhaid neamhrianaithe nár liostaíodh %s"
 
-#: wt-status.c
 msgid " (use -u option to show untracked files)"
 msgstr " (bain úsáid as an rogha -u chun comhaid neamhrianaithe a thaispeáint)"
 
-#: wt-status.c
 msgid "No changes"
 msgstr "Gan aon athruithe"
 
-#: wt-status.c
 #, c-format
 msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
 msgstr ""
 "níl aon athruithe curtha le tiomantas (bain úsáid as “git add” agus/nó “git "
 "commit -a”)\n"
 
-#: wt-status.c
 #, c-format
 msgid "no changes added to commit\n"
 msgstr "níl aon athruithe curtha le tiomantas\n"
 
-#: wt-status.c
 #, c-format
 msgid ""
 "nothing added to commit but untracked files present (use \"git add\" to "
@@ -29177,76 +24515,61 @@
 "ní chuirtear aon rud le tiomantas ach comhaid neamhrianaithe i láthair (bain "
 "úsáid as “git add” chun rianú)\n"
 
-#: wt-status.c
 #, c-format
 msgid "nothing added to commit but untracked files present\n"
 msgstr "ní chuir aon rud le tiomantas ach comhaid neamhrianaithe i láthair\n"
 
-#: wt-status.c
 #, c-format
 msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
 msgstr ""
 "aon rud le tiomantas (comhaid a chruthú/cóipeáil agus bain úsáid as “git "
 "add” chun rianú)\n"
 
-#: wt-status.c
 #, c-format
 msgid "nothing to commit\n"
 msgstr "aon rud le tiomantas\n"
 
-#: wt-status.c
 #, c-format
 msgid "nothing to commit (use -u to show untracked files)\n"
 msgstr ""
 "aon rud le tiomantas (bain úsáid as -u chun comhaid neamhrianaithe a "
 "thaispeáint)\n"
 
-#: wt-status.c
 #, c-format
 msgid "nothing to commit, working tree clean\n"
 msgstr "aon rud le tiomantas, crann oibre glan\n"
 
-#: wt-status.c
 msgid "No commits yet on "
 msgstr "Níl aon gealltanas ar aghaidh go fóill "
 
-#: wt-status.c
 msgid "HEAD (no branch)"
 msgstr "CEAD (gan aon bhrainse)"
 
-#: wt-status.c
 msgid "different"
 msgstr "difriúil"
 
-#: wt-status.c
 msgid "behind "
 msgstr "taobh thiar "
 
-#: wt-status.c
 msgid "ahead "
 msgstr "chun tosaigh "
 
 #. TRANSLATORS: the action is e.g. "pull with rebase"
-#: wt-status.c
 #, c-format
 msgid "cannot %s: You have unstaged changes."
 msgstr "ní féidir %s: Tá athruithe gan stáitse agat."
 
-#: wt-status.c
 msgid "additionally, your index contains uncommitted changes."
 msgstr "ina theannta sin, tá athruithe neamhthiomanta i d'innéacs."
 
-#: wt-status.c
 #, c-format
 msgid "cannot %s: Your index contains uncommitted changes."
 msgstr "ní féidir %s: Tá athruithe neamhthiomanta ag d'innéacs."
 
-#: xdiff-interface.c
 #, c-format
 msgid "unknown style '%s' given for '%s'"
 msgstr "stíl anaithnid '%s' a thugtar do '%s'"
 
-#: git-merge-octopus.sh git-merge-resolve.sh
 msgid ""
 "Error: Your local changes to the following files would be overwritten by "
 "merge"
@@ -29254,119 +24577,94 @@
 "Earráid: Déanfaí d'athruithe áitiúla ar na comhaid seo a leanas a "
 "fhorscríobh trí chumasc"
 
-#: git-merge-octopus.sh
 msgid "Automated merge did not work."
 msgstr "Níor oibrigh cumaisc uathoibrithe."
 
-#: git-merge-octopus.sh
 msgid "Should not be doing an octopus."
 msgstr "Níor chóir go mbeadh sé ag déanamh ochtair."
 
-#: git-merge-octopus.sh
 #, sh-format
 msgid "Unable to find common commit with $pretty_name"
 msgstr "Ní féidir tiomantas coiteann a fháil le $pretty_name"
 
-#: git-merge-octopus.sh
 #, sh-format
 msgid "Already up to date with $pretty_name"
 msgstr "Cothrom le dáta cheana féin le $pretty_name"
 
-#: git-merge-octopus.sh
 #, sh-format
 msgid "Fast-forwarding to: $pretty_name"
 msgstr "Seoladh go tapa chuig: $pretty_name"
 
-#: git-merge-octopus.sh
 #, sh-format
 msgid "Trying simple merge with $pretty_name"
 msgstr "Ag iarraidh cumasc simplí le $pretty_name"
 
-#: git-merge-octopus.sh
 msgid "Simple merge did not work, trying automatic merge."
 msgstr ""
 "Níor oibrigh an cumasc simplí, táim ag iarraidh cumasc uathoibríoch a "
 "dhéanamh."
 
-#: git-sh-setup.sh
 #, sh-format
 msgid "usage: $dashless $USAGE"
 msgstr "úsáid: $dashless $USAGE"
 
-#: git-sh-setup.sh
 #, sh-format
 msgid "Cannot chdir to $cdup, the toplevel of the working tree"
 msgstr "Ní féidir a chdir go $cdup, barr an chrainn oibre"
 
-#: git-sh-setup.sh
 #, sh-format
 msgid "fatal: $program_name cannot be used without a working tree."
 msgstr "marfach: ní féidir $program_name a úsáid gan crann oibre."
 
-#: git-sh-setup.sh
 msgid "Cannot rewrite branches: You have unstaged changes."
 msgstr "Ní féidir brainsí a athscríobh: Tá athruithe gan stáitse agat."
 
-#: git-sh-setup.sh
 #, sh-format
 msgid "Cannot $action: You have unstaged changes."
 msgstr "Ní féidir $action: Tá athruithe gan stáitse agat."
 
-#: git-sh-setup.sh
 #, sh-format
 msgid "Cannot $action: Your index contains uncommitted changes."
 msgstr "Ní féidir $action: Tá athruithe neamhthiomanta i d'innéacs."
 
-#: git-sh-setup.sh
 msgid "Additionally, your index contains uncommitted changes."
 msgstr "Ina theannta sin, tá athruithe neamhthiomanta i d'innéacs."
 
-#: git-sh-setup.sh
 msgid "You need to run this command from the toplevel of the working tree."
 msgstr "Ní mór duit an t-ordú seo a reáchtáil ó bharr an chrainn oibre."
 
-#: git-sh-setup.sh
 msgid "Unable to determine absolute path of git directory"
 msgstr "Ní féidir cosán iomlán eolaire git a chinneadh"
 
-#: git-send-email.perl
 msgid "local zone differs from GMT by a non-minute interval\n"
 msgstr "tá eatramh neamh-nóiméid difriúil ón gcrios áitiúil\n"
 
-#: git-send-email.perl
 msgid "local time offset greater than or equal to 24 hours\n"
 msgstr ""
 "fritháireamh ama áitiúil atá níos mó ná nó cothrom le 24 uair an chloig\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "fatal: command '%s' died with exit code %d"
 msgstr "marfach: fuair an t-ordú '%s' bás le cód imeachta %d"
 
-#: git-send-email.perl
 msgid "the editor exited uncleanly, aborting everything"
 msgstr "d’imigh an t-eagarthóir go neamhghlan, ag cur deireadh le gach rud"
 
-#: git-send-email.perl
 #, perl-format
 msgid ""
 "'%s' contains an intermediate version of the email you were composing.\n"
 msgstr "Tá leagan idirmheánach den ríomhphost a bhí á scríobh agat i '%s'.\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "'%s.final' contains the composed email.\n"
 msgstr "Cuimsíonn '%s.final' an ríomhphost comhdhéanta.\n"
 
-#: git-send-email.perl
 msgid "--dump-aliases incompatible with other options\n"
 msgstr "--dump-aliases neamhoiriúnach le roghanna eile\n"
 
-#: git-send-email.perl
 msgid "--dump-aliases and --translate-aliases are mutually exclusive\n"
 msgstr "Tá --dump-aliases agus --translate-aliases frithpháirteach\n"
 
-#: git-send-email.perl
 msgid ""
 "fatal: found configuration options for 'sendmail'\n"
 "git-send-email is configured with the sendemail.* options - note the 'e'.\n"
@@ -29378,11 +24676,9 @@
 "Socraigh sendemail.forbidSendmailVariables go bréagach chun an seiceáil seo "
 "a dhíchumasú.\n"
 
-#: git-send-email.perl
 msgid "Cannot run git format-patch from outside a repository\n"
 msgstr "Ní féidir git format-patch a rith ó lasmuigh de stórlann\n"
 
-#: git-send-email.perl
 msgid ""
 "`batch-size` and `relogin` must be specified together (via command-line or "
 "configuration option)\n"
@@ -29390,37 +24686,30 @@
 "Caithfear `méid baisce' agus `athlogán' a shonrú le chéile (trí líne "
 "ordaithe nó rogha cumraíochta)\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Unknown --suppress-cc field: '%s'\n"
 msgstr "Réimse anaithnid --suppress-cc: '%s'\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Unknown --confirm setting: '%s'\n"
 msgstr "Socrú --confirm anaithnid: '%s'\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "warning: sendmail alias with quotes is not supported: %s\n"
 msgstr "rabhadh: ní thacaítear le alias sendmail le luachana: %s\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "warning: `:include:` not supported: %s\n"
 msgstr "rabhadh: `:include: `níl tacaíocht: %s\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "warning: `/file` or `|pipe` redirection not supported: %s\n"
 msgstr "rabhadh: Ní thacaítear le hathreorú `/comhad` nó `|píopa`: %s\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "warning: sendmail line is not recognized: %s\n"
 msgstr "rabhadh: ní aithnítear líne sendmail: %s\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid ""
 "File '%s' exists but it could also be the range of commits\n"
@@ -29437,12 +24726,10 @@
 "    * Ag rá”. /%s” má tá comhad i gceist agat; nó\n"
 "    * Rogha --format-patch a thabhairt má tá raon i gceist agat.\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Failed to opendir %s: %s"
 msgstr "Theip ar %s a oscailt: %s"
 
-#: git-send-email.perl
 msgid ""
 "\n"
 "No patch files specified!\n"
@@ -29452,17 +24739,14 @@
 "Níl aon chomhaid paiste sonraithe!\n"
 "\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "No subject line in %s?"
 msgstr "Níl aon líne ábhair i %s?"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Failed to open for writing %s: %s"
 msgstr "Theip ar oscailt le haghaidh scríbhneoireachta %s: %s"
 
-#: git-send-email.perl
 msgid ""
 "Lines beginning in \"GIT:\" will be removed.\n"
 "Consider including an overall diffstat or table of contents\n"
@@ -29476,27 +24760,22 @@
 "\n"
 "Glan ábhar an choirp mura dteastaíonn uait achoimre a sheoladh.\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Failed to open %s.final: %s"
 msgstr "Theip ar %s.final a oscailt: %s"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Failed to open %s: %s"
 msgstr "Theip ar %s a oscailt: %s"
 
-#: git-send-email.perl
 msgid "Summary email is empty, skipping it\n"
 msgstr "Tá ríomhphost achoimre folamh, ag scipeáil é\n"
 
 #. TRANSLATORS: please keep [y/N] as is.
-#: git-send-email.perl
 #, perl-format
 msgid "Are you sure you want to use <%s> [y/N]? "
 msgstr "An bhfuil tú cinnte gur mhaith leat <%s> [Y/n] a úsáid? "
 
-#: git-send-email.perl
 msgid ""
 "The following files are 8bit, but do not declare a Content-Transfer-"
 "Encoding.\n"
@@ -29504,11 +24783,9 @@
 "Is iad na comhaid seo a leanas 8bit, ach ná dearbhaíonn siad Ionchódú "
 "Aistrithe Ábhar.\n"
 
-#: git-send-email.perl
 msgid "Which 8bit encoding should I declare [UTF-8]? "
 msgstr "Cén ionchódú 8 giotán ba chóir dom a dhearbhú [UTF-8]? "
 
-#: git-send-email.perl
 #, perl-format
 msgid ""
 "Refusing to send because the patch\n"
@@ -29521,22 +24798,18 @@
 "tá an teimpléad faoi réir an ábhair '*** ÁBHAR ANSEO ***'. Pasáil --force "
 "más mian leat a sheoladh i ndáiríre.\n"
 
-#: git-send-email.perl
 msgid "To whom should the emails be sent (if anyone)?"
 msgstr "Cé chuige ba chóir na ríomhphoist a sheoladh (más duine ar bith)?"
 
-#: git-send-email.perl
 #, perl-format
 msgid "fatal: alias '%s' expands to itself\n"
 msgstr "marfach: leathnaíonn alias '%s' chuige féin\n"
 
-#: git-send-email.perl
 msgid "Message-ID to be used as In-Reply-To for the first email (if any)? "
 msgstr ""
 "Aitheantas an Teachtaireachta le húsáid mar In-Reply-To don chéad ríomhphost "
 "(más ann dó)? "
 
-#: git-send-email.perl
 #, perl-format
 msgid "error: unable to extract a valid address from: %s\n"
 msgstr "earráid: ní féidir seoladh bailí a bhaint as: %s\n"
@@ -29544,16 +24817,13 @@
 #. TRANSLATORS: Make sure to include [q] [d] [e] in your
 #. translation. The program will only accept English input
 #. at this point.
-#: git-send-email.perl
 msgid "What to do with this address? ([q]uit|[d]rop|[e]dit): "
 msgstr "Cad atá le déanamh leis an seoladh seo? ([q]uit|[d]rop|[e]dit): "
 
-#: git-send-email.perl
 #, perl-format
 msgid "CA path \"%s\" does not exist"
 msgstr "Níl cosán CA “%s” ann"
 
-#: git-send-email.perl
 msgid ""
 "    The Cc list above has been expanded by additional\n"
 "    addresses found in the patch commit message. By default\n"
@@ -29582,132 +24852,112 @@
 #. TRANSLATORS: Make sure to include [y] [n] [e] [q] [a] in your
 #. translation. The program will only accept English input
 #. at this point.
-#: git-send-email.perl
 msgid "Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): "
 msgstr ""
 "An bhfuil tú ag iarraidh an ríomhphost seo a sheoladh? ([y]es|[n]o|[e]dit|"
 "[q]uit|[a]ll): "
 
-#: git-send-email.perl
 msgid "Send this email reply required"
 msgstr "Seol an freagra ríomhphoist riachtanach"
 
-#: git-send-email.perl
+msgid "The destination IMAP folder is not properly defined."
+msgstr "Níl an fillteán IMAP ceann scríbe sainmhínithe i gceart."
+
 msgid "The required SMTP server is not properly defined."
 msgstr "Níl an freastalaí SMTP riachtanach sainmhínithe i gceart."
 
-#: git-send-email.perl
 #, perl-format
 msgid "Server does not support STARTTLS! %s"
 msgstr "Ní thacaíonn freastalaí le STARTTLS! %s"
 
-#: git-send-email.perl
 #, perl-format
 msgid "STARTTLS failed! %s"
 msgstr "Theip ar STARTTLS! %s"
 
-#: git-send-email.perl
 msgid "Unable to initialize SMTP properly. Check config and use --smtp-debug."
 msgstr ""
 "Ní féidir SMTP a thionscnamh i gceart. Seiceáil configí agus bain úsáid as --"
 "smtp-debug."
 
-#: git-send-email.perl
 #, perl-format
 msgid "Outlook reassigned Message-ID to: %s\n"
 msgstr "Athshannaigh Outlook ID teachtaireachta chuig: %s\n"
 
-#: git-send-email.perl
 msgid "Warning: Could not retrieve Message-ID from server response.\n"
 msgstr ""
 "Rabhadh: Ní fhéadfaí teachtaireachtaí ID a aisghabháil ó fhreagairt "
 "freastalaí.\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Failed to send %s\n"
 msgstr "Theip ar %s a sheoladh\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Dry-Sent %s"
 msgstr "Seoladh tirim %s"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Sent %s"
 msgstr "Seoladh %s"
 
-#: git-send-email.perl
 msgid "Dry-OK. Log says:"
 msgstr "Tirim-ceart go leor. Log deir:"
 
-#: git-send-email.perl
 msgid "OK. Log says:"
 msgstr "CEART GO LEOR. Log deir:"
 
-#: git-send-email.perl
 msgid "Result: "
 msgstr "Toradh: "
 
-#: git-send-email.perl
 msgid "Result: OK"
 msgstr "Toradh: Ceart go leor"
 
-#: git-send-email.perl
 #, perl-format
 msgid "can't open file %s"
 msgstr "ní féidir comhad %s a oscailt"
 
-#: git-send-email.perl
 #, perl-format
 msgid "(mbox) Adding cc: %s from line '%s'\n"
 msgstr "(mbox) Ag cur cc: %s ó líne '%s'\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "(mbox) Adding to: %s from line '%s'\n"
 msgstr "(mbox) Ag cur le: %s ó líne '%s'\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "(non-mbox) Adding cc: %s from line '%s'\n"
 msgstr "(non-mbox) Ag cur cc: %s ó líne '%s'\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "(body) Adding cc: %s from line '%s'\n"
 msgstr "(corp) Ag cur cc: %s ó líne '%s'\n"
 
-#: git-send-email.perl
+#, perl-format
+msgid "error: invalid SMTP port '%s'\n"
+msgstr "earráid: port SMTP neamhbhailí '%s'\n"
+
 #, perl-format
 msgid "(%s) Could not execute '%s'"
 msgstr "(%s) Ní raibh '%s' in ann a fhorghníomhú"
 
-#: git-send-email.perl
 #, perl-format
 msgid "(%s) Malformed output from '%s'"
 msgstr "(%s) Aschur mífheidhmithe ó '%s'"
 
-#: git-send-email.perl
 #, perl-format
 msgid "(%s) failed to close pipe to '%s'"
 msgstr "Theip ar (%s) píopa a dhúnadh chuig '%s'"
 
-#: git-send-email.perl
 #, perl-format
 msgid "(%s) Adding %s: %s from: '%s'\n"
 msgstr "(%s) Ag cur %s leis: %s ó: '%s'\n"
 
-#: git-send-email.perl
 msgid "cannot send message as 7bit"
 msgstr "ní féidir teachtaireacht a sheoladh mar 7bit"
 
-#: git-send-email.perl
 msgid "invalid transfer encoding"
 msgstr "ionchódú aistrithe bailí"
 
-#: git-send-email.perl
 #, perl-format
 msgid ""
 "fatal: %s: rejected by %s hook\n"
@@ -29718,12 +24968,10 @@
 "%s\n"
 "rabhadh: níor seoladh aon phaistí\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "unable to open %s: %s\n"
-msgstr "nach féidir %s a oscailt: %s\n"
+msgstr "ní féidir %s a oscailt: %s\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid ""
 "fatal: %s:%d is longer than 998 characters\n"
@@ -29732,17 +24980,104 @@
 "marfach: %s: %d níos faide ná 998 carachtar\n"
 "rabhadh: níor seoladh aon phaistí\n"
 
-#: git-send-email.perl
 #, perl-format
 msgid "Skipping %s with backup suffix '%s'.\n"
-msgstr "Scaipeáil %s le hiarmhír cúltaca '%s'.\n"
+msgstr "Ag scipeáil %s leis an iarmhír chúltaca '%s'.\n"
 
 #. TRANSLATORS: please keep "[y|N]" as is.
-#: git-send-email.perl
 #, perl-format
 msgid "Do you really want to send %s? [y|N]: "
 msgstr "An bhfuil tú ag iarraidh %s a sheoladh i ndáiríre? [y|N]: "
 
+#~ msgid "No previous hunk"
+#~ msgstr "Níl aon hunk roimhe seo"
+
+#~ msgid "No next hunk"
+#~ msgstr "Níl aon chéad hunk eile"
+
+#, c-format
+#~ msgid "   (%s will become dangling)"
+#~ msgstr "   (beidh %s ag crochadh)"
+
+#, c-format
+#~ msgid "   (%s has become dangling)"
+#~ msgstr "   (%s has become dangling)"
+
+#~ msgid "git for-each-ref [<options>] [<pattern>]"
+#~ msgstr "git for-each-ref [<options>] [<pattern>]"
+
+#~ msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
+#~ msgstr "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
+
+#~ msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
+#~ msgstr "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
+
+#~ msgid "use at most one of --auto and --schedule=<frequency>"
+#~ msgstr "bain úsáid as --auto agus --schedule=<frequency> ar a mhéad"
+
+#, c-format
+#~ msgid "Final output: %d %s\n"
+#~ msgstr "Aschur deiridh: %d %s\n"
+
+#, c-format
+#~ msgid "%d (FSCK_IGNORE?) should never trigger this callback"
+#~ msgstr "%d (FSCK_IGNORE?) níor cheart go spreagfadh an t-aisghlaoch seo"
+
+#~ msgid ""
+#~ "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]"
+#~ msgstr ""
+#~ "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]"
+
+#~ msgid ""
+#~ "git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]"
+#~ msgstr ""
+#~ "git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]"
+
+#~ msgid "cannot use --stdin-packs with --cruft"
+#~ msgstr "ní féidir --stdin-packs a úsáid le --cruft"
+
+#~ 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 ""
+#~ "Tá 'git pack-redundant' ainmnithe le baint.\n"
+#~ "Má úsáideann tú an t-ordú seo fós, cuir rogha b\n"
+#~ "hreise, '--i-still-use-this', leis an líne ordaithe \n"
+#~ "agus cuir in iúl dúinn go n-úsáideann tú fós é trí ríomhphost \n"
+#~ "a sheoladh chuig <git@vger.kernel.org>.  Go raibh maith agat.\n"
+
+#~ msgid ""
+#~ "git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--"
+#~ "exclude <pattern>]"
+#~ msgstr ""
+#~ "<pattern><pattern>git pack-refs [--all] [--no-prunes] [--auto] [--"
+#~ "include] [--eisiamh]"
+
+#, c-format
+#~ msgid "deleting '%s' failed"
+#~ msgstr "theip ar '%s' a scriosadh"
+
+#, c-format
+#~ msgid "creating '%s' failed"
+#~ msgstr "theip ar chruthú '%s'"
+
+#, c-format
+#~ msgid "unreachable: invalid reference: %s"
+#~ msgstr "unrochtana: tagairt neamhbhailí: %s"
+
+#, c-format
+#~ msgid "could not open index for %s"
+#~ msgstr "ní raibh in ann innéacs a oscailt do %s"
+
+#~ msgid "trying to write commit not in index"
+#~ msgstr "ag iarraidh tiomantas a scríobh ní in innéacs"
+
+#~ msgid "cannot handle pushes this big"
+#~ msgstr "ní féidir brú mór seo a láimhseáil"
+
 #~ msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>"
 #~ msgstr "git cat-file (-t | -s) [--leis-cineál gan eolas] <object>"
 
diff --git a/po/id.po b/po/id.po
index 470e1c3..b85b11c 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: 2025-08-12 17:01+0000\n"
-"PO-Revision-Date: 2025-08-15 17:33+0700\n"
+"POT-Creation-Date: 2025-11-06 23:58+0000\n"
+"PO-Revision-Date: 2025-11-13 08:58+0700\n"
 "Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n"
 "Language-Team: Indonesian\n"
 "Language: id\n"
@@ -648,28 +648,28 @@
 
 #: add-patch.c
 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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
-"j - biarkan bingkah ini tak diputuskan, lihat bingkah berikutnya yang belum "
-"diputuskan\n"
-"J - biarkan bingkah ini tak diputuskan, lihat bingkah berikutnya\n"
-"k - biarkan bingkah ini tak diputuskan, lihat bingkah sebelumnya yang belum "
-"diputuskan\n"
-"K - biarkan bingkah ini tak diputuskan, lihat bingkah sebelumnya\n"
+"j - pergi ke bingkah yang belum diputuskan selanjutnya, gulung ke bawah\n"
+"J - pergi ke bingkah berikutnya, gulung ke bawah\n"
+"k - pergi ke bingkah yang belum diputuskan sebelumnya, gulung ke atas\n"
+"K - pergi ke bingkah sebelumnya, gulung ke atas\n"
 "g - pilih satu bingkah untuk dikunjungi\n"
 "/ - cari satu bingkah yang cocok dengan regex yang diberikan\n"
 "s - belah bingkah saat ini ke dalam bingkah yang lebih kecil\n"
 "e - sunting bingkah saat ini secara manual\n"
-"p - lihat bingkah saat ini, 'P' untuk menggunakan pager\n"
+"p - lihat bingkah saat ini\n"
+"P - lihat bingkah saat ini menggunakan pager\n"
 "? - lihat bantuan\n"
 
 #: add-patch.c
@@ -678,12 +678,12 @@
 msgstr "Hanya satu huruf yang diharapkan, dapat '%s'"
 
 #: add-patch.c
-msgid "No previous hunk"
-msgstr "Tidak ada bingkah sebelumnya"
+msgid "No other hunk"
+msgstr "Tidak ada bingkah lainnya"
 
 #: add-patch.c
-msgid "No next hunk"
-msgstr "Tidak ada bingkah selanjutnya"
+msgid "No other undecided hunk"
+msgstr "Tidak ada bingkah yang belum diputuskan lainnya"
 
 #: add-patch.c
 msgid "No other hunks to goto"
@@ -936,7 +936,8 @@
 msgstr "tanda kutip tak ditutup"
 
 #: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c
-#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c
+#: builtin/receive-pack.c builtin/refs.c builtin/repo.c builtin/tag.c
+#: t/helper/test-pkt-line.c
 msgid "too many arguments"
 msgstr "terlalu banyak argumen"
 
@@ -1261,7 +1262,7 @@
 msgid "%s has type %o, expected %o"
 msgstr "%s bertipe %o, diharapkan %o"
 
-#: apply.c read-cache.c
+#: apply.c builtin/fast-import.c read-cache.c
 #, c-format
 msgid "invalid path '%s'"
 msgstr "jalur tidak valid '%s'"
@@ -1644,7 +1645,7 @@
 msgid "git archive --remote <repo> [--exec <cmd>] --list"
 msgstr "git archive --remote <repo> [--exec <perintah>] --list"
 
-#: archive.c builtin/gc.c builtin/notes.c builtin/tag.c
+#: archive.c builtin/fast-import.c builtin/gc.c builtin/notes.c builtin/tag.c
 #, c-format
 msgid "cannot read '%s'"
 msgstr "tidak dapat membaca '%s'"
@@ -2005,9 +2006,9 @@
 msgstr ""
 "--reverse dan --first-parent bersama-sama butuh komit terbaru yang disebutkan"
 
-#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c
-#: remote.c sequencer.c submodule.c
+#: blame.c builtin/bisect.c builtin/commit.c builtin/fast-export.c
+#: builtin/log.c builtin/merge.c builtin/pack-objects.c builtin/shortlog.c
+#: midx-write.c pack-bitmap.c remote.c sequencer.c submodule.c
 msgid "revision walk setup failed"
 msgstr "persiapan jalan revisi gagal"
 
@@ -2260,7 +2261,7 @@
 
 #: builtin/add.c builtin/clean.c builtin/fetch.c builtin/mv.c
 #: builtin/prune-packed.c builtin/pull.c builtin/push.c builtin/remote.c
-#: builtin/rm.c builtin/send-pack.c
+#: builtin/rm.c builtin/send-pack.c builtin/sparse-checkout.c
 msgid "dry run"
 msgstr "latihan"
 
@@ -2418,8 +2419,8 @@
 msgstr "tindakan jelek '%s' untuk '%s'"
 
 #: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c builtin/revert.c diff-merges.c environment.c gpg-interface.c
-#: ls-refs.c parallel-checkout.c sequencer.c setup.c
+#: builtin/pull.c builtin/revert.c diff-merges.c diff.c environment.c
+#: gpg-interface.c ls-refs.c parallel-checkout.c sequencer.c setup.c
 #, c-format
 msgid "invalid value for '%s': '%s'"
 msgstr "nilai tidak valid untuk '%s': '%s'"
@@ -2771,7 +2772,8 @@
 #: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c
 #: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c
 #: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c
-#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c
+#: builtin/repo.c builtin/submodule--helper.c builtin/tag.c
+#: builtin/verify-tag.c
 msgid "format"
 msgstr "format"
 
@@ -2918,15 +2920,22 @@
 
 #: builtin/bisect.c
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-(new,bad)=<istilah> --term-(old, good)=<istilah>] "
-"[--no-checkout] [--first-parent] [<jelek> [<bagus>...]] [--] [<jalur>...]"
+"git bisect start [--term-(new,bad)=<istilah baru> --term-(old, "
+"good)=<istilah lama>]\n"
+"[--no-checkout] [--first-parent] [<jelek> [<bagus>...]] [--] [<spek "
+"jalur>...]"
 
 #: builtin/bisect.c
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "git bisect (good|bad) [<revisi>...]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (bad|new|<istilah baru>) [<revisi>]"
+
+#: builtin/bisect.c
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (good|old|<istilah lama>) [<revisi>...]"
 
 #: builtin/bisect.c
 msgid "git bisect skip [(<rev>|<range>)...]"
@@ -4326,7 +4335,7 @@
 msgid "read additional mailmap entries from file"
 msgstr "baca entri mailmap tambahan dari berkas"
 
-#: builtin/check-mailmap.c
+#: builtin/check-mailmap.c builtin/fast-import.c
 msgid "blob"
 msgstr "blob"
 
@@ -4948,12 +4957,12 @@
 "git clean [-d] [-f] [-i] [-n] [-q] [-e <pola>] [-x | -X] [--] [<spek "
 "jalur>...]"
 
-#: builtin/clean.c
+#: builtin/clean.c builtin/sparse-checkout.c
 #, c-format
 msgid "Removing %s\n"
 msgstr "Menghapus %s\n"
 
-#: builtin/clean.c
+#: builtin/clean.c builtin/sparse-checkout.c
 #, c-format
 msgid "Would remove %s\n"
 msgstr "Akan hapus %s\n"
@@ -5077,7 +5086,7 @@
 msgid "do not print names of files removed"
 msgstr "jangan cetak nama berkas yang dihapus"
 
-#: builtin/clean.c
+#: builtin/clean.c builtin/sparse-checkout.c
 msgid "force"
 msgstr "paksa"
 
@@ -5090,8 +5099,8 @@
 msgstr "hapus keseluruhan direktori"
 
 #: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c
-#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c
-#: builtin/show-ref.c ref-filter.h
+#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/show-ref.c
+#: pack-refs.c ref-filter.h
 msgid "pattern"
 msgstr "pola"
 
@@ -6943,6 +6952,16 @@
 
 #: builtin/describe.c
 #, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "tidak dapat mencari blob '%s' pada cabang yang belum lahir"
+
+#: builtin/describe.c
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "blob '%s' tidak dapat dijangkau dari HEAD"
+
+#: builtin/describe.c
+#, c-format
 msgid "describe %s\n"
 msgstr "jelaskan %s\n"
 
@@ -7122,6 +7141,10 @@
 msgid "%s...%s: no merge base"
 msgstr "%s...%s: tidak ada dasar penggabungan"
 
+#: builtin/diff.c setup.c
+msgid "cannot come back to cwd"
+msgstr "tidak dapat kembali ke cwd"
+
 #: builtin/diff.c
 msgid "Not a git repository"
 msgstr "bukan repositori git"
@@ -7262,10 +7285,168 @@
 msgstr "git fast-export [<opsi rev-list>]"
 
 #: builtin/fast-export.c
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "mode %s tidak dikenal: %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "mode tag-of-filtered tidak dikenal: %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "mode pengkodean ulang tidak dikenal: %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not read blob %s"
+msgstr "tidak dapat membaca blob %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "ketidakcocokan oid pada blob %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "tidak dapat menulis blob '%s'"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "status perbandingan '%c' tidak diharapkan untuk %s, %s"
+
+#: builtin/fast-export.c
+msgid "none"
+msgstr "tidak ada"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not find author in commit %s"
+msgstr "tidak dapat menemukan pengarang pada komit %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "tidak dapat menemukan pengkomit pada komit %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
 msgstr ""
-"Kesalahan: Tidak dapat mengekspor tag bersarang kecuali jika --mark-tags "
-"disebutkan."
+"menemukan pengkodean komit-spesifik %.*s pada komit %s; gunakan --"
+"reencode=[yes|no] untuk menanganinya"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr ""
+"menemukan komit bertandatangan %s; gunakan --signed-commits=<mode> untuk "
+"menanganinya"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr "mengekspor %<PRIuMAX> tandatangan untuk komit %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr "mengupas tandatangan dari komit %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+"melewatkan tag %s,\n"
+"karena tag pohon (atau tag dari tag pohon, dsm.) tidak didukung."
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not read tag %s"
+msgstr "tidak dapat membaca tag %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr ""
+"menemukan tag bertandatangan %s; gunakan --signed-tags=<mode> untuk "
+"menanganinya"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "mengekspor tag bertandatangan %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "mengupas tandatangan dari tag %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr ""
+"tag %s mentag objek tak terekspor; gunakan --tag-of-filtered-object=<mode> "
+"untuk menanganinya"
+
+#: builtin/fast-export.c
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr "tidak dapat mengekspor tag bersarang kecuali --mark-tags dirincikan."
+
+#: builtin/fast-export.c
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "tag %s tidak menunjuk kemana-mana?"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "%s: objek yang tak diharapkan bertipe %s, lewati."
+
+#: builtin/fast-export.c
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr "tag menunjuk pada objek yang bertipe yang tidak diharapkan %s, lewati."
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "tidak dapat membuka berkas tanda %s untuk ditulis."
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "tidak dapat menulis berkas tanda %s."
+
+#: builtin/fast-export.c builtin/fast-import.c
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "baris tanda rusak: %s"
+
+#: builtin/fast-export.c builtin/fast-import.c fetch-pack.c
+#, c-format
+msgid "object not found: %s"
+msgstr "object tidak ditemukan: %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "bukan sebuah komit? tidak bisa: %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "object %s already has a mark"
+msgstr "objek %s sudah bertanda"
 
 #: builtin/fast-export.c
 msgid "--anonymize-map token cannot be empty"
@@ -7353,34 +7534,572 @@
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Missing from marks for submodule '%s'"
-msgstr "Kehilangan tanda dari untuk submodul '%s'"
+msgid "can't write crash report %s"
+msgstr "tidak dapat menulis laporan kerusakan %s"
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Missing to marks for submodule '%s'"
-msgstr "Kehilangan tanda ke untuk submodul '%s'"
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "fast-import: membuang laporan kerusakan ke %s\n"
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "Perintah 'mark' diharapkan, dapat %s"
+msgid "mark :%<PRIuMAX> not declared"
+msgstr "tanda :%<PRIuMAX> tidak dirincikan"
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "Perintah 'to' diharapkan, dapat %s"
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "percobaan tidak valid saat membuat cabang duplikat: %s"
 
 #: builtin/fast-import.c
-msgid "Expected format name:filename for submodule rewrite option"
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "nama cabang tidak sesuai dengan standar Git: %s"
+
+#: builtin/fast-import.c
+msgid "internal consistency error creating the index"
+msgstr "galat konsistensi internal saat membuat indeks"
+
+#: builtin/fast-import.c
+msgid "cannot create keep file"
+msgstr "tidak dapat membuat berkas jaga"
+
+#: builtin/fast-import.c
+msgid "failed to write keep file"
+msgstr "gagal menulis berkas jaga"
+
+#: builtin/fast-import.c
+msgid "cannot store pack file"
+msgstr "tidak dapat menyimpan berkas pak"
+
+#: builtin/fast-import.c
+msgid "cannot store index file"
+msgstr "tidak dapat menyimpan berkas indeks"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "gagal mengunjungi ke awal dari '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "Git inti menolak indeks %s"
+
+#: builtin/fast-import.c
+msgid "cannot truncate pack to skip duplicate"
+msgstr "tidak dapat memotong pak untuk melewatkan duplikat"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "EOF pada data (%<PRIuMAX> perintah tersisa):"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "kegagalan deflate yang tidak diharapkan: %d"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a tree: %s"
+msgstr "bukan sebuah pohon: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't load tree %s"
+msgstr "tidak dapat memuat pohon %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "mode rusak di %s"
+
+#: builtin/fast-import.c
+msgid "root cannot be a non-directory"
+msgstr "akar tidak dapat menjadi non-direktori"
+
+#: builtin/fast-import.c
+msgid "empty path component found in input"
+msgstr "komponen jalur kosong ditemukan di masukan"
+
+#: builtin/fast-import.c
+msgid "non-directories cannot have subtrees"
+msgstr "non-direktori tidak dapat mempunyai subpohon"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
+msgstr "menjatuhkan %s karena akan menunjuk pada dirinya sendiri (yaitu ke %s)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "cabang %s kehilangan komit."
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "tidak memperbarui %s (ujung baru %s tidak mempunyai %s)"
+
+#: builtin/fast-import.c builtin/sparse-checkout.c commit-graph.c midx-write.c
+#: sequencer.c
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "tidak dapat membuat direktori utama dari %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "tidak dapat menulis berkas tanda %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "tidak dapat menulis berkas tanda %s: %s"
+
+#: builtin/fast-import.c object-file.c
+#, c-format
+msgid "unable to write file %s"
+msgstr "tidak dapat menulis berkas %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "perintah 'data n' diharapkan, dapat: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "EOF pada data (pengakhir '%s' tidak ditemukan)"
+
+#: builtin/fast-import.c
+msgid "data is too large to use in this context"
+msgstr "data terlalu besar untuk digunakan dalam konteks ini"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "EOF pada data (%lu bita tersisa)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "< hilang di untai identitas: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "spasi hilang sebelum < di untai identitas: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "> hilang di untai identitas: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "spasi hilang setalah > di untai identitas: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "tanggal mentah \"%s\" tidak valid pada identitas: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "tanggal rfc2822 \"%s\" tidak valid pada identitas: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "tanggal di identitas harus 'now': %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "too large fanout (%u)"
+msgstr "kipas keluar terlalu besar (%u)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "failed to remove path %s"
+msgstr "gagal menghapus jalur %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "tidak ada nilai setelah ':' pada tanda: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "sampah setelah tanda: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "spasi hilang setelah tanda: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid %s: %s"
+msgstr "%s tidak valid: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "NUL pada %s: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "sampah setelah %s: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "spasi hilang setelah %s: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "mode rusak: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "referensi data tidak valid: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "spasi hilang setelah SHA1: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "Tautan Git tidak dapat dirincikan 'inline': %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "bukan komit (sebenarnya %s): %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "direktori tidak dapat dirincikan sebagai 'inline': %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "%s not found: %s"
+msgstr "%s tidak ditemukan: %s"
+
+#: builtin/fast-import.c
+msgid "tree"
+msgstr "pohon"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "buakn sebuah %s (sebenarya %s): %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "path %s not in branch"
+msgstr "jalur %s bukan di dalam cabang"
+
+#: builtin/fast-import.c
+msgid "can't add a note on empty branch."
+msgstr "tidak dapat menambahkan catatan pada cabang kosong."
+
+#: builtin/fast-import.c
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr "tanda :%<PRIuMAX> bukan sebuah komit"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "bukan sebuah komit yang valid: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "nama referensi atau ekspresi SHA1 tidak valid: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "bukan sebuah blob (sebenarnya %s): %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "blob not found: %s"
+msgstr "blob tidak ditemukan: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "komit %s rusak"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "tidak dapat membuat caband dari dirinya sendiri: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
 msgstr ""
-"Format nama:nama berkas diharapkan untuk operasi penulisan ulang submodul"
+"format gpgsig: 'gpgsig <algoritma hash> <format tandatangan>' diharapkan, "
+"dapat 'gpgsig %s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "algoritma git hash tidak dikenal di gpgsig: '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "format tandatangan tidak valid pada gpgsig: '%s'"
+
+#: builtin/fast-import.c
+msgid "'unknown' signature format in gpgsig"
+msgstr "format tandatangan 'tidak dikenal' di gpgsig"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr "beberapa %s tandatangan ditemukan, abaikan tandatangan tambahan"
+
+#: builtin/fast-import.c
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr "parse_one_signature() mengembalikan algoritma hash tak dikenal"
+
+#: builtin/fast-import.c
+msgid "expected committer but didn't get one"
+msgstr "pengkomit diharapkan tapi tidak mendapatkannya"
+
+#: builtin/fast-import.c
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr ""
+"menemukan komit bertandatangan; gunakan --signed-commits=<mode> untuk "
+"menanganinya"
+
+#: builtin/fast-import.c
+msgid "stripping a commit signature"
+msgstr "mengupas tandatangan komit"
+
+#: builtin/fast-import.c
+msgid "importing a commit signature verbatim"
+msgstr "mengimpor tandatangan komit secara verbatim"
+
+#: builtin/fast-import.c
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr ""
+"menemukan tag bertandatangan; gunakan --signed-tags=<mode> untuk menanganinya"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr "mengimpor tag secara verbatim untuk tag '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr "mengupas tandatangan tag untuk tag '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "perintah 'from' diharapkan, dapat '%s'"
+
+#: builtin/fast-import.c
+msgid "can't tag an empty branch."
+msgstr "tidak dapat mentag sebuah cabang kosong."
+
+#: builtin/fast-import.c builtin/merge.c
+#, c-format
+msgid "not a valid object: %s"
+msgstr "bukan objek valid: %s"
+
+#: builtin/fast-import.c
+msgid "write to frontend failed"
+msgstr "penulisan ke frontend gagal"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't read object %s"
+msgstr "tidak dapat membaca objek %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "objek %s adalah %s tapi blob diharapkan."
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a mark: %s"
+msgstr "bukan sebuah tanda: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown mark: %s"
+msgstr "tanda tidak dikenal: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "sampah setelah SHA1: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "bukan mirip-pohon: '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't load object %s"
+msgstr "tidak dapat memuat objek %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "SHA1 tidak valid pada tag: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "SHA1 tidak valid pada komit: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing from marks for submodule '%s'"
+msgstr "tanda dari hilang untuk submodul '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing to marks for submodule '%s'"
+msgstr "tanda ke hilang untuk submodul '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after tree-ish: %s"
+msgstr "spasi hilang setelah mirip-pohon: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not in a commit: %s"
+msgstr "bukan di dalam komit: %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "[erintah 'mark' diharapkan, dapat %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "perintah 'to' diharapkan, dapat %s"
+
+#: builtin/fast-import.c
+msgid "only one import-marks command allowed per stream"
+msgstr "hanya satu perintah import-marks yang diperbolehkan per arus"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "argumen --date-format tidak dikenal %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s: argumen harus bilangan bulat non-negatif"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr "--depth tidak dapat melebihi %u"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr "--cat-blob-fd tidak dapat melebihi %d"
+
+#: builtin/fast-import.c
+msgid "expected format name:filename for submodule rewrite option"
+msgstr "format nama:nama berkas diharapkan untuk opsi penulisan ulang submodul"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr "max-pack-size sekarang dalam bita, asumsikan --max-pack-size=%lum"
+
+#: builtin/fast-import.c
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "max-pack-size minimal adalah 1 MiB"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "mode --signed-commits tidak dikenal '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "mode --signed-tags tidak dikenal: '%s'"
 
 #: builtin/fast-import.c
 #, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
 msgstr "fitur '%s' dilarang dalam input tanpa --allow-unsafe-features"
 
+#: builtin/fast-import.c
+#, c-format
+msgid "got feature command '%s' after data command"
+msgstr "dapat perintah fitur '%s' setelah perintah data"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "versi fast-import ini tidak mendukung fitur %s."
+
+#: builtin/fast-import.c
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr "dapat perintah opsi '%s' setelah perintah data"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "versi fast-import ini tidak mendukung opsi: %s"
+
+#: builtin/fast-import.c builtin/merge-recursive.c
+#, c-format
+msgid "unknown option %s"
+msgstr "opsi tidak dikenal %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown option --%s"
+msgstr "opsi tidak dikenal --%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unsupported command: %s"
+msgstr "perintah tidak didukung: %s"
+
+#: builtin/fast-import.c
+msgid "stream ends early"
+msgstr "arus berakhir lebih awal"
+
 #: builtin/fetch-pack.c
 #, c-format
 msgid "Lockfile created but not reported: %s"
@@ -7553,6 +8272,36 @@
 "mematikan peringatan ini sampai remote mengubah HEAD ke yang lain."
 
 #: builtin/fetch.c
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+"Anda berada dalam sistemberkas yang tidak peka huruf besar/kecil, dan\n"
+"remote yang Anda coba untuk diambil ada referensi yang hanya berbeda pada\n"
+"huruf besar/kecil. Tidak mungkin untuk menyimpan referensi tersebut dengan\n"
+"backend 'files'. Anda dapat menerimanya sebagaimana mestinya, yang dimana\n"
+"Anda tidak akan bisa menyimpan semua referensi remote pada disk; atau Anda\n"
+"dapat memindahkan repositori Anda agar menggunakan backend 'reftable'\n"
+"dengan perintah:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Perlu diingat bahwa belum semua implementasi Git mendukung format baru ini.\n"
+"Jadi, jika Anda menggunakan alat selain git untuk mengakses repositori ini,\n"
+"memindahkan ke reftables bisa jadi bukan sebuah opsi untuk Anda.\n"
+
+#: builtin/fetch.c
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -7859,26 +8608,6 @@
 msgstr "berkas untuk dibaca"
 
 #: builtin/for-each-ref.c
-msgid "git for-each-ref [<options>] [<pattern>]"
-msgstr "git for-each-ref [<opsi>] [<pola>]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--points-at <object>]"
-msgstr "git for-each-ref [--points-at <objek>]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr "git for-each-ref [--merged [<komit>]] [--no-merged [<komit>]]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr "git for-each-ref [--contains [<komit>]] [--no-contains [<komit>]]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--start-after <marker>]"
-msgstr "git for-each-ref [--start-after <penanda>]"
-
-#: builtin/for-each-ref.c
 msgid "quote placeholders suitably for shells"
 msgstr "kutip tempat penampung yang sesuai untuk cangkang"
 
@@ -7950,6 +8679,10 @@
 msgid "cannot use --start-after with patterns"
 msgstr "tidak dapat menggunakan --start-after dengan pola"
 
+#: builtin/for-each-ref.c
+msgid "git for-each-ref "
+msgstr "git for-each-ref "
+
 #: builtin/for-each-repo.c
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<konfigurasi> [--] <argumen perintah>"
@@ -8239,7 +8972,7 @@
 msgid "write dangling objects in .git/lost-found"
 msgstr "tulis objek teruntai dalam .git/lost-found"
 
-#: builtin/fsck.c builtin/prune.c
+#: builtin/fsck.c builtin/prune.c builtin/repo.c
 msgid "show progress"
 msgstr "perlihatkan perkembangan"
 
@@ -8546,6 +9279,10 @@
 "melewatkan tugas pengepakan tambahan karena core.multiPackIndex dinonaktifkan"
 
 #: builtin/gc.c
+msgid "failed to perform geometric repack"
+msgstr "gagal melakukan pak ulang geometri"
+
+#: builtin/gc.c
 #, c-format
 msgid "task '%s' failed"
 msgstr "tugas '%s' gagal"
@@ -8557,6 +9294,11 @@
 
 #: builtin/gc.c
 #, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "strategi pemeliharaan tidak dikenal: '%s'"
+
+#: builtin/gc.c
+#, c-format
 msgid "'%s' is not a valid task"
 msgstr "'%s' bukan tugas yang valid"
 
@@ -9659,6 +10401,35 @@
 msgid "no input file given for in-place editing"
 msgstr "tidak ada berkas masukan yang diberikan untuk penyuntingan di tempat"
 
+#: builtin/last-modified.c
+msgid "last-modified can only operate on one tree at a time"
+msgstr "last-modified hanya dapat beroperasi pada satu pohon pada satu waktu"
+
+#: builtin/last-modified.c
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "argumen last-modified tidak dikenal: %s"
+
+#: builtin/last-modified.c
+msgid "unable to setup last-modified"
+msgstr "tidak dapat mensetup last-modified"
+
+#: builtin/last-modified.c
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+"git last-modified [--recursive] [--show-trees] [<rentang revisi>] [[--] "
+"<jalur>...]"
+
+#: builtin/last-modified.c builtin/ls-tree.c
+msgid "recurse into subtrees"
+msgstr "rekursi ke dalam subpohon"
+
+#: builtin/last-modified.c
+msgid "show tree entries when recursing into subtrees"
+msgstr "perlihatkan entri pohon ketika mengulangi ke dalam subpohon"
+
 #: builtin/log.c
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
 msgstr "git log [<opsi>] [<rentang revisi>] [[--] <jalur>...]"
@@ -9709,6 +10480,23 @@
 msgstr "-L<rentang>:<berkas> tidak dapat digunakan dengan spek jalur"
 
 #: builtin/log.c
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+"\n"
+"petunjuk: Anda dapat mengganti 'git whatchanged <opsi>' dengan:\n"
+"petunjuk:\tgit log <opsi> --raw --no-merges\n"
+"petunjuk: Atau buat alias:\n"
+"petunjuk:\tgit config set --global alias.whatchanged 'log --raw --no-"
+"merges'\n"
+"\n"
+
+#: builtin/log.c
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s: berkas jelek"
@@ -10281,10 +11069,6 @@
 msgstr "hanya perlihatkan pohon"
 
 #: builtin/ls-tree.c
-msgid "recurse into subtrees"
-msgstr "rekursi ke dalam subpohon"
-
-#: builtin/ls-tree.c
 msgid "show trees when recursing"
 msgstr "perlihatkan pohon ketika rekursi"
 
@@ -10479,11 +11263,6 @@
 
 #: builtin/merge-recursive.c
 #, c-format
-msgid "unknown option %s"
-msgstr "opsi tidak dikenal %s"
-
-#: builtin/merge-recursive.c
-#, c-format
 msgid "could not parse object '%s'"
 msgstr "tidak dapat menguraikan objek '%s'"
 
@@ -10702,11 +11481,6 @@
 msgstr "stase gagal"
 
 #: builtin/merge.c
-#, c-format
-msgid "not a valid object: %s"
-msgstr "bukan objek valid: %s"
-
-#: builtin/merge.c
 msgid "read-tree failed"
 msgstr "read-tree gagal"
 
@@ -11164,7 +11938,7 @@
 msgid "Renaming %s to %s\n"
 msgstr "Mengganti nama %s ke %s\n"
 
-#: builtin/mv.c builtin/remote.c
+#: builtin/mv.c
 #, c-format
 msgid "renaming '%s' failed"
 msgstr "gagal mengganti nama '%s'"
@@ -11729,7 +12503,7 @@
 msgid "delta base offset out of bound for %s"
 msgstr "offset dasar delta di luar batas untuk %s"
 
-#: builtin/pack-objects.c
+#: builtin/pack-objects.c builtin/repo.c
 msgid "Counting objects"
 msgstr "Menghitung objek"
 
@@ -12148,32 +12922,8 @@
 "%<PRIu32>), pak yang digunakan ulang %<PRIu32> (dari %<PRIuMAX>)"
 
 #: builtin/pack-refs.c
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pola>][--exclude "
-"<pola>]"
-
-#: builtin/pack-refs.c
-msgid "pack everything"
-msgstr "pak semuanya"
-
-#: builtin/pack-refs.c
-msgid "prune loose refs (default)"
-msgstr "pangkas referensi longgar (asali)"
-
-#: builtin/pack-refs.c
-msgid "auto-pack refs as needed"
-msgstr "otomatis pak referensi jika dibutuhkan"
-
-#: builtin/pack-refs.c
-msgid "references to include"
-msgstr "referensi untuk ditambahkan"
-
-#: builtin/pack-refs.c
-msgid "references to exclude"
-msgstr "referensi untuk dikecualikan"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
 #: builtin/patch-id.c
 msgid "git patch-id [--stable | --unstable | --verbatim]"
@@ -12784,6 +13534,11 @@
 msgstr "git range-diff [<opsi>] <dasar> <ujung lama> <ujung baru>"
 
 #: builtin/range-diff.c
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "nilai max-memory tidak valid: %s"
+
+#: builtin/range-diff.c
 msgid "use simple diff colors"
 msgstr "gunakan warna diff sederhana"
 
@@ -12796,6 +13551,14 @@
 msgstr "lewatkan ke 'git log'"
 
 #: builtin/range-diff.c
+msgid "size"
+msgstr "ukuran"
+
+#: builtin/range-diff.c
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr "memoi maksimum untuk matriks biaya (asali 40)"
+
+#: builtin/range-diff.c
 msgid "only emit output related to the first range"
 msgstr "hanya keluarkan keluaran relatif terhadap rentang pertama"
 
@@ -13471,16 +14234,12 @@
 msgstr "git reflog list"
 
 #: builtin/reflog.c
-msgid ""
-"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
-"                  [--rewrite] [--updateref] [--stale-fix]\n"
-"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
-"<refs>...]"
-msgstr ""
-"git reflog expire [--expire=<waktu>] [--expire-unreachable=<waktu>]\n"
-"                  [--rewrite] [--updateref] [--stale-fix]\n"
-"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
-"<referensi>...]"
+msgid "git reflog exists <ref>"
+msgstr "git reflog exists <referensi>"
+
+#: builtin/reflog.c
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr "git reflog write <referensi> <oid lama> <oid baru> <pesan>"
 
 #: builtin/reflog.c
 msgid ""
@@ -13491,14 +14250,22 @@
 "                  [--dry-run | -n] [--verbose] <referensi>@{<penyebut>}..."
 
 #: builtin/reflog.c
-msgid "git reflog exists <ref>"
-msgstr "git reflog exists <referensi>"
-
-#: builtin/reflog.c
 msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
 msgstr "git reflog drop [--all [--single-worktee] | <referensi>...]"
 
 #: builtin/reflog.c
+msgid ""
+"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
+"<refs>...]"
+msgstr ""
+"git reflog expire [--expire=<waktu>] [--expire-unreachable=<waktu>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
+"<referensi>...]"
+
+#: builtin/reflog.c
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "stempel waktu tidak valid '%s' diberikan ke '--%s'"
@@ -13584,6 +14351,46 @@
 msgid "references specified along with --all"
 msgstr "referensi yang dirincikan bersamaan dengan --all"
 
+#: builtin/reflog.c
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "nama referensi tidak valid: %s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "ID objek lama tidak valid: '%s'"
+
+#: builtin/reflog.c
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "objek lama '%s' tidak ada"
+
+#: builtin/reflog.c
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "ID objek baru tidak valid: '%s'"
+
+#: builtin/reflog.c
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "objek baru '%s' tidak ada"
+
+#: builtin/reflog.c
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr "tidak dapat memulai transaksi: %s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr "tidak dapat mengantrikan pembaruan log referensi: %s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr "tidak dapat mengkomit pembaruan log referensi: %s"
+
 #: builtin/refs.c
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
@@ -13593,6 +14400,14 @@
 msgstr "git refs verify [--strict] [---verbose]"
 
 #: builtin/refs.c
+msgid "git refs exists <ref>"
+msgstr "git refs exists <referensi>"
+
+#: builtin/refs.c
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
+#: builtin/refs.c
 msgid "specify the reference format to convert to"
 msgstr "sebutkan format referensi untuk dikonversi"
 
@@ -13621,6 +14436,22 @@
 msgid "'git refs verify' takes no arguments"
 msgstr "'git refs verify' tidak mengambil argumen"
 
+#: builtin/refs.c
+msgid "git refs list "
+msgstr "git refs list"
+
+#: builtin/refs.c
+msgid "'git refs exists' requires a reference"
+msgstr "'git refs exists' butuh sebuah referensi"
+
+#: builtin/refs.c builtin/show-ref.c
+msgid "reference does not exist"
+msgstr "referensi tidak ada"
+
+#: builtin/refs.c builtin/show-ref.c
+msgid "failed to look up reference"
+msgstr "gagal mencari referensi"
+
 #: builtin/remote.c
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
@@ -13819,6 +14650,25 @@
 "sekarang menamai remote yang tiada '%s'"
 
 #: builtin/remote.c
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+"Remote yang Anda coba untuk dinamai punya referensi yang berkonflik di "
+"dalam\n"
+"spek referensi taget baru. Kemungkinan besar dikarenakan Anda mencoba untuk\n"
+"menumpuk remote pada dirinya sendiri, misalnya dengan menamai ulang "
+"'parent'\n"
+"ke 'parent/child' atau dengan menirnumpuk remote (yaitu sebaliknya).\n"
+"Jika demikian, Anda dapat mengatasinya dengan cara menamai ulang remote ke\n"
+"nama yang berbeda terlebih dahulu.\n"
+
+#: builtin/remote.c
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "Tidak ada remote seperti: '%s'"
@@ -13829,6 +14679,15 @@
 msgstr "Tidak dapat menamai ulang bagian konfigurasi '%s' ke '%s'"
 
 #: builtin/remote.c
+msgid "Renaming remote references"
+msgstr "Menamai ulang referensi remote"
+
+#: builtin/remote.c
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr "gagal mengantrikan penamaan ulang referensi remote: %s"
+
+#: builtin/remote.c
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -13840,18 +14699,9 @@
 "\tMohon perbarui konfigurasi secara manual bila diperlukan."
 
 #: builtin/remote.c
-msgid "Renaming remote references"
-msgstr "Menamai ulang referensi remote"
-
-#: builtin/remote.c
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "menghapus '%s' gagal"
-
-#: builtin/remote.c
-#, c-format
-msgid "creating '%s' failed"
-msgstr "membuat '%s' gagal"
+msgid "renaming remote refs failed: %s"
+msgstr "penaman ulang referensi remote gagal: %s"
 
 #: builtin/remote.c
 msgid ""
@@ -14203,57 +15053,6 @@
 " --no-write-bitmap-index atau nonaktifkan konfigurasi pack.writeBitmaps."
 
 #: builtin/repack.c
-msgid "could not start pack-objects to repack promisor objects"
-msgstr "tidak dapat memulai pack-objects untuk mengepak ulang objek pejanji"
-
-#: builtin/repack.c
-msgid "failed to feed promisor objects to pack-objects"
-msgstr "gagal mengumpan objek penjanji ke pack-objects"
-
-#: builtin/repack.c
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr "repack: Mengharapkan baris ID objek hex penuh hanya dari pack-objects."
-
-#: builtin/repack.c
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr ""
-"tidak dapat menyelesaikan pack-objects untuk mengepak ulang objek pejanji"
-
-#: builtin/repack.c
-#, c-format
-msgid "cannot open index for %s"
-msgstr "tidak dapat membuka indeks untuk %s"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr "pak %s terlalu besar untuk dipertimbangkan dalam deret geometri"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "pak %s terlalu besar untuk digulung"
-
-#: builtin/repack.c
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "tidak dapat membuka berkas sementara '%s' untuk ditulis"
-
-#: builtin/repack.c
-msgid "could not close refs snapshot tempfile"
-msgstr "tidak dapat menutup berkas sementara jepretan referensi"
-
-#: builtin/repack.c
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "tidak dapt memindahkan bitmap basi: %s"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "nama berkas paket %s tidak diawali dengan %s"
-
-#: builtin/repack.c
 msgid "pack everything in a single pack"
 msgstr "pak semuanya dalam satu pak"
 
@@ -14383,21 +15182,6 @@
 msgid "Nothing new to pack."
 msgstr "Tidak ada yang baru untuk dipak."
 
-#: builtin/repack.c
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "gagal mengganti nama pak ke '%s'"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "pack-objects tidak menulis berkas '%s' untuk pak %s-%s"
-
-#: builtin/repack.c sequencer.c
-#, c-format
-msgid "could not unlink: %s"
-msgstr "tidak dapat membatal taut: %s"
-
 #: builtin/replace.c
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] <objek> <pengganti>"
@@ -14720,6 +15504,80 @@
 msgid "replaying merge commits is not supported yet!"
 msgstr "memainkan ulang komit penggabungan belum didukung!"
 
+#: builtin/repo.c
+#, c-format
+msgid "key '%s' not found"
+msgstr "kunci '%s' tidak ditemukan"
+
+#: builtin/repo.c
+#, c-format
+msgid "invalid format '%s'"
+msgstr "format '%s' tidak valid"
+
+#: builtin/repo.c
+msgid "output format"
+msgstr "format keluaran"
+
+#: builtin/repo.c
+msgid "synonym for --format=nul"
+msgstr "sinonim untuk --format=nul"
+
+#: builtin/repo.c
+msgid "unsupported output format"
+msgstr "format keluaran tidak didukung"
+
+#: builtin/repo.c
+msgid "References"
+msgstr "Referensi"
+
+#: builtin/repo.c
+msgid "Count"
+msgstr "Hitungan"
+
+#: builtin/repo.c
+msgid "Branches"
+msgstr "Cabang"
+
+#: builtin/repo.c
+msgid "Tags"
+msgstr "Tag"
+
+#: builtin/repo.c
+msgid "Remotes"
+msgstr "Remote"
+
+#: builtin/repo.c
+msgid "Others"
+msgstr "Lainnya"
+
+#: builtin/repo.c
+msgid "Reachable objects"
+msgstr "Objek yang dapat dijangkau"
+
+#: builtin/repo.c
+msgid "Commits"
+msgstr "Komit"
+
+#: builtin/repo.c
+msgid "Trees"
+msgstr "Pohon"
+
+#: builtin/repo.c
+msgid "Blobs"
+msgstr "Blob"
+
+#: builtin/repo.c
+msgid "Repository structure"
+msgstr "Struktur repositori"
+
+#: builtin/repo.c
+msgid "Value"
+msgstr "Nilai"
+
+#: builtin/repo.c
+msgid "Counting references"
+msgstr "Menghitung referensi"
+
 #: builtin/rerere.c
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
@@ -15462,14 +16320,6 @@
 msgstr "git show-ref --exists <referensi>"
 
 #: builtin/show-ref.c
-msgid "reference does not exist"
-msgstr "referensi tidak ada"
-
-#: builtin/show-ref.c
-msgid "failed to look up reference"
-msgstr "gagal mencari referensi"
-
-#: builtin/show-ref.c
 msgid "only show tags (can be combined with --branches)"
 msgstr "hanya perlihatkan tag (bisa dikombinasikan dengan --branches)"
 
@@ -15510,10 +16360,10 @@
 #: builtin/sparse-checkout.c
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<opsi>]"
+"rules | clean) [<opsi>]"
 
 #: builtin/sparse-checkout.c
 msgid "this worktree is not sparse"
@@ -15562,11 +16412,6 @@
 msgid "toggle the use of a sparse index"
 msgstr "gunakan indeks tipis"
 
-#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c
-#, c-format
-msgid "unable to create leading directories of %s"
-msgstr "tidak dapat membuat direktori utama dari %s"
-
 #: builtin/sparse-checkout.c
 #, c-format
 msgid "failed to open '%s'"
@@ -15666,6 +16511,42 @@
 "harus berada di dalam checkout tipis untuk menerapkan ulang pola kejarangan"
 
 #: builtin/sparse-checkout.c
+msgid "report each affected file, not just directories"
+msgstr "laporkan setiap berkas terdampak, bukan hanya direktori"
+
+#: builtin/sparse-checkout.c
+msgid "must be in a sparse-checkout to clean directories"
+msgstr "harus berada di dalam checkout tipis untuk membersihkan direktori"
+
+#: builtin/sparse-checkout.c
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr ""
+"harus berada di mode checkout tipis kerucut untuk membersihkan direktori"
+
+#: builtin/sparse-checkout.c
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr ""
+"demi keamanan, menolak membersihkan tanpa salah satu dari --force atau --dry-"
+"run"
+
+#: builtin/sparse-checkout.c
+msgid "failed to read index"
+msgstr "gagal membaca indeks"
+
+#: builtin/sparse-checkout.c
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr ""
+"gagal mengkonversikan indeks ke indeks tipis; selesaikan konflik "
+"penggabungan dan coba lagi"
+
+#: builtin/sparse-checkout.c
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "gagal menghapus '%s'"
+
+#: builtin/sparse-checkout.c
 msgid "error while refreshing working directory"
 msgstr "kesalahan saat menyegarkan direktori kerja"
 
@@ -17783,10 +18664,6 @@
 msgid "only useful for debugging"
 msgstr "hanya berguna untuk penirkutuan"
 
-#: bulk-checkin.c
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "core.fsyncMethod = batch tidak didukung pada platform ini"
-
 #: bundle-uri.c
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
@@ -18299,6 +19176,10 @@
 msgstr "Tambah atau urai informasi terstruktur di dalam pesan komit"
 
 #: command-list.h
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr "EKSPERIMENTAL: Perlihatkan kapan berkas terakhir diubah"
+
+#: command-list.h
 msgid "Show commit logs"
 msgstr "Perlihatkan log komit"
 
@@ -18464,6 +19345,10 @@
 "repositori bare"
 
 #: command-list.h
+msgid "Retrieve information about the repository"
+msgstr "Ambil informasi tentang repositori"
+
+#: command-list.h
 msgid "Generates a summary of pending changes"
 msgstr "Buat ringkasan perubahan tertunda"
 
@@ -18572,9 +19457,8 @@
 msgstr "Baca, ubah dan hapus referensi simbolik"
 
 #: command-list.h
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr ""
-"Buat, daftar, hapus atau verifikasi objek tag yang ditandatangani dengan GPG"
+msgid "Create, list, delete or verify tags"
+msgstr "Buat, daftar, hapus, atau verifikasi tag"
 
 #: command-list.h
 msgid "Creates a temporary file with a blob's contents"
@@ -19632,6 +20516,50 @@
 msgstr "gagal menguraikan konfigurasi baris perintah"
 
 #: config.c
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"Untuk gunakan untai komentar bawaan (#) mohon jalankan\n"
+"\n"
+"%s"
+
+#: config.c
+msgid "<comment string>"
+msgstr "<untai komentar>"
+
+#: config.c
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+"\n"
+"Untuk menyetel untai komentar khusus mohon jalankan\n"
+"\n"
+"%s\n"
+"dengan '%s' adalah untai yang Anda ingin gunakan.\n"
+
+#: config.c
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr "Dukungan untuk '%s=auto' sudah dihapus dari Git 3.0"
+
+#: config.c
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr ""
+"Dukungan untuk '%s=auto' sudah tidak berlaku lagi dan akan dihapus dari Git "
+"3.0"
+
+#: config.c
 msgid "unknown error occurred while reading the configuration files"
 msgstr "error tidak diketahui ketika membaca berkas konfigurasi"
 
@@ -20223,6 +21151,14 @@
 msgstr "gagal menulis arsip"
 
 #: diff-lib.c
+msgid "max-depth is not supported for worktree diffs"
+msgstr "max-depth tidak didukung untuk diff pohon kerja"
+
+#: diff-lib.c
+msgid "max-depth is not supported for index diffs"
+msgstr "max-depth tidak didukung untuk diff indeks"
+
+#: diff-lib.c
 msgid "--merge-base does not work with ranges"
 msgstr "--merge-base tidak bekerja dengan rentang"
 
@@ -20872,6 +21808,14 @@
 msgstr "pilih berkas oleh tipe diff"
 
 #: diff.c
+msgid "<depth>"
+msgstr "<kedalaman>"
+
+#: diff.c
+msgid "maximum tree depth to recurse"
+msgstr "kedalaman pohon maksimal untuk diselami"
+
+#: diff.c
 msgid "<file>"
 msgstr "<berkas>"
 
@@ -21114,11 +22058,6 @@
 
 #: fetch-pack.c
 #, c-format
-msgid "object not found: %s"
-msgstr "object tidak ditemukan: %s"
-
-#: fetch-pack.c
-#, c-format
 msgid "error in object: %s"
 msgstr "kesalahan dalam objek: %s"
 
@@ -21465,6 +22404,11 @@
 msgstr "alias rekursif: %s"
 
 #: git.c
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr "putaran alias terdeteksi: perluasan '%s' tidak berhenti:%s"
+
+#: git.c
 msgid "write failure on standard output"
 msgstr "kegagalan menulis pada keluaran standar"
 
@@ -21478,11 +22422,6 @@
 
 #: git.c
 #, c-format
-msgid "alias loop detected: expansion of '%s' does not terminate:%s"
-msgstr "putaran alias terdeteksi: perluasan '%s' tidak berhenti:%s"
-
-#: git.c
-#, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "tidak dapat menangani %s sebagai bawaan"
 
@@ -21547,6 +22486,11 @@
 msgstr "gagal mendapatkan sidik jari ssh untuk kunci '%s'"
 
 #: gpg-interface.c
+#, c-format
+msgid "failed to get the ssh fingerprint for key %s"
+msgstr "gagal mendapatkan tandatangan ssh untuk kunci %s"
+
+#: gpg-interface.c
 msgid ""
 "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
 msgstr ""
@@ -21554,6 +22498,11 @@
 
 #: gpg-interface.c
 #, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr "gpg.ssh.defaultKeyCommand waktu pembuatan cacat: %s"
+
+#: gpg-interface.c
+#, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr "gpg.ssh.defaultKeyCommand sukses tapi tidak mengembalikan kunci: %s %s"
 
@@ -21866,6 +22815,14 @@
 "     diminta: %s\n"
 "  pengalihan: %s"
 
+#: http.h
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr ""
+"angka terlalu besar untuk diwakili sebagai curl_off_t pada platform ini: "
+"%<PRIuMAX>"
+
 #: ident.c
 msgid "Author identity unknown\n"
 msgstr "Identitas pengarang tidak dikenal\n"
@@ -22412,11 +23369,6 @@
 
 #: midx-write.c
 #, c-format
-msgid "could not open index for %s"
-msgstr "tidak dapat membuka indeks untuk %s"
-
-#: midx-write.c
-#, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "tidak dapat mentautkan '%s' ke '%s'"
 
@@ -22445,6 +23397,11 @@
 
 #: midx-write.c
 #, c-format
+msgid "failed to open preferred pack %s"
+msgstr "gagal membuka pak yang disukai '%s'"
+
+#: midx-write.c
+#, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr "tidak dapat memilih pak yang disukai %s tanpa objek"
 
@@ -22475,6 +23432,10 @@
 msgstr "tidak dapat menulis bitmap multipak"
 
 #: midx-write.c
+msgid "too many multi-pack-indexes"
+msgstr "terlalu banyak indeks multipak"
+
+#: midx-write.c
 msgid "unable to open multi-pack-index chain file"
 msgstr "tidak dapat membuka berkas rantai indeks multipak"
 
@@ -22810,11 +23771,6 @@
 
 #: object-file.c
 #, c-format
-msgid "unable to write file %s"
-msgstr "tidak dapat menulis berkas %s"
-
-#: object-file.c
-#, c-format
 msgid "unable to write repeatedly vanishing file %s"
 msgstr "tidak dapat menulis berkas yang menghilang %s terus-menerus"
 
@@ -22824,6 +23780,10 @@
 msgstr "tidak dapat menyetel perizinan ke '%s'"
 
 #: object-file.c
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = batch tidak didukung pada platform ini"
+
+#: object-file.c
 msgid "error when closing loose object file"
 msgstr "kesalahan saat menutup berkas objek longgar"
 
@@ -23434,6 +24394,26 @@
 msgid "mtimes file %s is corrupt"
 msgstr "berkas mtimes %s rusak"
 
+#: pack-refs.c
+msgid "pack everything"
+msgstr "pak semuanya"
+
+#: pack-refs.c
+msgid "prune loose refs (default)"
+msgstr "pangkas referensi longgar (asali)"
+
+#: pack-refs.c
+msgid "auto-pack refs as needed"
+msgstr "otomatis pak referensi jika dibutuhkan"
+
+#: pack-refs.c
+msgid "references to include"
+msgstr "referensi untuk ditambahkan"
+
+#: pack-refs.c
+msgid "references to exclude"
+msgstr "referensi untuk dikecualikan"
+
 #: pack-revindex.c
 #, c-format
 msgid "reverse-index file %s is too small"
@@ -23959,6 +24939,11 @@
 
 #: promisor-remote.c
 #, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr "bidang '%s' tidak didukung pada konfiugrasi '%s'"
+
+#: promisor-remote.c
+#, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "tidak ada URL atau URL kosong yang diiklankan untuk remote '%s'"
 
@@ -23969,13 +24954,18 @@
 
 #: promisor-remote.c
 #, c-format
-msgid "unknown '%s' value for '%s' config option"
-msgstr "nilai '%s' tidak dikenal untuk opsi konfigurasi '%s'"
+msgid "invalid element '%s' from remote info"
+msgstr "elemen '%s' invalid dari info remote"
 
 #: promisor-remote.c
 #, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "elemen '%s' dari info remote tidak dikenal"
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr "peladen mengiklankan remote pejanji tanpa nama atau URL: %s"
+
+#: promisor-remote.c
+#, c-format
+msgid "unknown '%s' value for '%s' config option"
+msgstr "nilai '%s' tidak dikenal untuk opsi konfigurasi '%s'"
 
 #: promisor-remote.c
 #, c-format
@@ -24100,6 +25090,17 @@
 
 #: range-diff.c
 #, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+"range-diff: tidak dapat menghitung range-diff, oleh karena melebihi memori "
+"maksimum untuk matriks biaya: %s (%<PRIuMAX> bita) diperlukan, terbatas pada "
+"%s (%<PRIuMAX> bita)"
+
+#: range-diff.c
+#, c-format
 msgid "could not parse log for '%s'"
 msgstr "tidak dapat menguraikan log untuk '%s'"
 
@@ -24736,6 +25737,10 @@
 msgstr "tidak ada log referensi untuk '%s'"
 
 #: refs.c
+msgid "Checking references consistency"
+msgstr "Memeriksa konsistensi referensi"
+
+#: refs.c
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "%s tidak menunjuk ke sebuah objek valid!"
@@ -24754,8 +25759,9 @@
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -24764,21 +25770,36 @@
 "\n"
 "\tgit branch -m <name>\n"
 msgstr ""
-"Menggunakan '%s' sebagai nama cabang awal. Nama cabang asali ini dapat\n"
-"berubah. Untuk menyetel nama cabang awal untuk digunakan pada semua\n"
-"repositori baru Anda, dimana akan mematikan peringatan ini, panggil:\n"
+"Menggunakan '%s' sebagai nama cabang awal. Nama cabang asali akan\n"
+"berubah menjadi \"main\" pada Git 3.0. Untuk menyetel nama cabang awal\n"
+"untuk digunakan pada semua repositori baru Anda, dimana akan mematikan\n"
+"peringatan ini, panggil:\n"
 "\n"
 "\tgit config --global init.defaultBranch <nama>\n"
 "\n"
 "Nama-nama yang umumnya dipilih selain 'master' adalah 'main', 'trunk' dan\n"
-"'development'. Cabang yang baru saja dibuat bisa dinamai ulang lewat "
-"perintah\n"
-"ini:\n"
+"'development'. Cabang yang baru saja dibuat bisa dinamai ulang lewat\n"
+"perintah ini:\n"
 "\n"
 "\tgit branch -m <nama>\n"
 
 #: refs.c
 #, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"Menggunakan '%s' sebagai nama untuk cabang awal sejak Git 3.0.\n"
+"Jika Anda mengharapkan Git untuk membuat 'master', cabang yang baru saja\n"
+"dibuat dapat dinamai ulang lewat perintah ini:\n"
+"\n"
+"\tgit branch -m master\n"
+
+#: refs.c
+#, c-format
 msgid "could not retrieve `%s`"
 msgstr "tidak dapat mengambil `%s`"
 
@@ -24884,6 +25905,29 @@
 msgid "migrated refs can be found at '%s'"
 msgstr "referensi termigrasi dapat ditemukan pada '%s'"
 
+#: refs/files-backend.c
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+"'core.preferSymlinkRefs=true' dinominasikan untuk dihapus.\n"
+"petunjuk: Penggunaan tautan simbolik untuk referensi simbolik sudah tidak\n"
+"petunjuk: didukung dan akan dihapus di Git 3.0; dengan demikian konfigurasi\n"
+"petunjuk: yang memberitahu Git untuk menggunakanya akan menghilang. Anda\n"
+"petunjuk: dapat menghapus setelannya dengan:\n"
+"petunjuk:\n"
+"petunjuk:\tgit config unset core.preferSymlinkRefs\n"
+"petunjuk:\n"
+"petunjuk: Lalu Git akan menggunakan format referensi simbolik tekstual\n"
+"petunjuk: sebagai gantinya."
+
 #: refs/files-backend.c refs/reftable-backend.c
 #, c-format
 msgid ""
@@ -24892,6 +25936,12 @@
 "tidak dapat mengunci referensi '%s': diharapkan referensi simbolik dengan "
 "target '%s': tetapi bukan referensi reguler"
 
+#: refs/files-backend.c refs/reftable-backend.c
+#, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr ""
+"mencoba menulis log referensi untuk '%s' dengan nilai yang tidak lengkap"
+
 #: refs/files-backend.c
 #, c-format
 msgid "cannot read ref file '%s'"
@@ -24902,10 +25952,6 @@
 msgid "cannot open directory %s"
 msgstr "tidak dapat membuka direktori %s"
 
-#: refs/files-backend.c
-msgid "Checking references consistency"
-msgstr "Memeriksa konsistensi referensi"
-
 #: refs/packed-backend.c
 #, c-format
 msgid "unable to open '%s'"
@@ -24955,6 +26001,12 @@
 
 #: refs/reftable-backend.c
 #, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr ""
+"tidak dapat mengunci referensi '%s' refernsi simbolik menggantung sudah ada"
+
+#: refs/reftable-backend.c
+#, c-format
 msgid "cannot lock ref '%s': reference already exists"
 msgstr "tidak dapat mengunci referensi '%s': referensi sudah ada"
 
@@ -25082,10 +26134,6 @@
 msgstr "RPC gagal; %s"
 
 #: remote-curl.c
-msgid "cannot handle pushes this big"
-msgstr "tidak dapat menangani dorongan sebesar ini"
-
-#: remote-curl.c
 #, c-format
 msgid "cannot deflate request; zlib deflate error %d"
 msgstr "tidak dapat mengempiskan permintaan; kesalahan mengempiskan zlib %d"
@@ -25306,6 +26354,14 @@
 
 #: remote.c
 #, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr ""
+"Bagian <sumber> dari spek referensi ('%s') merupakan ID objek yang tidak\n"
+"ada.\n"
+
+#: remote.c
+#, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "%s tidak dapat diselesaikan ke cabang"
 
@@ -25457,6 +26513,72 @@
 msgid "cannot strip one component off url '%s'"
 msgstr "tidak dapat mencopot satu komponen dari url '%s'"
 
+#: repack-geometry.c
+#, c-format
+msgid "cannot open index for %s"
+msgstr "tidak dapat membuka indeks untuk %s"
+
+#: repack-geometry.c
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr "pak %s terlalu besar untuk dipertimbangkan dalam deret geometri"
+
+#: repack-geometry.c
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "pak %s terlalu besar untuk digulung"
+
+#: repack-midx.c
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "tidak dapat membuka berkas sementara '%s' untuk ditulis"
+
+#: repack-midx.c
+msgid "could not close refs snapshot tempfile"
+msgstr "tidak dapat menutup berkas sementara jepretan referensi"
+
+#: repack-midx.c
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "tidak dapt memindahkan bitmap basi: %s"
+
+#: repack-promisor.c
+msgid "could not start pack-objects to repack promisor objects"
+msgstr "tidak dapat memulai pack-objects untuk mengepak ulang objek pejanji"
+
+#: repack-promisor.c
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "gagal mengumpan objek penjanji ke pack-objects"
+
+#: repack-promisor.c repack.c
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr "repack: Mengharapkan baris ID objek hex penuh hanya dari pack-objects."
+
+#: repack-promisor.c
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr ""
+"tidak dapat menyelesaikan pack-objects untuk mengepak ulang objek pejanji"
+
+#: repack.c
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "nama berkas paket %s tidak diawali dengan %s"
+
+#: repack.c
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr "gagal mengganti nama pak ke '%s'"
+
+#: repack.c
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "pack-objects tidak menulis berkas '%s' untuk pak %s-%s"
+
+#: repack.c sequencer.c
+#, c-format
+msgid "could not unlink: %s"
+msgstr "tidak dapat membatal taut: %s"
+
 #: replace-object.c
 #, c-format
 msgid "bad replace ref name: %s"
@@ -27059,10 +28181,6 @@
 msgstr "tidak dapat chdir ke '%s'"
 
 #: setup.c
-msgid "cannot come back to cwd"
-msgstr "tidak dapat kembali ke cwd"
-
-#: setup.c
 #, c-format
 msgid "failed to stat '%*s%s%s'"
 msgstr "gagal men-stat '%*s%s%s'"
@@ -28353,18 +29471,33 @@
 
 #: usage.c
 #, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "'%s' diajukan untuk dihapus.\n"
+
+#: usage.c
+#, c-format
 msgid ""
-"'%s' 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"
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
 msgstr ""
-"'%s' dinominasikan untuk dihapus.\n"
-"Jika Anda masih menggunakan perintah ini, mohon tambahkan sebuah opsi\n"
-"tambahan, '--i-still-use-this', pada baris perintah dan beri tahu kami jika\n"
-"Anda masih menggunakannya dengan mengirimkan surel ke\n"
-"<git@vger.kernel.org>. Terima kasih.\n"
+"Jika Anda masih menggunakan perintah ini, beginilah yang dapat Anda "
+"lakukan:\n"
+"\n"
+"- lihat https://git-scm.com/docs/BreakingChanges.html\n"
+"- periksa apakah ada yang sudah membahas ini pada milis dan jika mereka\n"
+"  ada sesuatu yang dapat membantu Anda: https://lore.kernel.org/git?q=%s\n"
+"- kirimkan email ke <git@vger.kernel.org> untuk memberitahu kami bahwa\n"
+"  Anda masih menggunakan perintah ini dan tidak dapat menemukan pengganti\n"
+"  yang cocok.\n"
+"\n"
 
 #: usage.c
 msgid "refusing to run without --i-still-use-this"
@@ -29433,6 +30566,10 @@
 msgstr "Balasan kirim surel ini diperlukan"
 
 #: git-send-email.perl
+msgid "The destination IMAP folder is not properly defined."
+msgstr "Folder IMAP tujuan tidak didefinisikan dengan benar."
+
+#: git-send-email.perl
 msgid "The required SMTP server is not properly defined."
 msgstr "Peladen SMTP yang diperlukan tidak dijelaskan dengan baik."
 
diff --git a/po/sv.po b/po/sv.po
index 5ee10ac..a7ae972 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: git 2.51.0\n"
+"Project-Id-Version: git 2.52.0\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2025-08-14 09:52+0100\n"
-"PO-Revision-Date: 2025-08-14 09:53+0100\n"
+"POT-Creation-Date: 2025-11-06 23:58+0000\n"
+"PO-Revision-Date: 2025-11-07 15:54+0100\n"
 "Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n"
 "Language-Team: Svenska <tp-sv@listor.tp-sv.se>\n"
 "Language: sv\n"
@@ -16,7 +16,6 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Gtranslator 42.0\n"
 
 #, c-format
 msgid "%s cannot be negative"
@@ -538,37 +537,39 @@
 msgstr "Ingenting applicerades.\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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
-"j - lämna stycket obestämt, se nästa obestämda stycke\n"
-"J - lämna stycket obestämt, se nästa stycke\n"
-"k - lämna stycket obestämt, se föregående obestämda stycke\n"
-"K - lämna stycket obestämt, se föregående stycke\n"
+"j - gå till nästa obestämda stycke, börja om vid slutet\n"
+"J - gå till nästa stycke, börja om vid slutet\n"
+"k - gå till föregående obestämda stycke, börja om vid början\n"
+"K - gå till föregående styckem, börja om vid början\n"
 "g - välj ett stycke att gå till\n"
 "/ - sök efter stycke som motsvarar angivet reguljärt uttryck\n"
 "s - dela aktuellt stycke i mindre styckens\n"
 "e - redigera aktuellt stycke manuellt\n"
-"p - visa aktuellt stycke, ”P” för att använda bläddrare\n"
+"p - visa aktuellt stycke\n"
+"P - visa aktuellt stycke i bläddrare\n"
 "? - visa hjälp\n"
 
 #, c-format
 msgid "Only one letter is expected, got '%s'"
 msgstr "Förväntade endast en bokstav, fick ”%s”"
 
-msgid "No previous hunk"
-msgstr "Inget föregående stycke"
+msgid "No other hunk"
+msgstr "Inget annat stycke"
 
-msgid "No next hunk"
-msgstr "Inget följande stycke"
+msgid "No other undecided hunk"
+msgstr "Inget annat obestämt stycke"
 
 msgid "No other hunks to goto"
 msgstr "Inga andra stycken att gå till"
@@ -2337,14 +2338,20 @@
 msgstr "Begränsa saknade objekt till befintlig ”sparse-checkout”"
 
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<dålig> [<bra>...]] [--]    [<sökvägar>...]"
+"git bisect start [--term-(bad|new)=<term-ny> --term-(good|old)=<term-"
+"gammal>]\n"
+"                 [--no-checkout] [--first-parent] [<dålig> [<bra>...]] [--] "
+"[<sökvägsspecar>...]"
 
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "git bisect (good|bad) [<incheckning>...]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (bad|new|<term-ny>) [<incheckning>]"
+
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (good|old|<term-gammal>) [<incheckning>...]"
 
 msgid "git bisect skip [(<rev>|<range>)...]"
 msgstr "git bisect skip [(<incheckning>|<intervall>)...]"
@@ -3001,11 +3008,11 @@
 msgstr "HEAD hittades inte under refs/heads!"
 
 msgid ""
-"branch with --recurse-submodules can only be used if submodule."
-"propagateBranches is enabled"
+"branch with --recurse-submodules can only be used if "
+"submodule.propagateBranches is enabled"
 msgstr ""
-"gren med --recurse-submodules kan endast användas om submodule."
-"propagateBranches har aktiverats"
+"gren med --recurse-submodules kan endast användas om "
+"submodule.propagateBranches har aktiverats"
 
 msgid "--recurse-submodules can only be used to create branches"
 msgstr "--recurse-submodules kan endast användas för att skapa grenar"
@@ -5519,6 +5526,14 @@
 msgstr "hittade %i taggar; gav upp sökning vid %s\n"
 
 #, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "kan inte leta efter ”%s” på en ofödd gren"
+
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "blob:en ”%s” kan inte nås från HEAD"
+
+#, c-format
 msgid "describe %s\n"
 msgstr "beskriva %s\n"
 
@@ -5658,6 +5673,9 @@
 msgid "%s...%s: no merge base"
 msgstr "%s...%s: ingen sammanslagningsbas"
 
+msgid "cannot come back to cwd"
+msgstr "kan inte gå tillbaka till arbetskatalogen (cwd)"
+
 msgid "Not a git repository"
 msgstr "Inte ett git-arkiv"
 
@@ -5768,8 +5786,139 @@
 msgid "git fast-export [<rev-list-opts>]"
 msgstr "git fast-export [<rev-list-flaggor>]"
 
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
-msgstr "Fel: Kan inte exportera nästlade taggar såvida inte --mark-tags anges."
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "okänd läge för %s: %s"
+
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "okänt läge för tag-of-filtered: %s"
+
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "okänt läge för reencode: %s"
+
+#, c-format
+msgid "could not read blob %s"
+msgstr "kunde inte läsa blob:en %s"
+
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "oid stämmer inte överens i blob:en %s"
+
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "kunde inte skriva blob:en ”%s”"
+
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "jämförelsesstatus ”%c” förväntades inte för %s, %s"
+
+msgid "none"
+msgstr "ingen"
+
+#, c-format
+msgid "could not find author in commit %s"
+msgstr "kunde inte hitta författare i incheckningen %s"
+
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "kunde inte hitta incheckare i incheckningen %s"
+
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
+msgstr ""
+"påträffade incheckningsspecifik teckenkodning %.*s i incheckningen %s; "
+"använd --reencode=[yes|no] för att hantera den"
+
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr ""
+"påträffade en signerad incheckning %s; använd --signed-commits=<läge> för "
+"att hantera den"
+
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr "exporterar %<PRIuMAX> signatur(er) för incheckningen %s"
+
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr "tar bort signatur(er) från incheckning %s"
+
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+"utelämnar taggen %s,\n"
+"eftersom taggar för träd (eller taggar för taggar för träd, osv.) inte stöds."
+
+#, c-format
+msgid "could not read tag %s"
+msgstr "kunde inte läsa taggen %s"
+
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr ""
+"påträffade signerade taggen %s; använd --signed-tags=<läge> för att hantera "
+"den"
+
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "exporterar signerad tagg %s"
+
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "tar bort signatur från taggen %s"
+
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr ""
+"taggen %s taggar et oexporterat objekt; använd --tag-of-filtered-"
+"object=<läge> för att hantera det"
+
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr "kan inte exportera nästlade taggar såvida inte --mark-tags anges."
+
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "taggen %s pekar ingenstans?"
+
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "%s: förväntade inte objekt av typen %s, hoppar över."
+
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr "taggen pekar på objekt av typ som inte förväntades %s, hoppar över."
+
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "kan inte öppna märkesfilen %s för skrivning"
+
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "kan inte skriva märkesfilen %s"
+
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "trasig märkesrad: %s"
+
+#, c-format
+msgid "object not found: %s"
+msgstr "objektet hittades inte: %s"
+
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "inte en incheckning? kan inte hända: %s"
+
+#, c-format
+msgid "object %s already has a mark"
+msgstr "objektet %s har redan ett märke"
 
 msgid "--anonymize-map token cannot be empty"
 msgstr "symbolen för --anonymize-map kan inte vara tom"
@@ -5835,29 +5984,456 @@
 msgstr "märk taggar med märke-id"
 
 #, c-format
-msgid "Missing from marks for submodule '%s'"
-msgstr "Saknar från-märken för undermodulen ”%s”"
+msgid "can't write crash report %s"
+msgstr "kan inte skriva kraschrapporten %s"
 
 #, c-format
-msgid "Missing to marks for submodule '%s'"
-msgstr "Saknar till-märken för undermodulen ”%s”"
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "fast-import: skriver kraschrapport till %s\n"
 
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "Förväntade ”mark”-kommando, fick %s"
+msgid "mark :%<PRIuMAX> not declared"
+msgstr "märket :%<PRIuMAX> har inte deklarerats"
 
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "Förväntade ”to”-kommando, fick %s"
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "ogiltigt försök att skapa duplicerad gren: %s"
 
-msgid "Expected format name:filename for submodule rewrite option"
-msgstr "Förväntade formatet namn:filnamn för undermodul-omskrivningsflaggan"
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "grenens namn är inte giltigt i Git: %s"
+
+msgid "internal consistency error creating the index"
+msgstr "internt konsistensfel när indexet skulle skapas"
+
+msgid "cannot create keep file"
+msgstr "kan skapa ”keep”-fil"
+
+msgid "failed to write keep file"
+msgstr "misslyckade skriva ”keep”-fil"
+
+msgid "cannot store pack file"
+msgstr "kan inte lagra paketfil"
+
+msgid "cannot store index file"
+msgstr "kan inte lagra indexfil"
+
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "misslyckades söka till början på ”%s”"
+
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "kärn-Git refuserade indexet %s"
+
+msgid "cannot truncate pack to skip duplicate"
+msgstr "kan inte trunkera paketfil för att hoppa över duplikat"
+
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "Filslut i data (%<PRIuMAX> byte återstår):"
+
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "oväntat fel i ”deflate”: %d"
+
+#, c-format
+msgid "not a tree: %s"
+msgstr "inte ett träd: %s"
+
+#, c-format
+msgid "can't load tree %s"
+msgstr "kan inte läsa träd %s"
+
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "trasigt läge i %s"
+
+msgid "root cannot be a non-directory"
+msgstr "roten måste vara en katalog"
+
+msgid "empty path component found in input"
+msgstr "fick tom sökvägskomponent i indata"
+
+msgid "non-directories cannot have subtrees"
+msgstr "endast kataloger kan ha underträd"
+
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
+msgstr "kastar %s eftersom det skulle peka på sig självt (dvs. till %s)"
+
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "grenen %s saknar incheckningar."
+
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "uppdaterar inte %s (ny ändpunkt %s innehåller inte %s)"
+
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "kan inte skapa inledande kataloger för %s"
+
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "kan inte skriva märkesfilen %s"
+
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "kan inte skriva märkesfilen %s: %s"
+
+#, c-format
+msgid "unable to write file %s"
+msgstr "kan inte skriva filen %s"
+
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "förväntade ”data n”-kommando, hittade: %s"
+
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "Filslut i data (avslutningsmarkören ”%s” hittades inte)"
+
+msgid "data is too large to use in this context"
+msgstr "data är för stort för att använda i denna kontext"
+
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "Filslut i data (%lu byte återstår)"
+
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "saknad < i ident-sträng: %s"
+
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "saknat blanksteg före < i ident-sträng: %s"
+
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "saknad > i ident-sträng: %s"
+
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "saknat blanksteg efter > i ident-sträng: %s"
+
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "ogiltigt rått datum ”%s” i ident: %s"
+
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "ogiltigt rfc2822-datum ”%s” i ident: %s"
+
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "datum i ident måste vara ”nu”: %s"
+
+#, c-format
+msgid "too large fanout (%u)"
+msgstr "för stor utbredning (%u)"
+
+#, c-format
+msgid "failed to remove path %s"
+msgstr "misslyckades ta bort sökvägen %s"
+
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "inget värde efter ”:” i märke: %s"
+
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "skräp efter märke: %s"
+
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "saknat blanksteg efter märke: %s"
+
+#, c-format
+msgid "invalid %s: %s"
+msgstr "ogiltig %s: %s"
+
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "NUL  i %s: %s"
+
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "skräp efter %s: %s"
+
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "saknat blanksteg efter %s: %s"
+
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "trasigt läge: %s"
+
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "ogiltig datareferens: %s"
+
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "saknat blanksteg efter SHA1: %s"
+
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "Git-länkar kan inte anges som ”inline”: %s"
+
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "inte en incheckning (faktiskt %s): %s"
+
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "kataloger kan inte anges som ”inline”: %s"
+
+#, c-format
+msgid "%s not found: %s"
+msgstr "hittar inte %s: %s"
+
+msgid "tree"
+msgstr "träd"
+
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "inte %s (faktiskt %s): %s"
+
+#, c-format
+msgid "path %s not in branch"
+msgstr "sökvägen %s inte på grenen"
+
+msgid "can't add a note on empty branch."
+msgstr "kan inte lägga till en anteckning på en tom gren."
+
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr "märket :%<PRIuMAX> är inte en incheckning"
+
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "inte en giltig incheckning: %s"
+
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "ogiltig referensnamn eller SHA1-uttryck: %s"
+
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "inte en blob (faktiskt %s): %s"
+
+#, c-format
+msgid "blob not found: %s"
+msgstr "blob:en hittades inte: %s"
+
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "incheckningen %s är trasig"
+
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "kan inte skapa gren från sig själv: %s"
+
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
+msgstr ""
+"förväntade gpgsig-format: ”gpgsig <hashningsalgo> <signaturformat>”, fick "
+"”gpgsig %s”"
+
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "okänd git-hashningsalgoritm i gpgsig: ”%s”"
+
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "felaktigt signaturformat i gpgsig: ”%s”"
+
+msgid "'unknown' signature format in gpgsig"
+msgstr "”okänt” signaturformat i gpgsig"
+
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr "multipla %s-signaturer hittade, ignorerar ytterligare signatur"
+
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr "parse_one_signature() returnerade okänd hashningsalgoritm"
+
+msgid "expected committer but didn't get one"
+msgstr "förväntade incheckare men fick ingen"
+
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr ""
+"påträffade en signerad incheckning; använd --signed-commits=<läge> för att "
+"hantera den"
+
+msgid "stripping a commit signature"
+msgstr "tar bort en incheckningssignatur"
+
+msgid "importing a commit signature verbatim"
+msgstr "importerar en incheckningssignatur oförändrad"
+
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr ""
+"upptäckte en signerad tagg; använd --signed-tags=<läge> för att hantera den"
+
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr "importerar en taggsignatur oförändrad för taggen ”%s”"
+
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr "tar bort en taggsignatur för taggen ”%s”"
+
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "förväntade ”from”-kommando, fick %s"
+
+msgid "can't tag an empty branch."
+msgstr "kan inte tagga en tom gren."
+
+#, c-format
+msgid "not a valid object: %s"
+msgstr "inte ett giltigt objekt: %s"
+
+msgid "write to frontend failed"
+msgstr "skrivning till framändan misslyckades"
+
+#, c-format
+msgid "can't read object %s"
+msgstr "kan inte läsa objektet %s"
+
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "objektet %s är en %s, men förväntade en blob."
+
+#, c-format
+msgid "not a mark: %s"
+msgstr "inte ett märke: %s"
+
+#, c-format
+msgid "unknown mark: %s"
+msgstr "okänt märke: %s"
+
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "skräp efter SHA1: %s"
+
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "inte ett träd-igt: %s"
+
+#, c-format
+msgid "can't load object %s"
+msgstr "kan inte läsa in objektet %s"
+
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "ogiltigt SHA1 i tagg: %s"
+
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "ogiltigt SHA1 i incheckning: %s"
+
+#, c-format
+msgid "missing from marks for submodule '%s'"
+msgstr "saknade från-märken i undermodulen ”%s”"
+
+#, c-format
+msgid "missing to marks for submodule '%s'"
+msgstr "saknade till-märken i undermodulen ”%s”"
+
+#, c-format
+msgid "missing space after tree-ish: %s"
+msgstr "saknat blanksteg efter träd-igt: %s"
+
+#, c-format
+msgid "not in a commit: %s"
+msgstr "inte en incheckning: %s"
+
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "förväntade ”mark”-kommando, fick %s"
+
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "förväntade ”to”-kommando, fick %s"
+
+msgid "only one import-marks command allowed per stream"
+msgstr "endast ett import-marks-kommando tillåts per ström"
+
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "okänt argument till --date-format: %s"
+
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s: argumentet måste vara ett icke-negativt heltal"
+
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr "--depth kan inte överstiga %u"
+
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr "--cat-blob-fd kan inte överstiga %d"
+
+msgid "expected format name:filename for submodule rewrite option"
+msgstr "förväntade formatet namn:filnamn för undermodul-omskrivningsflaggan"
+
+#, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr "max-pack-size är nu i byte, antar --max-pack-size=%lum"
+
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "minsta max-pack-size är 1 MiB"
+
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "okänt läge ”%s” för --signed-commits"
+
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "okänt läge ”%s” för --signed-tags"
 
 #, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
 msgstr "funktionen ”%s” förbjuden i indata utan --allow-unsafe-features"
 
 #, c-format
+msgid "got feature command '%s' after data command"
+msgstr "fick funktionskommando ”%s” efter datakommando"
+
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "den här versionen av fast-import stöder inte funktionen %s."
+
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr "fick tillvalskommando ”%s” efter datakommando"
+
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "den här versionen av fast-import stöder inte tillvalet: %s"
+
+#, c-format
+msgid "unknown option %s"
+msgstr "okänd flagga %s"
+
+#, c-format
+msgid "unknown option --%s"
+msgstr "okänd flagga --%s"
+
+#, c-format
+msgid "unsupported command: %s"
+msgstr "kommando stöds ej: %s"
+
+msgid "stream ends early"
+msgstr "strömmen slutade för tidigt"
+
+#, c-format
 msgid "Lockfile created but not reported: %s"
 msgstr "Låsfil skapad men inte rapporterad: %s"
 
@@ -5993,6 +6569,35 @@
 "varningen till fjärren ändrar HEAD till något annat genom att köra\n"
 "”git config set remote %s.followRemoteHEAD warn-if-not-branch-%s”."
 
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+"Du är på ett skiftlägesokänsligt filsystem och fjärren du försöker\n"
+"hämta från har referenser vars namn bara varierar i små och stora\n"
+"bokstäver. Det är inte möjligt att spara sådana referenser med\n"
+"”files”-bakändan. Du kan antingen godta det som det är, i vilket\n"
+"fall du inte kommer kunna lagra alla fjärr-referenser på disken.\n"
+"Eller så kan du migrera ditt arkiv till att använda bakändan\n"
+"”reftable” med hjälp av följande kommando:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Tänk på att alla implementationer av Git ännu inte stöder detta\n"
+"format. Så om du använder andra verktyg än Git för att läsa detta\n"
+"arkiv är migrering till referenstabeller kanske inte ett alternativ.\n"
+
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -6196,11 +6801,11 @@
 msgstr "protokollet stöder inte --negotiate-only, avslutar"
 
 msgid ""
-"--filter can only be used with the remote configured in extensions."
-"partialclone"
+"--filter can only be used with the remote configured in "
+"extensions.partialclone"
 msgstr ""
-"--filter kan endast användas med fjärren konfigurerad i extensions."
-"partialclone"
+"--filter kan endast användas med fjärren konfigurerad i "
+"extensions.partialclone"
 
 msgid "--atomic can only be used when fetching from one remote"
 msgstr "--atomic kan bara användas vid hämtning från en fjärr"
@@ -6231,23 +6836,6 @@
 msgid "file to read from"
 msgstr "fil att läsa från"
 
-msgid "git for-each-ref [<options>] [<pattern>]"
-msgstr "git for-each-ref [<flaggor>] [<mönster>]"
-
-msgid "git for-each-ref [--points-at <object>]"
-msgstr "git for-each-ref [--points-at <objekt>]"
-
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr ""
-"git for-each-ref [--merged [<incheckning>]] [--no-merged <incheckning>]]"
-
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr ""
-"git for-each-ref [--contains [<incheckning>]] [--no-contains [<incheckning>]]"
-
-msgid "git for-each-ref [--start-after <marker>]"
-msgstr "git for-each-ref [--start-after <markör>]"
-
 msgid "quote placeholders suitably for shells"
 msgstr "citera platshållare passande för skal"
 
@@ -6302,6 +6890,9 @@
 msgid "cannot use --start-after with patterns"
 msgstr "kan inte använda --start-after med mönster"
 
+msgid "git for-each-ref "
+msgstr "git for-each-ref "
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<konfig> [--] <argument>"
 
@@ -6777,6 +7368,9 @@
 "hoppar över ”incremental-repack”-uppgift eftersom core.multiPackIndex är "
 "inaktiverat"
 
+msgid "failed to perform geometric repack"
+msgstr "misslyckades att utföra geometrisk ompackning"
+
 #, c-format
 msgid "task '%s' failed"
 msgstr "uppgiften ”%s” misslyckades"
@@ -6786,6 +7380,10 @@
 msgstr "låsfilen ”%s” finns, hoppar över underhåll"
 
 #, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "okänd underhållsstrategi: ”%s”"
+
+#, c-format
 msgid "'%s' is not a valid task"
 msgstr "”%s” är inte en giltig uppgift"
 
@@ -7644,6 +8242,29 @@
 msgid "no input file given for in-place editing"
 msgstr "ingen indatafil angiven för redigering på plats"
 
+msgid "last-modified can only operate on one tree at a time"
+msgstr "last-modified kan bara användas på ett träd åt gången"
+
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "okänt argument till last-modified: %s"
+
+msgid "unable to setup last-modified"
+msgstr "kan inte ställa in last-modified"
+
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+"git last-modified [--recursive] [--show-trees] [<versionsintervall>] [[--] "
+"<sökväg>...]"
+
+msgid "recurse into subtrees"
+msgstr "rekursera ner i underträd"
+
+msgid "show tree entries when recursing into subtrees"
+msgstr "visa trädposter under rekursering in i underträd"
+
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
 msgstr "git log [<flaggor>] [<versionsintervall>] [[--] <sökväg>...]"
 
@@ -7682,6 +8303,20 @@
 msgid "-L<range>:<file> cannot be used with pathspec"
 msgstr "-L<intervall>:<fil> kan inte användas med sökvägsspecifikation"
 
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+"\n"
+"tips: du kan ersätta ”git whatchanged <flaggor>” med:\n"
+"tips:\tgit log <flaggor> --raw --no-merges\n"
+"tips: Eller skapa ett alias:\n"
+"tips:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s: felaktig fil"
@@ -8112,11 +8747,8 @@
 msgid "only show trees"
 msgstr "visa endast träd"
 
-msgid "recurse into subtrees"
-msgstr "rekursera ner i underträd"
-
 msgid "show trees when recursing"
-msgstr "visa träd medan rekursering"
+msgstr "visa träd under rekursering"
 
 msgid "terminate entries with NUL byte"
 msgstr "terminera poster med NUL-byte"
@@ -8261,10 +8893,6 @@
 msgstr "Kunde inte skriva objektfilen"
 
 #, c-format
-msgid "unknown option %s"
-msgstr "okänd flagga %s"
-
-#, c-format
 msgid "could not parse object '%s'"
 msgstr "kunde inte tolka objektet ”%s”"
 
@@ -8431,10 +9059,6 @@
 msgid "stash failed"
 msgstr "stash misslyckades"
 
-#, c-format
-msgid "not a valid object: %s"
-msgstr "inte ett giltigt objekt: %s"
-
 msgid "read-tree failed"
 msgstr "read-tree misslyckades"
 
@@ -9569,27 +10193,8 @@
 "Totalt %<PRIu32> (delta %<PRIu32>), återanvände %<PRIu32> (delta %<PRIu32>), "
 "paket-återanvända %<PRIu32> (från %<PRIuMAX>)"
 
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <mönster>] [--exclude "
-"<mönster>]"
-
-msgid "pack everything"
-msgstr "packa allt"
-
-msgid "prune loose refs (default)"
-msgstr "ta bort lösa referenser (standard)"
-
-msgid "auto-pack refs as needed"
-msgstr "packa referenser automatiskt om nödvändigt"
-
-msgid "references to include"
-msgstr "referenser att ta med"
-
-msgid "references to exclude"
-msgstr "referenser att utesluta"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
 msgid "git patch-id [--stable | --unstable | --verbatim]"
 msgstr "git patch-id [--stable | --unstable | --verbatim]"
@@ -9831,8 +10436,8 @@
 msgstr ""
 "\n"
 "För att undvika att en uppströmsgren automatiskt konfigureras när dess namn\n"
-"inte motsvarar den lokala grenen, se värdet ”simple” i branch."
-"autoSetupMerge\n"
+"inte motsvarar den lokala grenen, se värdet ”simple” i "
+"branch.autoSetupMerge\n"
 "i ”git help config”.\n"
 
 #, c-format
@@ -10095,6 +10700,10 @@
 msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
 msgstr "git range-diff [<flaggor>] <bas> <gammal-ända> <ny-ända>"
 
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "felaktigt värde för max-memory: %s"
+
 msgid "use simple diff colors"
 msgstr "använd enkla diff-färger"
 
@@ -10104,6 +10713,12 @@
 msgid "passed to 'git log'"
 msgstr "sänds till ”git log”"
 
+msgid "size"
+msgstr "storlek"
+
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr "maximalt minne för kostnadsmatris (förval 4G)"
+
 msgid "only emit output related to the first range"
 msgstr "visa endast utdata för det första intervallet"
 
@@ -10653,6 +11268,22 @@
 msgid "git reflog list"
 msgstr "git reflog list"
 
+msgid "git reflog exists <ref>"
+msgstr "git reflog exists <referens>"
+
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr "git reflog write <ref> <gammalt-oid> <nytt-oi> <meddelande>"
+
+msgid ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+msgstr ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specificering>}..."
+
+msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
+msgstr "git reflog drop [--all [--single-worktree] | <referenser>...]"
+
 msgid ""
 "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
 "                  [--rewrite] [--updateref] [--stale-fix]\n"
@@ -10664,19 +11295,6 @@
 "                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
 "<referenser>...]"
 
-msgid ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-msgstr ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specificering>}..."
-
-msgid "git reflog exists <ref>"
-msgstr "git reflog exists <referens>"
-
-msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
-msgstr "git reflog drop [--all [--single-worktree] | <referenser>...]"
-
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "ogiltig tidsstämpel ”%s” given i ”--%s”"
@@ -10744,12 +11362,50 @@
 msgid "references specified along with --all"
 msgstr "referenser angivna tillsammans med --all"
 
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "felaktigt referensnamn: %s"
+
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "ogiltigt gammalt objekt-ID: ”%s”"
+
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "gammalt objekt ”%s” finns inte"
+
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "ogiltigt nytt objekt-ID: ”%s”"
+
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "nytt objekt ”%s” finns inte"
+
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr "kan inte starta transaktionen: %s"
+
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr "kan inte köa referenslogguppdatering: %s"
+
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr "kan inte spara referenslogguppdatering: %s"
+
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 
 msgid "git refs verify [--strict] [--verbose]"
 msgstr "git refs verify [--strict] [--verbose]"
 
+msgid "git refs exists <ref>"
+msgstr "git refs exists <referens>"
+
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
 msgid "specify the reference format to convert to"
 msgstr "ange referensformatet att konvertera till"
 
@@ -10772,6 +11428,18 @@
 msgid "'git refs verify' takes no arguments"
 msgstr "”git refs verify” tar inget argument"
 
+msgid "git refs list "
+msgstr "git refs list"
+
+msgid "'git refs exists' requires a reference"
+msgstr "”git refs exists” kräver en referens"
+
+msgid "reference does not exist"
+msgstr "referensen existerar inte"
+
+msgid "failed to look up reference"
+msgstr "misslyckades slå upp referensen"
+
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
 "mirror=<fetch|push>] <name> <url>"
@@ -10928,6 +11596,24 @@
 "\t%s:%d\n"
 "anger nu den icke-existerande fjärren ”%s”"
 
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+"Fjärren du försöker byta namn på har motstridiga referenser i det\n"
+"nya målets referensspecifikationer. Det beror antagligen på att du\n"
+"försöker nästla en fjärr in i sig själv, t.ex. genom att namnändra\n"
+"”förälder” till ”förälder/barn” eller att avnästlar en, t.ex. åt\n"
+"andra hållet.\n"
+"\n"
+"Om så är fallet kan du du lösa det genom att första byta namnet på\n"
+"fjärren mot ett annat namn.\n"
+
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "Ingen sådan fjärr: ”%s”"
@@ -10936,6 +11622,13 @@
 msgid "Could not rename config section '%s' to '%s'"
 msgstr "Kunde inte byta namn på konfigurationssektionen ”%s” till ”%s”"
 
+msgid "Renaming remote references"
+msgstr "Byter namn på fjärreferenser"
+
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr "misslyckades köa namnändring av fjärr-referenser: %s"
+
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -10946,16 +11639,9 @@
 "\t%s\n"
 "\tUppdatera konfigurationen manuellt om nödvändigt."
 
-msgid "Renaming remote references"
-msgstr "Byter namn på fjärreferenser"
-
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "misslyckades ta bort ”%s”"
-
-#, c-format
-msgid "creating '%s' failed"
-msgstr "misslyckades skapa ”%s”"
+msgid "renaming remote refs failed: %s"
+msgstr "misslyckades namnändra fjärr-referenser: %s"
 
 msgid ""
 "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
@@ -11235,46 +11921,6 @@
 "Använd --no-write-bitmap-index eller inaktivera inställningen\n"
 "pack.writeBitmaps."
 
-msgid "could not start pack-objects to repack promisor objects"
-msgstr "kunde inte starta pack-objects för att packa om kontraktsobjekt"
-
-msgid "failed to feed promisor objects to pack-objects"
-msgstr "misslyckades sända kontraktsobjekt till pack-objects"
-
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr ""
-"repack: Förväntar kompletta hex-objekt-id-rader endast från pack-objects."
-
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr "kunde inte avsluta pack-objects för att packa om kontraktsobjekt"
-
-#, c-format
-msgid "cannot open index for %s"
-msgstr "kunde inte öppna indexet för %s"
-
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr "paketet %s för stort för att tas med i geometriskt förlopp"
-
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "paketet %s för stort att rulla upp"
-
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "kunde inte öppna temporär fil %s för skrivning"
-
-msgid "could not close refs snapshot tempfile"
-msgstr "kunde inte stänga temporär fil för refs-ögonblicksbild"
-
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "kunde inte ta bort gammal bitkarta: %s"
-
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "paketprefixet %s börjar inte med objkat %s"
-
 msgid "pack everything in a single pack"
 msgstr "packa allt i ett enda paket"
 
@@ -11372,18 +12018,6 @@
 msgid "Nothing new to pack."
 msgstr "Inget nytt att packa."
 
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "misslyckades byta namn på paket till ”%s”"
-
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "pack-objects skrev inte en ”%s”-fil för paketet %s-%s"
-
-#, c-format
-msgid "could not unlink: %s"
-msgstr "kunde inte ta bort: ”%s”"
-
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] <objekt> <ersättning>"
 
@@ -11639,6 +12273,62 @@
 msgid "replaying merge commits is not supported yet!"
 msgstr "kan ännu inte spela om sammanslagningsincheckningar!"
 
+#, c-format
+msgid "key '%s' not found"
+msgstr "nyckeln ”%s” hittades inte"
+
+#, c-format
+msgid "invalid format '%s'"
+msgstr "ogiltigt format ”%s”"
+
+msgid "output format"
+msgstr "utdataformat"
+
+msgid "synonym for --format=nul"
+msgstr "synonym till --format=nul"
+
+msgid "unsupported output format"
+msgstr "utdataformatet stöds ej"
+
+msgid "References"
+msgstr "Referenser"
+
+msgid "Count"
+msgstr "Antal"
+
+msgid "Branches"
+msgstr "Grenar"
+
+msgid "Tags"
+msgstr "Taggar"
+
+msgid "Remotes"
+msgstr "Fjärrar"
+
+msgid "Others"
+msgstr "Andra"
+
+msgid "Reachable objects"
+msgstr "Nåbara objekt"
+
+msgid "Commits"
+msgstr "Incheckningar"
+
+msgid "Trees"
+msgstr "Träd"
+
+msgid "Blobs"
+msgstr "Blob:ar"
+
+msgid "Repository structure"
+msgstr "Arkivstruktur"
+
+msgid "Value"
+msgstr "Värde"
+
+msgid "Counting references"
+msgstr "Räknar referenser"
+
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
 msgstr ""
@@ -12224,12 +12914,6 @@
 msgid "git show-ref --exists <ref>"
 msgstr "git show-ref --exists <ref>"
 
-msgid "reference does not exist"
-msgstr "referensen existerar inte"
-
-msgid "failed to look up reference"
-msgstr "misslyckades slå upp referensen"
-
 msgid "only show tags (can be combined with --branches)"
 msgstr "visa endast taggar (kan kombineras med --branches)"
 
@@ -12259,10 +12943,10 @@
 
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) <flaggor>"
+"rules | clean) <flaggor>"
 
 msgid "this worktree is not sparse"
 msgstr "arbetskatalogen är inte gren"
@@ -12303,10 +12987,6 @@
 msgstr "slå på/av användning av glest index"
 
 #, c-format
-msgid "unable to create leading directories of %s"
-msgstr "kan inte skapa inledande kataloger för %s"
-
-#, c-format
 msgid "failed to open '%s'"
 msgstr "misslyckades öppna ”%s”"
 
@@ -12386,6 +13066,32 @@
 msgstr ""
 "måste vara i en gles utcheckning för att tillämpa gleshetsmönster på nytt"
 
+msgid "report each affected file, not just directories"
+msgstr "rapportera varje påverkad fil, inte bara kataloger"
+
+msgid "must be in a sparse-checkout to clean directories"
+msgstr "måste vara i en gles utcheckning för städa kataloger"
+
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr "måste vara i en gles utcheckning i konläge för att städa kataloger"
+
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr "för säkerhets skull, vägrar rensa utan en av --force eller --dry-run"
+
+msgid "failed to read index"
+msgstr "misslyckades läsa index"
+
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr ""
+"misslyckades konvertera indexet till ett glest index; lös "
+"sammanslagningskonflikter och försök igen"
+
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "misslyckades ta bort ”%s”"
+
 msgid "error while refreshing working directory"
 msgstr "fel vid uppdatering av arbetskatalog"
 
@@ -14072,9 +14778,6 @@
 msgid "only useful for debugging"
 msgstr "endast användbart vid felsökning"
 
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "core.fsyncMethod = batch stöds inte på denna plattform"
-
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
 msgstr "kunde inte tolka listnyckeln %s med värdet ”%s”"
@@ -14465,6 +15168,9 @@
 msgstr ""
 "Lägg till eller tolka strukturerad information i incheckningsmeddelanden"
 
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr "EXPERIMENTELLT: Visa när filer sist ändrades"
+
 msgid "Show commit logs"
 msgstr "Visa incheckningsloggar"
 
@@ -14587,6 +15293,9 @@
 "EXPERIMENTELLT: Spela om incheckningar ovanpå en ny bas, fungerar även med "
 "nakna arkiv"
 
+msgid "Retrieve information about the repository"
+msgstr "Hämta information om arkivet"
+
 msgid "Generates a summary of pending changes"
 msgstr "Skapar en sammanfattning av väntande ändringar"
 
@@ -14668,8 +15377,8 @@
 msgid "Read, modify and delete symbolic refs"
 msgstr "Läs, modifiera eller ta bort symbolisk referens"
 
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr "Skapa, visa, ta bort eller verifiera GPG-signerat taggobjekt"
+msgid "Create, list, delete or verify tags"
+msgstr "Skapa, visa, ta bort eller verifiera taggar"
 
 msgid "Creates a temporary file with a blob's contents"
 msgstr "Skapar temporära filer med innehållet från en blob"
@@ -15011,11 +15720,11 @@
 
 #, c-format
 msgid ""
-"attempting to write a commit-graph, but 'commitGraph."
-"changedPathsVersion' (%d) is not supported"
+"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' "
+"(%d) is not supported"
 msgstr ""
-"försöker skriva en incheckningsgraf, men ”commitGraph."
-"changedPathsVersion” (%d) stöds inte"
+"försöker skriva en incheckningsgraf, men ”commitGraph.changedPathsVersion” "
+"(%d) stöds inte"
 
 msgid "too many commits to write graph"
 msgstr "för många incheckningar för att skriva graf"
@@ -15514,6 +16223,43 @@
 msgid "unable to parse command-line config"
 msgstr "kan inte tolka kommandoradskonfiguration"
 
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"För att använda standardkommentarssträngen (#), kör\n"
+"\n"
+"%s"
+
+msgid "<comment string>"
+msgstr "<kommentarssträng>"
+
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+"\n"
+"För att ange en skräddarsydd kommentarssträng, kör\n"
+"\n"
+"%s\n"
+"där ”%s” är strängen du vill använda.\n"
+
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr "Stöd för ”%s=auto” har tagits bort i Git 3.0"
+
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr "Stöd för ”%s=auto” är föråldrat och kommer tas bort i Git 3.0"
+
 msgid "unknown error occurred while reading the configuration files"
 msgstr "okänt fel uppstod vid läsning av konfigurationsfilerna"
 
@@ -15989,6 +16735,12 @@
 msgid "failed to write archive"
 msgstr "misslyckades skriva arkiv"
 
+msgid "max-depth is not supported for worktree diffs"
+msgstr "max-depth stöds inte för diffar i arbetskatalog"
+
+msgid "max-depth is not supported for index diffs"
+msgstr "max-depth stöds inte för index-diffar"
+
 msgid "--merge-base does not work with ranges"
 msgstr "--merge-base fungerar inte med intervall"
 
@@ -16492,6 +17244,12 @@
 msgid "select files by diff type"
 msgstr "välj filter efter diff-typ"
 
+msgid "<depth>"
+msgstr "<djup>"
+
+msgid "maximum tree depth to recurse"
+msgstr "maximal träddjup att rekursera"
+
 msgid "<file>"
 msgstr "<fil>"
 
@@ -16687,10 +17445,6 @@
 msgstr "ogiltig ”unshallow”-rad: %s"
 
 #, c-format
-msgid "object not found: %s"
-msgstr "objektet hittades inte: %s"
-
-#, c-format
 msgid "error in object: %s"
 msgstr "fel i objekt: %s"
 
@@ -16973,6 +17727,10 @@
 msgid "recursive alias: %s"
 msgstr "rekursivt alias: %s"
 
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr "alias-slinga detekterades: expansionen av ”%s” avslutas aldrig:%s"
+
 msgid "write failure on standard output"
 msgstr "skrivfel på standard ut"
 
@@ -16983,10 +17741,6 @@
 msgstr "stäng misslyckades på standard ut"
 
 #, c-format
-msgid "alias loop detected: expansion of '%s' does not terminate:%s"
-msgstr "alias-slinga detekterades: expansionen av ”%s” avslutas aldrig:%s"
-
-#, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "kan inte hantera %s som inbyggd"
 
@@ -17040,12 +17794,20 @@
 msgid "failed to get the ssh fingerprint for key '%s'"
 msgstr "misslyckades hämta ssh-fingeravtrycket för nyckeln ”%s”"
 
+#, c-format
+msgid "failed to get the ssh fingerprint for key %s"
+msgstr "misslyckades hämta ssh-fingeravtrycket för nyckeln %s"
+
 msgid ""
 "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
 msgstr ""
 "måste konfigurera antingen user.signingkey eller gpg.ssh.defaultKeyCommand"
 
 #, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr "fel format på gpg.ssh.defaultKeyCommand från byggtiden: %s"
+
+#, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr "gpg.ssh.defaultKeyCommand lyckades men gav inga nycklar: %s %s"
 
@@ -17091,8 +17853,8 @@
 "given pattern contains NULL byte (via -f <file>). This is only supported "
 "with -P under PCRE v2"
 msgstr ""
-"angivet mönster innehåller NULL-byte (via -f <fil>). Detta stöds endast med -"
-"P under PCRE v2"
+"angivet mönster innehåller NULL-byte (via -f <fil>). Detta stöds endast med "
+"-P under PCRE v2"
 
 #, c-format
 msgid "'%s': unable to read %s"
@@ -17298,6 +18060,13 @@
 "        bad om: %s\n"
 "  omdirigering: %s"
 
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr ""
+"värdet för stort för att representeras som curl_off_t på denna plattform: "
+"%<PRIuMAX>"
+
 msgid "Author identity unknown\n"
 msgstr "Författar-identitet okänd\n"
 
@@ -17755,10 +18524,6 @@
 msgstr "kunde inte läsa paket{"
 
 #, c-format
-msgid "could not open index for %s"
-msgstr "kunde inte öppna indexet för %s"
-
-#, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "kan inte länka ”%s” till ”%s”"
 
@@ -17781,6 +18546,10 @@
 msgstr "okänt föredraget paket: %s"
 
 #, c-format
+msgid "failed to open preferred pack %s"
+msgstr "misslyckades öppna föredraget paket %s"
+
+#, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr "kan inte välja föredraget paket %s som inte har några objekt"
 
@@ -17804,6 +18573,9 @@
 msgid "could not write multi-pack bitmap"
 msgstr "kunde inte skriva fler-paketsbitkarta"
 
+msgid "too many multi-pack-indexes"
+msgstr "för många multi-pack-index"
+
 msgid "unable to open multi-pack-index chain file"
 msgstr "kan inte öppna kedjefil för multi-pack-index"
 
@@ -18070,10 +18842,6 @@
 msgstr "filerna ”%s” och ”%s” har olika innehåll"
 
 #, c-format
-msgid "unable to write file %s"
-msgstr "kan inte skriva filen %s"
-
-#, c-format
 msgid "unable to write repeatedly vanishing file %s"
 msgstr "kan inte skriva till filen %s som hela tiden försvinner"
 
@@ -18081,6 +18849,9 @@
 msgid "unable to set permission to '%s'"
 msgstr "kan inte sätta behörigheten till ”%s”"
 
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = batch stöds inte på denna plattform"
+
 msgid "error when closing loose object file"
 msgstr "fel vid stängning av fil för löst objekt"
 
@@ -18578,6 +19349,21 @@
 msgid "mtimes file %s is corrupt"
 msgstr "mtimes-filen %s är trasig"
 
+msgid "pack everything"
+msgstr "packa allt"
+
+msgid "prune loose refs (default)"
+msgstr "ta bort lösa referenser (standard)"
+
+msgid "auto-pack refs as needed"
+msgstr "packa referenser automatiskt om nödvändigt"
+
+msgid "references to include"
+msgstr "referenser att ta med"
+
+msgid "references to exclude"
+msgstr "referenser att utesluta"
+
 #, c-format
 msgid "reverse-index file %s is too small"
 msgstr "reverse-index-filen %s är för liten"
@@ -18999,6 +19785,10 @@
 msgstr "kunde inte hämta %s från kontraktsfjärr"
 
 #, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr "fältet ”%s” i inställningen ”%s” stöds ej"
+
+#, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "ingen eller tom URL tillkännagavs för fjärren ”%s”"
 
@@ -19007,12 +19797,16 @@
 msgstr "känd fjärr som heter ”%s” men med URL:en ”%s” istället för ”%s”"
 
 #, c-format
-msgid "unknown '%s' value for '%s' config option"
-msgstr "okänt värde ”%s” för inställningen ”%s”"
+msgid "invalid element '%s' from remote info"
+msgstr "ogiltigt element ”%s” från fjärrinformation"
 
 #, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "okänt värde ”%s” från fjärrinformation"
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr "servern deklarerade en kontraktsfjärr utan namn eller URL: %s"
+
+#, c-format
+msgid "unknown '%s' value for '%s' config option"
+msgstr "okänt värde ”%s” för inställningen ”%s”"
 
 #, c-format
 msgid "accepted promisor remote '%s' not found"
@@ -19114,6 +19908,16 @@
 msgstr "misslyckades skapa diff"
 
 #, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+"range-diff: kan inte beräkna intervalldiff, eftersom den överstiger maximalt "
+"minne för konstnadsmatrisen: %s (%<PRIuMAX> bytes) krävs, begränsat till %s "
+"(%<PRIuMAX> bytes)"
+
+#, c-format
 msgid "could not parse log for '%s'"
 msgstr "kunde inte tolka loggen för ”%s”"
 
@@ -19642,6 +20446,9 @@
 msgid "no reflog for '%s'"
 msgstr "ingen referenslogg för ”%s”"
 
+msgid "Checking references consistency"
+msgstr "Kontrollerar konsistens för referenser"
+
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "”%s” pekar inte på ett giltigt objekt!"
@@ -19657,8 +20464,9 @@
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -19668,7 +20476,8 @@
 "\tgit branch -m <name>\n"
 msgstr ""
 "Använder ”%s” som namn för den inledande grenen. Detta förvalda grennamn\n"
-"kan ändras i framtiden. För att välja vilket namn som ska användas på\n"
+"kommer ändras till ”main” i Git 3.0. För att välja vilket namn som ska "
+"användas på\n"
 "den inledande grenen i alla nya arkiv, och dölja denna varning, kör du:\n"
 "\n"
 "\tgit config --global init.defaultBranch <namn>\n"
@@ -19679,6 +20488,20 @@
 "\tgit branch -m <namn>\n"
 
 #, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"Använder ”%s” som namn för den första grenen sedan Git 3.0.\n"
+"Om du förväntade att Git skulle skapa ”master” kan grenen\n"
+"som just skapades namnändras med det här kommandot:\n"
+"\n"
+"\tgit branch -m master\n"
+
+#, c-format
 msgid "could not retrieve `%s`"
 msgstr "kunde inte hämta ”%s”"
 
@@ -19763,6 +20586,26 @@
 msgid "migrated refs can be found at '%s'"
 msgstr "migrerade referenser hittas vid ”%s”"
 
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+"'core.preferSymlinkRefs=true' har nominerats för borttagning.\n"
+"tips: Användningen av symboliska länkar för symboliska referenser\n"
+"tips: avråds från och kommer tas bort i Git 3.0. Konfigurationen\n"
+"tips: som säger till Git att använda dem kommer därför försvinna.\n"
+"tips: Du kan ta bort den med:tips:\n"
+"tips:\tgit config unset core.preferSymlinkRefs\n"
+"tips:\n"
+"tips: Git kommer då använda textformat för symboliska referenser."
+
 #, c-format
 msgid ""
 "cannot lock ref '%s': expected symref with target '%s': but is a regular ref"
@@ -19771,6 +20614,10 @@
 "men är en vanlig referens"
 
 #, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr "försöker skriva referensloggen ”%s” med ofullständiga värden"
+
+#, c-format
 msgid "cannot read ref file '%s'"
 msgstr "kan inte läsa ref-fil ”%s”"
 
@@ -19778,9 +20625,6 @@
 msgid "cannot open directory %s"
 msgstr "kunde inte öppna katalogen %s"
 
-msgid "Checking references consistency"
-msgstr "Kontrollerar konsistens för referenser"
-
 #, c-format
 msgid "unable to open '%s'"
 msgstr "kan inte öppna ”%s”"
@@ -19820,6 +20664,10 @@
 "flera uppdateringar för ”%s” (inklusive en via symrefen ”%s”) tillåts inte"
 
 #, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr "kan inte låsa referensen ”%s”: hängande symbolisk referens finns redan"
+
+#, c-format
 msgid "cannot lock ref '%s': reference already exists"
 msgstr "kan inte låsa referensen ”%s”: referensen finns redan"
 
@@ -19918,9 +20766,6 @@
 msgid "RPC failed; %s"
 msgstr "RPC misslyckades; %s"
 
-msgid "cannot handle pushes this big"
-msgstr "kan inte hantera så stora sändningar"
-
 #, c-format
 msgid "cannot deflate request; zlib deflate error %d"
 msgstr "kan inte packa upp anrop; zlib-deflate-fel %d"
@@ -20108,6 +20953,11 @@
 "till ”%s:refs/tags/%s”?"
 
 #, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr "<Källa>-delen av ref.spec-en (”%s”) är ett objekt-ID som inte finns.\n"
+
+#, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "%s kan inte slås upp till en gren"
 
@@ -20231,6 +21081,58 @@
 msgstr "kan inte ta bort en komponent från url:en ”%s”"
 
 #, c-format
+msgid "cannot open index for %s"
+msgstr "kunde inte öppna indexet för %s"
+
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr "paketet %s för stort för att tas med i geometriskt förlopp"
+
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "paketet %s för stort att rulla upp"
+
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "kunde inte öppna temporär fil %s för skrivning"
+
+msgid "could not close refs snapshot tempfile"
+msgstr "kunde inte stänga temporär fil för refs-ögonblicksbild"
+
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "kunde inte ta bort gammal bitkarta: %s"
+
+msgid "could not start pack-objects to repack promisor objects"
+msgstr "kunde inte starta pack-objects för att packa om kontraktsobjekt"
+
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "misslyckades sända kontraktsobjekt till pack-objects"
+
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr ""
+"repack: Förväntar kompletta hex-objekt-id-rader endast från pack-objects."
+
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr "kunde inte avsluta pack-objects för att packa om kontraktsobjekt"
+
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "paketprefixet %s börjar inte med objkat %s"
+
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr "misslyckades byta namn på paket till ”%s”"
+
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "pack-objects skrev inte en ”%s”-fil för paketet %s-%s"
+
+#, c-format
+msgid "could not unlink: %s"
+msgstr "kunde inte ta bort: ”%s”"
+
+#, c-format
 msgid "bad replace ref name: %s"
 msgstr "felaktig ersättningsreferensnamn: %s"
 
@@ -21535,9 +22437,6 @@
 msgid "cannot chdir to '%s'"
 msgstr "kan inte byta katalog (chdir) till ”%s”"
 
-msgid "cannot come back to cwd"
-msgstr "kan inte gå tillbaka till arbetskatalogen (cwd)"
-
 #, c-format
 msgid "failed to stat '%*s%s%s'"
 msgstr "misslyckades ta status på ”%*ss%s%s”"
@@ -22601,18 +23500,32 @@
 msgstr "varning: "
 
 #, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "”%s” har nominerats för borttagning.\n"
+
+#, c-format
 msgid ""
-"'%s' 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"
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
 msgstr ""
-"”%s” har nominerats för borttagning.\n"
-"Om du fortfarande använder kommandot, lägg till flaggan\n"
-"”--i-still-use-this” på kommandoraden och berätta för\n"
-"oss att du fortfarande använder det på e-post till\n"
-"<git@vger.kernel.org>. Tack.\n"
+"Om du fortfarande använder det här kommandot kan du:\n"
+"\n"
+"- läsa https://git-scm.com/docs/BreakingChanges.html\n"
+"- se om någon har diskuterat det här på sändlistan\n"
+"  och se om de kommit på något som kan hjälpa dig:\n"
+"  https://lore.kernel.org/git/?q=%s\n"
+"- sända en e-post till <git@vger.kernel.org> för att\n"
+"  berätta för oss att du fortfarande använder kommandot\n"
+"  för att komma fram till en lämplig ersättning\n"
+"\n"
 
 msgid "refusing to run without --i-still-use-this"
 msgstr "vägrar köra utan --i-still-use-this"
@@ -23458,6 +24371,9 @@
 msgid "Send this email reply required"
 msgstr "Svar krävs på frågan ”Sända brevet?”"
 
+msgid "The destination IMAP folder is not properly defined."
+msgstr "Mål-IMAP-mappen har inte angivits korrekt."
+
 msgid "The required SMTP server is not properly defined."
 msgstr "Nödvändig SMTP-server har inte angivits korrekt."
 
diff --git a/po/tr.po b/po/tr.po
index 9c16191..7af591b 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -1,6 +1,6 @@
 # Turkish translations for Git
 # Git Türkçe çevirileri
-# Copyright (C) 2020-2024 Emir SARI <emir_sari@icloud.com>
+# SPDX-FileCopyrightText: 2020-2024, 2025 Emir SARI <emir_sari@icloud.com>
 # This file is distributed under the same license as the Git package.
 # Emir SARI <emir_sari@icloud.com>, 2020-2025
 #
@@ -49,6 +49,7 @@
 # pathspec                    | yol belirteci               #
 # pattern                     | dizgi                       #
 # porcelain                   | okunabilir                  #
+# promisor                    | vaatçi                      #
 # prune                       | buda(mak)                   #
 # pseudoref                   | yalancı başvuru             #
 # pull                        | çek(mek)                    #
@@ -96,15 +97,16 @@
 msgstr ""
 "Project-Id-Version: Git Turkish Localization Project\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2025-08-14 16:38+0300\n"
-"PO-Revision-Date: 2025-08-14 16:45+0300\n"
+"POT-Creation-Date: 2025-11-15 01:30+0300\n"
+"PO-Revision-Date: 2025-11-15 02:00+0300\n"
 "Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
-"Language-Team: Turkish (https://github.com/bitigchi/git-po/)\n"
+"Language-Team: Turkish <kde-i18n-doc@kde.org>\n"
 "Language: tr\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 25.07.70\n"
 
 #, c-format
 msgid "%s cannot be negative"
@@ -628,15 +630,16 @@
 msgstr "Hiçbir şey uygulanmadı.\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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
 "j - bu parça için sonra karar ver, bir sonraki karar verilmemiş parçayı gör\n"
@@ -647,18 +650,19 @@
 "/ - verilen düzenli ifade ile eşleşen bir parça ara\n"
 "s - geçerli parçayı daha ufak parçalara böl\n"
 "e - geçerli parçayı elle düzenle\n"
-"p - geçerli parçalı yazdır, sayfalayıcı için 'P' kullan\n"
+"p - geçerli parçayı yazdır\n"
+"P - geçerli sayfayı sayfalayıcı kullanarak yazdır\n"
 "? - yardımı yazdır\n"
 
 #, c-format
 msgid "Only one letter is expected, got '%s'"
 msgstr "Yalnızca bir harf bekleniyordu, '%s' alındı"
 
-msgid "No previous hunk"
-msgstr "Öncesinde parça yok"
+msgid "No other hunk"
+msgstr "Başka parça yok"
 
-msgid "No next hunk"
-msgstr "Sonrasında parça yok"
+msgid "No other undecided hunk"
+msgstr "Başka karar verilmemiş parça yok"
 
 msgid "No other hunks to goto"
 msgstr "Gidilecek başka bir parça yok"
@@ -2429,17 +2433,22 @@
 msgstr "Eksik nesneleri geçerli aralıklı çıkışa sınırla"
 
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-(new|bad)=<uçbirim> --term-(old|good)=<uçbirim>]    "
-"[--no-checkout] [--first-parent] [<kötü> [<iyi>...]] [--]   [<yol-blrtç>...]"
+"git bisect start [--term-(bad|new)=<yeni> --term-(good|old)=<eski>]\n"
+"                 [--no-checkout] [--first-parent] [<kötü> [<iyi>...]] [--]\n"
+"                 [<yol-belirteci>...]"
 
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "git bisect (good|bad) [<rev>...]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (bad|new|<yeni-terim>) [<revizyon>]"
+
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (good|old|<eski-terim>) [<revizyon>...]"
 
 msgid "git bisect skip [(<rev>|<range>)...]"
-msgstr "git bisect skip [(<rev>|<erim>)...]"
+msgstr "git bisect skip [(<revizyon>|<erim>)...]"
 
 msgid "git bisect reset [<commit>]"
 msgstr "git bisect reset [<işleme>]"
@@ -5417,7 +5426,7 @@
 msgstr "--fixed-value yalnızca 'değer-dizgisi' ile uygulanır"
 
 msgid "--default= cannot be used with --all or --url="
-msgstr "--default=, --all veya --url= ile kullanılamaz"
+msgstr "--default= bayrağı, --all veya --url= ile kullanılamaz"
 
 msgid "--url= cannot be used with --all, --regexp or --value"
 msgstr "--url=; --all, --regexp veya --value ile kullanılamaz"
@@ -5629,6 +5638,14 @@
 msgstr "%i etiket bulundu; arama şurada bitirildi: %s\n"
 
 #, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "henüz doğmamış bir dalda '%s' ikili nesnesi aranamaz"
+
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "'%s' ikili nesnesi, HEAD'den ulaşılabilir değil"
+
+#, c-format
 msgid "describe %s\n"
 msgstr "şunu tanımla: %s\n"
 
@@ -5767,6 +5784,9 @@
 msgid "%s...%s: no merge base"
 msgstr "%s...%s: birleştirme temeli yok"
 
+msgid "cannot come back to cwd"
+msgstr "cwd'ye geri dönülemiyor"
+
 msgid "Not a git repository"
 msgstr "Bir git deposu değil"
 
@@ -5877,10 +5897,140 @@
 msgid "git fast-export [<rev-list-opts>]"
 msgstr "git fast-export [<revizyon-listesi-seçenekleri>]"
 
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "bilinmeyen %s kipi: %s"
+
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "bilinmeyen tag-of-filtered kipi: %s"
+
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "bilinmeyen yeniden kodlama kipi: %s"
+
+#, c-format
+msgid "could not read blob %s"
+msgstr "%s ikili geniş nesnesi okunamadı"
+
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "%s ikili geniş nesnesinde oid uyuşmazlığı"
+
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "\"%s\" ikili geniş nesnesi yazılamadı"
+
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "şunlar için beklenmedik karşılaştırma durumu \"%c\": %s, %s"
+
+msgid "none"
+msgstr "yok"
+
+#, c-format
+msgid "could not find author in commit %s"
+msgstr "%s işlemesinde yazar bulunamadı"
+
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "%s işlemesinde işlemeci bulunamadı"
+
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
 msgstr ""
-"Hata: İç içe geçmiş etiketler --mark-tags belirtilmediği sürece dışa "
-"aktarılamaz."
+"şu işlemede, işlemeye özel %.*s kodlamasına denk gelindi; işlemek için --"
+"reencode[yes|no] kullanın: %s"
+
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr ""
+"imzalanmış %s işlemesine denk gelindi; işlemek için --signed-commits=<kip> "
+"kullanın"
+
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr "şu işleme için %<PRIuMAX> imza dışa aktarılıyor: %s"
+
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr "%s işlemesinden imzalar soyuluyor"
+
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+"etiket ağaçları desteklenmediğinden (veya etiketin etiketinin\n"
+"ağacı), %s etiketi yok sayılıyor"
+
+#, c-format
+msgid "could not read tag %s"
+msgstr "%s etiketi okunamadı"
+
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr ""
+"imzalanmış %s etiketinee denk gelindi; işlemek için --signed-tags=<kip> "
+"kullanın"
+
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "imzalanmış %s etiketi dışa aktarılıyor"
+
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "%s etiketinden imza soyuluyor"
+
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr ""
+"%s etiketi, dışa aktarılmayan nesneyi etiketliyor, işlemek için --tag-of-"
+"filtered-object=<kip> kullanın"
+
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr ""
+"--mark-tags belirtilmediği sürece iç içe geçmiş etiketler dışa aktarılamaz"
+
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "%s etiketi hiçbir yere işaret etmiyor?"
+
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "%s: %s türünden beklenmedik nesne, atlanıyor"
+
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr "etiket, beklenmedik türdeki %s nesnesine işaret ediyor, atlanıyor"
+
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "imler dosyası %s, yazmak için açılamıyor"
+
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "imler dosyası %s yazılamıyor"
+
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "hasarlı im satırı: %s"
+
+#, c-format
+msgid "object not found: %s"
+msgstr "nesne bulunamadı: %s"
+
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "bir işleme değil mi? oldurulamıyor: %s"
+
+#, c-format
+msgid "object %s already has a mark"
+msgstr "%s nesnesinde halihazırda bir im var"
 
 msgid "--anonymize-map token cannot be empty"
 msgstr "--anonymize-map jetonu boş olamaz"
@@ -5947,27 +6097,453 @@
 msgstr "etiketleri im numaralarıyla adlandır"
 
 #, c-format
-msgid "Missing from marks for submodule '%s'"
-msgstr "'%s' altmodülü için '(on)-dan' imleri eksik"
+msgid "can't write crash report %s"
+msgstr "çökme raporu %s yazılamıyor"
 
 #, c-format
-msgid "Missing to marks for submodule '%s'"
-msgstr "'%s' altmodülü için '(o)-na' imleri eksik"
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "fast-import: çökme raporu, %s konumuna dökülüyor\n"
 
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "'mark' komutu bekleniyordu, %s alındı"
+msgid "mark :%<PRIuMAX> not declared"
+msgstr ":%<PRIuMAX> imi beyan edilmemiş"
 
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "'to' komutu bekleniyordu, %s alındı"
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "yinelenmiş dal oluşturmak için geçersiz deneme: %s"
 
-msgid "Expected format name:filename for submodule rewrite option"
-msgstr "Altmodül yeniden yazım seçeneği için name:filename biçimi bekleniyordu"
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "dal adı, Git standartlarına uymuyor: %s"
+
+msgid "internal consistency error creating the index"
+msgstr "indeks oluşturulurken içsel tutarlılık hatası"
+
+msgid "cannot create keep file"
+msgstr "himaye dosyası oluşturulamıyor"
+
+msgid "failed to write keep file"
+msgstr "himaye dosyası yazılamadı"
+
+msgid "cannot store pack file"
+msgstr "paket dosyası depolanamıyor"
+
+msgid "cannot store index file"
+msgstr "indeks dosyası depolanamıyor"
+
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "\"%s\" başlanıcına doğru arama yapılamadı"
+
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "çekirdek Git, %s indeksini reddetti"
+
+msgid "cannot truncate pack to skip duplicate"
+msgstr "yinelenmişleri atlamak üzere paket kısaltılamıyor"
+
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "veride dosya sonu (%<PRIuMAX> bayt kaldı)"
+
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "beklenmedik söndürme hatası: %d"
+
+#, c-format
+msgid "not a tree: %s"
+msgstr "bir ağaç değil: %s"
+
+#, c-format
+msgid "can't load tree %s"
+msgstr "%s ağacı yüklenemiyor"
+
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "%s içinde hasarlı kip"
+
+msgid "root cannot be a non-directory"
+msgstr "kök, bir dizin dışında olamaz"
+
+msgid "empty path component found in input"
+msgstr "girdide boş yol bileşeni"
+
+msgid "non-directories cannot have subtrees"
+msgstr "dizin olmayan ögelerin altağaçları olamaz"
+
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
+msgstr "kendine işaret edeceğinden %s bırakılıyor (yani, %s konumuna)"
+
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "%s dalında işlemeler eksik"
+
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "%s güncellenmiyor (yeni %s ucunda %s yok)"
+
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "%s öncü dizinleri oluşturulamıyor"
+
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "imler dosyası %s yazılamıyor"
+
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "imler dosyası %s yazılamıyor: %s"
+
+#, c-format
+msgid "unable to write file %s"
+msgstr "%s dosyası yazılamıyor"
+
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "\"data n\" komutu bekleniyordu, şu bulundu: %s"
+
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "veride dosya sonu (\"%s\" sonlandırıcısı bulunamadı)"
+
+msgid "data is too large to use in this context"
+msgstr "veri, bu bağlamda kullanmak için pek büyük"
+
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "veride dosya sonu (%lu bayt kalan)"
+
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "kimlik dizisinde < eksik: %s"
+
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "kimlik dizisinde < öncesi boşluk eksik: %s"
+
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "kimlik dizisinde > eksik: %s"
+
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "kimlik dizisinde > öncesi boşluk eksik: %s"
+
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "kimlikte geçersiz ham tarih \"%s\": %s"
+
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "kimlikte geçersiz rfc2822 tarihi \"%s\": %s"
+
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "kimlikteki tarih \"şimdi\" olmalı: %s"
+
+#, c-format
+msgid "too large fanout (%u)"
+msgstr "pek büyük çıkış sayısı (%u)"
+
+#, c-format
+msgid "failed to remove path %s"
+msgstr "%s yolu kaldırılamadı"
+
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "imde \":\" sonrası değer yok: %s"
+
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "im sonrası çöp veri: %s"
+
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "im sonrası boşluk eksik: %s"
+
+#, c-format
+msgid "invalid %s: %s"
+msgstr "geçersiz %s: %s"
+
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "%s içinde NULL: %s"
+
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "%s sonrası çöp veri: %s"
+
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "%s sonrası boşluk eksik: %s"
+
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "hasarlı kip: %s"
+
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "geçersiz veri başvurusu: %s"
+
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "SHA1 sonrası boşluk eksik: %s"
+
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "Git bağlantıları \"satır içi\" olarak belirtilemez: %s"
+
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "bir işleme değil (aslında bir %s): %s"
+
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "dizinler \"satır içi\" olarak belirtilemez: %s"
+
+#, c-format
+msgid "%s not found: %s"
+msgstr "%s bulunamadı: %s"
+
+msgid "tree"
+msgstr "ağaç"
+
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "bir %s değil (aslında bir %s): %s"
+
+#, c-format
+msgid "path %s not in branch"
+msgstr "%s yolu dalda değil"
+
+msgid "can't add a note on empty branch."
+msgstr "boş dala not eklenemiyor"
+
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr ":%<PRIuMAX> imi bir işleme değil"
+
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "geçerli bir işleme değil: %s"
+
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "geçersiz başvuru adı veya SHA1 ifadesi: %s"
+
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "bir ikili geniş nesne değil (aslında bir %s): %s"
+
+#, c-format
+msgid "blob not found: %s"
+msgstr "ikili geniş nesne bulunamadı: %s"
+
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "%s işlemesi hasarlı"
+
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "kendinden bir dal oluşturulamıyor: %s"
+
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
+msgstr ""
+"\"gpgsig <sağlama-algoritması> <imza-biçimi>\" gpgsig biçimi bekleniyordu, "
+"\"gpgsig %s\" alındı"
+
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "gpgsig içinde bilinmeyen sağlama algoritması: \"%s\""
+
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "gpgsig içinde bilinmeyen imza biçimi: \"%s\""
+
+msgid "'unknown' signature format in gpgsig"
+msgstr "gpgsig içinde \"bilinmeyen\" imza biçimi"
+
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr "birden çok %s imzası bulundu, ek imzalar yok sayılıyor"
+
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr "parse_one_signature(), bilinmeyen bir sağlama algoritması döndürdü"
+
+msgid "expected committer but didn't get one"
+msgstr "işlemeci bekleniyordu; ancak bir tane bulunamadı"
+
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr ""
+"imzalı işlemeye denk gelindi; işlemek için --signed-commits=<kip> kullanın"
+
+msgid "stripping a commit signature"
+msgstr "bir işleme imzası soyuluyor"
+
+msgid "importing a commit signature verbatim"
+msgstr "bir işleme imzası olduğu gibi içe aktarılıyor"
+
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr ""
+"imzalanmış etikete denk gelindi; işlemek için --signed-tags=<kip> kullanın"
+
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr "\"%s\" etiketi için bir etiket imzası olduğu gibi içe aktarılıyor"
+
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr "\"%s\" etiketi için bir etiket imzası soyuluyor"
+
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "\"from\" komutu bekleniyordu, \"%s\" alındı"
+
+msgid "can't tag an empty branch."
+msgstr "boş bir dal etiketlenemiyor"
+
+#, c-format
+msgid "not a valid object: %s"
+msgstr "geçerli bir nesne değil: %s"
+
+msgid "write to frontend failed"
+msgstr "ön uca yazım başarısız"
+
+#, c-format
+msgid "can't read object %s"
+msgstr "%s nesnesi okunamıyor"
+
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "%s nesnesi bir %s; ancak bir ikili geniş nesne bekleniyordu"
+
+#, c-format
+msgid "not a mark: %s"
+msgstr "bir im değil: %s"
+
+#, c-format
+msgid "unknown mark: %s"
+msgstr "bilinmeyen im: %s"
+
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "SHA1 sonrası çöp veri: %s"
+
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "bir ağacımsı değil: %s"
+
+#, c-format
+msgid "can't load object %s"
+msgstr "%s nesnesi yüklenemiyor"
+
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "etikette geçersiz SHA1: %s"
+
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "işlemede geçersiz SHA1: %s"
+
+#, c-format
+msgid "missing from marks for submodule '%s'"
+msgstr "\"%s\" altmodülü için \"from\" imleri eksik"
+
+#, c-format
+msgid "missing to marks for submodule '%s'"
+msgstr "\"%s\" altmodülü için \"to\" imleri eksik"
+
+#, c-format
+msgid "missing space after tree-ish: %s"
+msgstr "ağacımsı sonrası eksik boşluk: %s"
+
+#, c-format
+msgid "not in a commit: %s"
+msgstr "bir işleme değil: %s"
+
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "\"mark\" komutu bekleniyordu, %s alındı"
+
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "\"to\" komutu bekleniyordu, %s alındı"
+
+msgid "only one import-marks command allowed per stream"
+msgstr "akış başına yalnızca bir import-marks komutuna izin veriliyor"
+
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "bilinmeyen --date-format argümanı %s"
+
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s: argüman, negatif olmayan bir tamsayı olmalı"
+
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr "--depth, %u değerini aşamaz"
+
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr "--cat-blob-fd, %d değerini aşamaz"
+
+msgid "expected format name:filename for submodule rewrite option"
+msgstr "altmodül yeniden yazım seçeneği için ad:dosya-adı biçimi bekleniyordu"
+
+#, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr "max-pack-size artık bayt türünden, --max-pack-size=%lum varsayılıyor"
+
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "olabilecek en küçük max-pack-size 1 MiB'dır"
+
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "bilinmeyen --signed-commits kipi \"%s\""
+
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "bilinmeyen --signed-tags kipi \"%s\""
 
 #, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
-msgstr "'%s' özelliği --allow-unsafe-features olmadan girdide yasaklı"
+msgstr "\"%s\" özelliği --allow-unsafe-features olmadan girdide yasaklı"
+
+#, c-format
+msgid "got feature command '%s' after data command"
+msgstr "veri komutu sonrası \"%s\" komut özelliği alındı"
+
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "fast-import'un bu sürümü şu özelliği desteklemiyor: %s"
+
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr "veri komutu sonrası \"%s\" komut seçeneği alındı"
+
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "fast-import'un bu sürümü şu seçeneği desteklemiyor: %s"
+
+#, c-format
+msgid "unknown option %s"
+msgstr "bilinmeyen seçenek %s"
+
+#, c-format
+msgid "unknown option --%s"
+msgstr "bilinmeyen seçenek --%s"
+
+#, c-format
+msgid "unsupported command: %s"
+msgstr "desteklenmeyen komut: %s"
+
+msgid "stream ends early"
+msgstr "akış erken bitiyor"
 
 #, c-format
 msgid "Lockfile created but not reported: %s"
@@ -6106,6 +6682,36 @@
 "komutunu çalıştırmak, uyarıyı HEAD'e veya başka bir şeye uzaktan\n"
 "değişiklik olana dek devre dışı bırakır."
 
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+"BÜYÜK/küçük harf duyarsız bir dosya sistemindesiniz ve getirmeye\n"
+"çalıştığınız uzak konumda harf biçiminden dolayı farklar içeren\n"
+"başvurular var. Bu tür başvuruları 'files' arka ucuyla depolamak\n"
+"olanaklı değildir. Bunu ya olduğu gibi kabul edebilir (bu durumda\n"
+"tüm uzak başvuruları diskte depolayamazsınız) ya da alternatif\n"
+"olarak deponuzu aşağıdaki komutla 'reftable' arka ucuna geçirerek\n"
+"bunu çözebilirsiniz:\n"
+"\n"
+"\tgit refs migrate --ref-format=reftable\n"
+"\n"
+"Lütfen Git'in tüm gerçeklemelerinin bu yeni biçimi henüz\n"
+"desteklemediğini not edin. Bu depoya erişmek için Git'ten farklı bir\n"
+"araçlar kullanıyorsanız başvuru tablolarına göç uygun bir seçenek\n"
+"değildir.\n"
+
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -6349,21 +6955,6 @@
 msgid "file to read from"
 msgstr "okunacak dosya"
 
-msgid "git for-each-ref [<options>] [<pattern>]"
-msgstr "git for-each-ref [<seçenekler>] [<dizgi>]"
-
-msgid "git for-each-ref [--points-at <object>]"
-msgstr "git for-each-ref [--points-at <nesne>]"
-
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr "git for-each-ref [--merged [<işleme>]] [--no-merged [<işleme>]]"
-
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr "git for-each-ref [--contains [<işleme>]] [--no-contains [<işleme>]]"
-
-msgid "git for-each-ref [--start-after <marker>]"
-msgstr "git for-each-ref [--start-after <imleyici>]"
-
 msgid "quote placeholders suitably for shells"
 msgstr "yer tutucuları kabuğun anlayabileceği biçimde tırnak içine al"
 
@@ -6418,6 +7009,9 @@
 msgid "cannot use --start-after with patterns"
 msgstr "dizgilerle --start-after kullanılamıyor"
 
+msgid "git for-each-ref "
+msgstr "git for-each-ref "
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<yapılandırma> [--] <argümanlar>"
 
@@ -6886,6 +7480,9 @@
 msgstr ""
 "incremental-repack görevi atlanıyor; çünkü core.multiPackIndex devre dışı"
 
+msgid "failed to perform geometric repack"
+msgstr "geometrik yeniden paketleme yapılamadı"
+
 #, c-format
 msgid "task '%s' failed"
 msgstr "'%s' görevi başarısız oldu"
@@ -6895,6 +7492,10 @@
 msgstr "kilit dosyası '%s' var, bakım atlanıyor"
 
 #, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "bilinmeyen bakım stratejisi: '%s'"
+
+#, c-format
 msgid "'%s' is not a valid task"
 msgstr "'%s' geçerli bir görev değil"
 
@@ -7761,6 +8362,29 @@
 msgid "no input file given for in-place editing"
 msgstr "yerinde düzenleme için girdi dosyası verilmedi"
 
+msgid "last-modified can only operate on one tree at a time"
+msgstr "last-modified yalnızca aynı anda bir ağaç üzerinde işleyebilir"
+
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "bilinmeyen last-modified argümanı: %s"
+
+msgid "unable to setup last-modified"
+msgstr "last-modified ayarları yapılamıyor"
+
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+"git last-modified [--recursive] [--show-trees] [<revizyon-erimi>]\n"
+"[[--] <yol>...]"
+
+msgid "recurse into subtrees"
+msgstr "altağaçlara özyinele"
+
+msgid "show tree entries when recursing into subtrees"
+msgstr "altağaçlara özyinelerken ağaç girdilerini göster"
+
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
 msgstr "git log [<seçenekler>] [<revizyon-erimi>] [[--] <yol>...]"
 
@@ -7799,6 +8423,22 @@
 msgid "-L<range>:<file> cannot be used with pathspec"
 msgstr "-L<erim>:<dosya>, yol belirteci ile kullanılamıyor"
 
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+"\n"
+"ipucu: 'git whatchanged <seçenekler>'i şununla değiştirebilirsiniz:\n"
+"ipucu:\tgit log <seçenekler> --raw --no-merges\n"
+"ipucu: Veya bir arma yapın:\n"
+"ipucu:\tgit config set --global alias.whatchanged\n"
+"          'log --raw --no-merges'\n"
+"\n"
+
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s: hatalı dosya"
@@ -8233,9 +8873,6 @@
 msgid "only show trees"
 msgstr "yalnızca ağaçları göster"
 
-msgid "recurse into subtrees"
-msgstr "altağaçlara özyinele"
-
 msgid "show trees when recursing"
 msgstr "özyinelerken ağaçları göster"
 
@@ -8383,10 +9020,6 @@
 msgstr "nesne dosyası yazılamadı"
 
 #, c-format
-msgid "unknown option %s"
-msgstr "bilinmeyen seçenek %s"
-
-#, c-format
 msgid "could not parse object '%s'"
 msgstr "'%s' nesnesi ayrıştırılamadı"
 
@@ -8554,10 +9187,6 @@
 msgid "stash failed"
 msgstr "zulalama başarısız oldu"
 
-#, c-format
-msgid "not a valid object: %s"
-msgstr "geçerli bir nesne değil: %s"
-
 msgid "read-tree failed"
 msgstr "read-tree başarısız oldu"
 
@@ -9688,27 +10317,8 @@
 "Toplam %<PRIu32> (delta %<PRIu32>), yeniden kullanılan %<PRIu32> (delta "
 "%<PRIu32>), yeniden kullanılan paket %<PRIu32> (%<PRIuMAX> konumundan)"
 
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <dizgi>] [--exclude "
-"<dizgi>]"
-
-msgid "pack everything"
-msgstr "her şeyi paketle"
-
-msgid "prune loose refs (default)"
-msgstr "gevşek başvuruları buda (öntanımlı)"
-
-msgid "auto-pack refs as needed"
-msgstr "gerekirse başvuruları paketle"
-
-msgid "references to include"
-msgstr "içerilecek başvurular"
-
-msgid "references to exclude"
-msgstr "dışarıda tutulacak başvurular"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
 msgid "git patch-id [--stable | --unstable | --verbatim]"
 msgstr "git patch-id [--stable | --unstable | --verbatim]"
@@ -10216,6 +10826,10 @@
 msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
 msgstr "git range-diff [<seçenekler>] <base> <old-tip> <new-tip>"
 
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "geçersiz en büyük bellek değeri: %s"
+
 msgid "use simple diff colors"
 msgstr "yalın diff renklerini kullan"
 
@@ -10225,6 +10839,12 @@
 msgid "passed to 'git log'"
 msgstr "'git log'a aktarıldı"
 
+msgid "size"
+msgstr "büyüklük"
+
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr "maliyet matrisi için en büyük bellek (öntanımlı 4 G)"
+
 msgid "only emit output related to the first range"
 msgstr "yalnızca ilk erimle ilişkili çıktıyı yay"
 
@@ -10781,6 +11401,22 @@
 msgid "git reflog list"
 msgstr "git reflog list"
 
+msgid "git reflog exists <ref>"
+msgstr "git reflog exists <başvuru>"
+
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr "git reflog write <başvuru> <eski-oid> <yeni-oid> <ileti>"
+
+msgid ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+msgstr ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <başvuru>@{<belirteç>}..."
+
+msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
+msgstr "git reflog drop [--all [--single-worktree] | <başvurular>...]"
+
 msgid ""
 "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
 "                  [--rewrite] [--updateref] [--stale-fix]\n"
@@ -10792,19 +11428,6 @@
 "                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
 "<zaman>...]"
 
-msgid ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-msgstr ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <başvuru>@{<belirteç>}..."
-
-msgid "git reflog exists <ref>"
-msgstr "git reflog exists <başvuru>"
-
-msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
-msgstr "git reflog drop [--all [--single-worktree] | <başvurular>...]"
-
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "geçersiz zaman damgası '%s', '--%s' argümanına verildi"
@@ -10873,12 +11496,50 @@
 msgid "references specified along with --all"
 msgstr "--all ile belirtilmiş başvurular"
 
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "geçersiz başvuru adı: %s"
+
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "geçersiz eski nesne kimliği: %s"
+
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "eski nesne '%s' yok"
+
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "geçersiz yeni nesne kimliği: %s"
+
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "yeni nesne '%s' yok"
+
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr "işlem başlatılamıyor: %s"
+
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr "başvuru günlüğü güncellemesi kuyruklanamadı: %s"
+
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr "başvuru günlüğü güncellemesi işlenemiyor: %s"
+
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=<biçim> [--no-reflog] [--dry-run]"
 
 msgid "git refs verify [--strict] [--verbose]"
 msgstr "git refs verify [--strict] [--verbose]"
 
+msgid "git refs exists <ref>"
+msgstr "git refs exists <başvuru>"
+
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
 msgid "specify the reference format to convert to"
 msgstr "dönüştürülecek başvuru biçimini belirt"
 
@@ -10901,6 +11562,18 @@
 msgid "'git refs verify' takes no arguments"
 msgstr "'git refs verify' bir argüman almıyor"
 
+msgid "git refs list "
+msgstr "git refs list"
+
+msgid "'git refs exists' requires a reference"
+msgstr "'git refs exists' bir başvuru gerektiriyor"
+
+msgid "reference does not exist"
+msgstr "başvuru yok"
+
+msgid "failed to look up reference"
+msgstr "başvuru bakılamadı"
+
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
 "mirror=<fetch|push>] <name> <url>"
@@ -11060,6 +11733,24 @@
 "\t%s:%d\n"
 "artık var olmayan '%s' uzak konumunu adlandırıyor"
 
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+"Yeniden adlandırmaya çalıştığınız uzak konumun yeni hedef başvuru\n"
+"belirtecinde çakışan başvurular var. Bu, büyük olasılıkla sizin\n"
+"bir uzak konumu başka bir uzak konumun içine geçirmeye çalışmanızdan\n"
+"dolayı oldu; örneğin, 'üst öge'yi 'üst öge/alt öge' olarak yeniden\n"
+"adlandırmanızdan veya tersini yaparak içeriden çıkarmanızdan.\n"
+"\n"
+"Eğer durum buysa önce uzak konumu başka bir şekilde yeniden\n"
+"adlandırarak bu sorunu çözebilirsiniz.\n"
+
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "Böyle bir uzak konum yok: '%s'"
@@ -11068,6 +11759,13 @@
 msgid "Could not rename config section '%s' to '%s'"
 msgstr "'%s' yapılandırma bölümü '%s' olarak yeniden adlandırılamadı"
 
+msgid "Renaming remote references"
+msgstr "Uzak konum başvuruları yeniden adlandırılıyor"
+
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr "uzak başvuru adlarını kuyruklama başarısız: %s"
+
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -11078,16 +11776,9 @@
 "\t%s\n"
 "\tLütfen gerekirse yapılandırmayı el ile güncelleyin."
 
-msgid "Renaming remote references"
-msgstr "Uzak konum başvuruları yeniden adlandırılıyor"
-
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "'%s' silinmesi başarısız"
-
-#, c-format
-msgid "creating '%s' failed"
-msgstr "'%s' oluşturulması başarısız"
+msgid "renaming remote refs failed: %s"
+msgstr "uzak başvurular yeniden adlandırılamadı: %s"
 
 msgid ""
 "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
@@ -11371,46 +12062,6 @@
 "--no-write-bitmap-index kullanın veya pack.writeBitmaps\n"
 "yapılandırmasını devre dışı bırakın."
 
-msgid "could not start pack-objects to repack promisor objects"
-msgstr "vaatçi nesneleri yeniden paketleme için pack-objects başlatılamadı"
-
-msgid "failed to feed promisor objects to pack-objects"
-msgstr "vaatçi nesneleri pack-objects'e beslenemedi"
-
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr ""
-"repack: Onaltılı tam nesne no satırları yalnızca pack-objects'ten bekleniyor."
-
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr "vaatçi nesneleri yeniden paketleme için pack-objects bitirilemedi"
-
-#, c-format
-msgid "cannot open index for %s"
-msgstr "%s için indeks açılamıyor"
-
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr "%s paketi, geometrik ilerlemede kullanmayı düşünmek için pek büyük"
-
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "%s paketi, sarmak için pek büyük"
-
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "geçici dosya '%s', yazma için açılamadı"
-
-msgid "could not close refs snapshot tempfile"
-msgstr "başvurular anlık görüntü geçici dosyası kapatılamadı"
-
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "eskimiş biteşlem kaldırılamadı: %s"
-
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "paket öneki %s, nesne dizini %s ile başlamıyor"
-
 msgid "pack everything in a single pack"
 msgstr "her şeyi tek bir pakete sığdır"
 
@@ -11507,18 +12158,6 @@
 msgid "Nothing new to pack."
 msgstr "Paketlenecek yeni bir şey yok."
 
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "paketi '%s' olarak yeniden adlandırma başarısız"
-
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "pack-objects, şu paket için bir '%s' dosyası yazmadı: %s-%s"
-
-#, c-format
-msgid "could not unlink: %s"
-msgstr "bağlantı kaldırılamadı: %s"
-
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] <nesne> <değişim>"
 
@@ -11774,6 +12413,62 @@
 msgid "replaying merge commits is not supported yet!"
 msgstr "birleştirme işlemelerini yeniden oynatma henüz desteklenmiyor!"
 
+#, c-format
+msgid "key '%s' not found"
+msgstr "'%s' anahtarı bulunamadı"
+
+#, c-format
+msgid "invalid format '%s'"
+msgstr "geçersiz biçim '%s'"
+
+msgid "output format"
+msgstr "çıktı biçimi"
+
+msgid "synonym for --format=nul"
+msgstr "--format=nul eşanlamlısı"
+
+msgid "unsupported output format"
+msgstr "desteklenmeyen çıktı biçimi"
+
+msgid "References"
+msgstr "Başvurular"
+
+msgid "Count"
+msgstr "Sayım"
+
+msgid "Branches"
+msgstr "Dallar"
+
+msgid "Tags"
+msgstr "Etiketler"
+
+msgid "Remotes"
+msgstr "Uzak konumlar"
+
+msgid "Others"
+msgstr "Diğerleri"
+
+msgid "Reachable objects"
+msgstr "Ulaşılabilir nesneler"
+
+msgid "Commits"
+msgstr "İşlemeler"
+
+msgid "Trees"
+msgstr "Ağaçlar"
+
+msgid "Blobs"
+msgstr "İkili geniş nesneler"
+
+msgid "Repository structure"
+msgstr "Depo yapısı"
+
+msgid "Value"
+msgstr "Değer"
+
+msgid "Counting references"
+msgstr "Başvurular sayılıyor"
+
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
 msgstr ""
@@ -12364,12 +13059,6 @@
 msgid "git show-ref --exists <ref>"
 msgstr "git show-ref --exists <başvuru>"
 
-msgid "reference does not exist"
-msgstr "başvuru yok"
-
-msgid "failed to look up reference"
-msgstr "başvuru bakılamadı"
-
 msgid "only show tags (can be combined with --branches)"
 msgstr "yalnızca etiketleri göster (--branches ile birlikte kullanılabilir)"
 
@@ -12399,10 +13088,10 @@
 
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
-"git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<seçenekler>]"
+"git sparse-checkout (init | list | set | add | reapply | disable\n"
+"| check-rules | clean) [<seçenekler>]"
 
 msgid "this worktree is not sparse"
 msgstr "bu çalışma ağacı aralıklı değil"
@@ -12443,10 +13132,6 @@
 msgstr "bir aralıklı indeksin kullanımını aç/kapat"
 
 #, c-format
-msgid "unable to create leading directories of %s"
-msgstr "%s öncü dizinleri oluşturulamıyor"
-
-#, c-format
 msgid "failed to open '%s'"
 msgstr "'%s' açılamadı"
 
@@ -12525,6 +13210,32 @@
 "aralıklılık dizgilerinin yeniden uygulanması için bir aralıklı çıkış içinde "
 "olmalı"
 
+msgid "report each affected file, not just directories"
+msgstr "yalnızca dizinler değil, tüm etkilenen dosyaları raporla"
+
+msgid "must be in a sparse-checkout to clean directories"
+msgstr "dizinleri temizlemek için bir aralıklı çıkış içinde olmalı"
+
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr "dizinleri temizlemek için koni kipindeki bir aralıklı çıkışta olmalı"
+
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr "güvenlik için --force veya --dry-run olmadan temizleme reddediliyor"
+
+msgid "failed to read index"
+msgstr "indeks okunamadı"
+
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr ""
+"indeks bir aralıklı indekse dönüştürülemedi; birleştirme çakışmalarını çözün "
+"ve yeniden deneyin"
+
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "'%s' kaldırılamadı"
+
 msgid "error while refreshing working directory"
 msgstr "çalışma dizini yenilenirken hata"
 
@@ -14207,9 +14918,6 @@
 msgid "only useful for debugging"
 msgstr "yalnızca hata ayıklama için yararlı"
 
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "core.fsyncMethod = batch, bu platformda desteklenmiyor"
-
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
 msgstr "demet liste anahtarı %s ile '%s' değeri ayrıştırılamıyor"
@@ -14599,6 +15307,9 @@
 msgid "Add or parse structured information in commit messages"
 msgstr "İşleme iletilerine düzenli bilgi ekle veya ayrıştır"
 
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr "DENEYSEL: Dosyaların en son ne zaman değiştirildiğini göster"
+
 msgid "Show commit logs"
 msgstr "İşleme günlüklerini göster"
 
@@ -14719,6 +15430,9 @@
 msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
 msgstr "DENEYSEL: İşlemeleri yeni temelde oynat, çıplak depolarla çalışır"
 
+msgid "Retrieve information about the repository"
+msgstr "Depo hakkında bilgi getir"
+
 msgid "Generates a summary of pending changes"
 msgstr "Bekleyen değişikliklerin bir özetini çıkart"
 
@@ -14800,8 +15514,8 @@
 msgid "Read, modify and delete symbolic refs"
 msgstr "Sembolik başvuruları oku, düzenle ve sil"
 
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr "GPG imzalı etiket oluştur, sil, listele, doğrula"
+msgid "Create, list, delete or verify tags"
+msgstr "Etiket oluştur, sil, listele, doğrula"
 
 msgid "Creates a temporary file with a blob's contents"
 msgstr "İkili nesnenin içeriği ile geçici bir dosya oluştur"
@@ -15644,6 +16358,45 @@
 msgid "unable to parse command-line config"
 msgstr "komut satırı yapılandırması ayrıştırılamıyor"
 
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"Öntanımlı yorum dizisini kullanmak için (#) şunu çalıştırın:\n"
+"\n"
+"%s"
+
+msgid "<comment string>"
+msgstr "<yorum-dizisi>"
+
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+"\n"
+"Özel bir yorum dizisi ayarlamak için şunu çalıştırın\n"
+"\n"
+"%s\n"
+"'%s', kullanmak istediğiniz dizidir.\n"
+
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr "'%s=auto' için olan destek Git 3.0 sürümünde kaldırılmıştır"
+
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr ""
+"'%s=auto' için olan destek artık kullanılmamaktadır ve Git 3.0 sürümünde "
+"kaldırılacaktır"
+
 msgid "unknown error occurred while reading the configuration files"
 msgstr "yapılandırma dosyaları okunurken beklenmedik bir hata oluştu"
 
@@ -16122,6 +16875,12 @@
 msgid "failed to write archive"
 msgstr "arşiv yazılamadı"
 
+msgid "max-depth is not supported for worktree diffs"
+msgstr "max-depth, çalışma ağacı diff'lerinde desteklenmiyor"
+
+msgid "max-depth is not supported for index diffs"
+msgstr "max-depth, indeks diff'lerinde desteklenmiyor"
+
 msgid "--merge-base does not work with ranges"
 msgstr "--merge-base erimlerle çalışmaz"
 
@@ -16627,6 +17386,12 @@
 msgid "select files by diff type"
 msgstr "dosyaları diff türüne göre seç"
 
+msgid "<depth>"
+msgstr "<derinlik>"
+
+msgid "maximum tree depth to recurse"
+msgstr "özyinelenecek en çok ağaç derinliği"
+
 msgid "<file>"
 msgstr "<dosya>"
 
@@ -16824,10 +17589,6 @@
 msgstr "geçersiz sığ olmayan satır: %s"
 
 #, c-format
-msgid "object not found: %s"
-msgstr "nesne bulunamadı: %s"
-
-#, c-format
 msgid "error in object: %s"
 msgstr "nesne içinde hata: %s"
 
@@ -17105,6 +17866,10 @@
 msgid "recursive alias: %s"
 msgstr "özyineli arma: %s"
 
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr "arma döngüsü algılandı: '%s' genişletilmesi sonlanmıyor:%s"
+
 msgid "write failure on standard output"
 msgstr "standart çıktı'da yazma hatası"
 
@@ -17115,10 +17880,6 @@
 msgstr "standart çıktı'da kapatma başarısız"
 
 #, c-format
-msgid "alias loop detected: expansion of '%s' does not terminate:%s"
-msgstr "arma döngüsü algılandı: '%s' genişletilmesi sonlanmıyor:%s"
-
-#, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "%s bir yerleşik olarak ele alınamıyor"
 
@@ -17172,6 +17933,10 @@
 msgid "failed to get the ssh fingerprint for key '%s'"
 msgstr "'%s' anahtarı için ssh parmak izi alınamadı"
 
+#, c-format
+msgid "failed to get the ssh fingerprint for key %s"
+msgstr "%s anahtarı için ssh parmak izi alınamadı"
+
 msgid ""
 "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
 msgstr ""
@@ -17179,6 +17944,10 @@
 "gerekiyor"
 
 #, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr "gpg.ssh.defaultKeyCommand için hatalı yapı süresi: %s"
+
+#, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr ""
 "gpg.ssh.defaultKeyCommand başarılı oldu; ancak herhangi bir anahtar "
@@ -17434,6 +18203,12 @@
 " şu istendi: %s\n"
 "   yönlenen: %s"
 
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr ""
+"bu platformda curl_off_t olarak temsil etmek için sayı pek büyük: %<PRIuMAX>"
+
 msgid "Author identity unknown\n"
 msgstr "Yazar kimliği bilinmiyor\n"
 
@@ -17897,10 +18672,6 @@
 msgstr "paket yüklenemedi"
 
 #, c-format
-msgid "could not open index for %s"
-msgstr "%s için indeks açılamadı"
-
-#, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "'%s', '%s' ile bağlantılanamıyor"
 
@@ -17923,6 +18694,10 @@
 msgstr "bilinmeyen tercih edilen paket: '%s'"
 
 #, c-format
+msgid "failed to open preferred pack %s"
+msgstr "yeğlenen paket %s açılamadı"
+
+#, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr "yeğlenen paket %s nesnesiz seçilemiyor"
 
@@ -17946,6 +18721,9 @@
 msgid "could not write multi-pack bitmap"
 msgstr "çoklu paket biteşlem yazılamadı"
 
+msgid "too many multi-pack-indexes"
+msgstr "pek çok multi-pack-indexes"
+
 msgid "unable to open multi-pack-index chain file"
 msgstr "multi-pack-index zincir dosyası açılamıyor"
 
@@ -18209,10 +18987,6 @@
 msgstr "'%s' ve '%s' dosyalarının içeriği farklı"
 
 #, c-format
-msgid "unable to write file %s"
-msgstr "%s dosyası yazılamıyor"
-
-#, c-format
 msgid "unable to write repeatedly vanishing file %s"
 msgstr "sürekli olarak kaybolan %s dosyası yazılamıyor"
 
@@ -18220,6 +18994,9 @@
 msgid "unable to set permission to '%s'"
 msgstr "'%s' ögesine izin ayarlanamıyor"
 
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = batch, bu platformda desteklenmiyor"
+
 msgid "error when closing loose object file"
 msgstr "gevşek nesne dosyası kapatılırken hata"
 
@@ -18719,6 +19496,21 @@
 msgid "mtimes file %s is corrupt"
 msgstr "%s mtimes dosyası hasarlı"
 
+msgid "pack everything"
+msgstr "her şeyi paketle"
+
+msgid "prune loose refs (default)"
+msgstr "gevşek başvuruları buda (öntanımlı)"
+
+msgid "auto-pack refs as needed"
+msgstr "gerekirse başvuruları paketle"
+
+msgid "references to include"
+msgstr "içerilecek başvurular"
+
+msgid "references to exclude"
+msgstr "dışarıda tutulacak başvurular"
+
 #, c-format
 msgid "reverse-index file %s is too small"
 msgstr "reverse-index dosyası %s pek küçük"
@@ -19139,6 +19931,10 @@
 msgstr "vaatçi uzak konumundan %s getirilemedi"
 
 #, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr "şu yapılandırmada desteklenmeyen '%s' alanı: '%s'"
+
+#, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "'%s' uzak konumu için olmayan veya boş URL sağlandı"
 
@@ -19147,12 +19943,16 @@
 msgstr "bilinen uzak konum adı '%s'; ancak URL'si '%s'; '%s' olmalı"
 
 #, c-format
-msgid "unknown '%s' value for '%s' config option"
-msgstr "'%s' yapılandırma seçeneği için bilinmeyen değer: '%s'"
+msgid "invalid element '%s' from remote info"
+msgstr "uzak konum bilgisinden geçersiz '%s' ögesi"
 
 #, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "uzak bilgiden bilinmeyen öge '%s'"
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr "sunucu bir ad veya URL olmadan bir vaatçiyi öne sürdü: %s"
+
+#, c-format
+msgid "unknown '%s' value for '%s' config option"
+msgstr "'%s' yapılandırma seçeneği için bilinmeyen değer: '%s'"
 
 #, c-format
 msgid "accepted promisor remote '%s' not found"
@@ -19250,6 +20050,16 @@
 msgstr "diff oluşturulamadı"
 
 #, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+"range-diff: maliyet matrisi için olan en çok belleği aştığından range-diff "
+"hesaplanamıyor: %s (%<PRIuMAX> bayt) gerekiyor, %s (%<PRIuMAX> bayt) olarak "
+"sınırlı"
+
+#, c-format
 msgid "could not parse log for '%s'"
 msgstr "'%s' günlüğü ayrıştırılamadı"
 
@@ -19775,6 +20585,9 @@
 msgid "no reflog for '%s'"
 msgstr "'%s' için başvuru günlüğü yok"
 
+msgid "Checking references consistency"
+msgstr "Başvuruların tutarlılığı denetleniyor"
+
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "%s geçerli bir nesneye işaret etmiyor!"
@@ -19790,8 +20603,9 @@
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -19800,9 +20614,10 @@
 "\n"
 "\tgit branch -m <name>\n"
 msgstr ""
-"Başlangıç dal adı olarak %s kullanılıyor. Bu öntanımlı dal adı\n"
-"değiştirilebilir. Bu iletiyi kapatmak ve yeni depolarınızda kullanılacak\n"
-"başlangıç dal adını yapılandırmak için şu komutu kullanın:\n"
+"Başlangıç dal adı olarak '%s' kullanılıyor. Öntanımlı dal\n"
+"adı Git 3.0 sürümünde 'main' olarak değiştirilecektir. Tüm yeni\n"
+"depolarınızda kullanılacak dal adını ayarlamak ve bu iletiyi susturmak\n"
+"için şu komutu kullanın:\n"
 "\n"
 "\tgit config --global init.defaultBranch <ad>\n"
 "\n"
@@ -19813,6 +20628,20 @@
 "\tgit branch -m <ad>\n"
 
 #, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"Git 3.0 sürümünden itibaren başlangıç dal adı olarak '%s'\n"
+"kullanılıyor. Git'in 'master' kullanmasını bekliyorduysanız yeni\n"
+"dal adı şu komutla değiştirilebilir:\n"
+"\n"
+"\tgit branch -m master\n"
+
+#, c-format
 msgid "could not retrieve `%s`"
 msgstr "'%s' alınamadı"
 
@@ -19899,6 +20728,27 @@
 msgid "migrated refs can be found at '%s'"
 msgstr "göç ettirilen başvurular '%s' konumunda bulunabilir"
 
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+"'core.preferSymlinkRefs=true', kaldırılma için aday gösterildi.\n"
+"ipucu: Sembolik başvurular için sembolik bağların kullanılması\n"
+"ipucu: artık yapılmayacak ve Git 3.0 sürümünde toptan kaldırılacak.\n"
+"ipucu: Git'in bunu kullanmasını söyleyen yapılandırma artık olmayacak.\n"
+"ipucu: Bunu, aşağıdaki komutu kullanarak kapatabilirsiniz:\n"
+"ipucu:\n"
+"ipucu:\tgit config unset core.preferSymlinkRefs\n"
+"ipucu:\n"
+"ipucu: Git o zaman metinsel sembolik başvuru biçimini kullanır."
+
 #, c-format
 msgid ""
 "cannot lock ref '%s': expected symref with target '%s': but is a regular ref"
@@ -19907,6 +20757,11 @@
 "bekleniyordu; ancak bu normal bir başvuru"
 
 #, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr ""
+"\"%s\" için olan başvuru günlüğüne eksik değerlerle yazılmaya çalışılıyor"
+
+#, c-format
 msgid "cannot read ref file '%s'"
 msgstr "başvuru dosyası '%s' yazılamıyor"
 
@@ -19914,9 +20769,6 @@
 msgid "cannot open directory %s"
 msgstr "%s dizini açılamıyor"
 
-msgid "Checking references consistency"
-msgstr "Başvuruların tutarlılığı denetleniyor"
-
 #, c-format
 msgid "unable to open '%s'"
 msgstr "'%s' açılamıyor"
@@ -19957,6 +20809,10 @@
 "de içeren) izin verilmiyor"
 
 #, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr "'%s' başvurusu kilitlenemiyor: Sallanan başvuru halihazırda var"
+
+#, c-format
 msgid "cannot lock ref '%s': reference already exists"
 msgstr "'%s' başvurusu kilitlenemiyor: Başvuru halihazırda var"
 
@@ -20056,9 +20912,6 @@
 msgid "RPC failed; %s"
 msgstr "RPC başarısız oldu; %s"
 
-msgid "cannot handle pushes this big"
-msgstr "bu kadar büyük itmeler ele alınamıyor"
-
 #, c-format
 msgid "cannot deflate request; zlib deflate error %d"
 msgstr "istek söndürülemiyor; 'zlib deflate' hatası %d"
@@ -20250,6 +21103,12 @@
 "etiketlemek istediniz?"
 
 #, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr ""
+"Başvuru belirtecinin <kaynak> kısmı ('%s'), var olmayan bir nesne kimliği.\n"
+
+#, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "%s dala çözülemiyor"
 
@@ -20373,6 +21232,58 @@
 msgstr "'%s' url'sinden bir bileşen çıkarılamıyor"
 
 #, c-format
+msgid "cannot open index for %s"
+msgstr "%s için indeks açılamıyor"
+
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr "%s paketi, geometrik ilerlemede kullanmayı düşünmek için pek büyük"
+
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "%s paketi, sarmak için pek büyük"
+
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "geçici dosya '%s', yazma için açılamadı"
+
+msgid "could not close refs snapshot tempfile"
+msgstr "başvurular anlık görüntü geçici dosyası kapatılamadı"
+
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "eskimiş biteşlem kaldırılamadı: %s"
+
+msgid "could not start pack-objects to repack promisor objects"
+msgstr "vaatçi nesneleri yeniden paketleme için pack-objects başlatılamadı"
+
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "vaatçi nesneleri pack-objects'e beslenemedi"
+
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr ""
+"repack: Onaltılı tam nesne no satırları yalnızca pack-objects'ten bekleniyor."
+
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr "vaatçi nesneleri yeniden paketleme için pack-objects bitirilemedi"
+
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "paket öneki %s, nesne dizini %s ile başlamıyor"
+
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr "paketi '%s' olarak yeniden adlandırma başarısız"
+
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "pack-objects, şu paket için bir '%s' dosyası yazmadı: %s-%s"
+
+#, c-format
+msgid "could not unlink: %s"
+msgstr "bağlantı kaldırılamadı: %s"
+
+#, c-format
 msgid "bad replace ref name: %s"
 msgstr "hatalı değiştirme başvurusu adı: %s"
 
@@ -20461,7 +21372,7 @@
 msgstr "gizli başvurular için desteklenmeyen bölüm: %s"
 
 msgid "--exclude-hidden= passed more than once"
-msgstr "--exclude-hidden=, birden çok kez geçirildi"
+msgstr "--exclude-hidden= bayrağı birden çok kez geçirildi"
 
 #, c-format
 msgid "resolve-undo records `%s` which is missing"
@@ -21672,9 +22583,6 @@
 msgid "cannot chdir to '%s'"
 msgstr "'%s' konumuna chdir yapılamıyor"
 
-msgid "cannot come back to cwd"
-msgstr "cwd'ye geri dönülemiyor"
-
 #, c-format
 msgid "failed to stat '%*s%s%s'"
 msgstr "'%*s%s%s' bilgileri alınamadı"
@@ -22732,19 +23640,32 @@
 msgstr "uyarı: "
 
 #, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "'%s', kaldırılması için aday gösterildi.\n"
+
+#, c-format
 msgid ""
-"'%s' 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"
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
 msgstr ""
-"'%s' komutu, kaldırma için aday\n"
-"gösterildi. Bu komutu hâlâ kullanıyorsanız lütfen\n"
-"komut satırında '--i-still-use-this' ek seçeneğini\n"
-"kullanın ve bunu hâlâ kullandığınızı\n"
-"<git@vger.kernel.org> adresine bir e-posta atarak\n"
-"bize haber verin. Sağ olun.\n"
+"Bu komutu hâlâ kullanıyorsanız şunları yapabilirsiniz:\n"
+"\n"
+"- https://git-scm.com/docs/BreakingChanges.html sayfasını okuyun\n"
+"- posta listesinde herhangi bir kişinin bunun hakkında konuşup\n"
+"  konuşmadığına ve size yardımcı olabilecek bir şey söylenip\n"
+"  söylenmediğine bakın: https://lore.kernel.org/git/?q=%s\n"
+"- <git@vger.kernel.org> adresine bir e-posta göndererek bize\n"
+"  bu komutu hâlâ kullandığınızı ve yerine uygun bir ikâmeyi\n"
+"  bulamadığınızı iletin\n"
+"\n"
 
 msgid "refusing to run without --i-still-use-this"
 msgstr "--i-still-use-this olmadan çalıştırma reddediliyor"
@@ -23593,6 +24514,9 @@
 msgid "Send this email reply required"
 msgstr "Bu e-postayı yanıt gerektirme seçeneğiyle gönder"
 
+msgid "The destination IMAP folder is not properly defined."
+msgstr "Hedef IMAP sunucusu klasörü düzgünce tanımlanmamış."
+
 msgid "The required SMTP server is not properly defined."
 msgstr "Gerekli SMTP sunucusu düzgünce tanımlanmamış."
 
diff --git a/po/uk.po b/po/uk.po
index 12c44f8..e6e13bf 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -8,9 +8,9 @@
 msgstr ""
 "Project-Id-Version: Git v2.46\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2025-08-14 15:16-0700\n"
-"PO-Revision-Date: 2025-08-14 17:33-0700\n"
-"Last-Translator: Kateryna Golovanova <kate@kgthreads.com>\n"
+"POT-Creation-Date: 2025-11-13 15:18-0800\n"
+"PO-Revision-Date: 2025-11-14 21:08-0800\n"
+"Last-Translator: Arkadii Yakovets <ark@cho.red>\n"
 "Language-Team: Ukrainian <https://github.com/arkid15r/git-uk-l10n/>\n"
 "Language: uk\n"
 "MIME-Version: 1.0\n"
@@ -18,7 +18,7 @@
 "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.6\n"
+"X-Generator: Poedit 3.8\n"
 
 #, c-format
 msgid "%s cannot be negative"
@@ -545,39 +545,39 @@
 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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
-"j - залишити цей шматок невизначеним, перейти до наступного невизначеного "
-"шматка\n"
-"J - залишити цей шматок невизначеним, перейти до наступного шматка\n"
-"k - залишити цей шматок невизначеним, перейти до попереднього невизначеного "
-"шматка\n"
-"K - залишити цей шматок невизначеним, перейти до попереднього шматка\n"
+"j - перейти до наступного невизначеного шматка, перевернути внизу\n"
+"J - перейти до наступного шматка, перевернути внизу\n"
+"k - перейти до попереднього невизначеного шматка, перевернути вгорі\n"
+"K - перейти до попереднього фрагмента, прокрутити вгорі\n"
 "g - вибрати шматок, до якого ви хочете перейти\n"
 "/ - шукати шматок, що відповідає заданому регвиру\n"
 "s - розбити поточний шматок на менші шматки\n"
 "e - редагувати поточний шматок вручну\n"
 "p - показати поточний шматок, \"P\" для гортання сторінок\n"
+"P - показати поточний шматок з гортанням сторінок\n"
 "? - показати довідку\n"
 
 #, c-format
 msgid "Only one letter is expected, got '%s'"
 msgstr "Очікувався лише один символ, отримано \"%s\""
 
-msgid "No previous hunk"
-msgstr "Немає попереднього шматка"
+msgid "No other hunk"
+msgstr "Немає інших шматків"
 
-msgid "No next hunk"
-msgstr "Немає наступного шматка"
+msgid "No other undecided hunk"
+msgstr "Ніяких інших невизначених шматків"
 
 msgid "No other hunks to goto"
 msgstr "Немає інших шматків для переходу"
@@ -2378,15 +2378,20 @@
 msgstr "Обмежити відсутні обʼєкти поточним розрідженим переходом"
 
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-(new,bad)=<термін> --term-(old,good)=<термін>]    "
-"[--no-checkout] [--first-parent] [<поганий> [<добрий>...]] [--]    "
-"[<визначник шляху>...]"
+"git bisect start [--term-(bad|new)=<новий-термін> --term-(good|old)=<старий-"
+"термін>]\n"
+"                 [--no-checkout] [--first-parent] [<поганий> [<добрий>...]] "
+"[--] [<визначник шляху>...]"
 
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "git bisect (добрий|поганий) [<ревізія>...]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (поганий|новий|<новий-термін>) [<ревізія>...]"
+
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (добрий|старий|<старий-термін>) [<ревізія>...]"
 
 msgid "git bisect skip [(<rev>|<range>)...]"
 msgstr "git bisect skip [(<ревізія>|<діапазон>)...]"
@@ -5629,6 +5634,14 @@
 msgstr "знайдено %i тегів; припинено пошук на %s\n"
 
 #, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "неможливо знайти blob \"%s\" на гілці, яка ще не створена"
+
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "blob \"%s\" недосяжний з HEAD"
+
+#, c-format
 msgid "describe %s\n"
 msgstr "описати %s\n"
 
@@ -5771,6 +5784,9 @@
 msgid "%s...%s: no merge base"
 msgstr "%s...%s: немає бази злиття"
 
+msgid "cannot come back to cwd"
+msgstr "неможливо повернутися до поточної робочої директорії"
+
 msgid "Not a git repository"
 msgstr "Не є git сховищем"
 
@@ -5880,9 +5896,139 @@
 msgid "git fast-export [<rev-list-opts>]"
 msgstr "git fast-export [<rev-list-опції>]"
 
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "невідомий режим %s: %s"
+
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "невідомий режим фільтрування тегів: %s"
+
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "невідомий режим перекодування: %s"
+
+#, c-format
+msgid "could not read blob %s"
+msgstr "не вдалося прочитати blob %s"
+
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "невідповідність oid у blob %s"
+
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "не вдалося записати blob \"%s\""
+
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "несподіваний стан порівняння \"%c\" для %s, %s"
+
+msgid "none"
+msgstr "нічого"
+
+#, c-format
+msgid "could not find author in commit %s"
+msgstr "не вдалося знайти автора в коміті %s"
+
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "не вдалося знайти комітера в коміті %s"
+
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
 msgstr ""
-"Помилка: неможливо експортувати вкладені теги, якщо не вказано --mark-tags."
+"виявлено специфічне для коміту кодування %.*s у коміті %s; для його обробки "
+"використовуйте --reencode=[yes|no]"
+
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr ""
+"виявлено підписаний коміт %s; використовуйте --signed-commits=<режим> для "
+"його обробки"
+
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr "експорт %<PRIuMAX> підписів для коміту %s"
+
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr "видалення підпису(-ів) з коміту %s"
+
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+"пропустити тег %s,\n"
+"оскільки теги дерев (або теги тегів дерев тощо) не підтримуються."
+
+#, c-format
+msgid "could not read tag %s"
+msgstr "не вдалося прочитати тег %s"
+
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr ""
+"виявлено підписаний тег %s; для його обробки використовуйте --signed-"
+"tags=<режим>"
+
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "експортування підписаного тегу %s"
+
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "видалення підпису з тегу %s"
+
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr ""
+"тег %s тегує неекспортований обʼєкт; для його обробки використовуйте --tag-"
+"of-filtered-object=<режим>"
+
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr "не можна експортувати вкладені теги, якщо не вказано --mark-tags."
+
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "тег %s нікуди не вказує?"
+
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "%s: несподіваний обʼєкт типу %s, пропущено."
+
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr "тег вказує на обʼєкт несподіваного типу %s, пропускаємо."
+
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "не вдалося відкрити файл позначок %s для запису."
+
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "не вдалося записати файл позначок %s."
+
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "пошкоджена лінія позначки: %s"
+
+#, c-format
+msgid "object not found: %s"
+msgstr "обʼєкт не знайдено: %s"
+
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "не коміт? не може бути: %s"
+
+#, c-format
+msgid "object %s already has a mark"
+msgstr "обʼєкт %s вже має позначку"
 
 msgid "--anonymize-map token cannot be empty"
 msgstr "--anonymize-map токен не може бути порожнім"
@@ -5950,23 +6096,420 @@
 msgstr "позначати теги ідентифікаторами позначок"
 
 #, c-format
-msgid "Missing from marks for submodule '%s'"
-msgstr "Відсутні \"від\" позначки для підмодуля \"%s\""
+msgid "can't write crash report %s"
+msgstr "неможливо написати звіт про збій %s"
 
 #, c-format
-msgid "Missing to marks for submodule '%s'"
-msgstr "Відсутні \"до\" позначки для підмодуля \"%s\""
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "швидкий імпорт: вивантаження звіту про збій у %s\n"
 
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "Очікувалась команда \"mark\", отримано %s"
+msgid "mark :%<PRIuMAX> not declared"
+msgstr "позначка :%<PRIuMAX> не визначена"
 
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "Очікувалась команда \"to\", отримано %s"
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "невірна спроба створити копію гілки: %s"
 
-msgid "Expected format name:filename for submodule rewrite option"
-msgstr "Очікуваний формат назва:назва файлу для параметра перезапису підмодуля"
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "назва гілки не відповідає стандартам Git: %s"
+
+msgid "internal consistency error creating the index"
+msgstr "внутрішня помилка узгодженості при створенні індексу"
+
+msgid "cannot create keep file"
+msgstr "неможливо створити keep файл"
+
+msgid "failed to write keep file"
+msgstr "не вдалося записати keep файл"
+
+msgid "cannot store pack file"
+msgstr "неможливо зберегти файл пакунка"
+
+msgid "cannot store index file"
+msgstr "неможливо зберегти індексний файл"
+
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "не вдалося запустити \"%s\""
+
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "ядро Git відхилило індекс %s"
+
+msgid "cannot truncate pack to skip duplicate"
+msgstr "не можна скоротити пакет, щоб пропустити дублікати"
+
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "EOF у даних (залишилося %<PRIuMAX> байт)"
+
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "несподівана помилка запакуванні: %d"
+
+#, c-format
+msgid "not a tree: %s"
+msgstr "не дерево: %s"
+
+#, c-format
+msgid "can't load tree %s"
+msgstr "неможливо завантажити дерево %s"
+
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "пошкоджений режим у %s"
+
+msgid "root cannot be a non-directory"
+msgstr "корінь не може бути не директорією"
+
+msgid "empty path component found in input"
+msgstr "у вхідних даних виявлено порожній компонент шляху"
+
+msgid "non-directories cannot have subtrees"
+msgstr "не директорії не можуть мати піддерева"
+
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
+msgstr "вилучення %s, оскільки воно вказувало б на себе (тобто на %s)"
+
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "у гілці %s не вистачає комітів."
+
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "не оновлюється %s (нова верхівка %s не містить %s)"
+
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "не вдалося створити провідні директорії %s"
+
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "неможливо записати файл позначок %s"
+
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "неможливо записати файл позначок %s: %s"
+
+#, c-format
+msgid "unable to write file %s"
+msgstr "не вдалося записати файл %s"
+
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "очікувалась команда \"data n\", знайдено: %s"
+
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "EOF в даних (завершувач \"%s\" не знайдено)"
+
+msgid "data is too large to use in this context"
+msgstr "дані занадто великі для використання в цьому контексті"
+
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "EOF в даних (залишилося %lu байтів)"
+
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "відсутній < у рядку ідентифікатора: %s"
+
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "відсутній пробіл перед < у рядку ідентифікатора: %s"
+
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "відсутній > у рядку ідентифікатора: %s"
+
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "відсутній пробіл після > у рядку ідентифікатора: %s"
+
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "невірна необроблена дата \"%s\" в ідентифікаторі: %s"
+
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "невірна rfc2822 дата \"%s\" в ідентифікаторі: %s"
+
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "дата в ідентифікаторі повинна бути \"now\": %s"
+
+#, c-format
+msgid "too large fanout (%u)"
+msgstr "занадто великий fanout (%u)"
+
+#, c-format
+msgid "failed to remove path %s"
+msgstr "не вдалося видалити шлях %s"
+
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "немає значення після \":\" у позначці: %s"
+
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "непотріб після позначки: %s"
+
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "відсутній пробіл після позначки: %s"
+
+#, c-format
+msgid "invalid %s: %s"
+msgstr "невірний %s: %s"
+
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "NUL в %s: %s"
+
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "сміття після %s: %s"
+
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "відсутній пробіл після %s: %s"
+
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "пошкоджений режим: %s"
+
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "невірний dataref: %s"
+
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "відсутній пробіл після SHA1: %s"
+
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "Git посилання не можна вказувати \"inline\": %s"
+
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "не коміт (насправді %s): %s"
+
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "директорії не можуть бути вказані \"вбудованими\": %s"
+
+#, c-format
+msgid "%s not found: %s"
+msgstr "%s не знайдено: %s"
+
+msgid "tree"
+msgstr "дерево"
+
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "не %s (насправді %s): %s"
+
+#, c-format
+msgid "path %s not in branch"
+msgstr "шлях %s не знаходиться у гілці"
+
+msgid "can't add a note on empty branch."
+msgstr "не можна додати нотатку до порожньої гілки."
+
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr "позначка :%<PRIuMAX> не є комітом"
+
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "недійсний коміт: %s"
+
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "невірна назва посилання або вираз SHA1: %s"
+
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "не blog (насправді %s): %s"
+
+#, c-format
+msgid "blob not found: %s"
+msgstr "не знайдено blob: %s"
+
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "коміт %s пошкоджений"
+
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "неможливо створити гілку з самої себе: %s"
+
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
+msgstr ""
+"очікувався формат gpgsig: \"gpgsig <алгоритм-хешування> <формат-підпису>\", "
+"отримано \"gpgsig %s\""
+
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "невідомий алгоритм хешування git у gpgsig: \"%s\""
+
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "невірний формат підпису в gpgsig: \"%s\""
+
+msgid "'unknown' signature format in gpgsig"
+msgstr "\"unknown\" формат підпису в gpgsig"
+
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr "знайдено кілька підписів %s, ігнорування додаткового підпису"
+
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr "parse_one_signature() повернув невідомий алгоритм хешування"
+
+msgid "expected committer but didn't get one"
+msgstr "очікувався комміттер, але його не отримали"
+
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr ""
+"виявлено підписаний коміт; використовуйте --signed-commits=<режим> для його "
+"обробки"
+
+msgid "stripping a commit signature"
+msgstr "видалення підпису коміту"
+
+msgid "importing a commit signature verbatim"
+msgstr "імпортування підпису комміту дослівно"
+
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr ""
+"зустрів підписаний тег; використовуйте --signed-tags=<режим> для його обробки"
+
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr "імпортування дослівного підпису для тегу \"%s\""
+
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr "видалення підпису для тегу \"%s\""
+
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "очікувалась команда \"from\", отримано \"%s\""
+
+msgid "can't tag an empty branch."
+msgstr "неможливо позначити порожню гілку."
+
+#, c-format
+msgid "not a valid object: %s"
+msgstr "не є припустимим обʼєктом: %s"
+
+msgid "write to frontend failed"
+msgstr "не вдалося записати в інтерфейс"
+
+#, c-format
+msgid "can't read object %s"
+msgstr "неможливо прочитати обʼєкт %s"
+
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "обʼєкт %s є %s, але очікувався blob."
+
+#, c-format
+msgid "not a mark: %s"
+msgstr "не позначка: %s"
+
+#, c-format
+msgid "unknown mark: %s"
+msgstr "невідома позначка: %s"
+
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "непотріб після SHA1: %s"
+
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "не деревоподібний: %s"
+
+#, c-format
+msgid "can't load object %s"
+msgstr "неможливо завантажити обʼєкт %s"
+
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "недійсний SHA1 у тезі: %s"
+
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "невірний SHA1 у коміті: %s"
+
+#, c-format
+msgid "missing from marks for submodule '%s'"
+msgstr "відсутні \"від\" позначки для підмодуля \"%s\""
+
+#, c-format
+msgid "missing to marks for submodule '%s'"
+msgstr "відсутні \"до\" позначки для підмодуля \"%s\""
+
+#, c-format
+msgid "missing space after tree-ish: %s"
+msgstr "відсутній пробіл після деревоподібного: %s"
+
+#, c-format
+msgid "not in a commit: %s"
+msgstr "не в коміті: %s"
+
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "очікувалась команда \"mark\", отримано %s"
+
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "очікувалась команда \"to\", отримано %s"
+
+msgid "only one import-marks command allowed per stream"
+msgstr "дозволено лише одну команду import-marks на потік"
+
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "невідомий --date-format аргумент %s"
+
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s: аргумент повинен бути невідʼємним цілим числом"
+
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr "--depth не може перевищувати %u"
+
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr "--cat-blob-fd не може перевищувати %d"
+
+msgid "expected format name:filename for submodule rewrite option"
+msgstr "очікуваний формат назва:назва_файлу для опції перезапису підмодуля"
+
+#, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr ""
+"max-pack-size тепер вимірюється в байтах, припускаючи --max-pack-size=%lum"
+
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "мінімальний розмір пакунка 1 МіБ"
+
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "невідомий --signed-commits режим \"%s\""
+
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "невідомий --signed-tags режим \"%s\""
 
 #, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
@@ -5974,6 +6517,37 @@
 "особливість \"%s\" не можна використовувати без --allow-unsafe-features"
 
 #, c-format
+msgid "got feature command '%s' after data command"
+msgstr "отримано команду функції \"%s\" після команди даних"
+
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "ця версія fast-import не підтримує функцію %s."
+
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr "отримано команду опції \"%s\" після команди даних"
+
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "ця версія fast-import не підтримує опцію: %s"
+
+#, c-format
+msgid "unknown option %s"
+msgstr "невідома опція %s"
+
+#, c-format
+msgid "unknown option --%s"
+msgstr "невідома опція --%s"
+
+#, c-format
+msgid "unsupported command: %s"
+msgstr "непідтримувана команда: %s"
+
+msgid "stream ends early"
+msgstr "потік закінчується раніше"
+
+#, c-format
 msgid "Lockfile created but not reported: %s"
 msgstr "Файл блокування створено, але не звітовано: %s"
 
@@ -6111,6 +6685,38 @@
 "\"git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s\"\n"
 "вимкне попередження, доки віддалене призначення не змінить HEAD на щось інше."
 
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+"Ви використовуєте файлову систему, яка не розрізняє регістр, а віддалений "
+"ресурс, з якого ви\n"
+"намагаєтеся завантажити дані, містить посилання, що відрізняються лише "
+"регістром.\n"
+"Зберегти такі посилання за допомогою бекенду \"files\" неможливо. Ви\n"
+"можете або прийняти це як є, але в такому випадку ви не зможете\n"
+"зберегти всі віддалені посилання на диску. Або ви можете\n"
+"змінити бекенд вашого сховища на \"reftable\" за допомогою\n"
+"наступної команди:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Зверніть увагу, що не всі реалізації Git ще підтримують цей\n"
+"новий формат. Тому, якщо ви використовуєте інші інструменти, крім Git, для "
+"доступу до цього\n"
+"сховища, перехід на reftables може бути неможливим.\n"
+
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -6358,21 +6964,6 @@
 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 "git for-each-ref [--points-at <обʼєкт>]"
-
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr "git for-each-ref [--merged [<коміт>]] [--no-merged [<коміт>]]"
-
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr "git for-each-ref [--contains [<коміт>]] [--no-contains [<коміт>]]"
-
-msgid "git for-each-ref [--start-after <marker>]"
-msgstr "git for-each-ref [--start-after <маркер>]"
-
 msgid "quote placeholders suitably for shells"
 msgstr "заповнювачі лапок для shell"
 
@@ -6428,6 +7019,9 @@
 msgid "cannot use --start-after with patterns"
 msgstr "неможливо використовувати --start-after із шаблонами"
 
+msgid "git for-each-ref "
+msgstr "git for-each-ref "
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<конфіг> [--] <аргументи>"
 
@@ -6904,6 +7498,9 @@
 msgstr ""
 "пропуск incremental-repack завдання, оскільки core.multiPackIndex вимкнено"
 
+msgid "failed to perform geometric repack"
+msgstr "не вдалося виконати геометричне перепакування"
+
 #, c-format
 msgid "task '%s' failed"
 msgstr "завдання \"%s\" завершилося невдало"
@@ -6913,6 +7510,10 @@
 msgstr "файл блокування \"%s\" існує, пропуск обслуговування"
 
 #, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "невідома стратегія обслуговування %s"
+
+#, c-format
 msgid "'%s' is not a valid task"
 msgstr "\"%s\" не є припустимим завданням"
 
@@ -7221,10 +7822,10 @@
 msgstr "показувати збіги лише з файлів, які відповідають усім шаблонам"
 
 msgid "pager"
-msgstr "пейджер"
+msgstr "гортання сторінок"
 
 msgid "show matching files in the pager"
-msgstr "показати відповідні файли в пейджері"
+msgstr "показати відповідні файли з гортанням сторінок"
 
 msgid "allow calling of grep(1) (ignored by this build)"
 msgstr "дозволяти виклик grep(1) (ігнорується у цій збірці)"
@@ -7786,6 +8387,29 @@
 msgid "no input file given for in-place editing"
 msgstr "не надано вхідного файлу для редагування на місці"
 
+msgid "last-modified can only operate on one tree at a time"
+msgstr "last-modified може працювати тільки з одним деревом за раз"
+
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "невідомий аргумент last-modified: %s"
+
+msgid "unable to setup last-modified"
+msgstr "не вдалося налаштувати last-modified"
+
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+"git last-modified [--recursive] [--show-trees] [<діапазон-ревізій>] [[--] "
+"<шлях>...]"
+
+msgid "recurse into subtrees"
+msgstr "рекурсивно в піддеревах"
+
+msgid "show tree entries when recursing into subtrees"
+msgstr "показати записи дерева при рекурсії в піддерева"
+
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
 msgstr "git log [<опції>] [<діапазон-ревізій>] [[--] <шлях>...]"
 
@@ -7824,6 +8448,22 @@
 msgid "-L<range>:<file> cannot be used with pathspec"
 msgstr "-L<діапазон>:<файл> не можна використовувати з визначником шляху"
 
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+"\n"
+"підказка: Ви можете замінити \"git whatchanged <опції>\" на:\n"
+"підказка:    git log <опції> --raw --no-merges\n"
+"підказка: Або створити псевдонім:\n"
+"підказка:    git config set --global alias.whatchanged \"log --raw --no-"
+"merges\"\n"
+"\n"
+
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s: невірний файл"
@@ -8267,9 +8907,6 @@
 msgid "only show trees"
 msgstr "показувати тільки дерева"
 
-msgid "recurse into subtrees"
-msgstr "рекурсивно в піддеревах"
-
 msgid "show trees when recursing"
 msgstr "відображати дерева при рекурсії"
 
@@ -8419,10 +9056,6 @@
 msgstr "Не вдалося записати файл обʼєкта"
 
 #, c-format
-msgid "unknown option %s"
-msgstr "невідома опція %s"
-
-#, c-format
 msgid "could not parse object '%s'"
 msgstr "не вдалося розібрати обʼєкт \"%s\""
 
@@ -8591,10 +9224,6 @@
 msgid "stash failed"
 msgstr "не вдалося додати до схову"
 
-#, c-format
-msgid "not a valid object: %s"
-msgstr "не є припустимим обʼєктом: %s"
-
 msgid "read-tree failed"
 msgstr "read-tree завершився невдало"
 
@@ -9740,27 +10369,8 @@
 "Всього %<PRIu32> (дельта %<PRIu32>), повторно використано %<PRIu32> (дельта "
 "%<PRIu32>), повторно використано пакунків %<PRIu32> (з %<PRIuMAX>)"
 
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <шаблон>] [--exclude "
-"<шаблон>]"
-
-msgid "pack everything"
-msgstr "запакувати все"
-
-msgid "prune loose refs (default)"
-msgstr "видалити вивільнені посилання (за замовчуванням)"
-
-msgid "auto-pack refs as needed"
-msgstr "автопакування посилань за потреби"
-
-msgid "references to include"
-msgstr "посилання для включення"
-
-msgid "references to exclude"
-msgstr "посилання для виключення"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
 msgid "git patch-id [--stable | --unstable | --verbatim]"
 msgstr "git patch-id [--stable | --unstable | --verbatim]"
@@ -10285,6 +10895,10 @@
 msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
 msgstr "git range-diff [<опції>] <база> <стара-верхівка> <нова-верхівка>"
 
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "неприпустиме значення максимального обсягу памʼяті: %s"
+
 msgid "use simple diff colors"
 msgstr "використовувати прості кольори diff"
 
@@ -10294,6 +10908,12 @@
 msgid "passed to 'git log'"
 msgstr "передано до \"git log\""
 
+msgid "size"
+msgstr "розмір"
+
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr "максимальний обсяг памʼяті для матриці витрат (за замовчуванням 4 Гб)"
+
 msgid "only emit output related to the first range"
 msgstr "видати тільки вивід, що відноситься до першого діапазону"
 
@@ -10859,6 +11479,22 @@
 msgid "git reflog list"
 msgstr "git reflog list"
 
+msgid "git reflog exists <ref>"
+msgstr "git reflog exists <посилання>"
+
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr "git reflog write <посилання> <старий-oid> <новий-oid> <повідомлення>"
+
+msgid ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+msgstr ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <посилання>@{<визначник>}..."
+
+msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
+msgstr "git reflog drop [--all [--single-worktree] | <посилання>...]"
+
 msgid ""
 "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
 "                  [--rewrite] [--updateref] [--stale-fix]\n"
@@ -10870,19 +11506,6 @@
 "                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
 "<посилання>...]"
 
-msgid ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-msgstr ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <посилання>@{<визначник>}..."
-
-msgid "git reflog exists <ref>"
-msgstr "git reflog exists <посилання>"
-
-msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
-msgstr "git reflog drop [--all [--single-worktree] | <посилання>...]"
-
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "неприпустима позначка часу \"%s\" передана до \"--%s\""
@@ -10950,12 +11573,50 @@
 msgid "references specified along with --all"
 msgstr "посилання, вказані разом з --all"
 
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "неприпустима назва посилання: %s"
+
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "невірний ідентифікатор старого об’єкта: \"%s\""
+
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "старий об’єкт \"%s\" не існує"
+
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "невірний ідентифікатор нового об’єкта: \"%s\""
+
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "новий об’єкт \"%s\" не існує"
+
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr "неможливо почати транзакцію: %s"
+
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr "неможливо встановити чергу оновлення журналу посилань: %s"
+
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr "неможливо зробити коміт оновлення журналу посилань: %s"
+
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=<формат> [--no-reflog] [--dry-run]"
 
 msgid "git refs verify [--strict] [--verbose]"
 msgstr "git refs verify [--strict] [--verbose]"
 
+msgid "git refs exists <ref>"
+msgstr "git ref exists <посилання>"
+
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
 msgid "specify the reference format to convert to"
 msgstr "вкажіть формат посилання, в який потрібно конвертувати"
 
@@ -10978,6 +11639,18 @@
 msgid "'git refs verify' takes no arguments"
 msgstr "\"git refs verify\" не потребує аргументів"
 
+msgid "git refs list "
+msgstr "git refs list "
+
+msgid "'git refs exists' requires a reference"
+msgstr "\"git refs exists\" потребує посилання"
+
+msgid "reference does not exist"
+msgstr "посилання не існує"
+
+msgid "failed to look up reference"
+msgstr "не вдалося знайти посилання"
+
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
 "mirror=<fetch|push>] <name> <url>"
@@ -11139,6 +11812,26 @@
 "\t%s:%d\n"
 "тепер називає неіснуюче віддалене посилання \"%s\""
 
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+"Віддалене призначення, яке ви намагаєтеся перейменувати, має суперечливі "
+"посилання в\n"
+"новому цільовому визначнику посилання. Найімовірніше, це спричинено тим, що "
+"ви намагаєтеся вкласти\n"
+"віддалене призначення в саме себе, наприклад, перейменувавши «parent» на "
+"«parent/child»\n"
+"або вилучивши вкладене віддалене призначення, тобто, навпаки.\n"
+"\n"
+"У такому випадку ви можете вирішити це, спочатку переназвавши\n"
+"віддалене призначення.\n"
+
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "Немає такого віддаленого призначення: \"%s\""
@@ -11147,6 +11840,13 @@
 msgid "Could not rename config section '%s' to '%s'"
 msgstr "Не вдалося перейменувати розділ конфігурації з \"%s\" на \"%s\""
 
+msgid "Renaming remote references"
+msgstr "Перейменування віддалених посилань"
+
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr "помилка при перейменуванні віддаленого посилання в черзі: %s"
+
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -11157,16 +11857,9 @@
 "%s\n"
 "Будь ласка, за потреби оновіть конфігурацію вручну."
 
-msgid "Renaming remote references"
-msgstr "Перейменування віддалених посилань"
-
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "не вдалося видалити \"%s\""
-
-#, c-format
-msgid "creating '%s' failed"
-msgstr "не вдалося створити \"%s\""
+msgid "renaming remote refs failed: %s"
+msgstr "не вдалося перейменувати віддалені посилання: %s"
 
 msgid ""
 "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
@@ -11456,47 +12149,6 @@
 "параметром\n"
 "--no-write-bitmap-index або вимкніть конфігурацію pack.writeBitmaps."
 
-msgid "could not start pack-objects to repack promisor objects"
-msgstr "не вдалося розпочати pack-objects для перепакування promisor обʼєктів"
-
-msgid "failed to feed promisor objects to pack-objects"
-msgstr "не вдалося передати promisor обʼєкти обʼєктам пакунків"
-
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr ""
-"перепакування: очікуються повні рядки hex ідентифікаторів обʼєктів тільки "
-"від pack-objects."
-
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr "не вдалося завершити pack-objects для перепакування promisor обʼєктів"
-
-#, c-format
-msgid "cannot open index for %s"
-msgstr "неможливо відкрити індекс для %s"
-
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr "пакунок %s занадто великий, щоб враховувати в геометричній прогресії"
-
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "пакунок %s занадто великий для згортання"
-
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "не вдалося відкрити тимчасовий файл %s для запису"
-
-msgid "could not close refs snapshot tempfile"
-msgstr "не вдалося закрити тимчасовий файл знімка посилань"
-
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "не вдалося видалити застарілий bitmap: %s"
-
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "префікс пакунку %s не починається з objdir %s"
-
 msgid "pack everything in a single pack"
 msgstr "запакувати все в один пакунок"
 
@@ -11594,18 +12246,6 @@
 msgid "Nothing new to pack."
 msgstr "Немає нічого нового для пакування."
 
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "перейменування пакунка на \"%s\" завершилося невдало"
-
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "pack-objects не записав файл \"%s\" для пакунка %s-%s"
-
-#, c-format
-msgid "could not unlink: %s"
-msgstr "не вдалося видалити: %s"
-
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] <обʼєкт> <заміна>"
 
@@ -11860,6 +12500,62 @@
 msgid "replaying merge commits is not supported yet!"
 msgstr "відтворення комітів злиття поки що не підтримується!"
 
+#, c-format
+msgid "key '%s' not found"
+msgstr "ключ \"%s\" не знайдено"
+
+#, c-format
+msgid "invalid format '%s'"
+msgstr "неприпустимий формат \"%s\""
+
+msgid "output format"
+msgstr "формат виводу"
+
+msgid "synonym for --format=nul"
+msgstr "те ж саме, що й --format=nul"
+
+msgid "unsupported output format"
+msgstr "непідтримуваний формат виводу"
+
+msgid "References"
+msgstr "Посилання"
+
+msgid "Count"
+msgstr "Кількість"
+
+msgid "Branches"
+msgstr "Гілки"
+
+msgid "Tags"
+msgstr "Теги"
+
+msgid "Remotes"
+msgstr "Віддалені призначення"
+
+msgid "Others"
+msgstr "Інші"
+
+msgid "Reachable objects"
+msgstr "Досяжні обʼєкти"
+
+msgid "Commits"
+msgstr "Коміти"
+
+msgid "Trees"
+msgstr "Дерева"
+
+msgid "Blobs"
+msgstr "Blobs"
+
+msgid "Repository structure"
+msgstr "Структура сховища"
+
+msgid "Value"
+msgstr "Значення"
+
+msgid "Counting references"
+msgstr "Підрахунок посилань"
+
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
 msgstr ""
@@ -12462,12 +13158,6 @@
 msgid "git show-ref --exists <ref>"
 msgstr "git show-ref --exists <посилання>"
 
-msgid "reference does not exist"
-msgstr "посилання не існує"
-
-msgid "failed to look up reference"
-msgstr "не вдалося знайти посилання"
-
 msgid "only show tags (can be combined with --branches)"
 msgstr "показувати тільки теги (можна комбінувати з --branches)"
 
@@ -12497,10 +13187,10 @@
 
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<опції>]"
+"rules | clean) [<опції>]"
 
 msgid "this worktree is not sparse"
 msgstr "це робоче дерево не є розрідженим"
@@ -12542,10 +13232,6 @@
 msgstr "перемкнути використання розрідженого індексу"
 
 #, c-format
-msgid "unable to create leading directories of %s"
-msgstr "не вдалося створити провідні директорії %s"
-
-#, c-format
 msgid "failed to open '%s'"
 msgstr "не вдалося відкрити \"%s\""
 
@@ -12627,6 +13313,36 @@
 "має перебувати в розрідженому переході для повторного застосування шаблонів "
 "розрідженості"
 
+msgid "report each affected file, not just directories"
+msgstr "повідомляти про кожен уражений файл, а не тільки про директорії"
+
+msgid "must be in a sparse-checkout to clean directories"
+msgstr "має перебувати в режимі розрідженого переходу для очищення директорій"
+
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr ""
+"має перебувати в режимі конусного розрідженого переходу, щоб очистити "
+"директорії"
+
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr ""
+"для безпеки, відмовлятися виконувати очищення без одного з параметрів --"
+"force або --dry-run"
+
+msgid "failed to read index"
+msgstr "не вдалося прочитати індекс"
+
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr ""
+"не вдалося перетворити індекс на розріджений індекс; розвʼяжіть конфлікти "
+"злиття та спробуйте ще раз"
+
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "не вдалося видалити \"%s\""
+
 msgid "error while refreshing working directory"
 msgstr "помилка під час оновлення робочої директорії"
 
@@ -14347,9 +15063,6 @@
 msgid "only useful for debugging"
 msgstr "корисно лише для відлагодження"
 
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "core.fsyncMethod = batch не підтримується на цій платформі"
-
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
 msgstr "не вдалося розібрати ключ списку пакунків %s зі значенням \"%s\""
@@ -14487,7 +15200,7 @@
 
 #, c-format
 msgid "directory '%s' is present in index, but not sparse"
-msgstr "Директорія \"%s\" присутня в індексі, але не є розрідженою"
+msgstr "директорія \"%s\" присутня в індексі, але не є розрідженою"
 
 msgid "corrupted cache-tree has entries not present in index"
 msgstr "пошкоджене cache-tree має записи, яких немає в індексі"
@@ -14743,6 +15456,9 @@
 msgid "Add or parse structured information in commit messages"
 msgstr "Додати або розібрати структуровану інформацію в дописах до комітів"
 
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr "ЕКСПЕРИМЕНТАЛЬНО: Показати, коли файли були змінені востаннє"
+
 msgid "Show commit logs"
 msgstr "Показати журнал коміту"
 
@@ -14866,6 +15582,9 @@
 "ЕКСПЕРИМЕНТАЛЬНО: Відтворення комітів на новій базі також працює з порожніми "
 "сховищами"
 
+msgid "Retrieve information about the repository"
+msgstr "Отримати інформацію про сховище"
+
 msgid "Generates a summary of pending changes"
 msgstr "Створює підсумок змін для розгляду"
 
@@ -14947,9 +15666,8 @@
 msgid "Read, modify and delete symbolic refs"
 msgstr "Прочитати, змінити та видалити символьні посилання"
 
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr ""
-"Створити, показати, видалити або перевірити обʼєкт тегу, підписаний GPG"
+msgid "Create, list, delete or verify tags"
+msgstr "Створити, перерахувати, видалити або перевірити теги"
 
 msgid "Creates a temporary file with a blob's contents"
 msgstr "Створює тимчасовий файл із вмістом blob"
@@ -15786,6 +16504,43 @@
 msgid "unable to parse command-line config"
 msgstr "не вдалося розібрати конфігурацію командного рядка"
 
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"Щоб використовувати стандартну строку коментаря (#), виконайте команду\n"
+"\n"
+"%s"
+
+msgid "<comment string>"
+msgstr "<строка_коментаря>"
+
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+"\n"
+"Щоб встановити власну строку коментаря, виконайте команду\n"
+"\n"
+"%s,\n"
+" де \"%s\" — це строка, яку ви хочете використовувати.\n"
+
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr "Підтримка \"%s=auto\" була видалена в Git 3.0"
+
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr "Підтримка \"%s=auto\" є застарілою і буде видалена в Git 3.0."
+
 msgid "unknown error occurred while reading the configuration files"
 msgstr "невідома помилка виникла під час читання конфігураційних файлів"
 
@@ -16274,6 +17029,12 @@
 msgid "failed to write archive"
 msgstr "не вдалося записати архів"
 
+msgid "max-depth is not supported for worktree diffs"
+msgstr "max-depth не підтримується для порівняння робочих дерев"
+
+msgid "max-depth is not supported for index diffs"
+msgstr "max-depth не підтримується для індексних diff"
+
 msgid "--merge-base does not work with ranges"
 msgstr "--merge-base не працює з діапазонами"
 
@@ -16783,6 +17544,12 @@
 msgid "select files by diff type"
 msgstr "вибрати файли за типом різниці"
 
+msgid "<depth>"
+msgstr "<глибина>"
+
+msgid "maximum tree depth to recurse"
+msgstr "максимальна глибина дерева для рекурсії"
+
 msgid "<file>"
 msgstr "<файл>"
 
@@ -16982,10 +17749,6 @@
 msgstr "неприпустимий unshallow рядок: %s"
 
 #, c-format
-msgid "object not found: %s"
-msgstr "обʼєкт не знайдено: %s"
-
-#, c-format
 msgid "error in object: %s"
 msgstr "помилка в обʼєкті: %s"
 
@@ -17267,6 +18030,10 @@
 msgid "recursive alias: %s"
 msgstr "рекурсивний псевдонім: %s"
 
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr "виявлено цикл псевдонімів: розширення \"%s\" не припиняє:%s"
+
 msgid "write failure on standard output"
 msgstr "помилка запису в стандартний вивід"
 
@@ -17277,10 +18044,6 @@
 msgstr "не вдалося закрити стандартний вивід"
 
 #, c-format
-msgid "alias loop detected: expansion of '%s' does not terminate:%s"
-msgstr "виявлено цикл псевдонімів: розширення \"%s\" не припиняє:%s"
-
-#, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "неможливо обробити %s як вбудовану команду"
 
@@ -17331,12 +18094,20 @@
 msgid "failed to get the ssh fingerprint for key '%s'"
 msgstr "не вдалося отримати ssh відбиток для ключа \"%s\""
 
+#, 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 ""
 "потрібно налаштувати або user.signingkey, або gpg.ssh.defaultKeyCommand"
 
 #, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr "помилка формування під час компіляції gpg.ssh.defaultKeyCommand: %s"
+
+#, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr ""
 "gpg.ssh.defaultKeyCommand команда виконалася успішно, але не повернула "
@@ -17601,6 +18372,13 @@
 "  запитували: %s\n"
 "   перенаправлення: %s"
 
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr ""
+"число занадто велике, щоб представити його як curl_off_t на цій платформі: "
+"%<PRIuMAX>"
+
 msgid "Author identity unknown\n"
 msgstr "Особистість автора невідома\n"
 
@@ -18060,10 +18838,6 @@
 msgstr "не вдалося завантажити пакунок"
 
 #, c-format
-msgid "could not open index for %s"
-msgstr "не вдалося відкрити індекс для %s"
-
-#, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "не вдалося звʼязати \"%s\" з \"%s\""
 
@@ -18087,6 +18861,10 @@
 msgstr "невідомий бажаний пакунок: \"%s\""
 
 #, c-format
+msgid "failed to open preferred pack %s"
+msgstr "не вдалося відкрити бажаний пакунок %s"
+
+#, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr "неможливо вибрати бажаний пакунок %s за відсутності об’єктів"
 
@@ -18110,6 +18888,9 @@
 msgid "could not write multi-pack bitmap"
 msgstr "не вдалося записати мультіпакунковий bitmap"
 
+msgid "too many multi-pack-indexes"
+msgstr "занадто багато multi-pack-indexes"
+
 msgid "unable to open multi-pack-index chain file"
 msgstr "не вдалося відкрити ланцюжковий файл multi-pack-index"
 
@@ -18378,10 +19159,6 @@
 msgstr "файли \"%s\" та \"%s\" відрізняються за вмістом"
 
 #, c-format
-msgid "unable to write file %s"
-msgstr "не вдалося записати файл %s"
-
-#, c-format
 msgid "unable to write repeatedly vanishing file %s"
 msgstr "не вдалося записати файл %s, який постійно зникає"
 
@@ -18389,6 +19166,9 @@
 msgid "unable to set permission to '%s'"
 msgstr "не вдалося встановити дозволи для \"%s\""
 
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = batch не підтримується на цій платформі"
+
 msgid "error when closing loose object file"
 msgstr "помилка при закритті файла вільного об’єкта"
 
@@ -18898,6 +19678,21 @@
 msgid "mtimes file %s is corrupt"
 msgstr "mtimes файл %s пошкоджено"
 
+msgid "pack everything"
+msgstr "запакувати все"
+
+msgid "prune loose refs (default)"
+msgstr "видалити вивільнені посилання (за замовчуванням)"
+
+msgid "auto-pack refs as needed"
+msgstr "автопакування посилань за потреби"
+
+msgid "references to include"
+msgstr "посилання для включення"
+
+msgid "references to exclude"
+msgstr "посилання для виключення"
+
 #, c-format
 msgid "reverse-index file %s is too small"
 msgstr "файл зворотного індексу %s занадто малий"
@@ -19327,6 +20122,10 @@
 msgstr "не вдалося отримати %s з віддаленого promisor"
 
 #, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr "непідтримуване поле \"%s\" у конфігурації \"%s\""
+
+#, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "відсутній або пустий обіцяний URL для віддаленого \"%s\""
 
@@ -19337,12 +20136,16 @@
 "замість \"%s\""
 
 #, c-format
-msgid "unknown '%s' value for '%s' config option"
-msgstr "невідоме значення \"%s\" для параметра конфігурації \"%s\""
+msgid "invalid element '%s' from remote info"
+msgstr "невірний елемент \"%s\" з віддаленої інформації"
 
 #, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "невідомий елемент \"%s\" з віддаленої інформації"
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr "сервер оголосив віддалений promisor без назви або URL-адреси: %s"
+
+#, c-format
+msgid "unknown '%s' value for '%s' config option"
+msgstr "невідоме значення \"%s\" для параметра конфігурації \"%s\""
 
 #, c-format
 msgid "accepted promisor remote '%s' not found"
@@ -19439,6 +20242,16 @@
 msgstr "не вдалося згенерувати різницю"
 
 #, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+"range-diff: неможливо розрахувати різницю діапазонів, оскільки вона "
+"перевищує максимальний обсяг памʼяті для матриці витрат: необхідно %s "
+"(%<PRIuMAX> байт), обмежено до %s (%<PRIuMAX> байт)"
+
+#, c-format
 msgid "could not parse log for '%s'"
 msgstr "не вдалося розібрати журнал для \"%s\""
 
@@ -19965,6 +20778,9 @@
 msgid "no reflog for '%s'"
 msgstr "немає журналу посилань для \"%s\""
 
+msgid "Checking references consistency"
+msgstr "Перевірка співпадіння посилань"
+
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "%s не вказує на допустимий обʼєкт!"
@@ -19980,8 +20796,9 @@
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -19990,19 +20807,34 @@
 "\n"
 "\tgit branch -m <name>\n"
 msgstr ""
-"Використання \"%s\" як назви початкової гілки. Назву гілки за замовчуванням\n"
-"може бути змінено. Щоб налаштувати назву початкової гілки для використання у "
-"всіх\n"
-"ваших нових сховищах, що приховає це попередження, викличте\n"
+"Використання \"%s\" як назву для початкової гілки. Ця назва гілки за "
+"замовчуванням\n"
+"зміниться на \"main\" у Git 3.0. Щоб налаштувати початкову назву гілки,\n"
+"яка буде використовуватися у всіх ваших нових сховищах, що приховає це "
+"попередження,\n"
+"виконайте:\n"
 "\n"
-"\tgit config --global init.defaultBranch <назва>.\n"
+"\tgit config --global init.defaultBranch <назва>\n"
 "\n"
-"Замість \"master\" зазвичай використовують такі назви, як \"main\", "
-"\"trunk\" та\n"
+"Замість \"master\" зазвичай вибирають імена \"main\", \"trunk\" і\n"
 "\"development\". Щойно створену гілку можна перейменувати за допомогою цієї "
 "команди:\n"
 "\n"
-"\tgit branch -m <назва>\n"
+"\tgit branch -m <name>\n"
+
+#, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"Використовується \"%s\" як назва початкової гілки з Git 3.0.\n"
+"Якщо ви очікували, що Git створить \"master\", щойно створену\n"
+"гілку можна перейменувати за допомогою команди:\n"
+"\n"
+"\tgit branch -m master\n"
 
 #, c-format
 msgid "could not retrieve `%s`"
@@ -20089,6 +20921,28 @@
 msgid "migrated refs can be found at '%s'"
 msgstr "перенесені посилання можна знайти в \"%s\""
 
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+"\"core.preferSymlinkRefs=true\" номіновано на видалення.\n"
+"hint: Використання символічних посилань для символьних посилань є "
+"застарілим\n"
+"hint: і буде видалено в Git 3.0. Конфігурація, яка\n"
+"hint: вказує Git використовувати їх, буде видалена. Ви можете скасувати\n"
+"hint: її за допомогою:\n"
+"hint:\n"
+"hint:    git config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Замість цього Git буде використовувати текстовий формат symref."
+
 #, c-format
 msgid ""
 "cannot lock ref '%s': expected symref with target '%s': but is a regular ref"
@@ -20097,6 +20951,10 @@
 "призначенням \"%s\", але це звичайне посилання"
 
 #, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr "спроба записати reflog для \"%s\" з неповними значеннями"
+
+#, c-format
 msgid "cannot read ref file '%s'"
 msgstr "неможливо прочитати файл посилання \"%s\""
 
@@ -20104,9 +20962,6 @@
 msgid "cannot open directory %s"
 msgstr "неможливо відкрити директорію %s"
 
-msgid "Checking references consistency"
-msgstr "Перевірка співпадіння посилань"
-
 #, c-format
 msgid "unable to open '%s'"
 msgstr "не вдалося відкрити \"%s\""
@@ -20150,6 +21005,10 @@
 "не дозволені"
 
 #, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr "неможливо заблокувати посилання \"%s\": вже існує незалежний symref"
+
+#, c-format
 msgid "cannot lock ref '%s': reference already exists"
 msgstr "неможливо зафіксувати посилання \"%s\": посилання вже існує"
 
@@ -20255,9 +21114,6 @@
 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"
@@ -20449,6 +21305,13 @@
 "\"%s:refs/tags/%s\"?"
 
 #, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr ""
+"Частина <джерело> визаначника посилання (\"%s\") є ідентифікатором обʼєкта, "
+"який не існує.\n"
+
+#, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "%s неможливо розвʼязати в гілку"
 
@@ -20585,6 +21448,59 @@
 msgstr "неможливо вилучити один компонент з url \"%s\""
 
 #, c-format
+msgid "cannot open index for %s"
+msgstr "неможливо відкрити індекс для %s"
+
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr "пакунок %s занадто великий, щоб враховувати в геометричній прогресії"
+
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "пакунок %s занадто великий для згортання"
+
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "не вдалося відкрити тимчасовий файл %s для запису"
+
+msgid "could not close refs snapshot tempfile"
+msgstr "не вдалося закрити тимчасовий файл знімка посилань"
+
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "не вдалося видалити застарілий bitmap: %s"
+
+msgid "could not start pack-objects to repack promisor objects"
+msgstr "не вдалося розпочати pack-objects для перепакування promisor обʼєктів"
+
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "не вдалося передати promisor обʼєкти обʼєктам пакунків"
+
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr ""
+"перепакування: очікуються повні рядки hex ідентифікаторів обʼєктів тільки "
+"від pack-objects."
+
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr "не вдалося завершити pack-objects для перепакування promisor обʼєктів"
+
+#, 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 "перейменування пакунка на \"%s\" завершилося невдало"
+
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "pack-objects не записав файл \"%s\" для пакунка %s-%s"
+
+#, c-format
+msgid "could not unlink: %s"
+msgstr "не вдалося видалити: %s"
+
+#, c-format
 msgid "bad replace ref name: %s"
 msgstr "неприпустима назва заміни посилання: %s"
 
@@ -21906,9 +22822,6 @@
 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\""
@@ -22989,19 +23902,33 @@
 msgstr "попередження: "
 
 #, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "\"%s\" номіновано на видалення.\n"
+
+#, c-format
 msgid ""
-"'%s' 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"
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
 msgstr ""
-"\"%s\" запропоновано для видалення.\n"
-"Якщо ви все ще використовуєте цю команду, додайте додаткову\n"
-"опцію \"--i-still-use-this\" у командний рядок\n"
-"і повідомте нас про те, що ви все ще її використовуєте, надіславши "
-"електронного листа\n"
-"на адресу <git@vger.kernel.org>.  Дякуємо.\n"
+"Якщо ви все ще використовуєте цю команду, ось що ви можете зробити:\n"
+"\n"
+"- прочитайте https://git-scm.com/docs/BreakingChanges.html\n"
+"- перевірте, чи хтось обговорював це у розсилці\n"
+"  і чи знайшли вони щось, що може\n"
+"  вам допомогти: https://lore.kernel.org/git/?q=%s\n"
+"- надішліть електронного листа на адресу <git@vger.kernel.org>, щоб "
+"повідомити нас,\n"
+"  що ви все ще використовуєте цю команду і не змогли\n"
+"  знайти їй гідну заміну\n"
+"\n"
 
 msgid "refusing to run without --i-still-use-this"
 msgstr "відмовлено в запуску без --i-still-use-this"
@@ -23874,6 +24801,9 @@
 msgid "Send this email reply required"
 msgstr "Відповідь на запитання \"Надіслати цей лист?\" є обовʼязковою"
 
+msgid "The destination IMAP folder is not properly defined."
+msgstr "Директорія IMAP призначення не визначена належним чином."
+
 msgid "The required SMTP server is not properly defined."
 msgstr "Потрібний SMTP-сервер не визначено належним чином."
 
diff --git a/po/vi.po b/po/vi.po
index caf714a..f91a7de 100644
--- a/po/vi.po
+++ b/po/vi.po
@@ -11,7 +11,7 @@
 # Vũ Tiến Hưng <newcomerminecraft@gmail.com>, 2024-2025.
 # ---
 # BẢNG THUẬT NGỮ / TERMINOLOGY
-# Updated: 2025-03-06, git 2.49
+# Updated: 2025-11-15, git 2.52
 #
 # Ghi chú:
 #  - Bảng thuật ngữ này chưa hoàn thiện.
@@ -61,15 +61,17 @@
 # | (v.) amend                        | tu bổ                        |
 # | (n.) revision                     | cải biên                     |
 # | (n.) repo/repository              | kho chứa                     |
+# | (n.) tag                          | thẻ                          |
+# | (v.) tag                          | tạo thẻ                      |
 # | | |
 # | ... TODO ...                      |                              |
 # +------------------------------------------------------------------+
 msgid ""
 msgstr ""
-"Project-Id-Version: git 2.51\n"
+"Project-Id-Version: git 2.52\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2025-08-12 17:01+0000\n"
-"PO-Revision-Date: 2025-08-14 16:16+0700\n"
+"POT-Creation-Date: 2025-11-06 23:58+0000\n"
+"PO-Revision-Date: 2025-11-15 11:38+0700\n"
 "Last-Translator: Vũ Tiến Hưng <newcomerminecraft@gmail.com>\n"
 "Language-Team: Vietnamese <https://github.com/Nekosha/git-po>\n"
 "Language: vi\n"
@@ -603,37 +605,39 @@
 msgstr "Đã không áp dụng gì cả.\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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
-"j - để lại khúc này là chưa quyết định, xem khúc chưa quyết định kế tiếp\n"
-"J - để lại khúc này là chưa quyết định, xem khúc kế tiếp\n"
-"k - để lại khúc này là chưa quyết định, xem khúc chưa quyết định kế trước\n"
-"K - để lại khúc này là chưa quyết định, xem khúc kế trước\n"
+"j - xem khúc chưa quyết định kế tiếp\n"
+"J - xem khúc kế tiếp\n"
+"k - xem khúc chưa quyết định kế trước\n"
+"K - xem khúc kế trước\n"
 "g - chọn một khúc muốn tới\n"
 "/ - tìm một khúc khớp với biểu thức chính quy\n"
 "s - chia khúc hiện tại thành các khúc nhỏ hơn\n"
 "e - sửa bằng tay khúc hiện hành\n"
-"p - in ra khúc hiện hành, 'P' để chạy trình phân trang\n"
+"p - in ra khúc hiện hành\n"
+"P - in tra khúc hiện hành có phân trang\n"
 "? - hiển thị trợ giúp\n"
 
 #, c-format
 msgid "Only one letter is expected, got '%s'"
 msgstr "Cần một ký tự, nhưng lại có '%s'"
 
-msgid "No previous hunk"
-msgstr "Không có khúc kế trước"
+msgid "No other hunk"
+msgstr "Không còn khúc nào để nhảy đến"
 
-msgid "No next hunk"
-msgstr "Không có khúc kế tiếp"
+msgid "No other undecided hunk"
+msgstr "Không còn khúc nào chưa quyết định"
 
 msgid "No other hunks to goto"
 msgstr "Không còn khúc nào để nhảy đến"
@@ -2394,14 +2398,19 @@
 msgstr "Chỉ lấy về đối tượng còn thiếu trong checkout thưa hiện tại"
 
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<đường/dẫn>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<đường/dẫn>...]"
 
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "git bisect (good|bad) [<rev>...]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (bad|new|<term-new>) [<rev>...]"
+
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (good|old|<term-old>) [<rev>...]"
 
 msgid "git bisect skip [(<rev>|<range>)...]"
 msgstr "git bisect skip [(<rev>|<vùng>)...]"
@@ -5606,6 +5615,14 @@
 msgstr "tìm thấy %i thẻ; từ bỏ tìm kiếm tại %s\n"
 
 #, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "không thể tìm blob '%s' trên một nhánh chưa sinh"
+
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "blob '%s' không thể tới được từ HEAD"
+
+#, c-format
 msgid "describe %s\n"
 msgstr "mô tả %s\n"
 
@@ -5746,6 +5763,9 @@
 msgid "%s...%s: no merge base"
 msgstr "%s...%s: không có gốc hòa trộn"
 
+msgid "cannot come back to cwd"
+msgstr "không thể quay lại thư mục làm việc hiện hành"
+
 msgid "Not a git repository"
 msgstr "Không phải là kho git"
 
@@ -5855,11 +5875,132 @@
 msgid "git fast-export [<rev-list-opts>]"
 msgstr "git fast-export [<rev-list-opts>]"
 
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
-msgstr "Lỗi: không thể xuất thẻ lồng nhau trừ khi --mark-tags được chỉ định."
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "không hiểu chế độ %s: %s"
+
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "không hiểu chế độ tag-of-filtered: %s"
+
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "Không hiểu chế độ mã hoá lại: %s"
+
+#, c-format
+msgid "could not read blob %s"
+msgstr "không thể đọc blob %s"
+
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "oid không khớp trong blob %s"
+
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "không thể ghi blob '%s'"
+
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "trạng thái lệnh so sánh không như mong đợi '%c' cho %s, %s"
+
+#
+msgid "none"
+msgstr "(không)"
+
+msgid "could not find author in commit %s"
+msgstr "không thể tìm thấy tác giả lần chuyển giao %s"
+
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "không thể tìm thấy người chuyển giao trong lần chuyển giao %s"
+
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
+msgstr ""
+
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr ""
+
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr ""
+
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr ""
+
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+
+#, c-format
+msgid "could not read tag %s"
+msgstr "không thể đọc thẻ %s"
+
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr ""
+
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "xuất thẻ đã ký %s"
+
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "Lọc bỏ chữ ký từ thẻ %s"
+
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr ""
+
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr "không thể xuất thẻ lồng nhau trừ khi --mark-tags được chỉ định."
+
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "thẻ %s chẳng chỉ đến đâu cả?"
+
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "%s: bỏ qua đối tượng kiểu không rõ %s."
+
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr "bỏ qua thẻ trỏ đến đối tượng kiểu không rõ %s."
+
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "không thể mở file dấu '%s' để ghi."
+
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "không thể ghi tập tin dấu %s."
+
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "dòng đánh dấu hỏng: %s"
+
+#, c-format
+msgid "object not found: %s"
+msgstr "không tìm thấy đối tượng: %s"
+
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "không phải là lần chuyển giao? sao lại thế: %s"
+
+#, c-format
+msgid "object %s already has a mark"
+msgstr "đối tượng %s đã có dấu"
 
 msgid "--anonymize-map token cannot be empty"
-msgstr "--anonymize-map thẻ không thể là rỗng"
+msgstr "--anonymize-map token không thể là rỗng"
 
 msgid "show progress after <n> objects"
 msgstr "hiển thị tiến triển sau <n> đối tượng"
@@ -5925,28 +6066,450 @@
 msgstr "gắn thẻ với các mã ID đánh dấu"
 
 #, c-format
-msgid "Missing from marks for submodule '%s'"
-msgstr "Thiếu các đánh dấu cho mô-đun-con '%s'"
+msgid "can't write crash report %s"
+msgstr "không thể ghi báo cáo crash %s"
 
 #, c-format
-msgid "Missing to marks for submodule '%s'"
-msgstr "Thiếu đánh dấu cho mô-đun-con '%s'"
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "fast-import: ghi báo cáo crash vào %s\n"
 
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "Cần lệnh 'mark', nhưng lại có %s"
+msgid "mark :%<PRIuMAX> not declared"
+msgstr "dấu chưa định nghĩa :%<PRIuMAX>"
 
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "Cần lệnh 'to', nhưng lại có %s"
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "tạo nhánh gặp lỗi trùng tên: %s"
 
-msgid "Expected format name:filename for submodule rewrite option"
-msgstr "Cần định dạng tên:tên_tập tin cho tùy chọn ghi lại mô-đun-con"
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "tên nhánh không hợp quy chuẩn Git: %s"
+
+msgid "internal consistency error creating the index"
+msgstr "lỗi nhất quán khi tạo chỉ mục"
+
+msgid "cannot create keep file"
+msgstr "không thể tạo keep file"
+
+msgid "failed to write keep file"
+msgstr "không thể ghi keep file"
+
+msgid "cannot store pack file"
+msgstr "không thể lưu trữ gói"
+
+msgid "cannot store index file"
+msgstr "không thể lưu trữ tập tin ghi chỉ mục"
+
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "gặp lỗi khi seek về đầu '%s'"
+
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "Git core từ chỗi chỉ mục %s"
+
+msgid "cannot truncate pack to skip duplicate"
+msgstr "không thể truncate gói để loại file trùng lặp"
+
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "hết dữ liệu (còn %<PRIuMAX> byte)"
+
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "gặp kết thúc tập tin đột xuất trong deflate: %d"
+
+#, c-format
+msgid "not a tree: %s"
+msgstr "không phải là cây: %s"
+
+#, c-format
+msgid "can't load tree %s"
+msgstr "không thể mở cây %s"
+
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "chế độ hỏng trong %s"
+
+msgid "root cannot be a non-directory"
+msgstr "thư mục gốc phải là thư mục"
+
+msgid "empty path component found in input"
+msgstr "đường dẫn trống rỗng trong đầu vào"
+
+msgid "non-directories cannot have subtrees"
+msgstr "không thể có cây thư mục mà không có thư mục"
+
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
+msgstr "bỏ %s vì nó trỏ đến chính có (tới %s)"
+
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "nhánh %s không có chuyển giao"
+
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "không cập nhật %s (đầu nhánh %s không chứa %s)"
+
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "không thể tạo các thư mục dẫn đầu của '%s'"
+
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "không thể ghi tập tin dấu %s"
+
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "không thể ghi tập tin dấu %s: %s"
+
+#, c-format
+msgid "unable to write file %s"
+msgstr "không thể ghi tập tin %s"
+
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "cần lệnh 'data n', nhưng lại có: %s"
+
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "hết dữ liệu (không tìm thấy kết '%s')"
+
+msgid "data is too large to use in this context"
+msgstr ""
+
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "hết dữ liệu (còn %lu byte)"
+
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "dòng định danh thiếu < : %s"
+
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "dòng định danh thiếu dấu cách trước < : %s"
+
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "dòng định danh thiếu > : %s"
+
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "dòng định danh thiếu dấu cách sau > : %s"
+
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "dòng định danh có ngày tháng \"%s\" không hợp lệ: %s"
+
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "dòng định danh có ngày tháng rfc2822 \"%s\" không hợp lệ: %s"
+
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "ngày tháng phải là 'now': %s"
+
+#, c-format
+msgid "too large fanout (%u)"
+msgstr ""
+
+#, c-format
+msgid "failed to remove path %s"
+msgstr "gặp lỗi khi xoá %s"
+
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "không có gì sau ':' ở dấu: %s"
+
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "có rác sau dấu: %s"
+
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "thiếu dấu cách sau dấu: %s"
+
+#, c-format
+msgid "invalid %s: %s"
+msgstr "%s không hợp lệ: %s"
+
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "ký tự NUL trong %s: %s"
+
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "có rác sau %s: %s"
+
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "thiếu dấu cách sau %s: %s"
+
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "chế độ hỏng: %s"
+
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "dataref không hợp lệ: '%s'"
+
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "thiếu dấu cách sau SHA1: %s"
+
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "không thể 'inline' liên kết Git: %s"
+
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "không phải là lần chuyển giao (thực ra là %s): %s"
+
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "không thể 'inline' thư mục: %s"
+
+#, c-format
+msgid "%s not found: %s"
+msgstr "Không tìm thấy %s: %s"
+
+msgid "tree"
+msgstr "cây"
+
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "không phải là %s (thực ra là %s): %s"
+
+#, c-format
+msgid "path %s not in branch"
+msgstr "đường dẫn %s không trong nhánh"
+
+msgid "can't add a note on empty branch."
+msgstr "không thể thêm ghi chú vào nhánh rỗng."
+
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr "dấu :%<PRIuMAX> không phải lần chuyển giao"
+
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "không phải là lần chuyển giao hợp lệ: %s"
+
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "tên tham chiếu hoặc SHA1 không hợp lệ: %s"
+
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "không phải là blob (thực ra là %s): %s"
+
+#, c-format
+msgid "blob not found: %s"
+msgstr "không tìm thấy blob: %s"
+
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "lần chuyển giao %s bị hỏng"
+
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "không thể tạo nhánh từ chính nó: %s"
+
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
+msgstr ""
+
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "không hiểu thuật toán băm dữ liệu trong gpgsig '%s'"
+
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "định dạng chữ ký không hợp lệ trong gpgsig: '%s'"
+
+msgid "'unknown' signature format in gpgsig"
+msgstr "định dạng chữ ký 'unknown' trong gpgsig"
+
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr ""
+
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr ""
+
+msgid "expected committer but didn't get one"
+msgstr "cần người chuyển giao nhưng không có"
+
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr ""
+
+msgid "stripping a commit signature"
+msgstr "loại bỏ chữ ký trong lần chuyển giao"
+
+msgid "importing a commit signature verbatim"
+msgstr ""
+
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr ""
+
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr ""
+
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr ""
+
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "Cần lệnh 'from', nhưng lại có '%s'"
+
+msgid "can't tag an empty branch."
+msgstr "không thể đánh thẻ nhánh rỗng."
+
+#, c-format
+msgid "not a valid object: %s"
+msgstr "không phải là một đối tượng hợp lệ: %s"
+
+msgid "write to frontend failed"
+msgstr ""
+
+#, c-format
+msgid "can't read object %s"
+msgstr "không thể đọc đối tượng %s"
+
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "đối tượng %s là %s, nhưng lại cần blob."
+
+#, c-format
+msgid "not a mark: %s"
+msgstr "không phải là dấu: %s"
+
+#, c-format
+msgid "unknown mark: %s"
+msgstr "không rõ dấu: %s"
+
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "có rác sau SHA1: %s"
+
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "không phải một tree-ish: %s"
+
+#, c-format
+msgid "can't load object %s"
+msgstr "không thể đọc đối tượng %s"
+
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "SHA1 không hợp lệ cho thẻ: %s"
+
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "SHA1 không hợp lệ cho lần chuyển giao: %s"
+
+#, c-format
+msgid "missing from marks for submodule '%s'"
+msgstr "thiếu đánh dấu from cho mô-đun-con '%s'"
+
+#, c-format
+msgid "missing to marks for submodule '%s'"
+msgstr "thiếu đánh dấu to cho mô-đun-con '%s'"
+
+#, c-format
+msgid "missing space after tree-ish: %s"
+msgstr "thiếu dấu cách sau tree-ish: %s"
+
+#, c-format
+msgid "not in a commit: %s"
+msgstr "không phải là lần chuyển giao: %s"
+
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "cần lệnh 'mark', nhưng lại có %s"
+
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "cần lệnh 'to', nhưng lại có %s"
+
+msgid "only one import-marks command allowed per stream"
+msgstr ""
+
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "không hiểu tham số --date-format: %s"
+
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s: đối số phải không âm"
+
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr ""
+
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr ""
+
+msgid "expected format name:filename for submodule rewrite option"
+msgstr "cần định dạng tên:tên_tập tin cho tùy chọn ghi lại mô-đun-con"
+
+#, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr ""
+
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "giới hạn kích thước tối thiểu của gói là 1 MiB"
+
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "không hiểu chế độ --signed-commits '%s'"
+
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "không hiểu chế độ --signed-tags '%s'"
 
 #, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
 msgstr ""
-"tính năng '%s' bị cấm chỉ trong đầu vào mà không có --allow-unsafe-features"
+"tính năng '%s' bị cấm trong đầu vào mà không có --allow-unsafe-features"
+
+#, c-format
+msgid "got feature command '%s' after data command"
+msgstr ""
+
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "fast-import bản này không hỗ trợ tính năng %s."
+
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr ""
+
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "fast-import bản này không hỗ trợ tuỳ chọn %s"
+
+#, c-format
+msgid "unknown option %s"
+msgstr "không hiểu tùy chọn %s"
+
+#, c-format
+msgid "unknown option --%s"
+msgstr "không hiểu tùy chọn --%s"
+
+#, c-format
+msgid "unsupported command: %s"
+msgstr "không hỗ trợ lệnh: %s"
+
+msgid "stream ends early"
+msgstr "stream kết thúc sớm"
 
 #, c-format
 msgid "Lockfile created but not reported: %s"
@@ -6022,7 +6585,7 @@
 msgstr ""
 "việc lấy về thường chỉ ra các nhánh buộc phải cập nhật,\n"
 "nhưng lựa chọn bị tắt; để kích hoạt lại, sử dụng cờ\n"
-"'--show-forced-updates' hoặc chạy 'git config fetch.showForcedUpdates true'."
+"'--show-forced-updates' hoặc chạy 'git config fetch.showForcedUpdates true'"
 
 #, c-format
 msgid ""
@@ -6083,6 +6646,22 @@
 "thông báo này. Cụ thể, 'git config set remote.%s.followRemoteHEAD %s'\n"
 "sẽ vô hiệu cảnh báo này tới khi máy chủ đổi HEAD về chỗ khác."
 
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -6323,25 +6902,6 @@
 msgid "file to read from"
 msgstr "tập tin để đọc dữ liệu từ đó"
 
-msgid "git for-each-ref [<options>] [<pattern>]"
-msgstr "git for-each-ref [<các tùy chọn>] [<mẫu>]"
-
-msgid "git for-each-ref [--points-at <object>]"
-msgstr "git for-each-ref [--points-at <đối tượng>]"
-
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr ""
-"git for-each-ref [--merged [<lần-chuyển-giao>]] [--no-merged [<lần-chuyển-"
-"giao>]]"
-
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr ""
-"git for-each-ref [--contains [<lần-chuyển-giao>]] [--no-contains [<lần-"
-"chuyển-giao>]]"
-
-msgid "git for-each-ref [--start-after <marker>]"
-msgstr "git for-each-ref [--start-after <dấu>]"
-
 msgid "quote placeholders suitably for shells"
 msgstr "trích dẫn dạng phù hợp cho shell"
 
@@ -6396,6 +6956,9 @@
 msgid "cannot use --start-after with patterns"
 msgstr "không thể dùng tùy chọn --start-after với mẫu"
 
+msgid "git for-each-ref "
+msgstr "git for-each-ref "
+
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<tùy chọn> [--] <đối số>"
 
@@ -6866,6 +7429,9 @@
 "skipping incremental-repack task because core.multiPackIndex is disabled"
 msgstr "bỏ qua tác vụ incremental-repack vì core.multiPackIndex bị vô hiệu hóa"
 
+msgid "failed to perform geometric repack"
+msgstr ""
+
 #, c-format
 msgid "task '%s' failed"
 msgstr "gặp lỗi khi thực hiện nhiệm vụ '%s'"
@@ -6875,6 +7441,10 @@
 msgstr "đã có khóa của tập tin '%s', bỏ qua bảo trì"
 
 #, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "không hiểu chiến lược bảo trì: '%s'"
+
+#, c-format
 msgid "'%s' is not a valid task"
 msgstr "'%s' không phải một nhiệm vụ hợp lệ"
 
@@ -7314,7 +7884,7 @@
 "'%s': path for unsupported man viewer.\n"
 "Please consider using 'man.<tool>.cmd' instead."
 msgstr ""
-"'%s': đường dẫn không hỗ trợ bộ trình chiếu man.\n"
+"'%s': đường dẫn không hỗ trợ trình xem man.\n"
 "Hãy cân nhắc đến việc sử dụng 'man.<tool>.cmd' để thay thế."
 
 #, c-format
@@ -7322,12 +7892,12 @@
 "'%s': cmd for supported man viewer.\n"
 "Please consider using 'man.<tool>.path' instead."
 msgstr ""
-"'%s': cmd (lệnh) hỗ trợ bộ trình chiếu man.\n"
+"'%s': cmd (lệnh) hỗ trợ trình xem man.\n"
 "Hãy cân nhắc đến việc sử dụng 'man.<tool>.path' để thay thế."
 
 #, c-format
 msgid "'%s': unknown man viewer."
-msgstr "'%s': không rõ chương trình xem man."
+msgstr "'%s': không rõ trình xem man."
 
 msgid "no man viewer handled the request"
 msgstr "không có trình xem trợ giúp dạng manpage tiếp hợp với yêu cầu"
@@ -7728,6 +8298,27 @@
 msgid "no input file given for in-place editing"
 msgstr "không đưa ra tập tin đầu vào để sửa tại-chỗ"
 
+msgid "last-modified can only operate on one tree at a time"
+msgstr ""
+
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "không hiểu tham số last-modified: %s"
+
+msgid "unable to setup last-modified"
+msgstr ""
+
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+
+msgid "recurse into subtrees"
+msgstr "đệ quy vào các thư mục con"
+
+msgid "show tree entries when recursing into subtrees"
+msgstr "hiển thị cây khi đệ quy"
+
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
 msgstr "git log [<các tùy chọn>] [<vùng-xem-xét>] [[--] </đường/dẫn>...]"
 
@@ -7766,6 +8357,15 @@
 msgid "-L<range>:<file> cannot be used with pathspec"
 msgstr "-L<vùng>:<tập tin> không thể được sử dụng với đặc tả đường dẫn"
 
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s: sai tập tin"
@@ -8206,9 +8806,6 @@
 msgid "only show trees"
 msgstr "chỉ hiển thị các tree"
 
-msgid "recurse into subtrees"
-msgstr "đệ quy vào các thư mục con"
-
 msgid "show trees when recursing"
 msgstr "hiển thị cây khi đệ quy"
 
@@ -8358,10 +8955,6 @@
 msgstr "Không thể ghi vào tập tin"
 
 #, c-format
-msgid "unknown option %s"
-msgstr "không hiểu tùy chọn %s"
-
-#, c-format
 msgid "could not parse object '%s'"
 msgstr "không thể đọc đối tượng '%s'"
 
@@ -8528,10 +9121,6 @@
 msgid "stash failed"
 msgstr "lệnh tạm cất gặp lỗi"
 
-#, c-format
-msgid "not a valid object: %s"
-msgstr "không phải là một đối tượng hợp lệ: %s"
-
 msgid "read-tree failed"
 msgstr "read-tree gặp lỗi"
 
@@ -9380,7 +9969,7 @@
 
 #, c-format
 msgid "unable to pack objects reachable from tag %s"
-msgstr "không thể đóng gói các đối tượng tiếp cận được từ thẻ '%s'"
+msgstr "không thể đóng gói các đối tượng tiếp cận được từ thẻ %s"
 
 #, c-format
 msgid "unable to get type of object %s"
@@ -9673,27 +10262,8 @@
 "Tổng %<PRIu32> (delta %<PRIu32>), dùng lại %<PRIu32> (delta %<PRIu32>), dùng "
 "lại pack %<PRIu32> (trong số %<PRIuMAX>)"
 
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-
-msgid "pack everything"
-msgstr "đóng gói mọi thứ"
-
-msgid "prune loose refs (default)"
-msgstr "prune (cắt cụt) những tham chiếu bị mất (mặc định)"
-
-msgid "auto-pack refs as needed"
-msgstr "tự động pack tham chiếu nếu cần"
-
-msgid "references to include"
-msgstr "bao gồm các tham chiếu"
-
-msgid "references to exclude"
-msgstr "loại trừ các tham chiếu"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
 msgid "git patch-id [--stable | --unstable | --verbatim]"
 msgstr "git patch-id [--stable | --unstable | --verbatim]"
@@ -10210,6 +10780,10 @@
 msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
 msgstr "git range-diff [<các tùy chọn>] <base> <old-tip> <new-tip>"
 
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "giá trị max-memory không hợp lệ: %s"
+
 msgid "use simple diff colors"
 msgstr "dùng màu diff đơn giản"
 
@@ -10219,6 +10793,12 @@
 msgid "passed to 'git log'"
 msgstr "chuyển cho 'git log'"
 
+msgid "size"
+msgstr ""
+
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr ""
+
 msgid "only emit output related to the first range"
 msgstr "chỉ phát ra kết quả liên quan đến vùng đầu tiên"
 
@@ -10778,30 +11358,33 @@
 msgid "git reflog list"
 msgstr "git reflog list"
 
-msgid ""
-"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
-"                  [--rewrite] [--updateref] [--stale-fix]\n"
-"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
-"<refs>...]"
-msgstr ""
-"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
-"                  [--rewrite] [--updateref] [--stale-fix]\n"
-"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
-"<refs>...]"
-
-msgid ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-msgstr ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-
 msgid "git reflog exists <ref>"
 msgstr "git reflog exists <tham_chiếu>"
 
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr ""
+
+msgid ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+msgstr ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+
 msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
 msgstr "git reflog drop [--all [--single-worktree] | <tham_chiếu>...]"
 
+msgid ""
+"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
+"<refs>...]"
+msgstr ""
+"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
+"<refs>...]"
+
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "dấu vết thời gian không hợp lệ '%s' đưa cho '--%s'"
@@ -10869,12 +11452,50 @@
 msgid "references specified along with --all"
 msgstr "chỉ định tham chiếu với tùy chọn --all"
 
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "tham chiếu không hợp lệ: %s"
+
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "ID đối tượng cũ không hợp lệ: '%s'"
+
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "đối tượng cũ '%s' không tồn tại"
+
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "ID đối tượng mới không hợp lệ: %s"
+
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "đối tượng mới '%s' không tồn tại"
+
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr ""
+
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr ""
+
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr ""
+
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=<định dạng> [--no-reflog] [--dry-run]"
 
 msgid "git refs verify [--strict] [--verbose]"
 msgstr "git refs verify [--strict] [--verbose]"
 
+msgid "git refs exists <ref>"
+msgstr "git refs exists <tham_chiếu>"
+
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
 msgid "specify the reference format to convert to"
 msgstr "chỉ định định dạng tham chiếu để chuyển đổi sang"
 
@@ -10897,6 +11518,18 @@
 msgid "'git refs verify' takes no arguments"
 msgstr "'git refs verify' không nhận tham số"
 
+msgid "git refs list "
+msgstr "git refs list "
+
+msgid "'git refs exists' requires a reference"
+msgstr ""
+
+msgid "reference does not exist"
+msgstr "tham chiếu không tồn tại"
+
+msgid "failed to look up reference"
+msgstr "gặp lỗi khi tìm tham chiếu"
+
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
 "mirror=<fetch|push>] <name> <url>"
@@ -11053,6 +11686,16 @@
 "\t%s:%d\n"
 "bây giờ tên trên máy chủ không tồn tại '%s'"
 
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "Không có máy chủ nào như vậy: '%s'"
@@ -11061,6 +11704,13 @@
 msgid "Could not rename config section '%s' to '%s'"
 msgstr "Không thể đổi tên phần của cấu hình từ '%s' thành '%s'"
 
+msgid "Renaming remote references"
+msgstr "Đổi tên các tham chiếu máy chủ"
+
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr ""
+
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -11071,16 +11721,9 @@
 "\t%s\n"
 "\tXin hãy cập nhật phần cấu hình một cách thủ công nếu cần."
 
-msgid "Renaming remote references"
-msgstr "Đổi tên các tham chiếu máy chủ"
-
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "gặp lỗi khi xóa '%s'"
-
-#, c-format
-msgid "creating '%s' failed"
-msgstr "gặp lỗi khi tạo '%s'"
+msgid "renaming remote refs failed: %s"
+msgstr "đổi tên tham chiếu gặp lỗi: %s"
 
 msgid ""
 "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
@@ -11354,48 +11997,6 @@
 "Gia tăng các repack là không tương thích với chỉ mục bitmap. Dùng\n"
 "--no-write-bitmap-index hay tắt cấu hình pack.writeBitmaps."
 
-msgid "could not start pack-objects to repack promisor objects"
-msgstr ""
-"không thể lấy thông tin thống kê pack-objects để đóng gói lại các đối tượng "
-"promisor"
-
-msgid "failed to feed promisor objects to pack-objects"
-msgstr "gặp lỗi khi đưa promisor object cho pack-objects"
-
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr ""
-"repack: Đang chỉ cần các dòng ID đối tượng dạng hexa đầy đủ từ pack-objects."
-
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr "không thể hoàn tất pack-objects để đóng gói các đối tượng promisor"
-
-#, c-format
-msgid "cannot open index for %s"
-msgstr "không thể mở chỉ mục cho %s"
-
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr "gói %s quá lớn để xem xét cấp số nhân"
-
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "gói %s quá lớn để cuộn lại"
-
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "không thể mở tập tin tạm %s để ghi"
-
-msgid "could not close refs snapshot tempfile"
-msgstr "không thể đóng tập tin snapshot các tham chiếu"
-
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "không thể xoá bỏ bitmap đã cũ: %s"
-
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "tiền tố gói '%s' không được bắt đầu với objdir '.%s'"
-
 msgid "pack everything in a single pack"
 msgstr "đóng gói mọi thứ trong một gói đơn"
 
@@ -11492,18 +12093,6 @@
 msgid "Nothing new to pack."
 msgstr "Không có gì mới để đóng gói."
 
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "gặp lỗi khi đổi tên gói thành '%s'"
-
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "pack-objects không ghi tập tin '%s' cho gói %s-%s"
-
-#, c-format
-msgid "could not unlink: %s"
-msgstr "không thể unlink: %s"
-
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] <đối-tượng> <thay-thế>"
 
@@ -11754,6 +12343,62 @@
 msgid "replaying merge commits is not supported yet!"
 msgstr "chưa hỗ trợ phát lại các lần hoà trộn!"
 
+#, c-format
+msgid "key '%s' not found"
+msgstr "không tìm thấy khoá '%s'"
+
+#, c-format
+msgid "invalid format '%s'"
+msgstr "định dạng không hợp lệ '%s'"
+
+msgid "output format"
+msgstr "định dạng kết quả"
+
+msgid "synonym for --format=nul"
+msgstr "đồng nghĩa với --format=nul"
+
+msgid "unsupported output format"
+msgstr "không hỗ trợ định dạng kết quả: %s"
+
+msgid "References"
+msgstr "kho tham chiếu"
+
+msgid "Count"
+msgstr "Số lượng"
+
+msgid "Branches"
+msgstr "Nhánh"
+
+msgid "Tags"
+msgstr "Thẻ"
+
+msgid "Remotes"
+msgstr "Máy chủ"
+
+msgid "Others"
+msgstr "Khác"
+
+msgid "Reachable objects"
+msgstr "Các đối tượng có thể tới được"
+
+msgid "Commits"
+msgstr "Lần chuyển giao"
+
+msgid "Trees"
+msgstr "Cây"
+
+msgid "Blobs"
+msgstr "Blob"
+
+msgid "Repository structure"
+msgstr "Bố cục kho Git"
+
+msgid "Value"
+msgstr "Giá trị"
+
+msgid "Counting references"
+msgstr "Đang đếm tham chiếu"
+
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
 msgstr ""
@@ -12335,12 +12980,6 @@
 msgid "git show-ref --exists <ref>"
 msgstr "git show-ref --exists <tham_chiếu>"
 
-msgid "reference does not exist"
-msgstr "tham chiếu không tồn tại"
-
-msgid "failed to look up reference"
-msgstr "gặp lỗi khi tìm tham chiếu"
-
 msgid "only show tags (can be combined with --branches)"
 msgstr "chỉ hiển thị thẻ (có thể kết hợp với --branches)"
 
@@ -12370,10 +13009,10 @@
 
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<các-tùy-chọn>]"
+"rules| clean) [<các-tùy-chọn>]"
 
 msgid "this worktree is not sparse"
 msgstr "cây làm việc này không thưa"
@@ -12414,10 +13053,6 @@
 msgstr "bật tắt việc sử dụng sparse index"
 
 #, c-format
-msgid "unable to create leading directories of %s"
-msgstr "không thể tạo các thư mục dẫn đầu của '%s'"
-
-#, c-format
 msgid "failed to open '%s'"
 msgstr "gặp lỗi khi mở '%s'"
 
@@ -12496,6 +13131,30 @@
 msgid "must be in a sparse-checkout to reapply sparsity patterns"
 msgstr "phải trong sparse-checkout để áp dụng lại các mẫu sparse"
 
+msgid "report each affected file, not just directories"
+msgstr "liệt kê các tập tin cùng thư mục"
+
+msgid "must be in a sparse-checkout to clean directories"
+msgstr "phải trong sparse-checkout để làm sạch thư mục"
+
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr "phải trong sparse-checkout chế độ cone để làm sạch thư mục"
+
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr "từ chối làm sạch mà không có tuỳ chọn --force hoặc --dry-run"
+
+msgid "failed to read index"
+msgstr "gặp lỗi đọc chỉ mục"
+
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr ""
+
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "gặp lỗi khi xoá '%s'"
+
 msgid "error while refreshing working directory"
 msgstr "gặp lỗi khi đọc lại thư mục làm việc"
 
@@ -14196,9 +14855,6 @@
 msgid "only useful for debugging"
 msgstr "chỉ hữu ích khi cần gỡ lỗi"
 
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "core.fsyncMethod = batch không được hỗ trợ trên nền tảng này"
-
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
 msgstr "không thể đọc danh sách bundle khoá %s giá trị '%s'"
@@ -14596,6 +15252,9 @@
 msgid "Add or parse structured information in commit messages"
 msgstr "Thêm hay đọc thông tin cấu trúc trong ghi chú lần chuyển giao"
 
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr ""
+
 msgid "Show commit logs"
 msgstr "Hiển thị nhật ký các lần chuyển giao"
 
@@ -14720,6 +15379,9 @@
 "ĐANG TRONG QUÁ TRÌNH THỬ NGHIỆM: Phát lại lần chuyển giao vào gốc mới, dùng "
 "được trong kho chứa bare"
 
+msgid "Retrieve information about the repository"
+msgstr "Đọc thông tin kho chứa"
+
 msgid "Generates a summary of pending changes"
 msgstr "Tạo ra một tóm tắt các thay đổi còn treo"
 
@@ -14803,8 +15465,8 @@
 msgid "Read, modify and delete symbolic refs"
 msgstr "Đọc, sửa và xóa tham chiếu mềm"
 
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr "Tạo, liệt kê, xóa hay xác minh một đối tượng thẻ được ký bằng GPG"
+msgid "Create, list, delete or verify tags"
+msgstr "Tạo, liệt kê, xóa hay xác minh thẻ"
 
 msgid "Creates a temporary file with a blob's contents"
 msgstr "Tạo một tập tin tạm với nội dung của blob"
@@ -15650,6 +16312,34 @@
 msgid "unable to parse command-line config"
 msgstr "không thể đọc cấu hình dòng lệnh"
 
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+
+msgid "<comment string>"
+msgstr "<ghi chú>"
+
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr ""
+
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr ""
+
 msgid "unknown error occurred while reading the configuration files"
 msgstr "đã có lỗi chưa biết xảy ra trong khi đọc các tập tin cấu hình"
 
@@ -16108,7 +16798,7 @@
 msgstr "đang bỏ qua '%s', không phải là một tập tin hay thư mục"
 
 msgid "could not duplicate stdout"
-msgstr "không thể nhân bản stdout"
+msgstr "không thể dup stdout"
 
 #, c-format
 msgid "could not add directory '%s' to archiver"
@@ -16117,8 +16807,14 @@
 msgid "failed to write archive"
 msgstr "gặp lỗi khi ghi kho nén"
 
+msgid "max-depth is not supported for worktree diffs"
+msgstr "không hỗ trợ max-depth cho diff ở cây làm việc"
+
+msgid "max-depth is not supported for index diffs"
+msgstr "không hỗ trợ max-depth cho diff chỉ mục"
+
 msgid "--merge-base does not work with ranges"
-msgstr "--merge-base không thể dùng với chỉ vùng"
+msgstr "--merge-base không thể dùng với vùng"
 
 msgid "unable to get HEAD"
 msgstr "không thể lấy HEAD"
@@ -16625,6 +17321,12 @@
 msgid "select files by diff type"
 msgstr "chọn các tập tin theo kiểu khác biệt"
 
+msgid "<depth>"
+msgstr "<độ-sâu>"
+
+msgid "maximum tree depth to recurse"
+msgstr "độ sâu đệ quy tối đa"
+
 msgid "<file>"
 msgstr "<tập tin>"
 
@@ -16817,10 +17519,6 @@
 msgstr "dòng unshallow không hợp lệ: %s"
 
 #, c-format
-msgid "object not found: %s"
-msgstr "không tìm thấy đối tượng: %s"
-
-#, c-format
 msgid "error in object: %s"
 msgstr "lỗi trong đối tượng: %s"
 
@@ -17103,6 +17801,11 @@
 msgid "recursive alias: %s"
 msgstr "đệ quy các bí danh: %s"
 
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr ""
+"dò tìm thấy các bí danh quẩn tròn: biểu thức của '%s' không có điểm kết:%s"
+
 msgid "write failure on standard output"
 msgstr "lỗi khi ghi ra stdout"
 
@@ -17113,11 +17816,6 @@
 msgstr "lỗi khi đóng stdout"
 
 #, c-format
-msgid "alias loop detected: expansion of '%s' does not terminate:%s"
-msgstr ""
-"dò tìm thấy các bí danh quẩn tròn: biểu thức của '%s' không có điểm kết:%s"
-
-#, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "không thể xử lý %s như là builtin"
 
@@ -17168,7 +17866,11 @@
 
 #, c-format
 msgid "failed to get the ssh fingerprint for key '%s'"
-msgstr "gặp lỗi khi lấy dấu vân tay ssh cho khóa '%s'"
+msgstr "gặp lỗi khi lấy ssh fingerprint cho khóa '%s'"
+
+#, c-format
+msgid "failed to get the ssh fingerprint for key %s"
+msgstr "gặp lỗi khi lấy ssh fingerprint cho khóa %s"
 
 msgid ""
 "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
@@ -17176,6 +17878,10 @@
 "hoặc là user.signingkey hoặc gpg.ssh.defaultKeyCommand cần được cấu hình"
 
 #, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr "gpg.ssh.defaultKeyCommand sai quy cách: %s"
+
+#, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr ""
 "gpg.ssh.defaultKeyCommand thành công nhưng lại không trả về khóa nào: %s %s"
@@ -17425,6 +18131,11 @@
 "      hỏi cho: %s\n"
 " chuyển hướng: %s"
 
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr ""
+
 msgid "Author identity unknown\n"
 msgstr "Chưa biết định danh tác giả\n"
 
@@ -17880,10 +18591,6 @@
 msgstr "không thể tải gói"
 
 #, c-format
-msgid "could not open index for %s"
-msgstr "không thể mở chỉ mục cho %s"
-
-#, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "không thể liên kết '%s' vào '%s'"
 
@@ -17906,6 +18613,10 @@
 msgstr "không hiểu preferred pack: %s"
 
 #, c-format
+msgid "failed to open preferred pack %s"
+msgstr "gặp lỗi khi mở preferred pack %s"
+
+#, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr "không thể chọn gói ưa dùng %s với không đối tượng nào"
 
@@ -17929,6 +18640,9 @@
 msgid "could not write multi-pack bitmap"
 msgstr "không thể ghi multi-pack bitmap"
 
+msgid "too many multi-pack-indexes"
+msgstr "quá nhiều multi-pack-indexes"
+
 msgid "unable to open multi-pack-index chain file"
 msgstr "không thể mở tập tin chain multi-pack-index"
 
@@ -18192,10 +18906,6 @@
 msgstr "tập tin '%s' và '%s' có nội dung khác nhau"
 
 #, c-format
-msgid "unable to write file %s"
-msgstr "không thể ghi tập tin %s"
-
-#, c-format
 msgid "unable to write repeatedly vanishing file %s"
 msgstr "không thể ghi vào tập tin biến mất liên tục %s"
 
@@ -18203,6 +18913,9 @@
 msgid "unable to set permission to '%s'"
 msgstr "không thể đặt quyền thành '%s'"
 
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = batch không được hỗ trợ trên nền tảng này"
+
 msgid "error when closing loose object file"
 msgstr "gặp lỗi trong khi đóng tập tin đối tượng"
 
@@ -18698,6 +19411,21 @@
 msgid "mtimes file %s is corrupt"
 msgstr "tập tin mtimes %s bị hỏng"
 
+msgid "pack everything"
+msgstr "đóng gói mọi thứ"
+
+msgid "prune loose refs (default)"
+msgstr "prune (cắt cụt) những tham chiếu bị mất (mặc định)"
+
+msgid "auto-pack refs as needed"
+msgstr "tự động pack tham chiếu nếu cần"
+
+msgid "references to include"
+msgstr "bao gồm các tham chiếu"
+
+msgid "references to exclude"
+msgstr "loại trừ các tham chiếu"
+
 #, c-format
 msgid "reverse-index file %s is too small"
 msgstr "tập tin reverse-index %s quá nhỏ"
@@ -19121,6 +19849,10 @@
 msgstr "không thể tải %s từ máy chủ promisor"
 
 #, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr ""
+
+#, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "URL máy chủ '%s' rỗng hoặc không có"
 
@@ -19129,12 +19861,16 @@
 msgstr "có máy chủ '%s' nhưng với URL '%s' thay vì '%s'"
 
 #, c-format
-msgid "unknown '%s' value for '%s' config option"
-msgstr "không hiểu giá trị '%s' cho cấu hình '%s'"
+msgid "invalid element '%s' from remote info"
+msgstr "không hiểu phần '%s' từ thông tin máy chủ"
 
 #, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "không hiểu phần '%s' từ thông tin máy chủ"
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr ""
+
+#, c-format
+msgid "unknown '%s' value for '%s' config option"
+msgstr "không hiểu giá trị '%s' cho cấu hình '%s'"
 
 #, c-format
 msgid "accepted promisor remote '%s' not found"
@@ -19228,6 +19964,13 @@
 msgstr "gặp lỗi khi tạo khác biệt"
 
 #, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+
+#, c-format
 msgid "could not parse log for '%s'"
 msgstr "không thể đọc nhật ký cho '%s'"
 
@@ -19758,6 +20501,9 @@
 msgid "no reflog for '%s'"
 msgstr "không reflog cho '%s'"
 
+msgid "Checking references consistency"
+msgstr "Đang kiểm tra tính nhất quán các tham chiếu"
+
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "'%s' không chỉ đến một lần chuyển giao hợp lệ nào cả!"
@@ -19773,8 +20519,9 @@
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -19783,9 +20530,9 @@
 "\n"
 "\tgit branch -m <name>\n"
 msgstr ""
-"Sử dụng '%s' làm tên cho nhánh ban đầu. Tên nhánh mặc định này\n"
-"có thể thay đổi. Để cấu hình tên nhánh khởi đầu sử dụng trong tất cả\n"
-"kho lưu trữ mới của bạn, cái mà sẽ ngăn chặn cảnh báo này, gọi lệnh:\n"
+"Sử dụng '%s' làm tên cho nhánh ban đầu. Tên nhánh mặc định\n"
+"sẽ thay đổi sang \"main\" từ Git 3.0. Để cấu hình tên nhánh ban đầu cho\n"
+"tất cả kho lưu trữ mới của bạn, và ngăn chặn cảnh báo này, gọi lệnh:\n"
 "\n"
 "\tgit config --global init.defaultBranch <tên>\n"
 "\n"
@@ -19795,6 +20542,20 @@
 "\tgit branch -m <tên>\n"
 
 #, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"Sử dụng '%s' làm tên cho nhánh ban đầu kể từ Git 3.0. \n"
+"Nếu bạn muốn git tạo nhánh 'master', nhánh vừa tạo có thể được\n"
+"đổi tên thông qua lệnh:\n"
+"\n"
+"\tgit branch -m master\n"
+
+#, c-format
 msgid "could not retrieve `%s`"
 msgstr "không thể lấy về '%s'"
 
@@ -19879,6 +20640,18 @@
 msgid "migrated refs can be found at '%s'"
 msgstr "ydam chiếu đã di cư tại '%s'"
 
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+
 #, c-format
 msgid ""
 "cannot lock ref '%s': expected symref with target '%s': but is a regular ref"
@@ -19887,6 +20660,10 @@
 "tham chiếu thường"
 
 #, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr "thử ghi tham chiếu cho '%s' không đầy đủ giá trị"
+
+#, c-format
 msgid "cannot read ref file '%s'"
 msgstr "không thể đọc tập tin ref '%s'"
 
@@ -19894,9 +20671,6 @@
 msgid "cannot open directory %s"
 msgstr "không thể mở thư mục %s"
 
-msgid "Checking references consistency"
-msgstr "Đang kiểm tra tính nhất quán các tham chiếu"
-
 #, c-format
 msgid "unable to open '%s'"
 msgstr "không thể mở '%s'"
@@ -19937,6 +20711,10 @@
 "chiếu biểu trưng '%s')"
 
 #, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr "không thể lock tham chiếu '%s': tham chiếu biểu trưng đã tồn tại"
+
+#, c-format
 msgid "cannot lock ref '%s': reference already exists"
 msgstr "không thể lock tham chiếu '%s': tham chiếu đã tồn tại"
 
@@ -20036,9 +20814,6 @@
 msgid "RPC failed; %s"
 msgstr "RPC gặp lỗi; %s"
 
-msgid "cannot handle pushes this big"
-msgstr "không thể xử lý đẩy lớn cỡ này"
-
 #, c-format
 msgid "cannot deflate request; zlib deflate error %d"
 msgstr "không thể giải nén yêu cầu; lỗi zlib deflate %d"
@@ -20226,6 +21001,11 @@
 "'%s:refs/tags/%s'?"
 
 #, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr ""
+
+#, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "'%s' không thể được phân giải thành nhánh"
 
@@ -20347,6 +21127,60 @@
 msgstr "không thể cắt bỏ một thành phần ra khỏi '%s' url"
 
 #, c-format
+msgid "cannot open index for %s"
+msgstr "không thể mở chỉ mục cho %s"
+
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr "gói %s quá lớn để xem xét cấp số nhân"
+
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "gói %s quá lớn để cuộn lại"
+
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "không thể mở tập tin tạm %s để ghi"
+
+msgid "could not close refs snapshot tempfile"
+msgstr "không thể đóng tập tin snapshot các tham chiếu"
+
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "không thể xoá bỏ bitmap đã cũ: %s"
+
+msgid "could not start pack-objects to repack promisor objects"
+msgstr ""
+"không thể lấy thông tin thống kê pack-objects để đóng gói lại các đối tượng "
+"promisor"
+
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "gặp lỗi khi đưa promisor object cho pack-objects"
+
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr ""
+"repack: Đang chỉ cần các dòng ID đối tượng dạng hexa đầy đủ từ pack-objects."
+
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr "không thể hoàn tất pack-objects để đóng gói các đối tượng promisor"
+
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "tiền tố gói '%s' không được bắt đầu với objdir '.%s'"
+
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr "gặp lỗi khi đổi tên gói thành '%s'"
+
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "pack-objects không ghi tập tin '%s' cho gói %s-%s"
+
+#, c-format
+msgid "could not unlink: %s"
+msgstr "không thể unlink: %s"
+
+#, c-format
 msgid "bad replace ref name: %s"
 msgstr "tên tham chiếu thay thế bị sai: %s"
 
@@ -21654,9 +22488,6 @@
 msgid "cannot chdir to '%s'"
 msgstr "không thể chdir (chuyển thư mục) sang '%s'"
 
-msgid "cannot come back to cwd"
-msgstr "không thể quay lại thư mục làm việc hiện hành"
-
 #, c-format
 msgid "failed to stat '%*s%s%s'"
 msgstr "gặp lỗi khi stat'%*s%s%s'"
@@ -22730,18 +23561,32 @@
 msgstr "cảnh báo: "
 
 #, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "'%s' được đề cử loại bỏ.\n"
+
+#, c-format
 msgid ""
-"'%s' 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"
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
 msgstr ""
-"'%s' đã được đề cử để loại bỏ.\n"
-"Nếu bạn vẫn còn sử dụng lệnh này, vui lòng bổ sung\n"
-"thêm một tùy chọn, '--i-still-use-this', trên dòng lệnh\n"
-"và cho chúng tôi biết bạn vẫn sử dụng nó bằng cách gửi e-mail\n"
-"đến <git@vger.kernel.org>. Xin cảm ơn.\n"
+"Nếu bạn vẫn còn dùng lệnh này, hãy làm theo các bước sau:\n"
+"\n"
+"- đọc https://git-scm.com/docs/BreakingChanges.html\n"
+"- kiểm tra xem có ai khác đã thảo luận trên mailing\n"
+"  list và có cách giúp bạn:\n"
+"  https://lore.kernel.org/git/?q=%s\n"
+"- gửi email tới <git@vger.kernel.org> để chúng tôi biết\n"
+"  bạn vẫn còng dùng lệnh này và không thể tìm phương án\n"
+"  thay thế\n"
+"\n"
 
 msgid "refusing to run without --i-still-use-this"
 msgstr "từ chối chạy lệnh này mà không có --i-still-use-this"
@@ -23604,6 +24449,9 @@
 msgid "Send this email reply required"
 msgstr "Hãy trả lời yêu cầu gửi email"
 
+msgid "The destination IMAP folder is not properly defined."
+msgstr "Thư mục IMAP đích chưa được định nghĩa đúng cách."
+
 msgid "The required SMTP server is not properly defined."
 msgstr "Máy chủ SMTP chưa được định nghĩa đúng cách."
 
@@ -23727,6 +24575,64 @@
 msgid "Do you really want to send %s? [y|N]: "
 msgstr "Bạn có thực sự muốn gửi %s? [y|N](có/KHÔNG): "
 
+#~ msgid "No previous hunk"
+#~ msgstr "Không có khúc kế trước"
+
+#~ msgid "No next hunk"
+#~ msgstr "Không có khúc kế tiếp"
+
+#~ msgid "git for-each-ref [<options>] [<pattern>]"
+#~ msgstr "git for-each-ref [<các tùy chọn>] [<mẫu>]"
+
+#~ msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
+#~ msgstr ""
+#~ "git for-each-ref [--merged [<lần-chuyển-giao>]] [--no-merged [<lần-chuyển-"
+#~ "giao>]]"
+
+#~ msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
+#~ msgstr ""
+#~ "git for-each-ref [--contains [<lần-chuyển-giao>]] [--no-contains [<lần-"
+#~ "chuyển-giao>]]"
+
+#~ msgid "git for-each-ref [--start-after <marker>]"
+#~ msgstr "git for-each-ref [--start-after <dấu>]"
+
+#~ msgid ""
+#~ "git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--"
+#~ "exclude <pattern>]"
+#~ msgstr ""
+#~ "git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--"
+#~ "exclude <pattern>]"
+
+#, c-format
+#~ msgid "deleting '%s' failed"
+#~ msgstr "gặp lỗi khi xóa '%s'"
+
+#, c-format
+#~ msgid "creating '%s' failed"
+#~ msgstr "gặp lỗi khi tạo '%s'"
+
+#, c-format
+#~ msgid "could not open index for %s"
+#~ msgstr "không thể mở chỉ mục cho %s"
+
+#~ msgid "cannot handle pushes this big"
+#~ msgstr "không thể xử lý đẩy lớn cỡ này"
+
+#, c-format
+#~ msgid ""
+#~ "'%s' 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 ""
+#~ "'%s' đã được đề cử để loại bỏ.\n"
+#~ "Nếu bạn vẫn còn sử dụng lệnh này, vui lòng bổ sung\n"
+#~ "thêm một tùy chọn, '--i-still-use-this', trên dòng lệnh\n"
+#~ "và cho chúng tôi biết bạn vẫn sử dụng nó bằng cách gửi e-mail\n"
+#~ "đến <git@vger.kernel.org>. Xin cảm ơn.\n"
+
 #~ msgid "start-after"
 #~ msgstr "start-after"
 
@@ -23778,10 +24684,6 @@
 #~ msgstr "không thể dùng tùy chọn --stdin-packs với --cruft"
 
 #, c-format
-#~ msgid "%s points nowhere!"
-#~ msgstr "%s chẳng chỉ đến đâu cả!"
-
-#, c-format
 #~ msgid "unreachable: invalid reference: %s"
 #~ msgstr "không tham chiếu được: tham chiếu không hợp lệ: %s"
 
@@ -23986,10 +24888,6 @@
 #~ "mục %s->%s trong %s"
 
 #, c-format
-#~ msgid "cannot read object %s"
-#~ msgstr "không thể đọc đối tượng %s"
-
-#, c-format
 #~ msgid "object %s is not a blob"
 #~ msgstr "đối tượng %s không phải là một blob"
 
diff --git a/po/zh_CN.po b/po/zh_CN.po
index a0d43c5..db7518c 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -155,8 +155,8 @@
 msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2025-08-12 20:20-0400\n"
-"PO-Revision-Date: 2025-08-17 08:14-0400\n"
+"POT-Creation-Date: 2025-11-15 22:02+0800\n"
+"PO-Revision-Date: 2025-11-16 01:03+0800\n"
 "Last-Translator: Teng Long <dyroneteng@gmail.com>\n"
 "Language-Team: GitHub <https://github.com/dyrone/git/>\n"
 "Language: zh_CN\n"
@@ -782,26 +782,28 @@
 
 #: add-patch.c
 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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
-"j - 维持该块未决状态,查看下一个未决块\n"
-"J - 维持该块未决状态,查看下一个块\n"
-"k - 维持该块未决状态,查看上一个未决块\n"
-"K - 维持该块未决状态,查看上一个块\n"
-"g - 选择跳转到一个块\n"
+"j - 跳转至下一个未决定块,在底部翻页\n"
+"J - 跳转至下一个块,在底部翻页\n"
+"k - 跳转至上一个未决定块,在顶部翻页\n"
+"K - 跳转至上一个块,在顶部翻页\n"
+"g - 选择要跳转的块\n"
 "/ - 查找和给定正则表达式匹配的块\n"
 "s - 拆分当前块为更小的块\n"
 "e - 手动编辑当前块\n"
-"p - 显示当前块, 'P' 使用分页器\n"
+"p - 显示当前块\n"
+"P - 使用分页器显示当前块\n"
 "? - 显示帮助\n"
 
 #: add-patch.c
@@ -810,12 +812,12 @@
 msgstr "预期只有一个字母,得到 '%s'"
 
 #: add-patch.c
-msgid "No previous hunk"
-msgstr "没有前一个块"
+msgid "No other hunk"
+msgstr "没有其它块"
 
 #: add-patch.c
-msgid "No next hunk"
-msgstr "没有下一个块"
+msgid "No other undecided hunk"
+msgstr "没有其它未决定的块"
 
 #: add-patch.c
 msgid "No other hunks to goto"
@@ -1060,7 +1062,8 @@
 msgstr "未关闭的引号"
 
 #: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c
-#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c
+#: builtin/receive-pack.c builtin/refs.c builtin/repo.c builtin/tag.c
+#: t/helper/test-pkt-line.c
 msgid "too many arguments"
 msgstr "太多参数"
 
@@ -1374,7 +1377,7 @@
 msgid "%s has type %o, expected %o"
 msgstr "%s 的类型是 %o,应为 %o"
 
-#: apply.c read-cache.c
+#: apply.c builtin/fast-import.c read-cache.c
 #, c-format
 msgid "invalid path '%s'"
 msgstr "无效路径 '%s'"
@@ -1753,7 +1756,7 @@
 msgid "git archive --remote <repo> [--exec <cmd>] --list"
 msgstr "git archive --remote <仓库> [--exec <命令>] --list"
 
-#: archive.c builtin/gc.c builtin/notes.c builtin/tag.c
+#: archive.c builtin/fast-import.c builtin/gc.c builtin/notes.c builtin/tag.c
 #, c-format
 msgid "cannot read '%s'"
 msgstr "不能读取 '%s'"
@@ -2112,9 +2115,9 @@
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr "--reverse 和 --first-parent 共用,需要指定最新的提交"
 
-#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c
-#: remote.c sequencer.c submodule.c
+#: blame.c builtin/bisect.c builtin/commit.c builtin/fast-export.c
+#: builtin/log.c builtin/merge.c builtin/pack-objects.c builtin/shortlog.c
+#: midx-write.c pack-bitmap.c remote.c sequencer.c submodule.c
 msgid "revision walk setup failed"
 msgstr "版本遍历初始化失败"
 
@@ -2353,7 +2356,7 @@
 
 #: builtin/add.c builtin/clean.c builtin/fetch.c builtin/mv.c
 #: builtin/prune-packed.c builtin/pull.c builtin/push.c builtin/remote.c
-#: builtin/rm.c builtin/send-pack.c
+#: builtin/rm.c builtin/send-pack.c builtin/sparse-checkout.c
 msgid "dry run"
 msgstr "演习"
 
@@ -2508,8 +2511,8 @@
 msgstr "'%2$s' 的错误动作 '%1$s'"
 
 #: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c builtin/revert.c diff-merges.c environment.c gpg-interface.c
-#: ls-refs.c parallel-checkout.c sequencer.c setup.c
+#: builtin/pull.c builtin/revert.c diff-merges.c diff.c environment.c
+#: gpg-interface.c ls-refs.c parallel-checkout.c sequencer.c setup.c
 #, c-format
 msgid "invalid value for '%s': '%s'"
 msgstr "'%s' 的值无效:'%s'"
@@ -2845,7 +2848,8 @@
 #: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c
 #: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c
 #: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c
-#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c
+#: builtin/repo.c builtin/submodule--helper.c builtin/tag.c
+#: builtin/verify-tag.c
 msgid "format"
 msgstr "格式"
 
@@ -2991,15 +2995,21 @@
 
 #: builtin/bisect.c
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-{new|bad}=<术语> --term-{old|good}=<术语>]    [--no-"
-"checkout] [--first-parent] [<坏> [<好>...]] [--]    [<路径规格>...]"
+"git bisect start [--term-(bad|new)=<新术语> --term-(good|old)=<旧术语>]\n"
+"                 [--no-checkout] [--first-parent] [<坏> [<好>...]] [--] [<路"
+"径规格>...]"
 
 #: builtin/bisect.c
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "git bisect (good|bad) [<版本>...]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (bad|new|<新术语>) [<版本>]"
+
+#: builtin/bisect.c
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (good|old|<旧术语>) [<版本>...]"
 
 #: builtin/bisect.c
 msgid "git bisect skip [(<rev>|<range>)...]"
@@ -3830,8 +3840,8 @@
 
 #: builtin/branch.c
 msgid ""
-"branch with --recurse-submodules can only be used if submodule."
-"propagateBranches is enabled"
+"branch with --recurse-submodules can only be used if "
+"submodule.propagateBranches is enabled"
 msgstr ""
 "带有 --recurse-submodules 的分支只能在 submodule.propagateBranches 启用时使用"
 
@@ -4380,7 +4390,7 @@
 msgid "read additional mailmap entries from file"
 msgstr "从文件中读取附加邮件映射条目"
 
-#: builtin/check-mailmap.c
+#: builtin/check-mailmap.c builtin/fast-import.c
 msgid "blob"
 msgstr "数据对象"
 
@@ -4993,12 +5003,12 @@
 msgstr ""
 "git clean [-d] [-f] [-i] [-n] [-q] [-e <模式>] [-x | -X] [--] <路径规格>..."
 
-#: builtin/clean.c
+#: builtin/clean.c builtin/sparse-checkout.c
 #, c-format
 msgid "Removing %s\n"
 msgstr "正删除 %s\n"
 
-#: builtin/clean.c
+#: builtin/clean.c builtin/sparse-checkout.c
 #, c-format
 msgid "Would remove %s\n"
 msgstr "将删除 %s\n"
@@ -5016,7 +5026,7 @@
 #: builtin/clean.c midx.c
 #, c-format
 msgid "failed to remove %s"
-msgstr "无法删除 %s"
+msgstr "无法删除 '%s'"
 
 #: builtin/clean.c
 #, c-format
@@ -5122,7 +5132,7 @@
 msgid "do not print names of files removed"
 msgstr "不打印删除文件的名称"
 
-#: builtin/clean.c
+#: builtin/clean.c builtin/sparse-checkout.c
 msgid "force"
 msgstr "强制"
 
@@ -5135,8 +5145,8 @@
 msgstr "删除整个目录"
 
 #: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c
-#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c
-#: builtin/show-ref.c ref-filter.h
+#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/show-ref.c
+#: pack-refs.c ref-filter.h
 msgid "pattern"
 msgstr "模式"
 
@@ -6952,6 +6962,16 @@
 
 #: builtin/describe.c
 #, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "无法在尚未诞生的分支上搜索数据对象 '%s'"
+
+#: builtin/describe.c
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "数据对象 '%s' 从 HEAD 不可达"
+
+#: builtin/describe.c
+#, c-format
 msgid "describe %s\n"
 msgstr "描述 %s\n"
 
@@ -7131,6 +7151,10 @@
 msgid "%s...%s: no merge base"
 msgstr "%s...%s:无合并基线"
 
+#: builtin/diff.c setup.c
+msgid "cannot come back to cwd"
+msgstr "无法返回当前工作目录"
+
 #: builtin/diff.c
 msgid "Not a git repository"
 msgstr "不是 git 仓库"
@@ -7269,8 +7293,162 @@
 msgstr "git fast-export [<rev-list 选项>]"
 
 #: builtin/fast-export.c
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
-msgstr "错误:除非指定 --mark-tags,否则无法导出嵌套标签。"
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "未知 %s 模式:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "未知 tag-of-filtered 模式:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "未知重编码模式:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not read blob %s"
+msgstr "无法读取数据对象 %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "数据对象 %s 中的对象 ID 不匹配"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "无法写入数据对象 '%s'"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "对于 %2$s、%3$s 出现非预期的比较状态 '%1$c'"
+
+#: builtin/fast-export.c
+msgid "none"
+msgstr "无"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not find author in commit %s"
+msgstr "无法在提交 %s 中找到作者"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "无法在提交 %s 中找到提交者"
+
+#: builtin/fast-export.c
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
+msgstr ""
+"在提交 %3$s 中遇到提交特定编码 %2$.*1$s;使用 --reencode=[yes|no] 来处理"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr "遇到已签名提交 %s;使用 --signed-commits=<模式> 来处理"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr "正在导出提交 %2$s 的 %1$<PRIuMAX> 个签名"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr "正在剥离提交 %s 的签名"
+
+#: builtin/fast-export.c
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+"忽略标签 %s,\n"
+"因为不支持树的标签(或树的标签的标签等)。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not read tag %s"
+msgstr "无法读取标签 %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr "遇到已签名标签 %s;使用 --signed-tags=<模式> 来处理"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "正在导出已签名标签 %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "正在从标签 %s 中剥离签名"
+
+#: builtin/fast-export.c
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr ""
+"标签 %s 指向未导出的对象;使用 --tag-of-filtered-object=<模式> 来处理它"
+
+#: builtin/fast-export.c
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr "除非指定 --mark-tags,否则无法导出嵌套标签。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "标签 %s 没有指向任何对象?"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "%s:遇到类型为 %s 的非预期对象,跳过。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr "标签指向非预期类型 %s 的对象,跳过。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "无法打开标记文件 %s 以写入。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "无法写入标记文件 %s。"
+
+#: builtin/fast-export.c builtin/fast-import.c
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "损坏的标记行:%s"
+
+#: builtin/fast-export.c builtin/fast-import.c fetch-pack.c
+#, c-format
+msgid "object not found: %s"
+msgstr "对象未找到:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "不是一个提交?不应该发生:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "object %s already has a mark"
+msgstr "对象 %s 已经有一个标记"
 
 #: builtin/fast-export.c
 msgid "--anonymize-map token cannot be empty"
@@ -7358,33 +7536,567 @@
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Missing from marks for submodule '%s'"
+msgid "can't write crash report %s"
+msgstr "无法写入崩溃报告 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "fast-import:正在转储崩溃报告到 %s\n"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "mark :%<PRIuMAX> not declared"
+msgstr "标记 :%<PRIuMAX> 未声明"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "尝试创建重复分支的无效操作:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "分支名称不符合 Git 标准:%s"
+
+#: builtin/fast-import.c
+msgid "internal consistency error creating the index"
+msgstr "创建索引时出现内部一致性错误"
+
+#: builtin/fast-import.c
+msgid "cannot create keep file"
+msgstr "无法创建 keep 文件"
+
+#: builtin/fast-import.c
+msgid "failed to write keep file"
+msgstr "无法写入 keep 文件"
+
+#: builtin/fast-import.c
+msgid "cannot store pack file"
+msgstr "无法存储包文件"
+
+#: builtin/fast-import.c
+msgid "cannot store index file"
+msgstr "无法存储索引文件"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "无法寻找到 '%s' 的开始位置"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "Git 核心拒绝索引 %s"
+
+#: builtin/fast-import.c
+msgid "cannot truncate pack to skip duplicate"
+msgstr "无法截断包以跳过重复"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "数据中 EOF(剩余 %<PRIuMAX> 字节)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "意外的压缩失败:%d"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a tree: %s"
+msgstr "不是一个树对象:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't load tree %s"
+msgstr "无法加载树 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "%s 中损坏的模式"
+
+#: builtin/fast-import.c
+msgid "root cannot be a non-directory"
+msgstr "根目录不能是非目录"
+
+#: builtin/fast-import.c
+msgid "empty path component found in input"
+msgstr "在输入中发现空路径组件"
+
+#: builtin/fast-import.c
+msgid "non-directories cannot have subtrees"
+msgstr "非目录不能有子树"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
+msgstr "丢弃 %s 因为它将指向自身(即 %s)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "分支 %s 缺少提交。"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "未更新 %s(新的分支顶端 %s 不包含 %s)"
+
+#: builtin/fast-import.c builtin/sparse-checkout.c commit-graph.c midx-write.c
+#: sequencer.c
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "不能为 %s 创建先导目录"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "无法写入标记文件 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "无法写入标记文件 %s:%s"
+
+#: builtin/fast-import.c object-file.c
+#, c-format
+msgid "unable to write file %s"
+msgstr "无法写文件 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "预期 'data n' 命令,实际:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "数据中 EOF(未找到终止符 '%s')"
+
+#: builtin/fast-import.c
+msgid "data is too large to use in this context"
+msgstr "数据太大无法在此上下文中使用"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "数据中 EOF(剩余 %lu 字节)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "身份标识字符串中缺少 <:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "身份标识字符串中 < 之前缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "身份标识字符串中缺少 >:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "身份标识字符串中 > 之后缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "身份标识中无效的原始日期 \"%s\":%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "身份标识中无效的 rfc2822 日期 \"%s\":%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "ident 中的日期必须为 'now':%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "too large fanout (%u)"
+msgstr "扇出值过大 (%u)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "failed to remove path %s"
+msgstr "无法删除路径 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "标记中 ':' 后面没有值:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "标记后面有垃圾内容:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "标记后面缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid %s: %s"
+msgstr "无效 %s:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "在 %s 中存在 NUL:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "在 %s 后面有垃圾内容:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "在 %s 后面缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "损坏的模式:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "无效的数据引用:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "SHA1 后面缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "Git 链接不能指定为 'inline':%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "不是一个提交(实际为 %s):%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "目录不能指定为 'inline':%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "%s not found: %s"
+msgstr "未找到%s:%s"
+
+#: builtin/fast-import.c
+msgid "tree"
+msgstr "树"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "不是一个 %s(实际为 %s):%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "path %s not in branch"
+msgstr "路径 %s 不在分支中"
+
+#: builtin/fast-import.c
+msgid "can't add a note on empty branch."
+msgstr "不能在空分支上添加注释。"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr "标记 :%<PRIuMAX> 不是一个提交"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "不是一个有效的提交:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "无效的引用名或 SHA1 表达式:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "不是一个数据对象(实际为 %s):%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "blob not found: %s"
+msgstr "数据对象未找到:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "提交 %s 损坏"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "无法从自身创建分支:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
+msgstr "期望的 gpgsig 格式:'gpgsig <哈希算法> <签名格式>',却得到 'gpgsig %s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "gpgsig 中未知的 git 哈希算法:'%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "gpgsig 中无效的签名格式:'%s'"
+
+#: builtin/fast-import.c
+msgid "'unknown' signature format in gpgsig"
+msgstr "gpgsig 中的 'unknown' 签名格式"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr "发现多个 %s 签名,忽略附加的签名"
+
+#: builtin/fast-import.c
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr "parse_one_signature() 返回了未知的哈希算法"
+
+#: builtin/fast-import.c
+msgid "expected committer but didn't get one"
+msgstr "预期提交者但未获取"
+
+#: builtin/fast-import.c
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr "遇到已签名提交;使用 --signed-commits=<模式> 来处理它"
+
+#: builtin/fast-import.c
+msgid "stripping a commit signature"
+msgstr "正在剥离提交签名"
+
+#: builtin/fast-import.c
+msgid "importing a commit signature verbatim"
+msgstr "逐字导入提交签名"
+
+#: builtin/fast-import.c
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr "遇到已签名标签;使用 --signed-tags=<模式> 来处理它"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr "逐字导入标签 '%s' 的签名"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr "正在剥离标签 '%s' 的签名"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "预期 'from' 命令,实际:'%s'"
+
+#: builtin/fast-import.c
+msgid "can't tag an empty branch."
+msgstr "无法标记一个空分支。"
+
+#: builtin/fast-import.c builtin/merge.c
+#, c-format
+msgid "not a valid object: %s"
+msgstr "不是一个有效对象:%s"
+
+#: builtin/fast-import.c
+msgid "write to frontend failed"
+msgstr "写入前端失败"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't read object %s"
+msgstr "无法读取对象 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "对象 %s 是一个 %s,但预期是数据对象。"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a mark: %s"
+msgstr "不是一个标记:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown mark: %s"
+msgstr "未知标记:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "SHA1 后面有垃圾内容:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "不是一个树对象:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't load object %s"
+msgstr "无法加载对象 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "标签中无效的 SHA1:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "提交中无效的 SHA1:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing from marks for submodule '%s'"
 msgstr "子模组 '%s' 缺少 from 标记"
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Missing to marks for submodule '%s'"
+msgid "missing to marks for submodule '%s'"
 msgstr "子模组 '%s' 缺少 to 标记"
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "预期 'mark' 命令,得到 %s"
+msgid "missing space after tree-ish: %s"
+msgstr "树对象后面缺少空格:%s"
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "预期 'to' 命令,得到 %s"
+msgid "not in a commit: %s"
+msgstr "不在一个提交中:%s"
 
 #: builtin/fast-import.c
-msgid "Expected format name:filename for submodule rewrite option"
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "预期 'mark' 命令,实际:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "预期 'to' 命令,实际:%s"
+
+#: builtin/fast-import.c
+msgid "only one import-marks command allowed per stream"
+msgstr "每个流只允许一个 import-marks 命令"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "未知的 --date-format 参数 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s:参数必须为非负整数"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr "--depth 不能超过 %u"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr "--cat-blob-fd 不能超过 %d"
+
+#: builtin/fast-import.c
+msgid "expected format name:filename for submodule rewrite option"
 msgstr "子模组重写选项的预期格式为 name:filename"
 
 #: builtin/fast-import.c
 #, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr "max-pack-size 现在以字节为单位,假定为 --max-pack-size=%lum"
+
+#: builtin/fast-import.c
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "最小 max-pack-size 为 1 MiB"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "未知的 --signed-commits 模式 '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "未知的 --signed-tags 模式 '%s'"
+
+#: builtin/fast-import.c
+#, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
 msgstr "不带 --allow-unsafe-features 的输入中禁止使用功能 '%s'"
 
+#: builtin/fast-import.c
+#, c-format
+msgid "got feature command '%s' after data command"
+msgstr "在 data 命令后得到 feature 命令 '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "此版本的 fast-import 不支持特性 %s。"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr "在 data 命令后得到 option 命令 '%s'"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "此版本的 fast-import 不支持选项:%s"
+
+#: builtin/fast-import.c builtin/merge-recursive.c
+#, c-format
+msgid "unknown option %s"
+msgstr "未知选项 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown option --%s"
+msgstr "未知选项 --%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unsupported command: %s"
+msgstr "不支持的命令:%s"
+
+#: builtin/fast-import.c
+msgid "stream ends early"
+msgstr "流过早结束"
+
 #: builtin/fetch-pack.c
 #, c-format
 msgid "Lockfile created but not reported: %s"
@@ -7552,6 +8264,32 @@
 "以禁用该警告,直到远程将 HEAD 更改为其他内容。"
 
 #: builtin/fetch.c
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+"您处于不区分大小写的文件系统中,而您正在尝试获取的远程仓库具有仅在\n"
+"大小写上不同的引用。使用 'files' 后端无法存储此类引用。您可以接受\n"
+"这种情况,但这意味着您无法在磁盘上存储所有远程引用。或者,您也可以\n"
+"使用以下命令将仓库迁移到使用 'reftable' 后端:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"请注意,并非所有 Git 实现都支持这种新格式。因此,如果您使用 Git\n"
+"以外的工具访问此仓库,迁移到 reftables 可能不是一个可选项。\n"
+
+#: builtin/fetch.c
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -7804,8 +8542,8 @@
 
 #: builtin/fetch.c
 msgid ""
-"--filter can only be used with the remote configured in extensions."
-"partialclone"
+"--filter can only be used with the remote configured in "
+"extensions.partialclone"
 msgstr "只可以将 --filter 用于在 extensions.partialclone 中配置的远程仓库"
 
 #: builtin/fetch.c
@@ -7846,26 +8584,6 @@
 msgstr "从文件中读取"
 
 #: builtin/for-each-ref.c
-msgid "git for-each-ref [<options>] [<pattern>]"
-msgstr "git for-each-ref [<选项>] [<模式>]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--points-at <object>]"
-msgstr "git for-each-ref [--points-at <对象>]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr "git for-each-ref [--merged [<提交>]] [--no-merged [<提交>]]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr "git for-each-ref [--contains [<提交>]] [--no-contains [<提交>]]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--start-after <marker>]"
-msgstr "git for-each-ref [--start-after <标记>]"
-
-#: builtin/for-each-ref.c
 msgid "quote placeholders suitably for shells"
 msgstr "引用占位符适用于 shells"
 
@@ -7937,6 +8655,10 @@
 msgid "cannot use --start-after with patterns"
 msgstr "不能将 --start-after 与模式匹配一同使用"
 
+#: builtin/for-each-ref.c
+msgid "git for-each-ref "
+msgstr "git for-each-ref "
+
 #: builtin/for-each-repo.c
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<配置> [--] <命令参数>"
@@ -8226,7 +8948,7 @@
 msgid "write dangling objects in .git/lost-found"
 msgstr "将悬空对象写入 .git/lost-found 中"
 
-#: builtin/fsck.c builtin/prune.c
+#: builtin/fsck.c builtin/prune.c builtin/repo.c
 msgid "show progress"
 msgstr "显示进度"
 
@@ -8528,6 +9250,10 @@
 msgstr "跳过增量重新打包任务,因为 core.multiPackIndex 被禁用"
 
 #: builtin/gc.c
+msgid "failed to perform geometric repack"
+msgstr "无法执行几何打包"
+
+#: builtin/gc.c
 #, c-format
 msgid "task '%s' failed"
 msgstr "任务 '%s' 失败"
@@ -8539,6 +9265,11 @@
 
 #: builtin/gc.c
 #, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "未知的维护策略:'%s'"
+
+#: builtin/gc.c
+#, c-format
 msgid "'%s' is not a valid task"
 msgstr "'%s' 不是一个有效的任务"
 
@@ -9627,6 +10358,34 @@
 msgid "no input file given for in-place editing"
 msgstr "没有给出要原位编辑的文件"
 
+#: builtin/last-modified.c
+msgid "last-modified can only operate on one tree at a time"
+msgstr "last-modified 一次只能在一个树对象上操作"
+
+#: builtin/last-modified.c
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "未知的 last-modified 参数:%s"
+
+#: builtin/last-modified.c
+msgid "unable to setup last-modified"
+msgstr "无法设置 last-modified"
+
+#: builtin/last-modified.c
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+"git last-modified [--recursive] [--show-trees] [<版本范围>] [[--] <路径>...]"
+
+#: builtin/last-modified.c builtin/ls-tree.c
+msgid "recurse into subtrees"
+msgstr "递归到子树"
+
+#: builtin/last-modified.c
+msgid "show tree entries when recursing into subtrees"
+msgstr "递归进入子目录时,显示树的条目"
+
 #: builtin/log.c
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
 msgstr "git log [<选项>] [<版本范围>] [[--] <路径>...]"
@@ -9675,6 +10434,22 @@
 msgstr "-L<范围>:<文件> 不能和路径表达式共用"
 
 #: builtin/log.c
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+"\n"
+"提示:您可以将 'git whatchanged <选项>' 替换为:\n"
+"提示:\tgit log <选项> --raw --no-merges\n"
+"提示:或者创建一个别名:\n"
+"提示:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+
+#: builtin/log.c
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s: 损坏的文件"
@@ -10237,10 +11012,6 @@
 msgstr "只显示树"
 
 #: builtin/ls-tree.c
-msgid "recurse into subtrees"
-msgstr "递归到子树"
-
-#: builtin/ls-tree.c
 msgid "show trees when recursing"
 msgstr "当递归时显示树"
 
@@ -10433,11 +11204,6 @@
 
 #: builtin/merge-recursive.c
 #, c-format
-msgid "unknown option %s"
-msgstr "未知选项 %s"
-
-#: builtin/merge-recursive.c
-#, c-format
 msgid "could not parse object '%s'"
 msgstr "不能解析对象 '%s'"
 
@@ -10656,11 +11422,6 @@
 msgstr "贮藏失败"
 
 #: builtin/merge.c
-#, c-format
-msgid "not a valid object: %s"
-msgstr "不是一个有效对象:%s"
-
-#: builtin/merge.c
 msgid "read-tree failed"
 msgstr "读取树失败"
 
@@ -11108,7 +11869,7 @@
 msgid "Renaming %s to %s\n"
 msgstr "重命名 %s 至 %s\n"
 
-#: builtin/mv.c builtin/remote.c
+#: builtin/mv.c
 #, c-format
 msgid "renaming '%s' failed"
 msgstr "重命名 '%s' 失败"
@@ -11660,7 +12421,7 @@
 msgid "delta base offset out of bound for %s"
 msgstr "%s 的 delta 基准偏移越界"
 
-#: builtin/pack-objects.c
+#: builtin/pack-objects.c builtin/repo.c
 msgid "Counting objects"
 msgstr "对象计数中"
 
@@ -12070,32 +12831,8 @@
 "%<PRIu32>(来自  %<PRIuMAX> 个包)"
 
 #: builtin/pack-refs.c
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <模式>] [--exclude <模"
-"式>]"
-
-#: builtin/pack-refs.c
-msgid "pack everything"
-msgstr "打包一切"
-
-#: builtin/pack-refs.c
-msgid "prune loose refs (default)"
-msgstr "清除松散的引用(默认)"
-
-#: builtin/pack-refs.c
-msgid "auto-pack refs as needed"
-msgstr "按需对引用自动打包"
-
-#: builtin/pack-refs.c
-msgid "references to include"
-msgstr "需包含的引用"
-
-#: builtin/pack-refs.c
-msgid "references to exclude"
-msgstr "需排除的引用"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
 #: builtin/patch-id.c
 msgid "git patch-id [--stable | --unstable | --verbatim]"
@@ -12426,8 +13163,8 @@
 "upstream, see 'push.autoSetupRemote' in 'git help config'.\n"
 msgstr ""
 "\n"
-"为了让没有追踪上游的分支自动配置,参见 'git help config' 中的 'push."
-"autoSetupRemote'。\n"
+"为了让没有追踪上游的分支自动配置,参见 'git help config' 中的 "
+"'push.autoSetupRemote'。\n"
 
 #: builtin/push.c
 #, c-format
@@ -12672,6 +13409,11 @@
 msgstr "git range-diff [<选项>] <base> <old-tip> <new-tip>"
 
 #: builtin/range-diff.c
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "无效的 max-memory 值:%s"
+
+#: builtin/range-diff.c
 msgid "use simple diff colors"
 msgstr "使用简单差异颜色"
 
@@ -12684,6 +13426,14 @@
 msgstr "传递给 'git log'"
 
 #: builtin/range-diff.c
+msgid "size"
+msgstr "大小"
+
+#: builtin/range-diff.c
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr "成本矩阵的最大内存(默认 4G)"
+
+#: builtin/range-diff.c
 msgid "only emit output related to the first range"
 msgstr "仅显示与第一个范围有关的输出"
 
@@ -12893,8 +13643,8 @@
 #: builtin/rebase.c
 #, c-format
 msgid ""
-"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"stop"
-"\"."
+"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
+"\"stop\"."
 msgstr "无法识别的空类型 '%s';有效值有 \"drop\"、\"keep\" 和 \"stop\"。"
 
 #: builtin/rebase.c
@@ -13340,16 +14090,12 @@
 msgstr "git reflog list"
 
 #: builtin/reflog.c
-msgid ""
-"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
-"                  [--rewrite] [--updateref] [--stale-fix]\n"
-"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
-"<refs>...]"
-msgstr ""
-"git reflog expire [--expire=<时间>] [--expire-unreachable=<时间>]\n"
-"                  [--rewrite] [--updateref] [--stale-fix]\n"
-"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | <"
-"引用>...]"
+msgid "git reflog exists <ref>"
+msgstr "git reflog exists <引用>"
+
+#: builtin/reflog.c
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr "git reflog write <引用> <旧oid> <新oid> <消息>"
 
 #: builtin/reflog.c
 msgid ""
@@ -13360,14 +14106,22 @@
 "                  [--dry-run | -n] [--verbose] <引用>@{<指定符>}..."
 
 #: builtin/reflog.c
-msgid "git reflog exists <ref>"
-msgstr "git reflog exists <引用>"
-
-#: builtin/reflog.c
 msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
 msgstr "git reflog drop [--all [--single-worktree] | <引用>...]"
 
 #: builtin/reflog.c
+msgid ""
+"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
+"<refs>...]"
+msgstr ""
+"git reflog expire [--expire=<时间>] [--expire-unreachable=<时间>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | <"
+"引用>...]"
+
+#: builtin/reflog.c
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "给 '--%2$s' 的时间戳 '%1$s' 无效"
@@ -13418,7 +14172,7 @@
 
 #: builtin/reflog.c
 msgid "limits processing to reflogs from the current worktree only"
-msgstr "仅处理当前工作树的引用日志"
+msgstr "仅处理当前工作区的引用日志"
 
 #: builtin/reflog.c
 #, c-format
@@ -13451,6 +14205,46 @@
 msgid "references specified along with --all"
 msgstr "--all 选项不能与具体引用同时使用"
 
+#: builtin/reflog.c
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "无效引用名称:%s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "无效对象 ID:%s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "旧对象 '%s' 不存在"
+
+#: builtin/reflog.c
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "无效的新对象 ID:'%s'"
+
+#: builtin/reflog.c
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "新对象 '%s' 不存在"
+
+#: builtin/reflog.c
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr "不能启动事务:%s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr "无法将引用日志更新加入队列:%s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr "无法提交引用日志更新:%s"
+
 #: builtin/refs.c
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=<格式> [--no-reflog] [--dry-run]"
@@ -13460,6 +14254,14 @@
 msgstr "git refs verify [--strict] [--verbose]"
 
 #: builtin/refs.c
+msgid "git refs exists <ref>"
+msgstr "git reflog exists <引用>"
+
+#: builtin/refs.c
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
+#: builtin/refs.c
 msgid "specify the reference format to convert to"
 msgstr "指定要转换的引用格式"
 
@@ -13488,6 +14290,22 @@
 msgid "'git refs verify' takes no arguments"
 msgstr "'git refs verify' 不接受任何参数"
 
+#: builtin/refs.c
+msgid "git refs list "
+msgstr "git reflog list"
+
+#: builtin/refs.c
+msgid "'git refs exists' requires a reference"
+msgstr "'git refs exists' 需要一个引用"
+
+#: builtin/refs.c builtin/show-ref.c
+msgid "reference does not exist"
+msgstr "引用不存在"
+
+#: builtin/refs.c builtin/show-ref.c
+msgid "failed to look up reference"
+msgstr "无法找到引用"
+
 #: builtin/remote.c
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
@@ -13683,6 +14501,22 @@
 "现在在为不存在的远程名 '%s' 命名"
 
 #: builtin/remote.c
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+"您尝试重命名的远程仓库在新目标引用规格中存在冲突的引用。这很可能\n"
+"是由于您尝试将远程仓库嵌套到自身,例如将 'parent' 重命名为 'parent/child',\n"
+"或者取消嵌套远程仓库(反向操作)。\n"
+"\n"
+"如果是这种情况,您可以先将远程仓库重命名为不同的名称来解决此问题。\n"
+
+#: builtin/remote.c
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "没有此远程仓库:'%s'"
@@ -13693,6 +14527,15 @@
 msgstr "不能重命名配置小节 '%s' 到 '%s'"
 
 #: builtin/remote.c
+msgid "Renaming remote references"
+msgstr "重命名远程引用中"
+
+#: builtin/remote.c
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr "无法将远程引用重命名操作加入队列:%s"
+
+#: builtin/remote.c
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -13704,18 +14547,9 @@
 "\t如果必要请手动更新配置。"
 
 #: builtin/remote.c
-msgid "Renaming remote references"
-msgstr "正在重命名远程引用"
-
-#: builtin/remote.c
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "删除 '%s' 失败"
-
-#: builtin/remote.c
-#, c-format
-msgid "creating '%s' failed"
-msgstr "创建 '%s' 失败"
+msgid "renaming remote refs failed: %s"
+msgstr "重命名远程引用失败:%s"
 
 #: builtin/remote.c
 msgid ""
@@ -14059,56 +14893,6 @@
 "或禁用 pack.writeBitmaps 配置。"
 
 #: builtin/repack.c
-msgid "could not start pack-objects to repack promisor objects"
-msgstr "无法开始 pack-objects 来重新打包 promisor 对象"
-
-#: builtin/repack.c
-msgid "failed to feed promisor objects to pack-objects"
-msgstr "无法将承诺者对象提供给 pack-objects"
-
-#: builtin/repack.c
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr "repack:期望来自 pack-objects 的完整十六进制对象 ID。"
-
-#: builtin/repack.c
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr "无法完成 pack-objects 来重新打包 promisor 对象"
-
-#: builtin/repack.c
-#, c-format
-msgid "cannot open index for %s"
-msgstr "不能打开 %s 的索引"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr "包 %s 太大,不在几何级数中考虑"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "包 %s 太大导致数字溢出"
-
-#: builtin/repack.c
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "无法打开临时文件 %s 进行写入"
-
-#: builtin/repack.c
-msgid "could not close refs snapshot tempfile"
-msgstr "不能关闭引用快照临时文件"
-
-#: builtin/repack.c
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "无法删除过期的位图: %s"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "包前缀 %s 没有以对象目录 %s 开始"
-
-#: builtin/repack.c
 msgid "pack everything in a single pack"
 msgstr "所有内容打包到一个包文件中"
 
@@ -14234,21 +15018,6 @@
 msgid "Nothing new to pack."
 msgstr "没有新的要打包。"
 
-#: builtin/repack.c
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "重命名包至 '%s' 失败"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "pack-objects 未为包 %2$s-%3$s 写入 '%1$s' 文件"
-
-#: builtin/repack.c sequencer.c
-#, c-format
-msgid "could not unlink: %s"
-msgstr "不能删除:%s"
-
 #: builtin/replace.c
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] <对象> <替换物>"
@@ -14562,6 +15331,80 @@
 msgid "replaying merge commits is not supported yet!"
 msgstr "目前还不支持重放到合并提交!"
 
+#: builtin/repo.c
+#, c-format
+msgid "key '%s' not found"
+msgstr "未找到键 '%s'"
+
+#: builtin/repo.c
+#, c-format
+msgid "invalid format '%s'"
+msgstr "无效格式 '%s'"
+
+#: builtin/repo.c
+msgid "output format"
+msgstr "输出格式"
+
+#: builtin/repo.c
+msgid "synonym for --format=nul"
+msgstr "和 --format=nul 同义"
+
+#: builtin/repo.c
+msgid "unsupported output format"
+msgstr "不支持的输出格式"
+
+#: builtin/repo.c
+msgid "References"
+msgstr "引用"
+
+#: builtin/repo.c
+msgid "Count"
+msgstr "计数"
+
+#: builtin/repo.c
+msgid "Branches"
+msgstr "分支"
+
+#: builtin/repo.c
+msgid "Tags"
+msgstr "标签"
+
+#: builtin/repo.c
+msgid "Remotes"
+msgstr "远程"
+
+#: builtin/repo.c
+msgid "Others"
+msgstr "其它"
+
+#: builtin/repo.c
+msgid "Reachable objects"
+msgstr "可达的对象"
+
+#: builtin/repo.c
+msgid "Commits"
+msgstr "提交"
+
+#: builtin/repo.c
+msgid "Trees"
+msgstr "树"
+
+#: builtin/repo.c
+msgid "Blobs"
+msgstr "数据对象"
+
+#: builtin/repo.c
+msgid "Repository structure"
+msgstr "仓库结构"
+
+#: builtin/repo.c
+msgid "Value"
+msgstr "值"
+
+#: builtin/repo.c
+msgid "Counting references"
+msgstr "正在引用计数"
+
 #: builtin/rerere.c
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
@@ -15294,14 +16137,6 @@
 msgstr "git show-ref --exists <引用>"
 
 #: builtin/show-ref.c
-msgid "reference does not exist"
-msgstr "引用不存在"
-
-#: builtin/show-ref.c
-msgid "failed to look up reference"
-msgstr "无法找到引用"
-
-#: builtin/show-ref.c
 msgid "only show tags (can be combined with --branches)"
 msgstr "仅显示标签(可与 --branches 组合使用)"
 
@@ -15340,10 +16175,10 @@
 #: builtin/sparse-checkout.c
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check\n"
-"-rules) [<选项>]"
+"-rules | clean) [<选项>]"
 
 #: builtin/sparse-checkout.c
 msgid "this worktree is not sparse"
@@ -15376,7 +16211,7 @@
 
 #: builtin/sparse-checkout.c
 msgid "failed to initialize worktree config"
-msgstr "无法初始化工作树配置"
+msgstr "无法初始化工作区配置"
 
 #: builtin/sparse-checkout.c
 msgid "failed to modify sparse-index config"
@@ -15390,11 +16225,6 @@
 msgid "toggle the use of a sparse index"
 msgstr "切换稀疏索引的使用"
 
-#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c
-#, c-format
-msgid "unable to create leading directories of %s"
-msgstr "不能为 %s 创建先导目录"
-
 #: builtin/sparse-checkout.c
 #, c-format
 msgid "failed to open '%s'"
@@ -15485,6 +16315,37 @@
 msgstr "必须在稀疏检出中重应用稀疏模式"
 
 #: builtin/sparse-checkout.c
+msgid "report each affected file, not just directories"
+msgstr "报告每个受影响的文件,而不仅是目录"
+
+#: builtin/sparse-checkout.c
+msgid "must be in a sparse-checkout to clean directories"
+msgstr "必须在稀疏检出中才能清理目录"
+
+#: builtin/sparse-checkout.c
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr "必须在锥形模式的稀疏检出中才能清理目录"
+
+#: builtin/sparse-checkout.c
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr "为了安全,在没有 --force 或 --dry-run 选项的情况下拒绝执行清理"
+
+#: builtin/sparse-checkout.c
+msgid "failed to read index"
+msgstr "无法读取索引"
+
+#: builtin/sparse-checkout.c
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr "无法将索引转换为稀疏索引;解决合并冲突后重试"
+
+#: builtin/sparse-checkout.c
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "无法删除 %s"
+
+#: builtin/sparse-checkout.c
 msgid "error while refreshing working directory"
 msgstr "刷新工作目录时出错"
 
@@ -17295,7 +18156,7 @@
 #: builtin/worktree.c
 #, c-format
 msgid "failed to copy worktree config from '%s' to '%s'"
-msgstr "无法把工作树配置从 '%s' 拷贝到 '%s'"
+msgstr "无法把工作区配置从 '%s' 拷贝到 '%s'"
 
 #: builtin/worktree.c
 #, c-format
@@ -17314,7 +18175,7 @@
 #: builtin/worktree.c
 #, c-format
 msgid "could not find created worktree '%s'"
-msgstr "无法找到已创建的工作树 '%s'"
+msgstr "无法找到已创建的工作区 '%s'"
 
 #: builtin/worktree.c
 #, c-format
@@ -17561,10 +18422,6 @@
 msgid "only useful for debugging"
 msgstr "只对调试有用"
 
-#: bulk-checkin.c
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "core.fsyncMethod = batch 不支持本平台"
-
 #: bundle-uri.c
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
@@ -18069,6 +18926,10 @@
 msgstr "添加或解析提交说明中的结构化信息"
 
 #: command-list.h
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr "实验性功能:显示文件最后修改的时间"
+
+#: command-list.h
 msgid "Show commit logs"
 msgstr "显示提交日志"
 
@@ -18118,7 +18979,7 @@
 
 #: command-list.h
 msgid "Perform merge without touching index or working tree"
-msgstr "在不触碰索引或工作树情况下应用合并"
+msgstr "在不触碰索引或工作区情况下应用合并"
 
 #: command-list.h
 msgid "Run merge conflict resolution tools to resolve merge conflicts"
@@ -18230,6 +19091,10 @@
 msgstr "试验中:基于一个新基线重放提交,同样适用于纯仓库"
 
 #: command-list.h
+msgid "Retrieve information about the repository"
+msgstr "检索仓库信息"
+
+#: command-list.h
 msgid "Generates a summary of pending changes"
 msgstr "生成待定更改的摘要"
 
@@ -18304,7 +19169,7 @@
 #  译者:中文字符串拼接,可删除前导空格
 #: command-list.h
 msgid "Reduce your working tree to a subset of tracked files"
-msgstr "将您的工作树缩减至已追踪文件的子集"
+msgstr "将您的工作区缩减至已追踪文件的子集"
 
 #: command-list.h
 msgid "Add file contents to the staging area"
@@ -18339,8 +19204,8 @@
 msgstr "读取、修改和删除符号引用"
 
 #: command-list.h
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr "创建、列出、删除或校验一个 GPG 签名的标签对象"
+msgid "Create, list, delete or verify tags"
+msgstr "创建、列出、删除或校验标签"
 
 #: command-list.h
 msgid "Creates a temporary file with a blob's contents"
@@ -18755,8 +19620,7 @@
 #: commit-graph.c
 #, c-format
 msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits"
-msgstr ""
-"无法合并提交图,总共已累加提交数:%<PRIuMAX>,当前待累加提交数:%<PRIuMAX>"
+msgstr "无法合并提交图,其提交数分别为 %<PRIuMAX> 和 %<PRIuMAX>"
 
 #: commit-graph.c
 #, c-format
@@ -18778,8 +19642,8 @@
 #: commit-graph.c
 #, c-format
 msgid ""
-"attempting to write a commit-graph, but 'commitGraph."
-"changedPathsVersion' (%d) is not supported"
+"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' "
+"(%d) is not supported"
 msgstr "尝试写入提交图,但不支持 'commitGraph.changedPathsVersion' (%d)"
 
 #: commit-graph.c
@@ -19202,8 +20066,8 @@
 "remote URLs cannot be configured in file directly or indirectly included by "
 "includeIf.hasconfig:remote.*.url"
 msgstr ""
-"远程 URL 不能在文件中配置,不管直接地还是通过 includeIf.hasconfig:remote.*."
-"url 间接地包含"
+"远程 URL 不能在文件中配置,不管直接地还是通过 "
+"includeIf.hasconfig:remote.*.url 间接地包含"
 
 #: config.c
 #, c-format
@@ -19382,6 +20246,48 @@
 msgstr "无法解析命令行中的配置"
 
 #: config.c
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"要使用默认的注释字符串(#)时请运行\n"
+"\n"
+"%s"
+
+#: config.c
+msgid "<comment string>"
+msgstr "<注释字符串>"
+
+#: config.c
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+"\n"
+"要设置自定义注释字符串时请运行\n"
+"\n"
+"%s\n"
+"其中 '%s' 是您希望使用的字符串。\n"
+
+#: config.c
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr "对 '%s=auto' 的支持已在 Git 3.0 中移除"
+
+#: config.c
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr "对 '%s=auto' 的支持已过时,将在 Git 3.0 中移除"
+
+#: config.c
 msgid "unknown error occurred while reading the configuration files"
 msgstr "在读取配置文件时遇到未知错误"
 
@@ -19961,6 +20867,14 @@
 msgstr "无法写入归档"
 
 #: diff-lib.c
+msgid "max-depth is not supported for worktree diffs"
+msgstr "工作区差异不支持 max-depth"
+
+#: diff-lib.c
+msgid "max-depth is not supported for index diffs"
+msgstr "索引差异不支持 max-depth"
+
+#: diff-lib.c
 msgid "--merge-base does not work with ranges"
 msgstr "--merge-base 不适用于范围"
 
@@ -20237,7 +21151,7 @@
 
 #: diff.c
 msgid "<width>[,<name-width>[,<count>]]"
-msgstr "<宽度>[,<文件名宽度>[,<次数>]]"
+msgstr "<宽度>[,<文件名宽度>[,<计数>]]"
 
 #: diff.c
 msgid "generate diffstat"
@@ -20261,7 +21175,7 @@
 
 #: diff.c
 msgid "<count>"
-msgstr "<次数>"
+msgstr "<计数>"
 
 #: diff.c
 msgid "generate diffstat with limited lines"
@@ -20586,6 +21500,14 @@
 msgstr "通过差异类型选择文件"
 
 #: diff.c
+msgid "<depth>"
+msgstr "<深度>"
+
+#: diff.c
+msgid "maximum tree depth to recurse"
+msgstr "递归的最大树深度"
+
+#: diff.c
 msgid "<file>"
 msgstr "<文件>"
 
@@ -20824,11 +21746,6 @@
 
 #: fetch-pack.c
 #, c-format
-msgid "object not found: %s"
-msgstr "对象未找到:%s"
-
-#: fetch-pack.c
-#, c-format
 msgid "error in object: %s"
 msgstr "对象中出错:%s"
 
@@ -21172,6 +22089,11 @@
 msgstr "递归的别名:%s"
 
 #: git.c
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr "检测到别名循环:'%s'的扩展未终止:%s"
+
+#: git.c
 msgid "write failure on standard output"
 msgstr "在标准输出写入失败"
 
@@ -21185,11 +22107,6 @@
 
 #: git.c
 #, c-format
-msgid "alias loop detected: expansion of '%s' does not terminate:%s"
-msgstr "检测到别名循环:'%s'的扩展未终止:%s"
-
-#: git.c
-#, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "不能作为内置命令处理 %s"
 
@@ -21251,12 +22168,22 @@
 msgstr "无法得到密钥 '%s' 的 ssh 指纹"
 
 #: gpg-interface.c
+#, c-format
+msgid "failed to get the ssh fingerprint for key %s"
+msgstr "无法得到密钥 '%s' 的 ssh 指纹"
+
+#: gpg-interface.c
 msgid ""
 "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
 msgstr "需要配置 user.signingkey 或者 gpg.ssh.defaultKeyCommand 其中之一"
 
 #: gpg-interface.c
 #, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr "构建时 gpg.ssh.defaultKeyCommand 格式错误:%s"
+
+#: gpg-interface.c
+#, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr "gpg.ssh.defaultKeyCommand 成功,但没有返回密钥:%s %s"
 
@@ -21564,6 +22491,12 @@
 "     请求:%s\n"
 "   重定向:%s"
 
+#: http.h
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr "数字太大,无法在此平台上表示为 curl_off_t:%<PRIuMAX>"
+
 #: ident.c
 msgid "Author identity unknown\n"
 msgstr "作者身份未知\n"
@@ -22092,11 +23025,6 @@
 
 #: midx-write.c
 #, c-format
-msgid "could not open index for %s"
-msgstr "不能打开 %s 的索引"
-
-#: midx-write.c
-#, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "无法将 '%s' 链接至 '%s'"
 
@@ -22125,6 +23053,11 @@
 
 #: midx-write.c
 #, c-format
+msgid "failed to open preferred pack %s"
+msgstr "无法打开首选包 %s"
+
+#: midx-write.c
+#, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr "不能选择没有对象的首选包 %s"
 
@@ -22155,6 +23088,10 @@
 msgstr "无法写入多包位图"
 
 #: midx-write.c
+msgid "too many multi-pack-indexes"
+msgstr "过多的多包索引"
+
+#: midx-write.c
 msgid "unable to open multi-pack-index chain file"
 msgstr "无法打开多包索引链文件"
 
@@ -22484,11 +23421,6 @@
 
 #: object-file.c
 #, c-format
-msgid "unable to write file %s"
-msgstr "无法写文件 %s"
-
-#: object-file.c
-#, c-format
 msgid "unable to write repeatedly vanishing file %s"
 msgstr "无法写入反复消失的文件 %s"
 
@@ -22498,6 +23430,10 @@
 msgstr "无法为 '%s' 设置权限"
 
 #: object-file.c
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = batch 不支持本平台"
+
+#: object-file.c
 msgid "error when closing loose object file"
 msgstr "关闭松散对象文件时出错"
 
@@ -23098,6 +24034,26 @@
 msgid "mtimes file %s is corrupt"
 msgstr "mtimes 文件 %s 损坏"
 
+#: pack-refs.c
+msgid "pack everything"
+msgstr "打包一切"
+
+#: pack-refs.c
+msgid "prune loose refs (default)"
+msgstr "清除松散的引用(默认)"
+
+#: pack-refs.c
+msgid "auto-pack refs as needed"
+msgstr "按需对引用自动打包"
+
+#: pack-refs.c
+msgid "references to include"
+msgstr "需包含的引用"
+
+#: pack-refs.c
+msgid "references to exclude"
+msgstr "需排除的引用"
+
 #: pack-revindex.c
 #, c-format
 msgid "reverse-index file %s is too small"
@@ -23616,6 +24572,11 @@
 
 #: promisor-remote.c
 #, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr "配置 '%2$s' 中存在不支持的字段 '%1$s'"
+
+#: promisor-remote.c
+#, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "远程 '%s' 的 URL 没有公布或为空"
 
@@ -23626,13 +24587,18 @@
 
 #: promisor-remote.c
 #, c-format
-msgid "unknown '%s' value for '%s' config option"
-msgstr "配置项 '%2$s' 为未知的取值 '%1$s'"
+msgid "invalid element '%s' from remote info"
+msgstr "远程信息中的无效元素 '%s'"
 
 #: promisor-remote.c
 #, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "远程信息中的未知元素 '%s'"
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr "服务器通告了一个没有名称或 URL 的承诺者远程:%s"
+
+#: promisor-remote.c
+#, c-format
+msgid "unknown '%s' value for '%s' config option"
+msgstr "配置项 '%2$s' 为未知的取值 '%1$s'"
 
 #: promisor-remote.c
 #, c-format
@@ -23744,6 +24710,16 @@
 
 #: range-diff.c
 #, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+"range-diff:无法计算 range-diff,因为它超出了成本矩阵的最大内存:需要 %s"
+"(%<PRIuMAX> 字节),限制为 %s(%<PRIuMAX> 字节)"
+
+#: range-diff.c
+#, c-format
 msgid "could not parse log for '%s'"
 msgstr "不能解析 '%s' 的日志"
 
@@ -24368,6 +25344,10 @@
 msgstr "没有 '%s' 的引用日志"
 
 #: refs.c
+msgid "Checking references consistency"
+msgstr "正在检查引用一致性"
+
+#: refs.c
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "%s 没有指向一个有效的对象!"
@@ -24388,8 +25368,9 @@
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -24398,18 +25379,32 @@
 "\n"
 "\tgit branch -m <name>\n"
 msgstr ""
-"使用 '%s' 作为初始分支的名称。这个默认分支名称可能会更改。要在新仓库中\n"
-"配置使用初始分支名,并消除这条警告,请执行:\n"
+"使用 '%s' 作为初始分支的名称。这个默认分支名称在 Git 3.0 中将会修改为\n"
+"\"main\"。要为您的所有新仓库配置初始分支名称(这将禁用此警告),请运行:\n"
 "\n"
 "\tgit config --global init.defaultBranch <名称>\n"
 "\n"
 "除了 'master' 之外,通常选定的名字有 'main'、'trunk' 和 'development'。\n"
-"可以通过以下命令重命名刚创建的分支:\n"
+"可以通过以下命令重命名新创建的分支:\n"
 "\n"
 "\tgit branch -m <name>\n"
 
 #: refs.c
 #, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"从 Git 3.0 开始,使用 '%s' 作为初始分支的名称。如果您期望 Git\n"
+"创建 'master',新创建的分支可以通过以下命令重命名:\n"
+"\n"
+"\tgit branch -m master\n"
+
+#: refs.c
+#, c-format
 msgid "could not retrieve `%s`"
 msgstr "无法获取 `%s`"
 
@@ -24515,12 +25510,38 @@
 msgid "migrated refs can be found at '%s'"
 msgstr "迁移的引用可以在 '%s' 处找到"
 
+#: refs/files-backend.c
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+"'core.preferSymlinkRefs=true' 已被列入移除计划。\n"
+"提示:使用符号链接表示符号引用的功能已被弃用,\n"
+"提示:并将在 Git 3.0 中移除。因此,用于启用该方式的\n"
+"提示:配置也将随之废弃。您可以用以下命令取消该配置:\n"
+"提示:\n"
+"提示:\tgit config unset core.preferSymlinkRefs\n"
+"提示:\n"
+"提示:Git 将改为使用文本 symref 格式。"
+
 #: refs/files-backend.c refs/reftable-backend.c
 #, c-format
 msgid ""
 "cannot lock ref '%s': expected symref with target '%s': but is a regular ref"
 msgstr "无法锁定引用 '%s':预期目标为 '%s' 的符号引用:但是是普通引用"
 
+#: refs/files-backend.c refs/reftable-backend.c
+#, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr "尝试为 '%s' 写入引用日志时使用了不完整的值"
+
 #: refs/files-backend.c
 #, c-format
 msgid "cannot read ref file '%s'"
@@ -24531,10 +25552,6 @@
 msgid "cannot open directory %s"
 msgstr "无法打开目录 %s"
 
-#: refs/files-backend.c
-msgid "Checking references consistency"
-msgstr "正在检查引用一致性"
-
 #: refs/packed-backend.c
 #, c-format
 msgid "unable to open '%s'"
@@ -24580,6 +25597,11 @@
 
 #: refs/reftable-backend.c
 #, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr "无法锁定引用 '%s':悬空符号引用已存在"
+
+#: refs/reftable-backend.c
+#, c-format
 msgid "cannot lock ref '%s': reference already exists"
 msgstr "无法锁定引用 '%s':引用已存在"
 
@@ -24704,10 +25726,6 @@
 msgstr "RPC 失败。%s"
 
 #: remote-curl.c
-msgid "cannot handle pushes this big"
-msgstr "不能处理这么大的推送"
-
-#: remote-curl.c
 #, c-format
 msgid "cannot deflate request; zlib deflate error %d"
 msgstr "不能压缩请求,zlib 压缩错误 %d"
@@ -24922,6 +25940,12 @@
 
 #: remote.c
 #, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr "引用规格的 <src> 部分('%s')是一个不存在的对象 ID。\n"
+
+#: remote.c
+#, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "%s 无法被解析为分支"
 
@@ -25071,6 +26095,71 @@
 msgid "cannot strip one component off url '%s'"
 msgstr "无法从 url '%s' 剥离一个组件"
 
+#: repack-geometry.c
+#, c-format
+msgid "cannot open index for %s"
+msgstr "不能打开 %s 的索引"
+
+#: repack-geometry.c
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr "包 %s 太大,不在几何打包过程中考虑"
+
+#: repack-geometry.c
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "包 %s 太大导致数字溢出"
+
+#: repack-midx.c
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "无法打开临时文件 %s 进行写入"
+
+#: repack-midx.c
+msgid "could not close refs snapshot tempfile"
+msgstr "不能关闭引用快照临时文件"
+
+#: repack-midx.c
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "无法删除过期的位图: %s"
+
+#: repack-promisor.c
+msgid "could not start pack-objects to repack promisor objects"
+msgstr "无法开始 pack-objects 来重新打包承诺者对象"
+
+#: repack-promisor.c
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "无法将承诺者对象提供给 pack-objects"
+
+#: repack-promisor.c repack.c
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr "repack:来自 pack-objects 的输入必须为完整的十六进制对象 ID 行。"
+
+#: repack-promisor.c
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr "无法完成 pack-objects 来重新打包 promisor 对象"
+
+#: repack.c
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "包前缀 %s 没有以对象目录 %s 开始"
+
+#: repack.c
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr "重命名包至 '%s' 失败"
+
+#: repack.c
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "pack-objects 未为包 %2$s-%3$s 写入 '%1$s' 文件"
+
+#: repack.c sequencer.c
+#, c-format
+msgid "could not unlink: %s"
+msgstr "不能删除:%s"
+
 #: replace-object.c
 #, c-format
 msgid "bad replace ref name: %s"
@@ -25255,7 +26344,7 @@
 
 #: scalar.c
 msgid "Scalar enlistments require a worktree"
-msgstr "Scalar 登记需要一个工作树"
+msgstr "Scalar 登记需要一个工作区"
 
 #: scalar.c
 #, c-format
@@ -26648,10 +27737,6 @@
 msgstr "不能切换目录到 '%s'"
 
 #: setup.c
-msgid "cannot come back to cwd"
-msgstr "无法返回当前工作目录"
-
-#: setup.c
 #, c-format
 msgid "failed to stat '%*s%s%s'"
 msgstr "无法获取 '%*s%s%s' 状态(stat)"
@@ -27859,7 +28944,7 @@
 #: unpack-trees.c
 #, c-format
 msgid "worktree and untracked commit have duplicate entries: %s"
-msgstr "工作树和未跟踪提交具有重复条目:%s"
+msgstr "工作区和未跟踪提交具有重复条目:%s"
 
 #: upload-pack.c
 msgid "expected flush after fetch arguments"
@@ -27917,17 +29002,32 @@
 
 #: usage.c
 #, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "'%s' 被提名以移除。\n"
+
+#: usage.c
+#, c-format
 msgid ""
-"'%s' 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"
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
 msgstr ""
-"'%s' 命令已被提名移除。\n"
-"如果您仍在使用该命令,请在命令行中添加额外选项\n"
-"'--i-still-use-this',并通过发送邮件至 <git@vger.kernel.org> \n"
-"通知我们您仍在使用它。谢谢。\n"
+"如果您仍在使用此命令,以下是您可以做的事情:\n"
+"\n"
+"- 阅读 https://git-scm.com/docs/BreakingChanges.html\n"
+"- 检查邮件列表中是否有人讨论过此问题,\n"
+"  以及他们是否提出了可以帮助您的建议:\n"
+"  https://lore.kernel.org/git/?q=%s\n"
+"- 发送电子邮件至 <git@vger.kernel.org>,让我们知道\n"
+"  您仍在使用此命令且无法确定合适的替代方案\n"
+"\n"
 
 #: usage.c
 msgid "refusing to run without --i-still-use-this"
@@ -28997,6 +30097,10 @@
 msgstr "发送要求的邮件回复"
 
 #: git-send-email.perl
+msgid "The destination IMAP folder is not properly defined."
+msgstr "目标 IMAP 文件夹没有正确定义。"
+
+#: git-send-email.perl
 msgid "The required SMTP server is not properly defined."
 msgstr "要求的 SMTP 服务器未被正确定义。"
 
diff --git a/po/zh_TW.po b/po/zh_TW.po
index 6fe5dbc..5301aff 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -30,9 +30,9 @@
 msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2025-08-16 12:10+0800\n"
-"PO-Revision-Date: 2025-08-16 12:11+0800\n"
-"Last-Translator: hms5232 <hms5232@hhming.moe>\n"
+"POT-Creation-Date: 2025-11-12 20:14+0800\n"
+"PO-Revision-Date: 2025-11-15 10:02+0000\n"
+"Last-Translator: Lumynous <lumynou5.tw@gmail.com>\n"
 "Language-Team: Chinese (Traditional Han script) <https://weblate.slat.org/"
 "projects/git-po/git-cli/zh_Hant/>\n"
 "Language: zh_TW\n"
@@ -40,9 +40,9 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Poedit 3.6\n"
-"X-ZhConverter: 繁化姬 dict-f4bc617e-r910 @ 2019/11/16 20:23:12 | https://"
-"zhconvert.org\n"
+"X-Generator: Weblate 5.13.2\n"
+"X-ZhConverter: 繁化姬 dict-f4bc617e-r910 @ 2019/11/16 20:23:12 | "
+"https://zhconvert.org\n"
 
 #: add-interactive.c
 #, c-format
@@ -660,26 +660,28 @@
 
 #: add-patch.c
 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"
+"j - go to the next undecided hunk, roll over at the bottom\n"
+"J - go to the next hunk, roll over at the bottom\n"
+"k - go to the previous undecided hunk, roll over at the top\n"
+"K - go to the previous hunk, roll over at the top\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"
-"p - print the current hunk, 'P' to use the pager\n"
+"p - print the current hunk\n"
+"P - print the current hunk using the pager\n"
 "? - print help\n"
 msgstr ""
-"j - 維持此區塊未決定狀態,檢視下一個未決定區塊\n"
-"J - 維持此區塊未決定狀態,檢視下一個區塊\n"
-"k - 維持此區塊未決定狀態,檢視上一個未決定區塊\n"
-"K - 維持此區塊未決定狀態,檢視上一個區塊\n"
+"j - 前往下一個未決區塊,在結尾時回到開頭\n"
+"J - 前往下一個區塊,在結尾時回到開頭\n"
+"k - 前往上一個未決區塊,在開頭時回到結尾\n"
+"K - 前往上一個區塊,在開頭時回到結尾\n"
 "g - 選擇要跳轉至的區塊\n"
 "/ - 尋找符合提供之常規表示式的區塊\n"
 "s - 分割目前區塊為更小的區塊\n"
 "e - 手動編輯目前區塊\n"
-"p - 輸出目前區塊,「P」分頁顯示\n"
+"p - 輸出目前區塊\n"
+"P - 分頁輸出目前區塊\n"
 "? - 顯示說明\n"
 
 #: add-patch.c
@@ -688,16 +690,16 @@
 msgstr "預期收到一個字母,卻收到「%s」"
 
 #: add-patch.c
-msgid "No previous hunk"
-msgstr "沒有上一個區塊"
+msgid "No other hunk"
+msgstr "沒有其他區塊"
 
 #: add-patch.c
-msgid "No next hunk"
-msgstr "沒有下一個區塊"
+msgid "No other undecided hunk"
+msgstr "沒有其他未決區塊"
 
 #: add-patch.c
 msgid "No other hunks to goto"
-msgstr "沒有其它可以跳轉的區塊"
+msgstr "沒有其他可以跳轉的區塊"
 
 #: add-patch.c
 msgid "go to which hunk (<ret> to see more)? "
@@ -720,7 +722,7 @@
 
 #: add-patch.c
 msgid "No other hunks to search"
-msgstr "沒有其它可以尋找的區塊"
+msgstr "沒有其他可以尋找的區塊"
 
 #: add-patch.c
 msgid "search for regex? "
@@ -939,7 +941,8 @@
 msgstr "未閉合的引號"
 
 #: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c
-#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c
+#: builtin/receive-pack.c builtin/refs.c builtin/repo.c builtin/tag.c
+#: t/helper/test-pkt-line.c
 msgid "too many arguments"
 msgstr "引數過多"
 
@@ -1251,7 +1254,7 @@
 msgid "%s has type %o, expected %o"
 msgstr "%s 的類型是 %o,預期是 %o"
 
-#: apply.c read-cache.c
+#: apply.c builtin/fast-import.c read-cache.c
 #, c-format
 msgid "invalid path '%s'"
 msgstr "路徑「%s」無效"
@@ -1626,7 +1629,7 @@
 msgid "git archive --remote <repo> [--exec <cmd>] --list"
 msgstr "git archive --remote <repo> [--exec <cmd>] --list"
 
-#: archive.c builtin/gc.c builtin/notes.c builtin/tag.c
+#: archive.c builtin/fast-import.c builtin/gc.c builtin/notes.c builtin/tag.c
 #, c-format
 msgid "cannot read '%s'"
 msgstr "無法讀取「%s」"
@@ -1983,9 +1986,9 @@
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr "--reverse 和 --first-parent 共用,需要指定最新的提交"
 
-#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c
-#: remote.c sequencer.c submodule.c
+#: blame.c builtin/bisect.c builtin/commit.c builtin/fast-export.c
+#: builtin/log.c builtin/merge.c builtin/pack-objects.c builtin/shortlog.c
+#: midx-write.c pack-bitmap.c remote.c sequencer.c submodule.c
 msgid "revision walk setup failed"
 msgstr "修訂版遍歷設定失敗"
 
@@ -2225,7 +2228,7 @@
 
 #: builtin/add.c builtin/clean.c builtin/fetch.c builtin/mv.c
 #: builtin/prune-packed.c builtin/pull.c builtin/push.c builtin/remote.c
-#: builtin/rm.c builtin/send-pack.c
+#: builtin/rm.c builtin/send-pack.c builtin/sparse-checkout.c
 msgid "dry run"
 msgstr "測試執行"
 
@@ -2313,7 +2316,7 @@
 "See \"git help submodule\" for more information."
 msgstr ""
 "您在目前的版本庫中加進另一個 Git 版本庫。\n"
-"複製外層的版本庫,將不包含嵌入版本庫的內容,\n"
+"拓製外層的版本庫,將不包含嵌入版本庫的內容,\n"
 "並且不包含取得此版本庫的方式。\n"
 "如果您要加入子模組,請使用:\n"
 "\n"
@@ -2383,8 +2386,8 @@
 msgstr "「%s」動作對「%s」無效"
 
 #: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c builtin/revert.c diff-merges.c environment.c gpg-interface.c
-#: ls-refs.c parallel-checkout.c sequencer.c setup.c
+#: builtin/pull.c builtin/revert.c diff-merges.c diff.c environment.c
+#: gpg-interface.c ls-refs.c parallel-checkout.c sequencer.c setup.c
 #, c-format
 msgid "invalid value for '%s': '%s'"
 msgstr "「%s」的值無效:「%s」"
@@ -2416,7 +2419,7 @@
 #: builtin/am.c
 #, c-format
 msgid "Failed to copy notes from '%s' to '%s'"
-msgstr "從「%s」拷貝註解到「%s」失敗"
+msgstr "從「%s」複製註解到「%s」失敗"
 
 #: builtin/am.c
 msgid "fseek failed"
@@ -2613,7 +2616,7 @@
 "already introduced the same changes; you might want to skip this patch."
 msgstr ""
 "沒有變更:是否忘記執行「git add」?\n"
-"如果沒有其他要新增到暫存區的,則很可能是其它提交\n"
+"如果沒有其他要新增到暫存區的,則很可能是其他提交\n"
 "已經引入了相同的變更。您也許想要略過這個修補檔。"
 
 #: builtin/am.c
@@ -2723,7 +2726,8 @@
 #: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c
 #: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c
 #: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c
-#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c
+#: builtin/repo.c builtin/submodule--helper.c builtin/tag.c
+#: builtin/verify-tag.c
 msgid "format"
 msgstr "format"
 
@@ -2869,15 +2873,21 @@
 
 #: builtin/bisect.c
 msgid ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 msgstr ""
-"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]    [--no-"
-"checkout] [--first-parent] [<bad> [<good>...]] [--]    [<pathspec>...]"
+"git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n"
+"                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
+"[<pathspec>...]"
 
 #: builtin/bisect.c
-msgid "git bisect (good|bad) [<rev>...]"
-msgstr "git bisect (good|bad) [<rev>...]"
+msgid "git bisect (bad|new|<term-new>) [<rev>]"
+msgstr "git bisect (bad|new|<term-new>) [<rev>]"
+
+#: builtin/bisect.c
+msgid "git bisect (good|old|<term-old>) [<rev>...]"
+msgstr "git bisect (good|old|<term-old>) [<rev>...]"
 
 #: builtin/bisect.c
 msgid "git bisect skip [(<rev>|<range>)...]"
@@ -3327,7 +3337,7 @@
 
 #: builtin/blame.c
 msgid "find line copies within and across files"
-msgstr "尋找檔案內及跨檔案拷貝的列"
+msgstr "尋找檔案內及跨檔案複製的列"
 
 #: builtin/blame.c
 msgid "find line movements within and across files"
@@ -3529,7 +3539,7 @@
 
 #: builtin/branch.c
 msgid "branch copy failed"
-msgstr "拷貝分支失敗"
+msgstr "複製分支失敗"
 
 #: builtin/branch.c
 #, c-format
@@ -3552,7 +3562,7 @@
 
 #: builtin/branch.c
 msgid "branch is copied, but update of config-file failed"
-msgstr "分支已拷貝,但組態檔案更新失敗"
+msgstr "分支已複製,但組態檔案更新失敗"
 
 #: builtin/branch.c
 #, c-format
@@ -3643,11 +3653,11 @@
 
 #: 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"
@@ -3735,7 +3745,7 @@
 
 #: 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"
@@ -3743,7 +3753,7 @@
 
 #: builtin/branch.c
 msgid "too many branches for a copy operation"
-msgstr "要進行拷貝動作的分支太多"
+msgstr "要進行複製動作的分支太多"
 
 #: builtin/branch.c
 msgid "too many arguments for a rename operation"
@@ -4265,7 +4275,7 @@
 msgid "read additional mailmap entries from file"
 msgstr "從檔案讀取額外 mailmap 項目"
 
-#: builtin/check-mailmap.c
+#: builtin/check-mailmap.c builtin/fast-import.c
 msgid "blob"
 msgstr "資料物件"
 
@@ -4494,7 +4504,7 @@
 #: builtin/checkout.c
 #, c-format
 msgid " ... and %d more.\n"
-msgstr " …… 及其它 %d 個。\n"
+msgstr " …… 及其他 %d 個。\n"
 
 #: builtin/checkout.c
 #, c-format
@@ -4868,12 +4878,12 @@
 "git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] "
 "[<pathspec>...]"
 
-#: builtin/clean.c
+#: builtin/clean.c builtin/sparse-checkout.c
 #, c-format
 msgid "Removing %s\n"
 msgstr "正在刪除 %s\n"
 
-#: builtin/clean.c
+#: builtin/clean.c builtin/sparse-checkout.c
 #, c-format
 msgid "Would remove %s\n"
 msgstr "將會刪除 %s\n"
@@ -4996,7 +5006,7 @@
 msgid "do not print names of files removed"
 msgstr "不輸出移除的檔案的名稱"
 
-#: builtin/clean.c
+#: builtin/clean.c builtin/sparse-checkout.c
 msgid "force"
 msgstr "force"
 
@@ -5009,8 +5019,8 @@
 msgstr "移除整個目錄"
 
 #: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c
-#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c
-#: builtin/show-ref.c ref-filter.h
+#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/show-ref.c
+#: pack-refs.c ref-filter.h
 msgid "pattern"
 msgstr "pattern"
 
@@ -5048,7 +5058,7 @@
 #: builtin/clone.c
 #, c-format
 msgid "'%s' is a symlink, refusing to clone with --local"
-msgstr "「%s」是符號連結,故不能使用 --local 複製"
+msgstr "「%s」是符號連結,故不能使用 --local 拓製"
 
 #: builtin/clone.c
 #, c-format
@@ -5058,7 +5068,7 @@
 #: builtin/clone.c
 #, c-format
 msgid "symlink '%s' exists, refusing to clone with --local"
-msgstr "符號連結「%s」已存在,拒絕使用 --local 複製"
+msgstr "符號連結「%s」已存在,拒絕使用 --local 拓製"
 
 #: builtin/clone.c compat/precompose_utf8.c
 #, c-format
@@ -5083,7 +5093,7 @@
 #: builtin/clone.c
 #, c-format
 msgid "failed to copy file to '%s'"
-msgstr "拷貝檔案至「%s」失敗"
+msgstr "複製檔案至「%s」失敗"
 
 #: builtin/clone.c refs/files-backend.c
 #, c-format
@@ -5101,7 +5111,7 @@
 "You can inspect what was checked out with 'git status'\n"
 "and retry with 'git restore --source=HEAD :/'\n"
 msgstr ""
-"複製成功,但是簽出失敗。\n"
+"拓製成功,但是簽出失敗。\n"
 "您可以透過「git status」檢查哪些已被簽出,然後使用指令\n"
 "「git restore --source=HEAD :/」重試\n"
 
@@ -5140,7 +5150,7 @@
 
 #: builtin/clone.c
 msgid "don't clone shallow repository"
-msgstr "不要複製淺層版本庫"
+msgstr "不要拓製淺層版本庫"
 
 #: builtin/clone.c
 msgid "don't create a checkout"
@@ -5156,11 +5166,11 @@
 
 #: builtin/clone.c
 msgid "to clone from a local repository"
-msgstr "從本機版本庫複製"
+msgstr "從本機版本庫拓製"
 
 #: builtin/clone.c
 msgid "don't use local hardlinks, always copy"
-msgstr "不使用本機硬連結,始終拷貝"
+msgstr "不使用本機硬連結,始終複製"
 
 #: builtin/clone.c
 msgid "setup as shared repository"
@@ -5172,11 +5182,11 @@
 
 #: builtin/clone.c
 msgid "initialize submodules in the clone"
-msgstr "在複製時初始化子模組"
+msgstr "在拓製時初始化子模組"
 
 #: builtin/clone.c
 msgid "number of submodules cloned in parallel"
-msgstr "平行複製的子模組數量"
+msgstr "平行拓製的子模組數量"
 
 #: builtin/clone.c builtin/init-db.c
 msgid "template-directory"
@@ -5192,7 +5202,7 @@
 
 #: 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
@@ -5210,7 +5220,7 @@
 
 #: builtin/clone.c
 msgid "clone single revision <rev> and check out"
-msgstr "複製單個修訂版 <rev> 並簽出"
+msgstr "拓製單個修訂版 <rev> 並簽出"
 
 #: builtin/clone.c
 msgid "path to git-upload-pack on the remote"
@@ -5222,11 +5232,11 @@
 
 #: builtin/clone.c
 msgid "create a shallow clone of that depth"
-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
 msgid "ref"
@@ -5234,19 +5244,19 @@
 
 #: builtin/clone.c builtin/fetch.c builtin/pull.c
 msgid "deepen history of shallow clone, excluding ref"
-msgstr "取得更多淺層複製的過往歷史記錄,除了特定修訂版"
+msgstr "取得更多淺層拓製的過往歷史記錄,除了特定修訂版"
 
 #: builtin/clone.c builtin/submodule--helper.c
 msgid "clone only one branch, HEAD or --branch"
-msgstr "只複製一個分支、HEAD 或 --branch"
+msgstr "只拓製一個分支、HEAD 或 --branch"
 
 #: builtin/clone.c
 msgid "clone tags, and make later fetches not to follow them"
-msgstr "複製標籤,並使後續抓取不要追蹤這些標籤"
+msgstr "拓製標籤,並使後續抓取不要追蹤這些標籤"
 
 #: builtin/clone.c
 msgid "any cloned submodules will be shallow"
-msgstr "子模組將以淺下載模式複製"
+msgstr "子模組將以淺下載模式拓製"
 
 #: builtin/clone.c builtin/init-db.c
 msgid "gitdir"
@@ -5280,11 +5290,11 @@
 
 #: builtin/clone.c
 msgid "apply partial clone filters to submodules"
-msgstr "將部分複製過濾器套用至子模組"
+msgstr "將部分拓製過濾器套用至子模組"
 
 #: builtin/clone.c
 msgid "any cloned submodules will use their remote-tracking branch"
-msgstr "任何複製的子模組都將使用它們的遠端追蹤分支"
+msgstr "任何拓製的子模組都將使用它們的遠端追蹤分支"
 
 #: builtin/clone.c
 msgid "initialize sparse-checkout file to include only files at root"
@@ -5308,7 +5318,7 @@
 
 #: builtin/clone.c scalar.c
 msgid "You must specify a repository to clone."
-msgstr "您必須指定要複製的版本庫。"
+msgstr "您必須指定要拓製的版本庫。"
 
 #: builtin/clone.c builtin/init-db.c builtin/refs.c builtin/submodule--helper.c
 #: setup.c
@@ -5354,12 +5364,12 @@
 #: builtin/clone.c
 #, c-format
 msgid "Cloning into bare repository '%s'...\n"
-msgstr "複製到純版本庫 '%s'...\n"
+msgstr "拓製到純版本庫 '%s'...\n"
 
 #: builtin/clone.c
 #, c-format
 msgid "Cloning into '%s'...\n"
-msgstr "正複製到 '%s'...\n"
+msgstr "正拓製到 '%s'...\n"
 
 #: builtin/clone.c
 msgid ""
@@ -5374,27 +5384,27 @@
 
 #: builtin/clone.c
 msgid "--depth is ignored in local clones; use file:// instead."
-msgstr "本機複製會忽略 --depth。請改用 file:// 通訊協定。"
+msgstr "本機拓製會忽略 --depth。請改用 file:// 通訊協定。"
 
 #: builtin/clone.c
 msgid "--shallow-since is ignored in local clones; use file:// instead."
-msgstr "本機複製會忽略 --shallow-since。請改用 file:// 協定。"
+msgstr "本機拓製會忽略 --shallow-since。請改用 file:// 協定。"
 
 #: builtin/clone.c
 msgid "--shallow-exclude is ignored in local clones; use file:// instead."
-msgstr "本機複製會忽略 --shallow-exclude。請改用 file:// 協定。"
+msgstr "本機拓製會忽略 --shallow-exclude。請改用 file:// 協定。"
 
 #: builtin/clone.c
 msgid "--filter is ignored in local clones; use file:// instead."
-msgstr "本機複製會忽略 --filter。請改用 file:// 協定。"
+msgstr "本機拓製會忽略 --filter。請改用 file:// 協定。"
 
 #: builtin/clone.c fetch-pack.c
 msgid "source repository is shallow, reject to clone."
-msgstr "來源版本庫是淺版本庫 (shallow)。拒絕複製。"
+msgstr "來源版本庫是淺版本庫 (shallow)。拒絕拓製。"
 
 #: builtin/clone.c
 msgid "source repository is shallow, ignoring --local"
-msgstr "來源版本庫是淺複製,忽略 --local"
+msgstr "來源版本庫是淺拓製,忽略 --local"
 
 #: builtin/clone.c
 msgid "--local is ignored"
@@ -5402,7 +5412,7 @@
 
 #: builtin/clone.c
 msgid "cannot clone from filtered bundle"
-msgstr "無法從過濾後的套件包複製"
+msgstr "無法從過濾後的套件包拓製"
 
 #: builtin/clone.c
 msgid "failed to initialize the repo, skipping bundle URI"
@@ -5433,7 +5443,7 @@
 
 #: builtin/clone.c
 msgid "You appear to have cloned an empty repository."
-msgstr "您複製的版本庫似乎是空的。"
+msgstr "您拓製的版本庫似乎是空的。"
 
 #: builtin/column.c
 msgid "git column [<options>]"
@@ -6516,7 +6526,7 @@
 
 #: builtin/config.c
 msgid "Other"
-msgstr "其它"
+msgstr "其他"
 
 #: builtin/config.c
 msgid "respect include directives on lookup"
@@ -6837,6 +6847,16 @@
 
 #: builtin/describe.c
 #, c-format
+msgid "cannot search for blob '%s' on an unborn branch"
+msgstr "不能在未誕生的分支上搜尋資料物件「%s」"
+
+#: builtin/describe.c
+#, c-format
+msgid "blob '%s' not reachable from HEAD"
+msgstr "從 HEAD 無法到達資料物件「%s」"
+
+#: builtin/describe.c
+#, c-format
 msgid "describe %s\n"
 msgstr "描述 %s\n"
 
@@ -6986,7 +7006,7 @@
 #: builtin/diff-pairs.c
 #, c-format
 msgid "unable to parse rename/copy score: %s"
-msgstr "無法解析重新命名/拷貝分數:%s"
+msgstr "無法解析重新命名/複製的相似度:%s"
 
 #: builtin/diff-pairs.c
 #, c-format
@@ -7016,6 +7036,10 @@
 msgid "%s...%s: no merge base"
 msgstr "%s...%s: 無合併基底"
 
+#: builtin/diff.c setup.c
+msgid "cannot come back to cwd"
+msgstr "無法返回目前工作目錄"
+
 #: builtin/diff.c
 msgid "Not a git repository"
 msgstr "不是一個 git 版本庫"
@@ -7079,7 +7103,7 @@
 #: builtin/difftool.c sequencer.c
 #, c-format
 msgid "could not copy '%s' to '%s'"
-msgstr "無法將「%s」拷貝至「%s」"
+msgstr "無法將「%s」複製至「%s」"
 
 #: builtin/difftool.c
 #, c-format
@@ -7154,8 +7178,161 @@
 msgstr "git fast-export [<rev-list-opts>]"
 
 #: builtin/fast-export.c
-msgid "Error: Cannot export nested tags unless --mark-tags is specified."
-msgstr "錯誤:除非指定 --mark-tags,否則無法匯出嵌套標籤。"
+#, c-format
+msgid "unknown %s mode: %s"
+msgstr "%s 的模式未知:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unknown tag-of-filtered mode: %s"
+msgstr "標籤之物件濾除者的模式未知:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unknown reencoding mode: %s"
+msgstr "重新編碼的模式未知:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not read blob %s"
+msgstr "無法讀取資料物件 %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "oid mismatch in blob %s"
+msgstr "資料物件 %s 中的物件 ID 不符"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not write blob '%s'"
+msgstr "無法寫入資料物件「%s」"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unexpected comparison status '%c' for %s, %s"
+msgstr "%2$s、%3$s 有非預期的比較狀態「%1$c」"
+
+#: builtin/fast-export.c
+msgid "none"
+msgstr "無"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not find author in commit %s"
+msgstr "無法從提交 %s 中找到作者"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not find committer in commit %s"
+msgstr "無法從提交 %s 中找到提交者"
+
+#: builtin/fast-export.c
+#, c-format
+msgid ""
+"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
+"no] to handle it"
+msgstr ""
+"發現提交特定的編碼 %.*s 在 %s 提交當中;使用 --reencode=[yes|no] 來處理"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
+msgstr "發現已簽署的提交 %s;使用 --signed-commits=<mode> 來處理"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "exporting %<PRIuMAX> signature(s) for commit %s"
+msgstr "匯出提交 %2$s 的 %1$<PRIuMAX> 個簽章"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "stripping signature(s) from commit %s"
+msgstr "去除提交 %s 的簽章"
+
+#: builtin/fast-export.c
+#, c-format
+msgid ""
+"omitting tag %s,\n"
+"since tags of trees (or tags of tags of trees, etc.) are not supported."
+msgstr ""
+"省略標籤 %s,\n"
+"不支援樹狀物件的標籤(或樹狀物件的標籤的標籤等)。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "could not read tag %s"
+msgstr "無法讀取標籤 %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
+msgstr "發現已簽署的標籤 %s;使用 --signed-tags=<mode> 來處理"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "exporting signed tag %s"
+msgstr "匯出已簽署的標籤 %s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "stripping signature from tag %s"
+msgstr "去除標籤 %s 的簽章"
+
+#: builtin/fast-export.c
+#, c-format
+msgid ""
+"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
+"it"
+msgstr "標籤 %s 在不支援的物件上;使用 --tag-of-filtered-object=<mode> 來處理"
+
+#: builtin/fast-export.c
+msgid "cannot export nested tags unless --mark-tags is specified."
+msgstr "除非指定 --mark-tags,否則不能匯出巢狀標籤。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "tag %s points nowhere?"
+msgstr "標籤 %s 不指向任何東西?"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "%s: unexpected object of type %s, skipping."
+msgstr "%s:非預期 %s 類型的物件,跳過。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "tag points to object of unexpected type %s, skipping."
+msgstr "標籤指向非預期類型 %s 的物件,跳過。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unable to open marks file %s for writing."
+msgstr "無法為寫入開啟標記檔案 %s。"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "unable to write marks file %s."
+msgstr "無法寫入標記檔案 %s。"
+
+#: builtin/fast-export.c builtin/fast-import.c
+#, c-format
+msgid "corrupt mark line: %s"
+msgstr "損壞的標記列:%s"
+
+#: builtin/fast-export.c builtin/fast-import.c fetch-pack.c
+#, c-format
+msgid "object not found: %s"
+msgstr "物件未找到:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "not a commit? can't happen: %s"
+msgstr "不是提交?不能發生:%s"
+
+#: builtin/fast-export.c
+#, c-format
+msgid "object %s already has a mark"
+msgstr "物件 %s 已有標記"
 
 #: builtin/fast-export.c
 msgid "--anonymize-map token cannot be empty"
@@ -7243,33 +7420,569 @@
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Missing from marks for submodule '%s'"
-msgstr "「%s」子模組缺少 from 標記"
+msgid "can't write crash report %s"
+msgstr "無法寫入 %s 當機報告"
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Missing to marks for submodule '%s'"
-msgstr "「%s」子模組缺少 to 標記"
+msgid "fast-import: dumping crash report to %s\n"
+msgstr "fast-import:傾印崩潰報告至 %s\n"
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Expected 'mark' command, got %s"
-msgstr "預期 'mark' 指令,得到 %s"
+msgid "mark :%<PRIuMAX> not declared"
+msgstr "未宣告標記 :%<PRIuMAX>"
 
 #: builtin/fast-import.c
 #, c-format
-msgid "Expected 'to' command, got %s"
-msgstr "預期 'to' 指令,得到 %s"
+msgid "invalid attempt to create duplicate branch: %s"
+msgstr "建立重複分支的嘗試無效:%s"
 
 #: builtin/fast-import.c
-msgid "Expected format name:filename for submodule rewrite option"
-msgstr "期望子模組 rewrite 選項的格式是 name:filename"
+#, c-format
+msgid "branch name doesn't conform to Git standards: %s"
+msgstr "分支名稱不符 Git 標準:%s"
+
+#: builtin/fast-import.c
+msgid "internal consistency error creating the index"
+msgstr "建立索引時發生內部一致性錯誤"
+
+#: builtin/fast-import.c
+msgid "cannot create keep file"
+msgstr "無法建立保留檔案"
+
+#: builtin/fast-import.c
+msgid "failed to write keep file"
+msgstr "無法寫入保留檔案"
+
+#: builtin/fast-import.c
+msgid "cannot store pack file"
+msgstr "無法儲存包檔案"
+
+#: builtin/fast-import.c
+msgid "cannot store index file"
+msgstr "無法儲存索引檔案"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "failed seeking to start of '%s'"
+msgstr "探尋 %s 的開頭失敗"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "core Git rejected index %s"
+msgstr "核心 Git 拒絕索引 %s"
+
+#: builtin/fast-import.c
+msgid "cannot truncate pack to skip duplicate"
+msgstr "無法截斷包來跳過重複項目"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "EOF in data (%<PRIuMAX> bytes remaining)"
+msgstr "資料中有 EOF(剩餘 %<PRIuMAX> 個位元組)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unexpected deflate failure: %d"
+msgstr "非預期的壓縮失敗:%d"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a tree: %s"
+msgstr "非樹狀物件:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't load tree %s"
+msgstr "無法載入樹狀物件 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "corrupt mode in %s"
+msgstr "%s 中有損壞的模式"
+
+#: builtin/fast-import.c
+msgid "root cannot be a non-directory"
+msgstr "根不能不是目錄"
+
+#: builtin/fast-import.c
+msgid "empty path component found in input"
+msgstr "輸入中有空的路徑部分"
+
+#: builtin/fast-import.c
+msgid "non-directories cannot have subtrees"
+msgstr "非目錄者不能有子樹"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "dropping %s since it would point to itself (i.e. to %s)"
+msgstr "捨棄 %s,因其指向自身(即指向 %s)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "branch %s is missing commits."
+msgstr "分支 %s 缺少提交。"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not updating %s (new tip %s does not contain %s)"
+msgstr "沒有更新 %s(提示:%s 不包含 %s)"
+
+#: builtin/fast-import.c builtin/sparse-checkout.c commit-graph.c midx-write.c
+#: sequencer.c
+#, c-format
+msgid "unable to create leading directories of %s"
+msgstr "不能為 %s 建立先導目錄"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unable to write marks file %s"
+msgstr "無法寫入標記檔案 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unable to write marks file %s: %s"
+msgstr "無法寫入標記檔案 %s:%s"
+
+#: builtin/fast-import.c object-file.c
+#, c-format
+msgid "unable to write file %s"
+msgstr "無法寫檔案 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'data n' command, found: %s"
+msgstr "預期「data n」命令,卻找到:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "EOF in data (terminator '%s' not found)"
+msgstr "資料中有 EOF(未找到終止子「%s」)"
+
+#: builtin/fast-import.c
+msgid "data is too large to use in this context"
+msgstr "要用於此上下文的資料太大"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "EOF in data (%lu bytes remaining)"
+msgstr "資料中有 EOF(剩餘 %lu 個位元組)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing < in ident string: %s"
+msgstr "身分字串中缺少 <:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space before < in ident string: %s"
+msgstr "身分字串的 < 前面缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing > in ident string: %s"
+msgstr "身分字串中缺少 >:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after > in ident string: %s"
+msgstr "身分字串的 > 後面缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid raw date \"%s\" in ident: %s"
+msgstr "身分中有無效的原始日期「%s」:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid rfc2822 date \"%s\" in ident: %s"
+msgstr "身分中有無效的 RFC2822 日期「%s」:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "date in ident must be 'now': %s"
+msgstr "身分中的日期必須是「now」:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "too large fanout (%u)"
+msgstr "扇出值太大(%u)"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "failed to remove path %s"
+msgstr "無法移除路徑 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "no value after ':' in mark: %s"
+msgstr "標記的「:」後沒有值:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "garbage after mark: %s"
+msgstr "標記後有垃圾:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after mark: %s"
+msgstr "標記後缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid %s: %s"
+msgstr "無效 %s:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "NUL in %s: %s"
+msgstr "%s 中有 NUL:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "garbage after %s: %s"
+msgstr "%s 後有垃圾:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after %s: %s"
+msgstr "%s 後缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "corrupt mode: %s"
+msgstr "損壞的模式:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid dataref: %s"
+msgstr "無效的資料引用:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after SHA1: %s"
+msgstr "SHA1 值後缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "Git links cannot be specified 'inline': %s"
+msgstr "Git 連結不能指定「inline」:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a commit (actually a %s): %s"
+msgstr "不是提交(而是 %s):%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "directories cannot be specified 'inline': %s"
+msgstr "目錄不能指定「inline」:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "%s not found: %s"
+msgstr "找不到 %s:%s"
+
+#: builtin/fast-import.c
+msgid "tree"
+msgstr "樹狀物件"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a %s (actually a %s): %s"
+msgstr "不是 %s(而是 %s):%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "path %s not in branch"
+msgstr "分支中沒有路徑 %s"
+
+#: builtin/fast-import.c
+msgid "can't add a note on empty branch."
+msgstr "不能在空分支上附加註記。"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "mark :%<PRIuMAX> not a commit"
+msgstr "標記 :%<PRIuMAX> 不是提交"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a valid commit: %s"
+msgstr "不是有效的提交:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid ref name or SHA1 expression: %s"
+msgstr "無效的引用名稱或 SHA1 表示式:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a blob (actually a %s): %s"
+msgstr "不是資料物件(而是 %s):%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "blob not found: %s"
+msgstr "找不到資料物件:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "the commit %s is corrupt"
+msgstr "提交 %s 損壞"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't create a branch from itself: %s"
+msgstr "不能從分支自身建立分支:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid ""
+"expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', got 'gpgsig "
+"%s'"
+msgstr ""
+"預期 gpgsig 格式:「gpgsig <hash-algo> <signature-format>」,卻收到「gpgsig "
+"%s」"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown git hash algorithm in gpgsig: '%s'"
+msgstr "gpgsig 中有未知的 Git 雜湊演算法:「%s」"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid signature format in gpgsig: '%s'"
+msgstr "gpgsig 中有無效的簽章格式:「%s」"
+
+#: builtin/fast-import.c
+msgid "'unknown' signature format in gpgsig"
+msgstr "gpgsig 中有「unknown」簽章格式"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "multiple %s signatures found, ignoring additional signature"
+msgstr "找到多個 %s 簽章,忽略多餘的簽章"
+
+#: builtin/fast-import.c
+msgid "parse_one_signature() returned unknown hash algo"
+msgstr "parse_one_signature() 回傳了未知的雜湊演算法"
+
+#: builtin/fast-import.c
+msgid "expected committer but didn't get one"
+msgstr "預期有提交者,卻沒收到"
+
+#: builtin/fast-import.c
+msgid "encountered signed commit; use --signed-commits=<mode> to handle it"
+msgstr "發現已簽署的提交;使用 --signed-commits=<mode> 來處理"
+
+#: builtin/fast-import.c
+msgid "stripping a commit signature"
+msgstr "去除提交簽章"
+
+#: builtin/fast-import.c
+msgid "importing a commit signature verbatim"
+msgstr "按原樣匯入提交簽章"
+
+#: builtin/fast-import.c
+msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
+msgstr "發現已簽署的標籤;使用 --signed-tags=<mode> 來處理"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "importing a tag signature verbatim for tag '%s'"
+msgstr "按原樣匯入標籤「%s」的簽章"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "stripping a tag signature for tag '%s'"
+msgstr "去除標籤「%s」的簽章"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'from' command, got '%s'"
+msgstr "預期「from」命令,卻收到「%s」"
+
+#: builtin/fast-import.c
+msgid "can't tag an empty branch."
+msgstr "空分支上不能有標籤。"
+
+#: builtin/fast-import.c builtin/merge.c
+#, c-format
+msgid "not a valid object: %s"
+msgstr "不是一個有效物件:%s"
+
+#: builtin/fast-import.c
+msgid "write to frontend failed"
+msgstr "寫入前端失敗"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't read object %s"
+msgstr "無法讀取物件 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "object %s is a %s but a blob was expected."
+msgstr "物件 %s 是 %s,但預期是資料物件。"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a mark: %s"
+msgstr "不是標記:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown mark: %s"
+msgstr "未知標記:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "garbage after SHA1: %s"
+msgstr "SHA1 值後有垃圾:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not a tree-ish: %s"
+msgstr "不是樹狀物件指示元:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "can't load object %s"
+msgstr "無法載入物件 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid SHA1 in tag: %s"
+msgstr "標籤中有無效的 SHA1 值:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "invalid SHA1 in commit: %s"
+msgstr "提交中有無效的 SHA1 值:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing from marks for submodule '%s'"
+msgstr "子模組「%s」缺少 from 標記"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing to marks for submodule '%s'"
+msgstr "子模組「%s」缺少 to 標記"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "missing space after tree-ish: %s"
+msgstr "樹狀物件指示元後缺少空格:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "not in a commit: %s"
+msgstr "不在提交中:%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'mark' command, got %s"
+msgstr "預期「mark」命令,卻收到 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "expected 'to' command, got %s"
+msgstr "預期「to」命令,卻收到 %s"
+
+#: builtin/fast-import.c
+msgid "only one import-marks command allowed per stream"
+msgstr "每個流僅限一個 import-marks 命令"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown --date-format argument %s"
+msgstr "未知的 --date-format 引數 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "%s: argument must be a non-negative integer"
+msgstr "%s:引數必須是非負整數"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "--depth cannot exceed %u"
+msgstr "--depth 不能超過 %u"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "--cat-blob-fd cannot exceed %d"
+msgstr "--cat-blob-fd 不能超過 %d"
+
+#: builtin/fast-import.c
+msgid "expected format name:filename for submodule rewrite option"
+msgstr "子模組 rewrite 選項預期格式 name:filename"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "max-pack-size is now in bytes, assuming --max-pack-size=%lum"
+msgstr "max-pack-size 現在的單位是位元組,假定 --max-pack-size=%lum"
+
+#: builtin/fast-import.c
+msgid "minimum max-pack-size is 1 MiB"
+msgstr "max-pack-size 的最小值是 1 MiB"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown --signed-commits mode '%s'"
+msgstr "未知的 --signed-commits 模式「%s」"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown --signed-tags mode '%s'"
+msgstr "未知的 --signed-tags 模式「%s」"
 
 #: builtin/fast-import.c
 #, c-format
 msgid "feature '%s' forbidden in input without --allow-unsafe-features"
 msgstr "沒有 --allow-unsafe-features 時,禁止在輸入中使用 '%s' 功能"
 
+#: builtin/fast-import.c
+#, c-format
+msgid "got feature command '%s' after data command"
+msgstr "在資料命令後收到功能命令「%s」"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "this version of fast-import does not support feature %s."
+msgstr "此版本的 fast-import 不支援功能 %s。"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "got option command '%s' after data command"
+msgstr "在資料命令後收到選項命令「%s」"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "this version of fast-import does not support option: %s"
+msgstr "此版本的 fast-import 不支援選項:%s"
+
+#: builtin/fast-import.c builtin/merge-recursive.c
+#, c-format
+msgid "unknown option %s"
+msgstr "未知選項 %s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unknown option --%s"
+msgstr "未知選項 --%s"
+
+#: builtin/fast-import.c
+#, c-format
+msgid "unsupported command: %s"
+msgstr "不支援的命令:%s"
+
+#: builtin/fast-import.c
+msgid "stream ends early"
+msgstr "流提早結束"
+
 #: builtin/fetch-pack.c
 #, c-format
 msgid "Lockfile created but not reported: %s"
@@ -7387,7 +8100,7 @@
 #: builtin/fetch.c
 #, c-format
 msgid "rejected %s because shallow roots are not allowed to be updated"
-msgstr "已拒絕 %s,不允許更新淺複製"
+msgstr "已拒絕 %s,不允許更新淺拓製"
 
 #: builtin/fetch.c
 msgid "[deleted]"
@@ -7438,6 +8151,32 @@
 "會停用這個警告,直到遠端將 HEAD 改為指向其他東西。"
 
 #: builtin/fetch.c
+msgid ""
+"You're on a case-insensitive filesystem, and the remote you are\n"
+"trying to fetch from has references that only differ in casing. It\n"
+"is impossible to store such references with the 'files' backend. You\n"
+"can either accept this as-is, in which case you won't be able to\n"
+"store all remote references on disk. Or you can alternatively\n"
+"migrate your repository to use the 'reftable' backend with the\n"
+"following command:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"Please keep in mind that not all implementations of Git support this\n"
+"new format yet. So if you use tools other than Git to access this\n"
+"repository it may not be an option to migrate to reftables.\n"
+msgstr ""
+"檔案系統不區分大小寫,但嘗試抓取的遠端上有引用只差在大小寫,不可能\n"
+"以「file」後端儲存這些引用。你可以按原樣接受,這表示你不能在硬碟上儲存\n"
+"所有遠端引用;抑或你可以令版本庫改為使用「reftable」後端,透過執行以下\n"
+"命令:\n"
+"\n"
+"    git refs migrate --ref-format=reftable\n"
+"\n"
+"請注意並非所有 Git 實作都支援這個新格式。因此若你還使用 Git 之外的工具\n"
+"來存取此版本庫,遷移至 reftable 可能不是個好選擇。\n"
+
+#: builtin/fetch.c
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -7585,11 +8324,11 @@
 
 #: builtin/fetch.c builtin/pull.c
 msgid "deepen history of shallow clone"
-msgstr "取得淺複製的更多過去歷史記錄"
+msgstr "取得淺拓製的更多過去歷史記錄"
 
 #: builtin/fetch.c builtin/pull.c
 msgid "deepen history of shallow repository based on time"
-msgstr "基於時間來深化淺複製的歷史"
+msgstr "根據時間深化淺層版本庫的歷史記錄"
 
 #: builtin/fetch.c builtin/pull.c
 msgid "convert to a complete repository"
@@ -7712,7 +8451,7 @@
 
 #: builtin/fmt-merge-msg.c
 msgid "populate log with at most <n> entries from shortlog"
-msgstr "向提交說明中最多複製指定條目(合併而來的提交)的簡短說明"
+msgstr "向提交說明中最多拓製指定條目(合併而來的提交)的簡短說明"
 
 #: builtin/fmt-merge-msg.c
 msgid "alias for --log (deprecated)"
@@ -7735,26 +8474,6 @@
 msgstr "從檔案中讀取"
 
 #: builtin/for-each-ref.c
-msgid "git for-each-ref [<options>] [<pattern>]"
-msgstr "git for-each-ref [<選項>] [<模式>]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--points-at <object>]"
-msgstr "git for-each-ref [--points-at <物件>]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr "git for-each-ref [--merged [<提交>]] [--no-merged [<提交>]]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr "git for-each-ref [--contains [<提交>]] [--no-contains [<提交>]]"
-
-#: builtin/for-each-ref.c
-msgid "git for-each-ref [--start-after <marker>]"
-msgstr "git for-each-ref [--start-after <marker>]"
-
-#: builtin/for-each-ref.c
 msgid "quote placeholders suitably for shells"
 msgstr "引用占位符適用於 shells"
 
@@ -7826,6 +8545,10 @@
 msgid "cannot use --start-after with patterns"
 msgstr "--start-after 無法搭配 pattern 使用"
 
+#: builtin/for-each-ref.c
+msgid "git for-each-ref "
+msgstr "git for-each-ref "
+
 #: builtin/for-each-repo.c
 msgid "git for-each-repo --config=<config> [--] <arguments>"
 msgstr "git for-each-repo --config=<config> [--] <arguments>"
@@ -8115,7 +8838,7 @@
 msgid "write dangling objects in .git/lost-found"
 msgstr "將懸空物件寫入 .git/lost-found 中"
 
-#: builtin/fsck.c builtin/prune.c
+#: builtin/fsck.c builtin/prune.c builtin/repo.c
 msgid "show progress"
 msgstr "顯示進度"
 
@@ -8321,7 +9044,7 @@
 
 #: builtin/gc.c
 msgid "repack all other packs except the largest pack"
-msgstr "除了最大的包之外,對所有其它包重新打包"
+msgstr "除了最大的包之外,對所有其他包重新打包"
 
 #: builtin/gc.c builtin/repack.c
 msgid "pack prefix to store a pack containing pruned objects"
@@ -8416,6 +9139,10 @@
 msgstr "略過增量重新打包工作,因為 core.multiPackIndex 已被停用"
 
 #: builtin/gc.c
+msgid "failed to perform geometric repack"
+msgstr "無法進行幾何重新封裝"
+
+#: builtin/gc.c
 #, c-format
 msgid "task '%s' failed"
 msgstr "作業 '%s' 失敗"
@@ -8427,6 +9154,11 @@
 
 #: builtin/gc.c
 #, c-format
+msgid "unknown maintenance strategy: '%s'"
+msgstr "未知的維護策略:「%s」"
+
+#: builtin/gc.c
+#, c-format
 msgid "'%s' is not a valid task"
 msgstr "'%s' 非有效作業"
 
@@ -9510,6 +10242,35 @@
 msgid "no input file given for in-place editing"
 msgstr "沒有給出要原位編輯的檔案"
 
+#: builtin/last-modified.c
+msgid "last-modified can only operate on one tree at a time"
+msgstr "last-modified 一次只能操作一個樹狀物件"
+
+#: builtin/last-modified.c
+#, c-format
+msgid "unknown last-modified argument: %s"
+msgstr "未知的 last-modified 引數:%s"
+
+#: builtin/last-modified.c
+msgid "unable to setup last-modified"
+msgstr "無法設定 last-modified"
+
+#: builtin/last-modified.c
+msgid ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+msgstr ""
+"git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] "
+"<path>...]"
+
+#: builtin/last-modified.c builtin/ls-tree.c
+msgid "recurse into subtrees"
+msgstr "遞迴到子樹"
+
+#: builtin/last-modified.c
+msgid "show tree entries when recursing into subtrees"
+msgstr "遞迴子樹時顯示樹狀物件項目"
+
 #: builtin/log.c
 msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
 msgstr "git log [<選項>] [<版本範圍>] [[--] <路徑>...]"
@@ -9558,6 +10319,22 @@
 msgstr "-L<範圍>:<檔案> 和 pathspec 不能同時使用"
 
 #: builtin/log.c
+msgid ""
+"\n"
+"hint: You can replace 'git whatchanged <opts>' with:\n"
+"hint:\tgit log <opts> --raw --no-merges\n"
+"hint: Or make an alias:\n"
+"hint:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+msgstr ""
+"\n"
+"提示:你可以將「git whatchanged <opts>」替換為:\n"
+"提示:\tgit log <opts> --raw --no-merges\n"
+"提示:或設定一個別名:\n"
+"提示:\tgit config set --global alias.whatchanged 'log --raw --no-merges'\n"
+"\n"
+
+#: builtin/log.c
 #, c-format
 msgid "git show %s: bad file"
 msgstr "git show %s: 損壞的檔案"
@@ -9975,7 +10752,7 @@
 
 #: builtin/ls-files.c
 msgid "show other files in the output"
-msgstr "顯示其它檔案"
+msgstr "顯示其他檔案"
 
 #: builtin/ls-files.c
 msgid "show ignored files in the output"
@@ -10119,10 +10896,6 @@
 msgstr "只顯示樹"
 
 #: builtin/ls-tree.c
-msgid "recurse into subtrees"
-msgstr "遞迴到子樹"
-
-#: builtin/ls-tree.c
 msgid "show trees when recursing"
 msgstr "當遞迴時顯示樹"
 
@@ -10169,7 +10942,7 @@
 
 #: builtin/mailinfo.c
 msgid "copy Message-ID to the end of commit message"
-msgstr "拷貝 Message-ID 至提交說明末尾"
+msgstr "複製 Message-ID 至提交說明末尾"
 
 #: builtin/mailinfo.c
 msgid "re-code metadata to i18n.commitEncoding"
@@ -10314,11 +11087,6 @@
 
 #: builtin/merge-recursive.c
 #, c-format
-msgid "unknown option %s"
-msgstr "未知選項 %s"
-
-#: builtin/merge-recursive.c
-#, c-format
 msgid "could not parse object '%s'"
 msgstr "無法解析物件「%s」"
 
@@ -10536,11 +11304,6 @@
 msgstr "貯存失敗"
 
 #: builtin/merge.c
-#, c-format
-msgid "not a valid object: %s"
-msgstr "不是一個有效物件:%s"
-
-#: builtin/merge.c
 msgid "read-tree failed"
 msgstr "讀取樹失敗"
 
@@ -10989,7 +11752,7 @@
 msgid "Renaming %s to %s\n"
 msgstr "重新命名 %s 至 %s\n"
 
-#: builtin/mv.c builtin/remote.c
+#: builtin/mv.c
 #, c-format
 msgid "renaming '%s' failed"
 msgstr "重新命名 '%s' 失敗"
@@ -11192,7 +11955,7 @@
 #: builtin/notes.c
 #, c-format
 msgid "failed to copy notes from '%s' to '%s'"
-msgstr "將註解從「%s」拷貝至「%s」失敗"
+msgstr "將註解從「%s」複製至「%s」失敗"
 
 #. TRANSLATORS: the first %s will be replaced by a git
 #. notes command: 'add', 'merge', 'remove', etc.
@@ -11281,12 +12044,12 @@
 msgid ""
 "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
 "existing notes"
-msgstr "無法拷貝註解。物件 %s 已有註解。使用「-f」覆寫現有的註解"
+msgstr "無法複製註解。物件 %s 已有註解。使用「-f」覆寫現有的註解"
 
 #: builtin/notes.c
 #, c-format
 msgid "missing notes on source object %s. Cannot copy."
-msgstr "來源物件 %s 缺少註解。無法拷貝。"
+msgstr "來源物件 %s 缺少註解。無法複製。"
 
 #: builtin/notes.c
 #, c-format
@@ -11541,7 +12304,7 @@
 msgid "delta base offset out of bound for %s"
 msgstr "%s 的 delta 基準位移越界"
 
-#: builtin/pack-objects.c
+#: builtin/pack-objects.c builtin/repo.c
 msgid "Counting objects"
 msgstr "正在計算物件數量"
 
@@ -11838,7 +12601,7 @@
 
 #: builtin/pack-objects.c
 msgid "create packs suitable for shallow fetches"
-msgstr "建立適合淺複製版本庫取得的包"
+msgstr "建立適合淺拓製版本庫取得的包"
 
 #: builtin/pack-objects.c
 msgid "ignore packs that have companion .keep file"
@@ -11854,7 +12617,7 @@
 
 #: builtin/pack-objects.c
 msgid "do not hide commits by grafts"
-msgstr "顯示被移植隱藏的提交"
+msgstr "不要因嫁接隱藏提交"
 
 #: builtin/pack-objects.c
 msgid "use a bitmap index if available to speed up counting objects"
@@ -11950,32 +12713,8 @@
 "%<PRIu32> (總共 %<PRIuMAX>)"
 
 #: builtin/pack-refs.c
-msgid ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-msgstr ""
-"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
-"<pattern>]"
-
-#: builtin/pack-refs.c
-msgid "pack everything"
-msgstr "打包一切"
-
-#: builtin/pack-refs.c
-msgid "prune loose refs (default)"
-msgstr "剪除鬆散引用(預設值)"
-
-#: builtin/pack-refs.c
-msgid "auto-pack refs as needed"
-msgstr "按需自動封裝引用"
-
-#: builtin/pack-refs.c
-msgid "references to include"
-msgstr "要包含的引用"
-
-#: builtin/pack-refs.c
-msgid "references to exclude"
-msgstr "要排除的引用"
+msgid "git pack-refs "
+msgstr "git pack-refs "
 
 #: builtin/patch-id.c
 msgid "git patch-id [--stable | --unstable | --verbatim]"
@@ -12554,6 +13293,11 @@
 msgstr "git range-diff [<選項>] <base> <old-tip> <new-tip>"
 
 #: builtin/range-diff.c
+#, c-format
+msgid "invalid max-memory value: %s"
+msgstr "無效的 max-memory 值:%s"
+
+#: builtin/range-diff.c
 msgid "use simple diff colors"
 msgstr "使用簡單差異顏色"
 
@@ -12566,6 +13310,14 @@
 msgstr "傳遞給 'git log'"
 
 #: builtin/range-diff.c
+msgid "size"
+msgstr "大小"
+
+#: builtin/range-diff.c
+msgid "maximum memory for cost matrix (default 4G)"
+msgstr "成本矩陣的最大記憶體(預設值 4G)"
+
+#: builtin/range-diff.c
 msgid "only emit output related to the first range"
 msgstr "只發出跟第一個範圍相關的輸出"
 
@@ -13223,34 +13975,38 @@
 msgstr "git reflog list"
 
 #: builtin/reflog.c
-msgid ""
-"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
-"                  [--rewrite] [--updateref] [--stale-fix]\n"
-"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
-"<refs>...]"
-msgstr ""
-"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
-"                  [--rewrite] [--updateref] [--stale-fix]\n"
-"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
-"<refs>...]"
-
-#: builtin/reflog.c
-msgid ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-msgstr ""
-"git reflog delete [--rewrite] [--updateref]\n"
-"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
-
-#: builtin/reflog.c
 msgid "git reflog exists <ref>"
 msgstr "git reflog exists <引用>"
 
 #: builtin/reflog.c
+msgid "git reflog write <ref> <old-oid> <new-oid> <message>"
+msgstr "git reflog write <ref> <old-oid> <new-oid> <message>"
+
+#: builtin/reflog.c
+msgid ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+msgstr ""
+"git reflog delete [--rewrite] [--updateref]\n"
+"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}..."
+
+#: builtin/reflog.c
 msgid "git reflog drop [--all [--single-worktree] | <refs>...]"
 msgstr "git reflog drop [--all [--single-worktree] | <refs>...]"
 
 #: builtin/reflog.c
+msgid ""
+"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
+"<refs>...]"
+msgstr ""
+"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
+"                  [--rewrite] [--updateref] [--stale-fix]\n"
+"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | "
+"<refs>...]"
+
+#: builtin/reflog.c
 #, c-format
 msgid "invalid timestamp '%s' given to '--%s'"
 msgstr "傳入「--%s」的時間戳「%s」無效"
@@ -13334,6 +14090,46 @@
 msgid "references specified along with --all"
 msgstr "同時指定參照和 --all 引數"
 
+#: builtin/reflog.c
+#, c-format
+msgid "invalid reference name: %s"
+msgstr "無效的引用名稱:%s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "invalid old object ID: '%s'"
+msgstr "無效的舊物件 ID:「%s」"
+
+#: builtin/reflog.c
+#, c-format
+msgid "old object '%s' does not exist"
+msgstr "舊物件「%s」不存在"
+
+#: builtin/reflog.c
+#, c-format
+msgid "invalid new object ID: '%s'"
+msgstr "無效的新物件 ID:「%s」"
+
+#: builtin/reflog.c
+#, c-format
+msgid "new object '%s' does not exist"
+msgstr "新物件「%s」不存在"
+
+#: builtin/reflog.c
+#, c-format
+msgid "cannot start transaction: %s"
+msgstr "無法開始事務:%s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "cannot queue reflog update: %s"
+msgstr "無法排入引用日誌更新:%s"
+
+#: builtin/reflog.c
+#, c-format
+msgid "cannot commit reflog update: %s"
+msgstr "無法提交引用日誌更新:%s"
+
 #: builtin/refs.c
 msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
 msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]"
@@ -13343,6 +14139,14 @@
 msgstr "git refs verify [--strict] [--verbose]"
 
 #: builtin/refs.c
+msgid "git refs exists <ref>"
+msgstr "git refs exists <ref>"
+
+#: builtin/refs.c
+msgid "git refs optimize "
+msgstr "git refs optimize "
+
+#: builtin/refs.c
 msgid "specify the reference format to convert to"
 msgstr "指定要轉換成的引用格式"
 
@@ -13371,6 +14175,22 @@
 msgid "'git refs verify' takes no arguments"
 msgstr "「git refs verify」不接受引數"
 
+#: builtin/refs.c
+msgid "git refs list "
+msgstr "git refs list "
+
+#: builtin/refs.c
+msgid "'git refs exists' requires a reference"
+msgstr "「git refs exists」需要指定引用"
+
+#: builtin/refs.c builtin/show-ref.c
+msgid "reference does not exist"
+msgstr "引用不存在"
+
+#: builtin/refs.c builtin/show-ref.c
+msgid "failed to look up reference"
+msgstr "無法查詢引用"
+
 #: builtin/remote.c
 msgid ""
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--"
@@ -13568,6 +14388,22 @@
 "現命名成不存在的遠端分支 '%s'"
 
 #: builtin/remote.c
+msgid ""
+"The remote you are trying to rename has conflicting references in the\n"
+"new target refspec. This is most likely caused by you trying to nest\n"
+"a remote into itself, e.g. by renaming 'parent' into 'parent/child'\n"
+"or by unnesting a remote, e.g. the other way round.\n"
+"\n"
+"If that is the case, you can address this by first renaming the\n"
+"remote to a different name.\n"
+msgstr ""
+"你嘗試重新命名的遠端在新的目標引用規格中有衝突的引用。這很可能是因為你\n"
+"嘗試令遠端與自身形成巢狀,例如將「parent」重新命名為「parent/child」,\n"
+"或是反向操作令其不再是巢狀。\n"
+"\n"
+"若是這種情況,你可以先將遠端改為不同的名稱來解決這個問題。\n"
+
+#: builtin/remote.c
 #, c-format
 msgid "No such remote: '%s'"
 msgstr "沒有此遠端版本庫:'%s'"
@@ -13578,6 +14414,15 @@
 msgstr "無法將組態的「%s」區段重新命名為「%s」"
 
 #: builtin/remote.c
+msgid "Renaming remote references"
+msgstr "正在重新命名遠端引用"
+
+#: builtin/remote.c
+#, c-format
+msgid "queueing remote ref renames failed: %s"
+msgstr "無法排入遠端引用的重新命名作業:%s"
+
+#: builtin/remote.c
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -13589,18 +14434,9 @@
 "\t如果必要請手動更新設定。"
 
 #: builtin/remote.c
-msgid "Renaming remote references"
-msgstr "正在重新命名遠端引用"
-
-#: builtin/remote.c
 #, c-format
-msgid "deleting '%s' failed"
-msgstr "刪除 '%s' 失敗"
-
-#: builtin/remote.c
-#, c-format
-msgid "creating '%s' failed"
-msgstr "建立 '%s' 失敗"
+msgid "renaming remote refs failed: %s"
+msgstr "無法重新命名遠端引用:%s"
 
 #: builtin/remote.c
 msgid ""
@@ -13941,56 +14777,6 @@
 "或停用 pack.writeBitmaps 設定。"
 
 #: builtin/repack.c
-msgid "could not start pack-objects to repack promisor objects"
-msgstr "無法開始 pack-objects 來重新打包 promisor 物件"
-
-#: builtin/repack.c
-msgid "failed to feed promisor objects to pack-objects"
-msgstr "無法將承諾者物件喂給 pack-objects"
-
-#: builtin/repack.c
-msgid "repack: Expecting full hex object ID lines only from pack-objects."
-msgstr "repack:期望來自 pack-objects 的完整十六進位物件 ID。"
-
-#: builtin/repack.c
-msgid "could not finish pack-objects to repack promisor objects"
-msgstr "無法結束 pack-objects 來重新打包 promisor 物件"
-
-#: builtin/repack.c
-#, c-format
-msgid "cannot open index for %s"
-msgstr "無法開啟 %s 的索引"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack %s too large to consider in geometric progression"
-msgstr "%s 包太大,以致不能在等比數列中考慮"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack %s too large to roll up"
-msgstr "%s 包太大,以致不能縮合"
-
-#: builtin/repack.c
-#, c-format
-msgid "could not open tempfile %s for writing"
-msgstr "無法開啟暫存檔 %s 進行寫入"
-
-#: builtin/repack.c
-msgid "could not close refs snapshot tempfile"
-msgstr "無法關閉 refs 的快照暫存檔"
-
-#: builtin/repack.c
-#, c-format
-msgid "could not remove stale bitmap: %s"
-msgstr "無法移除過時位圖:%s"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "封包前綴 %s 不以 objdir %s 開頭"
-
-#: builtin/repack.c
 msgid "pack everything in a single pack"
 msgstr "所有內容打包到一個包檔案中"
 
@@ -14116,21 +14902,6 @@
 msgid "Nothing new to pack."
 msgstr "沒有新的要打包。"
 
-#: builtin/repack.c
-#, c-format
-msgid "renaming pack to '%s' failed"
-msgstr "無法將包重新命名為「%s」"
-
-#: builtin/repack.c
-#, c-format
-msgid "pack-objects did not write a '%s' file for pack %s-%s"
-msgstr "pack-objects 沒有為 %2$s-%3$s 套件包寫入「%1$s」檔案"
-
-#: builtin/repack.c sequencer.c
-#, c-format
-msgid "could not unlink: %s"
-msgstr "無法刪除:%s"
-
 #: builtin/replace.c
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] <物件> <取代物>"
@@ -14264,7 +15035,7 @@
 msgid ""
 "original commit '%s' contains mergetag '%s' that is discarded; use --edit "
 "instead of --graft"
-msgstr "原始提交 '%s' 包含已經捨棄的合併標籤 '%s',使用 --edit 代替 --graft"
+msgstr "原始提交「%s」包含已經捨棄的合併標籤「%s」,使用 --edit 代替 --graft"
 
 #: builtin/replace.c
 #, c-format
@@ -14283,7 +15054,7 @@
 #: builtin/replace.c
 #, c-format
 msgid "graft for '%s' unnecessary"
-msgstr "對 '%s' 移植沒有必要"
+msgstr "沒有必要嫁接「%s」"
 
 #: builtin/replace.c
 #, c-format
@@ -14296,7 +15067,7 @@
 "could not convert the following graft(s):\n"
 "%s"
 msgstr ""
-"無法轉換下列移植:\n"
+"無法轉換下列嫁接:\n"
 "%s"
 
 #: builtin/replace.c
@@ -14317,7 +15088,7 @@
 
 #: builtin/replace.c
 msgid "convert existing graft file"
-msgstr "轉換現存的移植檔案"
+msgstr "轉換現有的嫁接檔案"
 
 #: builtin/replace.c
 msgid "replace the ref if it exists"
@@ -14361,7 +15132,7 @@
 
 #: builtin/replace.c
 msgid "--convert-graft-file takes no argument"
-msgstr "--convert-graft-file 不帶參數"
+msgstr "--convert-graft-file 不需要引數"
 
 #: builtin/replace.c
 msgid "only one pattern can be given with -l"
@@ -14443,6 +15214,80 @@
 msgid "replaying merge commits is not supported yet!"
 msgstr "尚不支援重放合併提交!"
 
+#: builtin/repo.c
+#, c-format
+msgid "key '%s' not found"
+msgstr "找不到「%s」鍵"
+
+#: builtin/repo.c
+#, c-format
+msgid "invalid format '%s'"
+msgstr "「%s」格式無效"
+
+#: builtin/repo.c
+msgid "output format"
+msgstr "輸出格式"
+
+#: builtin/repo.c
+msgid "synonym for --format=nul"
+msgstr "和 --format=nul 同義"
+
+#: builtin/repo.c
+msgid "unsupported output format"
+msgstr "不支援的輸出格式"
+
+#: builtin/repo.c
+msgid "References"
+msgstr "引用"
+
+#: builtin/repo.c
+msgid "Count"
+msgstr "總數"
+
+#: builtin/repo.c
+msgid "Branches"
+msgstr "分支"
+
+#: builtin/repo.c
+msgid "Tags"
+msgstr "標籤"
+
+#: builtin/repo.c
+msgid "Remotes"
+msgstr "遠端"
+
+#: builtin/repo.c
+msgid "Others"
+msgstr "其他"
+
+#: builtin/repo.c
+msgid "Reachable objects"
+msgstr "可到達物件"
+
+#: builtin/repo.c
+msgid "Commits"
+msgstr "提交"
+
+#: builtin/repo.c
+msgid "Trees"
+msgstr "樹狀物件"
+
+#: builtin/repo.c
+msgid "Blobs"
+msgstr "資料物件"
+
+#: builtin/repo.c
+msgid "Repository structure"
+msgstr "版本庫結構"
+
+#: builtin/repo.c
+msgid "Value"
+msgstr "值"
+
+#: builtin/repo.c
+msgid "Counting references"
+msgstr "正在計算引用數量"
+
 #: builtin/rerere.c
 msgid ""
 "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
@@ -15173,14 +16018,6 @@
 msgstr "git show-ref --exists <ref>"
 
 #: builtin/show-ref.c
-msgid "reference does not exist"
-msgstr "引用不存在"
-
-#: builtin/show-ref.c
-msgid "failed to look up reference"
-msgstr "無法查詢引用"
-
-#: builtin/show-ref.c
 msgid "only show tags (can be combined with --branches)"
 msgstr "只顯示標籤(可以和 --branches 共用)"
 
@@ -15219,10 +16056,10 @@
 #: builtin/sparse-checkout.c
 msgid ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 msgstr ""
 "git sparse-checkout (init | list | set | add | reapply | disable | check-"
-"rules) [<options>]"
+"rules | clean) [<options>]"
 
 #: builtin/sparse-checkout.c
 msgid "this worktree is not sparse"
@@ -15269,11 +16106,6 @@
 msgid "toggle the use of a sparse index"
 msgstr "切換是否使用稀疏索引"
 
-#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c
-#, c-format
-msgid "unable to create leading directories of %s"
-msgstr "不能為 %s 建立先導目錄"
-
 #: builtin/sparse-checkout.c
 #, c-format
 msgid "failed to open '%s'"
@@ -15365,6 +16197,37 @@
 msgstr "必須在稀疏提交才能重新套用稀疏樣式 (sparsity pattern)"
 
 #: builtin/sparse-checkout.c
+msgid "report each affected file, not just directories"
+msgstr "不只回報目錄,還回報每個受影響的檔案"
+
+#: builtin/sparse-checkout.c
+msgid "must be in a sparse-checkout to clean directories"
+msgstr "必須處於稀疏提交,才能清理目錄"
+
+#: builtin/sparse-checkout.c
+msgid "must be in a cone-mode sparse-checkout to clean directories"
+msgstr "必須處於 cone 模式的稀疏提交,才能清理目錄"
+
+#: builtin/sparse-checkout.c
+msgid "for safety, refusing to clean without one of --force or --dry-run"
+msgstr "為避免意外發生,只允許在傳入 --force 或 --dry-run 時清理"
+
+#: builtin/sparse-checkout.c
+msgid "failed to read index"
+msgstr "無法讀取索引"
+
+#: builtin/sparse-checkout.c
+msgid ""
+"failed to convert index to a sparse index; resolve merge conflicts and try "
+"again"
+msgstr "無法將索引轉換成稀疏索引,請解決合併衝突後重試"
+
+#: builtin/sparse-checkout.c
+#, c-format
+msgid "failed to remove '%s'"
+msgstr "無法移除「%s」"
+
+#: builtin/sparse-checkout.c
 msgid "error while refreshing working directory"
 msgstr "重新整理工作目錄時發生錯誤"
 
@@ -15999,9 +16862,9 @@
 "'--reference-if-able' instead of '--reference'."
 msgstr ""
 "從上級專案的備用版本庫計算得出的備用版本庫無效。\n"
-"這種情況下,請設定 submodule.alternateErrorStrategy 為 'info'\n"
-"以允許 Git 不用備用版本庫複製,亦可使用等效的 '--reference-if-able'\n"
-"而非 '--reference' 複製。"
+"這種情況下,請設定 submodule.alternateErrorStrategy 為「info」\n"
+"以允許 Git 不用備用版本庫拓製,亦可使用等效的「--reference-if-able」\n"
+"而非「--reference」拓製。"
 
 #: builtin/submodule--helper.c
 #, c-format
@@ -16036,7 +16899,7 @@
 #: builtin/submodule--helper.c
 #, c-format
 msgid "clone of '%s' into submodule path '%s' failed"
-msgstr "無法複製 '%s' 到子模組路徑 '%s'"
+msgstr "無法拓製「%s」到子模組路徑「%s」"
 
 #: builtin/submodule--helper.c
 #, c-format
@@ -16049,7 +16912,7 @@
 
 #: builtin/submodule--helper.c
 msgid "where the new submodule will be cloned to"
-msgstr "新的子模組將要複製的路徑"
+msgstr "新的子模組將要拓製的路徑"
 
 #: builtin/submodule--helper.c
 msgid "name of the new submodule"
@@ -16057,19 +16920,19 @@
 
 #: builtin/submodule--helper.c
 msgid "url where to clone the submodule from"
-msgstr "複製子模組的 url 位址"
+msgstr "拓製子模組的 url 位址"
 
 #: builtin/submodule--helper.c
 msgid "depth for shallow clones"
-msgstr "淺複製的深度"
+msgstr "淺拓製的深度"
 
 #: builtin/submodule--helper.c
 msgid "force cloning progress"
-msgstr "強制顯示複製進度"
+msgstr "強制顯示拓製進度"
 
 #: builtin/submodule--helper.c
 msgid "disallow cloning into non-empty directory"
-msgstr "不允許複製至非空白目錄"
+msgstr "不允許拓製至非空白目錄"
 
 #: builtin/submodule--helper.c
 msgid ""
@@ -16108,17 +16971,17 @@
 #: builtin/submodule--helper.c
 #, c-format
 msgid "cannot clone submodule '%s' without a URL"
-msgstr "無法在沒有網址的情況下複製「%s」子模組"
+msgstr "無法在沒有網址的情況下拓製「%s」子模組"
 
 #: builtin/submodule--helper.c
 #, c-format
 msgid "Failed to clone '%s'. Retry scheduled"
-msgstr "複製 '%s' 失敗。已排程重試作業"
+msgstr "拓製「%s」失敗。已排程重試作業"
 
 #: builtin/submodule--helper.c
 #, c-format
 msgid "Failed to clone '%s' a second time, aborting"
-msgstr "第二次嘗試複製 '%s' 失敗,中止作業"
+msgstr "第二次嘗試拓製「%s」失敗,中止作業"
 
 #: builtin/submodule--helper.c
 #, c-format
@@ -16243,7 +17106,7 @@
 
 #: builtin/submodule--helper.c
 msgid "create a shallow clone truncated to the specified number of revisions"
-msgstr "建立一個縮減至指定版本數的淺複製"
+msgstr "建立一個縮減至指定版本數的淺拓製"
 
 #: builtin/submodule--helper.c
 msgid "parallel jobs"
@@ -16251,15 +17114,15 @@
 
 #: builtin/submodule--helper.c
 msgid "whether the initial clone should follow the shallow recommendation"
-msgstr "初始複製是否應該遵循建議的淺複製選項"
+msgstr "初始拓製是否應該遵循建議的淺拓製選項"
 
 #: builtin/submodule--helper.c
 msgid "don't print cloning progress"
-msgstr "不要輸出複製進度"
+msgstr "不要輸出拓製進度"
 
 #: builtin/submodule--helper.c
 msgid "disallow cloning into non-empty directory, implies --init"
-msgstr "不允許複製進非空白目錄,隱含 --init"
+msgstr "不允許拓製進非空白目錄,隱含 --init"
 
 #: builtin/submodule--helper.c
 msgid ""
@@ -16359,10 +17222,10 @@
 "or you are unsure what this means choose another name with the '--name' "
 "option."
 msgstr ""
-"如果您想要直接使用這個本機 git 目錄,而非重新複製自\n"
+"如果您想要直接使用這個本機 git 目錄,而非重新拓製自\n"
 "  %s\n"
-"請使用 '--force' 選項。如果本機 git 目錄不是正確的版本庫\n"
-"假如您不太懂意思,請使用 '--name' 選項輸入其他名稱。"
+"請使用「--force」選項。如果本機 git 目錄不是正確的版本庫,\n"
+"或者是您不太懂意思,請使用「--name」選項輸入其他名稱。"
 
 #: builtin/submodule--helper.c
 #, c-format
@@ -17169,12 +18032,12 @@
 #: builtin/worktree.c
 #, c-format
 msgid "failed to copy '%s' to '%s'; sparse-checkout may not work correctly"
-msgstr "將「%s」拷貝至「%s」失敗;稀疏簽出可能無法正常運作"
+msgstr "將「%s」複製至「%s」失敗;稀疏簽出可能無法正常運作"
 
 #: builtin/worktree.c
 #, c-format
 msgid "failed to copy worktree config from '%s' to '%s'"
-msgstr "將工作區組態從「%s」拷貝至「%s」失敗"
+msgstr "將工作區組態從「%s」複製至「%s」失敗"
 
 #: builtin/worktree.c
 #, c-format
@@ -17236,7 +18099,7 @@
 
 #: builtin/worktree.c
 msgid "checkout <branch> even if already checked out in other worktree"
-msgstr "簽出 <分支>,即使已經被簽出到其它工作區"
+msgstr "簽出 <分支>,即使已經被簽出到其他工作區"
 
 #: builtin/worktree.c
 msgid "create a new branch"
@@ -17440,10 +18303,6 @@
 msgid "only useful for debugging"
 msgstr "只對除錯有用"
 
-#: bulk-checkin.c
-msgid "core.fsyncMethod = batch is unsupported on this platform"
-msgstr "core.fsyncMethod = batch 不支援本平台"
-
 #: bundle-uri.c
 #, c-format
 msgid "could not parse bundle list key %s with value '%s'"
@@ -17570,7 +18429,7 @@
 
 #: bundle.c
 msgid "unable to dup bundle descriptor"
-msgstr "無法複製套件包描述元"
+msgstr "無法拓製套件包描述元"
 
 #: bundle.c
 msgid "Could not spawn pack-objects"
@@ -17611,7 +18470,7 @@
 #: cache-tree.c
 #, c-format
 msgid "directory '%s' is present in index, but not sparse"
-msgstr "「%s」目錄已經在索引裡面,但不在稀疏簽出當中。"
+msgstr "「%s」目錄已經在索引裡面,但不在稀疏簽出當中"
 
 #: cache-tree.c unpack-trees.c
 msgid "corrupted cache-tree has entries not present in index"
@@ -17691,7 +18550,7 @@
 
 #: command-list.h
 msgid "Download missing objects in a partial clone"
-msgstr "在部分複製中下載缺少的物件"
+msgstr "在部分拓製中下載缺少的物件"
 
 #: command-list.h
 msgid "Use binary search to find the commit that introduced a bug"
@@ -17739,7 +18598,7 @@
 
 #: command-list.h
 msgid "Copy files from the index to the working tree"
-msgstr "從索引區拷貝檔案至工作區"
+msgstr "從索引區複製檔案至工作區"
 
 #: command-list.h
 msgid "Find commits yet to be applied to upstream"
@@ -17759,7 +18618,7 @@
 
 #: command-list.h
 msgid "Clone a repository into a new directory"
-msgstr "複製版本庫至新目錄"
+msgstr "拓製版本庫至新目錄"
 
 #: command-list.h
 msgid "Display data in columns"
@@ -17946,6 +18805,10 @@
 msgstr "新增或解析提交說明中的結構化訊息"
 
 #: command-list.h
+msgid "EXPERIMENTAL: Show when files were last modified"
+msgstr "實驗性功能:顯示檔案最後修改的時間"
+
+#: command-list.h
 msgid "Show commit logs"
 msgstr "顯示提交日誌"
 
@@ -18107,6 +18970,10 @@
 msgstr "實驗性功能:在新的基底重放提交,亦支援裸版本庫"
 
 #: command-list.h
+msgid "Retrieve information about the repository"
+msgstr "取得儲存庫的資訊"
+
+#: command-list.h
 msgid "Generates a summary of pending changes"
 msgstr "生成待定更改的摘要"
 
@@ -18216,8 +19083,8 @@
 msgstr "讀取、修改和刪除符號引用"
 
 #: command-list.h
-msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr "建立、列出、刪除或驗證一個 GPG 簽名的標籤物件"
+msgid "Create, list, delete or verify tags"
+msgstr "建立、列出、刪除或驗證標籤"
 
 #: command-list.h
 msgid "Creates a temporary file with a blob's contents"
@@ -18746,13 +19613,13 @@
 "Turn this message off by running\n"
 "\"git config set advice.graftFileDeprecated false\""
 msgstr ""
-"對 <GIT_DIR>/info/grafts 的支援已棄用,並將在\n"
-"未來的 Git 版本中被移除。\n"
+"<GIT_DIR>/info/grafts 已棄用,\n"
+"並將在未來的 Git 版本中移除。\n"
 "\n"
-"請使用「git replace --convert-graft-file」將\n"
-"grafts 轉換為取代引用。\n"
+"請使用「git replace --convert-graft-file」來\n"
+"將嫁接轉換為取代引用。\n"
 "\n"
-"設定「git config set advice.graftFileDeprecated false」\n"
+"執行「git config set advice.graftFileDeprecated false」\n"
 "可以關閉此訊息"
 
 #: commit.c
@@ -18914,7 +19781,7 @@
 #: compat/mingw.c
 #, c-format
 msgid "failed to copy SID (%ld)"
-msgstr "拷貝 SID 失敗(%ld)"
+msgstr "複製 SID 失敗(%ld)"
 
 #: compat/mingw.c
 #, c-format
@@ -19256,6 +20123,48 @@
 msgstr "無法解析命令列中的設定"
 
 #: config.c
+#, c-format
+msgid ""
+"\n"
+"To use the default comment string (#) please run\n"
+"\n"
+"%s"
+msgstr ""
+"\n"
+"如果要使用預設的備註字串 (#),請執行\n"
+"\n"
+"%s"
+
+#: config.c
+msgid "<comment string>"
+msgstr "<comment string>"
+
+#: config.c
+#, c-format
+msgid ""
+"\n"
+"To set a custom comment string please run\n"
+"\n"
+"%s\n"
+"where '%s' is the string you wish to use.\n"
+msgstr ""
+"\n"
+"如果要設定自訂的備註字串,請執行\n"
+"\n"
+"%s\n"
+"其中「%s」是您想使用的字串。\n"
+
+#: config.c
+#, c-format
+msgid "Support for '%s=auto' has been removed in Git 3.0"
+msgstr "「%s=auto」的支援,已經在 Git 3.0 中移除"
+
+#: config.c
+#, c-format
+msgid "Support for '%s=auto' is deprecated and will be removed in Git 3.0"
+msgstr "「%s=auto」已經棄用,將在 Git 3.0 中移除"
+
+#: config.c
 msgid "unknown error occurred while reading the configuration files"
 msgstr "在讀取設定檔案時遇到未知錯誤"
 
@@ -19395,11 +20304,11 @@
 #: connect.c
 #, c-format
 msgid "protocol error: expected shallow sha-1, got '%s'"
-msgstr "協定錯誤:預期淺複製 sha-1,卻得到 '%s'"
+msgstr "協定錯誤:預期淺拓製 sha-1,卻得到 '%s'"
 
 #: connect.c
 msgid "repository on the other end cannot be shallow"
-msgstr "另一端的版本庫不能是淺複製版本庫"
+msgstr "另一端的版本庫不能是淺拓製版本庫"
 
 #: connect.c
 msgid "invalid packet"
@@ -19813,7 +20722,7 @@
 
 #: diagnose.c
 msgid "could not duplicate stdout"
-msgstr "無法複製 stdout"
+msgstr "無法再製 stdout"
 
 #: diagnose.c
 #, c-format
@@ -19825,6 +20734,14 @@
 msgstr "無法寫入封存"
 
 #: diff-lib.c
+msgid "max-depth is not supported for worktree diffs"
+msgstr "不支援在工作區差異比較中使用 max-depth 選項"
+
+#: diff-lib.c
+msgid "max-depth is not supported for index diffs"
+msgstr "不支援在索引差異比較中使用 max-depth 選項"
+
+#: diff-lib.c
 msgid "--merge-base does not work with ranges"
 msgstr "--merge-base 跟範圍無法搭配運作"
 
@@ -19897,7 +20814,7 @@
 msgid ""
 "color-moved-ws: allow-indentation-change cannot be combined with other "
 "whitespace modes"
-msgstr "color-moved-ws:allow-indentation-change 不能與其它空白字元模式共用"
+msgstr "color-moved-ws:allow-indentation-change 不能與其他空白字元模式共用"
 
 #: diff.c
 #, c-format
@@ -20231,11 +21148,11 @@
 
 #: diff.c
 msgid "detect copies"
-msgstr "檢測拷貝"
+msgstr "檢測複製"
 
 #: diff.c
 msgid "use unmodified files as source to find copies"
-msgstr "使用未修改的檔案作為尋找拷貝的來源"
+msgstr "使用未修改的檔案作為尋找複製的來源"
 
 #: diff.c
 msgid "disable rename detection"
@@ -20253,7 +21170,7 @@
 msgid ""
 "prevent rename/copy detection if the number of rename/copy targets exceeds "
 "given limit"
-msgstr "如果重新命名/拷貝的目標數量超出提供的限度,則防止檢測重新命名/拷貝"
+msgstr "如果重新命名/複製的目標數量超出提供的限度,則防止檢測重新命名/複製"
 
 #: diff.c
 msgid "Diff algorithm options"
@@ -20337,7 +21254,7 @@
 
 #: diff.c
 msgid "Other diff options"
-msgstr "其它差異選項"
+msgstr "其他差異選項"
 
 #: diff.c
 msgid "when run from subdir, exclude changes outside and show relative paths"
@@ -20450,6 +21367,14 @@
 msgstr "透過差異類型選擇檔案"
 
 #: diff.c
+msgid "<depth>"
+msgstr "<depth>"
+
+#: diff.c
+msgid "maximum tree depth to recurse"
+msgstr "樹狀物件的遞迴最大深度"
+
+#: diff.c
 msgid "<file>"
 msgstr "<檔案>"
 
@@ -20660,7 +21585,7 @@
 
 #: fetch-pack.c
 msgid "git fetch-pack: expected a flush packet after shallow list"
-msgstr "git fetch-pack:在淺複製列表之後期望一個 flush 包"
+msgstr "git fetch-pack:在淺拓製列表之後期望一個 flush 包"
 
 #: fetch-pack.c
 msgid "git fetch-pack: expected ACK/NAK, got a flush packet"
@@ -20691,11 +21616,6 @@
 
 #: fetch-pack.c
 #, c-format
-msgid "object not found: %s"
-msgstr "物件未找到:%s"
-
-#: fetch-pack.c
-#, c-format
 msgid "error in object: %s"
 msgstr "物件中發生錯誤:%s"
 
@@ -20863,7 +21783,7 @@
 #: fetch-pack.c
 #, c-format
 msgid "error processing shallow info: %d"
-msgstr "處理淺複製訊息發生錯誤:%d"
+msgstr "處理淺拓製訊息發生錯誤:%d"
 
 #: fetch-pack.c
 #, c-format
@@ -21040,6 +21960,11 @@
 msgstr "遞迴的別名:%s"
 
 #: git.c
+#, c-format
+msgid "alias loop detected: expansion of '%s' does not terminate:%s"
+msgstr "偵測到別名循環:展開後的「%s」無窮無盡:%s"
+
+#: git.c
 msgid "write failure on standard output"
 msgstr "在標準輸出寫入失敗"
 
@@ -21053,11 +21978,6 @@
 
 #: git.c
 #, c-format
-msgid "alias loop detected: expansion of '%s' does not terminate:%s"
-msgstr "偵測到別名循環:展開後的「%s」無窮無盡:%s"
-
-#: git.c
-#, c-format
 msgid "cannot handle %s as a builtin"
 msgstr "不能作為內建指令處理 %s"
 
@@ -21119,12 +22039,22 @@
 msgstr "無法取得「%s」金鑰的 SSH 指紋"
 
 #: gpg-interface.c
+#, c-format
+msgid "failed to get the ssh fingerprint for key %s"
+msgstr "無法取得 %s 金鑰的 SSH 指紋"
+
+#: gpg-interface.c
 msgid ""
 "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
 msgstr "需要設定 user.signingkey 或 gpg.ssh.defaultKeyCommand 任一"
 
 #: gpg-interface.c
 #, c-format
+msgid "malformed build-time gpg.ssh.defaultKeyCommand: %s"
+msgstr "編譯期的 gpg.ssh.defaultKeyCommand 格式有誤:%s"
+
+#: gpg-interface.c
+#, c-format
 msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
 msgstr "gpg.ssh.defaultKeyCommand 執行成功,但沒回傳按鍵:%s %s"
 
@@ -21224,7 +22154,7 @@
 
 #: help.c
 msgid "Interacting with Others"
-msgstr "與其它系統互動"
+msgstr "與其他系統互動"
 
 #: help.c
 msgid "Low-level Commands / Manipulators"
@@ -21426,6 +22356,12 @@
 "     請求:%s\n"
 "   重定向:%s"
 
+#: http.h
+#, c-format
+msgid ""
+"number too large to represent as curl_off_t on this platform: %<PRIuMAX>"
+msgstr "數字過大,無法表示為這個平台上的 curl_off_t:%<PRIuMAX>"
+
 #: ident.c
 msgid "Author identity unknown\n"
 msgstr "作者身分未知\n"
@@ -21550,7 +22486,7 @@
 
 #: list-objects-filter-options.c
 msgid "unable to upgrade repository format to support partial clone"
-msgstr "無法升級版本庫格式,以支援部分複製"
+msgstr "無法升級版本庫格式,以支援部分拓製"
 
 #: list-objects-filter-options.h
 msgid "args"
@@ -21907,7 +22843,7 @@
 "      git add %s\n"
 "\n"
 "   來記錄上述的合併或更新\n"
-" - 解決上級專案中的其它衝突\n"
+" - 解決上級專案中的其他衝突\n"
 " - 在上級專案中,提交產生之索引資訊\n"
 
 #. TRANSLATORS: The %s arguments are: 1) tree hash of a merge
@@ -21957,11 +22893,6 @@
 
 #: midx-write.c
 #, c-format
-msgid "could not open index for %s"
-msgstr "無法開啟 %s 的索引"
-
-#: midx-write.c
-#, c-format
 msgid "unable to link '%s' to '%s'"
 msgstr "無法將「%s」link 至「%s」"
 
@@ -21990,6 +22921,11 @@
 
 #: midx-write.c
 #, c-format
+msgid "failed to open preferred pack %s"
+msgstr "無法開啟偏好的包 %s"
+
+#: midx-write.c
+#, c-format
 msgid "cannot select preferred pack %s with no objects"
 msgstr "無法選取偏好,沒有物件的 %s 包"
 
@@ -22020,6 +22956,10 @@
 msgstr "無法寫入多包位圖"
 
 #: midx-write.c
+msgid "too many multi-pack-indexes"
+msgstr "太多多包索引"
+
+#: midx-write.c
 msgid "unable to open multi-pack-index chain file"
 msgstr "無法開啟多封裝索引鏈檔案"
 
@@ -22349,11 +23289,6 @@
 
 #: object-file.c
 #, c-format
-msgid "unable to write file %s"
-msgstr "無法寫檔案 %s"
-
-#: object-file.c
-#, c-format
 msgid "unable to write repeatedly vanishing file %s"
 msgstr "無法寫入重複消失的檔案 %s"
 
@@ -22363,6 +23298,10 @@
 msgstr "無法為 '%s' 設定權限"
 
 #: object-file.c
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = batch 不支援本平台"
+
+#: object-file.c
 msgid "error when closing loose object file"
 msgstr "關閉鬆散物件檔案時發生錯誤"
 
@@ -22716,22 +23655,22 @@
 #: odb.c
 #, c-format
 msgid "reference repository '%s' as a linked checkout is not supported yet."
-msgstr "尚不支援將引用版本庫 '%s' 作為一個連結簽出。"
+msgstr "尚不支援將引用版本庫「%s」作為一個連結簽出。"
 
 #: odb.c
 #, c-format
 msgid "reference repository '%s' is not a local repository."
-msgstr "引用版本庫 '%s' 不是一個本機版本庫。"
+msgstr "引用版本庫「%s」不是一個本機版本庫。"
 
 #: odb.c
 #, c-format
 msgid "reference repository '%s' is shallow"
-msgstr "引用版本庫 '%s' 是一個淺複製"
+msgstr "引用版本庫「%s」是淺拓製的"
 
 #: odb.c
 #, c-format
 msgid "reference repository '%s' is grafted"
-msgstr "引用版本庫 '%s' 已被移植"
+msgstr "引用版本庫「%s」經過嫁接"
 
 #: odb.c
 #, c-format
@@ -22964,6 +23903,26 @@
 msgid "mtimes file %s is corrupt"
 msgstr "mtimes 檔案 %s 損壞"
 
+#: pack-refs.c
+msgid "pack everything"
+msgstr "打包一切"
+
+#: pack-refs.c
+msgid "prune loose refs (default)"
+msgstr "剪除鬆散引用(預設值)"
+
+#: pack-refs.c
+msgid "auto-pack refs as needed"
+msgstr "按需自動封裝引用"
+
+#: pack-refs.c
+msgid "references to include"
+msgstr "要包含的引用"
+
+#: pack-refs.c
+msgid "references to exclude"
+msgstr "要排除的引用"
+
 #: pack-revindex.c
 #, c-format
 msgid "reverse-index file %s is too small"
@@ -23329,7 +24288,7 @@
 msgid ""
 "global 'literal' pathspec setting is incompatible with all other global "
 "pathspec settings"
-msgstr "全域的 'literal' 路徑規格設定和其它的全域路徑規格設定不相容"
+msgstr "全域的 'literal' 路徑規格設定和其他的全域路徑規格設定不相容"
 
 #: pathspec.c
 msgid "invalid parameter for pathspec magic 'prefix'"
@@ -23482,6 +24441,11 @@
 
 #: promisor-remote.c
 #, c-format
+msgid "unsupported field '%s' in '%s' config"
+msgstr "不支援「%2$s」組態中的「%1$s」欄位"
+
+#: promisor-remote.c
+#, c-format
 msgid "no or empty URL advertised for remote '%s'"
 msgstr "遠端「%s」未公佈 URL 或 URL 空白"
 
@@ -23492,13 +24456,18 @@
 
 #: promisor-remote.c
 #, c-format
-msgid "unknown '%s' value for '%s' config option"
-msgstr "「%2$s」組態選項的值「%1$s」未知"
+msgid "invalid element '%s' from remote info"
+msgstr "遠端資訊的元素「%s」無效"
 
 #: promisor-remote.c
 #, c-format
-msgid "unknown element '%s' from remote info"
-msgstr "遠端資訊的元素「%s」未知"
+msgid "server advertised a promisor remote without a name or URL: %s"
+msgstr "伺服器公告了一個沒有名稱或 URL 的承諾者遠端:%s"
+
+#: promisor-remote.c
+#, c-format
+msgid "unknown '%s' value for '%s' config option"
+msgstr "「%2$s」組態選項的值「%1$s」未知"
 
 #: promisor-remote.c
 #, c-format
@@ -23610,6 +24579,16 @@
 
 #: range-diff.c
 #, c-format
+msgid ""
+"range-diff: unable to compute the range-diff, since it exceeds the maximum "
+"memory for the cost matrix: %s (%<PRIuMAX> bytes) needed, limited to %s "
+"(%<PRIuMAX> bytes)"
+msgstr ""
+"range-diff:無法計算範圍差異,因為它超過了成本矩陣的最大記憶體限制:%s(需要 "
+"%<PRIuMAX> 位元組),限制為 %s(%<PRIuMAX> 位元組)"
+
+#: range-diff.c
+#, c-format
 msgid "could not parse log for '%s'"
 msgstr "無法解析「%s」的日誌"
 
@@ -24233,6 +25212,10 @@
 msgstr "沒有 '%s' 的引用日誌"
 
 #: refs.c
+msgid "Checking references consistency"
+msgstr "正在檢查引用一致性"
+
+#: refs.c
 #, c-format
 msgid "%s does not point to a valid object!"
 msgstr "%s 沒有指向一個有效的物件!"
@@ -24253,8 +25236,9 @@
 #, 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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -24263,9 +25247,9 @@
 "\n"
 "\tgit branch -m <name>\n"
 msgstr ""
-"將「%s」設定為初始分支的名稱。這個預設分支名稱可以變更。\n"
-"如果要設定所有新版本庫要使用的初始分支名稱,\n"
-"請呼叫(會隱藏這個警告):\n"
+"將「%s」設定為初始分支的名稱。這個預設分支名稱會在 Git 3.0\n"
+"中改成「main」。如果要設定所有新版本庫要使用的初始分支\n"
+"名稱,請呼叫(會隱藏這個警告):\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -24276,6 +25260,21 @@
 
 #: refs.c
 #, c-format
+msgid ""
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+msgstr ""
+"由於 Git 3.0 的緣故,使用「%s」作為初始分支的名稱。\n"
+"如果您預期 Git 建立「master」分支,可以透過以下命令\n"
+"重新命名新建立的分支:\n"
+"\n"
+"\tgit branch -m master\n"
+
+#: refs.c
+#, c-format
 msgid "could not retrieve `%s`"
 msgstr "無法擷取「%s」"
 
@@ -24381,12 +25380,38 @@
 msgid "migrated refs can be found at '%s'"
 msgstr "可以在「%s」找到已遷移的引用"
 
+#: refs/files-backend.c
+msgid ""
+"'core.preferSymlinkRefs=true' is nominated for removal.\n"
+"hint: The use of symbolic links for symbolic refs is deprecated\n"
+"hint: and will be removed in Git 3.0. The configuration that\n"
+"hint: tells Git to use them is thus going away. You can unset\n"
+"hint: it with:\n"
+"hint:\n"
+"hint:\tgit config unset core.preferSymlinkRefs\n"
+"hint:\n"
+"hint: Git will then use the textual symref format instead."
+msgstr ""
+"「core.preferSymlinkRefs=true」已被提名移除。\n"
+"提示:使用符號連結表示符號引用的做法已被棄用\n"
+"提示:並將在 Git 3.0 中移除。令 Git 使用符號連結的組態\n"
+"提示:也將隨之消失。您可以透過以下命令取消該組態:\n"
+"提示:\n"
+"提示:\tgit config unset core.preferSymlinkRefs\n"
+"提示:\n"
+"提示:Git 將改為使用文字符號引用格式。"
+
 #: refs/files-backend.c refs/reftable-backend.c
 #, c-format
 msgid ""
 "cannot lock ref '%s': expected symref with target '%s': but is a regular ref"
 msgstr "無法鎖定引用「%s」:預期是指向「%s」的符號引用,但這個是一般引用"
 
+#: refs/files-backend.c refs/reftable-backend.c
+#, c-format
+msgid "trying to write reflog for '%s' with incomplete values"
+msgstr "嘗試將不完整的數值寫入「%s」的引用日誌"
+
 #: refs/files-backend.c
 #, c-format
 msgid "cannot read ref file '%s'"
@@ -24397,10 +25422,6 @@
 msgid "cannot open directory %s"
 msgstr "無法開啟 %s 目錄"
 
-#: refs/files-backend.c
-msgid "Checking references consistency"
-msgstr "正在檢查引用一致性"
-
 #: refs/packed-backend.c
 #, c-format
 msgid "unable to open '%s'"
@@ -24446,6 +25467,11 @@
 
 #: refs/reftable-backend.c
 #, c-format
+msgid "cannot lock ref '%s': dangling symref already exists"
+msgstr "無法鎖定引用「%s」:已經存在懸空符號引用"
+
+#: refs/reftable-backend.c
+#, c-format
 msgid "cannot lock ref '%s': reference already exists"
 msgstr "無法鎖定引用「%s」:引用已經存在"
 
@@ -24482,7 +25508,7 @@
 #: refs/reftable-backend.c
 #, c-format
 msgid "refname %s is a symbolic ref, copying it is not supported"
-msgstr "引用名稱 %s 是象徵式引用,不支援拷貝"
+msgstr "引用名稱 %s 是符號引用,不支援複製"
 
 #: refspec.c
 #, c-format
@@ -24570,10 +25596,6 @@
 msgstr "RPC 失敗。%s"
 
 #: remote-curl.c
-msgid "cannot handle pushes this big"
-msgstr "不能處理這麼大的推送"
-
-#: remote-curl.c
 #, c-format
 msgid "cannot deflate request; zlib deflate error %d"
 msgstr "不能壓縮請求,zlib 壓縮錯誤 %d"
@@ -24792,6 +25814,12 @@
 
 #: remote.c
 #, c-format
+msgid ""
+"The <src> part of the refspec ('%s') is an object ID that doesn't exist.\n"
+msgstr "引用規格(「%s」)的 <src> 部分是個不存在的物件 ID。\n"
+
+#: remote.c
+#, c-format
 msgid "%s cannot be resolved to branch"
 msgstr "%s 無法被解析為分支"
 
@@ -24936,6 +25964,71 @@
 msgid "cannot strip one component off url '%s'"
 msgstr "無法從 url '%s' 剝離一個元件"
 
+#: repack-geometry.c
+#, c-format
+msgid "cannot open index for %s"
+msgstr "無法開啟 %s 的索引"
+
+#: repack-geometry.c
+#, c-format
+msgid "pack %s too large to consider in geometric progression"
+msgstr "%s 包太大,以致不能在等比數列中考慮"
+
+#: repack-geometry.c
+#, c-format
+msgid "pack %s too large to roll up"
+msgstr "%s 包太大,以致不能縮合"
+
+#: repack-midx.c
+#, c-format
+msgid "could not open tempfile %s for writing"
+msgstr "無法開啟暫存檔 %s 進行寫入"
+
+#: repack-midx.c
+msgid "could not close refs snapshot tempfile"
+msgstr "無法關閉 refs 的快照暫存檔"
+
+#: repack-midx.c
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "無法移除過時位圖:%s"
+
+#: repack-promisor.c
+msgid "could not start pack-objects to repack promisor objects"
+msgstr "無法開始 pack-objects 來重新打包 promisor 物件"
+
+#: repack-promisor.c
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "無法將承諾者物件提供給 pack-objects"
+
+#: repack-promisor.c repack.c
+msgid "repack: Expecting full hex object ID lines only from pack-objects."
+msgstr "repack:期望來自 pack-objects 的完整十六進位物件 ID。"
+
+#: repack-promisor.c
+msgid "could not finish pack-objects to repack promisor objects"
+msgstr "無法結束 pack-objects 來重新打包 promisor 物件"
+
+#: repack.c
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "封包前綴 %s 不以 objdir %s 開頭"
+
+#: repack.c
+#, c-format
+msgid "renaming pack to '%s' failed"
+msgstr "無法將包重新命名為「%s」"
+
+#: repack.c
+#, c-format
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "pack-objects 沒有為 %2$s-%3$s 套件包寫入「%1$s」檔案"
+
+#: repack.c sequencer.c
+#, c-format
+msgid "could not unlink: %s"
+msgstr "無法刪除:%s"
+
 #: replace-object.c
 #, c-format
 msgid "bad replace ref name: %s"
@@ -25182,11 +26275,11 @@
 
 #: scalar.c
 msgid "branch to checkout after clone"
-msgstr "複製後要簽出的分支"
+msgstr "拓製後要簽出的分支"
 
 #: scalar.c
 msgid "when cloning, create full working directory"
-msgstr "複製時建立完整的工作目錄"
+msgstr "拓製時建立完整的工作目錄"
 
 #: scalar.c
 msgid "only download metadata for the branch that will be checked out"
@@ -25198,7 +26291,7 @@
 
 #: scalar.c
 msgid "specify if tags should be fetched during clone"
-msgstr "指定是否要在複製階段抓取標籤"
+msgstr "指定是否要在拓製階段抓取標籤"
 
 #: scalar.c
 msgid "specify if background maintenance should be enabled"
@@ -25244,11 +26337,11 @@
 
 #: scalar.c
 msgid "partial clone failed; attempting full clone"
-msgstr "部分複製失敗。嘗試完整複製"
+msgstr "部分拓製失敗。嘗試完整拓製"
 
 #: scalar.c
 msgid "could not configure for full clone"
-msgstr "無法設定完整複製"
+msgstr "無法設定完整拓製"
 
 #: scalar.c
 msgid "scalar diagnose [<enlistment>]"
@@ -26518,10 +27611,6 @@
 msgstr "不能切換目錄到 '%s'"
 
 #: setup.c
-msgid "cannot come back to cwd"
-msgstr "無法返回目前工作目錄"
-
-#: setup.c
 #, c-format
 msgid "failed to stat '%*s%s%s'"
 msgstr "取得 '%*s%s%s' 狀態(stat)失敗"
@@ -26612,7 +27701,7 @@
 #: setup.c
 #, c-format
 msgid "cannot copy '%s' to '%s'"
-msgstr "無法將「%s」拷貝至「%s」"
+msgstr "無法將「%s」複製至「%s」"
 
 #: setup.c
 #, c-format
@@ -26627,7 +27716,7 @@
 #: setup.c
 #, c-format
 msgid "not copying templates from '%s': %s"
-msgstr "未從「%s」拷貝範本:%s"
+msgstr "未從「%s」複製範本:%s"
 
 #: setup.c
 #, c-format
@@ -26932,12 +28021,12 @@
 #: submodule.c
 #, c-format
 msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link"
-msgstr "預期「%.*s」(位於子模組路徑「%s」)不是象徵式連結"
+msgstr "預期「%.*s」(位於子模組路徑「%s」)不是符號連結"
 
 #: submodule.c
 #, c-format
 msgid "expected submodule path '%s' not to be a symbolic link"
-msgstr "預期子模組路徑「%s」不是象徵式連結"
+msgstr "預期子模組路徑「%s」不是符號連結"
 
 #: submodule.c
 #, c-format
@@ -27179,7 +28268,7 @@
 
 #: transport-helper.c
 msgid "can't dup helper output fd"
-msgstr "無法複製協助工具輸出檔案句柄"
+msgstr "無法再製協助工具輸出檔案句柄"
 
 #: transport-helper.c
 #, c-format
@@ -27340,7 +28429,7 @@
 #: transport-helper.c
 #, c-format
 msgid "can't start thread for copying data: %s"
-msgstr "無法啟動執行緒來拷貝資料: %s"
+msgstr "無法啟動執行緒來複製資料: %s"
 
 #: transport-helper.c
 #, c-format
@@ -27354,7 +28443,7 @@
 
 #: transport-helper.c
 msgid "can't start thread for copying data"
-msgstr "無法啟動執行緒來拷貝資料"
+msgstr "無法啟動執行緒來複製資料"
 
 #: transport.c
 #, c-format
@@ -27785,17 +28874,32 @@
 
 #: usage.c
 #, c-format
+msgid "'%s' is nominated for removal.\n"
+msgstr "「%s」已被提名移除。\n"
+
+#: usage.c
+#, c-format
 msgid ""
-"'%s' 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"
+"If you still use this command, here's what you can do:\n"
+"\n"
+"- read https://git-scm.com/docs/BreakingChanges.html\n"
+"- check if anyone has discussed this on the mailing\n"
+"  list and if they came up with something that can\n"
+"  help you: https://lore.kernel.org/git/?q=%s\n"
+"- send an email to <git@vger.kernel.org> to let us\n"
+"  know that you still use this command and were unable\n"
+"  to determine a suitable replacement\n"
+"\n"
 msgstr ""
-"「%s」命令已被提名移除。\n"
-"如果您仍在使用該命令,請多加上「--i-still-use-this」\n"
-"選項,然後寄封電子郵件到 <git@vger.kernel.org>,\n"
-"讓我們知道您還在使用,謝謝。\n"
+"如果您仍然使用此命令,以下是您可以採取的措施:\n"
+"\n"
+"- 閱讀 https://git-scm.com/docs/BreakingChanges.html\n"
+"- 確認是否有人在郵件列表上討論過這個問題,\n"
+"  以及他們是否有想出能幫助您的解決方案:\n"
+"  https://lore.kernel.org/git/?q=%s\n"
+"- 寄送電子郵件至 <git@vger.kernel.org> 告知我們\n"
+"  您仍在使用此命令,且無法找到合適的替代方案\n"
+"\n"
 
 #: usage.c
 msgid "refusing to run without --i-still-use-this"
@@ -28481,7 +29585,7 @@
 #: wt-status.c
 #, c-format
 msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
-msgstr "沒有東西提交(建立/拷貝檔案並使用「git add」追蹤之)\n"
+msgstr "沒有東西提交(建立/複製檔案並使用「git add」追蹤之)\n"
 
 #: wt-status.c
 #, c-format
@@ -28650,7 +29754,7 @@
 
 #: git-send-email.perl
 msgid "--dump-aliases incompatible with other options\n"
-msgstr "--dump-aliases 和其它選項不相容\n"
+msgstr "--dump-aliases 和其他選項不相容\n"
 
 #: git-send-email.perl
 msgid "--dump-aliases and --translate-aliases are mutually exclusive\n"
@@ -28865,6 +29969,10 @@
 msgstr "傳送要求的信件回覆"
 
 #: git-send-email.perl
+msgid "The destination IMAP folder is not properly defined."
+msgstr "目的地 IMAP 收件匣未正確定義。"
+
+#: git-send-email.perl
 msgid "The required SMTP server is not properly defined."
 msgstr "要求的 SMTP 伺服器未被正確定義。"
 
@@ -29016,6 +30124,59 @@
 msgid "Do you really want to send %s? [y|N]: "
 msgstr "您真的要傳送 %s?[y|N]: "
 
+#~ msgid "No previous hunk"
+#~ msgstr "沒有上一個區塊"
+
+#~ msgid "No next hunk"
+#~ msgstr "沒有下一個區塊"
+
+#~ msgid "git for-each-ref [<options>] [<pattern>]"
+#~ msgstr "git for-each-ref [<選項>] [<模式>]"
+
+#~ msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
+#~ msgstr "git for-each-ref [--merged [<提交>]] [--no-merged [<提交>]]"
+
+#~ msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
+#~ msgstr "git for-each-ref [--contains [<提交>]] [--no-contains [<提交>]]"
+
+#~ msgid "git for-each-ref [--start-after <marker>]"
+#~ msgstr "git for-each-ref [--start-after <marker>]"
+
+#~ msgid ""
+#~ "git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--"
+#~ "exclude <pattern>]"
+#~ msgstr ""
+#~ "git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--"
+#~ "exclude <pattern>]"
+
+#, c-format
+#~ msgid "deleting '%s' failed"
+#~ msgstr "刪除 '%s' 失敗"
+
+#, c-format
+#~ msgid "creating '%s' failed"
+#~ msgstr "建立 '%s' 失敗"
+
+#, c-format
+#~ msgid "could not open index for %s"
+#~ msgstr "無法開啟 %s 的索引"
+
+#~ msgid "cannot handle pushes this big"
+#~ msgstr "不能處理這麼大的推送"
+
+#, c-format
+#~ msgid ""
+#~ "'%s' 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 ""
+#~ "「%s」命令已被提名移除。\n"
+#~ "如果您仍在使用該命令,請多加上「--i-still-use-this」\n"
+#~ "選項,然後寄封電子郵件到 <git@vger.kernel.org>,\n"
+#~ "讓我們知道您還在使用,謝謝。\n"
+
 #~ msgid "start-after"
 #~ msgstr "start-after"
 
@@ -29071,10 +30232,6 @@
 #~ msgid "%s: object is of unknown type '%s': %s"
 #~ msgstr "%s:物件屬於「%s」未知類型:%s"
 
-#, c-format
-#~ msgid "%s points nowhere!"
-#~ msgstr "%s 指向不存在!"
-
 #~ msgid "(bad commit)\n"
 #~ msgstr "(壞提交)\n"
 
@@ -29264,10 +30421,6 @@
 #~ "新命名目錄 %4$s->%5$s"
 
 #, c-format
-#~ msgid "cannot read object %s"
-#~ msgstr "不能讀取物件 %s"
-
-#, c-format
 #~ msgid "object %s is not a blob"
 #~ msgstr "物件 %s 不是一個資料物件"
 
diff --git a/pretty.c b/pretty.c
index cee96b9..e0646bb 100644
--- a/pretty.c
+++ b/pretty.c
@@ -470,7 +470,7 @@ static inline void strbuf_add_with_color(struct strbuf *sb, const char *color,
 
 static void append_line_with_color(struct strbuf *sb, struct grep_opt *opt,
 				   const char *line, size_t linelen,
-				   int color, enum grep_context ctx,
+				   enum git_colorbool color, enum grep_context ctx,
 				   enum grep_header_field field)
 {
 	const char *buf, *eol, *line_color, *match_color;
@@ -899,7 +899,7 @@ struct format_commit_context {
 	const char *message;
 	char *commit_encoding;
 	size_t width, indent1, indent2;
-	int auto_color;
+	enum git_colorbool auto_color;
 	int padding;
 
 	/* These offsets are relative to the start of the commit message. */
@@ -1455,14 +1455,14 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 	switch (placeholder[0]) {
 	case 'C':
 		if (starts_with(placeholder + 1, "(auto)")) {
-			c->auto_color = want_color(c->pretty_ctx->color);
-			if (c->auto_color && sb->len)
+			c->auto_color = c->pretty_ctx->color;
+			if (want_color(c->auto_color) && sb->len)
 				strbuf_addstr(sb, GIT_COLOR_RESET);
 			return 7; /* consumed 7 bytes, "C(auto)" */
 		} else {
 			int ret = parse_color(sb, placeholder, c);
 			if (ret)
-				c->auto_color = 0;
+				c->auto_color = GIT_COLOR_NEVER;
 			/*
 			 * Otherwise, we decided to treat %C<unknown>
 			 * as a literal string, and the previous
@@ -2167,7 +2167,7 @@ static int pp_utf8_width(const char *start, const char *end)
 }
 
 static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt,
-				 int color, int tabwidth, const char *line,
+				 enum git_colorbool color, int tabwidth, const char *line,
 				 int linelen)
 {
 	const char *tab;
diff --git a/pretty.h b/pretty.h
index df267af..fac6990 100644
--- a/pretty.h
+++ b/pretty.h
@@ -3,6 +3,7 @@
 
 #include "date.h"
 #include "string-list.h"
+#include "color.h"
 
 struct commit;
 struct repository;
@@ -46,7 +47,7 @@ struct pretty_print_context {
 	struct rev_info *rev;
 	const char *output_encoding;
 	struct string_list *mailmap;
-	int color;
+	enum git_colorbool color;
 	struct ident_split *from_ident;
 	unsigned encode_email_headers:1;
 	struct pretty_print_describe_status *describe_status;
diff --git a/promisor-remote.c b/promisor-remote.c
index 08b0da8..77ebf53 100644
--- a/promisor-remote.c
+++ b/promisor-remote.c
@@ -314,9 +314,162 @@ static int allow_unsanitized(char ch)
 	return ch > 32 && ch < 127;
 }
 
-static void promisor_info_vecs(struct repository *repo,
-			       struct strvec *names,
-			       struct strvec *urls)
+/*
+ * All the fields used in "promisor-remote" protocol capability,
+ * including the mandatory "name" and "url" ones.
+ */
+static const char promisor_field_name[] = "name";
+static const char promisor_field_url[] = "url";
+static const char promisor_field_filter[] = "partialCloneFilter";
+static const char promisor_field_token[] = "token";
+
+/*
+ * List of optional field names that can be used in the
+ * "promisor-remote" protocol capability (others must be
+ * ignored). Each field should correspond to a configurable property
+ * of a remote that can be relevant for the client.
+ */
+static const char *known_fields[] = {
+	promisor_field_filter, /* Filter used for partial clone */
+	promisor_field_token,  /* Authentication token for the remote */
+	NULL
+};
+
+/*
+ * Check if 'field' is in the list of the known field names for the
+ * "promisor-remote" protocol capability.
+ */
+static int is_known_field(const char *field)
+{
+	const char **p;
+
+	for (p = known_fields; *p; p++)
+		if (!strcasecmp(*p, field))
+			return 1;
+	return 0;
+}
+
+static int is_valid_field(struct string_list_item *item, void *cb_data)
+{
+	const char *field = item->string;
+	const char *config_key = (const char *)cb_data;
+
+	if (!is_known_field(field)) {
+		warning(_("unsupported field '%s' in '%s' config"), field, config_key);
+		return 0;
+	}
+	return 1;
+}
+
+static char *fields_from_config(struct string_list *fields_list, const char *config_key)
+{
+	char *fields = NULL;
+
+	if (!repo_config_get_string(the_repository, config_key, &fields) && *fields) {
+		string_list_split_in_place_f(fields_list, fields, ",", -1,
+					     STRING_LIST_SPLIT_TRIM |
+					     STRING_LIST_SPLIT_NONEMPTY);
+		filter_string_list(fields_list, 0, is_valid_field, (void *)config_key);
+	}
+
+	return fields;
+}
+
+static struct string_list *fields_sent(void)
+{
+	static struct string_list fields_list = STRING_LIST_INIT_NODUP;
+	static int initialized;
+
+	if (!initialized) {
+		fields_list.cmp = strcasecmp;
+		fields_from_config(&fields_list, "promisor.sendFields");
+		initialized = 1;
+	}
+
+	return &fields_list;
+}
+
+static struct string_list *fields_checked(void)
+{
+	static struct string_list fields_list = STRING_LIST_INIT_NODUP;
+	static int initialized;
+
+	if (!initialized) {
+		fields_list.cmp = strcasecmp;
+		fields_from_config(&fields_list, "promisor.checkFields");
+		initialized = 1;
+	}
+
+	return &fields_list;
+}
+
+/*
+ * Struct for promisor remotes involved in the "promisor-remote"
+ * protocol capability.
+ *
+ * Except for "name", each <member> in this struct and its <value>
+ * should correspond (either on the client side or on the server side)
+ * to a "remote.<name>.<member>" config variable set to <value> where
+ * "<name>" is a promisor remote name.
+ */
+struct promisor_info {
+	const char *name;
+	const char *url;
+	const char *filter;
+	const char *token;
+};
+
+static void promisor_info_free(struct promisor_info *p)
+{
+	free((char *)p->name);
+	free((char *)p->url);
+	free((char *)p->filter);
+	free((char *)p->token);
+	free(p);
+}
+
+static void promisor_info_list_clear(struct string_list *list)
+{
+	for (size_t i = 0; i < list->nr; i++)
+		promisor_info_free(list->items[i].util);
+	string_list_clear(list, 0);
+}
+
+static void set_one_field(struct promisor_info *p,
+			  const char *field, const char *value)
+{
+	if (!strcasecmp(field, promisor_field_filter))
+		p->filter = xstrdup(value);
+	else if (!strcasecmp(field, promisor_field_token))
+		p->token = xstrdup(value);
+	else
+		BUG("invalid field '%s'", field);
+}
+
+static void set_fields(struct promisor_info *p,
+		       struct string_list *field_names)
+{
+	struct string_list_item *item;
+
+	for_each_string_list_item(item, field_names) {
+		char *key = xstrfmt("remote.%s.%s", p->name, item->string);
+		const char *val;
+		if (!repo_config_get_string_tmp(the_repository, key, &val) && *val)
+			set_one_field(p, item->string, val);
+		free(key);
+	}
+}
+
+/*
+ * Populate 'list' with promisor remote information from the config.
+ * The 'util' pointer of each list item will hold a 'struct
+ * promisor_info'. Except "name" and "url", only members of that
+ * struct specified by the 'field_names' list are set (using values
+ * from the configuration).
+ */
+static void promisor_config_info_list(struct repository *repo,
+				      struct string_list *list,
+				      struct string_list *field_names)
 {
 	struct promisor_remote *r;
 
@@ -328,8 +481,17 @@ static void promisor_info_vecs(struct repository *repo,
 
 		/* Only add remotes with a non empty URL */
 		if (!repo_config_get_string_tmp(the_repository, url_key, &url) && *url) {
-			strvec_push(names, r->name);
-			strvec_push(urls, url);
+			struct promisor_info *new_info = xcalloc(1, sizeof(*new_info));
+			struct string_list_item *item;
+
+			new_info->name = xstrdup(r->name);
+			new_info->url = xstrdup(url);
+
+			if (field_names)
+				set_fields(new_info, field_names);
+
+			item = string_list_append(list, new_info->name);
+			item->util = new_info;
 		}
 
 		free(url_key);
@@ -340,47 +502,45 @@ char *promisor_remote_info(struct repository *repo)
 {
 	struct strbuf sb = STRBUF_INIT;
 	int advertise_promisors = 0;
-	struct strvec names = STRVEC_INIT;
-	struct strvec urls = STRVEC_INIT;
+	struct string_list config_info = STRING_LIST_INIT_NODUP;
+	struct string_list_item *item;
 
 	repo_config_get_bool(the_repository, "promisor.advertise", &advertise_promisors);
 
 	if (!advertise_promisors)
 		return NULL;
 
-	promisor_info_vecs(repo, &names, &urls);
+	promisor_config_info_list(repo, &config_info, fields_sent());
 
-	if (!names.nr)
+	if (!config_info.nr)
 		return NULL;
 
-	for (size_t i = 0; i < names.nr; i++) {
-		if (i)
+	for_each_string_list_item(item, &config_info) {
+		struct promisor_info *p = item->util;
+
+		if (item != config_info.items)
 			strbuf_addch(&sb, ';');
-		strbuf_addstr(&sb, "name=");
-		strbuf_addstr_urlencode(&sb, names.v[i], allow_unsanitized);
-		strbuf_addstr(&sb, ",url=");
-		strbuf_addstr_urlencode(&sb, urls.v[i], allow_unsanitized);
+
+		strbuf_addf(&sb, "%s=", promisor_field_name);
+		strbuf_addstr_urlencode(&sb, p->name, allow_unsanitized);
+		strbuf_addf(&sb, ",%s=", promisor_field_url);
+		strbuf_addstr_urlencode(&sb, p->url, allow_unsanitized);
+
+		if (p->filter) {
+			strbuf_addf(&sb, ",%s=", promisor_field_filter);
+			strbuf_addstr_urlencode(&sb, p->filter, allow_unsanitized);
+		}
+		if (p->token) {
+			strbuf_addf(&sb, ",%s=", promisor_field_token);
+			strbuf_addstr_urlencode(&sb, p->token, allow_unsanitized);
+		}
 	}
 
-	strvec_clear(&names);
-	strvec_clear(&urls);
+	promisor_info_list_clear(&config_info);
 
 	return strbuf_detach(&sb, NULL);
 }
 
-/*
- * Find first index of 'nicks' where there is 'nick'. 'nick' is
- * compared case sensitively to the strings in 'nicks'. If not found
- * 'nicks->nr' is returned.
- */
-static size_t remote_nick_find(struct strvec *nicks, const char *nick)
-{
-	for (size_t i = 0; i < nicks->nr; i++)
-		if (!strcmp(nicks->v[i], nick))
-			return i;
-	return nicks->nr;
-}
-
 enum accept_promisor {
 	ACCEPT_NONE = 0,
 	ACCEPT_KNOWN_URL,
@@ -388,23 +548,84 @@ enum accept_promisor {
 	ACCEPT_ALL
 };
 
-static int should_accept_remote(enum accept_promisor accept,
-				const char *remote_name, const char *remote_url,
-				struct strvec *names, struct strvec *urls)
+static int match_field_against_config(const char *field, const char *value,
+				      struct promisor_info *config_info)
 {
-	size_t i;
+	if (config_info->filter && !strcasecmp(field, promisor_field_filter))
+		return !strcmp(config_info->filter, value);
+	else if (config_info->token && !strcasecmp(field, promisor_field_token))
+		return !strcmp(config_info->token, value);
+
+	return 0;
+}
+
+static int all_fields_match(struct promisor_info *advertised,
+			    struct string_list *config_info,
+			    int in_list)
+{
+	struct string_list *fields = fields_checked();
+	struct string_list_item *item_checked;
+
+	for_each_string_list_item(item_checked, fields) {
+		int match = 0;
+		const char *field = item_checked->string;
+		const char *value = NULL;
+		struct string_list_item *item;
+
+		if (!strcasecmp(field, promisor_field_filter))
+			value = advertised->filter;
+		else if (!strcasecmp(field, promisor_field_token))
+			value = advertised->token;
+
+		if (!value)
+			return 0;
+
+		if (in_list) {
+			for_each_string_list_item(item, config_info) {
+				struct promisor_info *p = item->util;
+				if (match_field_against_config(field, value, p)) {
+					match = 1;
+					break;
+				}
+			}
+		} else {
+			item = string_list_lookup(config_info, advertised->name);
+			if (item) {
+				struct promisor_info *p = item->util;
+				match = match_field_against_config(field, value, p);
+			}
+		}
+
+		if (!match)
+			return 0;
+	}
+
+	return 1;
+}
+
+static int should_accept_remote(enum accept_promisor accept,
+				struct promisor_info *advertised,
+				struct string_list *config_info)
+{
+	struct promisor_info *p;
+	struct string_list_item *item;
+	const char *remote_name = advertised->name;
+	const char *remote_url = advertised->url;
 
 	if (accept == ACCEPT_ALL)
-		return 1;
+		return all_fields_match(advertised, config_info, 1);
 
-	i = remote_nick_find(names, remote_name);
+	/* Get config info for that promisor remote */
+	item = string_list_lookup(config_info, remote_name);
 
-	if (i >= names->nr)
+	if (!item)
 		/* We don't know about that remote */
 		return 0;
 
+	p = item->util;
+
 	if (accept == ACCEPT_KNOWN_NAME)
-		return 1;
+		return all_fields_match(advertised, config_info, 0);
 
 	if (accept != ACCEPT_KNOWN_URL)
 		BUG("Unhandled 'enum accept_promisor' value '%d'", accept);
@@ -414,24 +635,72 @@ static int should_accept_remote(enum accept_promisor accept,
 		return 0;
 	}
 
-	if (!strcmp(urls->v[i], remote_url))
-		return 1;
+	if (!strcmp(p->url, remote_url))
+		return all_fields_match(advertised, config_info, 0);
 
 	warning(_("known remote named '%s' but with URL '%s' instead of '%s'"),
-		remote_name, urls->v[i], remote_url);
+		remote_name, p->url, remote_url);
 
 	return 0;
 }
 
+static int skip_field_name_prefix(const char *elem, const char *field_name, const char **value)
+{
+	const char *p;
+	if (!skip_prefix(elem, field_name, &p) || *p != '=')
+		return 0;
+	*value = p + 1;
+	return 1;
+}
+
+static struct promisor_info *parse_one_advertised_remote(const char *remote_info)
+{
+	struct promisor_info *info = xcalloc(1, sizeof(*info));
+	struct string_list elem_list = STRING_LIST_INIT_DUP;
+	struct string_list_item *item;
+
+	string_list_split(&elem_list, remote_info, ",", -1);
+
+	for_each_string_list_item(item, &elem_list) {
+		const char *elem = item->string;
+		const char *p = strchr(elem, '=');
+
+		if (!p) {
+			warning(_("invalid element '%s' from remote info"), elem);
+			continue;
+		}
+
+		if (skip_field_name_prefix(elem, promisor_field_name, &p))
+			info->name = url_percent_decode(p);
+		else if (skip_field_name_prefix(elem, promisor_field_url, &p))
+			info->url = url_percent_decode(p);
+		else if (skip_field_name_prefix(elem, promisor_field_filter, &p))
+			info->filter = url_percent_decode(p);
+		else if (skip_field_name_prefix(elem, promisor_field_token, &p))
+			info->token = url_percent_decode(p);
+	}
+
+	string_list_clear(&elem_list, 0);
+
+	if (!info->name || !info->url) {
+		warning(_("server advertised a promisor remote without a name or URL: %s"),
+			remote_info);
+		promisor_info_free(info);
+		return NULL;
+	}
+
+	return info;
+}
+
 static void filter_promisor_remote(struct repository *repo,
 				   struct strvec *accepted,
 				   const char *info)
 {
-	struct strbuf **remotes;
 	const char *accept_str;
 	enum accept_promisor accept = ACCEPT_NONE;
-	struct strvec names = STRVEC_INIT;
-	struct strvec urls = STRVEC_INIT;
+	struct string_list config_info = STRING_LIST_INIT_NODUP;
+	struct string_list remote_info = STRING_LIST_INIT_DUP;
+	struct string_list_item *item;
 
 	if (!repo_config_get_string_tmp(the_repository, "promisor.acceptfromserver", &accept_str)) {
 		if (!*accept_str || !strcasecmp("None", accept_str))
@@ -450,49 +719,31 @@ static void filter_promisor_remote(struct repository *repo,
 	if (accept == ACCEPT_NONE)
 		return;
 
-	if (accept != ACCEPT_ALL)
-		promisor_info_vecs(repo, &names, &urls);
-
 	/* Parse remote info received */
 
-	remotes = strbuf_split_str(info, ';', 0);
+	string_list_split(&remote_info, info, ";", -1);
 
-	for (size_t i = 0; remotes[i]; i++) {
-		struct strbuf **elems;
-		const char *remote_name = NULL;
-		const char *remote_url = NULL;
-		char *decoded_name = NULL;
-		char *decoded_url = NULL;
+	for_each_string_list_item(item, &remote_info) {
+		struct promisor_info *advertised;
 
-		strbuf_strip_suffix(remotes[i], ";");
-		elems = strbuf_split(remotes[i], ',');
+		advertised = parse_one_advertised_remote(item->string);
 
-		for (size_t j = 0; elems[j]; j++) {
-			int res;
-			strbuf_strip_suffix(elems[j], ",");
-			res = skip_prefix(elems[j]->buf, "name=", &remote_name) ||
-				skip_prefix(elems[j]->buf, "url=", &remote_url);
-			if (!res)
-				warning(_("unknown element '%s' from remote info"),
-					elems[j]->buf);
+		if (!advertised)
+			continue;
+
+		if (!config_info.nr) {
+			promisor_config_info_list(repo, &config_info, fields_checked());
+			string_list_sort(&config_info);
 		}
 
-		if (remote_name)
-			decoded_name = url_percent_decode(remote_name);
-		if (remote_url)
-			decoded_url = url_percent_decode(remote_url);
+		if (should_accept_remote(accept, advertised, &config_info))
+			strvec_push(accepted, advertised->name);
 
-		if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &names, &urls))
-			strvec_push(accepted, decoded_name);
-
-		strbuf_list_free(elems);
-		free(decoded_name);
-		free(decoded_url);
+		promisor_info_free(advertised);
 	}
 
-	strvec_clear(&names);
-	strvec_clear(&urls);
-	strbuf_list_free(remotes);
+	promisor_info_list_clear(&config_info);
+	string_list_clear(&remote_info, 0);
 }
 
 char *promisor_remote_reply(const char *info)
@@ -518,16 +769,15 @@ char *promisor_remote_reply(const char *info)
 
 void mark_promisor_remotes_as_accepted(struct repository *r, const char *remotes)
 {
-	struct strbuf **accepted_remotes = strbuf_split_str(remotes, ';', 0);
+	struct string_list accepted_remotes = STRING_LIST_INIT_DUP;
+	struct string_list_item *item;
 
-	for (size_t i = 0; accepted_remotes[i]; i++) {
-		struct promisor_remote *p;
-		char *decoded_remote;
+	string_list_split(&accepted_remotes, remotes, ";", -1);
 
-		strbuf_strip_suffix(accepted_remotes[i], ";");
-		decoded_remote = url_percent_decode(accepted_remotes[i]->buf);
+	for_each_string_list_item(item, &accepted_remotes) {
+		char *decoded_remote = url_percent_decode(item->string);
+		struct promisor_remote *p = repo_promisor_remote_find(r, decoded_remote);
 
-		p = repo_promisor_remote_find(r, decoded_remote);
 		if (p)
 			p->accepted = 1;
 		else
@@ -537,5 +787,5 @@ void mark_promisor_remotes_as_accepted(struct repository *r, const char *remotes
 		free(decoded_remote);
 	}
 
-	strbuf_list_free(accepted_remotes);
+	string_list_clear(&accepted_remotes, 0);
 }
diff --git a/protocol.c b/protocol.c
index 65f6621..a3e26a8 100644
--- a/protocol.c
+++ b/protocol.c
@@ -61,7 +61,7 @@ enum protocol_version determine_protocol_version_server(void)
 	if (git_protocol) {
 		struct string_list list = STRING_LIST_INIT_DUP;
 		const struct string_list_item *item;
-		string_list_split(&list, git_protocol, ':', -1);
+		string_list_split(&list, git_protocol, ":", -1);
 
 		for_each_string_list_item(item, &list) {
 			const char *value;
diff --git a/pseudo-merge.c b/pseudo-merge.c
index 893b763..a2d5bd8 100644
--- a/pseudo-merge.c
+++ b/pseudo-merge.c
@@ -221,28 +221,25 @@ void load_pseudo_merges_from_config(struct repository *r,
 	}
 }
 
-static int find_pseudo_merge_group_for_ref(const char *refname,
-					   const char *referent UNUSED,
-					   const struct object_id *oid,
-					   int flags UNUSED,
-					   void *_data)
+static int find_pseudo_merge_group_for_ref(const struct reference *ref, void *_data)
 {
 	struct bitmap_writer *writer = _data;
+	const struct object_id *maybe_peeled = ref->oid;
 	struct object_id peeled;
 	struct commit *c;
 	uint32_t i;
 	int has_bitmap;
 
-	if (!peel_iterated_oid(the_repository, oid, &peeled))
-		oid = &peeled;
+	if (!reference_get_peeled_oid(the_repository, ref, &peeled))
+		maybe_peeled = &peeled;
 
-	c = lookup_commit(the_repository, oid);
+	c = lookup_commit(the_repository, maybe_peeled);
 	if (!c)
 		return 0;
-	if (!packlist_find(writer->to_pack, oid))
+	if (!packlist_find(writer->to_pack, maybe_peeled))
 		return 0;
 
-	has_bitmap = bitmap_writer_has_bitmapped_object_id(writer, oid);
+	has_bitmap = bitmap_writer_has_bitmapped_object_id(writer, maybe_peeled);
 
 	for (i = 0; i < writer->pseudo_merge_groups.nr; i++) {
 		struct pseudo_merge_group *group;
@@ -252,7 +249,7 @@ static int find_pseudo_merge_group_for_ref(const char *refname,
 		size_t j;
 
 		group = writer->pseudo_merge_groups.items[i].util;
-		if (regexec(group->pattern, refname, ARRAY_SIZE(captures),
+		if (regexec(group->pattern, ref->name, ARRAY_SIZE(captures),
 			    captures, 0))
 			continue;
 
@@ -269,7 +266,7 @@ static int find_pseudo_merge_group_for_ref(const char *refname,
 			if (group_name.len)
 				strbuf_addch(&group_name, '-');
 
-			strbuf_add(&group_name, refname + match->rm_so,
+			strbuf_add(&group_name, ref->name + match->rm_so,
 				   match->rm_eo - match->rm_so);
 		}
 
diff --git a/range-diff.c b/range-diff.c
index 8a2dcbe..57edff4 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -39,7 +39,7 @@ struct patch_util {
  * as struct object_id (will need to be free()d).
  */
 static int read_patches(const char *range, struct string_list *list,
-			const struct strvec *other_arg,
+			const struct strvec *log_arg,
 			unsigned int include_merges)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
@@ -69,8 +69,8 @@ static int read_patches(const char *range, struct string_list *list,
 	if (!include_merges)
 		strvec_push(&cp.args, "--no-merges");
 	strvec_push(&cp.args, range);
-	if (other_arg)
-		strvec_pushv(&cp.args, other_arg->v);
+	if (log_arg)
+		strvec_pushv(&cp.args, log_arg->v);
 	cp.out = -1;
 	cp.no_stdin = 1;
 	cp.git_cmd = 1;
@@ -325,13 +325,24 @@ static int diffsize(const char *a, const char *b)
 }
 
 static void get_correspondences(struct string_list *a, struct string_list *b,
-				int creation_factor)
+				int creation_factor, size_t max_memory)
 {
 	int n = a->nr + b->nr;
 	int *cost, c, *a2b, *b2a;
 	int i, j;
-
-	ALLOC_ARRAY(cost, st_mult(n, n));
+	size_t cost_size = st_mult(n, n);
+	size_t cost_bytes = st_mult(sizeof(int), cost_size);
+	if (cost_bytes >= max_memory) {
+		struct strbuf cost_str = STRBUF_INIT;
+		struct strbuf max_str = STRBUF_INIT;
+		strbuf_humanise_bytes(&cost_str, cost_bytes);
+		strbuf_humanise_bytes(&max_str, max_memory);
+		die(_("range-diff: unable to compute the range-diff, since it "
+		      "exceeds the maximum memory for the cost matrix: %s "
+		      "(%"PRIuMAX" bytes) needed, limited to %s (%"PRIuMAX" bytes)"),
+		    cost_str.buf, (uintmax_t)cost_bytes, max_str.buf, (uintmax_t)max_memory);
+	}
+	ALLOC_ARRAY(cost, cost_size);
 	ALLOC_ARRAY(a2b, n);
 	ALLOC_ARRAY(b2a, n);
 
@@ -583,15 +594,16 @@ int show_range_diff(const char *range1, const char *range2,
 	if (range_diff_opts->left_only && range_diff_opts->right_only)
 		res = error(_("options '%s' and '%s' cannot be used together"), "--left-only", "--right-only");
 
-	if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg, include_merges))
+	if (!res && read_patches(range1, &branch1, range_diff_opts->log_arg, include_merges))
 		res = error(_("could not parse log for '%s'"), range1);
-	if (!res && read_patches(range2, &branch2, range_diff_opts->other_arg, include_merges))
+	if (!res && read_patches(range2, &branch2, range_diff_opts->log_arg, include_merges))
 		res = error(_("could not parse log for '%s'"), range2);
 
 	if (!res) {
 		find_exact_matches(&branch1, &branch2);
 		get_correspondences(&branch1, &branch2,
-				    range_diff_opts->creation_factor);
+				    range_diff_opts->creation_factor,
+				    range_diff_opts->max_memory);
 		output(&branch1, &branch2, range_diff_opts);
 	}
 
diff --git a/range-diff.h b/range-diff.h
index cd85000..9b70a80 100644
--- a/range-diff.h
+++ b/range-diff.h
@@ -5,6 +5,10 @@
 #include "strvec.h"
 
 #define RANGE_DIFF_CREATION_FACTOR_DEFAULT 60
+#define RANGE_DIFF_MAX_MEMORY_DEFAULT \
+	(sizeof(void*) >= 8 ? \
+		((size_t)(1024L * 1024L) * (size_t)(4L * 1024L)) : /* 4GB on 64-bit */ \
+		((size_t)(1024L * 1024L) * (size_t)(2L * 1024L)))   /* 2GB on 32-bit */
 
 /*
  * A much higher value than the default, when we KNOW we are comparing
@@ -17,8 +21,9 @@ struct range_diff_options {
 	unsigned dual_color:1;
 	unsigned left_only:1, right_only:1;
 	unsigned include_merges:1;
+	size_t max_memory;
 	const struct diff_options *diffopt; /* may be NULL */
-	const struct strvec *other_arg; /* may be NULL */
+	const struct strvec *log_arg; /* may be NULL */
 };
 
 /*
diff --git a/reachable.c b/reachable.c
index 22266db..b753c39 100644
--- a/reachable.c
+++ b/reachable.c
@@ -83,18 +83,17 @@ static void add_rebase_files(struct rev_info *revs)
 	free_worktrees(worktrees);
 }
 
-static int add_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
-		       int flag, void *cb_data)
+static int add_one_ref(const struct reference *ref, void *cb_data)
 {
 	struct rev_info *revs = (struct rev_info *)cb_data;
 	struct object *object;
 
-	if ((flag & REF_ISSYMREF) && (flag & REF_ISBROKEN)) {
-		warning("symbolic ref is dangling: %s", path);
+	if ((ref->flags & REF_ISSYMREF) && (ref->flags & REF_ISBROKEN)) {
+		warning("symbolic ref is dangling: %s", ref->name);
 		return 0;
 	}
 
-	object = parse_object_or_die(the_repository, oid, path);
+	object = parse_object_or_die(the_repository, ref->oid, ref->name);
 	add_pending_object(revs, object, "");
 
 	return 0;
diff --git a/read-cache.c b/read-cache.c
index 06ad74d..990d4ea 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -8,7 +8,6 @@
 #define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "git-compat-util.h"
-#include "bulk-checkin.h"
 #include "config.h"
 #include "date.h"
 #include "diff.h"
@@ -707,7 +706,6 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 	int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
 			  (intent_only ? ADD_CACHE_NEW_ONLY : 0));
 	unsigned hash_flags = pretend ? 0 : INDEX_WRITE_OBJECT;
-	struct object_id oid;
 
 	if (flags & ADD_CACHE_RENORMALIZE)
 		hash_flags |= INDEX_RENORMALIZE;
@@ -717,8 +715,6 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 
 	namelen = strlen(path);
 	if (S_ISDIR(st_mode)) {
-		if (repo_resolve_gitlink_ref(the_repository, path, "HEAD", &oid) < 0)
-			return error(_("'%s' does not have a commit checked out"), path);
 		while (namelen && path[namelen-1] == '/')
 			namelen--;
 	}
@@ -1807,7 +1803,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
 
 	if (expand_name_field) {
 		const unsigned char *cp = (const unsigned char *)name;
-		size_t strip_len, previous_len;
+		uint64_t strip_len, previous_len;
 
 		/* If we're at the beginning of a block, ignore the previous name */
 		strip_len = decode_varint(&cp);
@@ -2655,8 +2651,10 @@ static int ce_write_entry(struct hashfile *f, struct cache_entry *ce,
 		hashwrite(f, ce->name, len);
 		hashwrite(f, padding, align_padding_size(size, len));
 	} else {
-		int common, to_remove, prefix_size;
+		int common, to_remove;
+		uint8_t prefix_size;
 		unsigned char to_remove_vi[16];
+
 		for (common = 0;
 		     (common < previous_name->len &&
 		      ce->name[common] &&
@@ -3947,6 +3945,7 @@ int add_files_to_cache(struct repository *repo, const char *prefix,
 		       const struct pathspec *pathspec, char *ps_matched,
 		       int include_sparse, int flags)
 {
+	struct odb_transaction *transaction;
 	struct update_callback_data data;
 	struct rev_info rev;
 
@@ -3972,9 +3971,9 @@ int add_files_to_cache(struct repository *repo, const char *prefix,
 	 * This function is invoked from commands other than 'add', which
 	 * may not have their own transaction active.
 	 */
-	begin_odb_transaction();
+	transaction = odb_transaction_begin(repo->objects);
 	run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
-	end_odb_transaction();
+	odb_transaction_commit(transaction);
 
 	release_revisions(&rev);
 	return !!data.add_errors;
diff --git a/ref-filter.c b/ref-filter.c
index 4edf0df..d745426 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -91,6 +91,7 @@ static struct expand_data {
 	struct object_id delta_base_oid;
 	void *content;
 
+	struct object *maybe_object;
 	struct object_info info;
 } oi, oi_deref;
 
@@ -435,7 +436,7 @@ static int remote_ref_atom_parser(struct ref_format *format UNUSED,
 	}
 
 	atom->u.remote_ref.nobracket = 0;
-	string_list_split(&params, arg, ',', -1);
+	string_list_split(&params, arg, ",", -1);
 
 	for (i = 0; i < params.nr; i++) {
 		const char *s = params.items[i].string;
@@ -831,7 +832,7 @@ static int align_atom_parser(struct ref_format *format UNUSED,
 
 	align->position = ALIGN_LEFT;
 
-	string_list_split(&params, arg, ',', -1);
+	string_list_split(&params, arg, ",", -1);
 	for (i = 0; i < params.nr; i++) {
 		const char *s = params.items[i].string;
 		int position;
@@ -1475,11 +1476,29 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_
 	}
 }
 
-/* See grab_values */
-static void grab_tag_values(struct atom_value *val, int deref, struct object *obj)
+static struct object *get_or_parse_object(struct expand_data *data, const char *refname,
+					  struct strbuf *err, int *eaten)
 {
+	if (!data->maybe_object) {
+		data->maybe_object = parse_object_buffer(the_repository, &data->oid, data->type,
+							 data->size, data->content, eaten);
+		if (!data->maybe_object) {
+			strbuf_addf(err, _("parse_object_buffer failed on %s for %s"),
+				    oid_to_hex(&data->oid), refname);
+			return NULL;
+		}
+	}
+
+	return data->maybe_object;
+}
+
+/* See grab_values */
+static int grab_tag_values(struct atom_value *val, int deref,
+			   struct expand_data *data, const char *refname,
+			   struct strbuf *err, int *eaten)
+{
+	struct tag *tag = NULL;
 	int i;
-	struct tag *tag = (struct tag *) obj;
 
 	for (i = 0; i < used_atom_cnt; i++) {
 		const char *name = used_atom[i].name;
@@ -1487,6 +1506,14 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
 		struct atom_value *v = &val[i];
 		if (!!deref != (*name == '*'))
 			continue;
+
+		if (!tag) {
+			tag = (struct tag *) get_or_parse_object(data, refname,
+								 err, eaten);
+			if (!tag)
+				return -1;
+		}
+
 		if (deref)
 			name++;
 		if (atom_type == ATOM_TAG)
@@ -1496,22 +1523,35 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
 		else if (atom_type == ATOM_OBJECT && tag->tagged)
 			v->s = xstrdup(oid_to_hex(&tag->tagged->oid));
 	}
+
+	return 0;
 }
 
 /* See grab_values */
-static void grab_commit_values(struct atom_value *val, int deref, struct object *obj)
+static int grab_commit_values(struct atom_value *val, int deref,
+			      struct expand_data *data, const char *refname,
+			      struct strbuf *err, int *eaten)
 {
 	int i;
-	struct commit *commit = (struct commit *) obj;
+	struct commit *commit = NULL;
 
 	for (i = 0; i < used_atom_cnt; i++) {
 		const char *name = used_atom[i].name;
 		enum atom_type atom_type = used_atom[i].atom_type;
 		struct atom_value *v = &val[i];
+
 		if (!!deref != (*name == '*'))
 			continue;
 		if (deref)
 			name++;
+
+		if (!commit) {
+			commit = (struct commit *) get_or_parse_object(data, refname,
+								       err, eaten);
+			if (!commit)
+				return -1;
+		}
+
 		if (atom_type == ATOM_TREE &&
 		    grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i]))
 			continue;
@@ -1531,6 +1571,8 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object
 			v->s = strbuf_detach(&s, NULL);
 		}
 	}
+
+	return 0;
 }
 
 static const char *find_wholine(const char *who, int wholen, const char *buf)
@@ -1759,10 +1801,12 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void
 	}
 }
 
-static void grab_signature(struct atom_value *val, int deref, struct object *obj)
+static int grab_signature(struct atom_value *val, int deref,
+			  struct expand_data *data, const char *refname,
+			  struct strbuf *err, int *eaten)
 {
 	int i;
-	struct commit *commit = (struct commit *) obj;
+	struct commit *commit = NULL;
 	struct signature_check sigc = { 0 };
 	int signature_checked = 0;
 
@@ -1790,6 +1834,13 @@ static void grab_signature(struct atom_value *val, int deref, struct object *obj
 			continue;
 
 		if (!signature_checked) {
+			if (!commit) {
+				commit = (struct commit *) get_or_parse_object(data, refname,
+									       err, eaten);
+				if (!commit)
+					return -1;
+			}
+
 			check_commit_signature(commit, &sigc);
 			signature_checked = 1;
 		}
@@ -1843,6 +1894,8 @@ static void grab_signature(struct atom_value *val, int deref, struct object *obj
 
 	if (signature_checked)
 		signature_check_clear(&sigc);
+
+	return 0;
 }
 
 static void find_subpos(const char *buf,
@@ -1920,9 +1973,8 @@ static void append_lines(struct strbuf *out, const char *buf, unsigned long size
 }
 
 static void grab_describe_values(struct atom_value *val, int deref,
-				 struct object *obj)
+				 struct expand_data *data)
 {
-	struct commit *commit = (struct commit *)obj;
 	int i;
 
 	for (i = 0; i < used_atom_cnt; i++) {
@@ -1944,7 +1996,7 @@ static void grab_describe_values(struct atom_value *val, int deref,
 		cmd.git_cmd = 1;
 		strvec_push(&cmd.args, "describe");
 		strvec_pushv(&cmd.args, atom->u.describe_args.v);
-		strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
+		strvec_push(&cmd.args, oid_to_hex(&data->oid));
 		if (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {
 			error(_("failed to run 'describe'"));
 			v->s = xstrdup("");
@@ -2066,24 +2118,36 @@ static void fill_missing_values(struct atom_value *val)
  * pointed at by the ref itself; otherwise it is the object the
  * ref (which is a tag) refers to.
  */
-static void grab_values(struct atom_value *val, int deref, struct object *obj, struct expand_data *data)
+static int grab_values(struct atom_value *val, int deref, struct expand_data *data,
+		       const char *refname, struct strbuf *err, int *eaten)
 {
 	void *buf = data->content;
+	int ret;
 
-	switch (obj->type) {
+	switch (data->type) {
 	case OBJ_TAG:
-		grab_tag_values(val, deref, obj);
+		ret = grab_tag_values(val, deref, data, refname, err, eaten);
+		if (ret < 0)
+			goto out;
+
 		grab_sub_body_contents(val, deref, data);
 		grab_person("tagger", val, deref, buf);
-		grab_describe_values(val, deref, obj);
+		grab_describe_values(val, deref, data);
 		break;
 	case OBJ_COMMIT:
-		grab_commit_values(val, deref, obj);
+		ret = grab_commit_values(val, deref, data, refname, err, eaten);
+		if (ret < 0)
+			goto out;
+
 		grab_sub_body_contents(val, deref, data);
 		grab_person("author", val, deref, buf);
 		grab_person("committer", val, deref, buf);
-		grab_signature(val, deref, obj);
-		grab_describe_values(val, deref, obj);
+
+		ret = grab_signature(val, deref, data, refname, err, eaten);
+		if (ret < 0)
+			goto out;
+
+		grab_describe_values(val, deref, data);
 		break;
 	case OBJ_TREE:
 		/* grab_tree_values(val, deref, obj, buf, sz); */
@@ -2094,8 +2158,12 @@ static void grab_values(struct atom_value *val, int deref, struct object *obj, s
 		grab_sub_body_contents(val, deref, data);
 		break;
 	default:
-		die("Eh?  Object of type %d?", obj->type);
+		die("Eh?  Object of type %d?", data->type);
 	}
+
+	ret = 0;
+out:
+	return ret;
 }
 
 static inline char *copy_advance(char *dst, const char *src)
@@ -2292,38 +2360,43 @@ static const char *get_refname(struct used_atom *atom, struct ref_array_item *re
 	return show_ref(&atom->u.refname, ref->refname);
 }
 
-static int get_object(struct ref_array_item *ref, int deref, struct object **obj,
+static int get_object(struct ref_array_item *ref, int deref,
 		      struct expand_data *oi, struct strbuf *err)
 {
-	/* parse_object_buffer() will set eaten to 0 if free() will be needed */
-	int eaten = 1;
+	/* parse_object_buffer() will set eaten to 1 if free() will be needed */
+	int eaten = 0;
+	int ret;
+
+	oi->maybe_object = NULL;
+
 	if (oi->info.contentp) {
 		/* We need to know that to use parse_object_buffer properly */
 		oi->info.sizep = &oi->size;
 		oi->info.typep = &oi->type;
 	}
+
 	if (odb_read_object_info_extended(the_repository->objects, &oi->oid, &oi->info,
-					  OBJECT_INFO_LOOKUP_REPLACE))
-		return strbuf_addf_ret(err, -1, _("missing object %s for %s"),
-				       oid_to_hex(&oi->oid), ref->refname);
+					  OBJECT_INFO_LOOKUP_REPLACE)) {
+		ret = strbuf_addf_ret(err, -1, _("missing object %s for %s"),
+				      oid_to_hex(&oi->oid), ref->refname);
+		goto out;
+	}
 	if (oi->info.disk_sizep && oi->disk_size < 0)
 		BUG("Object size is less than zero.");
 
 	if (oi->info.contentp) {
-		*obj = parse_object_buffer(the_repository, &oi->oid, oi->type, oi->size, oi->content, &eaten);
-		if (!*obj) {
-			if (!eaten)
-				free(oi->content);
-			return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
-					       oid_to_hex(&oi->oid), ref->refname);
-		}
-		grab_values(ref->value, deref, *obj, oi);
+		ret = grab_values(ref->value, deref, oi, ref->refname, err, &eaten);
+		if (ret < 0)
+			goto out;
 	}
 
 	grab_common_values(ref->value, deref, oi);
+	ret = 0;
+
+out:
 	if (!eaten)
 		free(oi->content);
-	return 0;
+	return ret;
 }
 
 static void populate_worktree_map(struct hashmap *map, struct worktree **worktrees)
@@ -2376,7 +2449,6 @@ static char *get_worktree_path(const struct ref_array_item *ref)
  */
 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;
@@ -2564,24 +2636,32 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
 
 
 	oi.oid = ref->objectname;
-	if (get_object(ref, 0, &obj, &oi, err))
+	if (get_object(ref, 0, &oi, err))
 		return -1;
 
 	/*
 	 * If there is no atom that wants to know about tagged
 	 * object, we are done.
 	 */
-	if (!need_tagged || (obj->type != OBJ_TAG))
+	if (!need_tagged || (oi.type != OBJ_TAG))
 		return 0;
 
 	/*
 	 * If it is a tag object, see if we use the peeled value. If we do,
 	 * grab the peeled OID.
 	 */
-	if (need_tagged && peel_iterated_oid(the_repository, &obj->oid, &oi_deref.oid))
-		die("bad tag");
+	if (need_tagged) {
+		if (!is_null_oid(&ref->peeled_oid)) {
+			oidcpy(&oi_deref.oid, &ref->peeled_oid);
+		} else if (!peel_object(the_repository, &oi.oid, &oi_deref.oid,
+					PEEL_OBJECT_VERIFY_TAGGED_OBJECT_TYPE)) {
+			/* We managed to peel the object ourselves. */
+		} else {
+			die("bad tag");
+		}
+	}
 
-	return get_object(ref, 1, &obj, &oi_deref, err);
+	return get_object(ref, 1, &oi_deref, err);
 }
 
 /*
@@ -2664,7 +2744,7 @@ static int match_name_as_path(const char **pattern, const char *refname,
 /* Return 1 if the refname matches one of the patterns, otherwise 0. */
 static int filter_pattern_match(struct ref_filter *filter, const char *refname)
 {
-	if (!*filter->name_patterns)
+	if (!filter->name_patterns || !*filter->name_patterns)
 		return 1; /* No pattern always matches */
 	if (filter->match_as_path)
 		return match_name_as_path(filter->name_patterns, refname,
@@ -2751,7 +2831,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
 		return for_each_fullref_with_seek(filter, cb, cb_data, 0);
 	}
 
-	if (!filter->name_patterns[0]) {
+	if (!filter->name_patterns || !filter->name_patterns[0]) {
 		/* no patterns; we have to look at everything */
 		return for_each_fullref_with_seek(filter, cb, cb_data, 0);
 	}
@@ -2807,12 +2887,15 @@ static int match_points_at(struct oid_array *points_at,
  * Callers can then fill in other struct members at their leisure.
  */
 static struct ref_array_item *new_ref_array_item(const char *refname,
-						 const struct object_id *oid)
+						 const struct object_id *oid,
+						 const struct object_id *peeled_oid)
 {
 	struct ref_array_item *ref;
 
 	FLEX_ALLOC_STR(ref, refname, refname);
 	oidcpy(&ref->objectname, oid);
+	if (peeled_oid)
+		oidcpy(&ref->peeled_oid, peeled_oid);
 	ref->rest = NULL;
 
 	return ref;
@@ -2826,14 +2909,15 @@ static void ref_array_append(struct ref_array *array, struct ref_array_item *ref
 
 struct ref_array_item *ref_array_push(struct ref_array *array,
 				      const char *refname,
-				      const struct object_id *oid)
+				      const struct object_id *oid,
+				      const struct object_id *peeled_oid)
 {
-	struct ref_array_item *ref = new_ref_array_item(refname, oid);
+	struct ref_array_item *ref = new_ref_array_item(refname, oid, peeled_oid);
 	ref_array_append(array, ref);
 	return ref;
 }
 
-static int ref_kind_from_refname(const char *refname)
+int ref_kind_from_refname(const char *refname)
 {
 	unsigned int i;
 
@@ -2871,25 +2955,25 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
 	return ref_kind_from_refname(refname);
 }
 
-static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid,
-			    int flag, struct ref_filter *filter)
+static struct ref_array_item *apply_ref_filter(const struct reference *ref,
+					       struct ref_filter *filter)
 {
-	struct ref_array_item *ref;
+	struct ref_array_item *item;
 	struct commit *commit = NULL;
 	unsigned int kind;
 
-	if (flag & REF_BAD_NAME) {
-		warning(_("ignoring ref with broken name %s"), refname);
+	if (ref->flags & REF_BAD_NAME) {
+		warning(_("ignoring ref with broken name %s"), ref->name);
 		return NULL;
 	}
 
-	if (flag & REF_ISBROKEN) {
-		warning(_("ignoring broken ref %s"), refname);
+	if (ref->flags & REF_ISBROKEN) {
+		warning(_("ignoring broken ref %s"), ref->name);
 		return NULL;
 	}
 
 	/* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */
-	kind = filter_ref_kind(filter, refname);
+	kind = filter_ref_kind(filter, ref->name);
 
 	/*
 	 * Generally HEAD refs are printed with special description denoting a rebase,
@@ -2902,13 +2986,13 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const char *
 	else if (!(kind & filter->kind))
 		return NULL;
 
-	if (!filter_pattern_match(filter, refname))
+	if (!filter_pattern_match(filter, ref->name))
 		return NULL;
 
-	if (filter_exclude_match(filter, refname))
+	if (filter_exclude_match(filter, ref->name))
 		return NULL;
 
-	if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname))
+	if (filter->points_at.nr && !match_points_at(&filter->points_at, ref->oid, ref->name))
 		return NULL;
 
 	/*
@@ -2918,7 +3002,7 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const char *
 	 */
 	if (filter->reachable_from || filter->unreachable_from ||
 	    filter->with_commit || filter->no_commit || filter->verbose) {
-		commit = lookup_commit_reference_gently(the_repository, oid, 1);
+		commit = lookup_commit_reference_gently(the_repository, ref->oid, 1);
 		if (!commit)
 			return NULL;
 		/* We perform the filtering for the '--contains' option... */
@@ -2936,13 +3020,13 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const char *
 	 * to do its job and the resulting list may yet to be pruned
 	 * by maxcount logic.
 	 */
-	ref = new_ref_array_item(refname, oid);
-	ref->commit = commit;
-	ref->flag = flag;
-	ref->kind = kind;
-	ref->symref = xstrdup_or_null(referent);
+	item = new_ref_array_item(ref->name, ref->oid, ref->peeled_oid);
+	item->commit = commit;
+	item->flag = ref->flags;
+	item->kind = kind;
+	item->symref = xstrdup_or_null(ref->target);
 
-	return ref;
+	return item;
 }
 
 struct ref_filter_cbdata {
@@ -2954,14 +3038,14 @@ struct ref_filter_cbdata {
  * A call-back given to for_each_ref().  Filter refs and keep them for
  * later object processing.
  */
-static int filter_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const struct reference *ref, void *cb_data)
 {
 	struct ref_filter_cbdata *ref_cbdata = cb_data;
-	struct ref_array_item *ref;
+	struct ref_array_item *item;
 
-	ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
-	if (ref)
-		ref_array_append(ref_cbdata->array, ref);
+	item = apply_ref_filter(ref, ref_cbdata->filter);
+	if (item)
+		ref_array_append(ref_cbdata->array, item);
 
 	return 0;
 }
@@ -2990,17 +3074,17 @@ struct ref_filter_and_format_cbdata {
 	} internal;
 };
 
-static int filter_and_format_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const struct reference *ref, void *cb_data)
 {
 	struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
-	struct ref_array_item *ref;
+	struct ref_array_item *item;
 	struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
 
-	ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
-	if (!ref)
+	item = apply_ref_filter(ref, ref_cbdata->filter);
+	if (!item)
 		return 0;
 
-	if (format_ref_array_item(ref, ref_cbdata->format, &output, &err))
+	if (format_ref_array_item(item, ref_cbdata->format, &output, &err))
 		die("%s", err.buf);
 
 	if (output.len || !ref_cbdata->format->array_opts.omit_empty) {
@@ -3010,7 +3094,7 @@ static int filter_and_format_one(const char *refname, const char *referent, cons
 
 	strbuf_release(&output);
 	strbuf_release(&err);
-	free_array_item(ref);
+	free_array_item(item);
 
 	/*
 	 * Increment the running count of refs that match the filter. If
@@ -3583,13 +3667,14 @@ void print_formatted_ref_array(struct ref_array *array, struct ref_format *forma
 }
 
 void pretty_print_ref(const char *name, const struct object_id *oid,
+		      const struct object_id *peeled_oid,
 		      struct ref_format *format)
 {
 	struct ref_array_item *ref_item;
 	struct strbuf output = STRBUF_INIT;
 	struct strbuf err = STRBUF_INIT;
 
-	ref_item = new_ref_array_item(name, oid);
+	ref_item = new_ref_array_item(name, oid, peeled_oid);
 	ref_item->kind = ref_kind_from_refname(name);
 	if (format_ref_array_item(ref_item, format, &output, &err))
 		die("%s", err.buf);
diff --git a/ref-filter.h b/ref-filter.h
index f22ca94..120221b 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -41,6 +41,7 @@ enum ref_sorting_order {
 
 struct ref_array_item {
 	struct object_id objectname;
+	struct object_id peeled_oid;
 	const char *rest;
 	int flag;
 	unsigned int kind;
@@ -95,7 +96,7 @@ struct ref_format {
 	const char *format;
 	const char *rest;
 	int quote_style;
-	int use_color;
+	enum git_colorbool use_color;
 
 	/* Internal state to ref-filter */
 	int need_color_reset_at_eol;
@@ -111,7 +112,7 @@ struct ref_format {
 	.exclude = STRVEC_INIT, \
 }
 #define REF_FORMAT_INIT {             \
-	.use_color = -1,              \
+	.use_color = GIT_COLOR_UNKNOWN, \
 }
 
 /*  Macros for checking --merged and --no-merged options */
@@ -135,6 +136,8 @@ struct ref_format {
 	OPT_STRVEC(0, "exclude", &(var)->exclude, \
 		   N_("pattern"), N_("exclude refs which match pattern"))
 
+/* Get the reference kind from the provided reference name. */
+int ref_kind_from_refname(const char *refname);
 /*
  * 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
@@ -185,6 +188,7 @@ void print_formatted_ref_array(struct ref_array *array, struct ref_format *forma
  * name must be a fully qualified refname.
  */
 void pretty_print_ref(const char *name, const struct object_id *oid,
+		      const struct object_id *peeled_oid,
 		      struct ref_format *format);
 
 /*
@@ -193,7 +197,8 @@ void pretty_print_ref(const char *name, const struct object_id *oid,
  */
 struct ref_array_item *ref_array_push(struct ref_array *array,
 				      const char *refname,
-				      const struct object_id *oid);
+				      const struct object_id *oid,
+				      const struct object_id *peeled_oid);
 
 /*
  * If the provided format includes ahead-behind atoms, then compute the
diff --git a/reflog-walk.c b/reflog-walk.c
index c7070b1..4f1ce04 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -22,9 +22,10 @@ struct complete_reflogs {
 	int nr, alloc;
 };
 
-static int read_one_reflog(struct object_id *ooid, struct object_id *noid,
-		const char *email, timestamp_t timestamp, int tz,
-		const char *message, void *cb_data)
+static int read_one_reflog(const char *refname UNUSED,
+			   struct object_id *ooid, struct object_id *noid,
+			   const char *email, timestamp_t timestamp, int tz,
+			   const char *message, void *cb_data)
 {
 	struct complete_reflogs *array = cb_data;
 	struct reflog_info *item;
diff --git a/reflog.c b/reflog.c
index b267369..ac87e20 100644
--- a/reflog.c
+++ b/reflog.c
@@ -423,16 +423,13 @@ int should_expire_reflog_ent_verbose(struct object_id *ooid,
 	return expire;
 }
 
-static int push_tip_to_list(const char *refname UNUSED,
-			    const char *referent UNUSED,
-			    const struct object_id *oid,
-			    int flags, void *cb_data)
+static int push_tip_to_list(const struct reference *ref, void *cb_data)
 {
 	struct commit_list **list = cb_data;
 	struct commit *tip_commit;
-	if (flags & REF_ISSYMREF)
+	if (ref->flags & REF_ISSYMREF)
 		return 0;
-	tip_commit = lookup_commit_reference_gently(the_repository, oid, 1);
+	tip_commit = lookup_commit_reference_gently(the_repository, ref->oid, 1);
 	if (!tip_commit)
 		return 0;
 	commit_list_insert(tip_commit, list);
@@ -507,7 +504,8 @@ void reflog_expiry_cleanup(void *cb_data)
 	free_commit_list(cb->mark_list);
 }
 
-int count_reflog_ent(struct object_id *ooid UNUSED,
+int count_reflog_ent(const char *refname UNUSED,
+		     struct object_id *ooid UNUSED,
 		     struct object_id *noid UNUSED,
 		     const char *email UNUSED,
 		     timestamp_t timestamp, int tz UNUSED,
diff --git a/reflog.h b/reflog.h
index 74b3f3c..b996712 100644
--- a/reflog.h
+++ b/reflog.h
@@ -65,7 +65,8 @@ void reflog_expiry_prepare(const char *refname, const struct object_id *oid,
 int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
 			     const char *email, timestamp_t timestamp, int tz,
 			     const char *message, void *cb_data);
-int count_reflog_ent(struct object_id *ooid, struct object_id *noid,
+int count_reflog_ent(const char *refname,
+		     struct object_id *ooid, struct object_id *noid,
 		     const char *email, timestamp_t timestamp, int tz,
 		     const char *message, void *cb_data);
 int should_expire_reflog_ent_verbose(struct object_id *ooid,
diff --git a/refs.c b/refs.c
index 17b4892..5583f6e 100644
--- a/refs.c
+++ b/refs.c
@@ -3,7 +3,6 @@
  */
 
 #define USE_THE_REPOSITORY_VARIABLE
-#define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "git-compat-util.h"
 #include "advice.h"
@@ -32,6 +31,7 @@
 #include "commit.h"
 #include "wildmatch.h"
 #include "ident.h"
+#include "fsck.h"
 
 /*
  * List of all available backends
@@ -323,6 +323,9 @@ int check_refname_format(const char *refname, int flags)
 int refs_fsck(struct ref_store *refs, struct fsck_options *o,
 	      struct worktree *wt)
 {
+	if (o->verbose)
+		fprintf_ln(stderr, _("Checking references consistency"));
+
 	return refs->be->fsck(refs, o, wt);
 }
 
@@ -423,17 +426,19 @@ int refs_ref_exists(struct ref_store *refs, const char *refname)
 					 NULL, NULL);
 }
 
-static int for_each_filter_refs(const char *refname, const char *referent,
-				const struct object_id *oid,
-				int flags, void *data)
+static int for_each_filter_refs(const struct reference *ref, void *data)
 {
 	struct for_each_ref_filter *filter = data;
 
-	if (wildmatch(filter->pattern, refname, 0))
+	if (wildmatch(filter->pattern, ref->name, 0))
 		return 0;
-	if (filter->prefix)
-		skip_prefix(refname, filter->prefix, &refname);
-	return filter->fn(refname, referent, oid, flags, filter->cb_data);
+	if (filter->prefix) {
+		struct reference skipped = *ref;
+		skip_prefix(skipped.name, filter->prefix, &skipped.name);
+		return filter->fn(&skipped, filter->cb_data);
+	} else {
+		return filter->fn(ref, filter->cb_data);
+	}
 }
 
 struct warn_if_dangling_data {
@@ -444,17 +449,15 @@ struct warn_if_dangling_data {
 	int dry_run;
 };
 
-static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED,
-				   const struct object_id *oid UNUSED,
-				   int flags, void *cb_data)
+static int warn_if_dangling_symref(const struct reference *ref, void *cb_data)
 {
 	struct warn_if_dangling_data *d = cb_data;
 	const char *resolves_to, *msg;
 
-	if (!(flags & REF_ISSYMREF))
+	if (!(ref->flags & REF_ISSYMREF))
 		return 0;
 
-	resolves_to = refs_resolve_ref_unsafe(d->refs, refname, 0, NULL, NULL);
+	resolves_to = refs_resolve_ref_unsafe(d->refs, ref->name, 0, NULL, NULL);
 	if (!resolves_to
 	    || !string_list_has_string(d->refnames, resolves_to)) {
 		return 0;
@@ -463,7 +466,7 @@ static int warn_if_dangling_symref(const char *refname, const char *referent UNU
 	msg = d->dry_run
 		? _("%s%s will become dangling after %s is deleted\n")
 		: _("%s%s has become dangling after %s was deleted\n");
-	fprintf(d->fp, msg, d->indent, refname, resolves_to);
+	fprintf(d->fp, msg, d->indent, ref->name, resolves_to);
 	return 0;
 }
 
@@ -504,8 +507,15 @@ int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_da
 	int flag;
 
 	strbuf_addf(&buf, "%sHEAD", get_git_namespace());
-	if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag))
-		ret = fn(buf.buf, NULL, &oid, flag, cb_data);
+	if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag)) {
+		struct reference ref = {
+			.name = buf.buf,
+			.oid = &oid,
+			.flags = flag,
+		};
+
+		ret = fn(&ref, cb_data);
+	}
 	strbuf_release(&buf);
 
 	return ret;
@@ -627,10 +637,12 @@ void expand_ref_prefix(struct strvec *prefixes, const char *prefix)
 		strvec_pushf(prefixes, *p, len, prefix);
 }
 
+#ifndef WITH_BREAKING_CHANGES
 static const char default_branch_name_advice[] = N_(
 "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"
+"will change to \"main\" in Git 3.0. To configure the initial branch name\n"
+"to use in all of your new repositories, which will suppress this warning,\n"
+"call:\n"
 "\n"
 "\tgit config --global init.defaultBranch <name>\n"
 "\n"
@@ -639,6 +651,15 @@ static const char default_branch_name_advice[] = N_(
 "\n"
 "\tgit branch -m <name>\n"
 );
+#else
+static const char default_branch_name_advice[] = N_(
+"Using '%s' as the name for the initial branch since Git 3.0.\n"
+"If you expected Git to create 'master', the just-created\n"
+"branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m master\n"
+);
+#endif /* WITH_BREAKING_CHANGES */
 
 char *repo_default_branch_name(struct repository *r, int quiet)
 {
@@ -649,11 +670,15 @@ char *repo_default_branch_name(struct repository *r, int quiet)
 
 	if (env && *env)
 		ret = xstrdup(env);
-	else if (repo_config_get_string(r, config_key, &ret) < 0)
+	if (!ret && repo_config_get_string(r, config_key, &ret) < 0)
 		die(_("could not retrieve `%s`"), config_display_key);
 
 	if (!ret) {
+#ifdef WITH_BREAKING_CHANGES
+		ret = xstrdup("main");
+#else
 		ret = xstrdup("master");
+#endif /* WITH_BREAKING_CHANGES */
 		if (!quiet)
 			advise_if_enabled(ADVICE_DEFAULT_BRANCH_NAME,
 					  _(default_branch_name_advice), ret);
@@ -1022,7 +1047,6 @@ int is_branch(const char *refname)
 }
 
 struct read_ref_at_cb {
-	const char *refname;
 	timestamp_t at_time;
 	int cnt;
 	int reccnt;
@@ -1052,7 +1076,8 @@ static void set_read_ref_cutoffs(struct read_ref_at_cb *cb,
 		*cb->cutoff_cnt = cb->reccnt;
 }
 
-static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
+static int read_ref_at_ent(const char *refname,
+			   struct object_id *ooid, struct object_id *noid,
 			   const char *email UNUSED,
 			   timestamp_t timestamp, int tz,
 			   const char *message, void *cb_data)
@@ -1072,14 +1097,13 @@ static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
 			oidcpy(cb->oid, noid);
 			if (!oideq(&cb->ooid, noid))
 				warning(_("log for ref %s has gap after %s"),
-					cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
+					refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
 		}
 		else if (cb->date == cb->at_time)
 			oidcpy(cb->oid, noid);
 		else if (!oideq(noid, cb->oid))
 			warning(_("log for ref %s unexpectedly ended on %s"),
-				cb->refname, show_date(cb->date, cb->tz,
-						       DATE_MODE(RFC2822)));
+				refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
 		cb->reccnt++;
 		oidcpy(&cb->ooid, ooid);
 		oidcpy(&cb->noid, noid);
@@ -1094,7 +1118,8 @@ static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
 	return 0;
 }
 
-static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
+static int read_ref_at_ent_oldest(const char *refname UNUSED,
+				  struct object_id *ooid, struct object_id *noid,
 				  const char *email UNUSED,
 				  timestamp_t timestamp, int tz,
 				  const char *message, void *cb_data)
@@ -1117,7 +1142,6 @@ int read_ref_at(struct ref_store *refs, const char *refname,
 	struct read_ref_at_cb cb;
 
 	memset(&cb, 0, sizeof(cb));
-	cb.refname = refname;
 	cb.at_time = at_time;
 	cb.cnt = cnt;
 	cb.msg = msg;
@@ -1696,8 +1720,6 @@ const char *find_descendant_ref(const char *dirname,
 				const struct string_list *extras,
 				const struct string_list *skip)
 {
-	int pos;
-
 	if (!extras)
 		return NULL;
 
@@ -1707,7 +1729,7 @@ const char *find_descendant_ref(const char *dirname,
 	 * with dirname (remember, dirname includes the trailing
 	 * slash) and is not in skip, then we have a conflict.
 	 */
-	for (pos = string_list_find_insert_index(extras, dirname, 0);
+	for (size_t pos = string_list_find_insert_index(extras, dirname, NULL);
 	     pos < extras->nr; pos++) {
 		const char *extra_refname = extras->items[pos].string;
 
@@ -1726,8 +1748,15 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 	int flag;
 
 	if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
-				    &oid, &flag))
-		return fn("HEAD", NULL, &oid, flag, cb_data);
+				    &oid, &flag)) {
+		struct reference ref = {
+			.name = "HEAD",
+			.oid = &oid,
+			.flags = flag,
+		};
+
+		return fn(&ref, cb_data);
+	}
 
 	return 0;
 }
@@ -1847,7 +1876,13 @@ int refs_for_each_namespaced_ref(struct ref_store *refs,
 
 int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(refs, "", NULL, fn, 0,
+	return refs_for_each_rawref_in(refs, "", fn, cb_data);
+}
+
+int refs_for_each_rawref_in(struct ref_store *refs, const char *prefix,
+			    each_ref_fn fn, void *cb_data)
+{
+	return do_for_each_ref(refs, prefix, NULL, fn, 0,
 			       DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 }
 
@@ -2278,20 +2313,28 @@ void base_ref_store_init(struct ref_store *refs, struct repository *repo,
 	refs->gitdir = xstrdup(path);
 }
 
-/* backend functions */
-int refs_pack_refs(struct ref_store *refs, struct pack_refs_opts *opts)
+int refs_optimize(struct ref_store *refs, struct refs_optimize_opts *opts)
 {
-	return refs->be->pack_refs(refs, opts);
+	return refs->be->optimize(refs, opts);
 }
 
-int peel_iterated_oid(struct repository *r, const struct object_id *base, struct object_id *peeled)
+int refs_optimize_required(struct ref_store *refs,
+			   struct refs_optimize_opts *opts,
+			   bool *required)
 {
-	if (current_ref_iter &&
-	    (current_ref_iter->oid == base ||
-	     oideq(current_ref_iter->oid, base)))
-		return ref_iterator_peel(current_ref_iter, peeled);
+	return refs->be->optimize_required(refs, opts, required);
+}
 
-	return peel_object(r, base, peeled) ? -1 : 0;
+int reference_get_peeled_oid(struct repository *repo,
+			     const struct reference *ref,
+			     struct object_id *peeled_oid)
+{
+	if (ref->peeled_oid) {
+		oidcpy(peeled_oid, ref->peeled_oid);
+		return 0;
+	}
+
+	return peel_object(repo, ref->oid, peeled_oid, 0) ? -1 : 0;
 }
 
 int refs_update_symref(struct ref_store *refs, const char *ref,
@@ -2385,7 +2428,7 @@ static int run_transaction_hook(struct ref_transaction *transaction,
 	struct child_process proc = CHILD_PROCESS_INIT;
 	struct strbuf buf = STRBUF_INIT;
 	const char *hook;
-	int ret = 0, i;
+	int ret = 0;
 
 	hook = find_hook(transaction->ref_store->repo, "reference-transaction");
 	if (!hook)
@@ -2402,7 +2445,7 @@ static int run_transaction_hook(struct ref_transaction *transaction,
 
 	sigchain_push(SIGPIPE, SIG_IGN);
 
-	for (i = 0; i < transaction->nr; i++) {
+	for (size_t i = 0; i < transaction->nr; i++) {
 		struct ref_update *update = transaction->updates[i];
 
 		if (update->flags & REF_LOG_ONLY)
@@ -2663,7 +2706,7 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs
 
 			while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
 				if (skip &&
-				    string_list_has_string(skip, iter->refname))
+				    string_list_has_string(skip, iter->ref.name))
 					continue;
 
 				if (transaction && ref_transaction_maybe_set_rejected(
@@ -2672,7 +2715,7 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs
 					continue;
 
 				strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
-					    iter->refname, refname);
+					    iter->ref.name, refname);
 				goto cleanup;
 			}
 
@@ -2727,14 +2770,10 @@ struct do_for_each_reflog_help {
 	void *cb_data;
 };
 
-static int do_for_each_reflog_helper(const char *refname,
-				     const char *referent UNUSED,
-				     const struct object_id *oid UNUSED,
-				     int flags UNUSED,
-				     void *cb_data)
+static int do_for_each_reflog_helper(const struct reference *ref, void *cb_data)
 {
 	struct do_for_each_reflog_help *hp = cb_data;
-	return hp->fn(refname, hp->cb_data);
+	return hp->fn(ref->name, hp->cb_data);
 }
 
 int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_data)
@@ -2795,9 +2834,7 @@ void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
 					    ref_transaction_for_each_queued_update_fn cb,
 					    void *cb_data)
 {
-	int i;
-
-	for (i = 0; i < transaction->nr; i++) {
+	for (size_t i = 0; i < transaction->nr; i++) {
 		struct ref_update *update = transaction->updates[i];
 
 		cb(update->refname,
@@ -2949,27 +2986,27 @@ struct migration_data {
 	struct ref_transaction *transaction;
 	struct strbuf *errbuf;
 	struct strbuf sb, name, mail;
+	uint64_t index;
 };
 
-static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			   int flags, void *cb_data)
+static int migrate_one_ref(const struct reference *ref, void *cb_data)
 {
 	struct migration_data *data = cb_data;
 	struct strbuf symref_target = STRBUF_INIT;
 	int ret;
 
-	if (flags & REF_ISSYMREF) {
-		ret = refs_read_symbolic_ref(data->old_refs, refname, &symref_target);
+	if (ref->flags & REF_ISSYMREF) {
+		ret = refs_read_symbolic_ref(data->old_refs, ref->name, &symref_target);
 		if (ret < 0)
 			goto done;
 
-		ret = ref_transaction_update(data->transaction, refname, NULL, null_oid(the_hash_algo),
+		ret = ref_transaction_update(data->transaction, ref->name, NULL, null_oid(the_hash_algo),
 					     symref_target.buf, NULL,
 					     REF_SKIP_CREATE_REFLOG | REF_NO_DEREF, NULL, data->errbuf);
 		if (ret < 0)
 			goto done;
 	} else {
-		ret = ref_transaction_create(data->transaction, refname, oid, NULL,
+		ret = ref_transaction_create(data->transaction, ref->name, ref->oid, NULL,
 					     REF_SKIP_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION,
 					     NULL, data->errbuf);
 		if (ret < 0)
@@ -2981,22 +3018,14 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con
 	return ret;
 }
 
-struct reflog_migration_data {
-	uint64_t index;
-	const char *refname;
-	struct ref_store *old_refs;
-	struct ref_transaction *transaction;
-	struct strbuf *errbuf;
-	struct strbuf *sb, *name, *mail;
-};
-
-static int migrate_one_reflog_entry(struct object_id *old_oid,
+static int migrate_one_reflog_entry(const char *refname,
+				    struct object_id *old_oid,
 				    struct object_id *new_oid,
 				    const char *committer,
 				    timestamp_t timestamp, int tz,
 				    const char *msg, void *cb_data)
 {
-	struct reflog_migration_data *data = cb_data;
+	struct migration_data *data = cb_data;
 	struct ident_split ident;
 	const char *date;
 	int ret;
@@ -3004,17 +3033,17 @@ static int migrate_one_reflog_entry(struct object_id *old_oid,
 	if (split_ident_line(&ident, committer, strlen(committer)) < 0)
 		return -1;
 
-	strbuf_reset(data->name);
-	strbuf_add(data->name, ident.name_begin, ident.name_end - ident.name_begin);
-	strbuf_reset(data->mail);
-	strbuf_add(data->mail, ident.mail_begin, ident.mail_end - ident.mail_begin);
+	strbuf_reset(&data->name);
+	strbuf_add(&data->name, ident.name_begin, ident.name_end - ident.name_begin);
+	strbuf_reset(&data->mail);
+	strbuf_add(&data->mail, ident.mail_begin, ident.mail_end - ident.mail_begin);
 
 	date = show_date(timestamp, tz, DATE_MODE(NORMAL));
-	strbuf_reset(data->sb);
-	strbuf_addstr(data->sb, fmt_ident(data->name->buf, data->mail->buf, WANT_BLANK_IDENT, date, 0));
+	strbuf_reset(&data->sb);
+	strbuf_addstr(&data->sb, fmt_ident(data->name.buf, data->mail.buf, WANT_BLANK_IDENT, date, 0));
 
-	ret = ref_transaction_update_reflog(data->transaction, data->refname,
-					    new_oid, old_oid, data->sb->buf,
+	ret = ref_transaction_update_reflog(data->transaction, refname,
+					    new_oid, old_oid, data->sb.buf,
 					    msg, data->index++, data->errbuf);
 	return ret;
 }
@@ -3022,18 +3051,8 @@ static int migrate_one_reflog_entry(struct object_id *old_oid,
 static int migrate_one_reflog(const char *refname, void *cb_data)
 {
 	struct migration_data *migration_data = cb_data;
-	struct reflog_migration_data data = {
-		.refname = refname,
-		.old_refs = migration_data->old_refs,
-		.transaction = migration_data->transaction,
-		.errbuf = migration_data->errbuf,
-		.sb = &migration_data->sb,
-		.name = &migration_data->name,
-		.mail = &migration_data->mail,
-	};
-
 	return refs_for_each_reflog_ent(migration_data->old_refs, refname,
-					migrate_one_reflog_entry, &data);
+					migrate_one_reflog_entry, migration_data);
 }
 
 static int move_files(const char *from_path, const char *to_path, struct strbuf *errbuf)
diff --git a/refs.h b/refs.h
index 0d24b64..d9051bb 100644
--- a/refs.h
+++ b/refs.h
@@ -333,36 +333,74 @@ struct ref_transaction;
  * stored in ref_iterator::flags. Other bits are for internal use
  * only:
  */
+enum reference_status {
+	/* Reference is a symbolic reference. */
+	REF_ISSYMREF = (1 << 0),
 
-/* Reference is a symbolic reference. */
-#define REF_ISSYMREF 0x01
+	/* Reference is a packed reference. */
+	REF_ISPACKED = (1 << 1),
 
-/* Reference is a packed reference. */
-#define REF_ISPACKED 0x02
+	/*
+	 * Reference cannot be resolved to an object name: dangling symbolic
+	 * reference (directly or indirectly), corrupt reference file,
+	 * reference exists but name is bad, or symbolic reference refers to
+	 * ill-formatted reference name.
+	 */
+	REF_ISBROKEN = (1 << 2),
+
+	/*
+	 * Reference name is not well formed.
+	 *
+	 * See git-check-ref-format(1) for the definition of well formed ref names.
+	 */
+	REF_BAD_NAME = (1 << 3),
+};
+
+/* A reference passed to `for_each_ref()`-style callbacks. */
+struct reference {
+	/* The fully-qualified name of the reference. */
+	const char *name;
+
+	/* The target of a symbolic ref. `NULL` for direct references. */
+	const char *target;
+
+	/*
+	 * The object ID of a reference. Either the direct object ID or the
+	 * resolved object ID in the case of a symbolic ref. May be the zero
+	 * object ID in case the symbolic ref cannot be resolved.
+	 */
+	const struct object_id *oid;
+
+	/*
+	 * An optional peeled object ID. This field _may_ be set for tags in
+	 * case the peeled value is present in the backend. Please refer to
+	 * `reference_get_peeled_oid()`.
+	 */
+	const struct object_id *peeled_oid;
+
+	/* A bitfield of `enum reference_status` flags. */
+	unsigned flags;
+};
 
 /*
- * Reference cannot be resolved to an object name: dangling symbolic
- * reference (directly or indirectly), corrupt reference file,
- * reference exists but name is bad, or symbolic reference refers to
- * ill-formatted reference name.
- */
-#define REF_ISBROKEN 0x04
-
-/*
- * Reference name is not well formed.
+ * Peel the tag to a non-tag commit. If present, this uses the peeled object ID
+ * exposed by the reference backend. Otherwise, the object is peeled via the
+ * object database, which is less efficient.
  *
- * See git-check-ref-format(1) for the definition of well formed ref names.
+ * Return `0` if the reference could be peeled, a negative error code
+ * otherwise.
  */
-#define REF_BAD_NAME 0x08
+int reference_get_peeled_oid(struct repository *repo,
+			     const struct reference *ref,
+			     struct object_id *peeled_oid);
 
 /*
  * The signature for the callback function for the for_each_*()
- * functions below.  The memory pointed to by the refname and oid
- * arguments is only guaranteed to be valid for the duration of a
+ * functions below.  The memory pointed to by the `struct reference`
+ * argument is only guaranteed to be valid for the duration of a
  * single callback invocation.
  */
-typedef int each_ref_fn(const char *refname, const char *referent,
-			const struct object_id *oid, int flags, void *cb_data);
+typedef int each_ref_fn(const struct reference *ref, void *cb_data);
 
 /*
  * The following functions invoke the specified callback function for
@@ -430,6 +468,8 @@ int refs_for_each_namespaced_ref(struct ref_store *refs,
 
 /* can be used to learn about broken ref and symref */
 int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data);
+int refs_for_each_rawref_in(struct ref_store *refs, const char *prefix,
+			    each_ref_fn fn, void *cb_data);
 
 /*
  * Iterates over all refs including root refs, i.e. pseudorefs and HEAD.
@@ -459,26 +499,33 @@ void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp,
 				const struct string_list *refnames);
 
 /*
- * Flags for controlling behaviour of pack_refs()
- * PACK_REFS_PRUNE: Prune loose refs after packing
- * PACK_REFS_AUTO: Pack refs on a best effort basis. The heuristics and end
- *                 result are decided by the ref backend. Backends may ignore
- *                 this flag and fall back to a normal repack.
+ * Flags for controlling behaviour of refs_optimize()
+ * REFS_OPTIMIZE_PRUNE: Prune loose refs after packing
+ * REFS_OPTIMIZE_AUTO: Pack refs on a best effort basis. The heuristics and end
+ *                     result are decided by the ref backend. Backends may ignore
+ *                     this flag and fall back to a normal repack.
  */
-#define PACK_REFS_PRUNE (1 << 0)
-#define PACK_REFS_AUTO  (1 << 1)
+#define REFS_OPTIMIZE_PRUNE (1 << 0)
+#define REFS_OPTIMIZE_AUTO  (1 << 1)
 
-struct pack_refs_opts {
+struct refs_optimize_opts {
 	unsigned int flags;
 	struct ref_exclusions *exclusions;
 	struct string_list *includes;
 };
 
 /*
- * Write a packed-refs file for the current repository.
- * flags: Combination of the above PACK_REFS_* flags.
+ * Optimize the ref store. The exact behavior is up to the backend.
+ * For the files backend, this is equivalent to packing refs.
  */
-int refs_pack_refs(struct ref_store *refs, struct pack_refs_opts *opts);
+int refs_optimize(struct ref_store *refs, struct refs_optimize_opts *opts);
+
+/*
+ * Check if refs backend can be optimized by calling 'refs_optimize'.
+ */
+int refs_optimize_required(struct ref_store *ref_store,
+			   struct refs_optimize_opts *opts,
+			   bool *required);
 
 /*
  * Setup reflog before using. Fill in err and return -1 on failure.
@@ -560,10 +607,13 @@ int refs_delete_reflog(struct ref_store *refs, const char *refname);
  * The cb_data is a caller-supplied pointer given to the iterator
  * functions.
  */
-typedef int each_reflog_ent_fn(
-		struct object_id *old_oid, struct object_id *new_oid,
-		const char *committer, timestamp_t timestamp,
-		int tz, const char *msg, void *cb_data);
+typedef int each_reflog_ent_fn(const char *refname,
+			       struct object_id *old_oid,
+			       struct object_id *new_oid,
+			       const char *committer,
+			       timestamp_t timestamp,
+			       int tz, const char *msg,
+			       void *cb_data);
 
 /* Iterate over reflog entries in the log for `refname`. */
 
@@ -1240,10 +1290,6 @@ int repo_migrate_ref_storage_format(struct repository *repo,
  * to the next entry, ref_iterator_advance() aborts the iteration,
  * frees the ref_iterator, and returns ITER_ERROR.
  *
- * The reference currently being looked at can be peeled by calling
- * ref_iterator_peel(). This function is often faster than peel_ref(),
- * so it should be preferred when iterating over references.
- *
  * Putting it all together, a typical iteration looks like this:
  *
  *     int ok;
@@ -1258,9 +1304,6 @@ int repo_migrate_ref_storage_format(struct repository *repo,
  *             // Access information about the current reference:
  *             if (!(iter->flags & REF_ISSYMREF))
  *                     printf("%s is %s\n", iter->refname, oid_to_hex(iter->oid));
- *
- *             // If you need to peel the reference:
- *             ref_iterator_peel(iter, &oid);
  *     }
  *
  *     if (ok != ITER_DONE)
@@ -1351,13 +1394,6 @@ enum ref_iterator_seek_flag {
 int ref_iterator_seek(struct ref_iterator *ref_iterator, const char *refname,
 		      unsigned int flags);
 
-/*
- * If possible, peel the reference currently being viewed by the
- * iterator. Return 0 on success.
- */
-int ref_iterator_peel(struct ref_iterator *ref_iterator,
-		      struct object_id *peeled);
-
 /* Free the reference iterator and any associated resources. */
 void ref_iterator_free(struct ref_iterator *ref_iterator);
 
diff --git a/refs/debug.c b/refs/debug.c
index da300ef..3e31228 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -1,7 +1,6 @@
 #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);
@@ -48,6 +47,14 @@ static int debug_create_on_disk(struct ref_store *refs, int flags, struct strbuf
 	return res;
 }
 
+static int debug_remove_on_disk(struct ref_store *refs, struct strbuf *err)
+{
+	struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
+	int res = drefs->refs->be->remove_on_disk(drefs->refs, err);
+	trace_printf_key(&trace_refs, "remove_on_disk: %d\n", res);
+	return res;
+}
+
 static int debug_transaction_prepare(struct ref_store *refs,
 				     struct ref_transaction *transaction,
 				     struct strbuf *err)
@@ -117,11 +124,22 @@ static int debug_transaction_abort(struct ref_store *refs,
 	return res;
 }
 
-static int debug_pack_refs(struct ref_store *ref_store, struct pack_refs_opts *opts)
+static int debug_optimize(struct ref_store *ref_store, struct refs_optimize_opts *opts)
 {
 	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = drefs->refs->be->pack_refs(drefs->refs, opts);
-	trace_printf_key(&trace_refs, "pack_refs: %d\n", res);
+	int res = drefs->refs->be->optimize(drefs->refs, opts);
+	trace_printf_key(&trace_refs, "optimize: %d\n", res);
+	return res;
+}
+
+static int debug_optimize_required(struct ref_store *ref_store,
+				   struct refs_optimize_opts *opts,
+				   bool *required)
+{
+	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
+	int res = drefs->refs->be->optimize_required(drefs->refs, opts, required);
+	trace_printf_key(&trace_refs, "optimize_required: %s, res: %d\n",
+			 required ? "yes" : "no", res);
 	return res;
 }
 
@@ -161,11 +179,9 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator)
 		trace_printf_key(&trace_refs, "iterator_advance: (%d)\n", res);
 	else
 		trace_printf_key(&trace_refs, "iterator_advance: %s (0)\n",
-			diter->iter->refname);
+			diter->iter->ref.name);
 
-	diter->base.refname = diter->iter->refname;
-	diter->base.oid = diter->iter->oid;
-	diter->base.flags = diter->iter->flags;
+	diter->base.ref = diter->iter->ref;
 	return res;
 }
 
@@ -180,16 +196,6 @@ static int debug_ref_iterator_seek(struct ref_iterator *ref_iterator,
 	return res;
 }
 
-static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	struct debug_ref_iterator *diter =
-		(struct debug_ref_iterator *)ref_iterator;
-	int res = diter->iter->vtable->peel(diter->iter, peeled);
-	trace_printf_key(&trace_refs, "iterator_peel: %s: %d\n", diter->iter->refname, res);
-	return res;
-}
-
 static void debug_ref_iterator_release(struct ref_iterator *ref_iterator)
 {
 	struct debug_ref_iterator *diter =
@@ -201,7 +207,6 @@ static void debug_ref_iterator_release(struct ref_iterator *ref_iterator)
 static struct ref_iterator_vtable debug_ref_iterator_vtable = {
 	.advance = debug_ref_iterator_advance,
 	.seek = debug_ref_iterator_seek,
-	.peel = debug_ref_iterator_peel,
 	.release = debug_ref_iterator_release,
 };
 
@@ -277,7 +282,8 @@ struct debug_reflog {
 	void *cb_data;
 };
 
-static int debug_print_reflog_ent(struct object_id *old_oid,
+static int debug_print_reflog_ent(const char *refname,
+				  struct object_id *old_oid,
 				  struct object_id *new_oid,
 				  const char *committer, timestamp_t timestamp,
 				  int tz, const char *msg, void *cb_data)
@@ -292,7 +298,7 @@ static int debug_print_reflog_ent(struct object_id *old_oid,
 	if (new_oid)
 		oid_to_hex_r(n, new_oid);
 
-	ret = dbg->fn(old_oid, new_oid, committer, timestamp, tz, msg,
+	ret = dbg->fn(refname, old_oid, new_oid, committer, timestamp, tz, msg,
 		      dbg->cb_data);
 	trace_printf_key(&trace_refs,
 			 "reflog_ent %s (ret %d): %s -> %s, %s %ld \"%.*s\"\n",
@@ -432,6 +438,7 @@ struct ref_storage_be refs_be_debug = {
 	.init = NULL,
 	.release = debug_release,
 	.create_on_disk = debug_create_on_disk,
+	.remove_on_disk = debug_remove_on_disk,
 
 	/*
 	 * None of these should be NULL. If the "files" backend (in
@@ -443,7 +450,9 @@ struct ref_storage_be refs_be_debug = {
 	.transaction_finish = debug_transaction_finish,
 	.transaction_abort = debug_transaction_abort,
 
-	.pack_refs = debug_pack_refs,
+	.optimize = debug_optimize,
+	.optimize_required = debug_optimize_required,
+
 	.rename_ref = debug_rename_ref,
 	.copy_ref = debug_copy_ref,
 
diff --git a/refs/files-backend.c b/refs/files-backend.c
index b2de84f..6f6f76a 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -20,7 +20,6 @@
 #include "../dir-iterator.h"
 #include "../lockfile.h"
 #include "../object.h"
-#include "../object-file.h"
 #include "../path.h"
 #include "../dir.h"
 #include "../chdir-notify.h"
@@ -962,26 +961,23 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
 
 	while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
 		if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
-		    parse_worktree_ref(iter->iter0->refname, NULL, NULL,
+		    parse_worktree_ref(iter->iter0->ref.name, NULL, NULL,
 				       NULL) != REF_WORKTREE_CURRENT)
 			continue;
 
 		if ((iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS) &&
-		    (iter->iter0->flags & REF_ISSYMREF) &&
-		    (iter->iter0->flags & REF_ISBROKEN))
+		    (iter->iter0->ref.flags & REF_ISSYMREF) &&
+		    (iter->iter0->ref.flags & REF_ISBROKEN))
 			continue;
 
 		if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
-		    !ref_resolves_to_object(iter->iter0->refname,
+		    !ref_resolves_to_object(iter->iter0->ref.name,
 					    iter->repo,
-					    iter->iter0->oid,
-					    iter->iter0->flags))
+					    iter->iter0->ref.oid,
+					    iter->iter0->ref.flags))
 			continue;
 
-		iter->base.refname = iter->iter0->refname;
-		iter->base.oid = iter->iter0->oid;
-		iter->base.flags = iter->iter0->flags;
-		iter->base.referent = iter->iter0->referent;
+		iter->base.ref = iter->iter0->ref;
 
 		return ITER_OK;
 	}
@@ -997,15 +993,6 @@ static int files_ref_iterator_seek(struct ref_iterator *ref_iterator,
 	return ref_iterator_seek(iter->iter0, refname, flags);
 }
 
-static int files_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	struct files_ref_iterator *iter =
-		(struct files_ref_iterator *)ref_iterator;
-
-	return ref_iterator_peel(iter->iter0, peeled);
-}
-
 static void files_ref_iterator_release(struct ref_iterator *ref_iterator)
 {
 	struct files_ref_iterator *iter =
@@ -1016,7 +1003,6 @@ static void files_ref_iterator_release(struct ref_iterator *ref_iterator)
 static struct ref_iterator_vtable files_ref_iterator_vtable = {
 	.advance = files_ref_iterator_advance,
 	.seek = files_ref_iterator_seek,
-	.peel = files_ref_iterator_peel,
 	.release = files_ref_iterator_release,
 };
 
@@ -1368,37 +1354,36 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune **refs_
  * Return true if the specified reference should be packed.
  */
 static int should_pack_ref(struct files_ref_store *refs,
-			   const char *refname,
-			   const struct object_id *oid, unsigned int ref_flags,
-			   struct pack_refs_opts *opts)
+			   const struct reference *ref,
+			   struct refs_optimize_opts *opts)
 {
 	struct string_list_item *item;
 
 	/* Do not pack per-worktree refs: */
-	if (parse_worktree_ref(refname, NULL, NULL, NULL) !=
+	if (parse_worktree_ref(ref->name, NULL, NULL, NULL) !=
 	    REF_WORKTREE_SHARED)
 		return 0;
 
 	/* Do not pack symbolic refs: */
-	if (ref_flags & REF_ISSYMREF)
+	if (ref->flags & REF_ISSYMREF)
 		return 0;
 
 	/* Do not pack broken refs: */
-	if (!ref_resolves_to_object(refname, refs->base.repo, oid, ref_flags))
+	if (!ref_resolves_to_object(ref->name, refs->base.repo, ref->oid, ref->flags))
 		return 0;
 
-	if (ref_excluded(opts->exclusions, refname))
+	if (ref_excluded(opts->exclusions, ref->name))
 		return 0;
 
 	for_each_string_list_item(item, opts->includes)
-		if (!wildmatch(item->string, refname, 0))
+		if (!wildmatch(item->string, ref->name, 0))
 			return 1;
 
 	return 0;
 }
 
 static int should_pack_refs(struct files_ref_store *refs,
-			    struct pack_refs_opts *opts)
+			    struct refs_optimize_opts *opts)
 {
 	struct ref_iterator *iter;
 	size_t packed_size;
@@ -1406,7 +1391,7 @@ static int should_pack_refs(struct files_ref_store *refs,
 	size_t limit;
 	int ret;
 
-	if (!(opts->flags & PACK_REFS_AUTO))
+	if (!(opts->flags & REFS_OPTIMIZE_AUTO))
 		return 1;
 
 	ret = packed_refs_size(refs->packed_ref_store, &packed_size);
@@ -1444,8 +1429,7 @@ static int should_pack_refs(struct files_ref_store *refs,
 	iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, 0), NULL,
 					refs->base.repo, 0);
 	while ((ret = ref_iterator_advance(iter)) == ITER_OK) {
-		if (should_pack_ref(refs, iter->refname, iter->oid,
-				    iter->flags, opts))
+		if (should_pack_ref(refs, &iter->ref, opts))
 			refcount++;
 		if (refcount >= limit) {
 			ref_iterator_free(iter);
@@ -1460,8 +1444,8 @@ static int should_pack_refs(struct files_ref_store *refs,
 	return 0;
 }
 
-static int files_pack_refs(struct ref_store *ref_store,
-			   struct pack_refs_opts *opts)
+static int files_optimize(struct ref_store *ref_store,
+			  struct refs_optimize_opts *opts)
 {
 	struct files_ref_store *refs =
 		files_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB,
@@ -1490,24 +1474,24 @@ static int files_pack_refs(struct ref_store *ref_store,
 		 * in the packed ref cache. If the reference should be
 		 * pruned, also add it to refs_to_prune.
 		 */
-		if (!should_pack_ref(refs, iter->refname, iter->oid, iter->flags, opts))
+		if (!should_pack_ref(refs, &iter->ref, opts))
 			continue;
 
 		/*
 		 * Add a reference creation for this reference to the
 		 * packed-refs transaction:
 		 */
-		if (ref_transaction_update(transaction, iter->refname,
-					   iter->oid, NULL, NULL, NULL,
+		if (ref_transaction_update(transaction, iter->ref.name,
+					   iter->ref.oid, NULL, NULL, NULL,
 					   REF_NO_DEREF, NULL, &err))
 			die("failure preparing to create packed reference %s: %s",
-			    iter->refname, err.buf);
+			    iter->ref.name, err.buf);
 
 		/* Schedule the loose reference for pruning if requested. */
-		if ((opts->flags & PACK_REFS_PRUNE)) {
+		if ((opts->flags & REFS_OPTIMIZE_PRUNE)) {
 			struct ref_to_prune *n;
-			FLEX_ALLOC_STR(n, name, iter->refname);
-			oidcpy(&n->oid, iter->oid);
+			FLEX_ALLOC_STR(n, name, iter->ref.name);
+			oidcpy(&n->oid, iter->ref.oid);
 			n->next = refs_to_prune;
 			refs_to_prune = n;
 		}
@@ -1528,6 +1512,16 @@ static int files_pack_refs(struct ref_store *ref_store,
 	return 0;
 }
 
+static int files_optimize_required(struct ref_store *ref_store,
+				   struct refs_optimize_opts *opts,
+				   bool *required)
+{
+	struct files_ref_store *refs = files_downcast(ref_store, REF_STORE_READ,
+						      "optimize_required");
+	*required = should_pack_refs(refs, opts);
+	return 0;
+}
+
 /*
  * People using contrib's git-new-workdir have .git/logs/refs ->
  * /some/other/path/.git/logs/refs, and that may live on another device.
@@ -2105,20 +2099,35 @@ static int commit_ref_update(struct files_ref_store *refs,
 	return 0;
 }
 
-#ifdef NO_SYMLINK_HEAD
+#if defined(NO_SYMLINK_HEAD) || defined(WITH_BREAKING_CHANGES)
 #define create_ref_symlink(a, b) (-1)
 #else
 static int create_ref_symlink(struct ref_lock *lock, const char *target)
 {
+	static int warn_once = 1;
+	char *ref_path;
 	int ret = -1;
 
-	char *ref_path = get_locked_file_path(&lock->lk);
+	ref_path = get_locked_file_path(&lock->lk);
 	unlink(ref_path);
 	ret = symlink(target, ref_path);
 	free(ref_path);
 
 	if (ret)
 		fprintf(stderr, "no symlink - falling back to symbolic ref\n");
+
+	if (warn_once)
+		warning(_("'core.preferSymlinkRefs=true' is nominated for removal.\n"
+			  "hint: The use of symbolic links for symbolic refs is deprecated\n"
+			  "hint: and will be removed in Git 3.0. The configuration that\n"
+			  "hint: tells Git to use them is thus going away. You can unset\n"
+			  "hint: it with:\n"
+			  "hint:\n"
+			  "hint:\tgit config unset core.preferSymlinkRefs\n"
+			  "hint:\n"
+			  "hint: Git will then use the textual symref format instead."));
+	warn_once = 0;
+
 	return ret;
 }
 #endif
@@ -2170,7 +2179,9 @@ static int files_delete_reflog(struct ref_store *ref_store,
 	return ret;
 }
 
-static int show_one_reflog_ent(struct files_ref_store *refs, struct strbuf *sb,
+static int show_one_reflog_ent(struct files_ref_store *refs,
+			       const char *refname,
+			       struct strbuf *sb,
 			       each_reflog_ent_fn fn, void *cb_data)
 {
 	struct object_id ooid, noid;
@@ -2197,7 +2208,7 @@ static int show_one_reflog_ent(struct files_ref_store *refs, struct strbuf *sb,
 		message += 6;
 	else
 		message += 7;
-	return fn(&ooid, &noid, p, timestamp, tz, message, cb_data);
+	return fn(refname, &ooid, &noid, p, timestamp, tz, message, cb_data);
 }
 
 static char *find_beginning_of_line(char *bob, char *scan)
@@ -2281,7 +2292,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,
 				strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1));
 				scanp = bp;
 				endp = bp + 1;
-				ret = show_one_reflog_ent(refs, &sb, fn, cb_data);
+				ret = show_one_reflog_ent(refs, refname, &sb, fn, cb_data);
 				strbuf_reset(&sb);
 				if (ret)
 					break;
@@ -2293,7 +2304,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,
 				 * Process it, and we can end the loop.
 				 */
 				strbuf_splice(&sb, 0, 0, buf, endp - buf);
-				ret = show_one_reflog_ent(refs, &sb, fn, cb_data);
+				ret = show_one_reflog_ent(refs, refname, &sb, fn, cb_data);
 				strbuf_reset(&sb);
 				break;
 			}
@@ -2343,7 +2354,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,
 		return -1;
 
 	while (!ret && !strbuf_getwholeline(&sb, logfp, '\n'))
-		ret = show_one_reflog_ent(refs, &sb, fn, cb_data);
+		ret = show_one_reflog_ent(refs, refname, &sb, fn, cb_data);
 	fclose(logfp);
 	strbuf_release(&sb);
 	return ret;
@@ -2369,7 +2380,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
 					 REFNAME_ALLOW_ONELEVEL))
 			continue;
 
-		iter->base.refname = diter->relative_path;
+		iter->base.ref.name = diter->relative_path;
 		return ITER_OK;
 	}
 
@@ -2383,12 +2394,6 @@ static int files_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
 	BUG("ref_iterator_seek() called for reflog_iterator");
 }
 
-static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
-				      struct object_id *peeled UNUSED)
-{
-	BUG("ref_iterator_peel() called for reflog_iterator");
-}
-
 static void files_reflog_iterator_release(struct ref_iterator *ref_iterator)
 {
 	struct files_reflog_iterator *iter =
@@ -2399,7 +2404,6 @@ static void files_reflog_iterator_release(struct ref_iterator *ref_iterator)
 static struct ref_iterator_vtable files_reflog_iterator_vtable = {
 	.advance = files_reflog_iterator_advance,
 	.seek = files_reflog_iterator_seek,
-	.peel = files_reflog_iterator_peel,
 	.release = files_reflog_iterator_release,
 };
 
@@ -2568,13 +2572,37 @@ static enum ref_transaction_error split_symref_update(struct ref_update *update,
  */
 static enum ref_transaction_error check_old_oid(struct ref_update *update,
 						struct object_id *oid,
+						struct strbuf *referent,
 						struct strbuf *err)
 {
 	if (update->flags & REF_LOG_ONLY ||
-	    !(update->flags & REF_HAVE_OLD) ||
-	    oideq(oid, &update->old_oid))
+	    !(update->flags & REF_HAVE_OLD))
 		return 0;
 
+	if (oideq(oid, &update->old_oid)) {
+		/*
+		 * Normally matching the expected old oid is enough. Either we
+		 * found the ref at the expected state, or we are creating and
+		 * expect the null oid (and likewise found nothing).
+		 *
+		 * But there is one exception for the null oid: if we found a
+		 * symref pointing to nothing we'll also get the null oid. In
+		 * regular recursive mode, that's good (we'll write to what the
+		 * symref points to, which doesn't exist). But in no-deref
+		 * mode, it means we'll clobber the symref, even though the
+		 * caller asked for this to be a creation event. So flag
+		 * that case to preserve the dangling symref.
+		 */
+		if ((update->flags & REF_NO_DEREF) && referent->len &&
+		    is_null_oid(oid)) {
+			strbuf_addf(err, "cannot lock ref '%s': "
+				    "dangling symref already exists",
+				    ref_update_original_update_refname(update));
+			return REF_TRANSACTION_ERROR_CREATE_EXISTS;
+		}
+		return 0;
+	}
+
 	if (is_null_oid(&update->old_oid)) {
 		strbuf_addf(err, "cannot lock ref '%s': "
 			    "reference already exists",
@@ -2713,7 +2741,8 @@ static enum ref_transaction_error lock_ref_for_update(struct files_ref_store *re
 			if (update->old_target)
 				ret = ref_update_check_old_target(referent.buf, update, err);
 			else
-				ret = check_old_oid(update, &lock->old_oid, err);
+				ret = check_old_oid(update, &lock->old_oid,
+						    &referent, err);
 			if (ret)
 				goto out;
 		} else {
@@ -2745,7 +2774,8 @@ static enum ref_transaction_error lock_ref_for_update(struct files_ref_store *re
 			ret = REF_TRANSACTION_ERROR_EXPECTED_SYMREF;
 			goto out;
 		} else {
-			ret = check_old_oid(update, &lock->old_oid, err);
+			ret = check_old_oid(update, &lock->old_oid,
+					    &referent, err);
 			if  (ret) {
 				goto out;
 			}
@@ -3073,7 +3103,7 @@ static int parse_and_write_reflog(struct files_ref_store *refs,
 		if (!(update->flags & REF_HAVE_OLD) ||
 		    !(update->flags & REF_HAVE_NEW) ||
 		    !(update->flags & REF_LOG_ONLY)) {
-			strbuf_addf(err, _("trying to write reflog for '%s'"
+			strbuf_addf(err, _("trying to write reflog for '%s' "
 					   "with incomplete values"), update->refname);
 			return REF_TRANSACTION_ERROR_GENERIC;
 		}
@@ -3114,14 +3144,11 @@ static int parse_and_write_reflog(struct files_ref_store *refs,
 	return 0;
 }
 
-static int ref_present(const char *refname, const char *referent UNUSED,
-		       const struct object_id *oid UNUSED,
-		       int flags UNUSED,
-		       void *cb_data)
+static int ref_present(const struct reference *ref, void *cb_data)
 {
 	struct string_list *affected_refnames = cb_data;
 
-	return string_list_has_string(affected_refnames, refname);
+	return string_list_has_string(affected_refnames, ref->name);
 }
 
 static int files_transaction_finish_initial(struct files_ref_store *refs,
@@ -3420,7 +3447,8 @@ struct expire_reflog_cb {
 		     dry_run:1;
 };
 
-static int expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
+static int expire_reflog_ent(const char *refname UNUSED,
+			     struct object_id *ooid, struct object_id *noid,
 			     const char *email, timestamp_t timestamp, int tz,
 			     const char *message, void *cb_data)
 {
@@ -3938,8 +3966,6 @@ static int files_fsck_refs(struct ref_store *ref_store,
 		NULL,
 	};
 
-	if (o->verbose)
-		fprintf_ln(stderr, _("Checking references consistency"));
 	return files_fsck_refs_dir(ref_store, o, "refs", wt, fsck_refs_fn);
 }
 
@@ -3965,7 +3991,8 @@ struct ref_storage_be refs_be_files = {
 	.transaction_finish = files_transaction_finish,
 	.transaction_abort = files_transaction_abort,
 
-	.pack_refs = files_pack_refs,
+	.optimize = files_optimize,
+	.optimize_required = files_optimize_required,
 	.rename_ref = files_rename_ref,
 	.copy_ref = files_copy_ref,
 
diff --git a/refs/iterator.c b/refs/iterator.c
index 17ef841..d79aa5e 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -21,12 +21,6 @@ int ref_iterator_seek(struct ref_iterator *ref_iterator, const char *refname,
 	return ref_iterator->vtable->seek(ref_iterator, refname, flags);
 }
 
-int ref_iterator_peel(struct ref_iterator *ref_iterator,
-		      struct object_id *peeled)
-{
-	return ref_iterator->vtable->peel(ref_iterator, peeled);
-}
-
 void ref_iterator_free(struct ref_iterator *ref_iterator)
 {
 	if (ref_iterator) {
@@ -41,10 +35,7 @@ void base_ref_iterator_init(struct ref_iterator *iter,
 			    struct ref_iterator_vtable *vtable)
 {
 	iter->vtable = vtable;
-	iter->refname = NULL;
-	iter->referent = NULL;
-	iter->oid = NULL;
-	iter->flags = 0;
+	memset(&iter->ref, 0, sizeof(iter->ref));
 }
 
 struct empty_ref_iterator {
@@ -63,12 +54,6 @@ static int empty_ref_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
 	return 0;
 }
 
-static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
-				   struct object_id *peeled UNUSED)
-{
-	BUG("peel called for empty iterator");
-}
-
 static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED)
 {
 }
@@ -76,7 +61,6 @@ static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED)
 static struct ref_iterator_vtable empty_ref_iterator_vtable = {
 	.advance = empty_ref_iterator_advance,
 	.seek = empty_ref_iterator_seek,
-	.peel = empty_ref_iterator_peel,
 	.release = empty_ref_iterator_release,
 };
 
@@ -127,8 +111,8 @@ enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree,
 		 * latter.
 		 */
 		if (iter_worktree) {
-			int cmp = strcmp(iter_worktree->refname,
-					 iter_common->refname);
+			int cmp = strcmp(iter_worktree->ref.name,
+					 iter_common->ref.name);
 			if (cmp < 0)
 				return ITER_SELECT_0;
 			else if (!cmp)
@@ -139,7 +123,7 @@ enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree,
 		  * We now know that the lexicographically-next ref is a common
 		  * ref. When the common ref is a shared one we return it.
 		  */
-		if (parse_worktree_ref(iter_common->refname, NULL, NULL,
+		if (parse_worktree_ref(iter_common->ref.name, NULL, NULL,
 				       NULL) == REF_WORKTREE_SHARED)
 			return ITER_SELECT_1;
 
@@ -212,10 +196,7 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
 		}
 
 		if (selection & ITER_YIELD_CURRENT) {
-			iter->base.referent = (*iter->current)->referent;
-			iter->base.refname = (*iter->current)->refname;
-			iter->base.oid = (*iter->current)->oid;
-			iter->base.flags = (*iter->current)->flags;
+			iter->base.ref = (*iter->current)->ref;
 			return ITER_OK;
 		}
 	}
@@ -246,18 +227,6 @@ static int merge_ref_iterator_seek(struct ref_iterator *ref_iterator,
 	return 0;
 }
 
-static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	struct merge_ref_iterator *iter =
-		(struct merge_ref_iterator *)ref_iterator;
-
-	if (!iter->current) {
-		BUG("peel called before advance for merge iterator");
-	}
-	return ref_iterator_peel(*iter->current, peeled);
-}
-
 static void merge_ref_iterator_release(struct ref_iterator *ref_iterator)
 {
 	struct merge_ref_iterator *iter =
@@ -269,7 +238,6 @@ static void merge_ref_iterator_release(struct ref_iterator *ref_iterator)
 static struct ref_iterator_vtable merge_ref_iterator_vtable = {
 	.advance = merge_ref_iterator_advance,
 	.seek = merge_ref_iterator_seek,
-	.peel = merge_ref_iterator_peel,
 	.release = merge_ref_iterator_release,
 };
 
@@ -313,7 +281,7 @@ static enum iterator_selection overlay_iterator_select(
 	else if (!front)
 		return ITER_SELECT_1;
 
-	cmp = strcmp(front->refname, back->refname);
+	cmp = strcmp(front->ref.name, back->ref.name);
 
 	if (cmp < 0)
 		return ITER_SELECT_0;
@@ -371,7 +339,7 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
 	int ok;
 
 	while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
-		int cmp = compare_prefix(iter->iter0->refname, iter->prefix);
+		int cmp = compare_prefix(iter->iter0->ref.name, iter->prefix);
 		if (cmp < 0)
 			continue;
 		/*
@@ -382,6 +350,8 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
 		if (cmp > 0)
 			return ITER_DONE;
 
+		iter->base.ref = iter->iter0->ref;
+
 		if (iter->trim) {
 			/*
 			 * It is nonsense to trim off characters that
@@ -392,15 +362,11 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
 			 * one character left in the refname after
 			 * trimming, report it as a bug:
 			 */
-			if (strlen(iter->iter0->refname) <= iter->trim)
+			if (strlen(iter->base.ref.name) <= iter->trim)
 				BUG("attempt to trim too many characters");
-			iter->base.refname = iter->iter0->refname + iter->trim;
-		} else {
-			iter->base.refname = iter->iter0->refname;
+			iter->base.ref.name += iter->trim;
 		}
 
-		iter->base.oid = iter->iter0->oid;
-		iter->base.flags = iter->iter0->flags;
 		return ITER_OK;
 	}
 
@@ -420,15 +386,6 @@ static int prefix_ref_iterator_seek(struct ref_iterator *ref_iterator,
 	return ref_iterator_seek(iter->iter0, refname, flags);
 }
 
-static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				    struct object_id *peeled)
-{
-	struct prefix_ref_iterator *iter =
-		(struct prefix_ref_iterator *)ref_iterator;
-
-	return ref_iterator_peel(iter->iter0, peeled);
-}
-
 static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator)
 {
 	struct prefix_ref_iterator *iter =
@@ -440,7 +397,6 @@ static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator)
 static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
 	.advance = prefix_ref_iterator_advance,
 	.seek = prefix_ref_iterator_seek,
-	.peel = prefix_ref_iterator_peel,
 	.release = prefix_ref_iterator_release,
 };
 
@@ -466,23 +422,18 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
 	return ref_iterator;
 }
 
-struct ref_iterator *current_ref_iter = NULL;
-
 int do_for_each_ref_iterator(struct ref_iterator *iter,
 			     each_ref_fn fn, void *cb_data)
 {
 	int retval = 0, ok;
-	struct ref_iterator *old_ref_iter = current_ref_iter;
 
-	current_ref_iter = iter;
 	while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
-		retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data);
+		retval = fn(&iter->ref, cb_data);
 		if (retval)
 			goto out;
 	}
 
 out:
-	current_ref_iter = old_ref_iter;
 	if (ok == ITER_ERROR)
 		retval = -1;
 	ref_iterator_free(iter);
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index a8c22a0..4ea0c12 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -882,6 +882,7 @@ static int next_record(struct packed_ref_iterator *iter)
 {
 	const char *p, *eol;
 
+	memset(&iter->base.ref, 0, sizeof(iter->base.ref));
 	strbuf_reset(&iter->refname_buf);
 
 	/*
@@ -908,7 +909,7 @@ static int next_record(struct packed_ref_iterator *iter)
 	if (iter->pos == iter->eof)
 		return ITER_DONE;
 
-	iter->base.flags = REF_ISPACKED;
+	iter->base.ref.flags = REF_ISPACKED;
 	p = iter->pos;
 
 	if (iter->eof - p < snapshot_hexsz(iter->snapshot) + 2 ||
@@ -916,6 +917,7 @@ static int next_record(struct packed_ref_iterator *iter)
 	    !isspace(*p++))
 		die_invalid_line(iter->snapshot->refs->path,
 				 iter->pos, iter->eof - iter->pos);
+	iter->base.ref.oid = &iter->oid;
 
 	eol = memchr(p, '\n', iter->eof - p);
 	if (!eol)
@@ -923,22 +925,22 @@ static int next_record(struct packed_ref_iterator *iter)
 				      iter->pos, iter->eof - iter->pos);
 
 	strbuf_add(&iter->refname_buf, p, eol - p);
-	iter->base.refname = iter->refname_buf.buf;
+	iter->base.ref.name = iter->refname_buf.buf;
 
 	if (refname_contains_nul(&iter->refname_buf))
-		die("packed refname contains embedded NULL: %s", iter->base.refname);
+		die("packed refname contains embedded NULL: %s", iter->base.ref.name);
 
-	if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) {
-		if (!refname_is_safe(iter->base.refname))
+	if (check_refname_format(iter->base.ref.name, REFNAME_ALLOW_ONELEVEL)) {
+		if (!refname_is_safe(iter->base.ref.name))
 			die("packed refname is dangerous: %s",
-			    iter->base.refname);
+			    iter->base.ref.name);
 		oidclr(&iter->oid, iter->repo->hash_algo);
-		iter->base.flags |= REF_BAD_NAME | REF_ISBROKEN;
+		iter->base.ref.flags |= REF_BAD_NAME | REF_ISBROKEN;
 	}
 	if (iter->snapshot->peeled == PEELED_FULLY ||
 	    (iter->snapshot->peeled == PEELED_TAGS &&
-	     starts_with(iter->base.refname, "refs/tags/")))
-		iter->base.flags |= REF_KNOWS_PEELED;
+	     starts_with(iter->base.ref.name, "refs/tags/")))
+		iter->base.ref.flags |= REF_KNOWS_PEELED;
 
 	iter->pos = eol + 1;
 
@@ -956,11 +958,12 @@ static int next_record(struct packed_ref_iterator *iter)
 		 * definitely know the value of *this* reference. But
 		 * we suppress it if the reference is broken:
 		 */
-		if ((iter->base.flags & REF_ISBROKEN)) {
+		if ((iter->base.ref.flags & REF_ISBROKEN)) {
 			oidclr(&iter->peeled, iter->repo->hash_algo);
-			iter->base.flags &= ~REF_KNOWS_PEELED;
+			iter->base.ref.flags &= ~REF_KNOWS_PEELED;
 		} else {
-			iter->base.flags |= REF_KNOWS_PEELED;
+			iter->base.ref.flags |= REF_KNOWS_PEELED;
+			iter->base.ref.peeled_oid = &iter->peeled;
 		}
 	} else {
 		oidclr(&iter->peeled, iter->repo->hash_algo);
@@ -976,15 +979,15 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
 	int ok;
 
 	while ((ok = next_record(iter)) == ITER_OK) {
-		const char *refname = iter->base.refname;
+		const char *refname = iter->base.ref.name;
 		const char *prefix = iter->prefix;
 
 		if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
-		    !is_per_worktree_ref(iter->base.refname))
+		    !is_per_worktree_ref(iter->base.ref.name))
 			continue;
 
 		if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
-		    !ref_resolves_to_object(iter->base.refname, iter->repo,
+		    !ref_resolves_to_object(iter->base.ref.name, iter->repo,
 					    &iter->oid, iter->flags))
 			continue;
 
@@ -1027,22 +1030,6 @@ static int packed_ref_iterator_seek(struct ref_iterator *ref_iterator,
 	return 0;
 }
 
-static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	struct packed_ref_iterator *iter =
-		(struct packed_ref_iterator *)ref_iterator;
-
-	if ((iter->base.flags & REF_KNOWS_PEELED)) {
-		oidcpy(peeled, &iter->peeled);
-		return is_null_oid(&iter->peeled) ? -1 : 0;
-	} else if ((iter->base.flags & (REF_ISBROKEN | REF_ISSYMREF))) {
-		return -1;
-	} else {
-		return peel_object(iter->repo, &iter->oid, peeled) ? -1 : 0;
-	}
-}
-
 static void packed_ref_iterator_release(struct ref_iterator *ref_iterator)
 {
 	struct packed_ref_iterator *iter =
@@ -1056,7 +1043,6 @@ static void packed_ref_iterator_release(struct ref_iterator *ref_iterator)
 static struct ref_iterator_vtable packed_ref_iterator_vtable = {
 	.advance = packed_ref_iterator_advance,
 	.seek = packed_ref_iterator_seek,
-	.peel = packed_ref_iterator_peel,
 	.release = packed_ref_iterator_release,
 };
 
@@ -1194,7 +1180,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
 	iter->snapshot = snapshot;
 	acquire_snapshot(snapshot);
 	strbuf_init(&iter->refname_buf, 0);
-	iter->base.oid = &iter->oid;
 	iter->repo = ref_store->repo;
 	iter->flags = flags;
 
@@ -1436,7 +1421,7 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
 			if (!iter)
 				cmp = +1;
 			else
-				cmp = strcmp(iter->refname, update->refname);
+				cmp = strcmp(iter->ref.name, update->refname);
 		}
 
 		if (!cmp) {
@@ -1459,11 +1444,11 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
 					}
 
 					goto error;
-				} else if (!oideq(&update->old_oid, iter->oid)) {
+				} else if (!oideq(&update->old_oid, iter->ref.oid)) {
 					strbuf_addf(err, "cannot update ref '%s': "
 						    "is at %s but expected %s",
 						    update->refname,
-						    oid_to_hex(iter->oid),
+						    oid_to_hex(iter->ref.oid),
 						    oid_to_hex(&update->old_oid));
 					ret = REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE;
 
@@ -1523,13 +1508,8 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
 
 		if (cmp < 0) {
 			/* Pass the old reference through. */
-
-			struct object_id peeled;
-			int peel_error = ref_iterator_peel(iter, &peeled);
-
-			if (write_packed_entry(out, iter->refname,
-					       iter->oid,
-					       peel_error ? NULL : &peeled))
+			if (write_packed_entry(out, iter->ref.name,
+					       iter->ref.oid, iter->ref.peeled_oid))
 				goto write_error;
 
 			if ((ok = ref_iterator_advance(iter)) != ITER_OK) {
@@ -1547,9 +1527,8 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
 			i++;
 		} else {
 			struct object_id peeled;
-			int peel_error = peel_object(refs->base.repo,
-						     &update->new_oid,
-						     &peeled);
+			int peel_error = peel_object(refs->base.repo, &update->new_oid,
+						     &peeled, PEEL_OBJECT_VERIFY_TAGGED_OBJECT_TYPE);
 
 			if (write_packed_entry(out, update->refname,
 					       &update->new_oid,
@@ -1794,8 +1773,8 @@ static int packed_transaction_finish(struct ref_store *ref_store,
 	return ret;
 }
 
-static int packed_pack_refs(struct ref_store *ref_store UNUSED,
-			    struct pack_refs_opts *pack_opts UNUSED)
+static int packed_optimize(struct ref_store *ref_store UNUSED,
+			   struct refs_optimize_opts *opts UNUSED)
 {
 	/*
 	 * Packed refs are already packed. It might be that loose refs
@@ -1805,6 +1784,17 @@ static int packed_pack_refs(struct ref_store *ref_store UNUSED,
 	return 0;
 }
 
+static int packed_optimize_required(struct ref_store *ref_store UNUSED,
+				    struct refs_optimize_opts *opts UNUSED,
+				    bool *required)
+{
+	/*
+	 * Packed refs are already optimized.
+	 */
+	*required = false;
+	return 0;
+}
+
 static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_store UNUSED)
 {
 	return empty_ref_iterator_begin();
@@ -2150,7 +2140,9 @@ struct ref_storage_be refs_be_packed = {
 	.transaction_finish = packed_transaction_finish,
 	.transaction_abort = packed_transaction_abort,
 
-	.pack_refs = packed_pack_refs,
+	.optimize = packed_optimize,
+	.optimize_required = packed_optimize_required,
+
 	.rename_ref = NULL,
 	.copy_ref = NULL,
 
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index c180e0a..ffef01a 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -425,10 +425,11 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
 			level->prefix_state = entry_prefix_state;
 			level->index = -1;
 		} else {
-			iter->base.refname = entry->name;
-			iter->base.referent = entry->u.value.referent;
-			iter->base.oid = &entry->u.value.oid;
-			iter->base.flags = entry->flag;
+			memset(&iter->base.ref, 0, sizeof(iter->base.ref));
+			iter->base.ref.name = entry->name;
+			iter->base.ref.target = entry->u.value.referent;
+			iter->base.ref.oid = &entry->u.value.oid;
+			iter->base.ref.flags = entry->flag;
 			return ITER_OK;
 		}
 	}
@@ -539,20 +540,12 @@ static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator,
 				 */
 				break;
 			}
-		} while (slash);
+		} while (slash && dir->nr);
 	}
 
 	return 0;
 }
 
-static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				   struct object_id *peeled)
-{
-	struct cache_ref_iterator *iter =
-		(struct cache_ref_iterator *)ref_iterator;
-	return peel_object(iter->repo, ref_iterator->oid, peeled) ? -1 : 0;
-}
-
 static void cache_ref_iterator_release(struct ref_iterator *ref_iterator)
 {
 	struct cache_ref_iterator *iter =
@@ -564,7 +557,6 @@ static void cache_ref_iterator_release(struct ref_iterator *ref_iterator)
 static struct ref_iterator_vtable cache_ref_iterator_vtable = {
 	.advance = cache_ref_iterator_advance,
 	.seek = cache_ref_iterator_seek,
-	.peel = cache_ref_iterator_peel,
 	.release = cache_ref_iterator_release,
 };
 
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 54c2079..c7d2a6e 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -249,10 +249,7 @@ const char *find_descendant_ref(const char *dirname,
  */
 struct ref_iterator {
 	struct ref_iterator_vtable *vtable;
-	const char *refname;
-	const char *referent;
-	const struct object_id *oid;
-	unsigned int flags;
+	struct reference ref;
 };
 
 /*
@@ -361,12 +358,6 @@ typedef int ref_iterator_seek_fn(struct ref_iterator *ref_iterator,
 				 const char *refname, unsigned int flags);
 
 /*
- * Peels the current ref, returning 0 for success or -1 for failure.
- */
-typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator,
-				 struct object_id *peeled);
-
-/*
  * Implementations of this function should free any resources specific
  * to the derived class.
  */
@@ -375,23 +366,9 @@ typedef void ref_iterator_release_fn(struct ref_iterator *ref_iterator);
 struct ref_iterator_vtable {
 	ref_iterator_advance_fn *advance;
 	ref_iterator_seek_fn *seek;
-	ref_iterator_peel_fn *peel;
 	ref_iterator_release_fn *release;
 };
 
-/*
- * current_ref_iter is a performance hack: when iterating over
- * references using the for_each_ref*() functions, current_ref_iter is
- * set to the reference iterator before calling the callback function.
- * If the callback function calls peel_ref(), then peel_ref() first
- * checks whether the reference to be peeled is the one referred to by
- * the iterator (it usually is) and if so, asks the iterator for the
- * peeled version of the reference if it is available. This avoids a
- * refname lookup in a common case. current_ref_iter is set to NULL
- * when the iteration is over.
- */
-extern struct ref_iterator *current_ref_iter;
-
 struct ref_store;
 
 /* refs backends */
@@ -445,8 +422,13 @@ typedef int ref_transaction_commit_fn(struct ref_store *refs,
 				      struct ref_transaction *transaction,
 				      struct strbuf *err);
 
-typedef int pack_refs_fn(struct ref_store *ref_store,
-			 struct pack_refs_opts *opts);
+typedef int optimize_fn(struct ref_store *ref_store,
+			struct refs_optimize_opts *opts);
+
+typedef int optimize_required_fn(struct ref_store *ref_store,
+				 struct refs_optimize_opts *opts,
+				 bool *required);
+
 typedef int rename_ref_fn(struct ref_store *ref_store,
 			  const char *oldref, const char *newref,
 			  const char *logmsg);
@@ -571,7 +553,8 @@ struct ref_storage_be {
 	ref_transaction_finish_fn *transaction_finish;
 	ref_transaction_abort_fn *transaction_abort;
 
-	pack_refs_fn *pack_refs;
+	optimize_fn *optimize;
+	optimize_required_fn *optimize_required;
 	rename_ref_fn *rename_ref;
 	copy_ref_fn *copy_ref;
 
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index c0440b4..4319a4e 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -6,20 +6,21 @@
 #include "../config.h"
 #include "../dir.h"
 #include "../environment.h"
+#include "../fsck.h"
 #include "../gettext.h"
 #include "../hash.h"
 #include "../hex.h"
 #include "../iterator.h"
 #include "../ident.h"
-#include "../lockfile.h"
 #include "../object.h"
 #include "../path.h"
 #include "../refs.h"
 #include "../reftable/reftable-basics.h"
-#include "../reftable/reftable-stack.h"
-#include "../reftable/reftable-record.h"
 #include "../reftable/reftable-error.h"
+#include "../reftable/reftable-fsck.h"
 #include "../reftable/reftable-iterator.h"
+#include "../reftable/reftable-record.h"
+#include "../reftable/reftable-stack.h"
 #include "../repo-settings.h"
 #include "../setup.h"
 #include "../strmap.h"
@@ -546,6 +547,7 @@ struct reftable_ref_iterator {
 	struct reftable_iterator iter;
 	struct reftable_ref_record ref;
 	struct object_id oid;
+	struct object_id peeled_oid;
 
 	char *prefix;
 	size_t prefix_len;
@@ -670,6 +672,8 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
 		case REFTABLE_REF_VAL2:
 			oidread(&iter->oid, iter->ref.value.val2.value,
 				refs->base.repo->hash_algo);
+			oidread(&iter->peeled_oid, iter->ref.value.val2.target_value,
+				refs->base.repo->hash_algo);
 			break;
 		case REFTABLE_REF_SYMREF:
 			referent = refs_resolve_ref_unsafe(&iter->refs->base,
@@ -703,10 +707,13 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
 					    &iter->oid, flags))
 				continue;
 
-		iter->base.refname = iter->ref.refname;
-		iter->base.referent = referent;
-		iter->base.oid = &iter->oid;
-		iter->base.flags = flags;
+		memset(&iter->base.ref, 0, sizeof(iter->base.ref));
+		iter->base.ref.name = iter->ref.refname;
+		iter->base.ref.target = referent;
+		iter->base.ref.oid = &iter->oid;
+		if (iter->ref.value_type == REFTABLE_REF_VAL2)
+			iter->base.ref.peeled_oid = &iter->peeled_oid;
+		iter->base.ref.flags = flags;
 
 		break;
 	}
@@ -737,21 +744,6 @@ static int reftable_ref_iterator_seek(struct ref_iterator *ref_iterator,
 	return iter->err;
 }
 
-static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator,
-				      struct object_id *peeled)
-{
-	struct reftable_ref_iterator *iter =
-		(struct reftable_ref_iterator *)ref_iterator;
-
-	if (iter->ref.value_type == REFTABLE_REF_VAL2) {
-		oidread(peeled, iter->ref.value.val2.target_value,
-			iter->refs->base.repo->hash_algo);
-		return 0;
-	}
-
-	return -1;
-}
-
 static void reftable_ref_iterator_release(struct ref_iterator *ref_iterator)
 {
 	struct reftable_ref_iterator *iter =
@@ -769,7 +761,6 @@ static void reftable_ref_iterator_release(struct ref_iterator *ref_iterator)
 static struct ref_iterator_vtable reftable_ref_iterator_vtable = {
 	.advance = reftable_ref_iterator_advance,
 	.seek = reftable_ref_iterator_seek,
-	.peel = reftable_ref_iterator_peel,
 	.release = reftable_ref_iterator_release,
 };
 
@@ -827,7 +818,7 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
 
 	iter = xcalloc(1, sizeof(*iter));
 	base_ref_iterator_init(&iter->base, &reftable_ref_iterator_vtable);
-	iter->base.oid = &iter->oid;
+	iter->base.ref.oid = &iter->oid;
 	iter->flags = flags;
 	iter->refs = refs;
 	iter->exclude_patterns = filter_exclude_patterns(exclude_patterns);
@@ -1012,10 +1003,6 @@ static int prepare_transaction_update(struct write_transaction_table_arg **out,
 	if (!arg) {
 		struct reftable_addition *addition;
 
-		ret = reftable_stack_reload(be->stack);
-		if (ret)
-			return ret;
-
 		ret = reftable_stack_new_addition(&addition, be->stack,
 						  REFTABLE_STACK_NEW_ADDITION_RELOAD);
 		if (ret) {
@@ -1106,7 +1093,7 @@ static enum ref_transaction_error prepare_single_update(struct reftable_ref_stor
 		if (!(u->flags & REF_HAVE_OLD) ||
 		    !(u->flags & REF_HAVE_NEW) ||
 		    !(u->flags & REF_LOG_ONLY)) {
-			strbuf_addf(err, _("trying to write reflog for '%s'"
+			strbuf_addf(err, _("trying to write reflog for '%s' "
 					   "with incomplete values"), u->refname);
 			return REF_TRANSACTION_ERROR_GENERIC;
 		}
@@ -1278,9 +1265,33 @@ static enum ref_transaction_error prepare_single_update(struct reftable_ref_stor
 		ret = ref_update_check_old_target(referent->buf, u, err);
 		if (ret)
 			return ret;
-	} else if ((u->flags & (REF_LOG_ONLY | REF_HAVE_OLD)) == REF_HAVE_OLD &&
-		   !oideq(&current_oid, &u->old_oid)) {
-		if (is_null_oid(&u->old_oid)) {
+	} else if ((u->flags & (REF_LOG_ONLY | REF_HAVE_OLD)) == REF_HAVE_OLD) {
+		if (oideq(&current_oid, &u->old_oid)) {
+			/*
+			 * Normally matching the expected old oid is enough. Either we
+			 * found the ref at the expected state, or we are creating and
+			 * expect the null oid (and likewise found nothing).
+			 *
+			 * But there is one exception for the null oid: if we found a
+			 * symref pointing to nothing we'll also get the null oid. In
+			 * regular recursive mode, that's good (we'll write to what the
+			 * symref points to, which doesn't exist). But in no-deref
+			 * mode, it means we'll clobber the symref, even though the
+			 * caller asked for this to be a creation event. So flag
+			 * that case to preserve the dangling symref.
+			 *
+			 * Everything else is OK and we can fall through to the
+			 * end of the conditional chain.
+			 */
+			if ((u->flags & REF_NO_DEREF) &&
+			    referent->len &&
+			    is_null_oid(&u->old_oid)) {
+				strbuf_addf(err, _("cannot lock ref '%s': "
+					    "dangling symref already exists"),
+					    ref_update_original_update_refname(u));
+				return REF_TRANSACTION_ERROR_CREATE_EXISTS;
+			}
+		} else if (is_null_oid(&u->old_oid)) {
 			strbuf_addf(err, _("cannot lock ref '%s': "
 					   "reference already exists"),
 				    ref_update_original_update_refname(u));
@@ -1621,7 +1632,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 			ref.refname = (char *)u->refname;
 			ref.update_index = ts;
 
-			peel_error = peel_object(arg->refs->base.repo, &u->new_oid, &peeled);
+			peel_error = peel_object(arg->refs->base.repo, &u->new_oid, &peeled,
+						 PEEL_OBJECT_VERIFY_TAGGED_OBJECT_TYPE);
 			if (!peel_error) {
 				ref.value_type = REFTABLE_REF_VAL2;
 				memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
@@ -1688,11 +1700,11 @@ static int reftable_be_transaction_finish(struct ref_store *ref_store UNUSED,
 	return ret;
 }
 
-static int reftable_be_pack_refs(struct ref_store *ref_store,
-				 struct pack_refs_opts *opts)
+static int reftable_be_optimize(struct ref_store *ref_store,
+				struct refs_optimize_opts *opts)
 {
 	struct reftable_ref_store *refs =
-		reftable_be_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB, "pack_refs");
+		reftable_be_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB, "optimize_refs");
 	struct reftable_stack *stack;
 	int ret;
 
@@ -1703,7 +1715,7 @@ static int reftable_be_pack_refs(struct ref_store *ref_store,
 	if (!stack)
 		stack = refs->main_backend.stack;
 
-	if (opts->flags & PACK_REFS_AUTO)
+	if (opts->flags & REFS_OPTIMIZE_AUTO)
 		ret = reftable_stack_auto_compact(stack);
 	else
 		ret = reftable_stack_compact_all(stack, NULL);
@@ -1721,6 +1733,29 @@ static int reftable_be_pack_refs(struct ref_store *ref_store,
 	return ret;
 }
 
+static int reftable_be_optimize_required(struct ref_store *ref_store,
+					 struct refs_optimize_opts *opts,
+					 bool *required)
+{
+	struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_READ,
+							       "optimize_refs_required");
+	struct reftable_stack *stack;
+	bool use_heuristics = false;
+
+	if (refs->err)
+		return refs->err;
+
+	stack = refs->worktree_backend.stack;
+	if (!stack)
+		stack = refs->main_backend.stack;
+
+	if (opts->flags & REFS_OPTIMIZE_AUTO)
+		use_heuristics = true;
+
+	return reftable_stack_compaction_required(stack, use_heuristics,
+						  required);
+}
+
 struct write_create_symref_arg {
 	struct reftable_ref_store *refs;
 	struct reftable_stack *stack;
@@ -1974,7 +2009,8 @@ static int reftable_be_rename_ref(struct ref_store *ref_store,
 	ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
 	if (ret)
 		goto done;
-	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg);
+	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg,
+				 REFTABLE_STACK_NEW_ADDITION_RELOAD);
 
 done:
 	assert(ret != REFTABLE_API_ERROR);
@@ -2003,7 +2039,8 @@ static int reftable_be_copy_ref(struct ref_store *ref_store,
 	ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
 	if (ret)
 		goto done;
-	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg);
+	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg,
+				 REFTABLE_STACK_NEW_ADDITION_RELOAD);
 
 done:
 	assert(ret != REFTABLE_API_ERROR);
@@ -2043,7 +2080,7 @@ static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator)
 
 		strbuf_reset(&iter->last_name);
 		strbuf_addstr(&iter->last_name, iter->log.refname);
-		iter->base.refname = iter->log.refname;
+		iter->base.ref.name = iter->log.refname;
 
 		break;
 	}
@@ -2063,13 +2100,6 @@ static int reftable_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSE
 	return -1;
 }
 
-static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
-					 struct object_id *peeled UNUSED)
-{
-	BUG("reftable reflog iterator cannot be peeled");
-	return -1;
-}
-
 static void reftable_reflog_iterator_release(struct ref_iterator *ref_iterator)
 {
 	struct reftable_reflog_iterator *iter =
@@ -2082,7 +2112,6 @@ static void reftable_reflog_iterator_release(struct ref_iterator *ref_iterator)
 static struct ref_iterator_vtable reftable_reflog_iterator_vtable = {
 	.advance = reftable_reflog_iterator_advance,
 	.seek = reftable_reflog_iterator_seek,
-	.peel = reftable_reflog_iterator_peel,
 	.release = reftable_reflog_iterator_release,
 };
 
@@ -2155,7 +2184,7 @@ static int yield_log_record(struct reftable_ref_store *refs,
 
 	full_committer = fmt_ident(log->value.update.name, log->value.update.email,
 				   WANT_COMMITTER_IDENT, NULL, IDENT_NO_DATE);
-	return fn(&old_oid, &new_oid, full_committer,
+	return fn(log->refname, &old_oid, &new_oid, full_committer,
 		  log->value.update.time, log->value.update.tz_offset,
 		  log->value.update.message, cb_data);
 }
@@ -2375,7 +2404,8 @@ static int reftable_be_create_reflog(struct ref_store *ref_store,
 		goto done;
 	arg.stack = be->stack;
 
-	ret = reftable_stack_add(be->stack, &write_reflog_existence_table, &arg);
+	ret = reftable_stack_add(be->stack, &write_reflog_existence_table, &arg,
+				 REFTABLE_STACK_NEW_ADDITION_RELOAD);
 
 done:
 	return ret;
@@ -2446,7 +2476,8 @@ static int reftable_be_delete_reflog(struct ref_store *ref_store,
 		return ret;
 	arg.stack = be->stack;
 
-	ret = reftable_stack_add(be->stack, &write_reflog_delete_table, &arg);
+	ret = reftable_stack_add(be->stack, &write_reflog_delete_table, &arg,
+				 REFTABLE_STACK_NEW_ADDITION_RELOAD);
 
 	assert(ret != REFTABLE_API_ERROR);
 	return ret;
@@ -2484,7 +2515,7 @@ static int write_reflog_expiry_table(struct reftable_writer *writer, void *cb_da
 		ref.refname = (char *)arg->refname;
 		ref.update_index = ts;
 
-		if (!peel_object(arg->refs->base.repo, &arg->update_oid, &peeled)) {
+		if (!peel_object(arg->refs->base.repo, &arg->update_oid, &peeled, 0)) {
 			ref.value_type = REFTABLE_REF_VAL2;
 			memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
 			memcpy(ref.value.val2.value, arg->update_oid.hash, GIT_MAX_RAWSZ);
@@ -2567,6 +2598,11 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
 	if (ret < 0)
 		goto done;
 
+	ret = reftable_stack_new_addition(&add, be->stack,
+					  REFTABLE_STACK_NEW_ADDITION_RELOAD);
+	if (ret < 0)
+		goto done;
+
 	ret = reftable_stack_init_log_iterator(be->stack, &it);
 	if (ret < 0)
 		goto done;
@@ -2575,10 +2611,6 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
 	if (ret < 0)
 		goto done;
 
-	ret = reftable_stack_new_addition(&add, be->stack, 0);
-	if (ret < 0)
-		goto done;
-
 	ret = reftable_backend_read_ref(be, refname, &oid, &referent, &type);
 	if (ret < 0)
 		goto done;
@@ -2683,11 +2715,56 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
 	return ret;
 }
 
-static int reftable_be_fsck(struct ref_store *ref_store UNUSED,
-			    struct fsck_options *o UNUSED,
+static void reftable_fsck_verbose_handler(const char *msg, void *cb_data)
+{
+	struct fsck_options *o = cb_data;
+
+	if (o->verbose)
+		fprintf_ln(stderr, "%s", msg);
+}
+
+static const enum fsck_msg_id fsck_msg_id_map[] = {
+	[REFTABLE_FSCK_ERROR_TABLE_NAME] = FSCK_MSG_BAD_REFTABLE_TABLE_NAME,
+};
+
+static int reftable_fsck_error_handler(struct reftable_fsck_info *info,
+				       void *cb_data)
+{
+	struct fsck_ref_report report = { .path = info->path };
+	struct fsck_options *o = cb_data;
+	enum fsck_msg_id msg_id;
+
+	if (info->error < 0 || info->error >= REFTABLE_FSCK_MAX_VALUE)
+		BUG("unknown fsck error: %d", (int)info->error);
+
+	msg_id = fsck_msg_id_map[info->error];
+
+	if (!msg_id)
+		BUG("fsck_msg_id value missing for reftable error: %d", (int)info->error);
+
+	return fsck_report_ref(o, &report, msg_id, "%s", info->msg);
+}
+
+static int reftable_be_fsck(struct ref_store *ref_store, struct fsck_options *o,
 			    struct worktree *wt UNUSED)
 {
-	return 0;
+	struct reftable_ref_store *refs;
+	struct strmap_entry *entry;
+	struct hashmap_iter iter;
+	int ret = 0;
+
+	refs = reftable_be_downcast(ref_store, REF_STORE_READ, "fsck");
+
+	ret |= reftable_fsck_check(refs->main_backend.stack, reftable_fsck_error_handler,
+				   reftable_fsck_verbose_handler, o);
+
+	strmap_for_each_entry(&refs->worktree_backends, &iter, entry) {
+		struct reftable_backend *b = (struct reftable_backend *)entry->value;
+		ret |= reftable_fsck_check(b->stack, reftable_fsck_error_handler,
+					   reftable_fsck_verbose_handler, o);
+	}
+
+	return ret;
 }
 
 struct ref_storage_be refs_be_reftable = {
@@ -2701,7 +2778,9 @@ struct ref_storage_be refs_be_reftable = {
 	.transaction_finish = reftable_be_transaction_finish,
 	.transaction_abort = reftable_be_transaction_abort,
 
-	.pack_refs = reftable_be_pack_refs,
+	.optimize = reftable_be_optimize,
+	.optimize_required = reftable_be_optimize_required,
+
 	.rename_ref = reftable_be_rename_ref,
 	.copy_ref = reftable_be_copy_ref,
 
diff --git a/reftable/basics.c b/reftable/basics.c
index 9988ebd..e969927 100644
--- a/reftable/basics.c
+++ b/reftable/basics.c
@@ -195,44 +195,55 @@ size_t names_length(const char **names)
 	return p - names;
 }
 
-char **parse_names(char *buf, int size)
+int parse_names(char *buf, int size, char ***out)
 {
 	char **names = NULL;
 	size_t names_cap = 0;
 	size_t names_len = 0;
 	char *p = buf;
 	char *end = buf + size;
+	int err = 0;
 
 	while (p < end) {
 		char *next = strchr(p, '\n');
-		if (next && next < end) {
-			*next = 0;
+		if (!next) {
+			err = REFTABLE_FORMAT_ERROR;
+			goto done;
+		} else if (next < end) {
+			*next = '\0';
 		} else {
 			next = end;
 		}
+
 		if (p < next) {
 			if (REFTABLE_ALLOC_GROW(names, names_len + 1,
-						names_cap))
-				goto err;
+						names_cap)) {
+				err = REFTABLE_OUT_OF_MEMORY_ERROR;
+				goto done;
+			}
 
 			names[names_len] = reftable_strdup(p);
-			if (!names[names_len++])
-				goto err;
+			if (!names[names_len++]) {
+				err = REFTABLE_OUT_OF_MEMORY_ERROR;
+				goto done;
+			}
 		}
 		p = next + 1;
 	}
 
-	if (REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap))
-		goto err;
+	if (REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap)) {
+		err = REFTABLE_OUT_OF_MEMORY_ERROR;
+		goto done;
+	}
 	names[names_len] = NULL;
 
-	return names;
-
-err:
+	*out = names;
+	return 0;
+done:
 	for (size_t i = 0; i < names_len; i++)
 		reftable_free(names[i]);
 	reftable_free(names);
-	return NULL;
+	return err;
 }
 
 int names_equal(const char **a, const char **b)
diff --git a/reftable/basics.h b/reftable/basics.h
index 7d22f96..e4b83b2 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -167,10 +167,11 @@ void free_names(char **a);
 
 /*
  * Parse a newline separated list of names. `size` is the length of the buffer,
- * without terminating '\0'. Empty names are discarded. Returns a `NULL`
- * pointer when allocations fail.
+ * without terminating '\0'. Empty names are discarded.
+ *
+ * Returns 0 on success, a reftable error code on error.
  */
-char **parse_names(char *buf, int size);
+int parse_names(char *buf, int size, char ***out);
 
 /* compares two NULL-terminated arrays of strings. */
 int names_equal(const char **a, const char **b);
diff --git a/reftable/fsck.c b/reftable/fsck.c
new file mode 100644
index 0000000..26b9115
--- /dev/null
+++ b/reftable/fsck.c
@@ -0,0 +1,100 @@
+#include "basics.h"
+#include "reftable-fsck.h"
+#include "reftable-table.h"
+#include "stack.h"
+
+static bool table_has_valid_name(const char *name)
+{
+	const char *ptr = name;
+	char *endptr;
+
+	/* strtoull doesn't set errno on success */
+	errno = 0;
+
+	strtoull(ptr, &endptr, 16);
+	if (errno)
+		return false;
+	ptr = endptr;
+
+	if (*ptr != '-')
+		return false;
+	ptr++;
+
+	strtoull(ptr, &endptr, 16);
+	if (errno)
+		return false;
+	ptr = endptr;
+
+	if (*ptr != '-')
+		return false;
+	ptr++;
+
+	strtoul(ptr, &endptr, 16);
+	if (errno)
+		return false;
+	ptr = endptr;
+
+	if (strcmp(ptr, ".ref") && strcmp(ptr, ".log"))
+		return false;
+
+	return true;
+}
+
+typedef int (*table_check_fn)(struct reftable_table *table,
+			      reftable_fsck_report_fn report_fn,
+			      void *cb_data);
+
+static int table_check_name(struct reftable_table *table,
+			    reftable_fsck_report_fn report_fn,
+			    void *cb_data)
+{
+	if (!table_has_valid_name(table->name)) {
+		struct reftable_fsck_info info;
+
+		info.error = REFTABLE_FSCK_ERROR_TABLE_NAME;
+		info.msg = "invalid reftable table name";
+		info.path = table->name;
+
+		return report_fn(&info, cb_data);
+	}
+
+	return 0;
+}
+
+static int table_checks(struct reftable_table *table,
+			reftable_fsck_report_fn report_fn,
+			reftable_fsck_verbose_fn verbose_fn UNUSED,
+			void *cb_data)
+{
+	table_check_fn table_check_fns[] = {
+		table_check_name,
+		NULL,
+	};
+	int err = 0;
+
+	for (size_t i = 0; table_check_fns[i]; i++)
+		err |= table_check_fns[i](table, report_fn, cb_data);
+
+	return err;
+}
+
+int reftable_fsck_check(struct reftable_stack *stack,
+			reftable_fsck_report_fn report_fn,
+			reftable_fsck_verbose_fn verbose_fn,
+			void *cb_data)
+{
+	struct reftable_buf msg = REFTABLE_BUF_INIT;
+	int err = 0;
+
+	for (size_t i = 0; i < stack->tables_len; i++) {
+		reftable_buf_reset(&msg);
+		reftable_buf_addstr(&msg, "Checking table: ");
+		reftable_buf_addstr(&msg, stack->tables[i]->name);
+		verbose_fn(msg.buf, cb_data);
+
+		err |= table_checks(stack->tables[i], report_fn, verbose_fn, cb_data);
+	}
+
+	reftable_buf_release(&msg);
+	return err;
+}
diff --git a/reftable/reftable-fsck.h b/reftable/reftable-fsck.h
new file mode 100644
index 0000000..007a392
--- /dev/null
+++ b/reftable/reftable-fsck.h
@@ -0,0 +1,40 @@
+#ifndef REFTABLE_FSCK_H
+#define REFTABLE_FSCK_H
+
+#include "reftable-stack.h"
+
+enum reftable_fsck_error {
+	/* Invalid table name */
+	REFTABLE_FSCK_ERROR_TABLE_NAME = 0,
+	/* Used for bounds checking, must be last */
+	REFTABLE_FSCK_MAX_VALUE,
+};
+
+/* Represents an individual error encountered during the FSCK checks. */
+struct reftable_fsck_info {
+	enum reftable_fsck_error error;
+	const char *msg;
+	const char *path;
+};
+
+typedef int reftable_fsck_report_fn(struct reftable_fsck_info *info,
+				    void *cb_data);
+typedef void reftable_fsck_verbose_fn(const char *msg, void *cb_data);
+
+/*
+ * Given a reftable stack, perform consistency checks on the stack.
+ *
+ * If an issue is encountered, the issue is reported to the callee via the
+ * provided 'report_fn'. If the issue is non-recoverable the flow will not
+ * continue. If it is recoverable, the flow will continue and further issues
+ * will be reported as identified.
+ *
+ * The 'verbose_fn' will be invoked to provide verbose information about
+ * the progress and state of the consistency checks.
+ */
+int reftable_fsck_check(struct reftable_stack *stack,
+			reftable_fsck_report_fn report_fn,
+			reftable_fsck_verbose_fn verbose_fn,
+			void *cb_data);
+
+#endif /* REFTABLE_FSCK_H */
diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h
index 910ec6e..c2415cb 100644
--- a/reftable/reftable-stack.h
+++ b/reftable/reftable-stack.h
@@ -68,12 +68,15 @@ int reftable_addition_commit(struct reftable_addition *add);
  * transaction. Releases the lock if held. */
 void reftable_addition_destroy(struct reftable_addition *add);
 
-/* add a new table to the stack. The write_table function must call
- * reftable_writer_set_limits, add refs and return an error value. */
+/*
+ * Add a new table to the stack. The write_table function must call
+ * reftable_writer_set_limits, add refs and return an error value.
+ * The flags are passed through to `reftable_stack_new_addition()`.
+ */
 int reftable_stack_add(struct reftable_stack *st,
 		       int (*write_table)(struct reftable_writer *wr,
 					  void *write_arg),
-		       void *write_arg);
+		       void *write_arg, unsigned flags);
 
 struct reftable_iterator;
 
@@ -120,6 +123,17 @@ struct reftable_log_expiry_config {
 int reftable_stack_compact_all(struct reftable_stack *st,
 			       struct reftable_log_expiry_config *config);
 
+/*
+ * Check if compaction is required.
+ *
+ * When `use_heuristics` is false, check if all tables can be compacted to a
+ * single table. If true, use heuristics to determine if the tables need to be
+ * compacted to maintain geometric progression.
+ */
+int reftable_stack_compaction_required(struct reftable_stack *st,
+				       bool use_heuristics,
+				       bool *required);
+
 /* heuristically compact unbalanced table stack. */
 int reftable_stack_auto_compact(struct reftable_stack *st);
 
diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h
index 0fbeff1..1e7003c 100644
--- a/reftable/reftable-writer.h
+++ b/reftable/reftable-writer.h
@@ -156,7 +156,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,
   the records before adding them, reordering the records array passed in.
 */
 int reftable_writer_add_refs(struct reftable_writer *w,
-			     struct reftable_ref_record *refs, int n);
+			     struct reftable_ref_record *refs, size_t n);
 
 /*
   adds reftable_log_records. Log records are keyed by (refname, decreasing
@@ -171,7 +171,7 @@ int reftable_writer_add_log(struct reftable_writer *w,
   the records before adding them, reordering records array passed in.
 */
 int reftable_writer_add_logs(struct reftable_writer *w,
-			     struct reftable_log_record *logs, int n);
+			     struct reftable_log_record *logs, size_t n);
 
 /* reftable_writer_close finalizes the reftable. The writer is retained so
  * statistics can be inspected. */
diff --git a/reftable/stack.c b/reftable/stack.c
index 4caf96a..1c9f21d 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -17,18 +17,6 @@
 #include "table.h"
 #include "writer.h"
 
-static int stack_try_add(struct reftable_stack *st,
-			 int (*write_table)(struct reftable_writer *wr,
-					    void *arg),
-			 void *arg);
-static int stack_write_compact(struct reftable_stack *st,
-			       struct reftable_writer *wr,
-			       size_t first, size_t last,
-			       struct reftable_log_expiry_config *config);
-static void reftable_addition_close(struct reftable_addition *add);
-static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
-					     int reuse_open);
-
 static int stack_filename(struct reftable_buf *dest, struct reftable_stack *st,
 			  const char *name)
 {
@@ -84,54 +72,6 @@ static int fd_writer_flush(void *arg)
 	return stack_fsync(writer->opts, writer->fd);
 }
 
-int reftable_new_stack(struct reftable_stack **dest, const char *dir,
-		       const struct reftable_write_options *_opts)
-{
-	struct reftable_buf list_file_name = REFTABLE_BUF_INIT;
-	struct reftable_write_options opts = { 0 };
-	struct reftable_stack *p;
-	int err;
-
-	p = reftable_calloc(1, sizeof(*p));
-	if (!p) {
-		err = REFTABLE_OUT_OF_MEMORY_ERROR;
-		goto out;
-	}
-
-	if (_opts)
-		opts = *_opts;
-	if (opts.hash_id == 0)
-		opts.hash_id = REFTABLE_HASH_SHA1;
-
-	*dest = NULL;
-
-	reftable_buf_reset(&list_file_name);
-	if ((err = reftable_buf_addstr(&list_file_name, dir)) < 0 ||
-	    (err = reftable_buf_addstr(&list_file_name, "/tables.list")) < 0)
-		goto out;
-
-	p->list_file = reftable_buf_detach(&list_file_name);
-	p->list_fd = -1;
-	p->opts = opts;
-	p->reftable_dir = reftable_strdup(dir);
-	if (!p->reftable_dir) {
-		err = REFTABLE_OUT_OF_MEMORY_ERROR;
-		goto out;
-	}
-
-	err = reftable_stack_reload_maybe_reuse(p, 1);
-	if (err < 0)
-		goto out;
-
-	*dest = p;
-	err = 0;
-
-out:
-	if (err < 0)
-		reftable_stack_destroy(p);
-	return err;
-}
-
 static int fd_read_lines(int fd, char ***namesp)
 {
 	char *buf = NULL;
@@ -169,12 +109,7 @@ static int fd_read_lines(int fd, char ***namesp)
 	}
 	buf[size] = 0;
 
-	*namesp = parse_names(buf, size);
-	if (!*namesp) {
-		err = REFTABLE_OUT_OF_MEMORY_ERROR;
-		goto done;
-	}
-
+	err = parse_names(buf, size, namesp);
 done:
 	reftable_free(buf);
 	return err;
@@ -591,9 +526,59 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
 	return err;
 }
 
-/* -1 = error
- 0 = up to date
- 1 = changed. */
+int reftable_new_stack(struct reftable_stack **dest, const char *dir,
+		       const struct reftable_write_options *_opts)
+{
+	struct reftable_buf list_file_name = REFTABLE_BUF_INIT;
+	struct reftable_write_options opts = { 0 };
+	struct reftable_stack *p;
+	int err;
+
+	p = reftable_calloc(1, sizeof(*p));
+	if (!p) {
+		err = REFTABLE_OUT_OF_MEMORY_ERROR;
+		goto out;
+	}
+
+	if (_opts)
+		opts = *_opts;
+	if (opts.hash_id == 0)
+		opts.hash_id = REFTABLE_HASH_SHA1;
+
+	*dest = NULL;
+
+	reftable_buf_reset(&list_file_name);
+	if ((err = reftable_buf_addstr(&list_file_name, dir)) < 0 ||
+	    (err = reftable_buf_addstr(&list_file_name, "/tables.list")) < 0)
+		goto out;
+
+	p->list_file = reftable_buf_detach(&list_file_name);
+	p->list_fd = -1;
+	p->opts = opts;
+	p->reftable_dir = reftable_strdup(dir);
+	if (!p->reftable_dir) {
+		err = REFTABLE_OUT_OF_MEMORY_ERROR;
+		goto out;
+	}
+
+	err = reftable_stack_reload_maybe_reuse(p, 1);
+	if (err < 0)
+		goto out;
+
+	*dest = p;
+	err = 0;
+
+out:
+	if (err < 0)
+		reftable_stack_destroy(p);
+	return err;
+}
+
+/*
+ * Check whether the given stack is up-to-date with what we have in memory.
+ * Returns 0 if so, 1 if the stack is out-of-date or a negative error code
+ * otherwise.
+ */
 static int stack_uptodate(struct reftable_stack *st)
 {
 	char **names = NULL;
@@ -667,34 +652,6 @@ int reftable_stack_reload(struct reftable_stack *st)
 	return err;
 }
 
-int reftable_stack_add(struct reftable_stack *st,
-		       int (*write)(struct reftable_writer *wr, void *arg),
-		       void *arg)
-{
-	int err = stack_try_add(st, write, arg);
-	if (err < 0) {
-		if (err == REFTABLE_OUTDATED_ERROR) {
-			/* Ignore error return, we want to propagate
-			   REFTABLE_OUTDATED_ERROR.
-			*/
-			reftable_stack_reload(st);
-		}
-		return err;
-	}
-
-	return 0;
-}
-
-static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)
-{
-	char buf[100];
-	uint32_t rnd = reftable_rand();
-	snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x",
-		 min, max, rnd);
-	reftable_buf_reset(dest);
-	return reftable_buf_addstr(dest, buf);
-}
-
 struct reftable_addition {
 	struct reftable_flock tables_list_lock;
 	struct reftable_stack *stack;
@@ -704,7 +661,25 @@ struct reftable_addition {
 	uint64_t next_update_index;
 };
 
-#define REFTABLE_ADDITION_INIT {0}
+static void reftable_addition_close(struct reftable_addition *add)
+{
+	struct reftable_buf nm = REFTABLE_BUF_INIT;
+	size_t i;
+
+	for (i = 0; i < add->new_tables_len; i++) {
+		if (!stack_filename(&nm, add->stack, add->new_tables[i]))
+			unlink(nm.buf);
+		reftable_free(add->new_tables[i]);
+		add->new_tables[i] = NULL;
+	}
+	reftable_free(add->new_tables);
+	add->new_tables = NULL;
+	add->new_tables_len = 0;
+	add->new_tables_cap = 0;
+
+	flock_release(&add->tables_list_lock);
+	reftable_buf_release(&nm);
+}
 
 static int reftable_stack_init_addition(struct reftable_addition *add,
 					struct reftable_stack *st,
@@ -713,18 +688,14 @@ static int reftable_stack_init_addition(struct reftable_addition *add,
 	struct reftable_buf lock_file_name = REFTABLE_BUF_INIT;
 	int err;
 
+	memset(add, 0, sizeof(*add));
 	add->stack = st;
 
 	err = flock_acquire(&add->tables_list_lock, st->list_file,
 			    st->opts.lock_timeout_ms);
-	if (err < 0) {
-		if (errno == EEXIST) {
-			err = REFTABLE_LOCK_ERROR;
-		} else {
-			err = REFTABLE_IO_ERROR;
-		}
+	if (err < 0)
 		goto done;
-	}
+
 	if (st->opts.default_permissions) {
 		if (chmod(add->tables_list_lock.path,
 			  st->opts.default_permissions) < 0) {
@@ -754,24 +725,54 @@ static int reftable_stack_init_addition(struct reftable_addition *add,
 	return err;
 }
 
-static void reftable_addition_close(struct reftable_addition *add)
+static int stack_try_add(struct reftable_stack *st,
+			 int (*write_table)(struct reftable_writer *wr,
+					    void *arg),
+			 void *arg, unsigned flags)
 {
-	struct reftable_buf nm = REFTABLE_BUF_INIT;
-	size_t i;
+	struct reftable_addition add;
+	int err;
 
-	for (i = 0; i < add->new_tables_len; i++) {
-		if (!stack_filename(&nm, add->stack, add->new_tables[i]))
-			unlink(nm.buf);
-		reftable_free(add->new_tables[i]);
-		add->new_tables[i] = NULL;
+	err = reftable_stack_init_addition(&add, st, flags);
+	if (err < 0)
+		goto done;
+
+	err = reftable_addition_add(&add, write_table, arg);
+	if (err < 0)
+		goto done;
+
+	err = reftable_addition_commit(&add);
+done:
+	reftable_addition_close(&add);
+	return err;
+}
+
+int reftable_stack_add(struct reftable_stack *st,
+		       int (*write)(struct reftable_writer *wr, void *arg),
+		       void *arg, unsigned flags)
+{
+	int err = stack_try_add(st, write, arg, flags);
+	if (err < 0) {
+		if (err == REFTABLE_OUTDATED_ERROR) {
+			/* Ignore error return, we want to propagate
+			   REFTABLE_OUTDATED_ERROR.
+			*/
+			reftable_stack_reload(st);
+		}
+		return err;
 	}
-	reftable_free(add->new_tables);
-	add->new_tables = NULL;
-	add->new_tables_len = 0;
-	add->new_tables_cap = 0;
 
-	flock_release(&add->tables_list_lock);
-	reftable_buf_release(&nm);
+	return 0;
+}
+
+static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)
+{
+	char buf[100];
+	uint32_t rnd = reftable_rand();
+	snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x",
+		 min, max, rnd);
+	reftable_buf_reset(dest);
+	return reftable_buf_addstr(dest, buf);
 }
 
 void reftable_addition_destroy(struct reftable_addition *add)
@@ -841,10 +842,13 @@ int reftable_addition_commit(struct reftable_addition *add)
 		 * control. It is possible that a concurrent writer is already
 		 * trying to compact parts of the stack, which would lead to a
 		 * `REFTABLE_LOCK_ERROR` because parts of the stack are locked
-		 * already. This is a benign error though, so we ignore it.
+		 * already. Similarly, the stack may have been rewritten by a
+		 * concurrent writer, which causes `REFTABLE_OUTDATED_ERROR`.
+		 * Both of these errors are benign, so we simply ignore them.
 		 */
 		err = reftable_stack_auto_compact(add->stack);
-		if (err < 0 && err != REFTABLE_LOCK_ERROR)
+		if (err < 0 && err != REFTABLE_LOCK_ERROR &&
+		    err != REFTABLE_OUTDATED_ERROR)
 			goto done;
 		err = 0;
 	}
@@ -858,39 +862,18 @@ int reftable_stack_new_addition(struct reftable_addition **dest,
 				struct reftable_stack *st,
 				unsigned int flags)
 {
-	int err = 0;
-	struct reftable_addition empty = REFTABLE_ADDITION_INIT;
+	int err;
 
 	REFTABLE_CALLOC_ARRAY(*dest, 1);
 	if (!*dest)
 		return REFTABLE_OUT_OF_MEMORY_ERROR;
 
-	**dest = empty;
 	err = reftable_stack_init_addition(*dest, st, flags);
 	if (err) {
 		reftable_free(*dest);
 		*dest = NULL;
 	}
-	return err;
-}
 
-static int stack_try_add(struct reftable_stack *st,
-			 int (*write_table)(struct reftable_writer *wr,
-					    void *arg),
-			 void *arg)
-{
-	struct reftable_addition add = REFTABLE_ADDITION_INIT;
-	int err = reftable_stack_init_addition(&add, st, 0);
-	if (err < 0)
-		goto done;
-
-	err = reftable_addition_add(&add, write_table, arg);
-	if (err < 0)
-		goto done;
-
-	err = reftable_addition_commit(&add);
-done:
-	reftable_addition_close(&add);
 	return err;
 }
 
@@ -1007,72 +990,6 @@ uint64_t reftable_stack_next_update_index(struct reftable_stack *st)
 	return 1;
 }
 
-static int stack_compact_locked(struct reftable_stack *st,
-				size_t first, size_t last,
-				struct reftable_log_expiry_config *config,
-				struct reftable_tmpfile *tab_file_out)
-{
-	struct reftable_buf next_name = REFTABLE_BUF_INIT;
-	struct reftable_buf tab_file_path = REFTABLE_BUF_INIT;
-	struct reftable_writer *wr = NULL;
-	struct fd_writer writer=  {
-		.opts = &st->opts,
-	};
-	struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT;
-	int err = 0;
-
-	err = format_name(&next_name, reftable_table_min_update_index(st->tables[first]),
-			  reftable_table_max_update_index(st->tables[last]));
-	if (err < 0)
-		goto done;
-
-	err = stack_filename(&tab_file_path, st, next_name.buf);
-	if (err < 0)
-		goto done;
-
-	err = reftable_buf_addstr(&tab_file_path, ".temp.XXXXXX");
-	if (err < 0)
-		goto done;
-
-	err = tmpfile_from_pattern(&tab_file, tab_file_path.buf);
-	if (err < 0)
-		goto done;
-
-	if (st->opts.default_permissions &&
-	    chmod(tab_file.path, st->opts.default_permissions) < 0) {
-		err = REFTABLE_IO_ERROR;
-		goto done;
-	}
-
-	writer.fd = tab_file.fd;
-	err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush,
-				  &writer, &st->opts);
-	if (err < 0)
-		goto done;
-
-	err = stack_write_compact(st, wr, first, last, config);
-	if (err < 0)
-		goto done;
-
-	err = reftable_writer_close(wr);
-	if (err < 0)
-		goto done;
-
-	err = tmpfile_close(&tab_file);
-	if (err < 0)
-		goto done;
-
-	*tab_file_out = tab_file;
-	tab_file = REFTABLE_TMPFILE_INIT;
-
-done:
-	tmpfile_delete(&tab_file);
-	reftable_writer_free(wr);
-	reftable_buf_release(&next_name);
-	reftable_buf_release(&tab_file_path);
-	return err;
-}
-
 static int stack_write_compact(struct reftable_stack *st,
 			       struct reftable_writer *wr,
 			       size_t first, size_t last,
@@ -1172,6 +1089,72 @@ static int stack_write_compact(struct reftable_stack *st,
 	return err;
 }
 
+static int stack_compact_locked(struct reftable_stack *st,
+				size_t first, size_t last,
+				struct reftable_log_expiry_config *config,
+				struct reftable_tmpfile *tab_file_out)
+{
+	struct reftable_buf next_name = REFTABLE_BUF_INIT;
+	struct reftable_buf tab_file_path = REFTABLE_BUF_INIT;
+	struct reftable_writer *wr = NULL;
+	struct fd_writer writer=  {
+		.opts = &st->opts,
+	};
+	struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT;
+	int err = 0;
+
+	err = format_name(&next_name, reftable_table_min_update_index(st->tables[first]),
+			  reftable_table_max_update_index(st->tables[last]));
+	if (err < 0)
+		goto done;
+
+	err = stack_filename(&tab_file_path, st, next_name.buf);
+	if (err < 0)
+		goto done;
+
+	err = reftable_buf_addstr(&tab_file_path, ".temp.XXXXXX");
+	if (err < 0)
+		goto done;
+
+	err = tmpfile_from_pattern(&tab_file, tab_file_path.buf);
+	if (err < 0)
+		goto done;
+
+	if (st->opts.default_permissions &&
+	    chmod(tab_file.path, st->opts.default_permissions) < 0) {
+		err = REFTABLE_IO_ERROR;
+		goto done;
+	}
+
+	writer.fd = tab_file.fd;
+	err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush,
+				  &writer, &st->opts);
+	if (err < 0)
+		goto done;
+
+	err = stack_write_compact(st, wr, first, last, config);
+	if (err < 0)
+		goto done;
+
+	err = reftable_writer_close(wr);
+	if (err < 0)
+		goto done;
+
+	err = tmpfile_close(&tab_file);
+	if (err < 0)
+		goto done;
+
+	*tab_file_out = tab_file;
+	tab_file = REFTABLE_TMPFILE_INIT;
+
+done:
+	tmpfile_delete(&tab_file);
+	reftable_writer_free(wr);
+	reftable_buf_release(&next_name);
+	reftable_buf_release(&tab_file_path);
+	return err;
+}
+
 enum stack_compact_range_flags {
 	/*
 	 * Perform a best-effort compaction. That is, even if we cannot lock
@@ -1219,18 +1202,28 @@ static int stack_compact_range(struct reftable_stack *st,
 	 * which are part of the user-specified range.
 	 */
 	err = flock_acquire(&tables_list_lock, st->list_file, st->opts.lock_timeout_ms);
-	if (err < 0) {
-		if (errno == EEXIST)
-			err = REFTABLE_LOCK_ERROR;
-		else
-			err = REFTABLE_IO_ERROR;
+	if (err < 0)
+		goto done;
+
+	/*
+	 * Check whether the stack is up-to-date. We unfortunately cannot
+	 * handle the situation gracefully in case it's _not_ up-to-date
+	 * because the range of tables that the user has requested us to
+	 * compact may have been changed. So instead we abort.
+	 *
+	 * We could in theory improve the situation by having the caller not
+	 * pass in a range, but instead the list of tables to compact. If so,
+	 * we could check that relevant tables still exist. But for now it's
+	 * good enough to just abort.
+	 */
+	err = stack_uptodate(st);
+	if (err < 0)
+		goto done;
+	if (err > 0) {
+		err = REFTABLE_OUTDATED_ERROR;
 		goto done;
 	}
 
-	err = stack_uptodate(st);
-	if (err)
-		goto done;
-
 	/*
 	 * Lock all tables in the user-provided range. This is the slice of our
 	 * stack which we'll compact.
@@ -1264,7 +1257,7 @@ static int stack_compact_range(struct reftable_stack *st,
 			 * tables, otherwise there would be nothing to compact.
 			 * In that case, we return a lock error to our caller.
 			 */
-			if (errno == EEXIST && last - (i - 1) >= 2 &&
+			if (err == REFTABLE_LOCK_ERROR && last - (i - 1) >= 2 &&
 			    flags & STACK_COMPACT_RANGE_BEST_EFFORT) {
 				err = 0;
 				/*
@@ -1276,13 +1269,9 @@ static int stack_compact_range(struct reftable_stack *st,
 				 */
 				first = (i - 1) + 1;
 				break;
-			} else if (errno == EEXIST) {
-				err = REFTABLE_LOCK_ERROR;
-				goto done;
-			} else {
-				err = REFTABLE_IO_ERROR;
-				goto done;
 			}
+
+			goto done;
 		}
 
 		/*
@@ -1291,10 +1280,8 @@ static int stack_compact_range(struct reftable_stack *st,
 		 * of tables.
 		 */
 		err = flock_close(&table_locks[nlocks++]);
-		if (err < 0) {
-			err = REFTABLE_IO_ERROR;
+		if (err < 0)
 			goto done;
-		}
 	}
 
 	/*
@@ -1326,13 +1313,8 @@ static int stack_compact_range(struct reftable_stack *st,
 	 * the new table.
 	 */
 	err = flock_acquire(&tables_list_lock, st->list_file, st->opts.lock_timeout_ms);
-	if (err < 0) {
-		if (errno == EEXIST)
-			err = REFTABLE_LOCK_ERROR;
-		else
-			err = REFTABLE_IO_ERROR;
+	if (err < 0)
 		goto done;
-	}
 
 	if (st->opts.default_permissions) {
 		if (chmod(tables_list_lock.path,
@@ -1644,7 +1626,8 @@ struct segment suggest_compaction_segment(uint64_t *sizes, size_t n,
 	return seg;
 }
 
-static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st)
+static int stack_segments_for_compaction(struct reftable_stack *st,
+					 struct segment *seg)
 {
 	int version = (st->opts.hash_id == REFTABLE_HASH_SHA1) ? 1 : 2;
 	int overhead = header_size(version) - 1;
@@ -1652,31 +1635,63 @@ static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st)
 
 	REFTABLE_CALLOC_ARRAY(sizes, st->merged->tables_len);
 	if (!sizes)
-		return NULL;
+		return REFTABLE_OUT_OF_MEMORY_ERROR;
 
 	for (size_t i = 0; i < st->merged->tables_len; i++)
 		sizes[i] = st->tables[i]->size - overhead;
 
-	return sizes;
+	*seg = suggest_compaction_segment(sizes, st->merged->tables_len,
+					  st->opts.auto_compaction_factor);
+	reftable_free(sizes);
+
+	return 0;
+}
+
+static int update_segment_if_compaction_required(struct reftable_stack *st,
+						 struct segment *seg,
+						 bool use_geometric,
+						 bool *required)
+{
+	int err;
+
+	if (st->merged->tables_len < 2) {
+		*required = false;
+		return 0;
+	}
+
+	if (!use_geometric) {
+		*required = true;
+		return 0;
+	}
+
+	err = stack_segments_for_compaction(st, seg);
+	if (err)
+		return err;
+
+	*required = segment_size(seg) > 0;
+	return 0;
+}
+
+int reftable_stack_compaction_required(struct reftable_stack *st,
+				       bool use_heuristics,
+				       bool *required)
+{
+	struct segment seg;
+	return update_segment_if_compaction_required(st, &seg, use_heuristics,
+						     required);
 }
 
 int reftable_stack_auto_compact(struct reftable_stack *st)
 {
 	struct segment seg;
-	uint64_t *sizes;
+	bool required;
+	int err;
 
-	if (st->merged->tables_len < 2)
-		return 0;
+	err = update_segment_if_compaction_required(st, &seg, true, &required);
+	if (err)
+		return err;
 
-	sizes = stack_table_sizes_for_compaction(st);
-	if (!sizes)
-		return REFTABLE_OUT_OF_MEMORY_ERROR;
-
-	seg = suggest_compaction_segment(sizes, st->merged->tables_len,
-					 st->opts.auto_compaction_factor);
-	reftable_free(sizes);
-
-	if (segment_size(&seg) > 0)
+	if (required)
 		return stack_compact_range(st, seg.start, seg.end - 1,
 					   NULL, STACK_COMPACT_RANGE_BEST_EFFORT);
 
diff --git a/reftable/system.c b/reftable/system.c
index 1ee268b..725a258 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -72,7 +72,7 @@ int flock_acquire(struct reftable_flock *l, const char *target_path,
 		reftable_free(lockfile);
 		if (errno == EEXIST)
 			return REFTABLE_LOCK_ERROR;
-		return -1;
+		return REFTABLE_IO_ERROR;
 	}
 
 	l->fd = get_lock_file_fd(lockfile);
diff --git a/reftable/system.h b/reftable/system.h
index beb9d24..c54ed4c 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -81,7 +81,9 @@ struct reftable_flock {
  * to acquire the lock. If `timeout_ms` is 0 we don't wait, if it is negative
  * we block indefinitely.
  *
- * Retrun 0 on success, a reftable error code on error.
+ * Retrun 0 on success, a reftable error code on error. Specifically,
+ * `REFTABLE_LOCK_ERROR` should be returned in case the target path is already
+ * locked.
  */
 int flock_acquire(struct reftable_flock *l, const char *target_path,
 		  long timeout_ms);
diff --git a/reftable/writer.c b/reftable/writer.c
index 3b4ebdd..0133b64 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -395,14 +395,16 @@ int reftable_writer_add_ref(struct reftable_writer *w,
 }
 
 int reftable_writer_add_refs(struct reftable_writer *w,
-			     struct reftable_ref_record *refs, int n)
+			     struct reftable_ref_record *refs, size_t n)
 {
 	int err = 0;
-	int i = 0;
-	QSORT(refs, n, reftable_ref_record_compare_name);
-	for (i = 0; err == 0 && i < n; i++) {
+
+	if (n)
+		qsort(refs, n, sizeof(*refs), reftable_ref_record_compare_name);
+
+	for (size_t i = 0; err == 0 && i < n; i++)
 		err = reftable_writer_add_ref(w, &refs[i]);
-	}
+
 	return err;
 }
 
@@ -486,15 +488,16 @@ int reftable_writer_add_log(struct reftable_writer *w,
 }
 
 int reftable_writer_add_logs(struct reftable_writer *w,
-			     struct reftable_log_record *logs, int n)
+			     struct reftable_log_record *logs, size_t n)
 {
 	int err = 0;
-	int i = 0;
-	QSORT(logs, n, reftable_log_record_compare_key);
 
-	for (i = 0; err == 0 && i < n; i++) {
+	if (n)
+		qsort(logs, n, sizeof(*logs), reftable_log_record_compare_key);
+
+	for (size_t i = 0; err == 0 && i < n; i++)
 		err = reftable_writer_add_log(w, &logs[i]);
-	}
+
 	return err;
 }
 
diff --git a/remote.c b/remote.c
index df88914..59b3715 100644
--- a/remote.c
+++ b/remote.c
@@ -2143,9 +2143,6 @@ static int stat_branch_pair(const char *branch_name, const char *base,
 	struct object_id oid;
 	struct commit *ours, *theirs;
 	struct rev_info revs;
-	struct setup_revision_opt opt = {
-		.free_removed_argv_elements = 1,
-	};
 	struct strvec argv = STRVEC_INIT;
 
 	/* Cannot stat if what we used to build on no longer exists */
@@ -2180,7 +2177,7 @@ static int stat_branch_pair(const char *branch_name, const char *base,
 	strvec_push(&argv, "--");
 
 	repo_init_revisions(the_repository, &revs, NULL);
-	setup_revisions(argv.nr, argv.v, &revs, &opt);
+	setup_revisions_from_strvec(&argv, &revs, NULL);
 	if (prepare_revision_walk(&revs))
 		die(_("revision walk setup failed"));
 
@@ -2318,21 +2315,19 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
 	return 1;
 }
 
-static int one_local_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			 int flag UNUSED,
-			 void *cb_data)
+static int one_local_ref(const struct reference *ref, void *cb_data)
 {
 	struct ref ***local_tail = cb_data;
-	struct ref *ref;
+	struct ref *local_ref;
 
 	/* we already know it starts with refs/ to get here */
-	if (check_refname_format(refname + 5, 0))
+	if (check_refname_format(ref->name + 5, 0))
 		return 0;
 
-	ref = alloc_ref(refname);
-	oidcpy(&ref->new_oid, oid);
-	**local_tail = ref;
-	*local_tail = &ref->next;
+	local_ref = alloc_ref(ref->name);
+	oidcpy(&local_ref->new_oid, ref->oid);
+	**local_tail = local_ref;
+	*local_tail = &local_ref->next;
 	return 0;
 }
 
@@ -2405,15 +2400,14 @@ struct stale_heads_info {
 	struct refspec *rs;
 };
 
-static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-			      int flags, void *cb_data)
+static int get_stale_heads_cb(const struct reference *ref, void *cb_data)
 {
 	struct stale_heads_info *info = cb_data;
 	struct string_list matches = STRING_LIST_INIT_DUP;
 	struct refspec_item query;
 	int i, stale = 1;
 	memset(&query, 0, sizeof(struct refspec_item));
-	query.dst = (char *)refname;
+	query.dst = (char *)ref->name;
 
 	refspec_find_all_matches(info->rs, &query, &matches);
 	if (matches.nr == 0)
@@ -2426,7 +2420,7 @@ static int get_stale_heads_cb(const char *refname, const char *referent UNUSED,
 	 * overlapping refspecs, we need to go over all of the
 	 * matching refs.
 	 */
-	if (flags & REF_ISSYMREF)
+	if (ref->flags & REF_ISSYMREF)
 		goto clean_exit;
 
 	for (i = 0; stale && i < matches.nr; i++)
@@ -2434,8 +2428,8 @@ static int get_stale_heads_cb(const char *refname, const char *referent UNUSED,
 			stale = 0;
 
 	if (stale) {
-		struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
-		oidcpy(&ref->new_oid, oid);
+		struct ref *linked_ref = make_linked_ref(ref->name, &info->stale_refs_tail);
+		oidcpy(&linked_ref->new_oid, ref->oid);
 	}
 
 clean_exit:
@@ -2584,7 +2578,8 @@ struct check_and_collect_until_cb_data {
 };
 
 /* Get the timestamp of the latest entry. */
-static int peek_reflog(struct object_id *o_oid UNUSED,
+static int peek_reflog(const char *refname UNUSED,
+		       struct object_id *o_oid UNUSED,
 		       struct object_id *n_oid UNUSED,
 		       const char *ident UNUSED,
 		       timestamp_t timestamp, int tz UNUSED,
@@ -2595,7 +2590,8 @@ static int peek_reflog(struct object_id *o_oid UNUSED,
 	return 1;
 }
 
-static int check_and_collect_until(struct object_id *o_oid UNUSED,
+static int check_and_collect_until(const char *refname UNUSED,
+				   struct object_id *o_oid UNUSED,
 				   struct object_id *n_oid,
 				   const char *ident UNUSED,
 				   timestamp_t timestamp, int tz UNUSED,
diff --git a/repack-cruft.c b/repack-cruft.c
new file mode 100644
index 0000000..0653e88
--- /dev/null
+++ b/repack-cruft.c
@@ -0,0 +1,98 @@
+#include "git-compat-util.h"
+#include "repack.h"
+#include "packfile.h"
+#include "repository.h"
+#include "run-command.h"
+
+static void combine_small_cruft_packs(FILE *in, off_t combine_cruft_below_size,
+				      struct existing_packs *existing)
+{
+	struct packed_git *p;
+	struct strbuf buf = STRBUF_INIT;
+	size_t i;
+
+	repo_for_each_pack(existing->repo, p) {
+		if (!(p->is_cruft && p->pack_local))
+			continue;
+
+		strbuf_reset(&buf);
+		strbuf_addstr(&buf, pack_basename(p));
+		strbuf_strip_suffix(&buf, ".pack");
+
+		if (!string_list_has_string(&existing->cruft_packs, buf.buf))
+			continue;
+
+		if (p->pack_size < combine_cruft_below_size) {
+			fprintf(in, "-%s\n", pack_basename(p));
+		} else {
+			existing_packs_retain_cruft(existing, p);
+			fprintf(in, "%s\n", pack_basename(p));
+		}
+	}
+
+	for (i = 0; i < existing->non_kept_packs.nr; i++)
+		fprintf(in, "-%s.pack\n",
+			existing->non_kept_packs.items[i].string);
+
+	strbuf_release(&buf);
+}
+
+int write_cruft_pack(const struct write_pack_opts *opts,
+		     const char *cruft_expiration,
+		     unsigned long combine_cruft_below_size,
+		     struct string_list *names,
+		     struct existing_packs *existing)
+{
+	struct child_process cmd = CHILD_PROCESS_INIT;
+	struct string_list_item *item;
+	FILE *in;
+	int ret;
+	const char *pack_prefix = write_pack_opts_pack_prefix(opts);
+
+	prepare_pack_objects(&cmd, opts->po_args, opts->destination);
+
+	strvec_push(&cmd.args, "--cruft");
+	if (cruft_expiration)
+		strvec_pushf(&cmd.args, "--cruft-expiration=%s",
+			     cruft_expiration);
+
+	strvec_push(&cmd.args, "--non-empty");
+
+	cmd.in = -1;
+
+	ret = start_command(&cmd);
+	if (ret)
+		return ret;
+
+	/*
+	 * names has a confusing double use: it both provides the list
+	 * of just-written new packs, and accepts the name of the cruft
+	 * pack we are writing.
+	 *
+	 * By the time it is read here, it contains only the pack(s)
+	 * that were just written, which is exactly the set of packs we
+	 * want to consider kept.
+	 *
+	 * If `--expire-to` is given, the double-use served by `names`
+	 * ensures that the pack written to `--expire-to` excludes any
+	 * objects contained in the cruft pack.
+	 */
+	in = xfdopen(cmd.in, "w");
+	for_each_string_list_item(item, names)
+		fprintf(in, "%s-%s.pack\n", pack_prefix, item->string);
+	if (combine_cruft_below_size && !cruft_expiration) {
+		combine_small_cruft_packs(in, combine_cruft_below_size,
+					  existing);
+	} else {
+		for_each_string_list_item(item, &existing->non_kept_packs)
+			fprintf(in, "-%s.pack\n", item->string);
+		for_each_string_list_item(item, &existing->cruft_packs)
+			fprintf(in, "-%s.pack\n", item->string);
+	}
+	for_each_string_list_item(item, &existing->kept_packs)
+		fprintf(in, "%s.pack\n", item->string);
+	fclose(in);
+
+	return finish_pack_objects_cmd(existing->repo->hash_algo, opts, &cmd,
+				       names);
+}
diff --git a/repack-filtered.c b/repack-filtered.c
new file mode 100644
index 0000000..edcf766
--- /dev/null
+++ b/repack-filtered.c
@@ -0,0 +1,51 @@
+#include "git-compat-util.h"
+#include "repack.h"
+#include "repository.h"
+#include "run-command.h"
+#include "string-list.h"
+
+int write_filtered_pack(const struct write_pack_opts *opts,
+			struct existing_packs *existing,
+			struct string_list *names)
+{
+	struct child_process cmd = CHILD_PROCESS_INIT;
+	struct string_list_item *item;
+	FILE *in;
+	int ret;
+	const char *caret;
+	const char *pack_prefix = write_pack_opts_pack_prefix(opts);
+
+	prepare_pack_objects(&cmd, opts->po_args, opts->destination);
+
+	strvec_push(&cmd.args, "--stdin-packs");
+
+	for_each_string_list_item(item, &existing->kept_packs)
+		strvec_pushf(&cmd.args, "--keep-pack=%s", item->string);
+
+	cmd.in = -1;
+
+	ret = start_command(&cmd);
+	if (ret)
+		return ret;
+
+	/*
+	 * Here 'names' contains only the pack(s) that were just
+	 * written, which is exactly the packs we want to keep. Also
+	 * 'existing_kept_packs' already contains the packs in
+	 * 'keep_pack_list'.
+	 */
+	in = xfdopen(cmd.in, "w");
+	for_each_string_list_item(item, names)
+		fprintf(in, "^%s-%s.pack\n", pack_prefix, item->string);
+	for_each_string_list_item(item, &existing->non_kept_packs)
+		fprintf(in, "%s.pack\n", item->string);
+	for_each_string_list_item(item, &existing->cruft_packs)
+		fprintf(in, "%s.pack\n", item->string);
+	caret = opts->po_args->pack_kept_objects ? "" : "^";
+	for_each_string_list_item(item, &existing->kept_packs)
+		fprintf(in, "%s%s.pack\n", caret, item->string);
+	fclose(in);
+
+	return finish_pack_objects_cmd(existing->repo->hash_algo, opts, &cmd,
+				       names);
+}
diff --git a/repack-geometry.c b/repack-geometry.c
new file mode 100644
index 0000000..b3e32cd
--- /dev/null
+++ b/repack-geometry.c
@@ -0,0 +1,232 @@
+#define DISABLE_SIGN_COMPARE_WARNINGS
+
+#include "git-compat-util.h"
+#include "repack.h"
+#include "repository.h"
+#include "hex.h"
+#include "packfile.h"
+
+static uint32_t pack_geometry_weight(struct packed_git *p)
+{
+	if (open_pack_index(p))
+		die(_("cannot open index for %s"), p->pack_name);
+	return p->num_objects;
+}
+
+static int pack_geometry_cmp(const void *va, const void *vb)
+{
+	uint32_t aw = pack_geometry_weight(*(struct packed_git **)va),
+		 bw = pack_geometry_weight(*(struct packed_git **)vb);
+
+	if (aw < bw)
+		return -1;
+	if (aw > bw)
+		return 1;
+	return 0;
+}
+
+void pack_geometry_init(struct pack_geometry *geometry,
+			struct existing_packs *existing,
+			const struct pack_objects_args *args)
+{
+	struct packed_git *p;
+	struct strbuf buf = STRBUF_INIT;
+
+	repo_for_each_pack(existing->repo, p) {
+		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 (!args->pack_kept_objects) {
+			/*
+			 * Any pack that has its pack_keep bit set will
+			 * appear in existing->kept_packs below, but
+			 * this saves us from doing a more expensive
+			 * check.
+			 */
+			if (p->pack_keep)
+				continue;
+
+			/*
+			 * The pack may be kept via the --keep-pack
+			 * option; check 'existing->kept_packs' to
+			 * determine whether to ignore it.
+			 */
+			strbuf_reset(&buf);
+			strbuf_addstr(&buf, pack_basename(p));
+			strbuf_strip_suffix(&buf, ".pack");
+
+			if (string_list_has_string(&existing->kept_packs, buf.buf))
+				continue;
+		}
+		if (p->is_cruft)
+			continue;
+
+		ALLOC_GROW(geometry->pack,
+			   geometry->pack_nr + 1,
+			   geometry->pack_alloc);
+
+		geometry->pack[geometry->pack_nr] = p;
+		geometry->pack_nr++;
+	}
+
+	QSORT(geometry->pack, geometry->pack_nr, pack_geometry_cmp);
+	strbuf_release(&buf);
+}
+
+void pack_geometry_split(struct pack_geometry *geometry)
+{
+	uint32_t i;
+	uint32_t split;
+	off_t total_size = 0;
+
+	if (!geometry->pack_nr) {
+		geometry->split = geometry->pack_nr;
+		return;
+	}
+
+	/*
+	 * First, count the number of packs (in descending order of size) which
+	 * already form a geometric progression.
+	 */
+	for (i = geometry->pack_nr - 1; i > 0; i--) {
+		struct packed_git *ours = geometry->pack[i];
+		struct packed_git *prev = geometry->pack[i - 1];
+
+		if (unsigned_mult_overflows(geometry->split_factor,
+					    pack_geometry_weight(prev)))
+			die(_("pack %s too large to consider in geometric "
+			      "progression"),
+			    prev->pack_name);
+
+		if (pack_geometry_weight(ours) <
+		    geometry->split_factor * pack_geometry_weight(prev))
+			break;
+	}
+
+	split = i;
+
+	if (split) {
+		/*
+		 * Move the split one to the right, since the top element in the
+		 * last-compared pair can't be in the progression. Only do this
+		 * when we split in the middle of the array (otherwise if we got
+		 * to the end, then the split is in the right place).
+		 */
+		split++;
+	}
+
+	/*
+	 * Then, anything to the left of 'split' must be in a new pack. But,
+	 * creating that new pack may cause packs in the heavy half to no longer
+	 * form a geometric progression.
+	 *
+	 * Compute an expected size of the new pack, and then determine how many
+	 * packs in the heavy half need to be joined into it (if any) to restore
+	 * the geometric progression.
+	 */
+	for (i = 0; i < split; i++) {
+		struct packed_git *p = geometry->pack[i];
+
+		if (unsigned_add_overflows(total_size, pack_geometry_weight(p)))
+			die(_("pack %s too large to roll up"), p->pack_name);
+		total_size += pack_geometry_weight(p);
+	}
+	for (i = split; i < geometry->pack_nr; i++) {
+		struct packed_git *ours = geometry->pack[i];
+
+		if (unsigned_mult_overflows(geometry->split_factor,
+					    total_size))
+			die(_("pack %s too large to roll up"), ours->pack_name);
+
+		if (pack_geometry_weight(ours) <
+		    geometry->split_factor * total_size) {
+			if (unsigned_add_overflows(total_size,
+						   pack_geometry_weight(ours)))
+				die(_("pack %s too large to roll up"),
+				    ours->pack_name);
+
+			split++;
+			total_size += pack_geometry_weight(ours);
+		} else
+			break;
+	}
+
+	geometry->split = split;
+}
+
+struct packed_git *pack_geometry_preferred_pack(struct pack_geometry *geometry)
+{
+	uint32_t i;
+
+	if (!geometry) {
+		/*
+		 * No geometry means either an all-into-one repack (in which
+		 * case there is only one pack left and it is the largest) or an
+		 * incremental one.
+		 *
+		 * If repacking incrementally, then we could check the size of
+		 * all packs to determine which should be preferred, but leave
+		 * this for later.
+		 */
+		return NULL;
+	}
+	if (geometry->split == geometry->pack_nr)
+		return NULL;
+
+	/*
+	 * 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;
+}
+
+void pack_geometry_remove_redundant(struct pack_geometry *geometry,
+				    struct string_list *names,
+				    struct existing_packs *existing,
+				    const char *packdir)
+{
+	const struct git_hash_algo *algop = existing->repo->hash_algo;
+	struct strbuf buf = STRBUF_INIT;
+	uint32_t i;
+
+	for (i = 0; i < geometry->split; i++) {
+		struct packed_git *p = geometry->pack[i];
+		if (string_list_has_string(names, hash_to_hex_algop(p->hash,
+								    algop)))
+			continue;
+
+		strbuf_reset(&buf);
+		strbuf_addstr(&buf, pack_basename(p));
+		strbuf_strip_suffix(&buf, ".pack");
+
+		if ((p->pack_keep) ||
+		    (string_list_has_string(&existing->kept_packs, buf.buf)))
+			continue;
+
+		repack_remove_redundant_pack(existing->repo, packdir, buf.buf);
+	}
+
+	strbuf_release(&buf);
+}
+
+void pack_geometry_release(struct pack_geometry *geometry)
+{
+	if (!geometry)
+		return;
+
+	free(geometry->pack);
+}
diff --git a/repack-midx.c b/repack-midx.c
new file mode 100644
index 0000000..74bdfa3
--- /dev/null
+++ b/repack-midx.c
@@ -0,0 +1,370 @@
+#include "git-compat-util.h"
+#include "repack.h"
+#include "hash.h"
+#include "hex.h"
+#include "odb.h"
+#include "oidset.h"
+#include "pack-bitmap.h"
+#include "refs.h"
+#include "run-command.h"
+#include "tempfile.h"
+
+struct midx_snapshot_ref_data {
+	struct repository *repo;
+	struct tempfile *f;
+	struct oidset seen;
+	int preferred;
+};
+
+static int midx_snapshot_ref_one(const struct reference *ref, void *_data)
+{
+	struct midx_snapshot_ref_data *data = _data;
+	const struct object_id *maybe_peeled = ref->oid;
+	struct object_id peeled;
+
+	if (!reference_get_peeled_oid(data->repo, ref, &peeled))
+		maybe_peeled = &peeled;
+
+	if (oidset_insert(&data->seen, maybe_peeled))
+		return 0; /* already seen */
+
+	if (odb_read_object_info(data->repo->objects, maybe_peeled, NULL) != OBJ_COMMIT)
+		return 0;
+
+	fprintf(data->f->fp, "%s%s\n", data->preferred ? "+" : "",
+		oid_to_hex(maybe_peeled));
+
+	return 0;
+}
+
+void midx_snapshot_refs(struct repository *repo, struct tempfile *f)
+{
+	struct midx_snapshot_ref_data data;
+	const struct string_list *preferred = bitmap_preferred_tips(repo);
+
+	data.repo = repo;
+	data.f = f;
+	data.preferred = 0;
+	oidset_init(&data.seen, 0);
+
+	if (!fdopen_tempfile(f, "w"))
+		 die(_("could not open tempfile %s for writing"),
+		     get_tempfile_path(f));
+
+	if (preferred) {
+		struct string_list_item *item;
+
+		data.preferred = 1;
+		for_each_string_list_item(item, preferred)
+			refs_for_each_ref_in(get_main_ref_store(repo),
+					     item->string,
+					     midx_snapshot_ref_one, &data);
+		data.preferred = 0;
+	}
+
+	refs_for_each_ref(get_main_ref_store(repo),
+			  midx_snapshot_ref_one, &data);
+
+	if (close_tempfile_gently(f)) {
+		int save_errno = errno;
+		delete_tempfile(&f);
+		errno = save_errno;
+		die_errno(_("could not close refs snapshot tempfile"));
+	}
+
+	oidset_clear(&data.seen);
+}
+
+static int midx_has_unknown_packs(struct string_list *include,
+				  struct pack_geometry *geometry,
+				  struct existing_packs *existing)
+{
+	struct string_list_item *item;
+
+	string_list_sort(include);
+
+	for_each_string_list_item(item, &existing->midx_packs) {
+		const char *pack_name = item->string;
+
+		/*
+		 * Determine whether or not each MIDX'd pack from the existing
+		 * MIDX (if any) is represented in the new MIDX. For each pack
+		 * in the MIDX, it must either be:
+		 *
+		 *  - In the "include" list of packs to be included in the new
+		 *    MIDX. Note this function is called before the include
+		 *    list is populated with any cruft pack(s).
+		 *
+		 *  - Below the geometric split line (if using pack geometry),
+		 *    indicating that the pack won't be included in the new
+		 *    MIDX, but its contents were rolled up as part of the
+		 *    geometric repack.
+		 *
+		 *  - In the existing non-kept packs list (if not using pack
+		 *    geometry), and marked as non-deleted.
+		 */
+		if (string_list_has_string(include, pack_name)) {
+			continue;
+		} else if (geometry) {
+			struct strbuf buf = STRBUF_INIT;
+			uint32_t j;
+
+			for (j = 0; j < geometry->split; j++) {
+				strbuf_reset(&buf);
+				strbuf_addstr(&buf, pack_basename(geometry->pack[j]));
+				strbuf_strip_suffix(&buf, ".pack");
+				strbuf_addstr(&buf, ".idx");
+
+				if (!strcmp(pack_name, buf.buf)) {
+					strbuf_release(&buf);
+					break;
+				}
+			}
+
+			strbuf_release(&buf);
+
+			if (j < geometry->split)
+				continue;
+		} else {
+			struct string_list_item *item;
+
+			item = string_list_lookup(&existing->non_kept_packs,
+						  pack_name);
+			if (item && !existing_pack_is_marked_for_deletion(item))
+				continue;
+		}
+
+		/*
+		 * If we got to this point, the MIDX includes some pack that we
+		 * don't know about.
+		 */
+		return 1;
+	}
+
+	return 0;
+}
+
+static void midx_included_packs(struct string_list *include,
+				struct repack_write_midx_opts *opts)
+{
+	struct existing_packs *existing = opts->existing;
+	struct pack_geometry *geometry = opts->geometry;
+	struct string_list *names = opts->names;
+	struct string_list_item *item;
+	struct strbuf buf = STRBUF_INIT;
+
+	for_each_string_list_item(item, &existing->kept_packs) {
+		strbuf_reset(&buf);
+		strbuf_addf(&buf, "%s.idx", item->string);
+		string_list_insert(include, buf.buf);
+	}
+
+	for_each_string_list_item(item, names) {
+		strbuf_reset(&buf);
+		strbuf_addf(&buf, "pack-%s.idx", item->string);
+		string_list_insert(include, buf.buf);
+	}
+
+	if (geometry->split_factor) {
+		uint32_t i;
+
+		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_reset(&buf);
+			strbuf_addstr(&buf, pack_basename(p));
+			strbuf_strip_suffix(&buf, ".pack");
+			strbuf_addstr(&buf, ".idx");
+
+			string_list_insert(include, buf.buf);
+		}
+	} else {
+		for_each_string_list_item(item, &existing->non_kept_packs) {
+			if (existing_pack_is_marked_for_deletion(item))
+				continue;
+
+			strbuf_reset(&buf);
+			strbuf_addf(&buf, "%s.idx", item->string);
+			string_list_insert(include, buf.buf);
+		}
+	}
+
+	if (opts->midx_must_contain_cruft ||
+	    midx_has_unknown_packs(include, geometry, existing)) {
+		/*
+		 * If there are one or more unknown pack(s) present (see
+		 * midx_has_unknown_packs() for what makes a pack
+		 * "unknown") in the MIDX before the repack, keep them
+		 * as they may be required to form a reachability
+		 * closure if the MIDX is bitmapped.
+		 *
+		 * For example, a cruft pack can be required to form a
+		 * reachability closure if the MIDX is bitmapped and one
+		 * or more of the bitmap's selected commits reaches a
+		 * once-cruft object that was later made reachable.
+		 */
+		for_each_string_list_item(item, &existing->cruft_packs) {
+			/*
+			 * When doing a --geometric repack, there is no
+			 * need to check for deleted packs, since we're
+			 * by definition not doing an ALL_INTO_ONE
+			 * repack (hence no packs will be deleted).
+			 * Otherwise we must check for and exclude any
+			 * packs which are enqueued for deletion.
+			 *
+			 * So we could omit the conditional below in the
+			 * --geometric case, but doing so is unnecessary
+			 *  since no packs are marked as pending
+			 *  deletion (since we only call
+			 *  `existing_packs_mark_for_deletion()` when
+			 *  doing an all-into-one repack).
+			 */
+			if (existing_pack_is_marked_for_deletion(item))
+				continue;
+
+			strbuf_reset(&buf);
+			strbuf_addf(&buf, "%s.idx", item->string);
+			string_list_insert(include, buf.buf);
+		}
+	} else {
+		/*
+		 * Modern versions of Git (with the appropriate
+		 * configuration setting) will write new copies of
+		 * once-cruft objects when doing a --geometric repack.
+		 *
+		 * If the MIDX has no cruft pack, new packs written
+		 * during a --geometric repack will not rely on the
+		 * cruft pack to form a reachability closure, so we can
+		 * avoid including them in the MIDX in that case.
+		 */
+		;
+	}
+
+	strbuf_release(&buf);
+}
+
+static void remove_redundant_bitmaps(struct string_list *include,
+				     const char *packdir)
+{
+	struct strbuf path = STRBUF_INIT;
+	struct string_list_item *item;
+	size_t packdir_len;
+
+	strbuf_addstr(&path, packdir);
+	strbuf_addch(&path, '/');
+	packdir_len = path.len;
+
+	/*
+	 * Remove any pack bitmaps corresponding to packs which are now
+	 * included in the MIDX.
+	 */
+	for_each_string_list_item(item, include) {
+		strbuf_addstr(&path, item->string);
+		strbuf_strip_suffix(&path, ".idx");
+		strbuf_addstr(&path, ".bitmap");
+
+		if (unlink(path.buf) && errno != ENOENT)
+			warning_errno(_("could not remove stale bitmap: %s"),
+				      path.buf);
+
+		strbuf_setlen(&path, packdir_len);
+	}
+	strbuf_release(&path);
+}
+
+int write_midx_included_packs(struct repack_write_midx_opts *opts)
+{
+	struct child_process cmd = CHILD_PROCESS_INIT;
+	struct string_list include = STRING_LIST_INIT_DUP;
+	struct string_list_item *item;
+	struct packed_git *preferred = pack_geometry_preferred_pack(opts->geometry);
+	FILE *in;
+	int ret = 0;
+
+	midx_included_packs(&include, opts);
+	if (!include.nr)
+		goto done;
+
+	cmd.in = -1;
+	cmd.git_cmd = 1;
+
+	strvec_push(&cmd.args, "multi-pack-index");
+	strvec_pushl(&cmd.args, "write", "--stdin-packs", NULL);
+
+	if (opts->show_progress)
+		strvec_push(&cmd.args, "--progress");
+	else
+		strvec_push(&cmd.args, "--no-progress");
+
+	if (opts->write_bitmaps)
+		strvec_push(&cmd.args, "--bitmap");
+
+	if (preferred)
+		strvec_pushf(&cmd.args, "--preferred-pack=%s",
+			     pack_basename(preferred));
+	else if (opts->names->nr) {
+		/* The largest pack was repacked, meaning that either
+		 * one or two packs exist depending on whether the
+		 * repository has a cruft pack or not.
+		 *
+		 * Select the non-cruft one as preferred to encourage
+		 * pack-reuse among packs containing reachable objects
+		 * over unreachable ones.
+		 *
+		 * (Note we could write multiple packs here if
+		 * `--max-pack-size` was given, but any one of them
+		 * will suffice, so pick the first one.)
+		 */
+		for_each_string_list_item(item, opts->names) {
+			struct generated_pack *pack = item->util;
+			if (generated_pack_has_ext(pack, ".mtimes"))
+				continue;
+
+			strvec_pushf(&cmd.args, "--preferred-pack=pack-%s.pack",
+				     item->string);
+			break;
+		}
+	} else {
+		/*
+		 * No packs were kept, and no packs were written. The
+		 * only thing remaining are .keep packs (unless
+		 * --pack-kept-objects was given).
+		 *
+		 * Set the `--preferred-pack` arbitrarily here.
+		 */
+		;
+	}
+
+	if (opts->refs_snapshot)
+		strvec_pushf(&cmd.args, "--refs-snapshot=%s",
+			     opts->refs_snapshot);
+
+	ret = start_command(&cmd);
+	if (ret)
+		goto done;
+
+	in = xfdopen(cmd.in, "w");
+	for_each_string_list_item(item, &include)
+		fprintf(in, "%s\n", item->string);
+	fclose(in);
+
+	ret = finish_command(&cmd);
+done:
+	if (!ret && opts->write_bitmaps)
+		remove_redundant_bitmaps(&include, opts->packdir);
+
+	string_list_clear(&include, 0);
+
+	return ret;
+}
diff --git a/repack-promisor.c b/repack-promisor.c
new file mode 100644
index 0000000..ee6e066
--- /dev/null
+++ b/repack-promisor.c
@@ -0,0 +1,102 @@
+#include "git-compat-util.h"
+#include "repack.h"
+#include "hex.h"
+#include "pack.h"
+#include "packfile.h"
+#include "path.h"
+#include "repository.h"
+#include "run-command.h"
+
+struct write_oid_context {
+	struct child_process *cmd;
+	const struct git_hash_algo *algop;
+};
+
+/*
+ * 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 UNUSED,
+		     uint32_t pos UNUSED, void *data)
+{
+	struct write_oid_context *ctx = data;
+	struct child_process *cmd = ctx->cmd;
+
+	if (cmd->in == -1) {
+		if (start_command(cmd))
+			die(_("could not start pack-objects to repack promisor objects"));
+	}
+
+	if (write_in_full(cmd->in, oid_to_hex(oid), ctx->algop->hexsz) < 0 ||
+	    write_in_full(cmd->in, "\n", 1) < 0)
+		die(_("failed to feed promisor objects to pack-objects"));
+	return 0;
+}
+
+void repack_promisor_objects(struct repository *repo,
+			     const struct pack_objects_args *args,
+			     struct string_list *names, const char *packtmp)
+{
+	struct write_oid_context ctx;
+	struct child_process cmd = CHILD_PROCESS_INIT;
+	FILE *out;
+	struct strbuf line = STRBUF_INIT;
+
+	prepare_pack_objects(&cmd, args, packtmp);
+	cmd.in = -1;
+
+	/*
+	 * NEEDSWORK: Giving pack-objects only the OIDs without any ordering
+	 * hints may result in suboptimal deltas in the resulting pack. See if
+	 * the OIDs can be sent with fake paths such that pack-objects can use a
+	 * {type -> existing pack order} ordering when computing deltas instead
+	 * of a {type -> size} ordering, which may produce better deltas.
+	 */
+	ctx.cmd = &cmd;
+	ctx.algop = repo->hash_algo;
+	for_each_packed_object(repo, write_oid, &ctx,
+			       FOR_EACH_OBJECT_PROMISOR_ONLY);
+
+	if (cmd.in == -1) {
+		/* No packed objects; cmd was never started */
+		child_process_clear(&cmd);
+		return;
+	}
+
+	close(cmd.in);
+
+	out = xfdopen(cmd.out, "r");
+	while (strbuf_getline_lf(&line, out) != EOF) {
+		struct string_list_item *item;
+		char *promisor_name;
+
+		if (line.len != repo->hash_algo->hexsz)
+			die(_("repack: Expecting full hex object ID lines only from pack-objects."));
+		item = string_list_append(names, line.buf);
+
+		/*
+		 * pack-objects creates the .pack and .idx files, but not the
+		 * .promisor file. Create the .promisor file, which is empty.
+		 *
+		 * NEEDSWORK: fetch-pack sometimes generates non-empty
+		 * .promisor files containing the ref names and associated
+		 * hashes at the point of generation of the corresponding
+		 * packfile, but this would not preserve their contents. Maybe
+		 * concatenate the contents of all .promisor files instead of
+		 * just creating a new empty file.
+		 */
+		promisor_name = mkpathdup("%s-%s.promisor", packtmp,
+					  line.buf);
+		write_promisor_file(promisor_name, NULL, 0);
+
+		item->util = generated_pack_populate(item->string, packtmp);
+
+		free(promisor_name);
+	}
+
+	fclose(out);
+	if (finish_command(&cmd))
+		die(_("could not finish pack-objects to repack promisor objects"));
+	strbuf_release(&line);
+}
diff --git a/repack.c b/repack.c
new file mode 100644
index 0000000..5968410
--- /dev/null
+++ b/repack.c
@@ -0,0 +1,359 @@
+#include "git-compat-util.h"
+#include "dir.h"
+#include "midx.h"
+#include "odb.h"
+#include "packfile.h"
+#include "path.h"
+#include "repack.h"
+#include "repository.h"
+#include "run-command.h"
+#include "tempfile.h"
+
+void prepare_pack_objects(struct child_process *cmd,
+			  const struct pack_objects_args *args,
+			  const char *out)
+{
+	strvec_push(&cmd->args, "pack-objects");
+	if (args->window)
+		strvec_pushf(&cmd->args, "--window=%s", args->window);
+	if (args->window_memory)
+		strvec_pushf(&cmd->args, "--window-memory=%s", args->window_memory);
+	if (args->depth)
+		strvec_pushf(&cmd->args, "--depth=%s", args->depth);
+	if (args->threads)
+		strvec_pushf(&cmd->args, "--threads=%s", args->threads);
+	if (args->max_pack_size)
+		strvec_pushf(&cmd->args, "--max-pack-size=%lu", args->max_pack_size);
+	if (args->no_reuse_delta)
+		strvec_pushf(&cmd->args, "--no-reuse-delta");
+	if (args->no_reuse_object)
+		strvec_pushf(&cmd->args, "--no-reuse-object");
+	if (args->name_hash_version)
+		strvec_pushf(&cmd->args, "--name-hash-version=%d", args->name_hash_version);
+	if (args->path_walk)
+		strvec_pushf(&cmd->args, "--path-walk");
+	if (args->local)
+		strvec_push(&cmd->args,  "--local");
+	if (args->quiet)
+		strvec_push(&cmd->args,  "--quiet");
+	if (args->delta_base_offset)
+		strvec_push(&cmd->args,  "--delta-base-offset");
+	if (!args->pack_kept_objects)
+		strvec_push(&cmd->args,  "--honor-pack-keep");
+	strvec_push(&cmd->args, out);
+	cmd->git_cmd = 1;
+	cmd->out = -1;
+}
+
+void pack_objects_args_release(struct pack_objects_args *args)
+{
+	free(args->window);
+	free(args->window_memory);
+	free(args->depth);
+	free(args->threads);
+	list_objects_filter_release(&args->filter_options);
+}
+
+void repack_remove_redundant_pack(struct repository *repo, const char *dir_name,
+				  const char *base_name)
+{
+	struct strbuf buf = STRBUF_INIT;
+	struct odb_source *source = repo->objects->sources;
+	struct multi_pack_index *m = get_multi_pack_index(source);
+	strbuf_addf(&buf, "%s.pack", base_name);
+	if (m && source->local && midx_contains_pack(m, buf.buf))
+		clear_midx_file(repo);
+	strbuf_insertf(&buf, 0, "%s/", dir_name);
+	unlink_pack_path(buf.buf, 1);
+	strbuf_release(&buf);
+}
+
+const char *write_pack_opts_pack_prefix(const struct write_pack_opts *opts)
+{
+	const char *pack_prefix;
+	if (!skip_prefix(opts->packtmp, opts->packdir, &pack_prefix))
+		die(_("pack prefix %s does not begin with objdir %s"),
+		    opts->packtmp, opts->packdir);
+	if (*pack_prefix == '/')
+		pack_prefix++;
+	return pack_prefix;
+}
+
+bool write_pack_opts_is_local(const struct write_pack_opts *opts)
+{
+	return starts_with(opts->destination, opts->packdir);
+}
+
+int finish_pack_objects_cmd(const struct git_hash_algo *algop,
+			    const struct write_pack_opts *opts,
+			    struct child_process *cmd,
+			    struct string_list *names)
+{
+	FILE *out;
+	bool local = write_pack_opts_is_local(opts);
+	struct strbuf line = STRBUF_INIT;
+
+	out = xfdopen(cmd->out, "r");
+	while (strbuf_getline_lf(&line, out) != EOF) {
+		struct string_list_item *item;
+
+		if (line.len != algop->hexsz)
+			die(_("repack: Expecting full hex object ID lines only "
+			      "from pack-objects."));
+		/*
+		 * Avoid putting packs written outside of the repository in the
+		 * list of names.
+		 */
+		if (local) {
+			item = string_list_append(names, line.buf);
+			item->util = generated_pack_populate(line.buf,
+							     opts->packtmp);
+		}
+	}
+	fclose(out);
+
+	strbuf_release(&line);
+
+	return finish_command(cmd);
+}
+
+#define DELETE_PACK 1
+#define RETAIN_PACK 2
+
+void existing_packs_collect(struct existing_packs *existing,
+			    const struct string_list *extra_keep)
+{
+	struct packed_git *p;
+	struct strbuf buf = STRBUF_INIT;
+
+	repo_for_each_pack(existing->repo, p) {
+		size_t i;
+		const char *base;
+
+		if (p->multi_pack_index)
+			string_list_append(&existing->midx_packs,
+					    pack_basename(p));
+		if (!p->pack_local)
+			continue;
+
+		base = pack_basename(p);
+
+		for (i = 0; i < extra_keep->nr; i++)
+			if (!fspathcmp(base, extra_keep->items[i].string))
+				break;
+
+		strbuf_reset(&buf);
+		strbuf_addstr(&buf, base);
+		strbuf_strip_suffix(&buf, ".pack");
+
+		if ((extra_keep->nr > 0 && i < extra_keep->nr) || p->pack_keep)
+			string_list_append(&existing->kept_packs, buf.buf);
+		else if (p->is_cruft)
+			string_list_append(&existing->cruft_packs, buf.buf);
+		else
+			string_list_append(&existing->non_kept_packs, buf.buf);
+	}
+
+	string_list_sort(&existing->kept_packs);
+	string_list_sort(&existing->non_kept_packs);
+	string_list_sort(&existing->cruft_packs);
+	string_list_sort(&existing->midx_packs);
+	strbuf_release(&buf);
+}
+
+int existing_packs_has_non_kept(const struct existing_packs *existing)
+{
+	return existing->non_kept_packs.nr || existing->cruft_packs.nr;
+}
+
+static void existing_pack_mark_for_deletion(struct string_list_item *item)
+{
+	item->util = (void*)((uintptr_t)item->util | DELETE_PACK);
+}
+
+static void existing_pack_unmark_for_deletion(struct string_list_item *item)
+{
+	item->util = (void*)((uintptr_t)item->util & ~DELETE_PACK);
+}
+
+int existing_pack_is_marked_for_deletion(struct string_list_item *item)
+{
+	return (uintptr_t)item->util & DELETE_PACK;
+}
+
+static void existing_packs_mark_retained(struct string_list_item *item)
+{
+	item->util = (void*)((uintptr_t)item->util | RETAIN_PACK);
+}
+
+static int existing_pack_is_retained(struct string_list_item *item)
+{
+	return (uintptr_t)item->util & RETAIN_PACK;
+}
+
+static void existing_packs_mark_for_deletion_1(const struct git_hash_algo *algop,
+					       struct string_list *names,
+					       struct string_list *list)
+{
+	struct string_list_item *item;
+	const size_t hexsz = algop->hexsz;
+
+	for_each_string_list_item(item, list) {
+		char *sha1;
+		size_t len = strlen(item->string);
+		if (len < hexsz)
+			continue;
+		sha1 = item->string + len - hexsz;
+
+		if (existing_pack_is_retained(item)) {
+			existing_pack_unmark_for_deletion(item);
+		} else if (!string_list_has_string(names, sha1)) {
+			/*
+			 * Mark this pack for deletion, which ensures
+			 * that this pack won't be included in a MIDX
+			 * (if `--write-midx` was given) and that we
+			 * will actually delete this pack (if `-d` was
+			 * given).
+			 */
+			existing_pack_mark_for_deletion(item);
+		}
+	}
+}
+
+void existing_packs_retain_cruft(struct existing_packs *existing,
+				 struct packed_git *cruft)
+{
+	struct strbuf buf = STRBUF_INIT;
+	struct string_list_item *item;
+
+	strbuf_addstr(&buf, pack_basename(cruft));
+	strbuf_strip_suffix(&buf, ".pack");
+
+	item = string_list_lookup(&existing->cruft_packs, buf.buf);
+	if (!item)
+		BUG("could not find cruft pack '%s'", pack_basename(cruft));
+
+	existing_packs_mark_retained(item);
+	strbuf_release(&buf);
+}
+
+void existing_packs_mark_for_deletion(struct existing_packs *existing,
+				      struct string_list *names)
+
+{
+	const struct git_hash_algo *algop = existing->repo->hash_algo;
+	existing_packs_mark_for_deletion_1(algop, names,
+					   &existing->non_kept_packs);
+	existing_packs_mark_for_deletion_1(algop, names,
+					   &existing->cruft_packs);
+}
+
+static void remove_redundant_packs_1(struct repository *repo,
+				     struct string_list *packs,
+				     const char *packdir)
+{
+	struct string_list_item *item;
+	for_each_string_list_item(item, packs) {
+		if (!existing_pack_is_marked_for_deletion(item))
+			continue;
+		repack_remove_redundant_pack(repo, packdir, item->string);
+	}
+}
+
+void existing_packs_remove_redundant(struct existing_packs *existing,
+				     const char *packdir)
+{
+	remove_redundant_packs_1(existing->repo, &existing->non_kept_packs,
+				 packdir);
+	remove_redundant_packs_1(existing->repo, &existing->cruft_packs,
+				 packdir);
+}
+
+void existing_packs_release(struct existing_packs *existing)
+{
+	string_list_clear(&existing->kept_packs, 0);
+	string_list_clear(&existing->non_kept_packs, 0);
+	string_list_clear(&existing->cruft_packs, 0);
+	string_list_clear(&existing->midx_packs, 0);
+}
+
+static struct {
+	const char *name;
+	unsigned optional:1;
+} exts[] = {
+	{".pack"},
+	{".rev", 1},
+	{".mtimes", 1},
+	{".bitmap", 1},
+	{".promisor", 1},
+	{".idx"},
+};
+
+struct generated_pack {
+	struct tempfile *tempfiles[ARRAY_SIZE(exts)];
+};
+
+struct generated_pack *generated_pack_populate(const char *name,
+					       const char *packtmp)
+{
+	struct stat statbuf;
+	struct strbuf path = STRBUF_INIT;
+	struct generated_pack *pack = xcalloc(1, sizeof(*pack));
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(exts); i++) {
+		strbuf_reset(&path);
+		strbuf_addf(&path, "%s-%s%s", packtmp, name, exts[i].name);
+
+		if (stat(path.buf, &statbuf))
+			continue;
+
+		pack->tempfiles[i] = register_tempfile(path.buf);
+	}
+
+	strbuf_release(&path);
+	return pack;
+}
+
+int generated_pack_has_ext(const struct generated_pack *pack, const char *ext)
+{
+	size_t i;
+	for (i = 0; i < ARRAY_SIZE(exts); i++) {
+		if (strcmp(exts[i].name, ext))
+			continue;
+		return !!pack->tempfiles[i];
+	}
+	BUG("unknown pack extension: '%s'", ext);
+}
+
+void generated_pack_install(struct generated_pack *pack, const char *name,
+			    const char *packdir, const char *packtmp)
+{
+	size_t ext;
+	for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
+		char *fname;
+
+		fname = mkpathdup("%s/pack-%s%s", packdir, name,
+				  exts[ext].name);
+
+		if (pack->tempfiles[ext]) {
+			const char *fname_old = get_tempfile_path(pack->tempfiles[ext]);
+			struct stat statbuffer;
+
+			if (!stat(fname_old, &statbuffer)) {
+				statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+				chmod(fname_old, statbuffer.st_mode);
+			}
+
+			if (rename_tempfile(&pack->tempfiles[ext], fname))
+				die_errno(_("renaming pack to '%s' failed"),
+					  fname);
+		} else if (!exts[ext].optional)
+			die(_("pack-objects did not write a '%s' file for pack %s-%s"),
+			    exts[ext].name, packtmp, name);
+		else if (unlink(fname) < 0 && errno != ENOENT)
+			die_errno(_("could not unlink: %s"), fname);
+
+		free(fname);
+	}
+}
diff --git a/repack.h b/repack.h
new file mode 100644
index 0000000..3a688a1
--- /dev/null
+++ b/repack.h
@@ -0,0 +1,146 @@
+#ifndef REPACK_H
+#define REPACK_H
+
+#include "list-objects-filter-options.h"
+#include "string-list.h"
+
+struct pack_objects_args {
+	char *window;
+	char *window_memory;
+	char *depth;
+	char *threads;
+	unsigned long max_pack_size;
+	int no_reuse_delta;
+	int no_reuse_object;
+	int quiet;
+	int local;
+	int name_hash_version;
+	int path_walk;
+	int delta_base_offset;
+	int pack_kept_objects;
+	struct list_objects_filter_options filter_options;
+};
+
+#define PACK_OBJECTS_ARGS_INIT { \
+	.delta_base_offset = 1, \
+	.pack_kept_objects = -1, \
+}
+
+struct child_process;
+
+void prepare_pack_objects(struct child_process *cmd,
+			  const struct pack_objects_args *args,
+			  const char *out);
+void pack_objects_args_release(struct pack_objects_args *args);
+
+void repack_remove_redundant_pack(struct repository *repo, const char *dir_name,
+				  const char *base_name);
+
+struct write_pack_opts {
+	struct pack_objects_args *po_args;
+	const char *destination;
+	const char *packdir;
+	const char *packtmp;
+};
+
+const char *write_pack_opts_pack_prefix(const struct write_pack_opts *opts);
+bool write_pack_opts_is_local(const struct write_pack_opts *opts);
+
+int finish_pack_objects_cmd(const struct git_hash_algo *algop,
+			    const struct write_pack_opts *opts,
+			    struct child_process *cmd,
+			    struct string_list *names);
+
+struct repository;
+struct packed_git;
+
+struct existing_packs {
+	struct repository *repo;
+	struct string_list kept_packs;
+	struct string_list non_kept_packs;
+	struct string_list cruft_packs;
+	struct string_list midx_packs;
+};
+
+#define EXISTING_PACKS_INIT { \
+	.kept_packs = STRING_LIST_INIT_DUP, \
+	.non_kept_packs = STRING_LIST_INIT_DUP, \
+	.cruft_packs = STRING_LIST_INIT_DUP, \
+}
+
+/*
+ * Adds all packs hex strings (pack-$HASH) to either packs->non_kept
+ * or packs->kept based on whether each pack has a corresponding
+ * .keep file or not.  Packs without a .keep file are not to be kept
+ * if we are going to pack everything into one file.
+ */
+void existing_packs_collect(struct existing_packs *existing,
+			    const struct string_list *extra_keep);
+int existing_packs_has_non_kept(const struct existing_packs *existing);
+int existing_pack_is_marked_for_deletion(struct string_list_item *item);
+void existing_packs_retain_cruft(struct existing_packs *existing,
+				 struct packed_git *cruft);
+void existing_packs_mark_for_deletion(struct existing_packs *existing,
+				      struct string_list *names);
+void existing_packs_remove_redundant(struct existing_packs *existing,
+				     const char *packdir);
+void existing_packs_release(struct existing_packs *existing);
+
+struct generated_pack;
+
+struct generated_pack *generated_pack_populate(const char *name,
+					       const char *packtmp);
+int generated_pack_has_ext(const struct generated_pack *pack, const char *ext);
+void generated_pack_install(struct generated_pack *pack, const char *name,
+			    const char *packdir, const char *packtmp);
+
+void repack_promisor_objects(struct repository *repo,
+			     const struct pack_objects_args *args,
+			     struct string_list *names, const char *packtmp);
+
+struct pack_geometry {
+	struct packed_git **pack;
+	uint32_t pack_nr, pack_alloc;
+	uint32_t split;
+
+	int split_factor;
+};
+
+void pack_geometry_init(struct pack_geometry *geometry,
+			struct existing_packs *existing,
+			const struct pack_objects_args *args);
+void pack_geometry_split(struct pack_geometry *geometry);
+struct packed_git *pack_geometry_preferred_pack(struct pack_geometry *geometry);
+void pack_geometry_remove_redundant(struct pack_geometry *geometry,
+				    struct string_list *names,
+				    struct existing_packs *existing,
+				    const char *packdir);
+void pack_geometry_release(struct pack_geometry *geometry);
+
+struct tempfile;
+
+struct repack_write_midx_opts {
+	struct existing_packs *existing;
+	struct pack_geometry *geometry;
+	struct string_list *names;
+	const char *refs_snapshot;
+	const char *packdir;
+	int show_progress;
+	int write_bitmaps;
+	int midx_must_contain_cruft;
+};
+
+void midx_snapshot_refs(struct repository *repo, struct tempfile *f);
+int write_midx_included_packs(struct repack_write_midx_opts *opts);
+
+int write_filtered_pack(const struct write_pack_opts *opts,
+			struct existing_packs *existing,
+			struct string_list *names);
+
+int write_cruft_pack(const struct write_pack_opts *opts,
+		     const char *cruft_expiration,
+		     unsigned long combine_cruft_below_size,
+		     struct string_list *names,
+		     struct existing_packs *existing);
+
+#endif /* REPACK_H */
diff --git a/replace-object.c b/replace-object.c
index 3eae051..03d0f1f 100644
--- a/replace-object.c
+++ b/replace-object.c
@@ -8,31 +8,27 @@
 #include "repository.h"
 #include "commit.h"
 
-static int register_replace_ref(const char *refname,
-				const char *referent UNUSED,
-				const struct object_id *oid,
-				int flag UNUSED,
-				void *cb_data)
+static int register_replace_ref(const struct reference *ref, void *cb_data)
 {
 	struct repository *r = cb_data;
 
 	/* Get sha1 from refname */
-	const char *slash = strrchr(refname, '/');
-	const char *hash = slash ? slash + 1 : refname;
+	const char *slash = strrchr(ref->name, '/');
+	const char *hash = slash ? slash + 1 : ref->name;
 	struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
 
 	if (get_oid_hex_algop(hash, &repl_obj->original.oid, r->hash_algo)) {
 		free(repl_obj);
-		warning(_("bad replace ref name: %s"), refname);
+		warning(_("bad replace ref name: %s"), ref->name);
 		return 0;
 	}
 
 	/* Copy sha1 from the read ref */
-	oidcpy(&repl_obj->replacement, oid);
+	oidcpy(&repl_obj->replacement, ref->oid);
 
 	/* Register new object */
 	if (oidmap_put(&r->objects->replace_map, repl_obj))
-		die(_("duplicate replace ref: %s"), refname);
+		die(_("duplicate replace ref: %s"), ref->name);
 
 	return 0;
 }
diff --git a/repository.c b/repository.c
index ecd6911..6aaa7ba 100644
--- a/repository.c
+++ b/repository.c
@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)
 	repo->parsed_objects = parsed_object_pool_new(repo);
 	ALLOC_ARRAY(repo->index, 1);
 	index_state_init(repo->index, repo);
+	repo->check_deprecated_config = true;
 
 	/*
 	 * When a command runs inside a repository, it learns what
@@ -159,19 +160,24 @@ void repo_set_gitdir(struct repository *repo,
 	 * until after xstrdup(root). Then we can free it.
 	 */
 	char *old_gitdir = repo->gitdir;
+	char *objects_path = NULL;
 
 	repo->gitdir = xstrdup(gitfile ? gitfile : root);
 	free(old_gitdir);
 
 	repo_set_commondir(repo, o->commondir);
+	expand_base_dir(&objects_path, o->object_dir,
+			repo->commondir, "objects");
 
 	if (!repo->objects->sources) {
-		CALLOC_ARRAY(repo->objects->sources, 1);
-		repo->objects->sources->odb = repo->objects;
+		repo->objects->sources = odb_source_new(repo->objects,
+							objects_path, true);
 		repo->objects->sources_tail = &repo->objects->sources->next;
+		free(objects_path);
+	} else {
+		free(repo->objects->sources->path);
+		repo->objects->sources->path = objects_path;
 	}
-	expand_base_dir(&repo->objects->sources->path, o->object_dir,
-			repo->commondir, "objects");
 
 	repo->objects->sources->disable_ref_updates = o->disable_ref_updates;
 
diff --git a/repository.h b/repository.h
index 042dc93..5808a5d 100644
--- a/repository.h
+++ b/repository.h
@@ -161,6 +161,9 @@ struct repository {
 
 	/* Indicate if a repository has a different 'commondir' from 'gitdir' */
 	unsigned different_commondir:1;
+
+	/* Should repo_config() check for deprecated settings */
+	bool check_deprecated_config;
 };
 
 #ifdef USE_THE_REPOSITORY_VARIABLE
diff --git a/revision.c b/revision.c
index 18f300d..5f0850a 100644
--- a/revision.c
+++ b/revision.c
@@ -671,12 +671,17 @@ static void trace2_bloom_filter_statistics_atexit(void)
 
 static int forbid_bloom_filters(struct pathspec *spec)
 {
-	if (spec->has_wildcard)
-		return 1;
-	if (spec->magic & ~PATHSPEC_LITERAL)
+	unsigned int allowed_magic =
+		PATHSPEC_FROMTOP |
+		PATHSPEC_MAXDEPTH |
+		PATHSPEC_LITERAL |
+		PATHSPEC_GLOB |
+		PATHSPEC_ATTR;
+
+	if (spec->magic & ~allowed_magic)
 		return 1;
 	for (size_t nr = 0; nr < spec->nr; nr++)
-		if (spec->items[nr].magic & ~PATHSPEC_LITERAL)
+		if (spec->items[nr].magic & ~allowed_magic)
 			return 1;
 
 	return 0;
@@ -691,23 +696,34 @@ static int convert_pathspec_to_bloom_keyvec(struct bloom_keyvec **out,
 	char *path_alloc = NULL;
 	const char *path;
 	size_t len;
-	int res = 0;
+	int res = -1;
 
+	len = pi->nowildcard_len;
+	if (len != pi->len) {
+		/*
+		 * for path like "dir/file*", nowildcard part would be
+		 * "dir/file", but only "dir" should be used for the
+		 * bloom filter.
+		 */
+		while (len > 0 && pi->match[len - 1] != '/')
+			len--;
+	}
 	/* remove single trailing slash from path, if needed */
-	if (pi->len > 0 && pi->match[pi->len - 1] == '/') {
-		path_alloc = xmemdupz(pi->match, pi->len - 1);
+	if (len > 0 && pi->match[len - 1] == '/')
+		len--;
+
+	if (!len)
+		goto cleanup;
+
+	if (len != pi->len) {
+		path_alloc = xmemdupz(pi->match, len);
 		path = path_alloc;
 	} else
 		path = pi->match;
 
-	len = strlen(path);
-	if (!len) {
-		res = -1;
-		goto cleanup;
-	}
-
 	*out = bloom_keyvec_new(path, len, settings);
 
+	res = 0;
 cleanup:
 	free(path_alloc);
 	return res;
@@ -758,9 +774,6 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs,
 	struct bloom_filter *filter;
 	int result = 0;
 
-	if (!revs->repo->objects->commit_graph)
-		return -1;
-
 	if (commit_graph_generation(commit) == GENERATION_NUMBER_INFINITY)
 		return -1;
 
@@ -1631,19 +1644,17 @@ struct all_refs_cb {
 	struct worktree *wt;
 };
 
-static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
-			  int flag UNUSED,
-			  void *cb_data)
+static int handle_one_ref(const struct reference *ref, void *cb_data)
 {
 	struct all_refs_cb *cb = cb_data;
 	struct object *object;
 
-	if (ref_excluded(&cb->all_revs->ref_excludes, path))
+	if (ref_excluded(&cb->all_revs->ref_excludes, ref->name))
 	    return 0;
 
-	object = get_reference(cb->all_revs, path, oid, cb->all_flags);
-	add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
-	add_pending_object(cb->all_revs, object, path);
+	object = get_reference(cb->all_revs, ref->name, ref->oid, cb->all_flags);
+	add_rev_cmdline(cb->all_revs, object, ref->name, REV_CMD_REF, cb->all_flags);
+	add_pending_object(cb->all_revs, object, ref->name);
 	return 0;
 }
 
@@ -1689,7 +1700,8 @@ static void handle_one_reflog_commit(struct object_id *oid, void *cb_data)
 	}
 }
 
-static int handle_one_reflog_ent(struct object_id *ooid, struct object_id *noid,
+static int handle_one_reflog_ent(const char *refname UNUSED,
+				 struct object_id *ooid, struct object_id *noid,
 				 const char *email UNUSED,
 				 timestamp_t timestamp UNUSED,
 				 int tz UNUSED,
@@ -2304,6 +2316,24 @@ static timestamp_t parse_age(const char *arg)
 	return num;
 }
 
+static void overwrite_argv(int *argc, const char **argv,
+			   const char **value,
+			   const struct setup_revision_opt *opt)
+{
+	/*
+	 * Detect the case when we are overwriting ourselves. The assignment
+	 * itself would be a noop either way, but this lets us avoid corner
+	 * cases around the free() and NULL operations.
+	 */
+	if (*value != argv[*argc]) {
+		if (opt && opt->free_removed_argv_elements)
+			free((char *)argv[*argc]);
+		argv[*argc] = *value;
+		*value = NULL;
+	}
+	(*argc)++;
+}
+
 static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv,
 			       int *unkc, const char **unkv,
 			       const struct setup_revision_opt* opt)
@@ -2325,7 +2355,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 	    starts_with(arg, "--branches=") || starts_with(arg, "--tags=") ||
 	    starts_with(arg, "--remotes=") || starts_with(arg, "--no-walk="))
 	{
-		unkv[(*unkc)++] = arg;
+		overwrite_argv(unkc, unkv, &argv[0], opt);
 		return 1;
 	}
 
@@ -2689,7 +2719,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 	} else {
 		int opts = diff_opt_parse(&revs->diffopt, argv, argc, revs->prefix);
 		if (!opts)
-			unkv[(*unkc)++] = arg;
+			overwrite_argv(unkc, unkv, &argv[0], opt);
 		return opts;
 	}
 
@@ -3001,7 +3031,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 
 			if (!strcmp(arg, "--stdin")) {
 				if (revs->disable_stdin) {
-					argv[left++] = arg;
+					overwrite_argv(&left, argv, &argv[i], opt);
 					continue;
 				}
 				if (revs->read_from_stdin++)
@@ -3157,9 +3187,34 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 		revs->show_notes_given = 1;
 	}
 
+	if (argv) {
+		if (opt && opt->free_removed_argv_elements)
+			free((char *)argv[left]);
+		argv[left] = NULL;
+	}
+
 	return left;
 }
 
+void setup_revisions_from_strvec(struct strvec *argv, struct rev_info *revs,
+				 struct setup_revision_opt *opt)
+{
+	struct setup_revision_opt fallback_opt;
+	int ret;
+
+	if (!opt) {
+		memset(&fallback_opt, 0, sizeof(fallback_opt));
+		opt = &fallback_opt;
+	}
+	opt->free_removed_argv_elements = 1;
+
+	ret = setup_revisions(argv->nr, argv->v, revs, opt);
+
+	for (size_t i = ret; i < argv->nr; i++)
+		free((char *)argv->v[i]);
+	argv->nr = ret;
+}
+
 static void release_revisions_cmdline(struct rev_cmdline_info *cmdline)
 {
 	unsigned int i;
diff --git a/revision.h b/revision.h
index 21e288c..b36acfc 100644
--- a/revision.h
+++ b/revision.h
@@ -334,6 +334,7 @@ struct rev_info {
 	/* range-diff */
 	const char *rdiff1;
 	const char *rdiff2;
+	struct strvec rdiff_log_arg;
 	int creation_factor;
 	const char *rdiff_title;
 
@@ -410,6 +411,7 @@ struct rev_info {
 	.expand_tabs_in_log = -1, \
 	.commit_format = CMIT_FMT_DEFAULT, \
 	.expand_tabs_in_log_default = 8, \
+	.rdiff_log_arg = STRVEC_INIT, \
 }
 
 /**
@@ -441,6 +443,8 @@ struct setup_revision_opt {
 };
 int setup_revisions(int argc, const char **argv, struct rev_info *revs,
 		    struct setup_revision_opt *);
+void setup_revisions_from_strvec(struct strvec *argv, struct rev_info *revs,
+				 struct setup_revision_opt *);
 
 /**
  * Free data allocated in a "struct rev_info" after it's been
diff --git a/scalar.c b/scalar.c
index 4a373c1..f754311 100644
--- a/scalar.c
+++ b/scalar.c
@@ -166,6 +166,7 @@ static int set_recommended_config(int reconfigure)
 #endif
 		/* Optional */
 		{ "status.aheadBehind", "false" },
+		{ "commitGraph.changedPaths", "true" },
 		{ "commitGraph.generationVersion", "1" },
 		{ "core.autoCRLF", "false" },
 		{ "core.safeCRLF", "false" },
diff --git a/sequencer.c b/sequencer.c
index 6d29a93..5476d39 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -6052,8 +6052,8 @@ static int make_script_with_merges(struct pretty_print_context *pp,
 	return 0;
 }
 
-int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
-			  const char **argv, unsigned flags)
+int sequencer_make_script(struct repository *r, struct strbuf *out,
+			  struct strvec *argv, unsigned flags)
 {
 	char *format = NULL;
 	struct pretty_print_context pp = {0};
@@ -6094,7 +6094,8 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
 	pp.fmt = revs.commit_format;
 	pp.output_encoding = get_log_output_encoding();
 
-	if (setup_revisions(argc, argv, &revs, NULL) > 1) {
+	setup_revisions_from_strvec(argv, &revs, NULL);
+	if (argv->nr > 1) {
 		ret = error(_("make_script: unhandled options"));
 		goto cleanup;
 	}
diff --git a/sequencer.h b/sequencer.h
index 304ba4b..719684c 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -186,8 +186,8 @@ int sequencer_remove_state(struct replay_opts *opts);
 #define TODO_LIST_REAPPLY_CHERRY_PICKS (1U << 7)
 #define TODO_LIST_WARN_SKIPPED_CHERRY_PICKS (1U << 8)
 
-int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
-			  const char **argv, unsigned flags);
+int sequencer_make_script(struct repository *r, struct strbuf *out,
+			  struct strvec *argv, unsigned flags);
 
 int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
 		    const char *shortrevisions, const char *onto_name,
diff --git a/server-info.c b/server-info.c
index 9bb30d9..4243e24 100644
--- a/server-info.c
+++ b/server-info.c
@@ -148,23 +148,21 @@ static int update_info_file(struct repository *r, char *path,
 	return ret;
 }
 
-static int add_info_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
-			int flag UNUSED,
-			void *cb_data)
+static int add_info_ref(const struct reference *ref, void *cb_data)
 {
 	struct update_info_ctx *uic = cb_data;
-	struct object *o = parse_object(uic->repo, oid);
+	struct object *o = parse_object(uic->repo, ref->oid);
 	if (!o)
 		return -1;
 
-	if (uic_printf(uic, "%s	%s\n", oid_to_hex(oid), path) < 0)
+	if (uic_printf(uic, "%s	%s\n", oid_to_hex(ref->oid), ref->name) < 0)
 		return -1;
 
 	if (o->type == OBJ_TAG) {
-		o = deref_tag(uic->repo, o, path, 0);
+		o = deref_tag(uic->repo, o, ref->name, 0);
 		if (o)
 			if (uic_printf(uic, "%s	%s^{}\n",
-				oid_to_hex(&o->oid), path) < 0)
+				oid_to_hex(&o->oid), ref->name) < 0)
 				return -1;
 	}
 	return 0;
@@ -292,7 +290,7 @@ static void init_pack_info(struct repository *r, const char *infofile, int force
 	int i;
 	size_t alloc = 0;
 
-	for (p = get_all_packs(r); p; p = p->next) {
+	repo_for_each_pack(r, p) {
 		/* we ignore things on alternate path since they are
 		 * not available to the pullers in general.
 		 */
diff --git a/setup.c b/setup.c
index 98ddbf3..7086741 100644
--- a/setup.c
+++ b/setup.c
@@ -1460,8 +1460,9 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
 
 	if (env_ceiling_dirs) {
 		int empty_entry_found = 0;
+		static const char path_sep[] = { PATH_SEP, '\0' };
 
-		string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
+		string_list_split(&ceiling_dirs, env_ceiling_dirs, path_sep, -1);
 		filter_string_list(&ceiling_dirs, 0,
 				   canonicalize_ceiling_entry, &empty_entry_found);
 		ceil_offset = longest_ancestor_length(dir->buf, &ceiling_dirs);
diff --git a/shallow.c b/shallow.c
index ef3adb6..55b9cd9 100644
--- a/shallow.c
+++ b/shallow.c
@@ -213,7 +213,7 @@ static void show_commit(struct commit *commit, void *data)
  * are marked with shallow_flag. The list of border/shallow commits
  * are also returned.
  */
-struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,
+struct commit_list *get_shallow_commits_by_rev_list(struct strvec *argv,
 						    int shallow_flag,
 						    int not_shallow_flag)
 {
@@ -232,7 +232,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,
 
 	repo_init_revisions(the_repository, &revs, NULL);
 	save_commit_buffer = 0;
-	setup_revisions(ac, av, &revs, NULL);
+	setup_revisions_from_strvec(argv, &revs, NULL);
 
 	if (prepare_revision_walk(&revs))
 		die("revision walk setup failed");
@@ -626,14 +626,10 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,
 	free(tmp);
 }
 
-static int mark_uninteresting(const char *refname UNUSED,
-			      const char *referent UNUSED,
-			      const struct object_id *oid,
-			      int flags UNUSED,
-			      void *cb_data UNUSED)
+static int mark_uninteresting(const struct reference *ref, void *cb_data UNUSED)
 {
 	struct commit *commit = lookup_commit_reference_gently(the_repository,
-							       oid, 1);
+							       ref->oid, 1);
 	if (!commit)
 		return 0;
 	commit->object.flags |= UNINTERESTING;
@@ -742,16 +738,12 @@ struct commit_array {
 	size_t nr, alloc;
 };
 
-static int add_ref(const char *refname UNUSED,
-		  const char *referent UNUSED,
-		   const struct object_id *oid,
-		   int flags UNUSED,
-		   void *cb_data)
+static int add_ref(const struct reference *ref, void *cb_data)
 {
 	struct commit_array *ca = cb_data;
 	ALLOC_GROW(ca->commits, ca->nr + 1, ca->alloc);
 	ca->commits[ca->nr] = lookup_commit_reference_gently(the_repository,
-							     oid, 1);
+							     ref->oid, 1);
 	if (ca->commits[ca->nr])
 		ca->nr++;
 	return 0;
diff --git a/shallow.h b/shallow.h
index 9bfeade..ad591bd 100644
--- a/shallow.h
+++ b/shallow.h
@@ -7,6 +7,7 @@
 #include "strbuf.h"
 
 struct oid_array;
+struct strvec;
 
 void set_alternate_shallow_file(struct repository *r, const char *path, int override);
 int register_shallow(struct repository *r, const struct object_id *oid);
@@ -36,8 +37,8 @@ void rollback_shallow_file(struct repository *r, struct shallow_lock *lk);
 
 struct commit_list *get_shallow_commits(struct object_array *heads,
 					int depth, int shallow_flag, int not_shallow_flag);
-struct commit_list *get_shallow_commits_by_rev_list(
-		int ac, const char **av, int shallow_flag, int not_shallow_flag);
+struct commit_list *get_shallow_commits_by_rev_list(struct strvec *argv,
+						    int shallow_flag, int not_shallow_flag);
 int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
 			  const struct oid_array *extra);
 
diff --git a/shared.mak b/shared.mak
index 1a99848..0e74920 100644
--- a/shared.mak
+++ b/shared.mak
@@ -56,6 +56,7 @@
 	QUIET_MKDIR_P_PARENT  = @echo '   ' MKDIR -p $(@D);
 
 ## Used in "Makefile"
+	QUIET_CARGO    = @echo '   ' CARGO $@;
 	QUIET_CC       = @echo '   ' CC $@;
 	QUIET_AR       = @echo '   ' AR $@;
 	QUIET_LINK     = @echo '   ' LINK $@;
@@ -88,6 +89,8 @@
 
 	QUIET_LINT_GITLINK	= @echo '   ' LINT GITLINK $<;
 	QUIET_LINT_MANSEC	= @echo '   ' LINT MAN SEC $<;
+	QUIET_LINT_DELIMSEC	= @echo '   ' LINT DEL SEC $<;
+	QUIET_LINT_DOCSTYLE	= @echo '   ' LINT DOCSTYLE $<;
 	QUIET_LINT_MANEND	= @echo '   ' LINT MAN END $<;
 
 	export V
diff --git a/sideband.c b/sideband.c
index 8f15b98..ea7c252 100644
--- a/sideband.c
+++ b/sideband.c
@@ -27,16 +27,16 @@ static struct keyword_entry keywords[] = {
 };
 
 /* Returns a color setting (GIT_COLOR_NEVER, etc). */
-static int use_sideband_colors(void)
+static enum git_colorbool use_sideband_colors(void)
 {
-	static int use_sideband_colors_cached = -1;
+	static enum git_colorbool use_sideband_colors_cached = GIT_COLOR_UNKNOWN;
 
 	const char *key = "color.remote";
 	struct strbuf sb = STRBUF_INIT;
 	const char *value;
 	int i;
 
-	if (use_sideband_colors_cached >= 0)
+	if (use_sideband_colors_cached != GIT_COLOR_UNKNOWN)
 		return use_sideband_colors_cached;
 
 	if (!repo_config_get_string_tmp(the_repository, key, &value))
diff --git a/sparse-index.c b/sparse-index.c
index 5634aba..76f90da 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -32,7 +32,9 @@ int give_advice_on_expansion = 1;
 	"Your working directory likely has contents that are outside of\n"     \
 	"your sparse-checkout patterns. Use 'git sparse-checkout list' to\n"   \
 	"see your sparse-checkout definition and compare it to your working\n" \
-	"directory contents. Running 'git clean' may assist in this cleanup."
+	"directory contents. Cleaning up any merge conflicts or staged\n"      \
+	"changes before running 'git sparse-checkout clean' or 'git\n"         \
+	"sparse-checkout reapply' may assist in this cleanup."
 
 struct modify_index_context {
 	struct index_state *write;
diff --git a/src/cargo-meson.sh b/src/cargo-meson.sh
new file mode 100755
index 0000000..3998db0
--- /dev/null
+++ b/src/cargo-meson.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+if test "$#" -lt 2
+then
+	exit 1
+fi
+
+SOURCE_DIR="$1"
+BUILD_DIR="$2"
+BUILD_TYPE=debug
+
+shift 2
+
+for arg
+do
+	case "$arg" in
+	--release)
+		BUILD_TYPE=release;;
+	esac
+done
+
+cargo build --lib --quiet --manifest-path="$SOURCE_DIR/Cargo.toml" --target-dir="$BUILD_DIR" "$@"
+RET=$?
+if test $RET -ne 0
+then
+	exit $RET
+fi
+
+case "$(cargo -vV | sed -s 's/^host: \(.*\)$/\1/')" in
+	*-windows-*)
+		LIBNAME=gitcore.lib;;
+	*)
+		LIBNAME=libgitcore.a;;
+esac
+
+if ! cmp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1
+then
+	cp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a"
+fi
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..9da70d8
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1 @@
+pub mod varint;
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..25b9ad5
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,41 @@
+libgit_rs_sources = [
+  'lib.rs',
+  'varint.rs',
+]
+
+# Unfortunately we must use a wrapper command to move the output file into the
+# current build directory. This can fixed once `cargo build --artifact-dir`
+# stabilizes. See https://github.com/rust-lang/cargo/issues/6790 for that
+# effort.
+cargo_command = [
+  shell,
+  meson.current_source_dir() / 'cargo-meson.sh',
+  meson.project_source_root(),
+  meson.current_build_dir(),
+]
+if get_option('buildtype') == 'release'
+  cargo_command += '--release'
+endif
+
+libgit_rs = custom_target('git_rs',
+  input: libgit_rs_sources + [
+    meson.project_source_root() / 'Cargo.toml',
+  ],
+  output: 'libgitcore.a',
+  command: cargo_command,
+)
+libgit_dependencies += declare_dependency(link_with: libgit_rs)
+
+if get_option('tests')
+  test('rust', cargo,
+    args: [
+      'test',
+      '--manifest-path',
+      meson.project_source_root() / 'Cargo.toml',
+      '--target-dir',
+      meson.current_build_dir() / 'target',
+    ],
+    timeout: 0,
+    protocol: 'rust',
+  )
+endif
diff --git a/src/varint.rs b/src/varint.rs
new file mode 100644
index 0000000..06492df
--- /dev/null
+++ b/src/varint.rs
@@ -0,0 +1,107 @@
+/// Decode the variable-length integer stored in `bufp` and return the decoded value.
+///
+/// Returns 0 in case the decoded integer would overflow u64::MAX.
+///
+/// # Safety
+///
+/// The buffer must be NUL-terminated to ensure safety.
+#[no_mangle]
+pub unsafe extern "C" fn decode_varint(bufp: *mut *const u8) -> u64 {
+    let mut buf = *bufp;
+    let mut c = *buf;
+    let mut val = u64::from(c & 127);
+
+    buf = buf.add(1);
+
+    while (c & 128) != 0 {
+        val = val.wrapping_add(1);
+        if val == 0 || val.leading_zeros() < 7 {
+            return 0; // overflow
+        }
+
+        c = *buf;
+        buf = buf.add(1);
+
+        val = (val << 7) + u64::from(c & 127);
+    }
+
+    *bufp = buf;
+    val
+}
+
+/// Encode `value` into `buf` as a variable-length integer unless `buf` is null.
+///
+/// Returns the number of bytes written, or, if `buf` is null, the number of bytes that would be
+/// written to encode the integer.
+///
+/// # Safety
+///
+/// `buf` must either be null or point to at least 16 bytes of memory.
+#[no_mangle]
+pub unsafe extern "C" fn encode_varint(value: u64, buf: *mut u8) -> u8 {
+    let mut varint: [u8; 16] = [0; 16];
+    let mut pos = varint.len() - 1;
+
+    varint[pos] = (value & 127) as u8;
+
+    let mut value = value >> 7;
+    while value != 0 {
+        pos -= 1;
+        value -= 1;
+        varint[pos] = 128 | (value & 127) as u8;
+        value >>= 7;
+    }
+
+    if !buf.is_null() {
+        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);
+    }
+
+    (varint.len() - pos) as u8
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_decode_varint() {
+        unsafe {
+            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);
+            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);
+            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);
+            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);
+            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);
+            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);
+
+            // Overflows are expected to return 0.
+            assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);
+        }
+    }
+
+    #[test]
+    fn test_encode_varint() {
+        unsafe {
+            let mut varint: [u8; 16] = [0; 16];
+
+            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);
+
+            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);
+            assert_eq!(varint, [0; 16]);
+
+            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);
+            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+
+            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);
+            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+
+            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);
+            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+
+            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);
+            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+
+            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);
+            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+        }
+    }
+}
diff --git a/streaming.c b/streaming.c
index 4b13827..00ad649 100644
--- a/streaming.c
+++ b/streaming.c
@@ -230,12 +230,21 @@ static int open_istream_loose(struct git_istream *st, struct repository *r,
 			      enum object_type *type)
 {
 	struct object_info oi = OBJECT_INFO_INIT;
+	struct odb_source *source;
+
 	oi.sizep = &st->size;
 	oi.typep = type;
 
-	st->u.loose.mapped = map_loose_object(r, oid, &st->u.loose.mapsize);
+	odb_prepare_alternates(r->objects);
+	for (source = r->objects->sources; source; source = source->next) {
+		st->u.loose.mapped = odb_source_loose_map_object(source, oid,
+								 &st->u.loose.mapsize);
+		if (st->u.loose.mapped)
+			break;
+	}
 	if (!st->u.loose.mapped)
 		return -1;
+
 	switch (unpack_loose_header(&st->z, st->u.loose.mapped,
 				    st->u.loose.mapsize, st->u.loose.hdr,
 				    sizeof(st->u.loose.hdr))) {
diff --git a/string-list.c b/string-list.c
index 53faaa8..08dc009 100644
--- a/string-list.c
+++ b/string-list.c
@@ -16,7 +16,7 @@ void string_list_init_dup(struct string_list *list)
 /* if there is no exact match, point to the index where the entry could be
  * inserted */
 static size_t get_entry_index(const struct string_list *list, const char *string,
-			      int *exact_match)
+			      bool *exact_match)
 {
 	size_t left = 0, right = list->nr;
 	compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
@@ -29,18 +29,20 @@ static size_t get_entry_index(const struct string_list *list, const char *string
 		else if (compare > 0)
 			left = middle + 1;
 		else {
-			*exact_match = 1;
+			if (exact_match)
+				*exact_match = true;
 			return middle;
 		}
 	}
 
-	*exact_match = 0;
+	if (exact_match)
+		*exact_match = false;
 	return right;
 }
 
 static size_t add_entry(struct string_list *list, const char *string)
 {
-	int exact_match = 0;
+	bool exact_match;
 	size_t index = get_entry_index(list, string, &exact_match);
 
 	if (exact_match)
@@ -68,7 +70,7 @@ struct string_list_item *string_list_insert(struct string_list *list, const char
 void string_list_remove(struct string_list *list, const char *string,
 			int free_util)
 {
-	int exact_match;
+	bool exact_match;
 	int i = get_entry_index(list, string, &exact_match);
 
 	if (exact_match) {
@@ -82,26 +84,23 @@ void string_list_remove(struct string_list *list, const char *string,
 	}
 }
 
-int string_list_has_string(const struct string_list *list, const char *string)
+bool string_list_has_string(const struct string_list *list, const char *string)
 {
-	int exact_match;
+	bool exact_match;
 	get_entry_index(list, string, &exact_match);
 	return exact_match;
 }
 
-int string_list_find_insert_index(const struct string_list *list, const char *string,
-				  int negative_existing_index)
+size_t string_list_find_insert_index(const struct string_list *list, const char *string,
+				     bool *exact_match)
 {
-	int exact_match;
-	int index = get_entry_index(list, string, &exact_match);
-	if (exact_match)
-		index = -1 - (negative_existing_index ? index : 0);
-	return index;
+	return get_entry_index(list, string, exact_match);
 }
 
 struct string_list_item *string_list_lookup(struct string_list *list, const char *string)
 {
-	int exact_match, i = get_entry_index(list, string, &exact_match);
+	bool exact_match;
+	size_t i = get_entry_index(list, string, &exact_match);
 	if (!exact_match)
 		return NULL;
 	return list->items + i;
@@ -276,55 +275,99 @@ void unsorted_string_list_delete_item(struct string_list *list, int i, int free_
 	list->nr--;
 }
 
-int string_list_split(struct string_list *list, const char *string,
-		      int delim, int maxsplit)
+/*
+ * append a substring [p..end] to list; return number of things it
+ * appended to the list.
+ */
+static int append_one(struct string_list *list,
+		      const char *p, const char *end,
+		      int in_place, unsigned flags)
+{
+	if (!end)
+		end = p + strlen(p);
+
+	if ((flags & STRING_LIST_SPLIT_TRIM)) {
+		/* rtrim */
+		for (; p < end; end--)
+			if (!isspace(end[-1]))
+				break;
+	}
+
+	if ((flags & STRING_LIST_SPLIT_NONEMPTY) && (end <= p))
+		return 0;
+
+	if (in_place) {
+		*((char *)end) = '\0';
+		string_list_append(list, p);
+	} else {
+		string_list_append_nodup(list, xmemdupz(p, end - p));
+	}
+	return 1;
+}
+
+/*
+ * Unfortunately this cannot become a public interface, as _in_place()
+ * wants to have "const char *string" while the other variant wants to
+ * have "char *string" for type safety.
+ *
+ * This accepts "const char *string" to allow both wrappers to use it;
+ * it internally casts away the constness when in_place is true by
+ * taking advantage of strpbrk() that takes a "const char *" arg and
+ * returns "char *" pointer into that const string.  Yucky but works ;-).
+ */
+static int split_string(struct string_list *list, const char *string, const char *delim,
+			int maxsplit, int in_place, unsigned flags)
 {
 	int count = 0;
-	const char *p = string, *end;
+	const char *p = string;
 
-	if (!list->strdup_strings)
-		die("internal error in string_list_split(): "
-		    "list->strdup_strings must be set");
+	if (in_place && list->strdup_strings)
+		BUG("string_list_split_in_place() called with strdup_strings");
+	else if (!in_place && !list->strdup_strings)
+		BUG("string_list_split() called without strdup_strings");
+
 	for (;;) {
-		count++;
-		if (maxsplit >= 0 && count > maxsplit) {
-			string_list_append(list, p);
-			return count;
+		char *end;
+
+		if (flags & STRING_LIST_SPLIT_TRIM) {
+			/* ltrim */
+			while (*p && isspace(*p))
+				p++;
 		}
-		end = strchr(p, delim);
-		if (end) {
-			string_list_append_nodup(list, xmemdupz(p, end - p));
-			p = end + 1;
-		} else {
-			string_list_append(list, p);
+
+		if (0 <= maxsplit && maxsplit <= count)
+			end = NULL;
+		else
+			end = strpbrk(p, delim);
+
+		count += append_one(list, p, end, in_place, flags);
+
+		if (!end)
 			return count;
-		}
+		p = end + 1;
 	}
 }
 
+int string_list_split(struct string_list *list, const char *string,
+		      const char *delim, int maxsplit)
+{
+	return split_string(list, string, delim, maxsplit, 0, 0);
+}
+
 int string_list_split_in_place(struct string_list *list, char *string,
 			       const char *delim, int maxsplit)
 {
-	int count = 0;
-	char *p = string, *end;
+	return split_string(list, string, delim, maxsplit, 1, 0);
+}
 
-	if (list->strdup_strings)
-		die("internal error in string_list_split_in_place(): "
-		    "list->strdup_strings must not be set");
-	for (;;) {
-		count++;
-		if (maxsplit >= 0 && count > maxsplit) {
-			string_list_append(list, p);
-			return count;
-		}
-		end = strpbrk(p, delim);
-		if (end) {
-			*end = '\0';
-			string_list_append(list, p);
-			p = end + 1;
-		} else {
-			string_list_append(list, p);
-			return count;
-		}
-	}
+int string_list_split_f(struct string_list *list, const char *string,
+			const char *delim, int maxsplit, unsigned flags)
+{
+	return split_string(list, string, delim, maxsplit, 0, flags);
+}
+
+int string_list_split_in_place_f(struct string_list *list, char *string,
+			       const char *delim, int maxsplit, unsigned flags)
+{
+	return split_string(list, string, delim, maxsplit, 1, flags);
 }
diff --git a/string-list.h b/string-list.h
index 122b318..fa6ba07 100644
--- a/string-list.h
+++ b/string-list.h
@@ -172,9 +172,15 @@ void string_list_remove_empty_items(struct string_list *list, int free_util);
 /* Use these functions only on sorted lists: */
 
 /** Determine if the string_list has a given string or not. */
-int string_list_has_string(const struct string_list *list, const char *string);
-int string_list_find_insert_index(const struct string_list *list, const char *string,
-				  int negative_existing_index);
+bool string_list_has_string(const struct string_list *list, const char *string);
+
+/**
+ * Find the index at which a new element should be inserted into the
+ * string_list to maintain sorted order. If exact_match is not NULL,
+ * it will be set to true if the string already exists in the list.
+ */
+size_t string_list_find_insert_index(const struct string_list *list, const char *string,
+				     bool *exact_match);
 
 /**
  * Insert a new element to the string_list. The returned pointer can
@@ -254,7 +260,7 @@ struct string_list_item *unsorted_string_list_lookup(struct string_list *list,
 void unsorted_string_list_delete_item(struct string_list *list, int i, int free_util);
 
 /**
- * Split string into substrings on character `delim` and append the
+ * Split string into substrings on characters in `delim` and append the
  * substrings to `list`.  The input string is not modified.
  * list->strdup_strings must be set, as new memory needs to be
  * allocated to hold the substrings.  If maxsplit is non-negative,
@@ -262,15 +268,15 @@ void unsorted_string_list_delete_item(struct string_list *list, int i, int free_
  * appended to list.
  *
  * Examples:
- *   string_list_split(l, "foo:bar:baz", ':', -1) -> ["foo", "bar", "baz"]
- *   string_list_split(l, "foo:bar:baz", ':', 0) -> ["foo:bar:baz"]
- *   string_list_split(l, "foo:bar:baz", ':', 1) -> ["foo", "bar:baz"]
- *   string_list_split(l, "foo:bar:", ':', -1) -> ["foo", "bar", ""]
- *   string_list_split(l, "", ':', -1) -> [""]
- *   string_list_split(l, ":", ':', -1) -> ["", ""]
+ *   string_list_split(l, "foo:bar:baz", ":", -1) -> ["foo", "bar", "baz"]
+ *   string_list_split(l, "foo:bar:baz", ":", 0) -> ["foo:bar:baz"]
+ *   string_list_split(l, "foo:bar:baz", ":", 1) -> ["foo", "bar:baz"]
+ *   string_list_split(l, "foo:bar:", ":", -1) -> ["foo", "bar", ""]
+ *   string_list_split(l, "", ":", -1) -> [""]
+ *   string_list_split(l, ":", ":", -1) -> ["", ""]
  */
 int string_list_split(struct string_list *list, const char *string,
-		      int delim, int maxsplit);
+		      const char *delim, int maxsplit);
 
 /*
  * Like string_list_split(), except that string is split in-place: the
@@ -281,4 +287,21 @@ int string_list_split(struct string_list *list, const char *string,
  */
 int string_list_split_in_place(struct string_list *list, char *string,
 			       const char *delim, int maxsplit);
+
+/* Flag bits for split_f and split_in_place_f functions */
+enum {
+	/*
+	 * trim whitespaces around resulting string piece before adding
+	 * it to the list
+	 */
+	STRING_LIST_SPLIT_TRIM = (1 << 0),
+	/* omit adding empty string piece to the resulting list */
+	STRING_LIST_SPLIT_NONEMPTY = (1 << 1),
+};
+
+int string_list_split_f(struct string_list *, const char *string,
+			const char *delim, int maxsplit, unsigned flags);
+
+int string_list_split_in_place_f(struct string_list *, char *string,
+				 const char *delim, int maxsplit, unsigned flags);
 #endif /* STRING_LIST_H */
diff --git a/sub-process.c b/sub-process.c
index 1daf5a9..83bf0a0 100644
--- a/sub-process.c
+++ b/sub-process.c
@@ -30,23 +30,20 @@ struct subprocess_entry *subprocess_find_entry(struct hashmap *hashmap, const ch
 
 int subprocess_read_status(int fd, struct strbuf *status)
 {
-	struct strbuf **pair;
-	char *line;
 	int len;
 
 	for (;;) {
+		char *line;
+		const char *value;
+
 		len = packet_read_line_gently(fd, NULL, &line);
 		if ((len < 0) || !line)
 			break;
-		pair = strbuf_split_str(line, '=', 2);
-		if (pair[0] && pair[0]->len && pair[1]) {
+		if (skip_prefix(line, "status=", &value)) {
 			/* the last "status=<foo>" line wins */
-			if (!strcmp(pair[0]->buf, "status=")) {
-				strbuf_reset(status);
-				strbuf_addbuf(status, pair[1]);
-			}
+			strbuf_reset(status);
+			strbuf_addstr(status, value);
 		}
-		strbuf_list_free(pair);
 	}
 
 	return (len < 0) ? len : 0;
diff --git a/submodule.c b/submodule.c
index fff3c75..40a5c6f 100644
--- a/submodule.c
+++ b/submodule.c
@@ -900,7 +900,7 @@ static void collect_changed_submodules(struct repository *r,
 	save_warning = warn_on_object_refname_ambiguity;
 	warn_on_object_refname_ambiguity = 0;
 	repo_init_revisions(r, &rev, NULL);
-	setup_revisions(argv->nr, argv->v, &rev, &s_r_opt);
+	setup_revisions_from_strvec(argv, &rev, &s_r_opt);
 	warn_on_object_refname_ambiguity = save_warning;
 	if (prepare_revision_walk(&rev))
 		die(_("revision walk setup failed"));
@@ -934,10 +934,7 @@ static void free_submodules_data(struct string_list *submodules)
 	string_list_clear(submodules, 1);
 }
 
-static int has_remote(const char *refname UNUSED,
-		      const char *referent UNUSED,
-		      const struct object_id *oid UNUSED,
-		      int flags UNUSED, void *cb_data UNUSED)
+static int has_remote(const struct reference *ref UNUSED, void *cb_data UNUSED)
 {
 	return 1;
 }
@@ -1255,13 +1252,10 @@ int push_unpushed_submodules(struct repository *r,
 	return ret;
 }
 
-static int append_oid_to_array(const char *ref UNUSED,
-			       const char *referent UNUSED,
-			       const struct object_id *oid,
-			       int flags UNUSED, void *data)
+static int append_oid_to_array(const struct reference *ref, void *data)
 {
 	struct oid_array *array = data;
-	oid_array_append(array, oid);
+	oid_array_append(array, ref->oid);
 	return 0;
 }
 
diff --git a/t/for-each-ref-tests.sh b/t/for-each-ref-tests.sh
new file mode 100644
index 0000000..4593be5
--- /dev/null
+++ b/t/for-each-ref-tests.sh
@@ -0,0 +1,2143 @@
+git_for_each_ref=${git_for_each_ref:-git for-each-ref}
+GNUPGHOME_NOT_USED=$GNUPGHOME
+. "$TEST_DIRECTORY"/lib-gpg.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
+
+# Mon Jul 3 23:18:43 2006 +0000
+datestamp=1151968723
+setdate_and_increment () {
+    GIT_COMMITTER_DATE="$datestamp +0200"
+    datestamp=$(expr "$datestamp" + 1)
+    GIT_AUTHOR_DATE="$datestamp +0200"
+    datestamp=$(expr "$datestamp" + 1)
+    export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
+}
+
+test_object_file_size () {
+	oid=$(git rev-parse "$1")
+	path=".git/objects/$(test_oid_to_path $oid)"
+	test_file_size "$path"
+}
+
+test_expect_success setup '
+	# setup .mailmap
+	cat >.mailmap <<-EOF &&
+	A Thor <athor@example.com> A U Thor <author@example.com>
+	C Mitter <cmitter@example.com> C O Mitter <committer@example.com>
+	EOF
+
+	setdate_and_increment &&
+	echo "Using $datestamp" > one &&
+	git add one &&
+	git commit -m "Initial" &&
+	git branch -M main &&
+	setdate_and_increment &&
+	git tag -a -m "Tagging at $datestamp" testtag &&
+	git update-ref refs/remotes/origin/main main &&
+	git remote add origin nowhere &&
+	git config branch.main.remote origin &&
+	git config branch.main.merge refs/heads/main &&
+	git remote add myfork elsewhere &&
+	git config remote.pushdefault myfork &&
+	git config push.default current
+'
+
+test_atom () {
+	case "$1" in
+		head) ref=refs/heads/main ;;
+		 tag) ref=refs/tags/testtag ;;
+		 sym) ref=refs/heads/sym ;;
+		   *) ref=$1 ;;
+	esac
+	format=$2
+	test_do=test_expect_${4:-success}
+
+	printf '%s\n' "$3" >expected
+	$test_do $PREREQ "basic atom: $ref $format" '
+		${git_for_each_ref} --format="%($format)" "$ref" >actual &&
+		sanitize_pgp <actual >actual.clean &&
+		test_cmp expected actual.clean
+	'
+
+	# Automatically test "contents:size" atom after testing "contents"
+	if test "$format" = "contents"
+	then
+		# for commit leg, $3 is changed there
+		expect=$(printf '%s' "$3" | wc -c)
+		$test_do $PREREQ "basic atom: $ref contents:size" '
+			type=$(git cat-file -t "$ref") &&
+			case $type in
+			tag)
+				# We cannot use $3 as it expects sanitize_pgp to run
+				git cat-file tag $ref >out &&
+				expect=$(tail -n +6 out | wc -c) &&
+				rm -f out ;;
+			tree | blob)
+				expect="" ;;
+			commit)
+				: "use the calculated expect" ;;
+			*)
+				BUG "unknown object type" ;;
+			esac &&
+			# Leave $expect unquoted to lose possible leading whitespaces
+			echo $expect >expected &&
+			${git_for_each_ref} --format="%(contents:size)" "$ref" >actual &&
+			test_cmp expected actual
+		'
+	fi
+}
+
+hexlen=$(test_oid hexsz)
+
+test_atom head refname refs/heads/main
+test_atom head refname: refs/heads/main
+test_atom head refname:short main
+test_atom head refname:lstrip=1 heads/main
+test_atom head refname:lstrip=2 main
+test_atom head refname:lstrip=-1 main
+test_atom head refname:lstrip=-2 heads/main
+test_atom head refname:rstrip=1 refs/heads
+test_atom head refname:rstrip=2 refs
+test_atom head refname:rstrip=-1 refs
+test_atom head refname:rstrip=-2 refs/heads
+test_atom head refname:strip=1 heads/main
+test_atom head refname:strip=2 main
+test_atom head refname:strip=-1 main
+test_atom head refname:strip=-2 heads/main
+test_atom head upstream refs/remotes/origin/main
+test_atom head upstream:short origin/main
+test_atom head upstream:lstrip=2 origin/main
+test_atom head upstream:lstrip=-2 origin/main
+test_atom head upstream:rstrip=2 refs/remotes
+test_atom head upstream:rstrip=-2 refs/remotes
+test_atom head upstream:strip=2 origin/main
+test_atom head upstream:strip=-2 origin/main
+test_atom head push refs/remotes/myfork/main
+test_atom head push:short myfork/main
+test_atom head push:lstrip=1 remotes/myfork/main
+test_atom head push:lstrip=-1 main
+test_atom head push:rstrip=1 refs/remotes/myfork
+test_atom head push:rstrip=-1 refs
+test_atom head push:strip=1 remotes/myfork/main
+test_atom head push:strip=-1 main
+test_atom head objecttype commit
+test_atom head objectsize $((131 + hexlen))
+test_atom head objectsize:disk $(test_object_file_size refs/heads/main)
+test_atom head deltabase $ZERO_OID
+test_atom head objectname $(git rev-parse refs/heads/main)
+test_atom head objectname:short $(git rev-parse --short refs/heads/main)
+test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
+test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
+test_atom head tree $(git rev-parse refs/heads/main^{tree})
+test_atom head tree:short $(git rev-parse --short refs/heads/main^{tree})
+test_atom head tree:short=1 $(git rev-parse --short=1 refs/heads/main^{tree})
+test_atom head tree:short=10 $(git rev-parse --short=10 refs/heads/main^{tree})
+test_atom head parent ''
+test_atom head parent:short ''
+test_atom head parent:short=1 ''
+test_atom head parent:short=10 ''
+test_atom head numparent 0
+test_atom head object ''
+test_atom head type ''
+test_atom head raw "$(git cat-file commit refs/heads/main)
+"
+test_atom head '*objectname' ''
+test_atom head '*objecttype' ''
+test_atom head author 'A U Thor <author@example.com> 1151968724 +0200'
+test_atom head authorname 'A U Thor'
+test_atom head authorname:mailmap 'A Thor'
+test_atom head authoremail '<author@example.com>'
+test_atom head authoremail:trim 'author@example.com'
+test_atom head authoremail:localpart 'author'
+test_atom head authoremail:trim,localpart 'author'
+test_atom head authoremail:mailmap '<athor@example.com>'
+test_atom head authoremail:mailmap,trim 'athor@example.com'
+test_atom head authoremail:trim,mailmap 'athor@example.com'
+test_atom head authoremail:mailmap,localpart 'athor'
+test_atom head authoremail:localpart,mailmap 'athor'
+test_atom head authoremail:mailmap,trim,localpart,mailmap,trim 'athor'
+test_atom head authordate 'Tue Jul 4 01:18:44 2006 +0200'
+test_atom head committer 'C O Mitter <committer@example.com> 1151968723 +0200'
+test_atom head committername 'C O Mitter'
+test_atom head committername:mailmap 'C Mitter'
+test_atom head committeremail '<committer@example.com>'
+test_atom head committeremail:trim 'committer@example.com'
+test_atom head committeremail:localpart 'committer'
+test_atom head committeremail:localpart,trim 'committer'
+test_atom head committeremail:mailmap '<cmitter@example.com>'
+test_atom head committeremail:mailmap,trim 'cmitter@example.com'
+test_atom head committeremail:trim,mailmap 'cmitter@example.com'
+test_atom head committeremail:mailmap,localpart 'cmitter'
+test_atom head committeremail:localpart,mailmap 'cmitter'
+test_atom head committeremail:trim,mailmap,trim,trim,localpart 'cmitter'
+test_atom head committerdate 'Tue Jul 4 01:18:43 2006 +0200'
+test_atom head tag ''
+test_atom head tagger ''
+test_atom head taggername ''
+test_atom head taggeremail ''
+test_atom head taggeremail:trim ''
+test_atom head taggeremail:localpart ''
+test_atom head taggerdate ''
+test_atom head creator 'C O Mitter <committer@example.com> 1151968723 +0200'
+test_atom head creatordate 'Tue Jul 4 01:18:43 2006 +0200'
+test_atom head subject 'Initial'
+test_atom head subject:sanitize 'Initial'
+test_atom head contents:subject 'Initial'
+test_atom head body ''
+test_atom head contents:body ''
+test_atom head contents:signature ''
+test_atom head contents 'Initial
+'
+test_atom head HEAD '*'
+
+test_atom tag refname refs/tags/testtag
+test_atom tag refname:short testtag
+test_atom tag upstream ''
+test_atom tag push ''
+test_atom tag objecttype tag
+test_atom tag objectsize $((114 + hexlen))
+test_atom tag objectsize:disk $(test_object_file_size refs/tags/testtag)
+test_atom tag '*objectsize:disk' $(test_object_file_size refs/heads/main)
+test_atom tag deltabase $ZERO_OID
+test_atom tag '*deltabase' $ZERO_OID
+test_atom tag objectname $(git rev-parse refs/tags/testtag)
+test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag)
+test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
+test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
+test_atom tag tree ''
+test_atom tag tree:short ''
+test_atom tag tree:short=1 ''
+test_atom tag tree:short=10 ''
+test_atom tag parent ''
+test_atom tag parent:short ''
+test_atom tag parent:short=1 ''
+test_atom tag parent:short=10 ''
+test_atom tag numparent ''
+test_atom tag object $(git rev-parse refs/tags/testtag^0)
+test_atom tag type 'commit'
+test_atom tag '*objectname' $(git rev-parse refs/tags/testtag^{})
+test_atom tag '*objecttype' 'commit'
+test_atom tag author ''
+test_atom tag authorname ''
+test_atom tag authorname:mailmap ''
+test_atom tag authoremail ''
+test_atom tag authoremail:trim ''
+test_atom tag authoremail:localpart ''
+test_atom tag authoremail:trim,localpart ''
+test_atom tag authoremail:mailmap ''
+test_atom tag authoremail:mailmap,trim ''
+test_atom tag authoremail:trim,mailmap ''
+test_atom tag authoremail:mailmap,localpart ''
+test_atom tag authoremail:localpart,mailmap ''
+test_atom tag authoremail:mailmap,trim,localpart,mailmap,trim ''
+test_atom tag authordate ''
+test_atom tag committer ''
+test_atom tag committername ''
+test_atom tag committername:mailmap ''
+test_atom tag committeremail ''
+test_atom tag committeremail:trim ''
+test_atom tag committeremail:localpart ''
+test_atom tag committeremail:localpart,trim ''
+test_atom tag committeremail:mailmap ''
+test_atom tag committeremail:mailmap,trim ''
+test_atom tag committeremail:trim,mailmap ''
+test_atom tag committeremail:mailmap,localpart ''
+test_atom tag committeremail:localpart,mailmap ''
+test_atom tag committeremail:trim,mailmap,trim,trim,localpart ''
+test_atom tag committerdate ''
+test_atom tag tag 'testtag'
+test_atom tag tagger 'C O Mitter <committer@example.com> 1151968725 +0200'
+test_atom tag taggername 'C O Mitter'
+test_atom tag taggername:mailmap 'C Mitter'
+test_atom tag taggeremail '<committer@example.com>'
+test_atom tag taggeremail:trim 'committer@example.com'
+test_atom tag taggeremail:localpart 'committer'
+test_atom tag taggeremail:trim,localpart 'committer'
+test_atom tag taggeremail:mailmap '<cmitter@example.com>'
+test_atom tag taggeremail:mailmap,trim 'cmitter@example.com'
+test_atom tag taggeremail:trim,mailmap 'cmitter@example.com'
+test_atom tag taggeremail:mailmap,localpart 'cmitter'
+test_atom tag taggeremail:localpart,mailmap 'cmitter'
+test_atom tag taggeremail:trim,mailmap,trim,localpart,localpart 'cmitter'
+test_atom tag taggerdate 'Tue Jul 4 01:18:45 2006 +0200'
+test_atom tag creator 'C O Mitter <committer@example.com> 1151968725 +0200'
+test_atom tag creatordate 'Tue Jul 4 01:18:45 2006 +0200'
+test_atom tag subject 'Tagging at 1151968727'
+test_atom tag subject:sanitize 'Tagging-at-1151968727'
+test_atom tag contents:subject 'Tagging at 1151968727'
+test_atom tag body ''
+test_atom tag contents:body ''
+test_atom tag contents:signature ''
+test_atom tag contents 'Tagging at 1151968727
+'
+test_atom tag HEAD ' '
+
+test_expect_success 'basic atom: refs/tags/testtag *raw' '
+	git cat-file commit refs/tags/testtag^{} >expected &&
+	${git_for_each_ref} --format="%(*raw)" refs/tags/testtag >actual &&
+	sanitize_pgp <expected >expected.clean &&
+	echo >>expected.clean &&
+	sanitize_pgp <actual >actual.clean &&
+	test_cmp expected.clean actual.clean
+'
+
+test_expect_success 'Check invalid atoms names are errors' '
+	test_must_fail ${git_for_each_ref} --format="%(INVALID)" refs/heads
+'
+
+test_expect_success 'Check format specifiers are ignored in naming date atoms' '
+	${git_for_each_ref} --format="%(authordate)" refs/heads &&
+	${git_for_each_ref} --format="%(authordate:default) %(authordate)" refs/heads &&
+	${git_for_each_ref} --format="%(authordate) %(authordate:default)" refs/heads &&
+	${git_for_each_ref} --format="%(authordate:default) %(authordate:default)" refs/heads
+'
+
+test_expect_success 'Check valid format specifiers for date fields' '
+	${git_for_each_ref} --format="%(authordate:default)" refs/heads &&
+	${git_for_each_ref} --format="%(authordate:relative)" refs/heads &&
+	${git_for_each_ref} --format="%(authordate:short)" refs/heads &&
+	${git_for_each_ref} --format="%(authordate:local)" refs/heads &&
+	${git_for_each_ref} --format="%(authordate:iso8601)" refs/heads &&
+	${git_for_each_ref} --format="%(authordate:rfc2822)" refs/heads
+'
+
+test_expect_success 'Check invalid format specifiers are errors' '
+	test_must_fail ${git_for_each_ref} --format="%(authordate:INVALID)" refs/heads
+'
+
+test_expect_success 'arguments to %(objectname:short=) must be positive integers' '
+	test_must_fail ${git_for_each_ref} --format="%(objectname:short=0)" &&
+	test_must_fail ${git_for_each_ref} --format="%(objectname:short=-1)" &&
+	test_must_fail ${git_for_each_ref} --format="%(objectname:short=foo)"
+'
+
+test_bad_atom () {
+	case "$1" in
+	head) ref=refs/heads/main ;;
+	 tag) ref=refs/tags/testtag ;;
+	 sym) ref=refs/heads/sym ;;
+	   *) ref=$1 ;;
+	esac
+	format=$2
+	test_do=test_expect_${4:-success}
+
+	printf '%s\n' "$3" >expect
+	$test_do $PREREQ "err basic atom: $ref $format" '
+		test_must_fail ${git_for_each_ref} \
+			--format="%($format)" "$ref" 2>error &&
+		test_cmp expect error
+	'
+}
+
+test_bad_atom head 'authoremail:foo' \
+	'fatal: unrecognized %(authoremail) argument: foo'
+
+test_bad_atom head 'authoremail:mailmap,trim,bar' \
+	'fatal: unrecognized %(authoremail) argument: bar'
+
+test_bad_atom head 'authoremail:trim,' \
+	'fatal: unrecognized %(authoremail) argument: '
+
+test_bad_atom head 'authoremail:mailmaptrim' \
+	'fatal: unrecognized %(authoremail) argument: trim'
+
+test_bad_atom head 'committeremail: ' \
+	'fatal: unrecognized %(committeremail) argument:  '
+
+test_bad_atom head 'committeremail: trim,foo' \
+	'fatal: unrecognized %(committeremail) argument:  trim,foo'
+
+test_bad_atom head 'committeremail:mailmap,localpart ' \
+	'fatal: unrecognized %(committeremail) argument:  '
+
+test_bad_atom head 'committeremail:trim_localpart' \
+	'fatal: unrecognized %(committeremail) argument: _localpart'
+
+test_bad_atom head 'committeremail:localpart,,,trim' \
+	'fatal: unrecognized %(committeremail) argument: ,,trim'
+
+test_bad_atom tag 'taggeremail:mailmap,trim, foo ' \
+	'fatal: unrecognized %(taggeremail) argument:  foo '
+
+test_bad_atom tag 'taggeremail:trim,localpart,' \
+	'fatal: unrecognized %(taggeremail) argument: '
+
+test_bad_atom tag 'taggeremail:mailmap;localpart trim' \
+	'fatal: unrecognized %(taggeremail) argument: ;localpart trim'
+
+test_bad_atom tag 'taggeremail:localpart trim' \
+	'fatal: unrecognized %(taggeremail) argument:  trim'
+
+test_bad_atom tag 'taggeremail:mailmap,mailmap,trim,qux,localpart,trim' \
+	'fatal: unrecognized %(taggeremail) argument: qux,localpart,trim'
+
+test_date () {
+	f=$1 &&
+	committer_date=$2 &&
+	author_date=$3 &&
+	tagger_date=$4 &&
+	cat >expected <<-EOF &&
+	'refs/heads/main' '$committer_date' '$author_date'
+	'refs/tags/testtag' '$tagger_date'
+	EOF
+	(
+		${git_for_each_ref} --shell \
+			--format="%(refname) %(committerdate${f:+:$f}) %(authordate${f:+:$f})" \
+			refs/heads &&
+		${git_for_each_ref} --shell \
+			--format="%(refname) %(taggerdate${f:+:$f})" \
+			refs/tags
+	) >actual &&
+	test_cmp expected actual
+}
+
+test_expect_success 'Check unformatted date fields output' '
+	test_date "" \
+		"Tue Jul 4 01:18:43 2006 +0200" \
+		"Tue Jul 4 01:18:44 2006 +0200" \
+		"Tue Jul 4 01:18:45 2006 +0200"
+'
+
+test_expect_success 'Check format "default" formatted date fields output' '
+	test_date default \
+		"Tue Jul 4 01:18:43 2006 +0200" \
+		"Tue Jul 4 01:18:44 2006 +0200" \
+		"Tue Jul 4 01:18:45 2006 +0200"
+'
+
+test_expect_success 'Check format "default-local" date fields output' '
+	test_date default-local "Mon Jul 3 23:18:43 2006" "Mon Jul 3 23:18:44 2006" "Mon Jul 3 23:18:45 2006"
+'
+
+# Don't know how to do relative check because I can't know when this script
+# is going to be run and can't fake the current time to git, and hence can't
+# provide expected output.  Instead, I'll just make sure that "relative"
+# doesn't exit in error
+test_expect_success 'Check format "relative" date fields output' '
+	f=relative &&
+	(${git_for_each_ref} --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
+	${git_for_each_ref} --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual
+'
+
+# We just check that this is the same as "relative" for now.
+test_expect_success 'Check format "relative-local" date fields output' '
+	test_date relative-local \
+		"$(${git_for_each_ref} --format="%(committerdate:relative)" refs/heads)" \
+		"$(${git_for_each_ref} --format="%(authordate:relative)" refs/heads)" \
+		"$(${git_for_each_ref} --format="%(taggerdate:relative)" refs/tags)"
+'
+
+test_expect_success 'Check format "short" date fields output' '
+	test_date short 2006-07-04 2006-07-04 2006-07-04
+'
+
+test_expect_success 'Check format "short-local" date fields output' '
+	test_date short-local 2006-07-03 2006-07-03 2006-07-03
+'
+
+test_expect_success 'Check format "local" date fields output' '
+	test_date local \
+		"Mon Jul 3 23:18:43 2006" \
+		"Mon Jul 3 23:18:44 2006" \
+		"Mon Jul 3 23:18:45 2006"
+'
+
+test_expect_success 'Check format "iso8601" date fields output' '
+	test_date iso8601 \
+		"2006-07-04 01:18:43 +0200" \
+		"2006-07-04 01:18:44 +0200" \
+		"2006-07-04 01:18:45 +0200"
+'
+
+test_expect_success 'Check format "iso8601-local" date fields output' '
+	test_date iso8601-local "2006-07-03 23:18:43 +0000" "2006-07-03 23:18:44 +0000" "2006-07-03 23:18:45 +0000"
+'
+
+test_expect_success 'Check format "rfc2822" date fields output' '
+	test_date rfc2822 \
+		"Tue, 4 Jul 2006 01:18:43 +0200" \
+		"Tue, 4 Jul 2006 01:18:44 +0200" \
+		"Tue, 4 Jul 2006 01:18:45 +0200"
+'
+
+test_expect_success 'Check format "rfc2822-local" date fields output' '
+	test_date rfc2822-local "Mon, 3 Jul 2006 23:18:43 +0000" "Mon, 3 Jul 2006 23:18:44 +0000" "Mon, 3 Jul 2006 23:18:45 +0000"
+'
+
+test_expect_success 'Check format "raw" date fields output' '
+	test_date raw "1151968723 +0200" "1151968724 +0200" "1151968725 +0200"
+'
+
+test_expect_success 'Check format "raw-local" date fields output' '
+	test_date raw-local "1151968723 +0000" "1151968724 +0000" "1151968725 +0000"
+'
+
+test_expect_success 'Check format of strftime date fields' '
+	echo "my date is 2006-07-04" >expected &&
+	${git_for_each_ref} \
+	  --format="%(authordate:format:my date is %Y-%m-%d)" \
+	  refs/heads >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'Check format of strftime-local date fields' '
+	echo "my date is 2006-07-03" >expected &&
+	${git_for_each_ref} \
+	  --format="%(authordate:format-local:my date is %Y-%m-%d)" \
+	  refs/heads >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'exercise strftime with odd fields' '
+	echo >expected &&
+	${git_for_each_ref} --format="%(authordate:format:)" refs/heads >actual &&
+	test_cmp expected actual &&
+	long="long format -- $ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID" &&
+	echo $long >expected &&
+	${git_for_each_ref} --format="%(authordate:format:$long)" refs/heads >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<\EOF
+refs/heads/main
+refs/remotes/origin/main
+refs/tags/testtag
+EOF
+
+test_expect_success 'Verify ascending sort' '
+	${git_for_each_ref} --format="%(refname)" --sort=refname >actual &&
+	test_cmp expected actual
+'
+
+
+cat >expected <<\EOF
+refs/tags/testtag
+refs/remotes/origin/main
+refs/heads/main
+EOF
+
+test_expect_success 'Verify descending sort' '
+	${git_for_each_ref} --format="%(refname)" --sort=-refname >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'Give help even with invalid sort atoms' '
+	test_expect_code 129 ${git_for_each_ref} --sort=bogus -h >actual 2>&1 &&
+	grep "^usage: ${git_for_each_ref}" actual
+'
+
+cat >expected <<\EOF
+refs/tags/testtag
+refs/tags/testtag-2
+EOF
+
+test_expect_success 'exercise patterns with prefixes' '
+	git tag testtag-2 &&
+	test_when_finished "git tag -d testtag-2" &&
+	${git_for_each_ref} --format="%(refname)" \
+		refs/tags/testtag refs/tags/testtag-2 >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<\EOF
+refs/tags/testtag
+refs/tags/testtag-2
+EOF
+
+test_expect_success 'exercise glob patterns with prefixes' '
+	git tag testtag-2 &&
+	test_when_finished "git tag -d testtag-2" &&
+	${git_for_each_ref} --format="%(refname)" \
+		refs/tags/testtag "refs/tags/testtag-*" >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<\EOF
+refs/tags/bar
+refs/tags/baz
+refs/tags/testtag
+EOF
+
+test_expect_success 'exercise patterns with prefix exclusions' '
+	for tag in foo/one foo/two foo/three bar baz
+	do
+		git tag "$tag" || return 1
+	done &&
+	test_when_finished "git tag -d foo/one foo/two foo/three bar baz" &&
+	${git_for_each_ref} --format="%(refname)" \
+		refs/tags/ --exclude=refs/tags/foo >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<\EOF
+refs/tags/bar
+refs/tags/baz
+refs/tags/foo/one
+refs/tags/testtag
+EOF
+
+test_expect_success 'exercise patterns with pattern exclusions' '
+	for tag in foo/one foo/two foo/three bar baz
+	do
+		git tag "$tag" || return 1
+	done &&
+	test_when_finished "git tag -d foo/one foo/two foo/three bar baz" &&
+	${git_for_each_ref} --format="%(refname)" \
+		refs/tags/ --exclude="refs/tags/foo/t*" >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<\EOF
+'refs/heads/main'
+'refs/remotes/origin/main'
+'refs/tags/testtag'
+EOF
+
+test_expect_success 'Quoting style: shell' '
+	${git_for_each_ref} --shell --format="%(refname)" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'Quoting style: perl' '
+	${git_for_each_ref} --perl --format="%(refname)" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'Quoting style: python' '
+	${git_for_each_ref} --python --format="%(refname)" >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<\EOF
+"refs/heads/main"
+"refs/remotes/origin/main"
+"refs/tags/testtag"
+EOF
+
+test_expect_success 'Quoting style: tcl' '
+	${git_for_each_ref} --tcl --format="%(refname)" >actual &&
+	test_cmp expected actual
+'
+
+for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
+	test_expect_success "more than one quoting style: $i" "
+		test_must_fail ${git_for_each_ref} $i 2>err &&
+		grep '^error: more than one quoting style' err
+	"
+done
+
+test_expect_success 'setup for upstream:track[short]' '
+	test_commit two
+'
+
+test_atom head upstream:track '[ahead 1]'
+test_atom head upstream:trackshort '>'
+test_atom head upstream:track,nobracket 'ahead 1'
+test_atom head upstream:nobracket,track 'ahead 1'
+
+test_expect_success 'setup for push:track[short]' '
+	test_commit third &&
+	git update-ref refs/remotes/myfork/main main &&
+	git reset main~1
+'
+
+test_atom head push:track '[behind 1]'
+test_atom head push:trackshort '<'
+
+test_expect_success 'Check that :track[short] cannot be used with other atoms' '
+	test_must_fail ${git_for_each_ref} --format="%(refname:track)" 2>/dev/null &&
+	test_must_fail ${git_for_each_ref} --format="%(refname:trackshort)" 2>/dev/null
+'
+
+test_expect_success 'Check that :track[short] works when upstream is invalid' '
+	cat >expected <<-\EOF &&
+	[gone]
+
+	EOF
+	test_when_finished "git config branch.main.merge refs/heads/main" &&
+	git config branch.main.merge refs/heads/does-not-exist &&
+	${git_for_each_ref} \
+		--format="%(upstream:track)$LF%(upstream:trackshort)" \
+		refs/heads >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'Check for invalid refname format' '
+	test_must_fail ${git_for_each_ref} --format="%(refname:INVALID)"
+'
+
+test_expect_success 'set up color tests' '
+	cat >expected.color <<-EOF &&
+	$(git rev-parse --short refs/heads/main) <GREEN>main<RESET>
+	$(git rev-parse --short refs/remotes/myfork/main) <GREEN>myfork/main<RESET>
+	$(git rev-parse --short refs/remotes/origin/main) <GREEN>origin/main<RESET>
+	$(git rev-parse --short refs/tags/testtag) <GREEN>testtag<RESET>
+	$(git rev-parse --short refs/tags/third) <GREEN>third<RESET>
+	$(git rev-parse --short refs/tags/two) <GREEN>two<RESET>
+	EOF
+	sed "s/<[^>]*>//g" <expected.color >expected.bare &&
+	color_format="%(objectname:short) %(color:green)%(refname:short)"
+'
+
+test_expect_success TTY '%(color) shows color with a tty' '
+	test_terminal ${git_for_each_ref} --format="$color_format" >actual.raw &&
+	test_decode_color <actual.raw >actual &&
+	test_cmp expected.color actual
+'
+
+test_expect_success '%(color) does not show color without tty' '
+	TERM=vt100 ${git_for_each_ref} --format="$color_format" >actual &&
+	test_cmp expected.bare actual
+'
+
+test_expect_success '--color can override tty check' '
+	${git_for_each_ref} --color --format="$color_format" >actual.raw &&
+	test_decode_color <actual.raw >actual &&
+	test_cmp expected.color actual
+'
+
+test_expect_success 'color.ui=always does not override tty check' '
+	git -c color.ui=always ${git_for_each_ref#git} --format="$color_format" >actual &&
+	test_cmp expected.bare actual
+'
+
+test_expect_success 'setup for describe atom tests' '
+	git init -b master describe-repo &&
+	(
+		cd describe-repo &&
+
+		test_commit --no-tag one &&
+		git tag tagone &&
+
+		test_commit --no-tag two &&
+		git tag -a -m "tag two" tagtwo
+	)
+'
+
+test_expect_success 'describe atom vs git describe' '
+	(
+		cd describe-repo &&
+
+		${git_for_each_ref} --format="%(objectname)" \
+			refs/tags/ >obj &&
+		while read hash
+		do
+			if desc=$(git describe $hash)
+			then
+				: >expect-contains-good
+			else
+				: >expect-contains-bad
+			fi &&
+			echo "$hash $desc" || return 1
+		done <obj >expect &&
+		test_path_exists expect-contains-good &&
+		test_path_exists expect-contains-bad &&
+
+		${git_for_each_ref} --format="%(objectname) %(describe)" \
+			refs/tags/ >actual 2>err &&
+		test_cmp expect actual &&
+		test_must_be_empty err
+	)
+'
+
+test_expect_success 'describe:tags vs describe --tags' '
+	(
+		cd describe-repo &&
+		git describe --tags >expect &&
+		${git_for_each_ref} --format="%(describe:tags)" \
+				refs/heads/master >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'describe:abbrev=... vs describe --abbrev=...' '
+	(
+		cd describe-repo &&
+
+		# Case 1: We have commits between HEAD and the most
+		#	  recent tag reachable from it
+		test_commit --no-tag file &&
+		git describe --abbrev=14 >expect &&
+		${git_for_each_ref} --format="%(describe:abbrev=14)" \
+			refs/heads/master >actual &&
+		test_cmp expect actual &&
+
+		# Make sure the hash used is at least 14 digits long
+		sed -e "s/^.*-g\([0-9a-f]*\)$/\1/" <actual >hexpart &&
+		test 15 -le $(wc -c <hexpart) &&
+
+		# Case 2: We have a tag at HEAD, describe directly gives
+		#	  the name of the tag
+		git tag -a -m tagged tagname &&
+		git describe --abbrev=14 >expect &&
+		${git_for_each_ref} --format="%(describe:abbrev=14)" \
+			refs/heads/master >actual &&
+		test_cmp expect actual &&
+		test tagname = $(cat actual)
+	)
+'
+
+test_expect_success 'describe:match=... vs describe --match ...' '
+	(
+		cd describe-repo &&
+		git tag -a -m "tag foo" tag-foo &&
+		git describe --match "*-foo" >expect &&
+		${git_for_each_ref} --format="%(describe:match="*-foo")" \
+			refs/heads/master >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'describe:exclude:... vs describe --exclude ...' '
+	(
+		cd describe-repo &&
+		git tag -a -m "tag bar" tag-bar &&
+		git describe --exclude "*-bar" >expect &&
+		${git_for_each_ref} --format="%(describe:exclude="*-bar")" \
+			refs/heads/master >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'deref with describe atom' '
+	(
+		cd describe-repo &&
+		cat >expect <<-\EOF &&
+
+		tagname
+		tagname
+		tagname
+
+		tagtwo
+		EOF
+		${git_for_each_ref} --format="%(*describe)" >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'err on bad describe atom arg' '
+	(
+		cd describe-repo &&
+
+		# The bad arg is the only arg passed to describe atom
+		cat >expect <<-\EOF &&
+		fatal: unrecognized %(describe) argument: baz
+		EOF
+		test_must_fail ${git_for_each_ref} --format="%(describe:baz)" \
+			refs/heads/master 2>actual &&
+		test_cmp expect actual &&
+
+		# The bad arg is in the middle of the option string
+		# passed to the describe atom
+		cat >expect <<-\EOF &&
+		fatal: unrecognized %(describe) argument: qux=1,abbrev=14
+		EOF
+		test_must_fail ${git_for_each_ref} \
+			--format="%(describe:tags,qux=1,abbrev=14)" \
+			ref/heads/master 2>actual &&
+		test_cmp expect actual
+	)
+'
+
+cat >expected <<\EOF
+heads/main
+tags/main
+EOF
+
+test_expect_success 'Check ambiguous head and tag refs (strict)' '
+	git config --bool core.warnambiguousrefs true &&
+	git checkout -b newtag &&
+	echo "Using $datestamp" > one &&
+	git add one &&
+	git commit -m "Branch" &&
+	setdate_and_increment &&
+	git tag -m "Tagging at $datestamp" main &&
+	${git_for_each_ref} --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<\EOF
+heads/main
+main
+EOF
+
+test_expect_success 'Check ambiguous head and tag refs (loose)' '
+	git config --bool core.warnambiguousrefs false &&
+	${git_for_each_ref} --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<\EOF
+heads/ambiguous
+ambiguous
+EOF
+
+test_expect_success 'Check ambiguous head and tag refs II (loose)' '
+	git checkout main &&
+	git tag ambiguous testtag^0 &&
+	git branch ambiguous testtag^0 &&
+	${git_for_each_ref} --format "%(refname:short)" refs/heads/ambiguous refs/tags/ambiguous >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'create tag without tagger' '
+	git tag -a -m "Broken tag" taggerless &&
+	git tag -f taggerless $(git cat-file tag taggerless |
+		sed -e "/^tagger /d" |
+		git hash-object --literally --stdin -w -t tag)
+'
+
+test_atom refs/tags/taggerless type 'commit'
+test_atom refs/tags/taggerless tag 'taggerless'
+test_atom refs/tags/taggerless tagger ''
+test_atom refs/tags/taggerless taggername ''
+test_atom refs/tags/taggerless taggeremail ''
+test_atom refs/tags/taggerless taggeremail:trim ''
+test_atom refs/tags/taggerless taggeremail:localpart ''
+test_atom refs/tags/taggerless taggerdate ''
+test_atom refs/tags/taggerless committer ''
+test_atom refs/tags/taggerless committername ''
+test_atom refs/tags/taggerless committeremail ''
+test_atom refs/tags/taggerless committeremail:trim ''
+test_atom refs/tags/taggerless committeremail:localpart ''
+test_atom refs/tags/taggerless committerdate ''
+test_atom refs/tags/taggerless subject 'Broken tag'
+
+test_expect_success 'an unusual tag with an incomplete line' '
+
+	git tag -m "bogo" bogo &&
+	bogo=$(git cat-file tag bogo) &&
+	bogo=$(printf "%s" "$bogo" | git mktag) &&
+	git tag -f bogo "$bogo" &&
+	${git_for_each_ref} --format "%(body)" refs/tags/bogo
+
+'
+
+test_expect_success 'create tag with subject and body content' '
+	cat >>msg <<-\EOF &&
+		the subject line
+
+		first body line
+		second body line
+	EOF
+	git tag -F msg subject-body
+'
+test_atom refs/tags/subject-body subject 'the subject line'
+test_atom refs/tags/subject-body subject:sanitize 'the-subject-line'
+test_atom refs/tags/subject-body body 'first body line
+second body line
+'
+test_atom refs/tags/subject-body contents 'the subject line
+
+first body line
+second body line
+'
+
+test_expect_success 'create tag with multiline subject' '
+	cat >msg <<-\EOF &&
+		first subject line
+		second subject line
+
+		first body line
+		second body line
+	EOF
+	git tag -F msg multiline
+'
+test_atom refs/tags/multiline subject 'first subject line second subject line'
+test_atom refs/tags/multiline subject:sanitize 'first-subject-line-second-subject-line'
+test_atom refs/tags/multiline contents:subject 'first subject line second subject line'
+test_atom refs/tags/multiline body 'first body line
+second body line
+'
+test_atom refs/tags/multiline contents:body 'first body line
+second body line
+'
+test_atom refs/tags/multiline contents:signature ''
+test_atom refs/tags/multiline contents 'first subject line
+second subject line
+
+first body line
+second body line
+'
+
+test_expect_success GPG 'create signed tags' '
+	git tag -s -m "" signed-empty &&
+	git tag -s -m "subject line" signed-short &&
+	cat >msg <<-\EOF &&
+	subject line
+
+	body contents
+	EOF
+	git tag -s -F msg signed-long
+'
+
+sig='-----BEGIN PGP SIGNATURE-----
+-----END PGP SIGNATURE-----
+'
+
+PREREQ=GPG
+test_atom refs/tags/signed-empty subject ''
+test_atom refs/tags/signed-empty subject:sanitize ''
+test_atom refs/tags/signed-empty contents:subject ''
+test_atom refs/tags/signed-empty body "$sig"
+test_atom refs/tags/signed-empty contents:body ''
+test_atom refs/tags/signed-empty contents:signature "$sig"
+test_atom refs/tags/signed-empty contents "$sig"
+
+test_expect_success GPG 'basic atom: refs/tags/signed-empty raw' '
+	git cat-file tag refs/tags/signed-empty >expected &&
+	${git_for_each_ref} --format="%(raw)" refs/tags/signed-empty >actual &&
+	sanitize_pgp <expected >expected.clean &&
+	echo >>expected.clean &&
+	sanitize_pgp <actual >actual.clean &&
+	test_cmp expected.clean actual.clean
+'
+
+test_atom refs/tags/signed-short subject 'subject line'
+test_atom refs/tags/signed-short subject:sanitize 'subject-line'
+test_atom refs/tags/signed-short contents:subject 'subject line'
+test_atom refs/tags/signed-short body "$sig"
+test_atom refs/tags/signed-short contents:body ''
+test_atom refs/tags/signed-short contents:signature "$sig"
+test_atom refs/tags/signed-short contents "subject line
+$sig"
+
+test_expect_success GPG 'basic atom: refs/tags/signed-short raw' '
+	git cat-file tag refs/tags/signed-short >expected &&
+	${git_for_each_ref} --format="%(raw)" refs/tags/signed-short >actual &&
+	sanitize_pgp <expected >expected.clean &&
+	echo >>expected.clean &&
+	sanitize_pgp <actual >actual.clean &&
+	test_cmp expected.clean actual.clean
+'
+
+test_atom refs/tags/signed-long subject 'subject line'
+test_atom refs/tags/signed-long subject:sanitize 'subject-line'
+test_atom refs/tags/signed-long contents:subject 'subject line'
+test_atom refs/tags/signed-long body "body contents
+$sig"
+test_atom refs/tags/signed-long contents:body 'body contents
+'
+test_atom refs/tags/signed-long contents:signature "$sig"
+test_atom refs/tags/signed-long contents "subject line
+
+body contents
+$sig"
+
+test_expect_success GPG 'basic atom: refs/tags/signed-long raw' '
+	git cat-file tag refs/tags/signed-long >expected &&
+	${git_for_each_ref} --format="%(raw)" refs/tags/signed-long >actual &&
+	sanitize_pgp <expected >expected.clean &&
+	echo >>expected.clean &&
+	sanitize_pgp <actual >actual.clean &&
+	test_cmp expected.clean actual.clean
+'
+
+test_expect_success 'set up refs pointing to tree and blob' '
+	git update-ref refs/mytrees/first refs/heads/main^{tree} &&
+	git update-ref refs/myblobs/first refs/heads/main:one
+'
+
+test_atom refs/mytrees/first subject ""
+test_atom refs/mytrees/first contents:subject ""
+test_atom refs/mytrees/first body ""
+test_atom refs/mytrees/first contents:body ""
+test_atom refs/mytrees/first contents:signature ""
+test_atom refs/mytrees/first contents ""
+
+test_expect_success 'basic atom: refs/mytrees/first raw' '
+	git cat-file tree refs/mytrees/first >expected &&
+	echo >>expected &&
+	${git_for_each_ref} --format="%(raw)" refs/mytrees/first >actual &&
+	test_cmp expected actual &&
+	git cat-file -s refs/mytrees/first >expected &&
+	${git_for_each_ref} --format="%(raw:size)" refs/mytrees/first >actual &&
+	test_cmp expected actual
+'
+
+test_atom refs/myblobs/first subject ""
+test_atom refs/myblobs/first contents:subject ""
+test_atom refs/myblobs/first body ""
+test_atom refs/myblobs/first contents:body ""
+test_atom refs/myblobs/first contents:signature ""
+test_atom refs/myblobs/first contents ""
+
+test_expect_success 'basic atom: refs/myblobs/first raw' '
+	git cat-file blob refs/myblobs/first >expected &&
+	echo >>expected &&
+	${git_for_each_ref} --format="%(raw)" refs/myblobs/first >actual &&
+	test_cmp expected actual &&
+	git cat-file -s refs/myblobs/first >expected &&
+	${git_for_each_ref} --format="%(raw:size)" refs/myblobs/first >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'set up refs pointing to binary blob' '
+	printf "a\0b\0c" >blob1 &&
+	printf "a\0c\0b" >blob2 &&
+	printf "\0a\0b\0c" >blob3 &&
+	printf "abc" >blob4 &&
+	printf "\0 \0 \0 " >blob5 &&
+	printf "\0 \0a\0 " >blob6 &&
+	printf "  " >blob7 &&
+	>blob8 &&
+	obj=$(git hash-object -w blob1) &&
+	git update-ref refs/myblobs/blob1 "$obj" &&
+	obj=$(git hash-object -w blob2) &&
+	git update-ref refs/myblobs/blob2 "$obj" &&
+	obj=$(git hash-object -w blob3) &&
+	git update-ref refs/myblobs/blob3 "$obj" &&
+	obj=$(git hash-object -w blob4) &&
+	git update-ref refs/myblobs/blob4 "$obj" &&
+	obj=$(git hash-object -w blob5) &&
+	git update-ref refs/myblobs/blob5 "$obj" &&
+	obj=$(git hash-object -w blob6) &&
+	git update-ref refs/myblobs/blob6 "$obj" &&
+	obj=$(git hash-object -w blob7) &&
+	git update-ref refs/myblobs/blob7 "$obj" &&
+	obj=$(git hash-object -w blob8) &&
+	git update-ref refs/myblobs/blob8 "$obj"
+'
+
+test_expect_success 'Verify sorts with raw' '
+	cat >expected <<-EOF &&
+	refs/myblobs/blob8
+	refs/myblobs/blob5
+	refs/myblobs/blob6
+	refs/myblobs/blob3
+	refs/myblobs/blob7
+	refs/mytrees/first
+	refs/myblobs/first
+	refs/myblobs/blob1
+	refs/myblobs/blob2
+	refs/myblobs/blob4
+	refs/heads/main
+	EOF
+	${git_for_each_ref} --format="%(refname)" --sort=raw \
+		refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'Verify sorts with raw:size' '
+	cat >expected <<-EOF &&
+	refs/myblobs/blob8
+	refs/myblobs/blob7
+	refs/myblobs/blob4
+	refs/myblobs/blob1
+	refs/myblobs/blob2
+	refs/myblobs/blob3
+	refs/myblobs/blob5
+	refs/myblobs/blob6
+	refs/myblobs/first
+	refs/mytrees/first
+	refs/heads/main
+	EOF
+	${git_for_each_ref} --format="%(refname)" --sort=raw:size \
+		refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'validate raw atom with %(if:equals)' '
+	cat >expected <<-EOF &&
+	not equals
+	not equals
+	not equals
+	not equals
+	not equals
+	not equals
+	refs/myblobs/blob4
+	not equals
+	not equals
+	not equals
+	not equals
+	not equals
+	EOF
+	${git_for_each_ref} --format="%(if:equals=abc)%(raw)%(then)%(refname)%(else)not equals%(end)" \
+		refs/myblobs/ refs/heads/ >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'validate raw atom with %(if:notequals)' '
+	cat >expected <<-EOF &&
+	refs/heads/ambiguous
+	refs/heads/main
+	refs/heads/newtag
+	refs/myblobs/blob1
+	refs/myblobs/blob2
+	refs/myblobs/blob3
+	equals
+	refs/myblobs/blob5
+	refs/myblobs/blob6
+	refs/myblobs/blob7
+	refs/myblobs/blob8
+	refs/myblobs/first
+	EOF
+	${git_for_each_ref} --format="%(if:notequals=abc)%(raw)%(then)%(refname)%(else)equals%(end)" \
+		refs/myblobs/ refs/heads/ >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'empty raw refs with %(if)' '
+	cat >expected <<-EOF &&
+	refs/myblobs/blob1 not empty
+	refs/myblobs/blob2 not empty
+	refs/myblobs/blob3 not empty
+	refs/myblobs/blob4 not empty
+	refs/myblobs/blob5 not empty
+	refs/myblobs/blob6 not empty
+	refs/myblobs/blob7 empty
+	refs/myblobs/blob8 empty
+	refs/myblobs/first not empty
+	EOF
+	${git_for_each_ref} --format="%(refname) %(if)%(raw)%(then)not empty%(else)empty%(end)" \
+		refs/myblobs/ >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '%(raw) with --python must fail' '
+	test_must_fail ${git_for_each_ref} --format="%(raw)" --python
+'
+
+test_expect_success '%(raw) with --tcl must fail' '
+	test_must_fail ${git_for_each_ref} --format="%(raw)" --tcl
+'
+
+test_expect_success PERL_TEST_HELPERS '%(raw) with --perl' '
+	${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/blob1 --perl | perl >actual &&
+	cmp blob1 actual &&
+	${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/blob3 --perl | perl >actual &&
+	cmp blob3 actual &&
+	${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/blob8 --perl | perl >actual &&
+	cmp blob8 actual &&
+	${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/first --perl | perl >actual &&
+	cmp one actual &&
+	git cat-file tree refs/mytrees/first > expected &&
+	${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/mytrees/first --perl | perl >actual &&
+	cmp expected actual
+'
+
+test_expect_success '%(raw) with --shell must fail' '
+	test_must_fail ${git_for_each_ref} --format="%(raw)" --shell
+'
+
+test_expect_success '%(raw) with --shell and --sort=raw must fail' '
+	test_must_fail ${git_for_each_ref} --format="%(raw)" --sort=raw --shell
+'
+
+test_expect_success '%(raw:size) with --shell' '
+	${git_for_each_ref} --format="%(raw:size)" | sed "s/^/$SQ/;s/$/$SQ/" >expect &&
+	${git_for_each_ref} --format="%(raw:size)" --shell >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success "${git_for_each_ref} --format compare with cat-file --batch" '
+	git rev-parse refs/mytrees/first | git cat-file --batch >expected &&
+	${git_for_each_ref} --format="%(objectname) %(objecttype) %(objectsize)
+%(raw)" refs/mytrees/first >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'verify sorts with contents:size' '
+	cat >expect <<-\EOF &&
+	refs/heads/main
+	refs/heads/newtag
+	refs/heads/ambiguous
+	EOF
+	${git_for_each_ref} --format="%(refname)" \
+		--sort=contents:size refs/heads/ >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'set up multiple-sort tags' '
+	for when in 100000 200000
+	do
+		for email in user1 user2
+		do
+			for ref in ref1 ref2
+			do
+				GIT_COMMITTER_DATE="@$when +0000" \
+				GIT_COMMITTER_EMAIL="$email@example.com" \
+				git tag -m "tag $ref-$when-$email" \
+				multi-$ref-$when-$email || return 1
+			done
+		done
+	done
+'
+
+test_expect_success 'Verify sort with multiple keys' '
+	cat >expected <<-\EOF &&
+	100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
+	100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
+	100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
+	100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
+	200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
+	200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
+	200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
+	200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
+	EOF
+	${git_for_each_ref} \
+		--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
+		--sort=-refname \
+		--sort=taggeremail \
+		--sort=taggerdate \
+		"refs/tags/multi-*" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'equivalent sorts fall back on refname' '
+	cat >expected <<-\EOF &&
+	100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
+	100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
+	100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
+	100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
+	200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
+	200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
+	200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
+	200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
+	EOF
+	${git_for_each_ref} \
+		--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
+		--sort=taggerdate \
+		"refs/tags/multi-*" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '--no-sort cancels the previous sort keys' '
+	cat >expected <<-\EOF &&
+	100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
+	100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
+	100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
+	100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
+	200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
+	200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
+	200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
+	200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
+	EOF
+	${git_for_each_ref} \
+		--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
+		--sort=-refname \
+		--sort=taggeremail \
+		--no-sort \
+		--sort=taggerdate \
+		"refs/tags/multi-*" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '--no-sort without subsequent --sort prints expected refs' '
+	cat >expected <<-\EOF &&
+	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
+	EOF
+
+	# Sort the results with `sort` for a consistent comparison against
+	# expected
+	${git_for_each_ref} \
+		--format="%(refname)" \
+		--no-sort \
+		"refs/tags/multi-*" | sort >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'set up custom date sorting' '
+	# Dates:
+	# - Wed Feb 07 2024 21:34:20 +0000
+	# - Tue Dec 14 1999 00:05:22 +0000
+	# - Fri Jun 04 2021 11:26:51 +0000
+	# - Mon Jan 22 2007 16:44:01 GMT+0000
+	i=1 &&
+	for when in 1707341660 945129922 1622806011 1169484241
+	do
+		GIT_COMMITTER_DATE="@$when +0000" \
+		GIT_COMMITTER_EMAIL="user@example.com" \
+		git tag -m "tag $when" custom-dates-$i &&
+		i=$(($i+1)) || return 1
+	done
+'
+
+test_expect_success 'sort by date defaults to full timestamp' '
+	cat >expected <<-\EOF &&
+	945129922 refs/tags/custom-dates-2
+	1169484241 refs/tags/custom-dates-4
+	1622806011 refs/tags/custom-dates-3
+	1707341660 refs/tags/custom-dates-1
+	EOF
+
+	${git_for_each_ref} \
+		--format="%(creatordate:unix) %(refname)" \
+		--sort=creatordate \
+		"refs/tags/custom-dates-*" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'sort by custom date format' '
+	cat >expected <<-\EOF &&
+	00:05:22 refs/tags/custom-dates-2
+	11:26:51 refs/tags/custom-dates-3
+	16:44:01 refs/tags/custom-dates-4
+	21:34:20 refs/tags/custom-dates-1
+	EOF
+
+	${git_for_each_ref} \
+		--format="%(creatordate:format:%H:%M:%S) %(refname)" \
+		--sort="creatordate:format:%H:%M:%S" \
+		"refs/tags/custom-dates-*" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' '
+	test_when_finished "git checkout main" &&
+	${git_for_each_ref} --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
+	sed -e "s/^\* /  /" actual >expect &&
+	git checkout --orphan orphaned-branch &&
+	${git_for_each_ref} --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
+	test_cmp expect actual
+'
+
+cat >trailers <<EOF
+Reviewed-by: A U Thor <author@example.com>
+Signed-off-by: A U Thor <author@example.com>
+[ v2 updated patch description ]
+Acked-by: A U Thor
+  <author@example.com>
+EOF
+
+unfold () {
+	perl -0pe 's/\n\s+/ /g'
+}
+
+test_expect_success 'set up trailers for next test' '
+	echo "Some contents" > two &&
+	git add two &&
+	git commit -F - <<-EOF
+	trailers: this commit message has trailers
+
+	Some message contents
+
+	$(cat trailers)
+	EOF
+'
+
+test_trailer_option () {
+	if test "$#" -eq 3
+	then
+		prereq="$1"
+		shift
+	fi &&
+	title=$1 option=$2
+	cat >expect
+	test_expect_success $prereq "$title" '
+		${git_for_each_ref} --format="%($option)" refs/heads/main >actual &&
+		test_cmp expect actual &&
+		${git_for_each_ref} --format="%(contents:$option)" refs/heads/main >actual &&
+		test_cmp expect actual
+	'
+}
+
+test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) unfolds trailers' \
+	'trailers:unfold' <<-EOF
+	$(unfold <trailers)
+
+	EOF
+
+test_trailer_option '%(trailers:only) shows only "key: value" trailers' \
+	'trailers:only' <<-EOF
+	$(grep -v patch.description <trailers)
+
+	EOF
+
+test_trailer_option '%(trailers:only=no,only=true) shows only "key: value" trailers' \
+	'trailers:only=no,only=true' <<-EOF
+	$(grep -v patch.description <trailers)
+
+	EOF
+
+test_trailer_option '%(trailers:only=yes) shows only "key: value" trailers' \
+	'trailers:only=yes' <<-EOF
+	$(grep -v patch.description <trailers)
+
+	EOF
+
+test_trailer_option '%(trailers:only=no) shows all trailers' \
+	'trailers:only=no' <<-EOF
+	$(cat trailers)
+
+	EOF
+
+test_trailer_option PERL_TEST_HELPERS '%(trailers:only) and %(trailers:unfold) work together' \
+	'trailers:only,unfold' <<-EOF
+	$(grep -v patch.description <trailers | unfold)
+
+	EOF
+
+test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) and %(trailers:only) work together' \
+	'trailers:unfold,only' <<-EOF
+	$(grep -v patch.description <trailers | unfold)
+
+	EOF
+
+test_trailer_option '%(trailers:key=foo) shows that trailer' \
+	'trailers:key=Signed-off-by' <<-EOF
+	Signed-off-by: A U Thor <author@example.com>
+
+	EOF
+
+test_trailer_option '%(trailers:key=foo) is case insensitive' \
+	'trailers:key=SiGned-oFf-bY' <<-EOF
+	Signed-off-by: A U Thor <author@example.com>
+
+	EOF
+
+test_trailer_option '%(trailers:key=foo:) trailing colon also works' \
+	'trailers:key=Signed-off-by:' <<-EOF
+	Signed-off-by: A U Thor <author@example.com>
+
+	EOF
+
+test_trailer_option '%(trailers:key=foo) multiple keys' \
+	'trailers:key=Reviewed-by:,key=Signed-off-by' <<-EOF
+	Reviewed-by: A U Thor <author@example.com>
+	Signed-off-by: A U Thor <author@example.com>
+
+	EOF
+
+test_trailer_option '%(trailers:key=nonexistent) becomes empty' \
+	'trailers:key=Shined-off-by:' <<-EOF
+
+	EOF
+
+test_trailer_option '%(trailers:key=foo) handles multiple lines even if folded' \
+	'trailers:key=Acked-by' <<-EOF
+	$(grep -v patch.description <trailers | grep -v Signed-off-by | grep -v Reviewed-by)
+
+	EOF
+
+test_trailer_option '%(trailers:key=foo,unfold) properly unfolds' \
+	'trailers:key=Signed-Off-by,unfold' <<-EOF
+	$(unfold <trailers | grep Signed-off-by)
+
+	EOF
+
+test_trailer_option '%(trailers:key=foo,only=no) also includes nontrailer lines' \
+	'trailers:key=Signed-off-by,only=no' <<-EOF
+	Signed-off-by: A U Thor <author@example.com>
+	$(grep patch.description <trailers)
+
+	EOF
+
+test_trailer_option '%(trailers:key=foo,valueonly) shows only value' \
+	'trailers:key=Signed-off-by,valueonly' <<-EOF
+	A U Thor <author@example.com>
+
+	EOF
+
+test_trailer_option '%(trailers:separator) changes separator' \
+	'trailers:separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
+	Reviewed-by: A U Thor <author@example.com>,Signed-off-by: A U Thor <author@example.com>
+	EOF
+
+test_trailer_option '%(trailers:key_value_separator) changes key-value separator' \
+	'trailers:key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
+	Reviewed-by,A U Thor <author@example.com>
+	Signed-off-by,A U Thor <author@example.com>
+
+	EOF
+
+test_trailer_option '%(trailers:separator,key_value_separator) changes both separators' \
+	'trailers:separator=%x2C,key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
+	Reviewed-by,A U Thor <author@example.com>,Signed-off-by,A U Thor <author@example.com>
+	EOF
+
+test_expect_success 'multiple %(trailers) use their own options' '
+	git tag -F - tag-with-trailers <<-\EOF &&
+	body
+
+	one: foo
+	one: bar
+	two: baz
+	two: qux
+	EOF
+	t1="%(trailers:key=one,key_value_separator=W,separator=X)" &&
+	t2="%(trailers:key=two,key_value_separator=Y,separator=Z)" &&
+	${git_for_each_ref} --format="$t1%0a$t2" refs/tags/tag-with-trailers >actual &&
+	cat >expect <<-\EOF &&
+	oneWfooXoneWbar
+	twoYbazZtwoYqux
+	EOF
+	test_cmp expect actual
+'
+
+test_failing_trailer_option () {
+	title=$1 option=$2
+	cat >expect
+	test_expect_success "$title" '
+		# error message cannot be checked under i18n
+		test_must_fail ${git_for_each_ref} --format="%($option)" refs/heads/main 2>actual &&
+		test_cmp expect actual &&
+		test_must_fail ${git_for_each_ref} --format="%(contents:$option)" refs/heads/main 2>actual &&
+		test_cmp expect actual
+	'
+}
+
+test_failing_trailer_option '%(trailers) rejects unknown trailers arguments' \
+	'trailers:unsupported' <<-\EOF
+	fatal: unknown %(trailers) argument: unsupported
+	EOF
+
+test_failing_trailer_option '%(trailers:key) without value is error' \
+	'trailers:key' <<-\EOF
+	fatal: expected %(trailers:key=<value>)
+	EOF
+
+test_expect_success 'if arguments, %(contents:trailers) shows error if colon is missing' '
+	cat >expect <<-EOF &&
+	fatal: unrecognized %(contents) argument: trailersonly
+	EOF
+	test_must_fail ${git_for_each_ref} --format="%(contents:trailersonly)" 2>actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'basic atom: head contents:trailers' '
+	${git_for_each_ref} --format="%(contents:trailers)" refs/heads/main >actual &&
+	sanitize_pgp <actual >actual.clean &&
+	# ${git_for_each_ref} ends with a blank line
+	cat >expect <<-EOF &&
+	$(cat trailers)
+
+	EOF
+	test_cmp expect actual.clean
+'
+
+test_expect_success 'basic atom: rest must fail' '
+	test_must_fail ${git_for_each_ref} --format="%(rest)" refs/heads/main
+'
+
+test_expect_success 'HEAD atom does not take arguments' '
+	test_must_fail ${git_for_each_ref} --format="%(HEAD:foo)" 2>err &&
+	echo "fatal: %(HEAD) does not take arguments" >expect &&
+	test_cmp expect err
+'
+
+test_expect_success 'subject atom rejects unknown arguments' '
+	test_must_fail ${git_for_each_ref} --format="%(subject:foo)" 2>err &&
+	echo "fatal: unrecognized %(subject) argument: foo" >expect &&
+	test_cmp expect err
+'
+
+test_expect_success 'refname atom rejects unknown arguments' '
+	test_must_fail ${git_for_each_ref} --format="%(refname:foo)" 2>err &&
+	echo "fatal: unrecognized %(refname) argument: foo" >expect &&
+	test_cmp expect err
+'
+
+test_expect_success 'trailer parsing not fooled by --- line' '
+	git commit --allow-empty -F - <<-\EOF &&
+	this is the subject
+
+	This is the body. The message has a "---" line which would confuse a
+	message+patch parser. But here we know we have only a commit message,
+	so we get it right.
+
+	trailer: wrong
+	---
+	This is more body.
+
+	trailer: right
+	EOF
+
+	{
+		echo "trailer: right" &&
+		echo
+	} >expect &&
+	${git_for_each_ref} --format="%(trailers)" refs/heads/main >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'Add symbolic ref for the following tests' '
+	git symbolic-ref refs/heads/sym refs/heads/main
+'
+
+cat >expected <<EOF
+refs/heads/main
+EOF
+
+test_expect_success 'Verify usage of %(symref) atom' '
+	${git_for_each_ref} --format="%(symref)" refs/heads/sym >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<EOF
+heads/main
+EOF
+
+test_expect_success 'Verify usage of %(symref:short) atom' '
+	${git_for_each_ref} --format="%(symref:short)" refs/heads/sym >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<EOF
+main
+heads/main
+EOF
+
+test_expect_success 'Verify usage of %(symref:lstrip) atom' '
+	${git_for_each_ref} --format="%(symref:lstrip=2)" refs/heads/sym > actual &&
+	${git_for_each_ref} --format="%(symref:lstrip=-2)" refs/heads/sym >> actual &&
+	test_cmp expected actual &&
+
+	${git_for_each_ref} --format="%(symref:strip=2)" refs/heads/sym > actual &&
+	${git_for_each_ref} --format="%(symref:strip=-2)" refs/heads/sym >> actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<EOF
+refs
+refs/heads
+EOF
+
+test_expect_success 'Verify usage of %(symref:rstrip) atom' '
+	${git_for_each_ref} --format="%(symref:rstrip=2)" refs/heads/sym > actual &&
+	${git_for_each_ref} --format="%(symref:rstrip=-2)" refs/heads/sym >> actual &&
+	test_cmp expected actual
+'
+
+test_expect_success ':remotename and :remoteref' '
+	git init remote-tests &&
+	(
+		cd remote-tests &&
+		test_commit initial &&
+		git branch -M main &&
+		git remote add from fifth.coffee:blub &&
+		git config branch.main.remote from &&
+		git config branch.main.merge refs/heads/stable &&
+		git remote add to southridge.audio:repo &&
+		git config remote.to.push "refs/heads/*:refs/heads/pushed/*" &&
+		git config branch.main.pushRemote to &&
+		for pair in "%(upstream)=refs/remotes/from/stable" \
+			"%(upstream:remotename)=from" \
+			"%(upstream:remoteref)=refs/heads/stable" \
+			"%(push)=refs/remotes/to/pushed/main" \
+			"%(push:remotename)=to" \
+			"%(push:remoteref)=refs/heads/pushed/main"
+		do
+			echo "${pair#*=}" >expect &&
+			${git_for_each_ref} --format="${pair%=*}" \
+				refs/heads/main >actual &&
+			test_cmp expect actual || exit 1
+		done &&
+		git branch push-simple &&
+		git config branch.push-simple.pushRemote from &&
+		actual="$(${git_for_each_ref} \
+			--format="%(push:remotename),%(push:remoteref)" \
+			refs/heads/push-simple)" &&
+		test from, = "$actual"
+	)
+'
+
+test_expect_success "${git_for_each_ref} --ignore-case ignores case" '
+	${git_for_each_ref} --format="%(refname)" refs/heads/MAIN >actual &&
+	test_must_be_empty actual &&
+
+	echo refs/heads/main >expect &&
+	${git_for_each_ref} --format="%(refname)" --ignore-case \
+		refs/heads/MAIN >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success "${git_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 "${git_for_each_ref} --ignore-case works on multiple sort keys" '
+	# name refs numerically to avoid case-insensitive filesystem conflicts
+	nr=0 &&
+	for email in a A b B
+	do
+		for subject in a A b B
+		do
+			GIT_COMMITTER_EMAIL="$email@example.com" \
+			git tag -m "tag $subject" icase-$(printf %02d $nr) &&
+			nr=$((nr+1))||
+			return 1
+		done
+	done &&
+	${git_for_each_ref} --ignore-case \
+		--format="%(taggeremail) %(subject) %(refname)" \
+		--sort=refname \
+		--sort=subject \
+		--sort=taggeremail \
+		refs/tags/icase-* >actual &&
+	cat >expect <<-\EOF &&
+	<a@example.com> tag a refs/tags/icase-00
+	<a@example.com> tag A refs/tags/icase-01
+	<A@example.com> tag a refs/tags/icase-04
+	<A@example.com> tag A refs/tags/icase-05
+	<a@example.com> tag b refs/tags/icase-02
+	<a@example.com> tag B refs/tags/icase-03
+	<A@example.com> tag b refs/tags/icase-06
+	<A@example.com> tag B refs/tags/icase-07
+	<b@example.com> tag a refs/tags/icase-08
+	<b@example.com> tag A refs/tags/icase-09
+	<B@example.com> tag a refs/tags/icase-12
+	<B@example.com> tag A refs/tags/icase-13
+	<b@example.com> tag b refs/tags/icase-10
+	<b@example.com> tag B refs/tags/icase-11
+	<B@example.com> tag b refs/tags/icase-14
+	<B@example.com> tag B refs/tags/icase-15
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "${git_for_each_ref} reports broken tags" '
+	git tag -m "good tag" broken-tag-good HEAD &&
+	git cat-file tag broken-tag-good >good &&
+	sed s/commit/blob/ <good >bad &&
+	bad=$(git hash-object -w -t tag bad) &&
+	git update-ref refs/tags/broken-tag-bad $bad &&
+	test_must_fail ${git_for_each_ref} --format="%(*objectname)" \
+		refs/tags/broken-tag-* &&
+	test_must_fail ${git_for_each_ref} --format="%(*objectname)" \
+		refs/tags/broken-tag-bad
+'
+
+test_expect_success 'set up tag with signature and no blank lines' '
+	git tag -F - fake-sig-no-blanks <<-\EOF
+	this is the subject
+	-----BEGIN PGP SIGNATURE-----
+	not a real signature, but we just care about the
+	subject/body parsing. It is important here that
+	there are no blank lines in the signature.
+	-----END PGP SIGNATURE-----
+	EOF
+'
+
+test_atom refs/tags/fake-sig-no-blanks contents:subject 'this is the subject'
+test_atom refs/tags/fake-sig-no-blanks contents:body ''
+test_atom refs/tags/fake-sig-no-blanks contents:signature "$sig"
+
+test_expect_success 'set up tag with CRLF signature' '
+	append_cr <<-\EOF |
+	this is the subject
+	-----BEGIN PGP SIGNATURE-----
+
+	not a real signature, but we just care about
+	the subject/body parsing. It is important here
+	that there is a blank line separating this
+	from the signature header.
+	-----END PGP SIGNATURE-----
+	EOF
+	git tag -F - --cleanup=verbatim fake-sig-crlf
+'
+
+test_atom refs/tags/fake-sig-crlf contents:subject 'this is the subject'
+test_atom refs/tags/fake-sig-crlf contents:body ''
+
+# CRLF is retained in the signature, so we have to pass our expected value
+# through append_cr. But test_atom requires a shell string, which means command
+# substitution, and the shell will strip trailing newlines from the output of
+# the substitution. Hack around it by adding and then removing a dummy line.
+sig_crlf="$(printf "%s" "$sig" | append_cr; echo dummy)"
+sig_crlf=${sig_crlf%dummy}
+test_atom refs/tags/fake-sig-crlf contents:signature "$sig_crlf"
+
+test_expect_success 'set up tag with signature and trailers' '
+	git tag -F - fake-sig-trailer <<-\EOF
+	this is the subject
+
+	this is the body
+
+	My-Trailer: foo
+	-----BEGIN PGP SIGNATURE-----
+
+	not a real signature, but we just care about the
+	subject/body/trailer parsing.
+	-----END PGP SIGNATURE-----
+	EOF
+'
+
+# use "separator=" here to suppress the terminating newline
+test_atom refs/tags/fake-sig-trailer trailers:separator= 'My-Trailer: foo'
+
+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_expect_success "${git_for_each_ref} with nested tags" '
+	git tag -am "Normal tag" nested/base HEAD &&
+	git tag -am "Nested tag" nested/nest1 refs/tags/nested/base &&
+	git tag -am "Double nested tag" nested/nest2 refs/tags/nested/nest1 &&
+
+	head_oid="$(git rev-parse HEAD)" &&
+	base_tag_oid="$(git rev-parse refs/tags/nested/base)" &&
+	nest1_tag_oid="$(git rev-parse refs/tags/nested/nest1)" &&
+	nest2_tag_oid="$(git rev-parse refs/tags/nested/nest2)" &&
+
+	cat >expect <<-EOF &&
+	refs/tags/nested/base $base_tag_oid tag $head_oid commit
+	refs/tags/nested/nest1 $nest1_tag_oid tag $head_oid commit
+	refs/tags/nested/nest2 $nest2_tag_oid tag $head_oid commit
+	EOF
+
+	${git_for_each_ref} \
+		--format="%(refname) %(objectname) %(objecttype) %(*objectname) %(*objecttype)" \
+		refs/tags/nested/ >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'is-base atom with non-commits' '
+	${git_for_each_ref} --format="%(is-base:HEAD) %(refname)" >out 2>err &&
+	grep "(HEAD) refs/heads/main" out &&
+
+	test_line_count = 2 err &&
+	grep "error: object .* is a commit, not a blob" err &&
+	grep "error: bad tag pointer to" err
+'
+
+GRADE_FORMAT="%(signature:grade)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)"
+TRUSTLEVEL_FORMAT="%(signature:trustlevel)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)"
+
+test_expect_success GPG 'setup for signature atom using gpg' '
+	git checkout -b signed &&
+
+	test_when_finished "test_unconfig commit.gpgSign" &&
+
+	echo "1" >file &&
+	git add file &&
+	test_tick &&
+	git commit -S -m "file: 1" &&
+	git tag first-signed &&
+
+	echo "2" >file &&
+	test_tick &&
+	git commit -a -m "file: 2" &&
+	git tag second-unsigned &&
+
+	git config commit.gpgSign 1 &&
+	echo "3" >file &&
+	test_tick &&
+	git commit -a --no-gpg-sign -m "file: 3" &&
+	git tag third-unsigned &&
+
+	test_tick &&
+	git rebase -f HEAD^^ && git tag second-signed HEAD^ &&
+	git tag third-signed &&
+
+	echo "4" >file &&
+	test_tick &&
+	git commit -a -SB7227189 -m "file: 4" &&
+	git tag fourth-signed &&
+
+	echo "5" >file &&
+	test_tick &&
+	git commit -a --no-gpg-sign -m "file: 5" &&
+	git tag fifth-unsigned &&
+
+	echo "6" >file &&
+	test_tick &&
+	git commit -a --no-gpg-sign -m "file: 6" &&
+
+	test_tick &&
+	git rebase -f HEAD^^ &&
+	git tag fifth-signed HEAD^ &&
+	git tag sixth-signed &&
+
+	echo "7" >file &&
+	test_tick &&
+	git commit -a --no-gpg-sign -m "file: 7" &&
+	git tag seventh-unsigned
+'
+
+test_expect_success GPGSSH 'setup for signature atom using ssh' '
+	test_when_finished "test_unconfig gpg.format user.signingkey" &&
+
+	test_config gpg.format ssh &&
+	test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+	echo "8" >file &&
+	test_tick &&
+	git add file &&
+	git commit -S -m "file: 8" &&
+	git tag eighth-signed-ssh
+'
+
+test_expect_success GPG2 'bare signature atom' '
+	git verify-commit first-signed 2>expect &&
+	echo  >>expect &&
+	${git_for_each_ref} refs/tags/first-signed \
+		--format="%(signature)" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success GPG 'show good signature with custom format' '
+	git verify-commit first-signed &&
+	cat >expect <<-\EOF &&
+	G
+	13B6F51ECDDE430D
+	C O Mitter <committer@example.com>
+	73D758744BE721698EC54E8713B6F51ECDDE430D
+	73D758744BE721698EC54E8713B6F51ECDDE430D
+	EOF
+	${git_for_each_ref} refs/tags/first-signed \
+		--format="$GRADE_FORMAT" >actual &&
+	test_cmp expect actual
+'
+test_expect_success GPGSSH 'show good signature with custom format with ssh' '
+	test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+	FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") &&
+	cat >expect.tmpl <<-\EOF &&
+	G
+	FINGERPRINT
+	principal with number 1
+	FINGERPRINT
+
+	EOF
+	sed "s|FINGERPRINT|$FINGERPRINT|g" expect.tmpl >expect &&
+	${git_for_each_ref} refs/tags/eighth-signed-ssh \
+		--format="$GRADE_FORMAT" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success GPG 'signature atom with grade option and bad signature' '
+	git cat-file commit third-signed >raw &&
+	sed -e "s/^file: 3/file: 3 forged/" raw >forged1 &&
+	FORGED1=$(git hash-object -w -t commit forged1) &&
+	git update-ref refs/tags/third-signed "$FORGED1" &&
+	test_must_fail git verify-commit "$FORGED1" &&
+
+	cat >expect <<-\EOF &&
+	B
+	13B6F51ECDDE430D
+	C O Mitter <committer@example.com>
+
+
+	EOF
+	${git_for_each_ref} refs/tags/third-signed \
+		--format="$GRADE_FORMAT" >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_for_each_ref} refs/tags/fourth-signed \
+		--format="$GRADE_FORMAT" >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_for_each_ref} refs/tags/fourth-signed \
+		--format="$TRUSTLEVEL_FORMAT" >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_for_each_ref} refs/tags/sixth-signed \
+		--format="$TRUSTLEVEL_FORMAT" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success GPG 'show unknown signature with custom format' '
+	cat >expect <<-\EOF &&
+	E
+	13B6F51ECDDE430D
+
+
+
+	EOF
+	GNUPGHOME="$GNUPGHOME_NOT_USED" ${git_for_each_ref} \
+		refs/tags/sixth-signed --format="$GRADE_FORMAT" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success GPG 'show lack of signature with custom format' '
+	cat >expect <<-\EOF &&
+	N
+
+
+
+
+	EOF
+	${git_for_each_ref} refs/tags/seventh-unsigned \
+		--format="$GRADE_FORMAT" >actual &&
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/helper/test-delete-gpgsig.c b/t/helper/test-delete-gpgsig.c
index e36831a..658c7a3 100644
--- a/t/helper/test-delete-gpgsig.c
+++ b/t/helper/test-delete-gpgsig.c
@@ -23,8 +23,7 @@ int cmd__delete_gpgsig(int argc, const char **argv)
 	if (!strcmp(pattern, "trailer")) {
 		size_t payload_size = parse_signed_buffer(buf.buf, buf.len);
 		fwrite(buf.buf, 1, payload_size, stdout);
-		fflush(stdout);
-		return 0;
+		goto out;
 	}
 
 	bufptr = buf.buf;
@@ -56,7 +55,9 @@ int cmd__delete_gpgsig(int argc, const char **argv)
 		fwrite(bufptr, 1, (eol - bufptr) + 1, stdout);
 		bufptr = eol + 1;
 	}
-	fflush(stdout);
 
+out:
+	fflush(stdout);
+	strbuf_release(&buf);
 	return 0;
 }
diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c
index 611a13a..fc4b8a7 100644
--- a/t/helper/test-find-pack.c
+++ b/t/helper/test-find-pack.c
@@ -39,11 +39,12 @@ int cmd__find_pack(int argc, const char **argv)
 	if (repo_get_oid(the_repository, argv[0], &oid))
 		die("cannot parse %s as an object name", argv[0]);
 
-	for (p = get_all_packs(the_repository); p; p = p->next)
+	repo_for_each_pack(the_repository, p) {
 		if (find_pack_entry_one(&oid, p)) {
 			printf("%s\n", p->pack_name);
 			actual_count++;
 		}
+	}
 
 	if (count > -1 && count != actual_count)
 		die("bad packfile count %d instead of %d", actual_count, count);
diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c
index 16a3145..56d223a 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -154,8 +154,8 @@ int cmd__hashmap(int argc UNUSED, const char **argv UNUSED)
 
 		/* break line into command and up to two parameters */
 		string_list_setlen(&parts, 0);
-		string_list_split_in_place(&parts, line.buf, DELIM, 2);
-		string_list_remove_empty_items(&parts, 0);
+		string_list_split_in_place_f(&parts, line.buf, DELIM, 2,
+					     STRING_LIST_SPLIT_NONEMPTY);
 
 		/* ignore empty lines */
 		if (!parts.nr)
diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c
index a288069..f8316a7 100644
--- a/t/helper/test-json-writer.c
+++ b/t/helper/test-json-writer.c
@@ -492,8 +492,8 @@ static int scripted(void)
 
 		/* 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);
+		string_list_split_in_place_f(&parts, line, " ", -1,
+					     STRING_LIST_SPLIT_NONEMPTY);
 
 		/* ignore empty lines */
 		if (!parts.nr || !*parts.items[0].string)
diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c
index d51aaa3..7a8ee1d 100644
--- a/t/helper/test-pack-mtimes.c
+++ b/t/helper/test-pack-mtimes.c
@@ -37,7 +37,7 @@ int cmd__pack_mtimes(int argc, const char **argv)
 	if (argc != 2)
 		usage(pack_mtimes_usage);
 
-	for (p = get_all_packs(the_repository); p; p = p->next) {
+	repo_for_each_pack(the_repository, p) {
 		strbuf_addstr(&buf, basename(p->pack_name));
 		strbuf_strip_suffix(&buf, ".pack");
 		strbuf_addstr(&buf, ".mtimes");
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index 086238c..f5f3375 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -348,6 +348,7 @@ int cmd__path_utils(int argc, const char **argv)
 	if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
 		int len;
 		struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
+		const char path_sep[] = { PATH_SEP, '\0' };
 		char *path = xstrdup(argv[2]);
 
 		/*
@@ -362,7 +363,7 @@ int cmd__path_utils(int argc, const char **argv)
 		 */
 		if (normalize_path_copy(path, path))
 			die("Path \"%s\" could not be normalized", argv[2]);
-		string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1);
+		string_list_split(&ceiling_dirs, argv[3], path_sep, -1);
 		filter_string_list(&ceiling_dirs, 0,
 				   normalize_ceiling_entry, NULL);
 		len = longest_ancestor_length(path, &ceiling_dirs);
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 028ec00..c58c938 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -63,7 +63,7 @@ int cmd__reach(int ac, const char **av)
 			die("failed to resolve %s", buf.buf + 2);
 
 		orig = parse_object(r, &oid);
-		peeled = deref_tag_noverify(the_repository, orig);
+		peeled = deref_tag(the_repository, orig, NULL, 0);
 
 		if (!peeled)
 			die("failed to load commit for input %s resulting in oid %s",
diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c
index ef5339b..6a5f64e 100644
--- a/t/helper/test-read-graph.c
+++ b/t/helper/test-read-graph.c
@@ -81,7 +81,7 @@ int cmd__read_graph(int argc, const char **argv)
 
 	prepare_repo_settings(the_repository);
 
-	graph = read_commit_graph_one(the_repository, source);
+	graph = read_commit_graph_one(source);
 	if (!graph) {
 		ret = 1;
 		goto done;
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index da2aa03..6de5d16 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -11,14 +11,24 @@
 #include "gettext.h"
 #include "pack-revindex.h"
 
+static struct multi_pack_index *setup_midx(const char *object_dir)
+{
+	struct odb_source *source;
+	setup_git_directory();
+	source = odb_find_source(the_repository->objects, object_dir);
+	if (!source)
+		source = odb_add_to_alternates_memory(the_repository->objects,
+						      object_dir);
+	return load_multi_pack_index(source);
+}
+
 static int read_midx_file(const char *object_dir, const char *checksum,
 			  int show_objects)
 {
 	uint32_t i;
 	struct multi_pack_index *m;
 
-	setup_git_directory();
-	m = load_multi_pack_index(the_repository, object_dir, 1);
+	m = setup_midx(object_dir);
 
 	if (!m)
 		return 1;
@@ -56,7 +66,7 @@ static int read_midx_file(const char *object_dir, const char *checksum,
 	for (i = 0; i < m->num_packs; i++)
 		printf("%s\n", m->pack_names[i]);
 
-	printf("object-dir: %s\n", m->object_dir);
+	printf("object-dir: %s\n", m->source->path);
 
 	if (show_objects) {
 		struct object_id oid;
@@ -65,7 +75,7 @@ static int read_midx_file(const char *object_dir, const char *checksum,
 		for (i = 0; i < m->num_objects; i++) {
 			nth_midxed_object_oid(&oid, m,
 					      i + m->num_objects_in_base);
-			fill_midx_entry(the_repository, &oid, &e, m);
+			fill_midx_entry(m, &oid, &e);
 
 			printf("%s %"PRIu64"\t%s\n",
 			       oid_to_hex(&oid), e.offset, e.p->pack_name);
@@ -81,8 +91,7 @@ static int read_midx_checksum(const char *object_dir)
 {
 	struct multi_pack_index *m;
 
-	setup_git_directory();
-	m = load_multi_pack_index(the_repository, object_dir, 1);
+	m = setup_midx(object_dir);
 	if (!m)
 		return 1;
 	printf("%s\n", hash_to_hex(get_midx_checksum(m)));
@@ -96,9 +105,7 @@ static int read_midx_preferred_pack(const char *object_dir)
 	struct multi_pack_index *midx = NULL;
 	uint32_t preferred_pack;
 
-	setup_git_directory();
-
-	midx = load_multi_pack_index(the_repository, object_dir, 1);
+	midx = setup_midx(object_dir);
 	if (!midx)
 		return 1;
 
@@ -119,14 +126,12 @@ static int read_midx_bitmapped_packs(const char *object_dir)
 	struct bitmapped_pack pack;
 	uint32_t i;
 
-	setup_git_directory();
-
-	midx = load_multi_pack_index(the_repository, object_dir, 1);
+	midx = setup_midx(object_dir);
 	if (!midx)
 		return 1;
 
 	for (i = 0; i < midx->num_packs + midx->num_packs_in_base; i++) {
-		if (nth_bitmapped_pack(the_repository, midx, &pack, i) < 0) {
+		if (nth_bitmapped_pack(midx, &pack, i) < 0) {
 			close_midx(midx);
 			return 1;
 		}
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 8d9a271..b121594 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -29,7 +29,7 @@ static unsigned int parse_flags(const char *str, struct flag_definition *defs)
 	if (!strcmp(str, "0"))
 		return 0;
 
-	string_list_split(&masks, str, ',', 64);
+	string_list_split(&masks, str, ",", 64);
 	for (size_t i = 0; i < masks.nr; i++) {
 		const char *name = masks.items[i].string;
 		struct flag_definition *def = defs;
@@ -154,10 +154,9 @@ static int cmd_rename_ref(struct ref_store *refs, const char **argv)
 	return refs_rename_ref(refs, oldref, newref, logmsg);
 }
 
-static int each_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-		    int flags, void *cb_data UNUSED)
+static int each_ref(const struct reference *ref, void *cb_data UNUSED)
 {
-	printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
+	printf("%s %s 0x%x\n", oid_to_hex(ref->oid), ref->name, ref->flags);
 	return 0;
 }
 
@@ -215,7 +214,8 @@ static int cmd_for_each_reflog(struct ref_store *refs,
 	return refs_for_each_reflog(refs, each_reflog, NULL);
 }
 
-static int each_reflog_ent(struct object_id *old_oid, struct object_id *new_oid,
+static int each_reflog_ent(const char *refname UNUSED,
+			   struct object_id *old_oid, struct object_id *new_oid,
 			   const char *committer, timestamp_t timestamp,
 			   int tz, const char *msg, void *cb_data UNUSED)
 {
diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh
index 937b876..97268ae 100644
--- a/t/lib-gpg.sh
+++ b/t/lib-gpg.sh
@@ -9,6 +9,16 @@
 GNUPGHOME="$(pwd)/gpghome"
 export GNUPGHOME
 
+# All the "test_lazy_prereq GPG*" below should use
+# `prepare_gnupghome()` either directly or through a call to
+# `test_have_prereq GPG*`. That's because `gpg` and `gpgsm`
+# only create the directory specified using "$GNUPGHOME" or
+# `--homedir` if it's the default (usually "~/.gnupg").
+prepare_gnupghome() {
+	mkdir -p "$GNUPGHOME" &&
+	chmod 0700 "$GNUPGHOME"
+}
+
 test_lazy_prereq GPG '
 	gpg_version=$(gpg --version 2>&1)
 	test $? != 127 || exit 1
@@ -38,8 +48,7 @@
 		# To export ownertrust:
 		#	gpg --homedir /tmp/gpghome --export-ownertrust \
 		#		> lib-gpg/ownertrust
-		mkdir "$GNUPGHOME" &&
-		chmod 0700 "$GNUPGHOME" &&
+		prepare_gnupghome &&
 		(gpgconf --kill all || : ) &&
 		gpg --homedir "${GNUPGHOME}" --import \
 			"$TEST_DIRECTORY"/lib-gpg/keyring.gpg &&
@@ -62,7 +71,16 @@
 		exit 1
 		;;
 	*)
+		prepare_gnupghome &&
 		(gpgconf --kill all || : ) &&
+
+		# NEEDSWORK: prepare_gnupghome() should definitely be
+		# called here, but it looks like it exposes a
+		# pre-existing, hidden bug by allowing some tests in
+		# t1016-compatObjectFormat.sh to run instead of being
+		# skipped. See:
+		# https://lore.kernel.org/git/ZoV8b2RvYxLOotSJ@teonanacatl.net/
+
 		gpg --homedir "${GNUPGHOME}" --import \
 			"$TEST_DIRECTORY"/lib-gpg/keyring.gpg &&
 		gpg --homedir "${GNUPGHOME}" --import-ownertrust \
@@ -132,8 +150,7 @@
 	test $? = 0 || exit 1;
 
 	# Setup some keys and an allowed signers file
-	mkdir -p "${GNUPGHOME}" &&
-	chmod 0700 "${GNUPGHOME}" &&
+	prepare_gnupghome &&
 	(setfacl -k "${GNUPGHOME}" 2>/dev/null || true) &&
 	ssh-keygen -t ed25519 -N "" -C "git ed25519 key" -f "${GPGSSH_KEY_PRIMARY}" >/dev/null &&
 	ssh-keygen -t rsa -b 2048 -N "" -C "git rsa2048 key" -f "${GPGSSH_KEY_SECONDARY}" >/dev/null &&
diff --git a/t/meson.build b/t/meson.build
index 9832455..dc43d69 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -1,5 +1,6 @@
 clar_test_suites = [
   'unit-tests/u-ctype.c',
+  'unit-tests/u-dir.c',
   'unit-tests/u-example-decorate.c',
   'unit-tests/u-hash.c',
   'unit-tests/u-hashmap.c',
@@ -23,6 +24,7 @@
   'unit-tests/u-strvec.c',
   'unit-tests/u-trailer.c',
   'unit-tests/u-urlmatch-normalization.c',
+  'unit-tests/u-utf8-width.c',
 ]
 
 clar_sources = [
@@ -145,6 +147,7 @@
   't0611-reftable-httpd.sh',
   't0612-reftable-jgit-compatibility.sh',
   't0613-reftable-write-options.sh',
+  't0614-reftable-fsck.sh',
   't1000-read-tree-m-3way.sh',
   't1001-read-tree-m-2way.sh',
   't1002-read-tree-m-u-2way.sh',
@@ -205,10 +208,14 @@
   't1419-exclude-refs.sh',
   't1420-lost-found.sh',
   't1421-reflog-write.sh',
+  't1422-show-ref-exists.sh',
   't1430-bad-ref-name.sh',
   't1450-fsck.sh',
   't1451-fsck-buffer.sh',
   't1460-refs-migrate.sh',
+  't1461-refs-list.sh',
+  't1462-refs-exists.sh',
+  't1463-refs-optimize.sh',
   't1500-rev-parse.sh',
   't1501-work-tree.sh',
   't1502-rev-parse-parseopt.sh',
@@ -231,6 +238,8 @@
   't1700-split-index.sh',
   't1701-racy-split-index.sh',
   't1800-hook.sh',
+  't1900-repo.sh',
+  't1901-repo-structure.sh',
   't2000-conflict-when-checking-files-out.sh',
   't2002-checkout-cache-u.sh',
   't2003-checkout-cache-mkdir.sh',
@@ -487,6 +496,7 @@
   't4069-remerge-diff.sh',
   't4070-diff-pairs.sh',
   't4071-diff-minimal.sh',
+  't4072-diff-max-depth.sh',
   't4100-apply-stat.sh',
   't4101-apply-nonl.sh',
   't4102-apply-rename.sh',
@@ -947,6 +957,7 @@
   't8012-blame-colors.sh',
   't8013-blame-ignore-revs.sh',
   't8014-blame-ignore-fuzzy.sh',
+  't8020-last-modified.sh',
   't9001-send-email.sh',
   't9002-column.sh',
   't9003-help-autocorrect.sh',
@@ -1027,6 +1038,8 @@
   't9302-fast-import-unpack-limit.sh',
   't9303-fast-import-compression.sh',
   't9304-fast-import-marks.sh',
+  't9305-fast-import-signatures.sh',
+  't9306-fast-import-signed-tags.sh',
   't9350-fast-export.sh',
   't9351-fast-export-anonymize.sh',
   't9400-git-cvsserver-server.sh',
@@ -1140,6 +1153,7 @@
   'perf/p7820-grep-engines.sh',
   'perf/p7821-grep-engines-fixed.sh',
   'perf/p7822-grep-perl-character.sh',
+  'perf/p8020-last-modified.sh',
   'perf/p9210-scalar.sh',
   'perf/p9300-fast-import-export.sh',
 ]
@@ -1215,4 +1229,4 @@
       timeout: 0,
     )
   endforeach
-endif
\ No newline at end of file
+endif
diff --git a/t/pack-refs-tests.sh b/t/pack-refs-tests.sh
new file mode 100644
index 0000000..81086c3
--- /dev/null
+++ b/t/pack-refs-tests.sh
@@ -0,0 +1,461 @@
+pack_refs=${pack_refs:-pack-refs}
+
+test_expect_success 'enable reflogs' '
+	git config core.logallrefupdates true
+'
+
+test_expect_success 'prepare a trivial repository' '
+	echo Hello > A &&
+	git update-index --add A &&
+	git commit -m "Initial commit." &&
+	HEAD=$(git rev-parse --verify HEAD)
+'
+
+test_expect_success '${pack_refs} --prune --all' '
+	test_path_is_missing .git/packed-refs &&
+	git ${pack_refs} --no-prune --all &&
+	test_path_is_file .git/packed-refs &&
+	N=$(find .git/refs -type f | wc -l) &&
+	test "$N" != 0 &&
+
+	git ${pack_refs} --prune --all &&
+	test_path_is_file .git/packed-refs &&
+	N=$(find .git/refs -type f) &&
+	test -z "$N"
+'
+
+SHA1=
+
+test_expect_success 'see if git show-ref works as expected' '
+	git branch a &&
+	SHA1=$(cat .git/refs/heads/a) &&
+	echo "$SHA1 refs/heads/a" >expect &&
+	git show-ref a >result &&
+	test_cmp expect result
+'
+
+test_expect_success 'see if a branch still exists when packed' '
+	git branch b &&
+	git ${pack_refs} --all &&
+	rm -f .git/refs/heads/b &&
+	echo "$SHA1 refs/heads/b" >expect &&
+	git show-ref b >result &&
+	test_cmp expect result
+'
+
+test_expect_success 'git branch c/d should barf if branch c exists' '
+	git branch c &&
+	git ${pack_refs} --all &&
+	rm -f .git/refs/heads/c &&
+	test_must_fail git branch c/d
+'
+
+test_expect_success 'see if a branch still exists after git ${pack_refs} --prune' '
+	git branch e &&
+	git ${pack_refs} --all --prune &&
+	echo "$SHA1 refs/heads/e" >expect &&
+	git show-ref e >result &&
+	test_cmp expect result
+'
+
+test_expect_success 'see if git ${pack_refs} --prune remove ref files' '
+	git branch f &&
+	git ${pack_refs} --all --prune &&
+	! test -f .git/refs/heads/f
+'
+
+test_expect_success 'see if git ${pack_refs} --prune removes empty dirs' '
+	git branch r/s/t &&
+	git ${pack_refs} --all --prune &&
+	! test -e .git/refs/heads/r
+'
+
+test_expect_success 'git branch g should work when git branch g/h has been deleted' '
+	git branch g/h &&
+	git ${pack_refs} --all --prune &&
+	git branch -d g/h &&
+	git branch g &&
+	git ${pack_refs} --all &&
+	git branch -d g
+'
+
+test_expect_success 'git branch i/j/k should barf if branch i exists' '
+	git branch i &&
+	git ${pack_refs} --all --prune &&
+	test_must_fail git branch i/j/k
+'
+
+test_expect_success 'test git branch k after branch k/l/m and k/lm have been deleted' '
+	git branch k/l &&
+	git branch k/lm &&
+	git branch -d k/l &&
+	git branch k/l/m &&
+	git branch -d k/l/m &&
+	git branch -d k/lm &&
+	git branch k
+'
+
+test_expect_success 'test git branch n after some branch deletion and pruning' '
+	git branch n/o &&
+	git branch n/op &&
+	git branch -d n/o &&
+	git branch n/o/p &&
+	git branch -d n/op &&
+	git ${pack_refs} --all --prune &&
+	git branch -d n/o/p &&
+	git branch n
+'
+
+test_expect_success 'test excluded refs are not packed' '
+	git branch dont_pack1 &&
+	git branch dont_pack2 &&
+	git branch pack_this &&
+	git ${pack_refs} --all --exclude "refs/heads/dont_pack*" &&
+	test -f .git/refs/heads/dont_pack1 &&
+	test -f .git/refs/heads/dont_pack2 &&
+	! test -f .git/refs/heads/pack_this'
+
+test_expect_success 'test --no-exclude refs clears excluded refs' '
+	git branch dont_pack3 &&
+	git branch dont_pack4 &&
+	git ${pack_refs} --all --exclude "refs/heads/dont_pack*" --no-exclude &&
+	! test -f .git/refs/heads/dont_pack3 &&
+	! test -f .git/refs/heads/dont_pack4'
+
+test_expect_success 'test only included refs are packed' '
+	git branch pack_this1 &&
+	git branch pack_this2 &&
+	git tag dont_pack5 &&
+	git ${pack_refs} --include "refs/heads/pack_this*" &&
+	test -f .git/refs/tags/dont_pack5 &&
+	! test -f .git/refs/heads/pack_this1 &&
+	! test -f .git/refs/heads/pack_this2'
+
+test_expect_success 'test --no-include refs clears included refs' '
+	git branch pack1 &&
+	git branch pack2 &&
+	git ${pack_refs} --include "refs/heads/pack*" --no-include &&
+	test -f .git/refs/heads/pack1 &&
+	test -f .git/refs/heads/pack2'
+
+test_expect_success 'test --exclude takes precedence over --include' '
+	git branch dont_pack5 &&
+	git ${pack_refs} --include "refs/heads/pack*" --exclude "refs/heads/pack*" &&
+	test -f .git/refs/heads/dont_pack5'
+
+test_expect_success 'see if up-to-date packed refs are preserved' '
+	git branch q &&
+	git ${pack_refs} --all --prune &&
+	git update-ref refs/heads/q refs/heads/q &&
+	! test -f .git/refs/heads/q
+'
+
+test_expect_success 'pack, prune and repack' '
+	git tag foo &&
+	git ${pack_refs} --all --prune &&
+	git show-ref >all-of-them &&
+	git ${pack_refs} &&
+	git show-ref >again &&
+	test_cmp all-of-them again
+'
+
+test_expect_success 'explicit ${pack_refs} with dangling packed reference' '
+	git commit --allow-empty -m "soon to be garbage-collected" &&
+	git ${pack_refs} --all &&
+	git reset --hard HEAD^ &&
+	git reflog expire --expire=all --all &&
+	git prune --expire=all &&
+	git ${pack_refs} --all 2>result &&
+	test_must_be_empty result
+'
+
+test_expect_success 'delete ref with dangling packed version' '
+	git checkout -b lamb &&
+	git commit --allow-empty -m "future garbage" &&
+	git ${pack_refs} --all &&
+	git reset --hard HEAD^ &&
+	git checkout main &&
+	git reflog expire --expire=all --all &&
+	git prune --expire=all &&
+	git branch -d lamb 2>result &&
+	test_must_be_empty result
+'
+
+test_expect_success 'delete ref while another dangling packed ref' '
+	git branch lamb &&
+	git commit --allow-empty -m "future garbage" &&
+	git ${pack_refs} --all &&
+	git reset --hard HEAD^ &&
+	git reflog expire --expire=all --all &&
+	git prune --expire=all &&
+	git branch -d lamb 2>result &&
+	test_must_be_empty result
+'
+
+test_expect_success 'pack ref directly below refs/' '
+	git update-ref refs/top HEAD &&
+	git ${pack_refs} --all --prune &&
+	grep refs/top .git/packed-refs &&
+	test_path_is_missing .git/refs/top
+'
+
+test_expect_success 'do not pack ref in refs/bisect' '
+	git update-ref refs/bisect/local HEAD &&
+	git ${pack_refs} --all --prune &&
+	! grep refs/bisect/local .git/packed-refs >/dev/null &&
+	test_path_is_file .git/refs/bisect/local
+'
+
+test_expect_success 'disable reflogs' '
+	git config core.logallrefupdates false &&
+	rm -rf .git/logs
+'
+
+test_expect_success 'create packed foo/bar/baz branch' '
+	git branch foo/bar/baz &&
+	git ${pack_refs} --all --prune &&
+	test_path_is_missing .git/refs/heads/foo/bar/baz &&
+	test_must_fail git reflog exists refs/heads/foo/bar/baz
+'
+
+test_expect_success 'notice d/f conflict with existing directory' '
+	test_must_fail git branch foo &&
+	test_must_fail git branch foo/bar
+'
+
+test_expect_success 'existing directory reports concrete ref' '
+	test_must_fail git branch foo 2>stderr &&
+	test_grep refs/heads/foo/bar/baz stderr
+'
+
+test_expect_success 'notice d/f conflict with existing ref' '
+	test_must_fail git branch foo/bar/baz/extra &&
+	test_must_fail git branch foo/bar/baz/lots/of/extra/components
+'
+
+test_expect_success 'reject packed-refs with unterminated line' '
+	cp .git/packed-refs .git/packed-refs.bak &&
+	test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
+	printf "%s" "$HEAD refs/zzzzz" >>.git/packed-refs &&
+	echo "fatal: unterminated line in .git/packed-refs: $HEAD refs/zzzzz" >expected_err &&
+	test_must_fail git for-each-ref >out 2>err &&
+	test_cmp expected_err err
+'
+
+test_expect_success 'reject packed-refs containing junk' '
+	cp .git/packed-refs .git/packed-refs.bak &&
+	test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
+	printf "%s\n" "bogus content" >>.git/packed-refs &&
+	echo "fatal: unexpected line in .git/packed-refs: bogus content" >expected_err &&
+	test_must_fail git for-each-ref >out 2>err &&
+	test_cmp expected_err err
+'
+
+test_expect_success 'reject packed-refs with a short SHA-1' '
+	cp .git/packed-refs .git/packed-refs.bak &&
+	test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
+	printf "%.7s %s\n" $HEAD refs/zzzzz >>.git/packed-refs &&
+	printf "fatal: unexpected line in .git/packed-refs: %.7s %s\n" $HEAD refs/zzzzz >expected_err &&
+	test_must_fail git for-each-ref >out 2>err &&
+	test_cmp expected_err err
+'
+
+test_expect_success 'timeout if packed-refs.lock exists' '
+	LOCK=.git/packed-refs.lock &&
+	>"$LOCK" &&
+	test_when_finished "rm -f $LOCK" &&
+	test_must_fail git ${pack_refs} --all --prune
+'
+
+test_expect_success 'retry acquiring packed-refs.lock' '
+	LOCK=.git/packed-refs.lock &&
+	>"$LOCK" &&
+	test_when_finished "wait && rm -f $LOCK" &&
+	{
+		( sleep 1 && rm -f $LOCK ) &
+	} &&
+	git -c core.packedrefstimeout=3000 ${pack_refs} --all --prune
+'
+
+test_expect_success SYMLINKS 'pack symlinked packed-refs' '
+	# First make sure that symlinking works when reading:
+	git update-ref refs/heads/lossy refs/heads/main &&
+	git for-each-ref >all-refs-before &&
+	mv .git/packed-refs .git/my-deviant-packed-refs &&
+	ln -s my-deviant-packed-refs .git/packed-refs &&
+	git for-each-ref >all-refs-linked &&
+	test_cmp all-refs-before all-refs-linked &&
+	git ${pack_refs} --all --prune &&
+	git for-each-ref >all-refs-packed &&
+	test_cmp all-refs-before all-refs-packed &&
+	test -h .git/packed-refs &&
+	test "$(test_readlink .git/packed-refs)" = "my-deviant-packed-refs"
+'
+
+# The 'packed-refs' file is stored directly in .git/. This means it is global
+# to the repository, and can only contain refs that are shared across all
+# worktrees.
+test_expect_success 'refs/worktree must not be packed' '
+	test_commit initial &&
+	test_commit wt1 &&
+	test_commit wt2 &&
+	git worktree add wt1 wt1 &&
+	git worktree add wt2 wt2 &&
+	git checkout initial &&
+	git update-ref refs/worktree/foo HEAD &&
+	git -C wt1 update-ref refs/worktree/foo HEAD &&
+	git -C wt2 update-ref refs/worktree/foo HEAD &&
+	git ${pack_refs} --all &&
+	test_path_is_missing .git/refs/tags/wt1 &&
+	test_path_is_file .git/refs/worktree/foo &&
+	test_path_is_file .git/worktrees/wt1/refs/worktree/foo &&
+	test_path_is_file .git/worktrees/wt2/refs/worktree/foo
+'
+
+# we do not want to count on running ${pack_refs} to
+# actually pack it, as it is perfectly reasonable to
+# skip processing a broken ref
+test_expect_success 'create packed-refs file with broken ref' '
+	test_tick && git commit --allow-empty -m one &&
+	recoverable=$(git rev-parse HEAD) &&
+	test_tick && git commit --allow-empty -m two &&
+	missing=$(git rev-parse HEAD) &&
+	rm -f .git/refs/heads/main &&
+	cat >.git/packed-refs <<-EOF &&
+	$missing refs/heads/main
+	$recoverable refs/heads/other
+	EOF
+	echo $missing >expect &&
+	git rev-parse refs/heads/main >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '${pack_refs} does not silently delete broken packed ref' '
+	git ${pack_refs} --all --prune &&
+	git rev-parse refs/heads/main >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '${pack_refs} does not drop broken refs during deletion' '
+	git update-ref -d refs/heads/other &&
+	git rev-parse refs/heads/main >actual &&
+	test_cmp expect actual
+'
+
+for command in "git ${pack_refs} --all --auto" "git maintenance run --task=${pack_refs} --auto"
+do
+	test_expect_success "$command does not repack below 16 refs without packed-refs" '
+		test_when_finished "rm -rf repo" &&
+		git init repo &&
+		(
+			cd repo &&
+			git config set maintenance.auto false &&
+			git commit --allow-empty --message "initial" &&
+
+			# Create 14 additional references, which brings us to
+			# 15 together with the default branch.
+			printf "create refs/heads/loose-%d HEAD\n" $(test_seq 14) >stdin &&
+			git update-ref --stdin <stdin &&
+			test_path_is_missing .git/packed-refs &&
+			git ${pack_refs} --auto --all &&
+			test_path_is_missing .git/packed-refs &&
+
+			# Create the 16th reference, which should cause us to repack.
+			git update-ref refs/heads/loose-15 HEAD &&
+			git ${pack_refs} --auto --all &&
+			test_path_is_file .git/packed-refs
+		)
+	'
+
+	test_expect_success "$command does not repack below 16 refs with small packed-refs" '
+		test_when_finished "rm -rf repo" &&
+		git init repo &&
+		(
+			cd repo &&
+			git config set maintenance.auto false &&
+			git commit --allow-empty --message "initial" &&
+
+			git ${pack_refs} --all &&
+			test_line_count = 2 .git/packed-refs &&
+
+			# Create 15 loose references.
+			printf "create refs/heads/loose-%d HEAD\n" $(test_seq 15) >stdin &&
+			git update-ref --stdin <stdin &&
+			git ${pack_refs} --auto --all &&
+			test_line_count = 2 .git/packed-refs &&
+
+			# Create the 16th loose reference, which should cause us to repack.
+			git update-ref refs/heads/loose-17 HEAD &&
+			git ${pack_refs} --auto --all &&
+			test_line_count = 18 .git/packed-refs
+		)
+	'
+
+	test_expect_success "$command scales with size of packed-refs" '
+		test_when_finished "rm -rf repo" &&
+		git init repo &&
+		(
+			cd repo &&
+			git config set maintenance.auto false &&
+			git commit --allow-empty --message "initial" &&
+
+			# Create 99 packed refs. This should cause the heuristic
+			# to require more than the minimum amount of loose refs.
+			test_seq 99 |
+			while read i
+			do
+				printf "create refs/heads/packed-%d HEAD\n" $i || return 1
+			done >stdin &&
+			git update-ref --stdin <stdin &&
+			git ${pack_refs} --all &&
+			test_line_count = 101 .git/packed-refs &&
+
+			# Create 24 loose refs, which should not yet cause us to repack.
+			printf "create refs/heads/loose-%d HEAD\n" $(test_seq 24) >stdin &&
+			git update-ref --stdin <stdin &&
+			git ${pack_refs} --auto --all &&
+			test_line_count = 101 .git/packed-refs &&
+
+			# Create another handful of refs to cross the border.
+			# Note that we explicitly do not check for strict
+			# boundaries here, as this also depends on the size of
+			# the object hash.
+			printf "create refs/heads/addn-%d HEAD\n" $(test_seq 10) >stdin &&
+			git update-ref --stdin <stdin &&
+			git ${pack_refs} --auto --all &&
+			test_line_count = 135 .git/packed-refs
+		)
+	'
+done
+
+test_expect_success 'pack-refs does not store invalid peeled tag value' '
+	test_when_finished rm -rf repo &&
+	git init repo &&
+	(
+		cd repo &&
+		git commit --allow-empty --message initial &&
+
+		echo garbage >blob-content &&
+		blob_id=$(git hash-object -w -t blob blob-content) &&
+
+		# Write an invalid tag into the object database. The tag itself
+		# is well-formed, but the tagged object is a blob while we
+		# claim that it is a commit.
+		cat >tag-content <<-EOF &&
+		object $blob_id
+		type commit
+		tag bad-tag
+		tagger C O Mitter <committer@example.com> 1112354055 +0200
+
+		annotated
+		EOF
+		tag_id=$(git hash-object -w -t tag tag-content) &&
+		git update-ref refs/tags/bad-tag "$tag_id" &&
+
+		# The packed-refs file should not contain the peeled object ID.
+		# If it did this would cause commands that use the peeled value
+		# to not notice this corrupted tag.
+		git pack-refs --all &&
+		test_grep ! "^\^" .git/packed-refs
+	)
+'
diff --git a/t/perf/p6010-merge-base.sh b/t/perf/p6010-merge-base.sh
new file mode 100755
index 0000000..54f52fa
--- /dev/null
+++ b/t/perf/p6010-merge-base.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+test_description='Test git merge-base'
+
+. ./perf-lib.sh
+
+test_perf_fresh_repo
+
+#
+# Creates lots of merges to make history traversal costly.  In
+# particular it creates 2^($max_level-1)-1 2-way merges on top of
+# 2^($max_level-1) root commits.  E.g., the commit history looks like
+# this for a $max_level of 3:
+#
+#     _1_
+#    /   \
+#   2     3
+#  / \   / \
+# 4   5 6   7
+#
+# The numbers are the fast-import marks, which also are the commit
+# messages.  1 is the HEAD commit and a merge, 2 and 3 are also merges,
+# 4-7 are the root commits.
+#
+build_history () {
+	local max_level="$1" &&
+	local level="${2:-1}" &&
+	local mark="${3:-1}" &&
+	if test $level -eq $max_level
+	then
+		echo "reset refs/heads/master" &&
+		echo "from $ZERO_OID" &&
+		echo "commit refs/heads/master" &&
+		echo "mark :$mark" &&
+		echo "committer C <c@example.com> 1234567890 +0000" &&
+		echo "data <<EOF" &&
+		echo "$mark" &&
+		echo "EOF"
+	else
+		local level1=$((level+1)) &&
+		local mark1=$((2*mark)) &&
+		local mark2=$((2*mark+1)) &&
+		build_history $max_level $level1 $mark1 &&
+		build_history $max_level $level1 $mark2 &&
+		echo "commit refs/heads/master" &&
+		echo "mark :$mark" &&
+		echo "committer C <c@example.com> 1234567890 +0000" &&
+		echo "data <<EOF" &&
+		echo "$mark" &&
+		echo "EOF" &&
+		echo "from :$mark1" &&
+		echo "merge :$mark2"
+	fi
+}
+
+#
+# Creates a new merge history in the same shape as build_history does,
+# while reusing the same root commits.  This way the two top commits
+# have 2^($max_level-1) merge bases between them.
+#
+build_history2 () {
+	local max_level="$1" &&
+	local level="${2:-1}" &&
+	local mark="${3:-1}" &&
+	if test $level -lt $max_level
+	then
+		local level1=$((level+1)) &&
+		local mark1=$((2*mark)) &&
+		local mark2=$((2*mark+1)) &&
+		build_history2 $max_level $level1 $mark1 &&
+		build_history2 $max_level $level1 $mark2 &&
+		echo "commit refs/heads/master" &&
+		echo "mark :$mark" &&
+		echo "committer C <c@example.com> 1234567890 +0000" &&
+		echo "data <<EOF" &&
+		echo "$mark II" &&
+		echo "EOF" &&
+		echo "from :$mark1" &&
+		echo "merge :$mark2"
+	fi
+}
+
+test_expect_success 'setup' '
+	max_level=15 &&
+	build_history $max_level | git fast-import --export-marks=marks &&
+	git tag one &&
+	build_history2 $max_level | git fast-import --import-marks=marks --force &&
+	git tag two &&
+	git gc &&
+	git log --format=%H --no-merges >expect
+'
+
+test_perf 'git merge-base' '
+	git merge-base --all one two >actual
+'
+
+test_expect_success 'verify result' '
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/perf/p8020-last-modified.sh b/t/perf/p8020-last-modified.sh
new file mode 100755
index 0000000..cb1f98d
--- /dev/null
+++ b/t/perf/p8020-last-modified.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='last-modified perf tests'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_perf 'top-level last-modified' '
+	git last-modified HEAD
+'
+
+test_perf 'top-level recursive last-modified' '
+	git last-modified -r HEAD
+'
+
+test_perf 'subdir last-modified' '
+	git ls-tree -d HEAD >subtrees &&
+	path="$(head -n 1 subtrees | cut -f2)" &&
+	git last-modified -r HEAD -- "$path"
+'
+
+test_done
diff --git a/t/show-ref-exists-tests.sh b/t/show-ref-exists-tests.sh
new file mode 100644
index 0000000..36e8e9d
--- /dev/null
+++ b/t/show-ref-exists-tests.sh
@@ -0,0 +1,77 @@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
+
+test_expect_success setup '
+	test_commit --annotate A &&
+	git checkout -b side &&
+	test_commit --annotate B &&
+	git checkout main &&
+	test_commit C &&
+	git branch B A^0
+'
+
+test_expect_success '--exists with existing reference' '
+	${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+	test_expect_code 2 ${git_show_ref_exists} refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+	test_expect_code 2 ${git_show_ref_exists} $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+	grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+	${git_show_ref_exists} HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+	test_when_finished "git update-ref -d refs/heads/bad...name" &&
+	new_oid=$(git rev-parse HEAD) &&
+	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+	test_when_finished "git symbolic-ref -d refs/symref" &&
+	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+	${git_show_ref_exists} refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+	${git_show_ref_exists} refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+	tree_oid=$(git rev-parse HEAD^{tree}) &&
+	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+	cat >expect <<-EOF &&
+	error: reference does not exist
+	EOF
+	test_expect_code 2 ${git_show_ref_exists} refs/heads 2>err &&
+	test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+	test_expect_code 2 ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+	test_when_finished "rm .git/FETCH_HEAD" &&
+	git rev-parse HEAD >.git/FETCH_HEAD &&
+	${git_show_ref_exists} FETCH_HEAD
+'
+
+test_done
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index f593c53..618da08 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -883,6 +883,22 @@
 	test_grep ! "hint: " err
 '
 
+test_expect_success 'default branch name' '
+	if test_have_prereq WITH_BREAKING_CHANGES
+	then
+		expect=main
+	else
+		expect=master
+	fi &&
+	echo "refs/heads/$expect" >expect &&
+	(
+		sane_unset GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+		git init default-initial-branch-name
+	) &&
+	git -C default-initial-branch-name symbolic-ref HEAD >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'overridden default main branch name (env)' '
 	test_config_global init.defaultBranch nmb &&
 	GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=env git init main-branch-env &&
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 3c98b62..582e207 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -664,4 +664,24 @@
 	test_cmp expect err
 '
 
+test_expect_success ULIMIT_STACK_SIZE 'deep macro recursion' '
+	n=3000 &&
+	{
+		i=0 &&
+		while test $i -lt $n; do
+			echo "[attr]a$i a$((i+1))" &&
+			i=$((i+1)) ||
+			return 1
+		done &&
+		echo "[attr]a$n -text" &&
+		echo "file a0"
+	} >.gitattributes &&
+	{
+		echo "file: text: unset" &&
+		test_seq -f "file: a%d: set" 0 $n
+	} >expect &&
+	run_with_limited_stack git check-attr -a file >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index 273d714..db8bde2 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -847,6 +847,17 @@
 	test_cmp expect actual
 '
 
+test_expect_success '** not confused by matching leading prefix' '
+	cat >.gitignore <<-\EOF &&
+	foo**/bar
+	EOF
+	git check-ignore foobar foo/bar >actual &&
+	cat >expect <<-\EOF &&
+	foo/bar
+	EOF
+	test_cmp expect actual
+'
+
 ############################################################################
 #
 # test whitespace handling
diff --git a/t/t0450-txt-doc-vs-help.sh b/t/t0450-txt-doc-vs-help.sh
index 2f7504a..e12e18f 100755
--- a/t/t0450-txt-doc-vs-help.sh
+++ b/t/t0450-txt-doc-vs-help.sh
@@ -41,7 +41,7 @@
 }
 
 builtin_to_adoc () {
-       echo "$GIT_BUILD_DIR/Documentation/git-$1.adoc"
+       echo "$GIT_SOURCE_DIR/Documentation/git-$1.adoc"
 }
 
 adoc_to_synopsis () {
@@ -112,10 +112,19 @@
 	adoc="$(builtin_to_adoc "$builtin")" &&
 	preq="$(echo BUILTIN_ADOC_$builtin | tr '[:lower:]-' '[:upper:]_')" &&
 
-	if test -f "$adoc"
+	# If and only if *.adoc is missing, builtin shall be listed in t0450/adoc-missing.
+	if grep -q "^$builtin$" "$TEST_DIRECTORY"/t0450/adoc-missing
 	then
+		test_expect_success "$builtin appropriately marked as not having .adoc" '
+			! test -f "$adoc"
+		'
+	else
 		test_set_prereq "$preq"
-	fi &&
+
+		test_expect_success "$builtin appropriately marked as having .adoc" '
+			test -f "$adoc"
+		'
+	fi
 
 	# *.adoc output assertions
 	test_expect_success "$preq" "$builtin *.adoc SYNOPSIS has dashed labels" '
diff --git a/t/t0450/adoc-help-mismatches b/t/t0450/adoc-help-mismatches
index 06b469b..8ee2d3f 100644
--- a/t/t0450/adoc-help-mismatches
+++ b/t/t0450/adoc-help-mismatches
@@ -2,7 +2,6 @@
 am
 apply
 archive
-bisect
 blame
 branch
 check-ref-format
@@ -17,7 +16,6 @@
 fast-import
 fetch-pack
 fmt-merge-msg
-for-each-ref
 format-patch
 fsck-objects
 fsmonitor--daemon
diff --git a/t/t0450/adoc-missing b/t/t0450/adoc-missing
new file mode 100644
index 0000000..1ec9f8d
--- /dev/null
+++ b/t/t0450/adoc-missing
@@ -0,0 +1,9 @@
+checkout--worker
+merge-ours
+merge-recursive
+merge-recursive-ours
+merge-recursive-theirs
+merge-subtree
+pickaxe
+submodule--helper
+upload-archive--writer
diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh
index 1e62c79..b11126e 100755
--- a/t/t0600-reffiles-backend.sh
+++ b/t/t0600-reffiles-backend.sh
@@ -477,9 +477,29 @@
 	prepare
 	commit
 	EOF
-	git update-ref --no-deref --stdin <stdin &&
-	test_path_is_symlink .git/TEST_SYMREF_HEAD &&
-	test "$(test_readlink .git/TEST_SYMREF_HEAD)" = refs/heads/new
+	git update-ref --no-deref --stdin <stdin 2>err &&
+	if test_have_prereq WITH_BREAKING_CHANGES
+	then
+		test_path_is_file .git/TEST_SYMREF_HEAD &&
+		echo "ref: refs/heads/new" >expect &&
+		test_cmp expect .git/TEST_SYMREF_HEAD &&
+		test_must_be_empty err
+	else
+		test_path_is_symlink .git/TEST_SYMREF_HEAD &&
+		test "$(test_readlink .git/TEST_SYMREF_HEAD)" = refs/heads/new &&
+		cat >expect <<-EOF &&
+		warning: ${SQ}core.preferSymlinkRefs=true${SQ} is nominated for removal.
+		hint: The use of symbolic links for symbolic refs is deprecated
+		hint: and will be removed in Git 3.0. The configuration that
+		hint: tells Git to use them is thus going away. You can unset
+		hint: it with:
+		hint:
+		hint:	git config unset core.preferSymlinkRefs
+		hint:
+		hint: Git will then use the textual symref format instead.
+		EOF
+		test_cmp expect err
+	fi
 '
 
 test_expect_success 'symref transaction supports false symlink config' '
diff --git a/t/t0601-reffiles-pack-refs.sh b/t/t0601-reffiles-pack-refs.sh
index aa7f6ec..3c70697 100755
--- a/t/t0601-reffiles-pack-refs.sh
+++ b/t/t0601-reffiles-pack-refs.sh
@@ -17,432 +17,6 @@
 
 . ./test-lib.sh
 
-test_expect_success 'enable reflogs' '
-	git config core.logallrefupdates true
-'
-
-test_expect_success 'prepare a trivial repository' '
-	echo Hello > A &&
-	git update-index --add A &&
-	git commit -m "Initial commit." &&
-	HEAD=$(git rev-parse --verify HEAD)
-'
-
-test_expect_success 'pack-refs --prune --all' '
-	test_path_is_missing .git/packed-refs &&
-	git pack-refs --no-prune --all &&
-	test_path_is_file .git/packed-refs &&
-	N=$(find .git/refs -type f | wc -l) &&
-	test "$N" != 0 &&
-
-	git pack-refs --prune --all &&
-	test_path_is_file .git/packed-refs &&
-	N=$(find .git/refs -type f) &&
-	test -z "$N"
-'
-
-SHA1=
-
-test_expect_success 'see if git show-ref works as expected' '
-	git branch a &&
-	SHA1=$(cat .git/refs/heads/a) &&
-	echo "$SHA1 refs/heads/a" >expect &&
-	git show-ref a >result &&
-	test_cmp expect result
-'
-
-test_expect_success 'see if a branch still exists when packed' '
-	git branch b &&
-	git pack-refs --all &&
-	rm -f .git/refs/heads/b &&
-	echo "$SHA1 refs/heads/b" >expect &&
-	git show-ref b >result &&
-	test_cmp expect result
-'
-
-test_expect_success 'git branch c/d should barf if branch c exists' '
-	git branch c &&
-	git pack-refs --all &&
-	rm -f .git/refs/heads/c &&
-	test_must_fail git branch c/d
-'
-
-test_expect_success 'see if a branch still exists after git pack-refs --prune' '
-	git branch e &&
-	git pack-refs --all --prune &&
-	echo "$SHA1 refs/heads/e" >expect &&
-	git show-ref e >result &&
-	test_cmp expect result
-'
-
-test_expect_success 'see if git pack-refs --prune remove ref files' '
-	git branch f &&
-	git pack-refs --all --prune &&
-	! test -f .git/refs/heads/f
-'
-
-test_expect_success 'see if git pack-refs --prune removes empty dirs' '
-	git branch r/s/t &&
-	git pack-refs --all --prune &&
-	! test -e .git/refs/heads/r
-'
-
-test_expect_success 'git branch g should work when git branch g/h has been deleted' '
-	git branch g/h &&
-	git pack-refs --all --prune &&
-	git branch -d g/h &&
-	git branch g &&
-	git pack-refs --all &&
-	git branch -d g
-'
-
-test_expect_success 'git branch i/j/k should barf if branch i exists' '
-	git branch i &&
-	git pack-refs --all --prune &&
-	test_must_fail git branch i/j/k
-'
-
-test_expect_success 'test git branch k after branch k/l/m and k/lm have been deleted' '
-	git branch k/l &&
-	git branch k/lm &&
-	git branch -d k/l &&
-	git branch k/l/m &&
-	git branch -d k/l/m &&
-	git branch -d k/lm &&
-	git branch k
-'
-
-test_expect_success 'test git branch n after some branch deletion and pruning' '
-	git branch n/o &&
-	git branch n/op &&
-	git branch -d n/o &&
-	git branch n/o/p &&
-	git branch -d n/op &&
-	git pack-refs --all --prune &&
-	git branch -d n/o/p &&
-	git branch n
-'
-
-test_expect_success 'test excluded refs are not packed' '
-	git branch dont_pack1 &&
-	git branch dont_pack2 &&
-	git branch pack_this &&
-	git pack-refs --all --exclude "refs/heads/dont_pack*" &&
-	test -f .git/refs/heads/dont_pack1 &&
-	test -f .git/refs/heads/dont_pack2 &&
-	! test -f .git/refs/heads/pack_this'
-
-test_expect_success 'test --no-exclude refs clears excluded refs' '
-	git branch dont_pack3 &&
-	git branch dont_pack4 &&
-	git pack-refs --all --exclude "refs/heads/dont_pack*" --no-exclude &&
-	! test -f .git/refs/heads/dont_pack3 &&
-	! test -f .git/refs/heads/dont_pack4'
-
-test_expect_success 'test only included refs are packed' '
-	git branch pack_this1 &&
-	git branch pack_this2 &&
-	git tag dont_pack5 &&
-	git pack-refs --include "refs/heads/pack_this*" &&
-	test -f .git/refs/tags/dont_pack5 &&
-	! test -f .git/refs/heads/pack_this1 &&
-	! test -f .git/refs/heads/pack_this2'
-
-test_expect_success 'test --no-include refs clears included refs' '
-	git branch pack1 &&
-	git branch pack2 &&
-	git pack-refs --include "refs/heads/pack*" --no-include &&
-	test -f .git/refs/heads/pack1 &&
-	test -f .git/refs/heads/pack2'
-
-test_expect_success 'test --exclude takes precedence over --include' '
-	git branch dont_pack5 &&
-	git pack-refs --include "refs/heads/pack*" --exclude "refs/heads/pack*" &&
-	test -f .git/refs/heads/dont_pack5'
-
-test_expect_success 'see if up-to-date packed refs are preserved' '
-	git branch q &&
-	git pack-refs --all --prune &&
-	git update-ref refs/heads/q refs/heads/q &&
-	! test -f .git/refs/heads/q
-'
-
-test_expect_success 'pack, prune and repack' '
-	git tag foo &&
-	git pack-refs --all --prune &&
-	git show-ref >all-of-them &&
-	git pack-refs &&
-	git show-ref >again &&
-	test_cmp all-of-them again
-'
-
-test_expect_success 'explicit pack-refs with dangling packed reference' '
-	git commit --allow-empty -m "soon to be garbage-collected" &&
-	git pack-refs --all &&
-	git reset --hard HEAD^ &&
-	git reflog expire --expire=all --all &&
-	git prune --expire=all &&
-	git pack-refs --all 2>result &&
-	test_must_be_empty result
-'
-
-test_expect_success 'delete ref with dangling packed version' '
-	git checkout -b lamb &&
-	git commit --allow-empty -m "future garbage" &&
-	git pack-refs --all &&
-	git reset --hard HEAD^ &&
-	git checkout main &&
-	git reflog expire --expire=all --all &&
-	git prune --expire=all &&
-	git branch -d lamb 2>result &&
-	test_must_be_empty result
-'
-
-test_expect_success 'delete ref while another dangling packed ref' '
-	git branch lamb &&
-	git commit --allow-empty -m "future garbage" &&
-	git pack-refs --all &&
-	git reset --hard HEAD^ &&
-	git reflog expire --expire=all --all &&
-	git prune --expire=all &&
-	git branch -d lamb 2>result &&
-	test_must_be_empty result
-'
-
-test_expect_success 'pack ref directly below refs/' '
-	git update-ref refs/top HEAD &&
-	git pack-refs --all --prune &&
-	grep refs/top .git/packed-refs &&
-	test_path_is_missing .git/refs/top
-'
-
-test_expect_success 'do not pack ref in refs/bisect' '
-	git update-ref refs/bisect/local HEAD &&
-	git pack-refs --all --prune &&
-	! grep refs/bisect/local .git/packed-refs >/dev/null &&
-	test_path_is_file .git/refs/bisect/local
-'
-
-test_expect_success 'disable reflogs' '
-	git config core.logallrefupdates false &&
-	rm -rf .git/logs
-'
-
-test_expect_success 'create packed foo/bar/baz branch' '
-	git branch foo/bar/baz &&
-	git pack-refs --all --prune &&
-	test_path_is_missing .git/refs/heads/foo/bar/baz &&
-	test_must_fail git reflog exists refs/heads/foo/bar/baz
-'
-
-test_expect_success 'notice d/f conflict with existing directory' '
-	test_must_fail git branch foo &&
-	test_must_fail git branch foo/bar
-'
-
-test_expect_success 'existing directory reports concrete ref' '
-	test_must_fail git branch foo 2>stderr &&
-	test_grep refs/heads/foo/bar/baz stderr
-'
-
-test_expect_success 'notice d/f conflict with existing ref' '
-	test_must_fail git branch foo/bar/baz/extra &&
-	test_must_fail git branch foo/bar/baz/lots/of/extra/components
-'
-
-test_expect_success 'reject packed-refs with unterminated line' '
-	cp .git/packed-refs .git/packed-refs.bak &&
-	test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
-	printf "%s" "$HEAD refs/zzzzz" >>.git/packed-refs &&
-	echo "fatal: unterminated line in .git/packed-refs: $HEAD refs/zzzzz" >expected_err &&
-	test_must_fail git for-each-ref >out 2>err &&
-	test_cmp expected_err err
-'
-
-test_expect_success 'reject packed-refs containing junk' '
-	cp .git/packed-refs .git/packed-refs.bak &&
-	test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
-	printf "%s\n" "bogus content" >>.git/packed-refs &&
-	echo "fatal: unexpected line in .git/packed-refs: bogus content" >expected_err &&
-	test_must_fail git for-each-ref >out 2>err &&
-	test_cmp expected_err err
-'
-
-test_expect_success 'reject packed-refs with a short SHA-1' '
-	cp .git/packed-refs .git/packed-refs.bak &&
-	test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
-	printf "%.7s %s\n" $HEAD refs/zzzzz >>.git/packed-refs &&
-	printf "fatal: unexpected line in .git/packed-refs: %.7s %s\n" $HEAD refs/zzzzz >expected_err &&
-	test_must_fail git for-each-ref >out 2>err &&
-	test_cmp expected_err err
-'
-
-test_expect_success 'timeout if packed-refs.lock exists' '
-	LOCK=.git/packed-refs.lock &&
-	>"$LOCK" &&
-	test_when_finished "rm -f $LOCK" &&
-	test_must_fail git pack-refs --all --prune
-'
-
-test_expect_success 'retry acquiring packed-refs.lock' '
-	LOCK=.git/packed-refs.lock &&
-	>"$LOCK" &&
-	test_when_finished "wait && rm -f $LOCK" &&
-	{
-		( sleep 1 && rm -f $LOCK ) &
-	} &&
-	git -c core.packedrefstimeout=3000 pack-refs --all --prune
-'
-
-test_expect_success SYMLINKS 'pack symlinked packed-refs' '
-	# First make sure that symlinking works when reading:
-	git update-ref refs/heads/lossy refs/heads/main &&
-	git for-each-ref >all-refs-before &&
-	mv .git/packed-refs .git/my-deviant-packed-refs &&
-	ln -s my-deviant-packed-refs .git/packed-refs &&
-	git for-each-ref >all-refs-linked &&
-	test_cmp all-refs-before all-refs-linked &&
-	git pack-refs --all --prune &&
-	git for-each-ref >all-refs-packed &&
-	test_cmp all-refs-before all-refs-packed &&
-	test -h .git/packed-refs &&
-	test "$(test_readlink .git/packed-refs)" = "my-deviant-packed-refs"
-'
-
-# The 'packed-refs' file is stored directly in .git/. This means it is global
-# to the repository, and can only contain refs that are shared across all
-# worktrees.
-test_expect_success 'refs/worktree must not be packed' '
-	test_commit initial &&
-	test_commit wt1 &&
-	test_commit wt2 &&
-	git worktree add wt1 wt1 &&
-	git worktree add wt2 wt2 &&
-	git checkout initial &&
-	git update-ref refs/worktree/foo HEAD &&
-	git -C wt1 update-ref refs/worktree/foo HEAD &&
-	git -C wt2 update-ref refs/worktree/foo HEAD &&
-	git pack-refs --all &&
-	test_path_is_missing .git/refs/tags/wt1 &&
-	test_path_is_file .git/refs/worktree/foo &&
-	test_path_is_file .git/worktrees/wt1/refs/worktree/foo &&
-	test_path_is_file .git/worktrees/wt2/refs/worktree/foo
-'
-
-# we do not want to count on running pack-refs to
-# actually pack it, as it is perfectly reasonable to
-# skip processing a broken ref
-test_expect_success 'create packed-refs file with broken ref' '
-	test_tick && git commit --allow-empty -m one &&
-	recoverable=$(git rev-parse HEAD) &&
-	test_tick && git commit --allow-empty -m two &&
-	missing=$(git rev-parse HEAD) &&
-	rm -f .git/refs/heads/main &&
-	cat >.git/packed-refs <<-EOF &&
-	$missing refs/heads/main
-	$recoverable refs/heads/other
-	EOF
-	echo $missing >expect &&
-	git rev-parse refs/heads/main >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success 'pack-refs does not silently delete broken packed ref' '
-	git pack-refs --all --prune &&
-	git rev-parse refs/heads/main >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success 'pack-refs does not drop broken refs during deletion' '
-	git update-ref -d refs/heads/other &&
-	git rev-parse refs/heads/main >actual &&
-	test_cmp expect actual
-'
-
-for command in "git pack-refs --all --auto" "git maintenance run --task=pack-refs --auto"
-do
-	test_expect_success "$command does not repack below 16 refs without packed-refs" '
-		test_when_finished "rm -rf repo" &&
-		git init repo &&
-		(
-			cd repo &&
-			git config set maintenance.auto false &&
-			git commit --allow-empty --message "initial" &&
-
-			# Create 14 additional references, which brings us to
-			# 15 together with the default branch.
-			printf "create refs/heads/loose-%d HEAD\n" $(test_seq 14) >stdin &&
-			git update-ref --stdin <stdin &&
-			test_path_is_missing .git/packed-refs &&
-			git pack-refs --auto --all &&
-			test_path_is_missing .git/packed-refs &&
-
-			# Create the 16th reference, which should cause us to repack.
-			git update-ref refs/heads/loose-15 HEAD &&
-			git pack-refs --auto --all &&
-			test_path_is_file .git/packed-refs
-		)
-	'
-
-	test_expect_success "$command does not repack below 16 refs with small packed-refs" '
-		test_when_finished "rm -rf repo" &&
-		git init repo &&
-		(
-			cd repo &&
-			git config set maintenance.auto false &&
-			git commit --allow-empty --message "initial" &&
-
-			git pack-refs --all &&
-			test_line_count = 2 .git/packed-refs &&
-
-			# Create 15 loose references.
-			printf "create refs/heads/loose-%d HEAD\n" $(test_seq 15) >stdin &&
-			git update-ref --stdin <stdin &&
-			git pack-refs --auto --all &&
-			test_line_count = 2 .git/packed-refs &&
-
-			# Create the 16th loose reference, which should cause us to repack.
-			git update-ref refs/heads/loose-17 HEAD &&
-			git pack-refs --auto --all &&
-			test_line_count = 18 .git/packed-refs
-		)
-	'
-
-	test_expect_success "$command scales with size of packed-refs" '
-		test_when_finished "rm -rf repo" &&
-		git init repo &&
-		(
-			cd repo &&
-			git config set maintenance.auto false &&
-			git commit --allow-empty --message "initial" &&
-
-			# Create 99 packed refs. This should cause the heuristic
-			# to require more than the minimum amount of loose refs.
-			test_seq 99 |
-			while read i
-			do
-				printf "create refs/heads/packed-%d HEAD\n" $i || return 1
-			done >stdin &&
-			git update-ref --stdin <stdin &&
-			git pack-refs --all &&
-			test_line_count = 101 .git/packed-refs &&
-
-			# Create 24 loose refs, which should not yet cause us to repack.
-			printf "create refs/heads/loose-%d HEAD\n" $(test_seq 24) >stdin &&
-			git update-ref --stdin <stdin &&
-			git pack-refs --auto --all &&
-			test_line_count = 101 .git/packed-refs &&
-
-			# Create another handful of refs to cross the border.
-			# Note that we explicitly do not check for strict
-			# boundaries here, as this also depends on the size of
-			# the object hash.
-			printf "create refs/heads/addn-%d HEAD\n" $(test_seq 10) >stdin &&
-			git update-ref --stdin <stdin &&
-			git pack-refs --auto --all &&
-			test_line_count = 135 .git/packed-refs
-		)
-	'
-done
+. "$TEST_DIRECTORY"/pack-refs-tests.sh
 
 test_done
diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh
index 3ea5d51..6575528 100755
--- a/t/t0610-reftable-basics.sh
+++ b/t/t0610-reftable-basics.sh
@@ -1135,4 +1135,32 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'writes do not persist peeled value for invalid tags' '
+	test_when_finished rm -rf repo &&
+	git init repo &&
+	(
+		cd repo &&
+		git commit --allow-empty --message initial &&
+
+		# We cannot easily verify that the peeled value is not stored
+		# in the tables. Instead, we test this indirectly: we create
+		# two tags that both point to the same object, but they claim
+		# different object types. If we parse both tags we notice that
+		# the parsed tagged object has a mismatch between the two tags
+		# and bail out.
+		#
+		# If we instead use the persisted peeled value we would not
+		# even parse the tags. As such, we would not notice the
+		# discrepancy either and thus listing these tags would succeed.
+		git tag tag-1 -m "tag 1" &&
+		git cat-file tag tag-1 >raw-tag &&
+		sed "s/^type commit$/type blob/" <raw-tag >broken-tag &&
+		broken_tag_id=$(git hash-object -w -t tag broken-tag) &&
+		git update-ref refs/tags/tag-2 $broken_tag_id &&
+
+		test_must_fail git for-each-ref --format="%(*objectname)" refs/tags/ 2>err &&
+		test_grep "bad tag pointer" err
+	)
+'
+
 test_done
diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh
index d77e601..e334751 100755
--- a/t/t0613-reftable-write-options.sh
+++ b/t/t0613-reftable-write-options.sh
@@ -11,16 +11,18 @@
 # Block sizes depend on the hash function, so we force SHA1 here.
 GIT_TEST_DEFAULT_HASH=sha1
 export GIT_TEST_DEFAULT_HASH
-# Block sizes also depend on the actual refs we write, so we force "master" to
-# be the default initial branch name.
-GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
-export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./test-lib.sh
 
+# Block sizes depend on the actual refs we write, so, for tests
+# that check block size, we force the initial branch name to be "master".
+init_repo () {
+	git init --initial-branch master repo
+}
+
 test_expect_success 'default write options' '
 	test_when_finished "rm -rf repo" &&
-	git init repo &&
+	init_repo &&
 	(
 		cd repo &&
 		test_commit initial &&
@@ -43,7 +45,7 @@
 test_expect_success 'disabled reflog writes no log blocks' '
 	test_config_global core.logAllRefUpdates false &&
 	test_when_finished "rm -rf repo" &&
-	git init repo &&
+	init_repo &&
 	(
 		cd repo &&
 		test_commit initial &&
@@ -62,7 +64,7 @@
 
 test_expect_success 'many refs results in multiple blocks' '
 	test_when_finished "rm -rf repo" &&
-	git init repo &&
+	init_repo &&
 	(
 		cd repo &&
 		test_commit initial &&
@@ -115,7 +117,7 @@
 test_expect_success 'small block size leads to multiple ref blocks' '
 	test_config_global core.logAllRefUpdates false &&
 	test_when_finished "rm -rf repo" &&
-	git init repo &&
+	init_repo &&
 	(
 		cd repo &&
 		test_commit A &&
@@ -172,7 +174,7 @@
 
 test_expect_success 'restart interval at every single record' '
 	test_when_finished "rm -rf repo" &&
-	git init repo &&
+	init_repo &&
 	(
 		cd repo &&
 		test_commit initial &&
@@ -212,7 +214,7 @@
 test_expect_success 'object index gets written by default with ref index' '
 	test_config_global core.logAllRefUpdates false &&
 	test_when_finished "rm -rf repo" &&
-	git init repo &&
+	init_repo &&
 	(
 		cd repo &&
 		test_commit initial &&
@@ -247,7 +249,7 @@
 test_expect_success 'object index can be disabled' '
 	test_config_global core.logAllRefUpdates false &&
 	test_when_finished "rm -rf repo" &&
-	git init repo &&
+	init_repo &&
 	(
 		cd repo &&
 		test_commit initial &&
diff --git a/t/t0614-reftable-fsck.sh b/t/t0614-reftable-fsck.sh
new file mode 100755
index 0000000..85cc47d
--- /dev/null
+++ b/t/t0614-reftable-fsck.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+test_description='Test reftable backend consistency check'
+
+GIT_TEST_DEFAULT_REF_FORMAT=reftable
+export GIT_TEST_DEFAULT_REF_FORMAT
+
+. ./test-lib.sh
+
+test_expect_success "no errors reported on a well formed repository" '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		git commit --allow-empty -m initial &&
+
+		for i in $(test_seq 20)
+		do
+			git update-ref refs/heads/branch-$i HEAD || return 1
+		done &&
+
+		# The repository should end up with multiple tables.
+		test_line_count ">" 1 .git/reftable/tables.list &&
+
+		git refs verify 2>err &&
+		test_must_be_empty err
+	)
+'
+
+for TABLE_NAME in "foo-bar-e4d12d59.ref" \
+	"0x00000000zzzz-0x00000000zzzz-e4d12d59.ref" \
+	"0x000000000001-0x000000000002-e4d12d59.abc" \
+	"0x000000000001-0x000000000002-e4d12d59.refabc"; do
+	test_expect_success "table name $TABLE_NAME should be checked" '
+		test_when_finished "rm -rf repo" &&
+		git init repo &&
+		(
+			cd repo &&
+			git commit --allow-empty -m initial &&
+
+			git refs verify 2>err &&
+			test_must_be_empty err &&
+
+			EXISTING_TABLE=$(head -n1 .git/reftable/tables.list) &&
+			mv ".git/reftable/$EXISTING_TABLE" ".git/reftable/$TABLE_NAME" &&
+			sed "s/${EXISTING_TABLE}/${TABLE_NAME}/g" .git/reftable/tables.list > tables.list &&
+			mv tables.list .git/reftable/tables.list &&
+
+			git refs verify 2>err &&
+			cat >expect <<-EOF &&
+			warning: ${TABLE_NAME}: badReftableTableName: invalid reftable table name
+			EOF
+			test_cmp expect err
+		)
+	'
+done
+
+test_done
diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh
index e9973f7..312fe67 100755
--- a/t/t1010-mktree.sh
+++ b/t/t1010-mktree.sh
@@ -11,10 +11,13 @@
 		git add "$d" || return 1
 	done &&
 	echo zero >one &&
-	git update-index --add --info-only one &&
-	git write-tree --missing-ok >tree.missing &&
-	git ls-tree $(cat tree.missing) >top.missing &&
-	git ls-tree -r $(cat tree.missing) >all.missing &&
+	if test_have_prereq BROKEN_OBJECTS
+	then
+		git update-index --add --info-only one &&
+		git write-tree --missing-ok >tree.missing &&
+		git ls-tree $(cat tree.missing) >top.missing &&
+		git ls-tree -r $(cat tree.missing) >all.missing
+	fi &&
 	echo one >one &&
 	git add one &&
 	git write-tree >tree &&
@@ -53,7 +56,7 @@
 	test_cmp tree.withsub actual
 '
 
-test_expect_success 'allow missing object with --missing' '
+test_expect_success BROKEN_OBJECTS 'allow missing object with --missing' '
 	git mktree --missing <top.missing >actual &&
 	test_cmp tree.missing actual
 '
diff --git a/t/t1016-compatObjectFormat.sh b/t/t1016-compatObjectFormat.sh
index e88362f..0efce53 100755
--- a/t/t1016-compatObjectFormat.sh
+++ b/t/t1016-compatObjectFormat.sh
@@ -21,6 +21,12 @@
 # different hash functions result in the same content in the commits.
 # This means that when the commit is translated between hash functions
 # the commit is identical to the commit in the other repository.
+#
+# Similarly this test relies on:
+#	gpg --faked-system-time '20230918T154812!
+# freezing the system time from gpg perspective so that two different
+# runs of gpg applied to the same data result in identical signatures.
+#
 
 compat_hash () {
 	case "$1" in
@@ -114,7 +120,7 @@
 		git config core.repositoryformatversion 1 &&
 		git config extensions.objectformat $hash &&
 		git config extensions.compatobjectformat $(compat_hash $hash) &&
-		test_config gpg.program $TEST_DIRECTORY/t1016/gpg &&
+		git config gpg.program $TEST_DIRECTORY/t1016/gpg &&
 		echo "Hello World!" >hello &&
 		eval hello_${hash}_oid=$(git hash-object hello) &&
 		git update-index --add hello &&
diff --git a/t/t1016/gpg b/t/t1016/gpg
index 2601cb1..34d6e05 100755
--- a/t/t1016/gpg
+++ b/t/t1016/gpg
@@ -1,2 +1,2 @@
 #!/bin/sh
-exec gpg --faked-system-time "20230918T154812" "$@"
+exec gpg --faked-system-time '20230918T154812!' "$@"
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index ab3a105..b2da4fe 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -1050,5 +1050,180 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'clean' '
+	git -C repo sparse-checkout set --cone deep/deeper1 &&
+	git -C repo sparse-checkout reapply &&
+	mkdir -p repo/deep/deeper2 repo/folder1/extra/inside &&
+
+	# Add untracked files
+	touch repo/deep/deeper2/file &&
+	touch repo/folder1/extra/inside/file &&
+
+	test_must_fail git -C repo sparse-checkout clean 2>err &&
+	grep "refusing to clean" err &&
+
+	git -C repo config clean.requireForce true &&
+	test_must_fail git -C repo sparse-checkout clean 2>err &&
+	grep "refusing to clean" err &&
+
+	cat >expect <<-\EOF &&
+	Would remove deep/deeper2/
+	Would remove folder1/
+	EOF
+
+	git -C repo sparse-checkout clean --dry-run >out &&
+	test_cmp expect out &&
+	test_path_exists repo/deep/deeper2 &&
+	test_path_exists repo/folder1/extra/inside/file &&
+
+	cat >expect <<-\EOF &&
+	Would remove deep/deeper2/file
+	Would remove folder1/extra/inside/file
+	EOF
+
+	git -C repo sparse-checkout clean --dry-run --verbose >out &&
+	test_cmp expect out &&
+
+	cat >expect <<-\EOF &&
+	Removing deep/deeper2/
+	Removing folder1/
+	EOF
+
+	git -C repo sparse-checkout clean -f >out &&
+	test_cmp expect out &&
+
+	test_path_is_missing repo/deep/deeper2 &&
+	test_path_is_missing repo/folder1
+'
+
+test_expect_success 'clean with sparse file states' '
+	test_when_finished git reset --hard &&
+	git -C repo sparse-checkout set --cone deep/deeper1 &&
+	mkdir repo/folder2 &&
+
+	# The previous test case checked the -f option, so
+	# test the config option in this one.
+	git -C repo config clean.requireForce false &&
+
+	# create an untracked file and a modified file
+	touch repo/folder2/file &&
+	echo dirty >repo/folder2/a &&
+
+	# First clean/reapply pass will do nothing.
+	git -C repo sparse-checkout clean >out &&
+	test_must_be_empty out &&
+	test_path_exists repo/folder2/a &&
+	test_path_exists repo/folder2/file &&
+
+	git -C repo sparse-checkout reapply 2>err &&
+	test_grep folder2 err &&
+	test_path_exists repo/folder2/a &&
+	test_path_exists repo/folder2/file &&
+
+	# Now, stage the change to the tracked file.
+	git -C repo add --sparse folder2/a &&
+
+	# Clean will continue not doing anything.
+	git -C repo sparse-checkout clean >out &&
+	test_line_count = 0 out &&
+	test_path_exists repo/folder2/a &&
+	test_path_exists repo/folder2/file &&
+
+	# But we can reapply to remove the staged change.
+	git -C repo sparse-checkout reapply 2>err &&
+	test_grep folder2 err &&
+	test_path_is_missing repo/folder2/a &&
+	test_path_exists repo/folder2/file &&
+
+	# We can clean now.
+	cat >expect <<-\EOF &&
+	Removing folder2/
+	EOF
+	git -C repo sparse-checkout clean >out &&
+	test_cmp expect out &&
+	test_path_is_missing repo/folder2 &&
+
+	# At the moment, the file is staged.
+	cat >expect <<-\EOF &&
+	M  folder2/a
+	EOF
+
+	git -C repo status -s >out &&
+	test_cmp expect out &&
+
+	# Reapply persists the modified state.
+	git -C repo sparse-checkout reapply &&
+	cat >expect <<-\EOF &&
+	M  folder2/a
+	EOF
+	git -C repo status -s >out &&
+	test_cmp expect out &&
+
+	# Committing the change leads to resolved status.
+	git -C repo commit -m "modified" &&
+	git -C repo status -s >out &&
+	test_must_be_empty out &&
+
+	# Repeat, but this time commit before reapplying.
+	mkdir repo/folder2/ &&
+	echo dirtier >repo/folder2/a &&
+	git -C repo add --sparse folder2/a &&
+	git -C repo sparse-checkout clean >out &&
+	test_must_be_empty out &&
+	test_path_exists repo/folder2/a &&
+
+	# Committing without reapplying makes it look like a deletion
+	# due to no skip-worktree bit.
+	git -C repo commit -m "dirtier" &&
+	git -C repo status -s >out &&
+	test_must_be_empty out &&
+
+	git -C repo sparse-checkout reapply &&
+	git -C repo status -s >out &&
+	test_must_be_empty out
+'
+
+test_expect_success 'sparse-checkout operations with merge conflicts' '
+	git clone repo merge &&
+
+	(
+		cd merge &&
+		mkdir -p folder1/even/more/dirs &&
+		echo base >folder1/even/more/dirs/file &&
+		git add folder1 &&
+		git commit -m "base" &&
+
+		git checkout -b right&&
+		echo right >folder1/even/more/dirs/file &&
+		git commit -a -m "right" &&
+
+		git checkout -b left HEAD~1 &&
+		echo left >folder1/even/more/dirs/file &&
+		git commit -a -m "left" &&
+
+		git checkout -b merge &&
+		git sparse-checkout set deep/deeper1 &&
+
+		test_must_fail git merge -m "will-conflict" right &&
+
+		test_must_fail git sparse-checkout clean -f 2>err &&
+		grep "failed to convert index to a sparse index" err &&
+
+		echo merged >folder1/even/more/dirs/file &&
+		git add --sparse folder1 &&
+		git merge --continue &&
+
+		test_path_exists folder1/even/more/dirs/file &&
+
+		# clean does not remove the file, because the
+		# SKIP_WORKTREE bit was not cleared by the merge command.
+		git sparse-checkout clean -f >out &&
+		test_line_count = 0 out &&
+		test_path_exists folder1/even/more/dirs/file &&
+
+		git sparse-checkout reapply &&
+		test_path_is_missing folder1
+	)
+'
 
 test_done
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index d810113..b0f691c 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -1506,6 +1506,8 @@
 	ensure_not_expanded reset --hard &&
 	ensure_not_expanded restore -s rename-out-to-out -- deep/deeper1 &&
 
+	ensure_not_expanded ls-files deep/deeper1 &&
+
 	echo >>sparse-index/README.md &&
 	ensure_not_expanded add -A &&
 	echo >>sparse-index/extra.txt &&
@@ -1607,6 +1609,17 @@
 	test_all_match git describe --dirty
 '
 
+test_expect_success 'ls-files filtering and expansion' '
+	init_repos &&
+
+	# This filtering will hit a sparse directory midway
+	# through the iteration.
+	test_all_match git ls-files deep &&
+
+	# This pathspec will filter the index to only a sparse
+	# directory.
+	test_all_match git ls-files folder1
+'
 
 test_expect_success 'sparse-index is not expanded: describe' '
 	init_repos &&
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index f856821..358d636 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -9,6 +9,7 @@
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
 
 for mode in legacy subcommands
 do
@@ -134,38 +135,39 @@
 	rm -f .git/config
 '
 
-cat > expect << EOF
+test_expect_success 'initial' '
+	cat >expect <<\EOF &&
 [section]
 	penguin = little blue
 EOF
-test_expect_success 'initial' '
 	git config ${mode_set} section.penguin "little blue" &&
 	test_cmp expect .git/config
 '
 
-cat > expect << EOF
+test_expect_success 'mixed case' '
+	cat >expect <<\EOF &&
 [section]
 	penguin = little blue
 	Movie = BadPhysics
 EOF
-test_expect_success 'mixed case' '
 	git config ${mode_set} Section.Movie BadPhysics &&
 	test_cmp expect .git/config
 '
 
-cat > expect << EOF
+test_expect_success 'similar section' '
+	cat >expect <<\EOF &&
 [section]
 	penguin = little blue
 	Movie = BadPhysics
 [Sections]
 	WhatEver = Second
 EOF
-test_expect_success 'similar section' '
 	git config ${mode_set} Sections.WhatEver Second &&
 	test_cmp expect .git/config
 '
 
-cat > expect << EOF
+test_expect_success 'uppercase section' '
+	cat >expect <<\EOF &&
 [section]
 	penguin = little blue
 	Movie = BadPhysics
@@ -173,7 +175,6 @@
 [Sections]
 	WhatEver = Second
 EOF
-test_expect_success 'uppercase section' '
 	git config ${mode_set} SECTION.UPPERCASE true &&
 	test_cmp expect .git/config
 '
@@ -186,7 +187,8 @@
 	git config section.penguin "very blue" !kingpin
 '
 
-cat > expect << EOF
+test_expect_success 'append comments' '
+	cat >expect <<\EOF &&
 [section]
 	Movie = BadPhysics
 	UPPERCASE = true
@@ -198,8 +200,6 @@
 [Sections]
 	WhatEver = Second
 EOF
-
-test_expect_success 'append comments' '
 	git config --replace-all --comment="Pygoscelis papua" section.penguin gentoo &&
 	git config ${mode_set} --comment="find fish" section.disposition peckish &&
 	git config ${mode_set} --comment="#abc" section.foo bar &&
@@ -214,7 +214,9 @@
 	test_must_fail git config ${mode_set} --comment="a${LF}b" section.k v
 '
 
-test_expect_success 'non-match result' 'test_cmp expect .git/config'
+test_expect_success 'non-match result' '
+	test_cmp expect .git/config
+'
 
 test_expect_success 'find mixed-case key by canonical name' '
 	test_cmp_config Second sections.whatever
@@ -265,14 +267,15 @@
 	git config ${mode_unset} beta.baz
 '
 
-cat > expect <<\EOF
-[alpha]
-bar = foo
-[beta]
-foo = bar
-EOF
-
-test_expect_success 'unset with cont. lines is correct' 'test_cmp expect .git/config'
+test_expect_success 'unset with cont. lines is correct' '
+	cat >expect <<-\EOF &&
+	[alpha]
+	bar = foo
+	[beta]
+	foo = bar
+	EOF
+	test_cmp expect .git/config
+'
 
 cat > .git/config << EOF
 [beta] ; silly comment # another comment
@@ -292,16 +295,15 @@
 	git config ${mode_unset_all} beta.haha
 '
 
-cat > expect << EOF
+test_expect_success 'multiple unset is correct' '
+	cat >expect <<EOF &&
 [beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
 
 # empty line
 		; comment
 [nextSection] noNewline = ouch
 EOF
-
-test_expect_success 'multiple unset is correct' '
 	test_cmp expect .git/config
 '
 
@@ -318,37 +320,37 @@
 	git config ${mode_replace_all} beta.haha gamma
 '
 
-cat > expect << EOF
+test_expect_success 'all replaced' '
+	cat >expect <<EOF &&
 [beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
 
 # empty line
 		; comment
 	haha = gamma
 [nextSection] noNewline = ouch
 EOF
-
-test_expect_success 'all replaced' '
 	test_cmp expect .git/config
 '
 
-cat > expect << EOF
+test_expect_success 'really mean test' '
+	cat >expect <<EOF &&
 [beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
 
 # empty line
 		; comment
 	haha = alpha
 [nextSection] noNewline = ouch
 EOF
-test_expect_success 'really mean test' '
 	git config ${mode_set} beta.haha alpha &&
 	test_cmp expect .git/config
 '
 
-cat > expect << EOF
+test_expect_success 'really really mean test' '
+	cat >expect <<EOF &&
 [beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
 
 # empty line
 		; comment
@@ -356,7 +358,6 @@
 [nextSection]
 	nonewline = wow
 EOF
-test_expect_success 'really really mean test' '
 	git config ${mode_set} nextsection.nonewline wow &&
 	test_cmp expect .git/config
 '
@@ -365,23 +366,24 @@
 	test_cmp_config alpha beta.haha
 '
 
-cat > expect << EOF
+test_expect_success 'unset' '
+	cat >expect <<EOF &&
 [beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
 
 # empty line
 		; comment
 [nextSection]
 	nonewline = wow
 EOF
-test_expect_success 'unset' '
 	git config ${mode_unset} beta.haha &&
 	test_cmp expect .git/config
 '
 
-cat > expect << EOF
+test_expect_success 'multivar' '
+	cat  >expect <<EOF &&
 [beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
 
 # empty line
 		; comment
@@ -389,7 +391,6 @@
 	nonewline = wow
 	NoNewLine = wow2 for me
 EOF
-test_expect_success 'multivar' '
 	git config nextsection.NoNewLine "wow2 for me" "for me$" &&
 	test_cmp expect .git/config
 '
@@ -415,9 +416,10 @@
 	test_cmp expect actual
 '
 
-cat > expect << EOF
+test_expect_success 'multivar replace' '
+	cat >expect <<EOF &&
 [beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
 
 # empty line
 		; comment
@@ -425,7 +427,6 @@
 	nonewline = wow3
 	NoNewLine = wow2 for me
 EOF
-test_expect_success 'multivar replace' '
 	git config nextsection.nonewline "wow3" "wow$" &&
 	test_cmp expect .git/config
 '
@@ -438,17 +439,16 @@
 	test_must_fail git config ${mode_unset} somesection.nonewline
 '
 
-cat > expect << EOF
+test_expect_success 'multivar unset' '
+	cat >expect <<EOF &&
 [beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
 
 # empty line
 		; comment
 [nextSection]
 	NoNewLine = wow2 for me
 EOF
-
-test_expect_success 'multivar unset' '
 	case "$mode" in
 	legacy)
 		git config --unset nextsection.nonewline "wow3$";;
@@ -458,17 +458,22 @@
 	test_cmp expect .git/config
 '
 
-test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla'
+test_expect_success 'invalid key' '
+	test_must_fail git config inval.2key blabla
+'
 
-test_expect_success 'correct key' 'git config 123456.a123 987'
+test_expect_success 'correct key' '
+	git config 123456.a123 987
+'
 
 test_expect_success 'hierarchical section' '
 	git config Version.1.2.3eX.Alpha beta
 '
 
-cat > expect << EOF
+test_expect_success 'hierarchical section value' '
+	cat >expect <<EOF &&
 [beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
 
 # empty line
 		; comment
@@ -479,65 +484,59 @@
 [Version "1.2.3eX"]
 	Alpha = beta
 EOF
-
-test_expect_success 'hierarchical section value' '
 	test_cmp expect .git/config
 '
 
-cat > expect << EOF
-beta.noindent=sillyValue
-nextsection.nonewline=wow2 for me
-123456.a123=987
-version.1.2.3eX.alpha=beta
-EOF
-
 test_expect_success 'working --list' '
+	cat >expect <<-\EOF &&
+	beta.noindent=sillyValue
+	nextsection.nonewline=wow2 for me
+	123456.a123=987
+	version.1.2.3eX.alpha=beta
+	EOF
 	git config ${mode_prefix}list > output &&
 	test_cmp expect output
 '
+
 test_expect_success '--list without repo produces empty output' '
 	git --git-dir=nonexistent config ${mode_prefix}list >output &&
 	test_must_be_empty output
 '
 
-cat > expect << EOF
-beta.noindent
-nextsection.nonewline
-123456.a123
-version.1.2.3eX.alpha
-EOF
-
 test_expect_success '--name-only --list' '
+	cat >expect <<-\EOF &&
+	beta.noindent
+	nextsection.nonewline
+	123456.a123
+	version.1.2.3eX.alpha
+	EOF
 	git config ${mode_prefix}list --name-only >output &&
 	test_cmp expect output
 '
 
-cat > expect << EOF
-beta.noindent sillyValue
-nextsection.nonewline wow2 for me
-EOF
-
 test_expect_success '--get-regexp' '
+	cat >expect <<-\EOF &&
+	beta.noindent sillyValue
+	nextsection.nonewline wow2 for me
+	EOF
 	git config ${mode_get_regexp} in >output &&
 	test_cmp expect output
 '
 
-cat > expect << EOF
-beta.noindent
-nextsection.nonewline
-EOF
-
 test_expect_success '--name-only --get-regexp' '
+	cat >expect <<-\EOF &&
+	beta.noindent
+	nextsection.nonewline
+	EOF
 	git config ${mode_get_regexp} --name-only in >output &&
 	test_cmp expect output
 '
 
-cat > expect << EOF
-wow2 for me
-wow4 for you
-EOF
-
 test_expect_success '--add' '
+	cat >expect <<-\EOF &&
+	wow2 for me
+	wow4 for you
+	EOF
 	git config --add nextsection.nonewline "wow4 for you" &&
 	git config ${mode_get_all} nextsection.nonewline > output &&
 	test_cmp expect output
@@ -558,37 +557,32 @@
 	git config --get emptyvalue.variable ^$
 '
 
-echo novalue.variable > expect
-
 test_expect_success 'get-regexp variable with no value' '
+	echo novalue.variable >expect &&
 	git config ${mode_get_regexp} novalue > output &&
 	test_cmp expect output
 '
 
-echo 'novalue.variable true' > expect
-
 test_expect_success 'get-regexp --bool variable with no value' '
+	echo "novalue.variable true" >expect &&
 	git config ${mode_get_regexp} --bool novalue > output &&
 	test_cmp expect output
 '
 
-echo 'emptyvalue.variable ' > expect
-
 test_expect_success 'get-regexp variable with empty value' '
+	echo "emptyvalue.variable " >expect &&
 	git config ${mode_get_regexp} emptyvalue > output &&
 	test_cmp expect output
 '
 
-echo true > expect
-
 test_expect_success 'get bool variable with no value' '
+	echo true >expect &&
 	git config --bool novalue.variable > output &&
 	test_cmp expect output
 '
 
-echo false > expect
-
 test_expect_success 'get bool variable with empty value' '
+	echo false >expect &&
 	git config --bool emptyvalue.variable > output &&
 	test_cmp expect output
 '
@@ -604,19 +598,19 @@
 	c = d
 EOF
 
-cat > expect << EOF
+test_expect_success 'new section is partial match of another' '
+	cat >expect <<\EOF &&
 [a.b]
 	c = d
 [a]
 	x = y
 EOF
-
-test_expect_success 'new section is partial match of another' '
 	git config a.x y &&
 	test_cmp expect .git/config
 '
 
-cat > expect << EOF
+test_expect_success 'new variable inserts into proper section' '
+	cat >expect <<\EOF &&
 [a.b]
 	c = d
 [a]
@@ -625,8 +619,6 @@
 [b]
 	x = y
 EOF
-
-test_expect_success 'new variable inserts into proper section' '
 	git config b.x y &&
 	git config a.b c &&
 	test_cmp expect .git/config
@@ -642,11 +634,10 @@
 	bahn = strasse
 EOF
 
-cat > expect << EOF
-ein.bahn=strasse
-EOF
-
 test_expect_success 'alternative GIT_CONFIG' '
+	cat >expect <<-\EOF &&
+	ein.bahn=strasse
+	EOF
 	GIT_CONFIG=other-config git config ${mode_prefix}list >output &&
 	test_cmp expect output
 '
@@ -675,14 +666,13 @@
 	test_cmp_config -C x strasse --file=../other-config --get ein.bahn
 '
 
-cat > expect << EOF
+test_expect_success '--set in alternative file' '
+	cat >expect <<\EOF &&
 [ein]
 	bahn = strasse
 [anwohner]
 	park = ausweis
 EOF
-
-test_expect_success '--set in alternative file' '
 	git config --file=other-config anwohner.park ausweis &&
 	test_cmp expect other-config
 '
@@ -730,7 +720,8 @@
 	git config ${mode_prefix}rename-section branch."1 234 blabl/a" branch.drei
 '
 
-cat > expect << EOF
+test_expect_success 'rename succeeded' '
+	cat >expect <<\EOF &&
 # Hallo
 	#Bello
 [branch "zwei"]
@@ -740,8 +731,6 @@
 [branch "drei"]
 weird
 EOF
-
-test_expect_success 'rename succeeded' '
 	test_cmp expect .git/config
 '
 
@@ -753,7 +742,8 @@
 	git config ${mode_prefix}rename-section branch.vier branch.zwei
 '
 
-cat > expect << EOF
+test_expect_success 'rename succeeded' '
+	cat >expect <<\EOF &&
 # Hallo
 	#Bello
 [branch "zwei"]
@@ -765,8 +755,6 @@
 [branch "zwei"]
 	z = 1
 EOF
-
-test_expect_success 'rename succeeded' '
 	test_cmp expect .git/config
 '
 
@@ -816,32 +804,29 @@
 	git config ${mode_prefix}remove-section branch.zwei
 '
 
-cat > expect << EOF
+test_expect_success 'section was removed properly' '
+	cat >expect <<\EOF &&
 # Hallo
 	#Bello
 [branch "drei"]
 weird
 EOF
-
-test_expect_success 'section was removed properly' '
 	test_cmp expect .git/config
 '
 
-cat > expect << EOF
+test_expect_success 'section ending' '
+	cat >expect <<\EOF &&
 [gitcvs]
 	enabled = true
 	dbname = %Ggitcvs2.%a.%m.sqlite
 [gitcvs "ext"]
 	dbname = %Ggitcvs1.%a.%m.sqlite
 EOF
-
-test_expect_success 'section ending' '
 	rm -f .git/config &&
 	git config ${mode_set} gitcvs.enabled true &&
 	git config ${mode_set} gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite &&
 	git config ${mode_set} gitcvs.dbname %Ggitcvs2.%a.%m.sqlite &&
 	test_cmp expect .git/config
-
 '
 
 test_expect_success numbers '
@@ -885,19 +870,17 @@
 	test_grep "bad config line 1 in standard input" output
 '
 
-cat > expect << EOF
-true
-false
-true
-false
-true
-false
-true
-false
-EOF
-
 test_expect_success bool '
-
+	cat >expect <<-\EOF &&
+	true
+	false
+	true
+	false
+	true
+	false
+	true
+	false
+	EOF
 	git config ${mode_set} bool.true1 01 &&
 	git config ${mode_set} bool.true2 -1 &&
 	git config ${mode_set} bool.true3 YeS &&
@@ -912,18 +895,20 @@
 	    git config --bool --get bool.true$i >>result &&
 	    git config --bool --get bool.false$i >>result || return 1
 	done &&
-	test_cmp expect result'
+	test_cmp expect result
+'
 
 test_expect_success 'invalid bool (--get)' '
-
 	git config ${mode_set} bool.nobool foobar &&
-	test_must_fail git config --bool --get bool.nobool'
+	test_must_fail git config --bool --get bool.nobool
+'
 
 test_expect_success 'invalid bool (set)' '
+	test_must_fail git config --bool bool.nobool foobar
+'
 
-	test_must_fail git config --bool bool.nobool foobar'
-
-cat > expect <<\EOF
+test_expect_success 'set --bool' '
+	cat >expect <<\EOF &&
 [bool]
 	true1 = true
 	true2 = true
@@ -934,9 +919,6 @@
 	false3 = false
 	false4 = false
 EOF
-
-test_expect_success 'set --bool' '
-
 	rm -f .git/config &&
 	git config --bool bool.true1 01 &&
 	git config --bool bool.true2 -1 &&
@@ -948,15 +930,13 @@
 	git config --bool bool.false4 FALSE &&
 	test_cmp expect .git/config'
 
-cat > expect <<\EOF
+test_expect_success 'set --int' '
+	cat >expect <<\EOF &&
 [int]
 	val1 = 1
 	val2 = -1
 	val3 = 5242880
 EOF
-
-test_expect_success 'set --int' '
-
 	rm -f .git/config &&
 	git config --int int.val1 01 &&
 	git config --int int.val2 -1 &&
@@ -994,7 +974,8 @@
 	test_cmp expect actual
 '
 
-cat >expect <<\EOF
+test_expect_success 'set --bool-or-int' '
+	cat >expect <<\EOF &&
 [bool]
 	true1 = true
 	false1 = false
@@ -1005,8 +986,6 @@
 	int2 = 1
 	int3 = -1
 EOF
-
-test_expect_success 'set --bool-or-int' '
 	rm -f .git/config &&
 	git config --bool-or-int bool.true1 true &&
 	git config --bool-or-int bool.false1 false &&
@@ -1018,44 +997,42 @@
 	test_cmp expect .git/config
 '
 
-cat >expect <<\EOF
+test_expect_success !MINGW 'set --path' '
+	cat >expect <<\EOF &&
 [path]
 	home = ~/
 	normal = /dev/null
 	trailingtilde = foo~
 EOF
-
-test_expect_success !MINGW 'set --path' '
 	rm -f .git/config &&
 	git config --path path.home "~/" &&
 	git config --path path.normal "/dev/null" &&
 	git config --path path.trailingtilde "foo~" &&
-	test_cmp expect .git/config'
+	test_cmp expect .git/config
+'
 
 if test_have_prereq !MINGW && test "${HOME+set}"
 then
 	test_set_prereq HOMEVAR
 fi
 
-cat >expect <<EOF
-$HOME/
-/dev/null
-foo~
-EOF
-
 test_expect_success HOMEVAR 'get --path' '
+	cat >expect <<-EOF &&
+	$HOME/
+	/dev/null
+	foo~
+	EOF
 	git config --get --path path.home > result &&
 	git config --get --path path.normal >> result &&
 	git config --get --path path.trailingtilde >> result &&
 	test_cmp expect result
 '
 
-cat >expect <<\EOF
-/dev/null
-foo~
-EOF
-
 test_expect_success !MINGW 'get --path copes with unset $HOME' '
+	cat >expect <<-\EOF &&
+	/dev/null
+	foo~
+	EOF
 	(
 		sane_unset HOME &&
 		test_must_fail git config --get --path path.home \
@@ -1107,17 +1084,35 @@
 	rm .git/config &&
 	git config ${mode_set} foo.color "red" &&
 	git config --get --type=color foo.color >actual.raw &&
+	git config get --type=color foo.color >actual-subcommand.raw &&
+	test_cmp actual.raw actual-subcommand.raw &&
 	test_decode_color <actual.raw >actual &&
 	echo "<RED>" >expect &&
 	test_cmp expect actual
 '
 
-cat >expect << EOF
+test_expect_success 'get --type=color with default value only' '
+	git config --get-color "" "red" >actual.raw &&
+	test_decode_color <actual.raw >actual &&
+	echo "<RED>" >expect &&
+	test_cmp expect actual &&
+	git config get --type=color --default="red" "" >actual-subcommand.raw &&
+	test_cmp actual.raw actual-subcommand.raw
+'
+
+test_expect_success TTY 'get --type=color does not use a pager' '
+	test_config core.pager "echo foobar" &&
+	test_terminal git config get --type=color --default="red" "" >actual.raw &&
+	test_decode_color <actual.raw >actual &&
+	echo "<RED>" >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'set --type=color' '
+	cat >expect <<\EOF &&
 [foo]
 	color = red
 EOF
-
-test_expect_success 'set --type=color' '
 	rm .git/config &&
 	git config --type=color foo.color "red" &&
 	test_cmp expect .git/config
@@ -1133,14 +1128,14 @@
 	test_grep "cannot parse color" error
 '
 
-cat > expect << EOF
+test_expect_success 'quoting' '
+	cat >expect <<\EOF &&
 [quote]
 	leading = " test"
 	ending = "test "
 	semicolon = "test;test"
 	hash = "test#test"
 EOF
-test_expect_success 'quoting' '
 	rm -f .git/config &&
 	git config ${mode_set} quote.leading " test" &&
 	git config ${mode_set} quote.ending "test " &&
@@ -1151,10 +1146,13 @@
 
 test_expect_success 'key with newline' '
 	test_must_fail git config ${mode_get} "key.with
-newline" 123'
+newline" 123
+'
 
-test_expect_success 'value with newline' 'git config ${mode_set} key.sub value.with\\\
-newline'
+test_expect_success 'value with newline' '
+	git config ${mode_set} key.sub value.with\\\
+newline
+'
 
 cat > .git/config <<\EOF
 [section]
@@ -1166,13 +1164,12 @@
 inued"
 EOF
 
-cat > expect <<\EOF
-section.continued=continued
-section.noncont=not continued
-section.quotecont=cont;inued
-EOF
-
 test_expect_success 'value continued on next line' '
+	cat >expect <<-\EOF &&
+	section.continued=continued
+	section.noncont=not continued
+	section.quotecont=cont;inued
+	EOF
 	git config ${mode_prefix}list > result &&
 	test_cmp expect result
 '
@@ -1365,7 +1362,6 @@
 '
 
 test_expect_success 'last one wins: two level vars' '
-
 	# sec.var and sec.VAR are the same variable, as the first
 	# and the last level of a configuration variable name is
 	# case insensitive.
@@ -1384,7 +1380,6 @@
 '
 
 test_expect_success 'last one wins: three level vars' '
-
 	# v.a.r and v.A.r are not the same variable, as the middle
 	# level of a three-level configuration variable name is
 	# case sensitive.
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 08d5df2..db7f544 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -2421,4 +2421,25 @@
 	test_path_is_missing .git/refs/heads/nested
 '
 
+test_expect_success 'dangling symref not overwritten by creation' '
+	test_when_finished "git update-ref -d refs/heads/dangling" &&
+	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+	test_must_fail git update-ref --no-deref --stdin 2>err <<-\EOF &&
+	create refs/heads/dangling HEAD
+	EOF
+	test_grep "cannot lock.*dangling symref already exists" err &&
+	test_must_fail git rev-parse --verify refs/heads/dangling &&
+	test_must_fail git rev-parse --verify refs/heads/does-not-exist
+'
+
+test_expect_success 'dangling symref overwritten without old oid' '
+	test_when_finished "git update-ref -d refs/heads/dangling" &&
+	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+	git update-ref --no-deref --stdin <<-\EOF &&
+	update refs/heads/dangling HEAD
+	EOF
+	git rev-parse --verify refs/heads/dangling &&
+	test_must_fail git rev-parse --verify refs/heads/does-not-exist
+'
+
 test_done
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 9da3650..36c903c 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -228,69 +228,4 @@
 	grep "cannot be used together" err
 '
 
-test_expect_success '--exists with existing reference' '
-	git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
-	test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
-	test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
-	grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
-	git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
-	test_when_finished "git update-ref -d refs/heads/bad...name" &&
-	new_oid=$(git rev-parse HEAD) &&
-	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
-	git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
-	test_when_finished "git symbolic-ref -d refs/symref" &&
-	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
-	git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
-	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
-	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
-	git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
-	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
-	tree_oid=$(git rev-parse HEAD^{tree}) &&
-	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
-	cat >expect <<-EOF &&
-	error: reference does not exist
-	EOF
-	test_expect_code 2 git show-ref --exists refs/heads 2>err &&
-	test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
-	test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
-	test_when_finished "rm .git/FETCH_HEAD" &&
-	git rev-parse HEAD >.git/FETCH_HEAD &&
-	git show-ref --exists FETCH_HEAD
-'
-
 test_done
diff --git a/t/t1421-reflog-write.sh b/t/t1421-reflog-write.sh
index 46df64c..603ec3f 100755
--- a/t/t1421-reflog-write.sh
+++ b/t/t1421-reflog-write.sh
@@ -108,6 +108,42 @@
 	)
 '
 
+test_expect_success 'uses user.name and user.email config' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		COMMIT_OID=$(git rev-parse HEAD) &&
+
+		sane_unset GIT_COMMITTER_NAME &&
+		sane_unset GIT_COMMITTER_EMAIL &&
+		git config --local user.name "Author" &&
+		git config --local user.email "a@uth.or" &&
+		git reflog write refs/heads/something $ZERO_OID $COMMIT_OID first &&
+		test_reflog_matches . refs/heads/something <<-EOF
+		$ZERO_OID $COMMIT_OID Author <a@uth.or> $GIT_COMMITTER_DATE	first
+		EOF
+	)
+'
+
+test_expect_success 'environment variables take precedence over config' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		COMMIT_OID=$(git rev-parse HEAD) &&
+
+		git config --local user.name "Author" &&
+		git config --local user.email "a@uth.or" &&
+		git reflog write refs/heads/something $ZERO_OID $COMMIT_OID first &&
+		test_reflog_matches . refs/heads/something <<-EOF
+		$ZERO_OID $COMMIT_OID $SIGNATURE	first
+		EOF
+	)
+'
+
 test_expect_success 'can write to root ref' '
 	test_when_finished "rm -rf repo" &&
 	git init repo &&
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
new file mode 100755
index 0000000..fdca3f1
--- /dev/null
+++ b/t/t1422-show-ref-exists.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+test_description='show-ref --exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 5ae86c4..c4b651c 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -454,6 +454,60 @@
 	test_grep "error in tag $tag.*unterminated header: NUL at offset" out
 '
 
+test_expect_success 'tag accepts gpgsig header even if not validly signed' '
+	test_oid_cache <<-\EOF &&
+	header sha1:gpgsig-sha256
+	header sha256:gpgsig
+	EOF
+	header=$(test_oid header) &&
+	sha=$(git rev-parse HEAD) &&
+	cat >good-tag <<-EOF &&
+	object $sha
+	type commit
+	tag good
+	tagger T A Gger <tagger@example.com> 1234567890 -0000
+	$header -----BEGIN PGP SIGNATURE-----
+	 Not a valid signature
+	 -----END PGP SIGNATURE-----
+
+	This is a good tag.
+	EOF
+
+	tag=$(git hash-object --literally -t tag -w --stdin <good-tag) &&
+	test_when_finished "remove_object $tag" &&
+	git update-ref refs/tags/good $tag &&
+	test_when_finished "git update-ref -d refs/tags/good" &&
+	git -c fsck.extraHeaderEntry=error fsck --tags
+'
+
+test_expect_success 'tag rejects invalid headers' '
+	test_oid_cache <<-\EOF &&
+	header sha1:gpgsig-sha256
+	header sha256:gpgsig
+	EOF
+	header=$(test_oid header) &&
+	sha=$(git rev-parse HEAD) &&
+	cat >bad-tag <<-EOF &&
+	object $sha
+	type commit
+	tag good
+	tagger T A Gger <tagger@example.com> 1234567890 -0000
+	$header -----BEGIN PGP SIGNATURE-----
+	 Not a valid signature
+	 -----END PGP SIGNATURE-----
+	junk
+
+	This is a bad tag with junk at the end of the headers.
+	EOF
+
+	tag=$(git hash-object --literally -t tag -w --stdin <bad-tag) &&
+	test_when_finished "remove_object $tag" &&
+	git update-ref refs/tags/bad $tag &&
+	test_when_finished "git update-ref -d refs/tags/bad" &&
+	test_must_fail git -c fsck.extraHeaderEntry=error fsck --tags 2>out &&
+	test_grep "error in tag $tag.*invalid format - extra header" out
+'
+
 test_expect_success 'cleaned up' '
 	git fsck >actual 2>&1 &&
 	test_must_be_empty actual
diff --git a/t/t1461-refs-list.sh b/t/t1461-refs-list.sh
new file mode 100755
index 0000000..36e3d81
--- /dev/null
+++ b/t/t1461-refs-list.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+test_description='git refs list tests'
+
+. ./test-lib.sh
+
+git_for_each_ref='git refs list'
+. "$TEST_DIRECTORY"/for-each-ref-tests.sh
diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
new file mode 100755
index 0000000..349453c
--- /dev/null
+++ b/t/t1462-refs-exists.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+test_description='refs exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+git_show_ref_exists='git refs exists'
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
diff --git a/t/t1463-refs-optimize.sh b/t/t1463-refs-optimize.sh
new file mode 100755
index 0000000..9afe3c1
--- /dev/null
+++ b/t/t1463-refs-optimize.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+test_description='git refs optimize should not change the branch semantic
+
+This test runs git refs optimize and git show-ref and checks that the branch
+semantic is still the same.
+'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_DEFAULT_REF_FORMAT=files
+export GIT_TEST_DEFAULT_REF_FORMAT
+
+. ./test-lib.sh
+
+pack_refs='refs optimize'
+. "$TEST_DIRECTORY"/pack-refs-tests.sh
+
+test_done
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 58a4583..7739ab6 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -207,6 +207,40 @@
 	grep "unknown mode for --show-object-format: squeamish-ossifrage" err
 '
 
+
+test_expect_success 'rev-parse --show-object-format in repo with compat mode' '
+	mkdir repo &&
+	(
+		sane_unset GIT_DEFAULT_HASH &&
+		cd repo &&
+		git init --object-format=sha256 &&
+		git config extensions.compatobjectformat sha1 &&
+		echo sha256 >expect &&
+		git rev-parse --show-object-format >actual &&
+		test_cmp expect actual &&
+		git rev-parse --show-object-format=storage >actual &&
+		test_cmp expect actual &&
+		git rev-parse --show-object-format=input >actual &&
+		test_cmp expect actual &&
+		git rev-parse --show-object-format=output >actual &&
+		test_cmp expect actual &&
+		echo sha1 >expect &&
+		git rev-parse --show-object-format=compat >actual &&
+		test_cmp expect actual &&
+		test_must_fail git rev-parse --show-object-format=squeamish-ossifrage 2>err &&
+		grep "unknown mode for --show-object-format: squeamish-ossifrage" err
+	) &&
+	mkdir repo2 &&
+	(
+		sane_unset GIT_DEFAULT_HASH &&
+		cd repo2 &&
+		git init --object-format=sha256 &&
+		echo >expect &&
+		git rev-parse --show-object-format=compat >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_expect_success 'rev-parse --show-ref-format' '
 	test_detect_ref_format >expect &&
 	git rev-parse --show-ref-format >actual &&
diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh
index 8f59b86..c824c1a 100755
--- a/t/t1517-outside-repo.sh
+++ b/t/t1517-outside-repo.sh
@@ -107,18 +107,46 @@
 	test_grep "^error: remote-curl" actual
 '
 
-test_expect_success 'update-server-info does not crash with -h' '
-	test_expect_code 129 git update-server-info -h >usage &&
-	test_grep "[Uu]sage: git update-server-info " usage &&
-	test_expect_code 129 nongit git update-server-info -h >usage &&
-	test_grep "[Uu]sage: git update-server-info " usage
-'
+for cmd in $(git --list-cmds=main)
+do
+	cmd=${cmd%.*} # strip .sh, .perl, etc.
+	case "$cmd" in
+	archimport | citool | credential-netrc | credential-libsecret | \
+	credential-osxkeychain | cvsexportcommit | cvsimport | cvsserver | \
+	daemon | \
+	difftool--helper | filter-branch | fsck-objects | get-tar-commit-id | \
+	gui | gui--askpass | \
+	http-backend | http-fetch | http-push | init-db | \
+	merge-octopus | merge-one-file | merge-resolve | mergetool | \
+	mktag | p4 | p4.py | pickaxe | remote-ftp | remote-ftps | \
+	remote-http | remote-https | replay | send-email | \
+	sh-i18n--envsubst | shell | show | stage | submodule | svn | \
+	upload-archive--writer | upload-pack | web--browse | whatchanged)
+		expect_outcome=expect_failure ;;
+	*)
+		expect_outcome=expect_success ;;
+	esac
+	case "$cmd" in
+	instaweb)
+		prereq=PERL ;;
+	*)
+		prereq= ;;
+	esac
+	test_$expect_outcome $prereq "'git $cmd -h' outside a repository" '
+		test_expect_code 129 nongit git $cmd -h >usage &&
+		test_grep "[Uu]sage: git $cmd " usage
+	'
+	test_$expect_outcome $prereq "'git $cmd --help-all' outside a repository" '
+		test_expect_code 129 nongit git $cmd --help-all >usage &&
+		test_grep "[Uu]sage: git $cmd " usage
+	'
+done
 
-test_expect_success 'prune does not crash with -h' '
-	test_expect_code 129 git prune -h >usage &&
-	test_grep "[Uu]sage: git prune " usage &&
-	test_expect_code 129 nongit git prune -h >usage &&
-	test_grep "[Uu]sage: git prune " usage
+test_expect_success 'fmt-merge-msg does not crash with -h' '
+	test_expect_code 129 git fmt-merge-msg -h >usage &&
+	test_grep "[Uu]sage: git fmt-merge-msg " usage &&
+	test_expect_code 129 nongit git fmt-merge-msg -h >usage &&
+	test_grep "[Uu]sage: git fmt-merge-msg " usage
 '
 
 test_done
diff --git a/t/t1900-repo.sh b/t/t1900-repo.sh
new file mode 100755
index 0000000..2beba67
--- /dev/null
+++ b/t/t1900-repo.sh
@@ -0,0 +1,113 @@
+#!/bin/sh
+
+test_description='test git repo-info'
+
+. ./test-lib.sh
+
+# Test whether a key-value pair is correctly returned
+#
+# Usage: test_repo_info <label> <init command> <repo_name> <key> <expected value>
+#
+# Arguments:
+#   label: the label of the test
+#   init_command: a command which creates a repository
+#   repo_name: the name of the repository that will be created in init_command
+#   key: the key of the field that is being tested
+#   expected_value: the value that the field should contain
+test_repo_info () {
+	label=$1
+	init_command=$2
+	repo_name=$3
+	key=$4
+	expected_value=$5
+
+	test_expect_success "setup: $label" '
+		eval "$init_command $repo_name"
+	'
+
+	test_expect_success "keyvalue: $label" '
+		echo "$key=$expected_value" > expect &&
+		git -C "$repo_name" repo info "$key" >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "nul: $label" '
+		printf "%s\n%s\0" "$key" "$expected_value" >expect &&
+		git -C "$repo_name" repo info --format=nul "$key" >actual &&
+		test_cmp_bin expect actual
+	'
+}
+
+test_repo_info 'ref format files is retrieved correctly' \
+	'git init --ref-format=files' 'format-files' 'references.format' 'files'
+
+test_repo_info 'ref format reftable is retrieved correctly' \
+	'git init --ref-format=reftable' 'format-reftable' 'references.format' 'reftable'
+
+test_repo_info 'bare repository = false is retrieved correctly' \
+	'git init' 'nonbare' 'layout.bare' 'false'
+
+test_repo_info 'bare repository = true is retrieved correctly' \
+	'git init --bare' 'bare' 'layout.bare' 'true'
+
+test_repo_info 'shallow repository = false is retrieved correctly' \
+	'git init' 'nonshallow' 'layout.shallow' 'false'
+
+test_expect_success 'setup remote' '
+	git init remote &&
+	echo x >remote/x &&
+	git -C remote add x &&
+	git -C remote commit -m x
+'
+
+test_repo_info 'shallow repository = true is retrieved correctly' \
+	'git clone --depth 1 "file://$PWD/remote"' 'shallow' 'layout.shallow' 'true'
+
+test_repo_info 'object.format = sha1 is retrieved correctly' \
+	'git init --object-format=sha1' 'sha1' 'object.format' 'sha1'
+
+test_repo_info 'object.format = sha256 is retrieved correctly' \
+	'git init --object-format=sha256' 'sha256' 'object.format' 'sha256'
+
+test_expect_success 'values returned in order requested' '
+	cat >expect <<-\EOF &&
+	layout.bare=false
+	references.format=files
+	layout.bare=false
+	EOF
+	git init --ref-format=files ordered &&
+	git -C ordered repo info layout.bare references.format layout.bare >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'git-repo-info fails if an invalid key is requested' '
+	echo "error: key ${SQ}foo${SQ} not found" >expect &&
+	test_must_fail git repo info foo 2>actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'git-repo-info outputs data even if there is an invalid field' '
+	echo "references.format=$(test_detect_ref_format)" >expect &&
+	test_must_fail git repo info foo references.format bar >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'git-repo-info aborts when requesting an invalid format' '
+	echo "fatal: invalid format ${SQ}foo${SQ}" >expect &&
+	test_must_fail git repo info --format=foo 2>actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '-z uses nul-terminated format' '
+	printf "layout.bare\nfalse\0layout.shallow\nfalse\0" >expected &&
+	git repo info -z layout.bare layout.shallow >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'git repo info uses the last requested format' '
+	echo "layout.bare=false" >expected &&
+	git repo info --format=nul -z --format=keyvalue layout.bare >actual &&
+	test_cmp expected actual
+'
+
+test_done
diff --git a/t/t1901-repo-structure.sh b/t/t1901-repo-structure.sh
new file mode 100755
index 0000000..36a71a1
--- /dev/null
+++ b/t/t1901-repo-structure.sh
@@ -0,0 +1,129 @@
+#!/bin/sh
+
+test_description='test git repo structure'
+
+. ./test-lib.sh
+
+test_expect_success 'empty repository' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		cat >expect <<-\EOF &&
+		| Repository structure | Value |
+		| -------------------- | ----- |
+		| * References         |       |
+		|   * Count            |     0 |
+		|     * Branches       |     0 |
+		|     * Tags           |     0 |
+		|     * Remotes        |     0 |
+		|     * Others         |     0 |
+		|                      |       |
+		| * Reachable objects  |       |
+		|   * Count            |     0 |
+		|     * Commits        |     0 |
+		|     * Trees          |     0 |
+		|     * Blobs          |     0 |
+		|     * Tags           |     0 |
+		EOF
+
+		git repo structure >out 2>err &&
+
+		test_cmp expect out &&
+		test_line_count = 0 err
+	)
+'
+
+test_expect_success 'repository with references and objects' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit_bulk 42 &&
+		git tag -a foo -m bar &&
+
+		oid="$(git rev-parse HEAD)" &&
+		git update-ref refs/remotes/origin/foo "$oid" &&
+
+		# Also creates a commit, tree, and blob.
+		git notes add -m foo &&
+
+		cat >expect <<-\EOF &&
+		| Repository structure | Value |
+		| -------------------- | ----- |
+		| * References         |       |
+		|   * Count            |     4 |
+		|     * Branches       |     1 |
+		|     * Tags           |     1 |
+		|     * Remotes        |     1 |
+		|     * Others         |     1 |
+		|                      |       |
+		| * Reachable objects  |       |
+		|   * Count            |   130 |
+		|     * Commits        |    43 |
+		|     * Trees          |    43 |
+		|     * Blobs          |    43 |
+		|     * Tags           |     1 |
+		EOF
+
+		git repo structure >out 2>err &&
+
+		test_cmp expect out &&
+		test_line_count = 0 err
+	)
+'
+
+test_expect_success 'keyvalue and nul format' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit_bulk 42 &&
+		git tag -a foo -m bar &&
+
+		cat >expect <<-\EOF &&
+		references.branches.count=1
+		references.tags.count=1
+		references.remotes.count=0
+		references.others.count=0
+		objects.commits.count=42
+		objects.trees.count=42
+		objects.blobs.count=42
+		objects.tags.count=1
+		EOF
+
+		git repo structure --format=keyvalue >out 2>err &&
+
+		test_cmp expect out &&
+		test_line_count = 0 err &&
+
+		# Replace key and value delimiters for nul format.
+		tr "\n=" "\0\n" <expect >expect_nul &&
+		git repo structure --format=nul >out 2>err &&
+
+		test_cmp expect_nul out &&
+		test_line_count = 0 err
+	)
+'
+
+test_expect_success 'progress meter option' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit foo &&
+
+		GIT_PROGRESS_DELAY=0 git repo structure --progress >out 2>err &&
+
+		test_file_not_empty out &&
+		test_grep "Counting references: 2, done." err &&
+		test_grep "Counting objects: 3, done." err &&
+
+		GIT_PROGRESS_DELAY=0 git repo structure --no-progress >out 2>err &&
+
+		test_file_not_empty out &&
+		test_line_count = 0 err
+	)
+'
+
+test_done
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 3da8241..655bb1a 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -235,6 +235,8 @@
 match 1 1 1 1 'foo*' 'foo\*'
 match 0 0 0 0 foobar 'foo\*bar'
 match 1 1 1 1 'f\oo' 'f\\oo'
+match 0 0 0 0 \
+      1 1 1 1 'foo\' 'foo\'
 match 1 1 1 1 ball '*[al]?'
 match 0 0 0 0 ten '[ten]'
 match 1 1 1 1 ten '**[!te]'
diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index e091df6..1e812df 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -707,7 +707,7 @@
 	! grep "note" 0000-*
 '
 
-test_expect_success 'format-patch --notes=custom --range-diff only compares custom notes' '
+test_expect_success 'format-patch --notes=custom --range-diff --cover-letter only compares custom notes' '
 	test_when_finished "git notes remove topic unmodified || :" &&
 	git notes add -m "topic note" topic &&
 	git notes add -m "unmodified note" unmodified &&
@@ -721,6 +721,20 @@
 	! grep "## Notes ##" 0000-*
 '
 
+# --range-diff on a single commit requires --no-cover-letter
+test_expect_success 'format-patch --notes=custom --range-diff on single commit only compares custom notes' '
+	test_when_finished "git notes remove HEAD unmodified || :" &&
+	git notes add -m "topic note" HEAD &&
+	test_when_finished "git notes --ref=custom remove HEAD unmodified || :" &&
+	git notes add -m "unmodified note" unmodified &&
+	git notes --ref=custom add -m "topic note (custom)" HEAD &&
+	git notes --ref=custom add -m "unmodified note (custom)" unmodified &&
+	git format-patch --notes=custom --range-diff=$prev \
+		-1 --stdout >actual &&
+	test_grep "## Notes (custom) ##" actual &&
+	test_grep ! "## Notes ##" actual
+'
+
 test_expect_success 'format-patch --range-diff with --no-notes' '
 	test_when_finished "git notes remove topic unmodified || :" &&
 	git notes add -m "topic note" topic &&
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 34d6ad0..e778dd8 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1176,7 +1176,7 @@
 	test B = $(git cat-file commit HEAD^ | sed -ne \$p)
 '
 
-test_expect_success 'rebase -i respects core.commentchar=auto' '
+test_expect_success !WITH_BREAKING_CHANGES 'rebase -i respects core.commentchar=auto' '
 	test_config core.commentchar auto &&
 	write_script copy-edit-script.sh <<-\EOF &&
 	cp "$1" edit-script
@@ -1184,8 +1184,23 @@
 	test_when_finished "git rebase --abort || :" &&
 	(
 		test_set_editor "$(pwd)/copy-edit-script.sh" &&
-		git rebase -i HEAD^
+		git rebase -i HEAD^ 2>err
 	) &&
+	sed -n "s/^hint: *\$//p; s/^hint: //p; s/^warning: //p" err >actual &&
+	cat >expect <<-EOF &&
+	Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0
+
+	To use the default comment string (#) please run
+
+	    git config unset core.commentChar
+
+	To set a custom comment string please run
+
+	    git config set core.commentChar <comment string>
+
+	where ${SQ}<comment string>${SQ} is the string you wish to use.
+	EOF
+	test_cmp expect actual &&
 	test -z "$(grep -ve "^#" -e "^\$" -e "^pick" edit-script)"
 '
 
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index b8a8dd7..f9b8999 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -328,7 +328,7 @@
 	test_expect_code 129 git rebase --edit-todo --no-reschedule-failed-exec
 '
 
-test_expect_success 'no change in comment character due to conflicts markers with core.commentChar=auto' '
+test_expect_success !WITH_BREAKING_CHANGES 'no change in comment character due to conflicts markers with core.commentChar=auto' '
 	git checkout -b branch-a &&
 	test_commit A F1 &&
 	git checkout -b branch-b HEAD^ &&
diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh
index 58b3759..cf3aacf 100755
--- a/t/t3650-replay-basics.sh
+++ b/t/t3650-replay-basics.sh
@@ -52,7 +52,7 @@
 '
 
 test_expect_success 'using replay to rebase two branches, one on top of other' '
-	git replay --onto main topic1..topic2 >result &&
+	git replay --ref-action=print --onto main topic1..topic2 >result &&
 
 	test_line_count = 1 result &&
 
@@ -68,7 +68,7 @@
 '
 
 test_expect_success 'using replay on bare repo to rebase two branches, one on top of other' '
-	git -C bare replay --onto main topic1..topic2 >result-bare &&
+	git -C bare replay --ref-action=print --onto main topic1..topic2 >result-bare &&
 	test_cmp expect result-bare
 '
 
@@ -86,7 +86,7 @@
 	# 2nd field of result is refs/heads/main vs. refs/heads/topic2
 	# 4th field of result is hash for main instead of hash for topic2
 
-	git replay --advance main topic1..topic2 >result &&
+	git replay --ref-action=print --advance main topic1..topic2 >result &&
 
 	test_line_count = 1 result &&
 
@@ -102,7 +102,7 @@
 '
 
 test_expect_success 'using replay on bare repo to perform basic cherry-pick' '
-	git -C bare replay --advance main topic1..topic2 >result-bare &&
+	git -C bare replay --ref-action=print --advance main topic1..topic2 >result-bare &&
 	test_cmp expect result-bare
 '
 
@@ -115,7 +115,7 @@
 '
 
 test_expect_success 'using replay to also rebase a contained branch' '
-	git replay --contained --onto main main..topic3 >result &&
+	git replay --ref-action=print --contained --onto main main..topic3 >result &&
 
 	test_line_count = 2 result &&
 	cut -f 3 -d " " result >new-branch-tips &&
@@ -139,12 +139,12 @@
 '
 
 test_expect_success 'using replay on bare repo to also rebase a contained branch' '
-	git -C bare replay --contained --onto main main..topic3 >result-bare &&
+	git -C bare replay --ref-action=print --contained --onto main main..topic3 >result-bare &&
 	test_cmp expect result-bare
 '
 
 test_expect_success 'using replay to rebase multiple divergent branches' '
-	git replay --onto main ^topic1 topic2 topic4 >result &&
+	git replay --ref-action=print --onto main ^topic1 topic2 topic4 >result &&
 
 	test_line_count = 2 result &&
 	cut -f 3 -d " " result >new-branch-tips &&
@@ -168,7 +168,7 @@
 '
 
 test_expect_success 'using replay on bare repo to rebase multiple divergent branches, including contained ones' '
-	git -C bare replay --contained --onto main ^main topic2 topic3 topic4 >result &&
+	git -C bare replay --ref-action=print --contained --onto main ^main topic2 topic3 topic4 >result &&
 
 	test_line_count = 4 result &&
 	cut -f 3 -d " " result >new-branch-tips &&
@@ -217,4 +217,101 @@
 		--onto rename-onto rename-onto..rename-from
 '
 
+test_expect_success 'default atomic behavior updates refs directly' '
+	# Use a separate branch to avoid contaminating topic2 for later tests
+	git branch test-atomic topic2 &&
+	test_when_finished "git branch -D test-atomic" &&
+
+	# Test default atomic behavior (no output, refs updated)
+	git replay --onto main topic1..test-atomic >output &&
+	test_must_be_empty output &&
+
+	# Verify ref was updated
+	git log --format=%s test-atomic >actual &&
+	test_write_lines E D M L B A >expect &&
+	test_cmp expect actual &&
+
+	# Verify reflog message includes SHA of onto commit
+	git reflog test-atomic -1 --format=%gs >reflog-msg &&
+	ONTO_SHA=$(git rev-parse main) &&
+	echo "replay --onto $ONTO_SHA" >expect-reflog &&
+	test_cmp expect-reflog reflog-msg
+'
+
+test_expect_success 'atomic behavior in bare repository' '
+	# Store original state for cleanup
+	START=$(git -C bare rev-parse topic2) &&
+	test_when_finished "git -C bare update-ref refs/heads/topic2 $START" &&
+
+	# Test atomic updates work in bare repo
+	git -C bare replay --onto main topic1..topic2 >output &&
+	test_must_be_empty output &&
+
+	# Verify ref was updated in bare repo
+	git -C bare log --format=%s topic2 >actual &&
+	test_write_lines E D M L B A >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'reflog message for --advance mode' '
+	# Store original state
+	START=$(git rev-parse main) &&
+	test_when_finished "git update-ref refs/heads/main $START" &&
+
+	# Test --advance mode reflog message
+	git replay --advance main topic1..topic2 >output &&
+	test_must_be_empty output &&
+
+	# Verify reflog message includes --advance and branch name
+	git reflog main -1 --format=%gs >reflog-msg &&
+	echo "replay --advance main" >expect-reflog &&
+	test_cmp expect-reflog reflog-msg
+'
+
+test_expect_success 'replay.refAction=print config option' '
+	# Store original state
+	START=$(git rev-parse topic2) &&
+	test_when_finished "git branch -f topic2 $START" &&
+
+	# Test with config set to print
+	test_config replay.refAction print &&
+	git replay --onto main topic1..topic2 >output &&
+	test_line_count = 1 output &&
+	test_grep "^update refs/heads/topic2 " output
+'
+
+test_expect_success 'replay.refAction=update config option' '
+	# Store original state
+	START=$(git rev-parse topic2) &&
+	test_when_finished "git branch -f topic2 $START" &&
+
+	# Test with config set to update
+	test_config replay.refAction update &&
+	git replay --onto main topic1..topic2 >output &&
+	test_must_be_empty output &&
+
+	# Verify ref was updated
+	git log --format=%s topic2 >actual &&
+	test_write_lines E D M L B A >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'command-line --ref-action overrides config' '
+	# Store original state
+	START=$(git rev-parse topic2) &&
+	test_when_finished "git branch -f topic2 $START" &&
+
+	# Set config to update but use --ref-action=print
+	test_config replay.refAction update &&
+	git replay --ref-action=print --onto main topic1..topic2 >output &&
+	test_line_count = 1 output &&
+	test_grep "^update refs/heads/topic2 " output
+'
+
+test_expect_success 'invalid replay.refAction value' '
+	test_config replay.refAction invalid &&
+	test_must_fail git replay --onto main topic1..topic2 2>error &&
+	test_grep "invalid.*replay.refAction.*value" error
+'
+
 test_done
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index df580a5..af93e53 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -388,6 +388,7 @@
 	test_must_fail git add empty >actual 2>&1 &&
 	cat >expect <<-EOF &&
 	error: '"'empty/'"' does not have a commit checked out
+	error: unable to index file '"'empty/'"'
 	fatal: adding files failed
 	EOF
 	test_cmp expect actual
@@ -541,6 +542,31 @@
 	)
 '
 
+test_expect_success 'cannot add a submodule of a different algorithm' '
+	git init --object-format=sha256 sha256 &&
+	(
+		cd sha256 &&
+		test_commit abc &&
+		git init --object-format=sha1 submodule &&
+		test_commit -C submodule def &&
+		test_must_fail git add submodule 2>err &&
+		test_grep "cannot add a submodule of a different hash algorithm" err &&
+		git ls-files --stage >entries &&
+		test_grep ! ^160000 entries
+	) &&
+	git init --object-format=sha1 sha1 &&
+	(
+		cd sha1 &&
+		test_commit abc &&
+		git init --object-format=sha256 submodule &&
+		test_commit -C submodule def &&
+		test_must_fail git add submodule 2>err &&
+		test_grep "cannot add a submodule of a different hash algorithm" err &&
+		git ls-files --stage >entries &&
+		test_grep ! ^160000 entries
+	)
+'
+
 test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' '
 	path="$(pwd)/BLUB" &&
 	touch "$path" &&
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index d9fe289..4285314 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -48,8 +48,8 @@
 	git add -N command &&
 	git diff command >expect &&
 	cat >>expect <<-EOF &&
-	(1/1) Stage addition [y,n,q,a,d,e,p,?]? Unknown command ${SQ}W${SQ} (use ${SQ}?${SQ} for help)
-	(1/1) Stage addition [y,n,q,a,d,e,p,?]?$SP
+	(1/1) Stage addition [y,n,q,a,d,e,p,P,?]? Unknown command ${SQ}W${SQ} (use ${SQ}?${SQ} for help)
+	(1/1) Stage addition [y,n,q,a,d,e,p,P,?]?$SP
 	EOF
 	git add -p -- command <command >actual 2>&1 &&
 	test_cmp expect actual
@@ -332,9 +332,9 @@
 	git -c core.filemode=true add -p >actual &&
 	sed -n "s/^\(([0-9/]*) Stage .*?\).*/\1/p" actual >actual.filtered &&
 	cat >expect <<-\EOF &&
-	(1/1) Stage deletion [y,n,q,a,d,p,?]?
-	(1/2) Stage mode change [y,n,q,a,d,j,J,g,/,p,?]?
-	(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]?
+	(1/1) Stage deletion [y,n,q,a,d,p,P,?]?
+	(1/2) Stage mode change [y,n,q,a,d,k,K,j,J,g,/,p,P,?]?
+	(2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]?
 	EOF
 	test_cmp expect actual.filtered
 '
@@ -521,13 +521,13 @@
 test_expect_success 'goto hunk 1 with "g 1"' '
 	test_when_finished "git reset" &&
 	tr _ " " >expect <<-EOF &&
-	(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? + 1:  -1,2 +1,3          +15
+	(2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]? + 1:  -1,2 +1,3          +15
 	_ 2:  -2,4 +3,8          +21
 	go to which hunk? @@ -1,2 +1,3 @@
 	_10
 	+15
 	_20
-	(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+	(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
 	EOF
 	test_write_lines s y g 1 | git add -p >actual &&
 	tail -n 7 <actual >actual.trimmed &&
@@ -540,7 +540,7 @@
 	_10
 	+15
 	_20
-	(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+	(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
 	EOF
 	test_write_lines s y g1 | git add -p >actual &&
 	tail -n 4 <actual >actual.trimmed &&
@@ -550,11 +550,11 @@
 test_expect_success 'navigate to hunk via regex /pattern' '
 	test_when_finished "git reset" &&
 	tr _ " " >expect <<-EOF &&
-	(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? @@ -1,2 +1,3 @@
+	(2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]? @@ -1,2 +1,3 @@
 	_10
 	+15
 	_20
-	(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+	(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
 	EOF
 	test_write_lines s y /1,2 | git add -p >actual &&
 	tail -n 5 <actual >actual.trimmed &&
@@ -567,7 +567,7 @@
 	_10
 	+15
 	_20
-	(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+	(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
 	EOF
 	test_write_lines s y / 1,2 | git add -p >actual &&
 	tail -n 4 <actual >actual.trimmed &&
@@ -579,11 +579,11 @@
 	tr _ " " >expect <<-EOF &&
 	+15
 	 20
-	(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? @@ -1,2 +1,3 @@
+	(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? @@ -1,2 +1,3 @@
 	 10
 	+15
 	 20
-	(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+	(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
 	EOF
 	test_write_lines s y g 1 p | git add -p >actual &&
 	tail -n 7 <actual >actual.trimmed &&
@@ -595,11 +595,11 @@
 	cat >expect <<-EOF &&
 	<GREEN>+<RESET><GREEN>15<RESET>
 	 20<RESET>
-	<BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>PAGER <CYAN>@@ -1,2 +1,3 @@<RESET>
+	<BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? <RESET>PAGER <CYAN>@@ -1,2 +1,3 @@<RESET>
 	PAGER  10<RESET>
 	PAGER <GREEN>+<RESET><GREEN>15<RESET>
 	PAGER  20<RESET>
-	<BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>
+	<BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? <RESET>
 	EOF
 	test_write_lines s y g 1 P |
 	(
@@ -796,21 +796,21 @@
 	<BLUE>+<RESET><BLUE>new<RESET>
 	<CYAN> more-context<RESET>
 	<BLUE>+<RESET><BLUE>another-one<RESET>
-	<YELLOW>(1/1) Stage this hunk [y,n,q,a,d,s,e,p,?]? <RESET><BOLD>Split into 2 hunks.<RESET>
+	<YELLOW>(1/1) Stage this hunk [y,n,q,a,d,s,e,p,P,?]? <RESET><BOLD>Split into 2 hunks.<RESET>
 	<MAGENTA>@@ -1,3 +1,3 @@<RESET>
 	<CYAN> context<RESET>
 	<BOLD>-old<RESET>
 	<BLUE>+<RESET><BLUE>new<RESET>
 	<CYAN> more-context<RESET>
-	<YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET><MAGENTA>@@ -3 +3,2 @@<RESET>
+	<YELLOW>(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? <RESET><MAGENTA>@@ -3 +3,2 @@<RESET>
 	<CYAN> more-context<RESET>
 	<BLUE>+<RESET><BLUE>another-one<RESET>
-	<YELLOW>(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET>
+	<YELLOW>(2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET>
 	<CYAN> context<RESET>
 	<BOLD>-old<RESET>
 	<BLUE>+new<RESET>
 	<CYAN> more-context<RESET>
-	<YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>
+	<YELLOW>(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? <RESET>
 	EOF
 	test_cmp expect actual
 '
@@ -1354,4 +1354,92 @@
 	'
 done
 
+test_expect_success 'splitting previous hunk marks split hunks as undecided' '
+	test_write_lines a " " b c d e f g h i j k >file &&
+	git add file &&
+	test_write_lines x " " b y d e f g h i j x >file &&
+	test_write_lines n K s n y q | git add -p file &&
+	git cat-file blob :file >actual &&
+	test_write_lines a " " b y d e f g h i j k >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'splitting edited hunk' '
+	# Before the first hunk is edited it can be split into two
+	# hunks, after editing it can be split into three hunks.
+
+	write_script fake-editor.sh <<-\EOF &&
+	sed "s/^ c/-c/" "$1" >"$1.tmp" &&
+	mv "$1.tmp" "$1"
+	EOF
+
+	test_write_lines a b c d e f g h i j k l m n >file &&
+	git add file &&
+	test_write_lines A b c d E f g h i j k l M n >file &&
+	(
+		test_set_editor "$(pwd)/fake-editor.sh" &&
+		test_write_lines e K s j y n y q | git add -p file
+	) &&
+	git cat-file blob :file >actual &&
+	test_write_lines a b d e f g h i j k l M n >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'options J, K roll over' '
+	test_write_lines a b c d e f g h i >file &&
+	git add file &&
+	test_write_lines X b c d e f g h X >file &&
+	test_write_lines J J K q | git add -p >out &&
+	test_write_lines 1 2 1 2 >expect &&
+	sed -n -e "s-/.*--" -e "s/^(//p" <out >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'options y, n, a, d, j, k, e roll over to next undecided (1)' '
+	test_write_lines a b c d e f g h i j k l m n o p q >file &&
+	git add file &&
+	test_write_lines X b c d e f g h X j k l m n o p X >file &&
+	test_set_editor : &&
+	test_write_lines g3 y g3 n g3 a g3 d g3 j g3 e k q | git add -p >out &&
+	test_write_lines 1  3 1  3 1  3 1  3 1  3 1  3 1 2 >expect &&
+	sed -n -e "s-/.*--" -e "s/^(//p" <out >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'options y, n, a, d, j, k, e roll over to next undecided (2)' '
+	test_write_lines a b c d e f g h i j k l m n o p q >file &&
+	git add file &&
+	test_write_lines X b c d e f g h X j k l m n o p X >file &&
+	test_set_editor : &&
+	test_write_lines y g3 y g3 n g3 a g3 d g3 j g3 e g1 k q | git add -p >out &&
+	test_write_lines 1 2  3 2  3 2  3 2  3 2  3 2  3 2  1 2 >expect &&
+	sed -n -e "s-/.*--" -e "s/^(//p" <out >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'invalid option s is rejected' '
+	test_write_lines a b c d e f g h i j k >file &&
+	git add file &&
+	test_write_lines X b X d e f g h i j X >file &&
+	test_write_lines j s q | git add -p >out &&
+	sed -ne "s/ @@.*//" -e "s/ \$//" -e "/^(/p" <out >actual &&
+	cat >expect <<-EOF &&
+	(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,s,e,p,P,?]?
+	(2/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? Sorry, cannot split this hunk
+	(2/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'EOF quits' '
+	echo a >file &&
+	echo a >file2 &&
+	git add file file2 &&
+	echo X >file &&
+	echo X >file2 &&
+	git add -p </dev/null >out &&
+	test_grep file out &&
+	test_grep ! file2 out
+'
+
 test_done
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 0bb4648..7087994 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -902,6 +902,7 @@
 
 test_expect_success 'apply: show same status as git status (relative to ./)' '
 	git stash clear &&
+	mkdir -p subdir &&
 	echo 1 >subdir/subfile1 &&
 	echo 2 >subdir/subfile2 &&
 	git add subdir/subfile1 &&
@@ -1356,6 +1357,7 @@
 
 test_expect_success 'stash -- <subdir> leaves untracked files in subdir intact' '
 	git reset &&
+	mkdir -p subdir &&
 	>subdir/untracked &&
 	>subdir/tracked1 &&
 	>subdir/tracked2 &&
@@ -1372,6 +1374,7 @@
 
 test_expect_success 'stash -- <subdir> works with binary files' '
 	git reset &&
+	mkdir -p subdir &&
 	>subdir/untracked &&
 	>subdir/tracked &&
 	cp "$TEST_DIRECTORY"/test-binary-1.png subdir/tracked-binary &&
@@ -1741,4 +1744,50 @@
 	)
 '
 
+test_expect_success SANITIZE_LEAK 'stash show handles -- without leaking' '
+	git stash show --
+'
+
+test_expect_success 'controlled error return on unrecognized option' '
+	test_expect_code 129 git stash show -p --invalid 2>usage &&
+	grep -e "^usage: git stash show" usage
+'
+
+test_expect_success 'stash.index=true implies --index' '
+	# setup for a few related tests
+	test_commit file base &&
+	echo index >file &&
+	git add file &&
+	echo working >file &&
+	git stash &&
+
+	test_when_finished "git reset --hard" &&
+	git -c stash.index=true stash apply &&
+	echo index >expect &&
+	git show :0:file >actual &&
+	test_cmp expect actual &&
+	echo working >expect &&
+	test_cmp expect file
+'
+
+test_expect_success 'stash.index=true overridden by --no-index' '
+	test_when_finished "git reset --hard" &&
+	git -c stash.index=true stash apply --no-index &&
+	echo base >expect &&
+	git show :0:file >actual &&
+	test_cmp expect actual &&
+	echo working >expect &&
+	test_cmp expect file
+'
+
+test_expect_success 'stash.index=false overridden by --index' '
+	test_when_finished "git reset --hard" &&
+	git -c stash.index=false stash apply --index &&
+	echo index >expect &&
+	git show :0:file >actual &&
+	test_cmp expect actual &&
+	echo working >expect &&
+	test_cmp expect file
+'
+
 test_done
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index 1289ae3..7704709 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -87,7 +87,6 @@
 
 test_expect_success 'clean up untracked/untracked file to prepare for next tests' '
 	git clean --force --quiet
-
 '
 
 test_expect_success 'stash pop after save --include-untracked leaves files untracked again' '
diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh
index e8faf0d..3fc81bc 100755
--- a/t/t4007-rename-3.sh
+++ b/t/t4007-rename-3.sh
@@ -41,6 +41,16 @@
 	compare_diff_raw current expected
 '
 
+test_expect_success 'exit code of quiet copy detection' '
+	test_expect_code 1 \
+	git diff --quiet --cached --find-copies-harder $tree
+'
+
+test_expect_success 'exit code of quiet copy detection with --no-ext-diff' '
+	test_expect_code 1 \
+	git diff --quiet --cached --find-copies-harder --no-ext-diff $tree
+'
+
 # In the tree, there is only path0/COPYING.  In the cache, path0 and
 # path1 both have COPYING and the latter is a copy of path0/COPYING.
 # However when we say we care only about path1, we should just see
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index cfeec23..d35695f 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -5,7 +5,7 @@
 
 test_description='Various diff formatting options'
 
-GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./test-lib.sh
@@ -70,7 +70,7 @@
 	GIT_COMMITTER_DATE="2006-06-26 00:04:00 +0000" &&
 	export GIT_AUTHOR_DATE GIT_COMMITTER_DATE &&
 
-	git checkout master &&
+	git checkout main &&
 	git pull -s ours --no-rebase . side &&
 
 	GIT_AUTHOR_DATE="2006-06-26 00:05:00 +0000" &&
@@ -95,7 +95,7 @@
 	test_write_lines B A >dir/sub &&
 	git add dir/sub &&
 	git commit -m "Rearranged lines in dir/sub" &&
-	git checkout master &&
+	git checkout main &&
 
 	GIT_AUTHOR_DATE="2006-06-26 00:06:00 +0000" &&
 	GIT_COMMITTER_DATE="2006-06-26 00:06:00 +0000" &&
@@ -103,7 +103,7 @@
 	git checkout -b mode initial &&
 	git update-index --chmod=+x file0 &&
 	git commit -m "update mode" &&
-	git checkout -f master &&
+	git checkout -f main &&
 
 	GIT_AUTHOR_DATE="2006-06-26 00:06:00 +0000" &&
 	GIT_COMMITTER_DATE="2006-06-26 00:06:00 +0000" &&
@@ -112,12 +112,12 @@
 	git update-index --chmod=+x file2 &&
 	git commit -m "update mode (file2)" &&
 	git notes add -m "note" &&
-	git checkout -f master &&
+	git checkout -f main &&
 
-	# Same merge as master, but with parents reversed. Hide it in a
+	# Same merge as main, but with parents reversed. Hide it in a
 	# pseudo-ref to avoid impacting tests with --all.
 	commit=$(echo reverse |
-		 git commit-tree -p master^2 -p master^1 master^{tree}) &&
+		 git commit-tree -p main^2 -p main^1 main^{tree}) &&
 	git update-ref REVERSE $commit &&
 
 	git config diff.renames false &&
@@ -127,15 +127,15 @@
 
 : <<\EOF
 ! [initial] Initial
- * [master] Merge branch 'side'
+ * [main] Merge branch 'side'
   ! [rearrange] Rearranged lines in dir/sub
    ! [side] Side
 ----
   +  [rearrange] Rearranged lines in dir/sub
- -   [master] Merge branch 'side'
+ -   [main] Merge branch 'side'
  * + [side] Side
- *   [master^] Third
- *   [master~2] Second
+ *   [main^] Third
+ *   [main~2] Second
 +*++ [initial] Initial
 EOF
 
@@ -311,64 +311,64 @@
 diff-tree --stat initial mode
 diff-tree --summary initial mode
 
-diff-tree master
-diff-tree -m master
-diff-tree -p master
-diff-tree -p -m master
-diff-tree -c master
-diff-tree -c --abbrev master
-:noellipses diff-tree -c --abbrev master
-diff-tree --cc master
+diff-tree main
+diff-tree -m main
+diff-tree -p main
+diff-tree -p -m main
+diff-tree -c main
+diff-tree -c --abbrev main
+:noellipses diff-tree -c --abbrev main
+diff-tree --cc main
 # stat only should show the diffstat with the first parent
-diff-tree -c --stat master
-diff-tree --cc --stat master
-diff-tree -c --stat --summary master
-diff-tree --cc --stat --summary master
+diff-tree -c --stat main
+diff-tree --cc --stat main
+diff-tree -c --stat --summary main
+diff-tree --cc --stat --summary main
 # stat summary should show the diffstat and summary with the first parent
 diff-tree -c --stat --summary side
 diff-tree --cc --stat --summary side
-diff-tree --cc --shortstat master
+diff-tree --cc --shortstat main
 diff-tree --cc --summary REVERSE
 # improved by Timo's patch
-diff-tree --cc --patch-with-stat master
+diff-tree --cc --patch-with-stat main
 # improved by Timo's patch
-diff-tree --cc --patch-with-stat --summary master
+diff-tree --cc --patch-with-stat --summary main
 # this is correct
 diff-tree --cc --patch-with-stat --summary side
 
-log master
-log -p master
-log --root master
-log --root -p master
-log --patch-with-stat master
-log --root --patch-with-stat master
-log --root --patch-with-stat --summary master
+log main
+log -p main
+log --root main
+log --root -p main
+log --patch-with-stat main
+log --root --patch-with-stat main
+log --root --patch-with-stat --summary main
 # improved by Timo's patch
-log --root -c --patch-with-stat --summary master
+log --root -c --patch-with-stat --summary main
 # improved by Timo's patch
-log --root --cc --patch-with-stat --summary master
-log --no-diff-merges -p --first-parent master
-log --diff-merges=off -p --first-parent master
-log --first-parent --diff-merges=off -p master
-log -p --first-parent master
-log -p --diff-merges=first-parent master
-log --diff-merges=first-parent master
-log -m -p --first-parent master
-log -m -p master
-log --cc -m -p master
-log -c -m -p master
-log -m --raw master
-log -m --stat master
-log -SF master
-log -S F master
-log -SF -p master
-log -SF master --max-count=0
-log -SF master --max-count=1
-log -SF master --max-count=2
-log -GF master
-log -GF -p master
-log -GF -p --pickaxe-all master
-log -IA -IB -I1 -I2 -p master
+log --root --cc --patch-with-stat --summary main
+log --no-diff-merges -p --first-parent main
+log --diff-merges=off -p --first-parent main
+log --first-parent --diff-merges=off -p main
+log -p --first-parent main
+log -p --diff-merges=first-parent main
+log --diff-merges=first-parent main
+log -m -p --first-parent main
+log -m -p main
+log --cc -m -p main
+log -c -m -p main
+log -m --raw main
+log -m --stat main
+log -SF main
+log -S F main
+log -SF -p main
+log -SF main --max-count=0
+log -SF main --max-count=1
+log -SF main --max-count=2
+log -GF main
+log -GF -p main
+log -GF -p --pickaxe-all main
+log -IA -IB -I1 -I2 -p main
 log --decorate --all
 log --decorate=full --all
 log --decorate --clear-decorations --all
@@ -377,35 +377,35 @@
 rev-list --parents HEAD
 rev-list --children HEAD
 
-whatchanged master
-:noellipses whatchanged master
-whatchanged -p master
-whatchanged --root master
-:noellipses whatchanged --root master
-whatchanged --root -p master
-whatchanged --patch-with-stat master
-whatchanged --root --patch-with-stat master
-whatchanged --root --patch-with-stat --summary master
+whatchanged main
+:noellipses whatchanged main
+whatchanged -p main
+whatchanged --root main
+:noellipses whatchanged --root main
+whatchanged --root -p main
+whatchanged --patch-with-stat main
+whatchanged --root --patch-with-stat main
+whatchanged --root --patch-with-stat --summary main
 # improved by Timo's patch
-whatchanged --root -c --patch-with-stat --summary master
+whatchanged --root -c --patch-with-stat --summary main
 # improved by Timo's patch
-whatchanged --root --cc --patch-with-stat --summary master
-whatchanged -SF master
-:noellipses whatchanged -SF master
-whatchanged -SF -p master
+whatchanged --root --cc --patch-with-stat --summary main
+whatchanged -SF main
+:noellipses whatchanged -SF main
+whatchanged -SF -p main
 
-log --patch-with-stat master -- dir/
-whatchanged --patch-with-stat master -- dir/
-log --patch-with-stat --summary master -- dir/
-whatchanged --patch-with-stat --summary master -- dir/
+log --patch-with-stat main -- dir/
+whatchanged --patch-with-stat main -- dir/
+log --patch-with-stat --summary main -- dir/
+whatchanged --patch-with-stat --summary main -- dir/
 
 show initial
 show --root initial
 show side
-show master
-show -c master
-show -m master
-show --first-parent master
+show main
+show -c main
+show -m main
+show --first-parent main
 show --stat side
 show --stat --summary side
 show --patch-with-stat side
@@ -414,22 +414,22 @@
 show --patch-with-stat --summary side
 
 format-patch --stdout initial..side
-format-patch --stdout initial..master^
-format-patch --stdout initial..master
-format-patch --stdout --no-numbered initial..master
-format-patch --stdout --numbered initial..master
+format-patch --stdout initial..main^
+format-patch --stdout initial..main
+format-patch --stdout --no-numbered initial..main
+format-patch --stdout --numbered initial..main
 format-patch --attach --stdout initial..side
 format-patch --attach --stdout --suffix=.diff initial..side
-format-patch --attach --stdout initial..master^
-format-patch --attach --stdout initial..master
+format-patch --attach --stdout initial..main^
+format-patch --attach --stdout initial..main
 format-patch --inline --stdout initial..side
-format-patch --inline --stdout initial..master^
-format-patch --inline --stdout --numbered-files initial..master
-format-patch --inline --stdout initial..master
-format-patch --inline --stdout --subject-prefix=TESTCASE initial..master
+format-patch --inline --stdout initial..main^
+format-patch --inline --stdout --numbered-files initial..main
+format-patch --inline --stdout initial..main
+format-patch --inline --stdout --subject-prefix=TESTCASE initial..main
 config format.subjectprefix DIFFERENT_PREFIX
-format-patch --inline --stdout initial..master^^
-format-patch --stdout --cover-letter -n initial..master^
+format-patch --inline --stdout initial..main^^
+format-patch --stdout --cover-letter -n initial..main^
 
 diff --abbrev initial..side
 diff -U initial..side
@@ -448,13 +448,13 @@
 diff --no-index --name-status dir2 dir
 diff --no-index --name-status -- dir2 dir
 diff --no-index dir dir3
-diff master master^ side
+diff main main^ side
 # Can't use spaces...
-diff --line-prefix=abc master master^ side
-diff --dirstat master~1 master~2
+diff --line-prefix=abc main main^ side
+diff --dirstat main~1 main~2
 diff --dirstat initial rearrange
 diff --dirstat-by-file initial rearrange
-diff --dirstat --cc master~1 master
+diff --dirstat --cc main~1 main
 # No-index --abbrev and --no-abbrev
 diff --raw initial
 :noellipses diff --raw initial
@@ -482,7 +482,7 @@
 '
 
 test_expect_success 'log -m matches pure log' '
-	git log master >result &&
+	git log main >result &&
 	process_diffs result >expected &&
 	git log -m >result &&
 	process_diffs result >actual &&
@@ -490,17 +490,17 @@
 '
 
 test_expect_success 'log --diff-merges=on matches --diff-merges=separate' '
-	git log -p --diff-merges=separate master >result &&
+	git log -p --diff-merges=separate main >result &&
 	process_diffs result >expected &&
-	git log -p --diff-merges=on master >result &&
+	git log -p --diff-merges=on main >result &&
 	process_diffs result >actual &&
 	test_cmp expected actual
 '
 
 test_expect_success 'log --dd matches --diff-merges=1 -p' '
-	git log --diff-merges=1 -p master >result &&
+	git log --diff-merges=1 -p main >result &&
 	process_diffs result >expected &&
-	git log --dd master >result &&
+	git log --dd main >result &&
 	process_diffs result >actual &&
 	test_cmp expected actual
 '
@@ -511,19 +511,19 @@
 '
 
 test_expect_success 'git config log.diffMerges first-parent' '
-	git log -p --diff-merges=first-parent master >result &&
+	git log -p --diff-merges=first-parent main >result &&
 	process_diffs result >expected &&
 	test_config log.diffMerges first-parent &&
-	git log -p --diff-merges=on master >result &&
+	git log -p --diff-merges=on main >result &&
 	process_diffs result >actual &&
 	test_cmp expected actual
 '
 
 test_expect_success 'git config log.diffMerges first-parent vs -m' '
-	git log -p --diff-merges=first-parent master >result &&
+	git log -p --diff-merges=first-parent main >result &&
 	process_diffs result >expected &&
 	test_config log.diffMerges first-parent &&
-	git log -p -m master >result &&
+	git log -p -m main >result &&
 	process_diffs result >actual &&
 	test_cmp expected actual
 '
@@ -572,7 +572,7 @@
 	Third
 	Second
 	EOF
-	git rev-list master | git diff-tree --stdin --format=%s -s >actual &&
+	git rev-list main | git diff-tree --stdin --format=%s -s >actual &&
 	test_cmp expect actual
 '
 
@@ -585,16 +585,16 @@
 
 	dir/sub
 	EOF
-	git rev-list master^ |
+	git rev-list main^ |
 	git diff-tree -r --stdin --name-only --format=%s dir >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success 'show A B ... -- <pathspec>' '
 	# side touches dir/sub, file0, and file3
-	# master^ touches dir/sub, and file1
-	# master^^ touches dir/sub, file0, and file2
-	git show --name-only --format="<%s>" side master^ master^^ -- dir >actual &&
+	# main^ touches dir/sub, and file1
+	# main^^ touches dir/sub, file0, and file2
+	git show --name-only --format="<%s>" side main^ main^^ -- dir >actual &&
 	cat >expect <<-\EOF &&
 	<Side>
 
@@ -610,7 +610,7 @@
 '
 
 test_expect_success 'diff -I<regex>: setup' '
-	git checkout master &&
+	git checkout main &&
 	test_seq 50 >file0 &&
 	git commit -m "Set up -I<regex> test file" file0 &&
 	test_seq 50 | sed -e "s/13/ten and three/" -e "/7\$/d" >file0 &&
@@ -661,6 +661,43 @@
 	test_grep ! "file1" actual
 '
 
+test_expect_success 'diff -I<regex>: ignore all content changes' '
+	test_when_finished "git rm -f file1 file2 file3" &&
+	: >file1 &&
+	git add file1 &&
+	: >file2 &&
+	git add file2 &&
+	: >file3 &&
+	git add file3 &&
+
+	rm -f file1 file2 &&
+	mkdir file2 &&
+	echo "A" >file3 &&
+	A_hash=$(git hash-object -w file3) &&
+	echo "B" >file3 &&
+	B_hash=$(git hash-object -w file3) &&
+	cat <<-EOF | git update-index --index-info &&
+	100644 $A_hash 1	file3
+	100644 $B_hash 2	file3
+	EOF
+
+	test_diff_no_content_changes () {
+		git diff $1 --ignore-blank-lines -I".*" >actual &&
+		test_line_count = 3 actual &&
+		test_grep "file1" actual &&
+		test_grep "file2" actual &&
+		test_grep "file3" actual &&
+		test_grep ! "diff --git" actual
+	} &&
+	test_diff_no_content_changes "--raw" &&
+	test_diff_no_content_changes "--name-only" &&
+	test_diff_no_content_changes "--name-status" &&
+
+	: >actual &&
+	test_must_fail git diff --quiet -I".*" >actual &&
+	test_must_be_empty actual
+'
+
 # check_prefix <patch> <src> <dst>
 # check only lines with paths to avoid dependency on exact oid/contents
 check_prefix () {
diff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_main
similarity index 86%
rename from t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master
rename to t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_main
index 9951e36..af1cf20 100644
--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --patch-with-stat --summary master
+$ git diff-tree --cc --patch-with-stat --summary main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_main
similarity index 88%
rename from t/t4013/diff.diff-tree_--cc_--patch-with-stat_master
rename to t/t4013/diff.diff-tree_--cc_--patch-with-stat_main
index db3c0a7..0ec6042 100644
--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master
+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --patch-with-stat master
+$ git diff-tree --cc --patch-with-stat main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.diff-tree_--cc_--shortstat_master b/t/t4013/diff.diff-tree_--cc_--shortstat_main
similarity index 65%
rename from t/t4013/diff.diff-tree_--cc_--shortstat_master
rename to t/t4013/diff.diff-tree_--cc_--shortstat_main
index a4ca42d..9a4ef03 100644
--- a/t/t4013/diff.diff-tree_--cc_--shortstat_master
+++ b/t/t4013/diff.diff-tree_--cc_--shortstat_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --shortstat master
+$ git diff-tree --cc --shortstat main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
  2 files changed, 5 insertions(+)
 $
diff --git a/t/t4013/diff.diff-tree_--cc_--stat_master b/t/t4013/diff.diff-tree_--cc_--stat_--summary_main
similarity index 71%
copy from t/t4013/diff.diff-tree_--cc_--stat_master
copy to t/t4013/diff.diff-tree_--cc_--stat_--summary_main
index 40b9179..9db08a4 100644
--- a/t/t4013/diff.diff-tree_--cc_--stat_master
+++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --stat master
+$ git diff-tree --cc --stat --summary main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master
deleted file mode 100644
index d019867..0000000
--- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master
+++ /dev/null
@@ -1,6 +0,0 @@
-$ git diff-tree --cc --stat --summary master
-59d314ad6f356dd08601a4cd5e530381da3e3c64
- dir/sub | 2 ++
- file0   | 3 +++
- 2 files changed, 5 insertions(+)
-$
diff --git a/t/t4013/diff.diff-tree_-c_--stat_master b/t/t4013/diff.diff-tree_--cc_--stat_main
similarity index 76%
rename from t/t4013/diff.diff-tree_-c_--stat_master
rename to t/t4013/diff.diff-tree_--cc_--stat_main
index 89d59b1..7ecc67a 100644
--- a/t/t4013/diff.diff-tree_-c_--stat_master
+++ b/t/t4013/diff.diff-tree_--cc_--stat_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c --stat master
+$ git diff-tree --cc --stat main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.diff-tree_--cc_master b/t/t4013/diff.diff-tree_--cc_main
similarity index 91%
rename from t/t4013/diff.diff-tree_--cc_master
rename to t/t4013/diff.diff-tree_--cc_main
index 5ecb4e1..1a96285 100644
--- a/t/t4013/diff.diff-tree_--cc_master
+++ b/t/t4013/diff.diff-tree_--cc_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc master
+$ git diff-tree --cc main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
 diff --cc dir/sub
 index cead32e,7289e35..992913c
diff --git a/t/t4013/diff.diff-tree_-c_--abbrev_master b/t/t4013/diff.diff-tree_-c_--abbrev_main
similarity index 82%
rename from t/t4013/diff.diff-tree_-c_--abbrev_master
rename to t/t4013/diff.diff-tree_-c_--abbrev_main
index b8e4aa2..039d127 100644
--- a/t/t4013/diff.diff-tree_-c_--abbrev_master
+++ b/t/t4013/diff.diff-tree_-c_--abbrev_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c --abbrev master
+$ git diff-tree -c --abbrev main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
 ::100644 100644 100644 cead32e... 7289e35... 992913c... MM	dir/sub
 ::100644 100644 100644 b414108... f4615da... 10a8a9f... MM	file0
diff --git a/t/t4013/diff.diff-tree_--cc_--stat_master b/t/t4013/diff.diff-tree_-c_--stat_--summary_main
similarity index 72%
rename from t/t4013/diff.diff-tree_--cc_--stat_master
rename to t/t4013/diff.diff-tree_-c_--stat_--summary_main
index 40b9179..05a8d16 100644
--- a/t/t4013/diff.diff-tree_--cc_--stat_master
+++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --stat master
+$ git diff-tree -c --stat --summary main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.diff-tree_-c_--stat_--summary_master b/t/t4013/diff.diff-tree_-c_--stat_--summary_master
deleted file mode 100644
index 81c3021..0000000
--- a/t/t4013/diff.diff-tree_-c_--stat_--summary_master
+++ /dev/null
@@ -1,6 +0,0 @@
-$ git diff-tree -c --stat --summary master
-59d314ad6f356dd08601a4cd5e530381da3e3c64
- dir/sub | 2 ++
- file0   | 3 +++
- 2 files changed, 5 insertions(+)
-$
diff --git a/t/t4013/diff.diff-tree_-c_--stat_master b/t/t4013/diff.diff-tree_-c_--stat_main
similarity index 76%
copy from t/t4013/diff.diff-tree_-c_--stat_master
copy to t/t4013/diff.diff-tree_-c_--stat_main
index 89d59b1..61d9f45 100644
--- a/t/t4013/diff.diff-tree_-c_--stat_master
+++ b/t/t4013/diff.diff-tree_-c_--stat_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c --stat master
+$ git diff-tree -c --stat main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.diff-tree_-c_master b/t/t4013/diff.diff-tree_-c_main
similarity index 92%
rename from t/t4013/diff.diff-tree_-c_master
rename to t/t4013/diff.diff-tree_-c_main
index e2d2bb2..a84e118 100644
--- a/t/t4013/diff.diff-tree_-c_master
+++ b/t/t4013/diff.diff-tree_-c_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c master
+$ git diff-tree -c main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
 ::100644 100644 100644 cead32e925b1420c84c14cbf7cf755e7e45af8ad 7289e35bff32727c08dda207511bec138fdb9ea5 992913c5aa0a5476d10c49ed0f21fc0c6d1aedf3 MM	dir/sub
 ::100644 100644 100644 b414108e81e5091fe0974a1858b4d0d22b107f70 f4615da674c09df322d6ba8d6b21ecfb1b1ba510 10a8a9f3657f91a156b9f0184ed79a20adef9f7f MM	file0
diff --git a/t/t4013/diff.diff-tree_-m_master b/t/t4013/diff.diff-tree_-m_main
similarity index 96%
rename from t/t4013/diff.diff-tree_-m_master
rename to t/t4013/diff.diff-tree_-m_main
index 6d0a220..5da1f7f 100644
--- a/t/t4013/diff.diff-tree_-m_master
+++ b/t/t4013/diff.diff-tree_-m_main
@@ -1,4 +1,4 @@
-$ git diff-tree -m master
+$ git diff-tree -m main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
 :040000 040000 65f5c9dd60ce3b2b3324b618ac7accf8d912c113 0564e026437809817a64fff393079714b6dd4628 M	dir
 :100644 100644 b414108e81e5091fe0974a1858b4d0d22b107f70 10a8a9f3657f91a156b9f0184ed79a20adef9f7f M	file0
diff --git a/t/t4013/diff.diff-tree_-p_-m_master b/t/t4013/diff.diff-tree_-p_-m_main
similarity index 96%
rename from t/t4013/diff.diff-tree_-p_-m_master
rename to t/t4013/diff.diff-tree_-p_-m_main
index b60bea0..29c9fc2 100644
--- a/t/t4013/diff.diff-tree_-p_-m_master
+++ b/t/t4013/diff.diff-tree_-p_-m_main
@@ -1,4 +1,4 @@
-$ git diff-tree -p -m master
+$ git diff-tree -p -m main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
diff --git a/t/t4013/diff.diff-tree_-p_main b/t/t4013/diff.diff-tree_-p_main
new file mode 100644
index 0000000..c658062
--- /dev/null
+++ b/t/t4013/diff.diff-tree_-p_main
@@ -0,0 +1,2 @@
+$ git diff-tree -p main
+$
diff --git a/t/t4013/diff.diff-tree_-p_master b/t/t4013/diff.diff-tree_-p_master
deleted file mode 100644
index b182875..0000000
--- a/t/t4013/diff.diff-tree_-p_master
+++ /dev/null
@@ -1,2 +0,0 @@
-$ git diff-tree -p master
-$
diff --git a/t/t4013/diff.diff-tree_main b/t/t4013/diff.diff-tree_main
new file mode 100644
index 0000000..dc5b9fd
--- /dev/null
+++ b/t/t4013/diff.diff-tree_main
@@ -0,0 +1,2 @@
+$ git diff-tree main
+$
diff --git a/t/t4013/diff.diff-tree_master b/t/t4013/diff.diff-tree_master
deleted file mode 100644
index fe9226f..0000000
--- a/t/t4013/diff.diff-tree_master
+++ /dev/null
@@ -1,2 +0,0 @@
-$ git diff-tree master
-$
diff --git a/t/t4013/diff.diff_--dirstat_--cc_main~1_main b/t/t4013/diff.diff_--dirstat_--cc_main~1_main
new file mode 100644
index 0000000..168a357
--- /dev/null
+++ b/t/t4013/diff.diff_--dirstat_--cc_main~1_main
@@ -0,0 +1,3 @@
+$ git diff --dirstat --cc main~1 main
+  40.0% dir/
+$
diff --git a/t/t4013/diff.diff_--dirstat_--cc_master~1_master b/t/t4013/diff.diff_--dirstat_--cc_master~1_master
deleted file mode 100644
index fba4e34..0000000
--- a/t/t4013/diff.diff_--dirstat_--cc_master~1_master
+++ /dev/null
@@ -1,3 +0,0 @@
-$ git diff --dirstat --cc master~1 master
-  40.0% dir/
-$
diff --git a/t/t4013/diff.diff_--dirstat_main~1_main~2 b/t/t4013/diff.diff_--dirstat_main~1_main~2
new file mode 100644
index 0000000..6809733
--- /dev/null
+++ b/t/t4013/diff.diff_--dirstat_main~1_main~2
@@ -0,0 +1,3 @@
+$ git diff --dirstat main~1 main~2
+  40.0% dir/
+$
diff --git a/t/t4013/diff.diff_--dirstat_master~1_master~2 b/t/t4013/diff.diff_--dirstat_master~1_master~2
deleted file mode 100644
index b672e1c..0000000
--- a/t/t4013/diff.diff_--dirstat_master~1_master~2
+++ /dev/null
@@ -1,3 +0,0 @@
-$ git diff --dirstat master~1 master~2
-  40.0% dir/
-$
diff --git a/t/t4013/diff.diff_--line-prefix=abc_master_master^_side b/t/t4013/diff.diff_--line-prefix=abc_main_main^_side
similarity index 87%
rename from t/t4013/diff.diff_--line-prefix=abc_master_master^_side
rename to t/t4013/diff.diff_--line-prefix=abc_main_main^_side
index 99f91e7..67a2145 100644
--- a/t/t4013/diff.diff_--line-prefix=abc_master_master^_side
+++ b/t/t4013/diff.diff_--line-prefix=abc_main_main^_side
@@ -1,4 +1,4 @@
-$ git diff --line-prefix=abc master master^ side
+$ git diff --line-prefix=abc main main^ side
 abcdiff --cc dir/sub
 abcindex cead32e,7289e35..992913c
 abc--- a/dir/sub
diff --git a/t/t4013/diff.diff_master_master^_side b/t/t4013/diff.diff_main_main^_side
similarity index 89%
rename from t/t4013/diff.diff_master_master^_side
rename to t/t4013/diff.diff_main_main^_side
index 50ec9ca..ab81ec9 100644
--- a/t/t4013/diff.diff_master_master^_side
+++ b/t/t4013/diff.diff_main_main^_side
@@ -1,4 +1,4 @@
-$ git diff master master^ side
+$ git diff main main^ side
 diff --cc dir/sub
 index cead32e,7289e35..992913c
 --- a/dir/sub
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..main
similarity index 97%
rename from t/t4013/diff.format-patch_--attach_--stdout_initial..master
rename to t/t4013/diff.format-patch_--attach_--stdout_initial..main
index 52fedc1..9f56380 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --attach --stdout initial..master
+$ git format-patch --attach --stdout initial..main
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..main^
similarity index 97%
rename from t/t4013/diff.format-patch_--attach_--stdout_initial..master^
rename to t/t4013/diff.format-patch_--attach_--stdout_initial..main^
index 1c3cde2..80132ea 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..main^
@@ -1,4 +1,4 @@
-$ git format-patch --attach --stdout initial..master^
+$ git format-patch --attach --stdout initial..main^
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..main
similarity index 99%
rename from t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master
rename to t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..main
index 02c4db7..8e88909 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout --numbered-files initial..master
+$ git format-patch --inline --stdout --numbered-files initial..main
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..main
similarity index 99%
rename from t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
rename to t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..main
index c7677c5..d7d2b12 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout --subject-prefix=TESTCASE initial..master
+$ git format-patch --inline --stdout --subject-prefix=TESTCASE initial..main
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..main
similarity index 97%
rename from t/t4013/diff.format-patch_--inline_--stdout_initial..master
rename to t/t4013/diff.format-patch_--inline_--stdout_initial..main
index 5b3e34e..c49c423 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout initial..master
+$ git format-patch --inline --stdout initial..main
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main^
similarity index 97%
rename from t/t4013/diff.format-patch_--inline_--stdout_initial..master^
rename to t/t4013/diff.format-patch_--inline_--stdout_initial..main^
index d13f8a8..8669dbf 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main^
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout initial..master^
+$ git format-patch --inline --stdout initial..main^
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main^^
similarity index 95%
rename from t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
rename to t/t4013/diff.format-patch_--inline_--stdout_initial..main^^
index caec553..b749be5 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main^^
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout initial..master^^
+$ git format-patch --inline --stdout initial..main^^
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..main^
similarity index 96%
rename from t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^
rename to t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..main^
index 244d964..567f222 100644
--- a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^
+++ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..main^
@@ -1,4 +1,4 @@
-$ git format-patch --stdout --cover-letter -n initial..master^
+$ git format-patch --stdout --cover-letter -n initial..main^
 From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
 From: C O Mitter <committer@example.com>
 Date: Mon, 26 Jun 2006 00:06:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..main
similarity index 96%
rename from t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master
rename to t/t4013/diff.format-patch_--stdout_--no-numbered_initial..main
index bfc287a..195b62e 100644
--- a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master
+++ b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --stdout --no-numbered initial..master
+$ git format-patch --stdout --no-numbered initial..main
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--numbered_initial..main
similarity index 96%
rename from t/t4013/diff.format-patch_--stdout_--numbered_initial..master
rename to t/t4013/diff.format-patch_--stdout_--numbered_initial..main
index 568f6f5..0678a38 100644
--- a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master
+++ b/t/t4013/diff.format-patch_--stdout_--numbered_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --stdout --numbered initial..master
+$ git format-patch --stdout --numbered initial..main
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_initial..master b/t/t4013/diff.format-patch_--stdout_initial..main
similarity index 97%
rename from t/t4013/diff.format-patch_--stdout_initial..master
rename to t/t4013/diff.format-patch_--stdout_initial..main
index 5f0352f..b4a6302 100644
--- a/t/t4013/diff.format-patch_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--stdout_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --stdout initial..master
+$ git format-patch --stdout initial..main
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_initial..master^ b/t/t4013/diff.format-patch_--stdout_initial..main^
similarity index 96%
rename from t/t4013/diff.format-patch_--stdout_initial..master^
rename to t/t4013/diff.format-patch_--stdout_initial..main^
index 2ae454d..36b3221 100644
--- a/t/t4013/diff.format-patch_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--stdout_initial..main^
@@ -1,4 +1,4 @@
-$ git format-patch --stdout initial..master^
+$ git format-patch --stdout initial..main^
 From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
 From: A U Thor <author@example.com>
 Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.log_-m_-p_master b/t/t4013/diff.log_--cc_-m_-p_main
similarity index 98%
copy from t/t4013/diff.log_-m_-p_master
copy to t/t4013/diff.log_--cc_-m_-p_main
index 9ca62a0..f32746e 100644
--- a/t/t4013/diff.log_-m_-p_master
+++ b/t/t4013/diff.log_--cc_-m_-p_main
@@ -1,4 +1,4 @@
-$ git log -m -p master
+$ git log --cc -m -p main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--cc_-m_-p_master b/t/t4013/diff.log_--cc_-m_-p_master
deleted file mode 100644
index 7c217cf..0000000
--- a/t/t4013/diff.log_--cc_-m_-p_master
+++ /dev/null
@@ -1,200 +0,0 @@
-$ git log --cc -m -p master
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
-diff --git a/dir/sub b/dir/sub
-index cead32e..992913c 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -4,3 +4,5 @@ C
- D
- E
- F
-+1
-+2
-diff --git a/file0 b/file0
-index b414108..10a8a9f 100644
---- a/file0
-+++ b/file0
-@@ -4,3 +4,6 @@
- 4
- 5
- 6
-+A
-+B
-+C
-
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a)
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
-diff --git a/dir/sub b/dir/sub
-index 7289e35..992913c 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,4 +1,8 @@
- A
- B
-+C
-+D
-+E
-+F
- 1
- 2
-diff --git a/file0 b/file0
-index f4615da..10a8a9f 100644
---- a/file0
-+++ b/file0
-@@ -1,6 +1,9 @@
- 1
- 2
- 3
-+4
-+5
-+6
- A
- B
- C
-diff --git a/file1 b/file1
-new file mode 100644
-index 0000000..b1e6722
---- /dev/null
-+++ b/file1
-@@ -0,0 +1,3 @@
-+A
-+B
-+C
-diff --git a/file2 b/file2
-deleted file mode 100644
-index 01e79c3..0000000
---- a/file2
-+++ /dev/null
-@@ -1,3 +0,0 @@
--1
--2
--3
-diff --git a/file3 b/file3
-deleted file mode 100644
-index 7289e35..0000000
---- a/file3
-+++ /dev/null
-@@ -1,4 +0,0 @@
--A
--B
--1
--2
-
-commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:03:00 2006 +0000
-
-    Side
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..7289e35 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+1
-+2
-diff --git a/file0 b/file0
-index 01e79c3..f4615da 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+A
-+B
-+C
-diff --git a/file3 b/file3
-new file mode 100644
-index 0000000..7289e35
---- /dev/null
-+++ b/file3
-@@ -0,0 +1,4 @@
-+A
-+B
-+1
-+2
-
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-
-diff --git a/dir/sub b/dir/sub
-index 8422d40..cead32e 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -2,3 +2,5 @@ A
- B
- C
- D
-+E
-+F
-diff --git a/file1 b/file1
-new file mode 100644
-index 0000000..b1e6722
---- /dev/null
-+++ b/file1
-@@ -0,0 +1,3 @@
-+A
-+B
-+C
-
-commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:01:00 2006 +0000
-
-    Second
-    
-    This is the second commit.
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..8422d40 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+C
-+D
-diff --git a/file0 b/file0
-index 01e79c3..b414108 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+4
-+5
-+6
-diff --git a/file2 b/file2
-deleted file mode 100644
-index 01e79c3..0000000
---- a/file2
-+++ /dev/null
-@@ -1,3 +0,0 @@
--1
--2
--3
-
-commit 444ac553ac7612cc88969031b02b3767fb8a353a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:00:00 2006 +0000
-
-    Initial
-$
diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all
index 6b0b334..c099399 100644
--- a/t/t4013/diff.log_--decorate=full_--all
+++ b/t/t4013/diff.log_--decorate=full_--all
@@ -26,7 +26,7 @@
 
     Notes added by 'git notes add'
 
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/main)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate=full_--clear-decorations_--all b/t/t4013/diff.log_--decorate=full_--clear-decorations_--all
index 1c030a6..c43684e 100644
--- a/t/t4013/diff.log_--decorate=full_--clear-decorations_--all
+++ b/t/t4013/diff.log_--decorate=full_--clear-decorations_--all
@@ -26,7 +26,7 @@
 
     Notes added by 'git notes add'
 
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/main)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate=full_--decorate-all_--all b/t/t4013/diff.log_--decorate=full_--decorate-all_--all
index d6e7928..48dca61 100644
--- a/t/t4013/diff.log_--decorate=full_--decorate-all_--all
+++ b/t/t4013/diff.log_--decorate=full_--decorate-all_--all
@@ -26,7 +26,7 @@
 
     Notes added by 'git notes add'
 
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/main)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all
index c7df1f5..8bbf891 100644
--- a/t/t4013/diff.log_--decorate_--all
+++ b/t/t4013/diff.log_--decorate_--all
@@ -26,7 +26,7 @@
 
     Notes added by 'git notes add'
 
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> main)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate_--clear-decorations_--all b/t/t4013/diff.log_--decorate_--clear-decorations_--all
index 88be82c..86b1353 100644
--- a/t/t4013/diff.log_--decorate_--clear-decorations_--all
+++ b/t/t4013/diff.log_--decorate_--clear-decorations_--all
@@ -26,7 +26,7 @@
 
     Notes added by 'git notes add'
 
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> main)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate_--decorate-all_--all b/t/t4013/diff.log_--decorate_--decorate-all_--all
index 5d22618..59fb17b 100644
--- a/t/t4013/diff.log_--decorate_--decorate-all_--all
+++ b/t/t4013/diff.log_--decorate_--decorate-all_--all
@@ -26,7 +26,7 @@
 
     Notes added by 'git notes add'
 
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> main)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--diff-merges=first-parent_master b/t/t4013/diff.log_--diff-merges=first-parent_main
similarity index 95%
rename from t/t4013/diff.log_--diff-merges=first-parent_master
rename to t/t4013/diff.log_--diff-merges=first-parent_main
index fa63a55..bacee62 100644
--- a/t/t4013/diff.log_--diff-merges=first-parent_master
+++ b/t/t4013/diff.log_--diff-merges=first-parent_main
@@ -1,4 +1,4 @@
-$ git log --diff-merges=first-parent master
+$ git log --diff-merges=first-parent main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master b/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_main
similarity index 95%
rename from t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master
rename to t/t4013/diff.log_--diff-merges=off_-p_--first-parent_main
index 5970022..fe180fd 100644
--- a/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master
+++ b/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_main
@@ -1,4 +1,4 @@
-$ git log --no-diff-merges -p --first-parent master
+$ git log --diff-merges=off -p --first-parent main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_master b/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_master
deleted file mode 100644
index 194e893..0000000
--- a/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_master
+++ /dev/null
@@ -1,78 +0,0 @@
-$ git log --diff-merges=off -p --first-parent master
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-
-diff --git a/dir/sub b/dir/sub
-index 8422d40..cead32e 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -2,3 +2,5 @@ A
- B
- C
- D
-+E
-+F
-diff --git a/file1 b/file1
-new file mode 100644
-index 0000000..b1e6722
---- /dev/null
-+++ b/file1
-@@ -0,0 +1,3 @@
-+A
-+B
-+C
-
-commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:01:00 2006 +0000
-
-    Second
-    
-    This is the second commit.
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..8422d40 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+C
-+D
-diff --git a/file0 b/file0
-index 01e79c3..b414108 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+4
-+5
-+6
-diff --git a/file2 b/file2
-deleted file mode 100644
-index 01e79c3..0000000
---- a/file2
-+++ /dev/null
-@@ -1,3 +0,0 @@
--1
--2
--3
-
-commit 444ac553ac7612cc88969031b02b3767fb8a353a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:00:00 2006 +0000
-
-    Initial
-$
diff --git a/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_master b/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_main
similarity index 95%
rename from t/t4013/diff.log_--first-parent_--diff-merges=off_-p_master
rename to t/t4013/diff.log_--first-parent_--diff-merges=off_-p_main
index 5d7461a..dca62d4 100644
--- a/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_master
+++ b/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_main
@@ -1,4 +1,4 @@
-$ git log --first-parent --diff-merges=off -p master
+$ git log --first-parent --diff-merges=off -p main
 commit 80e25ffa65bcdbe82ef654b4d06dbbde7945c37f
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master b/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_main
similarity index 95%
copy from t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master
copy to t/t4013/diff.log_--no-diff-merges_-p_--first-parent_main
index 5970022..0b54118 100644
--- a/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master
+++ b/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_main
@@ -1,4 +1,4 @@
-$ git log --no-diff-merges -p --first-parent master
+$ git log --no-diff-merges -p --first-parent main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_main_--_dir_
similarity index 95%
copy from t/t4013/diff.log_--patch-with-stat_master_--_dir_
copy to t/t4013/diff.log_--patch-with-stat_--summary_main_--_dir_
index d5207ca..3ed46cc 100644
--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_--summary_main_--_dir_
@@ -1,4 +1,4 @@
-$ git log --patch-with-stat master -- dir/
+$ git log --patch-with-stat --summary main -- dir/
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
deleted file mode 100644
index a18f147..0000000
--- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
+++ /dev/null
@@ -1,74 +0,0 @@
-$ git log --patch-with-stat --summary master -- dir/
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
-commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:03:00 2006 +0000
-
-    Side
----
- dir/sub | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..7289e35 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+1
-+2
-
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
----
- dir/sub | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/dir/sub b/dir/sub
-index 8422d40..cead32e 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -2,3 +2,5 @@ A
- B
- C
- D
-+E
-+F
-
-commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:01:00 2006 +0000
-
-    Second
-    
-    This is the second commit.
----
- dir/sub | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..8422d40 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+C
-+D
-
-commit 444ac553ac7612cc88969031b02b3767fb8a353a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:00:00 2006 +0000
-
-    Initial
-$
diff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_main
similarity index 97%
rename from t/t4013/diff.log_--patch-with-stat_master
rename to t/t4013/diff.log_--patch-with-stat_main
index ae425c4..2e12b55 100644
--- a/t/t4013/diff.log_--patch-with-stat_master
+++ b/t/t4013/diff.log_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git log --patch-with-stat master
+$ git log --patch-with-stat main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_main_--_dir_
similarity index 96%
rename from t/t4013/diff.log_--patch-with-stat_master_--_dir_
rename to t/t4013/diff.log_--patch-with-stat_main_--_dir_
index d5207ca..d511ea7 100644
--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_main_--_dir_
@@ -1,4 +1,4 @@
-$ git log --patch-with-stat master -- dir/
+$ git log --patch-with-stat main -- dir/
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_main
similarity index 97%
rename from t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
rename to t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_main
index 0fc1e8c..3cfd0e6 100644
--- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git log --root --cc --patch-with-stat --summary master
+$ git log --root --cc --patch-with-stat --summary main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_main
similarity index 97%
rename from t/t4013/diff.log_--root_--patch-with-stat_--summary_master
rename to t/t4013/diff.log_--root_--patch-with-stat_--summary_main
index dffc09d..9f4d6df 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git log --root --patch-with-stat --summary master
+$ git log --root --patch-with-stat --summary main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_main
similarity index 97%
rename from t/t4013/diff.log_--root_--patch-with-stat_master
rename to t/t4013/diff.log_--root_--patch-with-stat_main
index 55aa980..0d69ae2 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git log --root --patch-with-stat master
+$ git log --root --patch-with-stat main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_main
similarity index 97%
copy from t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
copy to t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_main
index d1d32bd..1b71add 100644
--- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root -c --patch-with-stat --summary master
+$ git log --root -c --patch-with-stat --summary main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
deleted file mode 100644
index 019d85f..0000000
--- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
+++ /dev/null
@@ -1,199 +0,0 @@
-$ git log --root -c --patch-with-stat --summary master
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
- dir/sub | 2 ++
- file0   | 3 +++
- 2 files changed, 5 insertions(+)
-
-diff --combined dir/sub
-index cead32e,7289e35..992913c
---- a/dir/sub
-+++ b/dir/sub
-@@@ -1,6 -1,4 +1,8 @@@
-  A
-  B
- +C
- +D
- +E
- +F
-+ 1
-+ 2
-diff --combined file0
-index b414108,f4615da..10a8a9f
---- a/file0
-+++ b/file0
-@@@ -1,6 -1,6 +1,9 @@@
-  1
-  2
-  3
- +4
- +5
- +6
-+ A
-+ B
-+ C
-
-commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:03:00 2006 +0000
-
-    Side
----
- dir/sub | 2 ++
- file0   | 3 +++
- file3   | 4 ++++
- 3 files changed, 9 insertions(+)
- create mode 100644 file3
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..7289e35 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+1
-+2
-diff --git a/file0 b/file0
-index 01e79c3..f4615da 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+A
-+B
-+C
-diff --git a/file3 b/file3
-new file mode 100644
-index 0000000..7289e35
---- /dev/null
-+++ b/file3
-@@ -0,0 +1,4 @@
-+A
-+B
-+1
-+2
-
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
----
- dir/sub | 2 ++
- file1   | 3 +++
- 2 files changed, 5 insertions(+)
- create mode 100644 file1
-
-diff --git a/dir/sub b/dir/sub
-index 8422d40..cead32e 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -2,3 +2,5 @@ A
- B
- C
- D
-+E
-+F
-diff --git a/file1 b/file1
-new file mode 100644
-index 0000000..b1e6722
---- /dev/null
-+++ b/file1
-@@ -0,0 +1,3 @@
-+A
-+B
-+C
-
-commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:01:00 2006 +0000
-
-    Second
-    
-    This is the second commit.
----
- dir/sub | 2 ++
- file0   | 3 +++
- file2   | 3 ---
- 3 files changed, 5 insertions(+), 3 deletions(-)
- delete mode 100644 file2
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..8422d40 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+C
-+D
-diff --git a/file0 b/file0
-index 01e79c3..b414108 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+4
-+5
-+6
-diff --git a/file2 b/file2
-deleted file mode 100644
-index 01e79c3..0000000
---- a/file2
-+++ /dev/null
-@@ -1,3 +0,0 @@
--1
--2
--3
-
-commit 444ac553ac7612cc88969031b02b3767fb8a353a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:00:00 2006 +0000
-
-    Initial
----
- dir/sub | 2 ++
- file0   | 3 +++
- file2   | 3 +++
- 3 files changed, 8 insertions(+)
- create mode 100644 dir/sub
- create mode 100644 file0
- create mode 100644 file2
-
-diff --git a/dir/sub b/dir/sub
-new file mode 100644
-index 0000000..35d242b
---- /dev/null
-+++ b/dir/sub
-@@ -0,0 +1,2 @@
-+A
-+B
-diff --git a/file0 b/file0
-new file mode 100644
-index 0000000..01e79c3
---- /dev/null
-+++ b/file0
-@@ -0,0 +1,3 @@
-+1
-+2
-+3
-diff --git a/file2 b/file2
-new file mode 100644
-index 0000000..01e79c3
---- /dev/null
-+++ b/file2
-@@ -0,0 +1,3 @@
-+1
-+2
-+3
-$
diff --git a/t/t4013/diff.log_--root_-p_master b/t/t4013/diff.log_--root_-p_main
similarity index 98%
rename from t/t4013/diff.log_--root_-p_master
rename to t/t4013/diff.log_--root_-p_main
index b42c334..0458129 100644
--- a/t/t4013/diff.log_--root_-p_master
+++ b/t/t4013/diff.log_--root_-p_main
@@ -1,4 +1,4 @@
-$ git log --root -p master
+$ git log --root -p main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_master b/t/t4013/diff.log_--root_main
similarity index 96%
copy from t/t4013/diff.log_master
copy to t/t4013/diff.log_--root_main
index a8f6ce5..d5e90fd 100644
--- a/t/t4013/diff.log_master
+++ b/t/t4013/diff.log_--root_main
@@ -1,4 +1,4 @@
-$ git log master
+$ git log --root main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_master b/t/t4013/diff.log_--root_master
deleted file mode 100644
index e8f4615..0000000
--- a/t/t4013/diff.log_--root_master
+++ /dev/null
@@ -1,34 +0,0 @@
-$ git log --root master
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
-commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:03:00 2006 +0000
-
-    Side
-
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-
-commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:01:00 2006 +0000
-
-    Second
-    
-    This is the second commit.
-
-commit 444ac553ac7612cc88969031b02b3767fb8a353a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:00:00 2006 +0000
-
-    Initial
-$
diff --git a/t/t4013/diff.log_-GF_-p_--pickaxe-all_master b/t/t4013/diff.log_-GF_-p_--pickaxe-all_main
similarity index 90%
rename from t/t4013/diff.log_-GF_-p_--pickaxe-all_master
rename to t/t4013/diff.log_-GF_-p_--pickaxe-all_main
index d36f880..1f7a497 100644
--- a/t/t4013/diff.log_-GF_-p_--pickaxe-all_master
+++ b/t/t4013/diff.log_-GF_-p_--pickaxe-all_main
@@ -1,4 +1,4 @@
-$ git log -GF -p --pickaxe-all master
+$ git log -GF -p --pickaxe-all main
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-SF_-p_master b/t/t4013/diff.log_-GF_-p_main
similarity index 91%
rename from t/t4013/diff.log_-SF_-p_master
rename to t/t4013/diff.log_-GF_-p_main
index 5e32438..c80dda4 100644
--- a/t/t4013/diff.log_-SF_-p_master
+++ b/t/t4013/diff.log_-GF_-p_main
@@ -1,4 +1,4 @@
-$ git log -SF -p master
+$ git log -GF -p main
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-GF_-p_master b/t/t4013/diff.log_-GF_-p_master
deleted file mode 100644
index 9d93f2c..0000000
--- a/t/t4013/diff.log_-GF_-p_master
+++ /dev/null
@@ -1,18 +0,0 @@
-$ git log -GF -p master
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-
-diff --git a/dir/sub b/dir/sub
-index 8422d40..cead32e 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -2,3 +2,5 @@ A
- B
- C
- D
-+E
-+F
-$
diff --git a/t/t4013/diff.log_-GF_master b/t/t4013/diff.log_-GF_main
similarity index 86%
copy from t/t4013/diff.log_-GF_master
copy to t/t4013/diff.log_-GF_main
index 4c6708d..b94a7f7 100644
--- a/t/t4013/diff.log_-GF_master
+++ b/t/t4013/diff.log_-GF_main
@@ -1,4 +1,4 @@
-$ git log -GF master
+$ git log -GF main
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_master b/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_main
similarity index 97%
rename from t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_master
rename to t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_main
index 929f35a..67e26b4 100644
--- a/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_master
+++ b/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_main
@@ -1,4 +1,4 @@
-$ git log -IA -IB -I1 -I2 -p master
+$ git log -IA -IB -I1 -I2 -p main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-SF_-p_master b/t/t4013/diff.log_-SF_-p_main
similarity index 91%
copy from t/t4013/diff.log_-SF_-p_master
copy to t/t4013/diff.log_-SF_-p_main
index 5e32438..fa82ac1 100644
--- a/t/t4013/diff.log_-SF_-p_master
+++ b/t/t4013/diff.log_-SF_-p_main
@@ -1,4 +1,4 @@
-$ git log -SF -p master
+$ git log -SF -p main
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-GF_master b/t/t4013/diff.log_-SF_main
similarity index 86%
rename from t/t4013/diff.log_-GF_master
rename to t/t4013/diff.log_-SF_main
index 4c6708d..dbf770d 100644
--- a/t/t4013/diff.log_-GF_master
+++ b/t/t4013/diff.log_-SF_main
@@ -1,4 +1,4 @@
-$ git log -GF master
+$ git log -SF main
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-SF_main_--max-count=0 b/t/t4013/diff.log_-SF_main_--max-count=0
new file mode 100644
index 0000000..683b17e
--- /dev/null
+++ b/t/t4013/diff.log_-SF_main_--max-count=0
@@ -0,0 +1,2 @@
+$ git log -SF main --max-count=0
+$
diff --git a/t/t4013/diff.log_-GF_master b/t/t4013/diff.log_-SF_main_--max-count=1
similarity index 80%
copy from t/t4013/diff.log_-GF_master
copy to t/t4013/diff.log_-SF_main_--max-count=1
index 4c6708d..2102426 100644
--- a/t/t4013/diff.log_-GF_master
+++ b/t/t4013/diff.log_-SF_main_--max-count=1
@@ -1,4 +1,4 @@
-$ git log -GF master
+$ git log -SF main --max-count=1
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-GF_master b/t/t4013/diff.log_-SF_main_--max-count=2
similarity index 80%
copy from t/t4013/diff.log_-GF_master
copy to t/t4013/diff.log_-SF_main_--max-count=2
index 4c6708d..23e12a4 100644
--- a/t/t4013/diff.log_-GF_master
+++ b/t/t4013/diff.log_-SF_main_--max-count=2
@@ -1,4 +1,4 @@
-$ git log -GF master
+$ git log -SF main --max-count=2
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-SF_master b/t/t4013/diff.log_-SF_master
deleted file mode 100644
index c1599f2..0000000
--- a/t/t4013/diff.log_-SF_master
+++ /dev/null
@@ -1,7 +0,0 @@
-$ git log -SF master
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=0 b/t/t4013/diff.log_-SF_master_--max-count=0
deleted file mode 100644
index c1fc6c8..0000000
--- a/t/t4013/diff.log_-SF_master_--max-count=0
+++ /dev/null
@@ -1,2 +0,0 @@
-$ git log -SF master --max-count=0
-$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=1 b/t/t4013/diff.log_-SF_master_--max-count=1
deleted file mode 100644
index c981a03..0000000
--- a/t/t4013/diff.log_-SF_master_--max-count=1
+++ /dev/null
@@ -1,7 +0,0 @@
-$ git log -SF master --max-count=1
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=2 b/t/t4013/diff.log_-SF_master_--max-count=2
deleted file mode 100644
index a6c55fd..0000000
--- a/t/t4013/diff.log_-SF_master_--max-count=2
+++ /dev/null
@@ -1,7 +0,0 @@
-$ git log -SF master --max-count=2
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-$
diff --git a/t/t4013/diff.log_-GF_master b/t/t4013/diff.log_-S_F_main
similarity index 86%
copy from t/t4013/diff.log_-GF_master
copy to t/t4013/diff.log_-S_F_main
index 4c6708d..a75a42e 100644
--- a/t/t4013/diff.log_-GF_master
+++ b/t/t4013/diff.log_-S_F_main
@@ -1,4 +1,4 @@
-$ git log -GF master
+$ git log -S F main
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-S_F_master b/t/t4013/diff.log_-S_F_master
deleted file mode 100644
index 978d2b4..0000000
--- a/t/t4013/diff.log_-S_F_master
+++ /dev/null
@@ -1,7 +0,0 @@
-$ git log -S F master
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-$
diff --git a/t/t4013/diff.log_-m_-p_master b/t/t4013/diff.log_-c_-m_-p_main
similarity index 98%
copy from t/t4013/diff.log_-m_-p_master
copy to t/t4013/diff.log_-c_-m_-p_main
index 9ca62a0..427f732 100644
--- a/t/t4013/diff.log_-m_-p_master
+++ b/t/t4013/diff.log_-c_-m_-p_main
@@ -1,4 +1,4 @@
-$ git log -m -p master
+$ git log -c -m -p main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-c_-m_-p_master b/t/t4013/diff.log_-c_-m_-p_master
deleted file mode 100644
index b660f3d..0000000
--- a/t/t4013/diff.log_-c_-m_-p_master
+++ /dev/null
@@ -1,200 +0,0 @@
-$ git log -c -m -p master
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
-diff --git a/dir/sub b/dir/sub
-index cead32e..992913c 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -4,3 +4,5 @@ C
- D
- E
- F
-+1
-+2
-diff --git a/file0 b/file0
-index b414108..10a8a9f 100644
---- a/file0
-+++ b/file0
-@@ -4,3 +4,6 @@
- 4
- 5
- 6
-+A
-+B
-+C
-
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a)
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
-diff --git a/dir/sub b/dir/sub
-index 7289e35..992913c 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,4 +1,8 @@
- A
- B
-+C
-+D
-+E
-+F
- 1
- 2
-diff --git a/file0 b/file0
-index f4615da..10a8a9f 100644
---- a/file0
-+++ b/file0
-@@ -1,6 +1,9 @@
- 1
- 2
- 3
-+4
-+5
-+6
- A
- B
- C
-diff --git a/file1 b/file1
-new file mode 100644
-index 0000000..b1e6722
---- /dev/null
-+++ b/file1
-@@ -0,0 +1,3 @@
-+A
-+B
-+C
-diff --git a/file2 b/file2
-deleted file mode 100644
-index 01e79c3..0000000
---- a/file2
-+++ /dev/null
-@@ -1,3 +0,0 @@
--1
--2
--3
-diff --git a/file3 b/file3
-deleted file mode 100644
-index 7289e35..0000000
---- a/file3
-+++ /dev/null
-@@ -1,4 +0,0 @@
--A
--B
--1
--2
-
-commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:03:00 2006 +0000
-
-    Side
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..7289e35 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+1
-+2
-diff --git a/file0 b/file0
-index 01e79c3..f4615da 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+A
-+B
-+C
-diff --git a/file3 b/file3
-new file mode 100644
-index 0000000..7289e35
---- /dev/null
-+++ b/file3
-@@ -0,0 +1,4 @@
-+A
-+B
-+1
-+2
-
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-
-diff --git a/dir/sub b/dir/sub
-index 8422d40..cead32e 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -2,3 +2,5 @@ A
- B
- C
- D
-+E
-+F
-diff --git a/file1 b/file1
-new file mode 100644
-index 0000000..b1e6722
---- /dev/null
-+++ b/file1
-@@ -0,0 +1,3 @@
-+A
-+B
-+C
-
-commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:01:00 2006 +0000
-
-    Second
-    
-    This is the second commit.
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..8422d40 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+C
-+D
-diff --git a/file0 b/file0
-index 01e79c3..b414108 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+4
-+5
-+6
-diff --git a/file2 b/file2
-deleted file mode 100644
-index 01e79c3..0000000
---- a/file2
-+++ /dev/null
-@@ -1,3 +0,0 @@
--1
--2
--3
-
-commit 444ac553ac7612cc88969031b02b3767fb8a353a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:00:00 2006 +0000
-
-    Initial
-$
diff --git a/t/t4013/diff.log_-m_--raw_master b/t/t4013/diff.log_-m_--raw_main
similarity index 98%
rename from t/t4013/diff.log_-m_--raw_master
rename to t/t4013/diff.log_-m_--raw_main
index cd2ecc4..31d9bc7 100644
--- a/t/t4013/diff.log_-m_--raw_master
+++ b/t/t4013/diff.log_-m_--raw_main
@@ -1,4 +1,4 @@
-$ git log -m --raw master
+$ git log -m --raw main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-m_--stat_master b/t/t4013/diff.log_-m_--stat_main
similarity index 97%
rename from t/t4013/diff.log_-m_--stat_master
rename to t/t4013/diff.log_-m_--stat_main
index c7db084..4c89092 100644
--- a/t/t4013/diff.log_-m_--stat_master
+++ b/t/t4013/diff.log_-m_--stat_main
@@ -1,4 +1,4 @@
-$ git log -m --stat master
+$ git log -m --stat main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-p_--first-parent_master b/t/t4013/diff.log_-m_-p_--first-parent_main
similarity index 97%
rename from t/t4013/diff.log_-p_--first-parent_master
rename to t/t4013/diff.log_-m_-p_--first-parent_main
index 28840eb..459e107 100644
--- a/t/t4013/diff.log_-p_--first-parent_master
+++ b/t/t4013/diff.log_-m_-p_--first-parent_main
@@ -1,4 +1,4 @@
-$ git log -p --first-parent master
+$ git log -m -p --first-parent main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-m_-p_--first-parent_master b/t/t4013/diff.log_-m_-p_--first-parent_master
deleted file mode 100644
index 7a0073f..0000000
--- a/t/t4013/diff.log_-m_-p_--first-parent_master
+++ /dev/null
@@ -1,100 +0,0 @@
-$ git log -m -p --first-parent master
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
-diff --git a/dir/sub b/dir/sub
-index cead32e..992913c 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -4,3 +4,5 @@ C
- D
- E
- F
-+1
-+2
-diff --git a/file0 b/file0
-index b414108..10a8a9f 100644
---- a/file0
-+++ b/file0
-@@ -4,3 +4,6 @@
- 4
- 5
- 6
-+A
-+B
-+C
-
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-
-diff --git a/dir/sub b/dir/sub
-index 8422d40..cead32e 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -2,3 +2,5 @@ A
- B
- C
- D
-+E
-+F
-diff --git a/file1 b/file1
-new file mode 100644
-index 0000000..b1e6722
---- /dev/null
-+++ b/file1
-@@ -0,0 +1,3 @@
-+A
-+B
-+C
-
-commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:01:00 2006 +0000
-
-    Second
-    
-    This is the second commit.
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..8422d40 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+C
-+D
-diff --git a/file0 b/file0
-index 01e79c3..b414108 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+4
-+5
-+6
-diff --git a/file2 b/file2
-deleted file mode 100644
-index 01e79c3..0000000
---- a/file2
-+++ /dev/null
-@@ -1,3 +0,0 @@
--1
--2
--3
-
-commit 444ac553ac7612cc88969031b02b3767fb8a353a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:00:00 2006 +0000
-
-    Initial
-$
diff --git a/t/t4013/diff.log_-m_-p_master b/t/t4013/diff.log_-m_-p_main
similarity index 98%
rename from t/t4013/diff.log_-m_-p_master
rename to t/t4013/diff.log_-m_-p_main
index 9ca62a0..07453c5 100644
--- a/t/t4013/diff.log_-m_-p_master
+++ b/t/t4013/diff.log_-m_-p_main
@@ -1,4 +1,4 @@
-$ git log -m -p master
+$ git log -m -p main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-p_--diff-merges=first-parent_master b/t/t4013/diff.log_-p_--diff-merges=first-parent_main
similarity index 97%
rename from t/t4013/diff.log_-p_--diff-merges=first-parent_master
rename to t/t4013/diff.log_-p_--diff-merges=first-parent_main
index 9538a27..264a2f3 100644
--- a/t/t4013/diff.log_-p_--diff-merges=first-parent_master
+++ b/t/t4013/diff.log_-p_--diff-merges=first-parent_main
@@ -1,4 +1,4 @@
-$ git log -p --diff-merges=first-parent master
+$ git log -p --diff-merges=first-parent main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-p_--first-parent_master b/t/t4013/diff.log_-p_--first-parent_main
similarity index 97%
copy from t/t4013/diff.log_-p_--first-parent_master
copy to t/t4013/diff.log_-p_--first-parent_main
index 28840eb..2479808 100644
--- a/t/t4013/diff.log_-p_--first-parent_master
+++ b/t/t4013/diff.log_-p_--first-parent_main
@@ -1,4 +1,4 @@
-$ git log -p --first-parent master
+$ git log -p --first-parent main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-p_master b/t/t4013/diff.log_-p_main
similarity index 98%
rename from t/t4013/diff.log_-p_master
rename to t/t4013/diff.log_-p_main
index bf1326d..c82b4db 100644
--- a/t/t4013/diff.log_-p_master
+++ b/t/t4013/diff.log_-p_main
@@ -1,4 +1,4 @@
-$ git log -p master
+$ git log -p main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_master b/t/t4013/diff.log_main
similarity index 97%
rename from t/t4013/diff.log_master
rename to t/t4013/diff.log_main
index a8f6ce5..50401f7 100644
--- a/t/t4013/diff.log_master
+++ b/t/t4013/diff.log_main
@@ -1,4 +1,4 @@
-$ git log master
+$ git log main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.noellipses-diff-tree_-c_--abbrev_master b/t/t4013/diff.noellipses-diff-tree_-c_--abbrev_main
similarity index 81%
rename from t/t4013/diff.noellipses-diff-tree_-c_--abbrev_master
rename to t/t4013/diff.noellipses-diff-tree_-c_--abbrev_main
index bb80f01..3aa1f80 100644
--- a/t/t4013/diff.noellipses-diff-tree_-c_--abbrev_master
+++ b/t/t4013/diff.noellipses-diff-tree_-c_--abbrev_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c --abbrev master
+$ git diff-tree -c --abbrev main
 59d314ad6f356dd08601a4cd5e530381da3e3c64
 ::100644 100644 100644 cead32e 7289e35 992913c MM	dir/sub
 ::100644 100644 100644 b414108 f4615da 10a8a9f MM	file0
diff --git a/t/t4013/diff.noellipses-whatchanged_--root_master b/t/t4013/diff.noellipses-whatchanged_--root_main
similarity index 96%
rename from t/t4013/diff.noellipses-whatchanged_--root_master
rename to t/t4013/diff.noellipses-whatchanged_--root_main
index c2cfd4e..2bec055 100644
--- a/t/t4013/diff.noellipses-whatchanged_--root_master
+++ b/t/t4013/diff.noellipses-whatchanged_--root_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root master
+$ git whatchanged --root main
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.noellipses-whatchanged_-SF_master b/t/t4013/diff.noellipses-whatchanged_-SF_main
similarity index 85%
rename from t/t4013/diff.noellipses-whatchanged_-SF_master
rename to t/t4013/diff.noellipses-whatchanged_-SF_main
index b36ce58..0c1476d 100644
--- a/t/t4013/diff.noellipses-whatchanged_-SF_master
+++ b/t/t4013/diff.noellipses-whatchanged_-SF_main
@@ -1,4 +1,4 @@
-$ git whatchanged -SF master
+$ git whatchanged -SF main
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.noellipses-whatchanged_master b/t/t4013/diff.noellipses-whatchanged_main
similarity index 96%
rename from t/t4013/diff.noellipses-whatchanged_master
rename to t/t4013/diff.noellipses-whatchanged_main
index 55e500f..c48d285 100644
--- a/t/t4013/diff.noellipses-whatchanged_master
+++ b/t/t4013/diff.noellipses-whatchanged_main
@@ -1,4 +1,4 @@
-$ git whatchanged master
+$ git whatchanged main
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.show_--first-parent_master b/t/t4013/diff.show_--first-parent_main
similarity index 92%
rename from t/t4013/diff.show_--first-parent_master
rename to t/t4013/diff.show_--first-parent_main
index 3dcbe47..480502d 100644
--- a/t/t4013/diff.show_--first-parent_master
+++ b/t/t4013/diff.show_--first-parent_main
@@ -1,4 +1,4 @@
-$ git show --first-parent master
+$ git show --first-parent main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.show_-c_master b/t/t4013/diff.show_-c_main
similarity index 95%
rename from t/t4013/diff.show_-c_master
rename to t/t4013/diff.show_-c_main
index 81aba8d..74ef8bc 100644
--- a/t/t4013/diff.show_-c_master
+++ b/t/t4013/diff.show_-c_main
@@ -1,4 +1,4 @@
-$ git show -c master
+$ git show -c main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.show_-m_master b/t/t4013/diff.show_-m_main
similarity index 97%
rename from t/t4013/diff.show_-m_master
rename to t/t4013/diff.show_-m_main
index 4ea2ee4..8fd5673 100644
--- a/t/t4013/diff.show_-m_master
+++ b/t/t4013/diff.show_-m_main
@@ -1,4 +1,4 @@
-$ git show -m master
+$ git show -m main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.show_master b/t/t4013/diff.show_main
similarity index 95%
rename from t/t4013/diff.show_master
rename to t/t4013/diff.show_main
index fb08ce0..630b52a 100644
--- a/t/t4013/diff.show_master
+++ b/t/t4013/diff.show_main
@@ -1,4 +1,4 @@
-$ git show master
+$ git show main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_main_--_dir_
similarity index 93%
rename from t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_
rename to t/t4013/diff.whatchanged_--patch-with-stat_--summary_main_--_dir_
index c8b6af2..ce0754d 100644
--- a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_
+++ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_main_--_dir_
@@ -1,4 +1,4 @@
-$ git whatchanged --patch-with-stat --summary master -- dir/
+$ git whatchanged --patch-with-stat --summary main -- dir/
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master b/t/t4013/diff.whatchanged_--patch-with-stat_main
similarity index 97%
rename from t/t4013/diff.whatchanged_--patch-with-stat_master
rename to t/t4013/diff.whatchanged_--patch-with-stat_main
index 1ac431b..aabccf3 100644
--- a/t/t4013/diff.whatchanged_--patch-with-stat_master
+++ b/t/t4013/diff.whatchanged_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git whatchanged --patch-with-stat master
+$ git whatchanged --patch-with-stat main
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_main_--_dir_
similarity index 94%
rename from t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_
rename to t/t4013/diff.whatchanged_--patch-with-stat_main_--_dir_
index b30c285..c05a0e8 100644
--- a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.whatchanged_--patch-with-stat_main_--_dir_
@@ -1,4 +1,4 @@
-$ git whatchanged --patch-with-stat master -- dir/
+$ git whatchanged --patch-with-stat main -- dir/
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_main
similarity index 97%
copy from t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
copy to t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_main
index 0fc1e8c..1f74b1b 100644
--- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git log --root --cc --patch-with-stat --summary master
+$ git whatchanged --root --cc --patch-with-stat --summary main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
deleted file mode 100644
index 30aae78..0000000
--- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
+++ /dev/null
@@ -1,199 +0,0 @@
-$ git whatchanged --root --cc --patch-with-stat --summary master
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494 c7a2ab9
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:04:00 2006 +0000
-
-    Merge branch 'side'
-
- dir/sub | 2 ++
- file0   | 3 +++
- 2 files changed, 5 insertions(+)
-
-diff --cc dir/sub
-index cead32e,7289e35..992913c
---- a/dir/sub
-+++ b/dir/sub
-@@@ -1,6 -1,4 +1,8 @@@
-  A
-  B
- +C
- +D
- +E
- +F
-+ 1
-+ 2
-diff --cc file0
-index b414108,f4615da..10a8a9f
---- a/file0
-+++ b/file0
-@@@ -1,6 -1,6 +1,9 @@@
-  1
-  2
-  3
- +4
- +5
- +6
-+ A
-+ B
-+ C
-
-commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:03:00 2006 +0000
-
-    Side
----
- dir/sub | 2 ++
- file0   | 3 +++
- file3   | 4 ++++
- 3 files changed, 9 insertions(+)
- create mode 100644 file3
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..7289e35 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+1
-+2
-diff --git a/file0 b/file0
-index 01e79c3..f4615da 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+A
-+B
-+C
-diff --git a/file3 b/file3
-new file mode 100644
-index 0000000..7289e35
---- /dev/null
-+++ b/file3
-@@ -0,0 +1,4 @@
-+A
-+B
-+1
-+2
-
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
----
- dir/sub | 2 ++
- file1   | 3 +++
- 2 files changed, 5 insertions(+)
- create mode 100644 file1
-
-diff --git a/dir/sub b/dir/sub
-index 8422d40..cead32e 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -2,3 +2,5 @@ A
- B
- C
- D
-+E
-+F
-diff --git a/file1 b/file1
-new file mode 100644
-index 0000000..b1e6722
---- /dev/null
-+++ b/file1
-@@ -0,0 +1,3 @@
-+A
-+B
-+C
-
-commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:01:00 2006 +0000
-
-    Second
-    
-    This is the second commit.
----
- dir/sub | 2 ++
- file0   | 3 +++
- file2   | 3 ---
- 3 files changed, 5 insertions(+), 3 deletions(-)
- delete mode 100644 file2
-
-diff --git a/dir/sub b/dir/sub
-index 35d242b..8422d40 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -1,2 +1,4 @@
- A
- B
-+C
-+D
-diff --git a/file0 b/file0
-index 01e79c3..b414108 100644
---- a/file0
-+++ b/file0
-@@ -1,3 +1,6 @@
- 1
- 2
- 3
-+4
-+5
-+6
-diff --git a/file2 b/file2
-deleted file mode 100644
-index 01e79c3..0000000
---- a/file2
-+++ /dev/null
-@@ -1,3 +0,0 @@
--1
--2
--3
-
-commit 444ac553ac7612cc88969031b02b3767fb8a353a
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:00:00 2006 +0000
-
-    Initial
----
- dir/sub | 2 ++
- file0   | 3 +++
- file2   | 3 +++
- 3 files changed, 8 insertions(+)
- create mode 100644 dir/sub
- create mode 100644 file0
- create mode 100644 file2
-
-diff --git a/dir/sub b/dir/sub
-new file mode 100644
-index 0000000..35d242b
---- /dev/null
-+++ b/dir/sub
-@@ -0,0 +1,2 @@
-+A
-+B
-diff --git a/file0 b/file0
-new file mode 100644
-index 0000000..01e79c3
---- /dev/null
-+++ b/file0
-@@ -0,0 +1,3 @@
-+1
-+2
-+3
-diff --git a/file2 b/file2
-new file mode 100644
-index 0000000..01e79c3
---- /dev/null
-+++ b/file2
-@@ -0,0 +1,3 @@
-+1
-+2
-+3
-$
diff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_main
similarity index 97%
rename from t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master
rename to t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_main
index db90e51..80d9812 100644
--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root --patch-with-stat --summary master
+$ git whatchanged --root --patch-with-stat --summary main
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_main
similarity index 97%
rename from t/t4013/diff.whatchanged_--root_--patch-with-stat_master
rename to t/t4013/diff.whatchanged_--root_--patch-with-stat_main
index 9a6cc92..c0b9082 100644
--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master
+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root --patch-with-stat master
+$ git whatchanged --root --patch-with-stat main
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_main
similarity index 97%
rename from t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
rename to t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_main
index d1d32bd..0002c69 100644
--- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root -c --patch-with-stat --summary master
+$ git whatchanged --root -c --patch-with-stat --summary main
 commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.whatchanged_--root_-p_master b/t/t4013/diff.whatchanged_--root_-p_main
similarity index 97%
rename from t/t4013/diff.whatchanged_--root_-p_master
rename to t/t4013/diff.whatchanged_--root_-p_main
index ebf1f06..39f3e2b 100644
--- a/t/t4013/diff.whatchanged_--root_-p_master
+++ b/t/t4013/diff.whatchanged_--root_-p_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root -p master
+$ git whatchanged --root -p main
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--root_master b/t/t4013/diff.whatchanged_--root_main
similarity index 96%
rename from t/t4013/diff.whatchanged_--root_master
rename to t/t4013/diff.whatchanged_--root_main
index a405cb6..36f4d66 100644
--- a/t/t4013/diff.whatchanged_--root_master
+++ b/t/t4013/diff.whatchanged_--root_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root master
+$ git whatchanged --root main
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.log_-SF_-p_master b/t/t4013/diff.whatchanged_-SF_-p_main
similarity index 89%
copy from t/t4013/diff.log_-SF_-p_master
copy to t/t4013/diff.whatchanged_-SF_-p_main
index 5e32438..0e2e67c 100644
--- a/t/t4013/diff.log_-SF_-p_master
+++ b/t/t4013/diff.whatchanged_-SF_-p_main
@@ -1,4 +1,4 @@
-$ git log -SF -p master
+$ git whatchanged -SF -p main
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_-SF_-p_master b/t/t4013/diff.whatchanged_-SF_-p_master
deleted file mode 100644
index f39da84..0000000
--- a/t/t4013/diff.whatchanged_-SF_-p_master
+++ /dev/null
@@ -1,18 +0,0 @@
-$ git whatchanged -SF -p master
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date:   Mon Jun 26 00:02:00 2006 +0000
-
-    Third
-
-diff --git a/dir/sub b/dir/sub
-index 8422d40..cead32e 100644
---- a/dir/sub
-+++ b/dir/sub
-@@ -2,3 +2,5 @@ A
- B
- C
- D
-+E
-+F
-$
diff --git a/t/t4013/diff.whatchanged_-SF_master b/t/t4013/diff.whatchanged_-SF_main
similarity index 86%
rename from t/t4013/diff.whatchanged_-SF_master
rename to t/t4013/diff.whatchanged_-SF_main
index 0499321..34c6bf6 100644
--- a/t/t4013/diff.whatchanged_-SF_master
+++ b/t/t4013/diff.whatchanged_-SF_main
@@ -1,4 +1,4 @@
-$ git whatchanged -SF master
+$ git whatchanged -SF main
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_-p_master b/t/t4013/diff.whatchanged_-p_main
similarity index 97%
rename from t/t4013/diff.whatchanged_-p_master
rename to t/t4013/diff.whatchanged_-p_main
index f18d432..18f3bde 100644
--- a/t/t4013/diff.whatchanged_-p_master
+++ b/t/t4013/diff.whatchanged_-p_main
@@ -1,4 +1,4 @@
-$ git whatchanged -p master
+$ git whatchanged -p main
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_master b/t/t4013/diff.whatchanged_main
similarity index 96%
rename from t/t4013/diff.whatchanged_master
rename to t/t4013/diff.whatchanged_main
index cd3bcc2..d6c83ed 100644
--- a/t/t4013/diff.whatchanged_master
+++ b/t/t4013/diff.whatchanged_main
@@ -1,4 +1,4 @@
-$ git whatchanged master
+$ git whatchanged main
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index c8a23d5..7ec5854 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -44,6 +44,16 @@
 
 '
 
+test_expect_success 'GIT_EXTERNAL_DIFF and --output' '
+	cat >expect <<-EOF &&
+	file $(git rev-parse --verify HEAD:file) 100644 file $(test_oid zero) 100644
+	EOF
+	GIT_EXTERNAL_DIFF=echo git diff --output=out >stdout &&
+	cut -d" " -f1,3- <out >actual &&
+	test_must_be_empty stdout &&
+	test_cmp expect actual
+'
+
 test_expect_success SYMLINKS 'typechange diff' '
 	rm -f file &&
 	ln -s elif file &&
diff --git a/t/t4072-diff-max-depth.sh b/t/t4072-diff-max-depth.sh
new file mode 100755
index 0000000..0fbf132
--- /dev/null
+++ b/t/t4072-diff-max-depth.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+test_description='check that diff --max-depth will limit recursion'
+. ./test-lib.sh
+
+make_dir() {
+	mkdir -p "$1" &&
+	echo "$2" >"$1/file"
+}
+
+make_files() {
+	echo "$1" >file &&
+	make_dir one "$1" &&
+	make_dir one/two "$1" &&
+	make_dir one/two/three "$1"
+}
+
+test_expect_success 'setup' '
+	git commit --allow-empty -m empty &&
+	git tag empty &&
+	make_files added &&
+	git add . &&
+	git commit -m added &&
+	make_files modified &&
+	git add . &&
+	git commit -m modified &&
+	make_files index &&
+	git add . &&
+	make_files worktree
+'
+
+test_expect_success '--max-depth is disallowed with wildcard pathspecs' '
+	test_must_fail git diff-tree --max-depth=0 HEAD^ HEAD -- "f*"
+'
+
+check_one() {
+	type=$1; shift
+	args=$1; shift
+	path=$1; shift
+	depth=$1; shift
+	test_expect_${expect:-success} "diff-$type $args, path=$path, depth=$depth" "
+		for i in $*; do echo \$i; done >expect &&
+		git diff-$type --max-depth=$depth --name-only $args -- $path >actual &&
+		test_cmp expect actual
+	"
+}
+
+# For tree comparisons, we expect to see subtrees at the boundary
+# get their own entry.
+check_trees() {
+	check_one tree "$*" '' 0 file one
+	check_one tree "$*" '' 1 file one/file one/two
+	check_one tree "$*" '' 2 file one/file one/two/file one/two/three
+	check_one tree "$*" '' 3 file one/file one/two/file one/two/three/file
+	check_one tree "$*" '' -1 file one/file one/two/file one/two/three/file
+	check_one tree "$*" one 0 one
+	check_one tree "$*" one 1 one/file one/two
+	check_one tree "$*" one 2 one/file one/two/file one/two/three
+	check_one tree "$*" one 3 one/file one/two/file one/two/three/file
+	check_one tree "$*" one/two 0 one/two
+	check_one tree "$*" one/two 1 one/two/file one/two/three
+	check_one tree "$*" one/two 2 one/two/file one/two/three/file
+	check_one tree "$*" one/two 2 one/two/file one/two/three/file
+	check_one tree "$*" one/two/three 0 one/two/three
+	check_one tree "$*" one/two/three 1 one/two/three/file
+}
+
+# But for index comparisons, we do not store subtrees at all, so we do not
+# expect them.
+check_index() {
+	check_one "$@" '' 0 file
+	check_one "$@" '' 1 file one/file
+	check_one "$@" '' 2 file one/file one/two/file
+	check_one "$@" '' 3 file one/file one/two/file one/two/three/file
+	check_one "$@" one 0
+	check_one "$@" one 1 one/file
+	check_one "$@" one 2 one/file one/two/file
+	check_one "$@" one 3 one/file one/two/file one/two/three/file
+	check_one "$@" one/two 0
+	check_one "$@" one/two 1 one/two/file
+	check_one "$@" one/two 2 one/two/file one/two/three/file
+	check_one "$@" one/two/three 0
+	check_one "$@" one/two/three 1 one/two/three/file
+
+	# Value '-1' for '--max-depth is the same as recursion without limit,
+	# and thus should always succeed.
+	local expect=
+	check_one "$@" '' -1 file one/file one/two/file one/two/three/file
+}
+
+# Check as a modification...
+check_trees HEAD^ HEAD
+# ...and as an addition...
+check_trees empty HEAD
+# ...and as a deletion.
+check_trees HEAD empty
+
+# We currently only implement max-depth for trees.
+expect=failure
+# Check index against a tree
+check_index index "--cached HEAD"
+# and index against the worktree
+check_index files ""
+expect=
+
+test_expect_success 'find shortest path within embedded pathspecs' '
+	cat >expect <<-\EOF &&
+	one/file
+	one/two/file
+	one/two/three/file
+	EOF
+	git diff-tree --max-depth=2 --name-only HEAD^ HEAD -- one one/two >actual &&
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 639868a..1064990 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -154,11 +154,34 @@
 	test_bloom_filters_used "-- file*"
 '
 
-test_expect_success 'git log with path contains a wildcard does not use Bloom filter' '
+test_expect_success 'git log with paths all contain non-wildcard part uses Bloom filter' '
+	test_bloom_filters_used "-- A/\* file4" &&
+	test_bloom_filters_used "-- A/file\*" &&
+	test_bloom_filters_used "-- * A/\*"
+'
+
+test_expect_success 'git log with path only contains wildcard part does not use Bloom filter' '
 	test_bloom_filters_not_used "-- file\*" &&
-	test_bloom_filters_not_used "-- A/\* file4" &&
-	test_bloom_filters_not_used "-- file4 A/\*" &&
-	test_bloom_filters_not_used "-- * A/\*"
+	test_bloom_filters_not_used "-- file\* A/\*" &&
+	test_bloom_filters_not_used "-- file\* *" &&
+	test_bloom_filters_not_used "-- \*"
+'
+
+test_expect_success 'git log with path contains various magic signatures' '
+	cd A &&
+	test_bloom_filters_used "-- \:\(top\)B" &&
+	cd .. &&
+
+	test_bloom_filters_used "-- \:\(glob\)A/\*\*/C" &&
+	test_bloom_filters_not_used "-- \:\(icase\)FILE4" &&
+	test_bloom_filters_not_used "-- \:\(exclude\)A/B/C" &&
+
+	test_when_finished "rm -f .gitattributes" &&
+	cat >.gitattributes <<-EOF &&
+	A/file1 text
+	A/B/file2 -text
+	EOF
+	test_bloom_filters_used "-- \:\(attr\:text\)A"
 '
 
 test_expect_success 'setup - add commit-graph to the chain without Bloom filters' '
diff --git a/t/t5200-update-server-info.sh b/t/t5200-update-server-info.sh
index 8365907..a551e95 100755
--- a/t/t5200-update-server-info.sh
+++ b/t/t5200-update-server-info.sh
@@ -46,4 +46,9 @@
 	test_must_be_empty dups
 '
 
+test_expect_success 'update-server-info does not crash with -h' '
+	test_expect_code 129 git update-server-info -h >usage &&
+	test_grep "[Uu]sage: git update-server-info " usage
+'
+
 test_done
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 1f1f664..2be7cd3 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -364,4 +364,9 @@
 	git cat-file -p $BLOB
 '
 
+test_expect_success 'prune does not crash with -h' '
+	test_expect_code 129 git prune -h >usage &&
+	test_grep "[Uu]sage: git prune " usage
+'
+
 test_done
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 0b3404f..98c6910 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -946,4 +946,48 @@
 	)
 '
 
+test_expect_success 'config commitGraph.changedPaths acts like --changed-paths' '
+	git init config-changed-paths &&
+	(
+		cd config-changed-paths &&
+
+		# commitGraph.changedPaths is not set and it should not write Bloom filters
+		test_commit first &&
+		GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+		test_grep ! "Bloom filters" error &&
+
+		# Set commitGraph.changedPaths to true and it should write Bloom filters
+		test_commit second &&
+		git config commitGraph.changedPaths true &&
+		GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+		test_grep "Bloom filters" error &&
+
+		# Add one more config commitGraph.changedPaths as false to disable the previous true config value
+		# It should still write Bloom filters due to existing filters
+		test_commit third &&
+		git config --add commitGraph.changedPaths false &&
+		GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+		test_grep "Bloom filters" error &&
+
+		# commitGraph.changedPaths is still false and command line options should take precedence
+		test_commit fourth &&
+		GIT_PROGRESS_DELAY=0 git commit-graph write --no-changed-paths --reachable --progress 2>error &&
+		test_grep ! "Bloom filters" error &&
+		GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+		test_grep ! "Bloom filters" error &&
+
+		# commitGraph.changedPaths is all cleared and then set to false again, command line options should take precedence
+		test_commit fifth &&
+		git config --unset-all commitGraph.changedPaths &&
+		git config commitGraph.changedPaths false &&
+		GIT_PROGRESS_DELAY=0 git commit-graph write --changed-paths --reachable --progress 2>error &&
+		test_grep "Bloom filters" error &&
+
+		# commitGraph.changedPaths is still false and it should write Bloom filters due to existing filters
+		test_commit sixth &&
+		GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+		test_grep "Bloom filters" error
+	)
+'
+
 test_done
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index 2c22fdb..93f319a 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -28,11 +28,11 @@
 		EOF
 		if test $NUM_PACKS -ge 1
 		then
-			ls $OBJECT_DIR/pack/ | grep idx | sort
+			ls "$OBJECT_DIR"/pack/ | grep idx | sort
 		fi &&
 		printf "object-dir: $OBJECT_DIR\n"
 	} >expect &&
-	test-tool read-midx $OBJECT_DIR >actual &&
+	test-tool read-midx "$OBJECT_DIR" >actual &&
 	test_cmp expect actual
 }
 
@@ -305,7 +305,7 @@
 
 		ofs=$(git show-index <objects/pack/test-BC-$bc.idx | grep $b |
 			cut -d" " -f1) &&
-		printf "%s %s\tobjects/pack/test-BC-%s.pack\n" \
+		printf "%s %s\t./objects/pack/test-BC-%s.pack\n" \
 			"$b" "$ofs" "$bc" >expect &&
 		grep ^$b out >actual &&
 
@@ -639,7 +639,7 @@
 		( cd ../objects64 && pwd ) >.git/objects/info/alternates &&
 		midx64=$(git multi-pack-index --object-dir=../objects64 write)
 	) &&
-	midx_read_expect 1 63 5 objects64 " large-offsets"
+	midx_read_expect 1 63 5 "$(pwd)/objects64" " large-offsets"
 '
 
 test_expect_success 'verify multi-pack-index with 64-bit offsets' '
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 2701eef..e592c0b 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -1658,4 +1658,77 @@
 	test_grep ".outer. is a superset of existing remote .outer/inner." err
 '
 
+test_expect_success 'rename handles unborn HEAD' '
+	test_when_finished "git remote remove unborn-renamed" &&
+	git remote add unborn url &&
+	git symbolic-ref refs/remotes/unborn/HEAD refs/remotes/unborn/nonexistent &&
+	git remote rename unborn unborn-renamed &&
+	git symbolic-ref refs/remotes/unborn-renamed/HEAD >actual &&
+	echo refs/remotes/unborn-renamed/nonexistent >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'rename can nest a remote into itself' '
+	test_commit parent-commit &&
+	COMMIT_ID=$(git rev-parse HEAD) &&
+	test_when_finished "git remote remove parent || true" &&
+	git remote add parent url &&
+	git update-ref refs/remotes/parent/branch $COMMIT_ID &&
+	test_when_finished "git remote remove parent/child" &&
+	git remote rename parent parent/child &&
+	git for-each-ref refs/remotes/ >actual &&
+	printf "$COMMIT_ID commit\trefs/remotes/parent/child/branch\n" >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'rename can nest a remote into itself with a conflicting branch name' '
+	test_commit parent-conflict &&
+	COMMIT_ID=$(git rev-parse HEAD) &&
+	test_when_finished "git remote remove parent || true" &&
+	git remote add parent url &&
+	git update-ref refs/remotes/parent/child $COMMIT_ID &&
+	test_when_finished "git remote remove parent/child" &&
+	test_must_fail git remote rename parent parent/child 2>err &&
+	test_grep "renaming remote references failed" err &&
+	test_grep "The remote you are trying to rename has conflicting references" err &&
+	git for-each-ref refs/remotes/ >actual &&
+	printf "$COMMIT_ID commit\trefs/remotes/parent/child\n" >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'rename can unnest a remote' '
+	test_commit parent-child-commit &&
+	COMMIT_ID=$(git rev-parse HEAD) &&
+	test_when_finished "git remote remove parent/child || true" &&
+	git remote add parent/child url &&
+	git update-ref refs/remotes/parent/child/branch $COMMIT_ID &&
+	git remote rename parent/child parent &&
+	git for-each-ref refs/remotes/ >actual &&
+	printf "$COMMIT_ID commit\trefs/remotes/parent/branch\n" >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'rename moves around the reflog' '
+	test_commit reflog-old &&
+	COMMIT_ID=$(git rev-parse HEAD) &&
+	test_config core.logAllRefUpdates true &&
+	test_when_finished "git remote remove reflog-old || true" &&
+	git remote add reflog-old url &&
+	git update-ref refs/remotes/reflog-old/branch $COMMIT_ID &&
+	test-tool ref-store main for-each-reflog >actual &&
+	test_grep refs/remotes/reflog-old/branch actual &&
+	test-tool ref-store main for-each-reflog-ent refs/remotes/reflog-old/branch >reflog-entries-old &&
+	test_line_count = 1 reflog-entries-old &&
+	git remote rename reflog-old reflog-new &&
+	test-tool ref-store main for-each-reflog >actual &&
+	test_grep ! refs/remotes/reflog-old actual &&
+	test_grep refs/remotes/reflog-new/branch actual &&
+	test-tool ref-store main for-each-reflog-ent refs/remotes/reflog-new/branch >reflog-entries-new &&
+	cat >expect <<-EOF &&
+	$(cat reflog-entries-old)
+	$COMMIT_ID $COMMIT_ID $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1112912173 -0700	remote: renamed refs/remotes/reflog-old/branch to refs/remotes/reflog-new/branch
+	EOF
+	test_cmp expect reflog-entries-new
+'
+
 test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 6b2739d..b7059cc 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -14,8 +14,6 @@
 	test_done
 fi
 
-D=$(pwd)
-
 test_expect_success setup '
 	echo >file original &&
 	git add file &&
@@ -69,46 +67,50 @@
 '
 
 test_expect_success "fetch test" '
-	cd "$D" &&
 	echo >file updated by origin &&
 	git commit -a -m "updated by origin" &&
-	cd two &&
-	git fetch &&
-	git rev-parse --verify refs/heads/one &&
-	mine=$(git rev-parse refs/heads/one) &&
-	his=$(cd ../one && git rev-parse refs/heads/main) &&
-	test "z$mine" = "z$his"
+	(
+		cd two &&
+		git fetch &&
+		git rev-parse --verify refs/heads/one &&
+		mine=$(git rev-parse refs/heads/one) &&
+		his=$(cd ../one && git rev-parse refs/heads/main) &&
+		test "z$mine" = "z$his"
+	)
 '
 
 test_expect_success "fetch test for-merge" '
-	cd "$D" &&
-	cd three &&
-	git fetch &&
-	git rev-parse --verify refs/heads/two &&
-	git rev-parse --verify refs/heads/one &&
-	main_in_two=$(cd ../two && git rev-parse main) &&
-	one_in_two=$(cd ../two && git rev-parse one) &&
-	{
-		echo "$one_in_two	" &&
-		echo "$main_in_two	not-for-merge"
-	} >expected &&
-	cut -f -2 .git/FETCH_HEAD >actual &&
-	test_cmp expected actual'
+	(
+		cd three &&
+		git fetch &&
+		git rev-parse --verify refs/heads/two &&
+		git rev-parse --verify refs/heads/one &&
+		main_in_two=$(cd ../two && git rev-parse main) &&
+		one_in_two=$(cd ../two && git rev-parse one) &&
+		{
+			echo "$one_in_two	" &&
+			echo "$main_in_two	not-for-merge"
+		} >expected &&
+		cut -f -2 .git/FETCH_HEAD >actual &&
+		test_cmp expected actual
+	)
+'
 
 test_expect_success "fetch test remote HEAD" '
-	cd "$D" &&
-	cd two &&
-	git fetch &&
-	git rev-parse --verify refs/remotes/origin/HEAD &&
-	git rev-parse --verify refs/remotes/origin/main &&
-	head=$(git rev-parse refs/remotes/origin/HEAD) &&
-	branch=$(git rev-parse refs/remotes/origin/main) &&
-	test "z$head" = "z$branch"'
+	(
+		cd two &&
+		git fetch &&
+		git rev-parse --verify refs/remotes/origin/HEAD &&
+		git rev-parse --verify refs/remotes/origin/main &&
+		head=$(git rev-parse refs/remotes/origin/HEAD) &&
+		branch=$(git rev-parse refs/remotes/origin/main) &&
+		test "z$head" = "z$branch"
+	)
+'
 
 test_expect_success "fetch test remote HEAD in bare repository" '
 	test_when_finished rm -rf barerepo &&
 	(
-		cd "$D" &&
 		git init --bare barerepo &&
 		cd barerepo &&
 		git remote add upstream ../two &&
@@ -123,262 +125,235 @@
 
 
 test_expect_success "fetch test remote HEAD change" '
-	cd "$D" &&
-	cd two &&
-	git switch -c other &&
-	git push -u origin other &&
-	git rev-parse --verify refs/remotes/origin/HEAD &&
-	git rev-parse --verify refs/remotes/origin/main &&
-	git rev-parse --verify refs/remotes/origin/other &&
-	git remote set-head origin other &&
-	git fetch &&
-	head=$(git rev-parse refs/remotes/origin/HEAD) &&
-	branch=$(git rev-parse refs/remotes/origin/other) &&
-	test "z$head" = "z$branch"'
+	(
+		cd two &&
+		git switch -c other &&
+		git push -u origin other &&
+		git rev-parse --verify refs/remotes/origin/HEAD &&
+		git rev-parse --verify refs/remotes/origin/main &&
+		git rev-parse --verify refs/remotes/origin/other &&
+		git remote set-head origin other &&
+		git fetch &&
+		head=$(git rev-parse refs/remotes/origin/HEAD) &&
+		branch=$(git rev-parse refs/remotes/origin/other) &&
+		test "z$head" = "z$branch"
+	)
+'
 
 test_expect_success "fetch test followRemoteHEAD never" '
-	test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
-	(
-		cd "$D" &&
-		cd two &&
-		git update-ref --no-deref -d refs/remotes/origin/HEAD &&
-		git config set remote.origin.followRemoteHEAD "never" &&
-		GIT_TRACE_PACKET=$PWD/trace.out git fetch &&
-		# Confirm that we do not even ask for HEAD when we are
-		# not going to act on it.
-		test_grep ! "ref-prefix HEAD" trace.out &&
-		test_must_fail git rev-parse --verify refs/remotes/origin/HEAD
-	)
+	git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
+	test_config -C two remote.origin.followRemoteHEAD "never" &&
+	GIT_TRACE_PACKET=$PWD/trace.out git -C two fetch &&
+	# Confirm that we do not even ask for HEAD when we are
+	# not going to act on it.
+	test_grep ! "ref-prefix HEAD" trace.out &&
+	test_must_fail git -C two rev-parse --verify refs/remotes/origin/HEAD
 '
 
 test_expect_success "fetch test followRemoteHEAD warn no change" '
-	test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
-	(
-		cd "$D" &&
-		cd two &&
-		git rev-parse --verify refs/remotes/origin/other &&
-		git remote set-head origin other &&
-		git rev-parse --verify refs/remotes/origin/HEAD &&
-		git rev-parse --verify refs/remotes/origin/main &&
-		git config set remote.origin.followRemoteHEAD "warn" &&
-		git fetch >output &&
-		echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
-			"but we have ${SQ}other${SQ} locally." >expect &&
-		test_cmp expect output &&
-		head=$(git rev-parse refs/remotes/origin/HEAD) &&
-		branch=$(git rev-parse refs/remotes/origin/other) &&
-		test "z$head" = "z$branch"
-	)
+	git -C two rev-parse --verify refs/remotes/origin/other &&
+	git -C two remote set-head origin other &&
+	git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+	git -C two rev-parse --verify refs/remotes/origin/main &&
+	test_config -C two remote.origin.followRemoteHEAD "warn" &&
+	git -C two fetch >output &&
+	echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
+		"but we have ${SQ}other${SQ} locally." >expect &&
+	test_cmp expect output &&
+	head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+	branch=$(git -C two rev-parse refs/remotes/origin/other) &&
+	test "z$head" = "z$branch"
 '
 
 test_expect_success "fetch test followRemoteHEAD warn create" '
-	test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
-	(
-		cd "$D" &&
-		cd two &&
-		git update-ref --no-deref -d refs/remotes/origin/HEAD &&
-		git config set remote.origin.followRemoteHEAD "warn" &&
-		git rev-parse --verify refs/remotes/origin/main &&
-		output=$(git fetch) &&
-		test "z" = "z$output" &&
-		head=$(git rev-parse refs/remotes/origin/HEAD) &&
-		branch=$(git rev-parse refs/remotes/origin/main) &&
-		test "z$head" = "z$branch"
-	)
+	git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
+	test_config -C two remote.origin.followRemoteHEAD "warn" &&
+	git -C two rev-parse --verify refs/remotes/origin/main &&
+	output=$(git -C two fetch) &&
+	test "z" = "z$output" &&
+	head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+	branch=$(git -C two rev-parse refs/remotes/origin/main) &&
+	test "z$head" = "z$branch"
 '
 
 test_expect_success "fetch test followRemoteHEAD warn detached" '
-	test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
-	(
-		cd "$D" &&
-		cd two &&
-		git update-ref --no-deref -d refs/remotes/origin/HEAD &&
-		git update-ref refs/remotes/origin/HEAD HEAD &&
-		HEAD=$(git log --pretty="%H") &&
-		git config set remote.origin.followRemoteHEAD "warn" &&
-		git fetch >output &&
-		echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
-			"but we have a detached HEAD pointing to" \
-			"${SQ}${HEAD}${SQ} locally." >expect &&
-		test_cmp expect output
-	)
+	git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
+	git -C two update-ref refs/remotes/origin/HEAD HEAD &&
+	HEAD=$(git -C two log --pretty="%H") &&
+	test_config -C two remote.origin.followRemoteHEAD "warn" &&
+	git -C two fetch >output &&
+	echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
+		"but we have a detached HEAD pointing to" \
+		"${SQ}${HEAD}${SQ} locally." >expect &&
+	test_cmp expect output
 '
 
 test_expect_success "fetch test followRemoteHEAD warn quiet" '
-	test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
-	(
-		cd "$D" &&
-		cd two &&
-		git rev-parse --verify refs/remotes/origin/other &&
-		git remote set-head origin other &&
-		git rev-parse --verify refs/remotes/origin/HEAD &&
-		git rev-parse --verify refs/remotes/origin/main &&
-		git config set remote.origin.followRemoteHEAD "warn" &&
-		output=$(git fetch --quiet) &&
-		test "z" = "z$output" &&
-		head=$(git rev-parse refs/remotes/origin/HEAD) &&
-		branch=$(git rev-parse refs/remotes/origin/other) &&
-		test "z$head" = "z$branch"
-	)
+	git -C two rev-parse --verify refs/remotes/origin/other &&
+	git -C two remote set-head origin other &&
+	git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+	git -C two rev-parse --verify refs/remotes/origin/main &&
+	test_config -C two remote.origin.followRemoteHEAD "warn" &&
+	output=$(git -C two fetch --quiet) &&
+	test "z" = "z$output" &&
+	head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+	branch=$(git -C two rev-parse refs/remotes/origin/other) &&
+	test "z$head" = "z$branch"
 '
 
 test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is same" '
-	test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
-	(
-		cd "$D" &&
-		cd two &&
-		git rev-parse --verify refs/remotes/origin/other &&
-		git remote set-head origin other &&
-		git rev-parse --verify refs/remotes/origin/HEAD &&
-		git rev-parse --verify refs/remotes/origin/main &&
-		git config set remote.origin.followRemoteHEAD "warn-if-not-main" &&
-		actual=$(git fetch) &&
-		test "z" = "z$actual" &&
-		head=$(git rev-parse refs/remotes/origin/HEAD) &&
-		branch=$(git rev-parse refs/remotes/origin/other) &&
-		test "z$head" = "z$branch"
-	)
+	git -C two rev-parse --verify refs/remotes/origin/other &&
+	git -C two remote set-head origin other &&
+	git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+	git -C two rev-parse --verify refs/remotes/origin/main &&
+	test_config -C two remote.origin.followRemoteHEAD "warn-if-not-main" &&
+	actual=$(git -C two fetch) &&
+	test "z" = "z$actual" &&
+	head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+	branch=$(git -C two rev-parse refs/remotes/origin/other) &&
+	test "z$head" = "z$branch"
 '
 
 test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is different" '
-	test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
-	(
-		cd "$D" &&
-		cd two &&
-		git rev-parse --verify refs/remotes/origin/other &&
-		git remote set-head origin other &&
-		git rev-parse --verify refs/remotes/origin/HEAD &&
-		git rev-parse --verify refs/remotes/origin/main &&
-		git config set remote.origin.followRemoteHEAD "warn-if-not-some/different-branch" &&
-		git fetch >actual &&
-		echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
-			"but we have ${SQ}other${SQ} locally." >expect &&
-		test_cmp expect actual &&
-		head=$(git rev-parse refs/remotes/origin/HEAD) &&
-		branch=$(git rev-parse refs/remotes/origin/other) &&
-		test "z$head" = "z$branch"
-	)
+	git -C two rev-parse --verify refs/remotes/origin/other &&
+	git -C two remote set-head origin other &&
+	git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+	git -C two rev-parse --verify refs/remotes/origin/main &&
+	test_config -C two remote.origin.followRemoteHEAD "warn-if-not-some/different-branch" &&
+	git -C two fetch >actual &&
+	echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
+		"but we have ${SQ}other${SQ} locally." >expect &&
+	test_cmp expect actual &&
+	head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+	branch=$(git -C two rev-parse refs/remotes/origin/other) &&
+	test "z$head" = "z$branch"
 '
 
 test_expect_success "fetch test followRemoteHEAD always" '
-	test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
-	(
-		cd "$D" &&
-		cd two &&
-		git rev-parse --verify refs/remotes/origin/other &&
-		git remote set-head origin other &&
-		git rev-parse --verify refs/remotes/origin/HEAD &&
-		git rev-parse --verify refs/remotes/origin/main &&
-		git config set remote.origin.followRemoteHEAD "always" &&
-		git fetch &&
-		head=$(git rev-parse refs/remotes/origin/HEAD) &&
-		branch=$(git rev-parse refs/remotes/origin/main) &&
-		test "z$head" = "z$branch"
-	)
+	git -C two rev-parse --verify refs/remotes/origin/other &&
+	git -C two remote set-head origin other &&
+	git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+	git -C two rev-parse --verify refs/remotes/origin/main &&
+	test_config -C two remote.origin.followRemoteHEAD "always" &&
+	git -C two fetch &&
+	head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+	branch=$(git -C two rev-parse refs/remotes/origin/main) &&
+	test "z$head" = "z$branch"
 '
 
 test_expect_success 'followRemoteHEAD does not kick in with refspecs' '
-	test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
-	(
-		cd "$D" &&
-		cd two &&
-		git remote set-head origin other &&
-		git config set remote.origin.followRemoteHEAD always &&
-		git fetch origin refs/heads/main:refs/remotes/origin/main &&
-		echo refs/remotes/origin/other >expect &&
-		git symbolic-ref refs/remotes/origin/HEAD >actual &&
-		test_cmp expect actual
-	)
+	git -C two remote set-head origin other &&
+	test_config -C two remote.origin.followRemoteHEAD always &&
+	git -C two fetch origin refs/heads/main:refs/remotes/origin/main &&
+	echo refs/remotes/origin/other >expect &&
+	git -C two symbolic-ref refs/remotes/origin/HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'followRemoteHEAD create does not overwrite dangling symref' '
+	git -C two remote add -m does-not-exist custom-head ../one &&
+	test_config -C two remote.custom-head.followRemoteHEAD create &&
+	git -C two fetch custom-head &&
+	echo refs/remotes/custom-head/does-not-exist >expect &&
+	git -C two symbolic-ref refs/remotes/custom-head/HEAD >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'fetch --prune on its own works as expected' '
-	cd "$D" &&
 	git clone . prune &&
-	cd prune &&
-	git update-ref refs/remotes/origin/extrabranch main &&
+	(
+		cd prune &&
+		git update-ref refs/remotes/origin/extrabranch main &&
 
-	git fetch --prune origin &&
-	test_must_fail git rev-parse origin/extrabranch
+		git fetch --prune origin &&
+		test_must_fail git rev-parse origin/extrabranch
+	)
 '
 
 test_expect_success 'fetch --prune with a branch name keeps branches' '
-	cd "$D" &&
 	git clone . prune-branch &&
-	cd prune-branch &&
-	git update-ref refs/remotes/origin/extrabranch main &&
+	(
+		cd prune-branch &&
+		git update-ref refs/remotes/origin/extrabranch main &&
 
-	git fetch --prune origin main &&
-	git rev-parse origin/extrabranch
+		git fetch --prune origin main &&
+		git rev-parse origin/extrabranch
+	)
 '
 
 test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
-	cd "$D" &&
 	git clone . prune-namespace &&
-	cd prune-namespace &&
+	(
+		cd prune-namespace &&
 
-	git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
-	git rev-parse origin/main
+		git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
+		git rev-parse origin/main
+	)
 '
 
 test_expect_success 'fetch --prune handles overlapping refspecs' '
-	cd "$D" &&
 	git update-ref refs/pull/42/head main &&
 	git clone . prune-overlapping &&
-	cd prune-overlapping &&
-	git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+	(
+		cd prune-overlapping &&
+		git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
 
-	git fetch --prune origin &&
-	git rev-parse origin/main &&
-	git rev-parse origin/pr/42 &&
+		git fetch --prune origin &&
+		git rev-parse origin/main &&
+		git rev-parse origin/pr/42 &&
 
-	git config --unset-all remote.origin.fetch &&
-	git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
-	git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
+		git config --unset-all remote.origin.fetch &&
+		git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+		git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
 
-	git fetch --prune origin &&
-	git rev-parse origin/main &&
-	git rev-parse origin/pr/42
+		git fetch --prune origin &&
+		git rev-parse origin/main &&
+		git rev-parse origin/pr/42
+	)
 '
 
 test_expect_success 'fetch --prune --tags prunes branches but not tags' '
-	cd "$D" &&
 	git clone . prune-tags &&
-	cd prune-tags &&
-	git tag sometag main &&
-	# Create what looks like a remote-tracking branch from an earlier
-	# fetch that has since been deleted from the remote:
-	git update-ref refs/remotes/origin/fake-remote main &&
+	(
+		cd prune-tags &&
+		git tag sometag main &&
+		# Create what looks like a remote-tracking branch from an earlier
+		# fetch that has since been deleted from the remote:
+		git update-ref refs/remotes/origin/fake-remote main &&
 
-	git fetch --prune --tags origin &&
-	git rev-parse origin/main &&
-	test_must_fail git rev-parse origin/fake-remote &&
-	git rev-parse sometag
+		git fetch --prune --tags origin &&
+		git rev-parse origin/main &&
+		test_must_fail git rev-parse origin/fake-remote &&
+		git rev-parse sometag
+	)
 '
 
 test_expect_success 'fetch --prune --tags with branch does not prune other things' '
-	cd "$D" &&
 	git clone . prune-tags-branch &&
-	cd prune-tags-branch &&
-	git tag sometag main &&
-	git update-ref refs/remotes/origin/extrabranch main &&
+	(
+		cd prune-tags-branch &&
+		git tag sometag main &&
+		git update-ref refs/remotes/origin/extrabranch main &&
 
-	git fetch --prune --tags origin main &&
-	git rev-parse origin/extrabranch &&
-	git rev-parse sometag
+		git fetch --prune --tags origin main &&
+		git rev-parse origin/extrabranch &&
+		git rev-parse sometag
+	)
 '
 
 test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '
-	cd "$D" &&
 	git clone . prune-tags-refspec &&
-	cd prune-tags-refspec &&
-	git tag sometag main &&
-	git update-ref refs/remotes/origin/foo/otherbranch main &&
-	git update-ref refs/remotes/origin/extrabranch main &&
+	(
+		cd prune-tags-refspec &&
+		git tag sometag main &&
+		git update-ref refs/remotes/origin/foo/otherbranch main &&
+		git update-ref refs/remotes/origin/extrabranch main &&
 
-	git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
-	test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
-	git rev-parse origin/extrabranch &&
-	git rev-parse sometag
+		git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
+		test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
+		git rev-parse origin/extrabranch &&
+		git rev-parse sometag
+	)
 '
 
 test_expect_success 'fetch --tags gets tags even without a configured remote' '
@@ -399,21 +374,21 @@
 '
 
 test_expect_success REFFILES 'fetch --prune fails to delete branches' '
-	cd "$D" &&
 	git clone . prune-fail &&
-	cd prune-fail &&
-	git update-ref refs/remotes/origin/extrabranch main &&
-	git pack-refs --all &&
-	: this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds  &&
-	>.git/packed-refs.new &&
+	(
+		cd prune-fail &&
+		git update-ref refs/remotes/origin/extrabranch main &&
+		git pack-refs --all &&
+		: this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds  &&
+		>.git/packed-refs.new &&
 
-	test_must_fail git fetch --prune origin
+		test_must_fail git fetch --prune origin
+	)
 '
 
 test_expect_success 'fetch --atomic works with a single branch' '
-	test_when_finished "rm -rf \"$D\"/atomic" &&
+	test_when_finished "rm -rf atomic" &&
 
-	cd "$D" &&
 	git clone . atomic &&
 	git branch atomic-branch &&
 	oid=$(git rev-parse atomic-branch) &&
@@ -426,9 +401,8 @@
 '
 
 test_expect_success 'fetch --atomic works with multiple branches' '
-	test_when_finished "rm -rf \"$D\"/atomic" &&
+	test_when_finished "rm -rf atomic" &&
 
-	cd "$D" &&
 	git clone . atomic &&
 	git branch atomic-branch-1 &&
 	git branch atomic-branch-2 &&
@@ -441,9 +415,8 @@
 '
 
 test_expect_success 'fetch --atomic works with mixed branches and tags' '
-	test_when_finished "rm -rf \"$D\"/atomic" &&
+	test_when_finished "rm -rf atomic" &&
 
-	cd "$D" &&
 	git clone . atomic &&
 	git branch atomic-mixed-branch &&
 	git tag atomic-mixed-tag &&
@@ -455,9 +428,8 @@
 '
 
 test_expect_success 'fetch --atomic prunes references' '
-	test_when_finished "rm -rf \"$D\"/atomic" &&
+	test_when_finished "rm -rf atomic" &&
 
-	cd "$D" &&
 	git branch atomic-prune-delete &&
 	git clone . atomic &&
 	git branch --delete atomic-prune-delete &&
@@ -471,9 +443,8 @@
 '
 
 test_expect_success 'fetch --atomic aborts with non-fast-forward update' '
-	test_when_finished "rm -rf \"$D\"/atomic" &&
+	test_when_finished "rm -rf atomic" &&
 
-	cd "$D" &&
 	git branch atomic-non-ff &&
 	git clone . atomic &&
 	git rev-parse HEAD >actual &&
@@ -490,9 +461,8 @@
 '
 
 test_expect_success 'fetch --atomic executes a single reference transaction only' '
-	test_when_finished "rm -rf \"$D\"/atomic" &&
+	test_when_finished "rm -rf atomic" &&
 
-	cd "$D" &&
 	git clone . atomic &&
 	git branch atomic-hooks-1 &&
 	git branch atomic-hooks-2 &&
@@ -517,9 +487,8 @@
 '
 
 test_expect_success 'fetch --atomic aborts all reference updates if hook aborts' '
-	test_when_finished "rm -rf \"$D\"/atomic" &&
+	test_when_finished "rm -rf atomic" &&
 
-	cd "$D" &&
 	git clone . atomic &&
 	git branch atomic-hooks-abort-1 &&
 	git branch atomic-hooks-abort-2 &&
@@ -554,9 +523,8 @@
 '
 
 test_expect_success 'fetch --atomic --append appends to FETCH_HEAD' '
-	test_when_finished "rm -rf \"$D\"/atomic" &&
+	test_when_finished "rm -rf atomic" &&
 
-	cd "$D" &&
 	git clone . atomic &&
 	oid=$(git rev-parse HEAD) &&
 
@@ -592,8 +560,7 @@
 '
 
 test_expect_success '--refmap="" ignores configured refspec' '
-	cd "$TRASH_DIRECTORY" &&
-	git clone "$D" remote-refs &&
+	git clone . remote-refs &&
 	git -C remote-refs rev-parse remotes/origin/main >old &&
 	git -C remote-refs update-ref refs/remotes/origin/main main~1 &&
 	git -C remote-refs rev-parse remotes/origin/main >new &&
@@ -617,34 +584,26 @@
 
 test_expect_success 'fetch tags when there is no tags' '
 
-    cd "$D" &&
-
-    mkdir notags &&
-    cd notags &&
-    git init &&
-
-    git fetch -t ..
+	git init notags &&
+	git -C notags fetch -t ..
 
 '
 
 test_expect_success 'fetch following tags' '
 
-	cd "$D" &&
 	git tag -a -m "annotated" anno HEAD &&
 	git tag light HEAD &&
 
-	mkdir four &&
-	cd four &&
-	git init &&
-
-	git fetch .. :track &&
-	git show-ref --verify refs/tags/anno &&
-	git show-ref --verify refs/tags/light
-
+	git init four &&
+	(
+		cd four &&
+		git fetch .. :track &&
+		git show-ref --verify refs/tags/anno &&
+		git show-ref --verify refs/tags/light
+	)
 '
 
 test_expect_success 'fetch uses remote ref names to describe new refs' '
-	cd "$D" &&
 	git init descriptive &&
 	(
 		cd descriptive &&
@@ -672,30 +631,20 @@
 
 test_expect_success 'fetch must not resolve short tag name' '
 
-	cd "$D" &&
-
-	mkdir five &&
-	cd five &&
-	git init &&
-
-	test_must_fail git fetch .. anno:five
+	git init five &&
+	test_must_fail git -C five fetch .. anno:five
 
 '
 
 test_expect_success 'fetch can now resolve short remote name' '
 
-	cd "$D" &&
 	git update-ref refs/remotes/six/HEAD HEAD &&
 
-	mkdir six &&
-	cd six &&
-	git init &&
-
-	git fetch .. six:six
+	git init six &&
+	git -C six fetch .. six:six
 '
 
 test_expect_success 'create bundle 1' '
-	cd "$D" &&
 	echo >file updated again by origin &&
 	git commit -a -m "tip" &&
 	git bundle create --version=3 bundle1 main^..main
@@ -709,35 +658,36 @@
 	OID refs/heads/main
 
 	EOF
-	sed -e "s/$OID_REGEX/OID/g" -e "5q" "$D"/bundle1 >actual &&
+	sed -e "s/$OID_REGEX/OID/g" -e "5q" bundle1 >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success 'create bundle 2' '
-	cd "$D" &&
 	git bundle create bundle2 main~2..main
 '
 
 test_expect_success 'unbundle 1' '
-	cd "$D/bundle" &&
-	git checkout -b some-branch &&
-	test_must_fail git fetch "$D/bundle1" main:main
+	(
+		cd bundle &&
+		git checkout -b some-branch &&
+		test_must_fail git fetch bundle1 main:main
+	)
 '
 
 
 test_expect_success 'bundle 1 has only 3 files ' '
-	cd "$D" &&
 	test_bundle_object_count bundle1 3
 '
 
 test_expect_success 'unbundle 2' '
-	cd "$D/bundle" &&
-	git fetch ../bundle2 main:main &&
-	test "tip" = "$(git log -1 --pretty=oneline main | cut -d" " -f2)"
+	(
+		cd bundle &&
+		git fetch ../bundle2 main:main &&
+		test "tip" = "$(git log -1 --pretty=oneline main | cut -d" " -f2)"
+	)
 '
 
 test_expect_success 'bundle does not prerequisite objects' '
-	cd "$D" &&
 	touch file2 &&
 	git add file2 &&
 	git commit -m add.file2 file2 &&
@@ -747,7 +697,6 @@
 
 test_expect_success 'bundle should be able to create a full history' '
 
-	cd "$D" &&
 	git tag -a -m "1.0" v1.0 main &&
 	git bundle create bundle4 v1.0
 
@@ -801,7 +750,6 @@
 
 test_expect_success 'bundle should record HEAD correctly' '
 
-	cd "$D" &&
 	git bundle create bundle5 HEAD main &&
 	git bundle list-heads bundle5 >actual &&
 	for h in HEAD refs/heads/main
@@ -821,7 +769,6 @@
 
 test_expect_success 'explicit fetch should update tracking' '
 
-	cd "$D" &&
 	git branch -f side &&
 	(
 		cd three &&
@@ -836,7 +783,6 @@
 
 test_expect_success 'explicit pull should update tracking' '
 
-	cd "$D" &&
 	git branch -f side &&
 	(
 		cd three &&
@@ -850,7 +796,6 @@
 '
 
 test_expect_success 'explicit --refmap is allowed only with command-line refspec' '
-	cd "$D" &&
 	(
 		cd three &&
 		test_must_fail git fetch --refmap="*:refs/remotes/none/*"
@@ -858,7 +803,6 @@
 '
 
 test_expect_success 'explicit --refmap option overrides remote.*.fetch' '
-	cd "$D" &&
 	git branch -f side &&
 	(
 		cd three &&
@@ -873,7 +817,6 @@
 '
 
 test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '
-	cd "$D" &&
 	git branch -f side &&
 	(
 		cd three &&
@@ -888,7 +831,6 @@
 
 test_expect_success 'configured fetch updates tracking' '
 
-	cd "$D" &&
 	git branch -f side &&
 	(
 		cd three &&
@@ -902,7 +844,6 @@
 '
 
 test_expect_success 'non-matching refspecs do not confuse tracking update' '
-	cd "$D" &&
 	git update-ref refs/odd/location HEAD &&
 	(
 		cd three &&
@@ -919,14 +860,12 @@
 
 test_expect_success 'pushing nonexistent branch by mistake should not segv' '
 
-	cd "$D" &&
 	test_must_fail git push seven no:no
 
 '
 
 test_expect_success 'auto tag following fetches minimum' '
 
-	cd "$D" &&
 	git clone .git follow &&
 	git checkout HEAD^0 &&
 	(
@@ -1325,7 +1264,7 @@
 		cd only-prunes &&
 		git fetch --prune origin 2>&1 | head -n1 >../actual
 	) &&
-	echo "From ${D}/." >expect &&
+	echo "From $(pwd)/." >expect &&
 	test_cmp expect actual
 '
 
@@ -1375,14 +1314,14 @@
 	echo "$*" &&
 	false
 	EOF
-	git clone "file://$D" auto-gc &&
+	git clone "file://$PWD" auto-gc &&
 	test_commit test2 &&
 	(
 		cd auto-gc &&
 		git config fetch.unpackLimit 1 &&
 		git config gc.autoPackLimit 1 &&
 		git config gc.autoDetach false &&
-		GIT_ASK_YESNO="$D/askyesno" git fetch --verbose >fetch.out 2>&1 &&
+		GIT_ASK_YESNO="$TRASH_DIRECTORY/askyesno" git fetch --verbose >fetch.out 2>&1 &&
 		test_grep "Auto packing the repository" fetch.out &&
 		! grep "Should I try again" fetch.out
 	)
diff --git a/t/t5710-promisor-remote-capability.sh b/t/t5710-promisor-remote-capability.sh
index cb061b1..023735d 100755
--- a/t/t5710-promisor-remote-capability.sh
+++ b/t/t5710-promisor-remote-capability.sh
@@ -295,6 +295,71 @@
 	check_missing_objects server 1 "$oid"
 '
 
+test_expect_success "clone with promisor.sendFields" '
+	git -C server config promisor.advertise true &&
+	test_when_finished "rm -rf client" &&
+
+	git -C server remote add otherLop "https://invalid.invalid"  &&
+	git -C server config remote.otherLop.token "fooBar" &&
+	git -C server config remote.otherLop.stuff "baz" &&
+	git -C server config remote.otherLop.partialCloneFilter "blob:limit=10k" &&
+	test_when_finished "git -C server remote remove otherLop" &&
+	test_config -C server promisor.sendFields "partialCloneFilter, token" &&
+	test_when_finished "rm trace" &&
+
+	# Clone from server to create a client
+	GIT_TRACE_PACKET="$(pwd)/trace" GIT_NO_LAZY_FETCH=0 git clone \
+		-c remote.lop.promisor=true \
+		-c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \
+		-c remote.lop.url="file://$(pwd)/lop" \
+		-c promisor.acceptfromserver=All \
+		--no-local --filter="blob:limit=5k" server client &&
+
+	# Check that fields are properly transmitted
+	ENCODED_URL=$(echo "file://$(pwd)/lop" | sed -e "s/ /%20/g") &&
+	PR1="name=lop,url=$ENCODED_URL,partialCloneFilter=blob:none" &&
+	PR2="name=otherLop,url=https://invalid.invalid,partialCloneFilter=blob:limit=10k,token=fooBar" &&
+	test_grep "clone< promisor-remote=$PR1;$PR2" trace &&
+	test_grep "clone> promisor-remote=lop;otherLop" trace &&
+
+	# Check that the largest object is still missing on the server
+	check_missing_objects server 1 "$oid"
+'
+
+test_expect_success "clone with promisor.checkFields" '
+	git -C server config promisor.advertise true &&
+	test_when_finished "rm -rf client" &&
+
+	git -C server remote add otherLop "https://invalid.invalid"  &&
+	git -C server config remote.otherLop.token "fooBar" &&
+	git -C server config remote.otherLop.stuff "baz" &&
+	git -C server config remote.otherLop.partialCloneFilter "blob:limit=10k" &&
+	test_when_finished "git -C server remote remove otherLop" &&
+	test_config -C server promisor.sendFields "partialCloneFilter, token" &&
+	test_when_finished "rm trace" &&
+
+	# Clone from server to create a client
+	GIT_TRACE_PACKET="$(pwd)/trace" GIT_NO_LAZY_FETCH=0 git clone \
+		-c remote.lop.promisor=true \
+		-c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \
+		-c remote.lop.url="file://$(pwd)/lop" \
+		-c remote.lop.partialCloneFilter="blob:none" \
+		-c promisor.acceptfromserver=All \
+		-c promisor.checkFields=partialcloneFilter \
+		--no-local --filter="blob:limit=5k" server client &&
+
+	# Check that fields are properly transmitted
+	ENCODED_URL=$(echo "file://$(pwd)/lop" | sed -e "s/ /%20/g") &&
+	PR1="name=lop,url=$ENCODED_URL,partialCloneFilter=blob:none" &&
+	PR2="name=otherLop,url=https://invalid.invalid,partialCloneFilter=blob:limit=10k,token=fooBar" &&
+	test_grep "clone< promisor-remote=$PR1;$PR2" trace &&
+	test_grep "clone> promisor-remote=lop" trace &&
+	test_grep ! "clone> promisor-remote=lop;otherLop" trace &&
+
+	# Check that the largest object is still missing on the server
+	check_missing_objects server 1 "$oid"
+'
+
 test_expect_success "clone with promisor.advertise set to 'true' but don't delete the client" '
 	git -C server config promisor.advertise true &&
 
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 256ccae..2c70cc5 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -409,6 +409,36 @@
 	test_grep "fatal: test-blob-1 is neither a commit nor blob" actual
 '
 
+test_expect_success 'describe an unreachable blob' '
+	blob=$(echo not-found-anywhere | git hash-object -w --stdin) &&
+	test_must_fail git describe $blob 2>actual &&
+	test_grep "blob .$blob. not reachable from HEAD" actual
+'
+
+test_expect_success 'describe blob on an unborn branch' '
+	oldbranch=$(git symbolic-ref HEAD) &&
+	test_when_finished "git symbolic-ref HEAD $oldbranch" &&
+	git symbolic-ref HEAD refs/heads/does-not-exist &&
+	test_must_fail git describe test-blob 2>actual &&
+	test_grep "cannot search .* on an unborn branch" actual
+'
+
+# This test creates a repository state that we generally try to disallow: HEAD
+# is pointing to an object that is not a commit. The ref update code forbids
+# non-commit writes directly to HEAD or to any branch in refs/heads/.  But we
+# can use the loophole of pointing HEAD to another non-branch ref (something we
+# should forbid, but don't for historical reasons).
+#
+# Do not take this test as an endorsement of the loophole! If we ever tighten
+# it, it is reasonable to just drop this test entirely.
+test_expect_success 'describe blob on a non-commit HEAD' '
+	oldbranch=$(git symbolic-ref HEAD) &&
+	test_when_finished "git symbolic-ref HEAD $oldbranch" &&
+	git symbolic-ref HEAD refs/tags/test-blob &&
+	test_must_fail git describe test-blob 2>actual &&
+	test_grep "blob .* not reachable from HEAD" actual
+'
+
 test_expect_success ULIMIT_STACK_SIZE 'name-rev works in a deep repo' '
 	i=1 &&
 	while test $i -lt 8000
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index ce9af79..1d98091 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -6,2150 +6,14 @@
 test_description='for-each-ref test'
 
 . ./test-lib.sh
-GNUPGHOME_NOT_USED=$GNUPGHOME
-. "$TEST_DIRECTORY"/lib-gpg.sh
-. "$TEST_DIRECTORY"/lib-terminal.sh
 
-# Mon Jul 3 23:18:43 2006 +0000
-datestamp=1151968723
-setdate_and_increment () {
-    GIT_COMMITTER_DATE="$datestamp +0200"
-    datestamp=$(expr "$datestamp" + 1)
-    GIT_AUTHOR_DATE="$datestamp +0200"
-    datestamp=$(expr "$datestamp" + 1)
-    export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
-}
-
-test_object_file_size () {
-	oid=$(git rev-parse "$1")
-	path=".git/objects/$(test_oid_to_path $oid)"
-	test_file_size "$path"
-}
-
-test_expect_success setup '
-	# setup .mailmap
-	cat >.mailmap <<-EOF &&
-	A Thor <athor@example.com> A U Thor <author@example.com>
-	C Mitter <cmitter@example.com> C O Mitter <committer@example.com>
-	EOF
-
-	setdate_and_increment &&
-	echo "Using $datestamp" > one &&
-	git add one &&
-	git commit -m "Initial" &&
-	git branch -M main &&
-	setdate_and_increment &&
-	git tag -a -m "Tagging at $datestamp" testtag &&
-	git update-ref refs/remotes/origin/main main &&
-	git remote add origin nowhere &&
-	git config branch.main.remote origin &&
-	git config branch.main.merge refs/heads/main &&
-	git remote add myfork elsewhere &&
-	git config remote.pushdefault myfork &&
-	git config push.default current
-'
-
-test_atom () {
-	case "$1" in
-		head) ref=refs/heads/main ;;
-		 tag) ref=refs/tags/testtag ;;
-		 sym) ref=refs/heads/sym ;;
-		   *) ref=$1 ;;
-	esac
-	format=$2
-	test_do=test_expect_${4:-success}
-
-	printf '%s\n' "$3" >expected
-	$test_do $PREREQ "basic atom: $ref $format" '
-		git for-each-ref --format="%($format)" "$ref" >actual &&
-		sanitize_pgp <actual >actual.clean &&
-		test_cmp expected actual.clean
-	'
-
-	# Automatically test "contents:size" atom after testing "contents"
-	if test "$format" = "contents"
-	then
-		# for commit leg, $3 is changed there
-		expect=$(printf '%s' "$3" | wc -c)
-		$test_do $PREREQ "basic atom: $ref contents:size" '
-			type=$(git cat-file -t "$ref") &&
-			case $type in
-			tag)
-				# We cannot use $3 as it expects sanitize_pgp to run
-				git cat-file tag $ref >out &&
-				expect=$(tail -n +6 out | wc -c) &&
-				rm -f out ;;
-			tree | blob)
-				expect="" ;;
-			commit)
-				: "use the calculated expect" ;;
-			*)
-				BUG "unknown object type" ;;
-			esac &&
-			# Leave $expect unquoted to lose possible leading whitespaces
-			echo $expect >expected &&
-			git for-each-ref --format="%(contents:size)" "$ref" >actual &&
-			test_cmp expected actual
-		'
-	fi
-}
-
-hexlen=$(test_oid hexsz)
-
-test_atom head refname refs/heads/main
-test_atom head refname: refs/heads/main
-test_atom head refname:short main
-test_atom head refname:lstrip=1 heads/main
-test_atom head refname:lstrip=2 main
-test_atom head refname:lstrip=-1 main
-test_atom head refname:lstrip=-2 heads/main
-test_atom head refname:rstrip=1 refs/heads
-test_atom head refname:rstrip=2 refs
-test_atom head refname:rstrip=-1 refs
-test_atom head refname:rstrip=-2 refs/heads
-test_atom head refname:strip=1 heads/main
-test_atom head refname:strip=2 main
-test_atom head refname:strip=-1 main
-test_atom head refname:strip=-2 heads/main
-test_atom head upstream refs/remotes/origin/main
-test_atom head upstream:short origin/main
-test_atom head upstream:lstrip=2 origin/main
-test_atom head upstream:lstrip=-2 origin/main
-test_atom head upstream:rstrip=2 refs/remotes
-test_atom head upstream:rstrip=-2 refs/remotes
-test_atom head upstream:strip=2 origin/main
-test_atom head upstream:strip=-2 origin/main
-test_atom head push refs/remotes/myfork/main
-test_atom head push:short myfork/main
-test_atom head push:lstrip=1 remotes/myfork/main
-test_atom head push:lstrip=-1 main
-test_atom head push:rstrip=1 refs/remotes/myfork
-test_atom head push:rstrip=-1 refs
-test_atom head push:strip=1 remotes/myfork/main
-test_atom head push:strip=-1 main
-test_atom head objecttype commit
-test_atom head objectsize $((131 + hexlen))
-test_atom head objectsize:disk $(test_object_file_size refs/heads/main)
-test_atom head deltabase $ZERO_OID
-test_atom head objectname $(git rev-parse refs/heads/main)
-test_atom head objectname:short $(git rev-parse --short refs/heads/main)
-test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
-test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
-test_atom head tree $(git rev-parse refs/heads/main^{tree})
-test_atom head tree:short $(git rev-parse --short refs/heads/main^{tree})
-test_atom head tree:short=1 $(git rev-parse --short=1 refs/heads/main^{tree})
-test_atom head tree:short=10 $(git rev-parse --short=10 refs/heads/main^{tree})
-test_atom head parent ''
-test_atom head parent:short ''
-test_atom head parent:short=1 ''
-test_atom head parent:short=10 ''
-test_atom head numparent 0
-test_atom head object ''
-test_atom head type ''
-test_atom head raw "$(git cat-file commit refs/heads/main)
-"
-test_atom head '*objectname' ''
-test_atom head '*objecttype' ''
-test_atom head author 'A U Thor <author@example.com> 1151968724 +0200'
-test_atom head authorname 'A U Thor'
-test_atom head authorname:mailmap 'A Thor'
-test_atom head authoremail '<author@example.com>'
-test_atom head authoremail:trim 'author@example.com'
-test_atom head authoremail:localpart 'author'
-test_atom head authoremail:trim,localpart 'author'
-test_atom head authoremail:mailmap '<athor@example.com>'
-test_atom head authoremail:mailmap,trim 'athor@example.com'
-test_atom head authoremail:trim,mailmap 'athor@example.com'
-test_atom head authoremail:mailmap,localpart 'athor'
-test_atom head authoremail:localpart,mailmap 'athor'
-test_atom head authoremail:mailmap,trim,localpart,mailmap,trim 'athor'
-test_atom head authordate 'Tue Jul 4 01:18:44 2006 +0200'
-test_atom head committer 'C O Mitter <committer@example.com> 1151968723 +0200'
-test_atom head committername 'C O Mitter'
-test_atom head committername:mailmap 'C Mitter'
-test_atom head committeremail '<committer@example.com>'
-test_atom head committeremail:trim 'committer@example.com'
-test_atom head committeremail:localpart 'committer'
-test_atom head committeremail:localpart,trim 'committer'
-test_atom head committeremail:mailmap '<cmitter@example.com>'
-test_atom head committeremail:mailmap,trim 'cmitter@example.com'
-test_atom head committeremail:trim,mailmap 'cmitter@example.com'
-test_atom head committeremail:mailmap,localpart 'cmitter'
-test_atom head committeremail:localpart,mailmap 'cmitter'
-test_atom head committeremail:trim,mailmap,trim,trim,localpart 'cmitter'
-test_atom head committerdate 'Tue Jul 4 01:18:43 2006 +0200'
-test_atom head tag ''
-test_atom head tagger ''
-test_atom head taggername ''
-test_atom head taggeremail ''
-test_atom head taggeremail:trim ''
-test_atom head taggeremail:localpart ''
-test_atom head taggerdate ''
-test_atom head creator 'C O Mitter <committer@example.com> 1151968723 +0200'
-test_atom head creatordate 'Tue Jul 4 01:18:43 2006 +0200'
-test_atom head subject 'Initial'
-test_atom head subject:sanitize 'Initial'
-test_atom head contents:subject 'Initial'
-test_atom head body ''
-test_atom head contents:body ''
-test_atom head contents:signature ''
-test_atom head contents 'Initial
-'
-test_atom head HEAD '*'
-
-test_atom tag refname refs/tags/testtag
-test_atom tag refname:short testtag
-test_atom tag upstream ''
-test_atom tag push ''
-test_atom tag objecttype tag
-test_atom tag objectsize $((114 + hexlen))
-test_atom tag objectsize:disk $(test_object_file_size refs/tags/testtag)
-test_atom tag '*objectsize:disk' $(test_object_file_size refs/heads/main)
-test_atom tag deltabase $ZERO_OID
-test_atom tag '*deltabase' $ZERO_OID
-test_atom tag objectname $(git rev-parse refs/tags/testtag)
-test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag)
-test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
-test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
-test_atom tag tree ''
-test_atom tag tree:short ''
-test_atom tag tree:short=1 ''
-test_atom tag tree:short=10 ''
-test_atom tag parent ''
-test_atom tag parent:short ''
-test_atom tag parent:short=1 ''
-test_atom tag parent:short=10 ''
-test_atom tag numparent ''
-test_atom tag object $(git rev-parse refs/tags/testtag^0)
-test_atom tag type 'commit'
-test_atom tag '*objectname' $(git rev-parse refs/tags/testtag^{})
-test_atom tag '*objecttype' 'commit'
-test_atom tag author ''
-test_atom tag authorname ''
-test_atom tag authorname:mailmap ''
-test_atom tag authoremail ''
-test_atom tag authoremail:trim ''
-test_atom tag authoremail:localpart ''
-test_atom tag authoremail:trim,localpart ''
-test_atom tag authoremail:mailmap ''
-test_atom tag authoremail:mailmap,trim ''
-test_atom tag authoremail:trim,mailmap ''
-test_atom tag authoremail:mailmap,localpart ''
-test_atom tag authoremail:localpart,mailmap ''
-test_atom tag authoremail:mailmap,trim,localpart,mailmap,trim ''
-test_atom tag authordate ''
-test_atom tag committer ''
-test_atom tag committername ''
-test_atom tag committername:mailmap ''
-test_atom tag committeremail ''
-test_atom tag committeremail:trim ''
-test_atom tag committeremail:localpart ''
-test_atom tag committeremail:localpart,trim ''
-test_atom tag committeremail:mailmap ''
-test_atom tag committeremail:mailmap,trim ''
-test_atom tag committeremail:trim,mailmap ''
-test_atom tag committeremail:mailmap,localpart ''
-test_atom tag committeremail:localpart,mailmap ''
-test_atom tag committeremail:trim,mailmap,trim,trim,localpart ''
-test_atom tag committerdate ''
-test_atom tag tag 'testtag'
-test_atom tag tagger 'C O Mitter <committer@example.com> 1151968725 +0200'
-test_atom tag taggername 'C O Mitter'
-test_atom tag taggername:mailmap 'C Mitter'
-test_atom tag taggeremail '<committer@example.com>'
-test_atom tag taggeremail:trim 'committer@example.com'
-test_atom tag taggeremail:localpart 'committer'
-test_atom tag taggeremail:trim,localpart 'committer'
-test_atom tag taggeremail:mailmap '<cmitter@example.com>'
-test_atom tag taggeremail:mailmap,trim 'cmitter@example.com'
-test_atom tag taggeremail:trim,mailmap 'cmitter@example.com'
-test_atom tag taggeremail:mailmap,localpart 'cmitter'
-test_atom tag taggeremail:localpart,mailmap 'cmitter'
-test_atom tag taggeremail:trim,mailmap,trim,localpart,localpart 'cmitter'
-test_atom tag taggerdate 'Tue Jul 4 01:18:45 2006 +0200'
-test_atom tag creator 'C O Mitter <committer@example.com> 1151968725 +0200'
-test_atom tag creatordate 'Tue Jul 4 01:18:45 2006 +0200'
-test_atom tag subject 'Tagging at 1151968727'
-test_atom tag subject:sanitize 'Tagging-at-1151968727'
-test_atom tag contents:subject 'Tagging at 1151968727'
-test_atom tag body ''
-test_atom tag contents:body ''
-test_atom tag contents:signature ''
-test_atom tag contents 'Tagging at 1151968727
-'
-test_atom tag HEAD ' '
-
-test_expect_success 'basic atom: refs/tags/testtag *raw' '
-	git cat-file commit refs/tags/testtag^{} >expected &&
-	git for-each-ref --format="%(*raw)" refs/tags/testtag >actual &&
-	sanitize_pgp <expected >expected.clean &&
-	echo >>expected.clean &&
-	sanitize_pgp <actual >actual.clean &&
-	test_cmp expected.clean actual.clean
-'
-
-test_expect_success 'Check invalid atoms names are errors' '
-	test_must_fail git for-each-ref --format="%(INVALID)" refs/heads
-'
-
-test_expect_success 'for-each-ref does not crash with -h' '
+test_expect_success "for-each-ref does not crash with -h" '
 	test_expect_code 129 git for-each-ref -h >usage &&
 	test_grep "[Uu]sage: git for-each-ref " usage &&
 	test_expect_code 129 nongit git for-each-ref -h >usage &&
 	test_grep "[Uu]sage: git for-each-ref " usage
 '
 
-test_expect_success 'Check format specifiers are ignored in naming date atoms' '
-	git for-each-ref --format="%(authordate)" refs/heads &&
-	git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads &&
-	git for-each-ref --format="%(authordate) %(authordate:default)" refs/heads &&
-	git for-each-ref --format="%(authordate:default) %(authordate:default)" refs/heads
-'
-
-test_expect_success 'Check valid format specifiers for date fields' '
-	git for-each-ref --format="%(authordate:default)" refs/heads &&
-	git for-each-ref --format="%(authordate:relative)" refs/heads &&
-	git for-each-ref --format="%(authordate:short)" refs/heads &&
-	git for-each-ref --format="%(authordate:local)" refs/heads &&
-	git for-each-ref --format="%(authordate:iso8601)" refs/heads &&
-	git for-each-ref --format="%(authordate:rfc2822)" refs/heads
-'
-
-test_expect_success 'Check invalid format specifiers are errors' '
-	test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads
-'
-
-test_expect_success 'arguments to %(objectname:short=) must be positive integers' '
-	test_must_fail git for-each-ref --format="%(objectname:short=0)" &&
-	test_must_fail git for-each-ref --format="%(objectname:short=-1)" &&
-	test_must_fail git for-each-ref --format="%(objectname:short=foo)"
-'
-
-test_bad_atom () {
-	case "$1" in
-	head) ref=refs/heads/main ;;
-	 tag) ref=refs/tags/testtag ;;
-	 sym) ref=refs/heads/sym ;;
-	   *) ref=$1 ;;
-	esac
-	format=$2
-	test_do=test_expect_${4:-success}
-
-	printf '%s\n' "$3" >expect
-	$test_do $PREREQ "err basic atom: $ref $format" '
-		test_must_fail git for-each-ref \
-			--format="%($format)" "$ref" 2>error &&
-		test_cmp expect error
-	'
-}
-
-test_bad_atom head 'authoremail:foo' \
-	'fatal: unrecognized %(authoremail) argument: foo'
-
-test_bad_atom head 'authoremail:mailmap,trim,bar' \
-	'fatal: unrecognized %(authoremail) argument: bar'
-
-test_bad_atom head 'authoremail:trim,' \
-	'fatal: unrecognized %(authoremail) argument: '
-
-test_bad_atom head 'authoremail:mailmaptrim' \
-	'fatal: unrecognized %(authoremail) argument: trim'
-
-test_bad_atom head 'committeremail: ' \
-	'fatal: unrecognized %(committeremail) argument:  '
-
-test_bad_atom head 'committeremail: trim,foo' \
-	'fatal: unrecognized %(committeremail) argument:  trim,foo'
-
-test_bad_atom head 'committeremail:mailmap,localpart ' \
-	'fatal: unrecognized %(committeremail) argument:  '
-
-test_bad_atom head 'committeremail:trim_localpart' \
-	'fatal: unrecognized %(committeremail) argument: _localpart'
-
-test_bad_atom head 'committeremail:localpart,,,trim' \
-	'fatal: unrecognized %(committeremail) argument: ,,trim'
-
-test_bad_atom tag 'taggeremail:mailmap,trim, foo ' \
-	'fatal: unrecognized %(taggeremail) argument:  foo '
-
-test_bad_atom tag 'taggeremail:trim,localpart,' \
-	'fatal: unrecognized %(taggeremail) argument: '
-
-test_bad_atom tag 'taggeremail:mailmap;localpart trim' \
-	'fatal: unrecognized %(taggeremail) argument: ;localpart trim'
-
-test_bad_atom tag 'taggeremail:localpart trim' \
-	'fatal: unrecognized %(taggeremail) argument:  trim'
-
-test_bad_atom tag 'taggeremail:mailmap,mailmap,trim,qux,localpart,trim' \
-	'fatal: unrecognized %(taggeremail) argument: qux,localpart,trim'
-
-test_date () {
-	f=$1 &&
-	committer_date=$2 &&
-	author_date=$3 &&
-	tagger_date=$4 &&
-	cat >expected <<-EOF &&
-	'refs/heads/main' '$committer_date' '$author_date'
-	'refs/tags/testtag' '$tagger_date'
-	EOF
-	(
-		git for-each-ref --shell \
-			--format="%(refname) %(committerdate${f:+:$f}) %(authordate${f:+:$f})" \
-			refs/heads &&
-		git for-each-ref --shell \
-			--format="%(refname) %(taggerdate${f:+:$f})" \
-			refs/tags
-	) >actual &&
-	test_cmp expected actual
-}
-
-test_expect_success 'Check unformatted date fields output' '
-	test_date "" \
-		"Tue Jul 4 01:18:43 2006 +0200" \
-		"Tue Jul 4 01:18:44 2006 +0200" \
-		"Tue Jul 4 01:18:45 2006 +0200"
-'
-
-test_expect_success 'Check format "default" formatted date fields output' '
-	test_date default \
-		"Tue Jul 4 01:18:43 2006 +0200" \
-		"Tue Jul 4 01:18:44 2006 +0200" \
-		"Tue Jul 4 01:18:45 2006 +0200"
-'
-
-test_expect_success 'Check format "default-local" date fields output' '
-	test_date default-local "Mon Jul 3 23:18:43 2006" "Mon Jul 3 23:18:44 2006" "Mon Jul 3 23:18:45 2006"
-'
-
-# Don't know how to do relative check because I can't know when this script
-# is going to be run and can't fake the current time to git, and hence can't
-# provide expected output.  Instead, I'll just make sure that "relative"
-# doesn't exit in error
-test_expect_success 'Check format "relative" date fields output' '
-	f=relative &&
-	(git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
-	git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual
-'
-
-# We just check that this is the same as "relative" for now.
-test_expect_success 'Check format "relative-local" date fields output' '
-	test_date relative-local \
-		"$(git for-each-ref --format="%(committerdate:relative)" refs/heads)" \
-		"$(git for-each-ref --format="%(authordate:relative)" refs/heads)" \
-		"$(git for-each-ref --format="%(taggerdate:relative)" refs/tags)"
-'
-
-test_expect_success 'Check format "short" date fields output' '
-	test_date short 2006-07-04 2006-07-04 2006-07-04
-'
-
-test_expect_success 'Check format "short-local" date fields output' '
-	test_date short-local 2006-07-03 2006-07-03 2006-07-03
-'
-
-test_expect_success 'Check format "local" date fields output' '
-	test_date local \
-		"Mon Jul 3 23:18:43 2006" \
-		"Mon Jul 3 23:18:44 2006" \
-		"Mon Jul 3 23:18:45 2006"
-'
-
-test_expect_success 'Check format "iso8601" date fields output' '
-	test_date iso8601 \
-		"2006-07-04 01:18:43 +0200" \
-		"2006-07-04 01:18:44 +0200" \
-		"2006-07-04 01:18:45 +0200"
-'
-
-test_expect_success 'Check format "iso8601-local" date fields output' '
-	test_date iso8601-local "2006-07-03 23:18:43 +0000" "2006-07-03 23:18:44 +0000" "2006-07-03 23:18:45 +0000"
-'
-
-test_expect_success 'Check format "rfc2822" date fields output' '
-	test_date rfc2822 \
-		"Tue, 4 Jul 2006 01:18:43 +0200" \
-		"Tue, 4 Jul 2006 01:18:44 +0200" \
-		"Tue, 4 Jul 2006 01:18:45 +0200"
-'
-
-test_expect_success 'Check format "rfc2822-local" date fields output' '
-	test_date rfc2822-local "Mon, 3 Jul 2006 23:18:43 +0000" "Mon, 3 Jul 2006 23:18:44 +0000" "Mon, 3 Jul 2006 23:18:45 +0000"
-'
-
-test_expect_success 'Check format "raw" date fields output' '
-	test_date raw "1151968723 +0200" "1151968724 +0200" "1151968725 +0200"
-'
-
-test_expect_success 'Check format "raw-local" date fields output' '
-	test_date raw-local "1151968723 +0000" "1151968724 +0000" "1151968725 +0000"
-'
-
-test_expect_success 'Check format of strftime date fields' '
-	echo "my date is 2006-07-04" >expected &&
-	git for-each-ref \
-	  --format="%(authordate:format:my date is %Y-%m-%d)" \
-	  refs/heads >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'Check format of strftime-local date fields' '
-	echo "my date is 2006-07-03" >expected &&
-	git for-each-ref \
-	  --format="%(authordate:format-local:my date is %Y-%m-%d)" \
-	  refs/heads >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'exercise strftime with odd fields' '
-	echo >expected &&
-	git for-each-ref --format="%(authordate:format:)" refs/heads >actual &&
-	test_cmp expected actual &&
-	long="long format -- $ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID" &&
-	echo $long >expected &&
-	git for-each-ref --format="%(authordate:format:$long)" refs/heads >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<\EOF
-refs/heads/main
-refs/remotes/origin/main
-refs/tags/testtag
-EOF
-
-test_expect_success 'Verify ascending sort' '
-	git for-each-ref --format="%(refname)" --sort=refname >actual &&
-	test_cmp expected actual
-'
-
-
-cat >expected <<\EOF
-refs/tags/testtag
-refs/remotes/origin/main
-refs/heads/main
-EOF
-
-test_expect_success 'Verify descending sort' '
-	git for-each-ref --format="%(refname)" --sort=-refname >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'Give help even with invalid sort atoms' '
-	test_expect_code 129 git for-each-ref --sort=bogus -h >actual 2>&1 &&
-	grep "^usage: git for-each-ref" actual
-'
-
-cat >expected <<\EOF
-refs/tags/testtag
-refs/tags/testtag-2
-EOF
-
-test_expect_success 'exercise patterns with prefixes' '
-	git tag testtag-2 &&
-	test_when_finished "git tag -d testtag-2" &&
-	git for-each-ref --format="%(refname)" \
-		refs/tags/testtag refs/tags/testtag-2 >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<\EOF
-refs/tags/testtag
-refs/tags/testtag-2
-EOF
-
-test_expect_success 'exercise glob patterns with prefixes' '
-	git tag testtag-2 &&
-	test_when_finished "git tag -d testtag-2" &&
-	git for-each-ref --format="%(refname)" \
-		refs/tags/testtag "refs/tags/testtag-*" >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<\EOF
-refs/tags/bar
-refs/tags/baz
-refs/tags/testtag
-EOF
-
-test_expect_success 'exercise patterns with prefix exclusions' '
-	for tag in foo/one foo/two foo/three bar baz
-	do
-		git tag "$tag" || return 1
-	done &&
-	test_when_finished "git tag -d foo/one foo/two foo/three bar baz" &&
-	git for-each-ref --format="%(refname)" \
-		refs/tags/ --exclude=refs/tags/foo >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<\EOF
-refs/tags/bar
-refs/tags/baz
-refs/tags/foo/one
-refs/tags/testtag
-EOF
-
-test_expect_success 'exercise patterns with pattern exclusions' '
-	for tag in foo/one foo/two foo/three bar baz
-	do
-		git tag "$tag" || return 1
-	done &&
-	test_when_finished "git tag -d foo/one foo/two foo/three bar baz" &&
-	git for-each-ref --format="%(refname)" \
-		refs/tags/ --exclude="refs/tags/foo/t*" >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<\EOF
-'refs/heads/main'
-'refs/remotes/origin/main'
-'refs/tags/testtag'
-EOF
-
-test_expect_success 'Quoting style: shell' '
-	git for-each-ref --shell --format="%(refname)" >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'Quoting style: perl' '
-	git for-each-ref --perl --format="%(refname)" >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'Quoting style: python' '
-	git for-each-ref --python --format="%(refname)" >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<\EOF
-"refs/heads/main"
-"refs/remotes/origin/main"
-"refs/tags/testtag"
-EOF
-
-test_expect_success 'Quoting style: tcl' '
-	git for-each-ref --tcl --format="%(refname)" >actual &&
-	test_cmp expected actual
-'
-
-for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
-	test_expect_success "more than one quoting style: $i" "
-		test_must_fail git for-each-ref $i 2>err &&
-		grep '^error: more than one quoting style' err
-	"
-done
-
-test_expect_success 'setup for upstream:track[short]' '
-	test_commit two
-'
-
-test_atom head upstream:track '[ahead 1]'
-test_atom head upstream:trackshort '>'
-test_atom head upstream:track,nobracket 'ahead 1'
-test_atom head upstream:nobracket,track 'ahead 1'
-
-test_expect_success 'setup for push:track[short]' '
-	test_commit third &&
-	git update-ref refs/remotes/myfork/main main &&
-	git reset main~1
-'
-
-test_atom head push:track '[behind 1]'
-test_atom head push:trackshort '<'
-
-test_expect_success 'Check that :track[short] cannot be used with other atoms' '
-	test_must_fail git for-each-ref --format="%(refname:track)" 2>/dev/null &&
-	test_must_fail git for-each-ref --format="%(refname:trackshort)" 2>/dev/null
-'
-
-test_expect_success 'Check that :track[short] works when upstream is invalid' '
-	cat >expected <<-\EOF &&
-	[gone]
-
-	EOF
-	test_when_finished "git config branch.main.merge refs/heads/main" &&
-	git config branch.main.merge refs/heads/does-not-exist &&
-	git for-each-ref \
-		--format="%(upstream:track)$LF%(upstream:trackshort)" \
-		refs/heads >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'Check for invalid refname format' '
-	test_must_fail git for-each-ref --format="%(refname:INVALID)"
-'
-
-test_expect_success 'set up color tests' '
-	cat >expected.color <<-EOF &&
-	$(git rev-parse --short refs/heads/main) <GREEN>main<RESET>
-	$(git rev-parse --short refs/remotes/myfork/main) <GREEN>myfork/main<RESET>
-	$(git rev-parse --short refs/remotes/origin/main) <GREEN>origin/main<RESET>
-	$(git rev-parse --short refs/tags/testtag) <GREEN>testtag<RESET>
-	$(git rev-parse --short refs/tags/third) <GREEN>third<RESET>
-	$(git rev-parse --short refs/tags/two) <GREEN>two<RESET>
-	EOF
-	sed "s/<[^>]*>//g" <expected.color >expected.bare &&
-	color_format="%(objectname:short) %(color:green)%(refname:short)"
-'
-
-test_expect_success TTY '%(color) shows color with a tty' '
-	test_terminal git for-each-ref --format="$color_format" >actual.raw &&
-	test_decode_color <actual.raw >actual &&
-	test_cmp expected.color actual
-'
-
-test_expect_success '%(color) does not show color without tty' '
-	TERM=vt100 git for-each-ref --format="$color_format" >actual &&
-	test_cmp expected.bare actual
-'
-
-test_expect_success '--color can override tty check' '
-	git for-each-ref --color --format="$color_format" >actual.raw &&
-	test_decode_color <actual.raw >actual &&
-	test_cmp expected.color actual
-'
-
-test_expect_success 'color.ui=always does not override tty check' '
-	git -c color.ui=always for-each-ref --format="$color_format" >actual &&
-	test_cmp expected.bare actual
-'
-
-test_expect_success 'setup for describe atom tests' '
-	git init -b master describe-repo &&
-	(
-		cd describe-repo &&
-
-		test_commit --no-tag one &&
-		git tag tagone &&
-
-		test_commit --no-tag two &&
-		git tag -a -m "tag two" tagtwo
-	)
-'
-
-test_expect_success 'describe atom vs git describe' '
-	(
-		cd describe-repo &&
-
-		git for-each-ref --format="%(objectname)" \
-			refs/tags/ >obj &&
-		while read hash
-		do
-			if desc=$(git describe $hash)
-			then
-				: >expect-contains-good
-			else
-				: >expect-contains-bad
-			fi &&
-			echo "$hash $desc" || return 1
-		done <obj >expect &&
-		test_path_exists expect-contains-good &&
-		test_path_exists expect-contains-bad &&
-
-		git for-each-ref --format="%(objectname) %(describe)" \
-			refs/tags/ >actual 2>err &&
-		test_cmp expect actual &&
-		test_must_be_empty err
-	)
-'
-
-test_expect_success 'describe:tags vs describe --tags' '
-	(
-		cd describe-repo &&
-		git describe --tags >expect &&
-		git for-each-ref --format="%(describe:tags)" \
-				refs/heads/master >actual &&
-		test_cmp expect actual
-	)
-'
-
-test_expect_success 'describe:abbrev=... vs describe --abbrev=...' '
-	(
-		cd describe-repo &&
-
-		# Case 1: We have commits between HEAD and the most
-		#	  recent tag reachable from it
-		test_commit --no-tag file &&
-		git describe --abbrev=14 >expect &&
-		git for-each-ref --format="%(describe:abbrev=14)" \
-			refs/heads/master >actual &&
-		test_cmp expect actual &&
-
-		# Make sure the hash used is at least 14 digits long
-		sed -e "s/^.*-g\([0-9a-f]*\)$/\1/" <actual >hexpart &&
-		test 15 -le $(wc -c <hexpart) &&
-
-		# Case 2: We have a tag at HEAD, describe directly gives
-		#	  the name of the tag
-		git tag -a -m tagged tagname &&
-		git describe --abbrev=14 >expect &&
-		git for-each-ref --format="%(describe:abbrev=14)" \
-			refs/heads/master >actual &&
-		test_cmp expect actual &&
-		test tagname = $(cat actual)
-	)
-'
-
-test_expect_success 'describe:match=... vs describe --match ...' '
-	(
-		cd describe-repo &&
-		git tag -a -m "tag foo" tag-foo &&
-		git describe --match "*-foo" >expect &&
-		git for-each-ref --format="%(describe:match="*-foo")" \
-			refs/heads/master >actual &&
-		test_cmp expect actual
-	)
-'
-
-test_expect_success 'describe:exclude:... vs describe --exclude ...' '
-	(
-		cd describe-repo &&
-		git tag -a -m "tag bar" tag-bar &&
-		git describe --exclude "*-bar" >expect &&
-		git for-each-ref --format="%(describe:exclude="*-bar")" \
-			refs/heads/master >actual &&
-		test_cmp expect actual
-	)
-'
-
-test_expect_success 'deref with describe atom' '
-	(
-		cd describe-repo &&
-		cat >expect <<-\EOF &&
-
-		tagname
-		tagname
-		tagname
-
-		tagtwo
-		EOF
-		git for-each-ref --format="%(*describe)" >actual &&
-		test_cmp expect actual
-	)
-'
-
-test_expect_success 'err on bad describe atom arg' '
-	(
-		cd describe-repo &&
-
-		# The bad arg is the only arg passed to describe atom
-		cat >expect <<-\EOF &&
-		fatal: unrecognized %(describe) argument: baz
-		EOF
-		test_must_fail git for-each-ref --format="%(describe:baz)" \
-			refs/heads/master 2>actual &&
-		test_cmp expect actual &&
-
-		# The bad arg is in the middle of the option string
-		# passed to the describe atom
-		cat >expect <<-\EOF &&
-		fatal: unrecognized %(describe) argument: qux=1,abbrev=14
-		EOF
-		test_must_fail git for-each-ref \
-			--format="%(describe:tags,qux=1,abbrev=14)" \
-			ref/heads/master 2>actual &&
-		test_cmp expect actual
-	)
-'
-
-cat >expected <<\EOF
-heads/main
-tags/main
-EOF
-
-test_expect_success 'Check ambiguous head and tag refs (strict)' '
-	git config --bool core.warnambiguousrefs true &&
-	git checkout -b newtag &&
-	echo "Using $datestamp" > one &&
-	git add one &&
-	git commit -m "Branch" &&
-	setdate_and_increment &&
-	git tag -m "Tagging at $datestamp" main &&
-	git for-each-ref --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<\EOF
-heads/main
-main
-EOF
-
-test_expect_success 'Check ambiguous head and tag refs (loose)' '
-	git config --bool core.warnambiguousrefs false &&
-	git for-each-ref --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<\EOF
-heads/ambiguous
-ambiguous
-EOF
-
-test_expect_success 'Check ambiguous head and tag refs II (loose)' '
-	git checkout main &&
-	git tag ambiguous testtag^0 &&
-	git branch ambiguous testtag^0 &&
-	git for-each-ref --format "%(refname:short)" refs/heads/ambiguous refs/tags/ambiguous >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'create tag without tagger' '
-	git tag -a -m "Broken tag" taggerless &&
-	git tag -f taggerless $(git cat-file tag taggerless |
-		sed -e "/^tagger /d" |
-		git hash-object --literally --stdin -w -t tag)
-'
-
-test_atom refs/tags/taggerless type 'commit'
-test_atom refs/tags/taggerless tag 'taggerless'
-test_atom refs/tags/taggerless tagger ''
-test_atom refs/tags/taggerless taggername ''
-test_atom refs/tags/taggerless taggeremail ''
-test_atom refs/tags/taggerless taggeremail:trim ''
-test_atom refs/tags/taggerless taggeremail:localpart ''
-test_atom refs/tags/taggerless taggerdate ''
-test_atom refs/tags/taggerless committer ''
-test_atom refs/tags/taggerless committername ''
-test_atom refs/tags/taggerless committeremail ''
-test_atom refs/tags/taggerless committeremail:trim ''
-test_atom refs/tags/taggerless committeremail:localpart ''
-test_atom refs/tags/taggerless committerdate ''
-test_atom refs/tags/taggerless subject 'Broken tag'
-
-test_expect_success 'an unusual tag with an incomplete line' '
-
-	git tag -m "bogo" bogo &&
-	bogo=$(git cat-file tag bogo) &&
-	bogo=$(printf "%s" "$bogo" | git mktag) &&
-	git tag -f bogo "$bogo" &&
-	git for-each-ref --format "%(body)" refs/tags/bogo
-
-'
-
-test_expect_success 'create tag with subject and body content' '
-	cat >>msg <<-\EOF &&
-		the subject line
-
-		first body line
-		second body line
-	EOF
-	git tag -F msg subject-body
-'
-test_atom refs/tags/subject-body subject 'the subject line'
-test_atom refs/tags/subject-body subject:sanitize 'the-subject-line'
-test_atom refs/tags/subject-body body 'first body line
-second body line
-'
-test_atom refs/tags/subject-body contents 'the subject line
-
-first body line
-second body line
-'
-
-test_expect_success 'create tag with multiline subject' '
-	cat >msg <<-\EOF &&
-		first subject line
-		second subject line
-
-		first body line
-		second body line
-	EOF
-	git tag -F msg multiline
-'
-test_atom refs/tags/multiline subject 'first subject line second subject line'
-test_atom refs/tags/multiline subject:sanitize 'first-subject-line-second-subject-line'
-test_atom refs/tags/multiline contents:subject 'first subject line second subject line'
-test_atom refs/tags/multiline body 'first body line
-second body line
-'
-test_atom refs/tags/multiline contents:body 'first body line
-second body line
-'
-test_atom refs/tags/multiline contents:signature ''
-test_atom refs/tags/multiline contents 'first subject line
-second subject line
-
-first body line
-second body line
-'
-
-test_expect_success GPG 'create signed tags' '
-	git tag -s -m "" signed-empty &&
-	git tag -s -m "subject line" signed-short &&
-	cat >msg <<-\EOF &&
-	subject line
-
-	body contents
-	EOF
-	git tag -s -F msg signed-long
-'
-
-sig='-----BEGIN PGP SIGNATURE-----
------END PGP SIGNATURE-----
-'
-
-PREREQ=GPG
-test_atom refs/tags/signed-empty subject ''
-test_atom refs/tags/signed-empty subject:sanitize ''
-test_atom refs/tags/signed-empty contents:subject ''
-test_atom refs/tags/signed-empty body "$sig"
-test_atom refs/tags/signed-empty contents:body ''
-test_atom refs/tags/signed-empty contents:signature "$sig"
-test_atom refs/tags/signed-empty contents "$sig"
-
-test_expect_success GPG 'basic atom: refs/tags/signed-empty raw' '
-	git cat-file tag refs/tags/signed-empty >expected &&
-	git for-each-ref --format="%(raw)" refs/tags/signed-empty >actual &&
-	sanitize_pgp <expected >expected.clean &&
-	echo >>expected.clean &&
-	sanitize_pgp <actual >actual.clean &&
-	test_cmp expected.clean actual.clean
-'
-
-test_atom refs/tags/signed-short subject 'subject line'
-test_atom refs/tags/signed-short subject:sanitize 'subject-line'
-test_atom refs/tags/signed-short contents:subject 'subject line'
-test_atom refs/tags/signed-short body "$sig"
-test_atom refs/tags/signed-short contents:body ''
-test_atom refs/tags/signed-short contents:signature "$sig"
-test_atom refs/tags/signed-short contents "subject line
-$sig"
-
-test_expect_success GPG 'basic atom: refs/tags/signed-short raw' '
-	git cat-file tag refs/tags/signed-short >expected &&
-	git for-each-ref --format="%(raw)" refs/tags/signed-short >actual &&
-	sanitize_pgp <expected >expected.clean &&
-	echo >>expected.clean &&
-	sanitize_pgp <actual >actual.clean &&
-	test_cmp expected.clean actual.clean
-'
-
-test_atom refs/tags/signed-long subject 'subject line'
-test_atom refs/tags/signed-long subject:sanitize 'subject-line'
-test_atom refs/tags/signed-long contents:subject 'subject line'
-test_atom refs/tags/signed-long body "body contents
-$sig"
-test_atom refs/tags/signed-long contents:body 'body contents
-'
-test_atom refs/tags/signed-long contents:signature "$sig"
-test_atom refs/tags/signed-long contents "subject line
-
-body contents
-$sig"
-
-test_expect_success GPG 'basic atom: refs/tags/signed-long raw' '
-	git cat-file tag refs/tags/signed-long >expected &&
-	git for-each-ref --format="%(raw)" refs/tags/signed-long >actual &&
-	sanitize_pgp <expected >expected.clean &&
-	echo >>expected.clean &&
-	sanitize_pgp <actual >actual.clean &&
-	test_cmp expected.clean actual.clean
-'
-
-test_expect_success 'set up refs pointing to tree and blob' '
-	git update-ref refs/mytrees/first refs/heads/main^{tree} &&
-	git update-ref refs/myblobs/first refs/heads/main:one
-'
-
-test_atom refs/mytrees/first subject ""
-test_atom refs/mytrees/first contents:subject ""
-test_atom refs/mytrees/first body ""
-test_atom refs/mytrees/first contents:body ""
-test_atom refs/mytrees/first contents:signature ""
-test_atom refs/mytrees/first contents ""
-
-test_expect_success 'basic atom: refs/mytrees/first raw' '
-	git cat-file tree refs/mytrees/first >expected &&
-	echo >>expected &&
-	git for-each-ref --format="%(raw)" refs/mytrees/first >actual &&
-	test_cmp expected actual &&
-	git cat-file -s refs/mytrees/first >expected &&
-	git for-each-ref --format="%(raw:size)" refs/mytrees/first >actual &&
-	test_cmp expected actual
-'
-
-test_atom refs/myblobs/first subject ""
-test_atom refs/myblobs/first contents:subject ""
-test_atom refs/myblobs/first body ""
-test_atom refs/myblobs/first contents:body ""
-test_atom refs/myblobs/first contents:signature ""
-test_atom refs/myblobs/first contents ""
-
-test_expect_success 'basic atom: refs/myblobs/first raw' '
-	git cat-file blob refs/myblobs/first >expected &&
-	echo >>expected &&
-	git for-each-ref --format="%(raw)" refs/myblobs/first >actual &&
-	test_cmp expected actual &&
-	git cat-file -s refs/myblobs/first >expected &&
-	git for-each-ref --format="%(raw:size)" refs/myblobs/first >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'set up refs pointing to binary blob' '
-	printf "a\0b\0c" >blob1 &&
-	printf "a\0c\0b" >blob2 &&
-	printf "\0a\0b\0c" >blob3 &&
-	printf "abc" >blob4 &&
-	printf "\0 \0 \0 " >blob5 &&
-	printf "\0 \0a\0 " >blob6 &&
-	printf "  " >blob7 &&
-	>blob8 &&
-	obj=$(git hash-object -w blob1) &&
-	git update-ref refs/myblobs/blob1 "$obj" &&
-	obj=$(git hash-object -w blob2) &&
-	git update-ref refs/myblobs/blob2 "$obj" &&
-	obj=$(git hash-object -w blob3) &&
-	git update-ref refs/myblobs/blob3 "$obj" &&
-	obj=$(git hash-object -w blob4) &&
-	git update-ref refs/myblobs/blob4 "$obj" &&
-	obj=$(git hash-object -w blob5) &&
-	git update-ref refs/myblobs/blob5 "$obj" &&
-	obj=$(git hash-object -w blob6) &&
-	git update-ref refs/myblobs/blob6 "$obj" &&
-	obj=$(git hash-object -w blob7) &&
-	git update-ref refs/myblobs/blob7 "$obj" &&
-	obj=$(git hash-object -w blob8) &&
-	git update-ref refs/myblobs/blob8 "$obj"
-'
-
-test_expect_success 'Verify sorts with raw' '
-	cat >expected <<-EOF &&
-	refs/myblobs/blob8
-	refs/myblobs/blob5
-	refs/myblobs/blob6
-	refs/myblobs/blob3
-	refs/myblobs/blob7
-	refs/mytrees/first
-	refs/myblobs/first
-	refs/myblobs/blob1
-	refs/myblobs/blob2
-	refs/myblobs/blob4
-	refs/heads/main
-	EOF
-	git for-each-ref --format="%(refname)" --sort=raw \
-		refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'Verify sorts with raw:size' '
-	cat >expected <<-EOF &&
-	refs/myblobs/blob8
-	refs/myblobs/blob7
-	refs/myblobs/blob4
-	refs/myblobs/blob1
-	refs/myblobs/blob2
-	refs/myblobs/blob3
-	refs/myblobs/blob5
-	refs/myblobs/blob6
-	refs/myblobs/first
-	refs/mytrees/first
-	refs/heads/main
-	EOF
-	git for-each-ref --format="%(refname)" --sort=raw:size \
-		refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'validate raw atom with %(if:equals)' '
-	cat >expected <<-EOF &&
-	not equals
-	not equals
-	not equals
-	not equals
-	not equals
-	not equals
-	refs/myblobs/blob4
-	not equals
-	not equals
-	not equals
-	not equals
-	not equals
-	EOF
-	git for-each-ref --format="%(if:equals=abc)%(raw)%(then)%(refname)%(else)not equals%(end)" \
-		refs/myblobs/ refs/heads/ >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'validate raw atom with %(if:notequals)' '
-	cat >expected <<-EOF &&
-	refs/heads/ambiguous
-	refs/heads/main
-	refs/heads/newtag
-	refs/myblobs/blob1
-	refs/myblobs/blob2
-	refs/myblobs/blob3
-	equals
-	refs/myblobs/blob5
-	refs/myblobs/blob6
-	refs/myblobs/blob7
-	refs/myblobs/blob8
-	refs/myblobs/first
-	EOF
-	git for-each-ref --format="%(if:notequals=abc)%(raw)%(then)%(refname)%(else)equals%(end)" \
-		refs/myblobs/ refs/heads/ >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'empty raw refs with %(if)' '
-	cat >expected <<-EOF &&
-	refs/myblobs/blob1 not empty
-	refs/myblobs/blob2 not empty
-	refs/myblobs/blob3 not empty
-	refs/myblobs/blob4 not empty
-	refs/myblobs/blob5 not empty
-	refs/myblobs/blob6 not empty
-	refs/myblobs/blob7 empty
-	refs/myblobs/blob8 empty
-	refs/myblobs/first not empty
-	EOF
-	git for-each-ref --format="%(refname) %(if)%(raw)%(then)not empty%(else)empty%(end)" \
-		refs/myblobs/ >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success '%(raw) with --python must fail' '
-	test_must_fail git for-each-ref --format="%(raw)" --python
-'
-
-test_expect_success '%(raw) with --tcl must fail' '
-	test_must_fail git for-each-ref --format="%(raw)" --tcl
-'
-
-test_expect_success PERL_TEST_HELPERS '%(raw) with --perl' '
-	git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/myblobs/blob1 --perl | perl >actual &&
-	cmp blob1 actual &&
-	git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/myblobs/blob3 --perl | perl >actual &&
-	cmp blob3 actual &&
-	git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/myblobs/blob8 --perl | perl >actual &&
-	cmp blob8 actual &&
-	git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/myblobs/first --perl | perl >actual &&
-	cmp one actual &&
-	git cat-file tree refs/mytrees/first > expected &&
-	git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/mytrees/first --perl | perl >actual &&
-	cmp expected actual
-'
-
-test_expect_success '%(raw) with --shell must fail' '
-	test_must_fail git for-each-ref --format="%(raw)" --shell
-'
-
-test_expect_success '%(raw) with --shell and --sort=raw must fail' '
-	test_must_fail git for-each-ref --format="%(raw)" --sort=raw --shell
-'
-
-test_expect_success '%(raw:size) with --shell' '
-	git for-each-ref --format="%(raw:size)" | sed "s/^/$SQ/;s/$/$SQ/" >expect &&
-	git for-each-ref --format="%(raw:size)" --shell >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success 'for-each-ref --format compare with cat-file --batch' '
-	git rev-parse refs/mytrees/first | git cat-file --batch >expected &&
-	git for-each-ref --format="%(objectname) %(objecttype) %(objectsize)
-%(raw)" refs/mytrees/first >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'verify sorts with contents:size' '
-	cat >expect <<-\EOF &&
-	refs/heads/main
-	refs/heads/newtag
-	refs/heads/ambiguous
-	EOF
-	git for-each-ref --format="%(refname)" \
-		--sort=contents:size refs/heads/ >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success 'set up multiple-sort tags' '
-	for when in 100000 200000
-	do
-		for email in user1 user2
-		do
-			for ref in ref1 ref2
-			do
-				GIT_COMMITTER_DATE="@$when +0000" \
-				GIT_COMMITTER_EMAIL="$email@example.com" \
-				git tag -m "tag $ref-$when-$email" \
-				multi-$ref-$when-$email || return 1
-			done
-		done
-	done
-'
-
-test_expect_success 'Verify sort with multiple keys' '
-	cat >expected <<-\EOF &&
-	100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
-	100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
-	100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
-	100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
-	200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
-	200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
-	200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
-	200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
-	EOF
-	git for-each-ref \
-		--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
-		--sort=-refname \
-		--sort=taggeremail \
-		--sort=taggerdate \
-		"refs/tags/multi-*" >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'equivalent sorts fall back on refname' '
-	cat >expected <<-\EOF &&
-	100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
-	100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
-	100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
-	100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
-	200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
-	200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
-	200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
-	200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
-	EOF
-	git for-each-ref \
-		--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
-		--sort=taggerdate \
-		"refs/tags/multi-*" >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success '--no-sort cancels the previous sort keys' '
-	cat >expected <<-\EOF &&
-	100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
-	100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
-	100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
-	100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
-	200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
-	200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
-	200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
-	200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
-	EOF
-	git for-each-ref \
-		--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
-		--sort=-refname \
-		--sort=taggeremail \
-		--no-sort \
-		--sort=taggerdate \
-		"refs/tags/multi-*" >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success '--no-sort without subsequent --sort prints expected refs' '
-	cat >expected <<-\EOF &&
-	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
-	EOF
-
-	# Sort the results with `sort` for a consistent comparison against
-	# expected
-	git for-each-ref \
-		--format="%(refname)" \
-		--no-sort \
-		"refs/tags/multi-*" | sort >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'set up custom date sorting' '
-	# Dates:
-	# - Wed Feb 07 2024 21:34:20 +0000
-	# - Tue Dec 14 1999 00:05:22 +0000
-	# - Fri Jun 04 2021 11:26:51 +0000
-	# - Mon Jan 22 2007 16:44:01 GMT+0000
-	i=1 &&
-	for when in 1707341660 945129922 1622806011 1169484241
-	do
-		GIT_COMMITTER_DATE="@$when +0000" \
-		GIT_COMMITTER_EMAIL="user@example.com" \
-		git tag -m "tag $when" custom-dates-$i &&
-		i=$(($i+1)) || return 1
-	done
-'
-
-test_expect_success 'sort by date defaults to full timestamp' '
-	cat >expected <<-\EOF &&
-	945129922 refs/tags/custom-dates-2
-	1169484241 refs/tags/custom-dates-4
-	1622806011 refs/tags/custom-dates-3
-	1707341660 refs/tags/custom-dates-1
-	EOF
-
-	git for-each-ref \
-		--format="%(creatordate:unix) %(refname)" \
-		--sort=creatordate \
-		"refs/tags/custom-dates-*" >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'sort by custom date format' '
-	cat >expected <<-\EOF &&
-	00:05:22 refs/tags/custom-dates-2
-	11:26:51 refs/tags/custom-dates-3
-	16:44:01 refs/tags/custom-dates-4
-	21:34:20 refs/tags/custom-dates-1
-	EOF
-
-	git for-each-ref \
-		--format="%(creatordate:format:%H:%M:%S) %(refname)" \
-		--sort="creatordate:format:%H:%M:%S" \
-		"refs/tags/custom-dates-*" >actual &&
-	test_cmp expected actual
-'
-
-test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' '
-	test_when_finished "git checkout main" &&
-	git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
-	sed -e "s/^\* /  /" actual >expect &&
-	git checkout --orphan orphaned-branch &&
-	git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
-	test_cmp expect actual
-'
-
-cat >trailers <<EOF
-Reviewed-by: A U Thor <author@example.com>
-Signed-off-by: A U Thor <author@example.com>
-[ v2 updated patch description ]
-Acked-by: A U Thor
-  <author@example.com>
-EOF
-
-unfold () {
-	perl -0pe 's/\n\s+/ /g'
-}
-
-test_expect_success 'set up trailers for next test' '
-	echo "Some contents" > two &&
-	git add two &&
-	git commit -F - <<-EOF
-	trailers: this commit message has trailers
-
-	Some message contents
-
-	$(cat trailers)
-	EOF
-'
-
-test_trailer_option () {
-	if test "$#" -eq 3
-	then
-		prereq="$1"
-		shift
-	fi &&
-	title=$1 option=$2
-	cat >expect
-	test_expect_success $prereq "$title" '
-		git for-each-ref --format="%($option)" refs/heads/main >actual &&
-		test_cmp expect actual &&
-		git for-each-ref --format="%(contents:$option)" refs/heads/main >actual &&
-		test_cmp expect actual
-	'
-}
-
-test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) unfolds trailers' \
-	'trailers:unfold' <<-EOF
-	$(unfold <trailers)
-
-	EOF
-
-test_trailer_option '%(trailers:only) shows only "key: value" trailers' \
-	'trailers:only' <<-EOF
-	$(grep -v patch.description <trailers)
-
-	EOF
-
-test_trailer_option '%(trailers:only=no,only=true) shows only "key: value" trailers' \
-	'trailers:only=no,only=true' <<-EOF
-	$(grep -v patch.description <trailers)
-
-	EOF
-
-test_trailer_option '%(trailers:only=yes) shows only "key: value" trailers' \
-	'trailers:only=yes' <<-EOF
-	$(grep -v patch.description <trailers)
-
-	EOF
-
-test_trailer_option '%(trailers:only=no) shows all trailers' \
-	'trailers:only=no' <<-EOF
-	$(cat trailers)
-
-	EOF
-
-test_trailer_option PERL_TEST_HELPERS '%(trailers:only) and %(trailers:unfold) work together' \
-	'trailers:only,unfold' <<-EOF
-	$(grep -v patch.description <trailers | unfold)
-
-	EOF
-
-test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) and %(trailers:only) work together' \
-	'trailers:unfold,only' <<-EOF
-	$(grep -v patch.description <trailers | unfold)
-
-	EOF
-
-test_trailer_option '%(trailers:key=foo) shows that trailer' \
-	'trailers:key=Signed-off-by' <<-EOF
-	Signed-off-by: A U Thor <author@example.com>
-
-	EOF
-
-test_trailer_option '%(trailers:key=foo) is case insensitive' \
-	'trailers:key=SiGned-oFf-bY' <<-EOF
-	Signed-off-by: A U Thor <author@example.com>
-
-	EOF
-
-test_trailer_option '%(trailers:key=foo:) trailing colon also works' \
-	'trailers:key=Signed-off-by:' <<-EOF
-	Signed-off-by: A U Thor <author@example.com>
-
-	EOF
-
-test_trailer_option '%(trailers:key=foo) multiple keys' \
-	'trailers:key=Reviewed-by:,key=Signed-off-by' <<-EOF
-	Reviewed-by: A U Thor <author@example.com>
-	Signed-off-by: A U Thor <author@example.com>
-
-	EOF
-
-test_trailer_option '%(trailers:key=nonexistent) becomes empty' \
-	'trailers:key=Shined-off-by:' <<-EOF
-
-	EOF
-
-test_trailer_option '%(trailers:key=foo) handles multiple lines even if folded' \
-	'trailers:key=Acked-by' <<-EOF
-	$(grep -v patch.description <trailers | grep -v Signed-off-by | grep -v Reviewed-by)
-
-	EOF
-
-test_trailer_option '%(trailers:key=foo,unfold) properly unfolds' \
-	'trailers:key=Signed-Off-by,unfold' <<-EOF
-	$(unfold <trailers | grep Signed-off-by)
-
-	EOF
-
-test_trailer_option '%(trailers:key=foo,only=no) also includes nontrailer lines' \
-	'trailers:key=Signed-off-by,only=no' <<-EOF
-	Signed-off-by: A U Thor <author@example.com>
-	$(grep patch.description <trailers)
-
-	EOF
-
-test_trailer_option '%(trailers:key=foo,valueonly) shows only value' \
-	'trailers:key=Signed-off-by,valueonly' <<-EOF
-	A U Thor <author@example.com>
-
-	EOF
-
-test_trailer_option '%(trailers:separator) changes separator' \
-	'trailers:separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
-	Reviewed-by: A U Thor <author@example.com>,Signed-off-by: A U Thor <author@example.com>
-	EOF
-
-test_trailer_option '%(trailers:key_value_separator) changes key-value separator' \
-	'trailers:key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
-	Reviewed-by,A U Thor <author@example.com>
-	Signed-off-by,A U Thor <author@example.com>
-
-	EOF
-
-test_trailer_option '%(trailers:separator,key_value_separator) changes both separators' \
-	'trailers:separator=%x2C,key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
-	Reviewed-by,A U Thor <author@example.com>,Signed-off-by,A U Thor <author@example.com>
-	EOF
-
-test_expect_success 'multiple %(trailers) use their own options' '
-	git tag -F - tag-with-trailers <<-\EOF &&
-	body
-
-	one: foo
-	one: bar
-	two: baz
-	two: qux
-	EOF
-	t1="%(trailers:key=one,key_value_separator=W,separator=X)" &&
-	t2="%(trailers:key=two,key_value_separator=Y,separator=Z)" &&
-	git for-each-ref --format="$t1%0a$t2" refs/tags/tag-with-trailers >actual &&
-	cat >expect <<-\EOF &&
-	oneWfooXoneWbar
-	twoYbazZtwoYqux
-	EOF
-	test_cmp expect actual
-'
-
-test_failing_trailer_option () {
-	title=$1 option=$2
-	cat >expect
-	test_expect_success "$title" '
-		# error message cannot be checked under i18n
-		test_must_fail git for-each-ref --format="%($option)" refs/heads/main 2>actual &&
-		test_cmp expect actual &&
-		test_must_fail git for-each-ref --format="%(contents:$option)" refs/heads/main 2>actual &&
-		test_cmp expect actual
-	'
-}
-
-test_failing_trailer_option '%(trailers) rejects unknown trailers arguments' \
-	'trailers:unsupported' <<-\EOF
-	fatal: unknown %(trailers) argument: unsupported
-	EOF
-
-test_failing_trailer_option '%(trailers:key) without value is error' \
-	'trailers:key' <<-\EOF
-	fatal: expected %(trailers:key=<value>)
-	EOF
-
-test_expect_success 'if arguments, %(contents:trailers) shows error if colon is missing' '
-	cat >expect <<-EOF &&
-	fatal: unrecognized %(contents) argument: trailersonly
-	EOF
-	test_must_fail git for-each-ref --format="%(contents:trailersonly)" 2>actual &&
-	test_cmp expect actual
-'
-
-test_expect_success 'basic atom: head contents:trailers' '
-	git for-each-ref --format="%(contents:trailers)" refs/heads/main >actual &&
-	sanitize_pgp <actual >actual.clean &&
-	# git for-each-ref ends with a blank line
-	cat >expect <<-EOF &&
-	$(cat trailers)
-
-	EOF
-	test_cmp expect actual.clean
-'
-
-test_expect_success 'basic atom: rest must fail' '
-	test_must_fail git for-each-ref --format="%(rest)" refs/heads/main
-'
-
-test_expect_success 'HEAD atom does not take arguments' '
-	test_must_fail git for-each-ref --format="%(HEAD:foo)" 2>err &&
-	echo "fatal: %(HEAD) does not take arguments" >expect &&
-	test_cmp expect err
-'
-
-test_expect_success 'subject atom rejects unknown arguments' '
-	test_must_fail git for-each-ref --format="%(subject:foo)" 2>err &&
-	echo "fatal: unrecognized %(subject) argument: foo" >expect &&
-	test_cmp expect err
-'
-
-test_expect_success 'refname atom rejects unknown arguments' '
-	test_must_fail git for-each-ref --format="%(refname:foo)" 2>err &&
-	echo "fatal: unrecognized %(refname) argument: foo" >expect &&
-	test_cmp expect err
-'
-
-test_expect_success 'trailer parsing not fooled by --- line' '
-	git commit --allow-empty -F - <<-\EOF &&
-	this is the subject
-
-	This is the body. The message has a "---" line which would confuse a
-	message+patch parser. But here we know we have only a commit message,
-	so we get it right.
-
-	trailer: wrong
-	---
-	This is more body.
-
-	trailer: right
-	EOF
-
-	{
-		echo "trailer: right" &&
-		echo
-	} >expect &&
-	git for-each-ref --format="%(trailers)" refs/heads/main >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success 'Add symbolic ref for the following tests' '
-	git symbolic-ref refs/heads/sym refs/heads/main
-'
-
-cat >expected <<EOF
-refs/heads/main
-EOF
-
-test_expect_success 'Verify usage of %(symref) atom' '
-	git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<EOF
-heads/main
-EOF
-
-test_expect_success 'Verify usage of %(symref:short) atom' '
-	git for-each-ref --format="%(symref:short)" refs/heads/sym >actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<EOF
-main
-heads/main
-EOF
-
-test_expect_success 'Verify usage of %(symref:lstrip) atom' '
-	git for-each-ref --format="%(symref:lstrip=2)" refs/heads/sym > actual &&
-	git for-each-ref --format="%(symref:lstrip=-2)" refs/heads/sym >> actual &&
-	test_cmp expected actual &&
-
-	git for-each-ref --format="%(symref:strip=2)" refs/heads/sym > actual &&
-	git for-each-ref --format="%(symref:strip=-2)" refs/heads/sym >> actual &&
-	test_cmp expected actual
-'
-
-cat >expected <<EOF
-refs
-refs/heads
-EOF
-
-test_expect_success 'Verify usage of %(symref:rstrip) atom' '
-	git for-each-ref --format="%(symref:rstrip=2)" refs/heads/sym > actual &&
-	git for-each-ref --format="%(symref:rstrip=-2)" refs/heads/sym >> actual &&
-	test_cmp expected actual
-'
-
-test_expect_success ':remotename and :remoteref' '
-	git init remote-tests &&
-	(
-		cd remote-tests &&
-		test_commit initial &&
-		git branch -M main &&
-		git remote add from fifth.coffee:blub &&
-		git config branch.main.remote from &&
-		git config branch.main.merge refs/heads/stable &&
-		git remote add to southridge.audio:repo &&
-		git config remote.to.push "refs/heads/*:refs/heads/pushed/*" &&
-		git config branch.main.pushRemote to &&
-		for pair in "%(upstream)=refs/remotes/from/stable" \
-			"%(upstream:remotename)=from" \
-			"%(upstream:remoteref)=refs/heads/stable" \
-			"%(push)=refs/remotes/to/pushed/main" \
-			"%(push:remotename)=to" \
-			"%(push:remoteref)=refs/heads/pushed/main"
-		do
-			echo "${pair#*=}" >expect &&
-			git for-each-ref --format="${pair%=*}" \
-				refs/heads/main >actual &&
-			test_cmp expect actual || exit 1
-		done &&
-		git branch push-simple &&
-		git config branch.push-simple.pushRemote from &&
-		actual="$(git for-each-ref \
-			--format="%(push:remotename),%(push:remoteref)" \
-			refs/heads/push-simple)" &&
-		test from, = "$actual"
-	)
-'
-
-test_expect_success 'for-each-ref --ignore-case ignores case' '
-	git for-each-ref --format="%(refname)" refs/heads/MAIN >actual &&
-	test_must_be_empty actual &&
-
-	echo refs/heads/main >expect &&
-	git for-each-ref --format="%(refname)" --ignore-case \
-		refs/heads/MAIN >actual &&
-	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 &&
-	for email in a A b B
-	do
-		for subject in a A b B
-		do
-			GIT_COMMITTER_EMAIL="$email@example.com" \
-			git tag -m "tag $subject" icase-$(printf %02d $nr) &&
-			nr=$((nr+1))||
-			return 1
-		done
-	done &&
-	git for-each-ref --ignore-case \
-		--format="%(taggeremail) %(subject) %(refname)" \
-		--sort=refname \
-		--sort=subject \
-		--sort=taggeremail \
-		refs/tags/icase-* >actual &&
-	cat >expect <<-\EOF &&
-	<a@example.com> tag a refs/tags/icase-00
-	<a@example.com> tag A refs/tags/icase-01
-	<A@example.com> tag a refs/tags/icase-04
-	<A@example.com> tag A refs/tags/icase-05
-	<a@example.com> tag b refs/tags/icase-02
-	<a@example.com> tag B refs/tags/icase-03
-	<A@example.com> tag b refs/tags/icase-06
-	<A@example.com> tag B refs/tags/icase-07
-	<b@example.com> tag a refs/tags/icase-08
-	<b@example.com> tag A refs/tags/icase-09
-	<B@example.com> tag a refs/tags/icase-12
-	<B@example.com> tag A refs/tags/icase-13
-	<b@example.com> tag b refs/tags/icase-10
-	<b@example.com> tag B refs/tags/icase-11
-	<B@example.com> tag b refs/tags/icase-14
-	<B@example.com> tag B refs/tags/icase-15
-	EOF
-	test_cmp expect actual
-'
-
-test_expect_success 'for-each-ref reports broken tags' '
-	git tag -m "good tag" broken-tag-good HEAD &&
-	git cat-file tag broken-tag-good >good &&
-	sed s/commit/blob/ <good >bad &&
-	bad=$(git hash-object -w -t tag bad) &&
-	git update-ref refs/tags/broken-tag-bad $bad &&
-	test_must_fail git for-each-ref --format="%(*objectname)" \
-		refs/tags/broken-tag-*
-'
-
-test_expect_success 'set up tag with signature and no blank lines' '
-	git tag -F - fake-sig-no-blanks <<-\EOF
-	this is the subject
-	-----BEGIN PGP SIGNATURE-----
-	not a real signature, but we just care about the
-	subject/body parsing. It is important here that
-	there are no blank lines in the signature.
-	-----END PGP SIGNATURE-----
-	EOF
-'
-
-test_atom refs/tags/fake-sig-no-blanks contents:subject 'this is the subject'
-test_atom refs/tags/fake-sig-no-blanks contents:body ''
-test_atom refs/tags/fake-sig-no-blanks contents:signature "$sig"
-
-test_expect_success 'set up tag with CRLF signature' '
-	append_cr <<-\EOF |
-	this is the subject
-	-----BEGIN PGP SIGNATURE-----
-
-	not a real signature, but we just care about
-	the subject/body parsing. It is important here
-	that there is a blank line separating this
-	from the signature header.
-	-----END PGP SIGNATURE-----
-	EOF
-	git tag -F - --cleanup=verbatim fake-sig-crlf
-'
-
-test_atom refs/tags/fake-sig-crlf contents:subject 'this is the subject'
-test_atom refs/tags/fake-sig-crlf contents:body ''
-
-# CRLF is retained in the signature, so we have to pass our expected value
-# through append_cr. But test_atom requires a shell string, which means command
-# substitution, and the shell will strip trailing newlines from the output of
-# the substitution. Hack around it by adding and then removing a dummy line.
-sig_crlf="$(printf "%s" "$sig" | append_cr; echo dummy)"
-sig_crlf=${sig_crlf%dummy}
-test_atom refs/tags/fake-sig-crlf contents:signature "$sig_crlf"
-
-test_expect_success 'set up tag with signature and trailers' '
-	git tag -F - fake-sig-trailer <<-\EOF
-	this is the subject
-
-	this is the body
-
-	My-Trailer: foo
-	-----BEGIN PGP SIGNATURE-----
-
-	not a real signature, but we just care about the
-	subject/body/trailer parsing.
-	-----END PGP SIGNATURE-----
-	EOF
-'
-
-# use "separator=" here to suppress the terminating newline
-test_atom refs/tags/fake-sig-trailer trailers:separator= 'My-Trailer: foo'
-
-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_expect_success 'git for-each-ref with nested tags' '
-	git tag -am "Normal tag" nested/base HEAD &&
-	git tag -am "Nested tag" nested/nest1 refs/tags/nested/base &&
-	git tag -am "Double nested tag" nested/nest2 refs/tags/nested/nest1 &&
-
-	head_oid="$(git rev-parse HEAD)" &&
-	base_tag_oid="$(git rev-parse refs/tags/nested/base)" &&
-	nest1_tag_oid="$(git rev-parse refs/tags/nested/nest1)" &&
-	nest2_tag_oid="$(git rev-parse refs/tags/nested/nest2)" &&
-
-	cat >expect <<-EOF &&
-	refs/tags/nested/base $base_tag_oid tag $head_oid commit
-	refs/tags/nested/nest1 $nest1_tag_oid tag $head_oid commit
-	refs/tags/nested/nest2 $nest2_tag_oid tag $head_oid commit
-	EOF
-
-	git for-each-ref \
-		--format="%(refname) %(objectname) %(objecttype) %(*objectname) %(*objecttype)" \
-		refs/tags/nested/ >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success 'is-base atom with non-commits' '
-	git for-each-ref --format="%(is-base:HEAD) %(refname)" >out 2>err &&
-	grep "(HEAD) refs/heads/main" out &&
-
-	test_line_count = 2 err &&
-	grep "error: object .* is a commit, not a blob" err &&
-	grep "error: bad tag pointer to" err
-'
-
-GRADE_FORMAT="%(signature:grade)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)"
-TRUSTLEVEL_FORMAT="%(signature:trustlevel)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)"
-
-test_expect_success GPG 'setup for signature atom using gpg' '
-	git checkout -b signed &&
-
-	test_when_finished "test_unconfig commit.gpgSign" &&
-
-	echo "1" >file &&
-	git add file &&
-	test_tick &&
-	git commit -S -m "file: 1" &&
-	git tag first-signed &&
-
-	echo "2" >file &&
-	test_tick &&
-	git commit -a -m "file: 2" &&
-	git tag second-unsigned &&
-
-	git config commit.gpgSign 1 &&
-	echo "3" >file &&
-	test_tick &&
-	git commit -a --no-gpg-sign -m "file: 3" &&
-	git tag third-unsigned &&
-
-	test_tick &&
-	git rebase -f HEAD^^ && git tag second-signed HEAD^ &&
-	git tag third-signed &&
-
-	echo "4" >file &&
-	test_tick &&
-	git commit -a -SB7227189 -m "file: 4" &&
-	git tag fourth-signed &&
-
-	echo "5" >file &&
-	test_tick &&
-	git commit -a --no-gpg-sign -m "file: 5" &&
-	git tag fifth-unsigned &&
-
-	echo "6" >file &&
-	test_tick &&
-	git commit -a --no-gpg-sign -m "file: 6" &&
-
-	test_tick &&
-	git rebase -f HEAD^^ &&
-	git tag fifth-signed HEAD^ &&
-	git tag sixth-signed &&
-
-	echo "7" >file &&
-	test_tick &&
-	git commit -a --no-gpg-sign -m "file: 7" &&
-	git tag seventh-unsigned
-'
-
-test_expect_success GPGSSH 'setup for signature atom using ssh' '
-	test_when_finished "test_unconfig gpg.format user.signingkey" &&
-
-	test_config gpg.format ssh &&
-	test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
-	echo "8" >file &&
-	test_tick &&
-	git add file &&
-	git commit -S -m "file: 8" &&
-	git tag eighth-signed-ssh
-'
-
-test_expect_success GPG2 'bare signature atom' '
-	git verify-commit first-signed 2>expect &&
-	echo  >>expect &&
-	git for-each-ref refs/tags/first-signed \
-		--format="%(signature)" >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success GPG 'show good signature with custom format' '
-	git verify-commit first-signed &&
-	cat >expect <<-\EOF &&
-	G
-	13B6F51ECDDE430D
-	C O Mitter <committer@example.com>
-	73D758744BE721698EC54E8713B6F51ECDDE430D
-	73D758744BE721698EC54E8713B6F51ECDDE430D
-	EOF
-	git for-each-ref refs/tags/first-signed \
-		--format="$GRADE_FORMAT" >actual &&
-	test_cmp expect actual
-'
-test_expect_success GPGSSH 'show good signature with custom format with ssh' '
-	test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
-	FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") &&
-	cat >expect.tmpl <<-\EOF &&
-	G
-	FINGERPRINT
-	principal with number 1
-	FINGERPRINT
-
-	EOF
-	sed "s|FINGERPRINT|$FINGERPRINT|g" expect.tmpl >expect &&
-	git for-each-ref refs/tags/eighth-signed-ssh \
-		--format="$GRADE_FORMAT" >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success GPG 'signature atom with grade option and bad signature' '
-	git cat-file commit third-signed >raw &&
-	sed -e "s/^file: 3/file: 3 forged/" raw >forged1 &&
-	FORGED1=$(git hash-object -w -t commit forged1) &&
-	git update-ref refs/tags/third-signed "$FORGED1" &&
-	test_must_fail git verify-commit "$FORGED1" &&
-
-	cat >expect <<-\EOF &&
-	B
-	13B6F51ECDDE430D
-	C O Mitter <committer@example.com>
-
-
-	EOF
-	git for-each-ref refs/tags/third-signed \
-		--format="$GRADE_FORMAT" >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 for-each-ref refs/tags/fourth-signed \
-		--format="$GRADE_FORMAT" >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 for-each-ref refs/tags/fourth-signed \
-		--format="$TRUSTLEVEL_FORMAT" >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 for-each-ref refs/tags/sixth-signed \
-		--format="$TRUSTLEVEL_FORMAT" >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success GPG 'show unknown signature with custom format' '
-	cat >expect <<-\EOF &&
-	E
-	13B6F51ECDDE430D
-
-
-
-	EOF
-	GNUPGHOME="$GNUPGHOME_NOT_USED" git for-each-ref \
-		refs/tags/sixth-signed --format="$GRADE_FORMAT" >actual &&
-	test_cmp expect actual
-'
-
-test_expect_success GPG 'show lack of signature with custom format' '
-	cat >expect <<-\EOF &&
-	N
-
-
-
-
-	EOF
-	git for-each-ref refs/tags/seventh-unsigned \
-		--format="$GRADE_FORMAT" >actual &&
-	test_cmp expect actual
-'
+. "$TEST_DIRECTORY"/for-each-ref-tests.sh
 
 test_done
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 9b80ea1..7f060d9 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -754,4 +754,69 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'start after with packed refs' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit default &&
+
+		git update-ref --stdin <<-\EOF &&
+		create refs/heads/branch @
+		create refs/heads/side @
+		create refs/odd/spot @
+		create refs/tags/one @
+		create refs/tags/two @
+		commit
+		EOF
+
+		cat >expect <<-\EOF &&
+		refs/tags/default
+		refs/tags/one
+		refs/tags/two
+		EOF
+
+		git pack-refs --all &&
+		git for-each-ref --format="%(refname)" --start-after=refs/odd/spot >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'start after with packed refs and some loose refs' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit default &&
+
+		git update-ref --stdin <<-\EOF &&
+		create refs/heads/branch @
+		create refs/heads/side @
+		create refs/odd/spot @
+		create refs/tags/one @
+		create refs/tags/two @
+		commit
+		EOF
+
+		git pack-refs --all &&
+
+		git update-ref --stdin <<-\EOF &&
+		create refs/heads/foo @
+		create refs/odd/tee @
+		commit
+		EOF
+
+		cat >expect <<-\EOF &&
+		refs/odd/tee
+		refs/tags/default
+		refs/tags/one
+		refs/tags/two
+		EOF
+
+
+		git for-each-ref --format="%(refname)" --start-after=refs/odd/spot >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_done
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 1083563..ce2ff2a 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -2293,24 +2293,26 @@
 # don't recurse down to tags for trees or blobs pointed to by *those*
 # commits.
 test_expect_success 'Does --[no-]contains stop at commits? Yes!' '
-	cd no-contains &&
-	blob=$(git rev-parse v0.3:v0.3.t) &&
-	tree=$(git rev-parse v0.3^{tree}) &&
-	git tag tag-blob $blob &&
-	git tag tag-tree $tree &&
-	git tag --contains v0.3 >actual &&
-	cat >expected <<-\EOF &&
-	v0.3
-	v0.4
-	v0.5
-	EOF
-	test_cmp expected actual &&
-	git tag --no-contains v0.3 >actual &&
-	cat >expected <<-\EOF &&
-	v0.1
-	v0.2
-	EOF
-	test_cmp expected actual
+	(
+		cd no-contains &&
+		blob=$(git rev-parse v0.3:v0.3.t) &&
+		tree=$(git rev-parse v0.3^{tree}) &&
+		git tag tag-blob $blob &&
+		git tag tag-tree $tree &&
+		git tag --contains v0.3 >actual &&
+		cat >expected <<-\EOF &&
+		v0.3
+		v0.4
+		v0.5
+		EOF
+		test_cmp expected actual &&
+		git tag --no-contains v0.3 >actual &&
+		cat >expected <<-\EOF &&
+		v0.1
+		v0.2
+		EOF
+		test_cmp expected actual
+	)
 '
 
 test_expect_success 'If tag is created then tag message file is unlinked' '
@@ -2332,4 +2334,24 @@
 	test_path_exists .git/TAG_EDITMSG
 '
 
+test_expect_success 'annotated tag version sort' '
+	git tag -a -m "sample 1.0" vsample-1.0 &&
+	git tag -a -m "sample 2.0" vsample-2.0 &&
+	git tag -a -m "sample 10.0" vsample-10.0 &&
+	cat >expect <<-EOF &&
+	vsample-1.0
+	vsample-2.0
+	vsample-10.0
+	EOF
+
+	git tag --list --sort=version:tag vsample-\* >actual &&
+	test_cmp expect actual &&
+
+	# Ensure that we also handle this case alright in the case we have the
+	# peeled values cached e.g. via the packed-refs file.
+	git pack-refs --all &&
+	git tag --list --sort=version:tag vsample-\* &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh
index 5fcf281..c490e57 100755
--- a/t/t7005-editor.sh
+++ b/t/t7005-editor.sh
@@ -7,125 +7,96 @@
 unset EDITOR VISUAL GIT_EDITOR
 
 test_expect_success 'determine default editor' '
-
 	vi=$(TERM=vt100 git var GIT_EDITOR) &&
 	test -n "$vi"
-
 '
 
-if ! expr "$vi" : '[a-z]*$' >/dev/null
-then
-	vi=
-fi
-
-for i in GIT_EDITOR core_editor EDITOR VISUAL $vi
-do
-	cat >e-$i.sh <<-EOF
-	#!$SHELL_PATH
-	echo "Edited by $i" >"\$1"
-	EOF
-	chmod +x e-$i.sh
-done
-
-if ! test -z "$vi"
-then
-	mv e-$vi.sh $vi
-fi
-
 test_expect_success setup '
+	if ! expr "$vi" : "[a-z]*$" >/dev/null
+	then
+		vi=
+	fi &&
+
+	for i in GIT_EDITOR core_editor EDITOR VISUAL $vi
+	do
+		write_script e-$i.sh <<-EOF || return 1
+			echo "Edited by $i" >"\$1"
+		EOF
+	done &&
+
+	if ! test -z "$vi"
+	then
+		mv e-$vi.sh $vi
+	fi &&
 
 	msg="Hand-edited" &&
 	test_commit "$msg" &&
-	echo "$msg" >expect &&
-	git show -s --format=%s > actual &&
-	test_cmp expect actual
-
+	test_commit_message HEAD -m "$msg"
 '
 
-TERM=dumb
-export TERM
 test_expect_success 'dumb should error out when falling back on vi' '
-
-	if git commit --amend
-	then
-		echo "Oops?"
-		false
-	else
-		: happy
-	fi
+	test_must_fail env TERM=dumb git commit --amend
 '
 
 test_expect_success 'dumb should prefer EDITOR to VISUAL' '
-
-	EDITOR=./e-EDITOR.sh &&
-	VISUAL=./e-VISUAL.sh &&
-	export EDITOR VISUAL &&
-	git commit --amend &&
-	test "$(git show -s --format=%s)" = "Edited by EDITOR"
-
+	TERM=dumb EDITOR=./e-EDITOR.sh VISUAL=./e-VISUAL.sh \
+		git commit --amend &&
+	test_commit_message HEAD -m "Edited by EDITOR"
 '
 
-TERM=vt100
-export TERM
 for i in $vi EDITOR VISUAL core_editor GIT_EDITOR
 do
-	echo "Edited by $i" >expect
-	unset EDITOR VISUAL GIT_EDITOR
-	git config --unset-all core.editor
-	case "$i" in
-	core_editor)
-		git config core.editor ./e-core_editor.sh
-		;;
-	[A-Z]*)
-		eval "$i=./e-$i.sh"
-		export $i
-		;;
-	esac
 	test_expect_success "Using $i" '
-		git --exec-path=. commit --amend &&
-		git show -s --pretty=oneline |
-		sed -e "s/^[0-9a-f]* //" >actual &&
-		test_cmp expect actual
+		if test "$i" = core_editor
+		then
+			test_config core.editor ./e-core_editor.sh
+		fi &&
+		(
+			case "$i" in
+			[A-Z]*)
+				eval "$i=./e-$i.sh" &&
+				export $i
+				;;
+			esac &&
+			PATH="$PWD:$PATH" TERM=vt100 git commit --amend
+		) &&
+		test_commit_message HEAD -m "Edited by $i"
 	'
 done
 
-unset EDITOR VISUAL GIT_EDITOR
-git config --unset-all core.editor
-for i in $vi EDITOR VISUAL core_editor GIT_EDITOR
-do
-	echo "Edited by $i" >expect
-	case "$i" in
-	core_editor)
-		git config core.editor ./e-core_editor.sh
-		;;
-	[A-Z]*)
-		eval "$i=./e-$i.sh"
-		export $i
-		;;
-	esac
-	test_expect_success "Using $i (override)" '
-		git --exec-path=. commit --amend &&
-		git show -s --pretty=oneline |
-		sed -e "s/^[0-9a-f]* //" >actual &&
-		test_cmp expect actual
-	'
-done
+test_expect_success 'Using editors with overrides' '
+	(
+		TERM=vt100 &&
+		export TERM &&
+		for i in $vi EDITOR VISUAL core_editor GIT_EDITOR
+		do
+			echo "Edited by $i" >expect &&
+			case "$i" in
+			core_editor)
+				git config core.editor ./e-core_editor.sh
+				;;
+			[A-Z]*)
+				eval "$i=./e-$i.sh" &&
+				export $i
+				;;
+			esac &&
+			PATH="$PWD:$PATH" git commit --amend &&
+			test_commit_message HEAD expect || exit 1
+		done
+	)
+'
 
 test_expect_success 'editor with a space' '
 	echo "echo space >\"\$1\"" >"e space.sh" &&
 	chmod a+x "e space.sh" &&
 	GIT_EDITOR="./e\ space.sh" git commit --amend &&
-	test space = "$(git show -s --pretty=format:%s)"
-
+	test_commit_message HEAD -m space
 '
 
-unset GIT_EDITOR
 test_expect_success 'core.editor with a space' '
-
-	git config core.editor \"./e\ space.sh\" &&
+	test_config core.editor \"./e\ space.sh\" &&
 	git commit --amend &&
-	test space = "$(git show -s --pretty=format:%s)"
-
+	test_commit_message HEAD -m space
 '
 
 test_done
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index fd3e7e3..e6b551d 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -407,6 +407,31 @@
 	test_grep toplevel output.err
 '
 
+test_expect_success 'submodule add of a different algorithm fails' '
+	git init --object-format=sha256 sha256 &&
+	(
+		cd sha256 &&
+		test_commit abc &&
+		git init --object-format=sha1 submodule &&
+		test_commit -C submodule def &&
+		test_must_fail git submodule add "$submodurl" submodule 2>err &&
+		test_grep "cannot add a submodule of a different hash algorithm" err &&
+		git ls-files --stage >entries &&
+		test_grep ! ^160000 entries
+	) &&
+	git init --object-format=sha1 sha1 &&
+	(
+		cd sha1 &&
+		test_commit abc &&
+		git init --object-format=sha256 submodule &&
+		test_commit -C submodule def &&
+		test_must_fail git submodule add "$submodurl" submodule 2>err &&
+		test_grep "cannot add a submodule of a different hash algorithm" err &&
+		git ls-files --stage >entries &&
+		test_grep ! ^160000 entries
+	)
+'
+
 test_expect_success 'setup - add an example entry to .gitmodules' '
 	git config --file=.gitmodules submodule.example.url git://example.com/init.git
 '
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 4dca8d9..66aff8e 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -31,56 +31,83 @@
 	echo changes >> foo &&
 	git add foo &&
 	(
+		GIT_EDITOR="echo hello >" &&
+		export GIT_EDITOR &&
+		test_must_fail git commit --template "$(pwd)"/notexist
+	)
+'
+
+test_expect_success 'nonexistent optional template file on command line' '
+	echo changes >> foo &&
+	git add foo &&
+	(
 		GIT_EDITOR="echo hello >\"\$1\"" &&
 		export GIT_EDITOR &&
-		test_must_fail git commit --template "$PWD"/notexist
+		git commit --template ":(optional)$(pwd)/notexist"
 	)
 '
 
 test_expect_success 'nonexistent template file in config should return error' '
-	test_config commit.template "$PWD"/notexist &&
+	test_config commit.template "$(pwd)"/notexist &&
 	(
-		GIT_EDITOR="echo hello >\"\$1\"" &&
+		GIT_EDITOR="echo hello >" &&
 		export GIT_EDITOR &&
-		test_must_fail git commit
+		test_must_fail git commit --allow-empty
 	)
 '
 
+test_expect_success 'nonexistent optional template file in config' '
+	test_config commit.template ":(optional)$(pwd)"/notexist &&
+	GIT_EDITOR="echo hello >" git commit --allow-empty &&
+	git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
+	echo hello >expect &&
+	test_cmp expect actual
+'
+
 # From now on we'll use a template file that exists.
-TEMPLATE="$PWD"/template
+TEMPLATE="$(pwd)"/template
 
 test_expect_success 'unedited template should not commit' '
-	echo "template line" > "$TEMPLATE" &&
-	test_must_fail git commit --template "$TEMPLATE"
+	echo "template line" >"$TEMPLATE" &&
+	test_must_fail git commit --allow-empty --template "$TEMPLATE"
 '
 
 test_expect_success 'unedited template with comments should not commit' '
-	echo "# comment in template" >> "$TEMPLATE" &&
-	test_must_fail git commit --template "$TEMPLATE"
+	echo "# comment in template" >>"$TEMPLATE" &&
+	test_must_fail git commit --allow-empty --template "$TEMPLATE"
 '
 
 test_expect_success 'a Signed-off-by line by itself should not commit' '
 	(
 		test_set_editor "$TEST_DIRECTORY"/t7500/add-signed-off &&
-		test_must_fail git commit --template "$TEMPLATE"
+		test_must_fail git commit --allow-empty --template "$TEMPLATE"
 	)
 '
 
 test_expect_success 'adding comments to a template should not commit' '
 	(
 		test_set_editor "$TEST_DIRECTORY"/t7500/add-comments &&
-		test_must_fail git commit --template "$TEMPLATE"
+		test_must_fail git commit --allow-empty --template "$TEMPLATE"
 	)
 '
 
 test_expect_success 'adding real content to a template should commit' '
 	(
 		test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
-		git commit --template "$TEMPLATE"
+		git commit --allow-empty --template "$TEMPLATE"
 	) &&
 	commit_msg_is "template linecommit message"
 '
 
+test_expect_success 'existent template marked optional should commit' '
+	echo "existent template" >"$TEMPLATE" &&
+	(
+		test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+		git commit --allow-empty --template ":(optional)$TEMPLATE"
+	) &&
+	commit_msg_is "existent templatecommit message"
+'
+
 test_expect_success '-t option should be short for --template' '
 	echo "short template" > "$TEMPLATE" &&
 	echo "new content" >> foo &&
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index b37e201..05f6da4 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -956,13 +956,39 @@
 	test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG
 '
 
-test_expect_success 'switch core.commentchar' '
+test_expect_success !WITH_BREAKING_CHANGES 'switch core.commentchar' '
 	test_commit "#foo" foo &&
-	GIT_EDITOR=.git/FAKE_EDITOR git -c core.commentChar=auto commit --amend &&
+	cat >config-include <<-\EOF &&
+	[core]
+	    commentString=:
+	    commentString=%
+	    commentChar=auto
+	EOF
+	test_when_finished "rm config-include" &&
+	test_config include.path "$(pwd)/config-include" &&
+	test_config core.commentChar ! &&
+	GIT_EDITOR=.git/FAKE_EDITOR git commit --amend 2>err &&
+	sed -n "s/^hint: *\$//p; s/^hint: //p; s/^warning: //p" err >actual &&
+	cat >expect <<-EOF &&
+	Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0
+
+	To use the default comment string (#) please run
+
+	    git config unset core.commentChar
+	    git config unset --file ~/config-include --all core.commentString
+	    git config unset --file ~/config-include core.commentChar
+
+	To set a custom comment string please run
+
+	    git config set --file ~/config-include core.commentChar <comment string>
+
+	where ${SQ}<comment string>${SQ} is the string you wish to use.
+	EOF
+	test_cmp expect actual &&
 	test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG
 '
 
-test_expect_success 'switch core.commentchar but out of options' '
+test_expect_success !WITH_BREAKING_CHANGES 'switch core.commentchar but out of options' '
 	cat >text <<\EOF &&
 # 1
 ; 2
@@ -982,4 +1008,24 @@
 	)
 '
 
+test_expect_success WITH_BREAKING_CHANGES 'core.commentChar=auto is rejected' '
+	test_config core.commentChar auto &&
+	test_must_fail git rev-parse --git-dir 2>err &&
+	sed -n "s/^hint: *\$//p; s/^hint: //p; s/^fatal: //p" err >actual &&
+	cat >expect <<-EOF &&
+	Support for ${SQ}core.commentChar=auto${SQ} has been removed in Git 3.0
+
+	To use the default comment string (#) please run
+
+	    git config unset core.commentChar
+
+	To set a custom comment string please run
+
+	    git config set core.commentChar <comment string>
+
+	where ${SQ}<comment string>${SQ} is the string you wish to use.
+	EOF
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index ddd273d..6b36f52 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -49,7 +49,9 @@
 		git maintenance run --auto 2>/dev/null &&
 	GIT_TRACE2_EVENT="$(pwd)/run-no-quiet.txt" \
 		git maintenance run --no-quiet 2>/dev/null &&
+	git maintenance is-needed &&
 	test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-no-auto.txt &&
+	! git maintenance is-needed --auto &&
 	test_subcommand ! git gc --auto --quiet --no-detach --skip-foreground-tasks <run-auto.txt &&
 	test_subcommand git gc --no-quiet --no-detach --skip-foreground-tasks <run-no-quiet.txt
 '
@@ -180,6 +182,11 @@
 
 	test_commit first &&
 
+	! git -c maintenance.commit-graph.auto=0 \
+		maintenance is-needed --auto --task=commit-graph &&
+	git -c maintenance.commit-graph.auto=1 \
+		maintenance is-needed --auto --task=commit-graph &&
+
 	GIT_TRACE2_EVENT="$(pwd)/cg-zero-means-no.txt" \
 		git -c maintenance.commit-graph.auto=0 $COMMAND &&
 	GIT_TRACE2_EVENT="$(pwd)/cg-one-satisfied.txt" \
@@ -290,16 +297,23 @@
 		git -c maintenance.loose-objects.auto=1 maintenance \
 		run --auto --task=loose-objects 2>/dev/null &&
 	test_subcommand ! git prune-packed --quiet <trace-lo1.txt &&
+
 	printf data-A | git hash-object -t blob --stdin -w &&
+	! git -c maintenance.loose-objects.auto=2 \
+		maintenance is-needed --auto --task=loose-objects &&
 	GIT_TRACE2_EVENT="$(pwd)/trace-loA" \
 		git -c maintenance.loose-objects.auto=2 \
 		maintenance run --auto --task=loose-objects 2>/dev/null &&
 	test_subcommand ! git prune-packed --quiet <trace-loA &&
+
 	printf data-B | git hash-object -t blob --stdin -w &&
+	git -c maintenance.loose-objects.auto=2 \
+		maintenance is-needed --auto --task=loose-objects &&
 	GIT_TRACE2_EVENT="$(pwd)/trace-loB" \
 		git -c maintenance.loose-objects.auto=2 \
 		maintenance run --auto --task=loose-objects 2>/dev/null &&
 	test_subcommand git prune-packed --quiet <trace-loB &&
+
 	GIT_TRACE2_EVENT="$(pwd)/trace-loC" \
 		git -c maintenance.loose-objects.auto=2 \
 		maintenance run --auto --task=loose-objects 2>/dev/null &&
@@ -421,10 +435,13 @@
 	test_commit A &&
 	git repack -adk &&
 	git multi-pack-index write &&
+	! git -c maintenance.incremental-repack.auto=1 \
+		maintenance is-needed --auto --task=incremental-repack &&
 	GIT_TRACE2_EVENT="$(pwd)/midx-init.txt" git \
 		-c maintenance.incremental-repack.auto=1 \
 		maintenance run --auto --task=incremental-repack 2>/dev/null &&
 	test_subcommand ! git multi-pack-index write --no-progress <midx-init.txt &&
+
 	test_commit B &&
 	git pack-objects --revs .git/objects/pack/pack <<-\EOF &&
 	HEAD
@@ -434,11 +451,14 @@
 		-c maintenance.incremental-repack.auto=2 \
 		maintenance run --auto --task=incremental-repack 2>/dev/null &&
 	test_subcommand ! git multi-pack-index write --no-progress <trace-A &&
+
 	test_commit C &&
 	git pack-objects --revs .git/objects/pack/pack <<-\EOF &&
 	HEAD
 	^HEAD~1
 	EOF
+	git -c maintenance.incremental-repack.auto=2 \
+		maintenance is-needed --auto --task=incremental-repack &&
 	GIT_TRACE2_EVENT=$(pwd)/trace-B git \
 		-c maintenance.incremental-repack.auto=2 \
 		maintenance run --auto --task=incremental-repack 2>/dev/null &&
@@ -465,6 +485,176 @@
 	)
 '
 
+run_and_verify_geometric_pack () {
+	EXPECTED_PACKS="$1" &&
+
+	# Verify that we perform a geometric repack.
+	rm -f "trace2.txt" &&
+	GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+		git maintenance run --task=geometric-repack 2>/dev/null &&
+	test_subcommand git repack -d -l --geometric=2 \
+		--quiet --write-midx <trace2.txt &&
+
+	# Verify that the number of packfiles matches our expectation.
+	ls -l .git/objects/pack/*.pack >packfiles &&
+	test_line_count = "$EXPECTED_PACKS" packfiles &&
+
+	# And verify that there are no loose objects anymore.
+	git count-objects -v >count &&
+	test_grep '^count: 0$' count
+}
+
+test_expect_success 'geometric repacking task' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		git config set maintenance.auto false &&
+		test_commit initial &&
+
+		# The initial repack causes an all-into-one repack.
+		GIT_TRACE2_EVENT="$(pwd)/initial-repack.txt" \
+			git maintenance run --task=geometric-repack 2>/dev/null &&
+		test_subcommand git repack -d -l --cruft --cruft-expiration=2.weeks.ago \
+			--quiet --write-midx <initial-repack.txt &&
+
+		# Repacking should now cause a no-op geometric repack because
+		# no packfiles need to be combined.
+		ls -l .git/objects/pack/*.pack >before &&
+		run_and_verify_geometric_pack 1 &&
+		ls -l .git/objects/pack/*.pack >after &&
+		test_cmp before after &&
+
+		# This incremental change creates a new packfile that only
+		# soaks up loose objects. The packfiles are not getting merged
+		# at this point.
+		test_commit loose &&
+		run_and_verify_geometric_pack 2 &&
+
+		# Both packfiles have 3 objects, so the next run would cause us
+		# to merge all packfiles together. This should be turned into
+		# an all-into-one-repack.
+		GIT_TRACE2_EVENT="$(pwd)/all-into-one-repack.txt" \
+			git maintenance run --task=geometric-repack 2>/dev/null &&
+		test_subcommand git repack -d -l --cruft --cruft-expiration=2.weeks.ago \
+			--quiet --write-midx <all-into-one-repack.txt &&
+
+		# The geometric repack soaks up unreachable objects.
+		echo blob-1 | git hash-object -w --stdin -t blob &&
+		run_and_verify_geometric_pack 2 &&
+
+		# A second unreachable object should be written into another packfile.
+		echo blob-2 | git hash-object -w --stdin -t blob &&
+		run_and_verify_geometric_pack 3 &&
+
+		# And these two small packs should now be merged via the
+		# geometric repack. The large packfile should remain intact.
+		run_and_verify_geometric_pack 2 &&
+
+		# If we now add two more objects and repack twice we should
+		# then see another all-into-one repack. This time around
+		# though, as we have unreachable objects, we should also see a
+		# cruft pack.
+		echo blob-3 | git hash-object -w --stdin -t blob &&
+		echo blob-4 | git hash-object -w --stdin -t blob &&
+		run_and_verify_geometric_pack 3 &&
+		GIT_TRACE2_EVENT="$(pwd)/cruft-repack.txt" \
+			git maintenance run --task=geometric-repack 2>/dev/null &&
+		test_subcommand git repack -d -l --cruft --cruft-expiration=2.weeks.ago \
+			--quiet --write-midx <cruft-repack.txt &&
+		ls .git/objects/pack/*.pack >packs &&
+		test_line_count = 2 packs &&
+		ls .git/objects/pack/*.mtimes >cruft &&
+		test_line_count = 1 cruft
+	)
+'
+
+test_geometric_repack_needed () {
+	NEEDED="$1"
+	GEOMETRIC_CONFIG="$2" &&
+	rm -f trace2.txt &&
+	GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+		git ${GEOMETRIC_CONFIG:+-c maintenance.geometric-repack.$GEOMETRIC_CONFIG} \
+		maintenance run --auto --task=geometric-repack 2>/dev/null &&
+	case "$NEEDED" in
+	true)
+		test_grep "\[\"git\",\"repack\"," trace2.txt;;
+	false)
+		! test_grep "\[\"git\",\"repack\"," trace2.txt;;
+	*)
+		BUG "invalid parameter: $NEEDED";;
+	esac
+}
+
+test_expect_success 'geometric repacking with --auto' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+
+		# An empty repository does not need repacking, except when
+		# explicitly told to do it.
+		test_geometric_repack_needed false &&
+		test_geometric_repack_needed false auto=0 &&
+		test_geometric_repack_needed false auto=1 &&
+		test_geometric_repack_needed true auto=-1 &&
+
+		test_oid_init &&
+
+		# Loose objects cause a repack when crossing the limit. Note
+		# that the number of objects gets extrapolated by having a look
+		# at the "objects/17/" shard.
+		test_commit "$(test_oid blob17_1)" &&
+		test_geometric_repack_needed false &&
+		test_commit "$(test_oid blob17_2)" &&
+		test_geometric_repack_needed false auto=257 &&
+		test_geometric_repack_needed true auto=256 &&
+
+		# Force another repack.
+		test_commit first &&
+		test_commit second &&
+		test_geometric_repack_needed true auto=-1 &&
+
+		# We now have two packfiles that would be merged together. As
+		# such, the repack should always happen unless the user has
+		# disabled the auto task.
+		test_geometric_repack_needed false auto=0 &&
+		test_geometric_repack_needed true auto=9000
+	)
+'
+
+test_expect_success 'geometric repacking honors configured split factor' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		git config set maintenance.auto false &&
+
+		# Create three different packs with 9, 2 and 1 object, respectively.
+		# This is done so that only a subset of packs would be merged
+		# together so that we can verify that `git repack` receives the
+		# correct geometric factor.
+		for i in $(test_seq 9)
+		do
+			echo first-$i | git hash-object -w --stdin -t blob || return 1
+		done &&
+		git repack --geometric=2 -d &&
+
+		for i in $(test_seq 2)
+		do
+			echo second-$i | git hash-object -w --stdin -t blob || return 1
+		done &&
+		git repack --geometric=2 -d &&
+
+		echo third | git hash-object -w --stdin -t blob &&
+		git repack --geometric=2 -d &&
+
+		test_geometric_repack_needed false splitFactor=2 &&
+		test_geometric_repack_needed true splitFactor=3 &&
+		test_subcommand git repack -d -l --geometric=3 --quiet --write-midx <trace2.txt
+	)
+'
+
 test_expect_success 'pack-refs task' '
 	for n in $(test_seq 1 5)
 	do
@@ -485,9 +675,15 @@
 	git reflog expire --all --expire=now &&
 	test_commit reflog-one &&
 	test_commit reflog-two &&
+
+	! git -c maintenance.reflog-expire.auto=3 \
+		maintenance is-needed --auto --task=reflog-expire &&
 	GIT_TRACE2_EVENT="$(pwd)/reflog-expire-auto.txt" \
 		git -c maintenance.reflog-expire.auto=3 maintenance run --auto --task=reflog-expire &&
 	test_subcommand ! git reflog expire --all <reflog-expire-auto.txt &&
+
+	git -c maintenance.reflog-expire.auto=2 \
+		maintenance is-needed --auto --task=reflog-expire &&
 	GIT_TRACE2_EVENT="$(pwd)/reflog-expire-auto.txt" \
 		git -c maintenance.reflog-expire.auto=2 maintenance run --auto --task=reflog-expire &&
 	test_subcommand git reflog expire --all <reflog-expire-auto.txt
@@ -514,6 +710,7 @@
 	test_expect_worktree_prune ! git maintenance run --auto --task=worktree-prune &&
 	mkdir .git/worktrees &&
 	: >.git/worktrees/abc &&
+	git maintenance is-needed --auto --task=worktree-prune &&
 	test_expect_worktree_prune git maintenance run --auto --task=worktree-prune
 '
 
@@ -530,22 +727,7 @@
 	test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=0 maintenance run --auto --task=worktree-prune &&
 	# A positive value should require at least this many prunable worktrees.
 	test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=4 maintenance run --auto --task=worktree-prune &&
-	test_expect_worktree_prune git -c maintenance.worktree-prune.auto=3 maintenance run --auto --task=worktree-prune
-'
-
-test_expect_success 'worktree-prune task with --auto honors maintenance.worktree-prune.auto' '
-	# A negative value should always prune.
-	test_expect_worktree_prune git -c maintenance.worktree-prune.auto=-1 maintenance run --auto --task=worktree-prune &&
-
-	mkdir .git/worktrees &&
-	: >.git/worktrees/first &&
-	: >.git/worktrees/second &&
-	: >.git/worktrees/third &&
-
-	# Zero should never prune.
-	test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=0 maintenance run --auto --task=worktree-prune &&
-	# A positive value should require at least this many prunable worktrees.
-	test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=4 maintenance run --auto --task=worktree-prune &&
+	git -c maintenance.worktree-prune.auto=3 maintenance is-needed --auto --task=worktree-prune &&
 	test_expect_worktree_prune git -c maintenance.worktree-prune.auto=3 maintenance run --auto --task=worktree-prune
 '
 
@@ -554,11 +736,13 @@
 	rm -rf worktree &&
 
 	rm -f worktree-prune.txt &&
+	! git -c gc.worktreePruneExpire=1.week.ago maintenance is-needed --auto --task=worktree-prune &&
 	GIT_TRACE2_EVENT="$(pwd)/worktree-prune.txt" git -c gc.worktreePruneExpire=1.week.ago maintenance run --auto --task=worktree-prune &&
 	test_subcommand ! git worktree prune --expire 1.week.ago <worktree-prune.txt &&
 	test_path_is_dir .git/worktrees/worktree &&
 
 	rm -f worktree-prune.txt &&
+	git -c gc.worktreePruneExpire=now maintenance is-needed --auto --task=worktree-prune &&
 	GIT_TRACE2_EVENT="$(pwd)/worktree-prune.txt" git -c gc.worktreePruneExpire=now maintenance run --auto --task=worktree-prune &&
 	test_subcommand git worktree prune --expire now <worktree-prune.txt &&
 	test_path_is_missing .git/worktrees/worktree
@@ -583,10 +767,13 @@
 
 test_expect_success 'rerere-gc task with --auto only prunes with prunable entries' '
 	test_when_finished "rm -rf .git/rr-cache" &&
+	! git maintenance is-needed --auto --task=rerere-gc &&
 	test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
 	mkdir .git/rr-cache &&
+	! git maintenance is-needed --auto --task=rerere-gc &&
 	test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
 	: >.git/rr-cache/entry &&
+	git maintenance is-needed --auto --task=rerere-gc &&
 	test_expect_rerere_gc git maintenance run --auto --task=rerere-gc
 '
 
@@ -594,17 +781,22 @@
 	test_when_finished "rm -rf .git/rr-cache" &&
 
 	# A negative value should always prune.
+	git -c maintenance.rerere-gc.auto=-1 maintenance is-needed --auto --task=rerere-gc &&
 	test_expect_rerere_gc git -c maintenance.rerere-gc.auto=-1 maintenance run --auto --task=rerere-gc &&
 
 	# A positive value prunes when there is at least one entry.
+	! git -c maintenance.rerere-gc.auto=9000 maintenance is-needed --auto --task=rerere-gc &&
 	test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
 	mkdir .git/rr-cache &&
+	! git -c maintenance.rerere-gc.auto=9000 maintenance is-needed --auto --task=rerere-gc &&
 	test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
 	: >.git/rr-cache/entry-1 &&
+	git -c maintenance.rerere-gc.auto=9000 maintenance is-needed --auto --task=rerere-gc &&
 	test_expect_rerere_gc git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
 
 	# Zero should never prune.
 	: >.git/rr-cache/entry-1 &&
+	! git -c maintenance.rerere-gc.auto=0 maintenance is-needed --auto --task=rerere-gc &&
 	test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=0 maintenance run --auto --task=rerere-gc
 '
 
@@ -716,6 +908,76 @@
 		<modified-daily.txt
 '
 
+test_strategy () {
+	STRATEGY="$1"
+	shift
+
+	cat >expect &&
+	rm -f trace2.txt &&
+	GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+		git -c maintenance.strategy=$STRATEGY maintenance run --quiet "$@" &&
+	sed -n 's/{"event":"child_start","sid":"[^/"]*",.*,"argv":\["\(.*\)\"]}/\1/p' <trace2.txt |
+		sed 's/","/ /g'  >actual
+	test_cmp expect actual
+}
+
+test_expect_success 'maintenance.strategy is respected' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+
+		test_must_fail git -c maintenance.strategy=unknown maintenance run 2>err &&
+		test_grep "unknown maintenance strategy: .unknown." err &&
+
+		test_strategy incremental <<-\EOF &&
+		git pack-refs --all --prune
+		git reflog expire --all
+		git gc --quiet --no-detach --skip-foreground-tasks
+		EOF
+
+		test_strategy incremental --schedule=weekly <<-\EOF &&
+		git pack-refs --all --prune
+		git prune-packed --quiet
+		git multi-pack-index write --no-progress
+		git multi-pack-index expire --no-progress
+		git multi-pack-index repack --no-progress --batch-size=1
+		git commit-graph write --split --reachable --no-progress
+		EOF
+
+		test_strategy gc <<-\EOF &&
+		git pack-refs --all --prune
+		git reflog expire --all
+		git gc --quiet --no-detach --skip-foreground-tasks
+		EOF
+
+		test_strategy gc --schedule=weekly <<-\EOF &&
+		git pack-refs --all --prune
+		git reflog expire --all
+		git gc --quiet --no-detach --skip-foreground-tasks
+		EOF
+
+		test_strategy geometric <<-\EOF &&
+		git pack-refs --all --prune
+		git reflog expire --all
+		git repack -d -l --geometric=2 --quiet --write-midx
+		git commit-graph write --split --reachable --no-progress
+		git worktree prune --expire 3.months.ago
+		git rerere gc
+		EOF
+
+		test_strategy geometric --schedule=weekly <<-\EOF
+		git pack-refs --all --prune
+		git reflog expire --all
+		git repack -d -l --geometric=2 --quiet --write-midx
+		git commit-graph write --split --reachable --no-progress
+		git worktree prune --expire 3.months.ago
+		git rerere gc
+		EOF
+	)
+'
+
 test_expect_success 'register and unregister' '
 	test_when_finished git config --global --unset-all maintenance.repo &&
 
@@ -1093,6 +1355,11 @@
 	nongit test_must_fail git maintenance unregister
 '
 
+test_expect_success 'fails when configured to use an invalid strategy' '
+	test_must_fail git -c maintenance.strategy=invalid maintenance run --schedule=hourly 2>err &&
+	test_grep "unknown maintenance strategy: .invalid." err
+'
+
 test_expect_success 'register and unregister bare repo' '
 	test_when_finished "git config --global --unset-all maintenance.repo || :" &&
 	test_might_fail git config --global --unset-all maintenance.repo &&
diff --git a/t/t8020-last-modified.sh b/t/t8020-last-modified.sh
new file mode 100755
index 0000000..a4c1114
--- /dev/null
+++ b/t/t8020-last-modified.sh
@@ -0,0 +1,230 @@
+#!/bin/sh
+
+test_description='last-modified tests'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	test_commit 1 file &&
+	mkdir a &&
+	test_commit 2 a/file &&
+	mkdir a/b &&
+	test_commit 3 a/b/file
+'
+
+test_expect_success 'cannot run last-modified on two trees' '
+	test_must_fail git last-modified HEAD HEAD~1
+'
+
+check_last_modified() {
+	local indir= &&
+	while test $# != 0
+	do
+		case "$1" in
+		-C)
+			indir="$2"
+			shift
+			;;
+		*)
+			break
+			;;
+		esac &&
+		shift
+	done &&
+
+	cat >expect &&
+	git ${indir:+-C "$indir"} last-modified "$@" >tmp.1 &&
+	git name-rev --annotate-stdin --name-only --tags \
+		<tmp.1 >tmp.2 &&
+	tr '\t' ' ' <tmp.2 >actual &&
+	test_cmp expect actual
+}
+
+test_expect_success 'last-modified non-recursive' '
+	check_last_modified <<-\EOF
+	3 a
+	1 file
+	EOF
+'
+
+test_expect_success 'last-modified recursive' '
+	check_last_modified -r <<-\EOF
+	3 a/b/file
+	2 a/file
+	1 file
+	EOF
+'
+
+test_expect_success 'last-modified recursive with show-trees' '
+	check_last_modified -r -t <<-\EOF
+	3 a/b
+	3 a/b/file
+	3 a
+	2 a/file
+	1 file
+	EOF
+'
+
+test_expect_success 'last-modified non-recursive with show-trees' '
+	check_last_modified -t <<-\EOF
+	3 a
+	1 file
+	EOF
+'
+
+test_expect_success 'last-modified subdir' '
+	check_last_modified a <<-\EOF
+	3 a
+	EOF
+'
+
+test_expect_success 'last-modified subdir recursive' '
+	check_last_modified -r a <<-\EOF
+	3 a/b/file
+	2 a/file
+	EOF
+'
+
+test_expect_success 'last-modified from non-HEAD commit' '
+	check_last_modified HEAD^ <<-\EOF
+	2 a
+	1 file
+	EOF
+'
+
+test_expect_success 'last-modified from subdir defaults to root' '
+	check_last_modified -C a <<-\EOF
+	3 a
+	1 file
+	EOF
+'
+
+test_expect_success 'last-modified from subdir uses relative pathspecs' '
+	check_last_modified -C a -r b <<-\EOF
+	3 a/b/file
+	EOF
+'
+
+test_expect_success 'limit last-modified traversal by count' '
+	check_last_modified -1 <<-\EOF
+	3 a
+	^2 file
+	EOF
+'
+
+test_expect_success 'limit last-modified traversal by commit' '
+	check_last_modified HEAD~2..HEAD <<-\EOF
+	3 a
+	^1 file
+	EOF
+'
+
+test_expect_success 'only last-modified files in the current tree' '
+	git rm -rf a &&
+	git commit -m "remove a" &&
+	check_last_modified <<-\EOF
+	1 file
+	EOF
+'
+
+test_expect_success 'subdirectory modified via merge' '
+	test_when_finished rm -rf repo &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit base &&
+		git switch --create left &&
+		mkdir subdir &&
+		test_commit left subdir/left &&
+		git switch --create right base &&
+		mkdir subdir &&
+		test_commit right subdir/right &&
+		git switch - &&
+		test_merge merge right &&
+		check_last_modified <<-\EOF
+		merge subdir
+		base base.t
+		EOF
+	)
+'
+
+test_expect_success 'cross merge boundaries in blaming' '
+	git checkout HEAD^0 &&
+	git rm -rf . &&
+	test_commit m1 &&
+	git checkout HEAD^ &&
+	git rm -rf . &&
+	test_commit m2 &&
+	git merge m1 &&
+	check_last_modified <<-\EOF
+	m2 m2.t
+	m1 m1.t
+	EOF
+'
+
+test_expect_success 'last-modified merge for resolved conflicts' '
+	git checkout HEAD^0 &&
+	git rm -rf . &&
+	test_commit c1 conflict &&
+	git checkout HEAD^ &&
+	git rm -rf . &&
+	test_commit c2 conflict &&
+	test_must_fail git merge c1 &&
+	test_commit resolved conflict &&
+	check_last_modified conflict <<-\EOF
+	resolved conflict
+	EOF
+'
+
+
+# Consider `file` with this content through history:
+#
+# A---B---B-------B---B
+#          \     /
+#           C---D
+test_expect_success 'last-modified merge ignores content from branch' '
+	git checkout HEAD^0 &&
+	git rm -rf . &&
+	test_commit a1 file A &&
+	test_commit a2 file B &&
+	test_commit a3 file C &&
+	test_commit a4 file D &&
+	git checkout a2 &&
+	git merge --no-commit --no-ff a4 &&
+	git checkout a2 -- file &&
+	git merge --continue &&
+	check_last_modified <<-\EOF
+	a2 file
+	EOF
+'
+
+# Consider `file` with this content through history:
+#
+#  A---B---B---C---D---B---B
+#           \         /
+#            B-------B
+test_expect_success 'last-modified merge undoes changes' '
+	git checkout HEAD^0 &&
+	git rm -rf . &&
+	test_commit b1 file A &&
+	test_commit b2 file B &&
+	test_commit b3 file C &&
+	test_commit b4 file D &&
+	git checkout b2 &&
+	test_commit b5 file2 2 &&
+	git checkout b4 &&
+	git merge --no-commit --no-ff b5 &&
+	git checkout b2 -- file &&
+	git merge --continue &&
+	check_last_modified <<-\EOF
+	b5 file2
+	b2 file
+	EOF
+'
+
+test_expect_success 'last-modified complains about unknown arguments' '
+	test_must_fail git last-modified --foo 2>err &&
+	grep "unknown last-modified argument: --foo" err
+'
+
+test_done
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 4dc3d64..5685cce 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -2927,16 +2927,16 @@
 # The error message when a space is missing not at the
 # end of the line is:
 #
-#   Missing space after ..
+#   missing space after ..
 #
 # or when extra characters come after the mark at the end
 # of the line:
 #
-#   Garbage after ..
+#   garbage after ..
 #
 # or when the dataref is neither "inline " or a known SHA1,
 #
-#   Invalid dataref ..
+#   invalid dataref ..
 #
 test_expect_success 'S: initialize for S tests' '
 	test_tick &&
@@ -3405,15 +3405,15 @@
 
 test_path_base_fail () {
 	local change="$1" prefix="$2" field="$3" suffix="$4"
-	test_path_fail "$change" 'unclosed " in '"$field"          "$prefix" '"hello.c'    "$suffix" "Invalid $field"
-	test_path_fail "$change" "invalid escape in quoted $field" "$prefix" '"hello\xff"' "$suffix" "Invalid $field"
+	test_path_fail "$change" 'unclosed " in '"$field"          "$prefix" '"hello.c'    "$suffix" "invalid $field"
+	test_path_fail "$change" "invalid escape in quoted $field" "$prefix" '"hello\xff"' "$suffix" "invalid $field"
 	test_path_fail "$change" "escaped NUL in quoted $field"    "$prefix" '"hello\000"' "$suffix" "NUL in $field"
 }
 test_path_eol_quoted_fail () {
 	local change="$1" prefix="$2" field="$3"
 	test_path_base_fail "$change" "$prefix" "$field" ''
-	test_path_fail "$change" "garbage after quoted $field" "$prefix" '"hello.c"' 'x' "Garbage after $field"
-	test_path_fail "$change" "space after quoted $field"   "$prefix" '"hello.c"' ' ' "Garbage after $field"
+	test_path_fail "$change" "garbage after quoted $field" "$prefix" '"hello.c"' 'x' "garbage after $field"
+	test_path_fail "$change" "space after quoted $field"   "$prefix" '"hello.c"' ' ' "garbage after $field"
 }
 test_path_eol_fail () {
 	local change="$1" prefix="$2" field="$3"
@@ -3422,8 +3422,8 @@
 test_path_space_fail () {
 	local change="$1" prefix="$2" field="$3"
 	test_path_base_fail "$change" "$prefix" "$field" ' world.c'
-	test_path_fail "$change" "missing space after quoted $field"   "$prefix" '"hello.c"' 'x world.c' "Missing space after $field"
-	test_path_fail "$change" "missing space after unquoted $field" "$prefix" 'hello.c'   ''          "Missing space after $field"
+	test_path_fail "$change" "missing space after quoted $field"   "$prefix" '"hello.c"' 'x world.c' "missing space after $field"
+	test_path_fail "$change" "missing space after unquoted $field" "$prefix" 'hello.c'   ''          "missing space after $field"
 }
 
 test_path_eol_fail   filemodify       'M 100644 :1 ' path
@@ -3820,7 +3820,7 @@
 		sed -e s/othername/somename/ tmp >tmp2 &&
 		git fast-import --force <tmp2 2>msgs &&
 
-		grep "Dropping.*since it would point to itself" msgs &&
+		grep "dropping.*since it would point to itself" msgs &&
 		git show-ref >refs &&
 		! grep refs/replace refs
 	)
diff --git a/t/t9305-fast-import-signatures.sh b/t/t9305-fast-import-signatures.sh
new file mode 100755
index 0000000..c2b4271
--- /dev/null
+++ b/t/t9305-fast-import-signatures.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+test_description='git fast-import --signed-commits=<mode>'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
+
+test_expect_success 'set up unsigned initial commit and import repo' '
+	test_commit first &&
+	git init new
+'
+
+test_expect_success GPG 'set up OpenPGP signed commit' '
+	git checkout -b openpgp-signing main &&
+	echo "Content for OpenPGP signing." >file-sign &&
+	git add file-sign &&
+	git commit -S -m "OpenPGP signed commit" &&
+	OPENPGP_SIGNING=$(git rev-parse --verify openpgp-signing)
+'
+
+test_expect_success GPG 'import OpenPGP signature with --signed-commits=verbatim' '
+	git fast-export --signed-commits=verbatim openpgp-signing >output &&
+	git -C new fast-import --quiet --signed-commits=verbatim <output >log 2>&1 &&
+	IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
+	test $OPENPGP_SIGNING = $IMPORTED &&
+	test_must_be_empty log
+'
+
+test_expect_success GPGSM 'set up X.509 signed commit' '
+	git checkout -b x509-signing main &&
+	test_config gpg.format x509 &&
+	test_config user.signingkey $GIT_COMMITTER_EMAIL &&
+	echo "Content for X.509 signing." >file-sign &&
+	git add file-sign &&
+	git commit -S -m "X.509 signed commit" &&
+	X509_SIGNING=$(git rev-parse HEAD)
+'
+
+test_expect_success GPGSM 'import X.509 signature fails with --signed-commits=abort' '
+	git fast-export --signed-commits=verbatim x509-signing >output &&
+	test_must_fail git -C new fast-import --quiet --signed-commits=abort <output
+'
+
+test_expect_success GPGSM 'import X.509 signature with --signed-commits=warn-verbatim' '
+	git -C new fast-import --quiet --signed-commits=warn-verbatim <output >log 2>&1 &&
+	IMPORTED=$(git -C new rev-parse --verify refs/heads/x509-signing) &&
+	test $X509_SIGNING = $IMPORTED &&
+	test_grep "importing a commit signature" log
+'
+
+test_expect_success GPGSSH 'set up SSH signed commit' '
+	git checkout -b ssh-signing main &&
+	test_config gpg.format ssh &&
+	test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+	echo "Content for SSH signing." >file-sign &&
+	git add file-sign &&
+	git commit -S -m "SSH signed commit" &&
+	SSH_SIGNING=$(git rev-parse HEAD)
+'
+
+test_expect_success GPGSSH 'strip SSH signature with --signed-commits=strip' '
+	git fast-export --signed-commits=verbatim ssh-signing >output &&
+	git -C new fast-import --quiet --signed-commits=strip <output >log 2>&1 &&
+	IMPORTED=$(git -C new rev-parse --verify refs/heads/ssh-signing) &&
+	test $SSH_SIGNING != $IMPORTED &&
+	git -C new cat-file commit "$IMPORTED" >actual &&
+	test_grep ! -E "^gpgsig" actual &&
+	test_must_be_empty log
+'
+
+test_expect_success GPG 'setup a commit with dual OpenPGP signatures on its SHA-1 and SHA-256 formats' '
+	# Create a signed SHA-256 commit
+	git init --object-format=sha256 explicit-sha256 &&
+	git -C explicit-sha256 config extensions.compatObjectFormat sha1 &&
+	git -C explicit-sha256 checkout -b dual-signed &&
+	test_commit -C explicit-sha256 A &&
+	echo B >explicit-sha256/B &&
+	git -C explicit-sha256 add B &&
+	test_tick &&
+	git -C explicit-sha256 commit -S -m "signed" B &&
+	SHA256_B=$(git -C explicit-sha256 rev-parse dual-signed) &&
+
+	# Create the corresponding SHA-1 commit
+	SHA1_B=$(git -C explicit-sha256 rev-parse --output-object-format=sha1 dual-signed) &&
+
+	# Check that the resulting SHA-1 commit has both signatures
+	git -C explicit-sha256 cat-file -p $SHA1_B >out &&
+	test_grep -E "^gpgsig " out &&
+	test_grep -E "^gpgsig-sha256 " out
+'
+
+test_expect_success GPG 'strip both OpenPGP signatures with --signed-commits=warn-strip' '
+	git -C explicit-sha256 fast-export --signed-commits=verbatim dual-signed >output &&
+	test_grep -E "^gpgsig sha1 openpgp" output &&
+	test_grep -E "^gpgsig sha256 openpgp" output &&
+	git -C new fast-import --quiet --signed-commits=warn-strip <output >log 2>&1 &&
+	git -C new cat-file commit refs/heads/dual-signed >actual &&
+	test_grep ! -E "^gpgsig " actual &&
+	test_grep ! -E "^gpgsig-sha256 " actual &&
+	test_grep "stripping a commit signature" log >out &&
+	test_line_count = 2 out
+'
+
+test_done
diff --git a/t/t9306-fast-import-signed-tags.sh b/t/t9306-fast-import-signed-tags.sh
new file mode 100755
index 0000000..363619e
--- /dev/null
+++ b/t/t9306-fast-import-signed-tags.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+test_description='git fast-import --signed-tags=<mode>'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
+
+test_expect_success 'set up unsigned initial commit and import repo' '
+	test_commit first &&
+	git init new
+'
+
+test_expect_success 'import no signed tag with --signed-tags=abort' '
+	git fast-export --signed-tags=verbatim >output &&
+	git -C new fast-import --quiet --signed-tags=abort <output
+'
+
+test_expect_success GPG 'set up OpenPGP signed tag' '
+	git tag -s -m "OpenPGP signed tag" openpgp-signed first &&
+	OPENPGP_SIGNED=$(git rev-parse --verify refs/tags/openpgp-signed) &&
+	git fast-export --signed-tags=verbatim openpgp-signed >output
+'
+
+test_expect_success GPG 'import OpenPGP signed tag with --signed-tags=abort' '
+	test_must_fail git -C new fast-import --quiet --signed-tags=abort <output
+'
+
+test_expect_success GPG 'import OpenPGP signed tag with --signed-tags=verbatim' '
+	git -C new fast-import --quiet --signed-tags=verbatim <output >log 2>&1 &&
+	IMPORTED=$(git -C new rev-parse --verify refs/tags/openpgp-signed) &&
+	test $OPENPGP_SIGNED = $IMPORTED &&
+	test_must_be_empty log
+'
+
+test_expect_success GPGSM 'setup X.509 signed tag' '
+	test_config gpg.format x509 &&
+	test_config user.signingkey $GIT_COMMITTER_EMAIL &&
+
+	git tag -s -m "X.509 signed tag" x509-signed first &&
+	X509_SIGNED=$(git rev-parse --verify refs/tags/x509-signed) &&
+	git fast-export --signed-tags=verbatim x509-signed >output
+'
+
+test_expect_success GPGSM 'import X.509 signed tag with --signed-tags=warn-strip' '
+	git -C new fast-import --quiet --signed-tags=warn-strip <output >log 2>&1 &&
+	test_grep "stripping a tag signature for tag '\''x509-signed'\''" log &&
+	IMPORTED=$(git -C new rev-parse --verify refs/tags/x509-signed) &&
+	test $X509_SIGNED != $IMPORTED &&
+	git -C new cat-file -p x509-signed >out &&
+	test_grep ! "SIGNED MESSAGE" out
+'
+
+test_expect_success GPGSSH 'setup SSH signed tag' '
+	test_config gpg.format ssh &&
+	test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+
+	git tag -s -m "SSH signed tag" ssh-signed first &&
+	SSH_SIGNED=$(git rev-parse --verify refs/tags/ssh-signed) &&
+	git fast-export --signed-tags=verbatim ssh-signed >output
+'
+
+test_expect_success GPGSSH 'import SSH signed tag with --signed-tags=warn-verbatim' '
+	git -C new fast-import --quiet --signed-tags=warn-verbatim <output >log 2>&1 &&
+	test_grep "importing a tag signature verbatim for tag '\''ssh-signed'\''" log &&
+	IMPORTED=$(git -C new rev-parse --verify refs/tags/ssh-signed) &&
+	test $SSH_SIGNED = $IMPORTED
+'
+
+test_expect_success GPGSSH 'import SSH signed tag with --signed-tags=strip' '
+	git -C new fast-import --quiet --signed-tags=strip <output >log 2>&1 &&
+	test_must_be_empty log &&
+	IMPORTED=$(git -C new rev-parse --verify refs/tags/ssh-signed) &&
+	test $SSH_SIGNED != $IMPORTED &&
+	git -C new cat-file -p ssh-signed >out &&
+	test_grep ! "SSH SIGNATURE" out
+'
+
+test_done
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 8f85c69..3d153a4 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -35,6 +35,7 @@
 	git commit -m sitzt file2 &&
 	test_tick &&
 	git tag -a -m valentin muss &&
+	ANNOTATED_TAG_COUNT=1 &&
 	git merge -s ours main
 
 '
@@ -229,7 +230,8 @@
 
 test_expect_success 'set up faked signed tag' '
 
-	git fast-import <signed-tag-import
+	git fast-import <signed-tag-import &&
+	ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1))
 
 '
 
@@ -277,6 +279,42 @@
 	test -s err
 '
 
+test_expect_success GPGSM 'setup X.509 signed tag' '
+	test_config gpg.format x509 &&
+	test_config user.signingkey $GIT_COMMITTER_EMAIL &&
+
+	git tag -s -m "X.509 signed tag" x509-signed $(git rev-parse HEAD) &&
+	ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1))
+'
+
+test_expect_success GPGSM 'signed-tags=verbatim with X.509' '
+	git fast-export --signed-tags=verbatim x509-signed > output &&
+	test_grep "SIGNED MESSAGE" output
+'
+
+test_expect_success GPGSM 'signed-tags=strip with X.509' '
+	git fast-export --signed-tags=strip x509-signed > output &&
+	test_grep ! "SIGNED MESSAGE" output
+'
+
+test_expect_success GPGSSH 'setup SSH signed tag' '
+	test_config gpg.format ssh &&
+	test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+
+	git tag -s -m "SSH signed tag" ssh-signed $(git rev-parse HEAD) &&
+	ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1))
+'
+
+test_expect_success GPGSSH 'signed-tags=verbatim with SSH' '
+	git fast-export --signed-tags=verbatim ssh-signed > output &&
+	test_grep "SSH SIGNATURE" output
+'
+
+test_expect_success GPGSSH 'signed-tags=strip with SSH' '
+	git fast-export --signed-tags=strip ssh-signed > output &&
+	test_grep ! "SSH SIGNATURE" output
+'
+
 test_expect_success GPG 'set up signed commit' '
 
 	# Generate a commit with both "gpgsig" and "encoding" set, so
@@ -491,8 +529,9 @@
 test_expect_success 'fast-export | fast-import when main is tagged' '
 
 	git tag -m msg last &&
+	ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1)) &&
 	git fast-export -C -C --signed-tags=strip --all > output &&
-	test $(grep -c "^tag " output) = 3
+	test $(grep -c "^tag " output) = $ANNOTATED_TAG_COUNT
 
 '
 
@@ -506,12 +545,13 @@
 
 	TAG=$(git hash-object --literally -t tag -w tag-content) &&
 	git update-ref refs/tags/sonnenschein $TAG &&
+	ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1)) &&
 	git fast-export -C -C --signed-tags=strip --all > output &&
-	test $(grep -c "^tag " output) = 4 &&
+	test $(grep -c "^tag " output) = $ANNOTATED_TAG_COUNT &&
 	! grep "Unspecified Tagger" output &&
 	git fast-export -C -C --signed-tags=strip --all \
 		--fake-missing-tagger > output &&
-	test $(grep -c "^tag " output) = 4 &&
+	test $(grep -c "^tag " output) = $ANNOTATED_TAG_COUNT &&
 	grep "Unspecified Tagger" output
 
 '
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 6650d33..964e1f1 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -11,9 +11,9 @@
 # untraceable with such ancient Bash versions.
 test_untraceable=UnfortunatelyYes
 
-# Override environment and always use master for the default initial branch
+# Override environment and always use main for the default initial branch
 # name for these tests, so that rev completion candidates are as expected.
-GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./lib-bash.sh
@@ -1453,7 +1453,7 @@
 		HEAD Z
 		final Z
 		initial Z
-		master Z
+		main Z
 		EOF
 	)
 '
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index a28de7b..52d7759 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1708,11 +1708,16 @@
 # Detect the hash algorithm in use.
 test_detect_hash () {
 	case "${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}" in
-	"sha256")
+	*:*)
+	    test_hash_algo="${GIT_TEST_DEFAULT_HASH%%:*}"
+	    test_compat_hash_algo="${GIT_TEST_DEFAULT_HASH##*:}"
+	    test_repo_compat_hash_algo="$test_compat_hash_algo"
+	    ;;
+	sha256)
 	    test_hash_algo=sha256
 	    test_compat_hash_algo=sha1
 	    ;;
-	*)
+	sha1)
 	    test_hash_algo=sha1
 	    test_compat_hash_algo=sha256
 	    ;;
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 621cd31..ef0ab7e 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -127,11 +127,18 @@
 	export GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS
 fi
 
-# Explicitly set the default branch name for testing, to avoid the
-# transitory "git init" warning under --verbose.
-: ${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME:=master}
+# Explicitly set the default branch name for testing, to squelch hints
+# from "git init" during the transition period.  Should be removed
+# after we decide to remove ADVICE_DEFAULT_BRANCH_NAME
+if test -z "$WITH_BREAKING_CHANGES"
+then
+	: ${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME:=master}
+else
+	: ${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME:=main}
+fi
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+
 ################################################################
 # It appears that people try to run tests without building...
 GIT_BINARY="${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X"
@@ -1917,6 +1924,19 @@
 test_lazy_prereq DEFAULT_REPO_FORMAT '
 	test_have_prereq SHA1,REFFILES
 '
+# BROKEN_OBJECTS is a test whether we can write deliberately broken objects and
+# expect them to work.  When running using SHA-256 mode with SHA-1
+# compatibility, we cannot write such objects because there's no SHA-1
+# compatibility value for a nonexistent object.
+test_lazy_prereq BROKEN_OBJECTS '
+	! test_have_prereq COMPAT_HASH
+'
+
+# COMPAT_HASH is a test if we're operating in a repository with SHA-256 with
+# SHA-1 compatibility.
+test_lazy_prereq COMPAT_HASH '
+	test -n "$test_repo_compat_hash_algo"
+'
 
 # Ensure that no test accidentally triggers a Git command
 # that runs the actual maintenance scheduler, affecting a user's
diff --git a/t/unit-tests/clar/.github/workflows/ci.yml b/t/unit-tests/clar/.github/workflows/ci.yml
index 0065843..4d47242 100644
--- a/t/unit-tests/clar/.github/workflows/ci.yml
+++ b/t/unit-tests/clar/.github/workflows/ci.yml
@@ -13,23 +13,56 @@
         platform:
           - os: ubuntu-latest
             generator: Unix Makefiles
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
+          - os: ubuntu-latest
+            generator: Unix Makefiles
+            env:
+              CC: "clang"
+              CFLAGS: "-Werror -Wall -Wextra -fsanitize=leak"
+          - os: ubuntu-latest
+            generator: Unix Makefiles
+            image: i386/debian:latest
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
           - os: macos-latest
             generator: Unix Makefiles
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
           - os: windows-latest
             generator: Visual Studio 17 2022
           - os: windows-latest
             generator: MSYS Makefiles
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
           - os: windows-latest
             generator: MinGW Makefiles
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
+      fail-fast: false
 
     runs-on: ${{ matrix.platform.os }}
+    container: ${{matrix.platform.image}}
+
+    env:
+      CC: ${{matrix.platform.env.CC}}
+      CFLAGS: ${{matrix.platform.env.CFLAGS}}
 
     steps:
+    - name: Prepare 32 bit container image
+      if: matrix.platform.image == 'i386/debian:latest'
+      run: apt -q update && apt -q -y install cmake gcc libc6-amd64 lib64stdc++6 make python3
     - name: Check out
-      uses: actions/checkout@v2
+      uses: actions/checkout@v4
     - name: Build
+      shell: bash
       run: |
         mkdir build
         cd build
         cmake .. -G "${{matrix.platform.generator}}"
-        cmake --build .
+        cmake --build . --verbose
+    - name: Test
+      shell: bash
+      run: |
+        cd build
+        CTEST_OUTPUT_ON_FAILURE=1 ctest --build-config Debug
diff --git a/t/unit-tests/clar/CMakeLists.txt b/t/unit-tests/clar/CMakeLists.txt
index 12d4af1..125db05 100644
--- a/t/unit-tests/clar/CMakeLists.txt
+++ b/t/unit-tests/clar/CMakeLists.txt
@@ -1,8 +1,15 @@
+include(CheckFunctionExists)
+
 cmake_minimum_required(VERSION 3.16..3.29)
 
 project(clar LANGUAGES C)
 
-option(BUILD_TESTS "Build test executable" ON)
+option(BUILD_EXAMPLE "Build the example." ON)
+
+check_function_exists(realpath CLAR_HAS_REALPATH)
+if(CLAR_HAS_REALPATH)
+	add_compile_definitions(-DCLAR_HAS_REALPATH)
+endif()
 
 add_library(clar INTERFACE)
 target_sources(clar INTERFACE
@@ -25,4 +32,8 @@
 	if(BUILD_TESTING)
 		add_subdirectory(test)
 	endif()
+
+	if(BUILD_EXAMPLE)
+		add_subdirectory(example)
+	endif()
 endif()
diff --git a/t/unit-tests/clar/README.md b/t/unit-tests/clar/README.md
index a8961c5..4159598 100644
--- a/t/unit-tests/clar/README.md
+++ b/t/unit-tests/clar/README.md
@@ -26,8 +26,7 @@
     ~~~~ sh
     $ mkdir tests
     $ cp -r $CLAR_ROOT/clar* tests
-    $ cp $CLAR_ROOT/test/clar_test.h tests
-    $ cp $CLAR_ROOT/test/main.c.sample tests/main.c
+    $ cp $CLAR_ROOT/example/*.c tests
     ~~~~
 
 - **One: Write some tests**
@@ -147,7 +146,7 @@
 
 1. copy the Clar boilerplate to your test directory
 2. copy (and probably modify) the sample `main.c` (from
-   `$CLAR_PATH/test/main.c.sample`)
+   `$CLAR_PATH/example/main.c`)
 3. run the Clar mixer (a.k.a. `generate.py`) to scan your test directory and
    write out the test suite metadata.
 4. compile your test files and the Clar boilerplate into a single test
@@ -159,7 +158,7 @@
 the `clar.c` and `clar.h` files, plus the code in the `clar/` subdirectory.
 You should not need to edit these files.
 
-The sample `main.c` (i.e. `$CLAR_PATH/test/main.c.sample`) file invokes
+The sample `main.c` (i.e. `$CLAR_PATH/example/main.c`) file invokes
 `clar_test(argc, argv)` to run the tests.  Usually, you will edit this file
 to perform any framework specific initialization and teardown that you need.
 
@@ -251,11 +250,16 @@
 
 -   `cl_fixture(const char *)`: Gets the full path to a fixture file.
 
-Please do note that these methods are *always* available whilst running a
-test, even when calling auxiliary/static functions inside the same file.
+### Auxiliary / helper functions
 
-It's strongly encouraged to perform test assertions in auxiliary methods,
-instead of returning error values. This is considered good Clar style.
+The clar API is always available while running a test, even when calling
+"auxiliary" (helper) functions.
+
+You're encouraged to perform test assertions in those auxiliary
+methods, instead of returning error values. This is considered good
+Clar style. _However_, when you do this, you need to call `cl_invoke`
+to preserve the current state; this ensures that failures are reported
+as coming from the actual test, instead of the auxiliary method.
 
 Style Example:
 
@@ -310,20 +314,19 @@
 
 void test_example__a_test_with_auxiliary_methods(void)
 {
-    check_string("foo");
-    check_string("bar");
+    cl_invoke(check_string("foo"));
+    cl_invoke(check_string("bar"));
 }
 ~~~~
 
 About Clar
 ==========
 
-Clar has been written from scratch by [Vicent Martí](https://github.com/vmg),
-to replace the old testing framework in [libgit2][libgit2].
-
-Do you know what languages are *in* on the SF startup scene? Node.js *and*
-Latin.  Follow [@vmg](https://www.twitter.com/vmg) on Twitter to
-receive more lessons on word etymology. You can be hip too.
-
+Clar was originally written by [Vicent Martí](https://github.com/vmg),
+to replace the old testing framework in [libgit2][libgit2]. It is
+currently maintained by [Edward Thomson](https://github.com/ethomson),
+and used by the [libgit2][libgit2] and [git][git] projects, amongst
+others.
 
 [libgit2]: https://github.com/libgit2/libgit2
+[git]: https://github.com/git/git
diff --git a/t/unit-tests/clar/clar.c b/t/unit-tests/clar/clar.c
index 03a3aa8..d6176e5 100644
--- a/t/unit-tests/clar/clar.c
+++ b/t/unit-tests/clar/clar.c
@@ -79,6 +79,8 @@
 #	else
 #		define p_snprintf snprintf
 #	endif
+
+#	define localtime_r(timer, buf) (localtime_s(buf, timer) == 0 ? buf : NULL)
 #else
 #	include <sys/wait.h> /* waitpid(2) */
 #	include <unistd.h>
@@ -150,7 +152,6 @@ static struct {
 
 	enum cl_output_format output_format;
 
-	int report_errors_only;
 	int exit_on_error;
 	int verbosity;
 
@@ -164,6 +165,10 @@ static struct {
 	struct clar_report *reports;
 	struct clar_report *last_report;
 
+	const char *invoke_file;
+	const char *invoke_func;
+	size_t invoke_line;
+
 	void (*local_cleanup)(void *);
 	void *local_cleanup_payload;
 
@@ -190,7 +195,7 @@ struct clar_suite {
 };
 
 /* From clar_print_*.c */
-static void clar_print_init(int test_count, int suite_count, const char *suite_names);
+static void clar_print_init(int test_count, int suite_count);
 static void clar_print_shutdown(int test_count, int suite_count, int error_count);
 static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error);
 static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status failed);
@@ -199,8 +204,10 @@ static void clar_print_onabortv(const char *msg, va_list argp);
 static void clar_print_onabort(const char *msg, ...);
 
 /* From clar_sandbox.c */
-static void clar_unsandbox(void);
-static void clar_sandbox(void);
+static void clar_tempdir_init(void);
+static void clar_tempdir_shutdown(void);
+static int clar_sandbox_create(const char *suite_name, const char *test_name);
+static int clar_sandbox_cleanup(void);
 
 /* From summary.h */
 static struct clar_summary *clar_summary_init(const char *filename);
@@ -304,6 +311,8 @@ clar_run_test(
 
 	CL_TRACE(CL_TRACE__TEST__BEGIN);
 
+	clar_sandbox_create(suite->name, test->name);
+
 	_clar.last_report->start = time(NULL);
 	clar_time_now(&start);
 
@@ -328,9 +337,13 @@ clar_run_test(
 	if (_clar.local_cleanup != NULL)
 		_clar.local_cleanup(_clar.local_cleanup_payload);
 
+	clar__clear_invokepoint();
+
 	if (cleanup->ptr != NULL)
 		cleanup->ptr();
 
+	clar_sandbox_cleanup();
+
 	CL_TRACE(CL_TRACE__TEST__END);
 
 	_clar.tests_ran++;
@@ -339,11 +352,7 @@ clar_run_test(
 	_clar.local_cleanup = NULL;
 	_clar.local_cleanup_payload = NULL;
 
-	if (_clar.report_errors_only) {
-		clar_report_errors(_clar.last_report);
-	} else {
-		clar_print_ontest(suite->name, test->name, _clar.tests_ran, _clar.last_report->status);
-	}
+	clar_print_ontest(suite->name, test->name, _clar.tests_ran, _clar.last_report->status);
 }
 
 static void
@@ -360,8 +369,7 @@ clar_run_suite(const struct clar_suite *suite, const char *filter)
 	if (_clar.exit_on_error && _clar.total_errors)
 		return;
 
-	if (!_clar.report_errors_only)
-		clar_print_onsuite(suite->name, ++_clar.suites_ran);
+	clar_print_onsuite(suite->name, ++_clar.suites_ran);
 
 	_clar.active_suite = suite->name;
 	_clar.active_test = NULL;
@@ -428,12 +436,12 @@ clar_usage(const char *arg)
 	printf("  -iname        Include the suite with `name`\n");
 	printf("  -xname        Exclude the suite with `name`\n");
 	printf("  -v            Increase verbosity (show suite names)\n");
-	printf("  -q            Only report tests that had an error\n");
+	printf("  -q            Decrease verbosity, inverse to -v\n");
 	printf("  -Q            Quit as soon as a test fails\n");
 	printf("  -t            Display results in tap format\n");
 	printf("  -l            Print suite names\n");
 	printf("  -r[filename]  Write summary file (to the optional filename)\n");
-	exit(-1);
+	exit(1);
 }
 
 static void
@@ -441,18 +449,11 @@ clar_parse_args(int argc, char **argv)
 {
 	int i;
 
-	/* Verify options before execute */
 	for (i = 1; i < argc; ++i) {
 		char *argument = argv[i];
 
-		if (argument[0] != '-' || argument[1] == '\0'
-		    || strchr("sixvqQtlr", argument[1]) == NULL) {
+		if (argument[0] != '-' || argument[1] == '\0')
 			clar_usage(argv[0]);
-		}
-	}
-
-	for (i = 1; i < argc; ++i) {
-		char *argument = argv[i];
 
 		switch (argument[1]) {
 		case 's':
@@ -465,8 +466,13 @@ clar_parse_args(int argc, char **argv)
 			argument += offset;
 			arglen = strlen(argument);
 
-			if (arglen == 0)
-				clar_usage(argv[0]);
+			if (arglen == 0) {
+				if (i + 1 == argc)
+					clar_usage(argv[0]);
+
+				argument = argv[++i];
+				arglen = strlen(argument);
+			}
 
 			for (j = 0; j < _clar_suite_count; ++j) {
 				suitelen = strlen(_clar_suites[j].name);
@@ -483,9 +489,6 @@ clar_parse_args(int argc, char **argv)
 
 					++found;
 
-					if (!exact)
-						_clar.verbosity = MAX(_clar.verbosity, 1);
-
 					switch (action) {
 					case 's': {
 						struct clar_explicit *explicit;
@@ -517,23 +520,37 @@ clar_parse_args(int argc, char **argv)
 
 			if (!found)
 				clar_abort("No suite matching '%s' found.\n", argument);
+
 			break;
 		}
 
 		case 'q':
-			_clar.report_errors_only = 1;
+			if (argument[2] != '\0')
+				clar_usage(argv[0]);
+
+			_clar.verbosity--;
 			break;
 
 		case 'Q':
+			if (argument[2] != '\0')
+				clar_usage(argv[0]);
+
 			_clar.exit_on_error = 1;
 			break;
 
 		case 't':
+			if (argument[2] != '\0')
+				clar_usage(argv[0]);
+
 			_clar.output_format = CL_OUTPUT_TAP;
 			break;
 
 		case 'l': {
 			size_t j;
+
+			if (argument[2] != '\0')
+				clar_usage(argv[0]);
+
 			printf("Test suites (use -s<name> to run just one):\n");
 			for (j = 0; j < _clar_suite_count; ++j)
 				printf(" %3d: %s\n", (int)j, _clar_suites[j].name);
@@ -542,23 +559,27 @@ clar_parse_args(int argc, char **argv)
 		}
 
 		case 'v':
+			if (argument[2] != '\0')
+				clar_usage(argv[0]);
+
 			_clar.verbosity++;
 			break;
 
 		case 'r':
 			_clar.write_summary = 1;
 			free(_clar.summary_filename);
+
 			if (*(argument + 2)) {
 				if ((_clar.summary_filename = strdup(argument + 2)) == NULL)
 					clar_abort("Failed to allocate summary filename.\n");
 			} else {
 				_clar.summary_filename = NULL;
 			}
+
 			break;
 
 		default:
-			clar_abort("Unexpected commandline argument '%s'.\n",
-				   argument[1]);
+			clar_usage(argv[0]);
 		}
 	}
 }
@@ -571,11 +592,7 @@ clar_test_init(int argc, char **argv)
 	if (argc > 1)
 		clar_parse_args(argc, argv);
 
-	clar_print_init(
-		(int)_clar_callback_count,
-		(int)_clar_suite_count,
-		""
-	);
+	clar_print_init((int)_clar_callback_count, (int)_clar_suite_count);
 
 	if (!_clar.summary_filename &&
 	    (summary_env = getenv("CLAR_SUMMARY")) != NULL) {
@@ -591,7 +608,7 @@ clar_test_init(int argc, char **argv)
 	if (_clar.write_summary)
 	    _clar.summary = clar_summary_init(_clar.summary_filename);
 
-	clar_sandbox();
+	clar_tempdir_init();
 }
 
 int
@@ -623,7 +640,7 @@ clar_test_shutdown(void)
 		_clar.total_errors
 	);
 
-	clar_unsandbox();
+	clar_tempdir_shutdown();
 
 	if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0)
 		clar_abort("Failed to write the summary file '%s: %s.\n",
@@ -635,6 +652,14 @@ clar_test_shutdown(void)
 	}
 
 	for (report = _clar.reports; report; report = report_next) {
+		struct clar_error *error, *error_next;
+
+		for (error = report->errors; error; error = error_next) {
+			free(error->description);
+			error_next = error->next;
+			free(error);
+		}
+
 		report_next = report->next;
 		free(report);
 	}
@@ -660,7 +685,7 @@ static void abort_test(void)
 		clar_print_onabort(
 				"Fatal error: a cleanup method raised an exception.\n");
 		clar_report_errors(_clar.last_report);
-		exit(-1);
+		exit(1);
 	}
 
 	CL_TRACE(CL_TRACE__TEST__LONGJMP);
@@ -695,9 +720,9 @@ void clar__fail(
 
 	_clar.last_report->last_error = error;
 
-	error->file = file;
-	error->function = function;
-	error->line_number = line;
+	error->file = _clar.invoke_file ? _clar.invoke_file : file;
+	error->function = _clar.invoke_func ? _clar.invoke_func : function;
+	error->line_number = _clar.invoke_line ? _clar.invoke_line : line;
 	error->error_msg = error_msg;
 
 	if (description != NULL &&
@@ -754,7 +779,12 @@ void clar__assert_equal(
 				p_snprintf(buf, sizeof(buf), "'%s' != '%s' (at byte %d)",
 					s1, s2, pos);
 			} else {
-				p_snprintf(buf, sizeof(buf), "'%s' != '%s'", s1, s2);
+				const char *q1 = s1 ? "'" : "";
+				const char *q2 = s2 ? "'" : "";
+				s1 = s1 ? s1 : "NULL";
+				s2 = s2 ? s2 : "NULL";
+				p_snprintf(buf, sizeof(buf), "%s%s%s != %s%s%s",
+					   q1, s1, q1, q2, s2, q2);
 			}
 		}
 	}
@@ -767,12 +797,17 @@ void clar__assert_equal(
 		if (!is_equal) {
 			if (s1 && s2) {
 				int pos;
-				for (pos = 0; s1[pos] == s2[pos] && pos < len; ++pos)
+				for (pos = 0; pos < len && s1[pos] == s2[pos]; ++pos)
 					/* find differing byte offset */;
 				p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s' (at byte %d)",
 					len, s1, len, s2, pos);
 			} else {
-				p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s'", len, s1, len, s2);
+				const char *q1 = s1 ? "'" : "";
+				const char *q2 = s2 ? "'" : "";
+				s1 = s1 ? s1 : "NULL";
+				s2 = s2 ? s2 : "NULL";
+				p_snprintf(buf, sizeof(buf), "%s%.*s%s != %s%.*s%s",
+					   q1, len, s1, q1, q2, len, s2, q2);
 			}
 		}
 	}
@@ -790,7 +825,12 @@ void clar__assert_equal(
 				p_snprintf(buf, sizeof(buf), "'%ls' != '%ls' (at byte %d)",
 					wcs1, wcs2, pos);
 			} else {
-				p_snprintf(buf, sizeof(buf), "'%ls' != '%ls'", wcs1, wcs2);
+				const char *q1 = wcs1 ? "'" : "";
+				const char *q2 = wcs2 ? "'" : "";
+				wcs1 = wcs1 ? wcs1 : L"NULL";
+				wcs2 = wcs2 ? wcs2 : L"NULL";
+				p_snprintf(buf, sizeof(buf), "%s%ls%s != %s%ls%s",
+					   q1, wcs1, q1, q2, wcs2, q2);
 			}
 		}
 	}
@@ -803,12 +843,17 @@ void clar__assert_equal(
 		if (!is_equal) {
 			if (wcs1 && wcs2) {
 				int pos;
-				for (pos = 0; wcs1[pos] == wcs2[pos] && pos < len; ++pos)
+				for (pos = 0; pos < len && wcs1[pos] == wcs2[pos]; ++pos)
 					/* find differing byte offset */;
 				p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls' (at byte %d)",
 					len, wcs1, len, wcs2, pos);
 			} else {
-				p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls'", len, wcs1, len, wcs2);
+				const char *q1 = wcs1 ? "'" : "";
+				const char *q2 = wcs2 ? "'" : "";
+				wcs1 = wcs1 ? wcs1 : L"NULL";
+				wcs2 = wcs2 ? wcs2 : L"NULL";
+				p_snprintf(buf, sizeof(buf), "%s%.*ls%s != %s%.*ls%s",
+					   q1, len, wcs1, q1, q2, len, wcs2, q2);
 			}
 		}
 	}
@@ -850,6 +895,23 @@ void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
 	_clar.local_cleanup_payload = opaque;
 }
 
+void clar__set_invokepoint(
+	const char *file,
+	const char *func,
+	size_t line)
+{
+	_clar.invoke_file = file;
+	_clar.invoke_func = func;
+	_clar.invoke_line = line;
+}
+
+void clar__clear_invokepoint(void)
+{
+	_clar.invoke_file = NULL;
+	_clar.invoke_func = NULL;
+	_clar.invoke_line = 0;
+}
+
 #include "clar/sandbox.h"
 #include "clar/fixtures.h"
 #include "clar/fs.h"
diff --git a/t/unit-tests/clar/clar.h b/t/unit-tests/clar/clar.h
index 8c22382..ca72292 100644
--- a/t/unit-tests/clar/clar.h
+++ b/t/unit-tests/clar/clar.h
@@ -8,6 +8,25 @@
 #define __CLAR_TEST_H__
 
 #include <stdlib.h>
+#include <limits.h>
+
+#if defined(_WIN32) && defined(CLAR_WIN32_LONGPATHS)
+# define CLAR_MAX_PATH 4096
+#elif defined(_WIN32)
+# define CLAR_MAX_PATH MAX_PATH
+#else
+# define CLAR_MAX_PATH PATH_MAX
+#endif
+
+#ifndef CLAR_SELFTEST
+# define CLAR_CURRENT_FILE __FILE__
+# define CLAR_CURRENT_LINE __LINE__
+# define CLAR_CURRENT_FUNC __func__
+#else
+# define CLAR_CURRENT_FILE "file"
+# define CLAR_CURRENT_LINE 42
+# define CLAR_CURRENT_FUNC "func"
+#endif
 
 enum cl_test_status {
 	CL_TEST_OK,
@@ -30,6 +49,7 @@ void clar_test_shutdown(void);
 int clar_test(int argc, char *argv[]);
 
 const char *clar_sandbox_path(void);
+const char *clar_tempdir_path(void);
 
 void cl_set_cleanup(void (*cleanup)(void *), void *opaque);
 void cl_fs_cleanup(void);
@@ -84,18 +104,32 @@ const char *cl_fixture_basename(const char *fixture_name);
 #endif
 
 /**
+ * Invoke a helper function, which itself will use `cl_assert`
+ * constructs. This will preserve the stack information of the
+ * current call point, so that function name and line number
+ * information is shown from the line of the test, instead of
+ * the helper function.
+ */
+#define cl_invoke(expr) \
+	do { \
+		clar__set_invokepoint(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE); \
+		expr; \
+		clar__clear_invokepoint(); \
+	} while(0)
+
+/**
  * Assertion macros with explicit error message
  */
-#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 1)
-#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 1)
-#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 1)
+#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Function call failed: " #expr, desc, 1)
+#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expected function call to fail: " #expr, desc, 1)
+#define cl_assert_(expr, desc) clar__assert((expr) != 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expression is not true: " #expr, desc, 1)
 
 /**
  * Check macros with explicit error message
  */
-#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 0)
-#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 0)
-#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 0)
+#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Function call failed: " #expr, desc, 0)
+#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expected function call to fail: " #expr, desc, 0)
+#define cl_check_(expr, desc) clar__assert((expr) != 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expression is not true: " #expr, desc, 0)
 
 /**
  * Assertion macros with no error message
@@ -114,33 +148,33 @@ const char *cl_fixture_basename(const char *fixture_name);
 /**
  * Forced failure/warning
  */
-#define cl_fail(desc) clar__fail(__FILE__, __func__, __LINE__, "Test failed.", desc, 1)
-#define cl_warning(desc) clar__fail(__FILE__, __func__, __LINE__, "Warning during test execution:", desc, 0)
+#define cl_fail(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Test failed.", desc, 1)
+#define cl_warning(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Warning during test execution:", desc, 0)
 
 #define cl_skip() clar__skip()
 
 /**
  * Typed assertion macros
  */
-#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2))
-#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2))
+#define cl_assert_equal_s(s1,s2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2))
+#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2))
 
-#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2))
-#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2))
+#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2))
+#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2))
 
-#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len))
-#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len))
+#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len))
+#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len))
 
-#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len))
-#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len))
+#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len))
+#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len))
 
-#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2))
-#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2))
-#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2))
+#define cl_assert_equal_i(i1,i2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2))
+#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2))
+#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2))
 
-#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__func__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0))
+#define cl_assert_equal_b(b1,b2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0))
 
-#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__func__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2))
+#define cl_assert_equal_p(p1,p2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2))
 
 void clar__skip(void);
 
@@ -170,4 +204,11 @@ void clar__assert_equal(
 	const char *fmt,
 	...);
 
+void clar__set_invokepoint(
+	const char *file,
+	const char *func,
+	size_t line);
+
+void clar__clear_invokepoint(void);
+
 #endif
diff --git a/t/unit-tests/clar/clar/fixtures.h b/t/unit-tests/clar/clar/fixtures.h
index 6ec6423..9f1023d 100644
--- a/t/unit-tests/clar/clar/fixtures.h
+++ b/t/unit-tests/clar/clar/fixtures.h
@@ -2,7 +2,7 @@
 static const char *
 fixture_path(const char *base, const char *fixture_name)
 {
-	static char _path[4096];
+	static char _path[CLAR_MAX_PATH];
 	size_t root_len;
 
 	root_len = strlen(base);
@@ -28,7 +28,7 @@ const char *cl_fixture(const char *fixture_name)
 
 void cl_fixture_sandbox(const char *fixture_name)
 {
-	fs_copy(cl_fixture(fixture_name), _clar_path);
+	fs_copy(cl_fixture(fixture_name), clar_sandbox_path());
 }
 
 const char *cl_fixture_basename(const char *fixture_name)
@@ -45,6 +45,6 @@ const char *cl_fixture_basename(const char *fixture_name)
 
 void cl_fixture_cleanup(const char *fixture_name)
 {
-	fs_rm(fixture_path(_clar_path, cl_fixture_basename(fixture_name)));
+	fs_rm(fixture_path(clar_sandbox_path(), cl_fixture_basename(fixture_name)));
 }
 #endif
diff --git a/t/unit-tests/clar/clar/fs.h b/t/unit-tests/clar/clar/fs.h
index 2203743..f1311d9 100644
--- a/t/unit-tests/clar/clar/fs.h
+++ b/t/unit-tests/clar/clar/fs.h
@@ -8,12 +8,6 @@
 
 #ifdef _WIN32
 
-#ifdef CLAR_WIN32_LONGPATHS
-# define CLAR_MAX_PATH 4096
-#else
-# define CLAR_MAX_PATH MAX_PATH
-#endif
-
 #define RM_RETRY_COUNT	5
 #define RM_RETRY_DELAY	10
 
@@ -296,7 +290,7 @@ void
 cl_fs_cleanup(void)
 {
 #ifdef CLAR_FIXTURE_PATH
-	fs_rm(fixture_path(_clar_path, "*"));
+	fs_rm(fixture_path(clar_tempdir_path(), "*"));
 #else
 	((void)fs_copy); /* unused */
 #endif
@@ -371,17 +365,19 @@ static void
 fs_copydir_helper(const char *source, const char *dest, int dest_mode)
 {
 	DIR *source_dir;
-	struct dirent *d;
 
 	mkdir(dest, dest_mode);
 
 	cl_assert_(source_dir = opendir(source), "Could not open source dir");
-	for (;;) {
+	while (1) {
+		struct dirent *d;
 		char *child;
 
 		errno = 0;
-		if ((d = readdir(source_dir)) == NULL)
+		d = readdir(source_dir);
+		if (!d)
 			break;
+
 		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
 			continue;
 
@@ -479,15 +475,18 @@ static void
 fs_rmdir_helper(const char *path)
 {
 	DIR *dir;
-	struct dirent *d;
 
 	cl_assert_(dir = opendir(path), "Could not open dir");
-	for (;;) {
+
+	while (1) {
+		struct dirent *d;
 		char *child;
 
 		errno = 0;
-		if ((d = readdir(dir)) == NULL)
+		d = readdir(dir);
+		if (!d)
 			break;
+
 		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
 			continue;
 
@@ -524,7 +523,7 @@ fs_rm(const char *path)
 void
 cl_fs_cleanup(void)
 {
-	clar_unsandbox();
-	clar_sandbox();
+	clar_tempdir_shutdown();
+	clar_tempdir_init();
 }
 #endif
diff --git a/t/unit-tests/clar/clar/print.h b/t/unit-tests/clar/clar/print.h
index 69d0ee9..89b6659 100644
--- a/t/unit-tests/clar/clar/print.h
+++ b/t/unit-tests/clar/clar/print.h
@@ -1,9 +1,13 @@
 /* clap: clar protocol, the traditional clar output format */
 
-static void clar_print_clap_init(int test_count, int suite_count, const char *suite_names)
+static void clar_print_clap_init(int test_count, int suite_count)
 {
 	(void)test_count;
-	printf("Loaded %d suites: %s\n", (int)suite_count, suite_names);
+
+	if (_clar.verbosity < 0)
+		return;
+
+	printf("Loaded %d suites:\n", (int)suite_count);
 	printf("Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')\n");
 }
 
@@ -13,10 +17,27 @@ static void clar_print_clap_shutdown(int test_count, int suite_count, int error_
 	(void)suite_count;
 	(void)error_count;
 
-	printf("\n\n");
+	if (_clar.verbosity >= 0)
+		printf("\n\n");
 	clar_report_all();
 }
 
+
+static void clar_print_indented(const char *str, int indent)
+{
+	const char *bol, *eol;
+
+	for (bol = str; *bol; bol = eol) {
+		eol = strchr(bol, '\n');
+		if (eol)
+			eol++;
+		else
+			eol = bol + strlen(bol);
+		printf("%*s%.*s", indent, "", (int)(eol - bol), bol);
+	}
+	putc('\n', stdout);
+}
+
 static void clar_print_clap_error(int num, const struct clar_report *report, const struct clar_error *error)
 {
 	printf("  %d) Failure:\n", num);
@@ -27,10 +48,10 @@ static void clar_print_clap_error(int num, const struct clar_report *report, con
 		error->file,
 		error->line_number);
 
-	printf("  %s\n", error->error_msg);
+	clar_print_indented(error->error_msg, 2);
 
 	if (error->description != NULL)
-		printf("  %s\n", error->description);
+		clar_print_indented(error->description, 2);
 
 	printf("\n");
 	fflush(stdout);
@@ -41,14 +62,17 @@ static void clar_print_clap_ontest(const char *suite_name, const char *test_name
 	(void)test_name;
 	(void)test_number;
 
+	if (_clar.verbosity < 0)
+		return;
+
 	if (_clar.verbosity > 1) {
 		printf("%s::%s: ", suite_name, test_name);
 
 		switch (status) {
 		case CL_TEST_OK: printf("ok\n"); break;
 		case CL_TEST_FAILURE: printf("fail\n"); break;
-		case CL_TEST_SKIP: printf("skipped"); break;
-		case CL_TEST_NOTRUN: printf("notrun"); break;
+		case CL_TEST_SKIP: printf("skipped\n"); break;
+		case CL_TEST_NOTRUN: printf("notrun\n"); break;
 		}
 	} else {
 		switch (status) {
@@ -64,6 +88,8 @@ static void clar_print_clap_ontest(const char *suite_name, const char *test_name
 
 static void clar_print_clap_onsuite(const char *suite_name, int suite_index)
 {
+	if (_clar.verbosity < 0)
+		return;
 	if (_clar.verbosity == 1)
 		printf("\n%s", suite_name);
 
@@ -77,11 +103,10 @@ static void clar_print_clap_onabort(const char *fmt, va_list arg)
 
 /* tap: test anywhere protocol format */
 
-static void clar_print_tap_init(int test_count, int suite_count, const char *suite_names)
+static void clar_print_tap_init(int test_count, int suite_count)
 {
 	(void)test_count;
 	(void)suite_count;
-	(void)suite_names;
 	printf("TAP version 13\n");
 }
 
@@ -127,18 +152,20 @@ static void clar_print_tap_ontest(const char *suite_name, const char *test_name,
 	case CL_TEST_FAILURE:
 		printf("not ok %d - %s::%s\n", test_number, suite_name, test_name);
 
-		printf("    ---\n");
-		printf("    reason: |\n");
-		printf("      %s\n", error->error_msg);
+		if (_clar.verbosity >= 0) {
+			printf("    ---\n");
+			printf("    reason: |\n");
+			clar_print_indented(error->error_msg, 6);
 
-		if (error->description)
-			printf("      %s\n", error->description);
+			if (error->description)
+				clar_print_indented(error->description, 6);
 
-		printf("    at:\n");
-		printf("      file: '"); print_escaped(error->file); printf("'\n");
-		printf("      line: %" PRIuMAX "\n", error->line_number);
-		printf("      function: '%s'\n", error->function);
-		printf("    ---\n");
+			printf("    at:\n");
+			printf("      file: '"); print_escaped(error->file); printf("'\n");
+			printf("      line: %" PRIuMAX "\n", error->line_number);
+			printf("      function: '%s'\n", error->function);
+			printf("    ---\n");
+		}
 
 		break;
 	case CL_TEST_SKIP:
@@ -152,6 +179,8 @@ static void clar_print_tap_ontest(const char *suite_name, const char *test_name,
 
 static void clar_print_tap_onsuite(const char *suite_name, int suite_index)
 {
+	if (_clar.verbosity < 0)
+		return;
 	printf("# start of suite %d: %s\n", suite_index, suite_name);
 }
 
@@ -177,9 +206,9 @@ static void clar_print_tap_onabort(const char *fmt, va_list arg)
 		} \
 	} while (0)
 
-static void clar_print_init(int test_count, int suite_count, const char *suite_names)
+static void clar_print_init(int test_count, int suite_count)
 {
-	PRINT(init, test_count, suite_count, suite_names);
+	PRINT(init, test_count, suite_count);
 }
 
 static void clar_print_shutdown(int test_count, int suite_count, int error_count)
diff --git a/t/unit-tests/clar/clar/sandbox.h b/t/unit-tests/clar/clar/sandbox.h
index bc960f5..52add8a 100644
--- a/t/unit-tests/clar/clar/sandbox.h
+++ b/t/unit-tests/clar/clar/sandbox.h
@@ -2,7 +2,17 @@
 #include <sys/syslimits.h>
 #endif
 
-static char _clar_path[4096 + 1];
+/*
+ * The tempdir is the temporary directory for the entirety of the clar
+ * process execution. The sandbox is an individual temporary directory
+ * for the execution of an individual test. Sandboxes are deleted
+ * entirely after test execution to avoid pollution across tests.
+ */
+
+static char _clar_tempdir[CLAR_MAX_PATH];
+static size_t _clar_tempdir_len;
+
+static char _clar_sandbox[CLAR_MAX_PATH];
 
 static int
 is_valid_tmp_path(const char *path)
@@ -15,7 +25,10 @@ is_valid_tmp_path(const char *path)
 	if (!S_ISDIR(st.st_mode))
 		return 0;
 
-	return (access(path, W_OK) == 0);
+	if (access(path, W_OK) != 0)
+		return 0;
+
+	return (strlen(path) < CLAR_MAX_PATH);
 }
 
 static int
@@ -31,14 +44,11 @@ find_tmp_path(char *buffer, size_t length)
 
 	for (i = 0; i < var_count; ++i) {
 		const char *env = getenv(env_vars[i]);
+
 		if (!env)
 			continue;
 
 		if (is_valid_tmp_path(env)) {
-#ifdef __APPLE__
-			if (length >= PATH_MAX && realpath(env, buffer) != NULL)
-				return 0;
-#endif
 			strncpy(buffer, env, length - 1);
 			buffer[length - 1] = '\0';
 			return 0;
@@ -47,21 +57,18 @@ find_tmp_path(char *buffer, size_t length)
 
 	/* If the environment doesn't say anything, try to use /tmp */
 	if (is_valid_tmp_path("/tmp")) {
-#ifdef __APPLE__
-		if (length >= PATH_MAX && realpath("/tmp", buffer) != NULL)
-			return 0;
-#endif
 		strncpy(buffer, "/tmp", length - 1);
 		buffer[length - 1] = '\0';
 		return 0;
 	}
 
 #else
-	DWORD env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length);
-	if (env_len > 0 && env_len < (DWORD)length)
+	DWORD len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length);
+	if (len > 0 && len < (DWORD)length)
 		return 0;
 
-	if (GetTempPath((DWORD)length, buffer))
+	len = GetTempPath((DWORD)length, buffer);
+	if (len > 0 && len < (DWORD)length)
 		return 0;
 #endif
 
@@ -75,17 +82,53 @@ find_tmp_path(char *buffer, size_t length)
 	return -1;
 }
 
-static void clar_unsandbox(void)
+static int canonicalize_tmp_path(char *buffer)
 {
-	if (_clar_path[0] == '\0')
+#ifdef _WIN32
+	char tmp[CLAR_MAX_PATH], *p;
+	DWORD ret;
+
+	ret = GetFullPathName(buffer, CLAR_MAX_PATH, tmp, NULL);
+
+	if (ret == 0 || ret > CLAR_MAX_PATH)
+		return -1;
+
+	ret = GetLongPathName(tmp, buffer, CLAR_MAX_PATH);
+
+	if (ret == 0 || ret > CLAR_MAX_PATH)
+		return -1;
+
+	/* normalize path to POSIX forward slashes */
+	for (p = buffer; *p; p++)
+		if (*p == '\\')
+			*p = '/';
+
+	return 0;
+#elif defined(CLAR_HAS_REALPATH)
+	char tmp[CLAR_MAX_PATH];
+
+	if (realpath(buffer, tmp) == NULL)
+		return -1;
+
+	strcpy(buffer, tmp);
+	return 0;
+#else
+	(void)buffer;
+	return 0;
+#endif
+}
+
+static void clar_tempdir_shutdown(void)
+{
+	if (_clar_tempdir[0] == '\0')
 		return;
 
 	cl_must_pass(chdir(".."));
 
-	fs_rm(_clar_path);
+	fs_rm(_clar_tempdir);
 }
 
-static int build_sandbox_path(void)
+static int build_tempdir_path(void)
 {
 #ifdef CLAR_TMPDIR
 	const char path_tail[] = CLAR_TMPDIR "_XXXXXX";
@@ -95,64 +138,153 @@ static int build_sandbox_path(void)
 
 	size_t len;
 
-	if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0)
+	if (find_tmp_path(_clar_tempdir, sizeof(_clar_tempdir)) < 0 ||
+	    canonicalize_tmp_path(_clar_tempdir) < 0)
 		return -1;
 
-	len = strlen(_clar_path);
+	len = strlen(_clar_tempdir);
 
-#ifdef _WIN32
-	{ /* normalize path to POSIX forward slashes */
-		size_t i;
-		for (i = 0; i < len; ++i) {
-			if (_clar_path[i] == '\\')
-				_clar_path[i] = '/';
-		}
-	}
-#endif
+	if (len + strlen(path_tail) + 2 > CLAR_MAX_PATH)
+		return -1;
 
-	if (_clar_path[len - 1] != '/') {
-		_clar_path[len++] = '/';
-	}
+	if (_clar_tempdir[len - 1] != '/')
+		_clar_tempdir[len++] = '/';
 
-	strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len);
+	strncpy(_clar_tempdir + len, path_tail, sizeof(_clar_tempdir) - len);
 
 #if defined(__MINGW32__)
-	if (_mktemp(_clar_path) == NULL)
+	if (_mktemp(_clar_tempdir) == NULL)
 		return -1;
 
-	if (mkdir(_clar_path, 0700) != 0)
+	if (mkdir(_clar_tempdir, 0700) != 0)
 		return -1;
 #elif defined(_WIN32)
-	if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0)
+	if (_mktemp_s(_clar_tempdir, sizeof(_clar_tempdir)) != 0)
 		return -1;
 
-	if (mkdir(_clar_path, 0700) != 0)
+	if (mkdir(_clar_tempdir, 0700) != 0)
 		return -1;
-#elif defined(__sun) || defined(__TANDEM)
-	if (mktemp(_clar_path) == NULL)
+#elif defined(__sun) || defined(__TANDEM) || defined(__hpux)
+	if (mktemp(_clar_tempdir) == NULL)
 		return -1;
 
-	if (mkdir(_clar_path, 0700) != 0)
+	if (mkdir(_clar_tempdir, 0700) != 0)
 		return -1;
 #else
-	if (mkdtemp(_clar_path) == NULL)
+	if (mkdtemp(_clar_tempdir) == NULL)
 		return -1;
 #endif
 
+	_clar_tempdir_len = strlen(_clar_tempdir);
+	return 0;
+}
+
+static void clar_tempdir_init(void)
+{
+	if (_clar_tempdir[0] == '\0' && build_tempdir_path() < 0)
+		clar_abort("Failed to build tempdir path.\n");
+
+	if (chdir(_clar_tempdir) != 0)
+		clar_abort("Failed to change into tempdir '%s': %s.\n",
+			   _clar_tempdir, strerror(errno));
+
+#if !defined(CLAR_SANDBOX_TEST_NAMES) && defined(_WIN32)
+	srand(clock() ^ (unsigned int)time(NULL) ^ GetCurrentProcessId() ^ GetCurrentThreadId());
+#elif !defined(CLAR_SANDBOX_TEST_NAMES)
+	srand(clock() ^ time(NULL) ^ ((unsigned)getpid() << 16));
+#endif
+}
+
+static void append(char *dst, const char *src)
+{
+	char *d;
+	const char *s;
+
+	for (d = dst; *d; d++)
+		;
+
+	for (s = src; *s; d++, s++)
+		if (*s == ':')
+			*d = '_';
+		else
+			*d = *s;
+
+	*d = '\0';
+}
+
+static int clar_sandbox_create(const char *suite_name, const char *test_name)
+{
+#ifndef CLAR_SANDBOX_TEST_NAMES
+	char alpha[] = "0123456789abcdef";
+	int num = rand();
+#endif
+
+	cl_assert(_clar_sandbox[0] == '\0');
+
+	/*
+	 * We may want to use test names as sandbox directory names for
+	 * readability, _however_ on platforms with restrictions for short
+	 * file / folder names (eg, Windows), this may be too long.
+	 */
+#ifdef CLAR_SANDBOX_TEST_NAMES
+	cl_assert(strlen(_clar_tempdir) + strlen(suite_name) + strlen(test_name) + 3 < CLAR_MAX_PATH);
+
+	strcpy(_clar_sandbox, _clar_tempdir);
+	_clar_sandbox[_clar_tempdir_len] = '/';
+	_clar_sandbox[_clar_tempdir_len + 1] = '\0';
+
+	append(_clar_sandbox, suite_name);
+	append(_clar_sandbox, "__");
+	append(_clar_sandbox, test_name);
+#else
+	((void)suite_name);
+	((void)test_name);
+	((void)append);
+
+	cl_assert(strlen(_clar_tempdir) + 9 < CLAR_MAX_PATH);
+
+	strcpy(_clar_sandbox, _clar_tempdir);
+	_clar_sandbox[_clar_tempdir_len] = '/';
+
+	_clar_sandbox[_clar_tempdir_len + 1] = alpha[(num & 0xf0000000) >> 28];
+	_clar_sandbox[_clar_tempdir_len + 2] = alpha[(num & 0x0f000000) >> 24];
+	_clar_sandbox[_clar_tempdir_len + 3] = alpha[(num & 0x00f00000) >> 20];
+	_clar_sandbox[_clar_tempdir_len + 4] = alpha[(num & 0x000f0000) >> 16];
+	_clar_sandbox[_clar_tempdir_len + 5] = alpha[(num & 0x0000f000) >> 12];
+	_clar_sandbox[_clar_tempdir_len + 6] = alpha[(num & 0x00000f00) >> 8];
+	_clar_sandbox[_clar_tempdir_len + 7] = alpha[(num & 0x000000f0) >> 4];
+	_clar_sandbox[_clar_tempdir_len + 8] = alpha[(num & 0x0000000f) >> 0];
+	_clar_sandbox[_clar_tempdir_len + 9] = '\0';
+#endif
+
+	if (mkdir(_clar_sandbox, 0700) != 0)
+		return -1;
+
+	if (chdir(_clar_sandbox) != 0)
+		return -1;
+
 	return 0;
 }
 
-static void clar_sandbox(void)
+static int clar_sandbox_cleanup(void)
 {
-	if (_clar_path[0] == '\0' && build_sandbox_path() < 0)
-		clar_abort("Failed to build sandbox path.\n");
+	cl_assert(_clar_sandbox[0] != '\0');
 
-	if (chdir(_clar_path) != 0)
-		clar_abort("Failed to change into sandbox directory '%s': %s.\n",
-			   _clar_path, strerror(errno));
+	if (chdir(_clar_tempdir) != 0)
+		return -1;
+
+	fs_rm(_clar_sandbox);
+	_clar_sandbox[0] = '\0';
+
+	return 0;
+}
+
+const char *clar_tempdir_path(void)
+{
+	return _clar_tempdir;
 }
 
 const char *clar_sandbox_path(void)
 {
-	return _clar_path;
+	return _clar_sandbox;
 }
diff --git a/t/unit-tests/clar/clar/summary.h b/t/unit-tests/clar/clar/summary.h
index 0d0b646..7b85f16 100644
--- a/t/unit-tests/clar/clar/summary.h
+++ b/t/unit-tests/clar/clar/summary.h
@@ -23,10 +23,11 @@ static int clar_summary_testsuite(struct clar_summary *summary,
     int idn, const char *name, time_t timestamp,
     int test_count, int fail_count, int error_count)
 {
-	struct tm *tm = localtime(&timestamp);
+	struct tm tm;
 	char iso_dt[20];
 
-	if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0)
+	localtime_r(&timestamp, &tm);
+	if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", &tm) == 0)
 		return -1;
 
 	return fprintf(summary->fp, "\t<testsuite"
diff --git a/t/unit-tests/clar/example/CMakeLists.txt b/t/unit-tests/clar/example/CMakeLists.txt
new file mode 100644
index 0000000..b72f187
--- /dev/null
+++ b/t/unit-tests/clar/example/CMakeLists.txt
@@ -0,0 +1,28 @@
+find_package(Python COMPONENTS Interpreter REQUIRED)
+
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
+	COMMAND "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/generate.py" --output "${CMAKE_CURRENT_BINARY_DIR}"
+	DEPENDS main.c example.c
+	WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+)
+
+add_executable(example)
+set_target_properties(example PROPERTIES
+	C_STANDARD 90
+	C_STANDARD_REQUIRED ON
+	C_EXTENSIONS OFF
+)
+target_sources(example PRIVATE
+	main.c
+	example.c
+	"${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
+)
+target_compile_definitions(example PRIVATE)
+target_compile_options(example PRIVATE
+	$<IF:$<CXX_COMPILER_ID:MSVC>,/W4,-Wall>
+)
+target_include_directories(example PRIVATE
+	"${CMAKE_SOURCE_DIR}"
+	"${CMAKE_CURRENT_BINARY_DIR}"
+)
+target_link_libraries(example clar)
diff --git a/t/unit-tests/clar/example/example.c b/t/unit-tests/clar/example/example.c
new file mode 100644
index 0000000..c07d6bf
--- /dev/null
+++ b/t/unit-tests/clar/example/example.c
@@ -0,0 +1,6 @@
+#include "clar.h"
+
+void test_example__simple_assert(void)
+{
+	cl_assert_equal_i(1, 1);
+}
diff --git a/t/unit-tests/clar/test/main.c.sample b/t/unit-tests/clar/example/main.c
similarity index 96%
rename from t/unit-tests/clar/test/main.c.sample
rename to t/unit-tests/clar/example/main.c
index a4d91b7..f8def7f 100644
--- a/t/unit-tests/clar/test/main.c.sample
+++ b/t/unit-tests/clar/example/main.c
@@ -5,7 +5,7 @@
  * For full terms see the included COPYING file.
  */
 
-#include "clar_test.h"
+#include "clar.h"
 
 /*
  * Minimal main() for clar tests.
diff --git a/t/unit-tests/clar/generate.py b/t/unit-tests/clar/generate.py
index 80996ac..fd2f0ee 100755
--- a/t/unit-tests/clar/generate.py
+++ b/t/unit-tests/clar/generate.py
@@ -158,17 +158,24 @@ def should_generate(self, path):
 
     def find_modules(self):
         modules = []
-        for root, _, files in os.walk(self.path):
-            module_root = root[len(self.path):]
-            module_root = [c for c in module_root.split(os.sep) if c]
 
-            tests_in_module = fnmatch.filter(files, "*.c")
+        if os.path.isfile(self.path):
+            full_path = os.path.abspath(self.path)
+            module_name = os.path.basename(self.path)
+            module_name = os.path.splitext(module_name)[0]
+            modules.append((full_path, module_name))
+        else:
+            for root, _, files in os.walk(self.path):
+                module_root = root[len(self.path):]
+                module_root = [c for c in module_root.split(os.sep) if c]
 
-            for test_file in tests_in_module:
-                full_path = os.path.join(root, test_file)
-                module_name = "_".join(module_root + [test_file[:-2]]).replace("-", "_")
+                tests_in_module = fnmatch.filter(files, "*.c")
 
-                modules.append((full_path, module_name))
+                for test_file in tests_in_module:
+                    full_path = os.path.join(root, test_file)
+                    module_name = "_".join(module_root + [test_file[:-2]]).replace("-", "_")
+
+                    modules.append((full_path, module_name))
 
         return modules
 
@@ -217,6 +224,7 @@ def callback_count(self):
 
     def write(self):
         output = os.path.join(self.output, 'clar.suite')
+        os.makedirs(self.output, exist_ok=True)
 
         if not self.should_generate(output):
             return False
@@ -258,7 +266,11 @@ def write(self):
         sys.exit(1)
 
     path = args.pop() if args else '.'
+    if os.path.isfile(path) and not options.output:
+        print("Must provide --output when specifying a file")
+        sys.exit(1)
     output = options.output or path
+
     suite = TestSuite(path, output)
     suite.load(options.force)
     suite.disable(options.excluded)
diff --git a/t/unit-tests/clar/test/CMakeLists.txt b/t/unit-tests/clar/test/CMakeLists.txt
index 7f2c1dc..f240166 100644
--- a/t/unit-tests/clar/test/CMakeLists.txt
+++ b/t/unit-tests/clar/test/CMakeLists.txt
@@ -2,12 +2,12 @@
 
 add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
 	COMMAND "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/generate.py" --output "${CMAKE_CURRENT_BINARY_DIR}"
-	DEPENDS main.c sample.c clar_test.h
+	DEPENDS main.c selftest.c
 	WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
 )
 
-add_executable(clar_test)
-set_target_properties(clar_test PROPERTIES
+add_executable(selftest)
+set_target_properties(selftest PROPERTIES
 	C_STANDARD 90
 	C_STANDARD_REQUIRED ON
 	C_EXTENSIONS OFF
@@ -15,25 +15,35 @@
 
 # MSVC generates all kinds of warnings. We may want to fix these in the future
 # and then unconditionally treat warnings as errors.
-if(NOT MSVC)
-	set_target_properties(clar_test PROPERTIES
+if (NOT MSVC)
+	set_target_properties(selftest PROPERTIES
 		COMPILE_WARNING_AS_ERROR ON
 	)
 endif()
 
-target_sources(clar_test PRIVATE
+target_sources(selftest PRIVATE
 	main.c
-	sample.c
+	selftest.c
 	"${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
 )
-target_compile_definitions(clar_test PRIVATE
-	CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/"
+target_compile_definitions(selftest PRIVATE
+	CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/expected/"
 )
-target_compile_options(clar_test PRIVATE
+target_compile_options(selftest PRIVATE
 	$<IF:$<CXX_COMPILER_ID:MSVC>,/W4,-Wall>
 )
-target_include_directories(clar_test PRIVATE
+target_include_directories(selftest PRIVATE
 	"${CMAKE_SOURCE_DIR}"
 	"${CMAKE_CURRENT_BINARY_DIR}"
 )
-target_link_libraries(clar_test clar)
+target_link_libraries(selftest clar)
+
+add_test(NAME build_selftest
+	COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --config "$<CONFIG>" --target selftest
+)
+set_tests_properties(build_selftest PROPERTIES FIXTURES_SETUP clar_test_fixture)
+
+add_subdirectory(suites)
+
+add_test(NAME selftest COMMAND "${CMAKE_CURRENT_BINARY_DIR}/selftest" $<TARGET_FILE_DIR:combined_suite>)
+set_tests_properties(selftest PROPERTIES FIXTURES_REQUIRED clar_test_fixture)
diff --git a/t/unit-tests/clar/test/clar_test.h b/t/unit-tests/clar/test/clar_test.h
deleted file mode 100644
index 0fcaa63..0000000
--- a/t/unit-tests/clar/test/clar_test.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) Vicent Marti. All rights reserved.
- *
- * This file is part of clar, distributed under the ISC license.
- * For full terms see the included COPYING file.
- */
-#ifndef __CLAR_TEST__
-#define __CLAR_TEST__
-
-/* Import the standard clar helper functions */
-#include "clar.h"
-
-/* Your custom shared includes / defines here */
-extern int global_test_counter;
-
-#endif
diff --git a/t/unit-tests/clar/test/expected/help b/t/unit-tests/clar/test/expected/help
new file mode 100644
index 0000000..9428def
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/help
@@ -0,0 +1,12 @@
+Usage: combined [options]
+
+Options:
+  -sname        Run only the suite with `name` (can go to individual test name)
+  -iname        Include the suite with `name`
+  -xname        Exclude the suite with `name`
+  -v            Increase verbosity (show suite names)
+  -q            Decrease verbosity, inverse to -v
+  -Q            Quit as soon as a test fails
+  -t            Display results in tap format
+  -l            Print suite names
+  -r[filename]  Write summary file (to the optional filename)
diff --git a/t/unit-tests/clar/test/expected/quiet b/t/unit-tests/clar/test/expected/quiet
new file mode 100644
index 0000000..280c99d
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/quiet
@@ -0,0 +1,44 @@
+  1) Failure:
+combined::1 [file:42]
+  Function call failed: -1
+
+  2) Failure:
+combined::2 [file:42]
+  Expression is not true: 100 == 101
+
+  3) Failure:
+combined::strings [file:42]
+  String mismatch: "mismatched" != actual ("this one fails")
+  'mismatched' != 'expected' (at byte 0)
+
+  4) Failure:
+combined::strings_with_length [file:42]
+  String mismatch: "exactly" != actual ("this one fails")
+  'exa' != 'exp' (at byte 2)
+
+  5) Failure:
+combined::int [file:42]
+  101 != value ("extra note on failing test")
+  101 != 100
+
+  6) Failure:
+combined::int_fmt [file:42]
+  022 != value
+  0022 != 0144
+
+  7) Failure:
+combined::bool [file:42]
+  0 != value
+  0 != 1
+
+  8) Failure:
+combined::multiline_description [file:42]
+  Function call failed: -1
+  description line 1
+  description line 2
+
+  9) Failure:
+combined::null_string [file:42]
+  String mismatch: "expected" != actual ("this one fails")
+  'expected' != NULL
+
diff --git a/t/unit-tests/clar/test/expected/specific_test b/t/unit-tests/clar/test/expected/specific_test
new file mode 100644
index 0000000..6c22e9f
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/specific_test
@@ -0,0 +1,9 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+F
+
+  1) Failure:
+combined::bool [file:42]
+  0 != value
+  0 != 1
+
diff --git a/t/unit-tests/clar/test/expected/stop_on_failure b/t/unit-tests/clar/test/expected/stop_on_failure
new file mode 100644
index 0000000..c236107
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/stop_on_failure
@@ -0,0 +1,8 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+F
+
+  1) Failure:
+combined::1 [file:42]
+  Function call failed: -1
+
diff --git a/t/unit-tests/clar/test/expected/suite_names b/t/unit-tests/clar/test/expected/suite_names
new file mode 100644
index 0000000..10d1538
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/suite_names
@@ -0,0 +1,2 @@
+Test suites (use -s<name> to run just one):
+   0: combined
diff --git a/t/unit-tests/clar/test/expected/summary.xml b/t/unit-tests/clar/test/expected/summary.xml
new file mode 100644
index 0000000..9a89d43
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/summary.xml
@@ -0,0 +1,41 @@
+<testsuites>
+	<testsuite id="0" name="selftest" hostname="localhost" timestamp="2024-09-06T10:04:08" tests="8" failures="8" errors="0">
+		<testcase name="1" classname="selftest" time="0.00">
+			<failure type="assert"><![CDATA[Function call failed: -1
+(null)]]></failure>
+		</testcase>
+		<testcase name="2" classname="selftest" time="0.00">
+			<failure type="assert"><![CDATA[Expression is not true: 100 == 101
+(null)]]></failure>
+		</testcase>
+		<testcase name="strings" classname="selftest" time="0.00">
+			<failure type="assert"><![CDATA[String mismatch: "mismatched" != actual ("this one fails")
+'mismatched' != 'expected' (at byte 0)]]></failure>
+		</testcase>
+		<testcase name="strings_with_length" classname="selftest" time="0.00">
+			<failure type="assert"><![CDATA[String mismatch: "exactly" != actual ("this one fails")
+'exa' != 'exp' (at byte 2)]]></failure>
+		</testcase>
+		<testcase name="int" classname="selftest" time="0.00">
+			<failure type="assert"><![CDATA[101 != value ("extra note on failing test")
+101 != 100]]></failure>
+		</testcase>
+		<testcase name="int_fmt" classname="selftest" time="0.00">
+			<failure type="assert"><![CDATA[022 != value
+0022 != 0144]]></failure>
+		</testcase>
+		<testcase name="bool" classname="selftest" time="0.00">
+			<failure type="assert"><![CDATA[0 != value
+0 != 1]]></failure>
+		</testcase>
+		<testcase name="multiline_description" classname="selftest" time="0.00">
+			<failure type="assert"><![CDATA[Function call failed: −1
+description line 1
+description line 2]]></failure>
+		</testcase>
+		<testcase name="null_string" classname="selftest" time="0.00">
+			<failure type="assert"><![CDATA[String mismatch: "expected" != actual ("this one fails")
+'expected' != NULL]]></failure>
+		</testcase>
+	</testsuite>
+</testsuites>
diff --git a/t/unit-tests/clar/test/expected/summary_with_filename b/t/unit-tests/clar/test/expected/summary_with_filename
new file mode 100644
index 0000000..4601607
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/summary_with_filename
@@ -0,0 +1,49 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+FFFFFFFFF
+
+  1) Failure:
+combined::1 [file:42]
+  Function call failed: -1
+
+  2) Failure:
+combined::2 [file:42]
+  Expression is not true: 100 == 101
+
+  3) Failure:
+combined::strings [file:42]
+  String mismatch: "mismatched" != actual ("this one fails")
+  'mismatched' != 'expected' (at byte 0)
+
+  4) Failure:
+combined::strings_with_length [file:42]
+  String mismatch: "exactly" != actual ("this one fails")
+  'exa' != 'exp' (at byte 2)
+
+  5) Failure:
+combined::int [file:42]
+  101 != value ("extra note on failing test")
+  101 != 100
+
+  6) Failure:
+combined::int_fmt [file:42]
+  022 != value
+  0022 != 0144
+
+  7) Failure:
+combined::bool [file:42]
+  0 != value
+  0 != 1
+
+  8) Failure:
+combined::multiline_description [file:42]
+  Function call failed: -1
+  description line 1
+  description line 2
+
+  9) Failure:
+combined::null_string [file:42]
+  String mismatch: "expected" != actual ("this one fails")
+  'expected' != NULL
+
+written summary file to different.xml
diff --git a/t/unit-tests/clar/test/expected/summary_without_filename b/t/unit-tests/clar/test/expected/summary_without_filename
new file mode 100644
index 0000000..7874c1d
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/summary_without_filename
@@ -0,0 +1,49 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+FFFFFFFFF
+
+  1) Failure:
+combined::1 [file:42]
+  Function call failed: -1
+
+  2) Failure:
+combined::2 [file:42]
+  Expression is not true: 100 == 101
+
+  3) Failure:
+combined::strings [file:42]
+  String mismatch: "mismatched" != actual ("this one fails")
+  'mismatched' != 'expected' (at byte 0)
+
+  4) Failure:
+combined::strings_with_length [file:42]
+  String mismatch: "exactly" != actual ("this one fails")
+  'exa' != 'exp' (at byte 2)
+
+  5) Failure:
+combined::int [file:42]
+  101 != value ("extra note on failing test")
+  101 != 100
+
+  6) Failure:
+combined::int_fmt [file:42]
+  022 != value
+  0022 != 0144
+
+  7) Failure:
+combined::bool [file:42]
+  0 != value
+  0 != 1
+
+  8) Failure:
+combined::multiline_description [file:42]
+  Function call failed: -1
+  description line 1
+  description line 2
+
+  9) Failure:
+combined::null_string [file:42]
+  String mismatch: "expected" != actual ("this one fails")
+  'expected' != NULL
+
+written summary file to summary.xml
diff --git a/t/unit-tests/clar/test/expected/tap b/t/unit-tests/clar/test/expected/tap
new file mode 100644
index 0000000..bddbd5d
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/tap
@@ -0,0 +1,92 @@
+TAP version 13
+# start of suite 1: combined
+not ok 1 - combined::1
+    ---
+    reason: |
+      Function call failed: -1
+    at:
+      file: 'file'
+      line: 42
+      function: 'func'
+    ---
+not ok 2 - combined::2
+    ---
+    reason: |
+      Expression is not true: 100 == 101
+    at:
+      file: 'file'
+      line: 42
+      function: 'func'
+    ---
+not ok 3 - combined::strings
+    ---
+    reason: |
+      String mismatch: "mismatched" != actual ("this one fails")
+      'mismatched' != 'expected' (at byte 0)
+    at:
+      file: 'file'
+      line: 42
+      function: 'func'
+    ---
+not ok 4 - combined::strings_with_length
+    ---
+    reason: |
+      String mismatch: "exactly" != actual ("this one fails")
+      'exa' != 'exp' (at byte 2)
+    at:
+      file: 'file'
+      line: 42
+      function: 'func'
+    ---
+not ok 5 - combined::int
+    ---
+    reason: |
+      101 != value ("extra note on failing test")
+      101 != 100
+    at:
+      file: 'file'
+      line: 42
+      function: 'func'
+    ---
+not ok 6 - combined::int_fmt
+    ---
+    reason: |
+      022 != value
+      0022 != 0144
+    at:
+      file: 'file'
+      line: 42
+      function: 'func'
+    ---
+not ok 7 - combined::bool
+    ---
+    reason: |
+      0 != value
+      0 != 1
+    at:
+      file: 'file'
+      line: 42
+      function: 'func'
+    ---
+not ok 8 - combined::multiline_description
+    ---
+    reason: |
+      Function call failed: -1
+      description line 1
+      description line 2
+    at:
+      file: 'file'
+      line: 42
+      function: 'func'
+    ---
+not ok 9 - combined::null_string
+    ---
+    reason: |
+      String mismatch: "expected" != actual ("this one fails")
+      'expected' != NULL
+    at:
+      file: 'file'
+      line: 42
+      function: 'func'
+    ---
+1..9
diff --git a/t/unit-tests/clar/test/expected/without_arguments b/t/unit-tests/clar/test/expected/without_arguments
new file mode 100644
index 0000000..1111d41
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/without_arguments
@@ -0,0 +1,48 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+FFFFFFFFF
+
+  1) Failure:
+combined::1 [file:42]
+  Function call failed: -1
+
+  2) Failure:
+combined::2 [file:42]
+  Expression is not true: 100 == 101
+
+  3) Failure:
+combined::strings [file:42]
+  String mismatch: "mismatched" != actual ("this one fails")
+  'mismatched' != 'expected' (at byte 0)
+
+  4) Failure:
+combined::strings_with_length [file:42]
+  String mismatch: "exactly" != actual ("this one fails")
+  'exa' != 'exp' (at byte 2)
+
+  5) Failure:
+combined::int [file:42]
+  101 != value ("extra note on failing test")
+  101 != 100
+
+  6) Failure:
+combined::int_fmt [file:42]
+  022 != value
+  0022 != 0144
+
+  7) Failure:
+combined::bool [file:42]
+  0 != value
+  0 != 1
+
+  8) Failure:
+combined::multiline_description [file:42]
+  Function call failed: -1
+  description line 1
+  description line 2
+
+  9) Failure:
+combined::null_string [file:42]
+  String mismatch: "expected" != actual ("this one fails")
+  'expected' != NULL
+
diff --git a/t/unit-tests/clar/test/main.c b/t/unit-tests/clar/test/main.c
index 59e56ad..94af440 100644
--- a/t/unit-tests/clar/test/main.c
+++ b/t/unit-tests/clar/test/main.c
@@ -1,23 +1,9 @@
-/*
- * Copyright (c) Vicent Marti. All rights reserved.
- *
- * This file is part of clar, distributed under the ISC license.
- * For full terms see the included COPYING file.
- */
+#include <stdio.h>
+#include <string.h>
 
-#include "clar_test.h"
+#include "selftest.h"
 
-/*
- * Sample main() for clar tests.
- *
- * You should write your own main routine for clar tests that does specific
- * setup and teardown as necessary for your application.  The only required
- * line is the call to `clar_test(argc, argv)`, which will execute the test
- * suite.  If you want to check the return value of the test application,
- * your main() should return the same value returned by clar_test().
- */
-
-int global_test_counter = 0;
+const char *selftest_suite_directory;
 
 #ifdef _WIN32
 int __cdecl main(int argc, char *argv[])
@@ -25,16 +11,15 @@ int __cdecl main(int argc, char *argv[])
 int main(int argc, char *argv[])
 #endif
 {
-	int ret;
+	if (argc < 2) {
+		fprintf(stderr, "usage: %s <selftest-suite-directory> <options>\n",
+			argv[0]);
+		exit(1);
+	}
 
-	/* Your custom initialization here */
-	global_test_counter = 0;
+	selftest_suite_directory = argv[1];
+	memmove(argv + 1, argv + 2, argc - 1);
+	argc -= 1;
 
-	/* Run the test suite */
-	ret = clar_test(argc, argv);
-
-	/* Your custom cleanup here */
-	cl_assert_equal_i(8, global_test_counter);
-
-	return ret;
+	return clar_test(argc, argv);
 }
diff --git a/t/unit-tests/clar/test/selftest.c b/t/unit-tests/clar/test/selftest.c
new file mode 100644
index 0000000..eed83e4
--- /dev/null
+++ b/t/unit-tests/clar/test/selftest.c
@@ -0,0 +1,370 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "selftest.h"
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+static char *read_full(HANDLE h, int is_pipe)
+{
+	char *data = NULL;
+	size_t data_size = 0;
+
+	while (1) {
+		CHAR buf[4096];
+		DWORD bytes_read;
+
+		if (!ReadFile(h, buf, sizeof(buf), &bytes_read, NULL)) {
+			if (!is_pipe)
+				cl_fail("Failed reading file handle.");
+			cl_assert_equal_i(GetLastError(), ERROR_BROKEN_PIPE);
+			break;
+		}
+		if (!bytes_read)
+			break;
+
+		data = realloc(data, data_size + bytes_read);
+		cl_assert(data);
+		memcpy(data + data_size, buf, bytes_read);
+		data_size += bytes_read;
+	}
+
+	data = realloc(data, data_size + 1);
+	cl_assert(data);
+	data[data_size] = '\0';
+
+	while (strstr(data, "\r\n")) {
+		char *ptr = strstr(data, "\r\n");
+		memmove(ptr, ptr + 1, strlen(ptr));
+	}
+
+	return data;
+}
+
+static char *read_file(const char *path)
+{
+	char *content;
+	HANDLE file;
+
+	file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL,
+			  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+	cl_assert(file != INVALID_HANDLE_VALUE);
+	content = read_full(file, 0);
+	cl_assert_equal_b(1, CloseHandle(file));
+
+	return content;
+}
+
+static char *execute(const char *suite, int expected_error_code, const char **args, size_t nargs)
+{
+	SECURITY_ATTRIBUTES security_attributes = { 0 };
+	PROCESS_INFORMATION process_info = { 0 };
+	STARTUPINFO startup_info = { 0 };
+	char binary_path[4096] = { 0 };
+	char cmdline[4096] = { 0 };
+	char *output = NULL;
+	HANDLE stdout_write;
+	HANDLE stdout_read;
+	DWORD exit_code;
+	size_t i;
+
+	snprintf(binary_path, sizeof(binary_path), "%s/%s_suite.exe",
+		 selftest_suite_directory, suite);
+
+	/*
+	 * Assemble command line arguments. In theory we'd have to properly
+	 * quote them. In practice none of our tests actually care.
+	 */
+	snprintf(cmdline, sizeof(cmdline), suite);
+	for (i = 0; i < nargs; i++) {
+		size_t cmdline_len = strlen(cmdline);
+		const char *arg = args[i];
+		cl_assert(cmdline_len + strlen(arg) < sizeof(cmdline));
+		snprintf(cmdline + cmdline_len, sizeof(cmdline) - cmdline_len,
+			 " %s", arg);
+	}
+
+	/*
+	 * Create a pipe that we will use to read data from the child process.
+	 * The writing side needs to be inheritable such that the child can use
+	 * it as stdout and stderr. The reading side should only be used by the
+	 * parent.
+	 */
+	security_attributes.nLength = sizeof(security_attributes);
+	security_attributes.bInheritHandle = TRUE;
+	cl_assert_equal_b(1, CreatePipe(&stdout_read, &stdout_write, &security_attributes, 0));
+	cl_assert_equal_b(1, SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0));
+
+	/*
+	 * Create the child process with our pipe.
+	 */
+	startup_info.cb = sizeof(startup_info);
+	startup_info.hStdError = stdout_write;
+	startup_info.hStdOutput = stdout_write;
+	startup_info.dwFlags |= STARTF_USESTDHANDLES;
+	cl_assert_equal_b(1, CreateProcess(binary_path, cmdline, NULL, NULL, TRUE,
+					   0, NULL, NULL, &startup_info, &process_info));
+	cl_assert_equal_b(1, CloseHandle(stdout_write));
+
+	output = read_full(stdout_read, 1);
+	cl_assert_equal_b(1, CloseHandle(stdout_read));
+	cl_assert_equal_b(1, GetExitCodeProcess(process_info.hProcess, &exit_code));
+	cl_assert_equal_i(exit_code, expected_error_code);
+
+	return output;
+}
+
+static void assert_output(const char *suite, const char *expected_output_file, int expected_error_code, ...)
+{
+	char *expected_output = NULL;
+	char *output = NULL;
+	const char *args[16];
+	va_list ap;
+	size_t i;
+
+	va_start(ap, expected_error_code);
+	for (i = 0; ; i++) {
+		const char *arg = va_arg(ap, const char *);
+		if (!arg)
+			break;
+		cl_assert(i < sizeof(args) / sizeof(*args));
+		args[i] = arg;
+	}
+	va_end(ap);
+
+	output = execute(suite, expected_error_code, args, i);
+	expected_output = read_file(cl_fixture(expected_output_file));
+	cl_assert_equal_s(output, expected_output);
+
+	free(expected_output);
+	free(output);
+}
+
+#else
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+# include <unistd.h>
+# include <sys/wait.h>
+
+static char *read_full(int fd)
+{
+	size_t data_bytes = 0;
+	char *data = NULL;
+
+	while (1) {
+		char buf[4096];
+		ssize_t n;
+
+		n = read(fd, buf, sizeof(buf));
+		if (n < 0) {
+			if (errno == EAGAIN || errno == EINTR)
+				continue;
+			cl_fail("Failed reading from child process.");
+		}
+		if (!n)
+			break;
+
+		data = realloc(data, data_bytes + n);
+		cl_assert(data);
+
+		memcpy(data + data_bytes, buf, n);
+		data_bytes += n;
+	}
+
+	data = realloc(data, data_bytes + 1);
+	cl_assert(data);
+	data[data_bytes] = '\0';
+
+	return data;
+}
+
+static char *read_file(const char *path)
+{
+	char *data;
+	int fd;
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		cl_fail("Failed reading expected file.");
+
+	data = read_full(fd);
+	cl_must_pass(close(fd));
+
+	return data;
+}
+
+static char *execute(const char *suite, int expected_error_code, const char **args, size_t nargs)
+{
+	int pipe_fds[2];
+	pid_t pid;
+
+	cl_must_pass(pipe(pipe_fds));
+
+	pid = fork();
+	if (!pid) {
+		const char *final_args[17] = { NULL };
+		char binary_path[4096];
+		size_t len = 0;
+		size_t i;
+
+		cl_assert(nargs < sizeof(final_args) / sizeof(*final_args));
+		final_args[0] = suite;
+		for (i = 0; i < nargs; i++)
+			final_args[i + 1] = args[i];
+
+		if (dup2(pipe_fds[1], STDOUT_FILENO) < 0 ||
+		    dup2(pipe_fds[1], STDERR_FILENO) < 0 ||
+		    close(0) < 0 ||
+		    close(pipe_fds[0]) < 0 ||
+		    close(pipe_fds[1]) < 0)
+			exit(1);
+
+		cl_assert(len + strlen(selftest_suite_directory) < sizeof(binary_path));
+		strcpy(binary_path, selftest_suite_directory);
+		len += strlen(selftest_suite_directory);
+
+		cl_assert(len + 1 < sizeof(binary_path));
+		binary_path[len] = '/';
+		len += 1;
+
+		cl_assert(len + strlen(suite) < sizeof(binary_path));
+		strcpy(binary_path + len, suite);
+		len += strlen(suite);
+
+		cl_assert(len + strlen("_suite") < sizeof(binary_path));
+		strcpy(binary_path + len, "_suite");
+		len += strlen("_suite");
+
+		binary_path[len] = '\0';
+
+		execv(binary_path, (char **) final_args);
+		exit(1);
+	} else if (pid > 0) {
+		pid_t waited_pid;
+		char *output;
+		int stat;
+
+		cl_must_pass(close(pipe_fds[1]));
+
+		output = read_full(pipe_fds[0]);
+
+		waited_pid = waitpid(pid, &stat, 0);
+		cl_assert_equal_i(pid, waited_pid);
+		cl_assert(WIFEXITED(stat));
+		cl_assert_equal_i(WEXITSTATUS(stat), expected_error_code);
+
+		return output;
+	} else {
+		cl_fail("Fork failed.");
+	}
+
+	return NULL;
+}
+
+static void assert_output(const char *suite, const char *expected_output_file, int expected_error_code, ...)
+{
+	char *expected_output, *output;
+	const char *args[16];
+	va_list ap;
+	size_t i;
+
+	va_start(ap, expected_error_code);
+	for (i = 0; ; i++) {
+		cl_assert(i < sizeof(args) / sizeof(*args));
+		args[i] = va_arg(ap, const char *);
+		if (!args[i])
+			break;
+	}
+	va_end(ap);
+
+	output = execute(suite, expected_error_code, args, i);
+	expected_output = read_file(cl_fixture(expected_output_file));
+	cl_assert_equal_s(output, expected_output);
+
+	free(expected_output);
+	free(output);
+}
+#endif
+
+void test_selftest__help(void)
+{
+	cl_invoke(assert_output("combined", "help", 1, "-h", NULL));
+}
+
+void test_selftest__without_arguments(void)
+{
+	cl_invoke(assert_output("combined", "without_arguments", 9, NULL));
+}
+
+void test_selftest__specific_test(void)
+{
+	cl_invoke(assert_output("combined", "specific_test", 1, "-scombined::bool", NULL));
+}
+
+void test_selftest__stop_on_failure(void)
+{
+	cl_invoke(assert_output("combined", "stop_on_failure", 1, "-Q", NULL));
+}
+
+void test_selftest__quiet(void)
+{
+	cl_invoke(assert_output("combined", "quiet", 9, "-q", NULL));
+}
+
+void test_selftest__tap(void)
+{
+	cl_invoke(assert_output("combined", "tap", 9, "-t", NULL));
+}
+
+void test_selftest__suite_names(void)
+{
+	cl_invoke(assert_output("combined", "suite_names", 0, "-l", NULL));
+}
+
+void test_selftest__summary_without_filename(void)
+{
+	struct stat st;
+	cl_invoke(assert_output("combined", "summary_without_filename", 9, "-r", NULL));
+	/* The summary contains timestamps, so we cannot verify its contents. */
+	cl_must_pass(stat("summary.xml", &st));
+}
+
+void test_selftest__summary_with_filename(void)
+{
+	struct stat st;
+	cl_invoke(assert_output("combined", "summary_with_filename", 9, "-rdifferent.xml", NULL));
+	/* The summary contains timestamps, so we cannot verify its contents. */
+	cl_must_pass(stat("different.xml", &st));
+}
+
+void test_selftest__pointer_equal(void)
+{
+	const char *args[] = {
+		"-spointer::equal",
+		"-t"
+	};
+	char *output = execute("pointer", 0, args, 2);
+	cl_assert_equal_s(output,
+		   "TAP version 13\n"
+		   "# start of suite 1: pointer\n"
+		   "ok 1 - pointer::equal\n"
+		   "1..1\n"
+	);
+	free(output);
+}
+
+void test_selftest__pointer_unequal(void)
+{
+	const char *args[] = {
+		"-spointer::unequal",
+	};
+	char *output = execute("pointer", 1, args, 1);
+	cl_assert(output);
+	cl_assert(strstr(output, "Pointer mismatch: "));
+	free(output);
+}
diff --git a/t/unit-tests/clar/test/selftest.h b/t/unit-tests/clar/test/selftest.h
new file mode 100644
index 0000000..c24e0c5
--- /dev/null
+++ b/t/unit-tests/clar/test/selftest.h
@@ -0,0 +1,3 @@
+#include "clar.h"
+
+extern const char *selftest_suite_directory;
diff --git a/t/unit-tests/clar/test/suites/CMakeLists.txt b/t/unit-tests/clar/test/suites/CMakeLists.txt
new file mode 100644
index 0000000..fa8ab94
--- /dev/null
+++ b/t/unit-tests/clar/test/suites/CMakeLists.txt
@@ -0,0 +1,53 @@
+list(APPEND suites
+	"combined"
+	"pointer"
+)
+
+foreach(suite IN LISTS suites)
+	add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${suite}/clar.suite"
+		COMMAND "${Python_EXECUTABLE}"
+			"${CMAKE_SOURCE_DIR}/generate.py"
+			"${CMAKE_CURRENT_SOURCE_DIR}/${suite}.c"
+			--output "${CMAKE_CURRENT_BINARY_DIR}/${suite}"
+		DEPENDS ${suite}.c
+		WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+	)
+
+	add_executable(${suite}_suite)
+	set_target_properties(${suite}_suite PROPERTIES
+		C_STANDARD 90
+		C_STANDARD_REQUIRED ON
+		C_EXTENSIONS OFF
+	)
+
+	# MSVC generates all kinds of warnings. We may want to fix these in the future
+	# and then unconditionally treat warnings as errors.
+	if(NOT MSVC)
+		set_target_properties(${suite}_suite PROPERTIES
+			COMPILE_WARNING_AS_ERROR ON
+		)
+	endif()
+
+	target_sources(${suite}_suite PRIVATE
+		main.c
+		${suite}.c
+		"${CMAKE_CURRENT_BINARY_DIR}/${suite}/clar.suite"
+	)
+	target_compile_definitions(${suite}_suite PRIVATE
+		CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/"
+		CLAR_SELFTEST
+	)
+	target_compile_options(${suite}_suite PRIVATE
+		$<IF:$<CXX_COMPILER_ID:MSVC>,/W4,-Wall>
+	)
+	target_include_directories(${suite}_suite PRIVATE
+		"${CMAKE_SOURCE_DIR}"
+		"${CMAKE_CURRENT_BINARY_DIR}/${suite}"
+	)
+	target_link_libraries(${suite}_suite clar)
+
+	add_test(NAME build_${suite}_suite
+		COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --config "$<CONFIG>" --target selftest
+	)
+	set_tests_properties(build_${suite}_suite PROPERTIES FIXTURES_SETUP clar_test_fixture)
+endforeach()
diff --git a/t/unit-tests/clar/test/sample.c b/t/unit-tests/clar/test/suites/combined.c
similarity index 69%
rename from t/unit-tests/clar/test/sample.c
rename to t/unit-tests/clar/test/suites/combined.c
index faa1209..e8b41c9 100644
--- a/t/unit-tests/clar/test/sample.c
+++ b/t/unit-tests/clar/test/suites/combined.c
@@ -1,6 +1,7 @@
-#include "clar_test.h"
 #include <sys/stat.h>
 
+#include "clar.h"
+
 static int file_size(const char *filename)
 {
 	struct stat st;
@@ -10,19 +11,14 @@ static int file_size(const char *filename)
 	return -1;
 }
 
-void test_sample__initialize(void)
-{
-	global_test_counter++;
-}
-
-void test_sample__cleanup(void)
+void test_combined__cleanup(void)
 {
 	cl_fixture_cleanup("test");
 
 	cl_assert(file_size("test/file") == -1);
 }
 
-void test_sample__1(void)
+void test_combined__1(void)
 {
 	cl_assert(1);
 	cl_must_pass(0);  /* 0 == success */
@@ -30,7 +26,7 @@ void test_sample__1(void)
 	cl_must_pass(-1); /* demonstrate a failing call */
 }
 
-void test_sample__2(void)
+void test_combined__2(void)
 {
 	cl_fixture_sandbox("test");
 
@@ -39,7 +35,7 @@ void test_sample__2(void)
 	cl_assert(100 == 101);
 }
 
-void test_sample__strings(void)
+void test_combined__strings(void)
 {
 	const char *actual = "expected";
 	cl_assert_equal_s("expected", actual);
@@ -47,7 +43,7 @@ void test_sample__strings(void)
 	cl_assert_equal_s_("mismatched", actual, "this one fails");
 }
 
-void test_sample__strings_with_length(void)
+void test_combined__strings_with_length(void)
 {
 	const char *actual = "expected";
 	cl_assert_equal_strn("expected_", actual, 8);
@@ -56,29 +52,34 @@ void test_sample__strings_with_length(void)
 	cl_assert_equal_strn_("exactly", actual, 3, "this one fails");
 }
 
-void test_sample__int(void)
+void test_combined__int(void)
 {
 	int value = 100;
 	cl_assert_equal_i(100, value);
 	cl_assert_equal_i_(101, value, "extra note on failing test");
 }
 
-void test_sample__int_fmt(void)
+void test_combined__int_fmt(void)
 {
 	int value = 100;
 	cl_assert_equal_i_fmt(022, value, "%04o");
 }
 
-void test_sample__bool(void)
+void test_combined__bool(void)
 {
 	int value = 100;
 	cl_assert_equal_b(1, value);       /* test equality as booleans */
 	cl_assert_equal_b(0, value);
 }
 
-void test_sample__ptr(void)
+void test_combined__multiline_description(void)
 {
-	const char *actual = "expected";
-	cl_assert_equal_p(actual, actual); /* pointers to same object */
-	cl_assert_equal_p(&actual, actual);
+	cl_must_pass_(-1, "description line 1\ndescription line 2");
+}
+
+void test_combined__null_string(void)
+{
+	const char *actual = NULL;
+	cl_assert_equal_s(actual, actual);
+	cl_assert_equal_s_("expected", actual, "this one fails");
 }
diff --git a/t/unit-tests/clar/test/suites/main.c b/t/unit-tests/clar/test/suites/main.c
new file mode 100644
index 0000000..3ab581d
--- /dev/null
+++ b/t/unit-tests/clar/test/suites/main.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) Vicent Marti. All rights reserved.
+ *
+ * This file is part of clar, distributed under the ISC license.
+ * For full terms see the included COPYING file.
+ */
+
+#include "clar.h"
+
+/*
+ * Selftest main() for clar tests.
+ *
+ * You should write your own main routine for clar tests that does specific
+ * setup and teardown as necessary for your application.  The only required
+ * line is the call to `clar_test(argc, argv)`, which will execute the test
+ * suite.  If you want to check the return value of the test application,
+ * your main() should return the same value returned by clar_test().
+ */
+
+#ifdef _WIN32
+int __cdecl main(int argc, char *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+	return clar_test(argc, argv);
+}
diff --git a/t/unit-tests/clar/test/suites/pointer.c b/t/unit-tests/clar/test/suites/pointer.c
new file mode 100644
index 0000000..20535b1
--- /dev/null
+++ b/t/unit-tests/clar/test/suites/pointer.c
@@ -0,0 +1,13 @@
+#include "clar.h"
+
+void test_pointer__equal(void)
+{
+	void *p1 = (void *)0x1;
+	cl_assert_equal_p(p1, p1);
+}
+
+void test_pointer__unequal(void)
+{
+	void *p1 = (void *)0x1, *p2 = (void *)0x2;
+	cl_assert_equal_p(p1, p2);
+}
diff --git a/t/unit-tests/clar/test/resources/test/file b/t/unit-tests/clar/test/suites/resources/test/file
similarity index 100%
rename from t/unit-tests/clar/test/resources/test/file
rename to t/unit-tests/clar/test/suites/resources/test/file
diff --git a/t/unit-tests/u-dir.c b/t/unit-tests/u-dir.c
new file mode 100644
index 0000000..2d0adaa
--- /dev/null
+++ b/t/unit-tests/u-dir.c
@@ -0,0 +1,47 @@
+#include "unit-test.h"
+#include "dir.h"
+
+#define TEST_WITHIN_DEPTH(path, depth, max_depth, expect) do { \
+		int actual = within_depth(path, strlen(path), \
+					  depth, max_depth); \
+		if (actual != expect) \
+			cl_failf("path '%s' with depth '%d' and max-depth '%d': expected %d, got %d", \
+				 path, depth, max_depth, expect, actual); \
+	} while (0)
+
+void test_dir__within_depth(void)
+{
+	/* depth = 0; max_depth = 0 */
+	TEST_WITHIN_DEPTH("",         0, 0, 1);
+	TEST_WITHIN_DEPTH("file",     0, 0, 1);
+	TEST_WITHIN_DEPTH("a",        0, 0, 1);
+	TEST_WITHIN_DEPTH("a/file",   0, 0, 0);
+	TEST_WITHIN_DEPTH("a/b",      0, 0, 0);
+	TEST_WITHIN_DEPTH("a/b/file", 0, 0, 0);
+
+	/* depth = 0; max_depth = 1 */
+	TEST_WITHIN_DEPTH("",         0, 1, 1);
+	TEST_WITHIN_DEPTH("file",     0, 1, 1);
+	TEST_WITHIN_DEPTH("a",        0, 1, 1);
+	TEST_WITHIN_DEPTH("a/file",   0, 1, 1);
+	TEST_WITHIN_DEPTH("a/b",      0, 1, 1);
+	TEST_WITHIN_DEPTH("a/b/file", 0, 1, 0);
+
+	/* depth = 1; max_depth = 1 */
+	TEST_WITHIN_DEPTH("",         1, 1, 1);
+	TEST_WITHIN_DEPTH("file",     1, 1, 1);
+	TEST_WITHIN_DEPTH("a",        1, 1, 1);
+	TEST_WITHIN_DEPTH("a/file",   1, 1, 0);
+	TEST_WITHIN_DEPTH("a/b",      1, 1, 0);
+	TEST_WITHIN_DEPTH("a/b/file", 1, 1, 0);
+
+	/* depth = 1; max_depth = 0 */
+	TEST_WITHIN_DEPTH("",         1, 0, 0);
+	TEST_WITHIN_DEPTH("file",     1, 0, 0);
+	TEST_WITHIN_DEPTH("a",        1, 0, 0);
+	TEST_WITHIN_DEPTH("a/file",   1, 0, 0);
+	TEST_WITHIN_DEPTH("a/b",      1, 0, 0);
+	TEST_WITHIN_DEPTH("a/b/file", 1, 0, 0);
+
+
+}
diff --git a/t/unit-tests/u-reftable-basics.c b/t/unit-tests/u-reftable-basics.c
index a047108..73566ed 100644
--- a/t/unit-tests/u-reftable-basics.c
+++ b/t/unit-tests/u-reftable-basics.c
@@ -9,6 +9,7 @@ license that can be found in the LICENSE file or at
 #include "unit-test.h"
 #include "lib-reftable.h"
 #include "reftable/basics.h"
+#include "reftable/reftable-error.h"
 
 struct integer_needle_lesseq_args {
 	int needle;
@@ -79,14 +80,18 @@ void test_reftable_basics__names_equal(void)
 void test_reftable_basics__parse_names(void)
 {
 	char in1[] = "line\n";
-	char in2[] = "a\nb\nc";
-	char **out = parse_names(in1, strlen(in1));
+	char in2[] = "a\nb\nc\n";
+	char **out = NULL;
+	int err = parse_names(in1, strlen(in1), &out);
+	cl_assert(err == 0);
 	cl_assert(out != NULL);
 	cl_assert_equal_s(out[0], "line");
 	cl_assert(!out[1]);
 	free_names(out);
 
-	out = parse_names(in2, strlen(in2));
+	out = NULL;
+	err = parse_names(in2, strlen(in2), &out);
+	cl_assert(err == 0);
 	cl_assert(out != NULL);
 	cl_assert_equal_s(out[0], "a");
 	cl_assert_equal_s(out[1], "b");
@@ -95,10 +100,21 @@ void test_reftable_basics__parse_names(void)
 	free_names(out);
 }
 
+void test_reftable_basics__parse_names_missing_newline(void)
+{
+	char in1[] = "line\nline2";
+	char **out = NULL;
+	int err = parse_names(in1, strlen(in1), &out);
+	cl_assert(err == REFTABLE_FORMAT_ERROR);
+	cl_assert(out == NULL);
+}
+
 void test_reftable_basics__parse_names_drop_empty_string(void)
 {
 	char in[] = "a\n\nb\n";
-	char **out = parse_names(in, strlen(in));
+	char **out = NULL;
+	int err = parse_names(in, strlen(in), &out);
+	cl_assert(err == 0);
 	cl_assert(out != NULL);
 	cl_assert_equal_s(out[0], "a");
 	/* simply '\n' should be dropped as empty string */
diff --git a/t/unit-tests/u-reftable-stack.c b/t/unit-tests/u-reftable-stack.c
index e4ea571..b8110cd 100644
--- a/t/unit-tests/u-reftable-stack.c
+++ b/t/unit-tests/u-reftable-stack.c
@@ -128,7 +128,7 @@ static void write_n_ref_tables(struct reftable_stack *st,
 		cl_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1);
 
 		cl_assert_equal_i(reftable_stack_add(st,
-						     &write_test_ref, &ref), 0);
+						     &write_test_ref, &ref, 0), 0);
 	}
 
 	st->opts.disable_auto_compact = disable_auto_compact;
@@ -171,7 +171,7 @@ void test_reftable_stack__add_one(void)
 	err = reftable_new_stack(&st, dir, &opts);
 	cl_assert(!err);
 
-	err = reftable_stack_add(st, write_test_ref, &ref);
+	err = reftable_stack_add(st, write_test_ref, &ref, 0);
 	cl_assert(!err);
 
 	err = reftable_stack_read_ref(st, ref.refname, &dest);
@@ -235,12 +235,12 @@ void test_reftable_stack__uptodate(void)
 	cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0);
 	cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0);
 	cl_assert_equal_i(reftable_stack_add(st1, write_test_ref,
-					     &ref1), 0);
+					     &ref1, 0), 0);
 	cl_assert_equal_i(reftable_stack_add(st2, write_test_ref,
-					     &ref2), REFTABLE_OUTDATED_ERROR);
+					     &ref2, 0), REFTABLE_OUTDATED_ERROR);
 	cl_assert_equal_i(reftable_stack_reload(st2), 0);
 	cl_assert_equal_i(reftable_stack_add(st2, write_test_ref,
-					     &ref2), 0);
+					     &ref2, 0), 0);
 	reftable_stack_destroy(st1);
 	reftable_stack_destroy(st2);
 	clear_dir(dir);
@@ -406,7 +406,7 @@ void test_reftable_stack__auto_compaction_fails_gracefully(void)
 
 	cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
 	cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
-					     &ref), 0);
+					     &ref, 0), 0);
 	cl_assert_equal_i(st->merged->tables_len, 1);
 	cl_assert_equal_i(st->stats.attempts, 0);
 	cl_assert_equal_i(st->stats.failures, 0);
@@ -424,7 +424,7 @@ void test_reftable_stack__auto_compaction_fails_gracefully(void)
 	write_file_buf(table_path.buf, "", 0);
 
 	ref.update_index = 2;
-	err = reftable_stack_add(st, write_test_ref, &ref);
+	err = reftable_stack_add(st, write_test_ref, &ref, 0);
 	cl_assert(!err);
 	cl_assert_equal_i(st->merged->tables_len, 2);
 	cl_assert_equal_i(st->stats.attempts, 1);
@@ -460,9 +460,9 @@ void test_reftable_stack__update_index_check(void)
 
 	cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
 	cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
-					     &ref1), 0);
+					     &ref1, 0), 0);
 	cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
-					     &ref2), REFTABLE_API_ERROR);
+					     &ref2, 0), REFTABLE_API_ERROR);
 	reftable_stack_destroy(st);
 	clear_dir(dir);
 }
@@ -477,7 +477,7 @@ void test_reftable_stack__lock_failure(void)
 	cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
 	for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--)
 		cl_assert_equal_i(reftable_stack_add(st, write_error,
-						     &i), i);
+						     &i, 0), i);
 
 	reftable_stack_destroy(st);
 	clear_dir(dir);
@@ -521,7 +521,7 @@ void test_reftable_stack__add(void)
 
 	for (i = 0; i < N; i++)
 		cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
-					     &refs[i]), 0);
+						     &refs[i], 0), 0);
 
 	for (i = 0; i < N; i++) {
 		struct write_log_arg arg = {
@@ -529,7 +529,7 @@ void test_reftable_stack__add(void)
 			.update_index = reftable_stack_next_update_index(st),
 		};
 		cl_assert_equal_i(reftable_stack_add(st, write_test_log,
-						     &arg), 0);
+						     &arg, 0), 0);
 	}
 
 	cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0);
@@ -612,8 +612,8 @@ void test_reftable_stack__iterator(void)
 	}
 
 	for (i = 0; i < N; i++)
-		cl_assert_equal_i(reftable_stack_add(st,
-						     write_test_ref, &refs[i]), 0);
+		cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+						     &refs[i], 0), 0);
 
 	for (i = 0; i < N; i++) {
 		struct write_log_arg arg = {
@@ -621,8 +621,8 @@ void test_reftable_stack__iterator(void)
 			.update_index = reftable_stack_next_update_index(st),
 		};
 
-		cl_assert_equal_i(reftable_stack_add(st,
-						     write_test_log, &arg), 0);
+		cl_assert_equal_i(reftable_stack_add(st, write_test_log,
+						     &arg, 0), 0);
 	}
 
 	reftable_stack_init_ref_iterator(st, &it);
@@ -697,11 +697,11 @@ void test_reftable_stack__log_normalize(void)
 
 	input.value.update.message = (char *) "one\ntwo";
 	cl_assert_equal_i(reftable_stack_add(st, write_test_log,
-					     &arg), REFTABLE_API_ERROR);
+					     &arg, 0), REFTABLE_API_ERROR);
 
 	input.value.update.message = (char *) "one";
 	cl_assert_equal_i(reftable_stack_add(st, write_test_log,
-					     &arg), 0);
+					     &arg, 0), 0);
 	cl_assert_equal_i(reftable_stack_read_log(st, input.refname,
 						  &dest), 0);
 	cl_assert_equal_s(dest.value.update.message, "one\n");
@@ -709,7 +709,7 @@ void test_reftable_stack__log_normalize(void)
 	input.value.update.message = (char *) "two\n";
 	arg.update_index = 2;
 	cl_assert_equal_i(reftable_stack_add(st, write_test_log,
-					     &arg), 0);
+					     &arg, 0), 0);
 	cl_assert_equal_i(reftable_stack_read_log(st, input.refname,
 						  &dest), 0);
 	cl_assert_equal_s(dest.value.update.message, "two\n");
@@ -759,15 +759,16 @@ void test_reftable_stack__tombstone(void)
 		}
 	}
 	for (i = 0; i < N; i++)
-		cl_assert_equal_i(reftable_stack_add(st, write_test_ref, &refs[i]), 0);
+		cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+						     &refs[i], 0), 0);
 
 	for (i = 0; i < N; i++) {
 		struct write_log_arg arg = {
 			.log = &logs[i],
 			.update_index = reftable_stack_next_update_index(st),
 		};
-		cl_assert_equal_i(reftable_stack_add(st,
-						     write_test_log, &arg), 0);
+		cl_assert_equal_i(reftable_stack_add(st, write_test_log,
+						     &arg, 0), 0);
 	}
 
 	cl_assert_equal_i(reftable_stack_read_ref(st, "branch",
@@ -815,7 +816,7 @@ void test_reftable_stack__hash_id(void)
 
 	cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
 	cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
-					     &ref), 0);
+					     &ref, 0), 0);
 
 	/* can't read it with the wrong hash ID. */
 	cl_assert_equal_i(reftable_new_stack(&st32, dir,
@@ -884,7 +885,7 @@ void test_reftable_stack__reflog_expire(void)
 			.update_index = reftable_stack_next_update_index(st),
 		};
 		cl_assert_equal_i(reftable_stack_add(st, write_test_log,
-						     &arg), 0);
+						     &arg, 0), 0);
 	}
 
 	cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0);
@@ -924,7 +925,7 @@ void test_reftable_stack__empty_add(void)
 
 	cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
 	cl_assert_equal_i(reftable_stack_add(st, write_nothing,
-					     NULL), 0);
+					     NULL, 0), 0);
 	cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0);
 	clear_dir(dir);
 	reftable_stack_destroy(st);
@@ -963,7 +964,7 @@ void test_reftable_stack__auto_compaction(void)
 		};
 		snprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i);
 
-		err = reftable_stack_add(st, write_test_ref, &ref);
+		err = reftable_stack_add(st, write_test_ref, &ref, 0);
 		cl_assert(!err);
 
 		err = reftable_stack_auto_compact(st);
@@ -999,7 +1000,7 @@ void test_reftable_stack__auto_compaction_factor(void)
 		};
 		xsnprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i);
 
-		err = reftable_stack_add(st, &write_test_ref, &ref);
+		err = reftable_stack_add(st, &write_test_ref, &ref, 0);
 		cl_assert(!err);
 
 		cl_assert(i < 5 || st->merged->tables_len < 5 * fastlogN(i, 5));
@@ -1066,6 +1067,7 @@ void test_reftable_stack__add_performs_auto_compaction(void)
 			.value_type = REFTABLE_REF_SYMREF,
 			.value.symref = (char *) "master",
 		};
+		bool required = false;
 		char buf[128];
 
 		/*
@@ -1078,18 +1080,25 @@ void test_reftable_stack__add_performs_auto_compaction(void)
 		snprintf(buf, sizeof(buf), "branch-%04"PRIuMAX, (uintmax_t)i);
 		ref.refname = buf;
 
-		cl_assert_equal_i(reftable_stack_add(st,
-						     write_test_ref, &ref), 0);
+		cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+						     &ref, 0), 0);
 
 		/*
 		 * The stack length should grow continuously for all runs where
 		 * auto compaction is disabled. When enabled, we should merge
 		 * all tables in the stack.
 		 */
-		if (i != n)
+		cl_assert_equal_i(reftable_stack_compaction_required(st, true, &required), 0);
+		if (i != n) {
 			cl_assert_equal_i(st->merged->tables_len, i + 1);
-		else
+			if (i < 1)
+				cl_assert_equal_b(required, false);
+			else
+				cl_assert_equal_b(required, true);
+		} else {
 			cl_assert_equal_i(st->merged->tables_len, 1);
+			cl_assert_equal_b(required, false);
+		}
 	}
 
 	reftable_stack_destroy(st);
diff --git a/t/unit-tests/u-string-list.c b/t/unit-tests/u-string-list.c
index d4ba5f9..a2457d7 100644
--- a/t/unit-tests/u-string-list.c
+++ b/t/unit-tests/u-string-list.c
@@ -43,7 +43,7 @@ static void t_string_list_equal(struct string_list *list,
 				  expected_strings->items[i].string);
 }
 
-static void t_string_list_split(const char *data, int delim, int maxsplit, ...)
+static void t_string_list_split(const char *data, const char *delim, int maxsplit, ...)
 {
 	struct string_list expected_strings = STRING_LIST_INIT_DUP;
 	struct string_list list = STRING_LIST_INIT_DUP;
@@ -63,15 +63,94 @@ static void t_string_list_split(const char *data, int delim, int maxsplit, ...)
 	string_list_clear(&list, 0);
 }
 
+static void t_string_list_split_f(const char *data, const char *delim,
+				  int maxsplit, unsigned flags, ...)
+{
+	struct string_list expected_strings = STRING_LIST_INIT_DUP;
+	struct string_list list = STRING_LIST_INIT_DUP;
+	va_list ap;
+	int len;
+
+	va_start(ap, flags);
+	t_vcreate_string_list_dup(&expected_strings, 0, ap);
+	va_end(ap);
+
+	string_list_clear(&list, 0);
+	len = string_list_split_f(&list, data, delim, maxsplit, flags);
+	cl_assert_equal_i(len, expected_strings.nr);
+	t_string_list_equal(&list, &expected_strings);
+
+	string_list_clear(&expected_strings, 0);
+	string_list_clear(&list, 0);
+}
+
+void test_string_list__split_f(void)
+{
+	t_string_list_split_f("::foo:bar:baz:", ":", -1, 0,
+			      "", "", "foo", "bar", "baz", "", NULL);
+	t_string_list_split_f(" foo:bar : baz", ":", -1, STRING_LIST_SPLIT_TRIM,
+			      "foo", "bar", "baz", NULL);
+	t_string_list_split_f("  a  b c  ", " ", 1, STRING_LIST_SPLIT_TRIM,
+			      "a", "b c", NULL);
+	t_string_list_split_f("::foo::bar:baz:", ":", -1, STRING_LIST_SPLIT_NONEMPTY,
+			      "foo", "bar", "baz", NULL);
+	t_string_list_split_f("foo:baz", ":", -1, STRING_LIST_SPLIT_NONEMPTY,
+			      "foo", "baz", NULL);
+	t_string_list_split_f("foo :: : baz", ":", -1,
+			      STRING_LIST_SPLIT_NONEMPTY | STRING_LIST_SPLIT_TRIM,
+			      "foo", "baz", NULL);
+}
+
+static void t_string_list_split_in_place_f(const char *data_, const char *delim,
+					   int maxsplit, unsigned flags, ...)
+{
+	struct string_list expected_strings = STRING_LIST_INIT_DUP;
+	struct string_list list = STRING_LIST_INIT_NODUP;
+	char *data = xstrdup(data_);
+	va_list ap;
+	int len;
+
+	va_start(ap, flags);
+	t_vcreate_string_list_dup(&expected_strings, 0, ap);
+	va_end(ap);
+
+	string_list_clear(&list, 0);
+	len = string_list_split_in_place_f(&list, data, delim, maxsplit, flags);
+	cl_assert_equal_i(len, expected_strings.nr);
+	t_string_list_equal(&list, &expected_strings);
+
+	free(data);
+	string_list_clear(&expected_strings, 0);
+	string_list_clear(&list, 0);
+}
+
+void test_string_list__split_in_place_f(void)
+{
+	t_string_list_split_in_place_f("::foo:bar:baz:", ":", -1, 0,
+				       "", "", "foo", "bar", "baz", "", NULL);
+	t_string_list_split_in_place_f(" foo:bar : baz", ":", -1, STRING_LIST_SPLIT_TRIM,
+				       "foo", "bar", "baz", NULL);
+	t_string_list_split_in_place_f("  a  b c  ", " ", 1, STRING_LIST_SPLIT_TRIM,
+				       "a", "b c", NULL);
+	t_string_list_split_in_place_f("::foo::bar:baz:", ":", -1,
+				       STRING_LIST_SPLIT_NONEMPTY,
+				       "foo", "bar", "baz", NULL);
+	t_string_list_split_in_place_f("foo:baz", ":", -1, STRING_LIST_SPLIT_NONEMPTY,
+				       "foo", "baz", NULL);
+	t_string_list_split_in_place_f("foo :: : baz", ":", -1,
+				       STRING_LIST_SPLIT_NONEMPTY | STRING_LIST_SPLIT_TRIM,
+				       "foo", "baz", NULL);
+}
+
 void test_string_list__split(void)
 {
-	t_string_list_split("foo:bar:baz", ':', -1, "foo", "bar", "baz", NULL);
-	t_string_list_split("foo:bar:baz", ':', 0, "foo:bar:baz", NULL);
-	t_string_list_split("foo:bar:baz", ':', 1, "foo", "bar:baz", NULL);
-	t_string_list_split("foo:bar:baz", ':', 2, "foo", "bar", "baz", NULL);
-	t_string_list_split("foo:bar:", ':', -1, "foo", "bar", "", NULL);
-	t_string_list_split("", ':', -1, "", NULL);
-	t_string_list_split(":", ':', -1, "", "", NULL);
+	t_string_list_split("foo:bar:baz", ":", -1, "foo", "bar", "baz", NULL);
+	t_string_list_split("foo:bar:baz", ":", 0, "foo:bar:baz", NULL);
+	t_string_list_split("foo:bar:baz", ":", 1, "foo", "bar:baz", NULL);
+	t_string_list_split("foo:bar:baz", ":", 2, "foo", "bar", "baz", NULL);
+	t_string_list_split("foo:bar:", ":", -1, "foo", "bar", "", NULL);
+	t_string_list_split("", ":", -1, "", NULL);
+	t_string_list_split(":", ":", -1, "", "", NULL);
 }
 
 static void t_string_list_split_in_place(const char *data, const char *delim,
diff --git a/t/unit-tests/u-utf8-width.c b/t/unit-tests/u-utf8-width.c
new file mode 100644
index 0000000..86e09c3
--- /dev/null
+++ b/t/unit-tests/u-utf8-width.c
@@ -0,0 +1,134 @@
+#include "unit-test.h"
+#include "utf8.h"
+#include "strbuf.h"
+
+/*
+ * Test utf8_strnwidth with various Chinese strings
+ * Chinese characters typically have a width of 2 columns when displayed
+ */
+void test_utf8_width__strnwidth_chinese(void)
+{
+	const char *str;
+
+	/* Test basic ASCII - each character should have width 1 */
+	cl_assert_equal_i(5, utf8_strnwidth("Hello", 5, 0));
+	/* skip_ansi = 1 */
+	cl_assert_equal_i(5, utf8_strnwidth("Hello", 5, 1));
+
+	/* Test simple Chinese characters - each should have width 2 */
+	/* "你好" is 6 bytes (3 bytes per char in UTF-8), 4 display columns */
+	cl_assert_equal_i(4, utf8_strnwidth("你好", 6, 0));
+
+	/* Test mixed ASCII and Chinese - ASCII = 1 column, Chinese = 2 columns */
+	/* "h"(1) + "i"(1) + "你"(2) + "好"(2) = 6 */
+	cl_assert_equal_i(6, utf8_strnwidth("Hi你好", 8, 0));
+
+	/* Test longer Chinese string */
+	/* 5 Chinese chars = 10 display columns */
+	cl_assert_equal_i(10, utf8_strnwidth("你好世界!", 15, 0));
+
+	/* Test individual Chinese character width */
+	cl_assert_equal_i(2, utf8_strnwidth("中", 3, 0));
+
+	/* Test empty string */
+	cl_assert_equal_i(0, utf8_strnwidth("", 0, 0));
+
+	/* Test length limiting */
+	str = "你好世界";
+	/* Only first char "你"(2 columns) within 3 bytes */
+	cl_assert_equal_i(2, utf8_strnwidth(str, 3, 0));
+	/* First two chars "你好"(4 columns) in 6 bytes */
+	cl_assert_equal_i(4, utf8_strnwidth(str, 6, 0));
+}
+
+/*
+ * Tests for utf8_strwidth (simpler version without length limit)
+ */
+void test_utf8_width__strwidth_chinese(void)
+{
+	/* Test basic ASCII */
+	cl_assert_equal_i(5, utf8_strwidth("Hello"));
+
+	/* Test Chinese characters */
+	/* 2 Chinese chars = 4 display columns */
+	cl_assert_equal_i(4, utf8_strwidth("你好"));
+
+	/* Test longer Chinese string */
+	/* 5 Chinese chars = 10 display columns */
+	cl_assert_equal_i(10, utf8_strwidth("你好世界!"));
+
+	/* Test mixed ASCII and Chinese */
+	/* 5 ASCII (5 cols) + 2 Chinese (4 cols) = 9 */
+	cl_assert_equal_i(9, utf8_strwidth("Hello世界"));
+	/* 2 ASCII (2 cols) + 2 Chinese (4 cols) + 1 ASCII (1 col) = 7 */
+	cl_assert_equal_i(7, utf8_strwidth("Hi世界!"));
+}
+
+/*
+ * Additional tests with other East Asian characters
+ */
+void test_utf8_width__strnwidth_japanese_korean(void)
+{
+	/* Japanese characters (should also be 2 columns each) */
+	/* 5 Japanese chars x 2 cols each = 10 display columns */
+	cl_assert_equal_i(10, utf8_strnwidth("こんにちは", 15, 0));
+
+	/* Korean characters (should also be 2 columns each) */
+	/* 5 Korean chars x 2 cols each = 10 display columns */
+	cl_assert_equal_i(10, utf8_strnwidth("안녕하세요", 15, 0));
+}
+
+/*
+ * Test utf8_strnwidth with CJK strings and ANSI sequences
+ */
+void test_utf8_width__strnwidth_cjk_with_ansi(void)
+{
+	/* Test CJK with ANSI sequences */
+	const char *ansi_test = "\033[1m你好\033[0m";
+	int width = utf8_strnwidth(ansi_test, strlen(ansi_test), 1);
+	/* Should skip ANSI sequences and count "你好" as 4 columns */
+	cl_assert_equal_i(4, width);
+
+	/* Test mixed ASCII, CJK, and ANSI */
+	ansi_test = "Hello\033[32m世界\033[0m!";
+	width = utf8_strnwidth(ansi_test, strlen(ansi_test), 1);
+	/* "Hello"(5) + "世界"(4) + "!"(1) = 10 */
+	cl_assert_equal_i(10, width);
+}
+
+/*
+ * Test the strbuf_utf8_align function with CJK characters
+ */
+void test_utf8_width__strbuf_utf8_align(void)
+{
+	struct strbuf buf = STRBUF_INIT;
+
+	/* Test left alignment with CJK */
+	strbuf_utf8_align(&buf, ALIGN_LEFT, 10, "你好");
+	/* Since "你好" is 4 display columns, we need 6 more spaces to reach 10 */
+	cl_assert_equal_s("你好      ", buf.buf);
+	strbuf_reset(&buf);
+
+	/* Test right alignment with CJK */
+	strbuf_utf8_align(&buf, ALIGN_RIGHT, 8, "世界");
+	/* "世界" is 4 display columns, so we need 4 leading spaces */
+	cl_assert_equal_s("    世界", buf.buf);
+	strbuf_reset(&buf);
+
+	/* Test center alignment with CJK */
+	strbuf_utf8_align(&buf, ALIGN_MIDDLE, 10, "中");
+	/* "中" is 2 display columns, so (10-2)/2 = 4 spaces on left, 4 on right */
+	cl_assert_equal_s("    中    ", buf.buf);
+	strbuf_reset(&buf);
+
+	strbuf_utf8_align(&buf, ALIGN_MIDDLE, 5, "中");
+	/* "中" is 2 display columns, so (5-2)/2 = 1 spaces on left, 2 on right */
+	cl_assert_equal_s(" 中  ", buf.buf);
+	strbuf_reset(&buf);
+
+	/* Test alignment that is smaller than string width */
+	strbuf_utf8_align(&buf, ALIGN_LEFT, 2, "你好");
+	/* Since "你好" is 4 display columns, it should not be truncated */
+	cl_assert_equal_s("你好", buf.buf);
+	strbuf_release(&buf);
+}
diff --git a/tag.c b/tag.c
index 1d52686..f5c232d 100644
--- a/tag.c
+++ b/tag.c
@@ -94,18 +94,6 @@ struct object *deref_tag(struct repository *r, struct object *o, const char *war
 	return o;
 }
 
-struct object *deref_tag_noverify(struct repository *r, struct object *o)
-{
-	while (o && o->type == OBJ_TAG) {
-		o = parse_object(r, &o->oid);
-		if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged)
-			o = ((struct tag *)o)->tagged;
-		else
-			o = NULL;
-	}
-	return o;
-}
-
 struct tag *lookup_tag(struct repository *r, const struct object_id *oid)
 {
 	struct object *obj = lookup_object(r, oid);
diff --git a/tag.h b/tag.h
index c49d7c1..ef12a61 100644
--- a/tag.h
+++ b/tag.h
@@ -16,7 +16,6 @@ int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, u
 int parse_tag(struct tag *item);
 void release_tag_memory(struct tag *t);
 struct object *deref_tag(struct repository *r, struct object *, const char *, int);
-struct object *deref_tag_noverify(struct repository *r, struct object *);
 int gpg_verify_tag(const struct object_id *oid,
 		   const char *name_to_report, unsigned flags);
 struct object_id *get_tagged_oid(struct tag *tag);
diff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c
index 22a99a0..bbcfeda 100644
--- a/trace2/tr2_cfg.c
+++ b/trace2/tr2_cfg.c
@@ -8,89 +8,65 @@
 #include "trace2/tr2_sysenv.h"
 #include "wildmatch.h"
 
-static struct strbuf **tr2_cfg_patterns;
-static int tr2_cfg_count_patterns;
+static struct string_list tr2_cfg_patterns = STRING_LIST_INIT_DUP;
 static int tr2_cfg_loaded;
 
-static struct strbuf **tr2_cfg_env_vars;
-static int tr2_cfg_env_vars_count;
+static struct string_list tr2_cfg_env_vars = STRING_LIST_INIT_DUP;
 static int tr2_cfg_env_vars_loaded;
 
 /*
  * Parse a string containing a comma-delimited list of config keys
- * or wildcard patterns into a list of strbufs.
+ * or wildcard patterns into a string list.
  */
-static int tr2_cfg_load_patterns(void)
+static size_t tr2_cfg_load_patterns(void)
 {
-	struct strbuf **s;
 	const char *envvar;
 
 	if (tr2_cfg_loaded)
-		return tr2_cfg_count_patterns;
+		return tr2_cfg_patterns.nr;
 	tr2_cfg_loaded = 1;
 
 	envvar = tr2_sysenv_get(TR2_SYSENV_CFG_PARAM);
 	if (!envvar || !*envvar)
-		return tr2_cfg_count_patterns;
+		return tr2_cfg_patterns.nr;
 
-	tr2_cfg_patterns = strbuf_split_buf(envvar, strlen(envvar), ',', -1);
-	for (s = tr2_cfg_patterns; *s; s++) {
-		struct strbuf *buf = *s;
-
-		if (buf->len && buf->buf[buf->len - 1] == ',')
-			strbuf_setlen(buf, buf->len - 1);
-		strbuf_trim_trailing_newline(*s);
-		strbuf_trim(*s);
-	}
-
-	tr2_cfg_count_patterns = s - tr2_cfg_patterns;
-	return tr2_cfg_count_patterns;
+	string_list_split_f(&tr2_cfg_patterns, envvar, ",", -1,
+			    STRING_LIST_SPLIT_TRIM);
+	return tr2_cfg_patterns.nr;
 }
 
 void tr2_cfg_free_patterns(void)
 {
-	if (tr2_cfg_patterns)
-		strbuf_list_free(tr2_cfg_patterns);
-	tr2_cfg_count_patterns = 0;
+	if (tr2_cfg_patterns.nr)
+		string_list_clear(&tr2_cfg_patterns, 0);
 	tr2_cfg_loaded = 0;
 }
 
 /*
  * Parse a string containing a comma-delimited list of environment variable
- * names into a list of strbufs.
+ * names into a string list.
  */
-static int tr2_load_env_vars(void)
+static size_t tr2_load_env_vars(void)
 {
-	struct strbuf **s;
 	const char *varlist;
 
 	if (tr2_cfg_env_vars_loaded)
-		return tr2_cfg_env_vars_count;
+		return tr2_cfg_env_vars.nr;
 	tr2_cfg_env_vars_loaded = 1;
 
 	varlist = tr2_sysenv_get(TR2_SYSENV_ENV_VARS);
 	if (!varlist || !*varlist)
-		return tr2_cfg_env_vars_count;
+		return tr2_cfg_env_vars.nr;
 
-	tr2_cfg_env_vars = strbuf_split_buf(varlist, strlen(varlist), ',', -1);
-	for (s = tr2_cfg_env_vars; *s; s++) {
-		struct strbuf *buf = *s;
-
-		if (buf->len && buf->buf[buf->len - 1] == ',')
-			strbuf_setlen(buf, buf->len - 1);
-		strbuf_trim_trailing_newline(*s);
-		strbuf_trim(*s);
-	}
-
-	tr2_cfg_env_vars_count = s - tr2_cfg_env_vars;
-	return tr2_cfg_env_vars_count;
+	string_list_split_f(&tr2_cfg_env_vars, varlist, ",", -1,
+			    STRING_LIST_SPLIT_TRIM);
+	return tr2_cfg_env_vars.nr;
 }
 
 void tr2_cfg_free_env_vars(void)
 {
-	if (tr2_cfg_env_vars)
-		strbuf_list_free(tr2_cfg_env_vars);
-	tr2_cfg_env_vars_count = 0;
+	if (tr2_cfg_env_vars.nr)
+		string_list_clear(&tr2_cfg_env_vars, 0);
 	tr2_cfg_env_vars_loaded = 0;
 }
 
@@ -105,12 +81,11 @@ struct tr2_cfg_data {
 static int tr2_cfg_cb(const char *key, const char *value,
 		      const struct config_context *ctx, void *d)
 {
-	struct strbuf **s;
+	struct string_list_item *item;
 	struct tr2_cfg_data *data = (struct tr2_cfg_data *)d;
 
-	for (s = tr2_cfg_patterns; *s; s++) {
-		struct strbuf *buf = *s;
-		int wm = wildmatch(buf->buf, key, WM_CASEFOLD);
+	for_each_string_list_item(item, &tr2_cfg_patterns) {
+		int wm = wildmatch(item->string, key, WM_CASEFOLD);
 		if (wm == WM_MATCH) {
 			trace2_def_param_fl(data->file, data->line, key, value,
 					    ctx->kvi);
@@ -132,17 +107,16 @@ void tr2_cfg_list_config_fl(const char *file, int line)
 void tr2_list_env_vars_fl(const char *file, int line)
 {
 	struct key_value_info kvi = KVI_INIT;
-	struct strbuf **s;
+	struct string_list_item *item;
 
 	kvi_from_param(&kvi);
 	if (tr2_load_env_vars() <= 0)
 		return;
 
-	for (s = tr2_cfg_env_vars; *s; s++) {
-		struct strbuf *buf = *s;
-		const char *val = getenv(buf->buf);
+	for_each_string_list_item(item, &tr2_cfg_env_vars) {
+		const char *val = getenv(item->string);
 		if (val && *val)
-			trace2_def_param_fl(file, line, buf->buf, val, &kvi);
+			trace2_def_param_fl(file, line, item->string, val, &kvi);
 	}
 }
 
diff --git a/transport-helper.c b/transport-helper.c
index 0789e5b..4d95d84 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -450,7 +450,7 @@ static int fetch_with_fetch(struct transport *transport,
 	}
 	strbuf_release(&buf);
 
-	reprepare_packed_git(the_repository);
+	odb_reprepare(the_repository->objects);
 	return 0;
 }
 
diff --git a/transport.c b/transport.c
index e305d6b..c7f06a7 100644
--- a/transport.c
+++ b/transport.c
@@ -30,7 +30,7 @@
 #include "color.h"
 #include "bundle-uri.h"
 
-static int transport_use_color = -1;
+static enum git_colorbool transport_use_color = GIT_COLOR_UNKNOWN;
 static char transport_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_RESET,
 	GIT_COLOR_RED		/* REJECTED */
@@ -1042,7 +1042,7 @@ static const struct string_list *protocol_allow_list(void)
 	if (enabled < 0) {
 		const char *v = getenv("GIT_ALLOW_PROTOCOL");
 		if (v) {
-			string_list_split(&allowed, v, ':', -1);
+			string_list_split(&allowed, v, ":", -1);
 			string_list_sort(&allowed);
 			enabled = 1;
 		} else {
diff --git a/tree-diff.c b/tree-diff.c
index e00fc2f..5988148 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -13,6 +13,7 @@
 #include "tree-walk.h"
 #include "environment.h"
 #include "repository.h"
+#include "dir.h"
 
 /*
  * Some mode bits are also used internally for computations.
@@ -48,6 +49,73 @@
 		free((x)); \
 } while(0)
 
+/* Returns true if and only if "dir" is a leading directory of "path" */
+static int is_dir_prefix(const char *path, const char *dir, int dirlen)
+{
+	return !strncmp(path, dir, dirlen) &&
+		(!path[dirlen] || path[dirlen] == '/');
+}
+
+static int check_recursion_depth(const struct strbuf *name,
+				 const struct pathspec *ps,
+				 int max_depth)
+{
+	int i;
+
+	if (!ps->nr)
+		return within_depth(name->buf, name->len, 1, max_depth);
+
+	/*
+	 * We look through the pathspecs in reverse-sorted order, because we
+	 * want to find the longest match first (e.g., "a/b" is better for
+	 * checking depth than "a/b/c").
+	 */
+	for (i = ps->nr - 1; i >= 0; i--) {
+		const struct pathspec_item *item = ps->items+i;
+
+		/*
+		 * If the name to match is longer than the pathspec, then we
+		 * are only interested if the pathspec matches and we are
+		 * within the allowed depth.
+		 */
+		if (name->len >= item->len) {
+			if (!is_dir_prefix(name->buf, item->match, item->len))
+				continue;
+			return within_depth(name->buf + item->len,
+					    name->len - item->len,
+					    1, max_depth);
+		}
+
+		/*
+		 * Otherwise, our name is shorter than the pathspec. We need to
+		 * check if it is a prefix of the pathspec; if so, we must
+		 * always recurse in order to process further (the resulting
+		 * paths we find might or might not match our pathspec, but we
+		 * cannot know until we recurse).
+		 */
+		if (is_dir_prefix(item->match, name->buf, name->len))
+			return 1;
+	}
+	return 0;
+}
+
+static int should_recurse(const struct strbuf *name, struct diff_options *opt)
+{
+	if (!opt->flags.recursive)
+		return 0;
+	if (!opt->max_depth_valid)
+		return 1;
+
+	/*
+	 * We catch this during diff_setup_done, but let's double-check
+	 * against any internal munging.
+	 */
+	if (opt->pathspec.has_wildcard)
+		BUG("wildcard pathspecs are incompatible with max-depth");
+
+	return check_recursion_depth(name, &opt->pathspec, opt->max_depth);
+}
+
 static void ll_diff_tree_paths(
 	struct combine_diff_path ***tail, const struct object_id *oid,
 	const struct object_id **parents_oid, int nparent,
@@ -170,9 +238,13 @@ static void emit_path(struct combine_diff_path ***tail,
 		mode = 0;
 	}
 
-	if (opt->flags.recursive && isdir) {
-		recurse = 1;
-		emitthis = opt->flags.tree_in_recursive;
+	if (isdir) {
+		strbuf_add(base, path, pathlen);
+		if (should_recurse(base, opt)) {
+			recurse = 1;
+			emitthis = opt->flags.tree_in_recursive;
+		}
+		strbuf_setlen(base, old_baselen);
 	}
 
 	if (emitthis) {
diff --git a/upload-pack.c b/upload-pack.c
index 9b9b149..2d2b70c 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -870,8 +870,8 @@ static void send_unshallow(struct upload_pack_data *data)
 	}
 }
 
-static int check_ref(const char *refname_full, const char *referent UNUSED, const struct object_id *oid,
-		     int flag, void *cb_data);
+static int check_ref(const struct reference *ref, void *cb_data);
+
 static void deepen(struct upload_pack_data *data, int depth)
 {
 	if (depth == INFINITE_DEPTH && !is_repository_shallow(the_repository)) {
@@ -913,13 +913,12 @@ static void deepen(struct upload_pack_data *data, int depth)
 }
 
 static void deepen_by_rev_list(struct upload_pack_data *data,
-			       int ac,
-			       const char **av)
+			       struct strvec *argv)
 {
 	struct commit_list *result;
 
 	disable_commit_graph(the_repository);
-	result = get_shallow_commits_by_rev_list(ac, av, SHALLOW, NOT_SHALLOW);
+	result = get_shallow_commits_by_rev_list(argv, SHALLOW, NOT_SHALLOW);
 	send_shallow(data, result);
 	free_commit_list(result);
 	send_unshallow(data);
@@ -955,7 +954,7 @@ static int send_shallow_list(struct upload_pack_data *data)
 			struct object *o = data->want_obj.objects[i].item;
 			strvec_push(&av, oid_to_hex(&o->oid));
 		}
-		deepen_by_rev_list(data, av.nr, av.v);
+		deepen_by_rev_list(data, &av);
 		strvec_clear(&av);
 		ret = 1;
 	} else {
@@ -1225,13 +1224,12 @@ static int mark_our_ref(const char *refname, const char *refname_full,
 	return 0;
 }
 
-static int check_ref(const char *refname_full, const char *referent UNUSED,const struct object_id *oid,
-		     int flag UNUSED, void *cb_data)
+static int check_ref(const struct reference *ref, void *cb_data)
 {
-	const char *refname = strip_namespace(refname_full);
+	const char *refname = strip_namespace(ref->name);
 	struct upload_pack_data *data = cb_data;
 
-	mark_our_ref(refname, refname_full, oid, &data->hidden_refs);
+	mark_our_ref(refname, ref->name, ref->oid, &data->hidden_refs);
 	return 0;
 }
 
@@ -1251,15 +1249,15 @@ static void format_session_id(struct strbuf *buf, struct upload_pack_data *d) {
 }
 
 static void write_v0_ref(struct upload_pack_data *data,
-			const char *refname, const char *refname_nons,
-			const struct object_id *oid)
+			 const struct reference *ref,
+			 const char *refname_nons)
 {
 	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";
 	struct object_id peeled;
 
-	if (mark_our_ref(refname_nons, refname, oid, &data->hidden_refs))
+	if (mark_our_ref(refname_nons, ref->name, ref->oid, &data->hidden_refs))
 		return;
 
 	if (capabilities) {
@@ -1269,7 +1267,7 @@ static void write_v0_ref(struct upload_pack_data *data,
 		format_symref_info(&symref_info, &data->symref);
 		format_session_id(&session_id, data);
 		packet_fwrite_fmt(stdout, "%s %s%c%s%s%s%s%s%s%s object-format=%s agent=%s\n",
-			     oid_to_hex(oid), refname_nons,
+			     oid_to_hex(ref->oid), refname_nons,
 			     0, capabilities,
 			     (data->allow_uor & ALLOW_TIP_SHA1) ?
 				     " allow-tip-sha1-in-want" : "",
@@ -1285,35 +1283,33 @@ static void write_v0_ref(struct upload_pack_data *data,
 		strbuf_release(&session_id);
 		data->sent_capabilities = 1;
 	} else {
-		packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons);
+		packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(ref->oid), refname_nons);
 	}
 	capabilities = NULL;
-	if (!peel_iterated_oid(the_repository, oid, &peeled))
+	if (!reference_get_peeled_oid(the_repository, ref, &peeled))
 		packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
 	return;
 }
 
-static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
-		    int flag UNUSED, void *cb_data)
+static int send_ref(const struct reference *ref, void *cb_data)
 {
-	write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
+	write_v0_ref(cb_data, ref, strip_namespace(ref->name));
 	return 0;
 }
 
-static int find_symref(const char *refname, const char *referent UNUSED,
-		       const struct object_id *oid UNUSED,
-		       int flag, void *cb_data)
+static int find_symref(const struct reference *ref, void *cb_data)
 {
 	const char *symref_target;
 	struct string_list_item *item;
+	int flag;
 
-	if ((flag & REF_ISSYMREF) == 0)
+	if ((ref->flags & REF_ISSYMREF) == 0)
 		return 0;
 	symref_target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
-						refname, 0, NULL, &flag);
+						ref->name, 0, NULL, &flag);
 	if (!symref_target || (flag & REF_ISSYMREF) == 0)
-		die("'%s' is a symref but it is not?", refname);
-	item = string_list_append(cb_data, strip_namespace(refname));
+		die("'%s' is a symref but it is not?", ref->name);
+	item = string_list_append(cb_data, strip_namespace(ref->name));
 	item->util = xstrdup(strip_namespace(symref_target));
 	return 0;
 }
@@ -1446,8 +1442,12 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
 					 send_ref, &data);
 		for_each_namespaced_ref_1(send_ref, &data);
 		if (!data.sent_capabilities) {
-			const char *refname = "capabilities^{}";
-			write_v0_ref(&data, refname, refname, null_oid(the_hash_algo));
+			struct reference ref = {
+				.name = "capabilities^{}",
+				.oid = null_oid(the_hash_algo),
+			};
+
+			write_v0_ref(&data, &ref, ref.name);
 		}
 		/*
 		 * fflush stdout before calling advertise_shallow_grafts because send_ref
@@ -1684,7 +1684,7 @@ static void process_args(struct packet_reader *request,
 			if (data->uri_protocols.nr)
 				send_err_and_die(data,
 						 "multiple packfile-uris lines forbidden");
-			string_list_split(&data->uri_protocols, p, ',', -1);
+			string_list_split(&data->uri_protocols, p, ",", -1);
 			continue;
 		}
 
diff --git a/usage.c b/usage.c
index 7545a61..527edb1 100644
--- a/usage.c
+++ b/usage.c
@@ -193,7 +193,8 @@ static void show_usage_if_asked_helper(const char *err, ...)
 
 void show_usage_if_asked(int ac, const char **av, const char *err)
 {
-	if (ac == 2 && !strcmp(av[1], "-h"))
+	if (ac == 2 && (!strcmp(av[1], "-h") ||
+			!strcmp(av[1], "--help-all")))
 		show_usage_if_asked_helper(err);
 }
 
diff --git a/varint.c b/varint.c
index 409c497..03cd544 100644
--- a/varint.c
+++ b/varint.c
@@ -1,11 +1,11 @@
 #include "git-compat-util.h"
 #include "varint.h"
 
-uintmax_t decode_varint(const unsigned char **bufp)
+uint64_t decode_varint(const unsigned char **bufp)
 {
 	const unsigned char *buf = *bufp;
 	unsigned char c = *buf++;
-	uintmax_t val = c & 127;
+	uint64_t val = c & 127;
 	while (c & 128) {
 		val += 1;
 		if (!val || MSB(val, 7))
@@ -17,7 +17,7 @@ uintmax_t decode_varint(const unsigned char **bufp)
 	return val;
 }
 
-int encode_varint(uintmax_t value, unsigned char *buf)
+uint8_t encode_varint(uint64_t value, unsigned char *buf)
 {
 	unsigned char varint[16];
 	unsigned pos = sizeof(varint) - 1;
diff --git a/varint.h b/varint.h
index f78bb0c..eb40193 100644
--- a/varint.h
+++ b/varint.h
@@ -1,7 +1,7 @@
 #ifndef VARINT_H
 #define VARINT_H
 
-int encode_varint(uintmax_t, unsigned char *);
-uintmax_t decode_varint(const unsigned char **);
+uint8_t encode_varint(uint64_t, unsigned char *);
+uint64_t decode_varint(const unsigned char **);
 
 #endif /* VARINT_H */
diff --git a/walker.c b/walker.c
index 8073754..409b646 100644
--- a/walker.c
+++ b/walker.c
@@ -226,14 +226,10 @@ static int interpret_target(struct walker *walker, char *target, struct object_i
 	return -1;
 }
 
-static int mark_complete(const char *path UNUSED,
-			const char *referent UNUSED,
-			 const struct object_id *oid,
-			 int flag UNUSED,
-			 void *cb_data UNUSED)
+static int mark_complete(const struct reference *ref, void *cb_data UNUSED)
 {
 	struct commit *commit = lookup_commit_reference_gently(the_repository,
-							       oid, 1);
+							       ref->oid, 1);
 
 	if (commit) {
 		commit->object.flags |= COMPLETE;
diff --git a/worktree.c b/worktree.c
index a2a5f51..9308389 100644
--- a/worktree.c
+++ b/worktree.c
@@ -595,8 +595,15 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
 		if (refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
 					    refname.buf,
 					    RESOLVE_REF_READING,
-					    &oid, &flag))
-			ret = fn(refname.buf, NULL, &oid, flag, cb_data);
+					    &oid, &flag)) {
+			struct reference ref = {
+				.name = refname.buf,
+				.oid = &oid,
+				.flags = flag,
+			};
+
+			ret = fn(&ref, cb_data);
+		}
 		if (ret)
 			break;
 	}
diff --git a/wrapper.c b/wrapper.c
index 2f00d2a..3d507d4 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -721,6 +721,19 @@ int xgethostname(char *buf, size_t len)
 	return ret;
 }
 
+int is_missing_file(const char *filename)
+{
+	struct stat st;
+
+	if (stat(filename, &st) < 0) {
+		if (errno == ENOENT)
+			return 1;
+		die_errno(_("could not stat %s"), filename);
+	}
+
+	return 0;
+}
+
 int is_empty_or_missing_file(const char *filename)
 {
 	struct stat st;
diff --git a/wrapper.h b/wrapper.h
index 7df824e..44a8597 100644
--- a/wrapper.h
+++ b/wrapper.h
@@ -66,7 +66,9 @@ void write_file_buf(const char *path, const char *buf, size_t len);
 __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. */
+/* Return 1 if the file does not exist, 0 otherwise. */
+int is_missing_file(const char *filename);
+/* Return 1 if the file is empty or does not exist, 0 otherwise. */
 int is_empty_or_missing_file(const char *filename);
 
 enum fsync_action {
diff --git a/wt-status.c b/wt-status.c
index d6917f0..e12adb2 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -148,7 +148,7 @@ void wt_status_prepare(struct repository *r, struct wt_status *s)
 	memcpy(s->color_palette, default_wt_status_colors,
 	       sizeof(default_wt_status_colors));
 	s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
-	s->use_color = -1;
+	s->use_color = GIT_COLOR_UNKNOWN;
 	s->relative_paths = 1;
 	s->branch = refs_resolve_refdup(get_main_ref_store(the_repository),
 					"HEAD", 0, NULL, NULL);
@@ -972,7 +972,8 @@ static void wt_longstatus_print_changed(struct wt_status *s)
 	wt_longstatus_print_trailer(s);
 }
 
-static int stash_count_refs(struct object_id *ooid UNUSED,
+static int stash_count_refs(const char *refname UNUSED,
+			    struct object_id *ooid UNUSED,
 			    struct object_id *noid UNUSED,
 			    const char *email UNUSED,
 			    timestamp_t timestamp UNUSED, int tz UNUSED,
@@ -1164,7 +1165,7 @@ static void wt_longstatus_print_verbose(struct wt_status *s)
 	 * before.
 	 */
 	if (s->fp != stdout) {
-		rev.diffopt.use_color = 0;
+		rev.diffopt.use_color = GIT_COLOR_NEVER;
 		wt_status_add_cut_line(s);
 	}
 	if (s->verbose > 1 && s->committable) {
@@ -1351,8 +1352,8 @@ static int split_commit_in_progress(struct wt_status *s)
  */
 static void abbrev_oid_in_line(struct strbuf *line)
 {
-	struct strbuf **split;
-	int i;
+	struct string_list split = STRING_LIST_INIT_DUP;
+	struct object_id oid;
 
 	if (starts_with(line->buf, "exec ") ||
 	    starts_with(line->buf, "x ") ||
@@ -1360,26 +1361,15 @@ static void abbrev_oid_in_line(struct strbuf *line)
 	    starts_with(line->buf, "l "))
 		return;
 
-	split = strbuf_split_max(line, ' ', 3);
-	if (split[0] && split[1]) {
-		struct object_id oid;
-
-		/*
-		 * strbuf_split_max left a space. Trim it and re-add
-		 * it after abbreviation.
-		 */
-		strbuf_trim(split[1]);
-		if (!repo_get_oid(the_repository, split[1]->buf, &oid)) {
-			strbuf_reset(split[1]);
-			strbuf_add_unique_abbrev(split[1], &oid,
-						 DEFAULT_ABBREV);
-			strbuf_addch(split[1], ' ');
-			strbuf_reset(line);
-			for (i = 0; split[i]; i++)
-				strbuf_addbuf(line, split[i]);
-		}
+	if ((2 <= string_list_split(&split, line->buf, " ", 2)) &&
+	    !repo_get_oid(the_repository, split.items[1].string, &oid)) {
+		strbuf_reset(line);
+		strbuf_addf(line, "%s ", split.items[0].string);
+		strbuf_add_unique_abbrev(line, &oid, DEFAULT_ABBREV);
+		for (size_t i = 2; i < split.nr; i++)
+			strbuf_addf(line, " %s", split.items[i].string);
 	}
-	strbuf_list_free(split);
+	string_list_clear(&split, 0);
 }
 
 static int read_rebase_todolist(const char *fname, struct string_list *lines)
@@ -1664,7 +1654,8 @@ struct grab_1st_switch_cbdata {
 	struct object_id noid;
 };
 
-static int grab_1st_switch(struct object_id *ooid UNUSED,
+static int grab_1st_switch(const char *refname UNUSED,
+			   struct object_id *ooid UNUSED,
 			   struct object_id *noid,
 			   const char *email UNUSED,
 			   timestamp_t timestamp UNUSED, int tz UNUSED,
@@ -2164,7 +2155,7 @@ static void wt_shortstatus_print(struct wt_status *s)
 
 static void wt_porcelain_print(struct wt_status *s)
 {
-	s->use_color = 0;
+	s->use_color = GIT_COLOR_NEVER;
 	s->relative_paths = 0;
 	s->prefix = NULL;
 	s->no_gettext = 1;
diff --git a/wt-status.h b/wt-status.h
index 4e377ce..e40a272 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -111,7 +111,7 @@ struct wt_status {
 	int amend;
 	enum commit_whence whence;
 	int nowarn;
-	int use_color;
+	enum git_colorbool use_color;
 	int no_gettext;
 	int display_comment_prefix;
 	int relative_paths;
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index 5a96e36..6f3998e 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -22,6 +22,11 @@
 
 #include "xinclude.h"
 
+static unsigned long get_hash(xdfile_t *xdf, long index)
+{
+	return xdf->recs[xdf->rindex[index]].ha;
+}
+
 #define XDL_MAX_COST_MIN 256
 #define XDL_HEUR_MIN_COST 256
 #define XDL_LINE_MAX (long)((1UL << (CHAR_BIT * sizeof(long) - 1)) - 1)
@@ -42,8 +47,8 @@ typedef struct s_xdpsplit {
  * using this algorithm, so a little bit of heuristic is needed to cut the
  * search and to return a suboptimal point.
  */
-static long xdl_split(unsigned long const *ha1, long off1, long lim1,
-		      unsigned long const *ha2, long off2, long lim2,
+static long xdl_split(xdfile_t *xdf1, long off1, long lim1,
+		      xdfile_t *xdf2, long off2, long lim2,
 		      long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl,
 		      xdalgoenv_t *xenv) {
 	long dmin = off1 - lim2, dmax = lim1 - off2;
@@ -87,7 +92,7 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
 				i1 = kvdf[d + 1];
 			prev1 = i1;
 			i2 = i1 - d;
-			for (; i1 < lim1 && i2 < lim2 && ha1[i1] == ha2[i2]; i1++, i2++);
+			for (; i1 < lim1 && i2 < lim2 && get_hash(xdf1, i1) == get_hash(xdf2, i2); i1++, i2++);
 			if (i1 - prev1 > xenv->snake_cnt)
 				got_snake = 1;
 			kvdf[d] = i1;
@@ -124,7 +129,7 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
 				i1 = kvdb[d + 1] - 1;
 			prev1 = i1;
 			i2 = i1 - d;
-			for (; i1 > off1 && i2 > off2 && ha1[i1 - 1] == ha2[i2 - 1]; i1--, i2--);
+			for (; i1 > off1 && i2 > off2 && get_hash(xdf1, i1 - 1) == get_hash(xdf2, i2 - 1); i1--, i2--);
 			if (prev1 - i1 > xenv->snake_cnt)
 				got_snake = 1;
 			kvdb[d] = i1;
@@ -159,7 +164,7 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
 				if (v > XDL_K_HEUR * ec && v > best &&
 				    off1 + xenv->snake_cnt <= i1 && i1 < lim1 &&
 				    off2 + xenv->snake_cnt <= i2 && i2 < lim2) {
-					for (k = 1; ha1[i1 - k] == ha2[i2 - k]; k++)
+					for (k = 1; get_hash(xdf1, i1 - k) == get_hash(xdf2, i2 - k); k++)
 						if (k == xenv->snake_cnt) {
 							best = v;
 							spl->i1 = i1;
@@ -183,7 +188,7 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
 				if (v > XDL_K_HEUR * ec && v > best &&
 				    off1 < i1 && i1 <= lim1 - xenv->snake_cnt &&
 				    off2 < i2 && i2 <= lim2 - xenv->snake_cnt) {
-					for (k = 0; ha1[i1 + k] == ha2[i2 + k]; k++)
+					for (k = 0; get_hash(xdf1, i1 + k) == get_hash(xdf2, i2 + k); k++)
 						if (k == xenv->snake_cnt - 1) {
 							best = v;
 							spl->i1 = i1;
@@ -257,33 +262,26 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
  * sub-boxes by calling the box splitting function. Note that the real job
  * (marking changed lines) is done in the two boundary reaching checks.
  */
-int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
-		 diffdata_t *dd2, long off2, long lim2,
+int xdl_recs_cmp(xdfile_t *xdf1, long off1, long lim1,
+		 xdfile_t *xdf2, long off2, long lim2,
 		 long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv) {
-	unsigned long const *ha1 = dd1->ha, *ha2 = dd2->ha;
 
 	/*
 	 * Shrink the box by walking through each diagonal snake (SW and NE).
 	 */
-	for (; off1 < lim1 && off2 < lim2 && ha1[off1] == ha2[off2]; off1++, off2++);
-	for (; off1 < lim1 && off2 < lim2 && ha1[lim1 - 1] == ha2[lim2 - 1]; lim1--, lim2--);
+	for (; off1 < lim1 && off2 < lim2 && get_hash(xdf1, off1) == get_hash(xdf2, off2); off1++, off2++);
+	for (; off1 < lim1 && off2 < lim2 && get_hash(xdf1, lim1 - 1) == get_hash(xdf2, lim2 - 1); lim1--, lim2--);
 
 	/*
 	 * If one dimension is empty, then all records on the other one must
 	 * be obviously changed.
 	 */
 	if (off1 == lim1) {
-		char *rchg2 = dd2->rchg;
-		long *rindex2 = dd2->rindex;
-
 		for (; off2 < lim2; off2++)
-			rchg2[rindex2[off2]] = 1;
+			xdf2->changed[xdf2->rindex[off2]] = true;
 	} else if (off2 == lim2) {
-		char *rchg1 = dd1->rchg;
-		long *rindex1 = dd1->rindex;
-
 		for (; off1 < lim1; off1++)
-			rchg1[rindex1[off1]] = 1;
+			xdf1->changed[xdf1->rindex[off1]] = true;
 	} else {
 		xdpsplit_t spl;
 		spl.i1 = spl.i2 = 0;
@@ -291,7 +289,7 @@ int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
 		/*
 		 * Divide ...
 		 */
-		if (xdl_split(ha1, off1, lim1, ha2, off2, lim2, kvdf, kvdb,
+		if (xdl_split(xdf1, off1, lim1, xdf2, off2, lim2, kvdf, kvdb,
 			      need_min, &spl, xenv) < 0) {
 
 			return -1;
@@ -300,9 +298,9 @@ int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
 		/*
 		 * ... et Impera.
 		 */
-		if (xdl_recs_cmp(dd1, off1, spl.i1, dd2, off2, spl.i2,
+		if (xdl_recs_cmp(xdf1, off1, spl.i1, xdf2, off2, spl.i2,
 				 kvdf, kvdb, spl.min_lo, xenv) < 0 ||
-		    xdl_recs_cmp(dd1, spl.i1, lim1, dd2, spl.i2, lim2,
+		    xdl_recs_cmp(xdf1, spl.i1, lim1, xdf2, spl.i2, lim2,
 				 kvdf, kvdb, spl.min_hi, xenv) < 0) {
 
 			return -1;
@@ -318,7 +316,6 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 	long ndiags;
 	long *kvd, *kvdf, *kvdb;
 	xdalgoenv_t xenv;
-	diffdata_t dd1, dd2;
 	int res;
 
 	if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0)
@@ -357,16 +354,7 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 	xenv.snake_cnt = XDL_SNAKE_CNT;
 	xenv.heur_min = XDL_HEUR_MIN_COST;
 
-	dd1.nrec = xe->xdf1.nreff;
-	dd1.ha = xe->xdf1.ha;
-	dd1.rchg = xe->xdf1.rchg;
-	dd1.rindex = xe->xdf1.rindex;
-	dd2.nrec = xe->xdf2.nreff;
-	dd2.ha = xe->xdf2.ha;
-	dd2.rchg = xe->xdf2.rchg;
-	dd2.rindex = xe->xdf2.rindex;
-
-	res = xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
+	res = xdl_recs_cmp(&xe->xdf1, 0, xe->xdf1.nreff, &xe->xdf2, 0, xe->xdf2.nreff,
 			   kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0,
 			   &xenv);
 	xdl_free(kvd);
@@ -501,13 +489,13 @@ static void measure_split(const xdfile_t *xdf, long split,
 		m->indent = -1;
 	} else {
 		m->end_of_file = 0;
-		m->indent = get_indent(xdf->recs[split]);
+		m->indent = get_indent(&xdf->recs[split]);
 	}
 
 	m->pre_blank = 0;
 	m->pre_indent = -1;
 	for (i = split - 1; i >= 0; i--) {
-		m->pre_indent = get_indent(xdf->recs[i]);
+		m->pre_indent = get_indent(&xdf->recs[i]);
 		if (m->pre_indent != -1)
 			break;
 		m->pre_blank += 1;
@@ -520,7 +508,7 @@ static void measure_split(const xdfile_t *xdf, long split,
 	m->post_blank = 0;
 	m->post_indent = -1;
 	for (i = split + 1; i < xdf->nrec; i++) {
-		m->post_indent = get_indent(xdf->recs[i]);
+		m->post_indent = get_indent(&xdf->recs[i]);
 		if (m->post_indent != -1)
 			break;
 		m->post_blank += 1;
@@ -720,7 +708,7 @@ struct xdlgroup {
 static void group_init(xdfile_t *xdf, struct xdlgroup *g)
 {
 	g->start = g->end = 0;
-	while (xdf->rchg[g->end])
+	while (xdf->changed[g->end])
 		g->end++;
 }
 
@@ -734,7 +722,7 @@ static inline int group_next(xdfile_t *xdf, struct xdlgroup *g)
 		return -1;
 
 	g->start = g->end + 1;
-	for (g->end = g->start; xdf->rchg[g->end]; g->end++)
+	for (g->end = g->start; xdf->changed[g->end]; g->end++)
 		;
 
 	return 0;
@@ -750,7 +738,7 @@ static inline int group_previous(xdfile_t *xdf, struct xdlgroup *g)
 		return -1;
 
 	g->end = g->start - 1;
-	for (g->start = g->end; xdf->rchg[g->start - 1]; g->start--)
+	for (g->start = g->end; xdf->changed[g->start - 1]; g->start--)
 		;
 
 	return 0;
@@ -764,11 +752,11 @@ static inline int group_previous(xdfile_t *xdf, struct xdlgroup *g)
 static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g)
 {
 	if (g->end < xdf->nrec &&
-	    recs_match(xdf->recs[g->start], xdf->recs[g->end])) {
-		xdf->rchg[g->start++] = 0;
-		xdf->rchg[g->end++] = 1;
+	    recs_match(&xdf->recs[g->start], &xdf->recs[g->end])) {
+		xdf->changed[g->start++] = false;
+		xdf->changed[g->end++] = true;
 
-		while (xdf->rchg[g->end])
+		while (xdf->changed[g->end])
 			g->end++;
 
 		return 0;
@@ -785,11 +773,11 @@ static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g)
 static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g)
 {
 	if (g->start > 0 &&
-	    recs_match(xdf->recs[g->start - 1], xdf->recs[g->end - 1])) {
-		xdf->rchg[--g->start] = 1;
-		xdf->rchg[--g->end] = 0;
+	    recs_match(&xdf->recs[g->start - 1], &xdf->recs[g->end - 1])) {
+		xdf->changed[--g->start] = true;
+		xdf->changed[--g->end] = false;
 
-		while (xdf->rchg[g->start - 1])
+		while (xdf->changed[g->start - 1])
 			g->start--;
 
 		return 0;
@@ -944,16 +932,16 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
 
 int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr) {
 	xdchange_t *cscr = NULL, *xch;
-	char *rchg1 = xe->xdf1.rchg, *rchg2 = xe->xdf2.rchg;
+	bool *changed1 = xe->xdf1.changed, *changed2 = xe->xdf2.changed;
 	long i1, i2, l1, l2;
 
 	/*
 	 * Trivial. Collects "groups" of changes and creates an edit script.
 	 */
 	for (i1 = xe->xdf1.nrec, i2 = xe->xdf2.nrec; i1 >= 0 || i2 >= 0; i1--, i2--)
-		if (rchg1[i1 - 1] || rchg2[i2 - 1]) {
-			for (l1 = i1; rchg1[i1 - 1]; i1--);
-			for (l2 = i2; rchg2[i2 - 1]; i2--);
+		if (changed1[i1 - 1] || changed2[i2 - 1]) {
+			for (l1 = i1; changed1[i1 - 1]; i1--);
+			for (l2 = i2; changed2[i2 - 1]; i2--);
 
 			if (!(xch = xdl_add_change(cscr, i1, i2, l1 - i1, l2 - i2))) {
 				xdl_free_script(cscr);
@@ -1000,16 +988,16 @@ static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long flags)
 
 	for (xch = xscr; xch; xch = xch->next) {
 		int ignore = 1;
-		xrecord_t **rec;
+		xrecord_t *rec;
 		long i;
 
 		rec = &xe->xdf1.recs[xch->i1];
 		for (i = 0; i < xch->chg1 && ignore; i++)
-			ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags);
+			ignore = xdl_blankline(rec[i].ptr, rec[i].size, flags);
 
 		rec = &xe->xdf2.recs[xch->i2];
 		for (i = 0; i < xch->chg2 && ignore; i++)
-			ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags);
+			ignore = xdl_blankline(rec[i].ptr, rec[i].size, flags);
 
 		xch->ignore = ignore;
 	}
@@ -1033,7 +1021,7 @@ static void xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe,
 	xdchange_t *xch;
 
 	for (xch = xscr; xch; xch = xch->next) {
-		xrecord_t **rec;
+		xrecord_t *rec;
 		int ignore = 1;
 		long i;
 
@@ -1045,11 +1033,11 @@ static void xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe,
 
 		rec = &xe->xdf1.recs[xch->i1];
 		for (i = 0; i < xch->chg1 && ignore; i++)
-			ignore = record_matches_regex(rec[i], xpp);
+			ignore = record_matches_regex(&rec[i], xpp);
 
 		rec = &xe->xdf2.recs[xch->i2];
 		for (i = 0; i < xch->chg2 && ignore; i++)
-			ignore = record_matches_regex(rec[i], xpp);
+			ignore = record_matches_regex(&rec[i], xpp);
 
 		xch->ignore = ignore;
 	}
diff --git a/xdiff/xdiffi.h b/xdiff/xdiffi.h
index 126c9d8..49e52c6 100644
--- a/xdiff/xdiffi.h
+++ b/xdiff/xdiffi.h
@@ -24,13 +24,6 @@
 #define XDIFFI_H
 
 
-typedef struct s_diffdata {
-	long nrec;
-	unsigned long const *ha;
-	long *rindex;
-	char *rchg;
-} diffdata_t;
-
 typedef struct s_xdalgoenv {
 	long mxcost;
 	long snake_cnt;
@@ -46,8 +39,8 @@ typedef struct s_xdchange {
 
 
 
-int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
-		 diffdata_t *dd2, long off2, long lim2,
+int xdl_recs_cmp(xdfile_t *xdf1, long off1, long lim1,
+		 xdfile_t *xdf2, long off2, long lim2,
 		 long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv);
 int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 		xdfenv_t *xe);
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index 1d40c9c..b2f1f30 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -22,23 +22,13 @@
 
 #include "xinclude.h"
 
-static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) {
 
-	*rec = xdf->recs[ri]->ptr;
+static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb)
+{
+	xrecord_t *rec = &xdf->recs[ri];
 
-	return xdf->recs[ri]->size;
-}
-
-
-static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb) {
-	long size, psize = strlen(pre);
-	char const *rec;
-
-	size = xdl_get_rec(xdf, ri, &rec);
-	if (xdl_emit_diffrec(rec, size, pre, psize, ecb) < 0) {
-
+	if (xdl_emit_diffrec(rec->ptr, rec->size, pre, strlen(pre), ecb) < 0)
 		return -1;
-	}
 
 	return 0;
 }
@@ -120,11 +110,11 @@ static long def_ff(const char *rec, long len, char *buf, long sz)
 static long match_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri,
 			   char *buf, long sz)
 {
-	const char *rec;
-	long len = xdl_get_rec(xdf, ri, &rec);
+	xrecord_t *rec = &xdf->recs[ri];
+
 	if (!xecfg->find_func)
-		return def_ff(rec, len, buf, sz);
-	return xecfg->find_func(rec, len, buf, sz, xecfg->find_func_priv);
+		return def_ff(rec->ptr, rec->size, buf, sz);
+	return xecfg->find_func(rec->ptr, rec->size, buf, sz, xecfg->find_func_priv);
 }
 
 static int is_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri)
@@ -160,14 +150,12 @@ static long get_func_line(xdfenv_t *xe, xdemitconf_t const *xecfg,
 
 static int is_empty_rec(xdfile_t *xdf, long ri)
 {
-	const char *rec;
-	long len = xdl_get_rec(xdf, ri, &rec);
+	xrecord_t *rec = &xdf->recs[ri];
+	long i = 0;
 
-	while (len > 0 && XDL_ISSPACE(*rec)) {
-		rec++;
-		len--;
-	}
-	return !len;
+	for (; i < rec->size && XDL_ISSPACE(rec->ptr[i]); i++);
+
+	return i == rec->size;
 }
 
 int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
diff --git a/xdiff/xhistogram.c b/xdiff/xhistogram.c
index 040d81e..6dc450b 100644
--- a/xdiff/xhistogram.c
+++ b/xdiff/xhistogram.c
@@ -86,7 +86,7 @@ struct region {
 	((LINE_MAP(index, ptr))->cnt)
 
 #define REC(env, s, l) \
-	(env->xdf##s.recs[l - 1])
+	(&env->xdf##s.recs[l - 1])
 
 static int cmp_recs(xrecord_t *r1, xrecord_t *r2)
 {
@@ -318,11 +318,11 @@ static int histogram_diff(xpparam_t const *xpp, xdfenv_t *env,
 
 	if (!count1) {
 		while(count2--)
-			env->xdf2.rchg[line2++ - 1] = 1;
+			env->xdf2.changed[line2++ - 1] = true;
 		return 0;
 	} else if (!count2) {
 		while(count1--)
-			env->xdf1.rchg[line1++ - 1] = 1;
+			env->xdf1.changed[line1++ - 1] = true;
 		return 0;
 	}
 
@@ -335,9 +335,9 @@ static int histogram_diff(xpparam_t const *xpp, xdfenv_t *env,
 	else {
 		if (lcs.begin1 == 0 && lcs.begin2 == 0) {
 			while (count1--)
-				env->xdf1.rchg[line1++ - 1] = 1;
+				env->xdf1.changed[line1++ - 1] = true;
 			while (count2--)
-				env->xdf2.rchg[line2++ - 1] = 1;
+				env->xdf2.changed[line2++ - 1] = true;
 			result = 0;
 		} else {
 			result = histogram_diff(xpp, env,
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index af40c88..fd600cb 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -97,12 +97,12 @@ static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
 		int line_count, long flags)
 {
 	int i;
-	xrecord_t **rec1 = xe1->xdf2.recs + i1;
-	xrecord_t **rec2 = xe2->xdf2.recs + i2;
+	xrecord_t *rec1 = xe1->xdf2.recs + i1;
+	xrecord_t *rec2 = xe2->xdf2.recs + i2;
 
 	for (i = 0; i < line_count; i++) {
-		int result = xdl_recmatch(rec1[i]->ptr, rec1[i]->size,
-			rec2[i]->ptr, rec2[i]->size, flags);
+		int result = xdl_recmatch(rec1[i].ptr, rec1[i].size,
+			rec2[i].ptr, rec2[i].size, flags);
 		if (!result)
 			return -1;
 	}
@@ -111,7 +111,7 @@ static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
 
 static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
 {
-	xrecord_t **recs;
+	xrecord_t *recs;
 	int size = 0;
 
 	recs = (use_orig ? xe->xdf1.recs : xe->xdf2.recs) + i;
@@ -119,12 +119,12 @@ static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int nee
 	if (count < 1)
 		return 0;
 
-	for (i = 0; i < count; size += recs[i++]->size)
+	for (i = 0; i < count; size += recs[i++].size)
 		if (dest)
-			memcpy(dest + size, recs[i]->ptr, recs[i]->size);
+			memcpy(dest + size, recs[i].ptr, recs[i].size);
 	if (add_nl) {
-		i = recs[count - 1]->size;
-		if (i == 0 || recs[count - 1]->ptr[i - 1] != '\n') {
+		i = recs[count - 1].size;
+		if (i == 0 || recs[count - 1].ptr[i - 1] != '\n') {
 			if (needs_cr) {
 				if (dest)
 					dest[size] = '\r';
@@ -160,22 +160,22 @@ static int is_eol_crlf(xdfile_t *file, int i)
 
 	if (i < file->nrec - 1)
 		/* All lines before the last *must* end in LF */
-		return (size = file->recs[i]->size) > 1 &&
-			file->recs[i]->ptr[size - 2] == '\r';
+		return (size = file->recs[i].size) > 1 &&
+			file->recs[i].ptr[size - 2] == '\r';
 	if (!file->nrec)
 		/* Cannot determine eol style from empty file */
 		return -1;
-	if ((size = file->recs[i]->size) &&
-			file->recs[i]->ptr[size - 1] == '\n')
+	if ((size = file->recs[i].size) &&
+			file->recs[i].ptr[size - 1] == '\n')
 		/* Last line; ends in LF; Is it CR/LF? */
 		return size > 1 &&
-			file->recs[i]->ptr[size - 2] == '\r';
+			file->recs[i].ptr[size - 2] == '\r';
 	if (!i)
 		/* The only line has no eol */
 		return -1;
 	/* Determine eol from second-to-last line */
-	return (size = file->recs[i - 1]->size) > 1 &&
-		file->recs[i - 1]->ptr[size - 2] == '\r';
+	return (size = file->recs[i - 1].size) > 1 &&
+		file->recs[i - 1].ptr[size - 2] == '\r';
 }
 
 static int is_cr_needed(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m)
@@ -334,22 +334,22 @@ static int recmatch(xrecord_t *rec1, xrecord_t *rec2, unsigned long flags)
 static void xdl_refine_zdiff3_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
 		xpparam_t const *xpp)
 {
-	xrecord_t **rec1 = xe1->xdf2.recs, **rec2 = xe2->xdf2.recs;
+	xrecord_t *rec1 = xe1->xdf2.recs, *rec2 = xe2->xdf2.recs;
 	for (; m; m = m->next) {
 		/* let's handle just the conflicts */
 		if (m->mode)
 			continue;
 
 		while(m->chg1 && m->chg2 &&
-		      recmatch(rec1[m->i1], rec2[m->i2], xpp->flags)) {
+		      recmatch(&rec1[m->i1], &rec2[m->i2], xpp->flags)) {
 			m->chg1--;
 			m->chg2--;
 			m->i1++;
 			m->i2++;
 		}
 		while (m->chg1 && m->chg2 &&
-		       recmatch(rec1[m->i1 + m->chg1 - 1],
-				rec2[m->i2 + m->chg2 - 1], xpp->flags)) {
+		       recmatch(&rec1[m->i1 + m->chg1 - 1],
+				&rec2[m->i2 + m->chg2 - 1], xpp->flags)) {
 			m->chg1--;
 			m->chg2--;
 		}
@@ -381,12 +381,12 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
 		 * This probably does not work outside git, since
 		 * we have a very simple mmfile structure.
 		 */
-		t1.ptr = (char *)xe1->xdf2.recs[m->i1]->ptr;
-		t1.size = xe1->xdf2.recs[m->i1 + m->chg1 - 1]->ptr
-			+ xe1->xdf2.recs[m->i1 + m->chg1 - 1]->size - t1.ptr;
-		t2.ptr = (char *)xe2->xdf2.recs[m->i2]->ptr;
-		t2.size = xe2->xdf2.recs[m->i2 + m->chg2 - 1]->ptr
-			+ xe2->xdf2.recs[m->i2 + m->chg2 - 1]->size - t2.ptr;
+		t1.ptr = (char *)xe1->xdf2.recs[m->i1].ptr;
+		t1.size = xe1->xdf2.recs[m->i1 + m->chg1 - 1].ptr
+			+ xe1->xdf2.recs[m->i1 + m->chg1 - 1].size - t1.ptr;
+		t2.ptr = (char *)xe2->xdf2.recs[m->i2].ptr;
+		t2.size = xe2->xdf2.recs[m->i2 + m->chg2 - 1].ptr
+			+ xe2->xdf2.recs[m->i2 + m->chg2 - 1].size - t2.ptr;
 		if (xdl_do_diff(&t1, &t2, xpp, &xe) < 0)
 			return -1;
 		if (xdl_change_compact(&xe.xdf1, &xe.xdf2, xpp->flags) < 0 ||
@@ -440,8 +440,8 @@ static int line_contains_alnum(const char *ptr, long size)
 static int lines_contain_alnum(xdfenv_t *xe, int i, int chg)
 {
 	for (; chg; chg--, i++)
-		if (line_contains_alnum(xe->xdf2.recs[i]->ptr,
-				xe->xdf2.recs[i]->size))
+		if (line_contains_alnum(xe->xdf2.recs[i].ptr,
+				xe->xdf2.recs[i].size))
 			return 1;
 	return 0;
 }
diff --git a/xdiff/xpatience.c b/xdiff/xpatience.c
index 77dc411..669b653 100644
--- a/xdiff/xpatience.c
+++ b/xdiff/xpatience.c
@@ -88,9 +88,9 @@ static int is_anchor(xpparam_t const *xpp, const char *line)
 static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
 			  int pass)
 {
-	xrecord_t **records = pass == 1 ?
+	xrecord_t *records = pass == 1 ?
 		map->env->xdf1.recs : map->env->xdf2.recs;
-	xrecord_t *record = records[line - 1];
+	xrecord_t *record = &records[line - 1];
 	/*
 	 * After xdl_prepare_env() (or more precisely, due to
 	 * xdl_classify_record()), the "ha" member of the records (AKA lines)
@@ -121,7 +121,7 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
 		return;
 	map->entries[index].line1 = line;
 	map->entries[index].hash = record->ha;
-	map->entries[index].anchor = is_anchor(xpp, map->env->xdf1.recs[line - 1]->ptr);
+	map->entries[index].anchor = is_anchor(xpp, map->env->xdf1.recs[line - 1].ptr);
 	if (!map->first)
 		map->first = map->entries + index;
 	if (map->last) {
@@ -246,8 +246,8 @@ static int find_longest_common_sequence(struct hashmap *map, struct entry **res)
 
 static int match(struct hashmap *map, int line1, int line2)
 {
-	xrecord_t *record1 = map->env->xdf1.recs[line1 - 1];
-	xrecord_t *record2 = map->env->xdf2.recs[line2 - 1];
+	xrecord_t *record1 = &map->env->xdf1.recs[line1 - 1];
+	xrecord_t *record2 = &map->env->xdf2.recs[line2 - 1];
 	return record1->ha == record2->ha;
 }
 
@@ -331,11 +331,11 @@ static int patience_diff(xpparam_t const *xpp, xdfenv_t *env,
 	/* trivial case: one side is empty */
 	if (!count1) {
 		while(count2--)
-			env->xdf2.rchg[line2++ - 1] = 1;
+			env->xdf2.changed[line2++ - 1] = true;
 		return 0;
 	} else if (!count2) {
 		while(count1--)
-			env->xdf1.rchg[line1++ - 1] = 1;
+			env->xdf1.changed[line1++ - 1] = true;
 		return 0;
 	}
 
@@ -347,9 +347,9 @@ static int patience_diff(xpparam_t const *xpp, xdfenv_t *env,
 	/* are there any matching lines at all? */
 	if (!map.has_matches) {
 		while(count1--)
-			env->xdf1.rchg[line1++ - 1] = 1;
+			env->xdf1.changed[line1++ - 1] = true;
 		while(count2--)
-			env->xdf2.rchg[line2++ - 1] = 1;
+			env->xdf2.changed[line2++ - 1] = true;
 		xdl_free(map.entries);
 		return 0;
 	}
diff --git a/xdiff/xprepare.c b/xdiff/xprepare.c
index e1d4017..192334f 100644
--- a/xdiff/xprepare.c
+++ b/xdiff/xprepare.c
@@ -29,12 +29,13 @@
 #define XDL_GUESS_NLINES1 256
 #define XDL_GUESS_NLINES2 20
 
+#define DISCARD 0
+#define KEEP 1
+#define INVESTIGATE 2
 
 typedef struct s_xdlclass {
 	struct s_xdlclass *next;
-	unsigned long ha;
-	char const *line;
-	long size;
+	xrecord_t rec;
 	long idx;
 	long len1, len2;
 } xdlclass_t;
@@ -53,21 +54,6 @@ typedef struct s_xdlclassifier {
 
 
 
-static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags);
-static void xdl_free_classifier(xdlclassifier_t *cf);
-static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t **rhash,
-			       unsigned int hbits, xrecord_t *rec);
-static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_t const *xpp,
-			   xdlclassifier_t *cf, xdfile_t *xdf);
-static void xdl_free_ctx(xdfile_t *xdf);
-static int xdl_clean_mmatch(char const *dis, long i, long s, long e);
-static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2);
-static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2);
-static int xdl_optimize_ctxs(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2);
-
-
-
-
 static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags) {
 	cf->flags = flags;
 
@@ -106,17 +92,14 @@ static void xdl_free_classifier(xdlclassifier_t *cf) {
 }
 
 
-static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t **rhash,
-			       unsigned int hbits, xrecord_t *rec) {
+static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t *rec) {
 	long hi;
-	char const *line;
 	xdlclass_t *rcrec;
 
-	line = rec->ptr;
 	hi = (long) XDL_HASHLONG(rec->ha, cf->hbits);
 	for (rcrec = cf->rchash[hi]; rcrec; rcrec = rcrec->next)
-		if (rcrec->ha == rec->ha &&
-				xdl_recmatch(rcrec->line, rcrec->size,
+		if (rcrec->rec.ha == rec->ha &&
+				xdl_recmatch(rcrec->rec.ptr, rcrec->rec.size,
 					rec->ptr, rec->size, cf->flags))
 			break;
 
@@ -129,9 +112,7 @@ static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t
 		if (XDL_ALLOC_GROW(cf->rcrecs, cf->count, cf->alloc))
 				return -1;
 		cf->rcrecs[rcrec->idx] = rcrec;
-		rcrec->line = line;
-		rcrec->size = rec->size;
-		rcrec->ha = rec->ha;
+		rcrec->rec = *rec;
 		rcrec->len1 = rcrec->len2 = 0;
 		rcrec->next = cf->rchash[hi];
 		cf->rchash[hi] = rcrec;
@@ -141,107 +122,263 @@ static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t
 
 	rec->ha = (unsigned long) rcrec->idx;
 
-	hi = (long) XDL_HASHLONG(rec->ha, hbits);
-	rec->next = rhash[hi];
-	rhash[hi] = rec;
-
 	return 0;
 }
 
 
+static void xdl_free_ctx(xdfile_t *xdf)
+{
+	xdl_free(xdf->rindex);
+	xdl_free(xdf->changed - 1);
+	xdl_free(xdf->recs);
+}
+
+
 static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_t const *xpp,
 			   xdlclassifier_t *cf, xdfile_t *xdf) {
-	unsigned int hbits;
-	long nrec, hsize, bsize;
+	long bsize;
 	unsigned long hav;
 	char const *blk, *cur, *top, *prev;
 	xrecord_t *crec;
-	xrecord_t **recs;
-	xrecord_t **rhash;
-	unsigned long *ha;
-	char *rchg;
-	long *rindex;
 
-	ha = NULL;
-	rindex = NULL;
-	rchg = NULL;
-	rhash = NULL;
-	recs = NULL;
+	xdf->rindex = NULL;
+	xdf->changed = NULL;
+	xdf->recs = NULL;
 
-	if (xdl_cha_init(&xdf->rcha, sizeof(xrecord_t), narec / 4 + 1) < 0)
-		goto abort;
-	if (!XDL_ALLOC_ARRAY(recs, narec))
+	if (!XDL_ALLOC_ARRAY(xdf->recs, narec))
 		goto abort;
 
-	hbits = xdl_hashbits((unsigned int) narec);
-	hsize = 1 << hbits;
-	if (!XDL_CALLOC_ARRAY(rhash, hsize))
-		goto abort;
-
-	nrec = 0;
+	xdf->nrec = 0;
 	if ((cur = blk = xdl_mmfile_first(mf, &bsize))) {
 		for (top = blk + bsize; cur < top; ) {
 			prev = cur;
 			hav = xdl_hash_record(&cur, top, xpp->flags);
-			if (XDL_ALLOC_GROW(recs, nrec + 1, narec))
+			if (XDL_ALLOC_GROW(xdf->recs, xdf->nrec + 1, narec))
 				goto abort;
-			if (!(crec = xdl_cha_alloc(&xdf->rcha)))
-				goto abort;
+			crec = &xdf->recs[xdf->nrec++];
 			crec->ptr = prev;
 			crec->size = (long) (cur - prev);
 			crec->ha = hav;
-			recs[nrec++] = crec;
-			if (xdl_classify_record(pass, cf, rhash, hbits, crec) < 0)
+			if (xdl_classify_record(pass, cf, crec) < 0)
 				goto abort;
 		}
 	}
 
-	if (!XDL_CALLOC_ARRAY(rchg, nrec + 2))
+	if (!XDL_CALLOC_ARRAY(xdf->changed, xdf->nrec + 2))
 		goto abort;
 
 	if ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) &&
 	    (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)) {
-		if (!XDL_ALLOC_ARRAY(rindex, nrec + 1))
-			goto abort;
-		if (!XDL_ALLOC_ARRAY(ha, nrec + 1))
+		if (!XDL_ALLOC_ARRAY(xdf->rindex, xdf->nrec + 1))
 			goto abort;
 	}
 
-	xdf->nrec = nrec;
-	xdf->recs = recs;
-	xdf->hbits = hbits;
-	xdf->rhash = rhash;
-	xdf->rchg = rchg + 1;
-	xdf->rindex = rindex;
+	xdf->changed += 1;
 	xdf->nreff = 0;
-	xdf->ha = ha;
 	xdf->dstart = 0;
-	xdf->dend = nrec - 1;
+	xdf->dend = xdf->nrec - 1;
 
 	return 0;
 
 abort:
-	xdl_free(ha);
-	xdl_free(rindex);
-	xdl_free(rchg);
-	xdl_free(rhash);
-	xdl_free(recs);
-	xdl_cha_free(&xdf->rcha);
+	xdl_free_ctx(xdf);
 	return -1;
 }
 
 
-static void xdl_free_ctx(xdfile_t *xdf) {
+void xdl_free_env(xdfenv_t *xe) {
 
-	xdl_free(xdf->rhash);
-	xdl_free(xdf->rindex);
-	xdl_free(xdf->rchg - 1);
-	xdl_free(xdf->ha);
-	xdl_free(xdf->recs);
-	xdl_cha_free(&xdf->rcha);
+	xdl_free_ctx(&xe->xdf2);
+	xdl_free_ctx(&xe->xdf1);
 }
 
 
+static bool xdl_clean_mmatch(uint8_t const *action, long i, long s, long e) {
+	long r, rdis0, rpdis0, rdis1, rpdis1;
+
+	/*
+	 * Limits the window that is examined during the similar-lines
+	 * scan. The loops below stops when action[i - r] == KEEP
+	 * (line that has no match), but there are corner cases where
+	 * the loop proceed all the way to the extremities by causing
+	 * huge performance penalties in case of big files.
+	 */
+	if (i - s > XDL_SIMSCAN_WINDOW)
+		s = i - XDL_SIMSCAN_WINDOW;
+	if (e - i > XDL_SIMSCAN_WINDOW)
+		e = i + XDL_SIMSCAN_WINDOW;
+
+	/*
+	 * Scans the lines before 'i' to find a run of lines that either
+	 * have no match (action[j] == DISCARD) or have multiple matches
+	 * (action[j] == INVESTIGATE). Note that we always call this
+	 * function with action[i] == INVESTIGATE, so the current line
+	 * (i) is already a multimatch line.
+	 */
+	for (r = 1, rdis0 = 0, rpdis0 = 1; (i - r) >= s; r++) {
+		if (action[i - r] == DISCARD)
+			rdis0++;
+		else if (action[i - r] == INVESTIGATE)
+			rpdis0++;
+		else if (action[i - r] == KEEP)
+			break;
+		else
+			BUG("Illegal value for action[i - r]");
+	}
+	/*
+	 * If the run before the line 'i' found only multimatch lines,
+	 * we return false and hence we don't make the current line (i)
+	 * discarded. We want to discard multimatch lines only when
+	 * they appear in the middle of runs with nomatch lines
+	 * (action[j] == DISCARD).
+	 */
+	if (rdis0 == 0)
+		return 0;
+	for (r = 1, rdis1 = 0, rpdis1 = 1; (i + r) <= e; r++) {
+		if (action[i + r] == DISCARD)
+			rdis1++;
+		else if (action[i + r] == INVESTIGATE)
+			rpdis1++;
+		else if (action[i + r] == KEEP)
+			break;
+		else
+			BUG("Illegal value for action[i + r]");
+	}
+	/*
+	 * If the run after the line 'i' found only multimatch lines,
+	 * we return false and hence we don't make the current line (i)
+	 * discarded.
+	 */
+	if (rdis1 == 0)
+		return false;
+	rdis1 += rdis0;
+	rpdis1 += rpdis0;
+
+	return rpdis1 * XDL_KPDIS_RUN < (rpdis1 + rdis1);
+}
+
+
+/*
+ * Try to reduce the problem complexity, discard records that have no
+ * matches on the other file. Also, lines that have multiple matches
+ * might be potentially discarded if they appear in a run of discardable.
+ */
+static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2) {
+	long i, nm, nreff, mlim;
+	xrecord_t *recs;
+	xdlclass_t *rcrec;
+	uint8_t *action1 = NULL, *action2 = NULL;
+	bool need_min = !!(cf->flags & XDF_NEED_MINIMAL);
+	int ret = 0;
+
+	/*
+	 * Create temporary arrays that will help us decide if
+	 * changed[i] should remain false, or become true.
+	 */
+	if (!XDL_CALLOC_ARRAY(action1, xdf1->nrec + 1)) {
+		ret = -1;
+		goto cleanup;
+	}
+	if (!XDL_CALLOC_ARRAY(action2, xdf2->nrec + 1)) {
+		ret = -1;
+		goto cleanup;
+	}
+
+	/*
+	 * Initialize temporary arrays with DISCARD, KEEP, or INVESTIGATE.
+	 */
+	if ((mlim = xdl_bogosqrt(xdf1->nrec)) > XDL_MAX_EQLIMIT)
+		mlim = XDL_MAX_EQLIMIT;
+	for (i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; i <= xdf1->dend; i++, recs++) {
+		rcrec = cf->rcrecs[recs->ha];
+		nm = rcrec ? rcrec->len2 : 0;
+		action1[i] = (nm == 0) ? DISCARD: (nm >= mlim && !need_min) ? INVESTIGATE: KEEP;
+	}
+
+	if ((mlim = xdl_bogosqrt(xdf2->nrec)) > XDL_MAX_EQLIMIT)
+		mlim = XDL_MAX_EQLIMIT;
+	for (i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; i <= xdf2->dend; i++, recs++) {
+		rcrec = cf->rcrecs[recs->ha];
+		nm = rcrec ? rcrec->len1 : 0;
+		action2[i] = (nm == 0) ? DISCARD: (nm >= mlim && !need_min) ? INVESTIGATE: KEEP;
+	}
+
+	/*
+	 * Use temporary arrays to decide if changed[i] should remain
+	 * false, or become true.
+	 */
+	for (nreff = 0, i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart];
+	     i <= xdf1->dend; i++, recs++) {
+		if (action1[i] == KEEP ||
+		    (action1[i] == INVESTIGATE && !xdl_clean_mmatch(action1, i, xdf1->dstart, xdf1->dend))) {
+			xdf1->rindex[nreff++] = i;
+			/* changed[i] remains false, i.e. keep */
+		} else
+			xdf1->changed[i] = true;
+			/* i.e. discard */
+	}
+	xdf1->nreff = nreff;
+
+	for (nreff = 0, i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart];
+	     i <= xdf2->dend; i++, recs++) {
+		if (action2[i] == KEEP ||
+		    (action2[i] == INVESTIGATE && !xdl_clean_mmatch(action2, i, xdf2->dstart, xdf2->dend))) {
+			xdf2->rindex[nreff++] = i;
+			/* changed[i] remains false, i.e. keep */
+		} else
+			xdf2->changed[i] = true;
+			/* i.e. discard */
+	}
+	xdf2->nreff = nreff;
+
+cleanup:
+	xdl_free(action1);
+	xdl_free(action2);
+
+	return ret;
+}
+
+
+/*
+ * Early trim initial and terminal matching records.
+ */
+static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2) {
+	long i, lim;
+	xrecord_t *recs1, *recs2;
+
+	recs1 = xdf1->recs;
+	recs2 = xdf2->recs;
+	for (i = 0, lim = XDL_MIN(xdf1->nrec, xdf2->nrec); i < lim;
+	     i++, recs1++, recs2++)
+		if (recs1->ha != recs2->ha)
+			break;
+
+	xdf1->dstart = xdf2->dstart = i;
+
+	recs1 = xdf1->recs + xdf1->nrec - 1;
+	recs2 = xdf2->recs + xdf2->nrec - 1;
+	for (lim -= i, i = 0; i < lim; i++, recs1--, recs2--)
+		if (recs1->ha != recs2->ha)
+			break;
+
+	xdf1->dend = xdf1->nrec - i - 1;
+	xdf2->dend = xdf2->nrec - i - 1;
+
+	return 0;
+}
+
+
+static int xdl_optimize_ctxs(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2) {
+
+	if (xdl_trim_ends(xdf1, xdf2) < 0 ||
+	    xdl_cleanup_records(cf, xdf1, xdf2) < 0) {
+
+		return -1;
+	}
+
+	return 0;
+}
+
 int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 		    xdfenv_t *xe) {
 	long enl1, enl2, sample;
@@ -291,172 +428,3 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 
 	return 0;
 }
-
-
-void xdl_free_env(xdfenv_t *xe) {
-
-	xdl_free_ctx(&xe->xdf2);
-	xdl_free_ctx(&xe->xdf1);
-}
-
-
-static int xdl_clean_mmatch(char const *dis, long i, long s, long e) {
-	long r, rdis0, rpdis0, rdis1, rpdis1;
-
-	/*
-	 * Limits the window the is examined during the similar-lines
-	 * scan. The loops below stops when dis[i - r] == 1 (line that
-	 * has no match), but there are corner cases where the loop
-	 * proceed all the way to the extremities by causing huge
-	 * performance penalties in case of big files.
-	 */
-	if (i - s > XDL_SIMSCAN_WINDOW)
-		s = i - XDL_SIMSCAN_WINDOW;
-	if (e - i > XDL_SIMSCAN_WINDOW)
-		e = i + XDL_SIMSCAN_WINDOW;
-
-	/*
-	 * Scans the lines before 'i' to find a run of lines that either
-	 * have no match (dis[j] == 0) or have multiple matches (dis[j] > 1).
-	 * Note that we always call this function with dis[i] > 1, so the
-	 * current line (i) is already a multimatch line.
-	 */
-	for (r = 1, rdis0 = 0, rpdis0 = 1; (i - r) >= s; r++) {
-		if (!dis[i - r])
-			rdis0++;
-		else if (dis[i - r] == 2)
-			rpdis0++;
-		else
-			break;
-	}
-	/*
-	 * If the run before the line 'i' found only multimatch lines, we
-	 * return 0 and hence we don't make the current line (i) discarded.
-	 * We want to discard multimatch lines only when they appear in the
-	 * middle of runs with nomatch lines (dis[j] == 0).
-	 */
-	if (rdis0 == 0)
-		return 0;
-	for (r = 1, rdis1 = 0, rpdis1 = 1; (i + r) <= e; r++) {
-		if (!dis[i + r])
-			rdis1++;
-		else if (dis[i + r] == 2)
-			rpdis1++;
-		else
-			break;
-	}
-	/*
-	 * If the run after the line 'i' found only multimatch lines, we
-	 * return 0 and hence we don't make the current line (i) discarded.
-	 */
-	if (rdis1 == 0)
-		return 0;
-	rdis1 += rdis0;
-	rpdis1 += rpdis0;
-
-	return rpdis1 * XDL_KPDIS_RUN < (rpdis1 + rdis1);
-}
-
-
-/*
- * Try to reduce the problem complexity, discard records that have no
- * matches on the other file. Also, lines that have multiple matches
- * might be potentially discarded if they happear in a run of discardable.
- */
-static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2) {
-	long i, nm, nreff, mlim;
-	xrecord_t **recs;
-	xdlclass_t *rcrec;
-	char *dis, *dis1, *dis2;
-	int need_min = !!(cf->flags & XDF_NEED_MINIMAL);
-
-	if (!XDL_CALLOC_ARRAY(dis, xdf1->nrec + xdf2->nrec + 2))
-		return -1;
-	dis1 = dis;
-	dis2 = dis1 + xdf1->nrec + 1;
-
-	if ((mlim = xdl_bogosqrt(xdf1->nrec)) > XDL_MAX_EQLIMIT)
-		mlim = XDL_MAX_EQLIMIT;
-	for (i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; i <= xdf1->dend; i++, recs++) {
-		rcrec = cf->rcrecs[(*recs)->ha];
-		nm = rcrec ? rcrec->len2 : 0;
-		dis1[i] = (nm == 0) ? 0: (nm >= mlim && !need_min) ? 2: 1;
-	}
-
-	if ((mlim = xdl_bogosqrt(xdf2->nrec)) > XDL_MAX_EQLIMIT)
-		mlim = XDL_MAX_EQLIMIT;
-	for (i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; i <= xdf2->dend; i++, recs++) {
-		rcrec = cf->rcrecs[(*recs)->ha];
-		nm = rcrec ? rcrec->len1 : 0;
-		dis2[i] = (nm == 0) ? 0: (nm >= mlim && !need_min) ? 2: 1;
-	}
-
-	for (nreff = 0, i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart];
-	     i <= xdf1->dend; i++, recs++) {
-		if (dis1[i] == 1 ||
-		    (dis1[i] == 2 && !xdl_clean_mmatch(dis1, i, xdf1->dstart, xdf1->dend))) {
-			xdf1->rindex[nreff] = i;
-			xdf1->ha[nreff] = (*recs)->ha;
-			nreff++;
-		} else
-			xdf1->rchg[i] = 1;
-	}
-	xdf1->nreff = nreff;
-
-	for (nreff = 0, i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart];
-	     i <= xdf2->dend; i++, recs++) {
-		if (dis2[i] == 1 ||
-		    (dis2[i] == 2 && !xdl_clean_mmatch(dis2, i, xdf2->dstart, xdf2->dend))) {
-			xdf2->rindex[nreff] = i;
-			xdf2->ha[nreff] = (*recs)->ha;
-			nreff++;
-		} else
-			xdf2->rchg[i] = 1;
-	}
-	xdf2->nreff = nreff;
-
-	xdl_free(dis);
-
-	return 0;
-}
-
-
-/*
- * Early trim initial and terminal matching records.
- */
-static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2) {
-	long i, lim;
-	xrecord_t **recs1, **recs2;
-
-	recs1 = xdf1->recs;
-	recs2 = xdf2->recs;
-	for (i = 0, lim = XDL_MIN(xdf1->nrec, xdf2->nrec); i < lim;
-	     i++, recs1++, recs2++)
-		if ((*recs1)->ha != (*recs2)->ha)
-			break;
-
-	xdf1->dstart = xdf2->dstart = i;
-
-	recs1 = xdf1->recs + xdf1->nrec - 1;
-	recs2 = xdf2->recs + xdf2->nrec - 1;
-	for (lim -= i, i = 0; i < lim; i++, recs1--, recs2--)
-		if ((*recs1)->ha != (*recs2)->ha)
-			break;
-
-	xdf1->dend = xdf1->nrec - i - 1;
-	xdf2->dend = xdf2->nrec - i - 1;
-
-	return 0;
-}
-
-
-static int xdl_optimize_ctxs(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2) {
-
-	if (xdl_trim_ends(xdf1, xdf2) < 0 ||
-	    xdl_cleanup_records(cf, xdf1, xdf2) < 0) {
-
-		return -1;
-	}
-
-	return 0;
-}
diff --git a/xdiff/xtypes.h b/xdiff/xtypes.h
index 8442bd4..f145abb 100644
--- a/xdiff/xtypes.h
+++ b/xdiff/xtypes.h
@@ -39,23 +39,18 @@ typedef struct s_chastore {
 } chastore_t;
 
 typedef struct s_xrecord {
-	struct s_xrecord *next;
 	char const *ptr;
 	long size;
 	unsigned long ha;
 } xrecord_t;
 
 typedef struct s_xdfile {
-	chastore_t rcha;
+	xrecord_t *recs;
 	long nrec;
-	unsigned int hbits;
-	xrecord_t **rhash;
 	long dstart, dend;
-	xrecord_t **recs;
-	char *rchg;
+	bool *changed;
 	long *rindex;
 	long nreff;
-	unsigned long *ha;
 } xdfile_t;
 
 typedef struct s_xdfenv {
diff --git a/xdiff/xutils.c b/xdiff/xutils.c
index 444a108..447e66c 100644
--- a/xdiff/xutils.c
+++ b/xdiff/xutils.c
@@ -249,7 +249,7 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
 	return 1;
 }
 
-static unsigned long xdl_hash_record_with_whitespace(char const **data,
+unsigned long xdl_hash_record_with_whitespace(char const **data,
 		char const *top, long flags) {
 	unsigned long ha = 5381;
 	char const *ptr = *data;
@@ -294,19 +294,67 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
 	return ha;
 }
 
-unsigned long xdl_hash_record(char const **data, char const *top, long flags) {
-	unsigned long ha = 5381;
+/*
+ * Compiler reassociation barrier: pretend to modify X and Y to disallow
+ * changing evaluation order with respect to following uses of X and Y.
+ */
+#ifdef __GNUC__
+#define REASSOC_FENCE(x, y) __asm__("" : "+r"(x), "+r"(y))
+#else
+#define REASSOC_FENCE(x, y)
+#endif
+
+unsigned long xdl_hash_record_verbatim(char const **data, char const *top) {
+	unsigned long ha = 5381, c0, c1;
 	char const *ptr = *data;
-
-	if (flags & XDF_WHITESPACE_FLAGS)
-		return xdl_hash_record_with_whitespace(data, top, flags);
-
+#if 0
+	/*
+	 * The baseline form of the optimized loop below. This is the djb2
+	 * hash (the above function uses a variant with XOR instead of ADD).
+	 */
 	for (; ptr < top && *ptr != '\n'; ptr++) {
 		ha += (ha << 5);
-		ha ^= (unsigned long) *ptr;
+		ha += (unsigned long) *ptr;
 	}
 	*data = ptr < top ? ptr + 1: ptr;
+#else
+	/* Process two characters per iteration. */
+	if (top - ptr >= 2) do {
+		if ((c0 = ptr[0]) == '\n') {
+			*data = ptr + 1;
+			return ha;
+		}
+		if ((c1 = ptr[1]) == '\n') {
+			*data = ptr + 2;
+			c0 += ha;
+			REASSOC_FENCE(c0, ha);
+			ha = ha * 32 + c0;
+			return ha;
+		}
+		/*
+		 * Combine characters C0 and C1 into the hash HA. We have
+		 * HA = (HA * 33 + C0) * 33 + C1, and we want to ensure
+		 * that dependency chain over HA is just one multiplication
+		 * and one addition, i.e. we want to evaluate this as
+		 * HA = HA * 33 * 33 + (C0 * 33 + C1), and likewise prefer
+		 * (C0 * 32 + (C0 + C1)) for the expression in parenthesis.
+		 */
+		ha *= 33 * 33;
+		c1 += c0;
+		REASSOC_FENCE(c1, c0);
+		c1 += c0 * 32;
+		REASSOC_FENCE(c1, ha);
+		ha += c1;
 
+		ptr += 2;
+	} while (ptr < top - 1);
+	*data = top;
+	if (ptr < top && (c0 = ptr[0]) != '\n') {
+		c0 += ha;
+		REASSOC_FENCE(c0, ha);
+		ha = ha * 32 + c0;
+	}
+#endif
 	return ha;
 }
 
@@ -416,17 +464,17 @@ int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
 	mmfile_t subfile1, subfile2;
 	xdfenv_t env;
 
-	subfile1.ptr = (char *)diff_env->xdf1.recs[line1 - 1]->ptr;
-	subfile1.size = diff_env->xdf1.recs[line1 + count1 - 2]->ptr +
-		diff_env->xdf1.recs[line1 + count1 - 2]->size - subfile1.ptr;
-	subfile2.ptr = (char *)diff_env->xdf2.recs[line2 - 1]->ptr;
-	subfile2.size = diff_env->xdf2.recs[line2 + count2 - 2]->ptr +
-		diff_env->xdf2.recs[line2 + count2 - 2]->size - subfile2.ptr;
+	subfile1.ptr = (char *)diff_env->xdf1.recs[line1 - 1].ptr;
+	subfile1.size = diff_env->xdf1.recs[line1 + count1 - 2].ptr +
+		diff_env->xdf1.recs[line1 + count1 - 2].size - subfile1.ptr;
+	subfile2.ptr = (char *)diff_env->xdf2.recs[line2 - 1].ptr;
+	subfile2.size = diff_env->xdf2.recs[line2 + count2 - 2].ptr +
+		diff_env->xdf2.recs[line2 + count2 - 2].size - subfile2.ptr;
 	if (xdl_do_diff(&subfile1, &subfile2, xpp, &env) < 0)
 		return -1;
 
-	memcpy(diff_env->xdf1.rchg + line1 - 1, env.xdf1.rchg, count1);
-	memcpy(diff_env->xdf2.rchg + line2 - 1, env.xdf2.rchg, count2);
+	memcpy(diff_env->xdf1.changed + line1 - 1, env.xdf1.changed, count1);
+	memcpy(diff_env->xdf2.changed + line2 - 1, env.xdf2.changed, count2);
 
 	xdl_free_env(&env);
 
diff --git a/xdiff/xutils.h b/xdiff/xutils.h
index fd0bba9..13f6831 100644
--- a/xdiff/xutils.h
+++ b/xdiff/xutils.h
@@ -34,7 +34,15 @@ void *xdl_cha_alloc(chastore_t *cha);
 long xdl_guess_lines(mmfile_t *mf, long sample);
 int xdl_blankline(const char *line, long size, long flags);
 int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags);
-unsigned long xdl_hash_record(char const **data, char const *top, long flags);
+unsigned long xdl_hash_record_verbatim(char const **data, char const *top);
+unsigned long xdl_hash_record_with_whitespace(char const **data, char const *top, long flags);
+static inline unsigned long xdl_hash_record(char const **data, char const *top, long flags)
+{
+	if (flags & XDF_WHITESPACE_FLAGS)
+		return xdl_hash_record_with_whitespace(data, top, flags);
+	else
+		return xdl_hash_record_verbatim(data, top);
+}
 unsigned int xdl_hashbits(unsigned int size);
 int xdl_num_out(char *out, long val);
 int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,