Merge branch 'stable-7.5' into stable-7.6

* stable-7.5:
  junit.http: Extract AppServerBase to dedupe the EE8 AppServer overlay
  Bazel: Add EE8 servlet test targets
  Bazel: Add EE8 servlet bridge targets
  Bazel: Rename //lib:servlet-api to //lib:jakarta-servlet-api
  Bazel: format build files with buildifier

Use merge strategy --ours to resolve conflicts between stable-7.5 using
WORKSPACE and stable-7.6 using MODULE.bazel.

Change-Id: I5c8e617e8f084e1c0d8719585f7f1543ce0e71a4
diff --git a/.bazelrc b/.bazelrc
index 0712ec2..385a71d 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,6 +1,6 @@
 # TODO(davido): Migrate all dependencies from WORKSPACE to MODULE.bazel
 # https://issues.gerritcodereview.com/issues/303819949
-common --noenable_bzlmod
+common --enable_bzlmod --lockfile_mode=error
 common --enable_workspace
 
 build --workspace_status_command="python3 ./tools/workspace_status.py"
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..ec4bb38
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1 @@
+blank_issues_enabled: false
\ No newline at end of file
diff --git a/Documentation/config-options.md b/Documentation/config-options.md
index ec00daa..4d931d7 100644
--- a/Documentation/config-options.md
+++ b/Documentation/config-options.md
@@ -81,6 +81,7 @@
 | `gc.autoDetach` | `true` |  ✅ | Make auto gc return immediately and run in background. |
 | `gc.autoPackLimit` | `50` |  ✅ | Number of packs until auto gc consolidates existing packs (except those marked with a .keep file) into a single pack. Setting `gc.autoPackLimit` to 0 disables automatic consolidation of packs. |
 | `gc.logExpiry` | `1.day.ago` | ✅ | If the file `gc.log` exists, then auto gc will print its content and exit successfully instead of running unless that file is more than `gc.logExpiry` old. |
+| `gc.packRefs`| `true` | ✅ | This variable determines whether JGit garbage collection will also pack refs. This can be set to `notbare` to enable it within all non-bare repos or it can be set to a boolean value. |
 | `gc.pruneExpire` | `2.weeks.ago` | ✅ | Grace period after which unreachable objects will be pruned. |
 | `gc.prunePackExpire` | `1.hour.ago` |  ⃞ | Grace period after which packfiles only containing unreachable objects will be pruned. |
 | `gc.writeChangedPaths` | `false`| ⃞ | Whether bloom filter should be written to commit-graph during a gc operation. |
diff --git a/MODULE.bazel b/MODULE.bazel
index 0b932b8..ab705cb 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -1,2 +1,102 @@
-# TODO(davido): Migrate all dependencies from WORKSPACE to MODULE.bazel
-# https://issues.gerritcodereview.com/issues/303819949
+module(name = "jgit")
+
+bazel_dep(name = "rules_java", version = "8.11.0")
+bazel_dep(name = "rules_jvm_external", version = "6.10")
+bazel_dep(name = "rules_shell", version = "0.6.1")
+bazel_dep(name = "rbe_autoconfig")
+git_override(
+    module_name = "rbe_autoconfig",
+    commit = "71f39817c028949bd6d25f1806502bcd33028d14",
+    remote = "https://github.com/davido/rbe_autoconfig.git",
+)
+
+register_toolchains("//tools:error_prone_warnings_toolchain_java17_definition")
+
+register_toolchains("//tools:error_prone_warnings_toolchain_java21_definition")
+
+git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
+
+git_repository(
+    name = "com_googlesource_gerrit_bazlets",
+    commit = "156bae8bb0d329d8886f681c723979cbdb39d37c",
+    remote = "https://gerrit.googlesource.com/bazlets",
+)
+
+BOUNCYCASTLE_VERSION = "1.83"
+
+BYTE_BUDDY_VERSION = "1.18.5"
+
+JETTY_VERSION = "12.1.6"
+
+JMH_VERSION = "1.37"
+
+JNA_VERSION = "5.18.1"
+
+SLF4J_VERSION = "2.0.17"
+
+SSHD_VERSION = "2.17.1"
+
+maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
+maven.install(
+    name = "external_deps",
+    artifacts = [
+        "args4j:args4j:2.37",
+        "com.google.code.gson:gson:2.13.2",
+        "com.google.errorprone:error_prone_type_annotations:2.46.0",
+        "com.googlecode.javaewah:JavaEWAH:1.2.3",
+        "com.jcraft:jsch:0.1.55",
+        "com.jcraft:jzlib:1.1.3",
+        "commons-codec:commons-codec:1.21.0",
+        "commons-io:commons-io:2.21.0",
+        "commons-logging:commons-logging:1.3.5",
+        "jakarta.servlet:jakarta.servlet-api:6.1.0",
+        "javax.servlet:javax.servlet-api:4.0.1",
+        "junit:junit:4.13.2",
+        "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
+        "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
+        "net.java.dev.jna:jna-platform:" + JNA_VERSION,
+        "net.java.dev.jna:jna:" + JNA_VERSION,
+        "net.sf.jopt-simple:jopt-simple:5.0.4",
+        "org.apache.commons:commons-compress:1.28.0",
+        "org.apache.commons:commons-lang3:3.20.0",
+        "org.apache.commons:commons-math3:3.6.1",
+        "org.apache.httpcomponents:httpclient:4.5.14",
+        "org.apache.httpcomponents:httpcore:4.4.16",
+        "org.apache.sshd:sshd-osgi:" + SSHD_VERSION,
+        "org.apache.sshd:sshd-sftp:" + SSHD_VERSION,
+        "org.assertj:assertj-core:3.27.7",
+        "org.bouncycastle:bcpg-jdk18on:" + BOUNCYCASTLE_VERSION,
+        "org.bouncycastle:bcpkix-jdk18on:" + BOUNCYCASTLE_VERSION,
+        "org.bouncycastle:bcprov-jdk18on:" + BOUNCYCASTLE_VERSION,
+        "org.bouncycastle:bcutil-jdk18on:" + BOUNCYCASTLE_VERSION,
+        "org.eclipse.jetty:jetty-http:" + JETTY_VERSION,
+        "org.eclipse.jetty:jetty-io:" + JETTY_VERSION,
+        "org.eclipse.jetty:jetty-security:" + JETTY_VERSION,
+        "org.eclipse.jetty:jetty-server:" + JETTY_VERSION,
+        "org.eclipse.jetty:jetty-session:" + JETTY_VERSION,
+        "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VERSION,
+        "org.eclipse.jetty:jetty-util:" + JETTY_VERSION,
+        "org.eclipse.jetty.ee8:jetty-ee8-nested:" + JETTY_VERSION,
+        "org.eclipse.jetty.ee8:jetty-ee8-security:" + JETTY_VERSION,
+        "org.eclipse.jetty.ee8:jetty-ee8-servlet:" + JETTY_VERSION,
+        "org.eclipse.jetty.ee10:jetty-ee10-servlet:" + JETTY_VERSION,
+        "org.hamcrest:hamcrest:3.0",
+        "org.mockito:mockito-core:5.21.0",
+        "org.objenesis:objenesis:3.4",
+        "org.openjdk.jmh:jmh-core:" + JMH_VERSION,
+        "org.openjdk.jmh:jmh-generator-annprocess:" + JMH_VERSION,
+        "org.slf4j:slf4j-api:" + SLF4J_VERSION,
+        "org.slf4j:jcl-over-slf4j:" + SLF4J_VERSION,
+        "org.slf4j:slf4j-simple:" + SLF4J_VERSION,
+        "org.tukaani:xz:1.11",
+    ],
+    duplicate_version_warning = "warn",
+    fail_on_missing_checksum = True,
+    fetch_sources = True,
+    known_contributing_modules = ["jgit"],
+    repositories = [
+        "https://repo1.maven.org/maven2",
+    ],
+    strict_visibility = True,
+)
+use_repo(maven, "external_deps")
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
new file mode 100644
index 0000000..fd0c91e
--- /dev/null
+++ b/MODULE.bazel.lock
@@ -0,0 +1,3291 @@
+{
+  "lockFileVersion": 13,
+  "registryFileHashes": {
+    "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
+    "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
+    "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
+    "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
+    "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
+    "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
+    "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
+    "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
+    "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
+    "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/MODULE.bazel": "d1086e248cda6576862b4b3fe9ad76a214e08c189af5b42557a6e1888812c5d5",
+    "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/source.json": "1b996859f840d8efc7c720efc61dcf2a84b1261cb3974cbbe9b6666ebf567775",
+    "https://bcr.bazel.build/modules/abseil-py/2.1.0/MODULE.bazel": "5ebe5bf853769c65707e5c28f216798f7a4b1042015e6a36e6d03094d94bec8a",
+    "https://bcr.bazel.build/modules/abseil-py/2.1.0/source.json": "0e8fc4f088ce07099c1cd6594c20c7ddbb48b4b3c0849b7d94ba94be88ff042b",
+    "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896",
+    "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
+    "https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b",
+    "https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef",
+    "https://bcr.bazel.build/modules/bazel_features/1.1.0/MODULE.bazel": "cfd42ff3b815a5f39554d97182657f8c4b9719568eb7fded2b9135f084bf760b",
+    "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
+    "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
+    "https://bcr.bazel.build/modules/bazel_features/1.13.0/MODULE.bazel": "c14c33c7c3c730612bdbe14ebbb5e61936b6f11322ea95a6e91cd1ba962f94df",
+    "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
+    "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
+    "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
+    "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
+    "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
+    "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a",
+    "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
+    "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9",
+    "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
+    "https://bcr.bazel.build/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc",
+    "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
+    "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
+    "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
+    "https://bcr.bazel.build/modules/bazel_worker_api/0.0.1/MODULE.bazel": "02a13b77321773b2042e70ee5e4c5e099c8ddee4cf2da9cd420442c36938d4bd",
+    "https://bcr.bazel.build/modules/bazel_worker_api/0.0.4/MODULE.bazel": "460aa12d01231a80cce03c548287b433b321d205b0028ae596728c35e5ee442e",
+    "https://bcr.bazel.build/modules/bazel_worker_api/0.0.4/source.json": "d353c410d47a8b65d09fa98e83d57ebec257a2c2b9c6e42d6fda1cb25e5464a5",
+    "https://bcr.bazel.build/modules/bazel_worker_java/0.0.4/MODULE.bazel": "82494a01018bb7ef06d4a17ec4cd7a758721f10eb8b6c820a818e70d669500db",
+    "https://bcr.bazel.build/modules/bazel_worker_java/0.0.4/source.json": "a2d30458fd86cf022c2b6331e652526fa08e17573b2f5034a9dbcacdf9c2583c",
+    "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
+    "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
+    "https://bcr.bazel.build/modules/gazelle/0.32.0/MODULE.bazel": "b499f58a5d0d3537f3cf5b76d8ada18242f64ec474d8391247438bf04f58c7b8",
+    "https://bcr.bazel.build/modules/gazelle/0.33.0/MODULE.bazel": "a13a0f279b462b784fb8dd52a4074526c4a2afe70e114c7d09066097a46b3350",
+    "https://bcr.bazel.build/modules/gazelle/0.34.0/MODULE.bazel": "abdd8ce4d70978933209db92e436deb3a8b737859e9354fb5fd11fb5c2004c8a",
+    "https://bcr.bazel.build/modules/gazelle/0.36.0/MODULE.bazel": "e375d5d6e9a6ca59b0cb38b0540bc9a05b6aa926d322f2de268ad267a2ee74c0",
+    "https://bcr.bazel.build/modules/gazelle/0.40.0/MODULE.bazel": "42ba5378ebe845fca43989a53186ab436d956db498acde790685fe0e8f9c6146",
+    "https://bcr.bazel.build/modules/gazelle/0.40.0/source.json": "1e5ef6e4d8b9b6836d93273c781e78ff829ea2e077afef7a57298040fa4f010a",
+    "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
+    "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
+    "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
+    "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
+    "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108",
+    "https://bcr.bazel.build/modules/googletest/1.15.2/source.json": "dbdda654dcb3a0d7a8bc5d0ac5fc7e150b58c2a986025ae5bc634bb2cb61f470",
+    "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
+    "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0",
+    "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000",
+    "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
+    "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
+    "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9",
+    "https://bcr.bazel.build/modules/package_metadata/0.0.7/MODULE.bazel": "7adb03933fc8401f495800cf4eafcff0edc6da0ff55c7db223ef69d19f689486",
+    "https://bcr.bazel.build/modules/package_metadata/0.0.7/source.json": "50639625e937b56115012674c797cca7a05a96b4878c87d803c13dc2b31de8a0",
+    "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
+    "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
+    "https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29",
+    "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
+    "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
+    "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
+    "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
+    "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
+    "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
+    "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
+    "https://bcr.bazel.build/modules/protobuf/23.1/MODULE.bazel": "88b393b3eb4101d18129e5db51847cd40a5517a53e81216144a8c32dfeeca52a",
+    "https://bcr.bazel.build/modules/protobuf/24.4/MODULE.bazel": "7bc7ce5f2abf36b3b7b7c8218d3acdebb9426aeb35c2257c96445756f970eb12",
+    "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
+    "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
+    "https://bcr.bazel.build/modules/protobuf/27.2/MODULE.bazel": "32450b50673882e4c8c3d10a83f3bc82161b213ed2f80d17e38bece8f165c295",
+    "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
+    "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
+    "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
+    "https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573",
+    "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858",
+    "https://bcr.bazel.build/modules/protobuf/31.1/MODULE.bazel": "379a389bb330b7b8c1cdf331cc90bf3e13de5614799b3b52cdb7c6f389f6b38e",
+    "https://bcr.bazel.build/modules/protobuf/31.1/source.json": "25af5d0219da0c0fc4d1191a24ce438e6ca7f49d2e1a94f354efeba6ef10426f",
+    "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
+    "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
+    "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680",
+    "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
+    "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a",
+    "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4",
+    "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa",
+    "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
+    "https://bcr.bazel.build/modules/rules_android/0.6.6/MODULE.bazel": "b0fb569752aab65ab1a9db0a8f6cfaf5aa1754965e17e95dcf0e4d88e192a68d",
+    "https://bcr.bazel.build/modules/rules_android/0.6.6/source.json": "a9d8dc2d5a102dc03269a94acc886a4cab82cdcb9ccbc77b0f665d6d17a6ae09",
+    "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a",
+    "https://bcr.bazel.build/modules/rules_apple/3.16.0/source.json": "d8b5fe461272018cc07cfafce11fe369c7525330804c37eec5a82f84cd475366",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
+    "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
+    "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
+    "https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8",
+    "https://bcr.bazel.build/modules/rules_cc/0.2.14/source.json": "55d0a4587c5592fad350f6e698530f4faf0e7dd15e69d43f8d87e220c78bea54",
+    "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
+    "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
+    "https://bcr.bazel.build/modules/rules_go/0.41.0/MODULE.bazel": "55861d8e8bb0e62cbd2896f60ff303f62ffcb0eddb74ecb0e5c0cbe36fc292c8",
+    "https://bcr.bazel.build/modules/rules_go/0.42.0/MODULE.bazel": "8cfa875b9aa8c6fce2b2e5925e73c1388173ea3c32a0db4d2b4804b453c14270",
+    "https://bcr.bazel.build/modules/rules_go/0.46.0/MODULE.bazel": "3477df8bdcc49e698b9d25f734c4f3a9f5931ff34ee48a2c662be168f5f2d3fd",
+    "https://bcr.bazel.build/modules/rules_go/0.50.1/MODULE.bazel": "b91a308dc5782bb0a8021ad4330c81fea5bda77f96b9e4c117b9b9c8f6665ee0",
+    "https://bcr.bazel.build/modules/rules_go/0.51.0-rc2/MODULE.bazel": "edfc3a9cea7bedb0eaaff37b0d7817c1a4bf72b3c615580b0ffcee6c52690fd4",
+    "https://bcr.bazel.build/modules/rules_go/0.51.0-rc2/source.json": "6b5cd0b3da2bd0e6949580851db990a04af0a285f072b9a0f059424457cd8cc9",
+    "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
+    "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
+    "https://bcr.bazel.build/modules/rules_java/6.3.0/MODULE.bazel": "a97c7678c19f236a956ad260d59c86e10a463badb7eb2eda787490f4c969b963",
+    "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
+    "https://bcr.bazel.build/modules/rules_java/7.1.0/MODULE.bazel": "30d9135a2b6561c761bd67bd4990da591e6bdc128790ce3e7afd6a3558b2fb64",
+    "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
+    "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
+    "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
+    "https://bcr.bazel.build/modules/rules_java/7.4.0/MODULE.bazel": "a592852f8a3dd539e82ee6542013bf2cadfc4c6946be8941e189d224500a8934",
+    "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
+    "https://bcr.bazel.build/modules/rules_java/7.6.5/MODULE.bazel": "481164be5e02e4cab6e77a36927683263be56b7e36fef918b458d7a8a1ebadb1",
+    "https://bcr.bazel.build/modules/rules_java/8.11.0/MODULE.bazel": "c3d280bc5ff1038dcb3bacb95d3f6b83da8dd27bba57820ec89ea4085da767ad",
+    "https://bcr.bazel.build/modules/rules_java/8.13.0/MODULE.bazel": "0444ebf737d144cf2bb2ccb368e7f1cce735264285f2a3711785827c1686625e",
+    "https://bcr.bazel.build/modules/rules_java/8.13.0/source.json": "4605c0f676b87dd9d1fabd4d743b71f04d97503bd1a79aad53f87399fb5396de",
+    "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
+    "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
+    "https://bcr.bazel.build/modules/rules_java/8.6.0/MODULE.bazel": "9c064c434606d75a086f15ade5edb514308cccd1544c2b2a89bbac4310e41c71",
+    "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
+    "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
+    "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
+    "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
+    "https://bcr.bazel.build/modules/rules_jvm_external/6.10/MODULE.bazel": "33e636ca6bc9ee0fa090a38aa33c631ded2d8cf6fead4124181d1b35dc474f7c",
+    "https://bcr.bazel.build/modules/rules_jvm_external/6.10/source.json": "c191249787625db72616a3fb3cc2786ab57355a2e3b615402b8b3b66b0f995b7",
+    "https://bcr.bazel.build/modules/rules_jvm_external/6.2/MODULE.bazel": "36a6e52487a855f33cb960724eb56547fa87e2c98a0474c3acad94339d7f8e99",
+    "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
+    "https://bcr.bazel.build/modules/rules_jvm_external/6.6/MODULE.bazel": "153042249c7060536dc95b6bb9f9bb8063b8a0b0cb7acdb381bddbc2374aed55",
+    "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd",
+    "https://bcr.bazel.build/modules/rules_kotlin/1.9.5/MODULE.bazel": "043a16a572f610558ec2030db3ff0c9938574e7dd9f58bded1bb07c0192ef025",
+    "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
+    "https://bcr.bazel.build/modules/rules_kotlin/2.1.3/MODULE.bazel": "ce7def6d576aa8d3a9c6d10e13b4d157296229674371f67dbf788dae0afae3d5",
+    "https://bcr.bazel.build/modules/rules_kotlin/2.1.3/source.json": "0b0dc9400f14b5fbb13d278ad3bf0413cdbaf0da0db337e055b855e35b878a3b",
+    "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
+    "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
+    "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
+    "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
+    "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
+    "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
+    "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
+    "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
+    "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
+    "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483",
+    "https://bcr.bazel.build/modules/rules_proto/6.0.0/MODULE.bazel": "b531d7f09f58dce456cd61b4579ce8c86b38544da75184eadaf0a7cb7966453f",
+    "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
+    "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
+    "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
+    "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
+    "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7",
+    "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
+    "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
+    "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
+    "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
+    "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
+    "https://bcr.bazel.build/modules/rules_python/0.37.1/MODULE.bazel": "3faeb2d9fa0a81f8980643ee33f212308f4d93eea4b9ce6f36d0b742e71e9500",
+    "https://bcr.bazel.build/modules/rules_python/0.37.2/MODULE.bazel": "b5ffde91410745750b6c13be1c5dc4555ef5bc50562af4a89fd77807fdde626a",
+    "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
+    "https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43",
+    "https://bcr.bazel.build/modules/rules_python/1.0.0/source.json": "b0162a65c6312e45e7912e39abd1a7f8856c2c7e41ecc9b6dc688a6f6400a917",
+    "https://bcr.bazel.build/modules/rules_robolectric/4.14.1.2/MODULE.bazel": "d44fec647d0aeb67b9f3b980cf68ba634976f3ae7ccd6c07d790b59b87a4f251",
+    "https://bcr.bazel.build/modules/rules_robolectric/4.14.1.2/source.json": "37c10335f2361c337c5c1f34ed36d2da70534c23088062b33a8bdaab68aa9dea",
+    "https://bcr.bazel.build/modules/rules_shell/0.1.2/MODULE.bazel": "66e4ca3ce084b04af0b9ff05ff14cab4e5df7503973818bb91cbc6cda08d32fc",
+    "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
+    "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
+    "https://bcr.bazel.build/modules/rules_shell/0.4.1/MODULE.bazel": "00e501db01bbf4e3e1dd1595959092c2fadf2087b2852d3f553b5370f5633592",
+    "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b",
+    "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c",
+    "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca",
+    "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046",
+    "https://bcr.bazel.build/modules/rules_swift/2.1.1/source.json": "40fc69dfaac64deddbb75bd99cdac55f4427d9ca0afbe408576a65428427a186",
+    "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
+    "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
+    "https://bcr.bazel.build/modules/stardoc/0.6.2/MODULE.bazel": "7060193196395f5dd668eda046ccbeacebfd98efc77fed418dbe2b82ffaa39fd",
+    "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
+    "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
+    "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
+    "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91",
+    "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/source.json": "32bd87e5f4d7acc57c5b2ff7c325ae3061d5e242c0c4c214ae87e0f1c13e54cb",
+    "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
+    "https://bcr.bazel.build/modules/upb/0.0.0-20230516-61a97ef/MODULE.bazel": "c0df5e35ad55e264160417fd0875932ee3c9dda63d9fccace35ac62f45e1b6f9",
+    "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
+    "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27",
+    "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
+    "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
+    "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
+    "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
+  },
+  "selectedYankedVersions": {},
+  "moduleExtensions": {
+    "@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": {
+      "general": {
+        "bzlTransitiveDigest": "ltCGFbl/LQQZXn/LEMXfKX7pGwyqNiOCHcmiQW0tmjM=",
+        "usagesDigest": "eXsWd8YDJDt7+F94YtjKuTAIRMWBi9JLS8hUiqynRIY=",
+        "recordedFileInputs": {},
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "local_config_apple_cc_toolchains": {
+            "bzlFile": "@@apple_support~//crosstool:setup.bzl",
+            "ruleClassName": "_apple_cc_autoconf_toolchains",
+            "attributes": {}
+          },
+          "local_config_apple_cc": {
+            "bzlFile": "@@apple_support~//crosstool:setup.bzl",
+            "ruleClassName": "_apple_cc_autoconf",
+            "attributes": {}
+          }
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "apple_support~",
+            "bazel_tools",
+            "bazel_tools"
+          ]
+        ]
+      }
+    },
+    "@@pybind11_bazel~//:internal_configure.bzl%internal_configure_extension": {
+      "general": {
+        "bzlTransitiveDigest": "CyAKLVVonohnkTSqg9II/HA7M49sOlnMkgMHL3CmDuc=",
+        "usagesDigest": "mFrTHX5eCiNU/OIIGVHH3cOILY9Zmjqk8RQYv8o6Thk=",
+        "recordedFileInputs": {
+          "@@pybind11_bazel~//MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34"
+        },
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "pybind11": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "build_file": "@@pybind11_bazel~//:pybind11-BUILD.bazel",
+              "strip_prefix": "pybind11-2.12.0",
+              "urls": [
+                "https://github.com/pybind/pybind11/archive/v2.12.0.zip"
+              ]
+            }
+          }
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "pybind11_bazel~",
+            "bazel_tools",
+            "bazel_tools"
+          ]
+        ]
+      }
+    },
+    "@@rules_android~//bzlmod_extensions:apksig.bzl%apksig_extension": {
+      "general": {
+        "bzlTransitiveDigest": "+fNvC5PNWx1aA64JjkW33+1zGbG9xgfi70xQhxbglhY=",
+        "usagesDigest": "TaGkNxVMBZxl1ANdUNPmIjKrA33bO+BpI06yTlpHdos=",
+        "recordedFileInputs": {},
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "apksig": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "url": "https://android.googlesource.com/platform/tools/apksig/+archive/24e3075e68ebe17c0b529bb24bfda819db5e2f3b.tar.gz",
+              "build_file": "@@rules_android~//bzlmod_extensions:apksig.BUILD"
+            }
+          }
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "rules_android~",
+            "bazel_tools",
+            "bazel_tools"
+          ]
+        ]
+      }
+    },
+    "@@rules_android~//bzlmod_extensions:com_android_dex.bzl%com_android_dex_extension": {
+      "general": {
+        "bzlTransitiveDigest": "/KJvxHLYhvSLJihEHN0e5Uzdd7OOMvpFb0BFUl1RUTs=",
+        "usagesDigest": "fh77SU1OUlWN5ivrGpY93+t0MipuVj89/MMUgfTpSa8=",
+        "recordedFileInputs": {},
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "com_android_dex": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "url": "https://android.googlesource.com/platform/dalvik/+archive/5a81c499a569731e2395f7c8d13c0e0d4e17a2b6.tar.gz",
+              "build_file": "@@rules_android~//bzlmod_extensions:com_android_dex.BUILD"
+            }
+          }
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "rules_android~",
+            "bazel_tools",
+            "bazel_tools"
+          ]
+        ]
+      }
+    },
+    "@@rules_android~//rules/android_sdk_repository:rule.bzl%android_sdk_repository_extension": {
+      "general": {
+        "bzlTransitiveDigest": "NAy+0M15JNVEBb8Tny6t7j3lKqTnsAMjoBB6LJ+C370=",
+        "usagesDigest": "weZLGEpNa+fTJZ9CEljWxpN3/kuPzj/ULgebzOt2h4g=",
+        "recordedFileInputs": {},
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "androidsdk": {
+            "bzlFile": "@@rules_android~//rules/android_sdk_repository:rule.bzl",
+            "ruleClassName": "_android_sdk_repository",
+            "attributes": {}
+          }
+        },
+        "recordedRepoMappingEntries": []
+      }
+    },
+    "@@rules_apple~//apple:apple.bzl%provisioning_profile_repository_extension": {
+      "general": {
+        "bzlTransitiveDigest": "OLmLOE2zg0CXXzAR24XTccdOw39pMG2gG6R1VFOgDsE=",
+        "usagesDigest": "cLx5XGjlbSDOpyA053y/jlr4GcaXFVTeHQic6eyG38E=",
+        "recordedFileInputs": {},
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "local_provisioning_profiles": {
+            "bzlFile": "@@rules_apple~//apple/internal:local_provisioning_profiles.bzl",
+            "ruleClassName": "provisioning_profile_repository",
+            "attributes": {}
+          }
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "apple_support~",
+            "bazel_skylib",
+            "bazel_skylib~"
+          ],
+          [
+            "rules_apple~",
+            "bazel_skylib",
+            "bazel_skylib~"
+          ],
+          [
+            "rules_apple~",
+            "bazel_tools",
+            "bazel_tools"
+          ],
+          [
+            "rules_apple~",
+            "build_bazel_apple_support",
+            "apple_support~"
+          ],
+          [
+            "rules_apple~",
+            "build_bazel_rules_swift",
+            "rules_swift~"
+          ],
+          [
+            "rules_swift~",
+            "bazel_skylib",
+            "bazel_skylib~"
+          ],
+          [
+            "rules_swift~",
+            "bazel_tools",
+            "bazel_tools"
+          ],
+          [
+            "rules_swift~",
+            "build_bazel_apple_support",
+            "apple_support~"
+          ],
+          [
+            "rules_swift~",
+            "build_bazel_rules_swift",
+            "rules_swift~"
+          ],
+          [
+            "rules_swift~",
+            "build_bazel_rules_swift_local_config",
+            "rules_swift~~non_module_deps~build_bazel_rules_swift_local_config"
+          ]
+        ]
+      }
+    },
+    "@@rules_apple~//apple:extensions.bzl%non_module_deps": {
+      "general": {
+        "bzlTransitiveDigest": "LJ3bhNqfW9y6MZFgtKQoPJyUMg/aEZ8H9QXSzK1VOBk=",
+        "usagesDigest": "5FfEPy/Z0Y2V9RbdJRDabgADFdvlfIIrps/5XYOnMNI=",
+        "recordedFileInputs": {},
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "xctestrunner": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/google/xctestrunner/archive/b7698df3d435b6491b4b4c0f9fc7a63fbed5e3a6.tar.gz"
+              ],
+              "strip_prefix": "xctestrunner-b7698df3d435b6491b4b4c0f9fc7a63fbed5e3a6",
+              "sha256": "ae3a063c985a8633cb7eb566db21656f8db8eb9a0edb8c182312c7f0db53730d"
+            }
+          }
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "rules_apple~",
+            "bazel_tools",
+            "bazel_tools"
+          ]
+        ]
+      }
+    },
+    "@@rules_kotlin~//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
+      "general": {
+        "bzlTransitiveDigest": "BSndOxBXlbe5qZf1NRxf828dpEK6tM429pCnaFoUFYs=",
+        "usagesDigest": "Dg5Nih77FaLAipQB7wgwsAy553a3po0eNGQVTZKgCM8=",
+        "recordedFileInputs": {},
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "com_github_jetbrains_kotlin_git": {
+            "bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:compiler.bzl",
+            "ruleClassName": "kotlin_compiler_git_repository",
+            "attributes": {
+              "urls": [
+                "https://github.com/JetBrains/kotlin/releases/download/v2.1.0/kotlin-compiler-2.1.0.zip"
+              ],
+              "sha256": "b6698d5728ad8f9edcdd01617d638073191d8a03139cc538a391b4e3759ad297"
+            }
+          },
+          "com_github_jetbrains_kotlin": {
+            "bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:compiler.bzl",
+            "ruleClassName": "kotlin_capabilities_repository",
+            "attributes": {
+              "git_repository_name": "com_github_jetbrains_kotlin_git",
+              "compiler_version": "2.1.0"
+            }
+          },
+          "com_github_google_ksp": {
+            "bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:ksp.bzl",
+            "ruleClassName": "ksp_compiler_plugin_repository",
+            "attributes": {
+              "urls": [
+                "https://github.com/google/ksp/releases/download/2.1.0-1.0.28/artifacts.zip"
+              ],
+              "sha256": "fc27b08cadc061a4a989af01cbeccb613feef1995f4aad68f2be0f886a3ee251",
+              "strip_version": "2.1.0-1.0.28"
+            }
+          },
+          "com_github_pinterest_ktlint": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_file",
+            "attributes": {
+              "sha256": "a9f923be58fbd32670a17f0b729b1df804af882fa57402165741cb26e5440ca1",
+              "urls": [
+                "https://github.com/pinterest/ktlint/releases/download/1.3.1/ktlint"
+              ],
+              "executable": true
+            }
+          },
+          "kotlinx_serialization_core_jvm": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_jar",
+            "attributes": {
+              "sha256": "29c821a8d4e25cbfe4f2ce96cdd4526f61f8f4e69a135f9612a34a81d93b65f1",
+              "urls": [
+                "https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-core-jvm/1.6.3/kotlinx-serialization-core-jvm-1.6.3.jar"
+              ]
+            }
+          },
+          "kotlinx_serialization_json": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_jar",
+            "attributes": {
+              "sha256": "8c0016890a79ab5980dd520a5ab1a6738023c29aa3b6437c482e0e5fdc06dab1",
+              "urls": [
+                "https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-json/1.6.3/kotlinx-serialization-json-1.6.3.jar"
+              ]
+            }
+          },
+          "kotlinx_serialization_json_jvm": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_jar",
+            "attributes": {
+              "sha256": "d3234179bcff1886d53d67c11eca47f7f3cf7b63c349d16965f6db51b7f3dd9a",
+              "urls": [
+                "https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-json-jvm/1.6.3/kotlinx-serialization-json-jvm-1.6.3.jar"
+              ]
+            }
+          }
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "rules_kotlin~",
+            "bazel_tools",
+            "bazel_tools"
+          ]
+        ]
+      }
+    },
+    "@@rules_python~//python/extensions:pip.bzl%pip": {
+      "general": {
+        "bzlTransitiveDigest": "AMoojKsX4Iw9GcO0xHbXz11GhPs9wzQ+Ua4OZ3muUzw=",
+        "usagesDigest": "ZVqDJcq4jlkbKBvSiotiO7ElR126/eiKOiKURsvOcoA=",
+        "recordedFileInputs": {
+          "@@rules_python~//tools/publish/requirements_linux.txt": "8175b4c8df50ae2f22d1706961884beeb54e7da27bd2447018314a175981997d",
+          "@@rules_python~//tools/publish/requirements_windows.txt": "7673adc71dc1a81d3661b90924d7a7c0fc998cd508b3cb4174337cef3f2de556",
+          "@@rules_python~//tools/publish/requirements_darwin.txt": "2994136eab7e57b083c3de76faf46f70fad130bc8e7360a7fed2b288b69e79dc"
+        },
+        "recordedDirentsInputs": {},
+        "envVariables": {
+          "RULES_PYTHON_REPO_DEBUG": null,
+          "RULES_PYTHON_REPO_DEBUG_VERBOSITY": null
+        },
+        "generatedRepoSpecs": {
+          "rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "backports.tarfile-1.2.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "backports-tarfile==1.2.0",
+              "sha256": "77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34",
+              "urls": [
+                "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "backports_tarfile-1.2.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "backports-tarfile==1.2.0",
+              "sha256": "d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991",
+              "urls": [
+                "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_certifi_py3_none_any_922820b5": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "certifi-2024.8.30-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "certifi==2024.8.30",
+              "sha256": "922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8",
+              "urls": [
+                "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_certifi_sdist_bec941d2": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "certifi-2024.8.30.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "certifi==2024.8.30",
+              "sha256": "bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9",
+              "urls": [
+                "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cffi==1.17.1",
+              "sha256": "a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41",
+              "urls": [
+                "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_ppc64le_46bf4316": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cffi==1.17.1",
+              "sha256": "46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1",
+              "urls": [
+                "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cffi==1.17.1",
+              "sha256": "a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6",
+              "urls": [
+                "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cffi==1.17.1",
+              "sha256": "610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cffi==1.17.1",
+              "sha256": "a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6",
+              "urls": [
+                "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cffi==1.17.1",
+              "sha256": "fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b",
+              "urls": [
+                "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cffi_sdist_1c39c601": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "cffi-1.17.1.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cffi==1.17.1",
+              "sha256": "1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824",
+              "urls": [
+                "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c",
+              "urls": [
+                "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944",
+              "urls": [
+                "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee",
+              "urls": [
+                "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c",
+              "urls": [
+                "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_ppc64le_ce031db0": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6",
+              "urls": [
+                "https://files.pythonhosted.org/packages/e2/29/d227805bff72ed6d6cb1ce08eec707f7cfbd9868044893617eb331f16295/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea",
+              "urls": [
+                "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc",
+              "urls": [
+                "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594",
+              "urls": [
+                "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_ppc64le_f1a2f519": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365",
+              "urls": [
+                "https://files.pythonhosted.org/packages/75/d2/0ab54463d3410709c09266dfb416d032a08f97fd7d60e94b8c6ef54ae14b/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129",
+              "urls": [
+                "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27",
+              "urls": [
+                "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "charset_normalizer-3.4.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079",
+              "urls": [
+                "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_charset_normalizer_sdist_223217c3": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "charset_normalizer-3.4.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "charset-normalizer==3.4.0",
+              "sha256": "223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e",
+              "urls": [
+                "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cryptography==43.0.3",
+              "sha256": "846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5",
+              "urls": [
+                "https://files.pythonhosted.org/packages/2f/78/55356eb9075d0be6e81b59f45c7b48df87f76a20e73893872170471f3ee8/cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cryptography==43.0.3",
+              "sha256": "0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4",
+              "urls": [
+                "https://files.pythonhosted.org/packages/2a/2c/488776a3dc843f95f86d2f957ca0fc3407d0242b50bede7fad1e339be03f/cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cryptography==43.0.3",
+              "sha256": "f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7",
+              "urls": [
+                "https://files.pythonhosted.org/packages/7c/04/2345ca92f7a22f601a9c62961741ef7dd0127c39f7310dffa0041c80f16f/cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cryptography==43.0.3",
+              "sha256": "c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ac/25/e715fa0bc24ac2114ed69da33adf451a38abb6f3f24ec207908112e9ba53/cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cryptography==43.0.3",
+              "sha256": "e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16",
+              "urls": [
+                "https://files.pythonhosted.org/packages/21/ce/b9c9ff56c7164d8e2edfb6c9305045fbc0df4508ccfdb13ee66eb8c95b0e/cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cryptography==43.0.3",
+              "sha256": "df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73",
+              "urls": [
+                "https://files.pythonhosted.org/packages/2a/33/b3682992ab2e9476b9c81fff22f02c8b0a1e6e1d49ee1750a67d85fd7ed2/cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_cryptography_sdist_315b9001": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "cryptography-43.0.3.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "cryptography==43.0.3",
+              "sha256": "315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805",
+              "urls": [
+                "https://files.pythonhosted.org/packages/0d/05/07b55d1fa21ac18c3a8c79f764e2514e6f6a9698f1be44994f5adf0d29db/cryptography-43.0.3.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "docutils-0.21.2-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "docutils==0.21.2",
+              "sha256": "dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2",
+              "urls": [
+                "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_docutils_sdist_3a6b1873": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "docutils-0.21.2.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "docutils==0.21.2",
+              "sha256": "3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_idna_py3_none_any_946d195a": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "idna-3.10-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "idna==3.10",
+              "sha256": "946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3",
+              "urls": [
+                "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_idna_sdist_12f65c9b": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "idna-3.10.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "idna==3.10",
+              "sha256": "12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
+              "urls": [
+                "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "importlib_metadata-8.5.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "importlib-metadata==8.5.0",
+              "sha256": "45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b",
+              "urls": [
+                "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_importlib_metadata_sdist_71522656": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "importlib_metadata-8.5.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "importlib-metadata==8.5.0",
+              "sha256": "71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7",
+              "urls": [
+                "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "jaraco.classes-3.4.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "jaraco-classes==3.4.0",
+              "sha256": "f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790",
+              "urls": [
+                "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "jaraco.classes-3.4.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "jaraco-classes==3.4.0",
+              "sha256": "47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd",
+              "urls": [
+                "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "jaraco.context-6.0.1-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "jaraco-context==6.0.1",
+              "sha256": "f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ff/db/0c52c4cf5e4bd9f5d7135ec7669a3a767af21b3a308e1ed3674881e52b62/jaraco.context-6.0.1-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "jaraco_context-6.0.1.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "jaraco-context==6.0.1",
+              "sha256": "9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3",
+              "urls": [
+                "https://files.pythonhosted.org/packages/df/ad/f3777b81bf0b6e7bc7514a1656d3e637b2e8e15fab2ce3235730b3e7a4e6/jaraco_context-6.0.1.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "jaraco.functools-4.1.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "jaraco-functools==4.1.0",
+              "sha256": "ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649",
+              "urls": [
+                "https://files.pythonhosted.org/packages/9f/4f/24b319316142c44283d7540e76c7b5a6dbd5db623abd86bb7b3491c21018/jaraco.functools-4.1.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "jaraco_functools-4.1.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "jaraco-functools==4.1.0",
+              "sha256": "70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ab/23/9894b3df5d0a6eb44611c36aec777823fc2e07740dabbd0b810e19594013/jaraco_functools-4.1.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "jeepney-0.8.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "jeepney==0.8.0",
+              "sha256": "c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ae/72/2a1e2290f1ab1e06f71f3d0f1646c9e4634e70e1d37491535e19266e8dc9/jeepney-0.8.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_jeepney_sdist_5efe48d2": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "jeepney-0.8.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "jeepney==0.8.0",
+              "sha256": "5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806",
+              "urls": [
+                "https://files.pythonhosted.org/packages/d6/f4/154cf374c2daf2020e05c3c6a03c91348d59b23c5366e968feb198306fdf/jeepney-0.8.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_keyring_py3_none_any_5426f817": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "keyring-25.4.1-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "keyring==25.4.1",
+              "sha256": "5426f817cf7f6f007ba5ec722b1bcad95a75b27d780343772ad76b17cb47b0bf",
+              "urls": [
+                "https://files.pythonhosted.org/packages/83/25/e6d59e5f0a0508d0dca8bb98c7f7fd3772fc943ac3f53d5ab18a218d32c0/keyring-25.4.1-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_keyring_sdist_b07ebc55": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "keyring-25.4.1.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "keyring==25.4.1",
+              "sha256": "b07ebc55f3e8ed86ac81dd31ef14e81ace9dd9c3d4b5d77a6e9a2016d0d71a1b",
+              "urls": [
+                "https://files.pythonhosted.org/packages/a5/1c/2bdbcfd5d59dc6274ffb175bc29aa07ecbfab196830e0cfbde7bd861a2ea/keyring-25.4.1.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "markdown_it_py-3.0.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "markdown-it-py==3.0.0",
+              "sha256": "355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1",
+              "urls": [
+                "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "markdown-it-py-3.0.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "markdown-it-py==3.0.0",
+              "sha256": "e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb",
+              "urls": [
+                "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_mdurl_py3_none_any_84008a41": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "mdurl-0.1.2-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "mdurl==0.1.2",
+              "sha256": "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8",
+              "urls": [
+                "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_mdurl_sdist_bb413d29": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "mdurl-0.1.2.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "mdurl==0.1.2",
+              "sha256": "bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba",
+              "urls": [
+                "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "more_itertools-10.5.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "more-itertools==10.5.0",
+              "sha256": "037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef",
+              "urls": [
+                "https://files.pythonhosted.org/packages/48/7e/3a64597054a70f7c86eb0a7d4fc315b8c1ab932f64883a297bdffeb5f967/more_itertools-10.5.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_more_itertools_sdist_5482bfef": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "more-itertools-10.5.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "more-itertools==10.5.0",
+              "sha256": "5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6",
+              "urls": [
+                "https://files.pythonhosted.org/packages/51/78/65922308c4248e0eb08ebcbe67c95d48615cc6f27854b6f2e57143e9178f/more-itertools-10.5.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "14c5a72e9fe82aea5fe3072116ad4661af5cf8e8ff8fc5ad3450f123e4925e86",
+              "urls": [
+                "https://files.pythonhosted.org/packages/b3/89/1daff5d9ba5a95a157c092c7c5f39b8dd2b1ddb4559966f808d31cfb67e0/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "7b7c2a3c9eb1a827d42539aa64091640bd275b81e097cd1d8d82ef91ffa2e811",
+              "urls": [
+                "https://files.pythonhosted.org/packages/2c/b6/42fc3c69cabf86b6b81e4c051a9b6e249c5ba9f8155590222c2622961f58/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "42c64511469005058cd17cc1537578eac40ae9f7200bedcfd1fc1a05f4f8c200",
+              "urls": [
+                "https://files.pythonhosted.org/packages/45/b9/833f385403abaf0023c6547389ec7a7acf141ddd9d1f21573723a6eab39a/nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "0411beb0589eacb6734f28d5497ca2ed379eafab8ad8c84b31bb5c34072b7164",
+              "urls": [
+                "https://files.pythonhosted.org/packages/05/2b/85977d9e11713b5747595ee61f381bc820749daf83f07b90b6c9964cf932/nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "5f36b271dae35c465ef5e9090e1fdaba4a60a56f0bb0ba03e0932a66f28b9189",
+              "urls": [
+                "https://files.pythonhosted.org/packages/72/f2/5c894d5265ab80a97c68ca36f25c8f6f0308abac649aaf152b74e7e854a8/nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64le_34c03fa7": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "34c03fa78e328c691f982b7c03d4423bdfd7da69cd707fe572f544cf74ac23ad",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ab/a7/375afcc710dbe2d64cfbd69e31f82f3e423d43737258af01f6a56d844085/nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "19aaba96e0f795bd0a6c56291495ff59364f4300d4a39b29a0abc9cb3774a84b",
+              "urls": [
+                "https://files.pythonhosted.org/packages/c2/a8/3bb02d0c60a03ad3a112b76c46971e9480efa98a8946677b5a59f60130ca/nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "de3ceed6e661954871d6cd78b410213bdcb136f79aafe22aa7182e028b8c7307",
+              "urls": [
+                "https://files.pythonhosted.org/packages/1b/63/6ab90d0e5225ab9780f6c9fb52254fa36b52bb7c188df9201d05b647e5e1/nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "f0eca9ca8628dbb4e916ae2491d72957fdd35f7a5d326b7032a345f111ac07fe",
+              "urls": [
+                "https://files.pythonhosted.org/packages/a3/da/0c4e282bc3cff4a0adf37005fa1fb42257673fbc1bbf7d1ff639ec3d255a/nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "3a157ab149e591bb638a55c8c6bcb8cdb559c8b12c13a8affaba6cedfe51713a",
+              "urls": [
+                "https://files.pythonhosted.org/packages/de/81/c291231463d21da5f8bba82c8167a6d6893cc5419b0639801ee5d3aeb8a9/nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "36c95d4b70530b320b365659bb5034341316e6a9b30f0b25fa9c9eff4c27a204",
+              "urls": [
+                "https://files.pythonhosted.org/packages/eb/61/73a007c74c37895fdf66e0edcd881f5eaa17a348ff02f4bb4bc906d61085/nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "nh3-0.2.18-cp37-abi3-win_amd64.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "8ce0f819d2f1933953fca255db2471ad58184a60508f03e6285e5114b6254844",
+              "urls": [
+                "https://files.pythonhosted.org/packages/26/8d/53c5b19c4999bdc6ba95f246f4ef35ca83d7d7423e5e38be43ad66544e5d/nh3-0.2.18-cp37-abi3-win_amd64.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_nh3_sdist_94a16692": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "nh3-0.2.18.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "nh3==0.2.18",
+              "sha256": "94a166927e53972a9698af9542ace4e38b9de50c34352b962f4d9a7d4c927af4",
+              "urls": [
+                "https://files.pythonhosted.org/packages/62/73/10df50b42ddb547a907deeb2f3c9823022580a7a47281e8eae8e003a9639/nh3-0.2.18.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "pkginfo-1.10.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "pkginfo==1.10.0",
+              "sha256": "889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097",
+              "urls": [
+                "https://files.pythonhosted.org/packages/56/09/054aea9b7534a15ad38a363a2bd974c20646ab1582a387a95b8df1bfea1c/pkginfo-1.10.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_pkginfo_sdist_5df73835": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "pkginfo-1.10.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "pkginfo==1.10.0",
+              "sha256": "5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297",
+              "urls": [
+                "https://files.pythonhosted.org/packages/2f/72/347ec5be4adc85c182ed2823d8d1c7b51e13b9a6b0c1aae59582eca652df/pkginfo-1.10.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "pycparser-2.22-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "pycparser==2.22",
+              "sha256": "c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc",
+              "urls": [
+                "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_pycparser_sdist_491c8be9": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "pycparser-2.22.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "pycparser==2.22",
+              "sha256": "491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6",
+              "urls": [
+                "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "pygments-2.18.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "pygments==2.18.0",
+              "sha256": "b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a",
+              "urls": [
+                "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_pygments_sdist_786ff802": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "pygments-2.18.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "pygments==2.18.0",
+              "sha256": "786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199",
+              "urls": [
+                "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_windows_x86_64"
+              ],
+              "filename": "pywin32_ctypes-0.2.3-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "pywin32-ctypes==0.2.3",
+              "sha256": "8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8",
+              "urls": [
+                "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "pywin32-ctypes-0.2.3.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "pywin32-ctypes==0.2.3",
+              "sha256": "d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755",
+              "urls": [
+                "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "readme_renderer-44.0-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "readme-renderer==44.0",
+              "sha256": "2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151",
+              "urls": [
+                "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_readme_renderer_sdist_8712034e": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "readme_renderer-44.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "readme-renderer==44.0",
+              "sha256": "8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1",
+              "urls": [
+                "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_requests_py3_none_any_70761cfe": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "requests-2.32.3-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "requests==2.32.3",
+              "sha256": "70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6",
+              "urls": [
+                "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_requests_sdist_55365417": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "requests-2.32.3.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "requests==2.32.3",
+              "sha256": "55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
+              "urls": [
+                "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "requests_toolbelt-1.0.0-py2.py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "requests-toolbelt==1.0.0",
+              "sha256": "cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06",
+              "urls": [
+                "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "requests-toolbelt-1.0.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "requests-toolbelt==1.0.0",
+              "sha256": "7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6",
+              "urls": [
+                "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "rfc3986-2.0.0-py2.py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "rfc3986==2.0.0",
+              "sha256": "50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_rfc3986_sdist_97aacf9d": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "rfc3986-2.0.0.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "rfc3986==2.0.0",
+              "sha256": "97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c",
+              "urls": [
+                "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_rich_py3_none_any_9836f509": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "rich-13.9.3-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "rich==13.9.3",
+              "sha256": "9836f5096eb2172c9e77df411c1b009bace4193d6a481d534fea75ebba758283",
+              "urls": [
+                "https://files.pythonhosted.org/packages/9a/e2/10e9819cf4a20bd8ea2f5dabafc2e6bf4a78d6a0965daeb60a4b34d1c11f/rich-13.9.3-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_rich_sdist_bc1e01b8": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "rich-13.9.3.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "rich==13.9.3",
+              "sha256": "bc1e01b899537598cf02579d2b9f4a415104d3fc439313a7a2c165d76557a08e",
+              "urls": [
+                "https://files.pythonhosted.org/packages/d9/e9/cf9ef5245d835065e6673781dbd4b8911d352fb770d56cf0879cf11b7ee1/rich-13.9.3.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "filename": "SecretStorage-3.3.3-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "secretstorage==3.3.3",
+              "sha256": "f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99",
+              "urls": [
+                "https://files.pythonhosted.org/packages/54/24/b4293291fa1dd830f353d2cb163295742fa87f179fcc8a20a306a81978b7/SecretStorage-3.3.3-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_secretstorage_sdist_2403533e": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "SecretStorage-3.3.3.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "secretstorage==3.3.3",
+              "sha256": "2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77",
+              "urls": [
+                "https://files.pythonhosted.org/packages/53/a4/f48c9d79cb507ed1373477dbceaba7401fd8a23af63b837fa61f1dcd3691/SecretStorage-3.3.3.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_twine_py3_none_any_215dbe7b": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "twine-5.1.1-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "twine==5.1.1",
+              "sha256": "215dbe7b4b94c2c50a7315c0275d2258399280fbb7d04182c7e55e24b5f93997",
+              "urls": [
+                "https://files.pythonhosted.org/packages/5d/ec/00f9d5fd040ae29867355e559a94e9a8429225a0284a3f5f091a3878bfc0/twine-5.1.1-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_twine_sdist_9aa08251": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "twine-5.1.1.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "twine==5.1.1",
+              "sha256": "9aa0825139c02b3434d913545c7b847a21c835e11597f5255842d457da2322db",
+              "urls": [
+                "https://files.pythonhosted.org/packages/77/68/bd982e5e949ef8334e6f7dcf76ae40922a8750aa2e347291ae1477a4782b/twine-5.1.1.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "urllib3-2.2.3-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "urllib3==2.2.3",
+              "sha256": "ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_urllib3_sdist_e7d814a8": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "urllib3-2.2.3.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "urllib3==2.2.3",
+              "sha256": "e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9",
+              "urls": [
+                "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_zipp_py3_none_any_a817ac80": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "filename": "zipp-3.20.2-py3-none-any.whl",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "zipp==3.20.2",
+              "sha256": "a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350",
+              "urls": [
+                "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl"
+              ]
+            }
+          },
+          "rules_python_publish_deps_311_zipp_sdist_bc9eb26f": {
+            "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl",
+            "ruleClassName": "whl_library",
+            "attributes": {
+              "dep_template": "@rules_python_publish_deps//{name}:{target}",
+              "experimental_target_platforms": [
+                "cp311_linux_aarch64",
+                "cp311_linux_arm",
+                "cp311_linux_ppc",
+                "cp311_linux_s390x",
+                "cp311_linux_x86_64",
+                "cp311_osx_aarch64",
+                "cp311_osx_x86_64",
+                "cp311_windows_x86_64"
+              ],
+              "extra_pip_args": [
+                "--index-url",
+                "https://pypi.org/simple"
+              ],
+              "filename": "zipp-3.20.2.tar.gz",
+              "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python",
+              "repo": "rules_python_publish_deps_311",
+              "requirement": "zipp==3.20.2",
+              "sha256": "bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29",
+              "urls": [
+                "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz"
+              ]
+            }
+          },
+          "rules_python_publish_deps": {
+            "bzlFile": "@@rules_python~//python/private/pypi:hub_repository.bzl",
+            "ruleClassName": "hub_repository",
+            "attributes": {
+              "repo_name": "rules_python_publish_deps",
+              "extra_hub_aliases": {},
+              "whl_map": {
+                "backports_tarfile": "{\"rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7\":[{\"filename\":\"backports.tarfile-1.2.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2\":[{\"filename\":\"backports_tarfile-1.2.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "certifi": "{\"rules_python_publish_deps_311_certifi_py3_none_any_922820b5\":[{\"filename\":\"certifi-2024.8.30-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_certifi_sdist_bec941d2\":[{\"filename\":\"certifi-2024.8.30.tar.gz\",\"version\":\"3.11\"}]}",
+                "cffi": "{\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_ppc64le_46bf4316\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_sdist_1c39c601\":[{\"filename\":\"cffi-1.17.1.tar.gz\",\"version\":\"3.11\"}]}",
+                "charset_normalizer": "{\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_ppc64le_ce031db0\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_ppc64le_f1a2f519\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe\":[{\"filename\":\"charset_normalizer-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_sdist_223217c3\":[{\"filename\":\"charset_normalizer-3.4.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "cryptography": "{\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_sdist_315b9001\":[{\"filename\":\"cryptography-43.0.3.tar.gz\",\"version\":\"3.11\"}]}",
+                "docutils": "{\"rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9\":[{\"filename\":\"docutils-0.21.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_docutils_sdist_3a6b1873\":[{\"filename\":\"docutils-0.21.2.tar.gz\",\"version\":\"3.11\"}]}",
+                "idna": "{\"rules_python_publish_deps_311_idna_py3_none_any_946d195a\":[{\"filename\":\"idna-3.10-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_idna_sdist_12f65c9b\":[{\"filename\":\"idna-3.10.tar.gz\",\"version\":\"3.11\"}]}",
+                "importlib_metadata": "{\"rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197\":[{\"filename\":\"importlib_metadata-8.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_importlib_metadata_sdist_71522656\":[{\"filename\":\"importlib_metadata-8.5.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "jaraco_classes": "{\"rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b\":[{\"filename\":\"jaraco.classes-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5\":[{\"filename\":\"jaraco.classes-3.4.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "jaraco_context": "{\"rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48\":[{\"filename\":\"jaraco.context-6.0.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5\":[{\"filename\":\"jaraco_context-6.0.1.tar.gz\",\"version\":\"3.11\"}]}",
+                "jaraco_functools": "{\"rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13\":[{\"filename\":\"jaraco.functools-4.1.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2\":[{\"filename\":\"jaraco_functools-4.1.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "jeepney": "{\"rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad\":[{\"filename\":\"jeepney-0.8.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jeepney_sdist_5efe48d2\":[{\"filename\":\"jeepney-0.8.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "keyring": "{\"rules_python_publish_deps_311_keyring_py3_none_any_5426f817\":[{\"filename\":\"keyring-25.4.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_keyring_sdist_b07ebc55\":[{\"filename\":\"keyring-25.4.1.tar.gz\",\"version\":\"3.11\"}]}",
+                "markdown_it_py": "{\"rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684\":[{\"filename\":\"markdown_it_py-3.0.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94\":[{\"filename\":\"markdown-it-py-3.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "mdurl": "{\"rules_python_publish_deps_311_mdurl_py3_none_any_84008a41\":[{\"filename\":\"mdurl-0.1.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_mdurl_sdist_bb413d29\":[{\"filename\":\"mdurl-0.1.2.tar.gz\",\"version\":\"3.11\"}]}",
+                "more_itertools": "{\"rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32\":[{\"filename\":\"more_itertools-10.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_more_itertools_sdist_5482bfef\":[{\"filename\":\"more-itertools-10.5.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "nh3": "{\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64le_34c03fa7\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_sdist_94a16692\":[{\"filename\":\"nh3-0.2.18.tar.gz\",\"version\":\"3.11\"}]}",
+                "pkginfo": "{\"rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2\":[{\"filename\":\"pkginfo-1.10.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pkginfo_sdist_5df73835\":[{\"filename\":\"pkginfo-1.10.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "pycparser": "{\"rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d\":[{\"filename\":\"pycparser-2.22-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pycparser_sdist_491c8be9\":[{\"filename\":\"pycparser-2.22.tar.gz\",\"version\":\"3.11\"}]}",
+                "pygments": "{\"rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0\":[{\"filename\":\"pygments-2.18.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pygments_sdist_786ff802\":[{\"filename\":\"pygments-2.18.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "pywin32_ctypes": "{\"rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337\":[{\"filename\":\"pywin32_ctypes-0.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04\":[{\"filename\":\"pywin32-ctypes-0.2.3.tar.gz\",\"version\":\"3.11\"}]}",
+                "readme_renderer": "{\"rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b\":[{\"filename\":\"readme_renderer-44.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_readme_renderer_sdist_8712034e\":[{\"filename\":\"readme_renderer-44.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "requests": "{\"rules_python_publish_deps_311_requests_py3_none_any_70761cfe\":[{\"filename\":\"requests-2.32.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_sdist_55365417\":[{\"filename\":\"requests-2.32.3.tar.gz\",\"version\":\"3.11\"}]}",
+                "requests_toolbelt": "{\"rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66\":[{\"filename\":\"requests_toolbelt-1.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3\":[{\"filename\":\"requests-toolbelt-1.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "rfc3986": "{\"rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b\":[{\"filename\":\"rfc3986-2.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rfc3986_sdist_97aacf9d\":[{\"filename\":\"rfc3986-2.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+                "rich": "{\"rules_python_publish_deps_311_rich_py3_none_any_9836f509\":[{\"filename\":\"rich-13.9.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rich_sdist_bc1e01b8\":[{\"filename\":\"rich-13.9.3.tar.gz\",\"version\":\"3.11\"}]}",
+                "secretstorage": "{\"rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662\":[{\"filename\":\"SecretStorage-3.3.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_secretstorage_sdist_2403533e\":[{\"filename\":\"SecretStorage-3.3.3.tar.gz\",\"version\":\"3.11\"}]}",
+                "twine": "{\"rules_python_publish_deps_311_twine_py3_none_any_215dbe7b\":[{\"filename\":\"twine-5.1.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_twine_sdist_9aa08251\":[{\"filename\":\"twine-5.1.1.tar.gz\",\"version\":\"3.11\"}]}",
+                "urllib3": "{\"rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0\":[{\"filename\":\"urllib3-2.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_urllib3_sdist_e7d814a8\":[{\"filename\":\"urllib3-2.2.3.tar.gz\",\"version\":\"3.11\"}]}",
+                "zipp": "{\"rules_python_publish_deps_311_zipp_py3_none_any_a817ac80\":[{\"filename\":\"zipp-3.20.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_zipp_sdist_bc9eb26f\":[{\"filename\":\"zipp-3.20.2.tar.gz\",\"version\":\"3.11\"}]}"
+              },
+              "packages": [
+                "backports_tarfile",
+                "certifi",
+                "charset_normalizer",
+                "docutils",
+                "idna",
+                "importlib_metadata",
+                "jaraco_classes",
+                "jaraco_context",
+                "jaraco_functools",
+                "keyring",
+                "markdown_it_py",
+                "mdurl",
+                "more_itertools",
+                "nh3",
+                "pkginfo",
+                "pygments",
+                "readme_renderer",
+                "requests",
+                "requests_toolbelt",
+                "rfc3986",
+                "rich",
+                "twine",
+                "urllib3",
+                "zipp"
+              ],
+              "groups": {}
+            }
+          }
+        },
+        "moduleExtensionMetadata": {
+          "useAllRepos": "NO",
+          "reproducible": false
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "bazel_features~",
+            "bazel_features_globals",
+            "bazel_features~~version_extension~bazel_features_globals"
+          ],
+          [
+            "bazel_features~",
+            "bazel_features_version",
+            "bazel_features~~version_extension~bazel_features_version"
+          ],
+          [
+            "rules_python~",
+            "bazel_features",
+            "bazel_features~"
+          ],
+          [
+            "rules_python~",
+            "bazel_skylib",
+            "bazel_skylib~"
+          ],
+          [
+            "rules_python~",
+            "bazel_tools",
+            "bazel_tools"
+          ],
+          [
+            "rules_python~",
+            "pypi__build",
+            "rules_python~~internal_deps~pypi__build"
+          ],
+          [
+            "rules_python~",
+            "pypi__click",
+            "rules_python~~internal_deps~pypi__click"
+          ],
+          [
+            "rules_python~",
+            "pypi__colorama",
+            "rules_python~~internal_deps~pypi__colorama"
+          ],
+          [
+            "rules_python~",
+            "pypi__importlib_metadata",
+            "rules_python~~internal_deps~pypi__importlib_metadata"
+          ],
+          [
+            "rules_python~",
+            "pypi__installer",
+            "rules_python~~internal_deps~pypi__installer"
+          ],
+          [
+            "rules_python~",
+            "pypi__more_itertools",
+            "rules_python~~internal_deps~pypi__more_itertools"
+          ],
+          [
+            "rules_python~",
+            "pypi__packaging",
+            "rules_python~~internal_deps~pypi__packaging"
+          ],
+          [
+            "rules_python~",
+            "pypi__pep517",
+            "rules_python~~internal_deps~pypi__pep517"
+          ],
+          [
+            "rules_python~",
+            "pypi__pip",
+            "rules_python~~internal_deps~pypi__pip"
+          ],
+          [
+            "rules_python~",
+            "pypi__pip_tools",
+            "rules_python~~internal_deps~pypi__pip_tools"
+          ],
+          [
+            "rules_python~",
+            "pypi__pyproject_hooks",
+            "rules_python~~internal_deps~pypi__pyproject_hooks"
+          ],
+          [
+            "rules_python~",
+            "pypi__setuptools",
+            "rules_python~~internal_deps~pypi__setuptools"
+          ],
+          [
+            "rules_python~",
+            "pypi__tomli",
+            "rules_python~~internal_deps~pypi__tomli"
+          ],
+          [
+            "rules_python~",
+            "pypi__wheel",
+            "rules_python~~internal_deps~pypi__wheel"
+          ],
+          [
+            "rules_python~",
+            "pypi__zipp",
+            "rules_python~~internal_deps~pypi__zipp"
+          ],
+          [
+            "rules_python~",
+            "pythons_hub",
+            "rules_python~~python~pythons_hub"
+          ],
+          [
+            "rules_python~~python~pythons_hub",
+            "python_3_10_host",
+            "rules_python~~python~python_3_10_host"
+          ],
+          [
+            "rules_python~~python~pythons_hub",
+            "python_3_11_host",
+            "rules_python~~python~python_3_11_host"
+          ],
+          [
+            "rules_python~~python~pythons_hub",
+            "python_3_12_host",
+            "rules_python~~python~python_3_12_host"
+          ],
+          [
+            "rules_python~~python~pythons_hub",
+            "python_3_9_host",
+            "rules_python~~python~python_3_9_host"
+          ]
+        ]
+      }
+    },
+    "@@rules_swift~//swift:extensions.bzl%non_module_deps": {
+      "general": {
+        "bzlTransitiveDigest": "vhXfCi07IAmWf5hLHcxh5xCtTwvEGrmMkOavEMD5pzs=",
+        "usagesDigest": "/dVEtCLqIAaLXjfRXsJupTS9pTgmYVN/tFdJlGgE5NA=",
+        "recordedFileInputs": {},
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "com_github_apple_swift_protobuf": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-protobuf/archive/1.20.2.tar.gz"
+              ],
+              "sha256": "3fb50bd4d293337f202d917b6ada22f9548a0a0aed9d9a4d791e6fbd8a246ebb",
+              "strip_prefix": "swift-protobuf-1.20.2/",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_protobuf/BUILD.overlay"
+            }
+          },
+          "com_github_grpc_grpc_swift": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/grpc/grpc-swift/archive/1.16.0.tar.gz"
+              ],
+              "sha256": "58b60431d0064969f9679411264b82e40a217ae6bd34e17096d92cc4e47556a5",
+              "strip_prefix": "grpc-swift-1.16.0/",
+              "build_file": "@@rules_swift~//third_party:com_github_grpc_grpc_swift/BUILD.overlay"
+            }
+          },
+          "com_github_apple_swift_docc_symbolkit": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-docc-symbolkit/archive/refs/tags/swift-5.10-RELEASE.tar.gz"
+              ],
+              "sha256": "de1d4b6940468ddb53b89df7aa1a81323b9712775b0e33e8254fa0f6f7469a97",
+              "strip_prefix": "swift-docc-symbolkit-swift-5.10-RELEASE",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_docc_symbolkit/BUILD.overlay"
+            }
+          },
+          "com_github_apple_swift_nio": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-nio/archive/2.42.0.tar.gz"
+              ],
+              "sha256": "e3304bc3fb53aea74a3e54bd005ede11f6dc357117d9b1db642d03aea87194a0",
+              "strip_prefix": "swift-nio-2.42.0/",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio/BUILD.overlay"
+            }
+          },
+          "com_github_apple_swift_nio_http2": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-nio-http2/archive/1.26.0.tar.gz"
+              ],
+              "sha256": "f0edfc9d6a7be1d587e5b403f2d04264bdfae59aac1d74f7d974a9022c6d2b25",
+              "strip_prefix": "swift-nio-http2-1.26.0/",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio_http2/BUILD.overlay"
+            }
+          },
+          "com_github_apple_swift_nio_transport_services": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-nio-transport-services/archive/1.15.0.tar.gz"
+              ],
+              "sha256": "f3498dafa633751a52b9b7f741f7ac30c42bcbeb3b9edca6d447e0da8e693262",
+              "strip_prefix": "swift-nio-transport-services-1.15.0/",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio_transport_services/BUILD.overlay"
+            }
+          },
+          "com_github_apple_swift_nio_extras": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-nio-extras/archive/1.4.0.tar.gz"
+              ],
+              "sha256": "4684b52951d9d9937bb3e8ccd6b5daedd777021ef2519ea2f18c4c922843b52b",
+              "strip_prefix": "swift-nio-extras-1.4.0/",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio_extras/BUILD.overlay"
+            }
+          },
+          "com_github_apple_swift_log": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-log/archive/1.4.4.tar.gz"
+              ],
+              "sha256": "48fe66426c784c0c20031f15dc17faf9f4c9037c192bfac2f643f65cb2321ba0",
+              "strip_prefix": "swift-log-1.4.4/",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_log/BUILD.overlay"
+            }
+          },
+          "com_github_apple_swift_nio_ssl": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-nio-ssl/archive/2.23.0.tar.gz"
+              ],
+              "sha256": "4787c63f61dd04d99e498adc3d1a628193387e41efddf8de19b8db04544d016d",
+              "strip_prefix": "swift-nio-ssl-2.23.0/",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio_ssl/BUILD.overlay"
+            }
+          },
+          "com_github_apple_swift_collections": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-collections/archive/1.0.4.tar.gz"
+              ],
+              "sha256": "d9e4c8a91c60fb9c92a04caccbb10ded42f4cb47b26a212bc6b39cc390a4b096",
+              "strip_prefix": "swift-collections-1.0.4/",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_collections/BUILD.overlay"
+            }
+          },
+          "com_github_apple_swift_atomics": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "urls": [
+                "https://github.com/apple/swift-atomics/archive/1.1.0.tar.gz"
+              ],
+              "sha256": "1bee7f469f7e8dc49f11cfa4da07182fbc79eab000ec2c17bfdce468c5d276fb",
+              "strip_prefix": "swift-atomics-1.1.0/",
+              "build_file": "@@rules_swift~//third_party:com_github_apple_swift_atomics/BUILD.overlay"
+            }
+          },
+          "build_bazel_rules_swift_index_import": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "build_file": "@@rules_swift~//third_party:build_bazel_rules_swift_index_import/BUILD.overlay",
+              "canonical_id": "index-import-5.8",
+              "urls": [
+                "https://github.com/MobileNativeFoundation/index-import/releases/download/5.8.0.1/index-import.tar.gz"
+              ],
+              "sha256": "28c1ffa39d99e74ed70623899b207b41f79214c498c603915aef55972a851a15"
+            }
+          },
+          "build_bazel_rules_swift_local_config": {
+            "bzlFile": "@@rules_swift~//swift/internal:swift_autoconfiguration.bzl",
+            "ruleClassName": "swift_autoconfiguration",
+            "attributes": {}
+          }
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "rules_swift~",
+            "bazel_tools",
+            "bazel_tools"
+          ],
+          [
+            "rules_swift~",
+            "build_bazel_rules_swift",
+            "rules_swift~"
+          ]
+        ]
+      }
+    }
+  }
+}
diff --git a/WORKSPACE b/WORKSPACE
index b6ef0b0..6ba4a02 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,359 +1,2 @@
-workspace(name = "jgit")
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-load("//tools:bazlets.bzl", "load_bazlets")
-
-load_bazlets(commit = "156bae8bb0d329d8886f681c723979cbdb39d37c")
-
-load(
-    "@com_googlesource_gerrit_bazlets//tools:maven_jar.bzl",
-    "maven_jar",
-)
-
-http_archive(
-    name = "rules_java",
-    sha256 = "4da3761f6855ad916568e2bfe86213ba6d2637f56b8360538a7fb6125abf6518",
-    urls = [
-        "https://github.com/bazelbuild/rules_java/releases/download/7.5.0/rules_java-7.5.0.tar.gz",
-    ],
-)
-
-load("@rules_java//java:repositories.bzl", "rules_java_dependencies", "rules_java_toolchains")
-
-rules_java_dependencies()
-
-http_archive(
-    name = "rules_shell",
-    sha256 = "e6b87c89bd0b27039e3af2c5da01147452f240f75d505f5b6880874f31036307",
-    strip_prefix = "rules_shell-0.6.1",
-    urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/rules_shell/releases/download/v0.6.1/rules_shell-v0.6.1.tar.gz",
-        "https://github.com/bazelbuild/rules_shell/releases/download/v0.6.1/rules_shell-v0.6.1.tar.gz",
-    ],
-)
-
-load("@rules_shell//shell:repositories.bzl", "rules_shell_dependencies", "rules_shell_toolchains")
-
-rules_shell_dependencies()
-
-http_archive(
-    name = "ubuntu2204_jdk17",
-    sha256 = "8ea82b81c9707e535ff93ef5349d11e55b2a23c62bcc3b0faaec052144aed87d",
-    strip_prefix = "rbe_autoconfig-5.1.0",
-    urls = [
-        "https://gerrit-bazel.storage.googleapis.com/rbe_autoconfig/v5.1.0.tar.gz",
-        "https://github.com/davido/rbe_autoconfig/releases/download/v5.1.0/v5.1.0.tar.gz",
-    ],
-)
-
-register_toolchains("//tools:error_prone_warnings_toolchain_java17_definition")
-
-register_toolchains("//tools:error_prone_warnings_toolchain_java21_definition")
-
-# Order of registering toolchains matters. rules_java toolchains take precedence
-# over the custom toolchains, so the default jdk21 toolchain gets picked
-# (one without custom package_config). That's why the `rules_java_toolchains()`
-# must be called after the `register_toolchain()` invocation.
-rules_java_toolchains()
-
-rules_shell_toolchains()
-
-JMH_VERS = "1.37"
-
-maven_jar(
-    name = "jmh-core",
-    artifact = "org.openjdk.jmh:jmh-core:" + JMH_VERS,
-    attach_source = False,
-    sha1 = "896f27e49105b35ea1964319c83d12082e7a79ef",
-)
-
-maven_jar(
-    name = "jmh-annotations",
-    artifact = "org.openjdk.jmh:jmh-generator-annprocess:" + JMH_VERS,
-    attach_source = False,
-    sha1 = "da93888682df163144edf9b13d2b78e54166063a",
-)
-
-maven_jar(
-    name = "jopt",
-    artifact = "net.sf.jopt-simple:jopt-simple:5.0.4",
-    attach_source = False,
-    sha1 = "4fdac2fbe92dfad86aa6e9301736f6b4342a3f5c",
-)
-
-maven_jar(
-    name = "math3",
-    artifact = "org.apache.commons:commons-math3:3.6.1",
-    attach_source = False,
-    sha1 = "e4ba98f1d4b3c80ec46392f25e094a6a2e58fcbf",
-)
-
-maven_jar(
-    name = "jsch",
-    artifact = "com.jcraft:jsch:0.1.55",
-    sha1 = "bbd40e5aa7aa3cfad5db34965456cee738a42a50",
-)
-
-maven_jar(
-    name = "jzlib",
-    artifact = "com.jcraft:jzlib:1.1.3",
-    sha1 = "c01428efa717624f7aabf4df319939dda9646b2d",
-)
-
-maven_jar(
-    name = "javaewah",
-    artifact = "com.googlecode.javaewah:JavaEWAH:1.2.3",
-    sha1 = "13a27c856e0c8808cee9a64032c58eee11c3adc9",
-)
-
-maven_jar(
-    name = "httpclient",
-    artifact = "org.apache.httpcomponents:httpclient:4.5.14",
-    sha1 = "1194890e6f56ec29177673f2f12d0b8e627dec98",
-)
-
-maven_jar(
-    name = "httpcore",
-    artifact = "org.apache.httpcomponents:httpcore:4.4.16",
-    sha1 = "51cf043c87253c9f58b539c9f7e44c8894223850",
-)
-
-SSHD_VERS = "2.16.0"
-
-maven_jar(
-    name = "sshd-osgi",
-    artifact = "org.apache.sshd:sshd-osgi:" + SSHD_VERS,
-    sha1 = "87cab2aaa6e06c5d48d746e90f0b3635f8c06419",
-)
-
-maven_jar(
-    name = "sshd-sftp",
-    artifact = "org.apache.sshd:sshd-sftp:" + SSHD_VERS,
-    sha1 = "09d9e7024535fb4a3f74367ba7e0a2f5093af638",
-)
-
-JNA_VERS = "5.18.1"
-
-maven_jar(
-    name = "jna",
-    artifact = "net.java.dev.jna:jna:" + JNA_VERS,
-    sha1 = "b27ba04287cc4abe769642fe8318d39fc89bf937",
-)
-
-maven_jar(
-    name = "jna-platform",
-    artifact = "net.java.dev.jna:jna-platform:" + JNA_VERS,
-    sha1 = "dd817f391efc492041c9ae91127527c13750a789",
-)
-
-maven_jar(
-    name = "commons-codec",
-    artifact = "commons-codec:commons-codec:1.20.0",
-    sha1 = "6a671d1c456a875ff61abec63216f754078bb0ed",
-)
-
-maven_jar(
-    name = "commons-logging",
-    artifact = "commons-logging:commons-logging:1.3.5",
-    sha1 = "a3fcc5d3c29b2b03433aa2d2f2d2c1b1638924a1",
-)
-
-SLF4J_VERS = "2.0.17"
-
-maven_jar(
-    name = "log-api",
-    artifact = "org.slf4j:slf4j-api:" + SLF4J_VERS,
-    sha1 = "d9e58ac9c7779ba3bf8142aff6c830617a7fe60f",
-)
-
-maven_jar(
-    name = "slf4j-simple",
-    artifact = "org.slf4j:slf4j-simple:" + SLF4J_VERS,
-    sha1 = "9872a3fd794ffe7b18d17747926a64d61526ca96",
-)
-
-maven_jar(
-    name = "servlet-api",
-    artifact = "jakarta.servlet:jakarta.servlet-api:6.1.0",
-    sha1 = "1169a246913fe3823782af7943e7a103634867c5",
-)
-
-maven_jar(
-    name = "javax-servlet-api",
-    artifact = "javax.servlet:javax.servlet-api:4.0.1",
-    sha1 = "a27082684a2ff0bf397666c3943496c44541d1ca",
-)
-
-maven_jar(
-    name = "commons-compress",
-    artifact = "org.apache.commons:commons-compress:1.28.0",
-    sha1 = "e482f2c7a88dac3c497e96aa420b6a769f59c8d7",
-)
-
-maven_jar(
-    name = "commons-lang3",
-    artifact = "org.apache.commons:commons-lang3:3.20.0",
-    sha1 = "65897b3e5731220962e659e001904af3c3cbeba9",
-)
-
-maven_jar(
-    name = "commons-io",
-    artifact = "commons-io:commons-io:2.21.0",
-    sha1 = "52a6f68fe5afe335cde95461dd5c3412f04996f7",
-)
-
-maven_jar(
-    name = "tukaani-xz",
-    artifact = "org.tukaani:xz:1.11",
-    sha1 = "bdfd1774efb216f506f4f3c5b08c205b308c50aa",
-)
-
-maven_jar(
-    name = "args4j",
-    artifact = "args4j:args4j:2.37",
-    sha1 = "244f60c057d72a785227c0562d3560f42a7ea54b",
-)
-
-maven_jar(
-    name = "junit",
-    artifact = "junit:junit:4.13.2",
-    sha1 = "8ac9e16d933b6fb43bc7f576336b8f4d7eb5ba12",
-)
-
-maven_jar(
-    name = "hamcrest",
-    artifact = "org.hamcrest:hamcrest:3.0",
-    sha1 = "8fd9b78a8e6a6510a078a9e30e9e86a6035cfaf7",
-)
-
-maven_jar(
-    name = "mockito",
-    artifact = "org.mockito:mockito-core:5.20.0",
-    sha1 = "a32f446f38acf636363c5693db6498047731b9e0",
-)
-
-maven_jar(
-    name = "assertj-core",
-    artifact = "org.assertj:assertj-core:3.27.6",
-    sha1 = "8f34ccd6808899ad1d0aac6a770b73191f2f2a53",
-)
-
-BYTE_BUDDY_VERSION = "1.18.1"
-
-maven_jar(
-    name = "bytebuddy",
-    artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
-    sha1 = "b7bc5138c3250d4b065caccc89666bf25e4de392",
-)
-
-maven_jar(
-    name = "bytebuddy-agent",
-    artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
-    sha1 = "d8e26676f505594ef51dfd275218fcc21c3656ef",
-)
-
-maven_jar(
-    name = "objenesis",
-    artifact = "org.objenesis:objenesis:3.4",
-    sha1 = "675cbe121a68019235d27f6c34b4f0ac30e07418",
-)
-
-maven_jar(
-    name = "gson",
-    artifact = "com.google.code.gson:gson:2.13.2",
-    sha1 = "48b8230771e573b54ce6e867a9001e75977fe78e",
-)
-
-JETTY_VER = "12.1.4"
-
-maven_jar(
-    name = "jetty-servlet",
-    artifact = "org.eclipse.jetty.ee10:jetty-ee10-servlet:" + JETTY_VER,
-    sha1 = "77ce63899d8a3d65ccdd68c6948faab9899ad66d",
-)
-
-maven_jar(
-    name = "jetty-ee8-nested",
-    artifact = "org.eclipse.jetty.ee8:jetty-ee8-nested:" + JETTY_VER,
-    sha1 = "f0f7177357594c872a6da340dbcc748fbdaa4048",
-)
-
-maven_jar(
-    name = "jetty-security-ee8",
-    artifact = "org.eclipse.jetty.ee8:jetty-ee8-security:" + JETTY_VER,
-    sha1 = "605d9573c48b7852b7b50aad870b130db93d42d6",
-)
-
-maven_jar(
-    name = "jetty-servlet-ee8",
-    artifact = "org.eclipse.jetty.ee8:jetty-ee8-servlet:" + JETTY_VER,
-    sha1 = "42188210ad02c9eac3b811ee68a4dc1b844972f2",
-)
-
-maven_jar(
-    name = "jetty-security",
-    artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VER,
-    sha1 = "1110c675e052608f9be78ff65884ae68672d793b",
-)
-
-maven_jar(
-    name = "jetty-server",
-    artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VER,
-    sha1 = "142e34e6e3ae2645df5a59c002180c9cbeeb940e",
-)
-
-maven_jar(
-    name = "jetty-session",
-    artifact = "org.eclipse.jetty:jetty-session:" + JETTY_VER,
-    sha1 = "85fe6e7bba3dccdac5d76f451f6e126f1da6ab87",
-)
-
-maven_jar(
-    name = "jetty-http",
-    artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VER,
-    sha1 = "310c2c94836b5675e97621f62d7d1f0cab79a142",
-)
-
-maven_jar(
-    name = "jetty-io",
-    artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VER,
-    sha1 = "f637ebb6d9cc27bedef24514d9a475b343f6fd17",
-)
-
-maven_jar(
-    name = "jetty-util",
-    artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VER,
-    sha1 = "f0ebb90ade7a18f5f8c2c1513d4433ccfbada69b",
-)
-
-maven_jar(
-    name = "jetty-util-ajax",
-    artifact = "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VER,
-    sha1 = "f14e709057b93e88c69e7060d591e9582146899b",
-)
-
-BOUNCYCASTLE_VER = "1.82"
-
-maven_jar(
-    name = "bcpg",
-    artifact = "org.bouncycastle:bcpg-jdk18on:" + BOUNCYCASTLE_VER,
-    sha1 = "55cd7f445018b18119e3f2e67978fb39445b791c",
-)
-
-maven_jar(
-    name = "bcprov",
-    artifact = "org.bouncycastle:bcprov-jdk18on:" + BOUNCYCASTLE_VER,
-    sha1 = "e1118397395d21909a1b7b15120d0c2a68d7fd0c",
-)
-
-maven_jar(
-    name = "bcutil",
-    artifact = "org.bouncycastle:bcutil-jdk18on:" + BOUNCYCASTLE_VER,
-    sha1 = "1850911d674c91ce6444783ff10478e2c6e9bbf9",
-)
-
-maven_jar(
-    name = "bcpkix",
-    artifact = "org.bouncycastle:bcpkix-jdk18on:" + BOUNCYCASTLE_VER,
-    sha1 = "ad7b7155abac3e4e4f73579d5176c11f7659c560",
-)
+# This file marks the root of the Bazel workspace.
+# See MODULE.bazel for external dependencies setup.
diff --git a/lib/BUILD b/lib/BUILD
index 7acc029..4ce0c1a 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -6,7 +6,7 @@
         "//org.eclipse.jgit.pgm:__pkg__",
         "//org.eclipse.jgit.pgm.test:__pkg__",
     ],
-    exports = ["@args4j//jar"],
+    exports = ["@external_deps//:args4j_args4j"],
 )
 
 java_library(
@@ -16,7 +16,7 @@
         "//org.eclipse.jgit.pgm.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@commons-compress//jar"],
+    exports = ["@external_deps//:org_apache_commons_commons_compress"],
 )
 
 java_library(
@@ -26,7 +26,7 @@
         "//org.eclipse.jgit.pgm.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@commons-lang3//jar"],
+    exports = ["@external_deps//:org_apache_commons_commons_lang3"],
 )
 
 java_library(
@@ -36,7 +36,7 @@
         "//org.eclipse.jgit.pgm.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@commons-io//jar"],
+    exports = ["@external_deps//:commons_io_commons_io"],
 )
 
 java_library(
@@ -45,13 +45,13 @@
         "//org.eclipse.jgit:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@commons-codec//jar"],
+    exports = ["@external_deps//:commons_codec_commons_codec"],
 )
 
 java_library(
     name = "commons-logging",
     visibility = ["//visibility:public"],
-    exports = ["@commons-logging//jar"],
+    exports = ["@external_deps//:commons_logging_commons_logging"],
 )
 
 java_library(
@@ -61,7 +61,7 @@
         "//org.eclipse.jgit.lfs.server:__pkg__",
         "//org.eclipse.jgit.lfs.server.ee8:__pkg__",
     ],
-    exports = ["@gson//jar"],
+    exports = ["@external_deps//:com_google_code_gson_gson"],
 )
 
 java_library(
@@ -72,7 +72,7 @@
         "//org.eclipse.jgit.lfs.server.test.ee8:__pkg__",
         "//org.eclipse.jgit.pgm:__pkg__",
     ],
-    exports = ["@httpclient//jar"],
+    exports = ["@external_deps//:org_apache_httpcomponents_httpclient"],
 )
 
 java_library(
@@ -87,7 +87,7 @@
         "//org.eclipse.jgit.lfs.server.test.ee8:__pkg__",
         "//org.eclipse.jgit.pgm:__pkg__",
     ],
-    exports = ["@httpcore//jar"],
+    exports = ["@external_deps//:org_apache_httpcomponents_httpcore"],
 )
 
 java_library(
@@ -99,7 +99,7 @@
         "//org.eclipse.jgit.ssh.apache.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@sshd-osgi//jar"],
+    exports = ["@external_deps//:org_apache_sshd_sshd_osgi"],
 )
 
 java_library(
@@ -110,7 +110,7 @@
         "//org.eclipse.jgit.ssh.apache.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@sshd-sftp//jar"],
+    exports = ["@external_deps//:org_apache_sshd_sshd_sftp"],
 )
 
 java_library(
@@ -118,7 +118,7 @@
     visibility = [
         "//org.eclipse.jgit.ssh.apache.agent:__pkg__",
     ],
-    exports = ["@jna//jar"],
+    exports = ["@external_deps//:net_java_dev_jna_jna"],
 )
 
 java_library(
@@ -126,20 +126,20 @@
     visibility = [
         "//org.eclipse.jgit.ssh.apache.agent:__pkg__",
     ],
-    exports = ["@jna-platform//jar"],
+    exports = ["@external_deps//:net_java_dev_jna_jna_platform"],
 )
 
 java_library(
     name = "javaewah",
     visibility = ["//visibility:public"],
-    exports = ["@javaewah//jar"],
+    exports = ["@external_deps//:com_googlecode_javaewah_JavaEWAH"],
 )
 
 java_library(
     name = "jetty-http",
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
-    exports = ["@jetty-http//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_jetty_http"],
     runtime_deps = [":commons-codec"],
 )
 
@@ -147,28 +147,28 @@
     name = "jetty-io",
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
-    exports = ["@jetty-io//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_jetty_io"],
 )
 
 java_library(
     name = "jetty-security",
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
-    exports = ["@jetty-security//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_jetty_security"],
 )
 
 java_library(
     name = "jetty-session",
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
-    exports = ["@jetty-session//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_jetty_session"],
 )
 
 java_library(
     name = "jetty-server",
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
-    exports = ["@jetty-server//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_jetty_server"],
 )
 
 java_library(
@@ -176,8 +176,8 @@
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
     exports = [
-        "@jetty-servlet//jar",
-        "@jetty-util-ajax//jar",
+        "@external_deps//:org_eclipse_jetty_ee10_jetty_ee10_servlet",
+        "@external_deps//:org_eclipse_jetty_jetty_util_ajax",
     ],
 )
 
@@ -185,7 +185,7 @@
     name = "jetty-ee8-nested",
     testonly = 1,
     visibility = ["//org.eclipse.jgit.junit.http.ee8:__pkg__"],
-    exports = ["@jetty-ee8-nested//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_ee8_jetty_ee8_nested"],
 )
 
 java_library(
@@ -196,7 +196,7 @@
         "//org.eclipse.jgit.junit.http.ee8:__pkg__",
         "//org.eclipse.jgit.lfs.server.test.ee8:__pkg__",
     ],
-    exports = ["@jetty-security-ee8//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_ee8_jetty_ee8_security"],
 )
 
 java_library(
@@ -207,35 +207,21 @@
         "//org.eclipse.jgit.junit.http.ee8:__pkg__",
         "//org.eclipse.jgit.lfs.server.test.ee8:__pkg__",
     ],
-    exports = ["@jetty-servlet-ee8//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_ee8_jetty_ee8_servlet"],
 )
 
 java_library(
     name = "jetty-util",
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
-    exports = ["@jetty-util//jar"],
-)
-
-java_library(
-    name = "jetty-ee10-nested",
-    # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
-    visibility = ["//visibility:public"],
-    exports = ["@jetty-ee10-nested//jar"],
-)
-
-java_library(
-    name = "jetty-ee10-security",
-    # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
-    visibility = ["//visibility:public"],
-    exports = ["@jetty-ee10-security//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_jetty_util"],
 )
 
 java_library(
     name = "jetty-ee10-servlet",
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
-    exports = ["@jetty-ee10-servlet//jar"],
+    exports = ["@external_deps//:org_eclipse_jetty_ee10_jetty_ee10_servlet"],
 )
 
 java_library(
@@ -245,7 +231,7 @@
         "//org.eclipse.jgit.ssh.jsch:__pkg__",
         "//org.eclipse.jgit.ssh.jsch.test:__pkg__",
     ],
-    exports = ["@jsch//jar"],
+    exports = ["@external_deps//:com_jcraft_jsch"],
 )
 
 java_library(
@@ -257,7 +243,7 @@
         "//org.eclipse.jgit.ssh.apache.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@bcpg//jar"],
+    exports = ["@external_deps//:org_bouncycastle_bcpg_jdk18on"],
 )
 
 java_library(
@@ -270,7 +256,7 @@
         "//org.eclipse.jgit.ssh.jsch.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@bcprov//jar"],
+    exports = ["@external_deps//:org_bouncycastle_bcprov_jdk18on"],
 )
 
 java_library(
@@ -283,7 +269,7 @@
         "//org.eclipse.jgit.ssh.jsch.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@bcutil//jar"],
+    exports = ["@external_deps//:org_bouncycastle_bcutil_jdk18on"],
 )
 
 java_library(
@@ -295,7 +281,7 @@
         "//org.eclipse.jgit.ssh.jsch.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@bcpkix//jar"],
+    exports = ["@external_deps//:org_bouncycastle_bcpkix_jdk18on"],
 )
 
 java_library(
@@ -304,7 +290,7 @@
         "//org.eclipse.jgit.ssh.jsch:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@jzlib//jar"],
+    exports = ["@external_deps//:com_jcraft_jzlib"],
 )
 
 java_library(
@@ -312,12 +298,12 @@
     testonly = 1,
     visibility = ["//visibility:public"],
     exports = [
-        "@bytebuddy-agent//jar",
-        "@bytebuddy//jar",
-        "@hamcrest//jar",
-        "@junit//jar",
-        "@mockito//jar",
-        "@objenesis//jar",
+        "@external_deps//:junit_junit",
+        "@external_deps//:net_bytebuddy_byte_buddy",
+        "@external_deps//:net_bytebuddy_byte_buddy_agent",
+        "@external_deps//:org_hamcrest_hamcrest",
+        "@external_deps//:org_mockito_mockito_core",
+        "@external_deps//:org_objenesis_objenesis",
     ],
 )
 
@@ -326,10 +312,10 @@
     testonly = 1,
     visibility = ["//visibility:public"],
     exports = [
-        "@bytebuddy-agent//jar",
-        "@bytebuddy//jar",
-        "@mockito//jar",
-        "@objenesis//jar",
+        "@external_deps//:net_bytebuddy_byte_buddy",
+        "@external_deps//:net_bytebuddy_byte_buddy_agent",
+        "@external_deps//:org_mockito_mockito_core",
+        "@external_deps//:org_objenesis_objenesis",
     ],
 )
 
@@ -338,7 +324,7 @@
     testonly = 1,
     visibility = ["//visibility:public"],
     exports = [
-        "@assertj-core//jar",
+        "@external_deps//:org_assertj_assertj_core",
     ],
 )
 
@@ -354,7 +340,7 @@
         "//org.eclipse.jgit.lfs.server.test:__pkg__",
         "//org.eclipse.jgit.pgm:__pkg__",
     ],
-    exports = ["@servlet-api//jar"],
+    exports = ["@external_deps//:jakarta_servlet_jakarta_servlet_api_6_1_0"],
 )
 
 java_library(
@@ -366,24 +352,24 @@
         "//org.eclipse.jgit.lfs.server.ee8:__pkg__",
         "//org.eclipse.jgit.lfs.server.test.ee8:__pkg__",
     ],
-    exports = ["@javax-servlet-api//jar"],
+    exports = ["@external_deps//:javax_servlet_javax_servlet_api"],
 )
 
 java_library(
     name = "slf4j-api",
     visibility = ["//visibility:public"],
-    exports = ["@log-api//jar"],
+    exports = ["@external_deps//:org_slf4j_slf4j_api"],
 )
 
 java_library(
     name = "slf4j-simple",
     visibility = ["//visibility:public"],
-    exports = ["@slf4j-simple//jar"],
+    exports = ["@external_deps//:org_slf4j_slf4j_simple"],
 )
 
 java_library(
     name = "xz",
     testonly = 1,
     visibility = ["//visibility:public"],
-    exports = ["@tukaani-xz//jar"],
+    exports = ["@external_deps//:org_tukaani_xz"],
 )
diff --git a/lib/jmh/BUILD b/lib/jmh/BUILD
index b15e66c..e6d3977 100644
--- a/lib/jmh/BUILD
+++ b/lib/jmh/BUILD
@@ -4,9 +4,9 @@
     name = "jmh",
     visibility = ["//visibility:public"],
     exports = [
-        "@jmh-annotations//jar",
-        "@jmh-core//jar",
-        "@jopt//jar",
-        "@math3//jar",
+        "@external_deps//:net_sf_jopt_simple_jopt_simple",
+        "@external_deps//:org_apache_commons_commons_math3",
+        "@external_deps//:org_openjdk_jmh_jmh_core",
+        "@external_deps//:org_openjdk_jmh_jmh_generator_annprocess",
     ],
 )
diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
index b3e4719..5c65d3f 100644
--- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
@@ -5,14 +5,14 @@
 Automatic-Module-Name: org.eclipse.jgit.ant.test
 Bundle-SymbolicName: org.eclipse.jgit.ant.test
 Bundle-Vendor: %Bundle-Vendor
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
 Import-Package: org.apache.tools.ant,
- org.eclipse.jgit.ant.tasks;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.ant.tasks;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.hamcrest;version="[3.0.0,4.0.0)",
  org.junit;version="[4.13,5.0.0)"
diff --git a/org.eclipse.jgit.ant.test/pom.xml b/org.eclipse.jgit.ant.test/pom.xml
index 937b78a..65c17a9 100644
--- a/org.eclipse.jgit.ant.test/pom.xml
+++ b/org.eclipse.jgit.ant.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ant.test</artifactId>
diff --git a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
index bf1a61d..1189ae1 100644
--- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
@@ -3,14 +3,14 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ant
 Bundle-SymbolicName: org.eclipse.jgit.ant
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
 Import-Package: org.apache.tools.ant,
-  org.eclipse.jgit.storage.file;version="[7.5.1,7.6.0)"
+  org.eclipse.jgit.storage.file;version="[7.6.1,7.7.0)"
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.jgit.ant;version="7.5.1",
- org.eclipse.jgit.ant.tasks;version="7.5.1";
+Export-Package: org.eclipse.jgit.ant;version="7.6.1",
+ org.eclipse.jgit.ant.tasks;version="7.6.1";
   uses:="org.apache.tools.ant,
    org.apache.tools.ant.types"
diff --git a/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
index 8bc02c8..4527ac7 100644
--- a/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.ant - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ant.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.ant;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.ant;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.ant/pom.xml b/org.eclipse.jgit.ant/pom.xml
index fcd4371..7015098 100644
--- a/org.eclipse.jgit.ant/pom.xml
+++ b/org.eclipse.jgit.ant/pom.xml
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ant</artifactId>
diff --git a/org.eclipse.jgit.archive/BUILD b/org.eclipse.jgit.archive/BUILD
index d4f5340..7c6d610 100644
--- a/org.eclipse.jgit.archive/BUILD
+++ b/org.eclipse.jgit.archive/BUILD
@@ -12,6 +12,7 @@
     resources = glob(["resources/**"]),
     deps = [
         "//lib:commons-compress",
+        "//lib:commons-io",
         "//lib:commons-lang3",
         # We want these deps to be provided_deps
         "//org.eclipse.jgit:jgit",
diff --git a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
index 07b850d..222318c 100644
--- a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.archive
 Bundle-SymbolicName: org.eclipse.jgit.archive
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -14,18 +14,18 @@
  org.apache.commons.compress.compressors.bzip2;version="[1.4,2.0)",
  org.apache.commons.compress.compressors.gzip;version="[1.4,2.0)",
  org.apache.commons.compress.compressors.xz;version="[1.4,2.0)",
- org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.osgi.framework;version="[1.3.0,2.0.0)",
  org.tukaani.xz
 Bundle-ActivationPolicy: lazy
 Bundle-Activator: org.eclipse.jgit.archive.FormatActivator
-Export-Package: org.eclipse.jgit.archive;version="7.5.1";
+Export-Package: org.eclipse.jgit.archive;version="7.6.1";
   uses:="org.apache.commons.compress.archivers,
    org.osgi.framework,
    org.eclipse.jgit.api,
    org.eclipse.jgit.lib",
- org.eclipse.jgit.archive.internal;version="7.5.1";x-internal:=true
+ org.eclipse.jgit.archive.internal;version="7.6.1";x-internal:=true
diff --git a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
index 831f34f..ea8db6b 100644
--- a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.archive - Sources
 Bundle-SymbolicName: org.eclipse.jgit.archive.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.archive;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.archive;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml
index 3e1cbea..cf805bd 100644
--- a/org.eclipse.jgit.archive/pom.xml
+++ b/org.eclipse.jgit.archive/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.archive</artifactId>
diff --git a/org.eclipse.jgit.benchmarks/pom.xml b/org.eclipse.jgit.benchmarks/pom.xml
index 7d9f9e6..f67eb4d 100644
--- a/org.eclipse.jgit.benchmarks/pom.xml
+++ b/org.eclipse.jgit.benchmarks/pom.xml
@@ -16,7 +16,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.benchmarks</artifactId>
diff --git a/org.eclipse.jgit.coverage/pom.xml b/org.eclipse.jgit.coverage/pom.xml
index 44bc58b..e922fbf 100644
--- a/org.eclipse.jgit.coverage/pom.xml
+++ b/org.eclipse.jgit.coverage/pom.xml
@@ -14,7 +14,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
@@ -27,88 +27,88 @@
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ant</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.archive</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.http.apache</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.http.server</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs.server</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.pgm</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ui</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ssh.apache</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
 
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.test</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ant.test</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.http.test</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.pgm.test</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs.test</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs.server.test</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
   </dependencies>
 
diff --git a/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
index 4136a34..6e13b63 100644
--- a/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.gpg.bc.test
 Bundle-SymbolicName: org.eclipse.jgit.gpg.bc.test
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -14,9 +14,9 @@
  org.bouncycastle.openpgp.operator;version="[1.80.0,2.0.0)",
  org.bouncycastle.openpgp.operator.jcajce;version="[1.80.0,2.0.0)",
  org.bouncycastle.util.encoders;version="[1.80.0,2.0.0)",
- org.eclipse.jgit.gpg.bc.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.gpg.bc.internal.keys;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util.sha1;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.gpg.bc.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.gpg.bc.internal.keys;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util.sha1;version="[7.6.1,7.7.0)",
  org.hamcrest;version="[3.0.0,4.0.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.runner;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.gpg.bc.test/pom.xml b/org.eclipse.jgit.gpg.bc.test/pom.xml
index b489073..6ca68db 100644
--- a/org.eclipse.jgit.gpg.bc.test/pom.xml
+++ b/org.eclipse.jgit.gpg.bc.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.gpg.bc.test</artifactId>
diff --git a/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF b/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
index b6c43a7..138ba43 100644
--- a/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
@@ -3,10 +3,10 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.gpg.bc
 Bundle-SymbolicName: org.eclipse.jgit.gpg.bc;singleton:=true
-Fragment-Host: org.eclipse.jgit;bundle-version="[7.5.1,7.6.0)"
+Fragment-Host: org.eclipse.jgit;bundle-version="[7.6.1,7.7.0)"
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/gpg_bc
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
 Import-Package: org.bouncycastle.asn1;version="[1.80.0,2.0.0)",
@@ -27,5 +27,5 @@
  org.bouncycastle.openpgp.operator.jcajce;version="[1.80.0,2.0.0)",
  org.bouncycastle.util.encoders;version="[1.80.0,2.0.0)",
  org.slf4j;version="[1.7.0,3.0.0)"
-Export-Package: org.eclipse.jgit.gpg.bc.internal;version="7.5.1";x-friends:="org.eclipse.jgit.gpg.bc.test",
- org.eclipse.jgit.gpg.bc.internal.keys;version="7.5.1";x-friends:="org.eclipse.jgit.gpg.bc.test"
+Export-Package: org.eclipse.jgit.gpg.bc.internal;version="7.6.1";x-friends:="org.eclipse.jgit.gpg.bc.test",
+ org.eclipse.jgit.gpg.bc.internal.keys;version="7.6.1";x-friends:="org.eclipse.jgit.gpg.bc.test"
diff --git a/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF
index 6a4d2b0..e02a782 100644
--- a/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.gpg.bc - Sources
 Bundle-SymbolicName: org.eclipse.jgit.gpg.bc.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.gpg.bc;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.gpg.bc;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.gpg.bc/pom.xml b/org.eclipse.jgit.gpg.bc/pom.xml
index fe4f637..2270876 100644
--- a/org.eclipse.jgit.gpg.bc/pom.xml
+++ b/org.eclipse.jgit.gpg.bc/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.gpg.bc</artifactId>
diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
index aba7386..a131f2b 100644
--- a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.apache
 Bundle-SymbolicName: org.eclipse.jgit.http.apache
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
 Bundle-Localization: OSGI-INF/l10n/plugin
@@ -27,11 +27,11 @@
  org.apache.http.impl.conn;version="[4.4.0,5.0.0)",
  org.apache.http.params;version="[4.3.0,5.0.0)",
  org.apache.http.ssl;version="[4.3.0,5.0.0)",
- org.eclipse.jgit.annotations;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.http;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)"
-Export-Package: org.eclipse.jgit.transport.http.apache;version="7.5.1";
+ org.eclipse.jgit.annotations;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.http;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)"
+Export-Package: org.eclipse.jgit.transport.http.apache;version="7.6.1";
   uses:="org.apache.http.client,
    org.eclipse.jgit.transport.http,
    org.apache.http.entity,
diff --git a/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
index 50c6aba..de4f1f5 100644
--- a/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.http.apache - Sources
 Bundle-SymbolicName: org.eclipse.jgit.http.apache.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml
index 9f8c083..08a3e58 100644
--- a/org.eclipse.jgit.http.apache/pom.xml
+++ b/org.eclipse.jgit.http.apache/pom.xml
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.apache</artifactId>
diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
index 5fc3c47..ec6205b 100644
--- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
@@ -3,31 +3,31 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.server
 Bundle-SymbolicName: org.eclipse.jgit.http.server
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Export-Package: org.eclipse.jgit.http.server;version="7.5.1",
- org.eclipse.jgit.http.server.glue;version="7.5.1";
+Export-Package: org.eclipse.jgit.http.server;version="7.6.1",
+ org.eclipse.jgit.http.server.glue;version="7.6.1";
   uses:="jakarta.servlet,
   	jakarta.servlet.http",
- org.eclipse.jgit.http.server.resolver;version="7.5.1";
+ org.eclipse.jgit.http.server.resolver;version="7.6.1";
   uses:="jakarta.servlet.http
    org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.transport,
 Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
  jakarta.servlet.http;version="[6.0.0,7.0.0)",
- org.eclipse.jgit.annotations;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.transport.parser;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.resolver;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)"
+ org.eclipse.jgit.annotations;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.transport.parser;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)"
diff --git a/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
index 8556eac..9e23425 100644
--- a/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.http.server - Sources
 Bundle-SymbolicName: org.eclipse.jgit.http.server.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml
index 27a3d3e..0141448 100644
--- a/org.eclipse.jgit.http.server/pom.xml
+++ b/org.eclipse.jgit.http.server/pom.xml
@@ -19,7 +19,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.server</artifactId>
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index cc47e35..babbd21 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.test
 Bundle-SymbolicName: org.eclipse.jgit.http.test
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -28,26 +28,26 @@
  org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)",
  org.eclipse.jetty.util.security;version="[12.0.0,13.0.0)",
  org.eclipse.jetty.util.thread;version="[12.0.0,13.0.0)",
- org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.http.server;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.http.server.glue;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.http.server.resolver;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit.http;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.http;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.http.apache;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.resolver;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.http.server;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.http.server.glue;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.http.server.resolver;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit.http;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.http;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.http.apache;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.hamcrest;version="[3.0.0,4.0.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.rules;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml
index aa5d258..3e9f456 100644
--- a/org.eclipse.jgit.http.test/pom.xml
+++ b/org.eclipse.jgit.http.test/pom.xml
@@ -18,7 +18,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.test</artifactId>
diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
index b0c2fd0..c13deaa 100644
--- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.junit.http
 Bundle-SymbolicName: org.eclipse.jgit.junit.http
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
@@ -23,17 +23,17 @@
  org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)",
  org.eclipse.jetty.util.security;version="[12.0.0,13.0.0)",
  org.eclipse.jetty.util.ssl;version="[12.0.0,13.0.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.http.server;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.resolver;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.http.server;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.6.1,7.7.0)",
  org.junit;version="[4.13,5.0.0)",
  org.slf4j.helpers;version="[1.7.0,3.0.0)"
-Export-Package: org.eclipse.jgit.junit.http;version="7.5.1";
+Export-Package: org.eclipse.jgit.junit.http;version="7.6.1";
   uses:="org.eclipse.jgit.transport,
    jakarta.servlet,
    jakarta.servlet.http,
diff --git a/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
index 03e8795..7dd9628 100644
--- a/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.junit.http - Sources
 Bundle-SymbolicName: org.eclipse.jgit.junit.http.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml
index a840c4f..dc3461c 100644
--- a/org.eclipse.jgit.junit.http/pom.xml
+++ b/org.eclipse.jgit.junit.http/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit.http</artifactId>
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
index 7b62993..48199fd 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
@@ -3,47 +3,47 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.junit.ssh
 Bundle-SymbolicName: org.eclipse.jgit.junit.ssh
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Import-Package: org.apache.sshd.common;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.config.keys;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.file.virtualfs;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.helpers;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.io;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.kex;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.keyprovider;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.session;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.signature;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.buffer;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.logging;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.security;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.threads;version="[2.16.0,2.17.0)",
- org.apache.sshd.core;version="[2.16.0,2.17.0)",
- org.apache.sshd.server;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.auth;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.auth.gss;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.auth.keyboard;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.auth.password;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.command;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.session;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.shell;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.subsystem;version="[2.16.0,2.17.0)",
- org.apache.sshd.sftp;version="[2.16.0,2.17.0)",
- org.apache.sshd.sftp.server;version="[2.16.0,2.17.0)",
- org.eclipse.jgit.annotations;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+Import-Package: org.apache.sshd.common;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.config.keys;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.file.virtualfs;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.helpers;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.io;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.kex;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.keyprovider;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.session;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.signature;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.buffer;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.logging;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.security;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.threads;version="[2.17.1,2.18.0)",
+ org.apache.sshd.core;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.auth;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.auth.gss;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.auth.keyboard;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.auth.password;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.command;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.session;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.shell;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.subsystem;version="[2.17.1,2.18.0)",
+ org.apache.sshd.sftp;version="[2.17.1,2.18.0)",
+ org.apache.sshd.sftp.server;version="[2.17.1,2.18.0)",
+ org.eclipse.jgit.annotations;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.experimental.theories;version="[4.13,5.0.0)",
  org.slf4j;version="[1.7.0,3.0.0)"
-Export-Package: org.eclipse.jgit.junit.ssh;version="7.5.1"
+Export-Package: org.eclipse.jgit.junit.ssh;version="7.6.1"
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
index 3202ac0..b092137 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.junit.ssh - Sources
 Bundle-SymbolicName: org.eclipse.jgit.junit.ssh.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit.ssh/pom.xml b/org.eclipse.jgit.junit.ssh/pom.xml
index b596c7b..821a913 100644
--- a/org.eclipse.jgit.junit.ssh/pom.xml
+++ b/org.eclipse.jgit.junit.ssh/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit.ssh</artifactId>
diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
index 4c01b09..fefcf2e 100644
--- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
@@ -3,38 +3,38 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.junit
 Bundle-SymbolicName: org.eclipse.jgit.junit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Import-Package: org.eclipse.jgit.annotations;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.dircache;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.pack;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.util;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.merge;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.pack;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="7.5.1",
- org.eclipse.jgit.treewalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util.io;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util.time;version="[7.5.1,7.6.0)",
+Import-Package: org.eclipse.jgit.annotations;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.dircache;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.util;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.merge;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.pack;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="7.6.1",
+ org.eclipse.jgit.treewalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util.io;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util.time;version="[7.6.1,7.7.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.rules;version="[4.13,5.0.0)",
  org.junit.runner;version="[4.13,5.0.0)",
  org.junit.runners;version="[4.13,5.0.0)",
  org.junit.runners.model;version="[4.13,5.0.0)",
  org.slf4j;version="[1.7.0,3.0.0)"
-Export-Package: org.eclipse.jgit.junit;version="7.5.1";
+Export-Package: org.eclipse.jgit.junit;version="7.6.1";
   uses:="org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
@@ -47,4 +47,4 @@
    org.junit.runners.model,
    org.junit.runner,
    org.eclipse.jgit.util.time",
- org.eclipse.jgit.junit.time;version="7.5.1";uses:="org.eclipse.jgit.util.time"
+ org.eclipse.jgit.junit.time;version="7.6.1";uses:="org.eclipse.jgit.util.time"
diff --git a/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
index 77e9a51..314da62 100644
--- a/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.junit - Sources
 Bundle-SymbolicName: org.eclipse.jgit.junit.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.junit;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.junit;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml
index f02ecbf..f9632d6 100644
--- a/org.eclipse.jgit.junit/pom.xml
+++ b/org.eclipse.jgit.junit/pom.xml
@@ -19,7 +19,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit</artifactId>
diff --git a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
index 36a0724..89fd39a 100644
--- a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs.server.test
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server.test
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -27,24 +27,24 @@
  org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)",
  org.eclipse.jetty.util.security;version="[12.0.0,13.0.0)",
  org.eclipse.jetty.util.thread;version="[12.0.0,13.0.0)",
- org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit.http;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.server;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.server.fs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.test;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit.http;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.server;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.test;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.hamcrest;version="[3.0.0,4.0.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.rules;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.lfs.server.test/pom.xml b/org.eclipse.jgit.lfs.server.test/pom.xml
index 346c3d3..418e535 100644
--- a/org.eclipse.jgit.lfs.server.test/pom.xml
+++ b/org.eclipse.jgit.lfs.server.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.server.test</artifactId>
diff --git a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
index 51577c3..4500e4f 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
@@ -3,21 +3,21 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs.server
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Export-Package: org.eclipse.jgit.lfs.server;version="7.5.1";
+Export-Package: org.eclipse.jgit.lfs.server;version="7.6.1";
   uses:="jakarta.servlet.http,
    org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.fs;version="7.5.1";
+ org.eclipse.jgit.lfs.server.fs;version="7.6.1";
   uses:="jakarta.servlet,
    jakarta.servlet.http,
    org.eclipse.jgit.lfs.server,
    org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.internal;version="7.5.1";x-internal:=true,
- org.eclipse.jgit.lfs.server.s3;version="7.5.1";
+ org.eclipse.jgit.lfs.server.internal;version="7.6.1";x-internal:=true,
+ org.eclipse.jgit.lfs.server.s3;version="7.6.1";
   uses:="org.eclipse.jgit.lfs.server,
    org.eclipse.jgit.lfs.lib"
 Import-Package: com.google.gson;version="[2.8.0,3.0.0)",
@@ -25,15 +25,15 @@
  jakarta.servlet.annotation;version="[6.0.0,7.0.0)",
  jakarta.servlet.http;version="[6.0.0,7.0.0)",
  org.apache.http;version="[4.3.0,5.0.0)",
- org.eclipse.jgit.annotations;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.http;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.http.apache;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.annotations;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.http;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.http.apache;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.slf4j;version="[1.7.0,3.0.0)"
diff --git a/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
index 16a895d..dcc9a36 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.lfs.server - Sources
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.lfs.server/pom.xml b/org.eclipse.jgit.lfs.server/pom.xml
index 61c3557..bb1eb07 100644
--- a/org.eclipse.jgit.lfs.server/pom.xml
+++ b/org.eclipse.jgit.lfs.server/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.server</artifactId>
diff --git a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
index 116fb5c..72b1723 100644
--- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
@@ -3,29 +3,29 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs.test
 Bundle-SymbolicName: org.eclipse.jgit.lfs.test
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Import-Package: org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.attributes;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.http;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+Import-Package: org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.attributes;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.http;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.hamcrest;version="[3.0.0,4.0.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.runner;version="[4.13,5.0.0)",
  org.junit.runners;version="[4.13,5.0.0)"
-Export-Package: org.eclipse.jgit.lfs.test;version="7.5.1";x-friends:="org.eclipse.jgit.lfs.server.test"
+Export-Package: org.eclipse.jgit.lfs.test;version="7.6.1";x-friends:="org.eclipse.jgit.lfs.server.test"
diff --git a/org.eclipse.jgit.lfs.test/pom.xml b/org.eclipse.jgit.lfs.test/pom.xml
index 011781c..6e98c74 100644
--- a/org.eclipse.jgit.lfs.test/pom.xml
+++ b/org.eclipse.jgit.lfs.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.test</artifactId>
diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
index ac88fc7..ab8a262 100644
--- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
@@ -3,33 +3,33 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs
 Bundle-SymbolicName: org.eclipse.jgit.lfs
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Export-Package: org.eclipse.jgit.lfs;version="7.5.1",
- org.eclipse.jgit.lfs.errors;version="7.5.1",
- org.eclipse.jgit.lfs.internal;version="7.5.1";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server",
- org.eclipse.jgit.lfs.lib;version="7.5.1"
+Export-Package: org.eclipse.jgit.lfs;version="7.6.1",
+ org.eclipse.jgit.lfs.errors;version="7.6.1",
+ org.eclipse.jgit.lfs.internal;version="7.6.1";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server",
+ org.eclipse.jgit.lfs.lib;version="7.6.1"
 Import-Package: com.google.gson;version="[2.8.2,3.0.0)",
  com.google.gson.stream;version="[2.8.2,3.0.0)",
- org.eclipse.jgit.annotations;version="[7.5.1,7.6.0)";resolution:=optional,
- org.eclipse.jgit.api.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.attributes;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.diff;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.dircache;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.hooks;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.pack;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.http;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util.io;version="[7.5.1,7.6.0)"
+ org.eclipse.jgit.annotations;version="[7.6.1,7.7.0)";resolution:=optional,
+ org.eclipse.jgit.api.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.attributes;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.diff;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.dircache;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.hooks;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.pack;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.http;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util.io;version="[7.6.1,7.7.0)"
diff --git a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
index 69d6100..230922e 100644
--- a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.lfs - Sources
 Bundle-SymbolicName: org.eclipse.jgit.lfs.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.lfs/pom.xml b/org.eclipse.jgit.lfs/pom.xml
index 3e58809..c80fd34 100644
--- a/org.eclipse.jgit.lfs/pom.xml
+++ b/org.eclipse.jgit.lfs/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs</artifactId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
index bb374ff..b61447a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit"
       label="%featureName"
-      version="7.5.1.qualifier"
+      version="7.6.1.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
index c890a56..b85b05c 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml
index e544ec6..762e58b 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.gpg.bc"
       label="%featureName"
-      version="7.5.1.qualifier"
+      version="7.6.1.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import plugin="org.eclipse.jgit" version="7.5.1" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="7.6.1" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml
index 77f7c73..a2a0048 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
index 014382b..c0af695 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.http.apache"
       label="%featureName"
-      version="7.5.1.qualifier"
+      version="7.6.1.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import plugin="org.eclipse.jgit" version="7.5.1" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="7.6.1" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
index b2b8faa..a1e2e27 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
index 01d927e..66006cf 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.junit"
       label="%featureName"
-      version="7.5.1.qualifier"
+      version="7.6.1.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -24,7 +24,7 @@
 
    <requires>
       <import plugin="com.jcraft.jsch"/>
-      <import plugin="org.eclipse.jgit" version="7.5.1" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="7.6.1" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
index 687df88..9fb1c87 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
index b4ba75e..388cc4e 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.lfs"
       label="%featureName"
-      version="7.5.1.qualifier"
+      version="7.6.1.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="7.5.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="7.6.1" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
index f7207f2..b9b3c8d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
index 82978df..9a2a51a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.pgm"
       label="%featureName"
-      version="7.5.1.qualifier"
+      version="7.6.1.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -35,9 +35,9 @@
          version="0.0.0"/>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="7.5.1" match="equivalent"/>
-      <import feature="org.eclipse.jgit.lfs" version="7.5.1" match="equivalent"/>
-      <import feature="org.eclipse.jgit.ssh.apache" version="7.5.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="7.6.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit.lfs" version="7.6.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit.ssh.apache" version="7.6.1" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
index 0249b15..dd96482 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
index 08294c7..ead448d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
@@ -216,6 +216,12 @@
    <bundle id="slf4j.simple.source">
       <category name="JGit-dependency-bundles"/>
    </bundle>
+   <bundle id="jcl.over.slf4j">
+      <category name="JGit-dependency-bundles"/>
+   </bundle>
+   <bundle id="jcl.over.slf4j.source">
+      <category name="JGit-dependency-bundles"/>
+   </bundle>
    <bundle id="org.tukaani.xz">
       <category name="JGit-dependency-bundles"/>
    </bundle>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
index 0e6e88f..31e64d7 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.repository</artifactId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
index 14022eb..09a9d13 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.source"
       label="%featureName"
-      version="7.5.1.qualifier"
+      version="7.6.1.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="7.5.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="7.6.1" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
index 777b856..ebcd2a2 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
@@ -30,7 +30,7 @@
     <dependency>
       <groupId>org.eclipse.jgit.feature</groupId>
       <artifactId>org.eclipse.jgit</artifactId>
-      <version>7.5.1-SNAPSHOT</version>
+      <version>7.6.1-SNAPSHOT</version>
     </dependency>
   </dependencies>
 
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
index 48edba8..8944c54 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.ssh.apache"
       label="%featureName"
-      version="7.5.1.qualifier"
+      version="7.6.1.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="7.5.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="7.6.1" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml
index 7aa2732..18a26e1 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml
index e48160a..25cee73 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.ssh.jsch"
       label="%featureName"
-      version="7.5.1.qualifier"
+      version="7.6.1.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import plugin="org.eclipse.jgit" version="7.5.1" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="7.6.1" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml
index f79389f..0871b20 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target
index b75d6f7..24715ea 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.34" sequenceNumber="1763654302">
+<target name="jgit-4.34" sequenceNumber="1772188163">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -58,6 +58,12 @@
           <version>2.0.17</version>
           <type>jar</type>
         </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>jcl-over-slf4j</artifactId>
+          <version>2.0.17</version>
+          <type>jar</type>
+        </dependency>
       </dependencies>
     </location>
     <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="sshd">
@@ -65,13 +71,13 @@
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-osgi</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-sftp</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -81,7 +87,7 @@
         <dependency>
           <groupId>org.mockito</groupId>
           <artifactId>mockito-core</artifactId>
-          <version>5.20.0</version>
+          <version>5.21.0</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -107,49 +113,49 @@
         <dependency>
           <groupId>org.eclipse.jetty.ee10</groupId>
           <artifactId>jetty-ee10-servlet</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-http</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-io</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-security</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-server</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-session</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util-ajax</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
@@ -195,13 +201,13 @@
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy-agent</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -211,25 +217,25 @@
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpg-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcprov-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpkix-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcutil-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -239,7 +245,7 @@
         <dependency>
           <groupId>org.assertj</groupId>
           <artifactId>assertj-core</artifactId>
-          <version>3.27.6</version>
+          <version>3.27.7</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -259,7 +265,7 @@
         <dependency>
           <groupId>commons-codec</groupId>
           <artifactId>commons-codec</artifactId>
-          <version>1.20.0</version>
+          <version>1.21.0</version>
           <type>jar</type>
         </dependency>
         <dependency>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target
index 0a7d6e2..b53ad33 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.35" sequenceNumber="1763654302">
+<target name="jgit-4.35" sequenceNumber="1772188163">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -58,6 +58,12 @@
           <version>2.0.17</version>
           <type>jar</type>
         </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>jcl-over-slf4j</artifactId>
+          <version>2.0.17</version>
+          <type>jar</type>
+        </dependency>
       </dependencies>
     </location>
     <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="sshd">
@@ -65,13 +71,13 @@
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-osgi</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-sftp</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -81,7 +87,7 @@
         <dependency>
           <groupId>org.mockito</groupId>
           <artifactId>mockito-core</artifactId>
-          <version>5.20.0</version>
+          <version>5.21.0</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -107,49 +113,49 @@
         <dependency>
           <groupId>org.eclipse.jetty.ee10</groupId>
           <artifactId>jetty-ee10-servlet</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-http</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-io</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-security</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-server</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-session</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util-ajax</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
@@ -195,13 +201,13 @@
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy-agent</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -211,25 +217,25 @@
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpg-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcprov-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpkix-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcutil-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -239,7 +245,7 @@
         <dependency>
           <groupId>org.assertj</groupId>
           <artifactId>assertj-core</artifactId>
-          <version>3.27.6</version>
+          <version>3.27.7</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -259,7 +265,7 @@
         <dependency>
           <groupId>commons-codec</groupId>
           <artifactId>commons-codec</artifactId>
-          <version>1.20.0</version>
+          <version>1.21.0</version>
           <type>jar</type>
         </dependency>
         <dependency>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target
index 5500a78..269dd9a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.36" sequenceNumber="1763654302">
+<target name="jgit-4.36" sequenceNumber="1772188163">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -58,6 +58,12 @@
           <version>2.0.17</version>
           <type>jar</type>
         </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>jcl-over-slf4j</artifactId>
+          <version>2.0.17</version>
+          <type>jar</type>
+        </dependency>
       </dependencies>
     </location>
     <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="sshd">
@@ -65,13 +71,13 @@
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-osgi</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-sftp</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -81,7 +87,7 @@
         <dependency>
           <groupId>org.mockito</groupId>
           <artifactId>mockito-core</artifactId>
-          <version>5.20.0</version>
+          <version>5.21.0</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -107,49 +113,49 @@
         <dependency>
           <groupId>org.eclipse.jetty.ee10</groupId>
           <artifactId>jetty-ee10-servlet</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-http</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-io</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-security</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-server</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-session</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util-ajax</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
@@ -195,13 +201,13 @@
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy-agent</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -211,25 +217,25 @@
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpg-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcprov-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpkix-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcutil-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -239,7 +245,7 @@
         <dependency>
           <groupId>org.assertj</groupId>
           <artifactId>assertj-core</artifactId>
-          <version>3.27.6</version>
+          <version>3.27.7</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -259,7 +265,7 @@
         <dependency>
           <groupId>commons-codec</groupId>
           <artifactId>commons-codec</artifactId>
-          <version>1.20.0</version>
+          <version>1.21.0</version>
           <type>jar</type>
         </dependency>
         <dependency>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.37.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.37.target
index 1900eda..9474a6b 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.37.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.37.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.37" sequenceNumber="1763654303">
+<target name="jgit-4.37" sequenceNumber="1772188163">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -58,6 +58,12 @@
           <version>2.0.17</version>
           <type>jar</type>
         </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>jcl-over-slf4j</artifactId>
+          <version>2.0.17</version>
+          <type>jar</type>
+        </dependency>
       </dependencies>
     </location>
     <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="sshd">
@@ -65,13 +71,13 @@
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-osgi</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-sftp</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -81,7 +87,7 @@
         <dependency>
           <groupId>org.mockito</groupId>
           <artifactId>mockito-core</artifactId>
-          <version>5.20.0</version>
+          <version>5.21.0</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -107,49 +113,49 @@
         <dependency>
           <groupId>org.eclipse.jetty.ee10</groupId>
           <artifactId>jetty-ee10-servlet</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-http</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-io</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-security</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-server</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-session</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util-ajax</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
@@ -195,13 +201,13 @@
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy-agent</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -211,25 +217,25 @@
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpg-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcprov-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpkix-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcutil-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -239,7 +245,7 @@
         <dependency>
           <groupId>org.assertj</groupId>
           <artifactId>assertj-core</artifactId>
-          <version>3.27.6</version>
+          <version>3.27.7</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -259,7 +265,7 @@
         <dependency>
           <groupId>commons-codec</groupId>
           <artifactId>commons-codec</artifactId>
-          <version>1.20.0</version>
+          <version>1.21.0</version>
           <type>jar</type>
         </dependency>
         <dependency>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.target
index 2571b91..250c5a0 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.38" sequenceNumber="1763654304">
+<target name="jgit-4.38" sequenceNumber="1772188163">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -32,7 +32,7 @@
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
-      <repository location="https://download.eclipse.org/staging/2025-12/"/>
+      <repository location="https://download.eclipse.org/releases/2025-12/"/>
     </location>
     <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="xz">
       <dependencies>
@@ -58,6 +58,12 @@
           <version>2.0.17</version>
           <type>jar</type>
         </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>jcl-over-slf4j</artifactId>
+          <version>2.0.17</version>
+          <type>jar</type>
+        </dependency>
       </dependencies>
     </location>
     <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="sshd">
@@ -65,13 +71,13 @@
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-osgi</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.apache.sshd</groupId>
           <artifactId>sshd-sftp</artifactId>
-          <version>2.16.0</version>
+          <version>2.17.1</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -81,7 +87,7 @@
         <dependency>
           <groupId>org.mockito</groupId>
           <artifactId>mockito-core</artifactId>
-          <version>5.20.0</version>
+          <version>5.21.0</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -107,49 +113,49 @@
         <dependency>
           <groupId>org.eclipse.jetty.ee10</groupId>
           <artifactId>jetty-ee10-servlet</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-http</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-io</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-security</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-server</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-session</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util-ajax</artifactId>
-          <version>12.1.4</version>
+          <version>12.1.6</version>
           <type>jar</type>
         </dependency>
         <dependency>
@@ -195,13 +201,13 @@
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy-agent</artifactId>
-          <version>1.18.1</version>
+          <version>1.18.5</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -211,25 +217,25 @@
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpg-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcprov-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcpkix-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcutil-jdk18on</artifactId>
-          <version>1.82</version>
+          <version>1.83</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -239,7 +245,7 @@
         <dependency>
           <groupId>org.assertj</groupId>
           <artifactId>assertj-core</artifactId>
-          <version>3.27.6</version>
+          <version>3.27.7</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -259,7 +265,7 @@
         <dependency>
           <groupId>commons-codec</groupId>
           <artifactId>commons-codec</artifactId>
-          <version>1.20.0</version>
+          <version>1.21.0</version>
           <type>jar</type>
         </dependency>
         <dependency>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.tpd
index cd20f43..a440dc6 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.tpd
@@ -3,6 +3,6 @@
 include "orbit/orbit-4.38.tpd"
 include "maven/dependencies.tpd"
 
-location "https://download.eclipse.org/staging/2025-12/" {
+location "https://download.eclipse.org/releases/2025-12/" {
 	org.eclipse.osgi lazy
 }
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.39.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.39.target
new file mode 100644
index 0000000..1682581
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.39.target
@@ -0,0 +1,298 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?pde?>
+<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
+<target name="jgit-4.39" sequenceNumber="1772188163">
+  <locations>
+    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+      <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
+      <unit id="com.jcraft.jsch.source" version="0.1.55.v20230916-1400"/>
+      <unit id="com.jcraft.jzlib" version="1.1.3.v20230916-1400"/>
+      <unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/>
+      <unit id="org.apache.ant" version="1.10.15.v20240901-1000"/>
+      <unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/>
+      <unit id="org.apache.aries.spifly.dynamic.bundle" version="1.3.7"/>
+      <unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/>
+      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.14"/>
+      <unit id="org.apache.httpcomponents.httpcore" version="4.4.16"/>
+      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.16"/>
+      <unit id="org.hamcrest" version="3.0.0"/>
+      <unit id="org.hamcrest.source" version="3.0.0"/>
+      <unit id="org.junit" version="4.13.2.v20240929-1000"/>
+      <unit id="org.junit.source" version="4.13.2.v20240929-1000"/>
+      <unit id="org.objectweb.asm" version="9.9.1"/>
+      <unit id="org.objectweb.asm.commons" version="9.9.1"/>
+      <unit id="org.objectweb.asm.util" version="9.9.1"/>
+      <unit id="org.objectweb.asm.tree" version="9.9.1"/>
+      <unit id="org.objectweb.asm.tree.analysis" version="9.9.1"/>
+      <unit id="org.objenesis" version="3.5.0"/>
+      <unit id="org.objenesis.source" version="3.5.0"/>
+      <unit id="org.osgi.service.cm" version="1.6.1.202109301733"/>
+      <unit id="org.osgi.service.cm.source" version="1.6.1.202109301733"/>
+      <repository location="https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2026-03"/>
+    </location>
+    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+      <unit id="org.eclipse.osgi" version="0.0.0"/>
+      <repository location="https://download.eclipse.org/staging/2026-03/"/>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="xz">
+      <dependencies>
+        <dependency>
+          <groupId>org.tukaani</groupId>
+          <artifactId>xz</artifactId>
+          <version>1.11</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="slf4j">
+      <dependencies>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-api</artifactId>
+          <version>2.0.17</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-simple</artifactId>
+          <version>2.0.17</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>jcl-over-slf4j</artifactId>
+          <version>2.0.17</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="sshd">
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.sshd</groupId>
+          <artifactId>sshd-osgi</artifactId>
+          <version>2.17.1</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.sshd</groupId>
+          <artifactId>sshd-sftp</artifactId>
+          <version>2.17.1</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="mockito">
+      <dependencies>
+        <dependency>
+          <groupId>org.mockito</groupId>
+          <artifactId>mockito-core</artifactId>
+          <version>5.21.0</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="jna">
+      <dependencies>
+        <dependency>
+          <groupId>net.java.dev.jna</groupId>
+          <artifactId>jna</artifactId>
+          <version>5.18.1</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>net.java.dev.jna</groupId>
+          <artifactId>jna-platform</artifactId>
+          <version>5.18.1</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="jetty">
+      <dependencies>
+        <dependency>
+          <groupId>org.eclipse.jetty.ee10</groupId>
+          <artifactId>jetty-ee10-servlet</artifactId>
+          <version>12.1.6</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-http</artifactId>
+          <version>12.1.6</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-io</artifactId>
+          <version>12.1.6</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-security</artifactId>
+          <version>12.1.6</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-server</artifactId>
+          <version>12.1.6</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-session</artifactId>
+          <version>12.1.6</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-util</artifactId>
+          <version>12.1.6</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-util-ajax</artifactId>
+          <version>12.1.6</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>jakarta.servlet</groupId>
+          <artifactId>jakarta.servlet-api</artifactId>
+          <version>6.1.0</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="javaewah">
+      <dependencies>
+        <dependency>
+          <groupId>com.googlecode.javaewah</groupId>
+          <artifactId>JavaEWAH</artifactId>
+          <version>1.2.3</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="hamcrest">
+      <dependencies>
+        <dependency>
+          <groupId>org.hamcrest</groupId>
+          <artifactId>hamcrest</artifactId>
+          <version>3.0</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="gson">
+      <dependencies>
+        <dependency>
+          <groupId>com.google.code.gson</groupId>
+          <artifactId>gson</artifactId>
+          <version>2.13.2</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="bytebuddy">
+      <dependencies>
+        <dependency>
+          <groupId>net.bytebuddy</groupId>
+          <artifactId>byte-buddy</artifactId>
+          <version>1.18.5</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>net.bytebuddy</groupId>
+          <artifactId>byte-buddy-agent</artifactId>
+          <version>1.18.5</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="bouncycastle">
+      <dependencies>
+        <dependency>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcpg-jdk18on</artifactId>
+          <version>1.83</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcprov-jdk18on</artifactId>
+          <version>1.83</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcpkix-jdk18on</artifactId>
+          <version>1.83</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcutil-jdk18on</artifactId>
+          <version>1.83</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="assertj">
+      <dependencies>
+        <dependency>
+          <groupId>org.assertj</groupId>
+          <artifactId>assertj-core</artifactId>
+          <version>3.27.7</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="args4j">
+      <dependencies>
+        <dependency>
+          <groupId>args4j</groupId>
+          <artifactId>args4j</artifactId>
+          <version>2.37</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+    <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="apache">
+      <dependencies>
+        <dependency>
+          <groupId>commons-codec</groupId>
+          <artifactId>commons-codec</artifactId>
+          <version>1.21.0</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.commons</groupId>
+          <artifactId>commons-compress</artifactId>
+          <version>1.28.0</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.commons</groupId>
+          <artifactId>commons-lang3</artifactId>
+          <version>3.20.0</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>commons-io</groupId>
+          <artifactId>commons-io</artifactId>
+          <version>2.21.0</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+          <version>1.3.5</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+  </locations>
+</target>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.39.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.39.tpd
new file mode 100644
index 0000000..0b32b1b
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.39.tpd
@@ -0,0 +1,8 @@
+target "jgit-4.39" with source configurePhase
+
+include "orbit/orbit-4.39.tpd"
+include "maven/dependencies.tpd"
+
+location "https://download.eclipse.org/staging/2026-03/" {
+	org.eclipse.osgi lazy
+}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd
index bd29539..d5d06dc 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd
@@ -10,7 +10,7 @@
 	dependency {
 		groupId = "commons-codec"
 		artifactId = "commons-codec"
-		version = "1.20.0"
+		version = "1.21.0"
 	}
 	dependency {
 		groupId = "org.apache.commons"
@@ -56,7 +56,7 @@
 	dependency {
 		groupId = "org.assertj"
 		artifactId = "assertj-core"
-		version = "3.27.6"
+		version = "3.27.7"
 	}
 }
 
@@ -69,22 +69,22 @@
 	dependency {
 		groupId = "org.bouncycastle"
 		artifactId = "bcpg-jdk18on"
-		version = "1.82"
+		version = "1.83"
 	}
 	dependency {
 		groupId = "org.bouncycastle"
 		artifactId = "bcprov-jdk18on"
-		version = "1.82"
+		version = "1.83"
 	}
 	dependency {
 		groupId = "org.bouncycastle"
 		artifactId = "bcpkix-jdk18on"
-		version = "1.82"
+		version = "1.83"
 	}
 	dependency {
 		groupId = "org.bouncycastle"
 		artifactId = "bcutil-jdk18on"
-		version = "1.82"
+		version = "1.83"
 	}
 }
 
@@ -97,12 +97,12 @@
 	dependency {
 		groupId = "net.bytebuddy"
 		artifactId = "byte-buddy"
-		version = "1.18.1"
+		version = "1.18.5"
 	}
 	dependency {
 		groupId = "net.bytebuddy"
 		artifactId = "byte-buddy-agent"
-		version = "1.18.1"
+		version = "1.18.5"
 	}
 }
 
@@ -154,42 +154,42 @@
 	dependency {
 		groupId = "org.eclipse.jetty.ee10"
 		artifactId = "jetty-ee10-servlet"
-		version = "12.1.4"
+		version = "12.1.6"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-http"
-		version = "12.1.4"
+		version = "12.1.6"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-io"
-		version = "12.1.4"
+		version = "12.1.6"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-security"
-		version = "12.1.4"
+		version = "12.1.6"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-server"
-		version = "12.1.4"
+		version = "12.1.6"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-session"
-		version = "12.1.4"
+		version = "12.1.6"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-util"
-		version = "12.1.4"
+		version = "12.1.6"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-util-ajax"
-		version = "12.1.4"
+		version = "12.1.6"
 	}
 	dependency {
 		groupId = "jakarta.servlet"
@@ -225,7 +225,7 @@
 	dependency {
 		groupId = "org.mockito"
 		artifactId = "mockito-core"
-		version = "5.20.0"
+		version = "5.21.0"
 	}
 }
 
@@ -238,12 +238,12 @@
 	dependency {
 		groupId = "org.apache.sshd"
 		artifactId = "sshd-osgi"
-		version = "2.16.0"
+		version = "2.17.1"
 	}
 	dependency {
 		groupId = "org.apache.sshd"
 		artifactId = "sshd-sftp"
-		version = "2.16.0"
+		version = "2.17.1"
 	}
 }
 
@@ -263,6 +263,11 @@
 		artifactId = "slf4j-simple"
 		version = "2.0.17"
 	}
+	dependency {
+		groupId = "org.slf4j"
+		artifactId = "jcl-over-slf4j"
+		version = "2.0.17"
+	}
 }
 
 maven xz
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.39.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.39.tpd
new file mode 100644
index 0000000..54f7789
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.39.tpd
@@ -0,0 +1,29 @@
+target "orbit-4.39" with source configurePhase
+// see https://download.eclipse.org/tools/orbit/downloads/
+
+location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2026-03" {
+	com.jcraft.jsch [0.1.55.v20230916-1400,0.1.55.v20230916-1400]
+	com.jcraft.jsch.source [0.1.55.v20230916-1400,0.1.55.v20230916-1400]
+	com.jcraft.jzlib [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
+	com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
+	org.apache.ant [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
+	org.apache.ant.source [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
+	org.apache.aries.spifly.dynamic.bundle [1.3.7,1.3.7]
+	org.apache.httpcomponents.httpclient [4.5.14,4.5.14]
+	org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14]
+	org.apache.httpcomponents.httpcore [4.4.16,4.4.16]
+	org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16]
+	org.hamcrest [3.0.0,3.0.0]
+	org.hamcrest.source [3.0.0,3.0.0]
+	org.junit [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
+	org.junit.source [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
+	org.objectweb.asm [9.9.1,9.9.1]
+	org.objectweb.asm.commons [9.9.1,9.9.1]
+	org.objectweb.asm.util [9.9.1,9.9.1]
+	org.objectweb.asm.tree [9.9.1,9.9.1]
+	org.objectweb.asm.tree.analysis [9.9.1,9.9.1]
+	org.objenesis [3.5.0,3.5.0]
+	org.objenesis.source [3.5.0,3.5.0]
+	org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733]
+	org.osgi.service.cm.source [1.6.1.202109301733,1.6.1.202109301733]
+}
diff --git a/org.eclipse.jgit.packaging/pom.xml b/org.eclipse.jgit.packaging/pom.xml
index 08a8989..0deaf2a 100644
--- a/org.eclipse.jgit.packaging/pom.xml
+++ b/org.eclipse.jgit.packaging/pom.xml
@@ -16,7 +16,7 @@
 
   <groupId>org.eclipse.jgit</groupId>
   <artifactId>jgit.tycho.parent</artifactId>
-  <version>7.5.1-SNAPSHOT</version>
+  <version>7.6.1-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>JGit Tycho Parent</name>
diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
index b64d3da..e8e35b5 100644
--- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
@@ -3,31 +3,31 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.pgm.test
 Bundle-SymbolicName: org.eclipse.jgit.pgm.test
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Import-Package: org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.diff;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.dircache;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.diffmergetool;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.merge;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.pgm;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.pgm.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.pgm.opt;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util.io;version="[7.5.1,7.6.0)",
+Import-Package: org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.diff;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.dircache;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.merge;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.pgm;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.pgm.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.pgm.opt;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util.io;version="[7.6.1,7.7.0)",
  org.hamcrest.core;bundle-version="[1.1.0,3.0.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.rules;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml
index 0b9d6f2..64a776c 100644
--- a/org.eclipse.jgit.pgm.test/pom.xml
+++ b/org.eclipse.jgit.pgm.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm.test</artifactId>
diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
index f65cc73..b84f517 100644
--- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.pgm
 Bundle-SymbolicName: org.eclipse.jgit.pgm
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -15,50 +15,50 @@
  org.eclipse.jetty.server.handler;version="[12.0.0,13.0.0)",
  org.eclipse.jetty.util;version="[12.0.0,13.0.0)",
  org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)",
- org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.archive;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.awtui;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.blame;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.diff;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.dircache;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.gitrepo;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.diffmergetool;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.io;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.midx;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.pack;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.server;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.server.fs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs.server.s3;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.merge;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.notes;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revplot;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk.filter;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.pack;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.http.apache;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.resolver;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.ssh.jsch;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.sshd;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util.io;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.archive;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.awtui;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.blame;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.diff;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.dircache;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.gitrepo;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.io;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.midx;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.server;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs.server.s3;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.merge;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.notes;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revplot;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk.filter;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.pack;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.http.apache;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.ssh.jsch;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.sshd;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util.io;version="[7.6.1,7.7.0)",
  org.kohsuke.args4j;version="[2.33.0,3.0.0)",
  org.kohsuke.args4j.spi;version="[2.33.0,3.0.0)"
-Export-Package: org.eclipse.jgit.console;version="7.5.1";
+Export-Package: org.eclipse.jgit.console;version="7.6.1";
  uses:="org.eclipse.jgit.transport,
   org.eclipse.jgit.util",
- org.eclipse.jgit.pgm;version="7.5.1";
+ org.eclipse.jgit.pgm;version="7.6.1";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.util.io,
    org.eclipse.jgit.awtui,
@@ -70,14 +70,14 @@
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.api,
    javax.swing",
- org.eclipse.jgit.pgm.debug;version="7.5.1";
+ org.eclipse.jgit.pgm.debug;version="7.6.1";
   uses:="org.eclipse.jgit.util.io,
    org.eclipse.jgit.pgm,
    org.eclipse.jetty.servlet",
- org.eclipse.jgit.pgm.internal;version="7.5.1";
+ org.eclipse.jgit.pgm.internal;version="7.6.1";
   x-friends:="org.eclipse.jgit.pgm.test,
    org.eclipse.jgit.test",
- org.eclipse.jgit.pgm.opt;version="7.5.1";
+ org.eclipse.jgit.pgm.opt;version="7.6.1";
   uses:="org.kohsuke.args4j,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
diff --git a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
index 1b194cd..b8dceb8 100644
--- a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.pgm - Sources
 Bundle-SymbolicName: org.eclipse.jgit.pgm.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml
index 2e29c6c..5cfa942 100644
--- a/org.eclipse.jgit.pgm/pom.xml
+++ b/org.eclipse.jgit.pgm/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm</artifactId>
diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
index 606b29d..96ecf2a 100644
--- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
+++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
@@ -284,6 +284,8 @@
 usage_DisplayTheVersionOfJgit=Display the version of jgit
 usage_Exclude=Do not consider tags matching the given glob(7) pattern, excluding the "refs/tags/" prefix
 usage_Gc=Cleanup unnecessary files and optimize the local repository
+usage_GcPackRefs=Pack all refs except symbolic refs, default can be configured by "gc.packRefs" which defaults to true
+usage_GcNoPackRefs=Do not pack refs
 usage_Glog=View commit history as a graph
 usage_DiffGuiTool=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.
 usage_MergeGuiTool=When git-mergetool is invoked with the -g or --gui option the default merge tool will be read from the configured merge.guitool variable instead of merge.tool.
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java
index 35ac7a1..f278e55 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java
@@ -13,6 +13,8 @@
 import org.eclipse.jgit.api.GarbageCollectCommand;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.GcConfig;
+import org.eclipse.jgit.lib.GcConfig.PackRefsMode;
 import org.eclipse.jgit.lib.TextProgressMonitor;
 import org.kohsuke.args4j.Option;
 
@@ -30,6 +32,16 @@ class Gc extends TextBuiltin {
 	@Option(name = "--pack-kept-objects", usage = "usage_PackKeptObjects")
 	private Boolean packKeptObjects;
 
+	@Option(name = "--pack-refs", forbids = {
+			"--no-pack-refs" }, usage = "usage_GcPackRefs")
+	private Boolean packRefs;
+
+	@Option(name = "--no-pack-refs", forbids = {
+			"--pack-refs" }, usage = "usage_GcNoPackRefs")
+	void noPackRefs(@SuppressWarnings("unused") final boolean ignored) {
+		packRefs = Boolean.FALSE;
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	protected void run() {
@@ -46,6 +58,11 @@ protected void run() {
 			if (packKeptObjects != null) {
 				command.setPackKeptObjects(packKeptObjects.booleanValue());
 			}
+			if (packRefs != null) {
+				command.setGcConfig(
+						new GcConfig(packRefs.booleanValue() ? PackRefsMode.TRUE
+								: PackRefsMode.FALSE));
+			}
 			command.call();
 		} catch (GitAPIException e) {
 			throw die(e.getMessage(), e);
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java
index a7df4fa..d91f713 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java
@@ -16,14 +16,13 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.util.LinkedHashMap;
 
 import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
 import org.eclipse.jgit.internal.storage.file.Pack;
 import org.eclipse.jgit.internal.storage.file.PackFile;
-import org.eclipse.jgit.internal.storage.file.PackIndex;
 import org.eclipse.jgit.internal.storage.midx.MultiPackIndexPrettyPrinter;
 import org.eclipse.jgit.internal.storage.midx.MultiPackIndexWriter;
+import org.eclipse.jgit.internal.storage.midx.PackIndexMerger;
 import org.eclipse.jgit.internal.storage.pack.PackExt;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.kohsuke.args4j.Argument;
@@ -86,11 +85,11 @@ private void writeMultiPackIndex() throws IOException {
 
 		ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
 
-		LinkedHashMap<String, PackIndex> indexes = new LinkedHashMap<>();
+		PackIndexMerger.Builder builder = PackIndexMerger.builder();
 		for (Pack pack : odb.getPacks()) {
 			PackFile packFile = pack.getPackFile().create(PackExt.INDEX);
 			try {
-				indexes.put(packFile.getName(), pack.getIndex());
+				builder.addPack(packFile.getName(), pack.getIndex());
 			} catch (IOException e) {
 				throw die("Cannot open index in pack", e);
 			}
@@ -98,7 +97,7 @@ private void writeMultiPackIndex() throws IOException {
 
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		try (FileOutputStream out = new FileOutputStream(midxPath)) {
-			writer.write(NullProgressMonitor.INSTANCE, out, indexes);
+			writer.write(NullProgressMonitor.INSTANCE, out, builder.build());
 		} catch (IOException e) {
 			throw die("Cannot write midx " + midxPath, e);
 		}
diff --git a/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF
index 4fad2d2..23f054f 100644
--- a/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF
@@ -2,17 +2,17 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.agent;singleton:=true
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Localization: OSGI-INF/l10n/agent
 Bundle-Vendor: %Bundle-Vendor
-Fragment-Host: org.eclipse.jgit.ssh.apache;bundle-version="[7.5.1,7.6.0)"
+Fragment-Host: org.eclipse.jgit.ssh.apache;bundle-version="[7.6.1,7.7.0)"
 Bundle-ActivationPolicy: lazy
 Automatic-Module-Name: org.eclipse.jgit.ssh.apache.agent
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Import-Package: org.eclipse.jgit.transport.sshd;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)"
+Import-Package: org.eclipse.jgit.transport.sshd;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)"
 Require-Bundle: com.sun.jna;bundle-version="[5.8.0,6.0.0)",
  com.sun.jna.platform;bundle-version="[5.8.0,6.0.0)"
-Export-Package: org.eclipse.jgit.internal.transport.sshd.agent.connector;version="7.5.1";x-internal:=true
+Export-Package: org.eclipse.jgit.internal.transport.sshd.agent.connector;version="7.6.1";x-internal:=true
diff --git a/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF
index 60495c9..6143a09 100644
--- a/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.ssh.apache.agent - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.agent.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache.agent;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache.agent;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.apache.agent/pom.xml b/org.eclipse.jgit.ssh.apache.agent/pom.xml
index 234dcdc..748454a 100644
--- a/org.eclipse.jgit.ssh.apache.agent/pom.xml
+++ b/org.eclipse.jgit.ssh.apache.agent/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.apache.agent</artifactId>
diff --git a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
index 973164b..f99e052 100644
--- a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
@@ -3,45 +3,45 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ssh.apache.test
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.test
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Import-Package: org.apache.sshd.agent;version="[2.16.0,2.17.0)",
- org.apache.sshd.certificate;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.config.hosts;version="[2.16.0,2.17.0)",
- org.apache.sshd.common;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.auth;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.cipher;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.config.keys;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.helpers;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.kex;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.keyprovider;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.session;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.signature;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.buffer;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.net;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.security;version="[2.16.0,2.17.0)",
- org.apache.sshd.core;version="[2.16.0,2.17.0)",
- org.apache.sshd.server;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.forward;version="[2.16.0,2.17.0)",
- org.eclipse.jgit.annotations;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.signing.ssh;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.transport.sshd;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.transport.sshd.proxy;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit.ssh;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.sshd;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.sshd.agent;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+Import-Package: org.apache.sshd.agent;version="[2.17.1,2.18.0)",
+ org.apache.sshd.certificate;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.config.hosts;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.auth;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.cipher;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.config.keys;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.helpers;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.kex;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.keyprovider;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.session;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.signature;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.buffer;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.net;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.security;version="[2.17.1,2.18.0)",
+ org.apache.sshd.core;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.forward;version="[2.17.1,2.18.0)",
+ org.eclipse.jgit.annotations;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.signing.ssh;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.transport.sshd;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.transport.sshd.proxy;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit.ssh;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.sshd;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.sshd.agent;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.hamcrest;version="[3.0.0,4.0.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.experimental.theories;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.ssh.apache.test/pom.xml b/org.eclipse.jgit.ssh.apache.test/pom.xml
index 72ed0d3..8dbc498 100644
--- a/org.eclipse.jgit.ssh.apache.test/pom.xml
+++ b/org.eclipse.jgit.ssh.apache.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId>
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
index d85e7b7..c4c1117 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
@@ -6,11 +6,11 @@
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-ActivationPolicy: lazy
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Export-Package: org.eclipse.jgit.internal.signing.ssh;version="7.5.1";x-friends:="org.eclipse.jgit.ssh.apache.test",
- org.eclipse.jgit.internal.transport.sshd;version="7.5.1";x-friends:="org.eclipse.jgit.ssh.apache.test";
+Export-Package: org.eclipse.jgit.internal.signing.ssh;version="7.6.1";x-friends:="org.eclipse.jgit.ssh.apache.test",
+ org.eclipse.jgit.internal.transport.sshd;version="7.6.1";x-friends:="org.eclipse.jgit.ssh.apache.test";
   uses:="org.apache.sshd.client,
    org.apache.sshd.client.auth,
    org.apache.sshd.client.auth.keyboard,
@@ -25,80 +25,80 @@
    org.apache.sshd.common.signature,
    org.apache.sshd.common.util.buffer,
    org.eclipse.jgit.transport",
- org.eclipse.jgit.internal.transport.sshd.agent;version="7.5.1";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.auth;version="7.5.1";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.pkcs11;version="7.5.1";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.proxy;version="7.5.1";x-friends:="org.eclipse.jgit.ssh.apache.test",
- org.eclipse.jgit.signing.ssh;version="7.5.1";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.transport.sshd;version="7.5.1";
+ org.eclipse.jgit.internal.transport.sshd.agent;version="7.6.1";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.auth;version="7.6.1";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.pkcs11;version="7.6.1";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.proxy;version="7.6.1";x-friends:="org.eclipse.jgit.ssh.apache.test",
+ org.eclipse.jgit.signing.ssh;version="7.6.1";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.transport.sshd;version="7.6.1";
   uses:="org.eclipse.jgit.transport,
    org.apache.sshd.client.config.hosts,
    org.apache.sshd.common.keyprovider,
    org.eclipse.jgit.util,
    org.apache.sshd.client.session,
    org.apache.sshd.client.keyverifier",
- org.eclipse.jgit.transport.sshd.agent;version="7.5.1"
+ org.eclipse.jgit.transport.sshd.agent;version="7.6.1"
 Import-Package: org.bouncycastle.jce.provider;version="[1.80.0,2.0.0)",
- org.apache.sshd.agent;version="[2.16.0,2.17.0)",
- org.apache.sshd.client;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.auth;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.auth.keyboard;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.auth.password;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.auth.pubkey;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.channel;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.config.hosts;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.config.keys;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.future;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.keyverifier;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.session;version="[2.16.0,2.17.0)",
- org.apache.sshd.client.session.forward;version="[2.16.0,2.17.0)",
- org.apache.sshd.common;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.auth;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.channel;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.cipher;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.compression;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.config.keys;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.config.keys.loader;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.config.keys.loader.openssh.kdf;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.config.keys.u2f;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.digest;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.forward;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.future;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.helpers;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.io;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.kex;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.kex.extension;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.kex.extension.parser;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.keyprovider;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.mac;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.random;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.session;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.session.helpers;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.signature;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.buffer;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.buffer.keys;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.closeable;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.io;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.io.der;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.io.functors;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.io.resource;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.logging;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.net;version="[2.16.0,2.17.0)",
- org.apache.sshd.common.util.security;version="[2.16.0,2.17.0)",
- org.apache.sshd.core;version="[2.16.0,2.17.0)",
- org.apache.sshd.server.auth;version="[2.16.0,2.17.0)",
- org.apache.sshd.sftp;version="[2.16.0,2.17.0)",
- org.apache.sshd.sftp.client;version="[2.16.0,2.17.0)",
- org.apache.sshd.sftp.common;version="[2.16.0,2.17.0)",
- org.eclipse.jgit.annotations;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.fnmatch;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+ org.apache.sshd.agent;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.auth;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.auth.keyboard;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.auth.password;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.auth.pubkey;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.channel;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.config.hosts;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.config.keys;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.future;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.keyverifier;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.session;version="[2.17.1,2.18.0)",
+ org.apache.sshd.client.session.forward;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.auth;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.channel;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.cipher;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.compression;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.config.keys;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.config.keys.loader;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.config.keys.loader.openssh.kdf;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.config.keys.u2f;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.digest;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.forward;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.future;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.helpers;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.io;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.kex;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.kex.extension;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.kex.extension.parser;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.keyprovider;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.mac;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.random;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.session;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.session.helpers;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.signature;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.buffer;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.buffer.keys;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.closeable;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.io;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.io.der;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.io.functors;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.io.resource;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.logging;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.net;version="[2.17.1,2.18.0)",
+ org.apache.sshd.common.util.security;version="[2.17.1,2.18.0)",
+ org.apache.sshd.core;version="[2.17.1,2.18.0)",
+ org.apache.sshd.server.auth;version="[2.17.1,2.18.0)",
+ org.apache.sshd.sftp;version="[2.17.1,2.18.0)",
+ org.apache.sshd.sftp.client;version="[2.17.1,2.18.0)",
+ org.apache.sshd.sftp.common;version="[2.17.1,2.18.0)",
+ org.eclipse.jgit.annotations;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.fnmatch;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.slf4j;version="[1.7.0,3.0.0)"
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
index ef612b7..905c9ca 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.ssh.apache - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.apache/pom.xml b/org.eclipse.jgit.ssh.apache/pom.xml
index 2de7a76..064070f 100644
--- a/org.eclipse.jgit.ssh.apache/pom.xml
+++ b/org.eclipse.jgit.ssh.apache/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.apache</artifactId>
diff --git a/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF
index 4d5cc36..f13697a 100644
--- a/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF
@@ -3,20 +3,20 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ssh.jsch.test
 Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch.test
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
 Import-Package: com.jcraft.jsch;version="[0.1.54,0.2.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit.ssh;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.ssh.jsch;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit.ssh;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.ssh.jsch;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
  org.hamcrest;version="[3.0.0,4.0.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.experimental.theories;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.ssh.jsch.test/pom.xml b/org.eclipse.jgit.ssh.jsch.test/pom.xml
index 0833655..271979f 100644
--- a/org.eclipse.jgit.ssh.jsch.test/pom.xml
+++ b/org.eclipse.jgit.ssh.jsch.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.jsch.test</artifactId>
diff --git a/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
index cbaf8ac..3e19f55 100644
--- a/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
@@ -3,20 +3,20 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ssh.jsch
 Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch;singleton:=true
-Fragment-Host: org.eclipse.jgit;bundle-version="[7.5.1,7.6.0)"
+Fragment-Host: org.eclipse.jgit;bundle-version="[7.6.1,7.7.0)"
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/jsch
 Bundle-ActivationPolicy: lazy
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Export-Package: org.eclipse.jgit.transport.ssh.jsch;version="7.5.1"
+Export-Package: org.eclipse.jgit.transport.ssh.jsch;version="7.6.1"
 Import-Package: com.jcraft.jsch;version="[0.1.37,0.2.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util.io;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util.io;version="[7.6.1,7.7.0)",
  org.slf4j;version="[1.7.0,3.0.0)"
diff --git a/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
index f8b3415..a233162 100644
--- a/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.ssh.jsch - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.jsch;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.jsch;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.jsch/pom.xml b/org.eclipse.jgit.ssh.jsch/pom.xml
index e6781d8..3c8e0b2 100644
--- a/org.eclipse.jgit.ssh.jsch/pom.xml
+++ b/org.eclipse.jgit.ssh.jsch/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.jsch</artifactId>
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index 1cf7813..6a46e85 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.test
 Bundle-SymbolicName: org.eclipse.jgit.test
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -21,66 +21,66 @@
  org.apache.commons.io.output;version="[2.15.0,3.0.0)",
  org.apache.commons.lang3;version="[3.17.0,4.0.0)",
  org.assertj.core.api;version="[3.14.0,4.0.0)",
- org.eclipse.jgit.annotations;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.api.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.archive;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.attributes;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.awtui;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.blame;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.blame.cache;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.diff;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.dircache;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.events;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.fnmatch;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.gitrepo;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.hooks;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.ignore;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.ignore.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.diff;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.diffmergetool;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.fsck;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.commitgraph;version="7.5.1",
- org.eclipse.jgit.internal.storage.dfs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.io;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.memory;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.midx;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.pack;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.transport.connectivity;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.transport.http;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.transport.parser;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.junit.time;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lfs;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.logging;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.merge;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.notes;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.patch;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.pgm;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.pgm.internal;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revplot;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk.filter;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.file;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.storage.pack;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.submodule;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.http;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport.resolver;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util.io;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util.sha1;version="[7.5.1,7.6.0)",
+ org.eclipse.jgit.annotations;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.api.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.archive;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.attributes;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.awtui;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.blame;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.blame.cache;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.diff;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.dircache;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.events;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.fnmatch;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.gitrepo;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.hooks;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.ignore;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.ignore.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.diff;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.fsck;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.commitgraph;version="7.6.1",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.io;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.memory;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.midx;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.transport.connectivity;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.transport.http;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.transport.parser;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.junit.time;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lfs;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.logging;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.merge;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.notes;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.patch;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.pgm;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.pgm.internal;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revplot;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk.filter;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.file;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.storage.pack;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.submodule;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.http;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util.io;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util.sha1;version="[7.6.1,7.7.0)",
  org.hamcrest;version="[3.0.0,4.0.0)",
  org.hamcrest.collection;version="[3.0.0,4.0.0)",
  org.junit;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java
index 334e52b..3aa6d69 100644
--- a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java
+++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java
@@ -25,13 +25,10 @@
 import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.eclipse.jgit.internal.storage.file.Pack;
 import org.eclipse.jgit.internal.storage.file.PackFile;
-import org.eclipse.jgit.internal.storage.file.PackIndex;
 import org.eclipse.jgit.internal.storage.pack.PackExt;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
@@ -93,15 +90,15 @@ public void jgit_loadsCgitMidx()
 	}
 
 	private byte[] generateJGitMidx() throws IOException {
-		Map<String, PackIndex> indexes = new HashMap<>();
+		PackIndexMerger.Builder builder = PackIndexMerger.builder();
 		for (Pack pack : db.getObjectDatabase().getPacks()) {
 			PackFile packFile = pack.getPackFile().create(PackExt.INDEX);
-			indexes.put(packFile.getName(), pack.getIndex());
+			builder.addPack(packFile.getName(), pack.getIndex());
 		}
 
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		writer.write(NullProgressMonitor.INSTANCE, out, indexes);
+		writer.write(NullProgressMonitor.INSTANCE, out, builder.build());
 		return out.toByteArray();
 	}
 
diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml
index f3e49af..2f9e9ee 100644
--- a/org.eclipse.jgit.test/pom.xml
+++ b/org.eclipse.jgit.test/pom.xml
@@ -19,7 +19,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.test</artifactId>
diff --git a/org.eclipse.jgit.test/src/org/eclipse/jgit/internal/storage/dfs/MidxTestUtils.java b/org.eclipse.jgit.test/src/org/eclipse/jgit/internal/storage/dfs/MidxTestUtils.java
new file mode 100644
index 0000000..c5210c8
--- /dev/null
+++ b/org.eclipse.jgit.test/src/org/eclipse/jgit/internal/storage/dfs/MidxTestUtils.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.zip.Deflater;
+
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.storage.pack.PackConfig;
+
+/**
+ * Helpers to write multipack indexes
+ */
+public class MidxTestUtils {
+	private MidxTestUtils() {
+	}
+
+	/**
+	 * Write a single pack into the repo with the blob as contents
+	 *
+	 * @param db
+	 *            repository
+	 * @param blob
+	 *            blob to write into the pack
+	 * @return object id of the blob written in the pack
+	 * @throws IOException
+	 *             a problem writing in the repo
+	 */
+	static ObjectId writePackWithBlob(DfsRepository db, String blob)
+			throws IOException {
+		return writePackWithBlobs(db, blob)[0];
+	}
+
+	/**
+	 * Write multiple blobs into a single pack in the repo
+	 *
+	 * @param db
+	 *            repository
+	 * @param blobs
+	 *            blobs to write into the pack
+	 * @return object ids of the blobs written in the pack, in the same order as
+	 *         the input parameters
+	 * @throws IOException
+	 *             a problem writing in the repo
+	 */
+	static ObjectId[] writePackWithBlobs(DfsRepository db, String... blobs)
+			throws IOException {
+		ObjectId[] oids = new ObjectId[blobs.length];
+
+		DfsInserter ins = (DfsInserter) db.newObjectInserter();
+		ins.setCompressionLevel(Deflater.NO_COMPRESSION);
+		for (int i = 0; i < blobs.length; i++) {
+			oids[i] = ins.insert(OBJ_BLOB, blobs[i].getBytes(UTF_8));
+		}
+		ins.flush();
+		return oids;
+	}
+
+	/**
+	 * Write a midx covering the only pack in the repo
+	 *
+	 * @param db
+	 *            a repository with a single pack
+	 * @return a midx covering that single pack
+	 * @throws IOException
+	 *             a problem writing in the repo
+	 */
+	static DfsPackFileMidx writeSinglePackMidx(DfsRepository db)
+			throws IOException {
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		assertEquals("More than one pack in db", 1, packs.length);
+		return writeSinglePackMidx(db, packs[0]);
+	}
+
+	/**
+	 * Write a midx covering a single pack
+	 *
+	 * @param db
+	 *            a repository to write the midx covering the pack
+	 * @param pack
+	 *            a pack in the repository that will be covered by a new midx
+	 * @return a midx covering that single pack
+	 * @throws IOException
+	 *             a problem writing in the repo
+	 */
+	static DfsPackFileMidx writeSinglePackMidx(DfsRepository db,
+			DfsPackFile pack) throws IOException {
+		return writeMultipackIndex(db, new DfsPackFile[] { pack }, null);
+	}
+
+	/**
+	 * Write a midx covering a single pack
+	 *
+	 * @param db
+	 *            a repository to write the midx covering the pack
+	 * @param pack
+	 *            a pack in the repository that will be covered by a new midx
+	 * @param base
+	 *            base of this midx (can be null)
+	 * @return a midx covering that single pack
+	 * @throws IOException
+	 *             a problem writing in the repo
+	 */
+	static DfsPackFileMidx writeSinglePackMidx(DfsRepository db,
+			DfsPackFile pack, @Nullable DfsPackFileMidx base)
+			throws IOException {
+		return writeMultipackIndex(db, new DfsPackFile[] { pack }, base);
+	}
+
+	/**
+	 * Write a midx in the repository
+	 *
+	 * @param db
+	 *            the repository
+	 * @param packs
+	 *            packs to be covered by this midx
+	 * @param base
+	 *            base of the newly created midx
+	 * @return the new midx instance
+	 * @throws IOException
+	 *             a problem writing in the repo
+	 */
+	static DfsPackFileMidx writeMultipackIndex(DfsRepository db,
+			DfsPackFile[] packs, DfsPackFileMidx base) throws IOException {
+		PackConfig packConfig = new PackConfig(db);
+		packConfig.setBitmapRecentCommitSpan(1); // bitmap every commit!
+		DfsPackDescription desc = DfsMidxWriter.writeMidx(
+				NullProgressMonitor.INSTANCE, db.getObjectDatabase(),
+				Arrays.asList(packs),
+				base != null ? base.getPackDescription() : null, packConfig);
+		db.getObjectDatabase().commitPack(List.of(desc), null);
+		return DfsPackFileMidx.create(DfsBlockCache.getInstance(), desc,
+				Arrays.asList(packs), base);
+	}
+
+	record CommitObjects(RevCommit commit, RevTree tree, RevBlob blob) {
+	}
+
+	private static int commitCounter = 1;
+
+	static List<CommitObjects> writeCommitChain(DfsRepository db,
+			String refname, int length) throws Exception {
+		List<CommitObjects> co = new ArrayList<>(length);
+		RevCommit tip = null;
+		Ref ref = db.getRefDatabase().findRef(refname);
+		if (ref != null) {
+			tip = db.parseCommit(ref.getObjectId());
+		}
+
+		try (TestRepository<InMemoryRepository> repository = new TestRepository<>(
+				(InMemoryRepository) db);
+				DfsInserter ins = (DfsInserter) db.getObjectDatabase()
+						.newInserter()) {
+			for (int i = 0; i < length; i++) {
+				RevBlob blob = repository.blob("blob" + commitCounter);
+
+				tip = repository.branch(refname).commit().parent(tip)
+						.add("blob" + commitCounter, blob).create();
+				commitCounter++;
+				co.add(new CommitObjects(tip, tip.getTree(), blob));
+			}
+		}
+		return co;
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
index 2266772..0d87109 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
@@ -27,6 +27,7 @@
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.nio.file.Files;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
@@ -110,6 +111,46 @@ public void testAddExistingSingleFile() throws IOException, GitAPIException {
 	}
 
 	@Test
+	public void testAddExistingMultipleFiles()
+			throws IOException, GitAPIException {
+		File file = new File(db.getWorkTree(), "a.txt");
+		FileUtils.createNewFile(file);
+		file = new File(db.getWorkTree(), "b.txt");
+		FileUtils.createNewFile(file);
+		try (PrintWriter writer = new PrintWriter(file, UTF_8.name())) {
+			writer.print("content");
+		}
+
+		try (Git git = new Git(db)) {
+			git.add().addFilepatterns("a.txt", "b.txt").call();
+
+			assertEquals(
+					"[a.txt, mode:100644, content:][b.txt, mode:100644, content:content]",
+					indexState(CONTENT));
+		}
+	}
+
+	@Test
+	public void testAddExistingMultipleFilesCollection()
+			throws IOException, GitAPIException {
+		File file = new File(db.getWorkTree(), "a.txt");
+		FileUtils.createNewFile(file);
+		file = new File(db.getWorkTree(), "b.txt");
+		FileUtils.createNewFile(file);
+		try (PrintWriter writer = new PrintWriter(file, UTF_8.name())) {
+			writer.print("content");
+		}
+
+		try (Git git = new Git(db)) {
+			git.add().addFilepatterns(List.of("a.txt", "b.txt")).call();
+
+			assertEquals(
+					"[a.txt, mode:100644, content:][b.txt, mode:100644, content:content]",
+					indexState(CONTENT));
+		}
+	}
+
+	@Test
 	public void testAddLink() throws IOException, GitAPIException {
 		assumeTrue(db.getFS().supportsSymlinks());
 		try (Git git = new Git(db)) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java
index 3f5c5da..cb91b12 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java
@@ -11,6 +11,8 @@
 
 import static org.eclipse.jgit.api.CherryPickCommitMessageProvider.ORIGINAL;
 import static org.eclipse.jgit.api.CherryPickCommitMessageProvider.ORIGINAL_WITH_REFERENCE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -22,6 +24,7 @@
 import java.util.Iterator;
 
 import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus;
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.ResetCommand.ResetType;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.JGitInternalException;
@@ -396,6 +399,23 @@ public void testCherryPickConflictMarkers() throws Exception {
 	}
 
 	@Test
+	public void testCherryPickConflictDiff3Markers() throws Exception {
+		try (Git git = new Git(db)) {
+			RevCommit sideCommit = prepareCherryPick(git);
+
+			db.getConfig().setEnum(CONFIG_MERGE_SECTION, null,
+					CONFIG_KEY_CONFLICTSTYLE, ConflictStyle.DIFF3);
+
+			CherryPickResult result = git.cherryPick()
+					.include(sideCommit.getId()).call();
+			assertEquals(CherryPickStatus.CONFLICTING, result.getStatus());
+
+			String expected = "<<<<<<< master\na(master)\n||||||| BASE\na\n=======\na(side)\n>>>>>>> 527460a side\n";
+			checkFile(new File(db.getWorkTree(), "a"), expected);
+		}
+	}
+
+	@Test
 	public void testCherryPickConflictFiresModifiedEvent() throws Exception {
 		ListenerHandle listener = null;
 		try (Git git = new Git(db)) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java
index 6090d5e..2954570 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java
@@ -9,12 +9,16 @@
  */
 package org.eclipse.jgit.api;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import java.io.IOException;
 import java.time.Instant;
 import java.util.Properties;
 
 import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.GcConfig;
+import org.eclipse.jgit.lib.GcConfig.PackRefsMode;
 import org.eclipse.jgit.util.GitTimeParser;
 import org.junit.Before;
 import org.junit.Test;
@@ -34,6 +38,22 @@ public void setUp() throws Exception {
 	}
 
 	@Test
+	public void testPackRefs() throws Exception {
+		assertTrue(hasLooseRef(git));
+
+		// by default, refs should be packed
+		git.gc().call();
+		assertFalse(hasLooseRef(git));
+
+		// now create a loose ref again
+		git.branchCreate().setName("foo").call();
+		assertTrue(hasLooseRef(git));
+
+		git.gc().setGcConfig(new GcConfig(PackRefsMode.FALSE)).call();
+		assertTrue(hasLooseRef(git));
+	}
+
+	@Test
 	public void testGConeCommit() throws Exception {
 		Instant expireNow = GitTimeParser.parseInstant("now");
 		Properties res = git.gc().setExpire(expireNow).call();
@@ -54,4 +74,10 @@ public void testGCmoreCommits() throws Exception {
 		Properties res = git.gc().setExpire(expireNow).call();
 		assertTrue(res.size() == 8);
 	}
+
+	private static boolean hasLooseRef(Git git) throws IOException {
+		return git.getRepository().getRefDatabase().getRefs().stream()
+				.filter(r -> !r.isSymbolic())
+				.anyMatch(r -> r.getStorage().isLoose());
+	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
index 1ec5067..086e261 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
@@ -10,6 +10,8 @@
  */
 package org.eclipse.jgit.api;
 
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.eclipse.jgit.lib.Constants.MASTER;
 import static org.eclipse.jgit.lib.Constants.R_HEADS;
 import static org.junit.Assert.assertEquals;
@@ -27,6 +29,7 @@
 import java.util.Iterator;
 import java.util.regex.Pattern;
 
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
 import org.eclipse.jgit.api.MergeResult.MergeStatus;
 import org.eclipse.jgit.api.ResetCommand.ResetType;
@@ -2220,4 +2223,37 @@ private void checkMergeFailedResult(final MergeResult result,
 		assertEquals(null, result.getConflicts());
 		assertEquals(RepositoryState.SAFE, db.getRepositoryState());
 	}
+
+	@Test
+	public void testDiff3ConflictStyle() throws Exception {
+		try (Git git = new Git(db)) {
+			writeTrashFile("a", "1\na\n3\n");
+			git.add().addFilepattern("a").call();
+			RevCommit initialCommit = git.commit().setMessage("initial").call();
+
+			createBranch(initialCommit, "refs/heads/side");
+			checkoutBranch("refs/heads/side");
+
+			writeTrashFile("a", "1\na(side)\n3\n");
+			git.add().addFilepattern("a").call();
+			RevCommit secondCommit = git.commit().setMessage("side").call();
+
+			checkoutBranch("refs/heads/master");
+
+			writeTrashFile("a", "1\na(main)\n3\n");
+			git.add().addFilepattern("a").call();
+			git.commit().setMessage("main").call();
+
+			db.getConfig().setEnum(CONFIG_MERGE_SECTION, null,
+					CONFIG_KEY_CONFLICTSTYLE, ConflictStyle.DIFF3);
+
+			MergeResult result = git.merge().include(secondCommit.getId())
+					.setStrategy(MergeStrategy.RESOLVE).call();
+			assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
+
+			assertEquals(
+					"1\n<<<<<<< HEAD\na(main)\n||||||| BASE\na\n=======\na(side)\n>>>>>>> d97aebf6e0bbdb3f21f8a22ec8cbf1ac24d986d8\n3\n",
+					read(new File(db.getWorkTree(), "a")));
+		}
+	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java
index 695681d..2dc77cf 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java
@@ -10,6 +10,8 @@
 package org.eclipse.jgit.api;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -25,6 +27,7 @@
 import java.util.concurrent.Callable;
 
 import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.MergeResult.MergeStatus;
 import org.eclipse.jgit.api.errors.NoHeadException;
 import org.eclipse.jgit.junit.JGitTestUtil;
@@ -163,6 +166,43 @@ public void testPullConflict() throws Exception {
 	}
 
 	@Test
+	public void testPullConflictDiff3() throws Exception {
+		PullResult res = target.pull().call();
+		// nothing to update since we don't have different data yet
+		assertTrue(res.getFetchResult().getTrackingRefUpdates().isEmpty());
+		assertTrue(res.getMergeResult().getMergeStatus()
+				.equals(MergeStatus.ALREADY_UP_TO_DATE));
+
+		assertFileContentsEqual(targetFile, "Hello world");
+
+		// change the source file
+		writeToFile(sourceFile, "Source change");
+		source.add().addFilepattern("SomeFile.txt").call();
+		source.commit().setMessage("Source change in remote").call();
+
+		// change the target file
+		writeToFile(targetFile, "Target change");
+		target.add().addFilepattern("SomeFile.txt").call();
+		target.commit().setMessage("Target change in local").call();
+
+		target.getRepository().getConfig().setEnum(CONFIG_MERGE_SECTION, null,
+				CONFIG_KEY_CONFLICTSTYLE, ConflictStyle.DIFF3);
+
+		res = target.pull().call();
+		assertFalse(res.getFetchResult().getTrackingRefUpdates().isEmpty());
+		assertTrue(res.getMergeResult().getMergeStatus()
+				.equals(MergeStatus.CONFLICTING));
+
+		String sourceChangeString = "Source change\n>>>>>>> branch 'master' of "
+				+ target.getRepository().getConfig().getString("remote",
+						"origin", "url");
+
+		assertFileContentsEqual(targetFile, "<<<<<<< HEAD\n" + "Target change\n"
+				+ "||||||| BASE\n" + "Hello world\n" + "=======\n"
+				+ sourceChangeString + "\n");
+	}
+
+	@Test
 	public void testPullConflictTheirs() throws Exception {
 		PullResult res = target.pull().call();
 		// nothing to update since we don't have different data yet
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
index 4c8cf06..d99c285 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
@@ -10,6 +10,8 @@
 package org.eclipse.jgit.api;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -30,6 +32,7 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.MergeResult.MergeStatus;
 import org.eclipse.jgit.api.RebaseCommand.InteractiveHandler;
 import org.eclipse.jgit.api.RebaseCommand.InteractiveHandler2;
@@ -371,6 +374,43 @@ public void testRebaseNoMergeBaseConflict() throws Exception {
 	}
 
 	/**
+	 * Create a commit A and an unrelated commit B creating the same file with
+	 * different content. Then rebase A onto B. The rebase should stop with a
+	 * conflict and the conflict style should be DIFF3.
+	 *
+	 * @throws Exception on errors
+	 */
+	@Test
+	public void testRebaseNoMergeBaseConflictDiff3() throws Exception {
+		writeTrashFile(FILE1, FILE1);
+		git.add().addFilepattern(FILE1).call();
+		RevCommit first = git.commit().setMessage("Add file").call();
+		File file1 = new File(db.getWorkTree(), FILE1);
+		assertTrue(file1.exists());
+		// Create an independent branch
+		git.checkout().setOrphan(true).setName("orphan").call();
+		git.rm().addFilepattern(FILE1).call();
+		assertFalse(file1.exists());
+		writeTrashFile(FILE1, "something else");
+		git.add().addFilepattern(FILE1).call();
+		git.commit().setMessage("Orphan").call();
+		checkoutBranch("refs/heads/master");
+		assertEquals(first.getId(), db.resolve("HEAD"));
+
+		db.getConfig().setEnum(CONFIG_MERGE_SECTION, null,
+				CONFIG_KEY_CONFLICTSTYLE, ConflictStyle.DIFF3);
+
+		RebaseResult res = git.rebase().setUpstream("refs/heads/orphan").call();
+		assertEquals(Status.STOPPED, res.getStatus());
+		assertEquals(first, res.getCurrentCommit());
+		checkFile(file1,
+				"<<<<<<< Upstream, based on orphan\n" + "something else\n"
+						+ "||||||| BASE\n" + "=======\n" + "file1\n"
+						+ ">>>>>>> "
+						+ first.abbreviate(7).name() + " Add file\n");
+	}
+
+	/**
 	 * Create the following commits and then attempt to rebase topic onto
 	 * master. This will serialize the branches.
 	 *
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java
index 89fdb32..a7a1dff 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java
@@ -9,6 +9,8 @@
  */
 package org.eclipse.jgit.api;
 
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -20,6 +22,7 @@
 import java.io.IOException;
 import java.util.Iterator;
 
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.MergeResult.MergeStatus;
 import org.eclipse.jgit.api.ResetCommand.ResetType;
 import org.eclipse.jgit.api.errors.GitAPIException;
@@ -377,6 +380,25 @@ public void testRevertConflictMarkers() throws Exception {
 	}
 
 	@Test
+	public void testRevertConflictMarkersDiff3() throws Exception {
+		try (Git git = new Git(db)) {
+			RevCommit sideCommit = prepareRevert(git);
+
+			db.getConfig().setEnum(CONFIG_MERGE_SECTION, null,
+					CONFIG_KEY_CONFLICTSTYLE, ConflictStyle.DIFF3);
+
+			RevertCommand revert = git.revert();
+			RevCommit newHead = revert.include(sideCommit.getId()).call();
+			assertNull(newHead);
+			MergeResult result = revert.getFailingResult();
+			assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
+
+			String expected = "<<<<<<< master\na(latest)\n||||||| BASE\na(previous)\n=======\na\n>>>>>>> ca96c31 second master\n";
+			checkFile(new File(db.getWorkTree(), "a"), expected);
+		}
+	}
+
+	@Test
 	public void testRevertOurCommitName() throws Exception {
 		try (Git git = new Git(db)) {
 			RevCommit sideCommit = prepareRevert(git);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java
index 49b31b1..b169fac 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java
@@ -9,15 +9,19 @@
  */
 package org.eclipse.jgit.api;
 
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.File;
 import java.text.MessageFormat;
 
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.errors.InvalidRefNameException;
 import org.eclipse.jgit.api.errors.JGitInternalException;
 import org.eclipse.jgit.api.errors.NoHeadException;
@@ -429,6 +433,43 @@ public void stashedContentMerge() throws Exception {
 	}
 
 	@Test
+	public void stashedContentMergeDiff3() throws Exception {
+		writeTrashFile(PATH, "content\nmore content\n");
+		git.add().addFilepattern(PATH).call();
+		git.commit().setMessage("more content").call();
+
+		writeTrashFile(PATH, "content\nhead change\nmore content\n");
+		git.add().addFilepattern(PATH).call();
+		git.commit().setMessage("even content").call();
+
+		writeTrashFile(PATH, "content\nstashed change\nmore content\n");
+
+		db.getConfig().setEnum(CONFIG_MERGE_SECTION, null,
+				CONFIG_KEY_CONFLICTSTYLE, ConflictStyle.DIFF3);
+
+		RevCommit stashed = git.stashCreate().call();
+		assertNotNull(stashed);
+		assertEquals("content\nhead change\nmore content\n",
+				read(committedFile));
+		assertTrue(git.status().call().isClean());
+		recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
+
+		writeTrashFile(PATH, "content\nmore content\ncommitted change\n");
+		git.add().addFilepattern(PATH).call();
+		git.commit().setMessage("committed change").call();
+		recorder.assertNoEvent();
+
+		assertThrows(StashApplyFailureException.class,
+				() -> git.stashApply().call());
+		recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
+		Status status = new StatusCommand(db).call();
+		assertEquals(1, status.getConflicting().size());
+		assertEquals(
+				"content\n<<<<<<< HEAD\n||||||| stashed HEAD\nhead change\n=======\nstashed change\n>>>>>>> stash\nmore content\ncommitted change\n",
+				read(PATH));
+	}
+
+	@Test
 	public void stashedContentMergeXtheirs() throws Exception {
 		writeTrashFile(PATH, "content\nmore content\n");
 		git.add().addFilepattern(PATH).call();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
index 0752cd5..c5acb95 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
@@ -1243,9 +1243,7 @@ public void midx_oneMidx_deleteMidxs_allObjectsOneGC() throws Exception {
 				.add("file.txt", git.blob("a blob")).parent(root).create();
 		assertEquals(3, countPacks(INSERT));
 
-		DfsPackDescription midx = DfsMidxWriter.writeMidx(
-				NullProgressMonitor.INSTANCE, odb,
-				Arrays.asList(odb.getPacks()), null);
+		DfsPackDescription midx = midx(Arrays.asList(odb.getPacks()), null);
 		odb.commitPack(List.of(midx), null);
 
 		gcNoTtl();
@@ -1279,13 +1277,11 @@ public void midx_chainedMidx_deleteMidxs_allObjsInOneGC() throws Exception {
 
 		List<DfsPackFile> basicPacks = Arrays.stream(odb.getPacks())
 				.collect(Collectors.toUnmodifiableList());
-		DfsPackDescription midx = DfsMidxWriter.writeMidx(NULL_PM, odb,
-				basicPacks.subList(0, 9), null);
-		odb.commitPack(List.of(midx), null);
+		DfsPackDescription baseMidx = midx(basicPacks.subList(0, 9), null);
+		odb.commitPack(List.of(baseMidx), null);
 
-		DfsPackDescription midx2 = DfsMidxWriter.writeMidx(NULL_PM, odb,
-				basicPacks.subList(9, 21), midx);
-		odb.commitPack(List.of(midx2), null);
+		DfsPackDescription tipMidx = midx(basicPacks.subList(9, 21), baseMidx);
+		odb.commitPack(List.of(tipMidx), null);
 
 		// Verify we got one pack that is an midx
 		// This is testing the test code
@@ -1294,7 +1290,7 @@ public void midx_chainedMidx_deleteMidxs_allObjsInOneGC() throws Exception {
 		DfsPackDescription theDesc = odb.getPacks()[0].getPackDescription();
 		assertTrue(theDesc.hasFileExt(MULTI_PACK_INDEX));
 		assertEquals(12, theDesc.getCoveredPacks().size());
-		assertEquals(theDesc.getMultiPackIndexBase(), midx);
+		assertEquals(theDesc.getMultiPackIndexBase(), baseMidx);
 		assertEquals(9,
 				theDesc.getMultiPackIndexBase().getCoveredPacks().size());
 		gcNoTtl();
@@ -1308,8 +1304,8 @@ public void midx_chainedMidx_deleteMidxs_allObjsInOneGC() throws Exception {
 		for (RevCommit c : knownCommits) {
 			assertTrue(isObjectInPack(c, pack));
 		}
-		assertFalse(odb.listPacks().contains(midx));
-		assertFalse(odb.listPacks().contains(midx2));
+		assertFalse(odb.listPacks().contains(baseMidx));
+		assertFalse(odb.listPacks().contains(tipMidx));
 	}
 
 	@Test
@@ -1323,8 +1319,7 @@ public void midx_packAndMidx_deleteMidxs_allObjectsOneGC()
 		assertEquals(3, countPacks(INSERT));
 
 		List<DfsPackFile> packs = Arrays.stream(odb.getPacks()).toList();
-		DfsPackDescription midx = DfsMidxWriter.writeMidx(NULL_PM, odb, packs,
-				null);
+		DfsPackDescription midx = midx(packs, null);
 		odb.commitPack(List.of(midx), null);
 
 		RevBlob blobOutOfMidx = git.blob("some content");
@@ -1500,6 +1495,15 @@ private static DfsPackFile findFirstBySource(DfsPackFile[] packs, PackSource sou
 				.findFirst().get();
 	}
 
+	private DfsPackDescription midx(List<DfsPackFile> coveredPacks,
+			DfsPackDescription base) throws IOException {
+		DfsPackDescription midx = DfsMidxWriter.writeMidx(NULL_PM, odb,
+				coveredPacks, base);
+		git.tick(1);
+		midx.setLastModified(git.getInstant().toEpochMilli());
+		return midx;
+	}
+
 	private TestRepository<InMemoryRepository>.CommitBuilder commit() {
 		return git.commit();
 	}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriterBitmapsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriterBitmapsTest.java
new file mode 100644
index 0000000..0872dd4
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriterBitmapsTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2026, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.dfs.MidxTestUtils.writeMultipackIndex;
+import static org.eclipse.jgit.internal.storage.dfs.MidxTestUtils.writeSinglePackMidx;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_DISTANT_COMMIT_SPAN;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_PACK_SECTION;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.internal.storage.dfs.MidxTestUtils.CommitObjects;
+import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
+import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+
+@RunWith(Parameterized.class)
+public class DfsMidxWriterBitmapsTest {
+
+	@Parameterized.Parameters(name = "{0}")
+	public static Iterable<TestInput> data() throws Exception {
+		return List.of(setupOneMidxOverOnePack(), setupOneMidxOverNPacks());
+	}
+
+	private record TestInput(String testDesc, DfsRepository db,
+			DfsPackFileMidx midx, List<CommitObjects> commitObjects,
+			Map<String, CommitObjects> tips, int expectedBitmaps) {
+		@Override
+		public String toString() {
+			return testDesc;
+		}
+	}
+
+	private TestInput ti;
+
+	public DfsMidxWriterBitmapsTest(TestInput ti) {
+		this.ti = ti;
+	}
+
+	@Test
+	public void bitmapIndex_allObjectsHaveBitmapPosition() throws IOException {
+		try (DfsReader ctx = ti.db().getObjectDatabase().newReader()) {
+			PackBitmapIndex bi = ti.midx().getBitmapIndex(ctx);
+			for (int i = 0; i < ti.midx().getObjectCount(ctx); i++) {
+				PackReverseIndex reverseIdx = ti.midx().getReverseIdx(ctx);
+				// All objects in the bitmap
+				ObjectId oidByOffset = reverseIdx.findObjectByPosition(i);
+				assertEquals(i, bi.findPosition(oidByOffset));
+			}
+		}
+	}
+
+	@Test
+	public void bitmapIndex_bitmapHasRightObjects() throws IOException {
+		try (DfsReader ctx = ti.db().getObjectDatabase().newReader()) {
+			PackBitmapIndex bi = ti.midx().getBitmapIndex(ctx);
+
+			ObjectId mainTip = ti.tips().get("refs/heads/main").commit();
+			ObjectId devTip = ti.tips().get("refs/heads/dev").commit();
+			EWAHCompressedBitmap mainBitmap = bi.getBitmap(mainTip);
+			EWAHCompressedBitmap devBitmap = bi.getBitmap(devTip);
+
+			// main and dev commit chains do not have any commit in common
+			assertTrue(mainBitmap.and(devBitmap).isEmpty());
+			assertEquals(420, ti.midx().getObjectCount(ctx));
+
+			RevWalk rw = new RevWalk(ti.db());
+			rw.markStart(rw.parseCommit(mainTip));
+			for (RevCommit c; (c = rw.next()) != null;) {
+				int bitmapPos = bi.findPosition(c);
+				assertTrue(mainBitmap.get(bitmapPos));
+				assertFalse(devBitmap.get(bitmapPos));
+			}
+			rw.reset();
+
+			// dev is an independent chain of commits. None of them
+			// should be in the bitmap of "main"
+			rw.markStart(rw.parseCommit(devTip));
+			for (RevCommit c; (c = rw.next()) != null;) {
+				int bitmapPos = bi.findPosition(c);
+				assertTrue(devBitmap.get(bitmapPos));
+				assertFalse(mainBitmap.get(bitmapPos));
+			}
+		}
+	}
+
+	static TestInput setupOneMidxOverNPacks() throws Exception {
+		InMemoryRepository db = new InMemoryRepository(
+				new DfsRepositoryDescription("one_midx_n_packs"));
+		db.getObjectDatabase().getReaderOptions().setUseMidxBitmaps(true);
+
+		List<CommitObjects> mainObjs = MidxTestUtils.writeCommitChain(db,
+				"refs/heads/main", 100);
+		List<CommitObjects> devObjs = MidxTestUtils.writeCommitChain(db,
+				"refs/heads/dev", 40);
+
+		Map<String, CommitObjects> tips = new HashMap<>();
+		tips.put("refs/heads/main", last(mainObjs));
+		tips.put("refs/heads/dev", last(devObjs));
+
+		List<CommitObjects> commitObjects = new ArrayList<>(160);
+		commitObjects.addAll(mainObjs);
+		commitObjects.addAll(devObjs);
+
+		DfsPackFileMidx midx1 = writeMultipackIndex(db,
+				db.getObjectDatabase().getPacks(), null);
+		return new TestInput("one midx - n packs", db, midx1, commitObjects,
+				tips, tips.size());
+	}
+
+	static TestInput setupOneMidxOverOnePack() throws Exception {
+		InMemoryRepository db = new InMemoryRepository(
+				new DfsRepositoryDescription("one_midx_n_packs"));
+		// Mo midx bitmaps in midx over one pack. No need to set useMidxBitmaps.
+		enableMidxBitmaps(db);
+
+		List<CommitObjects> mainObjs = MidxTestUtils.writeCommitChain(db,
+				"refs/heads/main", 100);
+		List<CommitObjects> devObjs = MidxTestUtils.writeCommitChain(db,
+				"refs/heads/dev", 40);
+		runGc(db);
+
+		Map<String, CommitObjects> tips = new HashMap<>();
+		tips.put("refs/heads/main", last(mainObjs));
+		tips.put("refs/heads/dev", last(devObjs));
+
+		List<CommitObjects> commitObjects = new ArrayList<>(160);
+		commitObjects.addAll(mainObjs);
+		commitObjects.addAll(devObjs);
+
+		DfsPackFileMidx midx1 = writeSinglePackMidx(db);
+		return new TestInput("one midx - one pack", db, midx1, commitObjects,
+				tips, 0);
+	}
+
+	private static void enableMidxBitmaps(DfsRepository repo) {
+		repo.getConfig().setInt(CONFIG_PACK_SECTION, null,
+				CONFIG_KEY_BITMAP_DISTANT_COMMIT_SPAN, 1);
+	}
+
+	private static void runGc(DfsRepository db) throws IOException {
+		DfsGarbageCollector garbageCollector = new DfsGarbageCollector(db);
+		garbageCollector.pack(NullProgressMonitor.INSTANCE);
+		assertEquals(1, garbageCollector.getNewPacks().size());
+	}
+
+	private static CommitObjects last(List<CommitObjects> l) {
+		return l.get(l.size() - 1);
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxIndexTest.java
new file mode 100644
index 0000000..8574688
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxIndexTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.dfs.MidxTestUtils.writeMultipackIndex;
+import static org.eclipse.jgit.internal.storage.dfs.MidxTestUtils.writePackWithBlobs;
+import static org.eclipse.jgit.internal.storage.dfs.MidxTestUtils.writeSinglePackMidx;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
+import org.eclipse.jgit.lib.AbbreviatedObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class DfsPackFileMidxIndexTest {
+
+	private static final ObjectId NOT_IN_PACK = ObjectId
+			.fromString("3f306cb3fcd5116919fecad615524bd6e6ea4ba7");
+
+	private static final List<String> BLOBS = List.of("blob one", "blob two",
+			"blob three", "blob four", "blob five", "blob six");
+
+	@Parameters(name = "{0}")
+	public static Iterable<TestInput> data() throws IOException {
+		return List.of(setupOneMidxOverOnePack(), setupOneMidxOverNPacks(),
+				setupMidxChainEachOverNPacks(),
+				setupMidxChainSingleAndNPacks());
+	}
+
+	private record TestInput(String testDesc, DfsRepository db,
+			DfsPackFileMidx midx, ObjectId[] oids) {
+		@Override
+		public String toString() {
+			return testDesc;
+		}
+
+	}
+
+	private TestInput ti;
+
+	public DfsPackFileMidxIndexTest(TestInput ti) {
+		this.ti = ti;
+	}
+
+	@Test
+	public void getPackIndex_getObjectCount() {
+		try (DfsReader ctx = ti.db().getObjectDatabase().newReader()) {
+			assertEquals(ti.oids().length,
+					ti.midx().getPackIndex(ctx).getObjectCount());
+		}
+	}
+
+	@Test
+	public void getPackIndex_position_findPosition_getObjectId() {
+		try (DfsReader ctx = ti.db.getObjectDatabase().newReader()) {
+			PackIndex idx = ti.midx().getPackIndex(ctx);
+			for (int i = 0; i < ti.oids().length; i++) {
+				ObjectId expected = ti.oids()[i];
+				int position = idx.findPosition(expected);
+				assertNotEquals(-1, position);
+				ObjectId actual = idx.getObjectId(position);
+				assertEquals(expected, actual);
+			}
+			assertEquals(-1, idx.findPosition(NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void getPackIndex_offset_findOffset_getOffset() {
+		try (DfsReader ctx = ti.db.getObjectDatabase().newReader()) {
+			PackIndex idx = ti.midx().getPackIndex(ctx);
+			for (int i = 0; i < ti.oids().length; i++) {
+				ObjectId oid = ti.oids()[i];
+				int oidPosition = idx.findPosition(oid);
+
+				long offsetById = idx.findOffset(oid);
+				long offsetByPos = idx.getOffset(oidPosition);
+				assertEquals(offsetById, offsetByPos);
+			}
+			assertEquals(-1, idx.findOffset(NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void getPackIndex_objects_contains_hasObjects() {
+		try (DfsReader ctx = ti.db.getObjectDatabase().newReader()) {
+			PackIndex idx = ti.midx().getPackIndex(ctx);
+			for (int i = 0; i < ti.oids().length; i++) {
+				ObjectId oid = ti.oids()[i];
+				assertTrue(idx.contains(oid));
+				assertTrue(idx.hasObject(oid));
+			}
+			assertFalse(idx.contains(NOT_IN_PACK));
+			assertFalse(idx.hasObject(NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void getPackIndex_resolve() throws IOException {
+		try (DfsReader ctx = ti.db.getObjectDatabase().newReader()) {
+			PackIndex idx = ti.midx().getPackIndex(ctx);
+			Set<ObjectId> matches = new HashSet<>();
+			// Sha1 of "blob two" = ae4116e0972d85cd751b458fea94ca9eb84dd692
+			idx.resolve(matches, AbbreviatedObjectId.fromString("ae411"), 100);
+			assertEquals(1, matches.size());
+		}
+	}
+
+	@Test
+	public void getReverseIndex_findObject() throws IOException {
+		try (DfsReader ctx = ti.db.getObjectDatabase().newReader()) {
+			PackIndex idx = ti.midx().getPackIndex(ctx);
+			PackReverseIndex ridx = ti.midx().getReverseIdx(ctx);
+			for (ObjectId oid : ti.oids()) {
+				long offset = idx.findOffset(oid);
+				assertEquals(oid, ridx.findObject(offset));
+			}
+		}
+	}
+
+	@Test
+	public void getReverseIndex_findObjectByPosition() throws IOException {
+		try (DfsReader ctx = ti.db.getObjectDatabase().newReader()) {
+			PackIndex idx = ti.midx().getPackIndex(ctx);
+			ObjectId[] offsetOrder = ti.oids().clone();
+			Arrays.sort(offsetOrder, Comparator.comparingLong(idx::findOffset));
+
+			PackReverseIndex ridx = ti.midx().getReverseIdx(ctx);
+			for (int i = 0; i < offsetOrder.length; i++) {
+				assertEquals(offsetOrder[i], ridx.findObjectByPosition(i));
+			}
+		}
+	}
+
+	@Test
+	public void getReverseIndex_findPosition() throws IOException {
+		try (DfsReader ctx = ti.db.getObjectDatabase().newReader()) {
+			PackIndex idx = ti.midx().getPackIndex(ctx);
+			ObjectId[] offsetOrder = ti.oids().clone();
+			Arrays.sort(offsetOrder, Comparator.comparingLong(idx::findOffset));
+
+			PackReverseIndex ridx = ti.midx().getReverseIdx(ctx);
+			for (int i = 0; i < offsetOrder.length; i++) {
+				long offset = idx.findOffset(offsetOrder[i]);
+				int position = ridx.findPosition(offset);
+				assertEquals(i, position);
+			}
+		}
+	}
+	static TestInput setupOneMidxOverOnePack() throws IOException {
+		InMemoryRepository db = new InMemoryRepository(
+				new DfsRepositoryDescription("one_midx_one_pack"));
+		ObjectId[] objectIds = writePackWithBlobs(db,
+				BLOBS.toArray(String[]::new));
+		DfsPackFileMidx midx1 = writeSinglePackMidx(db);
+		return new TestInput("one midx - one pack", db, midx1, objectIds);
+	}
+
+	static TestInput setupOneMidxOverNPacks() throws IOException {
+		InMemoryRepository db = new InMemoryRepository(
+				new DfsRepositoryDescription("one_midx_n_packs"));
+
+		ObjectId[] objectIds = BLOBS.stream().map(s -> {
+			try {
+				return MidxTestUtils.writePackWithBlob(db, s);
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+		}).toArray(ObjectId[]::new);
+		DfsPackFileMidx midx1 = writeMultipackIndex(db,
+				db.getObjectDatabase().getPacks(), null);
+		return new TestInput("one midx - n packs", db, midx1, objectIds);
+	}
+
+	static TestInput setupMidxChainEachOverNPacks() throws IOException {
+		InMemoryRepository db = new InMemoryRepository(
+				new DfsRepositoryDescription("two_midx_3_packs_each"));
+
+		ObjectId[] objectIds = BLOBS.stream().map(s -> {
+			try {
+				return MidxTestUtils.writePackWithBlob(db, s);
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+		}).toArray(ObjectId[]::new);
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// If the amount of blobs (i.e. packs), adjust the ranges covered by
+		// midx.
+		assertEquals(6, BLOBS.size());
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 3, 6), null);
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 0, 3), midxBase);
+		return new TestInput("two midx - 3 packs each", db, midxTip, objectIds);
+	}
+
+	static TestInput setupMidxChainSingleAndNPacks() throws IOException {
+		InMemoryRepository db = new InMemoryRepository(
+				new DfsRepositoryDescription("two_midx_3_packs_each"));
+
+		ObjectId[] objectIds = BLOBS.stream().map(s -> {
+			try {
+				return MidxTestUtils.writePackWithBlob(db, s);
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+		}).toArray(ObjectId[]::new);
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// If the amount of blobs (i.e. packs), adjust the ranges covered by
+		// midx.
+		assertEquals(6, BLOBS.size());
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 0, 1), midxBase);
+		return new TestInput("two midx - 1 pack, 5 packs", db, midxTip,
+				objectIds);
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacksTest.java
similarity index 84%
rename from org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxTest.java
rename to org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacksTest.java
index 48611da..0f0e113 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacksTest.java
@@ -12,12 +12,15 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC;
 import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_DISTANT_COMMIT_SPAN;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_PACK_SECTION;
 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
 import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
 import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThrows;
@@ -27,22 +30,18 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.zip.Deflater;
 
 import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.internal.storage.dfs.DfsPackFileMidx.DfsPackOffset;
 import org.eclipse.jgit.internal.storage.dfs.DfsPackFileMidx.VOffsetCalculator;
+import org.eclipse.jgit.internal.storage.dfs.DfsPackFileMidxNPacks.VOffsetCalculatorNPacks;
 import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
-import org.eclipse.jgit.internal.storage.file.PackIndex;
 import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.PackOffset;
-import org.eclipse.jgit.internal.storage.midx.MultiPackIndexWriter;
 import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
-import org.eclipse.jgit.internal.storage.pack.PackExt;
 import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
 import org.eclipse.jgit.internal.storage.pack.PackWriter;
 import org.eclipse.jgit.junit.JGitTestUtil;
@@ -53,6 +52,7 @@
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.ObjectLoader;
 import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.revwalk.RevBlob;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevTree;
@@ -61,7 +61,9 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class DfsPackFileMidxTest {
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+
+public class DfsPackFileMidxNPacksTest {
 
 	private static final ObjectId NOT_IN_PACK = ObjectId
 			.fromString("3f306cb3fcd5116919fecad615524bd6e6ea4ba7");
@@ -99,11 +101,11 @@ public void midx_findIdxPosition_withBase() throws IOException {
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 
 		// Packs are in reverse insertion order
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 4, 6), null);
-		DfsPackFileMidx midxMid = writeMultipackIndex(
+		DfsPackFileMidx midxMid = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 2, 4), midxBase);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 2), midxMid);
 
 		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
@@ -118,6 +120,49 @@ public void midx_findIdxPosition_withBase() throws IOException {
 	}
 
 	@Test
+	public void midx_getObjectAt() throws IOException {
+		ObjectId o1 = writePackWithBlob("something".getBytes(UTF_8));
+		ObjectId o2 = writePackWithBlob("something else".getBytes(UTF_8));
+		ObjectId o3 = writePackWithBlob("and more".getBytes(UTF_8));
+		DfsPackFileMidx midx = writeMultipackIndex();
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertEquals(o1, midx.getObjectAt(ctx, 2));
+			assertEquals(o2, midx.getObjectAt(ctx, 0));
+			assertEquals(o3, midx.getObjectAt(ctx, 1));
+		}
+	}
+
+	@Test
+	public void midx_getObjectAt_withBase() throws IOException {
+		ObjectId o1 = writePackWithBlob("o1".getBytes(UTF_8));
+		ObjectId o2 = writePackWithBlob("o2".getBytes(UTF_8));
+		ObjectId o3 = writePackWithBlob("o3".getBytes(UTF_8));
+		ObjectId o4 = writePackWithBlob("o4".getBytes(UTF_8));
+		ObjectId o5 = writePackWithBlob("o5".getBytes(UTF_8));
+		ObjectId o6 = writePackWithBlob("o6".getBytes(UTF_8));
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 4, 6), null);
+		DfsPackFileMidx midxMid = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 2, 4), midxBase);
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 0, 2), midxMid);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertEquals(o1, midxTip.getObjectAt(ctx, 0));
+			assertEquals(o2, midxTip.getObjectAt(ctx, 1));
+			assertEquals(o3, midxTip.getObjectAt(ctx, 2));
+			assertEquals(o4, midxTip.getObjectAt(ctx, 3));
+			// In sha1 order
+			assertEquals(o5, midxTip.getObjectAt(ctx, 5));
+			assertEquals(o6, midxTip.getObjectAt(ctx, 4));
+		}
+	}
+
+	@Test
 	public void midx_hasObject() throws IOException {
 		ObjectId o1 = writePackWithRandomBlob(100);
 		ObjectId o2 = writePackWithRandomBlob(200);
@@ -144,9 +189,9 @@ public void midx_hasObject_withBase() throws IOException {
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 
 		// Packs are in reverse insertion order
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 6), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
@@ -208,9 +253,9 @@ public void midx_get_withBase() throws IOException {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		// Packs are in reverse insertion order
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 6), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
@@ -275,9 +320,9 @@ public void midx_load_withBase() throws IOException {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		// Packs are in reverse insertion order
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 6), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
@@ -315,7 +360,7 @@ public void midx_findOffset() throws IOException {
 
 		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
 			long posOne = midx.findOffset(ctx, o1);
-			DfsPackFileMidx.DfsPackOffset po = midx.getOffsetCalculator()
+			DfsPackOffset po = midx.getOffsetCalculator()
 					.decode(posOne);
 			assertEquals(12, po.getPackOffset());
 			assertEquals(packThreeSize + packTwoSize, po.getPackStart());
@@ -374,9 +419,9 @@ public void midx_resolve_withBase() throws Exception {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		// Packs are in reverse insertion order
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 6), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
@@ -444,9 +489,9 @@ public void midx_findAllFromPack_withBase() throws Exception {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		// Packs are in reverse insertion order (o6 -> o1)
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 6), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		List<ObjectToPack> otps = List.of(new DfsObjectToPack(o1, OBJ_BLOB),
@@ -522,9 +567,9 @@ public void midx_copyPackAsIs_withBase() throws Exception {
 				.map(size -> size - 12 - 20) // remove header + CRC
 				.sum();
 
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 6), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		try (DfsReader ctx = db.getObjectDatabase().newReader();
@@ -559,9 +604,9 @@ public void midx_copyAsIs_withBase() throws Exception {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		// Packs are in reverse insertion order
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 6), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		assertEquals(213, copyAsIs(midxTip, baseObject).length);
@@ -624,16 +669,15 @@ public void midx_getObjectType_withBase() throws Exception {
 		ObjectId commit = writePackWithCommit();
 		ObjectId blob = writePackWithRandomBlob(200);
 		writePackWithCommit();
-
 		writePackWithCommit();
 		writePackWithRandomBlob(300);
 		ObjectId newCommit = writePackWithCommit();
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		// Packs are in reverse insertion order
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 4, 7), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 4), midxBase);
 
 		try (RevWalk rw = new RevWalk(db);
@@ -685,14 +729,12 @@ public void midx_getObjectSize_byId_withBase() throws Exception {
 
 		writePackWithRandomBlob(300);
 		ObjectId blobTwo = writePackWithRandomBlob(100);
-		System.out.println(
-				"pack count: " + db.getObjectDatabase().getPacks().length);
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		// Packs are in reverse insertion order
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 5), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		try (RevWalk rw = new RevWalk(db);
@@ -742,9 +784,9 @@ public void midx_getObjectSize_byOffset_withBase() throws Exception {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		// Packs are in reverse insertion order
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 5), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		try (RevWalk rw = new RevWalk(db);
@@ -813,9 +855,9 @@ public void midx_fillRepresentation_withBase() throws Exception {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		assertEquals(6, packs.length);
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 6), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
@@ -825,7 +867,7 @@ public void midx_fillRepresentation_withBase() throws Exception {
 			assertEquals(midxTip.getPackDescription(),
 					rep.pack.getPackDescription());
 			assertEquals(midxTip.findOffset(ctx, commitInTip), rep.offset);
-			assertEquals(150, rep.length);
+			assertEquals(151, rep.length);
 
 			// Commit in base midx
 			rep = fillRepresentation(midxTip, commitInBase, OBJ_COMMIT);
@@ -844,7 +886,7 @@ public void midx_fillRepresentation_withBase() throws Exception {
 	}
 
 	@Test
-	public void midx_getBitmapIndex() throws Exception {
+	public void midx_getBitmapIndex_gc() throws Exception {
 		RevCommit c1 = writePackWithCommit();
 		RevCommit c2 = writePackWithCommit();
 		gcWithBitmaps();
@@ -863,6 +905,32 @@ public void midx_getBitmapIndex() throws Exception {
 	}
 
 	@Test
+	public void midx_getBitmapIndex_midx() throws Exception {
+		RevCommit c1 = writePackWithCommit();
+		RevCommit c2 = writePackWithCommit();
+		gcWithBitmaps();
+
+		RevCommit c3 = writePackWithCommit();
+		DfsPackFileMidx dfsPackFileMidx = writeMultipackIndexWithBitmaps();
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			ctx.getOptions().setUseMidxBitmaps(true);
+			PackBitmapIndex bitmapIndex = dfsPackFileMidx.getBitmapIndex(ctx);
+			assertNotNull(bitmapIndex);
+			assertEquals(3, bitmapIndex.getBitmapCount());
+			// Both commits have same tree and blob
+			assertEquals(5, bitmapIndex.getObjectCount());
+
+			assertNotNull(bitmapIndex.getBitmap(c3));
+			assertNotNull(bitmapIndex.getBitmap(c2));
+			assertNotNull(bitmapIndex.getBitmap(c1));
+
+			EWAHCompressedBitmap bitmapC3 = bitmapIndex.getBitmap(c3);
+			EWAHCompressedBitmap bitmapC2 = bitmapIndex.getBitmap(c2);
+			assertEquals(1, bitmapC3.andNot(bitmapC2).cardinality());
+		}
+	}
+
+	@Test
 	public void midx_getAllCoveredPacks() throws Exception {
 		writePackWithCommit();
 		writePackWithRandomBlob(300);
@@ -870,11 +938,12 @@ public void midx_getAllCoveredPacks() throws Exception {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		assertEquals(4, packs.length);
-		DfsPackFileMidx midx = writeMultipackIndex(packs, null);
+		DfsPackFileMidx midx = MidxTestUtils.writeMultipackIndex(db, packs,
+				null);
 
 		assertEquals(4, midx.getAllCoveredPacks().size());
 		List<DfsPackDescription> expected = Arrays.stream(packs)
-				.map(p -> p.getPackDescription()).toList();
+				.map(DfsPackFile::getPackDescription).toList();
 		List<DfsPackDescription> actual = midx.getAllCoveredPacks().stream()
 				.map(DfsPackFile::getPackDescription).toList();
 		assertEquals(expected, actual);
@@ -890,11 +959,11 @@ public void midx_getAllCoveredPacks_withBase() throws Exception {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		assertEquals(6, packs.length);
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 4, 6), null);
-		DfsPackFileMidx midxMiddle = writeMultipackIndex(
+		DfsPackFileMidx midxMiddle = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 2, 4), midxBase);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 2), midxMiddle);
 
 		assertEquals(6, midxTip.getAllCoveredPacks().size());
@@ -915,9 +984,9 @@ public void midx_getCoveredPacks_withBase_onlyTopMidx() throws Exception {
 
 		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
 		assertEquals(6, packs.length);
-		DfsPackFileMidx midxBase = writeMultipackIndex(
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 3, 6), null);
-		DfsPackFileMidx midxTip = writeMultipackIndex(
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
 				Arrays.copyOfRange(packs, 0, 3), midxBase);
 
 		assertEquals(3, midxTip.getCoveredPacks().size());
@@ -975,12 +1044,30 @@ public void packwriter_via_midx() throws Exception {
 	}
 
 	@Test
+	public void getChecksum() throws Exception {
+		MidxTestUtils.writePackWithBlob(db, "something");
+		MidxTestUtils.writePackWithBlob(db, "something else");
+		MidxTestUtils.writePackWithBlob(db, "and more");
+		DfsPackFileMidx midx = writeMultipackIndex();
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			byte[] checksum = midx.getChecksum(ctx);
+			assertNotNull(checksum);
+			assertEquals(20, checksum.length);
+			assertNotEquals('M', checksum[0]);
+			assertNotEquals('I', checksum[1]);
+			assertNotEquals('D', checksum[2]);
+			assertNotEquals('X', checksum[3]);
+		}
+	}
+
+	@Test
 	public void voffsetcalculator_encode() {
 		DfsPackFile one = createDfsPackFile(800);
 		DfsPackFile two = createDfsPackFile(1200);
 		DfsPackFile three = createDfsPackFile(900);
 
-		VOffsetCalculator calc = VOffsetCalculator
+		VOffsetCalculatorNPacks calc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { one, two, three }, null);
 
 		PackOffset po = PackOffset.create(0, 12);
@@ -997,11 +1084,11 @@ public void voffsetcalculator_decode() {
 		DfsPackFile two = createDfsPackFile(1200);
 		DfsPackFile three = createDfsPackFile(900);
 
-		VOffsetCalculator calc = VOffsetCalculator
+		VOffsetCalculator calc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { one, two, three }, null);
 
 		// In first pack
-		DfsPackFileMidx.DfsPackOffset decoded = calc.decode(130);
+		DfsPackOffset decoded = calc.decode(130);
 		assertEquals(one.getPackDescription(),
 				decoded.getPack().getPackDescription());
 		assertEquals(130, decoded.getPackOffset());
@@ -1028,7 +1115,7 @@ public void voffsetcalculator_notFound() {
 		DfsPackFile two = createDfsPackFile(1200);
 		DfsPackFile three = createDfsPackFile(900);
 
-		VOffsetCalculator calc = VOffsetCalculator
+		VOffsetCalculatorNPacks calc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { one, two, three }, null);
 
 		assertEquals(-1, calc.encode(null));
@@ -1045,7 +1132,7 @@ public void voffsetcalculator_maxOffset() {
 				+ two.getPackDescription().getFileSize(PACK)
 				+ three.getPackDescription().getFileSize(PACK);
 
-		VOffsetCalculator calc = VOffsetCalculator
+		VOffsetCalculator calc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { one, two, three }, null);
 
 		assertEquals(totalSize, calc.getMaxOffset());
@@ -1057,14 +1144,14 @@ public void voffsetcalculator_withBase_encode() {
 		DfsPackFile two = createDfsPackFile(1200);
 		DfsPackFile three = createDfsPackFile(900);
 
-		VOffsetCalculator baseCalc = VOffsetCalculator
+		VOffsetCalculator baseCalc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { one, two, three }, null);
 
 		DfsPackFile four = createDfsPackFile(900);
 		DfsPackFile five = createDfsPackFile(1300);
 		DfsPackFile six = createDfsPackFile(1000);
 
-		VOffsetCalculator calc = VOffsetCalculator
+		VOffsetCalculatorNPacks calc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { four, five, six }, baseCalc);
 
 		// These packIds are now from the second top midx
@@ -1082,18 +1169,18 @@ public void voffsetcalculator_withBase_decode() {
 		DfsPackFile one = createDfsPackFile(800);
 		DfsPackFile two = createDfsPackFile(1200);
 		DfsPackFile three = createDfsPackFile(900);
-		VOffsetCalculator baseCalc = VOffsetCalculator
+		VOffsetCalculator baseCalc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { one, two, three }, null);
 
 		DfsPackFile four = createDfsPackFile(900);
 		DfsPackFile five = createDfsPackFile(1300);
 		DfsPackFile six = createDfsPackFile(1000);
 
-		VOffsetCalculator calc = VOffsetCalculator
+		VOffsetCalculator calc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { four, five, six }, baseCalc);
 
 		// In pack 1
-		DfsPackFileMidx.DfsPackOffset decoded = calc.decode(130);
+		DfsPackOffset decoded = calc.decode(130);
 		assertEquals(one.getPackDescription(),
 				decoded.getPack().getPackDescription());
 		assertEquals(130, decoded.getPackOffset());
@@ -1128,14 +1215,14 @@ public void voffsetcalculator_withBase_maxOffset() {
 		DfsPackFile two = createDfsPackFile(1200);
 		DfsPackFile three = createDfsPackFile(900);
 
-		VOffsetCalculator baseCalc = VOffsetCalculator
+		VOffsetCalculator baseCalc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { one, two, three }, null);
 
 		DfsPackFile four = createDfsPackFile(900);
 		DfsPackFile five = createDfsPackFile(1300);
 		DfsPackFile six = createDfsPackFile(1000);
 
-		VOffsetCalculator calc = VOffsetCalculator
+		VOffsetCalculator calc = VOffsetCalculatorNPacks
 				.fromPacks(new DfsPackFile[] { four, five, six }, baseCalc);
 
 		int expectedMaxOffset = 800 + 1200 + 900 + 900 + 1300 + 1000;
@@ -1152,7 +1239,21 @@ private static DfsPackFile createDfsPackFile(int size) {
 	}
 
 	private DfsPackFileMidx writeMultipackIndex() throws IOException {
-		return writeMultipackIndex(db.getObjectDatabase().getPacks(), null);
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		return MidxTestUtils.writeMultipackIndex(db, packs, null);
+	}
+
+	private DfsPackFileMidx writeMultipackIndexWithBitmaps()
+			throws IOException {
+		enableMidxBitmaps(db);
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		return MidxTestUtils.writeMultipackIndex(db, packs,
+				null);
+	}
+
+	private static void enableMidxBitmaps(DfsRepository repo) {
+		repo.getConfig().setInt(CONFIG_PACK_SECTION, null,
+				CONFIG_KEY_BITMAP_DISTANT_COMMIT_SPAN, 1);
 	}
 
 	private void gcWithBitmaps() throws IOException {
@@ -1160,39 +1261,15 @@ private void gcWithBitmaps() throws IOException {
 		garbageCollector.pack(NullProgressMonitor.INSTANCE);
 	}
 
-	private DfsPackFileMidx writeMultipackIndex(DfsPackFile[] packs,
-			DfsPackFileMidx base) throws IOException {
-		LinkedHashMap<String, PackIndex> forMidx = new LinkedHashMap<>(
-				packs.length);
-		Map<String, DfsPackDescription> descByName = new HashMap<>(
-				packs.length);
-		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
-			for (DfsPackFile pack : packs) {
-				forMidx.put(pack.getPackDescription().getPackName(),
-						pack.getPackIndex(ctx));
-				descByName.put(pack.getPackDescription().getPackName(),
-						pack.getPackDescription());
-			}
-		}
-		MultiPackIndexWriter w = new MultiPackIndexWriter();
-		DfsPackDescription desc = db.getObjectDatabase().newPack(GC);
-		try (DfsOutputStream out = db.getObjectDatabase().writeFile(desc,
-				PackExt.MULTI_PACK_INDEX)) {
-			MultiPackIndexWriter.Result midxStats = w
-					.write(NullProgressMonitor.INSTANCE, out, forMidx);
-			desc.setCoveredPacks(midxStats.packNames().stream()
-					.map(descByName::get).toList());
-			desc.addFileExt(PackExt.MULTI_PACK_INDEX);
-		}
-		db.getObjectDatabase().commitPack(List.of(desc), null);
-		return DfsPackFileMidx.create(DfsBlockCache.getInstance(), desc,
-				Arrays.asList(packs), base);
-	}
-
 	private RevCommit writePackWithCommit() throws Exception {
 		try (TestRepository<InMemoryRepository> repository = new TestRepository<>(
 				db)) {
-			return repository.branch("/refs/heads/main").commit()
+			Ref ref = repository.getRepository().getRefDatabase()
+					.findRef("refs/heads/main");
+			RevWalk rw = repository.getRevWalk();
+			RevCommit parent = ref != null ? rw.parseCommit(ref.getObjectId())
+					: null;
+			return repository.branch("refs/heads/main").commit().parent(parent)
 					.add("blob1", "blob1").create();
 		}
 	}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingleTest.java
new file mode 100644
index 0000000..aa2ddca
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingleTest.java
@@ -0,0 +1,1246 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC;
+import static org.eclipse.jgit.internal.storage.dfs.MidxTestUtils.writePackWithBlobs;
+import static org.eclipse.jgit.internal.storage.dfs.MidxTestUtils.writeSinglePackMidx;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
+import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.internal.storage.dfs.DfsPackFileMidx.DfsPackOffset;
+import org.eclipse.jgit.internal.storage.dfs.DfsPackFileMidxSingle.SingleVOffsetCalculator;
+import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.PackOffset;
+import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
+import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
+import org.eclipse.jgit.internal.storage.pack.PackWriter;
+import org.eclipse.jgit.junit.JGitTestUtil;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.junit.TestRng;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.pack.PackConfig;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DfsPackFileMidxSingleTest {
+
+	private static final ObjectId NOT_IN_PACK = ObjectId
+			.fromString("3f306cb3fcd5116919fecad615524bd6e6ea4ba7");
+
+	InMemoryRepository db;
+
+	@Before
+	public void setUp() {
+		db = new InMemoryRepository(new DfsRepositoryDescription("test"));
+	}
+
+	@Test
+	public void findIdxPosition() throws IOException {
+		ObjectId[] oids = writePackWithBlobs(db, "something",
+				"something else", "and more");
+		// oids = [a4..., 33..., 64...]
+		DfsPackFileMidx midx = writeSinglePackMidx(db);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertEquals(2, midx.findIdxPosition(ctx, oids[0]));
+			assertEquals(0, midx.findIdxPosition(ctx, oids[1]));
+			assertEquals(1, midx.findIdxPosition(ctx, oids[2]));
+			assertEquals(-1, midx.findIdxPosition(ctx, NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void findIdxPosition_withBase() throws IOException {
+		ObjectId o1 = MidxTestUtils.writePackWithBlob(db, "o1"); // 38
+		ObjectId o2 = MidxTestUtils.writePackWithBlob(db, "o2"); // 4a
+		ObjectId o3 = MidxTestUtils.writePackWithBlob(db, "o3"); // 45
+		ObjectId o4 = MidxTestUtils.writePackWithBlob(db, "o4"); // 4b
+		ObjectId o5 = MidxTestUtils.writePackWithBlob(db, "o5"); // 68
+		ObjectId o6 = MidxTestUtils.writePackWithBlob(db, "o6"); // 4d
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 3, 6), null);
+		DfsPackFileMidx midxMid = writeSinglePackMidx(db,
+				packs[2], midxBase);
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 0, 2), midxMid);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertEquals(0, midxTip.findIdxPosition(ctx, o1));
+			assertEquals(1, midxTip.findIdxPosition(ctx, o3));
+			assertEquals(2, midxTip.findIdxPosition(ctx, o2));
+			assertEquals(3, midxTip.findIdxPosition(ctx, o4));
+			assertEquals(4, midxTip.findIdxPosition(ctx, o6));
+			assertEquals(5, midxTip.findIdxPosition(ctx, o5));
+		}
+	}
+
+	@Test
+	public void getObjectAt() throws IOException {
+		ObjectId[] oids = writePackWithBlobs(db, "something",
+				"something else", "and more");
+		// oids = [a4..., 33..., 64...]
+		DfsPackFileMidx midx = writeSinglePackMidx(db);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertEquals(oids[0], midx.getObjectAt(ctx, 2));
+			assertEquals(oids[1], midx.getObjectAt(ctx, 0));
+			assertEquals(oids[2], midx.getObjectAt(ctx, 1));
+		}
+	}
+
+	@Test
+	public void getObjectAt_withBase() throws IOException {
+		ObjectId o1 = MidxTestUtils.writePackWithBlob(db, "o1");
+		ObjectId o2 = MidxTestUtils.writePackWithBlob(db, "o2");
+		ObjectId o3 = MidxTestUtils.writePackWithBlob(db, "o3");
+		ObjectId o4 = MidxTestUtils.writePackWithBlob(db, "o4");
+		ObjectId o5 = MidxTestUtils.writePackWithBlob(db, "o5");
+		ObjectId o6 = MidxTestUtils.writePackWithBlob(db, "o6");
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 3, 6), null);
+		DfsPackFileMidx midxMid = writeSinglePackMidx(db,
+				packs[2], midxBase);
+		DfsPackFileMidx midxTip = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 0, 2), midxMid);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertEquals(o1, midxTip.getObjectAt(ctx, 0));
+			assertEquals(o3, midxTip.getObjectAt(ctx, 1));
+			assertEquals(o2, midxTip.getObjectAt(ctx, 2));
+			assertEquals(o4, midxTip.getObjectAt(ctx, 3));
+			// In sha1 order
+			assertEquals(o6, midxTip.getObjectAt(ctx, 4));
+			assertEquals(o5, midxTip.getObjectAt(ctx, 5));
+		}
+	}
+
+	@Test
+	public void hasObject() throws IOException {
+		ObjectId[] oids = writePackWithBlobs(db, "aaaa", "bbbb",
+				"cccc");
+		DfsPackFile midx = writeSinglePackMidx(db);
+
+		// DfsPackFile midx = readDfsPackFileMidx();
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertTrue(midx.hasObject(ctx, oids[0]));
+			assertTrue(midx.hasObject(ctx, oids[1]));
+			assertTrue(midx.hasObject(ctx, oids[2]));
+			assertFalse(midx.hasObject(ctx, NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void hasObject_withBase() throws IOException {
+		ObjectId o1 = writePackWithRandomBlob(100);
+		ObjectId o2 = writePackWithRandomBlob(200);
+		ObjectId o3 = writePackWithRandomBlob(150);
+		ObjectId o4 = writePackWithRandomBlob(400);
+		ObjectId o5 = writePackWithRandomBlob(500);
+		ObjectId o6 = writePackWithRandomBlob(600);
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertTrue(midxBase.hasObject(ctx, o1));
+			assertTrue(midxBase.hasObject(ctx, o2));
+			assertTrue(midxBase.hasObject(ctx, o3));
+			assertTrue(midxBase.hasObject(ctx, o4));
+			assertTrue(midxBase.hasObject(ctx, o5));
+			// This is not in base
+			assertFalse(midxBase.hasObject(ctx, o6));
+
+			// Top midx has all objects
+			assertTrue(midxTip.hasObject(ctx, o1));
+			assertTrue(midxTip.hasObject(ctx, o2));
+			assertTrue(midxTip.hasObject(ctx, o3));
+			assertTrue(midxTip.hasObject(ctx, o4));
+			assertTrue(midxTip.hasObject(ctx, o5));
+			assertTrue(midxTip.hasObject(ctx, o6));
+
+			assertFalse(midxTip.hasObject(ctx, NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void get() throws IOException {
+		byte[] contentOne = "ONE".getBytes(UTF_8);
+		byte[] contentTwo = "TWO".getBytes(UTF_8);
+		byte[] contentThree = "THREE".getBytes(UTF_8);
+
+		ObjectId[] oids = writePackWithBlobs(db, "ONE", "TWO",
+				"THREE");
+		DfsPackFile midx = writeSinglePackMidx(db);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			ObjectLoader objectLoader = midx.get(ctx, oids[0]);
+			assertArrayEquals(contentOne, safeGetBytes(objectLoader));
+			objectLoader = midx.get(ctx, oids[1]);
+			assertArrayEquals(contentTwo, safeGetBytes(objectLoader));
+			objectLoader = midx.get(ctx, oids[2]);
+			assertArrayEquals(contentThree, safeGetBytes(objectLoader));
+			assertNull(midx.get(ctx, NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void get_withBase() throws IOException {
+		byte[] contentOne = "ONE".getBytes(UTF_8);
+		byte[] contentTwo = "TWO".getBytes(UTF_8);
+		byte[] contentThree = "THREE".getBytes(UTF_8);
+		byte[] contentFour = "FOUR".getBytes(UTF_8);
+		byte[] contentFive = "FIVE".getBytes(UTF_8);
+		byte[] contentSix = "SIX".getBytes(UTF_8);
+
+		ObjectId o1 = writePackWithBlob(contentOne);
+		ObjectId o2 = writePackWithBlob(contentTwo);
+		ObjectId o3 = writePackWithBlob(contentThree);
+		ObjectId o4 = writePackWithBlob(contentFour);
+		ObjectId o5 = writePackWithBlob(contentFive);
+		ObjectId o6 = writePackWithBlob(contentSix);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			ObjectLoader objectLoader = midxTip.get(ctx, o1);
+			assertArrayEquals(contentOne, safeGetBytes(objectLoader));
+			objectLoader = midxTip.get(ctx, o2);
+			assertArrayEquals(contentTwo, safeGetBytes(objectLoader));
+			objectLoader = midxTip.get(ctx, o3);
+			assertArrayEquals(contentThree, safeGetBytes(objectLoader));
+			objectLoader = midxTip.get(ctx, o4);
+			assertArrayEquals(contentFour, safeGetBytes(objectLoader));
+			objectLoader = midxTip.get(ctx, o5);
+			assertArrayEquals(contentFive, safeGetBytes(objectLoader));
+			objectLoader = midxTip.get(ctx, o6);
+			assertArrayEquals(contentSix, safeGetBytes(objectLoader));
+
+			assertNull(midxTip.get(ctx, NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void load() throws IOException {
+		byte[] contentOne = "ONE".getBytes(UTF_8);
+		byte[] contentTwo = "TWO".getBytes(UTF_8);
+		byte[] contentThree = "THREE".getBytes(UTF_8);
+
+		ObjectId[] oids = writePackWithBlobs(db, "ONE", "TWO",
+				"THREE");
+		DfsPackFile midx = writeSinglePackMidx(db);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			ObjectLoader objectLoader = midx.load(ctx,
+					midx.findOffset(ctx, oids[0]));
+			assertArrayEquals(contentOne, safeGetBytes(objectLoader));
+			objectLoader = midx.load(ctx, midx.findOffset(ctx, oids[1]));
+			assertArrayEquals(contentTwo, safeGetBytes(objectLoader));
+			objectLoader = midx.load(ctx, midx.findOffset(ctx, oids[2]));
+			assertArrayEquals(contentThree, safeGetBytes(objectLoader));
+
+			assertThrows(IllegalArgumentException.class,
+					() -> midx.load(ctx, 500));
+			assertNull(midx.load(ctx, -1));
+		}
+	}
+
+	@Test
+	public void load_withBase() throws IOException {
+		byte[] contentOne = "ONE".getBytes(UTF_8);
+		byte[] contentTwo = "TWO".getBytes(UTF_8);
+		byte[] contentThree = "THREE".getBytes(UTF_8);
+		byte[] contentFour = "FOUR".getBytes(UTF_8);
+		byte[] contentFive = "FIVE".getBytes(UTF_8);
+		byte[] contentSix = "SIX".getBytes(UTF_8);
+
+		ObjectId o1 = writePackWithBlob(contentOne);
+		ObjectId o2 = writePackWithBlob(contentTwo);
+		ObjectId o3 = writePackWithBlob(contentThree);
+		ObjectId o4 = writePackWithBlob(contentFour);
+		ObjectId o5 = writePackWithBlob(contentFive);
+		ObjectId o6 = writePackWithBlob(contentSix);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			ObjectLoader objectLoader = midxTip.load(ctx,
+					midxTip.findOffset(ctx, o1));
+			assertArrayEquals(contentOne, safeGetBytes(objectLoader));
+			objectLoader = midxTip.load(ctx, midxTip.findOffset(ctx, o2));
+			assertArrayEquals(contentTwo, safeGetBytes(objectLoader));
+			objectLoader = midxTip.load(ctx, midxTip.findOffset(ctx, o3));
+			assertArrayEquals(contentThree, safeGetBytes(objectLoader));
+			objectLoader = midxTip.load(ctx, midxTip.findOffset(ctx, o4));
+			assertArrayEquals(contentFour, safeGetBytes(objectLoader));
+			objectLoader = midxTip.load(ctx, midxTip.findOffset(ctx, o5));
+			assertArrayEquals(contentFive, safeGetBytes(objectLoader));
+			objectLoader = midxTip.load(ctx, midxTip.findOffset(ctx, o6));
+			assertArrayEquals(contentSix, safeGetBytes(objectLoader));
+
+			assertNull(midxTip.load(ctx, midxTip.findOffset(ctx, NOT_IN_PACK)));
+		}
+	}
+
+	@Test
+	public void findOffset() throws IOException {
+		ObjectId[] oids = writePackWithBlobs(db, "ONE", "TWO",
+				"THREE");
+		DfsPackFileMidx midx = writeSinglePackMidx(db);
+		DfsPackFile realPack = findPack(oids[0]);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertEquals(realPack.findOffset(ctx, oids[0]),
+					midx.findOffset(ctx, oids[0]));
+			assertEquals(realPack.findOffset(ctx, oids[1]),
+					midx.findOffset(ctx, oids[1]));
+			assertEquals(realPack.findOffset(ctx, oids[2]),
+					midx.findOffset(ctx, oids[2]));
+
+			long posNon = midx.findOffset(ctx, NOT_IN_PACK);
+			assertEquals(-1, posNon);
+		}
+	}
+
+	@Test
+	public void findOffset_withBase() throws IOException {
+		byte[] contentOne = "ONE".getBytes(UTF_8);
+		byte[] contentTwo = "TWO".getBytes(UTF_8);
+		byte[] contentThree = "THREE".getBytes(UTF_8);
+		byte[] contentFour = "FOUR".getBytes(UTF_8);
+		byte[] contentFive = "FIVE".getBytes(UTF_8);
+		byte[] contentSix = "SIX".getBytes(UTF_8);
+
+		ObjectId o1 = writePackWithBlob(contentOne);
+		ObjectId o2 = writePackWithBlob(contentTwo);
+		ObjectId o3 = writePackWithBlob(contentThree);
+		ObjectId o4 = writePackWithBlob(contentFour);
+		ObjectId o5 = writePackWithBlob(contentFive);
+		ObjectId o6 = writePackWithBlob(contentSix);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+		DfsPackFile coveredPack = findPack(o6);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertEquals(coveredPack.findOffset(ctx, o6) + midxBase.length,
+					midxTip.findOffset(ctx, o6));
+			assertEquals(findPack(o5).findOffset(ctx, o5),
+					midxTip.findOffset(ctx, o5));
+
+			// WE just check the offsets are in incremental order.
+			// midx orders first by pack, and we passed the most recent first,
+			// so in midx-offset order, o6 > o1 > o2 > o3 > o4 > o5
+			assertTrue(
+					midxTip.findOffset(ctx, o4) > midxTip.findOffset(ctx, o5));
+			assertTrue(
+					midxTip.findOffset(ctx, o3) > midxTip.findOffset(ctx, o4));
+
+			assertTrue(
+					midxTip.findOffset(ctx, o2) > midxTip.findOffset(ctx, o3));
+
+			assertTrue(
+					midxTip.findOffset(ctx, o1) > midxTip.findOffset(ctx, o2));
+			assertTrue(
+					midxTip.findOffset(ctx, o6) > midxTip.findOffset(ctx, o1));
+
+			long posNon = midxTip.findOffset(ctx, NOT_IN_PACK);
+			assertEquals(-1, posNon);
+		}
+	}
+
+	@Test
+	public void resolve() throws Exception {
+		// These oids do NOT have same prefix
+		ObjectId[] oids = writePackWithBlobs(db, "AAAAAA",
+				"BBBBBB", "CCCCCCC");
+		DfsPackFile midx = writeSinglePackMidx(db);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			Set<ObjectId> matches = new HashSet<>();
+			midx.resolve(ctx, matches, oids[0].abbreviate(6), 100);
+			assertEquals(1, matches.size());
+
+			matches.clear();
+			midx.resolve(ctx, matches, oids[1].abbreviate(6), 100);
+			assertEquals(1, matches.size());
+
+			matches = new HashSet<>();
+			midx.resolve(ctx, matches, NOT_IN_PACK.abbreviate(8), 100);
+			assertEquals(0, matches.size());
+		}
+	}
+
+	@Test
+	public void resolve_withBase() throws Exception {
+		ObjectId o1 = writePackWithRandomBlob(100);
+		ObjectId o2 = writePackWithRandomBlob(200);
+		writePackWithRandomBlob(150);
+		ObjectId o4 = writePackWithRandomBlob(400);
+		writePackWithRandomBlob(500);
+		writePackWithRandomBlob(600);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			Set<ObjectId> matches = new HashSet<>();
+			// Test with an ID that exists in the base
+			assertTrue(midxTip.hasObject(ctx, o1));
+			midxTip.resolve(ctx, matches, o1.abbreviate(6), 100);
+			assertEquals(1, matches.size());
+			assertTrue(matches.contains(o1));
+
+			matches.clear();
+			// Test with an ID that exists in the tip
+			midxTip.resolve(ctx, matches, o4.abbreviate(6), 100);
+			assertTrue(matches.contains(o4));
+			assertEquals(1, matches.size());
+
+			matches.clear();
+			midxTip.resolve(ctx, matches, o2.abbreviate(6), 1);
+			assertTrue(matches.contains(o2));
+			assertEquals(1, matches.size());
+
+			matches.clear();
+			midxTip.resolve(ctx, matches, NOT_IN_PACK.abbreviate(8), 100);
+			assertEquals(0, matches.size());
+		}
+	}
+
+	@Test
+	public void findAllFromPack() throws Exception {
+		ObjectId[] objectIds = writePackWithBlobs(db, "aaaaaaaa",
+				"bbbbbbbbb", "cccccccccc");
+		DfsPackFile midx = writeMultipackIndex();
+
+		List<ObjectToPack> otps = List.of(
+				new DfsObjectToPack(objectIds[0], OBJ_BLOB),
+				new DfsObjectToPack(objectIds[1], OBJ_BLOB),
+				new DfsObjectToPack(objectIds[2], OBJ_BLOB),
+				new DfsObjectToPack(NOT_IN_PACK, OBJ_BLOB));
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			List<DfsObjectToPack> allFromPack = midx.findAllFromPack(ctx, otps,
+					true);
+			assertEquals(3, allFromPack.size());
+
+			DfsObjectToPack oneToPack = allFromPack.get(0);
+			assertEquals(midx.findOffset(ctx, objectIds[0]),
+					oneToPack.getOffset());
+
+			DfsObjectToPack twoToPack = allFromPack.get(1);
+			assertEquals(midx.findOffset(ctx, objectIds[1]),
+					twoToPack.getOffset());
+
+			DfsObjectToPack threeToPack = allFromPack.get(2);
+			assertEquals(midx.findOffset(ctx, objectIds[2]),
+					threeToPack.getOffset());
+		}
+	}
+
+	@Test
+	public void findAllFromPack_withBase() throws Exception {
+		ObjectId o1 = writePackWithRandomBlob(100);
+		ObjectId o2 = writePackWithRandomBlob(200);
+		ObjectId o3 = writePackWithRandomBlob(150);
+		ObjectId o4 = writePackWithRandomBlob(400);
+		ObjectId o5 = writePackWithRandomBlob(500);
+		ObjectId o6 = writePackWithRandomBlob(600);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// Packs are in reverse insertion order (o6 -> o1)
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		List<ObjectToPack> otps = List.of(new DfsObjectToPack(o1, OBJ_BLOB),
+				new DfsObjectToPack(o4, OBJ_BLOB),
+				new DfsObjectToPack(o2, OBJ_BLOB),
+				new DfsObjectToPack(o5, OBJ_BLOB),
+				new DfsObjectToPack(NOT_IN_PACK, OBJ_BLOB),
+				new DfsObjectToPack(o3, OBJ_BLOB),
+				new DfsObjectToPack(o6, OBJ_BLOB));
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			List<DfsObjectToPack> allFromPack = midxTip.findAllFromPack(ctx,
+					otps, true);
+			assertEquals(6, allFromPack.size());
+
+			// Objects are in midx-offset order which is:
+			// base(o5< o4 < o3 < o2 < o1) -> tip (06)
+			DfsObjectToPack oneToPack = allFromPack.get(0);
+			assertEquals(midxTip.findOffset(ctx, o5), oneToPack.getOffset());
+
+			DfsObjectToPack twoToPack = allFromPack.get(1);
+			assertEquals(midxTip.findOffset(ctx, o4), twoToPack.getOffset());
+
+			DfsObjectToPack threeToPack = allFromPack.get(2);
+			assertEquals(midxTip.findOffset(ctx, o3), threeToPack.getOffset());
+
+			DfsObjectToPack fourToPack = allFromPack.get(3);
+			assertEquals(midxTip.findOffset(ctx, o2), fourToPack.getOffset());
+
+			DfsObjectToPack fiveToPack = allFromPack.get(4);
+			assertEquals(midxTip.findOffset(ctx, o1), fiveToPack.getOffset());
+
+			DfsObjectToPack sixToPack = allFromPack.get(5);
+			assertEquals(midxTip.findOffset(ctx, o6), sixToPack.getOffset());
+		}
+	}
+
+	@Test
+	public void copyPackAsIs() throws Exception {
+		ObjectId[] objectIds = writePackWithBlobs(db, "aaaaaa",
+				"bbbbbbbb", "ccccccccc");
+		DfsPackFileMidx midx = writeSinglePackMidx(db);
+		DfsPackFile pack = findPack(objectIds[0]);
+		assertArrayEquals(copyPackAsIs(pack), copyPackAsIs(midx));
+	}
+
+	@Test
+	public void copyPackAsIs_withBase() throws Exception {
+		writePackWithRandomBlob(100);
+		writePackWithRandomBlob(200);
+		writePackWithRandomBlob(150);
+		writePackWithRandomBlob(400);
+		writePackWithRandomBlob(500);
+		writePackWithRandomBlob(600);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		long expectedPackSize = Arrays.stream(packs)
+				.mapToLong(pack -> pack.getPackDescription().getFileSize(PACK))
+				.map(size -> size - 12 - 20) // remove header + CRC
+				.sum();
+
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader();
+				PackWriter pw = new PackWriter(new PackConfig(), ctx);
+				ByteArrayOutputStream os = new ByteArrayOutputStream();
+				PackOutputStream out = new PackOutputStream(
+						NullProgressMonitor.INSTANCE, os, pw)) {
+			midxTip.copyPackAsIs(out, ctx);
+			out.flush();
+			assertEquals(expectedPackSize, os.size());
+		}
+	}
+
+	private byte[] copyPackAsIs(DfsPackFile source) throws IOException {
+		try (DfsReader ctx = db.getObjectDatabase().newReader();
+				PackWriter pw = new PackWriter(new PackConfig(), ctx)) {
+			ByteArrayOutputStream os = new ByteArrayOutputStream();
+			PackOutputStream out = new PackOutputStream(
+					NullProgressMonitor.INSTANCE, os, pw);
+			source.copyPackAsIs(out, ctx);
+			out.flush();
+			return os.toByteArray();
+		}
+	}
+
+	@Test
+	public void copyAsIs() throws Exception {
+		ObjectId blob = writePackWithRandomBlob(200);
+		DfsPackFileMidx midx = writeSinglePackMidx(db);
+
+		assertEquals(213, copyAsIs(midx, blob).length);
+	}
+
+	@Test
+	public void copyAsIs_withBase() throws Exception {
+		writePackWithRandomBlob(100);
+		ObjectId baseObject = writePackWithRandomBlob(200);
+		writePackWithRandomBlob(150);
+		writePackWithRandomBlob(400);
+		MidxTestUtils.writePackWithBlob(db, "woohooABCxxxxx11111");
+		ObjectId tipObject = writePackWithRandomBlob(600);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		assertEquals(213, copyAsIs(midxTip, baseObject).length);
+
+		DfsPackFile pack = findPack(tipObject);
+		byte[] fromPack = copyAsIs(pack, tipObject);
+		// Reparsing produces the same id
+		byte[] fromMidx = copyAsIs(midxTip, tipObject);
+		assertArrayEquals(fromPack, fromMidx);
+	}
+
+	private byte[] copyAsIs(DfsPackFile pack, ObjectId oid) throws Exception {
+		try (DfsReader ctx = db.getObjectDatabase().newReader();
+				PackWriter pw = new PackWriter(new PackConfig(), ctx);
+				ByteArrayOutputStream os = new ByteArrayOutputStream();
+				PackOutputStream out = new PackOutputStream(
+						NullProgressMonitor.INSTANCE, os, pw)) {
+			// Object in the base
+			ObjectToPack otp = new DfsObjectToPack(oid, OBJ_BLOB);
+			DfsObjectToPack inPack = pack
+					.findAllFromPack(ctx, List.of(otp), false).get(0);
+			DfsObjectRepresentation r = new DfsObjectRepresentation(pack);
+			pack.fillRepresentation(r, inPack.getOffset(), ctx);
+			inPack.select(r);
+			pack.copyAsIs(out, inPack, false, ctx);
+			out.flush();
+			return os.toByteArray();
+		}
+	}
+
+	@Test
+	public void getDeltaHeader() {
+		// TODO(ifrade): Implement
+	}
+
+	@Test
+	public void getObjectType() throws Exception {
+		CommitObjects commitObjects = writePackWithOneCommit();
+		gcWithBitmaps();
+		DfsPackFile midx = writeSinglePackMidx(db);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			long commitPos = midx.findOffset(ctx, commitObjects.commit());
+			assertEquals(OBJ_COMMIT, midx.getObjectType(ctx, commitPos));
+
+			long treePos = midx.findOffset(ctx, commitObjects.tree());
+			assertEquals(OBJ_TREE, midx.getObjectType(ctx, treePos));
+
+			long blobPos = midx.findOffset(ctx, commitObjects.blob());
+			assertEquals(OBJ_BLOB, midx.getObjectType(ctx, blobPos));
+
+			assertThrows(IllegalArgumentException.class,
+					() -> midx.getObjectType(ctx, 12000));
+		}
+	}
+
+	@Test
+	public void getObjectType_withBase() throws Exception {
+		// This first commit creates two packs
+		CommitObjects objs = writePackWithOneCommit();
+		writePackWithCommit();
+
+		writePackWithCommit();
+		writePackWithRandomBlob(300);
+		ObjectId newCommit = writePackWithCommit();
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 7), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			long commitPos = midxTip.findOffset(ctx, objs.commit());
+			assertEquals(OBJ_COMMIT, midxTip.getObjectType(ctx, commitPos));
+
+			long treePos = midxTip.findOffset(ctx, objs.tree());
+			assertEquals(OBJ_TREE, midxTip.getObjectType(ctx, treePos));
+
+			long blobPos = midxTip.findOffset(ctx, objs.blob());
+			assertEquals(OBJ_BLOB, midxTip.getObjectType(ctx, blobPos));
+
+			long commitPosTip = midxTip.findOffset(ctx, newCommit);
+			assertEquals(OBJ_COMMIT, midxTip.getObjectType(ctx, commitPosTip));
+
+			assertThrows(IllegalArgumentException.class,
+					() -> midxTip.getObjectType(ctx, 12000));
+		}
+	}
+
+	@Test
+	public void getObjectSize_byId() throws Exception {
+		CommitObjects objs = writePackWithOneCommit();
+		gcWithBitmaps();
+		DfsPackFile midx = writeSinglePackMidx(db);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertEquals(168, midx.getObjectSize(ctx, objs.commit()));
+			assertEquals(33, midx.getObjectSize(ctx, objs.tree()));
+			assertEquals(5, midx.getObjectSize(ctx, objs.blob()));
+
+			assertEquals(-1, midx.getObjectSize(ctx, NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void getObjectSize_byId_withBase() throws Exception {
+		ObjectId commit = writePackWithCommit();
+		ObjectId blob = writePackWithRandomBlob(200);
+
+		writePackWithRandomBlob(300);
+		ObjectId blobTwo = writePackWithRandomBlob(100);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 5), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		try (RevWalk rw = new RevWalk(db);
+				DfsReader ctx = db.getObjectDatabase().newReader()) {
+			RevCommit aCommit = rw.parseCommit(commit);
+			RevTree aTree = rw.parseTree(aCommit.getTree());
+
+			assertEquals(168, midxTip.getObjectSize(ctx, aCommit));
+			assertEquals(33, midxTip.getObjectSize(ctx, aTree));
+			assertEquals(200, midxTip.getObjectSize(ctx, blob));
+			assertEquals(100, midxTip.getObjectSize(ctx, blobTwo));
+
+			assertEquals(-1, midxTip.getObjectSize(ctx, NOT_IN_PACK));
+		}
+	}
+
+	@Test
+	public void getObjectSize_byOffset() throws Exception {
+		ObjectId commit = writePackWithCommit();
+		gcWithBitmaps();
+		DfsPackFile midx = writeSinglePackMidx(db);
+
+		try (RevWalk rw = new RevWalk(db);
+				DfsReader ctx = db.getObjectDatabase().newReader()) {
+			RevCommit aCommit = rw.parseCommit(commit);
+			RevTree aTree = rw.parseTree(aCommit.getTree());
+
+			assertEquals(168,
+					midx.getObjectSize(ctx, midx.findOffset(ctx, aCommit)));
+			assertEquals(33,
+					midx.getObjectSize(ctx, midx.findOffset(ctx, aTree)));
+
+			assertEquals(-1, midx.getObjectSize(ctx, -1));
+		}
+	}
+
+	@Test
+	public void getObjectSize_byOffset_withBase() throws Exception {
+		ObjectId commit = writePackWithCommit();
+		ObjectId blob = writePackWithRandomBlob(200);
+
+		writePackWithRandomBlob(300);
+		ObjectId blobTwo = writePackWithRandomBlob(100);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		// Packs are in reverse insertion order
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 5), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		try (RevWalk rw = new RevWalk(db);
+				DfsReader ctx = db.getObjectDatabase().newReader()) {
+			RevCommit aCommit = rw.parseCommit(commit);
+			RevTree aTree = rw.parseTree(aCommit.getTree());
+
+			assertEquals(168, midxTip.getObjectSize(ctx,
+					midxTip.findOffset(ctx, aCommit)));
+			assertEquals(33,
+					midxTip.getObjectSize(ctx, midxTip.findOffset(ctx, aTree)));
+			assertEquals(200,
+					midxTip.getObjectSize(ctx, midxTip.findOffset(ctx, blob)));
+			assertEquals(100, midxTip.getObjectSize(ctx,
+					midxTip.findOffset(ctx, blobTwo)));
+
+			assertEquals(-1, midxTip.getObjectSize(ctx, -1));
+			assertEquals(-1, midxTip.getObjectSize(ctx,
+					midxTip.findOffset(ctx, NOT_IN_PACK)));
+		}
+	}
+
+	@Test
+	public void objectSizeIndex_disabled() throws Exception {
+		writePackWithRandomBlob(200);
+		DfsPackFile midx = writeSinglePackMidx(db);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertFalse(midx.hasObjectSizeIndex(ctx));
+		}
+	}
+
+	@Test
+	public void fillRepresentation() throws Exception {
+		RevCommit commit = writePackWithCommit();
+		gcWithBitmaps();
+		DfsPackFile midx = writeSinglePackMidx(db);
+
+		DfsObjectRepresentation rep = fillRepresentation(midx, commit,
+				OBJ_COMMIT);
+		assertEquals(midx, rep.pack);
+		assertEquals(12, rep.offset);
+		assertEquals(120, rep.length);
+	}
+
+	DfsObjectRepresentation fillRepresentation(DfsPackFile midx,
+			ObjectId commit, int typeHint) throws Exception {
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			ObjectToPack otp = new DfsObjectToPack(commit, typeHint);
+			DfsObjectToPack inPack = midx
+					.findAllFromPack(ctx, List.of(otp), true).get(0);
+			DfsObjectRepresentation rep = new DfsObjectRepresentation(midx);
+			midx.fillRepresentation(rep, inPack.getOffset(), ctx);
+			return rep;
+		}
+	}
+
+	@Test
+	public void fillRepresentation_withBase() throws Exception {
+		RevCommit commitInBase = writePackWithCommit();
+		ObjectId blob = writePackWithRandomBlob(300);
+		writePackWithRandomBlob(500);
+		writePackWithRandomBlob(100);
+		RevCommit commitInTip = writePackWithCommit();
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		assertEquals(6, packs.length);
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 6), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			// Commit in tip midx
+			DfsObjectRepresentation rep = fillRepresentation(midxTip,
+					commitInTip, OBJ_COMMIT);
+			assertEquals(midxTip.getPackDescription(),
+					rep.pack.getPackDescription());
+			assertEquals(midxTip.findOffset(ctx, commitInTip), rep.offset);
+			assertEquals(148, rep.length);
+
+			// Commit in base midx
+			rep = fillRepresentation(midxTip, commitInBase, OBJ_COMMIT);
+			assertEquals(midxTip.getPackDescription(),
+					rep.pack.getPackDescription());
+			assertEquals(midxTip.findOffset(ctx, commitInBase), rep.offset);
+			assertEquals(120, rep.length);
+
+			// Blob in base
+			rep = fillRepresentation(midxTip, blob, OBJ_COMMIT);
+			assertEquals(midxTip.getPackDescription(),
+					rep.pack.getPackDescription());
+			assertEquals(midxTip.findOffset(ctx, blob), rep.offset);
+			assertEquals(281, rep.length);
+		}
+	}
+
+	@Test
+	public void getBitmapIndex() throws Exception {
+		RevCommit c1 = writePackWithCommit();
+		RevCommit c2 = writePackWithCommit();
+		gcWithBitmaps();
+
+		DfsPackFileMidx midx = writeSinglePackMidx(db);
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			PackBitmapIndex bitmapIndex = midx.getBitmapIndex(ctx);
+			assertNotNull(bitmapIndex);
+			assertEquals(4, bitmapIndex.getObjectCount());
+			assertEquals(1, bitmapIndex.findPosition(c1));
+			assertEquals(0, bitmapIndex.findPosition(c2));
+		}
+	}
+
+	@Test
+	public void getAllCoveredPacks() throws Exception {
+		ObjectId[] objectIds = writePackWithBlobs(db, "aaaaaaaa",
+				"bbbbbbb", "ccccccc");
+		DfsPackFileMidx midx = writeSinglePackMidx(db);
+		DfsPackFile realPack = findPack(objectIds[0]);
+
+		assertEquals(1, midx.getAllCoveredPacks().size());
+		assertEquals(realPack.getPackDescription(),
+				midx.getAllCoveredPacks().get(0).getPackDescription());
+	}
+
+	@Test
+	public void getAllCoveredPacks_withBase() throws Exception {
+		writePackWithCommit();
+		writePackWithRandomBlob(300);
+		writePackWithRandomBlob(500);
+		writePackWithRandomBlob(100);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		assertEquals(5, packs.length);
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 5), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		assertEquals(5, midxTip.getAllCoveredPacks().size());
+		List<DfsPackDescription> expected = Arrays.stream(packs)
+				.map(DfsPackFile::getPackDescription).toList();
+		List<DfsPackDescription> actual = midxTip.getAllCoveredPacks().stream()
+				.map(DfsPackFile::getPackDescription).toList();
+		assertEquals(expected, actual);
+	}
+
+	@Test
+	public void getCoveredPacks_withBase_onlyTopMidx() throws Exception {
+		writePackWithCommit();
+		writePackWithRandomBlob(300);
+		writePackWithRandomBlob(500);
+		writePackWithRandomBlob(100);
+
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		assertEquals(5, packs.length);
+		DfsPackFileMidx midxBase = MidxTestUtils.writeMultipackIndex(db,
+				Arrays.copyOfRange(packs, 1, 5), null);
+		DfsPackFileMidx midxTip = writeSinglePackMidx(db,
+				packs[0], midxBase);
+
+		assertEquals(1, midxTip.getCoveredPacks().size());
+		assertEquals(packs[0].getPackDescription(),
+				midxTip.getAllCoveredPacks().get(0).getPackDescription());
+	}
+
+	@Test
+	public void corrupt() throws Exception {
+		RevCommit commit = writePackWithCommit();
+		DfsPackFile pack = findPack(commit);
+		DfsPackFileMidx midx = writeSinglePackMidx(db, pack);
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			assertFalse(midx.isCorrupt(midx.findOffset(ctx, commit)));
+		}
+	}
+
+	@Test
+	public void packwriter_via_midx() throws Exception {
+		ObjectId[] oids = writePackWithBlobs(db, "xxxxxxxyyyy",
+				"booooohooooo", "baaaaahaaaaaa");
+		ObjectId blob = oids[0];
+		ObjectId blobTwo = oids[1];
+		ObjectId notPacked = oids[2];
+
+		writeSinglePackMidx(db);
+
+		db.getObjectDatabase().setUseMultipackIndex(true);
+		byte[] writtenPack;
+		try (DfsReader ctx = db.getObjectDatabase().newReader();
+				RevWalk rw = new RevWalk(ctx);
+				PackWriter pw = new PackWriter(db, ctx)) {
+			pw.addObject(rw.lookupBlob(blob));
+			pw.addObject(rw.lookupBlob(blobTwo));
+
+			try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+				CounterProgressMonitor cpm = new CounterProgressMonitor();
+				pw.writePack(NullProgressMonitor.INSTANCE, cpm, out);
+				out.flush();
+				assertEquals(79, out.size());
+				assertEquals(2, cpm.objectsPacked);
+				writtenPack = out.toByteArray();
+			}
+		}
+
+		try (InMemoryRepository dest = new InMemoryRepository(
+				new DfsRepositoryDescription("test"));
+				ObjectInserter ins = dest.getObjectDatabase().newInserter()) {
+			ins.newPackParser(new ByteArrayInputStream(writtenPack))
+					.parse(NullProgressMonitor.INSTANCE);
+			assertTrue(dest.getObjectDatabase().has(blob));
+			assertTrue(dest.getObjectDatabase().has(blobTwo));
+			assertFalse(dest.getObjectDatabase().has(notPacked));
+		}
+	}
+
+	@Test
+	public void getChecksum() throws Exception {
+		writePackWithBlobs(db, "something", "something else", "and more");
+		DfsPackFileMidx midx = writeSinglePackMidx(db);
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			// The checksum includes packnames and can
+			// change between runs (e.g. running this test alone, or locally vs
+			// jenkins).
+			// Check at least that we don't get an empty checksum or the first
+			// bytes of the midx.
+			byte[] checksum = midx.getChecksum(ctx);
+			assertNotNull(checksum);
+			assertEquals(20, checksum.length);
+			assertNotEquals('M', checksum[0]);
+			assertNotEquals('I', checksum[1]);
+			assertNotEquals('D', checksum[2]);
+			assertNotEquals('X', checksum[3]);
+		}
+	}
+
+	@Test
+	public void voffsetcalculator_encode() {
+		DfsPackFile pack = createDfsPackFile(900);
+		SingleVOffsetCalculator calc = new SingleVOffsetCalculator(pack, null);
+
+		PackOffset po = PackOffset.create(0, 12);
+		assertEquals(12, calc.encode(po));
+		po = PackOffset.create(0, 800);
+		assertEquals(800, calc.encode(po));
+
+		// Invalid packId
+		assertThrows(IllegalArgumentException.class,
+				() -> calc.encode(PackOffset.create(1, 12)));
+	}
+
+	@Test
+	public void voffsetcalculator_decode() {
+		DfsPackFile pack = createDfsPackFile(800);
+		SingleVOffsetCalculator calc = new SingleVOffsetCalculator(pack, null);
+
+		DfsPackOffset decoded = calc.decode(130);
+		assertEquals(pack.getPackDescription(),
+				decoded.getPack().getPackDescription());
+		assertEquals(130, decoded.getPackOffset());
+		assertEquals(0, decoded.getPackStart());
+
+		decoded = calc.decode(0);
+		assertEquals(pack.getPackDescription(),
+				decoded.getPack().getPackDescription());
+		assertEquals(0, decoded.getPackOffset());
+		assertEquals(0, decoded.getPackStart());
+
+		assertThrows("too big", IllegalArgumentException.class,
+				() -> calc.decode(900));
+	}
+
+	@Test
+	public void voffsetcalculator_notFound() {
+		DfsPackFile pack = createDfsPackFile(800);
+		SingleVOffsetCalculator calc = new SingleVOffsetCalculator(pack, null);
+
+		assertEquals(-1, calc.encode(null));
+		assertNull(calc.decode(-1));
+	}
+
+	@Test
+	public void voffsetcalculator_maxOffset() {
+		DfsPackFile pack = createDfsPackFile(800);
+		SingleVOffsetCalculator calc = new SingleVOffsetCalculator(pack, null);
+		assertEquals(800, calc.getMaxOffset());
+	}
+
+	@Test
+	public void voffsetcalculator_withBase_encode() {
+		DfsPackFile one = createDfsPackFile(800);
+		SingleVOffsetCalculator calcOne = new SingleVOffsetCalculator(one,
+				null);
+		DfsPackFile two = createDfsPackFile(1200);
+		SingleVOffsetCalculator calcTwo = new SingleVOffsetCalculator(two,
+				calcOne);
+
+		PackOffset po = PackOffset.create(0, 12);
+		assertEquals(12 + 800, calcTwo.encode(po));
+	}
+
+	@Test
+	public void voffsetcalculator_withBase_decode() {
+		DfsPackFile one = createDfsPackFile(800);
+		SingleVOffsetCalculator calcOne = new SingleVOffsetCalculator(one,
+				null);
+		DfsPackFile two = createDfsPackFile(1200);
+		SingleVOffsetCalculator calcTwo = new SingleVOffsetCalculator(two,
+				calcOne);
+
+		// In top pack
+		DfsPackOffset decoded = calcTwo.decode(900);
+		assertEquals(two.getPackDescription(),
+				decoded.getPack().getPackDescription());
+		assertEquals(100, decoded.getPackOffset());
+		assertEquals(800, decoded.getPackStart());
+
+		// In parent pack
+		decoded = calcTwo.decode(700);
+		assertEquals(one.getPackDescription(),
+				decoded.getPack().getPackDescription());
+		assertEquals(700, decoded.getPackOffset());
+		assertEquals(0, decoded.getPackStart());
+	}
+
+	@Test
+	public void voffsetcalculator_withBase_maxOffset() {
+		DfsPackFile one = createDfsPackFile(800);
+		SingleVOffsetCalculator calcOne = new SingleVOffsetCalculator(one,
+				null);
+		DfsPackFile two = createDfsPackFile(1200);
+		SingleVOffsetCalculator calcTwo = new SingleVOffsetCalculator(two,
+				calcOne);
+
+		assertEquals(2000, calcTwo.getMaxOffset());
+	}
+
+	private static DfsPackFile createDfsPackFile(int size) {
+		DfsPackDescription desc = new DfsPackDescription(
+				new DfsRepositoryDescription("the_repo"), "pack_blabla", GC);
+		desc.addFileExt(PACK);
+		desc.setFileSize(PACK, size);
+		desc.setObjectCount(1);
+		return new DfsPackFile(null, desc);
+	}
+
+	private DfsPackFileMidx writeMultipackIndex() throws IOException {
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		return MidxTestUtils.writeMultipackIndex(db, packs, null);
+	}
+
+	private void gcWithBitmaps() throws IOException {
+		DfsGarbageCollector garbageCollector = new DfsGarbageCollector(db);
+		garbageCollector.pack(NullProgressMonitor.INSTANCE);
+	}
+
+	private RevCommit writePackWithCommit() throws Exception {
+		try (TestRepository<InMemoryRepository> repository = new TestRepository<>(
+				db)) {
+			// commitCounter++;
+			return repository.branch("/refs/heads/main").commit()
+					.add("blob" + commitCounter, "blob" + commitCounter)
+					.create();
+		}
+	}
+
+	record CommitObjects(RevCommit commit, RevTree tree, RevBlob blob) {
+	}
+
+	private static int commitCounter = 1;
+
+	private CommitObjects writePackWithOneCommit() throws Exception {
+		try (TestRepository<InMemoryRepository> repository = new TestRepository<>(
+				db)) {
+			RevBlob blob = repository.blob("blob" + commitCounter);
+			RevCommit revCommit = repository.branch("/refs/heads/main").commit()
+					.add("blob" + commitCounter, blob).create();
+			commitCounter++;
+			return new CommitObjects(revCommit, revCommit.getTree(), blob);
+		}
+	}
+
+	private ObjectId writePackWithRandomBlob(int size) throws IOException {
+		byte[] data = new TestRng(JGitTestUtil.getName()).nextBytes(size);
+		return writePackWithBlob(data);
+	}
+
+	private ObjectId writePackWithBlob(byte[] data) throws IOException {
+		DfsInserter ins = (DfsInserter) db.newObjectInserter();
+
+		ObjectId blobId = ins.insert(OBJ_BLOB, data);
+		ins.flush();
+		return blobId;
+	}
+
+	private DfsPackFile findPack(ObjectId oid) throws IOException {
+		DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+		try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+			for (DfsPackFile pack : packs) {
+				if (pack.hasObject(ctx, oid)) {
+					return pack;
+				}
+			}
+		}
+		throw new IllegalArgumentException("Object not in any pack");
+	}
+
+	private static final class CounterProgressMonitor
+			implements ProgressMonitor {
+
+		int objectsPacked = 0;
+
+		@Override
+		public void start(int totalTasks) {
+			// empty
+		}
+
+		@Override
+		public void beginTask(String title, int totalWork) {
+			System.out.println("Starting " + title);
+		}
+
+		@Override
+		public void update(int completed) {
+			objectsPacked += 1;
+		}
+
+		@Override
+		public void endTask() {
+			// empty
+		}
+
+		@Override
+		public boolean isCancelled() {
+			return false;
+		}
+
+		@Override
+		public void showDuration(boolean enabled) {
+			// empty
+		}
+	}
+
+	private byte[] safeGetBytes(@Nullable ObjectLoader ol) {
+		assertNotNull(ol);
+		byte[] data = ol.getBytes();
+		assertNotNull(data);
+		return data;
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackFilterTest.java
index 584bab1..68aacba 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackFilterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackFilterTest.java
@@ -130,6 +130,81 @@ public void useMidx_nestedMidxAndOnePack_topMidxAndPack() {
 	}
 
 	@Test
+	public void useMidx_unconnectedValidMidx_onlyTop() {
+
+		DfsPackDescription gc = pack("aaaa", GC, PACK);
+		DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+		DfsPackDescription firstMidx = pack("midx1", GC, MULTI_PACK_INDEX);
+		firstMidx.setCoveredPacks(List.of(gc, compact));
+
+		DfsPackDescription unconnectedValid = pack("randoMidx", GC,
+				MULTI_PACK_INDEX);
+		unconnectedValid.setCoveredPacks(List.of(gc));
+
+		DfsPackDescription compact2 = pack("dddd", COMPACT, PACK);
+		DfsPackDescription compact3 = pack("eeee", COMPACT, PACK);
+		DfsPackDescription topMidx = pack("midx2", GC, MULTI_PACK_INDEX);
+		topMidx.setCoveredPacks(List.of(compact2, compact3));
+		topMidx.setMultiPackIndexBase(firstMidx);
+
+		List<DfsPackDescription> reorgPacks = MidxPackFilter
+				.useMidx(List.of(gc, compact, firstMidx, unconnectedValid,
+						compact2, compact3, topMidx));
+		assertEquals(1, reorgPacks.size());
+		assertTrue(reorgPacks.contains(topMidx));
+	}
+
+	@Test
+	public void useMidx_unconnectedInvalidMidx_onlyTop() {
+		DfsPackDescription gc = pack("aaaa", GC, PACK);
+		DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+		DfsPackDescription firstMidx = pack("midx1", GC, MULTI_PACK_INDEX);
+		firstMidx.setCoveredPacks(List.of(gc, compact));
+
+		DfsPackDescription notCommitted = pack("not-in-db", GC, PACK);
+		DfsPackDescription unconnectedInvalid = pack("randoMidx", GC,
+				MULTI_PACK_INDEX);
+		unconnectedInvalid.setCoveredPacks(List.of(notCommitted));
+
+		DfsPackDescription compact2 = pack("dddd", COMPACT, PACK);
+		DfsPackDescription compact3 = pack("eeee", COMPACT, PACK);
+		DfsPackDescription topMidx = pack("midx2", GC, MULTI_PACK_INDEX);
+		topMidx.setCoveredPacks(List.of(compact2, compact3));
+		topMidx.setMultiPackIndexBase(firstMidx);
+
+		List<DfsPackDescription> reorgPacks = MidxPackFilter
+				.useMidx(List.of(gc, compact, firstMidx, unconnectedInvalid,
+						compact2, compact3, topMidx));
+		assertEquals(1, reorgPacks.size());
+		assertTrue(reorgPacks.contains(topMidx));
+	}
+
+	@Test
+	public void useMidx_latestMidxInvalid_takeNext() {
+		DfsPackDescription gc = pack("aaaa", GC, PACK);
+		DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+		DfsPackDescription firstMidx = pack("midx1", GC, MULTI_PACK_INDEX);
+		firstMidx.setCoveredPacks(List.of(gc, compact));
+
+		DfsPackDescription compact2 = pack("dddd", COMPACT, PACK);
+		DfsPackDescription compact3 = pack("eeee", COMPACT, PACK);
+		DfsPackDescription topMidx = pack("midx2", GC, MULTI_PACK_INDEX);
+		topMidx.setCoveredPacks(List.of(compact2, compact3));
+		topMidx.setMultiPackIndexBase(firstMidx);
+
+		DfsPackDescription notCommitted = pack("not-in-db", GC, PACK);
+		DfsPackDescription unconnectedInvalid = pack("randoMidx", GC,
+				MULTI_PACK_INDEX);
+		unconnectedInvalid.setCoveredPacks(List.of(notCommitted));
+
+		List<DfsPackDescription> reorgPacks = MidxPackFilter
+				.useMidx(List.of(gc, compact, firstMidx, unconnectedInvalid,
+						compact2, compact3, topMidx));
+		assertEquals(1, reorgPacks.size());
+		assertTrue(reorgPacks.contains(topMidx));
+	}
+
+	@Test
 	public void skipMidx_oneMidxCoversAll_allPacks() {
 		DfsPackDescription gc = pack("aaaa", GC, PACK);
 		DfsPackDescription compact = pack("cccc", COMPACT, PACK);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/RefAdvancerWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/RefAdvancerWalkTest.java
new file mode 100644
index 0000000..321ea01
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/RefAdvancerWalkTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2026, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Before;
+import org.junit.Test;
+
+public class RefAdvancerWalkTest {
+	private static final String MAIN = "refs/heads/main";
+
+	private InMemoryRepository db;
+
+	private TestRepository<InMemoryRepository> git;
+
+	private Set<RevCommit> commitsInMidx;
+
+	private Map<String, RevCommit> commitByLetter;
+
+	@Before
+	public void setUp() throws Exception {
+		db = new InMemoryRepository(
+				new DfsRepositoryDescription("ref advance"));
+		git = new TestRepository<>(db);
+		setupRepo();
+	}
+
+	/**
+	 * <pre>
+	 *  tipMergeBeforeMidx -> H
+	 *                        |
+	 *                        |
+	 *                        F  G <- tipStraight
+	 *                        |\ |
+	 *                        | \|
+	 * tipMergeMidxCommits -> D  E
+	 *                        |\ |
+	 *                      +--------+
+	 *                      | B  C <-- tipIn
+	 *                      | | /    |
+	 *                      | |/     |
+	 *                      | A      |
+	 *                      |    midx|
+	 *                      +--------+
+	 * </pre>
+	 */
+	private void setupRepo() throws Exception {
+		RevCommit a = commitToMain();
+		RevCommit b = commitToMain();
+		RevCommit c = commit(a);
+		RevCommit d = commitToMain(c);
+		RevCommit e = commit(c);
+		/* unused */ commitToMain();
+		RevCommit g = commit(e);
+		RevCommit h = commitToMain();
+
+		commitsInMidx = new HashSet<>();
+		commitsInMidx.add(a);
+		commitsInMidx.add(b);
+		commitsInMidx.add(c);
+
+		commitByLetter = Map.of("a", a, "b", b, "c", c, "d", d, "e", e, "g", g,
+				"h", h);
+
+	}
+
+	@Test
+	public void singleWant_linearHistory() throws Exception {
+		runTest("g", Set.of("c"));
+	}
+
+	@Test
+	public void singleWant_alreadyInMidx() throws Exception {
+		runTest("c", Set.of("c"));
+	}
+
+	@Test
+	public void singleWant_mergeCommitsInMidx() throws Exception {
+		runTest("d", Set.of("b", "c"));
+	}
+
+	@Test
+	public void singleWant_mergeBeforeMidx() throws Exception {
+		runTest("h", Set.of("b", "c"));
+	}
+
+	@Test
+	public void manyWant_mergeBeforeMidx() throws Exception {
+		runTest(Set.of("h", "c", "d", "g"), Set.of("b", "c"));
+	}
+
+	private void runTest(String want, Set<String> expectedTips)
+			throws IOException {
+		runTest(Set.of(want), expectedTips);
+	}
+
+	private void runTest(Set<String> want, Set<String> expectedTips)
+			throws IOException {
+		RefAdvancerWalk advancer = new RefAdvancerWalk(db,
+				commitsInMidx::contains);
+		List<ObjectId> wants = want.stream().map(commitByLetter::get)
+				.collect(Collectors.toUnmodifiableList());
+		Set<RevCommit> tipsInMidx = advancer.advance(wants);
+
+		Set<RevCommit> expected = expectedTips.stream().map(commitByLetter::get)
+				.collect(Collectors.toUnmodifiableSet());
+		assertEquals(expected.size(), tipsInMidx.size());
+		assertTrue(tipsInMidx.containsAll(expected));
+	}
+
+	private static int commitCounter = 0;
+
+	private RevCommit commitToMain() throws Exception {
+		int i = commitCounter++;
+		return git.branch(MAIN).commit()
+				.add("xx" + i, git.blob("content #" + i)).create();
+	}
+
+	private RevCommit commitToMain(RevCommit... extraParent) throws Exception {
+		int i = commitCounter++;
+		TestRepository<InMemoryRepository>.CommitBuilder commit = git
+				.branch(MAIN).commit();
+		for (RevCommit p : extraParent) {
+			commit.parent(p);
+		}
+
+		return commit.add("xx" + i, git.blob("content #" + i)).create();
+	}
+
+	private RevCommit commit(RevCommit parent) throws Exception {
+		int i = commitCounter++;
+		return git.commit().parent(parent)
+				.add("cc" + i, git.blob("out of main content #" + i)).create();
+	}
+
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java
index 434f7e4..101feec 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java
@@ -21,8 +21,11 @@
 import java.util.Collection;
 import java.util.List;
 
+import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
 import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.GcConfig;
+import org.eclipse.jgit.lib.GcConfig.PackRefsMode;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.revwalk.RevCommit;
@@ -376,4 +379,106 @@ private PackConfig configureGc(GC myGc, boolean aggressive) {
 		myGc.setPackConfig(pconfig);
 		return pconfig;
 	}
+
+	@Test
+	public void testPackRefs() throws Exception {
+		tr.branch("refs/heads/master").commit().add("A", "A").add("B", "B")
+				.create();
+		assertHasLooseRef(repo);
+
+		// by default, refs should be packed
+		gc.gc().get();
+		assertHasNoLooseRef(repo);
+
+		// now create a loose ref again
+		tr.branch("refs/heads/foo").commit().add("C", "C").create();
+		assertHasLooseRef(repo);
+		// and disable packing of refs
+		gc.setGcConfig(new GcConfig(PackRefsMode.FALSE));
+		gc.gc().get();
+		assertHasLooseRef(repo);
+	}
+
+	@Test
+	public void testPackRefsWithConfig() throws Exception {
+		tr.branch("refs/heads/master").commit().add("A", "A").add("B", "B")
+				.create();
+		assertHasLooseRef(repo);
+
+		// disable packing of refs via config
+		FileBasedConfig config = repo.getConfig();
+		config.setEnum(ConfigConstants.CONFIG_GC_SECTION, null,
+				ConfigConstants.CONFIG_KEY_PACK_REFS, PackRefsMode.FALSE);
+		config.save();
+		reloadGcFromRepoConfig();
+
+		gc.gc().get();
+		assertHasLooseRef(repo);
+
+		// now enable packing of refs via API
+		gc.setGcConfig(new GcConfig(PackRefsMode.TRUE));
+		gc.gc().get();
+		assertHasNoLooseRef(repo);
+	}
+
+	@Test
+	public void testPackRefsWithNotBareConfig() throws Exception {
+		// non-bare repo
+		tr.branch("refs/heads/master").commit().add("A", "A").add("B", "B")
+				.create();
+		assertHasLooseRef(repo);
+
+		// configure packing of refs only for non-bare repositories
+		FileBasedConfig config = repo.getConfig();
+		config.setEnum(ConfigConstants.CONFIG_GC_SECTION, null,
+				ConfigConstants.CONFIG_KEY_PACK_REFS, PackRefsMode.NOTBARE);
+		config.save();
+		reloadGcFromRepoConfig();
+
+		gc.gc().get();
+		assertHasNoLooseRef(repo);
+
+		// bare repo
+		String repoUri = repo.getDirectory().toURI().toString();
+		File dir = createUniqueTestGitDir(true);
+		try (FileRepository bareRepo = (FileRepository) Git.cloneRepository()
+				.setBare(true).setURI(repoUri).setDirectory(dir).call()
+				.getRepository(); Git git = new Git(bareRepo)) {
+			git.branchCreate().setName("refs/heads/branch-in-bare-repo")
+					.setStartPoint("refs/heads/master").call();
+			assertHasLooseRef(bareRepo);
+
+			// configure packing of refs only for non-bare repositories
+			FileBasedConfig bareConfig = bareRepo.getConfig();
+			bareConfig.setEnum(ConfigConstants.CONFIG_GC_SECTION, null,
+					ConfigConstants.CONFIG_KEY_PACK_REFS, PackRefsMode.NOTBARE);
+			bareConfig.save();
+			// create a new GC instance to reread the config
+			gc = new GC(bareRepo);
+
+			gc.gc().get();
+			assertHasLooseRef(bareRepo);
+		}
+	}
+
+	private static boolean hasLooseRef(FileRepository repository)
+			throws IOException {
+		return repository.getRefDatabase().getRefs().stream()
+				.filter(r -> !r.isSymbolic())
+				.anyMatch(r -> r.getStorage().isLoose());
+	}
+
+	private void reloadGcFromRepoConfig() {
+		gc = new GC(repo);
+	}
+
+	private static void assertHasLooseRef(FileRepository repository)
+			throws IOException {
+		assertTrue("should have loose ref", hasLooseRef(repository));
+	}
+
+	private static void assertHasNoLooseRef(FileRepository repository)
+			throws IOException {
+		assertFalse("should have no loose ref", hasLooseRef(repository));
+	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilderTest.java
new file mode 100644
index 0000000..10d9c2e
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilderTest.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2026, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.file;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jgit.internal.storage.pack.BitmapCommit;
+import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
+import org.eclipse.jgit.lib.BitmapIndex;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdOwnerMap;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+
+@RunWith(Parameterized.class)
+public class PackBitmapIndexBuilderTest {
+
+	/**
+	 * Numbers are oids
+	 *
+	 * <pre>
+	 *     tip
+	 *     10 (commit) -> 9 (tree) -> 8 (blob)
+	 *      |
+	 *      7 (commit) -> 6 (tree) -> 5,4  (blobs)
+	 *      |
+	 *      3 (commit) -> 2 (tree) ->  1 (blob)
+	 * </pre>
+	 */
+	private static final List<ObjectToPack> opts = List.of(
+			otp(10, 400, Constants.OBJ_COMMIT), otp(9, 900, Constants.OBJ_TREE),
+			otp(8, 280, Constants.OBJ_BLOB), otp(7, 200, Constants.OBJ_COMMIT),
+			otp(6, 410, Constants.OBJ_TREE), otp(5, 500, Constants.OBJ_BLOB),
+			otp(4, 450, Constants.OBJ_BLOB), otp(3, 470, Constants.OBJ_COMMIT),
+			otp(2, 700, Constants.OBJ_TREE), otp(1, 240, Constants.OBJ_BLOB));
+
+	public enum TestSetup {
+		SINGLE_BUILDER
+	}
+
+	@Parameterized.Parameters(name = "{0}")
+	public static Iterable<TestSetup> data() {
+		return Arrays.stream(TestSetup.values()).toList();
+	}
+
+	private final TestSetup currentSetup;
+
+	public PackBitmapIndexBuilderTest(TestSetup ts) {
+		this.currentSetup = ts;
+	}
+
+	@Test
+	public void getObjectSet() {
+		ObjectIdOwnerMap<ObjectIdOwnerMap.Entry> objectSet = createBuilder()
+				.getObjectSet();
+		for (int i = 1; i <= 10; i++) {
+			assertTrue(objectSet.contains(oid(i)));
+		}
+	}
+
+	@Test
+	public void addBitmap_getBitmap() {
+		EWAHCompressedBitmap added = EWAHCompressedBitmap.bitmapOf(1, 3, 5);
+		PackBitmapIndexBuilder pbi = createBuilder();
+		pbi.addBitmap(oid(11), added, 10);
+
+		EWAHCompressedBitmap retrieved = pbi.getBitmap(oid(11));
+		assertEquals(added, retrieved);
+	}
+
+	@Test
+	public void ofObjectType() {
+		PackBitmapIndexBuilder pbi = createBuilder();
+		BitmapIndexImpl bii = new BitmapIndexImpl(pbi);
+		BitmapIndex.BitmapBuilder bb = bii.newBitmapBuilder();
+		bb.addObject(oid(10), Constants.OBJ_COMMIT);
+		bb.addObject(oid(9), Constants.OBJ_TREE);
+		bb.addObject(oid(8), Constants.OBJ_BLOB);
+		BitmapIndex.Bitmap b = bb.build();
+
+		EWAHCompressedBitmap commits = pbi.ofObjectType(b.retrieveCompressed(),
+				Constants.OBJ_COMMIT);
+		assertInBitmap(pbi, commits, 10);
+		assertNotInBitmap(pbi, commits, 9);
+		assertNotInBitmap(pbi, commits, 8);
+
+		EWAHCompressedBitmap trees = pbi.ofObjectType(b.retrieveCompressed(),
+				Constants.OBJ_TREE);
+		assertNotInBitmap(pbi, trees, 10);
+		assertInBitmap(pbi, trees, 9);
+		assertNotInBitmap(pbi, trees, 8);
+
+		EWAHCompressedBitmap blobs = pbi.ofObjectType(b.retrieveCompressed(),
+				Constants.OBJ_BLOB);
+		assertNotInBitmap(pbi, blobs, 10);
+		assertNotInBitmap(pbi, blobs, 9);
+		assertInBitmap(pbi, blobs, 8);
+	}
+
+	@Test
+	public void findPosition() {
+		PackBitmapIndexBuilder pbi = createBuilder();
+		// All valid, non-repeating positions
+		Set<Integer> seen = new HashSet<>();
+		for (int oidAsInt = 1; oidAsInt <= 10; oidAsInt++) {
+			int p = pbi.findPosition(oid(oidAsInt));
+			assertTrue(p >= 0);
+			assertTrue(p < 10);
+			assertFalse(seen.contains(p));
+			seen.add(p);
+		}
+	}
+
+	@Test
+	public void getObject() {
+		PackBitmapIndexBuilder pbi = createBuilder();
+		for (int oidAsInt = 1; oidAsInt <= 10; oidAsInt++) {
+			ObjectId expected = oid(oidAsInt);
+			int p = pbi.findPosition(expected);
+			ObjectId actual = pbi.getObject(p);
+			assertEquals(expected, actual);
+		}
+	}
+
+	@Test
+	public void commits() {
+		PackBitmapIndexBuilder pbi = createBuilder();
+		EWAHCompressedBitmap commits = pbi.getCommits();
+		assertInBitmap(pbi, commits, 10);
+		assertInBitmap(pbi, commits, 7);
+		assertInBitmap(pbi, commits, 3);
+
+		assertNotInBitmap(pbi, commits, 9);
+		assertNotInBitmap(pbi, commits, 8);
+	}
+
+	@Test
+	public void trees() {
+		PackBitmapIndexBuilder pbi = createBuilder();
+		EWAHCompressedBitmap trees = pbi.getTrees();
+		assertInBitmap(pbi, trees, 9);
+		assertInBitmap(pbi, trees, 6);
+		assertInBitmap(pbi, trees, 2);
+
+		assertNotInBitmap(pbi, trees, 10);
+		assertNotInBitmap(pbi, trees, 8);
+	}
+
+	@Test
+	public void blobs() {
+		PackBitmapIndexBuilder pbi = createBuilder();
+		EWAHCompressedBitmap blobs = pbi.getBlobs();
+		assertInBitmap(pbi, blobs, 8);
+		assertInBitmap(pbi, blobs, 5);
+		assertInBitmap(pbi, blobs, 4);
+		assertInBitmap(pbi, blobs, 1);
+
+		assertNotInBitmap(pbi, blobs, 10);
+		assertNotInBitmap(pbi, blobs, 9);
+	}
+
+	@Test
+	public void getBitmapCount() {
+		// The builder only counts bitmaps "in progress" (in xor queue or ready
+		// to write)
+		assertEquals(0, createBuilder().getBitmapCount());
+	}
+
+	@Test
+	public void getBitmapCount_newBitmaps() {
+
+	}
+
+	@Test
+	public void reachableObjects_setInBitmap() {
+		PackBitmapIndexBuilder builder = createBuilder();
+		EWAHCompressedBitmap bitmapTen = builder.getBitmap(oid(10));
+		assertNotNull(bitmapTen);
+		for (int oidAsInt = 10; oidAsInt > 0; oidAsInt--) {
+			assertInBitmap(builder, bitmapTen, oidAsInt);
+		}
+
+		EWAHCompressedBitmap bitmapSeven = builder.getBitmap(oid(7));
+		assertNotNull(bitmapSeven);
+		assertNotInBitmap(builder, bitmapSeven, 10);
+		assertNotInBitmap(builder, bitmapSeven, 9);
+		assertNotInBitmap(builder, bitmapSeven, 8);
+		for (int i = 7; i > 0; i--) {
+			assertInBitmap(builder, bitmapSeven, i);
+		}
+	}
+
+	@Test
+	public void processBitmapForWrite() {
+		// processBitmapForWrite keeps the bitmaps in the builder instead of in
+		// the superclass, to calculate the XORs
+		PackBitmapIndexBuilder builder = createBuilder();
+		BitmapIndex bb = new BitmapIndexImpl(builder);
+		BitmapIndex.BitmapBuilder oneBitmap = bb.newBitmapBuilder();
+		oneBitmap.addObject(oid(10), Constants.OBJ_COMMIT);
+		oneBitmap.addObject(oid(9), Constants.OBJ_TREE);
+		oneBitmap.addObject(oid(8), Constants.OBJ_BLOB);
+		oneBitmap.addObject(oid(7), Constants.OBJ_COMMIT);
+		oneBitmap.addObject(oid(6), Constants.OBJ_TREE);
+		oneBitmap.addObject(oid(5), Constants.OBJ_BLOB);
+
+		BitmapIndex.BitmapBuilder anotherBitmap = bb.newBitmapBuilder();
+		anotherBitmap.addObject(oid(7), Constants.OBJ_COMMIT);
+		anotherBitmap.addObject(oid(6), Constants.OBJ_TREE);
+		anotherBitmap.addObject(oid(5), Constants.OBJ_BLOB);
+
+		builder.processBitmapForWrite(
+				new BitmapCommit(oid(10), false, 0, false), oneBitmap, 0);
+		builder.processBitmapForWrite(new BitmapCommit(oid(7), false, 0, false),
+				oneBitmap, 0);
+		assertEquals(2, builder.getBitmapCount());
+
+		List<PackBitmapIndexBuilder.StoredEntry> ses = builder
+				.getCompressedBitmaps();
+		assertEquals(2, ses.size());
+		assertEquals(oid(7), ses.get(0).getObjectId());
+		assertEquals(6, ses.get(0).getIdxPosition());
+
+		assertEquals(oid(10), ses.get(1).getObjectId());
+		assertEquals(9, ses.get(1).getIdxPosition());
+	}
+
+	@Test
+	public void getObjectCount() {
+		assertEquals(10, createBuilder().getObjectCount());
+	}
+
+	private static void assertInBitmap(PackBitmapIndexBuilder builder,
+			EWAHCompressedBitmap bitmap, int oidAsInt) {
+		ObjectId oid = oid(oidAsInt);
+		int pos = builder.findPosition(oid);
+		assertTrue(pos >= 0);
+		assertTrue(bitmap.get(pos));
+	}
+
+	private static void assertNotInBitmap(PackBitmapIndexBuilder builder,
+			EWAHCompressedBitmap bitmap, int oidAsInt) {
+		ObjectId oid = oid(oidAsInt);
+		int pos = builder.findPosition(oid);
+		assertTrue(pos >= 0);
+		assertFalse(bitmap.get(pos));
+	}
+
+	private PackBitmapIndexBuilder createBuilder() {
+		ArrayList<ObjectToPack> objectsToPack = new ArrayList<>(opts);
+		Collections.reverse(objectsToPack);
+		return switch (currentSetup) {
+		case SINGLE_BUILDER -> setupSinglePackBitmapIndex(objectsToPack);
+		};
+	}
+
+	static PackBitmapIndexBuilder setupSinglePackBitmapIndex(
+			List<ObjectToPack> objectsToPack) {
+		PackBitmapIndexBuilder b = new PackBitmapIndexBuilder(objectsToPack);
+
+		BitmapIndex bi = new BitmapIndexImpl(b);
+		// Base commit (3, 2, 1)
+		BitmapIndex.BitmapBuilder bitmapOne = bi.newBitmapBuilder();
+		bitmapOne.addObject(oid(3), Constants.OBJ_COMMIT);
+		bitmapOne.addObject(oid(2), Constants.OBJ_TREE);
+		bitmapOne.addObject(oid(1), Constants.OBJ_BLOB);
+		b.addBitmap(oid(3), bitmapOne.build(), 0);
+
+		// Middle commit (7, 6, 5, 4) with base commit as parent
+		BitmapIndex.BitmapBuilder middleBitmap = bi.newBitmapBuilder();
+		middleBitmap.addObject(oid(7), Constants.OBJ_COMMIT);
+		middleBitmap.addObject(oid(6), Constants.OBJ_TREE);
+		middleBitmap.addObject(oid(5), Constants.OBJ_BLOB);
+		middleBitmap.addObject(oid(4), Constants.OBJ_BLOB);
+		middleBitmap.or(bitmapOne);
+		b.addBitmap(oid(7), middleBitmap, 0);
+
+		BitmapIndex.BitmapBuilder tipBitmap = bi.newBitmapBuilder();
+		tipBitmap.addObject(oid(10), Constants.OBJ_COMMIT);
+		tipBitmap.addObject(oid(9), Constants.OBJ_TREE);
+		tipBitmap.addObject(oid(8), Constants.OBJ_BLOB);
+		tipBitmap.or(middleBitmap);
+		b.addBitmap(oid(10), tipBitmap, 0);
+
+		return b;
+	}
+
+	private static ObjectToPack otp(int oid, long offset, int type) {
+		ObjectToPack otp = new ObjectToPack(oid(oid), type);
+		otp.setOffset(offset);
+		return otp;
+	}
+
+	private static ObjectId oid(int n) {
+		return ObjectId.fromRaw(new int[] { 0, 0, 0, 0, n });
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
index baa0182..6552bac 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
@@ -37,6 +37,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.eclipse.jgit.api.PackRefsCommand;
 import org.eclipse.jgit.errors.LockFailedException;
 import org.eclipse.jgit.events.ListenerHandle;
 import org.eclipse.jgit.events.RefsChangedEvent;
@@ -44,6 +45,7 @@
 import org.eclipse.jgit.junit.Repeat;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Ref.Storage;
 import org.eclipse.jgit.lib.RefDatabase;
@@ -1062,6 +1064,60 @@ public void test_repack() throws Exception {
 	}
 
 	@Test
+	public void testPackedRefsHeaderWithSorted() throws Exception {
+		writeLooseRef("refs/heads/master", A);
+		writeLooseRef("refs/heads/other", B);
+		writeLooseRef("refs/tags/v1.0", v1_0);
+
+		PackRefsCommand packRefsCommand = new PackRefsCommand(diskRepo);
+		packRefsCommand.setAll(true);
+		packRefsCommand.call();
+
+		File packedRefsFile = new File(diskRepo.getCommonDirectory(), Constants.PACKED_REFS);
+		assertTrue("packed-refs should exist", packedRefsFile.exists());
+
+		String content = read(packedRefsFile);
+		String firstLine = content.split("\n")[0];
+		assertTrue("packed-refs should have header with sorted",
+				firstLine.contains(" sorted"));
+
+		int masterIndex = content.indexOf(A.name() + " refs/heads/master");
+		int otherIndex = content.indexOf(B.name() + " refs/heads/other");
+		int tagIndex = content.indexOf(v1_0.name() + " refs/tags/v1.0");
+		assertTrue("packed-refs should be sorted",
+				masterIndex < otherIndex && otherIndex < tagIndex);
+	}
+
+	@Test
+	public void testPackedRefsUnsortedGetsSorted() throws Exception {
+		writePackedRefs("# pack-refs with: peeled \n" + //
+				B.name() + " refs/heads/other\n" + //
+				v1_0.name() + " refs/tags/v1.0\n" + //
+				"^" + v1_0.getObject().name() + "\n" + //
+				A.name() + " refs/heads/master\n");
+
+		// extra loose-ref to trigger packing
+		writeLooseRef("refs/heads/loose", A);
+
+		PackRefsCommand packRefsCommand = new PackRefsCommand(diskRepo);
+		packRefsCommand.setAll(true);
+		packRefsCommand.call();
+
+		File packedRefsFile = new File(diskRepo.getCommonDirectory(), Constants.PACKED_REFS);
+		String content = read(packedRefsFile);
+		int looseIndex = content.indexOf(v1_0.name() + " refs/tags/loose");
+		int masterIndex = content.indexOf(A.name() + " refs/heads/master");
+		int otherIndex = content.indexOf(B.name() + " refs/heads/other");
+		int tagIndex = content.indexOf(v1_0.name() + " refs/tags/v1.0");
+		assertTrue(
+				"packed-refs should be sorted",
+				looseIndex < masterIndex &&
+						masterIndex < otherIndex &&
+						otherIndex < tagIndex
+		);
+	}
+
+	@Test
 	public void testFindRef_EmptyDatabase() throws IOException {
 		Ref r;
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MidxIteratorsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MidxIteratorsTest.java
new file mode 100644
index 0000000..3105423
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MidxIteratorsTest.java
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2026, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.midx;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.MidxIterator;
+import org.eclipse.jgit.junit.FakeIndexFactory;
+import org.eclipse.jgit.lib.ObjectId;
+import org.junit.Test;
+
+public class MidxIteratorsTest {
+	private final static String OID_PREFIX = "0000000000000000000000000000000000";
+
+	@Test
+	public void fromPackIndexIterator_basicIteration() {
+		PackIndex index1 = indexOf(object("000001", 500),
+				object("000003", 3000), object("000005", 1500));
+
+		MidxIterator it = MidxIterators.fromPackIndexIterator("index1", index1);
+		assertNextEntry(it, "000001", 0, 500);
+		assertNextEntry(it, "000003", 0, 3000);
+		assertNextEntry(it, "000005", 0, 1500);
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void fromPackIndexIterator_peek() {
+		PackIndex index1 = indexOf(object("000001", 500),
+				object("000003", 3000), object("000005", 1500));
+
+		MidxIterator it = MidxIterators.fromPackIndexIterator("index1", index1);
+		assertPeekEntry(it, "000001", 0, 500);
+		assertPeekEntry(it, "000001", 0, 500);
+		assertNextEntry(it, "000001", 0, 500);
+
+		assertPeekEntry(it, "000003", 0, 3000);
+		assertPeekEntry(it, "000003", 0, 3000);
+		assertNextEntry(it, "000003", 0, 3000);
+
+		assertPeekEntry(it, "000005", 0, 1500);
+		assertPeekEntry(it, "000005", 0, 1500);
+		assertNextEntry(it, "000005", 0, 1500);
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void fromPackIndexIterator_reset() {
+		PackIndex index1 = indexOf(object("000001", 500),
+				object("000003", 3000), object("000005", 1500));
+
+		MidxIterator it = MidxIterators.fromPackIndexIterator("index1", index1);
+		while (it.hasNext()) {
+			it.next();
+		}
+		it.reset();
+		assertNextEntry(it, "000001", 0, 500);
+		assertNextEntry(it, "000003", 0, 3000);
+
+		it.reset();
+		assertPeekEntry(it, "000001", 0, 500);
+	}
+
+	@Test
+	public void fromPackIndexIterator_getPackNames() {
+		PackIndex index1 = indexOf(object("000001", 500),
+				object("000003", 1500), object("000005", 3000));
+		MidxIterator it = MidxIterators.fromPackIndexIterator("index1", index1);
+		assertEquals(List.of("index1"), it.getPackNames());
+	}
+
+	@Test
+	public void fromPackIndexIterator_empty() {
+		MidxIterator it = MidxIterators.fromPackIndexIterator("index1",
+				indexOf());
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void join_basicIteration() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000003", 1, 1500)));
+
+		FakeMidxIterator itTwo = FakeMidxIterator.from("itTwo", 2,
+				List.of(new IndexEntry("000002", 0, 500),
+						new IndexEntry("000004", 1, 1500)));
+
+		MidxIterator it = MidxIterators.join(List.of(itOne, itTwo));
+		assertNextEntry(it, "000001", 0, 500);
+		assertNextEntry(it, "000002", 2, 500);
+		assertNextEntry(it, "000003", 1, 1500);
+		assertNextEntry(it, "000004", 3, 1500);
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void join_basicIteration_packIndexIterators() {
+		PackIndex idxOne = indexOf(object("000001", 500),
+				object("000003", 1500), object("000005", 3000));
+
+		PackIndex idxTwo = indexOf(object("000002", 500),
+				object("000003", 1500), object("000004", 3000));
+
+		List<MidxIterator> packIts = List.of(
+				MidxIterators.fromPackIndexIterator("index1", idxOne),
+				MidxIterators.fromPackIndexIterator("index2", idxTwo));
+		MidxIterator it = MidxIterators.join(packIts);
+		assertNextEntry(it, "000001", 0, 500);
+		assertNextEntry(it, "000002", 1, 500);
+		assertNextEntry(it, "000003", 0, 1500);
+		assertNextEntry(it, "000003", 1, 1500);
+		assertNextEntry(it, "000004", 1, 3000);
+		assertNextEntry(it, "000005", 0, 3000);
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void join_duplicates_inPackIdOrder() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2,
+				List.of(new IndexEntry("000001", 0, 501),
+						new IndexEntry("000003", 1, 1501)));
+
+		FakeMidxIterator itTwo = FakeMidxIterator.from("itTwo", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000003", 1, 1500)));
+
+		MidxIterator it = MidxIterators.join(List.of(itOne, itTwo));
+		assertNextEntry(it, "000001", 0, 501);
+		assertNextEntry(it, "000001", 2, 500);
+		assertNextEntry(it, "000003", 1, 1501);
+		assertNextEntry(it, "000003", 3, 1500);
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void join_duplicates_inPackIdOrder_shift() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 5,
+				List.of(new IndexEntry("000001", 4, 501),
+						new IndexEntry("000003", 2, 1501)));
+
+		FakeMidxIterator itTwo = FakeMidxIterator.from("itTwo", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000003", 1, 1500)));
+
+		MidxIterator it = MidxIterators.join(List.of(itOne, itTwo));
+		assertNextEntry(it, "000001", 4, 501);
+		assertNextEntry(it, "000001", 5, 500);
+		assertNextEntry(it, "000003", 2, 1501);
+		assertNextEntry(it, "000003", 6, 1500);
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void join_peek() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000003", 1, 1500)));
+
+		FakeMidxIterator itTwo = FakeMidxIterator.from("itTwo", 2,
+				List.of(new IndexEntry("000002", 0, 500),
+						new IndexEntry("000004", 1, 1500)));
+
+		MidxIterator it = MidxIterators.join(List.of(itOne, itTwo));
+		assertPeekEntry(it, "000001", 0, 500);
+		assertPeekEntry(it, "000001", 0, 500);
+		assertNextEntry(it, "000001", 0, 500);
+
+		assertPeekEntry(it, "000002", 2, 500);
+		assertPeekEntry(it, "000002", 2, 500);
+		assertNextEntry(it, "000002", 2, 500);
+
+		assertPeekEntry(it, "000003", 1, 1500);
+		assertPeekEntry(it, "000003", 1, 1500);
+		assertNextEntry(it, "000003", 1, 1500);
+
+		assertPeekEntry(it, "000004", 3, 1500);
+		assertPeekEntry(it, "000004", 3, 1500);
+		assertNextEntry(it, "000004", 3, 1500);
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void join_reset() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000003", 1, 1500)));
+
+		FakeMidxIterator itTwo = FakeMidxIterator.from("itTwo", 2,
+				List.of(new IndexEntry("000002", 0, 500),
+						new IndexEntry("000004", 1, 1500)));
+
+		MidxIterator it = MidxIterators.join(List.of(itOne, itTwo));
+		while (it.hasNext()) {
+			it.next();
+		}
+
+		it.reset();
+		assertNextEntry(it, "000001", 0, 500);
+		assertNextEntry(it, "000002", 2, 500);
+
+		it.reset();
+		assertPeekEntry(it, "000001", 0, 500);
+	}
+
+	@Test
+	public void join_getPackNames() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000003", 1, 1500)));
+
+		FakeMidxIterator itTwo = FakeMidxIterator.from("itTwo", 2,
+				List.of(new IndexEntry("000002", 0, 500),
+						new IndexEntry("000004", 1, 1500)));
+
+		MidxIterator it = MidxIterators.join(List.of(itOne, itTwo));
+		assertEquals(List.of("itOne0", "itOne1", "itTwo0", "itTwo1"),
+				it.getPackNames());
+	}
+
+	@Test
+	public void join_empty_totallyEmpty() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2, List.of());
+		FakeMidxIterator itTwo = FakeMidxIterator.from("itTwo", 2, List.of());
+
+		MidxIterator it = MidxIterators.join(List.of(itOne, itTwo));
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void join_empty_oneSideEmpty() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2, List.of());
+		FakeMidxIterator itTwo = FakeMidxIterator.from("itTwo", 2,
+				List.of(new IndexEntry("000002", 0, 500),
+						new IndexEntry("000004", 1, 1500)));
+
+		MidxIterator it = MidxIterators.join(List.of(itOne, itTwo));
+		// Even when empty, the first iterator occupies the packIds
+		assertNextEntry(it, "000002", 2, 500);
+		assertNextEntry(it, "000004", 3, 1500);
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void dedup_basicIteration() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000001", 1, 600),
+						new IndexEntry("000003", 0, 1500),
+						new IndexEntry("000003", 1, 1501)));
+		MidxIterator dedup = MidxIterators.dedup(itOne);
+		assertNextEntry(dedup, "000001", 0, 500);
+		assertNextEntry(dedup, "000003", 0, 1500);
+		assertFalse(dedup.hasNext());
+	}
+
+	@Test
+	public void dedup_peek() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000001", 1, 600),
+						new IndexEntry("000003", 0, 1500),
+						new IndexEntry("000003", 1, 1501)));
+
+		MidxIterator it = MidxIterators.dedup(itOne);
+		assertPeekEntry(it, "000001", 0, 500);
+		assertPeekEntry(it, "000001", 0, 500);
+		assertNextEntry(it, "000001", 0, 500);
+
+		assertPeekEntry(it, "000003", 0, 1500);
+		assertPeekEntry(it, "000003", 0, 1500);
+		assertNextEntry(it, "000003", 0, 1500);
+
+		assertFalse(it.hasNext());
+	}
+
+	@Test
+	public void dedup_reset() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000001", 1, 600),
+						new IndexEntry("000003", 0, 1500),
+						new IndexEntry("000003", 1, 1501),
+						new IndexEntry("000005", 0, 200),
+						new IndexEntry("000005", 1, 201)));
+
+		MidxIterator it = MidxIterators.dedup(itOne);
+		while (it.hasNext()) {
+			it.next();
+		}
+		it.reset();
+		assertNextEntry(it, "000001", 0, 500);
+		assertNextEntry(it, "000003", 0, 1500);
+
+		it.reset();
+		assertPeekEntry(it, "000001", 0, 500);
+	}
+
+	@Test
+	public void dedup_reset_sameElement() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 2,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000001", 1, 600),
+						new IndexEntry("000001", 2, 1500),
+						new IndexEntry("000001", 3, 1501),
+						new IndexEntry("000001", 4, 200),
+						new IndexEntry("000001", 5, 201)));
+
+		MidxIterator it = MidxIterators.dedup(itOne);
+		while (it.hasNext()) {
+			it.next();
+		}
+		it.reset();
+		assertNextEntry(it, "000001", 0, 500);
+
+		it.reset();
+		assertPeekEntry(it, "000001", 0, 500);
+	}
+
+	@Test
+	public void dedup_getPackNames() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 4,
+				List.of(new IndexEntry("000001", 0, 500),
+						new IndexEntry("000001", 1, 600),
+						new IndexEntry("000003", 2, 1500),
+						new IndexEntry("000003", 3, 1501)));
+		MidxIterator dedup = MidxIterators.dedup(itOne);
+		assertEquals(List.of("itOne0", "itOne1", "itOne2", "itOne3"),
+				dedup.getPackNames());
+	}
+
+	@Test
+	public void dedup_getEmpty() {
+		FakeMidxIterator itOne = FakeMidxIterator.from("itOne", 4, List.of());
+		MidxIterator dedup = MidxIterators.dedup(itOne);
+		assertFalse(dedup.hasNext());
+	}
+
+	private static void assertNextEntry(MidxIterator it, String shortOid,
+			int packId, int offset) {
+		assertTrue("expected to have more items", it.hasNext());
+		MultiPackIndex.MutableEntry e = it.next();
+		assertEquals(OID_PREFIX + shortOid, e.getObjectId().name());
+		assertEquals(packId, e.getPackId());
+		assertEquals(offset, e.getOffset());
+	}
+
+	private static void assertPeekEntry(MidxIterator it, String shortOid,
+			int packId, int offset) {
+		assertTrue(it.hasNext());
+		MultiPackIndex.MutableEntry e = it.peek();
+		assertEquals(OID_PREFIX + shortOid, e.getObjectId().name());
+		assertEquals(packId, e.getPackId());
+		assertEquals(offset, e.getOffset());
+	}
+
+	private static PackIndex indexOf(FakeIndexFactory.IndexObject... objs) {
+		return FakeIndexFactory.indexOf(Arrays.asList(objs));
+	}
+
+	private static FakeIndexFactory.IndexObject object(String name,
+			long offset) {
+		return new FakeIndexFactory.IndexObject(OID_PREFIX + name, offset);
+	}
+
+	private static class FakeMidxIterator implements MidxIterator {
+		private final List<String> packNames;
+
+		private final List<IndexEntry> entries;
+
+		private int position;
+
+		static FakeMidxIterator from(String packNameBase, int packCount,
+				List<IndexEntry> entries) {
+			List<String> packNames = IntStream.range(0, packCount)
+					.mapToObj(i -> packNameBase + i).toList();
+			return new FakeMidxIterator(packNames, entries);
+		}
+
+		private FakeMidxIterator(List<String> packNames,
+				List<IndexEntry> entries) {
+			this.entries = entries;
+			this.packNames = packNames;
+		}
+
+		@Override
+		public MultiPackIndex.MutableEntry peek() {
+			return entries.get(position).asMutableEntry();
+		}
+
+		@Override
+		public List<String> getPackNames() {
+			return packNames;
+		}
+
+		@Override
+		public boolean hasNext() {
+			return position < entries.size();
+		}
+
+		@Override
+		public MultiPackIndex.MutableEntry next() {
+			return entries.get(position++).asMutableEntry();
+		}
+
+		@Override
+		public void reset() {
+			position = 0;
+		}
+	}
+
+	record IndexEntry(String shortOid, int packId, int offset) {
+		MultiPackIndex.MutableEntry asMutableEntry() {
+			MultiPackIndex.MutableEntry entry = new MultiPackIndex.MutableEntry();
+			entry.oid.fromObjectId(ObjectId.fromString(OID_PREFIX + shortOid));
+			entry.packOffset.setValues(packId, offset);
+			return entry;
+		}
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java
index 3c7e27d..a59e874 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java
@@ -17,7 +17,6 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.util.LinkedHashMap;
 import java.util.List;
 
 import org.eclipse.jgit.internal.storage.file.PackIndex;
@@ -64,13 +63,11 @@ public void load_validFile_basic_jgit() throws Exception {
 				new FakeIndexFactory.IndexObject(
 						"0000000000000000000000000000000000000012", 1502)));
 
-		LinkedHashMap<String, PackIndex> packs = new LinkedHashMap<>(3);
-		packs.put("p1", idxOne);
-		packs.put("p2", idxTwo);
-		packs.put("p3", idxThree);
+		PackIndexMerger data = PackIndexMerger.builder().addPack("p1", idxOne)
+				.addPack("p2", idxTwo).addPack("p3", idxThree).build();
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		writer.write(NullProgressMonitor.INSTANCE, out, packs);
+		writer.write(NullProgressMonitor.INSTANCE, out, data);
 
 		MultiPackIndex midx = MultiPackIndexLoader
 				.read(new ByteArrayInputStream(out.toByteArray()));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java
index 6436e31..75a5a95 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java
@@ -11,6 +11,7 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -20,7 +21,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -81,36 +82,7 @@ public void basic_upstream() throws IOException {
 
 	@Test
 	public void basicMidx() throws IOException {
-		PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000001", 500),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000005", 12),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000010", 1500)));
-		PackIndex idxTwo = FakeIndexFactory.indexOf(List.of(
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000002", 501),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000003", 13),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000015", 1501)));
-		PackIndex idxThree = FakeIndexFactory.indexOf(List.of(
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000004", 502),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000007", 14),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000012", 1502)));
-
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
-				"p2", idxTwo, "p3", idxThree);
-		MultiPackIndexWriter writer = new MultiPackIndexWriter();
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		writer.write(NullProgressMonitor.INSTANCE, out, packs);
-
-		MultiPackIndex midx = MultiPackIndexLoader
-				.read(new ByteArrayInputStream(out.toByteArray()));
+		MultiPackIndex midx = createMultiPackIndex();
 		assertEquals(3, midx.getPackNames().length);
 		assertInIndex(midx, 0, "0000000000000000000000000000000000000001", 500);
 		assertInIndex(midx, 0, "0000000000000000000000000000000000000005", 12);
@@ -126,6 +98,7 @@ public void basicMidx() throws IOException {
 				1502);
 
 		assertNull(midx.find(ObjectId.zeroId()));
+		assertNotNull(midx.getChecksum());
 	}
 
 	@Test
@@ -140,7 +113,7 @@ public void jgit_largeOffsetChunk() throws IOException {
 						"0000000000000000000000000000000000000002", (1L << 35)),
 				new FakeIndexFactory.IndexObject(
 						"0000000000000000000000000000000000000003", 13)));
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+		PackIndexMerger packs = midxDataFor("p1", idxOne,
 				"p2", idxTwo);
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -171,7 +144,7 @@ public void jgit_largeOffset_noChunk() throws IOException {
 						"0000000000000000000000000000000000000002", 501),
 				new FakeIndexFactory.IndexObject(
 						"0000000000000000000000000000000000000003", 13)));
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+		PackIndexMerger packs = midxDataFor("p1", idxOne,
 				"p2", idxTwo);
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -208,7 +181,7 @@ public void jgit_resolve() throws IOException {
 				// Match
 				"32fe829a1c000000000000000000000000000010");
 
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+		PackIndexMerger packs = midxDataFor("p1", idxOne,
 				"p2", idxTwo);
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -252,8 +225,8 @@ public void jgit_resolve_matchLimit() throws IOException {
 				// Match
 				"32fe829a1c000000000000000000000000000010");
 
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
-				"p2", idxTwo);
+		PackIndexMerger packs = midxDataFor("r1", idxOne,
+				"r2", idxTwo);
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -287,7 +260,7 @@ public void jgit_resolve_noMatches() throws IOException {
 				"bbbbbb0000000000000000000000000000000003",
 				"32fe829a1c000000000000000000000000000010");
 
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+		PackIndexMerger packs = midxDataFor("p1", idxOne,
 				"p2", idxTwo);
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -318,7 +291,7 @@ public void jgit_resolve_noMatches_last() throws IOException {
 				"bbbbbb0000000000000000000000000000000003",
 				"32fe829a1c000000000000000000000000000010");
 
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+		PackIndexMerger packs = midxDataFor("p1", idxOne,
 				"p2", idxTwo);
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -340,11 +313,11 @@ public void jgit_resolve_empty() throws IOException {
 		PackIndex idxOne = FakeIndexFactory.indexOf(List.of());
 		PackIndex idxTwo = FakeIndexFactory.indexOf(List.of());
 
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+		PackIndexMerger data = midxDataFor("p1", idxOne,
 				"p2", idxTwo);
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		writer.write(NullProgressMonitor.INSTANCE, out, packs);
+		writer.write(NullProgressMonitor.INSTANCE, out, data);
 		MultiPackIndex midx = MultiPackIndexLoader
 				.read(new ByteArrayInputStream(out.toByteArray()));
 
@@ -356,61 +329,31 @@ public void jgit_resolve_empty() throws IOException {
 
 	@Test
 	public void jgit_findPosition() throws IOException {
-		PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000001", 500),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000005", 12),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000010", 1500)));
-		PackIndex idxTwo = FakeIndexFactory.indexOf(List.of(
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000002", 501),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000003", 13),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000015", 1501)));
-		PackIndex idxThree = FakeIndexFactory.indexOf(List.of(
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000004", 502),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000007", 14),
-				new FakeIndexFactory.IndexObject(
-						"0000000000000000000000000000000000000012", 1502)));
-
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
-				"p2", idxTwo, "p3", idxThree);
-		MultiPackIndexWriter writer = new MultiPackIndexWriter();
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		writer.write(NullProgressMonitor.INSTANCE, out, packs);
-
-		MultiPackIndex midx = MultiPackIndexLoader
-				.read(new ByteArrayInputStream(out.toByteArray()));
+		MultiPackIndex midx = createMultiPackIndex();
 		assertEquals(3, midx.getPackNames().length);
-		assertEquals(0, midx.findPosition(ObjectId
-				.fromString("0000000000000000000000000000000000000001")));
-		assertEquals(1, midx.findPosition(ObjectId
-				.fromString("0000000000000000000000000000000000000002")));
-		assertEquals(2, midx.findPosition(ObjectId
-				.fromString("0000000000000000000000000000000000000003")));
-		assertEquals(3, midx.findPosition(ObjectId
-				.fromString("0000000000000000000000000000000000000004")));
-		assertEquals(4, midx.findPosition(ObjectId
-				.fromString("0000000000000000000000000000000000000005")));
-		assertEquals(5, midx.findPosition(ObjectId
-				.fromString("0000000000000000000000000000000000000007")));
-		assertEquals(6, midx.findPosition(ObjectId
-				.fromString("0000000000000000000000000000000000000010")));
-		assertEquals(7, midx.findPosition(ObjectId
-				.fromString("0000000000000000000000000000000000000012")));
-		assertEquals(8, midx.findPosition(ObjectId
-				.fromString("0000000000000000000000000000000000000015")));
+		assertEquals(0, midx.findPosition(oid("001")));
+		assertEquals(oid("001"), midx.getObjectAt(0));
+		assertEquals(1, midx.findPosition(oid("002")));
+		assertEquals(oid("002"), midx.getObjectAt(1));
+		assertEquals(2, midx.findPosition(oid("003")));
+		assertEquals(oid("003"), midx.getObjectAt(2));
+		assertEquals(3, midx.findPosition(oid("004")));
+		assertEquals(oid("004"), midx.getObjectAt(3));
+		assertEquals(4, midx.findPosition(oid("005")));
+		assertEquals(oid("005"), midx.getObjectAt(4));
+		assertEquals(5, midx.findPosition(oid("007")));
+		assertEquals(oid("007"), midx.getObjectAt(5));
+		assertEquals(6, midx.findPosition(oid("010")));
+		assertEquals(oid("010"), midx.getObjectAt(6));
+		assertEquals(7, midx.findPosition(oid("012")));
+		assertEquals(oid("012"), midx.getObjectAt(7));
+		assertEquals(8, midx.findPosition(oid("015")));
+		assertEquals(oid("015"), midx.getObjectAt(8));
 
 		assertNull(midx.find(ObjectId.zeroId()));
 	}
 
-	@Test
-	public void jgit_getObjectCount() throws IOException {
+	private static MultiPackIndex createMultiPackIndex() throws IOException {
 		PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
 				new FakeIndexFactory.IndexObject(
 						"0000000000000000000000000000000000000001", 500),
@@ -433,14 +376,19 @@ public void jgit_getObjectCount() throws IOException {
 				new FakeIndexFactory.IndexObject(
 						"0000000000000000000000000000000000000012", 1502)));
 
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+		PackIndexMerger data = midxDataFor("p1", idxOne,
 				"p2", idxTwo, "p3", idxThree);
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		writer.write(NullProgressMonitor.INSTANCE, out, packs);
+		writer.write(NullProgressMonitor.INSTANCE, out, data);
 
-		MultiPackIndex midx = MultiPackIndexLoader
+		return MultiPackIndexLoader
 				.read(new ByteArrayInputStream(out.toByteArray()));
+	}
+
+	@Test
+	public void jgit_getObjectCount() throws IOException {
+		MultiPackIndex midx = createMultiPackIndex();
 		assertEquals(9, midx.getObjectCount());
 	}
 
@@ -449,17 +397,235 @@ public void jgit_getObjectCount_emtpy() throws IOException {
 		PackIndex idxOne = FakeIndexFactory.indexOf(List.of());
 		PackIndex idxTwo = FakeIndexFactory.indexOf(List.of());
 
-		LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+		PackIndexMerger data = midxDataFor("p1", idxOne,
 				"p2", idxTwo);
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		writer.write(NullProgressMonitor.INSTANCE, out, packs);
+		writer.write(NullProgressMonitor.INSTANCE, out, data);
 		MultiPackIndex midx = MultiPackIndexLoader
 				.read(new ByteArrayInputStream(out.toByteArray()));
 
 		assertEquals(0, midx.getObjectCount());
 	}
 
+	@Test
+	public void jgit_findBitmapPosition() throws IOException {
+		PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000001", 500),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000005", 12),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000010", 1500)));
+		PackIndex idxTwo = FakeIndexFactory.indexOf(List.of(
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000002", 501),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000003", 13),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000015", 1501)));
+		PackIndex idxThree = FakeIndexFactory.indexOf(List.of(
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000004", 502),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000007", 14),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000012", 1502)));
+
+		PackIndexMerger data = midxDataFor("p1", idxOne,
+				"p2", idxTwo, "p3", idxThree);
+		MultiPackIndexWriter writer = new MultiPackIndexWriter();
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		writer.write(NullProgressMonitor.INSTANCE, out, data);
+
+		MultiPackIndex midx = MultiPackIndexLoader
+				.read(new ByteArrayInputStream(out.toByteArray()));
+		MultiPackIndex.PackOffset packOffset;
+		packOffset = midx.find(ObjectId
+				.fromString("0000000000000000000000000000000000000005"));
+		assertEquals(0, midx.findBitmapPosition(packOffset));
+		packOffset = midx.find(ObjectId
+				.fromString("0000000000000000000000000000000000000001"));
+		assertEquals(1, midx.findBitmapPosition(packOffset));
+		packOffset = midx.find(ObjectId
+				.fromString("0000000000000000000000000000000000000010"));
+		assertEquals(2, midx.findBitmapPosition(packOffset));
+		packOffset = midx.find(ObjectId
+				.fromString("0000000000000000000000000000000000000003"));
+		assertEquals(3, midx.findBitmapPosition(packOffset));
+		packOffset = midx.find(ObjectId
+				.fromString("0000000000000000000000000000000000000002"));
+		assertEquals(4, midx.findBitmapPosition(packOffset));
+		packOffset = midx.find(ObjectId
+				.fromString("0000000000000000000000000000000000000015"));
+		assertEquals(5, midx.findBitmapPosition(packOffset));
+		packOffset = midx.find(ObjectId
+				.fromString("0000000000000000000000000000000000000007"));
+		assertEquals(6, midx.findBitmapPosition(packOffset));
+		packOffset = midx.find(ObjectId
+				.fromString("0000000000000000000000000000000000000004"));
+		assertEquals(7, midx.findBitmapPosition(packOffset));
+		packOffset = midx.find(ObjectId
+				.fromString("0000000000000000000000000000000000000012"));
+		assertEquals(8, midx.findBitmapPosition(packOffset));
+	}
+
+	@Test
+	public void jgit_getObjectAtBitmapPosition() throws IOException {
+		PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000001", 500),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000005", 12),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000010", 1500)));
+		PackIndex idxTwo = FakeIndexFactory.indexOf(List.of(
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000002", 501),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000003", 13),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000015", 1501)));
+		PackIndex idxThree = FakeIndexFactory.indexOf(List.of(
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000004", 502),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000007", 14),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000012", 1502)));
+
+		PackIndexMerger data = midxDataFor("p1", idxOne,
+				"p2", idxTwo, "p3", idxThree);
+		MultiPackIndexWriter writer = new MultiPackIndexWriter();
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		writer.write(NullProgressMonitor.INSTANCE, out, data);
+
+		MultiPackIndex midx = MultiPackIndexLoader
+				.read(new ByteArrayInputStream(out.toByteArray()));
+		assertEquals(
+				ObjectId.fromString("0000000000000000000000000000000000000005"),
+				midx.getObjectAtBitmapPosition(0));
+		assertEquals(
+				ObjectId.fromString("0000000000000000000000000000000000000001"),
+				midx.getObjectAtBitmapPosition(1));
+		assertEquals(
+				ObjectId.fromString("0000000000000000000000000000000000000010"),
+				midx.getObjectAtBitmapPosition(2));
+		assertEquals(
+				ObjectId.fromString("0000000000000000000000000000000000000003"),
+				midx.getObjectAtBitmapPosition(3));
+		assertEquals(
+				ObjectId.fromString("0000000000000000000000000000000000000002"),
+				midx.getObjectAtBitmapPosition(4));
+		assertEquals(
+				ObjectId.fromString("0000000000000000000000000000000000000015"),
+				midx.getObjectAtBitmapPosition(5));
+		assertEquals(
+				ObjectId.fromString("0000000000000000000000000000000000000007"),
+				midx.getObjectAtBitmapPosition(6));
+		assertEquals(
+				ObjectId.fromString("0000000000000000000000000000000000000004"),
+				midx.getObjectAtBitmapPosition(7));
+		assertEquals(
+				ObjectId.fromString("0000000000000000000000000000000000000012"),
+				midx.getObjectAtBitmapPosition(8));
+	}
+
+	@Test
+	public void jgit_iterator() throws IOException {
+		MultiPackIndex midx = createMultiPackIndex();
+		assertEquals(3, midx.getPackNames().length);
+		Iterator<MultiPackIndex.MutableEntry> iterator = midx.iterator();
+		assertNextEntry(iterator, "0000000000000000000000000000000000000001", 0,
+				500);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000002", 1,
+				501);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000003", 1,
+				13);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000004", 2,
+				502);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000005", 0,
+				12);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000007", 2,
+				14);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000010", 0,
+				1500);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000012", 2,
+				1502);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000015", 1,
+				1501);
+		assertFalse(iterator.hasNext());
+	}
+
+	@Test
+	public void jgit_iterator_emtpy() throws IOException {
+		PackIndex idxOne = FakeIndexFactory.indexOf(List.of());
+		PackIndex idxTwo = FakeIndexFactory.indexOf(List.of());
+
+		PackIndexMerger data = midxDataFor("p1", idxOne,
+				"p2", idxTwo);
+		MultiPackIndexWriter writer = new MultiPackIndexWriter();
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		writer.write(NullProgressMonitor.INSTANCE, out, data);
+		MultiPackIndex midx = MultiPackIndexLoader
+				.read(new ByteArrayInputStream(out.toByteArray()));
+
+		assertFalse(midx.iterator().hasNext());
+	}
+
+	@Test
+	public void jgit_iterator_peek() throws IOException {
+		PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000001", 500),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000005", 12),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000010", 1500)));
+		PackIndex idxTwo = FakeIndexFactory.indexOf(List.of(
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000002", 501),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000003", 13),
+				new FakeIndexFactory.IndexObject(
+						"0000000000000000000000000000000000000015", 1501)));
+
+		PackIndexMerger data = midxDataFor("p1", idxOne,
+				"p2", idxTwo);
+		MultiPackIndexWriter writer = new MultiPackIndexWriter();
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		writer.write(NullProgressMonitor.INSTANCE, out, data);
+
+		MultiPackIndex midx = MultiPackIndexLoader
+				.read(new ByteArrayInputStream(out.toByteArray()));
+		assertEquals(2, midx.getPackNames().length);
+		MultiPackIndex.MidxIterator iterator = midx.iterator();
+		assertNextEntry(iterator, "0000000000000000000000000000000000000001", 0,
+				500);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000002", 1,
+				501);
+		assertTrue(iterator.hasNext());
+		assertEntry(iterator.peek(), "0000000000000000000000000000000000000003",
+				1, 13);
+		assertEntry(iterator.peek(), "0000000000000000000000000000000000000003",
+				1, 13);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000003", 1,
+				13);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000005", 0,
+				12);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000010", 0,
+				1500);
+		assertNextEntry(iterator, "0000000000000000000000000000000000000015", 1,
+				1501);
+		assertFalse(iterator.hasNext());
+	}
+
+	@Test
+	public void jgit_iterator_getPackNames() throws IOException {
+		MultiPackIndex midx = createMultiPackIndex();
+		assertEquals(3, midx.iterator().getPackNames().size());
+	}
+
 	private static PackIndex indexWith(String... oids) {
 		List<FakeIndexFactory.IndexObject> idxObjs = new ArrayList<>(
 				oids.length);
@@ -481,20 +647,35 @@ private static void assertInIndex(MultiPackIndex midx, int expectedPackId,
 		assertEquals(expectedOffset, packOffset.getOffset());
 	}
 
-	private static LinkedHashMap<String, PackIndex> orderedMapOf(String s1,
-			PackIndex pi1, String s2, PackIndex pi2) {
-		LinkedHashMap<String, PackIndex> map = new LinkedHashMap<>(2);
-		map.put(s1, pi1);
-		map.put(s2, pi2);
-		return map;
+	private static void assertNextEntry(
+			Iterator<MultiPackIndex.MutableEntry> it, String oid,
+			int expectedPackId, long expectedOffset) {
+		assertTrue(it.hasNext());
+		assertEntry(it.next(), oid, expectedPackId, expectedOffset);
 	}
 
-	private static LinkedHashMap<String, PackIndex> orderedMapOf(String s1,
+	private static void assertEntry(MultiPackIndex.MutableEntry e, String oid,
+			int expectedPackId, long expectedOffset) {
+		assertEquals(oid, e.oid.name());
+		assertEquals(expectedPackId, e.packOffset.getPackId());
+		assertEquals(expectedOffset, e.packOffset.getOffset());
+	}
+
+	private static PackIndexMerger midxDataFor(String s1, PackIndex pi1,
+			String s2, PackIndex pi2) {
+		return PackIndexMerger.builder().addPack(s1, pi1).addPack(s2, pi2)
+				.build();
+	}
+
+	private static PackIndexMerger midxDataFor(String s1,
 			PackIndex pi1, String s2, PackIndex pi2, String s3, PackIndex pi3) {
-		LinkedHashMap<String, PackIndex> map = new LinkedHashMap<>(2);
-		map.put(s1, pi1);
-		map.put(s2, pi2);
-		map.put(s3, pi3);
-		return map;
+		return PackIndexMerger.builder().addPack(s1, pi1).addPack(s2, pi2)
+				.addPack(s3, pi3).build();
+	}
+
+	private static ObjectId oid(String last3chars) {
+		assertEquals(3, last3chars.length());
+		return ObjectId.fromString(
+				"0000000000000000000000000000000000000" + last3chars);
 	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java
index 9b085a3..1ca8aaf 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java
@@ -10,6 +10,7 @@
 package org.eclipse.jgit.internal.storage.midx;
 
 import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_BITMAPPEDPACKS;
 import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_LARGEOFFSETS;
 import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OBJECTOFFSETS;
 import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDFANOUT;
@@ -22,7 +23,6 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.LinkedHashMap;
 import java.util.List;
 
 import org.eclipse.jgit.internal.storage.file.PackIndex;
@@ -46,29 +46,31 @@ public void write_allSmallOffsets() throws IOException {
 				object("0000000000000000000000000000000000000004", 1500),
 				object("0000000000000000000000000000000000000006", 3000));
 
-		LinkedHashMap<String, PackIndex> data = new LinkedHashMap<>();
-		data.put("packname1", index1);
-		data.put("packname2", index2);
+		PackIndexMerger data = PackIndexMerger.builder()
+				.addPack("packname1", index1).addPack("packname2", index2)
+				.build();
 
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		writer.write(NullProgressMonitor.INSTANCE, out, data);
 		// header (12 bytes)
-		// + chunkHeader (6 * 12 bytes)
+		// + chunkHeader (7 * 12 bytes)
 		// + fanout table (256 * 4 bytes)
 		// + OIDs (6 * 20 bytes)
 		// + (pack, offset) pairs (6 * 8)
 		// + RIDX (6 * 4 bytes)
+		// + bitmap pack segments (2 * 8)
 		// + packfile names (2 * 10)
 		// + checksum (20)
-		assertEquals(1340, out.size());
+		assertEquals(1368, out.size());
 		List<Integer> chunkIds = readChunkIds(out);
-		assertEquals(5, chunkIds.size());
+		assertEquals(6, chunkIds.size());
 		assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT));
 		assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP));
 		assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS));
 		assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX));
-		assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
+		assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_BITMAPPEDPACKS));
+		assertEquals(5, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
 	}
 
 	@Test
@@ -82,29 +84,31 @@ public void write_smallOffset_limit() throws IOException {
 				object("0000000000000000000000000000000000000002", 500),
 				object("0000000000000000000000000000000000000004", 1500),
 				object("0000000000000000000000000000000000000006", 3000));
-		LinkedHashMap<String, PackIndex> data = new LinkedHashMap<>(2);
-		data.put("packname1", index1);
-		data.put("packname2", index2);
+		PackIndexMerger data = PackIndexMerger.builder()
+				.addPack("packname1", index1).addPack("packname2", index2)
+				.build();
 
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		writer.write(NullProgressMonitor.INSTANCE, out, data);
 		// header (12 bytes)
-		// + chunkHeader (6 * 12 bytes)
+		// + chunkHeader (7 * 12 bytes)
 		// + fanout table (256 * 4 bytes)
 		// + OIDs (6 * 20 bytes)
 		// + (pack, offset) pairs (6 * 8)
 		// + RIDX (6 * 4 bytes)
+		// + bitmap pack segments (2 * 8)
 		// + packfile names (2 * 10)
 		// + checksum (20)
-		assertEquals(1340, out.size());
+		assertEquals(1368, out.size());
 		List<Integer> chunkIds = readChunkIds(out);
-		assertEquals(5, chunkIds.size());
+		assertEquals(6, chunkIds.size());
 		assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT));
 		assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP));
 		assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS));
 		assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX));
-		assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
+		assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_BITMAPPEDPACKS));
+		assertEquals(5, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
 	}
 
 	@Test
@@ -117,32 +121,34 @@ public void write_largeOffset() throws IOException {
 				object("0000000000000000000000000000000000000002", 500),
 				object("0000000000000000000000000000000000000004", 1500),
 				object("0000000000000000000000000000000000000006", 3000));
-		LinkedHashMap<String, PackIndex> data = new LinkedHashMap<>(2);
-		data.put("bbbbbbbbb", index1);
-		data.put("aaaaaaaaa", index2);
+		PackIndexMerger data = PackIndexMerger.builder()
+				.addPack("bbbbbbbbb", index1).addPack("aaaaaaaaa", index2)
+				.build();
 
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		MultiPackIndexWriter.Result result = writer
 				.write(NullProgressMonitor.INSTANCE, out, data);
 		// header (12 bytes)
-		// + chunkHeader (7 * 12 bytes)
+		// + chunkHeader (8 * 12 bytes)
 		// + fanout table (256 * 4 bytes)
 		// + OIDs (6 * 20 bytes)
 		// + (pack, offset) pairs (6 * 8)
 		// + (large-offset) (1 * 8)
 		// + RIDX (6 * 4 bytes)
+		// + bitmap pack segments (2 * 8)
 		// + packfile names (2 * 10)
 		// + checksum (20)
-		assertEquals(1360, out.size());
+		assertEquals(1388, out.size());
 		List<Integer> chunkIds = readChunkIds(out);
-		assertEquals(6, chunkIds.size());
+		assertEquals(7, chunkIds.size());
 		assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT));
 		assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP));
 		assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS));
 		assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_LARGEOFFSETS));
 		assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX));
-		assertEquals(5, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
+		assertEquals(5, chunkIds.indexOf(MIDX_CHUNKID_BITMAPPEDPACKS));
+		assertEquals(6, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
 
 		assertEquals("bbbbbbbbb", result.packNames().get(0));
 		assertEquals("aaaaaaaaa", result.packNames().get(1));
@@ -152,20 +158,20 @@ public void write_largeOffset() throws IOException {
 	public void jgit_emptyMidx() throws IOException {
 		PackIndex idxOne = FakeIndexFactory.indexOf(List.of());
 		PackIndex idxTwo = FakeIndexFactory.indexOf(List.of());
-		LinkedHashMap<String, PackIndex> packs = new LinkedHashMap<>(2);
-		packs.put("p1", idxOne);
-		packs.put("p2", idxTwo);
+		PackIndexMerger packs = PackIndexMerger.builder().addPack("p1", idxOne)
+				.addPack("p2", idxTwo).build();
 		MultiPackIndexWriter writer = new MultiPackIndexWriter();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		writer.write(NullProgressMonitor.INSTANCE, out, packs);
 		List<Integer> chunkIds = readChunkIds(out);
-		assertEquals(1134, out.size());
-		assertEquals(5, chunkIds.size());
+		assertEquals(1162, out.size());
+		assertEquals(6, chunkIds.size());
 		assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT));
 		assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP));
 		assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS));
 		assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX));
-		assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
+		assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_BITMAPPEDPACKS));
+		assertEquals(5, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
 	}
 
 	private List<Integer> readChunkIds(ByteArrayOutputStream out) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java
index 0eafdaf..971087e 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java
@@ -9,23 +9,28 @@
  */
 package org.eclipse.jgit.internal.storage.midx;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 
 import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.MutableEntry;
 import org.eclipse.jgit.junit.FakeIndexFactory;
 import org.eclipse.jgit.junit.FakeIndexFactory.IndexObject;
+import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.junit.Test;
 
 public class PackIndexMergerTest {
 
 	@Test
-	public void rawIterator_noDuplicates() {
+	public void bySha1Iterator_noDuplicates() {
 		PackIndex idxOne = indexOf(
 				oidOffset("0000000000000000000000000000000000000001", 500),
 				oidOffset("0000000000000000000000000000000000000005", 12),
@@ -38,12 +43,12 @@ public void rawIterator_noDuplicates() {
 				oidOffset("0000000000000000000000000000000000000004", 502),
 				oidOffset("0000000000000000000000000000000000000007", 14),
 				oidOffset("0000000000000000000000000000000000000012", 1502));
-		PackIndexMerger merger = new PackIndexMerger(
-				orderedMapOf("p1", idxOne, "p2", idxTwo, "p3", idxThree));
+		PackIndexMerger merger = createMergerFor("p1", idxOne, "p2", idxTwo,
+				"p3", idxThree);
 		assertEquals(9, merger.getUniqueObjectCount());
 		assertEquals(3, merger.getPackCount());
 		assertFalse(merger.needsLargeOffsetsChunk());
-		Iterator<PackIndexMerger.MidxMutableEntry> it = merger.rawIterator();
+		Iterator<MutableEntry> it = merger.bySha1Iterator();
 		assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500);
 		assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 501);
 		assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 13);
@@ -60,92 +65,31 @@ public void rawIterator_noDuplicates() {
 	}
 
 	@Test
-	public void rawIterator_noDuplicates_honorPackOrder() {
+	public void bySha1Iterator_withDuplicates() {
 		PackIndex idxOne = indexOf(
 				oidOffset("0000000000000000000000000000000000000001", 500),
-				oidOffset("0000000000000000000000000000000000000005", 12),
 				oidOffset("0000000000000000000000000000000000000010", 1500));
 		PackIndex idxTwo = indexOf(
 				oidOffset("0000000000000000000000000000000000000002", 501),
 				oidOffset("0000000000000000000000000000000000000003", 13),
+				oidOffset("0000000000000000000000000000000000000005", 800),
 				oidOffset("0000000000000000000000000000000000000015", 1501));
 		PackIndex idxThree = indexOf(
 				oidOffset("0000000000000000000000000000000000000004", 502),
+				oidOffset("0000000000000000000000000000000000000005", 12),
 				oidOffset("0000000000000000000000000000000000000007", 14),
 				oidOffset("0000000000000000000000000000000000000012", 1502));
-        PackIndexMerger merger = new PackIndexMerger(
-				orderedMapOf("p3", idxThree, "p2", idxTwo, "p1", idxOne));
+		PackIndexMerger merger = createMergerFor("p1", idxOne, "p2", idxTwo,
+				"p3", idxThree);
 		assertEquals(9, merger.getUniqueObjectCount());
 		assertEquals(3, merger.getPackCount());
 		assertFalse(merger.needsLargeOffsetsChunk());
-		Iterator<PackIndexMerger.MidxMutableEntry> it = merger.rawIterator();
-		assertNextEntry(it, "0000000000000000000000000000000000000001", 2, 500);
-		assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 501);
-		assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 13);
-		assertNextEntry(it, "0000000000000000000000000000000000000004", 0, 502);
-		assertNextEntry(it, "0000000000000000000000000000000000000005", 2, 12);
-		assertNextEntry(it, "0000000000000000000000000000000000000007", 0, 14);
-		assertNextEntry(it, "0000000000000000000000000000000000000010", 2,
-				1500);
-		assertNextEntry(it, "0000000000000000000000000000000000000012", 0,
-				1502);
-		assertNextEntry(it, "0000000000000000000000000000000000000015", 1,
-				1501);
-		assertFalse(it.hasNext());
-	}
-
-	@Test
-	public void rawIterator_allDuplicates() {
-		PackIndex idxOne = indexOf(
-				oidOffset("0000000000000000000000000000000000000001", 500),
-				oidOffset("0000000000000000000000000000000000000005", 12),
-				oidOffset("0000000000000000000000000000000000000010", 1500));
-		PackIndexMerger merger = new PackIndexMerger(
-				orderedMapOf("p1", idxOne, "p2", idxOne, "p3", idxOne));
-		assertEquals(3, merger.getUniqueObjectCount());
-		assertEquals(3, merger.getPackCount());
-		assertFalse(merger.needsLargeOffsetsChunk());
-		Iterator<PackIndexMerger.MidxMutableEntry> it = merger.rawIterator();
-		assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500);
-		assertNextEntry(it, "0000000000000000000000000000000000000001", 1, 500);
-		assertNextEntry(it, "0000000000000000000000000000000000000001", 2, 500);
-		assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12);
-		assertNextEntry(it, "0000000000000000000000000000000000000005", 1, 12);
-		assertNextEntry(it, "0000000000000000000000000000000000000005", 2, 12);
-		assertNextEntry(it, "0000000000000000000000000000000000000010", 0,
-				1500);
-		assertNextEntry(it, "0000000000000000000000000000000000000010", 1,
-				1500);
-		assertNextEntry(it, "0000000000000000000000000000000000000010", 2,
-				1500);
-		assertFalse(it.hasNext());
-	}
-
-	@Test
-	public void bySha1Iterator_noDuplicates() {
-		PackIndex idxOne = indexOf(
-				oidOffset("0000000000000000000000000000000000000001", 500),
-				oidOffset("0000000000000000000000000000000000000005", 12),
-				oidOffset("0000000000000000000000000000000000000010", 1500));
-		PackIndex idxTwo = indexOf(
-				oidOffset("0000000000000000000000000000000000000002", 501),
-				oidOffset("0000000000000000000000000000000000000003", 13),
-				oidOffset("0000000000000000000000000000000000000015", 1501));
-		PackIndex idxThree = indexOf(
-				oidOffset("0000000000000000000000000000000000000004", 502),
-				oidOffset("0000000000000000000000000000000000000007", 14),
-				oidOffset("0000000000000000000000000000000000000012", 1502));
-		PackIndexMerger merger = new PackIndexMerger(
-				orderedMapOf("p1", idxOne, "p2", idxTwo, "p3", idxThree));
-		assertEquals(9, merger.getUniqueObjectCount());
-		assertEquals(3, merger.getPackCount());
-		assertFalse(merger.needsLargeOffsetsChunk());
-		Iterator<PackIndexMerger.MidxMutableEntry> it = merger.bySha1Iterator();
+		Iterator<MutableEntry> it = merger.bySha1Iterator();
 		assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500);
 		assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 501);
 		assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 13);
 		assertNextEntry(it, "0000000000000000000000000000000000000004", 2, 502);
-		assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12);
+		assertNextEntry(it, "0000000000000000000000000000000000000005", 1, 800);
 		assertNextEntry(it, "0000000000000000000000000000000000000007", 2, 14);
 		assertNextEntry(it, "0000000000000000000000000000000000000010", 0,
 				1500);
@@ -162,12 +106,12 @@ public void bySha1Iterator_allDuplicates() {
 				oidOffset("0000000000000000000000000000000000000001", 500),
 				oidOffset("0000000000000000000000000000000000000005", 12),
 				oidOffset("0000000000000000000000000000000000000010", 1500));
-		PackIndexMerger merger = new PackIndexMerger(
-				orderedMapOf("p1", idxOne, "p2", idxOne, "p3", idxOne));
+		PackIndexMerger merger = createMergerFor("p1", idxOne, "p2", idxOne,
+				"p3", idxOne);
 		assertEquals(3, merger.getUniqueObjectCount());
 		assertEquals(3, merger.getPackCount());
 		assertFalse(merger.needsLargeOffsetsChunk());
-		Iterator<PackIndexMerger.MidxMutableEntry> it = merger.bySha1Iterator();
+		Iterator<MutableEntry> it = merger.bySha1Iterator();
 		assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500);
 		assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12);
 		assertNextEntry(it, "0000000000000000000000000000000000000010", 0,
@@ -186,12 +130,12 @@ public void bySha1Iterator_differentIndexSizes() {
 				oidOffset("0000000000000000000000000000000000000004", 500),
 				oidOffset("0000000000000000000000000000000000000007", 12),
 				oidOffset("0000000000000000000000000000000000000012", 1500));
-		PackIndexMerger merger = new PackIndexMerger(
-				orderedMapOf("p1", idxOne, "p2", idxTwo, "p3", idxThree));
+		PackIndexMerger merger = createMergerFor("p1", idxOne, "p2", idxTwo,
+				"p3", idxThree);
 		assertEquals(6, merger.getUniqueObjectCount());
 		assertEquals(3, merger.getPackCount());
 		assertFalse(merger.needsLargeOffsetsChunk());
-		Iterator<PackIndexMerger.MidxMutableEntry> it = merger.bySha1Iterator();
+		Iterator<MutableEntry> it = merger.bySha1Iterator();
 		assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 500);
 		assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 12);
 		assertNextEntry(it, "0000000000000000000000000000000000000004", 2, 500);
@@ -204,8 +148,46 @@ public void bySha1Iterator_differentIndexSizes() {
 	}
 
 	@Test
+	public void bySha1Iterator_withAnotherMidx() throws IOException {
+		PackIndex idxOne = indexOf(
+				oidOffset("0000000000000000000000000000000000000010", 1500));
+		PackIndex idxTwo = indexOf(
+				oidOffset("0000000000000000000000000000000000000002", 500),
+				oidOffset("0000000000000000000000000000000000000003", 12));
+		PackIndex idxThree = indexOf(
+				oidOffset("0000000000000000000000000000000000000004", 500),
+				oidOffset("0000000000000000000000000000000000000007", 12),
+				oidOffset("0000000000000000000000000000000000000012", 1500));
+		MultiPackIndex midx = midxOf("one", idxOne, "two", idxTwo, "three",
+				idxThree);
+
+		PackIndex idxFour = indexOf(
+				oidOffset("0000000000000000000000000000000000000001", 12),
+				oidOffset("0000000000000000000000000000000000000007", 600),
+				oidOffset("0000000000000000000000000000000000000015", 300));
+
+		PackIndexMerger merger = PackIndexMerger.builder()
+				.addMidx(midx.iterator()).addPack("four", idxFour).build();
+		assertEquals(8, merger.getUniqueObjectCount());
+		assertEquals(4, merger.getPackCount());
+		assertFalse(merger.needsLargeOffsetsChunk());
+		Iterator<MutableEntry> it = merger.bySha1Iterator();
+		assertNextEntry(it, "0000000000000000000000000000000000000001", 3, 12);
+		assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 500);
+		assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 12);
+		assertNextEntry(it, "0000000000000000000000000000000000000004", 2, 500);
+		assertNextEntry(it, "0000000000000000000000000000000000000007", 2, 12);
+		assertNextEntry(it, "0000000000000000000000000000000000000010", 0,
+				1500);
+		assertNextEntry(it, "0000000000000000000000000000000000000012", 2,
+				1500);
+		assertNextEntry(it, "0000000000000000000000000000000000000015", 3, 300);
+		assertFalse(it.hasNext());
+	}
+
+	@Test
 	public void merger_noIndexes() {
-        PackIndexMerger merger = new PackIndexMerger(new LinkedHashMap<>());
+		PackIndexMerger merger = PackIndexMerger.builder().build();
 		assertEquals(0, merger.getUniqueObjectCount());
 		assertFalse(merger.needsLargeOffsetsChunk());
 		assertTrue(merger.getPackNames().isEmpty());
@@ -215,8 +197,8 @@ public void merger_noIndexes() {
 
 	@Test
 	public void merger_emptyIndexes() {
-		PackIndexMerger merger = new PackIndexMerger(
-                orderedMapOf("p1", indexOf(), "p2", indexOf()));
+		PackIndexMerger merger = createMergerFor("p1", indexOf(), "p2",
+				indexOf());
 		assertEquals(0, merger.getUniqueObjectCount());
 		assertFalse(merger.needsLargeOffsetsChunk());
 		assertEquals(2, merger.getPackNames().size());
@@ -231,8 +213,7 @@ public void bySha1Iterator_largeOffsets_needsChunk() {
 				oidOffset("0000000000000000000000000000000000000004", 12));
 		PackIndex idx2 = indexOf(oidOffset(
 				"0000000000000000000000000000000000000003", (1L << 31) + 10));
-		PackIndexMerger merger = new PackIndexMerger(
-                orderedMapOf("p1", idx1, "p2", idx2));
+		PackIndexMerger merger = createMergerFor("p1", idx1, "p2", idx2);
 		assertTrue(merger.needsLargeOffsetsChunk());
 		assertEquals(2, merger.getOffsetsOver31BitsCount());
 		assertEquals(3, merger.getUniqueObjectCount());
@@ -247,18 +228,75 @@ public void bySha1Iterator_largeOffsets_noChunk() {
 				oidOffset("0000000000000000000000000000000000000004", 12));
 		PackIndex idx2 = indexOf(oidOffset(
 				"0000000000000000000000000000000000000003", (1L << 31) + 10));
-		PackIndexMerger merger = new PackIndexMerger(
-                orderedMapOf("p1", idx1, "p2", idx2));
+		PackIndexMerger merger = createMergerFor("p1", idx1, "p2", idx2);
 		assertFalse(merger.needsLargeOffsetsChunk());
 		assertEquals(2, merger.getOffsetsOver31BitsCount());
 		assertEquals(3, merger.getUniqueObjectCount());
 	}
 
-	private static void assertNextEntry(
-			Iterator<PackIndexMerger.MidxMutableEntry> it, String oid,
+	@Test
+	public void getObjectsPerPack_noDuplicates() {
+		PackIndex idxOne = indexOf(
+				oidOffset("0000000000000000000000000000000000000001", 500),
+				oidOffset("0000000000000000000000000000000000000005", 12),
+				oidOffset("0000000000000000000000000000000000000010", 1500));
+		PackIndex idxTwo = indexOf(
+				oidOffset("0000000000000000000000000000000000000002", 501),
+				oidOffset("0000000000000000000000000000000000000003", 13),
+				oidOffset("0000000000000000000000000000000000000015", 1501));
+		PackIndex idxThree = indexOf(
+				oidOffset("0000000000000000000000000000000000000004", 502),
+				oidOffset("0000000000000000000000000000000000000007", 14),
+				oidOffset("0000000000000000000000000000000000000012", 1502));
+		PackIndexMerger merger = createMergerFor("p1", idxOne, "p2", idxTwo,
+				"p3", idxThree);
+		assertArrayEquals(new int[] { 3, 3, 3 }, merger.getObjectsPerPack());
+	}
+
+	@Test
+	public void getObjectsPerPack_differentIndexSizes() {
+		PackIndex idxOne = indexOf(
+				oidOffset("0000000000000000000000000000000000000010", 1500));
+		PackIndex idxTwo = indexOf(
+				oidOffset("0000000000000000000000000000000000000002", 500),
+				oidOffset("0000000000000000000000000000000000000003", 12));
+		PackIndex idxThree = indexOf(
+				oidOffset("0000000000000000000000000000000000000004", 500),
+				oidOffset("0000000000000000000000000000000000000007", 12),
+				oidOffset("0000000000000000000000000000000000000012", 1500));
+		PackIndexMerger merger = createMergerFor("p1", idxOne, "p2", idxTwo,
+				"p3", idxThree);
+		assertArrayEquals(new int[] { 1, 2, 3 }, merger.getObjectsPerPack());
+	}
+
+	@Test
+	public void getObjectsPerPack_allDuplicates() {
+		PackIndex idxOne = indexOf(
+				oidOffset("0000000000000000000000000000000000000001", 500),
+				oidOffset("0000000000000000000000000000000000000005", 12),
+				oidOffset("0000000000000000000000000000000000000010", 1500));
+		PackIndexMerger merger = createMergerFor("p1", idxOne, "p2", idxOne,
+				"p3", idxOne);
+		assertArrayEquals(new int[] { 3, 0, 0 }, merger.getObjectsPerPack());
+	}
+
+	@Test
+	public void getObjectsPerPack_noIndexes() {
+		PackIndexMerger merger = PackIndexMerger.builder().build();
+		assertArrayEquals(new int[] {}, merger.getObjectsPerPack());
+	}
+
+	@Test
+	public void getObjectsPerPack_emptyIndexes() {
+		PackIndexMerger merger = createMergerFor("p1", indexOf(), "p2",
+				indexOf());
+		assertArrayEquals(new int[] { 0, 0 }, merger.getObjectsPerPack());
+	}
+
+	private static void assertNextEntry(Iterator<MutableEntry> it, String oid,
 			int packId, long offset) {
 		assertTrue(it.hasNext());
-		PackIndexMerger.MidxMutableEntry e = it.next();
+		MutableEntry e = it.next();
 		assertEquals(oid, e.getObjectId().name());
 		assertEquals(packId, e.getPackId());
 		assertEquals(offset, e.getOffset());
@@ -272,21 +310,28 @@ private static PackIndex indexOf(IndexObject... objs) {
 		return FakeIndexFactory.indexOf(Arrays.asList(objs));
 	}
 
-    private static LinkedHashMap<String, PackIndex> orderedMapOf(String s1,
-                                                                 PackIndex pi1, String s2, PackIndex pi2) {
-        LinkedHashMap map = new LinkedHashMap(3);
-        map.put(s1, pi1);
-        map.put(s2, pi2);
-        return map;
-    }
+	private static MultiPackIndex midxOf(String s1, PackIndex idx1, String s2,
+			PackIndex idx2, String s3, PackIndex idx3) throws IOException {
+		PackIndexMerger merger = createMergerFor(s1, idx1, s2, idx2, s3, idx3);
+		MultiPackIndexWriter w = new MultiPackIndexWriter();
 
-	private static LinkedHashMap<String, PackIndex> orderedMapOf(String s1,
-                                                                 PackIndex pi1, String s2, PackIndex pi2, String s3, PackIndex pi3) {
-        LinkedHashMap map = new LinkedHashMap(3);
-        map.put(s1, pi1);
-        map.put(s2, pi2);
-        map.put(s3, pi3);
-        return map;
-    }
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		w.write(NullProgressMonitor.INSTANCE, out, merger);
+
+		ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+		return MultiPackIndexLoader.read(in);
+	}
+
+	private static PackIndexMerger createMergerFor(String s1, PackIndex pi1,
+			String s2, PackIndex pi2) {
+		return PackIndexMerger.builder().addPack(s1, pi1).addPack(s2, pi2)
+				.build();
+	}
+
+	private static PackIndexMerger createMergerFor(String s1, PackIndex pi1,
+			String s2, PackIndex pi2, String s3, PackIndex pi3) {
+		return PackIndexMerger.builder().addPack(s1, pi1).addPack(s2, pi2)
+				.addPack(s3, pi3).build();
+	}
 
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java
deleted file mode 100644
index 0b3ccac..0000000
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2025, Google LLC
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-package org.eclipse.jgit.internal.storage.midx;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import java.util.Arrays;
-
-import org.eclipse.jgit.internal.storage.file.PackIndex;
-import org.eclipse.jgit.junit.FakeIndexFactory;
-import org.junit.Test;
-
-public class PackIndexPeekIteratorTest {
-    @Test
-    public void next() {
-        PackIndex index1 = indexOf(
-                object("0000000000000000000000000000000000000001", 500),
-                object("0000000000000000000000000000000000000003", 1500),
-                object("0000000000000000000000000000000000000005", 3000));
-        PackIndexMerger.PackIndexPeekIterator it = new PackIndexMerger.PackIndexPeekIterator(0, index1);
-        assertEquals("0000000000000000000000000000000000000001", it.next().name());
-        assertEquals("0000000000000000000000000000000000000003", it.next().name());
-        assertEquals("0000000000000000000000000000000000000005", it.next().name());
-        assertNull(it.next());
-    }
-
-    @Test
-    public void peek_doesNotAdvance() {
-        PackIndex index1 = indexOf(
-                object("0000000000000000000000000000000000000001", 500),
-                object("0000000000000000000000000000000000000003", 1500),
-                object("0000000000000000000000000000000000000005", 3000));
-        PackIndexMerger.PackIndexPeekIterator it = new PackIndexMerger.PackIndexPeekIterator(0, index1);
-        it.next();
-        assertEquals("0000000000000000000000000000000000000001", it.peek().name());
-        assertEquals("0000000000000000000000000000000000000001", it.peek().name());
-        it.next();
-        assertEquals("0000000000000000000000000000000000000003", it.peek().name());
-        assertEquals("0000000000000000000000000000000000000003", it.peek().name());
-        it.next();
-        assertEquals("0000000000000000000000000000000000000005", it.peek().name());
-        assertEquals("0000000000000000000000000000000000000005", it.peek().name());
-        it.next();
-        assertNull(it.peek());
-        assertNull(it.peek());
-    }
-
-    @Test
-    public void empty() {
-        PackIndex index1 = indexOf();
-        PackIndexMerger.PackIndexPeekIterator it = new PackIndexMerger.PackIndexPeekIterator(0, index1);
-        assertNull(it.next());
-        assertNull(it.peek());
-    }
-
-    private static PackIndex indexOf(FakeIndexFactory.IndexObject... objs) {
-        return FakeIndexFactory.indexOf(Arrays.asList(objs));
-    }
-
-    private static FakeIndexFactory.IndexObject object(String name, long offset) {
-        return new FakeIndexFactory.IndexObject(name, offset);
-    }
-}
\ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java
index c6a6321..b5e4b21 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java
@@ -11,6 +11,8 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.time.Instant.EPOCH;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -30,6 +32,7 @@
 import java.util.Set;
 
 import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.MergeResult;
 import org.eclipse.jgit.api.MergeResult.MergeStatus;
 import org.eclipse.jgit.api.RebaseResult;
@@ -964,6 +967,39 @@ public void checkContentMergeConflict(MergeStrategy strategy)
 	}
 
 	@Theory
+	public void checkContentMergeConflictDiff3(MergeStrategy strategy)
+			throws Exception {
+		Git git = Git.wrap(db);
+
+		writeTrashFile("file", "1\n2\n3");
+		git.add().addFilepattern("file").call();
+		RevCommit first = git.commit().setMessage("added file").call();
+
+		writeTrashFile("file", "1master\n2\n3");
+		git.commit().setAll(true).setMessage("modified file on master").call();
+
+		git.checkout().setCreateBranch(true).setStartPoint(first)
+				.setName("side").call();
+		writeTrashFile("file", "1side\n2\n3");
+		RevCommit sideCommit = git.commit().setAll(true)
+				.setMessage("modified file on side").call();
+
+		git.checkout().setName("master").call();
+
+		db.getConfig().setEnum(CONFIG_MERGE_SECTION, null,
+				CONFIG_KEY_CONFLICTSTYLE, ConflictStyle.DIFF3);
+
+		MergeResult result = git.merge().setStrategy(strategy)
+				.include(sideCommit).call();
+		assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
+		String expected = "<<<<<<< HEAD\n" + "1master\n" + "||||||| BASE\n"
+				+ "1\n" + "=======\n" + "1side\n" + ">>>>>>> "
+				+ sideCommit.name() + "\n" + "2\n"
+				+ "3";
+		assertEquals(expected, read("file"));
+	}
+
+	@Theory
 	public void checkContentMergeConflict_noTree(MergeStrategy strategy)
 			throws Exception {
 		Git git = Git.wrap(db);
diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
index 9059d02..35c36de 100644
--- a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
@@ -4,15 +4,15 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ui
 Bundle-SymbolicName: org.eclipse.jgit.ui
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Export-Package: org.eclipse.jgit.awtui;version="7.5.1"
-Import-Package: org.eclipse.jgit.errors;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.lib;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.nls;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revplot;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.revwalk;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.transport;version="[7.5.1,7.6.0)",
- org.eclipse.jgit.util;version="[7.5.1,7.6.0)"
+Export-Package: org.eclipse.jgit.awtui;version="7.6.1"
+Import-Package: org.eclipse.jgit.errors;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.lib;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.nls;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revplot;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.revwalk;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.transport;version="[7.6.1,7.7.0)",
+ org.eclipse.jgit.util;version="[7.6.1,7.7.0)"
diff --git a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
index 5eedf45..ec9f7f0 100644
--- a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.ui - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ui.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit.ui;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit.ui;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml
index 385b86f..a362c39 100644
--- a/org.eclipse.jgit.ui/pom.xml
+++ b/org.eclipse.jgit.ui/pom.xml
@@ -19,7 +19,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ui</artifactId>
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index a7f899a..65c8c69 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit
 Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
@@ -11,8 +11,8 @@
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
 Service-Component: OSGI-INF/org.eclipse.jgit.internal.util.CleanupService.xml
 Eclipse-ExtensibleAPI: true
-Export-Package: org.eclipse.jgit.annotations;version="7.5.1",
- org.eclipse.jgit.api;version="7.5.1";
+Export-Package: org.eclipse.jgit.annotations;version="7.6.1",
+ org.eclipse.jgit.api;version="7.6.1";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.notes,
    org.eclipse.jgit.dircache,
@@ -27,21 +27,21 @@
    org.eclipse.jgit.revwalk.filter,
    org.eclipse.jgit.blame,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="7.5.1";
+ org.eclipse.jgit.api.errors;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="7.5.1";
+ org.eclipse.jgit.attributes;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk",
- org.eclipse.jgit.blame;version="7.5.1";
+ org.eclipse.jgit.blame;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.blame.cache,
    org.eclipse.jgit.diff,
    org.eclipse.jgit.treewalk.filter",
- org.eclipse.jgit.blame.cache;version="7.5.1";
+ org.eclipse.jgit.blame.cache;version="7.6.1";
   uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.diff;version="7.5.1";
+ org.eclipse.jgit.diff;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.patch,
@@ -49,55 +49,55 @@
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.util",
- org.eclipse.jgit.dircache;version="7.5.1";
+ org.eclipse.jgit.dircache;version="7.6.1";
   uses:="org.eclipse.jgit.events,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.attributes,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.util",
- org.eclipse.jgit.errors;version="7.5.1";
+ org.eclipse.jgit.errors;version="7.6.1";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib",
- org.eclipse.jgit.events;version="7.5.1";
+ org.eclipse.jgit.events;version="7.6.1";
   uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.fnmatch;version="7.5.1",
- org.eclipse.jgit.gitrepo;version="7.5.1";
+ org.eclipse.jgit.fnmatch;version="7.6.1",
+ org.eclipse.jgit.gitrepo;version="7.6.1";
   uses:="org.xml.sax.helpers,
    org.eclipse.jgit.api,
    org.eclipse.jgit.api.errors,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.xml.sax",
- org.eclipse.jgit.gitrepo.internal;version="7.5.1";x-internal:=true,
- org.eclipse.jgit.hooks;version="7.5.1";
+ org.eclipse.jgit.gitrepo.internal;version="7.6.1";x-internal:=true,
+ org.eclipse.jgit.hooks;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.util",
- org.eclipse.jgit.ignore;version="7.5.1",
- org.eclipse.jgit.ignore.internal;version="7.5.1";
+ org.eclipse.jgit.ignore;version="7.6.1",
+ org.eclipse.jgit.ignore.internal;version="7.6.1";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="7.5.1";
+ org.eclipse.jgit.internal;version="7.6.1";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.diff;version="7.5.1";
+ org.eclipse.jgit.internal.diff;version="7.6.1";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.diffmergetool;version="7.5.1";
+ org.eclipse.jgit.internal.diffmergetool;version="7.6.1";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.pgm.test,
    org.eclipse.jgit.pgm,
    org.eclipse.egit.ui",
- org.eclipse.jgit.internal.fsck;version="7.5.1";
+ org.eclipse.jgit.internal.fsck;version="7.6.1";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.revwalk;version="7.5.1";
+ org.eclipse.jgit.internal.revwalk;version="7.6.1";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.commitgraph;version="7.5.1";
+ org.eclipse.jgit.internal.storage.commitgraph;version="7.6.1";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.dfs;version="7.5.1";
+ org.eclipse.jgit.internal.storage.dfs;version="7.6.1";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.http.server,
    org.eclipse.jgit.http.test,
    org.eclipse.jgit.lfs.test",
- org.eclipse.jgit.internal.storage.file;version="7.5.1";
+ org.eclipse.jgit.internal.storage.file;version="7.6.1";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.junit,
    org.eclipse.jgit.junit.http,
@@ -109,39 +109,39 @@
    org.eclipse.jgit.ssh.apache,
    org.eclipse.jgit.ssh.apache.test,
    org.eclipse.jgit.ssh.jsch.test",
- org.eclipse.jgit.internal.storage.io;version="7.5.1";
+ org.eclipse.jgit.internal.storage.io;version="7.6.1";
   x-friends:="org.eclipse.jgit.junit,
    org.eclipse.jgit.test,
    org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.memory;version="7.5.1";
+ org.eclipse.jgit.internal.storage.memory;version="7.6.1";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.midx;version="7.5.1";
+ org.eclipse.jgit.internal.storage.midx;version="7.6.1";
   x-friends:="org.eclipse.jgit.pgm,
    org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.pack;version="7.5.1";
+ org.eclipse.jgit.internal.storage.pack;version="7.6.1";
   x-friends:="org.eclipse.jgit.junit,
    org.eclipse.jgit.test,
    org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftable;version="7.5.1";
+ org.eclipse.jgit.internal.storage.reftable;version="7.6.1";
   x-friends:="org.eclipse.jgit.http.test,
    org.eclipse.jgit.junit,
    org.eclipse.jgit.test,
    org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.submodule;version="7.5.1";x-internal:=true,
- org.eclipse.jgit.internal.transport.connectivity;version="7.5.1";
+ org.eclipse.jgit.internal.submodule;version="7.6.1";x-internal:=true,
+ org.eclipse.jgit.internal.transport.connectivity;version="7.6.1";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.http;version="7.5.1";
+ org.eclipse.jgit.internal.transport.http;version="7.6.1";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.parser;version="7.5.1";
+ org.eclipse.jgit.internal.transport.parser;version="7.6.1";
   x-friends:="org.eclipse.jgit.http.server,
    org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.ssh;version="7.5.1";
+ org.eclipse.jgit.internal.transport.ssh;version="7.6.1";
   x-friends:="org.eclipse.jgit.ssh.apache,
    org.eclipse.jgit.ssh.jsch,
    org.eclipse.jgit.test",
- org.eclipse.jgit.internal.util;version="7.5.1";
+ org.eclipse.jgit.internal.util;version="7.6.1";
   x-friends:="org.eclipse.jgit.junit",
- org.eclipse.jgit.lib;version="7.5.1";
+ org.eclipse.jgit.lib;version="7.6.1";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.util.sha1,
    org.eclipse.jgit.dircache,
@@ -156,12 +156,12 @@
    org.eclipse.jgit.util,
    org.eclipse.jgit.submodule,
    org.eclipse.jgit.util.time",
- org.eclipse.jgit.lib.internal;version="7.5.1";
+ org.eclipse.jgit.lib.internal;version="7.6.1";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.pgm,
    org.eclipse.egit.ui",
- org.eclipse.jgit.logging;version="7.5.1",
- org.eclipse.jgit.merge;version="7.5.1";
+ org.eclipse.jgit.logging;version="7.6.1",
+ org.eclipse.jgit.merge;version="7.6.1";
   uses:="org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
@@ -170,42 +170,42 @@
    org.eclipse.jgit.util,
    org.eclipse.jgit.api,
    org.eclipse.jgit.attributes",
- org.eclipse.jgit.nls;version="7.5.1",
- org.eclipse.jgit.notes;version="7.5.1";
+ org.eclipse.jgit.nls;version="7.6.1",
+ org.eclipse.jgit.notes;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="7.5.1";
+ org.eclipse.jgit.patch;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="7.5.1";
+ org.eclipse.jgit.revplot;version="7.6.1";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.lib",
- org.eclipse.jgit.revwalk;version="7.5.1";
+ org.eclipse.jgit.revwalk;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk.filter,
    org.eclipse.jgit.diff,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.internal.storage.commitgraph",
- org.eclipse.jgit.revwalk.filter;version="7.5.1";
+ org.eclipse.jgit.revwalk.filter;version="7.6.1";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="7.5.1";
+ org.eclipse.jgit.storage.file;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="7.5.1";
+ org.eclipse.jgit.storage.pack;version="7.6.1";
   uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.submodule;version="7.5.1";
+ org.eclipse.jgit.submodule;version="7.6.1";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.diff,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.util",
- org.eclipse.jgit.transport;version="7.5.1";
+ org.eclipse.jgit.transport;version="7.6.1";
   uses:="javax.crypto,
    org.eclipse.jgit.hooks,
    org.eclipse.jgit.util.io,
@@ -218,21 +218,21 @@
    org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.storage.pack,
    org.eclipse.jgit.errors",
- org.eclipse.jgit.transport.http;version="7.5.1";
+ org.eclipse.jgit.transport.http;version="7.6.1";
   uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="7.5.1";
+ org.eclipse.jgit.transport.resolver;version="7.6.1";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.lib",
- org.eclipse.jgit.treewalk;version="7.5.1";
+ org.eclipse.jgit.treewalk;version="7.6.1";
   uses:="org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.attributes,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.util",
- org.eclipse.jgit.treewalk.filter;version="7.5.1";
+ org.eclipse.jgit.treewalk.filter;version="7.6.1";
   uses:="org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util;version="7.5.1";
+ org.eclipse.jgit.util;version="7.6.1";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.hooks,
    org.eclipse.jgit.revwalk,
@@ -245,12 +245,12 @@
    org.eclipse.jgit.treewalk,
    javax.net.ssl,
    org.eclipse.jgit.util.time",
- org.eclipse.jgit.util.io;version="7.5.1";
+ org.eclipse.jgit.util.io;version="7.6.1";
   uses:="org.eclipse.jgit.attributes,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util.sha1;version="7.5.1",
- org.eclipse.jgit.util.time;version="7.5.1"
+ org.eclipse.jgit.util.sha1;version="7.6.1",
+ org.eclipse.jgit.util.time;version="7.6.1"
 Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
  javax.crypto,
  javax.management,
diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
index 52c0cae..f2662e0 100644
--- a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit - Sources
 Bundle-SymbolicName: org.eclipse.jgit.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.5.1.qualifier
+Bundle-Version: 7.6.1.qualifier
 Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Eclipse-SourceBundle: org.eclipse.jgit;version="7.5.1.qualifier";roots="."
+Eclipse-SourceBundle: org.eclipse.jgit;version="7.6.1.qualifier";roots="."
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index 0e52b76..d30d2ae 100644
--- a/org.eclipse.jgit/pom.xml
+++ b/org.eclipse.jgit/pom.xml
@@ -20,7 +20,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>7.5.1-SNAPSHOT</version>
+    <version>7.6.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit</artifactId>
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 0d50360..31d065e 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -789,6 +789,7 @@
 tagAlreadyExists=tag ''{0}'' already exists
 tagNameInvalid=tag name {0} is invalid
 tagOnRepoWithoutHEADCurrentlyNotSupported=Tag on repository without HEAD currently not supported
+temporaryBufferIsDestroyed=The TemporaryBuffer was destroyed and can't be used anymore.
 theFactoryMustNotBeNull=The factory must not be null
 threadInterruptedWhileRunning="Current thread interrupted while running {0}"
 timeIsUncertain=Time is uncertain
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
index b4d1cab..23bda6f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
@@ -20,7 +20,9 @@
 import java.text.MessageFormat;
 import java.time.Instant;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
 
 import org.eclipse.jgit.api.errors.FilterFailedException;
 import org.eclipse.jgit.api.errors.GitAPIException;
@@ -114,6 +116,36 @@ public AddCommand addFilepattern(String filepattern) {
 	}
 
 	/**
+	 * Add paths to a file/directory whose content should be added.
+	 *
+	 * @param patterns
+	 *            repository-relative paths of file/directory to add (with
+	 *            <code>/</code> as separator)
+	 * @return {@code this}
+	 * @since 7.6
+	 */
+	public AddCommand addFilepatterns(String... patterns) {
+		List.of(Objects.requireNonNull(patterns)).forEach(this::addFilepattern);
+		return this;
+	}
+
+	/**
+	 * Add paths to a file/directory whose content should be added.
+	 *
+	 * @param patterns
+	 *            repository-relative paths of file/directory to add (with
+	 *            <code>/</code> as separator)
+	 * @return {@code this}
+	 * @since 7.6
+	 */
+	public AddCommand addFilepatterns(Collection<String> patterns) {
+		if (patterns != null) {
+			patterns.forEach(this::addFilepattern);
+		}
+		return this;
+	}
+
+	/**
 	 * Allow clients to provide their own implementation of a FileTreeIterator
 	 *
 	 * @param f
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
index a353d1a..6761f1e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
@@ -10,6 +10,9 @@
 package org.eclipse.jgit.api;
 
 import static org.eclipse.jgit.api.CherryPickCommitMessageProvider.ORIGINAL;
+import static org.eclipse.jgit.api.MergeCommand.ConflictStyle.MERGE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
 
 import java.io.IOException;
@@ -18,6 +21,7 @@
 import java.util.List;
 import java.util.Map;
 
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.JGitInternalException;
@@ -73,6 +77,8 @@ public class CherryPickCommand extends GitCommand<CherryPickResult> {
 
 	private ContentMergeStrategy contentStrategy;
 
+	private ConflictStyle conflictStyle;
+
 	private Integer mainlineParentNumber;
 
 	private boolean noCommit = false;
@@ -138,9 +144,9 @@ public CherryPickResult call() throws GitAPIException, NoMessageException,
 				boolean noProblems;
 				Map<String, MergeFailureReason> failingPaths = null;
 				List<String> unmergedPaths = null;
-				if (merger instanceof ResolveMerger) {
-					ResolveMerger resolveMerger = (ResolveMerger) merger;
+				if (merger instanceof ResolveMerger resolveMerger) {
 					resolveMerger.setContentMergeStrategy(contentStrategy);
+					resolveMerger.setConflictStyle(getConflictStyle());
 					resolveMerger.setCommitNames(
 							new String[] { "BASE", ourName, cherryPickName }); //$NON-NLS-1$
 					resolveMerger
@@ -363,6 +369,25 @@ public CherryPickCommand setContentMergeStrategy(
 	}
 
 	/**
+	 * Sets the conflict style to be used when formatting merge conflicts.
+	 *
+	 * @param conflictStyle
+	 *            a {@link org.eclipse.jgit.api.MergeCommand.ConflictStyle}
+	 * @return {@code this}
+	 * @since 7.6
+	 */
+	public CherryPickCommand setConflictStyle(ConflictStyle conflictStyle) {
+		this.conflictStyle = conflictStyle;
+		return this;
+	}
+
+	private ConflictStyle getConflictStyle() {
+		return conflictStyle != null ? conflictStyle
+				: repo.getConfig().getEnum(CONFIG_MERGE_SECTION, null,
+						CONFIG_KEY_CONFLICTSTYLE, MERGE);
+	}
+
+	/**
 	 * Set the (1-based) parent number to diff against
 	 *
 	 * @param mainlineParentNumber
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java
index f6935e1..a16be79 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java
@@ -26,6 +26,7 @@
 import org.eclipse.jgit.internal.storage.file.GC;
 import org.eclipse.jgit.internal.storage.file.GC.RepoStatistics;
 import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.GcConfig;
 import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.StoredConfig;
@@ -66,6 +67,8 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
 
 	private Boolean packKeptObjects;
 
+	private GcConfig gcConfig;
+
 	/**
 	 * Constructor for GarbageCollectCommand.
 	 *
@@ -75,6 +78,7 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
 	protected GarbageCollectCommand(Repository repo) {
 		super(repo);
 		pconfig = new PackConfig(repo);
+		gcConfig = repo.getConfig().get(GcConfig.KEY);
 	}
 
 	/**
@@ -200,6 +204,19 @@ public GarbageCollectCommand setPrunePreserved(boolean prunePreserved) {
 		return this;
 	}
 
+	/**
+	 * Set the gc configuration
+	 *
+	 * @param gcConfig
+	 *            the gc configuration
+	 * @return {@code this}
+	 * @since 7.6
+	 */
+	public GarbageCollectCommand setGcConfig(GcConfig gcConfig) {
+		this.gcConfig = gcConfig;
+		return this;
+	}
+
 	@Override
 	public Properties call() throws GitAPIException {
 		checkCallable();
@@ -214,6 +231,7 @@ public Properties call() throws GitAPIException {
 				if (this.packKeptObjects != null) {
 					gc.setPackKeptObjects(packKeptObjects.booleanValue());
 				}
+				gc.setGcConfig(gcConfig);
 				try {
 					gc.gc().get();
 					return toProperties(gc.getStatistics());
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
index 7064f5a..a79fbf7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
@@ -75,6 +75,8 @@ public class MergeCommand extends GitCommand<MergeResult> {
 
 	private ContentMergeStrategy contentStrategy;
 
+	private ConflictStyle conflictStyle;
+
 	private List<Ref> commits = new ArrayList<>();
 
 	private Boolean squash;
@@ -336,9 +338,9 @@ public MergeResult call() throws GitAPIException, NoHeadException,
 				Map<String, org.eclipse.jgit.merge.MergeResult<?>> lowLevelResults = null;
 				Map<String, MergeFailureReason> failingPaths = null;
 				List<String> unmergedPaths = null;
-				if (merger instanceof ResolveMerger) {
-					ResolveMerger resolveMerger = (ResolveMerger) merger;
+				if (merger instanceof ResolveMerger resolveMerger) {
 					resolveMerger.setContentMergeStrategy(contentStrategy);
+					resolveMerger.setConflictStyle(conflictStyle);
 					resolveMerger.setCommitNames(new String[] {
 							"BASE", "HEAD", ref.getName() }); //$NON-NLS-1$ //$NON-NLS-2$
 					resolveMerger.setWorkingTreeIterator(new FileTreeIterator(repo));
@@ -456,6 +458,8 @@ private void fallBackToConfiguration() {
 			commit = Boolean.valueOf(config.isCommit());
 		if (fastForwardMode == null)
 			fastForwardMode = config.getFastForwardMode();
+		if (conflictStyle == null)
+			conflictStyle = config.getConflictStyle();
 	}
 
 	private void updateHead(StringBuilder refLogMessage, ObjectId newHeadId,
@@ -511,6 +515,19 @@ public MergeCommand setContentMergeStrategy(ContentMergeStrategy strategy) {
 	}
 
 	/**
+	 * Sets the conflict style to be used when formatting merge conflicts.
+	 *
+	 * @param conflictStyle
+	 *            a {@link org.eclipse.jgit.api.MergeCommand.ConflictStyle}
+	 * @return {@code this}
+	 * @since 7.6
+	 */
+	public MergeCommand setConflictStyle(ConflictStyle conflictStyle) {
+		this.conflictStyle = conflictStyle;
+		return this;
+	}
+
+	/**
 	 * Reference to a commit to be merged with the current head
 	 *
 	 * @param aCommit
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
index 4b2cee4..ff5dbff 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
@@ -11,10 +11,15 @@
  */
 package org.eclipse.jgit.api;
 
+import static org.eclipse.jgit.api.MergeCommand.ConflictStyle.MERGE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
+
 import java.io.IOException;
 import java.text.MessageFormat;
 
 import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
 import org.eclipse.jgit.api.MergeCommand.FastForwardMode.Merge;
 import org.eclipse.jgit.api.RebaseCommand.Operation;
@@ -72,6 +77,8 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
 
 	private ContentMergeStrategy contentStrategy;
 
+	private ConflictStyle conflictStyle;
+
 	private TagOpt tagOption;
 
 	private FastForwardMode fastForwardMode;
@@ -361,6 +368,7 @@ public PullResult call() throws GitAPIException,
 					.setOperation(Operation.BEGIN)
 					.setStrategy(strategy)
 					.setContentMergeStrategy(contentStrategy)
+					.setConflictStyle(getConflictStyle())
 					.setPreserveMerges(
 							pullRebaseMode == BranchRebaseMode.MERGES)
 					.call();
@@ -371,6 +379,7 @@ public PullResult call() throws GitAPIException,
 					.setProgressMonitor(monitor)
 					.setStrategy(strategy)
 					.setContentMergeStrategy(contentStrategy)
+					.setConflictStyle(getConflictStyle())
 					.setFastForward(getFastForwardMode()).call();
 			monitor.update(1);
 			result = new PullResult(fetchRes, remote, mergeRes);
@@ -464,6 +473,25 @@ public PullCommand setContentMergeStrategy(ContentMergeStrategy strategy) {
 	}
 
 	/**
+	 * Sets the conflict style to be used when formatting merge conflicts.
+	 *
+	 * @param conflictStyle
+	 *            a {@link org.eclipse.jgit.api.MergeCommand.ConflictStyle}
+	 * @return {@code this}
+	 * @since 7.6
+	 */
+	public PullCommand setConflictStyle(ConflictStyle conflictStyle) {
+		this.conflictStyle = conflictStyle;
+		return this;
+	}
+
+	private ConflictStyle getConflictStyle() {
+		return conflictStyle != null ? conflictStyle
+				: repo.getConfig().getEnum(CONFIG_MERGE_SECTION, null,
+						CONFIG_KEY_CONFLICTSTYLE, MERGE);
+	}
+
+	/**
 	 * Set the specification of annotated tag behavior during fetch
 	 *
 	 * @param tagOpt
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
index 3ae7a6c..ba8461d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
@@ -11,6 +11,9 @@
 package org.eclipse.jgit.api;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.api.MergeCommand.ConflictStyle.MERGE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -31,6 +34,7 @@
 import java.util.regex.Pattern;
 
 import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.RebaseResult.Status;
 import org.eclipse.jgit.api.ResetCommand.ResetType;
 import org.eclipse.jgit.api.errors.CheckoutConflictException;
@@ -220,6 +224,8 @@ public enum Operation {
 
 	private ContentMergeStrategy contentStrategy;
 
+	private ConflictStyle conflictStyle;
+
 	private boolean preserveMerges = false;
 
 	/**
@@ -557,6 +563,7 @@ private RebaseResult cherryPickCommitFlattening(RevCommit commitToPick)
 					.setReflogPrefix(REFLOG_PREFIX)
 					.setStrategy(strategy)
 					.setContentMergeStrategy(contentStrategy)
+						.setConflictStyle(getConflictStyle())
 					.call();
 				switch (cherryPickResult.getStatus()) {
 				case FAILED:
@@ -611,7 +618,8 @@ private RebaseResult cherryPickCommitPreservingMerges(RevCommit commitToPick)
 							.setOurCommitName(ourCommitName)
 							.setReflogPrefix(REFLOG_PREFIX)
 							.setStrategy(strategy)
-							.setContentMergeStrategy(contentStrategy);
+							.setContentMergeStrategy(contentStrategy)
+							.setConflictStyle(getConflictStyle());
 					if (isMerge) {
 						pickCommand.setMainlineParentNumber(1);
 						// We write a MERGE_HEAD and later commit explicitly
@@ -649,6 +657,7 @@ private RebaseResult cherryPickCommitPreservingMerges(RevCommit commitToPick)
 							.setProgressMonitor(monitor)
 							.setStrategy(strategy)
 							.setContentMergeStrategy(contentStrategy)
+							.setConflictStyle(getConflictStyle())
 							.setCommit(false);
 					for (int i = 1; i < commitToPick.getParentCount(); i++)
 						merge.include(newParents.get(i));
@@ -1039,6 +1048,8 @@ private RevCommit continueRebase() throws GitAPIException, IOException {
 				CommitCommand commit = git.commit();
 				commit.setMessage(rebaseState.readFile(MESSAGE));
 				commit.setAuthor(parseAuthor());
+				commit.setCleanupMode(
+						commitConfig.resolve(CleanupMode.DEFAULT, false));
 				return commit.call();
 			}
 		}
@@ -1698,6 +1709,25 @@ public RebaseCommand setContentMergeStrategy(ContentMergeStrategy strategy) {
 	}
 
 	/**
+	 * Sets the conflict style to be used when formatting merge conflicts.
+	 *
+	 * @param conflictStyle
+	 *            a {@link org.eclipse.jgit.api.MergeCommand.ConflictStyle}
+	 * @return {@code this}
+	 * @since 7.6
+	 */
+	public RebaseCommand setConflictStyle(ConflictStyle conflictStyle) {
+		this.conflictStyle = conflictStyle;
+		return this;
+	}
+
+	private ConflictStyle getConflictStyle() {
+		return conflictStyle != null ? conflictStyle
+				: repo.getConfig().getEnum(CONFIG_MERGE_SECTION, null,
+						CONFIG_KEY_CONFLICTSTYLE, MERGE);
+	}
+
+	/**
 	 * Whether to preserve merges during rebase
 	 *
 	 * @param preserve
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
index 6643c83..5a107d5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
@@ -9,6 +9,9 @@
  */
 package org.eclipse.jgit.api;
 
+import static org.eclipse.jgit.api.MergeCommand.ConflictStyle.MERGE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
 
 import java.io.IOException;
@@ -17,6 +20,7 @@
 import java.util.List;
 import java.util.Map;
 
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.MergeResult.MergeStatus;
 import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
 import org.eclipse.jgit.api.errors.GitAPIException;
@@ -74,6 +78,8 @@ public class RevertCommand extends GitCommand<RevCommit> {
 
 	private ProgressMonitor monitor = NullProgressMonitor.INSTANCE;
 
+	private ConflictStyle conflictStyle;
+
 	/**
 	 * <p>
 	 * Constructor for RevertCommand.
@@ -138,6 +144,7 @@ public RevCommit call() throws NoMessageException, UnmergedPathsException,
 						+ srcCommit.getShortMessage();
 
 				ResolveMerger merger = (ResolveMerger) strategy.newMerger(repo);
+				merger.setConflictStyle(getConflictStyle());
 				merger.setWorkingTreeIterator(new FileTreeIterator(repo));
 				merger.setBase(srcCommit.getTree());
 				merger.setCommitNames(new String[] {
@@ -344,4 +351,23 @@ public RevertCommand setInsertChangeId(boolean insertChangeId) {
 		return this;
 	}
 
+	/**
+	 * Sets the conflict style to be used when formatting merge conflicts.
+	 *
+	 * @param conflictStyle
+	 *            a {@link org.eclipse.jgit.api.MergeCommand.ConflictStyle}
+	 * @return {@code this}
+	 * @since 7.6
+	 */
+	public RevertCommand setConflictStyle(ConflictStyle conflictStyle) {
+		this.conflictStyle = conflictStyle;
+		return this;
+	}
+
+	private ConflictStyle getConflictStyle() {
+		return conflictStyle != null ? conflictStyle
+				: repo.getConfig().getEnum(CONFIG_MERGE_SECTION, null,
+						CONFIG_KEY_CONFLICTSTYLE, MERGE);
+	}
+
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
index b0b715e..aa733b5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
@@ -9,6 +9,9 @@
  */
 package org.eclipse.jgit.api;
 
+import static org.eclipse.jgit.api.MergeCommand.ConflictStyle.MERGE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.eclipse.jgit.treewalk.TreeWalk.OperationType.CHECKOUT_OP;
 
 import java.io.IOException;
@@ -17,6 +20,7 @@
 import java.util.List;
 import java.util.Set;
 
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.InvalidRefNameException;
 import org.eclipse.jgit.api.errors.JGitInternalException;
@@ -76,6 +80,8 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
 
 	private ContentMergeStrategy contentStrategy;
 
+	private ConflictStyle conflictStyle;
+
 	/**
 	 * Create command to apply the changes of a stashed commit
 	 *
@@ -173,8 +179,7 @@ public ObjectId call() throws GitAPIException,
 
 			Merger merger = strategy.newMerger(repo);
 			boolean mergeSucceeded;
-			if (merger instanceof ResolveMerger) {
-				ResolveMerger resolveMerger = (ResolveMerger) merger;
+			if (merger instanceof ResolveMerger resolveMerger) {
 				resolveMerger
 						.setCommitNames(new String[] { "stashed HEAD", "HEAD", //$NON-NLS-1$ //$NON-NLS-2$
 								"stash" }); //$NON-NLS-1$
@@ -182,6 +187,7 @@ public ObjectId call() throws GitAPIException,
 				resolveMerger
 						.setWorkingTreeIterator(new FileTreeIterator(repo));
 				resolveMerger.setContentMergeStrategy(contentStrategy);
+				resolveMerger.setConflictStyle(getConflictStyle());
 				mergeSucceeded = resolveMerger.merge(headCommit, stashCommit);
 				List<String> modifiedByMerge = resolveMerger.getModifiedFiles();
 				if (!modifiedByMerge.isEmpty()) {
@@ -199,12 +205,12 @@ public ObjectId call() throws GitAPIException,
 				dco.checkout(); // Ignoring failed deletes....
 				if (restoreIndex) {
 					Merger ixMerger = strategy.newMerger(repo, true);
-					if (ixMerger instanceof ResolveMerger) {
-						ResolveMerger resolveMerger = (ResolveMerger) ixMerger;
+					if (ixMerger instanceof ResolveMerger resolveMerger) {
 						resolveMerger.setCommitNames(new String[] { "stashed HEAD", //$NON-NLS-1$
 								"HEAD", "stashed index" }); //$NON-NLS-1$//$NON-NLS-2$
 						resolveMerger.setBase(stashHeadCommit);
 						resolveMerger.setContentMergeStrategy(contentStrategy);
+						resolveMerger.setConflictStyle(getConflictStyle());
 					}
 					boolean ok = ixMerger.merge(headCommit, stashIndexCommit);
 					if (ok) {
@@ -218,8 +224,7 @@ public ObjectId call() throws GitAPIException,
 
 				if (untrackedCommit != null) {
 					Merger untrackedMerger = strategy.newMerger(repo, true);
-					if (untrackedMerger instanceof ResolveMerger) {
-						ResolveMerger resolveMerger = (ResolveMerger) untrackedMerger;
+					if (untrackedMerger instanceof ResolveMerger resolveMerger) {
 						resolveMerger.setCommitNames(new String[] { "null", "HEAD", //$NON-NLS-1$//$NON-NLS-2$
 								"untracked files" }); //$NON-NLS-1$
 						// There is no common base for HEAD & untracked files
@@ -230,6 +235,7 @@ public ObjectId call() throws GitAPIException,
 						// commit.
 						resolveMerger.setBase(null);
 						resolveMerger.setContentMergeStrategy(contentStrategy);
+						resolveMerger.setConflictStyle(getConflictStyle());
 					}
 					boolean ok = untrackedMerger.merge(headCommit,
 							untrackedCommit);
@@ -305,6 +311,25 @@ public StashApplyCommand setContentMergeStrategy(
 	}
 
 	/**
+	 * Sets the conflict style to be used when formatting merge conflicts.
+	 *
+	 * @param conflictStyle
+	 *            a {@link org.eclipse.jgit.api.MergeCommand.ConflictStyle}
+	 * @return {@code this}
+	 * @since 7.6
+	 */
+	public StashApplyCommand setConflictStyle(ConflictStyle conflictStyle) {
+		this.conflictStyle = conflictStyle;
+		return this;
+	}
+
+	private ConflictStyle getConflictStyle() {
+		return conflictStyle != null ? conflictStyle
+				: repo.getConfig().getEnum(CONFIG_MERGE_SECTION, null,
+						CONFIG_KEY_CONFLICTSTYLE, MERGE);
+	}
+
+	/**
 	 * Whether the command should restore untracked files
 	 *
 	 * @param restoreUntracked
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index 9d2bb97..9365db2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -819,6 +819,7 @@ public static JGitText get() {
 	/***/ public String tagAlreadyExists;
 	/***/ public String tagNameInvalid;
 	/***/ public String tagOnRepoWithoutHEADCurrentlyNotSupported;
+	/***/ public String temporaryBufferIsDestroyed;
 	/***/ public String timeoutMeasureFsTimestampResolution;
 	/***/ public String transactionAborted;
 	/***/ public String theFactoryMustNotBeNull;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriter.java
index 28ef98d..0cdb304 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriter.java
@@ -15,15 +15,26 @@
 import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
 
 import java.io.IOException;
-import java.util.LinkedHashMap;
+import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
 import java.util.function.Function;
 
 import org.eclipse.jgit.annotations.Nullable;
-import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder;
 import org.eclipse.jgit.internal.storage.midx.MultiPackIndexWriter;
+import org.eclipse.jgit.internal.storage.midx.PackIndexMerger;
+import org.eclipse.jgit.internal.storage.pack.PackBitmapCalculator;
+import org.eclipse.jgit.internal.storage.pack.PackBitmapIndexWriter;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.pack.PackConfig;
 
 /**
  * Create a pack with a multipack index, setting the required fields in the
@@ -35,6 +46,30 @@ private DfsMidxWriter() {
 	}
 
 	/**
+	 * Create a pack with the multipack index (without bitmaps).
+	 *
+	 * @param pm
+	 *            a progress monitor
+	 * @param objdb
+	 *            an object database
+	 * @param packs
+	 *            the packs to cover
+	 * @param base
+	 *            parent of this midx in the chain (if any).
+	 *
+	 * @return a pack (uncommitted) with the multipack index of the packs passed
+	 *         as parameter.
+	 * @throws IOException
+	 *             an error opening the packs or writing the stream.
+	 */
+	public static DfsPackDescription writeMidx(ProgressMonitor pm,
+			DfsObjDatabase objdb, List<DfsPackFile> packs,
+			@Nullable DfsPackDescription base) throws IOException {
+		return writeMidx(pm, objdb, packs, base,
+				new PackConfig(objdb.getRepository()));
+	}
+
+	/**
 	 * Create a pack with the multipack index
 	 *
 	 * @param pm
@@ -45,6 +80,8 @@ private DfsMidxWriter() {
 	 *            the packs to cover
 	 * @param base
 	 *            parent of this midx in the chain (if any).
+	 * @param packConfig
+	 *            pack config with the parameters to write bitmaps.
 	 * @return a pack (uncommitted) with the multipack index of the packs passed
 	 *         as parameter.
 	 * @throws IOException
@@ -52,12 +89,12 @@ private DfsMidxWriter() {
 	 */
 	public static DfsPackDescription writeMidx(ProgressMonitor pm,
 			DfsObjDatabase objdb, List<DfsPackFile> packs,
-			@Nullable DfsPackDescription base) throws IOException {
-		LinkedHashMap<String, PackIndex> inputs = new LinkedHashMap<>(
-				packs.size());
+			@Nullable DfsPackDescription base, PackConfig packConfig)
+			throws IOException {
+		PackIndexMerger.Builder dataBuilder = PackIndexMerger.builder();
 		try (DfsReader ctx = objdb.newReader()) {
 			for (DfsPackFile pack : packs) {
-				inputs.put(pack.getPackDescription().getPackName(),
+				dataBuilder.addPack(pack.getPackDescription().getPackName(),
 						pack.getPackIndex(ctx));
 			}
 		}
@@ -66,8 +103,10 @@ public static DfsPackDescription writeMidx(ProgressMonitor pm,
 		try (DfsOutputStream out = objdb.writeFile(midxPackDesc,
 				MULTI_PACK_INDEX)) {
 			MultiPackIndexWriter w = new MultiPackIndexWriter();
-			MultiPackIndexWriter.Result result = w.write(pm, out, inputs);
+			MultiPackIndexWriter.Result result = w.write(pm, out,
+					dataBuilder.build());
 			midxPackDesc.addFileExt(MULTI_PACK_INDEX);
+			midxPackDesc.setFileSize(MULTI_PACK_INDEX, result.bytesWritten());
 			midxPackDesc.setObjectCount(result.objectCount());
 
 			Map<String, DfsPackDescription> byName = packs.stream()
@@ -82,6 +121,52 @@ public static DfsPackDescription writeMidx(ProgressMonitor pm,
 			}
 		}
 
+		// TODO(ifrade): At the moment write bitmaps only in the bottom midx.
+		// A single-pack midx in the base should be covering only GC. No
+		// need to write midx bitmaps (we will use GC bitmaps).
+		if (base == null && midxPackDesc.getCoveredPacks().size() > 1) {
+			createAndAttachBitmaps(objdb.getRepository(), midxPackDesc,
+					packConfig);
+		}
+
 		return midxPackDesc;
 	}
+
+	private static void createAndAttachBitmaps(DfsRepository db,
+			DfsPackDescription desc, PackConfig cfg) throws IOException {
+
+		DfsObjDatabase objdb = db.getObjectDatabase();
+		// We need a DfsPackFile to reread the contents
+		DfsPackFileMidx midxPack = db.getObjectDatabase().createDfsPackFileMidx(
+				DfsBlockCache.getInstance(), desc, new ArrayList<>());
+
+		// TODO(ifrade): Verify we duplicate the behaviour about tags of regular
+		// bitmapping
+		List<ObjectId> allHeads = db.getRefDatabase()
+				.getRefsByPrefix(Constants.R_HEADS).stream()
+				.map(r -> r.getObjectId()).filter(Objects::nonNull).toList();
+		if (allHeads.isEmpty()) {
+			return;
+		}
+
+		try (DfsReader ctx = objdb.newReader()) {
+			RefAdvancerWalk adv = new RefAdvancerWalk(db,
+					c -> midxPack.hasObject(ctx, c));
+			Set<RevCommit> inPack = adv.advance(allHeads);
+
+			byte[] checksum = midxPack.getChecksum(ctx);
+			PackBitmapIndexBuilder writeBitmaps = new PackBitmapIndexBuilder(
+					midxPack.getLocalObjects(ctx));
+			int commitCount = writeBitmaps.getCommits().cardinality();
+
+			PackBitmapCalculator calculator = new PackBitmapCalculator(cfg);
+			// This will do ctx.getBitmapIndex() to reuse/copy previous bitmaps
+			calculator.calculate(ctx, NullProgressMonitor.INSTANCE, commitCount,
+					inPack, new HashSet<>(), writeBitmaps);
+			PackBitmapIndexWriter pbiWriter = db.getObjectDatabase()
+					.getPackBitmapIndexWriter(desc);
+			pbiWriter.write(writeBitmaps, checksum);
+		}
+	}
+
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java
index ecc97e9..4997b90 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java
@@ -241,20 +241,6 @@ void setPackIndex(PackIndex idx) {
 	}
 
 	/**
-	 * Get the PackIndex for this PackFile.
-	 *
-	 * @param ctx
-	 *            reader context to support reading from the backing store if
-	 *            the index is not already loaded in memory.
-	 * @return the PackIndex.
-	 * @throws java.io.IOException
-	 *             the pack index is not available, or is corrupt.
-	 */
-	public PackIndex getPackIndex(DfsReader ctx) throws IOException {
-		return idx(ctx);
-	}
-
-	/**
 	 * Get a view of this packfile as a set of objects
 	 * <p>
 	 * To use when the caller only needs to check inclusion (without specific
@@ -267,10 +253,20 @@ public PackIndex getPackIndex(DfsReader ctx) throws IOException {
 	 *             cannot load the backing data from storage
 	 */
 	public ObjectIdSet asObjectIdSet(DfsReader ctx) throws IOException {
-		return idx(ctx);
+		return getPackIndex(ctx);
 	}
 
-	private PackIndex idx(DfsReader ctx) throws IOException {
+	/**
+	 * Get the PackIndex for this PackFile.
+	 *
+	 * @param ctx
+	 *            reader context to support reading from the backing store if
+	 *            the index is not already loaded in memory.
+	 * @return the PackIndex.
+	 * @throws java.io.IOException
+	 *             the pack index is not available, or is corrupt.
+	 */
+	public PackIndex getPackIndex(DfsReader ctx) throws IOException {
 		if (index != null) {
 			return index;
 		}
@@ -399,7 +395,8 @@ public PackReverseIndex getReverseIdx(DfsReader ctx) throws IOException {
 			return reverseIndex;
 		}
 
-		reverseIndex = indexFactory.getPackIndexes().reverseIndex(ctx, idx(ctx));
+		reverseIndex = indexFactory.getPackIndexes().reverseIndex(ctx,
+				getPackIndex(ctx));
 		if (reverseIndex == null) {
 			throw new IOException(
 					"Couldn't get a reference to the reverse index"); //$NON-NLS-1$
@@ -460,12 +457,12 @@ private PackObjectSizeIndex getObjectSizeIndex(DfsReader ctx)
 	 *             the pack index is not available, or is corrupt.
 	 */
 	public boolean hasObject(DfsReader ctx, AnyObjectId id) throws IOException {
-		final long offset = idx(ctx).findOffset(id);
+		final long offset = getPackIndex(ctx).findOffset(id);
 		return 0 < offset && !isCorrupt(offset);
 	}
 
 	int findIdxPosition(DfsReader ctx, AnyObjectId id) throws IOException {
-		return idx(ctx).findPosition(id);
+		return getPackIndex(ctx).findPosition(id);
 	}
 
 	/**
@@ -482,12 +479,12 @@ int findIdxPosition(DfsReader ctx, AnyObjectId id) throws IOException {
 	 */
 	ObjectLoader get(DfsReader ctx, AnyObjectId id)
 			throws IOException {
-		long offset = idx(ctx).findOffset(id);
+		long offset = getPackIndex(ctx).findOffset(id);
 		return 0 < offset && !isCorrupt(offset) ? load(ctx, offset) : null;
 	}
 
 	long findOffset(DfsReader ctx, AnyObjectId id) throws IOException {
-		return idx(ctx).findOffset(id);
+		return getPackIndex(ctx).findOffset(id);
 	}
 
 	/**
@@ -513,7 +510,7 @@ List<DfsObjectToPack> findAllFromPack(DfsReader ctx,
 			if (skipFound && otp.isFound()) {
 				continue;
 			}
-			long p = idx(ctx).findOffset(otp);
+			long p = getPackIndex(ctx).findOffset(otp);
 			if (p <= 0 || isCorrupt(p)) {
 				continue;
 			}
@@ -526,7 +523,7 @@ List<DfsObjectToPack> findAllFromPack(DfsReader ctx,
 
 	void resolve(DfsReader ctx, Set<ObjectId> matches, AbbreviatedObjectId id,
 			int matchLimit) throws IOException {
-		idx(ctx).resolve(matches, id, matchLimit);
+		getPackIndex(ctx).resolve(matches, id, matchLimit);
 	}
 
 	private byte[] decompress(long position, int sz, DfsReader ctx)
@@ -703,11 +700,11 @@ void copyAsIs(PackOutputStream out, DfsObjectToPack src,
 		try {
 			quickCopy = ctx.quickCopy(this, dataOffset, dataLength);
 
-			if (validate && idx(ctx).hasCRC32Support()) {
+			if (validate && getPackIndex(ctx).hasCRC32Support()) {
 				assert(crc1 != null);
 				// Index has the CRC32 code cached, validate the object.
 				//
-				expectedCRC = idx(ctx).findCRC32(src);
+				expectedCRC = getPackIndex(ctx).findCRC32(src);
 				if (quickCopy != null) {
 					quickCopy.crc32(crc1, dataOffset, (int) dataLength);
 				} else {
@@ -1000,7 +997,7 @@ ObjectLoader load(DfsReader ctx, long pos)
 
 	private long findDeltaBase(DfsReader ctx, ObjectId baseId)
 			throws IOException, MissingObjectException {
-		long ofs = idx(ctx).findOffset(baseId);
+		long ofs = getPackIndex(ctx).findOffset(baseId);
 		if (ofs < 0) {
 			throw new MissingObjectException(baseId,
 					JGitText.get().missingDeltaBase);
@@ -1094,7 +1091,7 @@ int getObjectType(DfsReader ctx, long pos) throws IOException {
 	}
 
 	long getObjectSize(DfsReader ctx, AnyObjectId id) throws IOException {
-		final long offset = idx(ctx).findOffset(id);
+		final long offset = getPackIndex(ctx).findOffset(id);
 		return 0 < offset ? getObjectSize(ctx, offset) : -1;
 	}
 
@@ -1545,7 +1542,8 @@ public LoadResult loadPackBitmapIndex(DfsReader ctx, DfsPackFile pack)
 				PackBitmapIndex bmidx;
 				try {
 					bmidx = PackBitmapIndex.read(alignTo8kBlocks(rc),
-							() -> pack.idx(ctx), () -> pack.getReverseIdx(ctx),
+							() -> pack.getPackIndex(ctx),
+							() -> pack.getReverseIdx(ctx),
 							ctx.getOptions().shouldLoadRevIndexInParallel());
 				} finally {
 					size = rc.position();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java
index 742fe6c..3c63db2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java
@@ -9,227 +9,87 @@
  */
 package org.eclipse.jgit.internal.storage.dfs;
 
-import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
-import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
-
 import java.io.IOException;
-import java.nio.channels.Channels;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Function;
-import java.util.stream.Collectors;
 import java.util.zip.DataFormatException;
 
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
-import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
-import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
 import org.eclipse.jgit.internal.storage.file.PackIndex;
 import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
 import org.eclipse.jgit.internal.storage.midx.MultiPackIndex;
-import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.PackOffset;
-import org.eclipse.jgit.internal.storage.midx.MultiPackIndexLoader;
 import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
 import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
 import org.eclipse.jgit.lib.AbbreviatedObjectId;
 import org.eclipse.jgit.lib.AnyObjectId;
-import org.eclipse.jgit.lib.BitmapIndex;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectIdSet;
 import org.eclipse.jgit.lib.ObjectLoader;
-import org.eclipse.jgit.util.BlockList;
 
 /**
- * Implementation of a DfsPackfile that tries to solve the queries in a
- * multipack index before resorting to the real packs.
+ * DfsPackFile with the extra methods to support midx.
  * <p>
- * It uses the position in the multipack index of the objects as their "offset".
+ * This is an abstract class to keep the inheritance from DfsPackFile and allow
+ * a dummy implementation for single packs.
+ * <p>
+ * We implement at this level methods that just translate midx to pack offsets
+ * and forward to the pack.
  */
-public final class DfsPackFileMidx extends DfsPackFile {
+public abstract sealed class DfsPackFileMidx extends DfsPackFile
+		permits DfsPackFileMidxNPacks, DfsPackFileMidxSingle {
 
-	private static final int REF_POSITION = 0;
-
-	private final List<DfsPackFile> packs;
-
-	// The required packs, in the order specified in the multipack index
-	// Initialized lazily, when the midx is loaded
-	private final DfsPackFile[] packsInIdOrder;
-
-	private MultiPackIndex midx;
-
-	private final DfsPackFileMidx base;
-
-	private final VOffsetCalculator offsetCalculator;
-
-	static DfsPackFileMidx create(DfsBlockCache cache, DfsPackDescription desc,
-			List<DfsPackFile> reqPacks, DfsPackFileMidx base) {
-		return new DfsPackFileMidx(cache, desc, reqPacks, base);
-	}
-
-	private DfsPackFileMidx(DfsBlockCache cache, DfsPackDescription desc,
-			List<DfsPackFile> requiredPacks, @Nullable DfsPackFileMidx base) {
-		super(cache, desc);
-		this.base = base;
-		this.packs = requiredPacks;
-		String[] coveredPackNames = desc.getCoveredPacks().stream()
-				.map(DfsPackDescription::getPackName).toArray(String[]::new);
-		packsInIdOrder = getPacksInMidxIdOrder(coveredPackNames);
-		offsetCalculator = VOffsetCalculator.fromPacks(packsInIdOrder,
-				base != null ? base.getOffsetCalculator() : null);
-		this.length = offsetCalculator.getMaxOffset();
-	}
-
-	private MultiPackIndex midx(DfsReader ctx) throws IOException {
-		if (midx != null) {
-			return midx;
+	/**
+	 * Create a midx pack
+	 *
+	 * @param cache
+	 *            dfs block cache
+	 * @param desc
+	 *            description of the pack, covering at least one other pack
+	 * @param requiredPacks
+	 *            DfsPackFile instances of the covered packs
+	 * @param base
+	 *            midx acting a base of this
+	 * @return a midx pack
+	 */
+	public static DfsPackFileMidx create(DfsBlockCache cache,
+			DfsPackDescription desc, List<DfsPackFile> requiredPacks,
+			@Nullable DfsPackFileMidx base) {
+		if (desc.getCoveredPacks().size() == 1) {
+			return new DfsPackFileMidxSingle(cache, desc, requiredPacks.get(0),
+					base);
 		}
-
-		DfsStreamKey revKey = desc.getStreamKey(MULTI_PACK_INDEX);
-		// Keep the value parsed in the loader, in case the Ref<> is
-		// nullified in ClockBlockCacheTable#reserveSpace
-		// before we read its value.
-		AtomicReference<MultiPackIndex> loadedRef = new AtomicReference<>(null);
-		DfsBlockCache.Ref<MultiPackIndex> cachedRef = cache.getOrLoadRef(revKey,
-				REF_POSITION, () -> {
-					RefWithSize midx1 = loadMultiPackIndex(ctx, desc);
-					loadedRef.set(midx1.idx);
-					return new DfsBlockCache.Ref<>(revKey, REF_POSITION,
-							midx1.size, midx1.idx);
-				});
-		// if (loadedRef.get() == null) {
-		// ctx.stats.ridxCacheHit;
-		// }
-		midx = cachedRef.get() != null ? cachedRef.get() : loadedRef.get();
-		return midx;
-	}
-
-	private static RefWithSize loadMultiPackIndex(DfsReader ctx,
-			DfsPackDescription desc) throws IOException {
-		try (ReadableChannel rc = ctx.db.openFile(desc, MULTI_PACK_INDEX)) {
-			MultiPackIndex midx = MultiPackIndexLoader
-					.read(Channels.newInputStream(rc));
-			// ctx.stats.readIdxBytes += rc.position();
-			return new RefWithSize(midx, midx.getMemorySize());
-		}
-	}
-
-	private record RefWithSize(MultiPackIndex idx, long size) {
-	}
-
-	private DfsPackFile[] getPacksInMidxIdOrder(String[] packNames) {
-		Map<String, DfsPackFile> byName = packs.stream()
-				.collect(Collectors.toUnmodifiableMap(
-						p -> p.getPackDescription().getPackName(),
-						Function.identity()));
-		DfsPackFile[] result = new DfsPackFile[desc.getCoveredPacks().size()];
-		for (int i = 0; i < packNames.length; i++) {
-			DfsPackFile pack = byName.get(packNames[i]);
-			if (pack == null) {
-				// This should have been checked in the object db
-				// when the pack description was loaded
-				throw new IllegalStateException("Required pack missing"); //$NON-NLS-1$
-			}
-			result[i] = pack;
-		}
-		return result;
-	}
-
-	// Visible for testing
-	VOffsetCalculator getOffsetCalculator() {
-		return offsetCalculator;
-	}
-
-	@Override
-	public PackIndex getPackIndex(DfsReader ctx) {
-		throw new IllegalStateException(
-				"Shouldn't use multipack index if the primary index is needed"); //$NON-NLS-1$
-	}
-
-	@Override
-	public ObjectIdSet asObjectIdSet(DfsReader ctx) throws IOException {
-		MultiPackIndex multiPackIndex = midx(ctx);
-		return objectId -> multiPackIndex.hasObject(objectId);
-	}
-
-	@Override
-	public PackReverseIndex getReverseIdx(DfsReader ctx) {
-		throw new IllegalStateException(
-				"Shouldn't use multipack index if the reverse index is needed"); //$NON-NLS-1$
-	}
-
-	@Override
-	public PackBitmapIndex getBitmapIndex(DfsReader ctx) throws IOException {
-		// TODO(ifrade): at some point we will have bitmaps over the multipack
-		// index
-		// At the moment bitmap is in GC, at the end of the chain
-		if (base != null) {
-			return base.getBitmapIndex(ctx);
-		}
-
-		for (DfsPackFile pack : packsInIdOrder) {
-			PackBitmapIndex bitmapIndex = pack.getBitmapIndex(ctx);
-			if (bitmapIndex != null) {
-				return bitmapIndex;
-			}
-		}
-		return null;
-	}
-
-	@Override
-	List<DfsPackFile> fullyIncludedIn(DfsReader ctx,
-			BitmapIndex.BitmapBuilder need) throws IOException {
-		List<DfsPackFile> fullyIncluded = new ArrayList<>();
-		for (DfsPackFile pack : packs) {
-			List<DfsPackFile> includedPacks = pack.fullyIncludedIn(ctx, need);
-			if (!includedPacks.isEmpty()) {
-				fullyIncluded.addAll(includedPacks);
-			}
-		}
-
-		if (base != null) {
-			fullyIncluded.addAll(base.fullyIncludedIn(ctx, need));
-		}
-
-		return fullyIncluded;
-	}
-
-	@Override
-	public CommitGraph getCommitGraph(DfsReader ctx) throws IOException {
-		for (DfsPackFile pack : packs) {
-			CommitGraph cg = pack.getCommitGraph(ctx);
-			if (cg != null) {
-				return cg;
-			}
-		}
-		return null;
+		return new DfsPackFileMidxNPacks(cache, desc, requiredPacks, base);
 	}
 
 	/**
-	 * Count of objects in this <b>pack</> (i.e. including, recursively, its
-	 * base)
+	 * Default constructor
 	 *
-	 * @param ctx
-	 *            a reader
-	 * @return count of objects in this pack, including its bases
-	 * @throws IOException
-	 *             an error reading a midx in the chain
+	 * @param cache
+	 *            dfs block cache
+	 * @param desc
+	 *            midx pack description
 	 */
-	private int getObjectCount(DfsReader ctx) throws IOException {
-		int baseObjectCount = base == null ? 0 : base.getObjectCount(ctx);
-		return midx(ctx).getObjectCount() + baseObjectCount;
+	protected DfsPackFileMidx(DfsBlockCache cache, DfsPackDescription desc) {
+		super(cache, desc);
 	}
 
 	/**
+	 * Base of this multipack index
+	 * <p>
+	 * If this midx is part of a chain, this is its parent
+	 *
+	 * @return the base of this multipack index
+	 */
+	public abstract DfsPackFileMidx getMultipackIndexBase();
+
+	/**
 	 * Packs indexed by this multipack index (base NOT included)
 	 *
 	 * @return packs indexed by this multipack index
 	 */
-	public List<DfsPackFile> getCoveredPacks() {
-		return packs;
-	}
+	public abstract List<DfsPackFile> getCoveredPacks();
 
 	/**
 	 * All packs indexed by this multipack index and its chain
@@ -240,7 +100,7 @@ public List<DfsPackFile> getCoveredPacks() {
 	 * @return packs indexed by this multipack index and its parents.
 	 */
 	public List<DfsPackFile> getAllCoveredPacks() {
-		List<DfsPackFile> coveredPacks = new ArrayList<>(packs);
+		List<DfsPackFile> coveredPacks = new ArrayList<>(getCoveredPacks());
 		DfsPackFileMidx base = getMultipackIndexBase();
 		while (base != null) {
 			coveredPacks.addAll(base.getCoveredPacks());
@@ -251,62 +111,89 @@ public List<DfsPackFile> getAllCoveredPacks() {
 	}
 
 	/**
-	 * Base of this multipack index
+	 * Get the objectId at the corresponding position in the midx chain up to
+	 * this point
 	 * <p>
-	 * If this midx is part of a chain, this is its parent
+	 * In a chain with midx-tip (100 objects) and midx-base (50 objects),
+	 * positions 0-49 belong to the base midx and 50-149 to the tip midx.
 	 *
-	 * @return the base of this multipack index
+	 * @param ctx
+	 *            a reader for the midx data
+	 * @param nthPosition
+	 *            position in midx chain
+	 * @return the objectId
+	 * @throws IOException
+	 *             a problem reading midx bytes
 	 */
-	public DfsPackFileMidx getMultipackIndexBase() {
-		return base;
+	abstract ObjectId getObjectAt(DfsReader ctx, long nthPosition)
+			throws IOException;
+
+	/**
+	 * Count of objects in this <b>pack</b> (i.e. including, recursively, its
+	 * base)
+	 *
+	 * @param ctx
+	 *            a reader
+	 * @return count of objects in this pack, including its bases
+	 * @throws IOException
+	 *             an error reading a midx in the chain
+	 */
+	protected int getObjectCount(DfsReader ctx) throws IOException {
+		return (int) getPackDescription().getObjectCount();
 	}
 
+	/**
+	 * Return checksum of the midx
+	 *
+	 * @param ctx
+	 *            a reader
+	 * @return checksum of the midx
+	 * @throws IOException
+	 *             an error reading the file
+	 */
+	protected abstract byte[] getChecksum(DfsReader ctx) throws IOException;
+
+	/**
+	 * Get a midx iterator over the contents of *this* midx, without the base.
+	 *
+	 * @param ctx
+	 *            a ready
+	 * @return an iterator over the objects in this midx in sha1 order
+	 * @throws IOException
+	 *             an error loading the underlying data
+	 */
+	protected abstract MultiPackIndex.MidxIterator localIterator(DfsReader ctx)
+			throws IOException;
+
 	@Override
-	public int findIdxPosition(DfsReader ctx, AnyObjectId id)
-			throws IOException {
-		int p = midx(ctx).findPosition(id);
-		if (p >= 0) {
-			int baseObjects = base == null ? 0 : base.getObjectCount(ctx);
-			return p + baseObjects;
-		}
-
-		if (base == null) {
-			return -1;
-		}
-
-		return base.findIdxPosition(ctx, id);
+	public final PackIndex getPackIndex(DfsReader ctx) {
+		return new MidxPackIndex(this, ctx);
 	}
 
+	/**
+	 * Return all objects in this midx (not recursively) as ObjectToPack
+	 * instances (oid, offset, type). Ordered by sha1.
+	 * <p>
+	 * ObjectToPack is the preferred format for the bitmap builder. This can
+	 * probably be optimized.
+	 *
+	 * @param ctx
+	 *            a reader
+	 * @return list of objects in this midx (NOT in its chain) with offset and
+	 *         type
+	 * @throws IOException
+	 *             an error reading the midx
+	 */
+	abstract List<ObjectToPack> getLocalObjects(DfsReader ctx)
+			throws IOException;
+
 	@Override
-	public boolean hasObject(DfsReader ctx, AnyObjectId id) throws IOException {
-		if (midx(ctx).hasObject(id)) {
-			return true;
-		}
-
-		if (base == null) {
-			return false;
-		}
-
-		return base.hasObject(ctx, id);
-	}
-
-	@Override
-	ObjectLoader get(DfsReader ctx, AnyObjectId id) throws IOException {
-		PackOffset location = midx(ctx).find(id);
-		if (location != null) {
-			return packsInIdOrder[location.getPackId()].get(ctx, id);
-		}
-
-		if (base == null) {
-			return null;
-		}
-
-		return base.get(ctx, id);
-	}
+	public abstract PackReverseIndex getReverseIdx(DfsReader ctx)
+			throws IOException;
 
 	@Override
 	ObjectLoader load(DfsReader ctx, long midxOffset) throws IOException {
-		DfsPackOffset location = offsetCalculator.decode(midxOffset);
+		DfsPackOffset location = getOffsetCalculator().decode(midxOffset);
 		if (location == null) {
 			return null;
 		}
@@ -314,41 +201,6 @@ ObjectLoader load(DfsReader ctx, long midxOffset) throws IOException {
 	}
 
 	@Override
-	long findOffset(DfsReader ctx, AnyObjectId id) throws IOException {
-		PackOffset location = midx(ctx).find(id);
-		if (location != null) {
-			return offsetCalculator.encode(location);
-		}
-
-		if (base == null) {
-			return -1;
-		}
-
-		return base.findOffset(ctx, id);
-	}
-
-	@Override
-	void resolve(DfsReader ctx, Set<ObjectId> matches, AbbreviatedObjectId id,
-			int matchLimit) throws IOException {
-		midx(ctx).resolve(matches, id, matchLimit);
-		if (matches.size() < matchLimit && base != null) {
-			base.resolve(ctx, matches, id, matchLimit);
-		}
-	}
-
-	@Override
-	void copyPackAsIs(PackOutputStream out, DfsReader ctx) throws IOException {
-		// Assumming the order of the packs does not really matter
-		for (DfsPackFile pack : packs) {
-			pack.copyPackAsIs(out, ctx);
-		}
-
-		if (base != null) {
-			base.copyPackAsIs(out, ctx);
-		}
-	}
-
-	@Override
 	void copyAsIs(PackOutputStream out, DfsObjectToPack src, boolean validate,
 			DfsReader ctx) throws IOException,
 			StoredObjectRepresentationNotAvailableException {
@@ -357,7 +209,7 @@ void copyAsIs(PackOutputStream out, DfsObjectToPack src, boolean validate,
 					"pack mismatch in object description"); //$NON-NLS-1$
 		}
 
-		DfsPackOffset location = offsetCalculator.decode(src.offset);
+		DfsPackOffset location = getOffsetCalculator().decode(src.offset);
 		// The real pack requires the real offset
 		src.offset = location.getPackOffset();
 		location.getPack().copyAsIs(out, src, validate, ctx);
@@ -366,90 +218,31 @@ void copyAsIs(PackOutputStream out, DfsObjectToPack src, boolean validate,
 	}
 
 	@Override
-	byte[] getDeltaHeader(DfsReader ctx, long pos)
+	final byte[] getDeltaHeader(DfsReader ctx, long pos)
 			throws IOException, DataFormatException {
-		DfsPackOffset location = offsetCalculator.decode(pos);
+		DfsPackOffset location = getOffsetCalculator().decode(pos);
 		return location.getPack().getDeltaHeader(ctx, location.getPackOffset());
 	}
 
 	@Override
-	int getObjectType(DfsReader ctx, long pos) throws IOException {
-		DfsPackOffset location = offsetCalculator.decode(pos);
+	final int getObjectType(DfsReader ctx, long pos) throws IOException {
+		DfsPackOffset location = getOffsetCalculator().decode(pos);
 		return location.getPack().getObjectType(ctx, location.getPackOffset());
 	}
 
 	@Override
-	long getObjectSize(DfsReader ctx, AnyObjectId id) throws IOException {
-		PackOffset local = midx(ctx).find(id);
-		if (local != null) {
-			return packsInIdOrder[local.getPackId()].getObjectSize(ctx, id);
-		}
-
-		if (base == null) {
-			return -1;
-		}
-
-		return base.getObjectSize(ctx, id);
-	}
-
-	@Override
-	long getObjectSize(DfsReader ctx, long pos) throws IOException {
+	final long getObjectSize(DfsReader ctx, long pos) throws IOException {
 		if (pos < 0) {
 			return -1;
 		}
-		DfsPackOffset location = offsetCalculator.decode(pos);
+		DfsPackOffset location = getOffsetCalculator().decode(pos);
 		return location.getPack().getObjectSize(ctx, location.getPackOffset());
 	}
 
 	@Override
-	boolean hasObjectSizeIndex(DfsReader ctx) {
-		return false;
-	}
-
-	@Override
-	int getObjectSizeIndexThreshold(DfsReader ctx) {
-		return Integer.MAX_VALUE;
-	}
-
-	@Override
-	long getIndexedObjectSize(DfsReader ctx, int idxPosition) {
-		// TODO(ifrade): if we forward to the pack, it reads its primary index
-		return -1;
-	}
-
-	@Override
-	List<DfsObjectToPack> findAllFromPack(DfsReader ctx,
-			Iterable<ObjectToPack> objects, boolean skipFound)
-			throws IOException {
-		List<DfsObjectToPack> tmp = new BlockList<>();
-		List<ObjectToPack> notFoundHere = new BlockList<>();
-		for (ObjectToPack obj : objects) {
-			DfsObjectToPack otp = (DfsObjectToPack) obj;
-			if (skipFound && otp.isFound()) {
-				continue;
-			}
-			long p = offsetCalculator.encode(midx(ctx).find(otp));
-			if (p < 0) {
-				notFoundHere.add(otp);
-				continue;
-			}
-			otp.setOffset(p);
-			tmp.add(otp);
-		}
-
-		if (base != null && !notFoundHere.isEmpty()) {
-			List<DfsObjectToPack> inChain = base.findAllFromPack(ctx,
-					notFoundHere, skipFound);
-			tmp.addAll(inChain);
-		}
-		tmp.sort(OFFSET_SORT);
-		return tmp;
-	}
-
-	@Override
-	void fillRepresentation(DfsObjectRepresentation r, long offset,
+	final void fillRepresentation(DfsObjectRepresentation r, long offset,
 			DfsReader ctx) throws IOException {
-		DfsPackOffset location = offsetCalculator.decode(offset);
+		DfsPackOffset location = getOffsetCalculator().decode(offset);
 		if (location == null) {
 			throw new IllegalArgumentException("Invalid offset in midx"); //$NON-NLS-1$
 		}
@@ -462,16 +255,16 @@ void fillRepresentation(DfsObjectRepresentation r, long offset,
 	}
 
 	@Override
-	void fillRepresentation(DfsObjectRepresentation r, long offset,
+	final void fillRepresentation(DfsObjectRepresentation r, long offset,
 			DfsReader ctx, PackReverseIndex rev) {
 		// This method shouldn't be called on the midx pack
 		throw new UnsupportedOperationException();
 	}
 
 	@Override
-	boolean isCorrupt(long offset) {
+	final boolean isCorrupt(long offset) {
 		// The index must have been loaded before to have this offset
-		DfsPackOffset location = offsetCalculator.decode(offset);
+		DfsPackOffset location = getOffsetCalculator().decode(offset);
 		if (location == null) {
 			throw new IllegalArgumentException("Invalid offset in midx"); //$NON-NLS-1$
 		}
@@ -479,105 +272,102 @@ boolean isCorrupt(long offset) {
 	}
 
 	@Override
-	DfsBlock readOneBlock(long pos, DfsReader ctx, ReadableChannel rc)
+	final DfsBlock readOneBlock(long pos, DfsReader ctx, ReadableChannel rc)
 			throws IOException {
 		// The index must have been loaded before to have this offset
-		DfsPackOffset location = offsetCalculator.decode(pos);
+		DfsPackOffset location = getOffsetCalculator().decode(pos);
 		return new DfsBlockMidx(location.getPack().readOneBlock(
 				location.getPackOffset(), ctx, rc), location.getPackStart());
 	}
 
 	@Override
-	DfsBlock getOrLoadBlock(long pos, DfsReader ctx) throws IOException {
+	final DfsBlock getOrLoadBlock(long pos, DfsReader ctx) throws IOException {
 		// The index must have been loaded before to have this offset
-		DfsPackOffset location = offsetCalculator.decode(pos);
+		DfsPackOffset location = getOffsetCalculator().decode(pos);
 		return new DfsBlockMidx(location.getPack().getOrLoadBlock(
 				location.getPackOffset(), ctx), location.getPackStart());
 	}
 
-	// Visible for testing
-	static class VOffsetCalculator {
-		private final DfsPackFile[] packs;
+	/**
+	 * Get the object calculator of this midx
+	 *
+	 * @return an offset calculator for this midx (including its chain)
+	 */
+	protected abstract VOffsetCalculator getOffsetCalculator();
 
-		private final long[] accSizes;
+	/**
+	 * Translates from midx-offset (considering all packs concatenated in midx
+	 * order) to (pack, offset) pair. This covers the whole midx chain.
+	 *
+	 * @implNote implementations take care of the encoding and chaining offset
+	 *           calculators.
+	 */
+	protected interface VOffsetCalculator {
+		/**
+		 * Return the pair of pack and offset from a midx offset
+		 *
+		 * @param voffset
+		 *            an offset in the midx chain
+		 * @return the corresponding pack and offset pair
+		 */
+		DfsPackOffset decode(long voffset);
 
-		private final long baseMaxOffset;
-
-		private final VOffsetCalculator baseOffsetCalculator;
-
-		private final DfsPackOffset poBuffer = new DfsPackOffset();
-
-		static VOffsetCalculator fromPacks(DfsPackFile[] packsInIdOrder,
-				VOffsetCalculator baseOffsetCalculator) {
-			long[] accSizes = new long[packsInIdOrder.length + 1];
-			accSizes[0] = 0;
-			for (int i = 0; i < packsInIdOrder.length; i++) {
-				accSizes[i + 1] = accSizes[i] + packsInIdOrder[i]
-						.getPackDescription().getFileSize(PACK);
-			}
-			return new VOffsetCalculator(packsInIdOrder, accSizes,
-					baseOffsetCalculator);
-		}
-
-		VOffsetCalculator(DfsPackFile[] packs, long[] packSizes,
-				VOffsetCalculator baseOffsetCalculator) {
-			this.packs = packs;
-			this.baseOffsetCalculator = baseOffsetCalculator;
-			this.baseMaxOffset = baseOffsetCalculator != null
-					? baseOffsetCalculator.getMaxOffset()
-					: 0;
-			accSizes = packSizes;
-		}
-
-		long encode(PackOffset location) {
-			if (location == null) {
-				return -1;
-			}
-			return location.getOffset() + accSizes[location.getPackId()]
-					+ baseMaxOffset;
-		}
-
-		DfsPackOffset decode(long voffset) {
-			if (voffset == -1) {
-				return null;
-			}
-
-			if (voffset < baseMaxOffset) {
-				return baseOffsetCalculator.decode(voffset);
-			}
-
-			long localOffset = voffset - baseMaxOffset;
-			for (int i = 0; i < accSizes.length; i++) {
-				if (localOffset <= accSizes[i]) {
-					return poBuffer.setValues(packs[i - 1],
-							accSizes[i - 1] + baseMaxOffset, voffset);
-				}
-			}
-			throw new IllegalArgumentException("Asking offset beyond limits"); //$NON-NLS-1$
-		}
-
-		long getMaxOffset() {
-			return accSizes[accSizes.length - 1] + baseMaxOffset;
-		}
+		/**
+		 * Max offset for this DfsPackFileMidx
+		 *
+		 * @return max offset for this pack (including its parents)
+		 */
+		long getMaxOffset();
 	}
 
-	static class DfsPackOffset {
+	/**
+	 * Data object that keeps a location readable as midx-offset or as
+	 * (pack/offset).
+	 * <p>
+	 * midx-offset is the offset considering the concatenation of all covered
+	 * packs in midx order. Only in the first pack of the base of the midx
+	 * chain, the pack offsets match the midx offsets.
+	 */
+	protected static final class DfsPackOffset {
 		private DfsPackFile pack;
 
 		private long packStart;
 
-		private long offset;
+		private long midxOffset;
 
-		private DfsPackOffset setValues(DfsPackFile pack, long packStart,
-				long globalOffset) {
+		/**
+		 * Set a location in this instance
+		 *
+		 * @param pack
+		 *            the pack that contains the object
+		 * @param packStart
+		 *            midx-offset where the pack starts
+		 * @param midxOffset
+		 *            midx-offset
+		 * @return an instance with this data
+		 */
+		DfsPackOffset setValues(DfsPackFile pack, long packStart,
+				long midxOffset) {
 			this.pack = pack;
 			this.packStart = packStart;
-			this.offset = globalOffset;
+			this.midxOffset = midxOffset;
 			return this;
 		}
 
 		/**
-		 * The pack
+		 * Set only the midx-offset
+		 *
+		 * @param midxOffset
+		 *            offset in the midx
+		 * @return and updated DfsPackOffset instance
+		 */
+		DfsPackOffset setMidxOffset(long midxOffset) {
+			this.midxOffset = midxOffset;
+			return this;
+		}
+
+		/**
+		 * The pack containing the object
 		 *
 		 * @return the pack
 		 */
@@ -601,10 +391,107 @@ long getPackStart() {
 		/**
 		 * Offset inside the pack (regular offset)
 		 *
-		 * @return offset inside this pack
+		 * @return offset inside the pack
 		 */
 		long getPackOffset() {
-			return offset - packStart;
+			return midxOffset - packStart;
+		}
+	}
+
+	private static class MidxPackIndex implements PackIndex {
+
+		private final DfsPackFileMidx pack;
+
+		private final DfsReader ctx;
+
+		MidxPackIndex(DfsPackFileMidx pack, DfsReader ctx) {
+			this.pack = pack;
+			this.ctx = ctx;
+		}
+
+		@Override
+		public Iterator<MutableEntry> iterator() {
+			throw new UnsupportedOperationException("Not implemented yet");
+		}
+
+		@Override
+		public long getObjectCount() {
+			try {
+				return pack.getObjectCount(ctx);
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+		}
+
+		@Override
+		public long getOffset64Count() {
+			// TODO(ifrade): This method seems to be used only for stats.
+			// Maybe we can just remove it.
+			return 0;
+		}
+
+		@Override
+		public ObjectId getObjectId(long nthPosition) {
+			try {
+				return pack.getObjectAt(ctx, nthPosition);
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+		}
+
+		@Override
+		public long getOffset(long nthPosition) {
+			ObjectId objectAt;
+			try {
+				objectAt = pack.getObjectAt(ctx, nthPosition);
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+			if (objectAt == null) {
+				return -1;
+			}
+
+			return findOffset(objectAt);
+		}
+
+		@Override
+		public long findOffset(AnyObjectId objId) {
+			try {
+				return pack.findOffset(ctx, objId);
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+		}
+
+		@Override
+		public int findPosition(AnyObjectId objId) {
+			try {
+				return pack.findIdxPosition(ctx, objId);
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+		}
+
+		@Override
+		public long findCRC32(AnyObjectId objId)
+				throws UnsupportedOperationException {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public boolean hasCRC32Support() {
+			return false;
+		}
+
+		@Override
+		public void resolve(Set<ObjectId> matches, AbbreviatedObjectId id,
+				int matchLimit) throws IOException {
+			pack.resolve(ctx, matches, id, matchLimit);
+		}
+
+		@Override
+		public byte[] getChecksum() {
+			throw new UnsupportedOperationException();
 		}
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacks.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacks.java
new file mode 100644
index 0000000..f042f2e
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacks.java
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.pack.PackExt.BITMAP_INDEX;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
+
+import java.io.IOException;
+import java.nio.channels.Channels;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.errors.PackMismatchException;
+import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
+import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
+import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.PackOffset;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndexLoader;
+import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
+import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
+import org.eclipse.jgit.lib.AbbreviatedObjectId;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.BitmapIndex;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdSet;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.util.BlockList;
+
+/**
+ * Implementation of a DfsPackfile that tries to solve the queries in a
+ * multipack index before resorting to the real packs.
+ * <p>
+ * It uses the position in the multipack index of the objects as their "offset".
+ */
+public final class DfsPackFileMidxNPacks extends DfsPackFileMidx {
+
+	private static final int REF_POSITION = 0;
+
+	// The required packs, in the order specified in the multipack index
+	// Initialized lazily, when the midx is loaded
+	private final DfsPackFile[] packsInIdOrder;
+
+	private MultiPackIndex midx;
+
+	private final DfsPackFileMidx base;
+
+	private final VOffsetCalculatorNPacks offsetCalculator;
+
+	/**
+	 * Create the DfsPackFileMidx instance for this midx with n packs
+	 *
+	 * @param cache
+	 *            dfs block cache
+	 * @param desc
+	 *            description of the midx
+	 * @param knownPacks
+	 *            known packs, to translate the pack names in coveredPacks into
+	 *            DfsPackFile instances. It must contain at least all packs
+	 *            covered by this midx.
+	 * @param base
+	 *            base used by this midx.
+	 */
+	DfsPackFileMidxNPacks(DfsBlockCache cache, DfsPackDescription desc,
+			List<DfsPackFile> knownPacks, @Nullable DfsPackFileMidx base) {
+		super(cache, desc);
+		this.base = base;
+		String[] coveredPackNames = desc.getCoveredPacks().stream()
+				.map(DfsPackDescription::getPackName).toArray(String[]::new);
+		packsInIdOrder = getPacksInMidxIdOrder(knownPacks, coveredPackNames);
+		offsetCalculator = VOffsetCalculatorNPacks.fromPacks(packsInIdOrder,
+				base != null ? base.getOffsetCalculator() : null);
+		this.length = offsetCalculator.getMaxOffset();
+	}
+
+	private MultiPackIndex midx(DfsReader ctx) throws IOException {
+		if (midx != null) {
+			return midx;
+		}
+
+		DfsStreamKey revKey = desc.getStreamKey(MULTI_PACK_INDEX);
+		// Keep the value parsed in the loader, in case the Ref<> is
+		// nullified in ClockBlockCacheTable#reserveSpace
+		// before we read its value.
+		AtomicReference<MultiPackIndex> loadedRef = new AtomicReference<>(null);
+		DfsBlockCache.Ref<MultiPackIndex> cachedRef = cache.getOrLoadRef(revKey,
+				REF_POSITION, () -> {
+					RefWithSize midx1 = loadMultiPackIndex(ctx, desc);
+					loadedRef.set(midx1.idx);
+					return new DfsBlockCache.Ref<>(revKey, REF_POSITION,
+							midx1.size, midx1.idx);
+				});
+		// if (loadedRef.get() == null) {
+		// ctx.stats.ridxCacheHit;
+		// }
+		midx = cachedRef.get() != null ? cachedRef.get() : loadedRef.get();
+		return midx;
+	}
+
+	private static RefWithSize loadMultiPackIndex(DfsReader ctx,
+			DfsPackDescription desc) throws IOException {
+		try (ReadableChannel rc = ctx.db.openFile(desc, MULTI_PACK_INDEX)) {
+			MultiPackIndex midx = MultiPackIndexLoader
+					.read(Channels.newInputStream(rc));
+			// ctx.stats.readIdxBytes += rc.position();
+			return new RefWithSize(midx, midx.getMemorySize());
+		}
+	}
+
+	private record RefWithSize(MultiPackIndex idx, long size) {
+	}
+
+	private DfsPackFile[] getPacksInMidxIdOrder(List<DfsPackFile> knownPacks,
+			String[] packNames) {
+		Map<String, DfsPackFile> byName = knownPacks.stream()
+				.collect(Collectors.toUnmodifiableMap(
+						p -> p.getPackDescription().getPackName(),
+						Function.identity()));
+		DfsPackFile[] result = new DfsPackFile[desc.getCoveredPacks().size()];
+		for (int i = 0; i < packNames.length; i++) {
+			DfsPackFile pack = byName.get(packNames[i]);
+			if (pack == null) {
+				// This should have been checked in the object db
+				// when the pack description was loaded
+				throw new IllegalStateException("Required pack missing"); //$NON-NLS-1$
+			}
+			result[i] = pack;
+		}
+		return result;
+	}
+
+	// Visible for testing
+	@Override
+	protected VOffsetCalculatorNPacks getOffsetCalculator() {
+		return offsetCalculator;
+	}
+
+	@Override
+	public ObjectIdSet asObjectIdSet(DfsReader ctx) throws IOException {
+		MultiPackIndex multiPackIndex = midx(ctx);
+		return multiPackIndex::hasObject;
+	}
+
+	@Override
+	public PackBitmapIndex getBitmapIndex(DfsReader ctx) throws IOException {
+		// We have bitmaps only at the bottom of the midx or pack stack
+		if (base != null) {
+			return base.getBitmapIndex(ctx);
+		}
+
+		if (ctx.getOptions().shouldUseMidxBitmaps()
+				&& getPackDescription().hasFileExt(BITMAP_INDEX)) {
+			// Return our own bitmaps
+			return super.getBitmapIndex(ctx);
+		}
+
+		for (DfsPackFile pack : packsInIdOrder) {
+			PackBitmapIndex bitmapIndex = pack.getBitmapIndex(ctx);
+			if (bitmapIndex != null) {
+				return bitmapIndex;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	List<DfsPackFile> fullyIncludedIn(DfsReader ctx,
+			BitmapIndex.BitmapBuilder need) throws IOException {
+		List<DfsPackFile> fullyIncluded = new ArrayList<>();
+		for (DfsPackFile pack : packsInIdOrder) {
+			List<DfsPackFile> includedPacks = pack.fullyIncludedIn(ctx, need);
+			if (!includedPacks.isEmpty()) {
+				fullyIncluded.addAll(includedPacks);
+			}
+		}
+
+		if (base != null) {
+			fullyIncluded.addAll(base.fullyIncludedIn(ctx, need));
+		}
+
+		return fullyIncluded;
+	}
+
+	@Override
+	public CommitGraph getCommitGraph(DfsReader ctx) throws IOException {
+		for (DfsPackFile pack : packsInIdOrder) {
+			CommitGraph cg = pack.getCommitGraph(ctx);
+			if (cg != null) {
+				return cg;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public List<ObjectToPack> getLocalObjects(DfsReader ctx)
+			throws IOException {
+		MultiPackIndex midx = midx(ctx);
+		int localObjCount = midx(ctx).getObjectCount();
+		List<ObjectToPack> otps = new ArrayList<>(localObjCount);
+		for (int idxPosition = 0; idxPosition < localObjCount; idxPosition++) {
+			ObjectId oid = midx.getObjectAt(idxPosition);
+			PackOffset packOffset = midx.find(oid);
+			long offset = offsetCalculator.encode(packOffset);
+			int objectType = getObjectType(ctx, offset);
+			ObjectToPack otp = new ObjectToPack(oid, objectType);
+			otp.setOffset(offset);
+			otps.add(otp);
+		}
+		return otps;
+	}
+
+	@Override
+	public PackReverseIndex getReverseIdx(DfsReader ctx) throws IOException {
+		return new MidxReverseIndex(ctx, this,
+				base == null ? 0 : base.getObjectCount(ctx),
+				getOffsetCalculator().baseMaxOffset,
+				base == null ? null : base.getReverseIdx(ctx));
+	}
+
+	/**
+	 * Count of objects in this <b>pack</b> (i.e. including, recursively, its
+	 * base)
+	 *
+	 * @param ctx
+	 *            a reader
+	 * @return count of objects in this pack, including its bases
+	 * @throws IOException
+	 *             an error reading a midx in the chain
+	 */
+	@Override
+	protected int getObjectCount(DfsReader ctx) throws IOException {
+		int baseObjectCount = base == null ? 0 : base.getObjectCount(ctx);
+		return midx(ctx).getObjectCount() + baseObjectCount;
+	}
+
+	@Override
+	protected byte[] getChecksum(DfsReader ctx) throws IOException {
+		return midx(ctx).getChecksum();
+	}
+
+	@Override
+	protected MultiPackIndex.MidxIterator localIterator(DfsReader ctx)
+			throws IOException {
+		return midx(ctx).iterator();
+	}
+
+	/**
+	 * Packs indexed by this multipack index (base NOT included)
+	 *
+	 * @return packs indexed by this multipack index
+	 */
+	@Override
+	public List<DfsPackFile> getCoveredPacks() {
+		return List.of(packsInIdOrder);
+	}
+
+	/**
+	 * Base of this multipack index
+	 * <p>
+	 * If this midx is part of a chain, this is its parent
+	 *
+	 * @return the base of this multipack index
+	 */
+	@Override
+	public DfsPackFileMidx getMultipackIndexBase() {
+		return base;
+	}
+
+	@Override
+	ObjectId getObjectAt(DfsReader ctx, long nthPosition) throws IOException {
+		int baseObjectCount = base == null ? 0 : base.getObjectCount(ctx);
+		if (nthPosition >= baseObjectCount) {
+			long localPosition = nthPosition - baseObjectCount;
+			return midx(ctx).getObjectAt((int) localPosition);
+		}
+
+		return base.getObjectAt(ctx, nthPosition);
+	}
+
+	@Override
+	public int findIdxPosition(DfsReader ctx, AnyObjectId id)
+			throws IOException {
+		int p = midx(ctx).findPosition(id);
+		if (p >= 0) {
+			int baseObjects = base == null ? 0 : base.getObjectCount(ctx);
+			return p + baseObjects;
+		}
+
+		if (base == null) {
+			return -1;
+		}
+
+		return base.findIdxPosition(ctx, id);
+	}
+
+	@Override
+	public boolean hasObject(DfsReader ctx, AnyObjectId id) throws IOException {
+		if (midx(ctx).hasObject(id)) {
+			return true;
+		}
+
+		if (base == null) {
+			return false;
+		}
+
+		return base.hasObject(ctx, id);
+	}
+
+	@Override
+	ObjectLoader get(DfsReader ctx, AnyObjectId id) throws IOException {
+		PackOffset location = midx(ctx).find(id);
+		if (location != null) {
+			return packsInIdOrder[location.getPackId()].get(ctx, id);
+		}
+
+		if (base == null) {
+			return null;
+		}
+
+		return base.get(ctx, id);
+	}
+
+	@Override
+	long findOffset(DfsReader ctx, AnyObjectId id) throws IOException {
+		PackOffset location = midx(ctx).find(id);
+		if (location != null) {
+			return offsetCalculator.encode(location);
+		}
+
+		if (base == null) {
+			return -1;
+		}
+
+		return base.findOffset(ctx, id);
+	}
+
+	@Override
+	void resolve(DfsReader ctx, Set<ObjectId> matches, AbbreviatedObjectId id,
+			int matchLimit) throws IOException {
+		midx(ctx).resolve(matches, id, matchLimit);
+		if (matches.size() < matchLimit && base != null) {
+			base.resolve(ctx, matches, id, matchLimit);
+		}
+	}
+
+	@Override
+	void copyPackAsIs(PackOutputStream out, DfsReader ctx) throws IOException {
+		// Assumming the order of the packs does not really matter
+		for (DfsPackFile pack : packsInIdOrder) {
+			pack.copyPackAsIs(out, ctx);
+		}
+
+		if (base != null) {
+			base.copyPackAsIs(out, ctx);
+		}
+	}
+
+	@Override
+	long getObjectSize(DfsReader ctx, AnyObjectId id) throws IOException {
+		PackOffset local = midx(ctx).find(id);
+		if (local != null) {
+			return packsInIdOrder[local.getPackId()].getObjectSize(ctx, id);
+		}
+
+		if (base == null) {
+			return -1;
+		}
+
+		return base.getObjectSize(ctx, id);
+	}
+
+	@Override
+	boolean hasObjectSizeIndex(DfsReader ctx) {
+		return false;
+	}
+
+	@Override
+	int getObjectSizeIndexThreshold(DfsReader ctx) {
+		return Integer.MAX_VALUE;
+	}
+
+	@Override
+	long getIndexedObjectSize(DfsReader ctx, int idxPosition) {
+		// TODO(ifrade): if we forward to the pack, it reads its primary index
+		return -1;
+	}
+
+	@Override
+	List<DfsObjectToPack> findAllFromPack(DfsReader ctx,
+			Iterable<ObjectToPack> objects, boolean skipFound)
+			throws IOException {
+		List<DfsObjectToPack> tmp = new BlockList<>();
+		List<ObjectToPack> notFoundHere = new BlockList<>();
+		for (ObjectToPack obj : objects) {
+			DfsObjectToPack otp = (DfsObjectToPack) obj;
+			if (skipFound && otp.isFound()) {
+				continue;
+			}
+			long p = offsetCalculator.encode(midx(ctx).find(otp));
+			if (p < 0) {
+				notFoundHere.add(otp);
+				continue;
+			}
+			otp.setOffset(p);
+			tmp.add(otp);
+		}
+
+		if (base != null && !notFoundHere.isEmpty()) {
+			List<DfsObjectToPack> inChain = base.findAllFromPack(ctx,
+					notFoundHere, skipFound);
+			tmp.addAll(inChain);
+		}
+		tmp.sort(OFFSET_SORT);
+		return tmp;
+	}
+
+	// Visible for testing
+	static class VOffsetCalculatorNPacks implements VOffsetCalculator {
+		private final DfsPackFile[] packs;
+
+		private final long[] accSizes;
+
+		private final long baseMaxOffset;
+
+		private final VOffsetCalculator baseOffsetCalculator;
+
+		private final DfsPackOffset poBuffer = new DfsPackOffset();
+
+		private final PackOffset localPoBuffer = new PackOffset();
+
+		static VOffsetCalculatorNPacks fromPacks(DfsPackFile[] packsInIdOrder,
+				VOffsetCalculator baseOffsetCalculator) {
+			long[] accSizes = new long[packsInIdOrder.length + 1];
+			accSizes[0] = 0;
+			for (int i = 0; i < packsInIdOrder.length; i++) {
+				accSizes[i + 1] = accSizes[i] + packsInIdOrder[i]
+						.getPackDescription().getFileSize(PACK);
+			}
+			return new VOffsetCalculatorNPacks(packsInIdOrder, accSizes,
+					baseOffsetCalculator);
+		}
+
+		VOffsetCalculatorNPacks(DfsPackFile[] packs, long[] packSizes,
+				VOffsetCalculator baseOffsetCalculator) {
+			this.packs = packs;
+			this.baseOffsetCalculator = baseOffsetCalculator;
+			this.baseMaxOffset = baseOffsetCalculator != null
+					? baseOffsetCalculator.getMaxOffset()
+					: 0;
+			accSizes = packSizes;
+		}
+
+		long encode(MultiPackIndex.PackOffset location) {
+			if (location == null) {
+				return -1;
+			}
+			return location.getOffset() + accSizes[location.getPackId()]
+					+ baseMaxOffset;
+		}
+
+		MultiPackIndex.PackOffset decodeLocal(long voffset) {
+			if (voffset == -1 || voffset < baseMaxOffset
+					|| voffset > getMaxOffset()) {
+				return null;
+			}
+
+			long localOffset = voffset - baseMaxOffset;
+			for (int i = 1; i < accSizes.length; i++) {
+				if (localOffset <= accSizes[i]) {
+					return localPoBuffer.setValues(i - 1,
+							localOffset - accSizes[i - 1]);
+				}
+			}
+			return null;
+		}
+
+		@Override
+		public DfsPackOffset decode(long voffset) {
+			if (voffset == -1) {
+				return null;
+			}
+
+			if (voffset < baseMaxOffset) {
+				return baseOffsetCalculator.decode(voffset);
+			}
+
+			long localOffset = voffset - baseMaxOffset;
+			for (int i = 0; i < accSizes.length; i++) {
+				if (localOffset <= accSizes[i]) {
+					return poBuffer.setValues(packs[i - 1],
+							accSizes[i - 1] + baseMaxOffset, voffset);
+				}
+			}
+			throw new IllegalArgumentException("Asking offset beyond limits"); //$NON-NLS-1$
+		}
+
+		@Override
+		public long getMaxOffset() {
+			return accSizes[accSizes.length - 1] + baseMaxOffset;
+		}
+	}
+
+	private static final class MidxReverseIndex implements PackReverseIndex {
+		private final PackReverseIndex parentRidx;
+
+		private final DfsPackFileMidxNPacks localMidx;
+
+		private final DfsReader ctx;
+
+		private final long baseObjectCount;
+
+		private final long baseMaxOffset;
+
+		MidxReverseIndex(DfsReader ctx, DfsPackFileMidxNPacks localMidx,
+				long baseObjectCount, long baseMaxOffset,
+				PackReverseIndex parentRidx) {
+			this.ctx = ctx;
+			this.parentRidx = parentRidx;
+			this.localMidx = localMidx;
+			this.baseObjectCount = baseObjectCount;
+			this.baseMaxOffset = baseMaxOffset;
+		}
+
+		@Override
+		public void verifyPackChecksum(String packFilePath)
+				throws PackMismatchException {
+
+		}
+
+		private MultiPackIndex loadLocalMidx() {
+			try {
+				return localMidx.midx(ctx);
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+		}
+
+		@Override
+		public ObjectId findObject(long offset) {
+			if (offset < baseMaxOffset) {
+				return parentRidx.findObject(offset);
+			}
+
+			PackOffset localPo = localMidx.getOffsetCalculator()
+					.decodeLocal(offset);
+			if (localPo == null) {
+				return null;
+			}
+
+			int p = loadLocalMidx().findBitmapPosition(localPo);
+			if (p == -1) {
+				// If we found the local
+				// position, this should NOT
+				// happen
+				throw new IllegalStateException();
+			}
+
+			return loadLocalMidx().getObjectAtBitmapPosition(p);
+		}
+
+		@Override
+		public long findNextOffset(long offset, long maxOffset)
+				throws CorruptObjectException {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public int findPosition(long offset) {
+			if (offset < baseMaxOffset) {
+				return parentRidx.findPosition(offset);
+			}
+
+			PackOffset localPo = localMidx.getOffsetCalculator()
+					.decodeLocal(offset);
+			if (localPo == null) {
+				return -1;
+			}
+
+			return loadLocalMidx().findBitmapPosition(localPo)
+					+ (int) baseObjectCount;
+		}
+
+		@Override
+		public ObjectId findObjectByPosition(int nthPosition) {
+			if (nthPosition < baseObjectCount) {
+				return parentRidx.findObjectByPosition(nthPosition);
+			}
+			return loadLocalMidx().getObjectAtBitmapPosition(
+					nthPosition - (int) baseObjectCount);
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingle.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingle.java
new file mode 100644
index 0000000..89dbf9d
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingle.java
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.channels.Channels;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.errors.PackMismatchException;
+import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
+import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
+import org.eclipse.jgit.internal.storage.midx.MidxIterators;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.PackOffset;
+import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
+import org.eclipse.jgit.lib.AbbreviatedObjectId;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.BitmapIndex;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdSet;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.util.BlockList;
+import org.eclipse.jgit.util.IO;
+
+/**
+ * A single pack that looks like a midx, to be used in the midx chain
+ */
+public final class DfsPackFileMidxSingle extends DfsPackFileMidx {
+	private final SingleVOffsetCalculator offsetCalculator;
+
+	private final DfsPackFile pack;
+
+	private final DfsPackFileMidx base;
+
+	private byte[] checksum;
+
+	private final LocalPackOffset poBuffer = new LocalPackOffset();
+
+	DfsPackFileMidxSingle(DfsBlockCache cache, DfsPackDescription midxDesc,
+			DfsPackFile pack, @Nullable DfsPackFileMidx base) {
+		super(cache, midxDesc);
+		this.pack = pack;
+		offsetCalculator = new SingleVOffsetCalculator(this.pack,
+				base != null ? base.getOffsetCalculator() : null);
+		this.length = offsetCalculator.getMaxOffset();
+		this.base = base;
+	}
+
+	// Visible for testing
+	@Override
+	protected VOffsetCalculator getOffsetCalculator() {
+		return offsetCalculator;
+	}
+
+	@Override
+	public ObjectIdSet asObjectIdSet(DfsReader ctx) throws IOException {
+		return pack.asObjectIdSet(ctx);
+	}
+
+	@Override
+	public PackReverseIndex getReverseIdx(DfsReader ctx) throws IOException {
+		return new MidxReverseIndex(pack.getReverseIdx(ctx),
+				offsetCalculator.baseMaxOffset,
+				base == null ? null : base.getReverseIdx(ctx),
+				base == null ? 0 : base.getObjectCount(ctx));
+	}
+
+	@Override
+	public PackBitmapIndex getBitmapIndex(DfsReader ctx) throws IOException {
+		// TODO(ifrade): at some point we will have bitmaps over the multipack
+		// index
+		// At the moment bitmap is in GC, at the end of the chain
+		if (base != null) {
+			return base.getBitmapIndex(ctx);
+		}
+
+		return pack.getBitmapIndex(ctx);
+	}
+
+	@Override
+	List<DfsPackFile> fullyIncludedIn(DfsReader ctx,
+			BitmapIndex.BitmapBuilder need) throws IOException {
+		List<DfsPackFile> fullyIncluded = new ArrayList<>();
+		List<DfsPackFile> includedPacks = pack.fullyIncludedIn(ctx, need);
+		if (!includedPacks.isEmpty()) {
+			fullyIncluded.addAll(includedPacks);
+		}
+
+		if (base != null) {
+			fullyIncluded.addAll(base.fullyIncludedIn(ctx, need));
+		}
+
+		return fullyIncluded;
+	}
+
+	@Override
+	public CommitGraph getCommitGraph(DfsReader ctx) throws IOException {
+		return pack.getCommitGraph(ctx);
+	}
+
+	/**
+	 * Count of objects in this <b>pack</b> (i.e. including, recursively, its
+	 * base)
+	 *
+	 * @param ctx
+	 *            a reader
+	 * @return count of objects in this pack, including its bases
+	 * @throws IOException
+	 *             an error reading a midx in the chain
+	 */
+	@Override
+	protected int getObjectCount(DfsReader ctx) throws IOException {
+		int baseObjectCount = base == null ? 0 : base.getObjectCount(ctx);
+		return (int) pack.getPackDescription().getObjectCount()
+				+ baseObjectCount;
+	}
+
+	@Override
+	protected byte[] getChecksum(DfsReader ctx) throws IOException {
+		if (checksum == null) {
+			long checksumPos = desc.getFileSize(MULTI_PACK_INDEX) - 20;
+			if (checksumPos <= 0) {
+				throw new IllegalStateException("Midx stream too short");
+			}
+
+			try (ReadableChannel rc = ctx.db.openFile(desc, MULTI_PACK_INDEX);
+					InputStream in = Channels.newInputStream(rc)) {
+				checksum = new byte[20];
+				in.skip(checksumPos);
+				IO.readFully(in, checksum, 0, 20);
+			}
+		}
+		return checksum;
+	}
+
+	@Override
+	protected MultiPackIndex.MidxIterator localIterator(DfsReader ctx)
+			throws IOException {
+		String packName = pack.getPackDescription().getPackName();
+		PackIndex packIndex = pack.getPackIndex(ctx);
+		return MidxIterators.fromPackIndexIterator(packName, packIndex);
+	}
+
+	/**
+	 * Packs indexed by this multipack index (base NOT included)
+	 *
+	 * @return packs indexed by this multipack index
+	 */
+	@Override
+	public List<DfsPackFile> getCoveredPacks() {
+		return List.of(pack);
+	}
+
+	/**
+	 * Base of this multipack index
+	 * <p>
+	 * If this midx is part of a chain, this is its parent
+	 *
+	 * @return the base of this multipack index
+	 */
+	@Override
+	public DfsPackFileMidx getMultipackIndexBase() {
+		return base;
+	}
+
+	@Override
+	public int findIdxPosition(DfsReader ctx, AnyObjectId id)
+			throws IOException {
+		int p = pack.findIdxPosition(ctx, id);
+		if (p >= 0) {
+			int baseObjects = base == null ? 0 : base.getObjectCount(ctx);
+			return p + baseObjects;
+		}
+
+		if (base == null) {
+			return -1;
+		}
+
+		return base.findIdxPosition(ctx, id);
+	}
+
+	@Override
+	ObjectId getObjectAt(DfsReader ctx, long nthPosition) throws IOException {
+		int baseObjects = base == null ? 0 : base.getObjectCount(ctx);
+		if (nthPosition >= baseObjects) {
+			long localPosition = nthPosition - baseObjects;
+			return pack.getPackIndex(ctx).getObjectId(localPosition);
+		}
+
+		return base.getObjectAt(ctx, nthPosition);
+	}
+
+	@Override
+	public boolean hasObject(DfsReader ctx, AnyObjectId id) throws IOException {
+		if (pack.hasObject(ctx, id)) {
+			return true;
+		}
+
+		if (base == null) {
+			return false;
+		}
+
+		return base.hasObject(ctx, id);
+	}
+
+	@Override
+	ObjectLoader get(DfsReader ctx, AnyObjectId id) throws IOException {
+		ObjectLoader objectLoader = pack.get(ctx, id);
+		if (objectLoader != null) {
+			return objectLoader;
+		}
+
+		if (base == null) {
+			return null;
+		}
+
+		return base.get(ctx, id);
+	}
+
+	private PackOffset find(DfsReader ctx, AnyObjectId id) throws IOException {
+		long offset = pack.findOffset(ctx, id);
+		if (offset >= 0) {
+			poBuffer.setOffset(offset);
+			return poBuffer;
+		}
+		return null;
+	}
+
+	@Override
+	long findOffset(DfsReader ctx, AnyObjectId id) throws IOException {
+		PackOffset po = find(ctx, id);
+		if (po != null) {
+			return offsetCalculator.encode(po);
+		}
+
+		if (base == null) {
+			return -1;
+		}
+
+		return base.findOffset(ctx, id);
+	}
+
+	@Override
+	void resolve(DfsReader ctx, Set<ObjectId> matches, AbbreviatedObjectId id,
+			int matchLimit) throws IOException {
+		pack.resolve(ctx, matches, id, matchLimit);
+		if (matches.size() < matchLimit && base != null) {
+			base.resolve(ctx, matches, id, matchLimit);
+		}
+	}
+
+	@Override
+	void copyPackAsIs(PackOutputStream out, DfsReader ctx) throws IOException {
+		pack.copyPackAsIs(out, ctx);
+
+		if (base != null) {
+			base.copyPackAsIs(out, ctx);
+		}
+	}
+
+	@Override
+	long getObjectSize(DfsReader ctx, AnyObjectId id) throws IOException {
+		long objectSize = pack.getObjectSize(ctx, id);
+		if (objectSize >= 0) {
+			return objectSize;
+		}
+
+		if (base == null) {
+			return -1;
+		}
+
+		return base.getObjectSize(ctx, id);
+	}
+
+	@Override
+	boolean hasObjectSizeIndex(DfsReader ctx) {
+		// TODO(ifrade): If the base has object size index, we can say yes
+		return false;
+	}
+
+	@Override
+	int getObjectSizeIndexThreshold(DfsReader ctx) {
+		return Integer.MAX_VALUE;
+	}
+
+	@Override
+	long getIndexedObjectSize(DfsReader ctx, int idxPosition) {
+		return -1;
+	}
+
+	@Override
+	public List<ObjectToPack> getLocalObjects(DfsReader ctx)
+			throws IOException {
+		PackIndex idx = getPackIndex(ctx);
+		int localObjCount = (int) idx.getObjectCount();
+		List<ObjectToPack> otps = new ArrayList<>(localObjCount);
+		for (int idxPosition = 0; idxPosition < localObjCount; idxPosition++) {
+			ObjectId oid = idx.getObjectId(idxPosition);
+			long offset = idx.getOffset(idxPosition);
+			int objectType = getObjectType(ctx, offset);
+			ObjectToPack otp = new ObjectToPack(oid, objectType);
+			otp.setOffset(offset);
+			otps.add(otp);
+		}
+		return otps;
+	}
+
+	@Override
+	List<DfsObjectToPack> findAllFromPack(DfsReader ctx,
+			Iterable<ObjectToPack> objects, boolean skipFound)
+			throws IOException {
+		List<DfsObjectToPack> tmp = new BlockList<>();
+		List<ObjectToPack> notFoundHere = new BlockList<>();
+		for (ObjectToPack obj : objects) {
+			DfsObjectToPack otp = (DfsObjectToPack) obj;
+			if (skipFound && otp.isFound()) {
+				continue;
+			}
+			long p = offsetCalculator.encode(find(ctx, otp));
+			if (p < 0) {
+				notFoundHere.add(otp);
+				continue;
+			}
+			otp.setOffset(p);
+			tmp.add(otp);
+		}
+
+		if (base != null && !notFoundHere.isEmpty()) {
+			List<DfsObjectToPack> inChain = base.findAllFromPack(ctx,
+					notFoundHere, skipFound);
+			tmp.addAll(inChain);
+		}
+		tmp.sort(OFFSET_SORT);
+		return tmp;
+	}
+
+	/**
+	 * As this pack is always at the bottom, midx-offset is always offset
+	 */
+	static class SingleVOffsetCalculator implements VOffsetCalculator {
+
+		private final long packSize;
+
+		private final DfsPackOffset poBuffer = new DfsPackOffset();
+
+		private final VOffsetCalculator baseOffsetCalculator;
+
+		private final long baseMaxOffset;
+
+		SingleVOffsetCalculator(DfsPackFile realPack,
+				@Nullable VOffsetCalculator base) {
+			this.packSize = realPack.getPackDescription()
+					.getFileSize(PackExt.PACK);
+			this.baseOffsetCalculator = base;
+			baseMaxOffset = base != null ? base.getMaxOffset() : 0;
+			poBuffer.setValues(realPack, baseMaxOffset, 0);
+		}
+
+		long encode(PackOffset location) {
+			if (location == null) {
+				return -1;
+			}
+
+			if (location.getOffset() > packSize || location.getPackId() != 0) {
+				throw new IllegalArgumentException(String.format(
+						"Invalid midx location (packId: %d, offset: %d)", //$NON-NLS-1$
+						location.getPackId(), location.getOffset()));
+			}
+			return location.getOffset() + baseMaxOffset;
+		}
+
+		@Override
+		public DfsPackOffset decode(long voffset) {
+			if (voffset == -1) {
+				return null;
+			}
+
+			if (voffset < baseMaxOffset) {
+				return baseOffsetCalculator.decode(voffset);
+			}
+
+			long localOffset = voffset - baseMaxOffset;
+			if (localOffset > packSize) {
+				throw new IllegalArgumentException(
+						"Asking offset beyond limits"); //$NON-NLS-1$
+			}
+
+			return poBuffer.setMidxOffset(voffset);
+		}
+
+		@Override
+		public long getMaxOffset() {
+			return packSize + baseMaxOffset;
+		}
+	}
+
+	/**
+	 * A packOffset with the packId and packStart fixed to 0
+	 */
+	private static class LocalPackOffset extends PackOffset {
+
+		void setOffset(long offset) {
+			super.setValues(0, offset);
+		}
+	}
+
+	private static class MidxReverseIndex implements PackReverseIndex {
+		private final long baseMaxOffset;
+
+		private final long baseObjectCount;
+
+		private final PackReverseIndex baseRidx;
+
+		private final PackReverseIndex ridx;
+
+		MidxReverseIndex(PackReverseIndex ridx, long baseMaxOffset,
+				PackReverseIndex baseRidx, long baseObjectCount) {
+			this.ridx = ridx;
+			this.baseMaxOffset = baseMaxOffset;
+			this.baseRidx = baseRidx;
+			this.baseObjectCount = baseObjectCount;
+
+		}
+
+		@Override
+		public void verifyPackChecksum(String packFilePath)
+				throws PackMismatchException {
+
+		}
+
+		@Override
+		public ObjectId findObject(long offset) {
+			if (offset < baseMaxOffset) {
+				return baseRidx.findObject(offset);
+			}
+
+			long localOffset = offset - baseMaxOffset;
+			return ridx.findObject(localOffset);
+		}
+
+		@Override
+		public long findNextOffset(long offset, long maxOffset)
+				throws CorruptObjectException {
+			// TODO(ifrade): In this single-pack midx we can actually implement
+			// this
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public int findPosition(long offset) {
+			if (offset < baseMaxOffset) {
+				return baseRidx.findPosition(offset);
+			}
+			long localOffset = offset - baseMaxOffset;
+			return ridx.findPosition(localOffset) + (int) baseObjectCount;
+		}
+
+		@Override
+		public ObjectId findObjectByPosition(int nthPosition) {
+			if (nthPosition < baseObjectCount) {
+				return baseRidx.findObjectByPosition(nthPosition);
+			}
+			long localPosition = nthPosition - baseObjectCount;
+			// TODO(ifrade): Check downcasting
+			return ridx.findObjectByPosition((int) localPosition);
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderOptions.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderOptions.java
index c397469..e1d7047 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderOptions.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderOptions.java
@@ -40,6 +40,8 @@ public class DfsReaderOptions {
 
 	private boolean useObjectSizeIndex;
 
+	private boolean useMidxBitmaps;
+
 	/**
 	 * Create a default reader configuration.
 	 */
@@ -163,6 +165,29 @@ public DfsReaderOptions setUseObjectSizeIndex(boolean useObjectSizeIndex) {
 	}
 
 	/**
+	 * Use bitmaps in the midx if available.
+	 *
+	 * @return true if a midx pack should use its own bitmaps. false to fallback
+	 *         to GC bitmaps.
+	 */
+	public boolean shouldUseMidxBitmaps() {
+		return useMidxBitmaps;
+	}
+
+	/**
+	 * Set if the midx packs should use their bitmaps or fallback to bitmaps in
+	 * GC pack.
+	 *
+	 * @param useMidxBitmaps
+	 *            useMidxBitmaps to set
+	 * @return {@code this}
+	 */
+	public DfsReaderOptions setUseMidxBitmaps(boolean useMidxBitmaps) {
+		this.useMidxBitmaps = useMidxBitmaps;
+		return this;
+	}
+
+	/**
 	 * Update properties by setting fields from the configuration.
 	 * <p>
 	 * If a property is not defined in the configuration, then it is left
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackFilter.java
index 50de974..670950a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackFilter.java
@@ -9,13 +9,16 @@
  */
 package org.eclipse.jgit.internal.storage.dfs;
 
-import org.eclipse.jgit.internal.storage.pack.PackExt;
-
+import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+
 /**
  * Format a flat list of packs and midxs into a valid list of packs.
  * <p>
@@ -30,6 +33,23 @@ public class MidxPackFilter {
 	private MidxPackFilter() {
 	}
 
+	private static Comparator<DfsPackDescription> midxComparator = Comparator
+			.comparingLong(DfsPackDescription::getLastModified)
+			// If multiple midx where written at the same time, take the one
+			// with covering most objects first (it must be the tip)
+			.thenComparingLong(MidxPackFilter::getTotalCoveredObjects)
+			.reversed();
+
+	private static long getTotalCoveredObjects(DfsPackDescription desc) {
+		long objCount = 0;
+		DfsPackDescription current = desc;
+		while (current != null) {
+			objCount += current.getObjectCount();
+			current = current.getMultiPackIndexBase();
+		}
+		return objCount;
+	}
+
 	/**
 	 * Reorganize the flat list of packs removing the midxs
 	 *
@@ -59,40 +79,60 @@ public static List<DfsPackDescription> skipMidxs(
 	 */
 	public static List<DfsPackDescription> useMidx(
 			List<DfsPackDescription> packs) {
-		// Take the packs covered by the midxs out of the list
 		List<DfsPackDescription> midxs = packs.stream()
 				.filter(desc -> desc.hasFileExt(PackExt.MULTI_PACK_INDEX))
-				.toList();
+				.sorted(midxComparator).toList();
 		if (midxs.isEmpty()) {
 			return packs;
 		}
 
-		Set<DfsPackDescription> inputPacks = new HashSet<>(packs);
-		Set<DfsPackDescription> allCoveredPacks = new HashSet<>();
-		for (DfsPackDescription midx : midxs) {
-			Set<DfsPackDescription> coveredPacks = new HashSet<>();
-			findCoveredPacks(midx, coveredPacks);
-			if (!inputPacks.containsAll(coveredPacks)) {
-				// This midx references packs not in the pack db.
-				// It could be part of a chain, so we just ignore all midxs
-				return skipMidxs(packs);
-			}
-			allCoveredPacks.addAll(coveredPacks);
+		Set<DfsPackDescription> packsSet = new HashSet<>(packs);
+		Optional<DfsPackDescription> bestMidx = midxs.stream()
+				.filter(midx -> isValid(midx, packsSet)).findFirst();
+		if (bestMidx.isEmpty()) {
+			return skipMidxs(packs);
 		}
 
-		return packs.stream().filter(d -> !allCoveredPacks.contains(d))
-				.collect(Collectors.toList());
+		// Take the packs covered by the midxs and other midxs themselves out of
+		// the list
+		Set<DfsPackDescription> coveredPacksAndMidxs = getAllCoveredPacks(
+				bestMidx.get());
+		return packs.stream().filter(p -> !coveredPacksAndMidxs.contains(p))
+				// At this point, any midx in the list besides bestMidx is a
+				// straggler.
+				.filter(p -> !p.hasFileExt(PackExt.MULTI_PACK_INDEX)
+						|| p.equals(bestMidx.get()))
+				.collect(Collectors.toCollection(ArrayList::new));
 	}
 
-	private static void findCoveredPacks(DfsPackDescription midx,
-			Set<DfsPackDescription> covered) {
-		if (!midx.getCoveredPacks().isEmpty()) {
-			covered.addAll(midx.getCoveredPacks());
-		}
+	private static boolean isValid(DfsPackDescription midx,
+			Set<DfsPackDescription> packs) {
+		DfsPackDescription tip = midx;
+		while (tip != null) {
+			if (!packs.containsAll(tip.getCoveredPacks())) {
+				return false;
+			}
 
-		if (midx.getMultiPackIndexBase() != null) {
-			findCoveredPacks(midx.getMultiPackIndexBase(), covered);
-			covered.add(midx.getMultiPackIndexBase());
+			tip = tip.getMultiPackIndexBase();
 		}
+		return true;
+	}
+
+	private static Set<DfsPackDescription> getAllCoveredPacks(
+			DfsPackDescription midx) {
+		Set<DfsPackDescription> covered = new HashSet<>();
+		DfsPackDescription current = midx;
+		while (current != null) {
+			if (!current.getCoveredPacks().isEmpty()) {
+				covered.addAll(current.getCoveredPacks());
+			}
+
+			DfsPackDescription base = current.getMultiPackIndexBase();
+			if (base != null) {
+				covered.add(base);
+			}
+			current = base;
+		}
+		return covered;
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/RefAdvancerWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/RefAdvancerWalk.java
new file mode 100644
index 0000000..d0d8056
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/RefAdvancerWalk.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2026, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jgit.errors.StopWalkException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevSort;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.revwalk.filter.RevFilter;
+
+/**
+ * Walk from some commits and find where to they enter a pack
+ */
+class RefAdvancerWalk {
+
+	private final DfsRepository db;
+
+	private final InPackPredicate includeP;
+
+	/**
+	 * True when the commit is in the pack
+	 */
+	@FunctionalInterface
+	interface InPackPredicate {
+		boolean test(RevCommit c) throws IOException;
+	}
+
+	RefAdvancerWalk(DfsRepository db, InPackPredicate include) {
+		this.db = db;
+		this.includeP = include;
+	}
+
+	private RevWalk createRevWalk() {
+		RevWalk rw = new RevWalk(db);
+		rw.sort(RevSort.COMMIT_TIME_DESC);
+		rw.setRevFilter(new FirstInPack(includeP));
+		return rw;
+	}
+
+	/**
+	 * Advance the tips to their first commit inside the pack
+	 *
+	 * @param allTips
+	 *            tips of interesting refs
+	 * @return first commit(s) where the tips enter the pack. A tips may
+	 *         translate into 0 commits (it doesn't enter the pack in its
+	 *         history), 1 commit (a linear history) or n commits (merges lead
+	 *         to multiple histories into the pack). A tip already inside the
+	 *         pack is returned as it is.
+	 * @throws IOException
+	 *             error browsing history
+	 */
+	Set<RevCommit> advance(List<ObjectId> allTips) throws IOException {
+		Set<RevCommit> tipsInMidx = new HashSet<>(allTips.size());
+		try (RevWalk rw = createRevWalk()) {
+			for (ObjectId tip : allTips) {
+				RevObject tipObject = rw.parseAny(tip);
+				if (!(tipObject instanceof RevCommit tipCommit)) {
+					continue;
+				}
+
+				rw.markStart(tipCommit);
+				RevCommit inPack;
+				while ((inPack = rw.next()) != null) {
+					tipsInMidx.add(inPack);
+				}
+			}
+		}
+		return tipsInMidx;
+	}
+
+	private static class FirstInPack extends RevFilter {
+
+		private final InPackPredicate isInPack;
+
+		FirstInPack(InPackPredicate isInPack) {
+			this.isInPack = isInPack;
+		}
+
+		@Override
+		public boolean include(RevWalk walker, RevCommit cmit)
+				throws StopWalkException, IOException {
+			if (!isInPack.test(cmit)) {
+				return false;
+			}
+
+			for (RevCommit p : cmit.getParents()) {
+				walker.markUninteresting(p);
+			}
+			return true;
+		}
+
+		@Override
+		public RevFilter clone() {
+			return this;
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
index 7c6a304..6a78271 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
@@ -82,6 +82,8 @@
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.CoreConfig;
 import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.GcConfig;
+import org.eclipse.jgit.lib.GcConfig.PackRefsMode;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectIdSet;
@@ -171,6 +173,8 @@ public static void setExecutor(ExecutorService e) {
 
 	private PackConfig pconfig;
 
+	private GcConfig gcConfig;
+
 	/**
 	 * the refs which existed during the last call to {@link #repack()}. This is
 	 * needed during {@link #prune(Set)} where we can optimize by looking at the
@@ -207,6 +211,7 @@ public GC(FileRepository repo) {
 		this.repo = repo;
 		this.pconfig = new PackConfig(repo);
 		this.pm = NullProgressMonitor.INSTANCE;
+		this.gcConfig = repo.getConfig().get(GcConfig.KEY);
 	}
 
 	/**
@@ -282,6 +287,18 @@ private ExecutorService executor() {
 		return (executor != null) ? executor : WorkQueue.getExecutor();
 	}
 
+	/**
+	 * Set the gc configuration.
+	 *
+	 * @param gcConfig
+	 *            the gc configuration
+	 * @return this instance
+	 */
+	public GC setGcConfig(GcConfig gcConfig) {
+		this.gcConfig = gcConfig;
+		return this;
+	}
+
 	private Collection<Pack> doGc()
 			throws IOException, ParseException, GitAPIException {
 		if (automatic && !needGc()) {
@@ -292,8 +309,13 @@ private Collection<Pack> doGc()
 				return Collections.emptyList();
 			}
 			pm.start(6 /* tasks */);
-			new PackRefsCommand(repo).setProgressMonitor(pm).setAll(true)
-					.call();
+			boolean packRefs = gcConfig.getPackRefs() == PackRefsMode.TRUE
+					|| (gcConfig.getPackRefs() == PackRefsMode.NOTBARE
+							&& !repo.isBare());
+			if (packRefs) {
+				new PackRefsCommand(repo).setProgressMonitor(pm).setAll(true)
+						.call();
+			}
 			// TODO: implement reflog_expire(pm, repo);
 			Collection<Pack> newPacks = repack();
 			prune(Collections.emptySet());
@@ -747,6 +769,15 @@ private long getPackExpireDate() throws ParseException {
 	}
 
 	/**
+	 * Get the gc configuration.
+	 *
+	 * @return the gc configuration.
+	 */
+	public GcConfig getGcConfig() {
+		return gcConfig;
+	}
+
+	/**
 	 * Remove all entries from a map which key is the id of an object referenced
 	 * by the given ObjectWalk
 	 *
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
index 544961b..872bb9e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
@@ -313,45 +313,53 @@ private int checkRescanPackThreshold(int retries, PackMismatchException e)
 	}
 
 	private void handlePackError(IOException e, Pack p) {
-		String warnTemplate = null;
-		String debugTemplate = null;
-		int transientErrorCount = 0;
-		String errorTemplate = JGitText.get().exceptionWhileReadingPack;
-		if ((e instanceof CorruptObjectException)
-				|| (e instanceof PackInvalidException)) {
-			warnTemplate = JGitText.get().corruptPack;
-			LOG.warn(MessageFormat.format(warnTemplate,
-					p.getPackFile().getAbsolutePath()), e);
-			// Assume the pack is corrupted, and remove it from the list.
-			remove(p);
-		} else if (e instanceof FileNotFoundException) {
-			if (p.getPackFile().exists()) {
-				errorTemplate = JGitText.get().packInaccessible;
-				transientErrorCount = p.incrementTransientErrorCount();
-			} else {
-				debugTemplate = JGitText.get().packWasDeleted;
-				remove(p);
-			}
+		Throwable cause = e.getCause();
+		if (e instanceof FileNotFoundException
+				|| cause instanceof FileNotFoundException) {
+			handleFileNotFound(e, p);
+		} else if (e instanceof CorruptObjectException
+				|| e instanceof PackInvalidException) {
+			handleCorruptPack(e, p);
 		} else if (FileUtils.isStaleFileHandleInCausalChain(e)) {
-			warnTemplate = JGitText.get().packHandleIsStale;
-			remove(p);
+			handleStaleFileHandle(e, p);
 		} else {
-			transientErrorCount = p.incrementTransientErrorCount();
+			handleTransientError(e, p,
+					JGitText.get().exceptionWhileReadingPack);
 		}
-		if (warnTemplate != null) {
-			LOG.warn(MessageFormat.format(warnTemplate,
-					p.getPackFile().getAbsolutePath()), e);
-		} else if (debugTemplate != null) {
-			LOG.debug(MessageFormat.format(debugTemplate,
-				p.getPackFile().getAbsolutePath()), e);
+	}
+
+	private void handleFileNotFound(IOException e, Pack p) {
+		if (p.getPackFile().exists()) {
+			handleTransientError(e, p, JGitText.get().packInaccessible);
 		} else {
-			if (doLogExponentialBackoff(transientErrorCount)) {
-				// Don't remove the pack from the list, as the error may be
-				// transient.
-				LOG.error(MessageFormat.format(errorTemplate,
-						p.getPackFile().getAbsolutePath(),
-						Integer.valueOf(transientErrorCount)), e);
+			if (LOG.isDebugEnabled()) {
+				LOG.debug(MessageFormat.format(JGitText.get().packWasDeleted,
+						p.getPackFile().getAbsolutePath()), e);
 			}
+			remove(p);
+		}
+	}
+
+	private void handleCorruptPack(IOException e, Pack p) {
+		LOG.warn(MessageFormat.format(JGitText.get().corruptPack,
+				p.getPackFile().getAbsolutePath()), e);
+		// Assume the pack is corrupted, and remove it from the list.
+		remove(p);
+	}
+
+	private void handleStaleFileHandle(IOException e, Pack p) {
+		LOG.warn(MessageFormat.format(JGitText.get().packHandleIsStale,
+				p.getPackFile().getAbsolutePath()), e);
+		remove(p);
+	}
+
+	private void handleTransientError(IOException e, Pack p,
+			String errorTemplate) {
+		int transientErrorCount = p.incrementTransientErrorCount();
+		if (doLogExponentialBackoff(transientErrorCount)) {
+			LOG.error(MessageFormat.format(errorTemplate,
+					p.getPackFile().getAbsolutePath(),
+					Integer.valueOf(transientErrorCount)), e);
 		}
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
index 91f7b24..bacc1ec 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
@@ -121,6 +121,9 @@ public class RefDirectory extends RefDatabase {
 	/** If in the header, denotes the file has peeled data. */
 	public static final String PACKED_REFS_PEELED = " peeled"; //$NON-NLS-1$
 
+	/** If in the header, denotes the file has sorted data. */
+	public static final String PACKED_REFS_SORTED = " sorted"; //$NON-NLS-1$
+
 	@SuppressWarnings("boxing")
 	private static final List<Integer> RETRY_SLEEP_MS =
 			Collections.unmodifiableList(Arrays.asList(0, 100, 200, 400, 800, 1600));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MidxIterators.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MidxIterators.java
new file mode 100644
index 0000000..c30b9b8
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MidxIterators.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2026, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.midx;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.MidxIterator;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.MutableEntry;
+import org.eclipse.jgit.lib.MutableObjectId;
+
+/**
+ * Helpers for midx iterators
+ */
+public final class MidxIterators {
+
+	/**
+	 * Wrap a PackIndex iterator so it looks like a midx iterator with a fixed
+	 * packId
+	 *
+	 * @param packName
+	 *            pack name this iterator is going over
+	 * @param idx
+	 *            a PackIndex
+	 * @return a midx iterator that returns the objects of the pack index in the
+	 *         original iterator order
+	 */
+	public static MidxIterator fromPackIndexIterator(String packName,
+			PackIndex idx) {
+		return new MidxIteratorOverPackIndex(packName, idx);
+	}
+
+	/**
+	 * Merge results from multiple midx iterators.
+	 * <p>
+	 * This iterator can return duplicates (in ascending packId order). Wrap
+	 * with {@link #dedup(MidxIterator)} to remove duplicates.
+	 * <p>
+	 * This iterator shifts the pack ids in iterator order. If the first
+	 * iterator covers 3 packs, packIds of the second iterator are increased by
+	 * 3.
+	 *
+	 * @param iterators
+	 *            midx iterators to combine
+	 * @return a unique iterator that returns the union of the iterators in sha1
+	 *         order. The packIds of the entries are shi
+	 */
+	public static MidxIterator join(List<MidxIterator> iterators) {
+		return new JoinMidxIterator(iterators);
+	}
+
+	/**
+	 * Dedup consecutive duplicates from a midx iterator
+	 *
+	 * @param source
+	 *            a midx iterator emitting entries in sha1 order. In case of
+	 *            duplicates, the first one is returned and others skipped.
+	 * @return iterator without duplicates.
+	 */
+	public static MidxIterator dedup(MidxIterator source) {
+		return new DedupMidxIterator(source);
+	}
+
+	private MidxIterators() {
+	}
+
+	/**
+	 * Convert a PackIndex iterator into a MidxIterator
+	 */
+	private static class MidxIteratorOverPackIndex implements MidxIterator {
+
+		private final List<String> packNames;
+
+		private final PackIndex idx;
+
+		private Iterator<PackIndex.MutableEntry> idxIt;
+
+		private boolean peeked;
+
+		private final MutableEntry entry = new MutableEntry();
+
+		MidxIteratorOverPackIndex(String packName,
+				PackIndex idx) {
+			this.packNames = List.of(packName);
+			this.idx = idx;
+			this.idxIt = idx.iterator();
+		}
+
+		@Override
+		public MutableEntry peek() {
+			if (peeked) {
+				return entry;
+			}
+
+			peeked = true;
+			readNext();
+			return entry;
+		}
+
+		@Override
+		public List<String> getPackNames() {
+			return packNames;
+		}
+
+		@Override
+		public boolean hasNext() {
+			if (peeked) {
+				return true;
+			}
+			return idxIt.hasNext();
+		}
+
+		@Override
+		public MutableEntry next() {
+			if (peeked) {
+				peeked = false;
+				return entry;
+			}
+			readNext();
+			return entry;
+		}
+
+		private void readNext() {
+			PackIndex.MutableEntry idx = idxIt.next();
+			idx.copyOidTo(entry.oid);
+			entry.packOffset.setValues(0, idx.getOffset());
+		}
+
+		@Override
+		public void reset() {
+			this.idxIt = idx.iterator();
+			this.entry.clear();
+			peeked = false;
+		}
+	}
+
+	private static class JoinMidxIterator implements MidxIterator {
+
+		private final List<String> packNames;
+
+		private final List<MidxIterator> indexIterators;
+
+		private final int[] packCountAgg;
+
+		private final MutableEntry local = new MutableEntry();
+
+		public JoinMidxIterator(List<MidxIterator> indexIterators) {
+			this.indexIterators = indexIterators;
+			packCountAgg = new int[indexIterators.size()];
+			for (int i = 1; i < indexIterators.size(); i++) {
+				packCountAgg[i] = indexIterators.get(i - 1).getPackNames()
+						.size() + packCountAgg[i - 1];
+			}
+			packNames = indexIterators.stream().map(MidxIterator::getPackNames)
+					.flatMap(List::stream).toList();
+		}
+
+		@Override
+		public MutableEntry peek() {
+			int p = best();
+			MidxIterator it = indexIterators.get(p);
+			return shiftPackId(it.peek(), packCountAgg[p]);
+		}
+
+		@Override
+		public List<String> getPackNames() {
+			return packNames;
+		}
+
+		@Override
+		public boolean hasNext() {
+			return indexIterators.stream().anyMatch(Iterator::hasNext);
+		}
+
+		@Override
+		public MutableEntry next() {
+			int p = best();
+			MidxIterator it = indexIterators.get(p);
+			return shiftPackId(it.next(), packCountAgg[p]);
+		}
+
+		private MutableEntry shiftPackId(MutableEntry entry, int shift) {
+			local.fill(entry, shift);
+			return local;
+		}
+
+		private int best() {
+			int winnerPos = -1;
+			int winnerPackShift = 0;
+			MidxIterator winner = null;
+			for (int index = 0; index < indexIterators.size(); index++) {
+				MidxIterator current = indexIterators.get(index);
+				if (!current.hasNext()) {
+					continue;
+				}
+				if (winner == null
+						|| compareEntries(current.peek(), packCountAgg[index],
+								winner.peek(), winnerPackShift) < 0) {
+					winner = current;
+					winnerPos = index;
+					winnerPackShift = packCountAgg[winnerPos];
+				}
+			}
+
+			if (winner == null) {
+				throw new NoSuchElementException();
+			}
+
+			return winnerPos;
+		}
+
+		private static int compareEntries(MutableEntry a, int aPackShift,
+				MutableEntry b, int bPackShift) {
+			int cmp = a.oid.compareTo(b.oid);
+			if (cmp != 0) {
+				return cmp;
+			}
+
+			return Integer.compare(a.getPackId() + aPackShift,
+					b.getPackId() + bPackShift);
+		}
+
+		@Override
+		public void reset() {
+			indexIterators.stream().forEach(MidxIterator::reset);
+			local.clear();
+		}
+	}
+
+	private static class DedupMidxIterator implements MidxIterator {
+		private final MidxIterator src;
+
+		private final MutableObjectId lastOid = new MutableObjectId();
+
+		private MutableEntry next;
+
+		private final MutableEntry copy = new MutableEntry();
+
+		/**
+		 * Iterator over sorted by sha1 entries that removes duplicates choosing
+		 * the first one found.
+		 *
+		 * @param src
+		 *            iterator in sha1 order
+		 */
+		DedupMidxIterator(MidxIterator src) {
+			this.src = src;
+			readNext();
+		}
+
+		@Override
+		public MutableEntry peek() {
+			return next;
+		}
+
+		@Override
+		public List<String> getPackNames() {
+			return src.getPackNames();
+		}
+
+		@Override
+		public boolean hasNext() {
+			return next != null;
+		}
+
+		@Override
+		public MutableEntry next() {
+			copy.fill(next, 0);
+			readNext();
+			return copy;
+		}
+
+		private void readNext() {
+			while (true) {
+				if (!src.hasNext()) {
+					next = null;
+					return;
+				}
+
+				next = src.next();
+				if (!lastOid.equals(next.oid)) {
+					lastOid.fromObjectId(next.oid);
+					return;
+				}
+			}
+		}
+
+		@Override
+		public void reset() {
+			lastOid.clear();
+			src.reset();
+			readNext();
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndex.java
index edaa221..b209aa9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndex.java
@@ -10,23 +10,26 @@
 
 package org.eclipse.jgit.internal.storage.midx;
 
+import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 import org.eclipse.jgit.lib.AbbreviatedObjectId;
 import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.MutableObjectId;
 import org.eclipse.jgit.lib.ObjectId;
 
 /**
  * An index over multiple packs
  */
-public interface MultiPackIndex {
+public interface MultiPackIndex extends Iterable<MultiPackIndex.MutableEntry> {
 
 	/**
 	 * Obtain the array of packfiles in the MultiPackIndex.
 	 * <p>
 	 * The pack ids correspond to positions in this list.
 	 *
-	 * @return array of packnames refered in this multipak index
+	 * @return array of packnames refered in this multipack index
 	 */
 	String[] getPackNames();
 
@@ -66,6 +69,35 @@ public interface MultiPackIndex {
 	int findPosition(AnyObjectId objectId);
 
 	/**
+	 * Return the position in offset order (i.e. ridx or bitmap position) for
+	 * the (packId, offset) pair.
+	 *
+	 * @param po
+	 *            a location in the midx (packId, offset)
+	 * @return the position in the midx, in offset order
+	 */
+	int findBitmapPosition(PackOffset po);
+
+	/**
+	 * Object id at the specified position in offset order (i.e. position in the
+	 * ridx or bitmap)
+	 *
+	 * @param bitmapPosition
+	 *            position in the bitmap
+	 * @return object id at that position.
+	 */
+	ObjectId getObjectAtBitmapPosition(int bitmapPosition);
+
+	/**
+	 * ObjectId at this position in the midx
+	 *
+	 * @param position
+	 *            position inside this midx in sha1 order
+	 * @return the object id at that position
+	 */
+	ObjectId getObjectAt(int position);
+
+	/**
 	 * Number of objects in this midx
 	 * <p>
 	 * This number doesn't match with the sum of objects in each covered pack
@@ -90,6 +122,13 @@ public interface MultiPackIndex {
 	void resolve(Set<ObjectId> matches, AbbreviatedObjectId id, int matchLimit);
 
 	/**
+	 * Index checksum of the contents of this midx file
+	 *
+	 * @return checksum of the contents of this midx file
+	 */
+	byte[] getChecksum();
+
+	/**
 	 * Memory size of this multipack index
 	 *
 	 * @return size of this multipack index in memory, in bytes
@@ -97,13 +136,46 @@ public interface MultiPackIndex {
 	long getMemorySize();
 
 	/**
+	 * Return an iterator over the <em>local</em> objects in this midx.
+	 * <p>
+	 * In chained midxs, this iterator does not include the base midx.
+	 *
+	 * @return iterator in sha1 order of the objects in this midx
+	 */
+	@Override
+	MidxIterator iterator();
+
+	/**
+	 * An peekable iterator for the midx
+	 */
+	interface MidxIterator extends Iterator<MutableEntry> {
+		/**
+		 * Like next() but without advancing the iterator.
+		 *
+		 * @return next() element in the iterator without advancing
+		 */
+		MutableEntry peek();
+
+		/**
+		 * Pack names in the order of new packIds emitted by the iterator
+		 *
+		 * @return pack names
+		 */
+		List<String> getPackNames();
+
+		/**
+		 * Restart the iteration from the beginning
+		 */
+		void reset();
+	}
+
+	/**
 	 * (packId, offset) coordinates of an object
 	 * <p>
 	 * Mutable object to avoid creating many instances while looking for objects
 	 * in the pack. Use #copy() to get a new instance with the data.
 	 */
-	class PackOffset {
-
+	class PackOffset implements Comparable<PackOffset> {
 		private int packId;
 
 		private long offset;
@@ -123,7 +195,10 @@ public static PackOffset create(int packId, long offset) {
 			return new PackOffset().setValues(packId, offset);
 		}
 
-		protected PackOffset setValues(int packId, long offset) {
+		public PackOffset() {
+		}
+
+		public PackOffset setValues(int packId, long offset) {
 			this.packId = packId;
 			this.offset = offset;
 			return this;
@@ -141,5 +216,71 @@ public PackOffset copy() {
 			PackOffset copy = new PackOffset();
 			return copy.setValues(this.packId, this.offset);
 		}
+
+		@Override
+		public int compareTo(PackOffset packOffset) {
+			int cmp = this.packId - packOffset.packId;
+			if (cmp != 0) {
+				return cmp;
+			}
+
+			return Long.compare(this.offset, packOffset.offset);
+		}
+
+		@Override
+		public String toString() {
+			return String.format("PackOffset(packId=%d|offset=%d)", packId,
+					offset);
+
+		}
+	}
+
+	/**
+	 * Entry from the midx with object id, pack id, offset (in pack)
+	 * <p>
+	 * Mutable so the iterator can reuse the instance for performance.
+	 */
+	class MutableEntry {
+		protected final MutableObjectId oid = new MutableObjectId();
+
+		protected final PackOffset packOffset = new PackOffset();
+
+		/**
+		 * Copy data from other into this instance, adding the shift to the
+		 * packId
+		 *
+		 * @param other
+		 *            another entry
+		 * @param shift
+		 *            amount to add to the packid
+		 * @return this instance
+		 */
+		public MutableEntry fill(MutableEntry other, int shift) {
+			oid.fromObjectId(other.oid);
+			packOffset.setValues(other.getPackId() + shift, other.getOffset());
+			return this;
+		}
+
+		public MutableObjectId getObjectId() {
+			return oid;
+		}
+
+		public int getPackId() {
+			return packOffset.getPackId();
+		}
+
+		public long getOffset() {
+			return packOffset.getOffset();
+		}
+
+		public void clear() {
+			oid.clear();
+			packOffset.setValues(0, 0);
+		}
+
+		@Override
+		public String toString() {
+			return String.format("%s,%s", oid.name(), packOffset);
+		}
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoader.java
index 1d4f47a..4b70c2c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoader.java
@@ -187,11 +187,17 @@ public static MultiPackIndex read(InputStream fd)
 			case MIDX_CHUNKID_LARGEOFFSETS:
 				builder.addObjectLargeOffsets(buffer);
 				break;
+			case MIDX_CHUNKID_REVINDEX:
+				builder.addReverseIndex(buffer);
+				break;
 			default:
 				LOG.warn(MessageFormat.format(JGitText.get().midxChunkUnknown,
 						Integer.toHexString(chunkId)));
 			}
 		}
+		byte[] checksum = new byte[20];
+		IO.readFully(fd, checksum, 0, 20);
+		builder.addChecksum(checksum);
 		return builder.build();
 	}
 
@@ -223,6 +229,8 @@ static class MultiPackIndexBuilder {
 		// Optional
 		private byte[] bitmapPackOrder;
 
+		private byte[] checksum;
+
 		private MultiPackIndexBuilder(int hashLength) {
 			this.hashLength = hashLength;
 		}
@@ -300,7 +308,8 @@ MultiPackIndex build() throws MultiPackIndexFormatException {
 
 			assertPackCounts(packCount, packNames.length);
 			return new MultiPackIndexV1(hashLength, oidFanout, oidLookup,
-					packNames, bitmappedPackfiles, objectOffsets, largeObjectOffsets);
+					packNames, bitmappedPackfiles, objectOffsets,
+					largeObjectOffsets, bitmapPackOrder, checksum);
 		}
 
 		private static void assertChunkNotNull(Object object, int chunkId)
@@ -330,6 +339,10 @@ private static void assertPackCounts(int headerCount,
 						Integer.valueOf(packfileNamesCount)));
 			}
 		}
+
+		public void addChecksum(byte[] checksum) {
+			this.checksum = checksum;
+		}
 	}
 
 	/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexV1.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexV1.java
index 8ae1fe6..cfa5c33 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexV1.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexV1.java
@@ -12,6 +12,7 @@
 
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Set;
 
 import org.eclipse.jgit.annotations.NonNull;
@@ -20,6 +21,7 @@
 import org.eclipse.jgit.internal.storage.midx.MultiPackIndexLoader.MultiPackIndexFormatException;
 import org.eclipse.jgit.lib.AbbreviatedObjectId;
 import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.MutableObjectId;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.util.NB;
 
@@ -34,20 +36,25 @@ class MultiPackIndexV1 implements MultiPackIndex {
 
 	private final String[] packNames;
 
-	private final byte[] bitmappedPackfiles;
-
 	private final OffsetLookup offsets;
 
 	private final PackOffset result = new PackOffset();
 
+	private final ReverseIndex ridx;
+
+	private final byte[] checksum;
+
 	MultiPackIndexV1(int hashLength, @NonNull byte[] oidFanout,
 			@NonNull byte[] oidLookup, String[] packNames,
 			byte[] bitmappedPackfiles, byte[] objectOffsets,
-			byte[] largeObjectOffsets) throws MultiPackIndexFormatException {
-		this.bitmappedPackfiles = bitmappedPackfiles;
+			byte[] largeObjectOffsets, byte[] bitmapPackOrder, byte[] checksum)
+			throws MultiPackIndexFormatException {
 		this.idx = new OidLookup(hashLength, oidFanout, oidLookup);
 		this.offsets = new OffsetLookup(objectOffsets, largeObjectOffsets);
 		this.packNames = packNames;
+		this.ridx = new ReverseIndex(bitmapPackOrder, idx, offsets,
+				bitmappedPackfiles);
+		this.checksum = checksum;
 	}
 
 	@Override
@@ -66,6 +73,21 @@ public int findPosition(AnyObjectId oid) {
 	}
 
 	@Override
+	public int findBitmapPosition(PackOffset po) {
+		return ridx.findBitmapPosition(po);
+	}
+
+	@Override
+	public ObjectId getObjectAtBitmapPosition(int bitmapPosition) {
+		return ridx.getObjectId(bitmapPosition);
+	}
+
+	@Override
+	public ObjectId getObjectAt(int position) {
+		return idx.getObjectAt(position);
+	}
+
+	@Override
 	public int getObjectCount() {
 		return idx.getObjectCount();
 	}
@@ -88,23 +110,30 @@ public void resolve(Set<ObjectId> matches, AbbreviatedObjectId id,
 	}
 
 	@Override
+	public byte[] getChecksum() {
+		return checksum;
+	}
+
+	@Override
 	public long getMemorySize() {
 		int packNamesSize = Arrays.stream(packNames)
 				.mapToInt(s -> s.getBytes(StandardCharsets.UTF_8).length).sum();
-		return packNamesSize + byteArrayLengh(bitmappedPackfiles)
-				+ idx.getMemorySize() + offsets.getMemorySize();
+		return packNamesSize + ridx.getMemorySize() + idx.getMemorySize()
+				+ offsets.getMemorySize() + checksum.length;
 	}
 
+
 	@Override
 	public String toString() {
 		return "MultiPackIndexV1 {idx=" + idx + ", packfileNames=" //$NON-NLS-1$ //$NON-NLS-2$
-				+ Arrays.toString(packNames) + ", bitmappedPackfiles=" //$NON-NLS-1$
-				+ byteArrayToString(bitmappedPackfiles) + ", objectOffsets=" //$NON-NLS-1$
+				+ Arrays.toString(packNames) + ", ridx=" //$NON-NLS-1$
+				+ ridx + ", objectOffsets=" //$NON-NLS-1$
 				+ offsets + '}';
 	}
 
-	private static String byteArrayToString(byte[] array) {
-		return array == null ? "null" : new String(array); //$NON-NLS-1$
+	@Override
+	public MidxIterator iterator() {
+		return new LocalMidxIterator(this);
 	}
 
 	private static int byteArrayLengh(byte[] array) {
@@ -246,6 +275,11 @@ int findMultiPackIndexPosition(AnyObjectId id) {
 			return -1;
 		}
 
+		ObjectId getObjectAt(int midxPosition) {
+			int rawOffset = hashLength * midxPosition;
+			return ObjectId.fromRaw(oidLookup, rawOffset);
+		}
+
 		void resolve(Set<ObjectId> matches, AbbreviatedObjectId id,
 				int matchLimit) {
 			if (matches.size() >= matchLimit) {
@@ -307,5 +341,134 @@ long getMemorySize() {
 		int getObjectCount() {
 			return fanoutTable[FANOUT - 1];
 		}
+
+		void readOidAt(int position, MutableObjectId output) {
+			output.fromRaw(oidLookup, idOffset(position));
+		}
+	}
+
+	/**
+	 * Iterates over a single midx
+	 */
+	private static class LocalMidxIterator implements MidxIterator {
+
+		private final MultiPackIndexV1 midx;
+
+		private int position;
+
+		private final MutableEntry entry;
+
+		/**
+		 * Iterator over a single idx (ignoring the bse)
+		 *
+		 * @param midx
+		 *            the midx to iterate
+		 */
+		LocalMidxIterator(MultiPackIndexV1 midx) {
+			this.midx = midx;
+			this.entry = new MutableEntry();
+		}
+
+		@Override
+		public boolean hasNext() {
+			return position < midx.idx.getObjectCount();
+		}
+
+		@Override
+		public MutableEntry next() {
+			MutableEntry current = peek();
+			position++;
+			return current;
+		}
+
+		@Override
+		public MutableEntry peek() {
+			midx.idx.readOidAt(position, entry.oid);
+			midx.offsets.getObjectOffset(position, entry.packOffset);
+			return entry;
+		}
+
+		@Override
+		public List<String> getPackNames() {
+			return Arrays.asList(midx.getPackNames());
+		}
+
+		@Override
+		public void reset() {
+			position = 0;
+		}
+	}
+
+	private static class ReverseIndex {
+		private final byte[] bitmappedPackfiles;
+
+		private final byte[] bitmapPackOrder;
+
+		private final OffsetLookup offsets;
+
+		private final OidLookup oids;
+
+		ReverseIndex(byte[] bitmapPackOrder, OidLookup oids,
+				OffsetLookup offsets, byte[] bitmappedPackfiles) {
+			this.bitmappedPackfiles = bitmappedPackfiles;
+			this.bitmapPackOrder = bitmapPackOrder;
+			this.oids = oids;
+			this.offsets = offsets;
+		}
+
+		public int findBitmapPosition(PackOffset po) {
+			if (bitmapPackOrder == null || bitmappedPackfiles == null) {
+				return -1;
+			}
+
+			/*
+			 * Bitmapped Packfiles (ID: {'B', 'T', 'M', 'P'}) Stores a table of
+			 * two 4-byte unsigned integers in network order. Each table entry
+			 * corresponds to a single pack (in the order that they appear above
+			 * in the `PNAM` chunk). The values for each table entry are as
+			 * follows: - The first bit position (in pseudo-pack order, see
+			 * below) to contain an object from that pack. - The number of bits
+			 * whose objects are selected from that pack.
+			 */
+			int packStartBit = NB.decodeInt32(bitmappedPackfiles,
+					po.getPackId() * 8);
+			int packBitLength = NB.decodeInt32(bitmappedPackfiles,
+					(po.getPackId() * 8) + 4);
+			return binarySearch(packStartBit, packStartBit + packBitLength, po);
+		}
+
+		private int binarySearch(int start, int end, PackOffset needle) {
+			PackOffset result = new PackOffset();
+			int low = start;
+			int high = end;
+			while (low < high) {
+				int mid = (low + high) >>> 1;
+				int midxPosition = NB.decodeInt32(bitmapPackOrder, mid * 4);
+				offsets.getObjectOffset(midxPosition, result);
+				int cmp = needle.compareTo(result);
+				if (cmp < 0) {
+					high = mid;
+				} else if (cmp == 0) {
+					return mid;
+				} else {
+					low = mid + 1;
+				}
+			}
+			return -1;
+		}
+
+		public ObjectId getObjectId(int bitmapPosition) {
+			if (bitmapPackOrder == null) {
+				return null;
+			}
+			int midxPosition = NB.decodeInt32(bitmapPackOrder,
+					bitmapPosition * 4);
+			return oids.getObjectAt(midxPosition);
+		}
+
+		public long getMemorySize() {
+			return (long) byteArrayLengh(bitmapPackOrder)
+					+ byteArrayLengh(bitmappedPackfiles);
+		}
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java
index 993e7df..7c69b78 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java
@@ -10,6 +10,7 @@
 package org.eclipse.jgit.internal.storage.midx;
 
 import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_BITMAPPEDPACKS;
 import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_LARGEOFFSETS;
 import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OBJECTOFFSETS;
 import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDFANOUT;
@@ -34,9 +35,8 @@
 import java.util.Map;
 
 import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.internal.storage.file.PackIndex;
 import org.eclipse.jgit.internal.storage.io.CancellableDigestOutputStream;
-import org.eclipse.jgit.internal.storage.midx.PackIndexMerger.MidxMutableEntry;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.MutableEntry;
 import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.util.NB;
 
@@ -77,17 +77,15 @@ public record Result(long bytesWritten, int objectCount,
 	 *            progress monitor
 	 * @param outputStream
 	 *            stream to write the multipack index file
-	 * @param inputs
-	 *            pairs of name and index for each pack to include in the
-	 *            multipack index.
+	 * @param data
+	 *            a pack index merger with the data sources (in order) for this
+	 *            midx
 	 * @return data about the write (e.g. bytes written)
 	 * @throws IOException
 	 *             Error writing to the stream
 	 */
 	public Result write(ProgressMonitor monitor, OutputStream outputStream,
-			Map<String, PackIndex> inputs) throws IOException {
-		PackIndexMerger data = new PackIndexMerger(inputs);
-
+			PackIndexMerger data) throws IOException {
 		// List of chunks in the order they need to be written
 		List<ChunkHeader> chunkHeaders = createChunkHeaders(data);
 		long expectedSize = calculateExpectedSize(chunkHeaders);
@@ -137,6 +135,8 @@ private List<ChunkHeader> createChunkHeaders(PackIndexMerger data) {
 		}
 		chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_REVINDEX,
 				4L * data.getUniqueObjectCount(), this::writeRidx));
+		chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_BITMAPPEDPACKS,
+				8L * data.getPackCount(), this::writeBitmappedPackfiles));
 
 		int packNamesSize = data.getPackNames().stream()
 				.mapToInt(String::length).map(i -> i + 1 /* null at the end */)
@@ -220,9 +220,9 @@ private void writeChunkLookup(CancellableDigestOutputStream out,
 	private void writeFanoutTable(WriteContext ctx) throws IOException {
 		byte[] tmp = new byte[4];
 		int[] fanout = new int[256];
-		Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator();
+		Iterator<MutableEntry> iterator = ctx.data.bySha1Iterator();
 		while (iterator.hasNext()) {
-			MidxMutableEntry e = iterator.next();
+			MutableEntry e = iterator.next();
 			fanout[e.getObjectId().getFirstByte() & 0xff]++;
 		}
 		for (int i = 1; i < fanout.length; i++) {
@@ -247,9 +247,9 @@ private void writeFanoutTable(WriteContext ctx) throws IOException {
 	private void writeOidLookUp(WriteContext ctx) throws IOException {
 		byte[] tmp = new byte[OBJECT_ID_LENGTH];
 
-		Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator();
+		Iterator<MutableEntry> iterator = ctx.data.bySha1Iterator();
 		while (iterator.hasNext()) {
-			MidxMutableEntry e = iterator.next();
+			MutableEntry e = iterator.next();
 			e.getObjectId().copyRawTo(tmp, 0);
 			ctx.out.write(tmp, 0, OBJECT_ID_LENGTH);
 		}
@@ -269,9 +269,9 @@ private void writeOidLookUp(WriteContext ctx) throws IOException {
 	 */
 	private void writeObjectOffsets(WriteContext ctx) throws IOException {
 		byte[] entry = new byte[8];
-		Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator();
+		Iterator<MutableEntry> iterator = ctx.data.bySha1Iterator();
 		while (iterator.hasNext()) {
-			MidxMutableEntry e = iterator.next();
+			MutableEntry e = iterator.next();
 			NB.encodeInt32(entry, 0, e.getPackId());
 			if (!ctx.data.needsLargeOffsetsChunk()
 					|| fitsIn31bits(e.getOffset())) {
@@ -302,19 +302,18 @@ private void writeRidx(WriteContext ctx) throws IOException {
 		// memory. We could also iterate reverse indexes looking up
 		// their position in the midx (and discarding if the pack doesn't
 		// match).
-		Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator();
+		Iterator<MutableEntry> iterator = ctx.data.bySha1Iterator();
 		int midxPosition = 0;
 		while (iterator.hasNext()) {
-			MidxMutableEntry e = iterator.next();
+			MutableEntry e = iterator.next();
 			OffsetPosition op = new OffsetPosition(e.getOffset(), midxPosition);
 			midxPosition++;
-			packOffsets.computeIfAbsent(Integer.valueOf(e.getPackId()),
-					k -> new ArrayList<>()).add(op);
+			packOffsets.computeIfAbsent(e.getPackId(), k -> new ArrayList<>())
+					.add(op);
 		}
 
 		for (int i = 0; i < ctx.data.getPackCount(); i++) {
-			List<OffsetPosition> offsetsForPack = packOffsets
-					.get(Integer.valueOf(i));
+			List<OffsetPosition> offsetsForPack = packOffsets.get(i);
 			if (offsetsForPack == null) {
 				continue;
 			}
@@ -328,6 +327,21 @@ private void writeRidx(WriteContext ctx) throws IOException {
 		}
 	}
 
+	private void writeBitmappedPackfiles(WriteContext ctx) throws IOException {
+		int[] objsPerPack = ctx.data.getObjectsPerPack();
+
+		byte[] buffer = new byte[8 * objsPerPack.length];
+		int bufferPos = 0;
+		int accruedBitmapPositions = 0;
+		for (int pack = 0; pack < objsPerPack.length; pack++) {
+			NB.encodeInt32(buffer, bufferPos, accruedBitmapPositions);
+			NB.encodeInt32(buffer, bufferPos + 4, objsPerPack[pack]);
+			accruedBitmapPositions += objsPerPack[pack];
+			bufferPos += 8;
+		}
+		ctx.out.write(buffer);
+	}
+
 	/**
 	 * Write the large offset chunk
 	 * <p>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java
index fd040b9..3436446 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java
@@ -10,13 +10,11 @@
 package org.eclipse.jgit.internal.storage.midx;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
 
 import org.eclipse.jgit.internal.storage.file.PackIndex;
-import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.MidxIterator;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.MutableEntry;
 import org.eclipse.jgit.lib.MutableObjectId;
 
 /**
@@ -32,59 +30,13 @@
  * entries. The stats of the combined index are calculated in an iteration at
  * construction time.
  */
-class PackIndexMerger {
+public class PackIndexMerger {
 
 	private static final int LIMIT_31_BITS = (1 << 31) - 1;
 
 	private static final long LIMIT_32_BITS = (1L << 32) - 1;
 
-	/**
-	 * Object returned by the iterator.
-	 * <p>
-	 * The iterator returns (on each next()) the same instance with different
-	 * values, to avoid allocating many short-lived objects. Callers should not
-	 * keep a reference to that returned value.
-	 */
-	static class MidxMutableEntry {
-		// The object id
-		private final MutableObjectId oid = new MutableObjectId();
-
-		// Position of the pack in the ordered list of pack in this merger
-		private int packId;
-
-		// Offset in its pack
-		private long offset;
-
-		public AnyObjectId getObjectId() {
-			return oid;
-		}
-
-		public int getPackId() {
-			return packId;
-		}
-
-		public long getOffset() {
-			return offset;
-		}
-
-		/**
-		 * Copy values from another mutable entry
-		 *
-		 * @param packId
-		 *            packId
-		 * @param other
-		 *            another mutable entry
-		 */
-		private void fill(int packId, PackIndex.MutableEntry other) {
-			other.copyOidTo(oid);
-			this.packId = packId;
-			this.offset = other.getOffset();
-		}
-	}
-
-	private final List<String> packNames;
-
-	private final List<PackIndex> indexes;
+	private final MidxIterator midxIterator;
 
 	private final boolean needsLargeOffsetsChunk;
 
@@ -92,41 +44,101 @@ private void fill(int packId, PackIndex.MutableEntry other) {
 
 	private final int uniqueObjectCount;
 
-	/**
-	 * Build a common view of these pack indexes
-	 * <p>
-	 * Order matters: in case of duplicates, the first pack with the object wins
-	 *
-	 * @param packs
-	 *            map of pack names to indexes, ordered.
-	 */
-	PackIndexMerger(Map<String, PackIndex> packs) {
-		this.packNames = packs.keySet().stream().toList();
-		this.indexes = packs.values().stream().toList();
+	private final int[] objectsPerPack;
 
-		// Iterate for duplicates
+	private final List<String> packnames;
+
+	/**
+	 * Builder collecting the inputs for the merger.
+	 * <p>
+	 * Order matters. Packs will appear in the midx in the order they are added.
+	 */
+	public static class Builder {
+
+		private final List<MidxIterator> packIndexes = new ArrayList<>();
+
+		/**
+		 * Add a regular pack to the midx
+		 *
+		 * @param name
+		 *            name of the pack
+		 * @param idx
+		 *            primary index of the pack
+		 * @return this builder
+		 */
+		public Builder addPack(String name, PackIndex idx) {
+			packIndexes.add(MidxIterators.fromPackIndexIterator(name, idx));
+			return this;
+		}
+
+		/**
+		 * Add data from this midx iterator to the merge
+		 * <p>
+		 * Packs are kept in the order of the iterator.
+		 *
+		 * @param midx
+		 *            a midx iterator
+		 * @return this builder
+		 */
+		public Builder addMidx(MidxIterator midx) {
+			packIndexes.add(midx);
+			return this;
+		}
+
+		/**
+		 * Build the merger instance
+		 *
+		 * @return a merger instance
+		 */
+		public PackIndexMerger build() {
+			return new PackIndexMerger(
+					MidxIterators.dedup(MidxIterators.join(packIndexes)));
+		}
+	}
+
+	/**
+	 * Create a builder
+	 *
+	 * @return an empty builder
+	 */
+	public static Builder builder() {
+		return new Builder();
+	}
+
+	/**
+	 * A common view of the input pack indexes
+	 *
+	 * @param midxIterator
+	 *            MidxIterator built by deduping union of all pack indexes
+	 */
+	private PackIndexMerger(MidxIterator midxIterator) {
+		this.midxIterator = midxIterator;
+		this.packnames = midxIterator.getPackNames();
+
+		objectsPerPack = new int[packnames.size()];
+		// Iterate for duplicates and counts that we need to build the chunk
+		// headers.
 		int objectCount = 0;
 		boolean hasLargeOffsets = false;
 		int over31bits = 0;
 		MutableObjectId lastSeen = new MutableObjectId();
-		MultiIndexIterator it = new MultiIndexIterator(indexes);
-		while (it.hasNext()) {
-			MidxMutableEntry entry = it.next();
-			if (lastSeen.equals(entry.oid)) {
-				continue;
-			}
+		while (midxIterator.hasNext()) {
+			MutableEntry entry = midxIterator.next();
 			// If there is at least one offset value larger than 2^32-1, then
 			// the large offset chunk must exist, and offsets larger than
 			// 2^31-1 must be stored in it instead
-			if (entry.offset > LIMIT_32_BITS) {
+			if (entry.getOffset() > LIMIT_32_BITS) {
 				hasLargeOffsets = true;
 			}
-			if (entry.offset > LIMIT_31_BITS) {
+			if (entry.getOffset() > LIMIT_31_BITS) {
 				over31bits++;
 			}
 
 			lastSeen.fromObjectId(entry.oid);
 			objectCount++;
+			// TODO(ifrade): we can calculate the fanout table already here.
+			// It saves an iteration over all objects for only 1Kb of memory
+			objectsPerPack[entry.getPackId()]++;
 		}
 		uniqueObjectCount = objectCount;
 		offsetsOver31BitsCount = over31bits;
@@ -164,6 +176,16 @@ int getOffsetsOver31BitsCount() {
 	}
 
 	/**
+	 * Number of objects selected for the midx per pack id
+	 *
+	 * @return array where position n contains the amount of objects selected
+	 *         for pack id n
+	 */
+	int[] getObjectsPerPack() {
+		return objectsPerPack;
+	}
+
+	/**
 	 * List of pack names in alphabetical order.
 	 * <p>
 	 * Order matters: In case of duplicates, the multipack index prefers the
@@ -173,7 +195,7 @@ int getOffsetsOver31BitsCount() {
 	 * @return List of pack names, in the order used by the merge.
 	 */
 	List<String> getPackNames() {
-		return packNames;
+		return packnames;
 	}
 
 	/**
@@ -182,160 +204,22 @@ List<String> getPackNames() {
 	 * @return count of packs merged
 	 */
 	int getPackCount() {
-		return packNames.size();
+		return packnames.size();
 	}
 
 	/**
 	 * Iterator over the merged indexes in sha1 order without duplicates
 	 * <p>
+	 * This always returns the same iterator resetted. We don't support two
+	 * iterators over this merged data.
+	 * <p>
 	 * The returned entry in the iterator is mutable, callers should NOT keep a
 	 * reference to it.
 	 *
 	 * @return an iterator in sha1 order without duplicates.
 	 */
-	Iterator<MidxMutableEntry> bySha1Iterator() {
-		return new DedupMultiIndexIterator(new MultiIndexIterator(indexes),
-				getUniqueObjectCount());
-	}
-
-	/**
-	 * For testing. Iterate all entries, not skipping duplicates (stable order)
-	 *
-	 * @return an iterator of all objects in sha1 order, including duplicates.
-	 */
-	Iterator<MidxMutableEntry> rawIterator() {
-		return new MultiIndexIterator(indexes);
-	}
-
-	/**
-	 * Iterator over n-indexes in ObjectId order.
-	 * <p>
-	 * It returns duplicates if the same object id is in different indexes. Wrap
-	 * it with {@link DedupMultiIndexIterator (Iterator, int)} to avoid
-	 * duplicates.
-	 */
-	private static final class MultiIndexIterator
-			implements Iterator<MidxMutableEntry> {
-
-		private final List<PackIndexPeekIterator> indexIterators;
-
-		private final MidxMutableEntry mutableEntry = new MidxMutableEntry();
-
-		MultiIndexIterator(List<PackIndex> indexes) {
-			this.indexIterators = new ArrayList<>(indexes.size());
-			for (int i = 0; i < indexes.size(); i++) {
-				PackIndexPeekIterator it = new PackIndexPeekIterator(i,
-						indexes.get(i));
-				// Position in the first element
-				if (it.next() != null) {
-					indexIterators.add(it);
-				}
-			}
-		}
-
-		@Override
-		public boolean hasNext() {
-			return !indexIterators.isEmpty();
-		}
-
-		@Override
-		public MidxMutableEntry next() {
-			PackIndexPeekIterator winner = null;
-			for (int index = 0; index < indexIterators.size(); index++) {
-				PackIndexPeekIterator current = indexIterators.get(index);
-				if (winner == null
-						|| current.peek().compareBySha1To(winner.peek()) < 0) {
-					winner = current;
-				}
-			}
-
-			if (winner == null) {
-				throw new NoSuchElementException();
-			}
-
-			mutableEntry.fill(winner.getPackId(), winner.peek());
-			if (winner.next() == null) {
-				indexIterators.remove(winner);
-			}
-			return mutableEntry;
-		}
-	}
-
-	private static class DedupMultiIndexIterator
-			implements Iterator<MidxMutableEntry> {
-		private final MultiIndexIterator src;
-
-		private int remaining;
-
-		private final MutableObjectId lastOid = new MutableObjectId();
-
-		DedupMultiIndexIterator(MultiIndexIterator src, int totalCount) {
-			this.src = src;
-			this.remaining = totalCount;
-		}
-
-		@Override
-		public boolean hasNext() {
-			return remaining > 0;
-		}
-
-		@Override
-		public MidxMutableEntry next() {
-			MidxMutableEntry next = src.next();
-			while (next != null && lastOid.equals(next.oid)) {
-				next = src.next();
-			}
-
-			if (next == null) {
-				throw new NoSuchElementException();
-			}
-
-			lastOid.fromObjectId(next.oid);
-			remaining--;
-			return next;
-		}
-	}
-
-	/**
-	 * Convenience around the PackIndex iterator to read the current value
-	 * multiple times without consuming it.
-	 * <p>
-	 * This is used to merge indexes in the multipack index, where we need to
-	 * compare the current value between indexes multiple times to find the
-	 * next.
-	 * <p>
-	 * We could also implement this keeping the position (int) and
-	 * MutableEntry#getObjectId, but that would create an ObjectId per entry.
-	 * This implementation reuses the MutableEntry and avoid instantiations.
-	 */
-	// Visible for testing
-	static class PackIndexPeekIterator {
-		private final Iterator<PackIndex.MutableEntry> it;
-
-		private final int packId;
-
-		PackIndex.MutableEntry current;
-
-		PackIndexPeekIterator(int packId, PackIndex index) {
-			it = index.iterator();
-			this.packId = packId;
-		}
-
-		PackIndex.MutableEntry next() {
-			if (it.hasNext()) {
-				current = it.next();
-			} else {
-				current = null;
-			}
-			return current;
-		}
-
-		PackIndex.MutableEntry peek() {
-			return current;
-		}
-
-		int getPackId() {
-			return packId;
-		}
+	MidxIterator bySha1Iterator() {
+		midxIterator.reset();
+		return midxIterator;
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/BitmapCommit.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/BitmapCommit.java
index 33c478e..41cbe4b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/BitmapCommit.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/BitmapCommit.java
@@ -30,8 +30,21 @@ public final class BitmapCommit extends ObjectId {
 		this.addToIndex = false;
 	}
 
-	BitmapCommit(AnyObjectId objectId, boolean reuseWalker, int flags,
-				 boolean addToIndex) {
+	// Visible for testing
+	/**
+	 * Commit that should get a bitmap
+	 *
+	 * @param objectId
+	 *            objectId of the commit
+	 * @param reuseWalker
+	 *            if the bitmap walker can be reused
+	 * @param flags
+	 *            flags
+	 * @param addToIndex
+	 *            if the bitmap should be added to the index
+	 */
+	public BitmapCommit(AnyObjectId objectId, boolean reuseWalker, int flags,
+			boolean addToIndex) {
 		super(objectId);
 		this.reuseWalker = reuseWalker;
 		this.flags = flags;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackBitmapCalculator.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackBitmapCalculator.java
new file mode 100644
index 0000000..7fa635f
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackBitmapCalculator.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2026, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.pack;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.BitmapIndex;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.revwalk.BitmapWalker;
+import org.eclipse.jgit.storage.pack.PackConfig;
+
+/**
+ * Helper to find out interesting commits, create their bitmaps and write them
+ * into the PackBitmapIndexBuilder.
+ */
+public class PackBitmapCalculator {
+
+	private final PackConfig config;
+
+	/**
+	 * Constructor
+	 *
+	 * @param config
+	 *            configuration
+	 */
+	public PackBitmapCalculator(PackConfig config) {
+		this.config = config;
+	}
+
+	/**
+	 * Choose commits, create bitmaps and send them to the builder
+	 *
+	 * @param reader
+	 *            an object reader
+	 * @param pm
+	 *            a progress monitor
+	 * @param wants
+	 *            where to start walking looking for commits to bitmap
+	 * @param numCommits
+	 *            expected number of new commits to include in the bitmap
+	 * @param excludeFromBitmapSelection
+	 *            commits to ignore
+	 * @param writeBitmaps
+	 *            store of newly created bitmaps
+	 * @throws IOException
+	 *             an error
+	 */
+	public void calculate(ObjectReader reader, ProgressMonitor pm,
+			int numCommits, Set<? extends ObjectId> wants,
+			Set<? extends ObjectId> excludeFromBitmapSelection,
+			PackBitmapIndexBuilder writeBitmaps) throws IOException {
+		PackWriterBitmapPreparer bitmapPreparer = new PackWriterBitmapPreparer(
+				reader, writeBitmaps, pm, wants, config);
+
+		Collection<BitmapCommit> selectedCommits = bitmapPreparer
+				.selectCommits(numCommits, excludeFromBitmapSelection);
+		pm.beginTask(JGitText.get().buildingBitmaps, selectedCommits.size());
+
+		BitmapWalker walker = bitmapPreparer.newBitmapWalker();
+		AnyObjectId last = null;
+		for (BitmapCommit cmit : selectedCommits) {
+			if (!cmit.isReuseWalker()) {
+				walker = bitmapPreparer.newBitmapWalker();
+			}
+			BitmapIndex.BitmapBuilder bitmap = walker
+					.findObjects(Collections.singleton(cmit), null, false);
+
+			if (last != null && cmit.isReuseWalker() && !bitmap.contains(last))
+				throw new IllegalStateException(
+						MessageFormat.format(JGitText.get().bitmapMissingObject,
+								cmit.name(), last.name()));
+			last = BitmapCommit.copyFrom(cmit).build();
+			writeBitmaps.processBitmapForWrite(cmit, bitmap.build(),
+					cmit.getFlags());
+
+			// The bitmap walker should stop when the walk hits the previous
+			// commit, which saves time.
+			walker.setPrevCommit(last);
+			walker.setPrevBitmap(bitmap);
+
+			pm.update(1);
+		}
+		pm.endTask();
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
index 27fb814..c2d7577 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
@@ -2534,40 +2534,10 @@ public boolean prepareBitmapIndex(ProgressMonitor pm) throws IOException {
 		// Allow byName to be GC'd if JVM GC runs before the end of the method.
 		byName = null;
 
-		PackWriterBitmapPreparer bitmapPreparer = new PackWriterBitmapPreparer(
-				reader, writeBitmaps, pm, stats.interestingObjects, config);
+		PackBitmapCalculator bitmapWrite = new PackBitmapCalculator(config);
+		bitmapWrite.calculate(reader, pm, numCommits, stats.interestingObjects,
+				excludeFromBitmapSelection, writeBitmaps);
 
-		Collection<BitmapCommit> selectedCommits = bitmapPreparer
-				.selectCommits(numCommits, excludeFromBitmapSelection);
-
-		beginPhase(PackingPhase.BUILDING_BITMAPS, pm, selectedCommits.size());
-
-		BitmapWalker walker = bitmapPreparer.newBitmapWalker();
-		AnyObjectId last = null;
-		for (BitmapCommit cmit : selectedCommits) {
-			if (!cmit.isReuseWalker()) {
-				walker = bitmapPreparer.newBitmapWalker();
-			}
-			BitmapBuilder bitmap = walker.findObjects(
-					Collections.singleton(cmit), null, false);
-
-			if (last != null && cmit.isReuseWalker() && !bitmap.contains(last))
-				throw new IllegalStateException(MessageFormat.format(
-						JGitText.get().bitmapMissingObject, cmit.name(),
-						last.name()));
-			last = BitmapCommit.copyFrom(cmit).build();
-			writeBitmaps.processBitmapForWrite(cmit, bitmap.build(),
-					cmit.getFlags());
-
-			// The bitmap walker should stop when the walk hits the previous
-			// commit, which saves time.
-			walker.setPrevCommit(last);
-			walker.setPrevBitmap(bitmap);
-
-			pm.update(1);
-		}
-
-		endPhase(pm);
 		return true;
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java
index b1ba5df..ae5b214 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java
@@ -97,11 +97,11 @@ public boolean matchConfigValue(String in) {
 
 	private final static Charset DEFAULT_COMMIT_MESSAGE_ENCODING = StandardCharsets.UTF_8;
 
-	private String i18nCommitEncoding;
+	private final String i18nCommitEncoding;
 
-	private String commitTemplatePath;
+	private final String commitTemplatePath;
 
-	private CleanupMode cleanupMode;
+	private final CleanupMode cleanupMode;
 
 	private char commentCharacter = '#';
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
index 56b801e..73c7006 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -1122,4 +1122,11 @@ public final class ConfigConstants {
 	 * @since 7.5
 	 */
 	public static final String CONFIG_KEY_MULTIPACKINDEX = "multiPackIndex";
+
+	/**
+	 * The "packRefs" key
+	 *
+	 * @since 7.6
+	 */
+	public static final String CONFIG_KEY_PACK_REFS = "packRefs";
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GcConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GcConfig.java
new file mode 100644
index 0000000..7239bd7
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GcConfig.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2026, Matthias Sohn <matthias.sohn@sap.com>
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.lib;
+
+import org.eclipse.jgit.lib.Config.SectionParser;
+
+/**
+ * GC configuration settings.
+ *
+ * @since 7.6
+ */
+public class GcConfig {
+	/** Key for {@link Config#get(SectionParser)}. */
+	public static final Config.SectionParser<GcConfig> KEY = GcConfig::new;
+
+	/**
+	 * Whether to pack refs during gc.
+	 */
+	public enum PackRefsMode {
+		/**
+		 * Pack no refs.
+		 */
+		FALSE,
+		/**
+		 * Pack all refs except symbolic refs.
+		 */
+		TRUE,
+		/**
+		 * Pack all refs except symbolic refs within all non-bare repositories.
+		 */
+		NOTBARE
+	}
+
+	private final PackRefsMode packRefs;
+
+	/**
+	 * Create a new gc configuration from the passed configuration.
+	 *
+	 * @param rc
+	 *            git configuration
+	 */
+	public GcConfig(Config rc) {
+		this.packRefs = rc.getEnum(ConfigConstants.CONFIG_GC_SECTION, null,
+				ConfigConstants.CONFIG_KEY_PACK_REFS, PackRefsMode.TRUE);
+	}
+
+	/**
+	 * Create a new gc configuration with the given settings.
+	 *
+	 * @param packRefs
+	 *            whether to pack refs during gc
+	 */
+	public GcConfig(PackRefsMode packRefs) {
+		this.packRefs = packRefs;
+	}
+
+	/**
+	 * Get the pack refs mode configuring which refs to pack during gc.
+	 *
+	 * @return the pack refs mode configuring which refs to pack during gc.
+	 */
+	public PackRefsMode getPackRefs() {
+		return packRefs;
+	}
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
index 41917f8..58aed82 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
@@ -139,6 +139,7 @@ public void writePackedRefs() throws IOException {
 		if (peeled) {
 			w.write(RefDirectory.PACKED_REFS_HEADER);
 			w.write(RefDirectory.PACKED_REFS_PEELED);
+			w.write(RefDirectory.PACKED_REFS_SORTED);
 			w.write('\n');
 		}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeConfig.java
index 54b7aa4..680e3e4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeConfig.java
@@ -9,8 +9,13 @@
  *******************************************************************************/
 package org.eclipse.jgit.merge;
 
+import static org.eclipse.jgit.api.MergeCommand.ConflictStyle.MERGE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
+
 import java.io.IOException;
 
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Config.SectionParser;
@@ -60,6 +65,8 @@ public static final SectionParser<MergeConfig> getParser(
 
 	private final FastForwardMode fastForwardMode;
 
+	private final ConflictStyle conflictStyle;
+
 	private final boolean squash;
 
 	private final boolean commit;
@@ -67,12 +74,14 @@ public static final SectionParser<MergeConfig> getParser(
 	private MergeConfig(String branch, Config config) {
 		String[] mergeOptions = getMergeOptions(branch, config);
 		fastForwardMode = getFastForwardMode(config, mergeOptions);
+		conflictStyle = getConflictStyle(config);
 		squash = isMergeConfigOptionSet("--squash", mergeOptions); //$NON-NLS-1$
 		commit = !isMergeConfigOptionSet("--no-commit", mergeOptions); //$NON-NLS-1$
 	}
 
 	private MergeConfig() {
 		fastForwardMode = FastForwardMode.FF;
+		conflictStyle = ConflictStyle.MERGE;
 		squash = false;
 		commit = true;
 	}
@@ -87,6 +96,16 @@ public FastForwardMode getFastForwardMode() {
 	}
 
 	/**
+	 * Get the configured conflict style
+	 *
+	 * @return the configured conflict style
+	 * @since 7.6
+	 */
+	public ConflictStyle getConflictStyle() {
+		return conflictStyle;
+	}
+
+	/**
 	 * Whether merges into this branch are configured to be squash merges, false
 	 * otherwise
 	 *
@@ -120,6 +139,11 @@ private static FastForwardMode getFastForwardMode(Config config,
 		return ffmode;
 	}
 
+	private ConflictStyle getConflictStyle(Config config) {
+		return config.getEnum(CONFIG_MERGE_SECTION, null,
+						CONFIG_KEY_CONFLICTSTYLE, MERGE);
+	}
+
 	private static boolean isMergeConfigOptionSet(String optionToLookFor,
 			String[] mergeOptions) {
 		for (String option : mergeOptions) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
index dc96f65..cb82577 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
@@ -16,9 +16,12 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.time.Instant.EPOCH;
+import static org.eclipse.jgit.api.MergeCommand.ConflictStyle.MERGE;
 import static org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm.HISTOGRAM;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DIFF_SECTION;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_ALGORITHM;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONFLICTSTYLE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
 
 import java.io.Closeable;
@@ -39,6 +42,7 @@
 
 import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.api.MergeCommand.ConflictStyle;
 import org.eclipse.jgit.attributes.Attribute;
 import org.eclipse.jgit.attributes.Attributes;
 import org.eclipse.jgit.attributes.AttributesNodeProvider;
@@ -831,6 +835,8 @@ public enum MergeFailureReason {
 	 */
 	protected MergeAlgorithm mergeAlgorithm;
 
+	private ConflictStyle conflictStyle;
+
 	/**
 	 * The {@link ContentMergeStrategy} to use for "resolve" and "recursive"
 	 * merges.
@@ -870,6 +876,7 @@ protected ResolveMerger(Repository local, boolean inCore) {
 		super(local);
 		Config config = local.getConfig();
 		mergeAlgorithm = getMergeAlgorithm(config);
+		conflictStyle = getConflictStyle(config);
 		commitNames = defaultCommitNames();
 		this.inCore = inCore;
 	}
@@ -896,6 +903,7 @@ protected ResolveMerger(Repository local) {
 	protected ResolveMerger(ObjectInserter inserter, Config config) {
 		super(inserter);
 		mergeAlgorithm = getMergeAlgorithm(config);
+		conflictStyle = getConflictStyle(config);
 		commitNames = defaultCommitNames();
 		inCore = true;
 	}
@@ -923,6 +931,23 @@ public void setContentMergeStrategy(ContentMergeStrategy strategy) {
 				: strategy;
 	}
 
+	/**
+	 * Sets the conflict style to be used when formatting merge conflicts.
+	 *
+	 * @param conflictStyle
+	 *            a {@link org.eclipse.jgit.api.MergeCommand.ConflictStyle}
+	 * @since 7.6
+	 */
+	public void setConflictStyle(ConflictStyle conflictStyle) {
+		this.conflictStyle = conflictStyle;
+	}
+
+	private ConflictStyle getConflictStyle(Config config) {
+		return config.getEnum(CONFIG_MERGE_SECTION,
+				null,
+				CONFIG_KEY_CONFLICTSTYLE, MERGE);
+	}
+
 	@Override
 	protected boolean mergeImpl() throws IOException {
 		return mergeTrees(mergeBase(), sourceTrees[0], sourceTrees[1],
@@ -1668,8 +1693,16 @@ private TemporaryBuffer doMerge(MergeResult<RawText> result)
 				db != null ? nonNullRepo().getDirectory() : null, workTreeUpdater.getInCoreFileSizeLimit());
 		boolean success = false;
 		try {
-			new MergeFormatter().formatMerge(buf, result,
-					Arrays.asList(commitNames), UTF_8);
+			switch (conflictStyle) {
+			case MERGE:
+				new MergeFormatter().formatMerge(buf, result,
+						Arrays.asList(commitNames), UTF_8);
+				break;
+			case DIFF3:
+				new MergeFormatter().formatMergeDiff3(buf, result,
+						Arrays.asList(commitNames), UTF_8);
+				break;
+			}
 			buf.close();
 			success = true;
 		} finally {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
index ba7573a..8e604ba 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
@@ -623,7 +623,7 @@ private Set<RevCommit> getCommitsMergedInto(RevCommit needle, Collection<RevComm
 				markStart(c);
 				boolean commitFound = false;
 				RevCommit next;
-				while ((next = next()) != null) {
+				while ((next = next()) != null && !monitor.isCancelled()) {
 					if (next.getGeneration() < cutoff) {
 						markUninteresting(next);
 						uninteresting.add(next);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
index fb893a6..0f45162 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
@@ -52,6 +52,8 @@ public abstract class TemporaryBuffer extends OutputStream {
 	/** If {@link #inCoreLimit} has been reached, remainder goes here. */
 	private OutputStream overflow;
 
+	private boolean destroyed;
+
 	/**
 	 * Create a new empty temporary buffer.
 	 *
@@ -85,6 +87,7 @@ protected TemporaryBuffer(int estimatedSize, int limit) {
 	/** {@inheritDoc} */
 	@Override
 	public void write(int b) throws IOException {
+		checkDestroyed();
 		if (overflow != null) {
 			overflow.write(b);
 			return;
@@ -106,6 +109,7 @@ public void write(int b) throws IOException {
 	/** {@inheritDoc} */
 	@Override
 	public void write(byte[] b, int off, int len) throws IOException {
+		checkDestroyed();
 		if (overflow == null) {
 			while (len > 0) {
 				Block s = last();
@@ -152,6 +156,7 @@ protected void doFlush() throws IOException {
 	 *             writing to a local temporary file.
 	 */
 	public void copy(InputStream in) throws IOException {
+		checkDestroyed();
 		if (blocks != null) {
 			for (;;) {
 				Block s = last();
@@ -183,6 +188,7 @@ public void copy(InputStream in) throws IOException {
 	 * @return total length of the buffer, in bytes.
 	 */
 	public long length() {
+		checkDestroyedUnchecked();
 		return inCoreLength();
 	}
 
@@ -201,6 +207,7 @@ private long inCoreLength() {
 	 *             an error occurred reading from a local temporary file
 	 */
 	public byte[] toByteArray() throws IOException {
+		checkDestroyed();
 		final long len = length();
 		if (Integer.MAX_VALUE < len)
 			throw new OutOfMemoryError(JGitText.get().lengthExceedsMaximumArraySize);
@@ -245,6 +252,7 @@ public String toString(int limit) {
 	 * @since 4.2
 	 */
 	public byte[] toByteArray(int limit) throws IOException {
+		checkDestroyed();
 		final long len = Math.min(length(), limit);
 		if (Integer.MAX_VALUE < len)
 			throw new OutOfMemoryError(
@@ -281,6 +289,7 @@ public String toString(int limit) {
 	 */
 	public void writeTo(OutputStream os, ProgressMonitor pm)
 			throws IOException {
+		checkDestroyed();
 		if (pm == null)
 			pm = NullProgressMonitor.INSTANCE;
 		for (Block b : blocks) {
@@ -301,6 +310,7 @@ public void writeTo(OutputStream os, ProgressMonitor pm)
 	 *             an error occurred opening the temporary file.
 	 */
 	public InputStream openInputStream() throws IOException {
+		checkDestroyed();
 		return new BlockInputStream();
 	}
 
@@ -315,6 +325,7 @@ public InputStream openInputStream() throws IOException {
 	 * @since 4.11
 	 */
 	public InputStream openInputStreamWithAutoDestroy() throws IOException {
+		checkDestroyed();
 		return new BlockInputStream() {
 			@Override
 			public void close() throws IOException {
@@ -328,13 +339,15 @@ public void close() throws IOException {
 	 * Reset this buffer for reuse, purging all buffered content.
 	 */
 	public void reset() {
-		if (overflow != null) {
-			destroy();
+		if (destroyed) {
+			return;
 		}
-		if (blocks != null)
+		closeOverflow();
+		if (blocks != null) {
 			blocks.clear();
-		else
+		} else {
 			blocks = new ArrayList<>(initialBlocks);
+		}
 		blocks.add(new Block(Math.min(inCoreLimit, Block.SZ)));
 	}
 
@@ -372,24 +385,24 @@ private void switchToOverflow() throws IOException {
 		overflow.write(last.buffer, 0, last.count);
 	}
 
-	/** {@inheritDoc} */
 	@Override
 	public void close() throws IOException {
-		if (overflow != null) {
-			try {
-				overflow.close();
-			} finally {
-				overflow = null;
-			}
+		if (destroyed) {
+			return;
 		}
+		closeOverflow();
 	}
 
 	/**
 	 * Clear this buffer so it has no data, and cannot be used again.
 	 */
 	public void destroy() {
+		destroyed = true;
 		blocks = null;
+		closeOverflow();
+	}
 
+	private void closeOverflow() {
 		if (overflow != null) {
 			try {
 				overflow.close();
@@ -401,6 +414,19 @@ public void destroy() {
 		}
 	}
 
+	private void checkDestroyed() throws IOException {
+		if (destroyed) {
+			throw new IOException(JGitText.get().temporaryBufferIsDestroyed);
+		}
+	}
+
+	private void checkDestroyedUnchecked() {
+		if (destroyed) {
+			throw new UncheckedIOException(
+					new IOException(JGitText.get().temporaryBufferIsDestroyed));
+		}
+	}
+
 	/**
 	 * A fully buffered output stream using local disk storage for large data.
 	 * <p>
@@ -462,6 +488,7 @@ protected OutputStream overflow() throws IOException {
 
 		@Override
 		public long length() {
+			super.checkDestroyedUnchecked();
 			if (onDiskFile == null) {
 				return super.length();
 			}
diff --git a/pom.xml b/pom.xml
index f4e15e6..18f8b12 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
   <groupId>org.eclipse.jgit</groupId>
   <artifactId>org.eclipse.jgit-parent</artifactId>
   <packaging>pom</packaging>
-  <version>7.5.1-SNAPSHOT</version>
+  <version>7.6.1-SNAPSHOT</version>
 
   <name>JGit - Parent</name>
   <url>${jgit-url}</url>
@@ -118,9 +118,9 @@
 
     <project.build.outputTimestamp>${commit.time.iso}</project.build.outputTimestamp>
 
-    <jgit-last-release-version>7.4.0.202509020913-r</jgit-last-release-version>
+    <jgit-last-release-version>7.5.0.202512021534-r</jgit-last-release-version>
     <ant-version>1.10.15</ant-version>
-    <apache-sshd-version>2.16.0</apache-sshd-version>
+    <apache-sshd-version>2.17.1</apache-sshd-version>
     <jsch-version>0.1.55</jsch-version>
     <jzlib-version>1.1.3</jzlib-version>
     <javaewah-version>1.2.3</javaewah-version>
@@ -130,25 +130,25 @@
     <commons-compress-version>1.28.0</commons-compress-version>
     <osgi-core-version>6.0.0</osgi-core-version>
     <servlet-api-version>6.1.0</servlet-api-version>
-    <jetty-version>12.1.4</jetty-version>
-    <japicmp-version>0.24.2</japicmp-version>
+    <jetty-version>12.1.6</jetty-version>
+    <japicmp-version>0.25.0</japicmp-version>
     <httpclient-version>4.5.14</httpclient-version>
     <httpcore-version>4.4.16</httpcore-version>
     <slf4j-version>2.0.17</slf4j-version>
     <maven-javadoc-plugin-version>3.12.0</maven-javadoc-plugin-version>
     <gson-version>2.13.2</gson-version>
-    <bouncycastle-version>1.82</bouncycastle-version>
-    <spotbugs-maven-plugin-version>4.9.8.1</spotbugs-maven-plugin-version>
+    <bouncycastle-version>1.83</bouncycastle-version>
+    <spotbugs-maven-plugin-version>4.9.8.2</spotbugs-maven-plugin-version>
     <maven-project-info-reports-plugin-version>3.9.0</maven-project-info-reports-plugin-version>
     <maven-jxr-plugin-version>3.6.0</maven-jxr-plugin-version>
     <maven-surefire-plugin-version>3.5.4</maven-surefire-plugin-version>
     <maven-surefire-report-plugin-version>${maven-surefire-plugin-version}</maven-surefire-report-plugin-version>
     <maven-compiler-plugin-version>3.14.1</maven-compiler-plugin-version>
-    <plexus-compiler-version>2.16.0</plexus-compiler-version>
+    <plexus-compiler-version>2.16.1</plexus-compiler-version>
     <hamcrest-version>3.0</hamcrest-version>
-    <assertj-version>3.27.6</assertj-version>
+    <assertj-version>3.27.7</assertj-version>
     <jna-version>5.18.1</jna-version>
-    <byte-buddy-version>1.18.1</byte-buddy-version>
+    <byte-buddy-version>1.18.5</byte-buddy-version>
 
     <!-- Properties to enable jacoco code coverage analysis -->
     <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
@@ -184,7 +184,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
-          <version>3.4.2</version>
+          <version>3.5.0</version>
           <configuration>
             <archive>
               <manifestEntries>
@@ -220,7 +220,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-antrun-plugin</artifactId>
-          <version>3.1.0</version>
+          <version>3.2.0</version>
         </plugin>
 
         <plugin>
@@ -232,7 +232,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-source-plugin</artifactId>
-          <version>3.3.1</version>
+          <version>3.4.0</version>
         </plugin>
 
         <plugin>
@@ -277,7 +277,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-pmd-plugin</artifactId>
-          <version>3.27.0</version>
+          <version>3.28.0</version>
           <configuration>
             <inputEncoding>${project.build.sourceEncoding}</inputEncoding>
             <minimumTokens>100</minimumTokens>
@@ -352,12 +352,12 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-resources-plugin</artifactId>
-          <version>3.3.1</version>
+          <version>3.4.0</version>
         </plugin>
         <plugin>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-maven-plugin</artifactId>
-          <version>3.5.0</version>
+          <version>3.5.10</version>
         </plugin>
         <plugin>
           <groupId>org.eclipse.dash</groupId>
@@ -899,7 +899,7 @@
       <dependency>
         <groupId>commons-codec</groupId>
         <artifactId>commons-codec</artifactId>
-        <version>1.20.0</version>
+        <version>1.21.0</version>
       </dependency>
 
       <dependency>
@@ -970,6 +970,12 @@
       </dependency>
 
       <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>jcl-over-slf4j</artifactId>
+        <version>${slf4j-version}</version>
+      </dependency>
+
+      <dependency>
         <groupId>com.google.code.gson</groupId>
         <artifactId>gson</artifactId>
         <version>${gson-version}</version>
@@ -1020,7 +1026,7 @@
       <dependency>
         <groupId>org.mockito</groupId>
         <artifactId>mockito-core</artifactId>
-        <version>5.20.0</version>
+        <version>5.21.0</version>
       </dependency>
 
       <dependency>
@@ -1129,7 +1135,7 @@
               <dependency>
                 <groupId>org.eclipse.jdt</groupId>
                 <artifactId>ecj</artifactId>
-                <version>3.43.0</version>
+                <version>3.44.0</version>
               </dependency>
             </dependencies>
           </plugin>
diff --git a/tools/bazlets.bzl b/tools/bazlets.bzl
deleted file mode 100644
index f089af4..0000000
--- a/tools/bazlets.bzl
+++ /dev/null
@@ -1,18 +0,0 @@
-load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
-
-NAME = "com_googlesource_gerrit_bazlets"
-
-def load_bazlets(
-        commit,
-        local_path = None):
-    if not local_path:
-        git_repository(
-            name = NAME,
-            remote = "https://gerrit.googlesource.com/bazlets",
-            commit = commit,
-        )
-    else:
-        native.local_repository(
-            name = NAME,
-            path = local_path,
-        )
diff --git a/tools/maven-central/Pipfile.lock b/tools/maven-central/Pipfile.lock
index 40358c9..e566398 100644
--- a/tools/maven-central/Pipfile.lock
+++ b/tools/maven-central/Pipfile.lock
@@ -27,104 +27,138 @@
         },
         "certifi": {
             "hashes": [
-                "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407",
-                "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"
+                "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c",
+                "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==2025.8.3"
+            "version": "==2026.1.4"
         },
         "charset-normalizer": {
             "hashes": [
-                "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91",
-                "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0",
-                "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154",
-                "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601",
-                "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884",
-                "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07",
-                "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c",
-                "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64",
-                "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe",
-                "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f",
-                "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432",
-                "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc",
-                "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa",
-                "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9",
-                "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae",
-                "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19",
-                "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d",
-                "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e",
-                "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4",
-                "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7",
-                "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312",
-                "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92",
-                "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31",
-                "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c",
-                "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f",
-                "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99",
-                "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b",
-                "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15",
-                "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392",
-                "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f",
-                "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8",
-                "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491",
-                "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0",
-                "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc",
-                "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0",
-                "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f",
-                "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a",
-                "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40",
-                "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927",
-                "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849",
-                "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce",
-                "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14",
-                "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05",
-                "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c",
-                "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c",
-                "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a",
-                "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc",
-                "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34",
-                "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9",
-                "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096",
-                "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14",
-                "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30",
-                "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b",
-                "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b",
-                "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942",
-                "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db",
-                "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5",
-                "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b",
-                "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce",
-                "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669",
-                "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0",
-                "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018",
-                "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93",
-                "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe",
-                "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049",
-                "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a",
-                "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef",
-                "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2",
-                "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca",
-                "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16",
-                "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f",
-                "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb",
-                "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1",
-                "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557",
-                "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37",
-                "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7",
-                "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72",
-                "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c",
-                "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"
+                "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad",
+                "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93",
+                "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394",
+                "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89",
+                "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc",
+                "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86",
+                "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63",
+                "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d",
+                "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f",
+                "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8",
+                "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0",
+                "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505",
+                "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161",
+                "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af",
+                "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152",
+                "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318",
+                "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72",
+                "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4",
+                "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e",
+                "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3",
+                "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576",
+                "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c",
+                "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1",
+                "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8",
+                "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1",
+                "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2",
+                "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44",
+                "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26",
+                "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88",
+                "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016",
+                "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede",
+                "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf",
+                "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a",
+                "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc",
+                "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0",
+                "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84",
+                "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db",
+                "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1",
+                "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7",
+                "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed",
+                "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8",
+                "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133",
+                "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e",
+                "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef",
+                "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14",
+                "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2",
+                "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0",
+                "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d",
+                "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828",
+                "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f",
+                "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf",
+                "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6",
+                "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328",
+                "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090",
+                "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa",
+                "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381",
+                "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c",
+                "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb",
+                "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc",
+                "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a",
+                "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec",
+                "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc",
+                "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac",
+                "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e",
+                "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313",
+                "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569",
+                "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3",
+                "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d",
+                "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525",
+                "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894",
+                "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3",
+                "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9",
+                "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a",
+                "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9",
+                "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14",
+                "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25",
+                "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50",
+                "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf",
+                "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1",
+                "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3",
+                "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac",
+                "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e",
+                "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815",
+                "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c",
+                "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6",
+                "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6",
+                "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e",
+                "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4",
+                "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84",
+                "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69",
+                "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15",
+                "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191",
+                "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0",
+                "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897",
+                "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd",
+                "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2",
+                "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794",
+                "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d",
+                "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074",
+                "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3",
+                "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224",
+                "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838",
+                "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a",
+                "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d",
+                "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d",
+                "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f",
+                "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8",
+                "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490",
+                "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966",
+                "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9",
+                "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3",
+                "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e",
+                "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==3.4.3"
+            "version": "==3.4.4"
         },
         "idna": {
             "hashes": [
-                "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
-                "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"
+                "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea",
+                "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==3.10"
+            "markers": "python_version >= '3.8'",
+            "version": "==3.11"
         },
         "pyyaml": {
             "hashes": [
@@ -217,11 +251,11 @@
         },
         "urllib3": {
             "hashes": [
-                "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760",
-                "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"
+                "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed",
+                "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"
             ],
             "markers": "python_version >= '3.9'",
-            "version": "==2.5.0"
+            "version": "==2.6.3"
         }
     },
     "develop": {
diff --git a/tools/maven-central/README.md b/tools/maven-central/README.md
index 40156a5..d4533d9 100644
--- a/tools/maven-central/README.md
+++ b/tools/maven-central/README.md
@@ -77,9 +77,29 @@
   if the release looks good. You can download uploaded artifacts from there.
   How to manually test a staged release is explained
   [here](https://central.sonatype.org/publish/publish-portal-api/#manually-testing-a-deployment-bundle)
-- publish the new release
+  - create a bearer token as described [here](https://central.sonatype.org/publish/publish-portal-api/#authentication-authorization)
+  - add the sections mentioned [here](https://central.sonatype.org/publish/publish-portal-api/#maven)
+    using the bearer token you created in the previous step to your `~/.m2/settings.xml`
+  - clone the jgit-build-test repo from github
+    ```
+    $ git clone https://github.com/msohn/jgit-build-test
+    ```
+  - update the version in its `pom.xml` to the new JGit release you staged
+  - delete all jgit artifacts from your local m2 repository
+    ```
+    $ rm -r ~/.m2/org/eclipse/jgit
+    ```
+  - build the jgit-built-test maven project to test if all artifacts of the new release
+    can be downloaded and used in a build
+    ```
+    $ mvn clean install -Pcentral.manual.testing
+    ```
+  - commit the version update in jgit-build-test and push it to github
+- if the test build of jgit-build-test succeeded publish the new release
   - by clicking "Publish" on the [portal deployment page](https://central.sonatype.com/publishing/deployments)
   - or by running
     ```
     $ JRELEASER_MAVENCENTRAL_STAGE=PUBLISH jreleaser deploy
     ```
+  - when publication finished check if the new version is available
+    on [Maven Central](https://repo1.maven.org/maven2/org/eclipse/jgit/)
diff --git a/tools/remote-bazelrc b/tools/remote-bazelrc
index f8aabd2..39797b8 100644
--- a/tools/remote-bazelrc
+++ b/tools/remote-bazelrc
@@ -30,11 +30,11 @@
 
 # Set several flags related to specifying the platform, toolchain and java
 # properties.
-build:remote --crosstool_top=@ubuntu2204_jdk17//cc:toolchain
-build:remote --extra_toolchains=@ubuntu2204_jdk17//config:cc-toolchain
-build:remote --extra_execution_platforms=@ubuntu2204_jdk17//config:platform
-build:remote --host_platform=@ubuntu2204_jdk17//config:platform
-build:remote --platforms=@ubuntu2204_jdk17//config:platform
+build:remote --crosstool_top=@rbe_autoconfig//cc:toolchain
+build:remote --extra_toolchains=@rbe_autoconfig//config:cc-toolchain
+build:remote --extra_execution_platforms=@rbe_autoconfig//config:platform
+build:remote --host_platform=@rbe_autoconfig//config:platform
+build:remote --platforms=@rbe_autoconfig//config:platform
 
 # Set various strategies so that all actions execute remotely. Mixing remote
 # and local execution will lead to errors unless the toolchain and remote